summaryrefslogtreecommitdiff
path: root/sys/src/9
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/9
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/9')
-rwxr-xr-xsys/src/9/alphapc/apc66
-rwxr-xr-xsys/src/9/alphapc/apccpu60
-rwxr-xr-xsys/src/9/alphapc/arch164.c363
-rwxr-xr-xsys/src/9/alphapc/audio.h16
-rwxr-xr-xsys/src/9/alphapc/axp.h71
-rwxr-xr-xsys/src/9/alphapc/cga.c113
-rwxr-xr-xsys/src/9/alphapc/clock.c112
-rwxr-xr-xsys/src/9/alphapc/cycintr.c27
-rwxr-xr-xsys/src/9/alphapc/dat.h266
-rwxr-xr-xsys/src/9/alphapc/devarch.c533
-rwxr-xr-xsys/src/9/alphapc/devvga.c407
-rwxr-xr-xsys/src/9/alphapc/dma.c331
-rwxr-xr-xsys/src/9/alphapc/etherif.h41
-rwxr-xr-xsys/src/9/alphapc/faultalpha.c62
-rwxr-xr-xsys/src/9/alphapc/fdc37c93x.c66
-rwxr-xr-xsys/src/9/alphapc/floppy.h181
-rwxr-xr-xsys/src/9/alphapc/fns.h128
-rwxr-xr-xsys/src/9/alphapc/fptrap.c46
-rwxr-xr-xsys/src/9/alphapc/i8259.c152
-rwxr-xr-xsys/src/9/alphapc/initcode47
-rwxr-xr-xsys/src/9/alphapc/io.h176
-rwxr-xr-xsys/src/9/alphapc/kbd.c456
-rwxr-xr-xsys/src/9/alphapc/l.s457
-rwxr-xr-xsys/src/9/alphapc/main.c703
-rwxr-xr-xsys/src/9/alphapc/mem.h89
-rwxr-xr-xsys/src/9/alphapc/memmove.s197
-rwxr-xr-xsys/src/9/alphapc/memset.s61
-rwxr-xr-xsys/src/9/alphapc/mkfile109
-rwxr-xr-xsys/src/9/alphapc/mmu.c299
-rwxr-xr-xsys/src/9/alphapc/osf1pal.h78
-rwxr-xr-xsys/src/9/alphapc/pci.c412
-rwxr-xr-xsys/src/9/alphapc/screen.h171
-rwxr-xr-xsys/src/9/alphapc/sd53c8xx.c2261
-rwxr-xr-xsys/src/9/alphapc/sd53c8xx.i805
-rwxr-xr-xsys/src/9/alphapc/sio.c18
-rwxr-xr-xsys/src/9/alphapc/trap.c916
-rwxr-xr-xsys/src/9/bitsy/Booting101245
-rwxr-xr-xsys/src/9/bitsy/bitsy49
-rwxr-xr-xsys/src/9/bitsy/bitsyreset.s103
-rwxr-xr-xsys/src/9/bitsy/clock.c254
-rwxr-xr-xsys/src/9/bitsy/dat.h290
-rwxr-xr-xsys/src/9/bitsy/defont.c291
-rwxr-xr-xsys/src/9/bitsy/devether.c599
-rwxr-xr-xsys/src/9/bitsy/devflash.c876
-rwxr-xr-xsys/src/9/bitsy/devpcmcia.c713
-rwxr-xr-xsys/src/9/bitsy/devpenmouse.c509
-rwxr-xr-xsys/src/9/bitsy/devuda1341.c1400
-rwxr-xr-xsys/src/9/bitsy/devµc.c452
-rwxr-xr-xsys/src/9/bitsy/etherif.h39
-rwxr-xr-xsys/src/9/bitsy/etherwavelan.c49
-rwxr-xr-xsys/src/9/bitsy/fns.h120
-rwxr-xr-xsys/src/9/bitsy/fpi.c300
-rwxr-xr-xsys/src/9/bitsy/fpi.h61
-rwxr-xr-xsys/src/9/bitsy/fpiarm.c570
-rwxr-xr-xsys/src/9/bitsy/fpimem.c136
-rwxr-xr-xsys/src/9/bitsy/gamma.c51
-rwxr-xr-xsys/src/9/bitsy/gamma.h8195
-rwxr-xr-xsys/src/9/bitsy/init9.s12
-rwxr-xr-xsys/src/9/bitsy/io.h337
-rwxr-xr-xsys/src/9/bitsy/l.s856
-rwxr-xr-xsys/src/9/bitsy/main.c555
-rwxr-xr-xsys/src/9/bitsy/map10
-rwxr-xr-xsys/src/9/bitsy/mem.h236
-rwxr-xr-xsys/src/9/bitsy/mkfile140
-rwxr-xr-xsys/src/9/bitsy/mmu.c533
-rwxr-xr-xsys/src/9/bitsy/mouse.c63
-rwxr-xr-xsys/src/9/bitsy/paqfiles/cpurc175
-rwxr-xr-xsys/src/9/bitsy/paqfiles/local6
-rwxr-xr-xsys/src/9/bitsy/paqfiles/mfs41
-rwxr-xr-xsys/src/9/bitsy/paqfiles/namespace53
-rwxr-xr-xsys/src/9/bitsy/paqfiles/startip9
-rwxr-xr-xsys/src/9/bitsy/paqfiles/unicode.6.font5
-rwxr-xr-xsys/src/9/bitsy/power.c356
-rwxr-xr-xsys/src/9/bitsy/random.c138
-rwxr-xr-xsys/src/9/bitsy/sa1110dma.c227
-rwxr-xr-xsys/src/9/bitsy/sa1110dma.h19
-rwxr-xr-xsys/src/9/bitsy/screen.c496
-rwxr-xr-xsys/src/9/bitsy/screen.h14
-rwxr-xr-xsys/src/9/bitsy/sd.h0
-rwxr-xr-xsys/src/9/bitsy/sdata.c2087
-rwxr-xr-xsys/src/9/bitsy/tar.c81
-rwxr-xr-xsys/src/9/bitsy/trap.c929
-rwxr-xr-xsys/src/9/bitsy/uartsa1110.c514
-rwxr-xr-xsys/src/9/bitsy/wavelan.c1221
-rwxr-xr-xsys/src/9/bitsy/wavelan.h1
-rwxr-xr-xsys/src/9/boot/aux.c182
-rwxr-xr-xsys/src/9/boot/boot.c353
-rwxr-xr-xsys/src/9/boot/boot.h73
-rwxr-xr-xsys/src/9/boot/bootauth.c72
-rwxr-xr-xsys/src/9/boot/bootcache.c80
-rwxr-xr-xsys/src/9/boot/bootip.c203
-rwxr-xr-xsys/src/9/boot/bootmkfile27
-rwxr-xr-xsys/src/9/boot/doauthenticate.c126
-rwxr-xr-xsys/src/9/boot/embed.c74
-rwxr-xr-xsys/src/9/boot/getpasswd.c43
-rwxr-xr-xsys/src/9/boot/libboot.a5bin0 -> 85034 bytes
-rwxr-xr-xsys/src/9/boot/libboot.a8bin0 -> 67468 bytes
-rwxr-xr-xsys/src/9/boot/local.c275
-rwxr-xr-xsys/src/9/boot/mkboot101
-rwxr-xr-xsys/src/9/boot/nopsession.c52
-rwxr-xr-xsys/src/9/boot/paq.c67
-rwxr-xr-xsys/src/9/boot/printstub.c22
-rwxr-xr-xsys/src/9/boot/sac.c50
-rwxr-xr-xsys/src/9/boot/settime.c149
-rwxr-xr-xsys/src/9/boot/testboot.c37
-rwxr-xr-xsys/src/9/ip/arp.c685
-rwxr-xr-xsys/src/9/ip/chandial.c124
-rwxr-xr-xsys/src/9/ip/devip.c1457
-rwxr-xr-xsys/src/9/ip/eipconvtest.c152
-rwxr-xr-xsys/src/9/ip/esp.c1112
-rwxr-xr-xsys/src/9/ip/ethermedium.c765
-rwxr-xr-xsys/src/9/ip/gre.c971
-rwxr-xr-xsys/src/9/ip/icmp.c492
-rwxr-xr-xsys/src/9/ip/icmp6.c909
-rwxr-xr-xsys/src/9/ip/igmp.c299
-rwxr-xr-xsys/src/9/ip/inferno.c28
-rwxr-xr-xsys/src/9/ip/ip.c706
-rwxr-xr-xsys/src/9/ip/ip.h744
-rwxr-xr-xsys/src/9/ip/ipaux.c368
-rwxr-xr-xsys/src/9/ip/ipifc.c1660
-rwxr-xr-xsys/src/9/ip/ipmux.c840
-rwxr-xr-xsys/src/9/ip/iproute.c854
-rwxr-xr-xsys/src/9/ip/ipv6.c621
-rwxr-xr-xsys/src/9/ip/ipv6.h188
-rwxr-xr-xsys/src/9/ip/loopbackmedium.c120
-rwxr-xr-xsys/src/9/ip/netdevmedium.c153
-rwxr-xr-xsys/src/9/ip/netlog.c261
-rwxr-xr-xsys/src/9/ip/nullmedium.c39
-rwxr-xr-xsys/src/9/ip/pktmedium.c79
-rwxr-xr-xsys/src/9/ip/ptclbsum.c72
-rwxr-xr-xsys/src/9/ip/rudp.c1055
-rwxr-xr-xsys/src/9/ip/tcp.c3236
-rwxr-xr-xsys/src/9/ip/udp.c620
-rwxr-xr-xsys/src/9/kw/arch.c222
-rwxr-xr-xsys/src/9/kw/archkw.c519
-rwxr-xr-xsys/src/9/kw/arm.h194
-rwxr-xr-xsys/src/9/kw/arm.s72
-rwxr-xr-xsys/src/9/kw/cga.c132
-rwxr-xr-xsys/src/9/kw/clock.c205
-rwxr-xr-xsys/src/9/kw/coproc.c153
-rwxr-xr-xsys/src/9/kw/dat.h320
-rwxr-xr-xsys/src/9/kw/devarch.c265
-rwxr-xr-xsys/src/9/kw/devether.c528
-rwxr-xr-xsys/src/9/kw/devrtc.c359
-rwxr-xr-xsys/src/9/kw/devtwsi.c305
-rwxr-xr-xsys/src/9/kw/devusb.c1460
-rwxr-xr-xsys/src/9/kw/ether1116.c1747
-rwxr-xr-xsys/src/9/kw/etherif.h55
-rwxr-xr-xsys/src/9/kw/ethermii.c235
-rwxr-xr-xsys/src/9/kw/ethermii.h143
-rwxr-xr-xsys/src/9/kw/flashkw.c671
-rwxr-xr-xsys/src/9/kw/fns.h203
-rwxr-xr-xsys/src/9/kw/fpi.c300
-rwxr-xr-xsys/src/9/kw/fpi.h61
-rwxr-xr-xsys/src/9/kw/fpiarm.c576
-rwxr-xr-xsys/src/9/kw/fpimem.c136
-rwxr-xr-xsys/src/9/kw/init9.s25
-rwxr-xr-xsys/src/9/kw/io.h425
-rwxr-xr-xsys/src/9/kw/l.s774
-rwxr-xr-xsys/src/9/kw/lexception.s187
-rwxr-xr-xsys/src/9/kw/lproc.s47
-rwxr-xr-xsys/src/9/kw/main.c678
-rwxr-xr-xsys/src/9/kw/mem.h142
-rwxr-xr-xsys/src/9/kw/mkfile156
-rwxr-xr-xsys/src/9/kw/mmu.c522
-rwxr-xr-xsys/src/9/kw/notes/movm.w22
-rwxr-xr-xsys/src/9/kw/nvrambin0 -> 512 bytes
-rwxr-xr-xsys/src/9/kw/openrd.words21
-rwxr-xr-xsys/src/9/kw/plug80
-rwxr-xr-xsys/src/9/kw/plug.words104
-rwxr-xr-xsys/src/9/kw/random.c138
-rwxr-xr-xsys/src/9/kw/rebootcode.s172
-rwxr-xr-xsys/src/9/kw/softfpu.c119
-rwxr-xr-xsys/src/9/kw/syscall.c354
-rwxr-xr-xsys/src/9/kw/trap.c671
-rwxr-xr-xsys/src/9/kw/uartkw.c362
-rwxr-xr-xsys/src/9/kw/ucalloc.c135
-rwxr-xr-xsys/src/9/kw/uncached.h36
-rwxr-xr-xsys/src/9/kw/usbehci.h242
-rwxr-xr-xsys/src/9/kw/usbehcikw.c350
-rwxr-xr-xsys/src/9/mkfile24
-rwxr-xr-xsys/src/9/mtx/clock.c112
-rwxr-xr-xsys/src/9/mtx/cycintr.c27
-rwxr-xr-xsys/src/9/mtx/dat.h213
-rwxr-xr-xsys/src/9/mtx/devarch.c401
-rwxr-xr-xsys/src/9/mtx/devether.c472
-rwxr-xr-xsys/src/9/mtx/devrtc.c438
-rwxr-xr-xsys/src/9/mtx/ether2114x.c1671
-rwxr-xr-xsys/src/9/mtx/etherif.h35
-rwxr-xr-xsys/src/9/mtx/fns.h110
-rwxr-xr-xsys/src/9/mtx/i8259.c213
-rwxr-xr-xsys/src/9/mtx/inb.s119
-rwxr-xr-xsys/src/9/mtx/initcode25
-rwxr-xr-xsys/src/9/mtx/io.h180
-rwxr-xr-xsys/src/9/mtx/kbd.c435
-rwxr-xr-xsys/src/9/mtx/l.s603
-rwxr-xr-xsys/src/9/mtx/main.c465
-rwxr-xr-xsys/src/9/mtx/mem.h195
-rwxr-xr-xsys/src/9/mtx/mkfile96
-rwxr-xr-xsys/src/9/mtx/mmu.c257
-rwxr-xr-xsys/src/9/mtx/mtx46
-rwxr-xr-xsys/src/9/mtx/mtxcpu46
-rwxr-xr-xsys/src/9/mtx/pci.c908
-rwxr-xr-xsys/src/9/mtx/random.c138
-rwxr-xr-xsys/src/9/mtx/raven.c153
-rwxr-xr-xsys/src/9/mtx/trap.c836
-rwxr-xr-xsys/src/9/mtx/uarti8250.c636
-rwxr-xr-xsys/src/9/omap/arch.c223
-rwxr-xr-xsys/src/9/omap/archomap.c1389
-rwxr-xr-xsys/src/9/omap/arm.h246
-rwxr-xr-xsys/src/9/omap/arm.s95
-rwxr-xr-xsys/src/9/omap/beagle82
-rwxr-xr-xsys/src/9/omap/cache.v7.s208
-rwxr-xr-xsys/src/9/omap/clock.c489
-rwxr-xr-xsys/src/9/omap/coproc.c133
-rwxr-xr-xsys/src/9/omap/dat.h303
-rwxr-xr-xsys/src/9/omap/devarch.c200
-rwxr-xr-xsys/src/9/omap/devcons.c1354
-rwxr-xr-xsys/src/9/omap/devdss.c180
-rwxr-xr-xsys/src/9/omap/devether.c530
-rwxr-xr-xsys/src/9/omap/devuart.c789
-rwxr-xr-xsys/src/9/omap/devusb.c1461
-rwxr-xr-xsys/src/9/omap/dma.c263
-rwxr-xr-xsys/src/9/omap/ether9221.c961
-rwxr-xr-xsys/src/9/omap/etherif.h41
-rwxr-xr-xsys/src/9/omap/fns.h178
-rwxr-xr-xsys/src/9/omap/fpi.c300
-rwxr-xr-xsys/src/9/omap/fpi.h61
-rwxr-xr-xsys/src/9/omap/fpiarm.c576
-rwxr-xr-xsys/src/9/omap/fpimem.c136
-rwxr-xr-xsys/src/9/omap/init9.s25
-rwxr-xr-xsys/src/9/omap/io.h82
-rwxr-xr-xsys/src/9/omap/kbd.c410
-rwxr-xr-xsys/src/9/omap/l.s569
-rwxr-xr-xsys/src/9/omap/lexception.s187
-rwxr-xr-xsys/src/9/omap/lproc.s47
-rwxr-xr-xsys/src/9/omap/main.c698
-rwxr-xr-xsys/src/9/omap/mem.h212
-rwxr-xr-xsys/src/9/omap/mkfile136
-rwxr-xr-xsys/src/9/omap/mmu.c496
-rwxr-xr-xsys/src/9/omap/mouse.c255
-rwxr-xr-xsys/src/9/omap/notes/movm.w22
-rwxr-xr-xsys/src/9/omap/nvrambin0 -> 512 bytes
-rwxr-xr-xsys/src/9/omap/random.c138
-rwxr-xr-xsys/src/9/omap/rebootcode.s209
-rwxr-xr-xsys/src/9/omap/screen.c791
-rwxr-xr-xsys/src/9/omap/screen.h105
-rwxr-xr-xsys/src/9/omap/softfpu.c119
-rwxr-xr-xsys/src/9/omap/syscall.c333
-rwxr-xr-xsys/src/9/omap/trap.c769
-rwxr-xr-xsys/src/9/omap/uarti8250.c850
-rwxr-xr-xsys/src/9/omap/ucalloc.c135
-rwxr-xr-xsys/src/9/omap/ucallocb.c152
-rwxr-xr-xsys/src/9/omap/uncached.h36
-rwxr-xr-xsys/src/9/omap/usbehci.h243
-rwxr-xr-xsys/src/9/omap/usbehciomap.c224
-rwxr-xr-xsys/src/9/omap/words202
-rwxr-xr-xsys/src/9/pc/a100p.cpbin0 -> 21984 bytes
-rwxr-xr-xsys/src/9/pc/ahci.h275
-rwxr-xr-xsys/src/9/pc/apbootstrap.s110
-rwxr-xr-xsys/src/9/pc/apic.c421
-rwxr-xr-xsys/src/9/pc/apm.c153
-rwxr-xr-xsys/src/9/pc/apmjump.s98
-rwxr-xr-xsys/src/9/pc/archmp.c139
-rwxr-xr-xsys/src/9/pc/audio.h15
-rwxr-xr-xsys/src/9/pc/bios32.c155
-rwxr-xr-xsys/src/9/pc/boot.fs202
-rwxr-xr-xsys/src/9/pc/cga.c127
-rwxr-xr-xsys/src/9/pc/dat.h350
-rwxr-xr-xsys/src/9/pc/devarch.c1062
-rwxr-xr-xsys/src/9/pc/devether.c558
-rwxr-xr-xsys/src/9/pc/devfloppy.c1087
-rwxr-xr-xsys/src/9/pc/devi82365.c1044
-rwxr-xr-xsys/src/9/pc/devlm78.c346
-rwxr-xr-xsys/src/9/pc/devlml.c403
-rwxr-xr-xsys/src/9/pc/devlml.h124
-rwxr-xr-xsys/src/9/pc/devlpt.c241
-rwxr-xr-xsys/src/9/pc/devpccard.c1918
-rwxr-xr-xsys/src/9/pc/devrtc.c461
-rwxr-xr-xsys/src/9/pc/devtv.c2194
-rwxr-xr-xsys/src/9/pc/devusb.c1479
-rwxr-xr-xsys/src/9/pc/devvga.c498
-rwxr-xr-xsys/src/9/pc/dma.c264
-rwxr-xr-xsys/src/9/pc/ether2000.c232
-rwxr-xr-xsys/src/9/pc/ether2114x.c1830
-rwxr-xr-xsys/src/9/pc/ether589.c215
-rwxr-xr-xsys/src/9/pc/ether79c970.c646
-rwxr-xr-xsys/src/9/pc/ether8003.c271
-rwxr-xr-xsys/src/9/pc/ether8139.c833
-rwxr-xr-xsys/src/9/pc/ether8169.c1245
-rwxr-xr-xsys/src/9/pc/ether82543gc.c1368
-rwxr-xr-xsys/src/9/pc/ether82557.c1336
-rwxr-xr-xsys/src/9/pc/ether82563.c1773
-rwxr-xr-xsys/src/9/pc/ether82598.c984
-rwxr-xr-xsys/src/9/pc/ether83815.c1214
-rwxr-xr-xsys/src/9/pc/ether8390.c812
-rwxr-xr-xsys/src/9/pc/ether8390.h74
-rwxr-xr-xsys/src/9/pc/etherdp83820.c1247
-rwxr-xr-xsys/src/9/pc/etherec2t.c175
-rwxr-xr-xsys/src/9/pc/etherelnk3.c2134
-rwxr-xr-xsys/src/9/pc/etherga620.c1275
-rwxr-xr-xsys/src/9/pc/etherga620fw.h4858
-rwxr-xr-xsys/src/9/pc/etherif.h39
-rwxr-xr-xsys/src/9/pc/etherigbe.c2042
-rwxr-xr-xsys/src/9/pc/etherm10g.c1636
-rwxr-xr-xsys/src/9/pc/etherm10g2k.i11174
-rwxr-xr-xsys/src/9/pc/etherm10g4k.i10871
-rwxr-xr-xsys/src/9/pc/ethermii.c235
-rwxr-xr-xsys/src/9/pc/ethermii.h116
-rwxr-xr-xsys/src/9/pc/ethersink.c65
-rwxr-xr-xsys/src/9/pc/ethersmc.c781
-rwxr-xr-xsys/src/9/pc/ethervgbe.c1160
-rwxr-xr-xsys/src/9/pc/ethervt6102.c1050
-rwxr-xr-xsys/src/9/pc/ethervt6105m.c1220
-rwxr-xr-xsys/src/9/pc/etherwavelan.c197
-rwxr-xr-xsys/src/9/pc/floppy.h183
-rwxr-xr-xsys/src/9/pc/fns.h184
-rwxr-xr-xsys/src/9/pc/hcwAMC.h2027
-rwxr-xr-xsys/src/9/pc/i8253.c316
-rwxr-xr-xsys/src/9/pc/i8259.c214
-rwxr-xr-xsys/src/9/pc/init9.c7
-rwxr-xr-xsys/src/9/pc/initcode.s23
-rwxr-xr-xsys/src/9/pc/io.h380
-rwxr-xr-xsys/src/9/pc/kbd.c715
-rwxr-xr-xsys/src/9/pc/l.s1294
-rwxr-xr-xsys/src/9/pc/main.c842
-rwxr-xr-xsys/src/9/pc/mem.h164
-rwxr-xr-xsys/src/9/pc/memory.c899
-rwxr-xr-xsys/src/9/pc/mkfile192
-rwxr-xr-xsys/src/9/pc/mmu.c1063
-rwxr-xr-xsys/src/9/pc/mouse.c343
-rwxr-xr-xsys/src/9/pc/mp.c898
-rwxr-xr-xsys/src/9/pc/mp.h235
-rwxr-xr-xsys/src/9/pc/mtrr.c341
-rwxr-xr-xsys/src/9/pc/nv_dma.h179
-rwxr-xr-xsys/src/9/pc/pc132
-rwxr-xr-xsys/src/9/pc/pcauth82
-rwxr-xr-xsys/src/9/pc/pccd130
-rwxr-xr-xsys/src/9/pc/pccpu99
-rwxr-xr-xsys/src/9/pc/pccpuf132
-rwxr-xr-xsys/src/9/pc/pcdisk134
-rwxr-xr-xsys/src/9/pc/pcf137
-rwxr-xr-xsys/src/9/pc/pcflop99
-rwxr-xr-xsys/src/9/pc/pcfs99
-rwxr-xr-xsys/src/9/pc/pci.c1488
-rwxr-xr-xsys/src/9/pc/pcmciamodem.c76
-rwxr-xr-xsys/src/9/pc/pcmkfile3
-rwxr-xr-xsys/src/9/pc/piix4smbus.c213
-rwxr-xr-xsys/src/9/pc/plan9l.s52
-rwxr-xr-xsys/src/9/pc/psaux.c57
-rwxr-xr-xsys/src/9/pc/ptclbsum386.s126
-rwxr-xr-xsys/src/9/pc/random.c139
-rwxr-xr-xsys/src/9/pc/realmode.c140
-rwxr-xr-xsys/src/9/pc/rebootcode.s54
-rwxr-xr-xsys/src/9/pc/screen.c748
-rwxr-xr-xsys/src/9/pc/screen.h177
-rwxr-xr-xsys/src/9/pc/sd53c8xx.c2270
-rwxr-xr-xsys/src/9/pc/sd53c8xx.n459
-rwxr-xr-xsys/src/9/pc/sdata.c2304
-rwxr-xr-xsys/src/9/pc/sdiahci.c2298
-rwxr-xr-xsys/src/9/pc/sdmv50xx.c1762
-rwxr-xr-xsys/src/9/pc/sdmylex.c1269
-rwxr-xr-xsys/src/9/pc/trap.c1077
-rwxr-xr-xsys/src/9/pc/uartaxp.c951
-rwxr-xr-xsys/src/9/pc/uarti8250.c739
-rwxr-xr-xsys/src/9/pc/uartisa.c97
-rwxr-xr-xsys/src/9/pc/uartpci.c219
-rwxr-xr-xsys/src/9/pc/uncached.h4
-rwxr-xr-xsys/src/9/pc/usbehci.h221
-rwxr-xr-xsys/src/9/pc/usbehcipc.c273
-rwxr-xr-xsys/src/9/pc/usbohci.c2567
-rwxr-xr-xsys/src/9/pc/usbuhci.c2315
-rwxr-xr-xsys/src/9/pc/vga.c263
-rwxr-xr-xsys/src/9/pc/vga3dfx.c202
-rwxr-xr-xsys/src/9/pc/vgaark2000pv.c191
-rwxr-xr-xsys/src/9/pc/vgabt485.c246
-rwxr-xr-xsys/src/9/pc/vgaclgd542x.c277
-rwxr-xr-xsys/src/9/pc/vgaclgd546x.c219
-rwxr-xr-xsys/src/9/pc/vgact65545.c150
-rwxr-xr-xsys/src/9/pc/vgacyber938x.c203
-rwxr-xr-xsys/src/9/pc/vgaet4000.c271
-rwxr-xr-xsys/src/9/pc/vgahiqvideo.c228
-rwxr-xr-xsys/src/9/pc/vgai81x.c259
-rwxr-xr-xsys/src/9/pc/vgamach64xx.c1210
-rwxr-xr-xsys/src/9/pc/vgamga2164w.c240
-rwxr-xr-xsys/src/9/pc/vgamga4xx.c525
-rwxr-xr-xsys/src/9/pc/vganeomagic.c516
-rwxr-xr-xsys/src/9/pc/vganvidia.c540
-rwxr-xr-xsys/src/9/pc/vgaradeon.c520
-rwxr-xr-xsys/src/9/pc/vgargb524.c237
-rwxr-xr-xsys/src/9/pc/vgas3.c568
-rwxr-xr-xsys/src/9/pc/vgasavage.c571
-rwxr-xr-xsys/src/9/pc/vgat2r4.c531
-rwxr-xr-xsys/src/9/pc/vgatvp3020.c217
-rwxr-xr-xsys/src/9/pc/vgatvp3026.c190
-rwxr-xr-xsys/src/9/pc/vgavesa.c227
-rwxr-xr-xsys/src/9/pc/vgavmware.c370
-rwxr-xr-xsys/src/9/pc/vgax.c103
-rwxr-xr-xsys/src/9/pc/wavelan.c1263
-rwxr-xr-xsys/src/9/pc/wavelan.h327
-rwxr-xr-xsys/src/9/port/alarm.c101
-rwxr-xr-xsys/src/9/port/alloc.c315
-rwxr-xr-xsys/src/9/port/allocb.c185
-rwxr-xr-xsys/src/9/port/aoe.h78
-rwxr-xr-xsys/src/9/port/auth.c157
-rwxr-xr-xsys/src/9/port/cache.c630
-rwxr-xr-xsys/src/9/port/chan.c1775
-rwxr-xr-xsys/src/9/port/cis.c539
-rwxr-xr-xsys/src/9/port/debugalloc.c681
-rwxr-xr-xsys/src/9/port/dev.c449
-rwxr-xr-xsys/src/9/port/devaoe.c2581
-rwxr-xr-xsys/src/9/port/devaudio.c1261
-rwxr-xr-xsys/src/9/port/devbridge.c1195
-rwxr-xr-xsys/src/9/port/devcap.c286
-rwxr-xr-xsys/src/9/port/devcons.c1354
-rwxr-xr-xsys/src/9/port/devdraw.c2203
-rwxr-xr-xsys/src/9/port/devdup.c146
-rwxr-xr-xsys/src/9/port/devenv.c438
-rwxr-xr-xsys/src/9/port/devflash.c654
-rwxr-xr-xsys/src/9/port/devfs.c1266
-rwxr-xr-xsys/src/9/port/devkbin.c120
-rwxr-xr-xsys/src/9/port/devkbmap.c179
-rwxr-xr-xsys/src/9/port/devkprof.c192
-rwxr-xr-xsys/src/9/port/devloopback.c743
-rwxr-xr-xsys/src/9/port/devmnt.c1197
-rwxr-xr-xsys/src/9/port/devmouse.c790
-rwxr-xr-xsys/src/9/port/devpipe.c391
-rwxr-xr-xsys/src/9/port/devpnp.c691
-rwxr-xr-xsys/src/9/port/devproc.c1592
-rwxr-xr-xsys/src/9/port/devroot.c261
-rwxr-xr-xsys/src/9/port/devsd.c1644
-rwxr-xr-xsys/src/9/port/devsdp.c2317
-rwxr-xr-xsys/src/9/port/devsegment.c578
-rwxr-xr-xsys/src/9/port/devsrv.c357
-rwxr-xr-xsys/src/9/port/devssl.c1505
-rwxr-xr-xsys/src/9/port/devtls.c2180
-rwxr-xr-xsys/src/9/port/devuart.c784
-rwxr-xr-xsys/src/9/port/devwd.c156
-rwxr-xr-xsys/src/9/port/ecc.c119
-rwxr-xr-xsys/src/9/port/edf.c679
-rwxr-xr-xsys/src/9/port/edf.h54
-rwxr-xr-xsys/src/9/port/error.h53
-rwxr-xr-xsys/src/9/port/fault.c407
-rwxr-xr-xsys/src/9/port/flashif.h152
-rwxr-xr-xsys/src/9/port/initcode.c39
-rwxr-xr-xsys/src/9/port/latin1.c76
-rwxr-xr-xsys/src/9/port/latin1.h100
-rwxr-xr-xsys/src/9/port/lib.h223
-rwxr-xr-xsys/src/9/port/log.c186
-rwxr-xr-xsys/src/9/port/master63
-rwxr-xr-xsys/src/9/port/master.local9
-rwxr-xr-xsys/src/9/port/mkbootrules59
-rwxr-xr-xsys/src/9/port/mkdevc191
-rwxr-xr-xsys/src/9/port/mkdevlist46
-rwxr-xr-xsys/src/9/port/mkerrstr3
-rwxr-xr-xsys/src/9/port/mkextract37
-rwxr-xr-xsys/src/9/port/mkfile15
-rwxr-xr-xsys/src/9/port/mkfilelist15
-rwxr-xr-xsys/src/9/port/mkroot15
-rwxr-xr-xsys/src/9/port/mkrootall31
-rwxr-xr-xsys/src/9/port/mkrootc54
-rwxr-xr-xsys/src/9/port/mksystab50
-rwxr-xr-xsys/src/9/port/mul64fract.c39
-rwxr-xr-xsys/src/9/port/nandecc.h11
-rwxr-xr-xsys/src/9/port/netif.c725
-rwxr-xr-xsys/src/9/port/netif.h139
-rwxr-xr-xsys/src/9/port/page.c652
-rwxr-xr-xsys/src/9/port/parse.c114
-rwxr-xr-xsys/src/9/port/pgrp.c320
-rwxr-xr-xsys/src/9/port/portclock.c272
-rwxr-xr-xsys/src/9/port/portdat.h961
-rwxr-xr-xsys/src/9/port/portfns.h395
-rwxr-xr-xsys/src/9/port/portmkfile97
-rwxr-xr-xsys/src/9/port/print.c25
-rwxr-xr-xsys/src/9/port/proc.c1616
-rwxr-xr-xsys/src/9/port/qio.c1540
-rwxr-xr-xsys/src/9/port/qlock.c223
-rwxr-xr-xsys/src/9/port/rdb.c109
-rwxr-xr-xsys/src/9/port/rebootcmd.c100
-rwxr-xr-xsys/src/9/port/sd.h137
-rwxr-xr-xsys/src/9/port/sdaoe.c625
-rwxr-xr-xsys/src/9/port/sdscsi.c424
-rwxr-xr-xsys/src/9/port/segment.c799
-rwxr-xr-xsys/src/9/port/semaphore.p183
-rwxr-xr-xsys/src/9/port/swap.c447
-rwxr-xr-xsys/src/9/port/syscallfmt.c405
-rwxr-xr-xsys/src/9/port/sysfile.c1335
-rwxr-xr-xsys/src/9/port/sysproc.c1068
-rwxr-xr-xsys/src/9/port/systab.h163
-rwxr-xr-xsys/src/9/port/taslock.c255
-rwxr-xr-xsys/src/9/port/thwack.c381
-rwxr-xr-xsys/src/9/port/thwack.h68
-rwxr-xr-xsys/src/9/port/tod.c315
-rwxr-xr-xsys/src/9/port/unthwack.c298
-rwxr-xr-xsys/src/9/port/usb.h196
-rwxr-xr-xsys/src/9/port/usbehci.c3204
-rwxr-xr-xsys/src/9/port/xalloc.c273
-rwxr-xr-xsys/src/9/ppc/blast59
-rwxr-xr-xsys/src/9/ppc/blast.h99
-rwxr-xr-xsys/src/9/ppc/clock.c88
-rwxr-xr-xsys/src/9/ppc/dat.h231
-rwxr-xr-xsys/src/9/ppc/devether.c470
-rwxr-xr-xsys/src/9/ppc/devflash.c963
-rwxr-xr-xsys/src/9/ppc/devirq.c355
-rwxr-xr-xsys/src/9/ppc/devtls.c2113
-rwxr-xr-xsys/src/9/ppc/etherfcc.c891
-rwxr-xr-xsys/src/9/ppc/etherif.h35
-rwxr-xr-xsys/src/9/ppc/ethersaturn.c229
-rwxr-xr-xsys/src/9/ppc/fns.h124
-rwxr-xr-xsys/src/9/ppc/init9.s29
-rwxr-xr-xsys/src/9/ppc/initcode25
-rwxr-xr-xsys/src/9/ppc/io.h30
-rwxr-xr-xsys/src/9/ppc/l.s1037
-rwxr-xr-xsys/src/9/ppc/lblast.h66
-rwxr-xr-xsys/src/9/ppc/lucu.h39
-rwxr-xr-xsys/src/9/ppc/m8260.c661
-rwxr-xr-xsys/src/9/ppc/m8260.h658
-rwxr-xr-xsys/src/9/ppc/main.c511
-rwxr-xr-xsys/src/9/ppc/mcc.c351
-rwxr-xr-xsys/src/9/ppc/mem.h229
-rwxr-xr-xsys/src/9/ppc/mkfile108
-rwxr-xr-xsys/src/9/ppc/mmu.c282
-rwxr-xr-xsys/src/9/ppc/msaturn.c190
-rwxr-xr-xsys/src/9/ppc/msaturn.h7
-rwxr-xr-xsys/src/9/ppc/mtx.c11
-rwxr-xr-xsys/src/9/ppc/random.c138
-rwxr-xr-xsys/src/9/ppc/saturntimer.c95
-rwxr-xr-xsys/src/9/ppc/trap.c857
-rwxr-xr-xsys/src/9/ppc/uartsaturn.c472
-rwxr-xr-xsys/src/9/ppc/uartsmc.c585
-rwxr-xr-xsys/src/9/ppc/ucu59
-rwxr-xr-xsys/src/9/ppc/ucu.h21
532 files changed, 272244 insertions, 0 deletions
diff --git a/sys/src/9/alphapc/apc b/sys/src/9/alphapc/apc
new file mode 100755
index 000000000..c91795f49
--- /dev/null
+++ b/sys/src/9/alphapc/apc
@@ -0,0 +1,66 @@
+dev
+ root
+ cons
+ arch
+ pnp pci
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+# rtc
+ ssl
+ cap
+ kprof
+# loopback
+
+ ether netif
+ ip arp chandial inferno ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum
+
+ draw screen vga vgax
+ mouse mouse
+ vga
+
+ sd
+ floppy dma
+
+ audio dma
+ uart
+
+link
+ ether2114x pci
+ ethermedium
+
+misc
+ arch164
+
+ sdata pci sdscsi
+# sd53c8xx pci sdscsi
+
+ uarti8250
+
+ vgargb524 =cur
+ vgas3 +cur
+ vgas3 +cur vgasavage
+ vgatvp3026 =cur
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+
+port
+ int cpuserver = 0;
+
+boot
+ tcp
+
+bootdir
+ bootapc.out boot
+ /alpha/bin/disk/kfs
+ /alpha/bin/auth/factotum
+ /alpha/bin/ip/ipconfig
+
diff --git a/sys/src/9/alphapc/apccpu b/sys/src/9/alphapc/apccpu
new file mode 100755
index 000000000..f8ed97149
--- /dev/null
+++ b/sys/src/9/alphapc/apccpu
@@ -0,0 +1,60 @@
+dev
+ root
+ cons
+ arch
+ pnp pci
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+# rtc
+ ssl
+ cap
+ kprof
+# loopback
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno
+
+ sd
+ floppy dma
+
+ audio dma
+ uart
+
+link
+ ether2114x pci
+ ethermedium
+ loopbackmedium
+
+misc
+ arch164
+
+ sdata pci sdscsi
+# sd53c8xx pci sdscsi
+
+ uarti8250
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+ gre
+ ipmux
+
+port
+ int cpuserver = 1;
+
+boot cpu
+ tcp
+
+bootdir
+ bootapccpu.out boot
+ /alpha/bin/ip/ipconfig
+ /alpha/bin/auth/factotum
+
+
diff --git a/sys/src/9/alphapc/arch164.c b/sys/src/9/alphapc/arch164.c
new file mode 100755
index 000000000..7860142bc
--- /dev/null
+++ b/sys/src/9/alphapc/arch164.c
@@ -0,0 +1,363 @@
+/*
+ * EB164 and similar
+ * CPU: 21164
+ * Core Logic: 21172 CIA or 21174 PYXIS
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+static ulong *core;
+static ulong *wind;
+
+static ulong windsave[16];
+static ulong coresave[1];
+
+ulong iobase0;
+ulong iobase1;
+#define iobase(p) (iobase0+(p))
+
+static int
+ident(void)
+{
+ return 0; /* bug! */
+}
+
+static uvlong* sgmap;
+
+static void
+sginit(void)
+{
+ ulong pa;
+ uvlong *pte;
+
+ sgmap = xspanalloc(BY2PG, BY2PG, 0);
+ memset(sgmap, 0, BY2PG);
+
+ /*
+ * Prepare scatter-gather map for 0-8MB.
+ */
+ pte = sgmap;
+ for(pa = 0; pa < 8*1024*1024; pa += BY2PG)
+ *pte++ = ((pa>>PGSHIFT)<<1)|1;
+
+ /*
+ * Set up a map for ISA DMA accesses to physical memory.
+ * Addresses presented by an ISA device between ISAWINDOW
+ * and ISAWINDOW+8MB will be translated to between 0 and
+ * 0+8MB of physical memory.
+ */
+ wind[0x400/4] = ISAWINDOW|2|1; /* window base */
+ wind[0x440/4] = 0x00700000; /* window mask */
+ wind[0x480/4] = PADDR(sgmap)>>2; /* <33:10> of sg map */
+
+ wind[0x100/4] = 3; /* invalidate tlb cache */
+}
+
+static void *
+kmapio(ulong space, ulong offset, int size)
+{
+ return kmapv(((uvlong)space<<32LL)|offset, size);
+}
+
+static void
+coreinit(void)
+{
+ int i;
+
+ core = kmapio(0x87, 0x40000000, 0x10000);
+ wind = kmapio(0x87, 0x60000000, 0x1000);
+
+ iobase0 = (ulong)kmapio(0x89, 0, 0x20000);
+
+ /* hae_io = core[0x440/4];
+ iobase1 = (ulong)kmapio(0x89, hae_io, 0x10000); */
+
+ /* save critical parts of hardware memory mapping */
+ for (i = 4; i < 8; i++) {
+ windsave[4*(i-4)+0] = wind[(i*0x100+0x00)/4];
+ windsave[4*(i-4)+1] = wind[(i*0x100+0x40)/4];
+ windsave[4*(i-4)+2] = wind[(i*0x100+0x80)/4];
+ }
+ coresave[0] = core[0x140/4];
+
+ /* disable windows */
+ wind[0x400/4] = 0;
+ wind[0x500/4] = 0;
+ wind[0x600/4] = 0;
+ wind[0x700/4] = 0;
+
+ sginit();
+
+ /*
+ * Set up a map for PCI DMA accesses to physical memory.
+ * Addresses presented by a PCI device between PCIWINDOW
+ * and PCIWINDOW+1GB will be translated to between 0 and
+ * 0+1GB of physical memory.
+ */
+ wind[0x500/4] = PCIWINDOW|1;
+ wind[0x540/4] = 0x3ff00000;
+ wind[0x580/4] = 0;
+
+ /* clear error state */
+ core[0x8200/4] = 0x7ff;
+
+ /* set config: byte/word enable, no monster window, etc. */
+ core[0x140/4] = 0x21;
+
+ /* turn off mcheck on master abort. now we can probe PCI space. */
+ core[0x8280/4] &= ~(1<<7);
+
+ /* set up interrupts. */
+ i8259init();
+ cserve(52, 4); /* enable SIO interrupt */
+}
+
+void
+ciaerror(void)
+{
+ print("cia error 0x%luX\n", core[0x8200/4]);
+}
+
+static void
+corehello(void)
+{
+ print("cpu%d: CIA revision %ld; cnfg %lux cntrl %lux\n",
+ 0, /* BUG */
+ core[0x80/4] & 0x7f, core[0x140/4], core[0x100/4]);
+ print("cpu%d: HAE_IO %lux\n", 0, core[0x440/4]);
+ print("\n");
+}
+
+static void
+coredetach(void)
+{
+ int i;
+
+ for (i = 4; i < 8; i++) {
+ wind[(i*0x100+0x00)/4] = windsave[4*(i-4)+0];
+ wind[(i*0x100+0x40)/4] = windsave[4*(i-4)+1];
+ wind[(i*0x100+0x80)/4] = windsave[4*(i-4)+2];
+ }
+ core[0x140/4] = coresave[0];
+/* for (i = 0; i < 4; i++)
+ if (i != 4)
+ cserve(53, i); /* disable interrupts */
+}
+
+static Lock pcicfgl;
+static ulong pcimap[256];
+
+static void*
+pcicfg2117x(int tbdf, int rno)
+{
+ int space, bus;
+ ulong base;
+
+ bus = BUSBNO(tbdf);
+ lock(&pcicfgl);
+ base = pcimap[bus];
+ if (base == 0) {
+ if(bus)
+ space = 0x8B;
+ else
+ space = 0x8A;
+ pcimap[bus] = base = (ulong)kmapio(space, MKBUS(0, bus, 0, 0), (1<<16));
+ }
+ unlock(&pcicfgl);
+ return (void*)(base + BUSDF(tbdf) + rno);
+}
+
+static void*
+pcimem2117x(int addr, int len)
+{
+ return kmapio(0x88, addr, len);
+}
+
+static int
+intrenable164(Vctl *v)
+{
+ int vec, irq;
+
+ irq = v->irq;
+ if(irq > MaxIrqPIC) {
+ print("intrenable: irq %d out of range\n", v->irq);
+ return -1;
+ }
+ if(BUSTYPE(v->tbdf) == BusPCI) {
+ vec = irq+VectorPCI;
+ cserve(52, irq);
+ }
+ else {
+ vec = irq+VectorPIC;
+ if(i8259enable(irq, v->tbdf, v) == -1)
+ return -1;
+ }
+ return vec;
+}
+
+/*
+ * I have a function pointer in PCArch for every one of these, because on
+ * some Alphas we have to use sparse mode, but on others we can use
+ * MOVB et al. Additionally, the PC164 documentation threatened us
+ * with the lie that the SIO is in region B, but everything else in region A.
+ * This turned out not to be the case. Given the cost of this solution, it
+ * may be better just to use sparse mode for I/O space on all platforms.
+ */
+int
+inb2117x(int port)
+{
+ mb();
+ return *(uchar*)(iobase(port));
+}
+
+ushort
+ins2117x(int port)
+{
+ mb();
+ return *(ushort*)(iobase(port));
+}
+
+ulong
+inl2117x(int port)
+{
+ mb();
+ return *(ulong*)(iobase(port));
+}
+
+void
+outb2117x(int port, int val)
+{
+ mb();
+ *(uchar*)(iobase(port)) = val;
+ mb();
+}
+
+void
+outs2117x(int port, ushort val)
+{
+ mb();
+ *(ushort*)(iobase(port)) = val;
+ mb();
+}
+
+void
+outl2117x(int port, ulong val)
+{
+ mb();
+ *(ulong*)(iobase(port)) = val;
+ mb();
+}
+
+void
+insb2117x(int port, void *buf, int len)
+{
+ int i;
+ uchar *p, *q;
+
+ p = (uchar*)iobase(port);
+ q = buf;
+ for(i = 0; i < len; i++){
+ mb();
+ *q++ = *p;
+ }
+}
+
+void
+inss2117x(int port, void *buf, int len)
+{
+ int i;
+ ushort *p, *q;
+
+ p = (ushort*)iobase(port);
+ q = buf;
+ for(i = 0; i < len; i++){
+ mb();
+ *q++ = *p;
+ }
+}
+
+void
+insl2117x(int port, void *buf, int len)
+{
+ int i;
+ ulong *p, *q;
+
+ p = (ulong*)iobase(port);
+ q = buf;
+ for(i = 0; i < len; i++){
+ mb();
+ *q++ = *p;
+ }
+}
+
+void
+outsb2117x(int port, void *buf, int len)
+{
+ int i;
+ uchar *p, *q;
+
+ p = (uchar*)iobase(port);
+ q = buf;
+ for(i = 0; i < len; i++){
+ mb();
+ *p = *q++;
+ }
+}
+
+void
+outss2117x(int port, void *buf, int len)
+{
+ int i;
+ ushort *p, *q;
+
+ p = (ushort*)iobase(port);
+ q = buf;
+ for(i = 0; i < len; i++){
+ mb();
+ *p = *q++;
+ }
+}
+
+void
+outsl2117x(int port, void *buf, int len)
+{
+ int i;
+ ulong *p, *q;
+
+ p = (ulong*)iobase(port);
+ q = buf;
+ for(i = 0; i < len; i++){
+ mb();
+ *p = *q++;
+ }
+}
+
+PCArch arch164 = {
+ "EB164",
+ ident,
+ coreinit,
+ corehello,
+ coredetach,
+ pcicfg2117x,
+ pcimem2117x,
+ intrenable164,
+ nil,
+ nil,
+
+ inb2117x,
+ ins2117x,
+ inl2117x,
+ outb2117x,
+ outs2117x,
+ outl2117x,
+ insb2117x,
+ inss2117x,
+ insl2117x,
+ outsb2117x,
+ outss2117x,
+ outsl2117x,
+};
diff --git a/sys/src/9/alphapc/audio.h b/sys/src/9/alphapc/audio.h
new file mode 100755
index 000000000..53d5a8afb
--- /dev/null
+++ b/sys/src/9/alphapc/audio.h
@@ -0,0 +1,16 @@
+enum
+{
+ Bufsize = 16*1024, /* 92 ms each */
+ Nbuf = 16, /* 1.5 seconds total */
+ Dma = 5,
+ IrqAUDIO = 5,
+ SBswab = 0,
+};
+
+#define seteisadma(a, b) dmainit(a, Bufsize);
+#define CACHELINESZ 128
+#define UNCACHED(type, v) (type*)((ulong)(v))
+#define dcflush(a, b)
+
+#define Int0vec
+#define setvec(v, f, a) intrenable(v, f, a, BUSUNKNOWN, "audio")
diff --git a/sys/src/9/alphapc/axp.h b/sys/src/9/alphapc/axp.h
new file mode 100755
index 000000000..102a6b66d
--- /dev/null
+++ b/sys/src/9/alphapc/axp.h
@@ -0,0 +1,71 @@
+typedef struct Hwrpb Hwrpb;
+typedef struct Hwcpu Hwcpu;
+typedef struct Hwdsr Hwdsr;
+
+struct Hwrpb
+{
+ uvlong phys;
+ uvlong sign;
+ uvlong rev;
+ uvlong size;
+ uvlong cpu0;
+ uvlong by2pg;
+ uvlong pabits;
+ uvlong maxasn;
+ char ssn[16];
+ uvlong systype;
+ uvlong sysvar;
+ uvlong sysrev;
+ uvlong ifreq;
+ uvlong cfreq;
+ uvlong vptb;
+ uvlong resv;
+ uvlong tbhint;
+ uvlong ncpu;
+ uvlong cpulen;
+ uvlong cpuoff;
+ uvlong nctb;
+ uvlong ctblen;
+ uvlong ctboff;
+ uvlong ccrboff;
+ uvlong memoff;
+ uvlong confoff;
+ uvlong fruoff;
+ uvlong termsaveva;
+ uvlong termsavex;
+ uvlong termrestva;
+ uvlong termrestx;
+ uvlong termresetva;
+ uvlong termresetx;
+ uvlong sysresv;
+ uvlong hardresv;
+ uvlong csum;
+ uvlong rxrdymsk;
+ uvlong txrdymsk;
+ uvlong dsroff; /* rev 6 or higher */
+};
+
+extern Hwrpb* hwrpb;
+
+struct Hwcpu
+{
+ uvlong hwpcb[16];
+ uvlong state;
+ uvlong palmainlen;
+ uvlong palscratchlen;
+ uvlong palmainpa;
+ uvlong palscratchpa;
+ uvlong palrev;
+ uvlong cputype;
+ uvlong cpuvar;
+ uvlong cpurev;
+ uvlong serial[2];
+ /* more crap ... */
+};
+
+struct Hwdsr
+{
+ vlong smm;
+ uvlong lurtoff;
+ uvlong sysnameoff;
+};
diff --git a/sys/src/9/alphapc/cga.c b/sys/src/9/alphapc/cga.c
new file mode 100755
index 000000000..c216617b7
--- /dev/null
+++ b/sys/src/9/alphapc/cga.c
@@ -0,0 +1,113 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+enum {
+ Width = 160,
+ Height = 25,
+
+ Attr = 0x4f, /* white on blue */
+};
+
+static ulong cgabase;
+#define CGASCREENBASE ((uchar*)cgabase)
+
+static int cgapos;
+static int screeninitdone;
+static Lock cgascreenlock;
+
+static uchar
+cgaregr(int index)
+{
+ outb(0x3D4, index);
+ return inb(0x3D4+1) & 0xFF;
+}
+
+static void
+cgaregw(int index, int data)
+{
+ outb(0x3D4, index);
+ outb(0x3D4+1, data);
+}
+
+static void
+movecursor(void)
+{
+ cgaregw(0x0E, (cgapos/2>>8) & 0xFF);
+ cgaregw(0x0F, cgapos/2 & 0xFF);
+ CGASCREENBASE[cgapos+1] = Attr;
+}
+
+static void
+cgascreenputc(int c)
+{
+ int i;
+
+ if(c == '\n'){
+ cgapos = cgapos/Width;
+ cgapos = (cgapos+1)*Width;
+ }
+ else if(c == '\t'){
+ i = 8 - ((cgapos/2)&7);
+ while(i-->0)
+ cgascreenputc(' ');
+ }
+ else if(c == '\b'){
+ if(cgapos >= 2)
+ cgapos -= 2;
+ cgascreenputc(' ');
+ cgapos -= 2;
+ }
+ else{
+ CGASCREENBASE[cgapos++] = c;
+ CGASCREENBASE[cgapos++] = Attr;
+ }
+ if(cgapos >= Width*Height){
+ memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
+ for (i = Width*(Height-1); i < Width*Height;) {
+ CGASCREENBASE[i++] = 0x20;
+ CGASCREENBASE[i++] = Attr;
+ }
+ cgapos = Width*(Height-1);
+ }
+ movecursor();
+}
+
+void
+screeninit(void)
+{
+ cgabase = (ulong)arch->pcimem(0xB8000, 0x8000);
+
+ cgapos = cgaregr(0x0E)<<8;
+ cgapos |= cgaregr(0x0F);
+ cgapos *= 2;
+ screeninitdone = 1;
+}
+
+static void
+cgascreenputs(char* s, int n)
+{
+ if(!screeninitdone)
+ return;
+ if(!islo()){
+ /*
+ * Don't deadlock trying to
+ * print in an interrupt.
+ */
+ if(!canlock(&cgascreenlock))
+ return;
+ }
+ else
+ lock(&cgascreenlock);
+
+ while(n-- > 0)
+ cgascreenputc(*s++);
+
+ unlock(&cgascreenlock);
+}
+
+void (*screenputs)(char*, int) = cgascreenputs;
diff --git a/sys/src/9/alphapc/clock.c b/sys/src/9/alphapc/clock.c
new file mode 100755
index 000000000..1300e9338
--- /dev/null
+++ b/sys/src/9/alphapc/clock.c
@@ -0,0 +1,112 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "axp.h"
+#include "ureg.h"
+
+void
+clockinit(void)
+{
+}
+
+uvlong
+cycletimer(void)
+{
+ ulong pcc;
+ vlong delta;
+
+ pcc = rpcc(nil) & 0xFFFFFFFF;
+ if(m->cpuhz == 0){
+ /*
+ * pcclast is needed to detect wraparound of
+ * the cycle timer which is only 32-bits.
+ * m->cpuhz is set from the info passed from
+ * the firmware.
+ * This could be in clockinit if can
+ * guarantee no wraparound between then and now.
+ *
+ * All the clock stuff needs work.
+ */
+ m->cpuhz = hwrpb->cfreq;
+ m->pcclast = pcc;
+ }
+ delta = pcc - m->pcclast;
+ if(delta < 0)
+ delta += 0x100000000LL;
+ m->pcclast = pcc;
+ m->fastclock += delta;
+
+ return MACHP(0)->fastclock;
+}
+
+uvlong
+fastticks(uvlong* hz)
+{
+ uvlong ticks;
+ int x;
+
+ x = splhi();
+ ticks = cycletimer();
+ splx(x);
+
+ if(hz)
+ *hz = m->cpuhz;
+
+ return ticks;
+}
+
+ulong
+µs(void)
+{
+ return fastticks2us(cycletimer());
+}
+
+/*
+ * performance measurement ticks. must be low overhead.
+ * doesn't have to count over a second.
+ */
+ulong
+perfticks(void)
+{
+ return rpcc(nil);
+}
+
+void
+timerset(Tval)
+{
+}
+
+void
+microdelay(int us)
+{
+ uvlong eot;
+
+ eot = fastticks(nil) + (m->cpuhz/1000000)*us;
+ while(fastticks(nil) < eot)
+ ;
+}
+
+void
+delay(int millisecs)
+{
+ microdelay(millisecs*1000);
+}
+
+void
+clock(Ureg *ureg)
+{
+ static int count;
+
+ cycletimer();
+
+ /* HZ == 100, timer == 1024Hz. error < 1ms */
+ count += 100;
+ if (count < 1024)
+ return;
+ count -= 1024;
+
+ timerintr(ureg, 0);
+}
diff --git a/sys/src/9/alphapc/cycintr.c b/sys/src/9/alphapc/cycintr.c
new file mode 100755
index 000000000..d56edba80
--- /dev/null
+++ b/sys/src/9/alphapc/cycintr.c
@@ -0,0 +1,27 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+int
+havetimer(void)
+{
+ return 0;
+}
+
+void
+timeradd(Timer *)
+{
+}
+
+void
+timerdel(Timer *)
+{
+}
+
+void
+clockintrsched(void)
+{
+}
diff --git a/sys/src/9/alphapc/dat.h b/sys/src/9/alphapc/dat.h
new file mode 100755
index 000000000..5257a291e
--- /dev/null
+++ b/sys/src/9/alphapc/dat.h
@@ -0,0 +1,266 @@
+typedef struct Conf Conf;
+typedef struct Confmem Confmem;
+typedef struct FPsave FPsave;
+typedef struct ISAConf ISAConf;
+typedef struct Label Label;
+typedef struct Lock Lock;
+typedef struct Mach Mach;
+typedef struct Notsave Notsave;
+typedef struct Page Page;
+typedef struct PCArch PCArch;
+typedef struct PCB PCB;
+typedef struct Pcidev Pcidev;
+typedef struct PMMU PMMU;
+typedef struct Proc Proc;
+typedef struct Sys Sys;
+typedef struct Ureg Ureg;
+typedef struct Vctl Vctl;
+typedef vlong Tval;
+
+#define MAXSYSARG 6 /* for mount(fd, mpt, flag, arg, srv) */
+
+/*
+ * parameters for sysproc.c
+ */
+#define AOUT_MAGIC L_MAGIC
+
+/*
+ * machine dependent definitions used by ../port/dat.h
+ */
+
+struct Lock
+{
+ ulong key; /* semaphore (non-zero = locked) */
+ ulong sr;
+ ulong pc;
+ Proc *p;
+ Mach *m;
+ ulong pid;
+ ushort isilock;
+};
+
+struct Label
+{
+ ulong sp;
+ ulong pc;
+};
+
+/*
+ * Proc.fpstate
+ */
+enum
+{
+ /* floating point states */
+ FPinit,
+ FPactive,
+ FPinactive,
+
+ /* bit or'd with the state */
+ FPillegal= 0x100,
+};
+
+struct FPsave
+{
+ long fpreg[2*32];
+ long dummy; /* lower bits of FPCR, useless */
+ long fpstatus;
+};
+
+struct Confmem
+{
+ ulong base;
+ ulong npage;
+ ulong kbase;
+ ulong klimit;
+};
+
+struct Conf
+{
+ ulong nmach; /* processors */
+ ulong nproc; /* processes */
+ 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 copymode; /* 0 is copy on write, 1 is copy on reference */
+ int monitor; /* has display? */
+ ulong ialloc; /* bytes available for interrupt time allocation */
+ ulong pipeqsize; /* size in bytes of pipe queues */
+};
+
+/*
+ * mmu goo in the Proc structure
+ */
+struct PMMU
+{
+ Page *mmutop; /* 1st level table */
+ Page *mmulvl2; /* 2nd level table */
+ Page *mmufree; /* unused page table pages */
+ Page *mmuused; /* used page table pages, except for mmustk */
+};
+
+/*
+ * things saved in the Proc structure during a notify
+ */
+struct Notsave
+{
+ ulong UNUSED;
+};
+
+#include "../port/portdat.h"
+
+/*
+ * machine dependent definitions not used by ../port/dat.h
+ */
+/*
+ * Fake kmap
+ */
+typedef void KMap;
+#define VA(k) ((ulong)(k))
+#define kmap(p) (KMap*)((p)->pa|KZERO)
+#define kunmap(k)
+
+/*
+ * Process Control Block, used by PALcode
+ */
+struct PCB {
+ uvlong ksp;
+ uvlong usp;
+ uvlong ptbr;
+ ulong asn;
+ ulong pcc;
+ uvlong unique;
+ ulong fen;
+ ulong dummy;
+ uvlong rsrv1;
+ uvlong rsrv2;
+};
+
+struct Mach
+{
+ /* OFFSETS OF THE FOLLOWING KNOWN BY l.s */
+ int machno; /* physical id of processor */
+ ulong splpc; /* pc that called splhi() */
+ Proc *proc; /* current process on this processor */
+
+ /* ordering from here on irrelevant */
+
+ ulong ticks; /* of the clock since boot time */
+ Label sched; /* scheduler wakeup */
+ Lock alarmlock; /* access to alarm list */
+ void *alarm; /* alarms bound to this clock */
+ int inclockintr;
+
+ Proc* readied; /* for runproc */
+ ulong schedticks; /* next forced context switch */
+
+ vlong cpuhz; /* hwrpb->cfreq */
+ uvlong cyclefreq; /* Frequency of user readable cycle counter */
+ ulong pcclast;
+ uvlong fastclock;
+ Perf perf; /* performance counters */
+
+ int tlbfault; /* only used by devproc; no access to tlb */
+ int tlbpurge; /* ... */
+ int pfault;
+ int cs;
+ int syscall;
+ int load;
+ int intr;
+ int flushmmu; /* make current proc flush it's mmu state */
+ int ilockdepth;
+
+ ulong spuriousintr;
+ int lastintr;
+
+ PCB;
+
+ /* MUST BE LAST */
+ int stack[1];
+};
+
+struct
+{
+ Lock;
+ short machs;
+ short exiting;
+ short ispanic;
+}active;
+
+/*
+ * Implementation-dependant functions (outside of Alpha architecture proper).
+ * Called PCArch because that's what mkdevc calls it (for the PC).
+ */
+struct PCArch
+{
+ char* id;
+ int (*ident)(void);
+
+ void (*coreinit)(void); /* set up core logic, PCI mappings etc */
+ void (*corehello)(void); /* identify core logic to user */
+ void (*coredetach)(void); /* restore core logic before return to console */
+ void *(*pcicfg)(int, int); /* map and point to PCI cfg space */
+ void *(*pcimem)(int, int); /* map and point to PCI memory space */
+ int (*intrenable)(Vctl*);
+ int (*intrvecno)(int);
+ int (*intrdisable)(int);
+
+ int (*_inb)(int);
+ ushort (*_ins)(int);
+ ulong (*_inl)(int);
+ void (*_outb)(int, int);
+ void (*_outs)(int, ushort);
+ void (*_outl)(int, ulong);
+ void (*_insb)(int, void*, int);
+ void (*_inss)(int, void*, int);
+ void (*_insl)(int, void*, int);
+ void (*_outsb)(int, void*, int);
+ void (*_outss)(int, void*, int);
+ void (*_outsl)(int, void*, int);
+};
+
+/*
+ * a parsed plan9.ini line
+ */
+#define NISAOPT 8
+
+struct ISAConf {
+ char *type;
+ ulong port;
+ int irq;
+ ulong dma;
+ ulong mem;
+ ulong size;
+ ulong freq;
+
+ int nopt;
+ char *opt[NISAOPT];
+};
+
+extern PCArch *arch;
+
+#define MACHP(n) ((Mach *)((int)&mach0+n*BY2PG))
+extern Mach mach0;
+
+extern register Mach *m;
+extern register Proc *up;
+
+/*
+ * hardware info about a device
+ */
+typedef struct {
+ ulong port;
+ int size;
+} Devport;
+
+struct DevConf
+{
+ ulong intnum; /* interrupt number */
+ char *type; /* card type, malloced */
+ int nports; /* Number of ports */
+ Devport *ports; /* The ports themselves */
+};
+
+extern FPsave initfp;
diff --git a/sys/src/9/alphapc/devarch.c b/sys/src/9/alphapc/devarch.c
new file mode 100755
index 000000000..352e47c6f
--- /dev/null
+++ b/sys/src/9/alphapc/devarch.c
@@ -0,0 +1,533 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "axp.h"
+
+typedef struct IOMap IOMap;
+struct IOMap
+{
+ IOMap *next;
+ char tag[13];
+ ulong start;
+ ulong end;
+};
+
+static struct
+{
+ Lock;
+ IOMap *m;
+ IOMap *free;
+ IOMap maps[32]; // some initial free maps
+
+ QLock ql; // lock for reading map
+} iomap;
+
+enum {
+ Qdir = 0,
+ Qioalloc = 1,
+ Qiob,
+ Qiow,
+ Qiol,
+ Qbase,
+
+ Qmax = 16,
+};
+
+typedef long Rdwrfn(Chan*, void*, long, vlong);
+
+static Rdwrfn *readfn[Qmax];
+static Rdwrfn *writefn[Qmax];
+
+static Dirtab archdir[] = {
+ ".", { Qdir, 0, QTDIR }, 0, 0555,
+ "ioalloc", { Qioalloc, 0 }, 0, 0444,
+ "iob", { Qiob, 0 }, 0, 0660,
+ "iow", { Qiow, 0 }, 0, 0660,
+ "iol", { Qiol, 0 }, 0, 0660,
+};
+Lock archwlock; /* the lock is only for changing archdir */
+int narchdir = Qbase;
+int (*_pcmspecial)(char *, ISAConf *);
+void (*_pcmspecialclose)(int);
+
+/*
+ * Add a file to the #P listing. Once added, you can't delete it.
+ * You can't add a file with the same name as one already there,
+ * and you get a pointer to the Dirtab entry so you can do things
+ * like change the Qid version. Changing the Qid path is disallowed.
+ */
+Dirtab*
+addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
+{
+ int i;
+ Dirtab d;
+ Dirtab *dp;
+
+ memset(&d, 0, sizeof d);
+ strcpy(d.name, name);
+ d.perm = perm;
+
+ lock(&archwlock);
+ if(narchdir >= Qmax){
+ unlock(&archwlock);
+ return nil;
+ }
+
+ for(i=0; i<narchdir; i++)
+ if(strcmp(archdir[i].name, name) == 0){
+ unlock(&archwlock);
+ return nil;
+ }
+
+ d.qid.path = narchdir;
+ archdir[narchdir] = d;
+ readfn[narchdir] = rdfn;
+ writefn[narchdir] = wrfn;
+ dp = &archdir[narchdir++];
+ unlock(&archwlock);
+
+ return dp;
+}
+
+void
+ioinit(void)
+{
+ int i;
+
+ for(i = 0; i < nelem(iomap.maps)-1; i++)
+ iomap.maps[i].next = &iomap.maps[i+1];
+ iomap.maps[i].next = nil;
+ iomap.free = iomap.maps;
+
+ // a dummy entry at 2^17
+ ioalloc(0x20000, 1, 0, "dummy");
+}
+
+//
+// alloc some io port space and remember who it was
+// alloced to. if port < 0, find a free region.
+//
+int
+ioalloc(int port, int size, int align, char *tag)
+{
+ IOMap *m, **l;
+ int i;
+
+ lock(&iomap);
+ if(port < 0){
+ // find a free port above 0x400 and below 0x1000
+ port = 0x400;
+ for(l = &iomap.m; *l; l = &(*l)->next){
+ m = *l;
+ i = m->start - port;
+ if(i > size)
+ break;
+ if(align > 0)
+ port = ((port+align-1)/align)*align;
+ else
+ port = m->end;
+ }
+ if(*l == nil){
+ unlock(&iomap);
+ return -1;
+ }
+ } else {
+ // see if the space clashes with previously allocated ports
+ for(l = &iomap.m; *l; l = &(*l)->next){
+ m = *l;
+ if(m->end <= port)
+ continue;
+ if(m->start >= port+size)
+ break;
+ unlock(&iomap);
+ return -1;
+ }
+ }
+ m = iomap.free;
+ if(m == nil){
+ print("ioalloc: out of maps");
+ unlock(&iomap);
+ return port;
+ }
+ iomap.free = m->next;
+ m->next = *l;
+ m->start = port;
+ m->end = port + size;
+ strncpy(m->tag, tag, sizeof(m->tag));
+ m->tag[sizeof(m->tag)-1] = 0;
+ *l = m;
+
+ archdir[0].qid.vers++;
+
+ unlock(&iomap);
+ return m->start;
+}
+
+void
+iofree(int port)
+{
+ IOMap *m, **l;
+
+ lock(&iomap);
+ for(l = &iomap.m; *l; l = &(*l)->next){
+ if((*l)->start == port){
+ m = *l;
+ *l = m->next;
+ m->next = iomap.free;
+ iomap.free = m;
+ break;
+ }
+ if((*l)->start > port)
+ break;
+ }
+ archdir[0].qid.vers++;
+ unlock(&iomap);
+}
+
+int
+iounused(int start, int end)
+{
+ IOMap *m;
+
+ for(m = iomap.m; m; m = m->next){
+ if(start >= m->start && start < m->end
+ || start <= m->start && end > m->start)
+ return 0;
+ }
+ return 1;
+}
+
+static void
+checkport(int start, int end)
+{
+ /* standard vga regs are OK */
+ if(start >= 0x2b0 && end <= 0x2df+1)
+ return;
+ if(start >= 0x3c0 && end <= 0x3da+1)
+ return;
+
+ if(iounused(start, end))
+ return;
+ error(Eperm);
+}
+
+static Chan*
+archattach(char* spec)
+{
+ return devattach('P', spec);
+}
+
+Walkqid*
+archwalk(Chan* c, Chan *nc, char** name, int nname)
+{
+ return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
+}
+
+static int
+archstat(Chan* c, uchar* dp, int n)
+{
+ return devstat(c, dp, n, archdir, narchdir, devgen);
+}
+
+static Chan*
+archopen(Chan* c, int omode)
+{
+ return devopen(c, omode, archdir, nelem(archdir), devgen);
+}
+
+static void
+archclose(Chan*)
+{
+}
+
+enum
+{
+ Linelen= 31,
+};
+
+static long
+archread(Chan *c, void *a, long n, vlong offset)
+{
+ char buf[Linelen+1], *p;
+ int port;
+ ushort *sp;
+ ulong *lp;
+ IOMap *m;
+ Rdwrfn *fn;
+
+ switch((ulong)c->qid.path){
+
+ case Qdir:
+ return devdirread(c, a, n, archdir, nelem(archdir), devgen);
+
+ case Qiob:
+ port = offset;
+ checkport(offset, offset+n);
+ for(p = a; port < offset+n; port++)
+ *p++ = inb(port);
+ return n;
+
+ case Qiow:
+ if((n & 0x01) || (offset & 0x01))
+ error(Ebadarg);
+ checkport(offset, offset+n+1);
+ n /= 2;
+ sp = a;
+ for(port = offset; port < offset+n; port += 2)
+ *sp++ = ins(port);
+ return n*2;
+
+ case Qiol:
+ if((n & 0x03) || (offset & 0x03))
+ error(Ebadarg);
+ checkport(offset, offset+n+3);
+ n /= 4;
+ lp = a;
+ for(port = offset; port < offset+n; port += 4)
+ *lp++ = inl(port);
+ return n*4;
+
+ case Qioalloc:
+ break;
+
+ default:
+ if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
+ return fn(c, a, n, offset);
+ error(Eperm);
+ break;
+ }
+
+ offset = offset/Linelen;
+ n = n/Linelen;
+ p = a;
+ lock(&iomap);
+ for(m = iomap.m; n > 0 && m != nil; m = m->next){
+ if(offset-- > 0)
+ continue;
+ if(strcmp(m->tag, "dummy") == 0)
+ break;
+ sprint(buf, "%8lux %8lux %-12.12s\n", m->start, m->end-1, m->tag);
+ memmove(p, buf, Linelen);
+ p += Linelen;
+ n--;
+ }
+ unlock(&iomap);
+
+ return p - (char*)a;
+}
+
+static long
+archwrite(Chan *c, void *a, long n, vlong offset)
+{
+ char *p;
+ int port;
+ ushort *sp;
+ ulong *lp;
+ Rdwrfn *fn;
+
+ switch((ulong)c->qid.path){
+
+ case Qiob:
+ p = a;
+ checkport(offset, offset+n);
+ for(port = offset; port < offset+n; port++)
+ outb(port, *p++);
+ return n;
+
+ case Qiow:
+ if((n & 01) || (offset & 01))
+ error(Ebadarg);
+ checkport(offset, offset+n+1);
+ n /= 2;
+ sp = a;
+ for(port = offset; port < offset+n; port += 2)
+ outs(port, *sp++);
+ return n*2;
+
+ case Qiol:
+ if((n & 0x03) || (offset & 0x03))
+ error(Ebadarg);
+ checkport(offset, offset+n+3);
+ n /= 4;
+ lp = a;
+ for(port = offset; port < offset+n; port += 4)
+ outl(port, *lp++);
+ return n*4;
+
+ default:
+ if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
+ return fn(c, a, n, offset);
+ error(Eperm);
+ break;
+ }
+ return 0;
+}
+
+Dev archdevtab = {
+ 'P',
+ "arch",
+
+ devreset,
+ devinit,
+ devshutdown,
+ archattach,
+ archwalk,
+ archstat,
+ archopen,
+ devcreate,
+ archclose,
+ archread,
+ devbread,
+ archwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+PCArch* arch;
+extern PCArch* knownarch[];
+
+PCArch archgeneric = {
+ "generic", /* id */
+ 0, /* ident */
+
+ 0, /* coreinit */
+ 0, /* coredetach */
+};
+
+static char *sysnames[] =
+{
+[1] "Alpha Demo. Unit",
+[2] "DEC 4000; Cobra",
+[3] "DEC 7000; Ruby",
+[4] "DEC 3000/500; Flamingo family (TC)",
+[6] "DEC 2000/300; Jensen (EISA/ISA)",
+[7] "DEC 3000/300; Pelican (TC)",
+[8] "Avalon A12; Avalon Multicomputer",
+[9] "DEC 2100/A500; Sable",
+[10] "DEC APXVME/64; AXPvme (VME?)",
+[11] "DEC AXPPCI/33; NoName (PCI/ISA)",
+[12] "DEC 21000; TurboLaser (PCI/EISA)",
+[13] "DEC 2100/A50; Avanti (PCI/ISA)",
+[14] "DEC MUSTANG; Mustang",
+[15] "DEC KN20AA; kn20aa (PCI/EISA)",
+[17] "DEC 1000; Mikasa (PCI/ISA?)",
+[19] "EB66; EB66 (PCI/ISA?)", // DEC?
+[20] "EB64P; EB64+ (PCI/ISA?)", // DEC?
+[21] "Alphabook1; Alphabook",
+[22] "DEC 4100; Rawhide (PCI/EISA)",
+[23] "DEC EV45/PBP; Lego",
+[24] "DEC 2100A/A500; Lynx",
+[26] "DEC AlphaPC 164", // only supported one: "EB164 (PCI/ISA)"
+[27] "DEC 1000A; Noritake",
+[28] "DEC AlphaVME/224; Cortex",
+[30] "DEC 550; Miata (PCI/ISA)",
+[32] "DEC EV56/PBP; Takara",
+[33] "DEC AlphaVME/320; Yukon (VME?)",
+[34] "DEC 6600; MonetGoldrush",
+// 200 and up is Alpha Processor Inc. machines
+// [201] "API UP1000; Nautilus",
+};
+
+static char *cpunames[] =
+{
+[1] "EV3",
+[2] "EV4: 21064",
+[3] "Simulation",
+[4] "LCA4: 2106[68]",
+[5] "EV5: 21164",
+[6] "EV45: 21064A",
+[7] "21164A", /* only supported one: EV56 */
+[8] "EV6: 21264",
+[9] "PCA256: 21164PC",
+};
+
+void
+cpuidprint(void)
+{
+ int i, maj, min;
+ Hwcpu *cpu;
+ Hwdsr *dsr;
+ char *s;
+
+ print("\n");
+
+ if (hwrpb->rev >= 6) {
+ dsr = (Hwdsr*)((ulong)hwrpb + hwrpb->dsroff);
+
+ s = (char*)dsr + dsr->sysnameoff + 8;
+ print("%s\n", s);
+ }
+ else {
+ s = "<unknown>";
+ if (hwrpb->systype < nelem(sysnames))
+ s = sysnames[hwrpb->systype];
+ print("%s (%llux, %llux, %llux)\n", s, hwrpb->systype, hwrpb->sysvar, hwrpb->sysrev);
+ }
+
+ for (i = 0; i < hwrpb->ncpu; i++) {
+ cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff + i*hwrpb->cpulen);
+ s = "<unknown>";
+ maj = (ulong)cpu->cputype;
+ min = (ulong)(cpu->cputype>>32);
+ if (maj < nelem(cpunames))
+ s = cpunames[maj];
+ print("cpu%d: %s-%d (%d.%d, %llux, %llux)\n",
+ i, s, min, maj, min, cpu->cpuvar, cpu->cpurev);
+ }
+
+ print("\n");
+}
+
+static long
+cputyperead(Chan*, void *a, long n, vlong offset)
+{
+ char str[32], *cputype;
+ ulong mhz, maj;
+ Hwcpu *cpu;
+
+ mhz = (m->cpuhz+999999)/1000000;
+ cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff); /* NB CPU 0 */
+ cputype = "unknown";
+ maj = (ulong)cpu->cputype;
+ if (maj < nelem(cpunames))
+ cputype = cpunames[maj];
+
+ snprint(str, sizeof(str), "%s %lud\n", cputype, mhz);
+ return readstr(offset, a, n, str);
+}
+
+void
+archinit(void)
+{
+ PCArch **p;
+
+ arch = 0;
+ for(p = knownarch; *p; p++){
+ if((*p)->ident && (*p)->ident() == 0){
+ arch = *p;
+ break;
+ }
+ }
+ if(arch == 0)
+ arch = &archgeneric;
+
+ addarchfile("cputype", 0444, cputyperead, nil);
+}
+
+int
+pcmspecial(char *idstr, ISAConf *isa)
+{
+ return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1;
+}
+
+void
+pcmspecialclose(int a)
+{
+ if (_pcmspecialclose != nil)
+ _pcmspecialclose(a);
+}
diff --git a/sys/src/9/alphapc/devvga.c b/sys/src/9/alphapc/devvga.c
new file mode 100755
index 000000000..551a19797
--- /dev/null
+++ b/sys/src/9/alphapc/devvga.c
@@ -0,0 +1,407 @@
+/*
+ * VGA controller
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+extern uchar *vgabios;
+
+enum {
+ Qdir,
+ Qvgactl,
+ Qvgabios,
+};
+
+static Dirtab vgadir[] = {
+ ".", { Qdir, 0, QTDIR }, 0, 0550,
+ "vgactl", { Qvgactl, 0 }, 0, 0660,
+ "vgabios", { Qvgabios, 0 }, 0x10000, 0440,
+};
+
+static void
+vgareset(void)
+{
+ /* reserve the 'standard' vga registers */
+ if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0)
+ panic("vga ports already allocated");
+ if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0)
+ panic("vga ports already allocated");
+ conf.monitor = 1;
+}
+
+static Chan*
+vgaattach(char* spec)
+{
+ if(*spec && strcmp(spec, "0"))
+ error(Eio);
+ return devattach('v', spec);
+}
+
+Walkqid*
+vgawalk(Chan* c, Chan *nc, char** name, int nname)
+{
+ return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
+}
+
+static int
+vgastat(Chan* c, uchar* dp, int n)
+{
+ return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
+}
+
+static Chan*
+vgaopen(Chan* c, int omode)
+{
+ return devopen(c, omode, vgadir, nelem(vgadir), devgen);
+}
+
+static void
+vgaclose(Chan*)
+{
+}
+
+static void
+checkport(int start, int end)
+{
+ /* standard vga regs are OK */
+ if(start >= 0x2b0 && end <= 0x2df+1)
+ return;
+ if(start >= 0x3c0 && end <= 0x3da+1)
+ return;
+
+ if(iounused(start, end))
+ return;
+ error(Eperm);
+}
+
+static long
+vgaread(Chan* c, void* a, long n, vlong off)
+{
+ int len;
+ char *p, *s;
+ VGAscr *scr;
+ ulong offset = off;
+ char chbuf[30];
+
+ switch((ulong)c->qid.path){
+
+ case Qdir:
+ return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);
+
+ case Qvgactl:
+ scr = &vgascreen[0];
+
+ p = malloc(READSTR);
+ if(waserror()){
+ free(p);
+ nexterror();
+ }
+
+ len = 0;
+
+ if(scr->dev)
+ s = scr->dev->name;
+ else
+ s = "cga";
+ len += snprint(p+len, READSTR-len, "type %s\n", s);
+
+ if(scr->gscreen) {
+ len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n",
+ scr->gscreen->r.max.x, scr->gscreen->r.max.y,
+ scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
+
+ if(Dx(scr->gscreen->r) != Dx(physgscreenr)
+ || Dy(scr->gscreen->r) != Dy(physgscreenr))
+ len += snprint(p+len, READSTR-len, "actualsize %dx%d\n",
+ physgscreenr.max.x, physgscreenr.max.y);
+ }
+
+ 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");
+ snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->paddr);
+ n = readstr(offset, a, n, p);
+ poperror();
+ free(p);
+
+ return n;
+
+ case Qvgabios:
+ if(vgabios == nil)
+ error(Egreg);
+ if(offset&0x80000000)
+ offset &= ~0x800E0000;
+ if(offset+n > 0x10000)
+ n = 0x10000-offset;
+ if(n < 0)
+ return 0;
+ memmove(a, vgabios+offset, n);
+ return n;
+
+ default:
+ error(Egreg);
+ break;
+ }
+
+ return 0;
+}
+
+static char Ebusy[] = "vga already configured";
+
+static void
+vgactl(char* a)
+{
+ int align, i, n, size, x, y, z;
+ char *chanstr, *field[6], *p;
+ ulong chan;
+ VGAscr *scr;
+ extern VGAdev *vgadev[];
+ extern VGAcur *vgacur[];
+ Rectangle r;
+
+ n = tokenize(a, field, nelem(field));
+ if(n < 1)
+ error(Ebadarg);
+
+ scr = &vgascreen[0];
+ if(strcmp(field[0], "hwgc") == 0){
+ if(n < 2)
+ error(Ebadarg);
+
+ if(strcmp(field[1], "off") == 0){
+ lock(&cursor);
+ if(scr->cur){
+ if(scr->cur->disable)
+ scr->cur->disable(scr);
+ scr->cur = nil;
+ }
+ unlock(&cursor);
+ return;
+ }
+
+ for(i = 0; vgacur[i]; i++){
+ if(strcmp(field[1], vgacur[i]->name))
+ continue;
+ lock(&cursor);
+ if(scr->cur && scr->cur->disable)
+ scr->cur->disable(scr);
+ scr->cur = vgacur[i];
+ if(scr->cur->enable)
+ scr->cur->enable(scr);
+ unlock(&cursor);
+ return;
+ }
+ }
+ else if(strcmp(field[0], "type") == 0){
+ if(n < 2)
+ error(Ebadarg);
+
+ for(i = 0; vgadev[i]; i++){
+ if(strcmp(field[1], vgadev[i]->name))
+ continue;
+ if(scr->dev && scr->dev->disable)
+ scr->dev->disable(scr);
+ scr->dev = vgadev[i];
+ if(scr->dev->enable)
+ scr->dev->enable(scr);
+ return;
+ }
+ }
+ else if(strcmp(field[0], "size") == 0){
+ if(n < 3)
+ error(Ebadarg);
+ if(drawhasclients())
+ error(Ebusy);
+
+ x = strtoul(field[1], &p, 0);
+ if(x == 0 || x > 2048)
+ error(Ebadarg);
+ if(*p)
+ p++;
+
+ y = strtoul(p, &p, 0);
+ if(y == 0 || y > 2048)
+ error(Ebadarg);
+ if(*p)
+ p++;
+
+ z = strtoul(p, &p, 0);
+
+ chanstr = field[2];
+ if((chan = strtochan(chanstr)) == 0)
+ error("bad channel");
+
+ if(chantodepth(chan) != z)
+ error("depth, channel do not match");
+
+ cursoroff(1);
+ deletescreenimage();
+ if(screensize(x, y, z, chan))
+ error(Egreg);
+ vgascreenwin(scr);
+ cursoron(1);
+ return;
+ }
+ else if(strcmp(field[0], "actualsize") == 0){
+ if(scr->gscreen == nil)
+ error("set the screen size first");
+
+ if(n < 2)
+ error(Ebadarg);
+ x = strtoul(field[1], &p, 0);
+ if(x == 0 || x > 2048)
+ error(Ebadarg);
+ if(*p)
+ p++;
+
+ y = strtoul(p, nil, 0);
+ if(y == 0 || y > 2048)
+ error(Ebadarg);
+
+ if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y)
+ error("physical screen bigger than virtual");
+
+ r = Rect(0,0,x,y);
+ if(!eqrect(r, scr->gscreen->r)){
+ if(scr->cur == nil || scr->cur->doespanning == 0)
+ error("virtual screen not supported");
+ }
+
+ physgscreenr = r;
+ return;
+ }
+ else if(strcmp(field[0], "palettedepth") == 0){
+ if(n < 2)
+ error(Ebadarg);
+
+ x = strtoul(field[1], &p, 0);
+ if(x != 8 && x != 6)
+ error(Ebadarg);
+
+ scr->palettedepth = x;
+ return;
+ }
+ else if(strcmp(field[0], "drawinit") == 0){
+ if(scr && scr->dev && scr->dev->drawinit)
+ scr->dev->drawinit(scr);
+ return;
+ }
+ else if(strcmp(field[0], "linear") == 0){
+ if(n < 2)
+ error(Ebadarg);
+
+ size = strtoul(field[1], 0, 0);
+ if(n < 3)
+ align = 0;
+ else
+ align = strtoul(field[2], 0, 0);
+ if(screenaperture(size, align))
+ error("not enough free address space");
+ return;
+ }
+/* else if(strcmp(field[0], "memset") == 0){
+ if(n < 4)
+ error(Ebadarg);
+ memset((void*)strtoul(field[1], 0, 0), atoi(field[2]), atoi(field[3]));
+ return;
+ }
+*/
+ else if(strcmp(field[0], "blank") == 0){
+ if(n < 1)
+ error(Ebadarg);
+ drawblankscreen(1);
+ return;
+ }
+ else if(strcmp(field[0], "blanktime") == 0){
+ if(n < 2)
+ error(Ebadarg);
+ blanktime = strtoul(field[1], 0, 0);
+ return;
+ }
+ else if(strcmp(field[0], "hwaccel") == 0){
+ if(n < 2)
+ error(Ebadarg);
+ if(strcmp(field[1], "on") == 0)
+ hwaccel = 1;
+ else if(strcmp(field[1], "off") == 0)
+ hwaccel = 0;
+ return;
+ }
+ else if(strcmp(field[0], "hwblank") == 0){
+ if(n < 2)
+ error(Ebadarg);
+ if(strcmp(field[1], "on") == 0)
+ hwblank = 1;
+ else if(strcmp(field[1], "off") == 0)
+ hwblank = 0;
+ return;
+ }
+
+ error(Ebadarg);
+}
+
+static long
+vgawrite(Chan* c, void* a, long n, vlong off)
+{
+ char *p;
+ ulong offset = off;
+
+ switch((ulong)c->qid.path){
+
+ case Qdir:
+ error(Eperm);
+
+ case Qvgactl:
+ if(offset || n >= READSTR)
+ error(Ebadarg);
+ p = malloc(READSTR);
+ if(waserror()){
+ free(p);
+ nexterror();
+ }
+ memmove(p, a, n);
+ p[n] = 0;
+ vgactl(p);
+ poperror();
+ free(p);
+ return n;
+
+ default:
+ error(Egreg);
+ break;
+ }
+
+ return 0;
+}
+
+Dev vgadevtab = {
+ 'v',
+ "vga",
+
+ vgareset,
+ devinit,
+ devshutdown,
+ vgaattach,
+ vgawalk,
+ vgastat,
+ vgaopen,
+ devcreate,
+ vgaclose,
+ vgaread,
+ devbread,
+ vgawrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/alphapc/dma.c b/sys/src/9/alphapc/dma.c
new file mode 100755
index 000000000..6382c1beb
--- /dev/null
+++ b/sys/src/9/alphapc/dma.c
@@ -0,0 +1,331 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#include "io.h"
+
+typedef struct DMAport DMAport;
+typedef struct DMA DMA;
+typedef struct DMAxfer DMAxfer;
+
+/*
+ * state of a dma transfer
+ */
+struct DMAxfer
+{
+ ulong bpa; /* bounce buffer physical address */
+ void* bva; /* bounce buffer virtual address */
+ int blen; /* bounce buffer length */
+ void* va; /* virtual address destination/src */
+ long len; /* bytes to be transferred */
+ int isread;
+};
+
+/*
+ * the dma controllers. the first half of this structure specifies
+ * the I/O ports used by the DMA controllers.
+ */
+struct DMAport
+{
+ uchar addr[4]; /* current address (4 channels) */
+ uchar count[4]; /* current count (4 channels) */
+ uchar page[4]; /* page registers (4 channels) */
+ uchar cmd; /* command status register */
+ uchar req; /* request registers */
+ uchar sbm; /* single bit mask register */
+ uchar mode; /* mode register */
+ uchar cbp; /* clear byte pointer */
+ uchar mc; /* master clear */
+ uchar cmask; /* clear mask register */
+ uchar wam; /* write all mask register bit */
+};
+
+struct DMA
+{
+ DMAport;
+ int shift;
+ Lock;
+ DMAxfer x[4];
+};
+
+DMA dma[2] = {
+ { 0x00, 0x02, 0x04, 0x06,
+ 0x01, 0x03, 0x05, 0x07,
+ 0x87, 0x83, 0x81, 0x82,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0 },
+
+ { 0xc0, 0xc4, 0xc8, 0xcc,
+ 0xc2, 0xc6, 0xca, 0xce,
+ 0x8f, 0x8b, 0x89, 0x8a,
+ 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
+ 1 },
+};
+
+extern int i8237dma;
+static void* i8237bva[2];
+static int i8237used;
+
+/*
+ * DMA must be in the first 16MB. This gets called early by the
+ * initialisation routines of any devices which require DMA to ensure
+ * the allocated bounce buffers are below the 16MB limit.
+ */
+void
+_i8237alloc(void)
+{
+ void* bva;
+
+ if(i8237dma <= 0)
+ return;
+ if(i8237dma > 2)
+ i8237dma = 2;
+
+ bva = xspanalloc(64*1024*i8237dma, BY2PG, 64*1024);
+ if(bva == nil || PADDR(bva)+64*1024*i8237dma > 16*MB){
+ /*
+ * This will panic with the current
+ * implementation of xspanalloc().
+ if(bva != nil)
+ xfree(bva);
+ */
+ return;
+ }
+
+ i8237bva[0] = bva;
+ if(i8237dma == 2)
+ i8237bva[1] = ((uchar*)i8237bva[0])+64*1024;
+}
+
+static void
+dmastatus(DMA *dp, int chan, char c)
+{
+ int a, l, s;
+
+ ilock(dp);
+ outb(dp->cbp, 0);
+ a = inb(dp->addr[chan]);
+ a |= inb(dp->addr[chan])<<8;
+ a |= inb(dp->page[chan])<<16;
+ a |= inb(0x400|dp->page[chan])<<24;
+ outb(dp->cbp, 0);
+ l = inb(dp->count[chan]);
+ l |= inb(dp->count[chan])<<8;
+ s = inb(dp->cmd);
+ iunlock(dp);
+ print("%c: addr %uX len %uX stat %uX\n", c, a, l, s);
+}
+
+int
+dmainit(int chan, int maxtransfer)
+{
+ DMA *dp;
+ DMAxfer *xp;
+ static int once;
+
+ if(once == 0){
+ if(ioalloc(0x00, 0x10, 0, "dma") < 0
+ || ioalloc(0x80, 0x10, 0, "dma") < 0
+ || ioalloc(0xd0, 0x10, 0, "dma") < 0)
+ panic("dmainit");
+ outb(dma[0].mc, 0);
+ outb(dma[1].mc, 0);
+ outb(dma[0].cmask, 0);
+ outb(dma[1].cmask, 0);
+ outb(dma[1].mode, 0xC0);
+ once = 1;
+ }
+
+ if(maxtransfer > 64*1024)
+ maxtransfer = 64*1024;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+ xp = &dp->x[chan];
+ if(xp->bva != nil){
+ if(xp->blen < maxtransfer)
+ return 1;
+ return 0;
+ }
+//dmastatus(dp, chan, 'I');
+
+ if(i8237used >= i8237dma || i8237bva[i8237used] == nil){
+ print("no i8237 DMA bounce buffer < 16MB\n");
+ return 1;
+ }
+ xp->bva = i8237bva[i8237used++];
+ xp->bpa = PADDR(xp->bva);
+ xp->blen = maxtransfer;
+ xp->len = 0;
+ xp->isread = 0;
+
+ return 0;
+}
+
+void
+xdmastatus(int chan)
+{
+ DMA *dp;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+
+ dmastatus(dp, chan, 'X');
+}
+
+/*
+ * setup a dma transfer. if the destination is not in kernel
+ * memory, allocate a page for the transfer.
+ *
+ * we assume BIOS has set up the command register before we
+ * are booted.
+ *
+ * return the updated transfer length (we can't transfer across 64k
+ * boundaries)
+ */
+long
+dmasetup(int chan, void *va, long len, int isread)
+{
+ DMA *dp;
+ ulong pa;
+ uchar mode;
+ DMAxfer *xp;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+ xp = &dp->x[chan];
+//print("va%lux+", va);
+#define tryPCI
+#ifndef PCIWADDR
+#define PCIWADDR(va) PADDR(va)
+#endif /* PCIWADDR */
+#ifdef notdef
+
+ /*
+ * 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(xp->bva == nil)
+ return -1;
+ if(len > xp->blen)
+ len = xp->blen;
+ if(!isread)
+ memmove(xp->bva, va, len);
+ xp->va = va;
+ xp->len = len;
+ xp->isread = isread;
+ pa = xp->bpa;
+ }
+ else
+ xp->len = 0;
+#endif /* notdef */
+#ifdef tryISA
+ pa = ISAWADDR(va);
+#endif /* tryISA */
+#ifdef tryPCI
+ pa = PCIWADDR(va);
+ if((((ulong)va)&0xF0000000) != KZERO){
+ if(xp->bva == nil)
+ return -1;
+ if(len > xp->blen)
+ len = xp->blen;
+ if(!isread)
+ memmove(xp->bva, va, len);
+ xp->va = va;
+ xp->len = len;
+ xp->isread = isread;
+ pa = PCIWADDR(xp->bva);
+ }
+ else
+ xp->len = 0;
+#endif /* tryPCI */
+
+ /*
+ * this setup must be atomic
+ */
+ mode = (isread ? 0x44 : 0x48) | chan;
+ ilock(dp);
+ outb(dp->cbp, 0); /* set count & address to their first byte */
+ outb(dp->mode, mode); /* single mode dma (give CPU a chance at mem) */
+ outb(dp->addr[chan], pa>>dp->shift); /* set address */
+ outb(dp->addr[chan], pa>>(8+dp->shift));
+ outb(dp->page[chan], pa>>16);
+#ifdef tryPCI
+ outb(0x400|dp->page[chan], pa>>24);
+#endif /* tryPCI */
+ outb(dp->cbp, 0); /* set count & address to their first byte */
+ outb(dp->count[chan], (len>>dp->shift)-1); /* set count */
+ outb(dp->count[chan], ((len>>dp->shift)-1)>>8);
+ outb(dp->sbm, chan); /* enable the channel */
+ iunlock(dp);
+//dmastatus(dp, chan, 'S');
+
+ return len;
+}
+
+int
+dmadone(int chan)
+{
+ DMA *dp;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+
+ return inb(dp->cmd) & (1<<chan);
+}
+
+/*
+ * this must be called after a dma has been completed.
+ *
+ * if a page has been allocated for the dma,
+ * copy the data into the actual destination
+ * and free the page.
+ */
+void
+dmaend(int chan)
+{
+ DMA *dp;
+ DMAxfer *xp;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+
+//dmastatus(dp, chan, 'E');
+ /*
+ * disable the channel
+ */
+ ilock(dp);
+ outb(dp->sbm, 4|chan);
+ iunlock(dp);
+
+ xp = &dp->x[chan];
+ if(xp->len == 0 || !xp->isread)
+ return;
+
+ /*
+ * copy out of temporary page
+ */
+ memmove(xp->va, xp->bva, xp->len);
+ xp->len = 0;
+}
+
+/*
+int
+dmacount(int chan)
+{
+ int retval;
+ DMA *dp;
+
+ dp = &dma[(chan>>2)&1];
+ outb(dp->cbp, 0);
+ retval = inb(dp->count[chan]);
+ retval |= inb(dp->count[chan]) << 8;
+ return((retval<<dp->shift)+1);
+}
+ */
diff --git a/sys/src/9/alphapc/etherif.h b/sys/src/9/alphapc/etherif.h
new file mode 100755
index 000000000..c044e75ef
--- /dev/null
+++ b/sys/src/9/alphapc/etherif.h
@@ -0,0 +1,41 @@
+enum {
+ MaxEther = 24,
+ Ntypes = 8,
+};
+
+typedef struct Ether Ether;
+struct Ether {
+ ISAConf; /* hardware info */
+
+ int ctlrno;
+ int tbdf; /* type+busno+devno+funcno */
+ int minmtu;
+ int maxmtu;
+ uchar ea[Eaddrlen];
+
+ void (*attach)(Ether*); /* filled in by reset routine */
+ void (*detach)(Ether*); /* NEW, from ../pc */
+ void (*transmit)(Ether*);
+ void (*interrupt)(Ureg*, void*);
+ long (*ifstat)(Ether*, void*, long, ulong);
+ long (*ctl)(Ether*, void*, long); /* custom ctl messages */
+/* START NEW, from ../pc */
+ void (*power)(Ether*, int); /* power on/off */
+ void (*shutdown)(Ether*); /* shutdown hardware before reboot */
+/* END NEW */
+ void *ctlr;
+
+ Queue* oq;
+
+ Netif;
+};
+
+extern Block* etheriq(Ether*, Block*, int);
+extern void addethercard(char*, int(*)(Ether*));
+extern ulong ethercrc(uchar*, int);
+extern int parseether(uchar*, char*);
+
+#define NEXT(x, l) (((x)+1)%(l))
+#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
diff --git a/sys/src/9/alphapc/faultalpha.c b/sys/src/9/alphapc/faultalpha.c
new file mode 100755
index 000000000..c2d646905
--- /dev/null
+++ b/sys/src/9/alphapc/faultalpha.c
@@ -0,0 +1,62 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+/*
+ * find out fault address and type of access.
+ * Call common fault handler.
+ */
+void
+faultalpha(Ureg *ur)
+{
+ ulong addr, cause;
+ int read, user;
+ char buf[ERRMAX];
+ uvlong x;
+
+ x = ur->a0&0xffffffff80000000LL;
+ if (x != 0LL && x != 0xffffffff80000000LL)
+ iprint("faultalpha bad addr %llux pc %llux\n", ur->a0, ur->pc);
+
+ addr = (ulong)ur->a0;
+ cause = (ulong)ur->a2;
+ addr &= ~(BY2PG-1);
+ read = (cause !=1);
+ user = (ulong)ur->status&UMODE;
+
+/* print("fault %s pc=0x%lux addr=0x%lux 0x%lux\n",
+ read? (cause != 0) ? "ifetch" : "read" : "write", (ulong)ur->pc, addr, (ulong)ur->a1); /**/
+
+ if(fault(addr, read) == 0)
+ return;
+
+ if(user){
+ sprint(buf, "sys: trap: fault %s addr=0x%lux",
+ read? (cause != 0) ? "ifetch" : "read" : "write", (ulong)ur->a0);
+ postnote(up, 1, buf, NDebug);
+ return;
+ }
+
+ iprint("kernel %s vaddr=0x%lux\n", read? (cause != 0) ? "ifetch" : "read" : "write", (ulong)ur->a0);
+ if(0)
+ mmudump();
+ dumpregs(ur);
+ _dumpstack(ur);
+ exit(1);
+}
+
+/*
+ * called in sysfile.c
+ */
+void
+evenaddr(ulong addr)
+{
+ if(addr & 3){
+ postnote(up, 1, "sys: odd address", NDebug);
+ error(Ebadarg);
+ }
+}
diff --git a/sys/src/9/alphapc/fdc37c93x.c b/sys/src/9/alphapc/fdc37c93x.c
new file mode 100755
index 000000000..ce2a63963
--- /dev/null
+++ b/sys/src/9/alphapc/fdc37c93x.c
@@ -0,0 +1,66 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ * SMC FDC37C93x Plug and Play Compatible Ultra I/O Controller.
+ */
+enum { /* I/O Ports */
+ Config = 0x370, /* could also be 0x3F0 */
+
+ Index = 0,
+ Data = 1,
+};
+
+static int fddregs[] = {
+ 0x30,
+ 0x60, 0x61,
+ 0x70,
+ 0x74,
+ 0xF0,
+ 0xF1,
+ 0xF2,
+ 0xF4,
+ 0xF5,
+ 0,
+};
+
+#define OUTB(p, d) outb(p, d); microdelay(10);
+
+void
+fdc37c93xdump(void)
+{
+ int config, i, x;
+
+ config = Config;
+
+ OUTB(config, 0x55);
+ OUTB(config, 0x55);
+
+ OUTB(config+Index, 0x20);
+ x = inb(config+Data);
+ print("fdc37c93x: Device ID 0x%2.2uX\n", x);
+ OUTB(config+Index, 0x22);
+ x = inb(config+Data);
+ print("fdc37c93x: Power/Control 0x%2.2uX\n", x);
+
+ OUTB(config+Index, 0x07);
+ OUTB(config+Data, 0);
+ for(i = 0; fddregs[i]; i++){
+ OUTB(config+Index, fddregs[i]);
+ x = inb(config+Data);
+ print("FDD%2.2uX: 0x%2.2uX\n", fddregs[i], x);
+ }
+
+ OUTB(config+Index, 0x70);
+ OUTB(config+Data, 0x06);
+ OUTB(config+Index, 0x74);
+ OUTB(config+Data, 0x02);
+ OUTB(config+Index, 0x30);
+ OUTB(config+Data, 0x01);
+
+ OUTB(config, 0xAA);
+}
diff --git a/sys/src/9/alphapc/floppy.h b/sys/src/9/alphapc/floppy.h
new file mode 100755
index 000000000..08dc1dd67
--- /dev/null
+++ b/sys/src/9/alphapc/floppy.h
@@ -0,0 +1,181 @@
+typedef struct FController FController;
+typedef struct FDrive FDrive;
+typedef struct FType FType;
+
+static void floppyintr(Ureg*);
+static int floppyon(FDrive*);
+static void floppyoff(FDrive*);
+static void floppysetdef(FDrive*);
+
+/*
+ * a floppy drive
+ */
+struct FDrive
+{
+ FType *t; /* floppy type */
+ int dt; /* drive type */
+ int dev;
+
+ ulong lasttouched; /* time last touched */
+ int cyl; /* current arm position */
+ int confused; /* needs to be recalibrated */
+ int vers;
+ int maxtries; /* max read attempts before Eio */
+
+ int tcyl; /* target cylinder */
+ int thead; /* target head */
+ int tsec; /* target sector */
+ long len; /* size of xfer */
+
+ uchar *cache; /* track cache */
+ int ccyl;
+ int chead;
+
+ Rendez r; /* waiting here for motor to spin up */
+};
+
+/*
+ * controller for 4 floppys
+ */
+struct FController
+{
+ QLock; /* exclusive access to the contoller */
+
+ int ndrive;
+ FDrive *d; /* the floppy drives */
+ FDrive *selected;
+ int rate; /* current rate selected */
+ uchar cmd[14]; /* command */
+ int ncmd; /* # command bytes */
+ uchar stat[14]; /* command status */
+ int nstat; /* # status bytes */
+ int confused; /* controler needs to be reset */
+ Rendez r; /* wait here for command termination */
+ int motor; /* bit mask of spinning disks */
+ Rendez kr; /* for motor watcher */
+};
+
+/*
+ * floppy types (all MFM encoding)
+ */
+struct FType
+{
+ char *name;
+ int dt; /* compatible drive type */
+ int bytes; /* bytes/sector */
+ int sectors; /* sectors/track */
+ int heads; /* number of heads */
+ int steps; /* steps per cylinder */
+ int tracks; /* tracks/disk */
+ int gpl; /* intersector gap length for read/write */
+ int fgpl; /* intersector gap length for format */
+ int rate; /* rate code */
+
+ /*
+ * these depend on previous entries and are set filled in
+ * by floppyinit
+ */
+ int bcode; /* coded version of bytes for the controller */
+ long cap; /* drive capacity in bytes */
+ long tsize; /* track size in bytes */
+};
+/* bits in the registers */
+enum
+{
+ /* status registers a & b */
+ Psra= 0x3f0,
+ Psrb= 0x3f1,
+
+ /* digital output register */
+ Pdor= 0x3f2,
+ Fintena= 0x8, /* enable floppy interrupt */
+ Fena= 0x4, /* 0 == reset controller */
+
+ /* main status register */
+ Pmsr= 0x3f4,
+ Fready= 0x80, /* ready to be touched */
+ Ffrom= 0x40, /* data from controller */
+ Ffloppybusy= 0x10, /* operation not over */
+
+ /* data register */
+ Pfdata= 0x3f5,
+ Frecal= 0x07, /* recalibrate cmd */
+ Fseek= 0x0f, /* seek cmd */
+ Fsense= 0x08, /* sense cmd */
+ Fread= 0x66, /* read cmd */
+ Freadid= 0x4a, /* read track id */
+ Fspec= 0x03, /* set hold times */
+ Fwrite= 0x45, /* write cmd */
+ Fformat= 0x4d, /* format cmd */
+ Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */
+ Fdumpreg= 0x0e, /* dump internal registers */
+
+ /* digital input register */
+ Pdir= 0x3F7, /* disk changed port (read only) */
+ Pdsr= 0x3F7, /* data rate select port (write only) */
+ Fchange= 0x80, /* disk has changed */
+
+ /* status 0 byte */
+ Drivemask= 3<<0,
+ Seekend= 1<<5,
+ Codemask= (3<<6)|(3<<3),
+ Cmdexec= 1<<6,
+
+ /* status 1 byte */
+ Overrun= 0x10,
+};
+
+
+static void
+pcfloppyintr(Ureg *ur, void *a)
+{
+ USED(a);
+
+ floppyintr(ur);
+}
+
+void
+floppysetup0(FController *fl)
+{
+ fl->ndrive = 0;
+ if(ioalloc(Psra, 6, 0, "floppy") < 0)
+ return;
+ if(ioalloc(Pdir, 1, 0, "floppy") < 0){
+ iofree(Psra);
+ return;
+ }
+ fl->ndrive = 1;
+}
+
+void
+floppysetup1(FController *fl)
+{
+ if(fl->ndrive > 0){
+ fl->d[0].dt = 4;
+ floppysetdef(&fl->d[0]);
+ }
+ if(fl->ndrive > 1){
+ fl->d[1].dt = 4;
+ floppysetdef(&fl->d[1]);
+ }
+
+ intrenable(IrqFLOPPY, pcfloppyintr, fl, BUSUNKNOWN, "floppy");
+}
+
+/*
+ * eject disk
+ */
+void
+floppyeject(FDrive *dp)
+{
+ floppyon(dp);
+ dp->vers++;
+ floppyoff(dp);
+}
+
+int
+floppyexec(char *a, long b, int c)
+{
+ USED(a, b, c);
+ return b;
+}
diff --git a/sys/src/9/alphapc/fns.h b/sys/src/9/alphapc/fns.h
new file mode 100755
index 000000000..88b0f3a68
--- /dev/null
+++ b/sys/src/9/alphapc/fns.h
@@ -0,0 +1,128 @@
+#include "../port/portfns.h"
+
+Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong));
+void archinit(void);
+void arginit(void);
+void arith(void);
+ulong cankaddr(ulong);
+void clock(Ureg*);
+void clockinit(void);
+void clockintrsched(void);
+#define coherence mb
+int cistrcmp(char*, char*);
+int cistrncmp(char*, char*, int);
+int cmpswap(long*, long, long);
+void cpuidprint(void);
+void cserve(ulong, ulong);
+#define cycles(x) do{}while(0)
+void timeradd(Timer *);
+void timerdel(Timer *);
+int dmacount(int);
+int dmadone(int);
+void dmaend(int);
+int dmainit(int, int);
+long dmasetup(int, void*, long, int);
+void _dumpstack(Ureg *);
+void evenaddr(ulong);
+void fataltrap(Ureg *, char *);
+void fault0(void);
+void faultalpha(Ureg*);
+ulong fcr31(void);
+void firmware(void);
+void fpenab(int);
+void fptrap(Ureg*);
+int getcfields(char*, char**, int, char*);
+char *getconf(char*);
+int havetimer(void);
+int i8042auxcmd(int);
+void i8042auxenable(void (*)(int, int));
+void i8042reset(void);
+void i8250console(void);
+void i8250mouse(char*, int(*)(Queue*,int), int);
+void i8250setmouseputc(char*, int (*)(Queue*, int));
+void i8259init(void);
+int i8259enable(int, int, Vctl*);
+#define idlehands() /* nothing to do in the runproc */
+void icflush(void);
+void illegal0(void);
+void intr0(void);
+void intrenable(int, void (*)(Ureg*, void*), void*, int, char*);
+int intrdisable(int, void (*)(Ureg *, void *), void*, int, char*);
+int ioalloc(int, int, int, char*);
+void iofree(int);
+void ioinit(void);
+int iounused(int, int);
+int irqallocread(char*, long, vlong);
+int isaconfig(char*, int, ISAConf*);
+void kbdinit(void);
+#define kexit(a)
+#define kmapinval()
+void *kmapv(uvlong, int);
+int kprint(char*, ...);
+void links(void);
+void mb(void);
+void memholes(void);
+ulong meminit(void);
+void mmudump(void);
+void mmuinit(void);
+void mmupark(void);
+#define mtrr(a, b, c)
+ulong pcibarsize(Pcidev*, int);
+int pcicfgr8(Pcidev*, int);
+int pcicfgr16(Pcidev*, int);
+int pcicfgr32(Pcidev*, int);
+void pcicfgw8(Pcidev*, int, int);
+void pcicfgw16(Pcidev*, int, int);
+void pcicfgw32(Pcidev*, int, int);
+void pciclrbme(Pcidev*);
+void pcihinv(Pcidev*);
+Pcidev* pcimatch(Pcidev*, int, int);
+Pcidev* pcimatchtbdf(int);
+void pcireset(void);
+void pcisetbme(Pcidev*);
+int pcmspecial(char*, ISAConf*);
+int (*_pcmspecial)(char *, ISAConf *);
+void pcmspecialclose(int);
+void (*_pcmspecialclose)(int);
+void prflush(void);
+void printinit(void);
+#define procrestore(p)
+void procsave(Proc*);
+void procsetup(Proc*);
+void restfpregs(FPsave*);
+uvlong rpcc(uvlong*);
+void screeninit(void);
+void (*screenputs)(char*, int);
+void setpcb(PCB *);
+PCB *swpctx(PCB *);
+void syscall0(void);
+int tas(ulong*);
+void tlbflush(int, ulong);
+void touser(void*);
+void trapinit(void);
+void unaligned(void);
+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))
+#define PADDR(a) ((ulong)(a)&~KZERO)
+
+#define inb(p) (arch->_inb)(p)
+#define ins(p) (arch->_ins)(p)
+#define inl(p) (arch->_inl)(p)
+#define outb(p, x) (arch->_outb)((p), (x))
+#define outs(p, x) (arch->_outs)((p), (x))
+#define outl(p, x) (arch->_outl)((p), (x))
+
+#define insb(p, buf, len) (arch->_insb)((p), (buf), (len))
+#define inss(p, buf, len) (arch->_inss)((p), (buf), (len))
+#define insl(p, buf, len) (arch->_insl)((p), (buf), (len))
+#define outsb(p, buf, len) (arch->_outsb)((p), (buf), (len))
+#define outss(p, buf, len) (arch->_outss)((p), (buf), (len))
+#define outsl(p, buf, len) (arch->_outsl)((p), (buf), (len))
diff --git a/sys/src/9/alphapc/fptrap.c b/sys/src/9/alphapc/fptrap.c
new file mode 100755
index 000000000..7b3c5a868
--- /dev/null
+++ b/sys/src/9/alphapc/fptrap.c
@@ -0,0 +1,46 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "ureg.h"
+#include "io.h"
+#include "../port/error.h"
+
+char *fpcause[] =
+{
+ "invalid operation",
+ "division by zero",
+ "overflow",
+ "underflow",
+ "inexact operation",
+ "integer overflow",
+};
+char *fpexcname(Ureg*, ulong, char*);
+
+void
+fptrap(Ureg *ur)
+{
+ char buf[ERRMAX];
+ int i;
+ ulong reason;
+
+ ur->pc &= ~2;
+ reason = (ulong)ur->a0;
+ for (i = 1; i < 6; i++)
+ if (reason & (1<<i)) {
+ sprint(buf, "fp: %s", fpcause[i-1]);
+ goto found;
+ }
+ sprint(buf, "fp: code 0x%lux", reason);
+
+found:
+ fataltrap(ur, buf);
+}
+
+char*
+fpexcname(Ureg *ur, ulong fcr31, char *buf)
+{
+ USED(ur, fcr31, buf);
+ return buf;
+}
diff --git a/sys/src/9/alphapc/i8259.c b/sys/src/9/alphapc/i8259.c
new file mode 100755
index 000000000..fe1f55708
--- /dev/null
+++ b/sys/src/9/alphapc/i8259.c
@@ -0,0 +1,152 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ * 8259 interrupt controllers
+ */
+enum
+{
+ Int0ctl= 0x20, /* control port (ICW1, OCW2, OCW3) */
+ Int0aux= 0x21, /* everything else (ICW2, ICW3, ICW4, OCW1) */
+ Int1ctl= 0xA0, /* control port */
+ Int1aux= 0xA1, /* everything else (ICW2, ICW3, ICW4, OCW1) */
+
+ Icw1= 0x10, /* select bit in ctl register */
+ Ocw2= 0x00,
+ Ocw3= 0x08,
+
+ EOI= 0x20, /* non-specific end of interrupt */
+
+ Elcr1= 0x4D0, /* Edge/Level Triggered Register */
+ Elcr2= 0x4D1,
+};
+
+static int int0mask; /* interrupts enabled for first 8259 */
+static int int1mask; /* interrupts enabled for second 8259 */
+
+int elcr; /* mask of level-triggered interrupts */
+
+void
+i8259init(void)
+{
+ int /*elcr1, */ x;
+
+ ioalloc(Int0ctl, 2, 0, "i8259.0");
+ ioalloc(Int1ctl, 2, 0, "i8259.1");
+ int0mask = 0xFF;
+ int1mask = 0xFF;
+
+ /*
+ * Set up the first 8259 interrupt processor.
+ * Make 8259 interrupts start at CPU vector Int0vec.
+ * Set the 8259 as master with edge triggered
+ * input with fully nested interrupts.
+ */
+ outb(Int0ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered,
+ ICW4 will be sent */
+ outb(Int0aux, VectorPIC); /* ICW2 - interrupt vector offset */
+ outb(Int0aux, 0x04); /* ICW3 - have slave on level 2 */
+ outb(Int0aux, 0x01); /* ICW4 - 8086 mode, not buffered */
+
+ /*
+ * Set up the second 8259 interrupt processor.
+ * Make 8259 interrupts start at CPU vector VectorPIC+8.
+ * Set the 8259 as slave with edge triggered
+ * input with fully nested interrupts.
+ */
+ outb(Int1ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered,
+ ICW4 will be sent */
+ outb(Int1aux, VectorPIC+8); /* ICW2 - interrupt vector offset */
+ outb(Int1aux, 0x02); /* ICW3 - I am a slave on level 2 */
+ outb(Int1aux, 0x01); /* ICW4 - 8086 mode, not buffered */
+ outb(Int1aux, int1mask);
+
+ /*
+ * pass #2 8259 interrupts to #1
+ */
+ int0mask &= ~0x04;
+ outb(Int0aux, int0mask);
+
+ /*
+ * Set Ocw3 to return the ISR when ctl read.
+ * After initialisation status read is set to IRR.
+ * Read IRR first to possibly deassert an outstanding
+ * interrupt.
+ */
+ x = inb(Int0ctl); USED(x);
+ outb(Int0ctl, Ocw3|0x03);
+ x = inb(Int1ctl); USED(x);
+ outb(Int1ctl, Ocw3|0x03);
+
+ /*
+ * Check for Edge/Level register.
+ * This check may not work for all chipsets.
+ */
+/* elcr1 = inb(Elcr1);
+ outb(Elcr1, 0);
+ if(inb(Elcr1) == 0){
+ outb(Elcr1, 0x20);
+ if(inb(Elcr1) == 0x20)
+ elcr = (inb(Elcr2)<<8)|elcr1;
+ }
+ outb(Elcr1, elcr1);
+ if(elcr)
+ iprint("ELCR: %4.4uX\n", elcr);
+/**/
+}
+
+int
+i8259isr(int v)
+{
+ int isr;
+
+ /*
+ * tell the 8259 that we're done with the
+ * highest level interrupt (interrupts are still
+ * off at this point)
+ */
+ isr = 0;
+ if(v >= VectorPIC && v <= MaxVectorPIC){
+ isr = inb(Int0ctl);
+ outb(Int0ctl, EOI);
+ if(v >= VectorPIC+8){
+ isr |= inb(Int1ctl)<<8;
+ outb(Int1ctl, EOI);
+ }
+ }
+
+ return isr & (1<<(v-VectorPIC));
+}
+
+int
+i8259enable(int v, int, Vctl* vctl)
+{
+ if(v > MaxIrqPIC){
+ print("i8259enable: vector %d out of range\n", v);
+ return -1;
+ }
+
+ /*
+ * enable corresponding interrupt in 8259
+ */
+ if(v < 8){
+ int0mask &= ~(1<<v);
+ outb(Int0aux, int0mask);
+ }
+ else{
+ int1mask &= ~(1<<(v-8));
+ outb(Int1aux, int1mask);
+ }
+
+ if(elcr & (1<<v))
+ vctl->eoi = i8259isr;
+ else
+ vctl->isr = i8259isr;
+ vctl->isintr = 1;
+
+ return v;
+}
diff --git a/sys/src/9/alphapc/initcode b/sys/src/9/alphapc/initcode
new file mode 100755
index 000000000..a43139dea
--- /dev/null
+++ b/sys/src/9/alphapc/initcode
@@ -0,0 +1,47 @@
+#include "/sys/src/libc/9syscall/sys.h"
+
+/*
+ * we pass in the argument of the exec parameters as 0(FP)
+ */
+
+TEXT main(SB),$16
+
+ MOVQ $setSB(SB), R29
+ MOVQ $boot(SB), R0
+ ADDQ $24, R30, R1 /* get a pointer to 0(FP) */
+ MOVL R0, 8(R30)
+ MOVL R1, 12(R30)
+ JSR exec(SB)
+
+ MOVQ $(1<<4), R0
+ MOVL R0, 8(R30)
+ MOVQ $RFORK, R0
+ CALL_PAL $0x83
+ MOVQ $RFORK, R0
+ CALL_PAL $0x83
+ MOVQ $RFORK, R0
+ CALL_PAL $0x83
+again:
+ ADDL $1, R1
+ MOVQ $0, R0 /* print r1 */
+ CALL_PAL $0x83
+ MOVQ $100000000, R2
+foo:
+ SUBQ $1, R2
+ BNE R2, foo
+ MOVQ $1000, R0
+ MOVL R0, 8(R30)
+ MOVQ $SLEEP, R0
+ CALL_PAL $0x83
+ JMP again
+
+TEXT exec(SB), $0
+ MOVQ $EXEC, R0
+ CALL_PAL $0x83
+ RET
+
+DATA boot+0(SB)/5,$"/boot"
+DATA boot+5(SB)/5,$"/boot"
+DATA bootv+0(SB)/4,$boot+6(SB)
+GLOBL boot+0(SB),$11
+GLOBL bootv+0(SB),$8
diff --git a/sys/src/9/alphapc/io.h b/sys/src/9/alphapc/io.h
new file mode 100755
index 000000000..b4c29d3b2
--- /dev/null
+++ b/sys/src/9/alphapc/io.h
@@ -0,0 +1,176 @@
+enum {
+ IrqCLOCK = 0,
+ IrqKBD = 1,
+ IrqUART1 = 3,
+ IrqUART0 = 4,
+ IrqPCMCIA = 5,
+ IrqFLOPPY = 6,
+ IrqLPT = 7,
+ IrqIRQ7 = 7,
+ IrqAUX = 12, /* PS/2 port */
+ IrqIRQ13 = 13, /* coprocessor on 386 */
+ IrqATA0 = 14,
+ IrqATA1 = 15,
+ MaxIrqPIC = 15,
+
+ VectorPIC = 64,
+ MaxVectorPIC = VectorPIC+MaxIrqPIC,
+ VectorPCI = 16, /* PCI bus (PLD) */
+};
+
+typedef struct Vctl {
+ Vctl* next; /* handlers on this vector */
+
+ char name[KNAMELEN]; /* of driver */
+ int isintr; /* interrupt or fault/trap */
+ int irq;
+ int tbdf;
+ int (*isr)(int); /* get isr bit for this irq */
+ int (*eoi)(int); /* eoi */
+
+ void (*f)(Ureg*, void*); /* handler to call */
+ void* a; /* argument to call it with */
+} Vctl;
+
+enum {
+ BusCBUS = 0, /* Corollary CBUS */
+ BusCBUSII, /* Corollary CBUS II */
+ BusEISA, /* Extended ISA */
+ BusFUTURE, /* IEEE Futurebus */
+ BusINTERN, /* Internal bus */
+ BusISA, /* Industry Standard Architecture */
+ BusMBI, /* Multibus I */
+ BusMBII, /* Multibus II */
+ BusMCA, /* Micro Channel Architecture */
+ BusMPI, /* MPI */
+ BusMPSA, /* MPSA */
+ BusNUBUS, /* Apple Macintosh NuBus */
+ BusPCI, /* Peripheral Component Interconnect */
+ BusPCMCIA, /* PC Memory Card International Association */
+ BusTC, /* DEC TurboChannel */
+ BusVL, /* VESA Local bus */
+ BusVME, /* VMEbus */
+ BusXPRESS, /* Express System Bus */
+};
+
+#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
+#define BUSFNO(tbdf) (((tbdf)>>8)&0x07)
+#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F)
+#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF)
+#define BUSTYPE(tbdf) ((tbdf)>>24)
+#define BUSDF(tbdf) ((tbdf)&0x000FF00)
+#define BUSBDF(tbdf) ((tbdf)&0x0FFFF00)
+#define BUSUNKNOWN (-1)
+
+enum {
+ MaxEISA = 16,
+ EISAconfig = 0xC80,
+};
+
+/*
+ * PCI support code.
+ */
+enum { /* type 0 and type 1 pre-defined header */
+ PciVID = 0x00, /* vendor ID */
+ PciDID = 0x02, /* device ID */
+ PciPCR = 0x04, /* command */
+ PciPSR = 0x06, /* status */
+ PciRID = 0x08, /* revision ID */
+ PciCCRp = 0x09, /* programming interface class code */
+ PciCCRu = 0x0A, /* sub-class code */
+ PciCCRb = 0x0B, /* base class code */
+ PciCLS = 0x0C, /* cache line size */
+ PciLTR = 0x0D, /* latency timer */
+ PciHDT = 0x0E, /* header type */
+ PciBST = 0x0F, /* BIST */
+
+ PciBAR0 = 0x10, /* base address */
+ PciBAR1 = 0x14,
+ PciROM = 0x30,
+
+ PciINTL = 0x3C, /* interrupt line */
+ PciINTP = 0x3D, /* interrupt pin */
+};
+
+enum { /* type 0 pre-defined header */
+ PciCIS = 0x28, /* cardbus CIS pointer */
+ PciSVID = 0x2C, /* subsystem vendor ID */
+ PciSID = 0x2E, /* cardbus CIS pointer */
+ PciEBAR0 = 0x30, /* xpansion ROM base address */
+ PciMGNT = 0x3E, /* burst period length */
+ PciMLT = 0x3F, /* maximum latency between bursts */
+};
+
+enum { /* type 1 pre-defined header */
+ PciPBN = 0x18, /* primary bus number */
+ PciSBN = 0x19, /* secondary bus number */
+ PciUBN = 0x1A, /* subordinate bus number */
+ PciSLTR = 0x1B, /* secondary latency timer */
+ PciIBR = 0x1C, /* I/O base */
+ PciILR = 0x1D, /* I/O limit */
+ PciSPSR = 0x1E, /* secondary status */
+ PciMBR = 0x20, /* memory base */
+ PciMLR = 0x22, /* memory limit */
+ PciPMBR = 0x24, /* prefetchable memory base */
+ PciPMLR = 0x26, /* prefetchable memory limit */
+ PciPUBR = 0x28, /* prefetchable base upper 32 bits */
+ PciPULR = 0x2C, /* prefetchable limit upper 32 bits */
+ PciIUBR = 0x30, /* I/O base upper 16 bits */
+ PciIULR = 0x32, /* I/O limit upper 16 bits */
+ PciEBAR1 = 0x28, /* expansion ROM base address */
+ PciBCR = 0x3E, /* bridge control register */
+};
+
+typedef struct Pcidev Pcidev;
+typedef struct Pcidev {
+ int tbdf; /* type+bus+device+function */
+ ushort vid; /* vendor ID */
+ ushort did; /* device ID */
+
+ ushort pcr;
+
+ uchar rid;
+ uchar ccrp;
+ uchar ccru;
+ uchar ccrb;
+ uchar cls;
+ uchar ltr;
+
+ struct {
+ ulong bar; /* base address */
+ int size;
+ } mem[6];
+
+ uchar intl; /* interrupt line */
+
+ Pcidev* list;
+ Pcidev* link; /* next device on this bno */
+
+ Pcidev* bridge; /* down a bus */
+ struct {
+ ulong bar;
+ int size;
+ } ioa, mema;
+
+ int pmrb; /* power management register block */
+};
+
+#define PCIWINDOW 0x40000000
+#define PCIWADDR(va) (PADDR(va)+PCIWINDOW)
+#define ISAWINDOW 0x00800000
+#define ISAWADDR(va) (PADDR(va)+ISAWINDOW)
+
+/*
+ * PCMCIA support code.
+ */
+/*
+ * Map between ISA memory space and PCMCIA card memory space.
+ */
+struct PCMmap {
+ ulong ca; /* card address */
+ ulong cea; /* card end address */
+ ulong isa; /* ISA address */
+ int len; /* length of the ISA area */
+ int attr; /* attribute memory */
+ int ref;
+};
diff --git a/sys/src/9/alphapc/kbd.c b/sys/src/9/alphapc/kbd.c
new file mode 100755
index 000000000..73ad3e1dd
--- /dev/null
+++ b/sys/src/9/alphapc/kbd.c
@@ -0,0 +1,456 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+enum {
+ Data= 0x60, /* data port */
+
+ Status= 0x64, /* status port */
+ Inready= 0x01, /* input character ready */
+ Outbusy= 0x02, /* output busy */
+ Sysflag= 0x04, /* system flag */
+ Cmddata= 0x08, /* cmd==0, data==1 */
+ Inhibit= 0x10, /* keyboard/mouse inhibited */
+ Minready= 0x20, /* mouse character ready */
+ Rtimeout= 0x40, /* general timeout */
+ Parity= 0x80,
+
+ Cmd= 0x64, /* command port (write only) */
+
+ Spec= 0x80,
+
+ PF= Spec|0x20, /* num pad function key */
+ View= Spec|0x00, /* view (shift window up) */
+ KF= 0xF000, /* function key (begin Unicode private space) */
+ Shift= Spec|0x60,
+ Break= Spec|0x61,
+ Ctrl= Spec|0x62,
+ Latin= Spec|0x63,
+ Caps= Spec|0x64,
+ Num= Spec|0x65,
+ Middle= Spec|0x66,
+ No= 0x00, /* peter */
+
+ Home= KF|13,
+ Up= KF|14,
+ Pgup= KF|15,
+ Print= KF|16,
+ Left= KF|17,
+ Right= KF|18,
+ End= '\r',
+ Down= View,
+ Pgdown= KF|19,
+ Ins= KF|20,
+ Scroll= KF|21,
+ Del= 0x7F,
+};
+
+/*
+ * The codes at 0x79 and 0x81 are produed by the PFU Happy Hacking keyboard.
+ * A 'standard' keyboard doesn't produce anything above 0x58.
+ */
+Rune kbtab[] =
+{
+[0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
+[0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
+[0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
+[0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
+[0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+[0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
+[0x30] 'b', 'n', 'm', ',', '.', '/', Shift, '*',
+[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',
+[0x48] '8', '9', '-', '4', '5', '6', '+', '1',
+[0x50] '2', '3', '0', '.', No, No, No, KF|11,
+[0x58] KF|12, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, View, No, Up, No, No, No, No,
+};
+
+Rune kbtabshift[] =
+{
+[0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
+[0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
+[0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
+[0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
+[0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
+[0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
+[0x30] 'B', 'N', 'M', '<', '>', '?', Shift, '*',
+[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',
+[0x48] '8', '9', '-', '4', '5', '6', '+', '1',
+[0x50] '2', '3', '0', '.', No, No, No, KF|11,
+[0x58] KF|12, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, Up, No, Up, No, No, No, No,
+};
+
+Rune kbtabesc1[] =
+{
+[0x00] No, No, No, No, No, No, No, No,
+[0x08] No, No, No, No, No, No, No, No,
+[0x10] No, No, No, No, No, No, No, No,
+[0x18] No, No, No, No, '\n', Ctrl, No, No,
+[0x20] No, No, No, No, No, No, No, No,
+[0x28] No, No, Shift, No, No, No, No, No,
+[0x30] No, No, No, No, No, '/', No, Print,
+[0x38] Latin, No, No, No, No, No, No, No,
+[0x40] No, No, No, No, No, No, Break, Home,
+[0x48] Up, Pgup, No, Left, No, Right, No, End,
+[0x50] Down, Pgdown, Ins, Del, No, No, No, No,
+[0x58] No, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, Up, No, No, No, No, No, No,
+};
+
+enum
+{
+ /* controller command byte */
+ Cscs1= (1<<6), /* scan code set 1 */
+ Cauxdis= (1<<5), /* mouse disable */
+ Ckbddis= (1<<4), /* kbd disable */
+ Csf= (1<<2), /* system flag */
+ Cauxint= (1<<1), /* mouse interrupt enable */
+ Ckbdint= (1<<0), /* kbd interrupt enable */
+};
+
+static Lock i8042lock;
+static uchar ccc;
+static void (*auxputc)(int, int);
+
+/*
+ * wait for output no longer busy
+ */
+static int
+outready(void)
+{
+ int tries;
+
+ for(tries = 0; (inb(Status) & Outbusy); tries++){
+ if(tries > 500)
+ return -1;
+ delay(2);
+ }
+ return 0;
+}
+
+/*
+ * wait for input
+ */
+static int
+inready(void)
+{
+ int tries;
+
+ for(tries = 0; !(inb(Status) & Inready); tries++){
+ if(tries > 500)
+ return -1;
+ delay(2);
+ }
+ return 0;
+}
+
+/*
+ * ask 8042 to reset the machine
+ */
+void
+i8042reset(void)
+{
+ ushort *s = KADDR(0x472);
+ int i, x;
+
+ *s = 0x1234; /* BIOS warm-boot flag */
+
+ /*
+ * newer reset the machine command
+ */
+ outready();
+ outb(Cmd, 0xFE);
+ outready();
+
+ /*
+ * Pulse it by hand (old somewhat reliable)
+ */
+ x = 0xDF;
+ for(i = 0; i < 5; i++){
+ x ^= 1;
+ outready();
+ outb(Cmd, 0xD1);
+ outready();
+ outb(Data, x); /* toggle reset */
+ delay(100);
+ }
+}
+
+int
+i8042auxcmd(int cmd)
+{
+ unsigned int c;
+ int tries;
+
+ c = 0;
+ tries = 0;
+
+ ilock(&i8042lock);
+ do{
+ if(tries++ > 2)
+ break;
+ if(outready() < 0)
+ break;
+ outb(Cmd, 0xD4);
+ if(outready() < 0)
+ break;
+ outb(Data, cmd);
+ if(outready() < 0)
+ break;
+ if(inready() < 0)
+ break;
+ c = inb(Data);
+ } while(c == 0xFE || c == 0);
+ iunlock(&i8042lock);
+
+ if(c != 0xFA){
+ print("i8042: %2.2ux returned to the %2.2ux command\n", c, cmd);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * keyboard interrupt
+ */
+static void
+i8042intr(Ureg*, void*)
+{
+ int s, c, i;
+ static int esc1, esc2;
+ static int alt, caps, ctl, num, shift;
+ static int collecting, nk;
+ static Rune kc[5];
+ int keyup;
+
+ /*
+ * get status
+ */
+ lock(&i8042lock);
+ s = inb(Status);
+ if(!(s&Inready)){
+ unlock(&i8042lock);
+ return;
+ }
+
+ /*
+ * get the character
+ */
+ c = inb(Data);
+ unlock(&i8042lock);
+
+ /*
+ * if it's the aux port...
+ */
+ if(s & Minready){
+ if(auxputc != nil)
+ auxputc(c, shift);
+ return;
+ }
+
+ /*
+ * e0's is the first of a 2 character sequence
+ */
+ if(c == 0xe0){
+ esc1 = 1;
+ return;
+ } else if(c == 0xe1){
+ esc2 = 2;
+ return;
+ }
+
+ keyup = c&0x80;
+ c &= 0x7f;
+ if(c > sizeof kbtab){
+ c |= keyup;
+ if(c != 0xFF) /* these come fairly often: CAPSLOCK U Y */
+ print("unknown key %ux\n", c);
+ return;
+ }
+
+ if(esc1){
+ c = kbtabesc1[c];
+ esc1 = 0;
+ } else if(esc2){
+ esc2--;
+ return;
+ } else if(shift)
+ c = kbtabshift[c];
+ else
+ c = kbtab[c];
+
+ if(caps && c<='z' && c>='a')
+ c += 'A' - 'a';
+
+ /*
+ * keyup only important for shifts
+ */
+ if(keyup){
+ switch(c){
+ case Latin:
+ alt = 0;
+ break;
+ case Shift:
+ shift = 0;
+ break;
+ case Ctrl:
+ ctl = 0;
+ break;
+ }
+ return;
+ }
+
+ /*
+ * normal character
+ */
+ if(!(c & (Spec|KF))){
+ if(ctl){
+ if(alt && c == Del)
+ exit(0);
+ c &= 0x1f;
+ }
+ if(!collecting){
+ kbdputc(kbdq, c);
+ return;
+ }
+ kc[nk++] = c;
+ c = latin1(kc, nk);
+ if(c < -1) /* need more keystrokes */
+ return;
+ if(c != -1) /* valid sequence */
+ kbdputc(kbdq, c);
+ else /* dump characters */
+ for(i=0; i<nk; i++)
+ kbdputc(kbdq, kc[i]);
+ nk = 0;
+ collecting = 0;
+ return;
+ } else {
+ switch(c){
+ case Caps:
+ caps ^= 1;
+ return;
+ case Num:
+ num ^= 1;
+ return;
+ case Shift:
+ shift = 1;
+ return;
+ case Latin:
+ alt = 1;
+ collecting = 1;
+ nk = 0;
+ return;
+ case Ctrl:
+ ctl = 1;
+ return;
+ }
+ }
+ kbdputc(kbdq, c);
+}
+
+void
+i8042auxenable(void (*putc)(int, int))
+{
+ char *err = "i8042: aux init failed\n";
+
+ /* enable kbd/aux xfers and interrupts */
+ ccc &= ~Cauxdis;
+ ccc |= Cauxint;
+
+ ilock(&i8042lock);
+ if(outready() < 0)
+ print(err);
+ outb(Cmd, 0x60); /* write control register */
+ if(outready() < 0)
+ print(err);
+ outb(Data, ccc);
+ if(outready() < 0)
+ print(err);
+ outb(Cmd, 0xA8); /* auxilliary device enable */
+ if(outready() < 0){
+ iunlock(&i8042lock);
+ return;
+ }
+ auxputc = putc;
+ intrenable(IrqAUX, i8042intr, 0, BUSUNKNOWN, "kbdaux");
+ iunlock(&i8042lock);
+}
+
+static void
+setscan(int code)
+{
+ char *err = "setscan: set scan code failed\n";
+
+ outb(Data, 0xF0);
+ if(inready() < 0 || inb(Data) != 0xFA || outready() < 0) {
+ print(err);
+ return;
+ }
+ outb(Data, code);
+ if(inready() < 0) {
+ print(err);
+ return;
+ }
+ inb(Data);
+ if(outready() < 0)
+ print(err);
+}
+
+void
+kbdinit(void)
+{
+ int c;
+
+ kbdq = qopen(4*1024, 0, 0, 0);
+ if(kbdq == nil)
+ panic("kbdinit");
+ qnoblock(kbdq, 1);
+
+ ioalloc(Data, 1, 0, "kbd");
+ ioalloc(Cmd, 1, 0, "kbd");
+
+ intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "kbd");
+
+ /* wait for a quiescent controller */
+ while((c = inb(Status)) & (Outbusy | Inready))
+ if(c & Inready)
+ inb(Data);
+
+ /* get current controller command byte */
+ outb(Cmd, 0x20);
+ if(inready() < 0){
+ print("kbdinit: can't read ccc\n");
+ ccc = 0;
+ } else
+ ccc = inb(Data);
+
+ /* enable kbd xfers and interrupts */
+ /* disable mouse */
+ ccc &= ~Ckbddis;
+ ccc |= Csf | Ckbdint | Cscs1;
+ if(outready() < 0)
+ print("kbd init failed\n");
+ outb(Cmd, 0x60);
+ if(outready() < 0)
+ print("kbd init failed\n");
+ outb(Data, ccc);
+ outready();
+ setscan(0x02);
+}
diff --git a/sys/src/9/alphapc/l.s b/sys/src/9/alphapc/l.s
new file mode 100755
index 000000000..a5c17c32b
--- /dev/null
+++ b/sys/src/9/alphapc/l.s
@@ -0,0 +1,457 @@
+#include "mem.h"
+#include "osf1pal.h"
+
+#define SP R30
+
+#define HI_IPL 6 /* use 7 to disable mchecks */
+
+TEXT _main(SB), $-8
+ MOVQ $setSB(SB), R29
+ MOVQ R29, R16
+ CALL_PAL $PALwrkgp
+ MOVQ $mach0(SB), R(MACH)
+ MOVQ $(BY2PG-8)(R(MACH)), R30
+ MOVQ R31, R(USER)
+ MOVQ R31, 0(R(MACH))
+
+ MOVQ $edata(SB), R1
+ MOVQ $end(SB), R2
+clrbss:
+ MOVQ R31, (R1)
+ ADDQ $8, R1
+ CMPUGT R1, R2, R3
+ BEQ R3, clrbss
+
+ MOVL R0, bootconf(SB) /* passed in from boot loader */
+
+_fpinit:
+ MOVQ $1, R16
+ CALL_PAL $PALwrfen
+
+ MOVQ initfpcr(SB), R1 /* MOVQ $0x2800800000000000, R1 */
+ MOVQ R1, (R30)
+ MOVT (R30), F1
+ MOVT F1, FPCR
+
+ MOVT $0.5, F28
+ ADDT F28, F28, F29
+ ADDT F29, F29, F30
+
+ MOVT F31, F1
+ MOVT F31, F2
+ MOVT F31, F3
+ MOVT F31, F4
+ MOVT F31, F5
+ MOVT F31, F6
+ MOVT F31, F7
+ MOVT F31, F8
+ MOVT F31, F9
+ MOVT F31, F10
+ MOVT F31, F11
+ MOVT F31, F12
+ MOVT F31, F13
+ MOVT F31, F14
+ MOVT F31, F15
+ MOVT F31, F16
+ MOVT F31, F17
+ MOVT F31, F18
+ MOVT F31, F19
+ MOVT F31, F20
+ MOVT F31, F21
+ MOVT F31, F22
+ MOVT F31, F23
+ MOVT F31, F24
+ MOVT F31, F25
+ MOVT F31, F26
+ MOVT F31, F27
+
+ JSR main(SB)
+ MOVQ $_divq(SB), R31 /* touch _divq etc.; doesn't need to execute */
+ MOVQ $_divl(SB), R31 /* touch _divl etc.; doesn't need to execute */
+ RET
+
+TEXT setpcb(SB), $-8
+ MOVQ R30, (R0)
+ AND $0x7FFFFFFF, R0, R16 /* make address physical */
+ CALL_PAL $PALswpctx
+ RET
+
+GLOBL mach0(SB), $(MAXMACH*BY2PG)
+GLOBL init_ptbr(SB), $8
+
+TEXT firmware(SB), $-8
+ CALL_PAL $PALhalt
+
+TEXT xxfirmware(SB), $-8
+ CALL_PAL $PALhalt
+
+TEXT splhi(SB), $0
+
+ MOVL R26, 4(R(MACH)) /* save PC in m->splpc */
+ MOVQ $HI_IPL, R16
+ CALL_PAL $PALswpipl
+ RET
+
+TEXT spllo(SB), $0
+ MOVQ R31, R16
+ CALL_PAL $PALswpipl
+ RET
+
+TEXT splx(SB), $0
+ MOVL R26, 4(R(MACH)) /* save PC in m->splpc */
+
+TEXT splxpc(SB), $0 /* for iunlock */
+ MOVQ R0, R16
+ CALL_PAL $PALswpipl
+ RET
+
+TEXT spldone(SB), $0
+ RET
+
+TEXT islo(SB), $0
+ CALL_PAL $PALrdps
+ AND $IPL, R0
+ XOR $HI_IPL, R0
+ RET
+
+TEXT mb(SB), $-8
+ MB
+ RET
+
+TEXT icflush(SB), $-8
+ CALL_PAL $PALimb
+ RET
+
+TEXT tlbflush(SB), $-8
+ MOVQ R0, R16
+ MOVL 4(FP), R17
+ CALL_PAL $PALtbi
+ RET
+
+TEXT swpctx(SB), $-8
+ MOVQ R0, R16
+ AND $0x7FFFFFFF, R16 /* make address physical */
+ CALL_PAL $PALswpctx
+ RET
+
+TEXT wrent(SB), $-8
+ MOVQ R0, R17
+ MOVL 4(FP), R16
+ CALL_PAL $PALwrent
+ RET
+
+TEXT wrvptptr(SB), $-8
+ MOVQ R0, R16
+ CALL_PAL $PALwrvptptr
+ RET
+
+TEXT cserve(SB), $-8
+ MOVQ R0, R16
+ MOVL 4(FP), R17
+ CALL_PAL $PALcserve
+ RET
+
+TEXT setlabel(SB), $-8
+ MOVL R30, 0(R0)
+ MOVL R26, 4(R0)
+ MOVQ $0, R0
+ RET
+
+TEXT gotolabel(SB), $-8
+ MOVL 0(R0), R30
+ MOVL 4(R0), R26
+ MOVQ $1, R0
+ RET
+
+TEXT tas(SB), $-8
+ MOVQ R0, R1 /* l */
+tas1:
+ MOVLL (R1), R0 /* l->key */
+ BNE R0, tas2
+ MOVQ $1, R2
+ MOVLC R2, (R1) /* l->key = 1 */
+ BEQ R2, tas1 /* write failed, try again? */
+tas2:
+ RET
+
+TEXT _xdec(SB), $-8
+ MOVQ R0, R1 /* p */
+dec1:
+ MOVLL (R1), R0 /* *p */
+ SUBL $1, R0
+ MOVQ R0, R2
+ MOVLC R2, (R1) /* --(*p) */
+ BEQ R2, dec1 /* write failed, retry */
+ RET
+
+TEXT _xinc(SB), $-8
+ MOVQ R0, R1 /* p */
+inc1:
+ MOVLL (R1), R0 /* *p */
+ ADDL $1, R0
+ MOVLC R0, (R1) /* (*p)++ */
+ BEQ R0, inc1 /* write failed, retry */
+ RET
+
+TEXT cmpswap(SB), $-8
+ MOVQ R0, R1 /* p */
+ MOVL old+4(FP), R2
+ MOVL new+8(FP), R3
+ MOVLL (R1), R0
+ CMPEQ R0, R2, R4
+ BEQ R4, fail /* if R0 != [sic] R2, goto fail */
+ MOVQ R3, R0
+ MOVLC R0, (R1)
+ RET
+fail:
+ MOVL $0, R0
+ RET
+
+TEXT fpenab(SB), $-8
+ MOVQ R0, R16
+ CALL_PAL $PALwrfen
+ RET
+
+TEXT rpcc(SB), $0
+ MOVL R0, R1
+ MOVL $0, R0
+ WORD $0x6000C000 /* RPCC R0 */
+ BEQ R1, _ret
+ MOVQ R0, (R1)
+_ret:
+ RET
+
+/*
+ * Exception handlers. The stack frame looks like this:
+ *
+ * R30+0: (unused) link reg storage (R26) (32 bits)
+ * R30+4: padding for alignment (32 bits)
+ * R30+8: trap()'s first arg storage (R0) (32 bits -- type Ureg*)
+ * R30+12: padding for alignment (32 bits)
+ * R30+16: first 31 fields of Ureg, saved here (31*64 bits)
+ * R30+264: other 6 fields of Ureg, saved by PALcode (6*64 bits)
+ * R30+312: previous value of KSP before trap
+ */
+
+TEXT arith(SB), $-8
+ SUBQ $(4*BY2WD+31*BY2V), R30
+ MOVQ R0, (4*BY2WD+4*BY2V)(R30)
+ MOVQ $1, R0
+ JMP trapcommon
+
+TEXT illegal0(SB), $-8
+ SUBQ $(4*BY2WD+31*BY2V), R30
+ MOVQ R0, (4*BY2WD+4*BY2V)(R30)
+ MOVQ $2, R0
+ JMP trapcommon
+
+TEXT fault0(SB), $-8
+ SUBQ $(4*BY2WD+31*BY2V), R30
+ MOVQ R0, (4*BY2WD+4*BY2V)(R30)
+ MOVQ $4, R0
+ JMP trapcommon
+
+TEXT unaligned(SB), $-8
+ SUBQ $(4*BY2WD+31*BY2V), R30
+ MOVQ R0, (4*BY2WD+4*BY2V)(R30)
+ MOVQ $6, R0
+ JMP trapcommon
+
+TEXT intr0(SB), $-8
+ SUBQ $(4*BY2WD+31*BY2V), R30
+ MOVQ R0, (4*BY2WD+4*BY2V)(R30)
+ MOVQ $3, R0
+
+trapcommon:
+ MOVQ R0, (4*BY2WD+0*BY2V)(R30)
+ MOVQ R16, (4*BY2WD+1*BY2V)(R30)
+ MOVQ R17, (4*BY2WD+2*BY2V)(R30)
+ MOVQ R18, (4*BY2WD+3*BY2V)(R30)
+
+ /* R0 already saved, (4*BY2WD+4*BY2V)(R30) */
+ MOVQ R1, (4*BY2WD+5*BY2V)(R30)
+ MOVQ R2, (4*BY2WD+6*BY2V)(R30)
+ MOVQ R3, (4*BY2WD+7*BY2V)(R30)
+ MOVQ R4, (4*BY2WD+8*BY2V)(R30)
+ MOVQ R5, (4*BY2WD+9*BY2V)(R30)
+ MOVQ R6, (4*BY2WD+10*BY2V)(R30)
+ MOVQ R7, (4*BY2WD+11*BY2V)(R30)
+ MOVQ R8, (4*BY2WD+12*BY2V)(R30)
+ MOVQ R9, (4*BY2WD+13*BY2V)(R30)
+ MOVQ R10, (4*BY2WD+14*BY2V)(R30)
+ MOVQ R11, (4*BY2WD+15*BY2V)(R30)
+ MOVQ R12, (4*BY2WD+16*BY2V)(R30)
+ MOVQ R13, (4*BY2WD+17*BY2V)(R30)
+ MOVQ R14, (4*BY2WD+18*BY2V)(R30)
+ MOVQ R15, (4*BY2WD+19*BY2V)(R30)
+ MOVQ R19, (4*BY2WD+20*BY2V)(R30)
+ MOVQ R20, (4*BY2WD+21*BY2V)(R30)
+ MOVQ R21, (4*BY2WD+22*BY2V)(R30)
+ MOVQ R22, (4*BY2WD+23*BY2V)(R30)
+ MOVQ R23, (4*BY2WD+24*BY2V)(R30)
+ MOVQ R24, (4*BY2WD+25*BY2V)(R30)
+ MOVQ R25, (4*BY2WD+26*BY2V)(R30)
+ MOVQ R26, (4*BY2WD+27*BY2V)(R30)
+ MOVQ R27, (4*BY2WD+28*BY2V)(R30)
+ MOVQ R28, (4*BY2WD+29*BY2V)(R30)
+
+ MOVQ $HI_IPL, R16
+ CALL_PAL $PALswpipl
+
+ CALL_PAL $PALrdusp
+ MOVQ R0, (4*BY2WD+30*BY2V)(R30) /* save USP */
+
+ MOVQ $mach0(SB), R(MACH)
+ MOVQ $(4*BY2WD)(R30), R0
+ JSR trap(SB)
+trapret:
+ MOVQ (4*BY2WD+30*BY2V)(R30), R16 /* USP */
+ CALL_PAL $PALwrusp /* ... */
+ MOVQ (4*BY2WD+4*BY2V)(R30), R0
+ MOVQ (4*BY2WD+5*BY2V)(R30), R1
+ MOVQ (4*BY2WD+6*BY2V)(R30), R2
+ MOVQ (4*BY2WD+7*BY2V)(R30), R3
+ MOVQ (4*BY2WD+8*BY2V)(R30), R4
+ MOVQ (4*BY2WD+9*BY2V)(R30), R5
+ MOVQ (4*BY2WD+10*BY2V)(R30), R6
+ MOVQ (4*BY2WD+11*BY2V)(R30), R7
+ MOVQ (4*BY2WD+12*BY2V)(R30), R8
+ MOVQ (4*BY2WD+13*BY2V)(R30), R9
+ MOVQ (4*BY2WD+14*BY2V)(R30), R10
+ MOVQ (4*BY2WD+15*BY2V)(R30), R11
+ MOVQ (4*BY2WD+16*BY2V)(R30), R12
+ MOVQ (4*BY2WD+17*BY2V)(R30), R13
+ MOVQ (4*BY2WD+18*BY2V)(R30), R14
+ MOVQ (4*BY2WD+19*BY2V)(R30), R15
+ MOVQ (4*BY2WD+20*BY2V)(R30), R19
+ MOVQ (4*BY2WD+21*BY2V)(R30), R20
+ MOVQ (4*BY2WD+22*BY2V)(R30), R21
+ MOVQ (4*BY2WD+23*BY2V)(R30), R22
+ MOVQ (4*BY2WD+24*BY2V)(R30), R23
+ MOVQ (4*BY2WD+25*BY2V)(R30), R24
+ MOVQ (4*BY2WD+26*BY2V)(R30), R25
+ MOVQ (4*BY2WD+27*BY2V)(R30), R26
+ MOVQ (4*BY2WD+28*BY2V)(R30), R27
+ MOVQ (4*BY2WD+29*BY2V)(R30), R28
+ /* USP already restored from (4*BY2WD+30*BY2V)(R30) */
+ ADDQ $(4*BY2WD+31*BY2V), R30
+ CALL_PAL $PALrti
+
+TEXT forkret(SB), $0
+ MOVQ R31, R0 /* Fake out system call return */
+ JMP systrapret
+
+TEXT syscall0(SB), $-8
+ SUBQ $(4*BY2WD+31*BY2V), R30
+ MOVQ R0, (4*BY2WD+4*BY2V)(R30) /* save scallnr in R0 */
+ MOVQ $HI_IPL, R16
+ CALL_PAL $PALswpipl
+ MOVQ $mach0(SB), R(MACH)
+ CALL_PAL $PALrdusp
+ MOVQ R0, (4*BY2WD+30*BY2V)(R30) /* save USP */
+ MOVQ R26, (4*BY2WD+27*BY2V)(R30) /* save last return address */
+ MOVQ $(4*BY2WD)(R30), R0 /* pass address of Ureg */
+ JSR syscall(SB)
+systrapret:
+ MOVQ (4*BY2WD+30*BY2V)(R30), R16 /* USP */
+ CALL_PAL $PALwrusp /* consider doing this in execregs... */
+ MOVQ (4*BY2WD+27*BY2V)(R30), R26 /* restore last return address */
+ ADDQ $(4*BY2WD+31*BY2V), R30
+ CALL_PAL $PALretsys
+
+/*
+ * Take first processor into user mode
+ * - argument is stack pointer to user
+ */
+
+TEXT touser(SB), $-8
+ MOVQ R0, R16
+ CALL_PAL $PALwrusp /* set USP to value passed */
+ SUBQ $(6*BY2V), R30 /* create frame for retsys */
+ MOVQ $(UTZERO+32), R26 /* header appears in text */
+ MOVQ R26, (1*BY2V)(R30) /* PC -- only reg that matters */
+ CALL_PAL $PALretsys
+
+TEXT rfnote(SB), $0
+ SUBL $(2*BY2WD), R0, SP
+ JMP trapret
+
+TEXT savefpregs(SB), $-8
+ MOVT F0, 0x00(R0)
+ MOVT F1, 0x08(R0)
+ MOVT F2, 0x10(R0)
+ MOVT F3, 0x18(R0)
+ MOVT F4, 0x20(R0)
+ MOVT F5, 0x28(R0)
+ MOVT F6, 0x30(R0)
+ MOVT F7, 0x38(R0)
+ MOVT F8, 0x40(R0)
+ MOVT F9, 0x48(R0)
+ MOVT F10, 0x50(R0)
+ MOVT F11, 0x58(R0)
+ MOVT F12, 0x60(R0)
+ MOVT F13, 0x68(R0)
+ MOVT F14, 0x70(R0)
+ MOVT F15, 0x78(R0)
+ MOVT F16, 0x80(R0)
+ MOVT F17, 0x88(R0)
+ MOVT F18, 0x90(R0)
+ MOVT F19, 0x98(R0)
+ MOVT F20, 0xA0(R0)
+ MOVT F21, 0xA8(R0)
+ MOVT F22, 0xB0(R0)
+ MOVT F23, 0xB8(R0)
+ MOVT F24, 0xC0(R0)
+ MOVT F25, 0xC8(R0)
+ MOVT F26, 0xD0(R0)
+ MOVT F27, 0xD8(R0)
+ MOVT F28, 0xE0(R0)
+ MOVT F29, 0xE8(R0)
+ MOVT F30, 0xF0(R0)
+ MOVT F31, 0xF8(R0)
+ MOVT FPCR, F0
+ MOVT F0, 0x100(R0)
+
+ MOVQ $0, R16
+ CALL_PAL $PALwrfen /* disable */
+ RET
+
+TEXT restfpregs(SB), $-8
+ MOVQ $1, R16
+ CALL_PAL $PALwrfen /* enable */
+
+ MOVT 0x100(R0), F0
+ MOVT F0, FPCR
+ MOVT 0x00(R0), F0
+ MOVT 0x08(R0), F1
+ MOVT 0x10(R0), F2
+ MOVT 0x18(R0), F3
+ MOVT 0x20(R0), F4
+ MOVT 0x28(R0), F5
+ MOVT 0x30(R0), F6
+ MOVT 0x38(R0), F7
+ MOVT 0x40(R0), F8
+ MOVT 0x48(R0), F9
+ MOVT 0x50(R0), F10
+ MOVT 0x58(R0), F11
+ MOVT 0x60(R0), F12
+ MOVT 0x68(R0), F13
+ MOVT 0x70(R0), F14
+ MOVT 0x78(R0), F15
+ MOVT 0x80(R0), F16
+ MOVT 0x88(R0), F17
+ MOVT 0x90(R0), F18
+ MOVT 0x98(R0), F19
+ MOVT 0xA0(R0), F20
+ MOVT 0xA8(R0), F21
+ MOVT 0xB0(R0), F22
+ MOVT 0xB8(R0), F23
+ MOVT 0xC0(R0), F24
+ MOVT 0xC8(R0), F25
+ MOVT 0xD0(R0), F26
+ MOVT 0xD8(R0), F27
+ MOVT 0xE0(R0), F28
+ MOVT 0xE8(R0), F29
+ MOVT 0xF0(R0), F30
+ MOVT 0xF8(R0), F31
+ RET
diff --git a/sys/src/9/alphapc/main.c b/sys/src/9/alphapc/main.c
new file mode 100755
index 000000000..c9f0dcc6e
--- /dev/null
+++ b/sys/src/9/alphapc/main.c
@@ -0,0 +1,703 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "init.h"
+#include "pool.h"
+#include "/sys/src/boot/alphapc/conf.h"
+#include "axp.h"
+
+char argbuf[128]; /* arguments passed to initcode and /boot */
+
+Hwrpb *hwrpb;
+Bootconf *bootconf;
+Conf conf;
+FPsave initfp;
+ /* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */
+uvlong initfpcr = (1LL<62)|(1LL<61)|(1LL<60)|(2LL<<58)|(1LL<48);
+
+char bootargs[BOOTARGSLEN];
+char *confname[MAXCONF];
+char *confval[MAXCONF];
+int nconf;
+
+static void
+options(void)
+{
+ long i, n;
+ char *cp, *line[MAXCONF], *p, *q;
+
+ cp = bootargs;
+ strncpy(cp, bootconf->bootargs, BOOTARGSLEN);
+ cp[BOOTARGSLEN-1] = 0;
+ /* can't print in this routine, see below in main() */
+
+ /*
+ * Strip out '\r', change '\t' -> ' '.
+ */
+ p = cp;
+ for(q = cp; *q; q++){
+ if(*q == '\r')
+ continue;
+ if(*q == '\t')
+ *q = ' ';
+ *p++ = *q;
+ }
+ *p = 0;
+
+ n = getfields(cp, line, MAXCONF, 1, "\n");
+ for(i = 0; i < n; i++){
+ if(*line[i] == '#')
+ continue;
+ cp = strchr(line[i], '=');
+ if(cp == nil)
+ continue;
+ *cp++ = '\0';
+ confname[nconf] = line[i];
+ confval[nconf] = cp;
+ nconf++;
+ }
+}
+
+/* debugging only */
+static void
+dumpopts(void)
+{
+ int i;
+
+ print("dumpopts: found /alpha/conf options at %#p\n",
+ bootconf->bootargs);
+ for(i = 0; i < nconf; i++)
+ print("dumpopts: read %s=%s\n", confname[i], confval[i]);
+}
+
+extern void (*i8237alloc)(void);
+
+void
+main(void)
+{
+ hwrpb = (Hwrpb*)0x10000000;
+ hwrpb = (Hwrpb*)(KZERO|hwrpb->phys);
+ arginit();
+ machinit();
+ options();
+ ioinit();
+ clockinit();
+ confinit();
+ archinit();
+ xinit();
+ memholes();
+ if(i8237alloc != nil)
+ i8237alloc();
+ mmuinit();
+ if(arch->coreinit)
+ arch->coreinit();
+ trapinit();
+ screeninit();
+ printinit();
+ /* it's now safe to print */
+ /* dumpopts(); /* DEBUG */
+ kbdinit();
+ i8250console();
+ quotefmtinstall();
+ print("\nPlan 9\n");
+
+ cpuidprint();
+ if(arch->corehello)
+ arch->corehello();
+
+ procinit0();
+ initseg();
+ timersinit();
+ links();
+ chandevreset();
+ pageinit();
+ swapinit();
+ savefpregs(&initfp);
+initfp.fpstatus = 0x68028000;
+ userinit();
+ schedinit();
+}
+
+/* cpu->state bits */
+enum {
+ Cpubootinprog = 1, /* boot in progress */
+ Cpucanrestart = 2, /* restart possible */
+ Cpuavail = 4, /* processor available */
+ Cpuexists = 8, /* processor present */
+ Cpuuserhalted = 0x10, /* user halted */
+ Cpuctxtokay = 0x20, /* context valid */
+ Cpupalokay = 0x40, /* PALcode valid */
+ Cpupalmemokay = 0x80, /* PALcode memory valid */
+ Cpupalloaded = 0x100, /* PALcode loaded */
+ Cpuhaltmask = 0xff0000, /* halt request mask */
+ Cpuhaltdflt = 0,
+ Cpuhaltsaveexit = 0x10000,
+ Cpuhaltcoldboot = 0x20000,
+ Cpuhaltwarmboot = 0x30000,
+ Cpuhaltstayhalted = 0x40000,
+ Cpumustbezero = 0xffffffffff000000ULL, /* 24:63 -- must be zero */
+};
+
+/*
+ * initialize a processor's mach structure. each processor does this
+ * for itself.
+ */
+void
+machinit(void)
+{
+ int n;
+ Hwcpu *cpu;
+
+ icflush();
+ n = m->machno;
+ memset(m, 0, sizeof(Mach));
+ m->machno = n;
+
+ active.exiting = 0;
+ active.machs = 1;
+
+ cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff + n*hwrpb->cpulen);
+ cpu->state &= ~Cpubootinprog;
+ if (0)
+ cpu->state |= Cpuhaltstayhalted;
+}
+
+void
+init0(void)
+{
+ int i;
+ char buf[2*KNAMELEN];
+
+ up->nerrlab = 0;
+
+ spllo();
+
+ /*
+ * These are o.k. because rootinit is null.
+ * Then early kproc's will have a root and dot.
+ */
+ up->slash = namec("#/", Atodir, 0, 0);
+ pathclose(up->slash->path);
+ up->slash->path = newpath("/");
+ up->dot = cclone(up->slash);
+
+ chandevinit();
+
+ if(!waserror()){
+ snprint(buf, sizeof(buf), "alpha %s alphapc", conffile);
+ ksetenv("terminal", buf, 0);
+ ksetenv("cputype", "alpha", 0);
+ if(cpuserver)
+ ksetenv("service", "cpu", 0);
+ else
+ ksetenv("service", "terminal", 0);
+ for(i = 0; i < nconf; i++)
+ if(confname[i]){
+ if(confname[i][0] != '*')
+ ksetenv(confname[i], confval[i], 0);
+ ksetenv(confname[i], confval[i], 1);
+ }
+ poperror();
+ }
+
+ kproc("alarm", alarmkproc, 0);
+ touser((uchar*)(USTKTOP - sizeof(argbuf)));
+}
+
+void
+userinit(void)
+{
+ Proc *p;
+ Segment *s;
+ KMap *k;
+ char **av;
+ Page *pg;
+
+ p = newproc();
+ p->pgrp = newpgrp();
+ p->egrp = smalloc(sizeof(Egrp));
+ p->egrp->ref = 1;
+ p->fgrp = dupfgrp(nil);
+ p->rgrp = newrgrp();
+ p->procmode = 0640;
+
+ kstrdup(&eve, "");
+ kstrdup(&p->text, "*init*");
+ kstrdup(&p->user, eve);
+
+ procsetup(p);
+
+ /*
+ * Kernel Stack
+ */
+ p->sched.pc = (ulong)init0;
+ p->sched.sp = (ulong)p->kstack+KSTACK-MAXSYSARG*BY2WD;
+ /*
+ * User Stack, pass input arguments to boot process
+ */
+ s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
+ p->seg[SSEG] = s;
+ pg = newpage(1, 0, USTKTOP-BY2PG);
+ segpage(s, pg);
+ k = kmap(pg);
+ for(av = (char**)argbuf; *av; av++)
+ *av += (USTKTOP - sizeof(argbuf)) - (ulong)argbuf;
+
+ memmove((uchar*)VA(k) + BY2PG - sizeof(argbuf), argbuf, sizeof argbuf);
+ kunmap(k);
+
+ /*
+ * Text
+ */
+ s = newseg(SG_TEXT, UTZERO, 1);
+ s->flushme++;
+ p->seg[TSEG] = s;
+ pg = newpage(1, 0, UTZERO);
+ memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
+ segpage(s, pg);
+ k = kmap(s->map[0]->pages[0]);
+ memmove((uchar*)VA(k), initcode, sizeof initcode);
+ kunmap(k);
+
+ ready(p);
+}
+
+void
+procsetup(Proc *p)
+{
+ p->fpstate = FPinit;
+ fpenab(0);
+}
+
+void
+procsave(Proc *p)
+{
+ if(p->fpstate == FPactive){
+ if(p->state == Moribund)
+ fpenab(0);
+ else
+ savefpregs(&up->fpsave);
+ p->fpstate = FPinactive;
+ }
+
+ /*
+ * Switch to the prototype page tables for this processor.
+ * While this processor is in the scheduler, the process could run
+ * on another processor and exit, returning the page tables to
+ * the free list where they could be reallocated and overwritten.
+ * When this processor eventually has to get an entry from the
+ * trashed page tables it will crash.
+ */
+ mmupark();
+}
+
+void
+setupboot(int halt)
+{
+ int n = 0; // cpu id of primary cpu, not just m->machno
+ Hwcpu *cpu = (Hwcpu*)((ulong)hwrpb + hwrpb->cpuoff + n*hwrpb->cpulen);
+
+ cpu->state &= ~(Cpucanrestart | Cpuhaltmask);
+ cpu->state |= (halt? Cpuhaltstayhalted: Cpuhaltwarmboot);
+}
+
+/* from ../pc */
+static void
+shutdown(int ispanic)
+{
+ int ms, once;
+
+ lock(&active);
+ if(ispanic)
+ active.ispanic = ispanic;
+ else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
+ active.ispanic = 0;
+ once = active.machs & (1<<m->machno);
+ active.machs &= ~(1<<m->machno);
+ active.exiting = 1;
+ unlock(&active);
+
+ if(once)
+ print("cpu%d: exiting\n", m->machno);
+ spllo();
+ for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
+ delay(TK2MS(2));
+ if(active.machs == 0 && consactive() == 0)
+ break;
+ }
+
+ if(active.ispanic && m->machno == 0) {
+ if(cpuserver)
+ delay(10000);
+ else
+ for (;;)
+ continue;
+ } else
+ delay(1000);
+}
+
+/* from ../pc: */
+void
+reboot(void *entry, void *code, ulong size)
+{
+ // writeconf(); // pass kernel environment to next kernel
+ shutdown(0);
+
+ /*
+ * should be the only processor running now
+ */
+ print("shutting down...\n");
+ delay(200);
+
+ splhi();
+
+ /* turn off buffered serial console */
+ serialoq = nil;
+
+ /* shutdown devices */
+ chandevshutdown();
+
+#ifdef FUTURE
+{
+ ulong *pdb;
+ /*
+ * Modify the machine page table to directly map the low 4MB of memory
+ * This allows the reboot code to turn off the page mapping
+ */
+ pdb = m->pdb;
+ pdb[PDX(0)] = pdb[PDX(KZERO)];
+ mmuflushtlb(PADDR(pdb));
+}
+ /* setup reboot trampoline function */
+{
+ void (*f)(ulong, ulong, ulong) = (void*)REBOOTADDR;
+
+ memmove(f, rebootcode, sizeof(rebootcode));
+#else
+ USED(entry, code, size);
+#endif
+
+ print("rebooting...\n");
+#ifdef FUTURE
+ /* off we go - never to return */
+ (*f)(PADDR(entry), PADDR(code), size);
+}
+#endif
+ setupboot(0); // reboot, don't halt
+ exit(0);
+}
+
+void
+exit(int ispanic)
+{
+ canlock(&active);
+ active.machs &= ~(1<<m->machno);
+ active.exiting = 1;
+ unlock(&active);
+
+ spllo();
+ print("cpu %d exiting\n", m->machno);
+ do
+ delay(100);
+ while(consactive());
+
+ splhi();
+ delay(1000); /* give serial fifo time to finish flushing */
+ if (getconf("*debug") != nil) {
+ USED(ispanic);
+ delay(60*1000); /* give us time to read the screen */
+ }
+ if(arch->coredetach)
+ arch->coredetach();
+ setupboot(1); // set up to halt
+ for (; ; )
+ firmware();
+
+ // on PC is just:
+ //if (0) {
+ // shutdown(ispanic);
+ // arch->reset();
+ //}
+}
+
+void
+confinit(void)
+{
+ ulong ktop, kpages;
+ Bank *b, *eb;
+ extern void _main(void);
+ int userpcnt;
+ char *p;
+
+ if(p = getconf("*kernelpercent"))
+ userpcnt = 100 - strtol(p, 0, 0);
+ else
+ userpcnt = 0;
+
+ /*
+ * The console firmware divides memory into 1 or more banks.
+ * FInd the bank with the kernel in it.
+ */
+ b = bootconf->bank;
+ eb = b+bootconf->nbank;
+ ktop = PGROUND((ulong)end);
+ ktop = PADDR(ktop);
+ while(b < eb) {
+ if(b->min < ktop && ktop < b->max)
+ break;
+ b++;
+ }
+ if(b == eb)
+ panic("confinit");
+
+ /*
+ * Split the bank of memory into 2 banks to fool the allocator into
+ * allocating low memory pages from bank 0 for any peripherals
+ * which only have a 24bit address counter.
+ */
+ conf.mem[0].npage = (8*1024*1024)/BY2PG;
+ conf.mem[0].base = 0;
+
+ conf.mem[1].npage = (b->max-8*1024*1024)/BY2PG;
+ conf.mem[1].base = 8*1024*1024;
+
+ conf.npage = conf.mem[0].npage+conf.mem[1].npage;
+ conf.upages = (conf.npage*70)/100;
+
+ conf.mem[0].npage -= ktop/BY2PG;
+ conf.mem[0].base += ktop;
+ conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
+
+ /*
+ * Fix up the bank we found to be the remnant, below the kernel.
+ * This, and the other banks, will be passed to xhole() later.
+ * BUG: conf.upages needs to be adjusted, but how? In practice,
+ * we only have 1 bank, and the remnant is small.
+ */
+ b->max = (uvlong)_main & ~(BY2PG-1);
+
+ conf.nmach = 1;
+ conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
+ if(cpuserver)
+ conf.nproc *= 3;
+ if(conf.nproc > 2000)
+ conf.nproc = 2000;
+ conf.nimage = 200;
+ conf.nswap = conf.nproc*80;
+ conf.nswppo = 4096;
+ conf.copymode = 0; /* copy on write */
+
+ if(cpuserver) {
+ if(userpcnt < 10)
+ userpcnt = 70;
+ kpages = conf.npage - (conf.npage*userpcnt)/100;
+
+ /*
+ * Hack for the big boys. Only good while physmem < 4GB.
+ * Give the kernel a max. of 16MB + enough to allocate the
+ * page pool.
+ * This is an overestimate as conf.upages < conf.npages.
+ * The patch of nimage is a band-aid, scanning the whole
+ * page list in imagereclaim just takes too long.
+ */
+ if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){
+ kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;
+ conf.nimage = 2000;
+ kpages += (conf.nproc*KSTACK)/BY2PG;
+ }
+ } else {
+ if(userpcnt < 10) {
+ if(conf.npage*BY2PG < 16*MB)
+ userpcnt = 40;
+ else
+ userpcnt = 60;
+ }
+ kpages = conf.npage - (conf.npage*userpcnt)/100;
+
+ /*
+ * Make sure terminals with low memory get at least
+ * 4MB on the first Image chunk allocation.
+ */
+ if(conf.npage*BY2PG < 16*MB)
+ imagmem->minarena = 4*1024*1024;
+ }
+ conf.upages = conf.npage - kpages;
+ conf.ialloc = (kpages/2)*BY2PG;
+
+ /*
+ * Guess how much is taken by the large permanent
+ * datastructures. Mntcache and Mntrpc are not accounted for
+ * (probably ~300KB).
+ */
+ kpages *= BY2PG;
+ kpages -= conf.upages*sizeof(Page)
+ + conf.nproc*sizeof(Proc)
+ + conf.nimage*sizeof(Image)
+ + conf.nswap
+ + conf.nswppo*sizeof(Page);
+ mainmem->maxsize = kpages;
+ if(!cpuserver){
+ /*
+ * give terminals lots of image memory, too; the dynamic
+ * allocation will balance the load properly, hopefully.
+ * be careful with 32-bit overflow.
+ */
+ imagmem->maxsize = kpages;
+ }
+
+// conf.monitor = 1; /* BUG */
+}
+
+void
+memholes(void)
+{
+ Bank *b, *eb;
+
+ b = bootconf->bank;
+ eb = b+bootconf->nbank;
+ while(b < eb) {
+ if(b->min < (1LL<<32) && b->max < (1LL<<32))
+ xhole(b->min, b->max-b->min);
+ b++;
+ }
+}
+
+char *sp;
+
+char *
+pusharg(char *p)
+{
+ int n;
+
+ n = strlen(p)+1;
+ sp -= n;
+ memmove(sp, p, n);
+ return sp;
+}
+
+void
+arginit(void)
+{
+ char **av;
+
+ av = (char**)argbuf;
+ sp = argbuf + sizeof(argbuf);
+ *av++ = pusharg("boot");
+ *av = 0;
+}
+
+char *
+getconf(char *name)
+{
+ int n;
+
+ for(n = 0; n < nconf; n++)
+ if(cistrcmp(confname[n], name) == 0) {
+ return confval[n];
+ }
+ return 0;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ char cc[32], *p;
+ int i, n;
+
+ snprint(cc, sizeof cc, "%s%d", class, ctlrno);
+ for(n = 0; n < nconf; n++){
+ if(cistrcmp(confname[n], cc) != 0)
+ continue;
+ isa->nopt = tokenize(confval[n], isa->opt, NISAOPT);
+ for(i = 0; i < isa->nopt; i++){
+ p = isa->opt[i];
+ if(cistrncmp(p, "type=", 5) == 0)
+ isa->type = p + 5;
+ else if(cistrncmp(p, "port=", 5) == 0)
+ isa->port = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "irq=", 4) == 0)
+ isa->irq = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "dma=", 4) == 0)
+ isa->dma = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "mem=", 4) == 0)
+ isa->mem = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "size=", 5) == 0)
+ isa->size = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "freq=", 5) == 0)
+ isa->freq = strtoul(p+5, &p, 0);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+int
+cistrcmp(char *a, char *b)
+{
+ int ac, bc;
+
+ for(;;){
+ ac = *a++;
+ bc = *b++;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+ return 0;
+}
+
+int
+cistrncmp(char *a, char *b, int n)
+{
+ unsigned ac, bc;
+
+ while(n > 0){
+ ac = *a++;
+ bc = *b++;
+ n--;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+
+ return 0;
+}
+
+int
+getcfields(char* lp, char** fields, int n, char* sep)
+{
+ int i;
+
+ for(i = 0; lp && *lp && i < n; i++){
+ while(*lp && strchr(sep, *lp) != 0)
+ *lp++ = 0;
+ if(*lp == 0)
+ break;
+ fields[i] = lp;
+ while(*lp && strchr(sep, *lp) == 0){
+ if(*lp == '\\' && *(lp+1) == '\n')
+ *lp++ = ' ';
+ lp++;
+ }
+ }
+
+ return i;
+}
diff --git a/sys/src/9/alphapc/mem.h b/sys/src/9/alphapc/mem.h
new file mode 100755
index 000000000..be8cbd6c6
--- /dev/null
+++ b/sys/src/9/alphapc/mem.h
@@ -0,0 +1,89 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define BI2BY 8 /* bits per byte */
+#define BI2WD 32 /* bits per word */
+#define BY2WD 4 /* bytes per word */
+#define BY2V 8 /* bytes per vlong */
+#define BY2PG 8192 /* bytes per page */
+#define WD2PG (BY2PG/BY2WD) /* words per page */
+#define PGSHIFT 13 /* log(BY2PG) */
+#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1))
+#define PGROUND(s) ROUND(s, BY2PG)
+#define BLOCKALIGN 8
+
+#define BY2PTE 8 /* bytes per pte entry */
+#define PTE2PG (BY2PG/BY2PTE) /* pte entries per page */
+
+#define MAXMACH 1 /* max # cpus system can run */
+#define KSTACK 4096 /* Size of kernel stack */
+
+/*
+ * Time
+ */
+#define HZ 100 /* clock frequency */
+#define MS2HZ (1000/HZ)
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+
+/*
+ * Magic registers
+ */
+#define MACH 15 /* R15 is m-> */
+#define USER 14 /* R14 is up-> */
+
+
+/*
+ * Fundamental addresses
+ */
+/* XXX MACHADDR, MACHP(n) */
+
+/*
+ * MMU
+ *
+ * A PTE is 64 bits, but a ulong is 32! Hence we encode
+ * the PTEs specially for fault.c, and decode them in putmmu().
+ * This means that we can only map the first 2G of physical
+ * space via putmmu() - ie only physical memory, not devices.
+ */
+#define PTEVALID 0x3301
+#define PTEKVALID 0x1101
+#define PTEASM 0x0010
+#define PTEGH(s) ((s)<<5)
+#define PTEWRITE 0
+#define PTERONLY 0x4
+#define PTEUNCACHED 0
+#define PPN(n) (((n)>>PGSHIFT)<<14)
+#define FIXPTE(x) ((((uvlong)(x)>>14)<<32)|((x) & 0x3fff))
+#define PTEPFN(pa) (((uvlong)(pa)>>PGSHIFT)<<32)
+#define NCOLOR 1
+#define getpgcolor(a) 0
+
+#define PTEMAPMEM (1024*1024)
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 512
+#define SSEGMAPSIZE 16
+
+/*
+ * Address spaces
+ */
+#define UZERO 0 /* base of user address space */
+#define UTZERO (UZERO+BY2PG) /* first address in user text */
+#define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */
+#define TSTKTOP KZERO /* top of temporary stack */
+#define TSTKSIZ 100
+#define KZERO 0x80000000 /* base of kernel address space */
+#define KTZERO (KZERO+0x400000) /* first address in kernel text */
+#define USTKSIZE (4*1024*1024) /* size of user stack */
+
+/*
+ * Processor Status (as returned by rdps)
+ */
+#define UMODE 0x8
+#define IPL 0x7
+
+
+#define isphys(x) (((ulong)x&KZERO)!=0)
diff --git a/sys/src/9/alphapc/memmove.s b/sys/src/9/alphapc/memmove.s
new file mode 100755
index 000000000..0fafb752d
--- /dev/null
+++ b/sys/src/9/alphapc/memmove.s
@@ -0,0 +1,197 @@
+#define QUAD 8
+#define ALIGN 64
+#define BLOCK 64
+
+TEXT memmove(SB), $0
+ MOVL from+4(FP), R7
+ MOVL n+8(FP), R10
+ MOVQ R0, R6
+
+ CMPUGE R7, R0, R5
+ BNE R5, _forward
+
+ MOVQ R6, R8 /* end to address */
+ ADDL R10, R6, R6 /* to+n */
+ ADDL R10, R7, R7 /* from+n */
+
+ CMPUGE $ALIGN, R10, R1 /* need at least ALIGN bytes */
+ BNE R1, _b1tail
+
+_balign:
+ AND $(ALIGN-1), R6, R1
+ BEQ R1, _baligned
+
+ MOVBU -1(R7), R2
+ ADDL $-1, R6, R6
+ MOVB R2, (R6)
+ ADDL $-1, R7, R7
+ JMP _balign
+
+_baligned:
+ AND $(QUAD-1), R7, R1 /* is the source quad-aligned */
+ BNE R1, _bunaligned
+
+ ADDL $(BLOCK-1), R8, R9
+_bblock:
+ CMPUGE R9, R6, R1
+ BNE R1, _b8tail
+
+ MOVQ -64(R7), R22
+ MOVQ -56(R7), R23
+ MOVQ -48(R7), R24
+ MOVQ -40(R7), R25
+ MOVQ -32(R7), R2
+ MOVQ -24(R7), R3
+ MOVQ -16(R7), R4
+ MOVQ -8(R7), R5
+
+ SUBL $64, R6, R6
+ SUBL $64, R7, R7
+
+ MOVQ R22, (R6)
+ MOVQ R23, 8(R6)
+ MOVQ R24, 16(R6)
+ MOVQ R25, 24(R6)
+ MOVQ R2, 32(R6)
+ MOVQ R3, 40(R6)
+ MOVQ R4, 48(R6)
+ MOVQ R5, 56(R6)
+ JMP _bblock
+
+_b8tail:
+ ADDL $(QUAD-1), R8, R9
+_b8block:
+ CMPUGE R9, R6, R1
+ BNE R1, _b1tail
+
+ MOVQ -8(R7), R2
+ SUBL $8, R6
+ MOVQ R2, (R6)
+ SUBL $8, R7
+ JMP _b8block
+
+_b1tail:
+ CMPUGE R8, R6, R1
+ BNE R1, _ret
+
+ MOVBU -1(R7), R2
+ SUBL $1, R6, R6
+ MOVB R2, (R6)
+ SUBL $1, R7, R7
+ JMP _b1tail
+_ret:
+ RET
+
+_bunaligned:
+ ADDL $(16-1), R8, R9
+
+_bu8block:
+ CMPUGE R9, R6, R1
+ BNE R1, _b1tail
+
+ MOVQU -16(R7), R4
+ MOVQU -8(R7), R3
+ MOVQU (R7), R2
+ SUBL $16, R6
+ EXTQH R7, R2, R2
+ EXTQL R7, R3, R5
+ OR R5, R2, R11
+ EXTQH R7, R3, R3
+ EXTQL R7, R4, R4
+ OR R3, R4, R13
+ MOVQ R11, 8(R6)
+ MOVQ R13, (R6)
+ SUBL $16, R7
+ JMP _bu8block
+
+_forward:
+ ADDL R10, R6, R8 /* end to address */
+
+ CMPUGE $ALIGN, R10, R1 /* need at least ALIGN bytes */
+ BNE R1, _f1tail
+
+_falign:
+ AND $(ALIGN-1), R6, R1
+ BEQ R1, _faligned
+
+ MOVBU (R7), R2
+ ADDL $1, R6, R6
+ ADDL $1, R7, R7
+ MOVB R2, -1(R6)
+ JMP _falign
+
+_faligned:
+ AND $(QUAD-1), R7, R1 /* is the source quad-aligned */
+ BNE R1, _funaligned
+
+ SUBL $(BLOCK-1), R8, R9
+_fblock:
+ CMPUGT R9, R6, R1
+ BEQ R1, _f8tail
+
+ MOVQ (R7), R2
+ MOVQ 8(R7), R3
+ MOVQ 16(R7), R4
+ MOVQ 24(R7), R5
+ MOVQ 32(R7), R22
+ MOVQ 40(R7), R23
+ MOVQ 48(R7), R24
+ MOVQ 56(R7), R25
+
+ ADDL $64, R6, R6
+ ADDL $64, R7, R7
+
+ MOVQ R2, -64(R6)
+ MOVQ R3, -56(R6)
+ MOVQ R4, -48(R6)
+ MOVQ R5, -40(R6)
+ MOVQ R22, -32(R6)
+ MOVQ R23, -24(R6)
+ MOVQ R24, -16(R6)
+ MOVQ R25, -8(R6)
+ JMP _fblock
+
+_f8tail:
+ SUBL $(QUAD-1), R8, R9
+_f8block:
+ CMPUGT R9, R6, R1
+ BEQ R1, _f1tail
+
+ MOVQ (R7), R2
+ ADDL $8, R6
+ ADDL $8, R7
+ MOVQ R2, -8(R6)
+ JMP _f8block
+
+_f1tail:
+ CMPUGT R8, R6, R1
+ BEQ R1, _fret
+ MOVBU (R7), R2
+ ADDL $1, R6, R6
+ ADDL $1, R7, R7
+ MOVB R2, -1(R6)
+ JMP _f1tail
+
+_fret:
+ RET
+
+_funaligned:
+ SUBL $(16-1), R8, R9
+_fu8block:
+ CMPUGT R9, R6, R1
+ BEQ R1, _f1tail
+
+ MOVQU (R7), R2
+ MOVQU 8(R7), R3
+ MOVQU 16(R7), R4
+ EXTQL R7, R2, R2
+ EXTQH R7, R3, R5
+ OR R5, R2, R11
+ EXTQL R7, R3, R3
+ MOVQ R11, (R6)
+ EXTQH R7, R4, R4
+ OR R3, R4, R11
+ MOVQ R11, 8(R6)
+ ADDL $16, R6
+ ADDL $16, R7
+ JMP _fu8block
diff --git a/sys/src/9/alphapc/memset.s b/sys/src/9/alphapc/memset.s
new file mode 100755
index 000000000..e3cfd468b
--- /dev/null
+++ b/sys/src/9/alphapc/memset.s
@@ -0,0 +1,61 @@
+TEXT memset(SB), $0
+ MOVL R0, R6
+ MOVBU data+4(FP), R2
+ MOVL n+8(FP), R10
+
+ ADDL R10, R0, R8
+
+ CMPUGE $8, R10, R1 /* need at least 8 bytes */
+ BNE R1, _1loop
+
+ SLLQ $8, R2, R1 /* replicate the byte */
+ OR R1, R2
+ SLLQ $16, R2, R1
+ OR R1, R2
+ SLLQ $32, R2, R1
+ OR R1, R2
+
+_align:
+ AND $(8-1), R6, R1
+ BEQ R1, _aligned
+
+ MOVB R2, (R6)
+ ADDL $1, R6, R6
+ JMP _align
+
+_aligned:
+ SUBL $(64-1), R8, R9 /* end pointer minus slop */
+_64loop:
+ CMPUGT R9, R6, R1
+ BEQ R1, _8tail
+
+ MOVQ R2, (R6)
+ MOVQ R2, 8(R6)
+ MOVQ R2, 16(R6)
+ MOVQ R2, 24(R6)
+ MOVQ R2, 32(R6)
+ MOVQ R2, 40(R6)
+ MOVQ R2, 48(R6)
+ MOVQ R2, 56(R6)
+ ADDL $64, R6, R6
+ JMP _64loop
+
+_8tail:
+ SUBL $(8-1), R8, R9
+_8loop:
+ CMPUGT R9, R6, R1
+ BEQ R1, _1loop
+
+ MOVQ R2, (R6)
+ ADDL $8, R6
+ JMP _8loop
+
+_1loop:
+ CMPUGT R8, R6, R1
+ BEQ R1, _ret
+ MOVB R2, (R6)
+ ADDL $1, R6
+ JMP _1loop
+
+_ret:
+ RET
diff --git a/sys/src/9/alphapc/mkfile b/sys/src/9/alphapc/mkfile
new file mode 100755
index 000000000..7accffead
--- /dev/null
+++ b/sys/src/9/alphapc/mkfile
@@ -0,0 +1,109 @@
+CONF=apc
+CONFLIST=apc apccpu
+
+objtype=alpha
+</$objtype/mkfile
+p=9
+
+DEVS=`{rc ../port/mkdevlist $CONF}
+
+PORT=\
+ alarm.$O\
+ alloc.$O\
+ allocb.$O\
+ auth.$O\
+ cache.$O\
+ chan.$O\
+ dev.$O\
+ fault.$O\
+ latin1.$O\
+ log.$O\
+ edf.$O\
+ mul64fract.$O\
+ page.$O\
+ parse.$O\
+ pgrp.$O\
+ portclock.$O\
+ print.$O\
+ proc.$O\
+ qio.$O\
+ qlock.$O\
+ rdb.$O\
+ rebootcmd.$O\
+ segment.$O\
+ swap.$O\
+ sysfile.$O\
+ sysproc.$O\
+ taslock.$O\
+ tod.$O\
+ xalloc.$O\
+
+OBJ=\
+ l.$O\
+ cga.$O\
+ clock.$O\
+ faultalpha.$O\
+ fdc37c93x.$O\
+ fptrap.$O\
+ i8259.$O\
+ kbd.$O\
+ main.$O\
+ mmu.$O\
+ random.$O\
+ trap.$O\
+ $CONF.root.$O\
+ $CONF.rootc.$O\
+ $DEVS\
+ $PORT\
+
+LIB=\
+ /$objtype/lib/libmemlayer.a\
+ /$objtype/lib/libmemdraw.a\
+ /$objtype/lib/libdraw.a\
+ /$objtype/lib/libip.a\
+ /$objtype/lib/libc.a\
+ /$objtype/lib/libsec.a\
+
+ETHER=`{echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
+VGA=`{echo devvga.c screen.c vga*.c | sed 's/\.c/.'$O'/g'}
+SDEV=`{echo devsd.c sd*.c | sed 's/\.c/.'$O'/g'}
+
+loadaddr = 0x80400020
+
+$p$CONF: $CONF.c $OBJ $LIB
+ $CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
+ $LD -o $target -H3 -R8 -T$loadaddr -l $OBJ $CONF.$O $LIB
+ size $target
+
+install:V: $p$CONF
+ cp $p$CONF /$objtype/$p$CONF
+
+<../boot/bootmkfile
+<../port/portmkfile
+<|../port/mkbootrules $CONF
+<../pc/pcmkfile
+
+init.h: initcode /sys/src/libc/9syscall/sys.h
+ $AS initcode
+ $LD -l -s -R8 -o init.out initcode.$O -lc
+ {echo 'uchar initcode[]={'
+ xd -r -1x init.out |
+ sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+ echo '};'} > init.h
+
+clock.$O: /$objtype/include/ureg.h axp.h
+devarch.$O: axp.h
+faultalpha.$O: /$objtype/include/ureg.h
+fptrap.$O: /$objtype/include/ureg.h
+kbd.$O: /$objtype/include/ureg.h
+l.$O: osf1pal.h
+main.$O: /$objtype/include/ureg.h errstr.h init.h
+mmu.$O: /sys/src/boot/alphapc/conf.h
+sd53c8xx.$O: /$objtype/include/ureg.h ../port/sd.h sd53c8xx.i
+trap.$O: /$objtype/include/ureg.h ../port/error.h ../port/systab.h
+
+sd53c8xx.i: ../pc/sd53c8xx.n
+ aux/na $prereq > $target
+
+acid:V:
+ $CC -a -w -I. ../port/qio.c>acid
diff --git a/sys/src/9/alphapc/mmu.c b/sys/src/9/alphapc/mmu.c
new file mode 100755
index 000000000..05ff63a5e
--- /dev/null
+++ b/sys/src/9/alphapc/mmu.c
@@ -0,0 +1,299 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "/sys/src/boot/alphapc/conf.h"
+
+static uvlong origlvl1; /* physical address */
+static uvlong klvl2; /* physical, as created by boot loader */
+static uchar *nextio; /* next virtual address to be allocated by kmapv */
+extern Bootconf *bootconf;
+
+#define LVL2OFF(v) ((((long)(v))>>(2*PGSHIFT-3))&(PTE2PG-1))
+#define LVL3OFF(v) ((((long)(v))>>(PGSHIFT))&(PTE2PG-1))
+
+static void
+setptb(ulong pa)
+{
+ m->ptbr = (uvlong)pa>>PGSHIFT;
+ swpctx(m);
+}
+
+void
+mmuinit(void)
+{
+ uvlong *plvl2;
+
+ /* set PCB to new one in mach structure before stomping on old one */
+ m->usp = 0;
+ m->fen = 1;
+ m->ptbr = bootconf->pcb->ptbr;
+ origlvl1 = (m->ptbr << PGSHIFT);
+ setpcb(m);
+
+ plvl2 = (uvlong*) (KZERO|origlvl1|(BY2PG-8));
+ klvl2 = (*plvl2 >> 32)<<PGSHIFT;
+
+ nextio = (uchar*) (KZERO|bootconf->maxphys);
+}
+
+static void
+mmuptefree(Proc* proc)
+{
+ uvlong *lvl2;
+ Page **last, *page;
+
+ if(proc->mmutop && proc->mmuused){
+ lvl2 = (uvlong*)proc->mmulvl2->va;
+ last = &proc->mmuused;
+ for(page = *last; page; page = page->next){
+ lvl2[page->daddr] = 0;
+ last = &page->next;
+ }
+ *last = proc->mmufree;
+ proc->mmufree = proc->mmuused;
+ proc->mmuused = 0;
+ }
+}
+
+void
+mmuswitch(Proc *proc)
+{
+ if(proc->newtlb){
+ mmuptefree(proc);
+ proc->newtlb = 0;
+ }
+
+ /* tell processor about new page table and flush cached entries */
+ if(proc->mmutop == 0)
+ setptb(origlvl1);
+ else
+ setptb(proc->mmutop->pa);
+ tlbflush(-1, 0);
+ icflush();
+}
+
+/* point to protoype page map */
+void
+mmupark(void)
+{
+ setptb(origlvl1);
+ icflush();
+}
+
+/*
+ * give all page table pages back to the free pool. This is called in sched()
+ * with palloc locked.
+ */
+void
+mmurelease(Proc *proc)
+{
+ Page *page, *next;
+
+ mmupark();
+ mmuptefree(proc);
+ proc->mmuused = 0;
+ if(proc->mmutop) {
+ proc->mmutop->next = proc->mmufree;
+ proc->mmufree = proc->mmutop;
+ proc->mmutop = 0;
+ }
+ if(proc->mmulvl2) {
+ proc->mmulvl2->next = proc->mmufree;
+ proc->mmufree = proc->mmulvl2;
+ proc->mmulvl2 = 0;
+ }
+ for(page = proc->mmufree; page; page = next){
+ next = page->next;
+ if(--page->ref)
+ panic("mmurelease: page->ref %d\n", page->ref);
+ pagechainhead(page);
+ }
+ if(proc->mmufree && palloc.r.p)
+ wakeup(&palloc.r);
+ proc->mmufree = 0;
+}
+
+void
+mmunewtop(void)
+{
+ Page *top, *lvl2;
+ uvlong *ppte;
+
+ top = newpage(1, 0, 0);
+ top->va = VA(kmap(top));
+ lvl2 = newpage(1, 0, 0);
+ lvl2->va = VA(kmap(lvl2));
+
+ ppte = (uvlong *)top->va;
+ ppte[0] = PTEPFN(lvl2->pa) | PTEKVALID;
+ ppte[PTE2PG-2] = PTEPFN(top->pa) | PTEKVALID;
+ ppte[PTE2PG-1] = PTEPFN(klvl2) | PTEKVALID;
+
+ up->mmutop = top;
+ up->mmulvl2 = lvl2;
+ setptb(top->pa);
+ tlbflush(-1, 0);
+ icflush();
+}
+
+void
+putmmu(ulong va, ulong pa, Page *pg)
+{
+ int lvl2off;
+ uvlong *lvl2, *pt;
+ int s;
+
+ if(up->mmutop == 0)
+ mmunewtop();
+
+ lvl2 = (uvlong*)up->mmulvl2->va;
+ lvl2off = LVL2OFF(va);
+
+ /*
+ * if bottom level page table missing, allocate one
+ * and point the top level page at it.
+ */
+ s = splhi();
+ if(lvl2[lvl2off] == 0){
+ if(up->mmufree == 0){
+ spllo();
+ pg = newpage(1, 0, 0);
+ pg->va = VA(kmap(pg));
+ splhi();
+ } else {
+ pg = up->mmufree;
+ up->mmufree = pg->next;
+ memset((void*)pg->va, 0, BY2PG);
+ }
+ lvl2[lvl2off] = PTEPFN(pg->pa) | PTEVALID;
+ pg->daddr = lvl2off;
+ pg->next = up->mmuused;
+ up->mmuused = pg;
+ }
+
+ /*
+ * put in new mmu entry
+ */
+ pt = (uvlong*)(((lvl2[lvl2off] >> 32)<<PGSHIFT)|KZERO);
+ pt[LVL3OFF(va)] = FIXPTE(pa);
+
+ /* flush cached mmu entries */
+ tlbflush(3, va);
+ icflush();
+ splx(s);
+}
+
+void *
+kmapv(uvlong pa, int size)
+{
+ void *va, *new;
+ int lvl2off, i, npage, offset;
+ uvlong *lvl2, *pt;
+
+ offset = pa&(BY2PG-1);
+ npage = ((size+offset+BY2PG-1)>>PGSHIFT);
+
+ va = nextio+offset;
+ lvl2 = (uvlong*)(KZERO|klvl2);
+ for (i = 0; i < npage; i++) {
+ lvl2off = LVL2OFF(nextio);
+ if (lvl2[lvl2off] == 0) {
+ new = xspanalloc(BY2PG, BY2PG, 0);
+ memset(new, 0, BY2PG);
+ lvl2[lvl2off] = PTEPFN(PADDR(new)) | PTEKVALID | PTEASM;
+ }
+ pt = (uvlong*)(((lvl2[lvl2off] >> 32)<<PGSHIFT)|KZERO);
+ pt[LVL3OFF(nextio)] = PTEPFN(pa) | PTEKVALID | PTEASM;
+ nextio += BY2PG;
+ pa += BY2PG;
+ }
+ return va;
+}
+
+void
+flushmmu(void)
+{
+ int s;
+
+ s = splhi();
+ up->newtlb = 1;
+ mmuswitch(up);
+ splx(s);
+
+}
+
+void*
+vmap(ulong pa, int size)
+{
+ void *va;
+
+ /*
+ * Viability hack. Only for PCI framebuffers.
+ */
+ if(pa == 0)
+ return 0;
+ va = kmapv(((uvlong)0x88<<32LL)|pa, size);
+ if(va == nil)
+ return 0;
+ return (void*)va;
+}
+
+void
+vunmap(void*, int)
+{
+ print("vunmap: virtual mapping not freed\n");
+}
+
+void
+mmudump(void)
+{
+ Page *top, *lvl2;
+
+ iprint("ptbr %lux up %#p\n", (ulong)m->ptbr, up);
+ if(up) {
+ top = up->mmutop;
+ if(top != nil)
+ iprint("top %lux top[N-1] %llux\n", top->va, ((uvlong *)top->va)[PTE2PG-1]);
+ lvl2 = up->mmulvl2;
+ if(lvl2 != nil)
+ iprint("lvl2 %lux\n", lvl2->va);
+ }
+}
+
+ulong
+upaalloc(int, int)
+{
+ return 0;
+}
+
+void
+upafree(ulong, int)
+{
+}
+
+void
+checkmmu(ulong, ulong)
+{
+}
+
+void
+countpagerefs(ulong*, int)
+{
+}
+
+/*
+ * Return the number of bytes that can be accessed via KADDR(pa).
+ * If pa is not a valid argument to KADDR, return 0.
+ */
+ulong
+cankaddr(ulong pa)
+{
+ ulong kzero;
+
+ kzero = -KZERO;
+ if(pa >= kzero)
+ return 0;
+ return kzero - pa;
+}
diff --git a/sys/src/9/alphapc/osf1pal.h b/sys/src/9/alphapc/osf1pal.h
new file mode 100755
index 000000000..0ee9e67ee
--- /dev/null
+++ b/sys/src/9/alphapc/osf1pal.h
@@ -0,0 +1,78 @@
+/*
+ * OSF/1 PALcode instructions, in numerical order.
+ * Values are from Digital EBSDK and FreeBSD/Alpha.
+ */
+
+/* Privilaged PAL functions */
+#define PALhalt 0x00 /* required per Alpha architecture */
+#define PALcflush 0x01
+#define PALdraina 0x02 /* required per Alpha architecture */
+/*
+ * ... 0x03 to 0x08 ?
+ */
+#define PALcserve 0x09
+#define PALswppal 0x0a
+/*
+ * ... 0x0b to 0x0c ?
+ */
+#define PALwripir 0x0d
+/*
+ * ... 0x0e to 0x0f ?
+ */
+#define PALrdmces 0x10
+#define PALwrmces 0x11
+/*
+ * ... 0x12 to 0x2a ?
+ */
+#define PALwrfen 0x2b
+ /* 0x2c OSF/1 ? */
+#define PALwrvptptr 0x2d
+/*
+ * ... 0x2e to 0x2f ?
+ */
+#define PALswpctx 0x30
+#define PALwrval 0x31
+#define PALrdval 0x32
+#define PALtbi 0x33
+#define PALwrent 0x34
+#define PALswpipl 0x35
+#define PALrdps 0x36
+#define PALwrkgp 0x37
+#define PALwrusp 0x38
+#define PALwrperfmon 0x39
+#define PALrdusp 0x3a
+ /* 0x3b OSF/1 ? */
+#define PALwhami 0x3c
+#define PALretsys 0x3d
+#define PALwtint 0x3e
+#define PALrti 0x3f
+
+/* Unprivileged PAL functions */
+#define PALbpt 0x80
+#define PALbugchk 0x81
+#define PALcallsys 0x83
+#define PALimb 0x86 /* required per Alpha architecture */
+/*
+ * ... 0x89 to 0x91 ?
+ */
+#define PALurti 0x92
+/*
+ * ... 0x93 to 0x9d ?
+ */
+#define PALrdunique 0x9e
+#define PALwrunique 0x9f
+/*
+ * ... 0xa0 to 0xa9 ?
+ */
+#define PALgentrap 0xaa
+/*
+ * ... 0xab to 0xac ?
+ */
+#define PALdbgstop 0xad
+#define PALclrfen 0xae
+/*
+ * ... 0xaf to 0xbd ?
+ */
+#define PALnphalt 0xbe
+#define PALcopypal 0xbf
+
diff --git a/sys/src/9/alphapc/pci.c b/sys/src/9/alphapc/pci.c
new file mode 100755
index 000000000..13d431c1a
--- /dev/null
+++ b/sys/src/9/alphapc/pci.c
@@ -0,0 +1,412 @@
+/*
+ * PCI support code.
+ * To do:
+ * initialise bridge mappings if the PCI BIOS didn't.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+enum {
+ MaxFNO = 7,
+ MaxUBN = 255,
+};
+
+enum
+{ /* command register */
+ IOen = (1<<0),
+ MEMen = (1<<1),
+ MASen = (1<<2),
+ MemWrInv = (1<<4),
+ PErrEn = (1<<6),
+ SErrEn = (1<<8),
+};
+
+static Lock pcicfglock;
+static Lock pcicfginitlock;
+static int pcicfgmode = -1;
+static int pcimaxdno;
+static Pcidev* pciroot;
+static Pcidev* pcilist;
+static Pcidev* pcitail;
+
+static int pcicfgrw32(int, int, int, int);
+
+uchar *vgabios;
+
+static int
+pciscan(int bno, Pcidev** list)
+{
+ ulong v;
+ Pcidev *p, *head, *tail;
+ int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
+
+ maxubn = bno;
+ head = nil;
+ tail = nil;
+ for(dno = 0; dno <= pcimaxdno; dno++){
+ maxfno = 0;
+ for(fno = 0; fno <= maxfno; fno++){
+ /*
+ * For this possible device, form the
+ * bus+device+function triplet needed to address it
+ * and try to read the vendor and device ID.
+ * If successful, allocate a device struct and
+ * start to fill it in with some useful information
+ * from the device's configuration space.
+ */
+ tbdf = MKBUS(BusPCI, bno, dno, fno);
+ l = pcicfgrw32(tbdf, PciVID, 0, 1);
+ if(l == 0xFFFFFFFF || l == 0)
+ continue;
+/* optional safety checks:
+ if(l == pcicfgrw32(tbdf, PciPCR, 0, 1))
+ continue;
+ if(l != pcicfgrw32(tbdf, PciVID, 0, 1))
+ continue;
+ if(l == pcicfgrw32(tbdf, PciPCR, 0, 1))
+ continue;
+*/
+ p = malloc(sizeof(*p));
+ p->tbdf = tbdf;
+ p->vid = l;
+ p->did = l>>16;
+
+ if(pcilist != nil)
+ pcitail->list = p;
+ else
+ pcilist = p;
+ pcitail = p;
+
+ p->rid = pcicfgr8(p, PciRID);
+ p->ccrp = pcicfgr8(p, PciCCRp);
+ p->ccru = pcicfgr8(p, PciCCRu);
+ p->ccrb = pcicfgr8(p, PciCCRb);
+ p->pcr = pcicfgr32(p, PciPCR);
+
+ p->intl = pcicfgr8(p, PciINTL);
+
+ /*
+ * If the device is a multi-function device adjust the
+ * loop count so all possible functions are checked.
+ */
+ hdt = pcicfgr8(p, PciHDT);
+ if(hdt & 0x80)
+ maxfno = MaxFNO;
+
+ /*
+ * If appropriate, read the base address registers
+ * and work out the sizes.
+ */
+ switch(p->ccrb){
+
+ case 0x03: /* display controller */
+ if(vgabios == nil) {
+ v = pcicfgr32(p, PciROM);
+ pcicfgw32(p, PciROM, v|1); /* enable decode */
+ vgabios = kmapv(((uvlong)0x88<<32LL)|(v&~0xffff), 0x10000);
+ // print("VGA BIOS %lux -> %lux\n", v, vgabios);
+ }
+ /* fall through */
+ case 0x01: /* mass storage controller */
+ case 0x02: /* network controller */
+ case 0x04: /* multimedia device */
+ case 0x07: /* simple communication controllers */
+ case 0x08: /* base system peripherals */
+ case 0x09: /* input devices */
+ case 0x0A: /* docking stations */
+ case 0x0B: /* processors */
+ case 0x0C: /* serial bus controllers */
+ if((hdt & 0x7F) != 0)
+ break;
+ rno = PciBAR0 - 4;
+ for(i = 0; i < nelem(p->mem); i++){
+ rno += 4;
+ p->mem[i].bar = pcicfgr32(p, rno);
+ pcicfgw32(p, rno, -1);
+ v = pcicfgr32(p, rno);
+ pcicfgw32(p, rno, p->mem[i].bar);
+ p->mem[i].size = -(v & ~0xF);
+ }
+ break;
+
+ case 0x00:
+ case 0x05: /* memory controller */
+ case 0x06: /* bridge device */
+ default:
+ break;
+ }
+
+ if(head != nil)
+ tail->link = p;
+ else
+ head = p;
+ tail = p;
+ }
+ }
+
+ *list = head;
+ for(p = head; p != nil; p = p->link){
+ /*
+ * Find PCI-PCI bridges and recursively descend the tree.
+ */
+ if(p->ccrb != 0x06 || p->ccru != 0x04)
+ continue;
+
+ /*
+ * If the secondary or subordinate bus number is not initialised
+ * try to do what the PCI BIOS should have done and fill in the
+ * numbers as the tree is descended. On the way down the subordinate
+ * bus number is set to the maximum as it's not known how many
+ * buses are behind this one; the final value is set on the way
+ * back up.
+ */
+ sbn = pcicfgr8(p, PciSBN);
+ ubn = pcicfgr8(p, PciUBN);
+ if(sbn == 0 || ubn == 0){
+ sbn = maxubn+1;
+ /*
+ * Make sure memory, I/O and master enables are off,
+ * set the primary, secondary and subordinate bus numbers
+ * and clear the secondary status before attempting to
+ * scan the secondary bus.
+ *
+ * Initialisation of the bridge should be done here.
+ */
+ pcicfgw32(p, PciPCR, 0xFFFF0000);
+ l = (MaxUBN<<16)|(sbn<<8)|bno;
+ pcicfgw32(p, PciPBN, l);
+ pcicfgw16(p, PciSPSR, 0xFFFF);
+ maxubn = pciscan(sbn, &p->bridge);
+ l = (maxubn<<16)|(sbn<<8)|bno;
+ pcicfgw32(p, PciPBN, l);
+ }
+ else{
+ maxubn = ubn;
+ pciscan(sbn, &p->bridge);
+ }
+ }
+
+ return maxubn;
+}
+
+static void
+pcicfginit(void)
+{
+ char *p;
+
+ lock(&pcicfginitlock);
+ if(pcicfgmode == -1){
+ pcicfgmode = 0;
+ pcimaxdno = 15; /* was 20; what is correct value??? */
+ if(p = getconf("*pcimaxdno"))
+ pcimaxdno = strtoul(p, 0, 0);
+ pciscan(0, &pciroot);
+ }
+ unlock(&pcicfginitlock);
+}
+
+static int
+pcicfgrw8(int tbdf, int rno, int data, int read)
+{
+ int x;
+ uchar *p;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+ x = -1;
+ if(BUSDNO(tbdf) > pcimaxdno)
+ return x;
+
+ p = (uchar*)arch->pcicfg(tbdf, rno);
+ if(read)
+ x = *p;
+ else
+ *p = data;
+
+ return x;
+}
+
+int
+pcicfgr8(Pcidev* pcidev, int rno)
+{
+ return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw8(Pcidev* pcidev, int rno, int data)
+{
+ pcicfgrw8(pcidev->tbdf, rno, data, 0);
+}
+
+static int
+pcicfgrw16(int tbdf, int rno, int data, int read)
+{
+ int x;
+ ushort *p;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+ x = -1;
+ if(BUSDNO(tbdf) > pcimaxdno)
+ return x;
+
+ p = (ushort*)arch->pcicfg(tbdf, rno);
+ if(read)
+ x = *p;
+ else
+ *p = data;
+
+ return x;
+}
+
+int
+pcicfgr16(Pcidev* pcidev, int rno)
+{
+ return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw16(Pcidev* pcidev, int rno, int data)
+{
+ pcicfgrw16(pcidev->tbdf, rno, data, 0);
+}
+
+static int
+pcicfgrw32(int tbdf, int rno, int data, int read)
+{
+ int x;
+ ulong *p;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+ x = -1;
+ if(BUSDNO(tbdf) > pcimaxdno)
+ return x;
+
+ p = (ulong*)arch->pcicfg(tbdf, rno);
+ if(read)
+ x = *p;
+ else
+ *p = data;
+
+ return x;
+}
+
+int
+pcicfgr32(Pcidev* pcidev, int rno)
+{
+ return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw32(Pcidev* pcidev, int rno, int data)
+{
+ pcicfgrw32(pcidev->tbdf, rno, data, 0);
+}
+
+Pcidev*
+pcimatch(Pcidev* prev, int vid, int did)
+{
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(prev == nil)
+ prev = pcilist;
+ else
+ prev = prev->list;
+
+ while(prev != nil) {
+ if((vid == 0 || prev->vid == vid)
+ && (did == 0 || prev->did == did))
+ break;
+ prev = prev->list;
+ }
+ return prev;
+}
+
+Pcidev*
+pcimatchtbdf(int tbdf)
+{
+ Pcidev *pcidev;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
+ if(pcidev->tbdf == tbdf)
+ break;
+ }
+ return pcidev;
+}
+
+void
+pcihinv(Pcidev* p)
+{
+ int i;
+ Pcidev *t;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+ if(p == nil) {
+ p = pciroot;
+ print("bus dev type vid did intl memory\n");
+ }
+ for(t = p; t != nil; t = t->link) {
+ print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %2d ",
+ BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
+ t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
+
+ for(i = 0; i < nelem(p->mem); i++) {
+ if(t->mem[i].size == 0)
+ continue;
+ print("%d:%.8lux %d ", i,
+ t->mem[i].bar, t->mem[i].size);
+ }
+ print("\n");
+ }
+ while(p != nil) {
+ if(p->bridge != nil)
+ pcihinv(p->bridge);
+ p = p->link;
+ }
+}
+
+void
+pcireset(void)
+{
+ Pcidev *p;
+ int pcr;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ for(p = pcilist; p != nil; p = p->list){
+ pcr = pcicfgr16(p, PciPSR);
+ pcicfgw16(p, PciPSR, pcr & ~0x04);
+ }
+}
+
+void
+pcisetbme(Pcidev* p)
+{
+ int pcr;
+
+ pcr = pcicfgr16(p, PciPCR);
+ pcr |= MASen;
+ pcicfgw16(p, PciPCR, pcr);
+}
+
+void
+pciclrbme(Pcidev* p)
+{
+ int pcr;
+
+ pcr = pcicfgr16(p, PciPCR);
+ pcr &= ~MASen;
+ pcicfgw16(p, PciPCR, pcr);
+}
diff --git a/sys/src/9/alphapc/screen.h b/sys/src/9/alphapc/screen.h
new file mode 100755
index 000000000..190b49152
--- /dev/null
+++ b/sys/src/9/alphapc/screen.h
@@ -0,0 +1,171 @@
+typedef struct Cursor Cursor;
+typedef struct Cursorinfo Cursorinfo;
+struct Cursorinfo {
+ Cursor;
+ Lock;
+};
+
+/* devmouse.c */
+extern void mousetrack(int, int, int, int);
+extern Point mousexy(void);
+
+extern void mouseaccelerate(int);
+extern int m3mouseputc(Queue*, int);
+extern int m5mouseputc(Queue*, int);
+extern int mouseputc(Queue*, int);
+
+extern Cursorinfo cursor;
+extern Cursor arrow;
+
+/*
+ * Generic VGA registers.
+ */
+enum {
+ MiscW = 0x03C2, /* Miscellaneous Output (W) */
+ MiscR = 0x03CC, /* Miscellaneous Output (R) */
+ Status0 = 0x03C2, /* Input status 0 (R) */
+ Status1 = 0x03DA, /* Input Status 1 (R) */
+ FeatureR = 0x03CA, /* Feature Control (R) */
+ FeatureW = 0x03DA, /* Feature Control (W) */
+
+ Seqx = 0x03C4, /* Sequencer Index, Data at Seqx+1 */
+ Crtx = 0x03D4, /* CRT Controller Index, Data at Crtx+1 */
+ Grx = 0x03CE, /* Graphics Controller Index, Data at Grx+1 */
+ Attrx = 0x03C0, /* Attribute Controller Index and Data */
+
+ PaddrW = 0x03C8, /* Palette Address Register, write */
+ Pdata = 0x03C9, /* Palette Data Register */
+ Pixmask = 0x03C6, /* Pixel Mask Register */
+ PaddrR = 0x03C7, /* Palette Address Register, read */
+ Pstatus = 0x03C7, /* DAC Status (RO) */
+
+ Pcolours = 256, /* Palette */
+ Pred = 0,
+ Pgreen = 1,
+ Pblue = 2,
+
+ Pblack = 0x00,
+ Pwhite = 0xFF,
+};
+
+#define VGAMEM() PADDR(arch->pcimem(0xA0000, 1<<16))
+
+#define vgai(port) inb(port)
+#define vgao(port, data) outb(port, data)
+
+extern int vgaxi(long, uchar);
+extern int vgaxo(long, uchar, uchar);
+
+/*
+ */
+typedef struct VGAdev VGAdev;
+typedef struct VGAcur VGAcur;
+typedef struct VGAscr VGAscr;
+
+struct VGAdev {
+ char* name;
+
+ void (*enable)(VGAscr*);
+ void (*disable)(VGAscr*);
+ void (*page)(VGAscr*, int);
+ void (*linear)(VGAscr*, int, int);
+ void (*drawinit)(VGAscr*);
+ int (*fill)(VGAscr*, Rectangle, ulong);
+ void (*flush)(VGAscr*, Rectangle);
+
+};
+
+struct VGAcur {
+ char* name;
+
+ void (*enable)(VGAscr*);
+ void (*disable)(VGAscr*);
+ void (*load)(VGAscr*, Cursor*);
+ int (*move)(VGAscr*, Point);
+
+ int doespanning;
+};
+
+/*
+ */
+struct VGAscr {
+ Lock devlock;
+ VGAdev* dev;
+ Pcidev* pci;
+
+ VGAcur* cur;
+ ulong storage;
+ Cursor;
+
+ int useflush;
+
+ ulong paddr; /* frame buffer */
+ void* vaddr;
+ int apsize;
+
+ ulong io; /* device specific registers */
+ ulong *mmio;
+
+ ulong colormap[Pcolours][3];
+ int palettedepth;
+
+ Memimage* gscreen;
+ Memdata* gscreendata;
+ Memsubfont* memdefont;
+
+ int (*fill)(VGAscr*, Rectangle, ulong);
+ int (*scroll)(VGAscr*, Rectangle, Rectangle);
+ void (*blank)(VGAscr*, int);
+ ulong id; /* internal identifier for driver use */
+};
+
+extern VGAscr vgascreen[];
+
+enum {
+ Backgnd = 0, /* black */
+};
+
+/* mouse.c */
+extern void mousectl(Cmdbuf*);
+
+/* screen.c */
+extern int hwaccel; /* use hw acceleration; default on */
+extern int hwblank; /* use hw blanking; default on */
+extern void addvgaseg(char*, ulong, ulong);
+extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*);
+extern void flushmemscreen(Rectangle);
+extern int cursoron(int);
+extern void cursoroff(int);
+extern void setcursor(Cursor*);
+extern int screensize(int, int, int, ulong);
+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 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;
+
+#define ishwimage(i) (vgascreen[0].gscreendata && (i)->data->bdata == vgascreen[0].gscreendata->bdata)
+
+
diff --git a/sys/src/9/alphapc/sd53c8xx.c b/sys/src/9/alphapc/sd53c8xx.c
new file mode 100755
index 000000000..b16c0a0a9
--- /dev/null
+++ b/sys/src/9/alphapc/sd53c8xx.c
@@ -0,0 +1,2261 @@
+/*
+ * NCR/Symbios/LSI Logic 53c8xx driver for Plan 9
+ * Nigel Roles (nigel@9fs.org)
+ *
+ * 27/5/02 Fixed problems with transfers >= 256 * 512
+ *
+ * 13/3/01 Fixed microcode to support targets > 7
+ *
+ * 01/12/00 Removed previous comments. Fixed a small problem in
+ * mismatch recovery for targets with synchronous offsets of >=16
+ * connected to >=875s. Thanks, Jean.
+ *
+ * Known problems
+ *
+ * Read/write mismatch recovery may fail on 53c1010s. Really need to get a manual.
+ */
+
+#define MAXTARGET 16 /* can be 8 or 16 */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "../port/sd.h"
+extern SDifc sd53c8xxifc;
+
+/**********************************/
+/* Portable configuration macros */
+/**********************************/
+
+//#define BOOTDEBUG
+//#define ASYNC_ONLY
+//#define INTERNAL_SCLK
+//#define ALWAYS_DO_WDTR
+#define WMR_DEBUG
+
+/**********************************/
+/* CPU specific macros */
+/**********************************/
+
+#define PRINTPREFIX "sd53c8xx: "
+
+#ifdef BOOTDEBUG
+
+#define KPRINT oprint
+#define IPRINT intrprint
+#define DEBUG(n) 1
+#define IFLUSH() iflush()
+
+#else
+
+static int idebug = 1;
+#define KPRINT if(0) iprint
+#define IPRINT if(idebug) iprint
+#define DEBUG(n) (0)
+#define IFLUSH()
+
+#endif /* BOOTDEBUG */
+
+/*******************************/
+/* General */
+/*******************************/
+
+#ifndef DMASEG
+#define DMASEG(x) PCIWADDR(x)
+#define legetl(x) (*(ulong*)(x))
+#define lesetl(x,v) (*(ulong*)(x) = (v))
+#define swabl(a,b,c)
+#else
+#endif /*DMASEG */
+#define DMASEG_TO_KADDR(x) KADDR((x)-PCIWINDOW)
+#define KPTR(x) ((x) == 0 ? 0 : DMASEG_TO_KADDR(x))
+
+#define MEGA 1000000L
+#ifdef INTERNAL_SCLK
+#define SCLK (33 * MEGA)
+#else
+#define SCLK (40 * MEGA)
+#endif /* INTERNAL_SCLK */
+#define ULTRA_NOCLOCKDOUBLE_SCLK (80 * MEGA)
+
+#define MAXSYNCSCSIRATE (5 * MEGA)
+#define MAXFASTSYNCSCSIRATE (10 * MEGA)
+#define MAXULTRASYNCSCSIRATE (20 * MEGA)
+#define MAXULTRA2SYNCSCSIRATE (40 * MEGA)
+#define MAXASYNCCORERATE (25 * MEGA)
+#define MAXSYNCCORERATE (25 * MEGA)
+#define MAXFASTSYNCCORERATE (50 * MEGA)
+#define MAXULTRASYNCCORERATE (80 * MEGA)
+#define MAXULTRA2SYNCCORERATE (160 * MEGA)
+
+
+#define X_MSG 1
+#define X_MSG_SDTR 1
+#define X_MSG_WDTR 3
+
+struct na_patch {
+ unsigned lwoff;
+ unsigned char type;
+};
+
+typedef struct Ncr {
+ uchar scntl0; /* 00 */
+ uchar scntl1;
+ uchar scntl2;
+ uchar scntl3;
+
+ uchar scid; /* 04 */
+ uchar sxfer;
+ uchar sdid;
+ uchar gpreg;
+
+ uchar sfbr; /* 08 */
+ uchar socl;
+ uchar ssid;
+ uchar sbcl;
+
+ uchar dstat; /* 0c */
+ uchar sstat0;
+ uchar sstat1;
+ uchar sstat2;
+
+ uchar dsa[4]; /* 10 */
+
+ uchar istat; /* 14 */
+ uchar istatpad[3];
+
+ uchar ctest0; /* 18 */
+ uchar ctest1;
+ uchar ctest2;
+ uchar ctest3;
+
+ uchar temp[4]; /* 1c */
+
+ uchar dfifo; /* 20 */
+ uchar ctest4;
+ uchar ctest5;
+ uchar ctest6;
+
+ uchar dbc[3]; /* 24 */
+ uchar dcmd; /* 27 */
+
+ uchar dnad[4]; /* 28 */
+ uchar dsp[4]; /* 2c */
+ uchar dsps[4]; /* 30 */
+
+ uchar scratcha[4]; /* 34 */
+
+ uchar dmode; /* 38 */
+ uchar dien;
+ uchar dwt;
+ uchar dcntl;
+
+ uchar adder[4]; /* 3c */
+
+ uchar sien0; /* 40 */
+ uchar sien1;
+ uchar sist0;
+ uchar sist1;
+
+ uchar slpar; /* 44 */
+ uchar slparpad0;
+ uchar macntl;
+ uchar gpcntl;
+
+ uchar stime0; /* 48 */
+ uchar stime1;
+ uchar respid;
+ uchar respidpad0;
+
+ uchar stest0; /* 4c */
+ uchar stest1;
+ uchar stest2;
+ uchar stest3;
+
+ uchar sidl; /* 50 */
+ uchar sidlpad[3];
+
+ uchar sodl; /* 54 */
+ uchar sodlpad[3];
+
+ uchar sbdl; /* 58 */
+ uchar sbdlpad[3];
+
+ uchar scratchb[4]; /* 5c */
+} Ncr;
+
+typedef struct Movedata {
+ uchar dbc[4];
+ uchar pa[4];
+} Movedata;
+
+typedef enum NegoState {
+ NeitherDone, WideInit, WideResponse, WideDone,
+ SyncInit, SyncResponse, BothDone
+} NegoState;
+
+typedef enum State {
+ Allocated, Queued, Active, Done
+} State;
+
+typedef struct Dsa {
+ uchar stateb;
+ uchar result;
+ uchar dmablks;
+ uchar flag; /* setbyte(state,3,...) */
+
+ union {
+ ulong dmancr; /* For block transfer: NCR order (little-endian) */
+ uchar dmaaddr[4];
+ };
+
+ uchar target; /* Target */
+ uchar pad0[3];
+
+ uchar lun; /* Logical Unit Number */
+ uchar pad1[3];
+
+ uchar scntl3;
+ uchar sxfer;
+ uchar pad2[2];
+
+ uchar next[4]; /* chaining for SCRIPT (NCR byte order) */
+ struct Dsa *freechain; /* chaining for freelist */
+ Rendez;
+ uchar scsi_id_buf[4];
+ Movedata msg_out_buf;
+ Movedata cmd_buf;
+ Movedata data_buf;
+ Movedata status_buf;
+ uchar msg_out[10]; /* enough to include SDTR */
+ uchar status;
+ int p9status;
+ uchar parityerror;
+} Dsa;
+
+typedef enum Feature {
+ BigFifo = 1, /* 536 byte fifo */
+ BurstOpCodeFetch = 2, /* burst fetch opcodes */
+ Prefetch = 4, /* prefetch 8 longwords */
+ LocalRAM = 8, /* 4K longwords of local RAM */
+ Differential = 16, /* Differential support */
+ Wide = 32, /* Wide capable */
+ Ultra = 64, /* Ultra capable */
+ ClockDouble = 128, /* Has clock doubler */
+ ClockQuad = 256, /* Has clock quadrupler (same as Ultra2) */
+ Ultra2 = 256,
+} Feature;
+
+typedef enum Burst {
+ Burst2 = 0,
+ Burst4 = 1,
+ Burst8 = 2,
+ Burst16 = 3,
+ Burst32 = 4,
+ Burst64 = 5,
+ Burst128 = 6
+} Burst;
+
+typedef struct Variant {
+ ushort did;
+ uchar maxrid; /* maximum allowed revision ID */
+ char *name;
+ Burst burst; /* codings for max burst */
+ uchar maxsyncoff; /* max synchronous offset */
+ uchar registers; /* number of 32 bit registers */
+ unsigned feature;
+} Variant;
+
+static unsigned char cf2[] = { 6, 2, 3, 4, 6, 8, 12, 16 };
+#define NULTRA2SCF (sizeof(cf2)/sizeof(cf2[0]))
+#define NULTRASCF (NULTRA2SCF - 2)
+#define NSCF (NULTRASCF - 1)
+
+typedef struct Controller {
+ Lock;
+ struct {
+ uchar scntl3;
+ uchar stest2;
+ } bios;
+ uchar synctab[NULTRA2SCF - 1][8];/* table of legal tpfs */
+ NegoState s[MAXTARGET];
+ uchar scntl3[MAXTARGET];
+ uchar sxfer[MAXTARGET];
+ uchar cap[MAXTARGET]; /* capabilities byte from Identify */
+ ushort capvalid; /* bit per target for validity of cap[] */
+ ushort wide; /* bit per target set if wide negotiated */
+ ulong sclk; /* clock speed of controller */
+ uchar clockmult; /* set by synctabinit */
+ uchar ccf; /* CCF bits */
+ uchar tpf; /* best tpf value for this controller */
+ uchar feature; /* requested features */
+ int running; /* is the script processor running? */
+ int ssm; /* single step mode */
+ Ncr *n; /* pointer to registers */
+ Variant *v; /* pointer to variant type */
+ ulong *script; /* where the real script is */
+ ulong scriptpa; /* where the real script is */
+ Pcidev* pcidev;
+ SDev* sdev;
+
+ struct {
+ Lock;
+ uchar head[4]; /* head of free list (NCR byte order) */
+ Dsa *freechain;
+ } dsalist;
+
+ QLock q[MAXTARGET]; /* queues for each target */
+} Controller;
+
+#define SYNCOFFMASK(c) (((c)->v->maxsyncoff * 2) - 1)
+#define SSIDMASK(c) (((c)->v->feature & Wide) ? 15 : 7)
+
+/* ISTAT */
+enum { Abrt = 0x80, Srst = 0x40, Sigp = 0x20, Sem = 0x10, Con = 0x08, Intf = 0x04, Sip = 0x02, Dip = 0x01 };
+
+/* DSTAT */
+enum { Dfe = 0x80, Mdpe = 0x40, Bf = 0x20, Abrted = 0x10, Ssi = 0x08, Sir = 0x04, Iid = 0x01 };
+
+/* SSTAT */
+enum { DataOut, DataIn, Cmd, Status, ReservedOut, ReservedIn, MessageOut, MessageIn };
+
+static void setmovedata(Movedata*, ulong, ulong);
+static void advancedata(Movedata*, long);
+static int bios_set_differential(Controller *c);
+
+static char *phase[] = {
+ "data out", "data in", "command", "status",
+ "reserved out", "reserved in", "message out", "message in"
+};
+
+#ifdef BOOTDEBUG
+#define DEBUGSIZE 10240
+char debugbuf[DEBUGSIZE];
+char *debuglast;
+
+static void
+intrprint(char *format, ...)
+{
+ if (debuglast == 0)
+ debuglast = debugbuf;
+ debuglast = vseprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
+}
+
+static void
+iflush()
+{
+ int s;
+ char *endp;
+ s = splhi();
+ if (debuglast == 0)
+ debuglast = debugbuf;
+ if (debuglast == debugbuf) {
+ splx(s);
+ return;
+ }
+ endp = debuglast;
+ splx(s);
+ screenputs(debugbuf, endp - debugbuf);
+ s = splhi();
+ memmove(debugbuf, endp, debuglast - endp);
+ debuglast -= endp - debugbuf;
+ splx(s);
+}
+
+static void
+oprint(char *format, ...)
+{
+ int s;
+
+ iflush();
+ s = splhi();
+ if (debuglast == 0)
+ debuglast = debugbuf;
+ debuglast = vseprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
+ splx(s);
+ iflush();
+}
+#endif
+
+#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) {
+ 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;
+ return d;
+}
+
+static void
+dsafree(Controller *c, Dsa *d)
+{
+ ilock(&c->dsalist);
+ d->freechain = c->dsalist.freechain;
+ c->dsalist.freechain = d;
+ lesetl(&d->stateb, A_STATE_FREE);
+ 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 != dsaend; d = KPTR(legetl(d->next))) {
+ if (d->target != 0xff && d->target != target)
+ continue;
+ if (lun != 0xff && d->lun != lun)
+ continue;
+ if (state != 0xff && d->stateb != state)
+ continue;
+ break;
+ }
+ return d;
+}
+
+static void
+dumpncrregs(Controller *c, int intr)
+{
+ int i;
+ Ncr *n = c->n;
+ int depth = c->v->registers / 4;
+
+ if (intr) {
+ IPRINT("sa = %.8lux\n", c->scriptpa);
+ }
+ else {
+ KPRINT("sa = %.8lux\n", c->scriptpa);
+ }
+ for (i = 0; i < depth; i++) {
+ int j;
+ for (j = 0; j < 4; j++) {
+ int k = j * depth + i;
+ uchar *p;
+
+ /* display little-endian to make 32-bit values readable */
+ p = (uchar*)n+k*4;
+ if (intr) {
+ IPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
+ }
+ else {
+ KPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
+ }
+ USED(p);
+ }
+ if (intr) {
+ IPRINT("\n");
+ }
+ else {
+ KPRINT("\n");
+ }
+ }
+}
+
+static int
+chooserate(Controller *c, int tpf, int *scfp, int *xferpp)
+{
+ /* find lowest entry >= tpf */
+ int besttpf = 1000;
+ int bestscfi = 0;
+ int bestxferp = 0;
+ int scf, xferp;
+ int maxscf;
+
+ if (c->v->feature & Ultra2)
+ maxscf = NULTRA2SCF;
+ else if (c->v->feature & Ultra)
+ maxscf = NULTRASCF;
+ else
+ maxscf = NSCF;
+
+ /*
+ * search large clock factors first since this should
+ * result in more reliable transfers
+ */
+ for (scf = maxscf; scf >= 1; scf--) {
+ for (xferp = 0; xferp < 8; xferp++) {
+ unsigned char v = c->synctab[scf - 1][xferp];
+ if (v == 0)
+ continue;
+ if (v >= tpf && v < besttpf) {
+ besttpf = v;
+ bestscfi = scf;
+ bestxferp = xferp;
+ }
+ }
+ }
+ if (besttpf == 1000)
+ return 0;
+ if (scfp)
+ *scfp = bestscfi;
+ if (xferpp)
+ *xferpp = bestxferp;
+ return besttpf;
+}
+
+static void
+synctabinit(Controller *c)
+{
+ int scf;
+ unsigned long scsilimit;
+ int xferp;
+ unsigned long cr, sr;
+ int tpf;
+ int fast;
+ int maxscf;
+
+ if (c->v->feature & Ultra2)
+ maxscf = NULTRA2SCF;
+ else if (c->v->feature & Ultra)
+ maxscf = NULTRASCF;
+ else
+ maxscf = NSCF;
+
+ /*
+ * for chips with no clock doubler, but Ultra capable (e.g. 860, or interestingly the
+ * first spin of the 875), assume 80MHz
+ * otherwise use the internal (33 Mhz) or external (40MHz) default
+ */
+
+ if ((c->v->feature & Ultra) != 0 && (c->v->feature & (ClockDouble | ClockQuad)) == 0)
+ c->sclk = ULTRA_NOCLOCKDOUBLE_SCLK;
+ else
+ c->sclk = SCLK;
+
+ /*
+ * otherwise, if the chip is Ultra capable, but has a slow(ish) clock,
+ * invoke the doubler
+ */
+
+ if (SCLK <= 40000000) {
+ if (c->v->feature & ClockDouble) {
+ c->sclk *= 2;
+ c->clockmult = 1;
+ }
+ else if (c->v->feature & ClockQuad) {
+ c->sclk *= 4;
+ c->clockmult = 1;
+ }
+ else
+ c->clockmult = 0;
+ }
+ else
+ c->clockmult = 0;
+
+ /* derive CCF from sclk */
+ /* woebetide anyone with SCLK < 16.7 or > 80MHz */
+ if (c->sclk <= 25 * MEGA)
+ c->ccf = 1;
+ else if (c->sclk <= 3750000)
+ c->ccf = 2;
+ else if (c->sclk <= 50 * MEGA)
+ c->ccf = 3;
+ else if (c->sclk <= 75 * MEGA)
+ c->ccf = 4;
+ else if ((c->v->feature & ClockDouble) && c->sclk <= 80 * MEGA)
+ c->ccf = 5;
+ else if ((c->v->feature & ClockQuad) && c->sclk <= 120 * MEGA)
+ c->ccf = 6;
+ else if ((c->v->feature & ClockQuad) && c->sclk <= 160 * MEGA)
+ c->ccf = 7;
+
+ for (scf = 1; scf < maxscf; scf++) {
+ /* check for legal core rate */
+ /* round up so we run slower for safety */
+ cr = (c->sclk * 2 + cf2[scf] - 1) / cf2[scf];
+ if (cr <= MAXSYNCCORERATE) {
+ scsilimit = MAXSYNCSCSIRATE;
+ fast = 0;
+ }
+ else if (cr <= MAXFASTSYNCCORERATE) {
+ scsilimit = MAXFASTSYNCSCSIRATE;
+ fast = 1;
+ }
+ else if ((c->v->feature & Ultra) && cr <= MAXULTRASYNCCORERATE) {
+ scsilimit = MAXULTRASYNCSCSIRATE;
+ fast = 2;
+ }
+ else if ((c->v->feature & Ultra2) && cr <= MAXULTRA2SYNCCORERATE) {
+ scsilimit = MAXULTRA2SYNCSCSIRATE;
+ fast = 3;
+ }
+ else
+ continue;
+ for (xferp = 11; xferp >= 4; xferp--) {
+ int ok;
+ int tp;
+ /* calculate scsi rate - round up again */
+ /* start from sclk for accuracy */
+ int totaldivide = xferp * cf2[scf];
+ sr = (c->sclk * 2 + totaldivide - 1) / totaldivide;
+ if (sr > scsilimit)
+ break;
+ /*
+ * now work out transfer period
+ * round down now so that period is pessimistic
+ */
+ tp = (MEGA * 1000) / sr;
+ /*
+ * bounds check it
+ */
+ if (tp < 25 || tp > 255 * 4)
+ continue;
+ /*
+ * spot stupid special case for Ultra or Ultra2
+ * while working out factor
+ */
+ if (tp == 25)
+ tpf = 10;
+ else if (tp == 50)
+ tpf = 12;
+ else if (tp < 52)
+ continue;
+ else
+ tpf = tp / 4;
+ /*
+ * now check tpf looks sensible
+ * given core rate
+ */
+ switch (fast) {
+ case 0:
+ /* scf must be ccf for SCSI 1 */
+ ok = tpf >= 50 && scf == c->ccf;
+ break;
+ case 1:
+ ok = tpf >= 25 && tpf < 50;
+ break;
+ case 2:
+ /*
+ * must use xferp of 4, or 5 at a pinch
+ * for an Ultra transfer
+ */
+ ok = xferp <= 5 && tpf >= 12 && tpf < 25;
+ break;
+ case 3:
+ ok = xferp == 4 && (tpf == 10 || tpf == 11);
+ break;
+ default:
+ ok = 0;
+ }
+ if (!ok)
+ continue;
+ c->synctab[scf - 1][xferp - 4] = tpf;
+ }
+ }
+
+#ifndef NO_ULTRA2
+ if (c->v->feature & Ultra2)
+ tpf = 10;
+ else
+#endif
+ if (c->v->feature & Ultra)
+ tpf = 12;
+ else
+ tpf = 25;
+ for (; tpf < 256; tpf++) {
+ if (chooserate(c, tpf, &scf, &xferp) == tpf) {
+ unsigned tp = tpf == 10 ? 25 : (tpf == 12 ? 50 : tpf * 4);
+ unsigned long khz = (MEGA + tp - 1) / (tp);
+ KPRINT(PRINTPREFIX "tpf=%d scf=%d.%.1d xferp=%d mhz=%ld.%.3ld\n",
+ tpf, cf2[scf] / 2, (cf2[scf] & 1) ? 5 : 0,
+ xferp + 4, khz / 1000, khz % 1000);
+ USED(khz);
+ if (c->tpf == 0)
+ c->tpf = tpf; /* note lowest value for controller */
+ }
+ }
+}
+
+static void
+synctodsa(Dsa *dsa, Controller *c)
+{
+/*
+ KPRINT("synctodsa(dsa=%lux, target=%d, scntl3=%.2lx sxfer=%.2x)\n",
+ dsa, dsa->target, c->scntl3[dsa->target], c->sxfer[dsa->target]);
+*/
+ dsa->scntl3 = c->scntl3[dsa->target];
+ dsa->sxfer = c->sxfer[dsa->target];
+}
+
+static void
+setsync(Dsa *dsa, Controller *c, int target, uchar ultra, uchar scf, uchar xferp, uchar reqack)
+{
+ c->scntl3[target] =
+ (c->scntl3[target] & 0x08) | (((scf << 4) | c->ccf | (ultra << 7)) & ~0x08);
+ c->sxfer[target] = (xferp << 5) | reqack;
+ c->s[target] = BothDone;
+ if (dsa) {
+ synctodsa(dsa, c);
+ c->n->scntl3 = c->scntl3[target];
+ c->n->sxfer = c->sxfer[target];
+ }
+}
+
+static void
+setasync(Dsa *dsa, Controller *c, int target)
+{
+ setsync(dsa, c, target, 0, c->ccf, 0, 0);
+}
+
+static void
+setwide(Dsa *dsa, Controller *c, int target, uchar wide)
+{
+ c->scntl3[target] = wide ? (1 << 3) : 0;
+ setasync(dsa, c, target);
+ c->s[target] = WideDone;
+}
+
+static int
+buildsdtrmsg(uchar *buf, uchar tpf, uchar offset)
+{
+ *buf++ = X_MSG;
+ *buf++ = 3;
+ *buf++ = X_MSG_SDTR;
+ *buf++ = tpf;
+ *buf = offset;
+ return 5;
+}
+
+static int
+buildwdtrmsg(uchar *buf, uchar expo)
+{
+ *buf++ = X_MSG;
+ *buf++ = 2;
+ *buf++ = X_MSG_WDTR;
+ *buf = expo;
+ return 4;
+}
+
+static void
+start(Controller *c, long entry)
+{
+ ulong p;
+
+ if (c->running)
+ panic(PRINTPREFIX "start called while running");
+ 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 */
+}
+
+static void
+ncrcontinue(Controller *c)
+{
+ if (c->running)
+ panic(PRINTPREFIX "ncrcontinue called while running");
+ /* set the start DMA bit to continue execution */
+ c->running = 1;
+ coherence();
+ c->n->dcntl |= 0x4;
+}
+
+static void
+softreset(Controller *c)
+{
+ Ncr *n = c->n;
+
+ n->istat = Srst; /* software reset */
+ n->istat = 0;
+ /* general initialisation */
+ n->scid = (1 << 6) | 7; /* respond to reselect, ID 7 */
+ n->respid = 1 << 7; /* response ID = 7 */
+
+#ifdef INTERNAL_SCLK
+ n->stest1 = 0x80; /* disable external scsi clock */
+#else
+ n->stest1 = 0x00;
+#endif
+
+ n->stime0 = 0xdd; /* about 0.5 second timeout on each device */
+ n->scntl0 |= 0x8; /* Enable parity checking */
+
+ /* continued setup */
+ n->sien0 = 0x8f;
+ n->sien1 = 0x04;
+ n->dien = 0x7d;
+ n->stest3 = 0x80; /* TolerANT enable */
+ c->running = 0;
+
+ if (c->v->feature & BigFifo)
+ n->ctest5 = (1 << 5);
+ n->dmode = c->v->burst << 6; /* set burst length bits */
+ if (c->v->burst & 4)
+ n->ctest5 |= (1 << 2); /* including overflow into ctest5 bit 2 */
+ if (c->v->feature & Prefetch)
+ n->dcntl |= (1 << 5); /* prefetch enable */
+ else if (c->v->feature & BurstOpCodeFetch)
+ n->dmode |= (1 << 1); /* burst opcode fetch */
+ if (c->v->feature & Differential) {
+ /* chip capable */
+ if ((c->feature & Differential) || bios_set_differential(c)) {
+ /* user enabled, or some evidence bios set differential */
+ if (n->sstat2 & (1 << 2))
+ print(PRINTPREFIX "can't go differential; wrong cable\n");
+ else {
+ n->stest2 = (1 << 5);
+ print(PRINTPREFIX "differential mode set\n");
+ }
+ }
+ }
+ if (c->clockmult) {
+ n->stest1 |= (1 << 3); /* power up doubler */
+ delay(2);
+ n->stest3 |= (1 << 5); /* stop clock */
+ n->stest1 |= (1 << 2); /* enable doubler */
+ n->stest3 &= ~(1 << 5); /* start clock */
+ /* pray */
+ }
+}
+
+static void
+msgsm(Dsa *dsa, Controller *c, int msg, int *cont, int *wakeme)
+{
+ uchar histpf, hisreqack;
+ int tpf;
+ int scf, xferp;
+ int len;
+
+ Ncr *n = c->n;
+
+ switch (c->s[dsa->target]) {
+ case SyncInit:
+ switch (msg) {
+ case A_SIR_MSG_SDTR:
+ /* reply to my SDTR */
+ histpf = n->scratcha[2];
+ hisreqack = n->scratcha[3];
+ KPRINT(PRINTPREFIX "%d: SDTN response %d %d\n",
+ dsa->target, histpf, hisreqack);
+
+ if (hisreqack == 0)
+ setasync(dsa, c, dsa->target);
+ else {
+ /* hisreqack should be <= c->v->maxsyncoff */
+ tpf = chooserate(c, histpf, &scf, &xferp);
+ KPRINT(PRINTPREFIX "%d: SDTN: using %d %d\n",
+ dsa->target, tpf, hisreqack);
+ setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
+ }
+ *cont = -2;
+ return;
+ case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
+ /* target ignored ATN for message after IDENTIFY - not SCSI-II */
+ KPRINT(PRINTPREFIX "%d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
+ KPRINT(PRINTPREFIX "%d: SDTN: async\n", dsa->target);
+ setasync(dsa, c, dsa->target);
+ *cont = E_to_decisions;
+ return;
+ case A_SIR_MSG_REJECT:
+ /* rejection of my SDTR */
+ KPRINT(PRINTPREFIX "%d: SDTN: rejected SDTR\n", dsa->target);
+ //async:
+ KPRINT(PRINTPREFIX "%d: SDTN: async\n", dsa->target);
+ setasync(dsa, c, dsa->target);
+ *cont = -2;
+ return;
+ }
+ break;
+ case WideInit:
+ switch (msg) {
+ case A_SIR_MSG_WDTR:
+ /* reply to my WDTR */
+ KPRINT(PRINTPREFIX "%d: WDTN: response %d\n",
+ dsa->target, n->scratcha[2]);
+ setwide(dsa, c, dsa->target, n->scratcha[2]);
+ *cont = -2;
+ return;
+ case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
+ /* target ignored ATN for message after IDENTIFY - not SCSI-II */
+ KPRINT(PRINTPREFIX "%d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
+ setwide(dsa, c, dsa->target, 0);
+ *cont = E_to_decisions;
+ return;
+ case A_SIR_MSG_REJECT:
+ /* rejection of my SDTR */
+ KPRINT(PRINTPREFIX "%d: WDTN: rejected WDTR\n", dsa->target);
+ setwide(dsa, c, dsa->target, 0);
+ *cont = -2;
+ return;
+ }
+ break;
+
+ case NeitherDone:
+ case WideDone:
+ case BothDone:
+ switch (msg) {
+ case A_SIR_MSG_WDTR: {
+ uchar hiswide, mywide;
+ hiswide = n->scratcha[2];
+ mywide = (c->v->feature & Wide) != 0;
+ KPRINT(PRINTPREFIX "%d: WDTN: target init %d\n",
+ dsa->target, hiswide);
+ if (hiswide < mywide)
+ mywide = hiswide;
+ KPRINT(PRINTPREFIX "%d: WDTN: responding %d\n",
+ dsa->target, mywide);
+ setwide(dsa, c, dsa->target, mywide);
+ len = buildwdtrmsg(dsa->msg_out, mywide);
+ setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
+ *cont = E_response;
+ c->s[dsa->target] = WideResponse;
+ return;
+ }
+ case A_SIR_MSG_SDTR:
+#ifdef ASYNC_ONLY
+ *cont = E_reject;
+ return;
+#else
+ /* target decides to renegotiate */
+ histpf = n->scratcha[2];
+ hisreqack = n->scratcha[3];
+ KPRINT(PRINTPREFIX "%d: SDTN: target init %d %d\n",
+ dsa->target, histpf, hisreqack);
+ if (hisreqack == 0) {
+ /* he wants asynchronous */
+ setasync(dsa, c, dsa->target);
+ tpf = 0;
+ }
+ else {
+ /* he wants synchronous */
+ tpf = chooserate(c, histpf, &scf, &xferp);
+ if (hisreqack > c->v->maxsyncoff)
+ hisreqack = c->v->maxsyncoff;
+ KPRINT(PRINTPREFIX "%d: using %d %d\n",
+ dsa->target, tpf, hisreqack);
+ setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
+ }
+ /* build my SDTR message */
+ len = buildsdtrmsg(dsa->msg_out, tpf, hisreqack);
+ setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
+ *cont = E_response;
+ c->s[dsa->target] = SyncResponse;
+ return;
+#endif
+ }
+ break;
+ case WideResponse:
+ switch (msg) {
+ case A_SIR_EV_RESPONSE_OK:
+ c->s[dsa->target] = WideDone;
+ KPRINT(PRINTPREFIX "%d: WDTN: response accepted\n", dsa->target);
+ *cont = -2;
+ return;
+ case A_SIR_MSG_REJECT:
+ setwide(dsa, c, dsa->target, 0);
+ KPRINT(PRINTPREFIX "%d: WDTN: response REJECTed\n", dsa->target);
+ *cont = -2;
+ return;
+ }
+ break;
+ case SyncResponse:
+ switch (msg) {
+ case A_SIR_EV_RESPONSE_OK:
+ c->s[dsa->target] = BothDone;
+ KPRINT(PRINTPREFIX "%d: SDTN: response accepted (%s)\n",
+ dsa->target, phase[n->sstat1 & 7]);
+ *cont = -2;
+ return; /* chf */
+ case A_SIR_MSG_REJECT:
+ setasync(dsa, c, dsa->target);
+ KPRINT(PRINTPREFIX "%d: SDTN: response REJECTed\n", dsa->target);
+ *cont = -2;
+ return;
+ }
+ break;
+ }
+ KPRINT(PRINTPREFIX "%d: msgsm: state %d msg %d\n",
+ dsa->target, c->s[dsa->target], msg);
+ *wakeme = 1;
+ return;
+}
+
+static void
+calcblockdma(Dsa *d, ulong base, ulong count)
+{
+ ulong blocks;
+ if (DEBUG(3))
+ blocks = 0;
+ else {
+ blocks = count / A_BSIZE;
+ if (blocks > 255)
+ blocks = 255;
+ }
+ d->dmablks = blocks;
+ d->dmaaddr[0] = base;
+ d->dmaaddr[1] = base >> 8;
+ d->dmaaddr[2] = base >> 16;
+ d->dmaaddr[3] = base >> 24;
+ setmovedata(&d->data_buf, base + blocks * A_BSIZE, count - blocks * A_BSIZE);
+ d->flag = legetl(d->data_buf.dbc) == 0;
+}
+
+static ulong
+read_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa)
+{
+ ulong dbc;
+ uchar dfifo = n->dfifo;
+ int inchip;
+
+ dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
+ if (n->ctest5 & (1 << 5))
+ inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
+ else
+ inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
+ if (inchip) {
+ IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: DMA FIFO = %d\n",
+ dsa->target, dsa->lun, inchip);
+ }
+ if (n->sxfer & SYNCOFFMASK(c)) {
+ /* SCSI FIFO */
+ uchar fifo = n->sstat1 >> 4;
+ if (c->v->maxsyncoff > 8)
+ fifo |= (n->sstat2 & (1 << 4));
+ if (fifo) {
+ inchip += fifo;
+ IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SCSI FIFO = %d\n",
+ dsa->target, dsa->lun, fifo);
+ }
+ }
+ else {
+ if (n->sstat0 & (1 << 7)) {
+ inchip++;
+ IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL full\n",
+ dsa->target, dsa->lun);
+ }
+ if (n->sstat2 & (1 << 7)) {
+ inchip++;
+ IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL msb full\n",
+ dsa->target, dsa->lun);
+ }
+ }
+ USED(inchip);
+ return dbc;
+}
+
+static ulong
+write_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa)
+{
+ ulong dbc;
+ uchar dfifo = n->dfifo;
+ int inchip;
+
+ dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
+ USED(dsa);
+ if (n->ctest5 & (1 << 5))
+ inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
+ else
+ inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
+#ifdef WMR_DEBUG
+ if (inchip) {
+ IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: DMA FIFO = %d\n",
+ dsa->target, dsa->lun, inchip);
+ }
+#endif
+ if (n->sstat0 & (1 << 5)) {
+ inchip++;
+#ifdef WMR_DEBUG
+ IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun);
+#endif
+ }
+ if (n->sstat2 & (1 << 5)) {
+ inchip++;
+#ifdef WMR_DEBUG
+ IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun);
+#endif
+ }
+ if (n->sxfer & SYNCOFFMASK(c)) {
+ /* synchronous SODR */
+ if (n->sstat0 & (1 << 6)) {
+ inchip++;
+#ifdef WMR_DEBUG
+ IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODR full\n",
+ dsa->target, dsa->lun);
+#endif
+ }
+ if (n->sstat2 & (1 << 6)) {
+ inchip++;
+#ifdef WMR_DEBUG
+ IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODR msb full\n",
+ dsa->target, dsa->lun);
+#endif
+ }
+ }
+ /* clear the dma fifo */
+ n->ctest3 |= (1 << 2);
+ /* wait till done */
+ while ((n->dstat & Dfe) == 0)
+ ;
+ return dbc + inchip;
+}
+
+static void
+sd53c8xxinterrupt(Ureg *ur, void *a)
+{
+ uchar istat;
+ ushort sist;
+ uchar dstat;
+ int wakeme = 0;
+ int cont = -1;
+ Dsa *dsa;
+ ulong dsapa;
+ Controller *c = a;
+ Ncr *n = c->n;
+
+ USED(ur);
+ if (DEBUG(1)) {
+ IPRINT(PRINTPREFIX "int\n");
+ }
+ ilock(c);
+ istat = n->istat;
+ if (istat & Intf) {
+ Dsa *d;
+ int wokesomething = 0;
+ if (DEBUG(1)) {
+ IPRINT(PRINTPREFIX "Intfly\n");
+ }
+ n->istat = Intf;
+ /* search for structures in A_STATE_DONE */
+ 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)) {
+ IPRINT(PRINTPREFIX "waking up dsa %lux\n", (ulong)d);
+ }
+ wakeup(d);
+ wokesomething = 1;
+ }
+ }
+ if (!wokesomething) {
+ IPRINT(PRINTPREFIX "nothing to wake up\n");
+ }
+ }
+
+ if ((istat & (Sip | Dip)) == 0) {
+ if (DEBUG(1)) {
+ IPRINT(PRINTPREFIX "int end %x\n", istat);
+ }
+ iunlock(c);
+ return;
+ }
+
+ sist = (n->sist1<<8)|n->sist0; /* BUG? can two-byte read be inconsistent? */
+ dstat = n->dstat;
+ 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)) {
+ IPRINT("sist = %.4x\n", sist);
+ }
+ if (sist & 0x80) {
+ ulong addr;
+ ulong sa;
+ ulong dbc;
+ ulong tbc;
+ int dmablks;
+ ulong dmaaddr;
+
+ addr = legetl(n->dsp);
+ sa = addr - c->scriptpa;
+ if (DEBUG(1) || DEBUG(2)) {
+ IPRINT(PRINTPREFIX "%d/%d: Phase Mismatch sa=%.8lux\n",
+ dsa->target, dsa->lun, sa);
+ }
+ /*
+ * now recover
+ */
+ if (sa == E_data_in_mismatch) {
+ /*
+ * though this is a failure in the residue, there may have been blocks
+ * as well. if so, dmablks will not have been zeroed, since the state
+ * was not saved by the microcode.
+ */
+ dbc = read_mismatch_recover(c, n, dsa);
+ tbc = legetl(dsa->data_buf.dbc) - dbc;
+ dsa->dmablks = 0;
+ n->scratcha[2] = 0;
+ advancedata(&dsa->data_buf, tbc);
+ if (DEBUG(1) || DEBUG(2)) {
+ IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n",
+ dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
+ }
+ cont = E_data_mismatch_recover;
+ }
+ else if (sa == E_data_in_block_mismatch) {
+ dbc = read_mismatch_recover(c, n, dsa);
+ tbc = A_BSIZE - dbc;
+ /* recover current state from registers */
+ dmablks = n->scratcha[2];
+ dmaaddr = legetl(n->scratchb);
+ /* we have got to dmaaddr + tbc */
+ /* we have dmablks * A_BSIZE - tbc + residue left to do */
+ /* so remaining transfer is */
+ IPRINT("in_block_mismatch: dmaaddr = 0x%lux tbc=%lud dmablks=%d\n",
+ dmaaddr, tbc, dmablks);
+ calcblockdma(dsa, dmaaddr + tbc,
+ dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
+ /* copy changes into scratch registers */
+ IPRINT("recalc: dmablks %d dmaaddr 0x%lx pa 0x%lx dbc %ld\n",
+ dsa->dmablks, legetl(dsa->dmaaddr),
+ legetl(dsa->data_buf.pa), legetl(dsa->data_buf.dbc));
+ n->scratcha[2] = dsa->dmablks;
+ lesetl(n->scratchb, dsa->dmancr);
+ cont = E_data_block_mismatch_recover;
+ }
+ else if (sa == E_data_out_mismatch) {
+ dbc = write_mismatch_recover(c, n, dsa);
+ tbc = legetl(dsa->data_buf.dbc) - dbc;
+ dsa->dmablks = 0;
+ n->scratcha[2] = 0;
+ advancedata(&dsa->data_buf, tbc);
+ if (DEBUG(1) || DEBUG(2)) {
+ IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n",
+ dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
+ }
+ cont = E_data_mismatch_recover;
+ }
+ else if (sa == E_data_out_block_mismatch) {
+ dbc = write_mismatch_recover(c, n, dsa);
+ tbc = legetl(dsa->data_buf.dbc) - dbc;
+ /* recover current state from registers */
+ dmablks = n->scratcha[2];
+ dmaaddr = legetl(n->scratchb);
+ /* we have got to dmaaddr + tbc */
+ /* we have dmablks blocks - tbc + residue left to do */
+ /* so remaining transfer is */
+ IPRINT("out_block_mismatch: dmaaddr = %lux tbc=%lud dmablks=%d\n",
+ dmaaddr, tbc, dmablks);
+ calcblockdma(dsa, dmaaddr + tbc,
+ dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
+ /* copy changes into scratch registers */
+ n->scratcha[2] = dsa->dmablks;
+ lesetl(n->scratchb, dsa->dmancr);
+ cont = E_data_block_mismatch_recover;
+ }
+ else if (sa == E_id_out_mismatch) {
+ /*
+ * target switched phases while attention held during
+ * message out. The possibilities are:
+ * 1. It didn't like the last message. This is indicated
+ * by the new phase being message_in. Use script to recover
+ *
+ * 2. It's not SCSI-II compliant. The new phase will be other
+ * than message_in. We should also indicate that the device
+ * is asynchronous, if it's the SDTR that got ignored
+ *
+ * For now, if the phase switch is not to message_in, and
+ * and it happens after IDENTIFY and before SDTR, we
+ * notify the negotiation state machine.
+ */
+ ulong lim = legetl(dsa->msg_out_buf.dbc);
+ uchar p = n->sstat1 & 7;
+ dbc = write_mismatch_recover(c, n, dsa);
+ tbc = lim - dbc;
+ IPRINT(PRINTPREFIX "%d/%d: msg_out_mismatch: %lud/%lud sent, phase %s\n",
+ dsa->target, dsa->lun, tbc, lim, phase[p]);
+ if (p != MessageIn && tbc == 1) {
+ msgsm(dsa, c, A_SIR_EV_PHASE_SWITCH_AFTER_ID, &cont, &wakeme);
+ }
+ else
+ cont = E_id_out_mismatch_recover;
+ }
+ else if (sa == E_cmd_out_mismatch) {
+ /*
+ * probably the command count is longer than the device wants ...
+ */
+ ulong lim = legetl(dsa->cmd_buf.dbc);
+ uchar p = n->sstat1 & 7;
+ dbc = write_mismatch_recover(c, n, dsa);
+ tbc = lim - dbc;
+ IPRINT(PRINTPREFIX "%d/%d: cmd_out_mismatch: %lud/%lud sent, phase %s\n",
+ dsa->target, dsa->lun, tbc, lim, phase[p]);
+ USED(p, tbc);
+ cont = E_to_decisions;
+ }
+ else {
+ IPRINT(PRINTPREFIX "%d/%d: ma sa=%.8lux wanted=%s got=%s\n",
+ dsa->target, dsa->lun, sa,
+ phase[n->dcmd & 7],
+ phase[n->sstat1 & 7]);
+ dumpncrregs(c, 1);
+ dsa->p9status = SDeio; /* chf */
+ wakeme = 1;
+ }
+ }
+ /*else*/ if (sist & 0x400) {
+ if (DEBUG(0)) {
+ IPRINT(PRINTPREFIX "%d/%d Sto\n", dsa->target, dsa->lun);
+ }
+ dsa->p9status = SDtimeout;
+ dsa->stateb = A_STATE_DONE;
+ coherence();
+ softreset(c);
+ cont = E_issue_check;
+ wakeme = 1;
+ }
+ if (sist & 0x1) {
+ IPRINT(PRINTPREFIX "%d/%d: parity error\n", dsa->target, dsa->lun);
+ dsa->parityerror = 1;
+ }
+ if (sist & 0x4) {
+ IPRINT(PRINTPREFIX "%d/%d: unexpected disconnect\n",
+ dsa->target, dsa->lun);
+ dumpncrregs(c, 1);
+ //wakeme = 1;
+ dsa->p9status = SDeio;
+ }
+ }
+ if (istat & Dip) {
+ if (DEBUG(1)) {
+ IPRINT("dstat = %.2x\n", dstat);
+ }
+ /*else*/ if (dstat & Ssi) {
+ ulong w = legetl(n->dsp) - c->scriptpa;
+ IPRINT("[%lux]", w);
+ USED(w);
+ cont = -2; /* restart */
+ }
+ if (dstat & Sir) {
+ switch (legetl(n->dsps)) {
+ case A_SIR_MSG_IO_COMPLETE:
+ dsa->p9status = dsa->status;
+ wakeme = 1;
+ break;
+ case A_SIR_MSG_SDTR:
+ case A_SIR_MSG_WDTR:
+ case A_SIR_MSG_REJECT:
+ case A_SIR_EV_RESPONSE_OK:
+ msgsm(dsa, c, legetl(n->dsps), &cont, &wakeme);
+ break;
+ case A_SIR_MSG_IGNORE_WIDE_RESIDUE:
+ /* back up one in the data transfer */
+ IPRINT(PRINTPREFIX "%d/%d: ignore wide residue %d, WSR = %d\n",
+ dsa->target, dsa->lun, n->scratcha[1], n->scntl2 & 1);
+ if (dsa->flag == 2) {
+ IPRINT(PRINTPREFIX "%d/%d: transfer over; residue ignored\n",
+ dsa->target, dsa->lun);
+ }
+ else {
+ calcblockdma(dsa, legetl(dsa->dmaaddr) - 1,
+ dsa->dmablks * A_BSIZE + legetl(dsa->data_buf.dbc) + 1);
+ }
+ cont = -2;
+ break;
+ case A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT:
+ IPRINT(PRINTPREFIX "%d: not msg_in after reselect (%s)",
+ n->ssid & SSIDMASK(c), phase[n->sstat1 & 7]);
+ dsa = dsafind(c, n->ssid & SSIDMASK(c), -1, A_STATE_DISCONNECTED);
+ 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);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DISC:
+ IPRINT(PRINTPREFIX "%d/%d: disconnect:", dsa->target, dsa->lun);
+ goto dsadump;
+ case A_SIR_NOTIFY_STATUS:
+ IPRINT(PRINTPREFIX "%d/%d: status\n", dsa->target, dsa->lun);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_COMMAND:
+ IPRINT(PRINTPREFIX "%d/%d: commands\n", dsa->target, dsa->lun);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DATA_IN:
+ IPRINT(PRINTPREFIX "%d/%d: data in a %lx b %lx\n",
+ dsa->target, dsa->lun, legetl(n->scratcha), legetl(n->scratchb));
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_BLOCK_DATA_IN:
+ IPRINT(PRINTPREFIX "%d/%d: block data in: a2 %x b %lx\n",
+ dsa->target, dsa->lun, n->scratcha[2], legetl(n->scratchb));
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DATA_OUT:
+ IPRINT(PRINTPREFIX "%d/%d: data out\n", dsa->target, dsa->lun);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DUMP:
+ IPRINT(PRINTPREFIX "%d/%d: dump\n", dsa->target, dsa->lun);
+ dumpncrregs(c, 1);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DUMP2:
+ IPRINT(PRINTPREFIX "%d/%d: dump2:", dsa->target, dsa->lun);
+ IPRINT(" sa %lux", legetl(n->dsp) - c->scriptpa);
+ IPRINT(" dsa %lux", legetl(n->dsa));
+ IPRINT(" sfbr %ux", n->sfbr);
+ IPRINT(" a %lux", legetl(n->scratcha));
+ IPRINT(" b %lux", legetl(n->scratchb));
+ IPRINT(" ssid %ux", n->ssid);
+ IPRINT("\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_WAIT_RESELECT:
+ IPRINT(PRINTPREFIX "wait reselect\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_RESELECT:
+ IPRINT(PRINTPREFIX "reselect: ssid %.2x sfbr %.2x at %ld\n",
+ n->ssid, n->sfbr, TK2MS(m->ticks));
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_ISSUE:
+ 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));
+ IPRINT("\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_ISSUE_CHECK:
+ IPRINT(PRINTPREFIX "issue check\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_SIGP:
+ IPRINT(PRINTPREFIX "responded to SIGP\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DUMP_NEXT_CODE: {
+ 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++) {
+ IPRINT(" %.8lux", dsp[x]);
+ }
+ IPRINT("\n");
+ USED(dsp);
+ cont = -2;
+ break;
+ }
+ case A_SIR_NOTIFY_WSR:
+ IPRINT(PRINTPREFIX "%d/%d: WSR set\n", dsa->target, dsa->lun);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_LOAD_SYNC:
+ IPRINT(PRINTPREFIX "%d/%d: scntl=%.2x sxfer=%.2x\n",
+ dsa->target, dsa->lun, n->scntl3, n->sxfer);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_RESELECTED_ON_SELECT:
+ if (DEBUG(2)) {
+ IPRINT(PRINTPREFIX "%d/%d: reselected during select\n",
+ dsa->target, dsa->lun);
+ }
+ cont = -2;
+ break;
+ case A_error_reselected: /* dsa isn't valid here */
+ iprint(PRINTPREFIX "reselection error\n");
+ dumpncrregs(c, 1);
+ 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;
+ default:
+ IPRINT(PRINTPREFIX "%d/%d: script error %ld\n",
+ dsa->target, dsa->lun, legetl(n->dsps));
+ dumpncrregs(c, 1);
+ wakeme = 1;
+ }
+ }
+ /*else*/ if (dstat & Iid) {
+ 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",
+ target, lun,
+ addr, addr - c->scriptpa, dbc);
+ 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;
+ }
+ /*else*/ if (dstat & Bf) {
+ IPRINT(PRINTPREFIX "%d/%d: Bus Fault\n", dsa->target, dsa->lun);
+ dumpncrregs(c, 1);
+ dsa->p9status = SDeio;
+ wakeme = 1;
+ }
+ }
+ if (cont == -2)
+ ncrcontinue(c);
+ else if (cont >= 0)
+ start(c, cont);
+ if (wakeme){
+ if(dsa->p9status == SDnostatus)
+ dsa->p9status = SDeio;
+ wakeup(dsa);
+ }
+ iunlock(c);
+ if (DEBUG(1)) {
+ IPRINT(PRINTPREFIX "int end 1\n");
+ }
+}
+
+static int
+done(void *arg)
+{
+ return ((Dsa *)arg)->p9status != SDnostatus;
+}
+
+static void
+setmovedata(Movedata *d, ulong pa, ulong bc)
+{
+ d->pa[0] = pa;
+ d->pa[1] = pa>>8;
+ d->pa[2] = pa>>16;
+ d->pa[3] = pa>>24;
+ d->dbc[0] = bc;
+ d->dbc[1] = bc>>8;
+ d->dbc[2] = bc>>16;
+ d->dbc[3] = bc>>24;
+}
+
+static void
+advancedata(Movedata *d, long v)
+{
+ lesetl(d->pa, legetl(d->pa) + v);
+ lesetl(d->dbc, legetl(d->dbc) - v);
+}
+
+static void
+dumpwritedata(uchar *data, int datalen)
+{
+ int i;
+ uchar *bp;
+ if (!DEBUG(0)){
+ USED(data, datalen);
+ return;
+ }
+
+ if (datalen) {
+ KPRINT(PRINTPREFIX "write:");
+ for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++) {
+ KPRINT("%.2ux", *bp);
+ }
+ if (i < datalen) {
+ KPRINT("...");
+ }
+ KPRINT("\n");
+ }
+}
+
+static void
+dumpreaddata(uchar *data, int datalen)
+{
+ int i;
+ uchar *bp;
+ if (!DEBUG(0)){
+ USED(data, datalen);
+ return;
+ }
+
+ if (datalen) {
+ KPRINT(PRINTPREFIX "read:");
+ for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++) {
+ KPRINT("%.2ux", *bp);
+ }
+ if (i < datalen) {
+ KPRINT("...");
+ }
+ KPRINT("\n");
+ }
+}
+
+static void
+busreset(Controller *c)
+{
+ int x, ntarget;
+
+ /* bus reset */
+ c->n->scntl1 |= (1 << 3);
+ delay(500);
+ c->n->scntl1 &= ~(1 << 3);
+ if(!(c->v->feature & Wide))
+ ntarget = 8;
+ else
+ ntarget = MAXTARGET;
+ for (x = 0; x < ntarget; x++) {
+ setwide(0, c, x, 0);
+#ifndef ASYNC_ONLY
+ c->s[x] = NeitherDone;
+#endif
+ }
+ c->capvalid = 0;
+}
+
+static void
+reset(Controller *c)
+{
+ /* should wakeup all pending tasks */
+ softreset(c);
+ busreset(c);
+}
+
+static int
+sd53c8xxrio(SDreq* r)
+{
+ Dsa *d;
+ uchar *bp;
+ Controller *c;
+ uchar target_expo, my_expo;
+ int bc, check, i, status, target;
+
+ if((target = r->unit->subno) == 0x07)
+ return r->status = SDtimeout; /* assign */
+
+ c = r->unit->dev->ctlr;
+
+ check = 0;
+ d = dsaalloc(c, target, r->lun);
+
+ qlock(&c->q[target]); /* obtain access to target */
+docheck:
+ /* load the transfer control stuff */
+ d->scsi_id_buf[0] = 0;
+ d->scsi_id_buf[1] = c->sxfer[target];
+ d->scsi_id_buf[2] = target;
+ d->scsi_id_buf[3] = c->scntl3[target];
+ synctodsa(d, c);
+
+ bc = 0;
+
+ d->msg_out[bc] = 0x80 | r->lun;
+
+#ifndef NO_DISCONNECT
+ d->msg_out[bc] |= (1 << 6);
+#endif
+ bc++;
+
+ /* work out what to do about negotiation */
+ switch (c->s[target]) {
+ default:
+ KPRINT(PRINTPREFIX "%d: strange nego state %d\n", target, c->s[target]);
+ c->s[target] = NeitherDone;
+ /* fall through */
+ case NeitherDone:
+ if ((c->capvalid & (1 << target)) == 0)
+ break;
+ target_expo = (c->cap[target] >> 5) & 3;
+ my_expo = (c->v->feature & Wide) != 0;
+ if (target_expo < my_expo)
+ my_expo = target_expo;
+#ifdef ALWAYS_DO_WDTR
+ bc += buildwdtrmsg(d->msg_out + bc, my_expo);
+ KPRINT(PRINTPREFIX "%d: WDTN: initiating expo %d\n", target, my_expo);
+ c->s[target] = WideInit;
+ break;
+#else
+ if (my_expo) {
+ bc += buildwdtrmsg(d->msg_out + bc, (c->v->feature & Wide) ? 1 : 0);
+ KPRINT(PRINTPREFIX "%d: WDTN: initiating expo %d\n", target, my_expo);
+ c->s[target] = WideInit;
+ break;
+ }
+ KPRINT(PRINTPREFIX "%d: WDTN: narrow\n", target);
+ /* fall through */
+#endif
+ case WideDone:
+ if (c->cap[target] & (1 << 4)) {
+ KPRINT(PRINTPREFIX "%d: SDTN: initiating %d %d\n", target, c->tpf, c->v->maxsyncoff);
+ bc += buildsdtrmsg(d->msg_out + bc, c->tpf, c->v->maxsyncoff);
+ c->s[target] = SyncInit;
+ break;
+ }
+ KPRINT(PRINTPREFIX "%d: SDTN: async only\n", target);
+ c->s[target] = BothDone;
+ break;
+
+ case BothDone:
+ break;
+ }
+
+ setmovedata(&d->msg_out_buf, DMASEG(d->msg_out), bc);
+ setmovedata(&d->cmd_buf, DMASEG(r->cmd), r->clen);
+ calcblockdma(d, r->data ? DMASEG(r->data) : 0, r->dlen);
+
+ if (DEBUG(0)) {
+ KPRINT(PRINTPREFIX "%d/%d: exec: ", target, r->lun);
+ for (bp = r->cmd; bp < &r->cmd[r->clen]; bp++) {
+ KPRINT("%.2ux", *bp);
+ }
+ KPRINT("\n");
+ if (!r->write) {
+ KPRINT(PRINTPREFIX "%d/%d: exec: limit=(%d)%ld\n",
+ target, r->lun, d->dmablks, legetl(d->data_buf.dbc));
+ }
+ else
+ dumpwritedata(r->data, r->dlen);
+ }
+
+ setmovedata(&d->status_buf, DMASEG(&d->status), 1);
+
+ d->p9status = SDnostatus;
+ d->parityerror = 0;
+ coherence();
+ d->stateb = A_STATE_ISSUE; /* start operation */
+ coherence();
+
+ ilock(c);
+ if (c->ssm)
+ c->n->dcntl |= 0x10; /* single step */
+ if (c->running) {
+ c->n->istat = Sigp;
+ }
+ else {
+ start(c, E_issue_check);
+ }
+ iunlock(c);
+
+ while(waserror())
+ ;
+ tsleep(d, done, d, 600 * 1000);
+ poperror();
+
+ if (!done(d)) {
+ KPRINT(PRINTPREFIX "%d/%d: exec: Timed out\n", target, r->lun);
+ dumpncrregs(c, 0);
+ dsafree(c, d);
+ reset(c);
+ qunlock(&c->q[target]);
+ r->status = SDtimeout;
+ return r->status = SDtimeout; /* assign */
+ }
+
+ if((status = d->p9status) == SDeio)
+ c->s[target] = NeitherDone;
+ if (d->parityerror) {
+ status = SDeio;
+ }
+
+ /*
+ * adjust datalen
+ */
+ r->rlen = r->dlen;
+ if (DEBUG(0)) {
+ KPRINT(PRINTPREFIX "%d/%d: exec: before rlen adjust: dmablks %d flag %d dbc %lud\n",
+ target, r->lun, d->dmablks, d->flag, legetl(d->data_buf.dbc));
+ }
+ r->rlen = r->dlen;
+ if (d->flag != 2) {
+ r->rlen -= d->dmablks * A_BSIZE;
+ r->rlen -= legetl(d->data_buf.dbc);
+ }
+ if(!r->write)
+ dumpreaddata(r->data, r->rlen);
+ if (DEBUG(0)) {
+ KPRINT(PRINTPREFIX "%d/%d: exec: p9status=%d status %d rlen %ld\n",
+ target, r->lun, d->p9status, status, r->rlen);
+ }
+ /*
+ * spot the identify
+ */
+ if ((c->capvalid & (1 << target)) == 0
+ && (status == SDok || status == SDcheck)
+ && r->cmd[0] == 0x12 && r->dlen >= 8) {
+ c->capvalid |= 1 << target;
+ bp = r->data;
+ c->cap[target] = bp[7];
+ KPRINT(PRINTPREFIX "%d: capabilities %.2x\n", target, bp[7]);
+ }
+ if(!check && status == SDcheck && !(r->flags & SDnosense)){
+ check = 1;
+ r->write = 0;
+ memset(r->cmd, 0, sizeof(r->cmd));
+ r->cmd[0] = 0x03;
+ r->cmd[1] = r->lun<<5;
+ r->cmd[4] = sizeof(r->sense)-1;
+ r->clen = 6;
+ r->data = r->sense;
+ r->dlen = sizeof(r->sense)-1;
+ /*
+ * Clear out the microcode state
+ * so the Dsa can be re-used.
+ */
+ lesetl(&d->stateb, A_STATE_ALLOCATED);
+ coherence();
+ goto docheck;
+ }
+ qunlock(&c->q[target]);
+ dsafree(c, d);
+
+ if(status == SDok && check){
+ status = SDcheck;
+ r->flags |= SDvalidsense;
+ }
+ if(DEBUG(0))
+ KPRINT(PRINTPREFIX "%d: r flags %8.8uX status %d rlen %ld\n",
+ target, r->flags, status, r->rlen);
+ if(r->flags & SDvalidsense){
+ if(!DEBUG(0))
+ KPRINT(PRINTPREFIX "%d: r flags %8.8uX status %d rlen %ld\n",
+ target, r->flags, status, r->rlen);
+ for(i = 0; i < r->rlen; i++)
+ KPRINT(" %2.2uX", r->sense[i]);
+ KPRINT("\n");
+ }
+ 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;
+ print(PRINTPREFIX "bios scntl3(%.2x) stest2(%.2x)\n", c->bios.scntl3, c->bios.stest2);
+}
+
+static int
+bios_set_differential(Controller *c)
+{
+ /* Concept lifted from FreeBSD - thanks Gerard */
+ /* basically, if clock conversion factors are set, then there is
+ * evidence the bios had a go at the chip, and if so, it would
+ * have set the differential enable bit in stest2
+ */
+ return (c->bios.scntl3 & 7) != 0 && (c->bios.stest2 & 0x20) != 0;
+}
+
+#define NCR_VID 0x1000
+#define NCR_810_DID 0x0001
+#define NCR_820_DID 0x0002 /* don't know enough about this one to support it */
+#define NCR_825_DID 0x0003
+#define NCR_815_DID 0x0004
+#define SYM_810AP_DID 0x0005
+#define SYM_860_DID 0x0006
+#define SYM_896_DID 0x000b
+#define SYM_895_DID 0x000c
+#define SYM_885_DID 0x000d /* ditto */
+#define SYM_875_DID 0x000f /* ditto */
+#define SYM_1010_DID 0x0020
+#define SYM_1011_DID 0x0021
+#define SYM_875J_DID 0x008f
+
+static Variant variant[] = {
+{ NCR_810_DID, 0x0f, "NCR53C810", Burst16, 8, 24, 0 },
+{ NCR_810_DID, 0x1f, "SYM53C810ALV", Burst16, 8, 24, Prefetch },
+{ NCR_810_DID, 0xff, "SYM53C810A", Burst16, 8, 24, Prefetch },
+{ SYM_810AP_DID, 0xff, "SYM53C810AP", Burst16, 8, 24, Prefetch },
+{ NCR_815_DID, 0xff, "NCR53C815", Burst16, 8, 24, BurstOpCodeFetch },
+{ NCR_825_DID, 0x0f, "NCR53C825", Burst16, 8, 24, Wide|BurstOpCodeFetch|Differential },
+{ NCR_825_DID, 0xff, "SYM53C825A", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide },
+{ SYM_860_DID, 0x0f, "SYM53C860", Burst16, 8, 24, Prefetch|Ultra },
+{ SYM_860_DID, 0xff, "SYM53C860LV", Burst16, 8, 24, Prefetch|Ultra },
+{ SYM_875_DID, 0x01, "SYM53C875r1", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra },
+{ SYM_875_DID, 0xff, "SYM53C875", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
+{ SYM_875J_DID, 0xff, "SYM53C875j", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
+{ SYM_885_DID, 0xff, "SYM53C885", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|ClockDouble },
+{ SYM_895_DID, 0xff, "SYM53C895", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+{ SYM_896_DID, 0xff, "SYM53C896", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+{ SYM_1010_DID, 0xff, "SYM53C1010", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+{ SYM_1011_DID, 0xff, "SYM53C1010", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+};
+
+static int
+xfunc(Controller *c, enum na_external x, unsigned long *v)
+{
+ switch (x)
+ {
+ case X_scsi_id_buf:
+ *v = offsetof(Dsa, scsi_id_buf[0]); return 1;
+ case X_msg_out_buf:
+ *v = offsetof(Dsa, msg_out_buf); return 1;
+ case X_cmd_buf:
+ *v = offsetof(Dsa, cmd_buf); return 1;
+ case X_data_buf:
+ *v = offsetof(Dsa, data_buf); return 1;
+ case X_status_buf:
+ *v = offsetof(Dsa, status_buf); return 1;
+ case X_dsa_head:
+ *v = DMASEG(&c->dsalist.head[0]); return 1;
+ case X_ssid_mask:
+ *v = SSIDMASK(c); return 1;
+ default:
+ print("xfunc: can't find external %d\n", x);
+ return 0;
+ }
+ return 1;
+}
+
+static int
+na_fixup(Controller *c, ulong pa_reg,
+ struct na_patch *patch, int patches,
+ int (*externval)(Controller*, int, ulong*))
+{
+ int p;
+ int v;
+ ulong *script, pa_script;
+ unsigned long lw, lv;
+
+ script = c->script;
+ pa_script = c->scriptpa;
+ for (p = 0; p < patches; p++) {
+ switch (patch[p].type) {
+ case 1:
+ /* script relative */
+ script[patch[p].lwoff] += pa_script;
+ break;
+ case 2:
+ /* register i/o relative */
+ script[patch[p].lwoff] += pa_reg;
+ break;
+ case 3:
+ /* data external */
+ lw = script[patch[p].lwoff];
+ v = (lw >> 8) & 0xff;
+ if (!(*externval)(c, v, &lv))
+ return 0;
+ v = lv & 0xff;
+ script[patch[p].lwoff] = (lw & 0xffff00ffL) | (v << 8);
+ break;
+ case 4:
+ /* 32 bit external */
+ lw = script[patch[p].lwoff];
+ if (!(*externval)(c, lw, &lv))
+ return 0;
+ script[patch[p].lwoff] = lv;
+ break;
+ case 5:
+ /* 24 bit external */
+ lw = script[patch[p].lwoff];
+ if (!(*externval)(c, lw & 0xffffff, &lv))
+ return 0;
+ script[patch[p].lwoff] = (lw & 0xff000000L) | (lv & 0xffffffL);
+ break;
+ }
+ }
+ return 1;
+}
+
+static SDev*
+sd53c8xxpnp(void)
+{
+ char *cp;
+ Pcidev *p;
+ Variant *v;
+ int ba, nctlr;
+ void *scriptma;
+ Controller *ctlr;
+ SDev *sdev, *head, *tail;
+ ulong regpa, *script, scriptpa;
+ void *regva, *scriptva;
+
+ if(cp = getconf("*maxsd53c8xx"))
+ nctlr = strtoul(cp, 0, 0);
+ else
+ nctlr = 32;
+
+ p = nil;
+ head = tail = nil;
+ while((p = pcimatch(p, NCR_VID, 0)) != nil && nctlr > 0){
+ for(v = variant; v < &variant[nelem(variant)]; v++){
+ if(p->did == v->did && p->rid <= v->maxrid)
+ break;
+ }
+ if(v >= &variant[nelem(variant)]) {
+ print("no match\n");
+ continue;
+ }
+ print(PRINTPREFIX "%s rev. 0x%2.2x intr=%d command=%4.4uX\n",
+ v->name, p->rid, p->intl, p->pcr);
+
+ regpa = p->mem[1].bar;
+ ba = 2;
+ if(regpa & 0x04){
+ if(p->mem[2].bar)
+ continue;
+ ba++;
+ }
+ 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){
+ vunmap(regva, p->mem[1].size);
+ continue;
+ }
+ scriptpa &= ~0x0F;
+ scriptva = vmap(scriptpa, p->mem[ba].size);
+ if(scriptva)
+ script = scriptva;
+ }
+ if(scriptpa == 0){
+ /*
+ * Either the map failed, or this chip does not have
+ * local RAM. It will need a copy of the microcode.
+ */
+ scriptma = malloc(sizeof(na_script));
+ if(scriptma == nil){
+ vunmap(regva, p->mem[1].size);
+ continue;
+ }
+ scriptpa = DMASEG(scriptma);
+ script = scriptma;
+ }
+
+ ctlr = malloc(sizeof(Controller));
+ sdev = malloc(sizeof(SDev));
+ if(ctlr == nil || sdev == nil){
+buggery:
+ if(ctlr)
+ free(ctlr);
+ if(sdev)
+ free(sdev);
+ if(scriptma)
+ free(scriptma);
+ else if(scriptva)
+ vunmap(scriptva, p->mem[ba].size);
+ if(regva)
+ vunmap(regva, p->mem[1].size);
+ continue;
+ }
+
+ 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));
+
+ /*
+ * Because we don't yet have an abstraction for the
+ * addresses as seen from the controller side (and on
+ * the 386 it doesn't matter), the following three lines
+ * are different between the 386 and alpha copies of
+ * this driver.
+ */
+ USED(scriptpa);
+ ctlr->scriptpa = p->mem[ba].bar & ~0x0F;
+ if(!na_fixup(ctlr, p->mem[1].bar & ~0x0F, na_patches, NA_PATCHES, xfunc)){
+ print("script fixup failed\n");
+ goto buggery;
+ }
+ swabl(ctlr->script, ctlr->script, sizeof(na_script));
+
+ 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
+ head = sdev;
+ tail = sdev;
+
+ nctlr--;
+ }
+
+ return head;
+}
+
+static int
+sd53c8xxenable(SDev* sdev)
+{
+ Pcidev *pcidev;
+ Controller *ctlr;
+ char name[32];
+
+ ctlr = sdev->ctlr;
+ pcidev = ctlr->pcidev;
+
+ pcisetbme(pcidev);
+
+ 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;
+}
+
+SDifc sd53c8xxifc = {
+ "53c8xx", /* name */
+
+ sd53c8xxpnp, /* pnp */
+ nil, /* legacy */
+ sd53c8xxenable, /* enable */
+ nil, /* disable */
+
+ scsiverify, /* verify */
+ scsionline, /* online */
+ sd53c8xxrio, /* rio */
+ nil, /* rctl */
+ nil, /* wctl */
+
+ scsibio, /* bio */
+ nil, /* probe */
+ nil, /* clear */
+ nil, /* stat */
+};
diff --git a/sys/src/9/alphapc/sd53c8xx.i b/sys/src/9/alphapc/sd53c8xx.i
new file mode 100755
index 000000000..ca562394d
--- /dev/null
+++ b/sys/src/9/alphapc/sd53c8xx.i
@@ -0,0 +1,805 @@
+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 */
+ /* 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 */
+ /* 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 */ 0x00000790L,
+/* 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 */ 0x000005b8L,
+/* 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 */ 0x000005a0L,
+/* 0058 */ 0xc0000004L, /* move memory 4, state, scratcha */
+/* 005c */ 0x00000640L,
+/* 0060 */ 0x00000034L,
+/* 0064 */ 0xc0000004L, /* move memory 4, dmaaddr, scratchb */
+/* 0068 */ 0x00000644L,
+/* 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 */ 0x00000644L,
+/* 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 */ 0x00000644L,
+/* 00b4 */ 0x818b0000L, /* jump data_in_block_loop, when data_in */
+/* 00b8 */ 0x00ffffb4L,
+/* 00bc */ 0xc0000004L, /* move memory 4, scratcha, state */
+/* 00c0 */ 0x00000034L,
+/* 00c4 */ 0x00000640L,
+/* 00c8 */ 0x88880000L, /* call save_state */
+/* 00cc */ 0x0000065cL,
+/* 00d0 */ 0x80880000L, /* jump to_decisions */
+/* 00d4 */ 0x00000520L,
+/* 00d8 */ 0xc0000004L, /* move memory 4, scratchb, dmaaddr */
+/* 00dc */ 0x0000005cL,
+/* 00e0 */ 0x00000644L,
+/* 00e4 */ 0xc0000004L, /* move memory 4, scratcha, state */
+/* 00e8 */ 0x00000034L,
+/* 00ec */ 0x00000640L,
+/* 00f0 */ 0x80880000L, /* jump to_decisions */
+/* 00f4 */ 0x00000500L,
+/* 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 */ 0x00000640L,
+/* 0124 */ 0x88880000L, /* call save_state */
+/* 0128 */ 0x00000600L,
+/* 012c */ 0x80880000L, /* jump post_data_to_decisions */
+/* 0130 */ 0x000004f4L,
+/* 0134 */ 0xc0000004L, /* move memory 4, state, scratcha */
+/* 0138 */ 0x00000640L,
+/* 013c */ 0x00000034L,
+/* 0140 */ 0xc0000004L, /* move memory 4, dmaaddr, scratchb */
+/* 0144 */ 0x00000644L,
+/* 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 */ 0x00000644L,
+/* 0164 */ 0x0000005cL,
+/* 0168 */ 0x28000200L, /* move BSIZE, ptr dmaaddr, when data_out */
+/* 016c */ 0x00000644L,
+/* 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 */ 0x00000644L,
+/* 019c */ 0x808b0000L, /* jump data_out_block_loop, when data_out */
+/* 01a0 */ 0x00ffffa8L,
+/* 01a4 */ 0xc0000004L, /* move memory 4, scratcha, state */
+/* 01a8 */ 0x00000034L,
+/* 01ac */ 0x00000640L,
+/* 01b0 */ 0x80880000L, /* jump to_decisions */
+/* 01b4 */ 0x00000440L,
+/* 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 */ 0x00000640L,
+/* 01e4 */ 0x88880000L, /* call save_state */
+/* 01e8 */ 0x00000540L,
+/* 01ec */ 0x80880000L, /* jump post_data_to_decisions */
+/* 01f0 */ 0x00000434L,
+/* 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 */ 0x00000640L,
+/* 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 */ 0x00000640L,
+/* 0284 */ 0x88880000L, /* call save_state */
+/* 0288 */ 0x000004a0L,
+/* 028c */ 0x98180000L, /* intfly 0 */
+/* 0290 */ 0x00000000L,
+/* 0294 */ 0x80880000L, /* jump issue_check */
+/* 0298 */ 0x000004b8L,
+/* 029c */ 0x98080000L, /* int SIR_MSG_REJECT */
+/* 02a0 */ 0x0000000aL,
+/* 02a4 */ 0x60000040L, /* clear ack */
+/* 02a8 */ 0x00000000L,
+/* 02ac */ 0x80880000L, /* jump to_decisions */
+/* 02b0 */ 0x00000344L,
+/* 02b4 */ 0x60000040L, /* clear ack */
+/* 02b8 */ 0x00000000L,
+/* 02bc */ 0x80880000L, /* jump to_decisions */
+/* 02c0 */ 0x00000334L,
+/* 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 */ 0x00000274L,
+/* 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 */ 0x0000021cL,
+/* 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 */ 0x000001d4L,
+/* 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 */ 0x000001a4L,
+/* 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 */ 0x00000164L,
+/* 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 */ 0x00000640L,
+/* 04d4 */ 0x00000034L,
+/* 04d8 */ 0x78340300L, /* move STATE_DISCONNECTED to scratcha0 */
+/* 04dc */ 0x00000000L,
+/* 04e0 */ 0xc0000004L, /* move memory 4, scratcha, state */
+/* 04e4 */ 0x00000034L,
+/* 04e8 */ 0x00000640L,
+/* 04ec */ 0x88880000L, /* call save_state */
+/* 04f0 */ 0x00000238L,
+/* 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 */ 0x00000248L,
+/* 050c */ 0x98080000L, /* int SIR_NOTIFY_RESELECTED_ON_SELECT */
+/* 0510 */ 0x00000075L,
+/* 0514 */ 0x80880000L, /* jump reselected */
+/* 0518 */ 0x00000008L,
+/* 051c */ 0x54000000L, /* wait reselect sigp_set */
+/* 0520 */ 0x00000228L,
+/* 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 */ 0x88880000L, /* call load_state */
+/* 0554 */ 0x00000100L,
+/* 0558 */ 0xc0000004L, /* move memory 4, state, scratcha */
+/* 055c */ 0x00000640L,
+/* 0560 */ 0x00000034L,
+/* 0564 */ 0x72340000L, /* move scratcha0 to sfbr */
+/* 0568 */ 0x00000000L,
+/* 056c */ 0x80840003L, /* jump find_dsa_next, if not STATE_DISCONNECTED */
+/* 0570 */ 0x00000040L,
+/* 0574 */ 0x980c0005L, /* int error_reselected, if STATE_END */
+/* 0578 */ 0x00000003L,
+/* 057c */ 0x740a0900L, /* move ssid & ssid_mask to sfbr */
+/* 0580 */ 0x00000000L,
+/* 0584 */ 0xc0000001L, /* move memory 1, targ, find_dsa_smc1 */
+/* 0588 */ 0x00000648L,
+/* 058c */ 0x00000590L,
+/* 0590 */ 0x808400ffL, /* jump find_dsa_next, if not 255 */
+/* 0594 */ 0x0000001cL,
+/* 0598 */ 0xc0000001L, /* move memory 1, lun, find_dsa_smc2 */
+/* 059c */ 0x0000064cL,
+/* 05a0 */ 0x000005acL,
+/* 05a4 */ 0x725c0000L, /* move scratchb0 to sfbr */
+/* 05a8 */ 0x00000000L,
+/* 05ac */ 0x808cf8ffL, /* jump reload_sync, if 255 and mask ~7 */
+/* 05b0 */ 0x00000034L,
+/* 05b4 */ 0xc0000004L, /* move memory 4, next, dsa */
+/* 05b8 */ 0x00000654L,
+/* 05bc */ 0x00000010L,
+/* 05c0 */ 0x80880000L, /* jump find_dsa_loop */
+/* 05c4 */ 0x00ffff88L,
+/* 05c8 */ 0x60000008L, /* clear atn */
+/* 05cc */ 0x00000000L,
+/* 05d0 */ 0x878b0000L, /* jump msg_in_phase, when msg_in */
+/* 05d4 */ 0x00fffc2cL,
+/* 05d8 */ 0x98080000L, /* int SIR_MSG_REJECT */
+/* 05dc */ 0x0000000aL,
+/* 05e0 */ 0x80880000L, /* jump to_decisions */
+/* 05e4 */ 0x00000010L,
+/* 05e8 */ 0x88880000L, /* call load_sync */
+/* 05ec */ 0x000001b0L,
+/* 05f0 */ 0x60000040L, /* clear ack */
+/* 05f4 */ 0x00000000L,
+/* 05f8 */ 0x818b0000L, /* jump data_in_phase, when data_in */
+/* 05fc */ 0x00fffa58L,
+/* 0600 */ 0x828a0000L, /* jump cmd_phase, if cmd */
+/* 0604 */ 0x00fffa38L,
+/* 0608 */ 0x808a0000L, /* jump data_out_phase, if data_out */
+/* 060c */ 0x00fffb24L,
+/* 0610 */ 0x838a0000L, /* jump status_phase, if status */
+/* 0614 */ 0x00fffbdcL,
+/* 0618 */ 0x878a0000L, /* jump msg_in_phase, if msg_in */
+/* 061c */ 0x00fffbe4L,
+/* 0620 */ 0x98080000L, /* int error_unexpected_phase */
+/* 0624 */ 0x00000004L,
+/* 0628 */ 0x838b0000L, /* jump status_phase, when status */
+/* 062c */ 0x00fffbc4L,
+/* 0630 */ 0x878a0000L, /* jump msg_in_phase, if msg_in */
+/* 0634 */ 0x00fffbccL,
+/* 0638 */ 0x98080000L, /* int error_unexpected_phase */
+/* 063c */ 0x00000004L,
+/* 0640 */ 0x00000000L, /* state: defw 0 */
+/* 0644 */ 0x00000000L, /* dmaaddr: defw 0 */
+/* 0648 */ 0x00000000L, /* targ: defw 0 */
+/* 064c */ 0x00000000L, /* lun: defw 0 */
+/* 0650 */ 0x00000000L, /* sync: defw 0 */
+/* 0654 */ 0x00000000L, /* next: defw 0 */
+ /* dsa_load_len = dsa_load_end - dsa_copy */
+ /* dsa_save_len = dsa_save_end - dsa_copy */
+/* 0658 */ 0x80880000L, /* jump load_state_okay */
+/* 065c */ 0x000000acL,
+/* 0660 */ 0x72100000L, /* move dsa0 to sfbr */
+/* 0664 */ 0x00000000L,
+/* 0668 */ 0x80840000L, /* jump load_state_okay, if not 0 */
+/* 066c */ 0x0000009cL,
+/* 0670 */ 0x72110000L, /* move dsa1 to sfbr */
+/* 0674 */ 0x00000000L,
+/* 0678 */ 0x80840000L, /* jump load_state_okay, if not 0 */
+/* 067c */ 0x0000008cL,
+/* 0680 */ 0x72120000L, /* move dsa2 to sfbr */
+/* 0684 */ 0x00000000L,
+/* 0688 */ 0x80840000L, /* jump load_state_okay, if not 0 */
+/* 068c */ 0x0000007cL,
+/* 0690 */ 0x72130000L, /* move dsa3 to sfbr */
+/* 0694 */ 0x00000000L,
+/* 0698 */ 0x80840000L, /* jump load_state_okay, if not 0 */
+/* 069c */ 0x0000006cL,
+/* 06a0 */ 0xc0000004L, /* move memory 4, dsa, dmaaddr */
+/* 06a4 */ 0x00000010L,
+/* 06a8 */ 0x00000644L,
+/* 06ac */ 0xc0000004L, /* move memory 4, dsa, targ */
+/* 06b0 */ 0x00000010L,
+/* 06b4 */ 0x00000648L,
+/* 06b8 */ 0xc0000004L, /* move memory 4, dsa, lun */
+/* 06bc */ 0x00000010L,
+/* 06c0 */ 0x0000064cL,
+/* 06c4 */ 0xc0000004L, /* move memory 4, dsa, sync */
+/* 06c8 */ 0x00000010L,
+/* 06cc */ 0x00000650L,
+/* 06d0 */ 0xc0000004L, /* move memory 4, dsa, next */
+/* 06d4 */ 0x00000010L,
+/* 06d8 */ 0x00000654L,
+/* 06dc */ 0xc0000004L, /* move memory 4, dsa, scratcha */
+/* 06e0 */ 0x00000010L,
+/* 06e4 */ 0x00000034L,
+/* 06e8 */ 0x68080500L, /* move STATE_END to sfbr */
+/* 06ec */ 0x00000000L,
+/* 06f0 */ 0x6a340000L, /* move sfbr to scratcha0 */
+/* 06f4 */ 0x00000000L,
+/* 06f8 */ 0xc0000004L, /* move memory 4, scratcha, state */
+/* 06fc */ 0x00000034L,
+/* 0700 */ 0x00000640L,
+/* 0704 */ 0x90080000L, /* return */
+/* 0708 */ 0x00000000L,
+/* 070c */ 0xc0000004L, /* move memory 4, dsa, load_state_smc0 + 4 */
+/* 0710 */ 0x00000010L,
+/* 0714 */ 0x0000071cL,
+/* 0718 */ 0xc0000018L, /* move memory dsa_load_len, 0, dsa_copy */
+/* 071c */ 0x00000000L,
+/* 0720 */ 0x00000640L,
+/* 0724 */ 0x90080000L, /* return */
+/* 0728 */ 0x00000000L,
+/* 072c */ 0xc0000004L, /* move memory 4, dsa, save_state_smc0 + 8 */
+/* 0730 */ 0x00000010L,
+/* 0734 */ 0x00000740L,
+/* 0738 */ 0xc0000008L, /* move memory dsa_save_len, dsa_copy, 0 */
+/* 073c */ 0x00000640L,
+/* 0740 */ 0x00000000L,
+/* 0744 */ 0x90080000L, /* return */
+/* 0748 */ 0x00000000L,
+/* 074c */ 0x721a0000L, /* move ctest2 to sfbr */
+/* 0750 */ 0x00000000L,
+/* 0754 */ 0xc0000004L, /* move memory 4, dsa_head, dsa */
+/* 0758 */ 0x00000008L,
+/* 075c */ 0x00000010L,
+/* 0760 */ 0x88880000L, /* call load_state */
+/* 0764 */ 0x00fffef0L,
+/* 0768 */ 0xc0000004L, /* move memory 4, state, scratcha */
+/* 076c */ 0x00000640L,
+/* 0770 */ 0x00000034L,
+/* 0774 */ 0x72340000L, /* move scratcha0 to sfbr */
+/* 0778 */ 0x00000000L,
+/* 077c */ 0x808c0002L, /* jump start, if STATE_ISSUE */
+/* 0780 */ 0x00fff884L,
+/* 0784 */ 0x808c0005L, /* jump wait_for_reselection, if STATE_END */
+/* 0788 */ 0x00fffd90L,
+/* 078c */ 0xc0000004L, /* move memory 4, next, dsa */
+/* 0790 */ 0x00000654L,
+/* 0794 */ 0x00000010L,
+/* 0798 */ 0x80880000L, /* jump issue_check_loop */
+/* 079c */ 0x00ffffc0L,
+/* 07a0 */ 0xc0000004L, /* move memory 4, sync, scratcha */
+/* 07a4 */ 0x00000650L,
+/* 07a8 */ 0x00000034L,
+/* 07ac */ 0x72340000L, /* move scratcha0 to sfbr */
+/* 07b0 */ 0x00000000L,
+/* 07b4 */ 0x6a030000L, /* move sfbr to scntl3 */
+/* 07b8 */ 0x00000000L,
+/* 07bc */ 0x72350000L, /* move scratcha1 to sfbr */
+/* 07c0 */ 0x00000000L,
+/* 07c4 */ 0x6a050000L, /* move sfbr to sxfer */
+/* 07c8 */ 0x00000000L,
+/* 07cc */ 0x90080000L, /* return */
+/* 07d0 */ 0x00000000L,
+};
+
+#define NA_SCRIPT_SIZE 501
+
+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 */
+ { 0x0157, 1 }, /* 0000055c */
+ { 0x0158, 2 }, /* 00000560 */
+ { 0x015f, 3 }, /* 0000057c */
+ { 0x0162, 1 }, /* 00000588 */
+ { 0x0163, 1 }, /* 0000058c */
+ { 0x0167, 1 }, /* 0000059c */
+ { 0x0168, 1 }, /* 000005a0 */
+ { 0x016e, 1 }, /* 000005b8 */
+ { 0x016f, 2 }, /* 000005bc */
+ { 0x01a9, 2 }, /* 000006a4 */
+ { 0x01aa, 1 }, /* 000006a8 */
+ { 0x01ac, 2 }, /* 000006b0 */
+ { 0x01ad, 1 }, /* 000006b4 */
+ { 0x01af, 2 }, /* 000006bc */
+ { 0x01b0, 1 }, /* 000006c0 */
+ { 0x01b2, 2 }, /* 000006c8 */
+ { 0x01b3, 1 }, /* 000006cc */
+ { 0x01b5, 2 }, /* 000006d4 */
+ { 0x01b6, 1 }, /* 000006d8 */
+ { 0x01b8, 2 }, /* 000006e0 */
+ { 0x01b9, 2 }, /* 000006e4 */
+ { 0x01bf, 2 }, /* 000006fc */
+ { 0x01c0, 1 }, /* 00000700 */
+ { 0x01c4, 2 }, /* 00000710 */
+ { 0x01c5, 1 }, /* 00000714 */
+ { 0x01c8, 1 }, /* 00000720 */
+ { 0x01cc, 2 }, /* 00000730 */
+ { 0x01cd, 1 }, /* 00000734 */
+ { 0x01cf, 1 }, /* 0000073c */
+ { 0x01d6, 4 }, /* 00000758 */
+ { 0x01d7, 2 }, /* 0000075c */
+ { 0x01db, 1 }, /* 0000076c */
+ { 0x01dc, 2 }, /* 00000770 */
+ { 0x01e4, 1 }, /* 00000790 */
+ { 0x01e5, 2 }, /* 00000794 */
+ { 0x01e9, 1 }, /* 000007a4 */
+ { 0x01ea, 2 }, /* 000007a8 */
+};
+#define NA_PATCHES 94
+
+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_loop = 1888,
+ E_save_state_smc0 = 1848,
+ E_load_state_smc0 = 1816,
+ E_load_state_okay = 1804,
+ E_dsa_load_end = 1624,
+ E_sync = 1616,
+ E_dsa_save_end = 1608,
+ E_dsa_copy = 1600,
+ E_id_out_mismatch_recover = 1480,
+ E_next = 1620,
+ E_reload_sync = 1512,
+ E_find_dsa_smc2 = 1452,
+ E_lun = 1612,
+ E_find_dsa_smc1 = 1424,
+ E_targ = 1608,
+ E_find_dsa_next = 1460,
+ E_load_state = 1624,
+ E_find_dsa_loop = 1360,
+ E_find_dsa = 1348,
+ E_sigp_set = 1868,
+ 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 = 1876,
+ 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 = 1576,
+ E_data_in_mismatch = 272,
+ E_data_mismatch_recover = 228,
+ E_data_block_mismatch_recover = 216,
+ E_save_state = 1836,
+ E_data_in_block_mismatch = 136,
+ E_data_in_normal = 248,
+ E_data_in_block_loop = 112,
+ E_dmaaddr = 1604,
+ E_state = 1600,
+ E_data_in_phase = 88,
+ E_cmd_out_mismatch = 80,
+ E_cmd_phase = 64,
+ E_to_decisions = 1528,
+ E_id_out_mismatch = 48,
+ E_start1 = 40,
+ E_reselected_on_select = 1292,
+ E_load_sync = 1952,
+ E_start = 8,
+ E_wait_for_reselection = 1308,
+};
+#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_END 5
+#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_LOAD_STATE 118
+#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
diff --git a/sys/src/9/alphapc/sio.c b/sys/src/9/alphapc/sio.c
new file mode 100755
index 000000000..1b75fabad
--- /dev/null
+++ b/sys/src/9/alphapc/sio.c
@@ -0,0 +1,18 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ * 82378ZB Saturn-I/O (SIO) PCI-to-ISA Bus Bridge.
+ */
+static Pcidev* siodev;
+
+void
+siodump(void)
+{
+ if(siodev == nil && (siodev = pcimatch(nil, 0x8086, 0x0484)) == nil)
+ return;
+}
diff --git a/sys/src/9/alphapc/trap.c b/sys/src/9/alphapc/trap.c
new file mode 100755
index 000000000..4767c802a
--- /dev/null
+++ b/sys/src/9/alphapc/trap.c
@@ -0,0 +1,916 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "ureg.h"
+#include "io.h"
+#include "../port/error.h"
+
+void noted(Ureg*, Ureg**, ulong);
+void rfnote(Ureg**);
+void kernfault(Ureg*, int);
+void illegal(Ureg *);
+void fen(Ureg *);
+
+char *regname[]={
+ "type", "a0", "a1",
+ "a2", "R0", "R1",
+ "R2", "R3", "R4",
+ "R5", "R6", "R7",
+ "R8", "R9", "R10",
+ "R11", "R12", "R13",
+ "R14", "R15", "R19",
+ "R20", "R21", "R22",
+ "R23", "R24", "R25",
+ "R26", "R27", "R28",
+ "R30", "status", "PC",
+ "R29", "R16", "R17",
+ "R18",
+};
+
+static Lock vctllock;
+static Vctl *vctl[256];
+
+void
+intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
+{
+ int vno;
+ Vctl *v;
+
+ if(f == nil){
+ print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n",
+ irq, tbdf, name);
+ return;
+ }
+
+ v = xalloc(sizeof(Vctl));
+ v->isintr = 1;
+ v->irq = irq;
+ v->tbdf = tbdf;
+ v->f = f;
+ v->a = a;
+ strncpy(v->name, name, KNAMELEN-1);
+ v->name[KNAMELEN-1] = 0;
+
+ ilock(&vctllock);
+ vno = arch->intrenable(v);
+ if(vno == -1){
+ iunlock(&vctllock);
+ print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n",
+ irq, tbdf, v->name);
+ xfree(v);
+ return;
+ }
+ if(vctl[vno]){
+ if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)
+ panic("intrenable: handler: %s %s %#p %#p %#p %#p",
+ vctl[vno]->name, v->name,
+ vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);
+ v->next = vctl[vno];
+ }
+ vctl[vno] = v;
+ iunlock(&vctllock);
+}
+
+int
+intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
+{
+ Vctl **pv, *v;
+ int vno;
+
+ /*
+ * For now, none of this will work with the APIC code,
+ * there is no mapping between irq and vector as the IRQ
+ * is pretty meaningless.
+ */
+ if(arch->intrvecno == nil)
+ return -1;
+ vno = arch->intrvecno(irq);
+ ilock(&vctllock);
+ for(pv = &vctl[vno]; *pv != nil; pv = &((*pv)->next)){
+ if((*pv)->irq != irq)
+ continue;
+ if((*pv)->tbdf != tbdf)
+ continue;
+ if((*pv)->f != f)
+ continue;
+ if((*pv)->a != a)
+ continue;
+ if(strcmp((*pv)->name, name) != 0)
+ continue;
+ break;
+ }
+ assert(*pv != nil);
+
+ v = *pv;
+ *pv = (*pv)->next; /* Link out the entry */
+
+ if (vctl[vno] == nil && arch->intrdisable != nil)
+ arch->intrdisable(irq);
+ iunlock(&vctllock);
+ xfree(v);
+ return 0;
+}
+
+int
+irqallocread(char *buf, long n, vlong offset)
+{
+ int vno;
+ Vctl *v;
+ long oldn;
+ char str[11+1+KNAMELEN+1], *p;
+ int m;
+
+ if(n < 0 || offset < 0)
+ error(Ebadarg);
+
+ oldn = n;
+ for(vno=0; vno<nelem(vctl); vno++){
+ for(v=vctl[vno]; v; v=v->next){
+ m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name);
+ if(m <= offset) /* if do not want this, skip entry */
+ offset -= m;
+ else{
+ /* skip offset bytes */
+ m -= offset;
+ p = str+offset;
+ offset = 0;
+
+ /* write at most max(n,m) bytes */
+ if(m > n)
+ m = n;
+ memmove(buf, p, m);
+ n -= m;
+ buf += m;
+
+ if(n == 0)
+ return oldn;
+ }
+ }
+ }
+ return oldn - n;
+}
+
+typedef struct Mcheck Mcheck;
+struct Mcheck
+{
+ ulong len;
+ ulong inprogress;
+ ulong procoff;
+ ulong sysoff;
+ ulong code;
+};
+
+static char *
+smcheck(ulong code)
+{
+ switch (code) {
+ case 0x80: return "tag parity error";
+ case 0x82: return "tag control parity error";
+ case 0x84: return "generic hard error";
+ case 0x86: return "correctable ECC error";
+ case 0x88: return "uncorrectable ECC error";
+ case 0x8a: return "OS-specific PAL bugcheck";
+ case 0x90: return "callsys in kernel mode";
+ case 0x96: return "i-cache read retryable error";
+ case 0x98: return "processor detected hard error";
+
+ case 0x203: return "system detected uncorrectable ECC error";
+ case 0x205: return "parity error detected by CIA";
+ case 0x207: return "non-existent memory error";
+ case 0x209: return "PCI SERR detected";
+ case 0x20b: return "PCI data parity error detected";
+ case 0x20d: return "PCI address parity error detected";
+ case 0x20f: return "PCI master abort error";
+ case 0x211: return "PCI target abort error";
+ case 0x213: return "scatter/gather PTE invalid error";
+ case 0x215: return "flash ROM write error";
+ case 0x217: return "IOA timeout detected";
+ case 0x219: return "IOCHK#, EISA add-in board parity or other catastrophic error";
+ case 0x21b: return "EISA fail-safe timer timeout";
+ case 0x21d: return "EISA bus time-out";
+ case 0x21f: return "EISA software generated NMI";
+ case 0x221: return "unexpected ev5 IRQ[3] interrupt";
+ default: return "unknown mcheck";
+ }
+}
+
+void
+mcheck(Ureg *ur, void *x)
+{
+ Mcheck *m;
+ uvlong *data;
+ int i, col;
+
+ m = x;
+ data = x;
+ iprint("panic: Machine Check @%#p: %s (%lux) len %lud\n",
+ m, smcheck(m->code), m->code, m->len);
+ iprint("proc offset %lux sys offset %lux\n", m->procoff, m->sysoff);
+ for (i = 0, col = 0; i < m->len/8; i++) {
+ iprint("%.3x: %.16llux%s", 8*i, data[i], (col == 2) ? "\n" : " ");
+ if (col++ == 2)
+ col = 0;
+ }
+ if(col != 2)
+ print("\n");
+ print("\n");
+ dumpregs(ur);
+ prflush();
+ firmware();
+}
+
+void
+intr(Ureg *ur)
+{
+ int i, vno;
+ Vctl *ctl, *v;
+ Mach *mach;
+
+ vno = (ulong)ur->a1>>4;
+ vno -= 0x80;
+ if(vno < nelem(vctl) && (ctl = vctl[vno])){
+ if(ctl->isintr){
+ m->intr++;
+ if(vno >= VectorPIC && vno <= MaxVectorPIC)
+ m->lastintr = vno-VectorPIC;
+ }
+
+ if(ctl->isr)
+ ctl->isr(vno);
+ for(v = ctl; v != nil; v = v->next) {
+ if(v->f)
+ v->f(ur, v->a);
+ }
+
+ if(ctl->eoi)
+ ctl->eoi(vno);
+
+ if(ctl->isintr && up)
+ preempted();
+ }
+ else if(vno >= VectorPIC && vno <= MaxVectorPIC){
+ /*
+ * An unknown interrupt.
+ * Check for a default IRQ7. This can happen when
+ * the IRQ input goes away before the acknowledge.
+ * In this case, a 'default IRQ7' is generated, but
+ * the corresponding bit in the ISR isn't set.
+ * In fact, just ignore all such interrupts.
+ */
+ iprint("cpu%d: spurious interrupt %d, last %d",
+ m->machno, vno-VectorPIC, m->lastintr);
+ for(i = 0; i < 32; i++){
+ if(!(active.machs & (1<<i)))
+ continue;
+ mach = MACHP(i);
+ if(m->machno == mach->machno)
+ continue;
+ iprint(": cpu%d: last %d", mach->machno, mach->lastintr);
+ }
+ iprint("\n");
+ m->spuriousintr++;
+ return;
+ }
+ else{
+ dumpregs(ur);
+ print("unknown intr: %d\n", vno); /* */
+ }
+}
+
+void
+trap(Ureg *ur)
+{
+ char buf[ERRMAX];
+ int clockintr, user, x;
+
+ user = ur->status&UMODE;
+
+ if(user){
+ up = m->proc;
+ up->dbgreg = ur;
+ }
+ clockintr = 0;
+ switch ((int)ur->type) {
+ case 1: /* arith */
+ fptrap(ur);
+ break;
+ case 2: /* bad instr or FEN */
+ illegal(ur);
+ break;
+
+ case 3: /* intr */
+ m->intr++;
+ switch ((int)ur->a0) {
+ case 0: /* interprocessor */
+ panic("interprocessor intr");
+ break;
+ case 1: /* clock */
+ clockintr = 1;
+ clock(ur);
+ break;
+ case 2: /* machine check */
+ mcheck(ur, (void*)(KZERO|(ulong)ur->a2));
+ break;
+ case 3: /* device */
+ intr(ur);
+ break;
+ case 4: /* perf counter */
+ panic("perf count");
+ break;
+ default:
+ panic("bad intr");
+ break;
+ }
+ break;
+
+ case 4: /* memory fault */
+ if(up == 0)
+ kernfault(ur, (ulong)ur->a1);
+
+ x = up->insyscall;
+ up->insyscall = 1;
+ spllo();
+ faultalpha(ur);
+ up->insyscall = x;
+ break;
+ case 6: /* alignment fault */
+ ur->pc -= 4;
+ sprint(buf, "trap: unaligned addr 0x%lux", (ulong)ur->a0);
+ fataltrap(ur, buf);
+ break;
+ default: /* cannot happen */
+ panic("bad trap type %d", (int)ur->type);
+ break;
+ }
+
+ splhi();
+
+ /* delaysched set because we held a lock or because our quantum ended */
+ if(up && up->delaysched && clockintr){
+ sched();
+ splhi();
+ }
+
+ if(user){
+ if(up->procctl || up->nnote)
+ notify(ur);
+ kexit(ur);
+ }
+}
+
+void
+trapinit(void)
+{
+ splhi();
+ wrent(0, intr0);
+ wrent(1, arith);
+ wrent(2, fault0);
+ wrent(3, illegal0);
+ wrent(4, unaligned);
+ wrent(5, syscall0);
+}
+
+void
+fataltrap(Ureg *ur, char *reason)
+{
+ char buf[ERRMAX];
+
+ if(ur->status&UMODE) {
+ spllo();
+ sprint(buf, "sys: %s", reason);
+ postnote(up, 1, buf, NDebug);
+ return;
+ }
+ print("kernel %s pc=%lux\n", reason, (ulong)ur->pc);
+ dumpregs(ur);
+ dumpstack();
+ if(m->machno == 0)
+ spllo();
+ exit(1);
+}
+
+void
+kernfault(Ureg *ur, int code)
+{
+ Label l;
+ char *s;
+
+ splhi();
+ if (code == 0)
+ s = "read";
+ else if (code == 1)
+ s = "write";
+ else
+ s = "ifetch";
+ print("panic: kfault %s VA=0x%lux\n", s, (ulong)ur->a0);
+ print("u=%#p status=0x%lux pc=0x%lux sp=0x%lux\n",
+ up, (ulong)ur->status, (ulong)ur->pc, (ulong)ur->sp);
+ dumpregs(ur);
+ l.sp = ur->sp;
+ l.pc = ur->pc;
+ dumpstack();
+ exit(1);
+}
+
+void
+dumpregs(Ureg *ur)
+{
+ int i, col;
+ uvlong *l;
+
+ if(up)
+ print("registers for %s %ld\n", up->text, up->pid);
+ else
+ print("registers for kernel\n");
+
+ l = &ur->type;
+ col = 0;
+ for (i = 0; i < sizeof regname/sizeof(char*); i++, l++) {
+ print("%-7s%.16llux%s", regname[i], *l, col == 2 ? "\n" : " ");
+ if (col++ == 2)
+ col = 0;
+ }
+ print("\n");
+}
+
+
+/*
+ * Fill in enough of Ureg to get a stack trace, and call a function.
+ * Used by debugging interface rdb.
+ */
+static void
+getpcsp(ulong *pc, ulong *sp)
+{
+ *pc = getcallerpc(&pc);
+ *sp = (ulong)&pc-8;
+}
+
+void
+callwithureg(void (*fn)(Ureg*))
+{
+ Ureg ureg;
+
+ getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
+ ureg.r26 = getcallerpc(&fn);
+ fn(&ureg);
+}
+
+void
+_dumpstack(Ureg *ureg)
+{
+ ulong l, sl, el, v, i, instr, op;
+ extern ulong etext;
+
+ l=(ulong)&l;
+ if(l&4)
+ l += 4;
+ if(up == 0){
+ el = (ulong)m+BY2PG;
+ sl = el-KSTACK;
+ }
+ else{
+ sl = (ulong)up->kstack;
+ el = sl + KSTACK;
+ }
+ if(l > el || l < sl){
+ el = (ulong)m+BY2PG;
+ sl = el-KSTACK;
+ }
+ if(l > el || l < sl)
+ return;
+ print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", (ulong)ureg->pc, (ulong)ureg->sp, (ulong)ureg->r26);
+
+ i = 0;
+ for(; l<el; l+=8){
+ v = *(ulong*)l - 4;
+ if(KTZERO < v && v < (ulong)&etext && (v&3) == 0){
+ /*
+ * Check for JSR/BSR
+ */
+ instr = *(ulong*)v;
+ op = (instr>>26);
+ if(op == 26 || op == 52){
+ print("%lux=%lux ", l, v);
+ i++;
+ }
+ }
+ if(i == 4){
+ i = 0;
+ print("\n");
+ }
+ }
+ if(i)
+ print("\n");
+}
+
+void
+dumpstack(void)
+{
+ callwithureg(_dumpstack);
+}
+
+int
+notify(Ureg *ur)
+{
+ int l;
+ ulong sp;
+ Note *n;
+
+ if(up->procctl)
+ procctl(up);
+ if(up->nnote == 0)
+ return 0;
+
+ spllo();
+ qlock(&up->debug);
+ up->notepending = 0;
+
+ if(up->fpstate == FPactive){
+ savefpregs(&up->fpsave);
+ up->fpstate = FPinactive;
+ }
+ up->fpstate |= FPillegal;
+
+ n = &up->note[0];
+ if(strncmp(n->msg, "sys:", 4) == 0) {
+ l = strlen(n->msg);
+ if(l > ERRMAX-15) /* " pc=0x12345678\0" */
+ l = ERRMAX-15;
+
+ sprint(n->msg+l, " pc=0x%lux", (ulong)ur->pc);
+ }
+
+ if(n->flag != NUser && (up->notified || up->notify==0)) {
+ if(n->flag == NDebug)
+ pprint("suicide: %s\n", n->msg);
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag!=NDebug);
+ }
+
+ if(up->notified) {
+ qunlock(&up->debug);
+ splhi();
+ return 0;
+ }
+
+ if(!up->notify) {
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag!=NDebug);
+ }
+ sp = ur->usp & ~(BY2V-1);
+ sp -= sizeof(Ureg);
+
+ if(!okaddr((ulong)up->notify, BY2WD, 0)
+ || !okaddr(sp-ERRMAX-6*BY2WD, sizeof(Ureg)+ERRMAX-6*BY2WD, 1)) {
+ pprint("suicide: bad address or sp in notify\n");
+print("suicide: bad address or sp in notify\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+
+ memmove((Ureg*)sp, ur, sizeof(Ureg));
+ *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
+ up->ureg = (void*)sp;
+ sp -= 2*BY2WD+ERRMAX;
+ memmove((char*)sp, up->note[0].msg, ERRMAX);
+ sp -= 4*BY2WD;
+ *(ulong*)(sp+3*BY2WD) = sp+4*BY2WD; /* arg 2 is string */
+ ur->r0 = (ulong)up->ureg; /* arg 1 (R0) is ureg* */
+ *(ulong*)(sp+2*BY2WD) = (ulong)up->ureg; /* arg 1 0(FP) is ureg* */
+ *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
+ ur->usp = sp;
+ ur->pc = (ulong)up->notify;
+ up->notified = 1;
+ up->nnote--;
+ memmove(&up->lastnote, &up->note[0], sizeof(Note));
+ memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
+
+ qunlock(&up->debug);
+ splhi();
+ return 1;
+}
+
+/*
+ * Check that status is OK to return from note.
+ */
+int
+validstatus(ulong kstatus, ulong ustatus)
+{
+ if((kstatus & 7) != (ustatus & 7))
+ return 0;
+ if((ustatus&UMODE) != UMODE)
+ return 0;
+ return 1;
+}
+
+/*
+ * Return user to state before notify()
+ */
+void
+noted(Ureg *kur, Ureg **urp, ulong arg0)
+{
+ Ureg *nur;
+ ulong oureg, sp;
+
+ qlock(&up->debug);
+ if(arg0!=NRSTR && !up->notified) {
+ qunlock(&up->debug);
+ pprint("call to noted() when not notified\n");
+print("call to noted() when not notified\n");
+ pexit("Suicide", 0);
+ }
+ up->notified = 0;
+
+ up->fpstate &= ~FPillegal;
+
+ nur = up->ureg;
+
+ oureg = (ulong)nur;
+ if((oureg & (BY2V-1))
+ || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
+ pprint("bad ureg in noted or call to noted() when not notified\n");
+print("bad ureg in noted or call to noted() when not notified\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+
+ if(!validstatus(kur->status, nur->status)) {
+ qunlock(&up->debug);
+ pprint("bad noted ureg status %lux\n", (ulong)nur->status);
+print("bad noted ureg status %lux\n", (ulong)nur->status);
+ pexit("Suicide", 0);
+ }
+
+ memmove(*urp, up->ureg, sizeof(Ureg));
+ switch(arg0) {
+ case NCONT:
+ case NRSTR:
+ if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
+ pprint("suicide: trap in noted\n");
+print("suicide: trap in noted\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+ up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
+ qunlock(&up->debug);
+ splhi();
+ rfnote(urp);
+ break;
+
+ case NSAVE:
+ if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
+ pprint("suicide: trap in noted\n");
+print("suicide: trap in noted\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+ qunlock(&up->debug);
+ sp = oureg-4*BY2WD-ERRMAX;
+ splhi();
+ (*urp)->sp = sp;
+ ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
+ ((ulong*)sp)[0] = 0; /* arg 0 is pc */
+ (*urp)->r0 = oureg; /* arg 1 is ureg* */
+ rfnote(urp);
+ break;
+
+ default:
+ pprint("unknown noted arg 0x%lux\n", arg0);
+print("unknown noted arg 0x%lux\n", arg0);
+ up->lastnote.flag = NDebug;
+ /* fall through */
+
+ case NDFLT:
+ if(up->lastnote.flag == NDebug)
+ pprint("suicide: %s\n", up->lastnote.msg);
+ qunlock(&up->debug);
+ pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
+ }
+}
+
+#include "../port/systab.h"
+
+long
+syscall(Ureg *aur)
+{
+ int i;
+ char *e;
+ long ret;
+ ulong sp;
+ Ureg *ur;
+ ulong scallnr;
+
+ m->syscall++;
+ up = m->proc;
+ up->insyscall = 1;
+ ur = aur;
+ up->pc = ur->pc;
+ up->dbgreg = aur;
+ ur->type = 5; /* for debugging */
+
+ scallnr = ur->r0;
+ up->scallnr = ur->r0;
+
+ if(scallnr == RFORK && up->fpstate == FPactive){
+ savefpregs(&up->fpsave);
+ up->fpstate = FPinactive;
+//print("SR=%lux+", up->fpsave.fpstatus);
+ }
+ spllo();
+
+ sp = ur->sp;
+ up->nerrlab = 0;
+ ret = -1;
+ if(!waserror()) {
+ if(scallnr >= nsyscall || systab[scallnr] == nil){
+ pprint("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc);
+ postnote(up, 1, "sys: bad sys call", NDebug);
+ error(Ebadarg);
+ }
+
+ if(sp & (BY2WD-1)){ /* XXX too weak? */
+ pprint("odd sp in sys call pc %lux sp %lux\n",
+ (ulong)ur->pc, (ulong)ur->sp);
+ postnote(up, 1, "sys: odd stack", NDebug);
+ error(Ebadarg);
+ }
+
+ if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)))
+ validaddr(sp, sizeof(Sargs), 0);
+
+ up->s = *((Sargs*)(sp+2*BY2WD));
+ up->psstate = sysctab[scallnr];
+ ret = systab[scallnr](up->s.args);
+ poperror();
+ }else{
+ /* failure: save the error buffer for errstr */
+ e = up->syserrstr;
+ up->syserrstr = up->errstr;
+ up->errstr = e;
+ }
+ if(up->nerrlab){
+ print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
+ for(i = 0; i < NERR; i++)
+ print("sp=%lux pc=%lux\n",
+ up->errlab[i].sp, up->errlab[i].pc);
+ panic("error stack");
+ }
+
+ up->nerrlab = 0;
+ up->psstate = 0;
+ up->insyscall = 0;
+ if(scallnr == NOTED) /* ugly hack */
+ noted(ur, &aur, *(ulong*)(sp+2*BY2WD)); /* doesn't return */
+
+ if(scallnr!=RFORK && (up->procctl || up->nnote)){
+ ur->r0 = ret; /* load up for noted() */
+ if(notify(ur))
+ return ur->r0;
+ }
+
+ return ret;
+}
+
+void
+forkchild(Proc *p, Ureg *ur)
+{
+ Ureg *cur;
+
+ p->sched.sp = (ulong)p->kstack+KSTACK-(4*BY2WD+sizeof(Ureg));
+ p->sched.pc = (ulong)forkret;
+
+ cur = (Ureg*)(p->sched.sp+4*BY2WD);
+ memmove(cur, ur, sizeof(Ureg));
+
+ /* Things from bottom of syscall we never got to execute */
+ p->psstate = 0;
+ p->insyscall = 0;
+}
+
+static
+void
+linkproc(void)
+{
+ spllo();
+ up->kpfun(up->kparg);
+ pexit("kproc exiting", 0);
+}
+
+void
+kprocchild(Proc *p, void (*func)(void*), void *arg)
+{
+ p->sched.pc = (ulong)linkproc;
+ p->sched.sp = (ulong)p->kstack+KSTACK;
+
+ p->kpfun = func;
+ p->kparg = arg;
+}
+
+long
+execregs(ulong entry, ulong ssize, ulong nargs)
+{
+ Ureg *ur;
+ ulong *sp;
+
+ sp = (ulong*)(USTKTOP - ssize);
+ *--sp = nargs;
+
+ ur = (Ureg*)up->dbgreg;
+ ur->usp = (ulong)sp;
+ ur->pc = entry;
+ return USTKTOP-BY2WD; /* address of user-level clock */
+}
+
+ulong
+userpc(void)
+{
+ Ureg *ur;
+
+ ur = (Ureg*)up->dbgreg;
+ return ur->pc;
+}
+
+/* This routine must save the values of registers the user is not permitted to write
+ * from devproc and then restore the saved values before returning
+ */
+void
+setregisters(Ureg *xp, char *pureg, char *uva, int n)
+{
+ ulong status;
+
+ status = xp->status;
+ memmove(pureg, uva, n);
+ xp->status = status;
+}
+
+/* Give enough context in the ureg to produce a kernel stack for
+ * a sleeping process
+ */
+void
+setkernur(Ureg *xp, Proc *p)
+{
+ xp->pc = p->sched.pc;
+ xp->sp = p->sched.sp;
+ xp->r26 = (ulong)sched;
+}
+
+ulong
+dbgpc(Proc *p)
+{
+ Ureg *ur;
+
+ ur = p->dbgreg;
+ if(ur == 0)
+ return 0;
+
+ return ur->pc;
+}
+
+void
+illegal(Ureg *ur)
+{
+ switch ((int)ur->a0) {
+ case 0: /* breakpoint */
+ ur->pc -= 4;
+ fataltrap(ur, "breakpoint");
+ break;
+ case 1: /* bugchk */
+ fataltrap(ur, "trap: bugchk");
+ break;
+ case 2: /* gentrap */
+ fataltrap(ur, "trap: gentrap");
+ break;
+ case 3: /* FEN */
+ fen(ur);
+ break;
+ case 4: /* opDEC */
+ fataltrap(ur, "trap: illegal instruction");
+ break;
+ default:
+ panic("illegal illegal %d", (int)ur->a0);
+ break;
+ }
+}
+
+void
+fen(Ureg *ur)
+{
+ if(up){
+ switch(up->fpstate){
+ case FPinit:
+ restfpregs(&initfp);
+ up->fpstate = FPactive;
+//print("EI=%lux+", initfp.fpstatus);
+ return;
+
+ case FPinactive:
+ restfpregs(&up->fpsave);
+ up->fpstate = FPactive;
+//print("EIA=%lux+", up->fpsave.fpstatus);
+ return;
+ }
+ }
+ fataltrap(ur, "trap: floating enable"); /* should never happen */
+}
diff --git a/sys/src/9/bitsy/Booting101 b/sys/src/9/bitsy/Booting101
new file mode 100755
index 000000000..56b20991b
--- /dev/null
+++ b/sys/src/9/bitsy/Booting101
@@ -0,0 +1,245 @@
+
+
+The bitsy comes with Wince. To get to Plan 9, you will need a serial cable,
+a Windows machine with a serial interface, the CDROM that comes with the bitsy,
+and a Plan 9 machine with a serial interface. The Windows machine is used to
+get the Linux boot loader onto the bitsy (and to save away wince, if you so
+desire). The Plan 9 machine is used to get the plan 9 kernel and a read only
+file system onto the bitsy.
+
+0. charge up the bitsy.
+
+1. go to
+ ftp://ftp.handhelds.org/pub/linux/compaq/ipaq/stable/install.html
+Get the latest version of the Linux "osloader" and "bootldr" programs
+(we have tried versions 1.3.0 and 0000-2.14.8, respectively; newest
+versions seem not to allow you to suspend your bitsy due to a bug
+which is probably ours). You can find them all at
+www.collyer.net/who/geoff/9/bitsy/.
+
+2. Use ActiveSync to copy osloader and bootldr to the bitsy. Copy or
+rename the bootldr binary to "bootldr" on Windows, then copy it to the
+bitsy; trying to rename it on WinCE won't produce the right result.
+
+Steps 3 - 7 may work on a Pocket PC bitsy, but see Steps 3a - 7a
+if they don't or if you have a Pocket PC 2002 bitsy.
+
+3. Run osloader by clicking on it under the WinCE File Explorer
+
+4. Use osloader to save your WinCE flash away. This takes a while,
+as it's 16MB over a 115,200 baud line.
+
+5. Select "Run" from the osloader menu. Ignore "Run from RAM"; it's
+not needed.
+
+6. At this point, the bitsy's screen turns blank, but you can still
+talk to the bitsy over its serial port. The serial port is connected
+to the OS loader's terminal program. On Windows, you have to exit
+ActiveSync before the serial port is available for a terminal program.
+I moved the bitsy and its cable over to a Plan 9 machine and connected
+using "con -b 115200 /dev/eia[01]" to talk to the console. The
+command "help" lists the OS loader's commands.
+
+7. Now you need to download the BOOT loader program into flash (right
+now, you're only running the OS loader program out of RAM; rebooting
+will get you back to WinCE). In the con window, "load bootldr" to the
+bitsy. It will indicate that it's starting an xmodem download.
+Under con, type "Ctrl-\" to get a ">>>" prompt. At this prompt, you
+want to run Plan 9's xms program to pipe the bootldr program to the
+bitsy. For example, to download /tmp/bootldr, type "!xms /tmp/bootldr".
+
+If this step works successfully, the OS loader will print out some sort
+of OK checksum message.
+
+If you have a Pocket PC 2002 or steps 3 - 7 above didn't work for you,
+try 3a - 7a.
+
+3a. Copy BootBlaster (also) to the bitsy via ActiveSync.
+
+4a. Save your flash by running osloader and selecting "Flash->Save to
+File". As it produces 4MB files, use ActiveSync to copy them off the
+bitsy.
+
+5a. Move the bitsy and its cable over to a Plan 9 machine and connect
+using "con -b 115200 /dev/eia[01]" to talk to the console.
+
+6a. Run BootBlaster by clicking on it under the WinCE File Explorer.
+
+7a. Select "Program"; it should copy "bootldr" into your flash in
+about 15 seconds.
+
+8. Reboot your bitsy (either cycle the power or use the reset
+switch). The new boot loader runs out of Flash. You'll get the linux
+penguin splash screen and a bunch of options triggered by buttons.
+Pick the one that gets you to the boot loader.
+
+9. Make the partitions you need in the bitsy's flash, type, using
+the con program:
+ partition reset
+ partition define bootldr 0x000000 0x040000 2
+ partition define params 0x040000 0x040000 0
+ partition define kernel 0x080000 0x0c0000 0
+ partition define user 0x140000 0x0c0000 0
+ partition define ramdisk 0x200000 0x600000 0
+ partition define fs 0x800000 0x800000 0
+ params save
+
+These are the partitions as shown by partition show:
+ boot> partition show
+ argv[1]=partition
+ npartitions=00000006
+ bootldr
+ base: 00000000
+ size: 00040000
+ flags: 00000002
+ params
+ base: 00040000
+ size: 00040000
+ flags: 00000000
+ kernel
+ base: 00080000
+ size: 000C0000
+ flags: 00000000
+ user
+ base: 00140000
+ size: 000C0000
+ flags: 00000000
+ ramdisk
+ base: 00200000
+ size: 00600000
+ flags: 00000000
+ fs
+ base: 00800000
+ size: 00800000
+ flags: 00000000
+
+After each line you'll get a message like `defining partition: params'.
+Different versions of the bootloader predefine different partitions.
+The bootldr partition is usually predefined, so you don't have to remake
+that. You may have to delete one or two partitions. The command is
+ partition delete <name>
+Make sure the partition layout is as given above; some of this knowledge is
+built into the kernel.
+
+10. Before you can fill the new partitions with a kernel and a read-only
+file system, you'll have to make them. In the directory /sys/src/9/bitsy,
+type mk and mk paqdisk. Before mk-ing paqdisk, make sure you have all
+the necessary arm binaries installed in /arm and examine the file
+paqfiles/mfs to see what you need to change for connecting to your local
+file servers.
+
+11. Now you can type "load kernel". The boot loader will prompt for
+another xmodem download. Again escape using "Ctrl-\", then use
+"!xms /sys/src/9/bitsy/9bitsy" (or "!xms /arm/9bitsy" if you've already
+installed it).
+
+12. Download the ramdisk, using "load ramdisk" and
+"!xms /sys/src/9/bitsy/paqdisk" (or "!xms /arm/paqdisk" if you've already
+installed it), similarly to 10, above.
+
+13. Type `boot' or `boot flash' depending on your version of the boot loader.
+If you need the latter, you may want to
+
+ set boot_type flash
+ params save
+
+to make boot flash the default.
+
+You'll get a Dutch flag (or a French one, if you hold the iPaq the wrong way),
+then the boot screen will say, on the serial port, thus in your con window:
+
+ root is from [paq]:
+
+Just wait a while or hit enter in the con window and it'll continue.
+
+14. The bitsy will now want to calibrate the screen. It'll put up a
+series of crosses that you should press the center of. Hold the pen
+down over each cross for a second or so; aim carefully. Hold the
+machine in your hand the way you'ld normally use it or the calibration
+could be off since there is depth to the glass in the screen.
+
+15. You'll get a new screen with a single line at the top and a
+keyboard/scribble area at the bottom. This is a simple one file
+editor. This file is similar to plan9.ini on PC's. There may be
+garbage on the top line. If there is, delete the garbage letters.
+(Be careful here: the backspace and delete keys are adjacent on the
+wee keyboard and it's much too easy to hit delete instead of
+backspace, especially if you haven't calibrated the screen dead-on.)
+You should be left with a single line containing (with different
+numbers):
+ calibrate='-16374 22919 251 -24'
+You need to enter a few more things, including, but not limited to:
+
+ user=<user-name>
+ wvkey1=<key string>
+ wvkey2=<key string>
+ wvkey3=<key string>
+ wvtxkey=<key string>
+ wvessid=<wavelan name>
+ auth=<ip address>
+ cpu=<ip address>
+ proxy=<ip address>
+ fs=<ip address>
+
+Your best bet is to copy these off a working bitsy. wv*key* only
+matter if your wireless network is encrypted. When roaming the world,
+omit wv*. When you're done, hit the "ESC" key on the simulated
+keyboard, or the side button near the word iPAQ on the bitsy. The
+system will now come up as you. However, you'll get a message about
+the flash file system being corrupted, because we haven't yet
+initialized it.
+
+16. To set up the file systems, sweep a window and give the following
+sequence of commands.
+
+ # aux/mkflashfs /dev/flash/fs
+ # aux/flashfs
+
+aux/flashfs created a Plan 9 server in /srv/brzr, which we can use to set up
+default directories.
+
+ # mount -c /srv/brzr /n/brzr
+ # cd /n/brzr
+ # mkdir n usr
+ # mkdir n/fs n/emelie n/choline n/nslocum
+ # mkdir usr/yourname usr/yourfriend
+
+17. For safety, reboot the system:
+
+ # reboot
+
+18. Now reboot, go through the Linux splash screen, the Plan 9 boot
+editor, and sweep yourself a new rio window.
+
+Before you can connect to other machines, you need a way to enter
+passwords and keys into factotum. The easiest way to do this is to
+run
+
+ # auth/fgui &
+
+in the window you just made. The window will disappear (fgui spends
+most of its time hidden), so sweep a new window and run the command
+
+ # mfs
+
+to connect to file servers. You will probably need to modify mfs to
+work in your environment (see point 10), though you can supply many
+of the variables it needs in step 15, and doing
+
+ # import $cpu /net
+
+before running mfs can go a long ways.
+
+19. When you're all set with a working wavelan, you can download new
+kernels more quickly using
+
+ # bitsyload k
+
+and new paqdisks using
+
+ # bitsyload r
+
+(r stands for ramdisk, the name of the partition into which paqdisk goes).
+Note that overwriting the ramdisk partition will cause the read-only file
+system which forms the root of you namespace to fail. You'll need to
+reboot immediately after bytsyload r.
diff --git a/sys/src/9/bitsy/bitsy b/sys/src/9/bitsy/bitsy
new file mode 100755
index 000000000..b87c7354e
--- /dev/null
+++ b/sys/src/9/bitsy/bitsy
@@ -0,0 +1,49 @@
+dev
+ root
+ cons
+ dup
+ env
+ ether netif
+ flash
+ ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
+ kprof
+ mnt
+ µc
+ pcmcia cis
+ draw
+ penmouse
+ pipe
+ proc
+ cap
+ srv
+ ssl
+ uart
+ uda1341
+ sd
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+ gre
+ ipmux
+
+link
+ etherwavelan wavelan
+ ethermedium
+
+misc
+ uartsa1110
+ sdata
+
+port
+ int cpuserver = 1;
+
+boot cpu
+boot
+ paq
+bootdir
+ bootbitsy.out boot
+ /arm/bin/paqfs paqfs
diff --git a/sys/src/9/bitsy/bitsyreset.s b/sys/src/9/bitsy/bitsyreset.s
new file mode 100755
index 000000000..b3607ae09
--- /dev/null
+++ b/sys/src/9/bitsy/bitsyreset.s
@@ -0,0 +1,103 @@
+#include "mem.h"
+
+ // Bitsy development board uses two banks: KM416S4030C,
+ // 12 row address bits, 8 col address bits
+ // Bitsy uses two banks KM416S8030C, 12 row address bits,
+ // 9 col address bits
+ // Have to set DRAC0 to 14 row bits or else you only get 8 col bits
+ // from the formfactor unit configuration registers: 0xF3536257
+mdcnfg: // DRAM Configuration Register 10.2.1
+ WORD 1<<0 | 1<<2 | 0<<3 | 0x5<<4 | 0x3<<8 | 3<<12 | 3<<14
+mdrefr0: // DRAM Refresh Control Register 10.2.2
+ WORD 1<<0 | 0x200<<4 | 1<<21 | 1<<22 | 1 <<31
+mdrefr1: // DRAM Refresh Control Register 10.2.2
+ WORD 1<<0 | 0x200<<4 | 1<<21 | 1<<22
+mdrefr2: // DRAM Refresh Control Register 10.2.2
+ WORD 1<<0 | 0x200<<4 | 1<<20 | 1<<21 | 1<<22
+
+ /* MDCAS settings from [1] Table 10-3 (page 10-18) */
+waveform0:
+ WORD 0xAAAAAAA7
+waveform1:
+ WORD 0xAAAAAAAA
+waveform2:
+ WORD 0xAAAAAAAA
+
+delay: // delay without using memory
+ mov $100, r1 // 200MHz: 100 × (2 instructions @ 5 ns) == 1 ms
+l1:
+ sub $1, r1
+ bgt l1
+ sub $1, r0
+ bgt delay
+ ret
+
+reset:
+ mov $INTREGS+4, r0 // turn off interrupts
+ mov $0, (r0)
+
+ // Is this necessary on wakeup?
+ mov $POWERREGS+14, r0 // set clock speed to 191.7MHz
+ mov $0xb, (r0)
+
+ // This is necessary on hard reset, but not on sleep reset
+ mov $0x80, r0 // wait ±128 µs
+ bl delay
+
+ /* check to see if we're operating out of DRAM */
+ bic $0x000000ff, pc, r4
+ bic $0x0000ff00, r4
+ bic $0x00ff0000, r4
+ cmp r4, $PHYSDRAM0
+ beq dram
+
+dramwakeup:
+
+ mov $POWERREGS+0x4, r1 // Clear DH in Power Manager Sleep Status Register
+ bic $(1<<3), (r1) // DH == DRAM Hold
+ // This releases nCAS/DQM and nRAS/nSDCS pins to make DRAM exit selfrefresh
+
+ /* Set up the DRAM in banks 0 and 1 [1] 10.3 */
+ mov $MEMCONFREGS, r1
+
+ mov mdrefr0, r2 // Turn on K1RUN
+ mov r2, 0x1c(r1)
+
+ mov mdrefr1, r2 // Turn off SLFRSH
+ mov r2, 0x1c(r1)
+
+ mov mdrefr2, r2 // Turn on E1PIN
+ mov r2, 0x1c(r1)
+
+ mov waveform0, r2
+ mov r2, 0x4(r1)
+
+ mov waveform1, r2
+ mov r2, 0x8(r1)
+
+ mov waveform2, r2
+ mov r2, 0xc(r1)
+
+ mov $PHYSDRAM0, r0
+ mov 0x00(r0), r2 // Eight non-burst read cycles
+ mov 0x20(r0), r2
+ mov 0x40(r0), r2
+ mov 0x60(r0), r2
+ mov 0x80(r0), r2
+ mov 0xa0(r0), r2
+ mov 0xc0(r0), r2
+ mov 0xe0(r0), r2
+
+ mov mdcnfg, r2 // Enable memory banks
+ mov r2, 0x0(r1)
+
+ // Is there any use in turning on EAPD and KAPD in the MDREFR register?
+
+ ret
+
+
+
+
+dram:
+
+
diff --git a/sys/src/9/bitsy/clock.c b/sys/src/9/bitsy/clock.c
new file mode 100755
index 000000000..ad04d5947
--- /dev/null
+++ b/sys/src/9/bitsy/clock.c
@@ -0,0 +1,254 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+
+enum {
+ RTCREGS = 0x90010000, /* real time clock registers */
+ RTSR_al = 0x01, /* alarm detected */
+ RTSR_hz = 0x02, /* 1Hz tick */
+ RTSR_ale= 0x04, /* alarm interrupt enable */
+ RTSR_hze= 0x08, /* 1Hz tick enable */
+
+ Never = 0xffffffff,
+};
+
+typedef struct OSTimer
+{
+ ulong osmr[4]; /* match registers */
+ volatile ulong oscr; /* counter register */
+ ulong ossr; /* status register */
+ ulong ower; /* watchdog enable register */
+ ulong oier; /* timer interrupt enable register */
+} OSTimer;
+
+typedef struct RTCregs
+{
+ ulong rtar; /* alarm */
+ ulong rcnr; /* count */
+ ulong rttr; /* trim */
+ ulong dummy; /* hole */
+ ulong rtsr; /* status */
+} RTCregs;
+
+OSTimer *timerregs = (OSTimer*)OSTIMERREGS;
+RTCregs *rtcregs = (RTCregs*)RTCREGS;
+static int clockinited;
+
+static void clockintr(Ureg*, void*);
+static void rtcintr(Ureg*, void*);
+static Tval when; /* scheduled time of next interrupt */
+
+long timeradjust;
+
+enum
+{
+ Minfreq = ClockFreq/HZ, /* At least one interrupt per HZ (50 ms) */
+ Maxfreq = ClockFreq/10000, /* At most one interrupt every 100 µs */
+};
+
+ulong
+clockpower(int on)
+{
+ static ulong savedtime;
+
+ if (on){
+ timerregs->ossr |= 1<<0;
+ timerregs->oier = 1<<0;
+ timerregs->osmr[0] = timerregs->oscr + Minfreq;
+ if (rtcregs->rttr == 0){
+ rtcregs->rttr = 0x8000; // nominal frequency.
+ rtcregs->rcnr = 0;
+ rtcregs->rtar = 0xffffffff;
+ rtcregs->rtsr |= RTSR_ale;
+ rtcregs->rtsr |= RTSR_hze;
+ }
+ if (rtcregs->rcnr > savedtime)
+ return rtcregs->rcnr - savedtime;
+ } else
+ savedtime = rtcregs->rcnr;
+ clockinited = on;
+ return 0L;
+}
+
+void
+clockinit(void)
+{
+ ulong x;
+ ulong id;
+
+ /* map the clock registers */
+ timerregs = mapspecial(OSTIMERREGS, sizeof(OSTimer));
+ rtcregs = mapspecial(RTCREGS, sizeof(RTCregs));
+
+ /* enable interrupts on match register 0, turn off all others */
+ timerregs->ossr |= 1<<0;
+ intrenable(IRQ, IRQtimer0, clockintr, nil, "clock");
+ timerregs->oier = 1<<0;
+
+ /* figure out processor frequency */
+ x = powerregs->ppcr & 0x1f;
+ conf.hz = ClockFreq*(x*4+16);
+ conf.mhz = (conf.hz+499999)/1000000;
+
+ /* get processor type */
+ id = getcpuid();
+
+ print("%lud MHZ ARM, ver %lux/part %lux/step %lud\n", conf.mhz,
+ (id>>16)&0xff, (id>>4)&0xfff, id&0xf);
+
+ /* post interrupt 1/HZ secs from now */
+ when = timerregs->oscr + Minfreq;
+ timerregs->osmr[0] = when;
+
+ /* enable RTC interrupts and alarms */
+ intrenable(IRQ, IRQrtc, rtcintr, nil, "rtc");
+ rtcregs->rttr = 0x8000; // make rcnr 1Hz
+ rtcregs->rcnr = 0; // reset counter
+ rtcregs->rtsr |= RTSR_al;
+ rtcregs->rtsr |= RTSR_ale;
+
+ timersinit();
+
+ clockinited = 1;
+}
+
+/* turn 32 bit counter into a 64 bit one. since todfix calls
+ * us at least once a second and we overflow once every 1165
+ * seconds, we won't miss an overflow.
+ */
+uvlong
+fastticks(uvlong *hz)
+{
+ static uvlong high;
+ static ulong last;
+ ulong x;
+
+ if(hz != nil)
+ *hz = ClockFreq;
+ x = timerregs->oscr;
+ if(x < last)
+ high += 1LL<<32;
+ last = x;
+ return high+x;
+}
+
+ulong
+µs(void)
+{
+ return fastticks2us(fastticks(nil));
+}
+
+void
+timerset(Tval v)
+{
+ ulong next, tics; /* Must be unsigned! */
+ static int count;
+
+ next = v;
+
+ /* post next interrupt: calculate # of tics from now */
+ tics = next - timerregs->oscr - Maxfreq;
+ if (tics > Minfreq){
+ timeradjust++;
+ next = timerregs->oscr + Maxfreq;
+ }
+ timerregs->osmr[0] = next;
+}
+
+static void
+clockintr(Ureg *ureg, void*)
+{
+ /* reset previous interrupt */
+ timerregs->ossr |= 1<<0;
+ when += Minfreq;
+ timerregs->osmr[0] = when; /* insurance */
+
+ timerintr(ureg, when);
+}
+
+void
+rtcalarm(ulong secs)
+{
+ vlong t;
+
+ if (t == 0){
+ iprint("RTC alarm cancelled\n");
+ rtcregs->rtsr &= ~RTSR_ale;
+ rtcregs->rtar = 0xffffffff;
+ } else {
+ t = todget(nil);
+ t = t / 1000000000ULL; // nsec to secs
+ if (secs < t)
+ return;
+ secs -= t;
+ iprint("RTC alarm set to %uld seconds from now\n", secs);
+ rtcregs->rtar = rtcregs->rcnr + secs;
+ rtcregs->rtsr|= RTSR_ale;
+ }
+}
+
+static void
+rtcintr(Ureg*, void*)
+{
+ /* reset interrupt */
+ rtcregs->rtsr&= ~RTSR_ale;
+ rtcregs->rtsr&= ~RTSR_al;
+
+ rtcregs->rtar = 0;
+ iprint("RTC alarm: %lud\n", rtcregs->rcnr);
+}
+
+void
+delay(int ms)
+{
+ ulong start;
+ int i;
+
+ if(clockinited){
+ while(ms-- > 0){
+ start = timerregs->oscr;
+ while(timerregs->oscr-start < ClockFreq/1000)
+ ;
+ }
+ } else {
+ while(ms-- > 0){
+ for(i = 0; i < 1000; i++)
+ ;
+ }
+ }
+}
+
+void
+microdelay(int µs)
+{
+ ulong start;
+ int i;
+
+ µs++;
+ if(clockinited){
+ start = timerregs->oscr;
+ while(timerregs->oscr - start < 1UL+(µs*ClockFreq)/1000000UL)
+ ;
+ } else {
+ while(µs-- > 0){
+ for(i = 0; i < 10; i++)
+ ;
+ }
+ }
+}
+
+/*
+ * performance measurement ticks. must be low overhead.
+ * doesn't have to count over a second.
+ */
+ulong
+perfticks(void)
+{
+ return timerregs->oscr;
+}
diff --git a/sys/src/9/bitsy/dat.h b/sys/src/9/bitsy/dat.h
new file mode 100755
index 000000000..a2e8b410a
--- /dev/null
+++ b/sys/src/9/bitsy/dat.h
@@ -0,0 +1,290 @@
+typedef struct Cisdat Cisdat;
+typedef struct Conf Conf;
+typedef struct Confmem Confmem;
+typedef struct FPU FPU;
+typedef struct FPenv FPenv;
+typedef struct FPsave FPsave;
+typedef struct DevConf DevConf;
+typedef struct Label Label;
+typedef struct Lock Lock;
+typedef struct MMU MMU;
+typedef struct Mach Mach;
+typedef struct Notsave Notsave;
+typedef struct Page Page;
+typedef struct PCMmap PCMmap;
+typedef struct PCMslot PCMslot;
+typedef struct PCMconftab PCMconftab;
+typedef struct PhysUart PhysUart;
+typedef struct PMMU PMMU;
+typedef struct Proc Proc;
+typedef struct Uart Uart;
+typedef struct Ureg Ureg;
+typedef struct Vctl Vctl;
+typedef long Tval;
+
+#pragma incomplete Ureg
+
+typedef void IntrHandler(Ureg*, void*);
+
+#define MAXSYSARG 5 /* for mount(fd, mpt, flag, arg, srv) */
+
+/*
+ * parameters for sysproc.c
+ */
+#define AOUT_MAGIC (E_MAGIC)
+
+struct Lock
+{
+ ulong key;
+ ulong sr;
+ ulong pc;
+ Proc *p;
+ Mach *m;
+ ushort isilock;
+};
+
+struct Label
+{
+ ulong sp;
+ ulong pc;
+};
+
+/*
+ * FPsave.status
+ */
+enum
+{
+ FPinit,
+ FPactive,
+ FPinactive,
+};
+struct FPsave
+{
+ ulong status;
+ ulong control;
+ 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 */
+ 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 copymode; /* 0 is copy on write, 1 is copy on reference */
+ int monitor;
+ ulong ialloc; /* bytes available for interrupt time allocation */
+ ulong pipeqsize; /* size in bytes of pipe queues */
+ ulong hz; /* processor cycle freq */
+ ulong mhz;
+};
+
+/*
+ * MMU stuff in proc
+ */
+enum
+{
+ NCOLOR= 1, /* 1 level cache, don't worry about VCE's */
+ Nmeg= 32, /* maximum size of user space */
+};
+
+struct PMMU
+{
+ Page *l1page[Nmeg]; /* this's process' level 1 entries */
+ ulong l1table[Nmeg]; /* ... */
+ Page *mmufree; /* free mmu pages */
+};
+
+/*
+ * things saved in the Proc structure during a notify
+ */
+struct Notsave
+{
+ int dummy;
+};
+
+#include "../port/portdat.h"
+
+struct Mach
+{
+ int machno; /* physical id of processor */
+ ulong splpc; /* pc of last caller to splhi */
+
+ Proc *proc; /* current process */
+ ulong mmupid; /* process id currently in mmu & cache */
+
+ ulong ticks; /* of the clock since boot time */
+ Label sched; /* scheduler wakeup */
+ Lock alarmlock; /* access to alarm list */
+ void* alarm; /* alarms bound to this clock */
+ int inclockintr;
+
+ Proc* readied; /* for runproc */
+ ulong schedticks; /* next forced context switch */
+
+ /* stats */
+ int tlbfault;
+ int tlbpurge;
+ int pfault;
+ int cs;
+ int syscall;
+ int load;
+ int intr;
+ vlong fastclock; /* last sampled value */
+ uvlong inidle; /* time spent in idlehands() */
+ ulong spuriousintr;
+ int lastintr;
+ int ilockdepth;
+ Perf perf; /* performance counters */
+
+ int flushmmu; /* make current proc flush it's mmu state */
+ Proc *pid2proc[31]; /* what proc holds what pid */
+ int lastpid; /* highest assigned pid slot */
+
+ int cpumhz; /* speed of cpu */
+ vlong cpuhz; /* ... */
+ uvlong cyclefreq; /* Frequency of user readable cycle counter */
+
+ /* save areas for exceptions */
+ ulong sfiq[5];
+ ulong sirq[5];
+ ulong sund[5];
+ ulong sabt[5];
+
+ int stack[1];
+};
+
+/*
+ * Fake kmap since we direct map dram
+ */
+typedef void KMap;
+#define VA(k) ((ulong)(k))
+#define kmap(p) (KMap*)((p)->pa)
+#define kunmap(k)
+
+struct
+{
+ Lock;
+ int machs; /* bitmap of active CPUs */
+ int exiting; /* shutdown */
+ int ispanic; /* shutdown in response to a panic */
+}active;
+
+#define MACHP(n) ((Mach *)(MACHADDR+(n)*BY2PG))
+
+extern Mach *m;
+extern Proc *up;
+
+enum
+{
+ OneMeg= 1024*1024,
+};
+
+/*
+ * PCMCIA structures known by both port/cis.c and the pcmcia driver
+ */
+
+/*
+ * Map between ISA memory space and PCMCIA card memory space.
+ */
+struct PCMmap {
+ ulong ca; /* card address */
+ ulong cea; /* card end address */
+ ulong isa; /* local virtual address */
+ int len; /* length of the ISA area */
+ int attr; /* attribute memory */
+};
+
+/*
+ * a PCMCIA configuration entry
+ */
+struct PCMconftab
+{
+ int index;
+ ushort irqs; /* legal irqs */
+ uchar irqtype;
+ uchar bit16; /* true for 16 bit access */
+ struct {
+ ulong start;
+ ulong len;
+ } io[16];
+ int nio;
+ uchar vpp1;
+ uchar vpp2;
+ uchar memwait;
+ ulong maxwait;
+ ulong readywait;
+ ulong otherwait;
+};
+
+/*
+ * PCMCIA card slot
+ */
+struct PCMslot
+{
+ RWlock;
+
+ Ref ref;
+
+ long memlen; /* memory length */
+ uchar slotno; /* slot number */
+ void *regs; /* i/o registers */
+ void *mem; /* memory */
+ void *attr; /* attribute memory */
+
+ /* status */
+ uchar occupied; /* card in the slot */
+ uchar configed; /* card configured */
+ uchar inserted; /* card just inserted */
+
+ Dev *dev; /* set in ctlwrite `configure' */
+
+ /* cis info */
+ int cisread; /* set when the cis has been read */
+ char verstr[512]; /* version string */
+ int ncfg; /* number of configurations */
+ struct {
+ ushort cpresent; /* config registers present */
+ ulong caddr; /* relative address of config registers */
+ } cfg[8];
+ int nctab; /* number of config table entries */
+ PCMconftab ctab[8];
+ PCMconftab *def; /* default conftab */
+
+ /* maps are fixed */
+ PCMmap memmap;
+ PCMmap attrmap;
+};
+
+/*
+ * hardware info about a device
+ */
+typedef struct {
+ ulong port;
+ int size;
+} Devport;
+
+struct DevConf
+{
+ RWlock; /* write: configure/unconfigure/suspend; read: normal access */
+ ulong mem; /* mapped memory address */
+ Devport *ports; /* ports[0]: mapped i/o regs, access size */
+ int nports; /* always 1 for the bitsy */
+ int itype; /* type of interrupt */
+ ulong intnum; /* interrupt number */
+ char *type; /* card type, mallocated */
+};
+
diff --git a/sys/src/9/bitsy/defont.c b/sys/src/9/bitsy/defont.c
new file mode 100755
index 000000000..ac6cd8b1b
--- /dev/null
+++ b/sys/src/9/bitsy/defont.c
@@ -0,0 +1,291 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+
+/*
+ * /tmp/latin1.6x13, in uncompressed form
+ */
+uchar
+defontdata[] =
+{
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x35,0x33,0x36,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x33,0x20,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2a,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x41,0x0e,0x00,0x60,0xc2,0x0a,0x00,
+ 0x00,0x00,0x60,0xc2,0x00,0x60,0xc2,0x00,0x00,0xa6,0x0c,0x20,0xa0,0x00,0x01,0x83,
+ 0x08,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x0c,0x00,0x00,0x00,0x00,0x0c,0x00,0x03,0x00,0x00,0x00,0x3f,
+ 0x30,0x03,0x1c,0x30,0x00,0x00,0x00,0x83,0x00,0x41,0x02,0x00,0x31,0x85,0x14,0x51,
+ 0xc0,0x00,0x31,0x85,0x14,0x31,0x85,0x14,0x01,0x43,0x18,0x51,0x45,0x00,0x08,0xc6,
+ 0x14,0x51,0x86,0x1c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x02,0x00,
+ 0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x08,0x00,0x0c,0x00,0x73,0xe0,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x85,0x00,0x71,0x24,0x0c,0x11,0x00,0x00,0x00,0x00,0x02,
+ 0x20,0x87,0x3e,0x13,0xe7,0x3e,0x71,0xc0,0x00,0x08,0x08,0x1c,0x70,0x8f,0x1c,0xf3,
+ 0xef,0x9c,0x89,0xc3,0xa2,0x82,0x28,0x9c,0xf1,0xcf,0x1c,0xfa,0x28,0xa2,0x8a,0x2f,
+ 0x9c,0x81,0xc2,0x00,0x30,0x08,0x00,0x08,0x03,0x00,0x80,0x00,0x20,0x60,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x23,0x04,0xaa,0x8f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x0c,0x80,0x00,0x02,0x22,0x12,0x00,0xc0,0x80,0x00,0x03,0x00,
+ 0x48,0x04,0x82,0x60,0x06,0xc0,0x00,0x84,0x80,0x49,0x24,0x08,0x00,0x08,0x80,0x01,
+ 0x40,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x88,0x00,0x00,0x70,0x00,
+ 0x00,0x00,0x04,0x22,0x60,0xc5,0x0a,0x00,0x00,0x00,0x60,0xc5,0x00,0x60,0xc5,0x00,
+ 0x09,0x46,0x0c,0x51,0x40,0x00,0x01,0x83,0x14,0x00,0xc8,0x00,0x1b,0xe0,0x00,0x03,
+ 0x84,0x00,0xc0,0x00,0x00,0xf0,0x0e,0x38,0xc3,0x0c,0x30,0xc2,0x4e,0x38,0x63,0x8e,
+ 0x38,0xe3,0x8c,0x28,0x00,0x85,0x14,0xa2,0xaa,0x08,0x20,0x82,0x00,0x00,0x00,0x02,
+ 0x51,0x88,0x82,0x12,0x08,0x82,0x8a,0x20,0x00,0x10,0x04,0x22,0x89,0x44,0xa2,0x4a,
+ 0x08,0x22,0x88,0x81,0x22,0x82,0x2c,0xa2,0x8a,0x28,0xa2,0x22,0x28,0xa2,0x8a,0x20,
+ 0x90,0x80,0x45,0x00,0x10,0x08,0x00,0x08,0x04,0x80,0x80,0x81,0x20,0x20,0x00,0x00,
+ 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x08,0x20,0x8a,0x94,0x77,0xff,0xff,0x1e,
+ 0xff,0xcf,0xff,0xff,0xc3,0xfc,0x71,0xcf,0x3c,0xf3,0xcf,0x6c,0x71,0xe7,0x1c,0x71,
+ 0xc7,0x3c,0x73,0xd7,0x00,0x02,0x00,0x8a,0x22,0x10,0x51,0x23,0x82,0x00,0x04,0x80,
+ 0x48,0x01,0x0c,0x00,0x0a,0x80,0x00,0x84,0xa0,0x51,0x42,0x80,0x71,0xc7,0x1c,0x71,
+ 0xc7,0xa2,0xfb,0xef,0xbe,0x71,0xc7,0x1c,0x4a,0x27,0x1c,0x71,0xc7,0x00,0x9a,0x28,
+ 0xa2,0x8a,0x27,0x22,0x31,0x88,0x94,0x51,0xc0,0x00,0x31,0x88,0x94,0x31,0x88,0x94,
+ 0x7e,0x83,0x18,0x8a,0x85,0x0c,0x00,0xc6,0x22,0x51,0x88,0x14,0x9f,0xee,0x38,0xe2,
+ 0x0a,0x08,0xa2,0x88,0x22,0x81,0xc8,0x20,0xa2,0x8a,0x28,0xa3,0x48,0x20,0x92,0x08,
+ 0x20,0x82,0x0a,0x28,0x00,0x85,0x14,0xa1,0x4a,0x10,0x20,0x8a,0x88,0x00,0x00,0x04,
+ 0x8a,0x88,0x84,0x32,0x08,0x04,0x8a,0x22,0x08,0x20,0x02,0x22,0x8a,0x24,0xa0,0x4a,
+ 0x08,0x20,0x88,0x81,0x24,0x83,0x6c,0xa2,0x8a,0x28,0xa0,0x22,0x28,0xa2,0x51,0x41,
+ 0x10,0x40,0x48,0x80,0x08,0x08,0x00,0x08,0x04,0x00,0x80,0x00,0x20,0x20,0x00,0x00,
+ 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x08,0x20,0x89,0x2a,0x74,0x71,0xc7,0x7d,
+ 0x7d,0xd7,0x5d,0xf7,0x5f,0x8d,0xf7,0xd7,0x5d,0x75,0xd7,0x2d,0xf7,0xdb,0x7d,0xf7,
+ 0xdf,0x5d,0xf5,0xd7,0x00,0x82,0x0c,0x71,0x42,0x10,0x02,0x14,0x84,0x00,0x08,0x40,
+ 0x48,0x82,0x02,0x00,0x0a,0x80,0x00,0x83,0x10,0x20,0x8d,0x08,0x8a,0x28,0xa2,0x8a,
+ 0x2a,0x20,0x82,0x08,0x20,0x20,0x82,0x08,0x4b,0x28,0xa2,0x8a,0x28,0x80,0x9a,0x28,
+ 0xa2,0x89,0x44,0xa6,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x0c,0x08,0x00,0x00,0x00,0x08,0x00,0xff,0xe8,0x20,0x83,
+ 0x8a,0x1c,0xc2,0x88,0x22,0xe2,0x0e,0x38,0xa2,0x8a,0x28,0xa2,0xce,0x30,0x83,0x8e,
+ 0x38,0xe2,0x8c,0x28,0x00,0x80,0x3e,0x70,0x44,0x00,0x40,0x4f,0x88,0x00,0x00,0x04,
+ 0x88,0x80,0x88,0x52,0xc8,0x04,0x8a,0x27,0x1c,0x43,0xe1,0x02,0x9a,0x24,0xa0,0x4a,
+ 0x08,0x20,0x88,0x81,0x28,0x82,0xaa,0xa2,0x8a,0x28,0xa0,0x22,0x28,0xa2,0x51,0x41,
+ 0x10,0x40,0x40,0x00,0x01,0xcf,0x1c,0x79,0xc4,0x1c,0xb1,0x83,0x24,0x23,0x4b,0x1c,
+ 0xf1,0xeb,0x1c,0xf2,0x28,0xa2,0x8a,0x2f,0x88,0x20,0x80,0x14,0xf5,0xf7,0xdf,0x1d,
+ 0x78,0xcf,0x5d,0xf7,0x47,0x7c,0x71,0xd7,0x5d,0x75,0xd7,0x4c,0x73,0xdf,0x1c,0x71,
+ 0xc7,0x3d,0x73,0xd7,0x00,0x87,0x12,0x51,0x42,0x1c,0x02,0xd4,0x8a,0xf8,0x0b,0x40,
+ 0x30,0x87,0x9c,0x01,0x2a,0x80,0x00,0x80,0x28,0x49,0x42,0x88,0x8a,0x28,0xa2,0x8a,
+ 0x2a,0x20,0x82,0x08,0x20,0x20,0x82,0x08,0x4b,0x28,0xa2,0x8a,0x28,0xa1,0xaa,0x28,
+ 0xa2,0x89,0x44,0xac,0x71,0xc7,0x1c,0x71,0xcf,0x1c,0x71,0xc7,0x1c,0x61,0x86,0x18,
+ 0x7a,0xc7,0x1c,0x71,0xc7,0x00,0x72,0x28,0xa2,0x8a,0x2f,0x22,0x1b,0xee,0x38,0xc2,
+ 0x0e,0x1c,0xa3,0x88,0x14,0x82,0x02,0x08,0xa2,0x8a,0x28,0xa2,0x42,0x20,0x92,0x02,
+ 0x20,0x82,0x8a,0x28,0x00,0x80,0x14,0x28,0x8a,0x00,0x40,0x47,0x3e,0x03,0xe0,0x08,
+ 0x88,0x81,0x1c,0x53,0x2f,0x08,0x71,0xe2,0x08,0x80,0x00,0x84,0xaa,0x27,0x20,0x4b,
+ 0xcf,0x20,0xf8,0x81,0x30,0x82,0xaa,0xa2,0xf2,0x2f,0x1c,0x22,0x25,0x2a,0x20,0x82,
+ 0x10,0x20,0x40,0x00,0x00,0x28,0xa2,0x8a,0x2f,0x22,0xc8,0x81,0x28,0x22,0xac,0xa2,
+ 0x8a,0x2c,0xa2,0x42,0x28,0xa2,0x52,0x21,0x30,0x20,0x60,0x2a,0xec,0x71,0xcf,0x7c,
+ 0x78,0xd7,0x1d,0xfa,0xdf,0x7f,0x7d,0xd7,0x5d,0x75,0xd7,0x6f,0x77,0xdb,0x7f,0x77,
+ 0xdf,0x5d,0x75,0xd7,0x00,0x8a,0x90,0x50,0x80,0x12,0x02,0x93,0x94,0x09,0xea,0x40,
+ 0x03,0xe0,0x00,0x01,0x26,0x8c,0x00,0x07,0x94,0x9a,0xa5,0x90,0x8a,0x28,0xa2,0x8a,
+ 0x2b,0xa0,0xf3,0xcf,0x3c,0x20,0x82,0x08,0xea,0xa8,0xa2,0x8a,0x28,0x92,0xaa,0x28,
+ 0xa2,0x88,0x85,0xa6,0x08,0x20,0x82,0x08,0x22,0xa2,0x8a,0x28,0xa2,0x20,0x82,0x08,
+ 0x8b,0x28,0xa2,0x8a,0x28,0x9e,0x9a,0x28,0xa2,0x8a,0x28,0xa2,0x3b,0xe2,0x20,0x83,
+ 0x8a,0x14,0xc2,0x8e,0x08,0x81,0xce,0x38,0xc3,0x0c,0x30,0xc2,0x4e,0x38,0x63,0x8e,
+ 0x38,0x83,0x8a,0x10,0x00,0x80,0x3e,0x29,0x09,0x80,0x40,0x4f,0x88,0x00,0x00,0x10,
+ 0x88,0x82,0x02,0x90,0x28,0x88,0x88,0x20,0x00,0x40,0x01,0x08,0xab,0xe4,0xa0,0x4a,
+ 0x08,0x26,0x88,0x81,0x28,0x82,0x29,0xa2,0x82,0x2a,0x02,0x22,0x25,0x2a,0x50,0x84,
+ 0x10,0x10,0x40,0x00,0x01,0xe8,0xa0,0x8b,0xe4,0x22,0x88,0x81,0x30,0x22,0xa8,0xa2,
+ 0x8a,0x28,0x18,0x42,0x28,0xaa,0x22,0x22,0x08,0x20,0x80,0x14,0xdf,0x77,0xdf,0x1d,
+ 0x7a,0xcf,0x5c,0x7d,0xdf,0x8c,0x71,0xcf,0x3c,0xf3,0xcf,0x6c,0x71,0xe7,0x1c,0x71,
+ 0xdf,0x5c,0x75,0xef,0x00,0x8a,0x3c,0x53,0xe2,0x0e,0x02,0xd0,0x28,0x09,0xea,0x40,
+ 0x00,0x80,0x00,0x01,0x22,0x8c,0x00,0x00,0x0a,0x28,0x2a,0xa0,0xfb,0xef,0xbe,0xfb,
+ 0xee,0x20,0x82,0x08,0x20,0x20,0x82,0x08,0x4a,0xa8,0xa2,0x8a,0x28,0x8c,0xaa,0x28,
+ 0xa2,0x88,0x86,0x22,0x79,0xe7,0x9e,0x79,0xe7,0xa0,0xfb,0xef,0xbe,0x20,0x82,0x08,
+ 0x8a,0x28,0xa2,0x8a,0x28,0x9e,0xaa,0x28,0xa2,0x8a,0x28,0xa2,0x33,0xee,0x38,0xf0,
+ 0xc5,0x3e,0x72,0x87,0x00,0x79,0xc0,0x00,0x20,0x01,0x0e,0x18,0xa4,0x98,0x49,0x16,
+ 0x1c,0x71,0xc7,0x1c,0x00,0x80,0x14,0x71,0x49,0x00,0x20,0x8a,0x88,0x00,0x00,0x10,
+ 0x88,0x84,0x02,0xf8,0x28,0x90,0x88,0x20,0x00,0x23,0xe2,0x08,0xb2,0x24,0xa0,0x4a,
+ 0x08,0x22,0x88,0x81,0x24,0x82,0x29,0xa2,0x82,0x29,0x02,0x22,0x25,0x2a,0x50,0x84,
+ 0x10,0x10,0x40,0x00,0x02,0x28,0xa0,0x8a,0x04,0x22,0x88,0x81,0x28,0x22,0xa8,0xa2,
+ 0x8a,0x28,0x04,0x42,0x25,0x2a,0x22,0x64,0x08,0x20,0x80,0x2a,0xdc,0x71,0xc3,0xce,
+ 0xb0,0x63,0x5e,0x3f,0xe1,0x8f,0xff,0xf7,0xff,0xbc,0x79,0xd6,0xd9,0xed,0xba,0x78,
+ 0xe3,0x8e,0x38,0xe3,0x00,0x8a,0x08,0x50,0x82,0x02,0x02,0x17,0x94,0x08,0x08,0x40,
+ 0x00,0x80,0x00,0x01,0x22,0x80,0x00,0x00,0x14,0x48,0x44,0xa2,0x8a,0x28,0xa2,0x8a,
+ 0x2a,0x20,0x82,0x08,0x20,0x20,0x82,0x08,0x4a,0x68,0xa2,0x8a,0x28,0x8c,0xca,0x28,
+ 0xa2,0x88,0x84,0x22,0x8a,0x28,0xa2,0x8a,0x2a,0x20,0x82,0x08,0x20,0x20,0x82,0x08,
+ 0x8a,0x28,0xa2,0x8a,0x28,0x80,0xaa,0x28,0xa2,0x8a,0x68,0xa6,0x33,0xe4,0x92,0x41,
+ 0x25,0x08,0x41,0xc4,0x3e,0x41,0x23,0x04,0x20,0x42,0x82,0x28,0xa6,0x94,0x69,0xb5,
+ 0x10,0x41,0x04,0x10,0x00,0x00,0x14,0x22,0xa6,0x80,0x20,0x82,0x00,0x30,0x02,0x20,
+ 0x50,0x88,0x22,0x12,0x28,0x90,0x8a,0x22,0x0c,0x10,0x04,0x00,0x82,0x24,0xa2,0x4a,
+ 0x08,0x22,0x88,0x89,0x22,0x82,0x28,0xa2,0x82,0xa8,0xa2,0x22,0x22,0x36,0x88,0x88,
+ 0x10,0x08,0x40,0x00,0x02,0x28,0xa2,0x8a,0x24,0x1e,0x88,0x81,0x24,0x22,0xa8,0xa2,
+ 0xf1,0xe8,0x22,0x4a,0x65,0x2a,0x51,0xa8,0x08,0x20,0x80,0x14,0xfe,0xdb,0x6f,0xb6,
+ 0xbd,0xef,0x8e,0xf0,0x6f,0xb7,0x3e,0xf7,0xef,0x5f,0x75,0xd6,0x5a,0xe5,0x92,0xbb,
+ 0xef,0xbe,0xfb,0xef,0x00,0x8a,0xbc,0x73,0xe2,0x02,0x01,0x20,0x0a,0x00,0x04,0x80,
+ 0x03,0xe0,0x00,0x01,0x62,0x80,0x00,0x00,0x28,0x78,0x87,0xa2,0x8a,0x28,0xa2,0x8a,
+ 0x2a,0x22,0x82,0x08,0x20,0x20,0x82,0x08,0x4a,0x68,0xa2,0x8a,0x28,0x92,0xca,0x28,
+ 0xa2,0x88,0x84,0x26,0x8a,0x28,0xa2,0x8a,0x2a,0xa2,0x8a,0x28,0xa2,0x20,0x82,0x08,
+ 0x8a,0x28,0xa2,0x8a,0x28,0x8c,0xca,0x69,0xa6,0x99,0xa8,0x9a,0x03,0xe3,0x0c,0x61,
+ 0x26,0x00,0x70,0x86,0x08,0x71,0xc4,0x84,0x20,0x41,0x04,0x48,0xc5,0x98,0x59,0x56,
+ 0x1c,0x71,0xc7,0x1c,0x00,0x80,0x00,0x02,0x40,0x00,0x11,0x00,0x00,0x20,0x07,0x20,
+ 0x23,0xef,0x9c,0x11,0xc7,0x10,0x71,0xc7,0x08,0x08,0x08,0x08,0x7a,0x2f,0x1c,0xf3,
+ 0xe8,0x1c,0x89,0xc6,0x22,0xfa,0x28,0x9c,0x81,0xc8,0x9c,0x21,0xc2,0x22,0x88,0x8f,
+ 0x9c,0x09,0xc0,0x00,0x01,0xef,0x1c,0x79,0xc4,0x02,0x89,0xc9,0x22,0x72,0x28,0x9c,
+ 0x80,0x28,0x1c,0x31,0xa2,0x14,0x88,0x2f,0x86,0x23,0x00,0x2a,0xdf,0x3c,0xe7,0xb6,
+ 0x7f,0xe3,0xde,0x7d,0xe3,0x8e,0xde,0xf7,0xef,0xbe,0xed,0xce,0x99,0xe9,0xaa,0x78,
+ 0xe3,0x8e,0x38,0xe3,0xc0,0x87,0x2a,0x88,0x82,0x12,0x00,0xc0,0x04,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x01,0xa2,0x80,0x10,0x00,0x10,0x08,0xe0,0x9c,0x8a,0x28,0xa2,0x8a,
+ 0x2b,0x9c,0xfb,0xef,0xbe,0x71,0xc7,0x1c,0xf2,0x27,0x1c,0x71,0xc7,0x21,0x71,0xc7,
+ 0x1c,0x70,0x84,0x2c,0x79,0xe7,0x9e,0x79,0xe7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,
+ 0x7a,0x27,0x1c,0x71,0xc7,0x0c,0x71,0xa6,0x9a,0x68,0x2f,0x02,0x03,0xe3,0x0c,0x40,
+ 0xc5,0x00,0x10,0x84,0x08,0x41,0x44,0x84,0x20,0x42,0x02,0x7c,0xa4,0x94,0x49,0x15,
+ 0x04,0x10,0x41,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x02,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x09,0x00,0x00,0x00,0x00,
+ 0x80,0x20,0x00,0x00,0x00,0x00,0x02,0x20,0x00,0x00,0x00,0x14,0xff,0x3c,0xef,0xce,
+ 0xbf,0xfb,0xde,0xfd,0xef,0xae,0xde,0xf7,0xef,0x7f,0x60,0xd6,0xda,0xed,0xba,0xbe,
+ 0xfb,0xef,0xbe,0xfb,0xc0,0x02,0x38,0x00,0x00,0x0c,0x00,0x00,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x10,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,
+ 0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x02,0x28,0x22,0x00,0x04,0x92,0x40,
+ 0x24,0x80,0x70,0x84,0x08,0x41,0x23,0x04,0x38,0x43,0x8e,0x08,0x94,0x98,0x49,0x16,
+ 0x1c,0x71,0xc7,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x06,0x00,0x00,0x00,0x00,
+ 0x80,0x20,0x00,0x00,0x00,0x00,0x01,0xc0,0x00,0x00,0x00,0x2a,0x02,0xdb,0x6f,0xf6,
+ 0xdf,0xe3,0xde,0xfd,0xef,0xb7,0x3e,0xf1,0xef,0x1c,0x7d,0xda,0xd9,0xed,0xba,0x78,
+ 0xe3,0x8e,0x38,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xc8,0x1c,
+ 0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x32,0x35,0x36,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x31,0x33,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x31,
+ 0x20,0x00,0x00,0x02,0x0a,0x00,0x06,0x06,0x00,0x02,0x0c,0x00,0x06,0x0c,0x00,0x04,
+ 0x0d,0x00,0x06,0x12,0x00,0x04,0x0d,0x00,0x06,0x18,0x00,0x04,0x0d,0x00,0x06,0x1e,
+ 0x00,0x03,0x0d,0x00,0x06,0x24,0x00,0x03,0x0d,0x00,0x06,0x2a,0x00,0x04,0x0a,0x00,
+ 0x06,0x30,0x00,0x03,0x0d,0x00,0x06,0x36,0x00,0x04,0x0d,0x00,0x06,0x3c,0x00,0x04,
+ 0x0d,0x00,0x06,0x42,0x00,0x04,0x0d,0x00,0x06,0x48,0x00,0x03,0x0d,0x00,0x06,0x4e,
+ 0x00,0x04,0x0d,0x00,0x06,0x54,0x00,0x03,0x0d,0x00,0x06,0x5a,0x00,0x03,0x0d,0x00,
+ 0x06,0x60,0x00,0x03,0x0d,0x00,0x06,0x66,0x00,0x03,0x0d,0x00,0x06,0x6c,0x00,0x03,
+ 0x0d,0x00,0x06,0x72,0x00,0x03,0x0d,0x00,0x06,0x78,0x00,0x03,0x0d,0x00,0x06,0x7e,
+ 0x00,0x03,0x0d,0x00,0x06,0x84,0x00,0x03,0x0d,0x00,0x06,0x8a,0x00,0x03,0x0d,0x00,
+ 0x06,0x90,0x00,0x03,0x0d,0x00,0x06,0x96,0x00,0x03,0x0d,0x00,0x06,0x9c,0x00,0x03,
+ 0x0d,0x00,0x06,0xa2,0x00,0x03,0x0d,0x00,0x06,0xa8,0x00,0x03,0x0d,0x00,0x06,0xae,
+ 0x00,0x03,0x0d,0x00,0x06,0xb4,0x00,0x03,0x0d,0x00,0x06,0xba,0x00,0x03,0x0d,0x00,
+ 0x06,0xc0,0x00,0x00,0x00,0x00,0x06,0xc6,0x00,0x02,0x0b,0x00,0x06,0xcc,0x00,0x02,
+ 0x05,0x00,0x06,0xd2,0x00,0x03,0x0a,0x00,0x06,0xd8,0x00,0x01,0x0a,0x00,0x06,0xde,
+ 0x00,0x02,0x0b,0x00,0x06,0xe4,0x00,0x02,0x0a,0x00,0x06,0xea,0x00,0x02,0x05,0x00,
+ 0x06,0xf0,0x00,0x02,0x0b,0x00,0x06,0xf6,0x00,0x02,0x0b,0x00,0x06,0xfc,0x00,0x03,
+ 0x0a,0x00,0x06,0x02,0x01,0x04,0x09,0x00,0x06,0x08,0x01,0x09,0x0c,0x00,0x06,0x0e,
+ 0x01,0x06,0x07,0x00,0x06,0x14,0x01,0x09,0x0c,0x00,0x06,0x1a,0x01,0x02,0x0b,0x00,
+ 0x06,0x20,0x01,0x02,0x0b,0x00,0x06,0x26,0x01,0x02,0x0b,0x00,0x06,0x2c,0x01,0x02,
+ 0x0b,0x00,0x06,0x32,0x01,0x02,0x0b,0x00,0x06,0x38,0x01,0x02,0x0b,0x00,0x06,0x3e,
+ 0x01,0x02,0x0b,0x00,0x06,0x44,0x01,0x02,0x0b,0x00,0x06,0x4a,0x01,0x02,0x0b,0x00,
+ 0x06,0x50,0x01,0x02,0x0b,0x00,0x06,0x56,0x01,0x02,0x0b,0x00,0x06,0x5c,0x01,0x00,
+ 0x0d,0x00,0x06,0x62,0x01,0x00,0x0d,0x00,0x06,0x68,0x01,0x02,0x0b,0x00,0x06,0x6e,
+ 0x01,0x00,0x0d,0x00,0x06,0x74,0x01,0x02,0x0b,0x00,0x06,0x7a,0x01,0x02,0x0b,0x00,
+ 0x06,0x80,0x01,0x02,0x0b,0x00,0x06,0x86,0x01,0x02,0x0b,0x00,0x06,0x8c,0x01,0x02,
+ 0x0b,0x00,0x06,0x92,0x01,0x02,0x0b,0x00,0x06,0x98,0x01,0x02,0x0b,0x00,0x06,0x9e,
+ 0x01,0x02,0x0b,0x00,0x06,0xa4,0x01,0x02,0x0b,0x00,0x06,0xaa,0x01,0x02,0x0b,0x00,
+ 0x06,0xb0,0x01,0x02,0x0b,0x00,0x06,0xb6,0x01,0x02,0x0b,0x00,0x06,0xbc,0x01,0x02,
+ 0x0b,0x00,0x06,0xc2,0x01,0x02,0x0b,0x00,0x06,0xc8,0x01,0x02,0x0b,0x00,0x06,0xce,
+ 0x01,0x02,0x0b,0x00,0x06,0xd4,0x01,0x02,0x0b,0x00,0x06,0xda,0x01,0x02,0x0b,0x00,
+ 0x06,0xe0,0x01,0x02,0x0b,0x00,0x06,0xe6,0x01,0x02,0x0c,0x00,0x06,0xec,0x01,0x02,
+ 0x0b,0x00,0x06,0xf2,0x01,0x02,0x0b,0x00,0x06,0xf8,0x01,0x02,0x0b,0x00,0x06,0xfe,
+ 0x01,0x02,0x0b,0x00,0x06,0x04,0x02,0x02,0x0b,0x00,0x06,0x0a,0x02,0x02,0x0b,0x00,
+ 0x06,0x10,0x02,0x02,0x0b,0x00,0x06,0x16,0x02,0x02,0x0b,0x00,0x06,0x1c,0x02,0x02,
+ 0x0b,0x00,0x06,0x22,0x02,0x02,0x0b,0x00,0x06,0x28,0x02,0x02,0x0b,0x00,0x06,0x2e,
+ 0x02,0x02,0x0b,0x00,0x06,0x34,0x02,0x02,0x05,0x00,0x06,0x3a,0x02,0x0b,0x0c,0x00,
+ 0x06,0x40,0x02,0x02,0x05,0x00,0x06,0x46,0x02,0x05,0x0b,0x00,0x06,0x4c,0x02,0x02,
+ 0x0b,0x00,0x06,0x52,0x02,0x05,0x0b,0x00,0x06,0x58,0x02,0x02,0x0b,0x00,0x06,0x5e,
+ 0x02,0x05,0x0b,0x00,0x06,0x64,0x02,0x02,0x0b,0x00,0x06,0x6a,0x02,0x05,0x0d,0x00,
+ 0x06,0x70,0x02,0x02,0x0b,0x00,0x06,0x76,0x02,0x03,0x0b,0x00,0x06,0x7c,0x02,0x03,
+ 0x0d,0x00,0x06,0x82,0x02,0x02,0x0b,0x00,0x06,0x88,0x02,0x02,0x0b,0x00,0x06,0x8e,
+ 0x02,0x05,0x0b,0x00,0x06,0x94,0x02,0x05,0x0b,0x00,0x06,0x9a,0x02,0x05,0x0b,0x00,
+ 0x06,0xa0,0x02,0x05,0x0d,0x00,0x06,0xa6,0x02,0x05,0x0d,0x00,0x06,0xac,0x02,0x05,
+ 0x0b,0x00,0x06,0xb2,0x02,0x05,0x0b,0x00,0x06,0xb8,0x02,0x03,0x0b,0x00,0x06,0xbe,
+ 0x02,0x05,0x0b,0x00,0x06,0xc4,0x02,0x05,0x0b,0x00,0x06,0xca,0x02,0x05,0x0b,0x00,
+ 0x06,0xd0,0x02,0x05,0x0b,0x00,0x06,0xd6,0x02,0x05,0x0d,0x00,0x06,0xdc,0x02,0x05,
+ 0x0b,0x00,0x06,0xe2,0x02,0x02,0x0b,0x00,0x06,0xe8,0x02,0x02,0x0b,0x00,0x06,0xee,
+ 0x02,0x02,0x0b,0x00,0x06,0xf4,0x02,0x02,0x05,0x00,0x06,0xfa,0x02,0x00,0x0d,0x00,
+ 0x06,0x00,0x03,0x00,0x0c,0x00,0x06,0x06,0x03,0x00,0x0d,0x00,0x06,0x0c,0x03,0x00,
+ 0x0d,0x00,0x06,0x12,0x03,0x00,0x0d,0x00,0x06,0x18,0x03,0x00,0x0d,0x00,0x06,0x1e,
+ 0x03,0x00,0x0d,0x00,0x06,0x24,0x03,0x00,0x0d,0x00,0x06,0x2a,0x03,0x00,0x0d,0x00,
+ 0x06,0x30,0x03,0x00,0x0d,0x00,0x06,0x36,0x03,0x00,0x0d,0x00,0x06,0x3c,0x03,0x00,
+ 0x0d,0x00,0x06,0x42,0x03,0x00,0x0d,0x00,0x06,0x48,0x03,0x00,0x0d,0x00,0x06,0x4e,
+ 0x03,0x00,0x0d,0x00,0x06,0x54,0x03,0x00,0x0d,0x00,0x06,0x5a,0x03,0x00,0x0d,0x00,
+ 0x06,0x60,0x03,0x00,0x0d,0x00,0x06,0x66,0x03,0x00,0x0d,0x00,0x06,0x6c,0x03,0x00,
+ 0x0d,0x00,0x06,0x72,0x03,0x00,0x0d,0x00,0x06,0x78,0x03,0x00,0x0d,0x00,0x06,0x7e,
+ 0x03,0x00,0x0d,0x00,0x06,0x84,0x03,0x00,0x0d,0x00,0x06,0x8a,0x03,0x00,0x0d,0x00,
+ 0x06,0x90,0x03,0x00,0x0d,0x00,0x06,0x96,0x03,0x00,0x0d,0x00,0x06,0x9c,0x03,0x00,
+ 0x0d,0x00,0x06,0xa2,0x03,0x00,0x0d,0x00,0x06,0xa8,0x03,0x00,0x0d,0x00,0x00,0xae,
+ 0x03,0x00,0x0d,0x00,0x00,0xb4,0x03,0x00,0x0d,0x00,0x00,0xba,0x03,0x00,0x0d,0x00,
+ 0x00,0xc0,0x03,0x01,0x0c,0x00,0x06,0xc6,0x03,0x02,0x0b,0x00,0x06,0xcc,0x03,0x03,
+ 0x0c,0x00,0x06,0xd2,0x03,0x04,0x0c,0x00,0x06,0xd8,0x03,0x03,0x0b,0x00,0x06,0xde,
+ 0x03,0x02,0x0b,0x00,0x06,0xe4,0x03,0x02,0x0b,0x00,0x06,0xea,0x03,0x01,0x0c,0x00,
+ 0x06,0xf0,0x03,0x03,0x04,0x00,0x06,0xf6,0x03,0x02,0x0b,0x00,0x06,0xfc,0x03,0x01,
+ 0x09,0x00,0x06,0x02,0x04,0x03,0x0c,0x00,0x06,0x08,0x04,0x05,0x09,0x00,0x06,0x0e,
+ 0x04,0x06,0x08,0x00,0x06,0x14,0x04,0x02,0x0b,0x00,0x06,0x1a,0x04,0x01,0x02,0x00,
+ 0x06,0x20,0x04,0x01,0x06,0x00,0x06,0x26,0x04,0x04,0x0a,0x00,0x06,0x2c,0x04,0x01,
+ 0x06,0x00,0x06,0x32,0x04,0x01,0x06,0x00,0x06,0x38,0x04,0x00,0x03,0x00,0x06,0x3e,
+ 0x04,0x05,0x0c,0x00,0x06,0x44,0x04,0x02,0x0b,0x00,0x06,0x4a,0x04,0x06,0x08,0x00,
+ 0x06,0x50,0x04,0x0a,0x0d,0x00,0x06,0x56,0x04,0x01,0x06,0x00,0x06,0x5c,0x04,0x01,
+ 0x07,0x00,0x06,0x62,0x04,0x03,0x0c,0x00,0x06,0x68,0x04,0x00,0x0b,0x00,0x06,0x6e,
+ 0x04,0x00,0x0b,0x00,0x06,0x74,0x04,0x00,0x0b,0x00,0x06,0x7a,0x04,0x02,0x0b,0x00,
+ 0x06,0x80,0x04,0x00,0x0b,0x00,0x06,0x86,0x04,0x00,0x0b,0x00,0x06,0x8c,0x04,0x00,
+ 0x0b,0x00,0x06,0x92,0x04,0x00,0x0b,0x00,0x06,0x98,0x04,0x01,0x0b,0x00,0x06,0x9e,
+ 0x04,0x01,0x0b,0x00,0x06,0xa4,0x04,0x03,0x0b,0x00,0x06,0xaa,0x04,0x02,0x0d,0x00,
+ 0x06,0xb0,0x04,0x00,0x0b,0x00,0x06,0xb6,0x04,0x00,0x0b,0x00,0x06,0xbc,0x04,0x00,
+ 0x0b,0x00,0x06,0xc2,0x04,0x01,0x0b,0x00,0x06,0xc8,0x04,0x00,0x0b,0x00,0x06,0xce,
+ 0x04,0x00,0x0b,0x00,0x06,0xd4,0x04,0x00,0x0b,0x00,0x06,0xda,0x04,0x01,0x0b,0x00,
+ 0x06,0xe0,0x04,0x02,0x0b,0x00,0x06,0xe6,0x04,0x00,0x0b,0x00,0x06,0xec,0x04,0x00,
+ 0x0b,0x00,0x06,0xf2,0x04,0x00,0x0b,0x00,0x06,0xf8,0x04,0x00,0x0b,0x00,0x06,0xfe,
+ 0x04,0x00,0x0b,0x00,0x06,0x04,0x05,0x01,0x0b,0x00,0x06,0x0a,0x05,0x05,0x0b,0x00,
+ 0x06,0x10,0x05,0x01,0x0c,0x00,0x06,0x16,0x05,0x00,0x0b,0x00,0x06,0x1c,0x05,0x00,
+ 0x0b,0x00,0x06,0x22,0x05,0x00,0x0b,0x00,0x06,0x28,0x05,0x01,0x0b,0x00,0x06,0x2e,
+ 0x05,0x00,0x0b,0x00,0x06,0x34,0x05,0x01,0x0b,0x00,0x06,0x3a,0x05,0x01,0x0c,0x00,
+ 0x06,0x40,0x05,0x02,0x0b,0x00,0x06,0x46,0x05,0x02,0x0b,0x00,0x06,0x4c,0x05,0x01,
+ 0x0b,0x00,0x06,0x52,0x05,0x02,0x0b,0x00,0x06,0x58,0x05,0x03,0x0b,0x00,0x06,0x5e,
+ 0x05,0x03,0x0b,0x00,0x06,0x64,0x05,0x05,0x0b,0x00,0x06,0x6a,0x05,0x05,0x0d,0x00,
+ 0x06,0x70,0x05,0x02,0x0b,0x00,0x06,0x76,0x05,0x02,0x0b,0x00,0x06,0x7c,0x05,0x01,
+ 0x0b,0x00,0x06,0x82,0x05,0x03,0x0b,0x00,0x06,0x88,0x05,0x02,0x0b,0x00,0x06,0x8e,
+ 0x05,0x02,0x0b,0x00,0x06,0x94,0x05,0x01,0x0b,0x00,0x06,0x9a,0x05,0x03,0x0b,0x00,
+ 0x06,0xa0,0x05,0x02,0x0b,0x00,0x06,0xa6,0x05,0x02,0x0b,0x00,0x06,0xac,0x05,0x02,
+ 0x0b,0x00,0x06,0xb2,0x05,0x02,0x0b,0x00,0x06,0xb8,0x05,0x01,0x0b,0x00,0x06,0xbe,
+ 0x05,0x02,0x0b,0x00,0x06,0xc4,0x05,0x03,0x0b,0x00,0x06,0xca,0x05,0x03,0x0b,0x00,
+ 0x06,0xd0,0x05,0x04,0x0c,0x00,0x06,0xd6,0x05,0x02,0x0b,0x00,0x06,0xdc,0x05,0x02,
+ 0x0b,0x00,0x06,0xe2,0x05,0x01,0x0b,0x00,0x06,0xe8,0x05,0x03,0x0b,0x00,0x06,0xee,
+ 0x05,0x02,0x0d,0x00,0x06,0xf4,0x05,0x01,0x0d,0x00,0x06,0xfa,0x05,0x03,0x0d,0x00,
+ 0x06,0x00,0x06,0x00,0x00,0x00,0x00,
+
+
+};
+
+int sizeofdefont = sizeof defontdata;
+
+void
+_unpackinfo(Fontchar *fc, uchar *p, int n)
+{
+ int j;
+
+ for(j=0; j<=n; j++){
+ fc->x = p[0]|(p[1]<<8);
+ fc->top = p[2];
+ fc->bottom = p[3];
+ fc->left = p[4];
+ fc->width = p[5];
+ fc++;
+ p += 6;
+ }
+}
diff --git a/sys/src/9/bitsy/devether.c b/sys/src/9/bitsy/devether.c
new file mode 100755
index 000000000..457c09e22
--- /dev/null
+++ b/sys/src/9/bitsy/devether.c
@@ -0,0 +1,599 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+static volatile Ether *etherxx[MaxEther];
+
+static struct {
+ char* type;
+ int (*reset)(Ether*);
+} cards[MaxEther+1];
+
+void
+addethercard(char* t, int (*r)(Ether*))
+{
+ static int ncard;
+
+ if(ncard == MaxEther)
+ panic("too many ether cards");
+ cards[ncard].type = t;
+ cards[ncard].reset = r;
+ ncard++;
+}
+
+void
+etherpower(int on)
+{
+ int i;
+ Ether *ether;
+ /* Power all ether cards on or off */
+
+iprint("etherpower %d\n", on);
+ for (i = 0; i < MaxEther; i++){
+ if ((ether = etherxx[i]) == nil)
+ continue;
+ if(on){
+ if (ether->writer == 0){
+ print("etherpower: already powered up\n");
+ continue;
+ }
+ if (ether->power)
+ ether->power(ether, on);
+ wunlock(ether);
+ /* Unlock when power restored */
+ }else{
+ if (ether->writer != 0){
+ print("etherpower: already powered down\n");
+ continue;
+ }
+ /* Keep locked until power goes back on */
+ wlock(ether);
+ if (ether->power)
+ ether->power(ether, on);
+ }
+ }
+}
+
+int
+etherconfig(int on, char *spec, DevConf *cf)
+{
+ Ether *ether;
+ int n, ctlrno;
+ char name[32], buf[128];
+ char *p, *e;
+
+ ctlrno = atoi(spec);
+ sprint(name, "ether%d", ctlrno);
+
+ if(on == 0)
+ return -1;
+
+ if(etherxx[ctlrno] != nil)
+ return -1;
+
+ ether = malloc(sizeof(Ether));
+ if(ether == nil)
+ panic("etherconfig");
+ ether->DevConf = *cf;
+
+ for(n = 0; cards[n].type; n++){
+ if(strcmp(cards[n].type, ether->type) != 0)
+ continue;
+ if(cards[n].reset(ether))
+ break;
+
+ if(ether->mbps >= 100){
+ netifinit(ether, name, Ntypes, 256*1024);
+ if(ether->oq == 0)
+ ether->oq = qopen(256*1024, Qmsg, 0, 0);
+ }
+ else{
+ netifinit(ether, name, Ntypes, 65*1024);
+ if(ether->oq == 0)
+ ether->oq = qopen(65*1024, Qmsg, 0, 0);
+ }
+ if(ether->oq == 0)
+ panic("etherreset %s", name);
+ ether->alen = Eaddrlen;
+ memmove(ether->addr, ether->ea, Eaddrlen);
+ memset(ether->bcast, 0xFF, Eaddrlen);
+ ether->mbps = 10;
+ ether->minmtu = ETHERMINTU;
+ ether->maxmtu = ETHERMAXTU;
+
+ if(ether->interrupt != nil)
+ intrenable(cf->itype, cf->intnum, ether->interrupt, ether, name);
+
+ p = buf;
+ e = buf+sizeof(buf);
+ p = seprint(p, e, "#l%d: %s: %dMbps port 0x%luX",
+ ctlrno, ether->type, ether->mbps, ether->ports[0].port);
+ if(ether->mem)
+ p = seprint(p, e, " addr 0x%luX", PADDR(ether->mem));
+ if(ether->ports[0].size)
+ p = seprint(p, e, " size 0x%X", ether->ports[0].size);
+ p = seprint(p, e, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
+ ether->ea[0], ether->ea[1], ether->ea[2],
+ ether->ea[3], ether->ea[4], ether->ea[5]);
+ seprint(p, e, "\n");
+ pprint(buf);
+
+ etherxx[ctlrno] = ether;
+ return 0;
+ }
+
+ if (ether->type)
+ free(ether->type);
+ free(ether);
+ return -1;
+}
+
+Chan*
+etherattach(char* spec)
+{
+ ulong ctlrno;
+ char *p;
+ Chan *chan;
+ Ether *ether;
+
+ ctlrno = 0;
+ if(spec && *spec){
+ ctlrno = strtoul(spec, &p, 0);
+ if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
+ error(Ebadarg);
+ }
+ if((ether = etherxx[ctlrno]) == 0)
+ error(Enodev);
+ rlock(ether);
+ if(waserror()) {
+ runlock(ether);
+ nexterror();
+ }
+ chan = devattach('l', spec);
+ chan->dev = ctlrno;
+ if(ether->attach)
+ ether->attach(ether);
+ poperror();
+ runlock(ether);
+ return chan;
+}
+
+static Walkqid*
+etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
+{
+ Walkqid *q;
+ Ether *ether;
+
+ ether = etherxx[chan->dev];
+ rlock(ether);
+ if(waserror()) {
+ runlock(ether);
+ nexterror();
+ }
+ q = netifwalk(ether, chan, nchan, name, nname);
+ poperror();
+ runlock(ether);
+ return q;
+}
+
+static int
+etherstat(Chan* chan, uchar* dp, int n)
+{
+ int s;
+ Ether *ether;
+
+ ether = etherxx[chan->dev];
+ rlock(ether);
+ if(waserror()) {
+ runlock(ether);
+ nexterror();
+ }
+ s = netifstat(ether, chan, dp, n);
+ poperror();
+ runlock(ether);
+ return s;
+}
+
+static Chan*
+etheropen(Chan* chan, int omode)
+{
+ Chan *c;
+ Ether *ether;
+
+ ether = etherxx[chan->dev];
+ rlock(ether);
+ if(waserror()) {
+ runlock(ether);
+ nexterror();
+ }
+ c = netifopen(ether, chan, omode);
+ poperror();
+ runlock(ether);
+ return c;
+}
+
+static void
+ethercreate(Chan*, char*, int, ulong)
+{
+}
+
+static void
+etherclose(Chan* chan)
+{
+ Ether *ether;
+
+ ether = etherxx[chan->dev];
+ rlock(ether);
+ if(waserror()) {
+ runlock(ether);
+ nexterror();
+ }
+ netifclose(ether, chan);
+ poperror();
+ runlock(ether);
+}
+
+static long
+etherread(Chan* chan, void* buf, long n, vlong off)
+{
+ Ether *ether;
+ ulong offset = off;
+ long r;
+
+ ether = etherxx[chan->dev];
+ rlock(ether);
+ if(waserror()) {
+ runlock(ether);
+ nexterror();
+ }
+ if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
+ /*
+ * With some controllers it is necessary to reach
+ * into the chip to extract statistics.
+ */
+ if(NETTYPE(chan->qid.path) == Nifstatqid){
+ r = ether->ifstat(ether, buf, n, offset);
+ goto out;
+ }
+ if(NETTYPE(chan->qid.path) == Nstatqid)
+ ether->ifstat(ether, buf, 0, offset);
+ }
+ r = netifread(ether, chan, buf, n, offset);
+out:
+ poperror();
+ runlock(ether);
+ return r;
+}
+
+static Block*
+etherbread(Chan* chan, long n, ulong offset)
+{
+ Block *b;
+ Ether *ether;
+
+ ether = etherxx[chan->dev];
+ rlock(ether);
+ if(waserror()) {
+ runlock(ether);
+ nexterror();
+ }
+ b = netifbread(ether, chan, n, offset);
+ poperror();
+ runlock(ether);
+ return b;
+}
+
+static int
+etherwstat(Chan* chan, uchar* dp, int n)
+{
+ Ether *ether;
+ int r;
+
+ ether = etherxx[chan->dev];
+ rlock(ether);
+ if(waserror()) {
+ runlock(ether);
+ nexterror();
+ }
+ r = netifwstat(ether, chan, dp, n);
+ poperror();
+ runlock(ether);
+ return r;
+}
+
+static void
+etherrtrace(Netfile* f, Etherpkt* pkt, int len)
+{
+ int i, n;
+ Block *bp;
+
+ if(qwindow(f->in) <= 0)
+ return;
+ if(len > 58)
+ n = 58;
+ else
+ n = len;
+ bp = iallocb(64);
+ if(bp == nil)
+ return;
+ memmove(bp->wp, pkt->d, n);
+ i = TK2MS(MACHP(0)->ticks);
+ bp->wp[58] = len>>8;
+ bp->wp[59] = len;
+ bp->wp[60] = i>>24;
+ bp->wp[61] = i>>16;
+ bp->wp[62] = i>>8;
+ bp->wp[63] = i;
+ bp->wp += 64;
+ qpass(f->in, bp);
+}
+
+Block*
+etheriq(Ether* ether, Block* bp, int fromwire)
+{
+ Etherpkt *pkt;
+ ushort type;
+ int len, multi, tome, fromme;
+ Netfile **ep, *f, **fp, *fx;
+ Block *xbp;
+
+ ether->inpackets++;
+
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ type = (pkt->type[0]<<8)|pkt->type[1];
+ fx = 0;
+ ep = &ether->f[Ntypes];
+
+ multi = pkt->d[0] & 1;
+ /* check for valid multicast addresses */
+ if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){
+ if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
+ if(fromwire){
+ freeb(bp);
+ bp = 0;
+ }
+ return bp;
+ }
+ }
+
+ /* is it for me? */
+ tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
+ fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
+
+ /*
+ * Multiplex the packet to all the connections which want it.
+ * If the packet is not to be used subsequently (fromwire != 0),
+ * attempt to simply pass it into one of the connections, thereby
+ * saving a copy of the data (usual case hopefully).
+ */
+ for(fp = ether->f; fp < ep; fp++){
+ if(f = *fp)
+ if(f->type == type || f->type < 0)
+ if(tome || multi || f->prom){
+ /* Don't want to hear bridged packets */
+ if(f->bridge && !fromwire && !fromme)
+ continue;
+ if(!f->headersonly){
+ if(fromwire && fx == 0)
+ fx = f;
+ else if(xbp = iallocb(len)){
+ memmove(xbp->wp, pkt, len);
+ xbp->wp += len;
+ qpass(f->in, xbp);
+ }
+ else
+ ether->soverflows++;
+ }
+ else
+ etherrtrace(f, pkt, len);
+ }
+ }
+
+ if(fx){
+ if(qpass(fx->in, bp) < 0)
+ ether->soverflows++;
+ return 0;
+ }
+ if(fromwire){
+ freeb(bp);
+ return 0;
+ }
+
+ return bp;
+}
+
+static int
+etheroq(Ether* ether, Block* bp)
+{
+ int len, loopback, s;
+ Etherpkt *pkt;
+
+ ether->outpackets++;
+
+ /*
+ * Check if the packet has to be placed back onto the input queue,
+ * i.e. if it's a loopback or broadcast packet or the interface is
+ * in promiscuous mode.
+ * If it's a loopback packet indicate to etheriq that the data isn't
+ * needed and return, etheriq will pass-on or free the block.
+ * To enable bridging to work, only packets that were originated
+ * by this interface are fed back.
+ */
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
+ if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
+ s = splhi();
+ etheriq(ether, bp, 0);
+ splx(s);
+ }
+
+ if(!loopback){
+ qbwrite(ether->oq, bp);
+ ether->transmit(ether);
+ } else
+ freeb(bp);
+
+ return len;
+}
+
+static long
+etherwrite(Chan* chan, void* buf, long n, vlong)
+{
+ Ether *ether;
+ Block *bp;
+ long l;
+
+ ether = etherxx[chan->dev];
+ rlock(ether);
+ if(waserror()) {
+ runlock(ether);
+ nexterror();
+ }
+ if(NETTYPE(chan->qid.path) != Ndataqid) {
+ l = netifwrite(ether, chan, buf, n);
+ if(l >= 0)
+ goto out;
+ if(n == sizeof("nonblocking")-1 && strncmp((char*)buf, "nonblocking", n) == 0){
+ qnoblock(ether->oq, 1);
+ goto out;
+ }
+ if(ether->ctl!=nil){
+ l = ether->ctl(ether,buf,n);
+ goto out;
+ }
+ error(Ebadctl);
+ }
+
+ if(n > ether->maxmtu)
+ error(Etoobig);
+ if(n < ether->minmtu)
+ error(Etoosmall);
+ bp = allocb(n);
+ memmove(bp->rp, buf, n);
+ memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
+ bp->wp += n;
+
+ l = etheroq(ether, bp);
+out:
+ poperror();
+ runlock(ether);
+ return l;
+}
+
+static long
+etherbwrite(Chan* chan, Block* bp, ulong)
+{
+ Ether *ether;
+ long n;
+
+ n = BLEN(bp);
+ if(NETTYPE(chan->qid.path) != Ndataqid){
+ if(waserror()) {
+ freeb(bp);
+ nexterror();
+ }
+ n = etherwrite(chan, bp->rp, n, 0);
+ poperror();
+ freeb(bp);
+ return n;
+ }
+ ether = etherxx[chan->dev];
+ rlock(ether);
+ if(waserror()) {
+ runlock(ether);
+ nexterror();
+ }
+ if(n > ether->maxmtu){
+ freeb(bp);
+ error(Etoobig);
+ }
+ if(n < ether->minmtu){
+ freeb(bp);
+ error(Etoosmall);
+ }
+ n = etheroq(ether, bp);
+ poperror();
+ runlock(ether);
+ return n;
+}
+
+int
+parseether(uchar *to, char *from)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ for(i = 0; i < 6; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+static void
+etherreset(void)
+{
+}
+
+#define POLY 0xedb88320
+
+/* really slow 32 bit crc for ethers */
+ulong
+ethercrc(uchar *p, int len)
+{
+ int i, j;
+ ulong crc, b;
+
+ crc = 0xffffffff;
+ for(i = 0; i < len; i++){
+ b = *p++;
+ for(j = 0; j < 8; j++){
+ crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
+ b >>= 1;
+ }
+ }
+ return crc;
+}
+
+Dev etherdevtab = {
+ 'l',
+ "ether",
+
+ etherreset,
+ devinit,
+ devshutdown,
+ etherattach,
+ etherwalk,
+ etherstat,
+ etheropen,
+ ethercreate,
+ etherclose,
+ etherread,
+ etherbread,
+ etherwrite,
+ etherbwrite,
+ devremove,
+ etherwstat,
+ etherpower,
+ etherconfig,
+};
diff --git a/sys/src/9/bitsy/devflash.c b/sys/src/9/bitsy/devflash.c
new file mode 100755
index 000000000..34c49c1df
--- /dev/null
+++ b/sys/src/9/bitsy/devflash.c
@@ -0,0 +1,876 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+/*
+ * on the bitsy, all 32 bit accesses to flash are mapped to two 16 bit
+ * accesses, one to the low half of the chip and the other to the high
+ * half. Therefore for all command accesses, ushort indices in the
+ * manuals turn into ulong indices in our code. Also, by copying all
+ * 16 bit commands to both halves of a 32 bit command, we erase 2
+ * sectors for each request erase request.
+ */
+
+#define mirror(x) (((x)<<16)|(x))
+
+/* this defines a contiguous set of erase blocks of one size */
+typedef struct FlashRegion FlashRegion;
+struct FlashRegion
+{
+ ulong addr; /* start of region */
+ ulong end; /* end of region + 1 */
+ ulong n; /* number of blocks */
+ ulong size; /* size of each block */
+};
+
+/* this defines a particular access algorithm */
+typedef struct FlashAlg FlashAlg;
+struct FlashAlg
+{
+ int id;
+ char *name;
+ void (*identify)(void); /* identify device */
+ void (*erase)(ulong); /* erase a region */
+ void (*write)(void*, long, ulong); /* write a region */
+};
+
+static void ise_id(void);
+static void ise_erase(ulong);
+static void ise_write(void*, long, ulong);
+
+static void afs_id(void);
+static void afs_erase(ulong);
+static void afs_write(void*, long, ulong);
+
+static ulong blockstart(ulong);
+static ulong blockend(ulong);
+
+FlashAlg falg[] =
+{
+ { 1, "Intel/Sharp Extended", ise_id, ise_erase, ise_write },
+ { 2, "AMD/Fujitsu Standard", afs_id, afs_erase, afs_write },
+};
+
+struct
+{
+ RWlock;
+ ulong *p;
+ ushort algid; /* access algorithm */
+ FlashAlg *alg;
+ ushort manid; /* manufacturer id */
+ ushort devid; /* device id */
+ ulong size; /* size in bytes */
+ int wbsize; /* size of write buffer */
+ ulong nr; /* number of regions */
+ uchar bootprotect;
+ FlashRegion r[32];
+} flash;
+
+enum
+{
+ Maxwchunk= 1024, /* maximum chunk written by one call to falg->write */
+};
+
+/*
+ * common flash interface
+ */
+static uchar
+cfigetc(int off)
+{
+ uchar rv;
+
+ flash.p[0x55] = mirror(0x98);
+ rv = flash.p[off];
+ flash.p[0x55] = mirror(0xFF);
+ return rv;
+}
+
+static ushort
+cfigets(int off)
+{
+ return (cfigetc(off+1)<<8)|cfigetc(off);
+}
+
+static ulong
+cfigetl(int off)
+{
+ return (cfigetc(off+3)<<24)|(cfigetc(off+2)<<16)|
+ (cfigetc(off+1)<<8)|cfigetc(off);
+}
+
+static void
+cfiquery(void)
+{
+ uchar q, r, y;
+ ulong x, addr;
+
+ q = cfigetc(0x10);
+ r = cfigetc(0x11);
+ y = cfigetc(0x12);
+ if(q != 'Q' || r != 'R' || y != 'Y'){
+ print("cfi query failed: %ux %ux %ux\n", q, r, y);
+ return;
+ }
+ flash.algid = cfigetc(0x13);
+ flash.size = 1<<(cfigetc(0x27)+1);
+ flash.wbsize = 1<<(cfigetc(0x2a)+1);
+ flash.nr = cfigetc(0x2c);
+ if(flash.nr > nelem(flash.r)){
+ print("cfi reports > %d regions\n", nelem(flash.r));
+ flash.nr = nelem(flash.r);
+ }
+ addr = 0;
+ for(q = 0; q < flash.nr; q++){
+ x = cfigetl(q+0x2d);
+ flash.r[q].size = 2*256*(x>>16);
+ flash.r[q].n = (x&0xffff)+1;
+ flash.r[q].addr = addr;
+ addr += flash.r[q].size*flash.r[q].n;
+ flash.r[q].end = addr;
+ }
+}
+
+/*
+ * flash device interface
+ */
+
+enum
+{
+ Qtopdir,
+ Q2nddir,
+ Qfctl,
+ Qfdata,
+
+ Maxpart= 8,
+};
+
+
+typedef struct FPart FPart;
+struct FPart
+{
+ char *name;
+ char *ctlname;
+ ulong start;
+ ulong end;
+};
+static FPart part[Maxpart];
+
+#define FQID(p,q) ((p)<<8|(q))
+#define FTYPE(q) ((q) & 0xff)
+#define FPART(q) (&part[(q) >>8])
+
+static int
+gen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
+{
+ Qid q;
+ FPart *fp;
+
+ q.vers = 0;
+
+ /* top level directory contains the name of the network */
+ if(c->qid.path == Qtopdir){
+ switch(i){
+ case DEVDOTDOT:
+ q.path = Qtopdir;
+ q.type = QTDIR;
+ devdir(c, q, "#F", 0, eve, DMDIR|0555, dp);
+ break;
+ case 0:
+ q.path = Q2nddir;
+ q.type = QTDIR;
+ devdir(c, q, "flash", 0, eve, DMDIR|0555, dp);
+ break;
+ default:
+ return -1;
+ }
+ return 1;
+ }
+
+ /* second level contains all partitions and their control files */
+ switch(i) {
+ case DEVDOTDOT:
+ q.path = Qtopdir;
+ q.type = QTDIR;
+ devdir(c, q, "#F", 0, eve, DMDIR|0555, dp);
+ break;
+ default:
+ if(i >= 2*Maxpart)
+ return -1;
+ fp = &part[i>>1];
+ if(fp->name == nil)
+ return 0;
+ if(i & 1){
+ q.path = FQID(i>>1, Qfdata);
+ q.type = QTFILE;
+ devdir(c, q, fp->name, fp->end-fp->start, eve, 0660, dp);
+ } else {
+ q.path = FQID(i>>1, Qfctl);
+ q.type = QTFILE;
+ devdir(c, q, fp->ctlname, 0, eve, 0660, dp);
+ }
+ break;
+ }
+ return 1;
+}
+
+static FPart*
+findpart(char *name)
+{
+ int i;
+
+ for(i = 0; i < Maxpart; i++)
+ if(part[i].name != nil && strcmp(name, part[i].name) == 0)
+ break;
+ if(i >= Maxpart)
+ return nil;
+ return &part[i];
+}
+
+static void
+addpart(FPart *fp, char *name, ulong start, ulong end)
+{
+ int i;
+ char ctlname[64];
+
+ if(fp == nil){
+ if(start >= flash.size || end > flash.size)
+ error(Ebadarg);
+ } else {
+ start += fp->start;
+ end += fp->start;
+ if(start >= fp->end || end > fp->end)
+ error(Ebadarg);
+ }
+ if(blockstart(start) != start)
+ error("must start on erase boundary");
+ if(blockstart(end) != end && end != flash.size)
+ error("must end on erase boundary");
+
+ fp = findpart(name);
+ if(fp != nil)
+ error(Eexist);
+ for(i = 0; i < Maxpart; i++)
+ if(part[i].name == nil)
+ break;
+ if(i == Maxpart)
+ error("no more partitions");
+ fp = &part[i];
+ kstrdup(&fp->name, name);
+ snprint(ctlname, sizeof ctlname, "%sctl", name);
+ kstrdup(&fp->ctlname, ctlname);
+ fp->start = start;
+ fp->end = end;
+}
+
+static void
+rempart(FPart *fp)
+{
+ char *p, *cp;
+
+ p = fp->name;
+ fp->name = nil;
+ cp = fp->ctlname;
+ fp->ctlname = nil;
+ free(p);
+ free(cp);
+}
+
+void
+flashinit(void)
+{
+ int i;
+
+ flash.p = (ulong*)FLASHZERO;
+ cfiquery();
+ for(i = 0; i < nelem(falg); i++)
+ if(flash.algid == falg[i].id){
+ flash.alg = &falg[i];
+ (*flash.alg->identify)();
+ break;
+ }
+ flash.bootprotect = 1;
+
+ addpart(nil, "flash", 0, flash.size);
+}
+
+static Chan*
+flashattach(char* spec)
+{
+ return devattach('F', spec);
+}
+
+static Walkqid*
+flashwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, nil, 0, gen);
+}
+
+static int
+flashstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, nil, 0, gen);
+}
+
+static Chan*
+flashopen(Chan* c, int omode)
+{
+ omode = openmode(omode);
+ if(strcmp(up->user, eve)!=0)
+ error(Eperm);
+ return devopen(c, omode, nil, 0, gen);
+}
+
+static void
+flashclose(Chan*)
+{
+}
+
+static long
+flashctlread(FPart *fp, void* a, long n, vlong off)
+{
+ char *buf, *p, *e;
+ int i;
+ ulong addr, end;
+
+ buf = smalloc(1024);
+ e = buf + 1024;
+ p = seprint(buf, e, "0x%-9lux 0x%-9x 0x%-9ux 0x%-9ux\n", fp->end-fp->start,
+ flash.wbsize, flash.manid, flash.devid);
+ addr = fp->start;
+ for(i = 0; i < flash.nr && addr < fp->end; i++)
+ if(flash.r[i].addr <= addr && flash.r[i].end > addr){
+ if(fp->end <= flash.r[i].end)
+ end = fp->end;
+ else
+ end = flash.r[i].end;
+ p = seprint(p, e, "0x%-9lux 0x%-9lux 0x%-9lux\n", addr,
+ (end-addr)/flash.r[i].size, flash.r[i].size);
+ addr = end;
+ }
+ n = readstr(off, a, n, buf);
+ free(buf);
+ return n;
+}
+
+static long
+flashdataread(FPart *fp, void* a, long n, vlong off)
+{
+ rlock(&flash);
+ if(waserror()){
+ runlock(&flash);
+ nexterror();
+ }
+ if(fp->name == nil)
+ error("partition vanished");
+ if(!iseve())
+ error(Eperm);
+ off += fp->start;
+ if(off >= fp->end)
+ n = 0;
+ if(off+n >= fp->end)
+ n = fp->end - off;
+ if(n > 0)
+ memmove(a, ((uchar*)FLASHZERO)+off, n);
+ runlock(&flash);
+ poperror();
+
+ return n;
+}
+
+static long
+flashread(Chan* c, void* a, long n, vlong off)
+{
+ int t;
+
+ if(c->qid.type == QTDIR)
+ return devdirread(c, a, n, nil, 0, gen);
+ t = FTYPE(c->qid.path);
+ switch(t){
+ default:
+ error(Eperm);
+ case Qfctl:
+ n = flashctlread(FPART(c->qid.path), a, n, off);
+ break;
+ case Qfdata:
+ n = flashdataread(FPART(c->qid.path), a, n, off);
+ break;
+ }
+ return n;
+}
+
+static void
+bootprotect(ulong addr)
+{
+ FlashRegion *r;
+
+ if(flash.bootprotect == 0)
+ return;
+ if(flash.nr == 0)
+ error("writing over boot loader disallowed");
+ r = flash.r;
+ if(addr >= r->addr && addr < r->addr + r->size)
+ error("writing over boot loader disallowed");
+}
+
+static ulong
+blockstart(ulong addr)
+{
+ FlashRegion *r, *e;
+ ulong x;
+
+ r = flash.r;
+ for(e = &flash.r[flash.nr]; r < e; r++)
+ if(addr >= r->addr && addr < r->end){
+ x = addr - r->addr;
+ x /= r->size;
+ return r->addr + x*r->size;
+ }
+
+ return (ulong)-1;
+}
+
+static ulong
+blockend(ulong addr)
+{
+ FlashRegion *r, *e;
+ ulong x;
+
+ r = flash.r;
+ for(e = &flash.r[flash.nr]; r < e; r++)
+ if(addr >= r->addr && addr < r->end){
+ x = addr - r->addr;
+ x /= r->size;
+ return r->addr + (x+1)*r->size;
+ }
+
+ return (ulong)-1;
+}
+
+static long
+flashctlwrite(FPart *fp, char *p, long n)
+{
+ Cmdbuf *cmd;
+ ulong off;
+
+ if(fp == nil)
+ panic("flashctlwrite");
+
+ cmd = parsecmd(p, n);
+ wlock(&flash);
+ if(waserror()){
+ wunlock(&flash);
+ nexterror();
+ }
+ if(strcmp(cmd->f[0], "erase") == 0){
+ switch(cmd->nf){
+ case 2:
+ /* erase a single block in the partition */
+ off = atoi(cmd->f[1]);
+ off += fp->start;
+ if(off >= fp->end)
+ error("region not in partition");
+ if(off != blockstart(off))
+ error("erase must be a block boundary");
+ bootprotect(off);
+ (*flash.alg->erase)(off);
+ break;
+ case 1:
+ /* erase the whole partition */
+ bootprotect(fp->start);
+ for(off = fp->start; off < fp->end; off = blockend(off))
+ (*flash.alg->erase)(off);
+ break;
+ default:
+ error(Ebadarg);
+ }
+ } else if(strcmp(cmd->f[0], "add") == 0){
+ if(cmd->nf != 4)
+ error(Ebadarg);
+ addpart(fp, cmd->f[1], strtoul(cmd->f[2], nil, 0), strtoul(cmd->f[3], nil, 0));
+ } else if(strcmp(cmd->f[0], "remove") == 0){
+ rempart(fp);
+ } else if(strcmp(cmd->f[0], "protectboot") == 0){
+ if(cmd->nf == 0 || strcmp(cmd->f[1], "off") != 0)
+ flash.bootprotect = 1;
+ else
+ flash.bootprotect = 0;
+ } else
+ error(Ebadarg);
+ poperror();
+ wunlock(&flash);
+ free(cmd);
+
+ return n;
+}
+
+static long
+flashdatawrite(FPart *fp, uchar *p, long n, long off)
+{
+ uchar *end;
+ int m;
+ int on;
+ long ooff;
+ uchar *buf;
+
+ if(fp == nil)
+ panic("flashctlwrite");
+
+ buf = nil;
+ wlock(&flash);
+ if(waserror()){
+ wunlock(&flash);
+ if(buf != nil)
+ free(buf);
+ nexterror();
+ }
+
+ if(fp->name == nil)
+ error("partition vanished");
+ if(!iseve())
+ error(Eperm);
+
+ /* can't cross partition boundaries */
+ off += fp->start;
+ if(off >= fp->end || off+n > fp->end || n <= 0)
+ error(Ebadarg);
+
+ /* make sure we're not writing the boot sector */
+ bootprotect(off);
+
+ on = n;
+
+ /*
+ * get the data into kernel memory to avoid faults during writing.
+ * if write is not on a quad boundary or not a multiple of 4 bytes,
+ * extend with data already in flash.
+ */
+ buf = smalloc(n+8);
+ m = off & 3;
+ if(m){
+ *(ulong*)buf = flash.p[(off)>>2];
+ n += m;
+ off -= m;
+ }
+ if(n & 3){
+ n -= n & 3;
+ *(ulong*)(&buf[n]) = flash.p[(off+n)>>2];
+ n += 4;
+ }
+ memmove(&buf[m], p, on);
+
+ /* (*flash.alg->write) can't cross blocks */
+ ooff = off;
+ p = buf;
+ for(end = p + n; p < end; p += m){
+ m = blockend(off) - off;
+ if(m > end - p)
+ m = end - p;
+ if(m > Maxwchunk)
+ m = Maxwchunk;
+ (*flash.alg->write)(p, m, off);
+ off += m;
+ }
+
+ /* make sure write succeeded */
+ if(memcmp(buf, &flash.p[ooff>>2], n) != 0)
+ error("written bytes don't match");
+
+ wunlock(&flash);
+ free(buf);
+ poperror();
+
+ return on;
+}
+
+static long
+flashwrite(Chan* c, void* a, long n, vlong off)
+{
+ int t;
+
+ if(c->qid.type == QTDIR)
+ error(Eperm);
+
+ if(!iseve())
+ error(Eperm);
+
+ t = FTYPE(c->qid.path);
+ switch(t){
+ default:
+ panic("flashwrite");
+ case Qfctl:
+ n = flashctlwrite(FPART(c->qid.path), a, n);
+ break;
+ case Qfdata:
+ n = flashdatawrite(FPART(c->qid.path), a, n, off);
+ break;
+ }
+ return n;
+}
+
+Dev flashdevtab = {
+ 'F',
+ "flash",
+
+ devreset,
+ flashinit,
+ devshutdown,
+ flashattach,
+ flashwalk,
+ flashstat,
+ flashopen,
+ devcreate,
+ flashclose,
+ flashread,
+ devbread,
+ flashwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+enum
+{
+ /* status register */
+ ISEs_lockerr= 1<<1,
+ ISEs_powererr= 1<<3,
+ ISEs_progerr= 1<<4,
+ ISEs_eraseerr= 1<<5,
+ ISEs_ready= 1<<7,
+ ISEs_err= (ISEs_lockerr|ISEs_powererr|ISEs_progerr|ISEs_eraseerr),
+
+ /* extended status register */
+ ISExs_bufavail= 1<<7,
+};
+
+
+
+/* intel/sharp extended command set */
+static void
+ise_reset(void)
+{
+ flash.p[0x55] = mirror(0xff); /* reset */
+}
+static void
+ise_id(void)
+{
+ ise_reset();
+ flash.p[0x555] = mirror(0x90); /* uncover vendor info */
+ flash.manid = flash.p[00];
+ flash.devid = flash.p[01];
+ ise_reset();
+}
+static void
+ise_clearerror(void)
+{
+ flash.p[0x100] = mirror(0x50);
+
+}
+static void
+ise_error(int bank, ulong status)
+{
+ char err[64];
+
+ if(status & (ISEs_lockerr)){
+ sprint(err, "flash%d: block locked %lux", bank, status);
+ error(err);
+ }
+ if(status & (ISEs_powererr)){
+ sprint(err, "flash%d: low prog voltage %lux", bank, status);
+ error(err);
+ }
+ if(status & (ISEs_progerr|ISEs_eraseerr)){
+ sprint(err, "flash%d: i/o error %lux", bank, status);
+ error(err);
+ }
+}
+static void
+ise_erase(ulong addr)
+{
+ ulong start;
+ ulong x;
+
+ addr >>= 2; /* convert to ulong offset */
+
+ flashprogpower(1);
+ flash.p[addr] = mirror(0x20);
+ flash.p[addr] = mirror(0xd0);
+ start = m->ticks;
+ do {
+ x = flash.p[addr];
+ if((x & mirror(ISEs_ready)) == mirror(ISEs_ready))
+ break;
+ } while(TK2MS(m->ticks-start) < 1500);
+ flashprogpower(0);
+
+ ise_clearerror();
+ ise_error(0, x);
+ ise_error(1, x>>16);
+
+ ise_reset();
+}
+/*
+ * the flash spec claimes writing goes faster if we use
+ * the write buffer. We fill the write buffer and then
+ * issue the write request. After the write request,
+ * subsequent reads will yield the status register.
+ *
+ * returns the status, even on timeouts.
+ *
+ * NOTE: I tried starting back to back buffered writes
+ * without reading the status in between, as the
+ * flowchart in the intel data sheet suggests.
+ * However, it always responded with an illegal
+ * command sequence, so I must be missing something.
+ * If someone learns better, please email me, though
+ * I doubt it will be much faster. - presotto@bell-labs.com
+ */
+static int
+ise_wbwrite(ulong *p, int n, ulong off, ulong baddr, ulong *status)
+{
+ ulong x, start;
+ int i;
+ int s;
+
+ /* put flash into write buffer mode */
+ start = m->ticks;
+ for(;;) {
+ s = splhi();
+ /* request write buffer mode */
+ flash.p[baddr] = mirror(0xe8);
+
+ /* look at extended status reg for status */
+ if((flash.p[baddr] & mirror(1<<7)) == mirror(1<<7))
+ break;
+ splx(s);
+
+ /* didn't work, keep trying for 2 secs */
+ if(TK2MS(m->ticks-start) > 2000){
+ /* set up to read status */
+ flash.p[baddr] = mirror(0x70);
+ *status = flash.p[baddr];
+ pprint("write buffered cmd timed out\n");
+ return -1;
+ }
+ }
+
+ /* fill write buffer */
+ flash.p[baddr] = mirror(n-1);
+ for(i = 0; i < n; i++)
+ flash.p[off+i] = *p++;
+
+ /* program from buffer */
+ flash.p[baddr] = mirror(0xd0);
+ splx(s);
+
+ /* wait till the programming is done */
+ start = m->ticks;
+ for(;;) {
+ x = *status = flash.p[baddr]; /* read status register */
+ if((x & mirror(ISEs_ready)) == mirror(ISEs_ready))
+ break;
+ if(TK2MS(m->ticks-start) > 2000){
+ pprint("read status timed out\n");
+ return -1;
+ }
+ }
+ if(x & mirror(ISEs_err))
+ return -1;
+
+ return n;
+}
+static void
+ise_write(void *a, long n, ulong off)
+{
+ ulong *p, *end;
+ int i, wbsize;
+ ulong x, baddr;
+
+ /* everything in terms of ulongs */
+ wbsize = flash.wbsize>>2;
+ baddr = blockstart(off);
+ off >>= 2;
+ n >>= 2;
+ p = a;
+ baddr >>= 2;
+
+ /* first see if write will succeed */
+ for(i = 0; i < n; i++)
+ if((p[i] & flash.p[off+i]) != p[i])
+ error("flash needs erase");
+
+ if(waserror()){
+ ise_reset();
+ flashprogpower(0);
+ nexterror();
+ }
+ flashprogpower(1);
+
+ /*
+ * use the first write to reach
+ * a write buffer boundary. the intel maunal
+ * says writes startng at wb boundaries
+ * maximize speed.
+ */
+ i = wbsize - (off & (wbsize-1));
+ for(end = p + n; p < end;){
+ if(i > end - p)
+ i = end - p;
+
+ if(ise_wbwrite(p, i, off, baddr, &x) < 0)
+ break;
+
+ off += i;
+ p += i;
+ i = wbsize;
+ }
+
+ ise_clearerror();
+ ise_error(0, x);
+ ise_error(1, x>>16);
+
+ ise_reset();
+ flashprogpower(0);
+ poperror();
+}
+
+/* amd/fujitsu standard command set
+ * I don't have an amd chipset to work with
+ * so I'm loathe to write this yet. If someone
+ * else does, please send it to me and I'll
+ * incorporate it -- presotto@bell-labs.com
+ */
+static void
+afs_reset(void)
+{
+ flash.p[0x55] = mirror(0xf0); /* reset */
+}
+static void
+afs_id(void)
+{
+ afs_reset();
+ flash.p[0x55] = mirror(0xf0); /* reset */
+ flash.p[0x555] = mirror(0xaa); /* query vendor block */
+ flash.p[0x2aa] = mirror(0x55);
+ flash.p[0x555] = mirror(0x90);
+ flash.manid = flash.p[00];
+ afs_reset();
+ flash.p[0x555] = mirror(0xaa); /* query vendor block */
+ flash.p[0x2aa] = mirror(0x55);
+ flash.p[0x555] = mirror(0x90);
+ flash.devid = flash.p[01];
+ afs_reset();
+}
+static void
+afs_erase(ulong)
+{
+ error("amd/fujistsu erase not implemented");
+}
+static void
+afs_write(void*, long, ulong)
+{
+ error("amd/fujistsu write not implemented");
+}
diff --git a/sys/src/9/bitsy/devpcmcia.c b/sys/src/9/bitsy/devpcmcia.c
new file mode 100755
index 000000000..c6a0e29c5
--- /dev/null
+++ b/sys/src/9/bitsy/devpcmcia.c
@@ -0,0 +1,713 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+/*
+ * BUG: insertion events are detected by polling.
+ * Should look into the compaq docs to see if
+ * there's an interrupt for card insertion
+ * there's probably one.
+ */
+
+static PCMslot slot[2];
+int nslot = 2;
+
+struct {
+ Ref;
+ Rendez event; // where to wait for card events
+ int evreader; // there's a reader for events
+} pcmcia;
+
+enum
+{
+ Qdir,
+ Qmem,
+ Qattr,
+ Qctl,
+ Qevs,
+
+ Nents = 3,
+};
+
+enum
+{
+ /*
+ * configuration registers - they start at an offset in attribute
+ * memory found in the CIS.
+ */
+ Rconfig= 0,
+ Creset= (1<<7), /* reset device */
+ Clevel= (1<<6), /* level sensitive interrupt line */
+};
+
+static void increfp(PCMslot*);
+static void decrefp(PCMslot*);
+static void slotmap(int, ulong, ulong, ulong);
+static void slottiming(int, int, int, int, int);
+static void slotinfo(Ureg*, void*);
+
+#define TYPE(c) (((ulong)c->qid.path)&0xff)
+#define PATH(s,t) (((s)<<8)|(t))
+
+static PCMslot*
+slotof(Chan *c)
+{
+ ulong x;
+
+ x = c->qid.path;
+ return slot + ((x>>8)&0xff);
+}
+
+static int
+pcmgen(Chan *c, char *, Dirtab * , int, int i, Dir *dp)
+{
+ int slotno;
+ Qid qid;
+ long len;
+ PCMslot *sp;
+
+ if(i == DEVDOTDOT){
+ mkqid(&qid, Qdir, 0, QTDIR);
+ devdir(c, qid, "#y", 0, eve, 0555, dp);
+ return 1;
+ }
+
+ if(i >= Nents*nslot + 1)
+ return -1;
+ if(i == Nents*nslot){
+ len = 0;
+ qid.path = PATH(0, Qevs);
+ snprint(up->genbuf, sizeof up->genbuf, "pcmevs");
+ goto found;
+ }
+
+ slotno = i/Nents;
+ sp = slot + slotno;
+ len = 0;
+ switch(i%Nents){
+ case 0:
+ qid.path = PATH(slotno, Qmem);
+ snprint(up->genbuf, sizeof up->genbuf, "pcm%dmem", slotno);
+ len = sp->memlen;
+ break;
+ case 1:
+ qid.path = PATH(slotno, Qattr);
+ snprint(up->genbuf, sizeof up->genbuf, "pcm%dattr", slotno);
+ len = sp->memlen;
+ break;
+ case 2:
+ qid.path = PATH(slotno, Qctl);
+ snprint(up->genbuf, sizeof up->genbuf, "pcm%dctl", slotno);
+ break;
+ }
+found:
+ qid.vers = 0;
+ qid.type = QTFILE;
+ devdir(c, qid, up->genbuf, len, eve, 0660, dp);
+ return 1;
+}
+
+static int
+bitno(ulong x)
+{
+ int i;
+
+ for(i = 0; i < 8*sizeof(x); i++)
+ if((1<<i) & x)
+ break;
+ return i;
+}
+
+/*
+ * set up the cards, default timing is 300 ns
+ */
+static void
+pcmciareset(void)
+{
+ /* staticly map the whole area */
+ slotmap(0, PHYSPCM0REGS, PYHSPCM0ATTR, PYHSPCM0MEM);
+ slotmap(1, PHYSPCM1REGS, PYHSPCM1ATTR, PYHSPCM1MEM);
+
+ /* set timing to the default, 300 */
+ slottiming(0, 300, 300, 300, 0);
+ slottiming(1, 300, 300, 300, 0);
+
+ /* if there's no pcmcia sleave, no interrupts */
+ if(gpioregs->level & GPIO_OPT_IND_i)
+ return;
+
+ /* sleave there, interrupt on card removal */
+ intrenable(GPIOrising, bitno(GPIO_CARD_IND1_i), slotinfo, nil, "pcmcia slot1 status");
+ intrenable(GPIOrising, bitno(GPIO_CARD_IND0_i), slotinfo, nil, "pcmcia slot0 status");
+}
+
+static Chan*
+pcmciaattach(char *spec)
+{
+ return devattach('y', spec);
+}
+
+static Walkqid*
+pcmciawalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, 0, 0, pcmgen);
+}
+
+static int
+pcmciastat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, 0, 0, pcmgen);
+}
+
+static Chan*
+pcmciaopen(Chan *c, int omode)
+{
+ PCMslot *slotp;
+
+ if(c->qid.type & QTDIR){
+ if(omode != OREAD)
+ error(Eperm);
+ } else {
+ slotp = slotof(c);
+ increfp(slotp);
+ }
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+static void
+pcmciaclose(Chan *c)
+{
+ if(c->flag & COPEN)
+ if((c->qid.type & QTDIR) == 0)
+ decrefp(slotof(c));
+}
+
+/* a memmove using only bytes */
+static void
+memmoveb(uchar *to, uchar *from, int n)
+{
+ while(n-- > 0)
+ *to++ = *from++;
+}
+
+/* a memmove using only shorts & bytes */
+static void
+memmoves(uchar *to, uchar *from, int n)
+{
+ ushort *t, *f;
+
+ if((((ulong)to) & 1) || (((ulong)from) & 1) || (n & 1)){
+ while(n-- > 0)
+ *to++ = *from++;
+ } else {
+ n = n/2;
+ t = (ushort*)to;
+ f = (ushort*)from;
+ while(n-- > 0)
+ *t++ = *f++;
+ }
+}
+
+static long
+pcmread(void *a, long n, ulong off, PCMslot *sp, uchar *start, ulong len)
+{
+ rlock(sp);
+ if(waserror()){
+ runlock(sp);
+ nexterror();
+ }
+ if(off > len)
+ return 0;
+ if(off + n > len)
+ n = len - off;
+ memmoveb(a, start+off, n);
+ runlock(sp);
+ poperror();
+ return n;
+}
+
+static long
+pcmctlread(void *a, long n, ulong off, PCMslot *sp)
+{
+ char *p, *buf, *e;
+
+ buf = p = malloc(READSTR);
+ if(waserror()){
+ free(buf);
+ nexterror();
+ }
+ e = p + READSTR;
+
+ buf[0] = 0;
+ if(sp->occupied){
+ p = seprint(p, e, "occupied\n");
+ if(sp->verstr[0])
+ p = seprint(p, e, "version %s\n", sp->verstr);
+ }
+ USED(p);
+
+ n = readstr(off, a, n, buf);
+ free(buf);
+ poperror();
+ return n;
+}
+
+static int
+inserted(void *)
+{
+ if (slot[0].inserted)
+ return 1;
+ if (slot[1].inserted)
+ return 2;
+ return 0;
+}
+
+static long
+pcmevsread(void *a, long n, ulong off)
+{
+ int i;
+ char *buf = nil;
+ char *e;
+
+ if (pcmcia.evreader)
+ error("At most one reader");
+ off = 0;
+ pcmcia.evreader++;
+ if (waserror()){
+ free(buf);
+ pcmcia.evreader--;
+ nexterror();
+ }
+ while((i = inserted(nil)) == 0){
+ slotinfo(nil, nil);
+ tsleep(&pcmcia.event, inserted, nil, 500);
+ }
+ pcmcia.evreader--;
+ slot[i-1].inserted = 0;
+ buf = malloc(READSTR);
+ e = buf + READSTR;
+ buf[0] = 0;
+ seprint(buf, e, "#y/pcm%dctl\n", i-1);
+ n = readstr(off, a, n, buf);
+ free(buf);
+ poperror();
+ return n;
+}
+
+static long
+pcmciaread(Chan *c, void *a, long n, vlong off)
+{
+ PCMslot *sp;
+ ulong offset = off;
+
+ sp = slotof(c);
+
+ switch(TYPE(c)){
+ case Qdir:
+ return devdirread(c, a, n, 0, 0, pcmgen);
+ case Qmem:
+ if(!sp->occupied)
+ error(Eio);
+ return pcmread(a, n, offset, sp, sp->mem, 64*OneMeg);
+ case Qattr:
+ if(!sp->occupied)
+ error(Eio);
+ return pcmread(a, n, offset, sp, sp->attr, OneMeg);
+ case Qevs:
+ return pcmevsread(a, n, offset);
+ case Qctl:
+ return pcmctlread(a, n, offset, sp);
+ }
+ error(Ebadarg);
+ return -1; /* not reached */
+}
+
+static long
+pcmwrite(void *a, long n, ulong off, PCMslot *sp, uchar *start, ulong len)
+{
+ rlock(sp);
+ if(waserror()){
+ runlock(sp);
+ nexterror();
+ }
+ if(off > len)
+ error(Eio);
+ if(off + n > len)
+ error(Eio);
+ memmoveb(start+off, a, n);
+ poperror();
+ runlock(sp);
+ return n;
+}
+
+static long
+pcmctlwrite(char *p, long n, ulong, PCMslot *sp)
+{
+ Cmdbuf *cmd;
+ uchar *cp;
+ int index, i, dtx;
+ Rune r;
+ DevConf cf;
+ Devport port;
+
+ cmd = parsecmd(p, n);
+ if(strcmp(cmd->f[0], "configure") == 0){
+ wlock(sp);
+ if(waserror()){
+ wunlock(sp);
+ nexterror();
+ }
+
+ /* see if driver exists and is configurable */
+ if(cmd->nf < 3)
+ error(Ebadarg);
+ p = cmd->f[1];
+ if(*p++ != '#')
+ error(Ebadarg);
+ p += chartorune(&r, p);
+ dtx = devno(r, 1);
+ if(dtx < 0)
+ error("no such device type");
+ if(devtab[dtx]->config == nil)
+ error("not a dynamicly configurable device");
+
+ /* set pcmcia card configuration */
+ index = 0;
+ if(sp->def != nil)
+ index = sp->def->index;
+ if(cmd->nf > 3){
+ i = atoi(cmd->f[3]);
+ if(i < 0 || i >= sp->nctab)
+ error("bad configuration index");
+ index = i;
+ }
+ if(sp->cfg[0].cpresent & (1<<Rconfig)){
+ cp = sp->attr;
+ cp += sp->cfg[0].caddr + Rconfig;
+ *cp = index;
+ }
+
+ /* configure device */
+ memset(&cf, 0, sizeof cf);
+ kstrdup(&cf.type, cmd->f[2]);
+ cf.mem = (ulong)sp->mem;
+ cf.ports = &port;
+ cf.ports[0].port = (ulong)sp->regs;
+ cf.ports[0].size = 0;
+ cf.nports = 1;
+ cf.itype = GPIOfalling;
+ cf.intnum = bitno(sp == slot ? GPIO_CARD_IRQ0_i : GPIO_CARD_IRQ1_i);
+ if(devtab[dtx]->config(1, p, &cf) < 0)
+ error("couldn't configure device");
+ sp->dev = devtab[dtx];
+ free(cf.type);
+ wunlock(sp);
+ poperror();
+
+ /* don't let the power turn off */
+ increfp(sp);
+ }else if(strcmp(cmd->f[0], "remove") == 0){
+ /* see if driver exists and is configurable */
+ if(cmd->nf != 2)
+ error(Ebadarg);
+ p = cmd->f[1];
+ if(*p++ != '#')
+ error(Ebadarg);
+ p += chartorune(&r, p);
+ dtx = devno(r, 1);
+ if(dtx < 0)
+ error("no such device type");
+ if(devtab[dtx]->config == nil)
+ error("not a dynamicly configurable device");
+ if(devtab[dtx]->config(0, p, nil) < 0)
+ error("couldn't unconfigure device");
+
+ /* let the power turn off */
+ decrefp(sp);
+ }
+ free(cmd);
+
+ return 0;
+}
+
+static long
+pcmciawrite(Chan *c, void *a, long n, vlong off)
+{
+ PCMslot *sp;
+ ulong offset = off;
+
+ sp = slotof(c);
+
+ switch(TYPE(c)){
+ case Qmem:
+ if(!sp->occupied)
+ error(Eio);
+ return pcmwrite(a, n, offset, sp, sp->mem, 64*OneMeg);
+ case Qattr:
+ if(!sp->occupied)
+ error(Eio);
+ return pcmwrite(a, n, offset, sp, sp->attr, OneMeg);
+ case Qevs:
+ break;
+ case Qctl:
+ if(!sp->occupied)
+ error(Eio);
+ return pcmctlwrite(a, n, offset, sp);
+ }
+ error(Ebadarg);
+ return -1; /* not reached */
+}
+
+/*
+ * power up/down pcmcia
+ */
+void
+pcmciapower(int on)
+{
+ PCMslot *sp;
+
+ /* if there's no pcmcia sleave, no interrupts */
+iprint("pcmciapower %d\n", on);
+
+ if (on){
+ /* set timing to the default, 300 */
+ slottiming(0, 300, 300, 300, 0);
+ slottiming(1, 300, 300, 300, 0);
+
+ /* if there's no pcmcia sleave, no interrupts */
+ if(gpioregs->level & GPIO_OPT_IND_i){
+ iprint("pcmciapower: no sleeve\n");
+ return;
+ }
+
+ for (sp = slot; sp < slot + nslot; sp++){
+ if (sp->dev){
+ increfp(sp);
+ iprint("pcmciapower: %s\n", sp->verstr);
+ delay(10000);
+ if (sp->dev->power)
+ sp->dev->power(on);
+ }
+ }
+ }else{
+ if(gpioregs->level & GPIO_OPT_IND_i){
+ iprint("pcmciapower: no sleeve\n");
+ return;
+ }
+
+ for (sp = slot; sp < slot + nslot; sp++){
+ if (sp->dev){
+ if (sp->dev->power)
+ sp->dev->power(on);
+ decrefp(sp);
+ }
+ sp->occupied = 0;
+ sp->cisread = 0;
+ }
+ egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 0);
+ }
+}
+
+Dev pcmciadevtab = {
+ 'y',
+ "pcmcia",
+
+ pcmciareset,
+ devinit,
+ devshutdown,
+ pcmciaattach,
+ pcmciawalk,
+ pcmciastat,
+ pcmciaopen,
+ devcreate,
+ pcmciaclose,
+ pcmciaread,
+ devbread,
+ pcmciawrite,
+ devbwrite,
+ devremove,
+ devwstat,
+ pcmciapower,
+};
+
+/* see what's there */
+static void
+slotinfo(Ureg*, void*)
+{
+ ulong x = gpioregs->level;
+
+ if(x & GPIO_OPT_IND_i){
+ /* no expansion pack */
+ slot[0].occupied = slot[0].inserted = 0;
+ slot[1].occupied = slot[1].inserted = 0;
+ } else {
+ if(x & GPIO_CARD_IND0_i){
+ slot[0].occupied = slot[0].inserted = 0;
+ slot[0].cisread = 0;
+ } else {
+ if(slot[0].occupied == 0){
+ slot[0].inserted = 1;
+ slot[0].cisread = 0;
+ }
+ slot[0].occupied = 1;
+ }
+ if(x & GPIO_CARD_IND1_i){
+ slot[1].occupied = slot[1].inserted = 0;
+ slot[1].cisread = 0;
+ } else {
+ if(slot[1].occupied == 0){
+ slot[1].inserted = 1;
+ slot[1].cisread = 0;
+ }
+ slot[1].occupied = 1;
+ }
+ if (inserted(nil))
+ wakeup(&pcmcia.event);
+ }
+}
+
+/* use reference card to turn cards on and off */
+static void
+increfp(PCMslot *sp)
+{
+ wlock(sp);
+ if(waserror()){
+ wunlock(sp);
+ nexterror();
+ }
+
+iprint("increfp %ld\n", sp - slot);
+ if(incref(&pcmcia) == 1){
+iprint("increfp full power\n");
+ egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 1);
+ delay(200);
+ egpiobits(EGPIO_pcmcia_reset, 1);
+ delay(100);
+ egpiobits(EGPIO_pcmcia_reset, 0);
+ delay(500);
+ }
+ incref(&sp->ref);
+ slotinfo(nil, nil);
+ if(sp->occupied && sp->cisread == 0) {
+ pcmcisread(sp);
+ }
+
+ wunlock(sp);
+ poperror();
+}
+
+static void
+decrefp(PCMslot *sp)
+{
+iprint("decrefp %ld\n", sp - slot);
+ decref(&sp->ref);
+ if(decref(&pcmcia) == 0){
+iprint("increfp power down\n");
+ egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 0);
+ }
+}
+
+/*
+ * the regions are staticly mapped
+ */
+static void
+slotmap(int slotno, ulong regs, ulong attr, ulong mem)
+{
+ PCMslot *sp;
+
+ sp = &slot[slotno];
+ sp->slotno = slotno;
+ sp->memlen = 64*OneMeg;
+ sp->verstr[0] = 0;
+
+ sp->mem = mapmem(mem, 64*OneMeg, 0);
+ sp->memmap.ca = 0;
+ sp->memmap.cea = 64*MB;
+ sp->memmap.isa = (ulong)mem;
+ sp->memmap.len = 64*OneMeg;
+ sp->memmap.attr = 0;
+
+ sp->attr = mapmem(attr, OneMeg, 0);
+ sp->attrmap.ca = 0;
+ sp->attrmap.cea = MB;
+ sp->attrmap.isa = (ulong)attr;
+ sp->attrmap.len = OneMeg;
+ sp->attrmap.attr = 1;
+
+ sp->regs = mapspecial(regs, 32*1024);
+}
+
+PCMmap*
+pcmmap(int slotno, ulong, int, int attr)
+{
+ if(slotno > nslot)
+ panic("pcmmap");
+ if(attr)
+ return &slot[slotno].attrmap;
+ else
+ return &slot[slotno].memmap;
+}
+
+void
+pcmunmap(int, PCMmap*)
+{
+}
+
+/*
+ * setup card timings
+ * times are in ns
+ * count = ceiling[access-time/(2*3*T)] - 1, where T is a processor cycle
+ *
+ */
+static int
+ns2count(int ns)
+{
+ ulong y;
+
+ /* get 100 times cycle time */
+ y = 100000000/(conf.hz/1000);
+
+ /* get 10 times ns/(cycle*6) */
+ y = (1000*ns)/(6*y);
+
+ /* round up */
+ y += 9;
+ y /= 10;
+
+ /* subtract 1 */
+ return y-1;
+}
+static void
+slottiming(int slotno, int tio, int tattr, int tmem, int fast)
+{
+ ulong x;
+
+ x = 0;
+ if(fast)
+ x |= 1<<MECR_fast0;
+ x |= ns2count(tio) << MECR_io0;
+ x |= ns2count(tattr) << MECR_attr0;
+ x |= ns2count(tmem) << MECR_mem0;
+ if(slotno == 0){
+ x |= memconfregs->mecr & 0xffff0000;
+ } else {
+ x <<= 16;
+ x |= memconfregs->mecr & 0xffff;
+ }
+ memconfregs->mecr = x;
+}
+
+/* For compat with ../pc devices. Don't use it for the bitsy
+ */
+int
+pcmspecial(char*, ISAConf*)
+{
+ return -1;
+}
diff --git a/sys/src/9/bitsy/devpenmouse.c b/sys/src/9/bitsy/devpenmouse.c
new file mode 100755
index 000000000..4174c21f7
--- /dev/null
+++ b/sys/src/9/bitsy/devpenmouse.c
@@ -0,0 +1,509 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+#include <ctype.h>
+
+typedef struct Mouseinfo Mouseinfo;
+typedef struct Mousestate Mousestate;
+typedef struct Calibration Calibration;
+
+struct Calibration
+{
+ long scalex;
+ long scaley;
+ long transx;
+ long transy;
+} calibration = {
+ -16435,
+ 23275,
+ 253,
+ -23
+};
+
+/* The pen goes down, tracks some and goes up again. The pen alone can
+ * only simulate a one-button mouse.
+ * To simulate a more-button (five, in this case) mouse, we use the four
+ * keys along the the bottom of the iPaq as modifiers.
+ * When one (or more) of the modifier keys is (are) down, a pen-down event
+ * causes the corresponding bottons to go down. If no modifier key is
+ * depressed, a pen-down event is translated into a button-one down event.
+ * Releasing the modifier keys has no direct effect. The pen-up event is
+ * the one that triggers mouse-up events.
+ */
+struct Mousestate
+{
+ Point xy; /* mouse.xy */
+ int buttons; /* mouse.buttons */
+ int modifiers; /* state of physical buttons 2, 3, 4, 5 */
+ ulong counter; /* increments every update */
+ ulong msec; /* time of last event */
+};
+
+struct Mouseinfo
+{
+ Lock;
+ Mousestate;
+ ulong lastcounter; /* value when /dev/mouse read */
+ ulong resize;
+ ulong lastresize;
+ Rendez r;
+ Ref;
+ QLock;
+ int open;
+ int inopen;
+ Mousestate queue[16]; /* circular buffer of click events */
+ int ri; /* read index into queue */
+ int wi; /* write index into queue */
+ uchar qfull; /* queue is full */
+};
+
+Mouseinfo mouse;
+int mouseshifted;
+
+int penmousechanged(void*);
+static void penmousetrack(int b, int x, int y);
+
+enum{
+ Qdir,
+ Qmouse,
+ Qmousein,
+ Qmousectl,
+};
+
+static Dirtab mousedir[]={
+ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
+ "mouse", {Qmouse}, 0, 0666,
+ "mousein", {Qmousein}, 0, 0220,
+ "mousectl", {Qmousectl}, 0, 0660,
+};
+
+enum
+{
+ CMcalibrate,
+ CMswap,
+};
+
+static Cmdtab penmousecmd[] =
+{
+ CMcalibrate, "calibrate", 0,
+ CMswap, "swap", 1,
+};
+
+static uchar buttonmap[8] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+};
+static int mouseswap;
+
+extern Memimage* gscreen;
+
+void
+penbutton(int up, int b) {
+ // button 5 (side button) immediately causes an event
+ // when the pen is down (button 1), other buttons also
+ // cause events, allowing chording with button 1
+ if ((b & 0x20) || (mouse.buttons & 0x1)) {
+ if (up)
+ mouse.buttons &= ~b;
+ else
+ mouse.buttons |= b;
+ penmousetrack(mouse.buttons, -1, -1);
+ } else {
+ if (up)
+ mouse.modifiers &= ~b;
+ else
+ mouse.modifiers |= b;
+ }
+}
+
+void
+pentrackxy(int x, int y) {
+
+ if (x == -1) {
+ /* pen up. associate with button 1 through 5 up */
+ mouse.buttons &= ~0x1f;
+ } else {
+ x = ((x*calibration.scalex)>>16) + calibration.transx;
+ y = ((y*calibration.scaley)>>16) + calibration.transy;
+ if ((mouse.buttons & 0x1f) == 0) {
+ if (mouse.modifiers)
+ mouse.buttons |= mouse.modifiers;
+ else
+ mouse.buttons |= 0x1;
+ }
+ }
+ penmousetrack(mouse.buttons, x, y);
+}
+
+static void
+penmousereset(void)
+{
+ if(!conf.monitor)
+ return;
+}
+
+static void
+penmouseinit(void)
+{
+ if(!conf.monitor)
+ return;
+}
+
+static Chan*
+penmouseattach(char *spec)
+{
+ if(!conf.monitor)
+ error(Egreg);
+ return devattach('m', spec);
+}
+
+static Walkqid*
+penmousewalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
+}
+
+static int
+penmousestat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, mousedir, nelem(mousedir), devgen);
+}
+
+static Chan*
+penmouseopen(Chan *c, int omode)
+{
+ switch((ulong)c->qid.path){
+ case Qdir:
+ if(omode != OREAD)
+ error(Eperm);
+ break;
+ case Qmouse:
+ lock(&mouse);
+ if(mouse.open){
+ unlock(&mouse);
+ error(Einuse);
+ }
+ mouse.open = 1;
+ mouse.ref++;
+ unlock(&mouse);
+ break;
+ case Qmousein:
+ /* error("disabled"); */
+ lock(&mouse);
+ if(mouse.inopen){
+ unlock(&mouse);
+ error(Einuse);
+ }
+ mouse.inopen = 1;
+ unlock(&mouse);
+ break;
+ default:
+ incref(&mouse);
+ }
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+static void
+penmousecreate(Chan*, char*, int, ulong)
+{
+ if(!conf.monitor)
+ error(Egreg);
+ error(Eperm);
+}
+
+static void
+penmouseclose(Chan *c)
+{
+ if(c->qid.path != Qdir && (c->flag&COPEN)){
+ lock(&mouse);
+ if(c->qid.path == Qmouse)
+ mouse.open = 0;
+ else if(c->qid.path == Qmousein){
+ mouse.inopen = 0;
+ unlock(&mouse);
+ return;
+ }
+ --mouse.ref;
+ unlock(&mouse);
+ }
+}
+
+static long
+penmouseread(Chan *c, void *va, long n, vlong)
+{
+ char buf[4*12+1];
+ static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };
+ Mousestate m;
+
+ switch((ulong)c->qid.path){
+ case Qdir:
+ return devdirread(c, va, n, mousedir, nelem(mousedir), devgen);
+
+ case Qmousectl:
+ sprint(buf, "c%11ld %11ld %11ld %11ld",
+ calibration.scalex, calibration.scaley,
+ calibration.transx, calibration.transy);
+ if(n > 1+4*12)
+ n = 1+4*12;
+ memmove(va, buf, n);
+ return n;
+
+ case Qmouse:
+ while(penmousechanged(0) == 0)
+ sleep(&mouse.r, penmousechanged, 0);
+
+ mouse.qfull = 0;
+
+ /*
+ * No lock of the indices is necessary here, because ri is only
+ * updated by us, and there is only one mouse reader
+ * at a time. I suppose that more than one process
+ * could try to read the fd at one time, but such behavior
+ * is degenerate and already violates the calling
+ * conventions for sleep above.
+ */
+ if(mouse.ri != mouse.wi) {
+ m = mouse.queue[mouse.ri];
+ if(++mouse.ri == nelem(mouse.queue))
+ mouse.ri = 0;
+ } else {
+ m = mouse.Mousestate;
+ }
+ sprint(buf, "m%11d %11d %11d %11lud",
+ m.xy.x, m.xy.y,
+ m.buttons,
+ m.msec);
+ 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;
+ }
+ return 0;
+}
+
+static void
+setbuttonmap(char* map)
+{
+ int i, x, one, two, three;
+
+ one = two = three = 0;
+ for(i = 0; i < 3; i++){
+ if(map[i] == 0)
+ error(Ebadarg);
+ if(map[i] == '1'){
+ if(one)
+ error(Ebadarg);
+ one = 1<<i;
+ }
+ else if(map[i] == '2'){
+ if(two)
+ error(Ebadarg);
+ two = 1<<i;
+ }
+ else if(map[i] == '3'){
+ if(three)
+ error(Ebadarg);
+ three = 1<<i;
+ }
+ else
+ error(Ebadarg);
+ }
+ if(map[i])
+ error(Ebadarg);
+
+ memset(buttonmap, 0, 8);
+ for(i = 0; i < 8; i++){
+ x = 0;
+ if(i & 1)
+ x |= one;
+ if(i & 2)
+ x |= two;
+ if(i & 4)
+ x |= three;
+ buttonmap[x] = i;
+ }
+}
+
+static long
+penmousewrite(Chan *c, void *va, long n, vlong)
+{
+ char *p;
+ Point pt;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ char buf[64];
+ int b;
+
+ p = va;
+ switch((ulong)c->qid.path){
+ case Qdir:
+ error(Eisdir);
+
+ case Qmousectl:
+ cb = parsecmd(va, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, penmousecmd, nelem(penmousecmd));
+ switch(ct->index){
+ case CMswap:
+ if(mouseswap)
+ setbuttonmap("123");
+ else
+ setbuttonmap("321");
+ mouseswap ^= 1;
+ break;
+ case CMcalibrate:
+ if (cb->nf == 1) {
+ calibration.scalex = 1<<16;
+ calibration.scaley = 1<<16;
+ calibration.transx = 0;
+ calibration.transy = 0;
+ } else if (cb->nf == 5) {
+ if ((!isdigit(*cb->f[1]) && *cb->f[1] != '-')
+ || (!isdigit(*cb->f[2]) && *cb->f[2] != '-')
+ || (!isdigit(*cb->f[3]) && *cb->f[3] != '-')
+ || (!isdigit(*cb->f[4]) && *cb->f[4] != '-'))
+ error("bad syntax in control file message");
+ calibration.scalex = strtol(cb->f[1], nil, 0);
+ calibration.scaley = strtol(cb->f[2], nil, 0);
+ calibration.transx = strtol(cb->f[3], nil, 0);
+ calibration.transy = strtol(cb->f[4], nil, 0);
+ } else
+ cmderror(cb, Ecmdargs);
+ break;
+ }
+ free(cb);
+ poperror();
+ return n;
+
+ case Qmousein:
+ if(n > sizeof buf-1)
+ n = sizeof buf -1;
+ memmove(buf, va, n);
+ buf[n] = 0;
+ p = 0;
+ pt.x = strtol(buf+1, &p, 0);
+ if(p == 0)
+ error(Eshort);
+ pt.y = strtol(p, &p, 0);
+ if(p == 0)
+ error(Eshort);
+ b = strtol(p, &p, 0);
+ penmousetrack(b, pt.x, pt.y);
+ return n;
+
+ case Qmouse:
+ if(n > sizeof buf-1)
+ n = sizeof buf -1;
+ memmove(buf, va, n);
+ buf[n] = 0;
+ p = 0;
+ pt.x = strtoul(buf+1, &p, 0);
+ if(p == 0)
+ error(Eshort);
+ pt.y = strtoul(p, 0, 0);
+ qlock(&mouse);
+ if(ptinrect(pt, gscreen->r))
+ penmousetrack(mouse.buttons, pt.x, pt.y);
+ qunlock(&mouse);
+ return n;
+ }
+
+ error(Egreg);
+ return -1;
+}
+
+Dev penmousedevtab = {
+ 'm',
+ "penmouse",
+
+ penmousereset,
+ penmouseinit,
+ devshutdown,
+ penmouseattach,
+ penmousewalk,
+ penmousestat,
+ penmouseopen,
+ penmousecreate,
+ penmouseclose,
+ penmouseread,
+ devbread,
+ penmousewrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+/*
+ * called at interrupt level to update the structure and
+ * awaken any waiting procs.
+ */
+static void
+penmousetrack(int b, int x, int y)
+{
+ int lastb;
+
+ if (x >= 0)
+ mouse.xy = Pt(x, y);
+ lastb = mouse.buttons;
+ mouse.buttons = b;
+ mouse.counter++;
+ mouse.msec = TK2MS(MACHP(0)->ticks);
+
+ /*
+ * if the queue fills, we discard the entire queue and don't
+ * queue any more events until a reader polls the mouse.
+ */
+ if(!mouse.qfull && lastb != b) { /* add to ring */
+ mouse.queue[mouse.wi] = mouse.Mousestate;
+ if(++mouse.wi == nelem(mouse.queue))
+ mouse.wi = 0;
+ if(mouse.wi == mouse.ri)
+ mouse.qfull = 1;
+ }
+ wakeup(&mouse.r);
+ drawactive(1);
+ resetsuspendtimer();
+}
+
+int
+penmousechanged(void*)
+{
+ return mouse.lastcounter != mouse.counter ||
+ mouse.lastresize != mouse.resize;
+}
+
+Point
+penmousexy(void)
+{
+ return mouse.xy;
+}
+
+/*
+ * notify reader that screen has been resized (ha!)
+ */
+void
+mouseresize(void)
+{
+ mouse.resize++;
+ wakeup(&mouse.r);
+}
+
diff --git a/sys/src/9/bitsy/devuda1341.c b/sys/src/9/bitsy/devuda1341.c
new file mode 100755
index 000000000..bdc54a469
--- /dev/null
+++ b/sys/src/9/bitsy/devuda1341.c
@@ -0,0 +1,1400 @@
+/*
+ * SAC/UDA 1341 Audio driver for the Bitsy
+ *
+ * The Philips UDA 1341 sound chip is accessed through the Serial Audio
+ * Controller (SAC) of the StrongARM SA-1110. This is much more a SAC
+ * controller than a UDA controller, but we have a devsac.c already.
+ *
+ * The code morphs Nicolas Pitre's <nico@cam.org> Linux controller
+ * and Ken's Soundblaster controller.
+ *
+ * The interface should be identical to that of devaudio.c
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+#include "sa1110dma.h"
+
+static int debug = 0;
+
+/*
+ * GPIO based L3 bus support.
+ *
+ * This provides control of Philips L3 type devices.
+ * GPIO lines are used for clock, data and mode pins.
+ *
+ * Note: The L3 pins are shared with I2C devices. This should not present
+ * any problems as long as an I2C start sequence is not generated. This is
+ * defined as a 1->0 transition on the data lines when the clock is high.
+ * It is critical this code only allow data transitions when the clock
+ * is low. This is always legal in L3.
+ *
+ * The IIC interface requires the clock and data pin to be LOW when idle. We
+ * must make sure we leave them in this state.
+ *
+ * It appears the read data is generated on the falling edge of the clock
+ * and should be held stable during the clock high time.
+ */
+
+/*
+ * L3 setup and hold times (expressed in µs)
+ */
+enum {
+ L3_AcquireTime = 1,
+ L3_ReleaseTime = 1,
+ L3_DataSetupTime = (190+999)/1000, /* 190 ns */
+ L3_DataHoldTime = ( 30+999)/1000,
+ L3_ModeSetupTime = (190+999)/1000,
+ L3_ModeHoldTime = (190+999)/1000,
+ L3_ClockHighTime = (100+999)/1000,
+ L3_ClockLowTime = (100+999)/1000,
+ L3_HaltTime = (190+999)/1000,
+};
+
+/* UDA 1341 Registers */
+enum {
+ /* Status0 register */
+ UdaStatusDC = 0, /* 1 bit */
+ UdaStatusIF = 1, /* 3 bits */
+ UdaStatusSC = 4, /* 2 bits */
+ UdaStatusRST = 6, /* 1 bit */
+};
+
+enum {
+ /* Status1 register */
+ UdaStatusPC = 0, /* 2 bits */
+ UdaStatusDS = 2, /* 1 bit */
+ UdaStatusPDA = 3, /* 1 bit */
+ UdaStatusPAD = 4, /* 1 bit */
+ UdaStatusIGS = 5, /* 1 bit */
+ UdaStatusOGS = 6, /* 1 bit */
+};
+
+/*
+ * UDA1341 L3 address and command types
+ */
+
+enum {
+ UDA1341_DATA0 = 0,
+ UDA1341_DATA1,
+ UDA1341_STATUS,
+ UDA1341_L3Addr = 0x14,
+};
+
+typedef struct AQueue AQueue;
+typedef struct Buf Buf;
+typedef struct IOstate IOstate;
+
+enum
+{
+ Qdir = 0,
+ Qaudio,
+ Qvolume,
+ Qstatus,
+ Qstats,
+
+ Fmono = 1,
+ Fin = 2,
+ Fout = 4,
+
+ Aclosed = 0,
+ Aread,
+ Awrite,
+
+ Vaudio = 0,
+ Vmic,
+ Vtreb,
+ Vbass,
+ Vspeed,
+ Vbufsize,
+ Vfilter,
+ Vinvert,
+ Nvol,
+
+ Bufsize = 4* 1024, /* 46 ms each */
+ Nbuf = 10, /* 1.5 seconds total */
+
+ Speed = 44100,
+ Ncmd = 50, /* max volume command words */
+};
+
+enum {
+ Flushbuf = 0xe0000000,
+};
+
+/* System Clock -- according to the manual, it seems that when the UDA is
+ configured in non MSB/I2S mode, it uses a divisor of 256 to the 12.288MHz
+ clock. The other rates are only supported in MSB mode, which should be
+ implemented at some point */
+enum {
+ SC512FS = 0 << 2,
+ SC384FS = 1 << 2,
+ SC256FS = 2 << 2,
+ CLOCKMASK = 3 << 2,
+};
+
+/* Format */
+enum {
+ LSB16 = 1 << 1,
+ LSB18 = 2 << 1,
+ LSB20 = 3 << 1,
+ MSB = 4 << 1,
+ MSB16 = 5 << 1,
+ MSB18 = 6 << 1,
+ MSB20 = 7 << 1,
+};
+
+Dirtab
+audiodir[] =
+{
+ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
+ "audio", {Qaudio}, 0, 0666,
+ "volume", {Qvolume}, 0, 0666,
+ "audiostatus", {Qstatus}, 0, 0444,
+ "audiostats", {Qstats}, 0, 0444,
+};
+
+struct Buf
+{
+ uchar* virt;
+ ulong phys;
+ uint nbytes;
+};
+
+struct IOstate
+{
+ QLock;
+ Lock ilock;
+ Rendez vous;
+ Chan *chan; /* chan of open */
+ int dma; /* dma chan, alloc on open, free on close */
+ int bufinit; /* boolean, if buffers allocated */
+ Buf buf[Nbuf]; /* buffers and queues */
+ volatile Buf *current; /* next dma to finish */
+ volatile Buf *next; /* next candidate for dma */
+ volatile Buf *filling; /* buffer being filled */
+/* to have defines just like linux — there's a real operating system */
+#define emptying filling
+};
+
+static struct
+{
+ QLock;
+ int amode; /* Aclosed/Aread/Awrite for /audio */
+ int intr; /* boolean an interrupt has happened */
+ int rivol[Nvol]; /* right/left input/output volumes */
+ int livol[Nvol];
+ int rovol[Nvol];
+ int lovol[Nvol];
+ ulong totcount; /* how many bytes processed since open */
+ vlong tottime; /* time at which totcount bytes were processed */
+ IOstate i;
+ IOstate o;
+} audio;
+
+int zerodma; /* dma buffer used for sending zero */
+
+typedef struct Iostats Iostats;
+struct Iostats {
+ ulong totaldma;
+ ulong idledma;
+ ulong faildma;
+ ulong samedma;
+ ulong empties;
+};
+
+static struct
+{
+ ulong bytes;
+ Iostats rx, tx;
+} iostats;
+
+static void setaudio(int in, int out, int left, int right, int value);
+static void setspeed(int in, int out, int left, int right, int value);
+static void setbufsize(int in, int out, int left, int right, int value);
+
+static struct
+{
+ char* name;
+ int flag;
+ int ilval; /* initial values */
+ int irval;
+ void (*setval)(int, int, int, int, int);
+} volumes[] =
+{
+[Vaudio] {"audio", Fout|Fmono, 80, 80, setaudio },
+[Vmic] {"mic", Fin|Fmono, 0, 0, nil },
+[Vtreb] {"treb", Fout|Fmono, 50, 50, nil },
+[Vbass] {"bass", Fout|Fmono, 50, 50, nil },
+[Vspeed] {"speed", Fin|Fout|Fmono, Speed, Speed, setspeed },
+[Vbufsize] {"bufsize", Fin|Fout|Fmono, Bufsize, Bufsize, setbufsize },
+[Vfilter] {"filter", Fout|Fmono, 0, 0, nil },
+[Vinvert] {"invert", Fin|Fout|Fmono, 0, 0, nil },
+[Nvol] {0}
+};
+
+static void setreg(char *name, int val, int n);
+
+/*
+ * Grab control of the IIC/L3 shared pins
+ */
+static void
+L3_acquirepins(void)
+{
+ gpioregs->set = (GPIO_L3_MODE_o | GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
+ gpioregs->direction |= (GPIO_L3_MODE_o | GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
+ microdelay(L3_AcquireTime);
+}
+
+/*
+ * Release control of the IIC/L3 shared pins
+ */
+static void
+L3_releasepins(void)
+{
+ gpioregs->direction &= ~(GPIO_L3_MODE_o | GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
+ microdelay(L3_ReleaseTime);
+}
+
+/*
+ * Initialize the interface
+ */
+static void
+L3_init(void)
+{
+ gpioregs->altfunc &= ~(GPIO_L3_SDA_io | GPIO_L3_SCLK_o | GPIO_L3_MODE_o);
+ L3_releasepins();
+}
+
+/*
+ * Get a bit. The clock is high on entry and on exit. Data is read after
+ * the clock low time has expired.
+ */
+static int
+L3_getbit(void)
+{
+ int data;
+
+ gpioregs->clear = GPIO_L3_SCLK_o;
+ microdelay(L3_ClockLowTime);
+
+ data = (gpioregs->level & GPIO_L3_SDA_io) ? 1 : 0;
+
+ gpioregs->set = GPIO_L3_SCLK_o;
+ microdelay(L3_ClockHighTime);
+
+ return data;
+}
+
+/*
+ * Send a bit. The clock is high on entry and on exit. Data is sent only
+ * when the clock is low (I2C compatibility).
+ */
+static void
+L3_sendbit(int bit)
+{
+ gpioregs->clear = GPIO_L3_SCLK_o;
+
+ if (bit & 1)
+ gpioregs->set = GPIO_L3_SDA_io;
+ else
+ gpioregs->clear = GPIO_L3_SDA_io;
+
+ /* Assumes L3_DataSetupTime < L3_ClockLowTime */
+ microdelay(L3_ClockLowTime);
+
+ gpioregs->set = GPIO_L3_SCLK_o;
+ microdelay(L3_ClockHighTime);
+}
+
+/*
+ * Send a byte. The mode line is set or pulsed based on the mode sequence
+ * count. The mode line is high on entry and exit. The mod line is pulsed
+ * before the second data byte and before ech byte thereafter.
+ */
+static void
+L3_sendbyte(char data, int mode)
+{
+ int i;
+
+ switch(mode) {
+ case 0: /* Address mode */
+ gpioregs->clear = GPIO_L3_MODE_o;
+ break;
+ case 1: /* First data byte */
+ break;
+ default: /* Subsequent bytes */
+ gpioregs->clear = GPIO_L3_MODE_o;
+ microdelay(L3_HaltTime);
+ gpioregs->set = GPIO_L3_MODE_o;
+ break;
+ }
+
+ microdelay(L3_ModeSetupTime);
+
+ for (i = 0; i < 8; i++)
+ L3_sendbit(data >> i);
+
+ if (mode == 0) /* Address mode */
+ gpioregs->set = GPIO_L3_MODE_o;
+
+ microdelay(L3_ModeHoldTime);
+}
+
+/*
+ * Get a byte. The mode line is set or pulsed based on the mode sequence
+ * count. The mode line is high on entry and exit. The mod line is pulsed
+ * before the second data byte and before each byte thereafter. This
+ * function is never valid with mode == 0 (address cycle) as the address
+ * is always sent on the bus, not read.
+ */
+static char
+L3_getbyte(int mode)
+{
+ char data = 0;
+ int i;
+
+ switch(mode) {
+ case 0: /* Address mode - never valid */
+ break;
+ case 1: /* First data byte */
+ break;
+ default: /* Subsequent bytes */
+ gpioregs->clear = GPIO_L3_MODE_o;
+ microdelay(L3_HaltTime);
+ gpioregs->set = GPIO_L3_MODE_o;
+ break;
+ }
+
+ microdelay(L3_ModeSetupTime);
+
+ for (i = 0; i < 8; i++)
+ data |= (L3_getbit() << i);
+
+ microdelay(L3_ModeHoldTime);
+
+ return data;
+}
+
+/*
+ * Write data to a device on the L3 bus. The address is passed as well as
+ * the data and length. The length written is returned. The register space
+ * is encoded in the address (low two bits are set and device address is
+ * in the upper 6 bits).
+ */
+static int
+L3_write(uchar addr, uchar *data, int len)
+{
+ int mode = 0;
+ int bytes = len;
+
+ L3_acquirepins();
+ L3_sendbyte(addr, mode++);
+ while(len--)
+ L3_sendbyte(*data++, mode++);
+ L3_releasepins();
+ return bytes;
+}
+
+/*
+ * Read data from a device on the L3 bus. The address is passed as well as
+ * the data and length. The length read is returned. The register space
+ * is encoded in the address (low two bits are set and device address is
+ * in the upper 6 bits).
+
+ * Commented out, not used
+static int
+L3_read(uchar addr, uchar *data, int len)
+{
+ int mode = 0;
+ int bytes = len;
+
+ L3_acquirepins();
+ L3_sendbyte(addr, mode++);
+ gpioregs->direction &= ~(GPIO_L3_SDA_io);
+ while(len--)
+ *data++ = L3_getbyte(mode++);
+ L3_releasepins();
+ return bytes;
+}
+ */
+
+void
+audiomute(int on)
+{
+ egpiobits(EGPIO_audio_mute, on);
+}
+
+static char Emode[] = "illegal open mode";
+static char Evolume[] = "illegal volume specifier";
+
+static void
+bufinit(IOstate *b)
+{
+ int i;
+
+ if (debug) print("bufinit\n");
+ for (i = 0; i < Nbuf; i++) {
+ b->buf[i].virt = xalloc(Bufsize);
+ b->buf[i].phys = PADDR(b->buf[i].virt);
+ memset(b->buf[i].virt, 0xAA, Bufsize);
+ }
+ b->bufinit = 1;
+};
+
+static void
+setempty(IOstate *b)
+{
+ int i;
+
+ if (debug) print("setempty\n");
+ for (i = 0; i < Nbuf; i++) {
+ b->buf[i].nbytes = 0;
+ }
+ b->filling = b->buf;
+ b->current = b->buf;
+ b->next = b->buf;
+}
+
+static int
+audioqnotempty(void *x)
+{
+ IOstate *s = x;
+
+ return dmaidle(s->dma) || s->emptying != s->current;
+}
+
+static int
+audioqnotfull(void *x)
+{
+ IOstate *s = x;
+
+ return dmaidle(s->dma) || s->filling != s->current;
+}
+
+SSPregs *sspregs;
+MCPregs *mcpregs;
+
+static void
+audioinit(void)
+{
+ /* Turn MCP operations off */
+ mcpregs = mapspecial(MCPREGS, sizeof(MCPregs));
+ mcpregs->status &= ~(1<<16);
+
+ sspregs = mapspecial(SSPREGS, sizeof(SSPregs));
+
+}
+
+uchar status0[1] = {0x02};
+uchar status1[1] = {0x80};
+uchar data00[1] = {0x00}; /* volume control, bits 0 – 5 */
+uchar data01[1] = {0x40};
+uchar data02[1] = {0x80};
+uchar data0e0[2] = {0xc0, 0xe0};
+uchar data0e1[2] = {0xc1, 0xe0};
+uchar data0e2[2] = {0xc2, 0xf2};
+/* there is no data0e3 */
+uchar data0e4[2] = {0xc4, 0xe0};
+uchar data0e5[2] = {0xc5, 0xe0};
+uchar data0e6[2] = {0xc6, 0xe3};
+
+static void
+enable(void)
+{
+ uchar data[1];
+
+ L3_init();
+
+ /* Setup the uarts */
+ ppcregs->assignment &= ~(1<<18);
+
+ sspregs->control0 = 0;
+ sspregs->control0 = 0x031f; /* 16 bits, TI frames, serial clock rate 3 */
+ sspregs->control1 = 0x0020; /* ext clock */
+ sspregs->control0 = 0x039f; /* enable */
+
+ /* Enable the audio power */
+ audioicpower(1);
+ egpiobits(EGPIO_codec_reset, 1);
+
+ setspeed(0, 0, 0, 0, volumes[Vspeed].ilval);
+
+ data[0] = status0[0] | 1 << UdaStatusRST;
+ L3_write(UDA1341_L3Addr | UDA1341_STATUS, data, 1 );
+ gpioregs->clear = EGPIO_codec_reset;
+ gpioregs->set = EGPIO_codec_reset;
+ /* write uda 1341 status[0] */
+ data[0] = status0[0];
+ L3_write(UDA1341_L3Addr | UDA1341_STATUS, data, 1);
+
+ if (debug)
+ print("enable: status0 = 0x%2.2ux\n", data[0]);
+
+ L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
+ L3_write(UDA1341_L3Addr | UDA1341_DATA0, data02, 1);
+ L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e2, 2);
+ L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e6, 2 );
+
+ if (debug) {
+ print("enable: status0 = 0x%2.2ux\n", data[0]);
+ print("enable: status1 = 0x%2.2ux\n", status1[0]);
+ print("enable: data02 = 0x%2.2ux\n", data02[0]);
+ print("enable: data0e2 = 0x%4.4ux\n", data0e2[0] | data0e2[1]<<8);
+ print("enable: data0e4 = 0x%4.4ux\n", data0e4[0] | data0e4[1]<<8);
+ print("enable: data0e6 = 0x%4.4ux\n", data0e6[0] | data0e6[1]<<8);
+ print("enable: sspregs->control0 = 0x%lux\n", sspregs->control0);
+ print("enable: sspregs->control1 = 0x%lux\n", sspregs->control1);
+ }
+}
+
+static void
+resetlevel(void)
+{
+ int i;
+
+ for(i=0; volumes[i].name; i++) {
+ audio.lovol[i] = volumes[i].ilval;
+ audio.rovol[i] = volumes[i].irval;
+ audio.livol[i] = volumes[i].ilval;
+ audio.rivol[i] = volumes[i].irval;
+ }
+}
+
+static void
+mxvolume(void) {
+ int *left, *right;
+
+ setspeed(0, 0, 0, 0, volumes[Vspeed].ilval);
+ if (!dmaidle(audio.i.dma) || !dmaidle(audio.o.dma))
+ L3_write(UDA1341_L3Addr | UDA1341_STATUS, status0, 1);
+
+ if(audio.amode & Aread){
+ left = audio.livol;
+ right = audio.rivol;
+ if (left[Vmic]+right[Vmic] == 0) {
+ /* Turn on automatic gain control (AGC) */
+ data0e4[1] |= 0x10;
+ L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e4, 2 );
+ } else {
+ int v;
+ /* Turn on manual gain control */
+ v = ((left[Vmic]+right[Vmic])*0x7f/200)&0x7f;
+ data0e4[1] &= ~0x13;
+ data0e5[1] &= ~0x1f;
+ data0e4[1] |= v & 0x3;
+ data0e5[0] |= (v & 0x7c)<<6;
+ data0e5[1] |= (v & 0x7c)>>2;
+ L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e4, 2 );
+ L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e5, 2 );
+ }
+ if (left[Vinvert]+right[Vinvert] == 0)
+ status1[0] &= ~0x04;
+ else
+ status1[0] |= 0x04;
+ L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
+ if (debug) {
+ print("mxvolume: status1 = 0x%2.2ux\n", status1[0]);
+ print("mxvolume: data0e4 = 0x%4.4ux\n", data0e4[0]|data0e4[0]<<8);
+ print("mxvolume: data0e5 = 0x%4.4ux\n", data0e5[0]|data0e5[0]<<8);
+ }
+ }
+ if(audio.amode & Awrite){
+ left = audio.lovol;
+ right = audio.rovol;
+ data00[0] &= ~0x3f;
+ data00[0] |= ((200-left[Vaudio]-right[Vaudio])*0x3f/200)&0x3f;
+ if (left[Vtreb]+right[Vtreb] <= 100
+ && left[Vbass]+right[Vbass] <= 100)
+ /* settings neutral */
+ data02[0] &= ~0x03;
+ else {
+ data02[0] |= 0x03;
+ data01[0] &= ~0x3f;
+ data01[0] |= ((left[Vtreb]+right[Vtreb]-100)*0x3/100)&0x03;
+ data01[0] |= (((left[Vbass]+right[Vbass]-100)*0xf/100)&0xf)<<2;
+ }
+ if (left[Vfilter]+right[Vfilter] == 0)
+ data02[0] &= ~0x10;
+ else
+ data02[0]|= 0x10;
+ if (left[Vinvert]+right[Vinvert] == 0)
+ status1[0] &= ~0x10;
+ else
+ status1[0] |= 0x10;
+ L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
+ L3_write(UDA1341_L3Addr | UDA1341_DATA0, data00, 1);
+ L3_write(UDA1341_L3Addr | UDA1341_DATA0, data01, 1);
+ L3_write(UDA1341_L3Addr | UDA1341_DATA0, data02, 1);
+ if (debug) {
+ print("mxvolume: status1 = 0x%2.2ux\n", status1[0]);
+ print("mxvolume: data00 = 0x%2.2ux\n", data00[0]);
+ print("mxvolume: data01 = 0x%2.2ux\n", data01[0]);
+ print("mxvolume: data02 = 0x%2.2ux\n", data02[0]);
+ }
+ }
+}
+
+static void
+setreg(char *name, int val, int n)
+{
+ uchar x[2];
+ int i;
+
+ x[0] = val;
+ x[1] = val>>8;
+
+ if(strcmp(name, "pause") == 0){
+ for(i = 0; i < n; i++)
+ microdelay(val);
+ return;
+ }
+
+ switch(n){
+ case 1:
+ case 2:
+ break;
+ default:
+ error("setreg");
+ }
+
+ if(strcmp(name, "status") == 0){
+ L3_write(UDA1341_L3Addr | UDA1341_STATUS, x, n);
+ } else if(strcmp(name, "data0") == 0){
+ L3_write(UDA1341_L3Addr | UDA1341_DATA0, x, n);
+ } else if(strcmp(name, "data1") == 0){
+ L3_write(UDA1341_L3Addr | UDA1341_DATA1, x, n);
+ } else
+ error("setreg");
+}
+
+static void
+outenable(void) {
+ /* turn on DAC, set output gain switch */
+ audioamppower(1);
+ audiomute(0);
+ status1[0] |= 0x41;
+ L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
+ /* set volume */
+ data00[0] |= 0xf;
+ L3_write(UDA1341_L3Addr | UDA1341_DATA0, data00, 1);
+ if (debug) {
+ print("outenable: status1 = 0x%2.2ux\n", status1[0]);
+ print("outenable: data00 = 0x%2.2ux\n", data00[0]);
+ }
+}
+
+static void
+outdisable(void) {
+ dmastop(audio.o.dma);
+ /* turn off DAC, clear output gain switch */
+ audiomute(1);
+ status1[0] &= ~0x41;
+ L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
+ if (debug) {
+ print("outdisable: status1 = 0x%2.2ux\n", status1[0]);
+ }
+ audioamppower(0);
+}
+
+static void
+inenable(void) {
+ /* turn on ADC, set input gain switch */
+ status1[0] |= 0x22;
+ L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
+ if (debug) {
+ print("inenable: status1 = 0x%2.2ux\n", status1[0]);
+ }
+}
+
+static void
+indisable(void) {
+ dmastop(audio.i.dma);
+ /* turn off ADC, clear input gain switch */
+ status1[0] &= ~0x22;
+ L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
+ if (debug) {
+ print("indisable: status1 = 0x%2.2ux\n", status1[0]);
+ }
+}
+
+static void
+sendaudio(IOstate *s) {
+ /* interrupt routine calls this too */
+ int n;
+
+ if (debug > 1) print("#A: sendaudio\n");
+ ilock(&s->ilock);
+ if ((audio.amode & Aread) && s->next == s->filling && dmaidle(s->dma)) {
+ // send an empty buffer to provide an input clock
+ zerodma |= dmastart(s->dma, Flushbuf, volumes[Vbufsize].ilval) & 0xff;
+ if (zerodma == 0)
+ if (debug) print("emptyfail\n");
+ iostats.tx.empties++;
+ iunlock(&s->ilock);
+ return;
+ }
+ while (s->next != s->filling) {
+ s->next->nbytes &= ~0x3; /* must be a multiple of 4 */
+ if(s->next->nbytes) {
+ if ((n = dmastart(s->dma, s->next->phys, s->next->nbytes)) == 0) {
+ iostats.tx.faildma++;
+ break;
+ }
+ iostats.tx.totaldma++;
+ switch (n >> 8) {
+ case 1:
+ iostats.tx.idledma++;
+ break;
+ case 3:
+ iostats.tx.faildma++;
+ break;
+ }
+ if (debug) {
+ if (debug > 1)
+ print("dmastart @%p\n", s->next);
+ else
+ iprint("+");
+ }
+ s->next->nbytes = 0;
+ }
+ s->next++;
+ if (s->next == &s->buf[Nbuf])
+ s->next = &s->buf[0];
+ }
+ iunlock(&s->ilock);
+}
+
+static void
+recvaudio(IOstate *s) {
+ /* interrupt routine calls this too */
+ int n;
+
+ if (debug > 1) print("#A: recvaudio\n");
+ ilock(&s->ilock);
+ while (s->next != s->emptying) {
+ assert(s->next->nbytes == 0);
+ if ((n = dmastart(s->dma, s->next->phys, volumes[Vbufsize].ilval)) == 0) {
+ iostats.rx.faildma++;
+ break;
+ }
+ iostats.rx.totaldma++;
+ switch (n >> 8) {
+ case 1:
+ iostats.rx.idledma++;
+ break;
+ case 3:
+ iostats.rx.faildma++;
+ break;
+ }
+ if (debug) {
+ if (debug > 1)
+ print("dmastart @%p\n", s->next);
+ else
+ iprint("+");
+ }
+ s->next++;
+ if (s->next == &s->buf[Nbuf])
+ s->next = &s->buf[0];
+ }
+ iunlock(&s->ilock);
+}
+
+void
+audiopower(int flag) {
+ IOstate *s;
+
+ if (debug) {
+ iprint("audiopower %d\n", flag);
+ }
+ if (flag) {
+ /* power on only when necessary */
+ if (audio.amode) {
+ audioamppower(1);
+ audioicpower(1);
+ egpiobits(EGPIO_codec_reset, 1);
+ enable();
+ if (audio.amode & Aread) {
+ inenable();
+ s = &audio.i;
+ dmareset(s->dma, 1, 0, 4, 2, SSPRecvDMA, Port4SSP);
+ recvaudio(s);
+ }
+ if (audio.amode & Awrite) {
+ outenable();
+ s = &audio.o;
+ dmareset(s->dma, 0, 0, 4, 2, SSPXmitDMA, Port4SSP);
+ sendaudio(s);
+ }
+ mxvolume();
+ }
+ } else {
+ /* power off */
+ if (audio.amode & Aread)
+ indisable();
+ if (audio.amode & Awrite)
+ outdisable();
+ egpiobits(EGPIO_codec_reset, 0);
+ audioamppower(0);
+ audioicpower(0);
+ }
+}
+
+static void
+audiointr(void *x, ulong ndma) {
+ IOstate *s = x;
+
+ if (debug) {
+ if (debug > 1)
+ iprint("#A: audio interrupt @%p\n", s->current);
+ else
+ iprint("-");
+ }
+ if (s == &audio.i || (ndma & ~zerodma)) {
+ /* A dma, not of a zero buffer completed, update current
+ * Only interrupt routine touches s->current
+ */
+ s->current->nbytes = (s == &audio.i)? volumes[Vbufsize].ilval: 0;
+ s->current++;
+ if (s->current == &s->buf[Nbuf])
+ s->current = &s->buf[0];
+ }
+ if (ndma) {
+ if (s == &audio.o) {
+ zerodma &= ~ndma;
+ sendaudio(s);
+ } else if (s == &audio.i)
+ recvaudio(s);
+ }
+ wakeup(&s->vous);
+}
+
+static Chan*
+audioattach(char *param)
+{
+ return devattach('A', param);
+}
+
+static Walkqid*
+audiowalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, audiodir, nelem(audiodir), devgen);
+}
+
+static int
+audiostat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, audiodir, nelem(audiodir), devgen);
+}
+
+static Chan*
+audioopen(Chan *c, int mode)
+{
+ IOstate *s;
+ int omode = mode;
+
+ switch((ulong)c->qid.path) {
+ default:
+ error(Eperm);
+ break;
+
+ case Qstatus:
+ case Qstats:
+ if((omode&7) != OREAD)
+ error(Eperm);
+ case Qvolume:
+ case Qdir:
+ break;
+
+ case Qaudio:
+ omode = (omode & 0x7) + 1;
+ if (omode & ~(Aread | Awrite))
+ error(Ebadarg);
+ qlock(&audio);
+ if(audio.amode & omode){
+ qunlock(&audio);
+ error(Einuse);
+ }
+ enable();
+ memset(&iostats, 0, sizeof(iostats));
+ if (omode & Aread) {
+ inenable();
+ s = &audio.i;
+ if(s->bufinit == 0)
+ bufinit(s);
+ setempty(s);
+ s->emptying = &s->buf[Nbuf-1];
+ s->chan = c;
+ s->dma = dmaalloc(1, 0, 4, 2, SSPRecvDMA, Port4SSP, audiointr, (void*)s);
+ audio.amode |= Aread;
+ }
+ if (omode & (Aread|Awrite) && (audio.amode & Awrite) == 0) {
+ s = &audio.o;
+ if(s->bufinit == 0)
+ bufinit(s);
+ setempty(s);
+ s->chan = c;
+ s->dma = dmaalloc(0, 0, 4, 2, SSPXmitDMA, Port4SSP, audiointr, (void*)s);
+ }
+ if (omode & Awrite) {
+ audio.amode |= Awrite;
+ outenable();
+ }
+ mxvolume();
+ if (audio.amode & Aread)
+ sendaudio(&audio.o);
+ qunlock(&audio);
+
+ if (debug) print("open done\n");
+ break;
+ }
+ c = devopen(c, mode, audiodir, nelem(audiodir), devgen);
+ c->mode = openmode(mode);
+ c->flag |= COPEN;
+ c->offset = 0;
+
+ return c;
+}
+
+static void
+audioclose(Chan *c)
+{
+ IOstate *s;
+
+ switch((ulong)c->qid.path) {
+ default:
+ error(Eperm);
+ break;
+
+ case Qdir:
+ case Qvolume:
+ case Qstatus:
+ case Qstats:
+ break;
+
+ case Qaudio:
+ if (debug > 1) print("#A: close\n");
+ if(c->flag & COPEN) {
+ qlock(&audio);
+ if (audio.i.chan == c) {
+ /* closing the read end */
+ audio.amode &= ~Aread;
+ s = &audio.i;
+ qlock(s);
+ indisable();
+ setempty(s);
+ dmafree(s->dma);
+ qunlock(s);
+ if ((audio.amode & Awrite) == 0) {
+ s = &audio.o;
+ qlock(s);
+ while(waserror())
+ ;
+ dmawait(s->dma);
+ poperror();
+ outdisable();
+ setempty(s);
+ dmafree(s->dma);
+ qunlock(s);
+ }
+ }
+ if (audio.o.chan == c) {
+ /* closing the write end */
+ audio.amode &= ~Awrite;
+ s = &audio.o;
+ qlock(s);
+ if (s->filling->nbytes) {
+ /* send remaining partial buffer */
+ s->filling++;
+ if (s->filling == &s->buf[Nbuf])
+ s->filling = &s->buf[0];
+ sendaudio(s);
+ }
+ while(waserror())
+ ;
+ dmawait(s->dma);
+ poperror();
+ outdisable();
+ setempty(s);
+ if ((audio.amode & Aread) == 0)
+ dmafree(s->dma);
+ qunlock(s);
+ }
+ if (audio.amode == 0) {
+ /* turn audio off */
+ egpiobits(EGPIO_codec_reset, 0);
+ audioicpower(0);
+ }
+ qunlock(&audio);
+ }
+ break;
+ }
+}
+
+static long
+audioread(Chan *c, void *v, long n, vlong off)
+{
+ int liv, riv, lov, rov;
+ long m, n0;
+ char buf[300];
+ int j;
+ ulong offset = off;
+ char *p;
+ IOstate *s;
+
+ n0 = n;
+ p = v;
+ switch((ulong)c->qid.path) {
+ default:
+ error(Eperm);
+ break;
+
+ case Qdir:
+ return devdirread(c, p, n, audiodir, nelem(audiodir), devgen);
+
+ case Qaudio:
+ if (debug > 1) print("#A: read %ld\n", n);
+ if((audio.amode & Aread) == 0)
+ error(Emode);
+ s = &audio.i;
+ qlock(s);
+ if(waserror()){
+ qunlock(s);
+ nexterror();
+ }
+ while(n > 0) {
+ if(s->emptying->nbytes == 0) {
+ if (debug > 1) print("#A: emptied @%p\n", s->emptying);
+ recvaudio(s);
+ s->emptying++;
+ if (s->emptying == &s->buf[Nbuf])
+ s->emptying = s->buf;
+ }
+ /* wait if dma in progress */
+ while (!dmaidle(s->dma) && s->emptying == s->current) {
+ if (debug > 1) print("#A: sleep\n");
+ sleep(&s->vous, audioqnotempty, s);
+ }
+
+ m = (s->emptying->nbytes > n)? n: s->emptying->nbytes;
+ memmove(p, s->emptying->virt + volumes[Vbufsize].ilval -
+ s->emptying->nbytes, m);
+
+ s->emptying->nbytes -= m;
+ n -= m;
+ p += m;
+ }
+ poperror();
+ qunlock(s);
+ break;
+
+ case Qstatus:
+ buf[0] = 0;
+ snprint(buf, sizeof(buf), "bytes %lud\ntime %lld\n",
+ audio.totcount, audio.tottime);
+ return readstr(offset, p, n, buf);
+
+ case Qstats:
+ buf[0] = 0;
+ snprint(buf, sizeof(buf),
+ "bytes %lud\nRX dmas %lud, while idle %lud, while busy %lud, "
+ "out-of-order %lud, empty dmas %lud\n"
+ "TX dmas %lud, while idle %lud, while busy %lud, "
+ "out-of-order %lud, empty dmas %lud\n",
+ iostats.bytes, iostats.rx.totaldma, iostats.rx.idledma,
+ iostats.rx.faildma, iostats.rx.samedma, iostats.rx.empties,
+ iostats.tx.totaldma, iostats.tx.idledma,
+ iostats.tx.faildma, iostats.tx.samedma, iostats.tx.empties);
+
+ return readstr(offset, p, n, buf);
+
+ case Qvolume:
+ j = 0;
+ buf[0] = 0;
+ for(m=0; volumes[m].name; m++){
+ if (m == Vaudio) {
+ liv = audio.livol[m];
+ riv = audio.rivol[m];
+ lov = audio.lovol[m];
+ rov = audio.rovol[m];
+ }
+ else {
+ lov = liv = volumes[m].ilval;
+ rov = riv = volumes[m].irval;
+ }
+
+ j += snprint(buf+j, sizeof(buf)-j, "%s", volumes[m].name);
+ if((volumes[m].flag & Fmono) || liv==riv && lov==rov){
+ if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov)
+ j += snprint(buf+j, sizeof(buf)-j, " %d", liv);
+ else{
+ if(volumes[m].flag & Fin)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " in %d", liv);
+ if(volumes[m].flag & Fout)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " out %d", lov);
+ }
+ }else{
+ if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) &&
+ liv==lov && riv==rov)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " left %d right %d",
+ liv, riv);
+ else{
+ if(volumes[m].flag & Fin)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " in left %d right %d",
+ liv, riv);
+ if(volumes[m].flag & Fout)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " out left %d right %d",
+ lov, rov);
+ }
+ }
+ j += snprint(buf+j, sizeof(buf)-j, "\n");
+ }
+ return readstr(offset, p, n, buf);
+ }
+ return n0-n;
+}
+
+static void
+setaudio(int in, int out, int left, int right, int value)
+{
+ if (value < 0 || value > 100)
+ error(Evolume);
+ if(left && out)
+ audio.lovol[Vaudio] = value;
+ if(left && in)
+ audio.livol[Vaudio] = value;
+ if(right && out)
+ audio.rovol[Vaudio] = value;
+ if(right && in)
+ audio.rivol[Vaudio] = value;
+}
+
+static void
+setspeed(int, int, int, int, int speed)
+{
+ uchar clock;
+
+ /* external clock configured for 44100 samples/sec */
+ switch (speed) {
+ case 32000:
+ /* 00 */
+ gpioregs->clear = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o;
+ clock = SC384FS; /* Only works in MSB mode! */
+ break;
+ case 48000:
+ /* 00 */
+ gpioregs->clear = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o;
+ clock = SC256FS;
+ break;
+ default:
+ speed = 44100;
+ case 44100:
+ /* 01 */
+ gpioregs->set = GPIO_CLK_SET0_o;
+ gpioregs->clear = GPIO_CLK_SET1_o;
+ clock = SC256FS;
+ break;
+ case 8000:
+ /* 10 */
+ gpioregs->set = GPIO_CLK_SET1_o;
+ gpioregs->clear = GPIO_CLK_SET0_o;
+ clock = SC512FS; /* Only works in MSB mode! */
+ break;
+ case 16000:
+ /* 10 */
+ gpioregs->set = GPIO_CLK_SET1_o;
+ gpioregs->clear = GPIO_CLK_SET0_o;
+ clock = SC256FS;
+ break;
+ case 11025:
+ /* 11 */
+ gpioregs->set = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o;
+ clock = SC512FS; /* Only works in MSB mode! */
+ break;
+ case 22050:
+ /* 11 */
+ gpioregs->set = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o;
+ clock = SC256FS;
+ break;
+ }
+
+ /* Wait for the UDA1341 to wake up */
+ delay(100);
+
+ /* Reset the chip */
+ status0[0] &= ~CLOCKMASK;
+
+ status0[0] |=clock;
+ volumes[Vspeed].ilval = speed;
+}
+
+static void
+setbufsize(int, int, int, int, int value)
+{
+ if ((value % 8) != 0 || value < 8 || value >= Bufsize)
+ error(Ebadarg);
+ volumes[Vbufsize].ilval = value;
+}
+
+static long
+audiowrite(Chan *c, void *vp, long n, vlong)
+{
+ long m, n0;
+ int i, v, left, right, in, out;
+ char *p;
+ IOstate *a;
+ Cmdbuf *cb;
+
+ p = vp;
+ n0 = n;
+ switch((ulong)c->qid.path) {
+ default:
+ error(Eperm);
+ break;
+
+ case Qvolume:
+ v = Vaudio;
+ left = 1;
+ right = 1;
+ in = 1;
+ out = 1;
+ cb = parsecmd(p, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+
+ for(i = 0; i < cb->nf; i++){
+ /*
+ * a number is volume
+ */
+ if(cb->f[i][0] >= '0' && cb->f[i][0] <= '9') {
+ m = strtoul(cb->f[i], 0, 10);
+ if (volumes[v].setval)
+ volumes[v].setval(in, out, left, right, m);
+ goto cont0;
+ }
+
+ for(m=0; volumes[m].name; m++) {
+ if(strcmp(cb->f[i], volumes[m].name) == 0) {
+ v = m;
+ in = 1;
+ out = 1;
+ left = 1;
+ right = 1;
+ goto cont0;
+ }
+ }
+
+ if(strcmp(cb->f[i], "reset") == 0) {
+ resetlevel();
+ goto cont0;
+ }
+ if(strcmp(cb->f[i], "debug") == 0) {
+ debug = debug?0:1;
+ goto cont0;
+ }
+ if(strcmp(cb->f[i], "in") == 0) {
+ in = 1;
+ out = 0;
+ goto cont0;
+ }
+ if(strcmp(cb->f[i], "out") == 0) {
+ in = 0;
+ out = 1;
+ goto cont0;
+ }
+ if(strcmp(cb->f[i], "left") == 0) {
+ left = 1;
+ right = 0;
+ goto cont0;
+ }
+ if(strcmp(cb->f[i], "right") == 0) {
+ left = 0;
+ right = 1;
+ goto cont0;
+ }
+ if(strcmp(cb->f[i], "reg") == 0) {
+ if(cb->nf < 3)
+ error(Evolume);
+ setreg(cb->f[1], atoi(cb->f[2]), cb->nf == 4 ? atoi(cb->f[3]):1);
+ return n0;
+ }
+ error(Evolume);
+ break;
+ cont0:;
+ }
+ mxvolume();
+ poperror();
+ free(cb);
+ break;
+
+ case Qaudio:
+ if (debug > 1) print("#A: write %ld\n", n);
+ if((audio.amode & Awrite) == 0)
+ error(Emode);
+ a = &audio.o;
+ qlock(a);
+ if(waserror()){
+ qunlock(a);
+ nexterror();
+ }
+ while(n > 0) {
+ /* wait if dma in progress */
+ while (!dmaidle(a->dma) && !zerodma && a->filling == a->current) {
+ if (debug > 1) print("#A: sleep\n");
+ sleep(&a->vous, audioqnotfull, a);
+ }
+ m = volumes[Vbufsize].ilval - a->filling->nbytes;
+ if(m > n)
+ m = n;
+ memmove(a->filling->virt + a->filling->nbytes, p, m);
+
+ a->filling->nbytes += m;
+ n -= m;
+ p += m;
+ if(a->filling->nbytes >= volumes[Vbufsize].ilval) {
+ if (debug > 1) print("#A: filled @%p\n", a->filling);
+ a->filling++;
+ if (a->filling == &a->buf[Nbuf])
+ a->filling = a->buf;
+ sendaudio(a);
+ }
+ }
+ poperror();
+ qunlock(a);
+ break;
+ }
+ return n0 - n;
+}
+
+Dev uda1341devtab = {
+ 'A',
+ "audio",
+
+ devreset,
+ audioinit,
+ devshutdown,
+ audioattach,
+ audiowalk,
+ audiostat,
+ audioopen,
+ devcreate,
+ audioclose,
+ audioread,
+ devbread,
+ audiowrite,
+ devbwrite,
+ devremove,
+ devwstat,
+ audiopower,
+};
diff --git a/sys/src/9/bitsy/devµc.c b/sys/src/9/bitsy/devµc.c
new file mode 100755
index 000000000..f3b627018
--- /dev/null
+++ b/sys/src/9/bitsy/devµc.c
@@ -0,0 +1,452 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+enum{
+ Qdir,
+ Qbacklight,
+ Qbattery,
+ Qbuttons,
+ Qcruft,
+ Qkbdin,
+ Qled,
+ Qversion,
+ Qpower,
+
+ /* command types */
+ BLversion= 0,
+ BLbuttons= 2, /* button events */
+ BLtouch= 3, /* read touch screen events */
+ BLled= 8, /* turn LED on/off */
+ BLbattery= 9, /* read battery status */
+ BLbacklight= 0xd, /* backlight control */
+
+ SOF= 0x2, /* start of frame */
+};
+
+/* from /sys/include/keyboard.h */
+enum {
+ KF= 0xF000, /* Rune: beginning of private Unicode space */
+ /* KF|1, KF|2, ..., KF|0xC is F1, F2, ..., F12 */
+ Khome= KF|0x0D,
+ Kup= KF|0x0E,
+ Kpgup= KF|0x0F,
+ Kprint= KF|0x10,
+ Kleft= KF|0x11,
+ Kright= KF|0x12,
+ Kdown= 0x80,
+ Kview= 0x80,
+ Kpgdown= KF|0x13,
+ Kins= KF|0x14,
+ Kend= '\r', /* [sic] */
+
+ Kalt= KF|0x15,
+ Kshift= KF|0x16,
+ Kctl= KF|0x17,
+};
+
+Dirtab µcdir[]={
+ ".", { Qdir, 0, QTDIR }, 0, DMDIR|0755,
+ "backlight", { Qbacklight, 0 }, 0, 0664,
+ "battery", { Qbattery, 0 }, 0, 0664,
+ "buttons", { Qbuttons, 0 }, 0, 0664,
+ "cruft", { Qcruft, 0 }, 0, 0664,
+ "kbdin", { Qkbdin, 0 }, 0, 0664,
+ "led", { Qled, 0 }, 0, 0664,
+ "version", { Qversion, 0 }, 0, 0664,
+ "power", { Qpower, 0 }, 0, 0600,
+};
+
+static struct µcontroller
+{
+ /* message being rcvd */
+ int state;
+ uchar buf[16+4];
+ uchar n;
+
+ /* for messages that require acks */
+ QLock;
+ Rendez r;
+
+ /* battery */
+ uchar acstatus;
+ uchar voltage;
+ ushort batstatus;
+ uchar batchem;
+
+ /* version string */
+ char version[16+2];
+} ctlr;
+
+/* button map */
+Rune bmap[2][4] =
+{
+ {Kup, Kright, Kleft, Kdown}, /* portrait mode */
+ {Kright, Kdown, Kup, Kleft}, /* landscape mode */
+};
+
+extern int landscape;
+
+int
+µcputc(Queue*, int ch)
+{
+ int i, len, b, up;
+ uchar cksum;
+ uchar *p;
+ static int samseq;
+ static int touching; /* guard against something we call going spllo() */
+ static int buttoning; /* guard against something we call going spllo() */
+
+ if(ctlr.n > sizeof(ctlr.buf))
+ panic("µcputc");
+
+ ctlr.buf[ctlr.n++] = (uchar)ch;
+
+ for(;;){
+ /* message hasn't started yet? */
+ if(ctlr.buf[0] != SOF){
+ p = memchr(ctlr.buf, SOF, ctlr.n);
+ if(p == nil){
+ ctlr.n = 0;
+ break;
+ } else {
+ ctlr.n -= p-ctlr.buf;
+ memmove(ctlr.buf, p, ctlr.n);
+ }
+ }
+
+ /* whole msg? */
+ len = ctlr.buf[1] & 0xf;
+ if(ctlr.n < 3 || ctlr.n < len+3)
+ break;
+
+ /* check the sum */
+ ctlr.buf[0] = ~SOF; /* make sure we process this msg exactly once */
+ cksum = 0;
+ for(i = 1; i < len+2; i++)
+ cksum += ctlr.buf[i];
+ if(ctlr.buf[len+2] != cksum)
+ continue;
+
+ /* parse resulting message */
+ p = ctlr.buf+2;
+ switch(ctlr.buf[1] >> 4){
+ case BLversion:
+ strncpy(ctlr.version, (char*)p, len);
+ ctlr.version[len] = '0';
+ strcat(ctlr.version, "\n");
+ wakeup(&ctlr.r);
+ break;
+ case BLbuttons:
+ if(len < 1 || buttoning)
+ break;
+ buttoning = 1;
+ b = p[0] & 0x7f;
+ up = p[0] & 0x80;
+
+ if(b > 5) {
+ /* rocker panel acts like arrow keys */
+ if(b < 10 && !up)
+ kbdputc(kbdq, bmap[landscape][b-6]);
+ } else {
+ /* the rest like mouse buttons */
+ if(--b == 0)
+ b = 5;
+ penbutton(up, 1<<b);
+ }
+ buttoning = 0;
+ break;
+ case BLtouch:
+ if(touching)
+ break;
+ touching = 1;
+ if(len == 4) {
+ if (samseq++ > 10){
+ if (landscape)
+ pentrackxy((p[0]<<8)|p[1], (p[2]<<8)|p[3]);
+ else
+ pentrackxy((p[2]<<8)|p[3], (p[0]<<8)|p[1]);
+ }
+ } else {
+ samseq = 0;
+ pentrackxy(-1, -1);
+ }
+ touching = 0;
+ break;
+ case BLled:
+ wakeup(&ctlr.r);
+ break;
+ case BLbattery:
+ if(len >= 5){
+ ctlr.acstatus = p[0];
+ ctlr.voltage = (p[3]<<8)|p[2];
+ ctlr.batstatus = p[4];
+ ctlr.batchem = p[1];
+ }
+ wakeup(&ctlr.r);
+ break;
+ case BLbacklight:
+ wakeup(&ctlr.r);
+ break;
+ default:
+ print("unknown µc message: %ux", ctlr.buf[1] >> 4);
+ for(i = 0; i < len; i++)
+ print(" %ux", p[i]);
+ print("\n");
+ break;
+ }
+
+ /* remove the message */
+ ctlr.n -= len+3;
+ memmove(ctlr.buf, &ctlr.buf[len+3], ctlr.n);
+ }
+ return 0;
+}
+
+static void
+_sendmsg(uchar id, uchar *data, int len)
+{
+ uchar buf[20];
+ uchar cksum;
+ uchar c;
+ uchar *p = buf;
+ int i;
+
+ /* create the message */
+ if(sizeof(buf) < len+4)
+ return;
+ cksum = (id<<4) | len;
+ *p++ = SOF;
+ *p++ = cksum;
+ for(i = 0; i < len; i++){
+ c = data[i];
+ cksum += c;
+ *p++ = c;
+ }
+ *p++ = cksum;
+
+ /* send the message - there should be a more generic way to do this */
+ serialµcputs(buf, p-buf);
+}
+
+/* the tsleep takes care of lost acks */
+static void
+sendmsgwithack(uchar id, uchar *data, int len)
+{
+ if(waserror()){
+ qunlock(&ctlr);
+ nexterror();
+ }
+ qlock(&ctlr);
+ _sendmsg(id, data, len);
+ tsleep(&ctlr.r, return0, 0, 100);
+ qunlock(&ctlr);
+ poperror();
+}
+
+static void
+sendmsg(uchar id, uchar *data, int len)
+{
+ if(waserror()){
+ qunlock(&ctlr);
+ nexterror();
+ }
+ qlock(&ctlr);
+ _sendmsg(id, data, len);
+ qunlock(&ctlr);
+ poperror();
+}
+
+void
+µcinit(void)
+{
+}
+
+static Chan*
+µcattach(char* spec)
+{
+ return devattach('r', spec);
+}
+
+static Walkqid*
+µcwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, µcdir, nelem(µcdir), devgen);
+}
+
+static int
+µcstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, µcdir, nelem(µcdir), devgen);
+}
+
+static Chan*
+µcopen(Chan* c, int omode)
+{
+ omode = openmode(omode);
+ if(!iseve())
+ error(Eperm);
+ return devopen(c, omode, µcdir, nelem(µcdir), devgen);
+}
+
+static void
+µcclose(Chan*)
+{
+}
+
+char*
+acstatus(int x)
+{
+ if(x)
+ return "attached";
+ else
+ return "detached";
+}
+
+char*
+batstatus(int x)
+{
+ switch(x){
+ case 1: return "high";
+ case 2: return "low";
+ case 4: return "critical";
+ case 8: return "charging";
+ case 0x80: return "none";
+ }
+ return "ok";
+}
+
+static long
+µcread(Chan* c, void* a, long n, vlong off)
+{
+ char buf[64];
+
+ if(c->qid.path == Qdir)
+ return devdirread(c, a, n, µcdir, nelem(µcdir), devgen);
+
+ switch((ulong)c->qid.path){
+ case Qbattery:
+ sendmsgwithack(BLbattery, nil, 0); /* send a battery request */
+ sprint(buf, "voltage: %d\nac: %s\nstatus: %s\n", ctlr.voltage,
+ acstatus(ctlr.acstatus),
+ batstatus(ctlr.batstatus));
+ return readstr(off, a, n, buf);
+ case Qversion:
+ sendmsgwithack(BLversion, nil, 0); /* send a battery request */
+ return readstr(off, a, n, ctlr.version);
+ }
+ error(Ebadarg);
+ return 0;
+}
+
+#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4)
+
+static uchar lightdata[16];
+
+static long
+µcwrite(Chan* c, void* a, long n, vlong)
+{
+ Cmdbuf *cmd;
+ uchar data[16];
+ char str[64];
+ int i, j;
+ ulong l;
+ Rune r;
+ extern ulong resumeaddr[];
+ extern void power_resume(void);
+
+ if(c->qid.path == Qkbdin){
+ if(n >= sizeof(str))
+ n = sizeof(str)-1;
+ memmove(str, a, n);
+ str[n] = 0;
+ for(i = 0; i < n; i += j){
+ j = chartorune(&r, &str[i]);
+ kbdcr2nl(nil, r);
+ }
+ return n;
+ }
+ if(c->qid.path == Qpower){
+ if(!iseve())
+ error(Eperm);
+ if(strncmp(a, "suspend", 7) == 0)
+ *resumeaddr = (ulong)power_resume;
+ else if(strncmp(a, "halt", 4) == 0)
+ *resumeaddr = 0;
+ else if(strncmp(a, "wakeup", 6) == 0){
+ cmd = parsecmd(a, n);
+ if (cmd->nf != 2)
+ error(Ebadarg);
+ l = strtoul(cmd->f[1], 0, 0);
+ rtcalarm(l);
+ return n;
+ } else
+ error(Ebadarg);
+ deepsleep();
+ return n;
+ }
+
+ cmd = parsecmd(a, n);
+ if(cmd->nf > 15)
+ error(Ebadarg);
+ for(i = 0; i < cmd->nf; i++)
+ data[i] = atoi(cmd->f[i]);
+
+ switch((ulong)c->qid.path){
+ case Qled:
+ sendmsgwithack(BLled, data, cmd->nf);
+ break;
+ case Qbacklight:
+ memmove(lightdata, data, 16);
+ sendmsgwithack(BLbacklight, data, cmd->nf);
+ break;
+ case Qcruft:
+// lcdtweak(cmd);
+ break;
+ default:
+ error(Ebadarg);
+ }
+ return n;
+}
+
+void
+µcpower(int on)
+{
+ uchar data[16];
+ if (on == 0)
+ return;
+ /* maybe dangerous, not holding the lock */
+ if (lightdata[0] == 0){
+ data[0]= 2;
+ data[1]= 1;
+ data[2]= 0;
+ } else
+ memmove(data, lightdata, 16);
+ _sendmsg(0xd, data, 3);
+ wakeup(&ctlr.r);
+}
+
+Dev µcdevtab = {
+ 'r',
+ "µc",
+
+ devreset,
+ µcinit,
+ devshutdown,
+ µcattach,
+ µcwalk,
+ µcstat,
+ µcopen,
+ devcreate,
+ µcclose,
+ µcread,
+ devbread,
+ µcwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/bitsy/etherif.h b/sys/src/9/bitsy/etherif.h
new file mode 100755
index 000000000..f51294ffb
--- /dev/null
+++ b/sys/src/9/bitsy/etherif.h
@@ -0,0 +1,39 @@
+enum {
+ MaxEther = 24,
+ Ntypes = 8,
+};
+
+typedef struct Ether Ether;
+struct Ether {
+ DevConf;
+
+ int ctlrno;
+ int tbdf; /* type+busno+devno+funcno */
+ int minmtu;
+ int maxmtu;
+ uchar ea[Eaddrlen];
+ int encry;
+
+ void (*attach)(Ether*); /* filled in by reset routine */
+ void (*detach)(Ether*);
+ void (*transmit)(Ether*);
+ void (*interrupt)(Ureg*, void*);
+ long (*ifstat)(Ether*, void*, long, ulong);
+ long (*ctl)(Ether*, void*, long); /* custom ctl messages */
+ void (*power)(Ether*, int); /* power on/off */
+ void (*shutdown)(Ether*); /* shutdown hardware before reboot */
+ void *ctlr;
+
+ Queue* oq;
+
+ Netif;
+};
+
+extern Block* etheriq(Ether*, Block*, int);
+extern void addethercard(char*, int(*)(Ether*));
+extern ulong ethercrc(uchar*, int);
+
+#define NEXT(x, l) (((x)+1)%(l))
+#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
diff --git a/sys/src/9/bitsy/etherwavelan.c b/sys/src/9/bitsy/etherwavelan.c
new file mode 100755
index 000000000..bc45ad066
--- /dev/null
+++ b/sys/src/9/bitsy/etherwavelan.c
@@ -0,0 +1,49 @@
+/* Bitsy pcmcia code for wavelan.c */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+#include "etherif.h"
+#include "../pc/wavelan.h"
+
+static int
+wavelanpcmciareset(Ether *ether)
+{
+ Ctlr *ctlr;
+
+ if((ctlr = malloc(sizeof(Ctlr))) == nil)
+ return -1;
+
+ ilock(ctlr);
+ ctlr->ctlrno = ether->ctlrno;
+
+ if (ether->ports == nil){
+ ether->ports = malloc(sizeof(Devport));
+ ether->ports[0].port = 0;
+ ether->ports[0].size = 0;
+ ether->nports= 1;
+ }
+ if (ether->ports[0].port==0)
+ ether->ports[0].port=WDfltIOB;
+ ctlr->iob = ether->ports[0].port;
+
+ if(wavelanreset(ether, ctlr) < 0){
+ iunlock(ctlr);
+ free(ctlr);
+ ether->ctlr = nil;
+ return -1;
+ }
+ iunlock(ctlr);
+ return 0;
+}
+
+void
+etherwavelanlink(void)
+{
+ addethercard("wavelan", wavelanpcmciareset);
+}
diff --git a/sys/src/9/bitsy/fns.h b/sys/src/9/bitsy/fns.h
new file mode 100755
index 000000000..08aff860a
--- /dev/null
+++ b/sys/src/9/bitsy/fns.h
@@ -0,0 +1,120 @@
+#include "../port/portfns.h"
+
+void audiopower(int);
+void audioamppower(int);
+void audioicpower(int);
+void cacheflush(void);
+void cachewb(void);
+void cachewbaddr(void*);
+void cachewbregion(ulong, int);
+ulong cankaddr(ulong);
+void dcacheinvalidate(void);
+int cistrcmp(char*, char*);
+int cistrncmp(char*, char*, int);
+void clockinit(void);
+ulong clockpower(int);
+int cmpswap(long*, long, long);
+#define coherence()
+#define cycles(x) do{}while(0)
+#define dcflush(a, b)
+void delay(int);
+void µcpower(int);
+void deepsleep(void);
+void dmainit(void);
+void doze(void);
+void egpiobits(ulong, int);
+void evenaddr(ulong);
+ulong findva(ulong, ulong, ulong);
+void flashprogpower(int);
+void flushmmu(void);
+int fpiarm(Ureg *ur);
+char* getconf(char*);
+ulong getcpuid(void);
+ulong getfar(void);
+ulong getfsr(void);
+ulong getcontrol(void);
+ulong getdac(void);
+ulong getttb(void);
+void* getlink(void);
+#define getpgcolor(a) 0
+ulong getsp(void);
+void icacheinvalidate(void);
+void idle(void);
+void idlehands(void);
+uchar inb(ulong);
+ushort ins(ulong);
+void inss(ulong, void*, int);
+ulong inl(ulong);
+void intrdisable(int, int, void (*)(Ureg*, void*), void*, char*);
+void intrenable(int, int, void (*)(Ureg*, void*), void*, char*);
+void irpower(int);
+#define kexit(a)
+#define kmapinval()
+void lcdpower(int);
+void links(void);
+void* mapmem(ulong, int, int);
+void mappedIvecEnable(void);
+void mappedIvecDisable(void);
+void* mapspecial(ulong, int);
+void meminit(void);
+void mmuinit(void);
+void mmuenable(void);
+void mmudisable(void);
+void mmuinvalidate(void);
+void mmuinvalidateaddr(ulong);
+void mmurestart(void);
+ulong mmu_kaddr(ulong);
+ulong mmu_paddr(ulong);
+int µcputc(Queue*, int);
+void noted(Ureg*, ulong);
+int notify(Ureg*);
+void outb(ulong, uchar);
+void outs(ulong, ushort);
+void outss(ulong, void*, int);
+void outl(ulong, ulong);
+void pcmciapower(int);
+void pcmcisread(PCMslot*);
+int pcmcistuple(int, int, int, void*, int);
+PCMmap* pcmmap(int, ulong, int, int);
+void pcmunmap(int, PCMmap*);
+void penbutton(int, int);
+void pentrackxy(int x, int y);
+void power_down(void);
+void powerinit(void);
+void powerkproc(void*);
+#define procrestore(p)
+void procsave(Proc*);
+void procsetup(Proc*);
+void putdac(ulong);
+void putttb(ulong);
+void putpid(ulong);
+void resetsuspendtimer(void);
+void rs232power(int);
+void rtcalarm(ulong);
+void sa1110_uartsetup(int);
+void screeninit(void);
+void screenpower(int);
+void serialµcputs(uchar *str, int n);
+void setr13(int, ulong*);
+uchar* tarlookup(uchar*, char*, int*);
+void timersinit(void);
+void timeradd(Timer*);
+void timerdel(Timer*);
+void timerset(Tval);
+void touser(void*);
+void trapdump(char *tag);
+void trapinit(void);
+void trapresume(void);
+int tas(void*);
+void uartpower(int);
+int uartstageoutput(Uart*);
+void uartkick(void*);
+void uartrecv(Uart*, char);
+#define userureg(ur) (((ur)->psr & PsrMask) == PsrMusr)
+void vectors(void);
+void vtable(void);
+void wbflush(void);
+#define KADDR(a) (void*)mmu_kaddr((ulong)(a))
+#define PADDR(a) mmu_paddr((ulong)(a))
+
+#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
diff --git a/sys/src/9/bitsy/fpi.c b/sys/src/9/bitsy/fpi.c
new file mode 100755
index 000000000..f341f2e4a
--- /dev/null
+++ b/sys/src/9/bitsy/fpi.c
@@ -0,0 +1,300 @@
+/*
+ * Floating Point Interpreter.
+ * shamelessly stolen from an original by ark.
+ */
+#include "fpi.h"
+
+void
+fpiround(Internal *i)
+{
+ unsigned long guard;
+
+ guard = i->l & GuardMask;
+ i->l &= ~GuardMask;
+ if(guard > (LsBit>>1) || (guard == (LsBit>>1) && (i->l & LsBit))){
+ i->l += LsBit;
+ if(i->l & CarryBit){
+ i->l &= ~CarryBit;
+ i->h++;
+ if(i->h & CarryBit){
+ if (i->h & 0x01)
+ i->l |= CarryBit;
+ i->l >>= 1;
+ i->h >>= 1;
+ i->e++;
+ }
+ }
+ }
+}
+
+static void
+matchexponents(Internal *x, Internal *y)
+{
+ int count;
+
+ count = y->e - x->e;
+ x->e = y->e;
+ if(count >= 2*FractBits){
+ x->l = x->l || x->h;
+ x->h = 0;
+ return;
+ }
+ if(count >= FractBits){
+ count -= FractBits;
+ x->l = x->h|(x->l != 0);
+ x->h = 0;
+ }
+ while(count > 0){
+ count--;
+ if(x->h & 0x01)
+ x->l |= CarryBit;
+ if(x->l & 0x01)
+ x->l |= 2;
+ x->l >>= 1;
+ x->h >>= 1;
+ }
+}
+
+static void
+shift(Internal *i)
+{
+ i->e--;
+ i->h <<= 1;
+ i->l <<= 1;
+ if(i->l & CarryBit){
+ i->l &= ~CarryBit;
+ i->h |= 0x01;
+ }
+}
+
+static void
+normalise(Internal *i)
+{
+ while((i->h & HiddenBit) == 0)
+ shift(i);
+}
+
+static void
+renormalise(Internal *i)
+{
+ if(i->e < -2 * FractBits)
+ i->e = -2 * FractBits;
+ while(i->e < 1){
+ i->e++;
+ if(i->h & 0x01)
+ i->l |= CarryBit;
+ i->h >>= 1;
+ i->l = (i->l>>1)|(i->l & 0x01);
+ }
+ if(i->e >= ExpInfinity)
+ SetInfinity(i);
+}
+
+void
+fpinormalise(Internal *x)
+{
+ if(!IsWeird(x) && !IsZero(x))
+ normalise(x);
+}
+
+void
+fpiadd(Internal *x, Internal *y, Internal *i)
+{
+ Internal *t;
+
+ i->s = x->s;
+ if(IsWeird(x) || IsWeird(y)){
+ if(IsNaN(x) || IsNaN(y))
+ SetQNaN(i);
+ else
+ SetInfinity(i);
+ return;
+ }
+ if(x->e > y->e){
+ t = x;
+ x = y;
+ y = t;
+ }
+ matchexponents(x, y);
+ i->e = x->e;
+ i->h = x->h + y->h;
+ i->l = x->l + y->l;
+ if(i->l & CarryBit){
+ i->h++;
+ i->l &= ~CarryBit;
+ }
+ if(i->h & (HiddenBit<<1)){
+ if(i->h & 0x01)
+ i->l |= CarryBit;
+ i->l = (i->l>>1)|(i->l & 0x01);
+ i->h >>= 1;
+ i->e++;
+ }
+ if(IsWeird(i))
+ SetInfinity(i);
+}
+
+void
+fpisub(Internal *x, Internal *y, Internal *i)
+{
+ Internal *t;
+
+ if(y->e < x->e
+ || (y->e == x->e && (y->h < x->h || (y->h == x->h && y->l < x->l)))){
+ t = x;
+ x = y;
+ y = t;
+ }
+ i->s = y->s;
+ if(IsNaN(y)){
+ SetQNaN(i);
+ return;
+ }
+ if(IsInfinity(y)){
+ if(IsInfinity(x))
+ SetQNaN(i);
+ else
+ SetInfinity(i);
+ return;
+ }
+ matchexponents(x, y);
+ i->e = y->e;
+ i->h = y->h - x->h;
+ i->l = y->l - x->l;
+ if(i->l < 0){
+ i->l += CarryBit;
+ i->h--;
+ }
+ if(i->h == 0 && i->l == 0)
+ SetZero(i);
+ else while(i->e > 1 && (i->h & HiddenBit) == 0)
+ shift(i);
+}
+
+#define CHUNK (FractBits/2)
+#define CMASK ((1<<CHUNK)-1)
+#define HI(x) ((short)((x)>>CHUNK) & CMASK)
+#define LO(x) ((short)(x) & CMASK)
+#define SPILL(x) ((x)>>CHUNK)
+#define M(x, y) ((long)a[x]*(long)b[y])
+#define C(h, l) (((long)((h) & CMASK)<<CHUNK)|((l) & CMASK))
+
+void
+fpimul(Internal *x, Internal *y, Internal *i)
+{
+ long a[4], b[4], c[7], f[4];
+
+ i->s = x->s^y->s;
+ if(IsWeird(x) || IsWeird(y)){
+ if(IsNaN(x) || IsNaN(y) || IsZero(x) || IsZero(y))
+ SetQNaN(i);
+ else
+ SetInfinity(i);
+ return;
+ }
+ else if(IsZero(x) || IsZero(y)){
+ SetZero(i);
+ return;
+ }
+ normalise(x);
+ normalise(y);
+ i->e = x->e + y->e - (ExpBias - 1);
+
+ a[0] = HI(x->h); b[0] = HI(y->h);
+ a[1] = LO(x->h); b[1] = LO(y->h);
+ a[2] = HI(x->l); b[2] = HI(y->l);
+ a[3] = LO(x->l); b[3] = LO(y->l);
+
+ c[6] = M(3, 3);
+ c[5] = M(2, 3) + M(3, 2) + SPILL(c[6]);
+ c[4] = M(1, 3) + M(2, 2) + M(3, 1) + SPILL(c[5]);
+ c[3] = M(0, 3) + M(1, 2) + M(2, 1) + M(3, 0) + SPILL(c[4]);
+ c[2] = M(0, 2) + M(1, 1) + M(2, 0) + SPILL(c[3]);
+ c[1] = M(0, 1) + M(1, 0) + SPILL(c[2]);
+ c[0] = M(0, 0) + SPILL(c[1]);
+
+ f[0] = c[0];
+ f[1] = C(c[1], c[2]);
+ f[2] = C(c[3], c[4]);
+ f[3] = C(c[5], c[6]);
+
+ if((f[0] & HiddenBit) == 0){
+ f[0] <<= 1;
+ f[1] <<= 1;
+ f[2] <<= 1;
+ f[3] <<= 1;
+ if(f[1] & CarryBit){
+ f[0] |= 1;
+ f[1] &= ~CarryBit;
+ }
+ if(f[2] & CarryBit){
+ f[1] |= 1;
+ f[2] &= ~CarryBit;
+ }
+ if(f[3] & CarryBit){
+ f[2] |= 1;
+ f[3] &= ~CarryBit;
+ }
+ i->e--;
+ }
+ i->h = f[0];
+ i->l = f[1];
+ if(f[2] || f[3])
+ i->l |= 1;
+ renormalise(i);
+}
+
+void
+fpidiv(Internal *x, Internal *y, Internal *i)
+{
+ i->s = x->s^y->s;
+ if(IsNaN(x) || IsNaN(y)
+ || (IsInfinity(x) && IsInfinity(y)) || (IsZero(x) && IsZero(y))){
+ SetQNaN(i);
+ return;
+ }
+ else if(IsZero(x) || IsInfinity(y)){
+ SetInfinity(i);
+ return;
+ }
+ else if(IsInfinity(x) || IsZero(y)){
+ SetZero(i);
+ return;
+ }
+ normalise(x);
+ normalise(y);
+ i->h = 0;
+ i->l = 0;
+ i->e = y->e - x->e + (ExpBias + 2*FractBits - 1);
+ do{
+ if(y->h > x->h || (y->h == x->h && y->l >= x->l)){
+ i->l |= 0x01;
+ y->h -= x->h;
+ y->l -= x->l;
+ if(y->l < 0){
+ y->l += CarryBit;
+ y->h--;
+ }
+ }
+ shift(y);
+ shift(i);
+ }while ((i->h & HiddenBit) == 0);
+ if(y->h || y->l)
+ i->l |= 0x01;
+ renormalise(i);
+}
+
+int
+fpicmp(Internal *x, Internal *y)
+{
+ if(IsNaN(x) && IsNaN(y))
+ return 0;
+ if(IsInfinity(x) && IsInfinity(y))
+ return y->s - x->s;
+ if(x->e == y->e && x->h == y->h && x->l == y->l)
+ return y->s - x->s;
+ if(x->e < y->e
+ || (x->e == y->e && (x->h < y->h || (x->h == y->h && x->l < y->l))))
+ return y->s ? 1: -1;
+ return x->s ? -1: 1;
+}
diff --git a/sys/src/9/bitsy/fpi.h b/sys/src/9/bitsy/fpi.h
new file mode 100755
index 000000000..abaa7c120
--- /dev/null
+++ b/sys/src/9/bitsy/fpi.h
@@ -0,0 +1,61 @@
+typedef long Word;
+typedef unsigned long Single;
+typedef struct {
+ unsigned long l;
+ unsigned long h;
+} Double;
+
+enum {
+ FractBits = 28,
+ CarryBit = 0x10000000,
+ HiddenBit = 0x08000000,
+ MsBit = HiddenBit,
+ NGuardBits = 3,
+ GuardMask = 0x07,
+ LsBit = (1<<NGuardBits),
+
+ SingleExpBias = 127,
+ SingleExpMax = 255,
+ DoubleExpBias = 1023,
+ DoubleExpMax = 2047,
+
+ ExpBias = DoubleExpBias,
+ ExpInfinity = DoubleExpMax,
+};
+
+typedef struct {
+ unsigned char s;
+ short e;
+ long l; /* 0000FFFFFFFFFFFFFFFFFFFFFFFFFGGG */
+ long h; /* 0000HFFFFFFFFFFFFFFFFFFFFFFFFFFF */
+} Internal;
+
+#define IsWeird(n) ((n)->e >= ExpInfinity)
+#define IsInfinity(n) (IsWeird(n) && (n)->h == HiddenBit && (n)->l == 0)
+#define SetInfinity(n) ((n)->e = ExpInfinity, (n)->h = HiddenBit, (n)->l = 0)
+#define IsNaN(n) (IsWeird(n) && (((n)->h & ~HiddenBit) || (n)->l))
+#define SetQNaN(n) ((n)->s = 0, (n)->e = ExpInfinity, \
+ (n)->h = HiddenBit|(LsBit<<1), (n)->l = 0)
+#define IsZero(n) ((n)->e == 1 && (n)->h == 0 && (n)->l == 0)
+#define SetZero(n) ((n)->e = 1, (n)->h = 0, (n)->l = 0)
+
+/*
+ * fpi.c
+ */
+extern void fpiround(Internal *);
+extern void fpiadd(Internal *, Internal *, Internal *);
+extern void fpisub(Internal *, Internal *, Internal *);
+extern void fpimul(Internal *, Internal *, Internal *);
+extern void fpidiv(Internal *, Internal *, Internal *);
+extern int fpicmp(Internal *, Internal *);
+extern void fpinormalise(Internal*);
+
+/*
+ * fpimem.c
+ */
+extern void fpis2i(Internal *, void *);
+extern void fpid2i(Internal *, void *);
+extern void fpiw2i(Internal *, void *);
+extern void fpii2s(void *, Internal *);
+extern void fpii2d(void *, Internal *);
+extern void fpii2w(Word *, Internal *);
diff --git a/sys/src/9/bitsy/fpiarm.c b/sys/src/9/bitsy/fpiarm.c
new file mode 100755
index 000000000..332b596b9
--- /dev/null
+++ b/sys/src/9/bitsy/fpiarm.c
@@ -0,0 +1,570 @@
+/*
+ * this doesn't attempt to implement ARM floating-point properties
+ * that aren't visible in the Inferno environment.
+ * all arithmetic is done in double precision.
+ * the FP trap status isn't updated.
+ */
+#include <u.h>
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include <ureg.h>
+
+#include "fpi.h"
+
+/* undef this if correct kernel r13 isn't in Ureg;
+ * check calculation in fpiarm below
+ */
+
+
+#define REG(ur, x) (*(long*)(((char*)(ur))+roff[(x)]))
+#define FR(ufp, x) (*(Internal*)(ufp)->regs[(x)&7])
+
+typedef struct FP2 FP2;
+typedef struct FP1 FP1;
+
+struct FP2 {
+ char* name;
+ void (*f)(Internal, Internal, Internal*);
+};
+
+struct FP1 {
+ char* name;
+ void (*f)(Internal*, Internal*);
+};
+
+enum {
+ N = 1<<31,
+ Z = 1<<30,
+ C = 1<<29,
+ V = 1<<28,
+ REGPC = 15,
+};
+
+int fpemudebug = 0;
+
+#undef OFR
+#define OFR(X) ((ulong)&((Ureg*)0)->X)
+
+static int roff[] = {
+ OFR(r0), OFR(r1), OFR(r2), OFR(r3),
+ OFR(r4), OFR(r5), OFR(r6), OFR(r7),
+ OFR(r8), OFR(r9), OFR(r10), OFR(r11),
+ OFR(r12), OFR(r13), OFR(r14), OFR(pc),
+};
+
+static Internal fpconst[8] = { /* indexed by op&7 */
+ /* s, e, l, h */
+ {0, 0x1, 0x00000000, 0x00000000}, /* 0.0 */
+ {0, 0x3FF, 0x00000000, 0x08000000}, /* 1.0 */
+ {0, 0x400, 0x00000000, 0x08000000}, /* 2.0 */
+ {0, 0x400, 0x00000000, 0x0C000000}, /* 3.0 */
+ {0, 0x401, 0x00000000, 0x08000000}, /* 4.0 */
+ {0, 0x401, 0x00000000, 0x0A000000}, /* 5.0 */
+ {0, 0x3FE, 0x00000000, 0x08000000}, /* 0.5 */
+ {0, 0x402, 0x00000000, 0x0A000000}, /* 10.0 */
+};
+
+/*
+ * arm binary operations
+ */
+
+static void
+fadd(Internal m, Internal n, Internal *d)
+{
+ (m.s == n.s? fpiadd: fpisub)(&m, &n, d);
+}
+
+static void
+fsub(Internal m, Internal n, Internal *d)
+{
+ m.s ^= 1;
+ (m.s == n.s? fpiadd: fpisub)(&m, &n, d);
+}
+
+static void
+fsubr(Internal m, Internal n, Internal *d)
+{
+ n.s ^= 1;
+ (n.s == m.s? fpiadd: fpisub)(&n, &m, d);
+}
+
+static void
+fmul(Internal m, Internal n, Internal *d)
+{
+ fpimul(&m, &n, d);
+}
+
+static void
+fdiv(Internal m, Internal n, Internal *d)
+{
+ fpidiv(&m, &n, d);
+}
+
+static void
+fdivr(Internal m, Internal n, Internal *d)
+{
+ fpidiv(&n, &m, d);
+}
+
+/*
+ * arm unary operations
+ */
+
+static void
+fmov(Internal *m, Internal *d)
+{
+ *d = *m;
+}
+
+static void
+fmovn(Internal *m, Internal *d)
+{
+ *d = *m;
+ d->s ^= 1;
+}
+
+static void
+fabsf(Internal *m, Internal *d)
+{
+ *d = *m;
+ d->s = 0;
+}
+
+static void
+frnd(Internal *m, Internal *d)
+{
+ short e;
+
+ (m->s? fsub: fadd)(fpconst[6], *m, d);
+ if(IsWeird(d))
+ return;
+ fpiround(d);
+ e = (d->e - ExpBias) + 1;
+ if(e <= 0)
+ SetZero(d);
+ else if(e > FractBits){
+ if(e < 2*FractBits)
+ d->l &= ~((1<<(2*FractBits - e))-1);
+ }else{
+ d->l = 0;
+ if(e < FractBits)
+ d->h &= ~((1<<(FractBits-e))-1);
+ }
+}
+
+static FP1 optab1[16] = { /* Fd := OP Fm */
+[0] {"MOVF", fmov},
+[1] {"NEGF", fmovn},
+[2] {"ABSF", fabsf},
+[3] {"RNDF", frnd},
+[4] {"SQTF", /*fsqt*/0},
+/* LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN all `deprecated' */
+/* URD and NRM aren't implemented */
+};
+
+static FP2 optab2[16] = { /* Fd := Fn OP Fm */
+[0] {"ADDF", fadd},
+[1] {"MULF", fmul},
+[2] {"SUBF", fsub},
+[3] {"RSUBF", fsubr},
+[4] {"DIVF", fdiv},
+[5] {"RDIVF", fdivr},
+/* POW, RPW deprecated */
+[8] {"REMF", /*frem*/0},
+[9] {"FMF", fmul}, /* fast multiply */
+[10] {"FDV", fdiv}, /* fast divide */
+[11] {"FRD", fdivr}, /* fast reverse divide */
+/* POL deprecated */
+};
+
+static ulong
+fcmp(Internal *n, Internal *m)
+{
+ int i;
+ Internal rm, rn;
+
+ if(IsWeird(m) || IsWeird(n)){
+ /* BUG: should trap if not masked */
+ return V|C;
+ }
+ rn = *n;
+ rm = *m;
+ fpiround(&rn);
+ fpiround(&rm);
+ i = fpicmp(&rn, &rm);
+ if(i > 0)
+ return C;
+ else if(i == 0)
+ return C|Z;
+ else
+ return N;
+}
+
+static void
+fld(void (*f)(Internal*, void*), int d, ulong ea, int n, FPsave *ufp)
+{
+ void *mem;
+
+ mem = (void*)ea;
+ (*f)(&FR(ufp, d), mem);
+ if(fpemudebug)
+ print("MOV%c #%lux, F%d\n", n==8? 'D': 'F', ea, d);
+}
+
+static void
+fst(void (*f)(void*, Internal*), ulong ea, int s, int n, FPsave *ufp)
+{
+ Internal tmp;
+ void *mem;
+
+ mem = (void*)ea;
+ tmp = FR(ufp, s);
+ if(fpemudebug)
+ print("MOV%c F%d,#%lux\n", n==8? 'D': 'F', s, ea);
+ (*f)(mem, &tmp);
+}
+
+static int
+condok(int cc, int c)
+{
+ switch(c){
+ case 0: /* Z set */
+ return cc&Z;
+ case 1: /* Z clear */
+ return (cc&Z) == 0;
+ case 2: /* C set */
+ return cc&C;
+ case 3: /* C clear */
+ return (cc&C) == 0;
+ case 4: /* N set */
+ return cc&N;
+ case 5: /* N clear */
+ return (cc&N) == 0;
+ case 6: /* V set */
+ return cc&V;
+ case 7: /* V clear */
+ return (cc&V) == 0;
+ case 8: /* C set and Z clear */
+ return cc&C && (cc&Z) == 0;
+ case 9: /* C clear or Z set */
+ return (cc&C) == 0 || cc&Z;
+ case 10: /* N set and V set, or N clear and V clear */
+ return (~cc&(N|V))==0 || (cc&(N|V)) == 0;
+ case 11: /* N set and V clear, or N clear and V set */
+ return (cc&(N|V))==N || (cc&(N|V))==V;
+ case 12: /* Z clear, and either N set and V set or N clear and V clear */
+ return (cc&Z) == 0 && ((~cc&(N|V))==0 || (cc&(N|V))==0);
+ case 13: /* Z set, or N set and V clear or N clear and V set */
+ return (cc&Z) || (cc&(N|V))==N || (cc&(N|V))==V;
+ case 14: /* always */
+ return 1;
+ case 15: /* never (reserved) */
+ return 0;
+ }
+ return 0; /* not reached */
+}
+
+static void
+unimp(ulong pc, ulong op)
+{
+ char buf[60];
+
+ snprint(buf, sizeof(buf), "sys: fp: pc=%lux unimp fp 0x%.8lux", pc, op);
+ if(fpemudebug)
+ print("FPE: %s\n", buf);
+ error(buf);
+ /* no return */
+}
+
+static void
+fpemu(ulong pc, ulong op, Ureg *ur, FPsave *ufp)
+{
+ int rn, rd, tag, o;
+ long off;
+ ulong ea;
+ Internal tmp, *fm, *fn;
+
+ /* note: would update fault status here if we noted numeric exceptions */
+
+ /*
+ * LDF, STF; 10.1.1
+ */
+ if(((op>>25)&7) == 6){
+ if(op & (1<<22))
+ unimp(pc, op); /* packed or extended */
+ rn = (op>>16)&0xF;
+ off = (op&0xFF)<<2;
+ if((op & (1<<23)) == 0)
+ off = -off;
+ ea = REG(ur, rn);
+ if(rn == REGPC)
+ ea += 8;
+ if(op & (1<<24))
+ ea += off;
+ rd = (op>>12)&7;
+ if(op & (1<<20)){
+ if(op & (1<<15))
+ fld(fpid2i, rd, ea, 8, ufp);
+ else
+ fld(fpis2i, rd, ea, 4, ufp);
+ }else{
+ if(op & (1<<15))
+ fst(fpii2d, ea, rd, 8, ufp);
+ else
+ fst(fpii2s, ea, rd, 4, ufp);
+ }
+ if((op & (1<<24)) == 0)
+ ea += off;
+ if(op & (1<<21))
+ REG(ur, rn) = ea;
+ return;
+ }
+
+ /*
+ * CPRT/transfer, 10.3
+ */
+ if(op & (1<<4)){
+ rd = (op>>12) & 0xF;
+
+ /*
+ * compare, 10.3.1
+ */
+ if(rd == 15 && op & (1<<20)){
+ rn = (op>>16)&7;
+ fn = &FR(ufp, rn);
+ if(op & (1<<3)){
+ fm = &fpconst[op&7];
+ tag = 'C';
+ }else{
+ fm = &FR(ufp, op&7);
+ tag = 'F';
+ }
+ switch((op>>21)&7){
+ default:
+ unimp(pc, op);
+ case 4: /* CMF: Fn :: Fm */
+ case 6: /* CMFE: Fn :: Fm (with exception) */
+ ur->psr &= ~(N|C|Z|V);
+ ur->psr |= fcmp(fn, fm);
+ break;
+ case 5: /* CNF: Fn :: -Fm */
+ case 7: /* CNFE: Fn :: -Fm (with exception) */
+ tmp = *fm;
+ tmp.s ^= 1;
+ ur->psr &= ~(N|C|Z|V);
+ ur->psr |= fcmp(fn, &tmp);
+ break;
+ }
+ if(fpemudebug)
+ print("CMPF %c%d,F%ld =%lux\n", tag, rn, op&7, ur->psr>>28);
+ return;
+ }
+
+ /*
+ * other transfer, 10.3
+ */
+ switch((op>>20)&0xF){
+ default:
+ unimp(pc, op);
+ case 0: /* FLT */
+ rn = (op>>16) & 7;
+ fpiw2i(&FR(ufp, rn), &REG(ur, rd));
+ if(fpemudebug)
+ print("MOVW[FD] R%d, F%d\n", rd, rn);
+ break;
+ case 1: /* FIX */
+ if(op & (1<<3))
+ unimp(pc, op);
+ rn = op & 7;
+ tmp = FR(ufp, rn);
+ fpii2w(&REG(ur, rd), &tmp);
+ if(fpemudebug)
+ print("MOV[FD]W F%d, R%d =%ld\n", rn, rd, REG(ur, rd));
+ break;
+ case 2: /* FPSR := Rd */
+ ufp->status = REG(ur, rd);
+ if(fpemudebug)
+ print("MOVW R%d, FPSR\n", rd);
+ break;
+ case 3: /* Rd := FPSR */
+ REG(ur, rd) = ufp->status;
+ if(fpemudebug)
+ print("MOVW FPSR, R%d\n", rd);
+ break;
+ case 4: /* FPCR := Rd */
+ ufp->control = REG(ur, rd);
+ if(fpemudebug)
+ print("MOVW R%d, FPCR\n", rd);
+ break;
+ case 5: /* Rd := FPCR */
+ REG(ur, rd) = ufp->control;
+ if(fpemudebug)
+ print("MOVW FPCR, R%d\n", rd);
+ break;
+ }
+ return;
+ }
+
+ /*
+ * arithmetic
+ */
+
+ if(op & (1<<3)){ /* constant */
+ fm = &fpconst[op&7];
+ tag = 'C';
+ }else{
+ fm = &FR(ufp, op&7);
+ tag = 'F';
+ }
+ rd = (op>>12)&7;
+ o = (op>>20)&0xF;
+ if(op & (1<<15)){ /* monadic */
+ FP1 *fp;
+ fp = &optab1[o];
+ if(fp->f == nil)
+ unimp(pc, op);
+ if(fpemudebug)
+ print("%s %c%ld,F%d\n", fp->name, tag, op&7, rd);
+ (*fp->f)(fm, &FR(ufp, rd));
+ } else {
+ FP2 *fp;
+ fp = &optab2[o];
+ if(fp->f == nil)
+ unimp(pc, op);
+ rn = (op>>16)&7;
+ if(fpemudebug)
+ print("%s %c%ld,F%d,F%d\n", fp->name, tag, op&7, rn, rd);
+ (*fp->f)(*fm, FR(ufp, rn), &FR(ufp, rd));
+ }
+}
+
+void
+casemu(ulong pc, ulong op, Ureg *ur)
+{
+ ulong *rp, ro, rn, *rd;
+
+ USED(pc);
+
+ rp = (ulong*)ur;
+ ro = rp[op>>16 & 0x7];
+ rn = rp[op>>0 & 0x7];
+ rd = rp + (op>>12 & 0x7);
+ rp = (ulong*)*rd;
+ validaddr((ulong)rp, 4, 1);
+ splhi();
+ if(*rd = (*rp == ro))
+ *rp = rn;
+ spllo();
+}
+
+int ldrexvalid;
+
+void
+ldrex(ulong pc, ulong op, Ureg *ur)
+{
+ ulong *rp, *rd, *addr;
+
+ USED(pc);
+
+ rp = (ulong*)ur;
+ rd = rp + (op>>16 & 0x7);
+ addr = (ulong*)*rd;
+ validaddr((ulong)addr, 4, 0);
+ ldrexvalid = 1;
+ rp[op>>12 & 0x7] = *addr;
+ if(fpemudebug)
+ print("ldrex, r%ld = [r%ld]@0x%8.8p = 0x%8.8lux",
+ op>>12 & 0x7, op>>16 & 0x7, addr, rp[op>>12 & 0x7]);
+}
+
+void
+strex(ulong pc, ulong op, Ureg *ur)
+{
+ ulong *rp, rn, *rd, *addr;
+
+ USED(pc);
+
+ rp = (ulong*)ur;
+ rd = rp + (op>>16 & 0x7);
+ rn = rp[op>>0 & 0x7];
+ addr = (ulong*)*rd;
+ validaddr((ulong)addr, 4, 1);
+ splhi();
+ if(ldrexvalid){
+ if(fpemudebug)
+ print("strex valid, [r%ld]@0x%8.8p = r%ld = 0x%8.8lux",
+ op>>16 & 0x7, addr, op>>0 & 0x7, rn);
+ *addr = rn;
+ ldrexvalid = 0;
+ rp[op>>12 & 0x7] = 0;
+ }else{
+ if(fpemudebug)
+ print("strex invalid, r%ld = 1", op>>16 & 0x7);
+ rp[op>>12 & 0x7] = 1;
+ }
+ spllo();
+}
+
+struct {
+ ulong opc;
+ ulong mask;
+ void (*f)(ulong, ulong, Ureg*);
+} specialopc[] = {
+ { 0x01900f9f, 0x0ff00fff, ldrex },
+ { 0x01800f90, 0x0ff00ff0, strex },
+ { 0x0ed00100, 0x0ef08100, casemu },
+ { 0x00000000, 0x00000000, nil }
+};
+
+
+/*
+ * returns the number of FP instructions emulated
+ */
+int
+fpiarm(Ureg *ur)
+{
+ ulong op, o;
+ FPsave *ufp;
+ int i, n;
+
+ if (up == nil)
+ panic("fpiarm not in a process");
+ ufp = &up->fpsave;
+ /* because all the state is in the proc structure,
+ * it need not be saved/restored
+ */
+ if(up->fpstate != FPactive) {
+// assert(sizeof(Internal) == sizeof(ufp->regs[0]));
+ up->fpstate = FPactive;
+ ufp->control = 0;
+ ufp->status = (0x01<<28)|(1<<12); /* software emulation, alternative C flag */
+ for(n = 0; n < 8; n++)
+ FR(ufp, n) = fpconst[0];
+ }
+ for(n=0; ;n++){
+ if(fpemudebug)
+ print("0x%8.8lux ", ur->pc);
+ validaddr(ur->pc, 4, 0);
+ op = *(ulong*)(ur->pc);
+ o = (op>>24) & 0xF;
+ if(condok(ur->psr, op>>28)){
+ for(i = 0; specialopc[i].f; i++)
+ if((op & specialopc[i].mask) == specialopc[i].opc)
+ break;
+ if(specialopc[i].f)
+ specialopc[i].f(ur->pc, op, ur);
+ else if((op & 0xF00) != 0x100 || o != 0xE && (o&~1) != 0xC)
+ break;
+ else
+ fpemu(ur->pc, op, ur, ufp);
+ }else if((op & 0xF00) != 0x100 || o != 0xE && (o&~1) != 0xC)
+ break;
+ ur->pc += 4;
+ }
+ if(fpemudebug) print("\n");
+ return n;
+}
diff --git a/sys/src/9/bitsy/fpimem.c b/sys/src/9/bitsy/fpimem.c
new file mode 100755
index 000000000..627ab6355
--- /dev/null
+++ b/sys/src/9/bitsy/fpimem.c
@@ -0,0 +1,136 @@
+#include "fpi.h"
+
+/*
+ * the following routines depend on memory format, not the machine
+ */
+
+void
+fpis2i(Internal *i, void *v)
+{
+ Single *s = v;
+
+ i->s = (*s & 0x80000000) ? 1: 0;
+ if((*s & ~0x80000000) == 0){
+ SetZero(i);
+ return;
+ }
+ i->e = ((*s>>23) & 0x00FF) - SingleExpBias + ExpBias;
+ i->h = (*s & 0x007FFFFF)<<(1+NGuardBits);
+ i->l = 0;
+ if(i->e)
+ i->h |= HiddenBit;
+ else
+ i->e++;
+}
+
+void
+fpid2i(Internal *i, void *v)
+{
+ Double *d = v;
+
+ i->s = (d->h & 0x80000000) ? 1: 0;
+ i->e = (d->h>>20) & 0x07FF;
+ i->h = ((d->h & 0x000FFFFF)<<(4+NGuardBits))|((d->l>>25) & 0x7F);
+ i->l = (d->l & 0x01FFFFFF)<<NGuardBits;
+ if(i->e)
+ i->h |= HiddenBit;
+ else
+ i->e++;
+}
+
+void
+fpiw2i(Internal *i, void *v)
+{
+ Word w, word = *(Word*)v;
+ short e;
+
+ if(word < 0){
+ i->s = 1;
+ word = -word;
+ }
+ else
+ i->s = 0;
+ if(word == 0){
+ SetZero(i);
+ return;
+ }
+ if(word > 0){
+ for (e = 0, w = word; w; w >>= 1, e++)
+ ;
+ } else
+ e = 32;
+ if(e > FractBits){
+ i->h = word>>(e - FractBits);
+ i->l = (word & ((1<<(e - FractBits)) - 1))<<(2*FractBits - e);
+ }
+ else {
+ i->h = word<<(FractBits - e);
+ i->l = 0;
+ }
+ i->e = (e - 1) + ExpBias;
+}
+
+void
+fpii2s(void *v, Internal *i)
+{
+ short e;
+ Single *s = (Single*)v;
+
+ fpiround(i);
+ if(i->h & HiddenBit)
+ i->h &= ~HiddenBit;
+ else
+ i->e--;
+ *s = i->s ? 0x80000000: 0;
+ e = i->e;
+ if(e < ExpBias){
+ if(e <= (ExpBias - SingleExpBias))
+ return;
+ e = SingleExpBias - (ExpBias - e);
+ }
+ else if(e >= (ExpBias + (SingleExpMax-SingleExpBias))){
+ *s |= SingleExpMax<<23;
+ return;
+ }
+ else
+ e = SingleExpBias + (e - ExpBias);
+ *s |= (e<<23)|(i->h>>(1+NGuardBits));
+}
+
+void
+fpii2d(void *v, Internal *i)
+{
+ Double *d = (Double*)v;
+
+ fpiround(i);
+ if(i->h & HiddenBit)
+ i->h &= ~HiddenBit;
+ else
+ i->e--;
+ i->l = ((i->h & GuardMask)<<25)|(i->l>>NGuardBits);
+ i->h >>= NGuardBits;
+ d->h = i->s ? 0x80000000: 0;
+ d->h |= (i->e<<20)|((i->h & 0x00FFFFFF)>>4);
+ d->l = (i->h<<28)|i->l;
+}
+
+void
+fpii2w(Word *word, Internal *i)
+{
+ Word w;
+ short e;
+
+ fpiround(i);
+ e = (i->e - ExpBias) + 1;
+ if(e <= 0)
+ w = 0;
+ else if(e > 31)
+ w = 0x7FFFFFFF;
+ else if(e > FractBits)
+ w = (i->h<<(e - FractBits))|(i->l>>(2*FractBits - e));
+ else
+ w = i->h>>(FractBits-e);
+ if(i->s)
+ w = -w;
+ *word = w;
+}
diff --git a/sys/src/9/bitsy/gamma.c b/sys/src/9/bitsy/gamma.c
new file mode 100755
index 000000000..489c39bfa
--- /dev/null
+++ b/sys/src/9/bitsy/gamma.c
@@ -0,0 +1,51 @@
+#include <u.h>
+#include <libc.h>
+#include <stdio.h>
+
+double gamma = 1.6;
+
+int
+remap5(int i)
+{
+ double v;
+
+ v = (double)i/31.0;
+ return 31.0*pow(v, gamma);
+}
+
+int
+remap6(int i)
+{
+ double v;
+
+ v = (double)i/63.0;
+ return 63.0*pow(v, gamma);
+}
+
+int
+remap(int i)
+{
+ int r, g, b;
+
+ b = i & 0x1F;
+ g = (i>>5) & 0x3F;
+ r = (i>>11) & 0x1F;
+ return (remap5(r)<<11) | (remap6(g)<<5) | (remap5(b)<<0);
+}
+
+void
+main(void)
+{
+ int i;
+
+ printf("/* gamma = %.2f */\n", gamma);
+ printf("ushort gamma[65536] = {\n");
+ for(i=0; i<65536; i++){
+ if((i%8) == 0)
+ printf("\t");
+ printf("0x%.4x, ", remap(i));
+ if((i%8) == 7)
+ printf("\n");
+ }
+ printf("};\n");
+}
diff --git a/sys/src/9/bitsy/gamma.h b/sys/src/9/bitsy/gamma.h
new file mode 100755
index 000000000..ef20ff993
--- /dev/null
+++ b/sys/src/9/bitsy/gamma.h
@@ -0,0 +1,8195 @@
+/* gamma = 1.60 */
+ushort gamma[65536] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0021, 0x0021, 0x0022, 0x0022,
+ 0x0023, 0x0024, 0x0025, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002a, 0x002b, 0x002c, 0x002e, 0x002f, 0x0030, 0x0031, 0x0033,
+ 0x0034, 0x0035, 0x0037, 0x0038, 0x003a, 0x003b, 0x003d, 0x003f,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0021, 0x0021, 0x0022, 0x0022,
+ 0x0023, 0x0024, 0x0025, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002a, 0x002b, 0x002c, 0x002e, 0x002f, 0x0030, 0x0031, 0x0033,
+ 0x0034, 0x0035, 0x0037, 0x0038, 0x003a, 0x003b, 0x003d, 0x003f,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0021, 0x0021, 0x0022, 0x0022,
+ 0x0023, 0x0024, 0x0025, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002a, 0x002b, 0x002c, 0x002e, 0x002f, 0x0030, 0x0031, 0x0033,
+ 0x0034, 0x0035, 0x0037, 0x0038, 0x003a, 0x003b, 0x003d, 0x003f,
+ 0x0040, 0x0040, 0x0040, 0x0040, 0x0041, 0x0041, 0x0042, 0x0042,
+ 0x0043, 0x0044, 0x0045, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049,
+ 0x004a, 0x004b, 0x004c, 0x004e, 0x004f, 0x0050, 0x0051, 0x0053,
+ 0x0054, 0x0055, 0x0057, 0x0058, 0x005a, 0x005b, 0x005d, 0x005f,
+ 0x0040, 0x0040, 0x0040, 0x0040, 0x0041, 0x0041, 0x0042, 0x0042,
+ 0x0043, 0x0044, 0x0045, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049,
+ 0x004a, 0x004b, 0x004c, 0x004e, 0x004f, 0x0050, 0x0051, 0x0053,
+ 0x0054, 0x0055, 0x0057, 0x0058, 0x005a, 0x005b, 0x005d, 0x005f,
+ 0x0060, 0x0060, 0x0060, 0x0060, 0x0061, 0x0061, 0x0062, 0x0062,
+ 0x0063, 0x0064, 0x0065, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
+ 0x006a, 0x006b, 0x006c, 0x006e, 0x006f, 0x0070, 0x0071, 0x0073,
+ 0x0074, 0x0075, 0x0077, 0x0078, 0x007a, 0x007b, 0x007d, 0x007f,
+ 0x0060, 0x0060, 0x0060, 0x0060, 0x0061, 0x0061, 0x0062, 0x0062,
+ 0x0063, 0x0064, 0x0065, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
+ 0x006a, 0x006b, 0x006c, 0x006e, 0x006f, 0x0070, 0x0071, 0x0073,
+ 0x0074, 0x0075, 0x0077, 0x0078, 0x007a, 0x007b, 0x007d, 0x007f,
+ 0x0080, 0x0080, 0x0080, 0x0080, 0x0081, 0x0081, 0x0082, 0x0082,
+ 0x0083, 0x0084, 0x0085, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089,
+ 0x008a, 0x008b, 0x008c, 0x008e, 0x008f, 0x0090, 0x0091, 0x0093,
+ 0x0094, 0x0095, 0x0097, 0x0098, 0x009a, 0x009b, 0x009d, 0x009f,
+ 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a1, 0x00a1, 0x00a2, 0x00a2,
+ 0x00a3, 0x00a4, 0x00a5, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9,
+ 0x00aa, 0x00ab, 0x00ac, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b3,
+ 0x00b4, 0x00b5, 0x00b7, 0x00b8, 0x00ba, 0x00bb, 0x00bd, 0x00bf,
+ 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a1, 0x00a1, 0x00a2, 0x00a2,
+ 0x00a3, 0x00a4, 0x00a5, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9,
+ 0x00aa, 0x00ab, 0x00ac, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b3,
+ 0x00b4, 0x00b5, 0x00b7, 0x00b8, 0x00ba, 0x00bb, 0x00bd, 0x00bf,
+ 0x00c0, 0x00c0, 0x00c0, 0x00c0, 0x00c1, 0x00c1, 0x00c2, 0x00c2,
+ 0x00c3, 0x00c4, 0x00c5, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9,
+ 0x00ca, 0x00cb, 0x00cc, 0x00ce, 0x00cf, 0x00d0, 0x00d1, 0x00d3,
+ 0x00d4, 0x00d5, 0x00d7, 0x00d8, 0x00da, 0x00db, 0x00dd, 0x00df,
+ 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e1, 0x00e1, 0x00e2, 0x00e2,
+ 0x00e3, 0x00e4, 0x00e5, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9,
+ 0x00ea, 0x00eb, 0x00ec, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f3,
+ 0x00f4, 0x00f5, 0x00f7, 0x00f8, 0x00fa, 0x00fb, 0x00fd, 0x00ff,
+ 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e1, 0x00e1, 0x00e2, 0x00e2,
+ 0x00e3, 0x00e4, 0x00e5, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9,
+ 0x00ea, 0x00eb, 0x00ec, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f3,
+ 0x00f4, 0x00f5, 0x00f7, 0x00f8, 0x00fa, 0x00fb, 0x00fd, 0x00ff,
+ 0x0100, 0x0100, 0x0100, 0x0100, 0x0101, 0x0101, 0x0102, 0x0102,
+ 0x0103, 0x0104, 0x0105, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109,
+ 0x010a, 0x010b, 0x010c, 0x010e, 0x010f, 0x0110, 0x0111, 0x0113,
+ 0x0114, 0x0115, 0x0117, 0x0118, 0x011a, 0x011b, 0x011d, 0x011f,
+ 0x0120, 0x0120, 0x0120, 0x0120, 0x0121, 0x0121, 0x0122, 0x0122,
+ 0x0123, 0x0124, 0x0125, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129,
+ 0x012a, 0x012b, 0x012c, 0x012e, 0x012f, 0x0130, 0x0131, 0x0133,
+ 0x0134, 0x0135, 0x0137, 0x0138, 0x013a, 0x013b, 0x013d, 0x013f,
+ 0x0140, 0x0140, 0x0140, 0x0140, 0x0141, 0x0141, 0x0142, 0x0142,
+ 0x0143, 0x0144, 0x0145, 0x0145, 0x0146, 0x0147, 0x0148, 0x0149,
+ 0x014a, 0x014b, 0x014c, 0x014e, 0x014f, 0x0150, 0x0151, 0x0153,
+ 0x0154, 0x0155, 0x0157, 0x0158, 0x015a, 0x015b, 0x015d, 0x015f,
+ 0x0140, 0x0140, 0x0140, 0x0140, 0x0141, 0x0141, 0x0142, 0x0142,
+ 0x0143, 0x0144, 0x0145, 0x0145, 0x0146, 0x0147, 0x0148, 0x0149,
+ 0x014a, 0x014b, 0x014c, 0x014e, 0x014f, 0x0150, 0x0151, 0x0153,
+ 0x0154, 0x0155, 0x0157, 0x0158, 0x015a, 0x015b, 0x015d, 0x015f,
+ 0x0160, 0x0160, 0x0160, 0x0160, 0x0161, 0x0161, 0x0162, 0x0162,
+ 0x0163, 0x0164, 0x0165, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169,
+ 0x016a, 0x016b, 0x016c, 0x016e, 0x016f, 0x0170, 0x0171, 0x0173,
+ 0x0174, 0x0175, 0x0177, 0x0178, 0x017a, 0x017b, 0x017d, 0x017f,
+ 0x0180, 0x0180, 0x0180, 0x0180, 0x0181, 0x0181, 0x0182, 0x0182,
+ 0x0183, 0x0184, 0x0185, 0x0185, 0x0186, 0x0187, 0x0188, 0x0189,
+ 0x018a, 0x018b, 0x018c, 0x018e, 0x018f, 0x0190, 0x0191, 0x0193,
+ 0x0194, 0x0195, 0x0197, 0x0198, 0x019a, 0x019b, 0x019d, 0x019f,
+ 0x01a0, 0x01a0, 0x01a0, 0x01a0, 0x01a1, 0x01a1, 0x01a2, 0x01a2,
+ 0x01a3, 0x01a4, 0x01a5, 0x01a5, 0x01a6, 0x01a7, 0x01a8, 0x01a9,
+ 0x01aa, 0x01ab, 0x01ac, 0x01ae, 0x01af, 0x01b0, 0x01b1, 0x01b3,
+ 0x01b4, 0x01b5, 0x01b7, 0x01b8, 0x01ba, 0x01bb, 0x01bd, 0x01bf,
+ 0x01c0, 0x01c0, 0x01c0, 0x01c0, 0x01c1, 0x01c1, 0x01c2, 0x01c2,
+ 0x01c3, 0x01c4, 0x01c5, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9,
+ 0x01ca, 0x01cb, 0x01cc, 0x01ce, 0x01cf, 0x01d0, 0x01d1, 0x01d3,
+ 0x01d4, 0x01d5, 0x01d7, 0x01d8, 0x01da, 0x01db, 0x01dd, 0x01df,
+ 0x01e0, 0x01e0, 0x01e0, 0x01e0, 0x01e1, 0x01e1, 0x01e2, 0x01e2,
+ 0x01e3, 0x01e4, 0x01e5, 0x01e5, 0x01e6, 0x01e7, 0x01e8, 0x01e9,
+ 0x01ea, 0x01eb, 0x01ec, 0x01ee, 0x01ef, 0x01f0, 0x01f1, 0x01f3,
+ 0x01f4, 0x01f5, 0x01f7, 0x01f8, 0x01fa, 0x01fb, 0x01fd, 0x01ff,
+ 0x0200, 0x0200, 0x0200, 0x0200, 0x0201, 0x0201, 0x0202, 0x0202,
+ 0x0203, 0x0204, 0x0205, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209,
+ 0x020a, 0x020b, 0x020c, 0x020e, 0x020f, 0x0210, 0x0211, 0x0213,
+ 0x0214, 0x0215, 0x0217, 0x0218, 0x021a, 0x021b, 0x021d, 0x021f,
+ 0x0220, 0x0220, 0x0220, 0x0220, 0x0221, 0x0221, 0x0222, 0x0222,
+ 0x0223, 0x0224, 0x0225, 0x0225, 0x0226, 0x0227, 0x0228, 0x0229,
+ 0x022a, 0x022b, 0x022c, 0x022e, 0x022f, 0x0230, 0x0231, 0x0233,
+ 0x0234, 0x0235, 0x0237, 0x0238, 0x023a, 0x023b, 0x023d, 0x023f,
+ 0x0240, 0x0240, 0x0240, 0x0240, 0x0241, 0x0241, 0x0242, 0x0242,
+ 0x0243, 0x0244, 0x0245, 0x0245, 0x0246, 0x0247, 0x0248, 0x0249,
+ 0x024a, 0x024b, 0x024c, 0x024e, 0x024f, 0x0250, 0x0251, 0x0253,
+ 0x0254, 0x0255, 0x0257, 0x0258, 0x025a, 0x025b, 0x025d, 0x025f,
+ 0x0260, 0x0260, 0x0260, 0x0260, 0x0261, 0x0261, 0x0262, 0x0262,
+ 0x0263, 0x0264, 0x0265, 0x0265, 0x0266, 0x0267, 0x0268, 0x0269,
+ 0x026a, 0x026b, 0x026c, 0x026e, 0x026f, 0x0270, 0x0271, 0x0273,
+ 0x0274, 0x0275, 0x0277, 0x0278, 0x027a, 0x027b, 0x027d, 0x027f,
+ 0x0280, 0x0280, 0x0280, 0x0280, 0x0281, 0x0281, 0x0282, 0x0282,
+ 0x0283, 0x0284, 0x0285, 0x0285, 0x0286, 0x0287, 0x0288, 0x0289,
+ 0x028a, 0x028b, 0x028c, 0x028e, 0x028f, 0x0290, 0x0291, 0x0293,
+ 0x0294, 0x0295, 0x0297, 0x0298, 0x029a, 0x029b, 0x029d, 0x029f,
+ 0x02a0, 0x02a0, 0x02a0, 0x02a0, 0x02a1, 0x02a1, 0x02a2, 0x02a2,
+ 0x02a3, 0x02a4, 0x02a5, 0x02a5, 0x02a6, 0x02a7, 0x02a8, 0x02a9,
+ 0x02aa, 0x02ab, 0x02ac, 0x02ae, 0x02af, 0x02b0, 0x02b1, 0x02b3,
+ 0x02b4, 0x02b5, 0x02b7, 0x02b8, 0x02ba, 0x02bb, 0x02bd, 0x02bf,
+ 0x02c0, 0x02c0, 0x02c0, 0x02c0, 0x02c1, 0x02c1, 0x02c2, 0x02c2,
+ 0x02c3, 0x02c4, 0x02c5, 0x02c5, 0x02c6, 0x02c7, 0x02c8, 0x02c9,
+ 0x02ca, 0x02cb, 0x02cc, 0x02ce, 0x02cf, 0x02d0, 0x02d1, 0x02d3,
+ 0x02d4, 0x02d5, 0x02d7, 0x02d8, 0x02da, 0x02db, 0x02dd, 0x02df,
+ 0x02e0, 0x02e0, 0x02e0, 0x02e0, 0x02e1, 0x02e1, 0x02e2, 0x02e2,
+ 0x02e3, 0x02e4, 0x02e5, 0x02e5, 0x02e6, 0x02e7, 0x02e8, 0x02e9,
+ 0x02ea, 0x02eb, 0x02ec, 0x02ee, 0x02ef, 0x02f0, 0x02f1, 0x02f3,
+ 0x02f4, 0x02f5, 0x02f7, 0x02f8, 0x02fa, 0x02fb, 0x02fd, 0x02ff,
+ 0x0300, 0x0300, 0x0300, 0x0300, 0x0301, 0x0301, 0x0302, 0x0302,
+ 0x0303, 0x0304, 0x0305, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309,
+ 0x030a, 0x030b, 0x030c, 0x030e, 0x030f, 0x0310, 0x0311, 0x0313,
+ 0x0314, 0x0315, 0x0317, 0x0318, 0x031a, 0x031b, 0x031d, 0x031f,
+ 0x0320, 0x0320, 0x0320, 0x0320, 0x0321, 0x0321, 0x0322, 0x0322,
+ 0x0323, 0x0324, 0x0325, 0x0325, 0x0326, 0x0327, 0x0328, 0x0329,
+ 0x032a, 0x032b, 0x032c, 0x032e, 0x032f, 0x0330, 0x0331, 0x0333,
+ 0x0334, 0x0335, 0x0337, 0x0338, 0x033a, 0x033b, 0x033d, 0x033f,
+ 0x0340, 0x0340, 0x0340, 0x0340, 0x0341, 0x0341, 0x0342, 0x0342,
+ 0x0343, 0x0344, 0x0345, 0x0345, 0x0346, 0x0347, 0x0348, 0x0349,
+ 0x034a, 0x034b, 0x034c, 0x034e, 0x034f, 0x0350, 0x0351, 0x0353,
+ 0x0354, 0x0355, 0x0357, 0x0358, 0x035a, 0x035b, 0x035d, 0x035f,
+ 0x0380, 0x0380, 0x0380, 0x0380, 0x0381, 0x0381, 0x0382, 0x0382,
+ 0x0383, 0x0384, 0x0385, 0x0385, 0x0386, 0x0387, 0x0388, 0x0389,
+ 0x038a, 0x038b, 0x038c, 0x038e, 0x038f, 0x0390, 0x0391, 0x0393,
+ 0x0394, 0x0395, 0x0397, 0x0398, 0x039a, 0x039b, 0x039d, 0x039f,
+ 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a1, 0x03a1, 0x03a2, 0x03a2,
+ 0x03a3, 0x03a4, 0x03a5, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9,
+ 0x03aa, 0x03ab, 0x03ac, 0x03ae, 0x03af, 0x03b0, 0x03b1, 0x03b3,
+ 0x03b4, 0x03b5, 0x03b7, 0x03b8, 0x03ba, 0x03bb, 0x03bd, 0x03bf,
+ 0x03c0, 0x03c0, 0x03c0, 0x03c0, 0x03c1, 0x03c1, 0x03c2, 0x03c2,
+ 0x03c3, 0x03c4, 0x03c5, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9,
+ 0x03ca, 0x03cb, 0x03cc, 0x03ce, 0x03cf, 0x03d0, 0x03d1, 0x03d3,
+ 0x03d4, 0x03d5, 0x03d7, 0x03d8, 0x03da, 0x03db, 0x03dd, 0x03df,
+ 0x03e0, 0x03e0, 0x03e0, 0x03e0, 0x03e1, 0x03e1, 0x03e2, 0x03e2,
+ 0x03e3, 0x03e4, 0x03e5, 0x03e5, 0x03e6, 0x03e7, 0x03e8, 0x03e9,
+ 0x03ea, 0x03eb, 0x03ec, 0x03ee, 0x03ef, 0x03f0, 0x03f1, 0x03f3,
+ 0x03f4, 0x03f5, 0x03f7, 0x03f8, 0x03fa, 0x03fb, 0x03fd, 0x03ff,
+ 0x0400, 0x0400, 0x0400, 0x0400, 0x0401, 0x0401, 0x0402, 0x0402,
+ 0x0403, 0x0404, 0x0405, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409,
+ 0x040a, 0x040b, 0x040c, 0x040e, 0x040f, 0x0410, 0x0411, 0x0413,
+ 0x0414, 0x0415, 0x0417, 0x0418, 0x041a, 0x041b, 0x041d, 0x041f,
+ 0x0440, 0x0440, 0x0440, 0x0440, 0x0441, 0x0441, 0x0442, 0x0442,
+ 0x0443, 0x0444, 0x0445, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
+ 0x044a, 0x044b, 0x044c, 0x044e, 0x044f, 0x0450, 0x0451, 0x0453,
+ 0x0454, 0x0455, 0x0457, 0x0458, 0x045a, 0x045b, 0x045d, 0x045f,
+ 0x0460, 0x0460, 0x0460, 0x0460, 0x0461, 0x0461, 0x0462, 0x0462,
+ 0x0463, 0x0464, 0x0465, 0x0465, 0x0466, 0x0467, 0x0468, 0x0469,
+ 0x046a, 0x046b, 0x046c, 0x046e, 0x046f, 0x0470, 0x0471, 0x0473,
+ 0x0474, 0x0475, 0x0477, 0x0478, 0x047a, 0x047b, 0x047d, 0x047f,
+ 0x0480, 0x0480, 0x0480, 0x0480, 0x0481, 0x0481, 0x0482, 0x0482,
+ 0x0483, 0x0484, 0x0485, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489,
+ 0x048a, 0x048b, 0x048c, 0x048e, 0x048f, 0x0490, 0x0491, 0x0493,
+ 0x0494, 0x0495, 0x0497, 0x0498, 0x049a, 0x049b, 0x049d, 0x049f,
+ 0x04c0, 0x04c0, 0x04c0, 0x04c0, 0x04c1, 0x04c1, 0x04c2, 0x04c2,
+ 0x04c3, 0x04c4, 0x04c5, 0x04c5, 0x04c6, 0x04c7, 0x04c8, 0x04c9,
+ 0x04ca, 0x04cb, 0x04cc, 0x04ce, 0x04cf, 0x04d0, 0x04d1, 0x04d3,
+ 0x04d4, 0x04d5, 0x04d7, 0x04d8, 0x04da, 0x04db, 0x04dd, 0x04df,
+ 0x04e0, 0x04e0, 0x04e0, 0x04e0, 0x04e1, 0x04e1, 0x04e2, 0x04e2,
+ 0x04e3, 0x04e4, 0x04e5, 0x04e5, 0x04e6, 0x04e7, 0x04e8, 0x04e9,
+ 0x04ea, 0x04eb, 0x04ec, 0x04ee, 0x04ef, 0x04f0, 0x04f1, 0x04f3,
+ 0x04f4, 0x04f5, 0x04f7, 0x04f8, 0x04fa, 0x04fb, 0x04fd, 0x04ff,
+ 0x0500, 0x0500, 0x0500, 0x0500, 0x0501, 0x0501, 0x0502, 0x0502,
+ 0x0503, 0x0504, 0x0505, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509,
+ 0x050a, 0x050b, 0x050c, 0x050e, 0x050f, 0x0510, 0x0511, 0x0513,
+ 0x0514, 0x0515, 0x0517, 0x0518, 0x051a, 0x051b, 0x051d, 0x051f,
+ 0x0540, 0x0540, 0x0540, 0x0540, 0x0541, 0x0541, 0x0542, 0x0542,
+ 0x0543, 0x0544, 0x0545, 0x0545, 0x0546, 0x0547, 0x0548, 0x0549,
+ 0x054a, 0x054b, 0x054c, 0x054e, 0x054f, 0x0550, 0x0551, 0x0553,
+ 0x0554, 0x0555, 0x0557, 0x0558, 0x055a, 0x055b, 0x055d, 0x055f,
+ 0x0560, 0x0560, 0x0560, 0x0560, 0x0561, 0x0561, 0x0562, 0x0562,
+ 0x0563, 0x0564, 0x0565, 0x0565, 0x0566, 0x0567, 0x0568, 0x0569,
+ 0x056a, 0x056b, 0x056c, 0x056e, 0x056f, 0x0570, 0x0571, 0x0573,
+ 0x0574, 0x0575, 0x0577, 0x0578, 0x057a, 0x057b, 0x057d, 0x057f,
+ 0x0580, 0x0580, 0x0580, 0x0580, 0x0581, 0x0581, 0x0582, 0x0582,
+ 0x0583, 0x0584, 0x0585, 0x0585, 0x0586, 0x0587, 0x0588, 0x0589,
+ 0x058a, 0x058b, 0x058c, 0x058e, 0x058f, 0x0590, 0x0591, 0x0593,
+ 0x0594, 0x0595, 0x0597, 0x0598, 0x059a, 0x059b, 0x059d, 0x059f,
+ 0x05c0, 0x05c0, 0x05c0, 0x05c0, 0x05c1, 0x05c1, 0x05c2, 0x05c2,
+ 0x05c3, 0x05c4, 0x05c5, 0x05c5, 0x05c6, 0x05c7, 0x05c8, 0x05c9,
+ 0x05ca, 0x05cb, 0x05cc, 0x05ce, 0x05cf, 0x05d0, 0x05d1, 0x05d3,
+ 0x05d4, 0x05d5, 0x05d7, 0x05d8, 0x05da, 0x05db, 0x05dd, 0x05df,
+ 0x05e0, 0x05e0, 0x05e0, 0x05e0, 0x05e1, 0x05e1, 0x05e2, 0x05e2,
+ 0x05e3, 0x05e4, 0x05e5, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9,
+ 0x05ea, 0x05eb, 0x05ec, 0x05ee, 0x05ef, 0x05f0, 0x05f1, 0x05f3,
+ 0x05f4, 0x05f5, 0x05f7, 0x05f8, 0x05fa, 0x05fb, 0x05fd, 0x05ff,
+ 0x0620, 0x0620, 0x0620, 0x0620, 0x0621, 0x0621, 0x0622, 0x0622,
+ 0x0623, 0x0624, 0x0625, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629,
+ 0x062a, 0x062b, 0x062c, 0x062e, 0x062f, 0x0630, 0x0631, 0x0633,
+ 0x0634, 0x0635, 0x0637, 0x0638, 0x063a, 0x063b, 0x063d, 0x063f,
+ 0x0640, 0x0640, 0x0640, 0x0640, 0x0641, 0x0641, 0x0642, 0x0642,
+ 0x0643, 0x0644, 0x0645, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649,
+ 0x064a, 0x064b, 0x064c, 0x064e, 0x064f, 0x0650, 0x0651, 0x0653,
+ 0x0654, 0x0655, 0x0657, 0x0658, 0x065a, 0x065b, 0x065d, 0x065f,
+ 0x0680, 0x0680, 0x0680, 0x0680, 0x0681, 0x0681, 0x0682, 0x0682,
+ 0x0683, 0x0684, 0x0685, 0x0685, 0x0686, 0x0687, 0x0688, 0x0689,
+ 0x068a, 0x068b, 0x068c, 0x068e, 0x068f, 0x0690, 0x0691, 0x0693,
+ 0x0694, 0x0695, 0x0697, 0x0698, 0x069a, 0x069b, 0x069d, 0x069f,
+ 0x06a0, 0x06a0, 0x06a0, 0x06a0, 0x06a1, 0x06a1, 0x06a2, 0x06a2,
+ 0x06a3, 0x06a4, 0x06a5, 0x06a5, 0x06a6, 0x06a7, 0x06a8, 0x06a9,
+ 0x06aa, 0x06ab, 0x06ac, 0x06ae, 0x06af, 0x06b0, 0x06b1, 0x06b3,
+ 0x06b4, 0x06b5, 0x06b7, 0x06b8, 0x06ba, 0x06bb, 0x06bd, 0x06bf,
+ 0x06e0, 0x06e0, 0x06e0, 0x06e0, 0x06e1, 0x06e1, 0x06e2, 0x06e2,
+ 0x06e3, 0x06e4, 0x06e5, 0x06e5, 0x06e6, 0x06e7, 0x06e8, 0x06e9,
+ 0x06ea, 0x06eb, 0x06ec, 0x06ee, 0x06ef, 0x06f0, 0x06f1, 0x06f3,
+ 0x06f4, 0x06f5, 0x06f7, 0x06f8, 0x06fa, 0x06fb, 0x06fd, 0x06ff,
+ 0x0700, 0x0700, 0x0700, 0x0700, 0x0701, 0x0701, 0x0702, 0x0702,
+ 0x0703, 0x0704, 0x0705, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709,
+ 0x070a, 0x070b, 0x070c, 0x070e, 0x070f, 0x0710, 0x0711, 0x0713,
+ 0x0714, 0x0715, 0x0717, 0x0718, 0x071a, 0x071b, 0x071d, 0x071f,
+ 0x0740, 0x0740, 0x0740, 0x0740, 0x0741, 0x0741, 0x0742, 0x0742,
+ 0x0743, 0x0744, 0x0745, 0x0745, 0x0746, 0x0747, 0x0748, 0x0749,
+ 0x074a, 0x074b, 0x074c, 0x074e, 0x074f, 0x0750, 0x0751, 0x0753,
+ 0x0754, 0x0755, 0x0757, 0x0758, 0x075a, 0x075b, 0x075d, 0x075f,
+ 0x0760, 0x0760, 0x0760, 0x0760, 0x0761, 0x0761, 0x0762, 0x0762,
+ 0x0763, 0x0764, 0x0765, 0x0765, 0x0766, 0x0767, 0x0768, 0x0769,
+ 0x076a, 0x076b, 0x076c, 0x076e, 0x076f, 0x0770, 0x0771, 0x0773,
+ 0x0774, 0x0775, 0x0777, 0x0778, 0x077a, 0x077b, 0x077d, 0x077f,
+ 0x07a0, 0x07a0, 0x07a0, 0x07a0, 0x07a1, 0x07a1, 0x07a2, 0x07a2,
+ 0x07a3, 0x07a4, 0x07a5, 0x07a5, 0x07a6, 0x07a7, 0x07a8, 0x07a9,
+ 0x07aa, 0x07ab, 0x07ac, 0x07ae, 0x07af, 0x07b0, 0x07b1, 0x07b3,
+ 0x07b4, 0x07b5, 0x07b7, 0x07b8, 0x07ba, 0x07bb, 0x07bd, 0x07bf,
+ 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e1, 0x07e1, 0x07e2, 0x07e2,
+ 0x07e3, 0x07e4, 0x07e5, 0x07e5, 0x07e6, 0x07e7, 0x07e8, 0x07e9,
+ 0x07ea, 0x07eb, 0x07ec, 0x07ee, 0x07ef, 0x07f0, 0x07f1, 0x07f3,
+ 0x07f4, 0x07f5, 0x07f7, 0x07f8, 0x07fa, 0x07fb, 0x07fd, 0x07ff,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0021, 0x0021, 0x0022, 0x0022,
+ 0x0023, 0x0024, 0x0025, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002a, 0x002b, 0x002c, 0x002e, 0x002f, 0x0030, 0x0031, 0x0033,
+ 0x0034, 0x0035, 0x0037, 0x0038, 0x003a, 0x003b, 0x003d, 0x003f,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0021, 0x0021, 0x0022, 0x0022,
+ 0x0023, 0x0024, 0x0025, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002a, 0x002b, 0x002c, 0x002e, 0x002f, 0x0030, 0x0031, 0x0033,
+ 0x0034, 0x0035, 0x0037, 0x0038, 0x003a, 0x003b, 0x003d, 0x003f,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0021, 0x0021, 0x0022, 0x0022,
+ 0x0023, 0x0024, 0x0025, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002a, 0x002b, 0x002c, 0x002e, 0x002f, 0x0030, 0x0031, 0x0033,
+ 0x0034, 0x0035, 0x0037, 0x0038, 0x003a, 0x003b, 0x003d, 0x003f,
+ 0x0040, 0x0040, 0x0040, 0x0040, 0x0041, 0x0041, 0x0042, 0x0042,
+ 0x0043, 0x0044, 0x0045, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049,
+ 0x004a, 0x004b, 0x004c, 0x004e, 0x004f, 0x0050, 0x0051, 0x0053,
+ 0x0054, 0x0055, 0x0057, 0x0058, 0x005a, 0x005b, 0x005d, 0x005f,
+ 0x0040, 0x0040, 0x0040, 0x0040, 0x0041, 0x0041, 0x0042, 0x0042,
+ 0x0043, 0x0044, 0x0045, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049,
+ 0x004a, 0x004b, 0x004c, 0x004e, 0x004f, 0x0050, 0x0051, 0x0053,
+ 0x0054, 0x0055, 0x0057, 0x0058, 0x005a, 0x005b, 0x005d, 0x005f,
+ 0x0060, 0x0060, 0x0060, 0x0060, 0x0061, 0x0061, 0x0062, 0x0062,
+ 0x0063, 0x0064, 0x0065, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
+ 0x006a, 0x006b, 0x006c, 0x006e, 0x006f, 0x0070, 0x0071, 0x0073,
+ 0x0074, 0x0075, 0x0077, 0x0078, 0x007a, 0x007b, 0x007d, 0x007f,
+ 0x0060, 0x0060, 0x0060, 0x0060, 0x0061, 0x0061, 0x0062, 0x0062,
+ 0x0063, 0x0064, 0x0065, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
+ 0x006a, 0x006b, 0x006c, 0x006e, 0x006f, 0x0070, 0x0071, 0x0073,
+ 0x0074, 0x0075, 0x0077, 0x0078, 0x007a, 0x007b, 0x007d, 0x007f,
+ 0x0080, 0x0080, 0x0080, 0x0080, 0x0081, 0x0081, 0x0082, 0x0082,
+ 0x0083, 0x0084, 0x0085, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089,
+ 0x008a, 0x008b, 0x008c, 0x008e, 0x008f, 0x0090, 0x0091, 0x0093,
+ 0x0094, 0x0095, 0x0097, 0x0098, 0x009a, 0x009b, 0x009d, 0x009f,
+ 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a1, 0x00a1, 0x00a2, 0x00a2,
+ 0x00a3, 0x00a4, 0x00a5, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9,
+ 0x00aa, 0x00ab, 0x00ac, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b3,
+ 0x00b4, 0x00b5, 0x00b7, 0x00b8, 0x00ba, 0x00bb, 0x00bd, 0x00bf,
+ 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a1, 0x00a1, 0x00a2, 0x00a2,
+ 0x00a3, 0x00a4, 0x00a5, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9,
+ 0x00aa, 0x00ab, 0x00ac, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b3,
+ 0x00b4, 0x00b5, 0x00b7, 0x00b8, 0x00ba, 0x00bb, 0x00bd, 0x00bf,
+ 0x00c0, 0x00c0, 0x00c0, 0x00c0, 0x00c1, 0x00c1, 0x00c2, 0x00c2,
+ 0x00c3, 0x00c4, 0x00c5, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9,
+ 0x00ca, 0x00cb, 0x00cc, 0x00ce, 0x00cf, 0x00d0, 0x00d1, 0x00d3,
+ 0x00d4, 0x00d5, 0x00d7, 0x00d8, 0x00da, 0x00db, 0x00dd, 0x00df,
+ 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e1, 0x00e1, 0x00e2, 0x00e2,
+ 0x00e3, 0x00e4, 0x00e5, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9,
+ 0x00ea, 0x00eb, 0x00ec, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f3,
+ 0x00f4, 0x00f5, 0x00f7, 0x00f8, 0x00fa, 0x00fb, 0x00fd, 0x00ff,
+ 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e1, 0x00e1, 0x00e2, 0x00e2,
+ 0x00e3, 0x00e4, 0x00e5, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9,
+ 0x00ea, 0x00eb, 0x00ec, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f3,
+ 0x00f4, 0x00f5, 0x00f7, 0x00f8, 0x00fa, 0x00fb, 0x00fd, 0x00ff,
+ 0x0100, 0x0100, 0x0100, 0x0100, 0x0101, 0x0101, 0x0102, 0x0102,
+ 0x0103, 0x0104, 0x0105, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109,
+ 0x010a, 0x010b, 0x010c, 0x010e, 0x010f, 0x0110, 0x0111, 0x0113,
+ 0x0114, 0x0115, 0x0117, 0x0118, 0x011a, 0x011b, 0x011d, 0x011f,
+ 0x0120, 0x0120, 0x0120, 0x0120, 0x0121, 0x0121, 0x0122, 0x0122,
+ 0x0123, 0x0124, 0x0125, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129,
+ 0x012a, 0x012b, 0x012c, 0x012e, 0x012f, 0x0130, 0x0131, 0x0133,
+ 0x0134, 0x0135, 0x0137, 0x0138, 0x013a, 0x013b, 0x013d, 0x013f,
+ 0x0140, 0x0140, 0x0140, 0x0140, 0x0141, 0x0141, 0x0142, 0x0142,
+ 0x0143, 0x0144, 0x0145, 0x0145, 0x0146, 0x0147, 0x0148, 0x0149,
+ 0x014a, 0x014b, 0x014c, 0x014e, 0x014f, 0x0150, 0x0151, 0x0153,
+ 0x0154, 0x0155, 0x0157, 0x0158, 0x015a, 0x015b, 0x015d, 0x015f,
+ 0x0140, 0x0140, 0x0140, 0x0140, 0x0141, 0x0141, 0x0142, 0x0142,
+ 0x0143, 0x0144, 0x0145, 0x0145, 0x0146, 0x0147, 0x0148, 0x0149,
+ 0x014a, 0x014b, 0x014c, 0x014e, 0x014f, 0x0150, 0x0151, 0x0153,
+ 0x0154, 0x0155, 0x0157, 0x0158, 0x015a, 0x015b, 0x015d, 0x015f,
+ 0x0160, 0x0160, 0x0160, 0x0160, 0x0161, 0x0161, 0x0162, 0x0162,
+ 0x0163, 0x0164, 0x0165, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169,
+ 0x016a, 0x016b, 0x016c, 0x016e, 0x016f, 0x0170, 0x0171, 0x0173,
+ 0x0174, 0x0175, 0x0177, 0x0178, 0x017a, 0x017b, 0x017d, 0x017f,
+ 0x0180, 0x0180, 0x0180, 0x0180, 0x0181, 0x0181, 0x0182, 0x0182,
+ 0x0183, 0x0184, 0x0185, 0x0185, 0x0186, 0x0187, 0x0188, 0x0189,
+ 0x018a, 0x018b, 0x018c, 0x018e, 0x018f, 0x0190, 0x0191, 0x0193,
+ 0x0194, 0x0195, 0x0197, 0x0198, 0x019a, 0x019b, 0x019d, 0x019f,
+ 0x01a0, 0x01a0, 0x01a0, 0x01a0, 0x01a1, 0x01a1, 0x01a2, 0x01a2,
+ 0x01a3, 0x01a4, 0x01a5, 0x01a5, 0x01a6, 0x01a7, 0x01a8, 0x01a9,
+ 0x01aa, 0x01ab, 0x01ac, 0x01ae, 0x01af, 0x01b0, 0x01b1, 0x01b3,
+ 0x01b4, 0x01b5, 0x01b7, 0x01b8, 0x01ba, 0x01bb, 0x01bd, 0x01bf,
+ 0x01c0, 0x01c0, 0x01c0, 0x01c0, 0x01c1, 0x01c1, 0x01c2, 0x01c2,
+ 0x01c3, 0x01c4, 0x01c5, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9,
+ 0x01ca, 0x01cb, 0x01cc, 0x01ce, 0x01cf, 0x01d0, 0x01d1, 0x01d3,
+ 0x01d4, 0x01d5, 0x01d7, 0x01d8, 0x01da, 0x01db, 0x01dd, 0x01df,
+ 0x01e0, 0x01e0, 0x01e0, 0x01e0, 0x01e1, 0x01e1, 0x01e2, 0x01e2,
+ 0x01e3, 0x01e4, 0x01e5, 0x01e5, 0x01e6, 0x01e7, 0x01e8, 0x01e9,
+ 0x01ea, 0x01eb, 0x01ec, 0x01ee, 0x01ef, 0x01f0, 0x01f1, 0x01f3,
+ 0x01f4, 0x01f5, 0x01f7, 0x01f8, 0x01fa, 0x01fb, 0x01fd, 0x01ff,
+ 0x0200, 0x0200, 0x0200, 0x0200, 0x0201, 0x0201, 0x0202, 0x0202,
+ 0x0203, 0x0204, 0x0205, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209,
+ 0x020a, 0x020b, 0x020c, 0x020e, 0x020f, 0x0210, 0x0211, 0x0213,
+ 0x0214, 0x0215, 0x0217, 0x0218, 0x021a, 0x021b, 0x021d, 0x021f,
+ 0x0220, 0x0220, 0x0220, 0x0220, 0x0221, 0x0221, 0x0222, 0x0222,
+ 0x0223, 0x0224, 0x0225, 0x0225, 0x0226, 0x0227, 0x0228, 0x0229,
+ 0x022a, 0x022b, 0x022c, 0x022e, 0x022f, 0x0230, 0x0231, 0x0233,
+ 0x0234, 0x0235, 0x0237, 0x0238, 0x023a, 0x023b, 0x023d, 0x023f,
+ 0x0240, 0x0240, 0x0240, 0x0240, 0x0241, 0x0241, 0x0242, 0x0242,
+ 0x0243, 0x0244, 0x0245, 0x0245, 0x0246, 0x0247, 0x0248, 0x0249,
+ 0x024a, 0x024b, 0x024c, 0x024e, 0x024f, 0x0250, 0x0251, 0x0253,
+ 0x0254, 0x0255, 0x0257, 0x0258, 0x025a, 0x025b, 0x025d, 0x025f,
+ 0x0260, 0x0260, 0x0260, 0x0260, 0x0261, 0x0261, 0x0262, 0x0262,
+ 0x0263, 0x0264, 0x0265, 0x0265, 0x0266, 0x0267, 0x0268, 0x0269,
+ 0x026a, 0x026b, 0x026c, 0x026e, 0x026f, 0x0270, 0x0271, 0x0273,
+ 0x0274, 0x0275, 0x0277, 0x0278, 0x027a, 0x027b, 0x027d, 0x027f,
+ 0x0280, 0x0280, 0x0280, 0x0280, 0x0281, 0x0281, 0x0282, 0x0282,
+ 0x0283, 0x0284, 0x0285, 0x0285, 0x0286, 0x0287, 0x0288, 0x0289,
+ 0x028a, 0x028b, 0x028c, 0x028e, 0x028f, 0x0290, 0x0291, 0x0293,
+ 0x0294, 0x0295, 0x0297, 0x0298, 0x029a, 0x029b, 0x029d, 0x029f,
+ 0x02a0, 0x02a0, 0x02a0, 0x02a0, 0x02a1, 0x02a1, 0x02a2, 0x02a2,
+ 0x02a3, 0x02a4, 0x02a5, 0x02a5, 0x02a6, 0x02a7, 0x02a8, 0x02a9,
+ 0x02aa, 0x02ab, 0x02ac, 0x02ae, 0x02af, 0x02b0, 0x02b1, 0x02b3,
+ 0x02b4, 0x02b5, 0x02b7, 0x02b8, 0x02ba, 0x02bb, 0x02bd, 0x02bf,
+ 0x02c0, 0x02c0, 0x02c0, 0x02c0, 0x02c1, 0x02c1, 0x02c2, 0x02c2,
+ 0x02c3, 0x02c4, 0x02c5, 0x02c5, 0x02c6, 0x02c7, 0x02c8, 0x02c9,
+ 0x02ca, 0x02cb, 0x02cc, 0x02ce, 0x02cf, 0x02d0, 0x02d1, 0x02d3,
+ 0x02d4, 0x02d5, 0x02d7, 0x02d8, 0x02da, 0x02db, 0x02dd, 0x02df,
+ 0x02e0, 0x02e0, 0x02e0, 0x02e0, 0x02e1, 0x02e1, 0x02e2, 0x02e2,
+ 0x02e3, 0x02e4, 0x02e5, 0x02e5, 0x02e6, 0x02e7, 0x02e8, 0x02e9,
+ 0x02ea, 0x02eb, 0x02ec, 0x02ee, 0x02ef, 0x02f0, 0x02f1, 0x02f3,
+ 0x02f4, 0x02f5, 0x02f7, 0x02f8, 0x02fa, 0x02fb, 0x02fd, 0x02ff,
+ 0x0300, 0x0300, 0x0300, 0x0300, 0x0301, 0x0301, 0x0302, 0x0302,
+ 0x0303, 0x0304, 0x0305, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309,
+ 0x030a, 0x030b, 0x030c, 0x030e, 0x030f, 0x0310, 0x0311, 0x0313,
+ 0x0314, 0x0315, 0x0317, 0x0318, 0x031a, 0x031b, 0x031d, 0x031f,
+ 0x0320, 0x0320, 0x0320, 0x0320, 0x0321, 0x0321, 0x0322, 0x0322,
+ 0x0323, 0x0324, 0x0325, 0x0325, 0x0326, 0x0327, 0x0328, 0x0329,
+ 0x032a, 0x032b, 0x032c, 0x032e, 0x032f, 0x0330, 0x0331, 0x0333,
+ 0x0334, 0x0335, 0x0337, 0x0338, 0x033a, 0x033b, 0x033d, 0x033f,
+ 0x0340, 0x0340, 0x0340, 0x0340, 0x0341, 0x0341, 0x0342, 0x0342,
+ 0x0343, 0x0344, 0x0345, 0x0345, 0x0346, 0x0347, 0x0348, 0x0349,
+ 0x034a, 0x034b, 0x034c, 0x034e, 0x034f, 0x0350, 0x0351, 0x0353,
+ 0x0354, 0x0355, 0x0357, 0x0358, 0x035a, 0x035b, 0x035d, 0x035f,
+ 0x0380, 0x0380, 0x0380, 0x0380, 0x0381, 0x0381, 0x0382, 0x0382,
+ 0x0383, 0x0384, 0x0385, 0x0385, 0x0386, 0x0387, 0x0388, 0x0389,
+ 0x038a, 0x038b, 0x038c, 0x038e, 0x038f, 0x0390, 0x0391, 0x0393,
+ 0x0394, 0x0395, 0x0397, 0x0398, 0x039a, 0x039b, 0x039d, 0x039f,
+ 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a1, 0x03a1, 0x03a2, 0x03a2,
+ 0x03a3, 0x03a4, 0x03a5, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9,
+ 0x03aa, 0x03ab, 0x03ac, 0x03ae, 0x03af, 0x03b0, 0x03b1, 0x03b3,
+ 0x03b4, 0x03b5, 0x03b7, 0x03b8, 0x03ba, 0x03bb, 0x03bd, 0x03bf,
+ 0x03c0, 0x03c0, 0x03c0, 0x03c0, 0x03c1, 0x03c1, 0x03c2, 0x03c2,
+ 0x03c3, 0x03c4, 0x03c5, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9,
+ 0x03ca, 0x03cb, 0x03cc, 0x03ce, 0x03cf, 0x03d0, 0x03d1, 0x03d3,
+ 0x03d4, 0x03d5, 0x03d7, 0x03d8, 0x03da, 0x03db, 0x03dd, 0x03df,
+ 0x03e0, 0x03e0, 0x03e0, 0x03e0, 0x03e1, 0x03e1, 0x03e2, 0x03e2,
+ 0x03e3, 0x03e4, 0x03e5, 0x03e5, 0x03e6, 0x03e7, 0x03e8, 0x03e9,
+ 0x03ea, 0x03eb, 0x03ec, 0x03ee, 0x03ef, 0x03f0, 0x03f1, 0x03f3,
+ 0x03f4, 0x03f5, 0x03f7, 0x03f8, 0x03fa, 0x03fb, 0x03fd, 0x03ff,
+ 0x0400, 0x0400, 0x0400, 0x0400, 0x0401, 0x0401, 0x0402, 0x0402,
+ 0x0403, 0x0404, 0x0405, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409,
+ 0x040a, 0x040b, 0x040c, 0x040e, 0x040f, 0x0410, 0x0411, 0x0413,
+ 0x0414, 0x0415, 0x0417, 0x0418, 0x041a, 0x041b, 0x041d, 0x041f,
+ 0x0440, 0x0440, 0x0440, 0x0440, 0x0441, 0x0441, 0x0442, 0x0442,
+ 0x0443, 0x0444, 0x0445, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
+ 0x044a, 0x044b, 0x044c, 0x044e, 0x044f, 0x0450, 0x0451, 0x0453,
+ 0x0454, 0x0455, 0x0457, 0x0458, 0x045a, 0x045b, 0x045d, 0x045f,
+ 0x0460, 0x0460, 0x0460, 0x0460, 0x0461, 0x0461, 0x0462, 0x0462,
+ 0x0463, 0x0464, 0x0465, 0x0465, 0x0466, 0x0467, 0x0468, 0x0469,
+ 0x046a, 0x046b, 0x046c, 0x046e, 0x046f, 0x0470, 0x0471, 0x0473,
+ 0x0474, 0x0475, 0x0477, 0x0478, 0x047a, 0x047b, 0x047d, 0x047f,
+ 0x0480, 0x0480, 0x0480, 0x0480, 0x0481, 0x0481, 0x0482, 0x0482,
+ 0x0483, 0x0484, 0x0485, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489,
+ 0x048a, 0x048b, 0x048c, 0x048e, 0x048f, 0x0490, 0x0491, 0x0493,
+ 0x0494, 0x0495, 0x0497, 0x0498, 0x049a, 0x049b, 0x049d, 0x049f,
+ 0x04c0, 0x04c0, 0x04c0, 0x04c0, 0x04c1, 0x04c1, 0x04c2, 0x04c2,
+ 0x04c3, 0x04c4, 0x04c5, 0x04c5, 0x04c6, 0x04c7, 0x04c8, 0x04c9,
+ 0x04ca, 0x04cb, 0x04cc, 0x04ce, 0x04cf, 0x04d0, 0x04d1, 0x04d3,
+ 0x04d4, 0x04d5, 0x04d7, 0x04d8, 0x04da, 0x04db, 0x04dd, 0x04df,
+ 0x04e0, 0x04e0, 0x04e0, 0x04e0, 0x04e1, 0x04e1, 0x04e2, 0x04e2,
+ 0x04e3, 0x04e4, 0x04e5, 0x04e5, 0x04e6, 0x04e7, 0x04e8, 0x04e9,
+ 0x04ea, 0x04eb, 0x04ec, 0x04ee, 0x04ef, 0x04f0, 0x04f1, 0x04f3,
+ 0x04f4, 0x04f5, 0x04f7, 0x04f8, 0x04fa, 0x04fb, 0x04fd, 0x04ff,
+ 0x0500, 0x0500, 0x0500, 0x0500, 0x0501, 0x0501, 0x0502, 0x0502,
+ 0x0503, 0x0504, 0x0505, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509,
+ 0x050a, 0x050b, 0x050c, 0x050e, 0x050f, 0x0510, 0x0511, 0x0513,
+ 0x0514, 0x0515, 0x0517, 0x0518, 0x051a, 0x051b, 0x051d, 0x051f,
+ 0x0540, 0x0540, 0x0540, 0x0540, 0x0541, 0x0541, 0x0542, 0x0542,
+ 0x0543, 0x0544, 0x0545, 0x0545, 0x0546, 0x0547, 0x0548, 0x0549,
+ 0x054a, 0x054b, 0x054c, 0x054e, 0x054f, 0x0550, 0x0551, 0x0553,
+ 0x0554, 0x0555, 0x0557, 0x0558, 0x055a, 0x055b, 0x055d, 0x055f,
+ 0x0560, 0x0560, 0x0560, 0x0560, 0x0561, 0x0561, 0x0562, 0x0562,
+ 0x0563, 0x0564, 0x0565, 0x0565, 0x0566, 0x0567, 0x0568, 0x0569,
+ 0x056a, 0x056b, 0x056c, 0x056e, 0x056f, 0x0570, 0x0571, 0x0573,
+ 0x0574, 0x0575, 0x0577, 0x0578, 0x057a, 0x057b, 0x057d, 0x057f,
+ 0x0580, 0x0580, 0x0580, 0x0580, 0x0581, 0x0581, 0x0582, 0x0582,
+ 0x0583, 0x0584, 0x0585, 0x0585, 0x0586, 0x0587, 0x0588, 0x0589,
+ 0x058a, 0x058b, 0x058c, 0x058e, 0x058f, 0x0590, 0x0591, 0x0593,
+ 0x0594, 0x0595, 0x0597, 0x0598, 0x059a, 0x059b, 0x059d, 0x059f,
+ 0x05c0, 0x05c0, 0x05c0, 0x05c0, 0x05c1, 0x05c1, 0x05c2, 0x05c2,
+ 0x05c3, 0x05c4, 0x05c5, 0x05c5, 0x05c6, 0x05c7, 0x05c8, 0x05c9,
+ 0x05ca, 0x05cb, 0x05cc, 0x05ce, 0x05cf, 0x05d0, 0x05d1, 0x05d3,
+ 0x05d4, 0x05d5, 0x05d7, 0x05d8, 0x05da, 0x05db, 0x05dd, 0x05df,
+ 0x05e0, 0x05e0, 0x05e0, 0x05e0, 0x05e1, 0x05e1, 0x05e2, 0x05e2,
+ 0x05e3, 0x05e4, 0x05e5, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9,
+ 0x05ea, 0x05eb, 0x05ec, 0x05ee, 0x05ef, 0x05f0, 0x05f1, 0x05f3,
+ 0x05f4, 0x05f5, 0x05f7, 0x05f8, 0x05fa, 0x05fb, 0x05fd, 0x05ff,
+ 0x0620, 0x0620, 0x0620, 0x0620, 0x0621, 0x0621, 0x0622, 0x0622,
+ 0x0623, 0x0624, 0x0625, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629,
+ 0x062a, 0x062b, 0x062c, 0x062e, 0x062f, 0x0630, 0x0631, 0x0633,
+ 0x0634, 0x0635, 0x0637, 0x0638, 0x063a, 0x063b, 0x063d, 0x063f,
+ 0x0640, 0x0640, 0x0640, 0x0640, 0x0641, 0x0641, 0x0642, 0x0642,
+ 0x0643, 0x0644, 0x0645, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649,
+ 0x064a, 0x064b, 0x064c, 0x064e, 0x064f, 0x0650, 0x0651, 0x0653,
+ 0x0654, 0x0655, 0x0657, 0x0658, 0x065a, 0x065b, 0x065d, 0x065f,
+ 0x0680, 0x0680, 0x0680, 0x0680, 0x0681, 0x0681, 0x0682, 0x0682,
+ 0x0683, 0x0684, 0x0685, 0x0685, 0x0686, 0x0687, 0x0688, 0x0689,
+ 0x068a, 0x068b, 0x068c, 0x068e, 0x068f, 0x0690, 0x0691, 0x0693,
+ 0x0694, 0x0695, 0x0697, 0x0698, 0x069a, 0x069b, 0x069d, 0x069f,
+ 0x06a0, 0x06a0, 0x06a0, 0x06a0, 0x06a1, 0x06a1, 0x06a2, 0x06a2,
+ 0x06a3, 0x06a4, 0x06a5, 0x06a5, 0x06a6, 0x06a7, 0x06a8, 0x06a9,
+ 0x06aa, 0x06ab, 0x06ac, 0x06ae, 0x06af, 0x06b0, 0x06b1, 0x06b3,
+ 0x06b4, 0x06b5, 0x06b7, 0x06b8, 0x06ba, 0x06bb, 0x06bd, 0x06bf,
+ 0x06e0, 0x06e0, 0x06e0, 0x06e0, 0x06e1, 0x06e1, 0x06e2, 0x06e2,
+ 0x06e3, 0x06e4, 0x06e5, 0x06e5, 0x06e6, 0x06e7, 0x06e8, 0x06e9,
+ 0x06ea, 0x06eb, 0x06ec, 0x06ee, 0x06ef, 0x06f0, 0x06f1, 0x06f3,
+ 0x06f4, 0x06f5, 0x06f7, 0x06f8, 0x06fa, 0x06fb, 0x06fd, 0x06ff,
+ 0x0700, 0x0700, 0x0700, 0x0700, 0x0701, 0x0701, 0x0702, 0x0702,
+ 0x0703, 0x0704, 0x0705, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709,
+ 0x070a, 0x070b, 0x070c, 0x070e, 0x070f, 0x0710, 0x0711, 0x0713,
+ 0x0714, 0x0715, 0x0717, 0x0718, 0x071a, 0x071b, 0x071d, 0x071f,
+ 0x0740, 0x0740, 0x0740, 0x0740, 0x0741, 0x0741, 0x0742, 0x0742,
+ 0x0743, 0x0744, 0x0745, 0x0745, 0x0746, 0x0747, 0x0748, 0x0749,
+ 0x074a, 0x074b, 0x074c, 0x074e, 0x074f, 0x0750, 0x0751, 0x0753,
+ 0x0754, 0x0755, 0x0757, 0x0758, 0x075a, 0x075b, 0x075d, 0x075f,
+ 0x0760, 0x0760, 0x0760, 0x0760, 0x0761, 0x0761, 0x0762, 0x0762,
+ 0x0763, 0x0764, 0x0765, 0x0765, 0x0766, 0x0767, 0x0768, 0x0769,
+ 0x076a, 0x076b, 0x076c, 0x076e, 0x076f, 0x0770, 0x0771, 0x0773,
+ 0x0774, 0x0775, 0x0777, 0x0778, 0x077a, 0x077b, 0x077d, 0x077f,
+ 0x07a0, 0x07a0, 0x07a0, 0x07a0, 0x07a1, 0x07a1, 0x07a2, 0x07a2,
+ 0x07a3, 0x07a4, 0x07a5, 0x07a5, 0x07a6, 0x07a7, 0x07a8, 0x07a9,
+ 0x07aa, 0x07ab, 0x07ac, 0x07ae, 0x07af, 0x07b0, 0x07b1, 0x07b3,
+ 0x07b4, 0x07b5, 0x07b7, 0x07b8, 0x07ba, 0x07bb, 0x07bd, 0x07bf,
+ 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e1, 0x07e1, 0x07e2, 0x07e2,
+ 0x07e3, 0x07e4, 0x07e5, 0x07e5, 0x07e6, 0x07e7, 0x07e8, 0x07e9,
+ 0x07ea, 0x07eb, 0x07ec, 0x07ee, 0x07ef, 0x07f0, 0x07f1, 0x07f3,
+ 0x07f4, 0x07f5, 0x07f7, 0x07f8, 0x07fa, 0x07fb, 0x07fd, 0x07ff,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0021, 0x0021, 0x0022, 0x0022,
+ 0x0023, 0x0024, 0x0025, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002a, 0x002b, 0x002c, 0x002e, 0x002f, 0x0030, 0x0031, 0x0033,
+ 0x0034, 0x0035, 0x0037, 0x0038, 0x003a, 0x003b, 0x003d, 0x003f,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0021, 0x0021, 0x0022, 0x0022,
+ 0x0023, 0x0024, 0x0025, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002a, 0x002b, 0x002c, 0x002e, 0x002f, 0x0030, 0x0031, 0x0033,
+ 0x0034, 0x0035, 0x0037, 0x0038, 0x003a, 0x003b, 0x003d, 0x003f,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0021, 0x0021, 0x0022, 0x0022,
+ 0x0023, 0x0024, 0x0025, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002a, 0x002b, 0x002c, 0x002e, 0x002f, 0x0030, 0x0031, 0x0033,
+ 0x0034, 0x0035, 0x0037, 0x0038, 0x003a, 0x003b, 0x003d, 0x003f,
+ 0x0040, 0x0040, 0x0040, 0x0040, 0x0041, 0x0041, 0x0042, 0x0042,
+ 0x0043, 0x0044, 0x0045, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049,
+ 0x004a, 0x004b, 0x004c, 0x004e, 0x004f, 0x0050, 0x0051, 0x0053,
+ 0x0054, 0x0055, 0x0057, 0x0058, 0x005a, 0x005b, 0x005d, 0x005f,
+ 0x0040, 0x0040, 0x0040, 0x0040, 0x0041, 0x0041, 0x0042, 0x0042,
+ 0x0043, 0x0044, 0x0045, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049,
+ 0x004a, 0x004b, 0x004c, 0x004e, 0x004f, 0x0050, 0x0051, 0x0053,
+ 0x0054, 0x0055, 0x0057, 0x0058, 0x005a, 0x005b, 0x005d, 0x005f,
+ 0x0060, 0x0060, 0x0060, 0x0060, 0x0061, 0x0061, 0x0062, 0x0062,
+ 0x0063, 0x0064, 0x0065, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
+ 0x006a, 0x006b, 0x006c, 0x006e, 0x006f, 0x0070, 0x0071, 0x0073,
+ 0x0074, 0x0075, 0x0077, 0x0078, 0x007a, 0x007b, 0x007d, 0x007f,
+ 0x0060, 0x0060, 0x0060, 0x0060, 0x0061, 0x0061, 0x0062, 0x0062,
+ 0x0063, 0x0064, 0x0065, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
+ 0x006a, 0x006b, 0x006c, 0x006e, 0x006f, 0x0070, 0x0071, 0x0073,
+ 0x0074, 0x0075, 0x0077, 0x0078, 0x007a, 0x007b, 0x007d, 0x007f,
+ 0x0080, 0x0080, 0x0080, 0x0080, 0x0081, 0x0081, 0x0082, 0x0082,
+ 0x0083, 0x0084, 0x0085, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089,
+ 0x008a, 0x008b, 0x008c, 0x008e, 0x008f, 0x0090, 0x0091, 0x0093,
+ 0x0094, 0x0095, 0x0097, 0x0098, 0x009a, 0x009b, 0x009d, 0x009f,
+ 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a1, 0x00a1, 0x00a2, 0x00a2,
+ 0x00a3, 0x00a4, 0x00a5, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9,
+ 0x00aa, 0x00ab, 0x00ac, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b3,
+ 0x00b4, 0x00b5, 0x00b7, 0x00b8, 0x00ba, 0x00bb, 0x00bd, 0x00bf,
+ 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a1, 0x00a1, 0x00a2, 0x00a2,
+ 0x00a3, 0x00a4, 0x00a5, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9,
+ 0x00aa, 0x00ab, 0x00ac, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b3,
+ 0x00b4, 0x00b5, 0x00b7, 0x00b8, 0x00ba, 0x00bb, 0x00bd, 0x00bf,
+ 0x00c0, 0x00c0, 0x00c0, 0x00c0, 0x00c1, 0x00c1, 0x00c2, 0x00c2,
+ 0x00c3, 0x00c4, 0x00c5, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9,
+ 0x00ca, 0x00cb, 0x00cc, 0x00ce, 0x00cf, 0x00d0, 0x00d1, 0x00d3,
+ 0x00d4, 0x00d5, 0x00d7, 0x00d8, 0x00da, 0x00db, 0x00dd, 0x00df,
+ 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e1, 0x00e1, 0x00e2, 0x00e2,
+ 0x00e3, 0x00e4, 0x00e5, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9,
+ 0x00ea, 0x00eb, 0x00ec, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f3,
+ 0x00f4, 0x00f5, 0x00f7, 0x00f8, 0x00fa, 0x00fb, 0x00fd, 0x00ff,
+ 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e1, 0x00e1, 0x00e2, 0x00e2,
+ 0x00e3, 0x00e4, 0x00e5, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9,
+ 0x00ea, 0x00eb, 0x00ec, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f3,
+ 0x00f4, 0x00f5, 0x00f7, 0x00f8, 0x00fa, 0x00fb, 0x00fd, 0x00ff,
+ 0x0100, 0x0100, 0x0100, 0x0100, 0x0101, 0x0101, 0x0102, 0x0102,
+ 0x0103, 0x0104, 0x0105, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109,
+ 0x010a, 0x010b, 0x010c, 0x010e, 0x010f, 0x0110, 0x0111, 0x0113,
+ 0x0114, 0x0115, 0x0117, 0x0118, 0x011a, 0x011b, 0x011d, 0x011f,
+ 0x0120, 0x0120, 0x0120, 0x0120, 0x0121, 0x0121, 0x0122, 0x0122,
+ 0x0123, 0x0124, 0x0125, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129,
+ 0x012a, 0x012b, 0x012c, 0x012e, 0x012f, 0x0130, 0x0131, 0x0133,
+ 0x0134, 0x0135, 0x0137, 0x0138, 0x013a, 0x013b, 0x013d, 0x013f,
+ 0x0140, 0x0140, 0x0140, 0x0140, 0x0141, 0x0141, 0x0142, 0x0142,
+ 0x0143, 0x0144, 0x0145, 0x0145, 0x0146, 0x0147, 0x0148, 0x0149,
+ 0x014a, 0x014b, 0x014c, 0x014e, 0x014f, 0x0150, 0x0151, 0x0153,
+ 0x0154, 0x0155, 0x0157, 0x0158, 0x015a, 0x015b, 0x015d, 0x015f,
+ 0x0140, 0x0140, 0x0140, 0x0140, 0x0141, 0x0141, 0x0142, 0x0142,
+ 0x0143, 0x0144, 0x0145, 0x0145, 0x0146, 0x0147, 0x0148, 0x0149,
+ 0x014a, 0x014b, 0x014c, 0x014e, 0x014f, 0x0150, 0x0151, 0x0153,
+ 0x0154, 0x0155, 0x0157, 0x0158, 0x015a, 0x015b, 0x015d, 0x015f,
+ 0x0160, 0x0160, 0x0160, 0x0160, 0x0161, 0x0161, 0x0162, 0x0162,
+ 0x0163, 0x0164, 0x0165, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169,
+ 0x016a, 0x016b, 0x016c, 0x016e, 0x016f, 0x0170, 0x0171, 0x0173,
+ 0x0174, 0x0175, 0x0177, 0x0178, 0x017a, 0x017b, 0x017d, 0x017f,
+ 0x0180, 0x0180, 0x0180, 0x0180, 0x0181, 0x0181, 0x0182, 0x0182,
+ 0x0183, 0x0184, 0x0185, 0x0185, 0x0186, 0x0187, 0x0188, 0x0189,
+ 0x018a, 0x018b, 0x018c, 0x018e, 0x018f, 0x0190, 0x0191, 0x0193,
+ 0x0194, 0x0195, 0x0197, 0x0198, 0x019a, 0x019b, 0x019d, 0x019f,
+ 0x01a0, 0x01a0, 0x01a0, 0x01a0, 0x01a1, 0x01a1, 0x01a2, 0x01a2,
+ 0x01a3, 0x01a4, 0x01a5, 0x01a5, 0x01a6, 0x01a7, 0x01a8, 0x01a9,
+ 0x01aa, 0x01ab, 0x01ac, 0x01ae, 0x01af, 0x01b0, 0x01b1, 0x01b3,
+ 0x01b4, 0x01b5, 0x01b7, 0x01b8, 0x01ba, 0x01bb, 0x01bd, 0x01bf,
+ 0x01c0, 0x01c0, 0x01c0, 0x01c0, 0x01c1, 0x01c1, 0x01c2, 0x01c2,
+ 0x01c3, 0x01c4, 0x01c5, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9,
+ 0x01ca, 0x01cb, 0x01cc, 0x01ce, 0x01cf, 0x01d0, 0x01d1, 0x01d3,
+ 0x01d4, 0x01d5, 0x01d7, 0x01d8, 0x01da, 0x01db, 0x01dd, 0x01df,
+ 0x01e0, 0x01e0, 0x01e0, 0x01e0, 0x01e1, 0x01e1, 0x01e2, 0x01e2,
+ 0x01e3, 0x01e4, 0x01e5, 0x01e5, 0x01e6, 0x01e7, 0x01e8, 0x01e9,
+ 0x01ea, 0x01eb, 0x01ec, 0x01ee, 0x01ef, 0x01f0, 0x01f1, 0x01f3,
+ 0x01f4, 0x01f5, 0x01f7, 0x01f8, 0x01fa, 0x01fb, 0x01fd, 0x01ff,
+ 0x0200, 0x0200, 0x0200, 0x0200, 0x0201, 0x0201, 0x0202, 0x0202,
+ 0x0203, 0x0204, 0x0205, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209,
+ 0x020a, 0x020b, 0x020c, 0x020e, 0x020f, 0x0210, 0x0211, 0x0213,
+ 0x0214, 0x0215, 0x0217, 0x0218, 0x021a, 0x021b, 0x021d, 0x021f,
+ 0x0220, 0x0220, 0x0220, 0x0220, 0x0221, 0x0221, 0x0222, 0x0222,
+ 0x0223, 0x0224, 0x0225, 0x0225, 0x0226, 0x0227, 0x0228, 0x0229,
+ 0x022a, 0x022b, 0x022c, 0x022e, 0x022f, 0x0230, 0x0231, 0x0233,
+ 0x0234, 0x0235, 0x0237, 0x0238, 0x023a, 0x023b, 0x023d, 0x023f,
+ 0x0240, 0x0240, 0x0240, 0x0240, 0x0241, 0x0241, 0x0242, 0x0242,
+ 0x0243, 0x0244, 0x0245, 0x0245, 0x0246, 0x0247, 0x0248, 0x0249,
+ 0x024a, 0x024b, 0x024c, 0x024e, 0x024f, 0x0250, 0x0251, 0x0253,
+ 0x0254, 0x0255, 0x0257, 0x0258, 0x025a, 0x025b, 0x025d, 0x025f,
+ 0x0260, 0x0260, 0x0260, 0x0260, 0x0261, 0x0261, 0x0262, 0x0262,
+ 0x0263, 0x0264, 0x0265, 0x0265, 0x0266, 0x0267, 0x0268, 0x0269,
+ 0x026a, 0x026b, 0x026c, 0x026e, 0x026f, 0x0270, 0x0271, 0x0273,
+ 0x0274, 0x0275, 0x0277, 0x0278, 0x027a, 0x027b, 0x027d, 0x027f,
+ 0x0280, 0x0280, 0x0280, 0x0280, 0x0281, 0x0281, 0x0282, 0x0282,
+ 0x0283, 0x0284, 0x0285, 0x0285, 0x0286, 0x0287, 0x0288, 0x0289,
+ 0x028a, 0x028b, 0x028c, 0x028e, 0x028f, 0x0290, 0x0291, 0x0293,
+ 0x0294, 0x0295, 0x0297, 0x0298, 0x029a, 0x029b, 0x029d, 0x029f,
+ 0x02a0, 0x02a0, 0x02a0, 0x02a0, 0x02a1, 0x02a1, 0x02a2, 0x02a2,
+ 0x02a3, 0x02a4, 0x02a5, 0x02a5, 0x02a6, 0x02a7, 0x02a8, 0x02a9,
+ 0x02aa, 0x02ab, 0x02ac, 0x02ae, 0x02af, 0x02b0, 0x02b1, 0x02b3,
+ 0x02b4, 0x02b5, 0x02b7, 0x02b8, 0x02ba, 0x02bb, 0x02bd, 0x02bf,
+ 0x02c0, 0x02c0, 0x02c0, 0x02c0, 0x02c1, 0x02c1, 0x02c2, 0x02c2,
+ 0x02c3, 0x02c4, 0x02c5, 0x02c5, 0x02c6, 0x02c7, 0x02c8, 0x02c9,
+ 0x02ca, 0x02cb, 0x02cc, 0x02ce, 0x02cf, 0x02d0, 0x02d1, 0x02d3,
+ 0x02d4, 0x02d5, 0x02d7, 0x02d8, 0x02da, 0x02db, 0x02dd, 0x02df,
+ 0x02e0, 0x02e0, 0x02e0, 0x02e0, 0x02e1, 0x02e1, 0x02e2, 0x02e2,
+ 0x02e3, 0x02e4, 0x02e5, 0x02e5, 0x02e6, 0x02e7, 0x02e8, 0x02e9,
+ 0x02ea, 0x02eb, 0x02ec, 0x02ee, 0x02ef, 0x02f0, 0x02f1, 0x02f3,
+ 0x02f4, 0x02f5, 0x02f7, 0x02f8, 0x02fa, 0x02fb, 0x02fd, 0x02ff,
+ 0x0300, 0x0300, 0x0300, 0x0300, 0x0301, 0x0301, 0x0302, 0x0302,
+ 0x0303, 0x0304, 0x0305, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309,
+ 0x030a, 0x030b, 0x030c, 0x030e, 0x030f, 0x0310, 0x0311, 0x0313,
+ 0x0314, 0x0315, 0x0317, 0x0318, 0x031a, 0x031b, 0x031d, 0x031f,
+ 0x0320, 0x0320, 0x0320, 0x0320, 0x0321, 0x0321, 0x0322, 0x0322,
+ 0x0323, 0x0324, 0x0325, 0x0325, 0x0326, 0x0327, 0x0328, 0x0329,
+ 0x032a, 0x032b, 0x032c, 0x032e, 0x032f, 0x0330, 0x0331, 0x0333,
+ 0x0334, 0x0335, 0x0337, 0x0338, 0x033a, 0x033b, 0x033d, 0x033f,
+ 0x0340, 0x0340, 0x0340, 0x0340, 0x0341, 0x0341, 0x0342, 0x0342,
+ 0x0343, 0x0344, 0x0345, 0x0345, 0x0346, 0x0347, 0x0348, 0x0349,
+ 0x034a, 0x034b, 0x034c, 0x034e, 0x034f, 0x0350, 0x0351, 0x0353,
+ 0x0354, 0x0355, 0x0357, 0x0358, 0x035a, 0x035b, 0x035d, 0x035f,
+ 0x0380, 0x0380, 0x0380, 0x0380, 0x0381, 0x0381, 0x0382, 0x0382,
+ 0x0383, 0x0384, 0x0385, 0x0385, 0x0386, 0x0387, 0x0388, 0x0389,
+ 0x038a, 0x038b, 0x038c, 0x038e, 0x038f, 0x0390, 0x0391, 0x0393,
+ 0x0394, 0x0395, 0x0397, 0x0398, 0x039a, 0x039b, 0x039d, 0x039f,
+ 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a1, 0x03a1, 0x03a2, 0x03a2,
+ 0x03a3, 0x03a4, 0x03a5, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9,
+ 0x03aa, 0x03ab, 0x03ac, 0x03ae, 0x03af, 0x03b0, 0x03b1, 0x03b3,
+ 0x03b4, 0x03b5, 0x03b7, 0x03b8, 0x03ba, 0x03bb, 0x03bd, 0x03bf,
+ 0x03c0, 0x03c0, 0x03c0, 0x03c0, 0x03c1, 0x03c1, 0x03c2, 0x03c2,
+ 0x03c3, 0x03c4, 0x03c5, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9,
+ 0x03ca, 0x03cb, 0x03cc, 0x03ce, 0x03cf, 0x03d0, 0x03d1, 0x03d3,
+ 0x03d4, 0x03d5, 0x03d7, 0x03d8, 0x03da, 0x03db, 0x03dd, 0x03df,
+ 0x03e0, 0x03e0, 0x03e0, 0x03e0, 0x03e1, 0x03e1, 0x03e2, 0x03e2,
+ 0x03e3, 0x03e4, 0x03e5, 0x03e5, 0x03e6, 0x03e7, 0x03e8, 0x03e9,
+ 0x03ea, 0x03eb, 0x03ec, 0x03ee, 0x03ef, 0x03f0, 0x03f1, 0x03f3,
+ 0x03f4, 0x03f5, 0x03f7, 0x03f8, 0x03fa, 0x03fb, 0x03fd, 0x03ff,
+ 0x0400, 0x0400, 0x0400, 0x0400, 0x0401, 0x0401, 0x0402, 0x0402,
+ 0x0403, 0x0404, 0x0405, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409,
+ 0x040a, 0x040b, 0x040c, 0x040e, 0x040f, 0x0410, 0x0411, 0x0413,
+ 0x0414, 0x0415, 0x0417, 0x0418, 0x041a, 0x041b, 0x041d, 0x041f,
+ 0x0440, 0x0440, 0x0440, 0x0440, 0x0441, 0x0441, 0x0442, 0x0442,
+ 0x0443, 0x0444, 0x0445, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
+ 0x044a, 0x044b, 0x044c, 0x044e, 0x044f, 0x0450, 0x0451, 0x0453,
+ 0x0454, 0x0455, 0x0457, 0x0458, 0x045a, 0x045b, 0x045d, 0x045f,
+ 0x0460, 0x0460, 0x0460, 0x0460, 0x0461, 0x0461, 0x0462, 0x0462,
+ 0x0463, 0x0464, 0x0465, 0x0465, 0x0466, 0x0467, 0x0468, 0x0469,
+ 0x046a, 0x046b, 0x046c, 0x046e, 0x046f, 0x0470, 0x0471, 0x0473,
+ 0x0474, 0x0475, 0x0477, 0x0478, 0x047a, 0x047b, 0x047d, 0x047f,
+ 0x0480, 0x0480, 0x0480, 0x0480, 0x0481, 0x0481, 0x0482, 0x0482,
+ 0x0483, 0x0484, 0x0485, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489,
+ 0x048a, 0x048b, 0x048c, 0x048e, 0x048f, 0x0490, 0x0491, 0x0493,
+ 0x0494, 0x0495, 0x0497, 0x0498, 0x049a, 0x049b, 0x049d, 0x049f,
+ 0x04c0, 0x04c0, 0x04c0, 0x04c0, 0x04c1, 0x04c1, 0x04c2, 0x04c2,
+ 0x04c3, 0x04c4, 0x04c5, 0x04c5, 0x04c6, 0x04c7, 0x04c8, 0x04c9,
+ 0x04ca, 0x04cb, 0x04cc, 0x04ce, 0x04cf, 0x04d0, 0x04d1, 0x04d3,
+ 0x04d4, 0x04d5, 0x04d7, 0x04d8, 0x04da, 0x04db, 0x04dd, 0x04df,
+ 0x04e0, 0x04e0, 0x04e0, 0x04e0, 0x04e1, 0x04e1, 0x04e2, 0x04e2,
+ 0x04e3, 0x04e4, 0x04e5, 0x04e5, 0x04e6, 0x04e7, 0x04e8, 0x04e9,
+ 0x04ea, 0x04eb, 0x04ec, 0x04ee, 0x04ef, 0x04f0, 0x04f1, 0x04f3,
+ 0x04f4, 0x04f5, 0x04f7, 0x04f8, 0x04fa, 0x04fb, 0x04fd, 0x04ff,
+ 0x0500, 0x0500, 0x0500, 0x0500, 0x0501, 0x0501, 0x0502, 0x0502,
+ 0x0503, 0x0504, 0x0505, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509,
+ 0x050a, 0x050b, 0x050c, 0x050e, 0x050f, 0x0510, 0x0511, 0x0513,
+ 0x0514, 0x0515, 0x0517, 0x0518, 0x051a, 0x051b, 0x051d, 0x051f,
+ 0x0540, 0x0540, 0x0540, 0x0540, 0x0541, 0x0541, 0x0542, 0x0542,
+ 0x0543, 0x0544, 0x0545, 0x0545, 0x0546, 0x0547, 0x0548, 0x0549,
+ 0x054a, 0x054b, 0x054c, 0x054e, 0x054f, 0x0550, 0x0551, 0x0553,
+ 0x0554, 0x0555, 0x0557, 0x0558, 0x055a, 0x055b, 0x055d, 0x055f,
+ 0x0560, 0x0560, 0x0560, 0x0560, 0x0561, 0x0561, 0x0562, 0x0562,
+ 0x0563, 0x0564, 0x0565, 0x0565, 0x0566, 0x0567, 0x0568, 0x0569,
+ 0x056a, 0x056b, 0x056c, 0x056e, 0x056f, 0x0570, 0x0571, 0x0573,
+ 0x0574, 0x0575, 0x0577, 0x0578, 0x057a, 0x057b, 0x057d, 0x057f,
+ 0x0580, 0x0580, 0x0580, 0x0580, 0x0581, 0x0581, 0x0582, 0x0582,
+ 0x0583, 0x0584, 0x0585, 0x0585, 0x0586, 0x0587, 0x0588, 0x0589,
+ 0x058a, 0x058b, 0x058c, 0x058e, 0x058f, 0x0590, 0x0591, 0x0593,
+ 0x0594, 0x0595, 0x0597, 0x0598, 0x059a, 0x059b, 0x059d, 0x059f,
+ 0x05c0, 0x05c0, 0x05c0, 0x05c0, 0x05c1, 0x05c1, 0x05c2, 0x05c2,
+ 0x05c3, 0x05c4, 0x05c5, 0x05c5, 0x05c6, 0x05c7, 0x05c8, 0x05c9,
+ 0x05ca, 0x05cb, 0x05cc, 0x05ce, 0x05cf, 0x05d0, 0x05d1, 0x05d3,
+ 0x05d4, 0x05d5, 0x05d7, 0x05d8, 0x05da, 0x05db, 0x05dd, 0x05df,
+ 0x05e0, 0x05e0, 0x05e0, 0x05e0, 0x05e1, 0x05e1, 0x05e2, 0x05e2,
+ 0x05e3, 0x05e4, 0x05e5, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9,
+ 0x05ea, 0x05eb, 0x05ec, 0x05ee, 0x05ef, 0x05f0, 0x05f1, 0x05f3,
+ 0x05f4, 0x05f5, 0x05f7, 0x05f8, 0x05fa, 0x05fb, 0x05fd, 0x05ff,
+ 0x0620, 0x0620, 0x0620, 0x0620, 0x0621, 0x0621, 0x0622, 0x0622,
+ 0x0623, 0x0624, 0x0625, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629,
+ 0x062a, 0x062b, 0x062c, 0x062e, 0x062f, 0x0630, 0x0631, 0x0633,
+ 0x0634, 0x0635, 0x0637, 0x0638, 0x063a, 0x063b, 0x063d, 0x063f,
+ 0x0640, 0x0640, 0x0640, 0x0640, 0x0641, 0x0641, 0x0642, 0x0642,
+ 0x0643, 0x0644, 0x0645, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649,
+ 0x064a, 0x064b, 0x064c, 0x064e, 0x064f, 0x0650, 0x0651, 0x0653,
+ 0x0654, 0x0655, 0x0657, 0x0658, 0x065a, 0x065b, 0x065d, 0x065f,
+ 0x0680, 0x0680, 0x0680, 0x0680, 0x0681, 0x0681, 0x0682, 0x0682,
+ 0x0683, 0x0684, 0x0685, 0x0685, 0x0686, 0x0687, 0x0688, 0x0689,
+ 0x068a, 0x068b, 0x068c, 0x068e, 0x068f, 0x0690, 0x0691, 0x0693,
+ 0x0694, 0x0695, 0x0697, 0x0698, 0x069a, 0x069b, 0x069d, 0x069f,
+ 0x06a0, 0x06a0, 0x06a0, 0x06a0, 0x06a1, 0x06a1, 0x06a2, 0x06a2,
+ 0x06a3, 0x06a4, 0x06a5, 0x06a5, 0x06a6, 0x06a7, 0x06a8, 0x06a9,
+ 0x06aa, 0x06ab, 0x06ac, 0x06ae, 0x06af, 0x06b0, 0x06b1, 0x06b3,
+ 0x06b4, 0x06b5, 0x06b7, 0x06b8, 0x06ba, 0x06bb, 0x06bd, 0x06bf,
+ 0x06e0, 0x06e0, 0x06e0, 0x06e0, 0x06e1, 0x06e1, 0x06e2, 0x06e2,
+ 0x06e3, 0x06e4, 0x06e5, 0x06e5, 0x06e6, 0x06e7, 0x06e8, 0x06e9,
+ 0x06ea, 0x06eb, 0x06ec, 0x06ee, 0x06ef, 0x06f0, 0x06f1, 0x06f3,
+ 0x06f4, 0x06f5, 0x06f7, 0x06f8, 0x06fa, 0x06fb, 0x06fd, 0x06ff,
+ 0x0700, 0x0700, 0x0700, 0x0700, 0x0701, 0x0701, 0x0702, 0x0702,
+ 0x0703, 0x0704, 0x0705, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709,
+ 0x070a, 0x070b, 0x070c, 0x070e, 0x070f, 0x0710, 0x0711, 0x0713,
+ 0x0714, 0x0715, 0x0717, 0x0718, 0x071a, 0x071b, 0x071d, 0x071f,
+ 0x0740, 0x0740, 0x0740, 0x0740, 0x0741, 0x0741, 0x0742, 0x0742,
+ 0x0743, 0x0744, 0x0745, 0x0745, 0x0746, 0x0747, 0x0748, 0x0749,
+ 0x074a, 0x074b, 0x074c, 0x074e, 0x074f, 0x0750, 0x0751, 0x0753,
+ 0x0754, 0x0755, 0x0757, 0x0758, 0x075a, 0x075b, 0x075d, 0x075f,
+ 0x0760, 0x0760, 0x0760, 0x0760, 0x0761, 0x0761, 0x0762, 0x0762,
+ 0x0763, 0x0764, 0x0765, 0x0765, 0x0766, 0x0767, 0x0768, 0x0769,
+ 0x076a, 0x076b, 0x076c, 0x076e, 0x076f, 0x0770, 0x0771, 0x0773,
+ 0x0774, 0x0775, 0x0777, 0x0778, 0x077a, 0x077b, 0x077d, 0x077f,
+ 0x07a0, 0x07a0, 0x07a0, 0x07a0, 0x07a1, 0x07a1, 0x07a2, 0x07a2,
+ 0x07a3, 0x07a4, 0x07a5, 0x07a5, 0x07a6, 0x07a7, 0x07a8, 0x07a9,
+ 0x07aa, 0x07ab, 0x07ac, 0x07ae, 0x07af, 0x07b0, 0x07b1, 0x07b3,
+ 0x07b4, 0x07b5, 0x07b7, 0x07b8, 0x07ba, 0x07bb, 0x07bd, 0x07bf,
+ 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e1, 0x07e1, 0x07e2, 0x07e2,
+ 0x07e3, 0x07e4, 0x07e5, 0x07e5, 0x07e6, 0x07e7, 0x07e8, 0x07e9,
+ 0x07ea, 0x07eb, 0x07ec, 0x07ee, 0x07ef, 0x07f0, 0x07f1, 0x07f3,
+ 0x07f4, 0x07f5, 0x07f7, 0x07f8, 0x07fa, 0x07fb, 0x07fd, 0x07ff,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0002, 0x0002,
+ 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x000c, 0x000e, 0x000f, 0x0010, 0x0011, 0x0013,
+ 0x0014, 0x0015, 0x0017, 0x0018, 0x001a, 0x001b, 0x001d, 0x001f,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0021, 0x0021, 0x0022, 0x0022,
+ 0x0023, 0x0024, 0x0025, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002a, 0x002b, 0x002c, 0x002e, 0x002f, 0x0030, 0x0031, 0x0033,
+ 0x0034, 0x0035, 0x0037, 0x0038, 0x003a, 0x003b, 0x003d, 0x003f,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0021, 0x0021, 0x0022, 0x0022,
+ 0x0023, 0x0024, 0x0025, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002a, 0x002b, 0x002c, 0x002e, 0x002f, 0x0030, 0x0031, 0x0033,
+ 0x0034, 0x0035, 0x0037, 0x0038, 0x003a, 0x003b, 0x003d, 0x003f,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0021, 0x0021, 0x0022, 0x0022,
+ 0x0023, 0x0024, 0x0025, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002a, 0x002b, 0x002c, 0x002e, 0x002f, 0x0030, 0x0031, 0x0033,
+ 0x0034, 0x0035, 0x0037, 0x0038, 0x003a, 0x003b, 0x003d, 0x003f,
+ 0x0040, 0x0040, 0x0040, 0x0040, 0x0041, 0x0041, 0x0042, 0x0042,
+ 0x0043, 0x0044, 0x0045, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049,
+ 0x004a, 0x004b, 0x004c, 0x004e, 0x004f, 0x0050, 0x0051, 0x0053,
+ 0x0054, 0x0055, 0x0057, 0x0058, 0x005a, 0x005b, 0x005d, 0x005f,
+ 0x0040, 0x0040, 0x0040, 0x0040, 0x0041, 0x0041, 0x0042, 0x0042,
+ 0x0043, 0x0044, 0x0045, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049,
+ 0x004a, 0x004b, 0x004c, 0x004e, 0x004f, 0x0050, 0x0051, 0x0053,
+ 0x0054, 0x0055, 0x0057, 0x0058, 0x005a, 0x005b, 0x005d, 0x005f,
+ 0x0060, 0x0060, 0x0060, 0x0060, 0x0061, 0x0061, 0x0062, 0x0062,
+ 0x0063, 0x0064, 0x0065, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
+ 0x006a, 0x006b, 0x006c, 0x006e, 0x006f, 0x0070, 0x0071, 0x0073,
+ 0x0074, 0x0075, 0x0077, 0x0078, 0x007a, 0x007b, 0x007d, 0x007f,
+ 0x0060, 0x0060, 0x0060, 0x0060, 0x0061, 0x0061, 0x0062, 0x0062,
+ 0x0063, 0x0064, 0x0065, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
+ 0x006a, 0x006b, 0x006c, 0x006e, 0x006f, 0x0070, 0x0071, 0x0073,
+ 0x0074, 0x0075, 0x0077, 0x0078, 0x007a, 0x007b, 0x007d, 0x007f,
+ 0x0080, 0x0080, 0x0080, 0x0080, 0x0081, 0x0081, 0x0082, 0x0082,
+ 0x0083, 0x0084, 0x0085, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089,
+ 0x008a, 0x008b, 0x008c, 0x008e, 0x008f, 0x0090, 0x0091, 0x0093,
+ 0x0094, 0x0095, 0x0097, 0x0098, 0x009a, 0x009b, 0x009d, 0x009f,
+ 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a1, 0x00a1, 0x00a2, 0x00a2,
+ 0x00a3, 0x00a4, 0x00a5, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9,
+ 0x00aa, 0x00ab, 0x00ac, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b3,
+ 0x00b4, 0x00b5, 0x00b7, 0x00b8, 0x00ba, 0x00bb, 0x00bd, 0x00bf,
+ 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a1, 0x00a1, 0x00a2, 0x00a2,
+ 0x00a3, 0x00a4, 0x00a5, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9,
+ 0x00aa, 0x00ab, 0x00ac, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b3,
+ 0x00b4, 0x00b5, 0x00b7, 0x00b8, 0x00ba, 0x00bb, 0x00bd, 0x00bf,
+ 0x00c0, 0x00c0, 0x00c0, 0x00c0, 0x00c1, 0x00c1, 0x00c2, 0x00c2,
+ 0x00c3, 0x00c4, 0x00c5, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9,
+ 0x00ca, 0x00cb, 0x00cc, 0x00ce, 0x00cf, 0x00d0, 0x00d1, 0x00d3,
+ 0x00d4, 0x00d5, 0x00d7, 0x00d8, 0x00da, 0x00db, 0x00dd, 0x00df,
+ 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e1, 0x00e1, 0x00e2, 0x00e2,
+ 0x00e3, 0x00e4, 0x00e5, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9,
+ 0x00ea, 0x00eb, 0x00ec, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f3,
+ 0x00f4, 0x00f5, 0x00f7, 0x00f8, 0x00fa, 0x00fb, 0x00fd, 0x00ff,
+ 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e1, 0x00e1, 0x00e2, 0x00e2,
+ 0x00e3, 0x00e4, 0x00e5, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9,
+ 0x00ea, 0x00eb, 0x00ec, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f3,
+ 0x00f4, 0x00f5, 0x00f7, 0x00f8, 0x00fa, 0x00fb, 0x00fd, 0x00ff,
+ 0x0100, 0x0100, 0x0100, 0x0100, 0x0101, 0x0101, 0x0102, 0x0102,
+ 0x0103, 0x0104, 0x0105, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109,
+ 0x010a, 0x010b, 0x010c, 0x010e, 0x010f, 0x0110, 0x0111, 0x0113,
+ 0x0114, 0x0115, 0x0117, 0x0118, 0x011a, 0x011b, 0x011d, 0x011f,
+ 0x0120, 0x0120, 0x0120, 0x0120, 0x0121, 0x0121, 0x0122, 0x0122,
+ 0x0123, 0x0124, 0x0125, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129,
+ 0x012a, 0x012b, 0x012c, 0x012e, 0x012f, 0x0130, 0x0131, 0x0133,
+ 0x0134, 0x0135, 0x0137, 0x0138, 0x013a, 0x013b, 0x013d, 0x013f,
+ 0x0140, 0x0140, 0x0140, 0x0140, 0x0141, 0x0141, 0x0142, 0x0142,
+ 0x0143, 0x0144, 0x0145, 0x0145, 0x0146, 0x0147, 0x0148, 0x0149,
+ 0x014a, 0x014b, 0x014c, 0x014e, 0x014f, 0x0150, 0x0151, 0x0153,
+ 0x0154, 0x0155, 0x0157, 0x0158, 0x015a, 0x015b, 0x015d, 0x015f,
+ 0x0140, 0x0140, 0x0140, 0x0140, 0x0141, 0x0141, 0x0142, 0x0142,
+ 0x0143, 0x0144, 0x0145, 0x0145, 0x0146, 0x0147, 0x0148, 0x0149,
+ 0x014a, 0x014b, 0x014c, 0x014e, 0x014f, 0x0150, 0x0151, 0x0153,
+ 0x0154, 0x0155, 0x0157, 0x0158, 0x015a, 0x015b, 0x015d, 0x015f,
+ 0x0160, 0x0160, 0x0160, 0x0160, 0x0161, 0x0161, 0x0162, 0x0162,
+ 0x0163, 0x0164, 0x0165, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169,
+ 0x016a, 0x016b, 0x016c, 0x016e, 0x016f, 0x0170, 0x0171, 0x0173,
+ 0x0174, 0x0175, 0x0177, 0x0178, 0x017a, 0x017b, 0x017d, 0x017f,
+ 0x0180, 0x0180, 0x0180, 0x0180, 0x0181, 0x0181, 0x0182, 0x0182,
+ 0x0183, 0x0184, 0x0185, 0x0185, 0x0186, 0x0187, 0x0188, 0x0189,
+ 0x018a, 0x018b, 0x018c, 0x018e, 0x018f, 0x0190, 0x0191, 0x0193,
+ 0x0194, 0x0195, 0x0197, 0x0198, 0x019a, 0x019b, 0x019d, 0x019f,
+ 0x01a0, 0x01a0, 0x01a0, 0x01a0, 0x01a1, 0x01a1, 0x01a2, 0x01a2,
+ 0x01a3, 0x01a4, 0x01a5, 0x01a5, 0x01a6, 0x01a7, 0x01a8, 0x01a9,
+ 0x01aa, 0x01ab, 0x01ac, 0x01ae, 0x01af, 0x01b0, 0x01b1, 0x01b3,
+ 0x01b4, 0x01b5, 0x01b7, 0x01b8, 0x01ba, 0x01bb, 0x01bd, 0x01bf,
+ 0x01c0, 0x01c0, 0x01c0, 0x01c0, 0x01c1, 0x01c1, 0x01c2, 0x01c2,
+ 0x01c3, 0x01c4, 0x01c5, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9,
+ 0x01ca, 0x01cb, 0x01cc, 0x01ce, 0x01cf, 0x01d0, 0x01d1, 0x01d3,
+ 0x01d4, 0x01d5, 0x01d7, 0x01d8, 0x01da, 0x01db, 0x01dd, 0x01df,
+ 0x01e0, 0x01e0, 0x01e0, 0x01e0, 0x01e1, 0x01e1, 0x01e2, 0x01e2,
+ 0x01e3, 0x01e4, 0x01e5, 0x01e5, 0x01e6, 0x01e7, 0x01e8, 0x01e9,
+ 0x01ea, 0x01eb, 0x01ec, 0x01ee, 0x01ef, 0x01f0, 0x01f1, 0x01f3,
+ 0x01f4, 0x01f5, 0x01f7, 0x01f8, 0x01fa, 0x01fb, 0x01fd, 0x01ff,
+ 0x0200, 0x0200, 0x0200, 0x0200, 0x0201, 0x0201, 0x0202, 0x0202,
+ 0x0203, 0x0204, 0x0205, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209,
+ 0x020a, 0x020b, 0x020c, 0x020e, 0x020f, 0x0210, 0x0211, 0x0213,
+ 0x0214, 0x0215, 0x0217, 0x0218, 0x021a, 0x021b, 0x021d, 0x021f,
+ 0x0220, 0x0220, 0x0220, 0x0220, 0x0221, 0x0221, 0x0222, 0x0222,
+ 0x0223, 0x0224, 0x0225, 0x0225, 0x0226, 0x0227, 0x0228, 0x0229,
+ 0x022a, 0x022b, 0x022c, 0x022e, 0x022f, 0x0230, 0x0231, 0x0233,
+ 0x0234, 0x0235, 0x0237, 0x0238, 0x023a, 0x023b, 0x023d, 0x023f,
+ 0x0240, 0x0240, 0x0240, 0x0240, 0x0241, 0x0241, 0x0242, 0x0242,
+ 0x0243, 0x0244, 0x0245, 0x0245, 0x0246, 0x0247, 0x0248, 0x0249,
+ 0x024a, 0x024b, 0x024c, 0x024e, 0x024f, 0x0250, 0x0251, 0x0253,
+ 0x0254, 0x0255, 0x0257, 0x0258, 0x025a, 0x025b, 0x025d, 0x025f,
+ 0x0260, 0x0260, 0x0260, 0x0260, 0x0261, 0x0261, 0x0262, 0x0262,
+ 0x0263, 0x0264, 0x0265, 0x0265, 0x0266, 0x0267, 0x0268, 0x0269,
+ 0x026a, 0x026b, 0x026c, 0x026e, 0x026f, 0x0270, 0x0271, 0x0273,
+ 0x0274, 0x0275, 0x0277, 0x0278, 0x027a, 0x027b, 0x027d, 0x027f,
+ 0x0280, 0x0280, 0x0280, 0x0280, 0x0281, 0x0281, 0x0282, 0x0282,
+ 0x0283, 0x0284, 0x0285, 0x0285, 0x0286, 0x0287, 0x0288, 0x0289,
+ 0x028a, 0x028b, 0x028c, 0x028e, 0x028f, 0x0290, 0x0291, 0x0293,
+ 0x0294, 0x0295, 0x0297, 0x0298, 0x029a, 0x029b, 0x029d, 0x029f,
+ 0x02a0, 0x02a0, 0x02a0, 0x02a0, 0x02a1, 0x02a1, 0x02a2, 0x02a2,
+ 0x02a3, 0x02a4, 0x02a5, 0x02a5, 0x02a6, 0x02a7, 0x02a8, 0x02a9,
+ 0x02aa, 0x02ab, 0x02ac, 0x02ae, 0x02af, 0x02b0, 0x02b1, 0x02b3,
+ 0x02b4, 0x02b5, 0x02b7, 0x02b8, 0x02ba, 0x02bb, 0x02bd, 0x02bf,
+ 0x02c0, 0x02c0, 0x02c0, 0x02c0, 0x02c1, 0x02c1, 0x02c2, 0x02c2,
+ 0x02c3, 0x02c4, 0x02c5, 0x02c5, 0x02c6, 0x02c7, 0x02c8, 0x02c9,
+ 0x02ca, 0x02cb, 0x02cc, 0x02ce, 0x02cf, 0x02d0, 0x02d1, 0x02d3,
+ 0x02d4, 0x02d5, 0x02d7, 0x02d8, 0x02da, 0x02db, 0x02dd, 0x02df,
+ 0x02e0, 0x02e0, 0x02e0, 0x02e0, 0x02e1, 0x02e1, 0x02e2, 0x02e2,
+ 0x02e3, 0x02e4, 0x02e5, 0x02e5, 0x02e6, 0x02e7, 0x02e8, 0x02e9,
+ 0x02ea, 0x02eb, 0x02ec, 0x02ee, 0x02ef, 0x02f0, 0x02f1, 0x02f3,
+ 0x02f4, 0x02f5, 0x02f7, 0x02f8, 0x02fa, 0x02fb, 0x02fd, 0x02ff,
+ 0x0300, 0x0300, 0x0300, 0x0300, 0x0301, 0x0301, 0x0302, 0x0302,
+ 0x0303, 0x0304, 0x0305, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309,
+ 0x030a, 0x030b, 0x030c, 0x030e, 0x030f, 0x0310, 0x0311, 0x0313,
+ 0x0314, 0x0315, 0x0317, 0x0318, 0x031a, 0x031b, 0x031d, 0x031f,
+ 0x0320, 0x0320, 0x0320, 0x0320, 0x0321, 0x0321, 0x0322, 0x0322,
+ 0x0323, 0x0324, 0x0325, 0x0325, 0x0326, 0x0327, 0x0328, 0x0329,
+ 0x032a, 0x032b, 0x032c, 0x032e, 0x032f, 0x0330, 0x0331, 0x0333,
+ 0x0334, 0x0335, 0x0337, 0x0338, 0x033a, 0x033b, 0x033d, 0x033f,
+ 0x0340, 0x0340, 0x0340, 0x0340, 0x0341, 0x0341, 0x0342, 0x0342,
+ 0x0343, 0x0344, 0x0345, 0x0345, 0x0346, 0x0347, 0x0348, 0x0349,
+ 0x034a, 0x034b, 0x034c, 0x034e, 0x034f, 0x0350, 0x0351, 0x0353,
+ 0x0354, 0x0355, 0x0357, 0x0358, 0x035a, 0x035b, 0x035d, 0x035f,
+ 0x0380, 0x0380, 0x0380, 0x0380, 0x0381, 0x0381, 0x0382, 0x0382,
+ 0x0383, 0x0384, 0x0385, 0x0385, 0x0386, 0x0387, 0x0388, 0x0389,
+ 0x038a, 0x038b, 0x038c, 0x038e, 0x038f, 0x0390, 0x0391, 0x0393,
+ 0x0394, 0x0395, 0x0397, 0x0398, 0x039a, 0x039b, 0x039d, 0x039f,
+ 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a1, 0x03a1, 0x03a2, 0x03a2,
+ 0x03a3, 0x03a4, 0x03a5, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9,
+ 0x03aa, 0x03ab, 0x03ac, 0x03ae, 0x03af, 0x03b0, 0x03b1, 0x03b3,
+ 0x03b4, 0x03b5, 0x03b7, 0x03b8, 0x03ba, 0x03bb, 0x03bd, 0x03bf,
+ 0x03c0, 0x03c0, 0x03c0, 0x03c0, 0x03c1, 0x03c1, 0x03c2, 0x03c2,
+ 0x03c3, 0x03c4, 0x03c5, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9,
+ 0x03ca, 0x03cb, 0x03cc, 0x03ce, 0x03cf, 0x03d0, 0x03d1, 0x03d3,
+ 0x03d4, 0x03d5, 0x03d7, 0x03d8, 0x03da, 0x03db, 0x03dd, 0x03df,
+ 0x03e0, 0x03e0, 0x03e0, 0x03e0, 0x03e1, 0x03e1, 0x03e2, 0x03e2,
+ 0x03e3, 0x03e4, 0x03e5, 0x03e5, 0x03e6, 0x03e7, 0x03e8, 0x03e9,
+ 0x03ea, 0x03eb, 0x03ec, 0x03ee, 0x03ef, 0x03f0, 0x03f1, 0x03f3,
+ 0x03f4, 0x03f5, 0x03f7, 0x03f8, 0x03fa, 0x03fb, 0x03fd, 0x03ff,
+ 0x0400, 0x0400, 0x0400, 0x0400, 0x0401, 0x0401, 0x0402, 0x0402,
+ 0x0403, 0x0404, 0x0405, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409,
+ 0x040a, 0x040b, 0x040c, 0x040e, 0x040f, 0x0410, 0x0411, 0x0413,
+ 0x0414, 0x0415, 0x0417, 0x0418, 0x041a, 0x041b, 0x041d, 0x041f,
+ 0x0440, 0x0440, 0x0440, 0x0440, 0x0441, 0x0441, 0x0442, 0x0442,
+ 0x0443, 0x0444, 0x0445, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
+ 0x044a, 0x044b, 0x044c, 0x044e, 0x044f, 0x0450, 0x0451, 0x0453,
+ 0x0454, 0x0455, 0x0457, 0x0458, 0x045a, 0x045b, 0x045d, 0x045f,
+ 0x0460, 0x0460, 0x0460, 0x0460, 0x0461, 0x0461, 0x0462, 0x0462,
+ 0x0463, 0x0464, 0x0465, 0x0465, 0x0466, 0x0467, 0x0468, 0x0469,
+ 0x046a, 0x046b, 0x046c, 0x046e, 0x046f, 0x0470, 0x0471, 0x0473,
+ 0x0474, 0x0475, 0x0477, 0x0478, 0x047a, 0x047b, 0x047d, 0x047f,
+ 0x0480, 0x0480, 0x0480, 0x0480, 0x0481, 0x0481, 0x0482, 0x0482,
+ 0x0483, 0x0484, 0x0485, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489,
+ 0x048a, 0x048b, 0x048c, 0x048e, 0x048f, 0x0490, 0x0491, 0x0493,
+ 0x0494, 0x0495, 0x0497, 0x0498, 0x049a, 0x049b, 0x049d, 0x049f,
+ 0x04c0, 0x04c0, 0x04c0, 0x04c0, 0x04c1, 0x04c1, 0x04c2, 0x04c2,
+ 0x04c3, 0x04c4, 0x04c5, 0x04c5, 0x04c6, 0x04c7, 0x04c8, 0x04c9,
+ 0x04ca, 0x04cb, 0x04cc, 0x04ce, 0x04cf, 0x04d0, 0x04d1, 0x04d3,
+ 0x04d4, 0x04d5, 0x04d7, 0x04d8, 0x04da, 0x04db, 0x04dd, 0x04df,
+ 0x04e0, 0x04e0, 0x04e0, 0x04e0, 0x04e1, 0x04e1, 0x04e2, 0x04e2,
+ 0x04e3, 0x04e4, 0x04e5, 0x04e5, 0x04e6, 0x04e7, 0x04e8, 0x04e9,
+ 0x04ea, 0x04eb, 0x04ec, 0x04ee, 0x04ef, 0x04f0, 0x04f1, 0x04f3,
+ 0x04f4, 0x04f5, 0x04f7, 0x04f8, 0x04fa, 0x04fb, 0x04fd, 0x04ff,
+ 0x0500, 0x0500, 0x0500, 0x0500, 0x0501, 0x0501, 0x0502, 0x0502,
+ 0x0503, 0x0504, 0x0505, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509,
+ 0x050a, 0x050b, 0x050c, 0x050e, 0x050f, 0x0510, 0x0511, 0x0513,
+ 0x0514, 0x0515, 0x0517, 0x0518, 0x051a, 0x051b, 0x051d, 0x051f,
+ 0x0540, 0x0540, 0x0540, 0x0540, 0x0541, 0x0541, 0x0542, 0x0542,
+ 0x0543, 0x0544, 0x0545, 0x0545, 0x0546, 0x0547, 0x0548, 0x0549,
+ 0x054a, 0x054b, 0x054c, 0x054e, 0x054f, 0x0550, 0x0551, 0x0553,
+ 0x0554, 0x0555, 0x0557, 0x0558, 0x055a, 0x055b, 0x055d, 0x055f,
+ 0x0560, 0x0560, 0x0560, 0x0560, 0x0561, 0x0561, 0x0562, 0x0562,
+ 0x0563, 0x0564, 0x0565, 0x0565, 0x0566, 0x0567, 0x0568, 0x0569,
+ 0x056a, 0x056b, 0x056c, 0x056e, 0x056f, 0x0570, 0x0571, 0x0573,
+ 0x0574, 0x0575, 0x0577, 0x0578, 0x057a, 0x057b, 0x057d, 0x057f,
+ 0x0580, 0x0580, 0x0580, 0x0580, 0x0581, 0x0581, 0x0582, 0x0582,
+ 0x0583, 0x0584, 0x0585, 0x0585, 0x0586, 0x0587, 0x0588, 0x0589,
+ 0x058a, 0x058b, 0x058c, 0x058e, 0x058f, 0x0590, 0x0591, 0x0593,
+ 0x0594, 0x0595, 0x0597, 0x0598, 0x059a, 0x059b, 0x059d, 0x059f,
+ 0x05c0, 0x05c0, 0x05c0, 0x05c0, 0x05c1, 0x05c1, 0x05c2, 0x05c2,
+ 0x05c3, 0x05c4, 0x05c5, 0x05c5, 0x05c6, 0x05c7, 0x05c8, 0x05c9,
+ 0x05ca, 0x05cb, 0x05cc, 0x05ce, 0x05cf, 0x05d0, 0x05d1, 0x05d3,
+ 0x05d4, 0x05d5, 0x05d7, 0x05d8, 0x05da, 0x05db, 0x05dd, 0x05df,
+ 0x05e0, 0x05e0, 0x05e0, 0x05e0, 0x05e1, 0x05e1, 0x05e2, 0x05e2,
+ 0x05e3, 0x05e4, 0x05e5, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9,
+ 0x05ea, 0x05eb, 0x05ec, 0x05ee, 0x05ef, 0x05f0, 0x05f1, 0x05f3,
+ 0x05f4, 0x05f5, 0x05f7, 0x05f8, 0x05fa, 0x05fb, 0x05fd, 0x05ff,
+ 0x0620, 0x0620, 0x0620, 0x0620, 0x0621, 0x0621, 0x0622, 0x0622,
+ 0x0623, 0x0624, 0x0625, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629,
+ 0x062a, 0x062b, 0x062c, 0x062e, 0x062f, 0x0630, 0x0631, 0x0633,
+ 0x0634, 0x0635, 0x0637, 0x0638, 0x063a, 0x063b, 0x063d, 0x063f,
+ 0x0640, 0x0640, 0x0640, 0x0640, 0x0641, 0x0641, 0x0642, 0x0642,
+ 0x0643, 0x0644, 0x0645, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649,
+ 0x064a, 0x064b, 0x064c, 0x064e, 0x064f, 0x0650, 0x0651, 0x0653,
+ 0x0654, 0x0655, 0x0657, 0x0658, 0x065a, 0x065b, 0x065d, 0x065f,
+ 0x0680, 0x0680, 0x0680, 0x0680, 0x0681, 0x0681, 0x0682, 0x0682,
+ 0x0683, 0x0684, 0x0685, 0x0685, 0x0686, 0x0687, 0x0688, 0x0689,
+ 0x068a, 0x068b, 0x068c, 0x068e, 0x068f, 0x0690, 0x0691, 0x0693,
+ 0x0694, 0x0695, 0x0697, 0x0698, 0x069a, 0x069b, 0x069d, 0x069f,
+ 0x06a0, 0x06a0, 0x06a0, 0x06a0, 0x06a1, 0x06a1, 0x06a2, 0x06a2,
+ 0x06a3, 0x06a4, 0x06a5, 0x06a5, 0x06a6, 0x06a7, 0x06a8, 0x06a9,
+ 0x06aa, 0x06ab, 0x06ac, 0x06ae, 0x06af, 0x06b0, 0x06b1, 0x06b3,
+ 0x06b4, 0x06b5, 0x06b7, 0x06b8, 0x06ba, 0x06bb, 0x06bd, 0x06bf,
+ 0x06e0, 0x06e0, 0x06e0, 0x06e0, 0x06e1, 0x06e1, 0x06e2, 0x06e2,
+ 0x06e3, 0x06e4, 0x06e5, 0x06e5, 0x06e6, 0x06e7, 0x06e8, 0x06e9,
+ 0x06ea, 0x06eb, 0x06ec, 0x06ee, 0x06ef, 0x06f0, 0x06f1, 0x06f3,
+ 0x06f4, 0x06f5, 0x06f7, 0x06f8, 0x06fa, 0x06fb, 0x06fd, 0x06ff,
+ 0x0700, 0x0700, 0x0700, 0x0700, 0x0701, 0x0701, 0x0702, 0x0702,
+ 0x0703, 0x0704, 0x0705, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709,
+ 0x070a, 0x070b, 0x070c, 0x070e, 0x070f, 0x0710, 0x0711, 0x0713,
+ 0x0714, 0x0715, 0x0717, 0x0718, 0x071a, 0x071b, 0x071d, 0x071f,
+ 0x0740, 0x0740, 0x0740, 0x0740, 0x0741, 0x0741, 0x0742, 0x0742,
+ 0x0743, 0x0744, 0x0745, 0x0745, 0x0746, 0x0747, 0x0748, 0x0749,
+ 0x074a, 0x074b, 0x074c, 0x074e, 0x074f, 0x0750, 0x0751, 0x0753,
+ 0x0754, 0x0755, 0x0757, 0x0758, 0x075a, 0x075b, 0x075d, 0x075f,
+ 0x0760, 0x0760, 0x0760, 0x0760, 0x0761, 0x0761, 0x0762, 0x0762,
+ 0x0763, 0x0764, 0x0765, 0x0765, 0x0766, 0x0767, 0x0768, 0x0769,
+ 0x076a, 0x076b, 0x076c, 0x076e, 0x076f, 0x0770, 0x0771, 0x0773,
+ 0x0774, 0x0775, 0x0777, 0x0778, 0x077a, 0x077b, 0x077d, 0x077f,
+ 0x07a0, 0x07a0, 0x07a0, 0x07a0, 0x07a1, 0x07a1, 0x07a2, 0x07a2,
+ 0x07a3, 0x07a4, 0x07a5, 0x07a5, 0x07a6, 0x07a7, 0x07a8, 0x07a9,
+ 0x07aa, 0x07ab, 0x07ac, 0x07ae, 0x07af, 0x07b0, 0x07b1, 0x07b3,
+ 0x07b4, 0x07b5, 0x07b7, 0x07b8, 0x07ba, 0x07bb, 0x07bd, 0x07bf,
+ 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e1, 0x07e1, 0x07e2, 0x07e2,
+ 0x07e3, 0x07e4, 0x07e5, 0x07e5, 0x07e6, 0x07e7, 0x07e8, 0x07e9,
+ 0x07ea, 0x07eb, 0x07ec, 0x07ee, 0x07ef, 0x07f0, 0x07f1, 0x07f3,
+ 0x07f4, 0x07f5, 0x07f7, 0x07f8, 0x07fa, 0x07fb, 0x07fd, 0x07ff,
+ 0x0800, 0x0800, 0x0800, 0x0800, 0x0801, 0x0801, 0x0802, 0x0802,
+ 0x0803, 0x0804, 0x0805, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809,
+ 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0811, 0x0813,
+ 0x0814, 0x0815, 0x0817, 0x0818, 0x081a, 0x081b, 0x081d, 0x081f,
+ 0x0800, 0x0800, 0x0800, 0x0800, 0x0801, 0x0801, 0x0802, 0x0802,
+ 0x0803, 0x0804, 0x0805, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809,
+ 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0811, 0x0813,
+ 0x0814, 0x0815, 0x0817, 0x0818, 0x081a, 0x081b, 0x081d, 0x081f,
+ 0x0800, 0x0800, 0x0800, 0x0800, 0x0801, 0x0801, 0x0802, 0x0802,
+ 0x0803, 0x0804, 0x0805, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809,
+ 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0811, 0x0813,
+ 0x0814, 0x0815, 0x0817, 0x0818, 0x081a, 0x081b, 0x081d, 0x081f,
+ 0x0800, 0x0800, 0x0800, 0x0800, 0x0801, 0x0801, 0x0802, 0x0802,
+ 0x0803, 0x0804, 0x0805, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809,
+ 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0811, 0x0813,
+ 0x0814, 0x0815, 0x0817, 0x0818, 0x081a, 0x081b, 0x081d, 0x081f,
+ 0x0800, 0x0800, 0x0800, 0x0800, 0x0801, 0x0801, 0x0802, 0x0802,
+ 0x0803, 0x0804, 0x0805, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809,
+ 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0811, 0x0813,
+ 0x0814, 0x0815, 0x0817, 0x0818, 0x081a, 0x081b, 0x081d, 0x081f,
+ 0x0820, 0x0820, 0x0820, 0x0820, 0x0821, 0x0821, 0x0822, 0x0822,
+ 0x0823, 0x0824, 0x0825, 0x0825, 0x0826, 0x0827, 0x0828, 0x0829,
+ 0x082a, 0x082b, 0x082c, 0x082e, 0x082f, 0x0830, 0x0831, 0x0833,
+ 0x0834, 0x0835, 0x0837, 0x0838, 0x083a, 0x083b, 0x083d, 0x083f,
+ 0x0820, 0x0820, 0x0820, 0x0820, 0x0821, 0x0821, 0x0822, 0x0822,
+ 0x0823, 0x0824, 0x0825, 0x0825, 0x0826, 0x0827, 0x0828, 0x0829,
+ 0x082a, 0x082b, 0x082c, 0x082e, 0x082f, 0x0830, 0x0831, 0x0833,
+ 0x0834, 0x0835, 0x0837, 0x0838, 0x083a, 0x083b, 0x083d, 0x083f,
+ 0x0820, 0x0820, 0x0820, 0x0820, 0x0821, 0x0821, 0x0822, 0x0822,
+ 0x0823, 0x0824, 0x0825, 0x0825, 0x0826, 0x0827, 0x0828, 0x0829,
+ 0x082a, 0x082b, 0x082c, 0x082e, 0x082f, 0x0830, 0x0831, 0x0833,
+ 0x0834, 0x0835, 0x0837, 0x0838, 0x083a, 0x083b, 0x083d, 0x083f,
+ 0x0840, 0x0840, 0x0840, 0x0840, 0x0841, 0x0841, 0x0842, 0x0842,
+ 0x0843, 0x0844, 0x0845, 0x0845, 0x0846, 0x0847, 0x0848, 0x0849,
+ 0x084a, 0x084b, 0x084c, 0x084e, 0x084f, 0x0850, 0x0851, 0x0853,
+ 0x0854, 0x0855, 0x0857, 0x0858, 0x085a, 0x085b, 0x085d, 0x085f,
+ 0x0840, 0x0840, 0x0840, 0x0840, 0x0841, 0x0841, 0x0842, 0x0842,
+ 0x0843, 0x0844, 0x0845, 0x0845, 0x0846, 0x0847, 0x0848, 0x0849,
+ 0x084a, 0x084b, 0x084c, 0x084e, 0x084f, 0x0850, 0x0851, 0x0853,
+ 0x0854, 0x0855, 0x0857, 0x0858, 0x085a, 0x085b, 0x085d, 0x085f,
+ 0x0860, 0x0860, 0x0860, 0x0860, 0x0861, 0x0861, 0x0862, 0x0862,
+ 0x0863, 0x0864, 0x0865, 0x0865, 0x0866, 0x0867, 0x0868, 0x0869,
+ 0x086a, 0x086b, 0x086c, 0x086e, 0x086f, 0x0870, 0x0871, 0x0873,
+ 0x0874, 0x0875, 0x0877, 0x0878, 0x087a, 0x087b, 0x087d, 0x087f,
+ 0x0860, 0x0860, 0x0860, 0x0860, 0x0861, 0x0861, 0x0862, 0x0862,
+ 0x0863, 0x0864, 0x0865, 0x0865, 0x0866, 0x0867, 0x0868, 0x0869,
+ 0x086a, 0x086b, 0x086c, 0x086e, 0x086f, 0x0870, 0x0871, 0x0873,
+ 0x0874, 0x0875, 0x0877, 0x0878, 0x087a, 0x087b, 0x087d, 0x087f,
+ 0x0880, 0x0880, 0x0880, 0x0880, 0x0881, 0x0881, 0x0882, 0x0882,
+ 0x0883, 0x0884, 0x0885, 0x0885, 0x0886, 0x0887, 0x0888, 0x0889,
+ 0x088a, 0x088b, 0x088c, 0x088e, 0x088f, 0x0890, 0x0891, 0x0893,
+ 0x0894, 0x0895, 0x0897, 0x0898, 0x089a, 0x089b, 0x089d, 0x089f,
+ 0x08a0, 0x08a0, 0x08a0, 0x08a0, 0x08a1, 0x08a1, 0x08a2, 0x08a2,
+ 0x08a3, 0x08a4, 0x08a5, 0x08a5, 0x08a6, 0x08a7, 0x08a8, 0x08a9,
+ 0x08aa, 0x08ab, 0x08ac, 0x08ae, 0x08af, 0x08b0, 0x08b1, 0x08b3,
+ 0x08b4, 0x08b5, 0x08b7, 0x08b8, 0x08ba, 0x08bb, 0x08bd, 0x08bf,
+ 0x08a0, 0x08a0, 0x08a0, 0x08a0, 0x08a1, 0x08a1, 0x08a2, 0x08a2,
+ 0x08a3, 0x08a4, 0x08a5, 0x08a5, 0x08a6, 0x08a7, 0x08a8, 0x08a9,
+ 0x08aa, 0x08ab, 0x08ac, 0x08ae, 0x08af, 0x08b0, 0x08b1, 0x08b3,
+ 0x08b4, 0x08b5, 0x08b7, 0x08b8, 0x08ba, 0x08bb, 0x08bd, 0x08bf,
+ 0x08c0, 0x08c0, 0x08c0, 0x08c0, 0x08c1, 0x08c1, 0x08c2, 0x08c2,
+ 0x08c3, 0x08c4, 0x08c5, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9,
+ 0x08ca, 0x08cb, 0x08cc, 0x08ce, 0x08cf, 0x08d0, 0x08d1, 0x08d3,
+ 0x08d4, 0x08d5, 0x08d7, 0x08d8, 0x08da, 0x08db, 0x08dd, 0x08df,
+ 0x08e0, 0x08e0, 0x08e0, 0x08e0, 0x08e1, 0x08e1, 0x08e2, 0x08e2,
+ 0x08e3, 0x08e4, 0x08e5, 0x08e5, 0x08e6, 0x08e7, 0x08e8, 0x08e9,
+ 0x08ea, 0x08eb, 0x08ec, 0x08ee, 0x08ef, 0x08f0, 0x08f1, 0x08f3,
+ 0x08f4, 0x08f5, 0x08f7, 0x08f8, 0x08fa, 0x08fb, 0x08fd, 0x08ff,
+ 0x08e0, 0x08e0, 0x08e0, 0x08e0, 0x08e1, 0x08e1, 0x08e2, 0x08e2,
+ 0x08e3, 0x08e4, 0x08e5, 0x08e5, 0x08e6, 0x08e7, 0x08e8, 0x08e9,
+ 0x08ea, 0x08eb, 0x08ec, 0x08ee, 0x08ef, 0x08f0, 0x08f1, 0x08f3,
+ 0x08f4, 0x08f5, 0x08f7, 0x08f8, 0x08fa, 0x08fb, 0x08fd, 0x08ff,
+ 0x0900, 0x0900, 0x0900, 0x0900, 0x0901, 0x0901, 0x0902, 0x0902,
+ 0x0903, 0x0904, 0x0905, 0x0905, 0x0906, 0x0907, 0x0908, 0x0909,
+ 0x090a, 0x090b, 0x090c, 0x090e, 0x090f, 0x0910, 0x0911, 0x0913,
+ 0x0914, 0x0915, 0x0917, 0x0918, 0x091a, 0x091b, 0x091d, 0x091f,
+ 0x0920, 0x0920, 0x0920, 0x0920, 0x0921, 0x0921, 0x0922, 0x0922,
+ 0x0923, 0x0924, 0x0925, 0x0925, 0x0926, 0x0927, 0x0928, 0x0929,
+ 0x092a, 0x092b, 0x092c, 0x092e, 0x092f, 0x0930, 0x0931, 0x0933,
+ 0x0934, 0x0935, 0x0937, 0x0938, 0x093a, 0x093b, 0x093d, 0x093f,
+ 0x0940, 0x0940, 0x0940, 0x0940, 0x0941, 0x0941, 0x0942, 0x0942,
+ 0x0943, 0x0944, 0x0945, 0x0945, 0x0946, 0x0947, 0x0948, 0x0949,
+ 0x094a, 0x094b, 0x094c, 0x094e, 0x094f, 0x0950, 0x0951, 0x0953,
+ 0x0954, 0x0955, 0x0957, 0x0958, 0x095a, 0x095b, 0x095d, 0x095f,
+ 0x0940, 0x0940, 0x0940, 0x0940, 0x0941, 0x0941, 0x0942, 0x0942,
+ 0x0943, 0x0944, 0x0945, 0x0945, 0x0946, 0x0947, 0x0948, 0x0949,
+ 0x094a, 0x094b, 0x094c, 0x094e, 0x094f, 0x0950, 0x0951, 0x0953,
+ 0x0954, 0x0955, 0x0957, 0x0958, 0x095a, 0x095b, 0x095d, 0x095f,
+ 0x0960, 0x0960, 0x0960, 0x0960, 0x0961, 0x0961, 0x0962, 0x0962,
+ 0x0963, 0x0964, 0x0965, 0x0965, 0x0966, 0x0967, 0x0968, 0x0969,
+ 0x096a, 0x096b, 0x096c, 0x096e, 0x096f, 0x0970, 0x0971, 0x0973,
+ 0x0974, 0x0975, 0x0977, 0x0978, 0x097a, 0x097b, 0x097d, 0x097f,
+ 0x0980, 0x0980, 0x0980, 0x0980, 0x0981, 0x0981, 0x0982, 0x0982,
+ 0x0983, 0x0984, 0x0985, 0x0985, 0x0986, 0x0987, 0x0988, 0x0989,
+ 0x098a, 0x098b, 0x098c, 0x098e, 0x098f, 0x0990, 0x0991, 0x0993,
+ 0x0994, 0x0995, 0x0997, 0x0998, 0x099a, 0x099b, 0x099d, 0x099f,
+ 0x09a0, 0x09a0, 0x09a0, 0x09a0, 0x09a1, 0x09a1, 0x09a2, 0x09a2,
+ 0x09a3, 0x09a4, 0x09a5, 0x09a5, 0x09a6, 0x09a7, 0x09a8, 0x09a9,
+ 0x09aa, 0x09ab, 0x09ac, 0x09ae, 0x09af, 0x09b0, 0x09b1, 0x09b3,
+ 0x09b4, 0x09b5, 0x09b7, 0x09b8, 0x09ba, 0x09bb, 0x09bd, 0x09bf,
+ 0x09c0, 0x09c0, 0x09c0, 0x09c0, 0x09c1, 0x09c1, 0x09c2, 0x09c2,
+ 0x09c3, 0x09c4, 0x09c5, 0x09c5, 0x09c6, 0x09c7, 0x09c8, 0x09c9,
+ 0x09ca, 0x09cb, 0x09cc, 0x09ce, 0x09cf, 0x09d0, 0x09d1, 0x09d3,
+ 0x09d4, 0x09d5, 0x09d7, 0x09d8, 0x09da, 0x09db, 0x09dd, 0x09df,
+ 0x09e0, 0x09e0, 0x09e0, 0x09e0, 0x09e1, 0x09e1, 0x09e2, 0x09e2,
+ 0x09e3, 0x09e4, 0x09e5, 0x09e5, 0x09e6, 0x09e7, 0x09e8, 0x09e9,
+ 0x09ea, 0x09eb, 0x09ec, 0x09ee, 0x09ef, 0x09f0, 0x09f1, 0x09f3,
+ 0x09f4, 0x09f5, 0x09f7, 0x09f8, 0x09fa, 0x09fb, 0x09fd, 0x09ff,
+ 0x0a00, 0x0a00, 0x0a00, 0x0a00, 0x0a01, 0x0a01, 0x0a02, 0x0a02,
+ 0x0a03, 0x0a04, 0x0a05, 0x0a05, 0x0a06, 0x0a07, 0x0a08, 0x0a09,
+ 0x0a0a, 0x0a0b, 0x0a0c, 0x0a0e, 0x0a0f, 0x0a10, 0x0a11, 0x0a13,
+ 0x0a14, 0x0a15, 0x0a17, 0x0a18, 0x0a1a, 0x0a1b, 0x0a1d, 0x0a1f,
+ 0x0a20, 0x0a20, 0x0a20, 0x0a20, 0x0a21, 0x0a21, 0x0a22, 0x0a22,
+ 0x0a23, 0x0a24, 0x0a25, 0x0a25, 0x0a26, 0x0a27, 0x0a28, 0x0a29,
+ 0x0a2a, 0x0a2b, 0x0a2c, 0x0a2e, 0x0a2f, 0x0a30, 0x0a31, 0x0a33,
+ 0x0a34, 0x0a35, 0x0a37, 0x0a38, 0x0a3a, 0x0a3b, 0x0a3d, 0x0a3f,
+ 0x0a40, 0x0a40, 0x0a40, 0x0a40, 0x0a41, 0x0a41, 0x0a42, 0x0a42,
+ 0x0a43, 0x0a44, 0x0a45, 0x0a45, 0x0a46, 0x0a47, 0x0a48, 0x0a49,
+ 0x0a4a, 0x0a4b, 0x0a4c, 0x0a4e, 0x0a4f, 0x0a50, 0x0a51, 0x0a53,
+ 0x0a54, 0x0a55, 0x0a57, 0x0a58, 0x0a5a, 0x0a5b, 0x0a5d, 0x0a5f,
+ 0x0a60, 0x0a60, 0x0a60, 0x0a60, 0x0a61, 0x0a61, 0x0a62, 0x0a62,
+ 0x0a63, 0x0a64, 0x0a65, 0x0a65, 0x0a66, 0x0a67, 0x0a68, 0x0a69,
+ 0x0a6a, 0x0a6b, 0x0a6c, 0x0a6e, 0x0a6f, 0x0a70, 0x0a71, 0x0a73,
+ 0x0a74, 0x0a75, 0x0a77, 0x0a78, 0x0a7a, 0x0a7b, 0x0a7d, 0x0a7f,
+ 0x0a80, 0x0a80, 0x0a80, 0x0a80, 0x0a81, 0x0a81, 0x0a82, 0x0a82,
+ 0x0a83, 0x0a84, 0x0a85, 0x0a85, 0x0a86, 0x0a87, 0x0a88, 0x0a89,
+ 0x0a8a, 0x0a8b, 0x0a8c, 0x0a8e, 0x0a8f, 0x0a90, 0x0a91, 0x0a93,
+ 0x0a94, 0x0a95, 0x0a97, 0x0a98, 0x0a9a, 0x0a9b, 0x0a9d, 0x0a9f,
+ 0x0aa0, 0x0aa0, 0x0aa0, 0x0aa0, 0x0aa1, 0x0aa1, 0x0aa2, 0x0aa2,
+ 0x0aa3, 0x0aa4, 0x0aa5, 0x0aa5, 0x0aa6, 0x0aa7, 0x0aa8, 0x0aa9,
+ 0x0aaa, 0x0aab, 0x0aac, 0x0aae, 0x0aaf, 0x0ab0, 0x0ab1, 0x0ab3,
+ 0x0ab4, 0x0ab5, 0x0ab7, 0x0ab8, 0x0aba, 0x0abb, 0x0abd, 0x0abf,
+ 0x0ac0, 0x0ac0, 0x0ac0, 0x0ac0, 0x0ac1, 0x0ac1, 0x0ac2, 0x0ac2,
+ 0x0ac3, 0x0ac4, 0x0ac5, 0x0ac5, 0x0ac6, 0x0ac7, 0x0ac8, 0x0ac9,
+ 0x0aca, 0x0acb, 0x0acc, 0x0ace, 0x0acf, 0x0ad0, 0x0ad1, 0x0ad3,
+ 0x0ad4, 0x0ad5, 0x0ad7, 0x0ad8, 0x0ada, 0x0adb, 0x0add, 0x0adf,
+ 0x0ae0, 0x0ae0, 0x0ae0, 0x0ae0, 0x0ae1, 0x0ae1, 0x0ae2, 0x0ae2,
+ 0x0ae3, 0x0ae4, 0x0ae5, 0x0ae5, 0x0ae6, 0x0ae7, 0x0ae8, 0x0ae9,
+ 0x0aea, 0x0aeb, 0x0aec, 0x0aee, 0x0aef, 0x0af0, 0x0af1, 0x0af3,
+ 0x0af4, 0x0af5, 0x0af7, 0x0af8, 0x0afa, 0x0afb, 0x0afd, 0x0aff,
+ 0x0b00, 0x0b00, 0x0b00, 0x0b00, 0x0b01, 0x0b01, 0x0b02, 0x0b02,
+ 0x0b03, 0x0b04, 0x0b05, 0x0b05, 0x0b06, 0x0b07, 0x0b08, 0x0b09,
+ 0x0b0a, 0x0b0b, 0x0b0c, 0x0b0e, 0x0b0f, 0x0b10, 0x0b11, 0x0b13,
+ 0x0b14, 0x0b15, 0x0b17, 0x0b18, 0x0b1a, 0x0b1b, 0x0b1d, 0x0b1f,
+ 0x0b20, 0x0b20, 0x0b20, 0x0b20, 0x0b21, 0x0b21, 0x0b22, 0x0b22,
+ 0x0b23, 0x0b24, 0x0b25, 0x0b25, 0x0b26, 0x0b27, 0x0b28, 0x0b29,
+ 0x0b2a, 0x0b2b, 0x0b2c, 0x0b2e, 0x0b2f, 0x0b30, 0x0b31, 0x0b33,
+ 0x0b34, 0x0b35, 0x0b37, 0x0b38, 0x0b3a, 0x0b3b, 0x0b3d, 0x0b3f,
+ 0x0b40, 0x0b40, 0x0b40, 0x0b40, 0x0b41, 0x0b41, 0x0b42, 0x0b42,
+ 0x0b43, 0x0b44, 0x0b45, 0x0b45, 0x0b46, 0x0b47, 0x0b48, 0x0b49,
+ 0x0b4a, 0x0b4b, 0x0b4c, 0x0b4e, 0x0b4f, 0x0b50, 0x0b51, 0x0b53,
+ 0x0b54, 0x0b55, 0x0b57, 0x0b58, 0x0b5a, 0x0b5b, 0x0b5d, 0x0b5f,
+ 0x0b80, 0x0b80, 0x0b80, 0x0b80, 0x0b81, 0x0b81, 0x0b82, 0x0b82,
+ 0x0b83, 0x0b84, 0x0b85, 0x0b85, 0x0b86, 0x0b87, 0x0b88, 0x0b89,
+ 0x0b8a, 0x0b8b, 0x0b8c, 0x0b8e, 0x0b8f, 0x0b90, 0x0b91, 0x0b93,
+ 0x0b94, 0x0b95, 0x0b97, 0x0b98, 0x0b9a, 0x0b9b, 0x0b9d, 0x0b9f,
+ 0x0ba0, 0x0ba0, 0x0ba0, 0x0ba0, 0x0ba1, 0x0ba1, 0x0ba2, 0x0ba2,
+ 0x0ba3, 0x0ba4, 0x0ba5, 0x0ba5, 0x0ba6, 0x0ba7, 0x0ba8, 0x0ba9,
+ 0x0baa, 0x0bab, 0x0bac, 0x0bae, 0x0baf, 0x0bb0, 0x0bb1, 0x0bb3,
+ 0x0bb4, 0x0bb5, 0x0bb7, 0x0bb8, 0x0bba, 0x0bbb, 0x0bbd, 0x0bbf,
+ 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc1, 0x0bc1, 0x0bc2, 0x0bc2,
+ 0x0bc3, 0x0bc4, 0x0bc5, 0x0bc5, 0x0bc6, 0x0bc7, 0x0bc8, 0x0bc9,
+ 0x0bca, 0x0bcb, 0x0bcc, 0x0bce, 0x0bcf, 0x0bd0, 0x0bd1, 0x0bd3,
+ 0x0bd4, 0x0bd5, 0x0bd7, 0x0bd8, 0x0bda, 0x0bdb, 0x0bdd, 0x0bdf,
+ 0x0be0, 0x0be0, 0x0be0, 0x0be0, 0x0be1, 0x0be1, 0x0be2, 0x0be2,
+ 0x0be3, 0x0be4, 0x0be5, 0x0be5, 0x0be6, 0x0be7, 0x0be8, 0x0be9,
+ 0x0bea, 0x0beb, 0x0bec, 0x0bee, 0x0bef, 0x0bf0, 0x0bf1, 0x0bf3,
+ 0x0bf4, 0x0bf5, 0x0bf7, 0x0bf8, 0x0bfa, 0x0bfb, 0x0bfd, 0x0bff,
+ 0x0c00, 0x0c00, 0x0c00, 0x0c00, 0x0c01, 0x0c01, 0x0c02, 0x0c02,
+ 0x0c03, 0x0c04, 0x0c05, 0x0c05, 0x0c06, 0x0c07, 0x0c08, 0x0c09,
+ 0x0c0a, 0x0c0b, 0x0c0c, 0x0c0e, 0x0c0f, 0x0c10, 0x0c11, 0x0c13,
+ 0x0c14, 0x0c15, 0x0c17, 0x0c18, 0x0c1a, 0x0c1b, 0x0c1d, 0x0c1f,
+ 0x0c40, 0x0c40, 0x0c40, 0x0c40, 0x0c41, 0x0c41, 0x0c42, 0x0c42,
+ 0x0c43, 0x0c44, 0x0c45, 0x0c45, 0x0c46, 0x0c47, 0x0c48, 0x0c49,
+ 0x0c4a, 0x0c4b, 0x0c4c, 0x0c4e, 0x0c4f, 0x0c50, 0x0c51, 0x0c53,
+ 0x0c54, 0x0c55, 0x0c57, 0x0c58, 0x0c5a, 0x0c5b, 0x0c5d, 0x0c5f,
+ 0x0c60, 0x0c60, 0x0c60, 0x0c60, 0x0c61, 0x0c61, 0x0c62, 0x0c62,
+ 0x0c63, 0x0c64, 0x0c65, 0x0c65, 0x0c66, 0x0c67, 0x0c68, 0x0c69,
+ 0x0c6a, 0x0c6b, 0x0c6c, 0x0c6e, 0x0c6f, 0x0c70, 0x0c71, 0x0c73,
+ 0x0c74, 0x0c75, 0x0c77, 0x0c78, 0x0c7a, 0x0c7b, 0x0c7d, 0x0c7f,
+ 0x0c80, 0x0c80, 0x0c80, 0x0c80, 0x0c81, 0x0c81, 0x0c82, 0x0c82,
+ 0x0c83, 0x0c84, 0x0c85, 0x0c85, 0x0c86, 0x0c87, 0x0c88, 0x0c89,
+ 0x0c8a, 0x0c8b, 0x0c8c, 0x0c8e, 0x0c8f, 0x0c90, 0x0c91, 0x0c93,
+ 0x0c94, 0x0c95, 0x0c97, 0x0c98, 0x0c9a, 0x0c9b, 0x0c9d, 0x0c9f,
+ 0x0cc0, 0x0cc0, 0x0cc0, 0x0cc0, 0x0cc1, 0x0cc1, 0x0cc2, 0x0cc2,
+ 0x0cc3, 0x0cc4, 0x0cc5, 0x0cc5, 0x0cc6, 0x0cc7, 0x0cc8, 0x0cc9,
+ 0x0cca, 0x0ccb, 0x0ccc, 0x0cce, 0x0ccf, 0x0cd0, 0x0cd1, 0x0cd3,
+ 0x0cd4, 0x0cd5, 0x0cd7, 0x0cd8, 0x0cda, 0x0cdb, 0x0cdd, 0x0cdf,
+ 0x0ce0, 0x0ce0, 0x0ce0, 0x0ce0, 0x0ce1, 0x0ce1, 0x0ce2, 0x0ce2,
+ 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9,
+ 0x0cea, 0x0ceb, 0x0cec, 0x0cee, 0x0cef, 0x0cf0, 0x0cf1, 0x0cf3,
+ 0x0cf4, 0x0cf5, 0x0cf7, 0x0cf8, 0x0cfa, 0x0cfb, 0x0cfd, 0x0cff,
+ 0x0d00, 0x0d00, 0x0d00, 0x0d00, 0x0d01, 0x0d01, 0x0d02, 0x0d02,
+ 0x0d03, 0x0d04, 0x0d05, 0x0d05, 0x0d06, 0x0d07, 0x0d08, 0x0d09,
+ 0x0d0a, 0x0d0b, 0x0d0c, 0x0d0e, 0x0d0f, 0x0d10, 0x0d11, 0x0d13,
+ 0x0d14, 0x0d15, 0x0d17, 0x0d18, 0x0d1a, 0x0d1b, 0x0d1d, 0x0d1f,
+ 0x0d40, 0x0d40, 0x0d40, 0x0d40, 0x0d41, 0x0d41, 0x0d42, 0x0d42,
+ 0x0d43, 0x0d44, 0x0d45, 0x0d45, 0x0d46, 0x0d47, 0x0d48, 0x0d49,
+ 0x0d4a, 0x0d4b, 0x0d4c, 0x0d4e, 0x0d4f, 0x0d50, 0x0d51, 0x0d53,
+ 0x0d54, 0x0d55, 0x0d57, 0x0d58, 0x0d5a, 0x0d5b, 0x0d5d, 0x0d5f,
+ 0x0d60, 0x0d60, 0x0d60, 0x0d60, 0x0d61, 0x0d61, 0x0d62, 0x0d62,
+ 0x0d63, 0x0d64, 0x0d65, 0x0d65, 0x0d66, 0x0d67, 0x0d68, 0x0d69,
+ 0x0d6a, 0x0d6b, 0x0d6c, 0x0d6e, 0x0d6f, 0x0d70, 0x0d71, 0x0d73,
+ 0x0d74, 0x0d75, 0x0d77, 0x0d78, 0x0d7a, 0x0d7b, 0x0d7d, 0x0d7f,
+ 0x0d80, 0x0d80, 0x0d80, 0x0d80, 0x0d81, 0x0d81, 0x0d82, 0x0d82,
+ 0x0d83, 0x0d84, 0x0d85, 0x0d85, 0x0d86, 0x0d87, 0x0d88, 0x0d89,
+ 0x0d8a, 0x0d8b, 0x0d8c, 0x0d8e, 0x0d8f, 0x0d90, 0x0d91, 0x0d93,
+ 0x0d94, 0x0d95, 0x0d97, 0x0d98, 0x0d9a, 0x0d9b, 0x0d9d, 0x0d9f,
+ 0x0dc0, 0x0dc0, 0x0dc0, 0x0dc0, 0x0dc1, 0x0dc1, 0x0dc2, 0x0dc2,
+ 0x0dc3, 0x0dc4, 0x0dc5, 0x0dc5, 0x0dc6, 0x0dc7, 0x0dc8, 0x0dc9,
+ 0x0dca, 0x0dcb, 0x0dcc, 0x0dce, 0x0dcf, 0x0dd0, 0x0dd1, 0x0dd3,
+ 0x0dd4, 0x0dd5, 0x0dd7, 0x0dd8, 0x0dda, 0x0ddb, 0x0ddd, 0x0ddf,
+ 0x0de0, 0x0de0, 0x0de0, 0x0de0, 0x0de1, 0x0de1, 0x0de2, 0x0de2,
+ 0x0de3, 0x0de4, 0x0de5, 0x0de5, 0x0de6, 0x0de7, 0x0de8, 0x0de9,
+ 0x0dea, 0x0deb, 0x0dec, 0x0dee, 0x0def, 0x0df0, 0x0df1, 0x0df3,
+ 0x0df4, 0x0df5, 0x0df7, 0x0df8, 0x0dfa, 0x0dfb, 0x0dfd, 0x0dff,
+ 0x0e20, 0x0e20, 0x0e20, 0x0e20, 0x0e21, 0x0e21, 0x0e22, 0x0e22,
+ 0x0e23, 0x0e24, 0x0e25, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29,
+ 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2e, 0x0e2f, 0x0e30, 0x0e31, 0x0e33,
+ 0x0e34, 0x0e35, 0x0e37, 0x0e38, 0x0e3a, 0x0e3b, 0x0e3d, 0x0e3f,
+ 0x0e40, 0x0e40, 0x0e40, 0x0e40, 0x0e41, 0x0e41, 0x0e42, 0x0e42,
+ 0x0e43, 0x0e44, 0x0e45, 0x0e45, 0x0e46, 0x0e47, 0x0e48, 0x0e49,
+ 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4e, 0x0e4f, 0x0e50, 0x0e51, 0x0e53,
+ 0x0e54, 0x0e55, 0x0e57, 0x0e58, 0x0e5a, 0x0e5b, 0x0e5d, 0x0e5f,
+ 0x0e80, 0x0e80, 0x0e80, 0x0e80, 0x0e81, 0x0e81, 0x0e82, 0x0e82,
+ 0x0e83, 0x0e84, 0x0e85, 0x0e85, 0x0e86, 0x0e87, 0x0e88, 0x0e89,
+ 0x0e8a, 0x0e8b, 0x0e8c, 0x0e8e, 0x0e8f, 0x0e90, 0x0e91, 0x0e93,
+ 0x0e94, 0x0e95, 0x0e97, 0x0e98, 0x0e9a, 0x0e9b, 0x0e9d, 0x0e9f,
+ 0x0ea0, 0x0ea0, 0x0ea0, 0x0ea0, 0x0ea1, 0x0ea1, 0x0ea2, 0x0ea2,
+ 0x0ea3, 0x0ea4, 0x0ea5, 0x0ea5, 0x0ea6, 0x0ea7, 0x0ea8, 0x0ea9,
+ 0x0eaa, 0x0eab, 0x0eac, 0x0eae, 0x0eaf, 0x0eb0, 0x0eb1, 0x0eb3,
+ 0x0eb4, 0x0eb5, 0x0eb7, 0x0eb8, 0x0eba, 0x0ebb, 0x0ebd, 0x0ebf,
+ 0x0ee0, 0x0ee0, 0x0ee0, 0x0ee0, 0x0ee1, 0x0ee1, 0x0ee2, 0x0ee2,
+ 0x0ee3, 0x0ee4, 0x0ee5, 0x0ee5, 0x0ee6, 0x0ee7, 0x0ee8, 0x0ee9,
+ 0x0eea, 0x0eeb, 0x0eec, 0x0eee, 0x0eef, 0x0ef0, 0x0ef1, 0x0ef3,
+ 0x0ef4, 0x0ef5, 0x0ef7, 0x0ef8, 0x0efa, 0x0efb, 0x0efd, 0x0eff,
+ 0x0f00, 0x0f00, 0x0f00, 0x0f00, 0x0f01, 0x0f01, 0x0f02, 0x0f02,
+ 0x0f03, 0x0f04, 0x0f05, 0x0f05, 0x0f06, 0x0f07, 0x0f08, 0x0f09,
+ 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0e, 0x0f0f, 0x0f10, 0x0f11, 0x0f13,
+ 0x0f14, 0x0f15, 0x0f17, 0x0f18, 0x0f1a, 0x0f1b, 0x0f1d, 0x0f1f,
+ 0x0f40, 0x0f40, 0x0f40, 0x0f40, 0x0f41, 0x0f41, 0x0f42, 0x0f42,
+ 0x0f43, 0x0f44, 0x0f45, 0x0f45, 0x0f46, 0x0f47, 0x0f48, 0x0f49,
+ 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4e, 0x0f4f, 0x0f50, 0x0f51, 0x0f53,
+ 0x0f54, 0x0f55, 0x0f57, 0x0f58, 0x0f5a, 0x0f5b, 0x0f5d, 0x0f5f,
+ 0x0f60, 0x0f60, 0x0f60, 0x0f60, 0x0f61, 0x0f61, 0x0f62, 0x0f62,
+ 0x0f63, 0x0f64, 0x0f65, 0x0f65, 0x0f66, 0x0f67, 0x0f68, 0x0f69,
+ 0x0f6a, 0x0f6b, 0x0f6c, 0x0f6e, 0x0f6f, 0x0f70, 0x0f71, 0x0f73,
+ 0x0f74, 0x0f75, 0x0f77, 0x0f78, 0x0f7a, 0x0f7b, 0x0f7d, 0x0f7f,
+ 0x0fa0, 0x0fa0, 0x0fa0, 0x0fa0, 0x0fa1, 0x0fa1, 0x0fa2, 0x0fa2,
+ 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa5, 0x0fa6, 0x0fa7, 0x0fa8, 0x0fa9,
+ 0x0faa, 0x0fab, 0x0fac, 0x0fae, 0x0faf, 0x0fb0, 0x0fb1, 0x0fb3,
+ 0x0fb4, 0x0fb5, 0x0fb7, 0x0fb8, 0x0fba, 0x0fbb, 0x0fbd, 0x0fbf,
+ 0x0fe0, 0x0fe0, 0x0fe0, 0x0fe0, 0x0fe1, 0x0fe1, 0x0fe2, 0x0fe2,
+ 0x0fe3, 0x0fe4, 0x0fe5, 0x0fe5, 0x0fe6, 0x0fe7, 0x0fe8, 0x0fe9,
+ 0x0fea, 0x0feb, 0x0fec, 0x0fee, 0x0fef, 0x0ff0, 0x0ff1, 0x0ff3,
+ 0x0ff4, 0x0ff5, 0x0ff7, 0x0ff8, 0x0ffa, 0x0ffb, 0x0ffd, 0x0fff,
+ 0x0800, 0x0800, 0x0800, 0x0800, 0x0801, 0x0801, 0x0802, 0x0802,
+ 0x0803, 0x0804, 0x0805, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809,
+ 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0811, 0x0813,
+ 0x0814, 0x0815, 0x0817, 0x0818, 0x081a, 0x081b, 0x081d, 0x081f,
+ 0x0800, 0x0800, 0x0800, 0x0800, 0x0801, 0x0801, 0x0802, 0x0802,
+ 0x0803, 0x0804, 0x0805, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809,
+ 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0811, 0x0813,
+ 0x0814, 0x0815, 0x0817, 0x0818, 0x081a, 0x081b, 0x081d, 0x081f,
+ 0x0800, 0x0800, 0x0800, 0x0800, 0x0801, 0x0801, 0x0802, 0x0802,
+ 0x0803, 0x0804, 0x0805, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809,
+ 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0811, 0x0813,
+ 0x0814, 0x0815, 0x0817, 0x0818, 0x081a, 0x081b, 0x081d, 0x081f,
+ 0x0800, 0x0800, 0x0800, 0x0800, 0x0801, 0x0801, 0x0802, 0x0802,
+ 0x0803, 0x0804, 0x0805, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809,
+ 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0811, 0x0813,
+ 0x0814, 0x0815, 0x0817, 0x0818, 0x081a, 0x081b, 0x081d, 0x081f,
+ 0x0800, 0x0800, 0x0800, 0x0800, 0x0801, 0x0801, 0x0802, 0x0802,
+ 0x0803, 0x0804, 0x0805, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809,
+ 0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0811, 0x0813,
+ 0x0814, 0x0815, 0x0817, 0x0818, 0x081a, 0x081b, 0x081d, 0x081f,
+ 0x0820, 0x0820, 0x0820, 0x0820, 0x0821, 0x0821, 0x0822, 0x0822,
+ 0x0823, 0x0824, 0x0825, 0x0825, 0x0826, 0x0827, 0x0828, 0x0829,
+ 0x082a, 0x082b, 0x082c, 0x082e, 0x082f, 0x0830, 0x0831, 0x0833,
+ 0x0834, 0x0835, 0x0837, 0x0838, 0x083a, 0x083b, 0x083d, 0x083f,
+ 0x0820, 0x0820, 0x0820, 0x0820, 0x0821, 0x0821, 0x0822, 0x0822,
+ 0x0823, 0x0824, 0x0825, 0x0825, 0x0826, 0x0827, 0x0828, 0x0829,
+ 0x082a, 0x082b, 0x082c, 0x082e, 0x082f, 0x0830, 0x0831, 0x0833,
+ 0x0834, 0x0835, 0x0837, 0x0838, 0x083a, 0x083b, 0x083d, 0x083f,
+ 0x0820, 0x0820, 0x0820, 0x0820, 0x0821, 0x0821, 0x0822, 0x0822,
+ 0x0823, 0x0824, 0x0825, 0x0825, 0x0826, 0x0827, 0x0828, 0x0829,
+ 0x082a, 0x082b, 0x082c, 0x082e, 0x082f, 0x0830, 0x0831, 0x0833,
+ 0x0834, 0x0835, 0x0837, 0x0838, 0x083a, 0x083b, 0x083d, 0x083f,
+ 0x0840, 0x0840, 0x0840, 0x0840, 0x0841, 0x0841, 0x0842, 0x0842,
+ 0x0843, 0x0844, 0x0845, 0x0845, 0x0846, 0x0847, 0x0848, 0x0849,
+ 0x084a, 0x084b, 0x084c, 0x084e, 0x084f, 0x0850, 0x0851, 0x0853,
+ 0x0854, 0x0855, 0x0857, 0x0858, 0x085a, 0x085b, 0x085d, 0x085f,
+ 0x0840, 0x0840, 0x0840, 0x0840, 0x0841, 0x0841, 0x0842, 0x0842,
+ 0x0843, 0x0844, 0x0845, 0x0845, 0x0846, 0x0847, 0x0848, 0x0849,
+ 0x084a, 0x084b, 0x084c, 0x084e, 0x084f, 0x0850, 0x0851, 0x0853,
+ 0x0854, 0x0855, 0x0857, 0x0858, 0x085a, 0x085b, 0x085d, 0x085f,
+ 0x0860, 0x0860, 0x0860, 0x0860, 0x0861, 0x0861, 0x0862, 0x0862,
+ 0x0863, 0x0864, 0x0865, 0x0865, 0x0866, 0x0867, 0x0868, 0x0869,
+ 0x086a, 0x086b, 0x086c, 0x086e, 0x086f, 0x0870, 0x0871, 0x0873,
+ 0x0874, 0x0875, 0x0877, 0x0878, 0x087a, 0x087b, 0x087d, 0x087f,
+ 0x0860, 0x0860, 0x0860, 0x0860, 0x0861, 0x0861, 0x0862, 0x0862,
+ 0x0863, 0x0864, 0x0865, 0x0865, 0x0866, 0x0867, 0x0868, 0x0869,
+ 0x086a, 0x086b, 0x086c, 0x086e, 0x086f, 0x0870, 0x0871, 0x0873,
+ 0x0874, 0x0875, 0x0877, 0x0878, 0x087a, 0x087b, 0x087d, 0x087f,
+ 0x0880, 0x0880, 0x0880, 0x0880, 0x0881, 0x0881, 0x0882, 0x0882,
+ 0x0883, 0x0884, 0x0885, 0x0885, 0x0886, 0x0887, 0x0888, 0x0889,
+ 0x088a, 0x088b, 0x088c, 0x088e, 0x088f, 0x0890, 0x0891, 0x0893,
+ 0x0894, 0x0895, 0x0897, 0x0898, 0x089a, 0x089b, 0x089d, 0x089f,
+ 0x08a0, 0x08a0, 0x08a0, 0x08a0, 0x08a1, 0x08a1, 0x08a2, 0x08a2,
+ 0x08a3, 0x08a4, 0x08a5, 0x08a5, 0x08a6, 0x08a7, 0x08a8, 0x08a9,
+ 0x08aa, 0x08ab, 0x08ac, 0x08ae, 0x08af, 0x08b0, 0x08b1, 0x08b3,
+ 0x08b4, 0x08b5, 0x08b7, 0x08b8, 0x08ba, 0x08bb, 0x08bd, 0x08bf,
+ 0x08a0, 0x08a0, 0x08a0, 0x08a0, 0x08a1, 0x08a1, 0x08a2, 0x08a2,
+ 0x08a3, 0x08a4, 0x08a5, 0x08a5, 0x08a6, 0x08a7, 0x08a8, 0x08a9,
+ 0x08aa, 0x08ab, 0x08ac, 0x08ae, 0x08af, 0x08b0, 0x08b1, 0x08b3,
+ 0x08b4, 0x08b5, 0x08b7, 0x08b8, 0x08ba, 0x08bb, 0x08bd, 0x08bf,
+ 0x08c0, 0x08c0, 0x08c0, 0x08c0, 0x08c1, 0x08c1, 0x08c2, 0x08c2,
+ 0x08c3, 0x08c4, 0x08c5, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9,
+ 0x08ca, 0x08cb, 0x08cc, 0x08ce, 0x08cf, 0x08d0, 0x08d1, 0x08d3,
+ 0x08d4, 0x08d5, 0x08d7, 0x08d8, 0x08da, 0x08db, 0x08dd, 0x08df,
+ 0x08e0, 0x08e0, 0x08e0, 0x08e0, 0x08e1, 0x08e1, 0x08e2, 0x08e2,
+ 0x08e3, 0x08e4, 0x08e5, 0x08e5, 0x08e6, 0x08e7, 0x08e8, 0x08e9,
+ 0x08ea, 0x08eb, 0x08ec, 0x08ee, 0x08ef, 0x08f0, 0x08f1, 0x08f3,
+ 0x08f4, 0x08f5, 0x08f7, 0x08f8, 0x08fa, 0x08fb, 0x08fd, 0x08ff,
+ 0x08e0, 0x08e0, 0x08e0, 0x08e0, 0x08e1, 0x08e1, 0x08e2, 0x08e2,
+ 0x08e3, 0x08e4, 0x08e5, 0x08e5, 0x08e6, 0x08e7, 0x08e8, 0x08e9,
+ 0x08ea, 0x08eb, 0x08ec, 0x08ee, 0x08ef, 0x08f0, 0x08f1, 0x08f3,
+ 0x08f4, 0x08f5, 0x08f7, 0x08f8, 0x08fa, 0x08fb, 0x08fd, 0x08ff,
+ 0x0900, 0x0900, 0x0900, 0x0900, 0x0901, 0x0901, 0x0902, 0x0902,
+ 0x0903, 0x0904, 0x0905, 0x0905, 0x0906, 0x0907, 0x0908, 0x0909,
+ 0x090a, 0x090b, 0x090c, 0x090e, 0x090f, 0x0910, 0x0911, 0x0913,
+ 0x0914, 0x0915, 0x0917, 0x0918, 0x091a, 0x091b, 0x091d, 0x091f,
+ 0x0920, 0x0920, 0x0920, 0x0920, 0x0921, 0x0921, 0x0922, 0x0922,
+ 0x0923, 0x0924, 0x0925, 0x0925, 0x0926, 0x0927, 0x0928, 0x0929,
+ 0x092a, 0x092b, 0x092c, 0x092e, 0x092f, 0x0930, 0x0931, 0x0933,
+ 0x0934, 0x0935, 0x0937, 0x0938, 0x093a, 0x093b, 0x093d, 0x093f,
+ 0x0940, 0x0940, 0x0940, 0x0940, 0x0941, 0x0941, 0x0942, 0x0942,
+ 0x0943, 0x0944, 0x0945, 0x0945, 0x0946, 0x0947, 0x0948, 0x0949,
+ 0x094a, 0x094b, 0x094c, 0x094e, 0x094f, 0x0950, 0x0951, 0x0953,
+ 0x0954, 0x0955, 0x0957, 0x0958, 0x095a, 0x095b, 0x095d, 0x095f,
+ 0x0940, 0x0940, 0x0940, 0x0940, 0x0941, 0x0941, 0x0942, 0x0942,
+ 0x0943, 0x0944, 0x0945, 0x0945, 0x0946, 0x0947, 0x0948, 0x0949,
+ 0x094a, 0x094b, 0x094c, 0x094e, 0x094f, 0x0950, 0x0951, 0x0953,
+ 0x0954, 0x0955, 0x0957, 0x0958, 0x095a, 0x095b, 0x095d, 0x095f,
+ 0x0960, 0x0960, 0x0960, 0x0960, 0x0961, 0x0961, 0x0962, 0x0962,
+ 0x0963, 0x0964, 0x0965, 0x0965, 0x0966, 0x0967, 0x0968, 0x0969,
+ 0x096a, 0x096b, 0x096c, 0x096e, 0x096f, 0x0970, 0x0971, 0x0973,
+ 0x0974, 0x0975, 0x0977, 0x0978, 0x097a, 0x097b, 0x097d, 0x097f,
+ 0x0980, 0x0980, 0x0980, 0x0980, 0x0981, 0x0981, 0x0982, 0x0982,
+ 0x0983, 0x0984, 0x0985, 0x0985, 0x0986, 0x0987, 0x0988, 0x0989,
+ 0x098a, 0x098b, 0x098c, 0x098e, 0x098f, 0x0990, 0x0991, 0x0993,
+ 0x0994, 0x0995, 0x0997, 0x0998, 0x099a, 0x099b, 0x099d, 0x099f,
+ 0x09a0, 0x09a0, 0x09a0, 0x09a0, 0x09a1, 0x09a1, 0x09a2, 0x09a2,
+ 0x09a3, 0x09a4, 0x09a5, 0x09a5, 0x09a6, 0x09a7, 0x09a8, 0x09a9,
+ 0x09aa, 0x09ab, 0x09ac, 0x09ae, 0x09af, 0x09b0, 0x09b1, 0x09b3,
+ 0x09b4, 0x09b5, 0x09b7, 0x09b8, 0x09ba, 0x09bb, 0x09bd, 0x09bf,
+ 0x09c0, 0x09c0, 0x09c0, 0x09c0, 0x09c1, 0x09c1, 0x09c2, 0x09c2,
+ 0x09c3, 0x09c4, 0x09c5, 0x09c5, 0x09c6, 0x09c7, 0x09c8, 0x09c9,
+ 0x09ca, 0x09cb, 0x09cc, 0x09ce, 0x09cf, 0x09d0, 0x09d1, 0x09d3,
+ 0x09d4, 0x09d5, 0x09d7, 0x09d8, 0x09da, 0x09db, 0x09dd, 0x09df,
+ 0x09e0, 0x09e0, 0x09e0, 0x09e0, 0x09e1, 0x09e1, 0x09e2, 0x09e2,
+ 0x09e3, 0x09e4, 0x09e5, 0x09e5, 0x09e6, 0x09e7, 0x09e8, 0x09e9,
+ 0x09ea, 0x09eb, 0x09ec, 0x09ee, 0x09ef, 0x09f0, 0x09f1, 0x09f3,
+ 0x09f4, 0x09f5, 0x09f7, 0x09f8, 0x09fa, 0x09fb, 0x09fd, 0x09ff,
+ 0x0a00, 0x0a00, 0x0a00, 0x0a00, 0x0a01, 0x0a01, 0x0a02, 0x0a02,
+ 0x0a03, 0x0a04, 0x0a05, 0x0a05, 0x0a06, 0x0a07, 0x0a08, 0x0a09,
+ 0x0a0a, 0x0a0b, 0x0a0c, 0x0a0e, 0x0a0f, 0x0a10, 0x0a11, 0x0a13,
+ 0x0a14, 0x0a15, 0x0a17, 0x0a18, 0x0a1a, 0x0a1b, 0x0a1d, 0x0a1f,
+ 0x0a20, 0x0a20, 0x0a20, 0x0a20, 0x0a21, 0x0a21, 0x0a22, 0x0a22,
+ 0x0a23, 0x0a24, 0x0a25, 0x0a25, 0x0a26, 0x0a27, 0x0a28, 0x0a29,
+ 0x0a2a, 0x0a2b, 0x0a2c, 0x0a2e, 0x0a2f, 0x0a30, 0x0a31, 0x0a33,
+ 0x0a34, 0x0a35, 0x0a37, 0x0a38, 0x0a3a, 0x0a3b, 0x0a3d, 0x0a3f,
+ 0x0a40, 0x0a40, 0x0a40, 0x0a40, 0x0a41, 0x0a41, 0x0a42, 0x0a42,
+ 0x0a43, 0x0a44, 0x0a45, 0x0a45, 0x0a46, 0x0a47, 0x0a48, 0x0a49,
+ 0x0a4a, 0x0a4b, 0x0a4c, 0x0a4e, 0x0a4f, 0x0a50, 0x0a51, 0x0a53,
+ 0x0a54, 0x0a55, 0x0a57, 0x0a58, 0x0a5a, 0x0a5b, 0x0a5d, 0x0a5f,
+ 0x0a60, 0x0a60, 0x0a60, 0x0a60, 0x0a61, 0x0a61, 0x0a62, 0x0a62,
+ 0x0a63, 0x0a64, 0x0a65, 0x0a65, 0x0a66, 0x0a67, 0x0a68, 0x0a69,
+ 0x0a6a, 0x0a6b, 0x0a6c, 0x0a6e, 0x0a6f, 0x0a70, 0x0a71, 0x0a73,
+ 0x0a74, 0x0a75, 0x0a77, 0x0a78, 0x0a7a, 0x0a7b, 0x0a7d, 0x0a7f,
+ 0x0a80, 0x0a80, 0x0a80, 0x0a80, 0x0a81, 0x0a81, 0x0a82, 0x0a82,
+ 0x0a83, 0x0a84, 0x0a85, 0x0a85, 0x0a86, 0x0a87, 0x0a88, 0x0a89,
+ 0x0a8a, 0x0a8b, 0x0a8c, 0x0a8e, 0x0a8f, 0x0a90, 0x0a91, 0x0a93,
+ 0x0a94, 0x0a95, 0x0a97, 0x0a98, 0x0a9a, 0x0a9b, 0x0a9d, 0x0a9f,
+ 0x0aa0, 0x0aa0, 0x0aa0, 0x0aa0, 0x0aa1, 0x0aa1, 0x0aa2, 0x0aa2,
+ 0x0aa3, 0x0aa4, 0x0aa5, 0x0aa5, 0x0aa6, 0x0aa7, 0x0aa8, 0x0aa9,
+ 0x0aaa, 0x0aab, 0x0aac, 0x0aae, 0x0aaf, 0x0ab0, 0x0ab1, 0x0ab3,
+ 0x0ab4, 0x0ab5, 0x0ab7, 0x0ab8, 0x0aba, 0x0abb, 0x0abd, 0x0abf,
+ 0x0ac0, 0x0ac0, 0x0ac0, 0x0ac0, 0x0ac1, 0x0ac1, 0x0ac2, 0x0ac2,
+ 0x0ac3, 0x0ac4, 0x0ac5, 0x0ac5, 0x0ac6, 0x0ac7, 0x0ac8, 0x0ac9,
+ 0x0aca, 0x0acb, 0x0acc, 0x0ace, 0x0acf, 0x0ad0, 0x0ad1, 0x0ad3,
+ 0x0ad4, 0x0ad5, 0x0ad7, 0x0ad8, 0x0ada, 0x0adb, 0x0add, 0x0adf,
+ 0x0ae0, 0x0ae0, 0x0ae0, 0x0ae0, 0x0ae1, 0x0ae1, 0x0ae2, 0x0ae2,
+ 0x0ae3, 0x0ae4, 0x0ae5, 0x0ae5, 0x0ae6, 0x0ae7, 0x0ae8, 0x0ae9,
+ 0x0aea, 0x0aeb, 0x0aec, 0x0aee, 0x0aef, 0x0af0, 0x0af1, 0x0af3,
+ 0x0af4, 0x0af5, 0x0af7, 0x0af8, 0x0afa, 0x0afb, 0x0afd, 0x0aff,
+ 0x0b00, 0x0b00, 0x0b00, 0x0b00, 0x0b01, 0x0b01, 0x0b02, 0x0b02,
+ 0x0b03, 0x0b04, 0x0b05, 0x0b05, 0x0b06, 0x0b07, 0x0b08, 0x0b09,
+ 0x0b0a, 0x0b0b, 0x0b0c, 0x0b0e, 0x0b0f, 0x0b10, 0x0b11, 0x0b13,
+ 0x0b14, 0x0b15, 0x0b17, 0x0b18, 0x0b1a, 0x0b1b, 0x0b1d, 0x0b1f,
+ 0x0b20, 0x0b20, 0x0b20, 0x0b20, 0x0b21, 0x0b21, 0x0b22, 0x0b22,
+ 0x0b23, 0x0b24, 0x0b25, 0x0b25, 0x0b26, 0x0b27, 0x0b28, 0x0b29,
+ 0x0b2a, 0x0b2b, 0x0b2c, 0x0b2e, 0x0b2f, 0x0b30, 0x0b31, 0x0b33,
+ 0x0b34, 0x0b35, 0x0b37, 0x0b38, 0x0b3a, 0x0b3b, 0x0b3d, 0x0b3f,
+ 0x0b40, 0x0b40, 0x0b40, 0x0b40, 0x0b41, 0x0b41, 0x0b42, 0x0b42,
+ 0x0b43, 0x0b44, 0x0b45, 0x0b45, 0x0b46, 0x0b47, 0x0b48, 0x0b49,
+ 0x0b4a, 0x0b4b, 0x0b4c, 0x0b4e, 0x0b4f, 0x0b50, 0x0b51, 0x0b53,
+ 0x0b54, 0x0b55, 0x0b57, 0x0b58, 0x0b5a, 0x0b5b, 0x0b5d, 0x0b5f,
+ 0x0b80, 0x0b80, 0x0b80, 0x0b80, 0x0b81, 0x0b81, 0x0b82, 0x0b82,
+ 0x0b83, 0x0b84, 0x0b85, 0x0b85, 0x0b86, 0x0b87, 0x0b88, 0x0b89,
+ 0x0b8a, 0x0b8b, 0x0b8c, 0x0b8e, 0x0b8f, 0x0b90, 0x0b91, 0x0b93,
+ 0x0b94, 0x0b95, 0x0b97, 0x0b98, 0x0b9a, 0x0b9b, 0x0b9d, 0x0b9f,
+ 0x0ba0, 0x0ba0, 0x0ba0, 0x0ba0, 0x0ba1, 0x0ba1, 0x0ba2, 0x0ba2,
+ 0x0ba3, 0x0ba4, 0x0ba5, 0x0ba5, 0x0ba6, 0x0ba7, 0x0ba8, 0x0ba9,
+ 0x0baa, 0x0bab, 0x0bac, 0x0bae, 0x0baf, 0x0bb0, 0x0bb1, 0x0bb3,
+ 0x0bb4, 0x0bb5, 0x0bb7, 0x0bb8, 0x0bba, 0x0bbb, 0x0bbd, 0x0bbf,
+ 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc0, 0x0bc1, 0x0bc1, 0x0bc2, 0x0bc2,
+ 0x0bc3, 0x0bc4, 0x0bc5, 0x0bc5, 0x0bc6, 0x0bc7, 0x0bc8, 0x0bc9,
+ 0x0bca, 0x0bcb, 0x0bcc, 0x0bce, 0x0bcf, 0x0bd0, 0x0bd1, 0x0bd3,
+ 0x0bd4, 0x0bd5, 0x0bd7, 0x0bd8, 0x0bda, 0x0bdb, 0x0bdd, 0x0bdf,
+ 0x0be0, 0x0be0, 0x0be0, 0x0be0, 0x0be1, 0x0be1, 0x0be2, 0x0be2,
+ 0x0be3, 0x0be4, 0x0be5, 0x0be5, 0x0be6, 0x0be7, 0x0be8, 0x0be9,
+ 0x0bea, 0x0beb, 0x0bec, 0x0bee, 0x0bef, 0x0bf0, 0x0bf1, 0x0bf3,
+ 0x0bf4, 0x0bf5, 0x0bf7, 0x0bf8, 0x0bfa, 0x0bfb, 0x0bfd, 0x0bff,
+ 0x0c00, 0x0c00, 0x0c00, 0x0c00, 0x0c01, 0x0c01, 0x0c02, 0x0c02,
+ 0x0c03, 0x0c04, 0x0c05, 0x0c05, 0x0c06, 0x0c07, 0x0c08, 0x0c09,
+ 0x0c0a, 0x0c0b, 0x0c0c, 0x0c0e, 0x0c0f, 0x0c10, 0x0c11, 0x0c13,
+ 0x0c14, 0x0c15, 0x0c17, 0x0c18, 0x0c1a, 0x0c1b, 0x0c1d, 0x0c1f,
+ 0x0c40, 0x0c40, 0x0c40, 0x0c40, 0x0c41, 0x0c41, 0x0c42, 0x0c42,
+ 0x0c43, 0x0c44, 0x0c45, 0x0c45, 0x0c46, 0x0c47, 0x0c48, 0x0c49,
+ 0x0c4a, 0x0c4b, 0x0c4c, 0x0c4e, 0x0c4f, 0x0c50, 0x0c51, 0x0c53,
+ 0x0c54, 0x0c55, 0x0c57, 0x0c58, 0x0c5a, 0x0c5b, 0x0c5d, 0x0c5f,
+ 0x0c60, 0x0c60, 0x0c60, 0x0c60, 0x0c61, 0x0c61, 0x0c62, 0x0c62,
+ 0x0c63, 0x0c64, 0x0c65, 0x0c65, 0x0c66, 0x0c67, 0x0c68, 0x0c69,
+ 0x0c6a, 0x0c6b, 0x0c6c, 0x0c6e, 0x0c6f, 0x0c70, 0x0c71, 0x0c73,
+ 0x0c74, 0x0c75, 0x0c77, 0x0c78, 0x0c7a, 0x0c7b, 0x0c7d, 0x0c7f,
+ 0x0c80, 0x0c80, 0x0c80, 0x0c80, 0x0c81, 0x0c81, 0x0c82, 0x0c82,
+ 0x0c83, 0x0c84, 0x0c85, 0x0c85, 0x0c86, 0x0c87, 0x0c88, 0x0c89,
+ 0x0c8a, 0x0c8b, 0x0c8c, 0x0c8e, 0x0c8f, 0x0c90, 0x0c91, 0x0c93,
+ 0x0c94, 0x0c95, 0x0c97, 0x0c98, 0x0c9a, 0x0c9b, 0x0c9d, 0x0c9f,
+ 0x0cc0, 0x0cc0, 0x0cc0, 0x0cc0, 0x0cc1, 0x0cc1, 0x0cc2, 0x0cc2,
+ 0x0cc3, 0x0cc4, 0x0cc5, 0x0cc5, 0x0cc6, 0x0cc7, 0x0cc8, 0x0cc9,
+ 0x0cca, 0x0ccb, 0x0ccc, 0x0cce, 0x0ccf, 0x0cd0, 0x0cd1, 0x0cd3,
+ 0x0cd4, 0x0cd5, 0x0cd7, 0x0cd8, 0x0cda, 0x0cdb, 0x0cdd, 0x0cdf,
+ 0x0ce0, 0x0ce0, 0x0ce0, 0x0ce0, 0x0ce1, 0x0ce1, 0x0ce2, 0x0ce2,
+ 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9,
+ 0x0cea, 0x0ceb, 0x0cec, 0x0cee, 0x0cef, 0x0cf0, 0x0cf1, 0x0cf3,
+ 0x0cf4, 0x0cf5, 0x0cf7, 0x0cf8, 0x0cfa, 0x0cfb, 0x0cfd, 0x0cff,
+ 0x0d00, 0x0d00, 0x0d00, 0x0d00, 0x0d01, 0x0d01, 0x0d02, 0x0d02,
+ 0x0d03, 0x0d04, 0x0d05, 0x0d05, 0x0d06, 0x0d07, 0x0d08, 0x0d09,
+ 0x0d0a, 0x0d0b, 0x0d0c, 0x0d0e, 0x0d0f, 0x0d10, 0x0d11, 0x0d13,
+ 0x0d14, 0x0d15, 0x0d17, 0x0d18, 0x0d1a, 0x0d1b, 0x0d1d, 0x0d1f,
+ 0x0d40, 0x0d40, 0x0d40, 0x0d40, 0x0d41, 0x0d41, 0x0d42, 0x0d42,
+ 0x0d43, 0x0d44, 0x0d45, 0x0d45, 0x0d46, 0x0d47, 0x0d48, 0x0d49,
+ 0x0d4a, 0x0d4b, 0x0d4c, 0x0d4e, 0x0d4f, 0x0d50, 0x0d51, 0x0d53,
+ 0x0d54, 0x0d55, 0x0d57, 0x0d58, 0x0d5a, 0x0d5b, 0x0d5d, 0x0d5f,
+ 0x0d60, 0x0d60, 0x0d60, 0x0d60, 0x0d61, 0x0d61, 0x0d62, 0x0d62,
+ 0x0d63, 0x0d64, 0x0d65, 0x0d65, 0x0d66, 0x0d67, 0x0d68, 0x0d69,
+ 0x0d6a, 0x0d6b, 0x0d6c, 0x0d6e, 0x0d6f, 0x0d70, 0x0d71, 0x0d73,
+ 0x0d74, 0x0d75, 0x0d77, 0x0d78, 0x0d7a, 0x0d7b, 0x0d7d, 0x0d7f,
+ 0x0d80, 0x0d80, 0x0d80, 0x0d80, 0x0d81, 0x0d81, 0x0d82, 0x0d82,
+ 0x0d83, 0x0d84, 0x0d85, 0x0d85, 0x0d86, 0x0d87, 0x0d88, 0x0d89,
+ 0x0d8a, 0x0d8b, 0x0d8c, 0x0d8e, 0x0d8f, 0x0d90, 0x0d91, 0x0d93,
+ 0x0d94, 0x0d95, 0x0d97, 0x0d98, 0x0d9a, 0x0d9b, 0x0d9d, 0x0d9f,
+ 0x0dc0, 0x0dc0, 0x0dc0, 0x0dc0, 0x0dc1, 0x0dc1, 0x0dc2, 0x0dc2,
+ 0x0dc3, 0x0dc4, 0x0dc5, 0x0dc5, 0x0dc6, 0x0dc7, 0x0dc8, 0x0dc9,
+ 0x0dca, 0x0dcb, 0x0dcc, 0x0dce, 0x0dcf, 0x0dd0, 0x0dd1, 0x0dd3,
+ 0x0dd4, 0x0dd5, 0x0dd7, 0x0dd8, 0x0dda, 0x0ddb, 0x0ddd, 0x0ddf,
+ 0x0de0, 0x0de0, 0x0de0, 0x0de0, 0x0de1, 0x0de1, 0x0de2, 0x0de2,
+ 0x0de3, 0x0de4, 0x0de5, 0x0de5, 0x0de6, 0x0de7, 0x0de8, 0x0de9,
+ 0x0dea, 0x0deb, 0x0dec, 0x0dee, 0x0def, 0x0df0, 0x0df1, 0x0df3,
+ 0x0df4, 0x0df5, 0x0df7, 0x0df8, 0x0dfa, 0x0dfb, 0x0dfd, 0x0dff,
+ 0x0e20, 0x0e20, 0x0e20, 0x0e20, 0x0e21, 0x0e21, 0x0e22, 0x0e22,
+ 0x0e23, 0x0e24, 0x0e25, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29,
+ 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2e, 0x0e2f, 0x0e30, 0x0e31, 0x0e33,
+ 0x0e34, 0x0e35, 0x0e37, 0x0e38, 0x0e3a, 0x0e3b, 0x0e3d, 0x0e3f,
+ 0x0e40, 0x0e40, 0x0e40, 0x0e40, 0x0e41, 0x0e41, 0x0e42, 0x0e42,
+ 0x0e43, 0x0e44, 0x0e45, 0x0e45, 0x0e46, 0x0e47, 0x0e48, 0x0e49,
+ 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4e, 0x0e4f, 0x0e50, 0x0e51, 0x0e53,
+ 0x0e54, 0x0e55, 0x0e57, 0x0e58, 0x0e5a, 0x0e5b, 0x0e5d, 0x0e5f,
+ 0x0e80, 0x0e80, 0x0e80, 0x0e80, 0x0e81, 0x0e81, 0x0e82, 0x0e82,
+ 0x0e83, 0x0e84, 0x0e85, 0x0e85, 0x0e86, 0x0e87, 0x0e88, 0x0e89,
+ 0x0e8a, 0x0e8b, 0x0e8c, 0x0e8e, 0x0e8f, 0x0e90, 0x0e91, 0x0e93,
+ 0x0e94, 0x0e95, 0x0e97, 0x0e98, 0x0e9a, 0x0e9b, 0x0e9d, 0x0e9f,
+ 0x0ea0, 0x0ea0, 0x0ea0, 0x0ea0, 0x0ea1, 0x0ea1, 0x0ea2, 0x0ea2,
+ 0x0ea3, 0x0ea4, 0x0ea5, 0x0ea5, 0x0ea6, 0x0ea7, 0x0ea8, 0x0ea9,
+ 0x0eaa, 0x0eab, 0x0eac, 0x0eae, 0x0eaf, 0x0eb0, 0x0eb1, 0x0eb3,
+ 0x0eb4, 0x0eb5, 0x0eb7, 0x0eb8, 0x0eba, 0x0ebb, 0x0ebd, 0x0ebf,
+ 0x0ee0, 0x0ee0, 0x0ee0, 0x0ee0, 0x0ee1, 0x0ee1, 0x0ee2, 0x0ee2,
+ 0x0ee3, 0x0ee4, 0x0ee5, 0x0ee5, 0x0ee6, 0x0ee7, 0x0ee8, 0x0ee9,
+ 0x0eea, 0x0eeb, 0x0eec, 0x0eee, 0x0eef, 0x0ef0, 0x0ef1, 0x0ef3,
+ 0x0ef4, 0x0ef5, 0x0ef7, 0x0ef8, 0x0efa, 0x0efb, 0x0efd, 0x0eff,
+ 0x0f00, 0x0f00, 0x0f00, 0x0f00, 0x0f01, 0x0f01, 0x0f02, 0x0f02,
+ 0x0f03, 0x0f04, 0x0f05, 0x0f05, 0x0f06, 0x0f07, 0x0f08, 0x0f09,
+ 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0e, 0x0f0f, 0x0f10, 0x0f11, 0x0f13,
+ 0x0f14, 0x0f15, 0x0f17, 0x0f18, 0x0f1a, 0x0f1b, 0x0f1d, 0x0f1f,
+ 0x0f40, 0x0f40, 0x0f40, 0x0f40, 0x0f41, 0x0f41, 0x0f42, 0x0f42,
+ 0x0f43, 0x0f44, 0x0f45, 0x0f45, 0x0f46, 0x0f47, 0x0f48, 0x0f49,
+ 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4e, 0x0f4f, 0x0f50, 0x0f51, 0x0f53,
+ 0x0f54, 0x0f55, 0x0f57, 0x0f58, 0x0f5a, 0x0f5b, 0x0f5d, 0x0f5f,
+ 0x0f60, 0x0f60, 0x0f60, 0x0f60, 0x0f61, 0x0f61, 0x0f62, 0x0f62,
+ 0x0f63, 0x0f64, 0x0f65, 0x0f65, 0x0f66, 0x0f67, 0x0f68, 0x0f69,
+ 0x0f6a, 0x0f6b, 0x0f6c, 0x0f6e, 0x0f6f, 0x0f70, 0x0f71, 0x0f73,
+ 0x0f74, 0x0f75, 0x0f77, 0x0f78, 0x0f7a, 0x0f7b, 0x0f7d, 0x0f7f,
+ 0x0fa0, 0x0fa0, 0x0fa0, 0x0fa0, 0x0fa1, 0x0fa1, 0x0fa2, 0x0fa2,
+ 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa5, 0x0fa6, 0x0fa7, 0x0fa8, 0x0fa9,
+ 0x0faa, 0x0fab, 0x0fac, 0x0fae, 0x0faf, 0x0fb0, 0x0fb1, 0x0fb3,
+ 0x0fb4, 0x0fb5, 0x0fb7, 0x0fb8, 0x0fba, 0x0fbb, 0x0fbd, 0x0fbf,
+ 0x0fe0, 0x0fe0, 0x0fe0, 0x0fe0, 0x0fe1, 0x0fe1, 0x0fe2, 0x0fe2,
+ 0x0fe3, 0x0fe4, 0x0fe5, 0x0fe5, 0x0fe6, 0x0fe7, 0x0fe8, 0x0fe9,
+ 0x0fea, 0x0feb, 0x0fec, 0x0fee, 0x0fef, 0x0ff0, 0x0ff1, 0x0ff3,
+ 0x0ff4, 0x0ff5, 0x0ff7, 0x0ff8, 0x0ffa, 0x0ffb, 0x0ffd, 0x0fff,
+ 0x1000, 0x1000, 0x1000, 0x1000, 0x1001, 0x1001, 0x1002, 0x1002,
+ 0x1003, 0x1004, 0x1005, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009,
+ 0x100a, 0x100b, 0x100c, 0x100e, 0x100f, 0x1010, 0x1011, 0x1013,
+ 0x1014, 0x1015, 0x1017, 0x1018, 0x101a, 0x101b, 0x101d, 0x101f,
+ 0x1000, 0x1000, 0x1000, 0x1000, 0x1001, 0x1001, 0x1002, 0x1002,
+ 0x1003, 0x1004, 0x1005, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009,
+ 0x100a, 0x100b, 0x100c, 0x100e, 0x100f, 0x1010, 0x1011, 0x1013,
+ 0x1014, 0x1015, 0x1017, 0x1018, 0x101a, 0x101b, 0x101d, 0x101f,
+ 0x1000, 0x1000, 0x1000, 0x1000, 0x1001, 0x1001, 0x1002, 0x1002,
+ 0x1003, 0x1004, 0x1005, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009,
+ 0x100a, 0x100b, 0x100c, 0x100e, 0x100f, 0x1010, 0x1011, 0x1013,
+ 0x1014, 0x1015, 0x1017, 0x1018, 0x101a, 0x101b, 0x101d, 0x101f,
+ 0x1000, 0x1000, 0x1000, 0x1000, 0x1001, 0x1001, 0x1002, 0x1002,
+ 0x1003, 0x1004, 0x1005, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009,
+ 0x100a, 0x100b, 0x100c, 0x100e, 0x100f, 0x1010, 0x1011, 0x1013,
+ 0x1014, 0x1015, 0x1017, 0x1018, 0x101a, 0x101b, 0x101d, 0x101f,
+ 0x1000, 0x1000, 0x1000, 0x1000, 0x1001, 0x1001, 0x1002, 0x1002,
+ 0x1003, 0x1004, 0x1005, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009,
+ 0x100a, 0x100b, 0x100c, 0x100e, 0x100f, 0x1010, 0x1011, 0x1013,
+ 0x1014, 0x1015, 0x1017, 0x1018, 0x101a, 0x101b, 0x101d, 0x101f,
+ 0x1020, 0x1020, 0x1020, 0x1020, 0x1021, 0x1021, 0x1022, 0x1022,
+ 0x1023, 0x1024, 0x1025, 0x1025, 0x1026, 0x1027, 0x1028, 0x1029,
+ 0x102a, 0x102b, 0x102c, 0x102e, 0x102f, 0x1030, 0x1031, 0x1033,
+ 0x1034, 0x1035, 0x1037, 0x1038, 0x103a, 0x103b, 0x103d, 0x103f,
+ 0x1020, 0x1020, 0x1020, 0x1020, 0x1021, 0x1021, 0x1022, 0x1022,
+ 0x1023, 0x1024, 0x1025, 0x1025, 0x1026, 0x1027, 0x1028, 0x1029,
+ 0x102a, 0x102b, 0x102c, 0x102e, 0x102f, 0x1030, 0x1031, 0x1033,
+ 0x1034, 0x1035, 0x1037, 0x1038, 0x103a, 0x103b, 0x103d, 0x103f,
+ 0x1020, 0x1020, 0x1020, 0x1020, 0x1021, 0x1021, 0x1022, 0x1022,
+ 0x1023, 0x1024, 0x1025, 0x1025, 0x1026, 0x1027, 0x1028, 0x1029,
+ 0x102a, 0x102b, 0x102c, 0x102e, 0x102f, 0x1030, 0x1031, 0x1033,
+ 0x1034, 0x1035, 0x1037, 0x1038, 0x103a, 0x103b, 0x103d, 0x103f,
+ 0x1040, 0x1040, 0x1040, 0x1040, 0x1041, 0x1041, 0x1042, 0x1042,
+ 0x1043, 0x1044, 0x1045, 0x1045, 0x1046, 0x1047, 0x1048, 0x1049,
+ 0x104a, 0x104b, 0x104c, 0x104e, 0x104f, 0x1050, 0x1051, 0x1053,
+ 0x1054, 0x1055, 0x1057, 0x1058, 0x105a, 0x105b, 0x105d, 0x105f,
+ 0x1040, 0x1040, 0x1040, 0x1040, 0x1041, 0x1041, 0x1042, 0x1042,
+ 0x1043, 0x1044, 0x1045, 0x1045, 0x1046, 0x1047, 0x1048, 0x1049,
+ 0x104a, 0x104b, 0x104c, 0x104e, 0x104f, 0x1050, 0x1051, 0x1053,
+ 0x1054, 0x1055, 0x1057, 0x1058, 0x105a, 0x105b, 0x105d, 0x105f,
+ 0x1060, 0x1060, 0x1060, 0x1060, 0x1061, 0x1061, 0x1062, 0x1062,
+ 0x1063, 0x1064, 0x1065, 0x1065, 0x1066, 0x1067, 0x1068, 0x1069,
+ 0x106a, 0x106b, 0x106c, 0x106e, 0x106f, 0x1070, 0x1071, 0x1073,
+ 0x1074, 0x1075, 0x1077, 0x1078, 0x107a, 0x107b, 0x107d, 0x107f,
+ 0x1060, 0x1060, 0x1060, 0x1060, 0x1061, 0x1061, 0x1062, 0x1062,
+ 0x1063, 0x1064, 0x1065, 0x1065, 0x1066, 0x1067, 0x1068, 0x1069,
+ 0x106a, 0x106b, 0x106c, 0x106e, 0x106f, 0x1070, 0x1071, 0x1073,
+ 0x1074, 0x1075, 0x1077, 0x1078, 0x107a, 0x107b, 0x107d, 0x107f,
+ 0x1080, 0x1080, 0x1080, 0x1080, 0x1081, 0x1081, 0x1082, 0x1082,
+ 0x1083, 0x1084, 0x1085, 0x1085, 0x1086, 0x1087, 0x1088, 0x1089,
+ 0x108a, 0x108b, 0x108c, 0x108e, 0x108f, 0x1090, 0x1091, 0x1093,
+ 0x1094, 0x1095, 0x1097, 0x1098, 0x109a, 0x109b, 0x109d, 0x109f,
+ 0x10a0, 0x10a0, 0x10a0, 0x10a0, 0x10a1, 0x10a1, 0x10a2, 0x10a2,
+ 0x10a3, 0x10a4, 0x10a5, 0x10a5, 0x10a6, 0x10a7, 0x10a8, 0x10a9,
+ 0x10aa, 0x10ab, 0x10ac, 0x10ae, 0x10af, 0x10b0, 0x10b1, 0x10b3,
+ 0x10b4, 0x10b5, 0x10b7, 0x10b8, 0x10ba, 0x10bb, 0x10bd, 0x10bf,
+ 0x10a0, 0x10a0, 0x10a0, 0x10a0, 0x10a1, 0x10a1, 0x10a2, 0x10a2,
+ 0x10a3, 0x10a4, 0x10a5, 0x10a5, 0x10a6, 0x10a7, 0x10a8, 0x10a9,
+ 0x10aa, 0x10ab, 0x10ac, 0x10ae, 0x10af, 0x10b0, 0x10b1, 0x10b3,
+ 0x10b4, 0x10b5, 0x10b7, 0x10b8, 0x10ba, 0x10bb, 0x10bd, 0x10bf,
+ 0x10c0, 0x10c0, 0x10c0, 0x10c0, 0x10c1, 0x10c1, 0x10c2, 0x10c2,
+ 0x10c3, 0x10c4, 0x10c5, 0x10c5, 0x10c6, 0x10c7, 0x10c8, 0x10c9,
+ 0x10ca, 0x10cb, 0x10cc, 0x10ce, 0x10cf, 0x10d0, 0x10d1, 0x10d3,
+ 0x10d4, 0x10d5, 0x10d7, 0x10d8, 0x10da, 0x10db, 0x10dd, 0x10df,
+ 0x10e0, 0x10e0, 0x10e0, 0x10e0, 0x10e1, 0x10e1, 0x10e2, 0x10e2,
+ 0x10e3, 0x10e4, 0x10e5, 0x10e5, 0x10e6, 0x10e7, 0x10e8, 0x10e9,
+ 0x10ea, 0x10eb, 0x10ec, 0x10ee, 0x10ef, 0x10f0, 0x10f1, 0x10f3,
+ 0x10f4, 0x10f5, 0x10f7, 0x10f8, 0x10fa, 0x10fb, 0x10fd, 0x10ff,
+ 0x10e0, 0x10e0, 0x10e0, 0x10e0, 0x10e1, 0x10e1, 0x10e2, 0x10e2,
+ 0x10e3, 0x10e4, 0x10e5, 0x10e5, 0x10e6, 0x10e7, 0x10e8, 0x10e9,
+ 0x10ea, 0x10eb, 0x10ec, 0x10ee, 0x10ef, 0x10f0, 0x10f1, 0x10f3,
+ 0x10f4, 0x10f5, 0x10f7, 0x10f8, 0x10fa, 0x10fb, 0x10fd, 0x10ff,
+ 0x1100, 0x1100, 0x1100, 0x1100, 0x1101, 0x1101, 0x1102, 0x1102,
+ 0x1103, 0x1104, 0x1105, 0x1105, 0x1106, 0x1107, 0x1108, 0x1109,
+ 0x110a, 0x110b, 0x110c, 0x110e, 0x110f, 0x1110, 0x1111, 0x1113,
+ 0x1114, 0x1115, 0x1117, 0x1118, 0x111a, 0x111b, 0x111d, 0x111f,
+ 0x1120, 0x1120, 0x1120, 0x1120, 0x1121, 0x1121, 0x1122, 0x1122,
+ 0x1123, 0x1124, 0x1125, 0x1125, 0x1126, 0x1127, 0x1128, 0x1129,
+ 0x112a, 0x112b, 0x112c, 0x112e, 0x112f, 0x1130, 0x1131, 0x1133,
+ 0x1134, 0x1135, 0x1137, 0x1138, 0x113a, 0x113b, 0x113d, 0x113f,
+ 0x1140, 0x1140, 0x1140, 0x1140, 0x1141, 0x1141, 0x1142, 0x1142,
+ 0x1143, 0x1144, 0x1145, 0x1145, 0x1146, 0x1147, 0x1148, 0x1149,
+ 0x114a, 0x114b, 0x114c, 0x114e, 0x114f, 0x1150, 0x1151, 0x1153,
+ 0x1154, 0x1155, 0x1157, 0x1158, 0x115a, 0x115b, 0x115d, 0x115f,
+ 0x1140, 0x1140, 0x1140, 0x1140, 0x1141, 0x1141, 0x1142, 0x1142,
+ 0x1143, 0x1144, 0x1145, 0x1145, 0x1146, 0x1147, 0x1148, 0x1149,
+ 0x114a, 0x114b, 0x114c, 0x114e, 0x114f, 0x1150, 0x1151, 0x1153,
+ 0x1154, 0x1155, 0x1157, 0x1158, 0x115a, 0x115b, 0x115d, 0x115f,
+ 0x1160, 0x1160, 0x1160, 0x1160, 0x1161, 0x1161, 0x1162, 0x1162,
+ 0x1163, 0x1164, 0x1165, 0x1165, 0x1166, 0x1167, 0x1168, 0x1169,
+ 0x116a, 0x116b, 0x116c, 0x116e, 0x116f, 0x1170, 0x1171, 0x1173,
+ 0x1174, 0x1175, 0x1177, 0x1178, 0x117a, 0x117b, 0x117d, 0x117f,
+ 0x1180, 0x1180, 0x1180, 0x1180, 0x1181, 0x1181, 0x1182, 0x1182,
+ 0x1183, 0x1184, 0x1185, 0x1185, 0x1186, 0x1187, 0x1188, 0x1189,
+ 0x118a, 0x118b, 0x118c, 0x118e, 0x118f, 0x1190, 0x1191, 0x1193,
+ 0x1194, 0x1195, 0x1197, 0x1198, 0x119a, 0x119b, 0x119d, 0x119f,
+ 0x11a0, 0x11a0, 0x11a0, 0x11a0, 0x11a1, 0x11a1, 0x11a2, 0x11a2,
+ 0x11a3, 0x11a4, 0x11a5, 0x11a5, 0x11a6, 0x11a7, 0x11a8, 0x11a9,
+ 0x11aa, 0x11ab, 0x11ac, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b3,
+ 0x11b4, 0x11b5, 0x11b7, 0x11b8, 0x11ba, 0x11bb, 0x11bd, 0x11bf,
+ 0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x11c1, 0x11c1, 0x11c2, 0x11c2,
+ 0x11c3, 0x11c4, 0x11c5, 0x11c5, 0x11c6, 0x11c7, 0x11c8, 0x11c9,
+ 0x11ca, 0x11cb, 0x11cc, 0x11ce, 0x11cf, 0x11d0, 0x11d1, 0x11d3,
+ 0x11d4, 0x11d5, 0x11d7, 0x11d8, 0x11da, 0x11db, 0x11dd, 0x11df,
+ 0x11e0, 0x11e0, 0x11e0, 0x11e0, 0x11e1, 0x11e1, 0x11e2, 0x11e2,
+ 0x11e3, 0x11e4, 0x11e5, 0x11e5, 0x11e6, 0x11e7, 0x11e8, 0x11e9,
+ 0x11ea, 0x11eb, 0x11ec, 0x11ee, 0x11ef, 0x11f0, 0x11f1, 0x11f3,
+ 0x11f4, 0x11f5, 0x11f7, 0x11f8, 0x11fa, 0x11fb, 0x11fd, 0x11ff,
+ 0x1200, 0x1200, 0x1200, 0x1200, 0x1201, 0x1201, 0x1202, 0x1202,
+ 0x1203, 0x1204, 0x1205, 0x1205, 0x1206, 0x1207, 0x1208, 0x1209,
+ 0x120a, 0x120b, 0x120c, 0x120e, 0x120f, 0x1210, 0x1211, 0x1213,
+ 0x1214, 0x1215, 0x1217, 0x1218, 0x121a, 0x121b, 0x121d, 0x121f,
+ 0x1220, 0x1220, 0x1220, 0x1220, 0x1221, 0x1221, 0x1222, 0x1222,
+ 0x1223, 0x1224, 0x1225, 0x1225, 0x1226, 0x1227, 0x1228, 0x1229,
+ 0x122a, 0x122b, 0x122c, 0x122e, 0x122f, 0x1230, 0x1231, 0x1233,
+ 0x1234, 0x1235, 0x1237, 0x1238, 0x123a, 0x123b, 0x123d, 0x123f,
+ 0x1240, 0x1240, 0x1240, 0x1240, 0x1241, 0x1241, 0x1242, 0x1242,
+ 0x1243, 0x1244, 0x1245, 0x1245, 0x1246, 0x1247, 0x1248, 0x1249,
+ 0x124a, 0x124b, 0x124c, 0x124e, 0x124f, 0x1250, 0x1251, 0x1253,
+ 0x1254, 0x1255, 0x1257, 0x1258, 0x125a, 0x125b, 0x125d, 0x125f,
+ 0x1260, 0x1260, 0x1260, 0x1260, 0x1261, 0x1261, 0x1262, 0x1262,
+ 0x1263, 0x1264, 0x1265, 0x1265, 0x1266, 0x1267, 0x1268, 0x1269,
+ 0x126a, 0x126b, 0x126c, 0x126e, 0x126f, 0x1270, 0x1271, 0x1273,
+ 0x1274, 0x1275, 0x1277, 0x1278, 0x127a, 0x127b, 0x127d, 0x127f,
+ 0x1280, 0x1280, 0x1280, 0x1280, 0x1281, 0x1281, 0x1282, 0x1282,
+ 0x1283, 0x1284, 0x1285, 0x1285, 0x1286, 0x1287, 0x1288, 0x1289,
+ 0x128a, 0x128b, 0x128c, 0x128e, 0x128f, 0x1290, 0x1291, 0x1293,
+ 0x1294, 0x1295, 0x1297, 0x1298, 0x129a, 0x129b, 0x129d, 0x129f,
+ 0x12a0, 0x12a0, 0x12a0, 0x12a0, 0x12a1, 0x12a1, 0x12a2, 0x12a2,
+ 0x12a3, 0x12a4, 0x12a5, 0x12a5, 0x12a6, 0x12a7, 0x12a8, 0x12a9,
+ 0x12aa, 0x12ab, 0x12ac, 0x12ae, 0x12af, 0x12b0, 0x12b1, 0x12b3,
+ 0x12b4, 0x12b5, 0x12b7, 0x12b8, 0x12ba, 0x12bb, 0x12bd, 0x12bf,
+ 0x12c0, 0x12c0, 0x12c0, 0x12c0, 0x12c1, 0x12c1, 0x12c2, 0x12c2,
+ 0x12c3, 0x12c4, 0x12c5, 0x12c5, 0x12c6, 0x12c7, 0x12c8, 0x12c9,
+ 0x12ca, 0x12cb, 0x12cc, 0x12ce, 0x12cf, 0x12d0, 0x12d1, 0x12d3,
+ 0x12d4, 0x12d5, 0x12d7, 0x12d8, 0x12da, 0x12db, 0x12dd, 0x12df,
+ 0x12e0, 0x12e0, 0x12e0, 0x12e0, 0x12e1, 0x12e1, 0x12e2, 0x12e2,
+ 0x12e3, 0x12e4, 0x12e5, 0x12e5, 0x12e6, 0x12e7, 0x12e8, 0x12e9,
+ 0x12ea, 0x12eb, 0x12ec, 0x12ee, 0x12ef, 0x12f0, 0x12f1, 0x12f3,
+ 0x12f4, 0x12f5, 0x12f7, 0x12f8, 0x12fa, 0x12fb, 0x12fd, 0x12ff,
+ 0x1300, 0x1300, 0x1300, 0x1300, 0x1301, 0x1301, 0x1302, 0x1302,
+ 0x1303, 0x1304, 0x1305, 0x1305, 0x1306, 0x1307, 0x1308, 0x1309,
+ 0x130a, 0x130b, 0x130c, 0x130e, 0x130f, 0x1310, 0x1311, 0x1313,
+ 0x1314, 0x1315, 0x1317, 0x1318, 0x131a, 0x131b, 0x131d, 0x131f,
+ 0x1320, 0x1320, 0x1320, 0x1320, 0x1321, 0x1321, 0x1322, 0x1322,
+ 0x1323, 0x1324, 0x1325, 0x1325, 0x1326, 0x1327, 0x1328, 0x1329,
+ 0x132a, 0x132b, 0x132c, 0x132e, 0x132f, 0x1330, 0x1331, 0x1333,
+ 0x1334, 0x1335, 0x1337, 0x1338, 0x133a, 0x133b, 0x133d, 0x133f,
+ 0x1340, 0x1340, 0x1340, 0x1340, 0x1341, 0x1341, 0x1342, 0x1342,
+ 0x1343, 0x1344, 0x1345, 0x1345, 0x1346, 0x1347, 0x1348, 0x1349,
+ 0x134a, 0x134b, 0x134c, 0x134e, 0x134f, 0x1350, 0x1351, 0x1353,
+ 0x1354, 0x1355, 0x1357, 0x1358, 0x135a, 0x135b, 0x135d, 0x135f,
+ 0x1380, 0x1380, 0x1380, 0x1380, 0x1381, 0x1381, 0x1382, 0x1382,
+ 0x1383, 0x1384, 0x1385, 0x1385, 0x1386, 0x1387, 0x1388, 0x1389,
+ 0x138a, 0x138b, 0x138c, 0x138e, 0x138f, 0x1390, 0x1391, 0x1393,
+ 0x1394, 0x1395, 0x1397, 0x1398, 0x139a, 0x139b, 0x139d, 0x139f,
+ 0x13a0, 0x13a0, 0x13a0, 0x13a0, 0x13a1, 0x13a1, 0x13a2, 0x13a2,
+ 0x13a3, 0x13a4, 0x13a5, 0x13a5, 0x13a6, 0x13a7, 0x13a8, 0x13a9,
+ 0x13aa, 0x13ab, 0x13ac, 0x13ae, 0x13af, 0x13b0, 0x13b1, 0x13b3,
+ 0x13b4, 0x13b5, 0x13b7, 0x13b8, 0x13ba, 0x13bb, 0x13bd, 0x13bf,
+ 0x13c0, 0x13c0, 0x13c0, 0x13c0, 0x13c1, 0x13c1, 0x13c2, 0x13c2,
+ 0x13c3, 0x13c4, 0x13c5, 0x13c5, 0x13c6, 0x13c7, 0x13c8, 0x13c9,
+ 0x13ca, 0x13cb, 0x13cc, 0x13ce, 0x13cf, 0x13d0, 0x13d1, 0x13d3,
+ 0x13d4, 0x13d5, 0x13d7, 0x13d8, 0x13da, 0x13db, 0x13dd, 0x13df,
+ 0x13e0, 0x13e0, 0x13e0, 0x13e0, 0x13e1, 0x13e1, 0x13e2, 0x13e2,
+ 0x13e3, 0x13e4, 0x13e5, 0x13e5, 0x13e6, 0x13e7, 0x13e8, 0x13e9,
+ 0x13ea, 0x13eb, 0x13ec, 0x13ee, 0x13ef, 0x13f0, 0x13f1, 0x13f3,
+ 0x13f4, 0x13f5, 0x13f7, 0x13f8, 0x13fa, 0x13fb, 0x13fd, 0x13ff,
+ 0x1400, 0x1400, 0x1400, 0x1400, 0x1401, 0x1401, 0x1402, 0x1402,
+ 0x1403, 0x1404, 0x1405, 0x1405, 0x1406, 0x1407, 0x1408, 0x1409,
+ 0x140a, 0x140b, 0x140c, 0x140e, 0x140f, 0x1410, 0x1411, 0x1413,
+ 0x1414, 0x1415, 0x1417, 0x1418, 0x141a, 0x141b, 0x141d, 0x141f,
+ 0x1440, 0x1440, 0x1440, 0x1440, 0x1441, 0x1441, 0x1442, 0x1442,
+ 0x1443, 0x1444, 0x1445, 0x1445, 0x1446, 0x1447, 0x1448, 0x1449,
+ 0x144a, 0x144b, 0x144c, 0x144e, 0x144f, 0x1450, 0x1451, 0x1453,
+ 0x1454, 0x1455, 0x1457, 0x1458, 0x145a, 0x145b, 0x145d, 0x145f,
+ 0x1460, 0x1460, 0x1460, 0x1460, 0x1461, 0x1461, 0x1462, 0x1462,
+ 0x1463, 0x1464, 0x1465, 0x1465, 0x1466, 0x1467, 0x1468, 0x1469,
+ 0x146a, 0x146b, 0x146c, 0x146e, 0x146f, 0x1470, 0x1471, 0x1473,
+ 0x1474, 0x1475, 0x1477, 0x1478, 0x147a, 0x147b, 0x147d, 0x147f,
+ 0x1480, 0x1480, 0x1480, 0x1480, 0x1481, 0x1481, 0x1482, 0x1482,
+ 0x1483, 0x1484, 0x1485, 0x1485, 0x1486, 0x1487, 0x1488, 0x1489,
+ 0x148a, 0x148b, 0x148c, 0x148e, 0x148f, 0x1490, 0x1491, 0x1493,
+ 0x1494, 0x1495, 0x1497, 0x1498, 0x149a, 0x149b, 0x149d, 0x149f,
+ 0x14c0, 0x14c0, 0x14c0, 0x14c0, 0x14c1, 0x14c1, 0x14c2, 0x14c2,
+ 0x14c3, 0x14c4, 0x14c5, 0x14c5, 0x14c6, 0x14c7, 0x14c8, 0x14c9,
+ 0x14ca, 0x14cb, 0x14cc, 0x14ce, 0x14cf, 0x14d0, 0x14d1, 0x14d3,
+ 0x14d4, 0x14d5, 0x14d7, 0x14d8, 0x14da, 0x14db, 0x14dd, 0x14df,
+ 0x14e0, 0x14e0, 0x14e0, 0x14e0, 0x14e1, 0x14e1, 0x14e2, 0x14e2,
+ 0x14e3, 0x14e4, 0x14e5, 0x14e5, 0x14e6, 0x14e7, 0x14e8, 0x14e9,
+ 0x14ea, 0x14eb, 0x14ec, 0x14ee, 0x14ef, 0x14f0, 0x14f1, 0x14f3,
+ 0x14f4, 0x14f5, 0x14f7, 0x14f8, 0x14fa, 0x14fb, 0x14fd, 0x14ff,
+ 0x1500, 0x1500, 0x1500, 0x1500, 0x1501, 0x1501, 0x1502, 0x1502,
+ 0x1503, 0x1504, 0x1505, 0x1505, 0x1506, 0x1507, 0x1508, 0x1509,
+ 0x150a, 0x150b, 0x150c, 0x150e, 0x150f, 0x1510, 0x1511, 0x1513,
+ 0x1514, 0x1515, 0x1517, 0x1518, 0x151a, 0x151b, 0x151d, 0x151f,
+ 0x1540, 0x1540, 0x1540, 0x1540, 0x1541, 0x1541, 0x1542, 0x1542,
+ 0x1543, 0x1544, 0x1545, 0x1545, 0x1546, 0x1547, 0x1548, 0x1549,
+ 0x154a, 0x154b, 0x154c, 0x154e, 0x154f, 0x1550, 0x1551, 0x1553,
+ 0x1554, 0x1555, 0x1557, 0x1558, 0x155a, 0x155b, 0x155d, 0x155f,
+ 0x1560, 0x1560, 0x1560, 0x1560, 0x1561, 0x1561, 0x1562, 0x1562,
+ 0x1563, 0x1564, 0x1565, 0x1565, 0x1566, 0x1567, 0x1568, 0x1569,
+ 0x156a, 0x156b, 0x156c, 0x156e, 0x156f, 0x1570, 0x1571, 0x1573,
+ 0x1574, 0x1575, 0x1577, 0x1578, 0x157a, 0x157b, 0x157d, 0x157f,
+ 0x1580, 0x1580, 0x1580, 0x1580, 0x1581, 0x1581, 0x1582, 0x1582,
+ 0x1583, 0x1584, 0x1585, 0x1585, 0x1586, 0x1587, 0x1588, 0x1589,
+ 0x158a, 0x158b, 0x158c, 0x158e, 0x158f, 0x1590, 0x1591, 0x1593,
+ 0x1594, 0x1595, 0x1597, 0x1598, 0x159a, 0x159b, 0x159d, 0x159f,
+ 0x15c0, 0x15c0, 0x15c0, 0x15c0, 0x15c1, 0x15c1, 0x15c2, 0x15c2,
+ 0x15c3, 0x15c4, 0x15c5, 0x15c5, 0x15c6, 0x15c7, 0x15c8, 0x15c9,
+ 0x15ca, 0x15cb, 0x15cc, 0x15ce, 0x15cf, 0x15d0, 0x15d1, 0x15d3,
+ 0x15d4, 0x15d5, 0x15d7, 0x15d8, 0x15da, 0x15db, 0x15dd, 0x15df,
+ 0x15e0, 0x15e0, 0x15e0, 0x15e0, 0x15e1, 0x15e1, 0x15e2, 0x15e2,
+ 0x15e3, 0x15e4, 0x15e5, 0x15e5, 0x15e6, 0x15e7, 0x15e8, 0x15e9,
+ 0x15ea, 0x15eb, 0x15ec, 0x15ee, 0x15ef, 0x15f0, 0x15f1, 0x15f3,
+ 0x15f4, 0x15f5, 0x15f7, 0x15f8, 0x15fa, 0x15fb, 0x15fd, 0x15ff,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1621, 0x1621, 0x1622, 0x1622,
+ 0x1623, 0x1624, 0x1625, 0x1625, 0x1626, 0x1627, 0x1628, 0x1629,
+ 0x162a, 0x162b, 0x162c, 0x162e, 0x162f, 0x1630, 0x1631, 0x1633,
+ 0x1634, 0x1635, 0x1637, 0x1638, 0x163a, 0x163b, 0x163d, 0x163f,
+ 0x1640, 0x1640, 0x1640, 0x1640, 0x1641, 0x1641, 0x1642, 0x1642,
+ 0x1643, 0x1644, 0x1645, 0x1645, 0x1646, 0x1647, 0x1648, 0x1649,
+ 0x164a, 0x164b, 0x164c, 0x164e, 0x164f, 0x1650, 0x1651, 0x1653,
+ 0x1654, 0x1655, 0x1657, 0x1658, 0x165a, 0x165b, 0x165d, 0x165f,
+ 0x1680, 0x1680, 0x1680, 0x1680, 0x1681, 0x1681, 0x1682, 0x1682,
+ 0x1683, 0x1684, 0x1685, 0x1685, 0x1686, 0x1687, 0x1688, 0x1689,
+ 0x168a, 0x168b, 0x168c, 0x168e, 0x168f, 0x1690, 0x1691, 0x1693,
+ 0x1694, 0x1695, 0x1697, 0x1698, 0x169a, 0x169b, 0x169d, 0x169f,
+ 0x16a0, 0x16a0, 0x16a0, 0x16a0, 0x16a1, 0x16a1, 0x16a2, 0x16a2,
+ 0x16a3, 0x16a4, 0x16a5, 0x16a5, 0x16a6, 0x16a7, 0x16a8, 0x16a9,
+ 0x16aa, 0x16ab, 0x16ac, 0x16ae, 0x16af, 0x16b0, 0x16b1, 0x16b3,
+ 0x16b4, 0x16b5, 0x16b7, 0x16b8, 0x16ba, 0x16bb, 0x16bd, 0x16bf,
+ 0x16e0, 0x16e0, 0x16e0, 0x16e0, 0x16e1, 0x16e1, 0x16e2, 0x16e2,
+ 0x16e3, 0x16e4, 0x16e5, 0x16e5, 0x16e6, 0x16e7, 0x16e8, 0x16e9,
+ 0x16ea, 0x16eb, 0x16ec, 0x16ee, 0x16ef, 0x16f0, 0x16f1, 0x16f3,
+ 0x16f4, 0x16f5, 0x16f7, 0x16f8, 0x16fa, 0x16fb, 0x16fd, 0x16ff,
+ 0x1700, 0x1700, 0x1700, 0x1700, 0x1701, 0x1701, 0x1702, 0x1702,
+ 0x1703, 0x1704, 0x1705, 0x1705, 0x1706, 0x1707, 0x1708, 0x1709,
+ 0x170a, 0x170b, 0x170c, 0x170e, 0x170f, 0x1710, 0x1711, 0x1713,
+ 0x1714, 0x1715, 0x1717, 0x1718, 0x171a, 0x171b, 0x171d, 0x171f,
+ 0x1740, 0x1740, 0x1740, 0x1740, 0x1741, 0x1741, 0x1742, 0x1742,
+ 0x1743, 0x1744, 0x1745, 0x1745, 0x1746, 0x1747, 0x1748, 0x1749,
+ 0x174a, 0x174b, 0x174c, 0x174e, 0x174f, 0x1750, 0x1751, 0x1753,
+ 0x1754, 0x1755, 0x1757, 0x1758, 0x175a, 0x175b, 0x175d, 0x175f,
+ 0x1760, 0x1760, 0x1760, 0x1760, 0x1761, 0x1761, 0x1762, 0x1762,
+ 0x1763, 0x1764, 0x1765, 0x1765, 0x1766, 0x1767, 0x1768, 0x1769,
+ 0x176a, 0x176b, 0x176c, 0x176e, 0x176f, 0x1770, 0x1771, 0x1773,
+ 0x1774, 0x1775, 0x1777, 0x1778, 0x177a, 0x177b, 0x177d, 0x177f,
+ 0x17a0, 0x17a0, 0x17a0, 0x17a0, 0x17a1, 0x17a1, 0x17a2, 0x17a2,
+ 0x17a3, 0x17a4, 0x17a5, 0x17a5, 0x17a6, 0x17a7, 0x17a8, 0x17a9,
+ 0x17aa, 0x17ab, 0x17ac, 0x17ae, 0x17af, 0x17b0, 0x17b1, 0x17b3,
+ 0x17b4, 0x17b5, 0x17b7, 0x17b8, 0x17ba, 0x17bb, 0x17bd, 0x17bf,
+ 0x17e0, 0x17e0, 0x17e0, 0x17e0, 0x17e1, 0x17e1, 0x17e2, 0x17e2,
+ 0x17e3, 0x17e4, 0x17e5, 0x17e5, 0x17e6, 0x17e7, 0x17e8, 0x17e9,
+ 0x17ea, 0x17eb, 0x17ec, 0x17ee, 0x17ef, 0x17f0, 0x17f1, 0x17f3,
+ 0x17f4, 0x17f5, 0x17f7, 0x17f8, 0x17fa, 0x17fb, 0x17fd, 0x17ff,
+ 0x1000, 0x1000, 0x1000, 0x1000, 0x1001, 0x1001, 0x1002, 0x1002,
+ 0x1003, 0x1004, 0x1005, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009,
+ 0x100a, 0x100b, 0x100c, 0x100e, 0x100f, 0x1010, 0x1011, 0x1013,
+ 0x1014, 0x1015, 0x1017, 0x1018, 0x101a, 0x101b, 0x101d, 0x101f,
+ 0x1000, 0x1000, 0x1000, 0x1000, 0x1001, 0x1001, 0x1002, 0x1002,
+ 0x1003, 0x1004, 0x1005, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009,
+ 0x100a, 0x100b, 0x100c, 0x100e, 0x100f, 0x1010, 0x1011, 0x1013,
+ 0x1014, 0x1015, 0x1017, 0x1018, 0x101a, 0x101b, 0x101d, 0x101f,
+ 0x1000, 0x1000, 0x1000, 0x1000, 0x1001, 0x1001, 0x1002, 0x1002,
+ 0x1003, 0x1004, 0x1005, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009,
+ 0x100a, 0x100b, 0x100c, 0x100e, 0x100f, 0x1010, 0x1011, 0x1013,
+ 0x1014, 0x1015, 0x1017, 0x1018, 0x101a, 0x101b, 0x101d, 0x101f,
+ 0x1000, 0x1000, 0x1000, 0x1000, 0x1001, 0x1001, 0x1002, 0x1002,
+ 0x1003, 0x1004, 0x1005, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009,
+ 0x100a, 0x100b, 0x100c, 0x100e, 0x100f, 0x1010, 0x1011, 0x1013,
+ 0x1014, 0x1015, 0x1017, 0x1018, 0x101a, 0x101b, 0x101d, 0x101f,
+ 0x1000, 0x1000, 0x1000, 0x1000, 0x1001, 0x1001, 0x1002, 0x1002,
+ 0x1003, 0x1004, 0x1005, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009,
+ 0x100a, 0x100b, 0x100c, 0x100e, 0x100f, 0x1010, 0x1011, 0x1013,
+ 0x1014, 0x1015, 0x1017, 0x1018, 0x101a, 0x101b, 0x101d, 0x101f,
+ 0x1020, 0x1020, 0x1020, 0x1020, 0x1021, 0x1021, 0x1022, 0x1022,
+ 0x1023, 0x1024, 0x1025, 0x1025, 0x1026, 0x1027, 0x1028, 0x1029,
+ 0x102a, 0x102b, 0x102c, 0x102e, 0x102f, 0x1030, 0x1031, 0x1033,
+ 0x1034, 0x1035, 0x1037, 0x1038, 0x103a, 0x103b, 0x103d, 0x103f,
+ 0x1020, 0x1020, 0x1020, 0x1020, 0x1021, 0x1021, 0x1022, 0x1022,
+ 0x1023, 0x1024, 0x1025, 0x1025, 0x1026, 0x1027, 0x1028, 0x1029,
+ 0x102a, 0x102b, 0x102c, 0x102e, 0x102f, 0x1030, 0x1031, 0x1033,
+ 0x1034, 0x1035, 0x1037, 0x1038, 0x103a, 0x103b, 0x103d, 0x103f,
+ 0x1020, 0x1020, 0x1020, 0x1020, 0x1021, 0x1021, 0x1022, 0x1022,
+ 0x1023, 0x1024, 0x1025, 0x1025, 0x1026, 0x1027, 0x1028, 0x1029,
+ 0x102a, 0x102b, 0x102c, 0x102e, 0x102f, 0x1030, 0x1031, 0x1033,
+ 0x1034, 0x1035, 0x1037, 0x1038, 0x103a, 0x103b, 0x103d, 0x103f,
+ 0x1040, 0x1040, 0x1040, 0x1040, 0x1041, 0x1041, 0x1042, 0x1042,
+ 0x1043, 0x1044, 0x1045, 0x1045, 0x1046, 0x1047, 0x1048, 0x1049,
+ 0x104a, 0x104b, 0x104c, 0x104e, 0x104f, 0x1050, 0x1051, 0x1053,
+ 0x1054, 0x1055, 0x1057, 0x1058, 0x105a, 0x105b, 0x105d, 0x105f,
+ 0x1040, 0x1040, 0x1040, 0x1040, 0x1041, 0x1041, 0x1042, 0x1042,
+ 0x1043, 0x1044, 0x1045, 0x1045, 0x1046, 0x1047, 0x1048, 0x1049,
+ 0x104a, 0x104b, 0x104c, 0x104e, 0x104f, 0x1050, 0x1051, 0x1053,
+ 0x1054, 0x1055, 0x1057, 0x1058, 0x105a, 0x105b, 0x105d, 0x105f,
+ 0x1060, 0x1060, 0x1060, 0x1060, 0x1061, 0x1061, 0x1062, 0x1062,
+ 0x1063, 0x1064, 0x1065, 0x1065, 0x1066, 0x1067, 0x1068, 0x1069,
+ 0x106a, 0x106b, 0x106c, 0x106e, 0x106f, 0x1070, 0x1071, 0x1073,
+ 0x1074, 0x1075, 0x1077, 0x1078, 0x107a, 0x107b, 0x107d, 0x107f,
+ 0x1060, 0x1060, 0x1060, 0x1060, 0x1061, 0x1061, 0x1062, 0x1062,
+ 0x1063, 0x1064, 0x1065, 0x1065, 0x1066, 0x1067, 0x1068, 0x1069,
+ 0x106a, 0x106b, 0x106c, 0x106e, 0x106f, 0x1070, 0x1071, 0x1073,
+ 0x1074, 0x1075, 0x1077, 0x1078, 0x107a, 0x107b, 0x107d, 0x107f,
+ 0x1080, 0x1080, 0x1080, 0x1080, 0x1081, 0x1081, 0x1082, 0x1082,
+ 0x1083, 0x1084, 0x1085, 0x1085, 0x1086, 0x1087, 0x1088, 0x1089,
+ 0x108a, 0x108b, 0x108c, 0x108e, 0x108f, 0x1090, 0x1091, 0x1093,
+ 0x1094, 0x1095, 0x1097, 0x1098, 0x109a, 0x109b, 0x109d, 0x109f,
+ 0x10a0, 0x10a0, 0x10a0, 0x10a0, 0x10a1, 0x10a1, 0x10a2, 0x10a2,
+ 0x10a3, 0x10a4, 0x10a5, 0x10a5, 0x10a6, 0x10a7, 0x10a8, 0x10a9,
+ 0x10aa, 0x10ab, 0x10ac, 0x10ae, 0x10af, 0x10b0, 0x10b1, 0x10b3,
+ 0x10b4, 0x10b5, 0x10b7, 0x10b8, 0x10ba, 0x10bb, 0x10bd, 0x10bf,
+ 0x10a0, 0x10a0, 0x10a0, 0x10a0, 0x10a1, 0x10a1, 0x10a2, 0x10a2,
+ 0x10a3, 0x10a4, 0x10a5, 0x10a5, 0x10a6, 0x10a7, 0x10a8, 0x10a9,
+ 0x10aa, 0x10ab, 0x10ac, 0x10ae, 0x10af, 0x10b0, 0x10b1, 0x10b3,
+ 0x10b4, 0x10b5, 0x10b7, 0x10b8, 0x10ba, 0x10bb, 0x10bd, 0x10bf,
+ 0x10c0, 0x10c0, 0x10c0, 0x10c0, 0x10c1, 0x10c1, 0x10c2, 0x10c2,
+ 0x10c3, 0x10c4, 0x10c5, 0x10c5, 0x10c6, 0x10c7, 0x10c8, 0x10c9,
+ 0x10ca, 0x10cb, 0x10cc, 0x10ce, 0x10cf, 0x10d0, 0x10d1, 0x10d3,
+ 0x10d4, 0x10d5, 0x10d7, 0x10d8, 0x10da, 0x10db, 0x10dd, 0x10df,
+ 0x10e0, 0x10e0, 0x10e0, 0x10e0, 0x10e1, 0x10e1, 0x10e2, 0x10e2,
+ 0x10e3, 0x10e4, 0x10e5, 0x10e5, 0x10e6, 0x10e7, 0x10e8, 0x10e9,
+ 0x10ea, 0x10eb, 0x10ec, 0x10ee, 0x10ef, 0x10f0, 0x10f1, 0x10f3,
+ 0x10f4, 0x10f5, 0x10f7, 0x10f8, 0x10fa, 0x10fb, 0x10fd, 0x10ff,
+ 0x10e0, 0x10e0, 0x10e0, 0x10e0, 0x10e1, 0x10e1, 0x10e2, 0x10e2,
+ 0x10e3, 0x10e4, 0x10e5, 0x10e5, 0x10e6, 0x10e7, 0x10e8, 0x10e9,
+ 0x10ea, 0x10eb, 0x10ec, 0x10ee, 0x10ef, 0x10f0, 0x10f1, 0x10f3,
+ 0x10f4, 0x10f5, 0x10f7, 0x10f8, 0x10fa, 0x10fb, 0x10fd, 0x10ff,
+ 0x1100, 0x1100, 0x1100, 0x1100, 0x1101, 0x1101, 0x1102, 0x1102,
+ 0x1103, 0x1104, 0x1105, 0x1105, 0x1106, 0x1107, 0x1108, 0x1109,
+ 0x110a, 0x110b, 0x110c, 0x110e, 0x110f, 0x1110, 0x1111, 0x1113,
+ 0x1114, 0x1115, 0x1117, 0x1118, 0x111a, 0x111b, 0x111d, 0x111f,
+ 0x1120, 0x1120, 0x1120, 0x1120, 0x1121, 0x1121, 0x1122, 0x1122,
+ 0x1123, 0x1124, 0x1125, 0x1125, 0x1126, 0x1127, 0x1128, 0x1129,
+ 0x112a, 0x112b, 0x112c, 0x112e, 0x112f, 0x1130, 0x1131, 0x1133,
+ 0x1134, 0x1135, 0x1137, 0x1138, 0x113a, 0x113b, 0x113d, 0x113f,
+ 0x1140, 0x1140, 0x1140, 0x1140, 0x1141, 0x1141, 0x1142, 0x1142,
+ 0x1143, 0x1144, 0x1145, 0x1145, 0x1146, 0x1147, 0x1148, 0x1149,
+ 0x114a, 0x114b, 0x114c, 0x114e, 0x114f, 0x1150, 0x1151, 0x1153,
+ 0x1154, 0x1155, 0x1157, 0x1158, 0x115a, 0x115b, 0x115d, 0x115f,
+ 0x1140, 0x1140, 0x1140, 0x1140, 0x1141, 0x1141, 0x1142, 0x1142,
+ 0x1143, 0x1144, 0x1145, 0x1145, 0x1146, 0x1147, 0x1148, 0x1149,
+ 0x114a, 0x114b, 0x114c, 0x114e, 0x114f, 0x1150, 0x1151, 0x1153,
+ 0x1154, 0x1155, 0x1157, 0x1158, 0x115a, 0x115b, 0x115d, 0x115f,
+ 0x1160, 0x1160, 0x1160, 0x1160, 0x1161, 0x1161, 0x1162, 0x1162,
+ 0x1163, 0x1164, 0x1165, 0x1165, 0x1166, 0x1167, 0x1168, 0x1169,
+ 0x116a, 0x116b, 0x116c, 0x116e, 0x116f, 0x1170, 0x1171, 0x1173,
+ 0x1174, 0x1175, 0x1177, 0x1178, 0x117a, 0x117b, 0x117d, 0x117f,
+ 0x1180, 0x1180, 0x1180, 0x1180, 0x1181, 0x1181, 0x1182, 0x1182,
+ 0x1183, 0x1184, 0x1185, 0x1185, 0x1186, 0x1187, 0x1188, 0x1189,
+ 0x118a, 0x118b, 0x118c, 0x118e, 0x118f, 0x1190, 0x1191, 0x1193,
+ 0x1194, 0x1195, 0x1197, 0x1198, 0x119a, 0x119b, 0x119d, 0x119f,
+ 0x11a0, 0x11a0, 0x11a0, 0x11a0, 0x11a1, 0x11a1, 0x11a2, 0x11a2,
+ 0x11a3, 0x11a4, 0x11a5, 0x11a5, 0x11a6, 0x11a7, 0x11a8, 0x11a9,
+ 0x11aa, 0x11ab, 0x11ac, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b3,
+ 0x11b4, 0x11b5, 0x11b7, 0x11b8, 0x11ba, 0x11bb, 0x11bd, 0x11bf,
+ 0x11c0, 0x11c0, 0x11c0, 0x11c0, 0x11c1, 0x11c1, 0x11c2, 0x11c2,
+ 0x11c3, 0x11c4, 0x11c5, 0x11c5, 0x11c6, 0x11c7, 0x11c8, 0x11c9,
+ 0x11ca, 0x11cb, 0x11cc, 0x11ce, 0x11cf, 0x11d0, 0x11d1, 0x11d3,
+ 0x11d4, 0x11d5, 0x11d7, 0x11d8, 0x11da, 0x11db, 0x11dd, 0x11df,
+ 0x11e0, 0x11e0, 0x11e0, 0x11e0, 0x11e1, 0x11e1, 0x11e2, 0x11e2,
+ 0x11e3, 0x11e4, 0x11e5, 0x11e5, 0x11e6, 0x11e7, 0x11e8, 0x11e9,
+ 0x11ea, 0x11eb, 0x11ec, 0x11ee, 0x11ef, 0x11f0, 0x11f1, 0x11f3,
+ 0x11f4, 0x11f5, 0x11f7, 0x11f8, 0x11fa, 0x11fb, 0x11fd, 0x11ff,
+ 0x1200, 0x1200, 0x1200, 0x1200, 0x1201, 0x1201, 0x1202, 0x1202,
+ 0x1203, 0x1204, 0x1205, 0x1205, 0x1206, 0x1207, 0x1208, 0x1209,
+ 0x120a, 0x120b, 0x120c, 0x120e, 0x120f, 0x1210, 0x1211, 0x1213,
+ 0x1214, 0x1215, 0x1217, 0x1218, 0x121a, 0x121b, 0x121d, 0x121f,
+ 0x1220, 0x1220, 0x1220, 0x1220, 0x1221, 0x1221, 0x1222, 0x1222,
+ 0x1223, 0x1224, 0x1225, 0x1225, 0x1226, 0x1227, 0x1228, 0x1229,
+ 0x122a, 0x122b, 0x122c, 0x122e, 0x122f, 0x1230, 0x1231, 0x1233,
+ 0x1234, 0x1235, 0x1237, 0x1238, 0x123a, 0x123b, 0x123d, 0x123f,
+ 0x1240, 0x1240, 0x1240, 0x1240, 0x1241, 0x1241, 0x1242, 0x1242,
+ 0x1243, 0x1244, 0x1245, 0x1245, 0x1246, 0x1247, 0x1248, 0x1249,
+ 0x124a, 0x124b, 0x124c, 0x124e, 0x124f, 0x1250, 0x1251, 0x1253,
+ 0x1254, 0x1255, 0x1257, 0x1258, 0x125a, 0x125b, 0x125d, 0x125f,
+ 0x1260, 0x1260, 0x1260, 0x1260, 0x1261, 0x1261, 0x1262, 0x1262,
+ 0x1263, 0x1264, 0x1265, 0x1265, 0x1266, 0x1267, 0x1268, 0x1269,
+ 0x126a, 0x126b, 0x126c, 0x126e, 0x126f, 0x1270, 0x1271, 0x1273,
+ 0x1274, 0x1275, 0x1277, 0x1278, 0x127a, 0x127b, 0x127d, 0x127f,
+ 0x1280, 0x1280, 0x1280, 0x1280, 0x1281, 0x1281, 0x1282, 0x1282,
+ 0x1283, 0x1284, 0x1285, 0x1285, 0x1286, 0x1287, 0x1288, 0x1289,
+ 0x128a, 0x128b, 0x128c, 0x128e, 0x128f, 0x1290, 0x1291, 0x1293,
+ 0x1294, 0x1295, 0x1297, 0x1298, 0x129a, 0x129b, 0x129d, 0x129f,
+ 0x12a0, 0x12a0, 0x12a0, 0x12a0, 0x12a1, 0x12a1, 0x12a2, 0x12a2,
+ 0x12a3, 0x12a4, 0x12a5, 0x12a5, 0x12a6, 0x12a7, 0x12a8, 0x12a9,
+ 0x12aa, 0x12ab, 0x12ac, 0x12ae, 0x12af, 0x12b0, 0x12b1, 0x12b3,
+ 0x12b4, 0x12b5, 0x12b7, 0x12b8, 0x12ba, 0x12bb, 0x12bd, 0x12bf,
+ 0x12c0, 0x12c0, 0x12c0, 0x12c0, 0x12c1, 0x12c1, 0x12c2, 0x12c2,
+ 0x12c3, 0x12c4, 0x12c5, 0x12c5, 0x12c6, 0x12c7, 0x12c8, 0x12c9,
+ 0x12ca, 0x12cb, 0x12cc, 0x12ce, 0x12cf, 0x12d0, 0x12d1, 0x12d3,
+ 0x12d4, 0x12d5, 0x12d7, 0x12d8, 0x12da, 0x12db, 0x12dd, 0x12df,
+ 0x12e0, 0x12e0, 0x12e0, 0x12e0, 0x12e1, 0x12e1, 0x12e2, 0x12e2,
+ 0x12e3, 0x12e4, 0x12e5, 0x12e5, 0x12e6, 0x12e7, 0x12e8, 0x12e9,
+ 0x12ea, 0x12eb, 0x12ec, 0x12ee, 0x12ef, 0x12f0, 0x12f1, 0x12f3,
+ 0x12f4, 0x12f5, 0x12f7, 0x12f8, 0x12fa, 0x12fb, 0x12fd, 0x12ff,
+ 0x1300, 0x1300, 0x1300, 0x1300, 0x1301, 0x1301, 0x1302, 0x1302,
+ 0x1303, 0x1304, 0x1305, 0x1305, 0x1306, 0x1307, 0x1308, 0x1309,
+ 0x130a, 0x130b, 0x130c, 0x130e, 0x130f, 0x1310, 0x1311, 0x1313,
+ 0x1314, 0x1315, 0x1317, 0x1318, 0x131a, 0x131b, 0x131d, 0x131f,
+ 0x1320, 0x1320, 0x1320, 0x1320, 0x1321, 0x1321, 0x1322, 0x1322,
+ 0x1323, 0x1324, 0x1325, 0x1325, 0x1326, 0x1327, 0x1328, 0x1329,
+ 0x132a, 0x132b, 0x132c, 0x132e, 0x132f, 0x1330, 0x1331, 0x1333,
+ 0x1334, 0x1335, 0x1337, 0x1338, 0x133a, 0x133b, 0x133d, 0x133f,
+ 0x1340, 0x1340, 0x1340, 0x1340, 0x1341, 0x1341, 0x1342, 0x1342,
+ 0x1343, 0x1344, 0x1345, 0x1345, 0x1346, 0x1347, 0x1348, 0x1349,
+ 0x134a, 0x134b, 0x134c, 0x134e, 0x134f, 0x1350, 0x1351, 0x1353,
+ 0x1354, 0x1355, 0x1357, 0x1358, 0x135a, 0x135b, 0x135d, 0x135f,
+ 0x1380, 0x1380, 0x1380, 0x1380, 0x1381, 0x1381, 0x1382, 0x1382,
+ 0x1383, 0x1384, 0x1385, 0x1385, 0x1386, 0x1387, 0x1388, 0x1389,
+ 0x138a, 0x138b, 0x138c, 0x138e, 0x138f, 0x1390, 0x1391, 0x1393,
+ 0x1394, 0x1395, 0x1397, 0x1398, 0x139a, 0x139b, 0x139d, 0x139f,
+ 0x13a0, 0x13a0, 0x13a0, 0x13a0, 0x13a1, 0x13a1, 0x13a2, 0x13a2,
+ 0x13a3, 0x13a4, 0x13a5, 0x13a5, 0x13a6, 0x13a7, 0x13a8, 0x13a9,
+ 0x13aa, 0x13ab, 0x13ac, 0x13ae, 0x13af, 0x13b0, 0x13b1, 0x13b3,
+ 0x13b4, 0x13b5, 0x13b7, 0x13b8, 0x13ba, 0x13bb, 0x13bd, 0x13bf,
+ 0x13c0, 0x13c0, 0x13c0, 0x13c0, 0x13c1, 0x13c1, 0x13c2, 0x13c2,
+ 0x13c3, 0x13c4, 0x13c5, 0x13c5, 0x13c6, 0x13c7, 0x13c8, 0x13c9,
+ 0x13ca, 0x13cb, 0x13cc, 0x13ce, 0x13cf, 0x13d0, 0x13d1, 0x13d3,
+ 0x13d4, 0x13d5, 0x13d7, 0x13d8, 0x13da, 0x13db, 0x13dd, 0x13df,
+ 0x13e0, 0x13e0, 0x13e0, 0x13e0, 0x13e1, 0x13e1, 0x13e2, 0x13e2,
+ 0x13e3, 0x13e4, 0x13e5, 0x13e5, 0x13e6, 0x13e7, 0x13e8, 0x13e9,
+ 0x13ea, 0x13eb, 0x13ec, 0x13ee, 0x13ef, 0x13f0, 0x13f1, 0x13f3,
+ 0x13f4, 0x13f5, 0x13f7, 0x13f8, 0x13fa, 0x13fb, 0x13fd, 0x13ff,
+ 0x1400, 0x1400, 0x1400, 0x1400, 0x1401, 0x1401, 0x1402, 0x1402,
+ 0x1403, 0x1404, 0x1405, 0x1405, 0x1406, 0x1407, 0x1408, 0x1409,
+ 0x140a, 0x140b, 0x140c, 0x140e, 0x140f, 0x1410, 0x1411, 0x1413,
+ 0x1414, 0x1415, 0x1417, 0x1418, 0x141a, 0x141b, 0x141d, 0x141f,
+ 0x1440, 0x1440, 0x1440, 0x1440, 0x1441, 0x1441, 0x1442, 0x1442,
+ 0x1443, 0x1444, 0x1445, 0x1445, 0x1446, 0x1447, 0x1448, 0x1449,
+ 0x144a, 0x144b, 0x144c, 0x144e, 0x144f, 0x1450, 0x1451, 0x1453,
+ 0x1454, 0x1455, 0x1457, 0x1458, 0x145a, 0x145b, 0x145d, 0x145f,
+ 0x1460, 0x1460, 0x1460, 0x1460, 0x1461, 0x1461, 0x1462, 0x1462,
+ 0x1463, 0x1464, 0x1465, 0x1465, 0x1466, 0x1467, 0x1468, 0x1469,
+ 0x146a, 0x146b, 0x146c, 0x146e, 0x146f, 0x1470, 0x1471, 0x1473,
+ 0x1474, 0x1475, 0x1477, 0x1478, 0x147a, 0x147b, 0x147d, 0x147f,
+ 0x1480, 0x1480, 0x1480, 0x1480, 0x1481, 0x1481, 0x1482, 0x1482,
+ 0x1483, 0x1484, 0x1485, 0x1485, 0x1486, 0x1487, 0x1488, 0x1489,
+ 0x148a, 0x148b, 0x148c, 0x148e, 0x148f, 0x1490, 0x1491, 0x1493,
+ 0x1494, 0x1495, 0x1497, 0x1498, 0x149a, 0x149b, 0x149d, 0x149f,
+ 0x14c0, 0x14c0, 0x14c0, 0x14c0, 0x14c1, 0x14c1, 0x14c2, 0x14c2,
+ 0x14c3, 0x14c4, 0x14c5, 0x14c5, 0x14c6, 0x14c7, 0x14c8, 0x14c9,
+ 0x14ca, 0x14cb, 0x14cc, 0x14ce, 0x14cf, 0x14d0, 0x14d1, 0x14d3,
+ 0x14d4, 0x14d5, 0x14d7, 0x14d8, 0x14da, 0x14db, 0x14dd, 0x14df,
+ 0x14e0, 0x14e0, 0x14e0, 0x14e0, 0x14e1, 0x14e1, 0x14e2, 0x14e2,
+ 0x14e3, 0x14e4, 0x14e5, 0x14e5, 0x14e6, 0x14e7, 0x14e8, 0x14e9,
+ 0x14ea, 0x14eb, 0x14ec, 0x14ee, 0x14ef, 0x14f0, 0x14f1, 0x14f3,
+ 0x14f4, 0x14f5, 0x14f7, 0x14f8, 0x14fa, 0x14fb, 0x14fd, 0x14ff,
+ 0x1500, 0x1500, 0x1500, 0x1500, 0x1501, 0x1501, 0x1502, 0x1502,
+ 0x1503, 0x1504, 0x1505, 0x1505, 0x1506, 0x1507, 0x1508, 0x1509,
+ 0x150a, 0x150b, 0x150c, 0x150e, 0x150f, 0x1510, 0x1511, 0x1513,
+ 0x1514, 0x1515, 0x1517, 0x1518, 0x151a, 0x151b, 0x151d, 0x151f,
+ 0x1540, 0x1540, 0x1540, 0x1540, 0x1541, 0x1541, 0x1542, 0x1542,
+ 0x1543, 0x1544, 0x1545, 0x1545, 0x1546, 0x1547, 0x1548, 0x1549,
+ 0x154a, 0x154b, 0x154c, 0x154e, 0x154f, 0x1550, 0x1551, 0x1553,
+ 0x1554, 0x1555, 0x1557, 0x1558, 0x155a, 0x155b, 0x155d, 0x155f,
+ 0x1560, 0x1560, 0x1560, 0x1560, 0x1561, 0x1561, 0x1562, 0x1562,
+ 0x1563, 0x1564, 0x1565, 0x1565, 0x1566, 0x1567, 0x1568, 0x1569,
+ 0x156a, 0x156b, 0x156c, 0x156e, 0x156f, 0x1570, 0x1571, 0x1573,
+ 0x1574, 0x1575, 0x1577, 0x1578, 0x157a, 0x157b, 0x157d, 0x157f,
+ 0x1580, 0x1580, 0x1580, 0x1580, 0x1581, 0x1581, 0x1582, 0x1582,
+ 0x1583, 0x1584, 0x1585, 0x1585, 0x1586, 0x1587, 0x1588, 0x1589,
+ 0x158a, 0x158b, 0x158c, 0x158e, 0x158f, 0x1590, 0x1591, 0x1593,
+ 0x1594, 0x1595, 0x1597, 0x1598, 0x159a, 0x159b, 0x159d, 0x159f,
+ 0x15c0, 0x15c0, 0x15c0, 0x15c0, 0x15c1, 0x15c1, 0x15c2, 0x15c2,
+ 0x15c3, 0x15c4, 0x15c5, 0x15c5, 0x15c6, 0x15c7, 0x15c8, 0x15c9,
+ 0x15ca, 0x15cb, 0x15cc, 0x15ce, 0x15cf, 0x15d0, 0x15d1, 0x15d3,
+ 0x15d4, 0x15d5, 0x15d7, 0x15d8, 0x15da, 0x15db, 0x15dd, 0x15df,
+ 0x15e0, 0x15e0, 0x15e0, 0x15e0, 0x15e1, 0x15e1, 0x15e2, 0x15e2,
+ 0x15e3, 0x15e4, 0x15e5, 0x15e5, 0x15e6, 0x15e7, 0x15e8, 0x15e9,
+ 0x15ea, 0x15eb, 0x15ec, 0x15ee, 0x15ef, 0x15f0, 0x15f1, 0x15f3,
+ 0x15f4, 0x15f5, 0x15f7, 0x15f8, 0x15fa, 0x15fb, 0x15fd, 0x15ff,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1621, 0x1621, 0x1622, 0x1622,
+ 0x1623, 0x1624, 0x1625, 0x1625, 0x1626, 0x1627, 0x1628, 0x1629,
+ 0x162a, 0x162b, 0x162c, 0x162e, 0x162f, 0x1630, 0x1631, 0x1633,
+ 0x1634, 0x1635, 0x1637, 0x1638, 0x163a, 0x163b, 0x163d, 0x163f,
+ 0x1640, 0x1640, 0x1640, 0x1640, 0x1641, 0x1641, 0x1642, 0x1642,
+ 0x1643, 0x1644, 0x1645, 0x1645, 0x1646, 0x1647, 0x1648, 0x1649,
+ 0x164a, 0x164b, 0x164c, 0x164e, 0x164f, 0x1650, 0x1651, 0x1653,
+ 0x1654, 0x1655, 0x1657, 0x1658, 0x165a, 0x165b, 0x165d, 0x165f,
+ 0x1680, 0x1680, 0x1680, 0x1680, 0x1681, 0x1681, 0x1682, 0x1682,
+ 0x1683, 0x1684, 0x1685, 0x1685, 0x1686, 0x1687, 0x1688, 0x1689,
+ 0x168a, 0x168b, 0x168c, 0x168e, 0x168f, 0x1690, 0x1691, 0x1693,
+ 0x1694, 0x1695, 0x1697, 0x1698, 0x169a, 0x169b, 0x169d, 0x169f,
+ 0x16a0, 0x16a0, 0x16a0, 0x16a0, 0x16a1, 0x16a1, 0x16a2, 0x16a2,
+ 0x16a3, 0x16a4, 0x16a5, 0x16a5, 0x16a6, 0x16a7, 0x16a8, 0x16a9,
+ 0x16aa, 0x16ab, 0x16ac, 0x16ae, 0x16af, 0x16b0, 0x16b1, 0x16b3,
+ 0x16b4, 0x16b5, 0x16b7, 0x16b8, 0x16ba, 0x16bb, 0x16bd, 0x16bf,
+ 0x16e0, 0x16e0, 0x16e0, 0x16e0, 0x16e1, 0x16e1, 0x16e2, 0x16e2,
+ 0x16e3, 0x16e4, 0x16e5, 0x16e5, 0x16e6, 0x16e7, 0x16e8, 0x16e9,
+ 0x16ea, 0x16eb, 0x16ec, 0x16ee, 0x16ef, 0x16f0, 0x16f1, 0x16f3,
+ 0x16f4, 0x16f5, 0x16f7, 0x16f8, 0x16fa, 0x16fb, 0x16fd, 0x16ff,
+ 0x1700, 0x1700, 0x1700, 0x1700, 0x1701, 0x1701, 0x1702, 0x1702,
+ 0x1703, 0x1704, 0x1705, 0x1705, 0x1706, 0x1707, 0x1708, 0x1709,
+ 0x170a, 0x170b, 0x170c, 0x170e, 0x170f, 0x1710, 0x1711, 0x1713,
+ 0x1714, 0x1715, 0x1717, 0x1718, 0x171a, 0x171b, 0x171d, 0x171f,
+ 0x1740, 0x1740, 0x1740, 0x1740, 0x1741, 0x1741, 0x1742, 0x1742,
+ 0x1743, 0x1744, 0x1745, 0x1745, 0x1746, 0x1747, 0x1748, 0x1749,
+ 0x174a, 0x174b, 0x174c, 0x174e, 0x174f, 0x1750, 0x1751, 0x1753,
+ 0x1754, 0x1755, 0x1757, 0x1758, 0x175a, 0x175b, 0x175d, 0x175f,
+ 0x1760, 0x1760, 0x1760, 0x1760, 0x1761, 0x1761, 0x1762, 0x1762,
+ 0x1763, 0x1764, 0x1765, 0x1765, 0x1766, 0x1767, 0x1768, 0x1769,
+ 0x176a, 0x176b, 0x176c, 0x176e, 0x176f, 0x1770, 0x1771, 0x1773,
+ 0x1774, 0x1775, 0x1777, 0x1778, 0x177a, 0x177b, 0x177d, 0x177f,
+ 0x17a0, 0x17a0, 0x17a0, 0x17a0, 0x17a1, 0x17a1, 0x17a2, 0x17a2,
+ 0x17a3, 0x17a4, 0x17a5, 0x17a5, 0x17a6, 0x17a7, 0x17a8, 0x17a9,
+ 0x17aa, 0x17ab, 0x17ac, 0x17ae, 0x17af, 0x17b0, 0x17b1, 0x17b3,
+ 0x17b4, 0x17b5, 0x17b7, 0x17b8, 0x17ba, 0x17bb, 0x17bd, 0x17bf,
+ 0x17e0, 0x17e0, 0x17e0, 0x17e0, 0x17e1, 0x17e1, 0x17e2, 0x17e2,
+ 0x17e3, 0x17e4, 0x17e5, 0x17e5, 0x17e6, 0x17e7, 0x17e8, 0x17e9,
+ 0x17ea, 0x17eb, 0x17ec, 0x17ee, 0x17ef, 0x17f0, 0x17f1, 0x17f3,
+ 0x17f4, 0x17f5, 0x17f7, 0x17f8, 0x17fa, 0x17fb, 0x17fd, 0x17ff,
+ 0x1800, 0x1800, 0x1800, 0x1800, 0x1801, 0x1801, 0x1802, 0x1802,
+ 0x1803, 0x1804, 0x1805, 0x1805, 0x1806, 0x1807, 0x1808, 0x1809,
+ 0x180a, 0x180b, 0x180c, 0x180e, 0x180f, 0x1810, 0x1811, 0x1813,
+ 0x1814, 0x1815, 0x1817, 0x1818, 0x181a, 0x181b, 0x181d, 0x181f,
+ 0x1800, 0x1800, 0x1800, 0x1800, 0x1801, 0x1801, 0x1802, 0x1802,
+ 0x1803, 0x1804, 0x1805, 0x1805, 0x1806, 0x1807, 0x1808, 0x1809,
+ 0x180a, 0x180b, 0x180c, 0x180e, 0x180f, 0x1810, 0x1811, 0x1813,
+ 0x1814, 0x1815, 0x1817, 0x1818, 0x181a, 0x181b, 0x181d, 0x181f,
+ 0x1800, 0x1800, 0x1800, 0x1800, 0x1801, 0x1801, 0x1802, 0x1802,
+ 0x1803, 0x1804, 0x1805, 0x1805, 0x1806, 0x1807, 0x1808, 0x1809,
+ 0x180a, 0x180b, 0x180c, 0x180e, 0x180f, 0x1810, 0x1811, 0x1813,
+ 0x1814, 0x1815, 0x1817, 0x1818, 0x181a, 0x181b, 0x181d, 0x181f,
+ 0x1800, 0x1800, 0x1800, 0x1800, 0x1801, 0x1801, 0x1802, 0x1802,
+ 0x1803, 0x1804, 0x1805, 0x1805, 0x1806, 0x1807, 0x1808, 0x1809,
+ 0x180a, 0x180b, 0x180c, 0x180e, 0x180f, 0x1810, 0x1811, 0x1813,
+ 0x1814, 0x1815, 0x1817, 0x1818, 0x181a, 0x181b, 0x181d, 0x181f,
+ 0x1800, 0x1800, 0x1800, 0x1800, 0x1801, 0x1801, 0x1802, 0x1802,
+ 0x1803, 0x1804, 0x1805, 0x1805, 0x1806, 0x1807, 0x1808, 0x1809,
+ 0x180a, 0x180b, 0x180c, 0x180e, 0x180f, 0x1810, 0x1811, 0x1813,
+ 0x1814, 0x1815, 0x1817, 0x1818, 0x181a, 0x181b, 0x181d, 0x181f,
+ 0x1820, 0x1820, 0x1820, 0x1820, 0x1821, 0x1821, 0x1822, 0x1822,
+ 0x1823, 0x1824, 0x1825, 0x1825, 0x1826, 0x1827, 0x1828, 0x1829,
+ 0x182a, 0x182b, 0x182c, 0x182e, 0x182f, 0x1830, 0x1831, 0x1833,
+ 0x1834, 0x1835, 0x1837, 0x1838, 0x183a, 0x183b, 0x183d, 0x183f,
+ 0x1820, 0x1820, 0x1820, 0x1820, 0x1821, 0x1821, 0x1822, 0x1822,
+ 0x1823, 0x1824, 0x1825, 0x1825, 0x1826, 0x1827, 0x1828, 0x1829,
+ 0x182a, 0x182b, 0x182c, 0x182e, 0x182f, 0x1830, 0x1831, 0x1833,
+ 0x1834, 0x1835, 0x1837, 0x1838, 0x183a, 0x183b, 0x183d, 0x183f,
+ 0x1820, 0x1820, 0x1820, 0x1820, 0x1821, 0x1821, 0x1822, 0x1822,
+ 0x1823, 0x1824, 0x1825, 0x1825, 0x1826, 0x1827, 0x1828, 0x1829,
+ 0x182a, 0x182b, 0x182c, 0x182e, 0x182f, 0x1830, 0x1831, 0x1833,
+ 0x1834, 0x1835, 0x1837, 0x1838, 0x183a, 0x183b, 0x183d, 0x183f,
+ 0x1840, 0x1840, 0x1840, 0x1840, 0x1841, 0x1841, 0x1842, 0x1842,
+ 0x1843, 0x1844, 0x1845, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849,
+ 0x184a, 0x184b, 0x184c, 0x184e, 0x184f, 0x1850, 0x1851, 0x1853,
+ 0x1854, 0x1855, 0x1857, 0x1858, 0x185a, 0x185b, 0x185d, 0x185f,
+ 0x1840, 0x1840, 0x1840, 0x1840, 0x1841, 0x1841, 0x1842, 0x1842,
+ 0x1843, 0x1844, 0x1845, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849,
+ 0x184a, 0x184b, 0x184c, 0x184e, 0x184f, 0x1850, 0x1851, 0x1853,
+ 0x1854, 0x1855, 0x1857, 0x1858, 0x185a, 0x185b, 0x185d, 0x185f,
+ 0x1860, 0x1860, 0x1860, 0x1860, 0x1861, 0x1861, 0x1862, 0x1862,
+ 0x1863, 0x1864, 0x1865, 0x1865, 0x1866, 0x1867, 0x1868, 0x1869,
+ 0x186a, 0x186b, 0x186c, 0x186e, 0x186f, 0x1870, 0x1871, 0x1873,
+ 0x1874, 0x1875, 0x1877, 0x1878, 0x187a, 0x187b, 0x187d, 0x187f,
+ 0x1860, 0x1860, 0x1860, 0x1860, 0x1861, 0x1861, 0x1862, 0x1862,
+ 0x1863, 0x1864, 0x1865, 0x1865, 0x1866, 0x1867, 0x1868, 0x1869,
+ 0x186a, 0x186b, 0x186c, 0x186e, 0x186f, 0x1870, 0x1871, 0x1873,
+ 0x1874, 0x1875, 0x1877, 0x1878, 0x187a, 0x187b, 0x187d, 0x187f,
+ 0x1880, 0x1880, 0x1880, 0x1880, 0x1881, 0x1881, 0x1882, 0x1882,
+ 0x1883, 0x1884, 0x1885, 0x1885, 0x1886, 0x1887, 0x1888, 0x1889,
+ 0x188a, 0x188b, 0x188c, 0x188e, 0x188f, 0x1890, 0x1891, 0x1893,
+ 0x1894, 0x1895, 0x1897, 0x1898, 0x189a, 0x189b, 0x189d, 0x189f,
+ 0x18a0, 0x18a0, 0x18a0, 0x18a0, 0x18a1, 0x18a1, 0x18a2, 0x18a2,
+ 0x18a3, 0x18a4, 0x18a5, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18a9,
+ 0x18aa, 0x18ab, 0x18ac, 0x18ae, 0x18af, 0x18b0, 0x18b1, 0x18b3,
+ 0x18b4, 0x18b5, 0x18b7, 0x18b8, 0x18ba, 0x18bb, 0x18bd, 0x18bf,
+ 0x18a0, 0x18a0, 0x18a0, 0x18a0, 0x18a1, 0x18a1, 0x18a2, 0x18a2,
+ 0x18a3, 0x18a4, 0x18a5, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18a9,
+ 0x18aa, 0x18ab, 0x18ac, 0x18ae, 0x18af, 0x18b0, 0x18b1, 0x18b3,
+ 0x18b4, 0x18b5, 0x18b7, 0x18b8, 0x18ba, 0x18bb, 0x18bd, 0x18bf,
+ 0x18c0, 0x18c0, 0x18c0, 0x18c0, 0x18c1, 0x18c1, 0x18c2, 0x18c2,
+ 0x18c3, 0x18c4, 0x18c5, 0x18c5, 0x18c6, 0x18c7, 0x18c8, 0x18c9,
+ 0x18ca, 0x18cb, 0x18cc, 0x18ce, 0x18cf, 0x18d0, 0x18d1, 0x18d3,
+ 0x18d4, 0x18d5, 0x18d7, 0x18d8, 0x18da, 0x18db, 0x18dd, 0x18df,
+ 0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x18e1, 0x18e1, 0x18e2, 0x18e2,
+ 0x18e3, 0x18e4, 0x18e5, 0x18e5, 0x18e6, 0x18e7, 0x18e8, 0x18e9,
+ 0x18ea, 0x18eb, 0x18ec, 0x18ee, 0x18ef, 0x18f0, 0x18f1, 0x18f3,
+ 0x18f4, 0x18f5, 0x18f7, 0x18f8, 0x18fa, 0x18fb, 0x18fd, 0x18ff,
+ 0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x18e1, 0x18e1, 0x18e2, 0x18e2,
+ 0x18e3, 0x18e4, 0x18e5, 0x18e5, 0x18e6, 0x18e7, 0x18e8, 0x18e9,
+ 0x18ea, 0x18eb, 0x18ec, 0x18ee, 0x18ef, 0x18f0, 0x18f1, 0x18f3,
+ 0x18f4, 0x18f5, 0x18f7, 0x18f8, 0x18fa, 0x18fb, 0x18fd, 0x18ff,
+ 0x1900, 0x1900, 0x1900, 0x1900, 0x1901, 0x1901, 0x1902, 0x1902,
+ 0x1903, 0x1904, 0x1905, 0x1905, 0x1906, 0x1907, 0x1908, 0x1909,
+ 0x190a, 0x190b, 0x190c, 0x190e, 0x190f, 0x1910, 0x1911, 0x1913,
+ 0x1914, 0x1915, 0x1917, 0x1918, 0x191a, 0x191b, 0x191d, 0x191f,
+ 0x1920, 0x1920, 0x1920, 0x1920, 0x1921, 0x1921, 0x1922, 0x1922,
+ 0x1923, 0x1924, 0x1925, 0x1925, 0x1926, 0x1927, 0x1928, 0x1929,
+ 0x192a, 0x192b, 0x192c, 0x192e, 0x192f, 0x1930, 0x1931, 0x1933,
+ 0x1934, 0x1935, 0x1937, 0x1938, 0x193a, 0x193b, 0x193d, 0x193f,
+ 0x1940, 0x1940, 0x1940, 0x1940, 0x1941, 0x1941, 0x1942, 0x1942,
+ 0x1943, 0x1944, 0x1945, 0x1945, 0x1946, 0x1947, 0x1948, 0x1949,
+ 0x194a, 0x194b, 0x194c, 0x194e, 0x194f, 0x1950, 0x1951, 0x1953,
+ 0x1954, 0x1955, 0x1957, 0x1958, 0x195a, 0x195b, 0x195d, 0x195f,
+ 0x1940, 0x1940, 0x1940, 0x1940, 0x1941, 0x1941, 0x1942, 0x1942,
+ 0x1943, 0x1944, 0x1945, 0x1945, 0x1946, 0x1947, 0x1948, 0x1949,
+ 0x194a, 0x194b, 0x194c, 0x194e, 0x194f, 0x1950, 0x1951, 0x1953,
+ 0x1954, 0x1955, 0x1957, 0x1958, 0x195a, 0x195b, 0x195d, 0x195f,
+ 0x1960, 0x1960, 0x1960, 0x1960, 0x1961, 0x1961, 0x1962, 0x1962,
+ 0x1963, 0x1964, 0x1965, 0x1965, 0x1966, 0x1967, 0x1968, 0x1969,
+ 0x196a, 0x196b, 0x196c, 0x196e, 0x196f, 0x1970, 0x1971, 0x1973,
+ 0x1974, 0x1975, 0x1977, 0x1978, 0x197a, 0x197b, 0x197d, 0x197f,
+ 0x1980, 0x1980, 0x1980, 0x1980, 0x1981, 0x1981, 0x1982, 0x1982,
+ 0x1983, 0x1984, 0x1985, 0x1985, 0x1986, 0x1987, 0x1988, 0x1989,
+ 0x198a, 0x198b, 0x198c, 0x198e, 0x198f, 0x1990, 0x1991, 0x1993,
+ 0x1994, 0x1995, 0x1997, 0x1998, 0x199a, 0x199b, 0x199d, 0x199f,
+ 0x19a0, 0x19a0, 0x19a0, 0x19a0, 0x19a1, 0x19a1, 0x19a2, 0x19a2,
+ 0x19a3, 0x19a4, 0x19a5, 0x19a5, 0x19a6, 0x19a7, 0x19a8, 0x19a9,
+ 0x19aa, 0x19ab, 0x19ac, 0x19ae, 0x19af, 0x19b0, 0x19b1, 0x19b3,
+ 0x19b4, 0x19b5, 0x19b7, 0x19b8, 0x19ba, 0x19bb, 0x19bd, 0x19bf,
+ 0x19c0, 0x19c0, 0x19c0, 0x19c0, 0x19c1, 0x19c1, 0x19c2, 0x19c2,
+ 0x19c3, 0x19c4, 0x19c5, 0x19c5, 0x19c6, 0x19c7, 0x19c8, 0x19c9,
+ 0x19ca, 0x19cb, 0x19cc, 0x19ce, 0x19cf, 0x19d0, 0x19d1, 0x19d3,
+ 0x19d4, 0x19d5, 0x19d7, 0x19d8, 0x19da, 0x19db, 0x19dd, 0x19df,
+ 0x19e0, 0x19e0, 0x19e0, 0x19e0, 0x19e1, 0x19e1, 0x19e2, 0x19e2,
+ 0x19e3, 0x19e4, 0x19e5, 0x19e5, 0x19e6, 0x19e7, 0x19e8, 0x19e9,
+ 0x19ea, 0x19eb, 0x19ec, 0x19ee, 0x19ef, 0x19f0, 0x19f1, 0x19f3,
+ 0x19f4, 0x19f5, 0x19f7, 0x19f8, 0x19fa, 0x19fb, 0x19fd, 0x19ff,
+ 0x1a00, 0x1a00, 0x1a00, 0x1a00, 0x1a01, 0x1a01, 0x1a02, 0x1a02,
+ 0x1a03, 0x1a04, 0x1a05, 0x1a05, 0x1a06, 0x1a07, 0x1a08, 0x1a09,
+ 0x1a0a, 0x1a0b, 0x1a0c, 0x1a0e, 0x1a0f, 0x1a10, 0x1a11, 0x1a13,
+ 0x1a14, 0x1a15, 0x1a17, 0x1a18, 0x1a1a, 0x1a1b, 0x1a1d, 0x1a1f,
+ 0x1a20, 0x1a20, 0x1a20, 0x1a20, 0x1a21, 0x1a21, 0x1a22, 0x1a22,
+ 0x1a23, 0x1a24, 0x1a25, 0x1a25, 0x1a26, 0x1a27, 0x1a28, 0x1a29,
+ 0x1a2a, 0x1a2b, 0x1a2c, 0x1a2e, 0x1a2f, 0x1a30, 0x1a31, 0x1a33,
+ 0x1a34, 0x1a35, 0x1a37, 0x1a38, 0x1a3a, 0x1a3b, 0x1a3d, 0x1a3f,
+ 0x1a40, 0x1a40, 0x1a40, 0x1a40, 0x1a41, 0x1a41, 0x1a42, 0x1a42,
+ 0x1a43, 0x1a44, 0x1a45, 0x1a45, 0x1a46, 0x1a47, 0x1a48, 0x1a49,
+ 0x1a4a, 0x1a4b, 0x1a4c, 0x1a4e, 0x1a4f, 0x1a50, 0x1a51, 0x1a53,
+ 0x1a54, 0x1a55, 0x1a57, 0x1a58, 0x1a5a, 0x1a5b, 0x1a5d, 0x1a5f,
+ 0x1a60, 0x1a60, 0x1a60, 0x1a60, 0x1a61, 0x1a61, 0x1a62, 0x1a62,
+ 0x1a63, 0x1a64, 0x1a65, 0x1a65, 0x1a66, 0x1a67, 0x1a68, 0x1a69,
+ 0x1a6a, 0x1a6b, 0x1a6c, 0x1a6e, 0x1a6f, 0x1a70, 0x1a71, 0x1a73,
+ 0x1a74, 0x1a75, 0x1a77, 0x1a78, 0x1a7a, 0x1a7b, 0x1a7d, 0x1a7f,
+ 0x1a80, 0x1a80, 0x1a80, 0x1a80, 0x1a81, 0x1a81, 0x1a82, 0x1a82,
+ 0x1a83, 0x1a84, 0x1a85, 0x1a85, 0x1a86, 0x1a87, 0x1a88, 0x1a89,
+ 0x1a8a, 0x1a8b, 0x1a8c, 0x1a8e, 0x1a8f, 0x1a90, 0x1a91, 0x1a93,
+ 0x1a94, 0x1a95, 0x1a97, 0x1a98, 0x1a9a, 0x1a9b, 0x1a9d, 0x1a9f,
+ 0x1aa0, 0x1aa0, 0x1aa0, 0x1aa0, 0x1aa1, 0x1aa1, 0x1aa2, 0x1aa2,
+ 0x1aa3, 0x1aa4, 0x1aa5, 0x1aa5, 0x1aa6, 0x1aa7, 0x1aa8, 0x1aa9,
+ 0x1aaa, 0x1aab, 0x1aac, 0x1aae, 0x1aaf, 0x1ab0, 0x1ab1, 0x1ab3,
+ 0x1ab4, 0x1ab5, 0x1ab7, 0x1ab8, 0x1aba, 0x1abb, 0x1abd, 0x1abf,
+ 0x1ac0, 0x1ac0, 0x1ac0, 0x1ac0, 0x1ac1, 0x1ac1, 0x1ac2, 0x1ac2,
+ 0x1ac3, 0x1ac4, 0x1ac5, 0x1ac5, 0x1ac6, 0x1ac7, 0x1ac8, 0x1ac9,
+ 0x1aca, 0x1acb, 0x1acc, 0x1ace, 0x1acf, 0x1ad0, 0x1ad1, 0x1ad3,
+ 0x1ad4, 0x1ad5, 0x1ad7, 0x1ad8, 0x1ada, 0x1adb, 0x1add, 0x1adf,
+ 0x1ae0, 0x1ae0, 0x1ae0, 0x1ae0, 0x1ae1, 0x1ae1, 0x1ae2, 0x1ae2,
+ 0x1ae3, 0x1ae4, 0x1ae5, 0x1ae5, 0x1ae6, 0x1ae7, 0x1ae8, 0x1ae9,
+ 0x1aea, 0x1aeb, 0x1aec, 0x1aee, 0x1aef, 0x1af0, 0x1af1, 0x1af3,
+ 0x1af4, 0x1af5, 0x1af7, 0x1af8, 0x1afa, 0x1afb, 0x1afd, 0x1aff,
+ 0x1b00, 0x1b00, 0x1b00, 0x1b00, 0x1b01, 0x1b01, 0x1b02, 0x1b02,
+ 0x1b03, 0x1b04, 0x1b05, 0x1b05, 0x1b06, 0x1b07, 0x1b08, 0x1b09,
+ 0x1b0a, 0x1b0b, 0x1b0c, 0x1b0e, 0x1b0f, 0x1b10, 0x1b11, 0x1b13,
+ 0x1b14, 0x1b15, 0x1b17, 0x1b18, 0x1b1a, 0x1b1b, 0x1b1d, 0x1b1f,
+ 0x1b20, 0x1b20, 0x1b20, 0x1b20, 0x1b21, 0x1b21, 0x1b22, 0x1b22,
+ 0x1b23, 0x1b24, 0x1b25, 0x1b25, 0x1b26, 0x1b27, 0x1b28, 0x1b29,
+ 0x1b2a, 0x1b2b, 0x1b2c, 0x1b2e, 0x1b2f, 0x1b30, 0x1b31, 0x1b33,
+ 0x1b34, 0x1b35, 0x1b37, 0x1b38, 0x1b3a, 0x1b3b, 0x1b3d, 0x1b3f,
+ 0x1b40, 0x1b40, 0x1b40, 0x1b40, 0x1b41, 0x1b41, 0x1b42, 0x1b42,
+ 0x1b43, 0x1b44, 0x1b45, 0x1b45, 0x1b46, 0x1b47, 0x1b48, 0x1b49,
+ 0x1b4a, 0x1b4b, 0x1b4c, 0x1b4e, 0x1b4f, 0x1b50, 0x1b51, 0x1b53,
+ 0x1b54, 0x1b55, 0x1b57, 0x1b58, 0x1b5a, 0x1b5b, 0x1b5d, 0x1b5f,
+ 0x1b80, 0x1b80, 0x1b80, 0x1b80, 0x1b81, 0x1b81, 0x1b82, 0x1b82,
+ 0x1b83, 0x1b84, 0x1b85, 0x1b85, 0x1b86, 0x1b87, 0x1b88, 0x1b89,
+ 0x1b8a, 0x1b8b, 0x1b8c, 0x1b8e, 0x1b8f, 0x1b90, 0x1b91, 0x1b93,
+ 0x1b94, 0x1b95, 0x1b97, 0x1b98, 0x1b9a, 0x1b9b, 0x1b9d, 0x1b9f,
+ 0x1ba0, 0x1ba0, 0x1ba0, 0x1ba0, 0x1ba1, 0x1ba1, 0x1ba2, 0x1ba2,
+ 0x1ba3, 0x1ba4, 0x1ba5, 0x1ba5, 0x1ba6, 0x1ba7, 0x1ba8, 0x1ba9,
+ 0x1baa, 0x1bab, 0x1bac, 0x1bae, 0x1baf, 0x1bb0, 0x1bb1, 0x1bb3,
+ 0x1bb4, 0x1bb5, 0x1bb7, 0x1bb8, 0x1bba, 0x1bbb, 0x1bbd, 0x1bbf,
+ 0x1bc0, 0x1bc0, 0x1bc0, 0x1bc0, 0x1bc1, 0x1bc1, 0x1bc2, 0x1bc2,
+ 0x1bc3, 0x1bc4, 0x1bc5, 0x1bc5, 0x1bc6, 0x1bc7, 0x1bc8, 0x1bc9,
+ 0x1bca, 0x1bcb, 0x1bcc, 0x1bce, 0x1bcf, 0x1bd0, 0x1bd1, 0x1bd3,
+ 0x1bd4, 0x1bd5, 0x1bd7, 0x1bd8, 0x1bda, 0x1bdb, 0x1bdd, 0x1bdf,
+ 0x1be0, 0x1be0, 0x1be0, 0x1be0, 0x1be1, 0x1be1, 0x1be2, 0x1be2,
+ 0x1be3, 0x1be4, 0x1be5, 0x1be5, 0x1be6, 0x1be7, 0x1be8, 0x1be9,
+ 0x1bea, 0x1beb, 0x1bec, 0x1bee, 0x1bef, 0x1bf0, 0x1bf1, 0x1bf3,
+ 0x1bf4, 0x1bf5, 0x1bf7, 0x1bf8, 0x1bfa, 0x1bfb, 0x1bfd, 0x1bff,
+ 0x1c00, 0x1c00, 0x1c00, 0x1c00, 0x1c01, 0x1c01, 0x1c02, 0x1c02,
+ 0x1c03, 0x1c04, 0x1c05, 0x1c05, 0x1c06, 0x1c07, 0x1c08, 0x1c09,
+ 0x1c0a, 0x1c0b, 0x1c0c, 0x1c0e, 0x1c0f, 0x1c10, 0x1c11, 0x1c13,
+ 0x1c14, 0x1c15, 0x1c17, 0x1c18, 0x1c1a, 0x1c1b, 0x1c1d, 0x1c1f,
+ 0x1c40, 0x1c40, 0x1c40, 0x1c40, 0x1c41, 0x1c41, 0x1c42, 0x1c42,
+ 0x1c43, 0x1c44, 0x1c45, 0x1c45, 0x1c46, 0x1c47, 0x1c48, 0x1c49,
+ 0x1c4a, 0x1c4b, 0x1c4c, 0x1c4e, 0x1c4f, 0x1c50, 0x1c51, 0x1c53,
+ 0x1c54, 0x1c55, 0x1c57, 0x1c58, 0x1c5a, 0x1c5b, 0x1c5d, 0x1c5f,
+ 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c61, 0x1c61, 0x1c62, 0x1c62,
+ 0x1c63, 0x1c64, 0x1c65, 0x1c65, 0x1c66, 0x1c67, 0x1c68, 0x1c69,
+ 0x1c6a, 0x1c6b, 0x1c6c, 0x1c6e, 0x1c6f, 0x1c70, 0x1c71, 0x1c73,
+ 0x1c74, 0x1c75, 0x1c77, 0x1c78, 0x1c7a, 0x1c7b, 0x1c7d, 0x1c7f,
+ 0x1c80, 0x1c80, 0x1c80, 0x1c80, 0x1c81, 0x1c81, 0x1c82, 0x1c82,
+ 0x1c83, 0x1c84, 0x1c85, 0x1c85, 0x1c86, 0x1c87, 0x1c88, 0x1c89,
+ 0x1c8a, 0x1c8b, 0x1c8c, 0x1c8e, 0x1c8f, 0x1c90, 0x1c91, 0x1c93,
+ 0x1c94, 0x1c95, 0x1c97, 0x1c98, 0x1c9a, 0x1c9b, 0x1c9d, 0x1c9f,
+ 0x1cc0, 0x1cc0, 0x1cc0, 0x1cc0, 0x1cc1, 0x1cc1, 0x1cc2, 0x1cc2,
+ 0x1cc3, 0x1cc4, 0x1cc5, 0x1cc5, 0x1cc6, 0x1cc7, 0x1cc8, 0x1cc9,
+ 0x1cca, 0x1ccb, 0x1ccc, 0x1cce, 0x1ccf, 0x1cd0, 0x1cd1, 0x1cd3,
+ 0x1cd4, 0x1cd5, 0x1cd7, 0x1cd8, 0x1cda, 0x1cdb, 0x1cdd, 0x1cdf,
+ 0x1ce0, 0x1ce0, 0x1ce0, 0x1ce0, 0x1ce1, 0x1ce1, 0x1ce2, 0x1ce2,
+ 0x1ce3, 0x1ce4, 0x1ce5, 0x1ce5, 0x1ce6, 0x1ce7, 0x1ce8, 0x1ce9,
+ 0x1cea, 0x1ceb, 0x1cec, 0x1cee, 0x1cef, 0x1cf0, 0x1cf1, 0x1cf3,
+ 0x1cf4, 0x1cf5, 0x1cf7, 0x1cf8, 0x1cfa, 0x1cfb, 0x1cfd, 0x1cff,
+ 0x1d00, 0x1d00, 0x1d00, 0x1d00, 0x1d01, 0x1d01, 0x1d02, 0x1d02,
+ 0x1d03, 0x1d04, 0x1d05, 0x1d05, 0x1d06, 0x1d07, 0x1d08, 0x1d09,
+ 0x1d0a, 0x1d0b, 0x1d0c, 0x1d0e, 0x1d0f, 0x1d10, 0x1d11, 0x1d13,
+ 0x1d14, 0x1d15, 0x1d17, 0x1d18, 0x1d1a, 0x1d1b, 0x1d1d, 0x1d1f,
+ 0x1d40, 0x1d40, 0x1d40, 0x1d40, 0x1d41, 0x1d41, 0x1d42, 0x1d42,
+ 0x1d43, 0x1d44, 0x1d45, 0x1d45, 0x1d46, 0x1d47, 0x1d48, 0x1d49,
+ 0x1d4a, 0x1d4b, 0x1d4c, 0x1d4e, 0x1d4f, 0x1d50, 0x1d51, 0x1d53,
+ 0x1d54, 0x1d55, 0x1d57, 0x1d58, 0x1d5a, 0x1d5b, 0x1d5d, 0x1d5f,
+ 0x1d60, 0x1d60, 0x1d60, 0x1d60, 0x1d61, 0x1d61, 0x1d62, 0x1d62,
+ 0x1d63, 0x1d64, 0x1d65, 0x1d65, 0x1d66, 0x1d67, 0x1d68, 0x1d69,
+ 0x1d6a, 0x1d6b, 0x1d6c, 0x1d6e, 0x1d6f, 0x1d70, 0x1d71, 0x1d73,
+ 0x1d74, 0x1d75, 0x1d77, 0x1d78, 0x1d7a, 0x1d7b, 0x1d7d, 0x1d7f,
+ 0x1d80, 0x1d80, 0x1d80, 0x1d80, 0x1d81, 0x1d81, 0x1d82, 0x1d82,
+ 0x1d83, 0x1d84, 0x1d85, 0x1d85, 0x1d86, 0x1d87, 0x1d88, 0x1d89,
+ 0x1d8a, 0x1d8b, 0x1d8c, 0x1d8e, 0x1d8f, 0x1d90, 0x1d91, 0x1d93,
+ 0x1d94, 0x1d95, 0x1d97, 0x1d98, 0x1d9a, 0x1d9b, 0x1d9d, 0x1d9f,
+ 0x1dc0, 0x1dc0, 0x1dc0, 0x1dc0, 0x1dc1, 0x1dc1, 0x1dc2, 0x1dc2,
+ 0x1dc3, 0x1dc4, 0x1dc5, 0x1dc5, 0x1dc6, 0x1dc7, 0x1dc8, 0x1dc9,
+ 0x1dca, 0x1dcb, 0x1dcc, 0x1dce, 0x1dcf, 0x1dd0, 0x1dd1, 0x1dd3,
+ 0x1dd4, 0x1dd5, 0x1dd7, 0x1dd8, 0x1dda, 0x1ddb, 0x1ddd, 0x1ddf,
+ 0x1de0, 0x1de0, 0x1de0, 0x1de0, 0x1de1, 0x1de1, 0x1de2, 0x1de2,
+ 0x1de3, 0x1de4, 0x1de5, 0x1de5, 0x1de6, 0x1de7, 0x1de8, 0x1de9,
+ 0x1dea, 0x1deb, 0x1dec, 0x1dee, 0x1def, 0x1df0, 0x1df1, 0x1df3,
+ 0x1df4, 0x1df5, 0x1df7, 0x1df8, 0x1dfa, 0x1dfb, 0x1dfd, 0x1dff,
+ 0x1e20, 0x1e20, 0x1e20, 0x1e20, 0x1e21, 0x1e21, 0x1e22, 0x1e22,
+ 0x1e23, 0x1e24, 0x1e25, 0x1e25, 0x1e26, 0x1e27, 0x1e28, 0x1e29,
+ 0x1e2a, 0x1e2b, 0x1e2c, 0x1e2e, 0x1e2f, 0x1e30, 0x1e31, 0x1e33,
+ 0x1e34, 0x1e35, 0x1e37, 0x1e38, 0x1e3a, 0x1e3b, 0x1e3d, 0x1e3f,
+ 0x1e40, 0x1e40, 0x1e40, 0x1e40, 0x1e41, 0x1e41, 0x1e42, 0x1e42,
+ 0x1e43, 0x1e44, 0x1e45, 0x1e45, 0x1e46, 0x1e47, 0x1e48, 0x1e49,
+ 0x1e4a, 0x1e4b, 0x1e4c, 0x1e4e, 0x1e4f, 0x1e50, 0x1e51, 0x1e53,
+ 0x1e54, 0x1e55, 0x1e57, 0x1e58, 0x1e5a, 0x1e5b, 0x1e5d, 0x1e5f,
+ 0x1e80, 0x1e80, 0x1e80, 0x1e80, 0x1e81, 0x1e81, 0x1e82, 0x1e82,
+ 0x1e83, 0x1e84, 0x1e85, 0x1e85, 0x1e86, 0x1e87, 0x1e88, 0x1e89,
+ 0x1e8a, 0x1e8b, 0x1e8c, 0x1e8e, 0x1e8f, 0x1e90, 0x1e91, 0x1e93,
+ 0x1e94, 0x1e95, 0x1e97, 0x1e98, 0x1e9a, 0x1e9b, 0x1e9d, 0x1e9f,
+ 0x1ea0, 0x1ea0, 0x1ea0, 0x1ea0, 0x1ea1, 0x1ea1, 0x1ea2, 0x1ea2,
+ 0x1ea3, 0x1ea4, 0x1ea5, 0x1ea5, 0x1ea6, 0x1ea7, 0x1ea8, 0x1ea9,
+ 0x1eaa, 0x1eab, 0x1eac, 0x1eae, 0x1eaf, 0x1eb0, 0x1eb1, 0x1eb3,
+ 0x1eb4, 0x1eb5, 0x1eb7, 0x1eb8, 0x1eba, 0x1ebb, 0x1ebd, 0x1ebf,
+ 0x1ee0, 0x1ee0, 0x1ee0, 0x1ee0, 0x1ee1, 0x1ee1, 0x1ee2, 0x1ee2,
+ 0x1ee3, 0x1ee4, 0x1ee5, 0x1ee5, 0x1ee6, 0x1ee7, 0x1ee8, 0x1ee9,
+ 0x1eea, 0x1eeb, 0x1eec, 0x1eee, 0x1eef, 0x1ef0, 0x1ef1, 0x1ef3,
+ 0x1ef4, 0x1ef5, 0x1ef7, 0x1ef8, 0x1efa, 0x1efb, 0x1efd, 0x1eff,
+ 0x1f00, 0x1f00, 0x1f00, 0x1f00, 0x1f01, 0x1f01, 0x1f02, 0x1f02,
+ 0x1f03, 0x1f04, 0x1f05, 0x1f05, 0x1f06, 0x1f07, 0x1f08, 0x1f09,
+ 0x1f0a, 0x1f0b, 0x1f0c, 0x1f0e, 0x1f0f, 0x1f10, 0x1f11, 0x1f13,
+ 0x1f14, 0x1f15, 0x1f17, 0x1f18, 0x1f1a, 0x1f1b, 0x1f1d, 0x1f1f,
+ 0x1f40, 0x1f40, 0x1f40, 0x1f40, 0x1f41, 0x1f41, 0x1f42, 0x1f42,
+ 0x1f43, 0x1f44, 0x1f45, 0x1f45, 0x1f46, 0x1f47, 0x1f48, 0x1f49,
+ 0x1f4a, 0x1f4b, 0x1f4c, 0x1f4e, 0x1f4f, 0x1f50, 0x1f51, 0x1f53,
+ 0x1f54, 0x1f55, 0x1f57, 0x1f58, 0x1f5a, 0x1f5b, 0x1f5d, 0x1f5f,
+ 0x1f60, 0x1f60, 0x1f60, 0x1f60, 0x1f61, 0x1f61, 0x1f62, 0x1f62,
+ 0x1f63, 0x1f64, 0x1f65, 0x1f65, 0x1f66, 0x1f67, 0x1f68, 0x1f69,
+ 0x1f6a, 0x1f6b, 0x1f6c, 0x1f6e, 0x1f6f, 0x1f70, 0x1f71, 0x1f73,
+ 0x1f74, 0x1f75, 0x1f77, 0x1f78, 0x1f7a, 0x1f7b, 0x1f7d, 0x1f7f,
+ 0x1fa0, 0x1fa0, 0x1fa0, 0x1fa0, 0x1fa1, 0x1fa1, 0x1fa2, 0x1fa2,
+ 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa5, 0x1fa6, 0x1fa7, 0x1fa8, 0x1fa9,
+ 0x1faa, 0x1fab, 0x1fac, 0x1fae, 0x1faf, 0x1fb0, 0x1fb1, 0x1fb3,
+ 0x1fb4, 0x1fb5, 0x1fb7, 0x1fb8, 0x1fba, 0x1fbb, 0x1fbd, 0x1fbf,
+ 0x1fe0, 0x1fe0, 0x1fe0, 0x1fe0, 0x1fe1, 0x1fe1, 0x1fe2, 0x1fe2,
+ 0x1fe3, 0x1fe4, 0x1fe5, 0x1fe5, 0x1fe6, 0x1fe7, 0x1fe8, 0x1fe9,
+ 0x1fea, 0x1feb, 0x1fec, 0x1fee, 0x1fef, 0x1ff0, 0x1ff1, 0x1ff3,
+ 0x1ff4, 0x1ff5, 0x1ff7, 0x1ff8, 0x1ffa, 0x1ffb, 0x1ffd, 0x1fff,
+ 0x2000, 0x2000, 0x2000, 0x2000, 0x2001, 0x2001, 0x2002, 0x2002,
+ 0x2003, 0x2004, 0x2005, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009,
+ 0x200a, 0x200b, 0x200c, 0x200e, 0x200f, 0x2010, 0x2011, 0x2013,
+ 0x2014, 0x2015, 0x2017, 0x2018, 0x201a, 0x201b, 0x201d, 0x201f,
+ 0x2000, 0x2000, 0x2000, 0x2000, 0x2001, 0x2001, 0x2002, 0x2002,
+ 0x2003, 0x2004, 0x2005, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009,
+ 0x200a, 0x200b, 0x200c, 0x200e, 0x200f, 0x2010, 0x2011, 0x2013,
+ 0x2014, 0x2015, 0x2017, 0x2018, 0x201a, 0x201b, 0x201d, 0x201f,
+ 0x2000, 0x2000, 0x2000, 0x2000, 0x2001, 0x2001, 0x2002, 0x2002,
+ 0x2003, 0x2004, 0x2005, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009,
+ 0x200a, 0x200b, 0x200c, 0x200e, 0x200f, 0x2010, 0x2011, 0x2013,
+ 0x2014, 0x2015, 0x2017, 0x2018, 0x201a, 0x201b, 0x201d, 0x201f,
+ 0x2000, 0x2000, 0x2000, 0x2000, 0x2001, 0x2001, 0x2002, 0x2002,
+ 0x2003, 0x2004, 0x2005, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009,
+ 0x200a, 0x200b, 0x200c, 0x200e, 0x200f, 0x2010, 0x2011, 0x2013,
+ 0x2014, 0x2015, 0x2017, 0x2018, 0x201a, 0x201b, 0x201d, 0x201f,
+ 0x2000, 0x2000, 0x2000, 0x2000, 0x2001, 0x2001, 0x2002, 0x2002,
+ 0x2003, 0x2004, 0x2005, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009,
+ 0x200a, 0x200b, 0x200c, 0x200e, 0x200f, 0x2010, 0x2011, 0x2013,
+ 0x2014, 0x2015, 0x2017, 0x2018, 0x201a, 0x201b, 0x201d, 0x201f,
+ 0x2020, 0x2020, 0x2020, 0x2020, 0x2021, 0x2021, 0x2022, 0x2022,
+ 0x2023, 0x2024, 0x2025, 0x2025, 0x2026, 0x2027, 0x2028, 0x2029,
+ 0x202a, 0x202b, 0x202c, 0x202e, 0x202f, 0x2030, 0x2031, 0x2033,
+ 0x2034, 0x2035, 0x2037, 0x2038, 0x203a, 0x203b, 0x203d, 0x203f,
+ 0x2020, 0x2020, 0x2020, 0x2020, 0x2021, 0x2021, 0x2022, 0x2022,
+ 0x2023, 0x2024, 0x2025, 0x2025, 0x2026, 0x2027, 0x2028, 0x2029,
+ 0x202a, 0x202b, 0x202c, 0x202e, 0x202f, 0x2030, 0x2031, 0x2033,
+ 0x2034, 0x2035, 0x2037, 0x2038, 0x203a, 0x203b, 0x203d, 0x203f,
+ 0x2020, 0x2020, 0x2020, 0x2020, 0x2021, 0x2021, 0x2022, 0x2022,
+ 0x2023, 0x2024, 0x2025, 0x2025, 0x2026, 0x2027, 0x2028, 0x2029,
+ 0x202a, 0x202b, 0x202c, 0x202e, 0x202f, 0x2030, 0x2031, 0x2033,
+ 0x2034, 0x2035, 0x2037, 0x2038, 0x203a, 0x203b, 0x203d, 0x203f,
+ 0x2040, 0x2040, 0x2040, 0x2040, 0x2041, 0x2041, 0x2042, 0x2042,
+ 0x2043, 0x2044, 0x2045, 0x2045, 0x2046, 0x2047, 0x2048, 0x2049,
+ 0x204a, 0x204b, 0x204c, 0x204e, 0x204f, 0x2050, 0x2051, 0x2053,
+ 0x2054, 0x2055, 0x2057, 0x2058, 0x205a, 0x205b, 0x205d, 0x205f,
+ 0x2040, 0x2040, 0x2040, 0x2040, 0x2041, 0x2041, 0x2042, 0x2042,
+ 0x2043, 0x2044, 0x2045, 0x2045, 0x2046, 0x2047, 0x2048, 0x2049,
+ 0x204a, 0x204b, 0x204c, 0x204e, 0x204f, 0x2050, 0x2051, 0x2053,
+ 0x2054, 0x2055, 0x2057, 0x2058, 0x205a, 0x205b, 0x205d, 0x205f,
+ 0x2060, 0x2060, 0x2060, 0x2060, 0x2061, 0x2061, 0x2062, 0x2062,
+ 0x2063, 0x2064, 0x2065, 0x2065, 0x2066, 0x2067, 0x2068, 0x2069,
+ 0x206a, 0x206b, 0x206c, 0x206e, 0x206f, 0x2070, 0x2071, 0x2073,
+ 0x2074, 0x2075, 0x2077, 0x2078, 0x207a, 0x207b, 0x207d, 0x207f,
+ 0x2060, 0x2060, 0x2060, 0x2060, 0x2061, 0x2061, 0x2062, 0x2062,
+ 0x2063, 0x2064, 0x2065, 0x2065, 0x2066, 0x2067, 0x2068, 0x2069,
+ 0x206a, 0x206b, 0x206c, 0x206e, 0x206f, 0x2070, 0x2071, 0x2073,
+ 0x2074, 0x2075, 0x2077, 0x2078, 0x207a, 0x207b, 0x207d, 0x207f,
+ 0x2080, 0x2080, 0x2080, 0x2080, 0x2081, 0x2081, 0x2082, 0x2082,
+ 0x2083, 0x2084, 0x2085, 0x2085, 0x2086, 0x2087, 0x2088, 0x2089,
+ 0x208a, 0x208b, 0x208c, 0x208e, 0x208f, 0x2090, 0x2091, 0x2093,
+ 0x2094, 0x2095, 0x2097, 0x2098, 0x209a, 0x209b, 0x209d, 0x209f,
+ 0x20a0, 0x20a0, 0x20a0, 0x20a0, 0x20a1, 0x20a1, 0x20a2, 0x20a2,
+ 0x20a3, 0x20a4, 0x20a5, 0x20a5, 0x20a6, 0x20a7, 0x20a8, 0x20a9,
+ 0x20aa, 0x20ab, 0x20ac, 0x20ae, 0x20af, 0x20b0, 0x20b1, 0x20b3,
+ 0x20b4, 0x20b5, 0x20b7, 0x20b8, 0x20ba, 0x20bb, 0x20bd, 0x20bf,
+ 0x20a0, 0x20a0, 0x20a0, 0x20a0, 0x20a1, 0x20a1, 0x20a2, 0x20a2,
+ 0x20a3, 0x20a4, 0x20a5, 0x20a5, 0x20a6, 0x20a7, 0x20a8, 0x20a9,
+ 0x20aa, 0x20ab, 0x20ac, 0x20ae, 0x20af, 0x20b0, 0x20b1, 0x20b3,
+ 0x20b4, 0x20b5, 0x20b7, 0x20b8, 0x20ba, 0x20bb, 0x20bd, 0x20bf,
+ 0x20c0, 0x20c0, 0x20c0, 0x20c0, 0x20c1, 0x20c1, 0x20c2, 0x20c2,
+ 0x20c3, 0x20c4, 0x20c5, 0x20c5, 0x20c6, 0x20c7, 0x20c8, 0x20c9,
+ 0x20ca, 0x20cb, 0x20cc, 0x20ce, 0x20cf, 0x20d0, 0x20d1, 0x20d3,
+ 0x20d4, 0x20d5, 0x20d7, 0x20d8, 0x20da, 0x20db, 0x20dd, 0x20df,
+ 0x20e0, 0x20e0, 0x20e0, 0x20e0, 0x20e1, 0x20e1, 0x20e2, 0x20e2,
+ 0x20e3, 0x20e4, 0x20e5, 0x20e5, 0x20e6, 0x20e7, 0x20e8, 0x20e9,
+ 0x20ea, 0x20eb, 0x20ec, 0x20ee, 0x20ef, 0x20f0, 0x20f1, 0x20f3,
+ 0x20f4, 0x20f5, 0x20f7, 0x20f8, 0x20fa, 0x20fb, 0x20fd, 0x20ff,
+ 0x20e0, 0x20e0, 0x20e0, 0x20e0, 0x20e1, 0x20e1, 0x20e2, 0x20e2,
+ 0x20e3, 0x20e4, 0x20e5, 0x20e5, 0x20e6, 0x20e7, 0x20e8, 0x20e9,
+ 0x20ea, 0x20eb, 0x20ec, 0x20ee, 0x20ef, 0x20f0, 0x20f1, 0x20f3,
+ 0x20f4, 0x20f5, 0x20f7, 0x20f8, 0x20fa, 0x20fb, 0x20fd, 0x20ff,
+ 0x2100, 0x2100, 0x2100, 0x2100, 0x2101, 0x2101, 0x2102, 0x2102,
+ 0x2103, 0x2104, 0x2105, 0x2105, 0x2106, 0x2107, 0x2108, 0x2109,
+ 0x210a, 0x210b, 0x210c, 0x210e, 0x210f, 0x2110, 0x2111, 0x2113,
+ 0x2114, 0x2115, 0x2117, 0x2118, 0x211a, 0x211b, 0x211d, 0x211f,
+ 0x2120, 0x2120, 0x2120, 0x2120, 0x2121, 0x2121, 0x2122, 0x2122,
+ 0x2123, 0x2124, 0x2125, 0x2125, 0x2126, 0x2127, 0x2128, 0x2129,
+ 0x212a, 0x212b, 0x212c, 0x212e, 0x212f, 0x2130, 0x2131, 0x2133,
+ 0x2134, 0x2135, 0x2137, 0x2138, 0x213a, 0x213b, 0x213d, 0x213f,
+ 0x2140, 0x2140, 0x2140, 0x2140, 0x2141, 0x2141, 0x2142, 0x2142,
+ 0x2143, 0x2144, 0x2145, 0x2145, 0x2146, 0x2147, 0x2148, 0x2149,
+ 0x214a, 0x214b, 0x214c, 0x214e, 0x214f, 0x2150, 0x2151, 0x2153,
+ 0x2154, 0x2155, 0x2157, 0x2158, 0x215a, 0x215b, 0x215d, 0x215f,
+ 0x2140, 0x2140, 0x2140, 0x2140, 0x2141, 0x2141, 0x2142, 0x2142,
+ 0x2143, 0x2144, 0x2145, 0x2145, 0x2146, 0x2147, 0x2148, 0x2149,
+ 0x214a, 0x214b, 0x214c, 0x214e, 0x214f, 0x2150, 0x2151, 0x2153,
+ 0x2154, 0x2155, 0x2157, 0x2158, 0x215a, 0x215b, 0x215d, 0x215f,
+ 0x2160, 0x2160, 0x2160, 0x2160, 0x2161, 0x2161, 0x2162, 0x2162,
+ 0x2163, 0x2164, 0x2165, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169,
+ 0x216a, 0x216b, 0x216c, 0x216e, 0x216f, 0x2170, 0x2171, 0x2173,
+ 0x2174, 0x2175, 0x2177, 0x2178, 0x217a, 0x217b, 0x217d, 0x217f,
+ 0x2180, 0x2180, 0x2180, 0x2180, 0x2181, 0x2181, 0x2182, 0x2182,
+ 0x2183, 0x2184, 0x2185, 0x2185, 0x2186, 0x2187, 0x2188, 0x2189,
+ 0x218a, 0x218b, 0x218c, 0x218e, 0x218f, 0x2190, 0x2191, 0x2193,
+ 0x2194, 0x2195, 0x2197, 0x2198, 0x219a, 0x219b, 0x219d, 0x219f,
+ 0x21a0, 0x21a0, 0x21a0, 0x21a0, 0x21a1, 0x21a1, 0x21a2, 0x21a2,
+ 0x21a3, 0x21a4, 0x21a5, 0x21a5, 0x21a6, 0x21a7, 0x21a8, 0x21a9,
+ 0x21aa, 0x21ab, 0x21ac, 0x21ae, 0x21af, 0x21b0, 0x21b1, 0x21b3,
+ 0x21b4, 0x21b5, 0x21b7, 0x21b8, 0x21ba, 0x21bb, 0x21bd, 0x21bf,
+ 0x21c0, 0x21c0, 0x21c0, 0x21c0, 0x21c1, 0x21c1, 0x21c2, 0x21c2,
+ 0x21c3, 0x21c4, 0x21c5, 0x21c5, 0x21c6, 0x21c7, 0x21c8, 0x21c9,
+ 0x21ca, 0x21cb, 0x21cc, 0x21ce, 0x21cf, 0x21d0, 0x21d1, 0x21d3,
+ 0x21d4, 0x21d5, 0x21d7, 0x21d8, 0x21da, 0x21db, 0x21dd, 0x21df,
+ 0x21e0, 0x21e0, 0x21e0, 0x21e0, 0x21e1, 0x21e1, 0x21e2, 0x21e2,
+ 0x21e3, 0x21e4, 0x21e5, 0x21e5, 0x21e6, 0x21e7, 0x21e8, 0x21e9,
+ 0x21ea, 0x21eb, 0x21ec, 0x21ee, 0x21ef, 0x21f0, 0x21f1, 0x21f3,
+ 0x21f4, 0x21f5, 0x21f7, 0x21f8, 0x21fa, 0x21fb, 0x21fd, 0x21ff,
+ 0x2200, 0x2200, 0x2200, 0x2200, 0x2201, 0x2201, 0x2202, 0x2202,
+ 0x2203, 0x2204, 0x2205, 0x2205, 0x2206, 0x2207, 0x2208, 0x2209,
+ 0x220a, 0x220b, 0x220c, 0x220e, 0x220f, 0x2210, 0x2211, 0x2213,
+ 0x2214, 0x2215, 0x2217, 0x2218, 0x221a, 0x221b, 0x221d, 0x221f,
+ 0x2220, 0x2220, 0x2220, 0x2220, 0x2221, 0x2221, 0x2222, 0x2222,
+ 0x2223, 0x2224, 0x2225, 0x2225, 0x2226, 0x2227, 0x2228, 0x2229,
+ 0x222a, 0x222b, 0x222c, 0x222e, 0x222f, 0x2230, 0x2231, 0x2233,
+ 0x2234, 0x2235, 0x2237, 0x2238, 0x223a, 0x223b, 0x223d, 0x223f,
+ 0x2240, 0x2240, 0x2240, 0x2240, 0x2241, 0x2241, 0x2242, 0x2242,
+ 0x2243, 0x2244, 0x2245, 0x2245, 0x2246, 0x2247, 0x2248, 0x2249,
+ 0x224a, 0x224b, 0x224c, 0x224e, 0x224f, 0x2250, 0x2251, 0x2253,
+ 0x2254, 0x2255, 0x2257, 0x2258, 0x225a, 0x225b, 0x225d, 0x225f,
+ 0x2260, 0x2260, 0x2260, 0x2260, 0x2261, 0x2261, 0x2262, 0x2262,
+ 0x2263, 0x2264, 0x2265, 0x2265, 0x2266, 0x2267, 0x2268, 0x2269,
+ 0x226a, 0x226b, 0x226c, 0x226e, 0x226f, 0x2270, 0x2271, 0x2273,
+ 0x2274, 0x2275, 0x2277, 0x2278, 0x227a, 0x227b, 0x227d, 0x227f,
+ 0x2280, 0x2280, 0x2280, 0x2280, 0x2281, 0x2281, 0x2282, 0x2282,
+ 0x2283, 0x2284, 0x2285, 0x2285, 0x2286, 0x2287, 0x2288, 0x2289,
+ 0x228a, 0x228b, 0x228c, 0x228e, 0x228f, 0x2290, 0x2291, 0x2293,
+ 0x2294, 0x2295, 0x2297, 0x2298, 0x229a, 0x229b, 0x229d, 0x229f,
+ 0x22a0, 0x22a0, 0x22a0, 0x22a0, 0x22a1, 0x22a1, 0x22a2, 0x22a2,
+ 0x22a3, 0x22a4, 0x22a5, 0x22a5, 0x22a6, 0x22a7, 0x22a8, 0x22a9,
+ 0x22aa, 0x22ab, 0x22ac, 0x22ae, 0x22af, 0x22b0, 0x22b1, 0x22b3,
+ 0x22b4, 0x22b5, 0x22b7, 0x22b8, 0x22ba, 0x22bb, 0x22bd, 0x22bf,
+ 0x22c0, 0x22c0, 0x22c0, 0x22c0, 0x22c1, 0x22c1, 0x22c2, 0x22c2,
+ 0x22c3, 0x22c4, 0x22c5, 0x22c5, 0x22c6, 0x22c7, 0x22c8, 0x22c9,
+ 0x22ca, 0x22cb, 0x22cc, 0x22ce, 0x22cf, 0x22d0, 0x22d1, 0x22d3,
+ 0x22d4, 0x22d5, 0x22d7, 0x22d8, 0x22da, 0x22db, 0x22dd, 0x22df,
+ 0x22e0, 0x22e0, 0x22e0, 0x22e0, 0x22e1, 0x22e1, 0x22e2, 0x22e2,
+ 0x22e3, 0x22e4, 0x22e5, 0x22e5, 0x22e6, 0x22e7, 0x22e8, 0x22e9,
+ 0x22ea, 0x22eb, 0x22ec, 0x22ee, 0x22ef, 0x22f0, 0x22f1, 0x22f3,
+ 0x22f4, 0x22f5, 0x22f7, 0x22f8, 0x22fa, 0x22fb, 0x22fd, 0x22ff,
+ 0x2300, 0x2300, 0x2300, 0x2300, 0x2301, 0x2301, 0x2302, 0x2302,
+ 0x2303, 0x2304, 0x2305, 0x2305, 0x2306, 0x2307, 0x2308, 0x2309,
+ 0x230a, 0x230b, 0x230c, 0x230e, 0x230f, 0x2310, 0x2311, 0x2313,
+ 0x2314, 0x2315, 0x2317, 0x2318, 0x231a, 0x231b, 0x231d, 0x231f,
+ 0x2320, 0x2320, 0x2320, 0x2320, 0x2321, 0x2321, 0x2322, 0x2322,
+ 0x2323, 0x2324, 0x2325, 0x2325, 0x2326, 0x2327, 0x2328, 0x2329,
+ 0x232a, 0x232b, 0x232c, 0x232e, 0x232f, 0x2330, 0x2331, 0x2333,
+ 0x2334, 0x2335, 0x2337, 0x2338, 0x233a, 0x233b, 0x233d, 0x233f,
+ 0x2340, 0x2340, 0x2340, 0x2340, 0x2341, 0x2341, 0x2342, 0x2342,
+ 0x2343, 0x2344, 0x2345, 0x2345, 0x2346, 0x2347, 0x2348, 0x2349,
+ 0x234a, 0x234b, 0x234c, 0x234e, 0x234f, 0x2350, 0x2351, 0x2353,
+ 0x2354, 0x2355, 0x2357, 0x2358, 0x235a, 0x235b, 0x235d, 0x235f,
+ 0x2380, 0x2380, 0x2380, 0x2380, 0x2381, 0x2381, 0x2382, 0x2382,
+ 0x2383, 0x2384, 0x2385, 0x2385, 0x2386, 0x2387, 0x2388, 0x2389,
+ 0x238a, 0x238b, 0x238c, 0x238e, 0x238f, 0x2390, 0x2391, 0x2393,
+ 0x2394, 0x2395, 0x2397, 0x2398, 0x239a, 0x239b, 0x239d, 0x239f,
+ 0x23a0, 0x23a0, 0x23a0, 0x23a0, 0x23a1, 0x23a1, 0x23a2, 0x23a2,
+ 0x23a3, 0x23a4, 0x23a5, 0x23a5, 0x23a6, 0x23a7, 0x23a8, 0x23a9,
+ 0x23aa, 0x23ab, 0x23ac, 0x23ae, 0x23af, 0x23b0, 0x23b1, 0x23b3,
+ 0x23b4, 0x23b5, 0x23b7, 0x23b8, 0x23ba, 0x23bb, 0x23bd, 0x23bf,
+ 0x23c0, 0x23c0, 0x23c0, 0x23c0, 0x23c1, 0x23c1, 0x23c2, 0x23c2,
+ 0x23c3, 0x23c4, 0x23c5, 0x23c5, 0x23c6, 0x23c7, 0x23c8, 0x23c9,
+ 0x23ca, 0x23cb, 0x23cc, 0x23ce, 0x23cf, 0x23d0, 0x23d1, 0x23d3,
+ 0x23d4, 0x23d5, 0x23d7, 0x23d8, 0x23da, 0x23db, 0x23dd, 0x23df,
+ 0x23e0, 0x23e0, 0x23e0, 0x23e0, 0x23e1, 0x23e1, 0x23e2, 0x23e2,
+ 0x23e3, 0x23e4, 0x23e5, 0x23e5, 0x23e6, 0x23e7, 0x23e8, 0x23e9,
+ 0x23ea, 0x23eb, 0x23ec, 0x23ee, 0x23ef, 0x23f0, 0x23f1, 0x23f3,
+ 0x23f4, 0x23f5, 0x23f7, 0x23f8, 0x23fa, 0x23fb, 0x23fd, 0x23ff,
+ 0x2400, 0x2400, 0x2400, 0x2400, 0x2401, 0x2401, 0x2402, 0x2402,
+ 0x2403, 0x2404, 0x2405, 0x2405, 0x2406, 0x2407, 0x2408, 0x2409,
+ 0x240a, 0x240b, 0x240c, 0x240e, 0x240f, 0x2410, 0x2411, 0x2413,
+ 0x2414, 0x2415, 0x2417, 0x2418, 0x241a, 0x241b, 0x241d, 0x241f,
+ 0x2440, 0x2440, 0x2440, 0x2440, 0x2441, 0x2441, 0x2442, 0x2442,
+ 0x2443, 0x2444, 0x2445, 0x2445, 0x2446, 0x2447, 0x2448, 0x2449,
+ 0x244a, 0x244b, 0x244c, 0x244e, 0x244f, 0x2450, 0x2451, 0x2453,
+ 0x2454, 0x2455, 0x2457, 0x2458, 0x245a, 0x245b, 0x245d, 0x245f,
+ 0x2460, 0x2460, 0x2460, 0x2460, 0x2461, 0x2461, 0x2462, 0x2462,
+ 0x2463, 0x2464, 0x2465, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469,
+ 0x246a, 0x246b, 0x246c, 0x246e, 0x246f, 0x2470, 0x2471, 0x2473,
+ 0x2474, 0x2475, 0x2477, 0x2478, 0x247a, 0x247b, 0x247d, 0x247f,
+ 0x2480, 0x2480, 0x2480, 0x2480, 0x2481, 0x2481, 0x2482, 0x2482,
+ 0x2483, 0x2484, 0x2485, 0x2485, 0x2486, 0x2487, 0x2488, 0x2489,
+ 0x248a, 0x248b, 0x248c, 0x248e, 0x248f, 0x2490, 0x2491, 0x2493,
+ 0x2494, 0x2495, 0x2497, 0x2498, 0x249a, 0x249b, 0x249d, 0x249f,
+ 0x24c0, 0x24c0, 0x24c0, 0x24c0, 0x24c1, 0x24c1, 0x24c2, 0x24c2,
+ 0x24c3, 0x24c4, 0x24c5, 0x24c5, 0x24c6, 0x24c7, 0x24c8, 0x24c9,
+ 0x24ca, 0x24cb, 0x24cc, 0x24ce, 0x24cf, 0x24d0, 0x24d1, 0x24d3,
+ 0x24d4, 0x24d5, 0x24d7, 0x24d8, 0x24da, 0x24db, 0x24dd, 0x24df,
+ 0x24e0, 0x24e0, 0x24e0, 0x24e0, 0x24e1, 0x24e1, 0x24e2, 0x24e2,
+ 0x24e3, 0x24e4, 0x24e5, 0x24e5, 0x24e6, 0x24e7, 0x24e8, 0x24e9,
+ 0x24ea, 0x24eb, 0x24ec, 0x24ee, 0x24ef, 0x24f0, 0x24f1, 0x24f3,
+ 0x24f4, 0x24f5, 0x24f7, 0x24f8, 0x24fa, 0x24fb, 0x24fd, 0x24ff,
+ 0x2500, 0x2500, 0x2500, 0x2500, 0x2501, 0x2501, 0x2502, 0x2502,
+ 0x2503, 0x2504, 0x2505, 0x2505, 0x2506, 0x2507, 0x2508, 0x2509,
+ 0x250a, 0x250b, 0x250c, 0x250e, 0x250f, 0x2510, 0x2511, 0x2513,
+ 0x2514, 0x2515, 0x2517, 0x2518, 0x251a, 0x251b, 0x251d, 0x251f,
+ 0x2540, 0x2540, 0x2540, 0x2540, 0x2541, 0x2541, 0x2542, 0x2542,
+ 0x2543, 0x2544, 0x2545, 0x2545, 0x2546, 0x2547, 0x2548, 0x2549,
+ 0x254a, 0x254b, 0x254c, 0x254e, 0x254f, 0x2550, 0x2551, 0x2553,
+ 0x2554, 0x2555, 0x2557, 0x2558, 0x255a, 0x255b, 0x255d, 0x255f,
+ 0x2560, 0x2560, 0x2560, 0x2560, 0x2561, 0x2561, 0x2562, 0x2562,
+ 0x2563, 0x2564, 0x2565, 0x2565, 0x2566, 0x2567, 0x2568, 0x2569,
+ 0x256a, 0x256b, 0x256c, 0x256e, 0x256f, 0x2570, 0x2571, 0x2573,
+ 0x2574, 0x2575, 0x2577, 0x2578, 0x257a, 0x257b, 0x257d, 0x257f,
+ 0x2580, 0x2580, 0x2580, 0x2580, 0x2581, 0x2581, 0x2582, 0x2582,
+ 0x2583, 0x2584, 0x2585, 0x2585, 0x2586, 0x2587, 0x2588, 0x2589,
+ 0x258a, 0x258b, 0x258c, 0x258e, 0x258f, 0x2590, 0x2591, 0x2593,
+ 0x2594, 0x2595, 0x2597, 0x2598, 0x259a, 0x259b, 0x259d, 0x259f,
+ 0x25c0, 0x25c0, 0x25c0, 0x25c0, 0x25c1, 0x25c1, 0x25c2, 0x25c2,
+ 0x25c3, 0x25c4, 0x25c5, 0x25c5, 0x25c6, 0x25c7, 0x25c8, 0x25c9,
+ 0x25ca, 0x25cb, 0x25cc, 0x25ce, 0x25cf, 0x25d0, 0x25d1, 0x25d3,
+ 0x25d4, 0x25d5, 0x25d7, 0x25d8, 0x25da, 0x25db, 0x25dd, 0x25df,
+ 0x25e0, 0x25e0, 0x25e0, 0x25e0, 0x25e1, 0x25e1, 0x25e2, 0x25e2,
+ 0x25e3, 0x25e4, 0x25e5, 0x25e5, 0x25e6, 0x25e7, 0x25e8, 0x25e9,
+ 0x25ea, 0x25eb, 0x25ec, 0x25ee, 0x25ef, 0x25f0, 0x25f1, 0x25f3,
+ 0x25f4, 0x25f5, 0x25f7, 0x25f8, 0x25fa, 0x25fb, 0x25fd, 0x25ff,
+ 0x2620, 0x2620, 0x2620, 0x2620, 0x2621, 0x2621, 0x2622, 0x2622,
+ 0x2623, 0x2624, 0x2625, 0x2625, 0x2626, 0x2627, 0x2628, 0x2629,
+ 0x262a, 0x262b, 0x262c, 0x262e, 0x262f, 0x2630, 0x2631, 0x2633,
+ 0x2634, 0x2635, 0x2637, 0x2638, 0x263a, 0x263b, 0x263d, 0x263f,
+ 0x2640, 0x2640, 0x2640, 0x2640, 0x2641, 0x2641, 0x2642, 0x2642,
+ 0x2643, 0x2644, 0x2645, 0x2645, 0x2646, 0x2647, 0x2648, 0x2649,
+ 0x264a, 0x264b, 0x264c, 0x264e, 0x264f, 0x2650, 0x2651, 0x2653,
+ 0x2654, 0x2655, 0x2657, 0x2658, 0x265a, 0x265b, 0x265d, 0x265f,
+ 0x2680, 0x2680, 0x2680, 0x2680, 0x2681, 0x2681, 0x2682, 0x2682,
+ 0x2683, 0x2684, 0x2685, 0x2685, 0x2686, 0x2687, 0x2688, 0x2689,
+ 0x268a, 0x268b, 0x268c, 0x268e, 0x268f, 0x2690, 0x2691, 0x2693,
+ 0x2694, 0x2695, 0x2697, 0x2698, 0x269a, 0x269b, 0x269d, 0x269f,
+ 0x26a0, 0x26a0, 0x26a0, 0x26a0, 0x26a1, 0x26a1, 0x26a2, 0x26a2,
+ 0x26a3, 0x26a4, 0x26a5, 0x26a5, 0x26a6, 0x26a7, 0x26a8, 0x26a9,
+ 0x26aa, 0x26ab, 0x26ac, 0x26ae, 0x26af, 0x26b0, 0x26b1, 0x26b3,
+ 0x26b4, 0x26b5, 0x26b7, 0x26b8, 0x26ba, 0x26bb, 0x26bd, 0x26bf,
+ 0x26e0, 0x26e0, 0x26e0, 0x26e0, 0x26e1, 0x26e1, 0x26e2, 0x26e2,
+ 0x26e3, 0x26e4, 0x26e5, 0x26e5, 0x26e6, 0x26e7, 0x26e8, 0x26e9,
+ 0x26ea, 0x26eb, 0x26ec, 0x26ee, 0x26ef, 0x26f0, 0x26f1, 0x26f3,
+ 0x26f4, 0x26f5, 0x26f7, 0x26f8, 0x26fa, 0x26fb, 0x26fd, 0x26ff,
+ 0x2700, 0x2700, 0x2700, 0x2700, 0x2701, 0x2701, 0x2702, 0x2702,
+ 0x2703, 0x2704, 0x2705, 0x2705, 0x2706, 0x2707, 0x2708, 0x2709,
+ 0x270a, 0x270b, 0x270c, 0x270e, 0x270f, 0x2710, 0x2711, 0x2713,
+ 0x2714, 0x2715, 0x2717, 0x2718, 0x271a, 0x271b, 0x271d, 0x271f,
+ 0x2740, 0x2740, 0x2740, 0x2740, 0x2741, 0x2741, 0x2742, 0x2742,
+ 0x2743, 0x2744, 0x2745, 0x2745, 0x2746, 0x2747, 0x2748, 0x2749,
+ 0x274a, 0x274b, 0x274c, 0x274e, 0x274f, 0x2750, 0x2751, 0x2753,
+ 0x2754, 0x2755, 0x2757, 0x2758, 0x275a, 0x275b, 0x275d, 0x275f,
+ 0x2760, 0x2760, 0x2760, 0x2760, 0x2761, 0x2761, 0x2762, 0x2762,
+ 0x2763, 0x2764, 0x2765, 0x2765, 0x2766, 0x2767, 0x2768, 0x2769,
+ 0x276a, 0x276b, 0x276c, 0x276e, 0x276f, 0x2770, 0x2771, 0x2773,
+ 0x2774, 0x2775, 0x2777, 0x2778, 0x277a, 0x277b, 0x277d, 0x277f,
+ 0x27a0, 0x27a0, 0x27a0, 0x27a0, 0x27a1, 0x27a1, 0x27a2, 0x27a2,
+ 0x27a3, 0x27a4, 0x27a5, 0x27a5, 0x27a6, 0x27a7, 0x27a8, 0x27a9,
+ 0x27aa, 0x27ab, 0x27ac, 0x27ae, 0x27af, 0x27b0, 0x27b1, 0x27b3,
+ 0x27b4, 0x27b5, 0x27b7, 0x27b8, 0x27ba, 0x27bb, 0x27bd, 0x27bf,
+ 0x27e0, 0x27e0, 0x27e0, 0x27e0, 0x27e1, 0x27e1, 0x27e2, 0x27e2,
+ 0x27e3, 0x27e4, 0x27e5, 0x27e5, 0x27e6, 0x27e7, 0x27e8, 0x27e9,
+ 0x27ea, 0x27eb, 0x27ec, 0x27ee, 0x27ef, 0x27f0, 0x27f1, 0x27f3,
+ 0x27f4, 0x27f5, 0x27f7, 0x27f8, 0x27fa, 0x27fb, 0x27fd, 0x27ff,
+ 0x2800, 0x2800, 0x2800, 0x2800, 0x2801, 0x2801, 0x2802, 0x2802,
+ 0x2803, 0x2804, 0x2805, 0x2805, 0x2806, 0x2807, 0x2808, 0x2809,
+ 0x280a, 0x280b, 0x280c, 0x280e, 0x280f, 0x2810, 0x2811, 0x2813,
+ 0x2814, 0x2815, 0x2817, 0x2818, 0x281a, 0x281b, 0x281d, 0x281f,
+ 0x2800, 0x2800, 0x2800, 0x2800, 0x2801, 0x2801, 0x2802, 0x2802,
+ 0x2803, 0x2804, 0x2805, 0x2805, 0x2806, 0x2807, 0x2808, 0x2809,
+ 0x280a, 0x280b, 0x280c, 0x280e, 0x280f, 0x2810, 0x2811, 0x2813,
+ 0x2814, 0x2815, 0x2817, 0x2818, 0x281a, 0x281b, 0x281d, 0x281f,
+ 0x2800, 0x2800, 0x2800, 0x2800, 0x2801, 0x2801, 0x2802, 0x2802,
+ 0x2803, 0x2804, 0x2805, 0x2805, 0x2806, 0x2807, 0x2808, 0x2809,
+ 0x280a, 0x280b, 0x280c, 0x280e, 0x280f, 0x2810, 0x2811, 0x2813,
+ 0x2814, 0x2815, 0x2817, 0x2818, 0x281a, 0x281b, 0x281d, 0x281f,
+ 0x2800, 0x2800, 0x2800, 0x2800, 0x2801, 0x2801, 0x2802, 0x2802,
+ 0x2803, 0x2804, 0x2805, 0x2805, 0x2806, 0x2807, 0x2808, 0x2809,
+ 0x280a, 0x280b, 0x280c, 0x280e, 0x280f, 0x2810, 0x2811, 0x2813,
+ 0x2814, 0x2815, 0x2817, 0x2818, 0x281a, 0x281b, 0x281d, 0x281f,
+ 0x2800, 0x2800, 0x2800, 0x2800, 0x2801, 0x2801, 0x2802, 0x2802,
+ 0x2803, 0x2804, 0x2805, 0x2805, 0x2806, 0x2807, 0x2808, 0x2809,
+ 0x280a, 0x280b, 0x280c, 0x280e, 0x280f, 0x2810, 0x2811, 0x2813,
+ 0x2814, 0x2815, 0x2817, 0x2818, 0x281a, 0x281b, 0x281d, 0x281f,
+ 0x2820, 0x2820, 0x2820, 0x2820, 0x2821, 0x2821, 0x2822, 0x2822,
+ 0x2823, 0x2824, 0x2825, 0x2825, 0x2826, 0x2827, 0x2828, 0x2829,
+ 0x282a, 0x282b, 0x282c, 0x282e, 0x282f, 0x2830, 0x2831, 0x2833,
+ 0x2834, 0x2835, 0x2837, 0x2838, 0x283a, 0x283b, 0x283d, 0x283f,
+ 0x2820, 0x2820, 0x2820, 0x2820, 0x2821, 0x2821, 0x2822, 0x2822,
+ 0x2823, 0x2824, 0x2825, 0x2825, 0x2826, 0x2827, 0x2828, 0x2829,
+ 0x282a, 0x282b, 0x282c, 0x282e, 0x282f, 0x2830, 0x2831, 0x2833,
+ 0x2834, 0x2835, 0x2837, 0x2838, 0x283a, 0x283b, 0x283d, 0x283f,
+ 0x2820, 0x2820, 0x2820, 0x2820, 0x2821, 0x2821, 0x2822, 0x2822,
+ 0x2823, 0x2824, 0x2825, 0x2825, 0x2826, 0x2827, 0x2828, 0x2829,
+ 0x282a, 0x282b, 0x282c, 0x282e, 0x282f, 0x2830, 0x2831, 0x2833,
+ 0x2834, 0x2835, 0x2837, 0x2838, 0x283a, 0x283b, 0x283d, 0x283f,
+ 0x2840, 0x2840, 0x2840, 0x2840, 0x2841, 0x2841, 0x2842, 0x2842,
+ 0x2843, 0x2844, 0x2845, 0x2845, 0x2846, 0x2847, 0x2848, 0x2849,
+ 0x284a, 0x284b, 0x284c, 0x284e, 0x284f, 0x2850, 0x2851, 0x2853,
+ 0x2854, 0x2855, 0x2857, 0x2858, 0x285a, 0x285b, 0x285d, 0x285f,
+ 0x2840, 0x2840, 0x2840, 0x2840, 0x2841, 0x2841, 0x2842, 0x2842,
+ 0x2843, 0x2844, 0x2845, 0x2845, 0x2846, 0x2847, 0x2848, 0x2849,
+ 0x284a, 0x284b, 0x284c, 0x284e, 0x284f, 0x2850, 0x2851, 0x2853,
+ 0x2854, 0x2855, 0x2857, 0x2858, 0x285a, 0x285b, 0x285d, 0x285f,
+ 0x2860, 0x2860, 0x2860, 0x2860, 0x2861, 0x2861, 0x2862, 0x2862,
+ 0x2863, 0x2864, 0x2865, 0x2865, 0x2866, 0x2867, 0x2868, 0x2869,
+ 0x286a, 0x286b, 0x286c, 0x286e, 0x286f, 0x2870, 0x2871, 0x2873,
+ 0x2874, 0x2875, 0x2877, 0x2878, 0x287a, 0x287b, 0x287d, 0x287f,
+ 0x2860, 0x2860, 0x2860, 0x2860, 0x2861, 0x2861, 0x2862, 0x2862,
+ 0x2863, 0x2864, 0x2865, 0x2865, 0x2866, 0x2867, 0x2868, 0x2869,
+ 0x286a, 0x286b, 0x286c, 0x286e, 0x286f, 0x2870, 0x2871, 0x2873,
+ 0x2874, 0x2875, 0x2877, 0x2878, 0x287a, 0x287b, 0x287d, 0x287f,
+ 0x2880, 0x2880, 0x2880, 0x2880, 0x2881, 0x2881, 0x2882, 0x2882,
+ 0x2883, 0x2884, 0x2885, 0x2885, 0x2886, 0x2887, 0x2888, 0x2889,
+ 0x288a, 0x288b, 0x288c, 0x288e, 0x288f, 0x2890, 0x2891, 0x2893,
+ 0x2894, 0x2895, 0x2897, 0x2898, 0x289a, 0x289b, 0x289d, 0x289f,
+ 0x28a0, 0x28a0, 0x28a0, 0x28a0, 0x28a1, 0x28a1, 0x28a2, 0x28a2,
+ 0x28a3, 0x28a4, 0x28a5, 0x28a5, 0x28a6, 0x28a7, 0x28a8, 0x28a9,
+ 0x28aa, 0x28ab, 0x28ac, 0x28ae, 0x28af, 0x28b0, 0x28b1, 0x28b3,
+ 0x28b4, 0x28b5, 0x28b7, 0x28b8, 0x28ba, 0x28bb, 0x28bd, 0x28bf,
+ 0x28a0, 0x28a0, 0x28a0, 0x28a0, 0x28a1, 0x28a1, 0x28a2, 0x28a2,
+ 0x28a3, 0x28a4, 0x28a5, 0x28a5, 0x28a6, 0x28a7, 0x28a8, 0x28a9,
+ 0x28aa, 0x28ab, 0x28ac, 0x28ae, 0x28af, 0x28b0, 0x28b1, 0x28b3,
+ 0x28b4, 0x28b5, 0x28b7, 0x28b8, 0x28ba, 0x28bb, 0x28bd, 0x28bf,
+ 0x28c0, 0x28c0, 0x28c0, 0x28c0, 0x28c1, 0x28c1, 0x28c2, 0x28c2,
+ 0x28c3, 0x28c4, 0x28c5, 0x28c5, 0x28c6, 0x28c7, 0x28c8, 0x28c9,
+ 0x28ca, 0x28cb, 0x28cc, 0x28ce, 0x28cf, 0x28d0, 0x28d1, 0x28d3,
+ 0x28d4, 0x28d5, 0x28d7, 0x28d8, 0x28da, 0x28db, 0x28dd, 0x28df,
+ 0x28e0, 0x28e0, 0x28e0, 0x28e0, 0x28e1, 0x28e1, 0x28e2, 0x28e2,
+ 0x28e3, 0x28e4, 0x28e5, 0x28e5, 0x28e6, 0x28e7, 0x28e8, 0x28e9,
+ 0x28ea, 0x28eb, 0x28ec, 0x28ee, 0x28ef, 0x28f0, 0x28f1, 0x28f3,
+ 0x28f4, 0x28f5, 0x28f7, 0x28f8, 0x28fa, 0x28fb, 0x28fd, 0x28ff,
+ 0x28e0, 0x28e0, 0x28e0, 0x28e0, 0x28e1, 0x28e1, 0x28e2, 0x28e2,
+ 0x28e3, 0x28e4, 0x28e5, 0x28e5, 0x28e6, 0x28e7, 0x28e8, 0x28e9,
+ 0x28ea, 0x28eb, 0x28ec, 0x28ee, 0x28ef, 0x28f0, 0x28f1, 0x28f3,
+ 0x28f4, 0x28f5, 0x28f7, 0x28f8, 0x28fa, 0x28fb, 0x28fd, 0x28ff,
+ 0x2900, 0x2900, 0x2900, 0x2900, 0x2901, 0x2901, 0x2902, 0x2902,
+ 0x2903, 0x2904, 0x2905, 0x2905, 0x2906, 0x2907, 0x2908, 0x2909,
+ 0x290a, 0x290b, 0x290c, 0x290e, 0x290f, 0x2910, 0x2911, 0x2913,
+ 0x2914, 0x2915, 0x2917, 0x2918, 0x291a, 0x291b, 0x291d, 0x291f,
+ 0x2920, 0x2920, 0x2920, 0x2920, 0x2921, 0x2921, 0x2922, 0x2922,
+ 0x2923, 0x2924, 0x2925, 0x2925, 0x2926, 0x2927, 0x2928, 0x2929,
+ 0x292a, 0x292b, 0x292c, 0x292e, 0x292f, 0x2930, 0x2931, 0x2933,
+ 0x2934, 0x2935, 0x2937, 0x2938, 0x293a, 0x293b, 0x293d, 0x293f,
+ 0x2940, 0x2940, 0x2940, 0x2940, 0x2941, 0x2941, 0x2942, 0x2942,
+ 0x2943, 0x2944, 0x2945, 0x2945, 0x2946, 0x2947, 0x2948, 0x2949,
+ 0x294a, 0x294b, 0x294c, 0x294e, 0x294f, 0x2950, 0x2951, 0x2953,
+ 0x2954, 0x2955, 0x2957, 0x2958, 0x295a, 0x295b, 0x295d, 0x295f,
+ 0x2940, 0x2940, 0x2940, 0x2940, 0x2941, 0x2941, 0x2942, 0x2942,
+ 0x2943, 0x2944, 0x2945, 0x2945, 0x2946, 0x2947, 0x2948, 0x2949,
+ 0x294a, 0x294b, 0x294c, 0x294e, 0x294f, 0x2950, 0x2951, 0x2953,
+ 0x2954, 0x2955, 0x2957, 0x2958, 0x295a, 0x295b, 0x295d, 0x295f,
+ 0x2960, 0x2960, 0x2960, 0x2960, 0x2961, 0x2961, 0x2962, 0x2962,
+ 0x2963, 0x2964, 0x2965, 0x2965, 0x2966, 0x2967, 0x2968, 0x2969,
+ 0x296a, 0x296b, 0x296c, 0x296e, 0x296f, 0x2970, 0x2971, 0x2973,
+ 0x2974, 0x2975, 0x2977, 0x2978, 0x297a, 0x297b, 0x297d, 0x297f,
+ 0x2980, 0x2980, 0x2980, 0x2980, 0x2981, 0x2981, 0x2982, 0x2982,
+ 0x2983, 0x2984, 0x2985, 0x2985, 0x2986, 0x2987, 0x2988, 0x2989,
+ 0x298a, 0x298b, 0x298c, 0x298e, 0x298f, 0x2990, 0x2991, 0x2993,
+ 0x2994, 0x2995, 0x2997, 0x2998, 0x299a, 0x299b, 0x299d, 0x299f,
+ 0x29a0, 0x29a0, 0x29a0, 0x29a0, 0x29a1, 0x29a1, 0x29a2, 0x29a2,
+ 0x29a3, 0x29a4, 0x29a5, 0x29a5, 0x29a6, 0x29a7, 0x29a8, 0x29a9,
+ 0x29aa, 0x29ab, 0x29ac, 0x29ae, 0x29af, 0x29b0, 0x29b1, 0x29b3,
+ 0x29b4, 0x29b5, 0x29b7, 0x29b8, 0x29ba, 0x29bb, 0x29bd, 0x29bf,
+ 0x29c0, 0x29c0, 0x29c0, 0x29c0, 0x29c1, 0x29c1, 0x29c2, 0x29c2,
+ 0x29c3, 0x29c4, 0x29c5, 0x29c5, 0x29c6, 0x29c7, 0x29c8, 0x29c9,
+ 0x29ca, 0x29cb, 0x29cc, 0x29ce, 0x29cf, 0x29d0, 0x29d1, 0x29d3,
+ 0x29d4, 0x29d5, 0x29d7, 0x29d8, 0x29da, 0x29db, 0x29dd, 0x29df,
+ 0x29e0, 0x29e0, 0x29e0, 0x29e0, 0x29e1, 0x29e1, 0x29e2, 0x29e2,
+ 0x29e3, 0x29e4, 0x29e5, 0x29e5, 0x29e6, 0x29e7, 0x29e8, 0x29e9,
+ 0x29ea, 0x29eb, 0x29ec, 0x29ee, 0x29ef, 0x29f0, 0x29f1, 0x29f3,
+ 0x29f4, 0x29f5, 0x29f7, 0x29f8, 0x29fa, 0x29fb, 0x29fd, 0x29ff,
+ 0x2a00, 0x2a00, 0x2a00, 0x2a00, 0x2a01, 0x2a01, 0x2a02, 0x2a02,
+ 0x2a03, 0x2a04, 0x2a05, 0x2a05, 0x2a06, 0x2a07, 0x2a08, 0x2a09,
+ 0x2a0a, 0x2a0b, 0x2a0c, 0x2a0e, 0x2a0f, 0x2a10, 0x2a11, 0x2a13,
+ 0x2a14, 0x2a15, 0x2a17, 0x2a18, 0x2a1a, 0x2a1b, 0x2a1d, 0x2a1f,
+ 0x2a20, 0x2a20, 0x2a20, 0x2a20, 0x2a21, 0x2a21, 0x2a22, 0x2a22,
+ 0x2a23, 0x2a24, 0x2a25, 0x2a25, 0x2a26, 0x2a27, 0x2a28, 0x2a29,
+ 0x2a2a, 0x2a2b, 0x2a2c, 0x2a2e, 0x2a2f, 0x2a30, 0x2a31, 0x2a33,
+ 0x2a34, 0x2a35, 0x2a37, 0x2a38, 0x2a3a, 0x2a3b, 0x2a3d, 0x2a3f,
+ 0x2a40, 0x2a40, 0x2a40, 0x2a40, 0x2a41, 0x2a41, 0x2a42, 0x2a42,
+ 0x2a43, 0x2a44, 0x2a45, 0x2a45, 0x2a46, 0x2a47, 0x2a48, 0x2a49,
+ 0x2a4a, 0x2a4b, 0x2a4c, 0x2a4e, 0x2a4f, 0x2a50, 0x2a51, 0x2a53,
+ 0x2a54, 0x2a55, 0x2a57, 0x2a58, 0x2a5a, 0x2a5b, 0x2a5d, 0x2a5f,
+ 0x2a60, 0x2a60, 0x2a60, 0x2a60, 0x2a61, 0x2a61, 0x2a62, 0x2a62,
+ 0x2a63, 0x2a64, 0x2a65, 0x2a65, 0x2a66, 0x2a67, 0x2a68, 0x2a69,
+ 0x2a6a, 0x2a6b, 0x2a6c, 0x2a6e, 0x2a6f, 0x2a70, 0x2a71, 0x2a73,
+ 0x2a74, 0x2a75, 0x2a77, 0x2a78, 0x2a7a, 0x2a7b, 0x2a7d, 0x2a7f,
+ 0x2a80, 0x2a80, 0x2a80, 0x2a80, 0x2a81, 0x2a81, 0x2a82, 0x2a82,
+ 0x2a83, 0x2a84, 0x2a85, 0x2a85, 0x2a86, 0x2a87, 0x2a88, 0x2a89,
+ 0x2a8a, 0x2a8b, 0x2a8c, 0x2a8e, 0x2a8f, 0x2a90, 0x2a91, 0x2a93,
+ 0x2a94, 0x2a95, 0x2a97, 0x2a98, 0x2a9a, 0x2a9b, 0x2a9d, 0x2a9f,
+ 0x2aa0, 0x2aa0, 0x2aa0, 0x2aa0, 0x2aa1, 0x2aa1, 0x2aa2, 0x2aa2,
+ 0x2aa3, 0x2aa4, 0x2aa5, 0x2aa5, 0x2aa6, 0x2aa7, 0x2aa8, 0x2aa9,
+ 0x2aaa, 0x2aab, 0x2aac, 0x2aae, 0x2aaf, 0x2ab0, 0x2ab1, 0x2ab3,
+ 0x2ab4, 0x2ab5, 0x2ab7, 0x2ab8, 0x2aba, 0x2abb, 0x2abd, 0x2abf,
+ 0x2ac0, 0x2ac0, 0x2ac0, 0x2ac0, 0x2ac1, 0x2ac1, 0x2ac2, 0x2ac2,
+ 0x2ac3, 0x2ac4, 0x2ac5, 0x2ac5, 0x2ac6, 0x2ac7, 0x2ac8, 0x2ac9,
+ 0x2aca, 0x2acb, 0x2acc, 0x2ace, 0x2acf, 0x2ad0, 0x2ad1, 0x2ad3,
+ 0x2ad4, 0x2ad5, 0x2ad7, 0x2ad8, 0x2ada, 0x2adb, 0x2add, 0x2adf,
+ 0x2ae0, 0x2ae0, 0x2ae0, 0x2ae0, 0x2ae1, 0x2ae1, 0x2ae2, 0x2ae2,
+ 0x2ae3, 0x2ae4, 0x2ae5, 0x2ae5, 0x2ae6, 0x2ae7, 0x2ae8, 0x2ae9,
+ 0x2aea, 0x2aeb, 0x2aec, 0x2aee, 0x2aef, 0x2af0, 0x2af1, 0x2af3,
+ 0x2af4, 0x2af5, 0x2af7, 0x2af8, 0x2afa, 0x2afb, 0x2afd, 0x2aff,
+ 0x2b00, 0x2b00, 0x2b00, 0x2b00, 0x2b01, 0x2b01, 0x2b02, 0x2b02,
+ 0x2b03, 0x2b04, 0x2b05, 0x2b05, 0x2b06, 0x2b07, 0x2b08, 0x2b09,
+ 0x2b0a, 0x2b0b, 0x2b0c, 0x2b0e, 0x2b0f, 0x2b10, 0x2b11, 0x2b13,
+ 0x2b14, 0x2b15, 0x2b17, 0x2b18, 0x2b1a, 0x2b1b, 0x2b1d, 0x2b1f,
+ 0x2b20, 0x2b20, 0x2b20, 0x2b20, 0x2b21, 0x2b21, 0x2b22, 0x2b22,
+ 0x2b23, 0x2b24, 0x2b25, 0x2b25, 0x2b26, 0x2b27, 0x2b28, 0x2b29,
+ 0x2b2a, 0x2b2b, 0x2b2c, 0x2b2e, 0x2b2f, 0x2b30, 0x2b31, 0x2b33,
+ 0x2b34, 0x2b35, 0x2b37, 0x2b38, 0x2b3a, 0x2b3b, 0x2b3d, 0x2b3f,
+ 0x2b40, 0x2b40, 0x2b40, 0x2b40, 0x2b41, 0x2b41, 0x2b42, 0x2b42,
+ 0x2b43, 0x2b44, 0x2b45, 0x2b45, 0x2b46, 0x2b47, 0x2b48, 0x2b49,
+ 0x2b4a, 0x2b4b, 0x2b4c, 0x2b4e, 0x2b4f, 0x2b50, 0x2b51, 0x2b53,
+ 0x2b54, 0x2b55, 0x2b57, 0x2b58, 0x2b5a, 0x2b5b, 0x2b5d, 0x2b5f,
+ 0x2b80, 0x2b80, 0x2b80, 0x2b80, 0x2b81, 0x2b81, 0x2b82, 0x2b82,
+ 0x2b83, 0x2b84, 0x2b85, 0x2b85, 0x2b86, 0x2b87, 0x2b88, 0x2b89,
+ 0x2b8a, 0x2b8b, 0x2b8c, 0x2b8e, 0x2b8f, 0x2b90, 0x2b91, 0x2b93,
+ 0x2b94, 0x2b95, 0x2b97, 0x2b98, 0x2b9a, 0x2b9b, 0x2b9d, 0x2b9f,
+ 0x2ba0, 0x2ba0, 0x2ba0, 0x2ba0, 0x2ba1, 0x2ba1, 0x2ba2, 0x2ba2,
+ 0x2ba3, 0x2ba4, 0x2ba5, 0x2ba5, 0x2ba6, 0x2ba7, 0x2ba8, 0x2ba9,
+ 0x2baa, 0x2bab, 0x2bac, 0x2bae, 0x2baf, 0x2bb0, 0x2bb1, 0x2bb3,
+ 0x2bb4, 0x2bb5, 0x2bb7, 0x2bb8, 0x2bba, 0x2bbb, 0x2bbd, 0x2bbf,
+ 0x2bc0, 0x2bc0, 0x2bc0, 0x2bc0, 0x2bc1, 0x2bc1, 0x2bc2, 0x2bc2,
+ 0x2bc3, 0x2bc4, 0x2bc5, 0x2bc5, 0x2bc6, 0x2bc7, 0x2bc8, 0x2bc9,
+ 0x2bca, 0x2bcb, 0x2bcc, 0x2bce, 0x2bcf, 0x2bd0, 0x2bd1, 0x2bd3,
+ 0x2bd4, 0x2bd5, 0x2bd7, 0x2bd8, 0x2bda, 0x2bdb, 0x2bdd, 0x2bdf,
+ 0x2be0, 0x2be0, 0x2be0, 0x2be0, 0x2be1, 0x2be1, 0x2be2, 0x2be2,
+ 0x2be3, 0x2be4, 0x2be5, 0x2be5, 0x2be6, 0x2be7, 0x2be8, 0x2be9,
+ 0x2bea, 0x2beb, 0x2bec, 0x2bee, 0x2bef, 0x2bf0, 0x2bf1, 0x2bf3,
+ 0x2bf4, 0x2bf5, 0x2bf7, 0x2bf8, 0x2bfa, 0x2bfb, 0x2bfd, 0x2bff,
+ 0x2c00, 0x2c00, 0x2c00, 0x2c00, 0x2c01, 0x2c01, 0x2c02, 0x2c02,
+ 0x2c03, 0x2c04, 0x2c05, 0x2c05, 0x2c06, 0x2c07, 0x2c08, 0x2c09,
+ 0x2c0a, 0x2c0b, 0x2c0c, 0x2c0e, 0x2c0f, 0x2c10, 0x2c11, 0x2c13,
+ 0x2c14, 0x2c15, 0x2c17, 0x2c18, 0x2c1a, 0x2c1b, 0x2c1d, 0x2c1f,
+ 0x2c40, 0x2c40, 0x2c40, 0x2c40, 0x2c41, 0x2c41, 0x2c42, 0x2c42,
+ 0x2c43, 0x2c44, 0x2c45, 0x2c45, 0x2c46, 0x2c47, 0x2c48, 0x2c49,
+ 0x2c4a, 0x2c4b, 0x2c4c, 0x2c4e, 0x2c4f, 0x2c50, 0x2c51, 0x2c53,
+ 0x2c54, 0x2c55, 0x2c57, 0x2c58, 0x2c5a, 0x2c5b, 0x2c5d, 0x2c5f,
+ 0x2c60, 0x2c60, 0x2c60, 0x2c60, 0x2c61, 0x2c61, 0x2c62, 0x2c62,
+ 0x2c63, 0x2c64, 0x2c65, 0x2c65, 0x2c66, 0x2c67, 0x2c68, 0x2c69,
+ 0x2c6a, 0x2c6b, 0x2c6c, 0x2c6e, 0x2c6f, 0x2c70, 0x2c71, 0x2c73,
+ 0x2c74, 0x2c75, 0x2c77, 0x2c78, 0x2c7a, 0x2c7b, 0x2c7d, 0x2c7f,
+ 0x2c80, 0x2c80, 0x2c80, 0x2c80, 0x2c81, 0x2c81, 0x2c82, 0x2c82,
+ 0x2c83, 0x2c84, 0x2c85, 0x2c85, 0x2c86, 0x2c87, 0x2c88, 0x2c89,
+ 0x2c8a, 0x2c8b, 0x2c8c, 0x2c8e, 0x2c8f, 0x2c90, 0x2c91, 0x2c93,
+ 0x2c94, 0x2c95, 0x2c97, 0x2c98, 0x2c9a, 0x2c9b, 0x2c9d, 0x2c9f,
+ 0x2cc0, 0x2cc0, 0x2cc0, 0x2cc0, 0x2cc1, 0x2cc1, 0x2cc2, 0x2cc2,
+ 0x2cc3, 0x2cc4, 0x2cc5, 0x2cc5, 0x2cc6, 0x2cc7, 0x2cc8, 0x2cc9,
+ 0x2cca, 0x2ccb, 0x2ccc, 0x2cce, 0x2ccf, 0x2cd0, 0x2cd1, 0x2cd3,
+ 0x2cd4, 0x2cd5, 0x2cd7, 0x2cd8, 0x2cda, 0x2cdb, 0x2cdd, 0x2cdf,
+ 0x2ce0, 0x2ce0, 0x2ce0, 0x2ce0, 0x2ce1, 0x2ce1, 0x2ce2, 0x2ce2,
+ 0x2ce3, 0x2ce4, 0x2ce5, 0x2ce5, 0x2ce6, 0x2ce7, 0x2ce8, 0x2ce9,
+ 0x2cea, 0x2ceb, 0x2cec, 0x2cee, 0x2cef, 0x2cf0, 0x2cf1, 0x2cf3,
+ 0x2cf4, 0x2cf5, 0x2cf7, 0x2cf8, 0x2cfa, 0x2cfb, 0x2cfd, 0x2cff,
+ 0x2d00, 0x2d00, 0x2d00, 0x2d00, 0x2d01, 0x2d01, 0x2d02, 0x2d02,
+ 0x2d03, 0x2d04, 0x2d05, 0x2d05, 0x2d06, 0x2d07, 0x2d08, 0x2d09,
+ 0x2d0a, 0x2d0b, 0x2d0c, 0x2d0e, 0x2d0f, 0x2d10, 0x2d11, 0x2d13,
+ 0x2d14, 0x2d15, 0x2d17, 0x2d18, 0x2d1a, 0x2d1b, 0x2d1d, 0x2d1f,
+ 0x2d40, 0x2d40, 0x2d40, 0x2d40, 0x2d41, 0x2d41, 0x2d42, 0x2d42,
+ 0x2d43, 0x2d44, 0x2d45, 0x2d45, 0x2d46, 0x2d47, 0x2d48, 0x2d49,
+ 0x2d4a, 0x2d4b, 0x2d4c, 0x2d4e, 0x2d4f, 0x2d50, 0x2d51, 0x2d53,
+ 0x2d54, 0x2d55, 0x2d57, 0x2d58, 0x2d5a, 0x2d5b, 0x2d5d, 0x2d5f,
+ 0x2d60, 0x2d60, 0x2d60, 0x2d60, 0x2d61, 0x2d61, 0x2d62, 0x2d62,
+ 0x2d63, 0x2d64, 0x2d65, 0x2d65, 0x2d66, 0x2d67, 0x2d68, 0x2d69,
+ 0x2d6a, 0x2d6b, 0x2d6c, 0x2d6e, 0x2d6f, 0x2d70, 0x2d71, 0x2d73,
+ 0x2d74, 0x2d75, 0x2d77, 0x2d78, 0x2d7a, 0x2d7b, 0x2d7d, 0x2d7f,
+ 0x2d80, 0x2d80, 0x2d80, 0x2d80, 0x2d81, 0x2d81, 0x2d82, 0x2d82,
+ 0x2d83, 0x2d84, 0x2d85, 0x2d85, 0x2d86, 0x2d87, 0x2d88, 0x2d89,
+ 0x2d8a, 0x2d8b, 0x2d8c, 0x2d8e, 0x2d8f, 0x2d90, 0x2d91, 0x2d93,
+ 0x2d94, 0x2d95, 0x2d97, 0x2d98, 0x2d9a, 0x2d9b, 0x2d9d, 0x2d9f,
+ 0x2dc0, 0x2dc0, 0x2dc0, 0x2dc0, 0x2dc1, 0x2dc1, 0x2dc2, 0x2dc2,
+ 0x2dc3, 0x2dc4, 0x2dc5, 0x2dc5, 0x2dc6, 0x2dc7, 0x2dc8, 0x2dc9,
+ 0x2dca, 0x2dcb, 0x2dcc, 0x2dce, 0x2dcf, 0x2dd0, 0x2dd1, 0x2dd3,
+ 0x2dd4, 0x2dd5, 0x2dd7, 0x2dd8, 0x2dda, 0x2ddb, 0x2ddd, 0x2ddf,
+ 0x2de0, 0x2de0, 0x2de0, 0x2de0, 0x2de1, 0x2de1, 0x2de2, 0x2de2,
+ 0x2de3, 0x2de4, 0x2de5, 0x2de5, 0x2de6, 0x2de7, 0x2de8, 0x2de9,
+ 0x2dea, 0x2deb, 0x2dec, 0x2dee, 0x2def, 0x2df0, 0x2df1, 0x2df3,
+ 0x2df4, 0x2df5, 0x2df7, 0x2df8, 0x2dfa, 0x2dfb, 0x2dfd, 0x2dff,
+ 0x2e20, 0x2e20, 0x2e20, 0x2e20, 0x2e21, 0x2e21, 0x2e22, 0x2e22,
+ 0x2e23, 0x2e24, 0x2e25, 0x2e25, 0x2e26, 0x2e27, 0x2e28, 0x2e29,
+ 0x2e2a, 0x2e2b, 0x2e2c, 0x2e2e, 0x2e2f, 0x2e30, 0x2e31, 0x2e33,
+ 0x2e34, 0x2e35, 0x2e37, 0x2e38, 0x2e3a, 0x2e3b, 0x2e3d, 0x2e3f,
+ 0x2e40, 0x2e40, 0x2e40, 0x2e40, 0x2e41, 0x2e41, 0x2e42, 0x2e42,
+ 0x2e43, 0x2e44, 0x2e45, 0x2e45, 0x2e46, 0x2e47, 0x2e48, 0x2e49,
+ 0x2e4a, 0x2e4b, 0x2e4c, 0x2e4e, 0x2e4f, 0x2e50, 0x2e51, 0x2e53,
+ 0x2e54, 0x2e55, 0x2e57, 0x2e58, 0x2e5a, 0x2e5b, 0x2e5d, 0x2e5f,
+ 0x2e80, 0x2e80, 0x2e80, 0x2e80, 0x2e81, 0x2e81, 0x2e82, 0x2e82,
+ 0x2e83, 0x2e84, 0x2e85, 0x2e85, 0x2e86, 0x2e87, 0x2e88, 0x2e89,
+ 0x2e8a, 0x2e8b, 0x2e8c, 0x2e8e, 0x2e8f, 0x2e90, 0x2e91, 0x2e93,
+ 0x2e94, 0x2e95, 0x2e97, 0x2e98, 0x2e9a, 0x2e9b, 0x2e9d, 0x2e9f,
+ 0x2ea0, 0x2ea0, 0x2ea0, 0x2ea0, 0x2ea1, 0x2ea1, 0x2ea2, 0x2ea2,
+ 0x2ea3, 0x2ea4, 0x2ea5, 0x2ea5, 0x2ea6, 0x2ea7, 0x2ea8, 0x2ea9,
+ 0x2eaa, 0x2eab, 0x2eac, 0x2eae, 0x2eaf, 0x2eb0, 0x2eb1, 0x2eb3,
+ 0x2eb4, 0x2eb5, 0x2eb7, 0x2eb8, 0x2eba, 0x2ebb, 0x2ebd, 0x2ebf,
+ 0x2ee0, 0x2ee0, 0x2ee0, 0x2ee0, 0x2ee1, 0x2ee1, 0x2ee2, 0x2ee2,
+ 0x2ee3, 0x2ee4, 0x2ee5, 0x2ee5, 0x2ee6, 0x2ee7, 0x2ee8, 0x2ee9,
+ 0x2eea, 0x2eeb, 0x2eec, 0x2eee, 0x2eef, 0x2ef0, 0x2ef1, 0x2ef3,
+ 0x2ef4, 0x2ef5, 0x2ef7, 0x2ef8, 0x2efa, 0x2efb, 0x2efd, 0x2eff,
+ 0x2f00, 0x2f00, 0x2f00, 0x2f00, 0x2f01, 0x2f01, 0x2f02, 0x2f02,
+ 0x2f03, 0x2f04, 0x2f05, 0x2f05, 0x2f06, 0x2f07, 0x2f08, 0x2f09,
+ 0x2f0a, 0x2f0b, 0x2f0c, 0x2f0e, 0x2f0f, 0x2f10, 0x2f11, 0x2f13,
+ 0x2f14, 0x2f15, 0x2f17, 0x2f18, 0x2f1a, 0x2f1b, 0x2f1d, 0x2f1f,
+ 0x2f40, 0x2f40, 0x2f40, 0x2f40, 0x2f41, 0x2f41, 0x2f42, 0x2f42,
+ 0x2f43, 0x2f44, 0x2f45, 0x2f45, 0x2f46, 0x2f47, 0x2f48, 0x2f49,
+ 0x2f4a, 0x2f4b, 0x2f4c, 0x2f4e, 0x2f4f, 0x2f50, 0x2f51, 0x2f53,
+ 0x2f54, 0x2f55, 0x2f57, 0x2f58, 0x2f5a, 0x2f5b, 0x2f5d, 0x2f5f,
+ 0x2f60, 0x2f60, 0x2f60, 0x2f60, 0x2f61, 0x2f61, 0x2f62, 0x2f62,
+ 0x2f63, 0x2f64, 0x2f65, 0x2f65, 0x2f66, 0x2f67, 0x2f68, 0x2f69,
+ 0x2f6a, 0x2f6b, 0x2f6c, 0x2f6e, 0x2f6f, 0x2f70, 0x2f71, 0x2f73,
+ 0x2f74, 0x2f75, 0x2f77, 0x2f78, 0x2f7a, 0x2f7b, 0x2f7d, 0x2f7f,
+ 0x2fa0, 0x2fa0, 0x2fa0, 0x2fa0, 0x2fa1, 0x2fa1, 0x2fa2, 0x2fa2,
+ 0x2fa3, 0x2fa4, 0x2fa5, 0x2fa5, 0x2fa6, 0x2fa7, 0x2fa8, 0x2fa9,
+ 0x2faa, 0x2fab, 0x2fac, 0x2fae, 0x2faf, 0x2fb0, 0x2fb1, 0x2fb3,
+ 0x2fb4, 0x2fb5, 0x2fb7, 0x2fb8, 0x2fba, 0x2fbb, 0x2fbd, 0x2fbf,
+ 0x2fe0, 0x2fe0, 0x2fe0, 0x2fe0, 0x2fe1, 0x2fe1, 0x2fe2, 0x2fe2,
+ 0x2fe3, 0x2fe4, 0x2fe5, 0x2fe5, 0x2fe6, 0x2fe7, 0x2fe8, 0x2fe9,
+ 0x2fea, 0x2feb, 0x2fec, 0x2fee, 0x2fef, 0x2ff0, 0x2ff1, 0x2ff3,
+ 0x2ff4, 0x2ff5, 0x2ff7, 0x2ff8, 0x2ffa, 0x2ffb, 0x2ffd, 0x2fff,
+ 0x2800, 0x2800, 0x2800, 0x2800, 0x2801, 0x2801, 0x2802, 0x2802,
+ 0x2803, 0x2804, 0x2805, 0x2805, 0x2806, 0x2807, 0x2808, 0x2809,
+ 0x280a, 0x280b, 0x280c, 0x280e, 0x280f, 0x2810, 0x2811, 0x2813,
+ 0x2814, 0x2815, 0x2817, 0x2818, 0x281a, 0x281b, 0x281d, 0x281f,
+ 0x2800, 0x2800, 0x2800, 0x2800, 0x2801, 0x2801, 0x2802, 0x2802,
+ 0x2803, 0x2804, 0x2805, 0x2805, 0x2806, 0x2807, 0x2808, 0x2809,
+ 0x280a, 0x280b, 0x280c, 0x280e, 0x280f, 0x2810, 0x2811, 0x2813,
+ 0x2814, 0x2815, 0x2817, 0x2818, 0x281a, 0x281b, 0x281d, 0x281f,
+ 0x2800, 0x2800, 0x2800, 0x2800, 0x2801, 0x2801, 0x2802, 0x2802,
+ 0x2803, 0x2804, 0x2805, 0x2805, 0x2806, 0x2807, 0x2808, 0x2809,
+ 0x280a, 0x280b, 0x280c, 0x280e, 0x280f, 0x2810, 0x2811, 0x2813,
+ 0x2814, 0x2815, 0x2817, 0x2818, 0x281a, 0x281b, 0x281d, 0x281f,
+ 0x2800, 0x2800, 0x2800, 0x2800, 0x2801, 0x2801, 0x2802, 0x2802,
+ 0x2803, 0x2804, 0x2805, 0x2805, 0x2806, 0x2807, 0x2808, 0x2809,
+ 0x280a, 0x280b, 0x280c, 0x280e, 0x280f, 0x2810, 0x2811, 0x2813,
+ 0x2814, 0x2815, 0x2817, 0x2818, 0x281a, 0x281b, 0x281d, 0x281f,
+ 0x2800, 0x2800, 0x2800, 0x2800, 0x2801, 0x2801, 0x2802, 0x2802,
+ 0x2803, 0x2804, 0x2805, 0x2805, 0x2806, 0x2807, 0x2808, 0x2809,
+ 0x280a, 0x280b, 0x280c, 0x280e, 0x280f, 0x2810, 0x2811, 0x2813,
+ 0x2814, 0x2815, 0x2817, 0x2818, 0x281a, 0x281b, 0x281d, 0x281f,
+ 0x2820, 0x2820, 0x2820, 0x2820, 0x2821, 0x2821, 0x2822, 0x2822,
+ 0x2823, 0x2824, 0x2825, 0x2825, 0x2826, 0x2827, 0x2828, 0x2829,
+ 0x282a, 0x282b, 0x282c, 0x282e, 0x282f, 0x2830, 0x2831, 0x2833,
+ 0x2834, 0x2835, 0x2837, 0x2838, 0x283a, 0x283b, 0x283d, 0x283f,
+ 0x2820, 0x2820, 0x2820, 0x2820, 0x2821, 0x2821, 0x2822, 0x2822,
+ 0x2823, 0x2824, 0x2825, 0x2825, 0x2826, 0x2827, 0x2828, 0x2829,
+ 0x282a, 0x282b, 0x282c, 0x282e, 0x282f, 0x2830, 0x2831, 0x2833,
+ 0x2834, 0x2835, 0x2837, 0x2838, 0x283a, 0x283b, 0x283d, 0x283f,
+ 0x2820, 0x2820, 0x2820, 0x2820, 0x2821, 0x2821, 0x2822, 0x2822,
+ 0x2823, 0x2824, 0x2825, 0x2825, 0x2826, 0x2827, 0x2828, 0x2829,
+ 0x282a, 0x282b, 0x282c, 0x282e, 0x282f, 0x2830, 0x2831, 0x2833,
+ 0x2834, 0x2835, 0x2837, 0x2838, 0x283a, 0x283b, 0x283d, 0x283f,
+ 0x2840, 0x2840, 0x2840, 0x2840, 0x2841, 0x2841, 0x2842, 0x2842,
+ 0x2843, 0x2844, 0x2845, 0x2845, 0x2846, 0x2847, 0x2848, 0x2849,
+ 0x284a, 0x284b, 0x284c, 0x284e, 0x284f, 0x2850, 0x2851, 0x2853,
+ 0x2854, 0x2855, 0x2857, 0x2858, 0x285a, 0x285b, 0x285d, 0x285f,
+ 0x2840, 0x2840, 0x2840, 0x2840, 0x2841, 0x2841, 0x2842, 0x2842,
+ 0x2843, 0x2844, 0x2845, 0x2845, 0x2846, 0x2847, 0x2848, 0x2849,
+ 0x284a, 0x284b, 0x284c, 0x284e, 0x284f, 0x2850, 0x2851, 0x2853,
+ 0x2854, 0x2855, 0x2857, 0x2858, 0x285a, 0x285b, 0x285d, 0x285f,
+ 0x2860, 0x2860, 0x2860, 0x2860, 0x2861, 0x2861, 0x2862, 0x2862,
+ 0x2863, 0x2864, 0x2865, 0x2865, 0x2866, 0x2867, 0x2868, 0x2869,
+ 0x286a, 0x286b, 0x286c, 0x286e, 0x286f, 0x2870, 0x2871, 0x2873,
+ 0x2874, 0x2875, 0x2877, 0x2878, 0x287a, 0x287b, 0x287d, 0x287f,
+ 0x2860, 0x2860, 0x2860, 0x2860, 0x2861, 0x2861, 0x2862, 0x2862,
+ 0x2863, 0x2864, 0x2865, 0x2865, 0x2866, 0x2867, 0x2868, 0x2869,
+ 0x286a, 0x286b, 0x286c, 0x286e, 0x286f, 0x2870, 0x2871, 0x2873,
+ 0x2874, 0x2875, 0x2877, 0x2878, 0x287a, 0x287b, 0x287d, 0x287f,
+ 0x2880, 0x2880, 0x2880, 0x2880, 0x2881, 0x2881, 0x2882, 0x2882,
+ 0x2883, 0x2884, 0x2885, 0x2885, 0x2886, 0x2887, 0x2888, 0x2889,
+ 0x288a, 0x288b, 0x288c, 0x288e, 0x288f, 0x2890, 0x2891, 0x2893,
+ 0x2894, 0x2895, 0x2897, 0x2898, 0x289a, 0x289b, 0x289d, 0x289f,
+ 0x28a0, 0x28a0, 0x28a0, 0x28a0, 0x28a1, 0x28a1, 0x28a2, 0x28a2,
+ 0x28a3, 0x28a4, 0x28a5, 0x28a5, 0x28a6, 0x28a7, 0x28a8, 0x28a9,
+ 0x28aa, 0x28ab, 0x28ac, 0x28ae, 0x28af, 0x28b0, 0x28b1, 0x28b3,
+ 0x28b4, 0x28b5, 0x28b7, 0x28b8, 0x28ba, 0x28bb, 0x28bd, 0x28bf,
+ 0x28a0, 0x28a0, 0x28a0, 0x28a0, 0x28a1, 0x28a1, 0x28a2, 0x28a2,
+ 0x28a3, 0x28a4, 0x28a5, 0x28a5, 0x28a6, 0x28a7, 0x28a8, 0x28a9,
+ 0x28aa, 0x28ab, 0x28ac, 0x28ae, 0x28af, 0x28b0, 0x28b1, 0x28b3,
+ 0x28b4, 0x28b5, 0x28b7, 0x28b8, 0x28ba, 0x28bb, 0x28bd, 0x28bf,
+ 0x28c0, 0x28c0, 0x28c0, 0x28c0, 0x28c1, 0x28c1, 0x28c2, 0x28c2,
+ 0x28c3, 0x28c4, 0x28c5, 0x28c5, 0x28c6, 0x28c7, 0x28c8, 0x28c9,
+ 0x28ca, 0x28cb, 0x28cc, 0x28ce, 0x28cf, 0x28d0, 0x28d1, 0x28d3,
+ 0x28d4, 0x28d5, 0x28d7, 0x28d8, 0x28da, 0x28db, 0x28dd, 0x28df,
+ 0x28e0, 0x28e0, 0x28e0, 0x28e0, 0x28e1, 0x28e1, 0x28e2, 0x28e2,
+ 0x28e3, 0x28e4, 0x28e5, 0x28e5, 0x28e6, 0x28e7, 0x28e8, 0x28e9,
+ 0x28ea, 0x28eb, 0x28ec, 0x28ee, 0x28ef, 0x28f0, 0x28f1, 0x28f3,
+ 0x28f4, 0x28f5, 0x28f7, 0x28f8, 0x28fa, 0x28fb, 0x28fd, 0x28ff,
+ 0x28e0, 0x28e0, 0x28e0, 0x28e0, 0x28e1, 0x28e1, 0x28e2, 0x28e2,
+ 0x28e3, 0x28e4, 0x28e5, 0x28e5, 0x28e6, 0x28e7, 0x28e8, 0x28e9,
+ 0x28ea, 0x28eb, 0x28ec, 0x28ee, 0x28ef, 0x28f0, 0x28f1, 0x28f3,
+ 0x28f4, 0x28f5, 0x28f7, 0x28f8, 0x28fa, 0x28fb, 0x28fd, 0x28ff,
+ 0x2900, 0x2900, 0x2900, 0x2900, 0x2901, 0x2901, 0x2902, 0x2902,
+ 0x2903, 0x2904, 0x2905, 0x2905, 0x2906, 0x2907, 0x2908, 0x2909,
+ 0x290a, 0x290b, 0x290c, 0x290e, 0x290f, 0x2910, 0x2911, 0x2913,
+ 0x2914, 0x2915, 0x2917, 0x2918, 0x291a, 0x291b, 0x291d, 0x291f,
+ 0x2920, 0x2920, 0x2920, 0x2920, 0x2921, 0x2921, 0x2922, 0x2922,
+ 0x2923, 0x2924, 0x2925, 0x2925, 0x2926, 0x2927, 0x2928, 0x2929,
+ 0x292a, 0x292b, 0x292c, 0x292e, 0x292f, 0x2930, 0x2931, 0x2933,
+ 0x2934, 0x2935, 0x2937, 0x2938, 0x293a, 0x293b, 0x293d, 0x293f,
+ 0x2940, 0x2940, 0x2940, 0x2940, 0x2941, 0x2941, 0x2942, 0x2942,
+ 0x2943, 0x2944, 0x2945, 0x2945, 0x2946, 0x2947, 0x2948, 0x2949,
+ 0x294a, 0x294b, 0x294c, 0x294e, 0x294f, 0x2950, 0x2951, 0x2953,
+ 0x2954, 0x2955, 0x2957, 0x2958, 0x295a, 0x295b, 0x295d, 0x295f,
+ 0x2940, 0x2940, 0x2940, 0x2940, 0x2941, 0x2941, 0x2942, 0x2942,
+ 0x2943, 0x2944, 0x2945, 0x2945, 0x2946, 0x2947, 0x2948, 0x2949,
+ 0x294a, 0x294b, 0x294c, 0x294e, 0x294f, 0x2950, 0x2951, 0x2953,
+ 0x2954, 0x2955, 0x2957, 0x2958, 0x295a, 0x295b, 0x295d, 0x295f,
+ 0x2960, 0x2960, 0x2960, 0x2960, 0x2961, 0x2961, 0x2962, 0x2962,
+ 0x2963, 0x2964, 0x2965, 0x2965, 0x2966, 0x2967, 0x2968, 0x2969,
+ 0x296a, 0x296b, 0x296c, 0x296e, 0x296f, 0x2970, 0x2971, 0x2973,
+ 0x2974, 0x2975, 0x2977, 0x2978, 0x297a, 0x297b, 0x297d, 0x297f,
+ 0x2980, 0x2980, 0x2980, 0x2980, 0x2981, 0x2981, 0x2982, 0x2982,
+ 0x2983, 0x2984, 0x2985, 0x2985, 0x2986, 0x2987, 0x2988, 0x2989,
+ 0x298a, 0x298b, 0x298c, 0x298e, 0x298f, 0x2990, 0x2991, 0x2993,
+ 0x2994, 0x2995, 0x2997, 0x2998, 0x299a, 0x299b, 0x299d, 0x299f,
+ 0x29a0, 0x29a0, 0x29a0, 0x29a0, 0x29a1, 0x29a1, 0x29a2, 0x29a2,
+ 0x29a3, 0x29a4, 0x29a5, 0x29a5, 0x29a6, 0x29a7, 0x29a8, 0x29a9,
+ 0x29aa, 0x29ab, 0x29ac, 0x29ae, 0x29af, 0x29b0, 0x29b1, 0x29b3,
+ 0x29b4, 0x29b5, 0x29b7, 0x29b8, 0x29ba, 0x29bb, 0x29bd, 0x29bf,
+ 0x29c0, 0x29c0, 0x29c0, 0x29c0, 0x29c1, 0x29c1, 0x29c2, 0x29c2,
+ 0x29c3, 0x29c4, 0x29c5, 0x29c5, 0x29c6, 0x29c7, 0x29c8, 0x29c9,
+ 0x29ca, 0x29cb, 0x29cc, 0x29ce, 0x29cf, 0x29d0, 0x29d1, 0x29d3,
+ 0x29d4, 0x29d5, 0x29d7, 0x29d8, 0x29da, 0x29db, 0x29dd, 0x29df,
+ 0x29e0, 0x29e0, 0x29e0, 0x29e0, 0x29e1, 0x29e1, 0x29e2, 0x29e2,
+ 0x29e3, 0x29e4, 0x29e5, 0x29e5, 0x29e6, 0x29e7, 0x29e8, 0x29e9,
+ 0x29ea, 0x29eb, 0x29ec, 0x29ee, 0x29ef, 0x29f0, 0x29f1, 0x29f3,
+ 0x29f4, 0x29f5, 0x29f7, 0x29f8, 0x29fa, 0x29fb, 0x29fd, 0x29ff,
+ 0x2a00, 0x2a00, 0x2a00, 0x2a00, 0x2a01, 0x2a01, 0x2a02, 0x2a02,
+ 0x2a03, 0x2a04, 0x2a05, 0x2a05, 0x2a06, 0x2a07, 0x2a08, 0x2a09,
+ 0x2a0a, 0x2a0b, 0x2a0c, 0x2a0e, 0x2a0f, 0x2a10, 0x2a11, 0x2a13,
+ 0x2a14, 0x2a15, 0x2a17, 0x2a18, 0x2a1a, 0x2a1b, 0x2a1d, 0x2a1f,
+ 0x2a20, 0x2a20, 0x2a20, 0x2a20, 0x2a21, 0x2a21, 0x2a22, 0x2a22,
+ 0x2a23, 0x2a24, 0x2a25, 0x2a25, 0x2a26, 0x2a27, 0x2a28, 0x2a29,
+ 0x2a2a, 0x2a2b, 0x2a2c, 0x2a2e, 0x2a2f, 0x2a30, 0x2a31, 0x2a33,
+ 0x2a34, 0x2a35, 0x2a37, 0x2a38, 0x2a3a, 0x2a3b, 0x2a3d, 0x2a3f,
+ 0x2a40, 0x2a40, 0x2a40, 0x2a40, 0x2a41, 0x2a41, 0x2a42, 0x2a42,
+ 0x2a43, 0x2a44, 0x2a45, 0x2a45, 0x2a46, 0x2a47, 0x2a48, 0x2a49,
+ 0x2a4a, 0x2a4b, 0x2a4c, 0x2a4e, 0x2a4f, 0x2a50, 0x2a51, 0x2a53,
+ 0x2a54, 0x2a55, 0x2a57, 0x2a58, 0x2a5a, 0x2a5b, 0x2a5d, 0x2a5f,
+ 0x2a60, 0x2a60, 0x2a60, 0x2a60, 0x2a61, 0x2a61, 0x2a62, 0x2a62,
+ 0x2a63, 0x2a64, 0x2a65, 0x2a65, 0x2a66, 0x2a67, 0x2a68, 0x2a69,
+ 0x2a6a, 0x2a6b, 0x2a6c, 0x2a6e, 0x2a6f, 0x2a70, 0x2a71, 0x2a73,
+ 0x2a74, 0x2a75, 0x2a77, 0x2a78, 0x2a7a, 0x2a7b, 0x2a7d, 0x2a7f,
+ 0x2a80, 0x2a80, 0x2a80, 0x2a80, 0x2a81, 0x2a81, 0x2a82, 0x2a82,
+ 0x2a83, 0x2a84, 0x2a85, 0x2a85, 0x2a86, 0x2a87, 0x2a88, 0x2a89,
+ 0x2a8a, 0x2a8b, 0x2a8c, 0x2a8e, 0x2a8f, 0x2a90, 0x2a91, 0x2a93,
+ 0x2a94, 0x2a95, 0x2a97, 0x2a98, 0x2a9a, 0x2a9b, 0x2a9d, 0x2a9f,
+ 0x2aa0, 0x2aa0, 0x2aa0, 0x2aa0, 0x2aa1, 0x2aa1, 0x2aa2, 0x2aa2,
+ 0x2aa3, 0x2aa4, 0x2aa5, 0x2aa5, 0x2aa6, 0x2aa7, 0x2aa8, 0x2aa9,
+ 0x2aaa, 0x2aab, 0x2aac, 0x2aae, 0x2aaf, 0x2ab0, 0x2ab1, 0x2ab3,
+ 0x2ab4, 0x2ab5, 0x2ab7, 0x2ab8, 0x2aba, 0x2abb, 0x2abd, 0x2abf,
+ 0x2ac0, 0x2ac0, 0x2ac0, 0x2ac0, 0x2ac1, 0x2ac1, 0x2ac2, 0x2ac2,
+ 0x2ac3, 0x2ac4, 0x2ac5, 0x2ac5, 0x2ac6, 0x2ac7, 0x2ac8, 0x2ac9,
+ 0x2aca, 0x2acb, 0x2acc, 0x2ace, 0x2acf, 0x2ad0, 0x2ad1, 0x2ad3,
+ 0x2ad4, 0x2ad5, 0x2ad7, 0x2ad8, 0x2ada, 0x2adb, 0x2add, 0x2adf,
+ 0x2ae0, 0x2ae0, 0x2ae0, 0x2ae0, 0x2ae1, 0x2ae1, 0x2ae2, 0x2ae2,
+ 0x2ae3, 0x2ae4, 0x2ae5, 0x2ae5, 0x2ae6, 0x2ae7, 0x2ae8, 0x2ae9,
+ 0x2aea, 0x2aeb, 0x2aec, 0x2aee, 0x2aef, 0x2af0, 0x2af1, 0x2af3,
+ 0x2af4, 0x2af5, 0x2af7, 0x2af8, 0x2afa, 0x2afb, 0x2afd, 0x2aff,
+ 0x2b00, 0x2b00, 0x2b00, 0x2b00, 0x2b01, 0x2b01, 0x2b02, 0x2b02,
+ 0x2b03, 0x2b04, 0x2b05, 0x2b05, 0x2b06, 0x2b07, 0x2b08, 0x2b09,
+ 0x2b0a, 0x2b0b, 0x2b0c, 0x2b0e, 0x2b0f, 0x2b10, 0x2b11, 0x2b13,
+ 0x2b14, 0x2b15, 0x2b17, 0x2b18, 0x2b1a, 0x2b1b, 0x2b1d, 0x2b1f,
+ 0x2b20, 0x2b20, 0x2b20, 0x2b20, 0x2b21, 0x2b21, 0x2b22, 0x2b22,
+ 0x2b23, 0x2b24, 0x2b25, 0x2b25, 0x2b26, 0x2b27, 0x2b28, 0x2b29,
+ 0x2b2a, 0x2b2b, 0x2b2c, 0x2b2e, 0x2b2f, 0x2b30, 0x2b31, 0x2b33,
+ 0x2b34, 0x2b35, 0x2b37, 0x2b38, 0x2b3a, 0x2b3b, 0x2b3d, 0x2b3f,
+ 0x2b40, 0x2b40, 0x2b40, 0x2b40, 0x2b41, 0x2b41, 0x2b42, 0x2b42,
+ 0x2b43, 0x2b44, 0x2b45, 0x2b45, 0x2b46, 0x2b47, 0x2b48, 0x2b49,
+ 0x2b4a, 0x2b4b, 0x2b4c, 0x2b4e, 0x2b4f, 0x2b50, 0x2b51, 0x2b53,
+ 0x2b54, 0x2b55, 0x2b57, 0x2b58, 0x2b5a, 0x2b5b, 0x2b5d, 0x2b5f,
+ 0x2b80, 0x2b80, 0x2b80, 0x2b80, 0x2b81, 0x2b81, 0x2b82, 0x2b82,
+ 0x2b83, 0x2b84, 0x2b85, 0x2b85, 0x2b86, 0x2b87, 0x2b88, 0x2b89,
+ 0x2b8a, 0x2b8b, 0x2b8c, 0x2b8e, 0x2b8f, 0x2b90, 0x2b91, 0x2b93,
+ 0x2b94, 0x2b95, 0x2b97, 0x2b98, 0x2b9a, 0x2b9b, 0x2b9d, 0x2b9f,
+ 0x2ba0, 0x2ba0, 0x2ba0, 0x2ba0, 0x2ba1, 0x2ba1, 0x2ba2, 0x2ba2,
+ 0x2ba3, 0x2ba4, 0x2ba5, 0x2ba5, 0x2ba6, 0x2ba7, 0x2ba8, 0x2ba9,
+ 0x2baa, 0x2bab, 0x2bac, 0x2bae, 0x2baf, 0x2bb0, 0x2bb1, 0x2bb3,
+ 0x2bb4, 0x2bb5, 0x2bb7, 0x2bb8, 0x2bba, 0x2bbb, 0x2bbd, 0x2bbf,
+ 0x2bc0, 0x2bc0, 0x2bc0, 0x2bc0, 0x2bc1, 0x2bc1, 0x2bc2, 0x2bc2,
+ 0x2bc3, 0x2bc4, 0x2bc5, 0x2bc5, 0x2bc6, 0x2bc7, 0x2bc8, 0x2bc9,
+ 0x2bca, 0x2bcb, 0x2bcc, 0x2bce, 0x2bcf, 0x2bd0, 0x2bd1, 0x2bd3,
+ 0x2bd4, 0x2bd5, 0x2bd7, 0x2bd8, 0x2bda, 0x2bdb, 0x2bdd, 0x2bdf,
+ 0x2be0, 0x2be0, 0x2be0, 0x2be0, 0x2be1, 0x2be1, 0x2be2, 0x2be2,
+ 0x2be3, 0x2be4, 0x2be5, 0x2be5, 0x2be6, 0x2be7, 0x2be8, 0x2be9,
+ 0x2bea, 0x2beb, 0x2bec, 0x2bee, 0x2bef, 0x2bf0, 0x2bf1, 0x2bf3,
+ 0x2bf4, 0x2bf5, 0x2bf7, 0x2bf8, 0x2bfa, 0x2bfb, 0x2bfd, 0x2bff,
+ 0x2c00, 0x2c00, 0x2c00, 0x2c00, 0x2c01, 0x2c01, 0x2c02, 0x2c02,
+ 0x2c03, 0x2c04, 0x2c05, 0x2c05, 0x2c06, 0x2c07, 0x2c08, 0x2c09,
+ 0x2c0a, 0x2c0b, 0x2c0c, 0x2c0e, 0x2c0f, 0x2c10, 0x2c11, 0x2c13,
+ 0x2c14, 0x2c15, 0x2c17, 0x2c18, 0x2c1a, 0x2c1b, 0x2c1d, 0x2c1f,
+ 0x2c40, 0x2c40, 0x2c40, 0x2c40, 0x2c41, 0x2c41, 0x2c42, 0x2c42,
+ 0x2c43, 0x2c44, 0x2c45, 0x2c45, 0x2c46, 0x2c47, 0x2c48, 0x2c49,
+ 0x2c4a, 0x2c4b, 0x2c4c, 0x2c4e, 0x2c4f, 0x2c50, 0x2c51, 0x2c53,
+ 0x2c54, 0x2c55, 0x2c57, 0x2c58, 0x2c5a, 0x2c5b, 0x2c5d, 0x2c5f,
+ 0x2c60, 0x2c60, 0x2c60, 0x2c60, 0x2c61, 0x2c61, 0x2c62, 0x2c62,
+ 0x2c63, 0x2c64, 0x2c65, 0x2c65, 0x2c66, 0x2c67, 0x2c68, 0x2c69,
+ 0x2c6a, 0x2c6b, 0x2c6c, 0x2c6e, 0x2c6f, 0x2c70, 0x2c71, 0x2c73,
+ 0x2c74, 0x2c75, 0x2c77, 0x2c78, 0x2c7a, 0x2c7b, 0x2c7d, 0x2c7f,
+ 0x2c80, 0x2c80, 0x2c80, 0x2c80, 0x2c81, 0x2c81, 0x2c82, 0x2c82,
+ 0x2c83, 0x2c84, 0x2c85, 0x2c85, 0x2c86, 0x2c87, 0x2c88, 0x2c89,
+ 0x2c8a, 0x2c8b, 0x2c8c, 0x2c8e, 0x2c8f, 0x2c90, 0x2c91, 0x2c93,
+ 0x2c94, 0x2c95, 0x2c97, 0x2c98, 0x2c9a, 0x2c9b, 0x2c9d, 0x2c9f,
+ 0x2cc0, 0x2cc0, 0x2cc0, 0x2cc0, 0x2cc1, 0x2cc1, 0x2cc2, 0x2cc2,
+ 0x2cc3, 0x2cc4, 0x2cc5, 0x2cc5, 0x2cc6, 0x2cc7, 0x2cc8, 0x2cc9,
+ 0x2cca, 0x2ccb, 0x2ccc, 0x2cce, 0x2ccf, 0x2cd0, 0x2cd1, 0x2cd3,
+ 0x2cd4, 0x2cd5, 0x2cd7, 0x2cd8, 0x2cda, 0x2cdb, 0x2cdd, 0x2cdf,
+ 0x2ce0, 0x2ce0, 0x2ce0, 0x2ce0, 0x2ce1, 0x2ce1, 0x2ce2, 0x2ce2,
+ 0x2ce3, 0x2ce4, 0x2ce5, 0x2ce5, 0x2ce6, 0x2ce7, 0x2ce8, 0x2ce9,
+ 0x2cea, 0x2ceb, 0x2cec, 0x2cee, 0x2cef, 0x2cf0, 0x2cf1, 0x2cf3,
+ 0x2cf4, 0x2cf5, 0x2cf7, 0x2cf8, 0x2cfa, 0x2cfb, 0x2cfd, 0x2cff,
+ 0x2d00, 0x2d00, 0x2d00, 0x2d00, 0x2d01, 0x2d01, 0x2d02, 0x2d02,
+ 0x2d03, 0x2d04, 0x2d05, 0x2d05, 0x2d06, 0x2d07, 0x2d08, 0x2d09,
+ 0x2d0a, 0x2d0b, 0x2d0c, 0x2d0e, 0x2d0f, 0x2d10, 0x2d11, 0x2d13,
+ 0x2d14, 0x2d15, 0x2d17, 0x2d18, 0x2d1a, 0x2d1b, 0x2d1d, 0x2d1f,
+ 0x2d40, 0x2d40, 0x2d40, 0x2d40, 0x2d41, 0x2d41, 0x2d42, 0x2d42,
+ 0x2d43, 0x2d44, 0x2d45, 0x2d45, 0x2d46, 0x2d47, 0x2d48, 0x2d49,
+ 0x2d4a, 0x2d4b, 0x2d4c, 0x2d4e, 0x2d4f, 0x2d50, 0x2d51, 0x2d53,
+ 0x2d54, 0x2d55, 0x2d57, 0x2d58, 0x2d5a, 0x2d5b, 0x2d5d, 0x2d5f,
+ 0x2d60, 0x2d60, 0x2d60, 0x2d60, 0x2d61, 0x2d61, 0x2d62, 0x2d62,
+ 0x2d63, 0x2d64, 0x2d65, 0x2d65, 0x2d66, 0x2d67, 0x2d68, 0x2d69,
+ 0x2d6a, 0x2d6b, 0x2d6c, 0x2d6e, 0x2d6f, 0x2d70, 0x2d71, 0x2d73,
+ 0x2d74, 0x2d75, 0x2d77, 0x2d78, 0x2d7a, 0x2d7b, 0x2d7d, 0x2d7f,
+ 0x2d80, 0x2d80, 0x2d80, 0x2d80, 0x2d81, 0x2d81, 0x2d82, 0x2d82,
+ 0x2d83, 0x2d84, 0x2d85, 0x2d85, 0x2d86, 0x2d87, 0x2d88, 0x2d89,
+ 0x2d8a, 0x2d8b, 0x2d8c, 0x2d8e, 0x2d8f, 0x2d90, 0x2d91, 0x2d93,
+ 0x2d94, 0x2d95, 0x2d97, 0x2d98, 0x2d9a, 0x2d9b, 0x2d9d, 0x2d9f,
+ 0x2dc0, 0x2dc0, 0x2dc0, 0x2dc0, 0x2dc1, 0x2dc1, 0x2dc2, 0x2dc2,
+ 0x2dc3, 0x2dc4, 0x2dc5, 0x2dc5, 0x2dc6, 0x2dc7, 0x2dc8, 0x2dc9,
+ 0x2dca, 0x2dcb, 0x2dcc, 0x2dce, 0x2dcf, 0x2dd0, 0x2dd1, 0x2dd3,
+ 0x2dd4, 0x2dd5, 0x2dd7, 0x2dd8, 0x2dda, 0x2ddb, 0x2ddd, 0x2ddf,
+ 0x2de0, 0x2de0, 0x2de0, 0x2de0, 0x2de1, 0x2de1, 0x2de2, 0x2de2,
+ 0x2de3, 0x2de4, 0x2de5, 0x2de5, 0x2de6, 0x2de7, 0x2de8, 0x2de9,
+ 0x2dea, 0x2deb, 0x2dec, 0x2dee, 0x2def, 0x2df0, 0x2df1, 0x2df3,
+ 0x2df4, 0x2df5, 0x2df7, 0x2df8, 0x2dfa, 0x2dfb, 0x2dfd, 0x2dff,
+ 0x2e20, 0x2e20, 0x2e20, 0x2e20, 0x2e21, 0x2e21, 0x2e22, 0x2e22,
+ 0x2e23, 0x2e24, 0x2e25, 0x2e25, 0x2e26, 0x2e27, 0x2e28, 0x2e29,
+ 0x2e2a, 0x2e2b, 0x2e2c, 0x2e2e, 0x2e2f, 0x2e30, 0x2e31, 0x2e33,
+ 0x2e34, 0x2e35, 0x2e37, 0x2e38, 0x2e3a, 0x2e3b, 0x2e3d, 0x2e3f,
+ 0x2e40, 0x2e40, 0x2e40, 0x2e40, 0x2e41, 0x2e41, 0x2e42, 0x2e42,
+ 0x2e43, 0x2e44, 0x2e45, 0x2e45, 0x2e46, 0x2e47, 0x2e48, 0x2e49,
+ 0x2e4a, 0x2e4b, 0x2e4c, 0x2e4e, 0x2e4f, 0x2e50, 0x2e51, 0x2e53,
+ 0x2e54, 0x2e55, 0x2e57, 0x2e58, 0x2e5a, 0x2e5b, 0x2e5d, 0x2e5f,
+ 0x2e80, 0x2e80, 0x2e80, 0x2e80, 0x2e81, 0x2e81, 0x2e82, 0x2e82,
+ 0x2e83, 0x2e84, 0x2e85, 0x2e85, 0x2e86, 0x2e87, 0x2e88, 0x2e89,
+ 0x2e8a, 0x2e8b, 0x2e8c, 0x2e8e, 0x2e8f, 0x2e90, 0x2e91, 0x2e93,
+ 0x2e94, 0x2e95, 0x2e97, 0x2e98, 0x2e9a, 0x2e9b, 0x2e9d, 0x2e9f,
+ 0x2ea0, 0x2ea0, 0x2ea0, 0x2ea0, 0x2ea1, 0x2ea1, 0x2ea2, 0x2ea2,
+ 0x2ea3, 0x2ea4, 0x2ea5, 0x2ea5, 0x2ea6, 0x2ea7, 0x2ea8, 0x2ea9,
+ 0x2eaa, 0x2eab, 0x2eac, 0x2eae, 0x2eaf, 0x2eb0, 0x2eb1, 0x2eb3,
+ 0x2eb4, 0x2eb5, 0x2eb7, 0x2eb8, 0x2eba, 0x2ebb, 0x2ebd, 0x2ebf,
+ 0x2ee0, 0x2ee0, 0x2ee0, 0x2ee0, 0x2ee1, 0x2ee1, 0x2ee2, 0x2ee2,
+ 0x2ee3, 0x2ee4, 0x2ee5, 0x2ee5, 0x2ee6, 0x2ee7, 0x2ee8, 0x2ee9,
+ 0x2eea, 0x2eeb, 0x2eec, 0x2eee, 0x2eef, 0x2ef0, 0x2ef1, 0x2ef3,
+ 0x2ef4, 0x2ef5, 0x2ef7, 0x2ef8, 0x2efa, 0x2efb, 0x2efd, 0x2eff,
+ 0x2f00, 0x2f00, 0x2f00, 0x2f00, 0x2f01, 0x2f01, 0x2f02, 0x2f02,
+ 0x2f03, 0x2f04, 0x2f05, 0x2f05, 0x2f06, 0x2f07, 0x2f08, 0x2f09,
+ 0x2f0a, 0x2f0b, 0x2f0c, 0x2f0e, 0x2f0f, 0x2f10, 0x2f11, 0x2f13,
+ 0x2f14, 0x2f15, 0x2f17, 0x2f18, 0x2f1a, 0x2f1b, 0x2f1d, 0x2f1f,
+ 0x2f40, 0x2f40, 0x2f40, 0x2f40, 0x2f41, 0x2f41, 0x2f42, 0x2f42,
+ 0x2f43, 0x2f44, 0x2f45, 0x2f45, 0x2f46, 0x2f47, 0x2f48, 0x2f49,
+ 0x2f4a, 0x2f4b, 0x2f4c, 0x2f4e, 0x2f4f, 0x2f50, 0x2f51, 0x2f53,
+ 0x2f54, 0x2f55, 0x2f57, 0x2f58, 0x2f5a, 0x2f5b, 0x2f5d, 0x2f5f,
+ 0x2f60, 0x2f60, 0x2f60, 0x2f60, 0x2f61, 0x2f61, 0x2f62, 0x2f62,
+ 0x2f63, 0x2f64, 0x2f65, 0x2f65, 0x2f66, 0x2f67, 0x2f68, 0x2f69,
+ 0x2f6a, 0x2f6b, 0x2f6c, 0x2f6e, 0x2f6f, 0x2f70, 0x2f71, 0x2f73,
+ 0x2f74, 0x2f75, 0x2f77, 0x2f78, 0x2f7a, 0x2f7b, 0x2f7d, 0x2f7f,
+ 0x2fa0, 0x2fa0, 0x2fa0, 0x2fa0, 0x2fa1, 0x2fa1, 0x2fa2, 0x2fa2,
+ 0x2fa3, 0x2fa4, 0x2fa5, 0x2fa5, 0x2fa6, 0x2fa7, 0x2fa8, 0x2fa9,
+ 0x2faa, 0x2fab, 0x2fac, 0x2fae, 0x2faf, 0x2fb0, 0x2fb1, 0x2fb3,
+ 0x2fb4, 0x2fb5, 0x2fb7, 0x2fb8, 0x2fba, 0x2fbb, 0x2fbd, 0x2fbf,
+ 0x2fe0, 0x2fe0, 0x2fe0, 0x2fe0, 0x2fe1, 0x2fe1, 0x2fe2, 0x2fe2,
+ 0x2fe3, 0x2fe4, 0x2fe5, 0x2fe5, 0x2fe6, 0x2fe7, 0x2fe8, 0x2fe9,
+ 0x2fea, 0x2feb, 0x2fec, 0x2fee, 0x2fef, 0x2ff0, 0x2ff1, 0x2ff3,
+ 0x2ff4, 0x2ff5, 0x2ff7, 0x2ff8, 0x2ffa, 0x2ffb, 0x2ffd, 0x2fff,
+ 0x3000, 0x3000, 0x3000, 0x3000, 0x3001, 0x3001, 0x3002, 0x3002,
+ 0x3003, 0x3004, 0x3005, 0x3005, 0x3006, 0x3007, 0x3008, 0x3009,
+ 0x300a, 0x300b, 0x300c, 0x300e, 0x300f, 0x3010, 0x3011, 0x3013,
+ 0x3014, 0x3015, 0x3017, 0x3018, 0x301a, 0x301b, 0x301d, 0x301f,
+ 0x3000, 0x3000, 0x3000, 0x3000, 0x3001, 0x3001, 0x3002, 0x3002,
+ 0x3003, 0x3004, 0x3005, 0x3005, 0x3006, 0x3007, 0x3008, 0x3009,
+ 0x300a, 0x300b, 0x300c, 0x300e, 0x300f, 0x3010, 0x3011, 0x3013,
+ 0x3014, 0x3015, 0x3017, 0x3018, 0x301a, 0x301b, 0x301d, 0x301f,
+ 0x3000, 0x3000, 0x3000, 0x3000, 0x3001, 0x3001, 0x3002, 0x3002,
+ 0x3003, 0x3004, 0x3005, 0x3005, 0x3006, 0x3007, 0x3008, 0x3009,
+ 0x300a, 0x300b, 0x300c, 0x300e, 0x300f, 0x3010, 0x3011, 0x3013,
+ 0x3014, 0x3015, 0x3017, 0x3018, 0x301a, 0x301b, 0x301d, 0x301f,
+ 0x3000, 0x3000, 0x3000, 0x3000, 0x3001, 0x3001, 0x3002, 0x3002,
+ 0x3003, 0x3004, 0x3005, 0x3005, 0x3006, 0x3007, 0x3008, 0x3009,
+ 0x300a, 0x300b, 0x300c, 0x300e, 0x300f, 0x3010, 0x3011, 0x3013,
+ 0x3014, 0x3015, 0x3017, 0x3018, 0x301a, 0x301b, 0x301d, 0x301f,
+ 0x3000, 0x3000, 0x3000, 0x3000, 0x3001, 0x3001, 0x3002, 0x3002,
+ 0x3003, 0x3004, 0x3005, 0x3005, 0x3006, 0x3007, 0x3008, 0x3009,
+ 0x300a, 0x300b, 0x300c, 0x300e, 0x300f, 0x3010, 0x3011, 0x3013,
+ 0x3014, 0x3015, 0x3017, 0x3018, 0x301a, 0x301b, 0x301d, 0x301f,
+ 0x3020, 0x3020, 0x3020, 0x3020, 0x3021, 0x3021, 0x3022, 0x3022,
+ 0x3023, 0x3024, 0x3025, 0x3025, 0x3026, 0x3027, 0x3028, 0x3029,
+ 0x302a, 0x302b, 0x302c, 0x302e, 0x302f, 0x3030, 0x3031, 0x3033,
+ 0x3034, 0x3035, 0x3037, 0x3038, 0x303a, 0x303b, 0x303d, 0x303f,
+ 0x3020, 0x3020, 0x3020, 0x3020, 0x3021, 0x3021, 0x3022, 0x3022,
+ 0x3023, 0x3024, 0x3025, 0x3025, 0x3026, 0x3027, 0x3028, 0x3029,
+ 0x302a, 0x302b, 0x302c, 0x302e, 0x302f, 0x3030, 0x3031, 0x3033,
+ 0x3034, 0x3035, 0x3037, 0x3038, 0x303a, 0x303b, 0x303d, 0x303f,
+ 0x3020, 0x3020, 0x3020, 0x3020, 0x3021, 0x3021, 0x3022, 0x3022,
+ 0x3023, 0x3024, 0x3025, 0x3025, 0x3026, 0x3027, 0x3028, 0x3029,
+ 0x302a, 0x302b, 0x302c, 0x302e, 0x302f, 0x3030, 0x3031, 0x3033,
+ 0x3034, 0x3035, 0x3037, 0x3038, 0x303a, 0x303b, 0x303d, 0x303f,
+ 0x3040, 0x3040, 0x3040, 0x3040, 0x3041, 0x3041, 0x3042, 0x3042,
+ 0x3043, 0x3044, 0x3045, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049,
+ 0x304a, 0x304b, 0x304c, 0x304e, 0x304f, 0x3050, 0x3051, 0x3053,
+ 0x3054, 0x3055, 0x3057, 0x3058, 0x305a, 0x305b, 0x305d, 0x305f,
+ 0x3040, 0x3040, 0x3040, 0x3040, 0x3041, 0x3041, 0x3042, 0x3042,
+ 0x3043, 0x3044, 0x3045, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049,
+ 0x304a, 0x304b, 0x304c, 0x304e, 0x304f, 0x3050, 0x3051, 0x3053,
+ 0x3054, 0x3055, 0x3057, 0x3058, 0x305a, 0x305b, 0x305d, 0x305f,
+ 0x3060, 0x3060, 0x3060, 0x3060, 0x3061, 0x3061, 0x3062, 0x3062,
+ 0x3063, 0x3064, 0x3065, 0x3065, 0x3066, 0x3067, 0x3068, 0x3069,
+ 0x306a, 0x306b, 0x306c, 0x306e, 0x306f, 0x3070, 0x3071, 0x3073,
+ 0x3074, 0x3075, 0x3077, 0x3078, 0x307a, 0x307b, 0x307d, 0x307f,
+ 0x3060, 0x3060, 0x3060, 0x3060, 0x3061, 0x3061, 0x3062, 0x3062,
+ 0x3063, 0x3064, 0x3065, 0x3065, 0x3066, 0x3067, 0x3068, 0x3069,
+ 0x306a, 0x306b, 0x306c, 0x306e, 0x306f, 0x3070, 0x3071, 0x3073,
+ 0x3074, 0x3075, 0x3077, 0x3078, 0x307a, 0x307b, 0x307d, 0x307f,
+ 0x3080, 0x3080, 0x3080, 0x3080, 0x3081, 0x3081, 0x3082, 0x3082,
+ 0x3083, 0x3084, 0x3085, 0x3085, 0x3086, 0x3087, 0x3088, 0x3089,
+ 0x308a, 0x308b, 0x308c, 0x308e, 0x308f, 0x3090, 0x3091, 0x3093,
+ 0x3094, 0x3095, 0x3097, 0x3098, 0x309a, 0x309b, 0x309d, 0x309f,
+ 0x30a0, 0x30a0, 0x30a0, 0x30a0, 0x30a1, 0x30a1, 0x30a2, 0x30a2,
+ 0x30a3, 0x30a4, 0x30a5, 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9,
+ 0x30aa, 0x30ab, 0x30ac, 0x30ae, 0x30af, 0x30b0, 0x30b1, 0x30b3,
+ 0x30b4, 0x30b5, 0x30b7, 0x30b8, 0x30ba, 0x30bb, 0x30bd, 0x30bf,
+ 0x30a0, 0x30a0, 0x30a0, 0x30a0, 0x30a1, 0x30a1, 0x30a2, 0x30a2,
+ 0x30a3, 0x30a4, 0x30a5, 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9,
+ 0x30aa, 0x30ab, 0x30ac, 0x30ae, 0x30af, 0x30b0, 0x30b1, 0x30b3,
+ 0x30b4, 0x30b5, 0x30b7, 0x30b8, 0x30ba, 0x30bb, 0x30bd, 0x30bf,
+ 0x30c0, 0x30c0, 0x30c0, 0x30c0, 0x30c1, 0x30c1, 0x30c2, 0x30c2,
+ 0x30c3, 0x30c4, 0x30c5, 0x30c5, 0x30c6, 0x30c7, 0x30c8, 0x30c9,
+ 0x30ca, 0x30cb, 0x30cc, 0x30ce, 0x30cf, 0x30d0, 0x30d1, 0x30d3,
+ 0x30d4, 0x30d5, 0x30d7, 0x30d8, 0x30da, 0x30db, 0x30dd, 0x30df,
+ 0x30e0, 0x30e0, 0x30e0, 0x30e0, 0x30e1, 0x30e1, 0x30e2, 0x30e2,
+ 0x30e3, 0x30e4, 0x30e5, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9,
+ 0x30ea, 0x30eb, 0x30ec, 0x30ee, 0x30ef, 0x30f0, 0x30f1, 0x30f3,
+ 0x30f4, 0x30f5, 0x30f7, 0x30f8, 0x30fa, 0x30fb, 0x30fd, 0x30ff,
+ 0x30e0, 0x30e0, 0x30e0, 0x30e0, 0x30e1, 0x30e1, 0x30e2, 0x30e2,
+ 0x30e3, 0x30e4, 0x30e5, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9,
+ 0x30ea, 0x30eb, 0x30ec, 0x30ee, 0x30ef, 0x30f0, 0x30f1, 0x30f3,
+ 0x30f4, 0x30f5, 0x30f7, 0x30f8, 0x30fa, 0x30fb, 0x30fd, 0x30ff,
+ 0x3100, 0x3100, 0x3100, 0x3100, 0x3101, 0x3101, 0x3102, 0x3102,
+ 0x3103, 0x3104, 0x3105, 0x3105, 0x3106, 0x3107, 0x3108, 0x3109,
+ 0x310a, 0x310b, 0x310c, 0x310e, 0x310f, 0x3110, 0x3111, 0x3113,
+ 0x3114, 0x3115, 0x3117, 0x3118, 0x311a, 0x311b, 0x311d, 0x311f,
+ 0x3120, 0x3120, 0x3120, 0x3120, 0x3121, 0x3121, 0x3122, 0x3122,
+ 0x3123, 0x3124, 0x3125, 0x3125, 0x3126, 0x3127, 0x3128, 0x3129,
+ 0x312a, 0x312b, 0x312c, 0x312e, 0x312f, 0x3130, 0x3131, 0x3133,
+ 0x3134, 0x3135, 0x3137, 0x3138, 0x313a, 0x313b, 0x313d, 0x313f,
+ 0x3140, 0x3140, 0x3140, 0x3140, 0x3141, 0x3141, 0x3142, 0x3142,
+ 0x3143, 0x3144, 0x3145, 0x3145, 0x3146, 0x3147, 0x3148, 0x3149,
+ 0x314a, 0x314b, 0x314c, 0x314e, 0x314f, 0x3150, 0x3151, 0x3153,
+ 0x3154, 0x3155, 0x3157, 0x3158, 0x315a, 0x315b, 0x315d, 0x315f,
+ 0x3140, 0x3140, 0x3140, 0x3140, 0x3141, 0x3141, 0x3142, 0x3142,
+ 0x3143, 0x3144, 0x3145, 0x3145, 0x3146, 0x3147, 0x3148, 0x3149,
+ 0x314a, 0x314b, 0x314c, 0x314e, 0x314f, 0x3150, 0x3151, 0x3153,
+ 0x3154, 0x3155, 0x3157, 0x3158, 0x315a, 0x315b, 0x315d, 0x315f,
+ 0x3160, 0x3160, 0x3160, 0x3160, 0x3161, 0x3161, 0x3162, 0x3162,
+ 0x3163, 0x3164, 0x3165, 0x3165, 0x3166, 0x3167, 0x3168, 0x3169,
+ 0x316a, 0x316b, 0x316c, 0x316e, 0x316f, 0x3170, 0x3171, 0x3173,
+ 0x3174, 0x3175, 0x3177, 0x3178, 0x317a, 0x317b, 0x317d, 0x317f,
+ 0x3180, 0x3180, 0x3180, 0x3180, 0x3181, 0x3181, 0x3182, 0x3182,
+ 0x3183, 0x3184, 0x3185, 0x3185, 0x3186, 0x3187, 0x3188, 0x3189,
+ 0x318a, 0x318b, 0x318c, 0x318e, 0x318f, 0x3190, 0x3191, 0x3193,
+ 0x3194, 0x3195, 0x3197, 0x3198, 0x319a, 0x319b, 0x319d, 0x319f,
+ 0x31a0, 0x31a0, 0x31a0, 0x31a0, 0x31a1, 0x31a1, 0x31a2, 0x31a2,
+ 0x31a3, 0x31a4, 0x31a5, 0x31a5, 0x31a6, 0x31a7, 0x31a8, 0x31a9,
+ 0x31aa, 0x31ab, 0x31ac, 0x31ae, 0x31af, 0x31b0, 0x31b1, 0x31b3,
+ 0x31b4, 0x31b5, 0x31b7, 0x31b8, 0x31ba, 0x31bb, 0x31bd, 0x31bf,
+ 0x31c0, 0x31c0, 0x31c0, 0x31c0, 0x31c1, 0x31c1, 0x31c2, 0x31c2,
+ 0x31c3, 0x31c4, 0x31c5, 0x31c5, 0x31c6, 0x31c7, 0x31c8, 0x31c9,
+ 0x31ca, 0x31cb, 0x31cc, 0x31ce, 0x31cf, 0x31d0, 0x31d1, 0x31d3,
+ 0x31d4, 0x31d5, 0x31d7, 0x31d8, 0x31da, 0x31db, 0x31dd, 0x31df,
+ 0x31e0, 0x31e0, 0x31e0, 0x31e0, 0x31e1, 0x31e1, 0x31e2, 0x31e2,
+ 0x31e3, 0x31e4, 0x31e5, 0x31e5, 0x31e6, 0x31e7, 0x31e8, 0x31e9,
+ 0x31ea, 0x31eb, 0x31ec, 0x31ee, 0x31ef, 0x31f0, 0x31f1, 0x31f3,
+ 0x31f4, 0x31f5, 0x31f7, 0x31f8, 0x31fa, 0x31fb, 0x31fd, 0x31ff,
+ 0x3200, 0x3200, 0x3200, 0x3200, 0x3201, 0x3201, 0x3202, 0x3202,
+ 0x3203, 0x3204, 0x3205, 0x3205, 0x3206, 0x3207, 0x3208, 0x3209,
+ 0x320a, 0x320b, 0x320c, 0x320e, 0x320f, 0x3210, 0x3211, 0x3213,
+ 0x3214, 0x3215, 0x3217, 0x3218, 0x321a, 0x321b, 0x321d, 0x321f,
+ 0x3220, 0x3220, 0x3220, 0x3220, 0x3221, 0x3221, 0x3222, 0x3222,
+ 0x3223, 0x3224, 0x3225, 0x3225, 0x3226, 0x3227, 0x3228, 0x3229,
+ 0x322a, 0x322b, 0x322c, 0x322e, 0x322f, 0x3230, 0x3231, 0x3233,
+ 0x3234, 0x3235, 0x3237, 0x3238, 0x323a, 0x323b, 0x323d, 0x323f,
+ 0x3240, 0x3240, 0x3240, 0x3240, 0x3241, 0x3241, 0x3242, 0x3242,
+ 0x3243, 0x3244, 0x3245, 0x3245, 0x3246, 0x3247, 0x3248, 0x3249,
+ 0x324a, 0x324b, 0x324c, 0x324e, 0x324f, 0x3250, 0x3251, 0x3253,
+ 0x3254, 0x3255, 0x3257, 0x3258, 0x325a, 0x325b, 0x325d, 0x325f,
+ 0x3260, 0x3260, 0x3260, 0x3260, 0x3261, 0x3261, 0x3262, 0x3262,
+ 0x3263, 0x3264, 0x3265, 0x3265, 0x3266, 0x3267, 0x3268, 0x3269,
+ 0x326a, 0x326b, 0x326c, 0x326e, 0x326f, 0x3270, 0x3271, 0x3273,
+ 0x3274, 0x3275, 0x3277, 0x3278, 0x327a, 0x327b, 0x327d, 0x327f,
+ 0x3280, 0x3280, 0x3280, 0x3280, 0x3281, 0x3281, 0x3282, 0x3282,
+ 0x3283, 0x3284, 0x3285, 0x3285, 0x3286, 0x3287, 0x3288, 0x3289,
+ 0x328a, 0x328b, 0x328c, 0x328e, 0x328f, 0x3290, 0x3291, 0x3293,
+ 0x3294, 0x3295, 0x3297, 0x3298, 0x329a, 0x329b, 0x329d, 0x329f,
+ 0x32a0, 0x32a0, 0x32a0, 0x32a0, 0x32a1, 0x32a1, 0x32a2, 0x32a2,
+ 0x32a3, 0x32a4, 0x32a5, 0x32a5, 0x32a6, 0x32a7, 0x32a8, 0x32a9,
+ 0x32aa, 0x32ab, 0x32ac, 0x32ae, 0x32af, 0x32b0, 0x32b1, 0x32b3,
+ 0x32b4, 0x32b5, 0x32b7, 0x32b8, 0x32ba, 0x32bb, 0x32bd, 0x32bf,
+ 0x32c0, 0x32c0, 0x32c0, 0x32c0, 0x32c1, 0x32c1, 0x32c2, 0x32c2,
+ 0x32c3, 0x32c4, 0x32c5, 0x32c5, 0x32c6, 0x32c7, 0x32c8, 0x32c9,
+ 0x32ca, 0x32cb, 0x32cc, 0x32ce, 0x32cf, 0x32d0, 0x32d1, 0x32d3,
+ 0x32d4, 0x32d5, 0x32d7, 0x32d8, 0x32da, 0x32db, 0x32dd, 0x32df,
+ 0x32e0, 0x32e0, 0x32e0, 0x32e0, 0x32e1, 0x32e1, 0x32e2, 0x32e2,
+ 0x32e3, 0x32e4, 0x32e5, 0x32e5, 0x32e6, 0x32e7, 0x32e8, 0x32e9,
+ 0x32ea, 0x32eb, 0x32ec, 0x32ee, 0x32ef, 0x32f0, 0x32f1, 0x32f3,
+ 0x32f4, 0x32f5, 0x32f7, 0x32f8, 0x32fa, 0x32fb, 0x32fd, 0x32ff,
+ 0x3300, 0x3300, 0x3300, 0x3300, 0x3301, 0x3301, 0x3302, 0x3302,
+ 0x3303, 0x3304, 0x3305, 0x3305, 0x3306, 0x3307, 0x3308, 0x3309,
+ 0x330a, 0x330b, 0x330c, 0x330e, 0x330f, 0x3310, 0x3311, 0x3313,
+ 0x3314, 0x3315, 0x3317, 0x3318, 0x331a, 0x331b, 0x331d, 0x331f,
+ 0x3320, 0x3320, 0x3320, 0x3320, 0x3321, 0x3321, 0x3322, 0x3322,
+ 0x3323, 0x3324, 0x3325, 0x3325, 0x3326, 0x3327, 0x3328, 0x3329,
+ 0x332a, 0x332b, 0x332c, 0x332e, 0x332f, 0x3330, 0x3331, 0x3333,
+ 0x3334, 0x3335, 0x3337, 0x3338, 0x333a, 0x333b, 0x333d, 0x333f,
+ 0x3340, 0x3340, 0x3340, 0x3340, 0x3341, 0x3341, 0x3342, 0x3342,
+ 0x3343, 0x3344, 0x3345, 0x3345, 0x3346, 0x3347, 0x3348, 0x3349,
+ 0x334a, 0x334b, 0x334c, 0x334e, 0x334f, 0x3350, 0x3351, 0x3353,
+ 0x3354, 0x3355, 0x3357, 0x3358, 0x335a, 0x335b, 0x335d, 0x335f,
+ 0x3380, 0x3380, 0x3380, 0x3380, 0x3381, 0x3381, 0x3382, 0x3382,
+ 0x3383, 0x3384, 0x3385, 0x3385, 0x3386, 0x3387, 0x3388, 0x3389,
+ 0x338a, 0x338b, 0x338c, 0x338e, 0x338f, 0x3390, 0x3391, 0x3393,
+ 0x3394, 0x3395, 0x3397, 0x3398, 0x339a, 0x339b, 0x339d, 0x339f,
+ 0x33a0, 0x33a0, 0x33a0, 0x33a0, 0x33a1, 0x33a1, 0x33a2, 0x33a2,
+ 0x33a3, 0x33a4, 0x33a5, 0x33a5, 0x33a6, 0x33a7, 0x33a8, 0x33a9,
+ 0x33aa, 0x33ab, 0x33ac, 0x33ae, 0x33af, 0x33b0, 0x33b1, 0x33b3,
+ 0x33b4, 0x33b5, 0x33b7, 0x33b8, 0x33ba, 0x33bb, 0x33bd, 0x33bf,
+ 0x33c0, 0x33c0, 0x33c0, 0x33c0, 0x33c1, 0x33c1, 0x33c2, 0x33c2,
+ 0x33c3, 0x33c4, 0x33c5, 0x33c5, 0x33c6, 0x33c7, 0x33c8, 0x33c9,
+ 0x33ca, 0x33cb, 0x33cc, 0x33ce, 0x33cf, 0x33d0, 0x33d1, 0x33d3,
+ 0x33d4, 0x33d5, 0x33d7, 0x33d8, 0x33da, 0x33db, 0x33dd, 0x33df,
+ 0x33e0, 0x33e0, 0x33e0, 0x33e0, 0x33e1, 0x33e1, 0x33e2, 0x33e2,
+ 0x33e3, 0x33e4, 0x33e5, 0x33e5, 0x33e6, 0x33e7, 0x33e8, 0x33e9,
+ 0x33ea, 0x33eb, 0x33ec, 0x33ee, 0x33ef, 0x33f0, 0x33f1, 0x33f3,
+ 0x33f4, 0x33f5, 0x33f7, 0x33f8, 0x33fa, 0x33fb, 0x33fd, 0x33ff,
+ 0x3400, 0x3400, 0x3400, 0x3400, 0x3401, 0x3401, 0x3402, 0x3402,
+ 0x3403, 0x3404, 0x3405, 0x3405, 0x3406, 0x3407, 0x3408, 0x3409,
+ 0x340a, 0x340b, 0x340c, 0x340e, 0x340f, 0x3410, 0x3411, 0x3413,
+ 0x3414, 0x3415, 0x3417, 0x3418, 0x341a, 0x341b, 0x341d, 0x341f,
+ 0x3440, 0x3440, 0x3440, 0x3440, 0x3441, 0x3441, 0x3442, 0x3442,
+ 0x3443, 0x3444, 0x3445, 0x3445, 0x3446, 0x3447, 0x3448, 0x3449,
+ 0x344a, 0x344b, 0x344c, 0x344e, 0x344f, 0x3450, 0x3451, 0x3453,
+ 0x3454, 0x3455, 0x3457, 0x3458, 0x345a, 0x345b, 0x345d, 0x345f,
+ 0x3460, 0x3460, 0x3460, 0x3460, 0x3461, 0x3461, 0x3462, 0x3462,
+ 0x3463, 0x3464, 0x3465, 0x3465, 0x3466, 0x3467, 0x3468, 0x3469,
+ 0x346a, 0x346b, 0x346c, 0x346e, 0x346f, 0x3470, 0x3471, 0x3473,
+ 0x3474, 0x3475, 0x3477, 0x3478, 0x347a, 0x347b, 0x347d, 0x347f,
+ 0x3480, 0x3480, 0x3480, 0x3480, 0x3481, 0x3481, 0x3482, 0x3482,
+ 0x3483, 0x3484, 0x3485, 0x3485, 0x3486, 0x3487, 0x3488, 0x3489,
+ 0x348a, 0x348b, 0x348c, 0x348e, 0x348f, 0x3490, 0x3491, 0x3493,
+ 0x3494, 0x3495, 0x3497, 0x3498, 0x349a, 0x349b, 0x349d, 0x349f,
+ 0x34c0, 0x34c0, 0x34c0, 0x34c0, 0x34c1, 0x34c1, 0x34c2, 0x34c2,
+ 0x34c3, 0x34c4, 0x34c5, 0x34c5, 0x34c6, 0x34c7, 0x34c8, 0x34c9,
+ 0x34ca, 0x34cb, 0x34cc, 0x34ce, 0x34cf, 0x34d0, 0x34d1, 0x34d3,
+ 0x34d4, 0x34d5, 0x34d7, 0x34d8, 0x34da, 0x34db, 0x34dd, 0x34df,
+ 0x34e0, 0x34e0, 0x34e0, 0x34e0, 0x34e1, 0x34e1, 0x34e2, 0x34e2,
+ 0x34e3, 0x34e4, 0x34e5, 0x34e5, 0x34e6, 0x34e7, 0x34e8, 0x34e9,
+ 0x34ea, 0x34eb, 0x34ec, 0x34ee, 0x34ef, 0x34f0, 0x34f1, 0x34f3,
+ 0x34f4, 0x34f5, 0x34f7, 0x34f8, 0x34fa, 0x34fb, 0x34fd, 0x34ff,
+ 0x3500, 0x3500, 0x3500, 0x3500, 0x3501, 0x3501, 0x3502, 0x3502,
+ 0x3503, 0x3504, 0x3505, 0x3505, 0x3506, 0x3507, 0x3508, 0x3509,
+ 0x350a, 0x350b, 0x350c, 0x350e, 0x350f, 0x3510, 0x3511, 0x3513,
+ 0x3514, 0x3515, 0x3517, 0x3518, 0x351a, 0x351b, 0x351d, 0x351f,
+ 0x3540, 0x3540, 0x3540, 0x3540, 0x3541, 0x3541, 0x3542, 0x3542,
+ 0x3543, 0x3544, 0x3545, 0x3545, 0x3546, 0x3547, 0x3548, 0x3549,
+ 0x354a, 0x354b, 0x354c, 0x354e, 0x354f, 0x3550, 0x3551, 0x3553,
+ 0x3554, 0x3555, 0x3557, 0x3558, 0x355a, 0x355b, 0x355d, 0x355f,
+ 0x3560, 0x3560, 0x3560, 0x3560, 0x3561, 0x3561, 0x3562, 0x3562,
+ 0x3563, 0x3564, 0x3565, 0x3565, 0x3566, 0x3567, 0x3568, 0x3569,
+ 0x356a, 0x356b, 0x356c, 0x356e, 0x356f, 0x3570, 0x3571, 0x3573,
+ 0x3574, 0x3575, 0x3577, 0x3578, 0x357a, 0x357b, 0x357d, 0x357f,
+ 0x3580, 0x3580, 0x3580, 0x3580, 0x3581, 0x3581, 0x3582, 0x3582,
+ 0x3583, 0x3584, 0x3585, 0x3585, 0x3586, 0x3587, 0x3588, 0x3589,
+ 0x358a, 0x358b, 0x358c, 0x358e, 0x358f, 0x3590, 0x3591, 0x3593,
+ 0x3594, 0x3595, 0x3597, 0x3598, 0x359a, 0x359b, 0x359d, 0x359f,
+ 0x35c0, 0x35c0, 0x35c0, 0x35c0, 0x35c1, 0x35c1, 0x35c2, 0x35c2,
+ 0x35c3, 0x35c4, 0x35c5, 0x35c5, 0x35c6, 0x35c7, 0x35c8, 0x35c9,
+ 0x35ca, 0x35cb, 0x35cc, 0x35ce, 0x35cf, 0x35d0, 0x35d1, 0x35d3,
+ 0x35d4, 0x35d5, 0x35d7, 0x35d8, 0x35da, 0x35db, 0x35dd, 0x35df,
+ 0x35e0, 0x35e0, 0x35e0, 0x35e0, 0x35e1, 0x35e1, 0x35e2, 0x35e2,
+ 0x35e3, 0x35e4, 0x35e5, 0x35e5, 0x35e6, 0x35e7, 0x35e8, 0x35e9,
+ 0x35ea, 0x35eb, 0x35ec, 0x35ee, 0x35ef, 0x35f0, 0x35f1, 0x35f3,
+ 0x35f4, 0x35f5, 0x35f7, 0x35f8, 0x35fa, 0x35fb, 0x35fd, 0x35ff,
+ 0x3620, 0x3620, 0x3620, 0x3620, 0x3621, 0x3621, 0x3622, 0x3622,
+ 0x3623, 0x3624, 0x3625, 0x3625, 0x3626, 0x3627, 0x3628, 0x3629,
+ 0x362a, 0x362b, 0x362c, 0x362e, 0x362f, 0x3630, 0x3631, 0x3633,
+ 0x3634, 0x3635, 0x3637, 0x3638, 0x363a, 0x363b, 0x363d, 0x363f,
+ 0x3640, 0x3640, 0x3640, 0x3640, 0x3641, 0x3641, 0x3642, 0x3642,
+ 0x3643, 0x3644, 0x3645, 0x3645, 0x3646, 0x3647, 0x3648, 0x3649,
+ 0x364a, 0x364b, 0x364c, 0x364e, 0x364f, 0x3650, 0x3651, 0x3653,
+ 0x3654, 0x3655, 0x3657, 0x3658, 0x365a, 0x365b, 0x365d, 0x365f,
+ 0x3680, 0x3680, 0x3680, 0x3680, 0x3681, 0x3681, 0x3682, 0x3682,
+ 0x3683, 0x3684, 0x3685, 0x3685, 0x3686, 0x3687, 0x3688, 0x3689,
+ 0x368a, 0x368b, 0x368c, 0x368e, 0x368f, 0x3690, 0x3691, 0x3693,
+ 0x3694, 0x3695, 0x3697, 0x3698, 0x369a, 0x369b, 0x369d, 0x369f,
+ 0x36a0, 0x36a0, 0x36a0, 0x36a0, 0x36a1, 0x36a1, 0x36a2, 0x36a2,
+ 0x36a3, 0x36a4, 0x36a5, 0x36a5, 0x36a6, 0x36a7, 0x36a8, 0x36a9,
+ 0x36aa, 0x36ab, 0x36ac, 0x36ae, 0x36af, 0x36b0, 0x36b1, 0x36b3,
+ 0x36b4, 0x36b5, 0x36b7, 0x36b8, 0x36ba, 0x36bb, 0x36bd, 0x36bf,
+ 0x36e0, 0x36e0, 0x36e0, 0x36e0, 0x36e1, 0x36e1, 0x36e2, 0x36e2,
+ 0x36e3, 0x36e4, 0x36e5, 0x36e5, 0x36e6, 0x36e7, 0x36e8, 0x36e9,
+ 0x36ea, 0x36eb, 0x36ec, 0x36ee, 0x36ef, 0x36f0, 0x36f1, 0x36f3,
+ 0x36f4, 0x36f5, 0x36f7, 0x36f8, 0x36fa, 0x36fb, 0x36fd, 0x36ff,
+ 0x3700, 0x3700, 0x3700, 0x3700, 0x3701, 0x3701, 0x3702, 0x3702,
+ 0x3703, 0x3704, 0x3705, 0x3705, 0x3706, 0x3707, 0x3708, 0x3709,
+ 0x370a, 0x370b, 0x370c, 0x370e, 0x370f, 0x3710, 0x3711, 0x3713,
+ 0x3714, 0x3715, 0x3717, 0x3718, 0x371a, 0x371b, 0x371d, 0x371f,
+ 0x3740, 0x3740, 0x3740, 0x3740, 0x3741, 0x3741, 0x3742, 0x3742,
+ 0x3743, 0x3744, 0x3745, 0x3745, 0x3746, 0x3747, 0x3748, 0x3749,
+ 0x374a, 0x374b, 0x374c, 0x374e, 0x374f, 0x3750, 0x3751, 0x3753,
+ 0x3754, 0x3755, 0x3757, 0x3758, 0x375a, 0x375b, 0x375d, 0x375f,
+ 0x3760, 0x3760, 0x3760, 0x3760, 0x3761, 0x3761, 0x3762, 0x3762,
+ 0x3763, 0x3764, 0x3765, 0x3765, 0x3766, 0x3767, 0x3768, 0x3769,
+ 0x376a, 0x376b, 0x376c, 0x376e, 0x376f, 0x3770, 0x3771, 0x3773,
+ 0x3774, 0x3775, 0x3777, 0x3778, 0x377a, 0x377b, 0x377d, 0x377f,
+ 0x37a0, 0x37a0, 0x37a0, 0x37a0, 0x37a1, 0x37a1, 0x37a2, 0x37a2,
+ 0x37a3, 0x37a4, 0x37a5, 0x37a5, 0x37a6, 0x37a7, 0x37a8, 0x37a9,
+ 0x37aa, 0x37ab, 0x37ac, 0x37ae, 0x37af, 0x37b0, 0x37b1, 0x37b3,
+ 0x37b4, 0x37b5, 0x37b7, 0x37b8, 0x37ba, 0x37bb, 0x37bd, 0x37bf,
+ 0x37e0, 0x37e0, 0x37e0, 0x37e0, 0x37e1, 0x37e1, 0x37e2, 0x37e2,
+ 0x37e3, 0x37e4, 0x37e5, 0x37e5, 0x37e6, 0x37e7, 0x37e8, 0x37e9,
+ 0x37ea, 0x37eb, 0x37ec, 0x37ee, 0x37ef, 0x37f0, 0x37f1, 0x37f3,
+ 0x37f4, 0x37f5, 0x37f7, 0x37f8, 0x37fa, 0x37fb, 0x37fd, 0x37ff,
+ 0x3800, 0x3800, 0x3800, 0x3800, 0x3801, 0x3801, 0x3802, 0x3802,
+ 0x3803, 0x3804, 0x3805, 0x3805, 0x3806, 0x3807, 0x3808, 0x3809,
+ 0x380a, 0x380b, 0x380c, 0x380e, 0x380f, 0x3810, 0x3811, 0x3813,
+ 0x3814, 0x3815, 0x3817, 0x3818, 0x381a, 0x381b, 0x381d, 0x381f,
+ 0x3800, 0x3800, 0x3800, 0x3800, 0x3801, 0x3801, 0x3802, 0x3802,
+ 0x3803, 0x3804, 0x3805, 0x3805, 0x3806, 0x3807, 0x3808, 0x3809,
+ 0x380a, 0x380b, 0x380c, 0x380e, 0x380f, 0x3810, 0x3811, 0x3813,
+ 0x3814, 0x3815, 0x3817, 0x3818, 0x381a, 0x381b, 0x381d, 0x381f,
+ 0x3800, 0x3800, 0x3800, 0x3800, 0x3801, 0x3801, 0x3802, 0x3802,
+ 0x3803, 0x3804, 0x3805, 0x3805, 0x3806, 0x3807, 0x3808, 0x3809,
+ 0x380a, 0x380b, 0x380c, 0x380e, 0x380f, 0x3810, 0x3811, 0x3813,
+ 0x3814, 0x3815, 0x3817, 0x3818, 0x381a, 0x381b, 0x381d, 0x381f,
+ 0x3800, 0x3800, 0x3800, 0x3800, 0x3801, 0x3801, 0x3802, 0x3802,
+ 0x3803, 0x3804, 0x3805, 0x3805, 0x3806, 0x3807, 0x3808, 0x3809,
+ 0x380a, 0x380b, 0x380c, 0x380e, 0x380f, 0x3810, 0x3811, 0x3813,
+ 0x3814, 0x3815, 0x3817, 0x3818, 0x381a, 0x381b, 0x381d, 0x381f,
+ 0x3800, 0x3800, 0x3800, 0x3800, 0x3801, 0x3801, 0x3802, 0x3802,
+ 0x3803, 0x3804, 0x3805, 0x3805, 0x3806, 0x3807, 0x3808, 0x3809,
+ 0x380a, 0x380b, 0x380c, 0x380e, 0x380f, 0x3810, 0x3811, 0x3813,
+ 0x3814, 0x3815, 0x3817, 0x3818, 0x381a, 0x381b, 0x381d, 0x381f,
+ 0x3820, 0x3820, 0x3820, 0x3820, 0x3821, 0x3821, 0x3822, 0x3822,
+ 0x3823, 0x3824, 0x3825, 0x3825, 0x3826, 0x3827, 0x3828, 0x3829,
+ 0x382a, 0x382b, 0x382c, 0x382e, 0x382f, 0x3830, 0x3831, 0x3833,
+ 0x3834, 0x3835, 0x3837, 0x3838, 0x383a, 0x383b, 0x383d, 0x383f,
+ 0x3820, 0x3820, 0x3820, 0x3820, 0x3821, 0x3821, 0x3822, 0x3822,
+ 0x3823, 0x3824, 0x3825, 0x3825, 0x3826, 0x3827, 0x3828, 0x3829,
+ 0x382a, 0x382b, 0x382c, 0x382e, 0x382f, 0x3830, 0x3831, 0x3833,
+ 0x3834, 0x3835, 0x3837, 0x3838, 0x383a, 0x383b, 0x383d, 0x383f,
+ 0x3820, 0x3820, 0x3820, 0x3820, 0x3821, 0x3821, 0x3822, 0x3822,
+ 0x3823, 0x3824, 0x3825, 0x3825, 0x3826, 0x3827, 0x3828, 0x3829,
+ 0x382a, 0x382b, 0x382c, 0x382e, 0x382f, 0x3830, 0x3831, 0x3833,
+ 0x3834, 0x3835, 0x3837, 0x3838, 0x383a, 0x383b, 0x383d, 0x383f,
+ 0x3840, 0x3840, 0x3840, 0x3840, 0x3841, 0x3841, 0x3842, 0x3842,
+ 0x3843, 0x3844, 0x3845, 0x3845, 0x3846, 0x3847, 0x3848, 0x3849,
+ 0x384a, 0x384b, 0x384c, 0x384e, 0x384f, 0x3850, 0x3851, 0x3853,
+ 0x3854, 0x3855, 0x3857, 0x3858, 0x385a, 0x385b, 0x385d, 0x385f,
+ 0x3840, 0x3840, 0x3840, 0x3840, 0x3841, 0x3841, 0x3842, 0x3842,
+ 0x3843, 0x3844, 0x3845, 0x3845, 0x3846, 0x3847, 0x3848, 0x3849,
+ 0x384a, 0x384b, 0x384c, 0x384e, 0x384f, 0x3850, 0x3851, 0x3853,
+ 0x3854, 0x3855, 0x3857, 0x3858, 0x385a, 0x385b, 0x385d, 0x385f,
+ 0x3860, 0x3860, 0x3860, 0x3860, 0x3861, 0x3861, 0x3862, 0x3862,
+ 0x3863, 0x3864, 0x3865, 0x3865, 0x3866, 0x3867, 0x3868, 0x3869,
+ 0x386a, 0x386b, 0x386c, 0x386e, 0x386f, 0x3870, 0x3871, 0x3873,
+ 0x3874, 0x3875, 0x3877, 0x3878, 0x387a, 0x387b, 0x387d, 0x387f,
+ 0x3860, 0x3860, 0x3860, 0x3860, 0x3861, 0x3861, 0x3862, 0x3862,
+ 0x3863, 0x3864, 0x3865, 0x3865, 0x3866, 0x3867, 0x3868, 0x3869,
+ 0x386a, 0x386b, 0x386c, 0x386e, 0x386f, 0x3870, 0x3871, 0x3873,
+ 0x3874, 0x3875, 0x3877, 0x3878, 0x387a, 0x387b, 0x387d, 0x387f,
+ 0x3880, 0x3880, 0x3880, 0x3880, 0x3881, 0x3881, 0x3882, 0x3882,
+ 0x3883, 0x3884, 0x3885, 0x3885, 0x3886, 0x3887, 0x3888, 0x3889,
+ 0x388a, 0x388b, 0x388c, 0x388e, 0x388f, 0x3890, 0x3891, 0x3893,
+ 0x3894, 0x3895, 0x3897, 0x3898, 0x389a, 0x389b, 0x389d, 0x389f,
+ 0x38a0, 0x38a0, 0x38a0, 0x38a0, 0x38a1, 0x38a1, 0x38a2, 0x38a2,
+ 0x38a3, 0x38a4, 0x38a5, 0x38a5, 0x38a6, 0x38a7, 0x38a8, 0x38a9,
+ 0x38aa, 0x38ab, 0x38ac, 0x38ae, 0x38af, 0x38b0, 0x38b1, 0x38b3,
+ 0x38b4, 0x38b5, 0x38b7, 0x38b8, 0x38ba, 0x38bb, 0x38bd, 0x38bf,
+ 0x38a0, 0x38a0, 0x38a0, 0x38a0, 0x38a1, 0x38a1, 0x38a2, 0x38a2,
+ 0x38a3, 0x38a4, 0x38a5, 0x38a5, 0x38a6, 0x38a7, 0x38a8, 0x38a9,
+ 0x38aa, 0x38ab, 0x38ac, 0x38ae, 0x38af, 0x38b0, 0x38b1, 0x38b3,
+ 0x38b4, 0x38b5, 0x38b7, 0x38b8, 0x38ba, 0x38bb, 0x38bd, 0x38bf,
+ 0x38c0, 0x38c0, 0x38c0, 0x38c0, 0x38c1, 0x38c1, 0x38c2, 0x38c2,
+ 0x38c3, 0x38c4, 0x38c5, 0x38c5, 0x38c6, 0x38c7, 0x38c8, 0x38c9,
+ 0x38ca, 0x38cb, 0x38cc, 0x38ce, 0x38cf, 0x38d0, 0x38d1, 0x38d3,
+ 0x38d4, 0x38d5, 0x38d7, 0x38d8, 0x38da, 0x38db, 0x38dd, 0x38df,
+ 0x38e0, 0x38e0, 0x38e0, 0x38e0, 0x38e1, 0x38e1, 0x38e2, 0x38e2,
+ 0x38e3, 0x38e4, 0x38e5, 0x38e5, 0x38e6, 0x38e7, 0x38e8, 0x38e9,
+ 0x38ea, 0x38eb, 0x38ec, 0x38ee, 0x38ef, 0x38f0, 0x38f1, 0x38f3,
+ 0x38f4, 0x38f5, 0x38f7, 0x38f8, 0x38fa, 0x38fb, 0x38fd, 0x38ff,
+ 0x38e0, 0x38e0, 0x38e0, 0x38e0, 0x38e1, 0x38e1, 0x38e2, 0x38e2,
+ 0x38e3, 0x38e4, 0x38e5, 0x38e5, 0x38e6, 0x38e7, 0x38e8, 0x38e9,
+ 0x38ea, 0x38eb, 0x38ec, 0x38ee, 0x38ef, 0x38f0, 0x38f1, 0x38f3,
+ 0x38f4, 0x38f5, 0x38f7, 0x38f8, 0x38fa, 0x38fb, 0x38fd, 0x38ff,
+ 0x3900, 0x3900, 0x3900, 0x3900, 0x3901, 0x3901, 0x3902, 0x3902,
+ 0x3903, 0x3904, 0x3905, 0x3905, 0x3906, 0x3907, 0x3908, 0x3909,
+ 0x390a, 0x390b, 0x390c, 0x390e, 0x390f, 0x3910, 0x3911, 0x3913,
+ 0x3914, 0x3915, 0x3917, 0x3918, 0x391a, 0x391b, 0x391d, 0x391f,
+ 0x3920, 0x3920, 0x3920, 0x3920, 0x3921, 0x3921, 0x3922, 0x3922,
+ 0x3923, 0x3924, 0x3925, 0x3925, 0x3926, 0x3927, 0x3928, 0x3929,
+ 0x392a, 0x392b, 0x392c, 0x392e, 0x392f, 0x3930, 0x3931, 0x3933,
+ 0x3934, 0x3935, 0x3937, 0x3938, 0x393a, 0x393b, 0x393d, 0x393f,
+ 0x3940, 0x3940, 0x3940, 0x3940, 0x3941, 0x3941, 0x3942, 0x3942,
+ 0x3943, 0x3944, 0x3945, 0x3945, 0x3946, 0x3947, 0x3948, 0x3949,
+ 0x394a, 0x394b, 0x394c, 0x394e, 0x394f, 0x3950, 0x3951, 0x3953,
+ 0x3954, 0x3955, 0x3957, 0x3958, 0x395a, 0x395b, 0x395d, 0x395f,
+ 0x3940, 0x3940, 0x3940, 0x3940, 0x3941, 0x3941, 0x3942, 0x3942,
+ 0x3943, 0x3944, 0x3945, 0x3945, 0x3946, 0x3947, 0x3948, 0x3949,
+ 0x394a, 0x394b, 0x394c, 0x394e, 0x394f, 0x3950, 0x3951, 0x3953,
+ 0x3954, 0x3955, 0x3957, 0x3958, 0x395a, 0x395b, 0x395d, 0x395f,
+ 0x3960, 0x3960, 0x3960, 0x3960, 0x3961, 0x3961, 0x3962, 0x3962,
+ 0x3963, 0x3964, 0x3965, 0x3965, 0x3966, 0x3967, 0x3968, 0x3969,
+ 0x396a, 0x396b, 0x396c, 0x396e, 0x396f, 0x3970, 0x3971, 0x3973,
+ 0x3974, 0x3975, 0x3977, 0x3978, 0x397a, 0x397b, 0x397d, 0x397f,
+ 0x3980, 0x3980, 0x3980, 0x3980, 0x3981, 0x3981, 0x3982, 0x3982,
+ 0x3983, 0x3984, 0x3985, 0x3985, 0x3986, 0x3987, 0x3988, 0x3989,
+ 0x398a, 0x398b, 0x398c, 0x398e, 0x398f, 0x3990, 0x3991, 0x3993,
+ 0x3994, 0x3995, 0x3997, 0x3998, 0x399a, 0x399b, 0x399d, 0x399f,
+ 0x39a0, 0x39a0, 0x39a0, 0x39a0, 0x39a1, 0x39a1, 0x39a2, 0x39a2,
+ 0x39a3, 0x39a4, 0x39a5, 0x39a5, 0x39a6, 0x39a7, 0x39a8, 0x39a9,
+ 0x39aa, 0x39ab, 0x39ac, 0x39ae, 0x39af, 0x39b0, 0x39b1, 0x39b3,
+ 0x39b4, 0x39b5, 0x39b7, 0x39b8, 0x39ba, 0x39bb, 0x39bd, 0x39bf,
+ 0x39c0, 0x39c0, 0x39c0, 0x39c0, 0x39c1, 0x39c1, 0x39c2, 0x39c2,
+ 0x39c3, 0x39c4, 0x39c5, 0x39c5, 0x39c6, 0x39c7, 0x39c8, 0x39c9,
+ 0x39ca, 0x39cb, 0x39cc, 0x39ce, 0x39cf, 0x39d0, 0x39d1, 0x39d3,
+ 0x39d4, 0x39d5, 0x39d7, 0x39d8, 0x39da, 0x39db, 0x39dd, 0x39df,
+ 0x39e0, 0x39e0, 0x39e0, 0x39e0, 0x39e1, 0x39e1, 0x39e2, 0x39e2,
+ 0x39e3, 0x39e4, 0x39e5, 0x39e5, 0x39e6, 0x39e7, 0x39e8, 0x39e9,
+ 0x39ea, 0x39eb, 0x39ec, 0x39ee, 0x39ef, 0x39f0, 0x39f1, 0x39f3,
+ 0x39f4, 0x39f5, 0x39f7, 0x39f8, 0x39fa, 0x39fb, 0x39fd, 0x39ff,
+ 0x3a00, 0x3a00, 0x3a00, 0x3a00, 0x3a01, 0x3a01, 0x3a02, 0x3a02,
+ 0x3a03, 0x3a04, 0x3a05, 0x3a05, 0x3a06, 0x3a07, 0x3a08, 0x3a09,
+ 0x3a0a, 0x3a0b, 0x3a0c, 0x3a0e, 0x3a0f, 0x3a10, 0x3a11, 0x3a13,
+ 0x3a14, 0x3a15, 0x3a17, 0x3a18, 0x3a1a, 0x3a1b, 0x3a1d, 0x3a1f,
+ 0x3a20, 0x3a20, 0x3a20, 0x3a20, 0x3a21, 0x3a21, 0x3a22, 0x3a22,
+ 0x3a23, 0x3a24, 0x3a25, 0x3a25, 0x3a26, 0x3a27, 0x3a28, 0x3a29,
+ 0x3a2a, 0x3a2b, 0x3a2c, 0x3a2e, 0x3a2f, 0x3a30, 0x3a31, 0x3a33,
+ 0x3a34, 0x3a35, 0x3a37, 0x3a38, 0x3a3a, 0x3a3b, 0x3a3d, 0x3a3f,
+ 0x3a40, 0x3a40, 0x3a40, 0x3a40, 0x3a41, 0x3a41, 0x3a42, 0x3a42,
+ 0x3a43, 0x3a44, 0x3a45, 0x3a45, 0x3a46, 0x3a47, 0x3a48, 0x3a49,
+ 0x3a4a, 0x3a4b, 0x3a4c, 0x3a4e, 0x3a4f, 0x3a50, 0x3a51, 0x3a53,
+ 0x3a54, 0x3a55, 0x3a57, 0x3a58, 0x3a5a, 0x3a5b, 0x3a5d, 0x3a5f,
+ 0x3a60, 0x3a60, 0x3a60, 0x3a60, 0x3a61, 0x3a61, 0x3a62, 0x3a62,
+ 0x3a63, 0x3a64, 0x3a65, 0x3a65, 0x3a66, 0x3a67, 0x3a68, 0x3a69,
+ 0x3a6a, 0x3a6b, 0x3a6c, 0x3a6e, 0x3a6f, 0x3a70, 0x3a71, 0x3a73,
+ 0x3a74, 0x3a75, 0x3a77, 0x3a78, 0x3a7a, 0x3a7b, 0x3a7d, 0x3a7f,
+ 0x3a80, 0x3a80, 0x3a80, 0x3a80, 0x3a81, 0x3a81, 0x3a82, 0x3a82,
+ 0x3a83, 0x3a84, 0x3a85, 0x3a85, 0x3a86, 0x3a87, 0x3a88, 0x3a89,
+ 0x3a8a, 0x3a8b, 0x3a8c, 0x3a8e, 0x3a8f, 0x3a90, 0x3a91, 0x3a93,
+ 0x3a94, 0x3a95, 0x3a97, 0x3a98, 0x3a9a, 0x3a9b, 0x3a9d, 0x3a9f,
+ 0x3aa0, 0x3aa0, 0x3aa0, 0x3aa0, 0x3aa1, 0x3aa1, 0x3aa2, 0x3aa2,
+ 0x3aa3, 0x3aa4, 0x3aa5, 0x3aa5, 0x3aa6, 0x3aa7, 0x3aa8, 0x3aa9,
+ 0x3aaa, 0x3aab, 0x3aac, 0x3aae, 0x3aaf, 0x3ab0, 0x3ab1, 0x3ab3,
+ 0x3ab4, 0x3ab5, 0x3ab7, 0x3ab8, 0x3aba, 0x3abb, 0x3abd, 0x3abf,
+ 0x3ac0, 0x3ac0, 0x3ac0, 0x3ac0, 0x3ac1, 0x3ac1, 0x3ac2, 0x3ac2,
+ 0x3ac3, 0x3ac4, 0x3ac5, 0x3ac5, 0x3ac6, 0x3ac7, 0x3ac8, 0x3ac9,
+ 0x3aca, 0x3acb, 0x3acc, 0x3ace, 0x3acf, 0x3ad0, 0x3ad1, 0x3ad3,
+ 0x3ad4, 0x3ad5, 0x3ad7, 0x3ad8, 0x3ada, 0x3adb, 0x3add, 0x3adf,
+ 0x3ae0, 0x3ae0, 0x3ae0, 0x3ae0, 0x3ae1, 0x3ae1, 0x3ae2, 0x3ae2,
+ 0x3ae3, 0x3ae4, 0x3ae5, 0x3ae5, 0x3ae6, 0x3ae7, 0x3ae8, 0x3ae9,
+ 0x3aea, 0x3aeb, 0x3aec, 0x3aee, 0x3aef, 0x3af0, 0x3af1, 0x3af3,
+ 0x3af4, 0x3af5, 0x3af7, 0x3af8, 0x3afa, 0x3afb, 0x3afd, 0x3aff,
+ 0x3b00, 0x3b00, 0x3b00, 0x3b00, 0x3b01, 0x3b01, 0x3b02, 0x3b02,
+ 0x3b03, 0x3b04, 0x3b05, 0x3b05, 0x3b06, 0x3b07, 0x3b08, 0x3b09,
+ 0x3b0a, 0x3b0b, 0x3b0c, 0x3b0e, 0x3b0f, 0x3b10, 0x3b11, 0x3b13,
+ 0x3b14, 0x3b15, 0x3b17, 0x3b18, 0x3b1a, 0x3b1b, 0x3b1d, 0x3b1f,
+ 0x3b20, 0x3b20, 0x3b20, 0x3b20, 0x3b21, 0x3b21, 0x3b22, 0x3b22,
+ 0x3b23, 0x3b24, 0x3b25, 0x3b25, 0x3b26, 0x3b27, 0x3b28, 0x3b29,
+ 0x3b2a, 0x3b2b, 0x3b2c, 0x3b2e, 0x3b2f, 0x3b30, 0x3b31, 0x3b33,
+ 0x3b34, 0x3b35, 0x3b37, 0x3b38, 0x3b3a, 0x3b3b, 0x3b3d, 0x3b3f,
+ 0x3b40, 0x3b40, 0x3b40, 0x3b40, 0x3b41, 0x3b41, 0x3b42, 0x3b42,
+ 0x3b43, 0x3b44, 0x3b45, 0x3b45, 0x3b46, 0x3b47, 0x3b48, 0x3b49,
+ 0x3b4a, 0x3b4b, 0x3b4c, 0x3b4e, 0x3b4f, 0x3b50, 0x3b51, 0x3b53,
+ 0x3b54, 0x3b55, 0x3b57, 0x3b58, 0x3b5a, 0x3b5b, 0x3b5d, 0x3b5f,
+ 0x3b80, 0x3b80, 0x3b80, 0x3b80, 0x3b81, 0x3b81, 0x3b82, 0x3b82,
+ 0x3b83, 0x3b84, 0x3b85, 0x3b85, 0x3b86, 0x3b87, 0x3b88, 0x3b89,
+ 0x3b8a, 0x3b8b, 0x3b8c, 0x3b8e, 0x3b8f, 0x3b90, 0x3b91, 0x3b93,
+ 0x3b94, 0x3b95, 0x3b97, 0x3b98, 0x3b9a, 0x3b9b, 0x3b9d, 0x3b9f,
+ 0x3ba0, 0x3ba0, 0x3ba0, 0x3ba0, 0x3ba1, 0x3ba1, 0x3ba2, 0x3ba2,
+ 0x3ba3, 0x3ba4, 0x3ba5, 0x3ba5, 0x3ba6, 0x3ba7, 0x3ba8, 0x3ba9,
+ 0x3baa, 0x3bab, 0x3bac, 0x3bae, 0x3baf, 0x3bb0, 0x3bb1, 0x3bb3,
+ 0x3bb4, 0x3bb5, 0x3bb7, 0x3bb8, 0x3bba, 0x3bbb, 0x3bbd, 0x3bbf,
+ 0x3bc0, 0x3bc0, 0x3bc0, 0x3bc0, 0x3bc1, 0x3bc1, 0x3bc2, 0x3bc2,
+ 0x3bc3, 0x3bc4, 0x3bc5, 0x3bc5, 0x3bc6, 0x3bc7, 0x3bc8, 0x3bc9,
+ 0x3bca, 0x3bcb, 0x3bcc, 0x3bce, 0x3bcf, 0x3bd0, 0x3bd1, 0x3bd3,
+ 0x3bd4, 0x3bd5, 0x3bd7, 0x3bd8, 0x3bda, 0x3bdb, 0x3bdd, 0x3bdf,
+ 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be1, 0x3be1, 0x3be2, 0x3be2,
+ 0x3be3, 0x3be4, 0x3be5, 0x3be5, 0x3be6, 0x3be7, 0x3be8, 0x3be9,
+ 0x3bea, 0x3beb, 0x3bec, 0x3bee, 0x3bef, 0x3bf0, 0x3bf1, 0x3bf3,
+ 0x3bf4, 0x3bf5, 0x3bf7, 0x3bf8, 0x3bfa, 0x3bfb, 0x3bfd, 0x3bff,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c01, 0x3c01, 0x3c02, 0x3c02,
+ 0x3c03, 0x3c04, 0x3c05, 0x3c05, 0x3c06, 0x3c07, 0x3c08, 0x3c09,
+ 0x3c0a, 0x3c0b, 0x3c0c, 0x3c0e, 0x3c0f, 0x3c10, 0x3c11, 0x3c13,
+ 0x3c14, 0x3c15, 0x3c17, 0x3c18, 0x3c1a, 0x3c1b, 0x3c1d, 0x3c1f,
+ 0x3c40, 0x3c40, 0x3c40, 0x3c40, 0x3c41, 0x3c41, 0x3c42, 0x3c42,
+ 0x3c43, 0x3c44, 0x3c45, 0x3c45, 0x3c46, 0x3c47, 0x3c48, 0x3c49,
+ 0x3c4a, 0x3c4b, 0x3c4c, 0x3c4e, 0x3c4f, 0x3c50, 0x3c51, 0x3c53,
+ 0x3c54, 0x3c55, 0x3c57, 0x3c58, 0x3c5a, 0x3c5b, 0x3c5d, 0x3c5f,
+ 0x3c60, 0x3c60, 0x3c60, 0x3c60, 0x3c61, 0x3c61, 0x3c62, 0x3c62,
+ 0x3c63, 0x3c64, 0x3c65, 0x3c65, 0x3c66, 0x3c67, 0x3c68, 0x3c69,
+ 0x3c6a, 0x3c6b, 0x3c6c, 0x3c6e, 0x3c6f, 0x3c70, 0x3c71, 0x3c73,
+ 0x3c74, 0x3c75, 0x3c77, 0x3c78, 0x3c7a, 0x3c7b, 0x3c7d, 0x3c7f,
+ 0x3c80, 0x3c80, 0x3c80, 0x3c80, 0x3c81, 0x3c81, 0x3c82, 0x3c82,
+ 0x3c83, 0x3c84, 0x3c85, 0x3c85, 0x3c86, 0x3c87, 0x3c88, 0x3c89,
+ 0x3c8a, 0x3c8b, 0x3c8c, 0x3c8e, 0x3c8f, 0x3c90, 0x3c91, 0x3c93,
+ 0x3c94, 0x3c95, 0x3c97, 0x3c98, 0x3c9a, 0x3c9b, 0x3c9d, 0x3c9f,
+ 0x3cc0, 0x3cc0, 0x3cc0, 0x3cc0, 0x3cc1, 0x3cc1, 0x3cc2, 0x3cc2,
+ 0x3cc3, 0x3cc4, 0x3cc5, 0x3cc5, 0x3cc6, 0x3cc7, 0x3cc8, 0x3cc9,
+ 0x3cca, 0x3ccb, 0x3ccc, 0x3cce, 0x3ccf, 0x3cd0, 0x3cd1, 0x3cd3,
+ 0x3cd4, 0x3cd5, 0x3cd7, 0x3cd8, 0x3cda, 0x3cdb, 0x3cdd, 0x3cdf,
+ 0x3ce0, 0x3ce0, 0x3ce0, 0x3ce0, 0x3ce1, 0x3ce1, 0x3ce2, 0x3ce2,
+ 0x3ce3, 0x3ce4, 0x3ce5, 0x3ce5, 0x3ce6, 0x3ce7, 0x3ce8, 0x3ce9,
+ 0x3cea, 0x3ceb, 0x3cec, 0x3cee, 0x3cef, 0x3cf0, 0x3cf1, 0x3cf3,
+ 0x3cf4, 0x3cf5, 0x3cf7, 0x3cf8, 0x3cfa, 0x3cfb, 0x3cfd, 0x3cff,
+ 0x3d00, 0x3d00, 0x3d00, 0x3d00, 0x3d01, 0x3d01, 0x3d02, 0x3d02,
+ 0x3d03, 0x3d04, 0x3d05, 0x3d05, 0x3d06, 0x3d07, 0x3d08, 0x3d09,
+ 0x3d0a, 0x3d0b, 0x3d0c, 0x3d0e, 0x3d0f, 0x3d10, 0x3d11, 0x3d13,
+ 0x3d14, 0x3d15, 0x3d17, 0x3d18, 0x3d1a, 0x3d1b, 0x3d1d, 0x3d1f,
+ 0x3d40, 0x3d40, 0x3d40, 0x3d40, 0x3d41, 0x3d41, 0x3d42, 0x3d42,
+ 0x3d43, 0x3d44, 0x3d45, 0x3d45, 0x3d46, 0x3d47, 0x3d48, 0x3d49,
+ 0x3d4a, 0x3d4b, 0x3d4c, 0x3d4e, 0x3d4f, 0x3d50, 0x3d51, 0x3d53,
+ 0x3d54, 0x3d55, 0x3d57, 0x3d58, 0x3d5a, 0x3d5b, 0x3d5d, 0x3d5f,
+ 0x3d60, 0x3d60, 0x3d60, 0x3d60, 0x3d61, 0x3d61, 0x3d62, 0x3d62,
+ 0x3d63, 0x3d64, 0x3d65, 0x3d65, 0x3d66, 0x3d67, 0x3d68, 0x3d69,
+ 0x3d6a, 0x3d6b, 0x3d6c, 0x3d6e, 0x3d6f, 0x3d70, 0x3d71, 0x3d73,
+ 0x3d74, 0x3d75, 0x3d77, 0x3d78, 0x3d7a, 0x3d7b, 0x3d7d, 0x3d7f,
+ 0x3d80, 0x3d80, 0x3d80, 0x3d80, 0x3d81, 0x3d81, 0x3d82, 0x3d82,
+ 0x3d83, 0x3d84, 0x3d85, 0x3d85, 0x3d86, 0x3d87, 0x3d88, 0x3d89,
+ 0x3d8a, 0x3d8b, 0x3d8c, 0x3d8e, 0x3d8f, 0x3d90, 0x3d91, 0x3d93,
+ 0x3d94, 0x3d95, 0x3d97, 0x3d98, 0x3d9a, 0x3d9b, 0x3d9d, 0x3d9f,
+ 0x3dc0, 0x3dc0, 0x3dc0, 0x3dc0, 0x3dc1, 0x3dc1, 0x3dc2, 0x3dc2,
+ 0x3dc3, 0x3dc4, 0x3dc5, 0x3dc5, 0x3dc6, 0x3dc7, 0x3dc8, 0x3dc9,
+ 0x3dca, 0x3dcb, 0x3dcc, 0x3dce, 0x3dcf, 0x3dd0, 0x3dd1, 0x3dd3,
+ 0x3dd4, 0x3dd5, 0x3dd7, 0x3dd8, 0x3dda, 0x3ddb, 0x3ddd, 0x3ddf,
+ 0x3de0, 0x3de0, 0x3de0, 0x3de0, 0x3de1, 0x3de1, 0x3de2, 0x3de2,
+ 0x3de3, 0x3de4, 0x3de5, 0x3de5, 0x3de6, 0x3de7, 0x3de8, 0x3de9,
+ 0x3dea, 0x3deb, 0x3dec, 0x3dee, 0x3def, 0x3df0, 0x3df1, 0x3df3,
+ 0x3df4, 0x3df5, 0x3df7, 0x3df8, 0x3dfa, 0x3dfb, 0x3dfd, 0x3dff,
+ 0x3e20, 0x3e20, 0x3e20, 0x3e20, 0x3e21, 0x3e21, 0x3e22, 0x3e22,
+ 0x3e23, 0x3e24, 0x3e25, 0x3e25, 0x3e26, 0x3e27, 0x3e28, 0x3e29,
+ 0x3e2a, 0x3e2b, 0x3e2c, 0x3e2e, 0x3e2f, 0x3e30, 0x3e31, 0x3e33,
+ 0x3e34, 0x3e35, 0x3e37, 0x3e38, 0x3e3a, 0x3e3b, 0x3e3d, 0x3e3f,
+ 0x3e40, 0x3e40, 0x3e40, 0x3e40, 0x3e41, 0x3e41, 0x3e42, 0x3e42,
+ 0x3e43, 0x3e44, 0x3e45, 0x3e45, 0x3e46, 0x3e47, 0x3e48, 0x3e49,
+ 0x3e4a, 0x3e4b, 0x3e4c, 0x3e4e, 0x3e4f, 0x3e50, 0x3e51, 0x3e53,
+ 0x3e54, 0x3e55, 0x3e57, 0x3e58, 0x3e5a, 0x3e5b, 0x3e5d, 0x3e5f,
+ 0x3e80, 0x3e80, 0x3e80, 0x3e80, 0x3e81, 0x3e81, 0x3e82, 0x3e82,
+ 0x3e83, 0x3e84, 0x3e85, 0x3e85, 0x3e86, 0x3e87, 0x3e88, 0x3e89,
+ 0x3e8a, 0x3e8b, 0x3e8c, 0x3e8e, 0x3e8f, 0x3e90, 0x3e91, 0x3e93,
+ 0x3e94, 0x3e95, 0x3e97, 0x3e98, 0x3e9a, 0x3e9b, 0x3e9d, 0x3e9f,
+ 0x3ea0, 0x3ea0, 0x3ea0, 0x3ea0, 0x3ea1, 0x3ea1, 0x3ea2, 0x3ea2,
+ 0x3ea3, 0x3ea4, 0x3ea5, 0x3ea5, 0x3ea6, 0x3ea7, 0x3ea8, 0x3ea9,
+ 0x3eaa, 0x3eab, 0x3eac, 0x3eae, 0x3eaf, 0x3eb0, 0x3eb1, 0x3eb3,
+ 0x3eb4, 0x3eb5, 0x3eb7, 0x3eb8, 0x3eba, 0x3ebb, 0x3ebd, 0x3ebf,
+ 0x3ee0, 0x3ee0, 0x3ee0, 0x3ee0, 0x3ee1, 0x3ee1, 0x3ee2, 0x3ee2,
+ 0x3ee3, 0x3ee4, 0x3ee5, 0x3ee5, 0x3ee6, 0x3ee7, 0x3ee8, 0x3ee9,
+ 0x3eea, 0x3eeb, 0x3eec, 0x3eee, 0x3eef, 0x3ef0, 0x3ef1, 0x3ef3,
+ 0x3ef4, 0x3ef5, 0x3ef7, 0x3ef8, 0x3efa, 0x3efb, 0x3efd, 0x3eff,
+ 0x3f00, 0x3f00, 0x3f00, 0x3f00, 0x3f01, 0x3f01, 0x3f02, 0x3f02,
+ 0x3f03, 0x3f04, 0x3f05, 0x3f05, 0x3f06, 0x3f07, 0x3f08, 0x3f09,
+ 0x3f0a, 0x3f0b, 0x3f0c, 0x3f0e, 0x3f0f, 0x3f10, 0x3f11, 0x3f13,
+ 0x3f14, 0x3f15, 0x3f17, 0x3f18, 0x3f1a, 0x3f1b, 0x3f1d, 0x3f1f,
+ 0x3f40, 0x3f40, 0x3f40, 0x3f40, 0x3f41, 0x3f41, 0x3f42, 0x3f42,
+ 0x3f43, 0x3f44, 0x3f45, 0x3f45, 0x3f46, 0x3f47, 0x3f48, 0x3f49,
+ 0x3f4a, 0x3f4b, 0x3f4c, 0x3f4e, 0x3f4f, 0x3f50, 0x3f51, 0x3f53,
+ 0x3f54, 0x3f55, 0x3f57, 0x3f58, 0x3f5a, 0x3f5b, 0x3f5d, 0x3f5f,
+ 0x3f60, 0x3f60, 0x3f60, 0x3f60, 0x3f61, 0x3f61, 0x3f62, 0x3f62,
+ 0x3f63, 0x3f64, 0x3f65, 0x3f65, 0x3f66, 0x3f67, 0x3f68, 0x3f69,
+ 0x3f6a, 0x3f6b, 0x3f6c, 0x3f6e, 0x3f6f, 0x3f70, 0x3f71, 0x3f73,
+ 0x3f74, 0x3f75, 0x3f77, 0x3f78, 0x3f7a, 0x3f7b, 0x3f7d, 0x3f7f,
+ 0x3fa0, 0x3fa0, 0x3fa0, 0x3fa0, 0x3fa1, 0x3fa1, 0x3fa2, 0x3fa2,
+ 0x3fa3, 0x3fa4, 0x3fa5, 0x3fa5, 0x3fa6, 0x3fa7, 0x3fa8, 0x3fa9,
+ 0x3faa, 0x3fab, 0x3fac, 0x3fae, 0x3faf, 0x3fb0, 0x3fb1, 0x3fb3,
+ 0x3fb4, 0x3fb5, 0x3fb7, 0x3fb8, 0x3fba, 0x3fbb, 0x3fbd, 0x3fbf,
+ 0x3fe0, 0x3fe0, 0x3fe0, 0x3fe0, 0x3fe1, 0x3fe1, 0x3fe2, 0x3fe2,
+ 0x3fe3, 0x3fe4, 0x3fe5, 0x3fe5, 0x3fe6, 0x3fe7, 0x3fe8, 0x3fe9,
+ 0x3fea, 0x3feb, 0x3fec, 0x3fee, 0x3fef, 0x3ff0, 0x3ff1, 0x3ff3,
+ 0x3ff4, 0x3ff5, 0x3ff7, 0x3ff8, 0x3ffa, 0x3ffb, 0x3ffd, 0x3fff,
+ 0x4000, 0x4000, 0x4000, 0x4000, 0x4001, 0x4001, 0x4002, 0x4002,
+ 0x4003, 0x4004, 0x4005, 0x4005, 0x4006, 0x4007, 0x4008, 0x4009,
+ 0x400a, 0x400b, 0x400c, 0x400e, 0x400f, 0x4010, 0x4011, 0x4013,
+ 0x4014, 0x4015, 0x4017, 0x4018, 0x401a, 0x401b, 0x401d, 0x401f,
+ 0x4000, 0x4000, 0x4000, 0x4000, 0x4001, 0x4001, 0x4002, 0x4002,
+ 0x4003, 0x4004, 0x4005, 0x4005, 0x4006, 0x4007, 0x4008, 0x4009,
+ 0x400a, 0x400b, 0x400c, 0x400e, 0x400f, 0x4010, 0x4011, 0x4013,
+ 0x4014, 0x4015, 0x4017, 0x4018, 0x401a, 0x401b, 0x401d, 0x401f,
+ 0x4000, 0x4000, 0x4000, 0x4000, 0x4001, 0x4001, 0x4002, 0x4002,
+ 0x4003, 0x4004, 0x4005, 0x4005, 0x4006, 0x4007, 0x4008, 0x4009,
+ 0x400a, 0x400b, 0x400c, 0x400e, 0x400f, 0x4010, 0x4011, 0x4013,
+ 0x4014, 0x4015, 0x4017, 0x4018, 0x401a, 0x401b, 0x401d, 0x401f,
+ 0x4000, 0x4000, 0x4000, 0x4000, 0x4001, 0x4001, 0x4002, 0x4002,
+ 0x4003, 0x4004, 0x4005, 0x4005, 0x4006, 0x4007, 0x4008, 0x4009,
+ 0x400a, 0x400b, 0x400c, 0x400e, 0x400f, 0x4010, 0x4011, 0x4013,
+ 0x4014, 0x4015, 0x4017, 0x4018, 0x401a, 0x401b, 0x401d, 0x401f,
+ 0x4000, 0x4000, 0x4000, 0x4000, 0x4001, 0x4001, 0x4002, 0x4002,
+ 0x4003, 0x4004, 0x4005, 0x4005, 0x4006, 0x4007, 0x4008, 0x4009,
+ 0x400a, 0x400b, 0x400c, 0x400e, 0x400f, 0x4010, 0x4011, 0x4013,
+ 0x4014, 0x4015, 0x4017, 0x4018, 0x401a, 0x401b, 0x401d, 0x401f,
+ 0x4020, 0x4020, 0x4020, 0x4020, 0x4021, 0x4021, 0x4022, 0x4022,
+ 0x4023, 0x4024, 0x4025, 0x4025, 0x4026, 0x4027, 0x4028, 0x4029,
+ 0x402a, 0x402b, 0x402c, 0x402e, 0x402f, 0x4030, 0x4031, 0x4033,
+ 0x4034, 0x4035, 0x4037, 0x4038, 0x403a, 0x403b, 0x403d, 0x403f,
+ 0x4020, 0x4020, 0x4020, 0x4020, 0x4021, 0x4021, 0x4022, 0x4022,
+ 0x4023, 0x4024, 0x4025, 0x4025, 0x4026, 0x4027, 0x4028, 0x4029,
+ 0x402a, 0x402b, 0x402c, 0x402e, 0x402f, 0x4030, 0x4031, 0x4033,
+ 0x4034, 0x4035, 0x4037, 0x4038, 0x403a, 0x403b, 0x403d, 0x403f,
+ 0x4020, 0x4020, 0x4020, 0x4020, 0x4021, 0x4021, 0x4022, 0x4022,
+ 0x4023, 0x4024, 0x4025, 0x4025, 0x4026, 0x4027, 0x4028, 0x4029,
+ 0x402a, 0x402b, 0x402c, 0x402e, 0x402f, 0x4030, 0x4031, 0x4033,
+ 0x4034, 0x4035, 0x4037, 0x4038, 0x403a, 0x403b, 0x403d, 0x403f,
+ 0x4040, 0x4040, 0x4040, 0x4040, 0x4041, 0x4041, 0x4042, 0x4042,
+ 0x4043, 0x4044, 0x4045, 0x4045, 0x4046, 0x4047, 0x4048, 0x4049,
+ 0x404a, 0x404b, 0x404c, 0x404e, 0x404f, 0x4050, 0x4051, 0x4053,
+ 0x4054, 0x4055, 0x4057, 0x4058, 0x405a, 0x405b, 0x405d, 0x405f,
+ 0x4040, 0x4040, 0x4040, 0x4040, 0x4041, 0x4041, 0x4042, 0x4042,
+ 0x4043, 0x4044, 0x4045, 0x4045, 0x4046, 0x4047, 0x4048, 0x4049,
+ 0x404a, 0x404b, 0x404c, 0x404e, 0x404f, 0x4050, 0x4051, 0x4053,
+ 0x4054, 0x4055, 0x4057, 0x4058, 0x405a, 0x405b, 0x405d, 0x405f,
+ 0x4060, 0x4060, 0x4060, 0x4060, 0x4061, 0x4061, 0x4062, 0x4062,
+ 0x4063, 0x4064, 0x4065, 0x4065, 0x4066, 0x4067, 0x4068, 0x4069,
+ 0x406a, 0x406b, 0x406c, 0x406e, 0x406f, 0x4070, 0x4071, 0x4073,
+ 0x4074, 0x4075, 0x4077, 0x4078, 0x407a, 0x407b, 0x407d, 0x407f,
+ 0x4060, 0x4060, 0x4060, 0x4060, 0x4061, 0x4061, 0x4062, 0x4062,
+ 0x4063, 0x4064, 0x4065, 0x4065, 0x4066, 0x4067, 0x4068, 0x4069,
+ 0x406a, 0x406b, 0x406c, 0x406e, 0x406f, 0x4070, 0x4071, 0x4073,
+ 0x4074, 0x4075, 0x4077, 0x4078, 0x407a, 0x407b, 0x407d, 0x407f,
+ 0x4080, 0x4080, 0x4080, 0x4080, 0x4081, 0x4081, 0x4082, 0x4082,
+ 0x4083, 0x4084, 0x4085, 0x4085, 0x4086, 0x4087, 0x4088, 0x4089,
+ 0x408a, 0x408b, 0x408c, 0x408e, 0x408f, 0x4090, 0x4091, 0x4093,
+ 0x4094, 0x4095, 0x4097, 0x4098, 0x409a, 0x409b, 0x409d, 0x409f,
+ 0x40a0, 0x40a0, 0x40a0, 0x40a0, 0x40a1, 0x40a1, 0x40a2, 0x40a2,
+ 0x40a3, 0x40a4, 0x40a5, 0x40a5, 0x40a6, 0x40a7, 0x40a8, 0x40a9,
+ 0x40aa, 0x40ab, 0x40ac, 0x40ae, 0x40af, 0x40b0, 0x40b1, 0x40b3,
+ 0x40b4, 0x40b5, 0x40b7, 0x40b8, 0x40ba, 0x40bb, 0x40bd, 0x40bf,
+ 0x40a0, 0x40a0, 0x40a0, 0x40a0, 0x40a1, 0x40a1, 0x40a2, 0x40a2,
+ 0x40a3, 0x40a4, 0x40a5, 0x40a5, 0x40a6, 0x40a7, 0x40a8, 0x40a9,
+ 0x40aa, 0x40ab, 0x40ac, 0x40ae, 0x40af, 0x40b0, 0x40b1, 0x40b3,
+ 0x40b4, 0x40b5, 0x40b7, 0x40b8, 0x40ba, 0x40bb, 0x40bd, 0x40bf,
+ 0x40c0, 0x40c0, 0x40c0, 0x40c0, 0x40c1, 0x40c1, 0x40c2, 0x40c2,
+ 0x40c3, 0x40c4, 0x40c5, 0x40c5, 0x40c6, 0x40c7, 0x40c8, 0x40c9,
+ 0x40ca, 0x40cb, 0x40cc, 0x40ce, 0x40cf, 0x40d0, 0x40d1, 0x40d3,
+ 0x40d4, 0x40d5, 0x40d7, 0x40d8, 0x40da, 0x40db, 0x40dd, 0x40df,
+ 0x40e0, 0x40e0, 0x40e0, 0x40e0, 0x40e1, 0x40e1, 0x40e2, 0x40e2,
+ 0x40e3, 0x40e4, 0x40e5, 0x40e5, 0x40e6, 0x40e7, 0x40e8, 0x40e9,
+ 0x40ea, 0x40eb, 0x40ec, 0x40ee, 0x40ef, 0x40f0, 0x40f1, 0x40f3,
+ 0x40f4, 0x40f5, 0x40f7, 0x40f8, 0x40fa, 0x40fb, 0x40fd, 0x40ff,
+ 0x40e0, 0x40e0, 0x40e0, 0x40e0, 0x40e1, 0x40e1, 0x40e2, 0x40e2,
+ 0x40e3, 0x40e4, 0x40e5, 0x40e5, 0x40e6, 0x40e7, 0x40e8, 0x40e9,
+ 0x40ea, 0x40eb, 0x40ec, 0x40ee, 0x40ef, 0x40f0, 0x40f1, 0x40f3,
+ 0x40f4, 0x40f5, 0x40f7, 0x40f8, 0x40fa, 0x40fb, 0x40fd, 0x40ff,
+ 0x4100, 0x4100, 0x4100, 0x4100, 0x4101, 0x4101, 0x4102, 0x4102,
+ 0x4103, 0x4104, 0x4105, 0x4105, 0x4106, 0x4107, 0x4108, 0x4109,
+ 0x410a, 0x410b, 0x410c, 0x410e, 0x410f, 0x4110, 0x4111, 0x4113,
+ 0x4114, 0x4115, 0x4117, 0x4118, 0x411a, 0x411b, 0x411d, 0x411f,
+ 0x4120, 0x4120, 0x4120, 0x4120, 0x4121, 0x4121, 0x4122, 0x4122,
+ 0x4123, 0x4124, 0x4125, 0x4125, 0x4126, 0x4127, 0x4128, 0x4129,
+ 0x412a, 0x412b, 0x412c, 0x412e, 0x412f, 0x4130, 0x4131, 0x4133,
+ 0x4134, 0x4135, 0x4137, 0x4138, 0x413a, 0x413b, 0x413d, 0x413f,
+ 0x4140, 0x4140, 0x4140, 0x4140, 0x4141, 0x4141, 0x4142, 0x4142,
+ 0x4143, 0x4144, 0x4145, 0x4145, 0x4146, 0x4147, 0x4148, 0x4149,
+ 0x414a, 0x414b, 0x414c, 0x414e, 0x414f, 0x4150, 0x4151, 0x4153,
+ 0x4154, 0x4155, 0x4157, 0x4158, 0x415a, 0x415b, 0x415d, 0x415f,
+ 0x4140, 0x4140, 0x4140, 0x4140, 0x4141, 0x4141, 0x4142, 0x4142,
+ 0x4143, 0x4144, 0x4145, 0x4145, 0x4146, 0x4147, 0x4148, 0x4149,
+ 0x414a, 0x414b, 0x414c, 0x414e, 0x414f, 0x4150, 0x4151, 0x4153,
+ 0x4154, 0x4155, 0x4157, 0x4158, 0x415a, 0x415b, 0x415d, 0x415f,
+ 0x4160, 0x4160, 0x4160, 0x4160, 0x4161, 0x4161, 0x4162, 0x4162,
+ 0x4163, 0x4164, 0x4165, 0x4165, 0x4166, 0x4167, 0x4168, 0x4169,
+ 0x416a, 0x416b, 0x416c, 0x416e, 0x416f, 0x4170, 0x4171, 0x4173,
+ 0x4174, 0x4175, 0x4177, 0x4178, 0x417a, 0x417b, 0x417d, 0x417f,
+ 0x4180, 0x4180, 0x4180, 0x4180, 0x4181, 0x4181, 0x4182, 0x4182,
+ 0x4183, 0x4184, 0x4185, 0x4185, 0x4186, 0x4187, 0x4188, 0x4189,
+ 0x418a, 0x418b, 0x418c, 0x418e, 0x418f, 0x4190, 0x4191, 0x4193,
+ 0x4194, 0x4195, 0x4197, 0x4198, 0x419a, 0x419b, 0x419d, 0x419f,
+ 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a1, 0x41a1, 0x41a2, 0x41a2,
+ 0x41a3, 0x41a4, 0x41a5, 0x41a5, 0x41a6, 0x41a7, 0x41a8, 0x41a9,
+ 0x41aa, 0x41ab, 0x41ac, 0x41ae, 0x41af, 0x41b0, 0x41b1, 0x41b3,
+ 0x41b4, 0x41b5, 0x41b7, 0x41b8, 0x41ba, 0x41bb, 0x41bd, 0x41bf,
+ 0x41c0, 0x41c0, 0x41c0, 0x41c0, 0x41c1, 0x41c1, 0x41c2, 0x41c2,
+ 0x41c3, 0x41c4, 0x41c5, 0x41c5, 0x41c6, 0x41c7, 0x41c8, 0x41c9,
+ 0x41ca, 0x41cb, 0x41cc, 0x41ce, 0x41cf, 0x41d0, 0x41d1, 0x41d3,
+ 0x41d4, 0x41d5, 0x41d7, 0x41d8, 0x41da, 0x41db, 0x41dd, 0x41df,
+ 0x41e0, 0x41e0, 0x41e0, 0x41e0, 0x41e1, 0x41e1, 0x41e2, 0x41e2,
+ 0x41e3, 0x41e4, 0x41e5, 0x41e5, 0x41e6, 0x41e7, 0x41e8, 0x41e9,
+ 0x41ea, 0x41eb, 0x41ec, 0x41ee, 0x41ef, 0x41f0, 0x41f1, 0x41f3,
+ 0x41f4, 0x41f5, 0x41f7, 0x41f8, 0x41fa, 0x41fb, 0x41fd, 0x41ff,
+ 0x4200, 0x4200, 0x4200, 0x4200, 0x4201, 0x4201, 0x4202, 0x4202,
+ 0x4203, 0x4204, 0x4205, 0x4205, 0x4206, 0x4207, 0x4208, 0x4209,
+ 0x420a, 0x420b, 0x420c, 0x420e, 0x420f, 0x4210, 0x4211, 0x4213,
+ 0x4214, 0x4215, 0x4217, 0x4218, 0x421a, 0x421b, 0x421d, 0x421f,
+ 0x4220, 0x4220, 0x4220, 0x4220, 0x4221, 0x4221, 0x4222, 0x4222,
+ 0x4223, 0x4224, 0x4225, 0x4225, 0x4226, 0x4227, 0x4228, 0x4229,
+ 0x422a, 0x422b, 0x422c, 0x422e, 0x422f, 0x4230, 0x4231, 0x4233,
+ 0x4234, 0x4235, 0x4237, 0x4238, 0x423a, 0x423b, 0x423d, 0x423f,
+ 0x4240, 0x4240, 0x4240, 0x4240, 0x4241, 0x4241, 0x4242, 0x4242,
+ 0x4243, 0x4244, 0x4245, 0x4245, 0x4246, 0x4247, 0x4248, 0x4249,
+ 0x424a, 0x424b, 0x424c, 0x424e, 0x424f, 0x4250, 0x4251, 0x4253,
+ 0x4254, 0x4255, 0x4257, 0x4258, 0x425a, 0x425b, 0x425d, 0x425f,
+ 0x4260, 0x4260, 0x4260, 0x4260, 0x4261, 0x4261, 0x4262, 0x4262,
+ 0x4263, 0x4264, 0x4265, 0x4265, 0x4266, 0x4267, 0x4268, 0x4269,
+ 0x426a, 0x426b, 0x426c, 0x426e, 0x426f, 0x4270, 0x4271, 0x4273,
+ 0x4274, 0x4275, 0x4277, 0x4278, 0x427a, 0x427b, 0x427d, 0x427f,
+ 0x4280, 0x4280, 0x4280, 0x4280, 0x4281, 0x4281, 0x4282, 0x4282,
+ 0x4283, 0x4284, 0x4285, 0x4285, 0x4286, 0x4287, 0x4288, 0x4289,
+ 0x428a, 0x428b, 0x428c, 0x428e, 0x428f, 0x4290, 0x4291, 0x4293,
+ 0x4294, 0x4295, 0x4297, 0x4298, 0x429a, 0x429b, 0x429d, 0x429f,
+ 0x42a0, 0x42a0, 0x42a0, 0x42a0, 0x42a1, 0x42a1, 0x42a2, 0x42a2,
+ 0x42a3, 0x42a4, 0x42a5, 0x42a5, 0x42a6, 0x42a7, 0x42a8, 0x42a9,
+ 0x42aa, 0x42ab, 0x42ac, 0x42ae, 0x42af, 0x42b0, 0x42b1, 0x42b3,
+ 0x42b4, 0x42b5, 0x42b7, 0x42b8, 0x42ba, 0x42bb, 0x42bd, 0x42bf,
+ 0x42c0, 0x42c0, 0x42c0, 0x42c0, 0x42c1, 0x42c1, 0x42c2, 0x42c2,
+ 0x42c3, 0x42c4, 0x42c5, 0x42c5, 0x42c6, 0x42c7, 0x42c8, 0x42c9,
+ 0x42ca, 0x42cb, 0x42cc, 0x42ce, 0x42cf, 0x42d0, 0x42d1, 0x42d3,
+ 0x42d4, 0x42d5, 0x42d7, 0x42d8, 0x42da, 0x42db, 0x42dd, 0x42df,
+ 0x42e0, 0x42e0, 0x42e0, 0x42e0, 0x42e1, 0x42e1, 0x42e2, 0x42e2,
+ 0x42e3, 0x42e4, 0x42e5, 0x42e5, 0x42e6, 0x42e7, 0x42e8, 0x42e9,
+ 0x42ea, 0x42eb, 0x42ec, 0x42ee, 0x42ef, 0x42f0, 0x42f1, 0x42f3,
+ 0x42f4, 0x42f5, 0x42f7, 0x42f8, 0x42fa, 0x42fb, 0x42fd, 0x42ff,
+ 0x4300, 0x4300, 0x4300, 0x4300, 0x4301, 0x4301, 0x4302, 0x4302,
+ 0x4303, 0x4304, 0x4305, 0x4305, 0x4306, 0x4307, 0x4308, 0x4309,
+ 0x430a, 0x430b, 0x430c, 0x430e, 0x430f, 0x4310, 0x4311, 0x4313,
+ 0x4314, 0x4315, 0x4317, 0x4318, 0x431a, 0x431b, 0x431d, 0x431f,
+ 0x4320, 0x4320, 0x4320, 0x4320, 0x4321, 0x4321, 0x4322, 0x4322,
+ 0x4323, 0x4324, 0x4325, 0x4325, 0x4326, 0x4327, 0x4328, 0x4329,
+ 0x432a, 0x432b, 0x432c, 0x432e, 0x432f, 0x4330, 0x4331, 0x4333,
+ 0x4334, 0x4335, 0x4337, 0x4338, 0x433a, 0x433b, 0x433d, 0x433f,
+ 0x4340, 0x4340, 0x4340, 0x4340, 0x4341, 0x4341, 0x4342, 0x4342,
+ 0x4343, 0x4344, 0x4345, 0x4345, 0x4346, 0x4347, 0x4348, 0x4349,
+ 0x434a, 0x434b, 0x434c, 0x434e, 0x434f, 0x4350, 0x4351, 0x4353,
+ 0x4354, 0x4355, 0x4357, 0x4358, 0x435a, 0x435b, 0x435d, 0x435f,
+ 0x4380, 0x4380, 0x4380, 0x4380, 0x4381, 0x4381, 0x4382, 0x4382,
+ 0x4383, 0x4384, 0x4385, 0x4385, 0x4386, 0x4387, 0x4388, 0x4389,
+ 0x438a, 0x438b, 0x438c, 0x438e, 0x438f, 0x4390, 0x4391, 0x4393,
+ 0x4394, 0x4395, 0x4397, 0x4398, 0x439a, 0x439b, 0x439d, 0x439f,
+ 0x43a0, 0x43a0, 0x43a0, 0x43a0, 0x43a1, 0x43a1, 0x43a2, 0x43a2,
+ 0x43a3, 0x43a4, 0x43a5, 0x43a5, 0x43a6, 0x43a7, 0x43a8, 0x43a9,
+ 0x43aa, 0x43ab, 0x43ac, 0x43ae, 0x43af, 0x43b0, 0x43b1, 0x43b3,
+ 0x43b4, 0x43b5, 0x43b7, 0x43b8, 0x43ba, 0x43bb, 0x43bd, 0x43bf,
+ 0x43c0, 0x43c0, 0x43c0, 0x43c0, 0x43c1, 0x43c1, 0x43c2, 0x43c2,
+ 0x43c3, 0x43c4, 0x43c5, 0x43c5, 0x43c6, 0x43c7, 0x43c8, 0x43c9,
+ 0x43ca, 0x43cb, 0x43cc, 0x43ce, 0x43cf, 0x43d0, 0x43d1, 0x43d3,
+ 0x43d4, 0x43d5, 0x43d7, 0x43d8, 0x43da, 0x43db, 0x43dd, 0x43df,
+ 0x43e0, 0x43e0, 0x43e0, 0x43e0, 0x43e1, 0x43e1, 0x43e2, 0x43e2,
+ 0x43e3, 0x43e4, 0x43e5, 0x43e5, 0x43e6, 0x43e7, 0x43e8, 0x43e9,
+ 0x43ea, 0x43eb, 0x43ec, 0x43ee, 0x43ef, 0x43f0, 0x43f1, 0x43f3,
+ 0x43f4, 0x43f5, 0x43f7, 0x43f8, 0x43fa, 0x43fb, 0x43fd, 0x43ff,
+ 0x4400, 0x4400, 0x4400, 0x4400, 0x4401, 0x4401, 0x4402, 0x4402,
+ 0x4403, 0x4404, 0x4405, 0x4405, 0x4406, 0x4407, 0x4408, 0x4409,
+ 0x440a, 0x440b, 0x440c, 0x440e, 0x440f, 0x4410, 0x4411, 0x4413,
+ 0x4414, 0x4415, 0x4417, 0x4418, 0x441a, 0x441b, 0x441d, 0x441f,
+ 0x4440, 0x4440, 0x4440, 0x4440, 0x4441, 0x4441, 0x4442, 0x4442,
+ 0x4443, 0x4444, 0x4445, 0x4445, 0x4446, 0x4447, 0x4448, 0x4449,
+ 0x444a, 0x444b, 0x444c, 0x444e, 0x444f, 0x4450, 0x4451, 0x4453,
+ 0x4454, 0x4455, 0x4457, 0x4458, 0x445a, 0x445b, 0x445d, 0x445f,
+ 0x4460, 0x4460, 0x4460, 0x4460, 0x4461, 0x4461, 0x4462, 0x4462,
+ 0x4463, 0x4464, 0x4465, 0x4465, 0x4466, 0x4467, 0x4468, 0x4469,
+ 0x446a, 0x446b, 0x446c, 0x446e, 0x446f, 0x4470, 0x4471, 0x4473,
+ 0x4474, 0x4475, 0x4477, 0x4478, 0x447a, 0x447b, 0x447d, 0x447f,
+ 0x4480, 0x4480, 0x4480, 0x4480, 0x4481, 0x4481, 0x4482, 0x4482,
+ 0x4483, 0x4484, 0x4485, 0x4485, 0x4486, 0x4487, 0x4488, 0x4489,
+ 0x448a, 0x448b, 0x448c, 0x448e, 0x448f, 0x4490, 0x4491, 0x4493,
+ 0x4494, 0x4495, 0x4497, 0x4498, 0x449a, 0x449b, 0x449d, 0x449f,
+ 0x44c0, 0x44c0, 0x44c0, 0x44c0, 0x44c1, 0x44c1, 0x44c2, 0x44c2,
+ 0x44c3, 0x44c4, 0x44c5, 0x44c5, 0x44c6, 0x44c7, 0x44c8, 0x44c9,
+ 0x44ca, 0x44cb, 0x44cc, 0x44ce, 0x44cf, 0x44d0, 0x44d1, 0x44d3,
+ 0x44d4, 0x44d5, 0x44d7, 0x44d8, 0x44da, 0x44db, 0x44dd, 0x44df,
+ 0x44e0, 0x44e0, 0x44e0, 0x44e0, 0x44e1, 0x44e1, 0x44e2, 0x44e2,
+ 0x44e3, 0x44e4, 0x44e5, 0x44e5, 0x44e6, 0x44e7, 0x44e8, 0x44e9,
+ 0x44ea, 0x44eb, 0x44ec, 0x44ee, 0x44ef, 0x44f0, 0x44f1, 0x44f3,
+ 0x44f4, 0x44f5, 0x44f7, 0x44f8, 0x44fa, 0x44fb, 0x44fd, 0x44ff,
+ 0x4500, 0x4500, 0x4500, 0x4500, 0x4501, 0x4501, 0x4502, 0x4502,
+ 0x4503, 0x4504, 0x4505, 0x4505, 0x4506, 0x4507, 0x4508, 0x4509,
+ 0x450a, 0x450b, 0x450c, 0x450e, 0x450f, 0x4510, 0x4511, 0x4513,
+ 0x4514, 0x4515, 0x4517, 0x4518, 0x451a, 0x451b, 0x451d, 0x451f,
+ 0x4540, 0x4540, 0x4540, 0x4540, 0x4541, 0x4541, 0x4542, 0x4542,
+ 0x4543, 0x4544, 0x4545, 0x4545, 0x4546, 0x4547, 0x4548, 0x4549,
+ 0x454a, 0x454b, 0x454c, 0x454e, 0x454f, 0x4550, 0x4551, 0x4553,
+ 0x4554, 0x4555, 0x4557, 0x4558, 0x455a, 0x455b, 0x455d, 0x455f,
+ 0x4560, 0x4560, 0x4560, 0x4560, 0x4561, 0x4561, 0x4562, 0x4562,
+ 0x4563, 0x4564, 0x4565, 0x4565, 0x4566, 0x4567, 0x4568, 0x4569,
+ 0x456a, 0x456b, 0x456c, 0x456e, 0x456f, 0x4570, 0x4571, 0x4573,
+ 0x4574, 0x4575, 0x4577, 0x4578, 0x457a, 0x457b, 0x457d, 0x457f,
+ 0x4580, 0x4580, 0x4580, 0x4580, 0x4581, 0x4581, 0x4582, 0x4582,
+ 0x4583, 0x4584, 0x4585, 0x4585, 0x4586, 0x4587, 0x4588, 0x4589,
+ 0x458a, 0x458b, 0x458c, 0x458e, 0x458f, 0x4590, 0x4591, 0x4593,
+ 0x4594, 0x4595, 0x4597, 0x4598, 0x459a, 0x459b, 0x459d, 0x459f,
+ 0x45c0, 0x45c0, 0x45c0, 0x45c0, 0x45c1, 0x45c1, 0x45c2, 0x45c2,
+ 0x45c3, 0x45c4, 0x45c5, 0x45c5, 0x45c6, 0x45c7, 0x45c8, 0x45c9,
+ 0x45ca, 0x45cb, 0x45cc, 0x45ce, 0x45cf, 0x45d0, 0x45d1, 0x45d3,
+ 0x45d4, 0x45d5, 0x45d7, 0x45d8, 0x45da, 0x45db, 0x45dd, 0x45df,
+ 0x45e0, 0x45e0, 0x45e0, 0x45e0, 0x45e1, 0x45e1, 0x45e2, 0x45e2,
+ 0x45e3, 0x45e4, 0x45e5, 0x45e5, 0x45e6, 0x45e7, 0x45e8, 0x45e9,
+ 0x45ea, 0x45eb, 0x45ec, 0x45ee, 0x45ef, 0x45f0, 0x45f1, 0x45f3,
+ 0x45f4, 0x45f5, 0x45f7, 0x45f8, 0x45fa, 0x45fb, 0x45fd, 0x45ff,
+ 0x4620, 0x4620, 0x4620, 0x4620, 0x4621, 0x4621, 0x4622, 0x4622,
+ 0x4623, 0x4624, 0x4625, 0x4625, 0x4626, 0x4627, 0x4628, 0x4629,
+ 0x462a, 0x462b, 0x462c, 0x462e, 0x462f, 0x4630, 0x4631, 0x4633,
+ 0x4634, 0x4635, 0x4637, 0x4638, 0x463a, 0x463b, 0x463d, 0x463f,
+ 0x4640, 0x4640, 0x4640, 0x4640, 0x4641, 0x4641, 0x4642, 0x4642,
+ 0x4643, 0x4644, 0x4645, 0x4645, 0x4646, 0x4647, 0x4648, 0x4649,
+ 0x464a, 0x464b, 0x464c, 0x464e, 0x464f, 0x4650, 0x4651, 0x4653,
+ 0x4654, 0x4655, 0x4657, 0x4658, 0x465a, 0x465b, 0x465d, 0x465f,
+ 0x4680, 0x4680, 0x4680, 0x4680, 0x4681, 0x4681, 0x4682, 0x4682,
+ 0x4683, 0x4684, 0x4685, 0x4685, 0x4686, 0x4687, 0x4688, 0x4689,
+ 0x468a, 0x468b, 0x468c, 0x468e, 0x468f, 0x4690, 0x4691, 0x4693,
+ 0x4694, 0x4695, 0x4697, 0x4698, 0x469a, 0x469b, 0x469d, 0x469f,
+ 0x46a0, 0x46a0, 0x46a0, 0x46a0, 0x46a1, 0x46a1, 0x46a2, 0x46a2,
+ 0x46a3, 0x46a4, 0x46a5, 0x46a5, 0x46a6, 0x46a7, 0x46a8, 0x46a9,
+ 0x46aa, 0x46ab, 0x46ac, 0x46ae, 0x46af, 0x46b0, 0x46b1, 0x46b3,
+ 0x46b4, 0x46b5, 0x46b7, 0x46b8, 0x46ba, 0x46bb, 0x46bd, 0x46bf,
+ 0x46e0, 0x46e0, 0x46e0, 0x46e0, 0x46e1, 0x46e1, 0x46e2, 0x46e2,
+ 0x46e3, 0x46e4, 0x46e5, 0x46e5, 0x46e6, 0x46e7, 0x46e8, 0x46e9,
+ 0x46ea, 0x46eb, 0x46ec, 0x46ee, 0x46ef, 0x46f0, 0x46f1, 0x46f3,
+ 0x46f4, 0x46f5, 0x46f7, 0x46f8, 0x46fa, 0x46fb, 0x46fd, 0x46ff,
+ 0x4700, 0x4700, 0x4700, 0x4700, 0x4701, 0x4701, 0x4702, 0x4702,
+ 0x4703, 0x4704, 0x4705, 0x4705, 0x4706, 0x4707, 0x4708, 0x4709,
+ 0x470a, 0x470b, 0x470c, 0x470e, 0x470f, 0x4710, 0x4711, 0x4713,
+ 0x4714, 0x4715, 0x4717, 0x4718, 0x471a, 0x471b, 0x471d, 0x471f,
+ 0x4740, 0x4740, 0x4740, 0x4740, 0x4741, 0x4741, 0x4742, 0x4742,
+ 0x4743, 0x4744, 0x4745, 0x4745, 0x4746, 0x4747, 0x4748, 0x4749,
+ 0x474a, 0x474b, 0x474c, 0x474e, 0x474f, 0x4750, 0x4751, 0x4753,
+ 0x4754, 0x4755, 0x4757, 0x4758, 0x475a, 0x475b, 0x475d, 0x475f,
+ 0x4760, 0x4760, 0x4760, 0x4760, 0x4761, 0x4761, 0x4762, 0x4762,
+ 0x4763, 0x4764, 0x4765, 0x4765, 0x4766, 0x4767, 0x4768, 0x4769,
+ 0x476a, 0x476b, 0x476c, 0x476e, 0x476f, 0x4770, 0x4771, 0x4773,
+ 0x4774, 0x4775, 0x4777, 0x4778, 0x477a, 0x477b, 0x477d, 0x477f,
+ 0x47a0, 0x47a0, 0x47a0, 0x47a0, 0x47a1, 0x47a1, 0x47a2, 0x47a2,
+ 0x47a3, 0x47a4, 0x47a5, 0x47a5, 0x47a6, 0x47a7, 0x47a8, 0x47a9,
+ 0x47aa, 0x47ab, 0x47ac, 0x47ae, 0x47af, 0x47b0, 0x47b1, 0x47b3,
+ 0x47b4, 0x47b5, 0x47b7, 0x47b8, 0x47ba, 0x47bb, 0x47bd, 0x47bf,
+ 0x47e0, 0x47e0, 0x47e0, 0x47e0, 0x47e1, 0x47e1, 0x47e2, 0x47e2,
+ 0x47e3, 0x47e4, 0x47e5, 0x47e5, 0x47e6, 0x47e7, 0x47e8, 0x47e9,
+ 0x47ea, 0x47eb, 0x47ec, 0x47ee, 0x47ef, 0x47f0, 0x47f1, 0x47f3,
+ 0x47f4, 0x47f5, 0x47f7, 0x47f8, 0x47fa, 0x47fb, 0x47fd, 0x47ff,
+ 0x4800, 0x4800, 0x4800, 0x4800, 0x4801, 0x4801, 0x4802, 0x4802,
+ 0x4803, 0x4804, 0x4805, 0x4805, 0x4806, 0x4807, 0x4808, 0x4809,
+ 0x480a, 0x480b, 0x480c, 0x480e, 0x480f, 0x4810, 0x4811, 0x4813,
+ 0x4814, 0x4815, 0x4817, 0x4818, 0x481a, 0x481b, 0x481d, 0x481f,
+ 0x4800, 0x4800, 0x4800, 0x4800, 0x4801, 0x4801, 0x4802, 0x4802,
+ 0x4803, 0x4804, 0x4805, 0x4805, 0x4806, 0x4807, 0x4808, 0x4809,
+ 0x480a, 0x480b, 0x480c, 0x480e, 0x480f, 0x4810, 0x4811, 0x4813,
+ 0x4814, 0x4815, 0x4817, 0x4818, 0x481a, 0x481b, 0x481d, 0x481f,
+ 0x4800, 0x4800, 0x4800, 0x4800, 0x4801, 0x4801, 0x4802, 0x4802,
+ 0x4803, 0x4804, 0x4805, 0x4805, 0x4806, 0x4807, 0x4808, 0x4809,
+ 0x480a, 0x480b, 0x480c, 0x480e, 0x480f, 0x4810, 0x4811, 0x4813,
+ 0x4814, 0x4815, 0x4817, 0x4818, 0x481a, 0x481b, 0x481d, 0x481f,
+ 0x4800, 0x4800, 0x4800, 0x4800, 0x4801, 0x4801, 0x4802, 0x4802,
+ 0x4803, 0x4804, 0x4805, 0x4805, 0x4806, 0x4807, 0x4808, 0x4809,
+ 0x480a, 0x480b, 0x480c, 0x480e, 0x480f, 0x4810, 0x4811, 0x4813,
+ 0x4814, 0x4815, 0x4817, 0x4818, 0x481a, 0x481b, 0x481d, 0x481f,
+ 0x4800, 0x4800, 0x4800, 0x4800, 0x4801, 0x4801, 0x4802, 0x4802,
+ 0x4803, 0x4804, 0x4805, 0x4805, 0x4806, 0x4807, 0x4808, 0x4809,
+ 0x480a, 0x480b, 0x480c, 0x480e, 0x480f, 0x4810, 0x4811, 0x4813,
+ 0x4814, 0x4815, 0x4817, 0x4818, 0x481a, 0x481b, 0x481d, 0x481f,
+ 0x4820, 0x4820, 0x4820, 0x4820, 0x4821, 0x4821, 0x4822, 0x4822,
+ 0x4823, 0x4824, 0x4825, 0x4825, 0x4826, 0x4827, 0x4828, 0x4829,
+ 0x482a, 0x482b, 0x482c, 0x482e, 0x482f, 0x4830, 0x4831, 0x4833,
+ 0x4834, 0x4835, 0x4837, 0x4838, 0x483a, 0x483b, 0x483d, 0x483f,
+ 0x4820, 0x4820, 0x4820, 0x4820, 0x4821, 0x4821, 0x4822, 0x4822,
+ 0x4823, 0x4824, 0x4825, 0x4825, 0x4826, 0x4827, 0x4828, 0x4829,
+ 0x482a, 0x482b, 0x482c, 0x482e, 0x482f, 0x4830, 0x4831, 0x4833,
+ 0x4834, 0x4835, 0x4837, 0x4838, 0x483a, 0x483b, 0x483d, 0x483f,
+ 0x4820, 0x4820, 0x4820, 0x4820, 0x4821, 0x4821, 0x4822, 0x4822,
+ 0x4823, 0x4824, 0x4825, 0x4825, 0x4826, 0x4827, 0x4828, 0x4829,
+ 0x482a, 0x482b, 0x482c, 0x482e, 0x482f, 0x4830, 0x4831, 0x4833,
+ 0x4834, 0x4835, 0x4837, 0x4838, 0x483a, 0x483b, 0x483d, 0x483f,
+ 0x4840, 0x4840, 0x4840, 0x4840, 0x4841, 0x4841, 0x4842, 0x4842,
+ 0x4843, 0x4844, 0x4845, 0x4845, 0x4846, 0x4847, 0x4848, 0x4849,
+ 0x484a, 0x484b, 0x484c, 0x484e, 0x484f, 0x4850, 0x4851, 0x4853,
+ 0x4854, 0x4855, 0x4857, 0x4858, 0x485a, 0x485b, 0x485d, 0x485f,
+ 0x4840, 0x4840, 0x4840, 0x4840, 0x4841, 0x4841, 0x4842, 0x4842,
+ 0x4843, 0x4844, 0x4845, 0x4845, 0x4846, 0x4847, 0x4848, 0x4849,
+ 0x484a, 0x484b, 0x484c, 0x484e, 0x484f, 0x4850, 0x4851, 0x4853,
+ 0x4854, 0x4855, 0x4857, 0x4858, 0x485a, 0x485b, 0x485d, 0x485f,
+ 0x4860, 0x4860, 0x4860, 0x4860, 0x4861, 0x4861, 0x4862, 0x4862,
+ 0x4863, 0x4864, 0x4865, 0x4865, 0x4866, 0x4867, 0x4868, 0x4869,
+ 0x486a, 0x486b, 0x486c, 0x486e, 0x486f, 0x4870, 0x4871, 0x4873,
+ 0x4874, 0x4875, 0x4877, 0x4878, 0x487a, 0x487b, 0x487d, 0x487f,
+ 0x4860, 0x4860, 0x4860, 0x4860, 0x4861, 0x4861, 0x4862, 0x4862,
+ 0x4863, 0x4864, 0x4865, 0x4865, 0x4866, 0x4867, 0x4868, 0x4869,
+ 0x486a, 0x486b, 0x486c, 0x486e, 0x486f, 0x4870, 0x4871, 0x4873,
+ 0x4874, 0x4875, 0x4877, 0x4878, 0x487a, 0x487b, 0x487d, 0x487f,
+ 0x4880, 0x4880, 0x4880, 0x4880, 0x4881, 0x4881, 0x4882, 0x4882,
+ 0x4883, 0x4884, 0x4885, 0x4885, 0x4886, 0x4887, 0x4888, 0x4889,
+ 0x488a, 0x488b, 0x488c, 0x488e, 0x488f, 0x4890, 0x4891, 0x4893,
+ 0x4894, 0x4895, 0x4897, 0x4898, 0x489a, 0x489b, 0x489d, 0x489f,
+ 0x48a0, 0x48a0, 0x48a0, 0x48a0, 0x48a1, 0x48a1, 0x48a2, 0x48a2,
+ 0x48a3, 0x48a4, 0x48a5, 0x48a5, 0x48a6, 0x48a7, 0x48a8, 0x48a9,
+ 0x48aa, 0x48ab, 0x48ac, 0x48ae, 0x48af, 0x48b0, 0x48b1, 0x48b3,
+ 0x48b4, 0x48b5, 0x48b7, 0x48b8, 0x48ba, 0x48bb, 0x48bd, 0x48bf,
+ 0x48a0, 0x48a0, 0x48a0, 0x48a0, 0x48a1, 0x48a1, 0x48a2, 0x48a2,
+ 0x48a3, 0x48a4, 0x48a5, 0x48a5, 0x48a6, 0x48a7, 0x48a8, 0x48a9,
+ 0x48aa, 0x48ab, 0x48ac, 0x48ae, 0x48af, 0x48b0, 0x48b1, 0x48b3,
+ 0x48b4, 0x48b5, 0x48b7, 0x48b8, 0x48ba, 0x48bb, 0x48bd, 0x48bf,
+ 0x48c0, 0x48c0, 0x48c0, 0x48c0, 0x48c1, 0x48c1, 0x48c2, 0x48c2,
+ 0x48c3, 0x48c4, 0x48c5, 0x48c5, 0x48c6, 0x48c7, 0x48c8, 0x48c9,
+ 0x48ca, 0x48cb, 0x48cc, 0x48ce, 0x48cf, 0x48d0, 0x48d1, 0x48d3,
+ 0x48d4, 0x48d5, 0x48d7, 0x48d8, 0x48da, 0x48db, 0x48dd, 0x48df,
+ 0x48e0, 0x48e0, 0x48e0, 0x48e0, 0x48e1, 0x48e1, 0x48e2, 0x48e2,
+ 0x48e3, 0x48e4, 0x48e5, 0x48e5, 0x48e6, 0x48e7, 0x48e8, 0x48e9,
+ 0x48ea, 0x48eb, 0x48ec, 0x48ee, 0x48ef, 0x48f0, 0x48f1, 0x48f3,
+ 0x48f4, 0x48f5, 0x48f7, 0x48f8, 0x48fa, 0x48fb, 0x48fd, 0x48ff,
+ 0x48e0, 0x48e0, 0x48e0, 0x48e0, 0x48e1, 0x48e1, 0x48e2, 0x48e2,
+ 0x48e3, 0x48e4, 0x48e5, 0x48e5, 0x48e6, 0x48e7, 0x48e8, 0x48e9,
+ 0x48ea, 0x48eb, 0x48ec, 0x48ee, 0x48ef, 0x48f0, 0x48f1, 0x48f3,
+ 0x48f4, 0x48f5, 0x48f7, 0x48f8, 0x48fa, 0x48fb, 0x48fd, 0x48ff,
+ 0x4900, 0x4900, 0x4900, 0x4900, 0x4901, 0x4901, 0x4902, 0x4902,
+ 0x4903, 0x4904, 0x4905, 0x4905, 0x4906, 0x4907, 0x4908, 0x4909,
+ 0x490a, 0x490b, 0x490c, 0x490e, 0x490f, 0x4910, 0x4911, 0x4913,
+ 0x4914, 0x4915, 0x4917, 0x4918, 0x491a, 0x491b, 0x491d, 0x491f,
+ 0x4920, 0x4920, 0x4920, 0x4920, 0x4921, 0x4921, 0x4922, 0x4922,
+ 0x4923, 0x4924, 0x4925, 0x4925, 0x4926, 0x4927, 0x4928, 0x4929,
+ 0x492a, 0x492b, 0x492c, 0x492e, 0x492f, 0x4930, 0x4931, 0x4933,
+ 0x4934, 0x4935, 0x4937, 0x4938, 0x493a, 0x493b, 0x493d, 0x493f,
+ 0x4940, 0x4940, 0x4940, 0x4940, 0x4941, 0x4941, 0x4942, 0x4942,
+ 0x4943, 0x4944, 0x4945, 0x4945, 0x4946, 0x4947, 0x4948, 0x4949,
+ 0x494a, 0x494b, 0x494c, 0x494e, 0x494f, 0x4950, 0x4951, 0x4953,
+ 0x4954, 0x4955, 0x4957, 0x4958, 0x495a, 0x495b, 0x495d, 0x495f,
+ 0x4940, 0x4940, 0x4940, 0x4940, 0x4941, 0x4941, 0x4942, 0x4942,
+ 0x4943, 0x4944, 0x4945, 0x4945, 0x4946, 0x4947, 0x4948, 0x4949,
+ 0x494a, 0x494b, 0x494c, 0x494e, 0x494f, 0x4950, 0x4951, 0x4953,
+ 0x4954, 0x4955, 0x4957, 0x4958, 0x495a, 0x495b, 0x495d, 0x495f,
+ 0x4960, 0x4960, 0x4960, 0x4960, 0x4961, 0x4961, 0x4962, 0x4962,
+ 0x4963, 0x4964, 0x4965, 0x4965, 0x4966, 0x4967, 0x4968, 0x4969,
+ 0x496a, 0x496b, 0x496c, 0x496e, 0x496f, 0x4970, 0x4971, 0x4973,
+ 0x4974, 0x4975, 0x4977, 0x4978, 0x497a, 0x497b, 0x497d, 0x497f,
+ 0x4980, 0x4980, 0x4980, 0x4980, 0x4981, 0x4981, 0x4982, 0x4982,
+ 0x4983, 0x4984, 0x4985, 0x4985, 0x4986, 0x4987, 0x4988, 0x4989,
+ 0x498a, 0x498b, 0x498c, 0x498e, 0x498f, 0x4990, 0x4991, 0x4993,
+ 0x4994, 0x4995, 0x4997, 0x4998, 0x499a, 0x499b, 0x499d, 0x499f,
+ 0x49a0, 0x49a0, 0x49a0, 0x49a0, 0x49a1, 0x49a1, 0x49a2, 0x49a2,
+ 0x49a3, 0x49a4, 0x49a5, 0x49a5, 0x49a6, 0x49a7, 0x49a8, 0x49a9,
+ 0x49aa, 0x49ab, 0x49ac, 0x49ae, 0x49af, 0x49b0, 0x49b1, 0x49b3,
+ 0x49b4, 0x49b5, 0x49b7, 0x49b8, 0x49ba, 0x49bb, 0x49bd, 0x49bf,
+ 0x49c0, 0x49c0, 0x49c0, 0x49c0, 0x49c1, 0x49c1, 0x49c2, 0x49c2,
+ 0x49c3, 0x49c4, 0x49c5, 0x49c5, 0x49c6, 0x49c7, 0x49c8, 0x49c9,
+ 0x49ca, 0x49cb, 0x49cc, 0x49ce, 0x49cf, 0x49d0, 0x49d1, 0x49d3,
+ 0x49d4, 0x49d5, 0x49d7, 0x49d8, 0x49da, 0x49db, 0x49dd, 0x49df,
+ 0x49e0, 0x49e0, 0x49e0, 0x49e0, 0x49e1, 0x49e1, 0x49e2, 0x49e2,
+ 0x49e3, 0x49e4, 0x49e5, 0x49e5, 0x49e6, 0x49e7, 0x49e8, 0x49e9,
+ 0x49ea, 0x49eb, 0x49ec, 0x49ee, 0x49ef, 0x49f0, 0x49f1, 0x49f3,
+ 0x49f4, 0x49f5, 0x49f7, 0x49f8, 0x49fa, 0x49fb, 0x49fd, 0x49ff,
+ 0x4a00, 0x4a00, 0x4a00, 0x4a00, 0x4a01, 0x4a01, 0x4a02, 0x4a02,
+ 0x4a03, 0x4a04, 0x4a05, 0x4a05, 0x4a06, 0x4a07, 0x4a08, 0x4a09,
+ 0x4a0a, 0x4a0b, 0x4a0c, 0x4a0e, 0x4a0f, 0x4a10, 0x4a11, 0x4a13,
+ 0x4a14, 0x4a15, 0x4a17, 0x4a18, 0x4a1a, 0x4a1b, 0x4a1d, 0x4a1f,
+ 0x4a20, 0x4a20, 0x4a20, 0x4a20, 0x4a21, 0x4a21, 0x4a22, 0x4a22,
+ 0x4a23, 0x4a24, 0x4a25, 0x4a25, 0x4a26, 0x4a27, 0x4a28, 0x4a29,
+ 0x4a2a, 0x4a2b, 0x4a2c, 0x4a2e, 0x4a2f, 0x4a30, 0x4a31, 0x4a33,
+ 0x4a34, 0x4a35, 0x4a37, 0x4a38, 0x4a3a, 0x4a3b, 0x4a3d, 0x4a3f,
+ 0x4a40, 0x4a40, 0x4a40, 0x4a40, 0x4a41, 0x4a41, 0x4a42, 0x4a42,
+ 0x4a43, 0x4a44, 0x4a45, 0x4a45, 0x4a46, 0x4a47, 0x4a48, 0x4a49,
+ 0x4a4a, 0x4a4b, 0x4a4c, 0x4a4e, 0x4a4f, 0x4a50, 0x4a51, 0x4a53,
+ 0x4a54, 0x4a55, 0x4a57, 0x4a58, 0x4a5a, 0x4a5b, 0x4a5d, 0x4a5f,
+ 0x4a60, 0x4a60, 0x4a60, 0x4a60, 0x4a61, 0x4a61, 0x4a62, 0x4a62,
+ 0x4a63, 0x4a64, 0x4a65, 0x4a65, 0x4a66, 0x4a67, 0x4a68, 0x4a69,
+ 0x4a6a, 0x4a6b, 0x4a6c, 0x4a6e, 0x4a6f, 0x4a70, 0x4a71, 0x4a73,
+ 0x4a74, 0x4a75, 0x4a77, 0x4a78, 0x4a7a, 0x4a7b, 0x4a7d, 0x4a7f,
+ 0x4a80, 0x4a80, 0x4a80, 0x4a80, 0x4a81, 0x4a81, 0x4a82, 0x4a82,
+ 0x4a83, 0x4a84, 0x4a85, 0x4a85, 0x4a86, 0x4a87, 0x4a88, 0x4a89,
+ 0x4a8a, 0x4a8b, 0x4a8c, 0x4a8e, 0x4a8f, 0x4a90, 0x4a91, 0x4a93,
+ 0x4a94, 0x4a95, 0x4a97, 0x4a98, 0x4a9a, 0x4a9b, 0x4a9d, 0x4a9f,
+ 0x4aa0, 0x4aa0, 0x4aa0, 0x4aa0, 0x4aa1, 0x4aa1, 0x4aa2, 0x4aa2,
+ 0x4aa3, 0x4aa4, 0x4aa5, 0x4aa5, 0x4aa6, 0x4aa7, 0x4aa8, 0x4aa9,
+ 0x4aaa, 0x4aab, 0x4aac, 0x4aae, 0x4aaf, 0x4ab0, 0x4ab1, 0x4ab3,
+ 0x4ab4, 0x4ab5, 0x4ab7, 0x4ab8, 0x4aba, 0x4abb, 0x4abd, 0x4abf,
+ 0x4ac0, 0x4ac0, 0x4ac0, 0x4ac0, 0x4ac1, 0x4ac1, 0x4ac2, 0x4ac2,
+ 0x4ac3, 0x4ac4, 0x4ac5, 0x4ac5, 0x4ac6, 0x4ac7, 0x4ac8, 0x4ac9,
+ 0x4aca, 0x4acb, 0x4acc, 0x4ace, 0x4acf, 0x4ad0, 0x4ad1, 0x4ad3,
+ 0x4ad4, 0x4ad5, 0x4ad7, 0x4ad8, 0x4ada, 0x4adb, 0x4add, 0x4adf,
+ 0x4ae0, 0x4ae0, 0x4ae0, 0x4ae0, 0x4ae1, 0x4ae1, 0x4ae2, 0x4ae2,
+ 0x4ae3, 0x4ae4, 0x4ae5, 0x4ae5, 0x4ae6, 0x4ae7, 0x4ae8, 0x4ae9,
+ 0x4aea, 0x4aeb, 0x4aec, 0x4aee, 0x4aef, 0x4af0, 0x4af1, 0x4af3,
+ 0x4af4, 0x4af5, 0x4af7, 0x4af8, 0x4afa, 0x4afb, 0x4afd, 0x4aff,
+ 0x4b00, 0x4b00, 0x4b00, 0x4b00, 0x4b01, 0x4b01, 0x4b02, 0x4b02,
+ 0x4b03, 0x4b04, 0x4b05, 0x4b05, 0x4b06, 0x4b07, 0x4b08, 0x4b09,
+ 0x4b0a, 0x4b0b, 0x4b0c, 0x4b0e, 0x4b0f, 0x4b10, 0x4b11, 0x4b13,
+ 0x4b14, 0x4b15, 0x4b17, 0x4b18, 0x4b1a, 0x4b1b, 0x4b1d, 0x4b1f,
+ 0x4b20, 0x4b20, 0x4b20, 0x4b20, 0x4b21, 0x4b21, 0x4b22, 0x4b22,
+ 0x4b23, 0x4b24, 0x4b25, 0x4b25, 0x4b26, 0x4b27, 0x4b28, 0x4b29,
+ 0x4b2a, 0x4b2b, 0x4b2c, 0x4b2e, 0x4b2f, 0x4b30, 0x4b31, 0x4b33,
+ 0x4b34, 0x4b35, 0x4b37, 0x4b38, 0x4b3a, 0x4b3b, 0x4b3d, 0x4b3f,
+ 0x4b40, 0x4b40, 0x4b40, 0x4b40, 0x4b41, 0x4b41, 0x4b42, 0x4b42,
+ 0x4b43, 0x4b44, 0x4b45, 0x4b45, 0x4b46, 0x4b47, 0x4b48, 0x4b49,
+ 0x4b4a, 0x4b4b, 0x4b4c, 0x4b4e, 0x4b4f, 0x4b50, 0x4b51, 0x4b53,
+ 0x4b54, 0x4b55, 0x4b57, 0x4b58, 0x4b5a, 0x4b5b, 0x4b5d, 0x4b5f,
+ 0x4b80, 0x4b80, 0x4b80, 0x4b80, 0x4b81, 0x4b81, 0x4b82, 0x4b82,
+ 0x4b83, 0x4b84, 0x4b85, 0x4b85, 0x4b86, 0x4b87, 0x4b88, 0x4b89,
+ 0x4b8a, 0x4b8b, 0x4b8c, 0x4b8e, 0x4b8f, 0x4b90, 0x4b91, 0x4b93,
+ 0x4b94, 0x4b95, 0x4b97, 0x4b98, 0x4b9a, 0x4b9b, 0x4b9d, 0x4b9f,
+ 0x4ba0, 0x4ba0, 0x4ba0, 0x4ba0, 0x4ba1, 0x4ba1, 0x4ba2, 0x4ba2,
+ 0x4ba3, 0x4ba4, 0x4ba5, 0x4ba5, 0x4ba6, 0x4ba7, 0x4ba8, 0x4ba9,
+ 0x4baa, 0x4bab, 0x4bac, 0x4bae, 0x4baf, 0x4bb0, 0x4bb1, 0x4bb3,
+ 0x4bb4, 0x4bb5, 0x4bb7, 0x4bb8, 0x4bba, 0x4bbb, 0x4bbd, 0x4bbf,
+ 0x4bc0, 0x4bc0, 0x4bc0, 0x4bc0, 0x4bc1, 0x4bc1, 0x4bc2, 0x4bc2,
+ 0x4bc3, 0x4bc4, 0x4bc5, 0x4bc5, 0x4bc6, 0x4bc7, 0x4bc8, 0x4bc9,
+ 0x4bca, 0x4bcb, 0x4bcc, 0x4bce, 0x4bcf, 0x4bd0, 0x4bd1, 0x4bd3,
+ 0x4bd4, 0x4bd5, 0x4bd7, 0x4bd8, 0x4bda, 0x4bdb, 0x4bdd, 0x4bdf,
+ 0x4be0, 0x4be0, 0x4be0, 0x4be0, 0x4be1, 0x4be1, 0x4be2, 0x4be2,
+ 0x4be3, 0x4be4, 0x4be5, 0x4be5, 0x4be6, 0x4be7, 0x4be8, 0x4be9,
+ 0x4bea, 0x4beb, 0x4bec, 0x4bee, 0x4bef, 0x4bf0, 0x4bf1, 0x4bf3,
+ 0x4bf4, 0x4bf5, 0x4bf7, 0x4bf8, 0x4bfa, 0x4bfb, 0x4bfd, 0x4bff,
+ 0x4c00, 0x4c00, 0x4c00, 0x4c00, 0x4c01, 0x4c01, 0x4c02, 0x4c02,
+ 0x4c03, 0x4c04, 0x4c05, 0x4c05, 0x4c06, 0x4c07, 0x4c08, 0x4c09,
+ 0x4c0a, 0x4c0b, 0x4c0c, 0x4c0e, 0x4c0f, 0x4c10, 0x4c11, 0x4c13,
+ 0x4c14, 0x4c15, 0x4c17, 0x4c18, 0x4c1a, 0x4c1b, 0x4c1d, 0x4c1f,
+ 0x4c40, 0x4c40, 0x4c40, 0x4c40, 0x4c41, 0x4c41, 0x4c42, 0x4c42,
+ 0x4c43, 0x4c44, 0x4c45, 0x4c45, 0x4c46, 0x4c47, 0x4c48, 0x4c49,
+ 0x4c4a, 0x4c4b, 0x4c4c, 0x4c4e, 0x4c4f, 0x4c50, 0x4c51, 0x4c53,
+ 0x4c54, 0x4c55, 0x4c57, 0x4c58, 0x4c5a, 0x4c5b, 0x4c5d, 0x4c5f,
+ 0x4c60, 0x4c60, 0x4c60, 0x4c60, 0x4c61, 0x4c61, 0x4c62, 0x4c62,
+ 0x4c63, 0x4c64, 0x4c65, 0x4c65, 0x4c66, 0x4c67, 0x4c68, 0x4c69,
+ 0x4c6a, 0x4c6b, 0x4c6c, 0x4c6e, 0x4c6f, 0x4c70, 0x4c71, 0x4c73,
+ 0x4c74, 0x4c75, 0x4c77, 0x4c78, 0x4c7a, 0x4c7b, 0x4c7d, 0x4c7f,
+ 0x4c80, 0x4c80, 0x4c80, 0x4c80, 0x4c81, 0x4c81, 0x4c82, 0x4c82,
+ 0x4c83, 0x4c84, 0x4c85, 0x4c85, 0x4c86, 0x4c87, 0x4c88, 0x4c89,
+ 0x4c8a, 0x4c8b, 0x4c8c, 0x4c8e, 0x4c8f, 0x4c90, 0x4c91, 0x4c93,
+ 0x4c94, 0x4c95, 0x4c97, 0x4c98, 0x4c9a, 0x4c9b, 0x4c9d, 0x4c9f,
+ 0x4cc0, 0x4cc0, 0x4cc0, 0x4cc0, 0x4cc1, 0x4cc1, 0x4cc2, 0x4cc2,
+ 0x4cc3, 0x4cc4, 0x4cc5, 0x4cc5, 0x4cc6, 0x4cc7, 0x4cc8, 0x4cc9,
+ 0x4cca, 0x4ccb, 0x4ccc, 0x4cce, 0x4ccf, 0x4cd0, 0x4cd1, 0x4cd3,
+ 0x4cd4, 0x4cd5, 0x4cd7, 0x4cd8, 0x4cda, 0x4cdb, 0x4cdd, 0x4cdf,
+ 0x4ce0, 0x4ce0, 0x4ce0, 0x4ce0, 0x4ce1, 0x4ce1, 0x4ce2, 0x4ce2,
+ 0x4ce3, 0x4ce4, 0x4ce5, 0x4ce5, 0x4ce6, 0x4ce7, 0x4ce8, 0x4ce9,
+ 0x4cea, 0x4ceb, 0x4cec, 0x4cee, 0x4cef, 0x4cf0, 0x4cf1, 0x4cf3,
+ 0x4cf4, 0x4cf5, 0x4cf7, 0x4cf8, 0x4cfa, 0x4cfb, 0x4cfd, 0x4cff,
+ 0x4d00, 0x4d00, 0x4d00, 0x4d00, 0x4d01, 0x4d01, 0x4d02, 0x4d02,
+ 0x4d03, 0x4d04, 0x4d05, 0x4d05, 0x4d06, 0x4d07, 0x4d08, 0x4d09,
+ 0x4d0a, 0x4d0b, 0x4d0c, 0x4d0e, 0x4d0f, 0x4d10, 0x4d11, 0x4d13,
+ 0x4d14, 0x4d15, 0x4d17, 0x4d18, 0x4d1a, 0x4d1b, 0x4d1d, 0x4d1f,
+ 0x4d40, 0x4d40, 0x4d40, 0x4d40, 0x4d41, 0x4d41, 0x4d42, 0x4d42,
+ 0x4d43, 0x4d44, 0x4d45, 0x4d45, 0x4d46, 0x4d47, 0x4d48, 0x4d49,
+ 0x4d4a, 0x4d4b, 0x4d4c, 0x4d4e, 0x4d4f, 0x4d50, 0x4d51, 0x4d53,
+ 0x4d54, 0x4d55, 0x4d57, 0x4d58, 0x4d5a, 0x4d5b, 0x4d5d, 0x4d5f,
+ 0x4d60, 0x4d60, 0x4d60, 0x4d60, 0x4d61, 0x4d61, 0x4d62, 0x4d62,
+ 0x4d63, 0x4d64, 0x4d65, 0x4d65, 0x4d66, 0x4d67, 0x4d68, 0x4d69,
+ 0x4d6a, 0x4d6b, 0x4d6c, 0x4d6e, 0x4d6f, 0x4d70, 0x4d71, 0x4d73,
+ 0x4d74, 0x4d75, 0x4d77, 0x4d78, 0x4d7a, 0x4d7b, 0x4d7d, 0x4d7f,
+ 0x4d80, 0x4d80, 0x4d80, 0x4d80, 0x4d81, 0x4d81, 0x4d82, 0x4d82,
+ 0x4d83, 0x4d84, 0x4d85, 0x4d85, 0x4d86, 0x4d87, 0x4d88, 0x4d89,
+ 0x4d8a, 0x4d8b, 0x4d8c, 0x4d8e, 0x4d8f, 0x4d90, 0x4d91, 0x4d93,
+ 0x4d94, 0x4d95, 0x4d97, 0x4d98, 0x4d9a, 0x4d9b, 0x4d9d, 0x4d9f,
+ 0x4dc0, 0x4dc0, 0x4dc0, 0x4dc0, 0x4dc1, 0x4dc1, 0x4dc2, 0x4dc2,
+ 0x4dc3, 0x4dc4, 0x4dc5, 0x4dc5, 0x4dc6, 0x4dc7, 0x4dc8, 0x4dc9,
+ 0x4dca, 0x4dcb, 0x4dcc, 0x4dce, 0x4dcf, 0x4dd0, 0x4dd1, 0x4dd3,
+ 0x4dd4, 0x4dd5, 0x4dd7, 0x4dd8, 0x4dda, 0x4ddb, 0x4ddd, 0x4ddf,
+ 0x4de0, 0x4de0, 0x4de0, 0x4de0, 0x4de1, 0x4de1, 0x4de2, 0x4de2,
+ 0x4de3, 0x4de4, 0x4de5, 0x4de5, 0x4de6, 0x4de7, 0x4de8, 0x4de9,
+ 0x4dea, 0x4deb, 0x4dec, 0x4dee, 0x4def, 0x4df0, 0x4df1, 0x4df3,
+ 0x4df4, 0x4df5, 0x4df7, 0x4df8, 0x4dfa, 0x4dfb, 0x4dfd, 0x4dff,
+ 0x4e20, 0x4e20, 0x4e20, 0x4e20, 0x4e21, 0x4e21, 0x4e22, 0x4e22,
+ 0x4e23, 0x4e24, 0x4e25, 0x4e25, 0x4e26, 0x4e27, 0x4e28, 0x4e29,
+ 0x4e2a, 0x4e2b, 0x4e2c, 0x4e2e, 0x4e2f, 0x4e30, 0x4e31, 0x4e33,
+ 0x4e34, 0x4e35, 0x4e37, 0x4e38, 0x4e3a, 0x4e3b, 0x4e3d, 0x4e3f,
+ 0x4e40, 0x4e40, 0x4e40, 0x4e40, 0x4e41, 0x4e41, 0x4e42, 0x4e42,
+ 0x4e43, 0x4e44, 0x4e45, 0x4e45, 0x4e46, 0x4e47, 0x4e48, 0x4e49,
+ 0x4e4a, 0x4e4b, 0x4e4c, 0x4e4e, 0x4e4f, 0x4e50, 0x4e51, 0x4e53,
+ 0x4e54, 0x4e55, 0x4e57, 0x4e58, 0x4e5a, 0x4e5b, 0x4e5d, 0x4e5f,
+ 0x4e80, 0x4e80, 0x4e80, 0x4e80, 0x4e81, 0x4e81, 0x4e82, 0x4e82,
+ 0x4e83, 0x4e84, 0x4e85, 0x4e85, 0x4e86, 0x4e87, 0x4e88, 0x4e89,
+ 0x4e8a, 0x4e8b, 0x4e8c, 0x4e8e, 0x4e8f, 0x4e90, 0x4e91, 0x4e93,
+ 0x4e94, 0x4e95, 0x4e97, 0x4e98, 0x4e9a, 0x4e9b, 0x4e9d, 0x4e9f,
+ 0x4ea0, 0x4ea0, 0x4ea0, 0x4ea0, 0x4ea1, 0x4ea1, 0x4ea2, 0x4ea2,
+ 0x4ea3, 0x4ea4, 0x4ea5, 0x4ea5, 0x4ea6, 0x4ea7, 0x4ea8, 0x4ea9,
+ 0x4eaa, 0x4eab, 0x4eac, 0x4eae, 0x4eaf, 0x4eb0, 0x4eb1, 0x4eb3,
+ 0x4eb4, 0x4eb5, 0x4eb7, 0x4eb8, 0x4eba, 0x4ebb, 0x4ebd, 0x4ebf,
+ 0x4ee0, 0x4ee0, 0x4ee0, 0x4ee0, 0x4ee1, 0x4ee1, 0x4ee2, 0x4ee2,
+ 0x4ee3, 0x4ee4, 0x4ee5, 0x4ee5, 0x4ee6, 0x4ee7, 0x4ee8, 0x4ee9,
+ 0x4eea, 0x4eeb, 0x4eec, 0x4eee, 0x4eef, 0x4ef0, 0x4ef1, 0x4ef3,
+ 0x4ef4, 0x4ef5, 0x4ef7, 0x4ef8, 0x4efa, 0x4efb, 0x4efd, 0x4eff,
+ 0x4f00, 0x4f00, 0x4f00, 0x4f00, 0x4f01, 0x4f01, 0x4f02, 0x4f02,
+ 0x4f03, 0x4f04, 0x4f05, 0x4f05, 0x4f06, 0x4f07, 0x4f08, 0x4f09,
+ 0x4f0a, 0x4f0b, 0x4f0c, 0x4f0e, 0x4f0f, 0x4f10, 0x4f11, 0x4f13,
+ 0x4f14, 0x4f15, 0x4f17, 0x4f18, 0x4f1a, 0x4f1b, 0x4f1d, 0x4f1f,
+ 0x4f40, 0x4f40, 0x4f40, 0x4f40, 0x4f41, 0x4f41, 0x4f42, 0x4f42,
+ 0x4f43, 0x4f44, 0x4f45, 0x4f45, 0x4f46, 0x4f47, 0x4f48, 0x4f49,
+ 0x4f4a, 0x4f4b, 0x4f4c, 0x4f4e, 0x4f4f, 0x4f50, 0x4f51, 0x4f53,
+ 0x4f54, 0x4f55, 0x4f57, 0x4f58, 0x4f5a, 0x4f5b, 0x4f5d, 0x4f5f,
+ 0x4f60, 0x4f60, 0x4f60, 0x4f60, 0x4f61, 0x4f61, 0x4f62, 0x4f62,
+ 0x4f63, 0x4f64, 0x4f65, 0x4f65, 0x4f66, 0x4f67, 0x4f68, 0x4f69,
+ 0x4f6a, 0x4f6b, 0x4f6c, 0x4f6e, 0x4f6f, 0x4f70, 0x4f71, 0x4f73,
+ 0x4f74, 0x4f75, 0x4f77, 0x4f78, 0x4f7a, 0x4f7b, 0x4f7d, 0x4f7f,
+ 0x4fa0, 0x4fa0, 0x4fa0, 0x4fa0, 0x4fa1, 0x4fa1, 0x4fa2, 0x4fa2,
+ 0x4fa3, 0x4fa4, 0x4fa5, 0x4fa5, 0x4fa6, 0x4fa7, 0x4fa8, 0x4fa9,
+ 0x4faa, 0x4fab, 0x4fac, 0x4fae, 0x4faf, 0x4fb0, 0x4fb1, 0x4fb3,
+ 0x4fb4, 0x4fb5, 0x4fb7, 0x4fb8, 0x4fba, 0x4fbb, 0x4fbd, 0x4fbf,
+ 0x4fe0, 0x4fe0, 0x4fe0, 0x4fe0, 0x4fe1, 0x4fe1, 0x4fe2, 0x4fe2,
+ 0x4fe3, 0x4fe4, 0x4fe5, 0x4fe5, 0x4fe6, 0x4fe7, 0x4fe8, 0x4fe9,
+ 0x4fea, 0x4feb, 0x4fec, 0x4fee, 0x4fef, 0x4ff0, 0x4ff1, 0x4ff3,
+ 0x4ff4, 0x4ff5, 0x4ff7, 0x4ff8, 0x4ffa, 0x4ffb, 0x4ffd, 0x4fff,
+ 0x5000, 0x5000, 0x5000, 0x5000, 0x5001, 0x5001, 0x5002, 0x5002,
+ 0x5003, 0x5004, 0x5005, 0x5005, 0x5006, 0x5007, 0x5008, 0x5009,
+ 0x500a, 0x500b, 0x500c, 0x500e, 0x500f, 0x5010, 0x5011, 0x5013,
+ 0x5014, 0x5015, 0x5017, 0x5018, 0x501a, 0x501b, 0x501d, 0x501f,
+ 0x5000, 0x5000, 0x5000, 0x5000, 0x5001, 0x5001, 0x5002, 0x5002,
+ 0x5003, 0x5004, 0x5005, 0x5005, 0x5006, 0x5007, 0x5008, 0x5009,
+ 0x500a, 0x500b, 0x500c, 0x500e, 0x500f, 0x5010, 0x5011, 0x5013,
+ 0x5014, 0x5015, 0x5017, 0x5018, 0x501a, 0x501b, 0x501d, 0x501f,
+ 0x5000, 0x5000, 0x5000, 0x5000, 0x5001, 0x5001, 0x5002, 0x5002,
+ 0x5003, 0x5004, 0x5005, 0x5005, 0x5006, 0x5007, 0x5008, 0x5009,
+ 0x500a, 0x500b, 0x500c, 0x500e, 0x500f, 0x5010, 0x5011, 0x5013,
+ 0x5014, 0x5015, 0x5017, 0x5018, 0x501a, 0x501b, 0x501d, 0x501f,
+ 0x5000, 0x5000, 0x5000, 0x5000, 0x5001, 0x5001, 0x5002, 0x5002,
+ 0x5003, 0x5004, 0x5005, 0x5005, 0x5006, 0x5007, 0x5008, 0x5009,
+ 0x500a, 0x500b, 0x500c, 0x500e, 0x500f, 0x5010, 0x5011, 0x5013,
+ 0x5014, 0x5015, 0x5017, 0x5018, 0x501a, 0x501b, 0x501d, 0x501f,
+ 0x5000, 0x5000, 0x5000, 0x5000, 0x5001, 0x5001, 0x5002, 0x5002,
+ 0x5003, 0x5004, 0x5005, 0x5005, 0x5006, 0x5007, 0x5008, 0x5009,
+ 0x500a, 0x500b, 0x500c, 0x500e, 0x500f, 0x5010, 0x5011, 0x5013,
+ 0x5014, 0x5015, 0x5017, 0x5018, 0x501a, 0x501b, 0x501d, 0x501f,
+ 0x5020, 0x5020, 0x5020, 0x5020, 0x5021, 0x5021, 0x5022, 0x5022,
+ 0x5023, 0x5024, 0x5025, 0x5025, 0x5026, 0x5027, 0x5028, 0x5029,
+ 0x502a, 0x502b, 0x502c, 0x502e, 0x502f, 0x5030, 0x5031, 0x5033,
+ 0x5034, 0x5035, 0x5037, 0x5038, 0x503a, 0x503b, 0x503d, 0x503f,
+ 0x5020, 0x5020, 0x5020, 0x5020, 0x5021, 0x5021, 0x5022, 0x5022,
+ 0x5023, 0x5024, 0x5025, 0x5025, 0x5026, 0x5027, 0x5028, 0x5029,
+ 0x502a, 0x502b, 0x502c, 0x502e, 0x502f, 0x5030, 0x5031, 0x5033,
+ 0x5034, 0x5035, 0x5037, 0x5038, 0x503a, 0x503b, 0x503d, 0x503f,
+ 0x5020, 0x5020, 0x5020, 0x5020, 0x5021, 0x5021, 0x5022, 0x5022,
+ 0x5023, 0x5024, 0x5025, 0x5025, 0x5026, 0x5027, 0x5028, 0x5029,
+ 0x502a, 0x502b, 0x502c, 0x502e, 0x502f, 0x5030, 0x5031, 0x5033,
+ 0x5034, 0x5035, 0x5037, 0x5038, 0x503a, 0x503b, 0x503d, 0x503f,
+ 0x5040, 0x5040, 0x5040, 0x5040, 0x5041, 0x5041, 0x5042, 0x5042,
+ 0x5043, 0x5044, 0x5045, 0x5045, 0x5046, 0x5047, 0x5048, 0x5049,
+ 0x504a, 0x504b, 0x504c, 0x504e, 0x504f, 0x5050, 0x5051, 0x5053,
+ 0x5054, 0x5055, 0x5057, 0x5058, 0x505a, 0x505b, 0x505d, 0x505f,
+ 0x5040, 0x5040, 0x5040, 0x5040, 0x5041, 0x5041, 0x5042, 0x5042,
+ 0x5043, 0x5044, 0x5045, 0x5045, 0x5046, 0x5047, 0x5048, 0x5049,
+ 0x504a, 0x504b, 0x504c, 0x504e, 0x504f, 0x5050, 0x5051, 0x5053,
+ 0x5054, 0x5055, 0x5057, 0x5058, 0x505a, 0x505b, 0x505d, 0x505f,
+ 0x5060, 0x5060, 0x5060, 0x5060, 0x5061, 0x5061, 0x5062, 0x5062,
+ 0x5063, 0x5064, 0x5065, 0x5065, 0x5066, 0x5067, 0x5068, 0x5069,
+ 0x506a, 0x506b, 0x506c, 0x506e, 0x506f, 0x5070, 0x5071, 0x5073,
+ 0x5074, 0x5075, 0x5077, 0x5078, 0x507a, 0x507b, 0x507d, 0x507f,
+ 0x5060, 0x5060, 0x5060, 0x5060, 0x5061, 0x5061, 0x5062, 0x5062,
+ 0x5063, 0x5064, 0x5065, 0x5065, 0x5066, 0x5067, 0x5068, 0x5069,
+ 0x506a, 0x506b, 0x506c, 0x506e, 0x506f, 0x5070, 0x5071, 0x5073,
+ 0x5074, 0x5075, 0x5077, 0x5078, 0x507a, 0x507b, 0x507d, 0x507f,
+ 0x5080, 0x5080, 0x5080, 0x5080, 0x5081, 0x5081, 0x5082, 0x5082,
+ 0x5083, 0x5084, 0x5085, 0x5085, 0x5086, 0x5087, 0x5088, 0x5089,
+ 0x508a, 0x508b, 0x508c, 0x508e, 0x508f, 0x5090, 0x5091, 0x5093,
+ 0x5094, 0x5095, 0x5097, 0x5098, 0x509a, 0x509b, 0x509d, 0x509f,
+ 0x50a0, 0x50a0, 0x50a0, 0x50a0, 0x50a1, 0x50a1, 0x50a2, 0x50a2,
+ 0x50a3, 0x50a4, 0x50a5, 0x50a5, 0x50a6, 0x50a7, 0x50a8, 0x50a9,
+ 0x50aa, 0x50ab, 0x50ac, 0x50ae, 0x50af, 0x50b0, 0x50b1, 0x50b3,
+ 0x50b4, 0x50b5, 0x50b7, 0x50b8, 0x50ba, 0x50bb, 0x50bd, 0x50bf,
+ 0x50a0, 0x50a0, 0x50a0, 0x50a0, 0x50a1, 0x50a1, 0x50a2, 0x50a2,
+ 0x50a3, 0x50a4, 0x50a5, 0x50a5, 0x50a6, 0x50a7, 0x50a8, 0x50a9,
+ 0x50aa, 0x50ab, 0x50ac, 0x50ae, 0x50af, 0x50b0, 0x50b1, 0x50b3,
+ 0x50b4, 0x50b5, 0x50b7, 0x50b8, 0x50ba, 0x50bb, 0x50bd, 0x50bf,
+ 0x50c0, 0x50c0, 0x50c0, 0x50c0, 0x50c1, 0x50c1, 0x50c2, 0x50c2,
+ 0x50c3, 0x50c4, 0x50c5, 0x50c5, 0x50c6, 0x50c7, 0x50c8, 0x50c9,
+ 0x50ca, 0x50cb, 0x50cc, 0x50ce, 0x50cf, 0x50d0, 0x50d1, 0x50d3,
+ 0x50d4, 0x50d5, 0x50d7, 0x50d8, 0x50da, 0x50db, 0x50dd, 0x50df,
+ 0x50e0, 0x50e0, 0x50e0, 0x50e0, 0x50e1, 0x50e1, 0x50e2, 0x50e2,
+ 0x50e3, 0x50e4, 0x50e5, 0x50e5, 0x50e6, 0x50e7, 0x50e8, 0x50e9,
+ 0x50ea, 0x50eb, 0x50ec, 0x50ee, 0x50ef, 0x50f0, 0x50f1, 0x50f3,
+ 0x50f4, 0x50f5, 0x50f7, 0x50f8, 0x50fa, 0x50fb, 0x50fd, 0x50ff,
+ 0x50e0, 0x50e0, 0x50e0, 0x50e0, 0x50e1, 0x50e1, 0x50e2, 0x50e2,
+ 0x50e3, 0x50e4, 0x50e5, 0x50e5, 0x50e6, 0x50e7, 0x50e8, 0x50e9,
+ 0x50ea, 0x50eb, 0x50ec, 0x50ee, 0x50ef, 0x50f0, 0x50f1, 0x50f3,
+ 0x50f4, 0x50f5, 0x50f7, 0x50f8, 0x50fa, 0x50fb, 0x50fd, 0x50ff,
+ 0x5100, 0x5100, 0x5100, 0x5100, 0x5101, 0x5101, 0x5102, 0x5102,
+ 0x5103, 0x5104, 0x5105, 0x5105, 0x5106, 0x5107, 0x5108, 0x5109,
+ 0x510a, 0x510b, 0x510c, 0x510e, 0x510f, 0x5110, 0x5111, 0x5113,
+ 0x5114, 0x5115, 0x5117, 0x5118, 0x511a, 0x511b, 0x511d, 0x511f,
+ 0x5120, 0x5120, 0x5120, 0x5120, 0x5121, 0x5121, 0x5122, 0x5122,
+ 0x5123, 0x5124, 0x5125, 0x5125, 0x5126, 0x5127, 0x5128, 0x5129,
+ 0x512a, 0x512b, 0x512c, 0x512e, 0x512f, 0x5130, 0x5131, 0x5133,
+ 0x5134, 0x5135, 0x5137, 0x5138, 0x513a, 0x513b, 0x513d, 0x513f,
+ 0x5140, 0x5140, 0x5140, 0x5140, 0x5141, 0x5141, 0x5142, 0x5142,
+ 0x5143, 0x5144, 0x5145, 0x5145, 0x5146, 0x5147, 0x5148, 0x5149,
+ 0x514a, 0x514b, 0x514c, 0x514e, 0x514f, 0x5150, 0x5151, 0x5153,
+ 0x5154, 0x5155, 0x5157, 0x5158, 0x515a, 0x515b, 0x515d, 0x515f,
+ 0x5140, 0x5140, 0x5140, 0x5140, 0x5141, 0x5141, 0x5142, 0x5142,
+ 0x5143, 0x5144, 0x5145, 0x5145, 0x5146, 0x5147, 0x5148, 0x5149,
+ 0x514a, 0x514b, 0x514c, 0x514e, 0x514f, 0x5150, 0x5151, 0x5153,
+ 0x5154, 0x5155, 0x5157, 0x5158, 0x515a, 0x515b, 0x515d, 0x515f,
+ 0x5160, 0x5160, 0x5160, 0x5160, 0x5161, 0x5161, 0x5162, 0x5162,
+ 0x5163, 0x5164, 0x5165, 0x5165, 0x5166, 0x5167, 0x5168, 0x5169,
+ 0x516a, 0x516b, 0x516c, 0x516e, 0x516f, 0x5170, 0x5171, 0x5173,
+ 0x5174, 0x5175, 0x5177, 0x5178, 0x517a, 0x517b, 0x517d, 0x517f,
+ 0x5180, 0x5180, 0x5180, 0x5180, 0x5181, 0x5181, 0x5182, 0x5182,
+ 0x5183, 0x5184, 0x5185, 0x5185, 0x5186, 0x5187, 0x5188, 0x5189,
+ 0x518a, 0x518b, 0x518c, 0x518e, 0x518f, 0x5190, 0x5191, 0x5193,
+ 0x5194, 0x5195, 0x5197, 0x5198, 0x519a, 0x519b, 0x519d, 0x519f,
+ 0x51a0, 0x51a0, 0x51a0, 0x51a0, 0x51a1, 0x51a1, 0x51a2, 0x51a2,
+ 0x51a3, 0x51a4, 0x51a5, 0x51a5, 0x51a6, 0x51a7, 0x51a8, 0x51a9,
+ 0x51aa, 0x51ab, 0x51ac, 0x51ae, 0x51af, 0x51b0, 0x51b1, 0x51b3,
+ 0x51b4, 0x51b5, 0x51b7, 0x51b8, 0x51ba, 0x51bb, 0x51bd, 0x51bf,
+ 0x51c0, 0x51c0, 0x51c0, 0x51c0, 0x51c1, 0x51c1, 0x51c2, 0x51c2,
+ 0x51c3, 0x51c4, 0x51c5, 0x51c5, 0x51c6, 0x51c7, 0x51c8, 0x51c9,
+ 0x51ca, 0x51cb, 0x51cc, 0x51ce, 0x51cf, 0x51d0, 0x51d1, 0x51d3,
+ 0x51d4, 0x51d5, 0x51d7, 0x51d8, 0x51da, 0x51db, 0x51dd, 0x51df,
+ 0x51e0, 0x51e0, 0x51e0, 0x51e0, 0x51e1, 0x51e1, 0x51e2, 0x51e2,
+ 0x51e3, 0x51e4, 0x51e5, 0x51e5, 0x51e6, 0x51e7, 0x51e8, 0x51e9,
+ 0x51ea, 0x51eb, 0x51ec, 0x51ee, 0x51ef, 0x51f0, 0x51f1, 0x51f3,
+ 0x51f4, 0x51f5, 0x51f7, 0x51f8, 0x51fa, 0x51fb, 0x51fd, 0x51ff,
+ 0x5200, 0x5200, 0x5200, 0x5200, 0x5201, 0x5201, 0x5202, 0x5202,
+ 0x5203, 0x5204, 0x5205, 0x5205, 0x5206, 0x5207, 0x5208, 0x5209,
+ 0x520a, 0x520b, 0x520c, 0x520e, 0x520f, 0x5210, 0x5211, 0x5213,
+ 0x5214, 0x5215, 0x5217, 0x5218, 0x521a, 0x521b, 0x521d, 0x521f,
+ 0x5220, 0x5220, 0x5220, 0x5220, 0x5221, 0x5221, 0x5222, 0x5222,
+ 0x5223, 0x5224, 0x5225, 0x5225, 0x5226, 0x5227, 0x5228, 0x5229,
+ 0x522a, 0x522b, 0x522c, 0x522e, 0x522f, 0x5230, 0x5231, 0x5233,
+ 0x5234, 0x5235, 0x5237, 0x5238, 0x523a, 0x523b, 0x523d, 0x523f,
+ 0x5240, 0x5240, 0x5240, 0x5240, 0x5241, 0x5241, 0x5242, 0x5242,
+ 0x5243, 0x5244, 0x5245, 0x5245, 0x5246, 0x5247, 0x5248, 0x5249,
+ 0x524a, 0x524b, 0x524c, 0x524e, 0x524f, 0x5250, 0x5251, 0x5253,
+ 0x5254, 0x5255, 0x5257, 0x5258, 0x525a, 0x525b, 0x525d, 0x525f,
+ 0x5260, 0x5260, 0x5260, 0x5260, 0x5261, 0x5261, 0x5262, 0x5262,
+ 0x5263, 0x5264, 0x5265, 0x5265, 0x5266, 0x5267, 0x5268, 0x5269,
+ 0x526a, 0x526b, 0x526c, 0x526e, 0x526f, 0x5270, 0x5271, 0x5273,
+ 0x5274, 0x5275, 0x5277, 0x5278, 0x527a, 0x527b, 0x527d, 0x527f,
+ 0x5280, 0x5280, 0x5280, 0x5280, 0x5281, 0x5281, 0x5282, 0x5282,
+ 0x5283, 0x5284, 0x5285, 0x5285, 0x5286, 0x5287, 0x5288, 0x5289,
+ 0x528a, 0x528b, 0x528c, 0x528e, 0x528f, 0x5290, 0x5291, 0x5293,
+ 0x5294, 0x5295, 0x5297, 0x5298, 0x529a, 0x529b, 0x529d, 0x529f,
+ 0x52a0, 0x52a0, 0x52a0, 0x52a0, 0x52a1, 0x52a1, 0x52a2, 0x52a2,
+ 0x52a3, 0x52a4, 0x52a5, 0x52a5, 0x52a6, 0x52a7, 0x52a8, 0x52a9,
+ 0x52aa, 0x52ab, 0x52ac, 0x52ae, 0x52af, 0x52b0, 0x52b1, 0x52b3,
+ 0x52b4, 0x52b5, 0x52b7, 0x52b8, 0x52ba, 0x52bb, 0x52bd, 0x52bf,
+ 0x52c0, 0x52c0, 0x52c0, 0x52c0, 0x52c1, 0x52c1, 0x52c2, 0x52c2,
+ 0x52c3, 0x52c4, 0x52c5, 0x52c5, 0x52c6, 0x52c7, 0x52c8, 0x52c9,
+ 0x52ca, 0x52cb, 0x52cc, 0x52ce, 0x52cf, 0x52d0, 0x52d1, 0x52d3,
+ 0x52d4, 0x52d5, 0x52d7, 0x52d8, 0x52da, 0x52db, 0x52dd, 0x52df,
+ 0x52e0, 0x52e0, 0x52e0, 0x52e0, 0x52e1, 0x52e1, 0x52e2, 0x52e2,
+ 0x52e3, 0x52e4, 0x52e5, 0x52e5, 0x52e6, 0x52e7, 0x52e8, 0x52e9,
+ 0x52ea, 0x52eb, 0x52ec, 0x52ee, 0x52ef, 0x52f0, 0x52f1, 0x52f3,
+ 0x52f4, 0x52f5, 0x52f7, 0x52f8, 0x52fa, 0x52fb, 0x52fd, 0x52ff,
+ 0x5300, 0x5300, 0x5300, 0x5300, 0x5301, 0x5301, 0x5302, 0x5302,
+ 0x5303, 0x5304, 0x5305, 0x5305, 0x5306, 0x5307, 0x5308, 0x5309,
+ 0x530a, 0x530b, 0x530c, 0x530e, 0x530f, 0x5310, 0x5311, 0x5313,
+ 0x5314, 0x5315, 0x5317, 0x5318, 0x531a, 0x531b, 0x531d, 0x531f,
+ 0x5320, 0x5320, 0x5320, 0x5320, 0x5321, 0x5321, 0x5322, 0x5322,
+ 0x5323, 0x5324, 0x5325, 0x5325, 0x5326, 0x5327, 0x5328, 0x5329,
+ 0x532a, 0x532b, 0x532c, 0x532e, 0x532f, 0x5330, 0x5331, 0x5333,
+ 0x5334, 0x5335, 0x5337, 0x5338, 0x533a, 0x533b, 0x533d, 0x533f,
+ 0x5340, 0x5340, 0x5340, 0x5340, 0x5341, 0x5341, 0x5342, 0x5342,
+ 0x5343, 0x5344, 0x5345, 0x5345, 0x5346, 0x5347, 0x5348, 0x5349,
+ 0x534a, 0x534b, 0x534c, 0x534e, 0x534f, 0x5350, 0x5351, 0x5353,
+ 0x5354, 0x5355, 0x5357, 0x5358, 0x535a, 0x535b, 0x535d, 0x535f,
+ 0x5380, 0x5380, 0x5380, 0x5380, 0x5381, 0x5381, 0x5382, 0x5382,
+ 0x5383, 0x5384, 0x5385, 0x5385, 0x5386, 0x5387, 0x5388, 0x5389,
+ 0x538a, 0x538b, 0x538c, 0x538e, 0x538f, 0x5390, 0x5391, 0x5393,
+ 0x5394, 0x5395, 0x5397, 0x5398, 0x539a, 0x539b, 0x539d, 0x539f,
+ 0x53a0, 0x53a0, 0x53a0, 0x53a0, 0x53a1, 0x53a1, 0x53a2, 0x53a2,
+ 0x53a3, 0x53a4, 0x53a5, 0x53a5, 0x53a6, 0x53a7, 0x53a8, 0x53a9,
+ 0x53aa, 0x53ab, 0x53ac, 0x53ae, 0x53af, 0x53b0, 0x53b1, 0x53b3,
+ 0x53b4, 0x53b5, 0x53b7, 0x53b8, 0x53ba, 0x53bb, 0x53bd, 0x53bf,
+ 0x53c0, 0x53c0, 0x53c0, 0x53c0, 0x53c1, 0x53c1, 0x53c2, 0x53c2,
+ 0x53c3, 0x53c4, 0x53c5, 0x53c5, 0x53c6, 0x53c7, 0x53c8, 0x53c9,
+ 0x53ca, 0x53cb, 0x53cc, 0x53ce, 0x53cf, 0x53d0, 0x53d1, 0x53d3,
+ 0x53d4, 0x53d5, 0x53d7, 0x53d8, 0x53da, 0x53db, 0x53dd, 0x53df,
+ 0x53e0, 0x53e0, 0x53e0, 0x53e0, 0x53e1, 0x53e1, 0x53e2, 0x53e2,
+ 0x53e3, 0x53e4, 0x53e5, 0x53e5, 0x53e6, 0x53e7, 0x53e8, 0x53e9,
+ 0x53ea, 0x53eb, 0x53ec, 0x53ee, 0x53ef, 0x53f0, 0x53f1, 0x53f3,
+ 0x53f4, 0x53f5, 0x53f7, 0x53f8, 0x53fa, 0x53fb, 0x53fd, 0x53ff,
+ 0x5400, 0x5400, 0x5400, 0x5400, 0x5401, 0x5401, 0x5402, 0x5402,
+ 0x5403, 0x5404, 0x5405, 0x5405, 0x5406, 0x5407, 0x5408, 0x5409,
+ 0x540a, 0x540b, 0x540c, 0x540e, 0x540f, 0x5410, 0x5411, 0x5413,
+ 0x5414, 0x5415, 0x5417, 0x5418, 0x541a, 0x541b, 0x541d, 0x541f,
+ 0x5440, 0x5440, 0x5440, 0x5440, 0x5441, 0x5441, 0x5442, 0x5442,
+ 0x5443, 0x5444, 0x5445, 0x5445, 0x5446, 0x5447, 0x5448, 0x5449,
+ 0x544a, 0x544b, 0x544c, 0x544e, 0x544f, 0x5450, 0x5451, 0x5453,
+ 0x5454, 0x5455, 0x5457, 0x5458, 0x545a, 0x545b, 0x545d, 0x545f,
+ 0x5460, 0x5460, 0x5460, 0x5460, 0x5461, 0x5461, 0x5462, 0x5462,
+ 0x5463, 0x5464, 0x5465, 0x5465, 0x5466, 0x5467, 0x5468, 0x5469,
+ 0x546a, 0x546b, 0x546c, 0x546e, 0x546f, 0x5470, 0x5471, 0x5473,
+ 0x5474, 0x5475, 0x5477, 0x5478, 0x547a, 0x547b, 0x547d, 0x547f,
+ 0x5480, 0x5480, 0x5480, 0x5480, 0x5481, 0x5481, 0x5482, 0x5482,
+ 0x5483, 0x5484, 0x5485, 0x5485, 0x5486, 0x5487, 0x5488, 0x5489,
+ 0x548a, 0x548b, 0x548c, 0x548e, 0x548f, 0x5490, 0x5491, 0x5493,
+ 0x5494, 0x5495, 0x5497, 0x5498, 0x549a, 0x549b, 0x549d, 0x549f,
+ 0x54c0, 0x54c0, 0x54c0, 0x54c0, 0x54c1, 0x54c1, 0x54c2, 0x54c2,
+ 0x54c3, 0x54c4, 0x54c5, 0x54c5, 0x54c6, 0x54c7, 0x54c8, 0x54c9,
+ 0x54ca, 0x54cb, 0x54cc, 0x54ce, 0x54cf, 0x54d0, 0x54d1, 0x54d3,
+ 0x54d4, 0x54d5, 0x54d7, 0x54d8, 0x54da, 0x54db, 0x54dd, 0x54df,
+ 0x54e0, 0x54e0, 0x54e0, 0x54e0, 0x54e1, 0x54e1, 0x54e2, 0x54e2,
+ 0x54e3, 0x54e4, 0x54e5, 0x54e5, 0x54e6, 0x54e7, 0x54e8, 0x54e9,
+ 0x54ea, 0x54eb, 0x54ec, 0x54ee, 0x54ef, 0x54f0, 0x54f1, 0x54f3,
+ 0x54f4, 0x54f5, 0x54f7, 0x54f8, 0x54fa, 0x54fb, 0x54fd, 0x54ff,
+ 0x5500, 0x5500, 0x5500, 0x5500, 0x5501, 0x5501, 0x5502, 0x5502,
+ 0x5503, 0x5504, 0x5505, 0x5505, 0x5506, 0x5507, 0x5508, 0x5509,
+ 0x550a, 0x550b, 0x550c, 0x550e, 0x550f, 0x5510, 0x5511, 0x5513,
+ 0x5514, 0x5515, 0x5517, 0x5518, 0x551a, 0x551b, 0x551d, 0x551f,
+ 0x5540, 0x5540, 0x5540, 0x5540, 0x5541, 0x5541, 0x5542, 0x5542,
+ 0x5543, 0x5544, 0x5545, 0x5545, 0x5546, 0x5547, 0x5548, 0x5549,
+ 0x554a, 0x554b, 0x554c, 0x554e, 0x554f, 0x5550, 0x5551, 0x5553,
+ 0x5554, 0x5555, 0x5557, 0x5558, 0x555a, 0x555b, 0x555d, 0x555f,
+ 0x5560, 0x5560, 0x5560, 0x5560, 0x5561, 0x5561, 0x5562, 0x5562,
+ 0x5563, 0x5564, 0x5565, 0x5565, 0x5566, 0x5567, 0x5568, 0x5569,
+ 0x556a, 0x556b, 0x556c, 0x556e, 0x556f, 0x5570, 0x5571, 0x5573,
+ 0x5574, 0x5575, 0x5577, 0x5578, 0x557a, 0x557b, 0x557d, 0x557f,
+ 0x5580, 0x5580, 0x5580, 0x5580, 0x5581, 0x5581, 0x5582, 0x5582,
+ 0x5583, 0x5584, 0x5585, 0x5585, 0x5586, 0x5587, 0x5588, 0x5589,
+ 0x558a, 0x558b, 0x558c, 0x558e, 0x558f, 0x5590, 0x5591, 0x5593,
+ 0x5594, 0x5595, 0x5597, 0x5598, 0x559a, 0x559b, 0x559d, 0x559f,
+ 0x55c0, 0x55c0, 0x55c0, 0x55c0, 0x55c1, 0x55c1, 0x55c2, 0x55c2,
+ 0x55c3, 0x55c4, 0x55c5, 0x55c5, 0x55c6, 0x55c7, 0x55c8, 0x55c9,
+ 0x55ca, 0x55cb, 0x55cc, 0x55ce, 0x55cf, 0x55d0, 0x55d1, 0x55d3,
+ 0x55d4, 0x55d5, 0x55d7, 0x55d8, 0x55da, 0x55db, 0x55dd, 0x55df,
+ 0x55e0, 0x55e0, 0x55e0, 0x55e0, 0x55e1, 0x55e1, 0x55e2, 0x55e2,
+ 0x55e3, 0x55e4, 0x55e5, 0x55e5, 0x55e6, 0x55e7, 0x55e8, 0x55e9,
+ 0x55ea, 0x55eb, 0x55ec, 0x55ee, 0x55ef, 0x55f0, 0x55f1, 0x55f3,
+ 0x55f4, 0x55f5, 0x55f7, 0x55f8, 0x55fa, 0x55fb, 0x55fd, 0x55ff,
+ 0x5620, 0x5620, 0x5620, 0x5620, 0x5621, 0x5621, 0x5622, 0x5622,
+ 0x5623, 0x5624, 0x5625, 0x5625, 0x5626, 0x5627, 0x5628, 0x5629,
+ 0x562a, 0x562b, 0x562c, 0x562e, 0x562f, 0x5630, 0x5631, 0x5633,
+ 0x5634, 0x5635, 0x5637, 0x5638, 0x563a, 0x563b, 0x563d, 0x563f,
+ 0x5640, 0x5640, 0x5640, 0x5640, 0x5641, 0x5641, 0x5642, 0x5642,
+ 0x5643, 0x5644, 0x5645, 0x5645, 0x5646, 0x5647, 0x5648, 0x5649,
+ 0x564a, 0x564b, 0x564c, 0x564e, 0x564f, 0x5650, 0x5651, 0x5653,
+ 0x5654, 0x5655, 0x5657, 0x5658, 0x565a, 0x565b, 0x565d, 0x565f,
+ 0x5680, 0x5680, 0x5680, 0x5680, 0x5681, 0x5681, 0x5682, 0x5682,
+ 0x5683, 0x5684, 0x5685, 0x5685, 0x5686, 0x5687, 0x5688, 0x5689,
+ 0x568a, 0x568b, 0x568c, 0x568e, 0x568f, 0x5690, 0x5691, 0x5693,
+ 0x5694, 0x5695, 0x5697, 0x5698, 0x569a, 0x569b, 0x569d, 0x569f,
+ 0x56a0, 0x56a0, 0x56a0, 0x56a0, 0x56a1, 0x56a1, 0x56a2, 0x56a2,
+ 0x56a3, 0x56a4, 0x56a5, 0x56a5, 0x56a6, 0x56a7, 0x56a8, 0x56a9,
+ 0x56aa, 0x56ab, 0x56ac, 0x56ae, 0x56af, 0x56b0, 0x56b1, 0x56b3,
+ 0x56b4, 0x56b5, 0x56b7, 0x56b8, 0x56ba, 0x56bb, 0x56bd, 0x56bf,
+ 0x56e0, 0x56e0, 0x56e0, 0x56e0, 0x56e1, 0x56e1, 0x56e2, 0x56e2,
+ 0x56e3, 0x56e4, 0x56e5, 0x56e5, 0x56e6, 0x56e7, 0x56e8, 0x56e9,
+ 0x56ea, 0x56eb, 0x56ec, 0x56ee, 0x56ef, 0x56f0, 0x56f1, 0x56f3,
+ 0x56f4, 0x56f5, 0x56f7, 0x56f8, 0x56fa, 0x56fb, 0x56fd, 0x56ff,
+ 0x5700, 0x5700, 0x5700, 0x5700, 0x5701, 0x5701, 0x5702, 0x5702,
+ 0x5703, 0x5704, 0x5705, 0x5705, 0x5706, 0x5707, 0x5708, 0x5709,
+ 0x570a, 0x570b, 0x570c, 0x570e, 0x570f, 0x5710, 0x5711, 0x5713,
+ 0x5714, 0x5715, 0x5717, 0x5718, 0x571a, 0x571b, 0x571d, 0x571f,
+ 0x5740, 0x5740, 0x5740, 0x5740, 0x5741, 0x5741, 0x5742, 0x5742,
+ 0x5743, 0x5744, 0x5745, 0x5745, 0x5746, 0x5747, 0x5748, 0x5749,
+ 0x574a, 0x574b, 0x574c, 0x574e, 0x574f, 0x5750, 0x5751, 0x5753,
+ 0x5754, 0x5755, 0x5757, 0x5758, 0x575a, 0x575b, 0x575d, 0x575f,
+ 0x5760, 0x5760, 0x5760, 0x5760, 0x5761, 0x5761, 0x5762, 0x5762,
+ 0x5763, 0x5764, 0x5765, 0x5765, 0x5766, 0x5767, 0x5768, 0x5769,
+ 0x576a, 0x576b, 0x576c, 0x576e, 0x576f, 0x5770, 0x5771, 0x5773,
+ 0x5774, 0x5775, 0x5777, 0x5778, 0x577a, 0x577b, 0x577d, 0x577f,
+ 0x57a0, 0x57a0, 0x57a0, 0x57a0, 0x57a1, 0x57a1, 0x57a2, 0x57a2,
+ 0x57a3, 0x57a4, 0x57a5, 0x57a5, 0x57a6, 0x57a7, 0x57a8, 0x57a9,
+ 0x57aa, 0x57ab, 0x57ac, 0x57ae, 0x57af, 0x57b0, 0x57b1, 0x57b3,
+ 0x57b4, 0x57b5, 0x57b7, 0x57b8, 0x57ba, 0x57bb, 0x57bd, 0x57bf,
+ 0x57e0, 0x57e0, 0x57e0, 0x57e0, 0x57e1, 0x57e1, 0x57e2, 0x57e2,
+ 0x57e3, 0x57e4, 0x57e5, 0x57e5, 0x57e6, 0x57e7, 0x57e8, 0x57e9,
+ 0x57ea, 0x57eb, 0x57ec, 0x57ee, 0x57ef, 0x57f0, 0x57f1, 0x57f3,
+ 0x57f4, 0x57f5, 0x57f7, 0x57f8, 0x57fa, 0x57fb, 0x57fd, 0x57ff,
+ 0x5800, 0x5800, 0x5800, 0x5800, 0x5801, 0x5801, 0x5802, 0x5802,
+ 0x5803, 0x5804, 0x5805, 0x5805, 0x5806, 0x5807, 0x5808, 0x5809,
+ 0x580a, 0x580b, 0x580c, 0x580e, 0x580f, 0x5810, 0x5811, 0x5813,
+ 0x5814, 0x5815, 0x5817, 0x5818, 0x581a, 0x581b, 0x581d, 0x581f,
+ 0x5800, 0x5800, 0x5800, 0x5800, 0x5801, 0x5801, 0x5802, 0x5802,
+ 0x5803, 0x5804, 0x5805, 0x5805, 0x5806, 0x5807, 0x5808, 0x5809,
+ 0x580a, 0x580b, 0x580c, 0x580e, 0x580f, 0x5810, 0x5811, 0x5813,
+ 0x5814, 0x5815, 0x5817, 0x5818, 0x581a, 0x581b, 0x581d, 0x581f,
+ 0x5800, 0x5800, 0x5800, 0x5800, 0x5801, 0x5801, 0x5802, 0x5802,
+ 0x5803, 0x5804, 0x5805, 0x5805, 0x5806, 0x5807, 0x5808, 0x5809,
+ 0x580a, 0x580b, 0x580c, 0x580e, 0x580f, 0x5810, 0x5811, 0x5813,
+ 0x5814, 0x5815, 0x5817, 0x5818, 0x581a, 0x581b, 0x581d, 0x581f,
+ 0x5800, 0x5800, 0x5800, 0x5800, 0x5801, 0x5801, 0x5802, 0x5802,
+ 0x5803, 0x5804, 0x5805, 0x5805, 0x5806, 0x5807, 0x5808, 0x5809,
+ 0x580a, 0x580b, 0x580c, 0x580e, 0x580f, 0x5810, 0x5811, 0x5813,
+ 0x5814, 0x5815, 0x5817, 0x5818, 0x581a, 0x581b, 0x581d, 0x581f,
+ 0x5800, 0x5800, 0x5800, 0x5800, 0x5801, 0x5801, 0x5802, 0x5802,
+ 0x5803, 0x5804, 0x5805, 0x5805, 0x5806, 0x5807, 0x5808, 0x5809,
+ 0x580a, 0x580b, 0x580c, 0x580e, 0x580f, 0x5810, 0x5811, 0x5813,
+ 0x5814, 0x5815, 0x5817, 0x5818, 0x581a, 0x581b, 0x581d, 0x581f,
+ 0x5820, 0x5820, 0x5820, 0x5820, 0x5821, 0x5821, 0x5822, 0x5822,
+ 0x5823, 0x5824, 0x5825, 0x5825, 0x5826, 0x5827, 0x5828, 0x5829,
+ 0x582a, 0x582b, 0x582c, 0x582e, 0x582f, 0x5830, 0x5831, 0x5833,
+ 0x5834, 0x5835, 0x5837, 0x5838, 0x583a, 0x583b, 0x583d, 0x583f,
+ 0x5820, 0x5820, 0x5820, 0x5820, 0x5821, 0x5821, 0x5822, 0x5822,
+ 0x5823, 0x5824, 0x5825, 0x5825, 0x5826, 0x5827, 0x5828, 0x5829,
+ 0x582a, 0x582b, 0x582c, 0x582e, 0x582f, 0x5830, 0x5831, 0x5833,
+ 0x5834, 0x5835, 0x5837, 0x5838, 0x583a, 0x583b, 0x583d, 0x583f,
+ 0x5820, 0x5820, 0x5820, 0x5820, 0x5821, 0x5821, 0x5822, 0x5822,
+ 0x5823, 0x5824, 0x5825, 0x5825, 0x5826, 0x5827, 0x5828, 0x5829,
+ 0x582a, 0x582b, 0x582c, 0x582e, 0x582f, 0x5830, 0x5831, 0x5833,
+ 0x5834, 0x5835, 0x5837, 0x5838, 0x583a, 0x583b, 0x583d, 0x583f,
+ 0x5840, 0x5840, 0x5840, 0x5840, 0x5841, 0x5841, 0x5842, 0x5842,
+ 0x5843, 0x5844, 0x5845, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849,
+ 0x584a, 0x584b, 0x584c, 0x584e, 0x584f, 0x5850, 0x5851, 0x5853,
+ 0x5854, 0x5855, 0x5857, 0x5858, 0x585a, 0x585b, 0x585d, 0x585f,
+ 0x5840, 0x5840, 0x5840, 0x5840, 0x5841, 0x5841, 0x5842, 0x5842,
+ 0x5843, 0x5844, 0x5845, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849,
+ 0x584a, 0x584b, 0x584c, 0x584e, 0x584f, 0x5850, 0x5851, 0x5853,
+ 0x5854, 0x5855, 0x5857, 0x5858, 0x585a, 0x585b, 0x585d, 0x585f,
+ 0x5860, 0x5860, 0x5860, 0x5860, 0x5861, 0x5861, 0x5862, 0x5862,
+ 0x5863, 0x5864, 0x5865, 0x5865, 0x5866, 0x5867, 0x5868, 0x5869,
+ 0x586a, 0x586b, 0x586c, 0x586e, 0x586f, 0x5870, 0x5871, 0x5873,
+ 0x5874, 0x5875, 0x5877, 0x5878, 0x587a, 0x587b, 0x587d, 0x587f,
+ 0x5860, 0x5860, 0x5860, 0x5860, 0x5861, 0x5861, 0x5862, 0x5862,
+ 0x5863, 0x5864, 0x5865, 0x5865, 0x5866, 0x5867, 0x5868, 0x5869,
+ 0x586a, 0x586b, 0x586c, 0x586e, 0x586f, 0x5870, 0x5871, 0x5873,
+ 0x5874, 0x5875, 0x5877, 0x5878, 0x587a, 0x587b, 0x587d, 0x587f,
+ 0x5880, 0x5880, 0x5880, 0x5880, 0x5881, 0x5881, 0x5882, 0x5882,
+ 0x5883, 0x5884, 0x5885, 0x5885, 0x5886, 0x5887, 0x5888, 0x5889,
+ 0x588a, 0x588b, 0x588c, 0x588e, 0x588f, 0x5890, 0x5891, 0x5893,
+ 0x5894, 0x5895, 0x5897, 0x5898, 0x589a, 0x589b, 0x589d, 0x589f,
+ 0x58a0, 0x58a0, 0x58a0, 0x58a0, 0x58a1, 0x58a1, 0x58a2, 0x58a2,
+ 0x58a3, 0x58a4, 0x58a5, 0x58a5, 0x58a6, 0x58a7, 0x58a8, 0x58a9,
+ 0x58aa, 0x58ab, 0x58ac, 0x58ae, 0x58af, 0x58b0, 0x58b1, 0x58b3,
+ 0x58b4, 0x58b5, 0x58b7, 0x58b8, 0x58ba, 0x58bb, 0x58bd, 0x58bf,
+ 0x58a0, 0x58a0, 0x58a0, 0x58a0, 0x58a1, 0x58a1, 0x58a2, 0x58a2,
+ 0x58a3, 0x58a4, 0x58a5, 0x58a5, 0x58a6, 0x58a7, 0x58a8, 0x58a9,
+ 0x58aa, 0x58ab, 0x58ac, 0x58ae, 0x58af, 0x58b0, 0x58b1, 0x58b3,
+ 0x58b4, 0x58b5, 0x58b7, 0x58b8, 0x58ba, 0x58bb, 0x58bd, 0x58bf,
+ 0x58c0, 0x58c0, 0x58c0, 0x58c0, 0x58c1, 0x58c1, 0x58c2, 0x58c2,
+ 0x58c3, 0x58c4, 0x58c5, 0x58c5, 0x58c6, 0x58c7, 0x58c8, 0x58c9,
+ 0x58ca, 0x58cb, 0x58cc, 0x58ce, 0x58cf, 0x58d0, 0x58d1, 0x58d3,
+ 0x58d4, 0x58d5, 0x58d7, 0x58d8, 0x58da, 0x58db, 0x58dd, 0x58df,
+ 0x58e0, 0x58e0, 0x58e0, 0x58e0, 0x58e1, 0x58e1, 0x58e2, 0x58e2,
+ 0x58e3, 0x58e4, 0x58e5, 0x58e5, 0x58e6, 0x58e7, 0x58e8, 0x58e9,
+ 0x58ea, 0x58eb, 0x58ec, 0x58ee, 0x58ef, 0x58f0, 0x58f1, 0x58f3,
+ 0x58f4, 0x58f5, 0x58f7, 0x58f8, 0x58fa, 0x58fb, 0x58fd, 0x58ff,
+ 0x58e0, 0x58e0, 0x58e0, 0x58e0, 0x58e1, 0x58e1, 0x58e2, 0x58e2,
+ 0x58e3, 0x58e4, 0x58e5, 0x58e5, 0x58e6, 0x58e7, 0x58e8, 0x58e9,
+ 0x58ea, 0x58eb, 0x58ec, 0x58ee, 0x58ef, 0x58f0, 0x58f1, 0x58f3,
+ 0x58f4, 0x58f5, 0x58f7, 0x58f8, 0x58fa, 0x58fb, 0x58fd, 0x58ff,
+ 0x5900, 0x5900, 0x5900, 0x5900, 0x5901, 0x5901, 0x5902, 0x5902,
+ 0x5903, 0x5904, 0x5905, 0x5905, 0x5906, 0x5907, 0x5908, 0x5909,
+ 0x590a, 0x590b, 0x590c, 0x590e, 0x590f, 0x5910, 0x5911, 0x5913,
+ 0x5914, 0x5915, 0x5917, 0x5918, 0x591a, 0x591b, 0x591d, 0x591f,
+ 0x5920, 0x5920, 0x5920, 0x5920, 0x5921, 0x5921, 0x5922, 0x5922,
+ 0x5923, 0x5924, 0x5925, 0x5925, 0x5926, 0x5927, 0x5928, 0x5929,
+ 0x592a, 0x592b, 0x592c, 0x592e, 0x592f, 0x5930, 0x5931, 0x5933,
+ 0x5934, 0x5935, 0x5937, 0x5938, 0x593a, 0x593b, 0x593d, 0x593f,
+ 0x5940, 0x5940, 0x5940, 0x5940, 0x5941, 0x5941, 0x5942, 0x5942,
+ 0x5943, 0x5944, 0x5945, 0x5945, 0x5946, 0x5947, 0x5948, 0x5949,
+ 0x594a, 0x594b, 0x594c, 0x594e, 0x594f, 0x5950, 0x5951, 0x5953,
+ 0x5954, 0x5955, 0x5957, 0x5958, 0x595a, 0x595b, 0x595d, 0x595f,
+ 0x5940, 0x5940, 0x5940, 0x5940, 0x5941, 0x5941, 0x5942, 0x5942,
+ 0x5943, 0x5944, 0x5945, 0x5945, 0x5946, 0x5947, 0x5948, 0x5949,
+ 0x594a, 0x594b, 0x594c, 0x594e, 0x594f, 0x5950, 0x5951, 0x5953,
+ 0x5954, 0x5955, 0x5957, 0x5958, 0x595a, 0x595b, 0x595d, 0x595f,
+ 0x5960, 0x5960, 0x5960, 0x5960, 0x5961, 0x5961, 0x5962, 0x5962,
+ 0x5963, 0x5964, 0x5965, 0x5965, 0x5966, 0x5967, 0x5968, 0x5969,
+ 0x596a, 0x596b, 0x596c, 0x596e, 0x596f, 0x5970, 0x5971, 0x5973,
+ 0x5974, 0x5975, 0x5977, 0x5978, 0x597a, 0x597b, 0x597d, 0x597f,
+ 0x5980, 0x5980, 0x5980, 0x5980, 0x5981, 0x5981, 0x5982, 0x5982,
+ 0x5983, 0x5984, 0x5985, 0x5985, 0x5986, 0x5987, 0x5988, 0x5989,
+ 0x598a, 0x598b, 0x598c, 0x598e, 0x598f, 0x5990, 0x5991, 0x5993,
+ 0x5994, 0x5995, 0x5997, 0x5998, 0x599a, 0x599b, 0x599d, 0x599f,
+ 0x59a0, 0x59a0, 0x59a0, 0x59a0, 0x59a1, 0x59a1, 0x59a2, 0x59a2,
+ 0x59a3, 0x59a4, 0x59a5, 0x59a5, 0x59a6, 0x59a7, 0x59a8, 0x59a9,
+ 0x59aa, 0x59ab, 0x59ac, 0x59ae, 0x59af, 0x59b0, 0x59b1, 0x59b3,
+ 0x59b4, 0x59b5, 0x59b7, 0x59b8, 0x59ba, 0x59bb, 0x59bd, 0x59bf,
+ 0x59c0, 0x59c0, 0x59c0, 0x59c0, 0x59c1, 0x59c1, 0x59c2, 0x59c2,
+ 0x59c3, 0x59c4, 0x59c5, 0x59c5, 0x59c6, 0x59c7, 0x59c8, 0x59c9,
+ 0x59ca, 0x59cb, 0x59cc, 0x59ce, 0x59cf, 0x59d0, 0x59d1, 0x59d3,
+ 0x59d4, 0x59d5, 0x59d7, 0x59d8, 0x59da, 0x59db, 0x59dd, 0x59df,
+ 0x59e0, 0x59e0, 0x59e0, 0x59e0, 0x59e1, 0x59e1, 0x59e2, 0x59e2,
+ 0x59e3, 0x59e4, 0x59e5, 0x59e5, 0x59e6, 0x59e7, 0x59e8, 0x59e9,
+ 0x59ea, 0x59eb, 0x59ec, 0x59ee, 0x59ef, 0x59f0, 0x59f1, 0x59f3,
+ 0x59f4, 0x59f5, 0x59f7, 0x59f8, 0x59fa, 0x59fb, 0x59fd, 0x59ff,
+ 0x5a00, 0x5a00, 0x5a00, 0x5a00, 0x5a01, 0x5a01, 0x5a02, 0x5a02,
+ 0x5a03, 0x5a04, 0x5a05, 0x5a05, 0x5a06, 0x5a07, 0x5a08, 0x5a09,
+ 0x5a0a, 0x5a0b, 0x5a0c, 0x5a0e, 0x5a0f, 0x5a10, 0x5a11, 0x5a13,
+ 0x5a14, 0x5a15, 0x5a17, 0x5a18, 0x5a1a, 0x5a1b, 0x5a1d, 0x5a1f,
+ 0x5a20, 0x5a20, 0x5a20, 0x5a20, 0x5a21, 0x5a21, 0x5a22, 0x5a22,
+ 0x5a23, 0x5a24, 0x5a25, 0x5a25, 0x5a26, 0x5a27, 0x5a28, 0x5a29,
+ 0x5a2a, 0x5a2b, 0x5a2c, 0x5a2e, 0x5a2f, 0x5a30, 0x5a31, 0x5a33,
+ 0x5a34, 0x5a35, 0x5a37, 0x5a38, 0x5a3a, 0x5a3b, 0x5a3d, 0x5a3f,
+ 0x5a40, 0x5a40, 0x5a40, 0x5a40, 0x5a41, 0x5a41, 0x5a42, 0x5a42,
+ 0x5a43, 0x5a44, 0x5a45, 0x5a45, 0x5a46, 0x5a47, 0x5a48, 0x5a49,
+ 0x5a4a, 0x5a4b, 0x5a4c, 0x5a4e, 0x5a4f, 0x5a50, 0x5a51, 0x5a53,
+ 0x5a54, 0x5a55, 0x5a57, 0x5a58, 0x5a5a, 0x5a5b, 0x5a5d, 0x5a5f,
+ 0x5a60, 0x5a60, 0x5a60, 0x5a60, 0x5a61, 0x5a61, 0x5a62, 0x5a62,
+ 0x5a63, 0x5a64, 0x5a65, 0x5a65, 0x5a66, 0x5a67, 0x5a68, 0x5a69,
+ 0x5a6a, 0x5a6b, 0x5a6c, 0x5a6e, 0x5a6f, 0x5a70, 0x5a71, 0x5a73,
+ 0x5a74, 0x5a75, 0x5a77, 0x5a78, 0x5a7a, 0x5a7b, 0x5a7d, 0x5a7f,
+ 0x5a80, 0x5a80, 0x5a80, 0x5a80, 0x5a81, 0x5a81, 0x5a82, 0x5a82,
+ 0x5a83, 0x5a84, 0x5a85, 0x5a85, 0x5a86, 0x5a87, 0x5a88, 0x5a89,
+ 0x5a8a, 0x5a8b, 0x5a8c, 0x5a8e, 0x5a8f, 0x5a90, 0x5a91, 0x5a93,
+ 0x5a94, 0x5a95, 0x5a97, 0x5a98, 0x5a9a, 0x5a9b, 0x5a9d, 0x5a9f,
+ 0x5aa0, 0x5aa0, 0x5aa0, 0x5aa0, 0x5aa1, 0x5aa1, 0x5aa2, 0x5aa2,
+ 0x5aa3, 0x5aa4, 0x5aa5, 0x5aa5, 0x5aa6, 0x5aa7, 0x5aa8, 0x5aa9,
+ 0x5aaa, 0x5aab, 0x5aac, 0x5aae, 0x5aaf, 0x5ab0, 0x5ab1, 0x5ab3,
+ 0x5ab4, 0x5ab5, 0x5ab7, 0x5ab8, 0x5aba, 0x5abb, 0x5abd, 0x5abf,
+ 0x5ac0, 0x5ac0, 0x5ac0, 0x5ac0, 0x5ac1, 0x5ac1, 0x5ac2, 0x5ac2,
+ 0x5ac3, 0x5ac4, 0x5ac5, 0x5ac5, 0x5ac6, 0x5ac7, 0x5ac8, 0x5ac9,
+ 0x5aca, 0x5acb, 0x5acc, 0x5ace, 0x5acf, 0x5ad0, 0x5ad1, 0x5ad3,
+ 0x5ad4, 0x5ad5, 0x5ad7, 0x5ad8, 0x5ada, 0x5adb, 0x5add, 0x5adf,
+ 0x5ae0, 0x5ae0, 0x5ae0, 0x5ae0, 0x5ae1, 0x5ae1, 0x5ae2, 0x5ae2,
+ 0x5ae3, 0x5ae4, 0x5ae5, 0x5ae5, 0x5ae6, 0x5ae7, 0x5ae8, 0x5ae9,
+ 0x5aea, 0x5aeb, 0x5aec, 0x5aee, 0x5aef, 0x5af0, 0x5af1, 0x5af3,
+ 0x5af4, 0x5af5, 0x5af7, 0x5af8, 0x5afa, 0x5afb, 0x5afd, 0x5aff,
+ 0x5b00, 0x5b00, 0x5b00, 0x5b00, 0x5b01, 0x5b01, 0x5b02, 0x5b02,
+ 0x5b03, 0x5b04, 0x5b05, 0x5b05, 0x5b06, 0x5b07, 0x5b08, 0x5b09,
+ 0x5b0a, 0x5b0b, 0x5b0c, 0x5b0e, 0x5b0f, 0x5b10, 0x5b11, 0x5b13,
+ 0x5b14, 0x5b15, 0x5b17, 0x5b18, 0x5b1a, 0x5b1b, 0x5b1d, 0x5b1f,
+ 0x5b20, 0x5b20, 0x5b20, 0x5b20, 0x5b21, 0x5b21, 0x5b22, 0x5b22,
+ 0x5b23, 0x5b24, 0x5b25, 0x5b25, 0x5b26, 0x5b27, 0x5b28, 0x5b29,
+ 0x5b2a, 0x5b2b, 0x5b2c, 0x5b2e, 0x5b2f, 0x5b30, 0x5b31, 0x5b33,
+ 0x5b34, 0x5b35, 0x5b37, 0x5b38, 0x5b3a, 0x5b3b, 0x5b3d, 0x5b3f,
+ 0x5b40, 0x5b40, 0x5b40, 0x5b40, 0x5b41, 0x5b41, 0x5b42, 0x5b42,
+ 0x5b43, 0x5b44, 0x5b45, 0x5b45, 0x5b46, 0x5b47, 0x5b48, 0x5b49,
+ 0x5b4a, 0x5b4b, 0x5b4c, 0x5b4e, 0x5b4f, 0x5b50, 0x5b51, 0x5b53,
+ 0x5b54, 0x5b55, 0x5b57, 0x5b58, 0x5b5a, 0x5b5b, 0x5b5d, 0x5b5f,
+ 0x5b80, 0x5b80, 0x5b80, 0x5b80, 0x5b81, 0x5b81, 0x5b82, 0x5b82,
+ 0x5b83, 0x5b84, 0x5b85, 0x5b85, 0x5b86, 0x5b87, 0x5b88, 0x5b89,
+ 0x5b8a, 0x5b8b, 0x5b8c, 0x5b8e, 0x5b8f, 0x5b90, 0x5b91, 0x5b93,
+ 0x5b94, 0x5b95, 0x5b97, 0x5b98, 0x5b9a, 0x5b9b, 0x5b9d, 0x5b9f,
+ 0x5ba0, 0x5ba0, 0x5ba0, 0x5ba0, 0x5ba1, 0x5ba1, 0x5ba2, 0x5ba2,
+ 0x5ba3, 0x5ba4, 0x5ba5, 0x5ba5, 0x5ba6, 0x5ba7, 0x5ba8, 0x5ba9,
+ 0x5baa, 0x5bab, 0x5bac, 0x5bae, 0x5baf, 0x5bb0, 0x5bb1, 0x5bb3,
+ 0x5bb4, 0x5bb5, 0x5bb7, 0x5bb8, 0x5bba, 0x5bbb, 0x5bbd, 0x5bbf,
+ 0x5bc0, 0x5bc0, 0x5bc0, 0x5bc0, 0x5bc1, 0x5bc1, 0x5bc2, 0x5bc2,
+ 0x5bc3, 0x5bc4, 0x5bc5, 0x5bc5, 0x5bc6, 0x5bc7, 0x5bc8, 0x5bc9,
+ 0x5bca, 0x5bcb, 0x5bcc, 0x5bce, 0x5bcf, 0x5bd0, 0x5bd1, 0x5bd3,
+ 0x5bd4, 0x5bd5, 0x5bd7, 0x5bd8, 0x5bda, 0x5bdb, 0x5bdd, 0x5bdf,
+ 0x5be0, 0x5be0, 0x5be0, 0x5be0, 0x5be1, 0x5be1, 0x5be2, 0x5be2,
+ 0x5be3, 0x5be4, 0x5be5, 0x5be5, 0x5be6, 0x5be7, 0x5be8, 0x5be9,
+ 0x5bea, 0x5beb, 0x5bec, 0x5bee, 0x5bef, 0x5bf0, 0x5bf1, 0x5bf3,
+ 0x5bf4, 0x5bf5, 0x5bf7, 0x5bf8, 0x5bfa, 0x5bfb, 0x5bfd, 0x5bff,
+ 0x5c00, 0x5c00, 0x5c00, 0x5c00, 0x5c01, 0x5c01, 0x5c02, 0x5c02,
+ 0x5c03, 0x5c04, 0x5c05, 0x5c05, 0x5c06, 0x5c07, 0x5c08, 0x5c09,
+ 0x5c0a, 0x5c0b, 0x5c0c, 0x5c0e, 0x5c0f, 0x5c10, 0x5c11, 0x5c13,
+ 0x5c14, 0x5c15, 0x5c17, 0x5c18, 0x5c1a, 0x5c1b, 0x5c1d, 0x5c1f,
+ 0x5c40, 0x5c40, 0x5c40, 0x5c40, 0x5c41, 0x5c41, 0x5c42, 0x5c42,
+ 0x5c43, 0x5c44, 0x5c45, 0x5c45, 0x5c46, 0x5c47, 0x5c48, 0x5c49,
+ 0x5c4a, 0x5c4b, 0x5c4c, 0x5c4e, 0x5c4f, 0x5c50, 0x5c51, 0x5c53,
+ 0x5c54, 0x5c55, 0x5c57, 0x5c58, 0x5c5a, 0x5c5b, 0x5c5d, 0x5c5f,
+ 0x5c60, 0x5c60, 0x5c60, 0x5c60, 0x5c61, 0x5c61, 0x5c62, 0x5c62,
+ 0x5c63, 0x5c64, 0x5c65, 0x5c65, 0x5c66, 0x5c67, 0x5c68, 0x5c69,
+ 0x5c6a, 0x5c6b, 0x5c6c, 0x5c6e, 0x5c6f, 0x5c70, 0x5c71, 0x5c73,
+ 0x5c74, 0x5c75, 0x5c77, 0x5c78, 0x5c7a, 0x5c7b, 0x5c7d, 0x5c7f,
+ 0x5c80, 0x5c80, 0x5c80, 0x5c80, 0x5c81, 0x5c81, 0x5c82, 0x5c82,
+ 0x5c83, 0x5c84, 0x5c85, 0x5c85, 0x5c86, 0x5c87, 0x5c88, 0x5c89,
+ 0x5c8a, 0x5c8b, 0x5c8c, 0x5c8e, 0x5c8f, 0x5c90, 0x5c91, 0x5c93,
+ 0x5c94, 0x5c95, 0x5c97, 0x5c98, 0x5c9a, 0x5c9b, 0x5c9d, 0x5c9f,
+ 0x5cc0, 0x5cc0, 0x5cc0, 0x5cc0, 0x5cc1, 0x5cc1, 0x5cc2, 0x5cc2,
+ 0x5cc3, 0x5cc4, 0x5cc5, 0x5cc5, 0x5cc6, 0x5cc7, 0x5cc8, 0x5cc9,
+ 0x5cca, 0x5ccb, 0x5ccc, 0x5cce, 0x5ccf, 0x5cd0, 0x5cd1, 0x5cd3,
+ 0x5cd4, 0x5cd5, 0x5cd7, 0x5cd8, 0x5cda, 0x5cdb, 0x5cdd, 0x5cdf,
+ 0x5ce0, 0x5ce0, 0x5ce0, 0x5ce0, 0x5ce1, 0x5ce1, 0x5ce2, 0x5ce2,
+ 0x5ce3, 0x5ce4, 0x5ce5, 0x5ce5, 0x5ce6, 0x5ce7, 0x5ce8, 0x5ce9,
+ 0x5cea, 0x5ceb, 0x5cec, 0x5cee, 0x5cef, 0x5cf0, 0x5cf1, 0x5cf3,
+ 0x5cf4, 0x5cf5, 0x5cf7, 0x5cf8, 0x5cfa, 0x5cfb, 0x5cfd, 0x5cff,
+ 0x5d00, 0x5d00, 0x5d00, 0x5d00, 0x5d01, 0x5d01, 0x5d02, 0x5d02,
+ 0x5d03, 0x5d04, 0x5d05, 0x5d05, 0x5d06, 0x5d07, 0x5d08, 0x5d09,
+ 0x5d0a, 0x5d0b, 0x5d0c, 0x5d0e, 0x5d0f, 0x5d10, 0x5d11, 0x5d13,
+ 0x5d14, 0x5d15, 0x5d17, 0x5d18, 0x5d1a, 0x5d1b, 0x5d1d, 0x5d1f,
+ 0x5d40, 0x5d40, 0x5d40, 0x5d40, 0x5d41, 0x5d41, 0x5d42, 0x5d42,
+ 0x5d43, 0x5d44, 0x5d45, 0x5d45, 0x5d46, 0x5d47, 0x5d48, 0x5d49,
+ 0x5d4a, 0x5d4b, 0x5d4c, 0x5d4e, 0x5d4f, 0x5d50, 0x5d51, 0x5d53,
+ 0x5d54, 0x5d55, 0x5d57, 0x5d58, 0x5d5a, 0x5d5b, 0x5d5d, 0x5d5f,
+ 0x5d60, 0x5d60, 0x5d60, 0x5d60, 0x5d61, 0x5d61, 0x5d62, 0x5d62,
+ 0x5d63, 0x5d64, 0x5d65, 0x5d65, 0x5d66, 0x5d67, 0x5d68, 0x5d69,
+ 0x5d6a, 0x5d6b, 0x5d6c, 0x5d6e, 0x5d6f, 0x5d70, 0x5d71, 0x5d73,
+ 0x5d74, 0x5d75, 0x5d77, 0x5d78, 0x5d7a, 0x5d7b, 0x5d7d, 0x5d7f,
+ 0x5d80, 0x5d80, 0x5d80, 0x5d80, 0x5d81, 0x5d81, 0x5d82, 0x5d82,
+ 0x5d83, 0x5d84, 0x5d85, 0x5d85, 0x5d86, 0x5d87, 0x5d88, 0x5d89,
+ 0x5d8a, 0x5d8b, 0x5d8c, 0x5d8e, 0x5d8f, 0x5d90, 0x5d91, 0x5d93,
+ 0x5d94, 0x5d95, 0x5d97, 0x5d98, 0x5d9a, 0x5d9b, 0x5d9d, 0x5d9f,
+ 0x5dc0, 0x5dc0, 0x5dc0, 0x5dc0, 0x5dc1, 0x5dc1, 0x5dc2, 0x5dc2,
+ 0x5dc3, 0x5dc4, 0x5dc5, 0x5dc5, 0x5dc6, 0x5dc7, 0x5dc8, 0x5dc9,
+ 0x5dca, 0x5dcb, 0x5dcc, 0x5dce, 0x5dcf, 0x5dd0, 0x5dd1, 0x5dd3,
+ 0x5dd4, 0x5dd5, 0x5dd7, 0x5dd8, 0x5dda, 0x5ddb, 0x5ddd, 0x5ddf,
+ 0x5de0, 0x5de0, 0x5de0, 0x5de0, 0x5de1, 0x5de1, 0x5de2, 0x5de2,
+ 0x5de3, 0x5de4, 0x5de5, 0x5de5, 0x5de6, 0x5de7, 0x5de8, 0x5de9,
+ 0x5dea, 0x5deb, 0x5dec, 0x5dee, 0x5def, 0x5df0, 0x5df1, 0x5df3,
+ 0x5df4, 0x5df5, 0x5df7, 0x5df8, 0x5dfa, 0x5dfb, 0x5dfd, 0x5dff,
+ 0x5e20, 0x5e20, 0x5e20, 0x5e20, 0x5e21, 0x5e21, 0x5e22, 0x5e22,
+ 0x5e23, 0x5e24, 0x5e25, 0x5e25, 0x5e26, 0x5e27, 0x5e28, 0x5e29,
+ 0x5e2a, 0x5e2b, 0x5e2c, 0x5e2e, 0x5e2f, 0x5e30, 0x5e31, 0x5e33,
+ 0x5e34, 0x5e35, 0x5e37, 0x5e38, 0x5e3a, 0x5e3b, 0x5e3d, 0x5e3f,
+ 0x5e40, 0x5e40, 0x5e40, 0x5e40, 0x5e41, 0x5e41, 0x5e42, 0x5e42,
+ 0x5e43, 0x5e44, 0x5e45, 0x5e45, 0x5e46, 0x5e47, 0x5e48, 0x5e49,
+ 0x5e4a, 0x5e4b, 0x5e4c, 0x5e4e, 0x5e4f, 0x5e50, 0x5e51, 0x5e53,
+ 0x5e54, 0x5e55, 0x5e57, 0x5e58, 0x5e5a, 0x5e5b, 0x5e5d, 0x5e5f,
+ 0x5e80, 0x5e80, 0x5e80, 0x5e80, 0x5e81, 0x5e81, 0x5e82, 0x5e82,
+ 0x5e83, 0x5e84, 0x5e85, 0x5e85, 0x5e86, 0x5e87, 0x5e88, 0x5e89,
+ 0x5e8a, 0x5e8b, 0x5e8c, 0x5e8e, 0x5e8f, 0x5e90, 0x5e91, 0x5e93,
+ 0x5e94, 0x5e95, 0x5e97, 0x5e98, 0x5e9a, 0x5e9b, 0x5e9d, 0x5e9f,
+ 0x5ea0, 0x5ea0, 0x5ea0, 0x5ea0, 0x5ea1, 0x5ea1, 0x5ea2, 0x5ea2,
+ 0x5ea3, 0x5ea4, 0x5ea5, 0x5ea5, 0x5ea6, 0x5ea7, 0x5ea8, 0x5ea9,
+ 0x5eaa, 0x5eab, 0x5eac, 0x5eae, 0x5eaf, 0x5eb0, 0x5eb1, 0x5eb3,
+ 0x5eb4, 0x5eb5, 0x5eb7, 0x5eb8, 0x5eba, 0x5ebb, 0x5ebd, 0x5ebf,
+ 0x5ee0, 0x5ee0, 0x5ee0, 0x5ee0, 0x5ee1, 0x5ee1, 0x5ee2, 0x5ee2,
+ 0x5ee3, 0x5ee4, 0x5ee5, 0x5ee5, 0x5ee6, 0x5ee7, 0x5ee8, 0x5ee9,
+ 0x5eea, 0x5eeb, 0x5eec, 0x5eee, 0x5eef, 0x5ef0, 0x5ef1, 0x5ef3,
+ 0x5ef4, 0x5ef5, 0x5ef7, 0x5ef8, 0x5efa, 0x5efb, 0x5efd, 0x5eff,
+ 0x5f00, 0x5f00, 0x5f00, 0x5f00, 0x5f01, 0x5f01, 0x5f02, 0x5f02,
+ 0x5f03, 0x5f04, 0x5f05, 0x5f05, 0x5f06, 0x5f07, 0x5f08, 0x5f09,
+ 0x5f0a, 0x5f0b, 0x5f0c, 0x5f0e, 0x5f0f, 0x5f10, 0x5f11, 0x5f13,
+ 0x5f14, 0x5f15, 0x5f17, 0x5f18, 0x5f1a, 0x5f1b, 0x5f1d, 0x5f1f,
+ 0x5f40, 0x5f40, 0x5f40, 0x5f40, 0x5f41, 0x5f41, 0x5f42, 0x5f42,
+ 0x5f43, 0x5f44, 0x5f45, 0x5f45, 0x5f46, 0x5f47, 0x5f48, 0x5f49,
+ 0x5f4a, 0x5f4b, 0x5f4c, 0x5f4e, 0x5f4f, 0x5f50, 0x5f51, 0x5f53,
+ 0x5f54, 0x5f55, 0x5f57, 0x5f58, 0x5f5a, 0x5f5b, 0x5f5d, 0x5f5f,
+ 0x5f60, 0x5f60, 0x5f60, 0x5f60, 0x5f61, 0x5f61, 0x5f62, 0x5f62,
+ 0x5f63, 0x5f64, 0x5f65, 0x5f65, 0x5f66, 0x5f67, 0x5f68, 0x5f69,
+ 0x5f6a, 0x5f6b, 0x5f6c, 0x5f6e, 0x5f6f, 0x5f70, 0x5f71, 0x5f73,
+ 0x5f74, 0x5f75, 0x5f77, 0x5f78, 0x5f7a, 0x5f7b, 0x5f7d, 0x5f7f,
+ 0x5fa0, 0x5fa0, 0x5fa0, 0x5fa0, 0x5fa1, 0x5fa1, 0x5fa2, 0x5fa2,
+ 0x5fa3, 0x5fa4, 0x5fa5, 0x5fa5, 0x5fa6, 0x5fa7, 0x5fa8, 0x5fa9,
+ 0x5faa, 0x5fab, 0x5fac, 0x5fae, 0x5faf, 0x5fb0, 0x5fb1, 0x5fb3,
+ 0x5fb4, 0x5fb5, 0x5fb7, 0x5fb8, 0x5fba, 0x5fbb, 0x5fbd, 0x5fbf,
+ 0x5fe0, 0x5fe0, 0x5fe0, 0x5fe0, 0x5fe1, 0x5fe1, 0x5fe2, 0x5fe2,
+ 0x5fe3, 0x5fe4, 0x5fe5, 0x5fe5, 0x5fe6, 0x5fe7, 0x5fe8, 0x5fe9,
+ 0x5fea, 0x5feb, 0x5fec, 0x5fee, 0x5fef, 0x5ff0, 0x5ff1, 0x5ff3,
+ 0x5ff4, 0x5ff5, 0x5ff7, 0x5ff8, 0x5ffa, 0x5ffb, 0x5ffd, 0x5fff,
+ 0x6000, 0x6000, 0x6000, 0x6000, 0x6001, 0x6001, 0x6002, 0x6002,
+ 0x6003, 0x6004, 0x6005, 0x6005, 0x6006, 0x6007, 0x6008, 0x6009,
+ 0x600a, 0x600b, 0x600c, 0x600e, 0x600f, 0x6010, 0x6011, 0x6013,
+ 0x6014, 0x6015, 0x6017, 0x6018, 0x601a, 0x601b, 0x601d, 0x601f,
+ 0x6000, 0x6000, 0x6000, 0x6000, 0x6001, 0x6001, 0x6002, 0x6002,
+ 0x6003, 0x6004, 0x6005, 0x6005, 0x6006, 0x6007, 0x6008, 0x6009,
+ 0x600a, 0x600b, 0x600c, 0x600e, 0x600f, 0x6010, 0x6011, 0x6013,
+ 0x6014, 0x6015, 0x6017, 0x6018, 0x601a, 0x601b, 0x601d, 0x601f,
+ 0x6000, 0x6000, 0x6000, 0x6000, 0x6001, 0x6001, 0x6002, 0x6002,
+ 0x6003, 0x6004, 0x6005, 0x6005, 0x6006, 0x6007, 0x6008, 0x6009,
+ 0x600a, 0x600b, 0x600c, 0x600e, 0x600f, 0x6010, 0x6011, 0x6013,
+ 0x6014, 0x6015, 0x6017, 0x6018, 0x601a, 0x601b, 0x601d, 0x601f,
+ 0x6000, 0x6000, 0x6000, 0x6000, 0x6001, 0x6001, 0x6002, 0x6002,
+ 0x6003, 0x6004, 0x6005, 0x6005, 0x6006, 0x6007, 0x6008, 0x6009,
+ 0x600a, 0x600b, 0x600c, 0x600e, 0x600f, 0x6010, 0x6011, 0x6013,
+ 0x6014, 0x6015, 0x6017, 0x6018, 0x601a, 0x601b, 0x601d, 0x601f,
+ 0x6000, 0x6000, 0x6000, 0x6000, 0x6001, 0x6001, 0x6002, 0x6002,
+ 0x6003, 0x6004, 0x6005, 0x6005, 0x6006, 0x6007, 0x6008, 0x6009,
+ 0x600a, 0x600b, 0x600c, 0x600e, 0x600f, 0x6010, 0x6011, 0x6013,
+ 0x6014, 0x6015, 0x6017, 0x6018, 0x601a, 0x601b, 0x601d, 0x601f,
+ 0x6020, 0x6020, 0x6020, 0x6020, 0x6021, 0x6021, 0x6022, 0x6022,
+ 0x6023, 0x6024, 0x6025, 0x6025, 0x6026, 0x6027, 0x6028, 0x6029,
+ 0x602a, 0x602b, 0x602c, 0x602e, 0x602f, 0x6030, 0x6031, 0x6033,
+ 0x6034, 0x6035, 0x6037, 0x6038, 0x603a, 0x603b, 0x603d, 0x603f,
+ 0x6020, 0x6020, 0x6020, 0x6020, 0x6021, 0x6021, 0x6022, 0x6022,
+ 0x6023, 0x6024, 0x6025, 0x6025, 0x6026, 0x6027, 0x6028, 0x6029,
+ 0x602a, 0x602b, 0x602c, 0x602e, 0x602f, 0x6030, 0x6031, 0x6033,
+ 0x6034, 0x6035, 0x6037, 0x6038, 0x603a, 0x603b, 0x603d, 0x603f,
+ 0x6020, 0x6020, 0x6020, 0x6020, 0x6021, 0x6021, 0x6022, 0x6022,
+ 0x6023, 0x6024, 0x6025, 0x6025, 0x6026, 0x6027, 0x6028, 0x6029,
+ 0x602a, 0x602b, 0x602c, 0x602e, 0x602f, 0x6030, 0x6031, 0x6033,
+ 0x6034, 0x6035, 0x6037, 0x6038, 0x603a, 0x603b, 0x603d, 0x603f,
+ 0x6040, 0x6040, 0x6040, 0x6040, 0x6041, 0x6041, 0x6042, 0x6042,
+ 0x6043, 0x6044, 0x6045, 0x6045, 0x6046, 0x6047, 0x6048, 0x6049,
+ 0x604a, 0x604b, 0x604c, 0x604e, 0x604f, 0x6050, 0x6051, 0x6053,
+ 0x6054, 0x6055, 0x6057, 0x6058, 0x605a, 0x605b, 0x605d, 0x605f,
+ 0x6040, 0x6040, 0x6040, 0x6040, 0x6041, 0x6041, 0x6042, 0x6042,
+ 0x6043, 0x6044, 0x6045, 0x6045, 0x6046, 0x6047, 0x6048, 0x6049,
+ 0x604a, 0x604b, 0x604c, 0x604e, 0x604f, 0x6050, 0x6051, 0x6053,
+ 0x6054, 0x6055, 0x6057, 0x6058, 0x605a, 0x605b, 0x605d, 0x605f,
+ 0x6060, 0x6060, 0x6060, 0x6060, 0x6061, 0x6061, 0x6062, 0x6062,
+ 0x6063, 0x6064, 0x6065, 0x6065, 0x6066, 0x6067, 0x6068, 0x6069,
+ 0x606a, 0x606b, 0x606c, 0x606e, 0x606f, 0x6070, 0x6071, 0x6073,
+ 0x6074, 0x6075, 0x6077, 0x6078, 0x607a, 0x607b, 0x607d, 0x607f,
+ 0x6060, 0x6060, 0x6060, 0x6060, 0x6061, 0x6061, 0x6062, 0x6062,
+ 0x6063, 0x6064, 0x6065, 0x6065, 0x6066, 0x6067, 0x6068, 0x6069,
+ 0x606a, 0x606b, 0x606c, 0x606e, 0x606f, 0x6070, 0x6071, 0x6073,
+ 0x6074, 0x6075, 0x6077, 0x6078, 0x607a, 0x607b, 0x607d, 0x607f,
+ 0x6080, 0x6080, 0x6080, 0x6080, 0x6081, 0x6081, 0x6082, 0x6082,
+ 0x6083, 0x6084, 0x6085, 0x6085, 0x6086, 0x6087, 0x6088, 0x6089,
+ 0x608a, 0x608b, 0x608c, 0x608e, 0x608f, 0x6090, 0x6091, 0x6093,
+ 0x6094, 0x6095, 0x6097, 0x6098, 0x609a, 0x609b, 0x609d, 0x609f,
+ 0x60a0, 0x60a0, 0x60a0, 0x60a0, 0x60a1, 0x60a1, 0x60a2, 0x60a2,
+ 0x60a3, 0x60a4, 0x60a5, 0x60a5, 0x60a6, 0x60a7, 0x60a8, 0x60a9,
+ 0x60aa, 0x60ab, 0x60ac, 0x60ae, 0x60af, 0x60b0, 0x60b1, 0x60b3,
+ 0x60b4, 0x60b5, 0x60b7, 0x60b8, 0x60ba, 0x60bb, 0x60bd, 0x60bf,
+ 0x60a0, 0x60a0, 0x60a0, 0x60a0, 0x60a1, 0x60a1, 0x60a2, 0x60a2,
+ 0x60a3, 0x60a4, 0x60a5, 0x60a5, 0x60a6, 0x60a7, 0x60a8, 0x60a9,
+ 0x60aa, 0x60ab, 0x60ac, 0x60ae, 0x60af, 0x60b0, 0x60b1, 0x60b3,
+ 0x60b4, 0x60b5, 0x60b7, 0x60b8, 0x60ba, 0x60bb, 0x60bd, 0x60bf,
+ 0x60c0, 0x60c0, 0x60c0, 0x60c0, 0x60c1, 0x60c1, 0x60c2, 0x60c2,
+ 0x60c3, 0x60c4, 0x60c5, 0x60c5, 0x60c6, 0x60c7, 0x60c8, 0x60c9,
+ 0x60ca, 0x60cb, 0x60cc, 0x60ce, 0x60cf, 0x60d0, 0x60d1, 0x60d3,
+ 0x60d4, 0x60d5, 0x60d7, 0x60d8, 0x60da, 0x60db, 0x60dd, 0x60df,
+ 0x60e0, 0x60e0, 0x60e0, 0x60e0, 0x60e1, 0x60e1, 0x60e2, 0x60e2,
+ 0x60e3, 0x60e4, 0x60e5, 0x60e5, 0x60e6, 0x60e7, 0x60e8, 0x60e9,
+ 0x60ea, 0x60eb, 0x60ec, 0x60ee, 0x60ef, 0x60f0, 0x60f1, 0x60f3,
+ 0x60f4, 0x60f5, 0x60f7, 0x60f8, 0x60fa, 0x60fb, 0x60fd, 0x60ff,
+ 0x60e0, 0x60e0, 0x60e0, 0x60e0, 0x60e1, 0x60e1, 0x60e2, 0x60e2,
+ 0x60e3, 0x60e4, 0x60e5, 0x60e5, 0x60e6, 0x60e7, 0x60e8, 0x60e9,
+ 0x60ea, 0x60eb, 0x60ec, 0x60ee, 0x60ef, 0x60f0, 0x60f1, 0x60f3,
+ 0x60f4, 0x60f5, 0x60f7, 0x60f8, 0x60fa, 0x60fb, 0x60fd, 0x60ff,
+ 0x6100, 0x6100, 0x6100, 0x6100, 0x6101, 0x6101, 0x6102, 0x6102,
+ 0x6103, 0x6104, 0x6105, 0x6105, 0x6106, 0x6107, 0x6108, 0x6109,
+ 0x610a, 0x610b, 0x610c, 0x610e, 0x610f, 0x6110, 0x6111, 0x6113,
+ 0x6114, 0x6115, 0x6117, 0x6118, 0x611a, 0x611b, 0x611d, 0x611f,
+ 0x6120, 0x6120, 0x6120, 0x6120, 0x6121, 0x6121, 0x6122, 0x6122,
+ 0x6123, 0x6124, 0x6125, 0x6125, 0x6126, 0x6127, 0x6128, 0x6129,
+ 0x612a, 0x612b, 0x612c, 0x612e, 0x612f, 0x6130, 0x6131, 0x6133,
+ 0x6134, 0x6135, 0x6137, 0x6138, 0x613a, 0x613b, 0x613d, 0x613f,
+ 0x6140, 0x6140, 0x6140, 0x6140, 0x6141, 0x6141, 0x6142, 0x6142,
+ 0x6143, 0x6144, 0x6145, 0x6145, 0x6146, 0x6147, 0x6148, 0x6149,
+ 0x614a, 0x614b, 0x614c, 0x614e, 0x614f, 0x6150, 0x6151, 0x6153,
+ 0x6154, 0x6155, 0x6157, 0x6158, 0x615a, 0x615b, 0x615d, 0x615f,
+ 0x6140, 0x6140, 0x6140, 0x6140, 0x6141, 0x6141, 0x6142, 0x6142,
+ 0x6143, 0x6144, 0x6145, 0x6145, 0x6146, 0x6147, 0x6148, 0x6149,
+ 0x614a, 0x614b, 0x614c, 0x614e, 0x614f, 0x6150, 0x6151, 0x6153,
+ 0x6154, 0x6155, 0x6157, 0x6158, 0x615a, 0x615b, 0x615d, 0x615f,
+ 0x6160, 0x6160, 0x6160, 0x6160, 0x6161, 0x6161, 0x6162, 0x6162,
+ 0x6163, 0x6164, 0x6165, 0x6165, 0x6166, 0x6167, 0x6168, 0x6169,
+ 0x616a, 0x616b, 0x616c, 0x616e, 0x616f, 0x6170, 0x6171, 0x6173,
+ 0x6174, 0x6175, 0x6177, 0x6178, 0x617a, 0x617b, 0x617d, 0x617f,
+ 0x6180, 0x6180, 0x6180, 0x6180, 0x6181, 0x6181, 0x6182, 0x6182,
+ 0x6183, 0x6184, 0x6185, 0x6185, 0x6186, 0x6187, 0x6188, 0x6189,
+ 0x618a, 0x618b, 0x618c, 0x618e, 0x618f, 0x6190, 0x6191, 0x6193,
+ 0x6194, 0x6195, 0x6197, 0x6198, 0x619a, 0x619b, 0x619d, 0x619f,
+ 0x61a0, 0x61a0, 0x61a0, 0x61a0, 0x61a1, 0x61a1, 0x61a2, 0x61a2,
+ 0x61a3, 0x61a4, 0x61a5, 0x61a5, 0x61a6, 0x61a7, 0x61a8, 0x61a9,
+ 0x61aa, 0x61ab, 0x61ac, 0x61ae, 0x61af, 0x61b0, 0x61b1, 0x61b3,
+ 0x61b4, 0x61b5, 0x61b7, 0x61b8, 0x61ba, 0x61bb, 0x61bd, 0x61bf,
+ 0x61c0, 0x61c0, 0x61c0, 0x61c0, 0x61c1, 0x61c1, 0x61c2, 0x61c2,
+ 0x61c3, 0x61c4, 0x61c5, 0x61c5, 0x61c6, 0x61c7, 0x61c8, 0x61c9,
+ 0x61ca, 0x61cb, 0x61cc, 0x61ce, 0x61cf, 0x61d0, 0x61d1, 0x61d3,
+ 0x61d4, 0x61d5, 0x61d7, 0x61d8, 0x61da, 0x61db, 0x61dd, 0x61df,
+ 0x61e0, 0x61e0, 0x61e0, 0x61e0, 0x61e1, 0x61e1, 0x61e2, 0x61e2,
+ 0x61e3, 0x61e4, 0x61e5, 0x61e5, 0x61e6, 0x61e7, 0x61e8, 0x61e9,
+ 0x61ea, 0x61eb, 0x61ec, 0x61ee, 0x61ef, 0x61f0, 0x61f1, 0x61f3,
+ 0x61f4, 0x61f5, 0x61f7, 0x61f8, 0x61fa, 0x61fb, 0x61fd, 0x61ff,
+ 0x6200, 0x6200, 0x6200, 0x6200, 0x6201, 0x6201, 0x6202, 0x6202,
+ 0x6203, 0x6204, 0x6205, 0x6205, 0x6206, 0x6207, 0x6208, 0x6209,
+ 0x620a, 0x620b, 0x620c, 0x620e, 0x620f, 0x6210, 0x6211, 0x6213,
+ 0x6214, 0x6215, 0x6217, 0x6218, 0x621a, 0x621b, 0x621d, 0x621f,
+ 0x6220, 0x6220, 0x6220, 0x6220, 0x6221, 0x6221, 0x6222, 0x6222,
+ 0x6223, 0x6224, 0x6225, 0x6225, 0x6226, 0x6227, 0x6228, 0x6229,
+ 0x622a, 0x622b, 0x622c, 0x622e, 0x622f, 0x6230, 0x6231, 0x6233,
+ 0x6234, 0x6235, 0x6237, 0x6238, 0x623a, 0x623b, 0x623d, 0x623f,
+ 0x6240, 0x6240, 0x6240, 0x6240, 0x6241, 0x6241, 0x6242, 0x6242,
+ 0x6243, 0x6244, 0x6245, 0x6245, 0x6246, 0x6247, 0x6248, 0x6249,
+ 0x624a, 0x624b, 0x624c, 0x624e, 0x624f, 0x6250, 0x6251, 0x6253,
+ 0x6254, 0x6255, 0x6257, 0x6258, 0x625a, 0x625b, 0x625d, 0x625f,
+ 0x6260, 0x6260, 0x6260, 0x6260, 0x6261, 0x6261, 0x6262, 0x6262,
+ 0x6263, 0x6264, 0x6265, 0x6265, 0x6266, 0x6267, 0x6268, 0x6269,
+ 0x626a, 0x626b, 0x626c, 0x626e, 0x626f, 0x6270, 0x6271, 0x6273,
+ 0x6274, 0x6275, 0x6277, 0x6278, 0x627a, 0x627b, 0x627d, 0x627f,
+ 0x6280, 0x6280, 0x6280, 0x6280, 0x6281, 0x6281, 0x6282, 0x6282,
+ 0x6283, 0x6284, 0x6285, 0x6285, 0x6286, 0x6287, 0x6288, 0x6289,
+ 0x628a, 0x628b, 0x628c, 0x628e, 0x628f, 0x6290, 0x6291, 0x6293,
+ 0x6294, 0x6295, 0x6297, 0x6298, 0x629a, 0x629b, 0x629d, 0x629f,
+ 0x62a0, 0x62a0, 0x62a0, 0x62a0, 0x62a1, 0x62a1, 0x62a2, 0x62a2,
+ 0x62a3, 0x62a4, 0x62a5, 0x62a5, 0x62a6, 0x62a7, 0x62a8, 0x62a9,
+ 0x62aa, 0x62ab, 0x62ac, 0x62ae, 0x62af, 0x62b0, 0x62b1, 0x62b3,
+ 0x62b4, 0x62b5, 0x62b7, 0x62b8, 0x62ba, 0x62bb, 0x62bd, 0x62bf,
+ 0x62c0, 0x62c0, 0x62c0, 0x62c0, 0x62c1, 0x62c1, 0x62c2, 0x62c2,
+ 0x62c3, 0x62c4, 0x62c5, 0x62c5, 0x62c6, 0x62c7, 0x62c8, 0x62c9,
+ 0x62ca, 0x62cb, 0x62cc, 0x62ce, 0x62cf, 0x62d0, 0x62d1, 0x62d3,
+ 0x62d4, 0x62d5, 0x62d7, 0x62d8, 0x62da, 0x62db, 0x62dd, 0x62df,
+ 0x62e0, 0x62e0, 0x62e0, 0x62e0, 0x62e1, 0x62e1, 0x62e2, 0x62e2,
+ 0x62e3, 0x62e4, 0x62e5, 0x62e5, 0x62e6, 0x62e7, 0x62e8, 0x62e9,
+ 0x62ea, 0x62eb, 0x62ec, 0x62ee, 0x62ef, 0x62f0, 0x62f1, 0x62f3,
+ 0x62f4, 0x62f5, 0x62f7, 0x62f8, 0x62fa, 0x62fb, 0x62fd, 0x62ff,
+ 0x6300, 0x6300, 0x6300, 0x6300, 0x6301, 0x6301, 0x6302, 0x6302,
+ 0x6303, 0x6304, 0x6305, 0x6305, 0x6306, 0x6307, 0x6308, 0x6309,
+ 0x630a, 0x630b, 0x630c, 0x630e, 0x630f, 0x6310, 0x6311, 0x6313,
+ 0x6314, 0x6315, 0x6317, 0x6318, 0x631a, 0x631b, 0x631d, 0x631f,
+ 0x6320, 0x6320, 0x6320, 0x6320, 0x6321, 0x6321, 0x6322, 0x6322,
+ 0x6323, 0x6324, 0x6325, 0x6325, 0x6326, 0x6327, 0x6328, 0x6329,
+ 0x632a, 0x632b, 0x632c, 0x632e, 0x632f, 0x6330, 0x6331, 0x6333,
+ 0x6334, 0x6335, 0x6337, 0x6338, 0x633a, 0x633b, 0x633d, 0x633f,
+ 0x6340, 0x6340, 0x6340, 0x6340, 0x6341, 0x6341, 0x6342, 0x6342,
+ 0x6343, 0x6344, 0x6345, 0x6345, 0x6346, 0x6347, 0x6348, 0x6349,
+ 0x634a, 0x634b, 0x634c, 0x634e, 0x634f, 0x6350, 0x6351, 0x6353,
+ 0x6354, 0x6355, 0x6357, 0x6358, 0x635a, 0x635b, 0x635d, 0x635f,
+ 0x6380, 0x6380, 0x6380, 0x6380, 0x6381, 0x6381, 0x6382, 0x6382,
+ 0x6383, 0x6384, 0x6385, 0x6385, 0x6386, 0x6387, 0x6388, 0x6389,
+ 0x638a, 0x638b, 0x638c, 0x638e, 0x638f, 0x6390, 0x6391, 0x6393,
+ 0x6394, 0x6395, 0x6397, 0x6398, 0x639a, 0x639b, 0x639d, 0x639f,
+ 0x63a0, 0x63a0, 0x63a0, 0x63a0, 0x63a1, 0x63a1, 0x63a2, 0x63a2,
+ 0x63a3, 0x63a4, 0x63a5, 0x63a5, 0x63a6, 0x63a7, 0x63a8, 0x63a9,
+ 0x63aa, 0x63ab, 0x63ac, 0x63ae, 0x63af, 0x63b0, 0x63b1, 0x63b3,
+ 0x63b4, 0x63b5, 0x63b7, 0x63b8, 0x63ba, 0x63bb, 0x63bd, 0x63bf,
+ 0x63c0, 0x63c0, 0x63c0, 0x63c0, 0x63c1, 0x63c1, 0x63c2, 0x63c2,
+ 0x63c3, 0x63c4, 0x63c5, 0x63c5, 0x63c6, 0x63c7, 0x63c8, 0x63c9,
+ 0x63ca, 0x63cb, 0x63cc, 0x63ce, 0x63cf, 0x63d0, 0x63d1, 0x63d3,
+ 0x63d4, 0x63d5, 0x63d7, 0x63d8, 0x63da, 0x63db, 0x63dd, 0x63df,
+ 0x63e0, 0x63e0, 0x63e0, 0x63e0, 0x63e1, 0x63e1, 0x63e2, 0x63e2,
+ 0x63e3, 0x63e4, 0x63e5, 0x63e5, 0x63e6, 0x63e7, 0x63e8, 0x63e9,
+ 0x63ea, 0x63eb, 0x63ec, 0x63ee, 0x63ef, 0x63f0, 0x63f1, 0x63f3,
+ 0x63f4, 0x63f5, 0x63f7, 0x63f8, 0x63fa, 0x63fb, 0x63fd, 0x63ff,
+ 0x6400, 0x6400, 0x6400, 0x6400, 0x6401, 0x6401, 0x6402, 0x6402,
+ 0x6403, 0x6404, 0x6405, 0x6405, 0x6406, 0x6407, 0x6408, 0x6409,
+ 0x640a, 0x640b, 0x640c, 0x640e, 0x640f, 0x6410, 0x6411, 0x6413,
+ 0x6414, 0x6415, 0x6417, 0x6418, 0x641a, 0x641b, 0x641d, 0x641f,
+ 0x6440, 0x6440, 0x6440, 0x6440, 0x6441, 0x6441, 0x6442, 0x6442,
+ 0x6443, 0x6444, 0x6445, 0x6445, 0x6446, 0x6447, 0x6448, 0x6449,
+ 0x644a, 0x644b, 0x644c, 0x644e, 0x644f, 0x6450, 0x6451, 0x6453,
+ 0x6454, 0x6455, 0x6457, 0x6458, 0x645a, 0x645b, 0x645d, 0x645f,
+ 0x6460, 0x6460, 0x6460, 0x6460, 0x6461, 0x6461, 0x6462, 0x6462,
+ 0x6463, 0x6464, 0x6465, 0x6465, 0x6466, 0x6467, 0x6468, 0x6469,
+ 0x646a, 0x646b, 0x646c, 0x646e, 0x646f, 0x6470, 0x6471, 0x6473,
+ 0x6474, 0x6475, 0x6477, 0x6478, 0x647a, 0x647b, 0x647d, 0x647f,
+ 0x6480, 0x6480, 0x6480, 0x6480, 0x6481, 0x6481, 0x6482, 0x6482,
+ 0x6483, 0x6484, 0x6485, 0x6485, 0x6486, 0x6487, 0x6488, 0x6489,
+ 0x648a, 0x648b, 0x648c, 0x648e, 0x648f, 0x6490, 0x6491, 0x6493,
+ 0x6494, 0x6495, 0x6497, 0x6498, 0x649a, 0x649b, 0x649d, 0x649f,
+ 0x64c0, 0x64c0, 0x64c0, 0x64c0, 0x64c1, 0x64c1, 0x64c2, 0x64c2,
+ 0x64c3, 0x64c4, 0x64c5, 0x64c5, 0x64c6, 0x64c7, 0x64c8, 0x64c9,
+ 0x64ca, 0x64cb, 0x64cc, 0x64ce, 0x64cf, 0x64d0, 0x64d1, 0x64d3,
+ 0x64d4, 0x64d5, 0x64d7, 0x64d8, 0x64da, 0x64db, 0x64dd, 0x64df,
+ 0x64e0, 0x64e0, 0x64e0, 0x64e0, 0x64e1, 0x64e1, 0x64e2, 0x64e2,
+ 0x64e3, 0x64e4, 0x64e5, 0x64e5, 0x64e6, 0x64e7, 0x64e8, 0x64e9,
+ 0x64ea, 0x64eb, 0x64ec, 0x64ee, 0x64ef, 0x64f0, 0x64f1, 0x64f3,
+ 0x64f4, 0x64f5, 0x64f7, 0x64f8, 0x64fa, 0x64fb, 0x64fd, 0x64ff,
+ 0x6500, 0x6500, 0x6500, 0x6500, 0x6501, 0x6501, 0x6502, 0x6502,
+ 0x6503, 0x6504, 0x6505, 0x6505, 0x6506, 0x6507, 0x6508, 0x6509,
+ 0x650a, 0x650b, 0x650c, 0x650e, 0x650f, 0x6510, 0x6511, 0x6513,
+ 0x6514, 0x6515, 0x6517, 0x6518, 0x651a, 0x651b, 0x651d, 0x651f,
+ 0x6540, 0x6540, 0x6540, 0x6540, 0x6541, 0x6541, 0x6542, 0x6542,
+ 0x6543, 0x6544, 0x6545, 0x6545, 0x6546, 0x6547, 0x6548, 0x6549,
+ 0x654a, 0x654b, 0x654c, 0x654e, 0x654f, 0x6550, 0x6551, 0x6553,
+ 0x6554, 0x6555, 0x6557, 0x6558, 0x655a, 0x655b, 0x655d, 0x655f,
+ 0x6560, 0x6560, 0x6560, 0x6560, 0x6561, 0x6561, 0x6562, 0x6562,
+ 0x6563, 0x6564, 0x6565, 0x6565, 0x6566, 0x6567, 0x6568, 0x6569,
+ 0x656a, 0x656b, 0x656c, 0x656e, 0x656f, 0x6570, 0x6571, 0x6573,
+ 0x6574, 0x6575, 0x6577, 0x6578, 0x657a, 0x657b, 0x657d, 0x657f,
+ 0x6580, 0x6580, 0x6580, 0x6580, 0x6581, 0x6581, 0x6582, 0x6582,
+ 0x6583, 0x6584, 0x6585, 0x6585, 0x6586, 0x6587, 0x6588, 0x6589,
+ 0x658a, 0x658b, 0x658c, 0x658e, 0x658f, 0x6590, 0x6591, 0x6593,
+ 0x6594, 0x6595, 0x6597, 0x6598, 0x659a, 0x659b, 0x659d, 0x659f,
+ 0x65c0, 0x65c0, 0x65c0, 0x65c0, 0x65c1, 0x65c1, 0x65c2, 0x65c2,
+ 0x65c3, 0x65c4, 0x65c5, 0x65c5, 0x65c6, 0x65c7, 0x65c8, 0x65c9,
+ 0x65ca, 0x65cb, 0x65cc, 0x65ce, 0x65cf, 0x65d0, 0x65d1, 0x65d3,
+ 0x65d4, 0x65d5, 0x65d7, 0x65d8, 0x65da, 0x65db, 0x65dd, 0x65df,
+ 0x65e0, 0x65e0, 0x65e0, 0x65e0, 0x65e1, 0x65e1, 0x65e2, 0x65e2,
+ 0x65e3, 0x65e4, 0x65e5, 0x65e5, 0x65e6, 0x65e7, 0x65e8, 0x65e9,
+ 0x65ea, 0x65eb, 0x65ec, 0x65ee, 0x65ef, 0x65f0, 0x65f1, 0x65f3,
+ 0x65f4, 0x65f5, 0x65f7, 0x65f8, 0x65fa, 0x65fb, 0x65fd, 0x65ff,
+ 0x6620, 0x6620, 0x6620, 0x6620, 0x6621, 0x6621, 0x6622, 0x6622,
+ 0x6623, 0x6624, 0x6625, 0x6625, 0x6626, 0x6627, 0x6628, 0x6629,
+ 0x662a, 0x662b, 0x662c, 0x662e, 0x662f, 0x6630, 0x6631, 0x6633,
+ 0x6634, 0x6635, 0x6637, 0x6638, 0x663a, 0x663b, 0x663d, 0x663f,
+ 0x6640, 0x6640, 0x6640, 0x6640, 0x6641, 0x6641, 0x6642, 0x6642,
+ 0x6643, 0x6644, 0x6645, 0x6645, 0x6646, 0x6647, 0x6648, 0x6649,
+ 0x664a, 0x664b, 0x664c, 0x664e, 0x664f, 0x6650, 0x6651, 0x6653,
+ 0x6654, 0x6655, 0x6657, 0x6658, 0x665a, 0x665b, 0x665d, 0x665f,
+ 0x6680, 0x6680, 0x6680, 0x6680, 0x6681, 0x6681, 0x6682, 0x6682,
+ 0x6683, 0x6684, 0x6685, 0x6685, 0x6686, 0x6687, 0x6688, 0x6689,
+ 0x668a, 0x668b, 0x668c, 0x668e, 0x668f, 0x6690, 0x6691, 0x6693,
+ 0x6694, 0x6695, 0x6697, 0x6698, 0x669a, 0x669b, 0x669d, 0x669f,
+ 0x66a0, 0x66a0, 0x66a0, 0x66a0, 0x66a1, 0x66a1, 0x66a2, 0x66a2,
+ 0x66a3, 0x66a4, 0x66a5, 0x66a5, 0x66a6, 0x66a7, 0x66a8, 0x66a9,
+ 0x66aa, 0x66ab, 0x66ac, 0x66ae, 0x66af, 0x66b0, 0x66b1, 0x66b3,
+ 0x66b4, 0x66b5, 0x66b7, 0x66b8, 0x66ba, 0x66bb, 0x66bd, 0x66bf,
+ 0x66e0, 0x66e0, 0x66e0, 0x66e0, 0x66e1, 0x66e1, 0x66e2, 0x66e2,
+ 0x66e3, 0x66e4, 0x66e5, 0x66e5, 0x66e6, 0x66e7, 0x66e8, 0x66e9,
+ 0x66ea, 0x66eb, 0x66ec, 0x66ee, 0x66ef, 0x66f0, 0x66f1, 0x66f3,
+ 0x66f4, 0x66f5, 0x66f7, 0x66f8, 0x66fa, 0x66fb, 0x66fd, 0x66ff,
+ 0x6700, 0x6700, 0x6700, 0x6700, 0x6701, 0x6701, 0x6702, 0x6702,
+ 0x6703, 0x6704, 0x6705, 0x6705, 0x6706, 0x6707, 0x6708, 0x6709,
+ 0x670a, 0x670b, 0x670c, 0x670e, 0x670f, 0x6710, 0x6711, 0x6713,
+ 0x6714, 0x6715, 0x6717, 0x6718, 0x671a, 0x671b, 0x671d, 0x671f,
+ 0x6740, 0x6740, 0x6740, 0x6740, 0x6741, 0x6741, 0x6742, 0x6742,
+ 0x6743, 0x6744, 0x6745, 0x6745, 0x6746, 0x6747, 0x6748, 0x6749,
+ 0x674a, 0x674b, 0x674c, 0x674e, 0x674f, 0x6750, 0x6751, 0x6753,
+ 0x6754, 0x6755, 0x6757, 0x6758, 0x675a, 0x675b, 0x675d, 0x675f,
+ 0x6760, 0x6760, 0x6760, 0x6760, 0x6761, 0x6761, 0x6762, 0x6762,
+ 0x6763, 0x6764, 0x6765, 0x6765, 0x6766, 0x6767, 0x6768, 0x6769,
+ 0x676a, 0x676b, 0x676c, 0x676e, 0x676f, 0x6770, 0x6771, 0x6773,
+ 0x6774, 0x6775, 0x6777, 0x6778, 0x677a, 0x677b, 0x677d, 0x677f,
+ 0x67a0, 0x67a0, 0x67a0, 0x67a0, 0x67a1, 0x67a1, 0x67a2, 0x67a2,
+ 0x67a3, 0x67a4, 0x67a5, 0x67a5, 0x67a6, 0x67a7, 0x67a8, 0x67a9,
+ 0x67aa, 0x67ab, 0x67ac, 0x67ae, 0x67af, 0x67b0, 0x67b1, 0x67b3,
+ 0x67b4, 0x67b5, 0x67b7, 0x67b8, 0x67ba, 0x67bb, 0x67bd, 0x67bf,
+ 0x67e0, 0x67e0, 0x67e0, 0x67e0, 0x67e1, 0x67e1, 0x67e2, 0x67e2,
+ 0x67e3, 0x67e4, 0x67e5, 0x67e5, 0x67e6, 0x67e7, 0x67e8, 0x67e9,
+ 0x67ea, 0x67eb, 0x67ec, 0x67ee, 0x67ef, 0x67f0, 0x67f1, 0x67f3,
+ 0x67f4, 0x67f5, 0x67f7, 0x67f8, 0x67fa, 0x67fb, 0x67fd, 0x67ff,
+ 0x7000, 0x7000, 0x7000, 0x7000, 0x7001, 0x7001, 0x7002, 0x7002,
+ 0x7003, 0x7004, 0x7005, 0x7005, 0x7006, 0x7007, 0x7008, 0x7009,
+ 0x700a, 0x700b, 0x700c, 0x700e, 0x700f, 0x7010, 0x7011, 0x7013,
+ 0x7014, 0x7015, 0x7017, 0x7018, 0x701a, 0x701b, 0x701d, 0x701f,
+ 0x7000, 0x7000, 0x7000, 0x7000, 0x7001, 0x7001, 0x7002, 0x7002,
+ 0x7003, 0x7004, 0x7005, 0x7005, 0x7006, 0x7007, 0x7008, 0x7009,
+ 0x700a, 0x700b, 0x700c, 0x700e, 0x700f, 0x7010, 0x7011, 0x7013,
+ 0x7014, 0x7015, 0x7017, 0x7018, 0x701a, 0x701b, 0x701d, 0x701f,
+ 0x7000, 0x7000, 0x7000, 0x7000, 0x7001, 0x7001, 0x7002, 0x7002,
+ 0x7003, 0x7004, 0x7005, 0x7005, 0x7006, 0x7007, 0x7008, 0x7009,
+ 0x700a, 0x700b, 0x700c, 0x700e, 0x700f, 0x7010, 0x7011, 0x7013,
+ 0x7014, 0x7015, 0x7017, 0x7018, 0x701a, 0x701b, 0x701d, 0x701f,
+ 0x7000, 0x7000, 0x7000, 0x7000, 0x7001, 0x7001, 0x7002, 0x7002,
+ 0x7003, 0x7004, 0x7005, 0x7005, 0x7006, 0x7007, 0x7008, 0x7009,
+ 0x700a, 0x700b, 0x700c, 0x700e, 0x700f, 0x7010, 0x7011, 0x7013,
+ 0x7014, 0x7015, 0x7017, 0x7018, 0x701a, 0x701b, 0x701d, 0x701f,
+ 0x7000, 0x7000, 0x7000, 0x7000, 0x7001, 0x7001, 0x7002, 0x7002,
+ 0x7003, 0x7004, 0x7005, 0x7005, 0x7006, 0x7007, 0x7008, 0x7009,
+ 0x700a, 0x700b, 0x700c, 0x700e, 0x700f, 0x7010, 0x7011, 0x7013,
+ 0x7014, 0x7015, 0x7017, 0x7018, 0x701a, 0x701b, 0x701d, 0x701f,
+ 0x7020, 0x7020, 0x7020, 0x7020, 0x7021, 0x7021, 0x7022, 0x7022,
+ 0x7023, 0x7024, 0x7025, 0x7025, 0x7026, 0x7027, 0x7028, 0x7029,
+ 0x702a, 0x702b, 0x702c, 0x702e, 0x702f, 0x7030, 0x7031, 0x7033,
+ 0x7034, 0x7035, 0x7037, 0x7038, 0x703a, 0x703b, 0x703d, 0x703f,
+ 0x7020, 0x7020, 0x7020, 0x7020, 0x7021, 0x7021, 0x7022, 0x7022,
+ 0x7023, 0x7024, 0x7025, 0x7025, 0x7026, 0x7027, 0x7028, 0x7029,
+ 0x702a, 0x702b, 0x702c, 0x702e, 0x702f, 0x7030, 0x7031, 0x7033,
+ 0x7034, 0x7035, 0x7037, 0x7038, 0x703a, 0x703b, 0x703d, 0x703f,
+ 0x7020, 0x7020, 0x7020, 0x7020, 0x7021, 0x7021, 0x7022, 0x7022,
+ 0x7023, 0x7024, 0x7025, 0x7025, 0x7026, 0x7027, 0x7028, 0x7029,
+ 0x702a, 0x702b, 0x702c, 0x702e, 0x702f, 0x7030, 0x7031, 0x7033,
+ 0x7034, 0x7035, 0x7037, 0x7038, 0x703a, 0x703b, 0x703d, 0x703f,
+ 0x7040, 0x7040, 0x7040, 0x7040, 0x7041, 0x7041, 0x7042, 0x7042,
+ 0x7043, 0x7044, 0x7045, 0x7045, 0x7046, 0x7047, 0x7048, 0x7049,
+ 0x704a, 0x704b, 0x704c, 0x704e, 0x704f, 0x7050, 0x7051, 0x7053,
+ 0x7054, 0x7055, 0x7057, 0x7058, 0x705a, 0x705b, 0x705d, 0x705f,
+ 0x7040, 0x7040, 0x7040, 0x7040, 0x7041, 0x7041, 0x7042, 0x7042,
+ 0x7043, 0x7044, 0x7045, 0x7045, 0x7046, 0x7047, 0x7048, 0x7049,
+ 0x704a, 0x704b, 0x704c, 0x704e, 0x704f, 0x7050, 0x7051, 0x7053,
+ 0x7054, 0x7055, 0x7057, 0x7058, 0x705a, 0x705b, 0x705d, 0x705f,
+ 0x7060, 0x7060, 0x7060, 0x7060, 0x7061, 0x7061, 0x7062, 0x7062,
+ 0x7063, 0x7064, 0x7065, 0x7065, 0x7066, 0x7067, 0x7068, 0x7069,
+ 0x706a, 0x706b, 0x706c, 0x706e, 0x706f, 0x7070, 0x7071, 0x7073,
+ 0x7074, 0x7075, 0x7077, 0x7078, 0x707a, 0x707b, 0x707d, 0x707f,
+ 0x7060, 0x7060, 0x7060, 0x7060, 0x7061, 0x7061, 0x7062, 0x7062,
+ 0x7063, 0x7064, 0x7065, 0x7065, 0x7066, 0x7067, 0x7068, 0x7069,
+ 0x706a, 0x706b, 0x706c, 0x706e, 0x706f, 0x7070, 0x7071, 0x7073,
+ 0x7074, 0x7075, 0x7077, 0x7078, 0x707a, 0x707b, 0x707d, 0x707f,
+ 0x7080, 0x7080, 0x7080, 0x7080, 0x7081, 0x7081, 0x7082, 0x7082,
+ 0x7083, 0x7084, 0x7085, 0x7085, 0x7086, 0x7087, 0x7088, 0x7089,
+ 0x708a, 0x708b, 0x708c, 0x708e, 0x708f, 0x7090, 0x7091, 0x7093,
+ 0x7094, 0x7095, 0x7097, 0x7098, 0x709a, 0x709b, 0x709d, 0x709f,
+ 0x70a0, 0x70a0, 0x70a0, 0x70a0, 0x70a1, 0x70a1, 0x70a2, 0x70a2,
+ 0x70a3, 0x70a4, 0x70a5, 0x70a5, 0x70a6, 0x70a7, 0x70a8, 0x70a9,
+ 0x70aa, 0x70ab, 0x70ac, 0x70ae, 0x70af, 0x70b0, 0x70b1, 0x70b3,
+ 0x70b4, 0x70b5, 0x70b7, 0x70b8, 0x70ba, 0x70bb, 0x70bd, 0x70bf,
+ 0x70a0, 0x70a0, 0x70a0, 0x70a0, 0x70a1, 0x70a1, 0x70a2, 0x70a2,
+ 0x70a3, 0x70a4, 0x70a5, 0x70a5, 0x70a6, 0x70a7, 0x70a8, 0x70a9,
+ 0x70aa, 0x70ab, 0x70ac, 0x70ae, 0x70af, 0x70b0, 0x70b1, 0x70b3,
+ 0x70b4, 0x70b5, 0x70b7, 0x70b8, 0x70ba, 0x70bb, 0x70bd, 0x70bf,
+ 0x70c0, 0x70c0, 0x70c0, 0x70c0, 0x70c1, 0x70c1, 0x70c2, 0x70c2,
+ 0x70c3, 0x70c4, 0x70c5, 0x70c5, 0x70c6, 0x70c7, 0x70c8, 0x70c9,
+ 0x70ca, 0x70cb, 0x70cc, 0x70ce, 0x70cf, 0x70d0, 0x70d1, 0x70d3,
+ 0x70d4, 0x70d5, 0x70d7, 0x70d8, 0x70da, 0x70db, 0x70dd, 0x70df,
+ 0x70e0, 0x70e0, 0x70e0, 0x70e0, 0x70e1, 0x70e1, 0x70e2, 0x70e2,
+ 0x70e3, 0x70e4, 0x70e5, 0x70e5, 0x70e6, 0x70e7, 0x70e8, 0x70e9,
+ 0x70ea, 0x70eb, 0x70ec, 0x70ee, 0x70ef, 0x70f0, 0x70f1, 0x70f3,
+ 0x70f4, 0x70f5, 0x70f7, 0x70f8, 0x70fa, 0x70fb, 0x70fd, 0x70ff,
+ 0x70e0, 0x70e0, 0x70e0, 0x70e0, 0x70e1, 0x70e1, 0x70e2, 0x70e2,
+ 0x70e3, 0x70e4, 0x70e5, 0x70e5, 0x70e6, 0x70e7, 0x70e8, 0x70e9,
+ 0x70ea, 0x70eb, 0x70ec, 0x70ee, 0x70ef, 0x70f0, 0x70f1, 0x70f3,
+ 0x70f4, 0x70f5, 0x70f7, 0x70f8, 0x70fa, 0x70fb, 0x70fd, 0x70ff,
+ 0x7100, 0x7100, 0x7100, 0x7100, 0x7101, 0x7101, 0x7102, 0x7102,
+ 0x7103, 0x7104, 0x7105, 0x7105, 0x7106, 0x7107, 0x7108, 0x7109,
+ 0x710a, 0x710b, 0x710c, 0x710e, 0x710f, 0x7110, 0x7111, 0x7113,
+ 0x7114, 0x7115, 0x7117, 0x7118, 0x711a, 0x711b, 0x711d, 0x711f,
+ 0x7120, 0x7120, 0x7120, 0x7120, 0x7121, 0x7121, 0x7122, 0x7122,
+ 0x7123, 0x7124, 0x7125, 0x7125, 0x7126, 0x7127, 0x7128, 0x7129,
+ 0x712a, 0x712b, 0x712c, 0x712e, 0x712f, 0x7130, 0x7131, 0x7133,
+ 0x7134, 0x7135, 0x7137, 0x7138, 0x713a, 0x713b, 0x713d, 0x713f,
+ 0x7140, 0x7140, 0x7140, 0x7140, 0x7141, 0x7141, 0x7142, 0x7142,
+ 0x7143, 0x7144, 0x7145, 0x7145, 0x7146, 0x7147, 0x7148, 0x7149,
+ 0x714a, 0x714b, 0x714c, 0x714e, 0x714f, 0x7150, 0x7151, 0x7153,
+ 0x7154, 0x7155, 0x7157, 0x7158, 0x715a, 0x715b, 0x715d, 0x715f,
+ 0x7140, 0x7140, 0x7140, 0x7140, 0x7141, 0x7141, 0x7142, 0x7142,
+ 0x7143, 0x7144, 0x7145, 0x7145, 0x7146, 0x7147, 0x7148, 0x7149,
+ 0x714a, 0x714b, 0x714c, 0x714e, 0x714f, 0x7150, 0x7151, 0x7153,
+ 0x7154, 0x7155, 0x7157, 0x7158, 0x715a, 0x715b, 0x715d, 0x715f,
+ 0x7160, 0x7160, 0x7160, 0x7160, 0x7161, 0x7161, 0x7162, 0x7162,
+ 0x7163, 0x7164, 0x7165, 0x7165, 0x7166, 0x7167, 0x7168, 0x7169,
+ 0x716a, 0x716b, 0x716c, 0x716e, 0x716f, 0x7170, 0x7171, 0x7173,
+ 0x7174, 0x7175, 0x7177, 0x7178, 0x717a, 0x717b, 0x717d, 0x717f,
+ 0x7180, 0x7180, 0x7180, 0x7180, 0x7181, 0x7181, 0x7182, 0x7182,
+ 0x7183, 0x7184, 0x7185, 0x7185, 0x7186, 0x7187, 0x7188, 0x7189,
+ 0x718a, 0x718b, 0x718c, 0x718e, 0x718f, 0x7190, 0x7191, 0x7193,
+ 0x7194, 0x7195, 0x7197, 0x7198, 0x719a, 0x719b, 0x719d, 0x719f,
+ 0x71a0, 0x71a0, 0x71a0, 0x71a0, 0x71a1, 0x71a1, 0x71a2, 0x71a2,
+ 0x71a3, 0x71a4, 0x71a5, 0x71a5, 0x71a6, 0x71a7, 0x71a8, 0x71a9,
+ 0x71aa, 0x71ab, 0x71ac, 0x71ae, 0x71af, 0x71b0, 0x71b1, 0x71b3,
+ 0x71b4, 0x71b5, 0x71b7, 0x71b8, 0x71ba, 0x71bb, 0x71bd, 0x71bf,
+ 0x71c0, 0x71c0, 0x71c0, 0x71c0, 0x71c1, 0x71c1, 0x71c2, 0x71c2,
+ 0x71c3, 0x71c4, 0x71c5, 0x71c5, 0x71c6, 0x71c7, 0x71c8, 0x71c9,
+ 0x71ca, 0x71cb, 0x71cc, 0x71ce, 0x71cf, 0x71d0, 0x71d1, 0x71d3,
+ 0x71d4, 0x71d5, 0x71d7, 0x71d8, 0x71da, 0x71db, 0x71dd, 0x71df,
+ 0x71e0, 0x71e0, 0x71e0, 0x71e0, 0x71e1, 0x71e1, 0x71e2, 0x71e2,
+ 0x71e3, 0x71e4, 0x71e5, 0x71e5, 0x71e6, 0x71e7, 0x71e8, 0x71e9,
+ 0x71ea, 0x71eb, 0x71ec, 0x71ee, 0x71ef, 0x71f0, 0x71f1, 0x71f3,
+ 0x71f4, 0x71f5, 0x71f7, 0x71f8, 0x71fa, 0x71fb, 0x71fd, 0x71ff,
+ 0x7200, 0x7200, 0x7200, 0x7200, 0x7201, 0x7201, 0x7202, 0x7202,
+ 0x7203, 0x7204, 0x7205, 0x7205, 0x7206, 0x7207, 0x7208, 0x7209,
+ 0x720a, 0x720b, 0x720c, 0x720e, 0x720f, 0x7210, 0x7211, 0x7213,
+ 0x7214, 0x7215, 0x7217, 0x7218, 0x721a, 0x721b, 0x721d, 0x721f,
+ 0x7220, 0x7220, 0x7220, 0x7220, 0x7221, 0x7221, 0x7222, 0x7222,
+ 0x7223, 0x7224, 0x7225, 0x7225, 0x7226, 0x7227, 0x7228, 0x7229,
+ 0x722a, 0x722b, 0x722c, 0x722e, 0x722f, 0x7230, 0x7231, 0x7233,
+ 0x7234, 0x7235, 0x7237, 0x7238, 0x723a, 0x723b, 0x723d, 0x723f,
+ 0x7240, 0x7240, 0x7240, 0x7240, 0x7241, 0x7241, 0x7242, 0x7242,
+ 0x7243, 0x7244, 0x7245, 0x7245, 0x7246, 0x7247, 0x7248, 0x7249,
+ 0x724a, 0x724b, 0x724c, 0x724e, 0x724f, 0x7250, 0x7251, 0x7253,
+ 0x7254, 0x7255, 0x7257, 0x7258, 0x725a, 0x725b, 0x725d, 0x725f,
+ 0x7260, 0x7260, 0x7260, 0x7260, 0x7261, 0x7261, 0x7262, 0x7262,
+ 0x7263, 0x7264, 0x7265, 0x7265, 0x7266, 0x7267, 0x7268, 0x7269,
+ 0x726a, 0x726b, 0x726c, 0x726e, 0x726f, 0x7270, 0x7271, 0x7273,
+ 0x7274, 0x7275, 0x7277, 0x7278, 0x727a, 0x727b, 0x727d, 0x727f,
+ 0x7280, 0x7280, 0x7280, 0x7280, 0x7281, 0x7281, 0x7282, 0x7282,
+ 0x7283, 0x7284, 0x7285, 0x7285, 0x7286, 0x7287, 0x7288, 0x7289,
+ 0x728a, 0x728b, 0x728c, 0x728e, 0x728f, 0x7290, 0x7291, 0x7293,
+ 0x7294, 0x7295, 0x7297, 0x7298, 0x729a, 0x729b, 0x729d, 0x729f,
+ 0x72a0, 0x72a0, 0x72a0, 0x72a0, 0x72a1, 0x72a1, 0x72a2, 0x72a2,
+ 0x72a3, 0x72a4, 0x72a5, 0x72a5, 0x72a6, 0x72a7, 0x72a8, 0x72a9,
+ 0x72aa, 0x72ab, 0x72ac, 0x72ae, 0x72af, 0x72b0, 0x72b1, 0x72b3,
+ 0x72b4, 0x72b5, 0x72b7, 0x72b8, 0x72ba, 0x72bb, 0x72bd, 0x72bf,
+ 0x72c0, 0x72c0, 0x72c0, 0x72c0, 0x72c1, 0x72c1, 0x72c2, 0x72c2,
+ 0x72c3, 0x72c4, 0x72c5, 0x72c5, 0x72c6, 0x72c7, 0x72c8, 0x72c9,
+ 0x72ca, 0x72cb, 0x72cc, 0x72ce, 0x72cf, 0x72d0, 0x72d1, 0x72d3,
+ 0x72d4, 0x72d5, 0x72d7, 0x72d8, 0x72da, 0x72db, 0x72dd, 0x72df,
+ 0x72e0, 0x72e0, 0x72e0, 0x72e0, 0x72e1, 0x72e1, 0x72e2, 0x72e2,
+ 0x72e3, 0x72e4, 0x72e5, 0x72e5, 0x72e6, 0x72e7, 0x72e8, 0x72e9,
+ 0x72ea, 0x72eb, 0x72ec, 0x72ee, 0x72ef, 0x72f0, 0x72f1, 0x72f3,
+ 0x72f4, 0x72f5, 0x72f7, 0x72f8, 0x72fa, 0x72fb, 0x72fd, 0x72ff,
+ 0x7300, 0x7300, 0x7300, 0x7300, 0x7301, 0x7301, 0x7302, 0x7302,
+ 0x7303, 0x7304, 0x7305, 0x7305, 0x7306, 0x7307, 0x7308, 0x7309,
+ 0x730a, 0x730b, 0x730c, 0x730e, 0x730f, 0x7310, 0x7311, 0x7313,
+ 0x7314, 0x7315, 0x7317, 0x7318, 0x731a, 0x731b, 0x731d, 0x731f,
+ 0x7320, 0x7320, 0x7320, 0x7320, 0x7321, 0x7321, 0x7322, 0x7322,
+ 0x7323, 0x7324, 0x7325, 0x7325, 0x7326, 0x7327, 0x7328, 0x7329,
+ 0x732a, 0x732b, 0x732c, 0x732e, 0x732f, 0x7330, 0x7331, 0x7333,
+ 0x7334, 0x7335, 0x7337, 0x7338, 0x733a, 0x733b, 0x733d, 0x733f,
+ 0x7340, 0x7340, 0x7340, 0x7340, 0x7341, 0x7341, 0x7342, 0x7342,
+ 0x7343, 0x7344, 0x7345, 0x7345, 0x7346, 0x7347, 0x7348, 0x7349,
+ 0x734a, 0x734b, 0x734c, 0x734e, 0x734f, 0x7350, 0x7351, 0x7353,
+ 0x7354, 0x7355, 0x7357, 0x7358, 0x735a, 0x735b, 0x735d, 0x735f,
+ 0x7380, 0x7380, 0x7380, 0x7380, 0x7381, 0x7381, 0x7382, 0x7382,
+ 0x7383, 0x7384, 0x7385, 0x7385, 0x7386, 0x7387, 0x7388, 0x7389,
+ 0x738a, 0x738b, 0x738c, 0x738e, 0x738f, 0x7390, 0x7391, 0x7393,
+ 0x7394, 0x7395, 0x7397, 0x7398, 0x739a, 0x739b, 0x739d, 0x739f,
+ 0x73a0, 0x73a0, 0x73a0, 0x73a0, 0x73a1, 0x73a1, 0x73a2, 0x73a2,
+ 0x73a3, 0x73a4, 0x73a5, 0x73a5, 0x73a6, 0x73a7, 0x73a8, 0x73a9,
+ 0x73aa, 0x73ab, 0x73ac, 0x73ae, 0x73af, 0x73b0, 0x73b1, 0x73b3,
+ 0x73b4, 0x73b5, 0x73b7, 0x73b8, 0x73ba, 0x73bb, 0x73bd, 0x73bf,
+ 0x73c0, 0x73c0, 0x73c0, 0x73c0, 0x73c1, 0x73c1, 0x73c2, 0x73c2,
+ 0x73c3, 0x73c4, 0x73c5, 0x73c5, 0x73c6, 0x73c7, 0x73c8, 0x73c9,
+ 0x73ca, 0x73cb, 0x73cc, 0x73ce, 0x73cf, 0x73d0, 0x73d1, 0x73d3,
+ 0x73d4, 0x73d5, 0x73d7, 0x73d8, 0x73da, 0x73db, 0x73dd, 0x73df,
+ 0x73e0, 0x73e0, 0x73e0, 0x73e0, 0x73e1, 0x73e1, 0x73e2, 0x73e2,
+ 0x73e3, 0x73e4, 0x73e5, 0x73e5, 0x73e6, 0x73e7, 0x73e8, 0x73e9,
+ 0x73ea, 0x73eb, 0x73ec, 0x73ee, 0x73ef, 0x73f0, 0x73f1, 0x73f3,
+ 0x73f4, 0x73f5, 0x73f7, 0x73f8, 0x73fa, 0x73fb, 0x73fd, 0x73ff,
+ 0x7400, 0x7400, 0x7400, 0x7400, 0x7401, 0x7401, 0x7402, 0x7402,
+ 0x7403, 0x7404, 0x7405, 0x7405, 0x7406, 0x7407, 0x7408, 0x7409,
+ 0x740a, 0x740b, 0x740c, 0x740e, 0x740f, 0x7410, 0x7411, 0x7413,
+ 0x7414, 0x7415, 0x7417, 0x7418, 0x741a, 0x741b, 0x741d, 0x741f,
+ 0x7440, 0x7440, 0x7440, 0x7440, 0x7441, 0x7441, 0x7442, 0x7442,
+ 0x7443, 0x7444, 0x7445, 0x7445, 0x7446, 0x7447, 0x7448, 0x7449,
+ 0x744a, 0x744b, 0x744c, 0x744e, 0x744f, 0x7450, 0x7451, 0x7453,
+ 0x7454, 0x7455, 0x7457, 0x7458, 0x745a, 0x745b, 0x745d, 0x745f,
+ 0x7460, 0x7460, 0x7460, 0x7460, 0x7461, 0x7461, 0x7462, 0x7462,
+ 0x7463, 0x7464, 0x7465, 0x7465, 0x7466, 0x7467, 0x7468, 0x7469,
+ 0x746a, 0x746b, 0x746c, 0x746e, 0x746f, 0x7470, 0x7471, 0x7473,
+ 0x7474, 0x7475, 0x7477, 0x7478, 0x747a, 0x747b, 0x747d, 0x747f,
+ 0x7480, 0x7480, 0x7480, 0x7480, 0x7481, 0x7481, 0x7482, 0x7482,
+ 0x7483, 0x7484, 0x7485, 0x7485, 0x7486, 0x7487, 0x7488, 0x7489,
+ 0x748a, 0x748b, 0x748c, 0x748e, 0x748f, 0x7490, 0x7491, 0x7493,
+ 0x7494, 0x7495, 0x7497, 0x7498, 0x749a, 0x749b, 0x749d, 0x749f,
+ 0x74c0, 0x74c0, 0x74c0, 0x74c0, 0x74c1, 0x74c1, 0x74c2, 0x74c2,
+ 0x74c3, 0x74c4, 0x74c5, 0x74c5, 0x74c6, 0x74c7, 0x74c8, 0x74c9,
+ 0x74ca, 0x74cb, 0x74cc, 0x74ce, 0x74cf, 0x74d0, 0x74d1, 0x74d3,
+ 0x74d4, 0x74d5, 0x74d7, 0x74d8, 0x74da, 0x74db, 0x74dd, 0x74df,
+ 0x74e0, 0x74e0, 0x74e0, 0x74e0, 0x74e1, 0x74e1, 0x74e2, 0x74e2,
+ 0x74e3, 0x74e4, 0x74e5, 0x74e5, 0x74e6, 0x74e7, 0x74e8, 0x74e9,
+ 0x74ea, 0x74eb, 0x74ec, 0x74ee, 0x74ef, 0x74f0, 0x74f1, 0x74f3,
+ 0x74f4, 0x74f5, 0x74f7, 0x74f8, 0x74fa, 0x74fb, 0x74fd, 0x74ff,
+ 0x7500, 0x7500, 0x7500, 0x7500, 0x7501, 0x7501, 0x7502, 0x7502,
+ 0x7503, 0x7504, 0x7505, 0x7505, 0x7506, 0x7507, 0x7508, 0x7509,
+ 0x750a, 0x750b, 0x750c, 0x750e, 0x750f, 0x7510, 0x7511, 0x7513,
+ 0x7514, 0x7515, 0x7517, 0x7518, 0x751a, 0x751b, 0x751d, 0x751f,
+ 0x7540, 0x7540, 0x7540, 0x7540, 0x7541, 0x7541, 0x7542, 0x7542,
+ 0x7543, 0x7544, 0x7545, 0x7545, 0x7546, 0x7547, 0x7548, 0x7549,
+ 0x754a, 0x754b, 0x754c, 0x754e, 0x754f, 0x7550, 0x7551, 0x7553,
+ 0x7554, 0x7555, 0x7557, 0x7558, 0x755a, 0x755b, 0x755d, 0x755f,
+ 0x7560, 0x7560, 0x7560, 0x7560, 0x7561, 0x7561, 0x7562, 0x7562,
+ 0x7563, 0x7564, 0x7565, 0x7565, 0x7566, 0x7567, 0x7568, 0x7569,
+ 0x756a, 0x756b, 0x756c, 0x756e, 0x756f, 0x7570, 0x7571, 0x7573,
+ 0x7574, 0x7575, 0x7577, 0x7578, 0x757a, 0x757b, 0x757d, 0x757f,
+ 0x7580, 0x7580, 0x7580, 0x7580, 0x7581, 0x7581, 0x7582, 0x7582,
+ 0x7583, 0x7584, 0x7585, 0x7585, 0x7586, 0x7587, 0x7588, 0x7589,
+ 0x758a, 0x758b, 0x758c, 0x758e, 0x758f, 0x7590, 0x7591, 0x7593,
+ 0x7594, 0x7595, 0x7597, 0x7598, 0x759a, 0x759b, 0x759d, 0x759f,
+ 0x75c0, 0x75c0, 0x75c0, 0x75c0, 0x75c1, 0x75c1, 0x75c2, 0x75c2,
+ 0x75c3, 0x75c4, 0x75c5, 0x75c5, 0x75c6, 0x75c7, 0x75c8, 0x75c9,
+ 0x75ca, 0x75cb, 0x75cc, 0x75ce, 0x75cf, 0x75d0, 0x75d1, 0x75d3,
+ 0x75d4, 0x75d5, 0x75d7, 0x75d8, 0x75da, 0x75db, 0x75dd, 0x75df,
+ 0x75e0, 0x75e0, 0x75e0, 0x75e0, 0x75e1, 0x75e1, 0x75e2, 0x75e2,
+ 0x75e3, 0x75e4, 0x75e5, 0x75e5, 0x75e6, 0x75e7, 0x75e8, 0x75e9,
+ 0x75ea, 0x75eb, 0x75ec, 0x75ee, 0x75ef, 0x75f0, 0x75f1, 0x75f3,
+ 0x75f4, 0x75f5, 0x75f7, 0x75f8, 0x75fa, 0x75fb, 0x75fd, 0x75ff,
+ 0x7620, 0x7620, 0x7620, 0x7620, 0x7621, 0x7621, 0x7622, 0x7622,
+ 0x7623, 0x7624, 0x7625, 0x7625, 0x7626, 0x7627, 0x7628, 0x7629,
+ 0x762a, 0x762b, 0x762c, 0x762e, 0x762f, 0x7630, 0x7631, 0x7633,
+ 0x7634, 0x7635, 0x7637, 0x7638, 0x763a, 0x763b, 0x763d, 0x763f,
+ 0x7640, 0x7640, 0x7640, 0x7640, 0x7641, 0x7641, 0x7642, 0x7642,
+ 0x7643, 0x7644, 0x7645, 0x7645, 0x7646, 0x7647, 0x7648, 0x7649,
+ 0x764a, 0x764b, 0x764c, 0x764e, 0x764f, 0x7650, 0x7651, 0x7653,
+ 0x7654, 0x7655, 0x7657, 0x7658, 0x765a, 0x765b, 0x765d, 0x765f,
+ 0x7680, 0x7680, 0x7680, 0x7680, 0x7681, 0x7681, 0x7682, 0x7682,
+ 0x7683, 0x7684, 0x7685, 0x7685, 0x7686, 0x7687, 0x7688, 0x7689,
+ 0x768a, 0x768b, 0x768c, 0x768e, 0x768f, 0x7690, 0x7691, 0x7693,
+ 0x7694, 0x7695, 0x7697, 0x7698, 0x769a, 0x769b, 0x769d, 0x769f,
+ 0x76a0, 0x76a0, 0x76a0, 0x76a0, 0x76a1, 0x76a1, 0x76a2, 0x76a2,
+ 0x76a3, 0x76a4, 0x76a5, 0x76a5, 0x76a6, 0x76a7, 0x76a8, 0x76a9,
+ 0x76aa, 0x76ab, 0x76ac, 0x76ae, 0x76af, 0x76b0, 0x76b1, 0x76b3,
+ 0x76b4, 0x76b5, 0x76b7, 0x76b8, 0x76ba, 0x76bb, 0x76bd, 0x76bf,
+ 0x76e0, 0x76e0, 0x76e0, 0x76e0, 0x76e1, 0x76e1, 0x76e2, 0x76e2,
+ 0x76e3, 0x76e4, 0x76e5, 0x76e5, 0x76e6, 0x76e7, 0x76e8, 0x76e9,
+ 0x76ea, 0x76eb, 0x76ec, 0x76ee, 0x76ef, 0x76f0, 0x76f1, 0x76f3,
+ 0x76f4, 0x76f5, 0x76f7, 0x76f8, 0x76fa, 0x76fb, 0x76fd, 0x76ff,
+ 0x7700, 0x7700, 0x7700, 0x7700, 0x7701, 0x7701, 0x7702, 0x7702,
+ 0x7703, 0x7704, 0x7705, 0x7705, 0x7706, 0x7707, 0x7708, 0x7709,
+ 0x770a, 0x770b, 0x770c, 0x770e, 0x770f, 0x7710, 0x7711, 0x7713,
+ 0x7714, 0x7715, 0x7717, 0x7718, 0x771a, 0x771b, 0x771d, 0x771f,
+ 0x7740, 0x7740, 0x7740, 0x7740, 0x7741, 0x7741, 0x7742, 0x7742,
+ 0x7743, 0x7744, 0x7745, 0x7745, 0x7746, 0x7747, 0x7748, 0x7749,
+ 0x774a, 0x774b, 0x774c, 0x774e, 0x774f, 0x7750, 0x7751, 0x7753,
+ 0x7754, 0x7755, 0x7757, 0x7758, 0x775a, 0x775b, 0x775d, 0x775f,
+ 0x7760, 0x7760, 0x7760, 0x7760, 0x7761, 0x7761, 0x7762, 0x7762,
+ 0x7763, 0x7764, 0x7765, 0x7765, 0x7766, 0x7767, 0x7768, 0x7769,
+ 0x776a, 0x776b, 0x776c, 0x776e, 0x776f, 0x7770, 0x7771, 0x7773,
+ 0x7774, 0x7775, 0x7777, 0x7778, 0x777a, 0x777b, 0x777d, 0x777f,
+ 0x77a0, 0x77a0, 0x77a0, 0x77a0, 0x77a1, 0x77a1, 0x77a2, 0x77a2,
+ 0x77a3, 0x77a4, 0x77a5, 0x77a5, 0x77a6, 0x77a7, 0x77a8, 0x77a9,
+ 0x77aa, 0x77ab, 0x77ac, 0x77ae, 0x77af, 0x77b0, 0x77b1, 0x77b3,
+ 0x77b4, 0x77b5, 0x77b7, 0x77b8, 0x77ba, 0x77bb, 0x77bd, 0x77bf,
+ 0x77e0, 0x77e0, 0x77e0, 0x77e0, 0x77e1, 0x77e1, 0x77e2, 0x77e2,
+ 0x77e3, 0x77e4, 0x77e5, 0x77e5, 0x77e6, 0x77e7, 0x77e8, 0x77e9,
+ 0x77ea, 0x77eb, 0x77ec, 0x77ee, 0x77ef, 0x77f0, 0x77f1, 0x77f3,
+ 0x77f4, 0x77f5, 0x77f7, 0x77f8, 0x77fa, 0x77fb, 0x77fd, 0x77ff,
+ 0x7800, 0x7800, 0x7800, 0x7800, 0x7801, 0x7801, 0x7802, 0x7802,
+ 0x7803, 0x7804, 0x7805, 0x7805, 0x7806, 0x7807, 0x7808, 0x7809,
+ 0x780a, 0x780b, 0x780c, 0x780e, 0x780f, 0x7810, 0x7811, 0x7813,
+ 0x7814, 0x7815, 0x7817, 0x7818, 0x781a, 0x781b, 0x781d, 0x781f,
+ 0x7800, 0x7800, 0x7800, 0x7800, 0x7801, 0x7801, 0x7802, 0x7802,
+ 0x7803, 0x7804, 0x7805, 0x7805, 0x7806, 0x7807, 0x7808, 0x7809,
+ 0x780a, 0x780b, 0x780c, 0x780e, 0x780f, 0x7810, 0x7811, 0x7813,
+ 0x7814, 0x7815, 0x7817, 0x7818, 0x781a, 0x781b, 0x781d, 0x781f,
+ 0x7800, 0x7800, 0x7800, 0x7800, 0x7801, 0x7801, 0x7802, 0x7802,
+ 0x7803, 0x7804, 0x7805, 0x7805, 0x7806, 0x7807, 0x7808, 0x7809,
+ 0x780a, 0x780b, 0x780c, 0x780e, 0x780f, 0x7810, 0x7811, 0x7813,
+ 0x7814, 0x7815, 0x7817, 0x7818, 0x781a, 0x781b, 0x781d, 0x781f,
+ 0x7800, 0x7800, 0x7800, 0x7800, 0x7801, 0x7801, 0x7802, 0x7802,
+ 0x7803, 0x7804, 0x7805, 0x7805, 0x7806, 0x7807, 0x7808, 0x7809,
+ 0x780a, 0x780b, 0x780c, 0x780e, 0x780f, 0x7810, 0x7811, 0x7813,
+ 0x7814, 0x7815, 0x7817, 0x7818, 0x781a, 0x781b, 0x781d, 0x781f,
+ 0x7800, 0x7800, 0x7800, 0x7800, 0x7801, 0x7801, 0x7802, 0x7802,
+ 0x7803, 0x7804, 0x7805, 0x7805, 0x7806, 0x7807, 0x7808, 0x7809,
+ 0x780a, 0x780b, 0x780c, 0x780e, 0x780f, 0x7810, 0x7811, 0x7813,
+ 0x7814, 0x7815, 0x7817, 0x7818, 0x781a, 0x781b, 0x781d, 0x781f,
+ 0x7820, 0x7820, 0x7820, 0x7820, 0x7821, 0x7821, 0x7822, 0x7822,
+ 0x7823, 0x7824, 0x7825, 0x7825, 0x7826, 0x7827, 0x7828, 0x7829,
+ 0x782a, 0x782b, 0x782c, 0x782e, 0x782f, 0x7830, 0x7831, 0x7833,
+ 0x7834, 0x7835, 0x7837, 0x7838, 0x783a, 0x783b, 0x783d, 0x783f,
+ 0x7820, 0x7820, 0x7820, 0x7820, 0x7821, 0x7821, 0x7822, 0x7822,
+ 0x7823, 0x7824, 0x7825, 0x7825, 0x7826, 0x7827, 0x7828, 0x7829,
+ 0x782a, 0x782b, 0x782c, 0x782e, 0x782f, 0x7830, 0x7831, 0x7833,
+ 0x7834, 0x7835, 0x7837, 0x7838, 0x783a, 0x783b, 0x783d, 0x783f,
+ 0x7820, 0x7820, 0x7820, 0x7820, 0x7821, 0x7821, 0x7822, 0x7822,
+ 0x7823, 0x7824, 0x7825, 0x7825, 0x7826, 0x7827, 0x7828, 0x7829,
+ 0x782a, 0x782b, 0x782c, 0x782e, 0x782f, 0x7830, 0x7831, 0x7833,
+ 0x7834, 0x7835, 0x7837, 0x7838, 0x783a, 0x783b, 0x783d, 0x783f,
+ 0x7840, 0x7840, 0x7840, 0x7840, 0x7841, 0x7841, 0x7842, 0x7842,
+ 0x7843, 0x7844, 0x7845, 0x7845, 0x7846, 0x7847, 0x7848, 0x7849,
+ 0x784a, 0x784b, 0x784c, 0x784e, 0x784f, 0x7850, 0x7851, 0x7853,
+ 0x7854, 0x7855, 0x7857, 0x7858, 0x785a, 0x785b, 0x785d, 0x785f,
+ 0x7840, 0x7840, 0x7840, 0x7840, 0x7841, 0x7841, 0x7842, 0x7842,
+ 0x7843, 0x7844, 0x7845, 0x7845, 0x7846, 0x7847, 0x7848, 0x7849,
+ 0x784a, 0x784b, 0x784c, 0x784e, 0x784f, 0x7850, 0x7851, 0x7853,
+ 0x7854, 0x7855, 0x7857, 0x7858, 0x785a, 0x785b, 0x785d, 0x785f,
+ 0x7860, 0x7860, 0x7860, 0x7860, 0x7861, 0x7861, 0x7862, 0x7862,
+ 0x7863, 0x7864, 0x7865, 0x7865, 0x7866, 0x7867, 0x7868, 0x7869,
+ 0x786a, 0x786b, 0x786c, 0x786e, 0x786f, 0x7870, 0x7871, 0x7873,
+ 0x7874, 0x7875, 0x7877, 0x7878, 0x787a, 0x787b, 0x787d, 0x787f,
+ 0x7860, 0x7860, 0x7860, 0x7860, 0x7861, 0x7861, 0x7862, 0x7862,
+ 0x7863, 0x7864, 0x7865, 0x7865, 0x7866, 0x7867, 0x7868, 0x7869,
+ 0x786a, 0x786b, 0x786c, 0x786e, 0x786f, 0x7870, 0x7871, 0x7873,
+ 0x7874, 0x7875, 0x7877, 0x7878, 0x787a, 0x787b, 0x787d, 0x787f,
+ 0x7880, 0x7880, 0x7880, 0x7880, 0x7881, 0x7881, 0x7882, 0x7882,
+ 0x7883, 0x7884, 0x7885, 0x7885, 0x7886, 0x7887, 0x7888, 0x7889,
+ 0x788a, 0x788b, 0x788c, 0x788e, 0x788f, 0x7890, 0x7891, 0x7893,
+ 0x7894, 0x7895, 0x7897, 0x7898, 0x789a, 0x789b, 0x789d, 0x789f,
+ 0x78a0, 0x78a0, 0x78a0, 0x78a0, 0x78a1, 0x78a1, 0x78a2, 0x78a2,
+ 0x78a3, 0x78a4, 0x78a5, 0x78a5, 0x78a6, 0x78a7, 0x78a8, 0x78a9,
+ 0x78aa, 0x78ab, 0x78ac, 0x78ae, 0x78af, 0x78b0, 0x78b1, 0x78b3,
+ 0x78b4, 0x78b5, 0x78b7, 0x78b8, 0x78ba, 0x78bb, 0x78bd, 0x78bf,
+ 0x78a0, 0x78a0, 0x78a0, 0x78a0, 0x78a1, 0x78a1, 0x78a2, 0x78a2,
+ 0x78a3, 0x78a4, 0x78a5, 0x78a5, 0x78a6, 0x78a7, 0x78a8, 0x78a9,
+ 0x78aa, 0x78ab, 0x78ac, 0x78ae, 0x78af, 0x78b0, 0x78b1, 0x78b3,
+ 0x78b4, 0x78b5, 0x78b7, 0x78b8, 0x78ba, 0x78bb, 0x78bd, 0x78bf,
+ 0x78c0, 0x78c0, 0x78c0, 0x78c0, 0x78c1, 0x78c1, 0x78c2, 0x78c2,
+ 0x78c3, 0x78c4, 0x78c5, 0x78c5, 0x78c6, 0x78c7, 0x78c8, 0x78c9,
+ 0x78ca, 0x78cb, 0x78cc, 0x78ce, 0x78cf, 0x78d0, 0x78d1, 0x78d3,
+ 0x78d4, 0x78d5, 0x78d7, 0x78d8, 0x78da, 0x78db, 0x78dd, 0x78df,
+ 0x78e0, 0x78e0, 0x78e0, 0x78e0, 0x78e1, 0x78e1, 0x78e2, 0x78e2,
+ 0x78e3, 0x78e4, 0x78e5, 0x78e5, 0x78e6, 0x78e7, 0x78e8, 0x78e9,
+ 0x78ea, 0x78eb, 0x78ec, 0x78ee, 0x78ef, 0x78f0, 0x78f1, 0x78f3,
+ 0x78f4, 0x78f5, 0x78f7, 0x78f8, 0x78fa, 0x78fb, 0x78fd, 0x78ff,
+ 0x78e0, 0x78e0, 0x78e0, 0x78e0, 0x78e1, 0x78e1, 0x78e2, 0x78e2,
+ 0x78e3, 0x78e4, 0x78e5, 0x78e5, 0x78e6, 0x78e7, 0x78e8, 0x78e9,
+ 0x78ea, 0x78eb, 0x78ec, 0x78ee, 0x78ef, 0x78f0, 0x78f1, 0x78f3,
+ 0x78f4, 0x78f5, 0x78f7, 0x78f8, 0x78fa, 0x78fb, 0x78fd, 0x78ff,
+ 0x7900, 0x7900, 0x7900, 0x7900, 0x7901, 0x7901, 0x7902, 0x7902,
+ 0x7903, 0x7904, 0x7905, 0x7905, 0x7906, 0x7907, 0x7908, 0x7909,
+ 0x790a, 0x790b, 0x790c, 0x790e, 0x790f, 0x7910, 0x7911, 0x7913,
+ 0x7914, 0x7915, 0x7917, 0x7918, 0x791a, 0x791b, 0x791d, 0x791f,
+ 0x7920, 0x7920, 0x7920, 0x7920, 0x7921, 0x7921, 0x7922, 0x7922,
+ 0x7923, 0x7924, 0x7925, 0x7925, 0x7926, 0x7927, 0x7928, 0x7929,
+ 0x792a, 0x792b, 0x792c, 0x792e, 0x792f, 0x7930, 0x7931, 0x7933,
+ 0x7934, 0x7935, 0x7937, 0x7938, 0x793a, 0x793b, 0x793d, 0x793f,
+ 0x7940, 0x7940, 0x7940, 0x7940, 0x7941, 0x7941, 0x7942, 0x7942,
+ 0x7943, 0x7944, 0x7945, 0x7945, 0x7946, 0x7947, 0x7948, 0x7949,
+ 0x794a, 0x794b, 0x794c, 0x794e, 0x794f, 0x7950, 0x7951, 0x7953,
+ 0x7954, 0x7955, 0x7957, 0x7958, 0x795a, 0x795b, 0x795d, 0x795f,
+ 0x7940, 0x7940, 0x7940, 0x7940, 0x7941, 0x7941, 0x7942, 0x7942,
+ 0x7943, 0x7944, 0x7945, 0x7945, 0x7946, 0x7947, 0x7948, 0x7949,
+ 0x794a, 0x794b, 0x794c, 0x794e, 0x794f, 0x7950, 0x7951, 0x7953,
+ 0x7954, 0x7955, 0x7957, 0x7958, 0x795a, 0x795b, 0x795d, 0x795f,
+ 0x7960, 0x7960, 0x7960, 0x7960, 0x7961, 0x7961, 0x7962, 0x7962,
+ 0x7963, 0x7964, 0x7965, 0x7965, 0x7966, 0x7967, 0x7968, 0x7969,
+ 0x796a, 0x796b, 0x796c, 0x796e, 0x796f, 0x7970, 0x7971, 0x7973,
+ 0x7974, 0x7975, 0x7977, 0x7978, 0x797a, 0x797b, 0x797d, 0x797f,
+ 0x7980, 0x7980, 0x7980, 0x7980, 0x7981, 0x7981, 0x7982, 0x7982,
+ 0x7983, 0x7984, 0x7985, 0x7985, 0x7986, 0x7987, 0x7988, 0x7989,
+ 0x798a, 0x798b, 0x798c, 0x798e, 0x798f, 0x7990, 0x7991, 0x7993,
+ 0x7994, 0x7995, 0x7997, 0x7998, 0x799a, 0x799b, 0x799d, 0x799f,
+ 0x79a0, 0x79a0, 0x79a0, 0x79a0, 0x79a1, 0x79a1, 0x79a2, 0x79a2,
+ 0x79a3, 0x79a4, 0x79a5, 0x79a5, 0x79a6, 0x79a7, 0x79a8, 0x79a9,
+ 0x79aa, 0x79ab, 0x79ac, 0x79ae, 0x79af, 0x79b0, 0x79b1, 0x79b3,
+ 0x79b4, 0x79b5, 0x79b7, 0x79b8, 0x79ba, 0x79bb, 0x79bd, 0x79bf,
+ 0x79c0, 0x79c0, 0x79c0, 0x79c0, 0x79c1, 0x79c1, 0x79c2, 0x79c2,
+ 0x79c3, 0x79c4, 0x79c5, 0x79c5, 0x79c6, 0x79c7, 0x79c8, 0x79c9,
+ 0x79ca, 0x79cb, 0x79cc, 0x79ce, 0x79cf, 0x79d0, 0x79d1, 0x79d3,
+ 0x79d4, 0x79d5, 0x79d7, 0x79d8, 0x79da, 0x79db, 0x79dd, 0x79df,
+ 0x79e0, 0x79e0, 0x79e0, 0x79e0, 0x79e1, 0x79e1, 0x79e2, 0x79e2,
+ 0x79e3, 0x79e4, 0x79e5, 0x79e5, 0x79e6, 0x79e7, 0x79e8, 0x79e9,
+ 0x79ea, 0x79eb, 0x79ec, 0x79ee, 0x79ef, 0x79f0, 0x79f1, 0x79f3,
+ 0x79f4, 0x79f5, 0x79f7, 0x79f8, 0x79fa, 0x79fb, 0x79fd, 0x79ff,
+ 0x7a00, 0x7a00, 0x7a00, 0x7a00, 0x7a01, 0x7a01, 0x7a02, 0x7a02,
+ 0x7a03, 0x7a04, 0x7a05, 0x7a05, 0x7a06, 0x7a07, 0x7a08, 0x7a09,
+ 0x7a0a, 0x7a0b, 0x7a0c, 0x7a0e, 0x7a0f, 0x7a10, 0x7a11, 0x7a13,
+ 0x7a14, 0x7a15, 0x7a17, 0x7a18, 0x7a1a, 0x7a1b, 0x7a1d, 0x7a1f,
+ 0x7a20, 0x7a20, 0x7a20, 0x7a20, 0x7a21, 0x7a21, 0x7a22, 0x7a22,
+ 0x7a23, 0x7a24, 0x7a25, 0x7a25, 0x7a26, 0x7a27, 0x7a28, 0x7a29,
+ 0x7a2a, 0x7a2b, 0x7a2c, 0x7a2e, 0x7a2f, 0x7a30, 0x7a31, 0x7a33,
+ 0x7a34, 0x7a35, 0x7a37, 0x7a38, 0x7a3a, 0x7a3b, 0x7a3d, 0x7a3f,
+ 0x7a40, 0x7a40, 0x7a40, 0x7a40, 0x7a41, 0x7a41, 0x7a42, 0x7a42,
+ 0x7a43, 0x7a44, 0x7a45, 0x7a45, 0x7a46, 0x7a47, 0x7a48, 0x7a49,
+ 0x7a4a, 0x7a4b, 0x7a4c, 0x7a4e, 0x7a4f, 0x7a50, 0x7a51, 0x7a53,
+ 0x7a54, 0x7a55, 0x7a57, 0x7a58, 0x7a5a, 0x7a5b, 0x7a5d, 0x7a5f,
+ 0x7a60, 0x7a60, 0x7a60, 0x7a60, 0x7a61, 0x7a61, 0x7a62, 0x7a62,
+ 0x7a63, 0x7a64, 0x7a65, 0x7a65, 0x7a66, 0x7a67, 0x7a68, 0x7a69,
+ 0x7a6a, 0x7a6b, 0x7a6c, 0x7a6e, 0x7a6f, 0x7a70, 0x7a71, 0x7a73,
+ 0x7a74, 0x7a75, 0x7a77, 0x7a78, 0x7a7a, 0x7a7b, 0x7a7d, 0x7a7f,
+ 0x7a80, 0x7a80, 0x7a80, 0x7a80, 0x7a81, 0x7a81, 0x7a82, 0x7a82,
+ 0x7a83, 0x7a84, 0x7a85, 0x7a85, 0x7a86, 0x7a87, 0x7a88, 0x7a89,
+ 0x7a8a, 0x7a8b, 0x7a8c, 0x7a8e, 0x7a8f, 0x7a90, 0x7a91, 0x7a93,
+ 0x7a94, 0x7a95, 0x7a97, 0x7a98, 0x7a9a, 0x7a9b, 0x7a9d, 0x7a9f,
+ 0x7aa0, 0x7aa0, 0x7aa0, 0x7aa0, 0x7aa1, 0x7aa1, 0x7aa2, 0x7aa2,
+ 0x7aa3, 0x7aa4, 0x7aa5, 0x7aa5, 0x7aa6, 0x7aa7, 0x7aa8, 0x7aa9,
+ 0x7aaa, 0x7aab, 0x7aac, 0x7aae, 0x7aaf, 0x7ab0, 0x7ab1, 0x7ab3,
+ 0x7ab4, 0x7ab5, 0x7ab7, 0x7ab8, 0x7aba, 0x7abb, 0x7abd, 0x7abf,
+ 0x7ac0, 0x7ac0, 0x7ac0, 0x7ac0, 0x7ac1, 0x7ac1, 0x7ac2, 0x7ac2,
+ 0x7ac3, 0x7ac4, 0x7ac5, 0x7ac5, 0x7ac6, 0x7ac7, 0x7ac8, 0x7ac9,
+ 0x7aca, 0x7acb, 0x7acc, 0x7ace, 0x7acf, 0x7ad0, 0x7ad1, 0x7ad3,
+ 0x7ad4, 0x7ad5, 0x7ad7, 0x7ad8, 0x7ada, 0x7adb, 0x7add, 0x7adf,
+ 0x7ae0, 0x7ae0, 0x7ae0, 0x7ae0, 0x7ae1, 0x7ae1, 0x7ae2, 0x7ae2,
+ 0x7ae3, 0x7ae4, 0x7ae5, 0x7ae5, 0x7ae6, 0x7ae7, 0x7ae8, 0x7ae9,
+ 0x7aea, 0x7aeb, 0x7aec, 0x7aee, 0x7aef, 0x7af0, 0x7af1, 0x7af3,
+ 0x7af4, 0x7af5, 0x7af7, 0x7af8, 0x7afa, 0x7afb, 0x7afd, 0x7aff,
+ 0x7b00, 0x7b00, 0x7b00, 0x7b00, 0x7b01, 0x7b01, 0x7b02, 0x7b02,
+ 0x7b03, 0x7b04, 0x7b05, 0x7b05, 0x7b06, 0x7b07, 0x7b08, 0x7b09,
+ 0x7b0a, 0x7b0b, 0x7b0c, 0x7b0e, 0x7b0f, 0x7b10, 0x7b11, 0x7b13,
+ 0x7b14, 0x7b15, 0x7b17, 0x7b18, 0x7b1a, 0x7b1b, 0x7b1d, 0x7b1f,
+ 0x7b20, 0x7b20, 0x7b20, 0x7b20, 0x7b21, 0x7b21, 0x7b22, 0x7b22,
+ 0x7b23, 0x7b24, 0x7b25, 0x7b25, 0x7b26, 0x7b27, 0x7b28, 0x7b29,
+ 0x7b2a, 0x7b2b, 0x7b2c, 0x7b2e, 0x7b2f, 0x7b30, 0x7b31, 0x7b33,
+ 0x7b34, 0x7b35, 0x7b37, 0x7b38, 0x7b3a, 0x7b3b, 0x7b3d, 0x7b3f,
+ 0x7b40, 0x7b40, 0x7b40, 0x7b40, 0x7b41, 0x7b41, 0x7b42, 0x7b42,
+ 0x7b43, 0x7b44, 0x7b45, 0x7b45, 0x7b46, 0x7b47, 0x7b48, 0x7b49,
+ 0x7b4a, 0x7b4b, 0x7b4c, 0x7b4e, 0x7b4f, 0x7b50, 0x7b51, 0x7b53,
+ 0x7b54, 0x7b55, 0x7b57, 0x7b58, 0x7b5a, 0x7b5b, 0x7b5d, 0x7b5f,
+ 0x7b80, 0x7b80, 0x7b80, 0x7b80, 0x7b81, 0x7b81, 0x7b82, 0x7b82,
+ 0x7b83, 0x7b84, 0x7b85, 0x7b85, 0x7b86, 0x7b87, 0x7b88, 0x7b89,
+ 0x7b8a, 0x7b8b, 0x7b8c, 0x7b8e, 0x7b8f, 0x7b90, 0x7b91, 0x7b93,
+ 0x7b94, 0x7b95, 0x7b97, 0x7b98, 0x7b9a, 0x7b9b, 0x7b9d, 0x7b9f,
+ 0x7ba0, 0x7ba0, 0x7ba0, 0x7ba0, 0x7ba1, 0x7ba1, 0x7ba2, 0x7ba2,
+ 0x7ba3, 0x7ba4, 0x7ba5, 0x7ba5, 0x7ba6, 0x7ba7, 0x7ba8, 0x7ba9,
+ 0x7baa, 0x7bab, 0x7bac, 0x7bae, 0x7baf, 0x7bb0, 0x7bb1, 0x7bb3,
+ 0x7bb4, 0x7bb5, 0x7bb7, 0x7bb8, 0x7bba, 0x7bbb, 0x7bbd, 0x7bbf,
+ 0x7bc0, 0x7bc0, 0x7bc0, 0x7bc0, 0x7bc1, 0x7bc1, 0x7bc2, 0x7bc2,
+ 0x7bc3, 0x7bc4, 0x7bc5, 0x7bc5, 0x7bc6, 0x7bc7, 0x7bc8, 0x7bc9,
+ 0x7bca, 0x7bcb, 0x7bcc, 0x7bce, 0x7bcf, 0x7bd0, 0x7bd1, 0x7bd3,
+ 0x7bd4, 0x7bd5, 0x7bd7, 0x7bd8, 0x7bda, 0x7bdb, 0x7bdd, 0x7bdf,
+ 0x7be0, 0x7be0, 0x7be0, 0x7be0, 0x7be1, 0x7be1, 0x7be2, 0x7be2,
+ 0x7be3, 0x7be4, 0x7be5, 0x7be5, 0x7be6, 0x7be7, 0x7be8, 0x7be9,
+ 0x7bea, 0x7beb, 0x7bec, 0x7bee, 0x7bef, 0x7bf0, 0x7bf1, 0x7bf3,
+ 0x7bf4, 0x7bf5, 0x7bf7, 0x7bf8, 0x7bfa, 0x7bfb, 0x7bfd, 0x7bff,
+ 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c01, 0x7c01, 0x7c02, 0x7c02,
+ 0x7c03, 0x7c04, 0x7c05, 0x7c05, 0x7c06, 0x7c07, 0x7c08, 0x7c09,
+ 0x7c0a, 0x7c0b, 0x7c0c, 0x7c0e, 0x7c0f, 0x7c10, 0x7c11, 0x7c13,
+ 0x7c14, 0x7c15, 0x7c17, 0x7c18, 0x7c1a, 0x7c1b, 0x7c1d, 0x7c1f,
+ 0x7c40, 0x7c40, 0x7c40, 0x7c40, 0x7c41, 0x7c41, 0x7c42, 0x7c42,
+ 0x7c43, 0x7c44, 0x7c45, 0x7c45, 0x7c46, 0x7c47, 0x7c48, 0x7c49,
+ 0x7c4a, 0x7c4b, 0x7c4c, 0x7c4e, 0x7c4f, 0x7c50, 0x7c51, 0x7c53,
+ 0x7c54, 0x7c55, 0x7c57, 0x7c58, 0x7c5a, 0x7c5b, 0x7c5d, 0x7c5f,
+ 0x7c60, 0x7c60, 0x7c60, 0x7c60, 0x7c61, 0x7c61, 0x7c62, 0x7c62,
+ 0x7c63, 0x7c64, 0x7c65, 0x7c65, 0x7c66, 0x7c67, 0x7c68, 0x7c69,
+ 0x7c6a, 0x7c6b, 0x7c6c, 0x7c6e, 0x7c6f, 0x7c70, 0x7c71, 0x7c73,
+ 0x7c74, 0x7c75, 0x7c77, 0x7c78, 0x7c7a, 0x7c7b, 0x7c7d, 0x7c7f,
+ 0x7c80, 0x7c80, 0x7c80, 0x7c80, 0x7c81, 0x7c81, 0x7c82, 0x7c82,
+ 0x7c83, 0x7c84, 0x7c85, 0x7c85, 0x7c86, 0x7c87, 0x7c88, 0x7c89,
+ 0x7c8a, 0x7c8b, 0x7c8c, 0x7c8e, 0x7c8f, 0x7c90, 0x7c91, 0x7c93,
+ 0x7c94, 0x7c95, 0x7c97, 0x7c98, 0x7c9a, 0x7c9b, 0x7c9d, 0x7c9f,
+ 0x7cc0, 0x7cc0, 0x7cc0, 0x7cc0, 0x7cc1, 0x7cc1, 0x7cc2, 0x7cc2,
+ 0x7cc3, 0x7cc4, 0x7cc5, 0x7cc5, 0x7cc6, 0x7cc7, 0x7cc8, 0x7cc9,
+ 0x7cca, 0x7ccb, 0x7ccc, 0x7cce, 0x7ccf, 0x7cd0, 0x7cd1, 0x7cd3,
+ 0x7cd4, 0x7cd5, 0x7cd7, 0x7cd8, 0x7cda, 0x7cdb, 0x7cdd, 0x7cdf,
+ 0x7ce0, 0x7ce0, 0x7ce0, 0x7ce0, 0x7ce1, 0x7ce1, 0x7ce2, 0x7ce2,
+ 0x7ce3, 0x7ce4, 0x7ce5, 0x7ce5, 0x7ce6, 0x7ce7, 0x7ce8, 0x7ce9,
+ 0x7cea, 0x7ceb, 0x7cec, 0x7cee, 0x7cef, 0x7cf0, 0x7cf1, 0x7cf3,
+ 0x7cf4, 0x7cf5, 0x7cf7, 0x7cf8, 0x7cfa, 0x7cfb, 0x7cfd, 0x7cff,
+ 0x7d00, 0x7d00, 0x7d00, 0x7d00, 0x7d01, 0x7d01, 0x7d02, 0x7d02,
+ 0x7d03, 0x7d04, 0x7d05, 0x7d05, 0x7d06, 0x7d07, 0x7d08, 0x7d09,
+ 0x7d0a, 0x7d0b, 0x7d0c, 0x7d0e, 0x7d0f, 0x7d10, 0x7d11, 0x7d13,
+ 0x7d14, 0x7d15, 0x7d17, 0x7d18, 0x7d1a, 0x7d1b, 0x7d1d, 0x7d1f,
+ 0x7d40, 0x7d40, 0x7d40, 0x7d40, 0x7d41, 0x7d41, 0x7d42, 0x7d42,
+ 0x7d43, 0x7d44, 0x7d45, 0x7d45, 0x7d46, 0x7d47, 0x7d48, 0x7d49,
+ 0x7d4a, 0x7d4b, 0x7d4c, 0x7d4e, 0x7d4f, 0x7d50, 0x7d51, 0x7d53,
+ 0x7d54, 0x7d55, 0x7d57, 0x7d58, 0x7d5a, 0x7d5b, 0x7d5d, 0x7d5f,
+ 0x7d60, 0x7d60, 0x7d60, 0x7d60, 0x7d61, 0x7d61, 0x7d62, 0x7d62,
+ 0x7d63, 0x7d64, 0x7d65, 0x7d65, 0x7d66, 0x7d67, 0x7d68, 0x7d69,
+ 0x7d6a, 0x7d6b, 0x7d6c, 0x7d6e, 0x7d6f, 0x7d70, 0x7d71, 0x7d73,
+ 0x7d74, 0x7d75, 0x7d77, 0x7d78, 0x7d7a, 0x7d7b, 0x7d7d, 0x7d7f,
+ 0x7d80, 0x7d80, 0x7d80, 0x7d80, 0x7d81, 0x7d81, 0x7d82, 0x7d82,
+ 0x7d83, 0x7d84, 0x7d85, 0x7d85, 0x7d86, 0x7d87, 0x7d88, 0x7d89,
+ 0x7d8a, 0x7d8b, 0x7d8c, 0x7d8e, 0x7d8f, 0x7d90, 0x7d91, 0x7d93,
+ 0x7d94, 0x7d95, 0x7d97, 0x7d98, 0x7d9a, 0x7d9b, 0x7d9d, 0x7d9f,
+ 0x7dc0, 0x7dc0, 0x7dc0, 0x7dc0, 0x7dc1, 0x7dc1, 0x7dc2, 0x7dc2,
+ 0x7dc3, 0x7dc4, 0x7dc5, 0x7dc5, 0x7dc6, 0x7dc7, 0x7dc8, 0x7dc9,
+ 0x7dca, 0x7dcb, 0x7dcc, 0x7dce, 0x7dcf, 0x7dd0, 0x7dd1, 0x7dd3,
+ 0x7dd4, 0x7dd5, 0x7dd7, 0x7dd8, 0x7dda, 0x7ddb, 0x7ddd, 0x7ddf,
+ 0x7de0, 0x7de0, 0x7de0, 0x7de0, 0x7de1, 0x7de1, 0x7de2, 0x7de2,
+ 0x7de3, 0x7de4, 0x7de5, 0x7de5, 0x7de6, 0x7de7, 0x7de8, 0x7de9,
+ 0x7dea, 0x7deb, 0x7dec, 0x7dee, 0x7def, 0x7df0, 0x7df1, 0x7df3,
+ 0x7df4, 0x7df5, 0x7df7, 0x7df8, 0x7dfa, 0x7dfb, 0x7dfd, 0x7dff,
+ 0x7e20, 0x7e20, 0x7e20, 0x7e20, 0x7e21, 0x7e21, 0x7e22, 0x7e22,
+ 0x7e23, 0x7e24, 0x7e25, 0x7e25, 0x7e26, 0x7e27, 0x7e28, 0x7e29,
+ 0x7e2a, 0x7e2b, 0x7e2c, 0x7e2e, 0x7e2f, 0x7e30, 0x7e31, 0x7e33,
+ 0x7e34, 0x7e35, 0x7e37, 0x7e38, 0x7e3a, 0x7e3b, 0x7e3d, 0x7e3f,
+ 0x7e40, 0x7e40, 0x7e40, 0x7e40, 0x7e41, 0x7e41, 0x7e42, 0x7e42,
+ 0x7e43, 0x7e44, 0x7e45, 0x7e45, 0x7e46, 0x7e47, 0x7e48, 0x7e49,
+ 0x7e4a, 0x7e4b, 0x7e4c, 0x7e4e, 0x7e4f, 0x7e50, 0x7e51, 0x7e53,
+ 0x7e54, 0x7e55, 0x7e57, 0x7e58, 0x7e5a, 0x7e5b, 0x7e5d, 0x7e5f,
+ 0x7e80, 0x7e80, 0x7e80, 0x7e80, 0x7e81, 0x7e81, 0x7e82, 0x7e82,
+ 0x7e83, 0x7e84, 0x7e85, 0x7e85, 0x7e86, 0x7e87, 0x7e88, 0x7e89,
+ 0x7e8a, 0x7e8b, 0x7e8c, 0x7e8e, 0x7e8f, 0x7e90, 0x7e91, 0x7e93,
+ 0x7e94, 0x7e95, 0x7e97, 0x7e98, 0x7e9a, 0x7e9b, 0x7e9d, 0x7e9f,
+ 0x7ea0, 0x7ea0, 0x7ea0, 0x7ea0, 0x7ea1, 0x7ea1, 0x7ea2, 0x7ea2,
+ 0x7ea3, 0x7ea4, 0x7ea5, 0x7ea5, 0x7ea6, 0x7ea7, 0x7ea8, 0x7ea9,
+ 0x7eaa, 0x7eab, 0x7eac, 0x7eae, 0x7eaf, 0x7eb0, 0x7eb1, 0x7eb3,
+ 0x7eb4, 0x7eb5, 0x7eb7, 0x7eb8, 0x7eba, 0x7ebb, 0x7ebd, 0x7ebf,
+ 0x7ee0, 0x7ee0, 0x7ee0, 0x7ee0, 0x7ee1, 0x7ee1, 0x7ee2, 0x7ee2,
+ 0x7ee3, 0x7ee4, 0x7ee5, 0x7ee5, 0x7ee6, 0x7ee7, 0x7ee8, 0x7ee9,
+ 0x7eea, 0x7eeb, 0x7eec, 0x7eee, 0x7eef, 0x7ef0, 0x7ef1, 0x7ef3,
+ 0x7ef4, 0x7ef5, 0x7ef7, 0x7ef8, 0x7efa, 0x7efb, 0x7efd, 0x7eff,
+ 0x7f00, 0x7f00, 0x7f00, 0x7f00, 0x7f01, 0x7f01, 0x7f02, 0x7f02,
+ 0x7f03, 0x7f04, 0x7f05, 0x7f05, 0x7f06, 0x7f07, 0x7f08, 0x7f09,
+ 0x7f0a, 0x7f0b, 0x7f0c, 0x7f0e, 0x7f0f, 0x7f10, 0x7f11, 0x7f13,
+ 0x7f14, 0x7f15, 0x7f17, 0x7f18, 0x7f1a, 0x7f1b, 0x7f1d, 0x7f1f,
+ 0x7f40, 0x7f40, 0x7f40, 0x7f40, 0x7f41, 0x7f41, 0x7f42, 0x7f42,
+ 0x7f43, 0x7f44, 0x7f45, 0x7f45, 0x7f46, 0x7f47, 0x7f48, 0x7f49,
+ 0x7f4a, 0x7f4b, 0x7f4c, 0x7f4e, 0x7f4f, 0x7f50, 0x7f51, 0x7f53,
+ 0x7f54, 0x7f55, 0x7f57, 0x7f58, 0x7f5a, 0x7f5b, 0x7f5d, 0x7f5f,
+ 0x7f60, 0x7f60, 0x7f60, 0x7f60, 0x7f61, 0x7f61, 0x7f62, 0x7f62,
+ 0x7f63, 0x7f64, 0x7f65, 0x7f65, 0x7f66, 0x7f67, 0x7f68, 0x7f69,
+ 0x7f6a, 0x7f6b, 0x7f6c, 0x7f6e, 0x7f6f, 0x7f70, 0x7f71, 0x7f73,
+ 0x7f74, 0x7f75, 0x7f77, 0x7f78, 0x7f7a, 0x7f7b, 0x7f7d, 0x7f7f,
+ 0x7fa0, 0x7fa0, 0x7fa0, 0x7fa0, 0x7fa1, 0x7fa1, 0x7fa2, 0x7fa2,
+ 0x7fa3, 0x7fa4, 0x7fa5, 0x7fa5, 0x7fa6, 0x7fa7, 0x7fa8, 0x7fa9,
+ 0x7faa, 0x7fab, 0x7fac, 0x7fae, 0x7faf, 0x7fb0, 0x7fb1, 0x7fb3,
+ 0x7fb4, 0x7fb5, 0x7fb7, 0x7fb8, 0x7fba, 0x7fbb, 0x7fbd, 0x7fbf,
+ 0x7fe0, 0x7fe0, 0x7fe0, 0x7fe0, 0x7fe1, 0x7fe1, 0x7fe2, 0x7fe2,
+ 0x7fe3, 0x7fe4, 0x7fe5, 0x7fe5, 0x7fe6, 0x7fe7, 0x7fe8, 0x7fe9,
+ 0x7fea, 0x7feb, 0x7fec, 0x7fee, 0x7fef, 0x7ff0, 0x7ff1, 0x7ff3,
+ 0x7ff4, 0x7ff5, 0x7ff7, 0x7ff8, 0x7ffa, 0x7ffb, 0x7ffd, 0x7fff,
+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8001, 0x8001, 0x8002, 0x8002,
+ 0x8003, 0x8004, 0x8005, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009,
+ 0x800a, 0x800b, 0x800c, 0x800e, 0x800f, 0x8010, 0x8011, 0x8013,
+ 0x8014, 0x8015, 0x8017, 0x8018, 0x801a, 0x801b, 0x801d, 0x801f,
+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8001, 0x8001, 0x8002, 0x8002,
+ 0x8003, 0x8004, 0x8005, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009,
+ 0x800a, 0x800b, 0x800c, 0x800e, 0x800f, 0x8010, 0x8011, 0x8013,
+ 0x8014, 0x8015, 0x8017, 0x8018, 0x801a, 0x801b, 0x801d, 0x801f,
+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8001, 0x8001, 0x8002, 0x8002,
+ 0x8003, 0x8004, 0x8005, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009,
+ 0x800a, 0x800b, 0x800c, 0x800e, 0x800f, 0x8010, 0x8011, 0x8013,
+ 0x8014, 0x8015, 0x8017, 0x8018, 0x801a, 0x801b, 0x801d, 0x801f,
+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8001, 0x8001, 0x8002, 0x8002,
+ 0x8003, 0x8004, 0x8005, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009,
+ 0x800a, 0x800b, 0x800c, 0x800e, 0x800f, 0x8010, 0x8011, 0x8013,
+ 0x8014, 0x8015, 0x8017, 0x8018, 0x801a, 0x801b, 0x801d, 0x801f,
+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8001, 0x8001, 0x8002, 0x8002,
+ 0x8003, 0x8004, 0x8005, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009,
+ 0x800a, 0x800b, 0x800c, 0x800e, 0x800f, 0x8010, 0x8011, 0x8013,
+ 0x8014, 0x8015, 0x8017, 0x8018, 0x801a, 0x801b, 0x801d, 0x801f,
+ 0x8020, 0x8020, 0x8020, 0x8020, 0x8021, 0x8021, 0x8022, 0x8022,
+ 0x8023, 0x8024, 0x8025, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029,
+ 0x802a, 0x802b, 0x802c, 0x802e, 0x802f, 0x8030, 0x8031, 0x8033,
+ 0x8034, 0x8035, 0x8037, 0x8038, 0x803a, 0x803b, 0x803d, 0x803f,
+ 0x8020, 0x8020, 0x8020, 0x8020, 0x8021, 0x8021, 0x8022, 0x8022,
+ 0x8023, 0x8024, 0x8025, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029,
+ 0x802a, 0x802b, 0x802c, 0x802e, 0x802f, 0x8030, 0x8031, 0x8033,
+ 0x8034, 0x8035, 0x8037, 0x8038, 0x803a, 0x803b, 0x803d, 0x803f,
+ 0x8020, 0x8020, 0x8020, 0x8020, 0x8021, 0x8021, 0x8022, 0x8022,
+ 0x8023, 0x8024, 0x8025, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029,
+ 0x802a, 0x802b, 0x802c, 0x802e, 0x802f, 0x8030, 0x8031, 0x8033,
+ 0x8034, 0x8035, 0x8037, 0x8038, 0x803a, 0x803b, 0x803d, 0x803f,
+ 0x8040, 0x8040, 0x8040, 0x8040, 0x8041, 0x8041, 0x8042, 0x8042,
+ 0x8043, 0x8044, 0x8045, 0x8045, 0x8046, 0x8047, 0x8048, 0x8049,
+ 0x804a, 0x804b, 0x804c, 0x804e, 0x804f, 0x8050, 0x8051, 0x8053,
+ 0x8054, 0x8055, 0x8057, 0x8058, 0x805a, 0x805b, 0x805d, 0x805f,
+ 0x8040, 0x8040, 0x8040, 0x8040, 0x8041, 0x8041, 0x8042, 0x8042,
+ 0x8043, 0x8044, 0x8045, 0x8045, 0x8046, 0x8047, 0x8048, 0x8049,
+ 0x804a, 0x804b, 0x804c, 0x804e, 0x804f, 0x8050, 0x8051, 0x8053,
+ 0x8054, 0x8055, 0x8057, 0x8058, 0x805a, 0x805b, 0x805d, 0x805f,
+ 0x8060, 0x8060, 0x8060, 0x8060, 0x8061, 0x8061, 0x8062, 0x8062,
+ 0x8063, 0x8064, 0x8065, 0x8065, 0x8066, 0x8067, 0x8068, 0x8069,
+ 0x806a, 0x806b, 0x806c, 0x806e, 0x806f, 0x8070, 0x8071, 0x8073,
+ 0x8074, 0x8075, 0x8077, 0x8078, 0x807a, 0x807b, 0x807d, 0x807f,
+ 0x8060, 0x8060, 0x8060, 0x8060, 0x8061, 0x8061, 0x8062, 0x8062,
+ 0x8063, 0x8064, 0x8065, 0x8065, 0x8066, 0x8067, 0x8068, 0x8069,
+ 0x806a, 0x806b, 0x806c, 0x806e, 0x806f, 0x8070, 0x8071, 0x8073,
+ 0x8074, 0x8075, 0x8077, 0x8078, 0x807a, 0x807b, 0x807d, 0x807f,
+ 0x8080, 0x8080, 0x8080, 0x8080, 0x8081, 0x8081, 0x8082, 0x8082,
+ 0x8083, 0x8084, 0x8085, 0x8085, 0x8086, 0x8087, 0x8088, 0x8089,
+ 0x808a, 0x808b, 0x808c, 0x808e, 0x808f, 0x8090, 0x8091, 0x8093,
+ 0x8094, 0x8095, 0x8097, 0x8098, 0x809a, 0x809b, 0x809d, 0x809f,
+ 0x80a0, 0x80a0, 0x80a0, 0x80a0, 0x80a1, 0x80a1, 0x80a2, 0x80a2,
+ 0x80a3, 0x80a4, 0x80a5, 0x80a5, 0x80a6, 0x80a7, 0x80a8, 0x80a9,
+ 0x80aa, 0x80ab, 0x80ac, 0x80ae, 0x80af, 0x80b0, 0x80b1, 0x80b3,
+ 0x80b4, 0x80b5, 0x80b7, 0x80b8, 0x80ba, 0x80bb, 0x80bd, 0x80bf,
+ 0x80a0, 0x80a0, 0x80a0, 0x80a0, 0x80a1, 0x80a1, 0x80a2, 0x80a2,
+ 0x80a3, 0x80a4, 0x80a5, 0x80a5, 0x80a6, 0x80a7, 0x80a8, 0x80a9,
+ 0x80aa, 0x80ab, 0x80ac, 0x80ae, 0x80af, 0x80b0, 0x80b1, 0x80b3,
+ 0x80b4, 0x80b5, 0x80b7, 0x80b8, 0x80ba, 0x80bb, 0x80bd, 0x80bf,
+ 0x80c0, 0x80c0, 0x80c0, 0x80c0, 0x80c1, 0x80c1, 0x80c2, 0x80c2,
+ 0x80c3, 0x80c4, 0x80c5, 0x80c5, 0x80c6, 0x80c7, 0x80c8, 0x80c9,
+ 0x80ca, 0x80cb, 0x80cc, 0x80ce, 0x80cf, 0x80d0, 0x80d1, 0x80d3,
+ 0x80d4, 0x80d5, 0x80d7, 0x80d8, 0x80da, 0x80db, 0x80dd, 0x80df,
+ 0x80e0, 0x80e0, 0x80e0, 0x80e0, 0x80e1, 0x80e1, 0x80e2, 0x80e2,
+ 0x80e3, 0x80e4, 0x80e5, 0x80e5, 0x80e6, 0x80e7, 0x80e8, 0x80e9,
+ 0x80ea, 0x80eb, 0x80ec, 0x80ee, 0x80ef, 0x80f0, 0x80f1, 0x80f3,
+ 0x80f4, 0x80f5, 0x80f7, 0x80f8, 0x80fa, 0x80fb, 0x80fd, 0x80ff,
+ 0x80e0, 0x80e0, 0x80e0, 0x80e0, 0x80e1, 0x80e1, 0x80e2, 0x80e2,
+ 0x80e3, 0x80e4, 0x80e5, 0x80e5, 0x80e6, 0x80e7, 0x80e8, 0x80e9,
+ 0x80ea, 0x80eb, 0x80ec, 0x80ee, 0x80ef, 0x80f0, 0x80f1, 0x80f3,
+ 0x80f4, 0x80f5, 0x80f7, 0x80f8, 0x80fa, 0x80fb, 0x80fd, 0x80ff,
+ 0x8100, 0x8100, 0x8100, 0x8100, 0x8101, 0x8101, 0x8102, 0x8102,
+ 0x8103, 0x8104, 0x8105, 0x8105, 0x8106, 0x8107, 0x8108, 0x8109,
+ 0x810a, 0x810b, 0x810c, 0x810e, 0x810f, 0x8110, 0x8111, 0x8113,
+ 0x8114, 0x8115, 0x8117, 0x8118, 0x811a, 0x811b, 0x811d, 0x811f,
+ 0x8120, 0x8120, 0x8120, 0x8120, 0x8121, 0x8121, 0x8122, 0x8122,
+ 0x8123, 0x8124, 0x8125, 0x8125, 0x8126, 0x8127, 0x8128, 0x8129,
+ 0x812a, 0x812b, 0x812c, 0x812e, 0x812f, 0x8130, 0x8131, 0x8133,
+ 0x8134, 0x8135, 0x8137, 0x8138, 0x813a, 0x813b, 0x813d, 0x813f,
+ 0x8140, 0x8140, 0x8140, 0x8140, 0x8141, 0x8141, 0x8142, 0x8142,
+ 0x8143, 0x8144, 0x8145, 0x8145, 0x8146, 0x8147, 0x8148, 0x8149,
+ 0x814a, 0x814b, 0x814c, 0x814e, 0x814f, 0x8150, 0x8151, 0x8153,
+ 0x8154, 0x8155, 0x8157, 0x8158, 0x815a, 0x815b, 0x815d, 0x815f,
+ 0x8140, 0x8140, 0x8140, 0x8140, 0x8141, 0x8141, 0x8142, 0x8142,
+ 0x8143, 0x8144, 0x8145, 0x8145, 0x8146, 0x8147, 0x8148, 0x8149,
+ 0x814a, 0x814b, 0x814c, 0x814e, 0x814f, 0x8150, 0x8151, 0x8153,
+ 0x8154, 0x8155, 0x8157, 0x8158, 0x815a, 0x815b, 0x815d, 0x815f,
+ 0x8160, 0x8160, 0x8160, 0x8160, 0x8161, 0x8161, 0x8162, 0x8162,
+ 0x8163, 0x8164, 0x8165, 0x8165, 0x8166, 0x8167, 0x8168, 0x8169,
+ 0x816a, 0x816b, 0x816c, 0x816e, 0x816f, 0x8170, 0x8171, 0x8173,
+ 0x8174, 0x8175, 0x8177, 0x8178, 0x817a, 0x817b, 0x817d, 0x817f,
+ 0x8180, 0x8180, 0x8180, 0x8180, 0x8181, 0x8181, 0x8182, 0x8182,
+ 0x8183, 0x8184, 0x8185, 0x8185, 0x8186, 0x8187, 0x8188, 0x8189,
+ 0x818a, 0x818b, 0x818c, 0x818e, 0x818f, 0x8190, 0x8191, 0x8193,
+ 0x8194, 0x8195, 0x8197, 0x8198, 0x819a, 0x819b, 0x819d, 0x819f,
+ 0x81a0, 0x81a0, 0x81a0, 0x81a0, 0x81a1, 0x81a1, 0x81a2, 0x81a2,
+ 0x81a3, 0x81a4, 0x81a5, 0x81a5, 0x81a6, 0x81a7, 0x81a8, 0x81a9,
+ 0x81aa, 0x81ab, 0x81ac, 0x81ae, 0x81af, 0x81b0, 0x81b1, 0x81b3,
+ 0x81b4, 0x81b5, 0x81b7, 0x81b8, 0x81ba, 0x81bb, 0x81bd, 0x81bf,
+ 0x81c0, 0x81c0, 0x81c0, 0x81c0, 0x81c1, 0x81c1, 0x81c2, 0x81c2,
+ 0x81c3, 0x81c4, 0x81c5, 0x81c5, 0x81c6, 0x81c7, 0x81c8, 0x81c9,
+ 0x81ca, 0x81cb, 0x81cc, 0x81ce, 0x81cf, 0x81d0, 0x81d1, 0x81d3,
+ 0x81d4, 0x81d5, 0x81d7, 0x81d8, 0x81da, 0x81db, 0x81dd, 0x81df,
+ 0x81e0, 0x81e0, 0x81e0, 0x81e0, 0x81e1, 0x81e1, 0x81e2, 0x81e2,
+ 0x81e3, 0x81e4, 0x81e5, 0x81e5, 0x81e6, 0x81e7, 0x81e8, 0x81e9,
+ 0x81ea, 0x81eb, 0x81ec, 0x81ee, 0x81ef, 0x81f0, 0x81f1, 0x81f3,
+ 0x81f4, 0x81f5, 0x81f7, 0x81f8, 0x81fa, 0x81fb, 0x81fd, 0x81ff,
+ 0x8200, 0x8200, 0x8200, 0x8200, 0x8201, 0x8201, 0x8202, 0x8202,
+ 0x8203, 0x8204, 0x8205, 0x8205, 0x8206, 0x8207, 0x8208, 0x8209,
+ 0x820a, 0x820b, 0x820c, 0x820e, 0x820f, 0x8210, 0x8211, 0x8213,
+ 0x8214, 0x8215, 0x8217, 0x8218, 0x821a, 0x821b, 0x821d, 0x821f,
+ 0x8220, 0x8220, 0x8220, 0x8220, 0x8221, 0x8221, 0x8222, 0x8222,
+ 0x8223, 0x8224, 0x8225, 0x8225, 0x8226, 0x8227, 0x8228, 0x8229,
+ 0x822a, 0x822b, 0x822c, 0x822e, 0x822f, 0x8230, 0x8231, 0x8233,
+ 0x8234, 0x8235, 0x8237, 0x8238, 0x823a, 0x823b, 0x823d, 0x823f,
+ 0x8240, 0x8240, 0x8240, 0x8240, 0x8241, 0x8241, 0x8242, 0x8242,
+ 0x8243, 0x8244, 0x8245, 0x8245, 0x8246, 0x8247, 0x8248, 0x8249,
+ 0x824a, 0x824b, 0x824c, 0x824e, 0x824f, 0x8250, 0x8251, 0x8253,
+ 0x8254, 0x8255, 0x8257, 0x8258, 0x825a, 0x825b, 0x825d, 0x825f,
+ 0x8260, 0x8260, 0x8260, 0x8260, 0x8261, 0x8261, 0x8262, 0x8262,
+ 0x8263, 0x8264, 0x8265, 0x8265, 0x8266, 0x8267, 0x8268, 0x8269,
+ 0x826a, 0x826b, 0x826c, 0x826e, 0x826f, 0x8270, 0x8271, 0x8273,
+ 0x8274, 0x8275, 0x8277, 0x8278, 0x827a, 0x827b, 0x827d, 0x827f,
+ 0x8280, 0x8280, 0x8280, 0x8280, 0x8281, 0x8281, 0x8282, 0x8282,
+ 0x8283, 0x8284, 0x8285, 0x8285, 0x8286, 0x8287, 0x8288, 0x8289,
+ 0x828a, 0x828b, 0x828c, 0x828e, 0x828f, 0x8290, 0x8291, 0x8293,
+ 0x8294, 0x8295, 0x8297, 0x8298, 0x829a, 0x829b, 0x829d, 0x829f,
+ 0x82a0, 0x82a0, 0x82a0, 0x82a0, 0x82a1, 0x82a1, 0x82a2, 0x82a2,
+ 0x82a3, 0x82a4, 0x82a5, 0x82a5, 0x82a6, 0x82a7, 0x82a8, 0x82a9,
+ 0x82aa, 0x82ab, 0x82ac, 0x82ae, 0x82af, 0x82b0, 0x82b1, 0x82b3,
+ 0x82b4, 0x82b5, 0x82b7, 0x82b8, 0x82ba, 0x82bb, 0x82bd, 0x82bf,
+ 0x82c0, 0x82c0, 0x82c0, 0x82c0, 0x82c1, 0x82c1, 0x82c2, 0x82c2,
+ 0x82c3, 0x82c4, 0x82c5, 0x82c5, 0x82c6, 0x82c7, 0x82c8, 0x82c9,
+ 0x82ca, 0x82cb, 0x82cc, 0x82ce, 0x82cf, 0x82d0, 0x82d1, 0x82d3,
+ 0x82d4, 0x82d5, 0x82d7, 0x82d8, 0x82da, 0x82db, 0x82dd, 0x82df,
+ 0x82e0, 0x82e0, 0x82e0, 0x82e0, 0x82e1, 0x82e1, 0x82e2, 0x82e2,
+ 0x82e3, 0x82e4, 0x82e5, 0x82e5, 0x82e6, 0x82e7, 0x82e8, 0x82e9,
+ 0x82ea, 0x82eb, 0x82ec, 0x82ee, 0x82ef, 0x82f0, 0x82f1, 0x82f3,
+ 0x82f4, 0x82f5, 0x82f7, 0x82f8, 0x82fa, 0x82fb, 0x82fd, 0x82ff,
+ 0x8300, 0x8300, 0x8300, 0x8300, 0x8301, 0x8301, 0x8302, 0x8302,
+ 0x8303, 0x8304, 0x8305, 0x8305, 0x8306, 0x8307, 0x8308, 0x8309,
+ 0x830a, 0x830b, 0x830c, 0x830e, 0x830f, 0x8310, 0x8311, 0x8313,
+ 0x8314, 0x8315, 0x8317, 0x8318, 0x831a, 0x831b, 0x831d, 0x831f,
+ 0x8320, 0x8320, 0x8320, 0x8320, 0x8321, 0x8321, 0x8322, 0x8322,
+ 0x8323, 0x8324, 0x8325, 0x8325, 0x8326, 0x8327, 0x8328, 0x8329,
+ 0x832a, 0x832b, 0x832c, 0x832e, 0x832f, 0x8330, 0x8331, 0x8333,
+ 0x8334, 0x8335, 0x8337, 0x8338, 0x833a, 0x833b, 0x833d, 0x833f,
+ 0x8340, 0x8340, 0x8340, 0x8340, 0x8341, 0x8341, 0x8342, 0x8342,
+ 0x8343, 0x8344, 0x8345, 0x8345, 0x8346, 0x8347, 0x8348, 0x8349,
+ 0x834a, 0x834b, 0x834c, 0x834e, 0x834f, 0x8350, 0x8351, 0x8353,
+ 0x8354, 0x8355, 0x8357, 0x8358, 0x835a, 0x835b, 0x835d, 0x835f,
+ 0x8380, 0x8380, 0x8380, 0x8380, 0x8381, 0x8381, 0x8382, 0x8382,
+ 0x8383, 0x8384, 0x8385, 0x8385, 0x8386, 0x8387, 0x8388, 0x8389,
+ 0x838a, 0x838b, 0x838c, 0x838e, 0x838f, 0x8390, 0x8391, 0x8393,
+ 0x8394, 0x8395, 0x8397, 0x8398, 0x839a, 0x839b, 0x839d, 0x839f,
+ 0x83a0, 0x83a0, 0x83a0, 0x83a0, 0x83a1, 0x83a1, 0x83a2, 0x83a2,
+ 0x83a3, 0x83a4, 0x83a5, 0x83a5, 0x83a6, 0x83a7, 0x83a8, 0x83a9,
+ 0x83aa, 0x83ab, 0x83ac, 0x83ae, 0x83af, 0x83b0, 0x83b1, 0x83b3,
+ 0x83b4, 0x83b5, 0x83b7, 0x83b8, 0x83ba, 0x83bb, 0x83bd, 0x83bf,
+ 0x83c0, 0x83c0, 0x83c0, 0x83c0, 0x83c1, 0x83c1, 0x83c2, 0x83c2,
+ 0x83c3, 0x83c4, 0x83c5, 0x83c5, 0x83c6, 0x83c7, 0x83c8, 0x83c9,
+ 0x83ca, 0x83cb, 0x83cc, 0x83ce, 0x83cf, 0x83d0, 0x83d1, 0x83d3,
+ 0x83d4, 0x83d5, 0x83d7, 0x83d8, 0x83da, 0x83db, 0x83dd, 0x83df,
+ 0x83e0, 0x83e0, 0x83e0, 0x83e0, 0x83e1, 0x83e1, 0x83e2, 0x83e2,
+ 0x83e3, 0x83e4, 0x83e5, 0x83e5, 0x83e6, 0x83e7, 0x83e8, 0x83e9,
+ 0x83ea, 0x83eb, 0x83ec, 0x83ee, 0x83ef, 0x83f0, 0x83f1, 0x83f3,
+ 0x83f4, 0x83f5, 0x83f7, 0x83f8, 0x83fa, 0x83fb, 0x83fd, 0x83ff,
+ 0x8400, 0x8400, 0x8400, 0x8400, 0x8401, 0x8401, 0x8402, 0x8402,
+ 0x8403, 0x8404, 0x8405, 0x8405, 0x8406, 0x8407, 0x8408, 0x8409,
+ 0x840a, 0x840b, 0x840c, 0x840e, 0x840f, 0x8410, 0x8411, 0x8413,
+ 0x8414, 0x8415, 0x8417, 0x8418, 0x841a, 0x841b, 0x841d, 0x841f,
+ 0x8440, 0x8440, 0x8440, 0x8440, 0x8441, 0x8441, 0x8442, 0x8442,
+ 0x8443, 0x8444, 0x8445, 0x8445, 0x8446, 0x8447, 0x8448, 0x8449,
+ 0x844a, 0x844b, 0x844c, 0x844e, 0x844f, 0x8450, 0x8451, 0x8453,
+ 0x8454, 0x8455, 0x8457, 0x8458, 0x845a, 0x845b, 0x845d, 0x845f,
+ 0x8460, 0x8460, 0x8460, 0x8460, 0x8461, 0x8461, 0x8462, 0x8462,
+ 0x8463, 0x8464, 0x8465, 0x8465, 0x8466, 0x8467, 0x8468, 0x8469,
+ 0x846a, 0x846b, 0x846c, 0x846e, 0x846f, 0x8470, 0x8471, 0x8473,
+ 0x8474, 0x8475, 0x8477, 0x8478, 0x847a, 0x847b, 0x847d, 0x847f,
+ 0x8480, 0x8480, 0x8480, 0x8480, 0x8481, 0x8481, 0x8482, 0x8482,
+ 0x8483, 0x8484, 0x8485, 0x8485, 0x8486, 0x8487, 0x8488, 0x8489,
+ 0x848a, 0x848b, 0x848c, 0x848e, 0x848f, 0x8490, 0x8491, 0x8493,
+ 0x8494, 0x8495, 0x8497, 0x8498, 0x849a, 0x849b, 0x849d, 0x849f,
+ 0x84c0, 0x84c0, 0x84c0, 0x84c0, 0x84c1, 0x84c1, 0x84c2, 0x84c2,
+ 0x84c3, 0x84c4, 0x84c5, 0x84c5, 0x84c6, 0x84c7, 0x84c8, 0x84c9,
+ 0x84ca, 0x84cb, 0x84cc, 0x84ce, 0x84cf, 0x84d0, 0x84d1, 0x84d3,
+ 0x84d4, 0x84d5, 0x84d7, 0x84d8, 0x84da, 0x84db, 0x84dd, 0x84df,
+ 0x84e0, 0x84e0, 0x84e0, 0x84e0, 0x84e1, 0x84e1, 0x84e2, 0x84e2,
+ 0x84e3, 0x84e4, 0x84e5, 0x84e5, 0x84e6, 0x84e7, 0x84e8, 0x84e9,
+ 0x84ea, 0x84eb, 0x84ec, 0x84ee, 0x84ef, 0x84f0, 0x84f1, 0x84f3,
+ 0x84f4, 0x84f5, 0x84f7, 0x84f8, 0x84fa, 0x84fb, 0x84fd, 0x84ff,
+ 0x8500, 0x8500, 0x8500, 0x8500, 0x8501, 0x8501, 0x8502, 0x8502,
+ 0x8503, 0x8504, 0x8505, 0x8505, 0x8506, 0x8507, 0x8508, 0x8509,
+ 0x850a, 0x850b, 0x850c, 0x850e, 0x850f, 0x8510, 0x8511, 0x8513,
+ 0x8514, 0x8515, 0x8517, 0x8518, 0x851a, 0x851b, 0x851d, 0x851f,
+ 0x8540, 0x8540, 0x8540, 0x8540, 0x8541, 0x8541, 0x8542, 0x8542,
+ 0x8543, 0x8544, 0x8545, 0x8545, 0x8546, 0x8547, 0x8548, 0x8549,
+ 0x854a, 0x854b, 0x854c, 0x854e, 0x854f, 0x8550, 0x8551, 0x8553,
+ 0x8554, 0x8555, 0x8557, 0x8558, 0x855a, 0x855b, 0x855d, 0x855f,
+ 0x8560, 0x8560, 0x8560, 0x8560, 0x8561, 0x8561, 0x8562, 0x8562,
+ 0x8563, 0x8564, 0x8565, 0x8565, 0x8566, 0x8567, 0x8568, 0x8569,
+ 0x856a, 0x856b, 0x856c, 0x856e, 0x856f, 0x8570, 0x8571, 0x8573,
+ 0x8574, 0x8575, 0x8577, 0x8578, 0x857a, 0x857b, 0x857d, 0x857f,
+ 0x8580, 0x8580, 0x8580, 0x8580, 0x8581, 0x8581, 0x8582, 0x8582,
+ 0x8583, 0x8584, 0x8585, 0x8585, 0x8586, 0x8587, 0x8588, 0x8589,
+ 0x858a, 0x858b, 0x858c, 0x858e, 0x858f, 0x8590, 0x8591, 0x8593,
+ 0x8594, 0x8595, 0x8597, 0x8598, 0x859a, 0x859b, 0x859d, 0x859f,
+ 0x85c0, 0x85c0, 0x85c0, 0x85c0, 0x85c1, 0x85c1, 0x85c2, 0x85c2,
+ 0x85c3, 0x85c4, 0x85c5, 0x85c5, 0x85c6, 0x85c7, 0x85c8, 0x85c9,
+ 0x85ca, 0x85cb, 0x85cc, 0x85ce, 0x85cf, 0x85d0, 0x85d1, 0x85d3,
+ 0x85d4, 0x85d5, 0x85d7, 0x85d8, 0x85da, 0x85db, 0x85dd, 0x85df,
+ 0x85e0, 0x85e0, 0x85e0, 0x85e0, 0x85e1, 0x85e1, 0x85e2, 0x85e2,
+ 0x85e3, 0x85e4, 0x85e5, 0x85e5, 0x85e6, 0x85e7, 0x85e8, 0x85e9,
+ 0x85ea, 0x85eb, 0x85ec, 0x85ee, 0x85ef, 0x85f0, 0x85f1, 0x85f3,
+ 0x85f4, 0x85f5, 0x85f7, 0x85f8, 0x85fa, 0x85fb, 0x85fd, 0x85ff,
+ 0x8620, 0x8620, 0x8620, 0x8620, 0x8621, 0x8621, 0x8622, 0x8622,
+ 0x8623, 0x8624, 0x8625, 0x8625, 0x8626, 0x8627, 0x8628, 0x8629,
+ 0x862a, 0x862b, 0x862c, 0x862e, 0x862f, 0x8630, 0x8631, 0x8633,
+ 0x8634, 0x8635, 0x8637, 0x8638, 0x863a, 0x863b, 0x863d, 0x863f,
+ 0x8640, 0x8640, 0x8640, 0x8640, 0x8641, 0x8641, 0x8642, 0x8642,
+ 0x8643, 0x8644, 0x8645, 0x8645, 0x8646, 0x8647, 0x8648, 0x8649,
+ 0x864a, 0x864b, 0x864c, 0x864e, 0x864f, 0x8650, 0x8651, 0x8653,
+ 0x8654, 0x8655, 0x8657, 0x8658, 0x865a, 0x865b, 0x865d, 0x865f,
+ 0x8680, 0x8680, 0x8680, 0x8680, 0x8681, 0x8681, 0x8682, 0x8682,
+ 0x8683, 0x8684, 0x8685, 0x8685, 0x8686, 0x8687, 0x8688, 0x8689,
+ 0x868a, 0x868b, 0x868c, 0x868e, 0x868f, 0x8690, 0x8691, 0x8693,
+ 0x8694, 0x8695, 0x8697, 0x8698, 0x869a, 0x869b, 0x869d, 0x869f,
+ 0x86a0, 0x86a0, 0x86a0, 0x86a0, 0x86a1, 0x86a1, 0x86a2, 0x86a2,
+ 0x86a3, 0x86a4, 0x86a5, 0x86a5, 0x86a6, 0x86a7, 0x86a8, 0x86a9,
+ 0x86aa, 0x86ab, 0x86ac, 0x86ae, 0x86af, 0x86b0, 0x86b1, 0x86b3,
+ 0x86b4, 0x86b5, 0x86b7, 0x86b8, 0x86ba, 0x86bb, 0x86bd, 0x86bf,
+ 0x86e0, 0x86e0, 0x86e0, 0x86e0, 0x86e1, 0x86e1, 0x86e2, 0x86e2,
+ 0x86e3, 0x86e4, 0x86e5, 0x86e5, 0x86e6, 0x86e7, 0x86e8, 0x86e9,
+ 0x86ea, 0x86eb, 0x86ec, 0x86ee, 0x86ef, 0x86f0, 0x86f1, 0x86f3,
+ 0x86f4, 0x86f5, 0x86f7, 0x86f8, 0x86fa, 0x86fb, 0x86fd, 0x86ff,
+ 0x8700, 0x8700, 0x8700, 0x8700, 0x8701, 0x8701, 0x8702, 0x8702,
+ 0x8703, 0x8704, 0x8705, 0x8705, 0x8706, 0x8707, 0x8708, 0x8709,
+ 0x870a, 0x870b, 0x870c, 0x870e, 0x870f, 0x8710, 0x8711, 0x8713,
+ 0x8714, 0x8715, 0x8717, 0x8718, 0x871a, 0x871b, 0x871d, 0x871f,
+ 0x8740, 0x8740, 0x8740, 0x8740, 0x8741, 0x8741, 0x8742, 0x8742,
+ 0x8743, 0x8744, 0x8745, 0x8745, 0x8746, 0x8747, 0x8748, 0x8749,
+ 0x874a, 0x874b, 0x874c, 0x874e, 0x874f, 0x8750, 0x8751, 0x8753,
+ 0x8754, 0x8755, 0x8757, 0x8758, 0x875a, 0x875b, 0x875d, 0x875f,
+ 0x8760, 0x8760, 0x8760, 0x8760, 0x8761, 0x8761, 0x8762, 0x8762,
+ 0x8763, 0x8764, 0x8765, 0x8765, 0x8766, 0x8767, 0x8768, 0x8769,
+ 0x876a, 0x876b, 0x876c, 0x876e, 0x876f, 0x8770, 0x8771, 0x8773,
+ 0x8774, 0x8775, 0x8777, 0x8778, 0x877a, 0x877b, 0x877d, 0x877f,
+ 0x87a0, 0x87a0, 0x87a0, 0x87a0, 0x87a1, 0x87a1, 0x87a2, 0x87a2,
+ 0x87a3, 0x87a4, 0x87a5, 0x87a5, 0x87a6, 0x87a7, 0x87a8, 0x87a9,
+ 0x87aa, 0x87ab, 0x87ac, 0x87ae, 0x87af, 0x87b0, 0x87b1, 0x87b3,
+ 0x87b4, 0x87b5, 0x87b7, 0x87b8, 0x87ba, 0x87bb, 0x87bd, 0x87bf,
+ 0x87e0, 0x87e0, 0x87e0, 0x87e0, 0x87e1, 0x87e1, 0x87e2, 0x87e2,
+ 0x87e3, 0x87e4, 0x87e5, 0x87e5, 0x87e6, 0x87e7, 0x87e8, 0x87e9,
+ 0x87ea, 0x87eb, 0x87ec, 0x87ee, 0x87ef, 0x87f0, 0x87f1, 0x87f3,
+ 0x87f4, 0x87f5, 0x87f7, 0x87f8, 0x87fa, 0x87fb, 0x87fd, 0x87ff,
+ 0x8800, 0x8800, 0x8800, 0x8800, 0x8801, 0x8801, 0x8802, 0x8802,
+ 0x8803, 0x8804, 0x8805, 0x8805, 0x8806, 0x8807, 0x8808, 0x8809,
+ 0x880a, 0x880b, 0x880c, 0x880e, 0x880f, 0x8810, 0x8811, 0x8813,
+ 0x8814, 0x8815, 0x8817, 0x8818, 0x881a, 0x881b, 0x881d, 0x881f,
+ 0x8800, 0x8800, 0x8800, 0x8800, 0x8801, 0x8801, 0x8802, 0x8802,
+ 0x8803, 0x8804, 0x8805, 0x8805, 0x8806, 0x8807, 0x8808, 0x8809,
+ 0x880a, 0x880b, 0x880c, 0x880e, 0x880f, 0x8810, 0x8811, 0x8813,
+ 0x8814, 0x8815, 0x8817, 0x8818, 0x881a, 0x881b, 0x881d, 0x881f,
+ 0x8800, 0x8800, 0x8800, 0x8800, 0x8801, 0x8801, 0x8802, 0x8802,
+ 0x8803, 0x8804, 0x8805, 0x8805, 0x8806, 0x8807, 0x8808, 0x8809,
+ 0x880a, 0x880b, 0x880c, 0x880e, 0x880f, 0x8810, 0x8811, 0x8813,
+ 0x8814, 0x8815, 0x8817, 0x8818, 0x881a, 0x881b, 0x881d, 0x881f,
+ 0x8800, 0x8800, 0x8800, 0x8800, 0x8801, 0x8801, 0x8802, 0x8802,
+ 0x8803, 0x8804, 0x8805, 0x8805, 0x8806, 0x8807, 0x8808, 0x8809,
+ 0x880a, 0x880b, 0x880c, 0x880e, 0x880f, 0x8810, 0x8811, 0x8813,
+ 0x8814, 0x8815, 0x8817, 0x8818, 0x881a, 0x881b, 0x881d, 0x881f,
+ 0x8800, 0x8800, 0x8800, 0x8800, 0x8801, 0x8801, 0x8802, 0x8802,
+ 0x8803, 0x8804, 0x8805, 0x8805, 0x8806, 0x8807, 0x8808, 0x8809,
+ 0x880a, 0x880b, 0x880c, 0x880e, 0x880f, 0x8810, 0x8811, 0x8813,
+ 0x8814, 0x8815, 0x8817, 0x8818, 0x881a, 0x881b, 0x881d, 0x881f,
+ 0x8820, 0x8820, 0x8820, 0x8820, 0x8821, 0x8821, 0x8822, 0x8822,
+ 0x8823, 0x8824, 0x8825, 0x8825, 0x8826, 0x8827, 0x8828, 0x8829,
+ 0x882a, 0x882b, 0x882c, 0x882e, 0x882f, 0x8830, 0x8831, 0x8833,
+ 0x8834, 0x8835, 0x8837, 0x8838, 0x883a, 0x883b, 0x883d, 0x883f,
+ 0x8820, 0x8820, 0x8820, 0x8820, 0x8821, 0x8821, 0x8822, 0x8822,
+ 0x8823, 0x8824, 0x8825, 0x8825, 0x8826, 0x8827, 0x8828, 0x8829,
+ 0x882a, 0x882b, 0x882c, 0x882e, 0x882f, 0x8830, 0x8831, 0x8833,
+ 0x8834, 0x8835, 0x8837, 0x8838, 0x883a, 0x883b, 0x883d, 0x883f,
+ 0x8820, 0x8820, 0x8820, 0x8820, 0x8821, 0x8821, 0x8822, 0x8822,
+ 0x8823, 0x8824, 0x8825, 0x8825, 0x8826, 0x8827, 0x8828, 0x8829,
+ 0x882a, 0x882b, 0x882c, 0x882e, 0x882f, 0x8830, 0x8831, 0x8833,
+ 0x8834, 0x8835, 0x8837, 0x8838, 0x883a, 0x883b, 0x883d, 0x883f,
+ 0x8840, 0x8840, 0x8840, 0x8840, 0x8841, 0x8841, 0x8842, 0x8842,
+ 0x8843, 0x8844, 0x8845, 0x8845, 0x8846, 0x8847, 0x8848, 0x8849,
+ 0x884a, 0x884b, 0x884c, 0x884e, 0x884f, 0x8850, 0x8851, 0x8853,
+ 0x8854, 0x8855, 0x8857, 0x8858, 0x885a, 0x885b, 0x885d, 0x885f,
+ 0x8840, 0x8840, 0x8840, 0x8840, 0x8841, 0x8841, 0x8842, 0x8842,
+ 0x8843, 0x8844, 0x8845, 0x8845, 0x8846, 0x8847, 0x8848, 0x8849,
+ 0x884a, 0x884b, 0x884c, 0x884e, 0x884f, 0x8850, 0x8851, 0x8853,
+ 0x8854, 0x8855, 0x8857, 0x8858, 0x885a, 0x885b, 0x885d, 0x885f,
+ 0x8860, 0x8860, 0x8860, 0x8860, 0x8861, 0x8861, 0x8862, 0x8862,
+ 0x8863, 0x8864, 0x8865, 0x8865, 0x8866, 0x8867, 0x8868, 0x8869,
+ 0x886a, 0x886b, 0x886c, 0x886e, 0x886f, 0x8870, 0x8871, 0x8873,
+ 0x8874, 0x8875, 0x8877, 0x8878, 0x887a, 0x887b, 0x887d, 0x887f,
+ 0x8860, 0x8860, 0x8860, 0x8860, 0x8861, 0x8861, 0x8862, 0x8862,
+ 0x8863, 0x8864, 0x8865, 0x8865, 0x8866, 0x8867, 0x8868, 0x8869,
+ 0x886a, 0x886b, 0x886c, 0x886e, 0x886f, 0x8870, 0x8871, 0x8873,
+ 0x8874, 0x8875, 0x8877, 0x8878, 0x887a, 0x887b, 0x887d, 0x887f,
+ 0x8880, 0x8880, 0x8880, 0x8880, 0x8881, 0x8881, 0x8882, 0x8882,
+ 0x8883, 0x8884, 0x8885, 0x8885, 0x8886, 0x8887, 0x8888, 0x8889,
+ 0x888a, 0x888b, 0x888c, 0x888e, 0x888f, 0x8890, 0x8891, 0x8893,
+ 0x8894, 0x8895, 0x8897, 0x8898, 0x889a, 0x889b, 0x889d, 0x889f,
+ 0x88a0, 0x88a0, 0x88a0, 0x88a0, 0x88a1, 0x88a1, 0x88a2, 0x88a2,
+ 0x88a3, 0x88a4, 0x88a5, 0x88a5, 0x88a6, 0x88a7, 0x88a8, 0x88a9,
+ 0x88aa, 0x88ab, 0x88ac, 0x88ae, 0x88af, 0x88b0, 0x88b1, 0x88b3,
+ 0x88b4, 0x88b5, 0x88b7, 0x88b8, 0x88ba, 0x88bb, 0x88bd, 0x88bf,
+ 0x88a0, 0x88a0, 0x88a0, 0x88a0, 0x88a1, 0x88a1, 0x88a2, 0x88a2,
+ 0x88a3, 0x88a4, 0x88a5, 0x88a5, 0x88a6, 0x88a7, 0x88a8, 0x88a9,
+ 0x88aa, 0x88ab, 0x88ac, 0x88ae, 0x88af, 0x88b0, 0x88b1, 0x88b3,
+ 0x88b4, 0x88b5, 0x88b7, 0x88b8, 0x88ba, 0x88bb, 0x88bd, 0x88bf,
+ 0x88c0, 0x88c0, 0x88c0, 0x88c0, 0x88c1, 0x88c1, 0x88c2, 0x88c2,
+ 0x88c3, 0x88c4, 0x88c5, 0x88c5, 0x88c6, 0x88c7, 0x88c8, 0x88c9,
+ 0x88ca, 0x88cb, 0x88cc, 0x88ce, 0x88cf, 0x88d0, 0x88d1, 0x88d3,
+ 0x88d4, 0x88d5, 0x88d7, 0x88d8, 0x88da, 0x88db, 0x88dd, 0x88df,
+ 0x88e0, 0x88e0, 0x88e0, 0x88e0, 0x88e1, 0x88e1, 0x88e2, 0x88e2,
+ 0x88e3, 0x88e4, 0x88e5, 0x88e5, 0x88e6, 0x88e7, 0x88e8, 0x88e9,
+ 0x88ea, 0x88eb, 0x88ec, 0x88ee, 0x88ef, 0x88f0, 0x88f1, 0x88f3,
+ 0x88f4, 0x88f5, 0x88f7, 0x88f8, 0x88fa, 0x88fb, 0x88fd, 0x88ff,
+ 0x88e0, 0x88e0, 0x88e0, 0x88e0, 0x88e1, 0x88e1, 0x88e2, 0x88e2,
+ 0x88e3, 0x88e4, 0x88e5, 0x88e5, 0x88e6, 0x88e7, 0x88e8, 0x88e9,
+ 0x88ea, 0x88eb, 0x88ec, 0x88ee, 0x88ef, 0x88f0, 0x88f1, 0x88f3,
+ 0x88f4, 0x88f5, 0x88f7, 0x88f8, 0x88fa, 0x88fb, 0x88fd, 0x88ff,
+ 0x8900, 0x8900, 0x8900, 0x8900, 0x8901, 0x8901, 0x8902, 0x8902,
+ 0x8903, 0x8904, 0x8905, 0x8905, 0x8906, 0x8907, 0x8908, 0x8909,
+ 0x890a, 0x890b, 0x890c, 0x890e, 0x890f, 0x8910, 0x8911, 0x8913,
+ 0x8914, 0x8915, 0x8917, 0x8918, 0x891a, 0x891b, 0x891d, 0x891f,
+ 0x8920, 0x8920, 0x8920, 0x8920, 0x8921, 0x8921, 0x8922, 0x8922,
+ 0x8923, 0x8924, 0x8925, 0x8925, 0x8926, 0x8927, 0x8928, 0x8929,
+ 0x892a, 0x892b, 0x892c, 0x892e, 0x892f, 0x8930, 0x8931, 0x8933,
+ 0x8934, 0x8935, 0x8937, 0x8938, 0x893a, 0x893b, 0x893d, 0x893f,
+ 0x8940, 0x8940, 0x8940, 0x8940, 0x8941, 0x8941, 0x8942, 0x8942,
+ 0x8943, 0x8944, 0x8945, 0x8945, 0x8946, 0x8947, 0x8948, 0x8949,
+ 0x894a, 0x894b, 0x894c, 0x894e, 0x894f, 0x8950, 0x8951, 0x8953,
+ 0x8954, 0x8955, 0x8957, 0x8958, 0x895a, 0x895b, 0x895d, 0x895f,
+ 0x8940, 0x8940, 0x8940, 0x8940, 0x8941, 0x8941, 0x8942, 0x8942,
+ 0x8943, 0x8944, 0x8945, 0x8945, 0x8946, 0x8947, 0x8948, 0x8949,
+ 0x894a, 0x894b, 0x894c, 0x894e, 0x894f, 0x8950, 0x8951, 0x8953,
+ 0x8954, 0x8955, 0x8957, 0x8958, 0x895a, 0x895b, 0x895d, 0x895f,
+ 0x8960, 0x8960, 0x8960, 0x8960, 0x8961, 0x8961, 0x8962, 0x8962,
+ 0x8963, 0x8964, 0x8965, 0x8965, 0x8966, 0x8967, 0x8968, 0x8969,
+ 0x896a, 0x896b, 0x896c, 0x896e, 0x896f, 0x8970, 0x8971, 0x8973,
+ 0x8974, 0x8975, 0x8977, 0x8978, 0x897a, 0x897b, 0x897d, 0x897f,
+ 0x8980, 0x8980, 0x8980, 0x8980, 0x8981, 0x8981, 0x8982, 0x8982,
+ 0x8983, 0x8984, 0x8985, 0x8985, 0x8986, 0x8987, 0x8988, 0x8989,
+ 0x898a, 0x898b, 0x898c, 0x898e, 0x898f, 0x8990, 0x8991, 0x8993,
+ 0x8994, 0x8995, 0x8997, 0x8998, 0x899a, 0x899b, 0x899d, 0x899f,
+ 0x89a0, 0x89a0, 0x89a0, 0x89a0, 0x89a1, 0x89a1, 0x89a2, 0x89a2,
+ 0x89a3, 0x89a4, 0x89a5, 0x89a5, 0x89a6, 0x89a7, 0x89a8, 0x89a9,
+ 0x89aa, 0x89ab, 0x89ac, 0x89ae, 0x89af, 0x89b0, 0x89b1, 0x89b3,
+ 0x89b4, 0x89b5, 0x89b7, 0x89b8, 0x89ba, 0x89bb, 0x89bd, 0x89bf,
+ 0x89c0, 0x89c0, 0x89c0, 0x89c0, 0x89c1, 0x89c1, 0x89c2, 0x89c2,
+ 0x89c3, 0x89c4, 0x89c5, 0x89c5, 0x89c6, 0x89c7, 0x89c8, 0x89c9,
+ 0x89ca, 0x89cb, 0x89cc, 0x89ce, 0x89cf, 0x89d0, 0x89d1, 0x89d3,
+ 0x89d4, 0x89d5, 0x89d7, 0x89d8, 0x89da, 0x89db, 0x89dd, 0x89df,
+ 0x89e0, 0x89e0, 0x89e0, 0x89e0, 0x89e1, 0x89e1, 0x89e2, 0x89e2,
+ 0x89e3, 0x89e4, 0x89e5, 0x89e5, 0x89e6, 0x89e7, 0x89e8, 0x89e9,
+ 0x89ea, 0x89eb, 0x89ec, 0x89ee, 0x89ef, 0x89f0, 0x89f1, 0x89f3,
+ 0x89f4, 0x89f5, 0x89f7, 0x89f8, 0x89fa, 0x89fb, 0x89fd, 0x89ff,
+ 0x8a00, 0x8a00, 0x8a00, 0x8a00, 0x8a01, 0x8a01, 0x8a02, 0x8a02,
+ 0x8a03, 0x8a04, 0x8a05, 0x8a05, 0x8a06, 0x8a07, 0x8a08, 0x8a09,
+ 0x8a0a, 0x8a0b, 0x8a0c, 0x8a0e, 0x8a0f, 0x8a10, 0x8a11, 0x8a13,
+ 0x8a14, 0x8a15, 0x8a17, 0x8a18, 0x8a1a, 0x8a1b, 0x8a1d, 0x8a1f,
+ 0x8a20, 0x8a20, 0x8a20, 0x8a20, 0x8a21, 0x8a21, 0x8a22, 0x8a22,
+ 0x8a23, 0x8a24, 0x8a25, 0x8a25, 0x8a26, 0x8a27, 0x8a28, 0x8a29,
+ 0x8a2a, 0x8a2b, 0x8a2c, 0x8a2e, 0x8a2f, 0x8a30, 0x8a31, 0x8a33,
+ 0x8a34, 0x8a35, 0x8a37, 0x8a38, 0x8a3a, 0x8a3b, 0x8a3d, 0x8a3f,
+ 0x8a40, 0x8a40, 0x8a40, 0x8a40, 0x8a41, 0x8a41, 0x8a42, 0x8a42,
+ 0x8a43, 0x8a44, 0x8a45, 0x8a45, 0x8a46, 0x8a47, 0x8a48, 0x8a49,
+ 0x8a4a, 0x8a4b, 0x8a4c, 0x8a4e, 0x8a4f, 0x8a50, 0x8a51, 0x8a53,
+ 0x8a54, 0x8a55, 0x8a57, 0x8a58, 0x8a5a, 0x8a5b, 0x8a5d, 0x8a5f,
+ 0x8a60, 0x8a60, 0x8a60, 0x8a60, 0x8a61, 0x8a61, 0x8a62, 0x8a62,
+ 0x8a63, 0x8a64, 0x8a65, 0x8a65, 0x8a66, 0x8a67, 0x8a68, 0x8a69,
+ 0x8a6a, 0x8a6b, 0x8a6c, 0x8a6e, 0x8a6f, 0x8a70, 0x8a71, 0x8a73,
+ 0x8a74, 0x8a75, 0x8a77, 0x8a78, 0x8a7a, 0x8a7b, 0x8a7d, 0x8a7f,
+ 0x8a80, 0x8a80, 0x8a80, 0x8a80, 0x8a81, 0x8a81, 0x8a82, 0x8a82,
+ 0x8a83, 0x8a84, 0x8a85, 0x8a85, 0x8a86, 0x8a87, 0x8a88, 0x8a89,
+ 0x8a8a, 0x8a8b, 0x8a8c, 0x8a8e, 0x8a8f, 0x8a90, 0x8a91, 0x8a93,
+ 0x8a94, 0x8a95, 0x8a97, 0x8a98, 0x8a9a, 0x8a9b, 0x8a9d, 0x8a9f,
+ 0x8aa0, 0x8aa0, 0x8aa0, 0x8aa0, 0x8aa1, 0x8aa1, 0x8aa2, 0x8aa2,
+ 0x8aa3, 0x8aa4, 0x8aa5, 0x8aa5, 0x8aa6, 0x8aa7, 0x8aa8, 0x8aa9,
+ 0x8aaa, 0x8aab, 0x8aac, 0x8aae, 0x8aaf, 0x8ab0, 0x8ab1, 0x8ab3,
+ 0x8ab4, 0x8ab5, 0x8ab7, 0x8ab8, 0x8aba, 0x8abb, 0x8abd, 0x8abf,
+ 0x8ac0, 0x8ac0, 0x8ac0, 0x8ac0, 0x8ac1, 0x8ac1, 0x8ac2, 0x8ac2,
+ 0x8ac3, 0x8ac4, 0x8ac5, 0x8ac5, 0x8ac6, 0x8ac7, 0x8ac8, 0x8ac9,
+ 0x8aca, 0x8acb, 0x8acc, 0x8ace, 0x8acf, 0x8ad0, 0x8ad1, 0x8ad3,
+ 0x8ad4, 0x8ad5, 0x8ad7, 0x8ad8, 0x8ada, 0x8adb, 0x8add, 0x8adf,
+ 0x8ae0, 0x8ae0, 0x8ae0, 0x8ae0, 0x8ae1, 0x8ae1, 0x8ae2, 0x8ae2,
+ 0x8ae3, 0x8ae4, 0x8ae5, 0x8ae5, 0x8ae6, 0x8ae7, 0x8ae8, 0x8ae9,
+ 0x8aea, 0x8aeb, 0x8aec, 0x8aee, 0x8aef, 0x8af0, 0x8af1, 0x8af3,
+ 0x8af4, 0x8af5, 0x8af7, 0x8af8, 0x8afa, 0x8afb, 0x8afd, 0x8aff,
+ 0x8b00, 0x8b00, 0x8b00, 0x8b00, 0x8b01, 0x8b01, 0x8b02, 0x8b02,
+ 0x8b03, 0x8b04, 0x8b05, 0x8b05, 0x8b06, 0x8b07, 0x8b08, 0x8b09,
+ 0x8b0a, 0x8b0b, 0x8b0c, 0x8b0e, 0x8b0f, 0x8b10, 0x8b11, 0x8b13,
+ 0x8b14, 0x8b15, 0x8b17, 0x8b18, 0x8b1a, 0x8b1b, 0x8b1d, 0x8b1f,
+ 0x8b20, 0x8b20, 0x8b20, 0x8b20, 0x8b21, 0x8b21, 0x8b22, 0x8b22,
+ 0x8b23, 0x8b24, 0x8b25, 0x8b25, 0x8b26, 0x8b27, 0x8b28, 0x8b29,
+ 0x8b2a, 0x8b2b, 0x8b2c, 0x8b2e, 0x8b2f, 0x8b30, 0x8b31, 0x8b33,
+ 0x8b34, 0x8b35, 0x8b37, 0x8b38, 0x8b3a, 0x8b3b, 0x8b3d, 0x8b3f,
+ 0x8b40, 0x8b40, 0x8b40, 0x8b40, 0x8b41, 0x8b41, 0x8b42, 0x8b42,
+ 0x8b43, 0x8b44, 0x8b45, 0x8b45, 0x8b46, 0x8b47, 0x8b48, 0x8b49,
+ 0x8b4a, 0x8b4b, 0x8b4c, 0x8b4e, 0x8b4f, 0x8b50, 0x8b51, 0x8b53,
+ 0x8b54, 0x8b55, 0x8b57, 0x8b58, 0x8b5a, 0x8b5b, 0x8b5d, 0x8b5f,
+ 0x8b80, 0x8b80, 0x8b80, 0x8b80, 0x8b81, 0x8b81, 0x8b82, 0x8b82,
+ 0x8b83, 0x8b84, 0x8b85, 0x8b85, 0x8b86, 0x8b87, 0x8b88, 0x8b89,
+ 0x8b8a, 0x8b8b, 0x8b8c, 0x8b8e, 0x8b8f, 0x8b90, 0x8b91, 0x8b93,
+ 0x8b94, 0x8b95, 0x8b97, 0x8b98, 0x8b9a, 0x8b9b, 0x8b9d, 0x8b9f,
+ 0x8ba0, 0x8ba0, 0x8ba0, 0x8ba0, 0x8ba1, 0x8ba1, 0x8ba2, 0x8ba2,
+ 0x8ba3, 0x8ba4, 0x8ba5, 0x8ba5, 0x8ba6, 0x8ba7, 0x8ba8, 0x8ba9,
+ 0x8baa, 0x8bab, 0x8bac, 0x8bae, 0x8baf, 0x8bb0, 0x8bb1, 0x8bb3,
+ 0x8bb4, 0x8bb5, 0x8bb7, 0x8bb8, 0x8bba, 0x8bbb, 0x8bbd, 0x8bbf,
+ 0x8bc0, 0x8bc0, 0x8bc0, 0x8bc0, 0x8bc1, 0x8bc1, 0x8bc2, 0x8bc2,
+ 0x8bc3, 0x8bc4, 0x8bc5, 0x8bc5, 0x8bc6, 0x8bc7, 0x8bc8, 0x8bc9,
+ 0x8bca, 0x8bcb, 0x8bcc, 0x8bce, 0x8bcf, 0x8bd0, 0x8bd1, 0x8bd3,
+ 0x8bd4, 0x8bd5, 0x8bd7, 0x8bd8, 0x8bda, 0x8bdb, 0x8bdd, 0x8bdf,
+ 0x8be0, 0x8be0, 0x8be0, 0x8be0, 0x8be1, 0x8be1, 0x8be2, 0x8be2,
+ 0x8be3, 0x8be4, 0x8be5, 0x8be5, 0x8be6, 0x8be7, 0x8be8, 0x8be9,
+ 0x8bea, 0x8beb, 0x8bec, 0x8bee, 0x8bef, 0x8bf0, 0x8bf1, 0x8bf3,
+ 0x8bf4, 0x8bf5, 0x8bf7, 0x8bf8, 0x8bfa, 0x8bfb, 0x8bfd, 0x8bff,
+ 0x8c00, 0x8c00, 0x8c00, 0x8c00, 0x8c01, 0x8c01, 0x8c02, 0x8c02,
+ 0x8c03, 0x8c04, 0x8c05, 0x8c05, 0x8c06, 0x8c07, 0x8c08, 0x8c09,
+ 0x8c0a, 0x8c0b, 0x8c0c, 0x8c0e, 0x8c0f, 0x8c10, 0x8c11, 0x8c13,
+ 0x8c14, 0x8c15, 0x8c17, 0x8c18, 0x8c1a, 0x8c1b, 0x8c1d, 0x8c1f,
+ 0x8c40, 0x8c40, 0x8c40, 0x8c40, 0x8c41, 0x8c41, 0x8c42, 0x8c42,
+ 0x8c43, 0x8c44, 0x8c45, 0x8c45, 0x8c46, 0x8c47, 0x8c48, 0x8c49,
+ 0x8c4a, 0x8c4b, 0x8c4c, 0x8c4e, 0x8c4f, 0x8c50, 0x8c51, 0x8c53,
+ 0x8c54, 0x8c55, 0x8c57, 0x8c58, 0x8c5a, 0x8c5b, 0x8c5d, 0x8c5f,
+ 0x8c60, 0x8c60, 0x8c60, 0x8c60, 0x8c61, 0x8c61, 0x8c62, 0x8c62,
+ 0x8c63, 0x8c64, 0x8c65, 0x8c65, 0x8c66, 0x8c67, 0x8c68, 0x8c69,
+ 0x8c6a, 0x8c6b, 0x8c6c, 0x8c6e, 0x8c6f, 0x8c70, 0x8c71, 0x8c73,
+ 0x8c74, 0x8c75, 0x8c77, 0x8c78, 0x8c7a, 0x8c7b, 0x8c7d, 0x8c7f,
+ 0x8c80, 0x8c80, 0x8c80, 0x8c80, 0x8c81, 0x8c81, 0x8c82, 0x8c82,
+ 0x8c83, 0x8c84, 0x8c85, 0x8c85, 0x8c86, 0x8c87, 0x8c88, 0x8c89,
+ 0x8c8a, 0x8c8b, 0x8c8c, 0x8c8e, 0x8c8f, 0x8c90, 0x8c91, 0x8c93,
+ 0x8c94, 0x8c95, 0x8c97, 0x8c98, 0x8c9a, 0x8c9b, 0x8c9d, 0x8c9f,
+ 0x8cc0, 0x8cc0, 0x8cc0, 0x8cc0, 0x8cc1, 0x8cc1, 0x8cc2, 0x8cc2,
+ 0x8cc3, 0x8cc4, 0x8cc5, 0x8cc5, 0x8cc6, 0x8cc7, 0x8cc8, 0x8cc9,
+ 0x8cca, 0x8ccb, 0x8ccc, 0x8cce, 0x8ccf, 0x8cd0, 0x8cd1, 0x8cd3,
+ 0x8cd4, 0x8cd5, 0x8cd7, 0x8cd8, 0x8cda, 0x8cdb, 0x8cdd, 0x8cdf,
+ 0x8ce0, 0x8ce0, 0x8ce0, 0x8ce0, 0x8ce1, 0x8ce1, 0x8ce2, 0x8ce2,
+ 0x8ce3, 0x8ce4, 0x8ce5, 0x8ce5, 0x8ce6, 0x8ce7, 0x8ce8, 0x8ce9,
+ 0x8cea, 0x8ceb, 0x8cec, 0x8cee, 0x8cef, 0x8cf0, 0x8cf1, 0x8cf3,
+ 0x8cf4, 0x8cf5, 0x8cf7, 0x8cf8, 0x8cfa, 0x8cfb, 0x8cfd, 0x8cff,
+ 0x8d00, 0x8d00, 0x8d00, 0x8d00, 0x8d01, 0x8d01, 0x8d02, 0x8d02,
+ 0x8d03, 0x8d04, 0x8d05, 0x8d05, 0x8d06, 0x8d07, 0x8d08, 0x8d09,
+ 0x8d0a, 0x8d0b, 0x8d0c, 0x8d0e, 0x8d0f, 0x8d10, 0x8d11, 0x8d13,
+ 0x8d14, 0x8d15, 0x8d17, 0x8d18, 0x8d1a, 0x8d1b, 0x8d1d, 0x8d1f,
+ 0x8d40, 0x8d40, 0x8d40, 0x8d40, 0x8d41, 0x8d41, 0x8d42, 0x8d42,
+ 0x8d43, 0x8d44, 0x8d45, 0x8d45, 0x8d46, 0x8d47, 0x8d48, 0x8d49,
+ 0x8d4a, 0x8d4b, 0x8d4c, 0x8d4e, 0x8d4f, 0x8d50, 0x8d51, 0x8d53,
+ 0x8d54, 0x8d55, 0x8d57, 0x8d58, 0x8d5a, 0x8d5b, 0x8d5d, 0x8d5f,
+ 0x8d60, 0x8d60, 0x8d60, 0x8d60, 0x8d61, 0x8d61, 0x8d62, 0x8d62,
+ 0x8d63, 0x8d64, 0x8d65, 0x8d65, 0x8d66, 0x8d67, 0x8d68, 0x8d69,
+ 0x8d6a, 0x8d6b, 0x8d6c, 0x8d6e, 0x8d6f, 0x8d70, 0x8d71, 0x8d73,
+ 0x8d74, 0x8d75, 0x8d77, 0x8d78, 0x8d7a, 0x8d7b, 0x8d7d, 0x8d7f,
+ 0x8d80, 0x8d80, 0x8d80, 0x8d80, 0x8d81, 0x8d81, 0x8d82, 0x8d82,
+ 0x8d83, 0x8d84, 0x8d85, 0x8d85, 0x8d86, 0x8d87, 0x8d88, 0x8d89,
+ 0x8d8a, 0x8d8b, 0x8d8c, 0x8d8e, 0x8d8f, 0x8d90, 0x8d91, 0x8d93,
+ 0x8d94, 0x8d95, 0x8d97, 0x8d98, 0x8d9a, 0x8d9b, 0x8d9d, 0x8d9f,
+ 0x8dc0, 0x8dc0, 0x8dc0, 0x8dc0, 0x8dc1, 0x8dc1, 0x8dc2, 0x8dc2,
+ 0x8dc3, 0x8dc4, 0x8dc5, 0x8dc5, 0x8dc6, 0x8dc7, 0x8dc8, 0x8dc9,
+ 0x8dca, 0x8dcb, 0x8dcc, 0x8dce, 0x8dcf, 0x8dd0, 0x8dd1, 0x8dd3,
+ 0x8dd4, 0x8dd5, 0x8dd7, 0x8dd8, 0x8dda, 0x8ddb, 0x8ddd, 0x8ddf,
+ 0x8de0, 0x8de0, 0x8de0, 0x8de0, 0x8de1, 0x8de1, 0x8de2, 0x8de2,
+ 0x8de3, 0x8de4, 0x8de5, 0x8de5, 0x8de6, 0x8de7, 0x8de8, 0x8de9,
+ 0x8dea, 0x8deb, 0x8dec, 0x8dee, 0x8def, 0x8df0, 0x8df1, 0x8df3,
+ 0x8df4, 0x8df5, 0x8df7, 0x8df8, 0x8dfa, 0x8dfb, 0x8dfd, 0x8dff,
+ 0x8e20, 0x8e20, 0x8e20, 0x8e20, 0x8e21, 0x8e21, 0x8e22, 0x8e22,
+ 0x8e23, 0x8e24, 0x8e25, 0x8e25, 0x8e26, 0x8e27, 0x8e28, 0x8e29,
+ 0x8e2a, 0x8e2b, 0x8e2c, 0x8e2e, 0x8e2f, 0x8e30, 0x8e31, 0x8e33,
+ 0x8e34, 0x8e35, 0x8e37, 0x8e38, 0x8e3a, 0x8e3b, 0x8e3d, 0x8e3f,
+ 0x8e40, 0x8e40, 0x8e40, 0x8e40, 0x8e41, 0x8e41, 0x8e42, 0x8e42,
+ 0x8e43, 0x8e44, 0x8e45, 0x8e45, 0x8e46, 0x8e47, 0x8e48, 0x8e49,
+ 0x8e4a, 0x8e4b, 0x8e4c, 0x8e4e, 0x8e4f, 0x8e50, 0x8e51, 0x8e53,
+ 0x8e54, 0x8e55, 0x8e57, 0x8e58, 0x8e5a, 0x8e5b, 0x8e5d, 0x8e5f,
+ 0x8e80, 0x8e80, 0x8e80, 0x8e80, 0x8e81, 0x8e81, 0x8e82, 0x8e82,
+ 0x8e83, 0x8e84, 0x8e85, 0x8e85, 0x8e86, 0x8e87, 0x8e88, 0x8e89,
+ 0x8e8a, 0x8e8b, 0x8e8c, 0x8e8e, 0x8e8f, 0x8e90, 0x8e91, 0x8e93,
+ 0x8e94, 0x8e95, 0x8e97, 0x8e98, 0x8e9a, 0x8e9b, 0x8e9d, 0x8e9f,
+ 0x8ea0, 0x8ea0, 0x8ea0, 0x8ea0, 0x8ea1, 0x8ea1, 0x8ea2, 0x8ea2,
+ 0x8ea3, 0x8ea4, 0x8ea5, 0x8ea5, 0x8ea6, 0x8ea7, 0x8ea8, 0x8ea9,
+ 0x8eaa, 0x8eab, 0x8eac, 0x8eae, 0x8eaf, 0x8eb0, 0x8eb1, 0x8eb3,
+ 0x8eb4, 0x8eb5, 0x8eb7, 0x8eb8, 0x8eba, 0x8ebb, 0x8ebd, 0x8ebf,
+ 0x8ee0, 0x8ee0, 0x8ee0, 0x8ee0, 0x8ee1, 0x8ee1, 0x8ee2, 0x8ee2,
+ 0x8ee3, 0x8ee4, 0x8ee5, 0x8ee5, 0x8ee6, 0x8ee7, 0x8ee8, 0x8ee9,
+ 0x8eea, 0x8eeb, 0x8eec, 0x8eee, 0x8eef, 0x8ef0, 0x8ef1, 0x8ef3,
+ 0x8ef4, 0x8ef5, 0x8ef7, 0x8ef8, 0x8efa, 0x8efb, 0x8efd, 0x8eff,
+ 0x8f00, 0x8f00, 0x8f00, 0x8f00, 0x8f01, 0x8f01, 0x8f02, 0x8f02,
+ 0x8f03, 0x8f04, 0x8f05, 0x8f05, 0x8f06, 0x8f07, 0x8f08, 0x8f09,
+ 0x8f0a, 0x8f0b, 0x8f0c, 0x8f0e, 0x8f0f, 0x8f10, 0x8f11, 0x8f13,
+ 0x8f14, 0x8f15, 0x8f17, 0x8f18, 0x8f1a, 0x8f1b, 0x8f1d, 0x8f1f,
+ 0x8f40, 0x8f40, 0x8f40, 0x8f40, 0x8f41, 0x8f41, 0x8f42, 0x8f42,
+ 0x8f43, 0x8f44, 0x8f45, 0x8f45, 0x8f46, 0x8f47, 0x8f48, 0x8f49,
+ 0x8f4a, 0x8f4b, 0x8f4c, 0x8f4e, 0x8f4f, 0x8f50, 0x8f51, 0x8f53,
+ 0x8f54, 0x8f55, 0x8f57, 0x8f58, 0x8f5a, 0x8f5b, 0x8f5d, 0x8f5f,
+ 0x8f60, 0x8f60, 0x8f60, 0x8f60, 0x8f61, 0x8f61, 0x8f62, 0x8f62,
+ 0x8f63, 0x8f64, 0x8f65, 0x8f65, 0x8f66, 0x8f67, 0x8f68, 0x8f69,
+ 0x8f6a, 0x8f6b, 0x8f6c, 0x8f6e, 0x8f6f, 0x8f70, 0x8f71, 0x8f73,
+ 0x8f74, 0x8f75, 0x8f77, 0x8f78, 0x8f7a, 0x8f7b, 0x8f7d, 0x8f7f,
+ 0x8fa0, 0x8fa0, 0x8fa0, 0x8fa0, 0x8fa1, 0x8fa1, 0x8fa2, 0x8fa2,
+ 0x8fa3, 0x8fa4, 0x8fa5, 0x8fa5, 0x8fa6, 0x8fa7, 0x8fa8, 0x8fa9,
+ 0x8faa, 0x8fab, 0x8fac, 0x8fae, 0x8faf, 0x8fb0, 0x8fb1, 0x8fb3,
+ 0x8fb4, 0x8fb5, 0x8fb7, 0x8fb8, 0x8fba, 0x8fbb, 0x8fbd, 0x8fbf,
+ 0x8fe0, 0x8fe0, 0x8fe0, 0x8fe0, 0x8fe1, 0x8fe1, 0x8fe2, 0x8fe2,
+ 0x8fe3, 0x8fe4, 0x8fe5, 0x8fe5, 0x8fe6, 0x8fe7, 0x8fe8, 0x8fe9,
+ 0x8fea, 0x8feb, 0x8fec, 0x8fee, 0x8fef, 0x8ff0, 0x8ff1, 0x8ff3,
+ 0x8ff4, 0x8ff5, 0x8ff7, 0x8ff8, 0x8ffa, 0x8ffb, 0x8ffd, 0x8fff,
+ 0x9800, 0x9800, 0x9800, 0x9800, 0x9801, 0x9801, 0x9802, 0x9802,
+ 0x9803, 0x9804, 0x9805, 0x9805, 0x9806, 0x9807, 0x9808, 0x9809,
+ 0x980a, 0x980b, 0x980c, 0x980e, 0x980f, 0x9810, 0x9811, 0x9813,
+ 0x9814, 0x9815, 0x9817, 0x9818, 0x981a, 0x981b, 0x981d, 0x981f,
+ 0x9800, 0x9800, 0x9800, 0x9800, 0x9801, 0x9801, 0x9802, 0x9802,
+ 0x9803, 0x9804, 0x9805, 0x9805, 0x9806, 0x9807, 0x9808, 0x9809,
+ 0x980a, 0x980b, 0x980c, 0x980e, 0x980f, 0x9810, 0x9811, 0x9813,
+ 0x9814, 0x9815, 0x9817, 0x9818, 0x981a, 0x981b, 0x981d, 0x981f,
+ 0x9800, 0x9800, 0x9800, 0x9800, 0x9801, 0x9801, 0x9802, 0x9802,
+ 0x9803, 0x9804, 0x9805, 0x9805, 0x9806, 0x9807, 0x9808, 0x9809,
+ 0x980a, 0x980b, 0x980c, 0x980e, 0x980f, 0x9810, 0x9811, 0x9813,
+ 0x9814, 0x9815, 0x9817, 0x9818, 0x981a, 0x981b, 0x981d, 0x981f,
+ 0x9800, 0x9800, 0x9800, 0x9800, 0x9801, 0x9801, 0x9802, 0x9802,
+ 0x9803, 0x9804, 0x9805, 0x9805, 0x9806, 0x9807, 0x9808, 0x9809,
+ 0x980a, 0x980b, 0x980c, 0x980e, 0x980f, 0x9810, 0x9811, 0x9813,
+ 0x9814, 0x9815, 0x9817, 0x9818, 0x981a, 0x981b, 0x981d, 0x981f,
+ 0x9800, 0x9800, 0x9800, 0x9800, 0x9801, 0x9801, 0x9802, 0x9802,
+ 0x9803, 0x9804, 0x9805, 0x9805, 0x9806, 0x9807, 0x9808, 0x9809,
+ 0x980a, 0x980b, 0x980c, 0x980e, 0x980f, 0x9810, 0x9811, 0x9813,
+ 0x9814, 0x9815, 0x9817, 0x9818, 0x981a, 0x981b, 0x981d, 0x981f,
+ 0x9820, 0x9820, 0x9820, 0x9820, 0x9821, 0x9821, 0x9822, 0x9822,
+ 0x9823, 0x9824, 0x9825, 0x9825, 0x9826, 0x9827, 0x9828, 0x9829,
+ 0x982a, 0x982b, 0x982c, 0x982e, 0x982f, 0x9830, 0x9831, 0x9833,
+ 0x9834, 0x9835, 0x9837, 0x9838, 0x983a, 0x983b, 0x983d, 0x983f,
+ 0x9820, 0x9820, 0x9820, 0x9820, 0x9821, 0x9821, 0x9822, 0x9822,
+ 0x9823, 0x9824, 0x9825, 0x9825, 0x9826, 0x9827, 0x9828, 0x9829,
+ 0x982a, 0x982b, 0x982c, 0x982e, 0x982f, 0x9830, 0x9831, 0x9833,
+ 0x9834, 0x9835, 0x9837, 0x9838, 0x983a, 0x983b, 0x983d, 0x983f,
+ 0x9820, 0x9820, 0x9820, 0x9820, 0x9821, 0x9821, 0x9822, 0x9822,
+ 0x9823, 0x9824, 0x9825, 0x9825, 0x9826, 0x9827, 0x9828, 0x9829,
+ 0x982a, 0x982b, 0x982c, 0x982e, 0x982f, 0x9830, 0x9831, 0x9833,
+ 0x9834, 0x9835, 0x9837, 0x9838, 0x983a, 0x983b, 0x983d, 0x983f,
+ 0x9840, 0x9840, 0x9840, 0x9840, 0x9841, 0x9841, 0x9842, 0x9842,
+ 0x9843, 0x9844, 0x9845, 0x9845, 0x9846, 0x9847, 0x9848, 0x9849,
+ 0x984a, 0x984b, 0x984c, 0x984e, 0x984f, 0x9850, 0x9851, 0x9853,
+ 0x9854, 0x9855, 0x9857, 0x9858, 0x985a, 0x985b, 0x985d, 0x985f,
+ 0x9840, 0x9840, 0x9840, 0x9840, 0x9841, 0x9841, 0x9842, 0x9842,
+ 0x9843, 0x9844, 0x9845, 0x9845, 0x9846, 0x9847, 0x9848, 0x9849,
+ 0x984a, 0x984b, 0x984c, 0x984e, 0x984f, 0x9850, 0x9851, 0x9853,
+ 0x9854, 0x9855, 0x9857, 0x9858, 0x985a, 0x985b, 0x985d, 0x985f,
+ 0x9860, 0x9860, 0x9860, 0x9860, 0x9861, 0x9861, 0x9862, 0x9862,
+ 0x9863, 0x9864, 0x9865, 0x9865, 0x9866, 0x9867, 0x9868, 0x9869,
+ 0x986a, 0x986b, 0x986c, 0x986e, 0x986f, 0x9870, 0x9871, 0x9873,
+ 0x9874, 0x9875, 0x9877, 0x9878, 0x987a, 0x987b, 0x987d, 0x987f,
+ 0x9860, 0x9860, 0x9860, 0x9860, 0x9861, 0x9861, 0x9862, 0x9862,
+ 0x9863, 0x9864, 0x9865, 0x9865, 0x9866, 0x9867, 0x9868, 0x9869,
+ 0x986a, 0x986b, 0x986c, 0x986e, 0x986f, 0x9870, 0x9871, 0x9873,
+ 0x9874, 0x9875, 0x9877, 0x9878, 0x987a, 0x987b, 0x987d, 0x987f,
+ 0x9880, 0x9880, 0x9880, 0x9880, 0x9881, 0x9881, 0x9882, 0x9882,
+ 0x9883, 0x9884, 0x9885, 0x9885, 0x9886, 0x9887, 0x9888, 0x9889,
+ 0x988a, 0x988b, 0x988c, 0x988e, 0x988f, 0x9890, 0x9891, 0x9893,
+ 0x9894, 0x9895, 0x9897, 0x9898, 0x989a, 0x989b, 0x989d, 0x989f,
+ 0x98a0, 0x98a0, 0x98a0, 0x98a0, 0x98a1, 0x98a1, 0x98a2, 0x98a2,
+ 0x98a3, 0x98a4, 0x98a5, 0x98a5, 0x98a6, 0x98a7, 0x98a8, 0x98a9,
+ 0x98aa, 0x98ab, 0x98ac, 0x98ae, 0x98af, 0x98b0, 0x98b1, 0x98b3,
+ 0x98b4, 0x98b5, 0x98b7, 0x98b8, 0x98ba, 0x98bb, 0x98bd, 0x98bf,
+ 0x98a0, 0x98a0, 0x98a0, 0x98a0, 0x98a1, 0x98a1, 0x98a2, 0x98a2,
+ 0x98a3, 0x98a4, 0x98a5, 0x98a5, 0x98a6, 0x98a7, 0x98a8, 0x98a9,
+ 0x98aa, 0x98ab, 0x98ac, 0x98ae, 0x98af, 0x98b0, 0x98b1, 0x98b3,
+ 0x98b4, 0x98b5, 0x98b7, 0x98b8, 0x98ba, 0x98bb, 0x98bd, 0x98bf,
+ 0x98c0, 0x98c0, 0x98c0, 0x98c0, 0x98c1, 0x98c1, 0x98c2, 0x98c2,
+ 0x98c3, 0x98c4, 0x98c5, 0x98c5, 0x98c6, 0x98c7, 0x98c8, 0x98c9,
+ 0x98ca, 0x98cb, 0x98cc, 0x98ce, 0x98cf, 0x98d0, 0x98d1, 0x98d3,
+ 0x98d4, 0x98d5, 0x98d7, 0x98d8, 0x98da, 0x98db, 0x98dd, 0x98df,
+ 0x98e0, 0x98e0, 0x98e0, 0x98e0, 0x98e1, 0x98e1, 0x98e2, 0x98e2,
+ 0x98e3, 0x98e4, 0x98e5, 0x98e5, 0x98e6, 0x98e7, 0x98e8, 0x98e9,
+ 0x98ea, 0x98eb, 0x98ec, 0x98ee, 0x98ef, 0x98f0, 0x98f1, 0x98f3,
+ 0x98f4, 0x98f5, 0x98f7, 0x98f8, 0x98fa, 0x98fb, 0x98fd, 0x98ff,
+ 0x98e0, 0x98e0, 0x98e0, 0x98e0, 0x98e1, 0x98e1, 0x98e2, 0x98e2,
+ 0x98e3, 0x98e4, 0x98e5, 0x98e5, 0x98e6, 0x98e7, 0x98e8, 0x98e9,
+ 0x98ea, 0x98eb, 0x98ec, 0x98ee, 0x98ef, 0x98f0, 0x98f1, 0x98f3,
+ 0x98f4, 0x98f5, 0x98f7, 0x98f8, 0x98fa, 0x98fb, 0x98fd, 0x98ff,
+ 0x9900, 0x9900, 0x9900, 0x9900, 0x9901, 0x9901, 0x9902, 0x9902,
+ 0x9903, 0x9904, 0x9905, 0x9905, 0x9906, 0x9907, 0x9908, 0x9909,
+ 0x990a, 0x990b, 0x990c, 0x990e, 0x990f, 0x9910, 0x9911, 0x9913,
+ 0x9914, 0x9915, 0x9917, 0x9918, 0x991a, 0x991b, 0x991d, 0x991f,
+ 0x9920, 0x9920, 0x9920, 0x9920, 0x9921, 0x9921, 0x9922, 0x9922,
+ 0x9923, 0x9924, 0x9925, 0x9925, 0x9926, 0x9927, 0x9928, 0x9929,
+ 0x992a, 0x992b, 0x992c, 0x992e, 0x992f, 0x9930, 0x9931, 0x9933,
+ 0x9934, 0x9935, 0x9937, 0x9938, 0x993a, 0x993b, 0x993d, 0x993f,
+ 0x9940, 0x9940, 0x9940, 0x9940, 0x9941, 0x9941, 0x9942, 0x9942,
+ 0x9943, 0x9944, 0x9945, 0x9945, 0x9946, 0x9947, 0x9948, 0x9949,
+ 0x994a, 0x994b, 0x994c, 0x994e, 0x994f, 0x9950, 0x9951, 0x9953,
+ 0x9954, 0x9955, 0x9957, 0x9958, 0x995a, 0x995b, 0x995d, 0x995f,
+ 0x9940, 0x9940, 0x9940, 0x9940, 0x9941, 0x9941, 0x9942, 0x9942,
+ 0x9943, 0x9944, 0x9945, 0x9945, 0x9946, 0x9947, 0x9948, 0x9949,
+ 0x994a, 0x994b, 0x994c, 0x994e, 0x994f, 0x9950, 0x9951, 0x9953,
+ 0x9954, 0x9955, 0x9957, 0x9958, 0x995a, 0x995b, 0x995d, 0x995f,
+ 0x9960, 0x9960, 0x9960, 0x9960, 0x9961, 0x9961, 0x9962, 0x9962,
+ 0x9963, 0x9964, 0x9965, 0x9965, 0x9966, 0x9967, 0x9968, 0x9969,
+ 0x996a, 0x996b, 0x996c, 0x996e, 0x996f, 0x9970, 0x9971, 0x9973,
+ 0x9974, 0x9975, 0x9977, 0x9978, 0x997a, 0x997b, 0x997d, 0x997f,
+ 0x9980, 0x9980, 0x9980, 0x9980, 0x9981, 0x9981, 0x9982, 0x9982,
+ 0x9983, 0x9984, 0x9985, 0x9985, 0x9986, 0x9987, 0x9988, 0x9989,
+ 0x998a, 0x998b, 0x998c, 0x998e, 0x998f, 0x9990, 0x9991, 0x9993,
+ 0x9994, 0x9995, 0x9997, 0x9998, 0x999a, 0x999b, 0x999d, 0x999f,
+ 0x99a0, 0x99a0, 0x99a0, 0x99a0, 0x99a1, 0x99a1, 0x99a2, 0x99a2,
+ 0x99a3, 0x99a4, 0x99a5, 0x99a5, 0x99a6, 0x99a7, 0x99a8, 0x99a9,
+ 0x99aa, 0x99ab, 0x99ac, 0x99ae, 0x99af, 0x99b0, 0x99b1, 0x99b3,
+ 0x99b4, 0x99b5, 0x99b7, 0x99b8, 0x99ba, 0x99bb, 0x99bd, 0x99bf,
+ 0x99c0, 0x99c0, 0x99c0, 0x99c0, 0x99c1, 0x99c1, 0x99c2, 0x99c2,
+ 0x99c3, 0x99c4, 0x99c5, 0x99c5, 0x99c6, 0x99c7, 0x99c8, 0x99c9,
+ 0x99ca, 0x99cb, 0x99cc, 0x99ce, 0x99cf, 0x99d0, 0x99d1, 0x99d3,
+ 0x99d4, 0x99d5, 0x99d7, 0x99d8, 0x99da, 0x99db, 0x99dd, 0x99df,
+ 0x99e0, 0x99e0, 0x99e0, 0x99e0, 0x99e1, 0x99e1, 0x99e2, 0x99e2,
+ 0x99e3, 0x99e4, 0x99e5, 0x99e5, 0x99e6, 0x99e7, 0x99e8, 0x99e9,
+ 0x99ea, 0x99eb, 0x99ec, 0x99ee, 0x99ef, 0x99f0, 0x99f1, 0x99f3,
+ 0x99f4, 0x99f5, 0x99f7, 0x99f8, 0x99fa, 0x99fb, 0x99fd, 0x99ff,
+ 0x9a00, 0x9a00, 0x9a00, 0x9a00, 0x9a01, 0x9a01, 0x9a02, 0x9a02,
+ 0x9a03, 0x9a04, 0x9a05, 0x9a05, 0x9a06, 0x9a07, 0x9a08, 0x9a09,
+ 0x9a0a, 0x9a0b, 0x9a0c, 0x9a0e, 0x9a0f, 0x9a10, 0x9a11, 0x9a13,
+ 0x9a14, 0x9a15, 0x9a17, 0x9a18, 0x9a1a, 0x9a1b, 0x9a1d, 0x9a1f,
+ 0x9a20, 0x9a20, 0x9a20, 0x9a20, 0x9a21, 0x9a21, 0x9a22, 0x9a22,
+ 0x9a23, 0x9a24, 0x9a25, 0x9a25, 0x9a26, 0x9a27, 0x9a28, 0x9a29,
+ 0x9a2a, 0x9a2b, 0x9a2c, 0x9a2e, 0x9a2f, 0x9a30, 0x9a31, 0x9a33,
+ 0x9a34, 0x9a35, 0x9a37, 0x9a38, 0x9a3a, 0x9a3b, 0x9a3d, 0x9a3f,
+ 0x9a40, 0x9a40, 0x9a40, 0x9a40, 0x9a41, 0x9a41, 0x9a42, 0x9a42,
+ 0x9a43, 0x9a44, 0x9a45, 0x9a45, 0x9a46, 0x9a47, 0x9a48, 0x9a49,
+ 0x9a4a, 0x9a4b, 0x9a4c, 0x9a4e, 0x9a4f, 0x9a50, 0x9a51, 0x9a53,
+ 0x9a54, 0x9a55, 0x9a57, 0x9a58, 0x9a5a, 0x9a5b, 0x9a5d, 0x9a5f,
+ 0x9a60, 0x9a60, 0x9a60, 0x9a60, 0x9a61, 0x9a61, 0x9a62, 0x9a62,
+ 0x9a63, 0x9a64, 0x9a65, 0x9a65, 0x9a66, 0x9a67, 0x9a68, 0x9a69,
+ 0x9a6a, 0x9a6b, 0x9a6c, 0x9a6e, 0x9a6f, 0x9a70, 0x9a71, 0x9a73,
+ 0x9a74, 0x9a75, 0x9a77, 0x9a78, 0x9a7a, 0x9a7b, 0x9a7d, 0x9a7f,
+ 0x9a80, 0x9a80, 0x9a80, 0x9a80, 0x9a81, 0x9a81, 0x9a82, 0x9a82,
+ 0x9a83, 0x9a84, 0x9a85, 0x9a85, 0x9a86, 0x9a87, 0x9a88, 0x9a89,
+ 0x9a8a, 0x9a8b, 0x9a8c, 0x9a8e, 0x9a8f, 0x9a90, 0x9a91, 0x9a93,
+ 0x9a94, 0x9a95, 0x9a97, 0x9a98, 0x9a9a, 0x9a9b, 0x9a9d, 0x9a9f,
+ 0x9aa0, 0x9aa0, 0x9aa0, 0x9aa0, 0x9aa1, 0x9aa1, 0x9aa2, 0x9aa2,
+ 0x9aa3, 0x9aa4, 0x9aa5, 0x9aa5, 0x9aa6, 0x9aa7, 0x9aa8, 0x9aa9,
+ 0x9aaa, 0x9aab, 0x9aac, 0x9aae, 0x9aaf, 0x9ab0, 0x9ab1, 0x9ab3,
+ 0x9ab4, 0x9ab5, 0x9ab7, 0x9ab8, 0x9aba, 0x9abb, 0x9abd, 0x9abf,
+ 0x9ac0, 0x9ac0, 0x9ac0, 0x9ac0, 0x9ac1, 0x9ac1, 0x9ac2, 0x9ac2,
+ 0x9ac3, 0x9ac4, 0x9ac5, 0x9ac5, 0x9ac6, 0x9ac7, 0x9ac8, 0x9ac9,
+ 0x9aca, 0x9acb, 0x9acc, 0x9ace, 0x9acf, 0x9ad0, 0x9ad1, 0x9ad3,
+ 0x9ad4, 0x9ad5, 0x9ad7, 0x9ad8, 0x9ada, 0x9adb, 0x9add, 0x9adf,
+ 0x9ae0, 0x9ae0, 0x9ae0, 0x9ae0, 0x9ae1, 0x9ae1, 0x9ae2, 0x9ae2,
+ 0x9ae3, 0x9ae4, 0x9ae5, 0x9ae5, 0x9ae6, 0x9ae7, 0x9ae8, 0x9ae9,
+ 0x9aea, 0x9aeb, 0x9aec, 0x9aee, 0x9aef, 0x9af0, 0x9af1, 0x9af3,
+ 0x9af4, 0x9af5, 0x9af7, 0x9af8, 0x9afa, 0x9afb, 0x9afd, 0x9aff,
+ 0x9b00, 0x9b00, 0x9b00, 0x9b00, 0x9b01, 0x9b01, 0x9b02, 0x9b02,
+ 0x9b03, 0x9b04, 0x9b05, 0x9b05, 0x9b06, 0x9b07, 0x9b08, 0x9b09,
+ 0x9b0a, 0x9b0b, 0x9b0c, 0x9b0e, 0x9b0f, 0x9b10, 0x9b11, 0x9b13,
+ 0x9b14, 0x9b15, 0x9b17, 0x9b18, 0x9b1a, 0x9b1b, 0x9b1d, 0x9b1f,
+ 0x9b20, 0x9b20, 0x9b20, 0x9b20, 0x9b21, 0x9b21, 0x9b22, 0x9b22,
+ 0x9b23, 0x9b24, 0x9b25, 0x9b25, 0x9b26, 0x9b27, 0x9b28, 0x9b29,
+ 0x9b2a, 0x9b2b, 0x9b2c, 0x9b2e, 0x9b2f, 0x9b30, 0x9b31, 0x9b33,
+ 0x9b34, 0x9b35, 0x9b37, 0x9b38, 0x9b3a, 0x9b3b, 0x9b3d, 0x9b3f,
+ 0x9b40, 0x9b40, 0x9b40, 0x9b40, 0x9b41, 0x9b41, 0x9b42, 0x9b42,
+ 0x9b43, 0x9b44, 0x9b45, 0x9b45, 0x9b46, 0x9b47, 0x9b48, 0x9b49,
+ 0x9b4a, 0x9b4b, 0x9b4c, 0x9b4e, 0x9b4f, 0x9b50, 0x9b51, 0x9b53,
+ 0x9b54, 0x9b55, 0x9b57, 0x9b58, 0x9b5a, 0x9b5b, 0x9b5d, 0x9b5f,
+ 0x9b80, 0x9b80, 0x9b80, 0x9b80, 0x9b81, 0x9b81, 0x9b82, 0x9b82,
+ 0x9b83, 0x9b84, 0x9b85, 0x9b85, 0x9b86, 0x9b87, 0x9b88, 0x9b89,
+ 0x9b8a, 0x9b8b, 0x9b8c, 0x9b8e, 0x9b8f, 0x9b90, 0x9b91, 0x9b93,
+ 0x9b94, 0x9b95, 0x9b97, 0x9b98, 0x9b9a, 0x9b9b, 0x9b9d, 0x9b9f,
+ 0x9ba0, 0x9ba0, 0x9ba0, 0x9ba0, 0x9ba1, 0x9ba1, 0x9ba2, 0x9ba2,
+ 0x9ba3, 0x9ba4, 0x9ba5, 0x9ba5, 0x9ba6, 0x9ba7, 0x9ba8, 0x9ba9,
+ 0x9baa, 0x9bab, 0x9bac, 0x9bae, 0x9baf, 0x9bb0, 0x9bb1, 0x9bb3,
+ 0x9bb4, 0x9bb5, 0x9bb7, 0x9bb8, 0x9bba, 0x9bbb, 0x9bbd, 0x9bbf,
+ 0x9bc0, 0x9bc0, 0x9bc0, 0x9bc0, 0x9bc1, 0x9bc1, 0x9bc2, 0x9bc2,
+ 0x9bc3, 0x9bc4, 0x9bc5, 0x9bc5, 0x9bc6, 0x9bc7, 0x9bc8, 0x9bc9,
+ 0x9bca, 0x9bcb, 0x9bcc, 0x9bce, 0x9bcf, 0x9bd0, 0x9bd1, 0x9bd3,
+ 0x9bd4, 0x9bd5, 0x9bd7, 0x9bd8, 0x9bda, 0x9bdb, 0x9bdd, 0x9bdf,
+ 0x9be0, 0x9be0, 0x9be0, 0x9be0, 0x9be1, 0x9be1, 0x9be2, 0x9be2,
+ 0x9be3, 0x9be4, 0x9be5, 0x9be5, 0x9be6, 0x9be7, 0x9be8, 0x9be9,
+ 0x9bea, 0x9beb, 0x9bec, 0x9bee, 0x9bef, 0x9bf0, 0x9bf1, 0x9bf3,
+ 0x9bf4, 0x9bf5, 0x9bf7, 0x9bf8, 0x9bfa, 0x9bfb, 0x9bfd, 0x9bff,
+ 0x9c00, 0x9c00, 0x9c00, 0x9c00, 0x9c01, 0x9c01, 0x9c02, 0x9c02,
+ 0x9c03, 0x9c04, 0x9c05, 0x9c05, 0x9c06, 0x9c07, 0x9c08, 0x9c09,
+ 0x9c0a, 0x9c0b, 0x9c0c, 0x9c0e, 0x9c0f, 0x9c10, 0x9c11, 0x9c13,
+ 0x9c14, 0x9c15, 0x9c17, 0x9c18, 0x9c1a, 0x9c1b, 0x9c1d, 0x9c1f,
+ 0x9c40, 0x9c40, 0x9c40, 0x9c40, 0x9c41, 0x9c41, 0x9c42, 0x9c42,
+ 0x9c43, 0x9c44, 0x9c45, 0x9c45, 0x9c46, 0x9c47, 0x9c48, 0x9c49,
+ 0x9c4a, 0x9c4b, 0x9c4c, 0x9c4e, 0x9c4f, 0x9c50, 0x9c51, 0x9c53,
+ 0x9c54, 0x9c55, 0x9c57, 0x9c58, 0x9c5a, 0x9c5b, 0x9c5d, 0x9c5f,
+ 0x9c60, 0x9c60, 0x9c60, 0x9c60, 0x9c61, 0x9c61, 0x9c62, 0x9c62,
+ 0x9c63, 0x9c64, 0x9c65, 0x9c65, 0x9c66, 0x9c67, 0x9c68, 0x9c69,
+ 0x9c6a, 0x9c6b, 0x9c6c, 0x9c6e, 0x9c6f, 0x9c70, 0x9c71, 0x9c73,
+ 0x9c74, 0x9c75, 0x9c77, 0x9c78, 0x9c7a, 0x9c7b, 0x9c7d, 0x9c7f,
+ 0x9c80, 0x9c80, 0x9c80, 0x9c80, 0x9c81, 0x9c81, 0x9c82, 0x9c82,
+ 0x9c83, 0x9c84, 0x9c85, 0x9c85, 0x9c86, 0x9c87, 0x9c88, 0x9c89,
+ 0x9c8a, 0x9c8b, 0x9c8c, 0x9c8e, 0x9c8f, 0x9c90, 0x9c91, 0x9c93,
+ 0x9c94, 0x9c95, 0x9c97, 0x9c98, 0x9c9a, 0x9c9b, 0x9c9d, 0x9c9f,
+ 0x9cc0, 0x9cc0, 0x9cc0, 0x9cc0, 0x9cc1, 0x9cc1, 0x9cc2, 0x9cc2,
+ 0x9cc3, 0x9cc4, 0x9cc5, 0x9cc5, 0x9cc6, 0x9cc7, 0x9cc8, 0x9cc9,
+ 0x9cca, 0x9ccb, 0x9ccc, 0x9cce, 0x9ccf, 0x9cd0, 0x9cd1, 0x9cd3,
+ 0x9cd4, 0x9cd5, 0x9cd7, 0x9cd8, 0x9cda, 0x9cdb, 0x9cdd, 0x9cdf,
+ 0x9ce0, 0x9ce0, 0x9ce0, 0x9ce0, 0x9ce1, 0x9ce1, 0x9ce2, 0x9ce2,
+ 0x9ce3, 0x9ce4, 0x9ce5, 0x9ce5, 0x9ce6, 0x9ce7, 0x9ce8, 0x9ce9,
+ 0x9cea, 0x9ceb, 0x9cec, 0x9cee, 0x9cef, 0x9cf0, 0x9cf1, 0x9cf3,
+ 0x9cf4, 0x9cf5, 0x9cf7, 0x9cf8, 0x9cfa, 0x9cfb, 0x9cfd, 0x9cff,
+ 0x9d00, 0x9d00, 0x9d00, 0x9d00, 0x9d01, 0x9d01, 0x9d02, 0x9d02,
+ 0x9d03, 0x9d04, 0x9d05, 0x9d05, 0x9d06, 0x9d07, 0x9d08, 0x9d09,
+ 0x9d0a, 0x9d0b, 0x9d0c, 0x9d0e, 0x9d0f, 0x9d10, 0x9d11, 0x9d13,
+ 0x9d14, 0x9d15, 0x9d17, 0x9d18, 0x9d1a, 0x9d1b, 0x9d1d, 0x9d1f,
+ 0x9d40, 0x9d40, 0x9d40, 0x9d40, 0x9d41, 0x9d41, 0x9d42, 0x9d42,
+ 0x9d43, 0x9d44, 0x9d45, 0x9d45, 0x9d46, 0x9d47, 0x9d48, 0x9d49,
+ 0x9d4a, 0x9d4b, 0x9d4c, 0x9d4e, 0x9d4f, 0x9d50, 0x9d51, 0x9d53,
+ 0x9d54, 0x9d55, 0x9d57, 0x9d58, 0x9d5a, 0x9d5b, 0x9d5d, 0x9d5f,
+ 0x9d60, 0x9d60, 0x9d60, 0x9d60, 0x9d61, 0x9d61, 0x9d62, 0x9d62,
+ 0x9d63, 0x9d64, 0x9d65, 0x9d65, 0x9d66, 0x9d67, 0x9d68, 0x9d69,
+ 0x9d6a, 0x9d6b, 0x9d6c, 0x9d6e, 0x9d6f, 0x9d70, 0x9d71, 0x9d73,
+ 0x9d74, 0x9d75, 0x9d77, 0x9d78, 0x9d7a, 0x9d7b, 0x9d7d, 0x9d7f,
+ 0x9d80, 0x9d80, 0x9d80, 0x9d80, 0x9d81, 0x9d81, 0x9d82, 0x9d82,
+ 0x9d83, 0x9d84, 0x9d85, 0x9d85, 0x9d86, 0x9d87, 0x9d88, 0x9d89,
+ 0x9d8a, 0x9d8b, 0x9d8c, 0x9d8e, 0x9d8f, 0x9d90, 0x9d91, 0x9d93,
+ 0x9d94, 0x9d95, 0x9d97, 0x9d98, 0x9d9a, 0x9d9b, 0x9d9d, 0x9d9f,
+ 0x9dc0, 0x9dc0, 0x9dc0, 0x9dc0, 0x9dc1, 0x9dc1, 0x9dc2, 0x9dc2,
+ 0x9dc3, 0x9dc4, 0x9dc5, 0x9dc5, 0x9dc6, 0x9dc7, 0x9dc8, 0x9dc9,
+ 0x9dca, 0x9dcb, 0x9dcc, 0x9dce, 0x9dcf, 0x9dd0, 0x9dd1, 0x9dd3,
+ 0x9dd4, 0x9dd5, 0x9dd7, 0x9dd8, 0x9dda, 0x9ddb, 0x9ddd, 0x9ddf,
+ 0x9de0, 0x9de0, 0x9de0, 0x9de0, 0x9de1, 0x9de1, 0x9de2, 0x9de2,
+ 0x9de3, 0x9de4, 0x9de5, 0x9de5, 0x9de6, 0x9de7, 0x9de8, 0x9de9,
+ 0x9dea, 0x9deb, 0x9dec, 0x9dee, 0x9def, 0x9df0, 0x9df1, 0x9df3,
+ 0x9df4, 0x9df5, 0x9df7, 0x9df8, 0x9dfa, 0x9dfb, 0x9dfd, 0x9dff,
+ 0x9e20, 0x9e20, 0x9e20, 0x9e20, 0x9e21, 0x9e21, 0x9e22, 0x9e22,
+ 0x9e23, 0x9e24, 0x9e25, 0x9e25, 0x9e26, 0x9e27, 0x9e28, 0x9e29,
+ 0x9e2a, 0x9e2b, 0x9e2c, 0x9e2e, 0x9e2f, 0x9e30, 0x9e31, 0x9e33,
+ 0x9e34, 0x9e35, 0x9e37, 0x9e38, 0x9e3a, 0x9e3b, 0x9e3d, 0x9e3f,
+ 0x9e40, 0x9e40, 0x9e40, 0x9e40, 0x9e41, 0x9e41, 0x9e42, 0x9e42,
+ 0x9e43, 0x9e44, 0x9e45, 0x9e45, 0x9e46, 0x9e47, 0x9e48, 0x9e49,
+ 0x9e4a, 0x9e4b, 0x9e4c, 0x9e4e, 0x9e4f, 0x9e50, 0x9e51, 0x9e53,
+ 0x9e54, 0x9e55, 0x9e57, 0x9e58, 0x9e5a, 0x9e5b, 0x9e5d, 0x9e5f,
+ 0x9e80, 0x9e80, 0x9e80, 0x9e80, 0x9e81, 0x9e81, 0x9e82, 0x9e82,
+ 0x9e83, 0x9e84, 0x9e85, 0x9e85, 0x9e86, 0x9e87, 0x9e88, 0x9e89,
+ 0x9e8a, 0x9e8b, 0x9e8c, 0x9e8e, 0x9e8f, 0x9e90, 0x9e91, 0x9e93,
+ 0x9e94, 0x9e95, 0x9e97, 0x9e98, 0x9e9a, 0x9e9b, 0x9e9d, 0x9e9f,
+ 0x9ea0, 0x9ea0, 0x9ea0, 0x9ea0, 0x9ea1, 0x9ea1, 0x9ea2, 0x9ea2,
+ 0x9ea3, 0x9ea4, 0x9ea5, 0x9ea5, 0x9ea6, 0x9ea7, 0x9ea8, 0x9ea9,
+ 0x9eaa, 0x9eab, 0x9eac, 0x9eae, 0x9eaf, 0x9eb0, 0x9eb1, 0x9eb3,
+ 0x9eb4, 0x9eb5, 0x9eb7, 0x9eb8, 0x9eba, 0x9ebb, 0x9ebd, 0x9ebf,
+ 0x9ee0, 0x9ee0, 0x9ee0, 0x9ee0, 0x9ee1, 0x9ee1, 0x9ee2, 0x9ee2,
+ 0x9ee3, 0x9ee4, 0x9ee5, 0x9ee5, 0x9ee6, 0x9ee7, 0x9ee8, 0x9ee9,
+ 0x9eea, 0x9eeb, 0x9eec, 0x9eee, 0x9eef, 0x9ef0, 0x9ef1, 0x9ef3,
+ 0x9ef4, 0x9ef5, 0x9ef7, 0x9ef8, 0x9efa, 0x9efb, 0x9efd, 0x9eff,
+ 0x9f00, 0x9f00, 0x9f00, 0x9f00, 0x9f01, 0x9f01, 0x9f02, 0x9f02,
+ 0x9f03, 0x9f04, 0x9f05, 0x9f05, 0x9f06, 0x9f07, 0x9f08, 0x9f09,
+ 0x9f0a, 0x9f0b, 0x9f0c, 0x9f0e, 0x9f0f, 0x9f10, 0x9f11, 0x9f13,
+ 0x9f14, 0x9f15, 0x9f17, 0x9f18, 0x9f1a, 0x9f1b, 0x9f1d, 0x9f1f,
+ 0x9f40, 0x9f40, 0x9f40, 0x9f40, 0x9f41, 0x9f41, 0x9f42, 0x9f42,
+ 0x9f43, 0x9f44, 0x9f45, 0x9f45, 0x9f46, 0x9f47, 0x9f48, 0x9f49,
+ 0x9f4a, 0x9f4b, 0x9f4c, 0x9f4e, 0x9f4f, 0x9f50, 0x9f51, 0x9f53,
+ 0x9f54, 0x9f55, 0x9f57, 0x9f58, 0x9f5a, 0x9f5b, 0x9f5d, 0x9f5f,
+ 0x9f60, 0x9f60, 0x9f60, 0x9f60, 0x9f61, 0x9f61, 0x9f62, 0x9f62,
+ 0x9f63, 0x9f64, 0x9f65, 0x9f65, 0x9f66, 0x9f67, 0x9f68, 0x9f69,
+ 0x9f6a, 0x9f6b, 0x9f6c, 0x9f6e, 0x9f6f, 0x9f70, 0x9f71, 0x9f73,
+ 0x9f74, 0x9f75, 0x9f77, 0x9f78, 0x9f7a, 0x9f7b, 0x9f7d, 0x9f7f,
+ 0x9fa0, 0x9fa0, 0x9fa0, 0x9fa0, 0x9fa1, 0x9fa1, 0x9fa2, 0x9fa2,
+ 0x9fa3, 0x9fa4, 0x9fa5, 0x9fa5, 0x9fa6, 0x9fa7, 0x9fa8, 0x9fa9,
+ 0x9faa, 0x9fab, 0x9fac, 0x9fae, 0x9faf, 0x9fb0, 0x9fb1, 0x9fb3,
+ 0x9fb4, 0x9fb5, 0x9fb7, 0x9fb8, 0x9fba, 0x9fbb, 0x9fbd, 0x9fbf,
+ 0x9fe0, 0x9fe0, 0x9fe0, 0x9fe0, 0x9fe1, 0x9fe1, 0x9fe2, 0x9fe2,
+ 0x9fe3, 0x9fe4, 0x9fe5, 0x9fe5, 0x9fe6, 0x9fe7, 0x9fe8, 0x9fe9,
+ 0x9fea, 0x9feb, 0x9fec, 0x9fee, 0x9fef, 0x9ff0, 0x9ff1, 0x9ff3,
+ 0x9ff4, 0x9ff5, 0x9ff7, 0x9ff8, 0x9ffa, 0x9ffb, 0x9ffd, 0x9fff,
+ 0xa000, 0xa000, 0xa000, 0xa000, 0xa001, 0xa001, 0xa002, 0xa002,
+ 0xa003, 0xa004, 0xa005, 0xa005, 0xa006, 0xa007, 0xa008, 0xa009,
+ 0xa00a, 0xa00b, 0xa00c, 0xa00e, 0xa00f, 0xa010, 0xa011, 0xa013,
+ 0xa014, 0xa015, 0xa017, 0xa018, 0xa01a, 0xa01b, 0xa01d, 0xa01f,
+ 0xa000, 0xa000, 0xa000, 0xa000, 0xa001, 0xa001, 0xa002, 0xa002,
+ 0xa003, 0xa004, 0xa005, 0xa005, 0xa006, 0xa007, 0xa008, 0xa009,
+ 0xa00a, 0xa00b, 0xa00c, 0xa00e, 0xa00f, 0xa010, 0xa011, 0xa013,
+ 0xa014, 0xa015, 0xa017, 0xa018, 0xa01a, 0xa01b, 0xa01d, 0xa01f,
+ 0xa000, 0xa000, 0xa000, 0xa000, 0xa001, 0xa001, 0xa002, 0xa002,
+ 0xa003, 0xa004, 0xa005, 0xa005, 0xa006, 0xa007, 0xa008, 0xa009,
+ 0xa00a, 0xa00b, 0xa00c, 0xa00e, 0xa00f, 0xa010, 0xa011, 0xa013,
+ 0xa014, 0xa015, 0xa017, 0xa018, 0xa01a, 0xa01b, 0xa01d, 0xa01f,
+ 0xa000, 0xa000, 0xa000, 0xa000, 0xa001, 0xa001, 0xa002, 0xa002,
+ 0xa003, 0xa004, 0xa005, 0xa005, 0xa006, 0xa007, 0xa008, 0xa009,
+ 0xa00a, 0xa00b, 0xa00c, 0xa00e, 0xa00f, 0xa010, 0xa011, 0xa013,
+ 0xa014, 0xa015, 0xa017, 0xa018, 0xa01a, 0xa01b, 0xa01d, 0xa01f,
+ 0xa000, 0xa000, 0xa000, 0xa000, 0xa001, 0xa001, 0xa002, 0xa002,
+ 0xa003, 0xa004, 0xa005, 0xa005, 0xa006, 0xa007, 0xa008, 0xa009,
+ 0xa00a, 0xa00b, 0xa00c, 0xa00e, 0xa00f, 0xa010, 0xa011, 0xa013,
+ 0xa014, 0xa015, 0xa017, 0xa018, 0xa01a, 0xa01b, 0xa01d, 0xa01f,
+ 0xa020, 0xa020, 0xa020, 0xa020, 0xa021, 0xa021, 0xa022, 0xa022,
+ 0xa023, 0xa024, 0xa025, 0xa025, 0xa026, 0xa027, 0xa028, 0xa029,
+ 0xa02a, 0xa02b, 0xa02c, 0xa02e, 0xa02f, 0xa030, 0xa031, 0xa033,
+ 0xa034, 0xa035, 0xa037, 0xa038, 0xa03a, 0xa03b, 0xa03d, 0xa03f,
+ 0xa020, 0xa020, 0xa020, 0xa020, 0xa021, 0xa021, 0xa022, 0xa022,
+ 0xa023, 0xa024, 0xa025, 0xa025, 0xa026, 0xa027, 0xa028, 0xa029,
+ 0xa02a, 0xa02b, 0xa02c, 0xa02e, 0xa02f, 0xa030, 0xa031, 0xa033,
+ 0xa034, 0xa035, 0xa037, 0xa038, 0xa03a, 0xa03b, 0xa03d, 0xa03f,
+ 0xa020, 0xa020, 0xa020, 0xa020, 0xa021, 0xa021, 0xa022, 0xa022,
+ 0xa023, 0xa024, 0xa025, 0xa025, 0xa026, 0xa027, 0xa028, 0xa029,
+ 0xa02a, 0xa02b, 0xa02c, 0xa02e, 0xa02f, 0xa030, 0xa031, 0xa033,
+ 0xa034, 0xa035, 0xa037, 0xa038, 0xa03a, 0xa03b, 0xa03d, 0xa03f,
+ 0xa040, 0xa040, 0xa040, 0xa040, 0xa041, 0xa041, 0xa042, 0xa042,
+ 0xa043, 0xa044, 0xa045, 0xa045, 0xa046, 0xa047, 0xa048, 0xa049,
+ 0xa04a, 0xa04b, 0xa04c, 0xa04e, 0xa04f, 0xa050, 0xa051, 0xa053,
+ 0xa054, 0xa055, 0xa057, 0xa058, 0xa05a, 0xa05b, 0xa05d, 0xa05f,
+ 0xa040, 0xa040, 0xa040, 0xa040, 0xa041, 0xa041, 0xa042, 0xa042,
+ 0xa043, 0xa044, 0xa045, 0xa045, 0xa046, 0xa047, 0xa048, 0xa049,
+ 0xa04a, 0xa04b, 0xa04c, 0xa04e, 0xa04f, 0xa050, 0xa051, 0xa053,
+ 0xa054, 0xa055, 0xa057, 0xa058, 0xa05a, 0xa05b, 0xa05d, 0xa05f,
+ 0xa060, 0xa060, 0xa060, 0xa060, 0xa061, 0xa061, 0xa062, 0xa062,
+ 0xa063, 0xa064, 0xa065, 0xa065, 0xa066, 0xa067, 0xa068, 0xa069,
+ 0xa06a, 0xa06b, 0xa06c, 0xa06e, 0xa06f, 0xa070, 0xa071, 0xa073,
+ 0xa074, 0xa075, 0xa077, 0xa078, 0xa07a, 0xa07b, 0xa07d, 0xa07f,
+ 0xa060, 0xa060, 0xa060, 0xa060, 0xa061, 0xa061, 0xa062, 0xa062,
+ 0xa063, 0xa064, 0xa065, 0xa065, 0xa066, 0xa067, 0xa068, 0xa069,
+ 0xa06a, 0xa06b, 0xa06c, 0xa06e, 0xa06f, 0xa070, 0xa071, 0xa073,
+ 0xa074, 0xa075, 0xa077, 0xa078, 0xa07a, 0xa07b, 0xa07d, 0xa07f,
+ 0xa080, 0xa080, 0xa080, 0xa080, 0xa081, 0xa081, 0xa082, 0xa082,
+ 0xa083, 0xa084, 0xa085, 0xa085, 0xa086, 0xa087, 0xa088, 0xa089,
+ 0xa08a, 0xa08b, 0xa08c, 0xa08e, 0xa08f, 0xa090, 0xa091, 0xa093,
+ 0xa094, 0xa095, 0xa097, 0xa098, 0xa09a, 0xa09b, 0xa09d, 0xa09f,
+ 0xa0a0, 0xa0a0, 0xa0a0, 0xa0a0, 0xa0a1, 0xa0a1, 0xa0a2, 0xa0a2,
+ 0xa0a3, 0xa0a4, 0xa0a5, 0xa0a5, 0xa0a6, 0xa0a7, 0xa0a8, 0xa0a9,
+ 0xa0aa, 0xa0ab, 0xa0ac, 0xa0ae, 0xa0af, 0xa0b0, 0xa0b1, 0xa0b3,
+ 0xa0b4, 0xa0b5, 0xa0b7, 0xa0b8, 0xa0ba, 0xa0bb, 0xa0bd, 0xa0bf,
+ 0xa0a0, 0xa0a0, 0xa0a0, 0xa0a0, 0xa0a1, 0xa0a1, 0xa0a2, 0xa0a2,
+ 0xa0a3, 0xa0a4, 0xa0a5, 0xa0a5, 0xa0a6, 0xa0a7, 0xa0a8, 0xa0a9,
+ 0xa0aa, 0xa0ab, 0xa0ac, 0xa0ae, 0xa0af, 0xa0b0, 0xa0b1, 0xa0b3,
+ 0xa0b4, 0xa0b5, 0xa0b7, 0xa0b8, 0xa0ba, 0xa0bb, 0xa0bd, 0xa0bf,
+ 0xa0c0, 0xa0c0, 0xa0c0, 0xa0c0, 0xa0c1, 0xa0c1, 0xa0c2, 0xa0c2,
+ 0xa0c3, 0xa0c4, 0xa0c5, 0xa0c5, 0xa0c6, 0xa0c7, 0xa0c8, 0xa0c9,
+ 0xa0ca, 0xa0cb, 0xa0cc, 0xa0ce, 0xa0cf, 0xa0d0, 0xa0d1, 0xa0d3,
+ 0xa0d4, 0xa0d5, 0xa0d7, 0xa0d8, 0xa0da, 0xa0db, 0xa0dd, 0xa0df,
+ 0xa0e0, 0xa0e0, 0xa0e0, 0xa0e0, 0xa0e1, 0xa0e1, 0xa0e2, 0xa0e2,
+ 0xa0e3, 0xa0e4, 0xa0e5, 0xa0e5, 0xa0e6, 0xa0e7, 0xa0e8, 0xa0e9,
+ 0xa0ea, 0xa0eb, 0xa0ec, 0xa0ee, 0xa0ef, 0xa0f0, 0xa0f1, 0xa0f3,
+ 0xa0f4, 0xa0f5, 0xa0f7, 0xa0f8, 0xa0fa, 0xa0fb, 0xa0fd, 0xa0ff,
+ 0xa0e0, 0xa0e0, 0xa0e0, 0xa0e0, 0xa0e1, 0xa0e1, 0xa0e2, 0xa0e2,
+ 0xa0e3, 0xa0e4, 0xa0e5, 0xa0e5, 0xa0e6, 0xa0e7, 0xa0e8, 0xa0e9,
+ 0xa0ea, 0xa0eb, 0xa0ec, 0xa0ee, 0xa0ef, 0xa0f0, 0xa0f1, 0xa0f3,
+ 0xa0f4, 0xa0f5, 0xa0f7, 0xa0f8, 0xa0fa, 0xa0fb, 0xa0fd, 0xa0ff,
+ 0xa100, 0xa100, 0xa100, 0xa100, 0xa101, 0xa101, 0xa102, 0xa102,
+ 0xa103, 0xa104, 0xa105, 0xa105, 0xa106, 0xa107, 0xa108, 0xa109,
+ 0xa10a, 0xa10b, 0xa10c, 0xa10e, 0xa10f, 0xa110, 0xa111, 0xa113,
+ 0xa114, 0xa115, 0xa117, 0xa118, 0xa11a, 0xa11b, 0xa11d, 0xa11f,
+ 0xa120, 0xa120, 0xa120, 0xa120, 0xa121, 0xa121, 0xa122, 0xa122,
+ 0xa123, 0xa124, 0xa125, 0xa125, 0xa126, 0xa127, 0xa128, 0xa129,
+ 0xa12a, 0xa12b, 0xa12c, 0xa12e, 0xa12f, 0xa130, 0xa131, 0xa133,
+ 0xa134, 0xa135, 0xa137, 0xa138, 0xa13a, 0xa13b, 0xa13d, 0xa13f,
+ 0xa140, 0xa140, 0xa140, 0xa140, 0xa141, 0xa141, 0xa142, 0xa142,
+ 0xa143, 0xa144, 0xa145, 0xa145, 0xa146, 0xa147, 0xa148, 0xa149,
+ 0xa14a, 0xa14b, 0xa14c, 0xa14e, 0xa14f, 0xa150, 0xa151, 0xa153,
+ 0xa154, 0xa155, 0xa157, 0xa158, 0xa15a, 0xa15b, 0xa15d, 0xa15f,
+ 0xa140, 0xa140, 0xa140, 0xa140, 0xa141, 0xa141, 0xa142, 0xa142,
+ 0xa143, 0xa144, 0xa145, 0xa145, 0xa146, 0xa147, 0xa148, 0xa149,
+ 0xa14a, 0xa14b, 0xa14c, 0xa14e, 0xa14f, 0xa150, 0xa151, 0xa153,
+ 0xa154, 0xa155, 0xa157, 0xa158, 0xa15a, 0xa15b, 0xa15d, 0xa15f,
+ 0xa160, 0xa160, 0xa160, 0xa160, 0xa161, 0xa161, 0xa162, 0xa162,
+ 0xa163, 0xa164, 0xa165, 0xa165, 0xa166, 0xa167, 0xa168, 0xa169,
+ 0xa16a, 0xa16b, 0xa16c, 0xa16e, 0xa16f, 0xa170, 0xa171, 0xa173,
+ 0xa174, 0xa175, 0xa177, 0xa178, 0xa17a, 0xa17b, 0xa17d, 0xa17f,
+ 0xa180, 0xa180, 0xa180, 0xa180, 0xa181, 0xa181, 0xa182, 0xa182,
+ 0xa183, 0xa184, 0xa185, 0xa185, 0xa186, 0xa187, 0xa188, 0xa189,
+ 0xa18a, 0xa18b, 0xa18c, 0xa18e, 0xa18f, 0xa190, 0xa191, 0xa193,
+ 0xa194, 0xa195, 0xa197, 0xa198, 0xa19a, 0xa19b, 0xa19d, 0xa19f,
+ 0xa1a0, 0xa1a0, 0xa1a0, 0xa1a0, 0xa1a1, 0xa1a1, 0xa1a2, 0xa1a2,
+ 0xa1a3, 0xa1a4, 0xa1a5, 0xa1a5, 0xa1a6, 0xa1a7, 0xa1a8, 0xa1a9,
+ 0xa1aa, 0xa1ab, 0xa1ac, 0xa1ae, 0xa1af, 0xa1b0, 0xa1b1, 0xa1b3,
+ 0xa1b4, 0xa1b5, 0xa1b7, 0xa1b8, 0xa1ba, 0xa1bb, 0xa1bd, 0xa1bf,
+ 0xa1c0, 0xa1c0, 0xa1c0, 0xa1c0, 0xa1c1, 0xa1c1, 0xa1c2, 0xa1c2,
+ 0xa1c3, 0xa1c4, 0xa1c5, 0xa1c5, 0xa1c6, 0xa1c7, 0xa1c8, 0xa1c9,
+ 0xa1ca, 0xa1cb, 0xa1cc, 0xa1ce, 0xa1cf, 0xa1d0, 0xa1d1, 0xa1d3,
+ 0xa1d4, 0xa1d5, 0xa1d7, 0xa1d8, 0xa1da, 0xa1db, 0xa1dd, 0xa1df,
+ 0xa1e0, 0xa1e0, 0xa1e0, 0xa1e0, 0xa1e1, 0xa1e1, 0xa1e2, 0xa1e2,
+ 0xa1e3, 0xa1e4, 0xa1e5, 0xa1e5, 0xa1e6, 0xa1e7, 0xa1e8, 0xa1e9,
+ 0xa1ea, 0xa1eb, 0xa1ec, 0xa1ee, 0xa1ef, 0xa1f0, 0xa1f1, 0xa1f3,
+ 0xa1f4, 0xa1f5, 0xa1f7, 0xa1f8, 0xa1fa, 0xa1fb, 0xa1fd, 0xa1ff,
+ 0xa200, 0xa200, 0xa200, 0xa200, 0xa201, 0xa201, 0xa202, 0xa202,
+ 0xa203, 0xa204, 0xa205, 0xa205, 0xa206, 0xa207, 0xa208, 0xa209,
+ 0xa20a, 0xa20b, 0xa20c, 0xa20e, 0xa20f, 0xa210, 0xa211, 0xa213,
+ 0xa214, 0xa215, 0xa217, 0xa218, 0xa21a, 0xa21b, 0xa21d, 0xa21f,
+ 0xa220, 0xa220, 0xa220, 0xa220, 0xa221, 0xa221, 0xa222, 0xa222,
+ 0xa223, 0xa224, 0xa225, 0xa225, 0xa226, 0xa227, 0xa228, 0xa229,
+ 0xa22a, 0xa22b, 0xa22c, 0xa22e, 0xa22f, 0xa230, 0xa231, 0xa233,
+ 0xa234, 0xa235, 0xa237, 0xa238, 0xa23a, 0xa23b, 0xa23d, 0xa23f,
+ 0xa240, 0xa240, 0xa240, 0xa240, 0xa241, 0xa241, 0xa242, 0xa242,
+ 0xa243, 0xa244, 0xa245, 0xa245, 0xa246, 0xa247, 0xa248, 0xa249,
+ 0xa24a, 0xa24b, 0xa24c, 0xa24e, 0xa24f, 0xa250, 0xa251, 0xa253,
+ 0xa254, 0xa255, 0xa257, 0xa258, 0xa25a, 0xa25b, 0xa25d, 0xa25f,
+ 0xa260, 0xa260, 0xa260, 0xa260, 0xa261, 0xa261, 0xa262, 0xa262,
+ 0xa263, 0xa264, 0xa265, 0xa265, 0xa266, 0xa267, 0xa268, 0xa269,
+ 0xa26a, 0xa26b, 0xa26c, 0xa26e, 0xa26f, 0xa270, 0xa271, 0xa273,
+ 0xa274, 0xa275, 0xa277, 0xa278, 0xa27a, 0xa27b, 0xa27d, 0xa27f,
+ 0xa280, 0xa280, 0xa280, 0xa280, 0xa281, 0xa281, 0xa282, 0xa282,
+ 0xa283, 0xa284, 0xa285, 0xa285, 0xa286, 0xa287, 0xa288, 0xa289,
+ 0xa28a, 0xa28b, 0xa28c, 0xa28e, 0xa28f, 0xa290, 0xa291, 0xa293,
+ 0xa294, 0xa295, 0xa297, 0xa298, 0xa29a, 0xa29b, 0xa29d, 0xa29f,
+ 0xa2a0, 0xa2a0, 0xa2a0, 0xa2a0, 0xa2a1, 0xa2a1, 0xa2a2, 0xa2a2,
+ 0xa2a3, 0xa2a4, 0xa2a5, 0xa2a5, 0xa2a6, 0xa2a7, 0xa2a8, 0xa2a9,
+ 0xa2aa, 0xa2ab, 0xa2ac, 0xa2ae, 0xa2af, 0xa2b0, 0xa2b1, 0xa2b3,
+ 0xa2b4, 0xa2b5, 0xa2b7, 0xa2b8, 0xa2ba, 0xa2bb, 0xa2bd, 0xa2bf,
+ 0xa2c0, 0xa2c0, 0xa2c0, 0xa2c0, 0xa2c1, 0xa2c1, 0xa2c2, 0xa2c2,
+ 0xa2c3, 0xa2c4, 0xa2c5, 0xa2c5, 0xa2c6, 0xa2c7, 0xa2c8, 0xa2c9,
+ 0xa2ca, 0xa2cb, 0xa2cc, 0xa2ce, 0xa2cf, 0xa2d0, 0xa2d1, 0xa2d3,
+ 0xa2d4, 0xa2d5, 0xa2d7, 0xa2d8, 0xa2da, 0xa2db, 0xa2dd, 0xa2df,
+ 0xa2e0, 0xa2e0, 0xa2e0, 0xa2e0, 0xa2e1, 0xa2e1, 0xa2e2, 0xa2e2,
+ 0xa2e3, 0xa2e4, 0xa2e5, 0xa2e5, 0xa2e6, 0xa2e7, 0xa2e8, 0xa2e9,
+ 0xa2ea, 0xa2eb, 0xa2ec, 0xa2ee, 0xa2ef, 0xa2f0, 0xa2f1, 0xa2f3,
+ 0xa2f4, 0xa2f5, 0xa2f7, 0xa2f8, 0xa2fa, 0xa2fb, 0xa2fd, 0xa2ff,
+ 0xa300, 0xa300, 0xa300, 0xa300, 0xa301, 0xa301, 0xa302, 0xa302,
+ 0xa303, 0xa304, 0xa305, 0xa305, 0xa306, 0xa307, 0xa308, 0xa309,
+ 0xa30a, 0xa30b, 0xa30c, 0xa30e, 0xa30f, 0xa310, 0xa311, 0xa313,
+ 0xa314, 0xa315, 0xa317, 0xa318, 0xa31a, 0xa31b, 0xa31d, 0xa31f,
+ 0xa320, 0xa320, 0xa320, 0xa320, 0xa321, 0xa321, 0xa322, 0xa322,
+ 0xa323, 0xa324, 0xa325, 0xa325, 0xa326, 0xa327, 0xa328, 0xa329,
+ 0xa32a, 0xa32b, 0xa32c, 0xa32e, 0xa32f, 0xa330, 0xa331, 0xa333,
+ 0xa334, 0xa335, 0xa337, 0xa338, 0xa33a, 0xa33b, 0xa33d, 0xa33f,
+ 0xa340, 0xa340, 0xa340, 0xa340, 0xa341, 0xa341, 0xa342, 0xa342,
+ 0xa343, 0xa344, 0xa345, 0xa345, 0xa346, 0xa347, 0xa348, 0xa349,
+ 0xa34a, 0xa34b, 0xa34c, 0xa34e, 0xa34f, 0xa350, 0xa351, 0xa353,
+ 0xa354, 0xa355, 0xa357, 0xa358, 0xa35a, 0xa35b, 0xa35d, 0xa35f,
+ 0xa380, 0xa380, 0xa380, 0xa380, 0xa381, 0xa381, 0xa382, 0xa382,
+ 0xa383, 0xa384, 0xa385, 0xa385, 0xa386, 0xa387, 0xa388, 0xa389,
+ 0xa38a, 0xa38b, 0xa38c, 0xa38e, 0xa38f, 0xa390, 0xa391, 0xa393,
+ 0xa394, 0xa395, 0xa397, 0xa398, 0xa39a, 0xa39b, 0xa39d, 0xa39f,
+ 0xa3a0, 0xa3a0, 0xa3a0, 0xa3a0, 0xa3a1, 0xa3a1, 0xa3a2, 0xa3a2,
+ 0xa3a3, 0xa3a4, 0xa3a5, 0xa3a5, 0xa3a6, 0xa3a7, 0xa3a8, 0xa3a9,
+ 0xa3aa, 0xa3ab, 0xa3ac, 0xa3ae, 0xa3af, 0xa3b0, 0xa3b1, 0xa3b3,
+ 0xa3b4, 0xa3b5, 0xa3b7, 0xa3b8, 0xa3ba, 0xa3bb, 0xa3bd, 0xa3bf,
+ 0xa3c0, 0xa3c0, 0xa3c0, 0xa3c0, 0xa3c1, 0xa3c1, 0xa3c2, 0xa3c2,
+ 0xa3c3, 0xa3c4, 0xa3c5, 0xa3c5, 0xa3c6, 0xa3c7, 0xa3c8, 0xa3c9,
+ 0xa3ca, 0xa3cb, 0xa3cc, 0xa3ce, 0xa3cf, 0xa3d0, 0xa3d1, 0xa3d3,
+ 0xa3d4, 0xa3d5, 0xa3d7, 0xa3d8, 0xa3da, 0xa3db, 0xa3dd, 0xa3df,
+ 0xa3e0, 0xa3e0, 0xa3e0, 0xa3e0, 0xa3e1, 0xa3e1, 0xa3e2, 0xa3e2,
+ 0xa3e3, 0xa3e4, 0xa3e5, 0xa3e5, 0xa3e6, 0xa3e7, 0xa3e8, 0xa3e9,
+ 0xa3ea, 0xa3eb, 0xa3ec, 0xa3ee, 0xa3ef, 0xa3f0, 0xa3f1, 0xa3f3,
+ 0xa3f4, 0xa3f5, 0xa3f7, 0xa3f8, 0xa3fa, 0xa3fb, 0xa3fd, 0xa3ff,
+ 0xa400, 0xa400, 0xa400, 0xa400, 0xa401, 0xa401, 0xa402, 0xa402,
+ 0xa403, 0xa404, 0xa405, 0xa405, 0xa406, 0xa407, 0xa408, 0xa409,
+ 0xa40a, 0xa40b, 0xa40c, 0xa40e, 0xa40f, 0xa410, 0xa411, 0xa413,
+ 0xa414, 0xa415, 0xa417, 0xa418, 0xa41a, 0xa41b, 0xa41d, 0xa41f,
+ 0xa440, 0xa440, 0xa440, 0xa440, 0xa441, 0xa441, 0xa442, 0xa442,
+ 0xa443, 0xa444, 0xa445, 0xa445, 0xa446, 0xa447, 0xa448, 0xa449,
+ 0xa44a, 0xa44b, 0xa44c, 0xa44e, 0xa44f, 0xa450, 0xa451, 0xa453,
+ 0xa454, 0xa455, 0xa457, 0xa458, 0xa45a, 0xa45b, 0xa45d, 0xa45f,
+ 0xa460, 0xa460, 0xa460, 0xa460, 0xa461, 0xa461, 0xa462, 0xa462,
+ 0xa463, 0xa464, 0xa465, 0xa465, 0xa466, 0xa467, 0xa468, 0xa469,
+ 0xa46a, 0xa46b, 0xa46c, 0xa46e, 0xa46f, 0xa470, 0xa471, 0xa473,
+ 0xa474, 0xa475, 0xa477, 0xa478, 0xa47a, 0xa47b, 0xa47d, 0xa47f,
+ 0xa480, 0xa480, 0xa480, 0xa480, 0xa481, 0xa481, 0xa482, 0xa482,
+ 0xa483, 0xa484, 0xa485, 0xa485, 0xa486, 0xa487, 0xa488, 0xa489,
+ 0xa48a, 0xa48b, 0xa48c, 0xa48e, 0xa48f, 0xa490, 0xa491, 0xa493,
+ 0xa494, 0xa495, 0xa497, 0xa498, 0xa49a, 0xa49b, 0xa49d, 0xa49f,
+ 0xa4c0, 0xa4c0, 0xa4c0, 0xa4c0, 0xa4c1, 0xa4c1, 0xa4c2, 0xa4c2,
+ 0xa4c3, 0xa4c4, 0xa4c5, 0xa4c5, 0xa4c6, 0xa4c7, 0xa4c8, 0xa4c9,
+ 0xa4ca, 0xa4cb, 0xa4cc, 0xa4ce, 0xa4cf, 0xa4d0, 0xa4d1, 0xa4d3,
+ 0xa4d4, 0xa4d5, 0xa4d7, 0xa4d8, 0xa4da, 0xa4db, 0xa4dd, 0xa4df,
+ 0xa4e0, 0xa4e0, 0xa4e0, 0xa4e0, 0xa4e1, 0xa4e1, 0xa4e2, 0xa4e2,
+ 0xa4e3, 0xa4e4, 0xa4e5, 0xa4e5, 0xa4e6, 0xa4e7, 0xa4e8, 0xa4e9,
+ 0xa4ea, 0xa4eb, 0xa4ec, 0xa4ee, 0xa4ef, 0xa4f0, 0xa4f1, 0xa4f3,
+ 0xa4f4, 0xa4f5, 0xa4f7, 0xa4f8, 0xa4fa, 0xa4fb, 0xa4fd, 0xa4ff,
+ 0xa500, 0xa500, 0xa500, 0xa500, 0xa501, 0xa501, 0xa502, 0xa502,
+ 0xa503, 0xa504, 0xa505, 0xa505, 0xa506, 0xa507, 0xa508, 0xa509,
+ 0xa50a, 0xa50b, 0xa50c, 0xa50e, 0xa50f, 0xa510, 0xa511, 0xa513,
+ 0xa514, 0xa515, 0xa517, 0xa518, 0xa51a, 0xa51b, 0xa51d, 0xa51f,
+ 0xa540, 0xa540, 0xa540, 0xa540, 0xa541, 0xa541, 0xa542, 0xa542,
+ 0xa543, 0xa544, 0xa545, 0xa545, 0xa546, 0xa547, 0xa548, 0xa549,
+ 0xa54a, 0xa54b, 0xa54c, 0xa54e, 0xa54f, 0xa550, 0xa551, 0xa553,
+ 0xa554, 0xa555, 0xa557, 0xa558, 0xa55a, 0xa55b, 0xa55d, 0xa55f,
+ 0xa560, 0xa560, 0xa560, 0xa560, 0xa561, 0xa561, 0xa562, 0xa562,
+ 0xa563, 0xa564, 0xa565, 0xa565, 0xa566, 0xa567, 0xa568, 0xa569,
+ 0xa56a, 0xa56b, 0xa56c, 0xa56e, 0xa56f, 0xa570, 0xa571, 0xa573,
+ 0xa574, 0xa575, 0xa577, 0xa578, 0xa57a, 0xa57b, 0xa57d, 0xa57f,
+ 0xa580, 0xa580, 0xa580, 0xa580, 0xa581, 0xa581, 0xa582, 0xa582,
+ 0xa583, 0xa584, 0xa585, 0xa585, 0xa586, 0xa587, 0xa588, 0xa589,
+ 0xa58a, 0xa58b, 0xa58c, 0xa58e, 0xa58f, 0xa590, 0xa591, 0xa593,
+ 0xa594, 0xa595, 0xa597, 0xa598, 0xa59a, 0xa59b, 0xa59d, 0xa59f,
+ 0xa5c0, 0xa5c0, 0xa5c0, 0xa5c0, 0xa5c1, 0xa5c1, 0xa5c2, 0xa5c2,
+ 0xa5c3, 0xa5c4, 0xa5c5, 0xa5c5, 0xa5c6, 0xa5c7, 0xa5c8, 0xa5c9,
+ 0xa5ca, 0xa5cb, 0xa5cc, 0xa5ce, 0xa5cf, 0xa5d0, 0xa5d1, 0xa5d3,
+ 0xa5d4, 0xa5d5, 0xa5d7, 0xa5d8, 0xa5da, 0xa5db, 0xa5dd, 0xa5df,
+ 0xa5e0, 0xa5e0, 0xa5e0, 0xa5e0, 0xa5e1, 0xa5e1, 0xa5e2, 0xa5e2,
+ 0xa5e3, 0xa5e4, 0xa5e5, 0xa5e5, 0xa5e6, 0xa5e7, 0xa5e8, 0xa5e9,
+ 0xa5ea, 0xa5eb, 0xa5ec, 0xa5ee, 0xa5ef, 0xa5f0, 0xa5f1, 0xa5f3,
+ 0xa5f4, 0xa5f5, 0xa5f7, 0xa5f8, 0xa5fa, 0xa5fb, 0xa5fd, 0xa5ff,
+ 0xa620, 0xa620, 0xa620, 0xa620, 0xa621, 0xa621, 0xa622, 0xa622,
+ 0xa623, 0xa624, 0xa625, 0xa625, 0xa626, 0xa627, 0xa628, 0xa629,
+ 0xa62a, 0xa62b, 0xa62c, 0xa62e, 0xa62f, 0xa630, 0xa631, 0xa633,
+ 0xa634, 0xa635, 0xa637, 0xa638, 0xa63a, 0xa63b, 0xa63d, 0xa63f,
+ 0xa640, 0xa640, 0xa640, 0xa640, 0xa641, 0xa641, 0xa642, 0xa642,
+ 0xa643, 0xa644, 0xa645, 0xa645, 0xa646, 0xa647, 0xa648, 0xa649,
+ 0xa64a, 0xa64b, 0xa64c, 0xa64e, 0xa64f, 0xa650, 0xa651, 0xa653,
+ 0xa654, 0xa655, 0xa657, 0xa658, 0xa65a, 0xa65b, 0xa65d, 0xa65f,
+ 0xa680, 0xa680, 0xa680, 0xa680, 0xa681, 0xa681, 0xa682, 0xa682,
+ 0xa683, 0xa684, 0xa685, 0xa685, 0xa686, 0xa687, 0xa688, 0xa689,
+ 0xa68a, 0xa68b, 0xa68c, 0xa68e, 0xa68f, 0xa690, 0xa691, 0xa693,
+ 0xa694, 0xa695, 0xa697, 0xa698, 0xa69a, 0xa69b, 0xa69d, 0xa69f,
+ 0xa6a0, 0xa6a0, 0xa6a0, 0xa6a0, 0xa6a1, 0xa6a1, 0xa6a2, 0xa6a2,
+ 0xa6a3, 0xa6a4, 0xa6a5, 0xa6a5, 0xa6a6, 0xa6a7, 0xa6a8, 0xa6a9,
+ 0xa6aa, 0xa6ab, 0xa6ac, 0xa6ae, 0xa6af, 0xa6b0, 0xa6b1, 0xa6b3,
+ 0xa6b4, 0xa6b5, 0xa6b7, 0xa6b8, 0xa6ba, 0xa6bb, 0xa6bd, 0xa6bf,
+ 0xa6e0, 0xa6e0, 0xa6e0, 0xa6e0, 0xa6e1, 0xa6e1, 0xa6e2, 0xa6e2,
+ 0xa6e3, 0xa6e4, 0xa6e5, 0xa6e5, 0xa6e6, 0xa6e7, 0xa6e8, 0xa6e9,
+ 0xa6ea, 0xa6eb, 0xa6ec, 0xa6ee, 0xa6ef, 0xa6f0, 0xa6f1, 0xa6f3,
+ 0xa6f4, 0xa6f5, 0xa6f7, 0xa6f8, 0xa6fa, 0xa6fb, 0xa6fd, 0xa6ff,
+ 0xa700, 0xa700, 0xa700, 0xa700, 0xa701, 0xa701, 0xa702, 0xa702,
+ 0xa703, 0xa704, 0xa705, 0xa705, 0xa706, 0xa707, 0xa708, 0xa709,
+ 0xa70a, 0xa70b, 0xa70c, 0xa70e, 0xa70f, 0xa710, 0xa711, 0xa713,
+ 0xa714, 0xa715, 0xa717, 0xa718, 0xa71a, 0xa71b, 0xa71d, 0xa71f,
+ 0xa740, 0xa740, 0xa740, 0xa740, 0xa741, 0xa741, 0xa742, 0xa742,
+ 0xa743, 0xa744, 0xa745, 0xa745, 0xa746, 0xa747, 0xa748, 0xa749,
+ 0xa74a, 0xa74b, 0xa74c, 0xa74e, 0xa74f, 0xa750, 0xa751, 0xa753,
+ 0xa754, 0xa755, 0xa757, 0xa758, 0xa75a, 0xa75b, 0xa75d, 0xa75f,
+ 0xa760, 0xa760, 0xa760, 0xa760, 0xa761, 0xa761, 0xa762, 0xa762,
+ 0xa763, 0xa764, 0xa765, 0xa765, 0xa766, 0xa767, 0xa768, 0xa769,
+ 0xa76a, 0xa76b, 0xa76c, 0xa76e, 0xa76f, 0xa770, 0xa771, 0xa773,
+ 0xa774, 0xa775, 0xa777, 0xa778, 0xa77a, 0xa77b, 0xa77d, 0xa77f,
+ 0xa7a0, 0xa7a0, 0xa7a0, 0xa7a0, 0xa7a1, 0xa7a1, 0xa7a2, 0xa7a2,
+ 0xa7a3, 0xa7a4, 0xa7a5, 0xa7a5, 0xa7a6, 0xa7a7, 0xa7a8, 0xa7a9,
+ 0xa7aa, 0xa7ab, 0xa7ac, 0xa7ae, 0xa7af, 0xa7b0, 0xa7b1, 0xa7b3,
+ 0xa7b4, 0xa7b5, 0xa7b7, 0xa7b8, 0xa7ba, 0xa7bb, 0xa7bd, 0xa7bf,
+ 0xa7e0, 0xa7e0, 0xa7e0, 0xa7e0, 0xa7e1, 0xa7e1, 0xa7e2, 0xa7e2,
+ 0xa7e3, 0xa7e4, 0xa7e5, 0xa7e5, 0xa7e6, 0xa7e7, 0xa7e8, 0xa7e9,
+ 0xa7ea, 0xa7eb, 0xa7ec, 0xa7ee, 0xa7ef, 0xa7f0, 0xa7f1, 0xa7f3,
+ 0xa7f4, 0xa7f5, 0xa7f7, 0xa7f8, 0xa7fa, 0xa7fb, 0xa7fd, 0xa7ff,
+ 0xa800, 0xa800, 0xa800, 0xa800, 0xa801, 0xa801, 0xa802, 0xa802,
+ 0xa803, 0xa804, 0xa805, 0xa805, 0xa806, 0xa807, 0xa808, 0xa809,
+ 0xa80a, 0xa80b, 0xa80c, 0xa80e, 0xa80f, 0xa810, 0xa811, 0xa813,
+ 0xa814, 0xa815, 0xa817, 0xa818, 0xa81a, 0xa81b, 0xa81d, 0xa81f,
+ 0xa800, 0xa800, 0xa800, 0xa800, 0xa801, 0xa801, 0xa802, 0xa802,
+ 0xa803, 0xa804, 0xa805, 0xa805, 0xa806, 0xa807, 0xa808, 0xa809,
+ 0xa80a, 0xa80b, 0xa80c, 0xa80e, 0xa80f, 0xa810, 0xa811, 0xa813,
+ 0xa814, 0xa815, 0xa817, 0xa818, 0xa81a, 0xa81b, 0xa81d, 0xa81f,
+ 0xa800, 0xa800, 0xa800, 0xa800, 0xa801, 0xa801, 0xa802, 0xa802,
+ 0xa803, 0xa804, 0xa805, 0xa805, 0xa806, 0xa807, 0xa808, 0xa809,
+ 0xa80a, 0xa80b, 0xa80c, 0xa80e, 0xa80f, 0xa810, 0xa811, 0xa813,
+ 0xa814, 0xa815, 0xa817, 0xa818, 0xa81a, 0xa81b, 0xa81d, 0xa81f,
+ 0xa800, 0xa800, 0xa800, 0xa800, 0xa801, 0xa801, 0xa802, 0xa802,
+ 0xa803, 0xa804, 0xa805, 0xa805, 0xa806, 0xa807, 0xa808, 0xa809,
+ 0xa80a, 0xa80b, 0xa80c, 0xa80e, 0xa80f, 0xa810, 0xa811, 0xa813,
+ 0xa814, 0xa815, 0xa817, 0xa818, 0xa81a, 0xa81b, 0xa81d, 0xa81f,
+ 0xa800, 0xa800, 0xa800, 0xa800, 0xa801, 0xa801, 0xa802, 0xa802,
+ 0xa803, 0xa804, 0xa805, 0xa805, 0xa806, 0xa807, 0xa808, 0xa809,
+ 0xa80a, 0xa80b, 0xa80c, 0xa80e, 0xa80f, 0xa810, 0xa811, 0xa813,
+ 0xa814, 0xa815, 0xa817, 0xa818, 0xa81a, 0xa81b, 0xa81d, 0xa81f,
+ 0xa820, 0xa820, 0xa820, 0xa820, 0xa821, 0xa821, 0xa822, 0xa822,
+ 0xa823, 0xa824, 0xa825, 0xa825, 0xa826, 0xa827, 0xa828, 0xa829,
+ 0xa82a, 0xa82b, 0xa82c, 0xa82e, 0xa82f, 0xa830, 0xa831, 0xa833,
+ 0xa834, 0xa835, 0xa837, 0xa838, 0xa83a, 0xa83b, 0xa83d, 0xa83f,
+ 0xa820, 0xa820, 0xa820, 0xa820, 0xa821, 0xa821, 0xa822, 0xa822,
+ 0xa823, 0xa824, 0xa825, 0xa825, 0xa826, 0xa827, 0xa828, 0xa829,
+ 0xa82a, 0xa82b, 0xa82c, 0xa82e, 0xa82f, 0xa830, 0xa831, 0xa833,
+ 0xa834, 0xa835, 0xa837, 0xa838, 0xa83a, 0xa83b, 0xa83d, 0xa83f,
+ 0xa820, 0xa820, 0xa820, 0xa820, 0xa821, 0xa821, 0xa822, 0xa822,
+ 0xa823, 0xa824, 0xa825, 0xa825, 0xa826, 0xa827, 0xa828, 0xa829,
+ 0xa82a, 0xa82b, 0xa82c, 0xa82e, 0xa82f, 0xa830, 0xa831, 0xa833,
+ 0xa834, 0xa835, 0xa837, 0xa838, 0xa83a, 0xa83b, 0xa83d, 0xa83f,
+ 0xa840, 0xa840, 0xa840, 0xa840, 0xa841, 0xa841, 0xa842, 0xa842,
+ 0xa843, 0xa844, 0xa845, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849,
+ 0xa84a, 0xa84b, 0xa84c, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa853,
+ 0xa854, 0xa855, 0xa857, 0xa858, 0xa85a, 0xa85b, 0xa85d, 0xa85f,
+ 0xa840, 0xa840, 0xa840, 0xa840, 0xa841, 0xa841, 0xa842, 0xa842,
+ 0xa843, 0xa844, 0xa845, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849,
+ 0xa84a, 0xa84b, 0xa84c, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa853,
+ 0xa854, 0xa855, 0xa857, 0xa858, 0xa85a, 0xa85b, 0xa85d, 0xa85f,
+ 0xa860, 0xa860, 0xa860, 0xa860, 0xa861, 0xa861, 0xa862, 0xa862,
+ 0xa863, 0xa864, 0xa865, 0xa865, 0xa866, 0xa867, 0xa868, 0xa869,
+ 0xa86a, 0xa86b, 0xa86c, 0xa86e, 0xa86f, 0xa870, 0xa871, 0xa873,
+ 0xa874, 0xa875, 0xa877, 0xa878, 0xa87a, 0xa87b, 0xa87d, 0xa87f,
+ 0xa860, 0xa860, 0xa860, 0xa860, 0xa861, 0xa861, 0xa862, 0xa862,
+ 0xa863, 0xa864, 0xa865, 0xa865, 0xa866, 0xa867, 0xa868, 0xa869,
+ 0xa86a, 0xa86b, 0xa86c, 0xa86e, 0xa86f, 0xa870, 0xa871, 0xa873,
+ 0xa874, 0xa875, 0xa877, 0xa878, 0xa87a, 0xa87b, 0xa87d, 0xa87f,
+ 0xa880, 0xa880, 0xa880, 0xa880, 0xa881, 0xa881, 0xa882, 0xa882,
+ 0xa883, 0xa884, 0xa885, 0xa885, 0xa886, 0xa887, 0xa888, 0xa889,
+ 0xa88a, 0xa88b, 0xa88c, 0xa88e, 0xa88f, 0xa890, 0xa891, 0xa893,
+ 0xa894, 0xa895, 0xa897, 0xa898, 0xa89a, 0xa89b, 0xa89d, 0xa89f,
+ 0xa8a0, 0xa8a0, 0xa8a0, 0xa8a0, 0xa8a1, 0xa8a1, 0xa8a2, 0xa8a2,
+ 0xa8a3, 0xa8a4, 0xa8a5, 0xa8a5, 0xa8a6, 0xa8a7, 0xa8a8, 0xa8a9,
+ 0xa8aa, 0xa8ab, 0xa8ac, 0xa8ae, 0xa8af, 0xa8b0, 0xa8b1, 0xa8b3,
+ 0xa8b4, 0xa8b5, 0xa8b7, 0xa8b8, 0xa8ba, 0xa8bb, 0xa8bd, 0xa8bf,
+ 0xa8a0, 0xa8a0, 0xa8a0, 0xa8a0, 0xa8a1, 0xa8a1, 0xa8a2, 0xa8a2,
+ 0xa8a3, 0xa8a4, 0xa8a5, 0xa8a5, 0xa8a6, 0xa8a7, 0xa8a8, 0xa8a9,
+ 0xa8aa, 0xa8ab, 0xa8ac, 0xa8ae, 0xa8af, 0xa8b0, 0xa8b1, 0xa8b3,
+ 0xa8b4, 0xa8b5, 0xa8b7, 0xa8b8, 0xa8ba, 0xa8bb, 0xa8bd, 0xa8bf,
+ 0xa8c0, 0xa8c0, 0xa8c0, 0xa8c0, 0xa8c1, 0xa8c1, 0xa8c2, 0xa8c2,
+ 0xa8c3, 0xa8c4, 0xa8c5, 0xa8c5, 0xa8c6, 0xa8c7, 0xa8c8, 0xa8c9,
+ 0xa8ca, 0xa8cb, 0xa8cc, 0xa8ce, 0xa8cf, 0xa8d0, 0xa8d1, 0xa8d3,
+ 0xa8d4, 0xa8d5, 0xa8d7, 0xa8d8, 0xa8da, 0xa8db, 0xa8dd, 0xa8df,
+ 0xa8e0, 0xa8e0, 0xa8e0, 0xa8e0, 0xa8e1, 0xa8e1, 0xa8e2, 0xa8e2,
+ 0xa8e3, 0xa8e4, 0xa8e5, 0xa8e5, 0xa8e6, 0xa8e7, 0xa8e8, 0xa8e9,
+ 0xa8ea, 0xa8eb, 0xa8ec, 0xa8ee, 0xa8ef, 0xa8f0, 0xa8f1, 0xa8f3,
+ 0xa8f4, 0xa8f5, 0xa8f7, 0xa8f8, 0xa8fa, 0xa8fb, 0xa8fd, 0xa8ff,
+ 0xa8e0, 0xa8e0, 0xa8e0, 0xa8e0, 0xa8e1, 0xa8e1, 0xa8e2, 0xa8e2,
+ 0xa8e3, 0xa8e4, 0xa8e5, 0xa8e5, 0xa8e6, 0xa8e7, 0xa8e8, 0xa8e9,
+ 0xa8ea, 0xa8eb, 0xa8ec, 0xa8ee, 0xa8ef, 0xa8f0, 0xa8f1, 0xa8f3,
+ 0xa8f4, 0xa8f5, 0xa8f7, 0xa8f8, 0xa8fa, 0xa8fb, 0xa8fd, 0xa8ff,
+ 0xa900, 0xa900, 0xa900, 0xa900, 0xa901, 0xa901, 0xa902, 0xa902,
+ 0xa903, 0xa904, 0xa905, 0xa905, 0xa906, 0xa907, 0xa908, 0xa909,
+ 0xa90a, 0xa90b, 0xa90c, 0xa90e, 0xa90f, 0xa910, 0xa911, 0xa913,
+ 0xa914, 0xa915, 0xa917, 0xa918, 0xa91a, 0xa91b, 0xa91d, 0xa91f,
+ 0xa920, 0xa920, 0xa920, 0xa920, 0xa921, 0xa921, 0xa922, 0xa922,
+ 0xa923, 0xa924, 0xa925, 0xa925, 0xa926, 0xa927, 0xa928, 0xa929,
+ 0xa92a, 0xa92b, 0xa92c, 0xa92e, 0xa92f, 0xa930, 0xa931, 0xa933,
+ 0xa934, 0xa935, 0xa937, 0xa938, 0xa93a, 0xa93b, 0xa93d, 0xa93f,
+ 0xa940, 0xa940, 0xa940, 0xa940, 0xa941, 0xa941, 0xa942, 0xa942,
+ 0xa943, 0xa944, 0xa945, 0xa945, 0xa946, 0xa947, 0xa948, 0xa949,
+ 0xa94a, 0xa94b, 0xa94c, 0xa94e, 0xa94f, 0xa950, 0xa951, 0xa953,
+ 0xa954, 0xa955, 0xa957, 0xa958, 0xa95a, 0xa95b, 0xa95d, 0xa95f,
+ 0xa940, 0xa940, 0xa940, 0xa940, 0xa941, 0xa941, 0xa942, 0xa942,
+ 0xa943, 0xa944, 0xa945, 0xa945, 0xa946, 0xa947, 0xa948, 0xa949,
+ 0xa94a, 0xa94b, 0xa94c, 0xa94e, 0xa94f, 0xa950, 0xa951, 0xa953,
+ 0xa954, 0xa955, 0xa957, 0xa958, 0xa95a, 0xa95b, 0xa95d, 0xa95f,
+ 0xa960, 0xa960, 0xa960, 0xa960, 0xa961, 0xa961, 0xa962, 0xa962,
+ 0xa963, 0xa964, 0xa965, 0xa965, 0xa966, 0xa967, 0xa968, 0xa969,
+ 0xa96a, 0xa96b, 0xa96c, 0xa96e, 0xa96f, 0xa970, 0xa971, 0xa973,
+ 0xa974, 0xa975, 0xa977, 0xa978, 0xa97a, 0xa97b, 0xa97d, 0xa97f,
+ 0xa980, 0xa980, 0xa980, 0xa980, 0xa981, 0xa981, 0xa982, 0xa982,
+ 0xa983, 0xa984, 0xa985, 0xa985, 0xa986, 0xa987, 0xa988, 0xa989,
+ 0xa98a, 0xa98b, 0xa98c, 0xa98e, 0xa98f, 0xa990, 0xa991, 0xa993,
+ 0xa994, 0xa995, 0xa997, 0xa998, 0xa99a, 0xa99b, 0xa99d, 0xa99f,
+ 0xa9a0, 0xa9a0, 0xa9a0, 0xa9a0, 0xa9a1, 0xa9a1, 0xa9a2, 0xa9a2,
+ 0xa9a3, 0xa9a4, 0xa9a5, 0xa9a5, 0xa9a6, 0xa9a7, 0xa9a8, 0xa9a9,
+ 0xa9aa, 0xa9ab, 0xa9ac, 0xa9ae, 0xa9af, 0xa9b0, 0xa9b1, 0xa9b3,
+ 0xa9b4, 0xa9b5, 0xa9b7, 0xa9b8, 0xa9ba, 0xa9bb, 0xa9bd, 0xa9bf,
+ 0xa9c0, 0xa9c0, 0xa9c0, 0xa9c0, 0xa9c1, 0xa9c1, 0xa9c2, 0xa9c2,
+ 0xa9c3, 0xa9c4, 0xa9c5, 0xa9c5, 0xa9c6, 0xa9c7, 0xa9c8, 0xa9c9,
+ 0xa9ca, 0xa9cb, 0xa9cc, 0xa9ce, 0xa9cf, 0xa9d0, 0xa9d1, 0xa9d3,
+ 0xa9d4, 0xa9d5, 0xa9d7, 0xa9d8, 0xa9da, 0xa9db, 0xa9dd, 0xa9df,
+ 0xa9e0, 0xa9e0, 0xa9e0, 0xa9e0, 0xa9e1, 0xa9e1, 0xa9e2, 0xa9e2,
+ 0xa9e3, 0xa9e4, 0xa9e5, 0xa9e5, 0xa9e6, 0xa9e7, 0xa9e8, 0xa9e9,
+ 0xa9ea, 0xa9eb, 0xa9ec, 0xa9ee, 0xa9ef, 0xa9f0, 0xa9f1, 0xa9f3,
+ 0xa9f4, 0xa9f5, 0xa9f7, 0xa9f8, 0xa9fa, 0xa9fb, 0xa9fd, 0xa9ff,
+ 0xaa00, 0xaa00, 0xaa00, 0xaa00, 0xaa01, 0xaa01, 0xaa02, 0xaa02,
+ 0xaa03, 0xaa04, 0xaa05, 0xaa05, 0xaa06, 0xaa07, 0xaa08, 0xaa09,
+ 0xaa0a, 0xaa0b, 0xaa0c, 0xaa0e, 0xaa0f, 0xaa10, 0xaa11, 0xaa13,
+ 0xaa14, 0xaa15, 0xaa17, 0xaa18, 0xaa1a, 0xaa1b, 0xaa1d, 0xaa1f,
+ 0xaa20, 0xaa20, 0xaa20, 0xaa20, 0xaa21, 0xaa21, 0xaa22, 0xaa22,
+ 0xaa23, 0xaa24, 0xaa25, 0xaa25, 0xaa26, 0xaa27, 0xaa28, 0xaa29,
+ 0xaa2a, 0xaa2b, 0xaa2c, 0xaa2e, 0xaa2f, 0xaa30, 0xaa31, 0xaa33,
+ 0xaa34, 0xaa35, 0xaa37, 0xaa38, 0xaa3a, 0xaa3b, 0xaa3d, 0xaa3f,
+ 0xaa40, 0xaa40, 0xaa40, 0xaa40, 0xaa41, 0xaa41, 0xaa42, 0xaa42,
+ 0xaa43, 0xaa44, 0xaa45, 0xaa45, 0xaa46, 0xaa47, 0xaa48, 0xaa49,
+ 0xaa4a, 0xaa4b, 0xaa4c, 0xaa4e, 0xaa4f, 0xaa50, 0xaa51, 0xaa53,
+ 0xaa54, 0xaa55, 0xaa57, 0xaa58, 0xaa5a, 0xaa5b, 0xaa5d, 0xaa5f,
+ 0xaa60, 0xaa60, 0xaa60, 0xaa60, 0xaa61, 0xaa61, 0xaa62, 0xaa62,
+ 0xaa63, 0xaa64, 0xaa65, 0xaa65, 0xaa66, 0xaa67, 0xaa68, 0xaa69,
+ 0xaa6a, 0xaa6b, 0xaa6c, 0xaa6e, 0xaa6f, 0xaa70, 0xaa71, 0xaa73,
+ 0xaa74, 0xaa75, 0xaa77, 0xaa78, 0xaa7a, 0xaa7b, 0xaa7d, 0xaa7f,
+ 0xaa80, 0xaa80, 0xaa80, 0xaa80, 0xaa81, 0xaa81, 0xaa82, 0xaa82,
+ 0xaa83, 0xaa84, 0xaa85, 0xaa85, 0xaa86, 0xaa87, 0xaa88, 0xaa89,
+ 0xaa8a, 0xaa8b, 0xaa8c, 0xaa8e, 0xaa8f, 0xaa90, 0xaa91, 0xaa93,
+ 0xaa94, 0xaa95, 0xaa97, 0xaa98, 0xaa9a, 0xaa9b, 0xaa9d, 0xaa9f,
+ 0xaaa0, 0xaaa0, 0xaaa0, 0xaaa0, 0xaaa1, 0xaaa1, 0xaaa2, 0xaaa2,
+ 0xaaa3, 0xaaa4, 0xaaa5, 0xaaa5, 0xaaa6, 0xaaa7, 0xaaa8, 0xaaa9,
+ 0xaaaa, 0xaaab, 0xaaac, 0xaaae, 0xaaaf, 0xaab0, 0xaab1, 0xaab3,
+ 0xaab4, 0xaab5, 0xaab7, 0xaab8, 0xaaba, 0xaabb, 0xaabd, 0xaabf,
+ 0xaac0, 0xaac0, 0xaac0, 0xaac0, 0xaac1, 0xaac1, 0xaac2, 0xaac2,
+ 0xaac3, 0xaac4, 0xaac5, 0xaac5, 0xaac6, 0xaac7, 0xaac8, 0xaac9,
+ 0xaaca, 0xaacb, 0xaacc, 0xaace, 0xaacf, 0xaad0, 0xaad1, 0xaad3,
+ 0xaad4, 0xaad5, 0xaad7, 0xaad8, 0xaada, 0xaadb, 0xaadd, 0xaadf,
+ 0xaae0, 0xaae0, 0xaae0, 0xaae0, 0xaae1, 0xaae1, 0xaae2, 0xaae2,
+ 0xaae3, 0xaae4, 0xaae5, 0xaae5, 0xaae6, 0xaae7, 0xaae8, 0xaae9,
+ 0xaaea, 0xaaeb, 0xaaec, 0xaaee, 0xaaef, 0xaaf0, 0xaaf1, 0xaaf3,
+ 0xaaf4, 0xaaf5, 0xaaf7, 0xaaf8, 0xaafa, 0xaafb, 0xaafd, 0xaaff,
+ 0xab00, 0xab00, 0xab00, 0xab00, 0xab01, 0xab01, 0xab02, 0xab02,
+ 0xab03, 0xab04, 0xab05, 0xab05, 0xab06, 0xab07, 0xab08, 0xab09,
+ 0xab0a, 0xab0b, 0xab0c, 0xab0e, 0xab0f, 0xab10, 0xab11, 0xab13,
+ 0xab14, 0xab15, 0xab17, 0xab18, 0xab1a, 0xab1b, 0xab1d, 0xab1f,
+ 0xab20, 0xab20, 0xab20, 0xab20, 0xab21, 0xab21, 0xab22, 0xab22,
+ 0xab23, 0xab24, 0xab25, 0xab25, 0xab26, 0xab27, 0xab28, 0xab29,
+ 0xab2a, 0xab2b, 0xab2c, 0xab2e, 0xab2f, 0xab30, 0xab31, 0xab33,
+ 0xab34, 0xab35, 0xab37, 0xab38, 0xab3a, 0xab3b, 0xab3d, 0xab3f,
+ 0xab40, 0xab40, 0xab40, 0xab40, 0xab41, 0xab41, 0xab42, 0xab42,
+ 0xab43, 0xab44, 0xab45, 0xab45, 0xab46, 0xab47, 0xab48, 0xab49,
+ 0xab4a, 0xab4b, 0xab4c, 0xab4e, 0xab4f, 0xab50, 0xab51, 0xab53,
+ 0xab54, 0xab55, 0xab57, 0xab58, 0xab5a, 0xab5b, 0xab5d, 0xab5f,
+ 0xab80, 0xab80, 0xab80, 0xab80, 0xab81, 0xab81, 0xab82, 0xab82,
+ 0xab83, 0xab84, 0xab85, 0xab85, 0xab86, 0xab87, 0xab88, 0xab89,
+ 0xab8a, 0xab8b, 0xab8c, 0xab8e, 0xab8f, 0xab90, 0xab91, 0xab93,
+ 0xab94, 0xab95, 0xab97, 0xab98, 0xab9a, 0xab9b, 0xab9d, 0xab9f,
+ 0xaba0, 0xaba0, 0xaba0, 0xaba0, 0xaba1, 0xaba1, 0xaba2, 0xaba2,
+ 0xaba3, 0xaba4, 0xaba5, 0xaba5, 0xaba6, 0xaba7, 0xaba8, 0xaba9,
+ 0xabaa, 0xabab, 0xabac, 0xabae, 0xabaf, 0xabb0, 0xabb1, 0xabb3,
+ 0xabb4, 0xabb5, 0xabb7, 0xabb8, 0xabba, 0xabbb, 0xabbd, 0xabbf,
+ 0xabc0, 0xabc0, 0xabc0, 0xabc0, 0xabc1, 0xabc1, 0xabc2, 0xabc2,
+ 0xabc3, 0xabc4, 0xabc5, 0xabc5, 0xabc6, 0xabc7, 0xabc8, 0xabc9,
+ 0xabca, 0xabcb, 0xabcc, 0xabce, 0xabcf, 0xabd0, 0xabd1, 0xabd3,
+ 0xabd4, 0xabd5, 0xabd7, 0xabd8, 0xabda, 0xabdb, 0xabdd, 0xabdf,
+ 0xabe0, 0xabe0, 0xabe0, 0xabe0, 0xabe1, 0xabe1, 0xabe2, 0xabe2,
+ 0xabe3, 0xabe4, 0xabe5, 0xabe5, 0xabe6, 0xabe7, 0xabe8, 0xabe9,
+ 0xabea, 0xabeb, 0xabec, 0xabee, 0xabef, 0xabf0, 0xabf1, 0xabf3,
+ 0xabf4, 0xabf5, 0xabf7, 0xabf8, 0xabfa, 0xabfb, 0xabfd, 0xabff,
+ 0xac00, 0xac00, 0xac00, 0xac00, 0xac01, 0xac01, 0xac02, 0xac02,
+ 0xac03, 0xac04, 0xac05, 0xac05, 0xac06, 0xac07, 0xac08, 0xac09,
+ 0xac0a, 0xac0b, 0xac0c, 0xac0e, 0xac0f, 0xac10, 0xac11, 0xac13,
+ 0xac14, 0xac15, 0xac17, 0xac18, 0xac1a, 0xac1b, 0xac1d, 0xac1f,
+ 0xac40, 0xac40, 0xac40, 0xac40, 0xac41, 0xac41, 0xac42, 0xac42,
+ 0xac43, 0xac44, 0xac45, 0xac45, 0xac46, 0xac47, 0xac48, 0xac49,
+ 0xac4a, 0xac4b, 0xac4c, 0xac4e, 0xac4f, 0xac50, 0xac51, 0xac53,
+ 0xac54, 0xac55, 0xac57, 0xac58, 0xac5a, 0xac5b, 0xac5d, 0xac5f,
+ 0xac60, 0xac60, 0xac60, 0xac60, 0xac61, 0xac61, 0xac62, 0xac62,
+ 0xac63, 0xac64, 0xac65, 0xac65, 0xac66, 0xac67, 0xac68, 0xac69,
+ 0xac6a, 0xac6b, 0xac6c, 0xac6e, 0xac6f, 0xac70, 0xac71, 0xac73,
+ 0xac74, 0xac75, 0xac77, 0xac78, 0xac7a, 0xac7b, 0xac7d, 0xac7f,
+ 0xac80, 0xac80, 0xac80, 0xac80, 0xac81, 0xac81, 0xac82, 0xac82,
+ 0xac83, 0xac84, 0xac85, 0xac85, 0xac86, 0xac87, 0xac88, 0xac89,
+ 0xac8a, 0xac8b, 0xac8c, 0xac8e, 0xac8f, 0xac90, 0xac91, 0xac93,
+ 0xac94, 0xac95, 0xac97, 0xac98, 0xac9a, 0xac9b, 0xac9d, 0xac9f,
+ 0xacc0, 0xacc0, 0xacc0, 0xacc0, 0xacc1, 0xacc1, 0xacc2, 0xacc2,
+ 0xacc3, 0xacc4, 0xacc5, 0xacc5, 0xacc6, 0xacc7, 0xacc8, 0xacc9,
+ 0xacca, 0xaccb, 0xaccc, 0xacce, 0xaccf, 0xacd0, 0xacd1, 0xacd3,
+ 0xacd4, 0xacd5, 0xacd7, 0xacd8, 0xacda, 0xacdb, 0xacdd, 0xacdf,
+ 0xace0, 0xace0, 0xace0, 0xace0, 0xace1, 0xace1, 0xace2, 0xace2,
+ 0xace3, 0xace4, 0xace5, 0xace5, 0xace6, 0xace7, 0xace8, 0xace9,
+ 0xacea, 0xaceb, 0xacec, 0xacee, 0xacef, 0xacf0, 0xacf1, 0xacf3,
+ 0xacf4, 0xacf5, 0xacf7, 0xacf8, 0xacfa, 0xacfb, 0xacfd, 0xacff,
+ 0xad00, 0xad00, 0xad00, 0xad00, 0xad01, 0xad01, 0xad02, 0xad02,
+ 0xad03, 0xad04, 0xad05, 0xad05, 0xad06, 0xad07, 0xad08, 0xad09,
+ 0xad0a, 0xad0b, 0xad0c, 0xad0e, 0xad0f, 0xad10, 0xad11, 0xad13,
+ 0xad14, 0xad15, 0xad17, 0xad18, 0xad1a, 0xad1b, 0xad1d, 0xad1f,
+ 0xad40, 0xad40, 0xad40, 0xad40, 0xad41, 0xad41, 0xad42, 0xad42,
+ 0xad43, 0xad44, 0xad45, 0xad45, 0xad46, 0xad47, 0xad48, 0xad49,
+ 0xad4a, 0xad4b, 0xad4c, 0xad4e, 0xad4f, 0xad50, 0xad51, 0xad53,
+ 0xad54, 0xad55, 0xad57, 0xad58, 0xad5a, 0xad5b, 0xad5d, 0xad5f,
+ 0xad60, 0xad60, 0xad60, 0xad60, 0xad61, 0xad61, 0xad62, 0xad62,
+ 0xad63, 0xad64, 0xad65, 0xad65, 0xad66, 0xad67, 0xad68, 0xad69,
+ 0xad6a, 0xad6b, 0xad6c, 0xad6e, 0xad6f, 0xad70, 0xad71, 0xad73,
+ 0xad74, 0xad75, 0xad77, 0xad78, 0xad7a, 0xad7b, 0xad7d, 0xad7f,
+ 0xad80, 0xad80, 0xad80, 0xad80, 0xad81, 0xad81, 0xad82, 0xad82,
+ 0xad83, 0xad84, 0xad85, 0xad85, 0xad86, 0xad87, 0xad88, 0xad89,
+ 0xad8a, 0xad8b, 0xad8c, 0xad8e, 0xad8f, 0xad90, 0xad91, 0xad93,
+ 0xad94, 0xad95, 0xad97, 0xad98, 0xad9a, 0xad9b, 0xad9d, 0xad9f,
+ 0xadc0, 0xadc0, 0xadc0, 0xadc0, 0xadc1, 0xadc1, 0xadc2, 0xadc2,
+ 0xadc3, 0xadc4, 0xadc5, 0xadc5, 0xadc6, 0xadc7, 0xadc8, 0xadc9,
+ 0xadca, 0xadcb, 0xadcc, 0xadce, 0xadcf, 0xadd0, 0xadd1, 0xadd3,
+ 0xadd4, 0xadd5, 0xadd7, 0xadd8, 0xadda, 0xaddb, 0xaddd, 0xaddf,
+ 0xade0, 0xade0, 0xade0, 0xade0, 0xade1, 0xade1, 0xade2, 0xade2,
+ 0xade3, 0xade4, 0xade5, 0xade5, 0xade6, 0xade7, 0xade8, 0xade9,
+ 0xadea, 0xadeb, 0xadec, 0xadee, 0xadef, 0xadf0, 0xadf1, 0xadf3,
+ 0xadf4, 0xadf5, 0xadf7, 0xadf8, 0xadfa, 0xadfb, 0xadfd, 0xadff,
+ 0xae20, 0xae20, 0xae20, 0xae20, 0xae21, 0xae21, 0xae22, 0xae22,
+ 0xae23, 0xae24, 0xae25, 0xae25, 0xae26, 0xae27, 0xae28, 0xae29,
+ 0xae2a, 0xae2b, 0xae2c, 0xae2e, 0xae2f, 0xae30, 0xae31, 0xae33,
+ 0xae34, 0xae35, 0xae37, 0xae38, 0xae3a, 0xae3b, 0xae3d, 0xae3f,
+ 0xae40, 0xae40, 0xae40, 0xae40, 0xae41, 0xae41, 0xae42, 0xae42,
+ 0xae43, 0xae44, 0xae45, 0xae45, 0xae46, 0xae47, 0xae48, 0xae49,
+ 0xae4a, 0xae4b, 0xae4c, 0xae4e, 0xae4f, 0xae50, 0xae51, 0xae53,
+ 0xae54, 0xae55, 0xae57, 0xae58, 0xae5a, 0xae5b, 0xae5d, 0xae5f,
+ 0xae80, 0xae80, 0xae80, 0xae80, 0xae81, 0xae81, 0xae82, 0xae82,
+ 0xae83, 0xae84, 0xae85, 0xae85, 0xae86, 0xae87, 0xae88, 0xae89,
+ 0xae8a, 0xae8b, 0xae8c, 0xae8e, 0xae8f, 0xae90, 0xae91, 0xae93,
+ 0xae94, 0xae95, 0xae97, 0xae98, 0xae9a, 0xae9b, 0xae9d, 0xae9f,
+ 0xaea0, 0xaea0, 0xaea0, 0xaea0, 0xaea1, 0xaea1, 0xaea2, 0xaea2,
+ 0xaea3, 0xaea4, 0xaea5, 0xaea5, 0xaea6, 0xaea7, 0xaea8, 0xaea9,
+ 0xaeaa, 0xaeab, 0xaeac, 0xaeae, 0xaeaf, 0xaeb0, 0xaeb1, 0xaeb3,
+ 0xaeb4, 0xaeb5, 0xaeb7, 0xaeb8, 0xaeba, 0xaebb, 0xaebd, 0xaebf,
+ 0xaee0, 0xaee0, 0xaee0, 0xaee0, 0xaee1, 0xaee1, 0xaee2, 0xaee2,
+ 0xaee3, 0xaee4, 0xaee5, 0xaee5, 0xaee6, 0xaee7, 0xaee8, 0xaee9,
+ 0xaeea, 0xaeeb, 0xaeec, 0xaeee, 0xaeef, 0xaef0, 0xaef1, 0xaef3,
+ 0xaef4, 0xaef5, 0xaef7, 0xaef8, 0xaefa, 0xaefb, 0xaefd, 0xaeff,
+ 0xaf00, 0xaf00, 0xaf00, 0xaf00, 0xaf01, 0xaf01, 0xaf02, 0xaf02,
+ 0xaf03, 0xaf04, 0xaf05, 0xaf05, 0xaf06, 0xaf07, 0xaf08, 0xaf09,
+ 0xaf0a, 0xaf0b, 0xaf0c, 0xaf0e, 0xaf0f, 0xaf10, 0xaf11, 0xaf13,
+ 0xaf14, 0xaf15, 0xaf17, 0xaf18, 0xaf1a, 0xaf1b, 0xaf1d, 0xaf1f,
+ 0xaf40, 0xaf40, 0xaf40, 0xaf40, 0xaf41, 0xaf41, 0xaf42, 0xaf42,
+ 0xaf43, 0xaf44, 0xaf45, 0xaf45, 0xaf46, 0xaf47, 0xaf48, 0xaf49,
+ 0xaf4a, 0xaf4b, 0xaf4c, 0xaf4e, 0xaf4f, 0xaf50, 0xaf51, 0xaf53,
+ 0xaf54, 0xaf55, 0xaf57, 0xaf58, 0xaf5a, 0xaf5b, 0xaf5d, 0xaf5f,
+ 0xaf60, 0xaf60, 0xaf60, 0xaf60, 0xaf61, 0xaf61, 0xaf62, 0xaf62,
+ 0xaf63, 0xaf64, 0xaf65, 0xaf65, 0xaf66, 0xaf67, 0xaf68, 0xaf69,
+ 0xaf6a, 0xaf6b, 0xaf6c, 0xaf6e, 0xaf6f, 0xaf70, 0xaf71, 0xaf73,
+ 0xaf74, 0xaf75, 0xaf77, 0xaf78, 0xaf7a, 0xaf7b, 0xaf7d, 0xaf7f,
+ 0xafa0, 0xafa0, 0xafa0, 0xafa0, 0xafa1, 0xafa1, 0xafa2, 0xafa2,
+ 0xafa3, 0xafa4, 0xafa5, 0xafa5, 0xafa6, 0xafa7, 0xafa8, 0xafa9,
+ 0xafaa, 0xafab, 0xafac, 0xafae, 0xafaf, 0xafb0, 0xafb1, 0xafb3,
+ 0xafb4, 0xafb5, 0xafb7, 0xafb8, 0xafba, 0xafbb, 0xafbd, 0xafbf,
+ 0xafe0, 0xafe0, 0xafe0, 0xafe0, 0xafe1, 0xafe1, 0xafe2, 0xafe2,
+ 0xafe3, 0xafe4, 0xafe5, 0xafe5, 0xafe6, 0xafe7, 0xafe8, 0xafe9,
+ 0xafea, 0xafeb, 0xafec, 0xafee, 0xafef, 0xaff0, 0xaff1, 0xaff3,
+ 0xaff4, 0xaff5, 0xaff7, 0xaff8, 0xaffa, 0xaffb, 0xaffd, 0xafff,
+ 0xb800, 0xb800, 0xb800, 0xb800, 0xb801, 0xb801, 0xb802, 0xb802,
+ 0xb803, 0xb804, 0xb805, 0xb805, 0xb806, 0xb807, 0xb808, 0xb809,
+ 0xb80a, 0xb80b, 0xb80c, 0xb80e, 0xb80f, 0xb810, 0xb811, 0xb813,
+ 0xb814, 0xb815, 0xb817, 0xb818, 0xb81a, 0xb81b, 0xb81d, 0xb81f,
+ 0xb800, 0xb800, 0xb800, 0xb800, 0xb801, 0xb801, 0xb802, 0xb802,
+ 0xb803, 0xb804, 0xb805, 0xb805, 0xb806, 0xb807, 0xb808, 0xb809,
+ 0xb80a, 0xb80b, 0xb80c, 0xb80e, 0xb80f, 0xb810, 0xb811, 0xb813,
+ 0xb814, 0xb815, 0xb817, 0xb818, 0xb81a, 0xb81b, 0xb81d, 0xb81f,
+ 0xb800, 0xb800, 0xb800, 0xb800, 0xb801, 0xb801, 0xb802, 0xb802,
+ 0xb803, 0xb804, 0xb805, 0xb805, 0xb806, 0xb807, 0xb808, 0xb809,
+ 0xb80a, 0xb80b, 0xb80c, 0xb80e, 0xb80f, 0xb810, 0xb811, 0xb813,
+ 0xb814, 0xb815, 0xb817, 0xb818, 0xb81a, 0xb81b, 0xb81d, 0xb81f,
+ 0xb800, 0xb800, 0xb800, 0xb800, 0xb801, 0xb801, 0xb802, 0xb802,
+ 0xb803, 0xb804, 0xb805, 0xb805, 0xb806, 0xb807, 0xb808, 0xb809,
+ 0xb80a, 0xb80b, 0xb80c, 0xb80e, 0xb80f, 0xb810, 0xb811, 0xb813,
+ 0xb814, 0xb815, 0xb817, 0xb818, 0xb81a, 0xb81b, 0xb81d, 0xb81f,
+ 0xb800, 0xb800, 0xb800, 0xb800, 0xb801, 0xb801, 0xb802, 0xb802,
+ 0xb803, 0xb804, 0xb805, 0xb805, 0xb806, 0xb807, 0xb808, 0xb809,
+ 0xb80a, 0xb80b, 0xb80c, 0xb80e, 0xb80f, 0xb810, 0xb811, 0xb813,
+ 0xb814, 0xb815, 0xb817, 0xb818, 0xb81a, 0xb81b, 0xb81d, 0xb81f,
+ 0xb820, 0xb820, 0xb820, 0xb820, 0xb821, 0xb821, 0xb822, 0xb822,
+ 0xb823, 0xb824, 0xb825, 0xb825, 0xb826, 0xb827, 0xb828, 0xb829,
+ 0xb82a, 0xb82b, 0xb82c, 0xb82e, 0xb82f, 0xb830, 0xb831, 0xb833,
+ 0xb834, 0xb835, 0xb837, 0xb838, 0xb83a, 0xb83b, 0xb83d, 0xb83f,
+ 0xb820, 0xb820, 0xb820, 0xb820, 0xb821, 0xb821, 0xb822, 0xb822,
+ 0xb823, 0xb824, 0xb825, 0xb825, 0xb826, 0xb827, 0xb828, 0xb829,
+ 0xb82a, 0xb82b, 0xb82c, 0xb82e, 0xb82f, 0xb830, 0xb831, 0xb833,
+ 0xb834, 0xb835, 0xb837, 0xb838, 0xb83a, 0xb83b, 0xb83d, 0xb83f,
+ 0xb820, 0xb820, 0xb820, 0xb820, 0xb821, 0xb821, 0xb822, 0xb822,
+ 0xb823, 0xb824, 0xb825, 0xb825, 0xb826, 0xb827, 0xb828, 0xb829,
+ 0xb82a, 0xb82b, 0xb82c, 0xb82e, 0xb82f, 0xb830, 0xb831, 0xb833,
+ 0xb834, 0xb835, 0xb837, 0xb838, 0xb83a, 0xb83b, 0xb83d, 0xb83f,
+ 0xb840, 0xb840, 0xb840, 0xb840, 0xb841, 0xb841, 0xb842, 0xb842,
+ 0xb843, 0xb844, 0xb845, 0xb845, 0xb846, 0xb847, 0xb848, 0xb849,
+ 0xb84a, 0xb84b, 0xb84c, 0xb84e, 0xb84f, 0xb850, 0xb851, 0xb853,
+ 0xb854, 0xb855, 0xb857, 0xb858, 0xb85a, 0xb85b, 0xb85d, 0xb85f,
+ 0xb840, 0xb840, 0xb840, 0xb840, 0xb841, 0xb841, 0xb842, 0xb842,
+ 0xb843, 0xb844, 0xb845, 0xb845, 0xb846, 0xb847, 0xb848, 0xb849,
+ 0xb84a, 0xb84b, 0xb84c, 0xb84e, 0xb84f, 0xb850, 0xb851, 0xb853,
+ 0xb854, 0xb855, 0xb857, 0xb858, 0xb85a, 0xb85b, 0xb85d, 0xb85f,
+ 0xb860, 0xb860, 0xb860, 0xb860, 0xb861, 0xb861, 0xb862, 0xb862,
+ 0xb863, 0xb864, 0xb865, 0xb865, 0xb866, 0xb867, 0xb868, 0xb869,
+ 0xb86a, 0xb86b, 0xb86c, 0xb86e, 0xb86f, 0xb870, 0xb871, 0xb873,
+ 0xb874, 0xb875, 0xb877, 0xb878, 0xb87a, 0xb87b, 0xb87d, 0xb87f,
+ 0xb860, 0xb860, 0xb860, 0xb860, 0xb861, 0xb861, 0xb862, 0xb862,
+ 0xb863, 0xb864, 0xb865, 0xb865, 0xb866, 0xb867, 0xb868, 0xb869,
+ 0xb86a, 0xb86b, 0xb86c, 0xb86e, 0xb86f, 0xb870, 0xb871, 0xb873,
+ 0xb874, 0xb875, 0xb877, 0xb878, 0xb87a, 0xb87b, 0xb87d, 0xb87f,
+ 0xb880, 0xb880, 0xb880, 0xb880, 0xb881, 0xb881, 0xb882, 0xb882,
+ 0xb883, 0xb884, 0xb885, 0xb885, 0xb886, 0xb887, 0xb888, 0xb889,
+ 0xb88a, 0xb88b, 0xb88c, 0xb88e, 0xb88f, 0xb890, 0xb891, 0xb893,
+ 0xb894, 0xb895, 0xb897, 0xb898, 0xb89a, 0xb89b, 0xb89d, 0xb89f,
+ 0xb8a0, 0xb8a0, 0xb8a0, 0xb8a0, 0xb8a1, 0xb8a1, 0xb8a2, 0xb8a2,
+ 0xb8a3, 0xb8a4, 0xb8a5, 0xb8a5, 0xb8a6, 0xb8a7, 0xb8a8, 0xb8a9,
+ 0xb8aa, 0xb8ab, 0xb8ac, 0xb8ae, 0xb8af, 0xb8b0, 0xb8b1, 0xb8b3,
+ 0xb8b4, 0xb8b5, 0xb8b7, 0xb8b8, 0xb8ba, 0xb8bb, 0xb8bd, 0xb8bf,
+ 0xb8a0, 0xb8a0, 0xb8a0, 0xb8a0, 0xb8a1, 0xb8a1, 0xb8a2, 0xb8a2,
+ 0xb8a3, 0xb8a4, 0xb8a5, 0xb8a5, 0xb8a6, 0xb8a7, 0xb8a8, 0xb8a9,
+ 0xb8aa, 0xb8ab, 0xb8ac, 0xb8ae, 0xb8af, 0xb8b0, 0xb8b1, 0xb8b3,
+ 0xb8b4, 0xb8b5, 0xb8b7, 0xb8b8, 0xb8ba, 0xb8bb, 0xb8bd, 0xb8bf,
+ 0xb8c0, 0xb8c0, 0xb8c0, 0xb8c0, 0xb8c1, 0xb8c1, 0xb8c2, 0xb8c2,
+ 0xb8c3, 0xb8c4, 0xb8c5, 0xb8c5, 0xb8c6, 0xb8c7, 0xb8c8, 0xb8c9,
+ 0xb8ca, 0xb8cb, 0xb8cc, 0xb8ce, 0xb8cf, 0xb8d0, 0xb8d1, 0xb8d3,
+ 0xb8d4, 0xb8d5, 0xb8d7, 0xb8d8, 0xb8da, 0xb8db, 0xb8dd, 0xb8df,
+ 0xb8e0, 0xb8e0, 0xb8e0, 0xb8e0, 0xb8e1, 0xb8e1, 0xb8e2, 0xb8e2,
+ 0xb8e3, 0xb8e4, 0xb8e5, 0xb8e5, 0xb8e6, 0xb8e7, 0xb8e8, 0xb8e9,
+ 0xb8ea, 0xb8eb, 0xb8ec, 0xb8ee, 0xb8ef, 0xb8f0, 0xb8f1, 0xb8f3,
+ 0xb8f4, 0xb8f5, 0xb8f7, 0xb8f8, 0xb8fa, 0xb8fb, 0xb8fd, 0xb8ff,
+ 0xb8e0, 0xb8e0, 0xb8e0, 0xb8e0, 0xb8e1, 0xb8e1, 0xb8e2, 0xb8e2,
+ 0xb8e3, 0xb8e4, 0xb8e5, 0xb8e5, 0xb8e6, 0xb8e7, 0xb8e8, 0xb8e9,
+ 0xb8ea, 0xb8eb, 0xb8ec, 0xb8ee, 0xb8ef, 0xb8f0, 0xb8f1, 0xb8f3,
+ 0xb8f4, 0xb8f5, 0xb8f7, 0xb8f8, 0xb8fa, 0xb8fb, 0xb8fd, 0xb8ff,
+ 0xb900, 0xb900, 0xb900, 0xb900, 0xb901, 0xb901, 0xb902, 0xb902,
+ 0xb903, 0xb904, 0xb905, 0xb905, 0xb906, 0xb907, 0xb908, 0xb909,
+ 0xb90a, 0xb90b, 0xb90c, 0xb90e, 0xb90f, 0xb910, 0xb911, 0xb913,
+ 0xb914, 0xb915, 0xb917, 0xb918, 0xb91a, 0xb91b, 0xb91d, 0xb91f,
+ 0xb920, 0xb920, 0xb920, 0xb920, 0xb921, 0xb921, 0xb922, 0xb922,
+ 0xb923, 0xb924, 0xb925, 0xb925, 0xb926, 0xb927, 0xb928, 0xb929,
+ 0xb92a, 0xb92b, 0xb92c, 0xb92e, 0xb92f, 0xb930, 0xb931, 0xb933,
+ 0xb934, 0xb935, 0xb937, 0xb938, 0xb93a, 0xb93b, 0xb93d, 0xb93f,
+ 0xb940, 0xb940, 0xb940, 0xb940, 0xb941, 0xb941, 0xb942, 0xb942,
+ 0xb943, 0xb944, 0xb945, 0xb945, 0xb946, 0xb947, 0xb948, 0xb949,
+ 0xb94a, 0xb94b, 0xb94c, 0xb94e, 0xb94f, 0xb950, 0xb951, 0xb953,
+ 0xb954, 0xb955, 0xb957, 0xb958, 0xb95a, 0xb95b, 0xb95d, 0xb95f,
+ 0xb940, 0xb940, 0xb940, 0xb940, 0xb941, 0xb941, 0xb942, 0xb942,
+ 0xb943, 0xb944, 0xb945, 0xb945, 0xb946, 0xb947, 0xb948, 0xb949,
+ 0xb94a, 0xb94b, 0xb94c, 0xb94e, 0xb94f, 0xb950, 0xb951, 0xb953,
+ 0xb954, 0xb955, 0xb957, 0xb958, 0xb95a, 0xb95b, 0xb95d, 0xb95f,
+ 0xb960, 0xb960, 0xb960, 0xb960, 0xb961, 0xb961, 0xb962, 0xb962,
+ 0xb963, 0xb964, 0xb965, 0xb965, 0xb966, 0xb967, 0xb968, 0xb969,
+ 0xb96a, 0xb96b, 0xb96c, 0xb96e, 0xb96f, 0xb970, 0xb971, 0xb973,
+ 0xb974, 0xb975, 0xb977, 0xb978, 0xb97a, 0xb97b, 0xb97d, 0xb97f,
+ 0xb980, 0xb980, 0xb980, 0xb980, 0xb981, 0xb981, 0xb982, 0xb982,
+ 0xb983, 0xb984, 0xb985, 0xb985, 0xb986, 0xb987, 0xb988, 0xb989,
+ 0xb98a, 0xb98b, 0xb98c, 0xb98e, 0xb98f, 0xb990, 0xb991, 0xb993,
+ 0xb994, 0xb995, 0xb997, 0xb998, 0xb99a, 0xb99b, 0xb99d, 0xb99f,
+ 0xb9a0, 0xb9a0, 0xb9a0, 0xb9a0, 0xb9a1, 0xb9a1, 0xb9a2, 0xb9a2,
+ 0xb9a3, 0xb9a4, 0xb9a5, 0xb9a5, 0xb9a6, 0xb9a7, 0xb9a8, 0xb9a9,
+ 0xb9aa, 0xb9ab, 0xb9ac, 0xb9ae, 0xb9af, 0xb9b0, 0xb9b1, 0xb9b3,
+ 0xb9b4, 0xb9b5, 0xb9b7, 0xb9b8, 0xb9ba, 0xb9bb, 0xb9bd, 0xb9bf,
+ 0xb9c0, 0xb9c0, 0xb9c0, 0xb9c0, 0xb9c1, 0xb9c1, 0xb9c2, 0xb9c2,
+ 0xb9c3, 0xb9c4, 0xb9c5, 0xb9c5, 0xb9c6, 0xb9c7, 0xb9c8, 0xb9c9,
+ 0xb9ca, 0xb9cb, 0xb9cc, 0xb9ce, 0xb9cf, 0xb9d0, 0xb9d1, 0xb9d3,
+ 0xb9d4, 0xb9d5, 0xb9d7, 0xb9d8, 0xb9da, 0xb9db, 0xb9dd, 0xb9df,
+ 0xb9e0, 0xb9e0, 0xb9e0, 0xb9e0, 0xb9e1, 0xb9e1, 0xb9e2, 0xb9e2,
+ 0xb9e3, 0xb9e4, 0xb9e5, 0xb9e5, 0xb9e6, 0xb9e7, 0xb9e8, 0xb9e9,
+ 0xb9ea, 0xb9eb, 0xb9ec, 0xb9ee, 0xb9ef, 0xb9f0, 0xb9f1, 0xb9f3,
+ 0xb9f4, 0xb9f5, 0xb9f7, 0xb9f8, 0xb9fa, 0xb9fb, 0xb9fd, 0xb9ff,
+ 0xba00, 0xba00, 0xba00, 0xba00, 0xba01, 0xba01, 0xba02, 0xba02,
+ 0xba03, 0xba04, 0xba05, 0xba05, 0xba06, 0xba07, 0xba08, 0xba09,
+ 0xba0a, 0xba0b, 0xba0c, 0xba0e, 0xba0f, 0xba10, 0xba11, 0xba13,
+ 0xba14, 0xba15, 0xba17, 0xba18, 0xba1a, 0xba1b, 0xba1d, 0xba1f,
+ 0xba20, 0xba20, 0xba20, 0xba20, 0xba21, 0xba21, 0xba22, 0xba22,
+ 0xba23, 0xba24, 0xba25, 0xba25, 0xba26, 0xba27, 0xba28, 0xba29,
+ 0xba2a, 0xba2b, 0xba2c, 0xba2e, 0xba2f, 0xba30, 0xba31, 0xba33,
+ 0xba34, 0xba35, 0xba37, 0xba38, 0xba3a, 0xba3b, 0xba3d, 0xba3f,
+ 0xba40, 0xba40, 0xba40, 0xba40, 0xba41, 0xba41, 0xba42, 0xba42,
+ 0xba43, 0xba44, 0xba45, 0xba45, 0xba46, 0xba47, 0xba48, 0xba49,
+ 0xba4a, 0xba4b, 0xba4c, 0xba4e, 0xba4f, 0xba50, 0xba51, 0xba53,
+ 0xba54, 0xba55, 0xba57, 0xba58, 0xba5a, 0xba5b, 0xba5d, 0xba5f,
+ 0xba60, 0xba60, 0xba60, 0xba60, 0xba61, 0xba61, 0xba62, 0xba62,
+ 0xba63, 0xba64, 0xba65, 0xba65, 0xba66, 0xba67, 0xba68, 0xba69,
+ 0xba6a, 0xba6b, 0xba6c, 0xba6e, 0xba6f, 0xba70, 0xba71, 0xba73,
+ 0xba74, 0xba75, 0xba77, 0xba78, 0xba7a, 0xba7b, 0xba7d, 0xba7f,
+ 0xba80, 0xba80, 0xba80, 0xba80, 0xba81, 0xba81, 0xba82, 0xba82,
+ 0xba83, 0xba84, 0xba85, 0xba85, 0xba86, 0xba87, 0xba88, 0xba89,
+ 0xba8a, 0xba8b, 0xba8c, 0xba8e, 0xba8f, 0xba90, 0xba91, 0xba93,
+ 0xba94, 0xba95, 0xba97, 0xba98, 0xba9a, 0xba9b, 0xba9d, 0xba9f,
+ 0xbaa0, 0xbaa0, 0xbaa0, 0xbaa0, 0xbaa1, 0xbaa1, 0xbaa2, 0xbaa2,
+ 0xbaa3, 0xbaa4, 0xbaa5, 0xbaa5, 0xbaa6, 0xbaa7, 0xbaa8, 0xbaa9,
+ 0xbaaa, 0xbaab, 0xbaac, 0xbaae, 0xbaaf, 0xbab0, 0xbab1, 0xbab3,
+ 0xbab4, 0xbab5, 0xbab7, 0xbab8, 0xbaba, 0xbabb, 0xbabd, 0xbabf,
+ 0xbac0, 0xbac0, 0xbac0, 0xbac0, 0xbac1, 0xbac1, 0xbac2, 0xbac2,
+ 0xbac3, 0xbac4, 0xbac5, 0xbac5, 0xbac6, 0xbac7, 0xbac8, 0xbac9,
+ 0xbaca, 0xbacb, 0xbacc, 0xbace, 0xbacf, 0xbad0, 0xbad1, 0xbad3,
+ 0xbad4, 0xbad5, 0xbad7, 0xbad8, 0xbada, 0xbadb, 0xbadd, 0xbadf,
+ 0xbae0, 0xbae0, 0xbae0, 0xbae0, 0xbae1, 0xbae1, 0xbae2, 0xbae2,
+ 0xbae3, 0xbae4, 0xbae5, 0xbae5, 0xbae6, 0xbae7, 0xbae8, 0xbae9,
+ 0xbaea, 0xbaeb, 0xbaec, 0xbaee, 0xbaef, 0xbaf0, 0xbaf1, 0xbaf3,
+ 0xbaf4, 0xbaf5, 0xbaf7, 0xbaf8, 0xbafa, 0xbafb, 0xbafd, 0xbaff,
+ 0xbb00, 0xbb00, 0xbb00, 0xbb00, 0xbb01, 0xbb01, 0xbb02, 0xbb02,
+ 0xbb03, 0xbb04, 0xbb05, 0xbb05, 0xbb06, 0xbb07, 0xbb08, 0xbb09,
+ 0xbb0a, 0xbb0b, 0xbb0c, 0xbb0e, 0xbb0f, 0xbb10, 0xbb11, 0xbb13,
+ 0xbb14, 0xbb15, 0xbb17, 0xbb18, 0xbb1a, 0xbb1b, 0xbb1d, 0xbb1f,
+ 0xbb20, 0xbb20, 0xbb20, 0xbb20, 0xbb21, 0xbb21, 0xbb22, 0xbb22,
+ 0xbb23, 0xbb24, 0xbb25, 0xbb25, 0xbb26, 0xbb27, 0xbb28, 0xbb29,
+ 0xbb2a, 0xbb2b, 0xbb2c, 0xbb2e, 0xbb2f, 0xbb30, 0xbb31, 0xbb33,
+ 0xbb34, 0xbb35, 0xbb37, 0xbb38, 0xbb3a, 0xbb3b, 0xbb3d, 0xbb3f,
+ 0xbb40, 0xbb40, 0xbb40, 0xbb40, 0xbb41, 0xbb41, 0xbb42, 0xbb42,
+ 0xbb43, 0xbb44, 0xbb45, 0xbb45, 0xbb46, 0xbb47, 0xbb48, 0xbb49,
+ 0xbb4a, 0xbb4b, 0xbb4c, 0xbb4e, 0xbb4f, 0xbb50, 0xbb51, 0xbb53,
+ 0xbb54, 0xbb55, 0xbb57, 0xbb58, 0xbb5a, 0xbb5b, 0xbb5d, 0xbb5f,
+ 0xbb80, 0xbb80, 0xbb80, 0xbb80, 0xbb81, 0xbb81, 0xbb82, 0xbb82,
+ 0xbb83, 0xbb84, 0xbb85, 0xbb85, 0xbb86, 0xbb87, 0xbb88, 0xbb89,
+ 0xbb8a, 0xbb8b, 0xbb8c, 0xbb8e, 0xbb8f, 0xbb90, 0xbb91, 0xbb93,
+ 0xbb94, 0xbb95, 0xbb97, 0xbb98, 0xbb9a, 0xbb9b, 0xbb9d, 0xbb9f,
+ 0xbba0, 0xbba0, 0xbba0, 0xbba0, 0xbba1, 0xbba1, 0xbba2, 0xbba2,
+ 0xbba3, 0xbba4, 0xbba5, 0xbba5, 0xbba6, 0xbba7, 0xbba8, 0xbba9,
+ 0xbbaa, 0xbbab, 0xbbac, 0xbbae, 0xbbaf, 0xbbb0, 0xbbb1, 0xbbb3,
+ 0xbbb4, 0xbbb5, 0xbbb7, 0xbbb8, 0xbbba, 0xbbbb, 0xbbbd, 0xbbbf,
+ 0xbbc0, 0xbbc0, 0xbbc0, 0xbbc0, 0xbbc1, 0xbbc1, 0xbbc2, 0xbbc2,
+ 0xbbc3, 0xbbc4, 0xbbc5, 0xbbc5, 0xbbc6, 0xbbc7, 0xbbc8, 0xbbc9,
+ 0xbbca, 0xbbcb, 0xbbcc, 0xbbce, 0xbbcf, 0xbbd0, 0xbbd1, 0xbbd3,
+ 0xbbd4, 0xbbd5, 0xbbd7, 0xbbd8, 0xbbda, 0xbbdb, 0xbbdd, 0xbbdf,
+ 0xbbe0, 0xbbe0, 0xbbe0, 0xbbe0, 0xbbe1, 0xbbe1, 0xbbe2, 0xbbe2,
+ 0xbbe3, 0xbbe4, 0xbbe5, 0xbbe5, 0xbbe6, 0xbbe7, 0xbbe8, 0xbbe9,
+ 0xbbea, 0xbbeb, 0xbbec, 0xbbee, 0xbbef, 0xbbf0, 0xbbf1, 0xbbf3,
+ 0xbbf4, 0xbbf5, 0xbbf7, 0xbbf8, 0xbbfa, 0xbbfb, 0xbbfd, 0xbbff,
+ 0xbc00, 0xbc00, 0xbc00, 0xbc00, 0xbc01, 0xbc01, 0xbc02, 0xbc02,
+ 0xbc03, 0xbc04, 0xbc05, 0xbc05, 0xbc06, 0xbc07, 0xbc08, 0xbc09,
+ 0xbc0a, 0xbc0b, 0xbc0c, 0xbc0e, 0xbc0f, 0xbc10, 0xbc11, 0xbc13,
+ 0xbc14, 0xbc15, 0xbc17, 0xbc18, 0xbc1a, 0xbc1b, 0xbc1d, 0xbc1f,
+ 0xbc40, 0xbc40, 0xbc40, 0xbc40, 0xbc41, 0xbc41, 0xbc42, 0xbc42,
+ 0xbc43, 0xbc44, 0xbc45, 0xbc45, 0xbc46, 0xbc47, 0xbc48, 0xbc49,
+ 0xbc4a, 0xbc4b, 0xbc4c, 0xbc4e, 0xbc4f, 0xbc50, 0xbc51, 0xbc53,
+ 0xbc54, 0xbc55, 0xbc57, 0xbc58, 0xbc5a, 0xbc5b, 0xbc5d, 0xbc5f,
+ 0xbc60, 0xbc60, 0xbc60, 0xbc60, 0xbc61, 0xbc61, 0xbc62, 0xbc62,
+ 0xbc63, 0xbc64, 0xbc65, 0xbc65, 0xbc66, 0xbc67, 0xbc68, 0xbc69,
+ 0xbc6a, 0xbc6b, 0xbc6c, 0xbc6e, 0xbc6f, 0xbc70, 0xbc71, 0xbc73,
+ 0xbc74, 0xbc75, 0xbc77, 0xbc78, 0xbc7a, 0xbc7b, 0xbc7d, 0xbc7f,
+ 0xbc80, 0xbc80, 0xbc80, 0xbc80, 0xbc81, 0xbc81, 0xbc82, 0xbc82,
+ 0xbc83, 0xbc84, 0xbc85, 0xbc85, 0xbc86, 0xbc87, 0xbc88, 0xbc89,
+ 0xbc8a, 0xbc8b, 0xbc8c, 0xbc8e, 0xbc8f, 0xbc90, 0xbc91, 0xbc93,
+ 0xbc94, 0xbc95, 0xbc97, 0xbc98, 0xbc9a, 0xbc9b, 0xbc9d, 0xbc9f,
+ 0xbcc0, 0xbcc0, 0xbcc0, 0xbcc0, 0xbcc1, 0xbcc1, 0xbcc2, 0xbcc2,
+ 0xbcc3, 0xbcc4, 0xbcc5, 0xbcc5, 0xbcc6, 0xbcc7, 0xbcc8, 0xbcc9,
+ 0xbcca, 0xbccb, 0xbccc, 0xbcce, 0xbccf, 0xbcd0, 0xbcd1, 0xbcd3,
+ 0xbcd4, 0xbcd5, 0xbcd7, 0xbcd8, 0xbcda, 0xbcdb, 0xbcdd, 0xbcdf,
+ 0xbce0, 0xbce0, 0xbce0, 0xbce0, 0xbce1, 0xbce1, 0xbce2, 0xbce2,
+ 0xbce3, 0xbce4, 0xbce5, 0xbce5, 0xbce6, 0xbce7, 0xbce8, 0xbce9,
+ 0xbcea, 0xbceb, 0xbcec, 0xbcee, 0xbcef, 0xbcf0, 0xbcf1, 0xbcf3,
+ 0xbcf4, 0xbcf5, 0xbcf7, 0xbcf8, 0xbcfa, 0xbcfb, 0xbcfd, 0xbcff,
+ 0xbd00, 0xbd00, 0xbd00, 0xbd00, 0xbd01, 0xbd01, 0xbd02, 0xbd02,
+ 0xbd03, 0xbd04, 0xbd05, 0xbd05, 0xbd06, 0xbd07, 0xbd08, 0xbd09,
+ 0xbd0a, 0xbd0b, 0xbd0c, 0xbd0e, 0xbd0f, 0xbd10, 0xbd11, 0xbd13,
+ 0xbd14, 0xbd15, 0xbd17, 0xbd18, 0xbd1a, 0xbd1b, 0xbd1d, 0xbd1f,
+ 0xbd40, 0xbd40, 0xbd40, 0xbd40, 0xbd41, 0xbd41, 0xbd42, 0xbd42,
+ 0xbd43, 0xbd44, 0xbd45, 0xbd45, 0xbd46, 0xbd47, 0xbd48, 0xbd49,
+ 0xbd4a, 0xbd4b, 0xbd4c, 0xbd4e, 0xbd4f, 0xbd50, 0xbd51, 0xbd53,
+ 0xbd54, 0xbd55, 0xbd57, 0xbd58, 0xbd5a, 0xbd5b, 0xbd5d, 0xbd5f,
+ 0xbd60, 0xbd60, 0xbd60, 0xbd60, 0xbd61, 0xbd61, 0xbd62, 0xbd62,
+ 0xbd63, 0xbd64, 0xbd65, 0xbd65, 0xbd66, 0xbd67, 0xbd68, 0xbd69,
+ 0xbd6a, 0xbd6b, 0xbd6c, 0xbd6e, 0xbd6f, 0xbd70, 0xbd71, 0xbd73,
+ 0xbd74, 0xbd75, 0xbd77, 0xbd78, 0xbd7a, 0xbd7b, 0xbd7d, 0xbd7f,
+ 0xbd80, 0xbd80, 0xbd80, 0xbd80, 0xbd81, 0xbd81, 0xbd82, 0xbd82,
+ 0xbd83, 0xbd84, 0xbd85, 0xbd85, 0xbd86, 0xbd87, 0xbd88, 0xbd89,
+ 0xbd8a, 0xbd8b, 0xbd8c, 0xbd8e, 0xbd8f, 0xbd90, 0xbd91, 0xbd93,
+ 0xbd94, 0xbd95, 0xbd97, 0xbd98, 0xbd9a, 0xbd9b, 0xbd9d, 0xbd9f,
+ 0xbdc0, 0xbdc0, 0xbdc0, 0xbdc0, 0xbdc1, 0xbdc1, 0xbdc2, 0xbdc2,
+ 0xbdc3, 0xbdc4, 0xbdc5, 0xbdc5, 0xbdc6, 0xbdc7, 0xbdc8, 0xbdc9,
+ 0xbdca, 0xbdcb, 0xbdcc, 0xbdce, 0xbdcf, 0xbdd0, 0xbdd1, 0xbdd3,
+ 0xbdd4, 0xbdd5, 0xbdd7, 0xbdd8, 0xbdda, 0xbddb, 0xbddd, 0xbddf,
+ 0xbde0, 0xbde0, 0xbde0, 0xbde0, 0xbde1, 0xbde1, 0xbde2, 0xbde2,
+ 0xbde3, 0xbde4, 0xbde5, 0xbde5, 0xbde6, 0xbde7, 0xbde8, 0xbde9,
+ 0xbdea, 0xbdeb, 0xbdec, 0xbdee, 0xbdef, 0xbdf0, 0xbdf1, 0xbdf3,
+ 0xbdf4, 0xbdf5, 0xbdf7, 0xbdf8, 0xbdfa, 0xbdfb, 0xbdfd, 0xbdff,
+ 0xbe20, 0xbe20, 0xbe20, 0xbe20, 0xbe21, 0xbe21, 0xbe22, 0xbe22,
+ 0xbe23, 0xbe24, 0xbe25, 0xbe25, 0xbe26, 0xbe27, 0xbe28, 0xbe29,
+ 0xbe2a, 0xbe2b, 0xbe2c, 0xbe2e, 0xbe2f, 0xbe30, 0xbe31, 0xbe33,
+ 0xbe34, 0xbe35, 0xbe37, 0xbe38, 0xbe3a, 0xbe3b, 0xbe3d, 0xbe3f,
+ 0xbe40, 0xbe40, 0xbe40, 0xbe40, 0xbe41, 0xbe41, 0xbe42, 0xbe42,
+ 0xbe43, 0xbe44, 0xbe45, 0xbe45, 0xbe46, 0xbe47, 0xbe48, 0xbe49,
+ 0xbe4a, 0xbe4b, 0xbe4c, 0xbe4e, 0xbe4f, 0xbe50, 0xbe51, 0xbe53,
+ 0xbe54, 0xbe55, 0xbe57, 0xbe58, 0xbe5a, 0xbe5b, 0xbe5d, 0xbe5f,
+ 0xbe80, 0xbe80, 0xbe80, 0xbe80, 0xbe81, 0xbe81, 0xbe82, 0xbe82,
+ 0xbe83, 0xbe84, 0xbe85, 0xbe85, 0xbe86, 0xbe87, 0xbe88, 0xbe89,
+ 0xbe8a, 0xbe8b, 0xbe8c, 0xbe8e, 0xbe8f, 0xbe90, 0xbe91, 0xbe93,
+ 0xbe94, 0xbe95, 0xbe97, 0xbe98, 0xbe9a, 0xbe9b, 0xbe9d, 0xbe9f,
+ 0xbea0, 0xbea0, 0xbea0, 0xbea0, 0xbea1, 0xbea1, 0xbea2, 0xbea2,
+ 0xbea3, 0xbea4, 0xbea5, 0xbea5, 0xbea6, 0xbea7, 0xbea8, 0xbea9,
+ 0xbeaa, 0xbeab, 0xbeac, 0xbeae, 0xbeaf, 0xbeb0, 0xbeb1, 0xbeb3,
+ 0xbeb4, 0xbeb5, 0xbeb7, 0xbeb8, 0xbeba, 0xbebb, 0xbebd, 0xbebf,
+ 0xbee0, 0xbee0, 0xbee0, 0xbee0, 0xbee1, 0xbee1, 0xbee2, 0xbee2,
+ 0xbee3, 0xbee4, 0xbee5, 0xbee5, 0xbee6, 0xbee7, 0xbee8, 0xbee9,
+ 0xbeea, 0xbeeb, 0xbeec, 0xbeee, 0xbeef, 0xbef0, 0xbef1, 0xbef3,
+ 0xbef4, 0xbef5, 0xbef7, 0xbef8, 0xbefa, 0xbefb, 0xbefd, 0xbeff,
+ 0xbf00, 0xbf00, 0xbf00, 0xbf00, 0xbf01, 0xbf01, 0xbf02, 0xbf02,
+ 0xbf03, 0xbf04, 0xbf05, 0xbf05, 0xbf06, 0xbf07, 0xbf08, 0xbf09,
+ 0xbf0a, 0xbf0b, 0xbf0c, 0xbf0e, 0xbf0f, 0xbf10, 0xbf11, 0xbf13,
+ 0xbf14, 0xbf15, 0xbf17, 0xbf18, 0xbf1a, 0xbf1b, 0xbf1d, 0xbf1f,
+ 0xbf40, 0xbf40, 0xbf40, 0xbf40, 0xbf41, 0xbf41, 0xbf42, 0xbf42,
+ 0xbf43, 0xbf44, 0xbf45, 0xbf45, 0xbf46, 0xbf47, 0xbf48, 0xbf49,
+ 0xbf4a, 0xbf4b, 0xbf4c, 0xbf4e, 0xbf4f, 0xbf50, 0xbf51, 0xbf53,
+ 0xbf54, 0xbf55, 0xbf57, 0xbf58, 0xbf5a, 0xbf5b, 0xbf5d, 0xbf5f,
+ 0xbf60, 0xbf60, 0xbf60, 0xbf60, 0xbf61, 0xbf61, 0xbf62, 0xbf62,
+ 0xbf63, 0xbf64, 0xbf65, 0xbf65, 0xbf66, 0xbf67, 0xbf68, 0xbf69,
+ 0xbf6a, 0xbf6b, 0xbf6c, 0xbf6e, 0xbf6f, 0xbf70, 0xbf71, 0xbf73,
+ 0xbf74, 0xbf75, 0xbf77, 0xbf78, 0xbf7a, 0xbf7b, 0xbf7d, 0xbf7f,
+ 0xbfa0, 0xbfa0, 0xbfa0, 0xbfa0, 0xbfa1, 0xbfa1, 0xbfa2, 0xbfa2,
+ 0xbfa3, 0xbfa4, 0xbfa5, 0xbfa5, 0xbfa6, 0xbfa7, 0xbfa8, 0xbfa9,
+ 0xbfaa, 0xbfab, 0xbfac, 0xbfae, 0xbfaf, 0xbfb0, 0xbfb1, 0xbfb3,
+ 0xbfb4, 0xbfb5, 0xbfb7, 0xbfb8, 0xbfba, 0xbfbb, 0xbfbd, 0xbfbf,
+ 0xbfe0, 0xbfe0, 0xbfe0, 0xbfe0, 0xbfe1, 0xbfe1, 0xbfe2, 0xbfe2,
+ 0xbfe3, 0xbfe4, 0xbfe5, 0xbfe5, 0xbfe6, 0xbfe7, 0xbfe8, 0xbfe9,
+ 0xbfea, 0xbfeb, 0xbfec, 0xbfee, 0xbfef, 0xbff0, 0xbff1, 0xbff3,
+ 0xbff4, 0xbff5, 0xbff7, 0xbff8, 0xbffa, 0xbffb, 0xbffd, 0xbfff,
+ 0xc000, 0xc000, 0xc000, 0xc000, 0xc001, 0xc001, 0xc002, 0xc002,
+ 0xc003, 0xc004, 0xc005, 0xc005, 0xc006, 0xc007, 0xc008, 0xc009,
+ 0xc00a, 0xc00b, 0xc00c, 0xc00e, 0xc00f, 0xc010, 0xc011, 0xc013,
+ 0xc014, 0xc015, 0xc017, 0xc018, 0xc01a, 0xc01b, 0xc01d, 0xc01f,
+ 0xc000, 0xc000, 0xc000, 0xc000, 0xc001, 0xc001, 0xc002, 0xc002,
+ 0xc003, 0xc004, 0xc005, 0xc005, 0xc006, 0xc007, 0xc008, 0xc009,
+ 0xc00a, 0xc00b, 0xc00c, 0xc00e, 0xc00f, 0xc010, 0xc011, 0xc013,
+ 0xc014, 0xc015, 0xc017, 0xc018, 0xc01a, 0xc01b, 0xc01d, 0xc01f,
+ 0xc000, 0xc000, 0xc000, 0xc000, 0xc001, 0xc001, 0xc002, 0xc002,
+ 0xc003, 0xc004, 0xc005, 0xc005, 0xc006, 0xc007, 0xc008, 0xc009,
+ 0xc00a, 0xc00b, 0xc00c, 0xc00e, 0xc00f, 0xc010, 0xc011, 0xc013,
+ 0xc014, 0xc015, 0xc017, 0xc018, 0xc01a, 0xc01b, 0xc01d, 0xc01f,
+ 0xc000, 0xc000, 0xc000, 0xc000, 0xc001, 0xc001, 0xc002, 0xc002,
+ 0xc003, 0xc004, 0xc005, 0xc005, 0xc006, 0xc007, 0xc008, 0xc009,
+ 0xc00a, 0xc00b, 0xc00c, 0xc00e, 0xc00f, 0xc010, 0xc011, 0xc013,
+ 0xc014, 0xc015, 0xc017, 0xc018, 0xc01a, 0xc01b, 0xc01d, 0xc01f,
+ 0xc000, 0xc000, 0xc000, 0xc000, 0xc001, 0xc001, 0xc002, 0xc002,
+ 0xc003, 0xc004, 0xc005, 0xc005, 0xc006, 0xc007, 0xc008, 0xc009,
+ 0xc00a, 0xc00b, 0xc00c, 0xc00e, 0xc00f, 0xc010, 0xc011, 0xc013,
+ 0xc014, 0xc015, 0xc017, 0xc018, 0xc01a, 0xc01b, 0xc01d, 0xc01f,
+ 0xc020, 0xc020, 0xc020, 0xc020, 0xc021, 0xc021, 0xc022, 0xc022,
+ 0xc023, 0xc024, 0xc025, 0xc025, 0xc026, 0xc027, 0xc028, 0xc029,
+ 0xc02a, 0xc02b, 0xc02c, 0xc02e, 0xc02f, 0xc030, 0xc031, 0xc033,
+ 0xc034, 0xc035, 0xc037, 0xc038, 0xc03a, 0xc03b, 0xc03d, 0xc03f,
+ 0xc020, 0xc020, 0xc020, 0xc020, 0xc021, 0xc021, 0xc022, 0xc022,
+ 0xc023, 0xc024, 0xc025, 0xc025, 0xc026, 0xc027, 0xc028, 0xc029,
+ 0xc02a, 0xc02b, 0xc02c, 0xc02e, 0xc02f, 0xc030, 0xc031, 0xc033,
+ 0xc034, 0xc035, 0xc037, 0xc038, 0xc03a, 0xc03b, 0xc03d, 0xc03f,
+ 0xc020, 0xc020, 0xc020, 0xc020, 0xc021, 0xc021, 0xc022, 0xc022,
+ 0xc023, 0xc024, 0xc025, 0xc025, 0xc026, 0xc027, 0xc028, 0xc029,
+ 0xc02a, 0xc02b, 0xc02c, 0xc02e, 0xc02f, 0xc030, 0xc031, 0xc033,
+ 0xc034, 0xc035, 0xc037, 0xc038, 0xc03a, 0xc03b, 0xc03d, 0xc03f,
+ 0xc040, 0xc040, 0xc040, 0xc040, 0xc041, 0xc041, 0xc042, 0xc042,
+ 0xc043, 0xc044, 0xc045, 0xc045, 0xc046, 0xc047, 0xc048, 0xc049,
+ 0xc04a, 0xc04b, 0xc04c, 0xc04e, 0xc04f, 0xc050, 0xc051, 0xc053,
+ 0xc054, 0xc055, 0xc057, 0xc058, 0xc05a, 0xc05b, 0xc05d, 0xc05f,
+ 0xc040, 0xc040, 0xc040, 0xc040, 0xc041, 0xc041, 0xc042, 0xc042,
+ 0xc043, 0xc044, 0xc045, 0xc045, 0xc046, 0xc047, 0xc048, 0xc049,
+ 0xc04a, 0xc04b, 0xc04c, 0xc04e, 0xc04f, 0xc050, 0xc051, 0xc053,
+ 0xc054, 0xc055, 0xc057, 0xc058, 0xc05a, 0xc05b, 0xc05d, 0xc05f,
+ 0xc060, 0xc060, 0xc060, 0xc060, 0xc061, 0xc061, 0xc062, 0xc062,
+ 0xc063, 0xc064, 0xc065, 0xc065, 0xc066, 0xc067, 0xc068, 0xc069,
+ 0xc06a, 0xc06b, 0xc06c, 0xc06e, 0xc06f, 0xc070, 0xc071, 0xc073,
+ 0xc074, 0xc075, 0xc077, 0xc078, 0xc07a, 0xc07b, 0xc07d, 0xc07f,
+ 0xc060, 0xc060, 0xc060, 0xc060, 0xc061, 0xc061, 0xc062, 0xc062,
+ 0xc063, 0xc064, 0xc065, 0xc065, 0xc066, 0xc067, 0xc068, 0xc069,
+ 0xc06a, 0xc06b, 0xc06c, 0xc06e, 0xc06f, 0xc070, 0xc071, 0xc073,
+ 0xc074, 0xc075, 0xc077, 0xc078, 0xc07a, 0xc07b, 0xc07d, 0xc07f,
+ 0xc080, 0xc080, 0xc080, 0xc080, 0xc081, 0xc081, 0xc082, 0xc082,
+ 0xc083, 0xc084, 0xc085, 0xc085, 0xc086, 0xc087, 0xc088, 0xc089,
+ 0xc08a, 0xc08b, 0xc08c, 0xc08e, 0xc08f, 0xc090, 0xc091, 0xc093,
+ 0xc094, 0xc095, 0xc097, 0xc098, 0xc09a, 0xc09b, 0xc09d, 0xc09f,
+ 0xc0a0, 0xc0a0, 0xc0a0, 0xc0a0, 0xc0a1, 0xc0a1, 0xc0a2, 0xc0a2,
+ 0xc0a3, 0xc0a4, 0xc0a5, 0xc0a5, 0xc0a6, 0xc0a7, 0xc0a8, 0xc0a9,
+ 0xc0aa, 0xc0ab, 0xc0ac, 0xc0ae, 0xc0af, 0xc0b0, 0xc0b1, 0xc0b3,
+ 0xc0b4, 0xc0b5, 0xc0b7, 0xc0b8, 0xc0ba, 0xc0bb, 0xc0bd, 0xc0bf,
+ 0xc0a0, 0xc0a0, 0xc0a0, 0xc0a0, 0xc0a1, 0xc0a1, 0xc0a2, 0xc0a2,
+ 0xc0a3, 0xc0a4, 0xc0a5, 0xc0a5, 0xc0a6, 0xc0a7, 0xc0a8, 0xc0a9,
+ 0xc0aa, 0xc0ab, 0xc0ac, 0xc0ae, 0xc0af, 0xc0b0, 0xc0b1, 0xc0b3,
+ 0xc0b4, 0xc0b5, 0xc0b7, 0xc0b8, 0xc0ba, 0xc0bb, 0xc0bd, 0xc0bf,
+ 0xc0c0, 0xc0c0, 0xc0c0, 0xc0c0, 0xc0c1, 0xc0c1, 0xc0c2, 0xc0c2,
+ 0xc0c3, 0xc0c4, 0xc0c5, 0xc0c5, 0xc0c6, 0xc0c7, 0xc0c8, 0xc0c9,
+ 0xc0ca, 0xc0cb, 0xc0cc, 0xc0ce, 0xc0cf, 0xc0d0, 0xc0d1, 0xc0d3,
+ 0xc0d4, 0xc0d5, 0xc0d7, 0xc0d8, 0xc0da, 0xc0db, 0xc0dd, 0xc0df,
+ 0xc0e0, 0xc0e0, 0xc0e0, 0xc0e0, 0xc0e1, 0xc0e1, 0xc0e2, 0xc0e2,
+ 0xc0e3, 0xc0e4, 0xc0e5, 0xc0e5, 0xc0e6, 0xc0e7, 0xc0e8, 0xc0e9,
+ 0xc0ea, 0xc0eb, 0xc0ec, 0xc0ee, 0xc0ef, 0xc0f0, 0xc0f1, 0xc0f3,
+ 0xc0f4, 0xc0f5, 0xc0f7, 0xc0f8, 0xc0fa, 0xc0fb, 0xc0fd, 0xc0ff,
+ 0xc0e0, 0xc0e0, 0xc0e0, 0xc0e0, 0xc0e1, 0xc0e1, 0xc0e2, 0xc0e2,
+ 0xc0e3, 0xc0e4, 0xc0e5, 0xc0e5, 0xc0e6, 0xc0e7, 0xc0e8, 0xc0e9,
+ 0xc0ea, 0xc0eb, 0xc0ec, 0xc0ee, 0xc0ef, 0xc0f0, 0xc0f1, 0xc0f3,
+ 0xc0f4, 0xc0f5, 0xc0f7, 0xc0f8, 0xc0fa, 0xc0fb, 0xc0fd, 0xc0ff,
+ 0xc100, 0xc100, 0xc100, 0xc100, 0xc101, 0xc101, 0xc102, 0xc102,
+ 0xc103, 0xc104, 0xc105, 0xc105, 0xc106, 0xc107, 0xc108, 0xc109,
+ 0xc10a, 0xc10b, 0xc10c, 0xc10e, 0xc10f, 0xc110, 0xc111, 0xc113,
+ 0xc114, 0xc115, 0xc117, 0xc118, 0xc11a, 0xc11b, 0xc11d, 0xc11f,
+ 0xc120, 0xc120, 0xc120, 0xc120, 0xc121, 0xc121, 0xc122, 0xc122,
+ 0xc123, 0xc124, 0xc125, 0xc125, 0xc126, 0xc127, 0xc128, 0xc129,
+ 0xc12a, 0xc12b, 0xc12c, 0xc12e, 0xc12f, 0xc130, 0xc131, 0xc133,
+ 0xc134, 0xc135, 0xc137, 0xc138, 0xc13a, 0xc13b, 0xc13d, 0xc13f,
+ 0xc140, 0xc140, 0xc140, 0xc140, 0xc141, 0xc141, 0xc142, 0xc142,
+ 0xc143, 0xc144, 0xc145, 0xc145, 0xc146, 0xc147, 0xc148, 0xc149,
+ 0xc14a, 0xc14b, 0xc14c, 0xc14e, 0xc14f, 0xc150, 0xc151, 0xc153,
+ 0xc154, 0xc155, 0xc157, 0xc158, 0xc15a, 0xc15b, 0xc15d, 0xc15f,
+ 0xc140, 0xc140, 0xc140, 0xc140, 0xc141, 0xc141, 0xc142, 0xc142,
+ 0xc143, 0xc144, 0xc145, 0xc145, 0xc146, 0xc147, 0xc148, 0xc149,
+ 0xc14a, 0xc14b, 0xc14c, 0xc14e, 0xc14f, 0xc150, 0xc151, 0xc153,
+ 0xc154, 0xc155, 0xc157, 0xc158, 0xc15a, 0xc15b, 0xc15d, 0xc15f,
+ 0xc160, 0xc160, 0xc160, 0xc160, 0xc161, 0xc161, 0xc162, 0xc162,
+ 0xc163, 0xc164, 0xc165, 0xc165, 0xc166, 0xc167, 0xc168, 0xc169,
+ 0xc16a, 0xc16b, 0xc16c, 0xc16e, 0xc16f, 0xc170, 0xc171, 0xc173,
+ 0xc174, 0xc175, 0xc177, 0xc178, 0xc17a, 0xc17b, 0xc17d, 0xc17f,
+ 0xc180, 0xc180, 0xc180, 0xc180, 0xc181, 0xc181, 0xc182, 0xc182,
+ 0xc183, 0xc184, 0xc185, 0xc185, 0xc186, 0xc187, 0xc188, 0xc189,
+ 0xc18a, 0xc18b, 0xc18c, 0xc18e, 0xc18f, 0xc190, 0xc191, 0xc193,
+ 0xc194, 0xc195, 0xc197, 0xc198, 0xc19a, 0xc19b, 0xc19d, 0xc19f,
+ 0xc1a0, 0xc1a0, 0xc1a0, 0xc1a0, 0xc1a1, 0xc1a1, 0xc1a2, 0xc1a2,
+ 0xc1a3, 0xc1a4, 0xc1a5, 0xc1a5, 0xc1a6, 0xc1a7, 0xc1a8, 0xc1a9,
+ 0xc1aa, 0xc1ab, 0xc1ac, 0xc1ae, 0xc1af, 0xc1b0, 0xc1b1, 0xc1b3,
+ 0xc1b4, 0xc1b5, 0xc1b7, 0xc1b8, 0xc1ba, 0xc1bb, 0xc1bd, 0xc1bf,
+ 0xc1c0, 0xc1c0, 0xc1c0, 0xc1c0, 0xc1c1, 0xc1c1, 0xc1c2, 0xc1c2,
+ 0xc1c3, 0xc1c4, 0xc1c5, 0xc1c5, 0xc1c6, 0xc1c7, 0xc1c8, 0xc1c9,
+ 0xc1ca, 0xc1cb, 0xc1cc, 0xc1ce, 0xc1cf, 0xc1d0, 0xc1d1, 0xc1d3,
+ 0xc1d4, 0xc1d5, 0xc1d7, 0xc1d8, 0xc1da, 0xc1db, 0xc1dd, 0xc1df,
+ 0xc1e0, 0xc1e0, 0xc1e0, 0xc1e0, 0xc1e1, 0xc1e1, 0xc1e2, 0xc1e2,
+ 0xc1e3, 0xc1e4, 0xc1e5, 0xc1e5, 0xc1e6, 0xc1e7, 0xc1e8, 0xc1e9,
+ 0xc1ea, 0xc1eb, 0xc1ec, 0xc1ee, 0xc1ef, 0xc1f0, 0xc1f1, 0xc1f3,
+ 0xc1f4, 0xc1f5, 0xc1f7, 0xc1f8, 0xc1fa, 0xc1fb, 0xc1fd, 0xc1ff,
+ 0xc200, 0xc200, 0xc200, 0xc200, 0xc201, 0xc201, 0xc202, 0xc202,
+ 0xc203, 0xc204, 0xc205, 0xc205, 0xc206, 0xc207, 0xc208, 0xc209,
+ 0xc20a, 0xc20b, 0xc20c, 0xc20e, 0xc20f, 0xc210, 0xc211, 0xc213,
+ 0xc214, 0xc215, 0xc217, 0xc218, 0xc21a, 0xc21b, 0xc21d, 0xc21f,
+ 0xc220, 0xc220, 0xc220, 0xc220, 0xc221, 0xc221, 0xc222, 0xc222,
+ 0xc223, 0xc224, 0xc225, 0xc225, 0xc226, 0xc227, 0xc228, 0xc229,
+ 0xc22a, 0xc22b, 0xc22c, 0xc22e, 0xc22f, 0xc230, 0xc231, 0xc233,
+ 0xc234, 0xc235, 0xc237, 0xc238, 0xc23a, 0xc23b, 0xc23d, 0xc23f,
+ 0xc240, 0xc240, 0xc240, 0xc240, 0xc241, 0xc241, 0xc242, 0xc242,
+ 0xc243, 0xc244, 0xc245, 0xc245, 0xc246, 0xc247, 0xc248, 0xc249,
+ 0xc24a, 0xc24b, 0xc24c, 0xc24e, 0xc24f, 0xc250, 0xc251, 0xc253,
+ 0xc254, 0xc255, 0xc257, 0xc258, 0xc25a, 0xc25b, 0xc25d, 0xc25f,
+ 0xc260, 0xc260, 0xc260, 0xc260, 0xc261, 0xc261, 0xc262, 0xc262,
+ 0xc263, 0xc264, 0xc265, 0xc265, 0xc266, 0xc267, 0xc268, 0xc269,
+ 0xc26a, 0xc26b, 0xc26c, 0xc26e, 0xc26f, 0xc270, 0xc271, 0xc273,
+ 0xc274, 0xc275, 0xc277, 0xc278, 0xc27a, 0xc27b, 0xc27d, 0xc27f,
+ 0xc280, 0xc280, 0xc280, 0xc280, 0xc281, 0xc281, 0xc282, 0xc282,
+ 0xc283, 0xc284, 0xc285, 0xc285, 0xc286, 0xc287, 0xc288, 0xc289,
+ 0xc28a, 0xc28b, 0xc28c, 0xc28e, 0xc28f, 0xc290, 0xc291, 0xc293,
+ 0xc294, 0xc295, 0xc297, 0xc298, 0xc29a, 0xc29b, 0xc29d, 0xc29f,
+ 0xc2a0, 0xc2a0, 0xc2a0, 0xc2a0, 0xc2a1, 0xc2a1, 0xc2a2, 0xc2a2,
+ 0xc2a3, 0xc2a4, 0xc2a5, 0xc2a5, 0xc2a6, 0xc2a7, 0xc2a8, 0xc2a9,
+ 0xc2aa, 0xc2ab, 0xc2ac, 0xc2ae, 0xc2af, 0xc2b0, 0xc2b1, 0xc2b3,
+ 0xc2b4, 0xc2b5, 0xc2b7, 0xc2b8, 0xc2ba, 0xc2bb, 0xc2bd, 0xc2bf,
+ 0xc2c0, 0xc2c0, 0xc2c0, 0xc2c0, 0xc2c1, 0xc2c1, 0xc2c2, 0xc2c2,
+ 0xc2c3, 0xc2c4, 0xc2c5, 0xc2c5, 0xc2c6, 0xc2c7, 0xc2c8, 0xc2c9,
+ 0xc2ca, 0xc2cb, 0xc2cc, 0xc2ce, 0xc2cf, 0xc2d0, 0xc2d1, 0xc2d3,
+ 0xc2d4, 0xc2d5, 0xc2d7, 0xc2d8, 0xc2da, 0xc2db, 0xc2dd, 0xc2df,
+ 0xc2e0, 0xc2e0, 0xc2e0, 0xc2e0, 0xc2e1, 0xc2e1, 0xc2e2, 0xc2e2,
+ 0xc2e3, 0xc2e4, 0xc2e5, 0xc2e5, 0xc2e6, 0xc2e7, 0xc2e8, 0xc2e9,
+ 0xc2ea, 0xc2eb, 0xc2ec, 0xc2ee, 0xc2ef, 0xc2f0, 0xc2f1, 0xc2f3,
+ 0xc2f4, 0xc2f5, 0xc2f7, 0xc2f8, 0xc2fa, 0xc2fb, 0xc2fd, 0xc2ff,
+ 0xc300, 0xc300, 0xc300, 0xc300, 0xc301, 0xc301, 0xc302, 0xc302,
+ 0xc303, 0xc304, 0xc305, 0xc305, 0xc306, 0xc307, 0xc308, 0xc309,
+ 0xc30a, 0xc30b, 0xc30c, 0xc30e, 0xc30f, 0xc310, 0xc311, 0xc313,
+ 0xc314, 0xc315, 0xc317, 0xc318, 0xc31a, 0xc31b, 0xc31d, 0xc31f,
+ 0xc320, 0xc320, 0xc320, 0xc320, 0xc321, 0xc321, 0xc322, 0xc322,
+ 0xc323, 0xc324, 0xc325, 0xc325, 0xc326, 0xc327, 0xc328, 0xc329,
+ 0xc32a, 0xc32b, 0xc32c, 0xc32e, 0xc32f, 0xc330, 0xc331, 0xc333,
+ 0xc334, 0xc335, 0xc337, 0xc338, 0xc33a, 0xc33b, 0xc33d, 0xc33f,
+ 0xc340, 0xc340, 0xc340, 0xc340, 0xc341, 0xc341, 0xc342, 0xc342,
+ 0xc343, 0xc344, 0xc345, 0xc345, 0xc346, 0xc347, 0xc348, 0xc349,
+ 0xc34a, 0xc34b, 0xc34c, 0xc34e, 0xc34f, 0xc350, 0xc351, 0xc353,
+ 0xc354, 0xc355, 0xc357, 0xc358, 0xc35a, 0xc35b, 0xc35d, 0xc35f,
+ 0xc380, 0xc380, 0xc380, 0xc380, 0xc381, 0xc381, 0xc382, 0xc382,
+ 0xc383, 0xc384, 0xc385, 0xc385, 0xc386, 0xc387, 0xc388, 0xc389,
+ 0xc38a, 0xc38b, 0xc38c, 0xc38e, 0xc38f, 0xc390, 0xc391, 0xc393,
+ 0xc394, 0xc395, 0xc397, 0xc398, 0xc39a, 0xc39b, 0xc39d, 0xc39f,
+ 0xc3a0, 0xc3a0, 0xc3a0, 0xc3a0, 0xc3a1, 0xc3a1, 0xc3a2, 0xc3a2,
+ 0xc3a3, 0xc3a4, 0xc3a5, 0xc3a5, 0xc3a6, 0xc3a7, 0xc3a8, 0xc3a9,
+ 0xc3aa, 0xc3ab, 0xc3ac, 0xc3ae, 0xc3af, 0xc3b0, 0xc3b1, 0xc3b3,
+ 0xc3b4, 0xc3b5, 0xc3b7, 0xc3b8, 0xc3ba, 0xc3bb, 0xc3bd, 0xc3bf,
+ 0xc3c0, 0xc3c0, 0xc3c0, 0xc3c0, 0xc3c1, 0xc3c1, 0xc3c2, 0xc3c2,
+ 0xc3c3, 0xc3c4, 0xc3c5, 0xc3c5, 0xc3c6, 0xc3c7, 0xc3c8, 0xc3c9,
+ 0xc3ca, 0xc3cb, 0xc3cc, 0xc3ce, 0xc3cf, 0xc3d0, 0xc3d1, 0xc3d3,
+ 0xc3d4, 0xc3d5, 0xc3d7, 0xc3d8, 0xc3da, 0xc3db, 0xc3dd, 0xc3df,
+ 0xc3e0, 0xc3e0, 0xc3e0, 0xc3e0, 0xc3e1, 0xc3e1, 0xc3e2, 0xc3e2,
+ 0xc3e3, 0xc3e4, 0xc3e5, 0xc3e5, 0xc3e6, 0xc3e7, 0xc3e8, 0xc3e9,
+ 0xc3ea, 0xc3eb, 0xc3ec, 0xc3ee, 0xc3ef, 0xc3f0, 0xc3f1, 0xc3f3,
+ 0xc3f4, 0xc3f5, 0xc3f7, 0xc3f8, 0xc3fa, 0xc3fb, 0xc3fd, 0xc3ff,
+ 0xc400, 0xc400, 0xc400, 0xc400, 0xc401, 0xc401, 0xc402, 0xc402,
+ 0xc403, 0xc404, 0xc405, 0xc405, 0xc406, 0xc407, 0xc408, 0xc409,
+ 0xc40a, 0xc40b, 0xc40c, 0xc40e, 0xc40f, 0xc410, 0xc411, 0xc413,
+ 0xc414, 0xc415, 0xc417, 0xc418, 0xc41a, 0xc41b, 0xc41d, 0xc41f,
+ 0xc440, 0xc440, 0xc440, 0xc440, 0xc441, 0xc441, 0xc442, 0xc442,
+ 0xc443, 0xc444, 0xc445, 0xc445, 0xc446, 0xc447, 0xc448, 0xc449,
+ 0xc44a, 0xc44b, 0xc44c, 0xc44e, 0xc44f, 0xc450, 0xc451, 0xc453,
+ 0xc454, 0xc455, 0xc457, 0xc458, 0xc45a, 0xc45b, 0xc45d, 0xc45f,
+ 0xc460, 0xc460, 0xc460, 0xc460, 0xc461, 0xc461, 0xc462, 0xc462,
+ 0xc463, 0xc464, 0xc465, 0xc465, 0xc466, 0xc467, 0xc468, 0xc469,
+ 0xc46a, 0xc46b, 0xc46c, 0xc46e, 0xc46f, 0xc470, 0xc471, 0xc473,
+ 0xc474, 0xc475, 0xc477, 0xc478, 0xc47a, 0xc47b, 0xc47d, 0xc47f,
+ 0xc480, 0xc480, 0xc480, 0xc480, 0xc481, 0xc481, 0xc482, 0xc482,
+ 0xc483, 0xc484, 0xc485, 0xc485, 0xc486, 0xc487, 0xc488, 0xc489,
+ 0xc48a, 0xc48b, 0xc48c, 0xc48e, 0xc48f, 0xc490, 0xc491, 0xc493,
+ 0xc494, 0xc495, 0xc497, 0xc498, 0xc49a, 0xc49b, 0xc49d, 0xc49f,
+ 0xc4c0, 0xc4c0, 0xc4c0, 0xc4c0, 0xc4c1, 0xc4c1, 0xc4c2, 0xc4c2,
+ 0xc4c3, 0xc4c4, 0xc4c5, 0xc4c5, 0xc4c6, 0xc4c7, 0xc4c8, 0xc4c9,
+ 0xc4ca, 0xc4cb, 0xc4cc, 0xc4ce, 0xc4cf, 0xc4d0, 0xc4d1, 0xc4d3,
+ 0xc4d4, 0xc4d5, 0xc4d7, 0xc4d8, 0xc4da, 0xc4db, 0xc4dd, 0xc4df,
+ 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e1, 0xc4e1, 0xc4e2, 0xc4e2,
+ 0xc4e3, 0xc4e4, 0xc4e5, 0xc4e5, 0xc4e6, 0xc4e7, 0xc4e8, 0xc4e9,
+ 0xc4ea, 0xc4eb, 0xc4ec, 0xc4ee, 0xc4ef, 0xc4f0, 0xc4f1, 0xc4f3,
+ 0xc4f4, 0xc4f5, 0xc4f7, 0xc4f8, 0xc4fa, 0xc4fb, 0xc4fd, 0xc4ff,
+ 0xc500, 0xc500, 0xc500, 0xc500, 0xc501, 0xc501, 0xc502, 0xc502,
+ 0xc503, 0xc504, 0xc505, 0xc505, 0xc506, 0xc507, 0xc508, 0xc509,
+ 0xc50a, 0xc50b, 0xc50c, 0xc50e, 0xc50f, 0xc510, 0xc511, 0xc513,
+ 0xc514, 0xc515, 0xc517, 0xc518, 0xc51a, 0xc51b, 0xc51d, 0xc51f,
+ 0xc540, 0xc540, 0xc540, 0xc540, 0xc541, 0xc541, 0xc542, 0xc542,
+ 0xc543, 0xc544, 0xc545, 0xc545, 0xc546, 0xc547, 0xc548, 0xc549,
+ 0xc54a, 0xc54b, 0xc54c, 0xc54e, 0xc54f, 0xc550, 0xc551, 0xc553,
+ 0xc554, 0xc555, 0xc557, 0xc558, 0xc55a, 0xc55b, 0xc55d, 0xc55f,
+ 0xc560, 0xc560, 0xc560, 0xc560, 0xc561, 0xc561, 0xc562, 0xc562,
+ 0xc563, 0xc564, 0xc565, 0xc565, 0xc566, 0xc567, 0xc568, 0xc569,
+ 0xc56a, 0xc56b, 0xc56c, 0xc56e, 0xc56f, 0xc570, 0xc571, 0xc573,
+ 0xc574, 0xc575, 0xc577, 0xc578, 0xc57a, 0xc57b, 0xc57d, 0xc57f,
+ 0xc580, 0xc580, 0xc580, 0xc580, 0xc581, 0xc581, 0xc582, 0xc582,
+ 0xc583, 0xc584, 0xc585, 0xc585, 0xc586, 0xc587, 0xc588, 0xc589,
+ 0xc58a, 0xc58b, 0xc58c, 0xc58e, 0xc58f, 0xc590, 0xc591, 0xc593,
+ 0xc594, 0xc595, 0xc597, 0xc598, 0xc59a, 0xc59b, 0xc59d, 0xc59f,
+ 0xc5c0, 0xc5c0, 0xc5c0, 0xc5c0, 0xc5c1, 0xc5c1, 0xc5c2, 0xc5c2,
+ 0xc5c3, 0xc5c4, 0xc5c5, 0xc5c5, 0xc5c6, 0xc5c7, 0xc5c8, 0xc5c9,
+ 0xc5ca, 0xc5cb, 0xc5cc, 0xc5ce, 0xc5cf, 0xc5d0, 0xc5d1, 0xc5d3,
+ 0xc5d4, 0xc5d5, 0xc5d7, 0xc5d8, 0xc5da, 0xc5db, 0xc5dd, 0xc5df,
+ 0xc5e0, 0xc5e0, 0xc5e0, 0xc5e0, 0xc5e1, 0xc5e1, 0xc5e2, 0xc5e2,
+ 0xc5e3, 0xc5e4, 0xc5e5, 0xc5e5, 0xc5e6, 0xc5e7, 0xc5e8, 0xc5e9,
+ 0xc5ea, 0xc5eb, 0xc5ec, 0xc5ee, 0xc5ef, 0xc5f0, 0xc5f1, 0xc5f3,
+ 0xc5f4, 0xc5f5, 0xc5f7, 0xc5f8, 0xc5fa, 0xc5fb, 0xc5fd, 0xc5ff,
+ 0xc620, 0xc620, 0xc620, 0xc620, 0xc621, 0xc621, 0xc622, 0xc622,
+ 0xc623, 0xc624, 0xc625, 0xc625, 0xc626, 0xc627, 0xc628, 0xc629,
+ 0xc62a, 0xc62b, 0xc62c, 0xc62e, 0xc62f, 0xc630, 0xc631, 0xc633,
+ 0xc634, 0xc635, 0xc637, 0xc638, 0xc63a, 0xc63b, 0xc63d, 0xc63f,
+ 0xc640, 0xc640, 0xc640, 0xc640, 0xc641, 0xc641, 0xc642, 0xc642,
+ 0xc643, 0xc644, 0xc645, 0xc645, 0xc646, 0xc647, 0xc648, 0xc649,
+ 0xc64a, 0xc64b, 0xc64c, 0xc64e, 0xc64f, 0xc650, 0xc651, 0xc653,
+ 0xc654, 0xc655, 0xc657, 0xc658, 0xc65a, 0xc65b, 0xc65d, 0xc65f,
+ 0xc680, 0xc680, 0xc680, 0xc680, 0xc681, 0xc681, 0xc682, 0xc682,
+ 0xc683, 0xc684, 0xc685, 0xc685, 0xc686, 0xc687, 0xc688, 0xc689,
+ 0xc68a, 0xc68b, 0xc68c, 0xc68e, 0xc68f, 0xc690, 0xc691, 0xc693,
+ 0xc694, 0xc695, 0xc697, 0xc698, 0xc69a, 0xc69b, 0xc69d, 0xc69f,
+ 0xc6a0, 0xc6a0, 0xc6a0, 0xc6a0, 0xc6a1, 0xc6a1, 0xc6a2, 0xc6a2,
+ 0xc6a3, 0xc6a4, 0xc6a5, 0xc6a5, 0xc6a6, 0xc6a7, 0xc6a8, 0xc6a9,
+ 0xc6aa, 0xc6ab, 0xc6ac, 0xc6ae, 0xc6af, 0xc6b0, 0xc6b1, 0xc6b3,
+ 0xc6b4, 0xc6b5, 0xc6b7, 0xc6b8, 0xc6ba, 0xc6bb, 0xc6bd, 0xc6bf,
+ 0xc6e0, 0xc6e0, 0xc6e0, 0xc6e0, 0xc6e1, 0xc6e1, 0xc6e2, 0xc6e2,
+ 0xc6e3, 0xc6e4, 0xc6e5, 0xc6e5, 0xc6e6, 0xc6e7, 0xc6e8, 0xc6e9,
+ 0xc6ea, 0xc6eb, 0xc6ec, 0xc6ee, 0xc6ef, 0xc6f0, 0xc6f1, 0xc6f3,
+ 0xc6f4, 0xc6f5, 0xc6f7, 0xc6f8, 0xc6fa, 0xc6fb, 0xc6fd, 0xc6ff,
+ 0xc700, 0xc700, 0xc700, 0xc700, 0xc701, 0xc701, 0xc702, 0xc702,
+ 0xc703, 0xc704, 0xc705, 0xc705, 0xc706, 0xc707, 0xc708, 0xc709,
+ 0xc70a, 0xc70b, 0xc70c, 0xc70e, 0xc70f, 0xc710, 0xc711, 0xc713,
+ 0xc714, 0xc715, 0xc717, 0xc718, 0xc71a, 0xc71b, 0xc71d, 0xc71f,
+ 0xc740, 0xc740, 0xc740, 0xc740, 0xc741, 0xc741, 0xc742, 0xc742,
+ 0xc743, 0xc744, 0xc745, 0xc745, 0xc746, 0xc747, 0xc748, 0xc749,
+ 0xc74a, 0xc74b, 0xc74c, 0xc74e, 0xc74f, 0xc750, 0xc751, 0xc753,
+ 0xc754, 0xc755, 0xc757, 0xc758, 0xc75a, 0xc75b, 0xc75d, 0xc75f,
+ 0xc760, 0xc760, 0xc760, 0xc760, 0xc761, 0xc761, 0xc762, 0xc762,
+ 0xc763, 0xc764, 0xc765, 0xc765, 0xc766, 0xc767, 0xc768, 0xc769,
+ 0xc76a, 0xc76b, 0xc76c, 0xc76e, 0xc76f, 0xc770, 0xc771, 0xc773,
+ 0xc774, 0xc775, 0xc777, 0xc778, 0xc77a, 0xc77b, 0xc77d, 0xc77f,
+ 0xc7a0, 0xc7a0, 0xc7a0, 0xc7a0, 0xc7a1, 0xc7a1, 0xc7a2, 0xc7a2,
+ 0xc7a3, 0xc7a4, 0xc7a5, 0xc7a5, 0xc7a6, 0xc7a7, 0xc7a8, 0xc7a9,
+ 0xc7aa, 0xc7ab, 0xc7ac, 0xc7ae, 0xc7af, 0xc7b0, 0xc7b1, 0xc7b3,
+ 0xc7b4, 0xc7b5, 0xc7b7, 0xc7b8, 0xc7ba, 0xc7bb, 0xc7bd, 0xc7bf,
+ 0xc7e0, 0xc7e0, 0xc7e0, 0xc7e0, 0xc7e1, 0xc7e1, 0xc7e2, 0xc7e2,
+ 0xc7e3, 0xc7e4, 0xc7e5, 0xc7e5, 0xc7e6, 0xc7e7, 0xc7e8, 0xc7e9,
+ 0xc7ea, 0xc7eb, 0xc7ec, 0xc7ee, 0xc7ef, 0xc7f0, 0xc7f1, 0xc7f3,
+ 0xc7f4, 0xc7f5, 0xc7f7, 0xc7f8, 0xc7fa, 0xc7fb, 0xc7fd, 0xc7ff,
+ 0xd000, 0xd000, 0xd000, 0xd000, 0xd001, 0xd001, 0xd002, 0xd002,
+ 0xd003, 0xd004, 0xd005, 0xd005, 0xd006, 0xd007, 0xd008, 0xd009,
+ 0xd00a, 0xd00b, 0xd00c, 0xd00e, 0xd00f, 0xd010, 0xd011, 0xd013,
+ 0xd014, 0xd015, 0xd017, 0xd018, 0xd01a, 0xd01b, 0xd01d, 0xd01f,
+ 0xd000, 0xd000, 0xd000, 0xd000, 0xd001, 0xd001, 0xd002, 0xd002,
+ 0xd003, 0xd004, 0xd005, 0xd005, 0xd006, 0xd007, 0xd008, 0xd009,
+ 0xd00a, 0xd00b, 0xd00c, 0xd00e, 0xd00f, 0xd010, 0xd011, 0xd013,
+ 0xd014, 0xd015, 0xd017, 0xd018, 0xd01a, 0xd01b, 0xd01d, 0xd01f,
+ 0xd000, 0xd000, 0xd000, 0xd000, 0xd001, 0xd001, 0xd002, 0xd002,
+ 0xd003, 0xd004, 0xd005, 0xd005, 0xd006, 0xd007, 0xd008, 0xd009,
+ 0xd00a, 0xd00b, 0xd00c, 0xd00e, 0xd00f, 0xd010, 0xd011, 0xd013,
+ 0xd014, 0xd015, 0xd017, 0xd018, 0xd01a, 0xd01b, 0xd01d, 0xd01f,
+ 0xd000, 0xd000, 0xd000, 0xd000, 0xd001, 0xd001, 0xd002, 0xd002,
+ 0xd003, 0xd004, 0xd005, 0xd005, 0xd006, 0xd007, 0xd008, 0xd009,
+ 0xd00a, 0xd00b, 0xd00c, 0xd00e, 0xd00f, 0xd010, 0xd011, 0xd013,
+ 0xd014, 0xd015, 0xd017, 0xd018, 0xd01a, 0xd01b, 0xd01d, 0xd01f,
+ 0xd000, 0xd000, 0xd000, 0xd000, 0xd001, 0xd001, 0xd002, 0xd002,
+ 0xd003, 0xd004, 0xd005, 0xd005, 0xd006, 0xd007, 0xd008, 0xd009,
+ 0xd00a, 0xd00b, 0xd00c, 0xd00e, 0xd00f, 0xd010, 0xd011, 0xd013,
+ 0xd014, 0xd015, 0xd017, 0xd018, 0xd01a, 0xd01b, 0xd01d, 0xd01f,
+ 0xd020, 0xd020, 0xd020, 0xd020, 0xd021, 0xd021, 0xd022, 0xd022,
+ 0xd023, 0xd024, 0xd025, 0xd025, 0xd026, 0xd027, 0xd028, 0xd029,
+ 0xd02a, 0xd02b, 0xd02c, 0xd02e, 0xd02f, 0xd030, 0xd031, 0xd033,
+ 0xd034, 0xd035, 0xd037, 0xd038, 0xd03a, 0xd03b, 0xd03d, 0xd03f,
+ 0xd020, 0xd020, 0xd020, 0xd020, 0xd021, 0xd021, 0xd022, 0xd022,
+ 0xd023, 0xd024, 0xd025, 0xd025, 0xd026, 0xd027, 0xd028, 0xd029,
+ 0xd02a, 0xd02b, 0xd02c, 0xd02e, 0xd02f, 0xd030, 0xd031, 0xd033,
+ 0xd034, 0xd035, 0xd037, 0xd038, 0xd03a, 0xd03b, 0xd03d, 0xd03f,
+ 0xd020, 0xd020, 0xd020, 0xd020, 0xd021, 0xd021, 0xd022, 0xd022,
+ 0xd023, 0xd024, 0xd025, 0xd025, 0xd026, 0xd027, 0xd028, 0xd029,
+ 0xd02a, 0xd02b, 0xd02c, 0xd02e, 0xd02f, 0xd030, 0xd031, 0xd033,
+ 0xd034, 0xd035, 0xd037, 0xd038, 0xd03a, 0xd03b, 0xd03d, 0xd03f,
+ 0xd040, 0xd040, 0xd040, 0xd040, 0xd041, 0xd041, 0xd042, 0xd042,
+ 0xd043, 0xd044, 0xd045, 0xd045, 0xd046, 0xd047, 0xd048, 0xd049,
+ 0xd04a, 0xd04b, 0xd04c, 0xd04e, 0xd04f, 0xd050, 0xd051, 0xd053,
+ 0xd054, 0xd055, 0xd057, 0xd058, 0xd05a, 0xd05b, 0xd05d, 0xd05f,
+ 0xd040, 0xd040, 0xd040, 0xd040, 0xd041, 0xd041, 0xd042, 0xd042,
+ 0xd043, 0xd044, 0xd045, 0xd045, 0xd046, 0xd047, 0xd048, 0xd049,
+ 0xd04a, 0xd04b, 0xd04c, 0xd04e, 0xd04f, 0xd050, 0xd051, 0xd053,
+ 0xd054, 0xd055, 0xd057, 0xd058, 0xd05a, 0xd05b, 0xd05d, 0xd05f,
+ 0xd060, 0xd060, 0xd060, 0xd060, 0xd061, 0xd061, 0xd062, 0xd062,
+ 0xd063, 0xd064, 0xd065, 0xd065, 0xd066, 0xd067, 0xd068, 0xd069,
+ 0xd06a, 0xd06b, 0xd06c, 0xd06e, 0xd06f, 0xd070, 0xd071, 0xd073,
+ 0xd074, 0xd075, 0xd077, 0xd078, 0xd07a, 0xd07b, 0xd07d, 0xd07f,
+ 0xd060, 0xd060, 0xd060, 0xd060, 0xd061, 0xd061, 0xd062, 0xd062,
+ 0xd063, 0xd064, 0xd065, 0xd065, 0xd066, 0xd067, 0xd068, 0xd069,
+ 0xd06a, 0xd06b, 0xd06c, 0xd06e, 0xd06f, 0xd070, 0xd071, 0xd073,
+ 0xd074, 0xd075, 0xd077, 0xd078, 0xd07a, 0xd07b, 0xd07d, 0xd07f,
+ 0xd080, 0xd080, 0xd080, 0xd080, 0xd081, 0xd081, 0xd082, 0xd082,
+ 0xd083, 0xd084, 0xd085, 0xd085, 0xd086, 0xd087, 0xd088, 0xd089,
+ 0xd08a, 0xd08b, 0xd08c, 0xd08e, 0xd08f, 0xd090, 0xd091, 0xd093,
+ 0xd094, 0xd095, 0xd097, 0xd098, 0xd09a, 0xd09b, 0xd09d, 0xd09f,
+ 0xd0a0, 0xd0a0, 0xd0a0, 0xd0a0, 0xd0a1, 0xd0a1, 0xd0a2, 0xd0a2,
+ 0xd0a3, 0xd0a4, 0xd0a5, 0xd0a5, 0xd0a6, 0xd0a7, 0xd0a8, 0xd0a9,
+ 0xd0aa, 0xd0ab, 0xd0ac, 0xd0ae, 0xd0af, 0xd0b0, 0xd0b1, 0xd0b3,
+ 0xd0b4, 0xd0b5, 0xd0b7, 0xd0b8, 0xd0ba, 0xd0bb, 0xd0bd, 0xd0bf,
+ 0xd0a0, 0xd0a0, 0xd0a0, 0xd0a0, 0xd0a1, 0xd0a1, 0xd0a2, 0xd0a2,
+ 0xd0a3, 0xd0a4, 0xd0a5, 0xd0a5, 0xd0a6, 0xd0a7, 0xd0a8, 0xd0a9,
+ 0xd0aa, 0xd0ab, 0xd0ac, 0xd0ae, 0xd0af, 0xd0b0, 0xd0b1, 0xd0b3,
+ 0xd0b4, 0xd0b5, 0xd0b7, 0xd0b8, 0xd0ba, 0xd0bb, 0xd0bd, 0xd0bf,
+ 0xd0c0, 0xd0c0, 0xd0c0, 0xd0c0, 0xd0c1, 0xd0c1, 0xd0c2, 0xd0c2,
+ 0xd0c3, 0xd0c4, 0xd0c5, 0xd0c5, 0xd0c6, 0xd0c7, 0xd0c8, 0xd0c9,
+ 0xd0ca, 0xd0cb, 0xd0cc, 0xd0ce, 0xd0cf, 0xd0d0, 0xd0d1, 0xd0d3,
+ 0xd0d4, 0xd0d5, 0xd0d7, 0xd0d8, 0xd0da, 0xd0db, 0xd0dd, 0xd0df,
+ 0xd0e0, 0xd0e0, 0xd0e0, 0xd0e0, 0xd0e1, 0xd0e1, 0xd0e2, 0xd0e2,
+ 0xd0e3, 0xd0e4, 0xd0e5, 0xd0e5, 0xd0e6, 0xd0e7, 0xd0e8, 0xd0e9,
+ 0xd0ea, 0xd0eb, 0xd0ec, 0xd0ee, 0xd0ef, 0xd0f0, 0xd0f1, 0xd0f3,
+ 0xd0f4, 0xd0f5, 0xd0f7, 0xd0f8, 0xd0fa, 0xd0fb, 0xd0fd, 0xd0ff,
+ 0xd0e0, 0xd0e0, 0xd0e0, 0xd0e0, 0xd0e1, 0xd0e1, 0xd0e2, 0xd0e2,
+ 0xd0e3, 0xd0e4, 0xd0e5, 0xd0e5, 0xd0e6, 0xd0e7, 0xd0e8, 0xd0e9,
+ 0xd0ea, 0xd0eb, 0xd0ec, 0xd0ee, 0xd0ef, 0xd0f0, 0xd0f1, 0xd0f3,
+ 0xd0f4, 0xd0f5, 0xd0f7, 0xd0f8, 0xd0fa, 0xd0fb, 0xd0fd, 0xd0ff,
+ 0xd100, 0xd100, 0xd100, 0xd100, 0xd101, 0xd101, 0xd102, 0xd102,
+ 0xd103, 0xd104, 0xd105, 0xd105, 0xd106, 0xd107, 0xd108, 0xd109,
+ 0xd10a, 0xd10b, 0xd10c, 0xd10e, 0xd10f, 0xd110, 0xd111, 0xd113,
+ 0xd114, 0xd115, 0xd117, 0xd118, 0xd11a, 0xd11b, 0xd11d, 0xd11f,
+ 0xd120, 0xd120, 0xd120, 0xd120, 0xd121, 0xd121, 0xd122, 0xd122,
+ 0xd123, 0xd124, 0xd125, 0xd125, 0xd126, 0xd127, 0xd128, 0xd129,
+ 0xd12a, 0xd12b, 0xd12c, 0xd12e, 0xd12f, 0xd130, 0xd131, 0xd133,
+ 0xd134, 0xd135, 0xd137, 0xd138, 0xd13a, 0xd13b, 0xd13d, 0xd13f,
+ 0xd140, 0xd140, 0xd140, 0xd140, 0xd141, 0xd141, 0xd142, 0xd142,
+ 0xd143, 0xd144, 0xd145, 0xd145, 0xd146, 0xd147, 0xd148, 0xd149,
+ 0xd14a, 0xd14b, 0xd14c, 0xd14e, 0xd14f, 0xd150, 0xd151, 0xd153,
+ 0xd154, 0xd155, 0xd157, 0xd158, 0xd15a, 0xd15b, 0xd15d, 0xd15f,
+ 0xd140, 0xd140, 0xd140, 0xd140, 0xd141, 0xd141, 0xd142, 0xd142,
+ 0xd143, 0xd144, 0xd145, 0xd145, 0xd146, 0xd147, 0xd148, 0xd149,
+ 0xd14a, 0xd14b, 0xd14c, 0xd14e, 0xd14f, 0xd150, 0xd151, 0xd153,
+ 0xd154, 0xd155, 0xd157, 0xd158, 0xd15a, 0xd15b, 0xd15d, 0xd15f,
+ 0xd160, 0xd160, 0xd160, 0xd160, 0xd161, 0xd161, 0xd162, 0xd162,
+ 0xd163, 0xd164, 0xd165, 0xd165, 0xd166, 0xd167, 0xd168, 0xd169,
+ 0xd16a, 0xd16b, 0xd16c, 0xd16e, 0xd16f, 0xd170, 0xd171, 0xd173,
+ 0xd174, 0xd175, 0xd177, 0xd178, 0xd17a, 0xd17b, 0xd17d, 0xd17f,
+ 0xd180, 0xd180, 0xd180, 0xd180, 0xd181, 0xd181, 0xd182, 0xd182,
+ 0xd183, 0xd184, 0xd185, 0xd185, 0xd186, 0xd187, 0xd188, 0xd189,
+ 0xd18a, 0xd18b, 0xd18c, 0xd18e, 0xd18f, 0xd190, 0xd191, 0xd193,
+ 0xd194, 0xd195, 0xd197, 0xd198, 0xd19a, 0xd19b, 0xd19d, 0xd19f,
+ 0xd1a0, 0xd1a0, 0xd1a0, 0xd1a0, 0xd1a1, 0xd1a1, 0xd1a2, 0xd1a2,
+ 0xd1a3, 0xd1a4, 0xd1a5, 0xd1a5, 0xd1a6, 0xd1a7, 0xd1a8, 0xd1a9,
+ 0xd1aa, 0xd1ab, 0xd1ac, 0xd1ae, 0xd1af, 0xd1b0, 0xd1b1, 0xd1b3,
+ 0xd1b4, 0xd1b5, 0xd1b7, 0xd1b8, 0xd1ba, 0xd1bb, 0xd1bd, 0xd1bf,
+ 0xd1c0, 0xd1c0, 0xd1c0, 0xd1c0, 0xd1c1, 0xd1c1, 0xd1c2, 0xd1c2,
+ 0xd1c3, 0xd1c4, 0xd1c5, 0xd1c5, 0xd1c6, 0xd1c7, 0xd1c8, 0xd1c9,
+ 0xd1ca, 0xd1cb, 0xd1cc, 0xd1ce, 0xd1cf, 0xd1d0, 0xd1d1, 0xd1d3,
+ 0xd1d4, 0xd1d5, 0xd1d7, 0xd1d8, 0xd1da, 0xd1db, 0xd1dd, 0xd1df,
+ 0xd1e0, 0xd1e0, 0xd1e0, 0xd1e0, 0xd1e1, 0xd1e1, 0xd1e2, 0xd1e2,
+ 0xd1e3, 0xd1e4, 0xd1e5, 0xd1e5, 0xd1e6, 0xd1e7, 0xd1e8, 0xd1e9,
+ 0xd1ea, 0xd1eb, 0xd1ec, 0xd1ee, 0xd1ef, 0xd1f0, 0xd1f1, 0xd1f3,
+ 0xd1f4, 0xd1f5, 0xd1f7, 0xd1f8, 0xd1fa, 0xd1fb, 0xd1fd, 0xd1ff,
+ 0xd200, 0xd200, 0xd200, 0xd200, 0xd201, 0xd201, 0xd202, 0xd202,
+ 0xd203, 0xd204, 0xd205, 0xd205, 0xd206, 0xd207, 0xd208, 0xd209,
+ 0xd20a, 0xd20b, 0xd20c, 0xd20e, 0xd20f, 0xd210, 0xd211, 0xd213,
+ 0xd214, 0xd215, 0xd217, 0xd218, 0xd21a, 0xd21b, 0xd21d, 0xd21f,
+ 0xd220, 0xd220, 0xd220, 0xd220, 0xd221, 0xd221, 0xd222, 0xd222,
+ 0xd223, 0xd224, 0xd225, 0xd225, 0xd226, 0xd227, 0xd228, 0xd229,
+ 0xd22a, 0xd22b, 0xd22c, 0xd22e, 0xd22f, 0xd230, 0xd231, 0xd233,
+ 0xd234, 0xd235, 0xd237, 0xd238, 0xd23a, 0xd23b, 0xd23d, 0xd23f,
+ 0xd240, 0xd240, 0xd240, 0xd240, 0xd241, 0xd241, 0xd242, 0xd242,
+ 0xd243, 0xd244, 0xd245, 0xd245, 0xd246, 0xd247, 0xd248, 0xd249,
+ 0xd24a, 0xd24b, 0xd24c, 0xd24e, 0xd24f, 0xd250, 0xd251, 0xd253,
+ 0xd254, 0xd255, 0xd257, 0xd258, 0xd25a, 0xd25b, 0xd25d, 0xd25f,
+ 0xd260, 0xd260, 0xd260, 0xd260, 0xd261, 0xd261, 0xd262, 0xd262,
+ 0xd263, 0xd264, 0xd265, 0xd265, 0xd266, 0xd267, 0xd268, 0xd269,
+ 0xd26a, 0xd26b, 0xd26c, 0xd26e, 0xd26f, 0xd270, 0xd271, 0xd273,
+ 0xd274, 0xd275, 0xd277, 0xd278, 0xd27a, 0xd27b, 0xd27d, 0xd27f,
+ 0xd280, 0xd280, 0xd280, 0xd280, 0xd281, 0xd281, 0xd282, 0xd282,
+ 0xd283, 0xd284, 0xd285, 0xd285, 0xd286, 0xd287, 0xd288, 0xd289,
+ 0xd28a, 0xd28b, 0xd28c, 0xd28e, 0xd28f, 0xd290, 0xd291, 0xd293,
+ 0xd294, 0xd295, 0xd297, 0xd298, 0xd29a, 0xd29b, 0xd29d, 0xd29f,
+ 0xd2a0, 0xd2a0, 0xd2a0, 0xd2a0, 0xd2a1, 0xd2a1, 0xd2a2, 0xd2a2,
+ 0xd2a3, 0xd2a4, 0xd2a5, 0xd2a5, 0xd2a6, 0xd2a7, 0xd2a8, 0xd2a9,
+ 0xd2aa, 0xd2ab, 0xd2ac, 0xd2ae, 0xd2af, 0xd2b0, 0xd2b1, 0xd2b3,
+ 0xd2b4, 0xd2b5, 0xd2b7, 0xd2b8, 0xd2ba, 0xd2bb, 0xd2bd, 0xd2bf,
+ 0xd2c0, 0xd2c0, 0xd2c0, 0xd2c0, 0xd2c1, 0xd2c1, 0xd2c2, 0xd2c2,
+ 0xd2c3, 0xd2c4, 0xd2c5, 0xd2c5, 0xd2c6, 0xd2c7, 0xd2c8, 0xd2c9,
+ 0xd2ca, 0xd2cb, 0xd2cc, 0xd2ce, 0xd2cf, 0xd2d0, 0xd2d1, 0xd2d3,
+ 0xd2d4, 0xd2d5, 0xd2d7, 0xd2d8, 0xd2da, 0xd2db, 0xd2dd, 0xd2df,
+ 0xd2e0, 0xd2e0, 0xd2e0, 0xd2e0, 0xd2e1, 0xd2e1, 0xd2e2, 0xd2e2,
+ 0xd2e3, 0xd2e4, 0xd2e5, 0xd2e5, 0xd2e6, 0xd2e7, 0xd2e8, 0xd2e9,
+ 0xd2ea, 0xd2eb, 0xd2ec, 0xd2ee, 0xd2ef, 0xd2f0, 0xd2f1, 0xd2f3,
+ 0xd2f4, 0xd2f5, 0xd2f7, 0xd2f8, 0xd2fa, 0xd2fb, 0xd2fd, 0xd2ff,
+ 0xd300, 0xd300, 0xd300, 0xd300, 0xd301, 0xd301, 0xd302, 0xd302,
+ 0xd303, 0xd304, 0xd305, 0xd305, 0xd306, 0xd307, 0xd308, 0xd309,
+ 0xd30a, 0xd30b, 0xd30c, 0xd30e, 0xd30f, 0xd310, 0xd311, 0xd313,
+ 0xd314, 0xd315, 0xd317, 0xd318, 0xd31a, 0xd31b, 0xd31d, 0xd31f,
+ 0xd320, 0xd320, 0xd320, 0xd320, 0xd321, 0xd321, 0xd322, 0xd322,
+ 0xd323, 0xd324, 0xd325, 0xd325, 0xd326, 0xd327, 0xd328, 0xd329,
+ 0xd32a, 0xd32b, 0xd32c, 0xd32e, 0xd32f, 0xd330, 0xd331, 0xd333,
+ 0xd334, 0xd335, 0xd337, 0xd338, 0xd33a, 0xd33b, 0xd33d, 0xd33f,
+ 0xd340, 0xd340, 0xd340, 0xd340, 0xd341, 0xd341, 0xd342, 0xd342,
+ 0xd343, 0xd344, 0xd345, 0xd345, 0xd346, 0xd347, 0xd348, 0xd349,
+ 0xd34a, 0xd34b, 0xd34c, 0xd34e, 0xd34f, 0xd350, 0xd351, 0xd353,
+ 0xd354, 0xd355, 0xd357, 0xd358, 0xd35a, 0xd35b, 0xd35d, 0xd35f,
+ 0xd380, 0xd380, 0xd380, 0xd380, 0xd381, 0xd381, 0xd382, 0xd382,
+ 0xd383, 0xd384, 0xd385, 0xd385, 0xd386, 0xd387, 0xd388, 0xd389,
+ 0xd38a, 0xd38b, 0xd38c, 0xd38e, 0xd38f, 0xd390, 0xd391, 0xd393,
+ 0xd394, 0xd395, 0xd397, 0xd398, 0xd39a, 0xd39b, 0xd39d, 0xd39f,
+ 0xd3a0, 0xd3a0, 0xd3a0, 0xd3a0, 0xd3a1, 0xd3a1, 0xd3a2, 0xd3a2,
+ 0xd3a3, 0xd3a4, 0xd3a5, 0xd3a5, 0xd3a6, 0xd3a7, 0xd3a8, 0xd3a9,
+ 0xd3aa, 0xd3ab, 0xd3ac, 0xd3ae, 0xd3af, 0xd3b0, 0xd3b1, 0xd3b3,
+ 0xd3b4, 0xd3b5, 0xd3b7, 0xd3b8, 0xd3ba, 0xd3bb, 0xd3bd, 0xd3bf,
+ 0xd3c0, 0xd3c0, 0xd3c0, 0xd3c0, 0xd3c1, 0xd3c1, 0xd3c2, 0xd3c2,
+ 0xd3c3, 0xd3c4, 0xd3c5, 0xd3c5, 0xd3c6, 0xd3c7, 0xd3c8, 0xd3c9,
+ 0xd3ca, 0xd3cb, 0xd3cc, 0xd3ce, 0xd3cf, 0xd3d0, 0xd3d1, 0xd3d3,
+ 0xd3d4, 0xd3d5, 0xd3d7, 0xd3d8, 0xd3da, 0xd3db, 0xd3dd, 0xd3df,
+ 0xd3e0, 0xd3e0, 0xd3e0, 0xd3e0, 0xd3e1, 0xd3e1, 0xd3e2, 0xd3e2,
+ 0xd3e3, 0xd3e4, 0xd3e5, 0xd3e5, 0xd3e6, 0xd3e7, 0xd3e8, 0xd3e9,
+ 0xd3ea, 0xd3eb, 0xd3ec, 0xd3ee, 0xd3ef, 0xd3f0, 0xd3f1, 0xd3f3,
+ 0xd3f4, 0xd3f5, 0xd3f7, 0xd3f8, 0xd3fa, 0xd3fb, 0xd3fd, 0xd3ff,
+ 0xd400, 0xd400, 0xd400, 0xd400, 0xd401, 0xd401, 0xd402, 0xd402,
+ 0xd403, 0xd404, 0xd405, 0xd405, 0xd406, 0xd407, 0xd408, 0xd409,
+ 0xd40a, 0xd40b, 0xd40c, 0xd40e, 0xd40f, 0xd410, 0xd411, 0xd413,
+ 0xd414, 0xd415, 0xd417, 0xd418, 0xd41a, 0xd41b, 0xd41d, 0xd41f,
+ 0xd440, 0xd440, 0xd440, 0xd440, 0xd441, 0xd441, 0xd442, 0xd442,
+ 0xd443, 0xd444, 0xd445, 0xd445, 0xd446, 0xd447, 0xd448, 0xd449,
+ 0xd44a, 0xd44b, 0xd44c, 0xd44e, 0xd44f, 0xd450, 0xd451, 0xd453,
+ 0xd454, 0xd455, 0xd457, 0xd458, 0xd45a, 0xd45b, 0xd45d, 0xd45f,
+ 0xd460, 0xd460, 0xd460, 0xd460, 0xd461, 0xd461, 0xd462, 0xd462,
+ 0xd463, 0xd464, 0xd465, 0xd465, 0xd466, 0xd467, 0xd468, 0xd469,
+ 0xd46a, 0xd46b, 0xd46c, 0xd46e, 0xd46f, 0xd470, 0xd471, 0xd473,
+ 0xd474, 0xd475, 0xd477, 0xd478, 0xd47a, 0xd47b, 0xd47d, 0xd47f,
+ 0xd480, 0xd480, 0xd480, 0xd480, 0xd481, 0xd481, 0xd482, 0xd482,
+ 0xd483, 0xd484, 0xd485, 0xd485, 0xd486, 0xd487, 0xd488, 0xd489,
+ 0xd48a, 0xd48b, 0xd48c, 0xd48e, 0xd48f, 0xd490, 0xd491, 0xd493,
+ 0xd494, 0xd495, 0xd497, 0xd498, 0xd49a, 0xd49b, 0xd49d, 0xd49f,
+ 0xd4c0, 0xd4c0, 0xd4c0, 0xd4c0, 0xd4c1, 0xd4c1, 0xd4c2, 0xd4c2,
+ 0xd4c3, 0xd4c4, 0xd4c5, 0xd4c5, 0xd4c6, 0xd4c7, 0xd4c8, 0xd4c9,
+ 0xd4ca, 0xd4cb, 0xd4cc, 0xd4ce, 0xd4cf, 0xd4d0, 0xd4d1, 0xd4d3,
+ 0xd4d4, 0xd4d5, 0xd4d7, 0xd4d8, 0xd4da, 0xd4db, 0xd4dd, 0xd4df,
+ 0xd4e0, 0xd4e0, 0xd4e0, 0xd4e0, 0xd4e1, 0xd4e1, 0xd4e2, 0xd4e2,
+ 0xd4e3, 0xd4e4, 0xd4e5, 0xd4e5, 0xd4e6, 0xd4e7, 0xd4e8, 0xd4e9,
+ 0xd4ea, 0xd4eb, 0xd4ec, 0xd4ee, 0xd4ef, 0xd4f0, 0xd4f1, 0xd4f3,
+ 0xd4f4, 0xd4f5, 0xd4f7, 0xd4f8, 0xd4fa, 0xd4fb, 0xd4fd, 0xd4ff,
+ 0xd500, 0xd500, 0xd500, 0xd500, 0xd501, 0xd501, 0xd502, 0xd502,
+ 0xd503, 0xd504, 0xd505, 0xd505, 0xd506, 0xd507, 0xd508, 0xd509,
+ 0xd50a, 0xd50b, 0xd50c, 0xd50e, 0xd50f, 0xd510, 0xd511, 0xd513,
+ 0xd514, 0xd515, 0xd517, 0xd518, 0xd51a, 0xd51b, 0xd51d, 0xd51f,
+ 0xd540, 0xd540, 0xd540, 0xd540, 0xd541, 0xd541, 0xd542, 0xd542,
+ 0xd543, 0xd544, 0xd545, 0xd545, 0xd546, 0xd547, 0xd548, 0xd549,
+ 0xd54a, 0xd54b, 0xd54c, 0xd54e, 0xd54f, 0xd550, 0xd551, 0xd553,
+ 0xd554, 0xd555, 0xd557, 0xd558, 0xd55a, 0xd55b, 0xd55d, 0xd55f,
+ 0xd560, 0xd560, 0xd560, 0xd560, 0xd561, 0xd561, 0xd562, 0xd562,
+ 0xd563, 0xd564, 0xd565, 0xd565, 0xd566, 0xd567, 0xd568, 0xd569,
+ 0xd56a, 0xd56b, 0xd56c, 0xd56e, 0xd56f, 0xd570, 0xd571, 0xd573,
+ 0xd574, 0xd575, 0xd577, 0xd578, 0xd57a, 0xd57b, 0xd57d, 0xd57f,
+ 0xd580, 0xd580, 0xd580, 0xd580, 0xd581, 0xd581, 0xd582, 0xd582,
+ 0xd583, 0xd584, 0xd585, 0xd585, 0xd586, 0xd587, 0xd588, 0xd589,
+ 0xd58a, 0xd58b, 0xd58c, 0xd58e, 0xd58f, 0xd590, 0xd591, 0xd593,
+ 0xd594, 0xd595, 0xd597, 0xd598, 0xd59a, 0xd59b, 0xd59d, 0xd59f,
+ 0xd5c0, 0xd5c0, 0xd5c0, 0xd5c0, 0xd5c1, 0xd5c1, 0xd5c2, 0xd5c2,
+ 0xd5c3, 0xd5c4, 0xd5c5, 0xd5c5, 0xd5c6, 0xd5c7, 0xd5c8, 0xd5c9,
+ 0xd5ca, 0xd5cb, 0xd5cc, 0xd5ce, 0xd5cf, 0xd5d0, 0xd5d1, 0xd5d3,
+ 0xd5d4, 0xd5d5, 0xd5d7, 0xd5d8, 0xd5da, 0xd5db, 0xd5dd, 0xd5df,
+ 0xd5e0, 0xd5e0, 0xd5e0, 0xd5e0, 0xd5e1, 0xd5e1, 0xd5e2, 0xd5e2,
+ 0xd5e3, 0xd5e4, 0xd5e5, 0xd5e5, 0xd5e6, 0xd5e7, 0xd5e8, 0xd5e9,
+ 0xd5ea, 0xd5eb, 0xd5ec, 0xd5ee, 0xd5ef, 0xd5f0, 0xd5f1, 0xd5f3,
+ 0xd5f4, 0xd5f5, 0xd5f7, 0xd5f8, 0xd5fa, 0xd5fb, 0xd5fd, 0xd5ff,
+ 0xd620, 0xd620, 0xd620, 0xd620, 0xd621, 0xd621, 0xd622, 0xd622,
+ 0xd623, 0xd624, 0xd625, 0xd625, 0xd626, 0xd627, 0xd628, 0xd629,
+ 0xd62a, 0xd62b, 0xd62c, 0xd62e, 0xd62f, 0xd630, 0xd631, 0xd633,
+ 0xd634, 0xd635, 0xd637, 0xd638, 0xd63a, 0xd63b, 0xd63d, 0xd63f,
+ 0xd640, 0xd640, 0xd640, 0xd640, 0xd641, 0xd641, 0xd642, 0xd642,
+ 0xd643, 0xd644, 0xd645, 0xd645, 0xd646, 0xd647, 0xd648, 0xd649,
+ 0xd64a, 0xd64b, 0xd64c, 0xd64e, 0xd64f, 0xd650, 0xd651, 0xd653,
+ 0xd654, 0xd655, 0xd657, 0xd658, 0xd65a, 0xd65b, 0xd65d, 0xd65f,
+ 0xd680, 0xd680, 0xd680, 0xd680, 0xd681, 0xd681, 0xd682, 0xd682,
+ 0xd683, 0xd684, 0xd685, 0xd685, 0xd686, 0xd687, 0xd688, 0xd689,
+ 0xd68a, 0xd68b, 0xd68c, 0xd68e, 0xd68f, 0xd690, 0xd691, 0xd693,
+ 0xd694, 0xd695, 0xd697, 0xd698, 0xd69a, 0xd69b, 0xd69d, 0xd69f,
+ 0xd6a0, 0xd6a0, 0xd6a0, 0xd6a0, 0xd6a1, 0xd6a1, 0xd6a2, 0xd6a2,
+ 0xd6a3, 0xd6a4, 0xd6a5, 0xd6a5, 0xd6a6, 0xd6a7, 0xd6a8, 0xd6a9,
+ 0xd6aa, 0xd6ab, 0xd6ac, 0xd6ae, 0xd6af, 0xd6b0, 0xd6b1, 0xd6b3,
+ 0xd6b4, 0xd6b5, 0xd6b7, 0xd6b8, 0xd6ba, 0xd6bb, 0xd6bd, 0xd6bf,
+ 0xd6e0, 0xd6e0, 0xd6e0, 0xd6e0, 0xd6e1, 0xd6e1, 0xd6e2, 0xd6e2,
+ 0xd6e3, 0xd6e4, 0xd6e5, 0xd6e5, 0xd6e6, 0xd6e7, 0xd6e8, 0xd6e9,
+ 0xd6ea, 0xd6eb, 0xd6ec, 0xd6ee, 0xd6ef, 0xd6f0, 0xd6f1, 0xd6f3,
+ 0xd6f4, 0xd6f5, 0xd6f7, 0xd6f8, 0xd6fa, 0xd6fb, 0xd6fd, 0xd6ff,
+ 0xd700, 0xd700, 0xd700, 0xd700, 0xd701, 0xd701, 0xd702, 0xd702,
+ 0xd703, 0xd704, 0xd705, 0xd705, 0xd706, 0xd707, 0xd708, 0xd709,
+ 0xd70a, 0xd70b, 0xd70c, 0xd70e, 0xd70f, 0xd710, 0xd711, 0xd713,
+ 0xd714, 0xd715, 0xd717, 0xd718, 0xd71a, 0xd71b, 0xd71d, 0xd71f,
+ 0xd740, 0xd740, 0xd740, 0xd740, 0xd741, 0xd741, 0xd742, 0xd742,
+ 0xd743, 0xd744, 0xd745, 0xd745, 0xd746, 0xd747, 0xd748, 0xd749,
+ 0xd74a, 0xd74b, 0xd74c, 0xd74e, 0xd74f, 0xd750, 0xd751, 0xd753,
+ 0xd754, 0xd755, 0xd757, 0xd758, 0xd75a, 0xd75b, 0xd75d, 0xd75f,
+ 0xd760, 0xd760, 0xd760, 0xd760, 0xd761, 0xd761, 0xd762, 0xd762,
+ 0xd763, 0xd764, 0xd765, 0xd765, 0xd766, 0xd767, 0xd768, 0xd769,
+ 0xd76a, 0xd76b, 0xd76c, 0xd76e, 0xd76f, 0xd770, 0xd771, 0xd773,
+ 0xd774, 0xd775, 0xd777, 0xd778, 0xd77a, 0xd77b, 0xd77d, 0xd77f,
+ 0xd7a0, 0xd7a0, 0xd7a0, 0xd7a0, 0xd7a1, 0xd7a1, 0xd7a2, 0xd7a2,
+ 0xd7a3, 0xd7a4, 0xd7a5, 0xd7a5, 0xd7a6, 0xd7a7, 0xd7a8, 0xd7a9,
+ 0xd7aa, 0xd7ab, 0xd7ac, 0xd7ae, 0xd7af, 0xd7b0, 0xd7b1, 0xd7b3,
+ 0xd7b4, 0xd7b5, 0xd7b7, 0xd7b8, 0xd7ba, 0xd7bb, 0xd7bd, 0xd7bf,
+ 0xd7e0, 0xd7e0, 0xd7e0, 0xd7e0, 0xd7e1, 0xd7e1, 0xd7e2, 0xd7e2,
+ 0xd7e3, 0xd7e4, 0xd7e5, 0xd7e5, 0xd7e6, 0xd7e7, 0xd7e8, 0xd7e9,
+ 0xd7ea, 0xd7eb, 0xd7ec, 0xd7ee, 0xd7ef, 0xd7f0, 0xd7f1, 0xd7f3,
+ 0xd7f4, 0xd7f5, 0xd7f7, 0xd7f8, 0xd7fa, 0xd7fb, 0xd7fd, 0xd7ff,
+ 0xd800, 0xd800, 0xd800, 0xd800, 0xd801, 0xd801, 0xd802, 0xd802,
+ 0xd803, 0xd804, 0xd805, 0xd805, 0xd806, 0xd807, 0xd808, 0xd809,
+ 0xd80a, 0xd80b, 0xd80c, 0xd80e, 0xd80f, 0xd810, 0xd811, 0xd813,
+ 0xd814, 0xd815, 0xd817, 0xd818, 0xd81a, 0xd81b, 0xd81d, 0xd81f,
+ 0xd800, 0xd800, 0xd800, 0xd800, 0xd801, 0xd801, 0xd802, 0xd802,
+ 0xd803, 0xd804, 0xd805, 0xd805, 0xd806, 0xd807, 0xd808, 0xd809,
+ 0xd80a, 0xd80b, 0xd80c, 0xd80e, 0xd80f, 0xd810, 0xd811, 0xd813,
+ 0xd814, 0xd815, 0xd817, 0xd818, 0xd81a, 0xd81b, 0xd81d, 0xd81f,
+ 0xd800, 0xd800, 0xd800, 0xd800, 0xd801, 0xd801, 0xd802, 0xd802,
+ 0xd803, 0xd804, 0xd805, 0xd805, 0xd806, 0xd807, 0xd808, 0xd809,
+ 0xd80a, 0xd80b, 0xd80c, 0xd80e, 0xd80f, 0xd810, 0xd811, 0xd813,
+ 0xd814, 0xd815, 0xd817, 0xd818, 0xd81a, 0xd81b, 0xd81d, 0xd81f,
+ 0xd800, 0xd800, 0xd800, 0xd800, 0xd801, 0xd801, 0xd802, 0xd802,
+ 0xd803, 0xd804, 0xd805, 0xd805, 0xd806, 0xd807, 0xd808, 0xd809,
+ 0xd80a, 0xd80b, 0xd80c, 0xd80e, 0xd80f, 0xd810, 0xd811, 0xd813,
+ 0xd814, 0xd815, 0xd817, 0xd818, 0xd81a, 0xd81b, 0xd81d, 0xd81f,
+ 0xd800, 0xd800, 0xd800, 0xd800, 0xd801, 0xd801, 0xd802, 0xd802,
+ 0xd803, 0xd804, 0xd805, 0xd805, 0xd806, 0xd807, 0xd808, 0xd809,
+ 0xd80a, 0xd80b, 0xd80c, 0xd80e, 0xd80f, 0xd810, 0xd811, 0xd813,
+ 0xd814, 0xd815, 0xd817, 0xd818, 0xd81a, 0xd81b, 0xd81d, 0xd81f,
+ 0xd820, 0xd820, 0xd820, 0xd820, 0xd821, 0xd821, 0xd822, 0xd822,
+ 0xd823, 0xd824, 0xd825, 0xd825, 0xd826, 0xd827, 0xd828, 0xd829,
+ 0xd82a, 0xd82b, 0xd82c, 0xd82e, 0xd82f, 0xd830, 0xd831, 0xd833,
+ 0xd834, 0xd835, 0xd837, 0xd838, 0xd83a, 0xd83b, 0xd83d, 0xd83f,
+ 0xd820, 0xd820, 0xd820, 0xd820, 0xd821, 0xd821, 0xd822, 0xd822,
+ 0xd823, 0xd824, 0xd825, 0xd825, 0xd826, 0xd827, 0xd828, 0xd829,
+ 0xd82a, 0xd82b, 0xd82c, 0xd82e, 0xd82f, 0xd830, 0xd831, 0xd833,
+ 0xd834, 0xd835, 0xd837, 0xd838, 0xd83a, 0xd83b, 0xd83d, 0xd83f,
+ 0xd820, 0xd820, 0xd820, 0xd820, 0xd821, 0xd821, 0xd822, 0xd822,
+ 0xd823, 0xd824, 0xd825, 0xd825, 0xd826, 0xd827, 0xd828, 0xd829,
+ 0xd82a, 0xd82b, 0xd82c, 0xd82e, 0xd82f, 0xd830, 0xd831, 0xd833,
+ 0xd834, 0xd835, 0xd837, 0xd838, 0xd83a, 0xd83b, 0xd83d, 0xd83f,
+ 0xd840, 0xd840, 0xd840, 0xd840, 0xd841, 0xd841, 0xd842, 0xd842,
+ 0xd843, 0xd844, 0xd845, 0xd845, 0xd846, 0xd847, 0xd848, 0xd849,
+ 0xd84a, 0xd84b, 0xd84c, 0xd84e, 0xd84f, 0xd850, 0xd851, 0xd853,
+ 0xd854, 0xd855, 0xd857, 0xd858, 0xd85a, 0xd85b, 0xd85d, 0xd85f,
+ 0xd840, 0xd840, 0xd840, 0xd840, 0xd841, 0xd841, 0xd842, 0xd842,
+ 0xd843, 0xd844, 0xd845, 0xd845, 0xd846, 0xd847, 0xd848, 0xd849,
+ 0xd84a, 0xd84b, 0xd84c, 0xd84e, 0xd84f, 0xd850, 0xd851, 0xd853,
+ 0xd854, 0xd855, 0xd857, 0xd858, 0xd85a, 0xd85b, 0xd85d, 0xd85f,
+ 0xd860, 0xd860, 0xd860, 0xd860, 0xd861, 0xd861, 0xd862, 0xd862,
+ 0xd863, 0xd864, 0xd865, 0xd865, 0xd866, 0xd867, 0xd868, 0xd869,
+ 0xd86a, 0xd86b, 0xd86c, 0xd86e, 0xd86f, 0xd870, 0xd871, 0xd873,
+ 0xd874, 0xd875, 0xd877, 0xd878, 0xd87a, 0xd87b, 0xd87d, 0xd87f,
+ 0xd860, 0xd860, 0xd860, 0xd860, 0xd861, 0xd861, 0xd862, 0xd862,
+ 0xd863, 0xd864, 0xd865, 0xd865, 0xd866, 0xd867, 0xd868, 0xd869,
+ 0xd86a, 0xd86b, 0xd86c, 0xd86e, 0xd86f, 0xd870, 0xd871, 0xd873,
+ 0xd874, 0xd875, 0xd877, 0xd878, 0xd87a, 0xd87b, 0xd87d, 0xd87f,
+ 0xd880, 0xd880, 0xd880, 0xd880, 0xd881, 0xd881, 0xd882, 0xd882,
+ 0xd883, 0xd884, 0xd885, 0xd885, 0xd886, 0xd887, 0xd888, 0xd889,
+ 0xd88a, 0xd88b, 0xd88c, 0xd88e, 0xd88f, 0xd890, 0xd891, 0xd893,
+ 0xd894, 0xd895, 0xd897, 0xd898, 0xd89a, 0xd89b, 0xd89d, 0xd89f,
+ 0xd8a0, 0xd8a0, 0xd8a0, 0xd8a0, 0xd8a1, 0xd8a1, 0xd8a2, 0xd8a2,
+ 0xd8a3, 0xd8a4, 0xd8a5, 0xd8a5, 0xd8a6, 0xd8a7, 0xd8a8, 0xd8a9,
+ 0xd8aa, 0xd8ab, 0xd8ac, 0xd8ae, 0xd8af, 0xd8b0, 0xd8b1, 0xd8b3,
+ 0xd8b4, 0xd8b5, 0xd8b7, 0xd8b8, 0xd8ba, 0xd8bb, 0xd8bd, 0xd8bf,
+ 0xd8a0, 0xd8a0, 0xd8a0, 0xd8a0, 0xd8a1, 0xd8a1, 0xd8a2, 0xd8a2,
+ 0xd8a3, 0xd8a4, 0xd8a5, 0xd8a5, 0xd8a6, 0xd8a7, 0xd8a8, 0xd8a9,
+ 0xd8aa, 0xd8ab, 0xd8ac, 0xd8ae, 0xd8af, 0xd8b0, 0xd8b1, 0xd8b3,
+ 0xd8b4, 0xd8b5, 0xd8b7, 0xd8b8, 0xd8ba, 0xd8bb, 0xd8bd, 0xd8bf,
+ 0xd8c0, 0xd8c0, 0xd8c0, 0xd8c0, 0xd8c1, 0xd8c1, 0xd8c2, 0xd8c2,
+ 0xd8c3, 0xd8c4, 0xd8c5, 0xd8c5, 0xd8c6, 0xd8c7, 0xd8c8, 0xd8c9,
+ 0xd8ca, 0xd8cb, 0xd8cc, 0xd8ce, 0xd8cf, 0xd8d0, 0xd8d1, 0xd8d3,
+ 0xd8d4, 0xd8d5, 0xd8d7, 0xd8d8, 0xd8da, 0xd8db, 0xd8dd, 0xd8df,
+ 0xd8e0, 0xd8e0, 0xd8e0, 0xd8e0, 0xd8e1, 0xd8e1, 0xd8e2, 0xd8e2,
+ 0xd8e3, 0xd8e4, 0xd8e5, 0xd8e5, 0xd8e6, 0xd8e7, 0xd8e8, 0xd8e9,
+ 0xd8ea, 0xd8eb, 0xd8ec, 0xd8ee, 0xd8ef, 0xd8f0, 0xd8f1, 0xd8f3,
+ 0xd8f4, 0xd8f5, 0xd8f7, 0xd8f8, 0xd8fa, 0xd8fb, 0xd8fd, 0xd8ff,
+ 0xd8e0, 0xd8e0, 0xd8e0, 0xd8e0, 0xd8e1, 0xd8e1, 0xd8e2, 0xd8e2,
+ 0xd8e3, 0xd8e4, 0xd8e5, 0xd8e5, 0xd8e6, 0xd8e7, 0xd8e8, 0xd8e9,
+ 0xd8ea, 0xd8eb, 0xd8ec, 0xd8ee, 0xd8ef, 0xd8f0, 0xd8f1, 0xd8f3,
+ 0xd8f4, 0xd8f5, 0xd8f7, 0xd8f8, 0xd8fa, 0xd8fb, 0xd8fd, 0xd8ff,
+ 0xd900, 0xd900, 0xd900, 0xd900, 0xd901, 0xd901, 0xd902, 0xd902,
+ 0xd903, 0xd904, 0xd905, 0xd905, 0xd906, 0xd907, 0xd908, 0xd909,
+ 0xd90a, 0xd90b, 0xd90c, 0xd90e, 0xd90f, 0xd910, 0xd911, 0xd913,
+ 0xd914, 0xd915, 0xd917, 0xd918, 0xd91a, 0xd91b, 0xd91d, 0xd91f,
+ 0xd920, 0xd920, 0xd920, 0xd920, 0xd921, 0xd921, 0xd922, 0xd922,
+ 0xd923, 0xd924, 0xd925, 0xd925, 0xd926, 0xd927, 0xd928, 0xd929,
+ 0xd92a, 0xd92b, 0xd92c, 0xd92e, 0xd92f, 0xd930, 0xd931, 0xd933,
+ 0xd934, 0xd935, 0xd937, 0xd938, 0xd93a, 0xd93b, 0xd93d, 0xd93f,
+ 0xd940, 0xd940, 0xd940, 0xd940, 0xd941, 0xd941, 0xd942, 0xd942,
+ 0xd943, 0xd944, 0xd945, 0xd945, 0xd946, 0xd947, 0xd948, 0xd949,
+ 0xd94a, 0xd94b, 0xd94c, 0xd94e, 0xd94f, 0xd950, 0xd951, 0xd953,
+ 0xd954, 0xd955, 0xd957, 0xd958, 0xd95a, 0xd95b, 0xd95d, 0xd95f,
+ 0xd940, 0xd940, 0xd940, 0xd940, 0xd941, 0xd941, 0xd942, 0xd942,
+ 0xd943, 0xd944, 0xd945, 0xd945, 0xd946, 0xd947, 0xd948, 0xd949,
+ 0xd94a, 0xd94b, 0xd94c, 0xd94e, 0xd94f, 0xd950, 0xd951, 0xd953,
+ 0xd954, 0xd955, 0xd957, 0xd958, 0xd95a, 0xd95b, 0xd95d, 0xd95f,
+ 0xd960, 0xd960, 0xd960, 0xd960, 0xd961, 0xd961, 0xd962, 0xd962,
+ 0xd963, 0xd964, 0xd965, 0xd965, 0xd966, 0xd967, 0xd968, 0xd969,
+ 0xd96a, 0xd96b, 0xd96c, 0xd96e, 0xd96f, 0xd970, 0xd971, 0xd973,
+ 0xd974, 0xd975, 0xd977, 0xd978, 0xd97a, 0xd97b, 0xd97d, 0xd97f,
+ 0xd980, 0xd980, 0xd980, 0xd980, 0xd981, 0xd981, 0xd982, 0xd982,
+ 0xd983, 0xd984, 0xd985, 0xd985, 0xd986, 0xd987, 0xd988, 0xd989,
+ 0xd98a, 0xd98b, 0xd98c, 0xd98e, 0xd98f, 0xd990, 0xd991, 0xd993,
+ 0xd994, 0xd995, 0xd997, 0xd998, 0xd99a, 0xd99b, 0xd99d, 0xd99f,
+ 0xd9a0, 0xd9a0, 0xd9a0, 0xd9a0, 0xd9a1, 0xd9a1, 0xd9a2, 0xd9a2,
+ 0xd9a3, 0xd9a4, 0xd9a5, 0xd9a5, 0xd9a6, 0xd9a7, 0xd9a8, 0xd9a9,
+ 0xd9aa, 0xd9ab, 0xd9ac, 0xd9ae, 0xd9af, 0xd9b0, 0xd9b1, 0xd9b3,
+ 0xd9b4, 0xd9b5, 0xd9b7, 0xd9b8, 0xd9ba, 0xd9bb, 0xd9bd, 0xd9bf,
+ 0xd9c0, 0xd9c0, 0xd9c0, 0xd9c0, 0xd9c1, 0xd9c1, 0xd9c2, 0xd9c2,
+ 0xd9c3, 0xd9c4, 0xd9c5, 0xd9c5, 0xd9c6, 0xd9c7, 0xd9c8, 0xd9c9,
+ 0xd9ca, 0xd9cb, 0xd9cc, 0xd9ce, 0xd9cf, 0xd9d0, 0xd9d1, 0xd9d3,
+ 0xd9d4, 0xd9d5, 0xd9d7, 0xd9d8, 0xd9da, 0xd9db, 0xd9dd, 0xd9df,
+ 0xd9e0, 0xd9e0, 0xd9e0, 0xd9e0, 0xd9e1, 0xd9e1, 0xd9e2, 0xd9e2,
+ 0xd9e3, 0xd9e4, 0xd9e5, 0xd9e5, 0xd9e6, 0xd9e7, 0xd9e8, 0xd9e9,
+ 0xd9ea, 0xd9eb, 0xd9ec, 0xd9ee, 0xd9ef, 0xd9f0, 0xd9f1, 0xd9f3,
+ 0xd9f4, 0xd9f5, 0xd9f7, 0xd9f8, 0xd9fa, 0xd9fb, 0xd9fd, 0xd9ff,
+ 0xda00, 0xda00, 0xda00, 0xda00, 0xda01, 0xda01, 0xda02, 0xda02,
+ 0xda03, 0xda04, 0xda05, 0xda05, 0xda06, 0xda07, 0xda08, 0xda09,
+ 0xda0a, 0xda0b, 0xda0c, 0xda0e, 0xda0f, 0xda10, 0xda11, 0xda13,
+ 0xda14, 0xda15, 0xda17, 0xda18, 0xda1a, 0xda1b, 0xda1d, 0xda1f,
+ 0xda20, 0xda20, 0xda20, 0xda20, 0xda21, 0xda21, 0xda22, 0xda22,
+ 0xda23, 0xda24, 0xda25, 0xda25, 0xda26, 0xda27, 0xda28, 0xda29,
+ 0xda2a, 0xda2b, 0xda2c, 0xda2e, 0xda2f, 0xda30, 0xda31, 0xda33,
+ 0xda34, 0xda35, 0xda37, 0xda38, 0xda3a, 0xda3b, 0xda3d, 0xda3f,
+ 0xda40, 0xda40, 0xda40, 0xda40, 0xda41, 0xda41, 0xda42, 0xda42,
+ 0xda43, 0xda44, 0xda45, 0xda45, 0xda46, 0xda47, 0xda48, 0xda49,
+ 0xda4a, 0xda4b, 0xda4c, 0xda4e, 0xda4f, 0xda50, 0xda51, 0xda53,
+ 0xda54, 0xda55, 0xda57, 0xda58, 0xda5a, 0xda5b, 0xda5d, 0xda5f,
+ 0xda60, 0xda60, 0xda60, 0xda60, 0xda61, 0xda61, 0xda62, 0xda62,
+ 0xda63, 0xda64, 0xda65, 0xda65, 0xda66, 0xda67, 0xda68, 0xda69,
+ 0xda6a, 0xda6b, 0xda6c, 0xda6e, 0xda6f, 0xda70, 0xda71, 0xda73,
+ 0xda74, 0xda75, 0xda77, 0xda78, 0xda7a, 0xda7b, 0xda7d, 0xda7f,
+ 0xda80, 0xda80, 0xda80, 0xda80, 0xda81, 0xda81, 0xda82, 0xda82,
+ 0xda83, 0xda84, 0xda85, 0xda85, 0xda86, 0xda87, 0xda88, 0xda89,
+ 0xda8a, 0xda8b, 0xda8c, 0xda8e, 0xda8f, 0xda90, 0xda91, 0xda93,
+ 0xda94, 0xda95, 0xda97, 0xda98, 0xda9a, 0xda9b, 0xda9d, 0xda9f,
+ 0xdaa0, 0xdaa0, 0xdaa0, 0xdaa0, 0xdaa1, 0xdaa1, 0xdaa2, 0xdaa2,
+ 0xdaa3, 0xdaa4, 0xdaa5, 0xdaa5, 0xdaa6, 0xdaa7, 0xdaa8, 0xdaa9,
+ 0xdaaa, 0xdaab, 0xdaac, 0xdaae, 0xdaaf, 0xdab0, 0xdab1, 0xdab3,
+ 0xdab4, 0xdab5, 0xdab7, 0xdab8, 0xdaba, 0xdabb, 0xdabd, 0xdabf,
+ 0xdac0, 0xdac0, 0xdac0, 0xdac0, 0xdac1, 0xdac1, 0xdac2, 0xdac2,
+ 0xdac3, 0xdac4, 0xdac5, 0xdac5, 0xdac6, 0xdac7, 0xdac8, 0xdac9,
+ 0xdaca, 0xdacb, 0xdacc, 0xdace, 0xdacf, 0xdad0, 0xdad1, 0xdad3,
+ 0xdad4, 0xdad5, 0xdad7, 0xdad8, 0xdada, 0xdadb, 0xdadd, 0xdadf,
+ 0xdae0, 0xdae0, 0xdae0, 0xdae0, 0xdae1, 0xdae1, 0xdae2, 0xdae2,
+ 0xdae3, 0xdae4, 0xdae5, 0xdae5, 0xdae6, 0xdae7, 0xdae8, 0xdae9,
+ 0xdaea, 0xdaeb, 0xdaec, 0xdaee, 0xdaef, 0xdaf0, 0xdaf1, 0xdaf3,
+ 0xdaf4, 0xdaf5, 0xdaf7, 0xdaf8, 0xdafa, 0xdafb, 0xdafd, 0xdaff,
+ 0xdb00, 0xdb00, 0xdb00, 0xdb00, 0xdb01, 0xdb01, 0xdb02, 0xdb02,
+ 0xdb03, 0xdb04, 0xdb05, 0xdb05, 0xdb06, 0xdb07, 0xdb08, 0xdb09,
+ 0xdb0a, 0xdb0b, 0xdb0c, 0xdb0e, 0xdb0f, 0xdb10, 0xdb11, 0xdb13,
+ 0xdb14, 0xdb15, 0xdb17, 0xdb18, 0xdb1a, 0xdb1b, 0xdb1d, 0xdb1f,
+ 0xdb20, 0xdb20, 0xdb20, 0xdb20, 0xdb21, 0xdb21, 0xdb22, 0xdb22,
+ 0xdb23, 0xdb24, 0xdb25, 0xdb25, 0xdb26, 0xdb27, 0xdb28, 0xdb29,
+ 0xdb2a, 0xdb2b, 0xdb2c, 0xdb2e, 0xdb2f, 0xdb30, 0xdb31, 0xdb33,
+ 0xdb34, 0xdb35, 0xdb37, 0xdb38, 0xdb3a, 0xdb3b, 0xdb3d, 0xdb3f,
+ 0xdb40, 0xdb40, 0xdb40, 0xdb40, 0xdb41, 0xdb41, 0xdb42, 0xdb42,
+ 0xdb43, 0xdb44, 0xdb45, 0xdb45, 0xdb46, 0xdb47, 0xdb48, 0xdb49,
+ 0xdb4a, 0xdb4b, 0xdb4c, 0xdb4e, 0xdb4f, 0xdb50, 0xdb51, 0xdb53,
+ 0xdb54, 0xdb55, 0xdb57, 0xdb58, 0xdb5a, 0xdb5b, 0xdb5d, 0xdb5f,
+ 0xdb80, 0xdb80, 0xdb80, 0xdb80, 0xdb81, 0xdb81, 0xdb82, 0xdb82,
+ 0xdb83, 0xdb84, 0xdb85, 0xdb85, 0xdb86, 0xdb87, 0xdb88, 0xdb89,
+ 0xdb8a, 0xdb8b, 0xdb8c, 0xdb8e, 0xdb8f, 0xdb90, 0xdb91, 0xdb93,
+ 0xdb94, 0xdb95, 0xdb97, 0xdb98, 0xdb9a, 0xdb9b, 0xdb9d, 0xdb9f,
+ 0xdba0, 0xdba0, 0xdba0, 0xdba0, 0xdba1, 0xdba1, 0xdba2, 0xdba2,
+ 0xdba3, 0xdba4, 0xdba5, 0xdba5, 0xdba6, 0xdba7, 0xdba8, 0xdba9,
+ 0xdbaa, 0xdbab, 0xdbac, 0xdbae, 0xdbaf, 0xdbb0, 0xdbb1, 0xdbb3,
+ 0xdbb4, 0xdbb5, 0xdbb7, 0xdbb8, 0xdbba, 0xdbbb, 0xdbbd, 0xdbbf,
+ 0xdbc0, 0xdbc0, 0xdbc0, 0xdbc0, 0xdbc1, 0xdbc1, 0xdbc2, 0xdbc2,
+ 0xdbc3, 0xdbc4, 0xdbc5, 0xdbc5, 0xdbc6, 0xdbc7, 0xdbc8, 0xdbc9,
+ 0xdbca, 0xdbcb, 0xdbcc, 0xdbce, 0xdbcf, 0xdbd0, 0xdbd1, 0xdbd3,
+ 0xdbd4, 0xdbd5, 0xdbd7, 0xdbd8, 0xdbda, 0xdbdb, 0xdbdd, 0xdbdf,
+ 0xdbe0, 0xdbe0, 0xdbe0, 0xdbe0, 0xdbe1, 0xdbe1, 0xdbe2, 0xdbe2,
+ 0xdbe3, 0xdbe4, 0xdbe5, 0xdbe5, 0xdbe6, 0xdbe7, 0xdbe8, 0xdbe9,
+ 0xdbea, 0xdbeb, 0xdbec, 0xdbee, 0xdbef, 0xdbf0, 0xdbf1, 0xdbf3,
+ 0xdbf4, 0xdbf5, 0xdbf7, 0xdbf8, 0xdbfa, 0xdbfb, 0xdbfd, 0xdbff,
+ 0xdc00, 0xdc00, 0xdc00, 0xdc00, 0xdc01, 0xdc01, 0xdc02, 0xdc02,
+ 0xdc03, 0xdc04, 0xdc05, 0xdc05, 0xdc06, 0xdc07, 0xdc08, 0xdc09,
+ 0xdc0a, 0xdc0b, 0xdc0c, 0xdc0e, 0xdc0f, 0xdc10, 0xdc11, 0xdc13,
+ 0xdc14, 0xdc15, 0xdc17, 0xdc18, 0xdc1a, 0xdc1b, 0xdc1d, 0xdc1f,
+ 0xdc40, 0xdc40, 0xdc40, 0xdc40, 0xdc41, 0xdc41, 0xdc42, 0xdc42,
+ 0xdc43, 0xdc44, 0xdc45, 0xdc45, 0xdc46, 0xdc47, 0xdc48, 0xdc49,
+ 0xdc4a, 0xdc4b, 0xdc4c, 0xdc4e, 0xdc4f, 0xdc50, 0xdc51, 0xdc53,
+ 0xdc54, 0xdc55, 0xdc57, 0xdc58, 0xdc5a, 0xdc5b, 0xdc5d, 0xdc5f,
+ 0xdc60, 0xdc60, 0xdc60, 0xdc60, 0xdc61, 0xdc61, 0xdc62, 0xdc62,
+ 0xdc63, 0xdc64, 0xdc65, 0xdc65, 0xdc66, 0xdc67, 0xdc68, 0xdc69,
+ 0xdc6a, 0xdc6b, 0xdc6c, 0xdc6e, 0xdc6f, 0xdc70, 0xdc71, 0xdc73,
+ 0xdc74, 0xdc75, 0xdc77, 0xdc78, 0xdc7a, 0xdc7b, 0xdc7d, 0xdc7f,
+ 0xdc80, 0xdc80, 0xdc80, 0xdc80, 0xdc81, 0xdc81, 0xdc82, 0xdc82,
+ 0xdc83, 0xdc84, 0xdc85, 0xdc85, 0xdc86, 0xdc87, 0xdc88, 0xdc89,
+ 0xdc8a, 0xdc8b, 0xdc8c, 0xdc8e, 0xdc8f, 0xdc90, 0xdc91, 0xdc93,
+ 0xdc94, 0xdc95, 0xdc97, 0xdc98, 0xdc9a, 0xdc9b, 0xdc9d, 0xdc9f,
+ 0xdcc0, 0xdcc0, 0xdcc0, 0xdcc0, 0xdcc1, 0xdcc1, 0xdcc2, 0xdcc2,
+ 0xdcc3, 0xdcc4, 0xdcc5, 0xdcc5, 0xdcc6, 0xdcc7, 0xdcc8, 0xdcc9,
+ 0xdcca, 0xdccb, 0xdccc, 0xdcce, 0xdccf, 0xdcd0, 0xdcd1, 0xdcd3,
+ 0xdcd4, 0xdcd5, 0xdcd7, 0xdcd8, 0xdcda, 0xdcdb, 0xdcdd, 0xdcdf,
+ 0xdce0, 0xdce0, 0xdce0, 0xdce0, 0xdce1, 0xdce1, 0xdce2, 0xdce2,
+ 0xdce3, 0xdce4, 0xdce5, 0xdce5, 0xdce6, 0xdce7, 0xdce8, 0xdce9,
+ 0xdcea, 0xdceb, 0xdcec, 0xdcee, 0xdcef, 0xdcf0, 0xdcf1, 0xdcf3,
+ 0xdcf4, 0xdcf5, 0xdcf7, 0xdcf8, 0xdcfa, 0xdcfb, 0xdcfd, 0xdcff,
+ 0xdd00, 0xdd00, 0xdd00, 0xdd00, 0xdd01, 0xdd01, 0xdd02, 0xdd02,
+ 0xdd03, 0xdd04, 0xdd05, 0xdd05, 0xdd06, 0xdd07, 0xdd08, 0xdd09,
+ 0xdd0a, 0xdd0b, 0xdd0c, 0xdd0e, 0xdd0f, 0xdd10, 0xdd11, 0xdd13,
+ 0xdd14, 0xdd15, 0xdd17, 0xdd18, 0xdd1a, 0xdd1b, 0xdd1d, 0xdd1f,
+ 0xdd40, 0xdd40, 0xdd40, 0xdd40, 0xdd41, 0xdd41, 0xdd42, 0xdd42,
+ 0xdd43, 0xdd44, 0xdd45, 0xdd45, 0xdd46, 0xdd47, 0xdd48, 0xdd49,
+ 0xdd4a, 0xdd4b, 0xdd4c, 0xdd4e, 0xdd4f, 0xdd50, 0xdd51, 0xdd53,
+ 0xdd54, 0xdd55, 0xdd57, 0xdd58, 0xdd5a, 0xdd5b, 0xdd5d, 0xdd5f,
+ 0xdd60, 0xdd60, 0xdd60, 0xdd60, 0xdd61, 0xdd61, 0xdd62, 0xdd62,
+ 0xdd63, 0xdd64, 0xdd65, 0xdd65, 0xdd66, 0xdd67, 0xdd68, 0xdd69,
+ 0xdd6a, 0xdd6b, 0xdd6c, 0xdd6e, 0xdd6f, 0xdd70, 0xdd71, 0xdd73,
+ 0xdd74, 0xdd75, 0xdd77, 0xdd78, 0xdd7a, 0xdd7b, 0xdd7d, 0xdd7f,
+ 0xdd80, 0xdd80, 0xdd80, 0xdd80, 0xdd81, 0xdd81, 0xdd82, 0xdd82,
+ 0xdd83, 0xdd84, 0xdd85, 0xdd85, 0xdd86, 0xdd87, 0xdd88, 0xdd89,
+ 0xdd8a, 0xdd8b, 0xdd8c, 0xdd8e, 0xdd8f, 0xdd90, 0xdd91, 0xdd93,
+ 0xdd94, 0xdd95, 0xdd97, 0xdd98, 0xdd9a, 0xdd9b, 0xdd9d, 0xdd9f,
+ 0xddc0, 0xddc0, 0xddc0, 0xddc0, 0xddc1, 0xddc1, 0xddc2, 0xddc2,
+ 0xddc3, 0xddc4, 0xddc5, 0xddc5, 0xddc6, 0xddc7, 0xddc8, 0xddc9,
+ 0xddca, 0xddcb, 0xddcc, 0xddce, 0xddcf, 0xddd0, 0xddd1, 0xddd3,
+ 0xddd4, 0xddd5, 0xddd7, 0xddd8, 0xddda, 0xdddb, 0xdddd, 0xdddf,
+ 0xdde0, 0xdde0, 0xdde0, 0xdde0, 0xdde1, 0xdde1, 0xdde2, 0xdde2,
+ 0xdde3, 0xdde4, 0xdde5, 0xdde5, 0xdde6, 0xdde7, 0xdde8, 0xdde9,
+ 0xddea, 0xddeb, 0xddec, 0xddee, 0xddef, 0xddf0, 0xddf1, 0xddf3,
+ 0xddf4, 0xddf5, 0xddf7, 0xddf8, 0xddfa, 0xddfb, 0xddfd, 0xddff,
+ 0xde20, 0xde20, 0xde20, 0xde20, 0xde21, 0xde21, 0xde22, 0xde22,
+ 0xde23, 0xde24, 0xde25, 0xde25, 0xde26, 0xde27, 0xde28, 0xde29,
+ 0xde2a, 0xde2b, 0xde2c, 0xde2e, 0xde2f, 0xde30, 0xde31, 0xde33,
+ 0xde34, 0xde35, 0xde37, 0xde38, 0xde3a, 0xde3b, 0xde3d, 0xde3f,
+ 0xde40, 0xde40, 0xde40, 0xde40, 0xde41, 0xde41, 0xde42, 0xde42,
+ 0xde43, 0xde44, 0xde45, 0xde45, 0xde46, 0xde47, 0xde48, 0xde49,
+ 0xde4a, 0xde4b, 0xde4c, 0xde4e, 0xde4f, 0xde50, 0xde51, 0xde53,
+ 0xde54, 0xde55, 0xde57, 0xde58, 0xde5a, 0xde5b, 0xde5d, 0xde5f,
+ 0xde80, 0xde80, 0xde80, 0xde80, 0xde81, 0xde81, 0xde82, 0xde82,
+ 0xde83, 0xde84, 0xde85, 0xde85, 0xde86, 0xde87, 0xde88, 0xde89,
+ 0xde8a, 0xde8b, 0xde8c, 0xde8e, 0xde8f, 0xde90, 0xde91, 0xde93,
+ 0xde94, 0xde95, 0xde97, 0xde98, 0xde9a, 0xde9b, 0xde9d, 0xde9f,
+ 0xdea0, 0xdea0, 0xdea0, 0xdea0, 0xdea1, 0xdea1, 0xdea2, 0xdea2,
+ 0xdea3, 0xdea4, 0xdea5, 0xdea5, 0xdea6, 0xdea7, 0xdea8, 0xdea9,
+ 0xdeaa, 0xdeab, 0xdeac, 0xdeae, 0xdeaf, 0xdeb0, 0xdeb1, 0xdeb3,
+ 0xdeb4, 0xdeb5, 0xdeb7, 0xdeb8, 0xdeba, 0xdebb, 0xdebd, 0xdebf,
+ 0xdee0, 0xdee0, 0xdee0, 0xdee0, 0xdee1, 0xdee1, 0xdee2, 0xdee2,
+ 0xdee3, 0xdee4, 0xdee5, 0xdee5, 0xdee6, 0xdee7, 0xdee8, 0xdee9,
+ 0xdeea, 0xdeeb, 0xdeec, 0xdeee, 0xdeef, 0xdef0, 0xdef1, 0xdef3,
+ 0xdef4, 0xdef5, 0xdef7, 0xdef8, 0xdefa, 0xdefb, 0xdefd, 0xdeff,
+ 0xdf00, 0xdf00, 0xdf00, 0xdf00, 0xdf01, 0xdf01, 0xdf02, 0xdf02,
+ 0xdf03, 0xdf04, 0xdf05, 0xdf05, 0xdf06, 0xdf07, 0xdf08, 0xdf09,
+ 0xdf0a, 0xdf0b, 0xdf0c, 0xdf0e, 0xdf0f, 0xdf10, 0xdf11, 0xdf13,
+ 0xdf14, 0xdf15, 0xdf17, 0xdf18, 0xdf1a, 0xdf1b, 0xdf1d, 0xdf1f,
+ 0xdf40, 0xdf40, 0xdf40, 0xdf40, 0xdf41, 0xdf41, 0xdf42, 0xdf42,
+ 0xdf43, 0xdf44, 0xdf45, 0xdf45, 0xdf46, 0xdf47, 0xdf48, 0xdf49,
+ 0xdf4a, 0xdf4b, 0xdf4c, 0xdf4e, 0xdf4f, 0xdf50, 0xdf51, 0xdf53,
+ 0xdf54, 0xdf55, 0xdf57, 0xdf58, 0xdf5a, 0xdf5b, 0xdf5d, 0xdf5f,
+ 0xdf60, 0xdf60, 0xdf60, 0xdf60, 0xdf61, 0xdf61, 0xdf62, 0xdf62,
+ 0xdf63, 0xdf64, 0xdf65, 0xdf65, 0xdf66, 0xdf67, 0xdf68, 0xdf69,
+ 0xdf6a, 0xdf6b, 0xdf6c, 0xdf6e, 0xdf6f, 0xdf70, 0xdf71, 0xdf73,
+ 0xdf74, 0xdf75, 0xdf77, 0xdf78, 0xdf7a, 0xdf7b, 0xdf7d, 0xdf7f,
+ 0xdfa0, 0xdfa0, 0xdfa0, 0xdfa0, 0xdfa1, 0xdfa1, 0xdfa2, 0xdfa2,
+ 0xdfa3, 0xdfa4, 0xdfa5, 0xdfa5, 0xdfa6, 0xdfa7, 0xdfa8, 0xdfa9,
+ 0xdfaa, 0xdfab, 0xdfac, 0xdfae, 0xdfaf, 0xdfb0, 0xdfb1, 0xdfb3,
+ 0xdfb4, 0xdfb5, 0xdfb7, 0xdfb8, 0xdfba, 0xdfbb, 0xdfbd, 0xdfbf,
+ 0xdfe0, 0xdfe0, 0xdfe0, 0xdfe0, 0xdfe1, 0xdfe1, 0xdfe2, 0xdfe2,
+ 0xdfe3, 0xdfe4, 0xdfe5, 0xdfe5, 0xdfe6, 0xdfe7, 0xdfe8, 0xdfe9,
+ 0xdfea, 0xdfeb, 0xdfec, 0xdfee, 0xdfef, 0xdff0, 0xdff1, 0xdff3,
+ 0xdff4, 0xdff5, 0xdff7, 0xdff8, 0xdffa, 0xdffb, 0xdffd, 0xdfff,
+ 0xe800, 0xe800, 0xe800, 0xe800, 0xe801, 0xe801, 0xe802, 0xe802,
+ 0xe803, 0xe804, 0xe805, 0xe805, 0xe806, 0xe807, 0xe808, 0xe809,
+ 0xe80a, 0xe80b, 0xe80c, 0xe80e, 0xe80f, 0xe810, 0xe811, 0xe813,
+ 0xe814, 0xe815, 0xe817, 0xe818, 0xe81a, 0xe81b, 0xe81d, 0xe81f,
+ 0xe800, 0xe800, 0xe800, 0xe800, 0xe801, 0xe801, 0xe802, 0xe802,
+ 0xe803, 0xe804, 0xe805, 0xe805, 0xe806, 0xe807, 0xe808, 0xe809,
+ 0xe80a, 0xe80b, 0xe80c, 0xe80e, 0xe80f, 0xe810, 0xe811, 0xe813,
+ 0xe814, 0xe815, 0xe817, 0xe818, 0xe81a, 0xe81b, 0xe81d, 0xe81f,
+ 0xe800, 0xe800, 0xe800, 0xe800, 0xe801, 0xe801, 0xe802, 0xe802,
+ 0xe803, 0xe804, 0xe805, 0xe805, 0xe806, 0xe807, 0xe808, 0xe809,
+ 0xe80a, 0xe80b, 0xe80c, 0xe80e, 0xe80f, 0xe810, 0xe811, 0xe813,
+ 0xe814, 0xe815, 0xe817, 0xe818, 0xe81a, 0xe81b, 0xe81d, 0xe81f,
+ 0xe800, 0xe800, 0xe800, 0xe800, 0xe801, 0xe801, 0xe802, 0xe802,
+ 0xe803, 0xe804, 0xe805, 0xe805, 0xe806, 0xe807, 0xe808, 0xe809,
+ 0xe80a, 0xe80b, 0xe80c, 0xe80e, 0xe80f, 0xe810, 0xe811, 0xe813,
+ 0xe814, 0xe815, 0xe817, 0xe818, 0xe81a, 0xe81b, 0xe81d, 0xe81f,
+ 0xe800, 0xe800, 0xe800, 0xe800, 0xe801, 0xe801, 0xe802, 0xe802,
+ 0xe803, 0xe804, 0xe805, 0xe805, 0xe806, 0xe807, 0xe808, 0xe809,
+ 0xe80a, 0xe80b, 0xe80c, 0xe80e, 0xe80f, 0xe810, 0xe811, 0xe813,
+ 0xe814, 0xe815, 0xe817, 0xe818, 0xe81a, 0xe81b, 0xe81d, 0xe81f,
+ 0xe820, 0xe820, 0xe820, 0xe820, 0xe821, 0xe821, 0xe822, 0xe822,
+ 0xe823, 0xe824, 0xe825, 0xe825, 0xe826, 0xe827, 0xe828, 0xe829,
+ 0xe82a, 0xe82b, 0xe82c, 0xe82e, 0xe82f, 0xe830, 0xe831, 0xe833,
+ 0xe834, 0xe835, 0xe837, 0xe838, 0xe83a, 0xe83b, 0xe83d, 0xe83f,
+ 0xe820, 0xe820, 0xe820, 0xe820, 0xe821, 0xe821, 0xe822, 0xe822,
+ 0xe823, 0xe824, 0xe825, 0xe825, 0xe826, 0xe827, 0xe828, 0xe829,
+ 0xe82a, 0xe82b, 0xe82c, 0xe82e, 0xe82f, 0xe830, 0xe831, 0xe833,
+ 0xe834, 0xe835, 0xe837, 0xe838, 0xe83a, 0xe83b, 0xe83d, 0xe83f,
+ 0xe820, 0xe820, 0xe820, 0xe820, 0xe821, 0xe821, 0xe822, 0xe822,
+ 0xe823, 0xe824, 0xe825, 0xe825, 0xe826, 0xe827, 0xe828, 0xe829,
+ 0xe82a, 0xe82b, 0xe82c, 0xe82e, 0xe82f, 0xe830, 0xe831, 0xe833,
+ 0xe834, 0xe835, 0xe837, 0xe838, 0xe83a, 0xe83b, 0xe83d, 0xe83f,
+ 0xe840, 0xe840, 0xe840, 0xe840, 0xe841, 0xe841, 0xe842, 0xe842,
+ 0xe843, 0xe844, 0xe845, 0xe845, 0xe846, 0xe847, 0xe848, 0xe849,
+ 0xe84a, 0xe84b, 0xe84c, 0xe84e, 0xe84f, 0xe850, 0xe851, 0xe853,
+ 0xe854, 0xe855, 0xe857, 0xe858, 0xe85a, 0xe85b, 0xe85d, 0xe85f,
+ 0xe840, 0xe840, 0xe840, 0xe840, 0xe841, 0xe841, 0xe842, 0xe842,
+ 0xe843, 0xe844, 0xe845, 0xe845, 0xe846, 0xe847, 0xe848, 0xe849,
+ 0xe84a, 0xe84b, 0xe84c, 0xe84e, 0xe84f, 0xe850, 0xe851, 0xe853,
+ 0xe854, 0xe855, 0xe857, 0xe858, 0xe85a, 0xe85b, 0xe85d, 0xe85f,
+ 0xe860, 0xe860, 0xe860, 0xe860, 0xe861, 0xe861, 0xe862, 0xe862,
+ 0xe863, 0xe864, 0xe865, 0xe865, 0xe866, 0xe867, 0xe868, 0xe869,
+ 0xe86a, 0xe86b, 0xe86c, 0xe86e, 0xe86f, 0xe870, 0xe871, 0xe873,
+ 0xe874, 0xe875, 0xe877, 0xe878, 0xe87a, 0xe87b, 0xe87d, 0xe87f,
+ 0xe860, 0xe860, 0xe860, 0xe860, 0xe861, 0xe861, 0xe862, 0xe862,
+ 0xe863, 0xe864, 0xe865, 0xe865, 0xe866, 0xe867, 0xe868, 0xe869,
+ 0xe86a, 0xe86b, 0xe86c, 0xe86e, 0xe86f, 0xe870, 0xe871, 0xe873,
+ 0xe874, 0xe875, 0xe877, 0xe878, 0xe87a, 0xe87b, 0xe87d, 0xe87f,
+ 0xe880, 0xe880, 0xe880, 0xe880, 0xe881, 0xe881, 0xe882, 0xe882,
+ 0xe883, 0xe884, 0xe885, 0xe885, 0xe886, 0xe887, 0xe888, 0xe889,
+ 0xe88a, 0xe88b, 0xe88c, 0xe88e, 0xe88f, 0xe890, 0xe891, 0xe893,
+ 0xe894, 0xe895, 0xe897, 0xe898, 0xe89a, 0xe89b, 0xe89d, 0xe89f,
+ 0xe8a0, 0xe8a0, 0xe8a0, 0xe8a0, 0xe8a1, 0xe8a1, 0xe8a2, 0xe8a2,
+ 0xe8a3, 0xe8a4, 0xe8a5, 0xe8a5, 0xe8a6, 0xe8a7, 0xe8a8, 0xe8a9,
+ 0xe8aa, 0xe8ab, 0xe8ac, 0xe8ae, 0xe8af, 0xe8b0, 0xe8b1, 0xe8b3,
+ 0xe8b4, 0xe8b5, 0xe8b7, 0xe8b8, 0xe8ba, 0xe8bb, 0xe8bd, 0xe8bf,
+ 0xe8a0, 0xe8a0, 0xe8a0, 0xe8a0, 0xe8a1, 0xe8a1, 0xe8a2, 0xe8a2,
+ 0xe8a3, 0xe8a4, 0xe8a5, 0xe8a5, 0xe8a6, 0xe8a7, 0xe8a8, 0xe8a9,
+ 0xe8aa, 0xe8ab, 0xe8ac, 0xe8ae, 0xe8af, 0xe8b0, 0xe8b1, 0xe8b3,
+ 0xe8b4, 0xe8b5, 0xe8b7, 0xe8b8, 0xe8ba, 0xe8bb, 0xe8bd, 0xe8bf,
+ 0xe8c0, 0xe8c0, 0xe8c0, 0xe8c0, 0xe8c1, 0xe8c1, 0xe8c2, 0xe8c2,
+ 0xe8c3, 0xe8c4, 0xe8c5, 0xe8c5, 0xe8c6, 0xe8c7, 0xe8c8, 0xe8c9,
+ 0xe8ca, 0xe8cb, 0xe8cc, 0xe8ce, 0xe8cf, 0xe8d0, 0xe8d1, 0xe8d3,
+ 0xe8d4, 0xe8d5, 0xe8d7, 0xe8d8, 0xe8da, 0xe8db, 0xe8dd, 0xe8df,
+ 0xe8e0, 0xe8e0, 0xe8e0, 0xe8e0, 0xe8e1, 0xe8e1, 0xe8e2, 0xe8e2,
+ 0xe8e3, 0xe8e4, 0xe8e5, 0xe8e5, 0xe8e6, 0xe8e7, 0xe8e8, 0xe8e9,
+ 0xe8ea, 0xe8eb, 0xe8ec, 0xe8ee, 0xe8ef, 0xe8f0, 0xe8f1, 0xe8f3,
+ 0xe8f4, 0xe8f5, 0xe8f7, 0xe8f8, 0xe8fa, 0xe8fb, 0xe8fd, 0xe8ff,
+ 0xe8e0, 0xe8e0, 0xe8e0, 0xe8e0, 0xe8e1, 0xe8e1, 0xe8e2, 0xe8e2,
+ 0xe8e3, 0xe8e4, 0xe8e5, 0xe8e5, 0xe8e6, 0xe8e7, 0xe8e8, 0xe8e9,
+ 0xe8ea, 0xe8eb, 0xe8ec, 0xe8ee, 0xe8ef, 0xe8f0, 0xe8f1, 0xe8f3,
+ 0xe8f4, 0xe8f5, 0xe8f7, 0xe8f8, 0xe8fa, 0xe8fb, 0xe8fd, 0xe8ff,
+ 0xe900, 0xe900, 0xe900, 0xe900, 0xe901, 0xe901, 0xe902, 0xe902,
+ 0xe903, 0xe904, 0xe905, 0xe905, 0xe906, 0xe907, 0xe908, 0xe909,
+ 0xe90a, 0xe90b, 0xe90c, 0xe90e, 0xe90f, 0xe910, 0xe911, 0xe913,
+ 0xe914, 0xe915, 0xe917, 0xe918, 0xe91a, 0xe91b, 0xe91d, 0xe91f,
+ 0xe920, 0xe920, 0xe920, 0xe920, 0xe921, 0xe921, 0xe922, 0xe922,
+ 0xe923, 0xe924, 0xe925, 0xe925, 0xe926, 0xe927, 0xe928, 0xe929,
+ 0xe92a, 0xe92b, 0xe92c, 0xe92e, 0xe92f, 0xe930, 0xe931, 0xe933,
+ 0xe934, 0xe935, 0xe937, 0xe938, 0xe93a, 0xe93b, 0xe93d, 0xe93f,
+ 0xe940, 0xe940, 0xe940, 0xe940, 0xe941, 0xe941, 0xe942, 0xe942,
+ 0xe943, 0xe944, 0xe945, 0xe945, 0xe946, 0xe947, 0xe948, 0xe949,
+ 0xe94a, 0xe94b, 0xe94c, 0xe94e, 0xe94f, 0xe950, 0xe951, 0xe953,
+ 0xe954, 0xe955, 0xe957, 0xe958, 0xe95a, 0xe95b, 0xe95d, 0xe95f,
+ 0xe940, 0xe940, 0xe940, 0xe940, 0xe941, 0xe941, 0xe942, 0xe942,
+ 0xe943, 0xe944, 0xe945, 0xe945, 0xe946, 0xe947, 0xe948, 0xe949,
+ 0xe94a, 0xe94b, 0xe94c, 0xe94e, 0xe94f, 0xe950, 0xe951, 0xe953,
+ 0xe954, 0xe955, 0xe957, 0xe958, 0xe95a, 0xe95b, 0xe95d, 0xe95f,
+ 0xe960, 0xe960, 0xe960, 0xe960, 0xe961, 0xe961, 0xe962, 0xe962,
+ 0xe963, 0xe964, 0xe965, 0xe965, 0xe966, 0xe967, 0xe968, 0xe969,
+ 0xe96a, 0xe96b, 0xe96c, 0xe96e, 0xe96f, 0xe970, 0xe971, 0xe973,
+ 0xe974, 0xe975, 0xe977, 0xe978, 0xe97a, 0xe97b, 0xe97d, 0xe97f,
+ 0xe980, 0xe980, 0xe980, 0xe980, 0xe981, 0xe981, 0xe982, 0xe982,
+ 0xe983, 0xe984, 0xe985, 0xe985, 0xe986, 0xe987, 0xe988, 0xe989,
+ 0xe98a, 0xe98b, 0xe98c, 0xe98e, 0xe98f, 0xe990, 0xe991, 0xe993,
+ 0xe994, 0xe995, 0xe997, 0xe998, 0xe99a, 0xe99b, 0xe99d, 0xe99f,
+ 0xe9a0, 0xe9a0, 0xe9a0, 0xe9a0, 0xe9a1, 0xe9a1, 0xe9a2, 0xe9a2,
+ 0xe9a3, 0xe9a4, 0xe9a5, 0xe9a5, 0xe9a6, 0xe9a7, 0xe9a8, 0xe9a9,
+ 0xe9aa, 0xe9ab, 0xe9ac, 0xe9ae, 0xe9af, 0xe9b0, 0xe9b1, 0xe9b3,
+ 0xe9b4, 0xe9b5, 0xe9b7, 0xe9b8, 0xe9ba, 0xe9bb, 0xe9bd, 0xe9bf,
+ 0xe9c0, 0xe9c0, 0xe9c0, 0xe9c0, 0xe9c1, 0xe9c1, 0xe9c2, 0xe9c2,
+ 0xe9c3, 0xe9c4, 0xe9c5, 0xe9c5, 0xe9c6, 0xe9c7, 0xe9c8, 0xe9c9,
+ 0xe9ca, 0xe9cb, 0xe9cc, 0xe9ce, 0xe9cf, 0xe9d0, 0xe9d1, 0xe9d3,
+ 0xe9d4, 0xe9d5, 0xe9d7, 0xe9d8, 0xe9da, 0xe9db, 0xe9dd, 0xe9df,
+ 0xe9e0, 0xe9e0, 0xe9e0, 0xe9e0, 0xe9e1, 0xe9e1, 0xe9e2, 0xe9e2,
+ 0xe9e3, 0xe9e4, 0xe9e5, 0xe9e5, 0xe9e6, 0xe9e7, 0xe9e8, 0xe9e9,
+ 0xe9ea, 0xe9eb, 0xe9ec, 0xe9ee, 0xe9ef, 0xe9f0, 0xe9f1, 0xe9f3,
+ 0xe9f4, 0xe9f5, 0xe9f7, 0xe9f8, 0xe9fa, 0xe9fb, 0xe9fd, 0xe9ff,
+ 0xea00, 0xea00, 0xea00, 0xea00, 0xea01, 0xea01, 0xea02, 0xea02,
+ 0xea03, 0xea04, 0xea05, 0xea05, 0xea06, 0xea07, 0xea08, 0xea09,
+ 0xea0a, 0xea0b, 0xea0c, 0xea0e, 0xea0f, 0xea10, 0xea11, 0xea13,
+ 0xea14, 0xea15, 0xea17, 0xea18, 0xea1a, 0xea1b, 0xea1d, 0xea1f,
+ 0xea20, 0xea20, 0xea20, 0xea20, 0xea21, 0xea21, 0xea22, 0xea22,
+ 0xea23, 0xea24, 0xea25, 0xea25, 0xea26, 0xea27, 0xea28, 0xea29,
+ 0xea2a, 0xea2b, 0xea2c, 0xea2e, 0xea2f, 0xea30, 0xea31, 0xea33,
+ 0xea34, 0xea35, 0xea37, 0xea38, 0xea3a, 0xea3b, 0xea3d, 0xea3f,
+ 0xea40, 0xea40, 0xea40, 0xea40, 0xea41, 0xea41, 0xea42, 0xea42,
+ 0xea43, 0xea44, 0xea45, 0xea45, 0xea46, 0xea47, 0xea48, 0xea49,
+ 0xea4a, 0xea4b, 0xea4c, 0xea4e, 0xea4f, 0xea50, 0xea51, 0xea53,
+ 0xea54, 0xea55, 0xea57, 0xea58, 0xea5a, 0xea5b, 0xea5d, 0xea5f,
+ 0xea60, 0xea60, 0xea60, 0xea60, 0xea61, 0xea61, 0xea62, 0xea62,
+ 0xea63, 0xea64, 0xea65, 0xea65, 0xea66, 0xea67, 0xea68, 0xea69,
+ 0xea6a, 0xea6b, 0xea6c, 0xea6e, 0xea6f, 0xea70, 0xea71, 0xea73,
+ 0xea74, 0xea75, 0xea77, 0xea78, 0xea7a, 0xea7b, 0xea7d, 0xea7f,
+ 0xea80, 0xea80, 0xea80, 0xea80, 0xea81, 0xea81, 0xea82, 0xea82,
+ 0xea83, 0xea84, 0xea85, 0xea85, 0xea86, 0xea87, 0xea88, 0xea89,
+ 0xea8a, 0xea8b, 0xea8c, 0xea8e, 0xea8f, 0xea90, 0xea91, 0xea93,
+ 0xea94, 0xea95, 0xea97, 0xea98, 0xea9a, 0xea9b, 0xea9d, 0xea9f,
+ 0xeaa0, 0xeaa0, 0xeaa0, 0xeaa0, 0xeaa1, 0xeaa1, 0xeaa2, 0xeaa2,
+ 0xeaa3, 0xeaa4, 0xeaa5, 0xeaa5, 0xeaa6, 0xeaa7, 0xeaa8, 0xeaa9,
+ 0xeaaa, 0xeaab, 0xeaac, 0xeaae, 0xeaaf, 0xeab0, 0xeab1, 0xeab3,
+ 0xeab4, 0xeab5, 0xeab7, 0xeab8, 0xeaba, 0xeabb, 0xeabd, 0xeabf,
+ 0xeac0, 0xeac0, 0xeac0, 0xeac0, 0xeac1, 0xeac1, 0xeac2, 0xeac2,
+ 0xeac3, 0xeac4, 0xeac5, 0xeac5, 0xeac6, 0xeac7, 0xeac8, 0xeac9,
+ 0xeaca, 0xeacb, 0xeacc, 0xeace, 0xeacf, 0xead0, 0xead1, 0xead3,
+ 0xead4, 0xead5, 0xead7, 0xead8, 0xeada, 0xeadb, 0xeadd, 0xeadf,
+ 0xeae0, 0xeae0, 0xeae0, 0xeae0, 0xeae1, 0xeae1, 0xeae2, 0xeae2,
+ 0xeae3, 0xeae4, 0xeae5, 0xeae5, 0xeae6, 0xeae7, 0xeae8, 0xeae9,
+ 0xeaea, 0xeaeb, 0xeaec, 0xeaee, 0xeaef, 0xeaf0, 0xeaf1, 0xeaf3,
+ 0xeaf4, 0xeaf5, 0xeaf7, 0xeaf8, 0xeafa, 0xeafb, 0xeafd, 0xeaff,
+ 0xeb00, 0xeb00, 0xeb00, 0xeb00, 0xeb01, 0xeb01, 0xeb02, 0xeb02,
+ 0xeb03, 0xeb04, 0xeb05, 0xeb05, 0xeb06, 0xeb07, 0xeb08, 0xeb09,
+ 0xeb0a, 0xeb0b, 0xeb0c, 0xeb0e, 0xeb0f, 0xeb10, 0xeb11, 0xeb13,
+ 0xeb14, 0xeb15, 0xeb17, 0xeb18, 0xeb1a, 0xeb1b, 0xeb1d, 0xeb1f,
+ 0xeb20, 0xeb20, 0xeb20, 0xeb20, 0xeb21, 0xeb21, 0xeb22, 0xeb22,
+ 0xeb23, 0xeb24, 0xeb25, 0xeb25, 0xeb26, 0xeb27, 0xeb28, 0xeb29,
+ 0xeb2a, 0xeb2b, 0xeb2c, 0xeb2e, 0xeb2f, 0xeb30, 0xeb31, 0xeb33,
+ 0xeb34, 0xeb35, 0xeb37, 0xeb38, 0xeb3a, 0xeb3b, 0xeb3d, 0xeb3f,
+ 0xeb40, 0xeb40, 0xeb40, 0xeb40, 0xeb41, 0xeb41, 0xeb42, 0xeb42,
+ 0xeb43, 0xeb44, 0xeb45, 0xeb45, 0xeb46, 0xeb47, 0xeb48, 0xeb49,
+ 0xeb4a, 0xeb4b, 0xeb4c, 0xeb4e, 0xeb4f, 0xeb50, 0xeb51, 0xeb53,
+ 0xeb54, 0xeb55, 0xeb57, 0xeb58, 0xeb5a, 0xeb5b, 0xeb5d, 0xeb5f,
+ 0xeb80, 0xeb80, 0xeb80, 0xeb80, 0xeb81, 0xeb81, 0xeb82, 0xeb82,
+ 0xeb83, 0xeb84, 0xeb85, 0xeb85, 0xeb86, 0xeb87, 0xeb88, 0xeb89,
+ 0xeb8a, 0xeb8b, 0xeb8c, 0xeb8e, 0xeb8f, 0xeb90, 0xeb91, 0xeb93,
+ 0xeb94, 0xeb95, 0xeb97, 0xeb98, 0xeb9a, 0xeb9b, 0xeb9d, 0xeb9f,
+ 0xeba0, 0xeba0, 0xeba0, 0xeba0, 0xeba1, 0xeba1, 0xeba2, 0xeba2,
+ 0xeba3, 0xeba4, 0xeba5, 0xeba5, 0xeba6, 0xeba7, 0xeba8, 0xeba9,
+ 0xebaa, 0xebab, 0xebac, 0xebae, 0xebaf, 0xebb0, 0xebb1, 0xebb3,
+ 0xebb4, 0xebb5, 0xebb7, 0xebb8, 0xebba, 0xebbb, 0xebbd, 0xebbf,
+ 0xebc0, 0xebc0, 0xebc0, 0xebc0, 0xebc1, 0xebc1, 0xebc2, 0xebc2,
+ 0xebc3, 0xebc4, 0xebc5, 0xebc5, 0xebc6, 0xebc7, 0xebc8, 0xebc9,
+ 0xebca, 0xebcb, 0xebcc, 0xebce, 0xebcf, 0xebd0, 0xebd1, 0xebd3,
+ 0xebd4, 0xebd5, 0xebd7, 0xebd8, 0xebda, 0xebdb, 0xebdd, 0xebdf,
+ 0xebe0, 0xebe0, 0xebe0, 0xebe0, 0xebe1, 0xebe1, 0xebe2, 0xebe2,
+ 0xebe3, 0xebe4, 0xebe5, 0xebe5, 0xebe6, 0xebe7, 0xebe8, 0xebe9,
+ 0xebea, 0xebeb, 0xebec, 0xebee, 0xebef, 0xebf0, 0xebf1, 0xebf3,
+ 0xebf4, 0xebf5, 0xebf7, 0xebf8, 0xebfa, 0xebfb, 0xebfd, 0xebff,
+ 0xec00, 0xec00, 0xec00, 0xec00, 0xec01, 0xec01, 0xec02, 0xec02,
+ 0xec03, 0xec04, 0xec05, 0xec05, 0xec06, 0xec07, 0xec08, 0xec09,
+ 0xec0a, 0xec0b, 0xec0c, 0xec0e, 0xec0f, 0xec10, 0xec11, 0xec13,
+ 0xec14, 0xec15, 0xec17, 0xec18, 0xec1a, 0xec1b, 0xec1d, 0xec1f,
+ 0xec40, 0xec40, 0xec40, 0xec40, 0xec41, 0xec41, 0xec42, 0xec42,
+ 0xec43, 0xec44, 0xec45, 0xec45, 0xec46, 0xec47, 0xec48, 0xec49,
+ 0xec4a, 0xec4b, 0xec4c, 0xec4e, 0xec4f, 0xec50, 0xec51, 0xec53,
+ 0xec54, 0xec55, 0xec57, 0xec58, 0xec5a, 0xec5b, 0xec5d, 0xec5f,
+ 0xec60, 0xec60, 0xec60, 0xec60, 0xec61, 0xec61, 0xec62, 0xec62,
+ 0xec63, 0xec64, 0xec65, 0xec65, 0xec66, 0xec67, 0xec68, 0xec69,
+ 0xec6a, 0xec6b, 0xec6c, 0xec6e, 0xec6f, 0xec70, 0xec71, 0xec73,
+ 0xec74, 0xec75, 0xec77, 0xec78, 0xec7a, 0xec7b, 0xec7d, 0xec7f,
+ 0xec80, 0xec80, 0xec80, 0xec80, 0xec81, 0xec81, 0xec82, 0xec82,
+ 0xec83, 0xec84, 0xec85, 0xec85, 0xec86, 0xec87, 0xec88, 0xec89,
+ 0xec8a, 0xec8b, 0xec8c, 0xec8e, 0xec8f, 0xec90, 0xec91, 0xec93,
+ 0xec94, 0xec95, 0xec97, 0xec98, 0xec9a, 0xec9b, 0xec9d, 0xec9f,
+ 0xecc0, 0xecc0, 0xecc0, 0xecc0, 0xecc1, 0xecc1, 0xecc2, 0xecc2,
+ 0xecc3, 0xecc4, 0xecc5, 0xecc5, 0xecc6, 0xecc7, 0xecc8, 0xecc9,
+ 0xecca, 0xeccb, 0xeccc, 0xecce, 0xeccf, 0xecd0, 0xecd1, 0xecd3,
+ 0xecd4, 0xecd5, 0xecd7, 0xecd8, 0xecda, 0xecdb, 0xecdd, 0xecdf,
+ 0xece0, 0xece0, 0xece0, 0xece0, 0xece1, 0xece1, 0xece2, 0xece2,
+ 0xece3, 0xece4, 0xece5, 0xece5, 0xece6, 0xece7, 0xece8, 0xece9,
+ 0xecea, 0xeceb, 0xecec, 0xecee, 0xecef, 0xecf0, 0xecf1, 0xecf3,
+ 0xecf4, 0xecf5, 0xecf7, 0xecf8, 0xecfa, 0xecfb, 0xecfd, 0xecff,
+ 0xed00, 0xed00, 0xed00, 0xed00, 0xed01, 0xed01, 0xed02, 0xed02,
+ 0xed03, 0xed04, 0xed05, 0xed05, 0xed06, 0xed07, 0xed08, 0xed09,
+ 0xed0a, 0xed0b, 0xed0c, 0xed0e, 0xed0f, 0xed10, 0xed11, 0xed13,
+ 0xed14, 0xed15, 0xed17, 0xed18, 0xed1a, 0xed1b, 0xed1d, 0xed1f,
+ 0xed40, 0xed40, 0xed40, 0xed40, 0xed41, 0xed41, 0xed42, 0xed42,
+ 0xed43, 0xed44, 0xed45, 0xed45, 0xed46, 0xed47, 0xed48, 0xed49,
+ 0xed4a, 0xed4b, 0xed4c, 0xed4e, 0xed4f, 0xed50, 0xed51, 0xed53,
+ 0xed54, 0xed55, 0xed57, 0xed58, 0xed5a, 0xed5b, 0xed5d, 0xed5f,
+ 0xed60, 0xed60, 0xed60, 0xed60, 0xed61, 0xed61, 0xed62, 0xed62,
+ 0xed63, 0xed64, 0xed65, 0xed65, 0xed66, 0xed67, 0xed68, 0xed69,
+ 0xed6a, 0xed6b, 0xed6c, 0xed6e, 0xed6f, 0xed70, 0xed71, 0xed73,
+ 0xed74, 0xed75, 0xed77, 0xed78, 0xed7a, 0xed7b, 0xed7d, 0xed7f,
+ 0xed80, 0xed80, 0xed80, 0xed80, 0xed81, 0xed81, 0xed82, 0xed82,
+ 0xed83, 0xed84, 0xed85, 0xed85, 0xed86, 0xed87, 0xed88, 0xed89,
+ 0xed8a, 0xed8b, 0xed8c, 0xed8e, 0xed8f, 0xed90, 0xed91, 0xed93,
+ 0xed94, 0xed95, 0xed97, 0xed98, 0xed9a, 0xed9b, 0xed9d, 0xed9f,
+ 0xedc0, 0xedc0, 0xedc0, 0xedc0, 0xedc1, 0xedc1, 0xedc2, 0xedc2,
+ 0xedc3, 0xedc4, 0xedc5, 0xedc5, 0xedc6, 0xedc7, 0xedc8, 0xedc9,
+ 0xedca, 0xedcb, 0xedcc, 0xedce, 0xedcf, 0xedd0, 0xedd1, 0xedd3,
+ 0xedd4, 0xedd5, 0xedd7, 0xedd8, 0xedda, 0xeddb, 0xeddd, 0xeddf,
+ 0xede0, 0xede0, 0xede0, 0xede0, 0xede1, 0xede1, 0xede2, 0xede2,
+ 0xede3, 0xede4, 0xede5, 0xede5, 0xede6, 0xede7, 0xede8, 0xede9,
+ 0xedea, 0xedeb, 0xedec, 0xedee, 0xedef, 0xedf0, 0xedf1, 0xedf3,
+ 0xedf4, 0xedf5, 0xedf7, 0xedf8, 0xedfa, 0xedfb, 0xedfd, 0xedff,
+ 0xee20, 0xee20, 0xee20, 0xee20, 0xee21, 0xee21, 0xee22, 0xee22,
+ 0xee23, 0xee24, 0xee25, 0xee25, 0xee26, 0xee27, 0xee28, 0xee29,
+ 0xee2a, 0xee2b, 0xee2c, 0xee2e, 0xee2f, 0xee30, 0xee31, 0xee33,
+ 0xee34, 0xee35, 0xee37, 0xee38, 0xee3a, 0xee3b, 0xee3d, 0xee3f,
+ 0xee40, 0xee40, 0xee40, 0xee40, 0xee41, 0xee41, 0xee42, 0xee42,
+ 0xee43, 0xee44, 0xee45, 0xee45, 0xee46, 0xee47, 0xee48, 0xee49,
+ 0xee4a, 0xee4b, 0xee4c, 0xee4e, 0xee4f, 0xee50, 0xee51, 0xee53,
+ 0xee54, 0xee55, 0xee57, 0xee58, 0xee5a, 0xee5b, 0xee5d, 0xee5f,
+ 0xee80, 0xee80, 0xee80, 0xee80, 0xee81, 0xee81, 0xee82, 0xee82,
+ 0xee83, 0xee84, 0xee85, 0xee85, 0xee86, 0xee87, 0xee88, 0xee89,
+ 0xee8a, 0xee8b, 0xee8c, 0xee8e, 0xee8f, 0xee90, 0xee91, 0xee93,
+ 0xee94, 0xee95, 0xee97, 0xee98, 0xee9a, 0xee9b, 0xee9d, 0xee9f,
+ 0xeea0, 0xeea0, 0xeea0, 0xeea0, 0xeea1, 0xeea1, 0xeea2, 0xeea2,
+ 0xeea3, 0xeea4, 0xeea5, 0xeea5, 0xeea6, 0xeea7, 0xeea8, 0xeea9,
+ 0xeeaa, 0xeeab, 0xeeac, 0xeeae, 0xeeaf, 0xeeb0, 0xeeb1, 0xeeb3,
+ 0xeeb4, 0xeeb5, 0xeeb7, 0xeeb8, 0xeeba, 0xeebb, 0xeebd, 0xeebf,
+ 0xeee0, 0xeee0, 0xeee0, 0xeee0, 0xeee1, 0xeee1, 0xeee2, 0xeee2,
+ 0xeee3, 0xeee4, 0xeee5, 0xeee5, 0xeee6, 0xeee7, 0xeee8, 0xeee9,
+ 0xeeea, 0xeeeb, 0xeeec, 0xeeee, 0xeeef, 0xeef0, 0xeef1, 0xeef3,
+ 0xeef4, 0xeef5, 0xeef7, 0xeef8, 0xeefa, 0xeefb, 0xeefd, 0xeeff,
+ 0xef00, 0xef00, 0xef00, 0xef00, 0xef01, 0xef01, 0xef02, 0xef02,
+ 0xef03, 0xef04, 0xef05, 0xef05, 0xef06, 0xef07, 0xef08, 0xef09,
+ 0xef0a, 0xef0b, 0xef0c, 0xef0e, 0xef0f, 0xef10, 0xef11, 0xef13,
+ 0xef14, 0xef15, 0xef17, 0xef18, 0xef1a, 0xef1b, 0xef1d, 0xef1f,
+ 0xef40, 0xef40, 0xef40, 0xef40, 0xef41, 0xef41, 0xef42, 0xef42,
+ 0xef43, 0xef44, 0xef45, 0xef45, 0xef46, 0xef47, 0xef48, 0xef49,
+ 0xef4a, 0xef4b, 0xef4c, 0xef4e, 0xef4f, 0xef50, 0xef51, 0xef53,
+ 0xef54, 0xef55, 0xef57, 0xef58, 0xef5a, 0xef5b, 0xef5d, 0xef5f,
+ 0xef60, 0xef60, 0xef60, 0xef60, 0xef61, 0xef61, 0xef62, 0xef62,
+ 0xef63, 0xef64, 0xef65, 0xef65, 0xef66, 0xef67, 0xef68, 0xef69,
+ 0xef6a, 0xef6b, 0xef6c, 0xef6e, 0xef6f, 0xef70, 0xef71, 0xef73,
+ 0xef74, 0xef75, 0xef77, 0xef78, 0xef7a, 0xef7b, 0xef7d, 0xef7f,
+ 0xefa0, 0xefa0, 0xefa0, 0xefa0, 0xefa1, 0xefa1, 0xefa2, 0xefa2,
+ 0xefa3, 0xefa4, 0xefa5, 0xefa5, 0xefa6, 0xefa7, 0xefa8, 0xefa9,
+ 0xefaa, 0xefab, 0xefac, 0xefae, 0xefaf, 0xefb0, 0xefb1, 0xefb3,
+ 0xefb4, 0xefb5, 0xefb7, 0xefb8, 0xefba, 0xefbb, 0xefbd, 0xefbf,
+ 0xefe0, 0xefe0, 0xefe0, 0xefe0, 0xefe1, 0xefe1, 0xefe2, 0xefe2,
+ 0xefe3, 0xefe4, 0xefe5, 0xefe5, 0xefe6, 0xefe7, 0xefe8, 0xefe9,
+ 0xefea, 0xefeb, 0xefec, 0xefee, 0xefef, 0xeff0, 0xeff1, 0xeff3,
+ 0xeff4, 0xeff5, 0xeff7, 0xeff8, 0xeffa, 0xeffb, 0xeffd, 0xefff,
+ 0xf800, 0xf800, 0xf800, 0xf800, 0xf801, 0xf801, 0xf802, 0xf802,
+ 0xf803, 0xf804, 0xf805, 0xf805, 0xf806, 0xf807, 0xf808, 0xf809,
+ 0xf80a, 0xf80b, 0xf80c, 0xf80e, 0xf80f, 0xf810, 0xf811, 0xf813,
+ 0xf814, 0xf815, 0xf817, 0xf818, 0xf81a, 0xf81b, 0xf81d, 0xf81f,
+ 0xf800, 0xf800, 0xf800, 0xf800, 0xf801, 0xf801, 0xf802, 0xf802,
+ 0xf803, 0xf804, 0xf805, 0xf805, 0xf806, 0xf807, 0xf808, 0xf809,
+ 0xf80a, 0xf80b, 0xf80c, 0xf80e, 0xf80f, 0xf810, 0xf811, 0xf813,
+ 0xf814, 0xf815, 0xf817, 0xf818, 0xf81a, 0xf81b, 0xf81d, 0xf81f,
+ 0xf800, 0xf800, 0xf800, 0xf800, 0xf801, 0xf801, 0xf802, 0xf802,
+ 0xf803, 0xf804, 0xf805, 0xf805, 0xf806, 0xf807, 0xf808, 0xf809,
+ 0xf80a, 0xf80b, 0xf80c, 0xf80e, 0xf80f, 0xf810, 0xf811, 0xf813,
+ 0xf814, 0xf815, 0xf817, 0xf818, 0xf81a, 0xf81b, 0xf81d, 0xf81f,
+ 0xf800, 0xf800, 0xf800, 0xf800, 0xf801, 0xf801, 0xf802, 0xf802,
+ 0xf803, 0xf804, 0xf805, 0xf805, 0xf806, 0xf807, 0xf808, 0xf809,
+ 0xf80a, 0xf80b, 0xf80c, 0xf80e, 0xf80f, 0xf810, 0xf811, 0xf813,
+ 0xf814, 0xf815, 0xf817, 0xf818, 0xf81a, 0xf81b, 0xf81d, 0xf81f,
+ 0xf800, 0xf800, 0xf800, 0xf800, 0xf801, 0xf801, 0xf802, 0xf802,
+ 0xf803, 0xf804, 0xf805, 0xf805, 0xf806, 0xf807, 0xf808, 0xf809,
+ 0xf80a, 0xf80b, 0xf80c, 0xf80e, 0xf80f, 0xf810, 0xf811, 0xf813,
+ 0xf814, 0xf815, 0xf817, 0xf818, 0xf81a, 0xf81b, 0xf81d, 0xf81f,
+ 0xf820, 0xf820, 0xf820, 0xf820, 0xf821, 0xf821, 0xf822, 0xf822,
+ 0xf823, 0xf824, 0xf825, 0xf825, 0xf826, 0xf827, 0xf828, 0xf829,
+ 0xf82a, 0xf82b, 0xf82c, 0xf82e, 0xf82f, 0xf830, 0xf831, 0xf833,
+ 0xf834, 0xf835, 0xf837, 0xf838, 0xf83a, 0xf83b, 0xf83d, 0xf83f,
+ 0xf820, 0xf820, 0xf820, 0xf820, 0xf821, 0xf821, 0xf822, 0xf822,
+ 0xf823, 0xf824, 0xf825, 0xf825, 0xf826, 0xf827, 0xf828, 0xf829,
+ 0xf82a, 0xf82b, 0xf82c, 0xf82e, 0xf82f, 0xf830, 0xf831, 0xf833,
+ 0xf834, 0xf835, 0xf837, 0xf838, 0xf83a, 0xf83b, 0xf83d, 0xf83f,
+ 0xf820, 0xf820, 0xf820, 0xf820, 0xf821, 0xf821, 0xf822, 0xf822,
+ 0xf823, 0xf824, 0xf825, 0xf825, 0xf826, 0xf827, 0xf828, 0xf829,
+ 0xf82a, 0xf82b, 0xf82c, 0xf82e, 0xf82f, 0xf830, 0xf831, 0xf833,
+ 0xf834, 0xf835, 0xf837, 0xf838, 0xf83a, 0xf83b, 0xf83d, 0xf83f,
+ 0xf840, 0xf840, 0xf840, 0xf840, 0xf841, 0xf841, 0xf842, 0xf842,
+ 0xf843, 0xf844, 0xf845, 0xf845, 0xf846, 0xf847, 0xf848, 0xf849,
+ 0xf84a, 0xf84b, 0xf84c, 0xf84e, 0xf84f, 0xf850, 0xf851, 0xf853,
+ 0xf854, 0xf855, 0xf857, 0xf858, 0xf85a, 0xf85b, 0xf85d, 0xf85f,
+ 0xf840, 0xf840, 0xf840, 0xf840, 0xf841, 0xf841, 0xf842, 0xf842,
+ 0xf843, 0xf844, 0xf845, 0xf845, 0xf846, 0xf847, 0xf848, 0xf849,
+ 0xf84a, 0xf84b, 0xf84c, 0xf84e, 0xf84f, 0xf850, 0xf851, 0xf853,
+ 0xf854, 0xf855, 0xf857, 0xf858, 0xf85a, 0xf85b, 0xf85d, 0xf85f,
+ 0xf860, 0xf860, 0xf860, 0xf860, 0xf861, 0xf861, 0xf862, 0xf862,
+ 0xf863, 0xf864, 0xf865, 0xf865, 0xf866, 0xf867, 0xf868, 0xf869,
+ 0xf86a, 0xf86b, 0xf86c, 0xf86e, 0xf86f, 0xf870, 0xf871, 0xf873,
+ 0xf874, 0xf875, 0xf877, 0xf878, 0xf87a, 0xf87b, 0xf87d, 0xf87f,
+ 0xf860, 0xf860, 0xf860, 0xf860, 0xf861, 0xf861, 0xf862, 0xf862,
+ 0xf863, 0xf864, 0xf865, 0xf865, 0xf866, 0xf867, 0xf868, 0xf869,
+ 0xf86a, 0xf86b, 0xf86c, 0xf86e, 0xf86f, 0xf870, 0xf871, 0xf873,
+ 0xf874, 0xf875, 0xf877, 0xf878, 0xf87a, 0xf87b, 0xf87d, 0xf87f,
+ 0xf880, 0xf880, 0xf880, 0xf880, 0xf881, 0xf881, 0xf882, 0xf882,
+ 0xf883, 0xf884, 0xf885, 0xf885, 0xf886, 0xf887, 0xf888, 0xf889,
+ 0xf88a, 0xf88b, 0xf88c, 0xf88e, 0xf88f, 0xf890, 0xf891, 0xf893,
+ 0xf894, 0xf895, 0xf897, 0xf898, 0xf89a, 0xf89b, 0xf89d, 0xf89f,
+ 0xf8a0, 0xf8a0, 0xf8a0, 0xf8a0, 0xf8a1, 0xf8a1, 0xf8a2, 0xf8a2,
+ 0xf8a3, 0xf8a4, 0xf8a5, 0xf8a5, 0xf8a6, 0xf8a7, 0xf8a8, 0xf8a9,
+ 0xf8aa, 0xf8ab, 0xf8ac, 0xf8ae, 0xf8af, 0xf8b0, 0xf8b1, 0xf8b3,
+ 0xf8b4, 0xf8b5, 0xf8b7, 0xf8b8, 0xf8ba, 0xf8bb, 0xf8bd, 0xf8bf,
+ 0xf8a0, 0xf8a0, 0xf8a0, 0xf8a0, 0xf8a1, 0xf8a1, 0xf8a2, 0xf8a2,
+ 0xf8a3, 0xf8a4, 0xf8a5, 0xf8a5, 0xf8a6, 0xf8a7, 0xf8a8, 0xf8a9,
+ 0xf8aa, 0xf8ab, 0xf8ac, 0xf8ae, 0xf8af, 0xf8b0, 0xf8b1, 0xf8b3,
+ 0xf8b4, 0xf8b5, 0xf8b7, 0xf8b8, 0xf8ba, 0xf8bb, 0xf8bd, 0xf8bf,
+ 0xf8c0, 0xf8c0, 0xf8c0, 0xf8c0, 0xf8c1, 0xf8c1, 0xf8c2, 0xf8c2,
+ 0xf8c3, 0xf8c4, 0xf8c5, 0xf8c5, 0xf8c6, 0xf8c7, 0xf8c8, 0xf8c9,
+ 0xf8ca, 0xf8cb, 0xf8cc, 0xf8ce, 0xf8cf, 0xf8d0, 0xf8d1, 0xf8d3,
+ 0xf8d4, 0xf8d5, 0xf8d7, 0xf8d8, 0xf8da, 0xf8db, 0xf8dd, 0xf8df,
+ 0xf8e0, 0xf8e0, 0xf8e0, 0xf8e0, 0xf8e1, 0xf8e1, 0xf8e2, 0xf8e2,
+ 0xf8e3, 0xf8e4, 0xf8e5, 0xf8e5, 0xf8e6, 0xf8e7, 0xf8e8, 0xf8e9,
+ 0xf8ea, 0xf8eb, 0xf8ec, 0xf8ee, 0xf8ef, 0xf8f0, 0xf8f1, 0xf8f3,
+ 0xf8f4, 0xf8f5, 0xf8f7, 0xf8f8, 0xf8fa, 0xf8fb, 0xf8fd, 0xf8ff,
+ 0xf8e0, 0xf8e0, 0xf8e0, 0xf8e0, 0xf8e1, 0xf8e1, 0xf8e2, 0xf8e2,
+ 0xf8e3, 0xf8e4, 0xf8e5, 0xf8e5, 0xf8e6, 0xf8e7, 0xf8e8, 0xf8e9,
+ 0xf8ea, 0xf8eb, 0xf8ec, 0xf8ee, 0xf8ef, 0xf8f0, 0xf8f1, 0xf8f3,
+ 0xf8f4, 0xf8f5, 0xf8f7, 0xf8f8, 0xf8fa, 0xf8fb, 0xf8fd, 0xf8ff,
+ 0xf900, 0xf900, 0xf900, 0xf900, 0xf901, 0xf901, 0xf902, 0xf902,
+ 0xf903, 0xf904, 0xf905, 0xf905, 0xf906, 0xf907, 0xf908, 0xf909,
+ 0xf90a, 0xf90b, 0xf90c, 0xf90e, 0xf90f, 0xf910, 0xf911, 0xf913,
+ 0xf914, 0xf915, 0xf917, 0xf918, 0xf91a, 0xf91b, 0xf91d, 0xf91f,
+ 0xf920, 0xf920, 0xf920, 0xf920, 0xf921, 0xf921, 0xf922, 0xf922,
+ 0xf923, 0xf924, 0xf925, 0xf925, 0xf926, 0xf927, 0xf928, 0xf929,
+ 0xf92a, 0xf92b, 0xf92c, 0xf92e, 0xf92f, 0xf930, 0xf931, 0xf933,
+ 0xf934, 0xf935, 0xf937, 0xf938, 0xf93a, 0xf93b, 0xf93d, 0xf93f,
+ 0xf940, 0xf940, 0xf940, 0xf940, 0xf941, 0xf941, 0xf942, 0xf942,
+ 0xf943, 0xf944, 0xf945, 0xf945, 0xf946, 0xf947, 0xf948, 0xf949,
+ 0xf94a, 0xf94b, 0xf94c, 0xf94e, 0xf94f, 0xf950, 0xf951, 0xf953,
+ 0xf954, 0xf955, 0xf957, 0xf958, 0xf95a, 0xf95b, 0xf95d, 0xf95f,
+ 0xf940, 0xf940, 0xf940, 0xf940, 0xf941, 0xf941, 0xf942, 0xf942,
+ 0xf943, 0xf944, 0xf945, 0xf945, 0xf946, 0xf947, 0xf948, 0xf949,
+ 0xf94a, 0xf94b, 0xf94c, 0xf94e, 0xf94f, 0xf950, 0xf951, 0xf953,
+ 0xf954, 0xf955, 0xf957, 0xf958, 0xf95a, 0xf95b, 0xf95d, 0xf95f,
+ 0xf960, 0xf960, 0xf960, 0xf960, 0xf961, 0xf961, 0xf962, 0xf962,
+ 0xf963, 0xf964, 0xf965, 0xf965, 0xf966, 0xf967, 0xf968, 0xf969,
+ 0xf96a, 0xf96b, 0xf96c, 0xf96e, 0xf96f, 0xf970, 0xf971, 0xf973,
+ 0xf974, 0xf975, 0xf977, 0xf978, 0xf97a, 0xf97b, 0xf97d, 0xf97f,
+ 0xf980, 0xf980, 0xf980, 0xf980, 0xf981, 0xf981, 0xf982, 0xf982,
+ 0xf983, 0xf984, 0xf985, 0xf985, 0xf986, 0xf987, 0xf988, 0xf989,
+ 0xf98a, 0xf98b, 0xf98c, 0xf98e, 0xf98f, 0xf990, 0xf991, 0xf993,
+ 0xf994, 0xf995, 0xf997, 0xf998, 0xf99a, 0xf99b, 0xf99d, 0xf99f,
+ 0xf9a0, 0xf9a0, 0xf9a0, 0xf9a0, 0xf9a1, 0xf9a1, 0xf9a2, 0xf9a2,
+ 0xf9a3, 0xf9a4, 0xf9a5, 0xf9a5, 0xf9a6, 0xf9a7, 0xf9a8, 0xf9a9,
+ 0xf9aa, 0xf9ab, 0xf9ac, 0xf9ae, 0xf9af, 0xf9b0, 0xf9b1, 0xf9b3,
+ 0xf9b4, 0xf9b5, 0xf9b7, 0xf9b8, 0xf9ba, 0xf9bb, 0xf9bd, 0xf9bf,
+ 0xf9c0, 0xf9c0, 0xf9c0, 0xf9c0, 0xf9c1, 0xf9c1, 0xf9c2, 0xf9c2,
+ 0xf9c3, 0xf9c4, 0xf9c5, 0xf9c5, 0xf9c6, 0xf9c7, 0xf9c8, 0xf9c9,
+ 0xf9ca, 0xf9cb, 0xf9cc, 0xf9ce, 0xf9cf, 0xf9d0, 0xf9d1, 0xf9d3,
+ 0xf9d4, 0xf9d5, 0xf9d7, 0xf9d8, 0xf9da, 0xf9db, 0xf9dd, 0xf9df,
+ 0xf9e0, 0xf9e0, 0xf9e0, 0xf9e0, 0xf9e1, 0xf9e1, 0xf9e2, 0xf9e2,
+ 0xf9e3, 0xf9e4, 0xf9e5, 0xf9e5, 0xf9e6, 0xf9e7, 0xf9e8, 0xf9e9,
+ 0xf9ea, 0xf9eb, 0xf9ec, 0xf9ee, 0xf9ef, 0xf9f0, 0xf9f1, 0xf9f3,
+ 0xf9f4, 0xf9f5, 0xf9f7, 0xf9f8, 0xf9fa, 0xf9fb, 0xf9fd, 0xf9ff,
+ 0xfa00, 0xfa00, 0xfa00, 0xfa00, 0xfa01, 0xfa01, 0xfa02, 0xfa02,
+ 0xfa03, 0xfa04, 0xfa05, 0xfa05, 0xfa06, 0xfa07, 0xfa08, 0xfa09,
+ 0xfa0a, 0xfa0b, 0xfa0c, 0xfa0e, 0xfa0f, 0xfa10, 0xfa11, 0xfa13,
+ 0xfa14, 0xfa15, 0xfa17, 0xfa18, 0xfa1a, 0xfa1b, 0xfa1d, 0xfa1f,
+ 0xfa20, 0xfa20, 0xfa20, 0xfa20, 0xfa21, 0xfa21, 0xfa22, 0xfa22,
+ 0xfa23, 0xfa24, 0xfa25, 0xfa25, 0xfa26, 0xfa27, 0xfa28, 0xfa29,
+ 0xfa2a, 0xfa2b, 0xfa2c, 0xfa2e, 0xfa2f, 0xfa30, 0xfa31, 0xfa33,
+ 0xfa34, 0xfa35, 0xfa37, 0xfa38, 0xfa3a, 0xfa3b, 0xfa3d, 0xfa3f,
+ 0xfa40, 0xfa40, 0xfa40, 0xfa40, 0xfa41, 0xfa41, 0xfa42, 0xfa42,
+ 0xfa43, 0xfa44, 0xfa45, 0xfa45, 0xfa46, 0xfa47, 0xfa48, 0xfa49,
+ 0xfa4a, 0xfa4b, 0xfa4c, 0xfa4e, 0xfa4f, 0xfa50, 0xfa51, 0xfa53,
+ 0xfa54, 0xfa55, 0xfa57, 0xfa58, 0xfa5a, 0xfa5b, 0xfa5d, 0xfa5f,
+ 0xfa60, 0xfa60, 0xfa60, 0xfa60, 0xfa61, 0xfa61, 0xfa62, 0xfa62,
+ 0xfa63, 0xfa64, 0xfa65, 0xfa65, 0xfa66, 0xfa67, 0xfa68, 0xfa69,
+ 0xfa6a, 0xfa6b, 0xfa6c, 0xfa6e, 0xfa6f, 0xfa70, 0xfa71, 0xfa73,
+ 0xfa74, 0xfa75, 0xfa77, 0xfa78, 0xfa7a, 0xfa7b, 0xfa7d, 0xfa7f,
+ 0xfa80, 0xfa80, 0xfa80, 0xfa80, 0xfa81, 0xfa81, 0xfa82, 0xfa82,
+ 0xfa83, 0xfa84, 0xfa85, 0xfa85, 0xfa86, 0xfa87, 0xfa88, 0xfa89,
+ 0xfa8a, 0xfa8b, 0xfa8c, 0xfa8e, 0xfa8f, 0xfa90, 0xfa91, 0xfa93,
+ 0xfa94, 0xfa95, 0xfa97, 0xfa98, 0xfa9a, 0xfa9b, 0xfa9d, 0xfa9f,
+ 0xfaa0, 0xfaa0, 0xfaa0, 0xfaa0, 0xfaa1, 0xfaa1, 0xfaa2, 0xfaa2,
+ 0xfaa3, 0xfaa4, 0xfaa5, 0xfaa5, 0xfaa6, 0xfaa7, 0xfaa8, 0xfaa9,
+ 0xfaaa, 0xfaab, 0xfaac, 0xfaae, 0xfaaf, 0xfab0, 0xfab1, 0xfab3,
+ 0xfab4, 0xfab5, 0xfab7, 0xfab8, 0xfaba, 0xfabb, 0xfabd, 0xfabf,
+ 0xfac0, 0xfac0, 0xfac0, 0xfac0, 0xfac1, 0xfac1, 0xfac2, 0xfac2,
+ 0xfac3, 0xfac4, 0xfac5, 0xfac5, 0xfac6, 0xfac7, 0xfac8, 0xfac9,
+ 0xfaca, 0xfacb, 0xfacc, 0xface, 0xfacf, 0xfad0, 0xfad1, 0xfad3,
+ 0xfad4, 0xfad5, 0xfad7, 0xfad8, 0xfada, 0xfadb, 0xfadd, 0xfadf,
+ 0xfae0, 0xfae0, 0xfae0, 0xfae0, 0xfae1, 0xfae1, 0xfae2, 0xfae2,
+ 0xfae3, 0xfae4, 0xfae5, 0xfae5, 0xfae6, 0xfae7, 0xfae8, 0xfae9,
+ 0xfaea, 0xfaeb, 0xfaec, 0xfaee, 0xfaef, 0xfaf0, 0xfaf1, 0xfaf3,
+ 0xfaf4, 0xfaf5, 0xfaf7, 0xfaf8, 0xfafa, 0xfafb, 0xfafd, 0xfaff,
+ 0xfb00, 0xfb00, 0xfb00, 0xfb00, 0xfb01, 0xfb01, 0xfb02, 0xfb02,
+ 0xfb03, 0xfb04, 0xfb05, 0xfb05, 0xfb06, 0xfb07, 0xfb08, 0xfb09,
+ 0xfb0a, 0xfb0b, 0xfb0c, 0xfb0e, 0xfb0f, 0xfb10, 0xfb11, 0xfb13,
+ 0xfb14, 0xfb15, 0xfb17, 0xfb18, 0xfb1a, 0xfb1b, 0xfb1d, 0xfb1f,
+ 0xfb20, 0xfb20, 0xfb20, 0xfb20, 0xfb21, 0xfb21, 0xfb22, 0xfb22,
+ 0xfb23, 0xfb24, 0xfb25, 0xfb25, 0xfb26, 0xfb27, 0xfb28, 0xfb29,
+ 0xfb2a, 0xfb2b, 0xfb2c, 0xfb2e, 0xfb2f, 0xfb30, 0xfb31, 0xfb33,
+ 0xfb34, 0xfb35, 0xfb37, 0xfb38, 0xfb3a, 0xfb3b, 0xfb3d, 0xfb3f,
+ 0xfb40, 0xfb40, 0xfb40, 0xfb40, 0xfb41, 0xfb41, 0xfb42, 0xfb42,
+ 0xfb43, 0xfb44, 0xfb45, 0xfb45, 0xfb46, 0xfb47, 0xfb48, 0xfb49,
+ 0xfb4a, 0xfb4b, 0xfb4c, 0xfb4e, 0xfb4f, 0xfb50, 0xfb51, 0xfb53,
+ 0xfb54, 0xfb55, 0xfb57, 0xfb58, 0xfb5a, 0xfb5b, 0xfb5d, 0xfb5f,
+ 0xfb80, 0xfb80, 0xfb80, 0xfb80, 0xfb81, 0xfb81, 0xfb82, 0xfb82,
+ 0xfb83, 0xfb84, 0xfb85, 0xfb85, 0xfb86, 0xfb87, 0xfb88, 0xfb89,
+ 0xfb8a, 0xfb8b, 0xfb8c, 0xfb8e, 0xfb8f, 0xfb90, 0xfb91, 0xfb93,
+ 0xfb94, 0xfb95, 0xfb97, 0xfb98, 0xfb9a, 0xfb9b, 0xfb9d, 0xfb9f,
+ 0xfba0, 0xfba0, 0xfba0, 0xfba0, 0xfba1, 0xfba1, 0xfba2, 0xfba2,
+ 0xfba3, 0xfba4, 0xfba5, 0xfba5, 0xfba6, 0xfba7, 0xfba8, 0xfba9,
+ 0xfbaa, 0xfbab, 0xfbac, 0xfbae, 0xfbaf, 0xfbb0, 0xfbb1, 0xfbb3,
+ 0xfbb4, 0xfbb5, 0xfbb7, 0xfbb8, 0xfbba, 0xfbbb, 0xfbbd, 0xfbbf,
+ 0xfbc0, 0xfbc0, 0xfbc0, 0xfbc0, 0xfbc1, 0xfbc1, 0xfbc2, 0xfbc2,
+ 0xfbc3, 0xfbc4, 0xfbc5, 0xfbc5, 0xfbc6, 0xfbc7, 0xfbc8, 0xfbc9,
+ 0xfbca, 0xfbcb, 0xfbcc, 0xfbce, 0xfbcf, 0xfbd0, 0xfbd1, 0xfbd3,
+ 0xfbd4, 0xfbd5, 0xfbd7, 0xfbd8, 0xfbda, 0xfbdb, 0xfbdd, 0xfbdf,
+ 0xfbe0, 0xfbe0, 0xfbe0, 0xfbe0, 0xfbe1, 0xfbe1, 0xfbe2, 0xfbe2,
+ 0xfbe3, 0xfbe4, 0xfbe5, 0xfbe5, 0xfbe6, 0xfbe7, 0xfbe8, 0xfbe9,
+ 0xfbea, 0xfbeb, 0xfbec, 0xfbee, 0xfbef, 0xfbf0, 0xfbf1, 0xfbf3,
+ 0xfbf4, 0xfbf5, 0xfbf7, 0xfbf8, 0xfbfa, 0xfbfb, 0xfbfd, 0xfbff,
+ 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc01, 0xfc01, 0xfc02, 0xfc02,
+ 0xfc03, 0xfc04, 0xfc05, 0xfc05, 0xfc06, 0xfc07, 0xfc08, 0xfc09,
+ 0xfc0a, 0xfc0b, 0xfc0c, 0xfc0e, 0xfc0f, 0xfc10, 0xfc11, 0xfc13,
+ 0xfc14, 0xfc15, 0xfc17, 0xfc18, 0xfc1a, 0xfc1b, 0xfc1d, 0xfc1f,
+ 0xfc40, 0xfc40, 0xfc40, 0xfc40, 0xfc41, 0xfc41, 0xfc42, 0xfc42,
+ 0xfc43, 0xfc44, 0xfc45, 0xfc45, 0xfc46, 0xfc47, 0xfc48, 0xfc49,
+ 0xfc4a, 0xfc4b, 0xfc4c, 0xfc4e, 0xfc4f, 0xfc50, 0xfc51, 0xfc53,
+ 0xfc54, 0xfc55, 0xfc57, 0xfc58, 0xfc5a, 0xfc5b, 0xfc5d, 0xfc5f,
+ 0xfc60, 0xfc60, 0xfc60, 0xfc60, 0xfc61, 0xfc61, 0xfc62, 0xfc62,
+ 0xfc63, 0xfc64, 0xfc65, 0xfc65, 0xfc66, 0xfc67, 0xfc68, 0xfc69,
+ 0xfc6a, 0xfc6b, 0xfc6c, 0xfc6e, 0xfc6f, 0xfc70, 0xfc71, 0xfc73,
+ 0xfc74, 0xfc75, 0xfc77, 0xfc78, 0xfc7a, 0xfc7b, 0xfc7d, 0xfc7f,
+ 0xfc80, 0xfc80, 0xfc80, 0xfc80, 0xfc81, 0xfc81, 0xfc82, 0xfc82,
+ 0xfc83, 0xfc84, 0xfc85, 0xfc85, 0xfc86, 0xfc87, 0xfc88, 0xfc89,
+ 0xfc8a, 0xfc8b, 0xfc8c, 0xfc8e, 0xfc8f, 0xfc90, 0xfc91, 0xfc93,
+ 0xfc94, 0xfc95, 0xfc97, 0xfc98, 0xfc9a, 0xfc9b, 0xfc9d, 0xfc9f,
+ 0xfcc0, 0xfcc0, 0xfcc0, 0xfcc0, 0xfcc1, 0xfcc1, 0xfcc2, 0xfcc2,
+ 0xfcc3, 0xfcc4, 0xfcc5, 0xfcc5, 0xfcc6, 0xfcc7, 0xfcc8, 0xfcc9,
+ 0xfcca, 0xfccb, 0xfccc, 0xfcce, 0xfccf, 0xfcd0, 0xfcd1, 0xfcd3,
+ 0xfcd4, 0xfcd5, 0xfcd7, 0xfcd8, 0xfcda, 0xfcdb, 0xfcdd, 0xfcdf,
+ 0xfce0, 0xfce0, 0xfce0, 0xfce0, 0xfce1, 0xfce1, 0xfce2, 0xfce2,
+ 0xfce3, 0xfce4, 0xfce5, 0xfce5, 0xfce6, 0xfce7, 0xfce8, 0xfce9,
+ 0xfcea, 0xfceb, 0xfcec, 0xfcee, 0xfcef, 0xfcf0, 0xfcf1, 0xfcf3,
+ 0xfcf4, 0xfcf5, 0xfcf7, 0xfcf8, 0xfcfa, 0xfcfb, 0xfcfd, 0xfcff,
+ 0xfd00, 0xfd00, 0xfd00, 0xfd00, 0xfd01, 0xfd01, 0xfd02, 0xfd02,
+ 0xfd03, 0xfd04, 0xfd05, 0xfd05, 0xfd06, 0xfd07, 0xfd08, 0xfd09,
+ 0xfd0a, 0xfd0b, 0xfd0c, 0xfd0e, 0xfd0f, 0xfd10, 0xfd11, 0xfd13,
+ 0xfd14, 0xfd15, 0xfd17, 0xfd18, 0xfd1a, 0xfd1b, 0xfd1d, 0xfd1f,
+ 0xfd40, 0xfd40, 0xfd40, 0xfd40, 0xfd41, 0xfd41, 0xfd42, 0xfd42,
+ 0xfd43, 0xfd44, 0xfd45, 0xfd45, 0xfd46, 0xfd47, 0xfd48, 0xfd49,
+ 0xfd4a, 0xfd4b, 0xfd4c, 0xfd4e, 0xfd4f, 0xfd50, 0xfd51, 0xfd53,
+ 0xfd54, 0xfd55, 0xfd57, 0xfd58, 0xfd5a, 0xfd5b, 0xfd5d, 0xfd5f,
+ 0xfd60, 0xfd60, 0xfd60, 0xfd60, 0xfd61, 0xfd61, 0xfd62, 0xfd62,
+ 0xfd63, 0xfd64, 0xfd65, 0xfd65, 0xfd66, 0xfd67, 0xfd68, 0xfd69,
+ 0xfd6a, 0xfd6b, 0xfd6c, 0xfd6e, 0xfd6f, 0xfd70, 0xfd71, 0xfd73,
+ 0xfd74, 0xfd75, 0xfd77, 0xfd78, 0xfd7a, 0xfd7b, 0xfd7d, 0xfd7f,
+ 0xfd80, 0xfd80, 0xfd80, 0xfd80, 0xfd81, 0xfd81, 0xfd82, 0xfd82,
+ 0xfd83, 0xfd84, 0xfd85, 0xfd85, 0xfd86, 0xfd87, 0xfd88, 0xfd89,
+ 0xfd8a, 0xfd8b, 0xfd8c, 0xfd8e, 0xfd8f, 0xfd90, 0xfd91, 0xfd93,
+ 0xfd94, 0xfd95, 0xfd97, 0xfd98, 0xfd9a, 0xfd9b, 0xfd9d, 0xfd9f,
+ 0xfdc0, 0xfdc0, 0xfdc0, 0xfdc0, 0xfdc1, 0xfdc1, 0xfdc2, 0xfdc2,
+ 0xfdc3, 0xfdc4, 0xfdc5, 0xfdc5, 0xfdc6, 0xfdc7, 0xfdc8, 0xfdc9,
+ 0xfdca, 0xfdcb, 0xfdcc, 0xfdce, 0xfdcf, 0xfdd0, 0xfdd1, 0xfdd3,
+ 0xfdd4, 0xfdd5, 0xfdd7, 0xfdd8, 0xfdda, 0xfddb, 0xfddd, 0xfddf,
+ 0xfde0, 0xfde0, 0xfde0, 0xfde0, 0xfde1, 0xfde1, 0xfde2, 0xfde2,
+ 0xfde3, 0xfde4, 0xfde5, 0xfde5, 0xfde6, 0xfde7, 0xfde8, 0xfde9,
+ 0xfdea, 0xfdeb, 0xfdec, 0xfdee, 0xfdef, 0xfdf0, 0xfdf1, 0xfdf3,
+ 0xfdf4, 0xfdf5, 0xfdf7, 0xfdf8, 0xfdfa, 0xfdfb, 0xfdfd, 0xfdff,
+ 0xfe20, 0xfe20, 0xfe20, 0xfe20, 0xfe21, 0xfe21, 0xfe22, 0xfe22,
+ 0xfe23, 0xfe24, 0xfe25, 0xfe25, 0xfe26, 0xfe27, 0xfe28, 0xfe29,
+ 0xfe2a, 0xfe2b, 0xfe2c, 0xfe2e, 0xfe2f, 0xfe30, 0xfe31, 0xfe33,
+ 0xfe34, 0xfe35, 0xfe37, 0xfe38, 0xfe3a, 0xfe3b, 0xfe3d, 0xfe3f,
+ 0xfe40, 0xfe40, 0xfe40, 0xfe40, 0xfe41, 0xfe41, 0xfe42, 0xfe42,
+ 0xfe43, 0xfe44, 0xfe45, 0xfe45, 0xfe46, 0xfe47, 0xfe48, 0xfe49,
+ 0xfe4a, 0xfe4b, 0xfe4c, 0xfe4e, 0xfe4f, 0xfe50, 0xfe51, 0xfe53,
+ 0xfe54, 0xfe55, 0xfe57, 0xfe58, 0xfe5a, 0xfe5b, 0xfe5d, 0xfe5f,
+ 0xfe80, 0xfe80, 0xfe80, 0xfe80, 0xfe81, 0xfe81, 0xfe82, 0xfe82,
+ 0xfe83, 0xfe84, 0xfe85, 0xfe85, 0xfe86, 0xfe87, 0xfe88, 0xfe89,
+ 0xfe8a, 0xfe8b, 0xfe8c, 0xfe8e, 0xfe8f, 0xfe90, 0xfe91, 0xfe93,
+ 0xfe94, 0xfe95, 0xfe97, 0xfe98, 0xfe9a, 0xfe9b, 0xfe9d, 0xfe9f,
+ 0xfea0, 0xfea0, 0xfea0, 0xfea0, 0xfea1, 0xfea1, 0xfea2, 0xfea2,
+ 0xfea3, 0xfea4, 0xfea5, 0xfea5, 0xfea6, 0xfea7, 0xfea8, 0xfea9,
+ 0xfeaa, 0xfeab, 0xfeac, 0xfeae, 0xfeaf, 0xfeb0, 0xfeb1, 0xfeb3,
+ 0xfeb4, 0xfeb5, 0xfeb7, 0xfeb8, 0xfeba, 0xfebb, 0xfebd, 0xfebf,
+ 0xfee0, 0xfee0, 0xfee0, 0xfee0, 0xfee1, 0xfee1, 0xfee2, 0xfee2,
+ 0xfee3, 0xfee4, 0xfee5, 0xfee5, 0xfee6, 0xfee7, 0xfee8, 0xfee9,
+ 0xfeea, 0xfeeb, 0xfeec, 0xfeee, 0xfeef, 0xfef0, 0xfef1, 0xfef3,
+ 0xfef4, 0xfef5, 0xfef7, 0xfef8, 0xfefa, 0xfefb, 0xfefd, 0xfeff,
+ 0xff00, 0xff00, 0xff00, 0xff00, 0xff01, 0xff01, 0xff02, 0xff02,
+ 0xff03, 0xff04, 0xff05, 0xff05, 0xff06, 0xff07, 0xff08, 0xff09,
+ 0xff0a, 0xff0b, 0xff0c, 0xff0e, 0xff0f, 0xff10, 0xff11, 0xff13,
+ 0xff14, 0xff15, 0xff17, 0xff18, 0xff1a, 0xff1b, 0xff1d, 0xff1f,
+ 0xff40, 0xff40, 0xff40, 0xff40, 0xff41, 0xff41, 0xff42, 0xff42,
+ 0xff43, 0xff44, 0xff45, 0xff45, 0xff46, 0xff47, 0xff48, 0xff49,
+ 0xff4a, 0xff4b, 0xff4c, 0xff4e, 0xff4f, 0xff50, 0xff51, 0xff53,
+ 0xff54, 0xff55, 0xff57, 0xff58, 0xff5a, 0xff5b, 0xff5d, 0xff5f,
+ 0xff60, 0xff60, 0xff60, 0xff60, 0xff61, 0xff61, 0xff62, 0xff62,
+ 0xff63, 0xff64, 0xff65, 0xff65, 0xff66, 0xff67, 0xff68, 0xff69,
+ 0xff6a, 0xff6b, 0xff6c, 0xff6e, 0xff6f, 0xff70, 0xff71, 0xff73,
+ 0xff74, 0xff75, 0xff77, 0xff78, 0xff7a, 0xff7b, 0xff7d, 0xff7f,
+ 0xffa0, 0xffa0, 0xffa0, 0xffa0, 0xffa1, 0xffa1, 0xffa2, 0xffa2,
+ 0xffa3, 0xffa4, 0xffa5, 0xffa5, 0xffa6, 0xffa7, 0xffa8, 0xffa9,
+ 0xffaa, 0xffab, 0xffac, 0xffae, 0xffaf, 0xffb0, 0xffb1, 0xffb3,
+ 0xffb4, 0xffb5, 0xffb7, 0xffb8, 0xffba, 0xffbb, 0xffbd, 0xffbf,
+ 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe1, 0xffe1, 0xffe2, 0xffe2,
+ 0xffe3, 0xffe4, 0xffe5, 0xffe5, 0xffe6, 0xffe7, 0xffe8, 0xffe9,
+ 0xffea, 0xffeb, 0xffec, 0xffee, 0xffef, 0xfff0, 0xfff1, 0xfff3,
+ 0xfff4, 0xfff5, 0xfff7, 0xfff8, 0xfffa, 0xfffb, 0xfffd, 0xffff,
+};
diff --git a/sys/src/9/bitsy/init9.s b/sys/src/9/bitsy/init9.s
new file mode 100755
index 000000000..2de558259
--- /dev/null
+++ b/sys/src/9/bitsy/init9.s
@@ -0,0 +1,12 @@
+TEXT _main(SB),$8
+ MOVW $setR12(SB), R12 /* load the SB */
+ MOVW $boot(SB), R0
+
+ ADD $12, R13, R1 /* get a pointer to 0(FP) */
+
+ MOVW R0, 4(R13)
+ MOVW R1, 8(R13)
+
+ BL startboot(SB)
+
+
diff --git a/sys/src/9/bitsy/io.h b/sys/src/9/bitsy/io.h
new file mode 100755
index 000000000..bedfdf0a7
--- /dev/null
+++ b/sys/src/9/bitsy/io.h
@@ -0,0 +1,337 @@
+/*
+ * Definitions for IO devices. Used only in C.
+ */
+
+enum
+{
+ /* hardware counter frequency */
+ ClockFreq= 3686400,
+};
+
+/*
+ * IRQ's defined by SA1100
+ */
+enum
+{
+ IRQgpio0= 0,
+ IRQgpio1= 1,
+ IRQgpio2= 2,
+ IRQgpio3= 3,
+ IRQgpio4= 4,
+ IRQgpio5= 5,
+ IRQgpio6= 6,
+ IRQgpio7= 7,
+ IRQgpio8= 8,
+ IRQgpio9= 9,
+ IRQgpio10= 10,
+ IRQgpiohi= 11,
+ IRQlcd= 12,
+ IRQudc= 13,
+ IRQuart1b= 15,
+ IRQuart2= 16,
+ IRQuart3= 17,
+ IRQmcp= 18,
+ IRQssp= 19,
+ IRQdma0= 20,
+ IRQdma1= 21,
+ IRQdma2= 22,
+ IRQdma3= 23,
+ IRQdma4= 24,
+ IRQdma5= 25,
+ IRQtimer0= 26,
+ IRQtimer1= 27,
+ IRQtimer2= 28,
+ IRQtimer3= 29,
+ IRQsecond= 30,
+ IRQrtc= 31,
+};
+
+/*
+ * GPIO lines (signal names from compaq document). _i indicates input
+ * and _o output.
+ */
+enum
+{
+ GPIO_PWR_ON_i= 1<<0, /* power button */
+ GPIO_UP_IRQ_i= 1<<1, /* microcontroller interrupts */
+ GPIO_LDD8_o= 1<<2, /* LCD data 8-15 */
+ GPIO_LDD9_o= 1<<3,
+ GPIO_LDD10_o= 1<<4,
+ GPIO_LDD11_o= 1<<5,
+ GPIO_LDD12_o= 1<<6,
+ GPIO_LDD13_o= 1<<7,
+ GPIO_LDD14_o= 1<<8,
+ GPIO_LDD15_o= 1<<9,
+ GPIO_CARD_IND1_i= 1<<10, /* card inserted in PCMCIA socket 1 */
+ GPIO_CARD_IRQ1_i= 1<<11, /* PCMCIA socket 1 interrupt */
+ GPIO_CLK_SET0_o= 1<<12, /* clock selects for audio codec */
+ GPIO_CLK_SET1_o= 1<<13,
+ GPIO_L3_SDA_io= 1<<14, /* UDA1341 interface */
+ GPIO_L3_MODE_o= 1<<15,
+ GPIO_L3_SCLK_o= 1<<16,
+ GPIO_CARD_IND0_i= 1<<17, /* card inserted in PCMCIA socket 0 */
+ GPIO_KEY_ACT_i= 1<<18, /* hot key from cradle */
+ GPIO_SYS_CLK_i= 1<<19, /* clock from codec */
+ GPIO_BAT_FAULT_i= 1<<20, /* battery fault */
+ GPIO_CARD_IRQ0_i= 1<<21, /* PCMCIA socket 0 interrupt */
+ GPIO_LOCK_i= 1<<22, /* expansion pack lock/unlock */
+ GPIO_COM_DCD_i= 1<<23, /* DCD from UART3 */
+ GPIO_OPT_IRQ_i= 1<<24, /* expansion pack IRQ */
+ GPIO_COM_CTS_i= 1<<25, /* CTS from UART3 */
+ GPIO_COM_RTS_o= 1<<26, /* RTS to UART3 */
+ GPIO_OPT_IND_i= 1<<27, /* expansion pack inserted */
+
+/* Peripheral Unit GPIO pin assignments: alternate functions */
+ GPIO_SSP_TXD_o= 1<<10, /* SSP Transmit Data */
+ GPIO_SSP_RXD_i= 1<<11, /* SSP Receive Data */
+ GPIO_SSP_SCLK_o= 1<<12, /* SSP Sample CLocK */
+ GPIO_SSP_SFRM_o= 1<<13, /* SSP Sample FRaMe */
+ /* ser. port 1: */
+ GPIO_UART_TXD_o= 1<<14, /* UART Transmit Data */
+ GPIO_UART_RXD_i= 1<<15, /* UART Receive Data */
+ GPIO_SDLC_SCLK_io= 1<<16, /* SDLC Sample CLocK (I/O) */
+ GPIO_SDLC_AAF_o= 1<<17, /* SDLC Abort After Frame */
+ GPIO_UART_SCLK1_i= 1<<18, /* UART Sample CLocK 1 */
+ /* ser. port 4: */
+ GPIO_SSP_CLK_i= 1<<19, /* SSP external CLocK */
+ /* ser. port 3: */
+ GPIO_UART_SCLK3_i= 1<<20, /* UART Sample CLocK 3 */
+ /* ser. port 4: */
+ GPIO_MCP_CLK_i= 1<<21, /* MCP CLocK */
+ /* test controller: */
+ GPIO_TIC_ACK_o= 1<<21, /* TIC ACKnowledge */
+ GPIO_MBGNT_o= 1<<21, /* Memory Bus GraNT */
+ GPIO_TREQA_i= 1<<22, /* TIC REQuest A */
+ GPIO_MBREQ_i= 1<<22, /* Memory Bus REQuest */
+ GPIO_TREQB_i= 1<<23, /* TIC REQuest B */
+ GPIO_1Hz_o= 1<<25, /* 1 Hz clock */
+ GPIO_RCLK_o= 1<<26, /* internal (R) CLocK (O, fcpu/2) */
+ GPIO_32_768kHz_o= 1<<27, /* 32.768 kHz clock (O, RTC) */
+};
+
+/*
+ * types of interrupts
+ */
+enum
+{
+ GPIOrising,
+ GPIOfalling,
+ GPIOboth,
+ IRQ,
+};
+
+/* hardware registers */
+typedef struct Uartregs Uartregs;
+struct Uartregs
+{
+ ulong ctl[4];
+ ulong dummya;
+ ulong data;
+ ulong dummyb;
+ ulong status[2];
+};
+extern Uartregs *uart3regs;
+extern Uartregs *uart1regs;
+
+/* general purpose I/O lines control registers */
+typedef struct GPIOregs GPIOregs;
+struct GPIOregs
+{
+ ulong level; /* 1 == high */
+ ulong direction; /* 1 == output */
+ ulong set; /* a 1 sets the bit, 0 leaves it alone */
+ ulong clear; /* a 1 clears the bit, 0 leaves it alone */
+ ulong rising; /* rising edge detect enable */
+ ulong falling; /* falling edge detect enable */
+ ulong edgestatus; /* writing a 1 bit clears */
+ ulong altfunc; /* turn on alternate function for any set bits */
+};
+
+extern GPIOregs *gpioregs;
+
+/* extra general purpose I/O bits, output only */
+enum
+{
+ EGPIO_prog_flash= 1<<0,
+ EGPIO_pcmcia_reset= 1<<1,
+ EGPIO_exppack_reset= 1<<2,
+ EGPIO_codec_reset= 1<<3,
+ EGPIO_exp_nvram_power= 1<<4,
+ EGPIO_exp_full_power= 1<<5,
+ EGPIO_lcd_3v= 1<<6,
+ EGPIO_rs232_power= 1<<7,
+ EGPIO_lcd_ic_power= 1<<8,
+ EGPIO_ir_power= 1<<9,
+ EGPIO_audio_power= 1<<10,
+ EGPIO_audio_ic_power= 1<<11,
+ EGPIO_audio_mute= 1<<12,
+ EGPIO_fir= 1<<13, /* not set is sir */
+ EGPIO_lcd_5v= 1<<14,
+ EGPIO_lcd_9v= 1<<15,
+};
+extern ulong *egpioreg;
+
+/* Peripheral pin controller registers */
+typedef struct PPCregs PPCregs;
+struct PPCregs {
+ ulong direction;
+ ulong state;
+ ulong assignment;
+ ulong sleepdir;
+ ulong flags;
+};
+extern PPCregs *ppcregs;
+
+/* Synchronous Serial Port controller registers */
+typedef struct SSPregs SSPregs;
+struct SSPregs {
+ ulong control0;
+ ulong control1;
+ ulong dummy0;
+ ulong data;
+ ulong dummy1;
+ ulong status;
+};
+extern SSPregs *sspregs;
+
+/* Multimedia Communications Port controller registers */
+typedef struct MCPregs MCPregs;
+struct MCPregs {
+ ulong control0;
+ ulong reserved0;
+ ulong data0;
+ ulong data1;
+ ulong data2;
+ ulong reserved1;
+ ulong status;
+ ulong reserved[11];
+ ulong control1;
+};
+extern MCPregs *mcpregs;
+
+/*
+ * memory configuration
+ */
+enum
+{
+ /* bit shifts for pcmcia access time counters */
+ MECR_io0= 0,
+ MECR_attr0= 5,
+ MECR_mem0= 10,
+ MECR_fast0= 11,
+ MECR_io1= MECR_io0+16,
+ MECR_attr1= MECR_attr0+16,
+ MECR_mem1= MECR_mem0+16,
+ MECR_fast1= MECR_fast0+16,
+
+ REFR_kapd= 29,
+ REFR_eapd= 28,
+ REFR_k1db2= 22,
+ REFR_slfrsh= 31,
+};
+
+typedef struct MemConfRegs MemConfRegs;
+struct MemConfRegs
+{
+ ulong mdcnfg; /* 0x00 dram */
+ ulong mdcas00; /* 0x04 dram banks 0/1 */
+ ulong mdcas01; /* 0x08 */
+ ulong mdcas02; /* 0x0c */
+ ulong msc0; /* 0x10 static */
+ ulong msc1; /* 0x14 */
+ ulong mecr; /* 0x18 pcmcia */
+ ulong mdrefr; /* 0x1c dram refresh */
+ ulong mdcas20; /* 0x20 dram banks 2/3 */
+ ulong mdcas21; /* 0x24 */
+ ulong mdcas22; /* 0x28 */
+ ulong msc2; /* 0x2c static */
+ ulong smcnfg; /* 0x30 SMROM config */
+};
+extern MemConfRegs *memconfregs;
+
+/*
+ * power management
+ */
+
+/* Power management ops */
+
+typedef struct PowerRegs PowerRegs;
+struct PowerRegs
+{
+ ulong pmcr; /* 0x0 Power manager control register */
+ ulong pssr; /* 0x4 Power manager sleep status register */
+ ulong pspr; /* 0x8 Power manager scratch pad register */
+ ulong pwer; /* 0xc Power manager wakeup enable register */
+ ulong pcfr; /* 0x10 Power manager general configuration register */
+ ulong ppcr; /* 0x14 Power manager PPL configuration register */
+ ulong pgsr; /* 0x18 Power manager GPIO sleep state register */
+ ulong posr; /* 0x1c Power manager oscillator status register */
+};
+extern PowerRegs *powerregs;
+
+/*
+ * reset controller
+ */
+
+enum
+{
+ RCSR_hwr = 0x00000001, /* hw reset */
+ RCSR_swr = 0x00000002, /* sw reset */
+ RCSR_wdr = 0x00000004, /* watch dog */
+ RCSR_smr = 0x00000008, /* sleep mode reset */
+};
+
+typedef struct ResetRegs ResetRegs;
+struct ResetRegs
+{
+ ulong rsrr; /* reset controller software reset register */
+ ulong rcsr; /* reset controller status register */
+};
+extern ResetRegs *resetregs;
+
+typedef struct OSTimerRegs OSTimerRegs;
+struct OSTimerRegs
+{
+ ulong osmr[4]; /* match registers */
+ ulong oscr; /* counter register */
+ ulong ossr; /* status register */
+ ulong ower; /* watchdog enable register */
+ ulong oier; /* timer interrupt enable register */
+};
+extern OSTimerRegs* timerregs;
+
+typedef struct Intrregs Intrregs;
+struct Intrregs
+{
+ ulong icip; /* pending IRQs */
+ ulong icmr; /* IRQ mask */
+ ulong iclr; /* IRQ if bit == 0, FRIQ if 1 */
+ ulong iccr; /* control register */
+ ulong icfp; /* pending FIQs */
+ ulong dummy1[3];
+ ulong icpr; /* pending interrupts */
+};
+extern Intrregs *intrregs;
+
+typedef struct Gpclkregs Gpclkregs;
+struct Gpclkregs
+{
+ ulong r0;
+ ulong r1;
+ ulong dummya;
+ ulong r2;
+ ulong r3;
+};
+extern Gpclkregs *gpclkregs;
+
+/*
+ * Dont use this on bitsy drivers.
+ * This is for compat with code compiled
+ * from the ../pc directory
+ */
+
+typedef struct Pcidev Pcidev;
+typedef struct ISAConf ISAConf;
+struct Pcidev { int dummy; };
+struct ISAConf{ int port; int irq; };
+int pcmspecial(char*, ISAConf*);
diff --git a/sys/src/9/bitsy/l.s b/sys/src/9/bitsy/l.s
new file mode 100755
index 000000000..281fa41b0
--- /dev/null
+++ b/sys/src/9/bitsy/l.s
@@ -0,0 +1,856 @@
+#include "mem.h"
+
+/*
+ * Entered here from Compaq's bootldr with MMU disabled.
+ */
+TEXT _start(SB), $-4
+ MOVW $setR12(SB), R12 /* load the SB */
+_main:
+ /* SVC mode, interrupts disabled */
+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
+ MOVW R1, CPSR
+
+ /* disable the MMU */
+ MOVW $0x130, R1
+ MCR CpMMU, 0, R1, C(CpControl), C(0x0)
+
+ /* flush caches */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+ /* drain prefetch */
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+
+ /* drain write buffer */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+
+ MOVW $(MACHADDR+4*BY2PG), R13 /* stack */
+ SUB $4, R13 /* link */
+ BL main(SB)
+ BL exit(SB)
+ /* we shouldn't get here */
+_mainloop:
+ B _mainloop
+ BL _div(SB) /* hack to get _div etc loaded */
+
+/* flush tlb's */
+TEXT mmuinvalidate(SB), $-4
+ MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
+ RET
+
+/* flush tlb's */
+TEXT mmuinvalidateaddr(SB), $-4
+ MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x6), 1
+ RET
+
+/* write back and invalidate i and d caches */
+TEXT cacheflush(SB), $-4
+ /* splhi */
+ MOVW CPSR, R3
+ ORR $(PsrDirq), R3, R1
+ MOVW R1, CPSR
+
+ /* write back any dirty data */
+ MOVW $0xe0000000,R0
+ ADD $(8*1024),R0,R1
+_cfloop:
+ MOVW.P 32(R0),R2
+ CMP.S R0,R1
+ BGE _cfloop
+
+ /* drain write buffer and invalidate i cache contents */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x5), 0
+
+ /* drain prefetch */
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+
+ /* splx */
+ MOVW R3, CPSR
+ RET
+
+/* write back d cache */
+TEXT cachewb(SB), $-4
+ /* write back any dirty data */
+_cachewb:
+ MOVW $0xe0000000,R0
+ ADD $(8*1024),R0,R1
+_cwbloop:
+ MOVW.P 32(R0),R2
+ CMP.S R0,R1
+ BGE _cwbloop
+
+ /* drain write buffer */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+ RET
+
+/* write back a single cache line */
+TEXT cachewbaddr(SB), $-4
+ BIC $31,R0
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
+ B _wbflush
+
+/* write back a region of cache lines */
+TEXT cachewbregion(SB), $-4
+ MOVW 4(FP),R1
+ CMP.S $(4*1024),R1
+ BGT _cachewb
+ ADD R0,R1
+ BIC $31,R0
+_cwbrloop:
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
+ ADD $32,R0
+ CMP.S R0,R1
+ BGT _cwbrloop
+ B _wbflush
+
+/* invalidate the dcache */
+TEXT dcacheinvalidate(SB), $-4
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x6)
+ RET
+
+/* invalidate the icache */
+TEXT icacheinvalidate(SB), $-4
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x9)
+ RET
+
+/* drain write buffer */
+TEXT wbflush(SB), $-4
+_wbflush:
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+ RET
+
+/* return cpu id */
+TEXT getcpuid(SB), $-4
+ MRC CpMMU, 0, R0, C(CpCPUID), C(0x0)
+ RET
+
+/* return fault status */
+TEXT getfsr(SB), $-4
+ MRC CpMMU, 0, R0, C(CpFSR), C(0x0)
+ RET
+
+/* return mmu control register */
+TEXT getcontrol(SB), $-4
+ SUB R0, R0
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
+
+/* return mmu dac register */
+TEXT getdac(SB), $-4
+ SUB R0, R0
+ MRC CpMMU, 0, R0, C(CpDAC), C(0x0)
+ RET
+
+/* return mmu ttb register */
+TEXT getttb(SB), $-4
+ SUB R0, R0
+ MRC CpMMU, 0, R0, C(CpTTB), C(0x0)
+ RET
+
+/* return fault address */
+TEXT getfar(SB), $-4
+ MRC CpMMU, 0, R0, C(CpFAR), C(0x0)
+ RET
+
+/* set the translation table base */
+TEXT putttb(SB), $-4
+ MCR CpMMU, 0, R0, C(CpTTB), C(0x0)
+ RET
+
+/*
+ * enable mmu, i and d caches
+ */
+TEXT mmuenable(SB), $-4
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ ORR $(CpCmmuena|CpCdcache|CpCicache|CpCwb|CpCsystem), R0
+ BIC $(CpCrom), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ RET
+
+TEXT mmudisable(SB), $-4
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ BIC $(CpCmmuena|CpCdcache|CpCicache|CpCwb|CpCvivec), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
+
+/*
+ * use exception vectors at 0xffff0000
+ */
+TEXT mappedIvecEnable(SB), $-4
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ ORR $(CpCvivec), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
+TEXT mappedIvecDisable(SB), $-4
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ BIC $(CpCvivec), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
+
+/* set the translation table base */
+TEXT putdac(SB), $-4
+ MCR CpMMU, 0, R0, C(CpDAC), C(0x0)
+ RET
+
+/* set address translation pid */
+TEXT putpid(SB), $-4
+ MCR CpMMU, 0, R0, C(CpPID), C(0x0)
+ RET
+
+/*
+ * set the stack value for the mode passed in R0
+ */
+TEXT setr13(SB), $-4
+ MOVW 4(FP), R1
+
+ MOVW CPSR, R2
+ BIC $PsrMask, R2, R3
+ ORR R0, R3
+ MOVW R3, CPSR
+
+ MOVW R13, R0
+ MOVW R1, R13
+
+ MOVW R2, CPSR
+ RET
+
+/*
+ * exception vectors, copied by trapinit() to somewhere useful
+ */
+
+TEXT vectors(SB), $-4
+ MOVW 0x18(R15), R15 /* reset */
+ MOVW 0x18(R15), R15 /* undefined */
+ MOVW 0x18(R15), R15 /* SWI */
+ MOVW 0x18(R15), R15 /* prefetch abort */
+ MOVW 0x18(R15), R15 /* data abort */
+ MOVW 0x18(R15), R15 /* reserved */
+ MOVW 0x18(R15), R15 /* IRQ */
+ MOVW 0x18(R15), R15 /* FIQ */
+
+TEXT vtable(SB), $-4
+ WORD $_vsvc(SB) /* reset, in svc mode already */
+ WORD $_vund(SB) /* undefined, switch to svc mode */
+ WORD $_vsvc(SB) /* swi, in svc mode already */
+ WORD $_vpabt(SB) /* prefetch abort, switch to svc mode */
+ WORD $_vdabt(SB) /* data abort, switch to svc mode */
+ WORD $_vsvc(SB) /* reserved */
+ WORD $_virq(SB) /* IRQ, switch to svc mode */
+ WORD $_vfiq(SB) /* FIQ, switch to svc mode */
+
+TEXT _vrst(SB), $-4
+ BL resettrap(SB)
+
+TEXT _vsvc(SB), $-4 /* SWI */
+ MOVW.W R14, -4(R13) /* ureg->pc = interupted PC */
+ MOVW SPSR, R14 /* ureg->psr = SPSR */
+ MOVW.W R14, -4(R13) /* ... */
+ MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */
+ MOVW.W R14, -4(R13) /* ... */
+ MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $8, R13 /* space for argument+link */
+
+ BL syscall(SB)
+
+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT _vund(SB), $-4 /* undefined */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMund, R0
+ B _vswitch
+
+TEXT _vpabt(SB), $-4 /* prefetch abort */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMabt, R0 /* r0 = type */
+ B _vswitch
+
+TEXT _vdabt(SB), $-4 /* prefetch abort */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $(PsrMabt+1), R0 /* r0 = type */
+ B _vswitch
+
+TEXT _virq(SB), $-4 /* IRQ */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMirq, R0 /* r0 = type */
+ B _vswitch
+
+ /*
+ * come here with type in R0 and R13 pointing above saved [r0-r4]
+ * and type in r0. we'll switch to SVC mode and then call trap.
+ */
+_vswitch:
+ MOVW SPSR, R1 /* save SPSR for ureg */
+ MOVW R14, R2 /* save interrupted pc for ureg */
+ MOVW R13, R3 /* save pointer to where the original [R0-R3] are */
+
+ /* switch to svc mode */
+ MOVW CPSR, R14
+ BIC $PsrMask, R14
+ ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
+ MOVW R14, CPSR
+
+ /* interupted code kernel or user? */
+ AND.S $0xf, R1, R4
+ BEQ _userexcep
+
+ /* here for trap from SVC mode */
+ MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
+ MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
+ MOVM.DB.W [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $8, R13 /* space for argument+link (for debugger) */
+ MOVW $0xdeaddead,R11 /* marker */
+
+ BL trap(SB)
+
+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+ /* here for trap from USER mode */
+_userexcep:
+ MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
+ MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
+ MOVM.DB.W.S [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $8, R13 /* space for argument+link (for debugger) */
+
+ BL trap(SB)
+
+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT _vfiq(SB), $-4 /* FIQ */
+ RFE /* FIQ is special, ignore it for now */
+
+/*
+ * This is the first jump from kernel to user mode.
+ * Fake a return from interrupt.
+ *
+ * Enter with R0 containing the user stack pointer.
+ * UTZERO + 0x20 is always the entry point.
+ *
+ */
+TEXT touser(SB),$-4
+ /* store the user stack pointer into the USR_r13 */
+ MOVM.DB.W [R0], (R13)
+ MOVM.S.IA.W (R13),[R13]
+
+ /* set up a PSR for user level */
+ MOVW $(PsrMusr), R0
+ MOVW R0,SPSR
+
+ /* save the PC on the stack */
+ MOVW $(UTZERO+0x20), R0
+ MOVM.DB.W [R0],(R13)
+
+ /* return from interrupt */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+/*
+ * here to jump to a newly forked process
+ */
+TEXT forkret(SB),$-4
+ ADD $(4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT splhi(SB), $-4
+ /* save caller pc in Mach */
+ MOVW $(MACHADDR+0x04),R2
+ MOVW R14,0(R2)
+ /* turn off interrupts */
+ MOVW CPSR, R0
+ ORR $(PsrDirq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+TEXT spllo(SB), $-4
+ MOVW CPSR, R0
+ BIC $(PsrDirq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+TEXT splx(SB), $-4
+ /* save caller pc in Mach */
+ MOVW $(MACHADDR+0x04),R2
+ MOVW R14,0(R2)
+ /* reset interrupt level */
+ MOVW R0, R1
+ MOVW CPSR, R0
+ MOVW R1, CPSR
+ RET
+
+TEXT splxpc(SB), $-4 /* for iunlock */
+ MOVW R0, R1
+ MOVW CPSR, R0
+ MOVW R1, CPSR
+ RET
+
+TEXT spldone(SB), $0
+ RET
+
+TEXT islo(SB), $-4
+ MOVW CPSR, R0
+ AND $(PsrDirq), R0
+ EOR $(PsrDirq), R0
+ RET
+
+TEXT cpsrr(SB), $-4
+ MOVW CPSR, R0
+ RET
+
+TEXT spsrr(SB), $-4
+ MOVW SPSR, R0
+ RET
+
+TEXT getsp(SB), $-4
+ MOVW R13, R0
+ RET
+
+TEXT getlink(SB), $-4
+ MOVW R14, R0
+ RET
+
+TEXT getcallerpc(SB), $-4
+ MOVW 0(R13), R0
+ RET
+
+TEXT tas(SB), $-4
+ MOVW R0, R1
+ MOVW $0xDEADDEAD, R0
+ MOVW R0, R3
+ SWPW R0, (R1)
+ CMP.S R0, R3
+ BEQ _tasout
+ EOR R3, R3
+ CMP.S R0, R3
+ BEQ _tasout
+ MOVW $1,R15
+_tasout:
+ RET
+
+TEXT setlabel(SB), $-4
+ MOVW R13, 0(R0) /* sp */
+ MOVW R14, 4(R0) /* pc */
+ MOVW $0, R0
+ RET
+
+TEXT gotolabel(SB), $-4
+ MOVW 0(R0), R13 /* sp */
+ MOVW 4(R0), R14 /* pc */
+ MOVW $1, R0
+ RET
+
+/* save the state machine in power_state[] for an upcoming suspend
+ */
+TEXT setpowerlabel(SB), $-4
+ MOVW $power_state+0(SB), R0
+ /* svc */ /* power_state[]: what */
+ MOVW R1, 0(R0)
+ MOVW R2, 4(R0)
+ MOVW R3, 8(R0)
+ MOVW R4, 12(R0)
+ MOVW R5, 16(R0)
+ MOVW R6, 20(R0)
+ MOVW R7, 24(R0)
+ MOVW R8, 28(R0)
+ MOVW R9, 32(R0)
+ MOVW R10,36(R0)
+ MOVW R11,40(R0)
+ MOVW R12,44(R0)
+ MOVW R13,48(R0)
+ MOVW R14,52(R0)
+ MOVW SPSR, R1
+ MOVW R1, 56(R0)
+ MOVW CPSR, R2
+ MOVW R2, 60(R0)
+ /* copro */
+ MRC CpMMU, 0, R3, C(CpDAC), C(0x0)
+ MOVW R3, 144(R0)
+ MRC CpMMU, 0, R3, C(CpTTB), C(0x0)
+ MOVW R3, 148(R0)
+ MRC CpMMU, 0, R3, C(CpControl), C(0x0)
+ MOVW R3, 152(R0)
+ MRC CpMMU, 0, R3, C(CpFSR), C(0x0)
+ MOVW R3, 156(R0)
+ MRC CpMMU, 0, R3, C(CpFAR), C(0x0)
+ MOVW R3, 160(R0)
+ MRC CpMMU, 0, R3, C(CpPID), C(0x0)
+ MOVW R3, 164(R0)
+ /* usr */
+ BIC $(PsrMask), R2, R3
+ ORR $(0xdf), R3
+ MOVW R3, CPSR
+ MOVW SPSR, R11
+ MOVW R11, 168(R0)
+ MOVW R12, 172(R0)
+ MOVW R13, 176(R0)
+ MOVW R14, 180(R0)
+ /* irq */
+ BIC $(PsrMask), R2, R3
+ ORR $(0xd2), R3
+ MOVW R3, CPSR
+ MOVW SPSR, R11
+ MOVW R11, 64(R0)
+ MOVW R12, 68(R0)
+ MOVW R13, 72(R0)
+ MOVW R14, 76(R0)
+ /* und */
+ BIC $(PsrMask), R2, R3
+ ORR $(0xdb), R3
+ MOVW R3, CPSR
+ MOVW SPSR, R11
+ MOVW R11, 80(R0)
+ MOVW R12, 84(R0)
+ MOVW R13, 88(R0)
+ MOVW R14, 92(R0)
+ /* abt */
+ BIC $(PsrMask), R2, R3
+ ORR $(0xd7), R3
+ MOVW R3, CPSR
+ MOVW SPSR, R11
+ MOVW R11, 96(R0)
+ MOVW R12, 100(R0)
+ MOVW R13, 104(R0)
+ MOVW R14, 108(R0)
+ /* fiq */
+ BIC $(PsrMask), R2, R3
+ ORR $(0xd1), R3
+ MOVW R3, CPSR
+ MOVW SPSR, R7
+ MOVW R7, 112(R0)
+ MOVW R8, 116(R0)
+ MOVW R9, 120(R0)
+ MOVW R10,124(R0)
+ MOVW R11,128(R0)
+ MOVW R12,132(R0)
+ MOVW R13,136(R0)
+ MOVW R14,140(R0)
+ /* done */
+ MOVW R2, CPSR
+ MOVW R1, SPSR
+ MOVW $0, R0
+ RET
+
+/* Entered after a resume from suspend state.
+ * The bootldr jumps here after a processor reset.
+ */
+TEXT power_resume(SB), $-4
+ MOVW $setR12(SB), R12 /* load the SB */
+ /* SVC mode, interrupts disabled */
+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
+ MOVW R1, CPSR
+ /* gotopowerlabel() */
+ /* svc */
+
+ MOVW $power_state+0(SB), R0
+ MOVW 56(R0), R1 /* R1: SPSR, R2: CPSR */
+ MOVW 60(R0), R2
+ MOVW R1, SPSR
+ MOVW R2, CPSR
+ /* copro */
+ /* flush caches */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+ /* drain prefetch */
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ /* drain write buffer */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+ MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
+ MOVW 144(R0), R3
+ MCR CpMMU, 0, R3, C(CpDAC), C(0x0)
+ MOVW 148(R0), R3
+ MCR CpMMU, 0, R3, C(CpTTB), C(0x0)
+ MOVW 156(R0), R3
+ MCR CpMMU, 0, R3, C(CpFSR), C(0x0)
+ MOVW 160(R0), R3
+ MCR CpMMU, 0, R3, C(CpFAR), C(0x0)
+ MOVW 164(R0), R3
+ MCR CpMMU, 0, R3, C(CpPID), C(0x0)
+ MOVW 152(R0), R3
+ MCR CpMMU, 0, R3, C(CpControl), C(0x0) /* Enable cache */
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ /* flush i&d caches */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+ /* flush tlb */
+ MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7), 0
+ /* drain prefetch */
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ /* usr */
+ BIC $(PsrMask), R2, R3
+ ORR $(0xdf), R3
+ MOVW 168(R0), R11
+ MOVW 172(R0), R12
+ MOVW 176(R0), R13
+ MOVW 180(R0), R14
+ MOVW R11, SPSR
+ /* irq */
+ BIC $(PsrMask), R2, R3
+ ORR $(0xd2), R3
+ MOVW R3, CPSR
+ MOVW 64(R0), R11
+ MOVW 68(R0), R12
+ MOVW 72(R0), R13
+ MOVW 76(R0), R14
+ MOVW R11, SPSR
+ /* und */
+ BIC $(PsrMask), R2, R3
+ ORR $(0xdb), R3
+ MOVW R3, CPSR
+ MOVW 80(R0), R11
+ MOVW 84(R0), R12
+ MOVW 88(R0), R13
+ MOVW 92(R0), R14
+ MOVW R11, SPSR
+ /* abt */
+ BIC $(PsrMask), R2, R3
+ ORR $(0xd7), R3
+ MOVW R3, CPSR
+ MOVW 96(R0), R11
+ MOVW 100(R0), R12
+ MOVW 104(R0), R13
+ MOVW 108(R0), R14
+ MOVW R11, SPSR
+ /* fiq */
+ BIC $(PsrMask), R2, R3
+ ORR $(0xd1), R3
+ MOVW R3, CPSR
+ MOVW 112(R0), R7
+ MOVW 116(R0), R8
+ MOVW 120(R0), R9
+ MOVW 124(R0), R10
+ MOVW 128(R0), R11
+ MOVW 132(R0), R12
+ MOVW 136(R0), R13
+ MOVW 140(R0), R14
+ MOVW R7, SPSR
+ /* svc */
+ MOVW 56(R0), R1
+ MOVW 60(R0), R2
+ MOVW R1, SPSR
+ MOVW R2, CPSR
+ MOVW 0(R0), R1
+ MOVW 4(R0), R2
+ MOVW 8(R0), R3
+ MOVW 12(R0),R4
+ MOVW 16(R0),R5
+ MOVW 20(R0),R6
+ MOVW 24(R0),R7
+ MOVW 28(R0),R8
+ MOVW 32(R0),R9
+ MOVW 36(R0),R10
+ MOVW 40(R0),R11
+ MOVW 44(R0),R12
+ MOVW 48(R0),R13
+ MOVW 52(R0),R14
+ RET
+loop:
+ B loop
+
+TEXT power_down(SB), $-4
+
+ TEXT sa1100_power_off<>+0(SB),$8
+ MOVW resetregs+0(SB),R7
+ MOVW gpioregs+0(SB),R6
+ MOVW memconfregs+0(SB),R5
+ MOVW powerregs+0(SB),R3
+
+
+ /* wakeup on power | rtc */
+ MOVW $(PWR_rtc|PWR_gpio0),R2
+ MOVW R2,0xc(R3)
+
+ /* clear reset status */
+ MOVW $(RCSR_all), R2
+ MOVW R2, 0x4(R7)
+ /* float */
+ MOVW $(PCFR_opde|PCFR_fp|PCFR_fs), R2
+ MOVW R2,0x10(R3)
+ /* sleep state */
+ MOVW $0,R2
+ MOVW R2,0x18(R3)
+ /* set resume address (pspr)*/
+ MOVW $resumeaddr+0(SB),R1
+ MOVW 0x0(R1), R2
+ MOVW R2,0x8(R3)
+
+ BL cacheflush(SB)
+
+ /* disable clock switching */
+ MCR CpPWR, 0, R1, C(CpTest), C(0x2), 2
+
+ /* adjust mem timing */
+ MOVW memconfregs+0(SB),R5
+ MOVW 0x1c(R5), R2
+ ORR $(MDREFR_k1db2), R2
+ MOVW R2, 0x1c(R5)
+
+ /* set PLL to lower speed w/ delay (ppcr = 0)*/
+ MOVW powerregs+0(SB),R3
+ MOVW $(120*206),R0
+l11: SUB $1,R0
+ BGT l11
+ MOVW $0, R2
+ MOVW R2, 0x14(R3)
+ MOVW $(120*206),R0
+l12: SUB $1,R0
+ BGT l12
+
+ /* setup registers for suspend procedure:
+ * 1. clear RT in mscx (R1, R7, R8)
+ * 2. clear DRI in mdrefr (R4)
+ * 3. set slfrsh in mdrefr (R6)
+ * 4. clear DE in mdcnfg (R9)
+ * 5. clear dram refresh (R10)
+ * 6. force sleep (R2)
+ */
+ /* 1 */
+ MOVW 0x10(R5), R2
+ BIC $(MSC_rt), R2
+ MOVW R2, R1
+ MOVW 0x14(R5), R2
+ BIC $(MSC_rt), R2
+ MOVW R2, R7
+ MOVW 0x2c(R5), R2
+ BIC $(MSC_rt), R2
+ MOVW R2, R8
+ /* 2 */
+ MOVW 0x1c(R5), R2
+ BIC $(0xff00), R2
+ BIC $(0x00f0), R2
+ MOVW R2, R4
+ /* 3 */
+ ORR $(MDREFR_slfrsh), R2, R6
+ /* 4 */
+ MOVW 0x0(R5), R9
+ BIC $(MDCFNG_de), R9, R9
+ /* 5 */
+ MOVW R4, R2
+ BIC $(MDREFR_slfrsh), R2, R2
+ BIC $(MDREFR_e1pin), R2, R2
+ MOVW R2, R10
+ /* 6 */
+ MOVW $1,R2
+
+TEXT power_magic(SB), $-4
+ /* power_code gets copied into the area of no-ops below,
+ * at a cache-line boundary (8 instructions)
+ */
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+ MOVW R0, R0
+
+TEXT power_code(SB), $-4
+ /* Follow the procedure; this code gets copied to the no-op
+ * area preceding this code
+ */
+ /* 1 */
+ MOVW R1, 0x10(R5)
+ MOVW R7, 0x14(R5)
+ MOVW R8, 0x2c(R5)
+ /* 2 */
+ MOVW R4, 0x1c(R5)
+ /* 3 */
+ MOVW R6, 0x1c(R5)
+ /* 4 */
+ MOVW R9, 0x0(R5)
+ /* 5 */
+ MOVW R10, 0x1c(R5)
+ /* 6 */
+ MOVW R2, 0x0(R3)
+slloop:
+ B slloop /* loop waiting for sleep */
+
+/* The first MCR instruction of this function needs to be on a cache-line
+ * boundary; to make this happen, it will be copied to the first cache-line
+ * boundary 8 words from the start of doze.
+ *
+ * Doze puts the machine into idle mode. Any interrupt will get it out
+ * at the next instruction (the RET, to be precise).
+ */
+TEXT doze(SB), $-4
+ MOVW $UCDRAMZERO, R1
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ RET
+
+TEXT doze_code(SB), $-4
+ MCR CpPWR, 0, R0, C(CpTest), C(0x2), 2
+ MOVW (R1), R0
+ MCR CpPWR, 0, R0, C(CpTest), C(0x8), 2
diff --git a/sys/src/9/bitsy/main.c b/sys/src/9/bitsy/main.c
new file mode 100755
index 000000000..041b780c1
--- /dev/null
+++ b/sys/src/9/bitsy/main.c
@@ -0,0 +1,555 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "init.h"
+#include "pool.h"
+
+Mach *m;
+Proc *up;
+Conf conf;
+int noprint;
+
+void
+main(void)
+{
+ mmuinvalidate();
+
+ /* zero out bss */
+ memset(edata, 0, end-edata);
+
+ /* point to Mach structure */
+ m = (Mach*)MACHADDR;
+ memset(m, 0, sizeof(Mach));
+ m->ticks = 1;
+
+ active.machs = 1;
+
+ rs232power(1);
+ quotefmtinstall();
+ iprint("\nPlan 9 bitsy kernel\n");
+ confinit();
+ xinit();
+ mmuinit();
+ machinit();
+ trapinit();
+ sa1110_uartsetup(1);
+ dmainit();
+ screeninit();
+ printinit(); /* from here on, print works, before this we need iprint */
+ clockinit();
+ procinit0();
+ initseg();
+ links();
+ chandevreset();
+ pageinit();
+ swapinit();
+ userinit();
+ powerinit();
+ schedinit();
+}
+
+/* need to do better */
+void
+reboot(void*, void*, ulong)
+{
+ exit(0);
+}
+
+
+/*
+ * exit kernel either on a panic or user request
+ */
+void
+exit(int ispanic)
+{
+ void (*f)(void);
+
+ USED(ispanic);
+ delay(1000);
+
+ iprint("it's a wonderful day to die\n");
+ cacheflush();
+ mmuinvalidate();
+ mmudisable();
+ f = nil;
+ (*f)();
+}
+
+static uchar *sp;
+
+/*
+ * starting place for first process
+ */
+void
+init0(void)
+{
+ up->nerrlab = 0;
+
+ spllo();
+
+ /*
+ * These are o.k. because rootinit is null.
+ * Then early kproc's will have a root and dot.
+ */
+ up->slash = namec("#/", Atodir, 0, 0);
+ pathclose(up->slash->path);
+ up->slash->path = newpath("/");
+ up->dot = cclone(up->slash);
+
+ chandevinit();
+
+ if(!waserror()){
+ ksetenv("terminal", "bitsy", 0);
+ ksetenv("cputype", "arm", 0);
+ if(cpuserver)
+ ksetenv("service", "cpu", 0);
+ else
+ ksetenv("service", "terminal", 0);
+ poperror();
+ }
+ kproc("alarm", alarmkproc, 0);
+ kproc("power", powerkproc, 0);
+
+ touser(sp);
+}
+
+/*
+ * pass boot arguments to /boot
+ */
+static uchar *
+pusharg(char *p)
+{
+ int n;
+
+ n = strlen(p)+1;
+ sp -= n;
+ memmove(sp, p, n);
+ return sp;
+}
+static void
+bootargs(ulong base)
+{
+ int i, ac;
+ uchar *av[32];
+ uchar *bootpath;
+ uchar **lsp;
+
+ /*
+ * the sizeof(Sargs) is to make the validaddr check in
+ * trap.c's syscall() work even when we have less than the
+ * max number of args.
+ */
+ sp = (uchar*)base + BY2PG - sizeof(Sargs);
+
+ bootpath = pusharg("/boot/boot");
+ ac = 0;
+ av[ac++] = pusharg("boot");
+
+ /* 4 byte word align stack */
+ sp = (uchar*)((ulong)sp & ~3);
+
+ /* build argc, argv on stack */
+ sp -= (ac+1)*sizeof(sp);
+ lsp = (uchar**)sp;
+ for(i = 0; i < ac; i++)
+ *lsp++ = av[i] + ((USTKTOP - BY2PG) - base);
+ *lsp = 0;
+
+ /* push argv onto stack */
+ sp -= BY2WD;
+ lsp = (uchar**)sp;
+ *lsp = sp + BY2WD + ((USTKTOP - BY2PG) - base);
+
+ /* push pointer to "/boot" */
+ sp -= BY2WD;
+ lsp = (uchar**)sp;
+ *lsp = bootpath + ((USTKTOP - BY2PG) - base);
+
+ /* leave space for where the initcode's caller's return PC would normally reside */
+ sp -= BY2WD;
+
+ /* relocate stack to user's virtual addresses */
+ sp += (USTKTOP - BY2PG) - base;
+}
+
+/*
+ * create the first process
+ */
+void
+userinit(void)
+{
+ Proc *p;
+ Segment *s;
+ KMap *k;
+ Page *pg;
+
+ /* no processes yet */
+ up = nil;
+
+ p = newproc();
+ p->pgrp = newpgrp();
+ p->egrp = smalloc(sizeof(Egrp));
+ p->egrp->ref = 1;
+ p->fgrp = dupfgrp(nil);
+ p->rgrp = newrgrp();
+ p->procmode = 0640;
+
+ kstrdup(&eve, "");
+ kstrdup(&p->text, "*init*");
+ kstrdup(&p->user, eve);
+
+ /*
+ * Kernel Stack
+ */
+ p->sched.pc = (ulong)init0;
+ p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
+
+ /*
+ * User Stack
+ */
+ s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
+ p->seg[SSEG] = s;
+ pg = newpage(1, 0, USTKTOP-BY2PG);
+ segpage(s, pg);
+ k = kmap(pg);
+ bootargs(VA(k));
+ kunmap(k);
+
+ /*
+ * Text
+ */
+ s = newseg(SG_TEXT, UTZERO, 1);
+ p->seg[TSEG] = s;
+ pg = newpage(1, 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);
+
+ ready(p);
+}
+
+/*
+ * set mach dependent process state for a new process
+ */
+void
+procsetup(Proc *p)
+{
+ p->fpstate = FPinit;
+}
+
+/*
+ * Save the mach dependent part of the process state.
+ */
+void
+procsave(Proc *p)
+{
+ USED(p);
+}
+
+/* place holder */
+/*
+ * dummy since rdb is not included
+ */
+void
+rdb(void)
+{
+}
+
+/*
+ * probe the last location in a meg of memory, make sure it's not
+ * reflected into something else we've already found.
+ */
+int
+probemem(ulong addr)
+{
+ int i;
+ ulong *p;
+ ulong a;
+
+ addr += OneMeg - sizeof(ulong);
+ p = (ulong*)addr;
+ *p = addr;
+ 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)
+ return -1;
+ return 0;
+}
+
+/*
+ * we assume that the kernel is at the beginning of one of the
+ * contiguous chunks of memory.
+ */
+void
+confinit(void)
+{
+ int i, j;
+ ulong addr;
+ ulong ktop;
+
+ /* find first two contiguous sections of available memory */
+ addr = PHYSDRAM0;
+ for(i=0; i<nelem(conf.mem); i++){
+ conf.mem[i].base = addr;
+ conf.mem[i].limit = addr;
+ }
+ 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;
+ }
+ }
+
+ 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;
+ }
+
+ if(conf.npage > 16*MB/BY2PG){
+ conf.upages = (conf.npage*60)/100;
+ imagmem->minarena = 4*1024*1024;
+ }else
+ conf.upages = (conf.npage*40)/100;
+ conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
+
+ /* only one processor */
+ conf.nmach = 1;
+
+ /* set up other configuration parameters */
+ conf.nproc = 100;
+ conf.nswap = conf.npage*3;
+ conf.nswppo = 4096;
+ conf.nimage = 200;
+
+ conf.monitor = 1;
+
+ conf.copymode = 0; /* copy on write */
+}
+
+GPIOregs *gpioregs;
+ulong *egpioreg = (ulong*)EGPIOREGS;
+PPCregs *ppcregs;
+MemConfRegs *memconfregs;
+PowerRegs *powerregs;
+ResetRegs *resetregs;
+
+/*
+ * configure the machine
+ */
+void
+machinit(void)
+{
+ /* set direction of SA1110 io pins and select alternate functions for some */
+ gpioregs = mapspecial(GPIOREGS, sizeof(GPIOregs));
+ gpioregs->direction =
+ GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
+ |GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o
+ |GPIO_CLK_SET0_o|GPIO_CLK_SET1_o
+ |GPIO_L3_SDA_io|GPIO_L3_MODE_o|GPIO_L3_SCLK_o
+ |GPIO_COM_RTS_o;
+ gpioregs->rising = 0;
+ gpioregs->falling = 0;
+ gpioregs->altfunc |=
+ GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
+ |GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o
+ |GPIO_SSP_CLK_i;
+
+ /* map in special H3650 io pins */
+ egpioreg = mapspecial(EGPIOREGS, sizeof(ulong));
+
+ /* map in peripheral pin controller (ssp will need it) */
+ ppcregs = mapspecial(PPCREGS, sizeof(PPCregs));
+
+ /* SA1110 power management */
+ powerregs = mapspecial(POWERREGS, sizeof(PowerRegs));
+
+ /* memory configuraton */
+ memconfregs = mapspecial(MEMCONFREGS, sizeof(MemConfRegs));
+
+ /* reset controller */
+ resetregs = mapspecial(RESETREGS, sizeof(ResetRegs));
+}
+
+
+/*
+ * manage egpio bits
+ */
+static ulong egpiosticky;
+
+void
+egpiobits(ulong bits, int on)
+{
+ if(on)
+ egpiosticky |= bits;
+ else
+ egpiosticky &= ~bits;
+ *egpioreg = egpiosticky;
+}
+
+void
+rs232power(int on)
+{
+ egpiobits(EGPIO_rs232_power, on);
+ delay(50);
+}
+
+void
+audioamppower(int on)
+{
+ egpiobits(EGPIO_audio_power, on);
+ delay(50);
+}
+
+void
+audioicpower(int on)
+{
+ egpiobits(EGPIO_audio_ic_power, on);
+ delay(50);
+}
+
+void
+irpower(int on)
+{
+ egpiobits(EGPIO_ir_power, on);
+ delay(50);
+}
+
+void
+lcdpower(int on)
+{
+ egpiobits(EGPIO_lcd_3v|EGPIO_lcd_ic_power|EGPIO_lcd_5v|EGPIO_lcd_9v, on);
+ delay(50);
+}
+
+void
+flashprogpower(int on)
+{
+ egpiobits(EGPIO_prog_flash, on);
+}
+
+/* here on hardware reset */
+void
+resettrap(void)
+{
+}
+
+/*
+ * for drivers that used to run on x86's
+ */
+void
+outb(ulong a, uchar v)
+{
+ *(uchar*)a = v;
+}
+void
+outs(ulong a, ushort v)
+{
+ *(ushort*)a = v;
+}
+void
+outss(ulong a, void *p, int n)
+{
+ ushort *sp = p;
+
+ while(n-- > 0)
+ *(ushort*)a = *sp++;
+}
+void
+outl(ulong a, ulong v)
+{
+ *(ulong*)a = v;
+}
+uchar
+inb(ulong a)
+{
+ return *(uchar*)a;
+}
+ushort
+ins(ulong a)
+{
+ return *(ushort*)a;
+}
+void
+inss(ulong a, void *p, int n)
+{
+ ushort *sp = p;
+
+ while(n-- > 0)
+ *sp++ = *(ushort*)a;
+}
+ulong
+inl(ulong a)
+{
+ return *(ulong*)a;
+}
+
+char*
+getconf(char*)
+{
+ return nil;
+}
+
+long
+_xdec(long *p)
+{
+ int s;
+ long v;
+
+ s = splhi();
+ v = --*p;
+ splx(s);
+ return v;
+}
+
+void
+_xinc(long *p)
+{
+ int s;
+
+ s = splhi();
+ ++*p;
+ splx(s);
+}
+
+int
+cmpswap(long *addr, long old, long new)
+{
+ int r, s;
+
+ s = splhi();
+ if(r = (*addr==old))
+ *addr = new;
+ splx(s);
+ return r;
+}
+
diff --git a/sys/src/9/bitsy/map b/sys/src/9/bitsy/map
new file mode 100755
index 000000000..87f67bece
--- /dev/null
+++ b/sys/src/9/bitsy/map
@@ -0,0 +1,10 @@
+defn acidmap()
+{
+ local dfoffset;
+
+ dfoffset = map()[1][3];
+ map({"text", _start, etext, 0x20});
+ map({"data", etext+1, edata, dfoffset});
+ print("Set map for plan 9 kernel image\n");
+ print("btext ", _start, " etext ", etext, "\n");
+}
diff --git a/sys/src/9/bitsy/mem.h b/sys/src/9/bitsy/mem.h
new file mode 100755
index 000000000..409f90c94
--- /dev/null
+++ b/sys/src/9/bitsy/mem.h
@@ -0,0 +1,236 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define BI2BY 8 /* bits per byte */
+#define BI2WD 32 /* bits per word */
+#define BY2WD 4 /* bytes per word */
+#define BY2V 8 /* bytes per double word */
+#define BY2PG 4096 /* bytes per page */
+#define WD2PG (BY2PG/BY2WD) /* words per page */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
+#define PGROUND(s) ROUND(s, BY2PG)
+#define BLOCKALIGN 8
+
+#define MAXMACH 1 /* max # cpus system can run */
+
+/*
+ * Time
+ */
+#define HZ (20) /* clock frequency */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+
+/*
+ * Virtual addresses:
+ *
+ * We direct map all discovered DRAM and the area twixt 0xe0000000 and
+ * 0xe8000000 used to provide zeros for cache flushing.
+ *
+ * Flash is mapped to 0xb0000000 and special registers are mapped
+ * on demand to areas starting at 0xa0000000.
+ *
+ * The direct mapping is convenient but not necessary. It means
+ * that we don't have to turn on the MMU till well into the
+ * kernel. This can be changed by providing a mapping in l.s
+ * before calling main.
+ */
+#define UZERO 0 /* base of user address space */
+#define UTZERO (UZERO+BY2PG) /* first address in user text */
+#define KZERO 0xC0000000 /* base of kernel address space */
+#define KTZERO 0xC0008000 /* first address in kernel text */
+#define EMEMZERO 0x90000000 /* 256 meg for add on memory */
+#define EMEMTOP 0xA0000000 /* ... */
+#define REGZERO 0xA0000000 /* 128 meg for mapspecial regs */
+#define REGTOP 0xA8000000 /* ... */
+#define FLASHZERO 0xB0000000 /* 128 meg for flash */
+#define FLASHTOP 0xB8000000 /* ... */
+#define DRAMZERO 0xC0000000 /* 128 meg for dram */
+#define DRAMTOP 0xC8000000 /* ... */
+#define UCDRAMZERO 0xC8000000 /* 128 meg for dram (uncached/unbuffered) */
+#define UCDRAMTOP 0xD0000000 /* ... */
+#define NULLZERO 0xE0000000 /* 128 meg for cache flush zeroes */
+#define NULLTOP 0xE8000000 /* ... */
+#define USTKTOP 0x2000000 /* byte just beyond user stack */
+#define USTKSIZE (8*1024*1024) /* size of user stack */
+#define TSTKTOP (USTKTOP-USTKSIZE) /* end of new stack in sysexec */
+#define TSTKSIZ 100
+#define MACHADDR (KZERO+0x00001000)
+#define EVECTORS 0xFFFF0000 /* virt base of exception vectors */
+
+#define KSTACK (16*1024) /* Size of kernel stack */
+
+/*
+ * Offsets into flash
+ */
+#define Flash_bootldr (FLASHZERO+0x0) /* boot loader */
+#define Flash_kernel (FLASHZERO+0x10000) /* boot kernel */
+#define Flash_tar (FLASHZERO+0x200000) /* fs.sac (tar file) */
+
+/*
+ * virtual MMU
+ */
+#define PTEMAPMEM (1024*1024)
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 1984
+#define SSEGMAPSIZE 16
+#define PPN(x) ((x)&~(BY2PG-1))
+
+/*
+ * SA1110 definitions
+ */
+
+/*
+ * memory physical addresses
+ */
+#define PHYSFLASH0 0x00000000
+#define PHYSDRAM0 0xC0000000
+#define PHYSNULL0 0xE0000000
+
+/*
+ * peripheral control module physical addresses
+ */
+#define USBREGS 0x80000000 /* serial port 0 - USB */
+#define UART1REGS 0x80010000 /* serial port 1 - UART */
+#define GPCLKREGS 0x80020060 /* serial port 1 - general purpose clock */
+#define UART2REGS 0x80030000 /* serial port 2 - low speed IR */
+#define HSSPREGS 0x80040060 /* serial port 2 - high speed IR */
+#define UART3REGS 0x80050000 /* serial port 3 - RS232 UART */
+#define MCPREGS 0x80060000 /* serial port 4 - multimedia comm port */
+#define SSPREGS 0x80070060 /* serial port 4 - synchronous serial port */
+#define OSTIMERREGS 0x90000000 /* operating system timer registers */
+#define POWERREGS 0x90020000 /* power management */
+#define RESETREGS 0x90030000 /* reset controller */
+#define GPIOREGS 0x90040000 /* 28 general purpose IO pins */
+#define INTRREGS 0x90050000 /* interrupt registers */
+#define PPCREGS 0x90060000 /* peripheral pin controller */
+#define MEMCONFREGS 0xA0000000 /* memory configuration */
+#define LCDREGS 0xB0100000 /* display */
+
+/*
+ * PCMCIA addresses
+ */
+#define PHYSPCM0REGS 0x20000000
+#define PYHSPCM0ATTR 0x28000000
+#define PYHSPCM0MEM 0x2C000000
+#define PHYSPCM1REGS 0x30000000
+#define PYHSPCM1ATTR 0x38000000
+#define PYHSPCM1MEM 0x3C000000
+
+/*
+ * Program Status Registers
+ */
+#define PsrMusr 0x00000010 /* mode */
+#define PsrMfiq 0x00000011
+#define PsrMirq 0x00000012
+#define PsrMsvc 0x00000013
+#define PsrMabt 0x00000017
+#define PsrMund 0x0000001B
+#define PsrMask 0x0000001F
+
+#define PsrDfiq 0x00000040 /* disable FIQ interrupts */
+#define PsrDirq 0x00000080 /* disable IRQ interrupts */
+
+#define PsrV 0x10000000 /* overflow */
+#define PsrC 0x20000000 /* carry/borrow/extend */
+#define PsrZ 0x40000000 /* zero */
+#define PsrN 0x80000000 /* negative/less than */
+
+/*
+ * Coprocessors
+ */
+#define CpMMU 15
+#define CpPWR 15
+
+/*
+ * Internal MMU coprocessor registers
+ */
+#define CpCPUID 0 /* R: */
+#define CpControl 1 /* RW: */
+#define CpTTB 2 /* RW: translation table base */
+#define CpDAC 3 /* RW: domain access control */
+#define CpFSR 5 /* RW: fault status */
+#define CpFAR 6 /* RW: fault address */
+#define CpCacheFlush 7 /* W: cache flushing, wb draining*/
+#define CpTLBFlush 8 /* W: TLB flushing */
+#define CpRBFlush 9 /* W: Read Buffer ops */
+#define CpPID 13 /* RW: PID for virtual mapping */
+#define CpBpt 14 /* W: Breakpoint register */
+#define CpTest 15 /* W: Test, Clock and Idle Control */
+
+/*
+ * CpControl
+ */
+#define CpCmmuena 0x00000001 /* M: MMU enable */
+#define CpCalign 0x00000002 /* A: alignment fault enable */
+#define CpCdcache 0x00000004 /* C: data cache on */
+#define CpCwb 0x00000008 /* W: write buffer turned on */
+#define CpCi32 0x00000010 /* P: 32-bit program space */
+#define CpCd32 0x00000020 /* D: 32-bit data space */
+#define CpCbe 0x00000080 /* B: big-endian operation */
+#define CpCsystem 0x00000100 /* S: system permission */
+#define CpCrom 0x00000200 /* R: ROM permission */
+#define CpCicache 0x00001000 /* I: instruction cache on */
+#define CpCvivec 0x00002000 /* X: virtual interrupt vector adjust */
+
+/*
+ * fault codes
+ */
+#define FCterm 0x2 /* terminal */
+#define FCvec 0x0 /* vector */
+#define FCalignf 0x1 /* unaligned full word data access */
+#define FCalignh 0x3 /* unaligned half word data access */
+#define FCl1abort 0xc /* level 1 external abort on translation */
+#define FCl2abort 0xe /* level 2 external abort on translation */
+#define FCtransSec 0x5 /* section translation */
+#define FCtransPage 0x7 /* page translation */
+#define FCdomainSec 0x9 /* section domain */
+#define FCdomainPage 0x11 /* page domain */
+#define FCpermSec 0x9 /* section permissions */
+#define FCpermPage 0x11 /* page permissions */
+#define FCabortLFSec 0x4 /* external abort on linefetch for section */
+#define FCabortLFPage 0x6 /* external abort on linefetch for page */
+#define FCabortNLFSec 0x8 /* external abort on non-linefetch for section */
+#define FCabortNLFPage 0xa /* external abort on non-linefetch for page */
+
+/*
+ * PTE bits used by fault.h. mmu.c translates them to real values.
+ */
+#define PTEVALID (1<<0)
+#define PTERONLY 0 /* this is implied by the absence of PTEWRITE */
+#define PTEWRITE (1<<1)
+#define PTEUNCACHED (1<<2)
+#define PTEKERNEL (1<<3) /* no user access */
+
+/*
+ * H3650 specific definitions
+ */
+#define EGPIOREGS 0x49000000 /* Additional GPIO register */
+
+/* Power management */
+
+#define PWR_rtc 0x80000000 /* resume on RTC */
+#define PWR_gpio0 0x00000001 /* resume on power button */
+
+#define RCSR_all 0x0000000f
+#define PCFR_opde 0x00000001 /* oscillator power-down enable */
+#define PCFR_suspend 0x00000001
+#define PCFR_fp 0x00000002 /* float pcmcia */
+#define PCFR_fs 0x00000004 /* float static memory */
+#define PCFR_fo 0x00000008
+
+#define MDREFR_k1db2 (1 << 22)
+#define MDREFR_slfrsh 0x80000000 /* self refresh */
+#define MDREFR_e1pin (1 << 20)
+#define MSC_rt 0x00030003
+
+#define MDCNFG_de0 0x00000001 /* dram enable */
+#define MDCNFG_de1 0x00000002
+#define MDCNFG_de2 0x00000004
+#define MDCNFG_de3 0x00000008
+#define MDCFNG_de 0x0000000f
+#define PMCR_sf 1
diff --git a/sys/src/9/bitsy/mkfile b/sys/src/9/bitsy/mkfile
new file mode 100755
index 000000000..9fde07deb
--- /dev/null
+++ b/sys/src/9/bitsy/mkfile
@@ -0,0 +1,140 @@
+CONF=bitsy
+CONFLIST=bitsy
+
+objtype=arm
+</$objtype/mkfile
+p=9
+
+DEVS=`{rc ../port/mkdevlist $CONF}
+
+PORT=\
+ alarm.$O\
+ alloc.$O\
+ allocb.$O\
+ auth.$O\
+ cache.$O\
+ chan.$O\
+ dev.$O\
+ edf.$O\
+ fault.$O\
+ latin1.$O\
+ mul64fract.$O\
+ rebootcmd.$O\
+ page.$O\
+ parse.$O\
+ pgrp.$O\
+ portclock.$O\
+ print.$O\
+ proc.$O\
+ qio.$O\
+ qlock.$O\
+ segment.$O\
+ swap.$O\
+ sysfile.$O\
+ sysproc.$O\
+ taslock.$O\
+ tod.$O\
+ xalloc.$O\
+
+OBJ=\
+ l.$O\
+ clock.$O\
+ defont.$O\
+ fpi.$O\
+ fpiarm.$O\
+ fpimem.$O\
+ main.$O\
+ mmu.$O\
+ power.$O\
+ random.$O\
+ sa1110dma.$O\
+ screen.$O\
+ trap.$O\
+ $CONF.root.$O\
+ $CONF.rootc.$O\
+ $DEVS\
+ $PORT\
+
+LIB=\
+ /$objtype/lib/libmemlayer.a\
+ /$objtype/lib/libmemdraw.a\
+ /$objtype/lib/libdraw.a\
+ /$objtype/lib/libip.a\
+ /$objtype/lib/libc.a\
+ /$objtype/lib/libsec.a\
+ /$objtype/lib/libip.a\
+
+size:VQ: $p$CONF
+ ls -l $p$CONF|sed 's/^[^ ]+ [^ ]+ [^ ]+ [^ ]+ [^ ]+ ([^ ]+).*/load ram 0xc0008000 \1/'
+ echo load kernel
+ echo !xms /sys/src/9/bitsy/^$p$CONF
+ echo jump 0xc0008010
+
+acid:VQ:
+ echo acid -lmap s9bitsy
+
+$p$CONF: $OBJ $CONF.c $LIB /arm/inflate
+ $CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
+ $LD -o $target -H5 -R4 -T0xC0008010 -l $OBJ $CONF.$O $LIB
+ $LD -o s$target -R4 -T0xC0008010 -l $OBJ $CONF.$O $LIB
+ gzip $target
+ cat /arm/inflate $target.gz > $target
+ echo the boot loader misses the last 12 bytes >> $target
+ rm $target.gz
+
+install:V: $p$CONF paqdisk
+ if(test -d /n/once/arm){
+ cp $p$CONF /n/once/arm/$p$CONF
+ cp s$p$CONF /n/once/arm/s$p$CONF
+ cp paqdisk /n/once/arm/paqdisk
+ }
+ if not
+ status=''
+ # 9fs lookout && cp $p$CONF /n/lookout/$objtype/$p$CONF
+
+installkern:V: $p$CONF
+ cp $p$CONF /$objtype/$p$CONF
+ cp s$p$CONF /$objtype/s$p$CONF
+
+<../boot/bootmkfile
+<../port/portmkfile
+<|../port/mkbootrules $CONF
+
+init.h:D: ../port/initcode.c init9.s
+ $CC ../port/initcode.c
+ $AS init9.s
+ $LD -l -R1 -s -o init.out init9.$O initcode.$O /arm/lib/libc.a
+ {echo 'uchar initcode[]={'
+ xd -1x <init.out |
+ sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+ echo '};'} > init.h
+
+clock.$O: /$objtype/include/ureg.h
+devether.$O: /$objtype/include/ureg.h ../port/netif.h
+devpcmcia.$O: /$objtype/include/ureg.h
+fpi.$O: fpi.h
+fpiarm.$O: /$objtype/include/ureg.h fpi.h
+fpimem.$O: fpi.h
+main.$O: /$objtype/include/ureg.h errstr.h init.h
+mmu.$O: /$objtype/include/ureg.h
+power.$O: /$objtype/include/ureg.h
+scu.$O: /$objtype/include/ureg.h
+sa1110dma.$O: /$objtype/include/ureg.h
+screen.$O: gamma.h
+sdata.$O: /$objtype/include/ureg.h
+trap$O: /$objtype/include/ureg.h
+wavelan.$O: /$objtype/include/ureg.h wavelan.c wavelan.h ../pc/wavelan.h
+
+paqdisk:V:
+ rm -fr armpaq
+ mkdir armpaq
+ cd armpaq
+ disk/mkfs -d . /sys/lib/sysconfig/proto/armpaqproto
+ mkpaqfs -o ../paqdisk
+ cd ..
+ echo load ramdisk
+ echo !xms /sys/src/9/bitsy/paqdisk
+
+bitsy.clean:
+ rm -rf armpaq $p$CONF s$p$CONF paqdisk $CONF.c boot$CONF.c ../boot/libboot.a5
+
diff --git a/sys/src/9/bitsy/mmu.c b/sys/src/9/bitsy/mmu.c
new file mode 100755
index 000000000..ba89a6b13
--- /dev/null
+++ b/sys/src/9/bitsy/mmu.c
@@ -0,0 +1,533 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+/*
+ * to avoid mmu and cash flushing, we use the pid register in the MMU
+ * to map all user addresses. Although there are 64 possible pids, we
+ * can only use 31 because there are only 32 protection domains and we
+ * need one for the kernel. Pid i is thus associated with domain i.
+ * Domain 0 is used for the kernel.
+ */
+
+/* real protection bits */
+enum
+{
+ /* level 1 descriptor bits */
+ L1TypeMask= (3<<0),
+ L1Invalid= (0<<0),
+ L1PageTable= (1<<0),
+ L1Section= (2<<0),
+ L1Cached= (1<<3),
+ L1Buffered= (1<<2),
+ L1DomShift= 5,
+ L1Domain0= (0<<L1DomShift),
+ L1KernelRO= (0x0<<10),
+ L1KernelRW= (0x1<<10),
+ L1UserRO= (0x2<<10),
+ L1UserRW= (0x3<<10),
+ L1SectBaseMask= (0xFFF<<20),
+ L1PTBaseMask= (0x3FFFFF<<10),
+
+ /* level 2 descriptor bits */
+ L2TypeMask= (3<<0),
+ L2SmallPage= (2<<0),
+ L2LargePage= (1<<0),
+ L2Cached= (1<<3),
+ L2Buffered= (1<<2),
+ L2KernelRW= (0x55<<4),
+ L2UserRO= (0xAA<<4),
+ L2UserRW= (0xFF<<4),
+ L2PageBaseMask= (0xFFFFF<<12),
+
+ /* domain values */
+ Dnoaccess= 0,
+ Dclient= 1,
+ Dmanager= 3,
+};
+
+ulong *l1table;
+static int mmuinited;
+
+/*
+ * We map all of memory, flash, and the zeros area with sections.
+ * Special use space is mapped on the fly with regmap.
+ */
+void
+mmuinit(void)
+{
+ ulong a, o;
+ ulong *t;
+
+ /* get a prototype level 1 page */
+ l1table = xspanalloc(16*1024, 16*1024, 0);
+ memset(l1table, 0, 16*1024);
+
+ /* map low mem (I really don't know why I have to do this -- presotto) */
+ for(o = 0; o < 1*OneMeg; o += OneMeg)
+ l1table[(0+o)>>20] = L1Section | L1KernelRW| L1Domain0
+ | L1Cached | L1Buffered
+ | ((0+o)&L1SectBaseMask);
+
+ /* map DRAM */
+ for(o = 0; o < DRAMTOP-DRAMZERO; o += OneMeg)
+ l1table[(DRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0
+ | L1Cached | L1Buffered
+ | ((PHYSDRAM0+o)&L1SectBaseMask);
+
+ /* uncached DRAM */
+ for(o = 0; o < UCDRAMTOP-UCDRAMZERO; o += OneMeg)
+ l1table[(UCDRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0
+ | ((PHYSDRAM0+o)&L1SectBaseMask);
+
+ /* map zeros area */
+ for(o = 0; o < NULLTOP-NULLZERO; o += OneMeg)
+ l1table[(NULLZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0
+ | L1Cached | L1Buffered
+ | ((PHYSNULL0+o)&L1SectBaseMask);
+
+ /* map flash */
+ for(o = 0; o < FLASHTOP-FLASHZERO; o += OneMeg)
+ l1table[(FLASHZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0
+ | ((PHYSFLASH0+o)&L1SectBaseMask);
+
+ /* map peripheral control module regs */
+ mapspecial(0x80000000, OneMeg);
+
+ /* map system control module regs */
+ mapspecial(0x90000000, OneMeg);
+
+ /*
+ * double map start of ram to exception vectors
+ */
+ a = EVECTORS;
+ t = xspanalloc(BY2PG, 1024, 0);
+ memset(t, 0, BY2PG);
+ l1table[a>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask);
+ t[(a&0xfffff)>>PGSHIFT] = L2SmallPage | L2KernelRW | (PHYSDRAM0 & L2PageBaseMask);
+
+ mmurestart();
+
+ mmuinited = 1;
+}
+
+void
+mmurestart(void) {
+ /* set up the domain register to cause all domains to obey pte access bits */
+
+ putdac(Dclient);
+
+ /* point to map */
+ putttb((ulong)l1table);
+
+ /* enable mmu */
+ wbflush();
+ mmuinvalidate();
+ mmuenable();
+ cacheflush();
+}
+
+/*
+ * map on request
+ */
+static void*
+_map(ulong pa, int len, ulong zero, ulong top, ulong l1prop, ulong l2prop)
+{
+ ulong *t;
+ ulong va, i, base, end, off, entry;
+ int large;
+ ulong* rv;
+
+ rv = nil;
+ large = len >= 128*1024;
+ if(large){
+ base = pa & ~(OneMeg-1);
+ end = (pa+len-1) & ~(OneMeg-1);
+ } else {
+ base = pa & ~(BY2PG-1);
+ end = (pa+len-1) & ~(BY2PG-1);
+ }
+ off = pa - base;
+
+ for(va = zero; va < top && base <= end; va += OneMeg){
+ switch(l1table[va>>20] & L1TypeMask){
+ default:
+ /* found unused entry on level 1 table */
+ if(large){
+ if(rv == nil)
+ rv = (ulong*)(va+off);
+ l1table[va>>20] = L1Section | l1prop | L1Domain0 |
+ (base & L1SectBaseMask);
+ base += OneMeg;
+ continue;
+ } else {
+
+ /* create an L2 page table and keep going */
+ t = xspanalloc(BY2PG, 1024, 0);
+ memset(t, 0, BY2PG);
+ l1table[va>>20] = L1PageTable | L1Domain0 |
+ (((ulong)t) & L1PTBaseMask);
+ }
+ break;
+ case L1Section:
+ /* if it's already mapped in a one meg area, don't remap */
+ entry = l1table[va>>20];
+ i = entry & L1SectBaseMask;
+ if(pa >= i && (pa+len) <= i + OneMeg)
+ if((entry & ~L1SectBaseMask) == (L1Section | l1prop | L1Domain0))
+ return (void*)(va + (pa & (OneMeg-1)));
+
+ continue;
+ case L1PageTable:
+ if(large)
+ continue;
+ break;
+ }
+
+ /* here if we're using page maps instead of sections */
+ t = (ulong*)(l1table[va>>20] & L1PTBaseMask);
+ for(i = 0; i < OneMeg && base <= end; i += BY2PG){
+ entry = t[i>>PGSHIFT];
+
+ /* found unused entry on level 2 table */
+ if((entry & L2TypeMask) != L2SmallPage){
+ if(rv == nil)
+ rv = (ulong*)(va+i+off);
+ t[i>>PGSHIFT] = L2SmallPage | l2prop |
+ (base & L2PageBaseMask);
+ base += BY2PG;
+ continue;
+ }
+ }
+ }
+
+ /* didn't fit */
+ if(base <= end)
+ return nil;
+ cacheflush();
+
+ return rv;
+}
+
+/* map in i/o registers */
+void*
+mapspecial(ulong pa, int len)
+{
+ return _map(pa, len, REGZERO, REGTOP, L1KernelRW, L2KernelRW);
+}
+
+/* map add on memory */
+void*
+mapmem(ulong pa, int len, int cached)
+{
+ ulong l1, l2;
+
+ if(cached){
+ l1 = L1KernelRW|L1Cached|L1Buffered;
+ l2 = L2KernelRW|L2Cached|L2Buffered;
+ } else {
+ l1 = L1KernelRW;
+ l2 = L2KernelRW;
+ }
+ return _map(pa, len, EMEMZERO, EMEMTOP, l1, l2);
+}
+
+/* map a virtual address to a physical one */
+ulong
+mmu_paddr(ulong va)
+{
+ ulong entry;
+ ulong *t;
+
+ entry = l1table[va>>20];
+ switch(entry & L1TypeMask){
+ case L1Section:
+ return (entry & L1SectBaseMask) | (va & (OneMeg-1));
+ case L1PageTable:
+ t = (ulong*)(entry & L1PTBaseMask);
+ va &= OneMeg-1;
+ entry = t[va>>PGSHIFT];
+ switch(entry & L1TypeMask){
+ case L2SmallPage:
+ return (entry & L2PageBaseMask) | (va & (BY2PG-1));
+ }
+ }
+ return 0;
+}
+
+/* map a physical address to a virtual one */
+ulong
+findva(ulong pa, ulong zero, ulong top)
+{
+ int i;
+ ulong entry, va;
+ ulong start, end;
+ ulong *t;
+
+ for(va = zero; va < top; va += OneMeg){
+ /* search the L1 entry */
+ entry = l1table[va>>20];
+ switch(entry & L1TypeMask){
+ default:
+ return 0; /* no holes */
+ case L1Section:
+ start = entry & L1SectBaseMask;
+ end = start + OneMeg;
+ if(pa >= start && pa < end)
+ return va | (pa & (OneMeg-1));
+ continue;
+ case L1PageTable:
+ break;
+ }
+
+ /* search the L2 entry */
+ t = (ulong*)(l1table[va>>20] & L1PTBaseMask);
+ for(i = 0; i < OneMeg; i += BY2PG){
+ entry = t[i>>PGSHIFT];
+
+ /* found unused entry on level 2 table */
+ if((entry & L2TypeMask) != L2SmallPage)
+ break;
+
+ start = entry & L2PageBaseMask;
+ end = start + BY2PG;
+ if(pa >= start && pa < end)
+ return va | (BY2PG*i) | (pa & (BY2PG-1));
+ }
+ }
+ return 0;
+}
+ulong
+mmu_kaddr(ulong pa)
+{
+ ulong va;
+
+ /* try the easy stuff first (the first case is true most of the time) */
+ if(pa >= PHYSDRAM0 && pa <= PHYSDRAM0+(DRAMTOP-DRAMZERO))
+ return DRAMZERO+(pa-PHYSDRAM0);
+ if(pa >= PHYSFLASH0 && pa <= PHYSFLASH0+(FLASHTOP-FLASHZERO))
+ return FLASHZERO+(pa-PHYSFLASH0);
+ if(pa >= PHYSNULL0 && pa <= PHYSNULL0+(NULLTOP-NULLZERO))
+ return NULLZERO+(pa-PHYSNULL0);
+
+ if(!mmuinited)
+ return 0; /* this shouldn't happen */
+
+ /* walk the map for the special regs and extended memory */
+ va = findva(pa, EMEMZERO, EMEMTOP);
+ if(va != 0)
+ return va;
+ return findva(pa, REGZERO, REGTOP);
+}
+
+/*
+ * Return the number of bytes that can be accessed via KADDR(pa).
+ * If pa is not a valid argument to KADDR, return 0.
+ */
+ulong
+cankaddr(ulong pa)
+{
+ /*
+ * Is this enough?
+ * We'll find out if anyone still has one
+ * of these...
+ */
+ if(pa >= PHYSDRAM0 && pa <= PHYSDRAM0+(DRAMTOP-DRAMZERO))
+ return PHYSDRAM0+(DRAMTOP-DRAMZERO) - pa;
+ return 0;
+}
+
+/*
+ * table to map fault.c bits to physical bits
+ */
+static ulong mmubits[16] =
+{
+ [PTEVALID] L2SmallPage|L2Cached|L2Buffered|L2UserRO,
+ [PTEVALID|PTEWRITE] L2SmallPage|L2Cached|L2Buffered|L2UserRW,
+ [PTEVALID|PTEUNCACHED] L2SmallPage|L2UserRO,
+ [PTEVALID|PTEUNCACHED|PTEWRITE] L2SmallPage|L2UserRW,
+
+ [PTEKERNEL|PTEVALID] L2SmallPage|L2Cached|L2Buffered|L2KernelRW,
+ [PTEKERNEL|PTEVALID|PTEWRITE] L2SmallPage|L2Cached|L2Buffered|L2KernelRW,
+ [PTEKERNEL|PTEVALID|PTEUNCACHED] L2SmallPage|L2KernelRW,
+ [PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE] L2SmallPage|L2KernelRW,
+};
+
+/*
+ * add an entry to the current map
+ */
+void
+putmmu(ulong va, ulong pa, Page *pg)
+{
+ Page *l2pg;
+ ulong *t, *l1p, *l2p;
+ int s;
+
+ s = splhi();
+
+ /* clear out the current entry */
+ mmuinvalidateaddr(va);
+
+ l2pg = up->l1page[va>>20];
+ if(l2pg == nil){
+ l2pg = up->mmufree;
+ if(l2pg != nil){
+ up->mmufree = l2pg->next;
+ } else {
+ l2pg = auxpage();
+ if(l2pg == nil)
+ pexit("out of memory", 1);
+ }
+ l2pg->va = VA(kmap(l2pg));
+ up->l1page[va>>20] = l2pg;
+ memset((uchar*)(l2pg->va), 0, BY2PG);
+ }
+
+ /* always point L1 entry to L2 page, can't hurt */
+ l1p = &l1table[va>>20];
+ *l1p = L1PageTable | L1Domain0 | (l2pg->pa & L1PTBaseMask);
+ up->l1table[va>>20] = *l1p;
+ t = (ulong*)l2pg->va;
+
+ /* set L2 entry */
+ l2p = &t[(va & (OneMeg-1))>>PGSHIFT];
+ *l2p = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)]
+ | (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE));
+
+ /* write back dirty entries - we need this because the pio() in
+ * fault.c is writing via a different virt addr and won't clean
+ * its changes out of the dcache. Page coloring doesn't work
+ * on this mmu because the virtual cache is set associative
+ * rather than direct mapped.
+ */
+ cachewb();
+ if(pg->cachectl[0] == PG_TXTFLUSH){
+ /* pio() sets PG_TXTFLUSH whenever a text page has been written */
+ icacheinvalidate();
+ pg->cachectl[0] = PG_NOFLUSH;
+ }
+
+ splx(s);
+}
+
+/*
+ * free up all page tables for this proc
+ */
+void
+mmuptefree(Proc *p)
+{
+ Page *pg;
+ int i;
+
+ for(i = 0; i < Nmeg; i++){
+ pg = p->l1page[i];
+ if(pg == nil)
+ continue;
+ p->l1page[i] = nil;
+ pg->next = p->mmufree;
+ p->mmufree = pg;
+ }
+ memset(p->l1table, 0, sizeof(p->l1table));
+}
+
+/*
+ * this is called with palloc locked so the pagechainhead is kosher
+ */
+void
+mmurelease(Proc* p)
+{
+ Page *pg, *next;
+
+ /* write back dirty cache entries before changing map */
+ cacheflush();
+
+ mmuptefree(p);
+
+ for(pg = p->mmufree; pg; pg = next){
+ next = pg->next;
+ if(--pg->ref)
+ panic("mmurelease: pg->ref %d\n", pg->ref);
+ pagechainhead(pg);
+ }
+ if(p->mmufree && palloc.r.p)
+ wakeup(&palloc.r);
+ p->mmufree = nil;
+
+ memset(l1table, 0, sizeof(p->l1table));
+ cachewbregion((ulong)l1table, sizeof(p->l1table));
+}
+
+void
+mmuswitch(Proc *p)
+{
+ if(m->mmupid == p->pid && p->newtlb == 0)
+ return;
+ m->mmupid = p->pid;
+
+ /* write back dirty cache entries and invalidate all cache entries */
+ cacheflush();
+
+ if(p->newtlb){
+ mmuptefree(p);
+ p->newtlb = 0;
+ }
+
+ /* move in new map */
+ memmove(l1table, p->l1table, sizeof(p->l1table));
+
+ /* make sure map is in memory */
+ cachewbregion((ulong)l1table, sizeof(p->l1table));
+
+ /* lose any possible stale tlb entries */
+ mmuinvalidate();
+}
+
+void
+flushmmu(void)
+{
+ int s;
+
+ s = splhi();
+ up->newtlb = 1;
+ mmuswitch(up);
+ splx(s);
+}
+
+void
+peekmmu(ulong va)
+{
+ ulong e, d;
+
+ e = l1table[va>>20];
+ switch(e & L1TypeMask){
+ default:
+ iprint("l1: %#p[%#lux] = %#lux invalid\n", l1table, va>>20, e);
+ break;
+ case L1PageTable:
+ iprint("l1: %#p[%#lux] = %#lux pt\n", l1table, va>>20, e);
+ va &= OneMeg-1;
+ va >>= PGSHIFT;
+ e &= L1PTBaseMask;
+ d = ((ulong*)e)[va];
+ iprint("l2: %#lux[%#lux] = %#lux\n", e, va, d);
+ break;
+ case L1Section:
+ iprint("l1: %#p[%#lux] = %#lux section\n", l1table, va>>20, e);
+ break;
+ }
+}
+
+void
+checkmmu(ulong, ulong)
+{
+}
+
+void
+countpagerefs(ulong*, int)
+{
+}
diff --git a/sys/src/9/bitsy/mouse.c b/sys/src/9/bitsy/mouse.c
new file mode 100755
index 000000000..f26607022
--- /dev/null
+++ b/sys/src/9/bitsy/mouse.c
@@ -0,0 +1,63 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+enum {
+ Button1 = 0x1;
+ Button2 = 0x2;
+ Button3 = 0x4;
+};
+
+int buttons;
+Point position;
+
+static void
+mousevent(void) {
+ static int curbuttons;
+ static Point curposition;
+
+ if (buttons == curbuttons && eqpt(position, curposition))
+ return;
+
+ /* generate a mouse event */
+ curbuttons = buttons;
+ curposition = position;
+}
+
+void
+buttonevent(int event) {
+ switch (event) {
+ case 0x02:
+ /* Button 2 down */
+ buttons |= Button2;
+ mousevent();
+ break;
+ case 0x82:
+ /* Button 2 up */
+ buttons &= ~Button2;
+ mousevent();
+ break;
+ case 0x03:
+ /* Button 3 down */
+ buttons |= Button3;
+ mousevent();
+ break;
+ case 0x83:
+ /* Button 3 up */
+ buttons &= ~Button3;
+ mousevent();
+ break;
+ default:
+ /* other buttons */
+ }
+}
diff --git a/sys/src/9/bitsy/paqfiles/cpurc b/sys/src/9/bitsy/paqfiles/cpurc
new file mode 100755
index 000000000..fcc6da2d9
--- /dev/null
+++ b/sys/src/9/bitsy/paqfiles/cpurc
@@ -0,0 +1,175 @@
+#!/bin/rc
+
+debug=0
+
+#set service to terminal (necessary for factotum, handy for everything else)
+service=terminal
+
+echo -n terminal > /env/service
+echo -n plan9 > /env/site
+echo -n astro > /env/facedom
+echo -n emelie > /env/fs
+
+bind -a '#y' /dev
+bind -a '#F' /dev
+bind -a '#I' /net
+bind -a '#D' /net
+
+# parallelism for mk
+NPROC=1
+
+sysname=`{cat /dev/sysname}
+if (~ $sysname ''){
+ sysname=bitsy
+ echo $sysname>/dev/sysname
+}
+prompt=($sysname^'# ' ' ')
+
+# flavor
+fileserver=emelie
+cpu=olive
+
+# user defined flash partitions
+echo -n add fs 0x0800000 0x1000000 > /dev/flash/flashctl
+
+# so we can see things
+light 0
+
+# set variables
+if(~ $debug 1) echo ramfs
+ramfs
+if(~ $debug 1) echo pencal
+params -f
+if(! grep -s '^calibrate=' /tmp/tmpparams)
+ pencal >>/tmp/tmpparams
+if not {
+ eval `{grep '^calibrate=' /tmp/tmpparams}
+ echo calibrate $calibrate > '#m/mousectl'
+}
+prompter /tmp/tmpparams
+params
+if(~ $debug 1) {
+ echo tmpparams:
+ cat /tmp/tmpparams
+}
+. /tmp/tmpparams
+
+if(~ $debug 1) echo set user
+# set userid
+if(test -e /env/user){
+ echo -n $user > /dev/hostowner
+}
+
+if(~ $debug 1) echo start flashfs
+# bind in read/write file system
+if (aux/flashfs) {
+ if (~ $debug 1) echo flashfs started
+ mount /srv/brzr /n/tmp
+ bind -a /n /n/tmp/n
+ bind -a /sys/lib /n/tmp/sys/lib
+ bind -a /sys /n/tmp/sys
+ bind -a /arm/bin/auth /n/tmp/arm/bin/auth
+ bind -a /arm/bin/ndb /n/tmp/arm/bin/ndb
+ bind -a /arm/bin/ip /n/tmp/arm/bin/ip
+ bind -a /arm/bin/aux /n/tmp/arm/bin/aux
+ bind -a /arm/bin /n/tmp/arm/bin
+ bind -a /arm /n/tmp/arm
+ bind -a /lib/ndb /n/tmp/lib/ndb
+ bind -a /lib/font /n/tmp/lib/font
+ bind -a /lib /n/tmp/lib
+ bind -a / /n/tmp
+ bind /n/tmp /
+ unmount /n/tmp
+} >[2] /dev/null
+
+# start network
+if(grep -s WaveLAN/IEEE /dev/pcm0ctl){
+ if (~ $debug 1) echo 'configure #l0 wavelan'
+ echo -n 'configure #l0 wavelan'>/dev/pcm0ctl
+ bind -a '#l0' /net
+ switch($wvkey1){
+ case ''
+ ;
+ case *
+ echo -n 'key1 '^$wvkey1 >/net/ether0/clone
+ }
+ switch($wvkey2){
+ case ''
+ ;
+ case *
+ echo -n 'key2 '^$wvkey2 >/net/ether0/clone
+ }
+ switch($wvkey3){
+ case ''
+ ;
+ case *
+ echo -n 'key3 '^$wvkey3 >/net/ether0/clone
+ }
+ switch($wvtxkey){
+ case ''
+ ;
+ case *
+ echo -n 'txkey '^$wvtxkey >/net/ether0/clone
+ }
+ switch($wvmode){
+ case ''
+ ;
+ case *
+ echo -n 'mode '^$wvmode >/net/ether0/clone
+ }
+ switch($wvibss){
+ case ''
+ ;
+ case *
+ echo -n 'ibss '^$wvibss >/net/ether0/clone
+ }
+ switch($wvessid){
+ case ''
+ ;
+ case *
+ echo -n 'essid '^$wvessid >/net/ether0/clone
+ }
+ switch($wvcrypt){
+ case ''
+ ;
+ case *
+ echo -n 'crypt '^$wvcrypt >/net/ether0/clone
+ }
+ if (~ $debug 1) echo ip/ipconfig ether /net/ether0 $ipaddr $ipmask
+ ip/ipconfig ether /net/ether0 $ipaddr $ipmask
+ if(test -e /env/auth)
+ echo ' auth='^$auth >>/net/ndb
+ if(test -e /env/dns)
+ echo ' dns='^$dns >>/net/ndb
+ if(test -e /env/dnsdomain)
+ echo ' dnsdomain='^$dnsdomain >>/net/ndb
+ if(test -e /env/authdom)
+ echo ' authdom='^$authdom >>/net/ndb
+
+ if (~ $debug 1) echo ndb/cs
+ ndb/cs
+ ndb/dns -r
+}
+
+auth/factotum -n -s factotum -a $auth
+
+if(! test -e /env/font)
+ font=/lib/font/bit/lucidasans/unicode.6.font
+if(! test -e /env/tabstop)
+ tabstop=2
+
+if (test -d /usr/$user) {
+ home=/usr/$user
+ cd $home
+ if (test -r lib/profile) {
+ . lib/profile
+ exec /bin/rc
+ }
+ if (test -r lib/windows) {
+ if (~ $debug 1) echo 'exec rio -sk ''/bin/keyboard -l'' -i '$home'/lib/windows'
+ exec rio -sk '/bin/keyboard -l -w' -i $home/lib/windows
+ }
+}
+# bind in read/write file system
+if (~ $debug 1) echo 'exec rio -sk ''/bin/keyboard -l'''
+exec rio -sk '/bin/keyboard -l -w'
diff --git a/sys/src/9/bitsy/paqfiles/local b/sys/src/9/bitsy/paqfiles/local
new file mode 100755
index 000000000..d00bea6a1
--- /dev/null
+++ b/sys/src/9/bitsy/paqfiles/local
@@ -0,0 +1,6 @@
+#
+# files comprising the database
+#
+database=
+ file=/lib/ndb/local
+ file=/lib/ndb/common
diff --git a/sys/src/9/bitsy/paqfiles/mfs b/sys/src/9/bitsy/paqfiles/mfs
new file mode 100755
index 000000000..77441459e
--- /dev/null
+++ b/sys/src/9/bitsy/paqfiles/mfs
@@ -0,0 +1,41 @@
+#!/bin/rc
+
+# $proxy is typically set to tailfan's address.
+ipnet=`{grep 'ip=' /net/ndb | sed 's/^.*ip=([0-9]+\.[0-9]+\.[0-9]+\.).*$/\1/'}
+if (~ $proxy $ipnet^*){
+ # Use a proxy
+ echo import $proxy /net /net
+ import $proxy /net /net
+}
+
+switch($fs){
+case ''
+ echo you must set the environment variable fs
+ exit 0
+}
+if (! test -e /mnt/factotum) {
+ if (test -e /srv/factotum) {
+ mount -b /srv/factotum /mnt
+ }
+ if not {
+ auth/factotum -u
+ }
+}
+srv -m $fs $fs /n/fs
+bind -b /n/fs/arm/bin /bin
+bind -b /n/fs/rc/bin /bin
+bind -a /n/fs/lib /lib
+bind -b /n/fs/sys /sys
+bind -a /n/fs/usr /usr
+bind -c /n/fs/mail /mail
+bind -c /n/fs/acme /acme
+user=`{cat /dev/user}
+home=/usr/$user
+bind -a /n/fs/usr/$user /usr/$user
+bind -cb /usr/$user/tmp /tmp
+bind -b /usr/$user/bin/rc /bin
+bind -b /usr/$user/bin/arm /bin
+bind -a /n/fs/lib/font/bit/lucidasans /lib/font/bit/lucidasans
+bind -a /n/fs/lib/font/bit/lucida /lib/font/bit/lucida
+bind -a /n/fs/lib/font/bit/misc /lib/font/bit/misc
+#service=cpu aux/listen -t /bin/service
diff --git a/sys/src/9/bitsy/paqfiles/namespace b/sys/src/9/bitsy/paqfiles/namespace
new file mode 100755
index 000000000..e3c638439
--- /dev/null
+++ b/sys/src/9/bitsy/paqfiles/namespace
@@ -0,0 +1,53 @@
+# root
+mount #s/boot /root
+bind -a /root /
+bind -c /root/mnt /mnt
+
+# kernel devices
+bind #c /dev
+bind #d /fd
+bind -c #e /env
+bind #p /proc
+bind -c #s /srv
+bind -a #t /dev
+bind -a #r /dev
+bind -a #m /dev
+bind -a #y /dev
+bind -a #I /net
+bind -a #A /dev
+bind -a #F /dev
+bind -a #¤ /dev
+
+# servers
+mount -a /srv/cs /net
+mount -a /srv/dns /net
+mount -a /srv/factotum /mnt
+
+# read/write file system
+mount /srv/brzr /n/brzr
+mount /srv/brzr /n/tmp
+bind -a /n /n/tmp/n
+bind -a /sys/lib /n/tmp/sys/lib
+bind -a /sys /n/tmp/sys
+bind -a /arm/bin/auth /n/tmp/arm/bin/auth
+bind -a /arm/bin/ndb /n/tmp/arm/bin/ndb
+bind -a /arm/bin/ip /n/tmp/arm/bin/ip
+bind -a /arm/bin/aux /n/tmp/arm/bin/aux
+bind -a /arm/bin /n/tmp/arm/bin
+bind -a /arm /n/tmp/arm
+bind -a /lib/ndb /n/tmp/lib/ndb
+bind -a /lib/font /n/tmp/lib/font
+bind -a /lib /n/tmp/lib
+bind -a / /n/tmp
+bind /n/tmp /
+unmount /n/tmp
+
+# standard bin
+bind /arm/bin /bin
+bind -a /rc/bin /bin
+bind -a /arm/bin/bitsy /bin
+
+# user defines
+bind -cb /usr/$user/tmp /tmp
+bind -b /usr/$user/bin/rc /bin
+bind -b /usr/$user/bin/arm /bin
diff --git a/sys/src/9/bitsy/paqfiles/startip b/sys/src/9/bitsy/paqfiles/startip
new file mode 100755
index 000000000..e02dba6dc
--- /dev/null
+++ b/sys/src/9/bitsy/paqfiles/startip
@@ -0,0 +1,9 @@
+#!/bin/rc
+if(grep -s WaveLAN/IEEE /dev/pcm0ctl){
+ echo -n 'configure #l0 WaveLAN/IEEE'>/dev/pcm0ctl
+ bind -a '#l0' /net
+ echo -n 'key moon1'>/net/ether0/clone
+ ip/ipconfig ether /net/ether0
+ ndb/cs
+ ndb/dns -r
+}
diff --git a/sys/src/9/bitsy/paqfiles/unicode.6.font b/sys/src/9/bitsy/paqfiles/unicode.6.font
new file mode 100755
index 000000000..edd129934
--- /dev/null
+++ b/sys/src/9/bitsy/paqfiles/unicode.6.font
@@ -0,0 +1,5 @@
+11 9
+0x0000 0x00FF lsr.10
+0x0100 0x01f0 ../lucida/EuroLatin.5.0
+0x2000 0x20aa ../lucida/GenPunct.5.0
+0x2200 0x22f1 ../lucida/MathOps1.5.0
diff --git a/sys/src/9/bitsy/power.c b/sys/src/9/bitsy/power.c
new file mode 100755
index 000000000..1c495a160
--- /dev/null
+++ b/sys/src/9/bitsy/power.c
@@ -0,0 +1,356 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "pool.h"
+
+/* Power management for the bitsy */
+
+#define TODFREQ 1000000000LL
+
+/* saved state during power down.
+ * it's only used up to 164/4.
+ * it's only used by routines in l.s
+ */
+ulong power_state[200/4];
+
+ulong resumeaddr[1];
+Rendez powerr;
+ulong powerflag = 0; /* set to start power-off sequence */
+
+extern void power_resume(void);
+extern int setpowerlabel(void);
+extern void _start(void);
+extern Uart sa1110uart[];
+
+GPIOregs savedgpioregs;
+Intrregs savedintrregs;
+
+#define R(p) ((Uartregs*)((p)->regs))
+
+uchar *savedtext;
+
+static void
+checkflash(void)
+{
+ ulong *p;
+ ulong s;
+
+ s = 0;
+ for (p = (ulong*)FLASHZERO; p < (ulong*)(FLASHZERO+8*1024*1024); p++)
+ s += *p;
+ iprint("flash checksum is 0x%lux\n", s);
+}
+
+static void
+checkktext(void)
+{
+ ulong *p;
+ ulong s;
+
+ s = 0;
+ for (p = (ulong*)_start; p < (ulong*)etext; p++){
+ if(*p == 0)
+ iprint("%#p->0\n", p);
+ if (((ulong)p & 0x1fff) == 0){
+ iprint("page 0x%lux checksum 0x%lux\n",
+ (ulong)(p-1)&~0x1fff, s);
+ s = 0;
+ }
+ s += *p;
+ }
+ iprint("page 0x%lux checksum 0x%lux\n", (ulong)(p-1)&~0x1fff, s);
+}
+
+static void
+checkpagetab(void)
+{
+ extern ulong l1table;
+ ulong *p;
+ ulong s;
+
+ s = 0;
+ for (p = (ulong*)l1table; p < (ulong*)(l1table+16*1024); p++)
+ s += *p;
+ iprint("page table checksum is 0x%lux\n", s);
+}
+
+
+static void
+dumpitall(void)
+{
+ extern ulong l1table;
+
+ iprint("intr: icip %lux iclr %lux iccr %lux icmr %lux\n",
+ intrregs->icip,
+ intrregs->iclr, intrregs->iccr, intrregs->icmr );
+ iprint("gpio: lvl %lux dir %lux, re %lux, fe %lux sts %lux alt %lux\n",
+ gpioregs->level,
+ gpioregs->direction, gpioregs->rising, gpioregs->falling,
+ gpioregs->edgestatus, gpioregs->altfunc);
+ iprint("uart1: %lux %lux %lux \nuart3: %lux %lux %lux\n",
+ R(&sa1110uart[0])->ctl[0], R(&sa1110uart[0])->status[0], R(&sa1110uart[0])->status[1],
+ R(&sa1110uart[1])->ctl[0], R(&sa1110uart[1])->status[0], R(&sa1110uart[1])->status[1]);
+ iprint("tmr: osmr %lux %lux %lux %lux oscr %lux ossr %lux oier %lux\n",
+ timerregs->osmr[0], timerregs->osmr[1],
+ timerregs->osmr[2], timerregs->osmr[3],
+ timerregs->oscr, timerregs->ossr, timerregs->oier);
+ iprint("dram: mdcnfg %lux mdrefr %lux cas %lux %lux %lux %lux %lux %lux\n",
+ memconfregs->mdcnfg, memconfregs->mdrefr,
+ memconfregs->mdcas00, memconfregs->mdcas01,memconfregs->mdcas02,
+ memconfregs->mdcas20, memconfregs->mdcas21,memconfregs->mdcas22);
+ iprint("dram: mdcnfg msc %lux %lux %lux mecr %lux\n",
+ memconfregs->msc0, memconfregs->msc1,memconfregs->msc2,
+ memconfregs->mecr);
+ iprint("mmu: CpControl %lux CpTTB %lux CpDAC %lux l1table 0x%lux\n",
+ getcontrol(), getttb(), getdac(), l1table);
+ iprint("powerregs: pmcr %lux pssr %lux pcfr %lux ppcr %lux pwer %lux pspr %lux pgsr %lux posr %lux\n",
+ powerregs->pmcr, powerregs->pssr, powerregs->pcfr, powerregs->ppcr,
+ powerregs->pwer, powerregs->pspr, powerregs->pgsr, powerregs->posr);
+ checkpagetab();
+ checkflash();
+ checkktext();
+ iprint("\n\n");
+}
+
+static void
+intrcpy(Intrregs *to, Intrregs *from)
+{
+ to->iclr = from->iclr;
+ to->iccr = from->iccr;
+ to->icmr = from->icmr; // interrupts enabled
+}
+
+static void
+gpiosave(GPIOregs *to, GPIOregs *from)
+{
+ to->level = from->level;
+ to->rising = from->rising; // gpio intrs enabled
+ to->falling= from->falling; // gpio intrs enabled
+ to->altfunc = from->altfunc;
+ to->direction = from->direction;
+}
+
+static void
+gpiorestore(GPIOregs *to, GPIOregs *from)
+{
+ to->direction = from->direction;
+ to->altfunc = from->altfunc;
+ to->set = from->level & 0x0fffffff;
+ to->clear = ~from->level & 0x0fffffff;
+ to->rising = from->rising; // gpio intrs enabled
+ to->falling= from->falling; // gpio intrs enabled
+}
+
+void (*restart)(void) = nil;
+
+static int
+bitno(ulong x)
+{
+ int i;
+
+ for(i = 0; i < 8*sizeof(x); i++)
+ if((1<<i) & x)
+ break;
+ return i;
+}
+
+int
+powerdown(void *)
+{
+ return powerflag;
+}
+
+void
+deepsleep(void) {
+ static int power_pl;
+ ulong xsp, xlink;
+// ulong mecr;
+ ulong clkd;
+ vlong savedtod;
+ extern void power_resume(void);
+
+ power_pl = splhi();
+ xlink = getcallerpc(&xlink);
+
+ /* Power down */
+ pcmciapower(0);
+ irpower(0);
+ audiopower(0);
+ screenpower(0);
+ µcpower(0);
+ iprint("entering suspend mode, sp = %#p, pc = 0x%lux, psw = 0x%ux\n",
+ &xsp, xlink, power_pl);
+// dumpitall();
+ delay(1000);
+ uartpower(0);
+ rs232power(0);
+ clockpower(0);
+ gpiosave(&savedgpioregs, gpioregs);
+ intrcpy(&savedintrregs, intrregs);
+ cacheflush();
+ delay(50);
+ if(setpowerlabel()){
+ /* return here with mmu back on */
+ trapresume();
+
+ gpiorestore(gpioregs, &savedgpioregs);
+ delay(50);
+ intrcpy(intrregs, &savedintrregs);
+ if(intrregs->icip & (1<<IRQgpio0)){
+ // don't want to sleep now. clear on/off irq.
+ gpioregs->edgestatus = (1<<IRQgpio0);
+ intrregs->icip = (1<<IRQgpio0);
+ }
+ clkd = clockpower(1);
+ gpclkregs->r0 = 1<<0;
+ todset(savedtod + clkd * TODFREQ, 0LL, 0);
+ resetsuspendtimer();
+ rs232power(1);
+ uartpower(1);
+ delay(100);
+ xlink = getcallerpc(&xlink);
+ iprint("\nresuming execution, sp = %#p, pc = 0x%lux, psw = 0x%ux\n",
+ &xsp, xlink, splhi());
+// dumpitall();
+ delay(1000);
+// irpower(1);
+ audiopower(1);
+ µcpower(1);
+ screenpower(1);
+ pcmciapower(1);
+ splx(power_pl);
+ return;
+ }
+ cacheflush();
+ delay(100);
+ savedtod = todget(nil);
+ power_down();
+ /* no return */
+}
+
+void
+powerkproc(void*)
+{
+ ulong xlink, xlink1;
+
+ for(;;){
+ while(powerflag == 0)
+ sleep(&powerr, powerdown, 0);
+
+ xlink = getcallerpc(&xlink);
+
+// iprint("call deepsleep, pc = 0x%lux, sp = 0x%lux\n", xlink, &xlink);
+ deepsleep();
+ xlink1 = getcallerpc(&xlink1);
+
+
+ delay(2000);
+
+// iprint("deepsleep returned, pc = 0x%lux, sp = 0x%lux\n", xlink1, &xlink);
+ powerflag = 0;
+ }
+}
+
+void
+onoffintr(Ureg* , void*)
+{
+ int i;
+
+ /* Power down interrupt comes on power button release.
+ * Act only after button has been released a full 100 ms
+ */
+
+ if (powerflag)
+ return;
+
+ for (i = 0; i < 100; i++) {
+ delay(1);
+ if ((gpioregs->level & GPIO_PWR_ON_i) == 0)
+ return; /* bounced */
+ }
+
+ powerflag = 1;
+ wakeup(&powerr);
+}
+
+static void
+blanktimer(void)
+{
+ drawactive(0);
+}
+
+static ulong suspendtime = 120 * HZ;
+static int lastsuspend;
+
+void
+resetsuspendtimer(void)
+{
+ suspendtime = 60 * HZ;
+}
+
+static void
+suspendtimer(void)
+{
+#ifdef notdef
+ uvlong now;
+
+ if (suspendtime > 0)
+ suspendtime--;
+ if (suspendtime == 0){
+ now = seconds();
+ if (now < lastsuspend + 10){
+ resetsuspendtimer();
+ return;
+ }
+ lastsuspend = seconds();
+ deepsleep();
+ lastsuspend = seconds();
+ return;
+ }
+#endif /* notdef */
+}
+
+void
+powerinit(void)
+{
+ extern ulong power_magic;
+ extern ulong power_code;
+ extern ulong doze_code;
+ ulong *p, *q, i;
+
+ p = (ulong*)(((ulong)&power_magic + 0x1f) & ~0x1f);
+ q = &power_code;
+ for (i = 0; i < 8; i++)
+ *p++ = *q++;
+ p = (ulong*)(((ulong)doze + 0x3f) & ~0x1f);
+ q = &doze_code;
+ for (i = 0; i < 3; i++)
+ *p++ = *q++;
+
+ *resumeaddr = (ulong) power_resume;
+ addclock0link(blanktimer, 1000/HZ);
+ addclock0link(suspendtimer, 1000/HZ);
+ intrenable(GPIOrising, bitno(GPIO_PWR_ON_i), onoffintr, nil, "on/off");
+}
+
+void
+idlehands(void)
+{
+ char *msgb = "idlehands called with splhi\n";
+ char *msga = "doze returns with splhi\n";
+
+ if(!islo()){
+ uartputs(msga, strlen(msga));
+ spllo();
+ }
+ doze();
+ if(!islo()){
+ uartputs(msgb, strlen(msgb));
+ spllo();
+ }
+}
+
diff --git a/sys/src/9/bitsy/random.c b/sys/src/9/bitsy/random.c
new file mode 100755
index 000000000..7bade6cd1
--- /dev/null
+++ b/sys/src/9/bitsy/random.c
@@ -0,0 +1,138 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+
+struct Rb
+{
+ QLock;
+ Rendez producer;
+ Rendez consumer;
+ ulong randomcount;
+ uchar buf[128];
+ uchar *ep;
+ uchar *rp;
+ uchar *wp;
+ uchar next;
+ uchar wakeme;
+ ushort bits;
+ ulong randn;
+} rb;
+
+static int
+rbnotfull(void*)
+{
+ int i;
+
+ i = rb.rp - rb.wp;
+ return i != 1 && i != (1 - sizeof(rb.buf));
+}
+
+static int
+rbnotempty(void*)
+{
+ return rb.wp != rb.rp;
+}
+
+static void
+genrandom(void*)
+{
+ up->basepri = PriNormal;
+ up->priority = up->basepri;
+
+ for(;;){
+ for(;;)
+ if(++rb.randomcount > 100000)
+ break;
+ if(anyhigher())
+ sched();
+ if(!rbnotfull(0))
+ sleep(&rb.producer, rbnotfull, 0);
+ }
+}
+
+/*
+ * produce random bits in a circular buffer
+ */
+static void
+randomclock(void)
+{
+ if(rb.randomcount == 0 || !rbnotfull(0))
+ return;
+
+ rb.bits = (rb.bits<<2) ^ rb.randomcount;
+ rb.randomcount = 0;
+
+ rb.next++;
+ if(rb.next != 8/2)
+ return;
+ rb.next = 0;
+
+ *rb.wp ^= rb.bits;
+ if(rb.wp+1 == rb.ep)
+ rb.wp = rb.buf;
+ else
+ rb.wp = rb.wp+1;
+
+ if(rb.wakeme)
+ wakeup(&rb.consumer);
+}
+
+void
+randominit(void)
+{
+ addclock0link(randomclock, 1000/HZ);
+ rb.ep = rb.buf + sizeof(rb.buf);
+ rb.rp = rb.wp = rb.buf;
+ kproc("genrandom", genrandom, 0);
+}
+
+/*
+ * consume random bytes from a circular buffer
+ */
+ulong
+randomread(void *xp, ulong n)
+{
+ uchar *e, *p;
+ ulong x;
+
+ p = xp;
+
+ if(waserror()){
+ qunlock(&rb);
+ nexterror();
+ }
+
+ qlock(&rb);
+ for(e = p + n; p < e; ){
+ if(rb.wp == rb.rp){
+ rb.wakeme = 1;
+ wakeup(&rb.producer);
+ sleep(&rb.consumer, rbnotempty, 0);
+ rb.wakeme = 0;
+ continue;
+ }
+
+ /*
+ * beating clocks will be precictable if
+ * they are synchronized. Use a cheap pseudo
+ * random number generator to obscure any cycles.
+ */
+ x = rb.randn*1103515245 ^ *rb.rp;
+ *p++ = rb.randn = x;
+
+ if(rb.rp+1 == rb.ep)
+ rb.rp = rb.buf;
+ else
+ rb.rp = rb.rp+1;
+ }
+ qunlock(&rb);
+ poperror();
+
+ wakeup(&rb.producer);
+
+ return n;
+}
diff --git a/sys/src/9/bitsy/sa1110dma.c b/sys/src/9/bitsy/sa1110dma.c
new file mode 100755
index 000000000..f95093d38
--- /dev/null
+++ b/sys/src/9/bitsy/sa1110dma.c
@@ -0,0 +1,227 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "sa1110dma.h"
+
+static int debug = 0;
+
+/*
+ * DMA helper routines
+ */
+
+enum {
+ NDMA = 6, /* Number of DMA channels */
+ DMAREGS = 0xb0000000, /* DMA registers, physical */
+};
+
+enum {
+ /* Device Address Register, DDAR */
+ RW = 0,
+ E = 1,
+ BS = 2,
+ DW = 3,
+ DS = 4, /* bits 4 - 7 */
+ DA = 8 /* bits 8 - 31 */
+};
+
+enum {
+ /* Device Control & Status Register, DCSR */
+ RUN = 0,
+ IE = 1,
+ ERROR = 2,
+ DONEA = 3,
+ STRTA = 4,
+ DONEB = 5,
+ STRTB = 6,
+ BIU = 7
+};
+
+typedef struct DMAchan {
+ int allocated;
+ Rendez r;
+ void (*intr)(void*, ulong);
+ void *param;
+} DMAchan;
+
+struct {
+ Lock;
+ DMAchan chan[6];
+} dma;
+
+struct dmaregs {
+ ulong ddar;
+ ulong dcsr_set;
+ ulong dcsr_clr;
+ ulong dcsr_rd;
+ ulong dstrtA;
+ ulong dxcntA;
+ ulong dstrtB;
+ ulong dxcntB;
+} *dmaregs;
+
+static void dmaintr(Ureg*, void *);
+
+void
+dmainit(void) {
+ int i;
+
+ /* map the lcd regs into the kernel's virtual space */
+ dmaregs = (struct dmaregs*)mapspecial(DMAREGS, NDMA*sizeof(struct dmaregs));
+ if (debug) print("dma: dmaalloc registers 0x%ux mapped at 0x%p\n",
+ DMAREGS, dmaregs);
+ for (i = 0; i < NDMA; i++) {
+ intrenable(IRQ, IRQdma0+i, dmaintr, &dmaregs[i], "DMA");
+ }
+}
+
+void
+dmareset(int i, int rd, int bigendian, int burstsize, int datumsize, int device, ulong port) {
+ ulong ddar;
+
+ ddar =
+ (rd?1:0)<<RW |
+ (bigendian?1:0)<<E |
+ ((burstsize==8)?1:0)<<BS |
+ ((datumsize==2)?1:0)<<DW |
+ device<<DS |
+ 0x80000000 | ((ulong)port << 6);
+ dmaregs[i].ddar = ddar;
+ dmaregs[i].dcsr_clr = 0xff;
+ if (debug) print("dma: dmareset: 0x%lux\n", ddar);
+}
+
+int
+dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, ulong port, void (*intr)(void*, ulong), void *param) {
+ int i;
+
+ lock(&dma);
+ for (i = 0; i < NDMA; i++) {
+ if (dma.chan[i].allocated)
+ continue;
+ dma.chan[i].allocated++;
+ unlock(&dma);
+ dmareset(i, rd, bigendian, burstsize, datumsize, device, port);
+ dma.chan[i].intr = intr;
+ dma.chan[i].param = param;
+ return i;
+ }
+ unlock(&dma);
+ return -1;
+}
+
+void
+dmafree(int i) {
+ dmaregs[i].dcsr_clr = 0xff;
+ dmaregs[i].ddar = 0;
+ dma.chan[i].allocated = 0;
+ dma.chan[i].intr = nil;
+}
+
+void
+dmastop(int i) {
+ dmaregs[i].dcsr_clr = 0xff;
+}
+
+ulong
+dmastart(int chan, ulong addr, int count) {
+ ulong status, n;
+ static int last;
+
+ /* If this gets called from interrupt routines, make sure ilocks are used */
+ status = dmaregs[chan].dcsr_rd;
+ if (debug > 1)
+ iprint("dma: dmastart 0x%lux\n", status);
+
+ if ((status & (1<<STRTA|1<<STRTB|1<<RUN)) == (1<<STRTA|1<<STRTB|1<<RUN)) {
+ return 0;
+ }
+ cachewbregion(addr, count);
+ n = 0x100;
+ if ((status & (1<<BIU | 1<<STRTB)) == (1<<BIU | 1<<STRTB) ||
+ (status & (1<<BIU | 1<<STRTA)) == 0) {
+ if (status & 1<<STRTA)
+ iprint("writing busy dma entry 0x%lux\n", status);
+ if (status & 1<<STRTB)
+ n = (last == 1)?0x200:0x300;
+ last = 2;
+ dmaregs[chan].dstrtA = addr;
+ dmaregs[chan].dxcntA = count;
+ dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTA;
+ n |= 1<<DONEA;
+ } else {
+ if (status & 1<<STRTB)
+ iprint("writing busy dma entry 0x%lux\n", status);
+ if (status & 1<<STRTA)
+ n = (last == 2)?0x200:0x300;
+ last = 1;
+ dmaregs[chan].dstrtB = addr;
+ dmaregs[chan].dxcntB = count;
+ dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTB;
+ n |= 1<<DONEB;
+ }
+ return n;
+}
+
+int
+dmaidle(int chan) {
+ ulong status;
+
+ status = dmaregs[chan].dcsr_rd;
+ if (debug > 1) print("dmaidle: 0x%lux\n", status);
+ return (status & (1<<STRTA|1<<STRTB)) == 0;
+}
+
+static int
+_dmaidle(void* chan) {
+ ulong status;
+
+ status = dmaregs[(int)chan].dcsr_rd;
+ return (status & (1<<STRTA|1<<STRTB)) == 0;
+}
+
+void
+dmawait(int chan) {
+ while (!dmaidle(chan))
+ sleep(&dma.chan[chan].r, _dmaidle, (void*)chan);
+}
+
+/*
+ * interrupt routine
+ */
+static void
+dmaintr(Ureg*, void *x)
+{
+ int i;
+ struct dmaregs *regs = x;
+ ulong dcsr, donebit;
+
+ i = regs - dmaregs;
+ dcsr = regs->dcsr_rd;
+ if (debug > 1)
+ iprint("dma: interrupt channel %d, status 0x%lux\n", i, dcsr);
+ if (dcsr & 1<<ERROR)
+ iprint("error, channel %d, status 0x%lux\n", i, dcsr);
+ donebit = 1<<((dcsr&1<<BIU)?DONEA:DONEB);
+ if (dcsr & donebit) {
+ regs->dcsr_clr = 1<<DONEA|1<<DONEB;
+ if (dma.chan[i].intr) {
+ (*dma.chan[i].intr)(dma.chan[i].param, dcsr & (1<<DONEA|1<<DONEB));
+ }
+ wakeup(&dma.chan[i].r);
+ return;
+ }
+ if (dcsr & 1<<ERROR) {
+ regs->dcsr_clr = ERROR;
+ iprint("DMA error, channel %d, status 0x%lux\n", i, dcsr);
+ if (dma.chan[i].intr) {
+ (*dma.chan[i].intr)(dma.chan[i].param, 0);
+ }
+ wakeup(&dma.chan[i].r);
+ return;
+ }
+ iprint("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr);
+}
diff --git a/sys/src/9/bitsy/sa1110dma.h b/sys/src/9/bitsy/sa1110dma.h
new file mode 100755
index 000000000..24810e8d4
--- /dev/null
+++ b/sys/src/9/bitsy/sa1110dma.h
@@ -0,0 +1,19 @@
+
+enum {
+ Port4MCP = 0x80060008,
+ Port4SSP = 0x8007006c,
+ AudioDMA = 0xa,
+ SSPXmitDMA = 0xe,
+ SSPRecvDMA = 0xf,
+};
+
+void dmainit(void);
+int dmaalloc(int, int, int, int, int, ulong, void (*)(void*, ulong), void*);
+void dmareset(int, int, int, int, int, int, ulong);
+void dmafree(int);
+
+ulong dmastart(int, ulong, int);
+
+void dmawait(int);
+void dmastop(int);
+int dmaidle(int);
diff --git a/sys/src/9/bitsy/screen.c b/sys/src/9/bitsy/screen.c
new file mode 100755
index 000000000..9946a8b31
--- /dev/null
+++ b/sys/src/9/bitsy/screen.c
@@ -0,0 +1,496 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+#include "gamma.h"
+
+#define MINX 8
+
+int landscape = 0; /* orientation of the screen, default is 0: portait */
+
+enum {
+ Wid = 240,
+ Ht = 320,
+ Pal0 = 0x2000, /* 16-bit pixel data in active mode (12 in passive) */
+
+ hsw = 0x00,
+ elw = 0x0e,
+ blw = 0x0d,
+
+ vsw = 0x02,
+ efw = 0x01,
+ bfw = 0x0a,
+
+ pcd = 0x10,
+};
+
+struct sa1110fb {
+ /* Frame buffer for 16-bit active color */
+ short palette[16]; /* entry 0 set to Pal0, the rest to 0 */
+ ushort pixel[Wid*Ht]; /* Pixel data */
+} *framebuf;
+
+enum {
+/* LCD Control Register 0, lcd->lccr0 */
+ LEN = 0, /* 1 bit */
+ CMS = 1, /* 1 bit */
+ SDS = 2, /* 1 bit */
+ LDM = 3, /* 1 bit */
+ BAM = 4, /* 1 bit */
+ ERM = 5, /* 1 bit */
+ PAS = 7, /* 1 bit */
+ BLE = 8, /* 1 bit */
+ DPD = 9, /* 1 bit */
+ PDD = 12, /* 8 bits */
+};
+
+enum {
+/* LCD Control Register 1, lcd->lccr1 */
+ PPL = 0, /* 10 bits */
+ HSW = 10, /* 6 bits */
+ ELW = 16, /* 8 bits */
+ BLW = 24, /* 8 bits */
+};
+
+enum {
+/* LCD Control Register 2, lcd->lccr2 */
+ LPP = 0, /* 10 bits */
+ VSW = 10, /* 6 bits */
+ EFW = 16, /* 8 bits */
+ BFW = 24, /* 8 bits */
+};
+
+enum {
+/* LCD Control Register 3, lcd->lccr3 */
+ PCD = 0, /* 8 bits */
+ ACB = 8, /* 8 bits */
+ API = 16, /* 4 bits */
+ VSP = 20, /* 1 bit */
+ HSP = 21, /* 1 bit */
+ PCP = 22, /* 1 bit */
+ OEP = 23, /* 1 bit */
+};
+
+enum {
+/* LCD Status Register, lcd->lcsr */
+ LDD = 0, /* 1 bit */
+ BAU = 1, /* 1 bit */
+ BER = 2, /* 1 bit */
+ ABC = 3, /* 1 bit */
+ IOL = 4, /* 1 bit */
+ IUL = 5, /* 1 bit */
+ OIU = 6, /* 1 bit */
+ IUU = 7, /* 1 bit */
+ OOL = 8, /* 1 bit */
+ OUL = 9, /* 1 bit */
+ OOU = 10, /* 1 bit */
+ OUU = 11, /* 1 bit */
+};
+
+struct sa1110regs {
+ ulong lccr0;
+ ulong lcsr;
+ ulong dummies[2];
+ short* dbar1;
+ ulong dcar1;
+ ulong dbar2;
+ ulong dcar2;
+ ulong lccr1;
+ ulong lccr2;
+ ulong lccr3;
+} *lcd;
+
+Point ZP = {0, 0};
+
+static Memdata xgdata;
+
+static Memimage xgscreen =
+{
+ { 0, 0, Wid, Ht }, /* r */
+ { 0, 0, Wid, Ht }, /* clipr */
+ 16, /* depth */
+ 3, /* nchan */
+ RGB16, /* chan */
+ nil, /* cmap */
+ &xgdata, /* data */
+ 0, /* zero */
+ Wid/2, /* width */
+ 0, /* layer */
+ 0, /* flags */
+};
+
+struct{
+ Point pos;
+ int bwid;
+}out;
+
+Memimage *gscreen;
+Memimage *conscol;
+Memimage *back;
+
+Memsubfont *memdefont;
+
+Lock screenlock;
+
+Point ZP = {0, 0};
+ushort *vscreen; /* virtual screen */
+Rectangle window;
+Point curpos;
+int h, w;
+int drawdebug;
+
+static ulong rep(ulong, int);
+static void screenwin(void);
+static void screenputc(char *buf);
+static void bitsyscreenputs(char *s, int n);
+static void scroll(void);
+
+static void
+lcdinit(void)
+{
+ /* the following line works because main memory is direct mapped */
+ gpioregs->direction |=
+ GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
+ |GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o;
+ gpioregs->altfunc |=
+ GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
+ |GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o;
+ framebuf->palette[0] = Pal0;
+ lcd->dbar1 = framebuf->palette;
+ lcd->lccr3 = pcd<<PCD | 0<<ACB | 0<<API | 1<<VSP | 1<<HSP | 0<<PCP | 0<<OEP;
+ lcd->lccr2 = (Wid-1)<<LPP | vsw<<VSW | efw<<EFW | bfw<<BFW;
+ lcd->lccr1 = (Ht-16)<<PPL | hsw<<HSW | elw<<ELW | blw<<BLW;
+ lcd->lccr0 = 1<<LEN | 0<<CMS | 0<<SDS | 1<<LDM | 1<<BAM | 1<<ERM | 1<<PAS | 0<<BLE | 0<<DPD | 0<<PDD;
+}
+
+void
+flipscreen(int ls) {
+ if (ls == landscape)
+ return;
+ if (ls) {
+ gscreen->r = Rect(0, 0, Ht, Wid);
+ gscreen->clipr = gscreen->r;
+ gscreen->width = Ht/2;
+ xgdata.bdata = (uchar *)framebuf->pixel;
+ } else {
+ gscreen->r = Rect(0, 0, Wid, Ht);
+ gscreen->clipr = gscreen->r;
+ gscreen->width = Wid/2;
+ xgdata.bdata = (uchar *)vscreen;
+ }
+ landscape = ls;
+}
+
+void
+lcdtweak(Cmdbuf *cmd)
+{
+ if(cmd->nf < 4)
+ return;
+ if(*cmd->f[0] == 'h')
+ lcd->lccr1 = ((Ht-16)<<PPL)
+ | (atoi(cmd->f[1])<<HSW)
+ | (atoi(cmd->f[2])<<ELW)
+ | (atoi(cmd->f[3])<<BLW);
+ if(*cmd->f[0] == 'v')
+ lcd->lccr2 = ((Wid-1)<<LPP)
+ | (atoi(cmd->f[1])<<VSW)
+ | (atoi(cmd->f[2])<<EFW)
+ | (atoi(cmd->f[3])<<BFW);
+}
+
+void
+screenpower(int on)
+{
+ blankscreen(on == 0);
+}
+
+void
+screeninit(void)
+{
+ int i;
+
+ /* map the lcd regs into the kernel's virtual space */
+ lcd = (struct sa1110regs*)mapspecial(LCDREGS, sizeof(struct sa1110regs));;
+
+ framebuf = xspanalloc(sizeof *framebuf, 0x100, 0);
+
+ vscreen = xalloc(sizeof(ushort)*Wid*Ht);
+
+ lcdpower(1);
+ lcdinit();
+
+ gscreen = &xgscreen;
+
+ xgdata.ref = 1;
+ i = 0;
+ if (landscape) {
+ gscreen->r = Rect(0, 0, Ht, Wid);
+ gscreen->clipr = gscreen->r;
+ gscreen->width = Ht/2;
+ xgdata.bdata = (uchar *)framebuf->pixel;
+ while (i < Wid*Ht*1/3) framebuf->pixel[i++] = 0xf800; /* red */
+ while (i < Wid*Ht*2/3) framebuf->pixel[i++] = 0xffff; /* white */
+ while (i < Wid*Ht*3/3) framebuf->pixel[i++] = 0x001f; /* blue */
+ } else {
+ gscreen->r = Rect(0, 0, Wid, Ht);
+ gscreen->clipr = gscreen->r;
+ gscreen->width = Wid/2;
+ xgdata.bdata = (uchar *)vscreen;
+ while (i < Wid*Ht*1/3) vscreen[i++] = 0xf800; /* red */
+ while (i < Wid*Ht*2/3) vscreen[i++] = 0xffff; /* white */
+ while (i < Wid*Ht*3/3) vscreen[i++] = 0x001f; /* blue */
+ flushmemscreen(gscreen->r);
+ }
+ memimageinit();
+ memdefont = getmemdefont();
+
+ out.pos.x = MINX;
+ out.pos.y = 0;
+ out.bwid = memdefont->info[' '].width;
+
+ blanktime = 3; /* minutes */
+
+ screenwin();
+// screenputs = bitsyscreenputs;
+ screenputs = nil;
+}
+
+void
+flushmemscreen(Rectangle r)
+{
+ int x, y;
+ ulong start, end;
+
+ if (landscape == 0) {
+ if (r.min.x < 0) r.min.x = 0;
+ if (r.max.x > Wid) r.max.x = Wid;
+ if (r.min.y < 0) r.min.y = 0;
+ if (r.max.y > Ht) r.max.y = Ht;
+ for (x = r.min.x; x < r.max.x; x++)
+ for (y = r.min.y; y < r.max.y; y++)
+ framebuf->pixel[(x+1)*Ht-1-y] = gamma[vscreen[y*Wid+x]];
+ start = (ulong)&framebuf->pixel[(r.min.x+1)*Ht-1-(r.max.y-1)];
+ end = (ulong)&framebuf->pixel[(r.max.x-1+1)*Ht-1-(r.min.y)];
+ } else {
+ start = (ulong)&framebuf->pixel[r.min.y*Ht + r.min.x];
+ end = (ulong)&framebuf->pixel[(r.max.y-1)*Ht + r.max.x - 1];
+ }
+ cachewbregion(start, end-start);
+}
+
+/*
+ * export screen to devdraw
+ */
+uchar*
+attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
+{
+ *r = gscreen->r;
+ *d = gscreen->depth;
+ *chan = gscreen->chan;
+ *width = gscreen->width;
+ *softscreen = (landscape == 0);
+
+ return (uchar*)gscreen->data->bdata;
+}
+
+void
+getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
+{
+ USED(p, pr, pg, pb);
+}
+
+int
+setcolor(ulong p, ulong r, ulong g, ulong b)
+{
+ USED(p,r,g,b);
+ return 0;
+}
+
+void
+blankscreen(int blank)
+{
+ int cnt;
+
+ if (blank) {
+ lcd->lccr0 &= ~(1<<LEN); /* disable the LCD */
+ cnt = 0;
+ while((lcd->lcsr & (1<<LDD)) == 0) {
+ delay(10);
+ if (++cnt == 100) {
+ iprint("LCD doesn't stop\n");
+ break;
+ }
+ }
+ lcdpower(0);
+ } else {
+ lcdpower(1);
+ lcdinit();
+ }
+}
+
+static void
+bitsyscreenputs(char *s, int n)
+{
+ int i;
+ Rune r;
+ char buf[4];
+
+ if(!islo()) {
+ /* don't deadlock trying to print in interrupt */
+ if(!canlock(&screenlock))
+ return;
+ }
+ else
+ lock(&screenlock);
+
+ while(n > 0){
+ i = chartorune(&r, s);
+ if(i == 0){
+ s++;
+ --n;
+ continue;
+ }
+ memmove(buf, s, i);
+ buf[i] = 0;
+ n -= i;
+ s += i;
+ screenputc(buf);
+ }
+ unlock(&screenlock);
+}
+
+static void
+screenwin(void)
+{
+ Point p, q;
+ char *greet;
+ Memimage *orange;
+ Rectangle r;
+
+ memsetchan(gscreen, RGB16);
+
+ back = memwhite;
+ conscol = memblack;
+
+ orange = allocmemimage(Rect(0,0,1,1), RGB16);
+ orange->flags |= Frepl;
+ orange->clipr = gscreen->r;
+ orange->data->bdata[0] = 0x40;
+ orange->data->bdata[1] = 0xfd;
+
+ w = memdefont->info[' '].width;
+ h = memdefont->height;
+
+ r = insetrect(gscreen->r, 4);
+
+ memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S);
+ window = insetrect(r, 4);
+ memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
+
+ memimagedraw(gscreen, Rect(window.min.x, window.min.y,
+ window.max.x, window.min.y+h+5+6), orange, ZP, nil, ZP, S);
+ freememimage(orange);
+ window = insetrect(window, 5);
+
+ greet = " Plan 9 Console ";
+ p = addpt(window.min, Pt(10, 0));
+ q = memsubfontwidth(memdefont, greet);
+ memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
+ flushmemscreen(r);
+ window.min.y += h+6;
+ curpos = window.min;
+ window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
+}
+
+static void
+screenputc(char *buf)
+{
+ Point p;
+ int w, pos;
+ Rectangle r;
+ static int *xp;
+ static int xbuf[256];
+
+ if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
+ xp = xbuf;
+
+ switch(buf[0]) {
+ case '\n':
+ if(curpos.y+h >= window.max.y)
+ scroll();
+ curpos.y += h;
+ screenputc("\r");
+ break;
+ case '\r':
+ xp = xbuf;
+ curpos.x = window.min.x;
+ break;
+ case '\t':
+ p = memsubfontwidth(memdefont, " ");
+ w = p.x;
+ if(curpos.x >= window.max.x-4*w)
+ screenputc("\n");
+
+ pos = (curpos.x-window.min.x)/w;
+ pos = 4-(pos%4);
+ *xp++ = curpos.x;
+ r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
+ memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
+ flushmemscreen(r);
+ curpos.x += pos*w;
+ break;
+ case '\b':
+ if(xp <= xbuf)
+ break;
+ xp--;
+ r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
+ memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
+ flushmemscreen(r);
+ curpos.x = *xp;
+ break;
+ case '\0':
+ break;
+ default:
+ p = memsubfontwidth(memdefont, buf);
+ w = p.x;
+
+ if(curpos.x >= window.max.x-w)
+ screenputc("\n");
+
+ *xp++ = curpos.x;
+ r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h);
+ memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
+ memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
+ flushmemscreen(r);
+ curpos.x += w;
+ }
+}
+
+static void
+scroll(void)
+{
+ int o;
+ Point p;
+ Rectangle r;
+
+ o = 8*h;
+ r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
+ p = Pt(window.min.x, window.min.y+o);
+ memimagedraw(gscreen, r, gscreen, p, nil, p, S);
+ flushmemscreen(r);
+ r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
+ memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
+ flushmemscreen(r);
+
+ curpos.y -= o;
+}
diff --git a/sys/src/9/bitsy/screen.h b/sys/src/9/bitsy/screen.h
new file mode 100755
index 000000000..e85b84992
--- /dev/null
+++ b/sys/src/9/bitsy/screen.h
@@ -0,0 +1,14 @@
+typedef struct Cursorinfo Cursorinfo;
+typedef struct Cursor Cursor;
+
+extern ulong blanktime;
+
+struct Cursorinfo {
+ Lock;
+};
+
+extern void blankscreen(int);
+extern void flushmemscreen(Rectangle);
+extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*);
+
+#define ishwimage(i) 0
diff --git a/sys/src/9/bitsy/sd.h b/sys/src/9/bitsy/sd.h
new file mode 100755
index 000000000..e69de29bb
--- /dev/null
+++ b/sys/src/9/bitsy/sd.h
diff --git a/sys/src/9/bitsy/sdata.c b/sys/src/9/bitsy/sdata.c
new file mode 100755
index 000000000..ac92c4bf1
--- /dev/null
+++ b/sys/src/9/bitsy/sdata.c
@@ -0,0 +1,2087 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+#include "../port/sd.h"
+
+
+extern SDifc sdataifc;
+
+//BUG?
+#define PCIWADDR(x) ((ulong)(x))
+
+enum {
+ DbgCONFIG = 0x01, /* detected drive config info */
+ DbgIDENTIFY = 0x02, /* detected drive identify info */
+ DbgSTATE = 0x04, /* dump state on panic */
+ DbgPROBE = 0x08, /* trace device probing */
+ DbgDEBUG = 0x80, /* the current problem... */
+};
+#define DEBUG (DbgDEBUG|DbgSTATE|DbgCONFIG)
+
+enum { /* I/O ports */
+ Data = 0,
+ Error = 1, /* (read) */
+ Features = 1, /* (write) */
+ Count = 2, /* sector count */
+ Ir = 2, /* interrupt reason (PACKET) */
+ Sector = 3, /* sector number, LBA<7-0> */
+ Cyllo = 4, /* cylinder low, LBA<15-8> */
+ Bytelo = 4, /* byte count low (PACKET) */
+ Cylhi = 5, /* cylinder high, LBA<23-16> */
+ Bytehi = 5, /* byte count hi (PACKET) */
+ Dh = 6, /* Device/Head, LBA<32-14> */
+ Status = 7, /* (read) */
+ Command = 7, /* (write) */
+
+ As = 2, /* Alternate Status (read) */
+ Dc = 2, /* Device Control (write) */
+};
+
+enum { /* Error */
+ Med = 0x01, /* Media error */
+ Ili = 0x01, /* command set specific (PACKET) */
+ Nm = 0x02, /* No Media */
+ Eom = 0x02, /* command set specific (PACKET) */
+ Abrt = 0x04, /* Aborted command */
+ Mcr = 0x08, /* Media Change Request */
+ Idnf = 0x10, /* no user-accessible address */
+ Mc = 0x20, /* Media Change */
+ Unc = 0x40, /* Uncorrectable data error */
+ Wp = 0x40, /* Write Protect */
+ Icrc = 0x80, /* Interface CRC error */
+};
+
+enum { /* Features */
+ Dma = 0x01, /* data transfer via DMA (PACKET) */
+ Ovl = 0x02, /* command overlapped (PACKET) */
+};
+
+enum { /* Interrupt Reason */
+ Cd = 0x01, /* Command/Data */
+ Io = 0x02, /* I/O direction */
+ Rel = 0x04, /* Bus Release */
+};
+
+enum { /* Device/Head */
+ Dev0 = 0xA0, /* Master */
+ Dev1 = 0xB0, /* Slave */
+ Lba = 0x40, /* LBA mode */
+};
+
+enum { /* Status, Alternate Status */
+ Err = 0x01, /* Error */
+ Chk = 0x01, /* Check error (PACKET) */
+ Drq = 0x08, /* Data Request */
+ Dsc = 0x10, /* Device Seek Complete */
+ Serv = 0x10, /* Service */
+ Df = 0x20, /* Device Fault */
+ Dmrd = 0x20, /* DMA ready (PACKET) */
+ Drdy = 0x40, /* Device Ready */
+ Bsy = 0x80, /* Busy */
+};
+
+enum { /* Command */
+ Cnop = 0x00, /* NOP */
+ Cdr = 0x08, /* Device Reset */
+ Crs = 0x20, /* Read Sectors */
+ Cws = 0x30, /* Write Sectors */
+ Cedd = 0x90, /* Execute Device Diagnostics */
+ Cpkt = 0xA0, /* Packet */
+ Cidpkt = 0xA1, /* Identify Packet Device */
+ Crsm = 0xC4, /* Read Multiple */
+ Cwsm = 0xC5, /* Write Multiple */
+ Csm = 0xC6, /* Set Multiple */
+ Crdq = 0xC7, /* Read DMA queued */
+ Crd = 0xC8, /* Read DMA */
+ Cwd = 0xCA, /* Write DMA */
+ Cwdq = 0xCC, /* Write DMA queued */
+ Cstandby = 0xE2, /* Standby */
+ Cid = 0xEC, /* Identify Device */
+ Csf = 0xEF, /* Set Features */
+};
+
+enum { /* Device Control */
+ Nien = 0x02, /* (not) Interrupt Enable */
+ Srst = 0x04, /* Software Reset */
+};
+
+enum { /* PCI Configuration Registers */
+ Bmiba = 0x20, /* Bus Master Interface Base Address */
+ Idetim = 0x40, /* IE Timing */
+ Sidetim = 0x44, /* Slave IE Timing */
+ Udmactl = 0x48, /* Ultra DMA/33 Control */
+ Udmatim = 0x4A, /* Ultra DMA/33 Timing */
+};
+
+enum { /* Bus Master IDE I/O Ports */
+ Bmicx = 0, /* Command */
+ Bmisx = 2, /* Status */
+ Bmidtpx = 4, /* Descriptor Table Pointer */
+};
+
+enum { /* Bmicx */
+ Ssbm = 0x01, /* Start/Stop Bus Master */
+ Rwcon = 0x08, /* Read/Write Control */
+};
+
+enum { /* Bmisx */
+ Bmidea = 0x01, /* Bus Master IDE Active */
+ Idedmae = 0x02, /* IDE DMA Error (R/WC) */
+ Ideints = 0x04, /* IDE Interrupt Status (R/WC) */
+ Dma0cap = 0x20, /* Drive 0 DMA Capable */
+ Dma1cap = 0x40, /* Drive 0 DMA Capable */
+};
+enum { /* Physical Region Descriptor */
+ PrdEOT = 0x80000000, /* Bus Master IDE Active */
+};
+
+enum { /* offsets into the identify info. */
+ Iconfig = 0, /* general configuration */
+ Ilcyl = 1, /* logical cylinders */
+ Ilhead = 3, /* logical heads */
+ Ilsec = 6, /* logical sectors per logical track */
+ Iserial = 10, /* serial number */
+ Ifirmware = 23, /* firmware revision */
+ Imodel = 27, /* model number */
+ Imaxrwm = 47, /* max. read/write multiple sectors */
+ Icapabilities = 49, /* capabilities */
+ Istandby = 50, /* device specific standby timer */
+ Ipiomode = 51, /* PIO data transfer mode number */
+ Ivalid = 53,
+ Iccyl = 54, /* cylinders if (valid&0x01) */
+ Ichead = 55, /* heads if (valid&0x01) */
+ Icsec = 56, /* sectors if (valid&0x01) */
+ Iccap = 57, /* capacity if (valid&0x01) */
+ Irwm = 59, /* read/write multiple */
+ Ilba0 = 60, /* LBA size */
+ Ilba1 = 61, /* LBA size */
+ Imwdma = 63, /* multiword DMA mode */
+ Iapiomode = 64, /* advanced PIO modes supported */
+ Iminmwdma = 65, /* min. multiword DMA cycle time */
+ Irecmwdma = 66, /* rec. multiword DMA cycle time */
+ Iminpio = 67, /* min. PIO cycle w/o flow control */
+ Iminiordy = 68, /* min. PIO cycle with IORDY */
+ Ipcktbr = 71, /* time from PACKET to bus release */
+ Iserbsy = 72, /* time from SERVICE to !Bsy */
+ Iqdepth = 75, /* max. queue depth */
+ Imajor = 80, /* major version number */
+ Iminor = 81, /* minor version number */
+ Icsfs = 82, /* command set/feature supported */
+ Icsfe = 85, /* command set/feature enabled */
+ Iudma = 88, /* ultra DMA mode */
+ Ierase = 89, /* time for security erase */
+ Ieerase = 90, /* time for enhanced security erase */
+ Ipower = 91, /* current advanced power management */
+ Irmsn = 127, /* removable status notification */
+ Istatus = 128, /* security status */
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Drive Drive;
+
+typedef struct Prd {
+ ulong pa; /* Physical Base Address */
+ int count;
+} Prd;
+
+enum {
+ Nprd = SDmaxio/(64*1024)+2,
+};
+
+typedef struct Ctlr {
+ int cmdport;
+ int ctlport;
+ int irq;
+ int tbdf;
+ int bmiba; /* bus master interface base address */
+
+ void (*ienable)(Ctlr*);
+ SDev* sdev;
+
+ Drive* drive[2];
+
+ Prd* prdt; /* physical region descriptor table */
+
+ QLock; /* current command */
+ Drive* curdrive;
+ int command; /* last command issued (debugging) */
+ Rendez;
+ int done;
+
+ Lock; /* register access */
+} Ctlr;
+
+typedef struct Drive {
+ Ctlr* ctlr;
+
+ int dev;
+ ushort info[256];
+ int c; /* cylinder */
+ int h; /* head */
+ int s; /* sector */
+ int sectors; /* total */
+ int secsize; /* sector size */
+
+ int dma; /* DMA R/W possible */
+ int dmactl;
+ int rwm; /* read/write multiple possible */
+ int rwmctl;
+
+ int pkt; /* PACKET device, length of pktcmd */
+ uchar pktcmd[16];
+ int pktdma; /* this PACKET command using dma */
+
+ uchar sense[18];
+ uchar inquiry[48];
+
+ QLock; /* drive access */
+ int command; /* current command */
+ int write;
+ uchar* data;
+ int dlen;
+ uchar* limit;
+ int count; /* sectors */
+ int block; /* R/W bytes per block */
+ int status;
+ int error;
+} Drive;
+
+
+
+static void
+atadumpstate(Drive* drive, uchar* cmd, int lba, int count)
+{
+ Prd *prd;
+ Ctlr *ctlr;
+ int i, bmiba;
+
+ if(!(DEBUG & DbgSTATE)){
+ USED(drive, cmd, lba, count);
+ return;
+ }
+
+ ctlr = drive->ctlr;
+ print("command %2.2uX\n", ctlr->command);
+ print("data %8.8p limit %8.8p dlen %d status %uX error %uX\n",
+ drive->data, drive->limit, drive->dlen,
+ drive->status, drive->error);
+ if(cmd != nil){
+ print("lba %d -> %d, count %d -> %d (%d)\n",
+ (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5], lba,
+ (cmd[7]<<8)|cmd[8], count, drive->count);
+ }
+ if(!(inb(ctlr->ctlport+As) & Bsy)){
+ for(i = 1; i < 7; i++)
+ print(" 0x%2.2uX", inb(ctlr->cmdport+i));
+ print(" 0x%2.2uX\n", inb(ctlr->ctlport+As));
+ }
+ if(drive->command == Cwd || drive->command == Crd){
+ bmiba = ctlr->bmiba;
+ prd = ctlr->prdt;
+ print("bmicx %2.2uX bmisx %2.2uX prdt %8.8p\n",
+ inb(bmiba+Bmicx), inb(bmiba+Bmisx), prd);
+ for(;;){
+ print("pa 0x%8.8luX count %8.8uX\n",
+ prd->pa, prd->count);
+ if(prd->count & PrdEOT)
+ break;
+ prd++;
+ }
+ }
+}
+
+static int
+atadebug(int cmdport, int ctlport, char* fmt, ...)
+{
+ int i, n;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ if(!(DEBUG & DbgPROBE)){
+ USED(cmdport, ctlport, fmt);
+ return 0;
+ }
+
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+
+ if(cmdport){
+ if(buf[n-1] == '\n')
+ n--;
+ n += snprint(buf+n, PRINTSIZE-n, " ataregs 0x%uX:",
+ cmdport);
+ for(i = Features; i < Command; i++)
+ n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",
+ inb(cmdport+i));
+ if(ctlport)
+ n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",
+ inb(ctlport+As));
+ n += snprint(buf+n, PRINTSIZE-n, "\n");
+ }
+ putstrn(buf, n);
+
+ return n;
+}
+
+static int
+ataready(int cmdport, int ctlport, int dev, int reset, int ready, int micro)
+{
+ int as;
+
+ atadebug(cmdport, ctlport, "ataready: dev %uX reset %uX ready %uX",
+ dev, reset, ready);
+
+ for(;;){
+ /*
+ * Wait for the controller to become not busy and
+ * possibly for a status bit to become true (usually
+ * Drdy). Must change to the appropriate device
+ * register set if necessary before testing for ready.
+ * Always run through the loop at least once so it
+ * can be used as a test for !Bsy.
+ */
+ as = inb(ctlport+As);
+ if((as & reset) == 0){
+ if(dev){
+ outb(cmdport+Dh, dev);
+ dev = 0;
+ }
+ else if(ready == 0 || (as & ready)){
+ atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);
+ return as;
+ }
+ }
+ if(micro-- <= 0){
+ atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);
+ break;
+ }
+ microdelay(4);
+ }
+ atadebug(cmdport, ctlport, "ataready: timeout");
+
+ return -1;
+}
+
+static int
+atacsf(Drive* drive, vlong csf, int supported)
+{
+ ushort *info;
+ int cmdset, i, x;
+
+ if(supported)
+ info = &drive->info[Icsfs];
+ else
+ info = &drive->info[Icsfe];
+
+ for(i = 0; i < 3; i++){
+ x = (csf>>(16*i)) & 0xFFFF;
+ if(x == 0)
+ continue;
+ cmdset = info[i];
+ if(cmdset == 0 || cmdset == 0xFFFF)
+ return 0;
+ return cmdset & x;
+ }
+
+ return 0;
+}
+
+static int
+atadone(void* arg)
+{
+ return ((Ctlr*)arg)->done;
+}
+
+static int
+atarwmmode(Drive* drive, int cmdport, int ctlport, int dev)
+{
+ int as, maxrwm, rwm;
+
+ maxrwm = (drive->info[Imaxrwm] & 0xFF);
+ if(maxrwm == 0)
+ return 0;
+
+ /*
+ * Sometimes drives come up with the current count set
+ * to 0; if so, set a suitable value, otherwise believe
+ * the value in Irwm if the 0x100 bit is set.
+ */
+ if(drive->info[Irwm] & 0x100)
+ rwm = (drive->info[Irwm] & 0xFF);
+ else
+ rwm = 0;
+ if(rwm == 0)
+ rwm = maxrwm;
+ if(rwm > 16)
+ rwm = 16;
+ if(ataready(cmdport, ctlport, dev, Bsy|Drq, Drdy, 102*1000) < 0)
+ return 0;
+ outb(cmdport+Count, rwm);
+ outb(cmdport+Command, Csm);
+ microdelay(4);
+ as = ataready(cmdport, ctlport, 0, Bsy, Drdy|Df|Err, 1000);
+ inb(cmdport+Status);
+ if(as < 0 || (as & (Df|Err)))
+ return 0;
+
+ drive->rwm = rwm;
+
+ return rwm;
+}
+
+static int
+atadmamode(Drive* drive)
+{
+ int dma;
+
+ /*
+ * Check if any DMA mode enabled.
+ * Assumes the BIOS has picked and enabled the best.
+ * This is completely passive at the moment, no attempt is
+ * made to ensure the hardware is correctly set up.
+ */
+ dma = drive->info[Imwdma] & 0x0707;
+ drive->dma = (dma>>8) & dma;
+ if(drive->dma == 0 && (drive->info[Ivalid] & 0x04)){
+ dma = drive->info[Iudma] & 0x1F1F;
+ drive->dma = (dma>>8) & dma;
+ if(drive->dma)
+ drive->dma |= 'U'<<16;
+ }
+
+ return dma;
+}
+
+static int
+ataidentify(int cmdport, int ctlport, int dev, int pkt, void* info)
+{
+ int as, command, drdy;
+
+ if(pkt){
+ command = Cidpkt;
+ drdy = 0;
+ }
+ else{
+ command = Cid;
+ drdy = Drdy;
+ }
+ as = ataready(cmdport, ctlport, dev, Bsy|Drq, drdy, 103*1000);
+ if(as < 0)
+ return as;
+ outb(cmdport+Command, command);
+ microdelay(4);
+
+ as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 400*1000);
+ if(as < 0)
+ return -1;
+ if(as & Err)
+ return as;
+
+ memset(info, 0, 512);
+ inss(cmdport+Data, info, 256);
+ inb(cmdport+Status);
+
+ if(DEBUG & DbgIDENTIFY){
+ int i;
+ ushort *sp;
+
+ sp = (ushort*)info;
+ for(i = 0; i < 32; i++){
+ if(i && (i%16) == 0)
+ print("\n");
+ print(" %4.4uX", *sp);
+ sp++;
+ }
+ print("\n");
+ }
+
+ return 0;
+}
+
+static Drive*
+atadrive(int cmdport, int ctlport, int dev)
+{
+ ushort *sp;
+ Drive *drive;
+ int as, i, pkt;
+ uchar buf[512], *p;
+
+ atadebug(0, 0, "identify: port 0x%uX dev 0x%2.2uX\n", cmdport, dev);
+ pkt = 1;
+retry:
+ as = ataidentify(cmdport, ctlport, dev, pkt, buf);
+ if(as < 0)
+ return nil;
+ if(as & Err){
+ if(pkt == 0)
+ return nil;
+ pkt = 0;
+ goto retry;
+ }
+
+ if((drive = malloc(sizeof(Drive))) == nil)
+ return nil;
+ drive->dev = dev;
+ memmove(drive->info, buf, sizeof(drive->info));
+ drive->sense[0] = 0x70;
+ drive->sense[7] = sizeof(drive->sense)-7;
+
+ drive->inquiry[2] = 2;
+ drive->inquiry[3] = 2;
+ drive->inquiry[4] = sizeof(drive->inquiry)-4;
+ p = &drive->inquiry[8];
+ sp = &drive->info[Imodel];
+ for(i = 0; i < 20; i++){
+ *p++ = *sp>>8;
+ *p++ = *sp++;
+ }
+
+ drive->secsize = 512;
+ if(drive->info[Iconfig] != 0x848A && (drive->info[Iconfig] & 0xC000) == 0x8000){
+ if(drive->info[Iconfig] & 0x01)
+ drive->pkt = 16;
+ else
+ drive->pkt = 12;
+ }
+ else{
+ if(drive->info[Ivalid] & 0x0001){
+ drive->c = drive->info[Ilcyl];
+ drive->h = drive->info[Ilhead];
+ drive->s = drive->info[Ilsec];
+ }
+ else{
+ drive->c = drive->info[Iccyl];
+ drive->h = drive->info[Ichead];
+ drive->s = drive->info[Icsec];
+ }
+ if(drive->info[Icapabilities] & 0x0200){
+ drive->sectors = (drive->info[Ilba1]<<16)
+ |drive->info[Ilba0];
+ drive->dev |= Lba;
+ }
+ else
+ drive->sectors = drive->c*drive->h*drive->s;
+ atarwmmode(drive, cmdport, ctlport, dev);
+ }
+ atadmamode(drive);
+
+ if(DEBUG & DbgCONFIG){
+ print("dev %2.2uX port %uX config %4.4uX capabilities %4.4uX",
+ dev, cmdport,
+ drive->info[Iconfig], drive->info[Icapabilities]);
+ print(" mwdma %4.4uX", drive->info[Imwdma]);
+ if(drive->info[Ivalid] & 0x04)
+ print(" udma %4.4uX", drive->info[Iudma]);
+ print(" dma %8.8uX rwm %ud\n", drive->dma, drive->rwm);
+ }
+
+ return drive;
+}
+
+static void
+atasrst(int ctlport)
+{
+ /*
+ * Srst is a big stick and may cause problems if further
+ * commands are tried before the drives become ready again.
+ * Also, there will be problems here if overlapped commands
+ * are ever supported.
+ */
+ microdelay(20);
+ outb(ctlport+Dc, Srst);
+ microdelay(20);
+ outb(ctlport+Dc, 0);
+ microdelay(4*1000);
+}
+
+static SDev*
+ataprobe(int cmdport, int ctlport, int irq)
+{
+ Ctlr* ctlr;
+ SDev *sdev;
+ Drive *drive;
+ int dev, error, rhi, rlo;
+
+ /*
+ * Try to detect a floating bus.
+ * Bsy should be cleared. If not, see if the cylinder registers
+ * are read/write capable.
+ * If the master fails, try the slave to catch slave-only
+ * configurations.
+ * There's no need to restore the tested registers as they will
+ * be reset on any detected drives by the Cedd command.
+ * All this indicates is that there is at least one drive on the
+ * controller; when the non-existent drive is selected in a
+ * single-drive configuration the registers of the existing drive
+ * are often seen, only command execution fails.
+ */
+ dev = Dev0;
+ if(inb(ctlport+As) & Bsy){
+ outb(cmdport+Dh, dev);
+ microdelay(5);
+trydev1:
+ atadebug(cmdport, ctlport, "ataprobe bsy");
+ outb(cmdport+Cyllo, 0xAA);
+ outb(cmdport+Cylhi, 0x55);
+ outb(cmdport+Sector, 0xFF);
+ rlo = inb(cmdport+Cyllo);
+ rhi = inb(cmdport+Cylhi);
+ if(rlo != 0xAA && (rlo == 0xFF || rhi != 0x55)){
+ if(dev == Dev1){
+release:
+ return nil;
+ }
+ dev = Dev1;
+ if(ataready(cmdport, ctlport, dev, Bsy, 0, 20*1000) < 0)
+ goto trydev1;
+ }
+ }
+
+ /*
+ * Disable interrupts on any detected controllers.
+ */
+ outb(ctlport+Dc, Nien);
+tryedd1:
+ if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 105*1000) < 0){
+ /*
+ * There's something there, but it didn't come up clean,
+ * so try hitting it with a big stick. The timing here is
+ * wrong but this is a last-ditch effort and it sometimes
+ * gets some marginal hardware back online.
+ */
+ atasrst(ctlport);
+ if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 106*1000) < 0)
+ goto release;
+ }
+
+ /*
+ * Can only get here if controller is not busy.
+ * If there are drives Bsy will be set within 400nS,
+ * must wait 2mS before testing Status.
+ * Wait for the command to complete (6 seconds max).
+ */
+ outb(cmdport+Command, Cedd);
+ delay(5);
+ if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 6*1000*1000) < 0)
+ goto release;
+
+ /*
+ * If bit 0 of the error register is set then the selected drive
+ * exists. This is enough to detect single-drive configurations.
+ * However, if the master exists there is no way short of executing
+ * a command to determine if a slave is present.
+ * It appears possible to get here testing Dev0 although it doesn't
+ * exist and the EDD won't take, so try again with Dev1.
+ */
+ error = inb(cmdport+Error);
+ atadebug(cmdport, ctlport, "ataprobe: dev %uX", dev);
+ if((error & ~0x80) != 0x01){
+ if(dev == Dev1)
+ goto release;
+ dev = Dev1;
+ goto tryedd1;
+ }
+
+ /*
+ * At least one drive is known to exist, try to
+ * identify it. If that fails, don't bother checking
+ * any further.
+ * If the one drive found is Dev0 and the EDD command
+ * didn't indicate Dev1 doesn't exist, check for it.
+ */
+ if((drive = atadrive(cmdport, ctlport, dev)) == nil)
+ goto release;
+ if((ctlr = malloc(sizeof(Ctlr))) == nil){
+ free(drive);
+ goto release;
+ }
+ if((sdev = malloc(sizeof(SDev))) == nil){
+ free(ctlr);
+ free(drive);
+ goto release;
+ }
+ drive->ctlr = ctlr;
+ if(dev == Dev0){
+ ctlr->drive[0] = drive;
+#ifdef notdef
+ if(!(error & 0x80)){
+ /*
+ * Always leave Dh pointing to a valid drive,
+ * otherwise a subsequent call to ataready on
+ * this controller may try to test a bogus Status.
+ * Ataprobe is the only place possibly invalid
+ * drives should be selected.
+ */
+ drive = atadrive(cmdport, ctlport, Dev1);
+ if(drive != nil){
+ drive->ctlr = ctlr;
+ ctlr->drive[1] = drive;
+ }
+ else{
+ outb(cmdport+Dh, Dev0);
+ microdelay(1);
+ }
+ }
+#endif
+ }
+ else
+ ctlr->drive[1] = drive;
+
+ ctlr->cmdport = cmdport;
+ ctlr->ctlport = ctlport;
+ ctlr->irq = irq;
+ ctlr->tbdf = -1;
+ ctlr->command = Cedd; /* debugging */
+
+ sdev->ifc = &sdataifc;
+ sdev->ctlr = ctlr;
+ sdev->idno = 'C';
+ sdev->nunit = 1;
+ ctlr->sdev = sdev;
+
+ return sdev;
+}
+
+static int
+atasetsense(Drive* drive, int status, int key, int asc, int ascq)
+{
+ drive->sense[2] = key;
+ drive->sense[12] = asc;
+ drive->sense[13] = ascq;
+
+ return status;
+}
+
+static int
+atastandby(Drive* drive, int period)
+{
+ Ctlr* ctlr;
+ int cmdport, done;
+
+ ctlr = drive->ctlr;
+ drive->command = Cstandby;
+ qlock(ctlr);
+
+ cmdport = ctlr->cmdport;
+ ilock(ctlr);
+ outb(cmdport+Count, period);
+ outb(cmdport+Dh, drive->dev);
+ ctlr->done = 0;
+ ctlr->curdrive = drive;
+ ctlr->command = Cstandby; /* debugging */
+ outb(cmdport+Command, Cstandby);
+ iunlock(ctlr);
+
+ while(waserror())
+ ;
+ tsleep(ctlr, atadone, ctlr, 30*1000);
+ poperror();
+
+ done = ctlr->done;
+ qunlock(ctlr);
+
+ if(!done || (drive->status & Err))
+ return atasetsense(drive, SDcheck, 4, 8, drive->error);
+ 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)
+{
+ Ctlr* ctlr;
+ int as, cmdport, ctlport, timeo;
+
+ /*
+ * Attempt to abort a command by using NOP.
+ * In response, the drive is supposed to set Abrt
+ * in the Error register, set (Drdy|Err) in Status
+ * and clear Bsy when done. However, some drives
+ * (e.g. ATAPI Zip) just go Bsy then clear Status
+ * when done, hence the timeout loop only on Bsy
+ * and the forced setting of drive->error.
+ */
+ ctlr = drive->ctlr;
+ cmdport = ctlr->cmdport;
+ outb(cmdport+Features, subcommand);
+ outb(cmdport+Dh, drive->dev);
+ ctlr->command = Cnop; /* debugging */
+ outb(cmdport+Command, Cnop);
+
+ microdelay(1);
+ ctlport = ctlr->ctlport;
+ for(timeo = 0; timeo < 1000; timeo++){
+ as = inb(ctlport+As);
+ if(!(as & Bsy))
+ break;
+ microdelay(1);
+ }
+ drive->error |= Abrt;
+}
+
+static void
+ataabort(Drive* drive, int dolock)
+{
+ /*
+ * If NOP is available (packet commands) use it otherwise
+ * must try a software reset.
+ */
+ if(dolock)
+ ilock(drive->ctlr);
+ if(atacsf(drive, 0x0000000000004000LL, 0))
+ atanop(drive, 0);
+ else{
+ atasrst(drive->ctlr->ctlport);
+ drive->error |= Abrt;
+ }
+ if(dolock)
+ iunlock(drive->ctlr);
+}
+
+static int
+atadmasetup(Drive* drive, int )
+{
+ drive->dmactl = 0;
+ return -1;
+
+#ifdef notdef
+ Prd *prd;
+ ulong pa;
+ Ctlr *ctlr;
+ int bmiba, bmisx, count;
+
+ 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.
+ */
+ if(prd == nil){
+ drive->dmactl = 0;
+ return -1;
+ }
+
+ for(;;){
+ prd->pa = pa;
+ count = 64*1024 - (pa & 0xFFFF);
+ if(count >= len){
+ prd->count = PrdEOT|(len & 0xFFFF);
+ break;
+ }
+ prd->count = count;
+ len -= count;
+ pa += count;
+ prd++;
+ }
+
+ bmiba = ctlr->bmiba;
+ outl(bmiba+Bmidtpx, PCIWADDR(ctlr->prdt));
+ if(drive->write)
+ outb(ctlr->bmiba+Bmicx, 0);
+ else
+ outb(ctlr->bmiba+Bmicx, Rwcon);
+ bmisx = inb(bmiba+Bmisx);
+ outb(bmiba+Bmisx, bmisx|Ideints|Idedmae);
+
+ return 0;
+#endif
+}
+
+static void
+atadmastart(Ctlr* ctlr, int write)
+{
+ if(write)
+ outb(ctlr->bmiba+Bmicx, Ssbm);
+ else
+ outb(ctlr->bmiba+Bmicx, Rwcon|Ssbm);
+}
+
+static int
+atadmastop(Ctlr* ctlr)
+{
+ int bmiba;
+
+ bmiba = ctlr->bmiba;
+ outb(bmiba+Bmicx, inb(bmiba+Bmicx) & ~Ssbm);
+
+ return inb(bmiba+Bmisx);
+}
+
+static void
+atadmainterrupt(Drive* drive, int count)
+{
+ Ctlr* ctlr;
+ int bmiba, bmisx;
+
+ ctlr = drive->ctlr;
+ bmiba = ctlr->bmiba;
+ bmisx = inb(bmiba+Bmisx);
+ switch(bmisx & (Ideints|Idedmae|Bmidea)){
+ case Bmidea:
+ /*
+ * Data transfer still in progress, nothing to do
+ * (this should never happen).
+ */
+ return;
+
+ case Ideints:
+ case Ideints|Bmidea:
+ /*
+ * Normal termination, tidy up.
+ */
+ drive->data += count;
+ break;
+
+ default:
+ /*
+ * What's left are error conditions (memory transfer
+ * problem) and the device is not done but the PRD is
+ * exhausted. For both cases must somehow tell the
+ * drive to abort.
+ */
+ ataabort(drive, 0);
+ break;
+ }
+ atadmastop(ctlr);
+ ctlr->done = 1;
+}
+
+static void
+atapktinterrupt(Drive* drive)
+{
+ Ctlr* ctlr;
+ int cmdport, len;
+
+ ctlr = drive->ctlr;
+ cmdport = ctlr->cmdport;
+ switch(inb(cmdport+Ir) & (/*Rel|*/Io|Cd)){
+ case Cd:
+ outss(cmdport+Data, drive->pktcmd, drive->pkt/2);
+ break;
+
+ case 0:
+ len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
+ if(drive->data+len > drive->limit){
+ atanop(drive, 0);
+ break;
+ }
+ outss(cmdport+Data, drive->data, len/2);
+ drive->data += len;
+ break;
+
+ case Io:
+ len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
+ if(drive->data+len > drive->limit){
+ atanop(drive, 0);
+ break;
+ }
+ inss(cmdport+Data, drive->data, len/2);
+ drive->data += len;
+ break;
+
+ case Io|Cd:
+ if(drive->pktdma)
+ atadmainterrupt(drive, drive->dlen);
+ else
+ ctlr->done = 1;
+ break;
+ }
+}
+
+static int
+atapktio(Drive* drive, uchar* cmd, int clen)
+{
+ Ctlr *ctlr;
+ int as, cmdport, ctlport, len, r, timeo;
+
+ if(cmd[0] == 0x5A && (cmd[2] & 0x3F) == 0)
+ return atamodesense(drive, cmd);
+
+ r = SDok;
+
+ drive->command = Cpkt;
+ memmove(drive->pktcmd, cmd, clen);
+ memset(drive->pktcmd+clen, 0, drive->pkt-clen);
+ drive->limit = drive->data+drive->dlen;
+
+ ctlr = drive->ctlr;
+ cmdport = ctlr->cmdport;
+ ctlport = ctlr->ctlport;
+
+ qlock(ctlr);
+
+ if(ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 107*1000) < 0){
+ qunlock(ctlr);
+ return -1;
+ }
+
+ ilock(ctlr);
+ if(drive->dlen && drive->dmactl && !atadmasetup(drive, drive->dlen))
+ drive->pktdma = Dma;
+ else
+ drive->pktdma = 0;
+
+ outb(cmdport+Features, drive->pktdma);
+ outb(cmdport+Count, 0);
+ outb(cmdport+Sector, 0);
+ len = 16*drive->secsize;
+ outb(cmdport+Bytelo, len);
+ outb(cmdport+Bytehi, len>>8);
+ outb(cmdport+Dh, drive->dev);
+ ctlr->done = 0;
+ ctlr->curdrive = drive;
+ ctlr->command = Cpkt; /* debugging */
+ if(drive->pktdma)
+ atadmastart(ctlr, drive->write);
+ outb(cmdport+Command, Cpkt);
+
+ if((drive->info[Iconfig] & 0x0060) != 0x0020){
+ microdelay(1);
+ as = ataready(cmdport, ctlport, 0, Bsy, Drq|Chk, 4*1000);
+ if(as < 0)
+ r = SDtimeout;
+ else if(as & Chk)
+ r = SDcheck;
+ else
+ atapktinterrupt(drive);
+ }
+ iunlock(ctlr);
+
+ while(waserror())
+ ;
+ if(!drive->pktdma)
+ sleep(ctlr, atadone, ctlr);
+ else for(timeo = 0; !ctlr->done; timeo++){
+ tsleep(ctlr, atadone, ctlr, 1000);
+ if(ctlr->done)
+ break;
+ ilock(ctlr);
+ atadmainterrupt(drive, 0);
+ if(!drive->error && timeo > 10){
+ ataabort(drive, 0);
+ atadmastop(ctlr);
+ drive->dmactl = 0;
+ drive->error |= Abrt;
+ }
+ if(drive->error){
+ drive->status |= Chk;
+ ctlr->curdrive = nil;
+ }
+ iunlock(ctlr);
+ }
+ poperror();
+
+ qunlock(ctlr);
+
+ if(drive->status & Chk)
+ r = SDcheck;
+
+ return r;
+}
+
+static int
+atageniostart(Drive* drive, int lba)
+{
+ Ctlr *ctlr;
+ int as, c, cmdport, ctlport, h, len, s;
+
+ if(drive->dev & Lba){
+ c = (lba>>8) & 0xFFFF;
+ h = (lba>>24) & 0x0F;
+ s = lba & 0xFF;
+ }
+ else{
+ c = lba/(drive->s*drive->h);
+ h = ((lba/drive->s) % drive->h);
+ s = (lba % drive->s) + 1;
+ }
+
+ ctlr = drive->ctlr;
+ cmdport = ctlr->cmdport;
+ ctlport = ctlr->ctlport;
+ if(ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 101*1000) < 0)
+ return -1;
+
+ ilock(ctlr);
+ if(drive->dmactl && !atadmasetup(drive, drive->count*drive->secsize)){
+ if(drive->write)
+ drive->command = Cwd;
+ else
+ drive->command = Crd;
+ }
+ else if(drive->rwmctl){
+ drive->block = drive->rwm*drive->secsize;
+ if(drive->write)
+ drive->command = Cwsm;
+ else
+ drive->command = Crsm;
+ }
+ else{
+ drive->block = drive->secsize;
+ if(drive->write)
+ drive->command = Cws;
+ else
+ drive->command = Crs;
+ }
+ drive->limit = drive->data + drive->count*drive->secsize;
+
+ outb(cmdport+Count, drive->count);
+ outb(cmdport+Sector, s);
+ outb(cmdport+Dh, drive->dev|h);
+ outb(cmdport+Cyllo, c);
+ outb(cmdport+Cylhi, c>>8);
+ ctlr->done = 0;
+ ctlr->curdrive = drive;
+ ctlr->command = drive->command; /* debugging */
+ outb(cmdport+Command, drive->command);
+
+ switch(drive->command){
+ case Cws:
+ case Cwsm:
+ microdelay(1);
+ as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 1000);
+ if(as < 0 || (as & Err)){
+ iunlock(ctlr);
+ return -1;
+ }
+ len = drive->block;
+ if(drive->data+len > drive->limit)
+ len = drive->limit-drive->data;
+ outss(cmdport+Data, drive->data, len/2);
+ break;
+
+ case Crd:
+ case Cwd:
+ atadmastart(ctlr, drive->write);
+ break;
+ }
+ iunlock(ctlr);
+
+ return 0;
+}
+
+static int
+atagenioretry(Drive* drive)
+{
+ if(drive->dmactl)
+ drive->dmactl = 0;
+ else if(drive->rwmctl)
+ drive->rwmctl = 0;
+ else
+ return atasetsense(drive, SDcheck, 4, 8, drive->error);
+
+ return SDretry;
+}
+
+static int
+atagenio(Drive* drive, uchar* cmd, int)
+{
+ uchar *p;
+ Ctlr *ctlr;
+ int count, lba, len;
+
+ /*
+ * Map SCSI commands into ATA commands for discs.
+ * Fail any command with a LUN except INQUIRY which
+ * will return 'logical unit not supported'.
+ */
+ if((cmd[1]>>5) && cmd[0] != 0x12)
+ return atasetsense(drive, SDcheck, 0x05, 0x25, 0);
+
+ switch(cmd[0]){
+ default:
+ return atasetsense(drive, SDcheck, 0x05, 0x20, 0);
+
+ case 0x00: /* test unit ready */
+ return SDok;
+
+ case 0x03: /* request sense */
+ if(cmd[4] < sizeof(drive->sense))
+ len = cmd[4];
+ else
+ len = sizeof(drive->sense);
+ if(drive->data && drive->dlen >= len){
+ memmove(drive->data, drive->sense, len);
+ drive->data += len;
+ }
+ return SDok;
+
+ case 0x12: /* inquiry */
+ if(cmd[4] < sizeof(drive->inquiry))
+ len = cmd[4];
+ else
+ len = sizeof(drive->inquiry);
+ if(drive->data && drive->dlen >= len){
+ memmove(drive->data, drive->inquiry, len);
+ drive->data += len;
+ }
+ return SDok;
+
+ case 0x1B: /* start/stop unit */
+ /*
+ * NOP for now, can use the power management feature
+ * set later.
+ */
+ return SDok;
+
+ case 0x25: /* read capacity */
+ if((cmd[1] & 0x01) || cmd[2] || cmd[3])
+ return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
+ if(drive->data == nil || drive->dlen < 8)
+ return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
+ /*
+ * Read capacity returns the LBA of the last sector.
+ */
+ len = drive->sectors-1;
+ p = drive->data;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p++ = len;
+ len = drive->secsize;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p = len;
+ drive->data += 8;
+ return SDok;
+
+ case 0x28: /* read */
+ case 0x2A: /* write */
+ break;
+
+ case 0x5A:
+ return atamodesense(drive, cmd);
+ }
+
+ ctlr = drive->ctlr;
+ lba = (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5];
+ count = (cmd[7]<<8)|cmd[8];
+ if(drive->data == nil)
+ return SDok;
+ if(drive->dlen < count*drive->secsize)
+ count = drive->dlen/drive->secsize;
+ qlock(ctlr);
+ while(count){
+ if(count > 256)
+ drive->count = 256;
+ else
+ drive->count = count;
+ if(atageniostart(drive, lba)){
+ ilock(ctlr);
+ atanop(drive, 0);
+ iunlock(ctlr);
+ qunlock(ctlr);
+ return atagenioretry(drive);
+ }
+
+ while(waserror())
+ ;
+ tsleep(ctlr, atadone, ctlr, 30*1000);
+ poperror();
+ if(!ctlr->done){
+ /*
+ * What should the above timeout be? In
+ * standby and sleep modes it could take as
+ * long as 30 seconds for a drive to respond.
+ * Very hard to get out of this cleanly.
+ */
+ atadumpstate(drive, cmd, lba, count);
+ ataabort(drive, 1);
+ qunlock(ctlr);
+ return atagenioretry(drive);
+ }
+
+ if(drive->status & Err){
+ qunlock(ctlr);
+ return atasetsense(drive, SDcheck, 4, 8, drive->error);
+ }
+ count -= drive->count;
+ lba += drive->count;
+ }
+ qunlock(ctlr);
+
+ return SDok;
+}
+
+static int
+atario(SDreq* r)
+{
+ Ctlr *ctlr;
+ Drive *drive;
+ SDunit *unit;
+ uchar cmd10[10], *cmdp, *p;
+ int clen, reqstatus, status;
+
+ unit = r->unit;
+ if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil){
+ r->status = SDtimeout;
+ return SDtimeout;
+ }
+ drive = ctlr->drive[unit->subno];
+
+ /*
+ * Most SCSI commands can be passed unchanged except for
+ * the padding on the end. The few which require munging
+ * are not used internally. Mode select/sense(6) could be
+ * converted to the 10-byte form but it's not worth the
+ * effort. Read/write(6) are easy.
+ */
+ switch(r->cmd[0]){
+ case 0x08: /* read */
+ case 0x0A: /* write */
+ cmdp = cmd10;
+ memset(cmdp, 0, sizeof(cmd10));
+ cmdp[0] = r->cmd[0]|0x20;
+ cmdp[1] = r->cmd[1] & 0xE0;
+ cmdp[5] = r->cmd[3];
+ cmdp[4] = r->cmd[2];
+ cmdp[3] = r->cmd[1] & 0x0F;
+ cmdp[8] = r->cmd[4];
+ clen = sizeof(cmd10);
+ break;
+
+ default:
+ cmdp = r->cmd;
+ clen = r->clen;
+ break;
+ }
+
+ qlock(drive);
+retry:
+ drive->write = r->write;
+ drive->data = r->data;
+ drive->dlen = r->dlen;
+
+ drive->status = 0;
+ drive->error = 0;
+ if(drive->pkt)
+ status = atapktio(drive, cmdp, clen);
+ else
+ status = atagenio(drive, cmdp, clen);
+ if(status == SDretry){
+ if(DbgDEBUG)
+ print("%s: retry: dma %8.8uX rwm %4.4uX\n",
+ unit->name, drive->dmactl, drive->rwmctl);
+ goto retry;
+ }
+ if(status == SDok){
+ atasetsense(drive, SDok, 0, 0, 0);
+ if(drive->data){
+ p = r->data;
+ r->rlen = drive->data - p;
+ }
+ else
+ r->rlen = 0;
+ }
+ else if(status == SDcheck && !(r->flags & SDnosense)){
+ drive->write = 0;
+ memset(cmd10, 0, sizeof(cmd10));
+ cmd10[0] = 0x03;
+ cmd10[1] = r->lun<<5;
+ cmd10[4] = sizeof(r->sense)-1;
+ drive->data = r->sense;
+ drive->dlen = sizeof(r->sense)-1;
+ drive->status = 0;
+ drive->error = 0;
+ if(drive->pkt)
+ reqstatus = atapktio(drive, cmd10, 6);
+ else
+ reqstatus = atagenio(drive, cmd10, 6);
+ if(reqstatus == SDok){
+ r->flags |= SDvalidsense;
+ atasetsense(drive, SDok, 0, 0, 0);
+ }
+ }
+ qunlock(drive);
+ r->status = status;
+ if(status != SDok)
+ return status;
+
+ /*
+ * Fix up any results.
+ * Many ATAPI CD-ROMs ignore the LUN field completely and
+ * return valid INQUIRY data. Patch the response to indicate
+ * 'logical unit not supported' if the LUN is non-zero.
+ */
+ switch(cmdp[0]){
+ case 0x12: /* inquiry */
+ if((p = r->data) == nil)
+ break;
+ if((cmdp[1]>>5) && (!drive->pkt || (p[0] & 0x1F) == 0x05))
+ p[0] = 0x7F;
+ /*FALLTHROUGH*/
+ default:
+ break;
+ }
+
+ return SDok;
+}
+
+
+static void
+atainterrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Drive *drive;
+ int cmdport, len, status;
+
+ ctlr = arg;
+
+ ilock(ctlr);
+ if(inb(ctlr->ctlport+As) & Bsy){
+ iunlock(ctlr);
+ if(DEBUG & DbgDEBUG)
+ print("IBsy+");
+ return;
+ }
+ cmdport = ctlr->cmdport;
+ status = inb(cmdport+Status);
+ if((drive = ctlr->curdrive) == nil){
+ iunlock(ctlr);
+ if((DEBUG & DbgDEBUG) && ctlr->command != Cedd)
+ print("Inil%2.2uX/%2.2uX+", ctlr->command, status);
+ return;
+ }
+
+ if(status & Err)
+ drive->error = inb(cmdport+Error);
+ else switch(drive->command){
+ default:
+ drive->error = Abrt;
+ break;
+
+ case Crs:
+ case Crsm:
+ if(!(status & Drq)){
+ drive->error = Abrt;
+ break;
+ }
+ len = drive->block;
+ if(drive->data+len > drive->limit)
+ len = drive->limit-drive->data;
+ inss(cmdport+Data, drive->data, len/2);
+ drive->data += len;
+ if(drive->data >= drive->limit)
+ ctlr->done = 1;
+ break;
+
+ case Cws:
+ case Cwsm:
+ len = drive->block;
+ if(drive->data+len > drive->limit)
+ len = drive->limit-drive->data;
+ drive->data += len;
+ if(drive->data >= drive->limit){
+ ctlr->done = 1;
+ break;
+ }
+ if(!(status & Drq)){
+ drive->error = Abrt;
+ break;
+ }
+ len = drive->block;
+ if(drive->data+len > drive->limit)
+ len = drive->limit-drive->data;
+ outss(cmdport+Data, drive->data, len/2);
+ break;
+
+ case Cpkt:
+ atapktinterrupt(drive);
+ break;
+
+ case Crd:
+ case Cwd:
+ atadmainterrupt(drive, drive->count*drive->secsize);
+ break;
+
+ case Cstandby:
+ ctlr->done = 1;
+ break;
+ }
+ iunlock(ctlr);
+
+ if(drive->error){
+ status |= Err;
+ ctlr->done = 1;
+ }
+
+ if(ctlr->done){
+ ctlr->curdrive = nil;
+ drive->status = status;
+ wakeup(ctlr);
+ }
+}
+
+#ifdef notdef
+static SDev*
+atapnp(void)
+{
+ int cmdport;
+ int ctlport;
+ int irq;
+
+ cmdport = 0x200;
+ ctlport = cmdport + 0x0C;
+ irq = 10;
+ return ataprobe(cmdport, ctlport, irq);
+}
+#endif
+
+
+static SDev*
+atalegacy(int port, int irq)
+{
+ return ataprobe(port, port+0x204, irq);
+}
+
+static int ataitype;
+static int atairq;
+static int
+ataenable(SDev* sdev)
+{
+ Ctlr *ctlr;
+ char name[KNAMELEN];
+
+ ctlr = sdev->ctlr;
+
+ if(ctlr->bmiba){
+ ctlr->prdt = xspanalloc(Nprd*sizeof(Prd), 4, 4*1024);
+ }
+ snprint(name, KNAMELEN, "%s (%s)", sdev->name, sdev->ifc->name);
+// intrenable(ctlr->irq, atainterrupt, ctlr, ctlr->tbdf, name);
+ outb(ctlr->ctlport+Dc, 0);
+ intrenable(ataitype, atairq, atainterrupt, ctlr, name);
+ if(ctlr->ienable)
+ ctlr->ienable(ctlr);
+
+ return 1;
+}
+
+static int
+atarctl(SDunit* unit, char* p, int l)
+{
+ int n;
+ Ctlr *ctlr;
+ Drive *drive;
+
+ if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil)
+ return 0;
+ drive = ctlr->drive[unit->subno];
+
+ qlock(drive);
+ n = snprint(p, l, "config %4.4uX capabilities %4.4uX",
+ drive->info[Iconfig], drive->info[Icapabilities]);
+ if(drive->dma)
+ n += snprint(p+n, l-n, " dma %8.8uX dmactl %8.8uX",
+ drive->dma, drive->dmactl);
+ if(drive->rwm)
+ n += snprint(p+n, l-n, " rwm %ud rwmctl %ud",
+ drive->rwm, drive->rwmctl);
+ n += snprint(p+n, l-n, "\n");
+ if(unit->sectors){
+ n += snprint(p+n, l-n, "geometry %llud %ld",
+ unit->sectors, unit->secsize);
+ if(drive->pkt == 0)
+ n += snprint(p+n, l-n, " %d %d %d",
+ drive->c, drive->h, drive->s);
+ n += snprint(p+n, l-n, "\n");
+ }
+ qunlock(drive);
+
+ return n;
+}
+
+static int
+atawctl(SDunit* unit, Cmdbuf* cb)
+{
+ int period;
+ Ctlr *ctlr;
+ Drive *drive;
+
+ if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil)
+ return 0;
+ drive = ctlr->drive[unit->subno];
+
+ qlock(drive);
+ if(waserror()){
+ qunlock(drive);
+ nexterror();
+ }
+
+ /*
+ * Dma and rwm control is passive at the moment,
+ * i.e. it is assumed that the hardware is set up
+ * correctly already either by the BIOS or when
+ * the drive was initially identified.
+ */
+ if(strcmp(cb->f[0], "dma") == 0){
+ if(cb->nf != 2 || drive->dma == 0)
+ error(Ebadctl);
+ if(strcmp(cb->f[1], "on") == 0)
+ drive->dmactl = drive->dma;
+ else if(strcmp(cb->f[1], "off") == 0)
+ drive->dmactl = 0;
+ else
+ error(Ebadctl);
+ }
+ else if(strcmp(cb->f[0], "rwm") == 0){
+ if(cb->nf != 2 || drive->rwm == 0)
+ error(Ebadctl);
+ if(strcmp(cb->f[1], "on") == 0)
+ drive->rwmctl = drive->rwm;
+ else if(strcmp(cb->f[1], "off") == 0)
+ drive->rwmctl = 0;
+ else
+ error(Ebadctl);
+ }
+ else if(strcmp(cb->f[0], "standby") == 0){
+ switch(cb->nf){
+ default:
+ error(Ebadctl);
+ case 2:
+ period = strtol(cb->f[1], 0, 0);
+ if(period && (period < 30 || period > 240*5))
+ error(Ebadctl);
+ period /= 5;
+ break;
+ }
+ if(atastandby(drive, period) != SDok)
+ error(Ebadctl);
+ }
+ else
+ error(Ebadctl);
+ qunlock(drive);
+ poperror();
+
+ return 0;
+}
+
+static int
+scsitest(SDreq* r)
+{
+ r->write = 0;
+ memset(r->cmd, 0, sizeof(r->cmd));
+ r->cmd[1] = r->lun<<5;
+ r->clen = 6;
+ r->data = nil;
+ r->dlen = 0;
+ r->flags = 0;
+
+ r->status = ~0;
+
+ return r->unit->dev->ifc->rio(r);
+}
+
+static int
+scsirio(SDreq* r)
+{
+ /*
+ * Perform an I/O request, returning
+ * -1 failure
+ * 0 ok
+ * 1 no medium present
+ * 2 retry
+ * The contents of r may be altered so the
+ * caller should re-initialise if necesary.
+ */
+ r->status = ~0;
+ switch(r->unit->dev->ifc->rio(r)){
+ default:
+ break;
+ case SDcheck:
+ if(!(r->flags & SDvalidsense))
+ break;
+ switch(r->sense[2] & 0x0F){
+ case 0x00: /* no sense */
+ case 0x01: /* recovered error */
+ return 2;
+ case 0x06: /* check condition */
+ /*
+ * 0x28 - not ready to ready transition,
+ * medium may have changed.
+ * 0x29 - power on or some type of reset.
+ */
+ if(r->sense[12] == 0x28 && r->sense[13] == 0)
+ return 2;
+ if(r->sense[12] == 0x29)
+ return 2;
+ break;
+ case 0x02: /* not ready */
+ /*
+ * If no medium present, bail out.
+ * If unit is becoming ready, rather than not
+ * not ready, wait a little then poke it again. */
+ if(r->sense[12] == 0x3A)
+ break;
+ if(r->sense[12] != 0x04 || r->sense[13] != 0x01)
+ break;
+
+ while(waserror())
+ ;
+ tsleep(&up->sleep, return0, 0, 500);
+ poperror();
+ scsitest(r);
+ return 2;
+ default:
+ break;
+ }
+ break;
+ case SDok:
+ return 0;
+ }
+ return -1;
+}
+
+
+static int
+ataverify(SDunit* unit)
+{
+ SDreq *r;
+ int i, status;
+ uchar *inquiry;
+
+ if((r = malloc(sizeof(SDreq))) == nil)
+ return 0;
+ if((inquiry = sdmalloc(sizeof(unit->inquiry))) == nil){
+ free(r);
+ return 0;
+ }
+ r->unit = unit;
+ r->lun = 0; /* ??? */
+
+ memset(unit->inquiry, 0, sizeof(unit->inquiry));
+ r->write = 0;
+ r->cmd[0] = 0x12;
+ r->cmd[1] = r->lun<<5;
+ r->cmd[4] = sizeof(unit->inquiry)-1;
+ r->clen = 6;
+ r->data = inquiry;
+ r->dlen = sizeof(unit->inquiry)-1;
+ r->flags = 0;
+
+ r->status = ~0;
+ if(unit->dev->ifc->rio(r) != SDok){
+ free(r);
+ return 0;
+ }
+ memmove(unit->inquiry, inquiry, r->dlen);
+ free(inquiry);
+
+ SET(status);
+ for(i = 0; i < 3; i++){
+ while((status = scsitest(r)) == SDbusy)
+ ;
+ if(status == SDok || status != SDcheck)
+ break;
+ if(!(r->flags & SDvalidsense))
+ break;
+ if((r->sense[2] & 0x0F) != 0x02)
+ continue;
+ /*
+ * Unit is 'not ready'.
+ * If it needs an initialising command, set status
+ * so it will be spun-up below.
+ * If there's no medium, that's OK too, but don't
+ * try to spin it up.
+ */
+ if(r->sense[12] == 0x04 && r->sense[13] == 0x02){
+ status = SDok;
+ break;
+ }
+ if(r->sense[12] == 0x3A)
+ break;
+ }
+
+ if(status == SDok){
+ /*
+ * Try to ensure a direct-access device is spinning.
+ * Don't wait for completion, ignore the result.
+ */
+ if((unit->inquiry[0] & 0x1F) == 0){
+ memset(r->cmd, 0, sizeof(r->cmd));
+ r->write = 0;
+ r->cmd[0] = 0x1B;
+ r->cmd[1] = (r->lun<<5)|0x01;
+ r->cmd[4] = 1;
+ r->clen = 6;
+ r->data = nil;
+ r->dlen = 0;
+ r->flags = 0;
+
+ r->status = ~0;
+ unit->dev->ifc->rio(r);
+ }
+ }
+ free(r);
+
+ if(status == SDok || status == SDcheck)
+ return 1;
+ return 0;
+}
+
+static int
+ataonline(SDunit* unit)
+{
+ SDreq *r;
+ uchar *p;
+ int ok, retries;
+
+ if((r = malloc(sizeof(SDreq))) == nil)
+ return 0;
+ if((p = sdmalloc(8)) == nil){
+ free(r);
+ return 0;
+ }
+
+ ok = 0;
+
+ r->unit = unit;
+ r->lun = 0; /* ??? */
+ for(retries = 0; retries < 10; retries++){
+ /*
+ * Read-capacity is mandatory for DA, WORM, CD-ROM and
+ * MO. It may return 'not ready' if type DA is not
+ * spun up, type MO or type CD-ROM are not loaded or just
+ * plain slow getting their act together after a reset.
+ */
+ r->write = 0;
+ memset(r->cmd, 0, sizeof(r->cmd));
+ r->cmd[0] = 0x25;
+ r->cmd[1] = r->lun<<5;
+ r->clen = 10;
+ r->data = p;
+ r->dlen = 8;
+ r->flags = 0;
+
+ r->status = ~0;
+ switch(scsirio(r)){
+ default:
+ break;
+ case 0:
+ unit->sectors = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
+ /*
+ * Read-capacity returns the LBA of the last sector,
+ * therefore the number of sectors must be incremented.
+ */
+ unit->sectors++;
+ unit->secsize = (p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7];
+
+ /*
+ * Some ATAPI CD readers lie about the block size.
+ * Since we don't read audio via this interface
+ * it's okay to always fudge this.
+ */
+ if(unit->secsize == 2352)
+ unit->secsize = 2048;
+ ok = 1;
+ break;
+ case 1:
+ ok = 1;
+ break;
+ case 2:
+ continue;
+ }
+ break;
+ }
+ free(p);
+ free(r);
+
+ if(ok)
+ return ok+retries;
+ else
+ return 0;
+}
+
+static long
+atabio(SDunit* unit, int lun, int write, void* data, long nb, uvlong bno)
+{
+ SDreq *r;
+ long rlen;
+
+ if((r = malloc(sizeof(SDreq))) == nil)
+ error(Enomem);
+ r->unit = unit;
+ r->lun = lun;
+again:
+ r->write = write;
+ if(write == 0)
+ r->cmd[0] = 0x28;
+ else
+ r->cmd[0] = 0x2A;
+ r->cmd[1] = (lun<<5);
+ r->cmd[2] = bno>>24;
+ r->cmd[3] = bno>>16;
+ r->cmd[4] = bno>>8;
+ r->cmd[5] = bno;
+ r->cmd[6] = 0;
+ r->cmd[7] = nb>>8;
+ r->cmd[8] = nb;
+ r->cmd[9] = 0;
+ r->clen = 10;
+ r->data = data;
+ r->dlen = nb*unit->secsize;
+ r->flags = 0;
+
+ r->status = ~0;
+ switch(scsirio(r)){
+ default:
+ rlen = -1;
+ break;
+ case 0:
+ rlen = r->rlen;
+ break;
+ case 2:
+ rlen = -1;
+ if(!(r->flags & SDvalidsense))
+ break;
+ switch(r->sense[2] & 0x0F){
+ default:
+ break;
+ case 0x06: /* check condition */
+ /*
+ * Check for a removeable media change.
+ * If so, mark it by zapping the geometry info
+ * to force an online request.
+ */
+ if(r->sense[12] != 0x28 || r->sense[13] != 0)
+ break;
+ if(unit->inquiry[1] & 0x80)
+ unit->sectors = 0;
+ break;
+ case 0x02: /* not ready */
+ /*
+ * If unit is becoming ready,
+ * rather than not not ready, try again.
+ */
+ if(r->sense[12] == 0x04 && r->sense[13] == 0x01)
+ goto again;
+ break;
+ }
+ break;
+ }
+ free(r);
+
+ return rlen;
+}
+
+
+struct Try {
+ int p;
+ int c;
+} tries[] = {
+ { 0, 0x0c },
+ { 0, 0 },
+};
+
+static SDev*
+ataprobew(DevConf *cf)
+{
+ int cmdport;
+ int ctlport;
+ int irq;
+ SDev* rc;
+ struct Try *try;
+
+ rc = nil;
+ for (try = &tries[0]; try->p != 0 || try->c != 0; try++){
+ ataitype = cf->itype;
+ atairq = cf->intnum;
+ cmdport = cf->ports[0].port + try->p;
+ ctlport = cmdport + try->c;
+ irq = cf->intnum;
+ rc = ataprobe(cmdport, ctlport, irq);
+ if (rc)
+ break;
+ }
+ return rc;
+}
+
+static void
+ataclear(SDev *sdev)
+{
+ Ctlr* ctlr;
+
+ ctlr = sdev->ctlr;
+
+ if (ctlr->drive[0])
+ free(ctlr->drive[0]);
+ if (ctlr->drive[1])
+ free(ctlr->drive[1]);
+ if (sdev->name)
+ free(sdev->name);
+ if (sdev->unitflg)
+ free(sdev->unitflg);
+ if (sdev->unit)
+ free(sdev->unit);
+ free(ctlr);
+ free(sdev);
+}
+
+static char *
+atastat(SDev *sdev, char *p, char *e)
+{
+ Ctlr *ctlr = sdev->ctlr;
+
+ return seprint(p, e, "%s ata port %X ctl %X irq %d\n",
+ sdev->name, ctlr->cmdport, ctlr->ctlport, ctlr->irq);
+}
+
+
+SDifc sdataifc = {
+ "ata", /* name */
+
+ nil, /* pnp */
+ atalegacy, /* legacy */
+ ataenable, /* enable */
+ nil, /* disable */
+
+ ataverify, /* verify */
+ ataonline, /* online */
+ atario, /* rio */
+ atarctl, /* rctl */
+ atawctl, /* wctl */
+
+ atabio, /* bio */
+ ataprobew, /* probew */
+ ataclear, /* clear */
+ atastat, /* stat */
+};
+
diff --git a/sys/src/9/bitsy/tar.c b/sys/src/9/bitsy/tar.c
new file mode 100755
index 000000000..88171e6bc
--- /dev/null
+++ b/sys/src/9/bitsy/tar.c
@@ -0,0 +1,81 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+typedef union Hblock Hblock;
+
+#define TBLOCK 512
+#define NAMSIZ 100
+union Hblock
+{
+ char dummy[TBLOCK];
+ struct header
+ {
+ char name[NAMSIZ];
+ char mode[8];
+ char uid[8];
+ char gid[8];
+ char size[12];
+ char mtime[12];
+ char chksum[8];
+ char linkflag;
+ char linkname[NAMSIZ];
+ } dbuf;
+};
+
+static int getdir(Hblock *hb, Dir *sp);
+static int checksum(Hblock *hb);
+
+uchar*
+tarlookup(uchar *addr, char *file, int *dlen)
+{
+ Hblock *hp;
+ Dir dir;
+
+ hp = (Hblock*)addr;
+ while(getdir(hp, &dir) != 0) {
+ if(strcmp(file, hp->dbuf.name) == 0) {
+ *dlen = dir.length;
+ return (uchar*)(hp+1);
+ }
+ hp += (dir.length+TBLOCK-1)/TBLOCK + 1;
+ }
+ return 0;
+}
+
+static int
+getdir(Hblock *hp, Dir *sp)
+{
+ int chksum;
+
+ if (hp->dbuf.name[0] == '\0')
+ return 0;
+ sp->length = strtol(hp->dbuf.size, 0, 8);
+ sp->mtime = strtol(hp->dbuf.mtime, 0, 8);
+ chksum = strtol(hp->dbuf.chksum, 0, 8);
+ if (chksum != checksum(hp)) {
+ print("directory checksum error\n");
+ return 0;
+ }
+ return 1;
+}
+
+static int
+checksum(Hblock *hp)
+{
+ int i;
+ char *cp;
+
+ i = 0;
+ for (cp = hp->dummy; cp < &hp->dummy[TBLOCK]; cp++) {
+ if(cp < hp->dbuf.chksum || cp >= &hp->dbuf.chksum[sizeof(hp->dbuf.chksum)])
+ i += *cp & 0xff;
+ else
+ i += ' ' & 0xff;
+ }
+ return(i);
+}
diff --git a/sys/src/9/bitsy/trap.c b/sys/src/9/bitsy/trap.c
new file mode 100755
index 000000000..2b8f80973
--- /dev/null
+++ b/sys/src/9/bitsy/trap.c
@@ -0,0 +1,929 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+#include "tos.h"
+
+Intrregs *intrregs;
+
+typedef struct Vctl {
+ Vctl* next; /* handlers on this vector */
+ char *name; /* of driver, xallocated */
+ void (*f)(Ureg*, void*); /* handler to call */
+ void* a; /* argument to call it with */
+} Vctl;
+
+static Lock vctllock;
+static Vctl *vctl[32];
+static Vctl *gpiovctl[27];
+static int gpioirqref[12];
+
+/*
+ * Layout at virtual address 0.
+ */
+typedef struct Vpage0 {
+ void (*vectors[8])(void);
+ ulong vtable[8];
+} Vpage0;
+Vpage0 *vpage0;
+
+static int irq(Ureg*);
+static void gpiointr(Ureg*, void*);
+
+/* recover state after power suspend
+ * NB: to help debugging bad suspend code,
+ * I changed some prints below to iprints,
+ * to avoid deadlocks when a panic is being
+ * issued during the suspend/resume handler.
+ */
+void
+trapresume(void)
+{
+ vpage0 = (Vpage0*)EVECTORS;
+ memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
+ memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
+ wbflush();
+ mappedIvecEnable();
+}
+
+/*
+ * set up for exceptions
+ */
+void
+trapinit(void)
+{
+ /* set up the exception vectors */
+ vpage0 = (Vpage0*)EVECTORS;
+ memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
+ memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
+
+ wbflush();
+
+ /* use exception vectors at 0xFFFF0000 */
+ mappedIvecEnable();
+
+ /* set up the stacks for the interrupt modes */
+ setr13(PsrMfiq, m->sfiq);
+ setr13(PsrMirq, m->sirq);
+ setr13(PsrMabt, m->sabt);
+ setr13(PsrMund, m->sund);
+
+ /* map in interrupt registers */
+ intrregs = mapspecial(INTRREGS, sizeof(*intrregs));
+
+ /* make all interrupts IRQ (i.e. not FIQ) and disable all interrupts */
+ intrregs->iclr = 0;
+ intrregs->icmr = 0;
+
+ /* turn off all gpio interrupts */
+ gpioregs->rising = 0;
+ gpioregs->falling = 0;
+ gpioregs->edgestatus = gpioregs->edgestatus;
+
+ /* allow all enabled interrupts to take processor out of sleep mode */
+ intrregs->iccr = 0;
+}
+
+void
+trapdump(char *tag)
+{
+ iprint("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n",
+ tag, intrregs->icip, intrregs->icmr, intrregs->iclr,
+ intrregs->iccr, intrregs->icfp);
+}
+
+void
+warnregs(Ureg *ur, char *tag)
+{
+ char buf[1024];
+ char *e = buf+sizeof(buf);
+ char *p;
+
+ p = seprint(buf, e, "%s:\n", tag);
+ p = seprint(p, e, "type 0x%.8lux psr 0x%.8lux pc 0x%.8lux\n",
+ ur->type, ur->psr, ur->pc);
+ p = seprint(p, e, "r0 0x%.8lux r1 0x%.8lux r2 0x%.8lux r3 0x%.8lux\n",
+ ur->r0, ur->r1, ur->r2, ur->r3);
+ p = seprint(p, e, "r4 0x%.8lux r5 0x%.8lux r6 0x%.8lux r7 0x%.8lux\n",
+ ur->r4, ur->r5, ur->r6, ur->r7);
+ p = seprint(p, e, "r8 0x%.8lux r9 0x%.8lux r10 0x%.8lux r11 0x%.8lux\n",
+ ur->r8, ur->r9, ur->r10, ur->r11);
+ seprint(p, e, "r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n",
+ ur->r12, ur->r13, ur->r14);
+ iprint("%s", buf);
+}
+
+/*
+ * enable an irq interrupt
+ */
+static void
+irqenable(int irq, IntrHandler *f, void* a, char *name)
+{
+ Vctl *v;
+
+ if(irq >= nelem(vctl) || irq < 0)
+ panic("intrenable");
+
+ v = malloc(sizeof(Vctl));
+ v->f = f;
+ v->a = a;
+ v->name = xalloc(strlen(name)+1);
+ strcpy(v->name, name);
+
+ lock(&vctllock);
+ v->next = vctl[irq];
+ vctl[irq] = v;
+ intrregs->icmr |= 1<<irq;
+ unlock(&vctllock);
+}
+
+/*
+ * disable an irq interrupt
+ */
+static void
+irqdisable(int irq, IntrHandler *f, void* a, char *name)
+{
+ Vctl **vp, *v;
+
+ if(irq >= nelem(vctl) || irq < 0)
+ panic("intrdisable");
+
+ lock(&vctllock);
+ for(vp = &vctl[irq]; v = *vp; vp = &v->next)
+ if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
+ print("irqdisable: remove %s\n", name);
+ *vp = v->next;
+ free(v);
+ break;
+ }
+ if (v == nil)
+ print("irqdisable: irq %d, name %s not enabled\n", irq, name);
+ if (vctl[irq] == nil){
+ print("irqdisable: clear icmr bit %d\n", irq);
+ intrregs->icmr &= ~(1<<irq);
+ }
+ unlock(&vctllock);
+}
+
+/*
+ * enable an interrupt
+ */
+void
+intrenable(int type, int which, IntrHandler *f, void* a, char *name)
+{
+ int irq;
+ Vctl *v;
+
+ if(type == IRQ){
+ irqenable(which, f, a, name);
+ return;
+ }
+
+ /* from here down, it must be a GPIO edge interrupt */
+ irq = which;
+ if(which >= nelem(gpiovctl) || which < 0)
+ panic("intrenable");
+ if(which > 11)
+ irq = 11;
+
+ /* the pin had better be configured as input */
+ if((1<<which) & gpioregs->direction)
+ panic("intrenable of output pin %d", which);
+
+ /* create a second level vctl for the gpio edge interrupt */
+ v = malloc(sizeof(Vctl));
+ v->f = f;
+ v->a = a;
+ v->name = xalloc(strlen(name)+1);
+ strcpy(v->name, name);
+
+ lock(&vctllock);
+ v->next = gpiovctl[which];
+ gpiovctl[which] = v;
+
+ /* set edge register to enable interrupt */
+ switch(type){
+ case GPIOboth:
+ gpioregs->rising |= 1<<which;
+ gpioregs->falling |= 1<<which;
+ break;
+ case GPIOfalling:
+ gpioregs->falling |= 1<<which;
+ break;
+ case GPIOrising:
+ gpioregs->rising |= 1<<which;
+ break;
+ }
+ unlock(&vctllock);
+ /* point the irq to the gpio interrupt handler */
+ if(gpioirqref[irq]++ == 0)
+ irqenable(irq, gpiointr, nil, "gpio edge");
+}
+
+/*
+ * disable an interrupt
+ */
+void
+intrdisable(int type, int which, IntrHandler *f, void* a, char *name)
+{
+ int irq;
+ Vctl **vp, *v;
+
+
+ if(type == IRQ){
+ irqdisable(which, f, a, name);
+ return;
+ }
+
+ /* from here down, it must be a GPIO edge interrupt */
+ irq = which;
+ if(which >= nelem(gpiovctl) || which < 0)
+ panic("intrdisable");
+ if(which > 11)
+ irq = 11;
+
+ lock(&vctllock);
+ for(vp = &gpiovctl[which]; v = *vp; vp = &v->next)
+ if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
+ break;
+ }
+ if (gpiovctl[which] == nil){
+ /* set edge register to enable interrupt */
+ switch(type){
+ case GPIOboth:
+ print("intrdisable: gpio-rising+falling clear bit %d\n", which);
+ gpioregs->rising &= ~(1<<which);
+ gpioregs->falling &= ~(1<<which);
+ break;
+ case GPIOfalling:
+ print("intrdisable: gpio-falling clear bit %d\n", which);
+ gpioregs->falling &= ~(1<<which);
+ break;
+ case GPIOrising:
+ print("intrdisable: gpio-rising clear bit %d\n", which);
+ gpioregs->rising &= ~(1<<which);
+ break;
+ }
+
+ }
+ if (v) {
+ print("intrdisable: removing %s\n", name);
+ *vp = v->next;
+ }else
+ print("intrdisable: which %d, name %s not enabled\n", which, name);
+ unlock(&vctllock);
+ /* disable the gpio interrupt handler if necessary */
+ if(--gpioirqref[irq] == 0){
+ print("intrdisable: inrqdisable gpiointr\n");
+ irqdisable(irq, gpiointr, nil, "gpio edge");
+ }
+ free(v);
+}
+
+/*
+ * called by trap to handle access faults
+ */
+static void
+faultarm(Ureg *ureg, ulong va, int user, int read)
+{
+ int n, insyscall;
+ char buf[ERRMAX];
+
+ if (up == nil) {
+ warnregs(ureg, "kernel fault");
+ panic("fault: nil up in faultarm, accessing 0x%lux", va);
+ }
+ insyscall = up->insyscall;
+ up->insyscall = 1;
+ n = fault(va, read);
+ if(n < 0){
+ if(!user){
+ warnregs(ureg, "kernel fault");
+ panic("fault: kernel accessing 0x%lux", va);
+ }
+// warnregs(ureg, "user fault");
+ sprint(buf, "sys: trap: fault %s va=0x%lux", read ? "read" : "write", va);
+ postnote(up, 1, buf, NDebug);
+ }
+ up->insyscall = insyscall;
+}
+
+/*
+ * returns 1 if the instruction writes memory, 0 otherwise
+ */
+int
+writetomem(ulong inst)
+{
+ /* swap always write memory */
+ if((inst & 0x0FC00000) == 0x01000000)
+ return 1;
+
+ /* loads and stores are distinguished by bit 20 */
+ if(inst & (1<<20))
+ return 0;
+
+ return 1;
+}
+
+
+/*
+ * here on all exceptions other than syscall (SWI)
+ */
+void
+trap(Ureg *ureg)
+{
+ ulong inst;
+ int clockintr, user, x, rv;
+ ulong va, fsr;
+ char buf[ERRMAX];
+ int rem;
+
+ if(up != nil)
+ rem = ((char*)ureg)-up->kstack;
+ else
+ rem = ((char*)ureg)-((char*)(MACHADDR+sizeof(Mach)));
+ if(rem < 256) {
+ dumpstack();
+ panic("trap %d bytes remaining, up = %#p, ureg = %#p, at pc 0x%lux",
+ rem, up, ureg, ureg->pc);
+ }
+
+ user = (ureg->psr & PsrMask) == PsrMusr;
+
+ /*
+ * All interrupts/exceptions should be resumed at ureg->pc-4,
+ * except for Data Abort which resumes at ureg->pc-8.
+ */
+ if(ureg->type == (PsrMabt+1))
+ ureg->pc -= 8;
+ else
+ ureg->pc -= 4;
+
+ clockintr = 0;
+ switch(ureg->type){
+ default:
+ panic("unknown trap");
+ break;
+ case PsrMirq:
+ clockintr = irq(ureg);
+ break;
+ case PsrMabt: /* prefetch fault */
+ faultarm(ureg, ureg->pc, user, 1);
+ break;
+ case PsrMabt+1: /* data fault */
+ va = getfar();
+ inst = *(ulong*)(ureg->pc);
+ fsr = getfsr() & 0xf;
+ switch(fsr){
+ case 0x0:
+ panic("vector exception at %lux", ureg->pc);
+ break;
+ case 0x1:
+ case 0x3:
+ if(user){
+ snprint(buf, sizeof(buf), "sys: alignment: pc 0x%lux va 0x%lux\n",
+ ureg->pc, va);
+ postnote(up, 1, buf, NDebug);
+ } else
+ panic("kernel alignment: pc 0x%lux va 0x%lux", ureg->pc, va);
+ break;
+ case 0x2:
+ panic("terminal exception at %lux", ureg->pc);
+ break;
+ case 0x4:
+ case 0x6:
+ case 0x8:
+ case 0xa:
+ case 0xc:
+ case 0xe:
+ panic("external abort 0x%lux pc 0x%lux addr 0x%lux", fsr, ureg->pc, va);
+ break;
+ case 0x5:
+ case 0x7:
+ /* translation fault, i.e., no pte entry */
+ faultarm(ureg, va, user, !writetomem(inst));
+ break;
+ case 0x9:
+ case 0xb:
+ /* domain fault, accessing something we shouldn't */
+ if(user){
+ sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n",
+ ureg->pc, va);
+ postnote(up, 1, buf, NDebug);
+ } else
+ panic("kernel access violation: pc 0x%lux va 0x%lux",
+ ureg->pc, va);
+ break;
+ case 0xd:
+ case 0xf:
+ /* permission error, copy on write or real permission error */
+ faultarm(ureg, va, user, !writetomem(inst));
+ break;
+ }
+ break;
+ case PsrMund: /* undefined instruction */
+ if (user) {
+ /* look for floating point instructions to interpret */
+ x = spllo();
+ rv = fpiarm(ureg);
+ splx(x);
+ if (rv == 0) {
+ sprint(buf, "undefined instruction: pc 0x%lux\n", ureg->pc);
+ postnote(up, 1, buf, NDebug);
+ }
+ }else{
+ iprint("undefined instruction: pc=0x%lux, inst=0x%lux, 0x%lux, 0x%lux, 0x%lux, 0x%lux\n", ureg->pc, ((ulong*)ureg->pc)[-2], ((ulong*)ureg->pc)[-1], ((ulong*)ureg->pc)[0], ((ulong*)ureg->pc)[1], ((ulong*)ureg->pc)[2]);
+ panic("undefined instruction");
+ }
+ break;
+ }
+ splhi();
+
+ /* delaysched set because we held a lock or because our quantum ended */
+ if(up && up->delaysched && clockintr){
+ sched();
+ splhi();
+ }
+
+ if(user){
+ if(up->procctl || up->nnote)
+ notify(ureg);
+ kexit(ureg);
+ }
+}
+
+/*
+ * here on irq's
+ */
+static int
+irq(Ureg *ur)
+{
+ ulong va;
+ int clockintr, i;
+ Vctl *v;
+
+ va = intrregs->icip;
+
+ if(va & (1<<IRQtimer0))
+ clockintr = 1;
+ else
+ clockintr = 0;
+ for(i = 0; i < 32; i++){
+ if(((1<<i) & va) == 0)
+ continue;
+ for(v = vctl[i]; v != nil; v = v->next){
+ v->f(ur, v->a);
+ va &= ~(1<<i);
+ }
+ }
+ if(va)
+ print("unknown interrupt: %lux\n", va);
+
+ return clockintr;
+}
+
+/*
+ * here on gpio interrupts
+ */
+static void
+gpiointr(Ureg *ur, void*)
+{
+ ulong va;
+ int i;
+ Vctl *v;
+
+ va = gpioregs->edgestatus;
+ gpioregs->edgestatus = va;
+
+ for(i = 0; i < 27; i++){
+ if(((1<<i) & va) == 0)
+ continue;
+ for(v = gpiovctl[i]; v != nil; v = v->next){
+ v->f(ur, v->a);
+ va &= ~(1<<i);
+ }
+ }
+ if(va)
+ print("unknown gpio interrupt: %lux\n", va);
+}
+
+/*
+ * system calls
+ */
+#include "../port/systab.h"
+
+/*
+ * Syscall is called directly from assembler without going through trap().
+ */
+void
+syscall(Ureg* ureg)
+{
+ char *e;
+ ulong sp;
+ long ret;
+ int i, scallnr;
+
+ if((ureg->psr & PsrMask) != PsrMusr) {
+ panic("syscall: pc 0x%lux r14 0x%lux cs 0x%lux", ureg->pc, ureg->r14, ureg->psr);
+ }
+
+ m->syscall++;
+ up->insyscall = 1;
+ up->pc = ureg->pc;
+ up->dbgreg = ureg;
+
+ scallnr = ureg->r0;
+ up->scallnr = scallnr;
+ spllo();
+
+ sp = ureg->sp;
+ up->nerrlab = 0;
+ ret = -1;
+ if(!waserror()){
+ if(scallnr >= nsyscall){
+ pprint("bad sys call number %d pc %lux\n",
+ scallnr, ureg->pc);
+ postnote(up, 1, "sys: bad sys call", NDebug);
+ error(Ebadarg);
+ }
+
+ if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
+ validaddr(sp, sizeof(Sargs)+BY2WD, 0);
+
+ up->s = *((Sargs*)(sp+BY2WD));
+ up->psstate = sysctab[scallnr];
+
+ ret = systab[scallnr](up->s.args);
+ poperror();
+ }else{
+ /* failure: save the error buffer for errstr */
+ e = up->syserrstr;
+ up->syserrstr = up->errstr;
+ up->errstr = e;
+ }
+ if(up->nerrlab){
+ print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
+ for(i = 0; i < NERR; i++)
+ print("sp=%lux pc=%lux\n",
+ up->errlab[i].sp, up->errlab[i].pc);
+ panic("error stack");
+ }
+
+ up->insyscall = 0;
+ up->psstate = 0;
+
+ /*
+ * Put return value in frame. On the x86 the syscall is
+ * just another trap and the return value from syscall is
+ * ignored. On other machines the return value is put into
+ * the results register by caller of syscall.
+ */
+ ureg->r0 = ret;
+
+ if(scallnr == NOTED)
+ noted(ureg, *(ulong*)(sp+BY2WD));
+
+ if(up->delaysched)
+ sched();
+
+ splhi();
+ if(scallnr != RFORK && (up->procctl || up->nnote))
+ notify(ureg);
+}
+
+/*
+ * Return user to state before notify()
+ */
+void
+noted(Ureg* ureg, ulong arg0)
+{
+ Ureg *nureg;
+ ulong oureg, sp;
+
+ qlock(&up->debug);
+ if(arg0!=NRSTR && !up->notified) {
+ qunlock(&up->debug);
+ pprint("call to noted() when not notified\n");
+ pexit("Suicide", 0);
+ }
+ up->notified = 0;
+
+ nureg = up->ureg; /* pointer to user returned Ureg struct */
+
+ /* sanity clause */
+ oureg = (ulong)nureg;
+ if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
+ pprint("bad ureg in noted or call to noted when not notified\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+
+ /* don't let user change system flags */
+ nureg->psr = (ureg->psr & ~(PsrMask|PsrDfiq|PsrDirq)) |
+ (nureg->psr & (PsrMask|PsrDfiq|PsrDirq));
+
+ memmove(ureg, nureg, sizeof(Ureg));
+
+ switch(arg0){
+ case NCONT:
+ case NRSTR:
+ if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->sp, BY2WD, 0)){
+ qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
+ pexit("Suicide", 0);
+ }
+ up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
+ qunlock(&up->debug);
+ break;
+
+ case NSAVE:
+ if(!okaddr(nureg->pc, BY2WD, 0)
+ || !okaddr(nureg->sp, BY2WD, 0)){
+ qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
+ pexit("Suicide", 0);
+ }
+ qunlock(&up->debug);
+ sp = oureg-4*BY2WD-ERRMAX;
+ splhi();
+ ureg->sp = sp;
+ ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
+ ((ulong*)sp)[0] = 0; /* arg 0 is pc */
+ break;
+
+ default:
+ pprint("unknown noted arg 0x%lux\n", arg0);
+ up->lastnote.flag = NDebug;
+ /* fall through */
+
+ case NDFLT:
+ if(up->lastnote.flag == NDebug){
+ qunlock(&up->debug);
+ pprint("suicide: %s\n", up->lastnote.msg);
+ } else
+ qunlock(&up->debug);
+ pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
+ }
+}
+
+/*
+ * Call user, if necessary, with note.
+ * Pass user the Ureg struct and the note on his stack.
+ */
+int
+notify(Ureg* ureg)
+{
+ int l;
+ ulong s, sp;
+ Note *n;
+
+ if(up->procctl)
+ procctl(up);
+ if(up->nnote == 0)
+ return 0;
+
+ s = spllo();
+ qlock(&up->debug);
+ up->notepending = 0;
+ n = &up->note[0];
+ if(strncmp(n->msg, "sys:", 4) == 0){
+ l = strlen(n->msg);
+ if(l > ERRMAX-15) /* " pc=0x12345678\0" */
+ l = ERRMAX-15;
+ sprint(n->msg+l, " pc=0x%.8lux", ureg->pc);
+ }
+
+ if(n->flag!=NUser && (up->notified || up->notify==0)){
+ if(n->flag == NDebug)
+ pprint("suicide: %s\n", n->msg);
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag!=NDebug);
+ }
+
+ if(up->notified) {
+ qunlock(&up->debug);
+ splhi();
+ return 0;
+ }
+
+ if(!up->notify){
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag!=NDebug);
+ }
+ sp = ureg->sp;
+ sp -= sizeof(Ureg);
+
+ if(!okaddr((ulong)up->notify, 1, 0)
+ || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)){
+ pprint("suicide: bad address in notify\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+
+ up->ureg = (void*)sp;
+ memmove((Ureg*)sp, ureg, sizeof(Ureg));
+ *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
+ up->ureg = (void*)sp;
+ sp -= BY2WD+ERRMAX;
+ memmove((char*)sp, up->note[0].msg, ERRMAX);
+ sp -= 3*BY2WD;
+ *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */
+ *(ulong*)(sp+1*BY2WD) = (ulong)up->ureg; /* arg 1 is ureg* */
+ *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
+ ureg->sp = sp;
+ ureg->pc = (ulong)up->notify;
+ up->notified = 1;
+ up->nnote--;
+ memmove(&up->lastnote, &up->note[0], sizeof(Note));
+ memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
+
+ qunlock(&up->debug);
+ splx(s);
+ return 1;
+}
+
+/* Give enough context in the ureg to produce a kernel stack for
+ * a sleeping process
+ */
+void
+setkernur(Ureg *ureg, Proc *p)
+{
+ ureg->pc = p->sched.pc;
+ ureg->sp = p->sched.sp+4;
+ ureg->r14 = (ulong)sched;
+}
+
+/*
+ * return the userpc the last exception happened at
+ */
+ulong
+userpc(void)
+{
+ Ureg *ureg;
+
+ ureg = (Ureg*)up->dbgreg;
+ return ureg->pc;
+}
+
+/* This routine must save the values of registers the user is not permitted
+ * to write from devproc and then restore the saved values before returning.
+ */
+void
+setregisters(Ureg* ureg, char* pureg, char* uva, int n)
+{
+ USED(ureg, pureg, uva, n);
+}
+
+/*
+ * this is the body for all kproc's
+ */
+static void
+linkproc(void)
+{
+ spllo();
+ up->kpfun(up->kparg);
+ pexit("kproc exiting", 0);
+}
+
+/*
+ * setup stack and initial PC for a new kernel proc. This is architecture
+ * dependent because of the starting stack location
+ */
+void
+kprocchild(Proc *p, void (*func)(void*), void *arg)
+{
+ p->sched.pc = (ulong)linkproc;
+ p->sched.sp = (ulong)p->kstack+KSTACK;
+
+ p->kpfun = func;
+ p->kparg = arg;
+}
+
+
+/*
+ * Craft a return frame which will cause the child to pop out of
+ * the scheduler in user mode with the return register zero. Set
+ * pc to point to a l.s return function.
+ */
+void
+forkchild(Proc *p, Ureg *ureg)
+{
+ Ureg *cureg;
+
+//print("%lud setting up for forking child %lud\n", up->pid, p->pid);
+ p->sched.sp = (ulong)p->kstack+KSTACK-sizeof(Ureg);
+ p->sched.pc = (ulong)forkret;
+
+ cureg = (Ureg*)(p->sched.sp);
+ memmove(cureg, ureg, sizeof(Ureg));
+
+ /* syscall returns 0 for child */
+ cureg->r0 = 0;
+
+ /* Things from bottom of syscall which were never executed */
+ p->psstate = 0;
+ p->insyscall = 0;
+}
+
+/*
+ * setup stack, initial PC, and any arch dependent regs for an execing user proc.
+ */
+long
+execregs(ulong entry, ulong ssize, ulong nargs)
+{
+ ulong *sp;
+ Ureg *ureg;
+
+ sp = (ulong*)(USTKTOP - ssize);
+ *--sp = nargs;
+
+ ureg = up->dbgreg;
+ memset(ureg, 0, 15*sizeof(ulong));
+ ureg->r13 = (ulong)sp;
+ ureg->pc = entry;
+//print("%lud: EXECREGS pc 0x%lux sp 0x%lux\n", up->pid, ureg->pc, ureg->r13);
+ return USTKTOP-sizeof(Tos); /* address of kernel/user shared data */
+}
+
+/*
+ * Fill in enough of Ureg to get a stack trace, and call a function.
+ * Used by debugging interface rdb.
+ */
+void
+callwithureg(void (*fn)(Ureg*))
+{
+ Ureg ureg;
+ ureg.pc = getcallerpc(&fn);
+ ureg.sp = (ulong)&fn;
+ fn(&ureg);
+}
+
+static void
+_dumpstack(Ureg *ureg)
+{
+ ulong l, v, i;
+ ulong *p;
+ extern ulong etext;
+
+ if(up == 0){
+ iprint("no current proc\n");
+ return;
+ }
+
+ iprint("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->r14);
+ i = 0;
+ for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){
+ v = *(ulong*)l;
+ if(KTZERO < v && v < (ulong)&etext && (v&3)==0){
+ v -= 4;
+ p = (ulong*)v;
+ if((*p & 0x0f000000) == 0x0b000000){
+ iprint("%.8lux=%.8lux ", l, v);
+ i++;
+ }
+ }
+ if(i == 4){
+ i = 0;
+ iprint("\n");
+ }
+ }
+ if(i)
+ iprint("\n");
+}
+
+void
+dumpstack(void)
+{
+ callwithureg(_dumpstack);
+}
+
+/*
+ * pc output by ps
+ */
+ulong
+dbgpc(Proc *p)
+{
+ Ureg *ureg;
+
+ ureg = p->dbgreg;
+ if(ureg == 0)
+ return 0;
+
+ return ureg->pc;
+}
+
+/*
+ * called in sysfile.c
+ */
+void
+evenaddr(ulong addr)
+{
+ if(addr & 3){
+ postnote(up, 1, "sys: odd address", NDebug);
+ error(Ebadarg);
+ }
+}
diff --git a/sys/src/9/bitsy/uartsa1110.c b/sys/src/9/bitsy/uartsa1110.c
new file mode 100755
index 000000000..02b5e6298
--- /dev/null
+++ b/sys/src/9/bitsy/uartsa1110.c
@@ -0,0 +1,514 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#include "../port/netif.h"
+
+/* this isn't strictly an sa1110 driver. The rts/cts stuff is h3650 specific */
+
+static void sa1110_uartpower(Uart *, int);
+
+enum
+{
+ /* ctl[0] bits */
+ Parity= 1<<0,
+ Even= 1<<1,
+ Stop2= 1<<2,
+ Bits8= 1<<3,
+ SCE= 1<<4, /* synchronous clock enable */
+ RCE= 1<<5, /* rx on falling edge of clock */
+ TCE= 1<<6, /* tx on falling edge of clock */
+
+ /* ctl[3] bits */
+ Rena= 1<<0, /* receiver enable */
+ Tena= 1<<1, /* transmitter enable */
+ Break= 1<<2, /* force TXD3 low */
+ Rintena= 1<<3, /* enable receive interrupt */
+ Tintena= 1<<4, /* enable transmitter interrupt */
+ Loopback= 1<<5, /* loop back data */
+
+ /* data bits */
+ DEparity= 1<<8, /* parity error */
+ DEframe= 1<<9, /* framing error */
+ DEoverrun= 1<<10, /* overrun error */
+
+ /* status[0] bits */
+ Tint= 1<<0, /* transmit fifo half full interrupt */
+ Rint0= 1<<1, /* receiver fifo 1/3-2/3 full */
+ Rint1= 1<<2, /* receiver fifo not empty and receiver idle */
+ Breakstart= 1<<3,
+ Breakend= 1<<4,
+ Fifoerror= 1<<5, /* fifo error */
+
+ /* status[1] bits */
+ Tbusy= 1<<0, /* transmitting */
+ Rnotempty= 1<<1, /* receive fifo not empty */
+ Tnotfull= 1<<2, /* transmit fifo not full */
+ ParityError= 1<<3,
+ FrameError= 1<<4,
+ Overrun= 1<<5,
+};
+
+extern PhysUart sa1110physuart;
+
+//static
+Uart sa1110uart[2] = {
+{ .regs = (void*)UART3REGS,
+ .name = "serialport3",
+ .freq = ClockFreq,
+ .bits = 8,
+ .stop = 1,
+ .parity = 'n',
+ .baud = 115200,
+ .phys = &sa1110physuart,
+ .special = 0,
+ .next = &sa1110uart[1], },
+
+{ .regs = (void*)UART1REGS,
+ .name = "serialport1",
+ .freq = ClockFreq,
+ .bits = 8,
+ .stop = 1,
+ .parity = 'n',
+ .baud = 115200,
+ .phys = &sa1110physuart,
+ .putc = µcputc,
+ .special = 0,
+ .next = nil, },
+};
+static Uart* µcuart;
+
+#define R(p) ((Uartregs*)((p)->regs))
+#define SR(p) ((Uartregs*)((p)->saveregs))
+
+/*
+ * enable a port's interrupts. set DTR and RTS
+ */
+static void
+sa1110_uartenable(Uart *p, int intena)
+{
+ ulong s;
+
+ s = R(p)->ctl[3] & ~(Rintena|Tintena|Rena|Tena);
+ if(intena)
+ R(p)->ctl[3] = s |Rintena|Tintena|Rena|Tena;
+ else
+ R(p)->ctl[3] = s | Rena|Tena;
+}
+
+/*
+ * disable interrupts. clear DTR, and RTS
+ */
+static void
+sa1110_uartdisable(Uart *p)
+{
+ R(p)->ctl[3] &= ~(Rintena|Tintena|Rena|Tena);
+}
+
+static long
+sa1110_uartstatus(Uart *p, void *buf, long n, long offset)
+{
+ char str[256];
+ ulong ctl0;
+
+ ctl0 = R(p)->ctl[0];
+ snprint(str, sizeof(str),
+ "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
+ "dev(%d) type(%d) framing(%d) overruns(%d)%s%s%s%s\n",
+
+ p->baud,
+ p->hup_dcd,
+ 0,
+ p->hup_dsr,
+ (ctl0 & Bits8) ? 8 : 7,
+ 0,
+ (ctl0 & Parity) ? ((ctl0 & Even) ? 'e' : 'o') : 'n',
+ 0,
+ (ctl0 & Stop2) ? 2 : 1,
+ 1,
+
+ p->dev,
+ p->type,
+ p->ferr,
+ p->oerr,
+ "",
+ "",
+ "",
+ "" );
+ return readstr(offset, buf, n, str);
+}
+
+/*
+ * set the buad rate
+ */
+static int
+sa1110_uartbaud(Uart *p, int rate)
+{
+ ulong brconst;
+ ulong ctl3;
+
+ if(rate <= 0)
+ return -1;
+
+ /* disable */
+ ctl3 = R(p)->ctl[3];
+ R(p)->ctl[3] = 0;
+
+ brconst = p->freq/(16*rate) - 1;
+ R(p)->ctl[1] = (brconst>>8) & 0xf;
+ R(p)->ctl[2] = brconst & 0xff;
+
+ /* reenable */
+ R(p)->ctl[3] = ctl3;
+
+ p->baud = rate;
+ return 0;
+}
+
+/*
+ * send a break
+ */
+static void
+sa1110_uartbreak(Uart *p, int ms)
+{
+ if(ms == 0)
+ ms = 200;
+
+ R(p)->ctl[3] |= Break;
+ tsleep(&up->sleep, return0, 0, ms);
+ R(p)->ctl[3] &= ~Break;
+}
+
+/*
+ * set bits/char
+ */
+static int
+sa1110_uartbits(Uart *p, int n)
+{
+ ulong ctl0, ctl3;
+
+ ctl0 = R(p)->ctl[0];
+ switch(n){
+ case 7:
+ ctl0 &= ~Bits8;
+ break;
+ case 8:
+ ctl0 |= Bits8;
+ break;
+ default:
+ return -1;
+ }
+
+ /* disable */
+ ctl3 = R(p)->ctl[3];
+ R(p)->ctl[3] = 0;
+
+ R(p)->ctl[0] = ctl0;
+
+ /* reenable */
+ R(p)->ctl[3] = ctl3;
+
+ p->bits = n;
+ return 0;
+}
+
+/*
+ * set stop bits
+ */
+static int
+sa1110_uartstop(Uart *p, int n)
+{
+ ulong ctl0, ctl3;
+
+ ctl0 = R(p)->ctl[0];
+ switch(n){
+ case 1:
+ ctl0 &= ~Stop2;
+ break;
+ case 2:
+ ctl0 |= Stop2;
+ break;
+ default:
+ return -1;
+ }
+
+ /* disable */
+ ctl3 = R(p)->ctl[3];
+ R(p)->ctl[3] = 0;
+
+ R(p)->ctl[0] = ctl0;
+
+ /* reenable */
+ R(p)->ctl[3] = ctl3;
+
+ p->stop = n;
+ return 0;
+}
+
+/*
+ * turn on/off rts
+ */
+static void
+sa1110_uartrts(Uart*, int)
+{
+}
+
+/*
+ * turn on/off dtr
+ */
+static void
+sa1110_uartdtr(Uart*, int)
+{
+}
+
+/*
+ * turn on/off modem flow control on/off (rts/cts)
+ */
+static void
+sa1110_uartmodemctl(Uart *p, int on)
+{
+ if(on) {
+ } else {
+ p->cts = 1;
+ }
+}
+
+/*
+ * set parity
+ */
+static int
+sa1110_uartparity(Uart *p, int type)
+{
+ ulong ctl0, ctl3;
+
+ ctl0 = R(p)->ctl[0];
+ switch(type){
+ case 'e':
+ ctl0 |= Parity|Even;
+ break;
+ case 'o':
+ ctl0 |= Parity;
+ break;
+ default:
+ ctl0 &= ~(Parity|Even);
+ break;
+ }
+
+ /* disable */
+ ctl3 = R(p)->ctl[3];
+ R(p)->ctl[3] = 0;
+
+ R(p)->ctl[0] = ctl0;
+
+ /* reenable */
+ R(p)->ctl[3] = ctl3;
+
+ return 0;
+}
+
+/*
+ * restart output if not blocked and OK to send
+ */
+static void
+sa1110_uartkick(Uart *p)
+{
+ int i;
+
+ R(p)->ctl[3] &= ~Tintena;
+
+ if(p->cts == 0 || p->blocked)
+ return;
+
+ for(i = 0; i < 1024; i++){
+ if(!(R(p)->status[1] & Tnotfull)){
+ R(p)->ctl[3] |= Tintena;
+ break;
+ }
+ if(p->op >= p->oe && uartstageoutput(p) == 0)
+ break;
+ R(p)->data = *p->op++;
+ }
+}
+
+/*
+ * take an interrupt
+ */
+static void
+sa1110_uartintr(Ureg*, void *x)
+{
+ Uart *p;
+ ulong s;
+ Uartregs *regs;
+
+ p = x;
+ regs = p->regs;
+
+ /* receiver interrupt, snarf bytes */
+ while(regs->status[1] & Rnotempty)
+ uartrecv(p, regs->data);
+
+ /* remember and reset interrupt causes */
+ s = regs->status[0];
+ regs->status[0] |= s;
+
+ if(s & Tint){
+ /* transmitter interrupt, restart */
+ uartkick(p);
+ }
+
+ if(s & (ParityError|FrameError|Overrun)){
+ if(s & ParityError)
+ p->parity++;
+ if(s & FrameError)
+ p->ferr++;
+ if(s & Overrun)
+ p->oerr++;
+ }
+
+ /* receiver interrupt, snarf bytes */
+ while(regs->status[1] & Rnotempty)
+ uartrecv(p, regs->data);
+}
+
+static Uart*
+sa1110_pnp(void)
+{
+ return sa1110uart;
+}
+
+static int
+sa1110_getc(Uart *uart)
+{
+ Uartregs *ur;
+
+ ur = uart->regs;
+ while((ur->status[1] & Rnotempty) == 0)
+ ;
+ return ur->data;
+}
+
+static void
+sa1110_putc(Uart *uart, int c)
+{
+ Uartregs *ur;
+
+ ur = uart->regs;
+ /* wait for output ready */
+ while((ur->status[1] & Tnotfull) == 0)
+ ;
+ ur->data = c;
+ while((ur->status[1] & Tbusy))
+ ;
+}
+
+PhysUart sa1110physuart = {
+ .name= "sa1110",
+ .pnp= sa1110_pnp,
+ .enable= sa1110_uartenable,
+ .disable= sa1110_uartdisable,
+ .bits= sa1110_uartbits,
+ .kick= sa1110_uartkick,
+ .modemctl= sa1110_uartmodemctl,
+ .baud= sa1110_uartbaud,
+ .stop= sa1110_uartstop,
+ .parity= sa1110_uartparity,
+ .dobreak= sa1110_uartbreak,
+ .rts= sa1110_uartrts,
+ .dtr= sa1110_uartdtr,
+ .status= sa1110_uartstatus,
+ .power= sa1110_uartpower,
+ .getc= sa1110_getc,
+ .putc= sa1110_putc,
+};
+
+/*
+ * for iprint, just write it
+ */
+void
+serialµcputs(uchar *str, int n)
+{
+ Uartregs *ur;
+
+ if(µcuart == nil)
+ return;
+ ur = µcuart->regs;
+ while(n-- > 0){
+ /* wait for output ready */
+ while((ur->status[1] & Tnotfull) == 0)
+ ;
+ ur->data = *str++;
+ }
+ while((ur->status[1] & Tbusy))
+ ;
+}
+
+enum
+{
+ /* gpclk register 0 */
+ Gpclk_sus= 1<<0, /* set uart mode */
+};
+
+Gpclkregs *gpclkregs;
+
+/*
+ * setup all uarts (called early by main() to allow debugging output to
+ * a serial port)
+ */
+void
+sa1110_uartsetup(int console)
+{
+ Uart *p;
+
+ /* external serial port (eia0) */
+ p = &sa1110uart[0];
+ p->regs = mapspecial(UART3REGS, sizeof(Uartregs));
+ p->saveregs = xalloc(sizeof(Uartregs));
+ /* set eia0 up as a console */
+ if(console){
+ uartctl(p, "b115200 l8 pn s1");
+ (*p->phys->enable)(p, 0);
+ p->console = 1;
+ consuart = p;
+ }
+ intrenable(IRQ, IRQuart3, sa1110_uartintr, p, p->name);
+
+ /* port for talking to microcontroller (eia1) */
+ gpclkregs = mapspecial(GPCLKREGS, sizeof(Gpclkregs));
+ gpclkregs->r0 = Gpclk_sus; /* set uart mode */
+
+ p = &sa1110uart[1];
+ p->regs = mapspecial(UART1REGS, sizeof(Uartregs));
+ p->saveregs = xalloc(sizeof(Uartregs));
+ uartctl(p, "b115200 l8 pn s1");
+ µcuart = p;
+ p->special = 1;
+ (*p->phys->enable)(p, 0);
+ intrenable(IRQ, IRQuart1b, sa1110_uartintr, p, p->name);
+}
+
+static void
+uartcpy(Uartregs *to, Uartregs *from)
+{
+ to->ctl[0] = from->ctl[0];
+// to->ctl[1] = from->ctl[1];
+// to->ctl[2] = from->ctl[2];
+ to->ctl[3] = from->ctl[3];
+
+}
+
+static void
+sa1110_uartpower(Uart *p, int powerup)
+{
+ if (powerup) {
+ /* power up, restore the registers */
+ uartcpy(R(p), SR(p));
+ R(p)->status[0] = R(p)->status[0];
+ } else {
+ /* power down, save the registers */
+ uartcpy(SR(p), R(p));
+ }
+}
diff --git a/sys/src/9/bitsy/wavelan.c b/sys/src/9/bitsy/wavelan.c
new file mode 100755
index 000000000..5d12eca62
--- /dev/null
+++ b/sys/src/9/bitsy/wavelan.c
@@ -0,0 +1,1221 @@
+/*
+ Lucent Wavelan IEEE 802.11 pcmcia.
+ There is almost no documentation for the card.
+ the driver is done using both the FreeBSD, Linux and
+ original Plan 9 drivers as `documentation'.
+
+ Has been used with the card plugged in during all up time.
+ no cards removals/insertions yet.
+
+ For known BUGS see the comments below. Besides,
+ the driver keeps interrupts disabled for just too
+ long. When it gets robust, locks should be revisited.
+
+ BUGS: check endian, alignment and mem/io issues;
+ multicast;
+ receive watchdog interrupts.
+ TODO: automatic power management;
+ improve locking.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+#include "etherif.h"
+#include "wavelan.h"
+
+enum
+{
+ MSperTick= 50, /* ms between ticks of kproc */
+};
+
+/*
+ * When we're using a PCI device and memory-mapped I/O,
+ * the registers are spaced out as though each takes 32 bits,
+ * even though they are only 16-bit registers. Thus,
+ * ctlr->mmb[reg] is the right way to access register reg,
+ * even though a priori you'd expect to use ctlr->mmb[reg/2].
+ */
+void
+csr_outs(Ctlr *ctlr, int reg, ushort arg)
+{
+ if(ctlr->mmb)
+ ctlr->mmb[reg] = arg;
+ else
+ outs(ctlr->iob+reg, arg);
+}
+
+ushort
+csr_ins(Ctlr *ctlr, int reg)
+{
+ if(ctlr->mmb)
+ return ctlr->mmb[reg];
+ else
+ return ins(ctlr->iob+reg);
+}
+
+static void
+csr_ack(Ctlr *ctlr, int ev)
+{
+ csr_outs(ctlr, WR_EvAck, ev);
+}
+
+static void
+csr_inss(Ctlr *ctlr, int reg, void *dat, int ndat)
+{
+ ushort *rp, *wp;
+
+ if(ctlr->mmb){
+ rp = &ctlr->mmb[reg];
+ wp = dat;
+ while(ndat-- > 0)
+ *wp++ = *rp;
+ }else
+ inss(ctlr->iob+reg, dat, ndat);
+}
+
+static void
+csr_outss(Ctlr *ctlr, int reg, void *dat, int ndat)
+{
+ ushort *rp, *wp;
+
+ if(ctlr->mmb){
+ rp = dat;
+ wp = &ctlr->mmb[reg];
+ while(ndat-- > 0)
+ *wp = *rp++;
+ }else
+ outss(ctlr->iob+reg, dat, ndat);
+}
+
+// w_... routines do not ilock the Ctlr and should
+// be called locked.
+
+void
+w_intdis(Ctlr* ctlr)
+{
+ csr_outs(ctlr, WR_IntEna, 0);
+ csr_ack(ctlr, 0xffff);
+}
+
+static void
+w_intena(Ctlr* ctlr)
+{
+ csr_outs(ctlr, WR_IntEna, WEvs);
+}
+
+int
+w_cmd(Ctlr *ctlr, ushort cmd, ushort arg)
+{
+ int i, rc;
+
+ for(i=0; i<WTmOut; i++)
+ if((csr_ins(ctlr, WR_Cmd)&WCmdBusy) == 0)
+ break;
+ if(i==WTmOut){
+ print("#l%d: issuing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_Cmd));
+ return -1;
+ }
+
+ csr_outs(ctlr, WR_Parm0, arg);
+ csr_outs(ctlr, WR_Cmd, cmd);
+
+ for(i=0; i<WTmOut; i++)
+ if(csr_ins(ctlr, WR_EvSts)&WCmdEv)
+ break;
+ if(i==WTmOut){
+ /*
+ * WCmdIni can take a really long time.
+ */
+ enum { IniTmOut = 2000 };
+ for(i=0; i<IniTmOut; i++){
+ if(csr_ins(ctlr, WR_EvSts)&WCmdEv)
+ break;
+ microdelay(100);
+ }
+ if(i < IniTmOut)
+ if(0) print("#l%d: long cmd %.4ux %d\n", ctlr->ctlrno, cmd, i);
+ if(i == IniTmOut){
+ print("#l%d: execing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_EvSts));
+ return -1;
+ }
+ }
+ rc = csr_ins(ctlr, WR_Sts);
+ csr_ack(ctlr, WCmdEv);
+
+ if((rc&WCmdMsk) != (cmd&WCmdMsk)){
+ print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc);
+ return -1;
+ }
+ if(rc&WResSts){
+ /*
+ * Don't print; this happens on every WCmdAccWr for some reason.
+ */
+ if(0) print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+w_seek(Ctlr* ctlr, ushort id, ushort offset, int chan)
+{
+ int i, rc;
+ static ushort sel[] = { WR_Sel0, WR_Sel1 };
+ static ushort off[] = { WR_Off0, WR_Off1 };
+
+ if(chan != 0 && chan != 1)
+ panic("wavelan: bad chan\n");
+ csr_outs(ctlr, sel[chan], id);
+ csr_outs(ctlr, off[chan], offset);
+ for (i=0; i<WTmOut; i++){
+ rc = csr_ins(ctlr, off[chan]);
+ if((rc & (WBusyOff|WErrOff)) == 0)
+ return 0;
+ }
+ return -1;
+}
+
+int
+w_inltv(Ctlr* ctlr, Wltv* ltv)
+{
+ int len;
+ ushort code;
+
+ if(w_cmd(ctlr, WCmdAccRd, ltv->type)){
+ DEBUG("wavelan: access read failed\n");
+ return -1;
+ }
+ if(w_seek(ctlr,ltv->type,0,1)){
+ DEBUG("wavelan: seek failed\n");
+ return -1;
+ }
+ len = csr_ins(ctlr, WR_Data1);
+ if(len > ltv->len)
+ return -1;
+ ltv->len = len;
+ if((code=csr_ins(ctlr, WR_Data1)) != ltv->type){
+ USED(code);
+ DEBUG("wavelan: type %x != code %x\n",ltv->type,code);
+ return -1;
+ }
+ if(ltv->len > 0)
+ csr_inss(ctlr, WR_Data1, &ltv->val, ltv->len-1);
+
+ return 0;
+}
+
+static void
+w_outltv(Ctlr* ctlr, Wltv* ltv)
+{
+ if(w_seek(ctlr,ltv->type, 0, 1))
+ return;
+ csr_outss(ctlr, WR_Data1, ltv, ltv->len+1);
+ w_cmd(ctlr, WCmdAccWr, ltv->type);
+}
+
+void
+ltv_outs(Ctlr* ctlr, int type, ushort val)
+{
+ Wltv ltv;
+
+ ltv.len = 2;
+ ltv.type = type;
+ ltv.val = val;
+ w_outltv(ctlr, &ltv);
+}
+
+int
+ltv_ins(Ctlr* ctlr, int type)
+{
+ Wltv ltv;
+
+ ltv.len = 2;
+ ltv.type = type;
+ ltv.val = 0;
+ if(w_inltv(ctlr, &ltv))
+ return -1;
+ return ltv.val;
+}
+
+static void
+ltv_outstr(Ctlr* ctlr, int type, char* val)
+{
+ Wltv ltv;
+ int len;
+
+ len = strlen(val);
+ if(len > sizeof(ltv.s))
+ len = sizeof(ltv.s);
+ memset(&ltv, 0, sizeof(ltv));
+ ltv.len = (sizeof(ltv.type)+sizeof(ltv.slen)+sizeof(ltv.s))/2;
+ ltv.type = type;
+
+// This should be ltv.slen = len; according to Axel Belinfante
+ ltv.slen = len;
+
+ strncpy(ltv.s, val, len);
+ w_outltv(ctlr, &ltv);
+}
+
+static char Unkname[] = "who knows";
+static char Nilname[] = "card does not tell";
+
+static char*
+ltv_inname(Ctlr* ctlr, int type)
+{
+ static Wltv ltv;
+ int len;
+
+ memset(&ltv,0,sizeof(ltv));
+ ltv.len = WNameLen/2+2;
+ ltv.type = type;
+ if(w_inltv(ctlr, &ltv))
+ return Unkname;
+ len = ltv.slen;
+ if(len == 0 || ltv.s[0] == 0)
+ return Nilname;
+ if(len >= sizeof ltv.s)
+ len = sizeof ltv.s - 1;
+ ltv.s[len] = '\0';
+ return ltv.s;
+}
+
+static int
+w_read(Ctlr* ctlr, int type, int off, void* buf, ulong len)
+{
+ if(w_seek(ctlr, type, off, 1)){
+ DEBUG("wavelan: w_read: seek failed");
+ return 0;
+ }
+ csr_inss(ctlr, WR_Data1, buf, len/2);
+
+ return len;
+}
+
+static int
+w_write(Ctlr* ctlr, int type, int off, void* buf, ulong len)
+{
+ if(w_seek(ctlr, type, off, 0)){
+ DEBUG("wavelan: w_write: seek failed\n");
+ return 0;
+ }
+
+ csr_outss(ctlr, WR_Data0, buf, len/2);
+ csr_outs(ctlr, WR_Data0, 0xdead);
+ csr_outs(ctlr, WR_Data0, 0xbeef);
+ if(w_seek(ctlr, type, off + len, 0)){
+ DEBUG("wavelan: write seek failed\n");
+ return 0;
+ }
+ if(csr_ins(ctlr, WR_Data0) == 0xdead && csr_ins(ctlr, WR_Data0) == 0xbeef)
+ return len;
+
+ DEBUG("wavelan: Hermes bug byte.\n");
+ return 0;
+}
+
+static int
+w_alloc(Ctlr* ctlr, int len)
+{
+ int rc;
+ int i,j;
+
+ if(w_cmd(ctlr, WCmdMalloc, len)==0)
+ for (i = 0; i<WTmOut; i++)
+ if(csr_ins(ctlr, WR_EvSts) & WAllocEv){
+ csr_ack(ctlr, WAllocEv);
+ rc=csr_ins(ctlr, WR_Alloc);
+ if(w_seek(ctlr, rc, 0, 0))
+ return -1;
+ len = len/2;
+ for (j=0; j<len; j++)
+ csr_outs(ctlr, WR_Data0, 0);
+ return rc;
+ }
+ return -1;
+}
+
+static int
+w_enable(Ether* ether)
+{
+ Wltv ltv;
+ Ctlr* ctlr = (Ctlr*) ether->ctlr;
+
+ if(!ctlr)
+ return -1;
+
+ w_intdis(ctlr);
+ w_cmd(ctlr, WCmdDis, 0);
+ w_intdis(ctlr);
+ if(w_cmd(ctlr, WCmdIni, 0))
+ return -1;
+ w_intdis(ctlr);
+
+ ltv_outs(ctlr, WTyp_Tick, 8);
+ ltv_outs(ctlr, WTyp_MaxLen, ctlr->maxlen);
+ ltv_outs(ctlr, WTyp_Ptype, ctlr->ptype);
+ ltv_outs(ctlr, WTyp_CreateIBSS, ctlr->createibss);
+ ltv_outs(ctlr, WTyp_RtsThres, ctlr->rtsthres);
+ ltv_outs(ctlr, WTyp_TxRate, ctlr->txrate);
+ ltv_outs(ctlr, WTyp_ApDens, ctlr->apdensity);
+ ltv_outs(ctlr, WTyp_PMWait, ctlr->pmwait);
+ ltv_outs(ctlr, WTyp_PM, ctlr->pmena);
+ if(*ctlr->netname)
+ ltv_outstr(ctlr, WTyp_NetName, ctlr->netname);
+ if(*ctlr->wantname)
+ ltv_outstr(ctlr, WTyp_WantName, ctlr->wantname);
+ ltv_outs(ctlr, WTyp_Chan, ctlr->chan);
+ if(*ctlr->nodename)
+ ltv_outstr(ctlr, WTyp_NodeName, ctlr->nodename);
+ ltv.len = 4;
+ ltv.type = WTyp_Mac;
+ memmove(ltv.addr, ether->ea, Eaddrlen);
+ w_outltv(ctlr, &ltv);
+
+ ltv_outs(ctlr, WTyp_Prom, (ether->prom?1:0));
+
+ if(ctlr->hascrypt && ctlr->crypt){
+ ltv_outs(ctlr, WTyp_Crypt, ctlr->crypt);
+ ltv_outs(ctlr, WTyp_TxKey, ctlr->txkey);
+ w_outltv(ctlr, &ctlr->keys);
+ ltv_outs(ctlr, WTyp_XClear, ctlr->xclear);
+ }
+
+ // BUG: set multicast addresses
+
+ if(w_cmd(ctlr, WCmdEna, 0)){
+ DEBUG("wavelan: Enable failed");
+ return -1;
+ }
+ ctlr->txdid = w_alloc(ctlr, 1518 + sizeof(WFrame) + 8);
+ ctlr->txmid = w_alloc(ctlr, 1518 + sizeof(WFrame) + 8);
+ if(ctlr->txdid == -1 || ctlr->txmid == -1)
+ DEBUG("wavelan: alloc failed");
+ ctlr->txbusy = 0;
+ w_intena(ctlr);
+ return 0;
+}
+
+static void
+w_rxdone(Ether* ether)
+{
+ Ctlr* ctlr = (Ctlr*) ether->ctlr;
+ int len, sp;
+ WFrame f;
+ Block* bp=0;
+ Etherpkt* ep;
+
+ sp = csr_ins(ctlr, WR_RXId);
+ len = w_read(ctlr, sp, 0, &f, sizeof(f));
+ if(len == 0){
+ DEBUG("wavelan: read frame error\n");
+ goto rxerror;
+ }
+ if(f.sts&WF_Err){
+ goto rxerror;
+ }
+ switch(f.sts){
+ case WF_1042:
+ case WF_Tunnel:
+ case WF_WMP:
+ len = f.dlen + WSnapHdrLen;
+ bp = iallocb(ETHERHDRSIZE + len + 2);
+ if(!bp)
+ goto rxerror;
+ ep = (Etherpkt*) bp->wp;
+ memmove(ep->d, f.addr1, Eaddrlen);
+ memmove(ep->s, f.addr2, Eaddrlen);
+ memmove(ep->type,&f.type,2);
+ bp->wp += ETHERHDRSIZE;
+ if(w_read(ctlr, sp, WF_802_11_Off, bp->wp, len+2) == 0){
+ DEBUG("wavelan: read 802.11 error\n");
+ goto rxerror;
+ }
+ bp->wp = bp->rp+(ETHERHDRSIZE+f.dlen);
+ break;
+ default:
+ len = ETHERHDRSIZE + f.dlen + 2;
+ bp = iallocb(len);
+ if(!bp)
+ goto rxerror;
+ if(w_read(ctlr, sp, WF_802_3_Off, bp->wp, len) == 0){
+ DEBUG("wavelan: read 800.3 error\n");
+ goto rxerror;
+ }
+ bp->wp += len;
+ }
+
+ ctlr->nrx++;
+ etheriq(ether,bp,1);
+ ctlr->signal = ((ctlr->signal*15)+((f.qinfo>>8) & 0xFF))/16;
+ ctlr->noise = ((ctlr->noise*15)+(f.qinfo & 0xFF))/16;
+ return;
+
+rxerror:
+ freeb(bp);
+ ctlr->nrxerr++;
+}
+
+static void
+w_txstart(Ether* ether)
+{
+ Etherpkt *pkt;
+ Ctlr *ctlr;
+ Block *bp;
+ int len, off;
+
+ if((ctlr = ether->ctlr) == nil || (ctlr->state & (Attached|Power)) != (Attached|Power) || ctlr->txbusy)
+ return;
+
+ if((bp = qget(ether->oq)) == nil)
+ return;
+ pkt = (Etherpkt*)bp->rp;
+
+ //
+ // If the packet header type field is > 1500 it is an IP or
+ // ARP datagram, otherwise it is an 802.3 packet. See RFC1042.
+ //
+ memset(&ctlr->txf, 0, sizeof(ctlr->txf));
+ if(((pkt->type[0]<<8)|pkt->type[1]) > 1500){
+ ctlr->txf.framectl = WF_Data;
+ memmove(ctlr->txf.addr1, pkt->d, Eaddrlen);
+ memmove(ctlr->txf.addr2, pkt->s, Eaddrlen);
+ memmove(ctlr->txf.dstaddr, pkt->d, Eaddrlen);
+ memmove(ctlr->txf.srcaddr, pkt->s, Eaddrlen);
+ memmove(&ctlr->txf.type, pkt->type, 2);
+ bp->rp += ETHERHDRSIZE;
+ len = BLEN(bp);
+ off = WF_802_11_Off;
+ ctlr->txf.dlen = len+ETHERHDRSIZE-WSnapHdrLen;
+ hnputs((uchar*)&ctlr->txf.dat[0], WSnap0);
+ hnputs((uchar*)&ctlr->txf.dat[1], WSnap1);
+ hnputs((uchar*)&ctlr->txf.len, len+ETHERHDRSIZE-WSnapHdrLen);
+ }
+ else{
+ len = BLEN(bp);
+ off = WF_802_3_Off;
+ ctlr->txf.dlen = len;
+ }
+ w_write(ctlr, ctlr->txdid, 0, &ctlr->txf, sizeof(ctlr->txf));
+ w_write(ctlr, ctlr->txdid, off, bp->rp, len+2);
+
+ if(w_cmd(ctlr, WCmdReclaim|WCmdTx, ctlr->txdid)){
+ DEBUG("wavelan: transmit failed\n");
+ ctlr->ntxerr++;
+ }
+ else{
+ ctlr->txbusy = 1;
+ ctlr->txtmout = 2;
+ }
+ freeb(bp);
+}
+
+static void
+w_txdone(Ctlr* ctlr, int sts)
+{
+ ctlr->txbusy = 0;
+ ctlr->txtmout = 0;
+ if(sts & WTxErrEv)
+ ctlr->ntxerr++;
+ else
+ ctlr->ntx++;
+}
+
+/* save the stats info in the ctlr struct */
+static void
+w_stats(Ctlr* ctlr, int len)
+{
+ int i, rc;
+ ulong* p = (ulong*)&ctlr->WStats;
+ ulong* pend = (ulong*)&ctlr->end;
+
+ for (i = 0; i < len && p < pend; i++){
+ rc = csr_ins(ctlr, WR_Data1);
+ if(rc > 0xf000)
+ rc = ~rc & 0xffff;
+ p[i] += rc;
+ }
+}
+
+/* send the base station scan info to any readers */
+static void
+w_scaninfo(Ether* ether, Ctlr *ctlr, int len)
+{
+ int i, j;
+ Netfile **ep, *f, **fp;
+ Block *bp;
+ WScan *wsp;
+ ushort *scanbuf;
+
+ scanbuf = malloc(len*2);
+ if(scanbuf == nil)
+ return;
+
+ for (i = 0; i < len ; i++)
+ scanbuf[i] = csr_ins(ctlr, WR_Data1);
+
+ /* calculate number of samples */
+ len /= 25;
+ if(len == 0)
+ goto out;
+
+ i = ether->scan;
+ ep = &ether->f[Ntypes];
+ for(fp = ether->f; fp < ep && i > 0; fp++){
+ f = *fp;
+ if(f == nil || f->scan == 0)
+ continue;
+
+ bp = iallocb(100*len);
+ if(bp == nil)
+ break;
+ for(j = 0; j < len; j++){
+ wsp = (WScan*)(&scanbuf[j*25]);
+ if(wsp->ssid_len > 32)
+ wsp->ssid_len = 32;
+ bp->wp = (uchar*)seprint((char*)bp->wp, (char*)bp->lim,
+ "ssid=%.*s;bssid=%E;signal=%d;noise=%d;chan=%d%s\n",
+ wsp->ssid_len, wsp->ssid, wsp->bssid, wsp->signal,
+ wsp->noise, wsp->chan, (wsp->capinfo&(1<<4))?";wep":"");
+ }
+ qpass(f->in, bp);
+ i--;
+ }
+out:
+ free(scanbuf);
+}
+
+static int
+w_info(Ether *ether, Ctlr* ctlr)
+{
+ int sp;
+ Wltv ltv;
+
+ sp = csr_ins(ctlr, WR_InfoId);
+ ltv.len = ltv.type = 0;
+ w_read(ctlr, sp, 0, &ltv, 4);
+ ltv.len--;
+ switch(ltv.type){
+ case WTyp_Stats:
+ w_stats(ctlr, ltv.len);
+ return 0;
+ case WTyp_Scan:
+ w_scaninfo(ether, ctlr, ltv.len);
+ return 0;
+ }
+ return -1;
+}
+
+/* set scanning interval */
+static void
+w_scanbs(void *a, uint secs)
+{
+ Ether *ether = a;
+ Ctlr* ctlr = (Ctlr*) ether->ctlr;
+
+ ctlr->scanticks = secs*(1000/MSperTick);
+}
+
+static void
+w_intr(Ether *ether)
+{
+ int rc, txid;
+ Ctlr* ctlr = (Ctlr*) ether->ctlr;
+
+ if((ctlr->state & Power) == 0)
+ return;
+
+ if((ctlr->state & Attached) == 0){
+ csr_ack(ctlr, 0xffff);
+ csr_outs(ctlr, WR_IntEna, 0);
+ return;
+ }
+
+ rc = csr_ins(ctlr, WR_EvSts);
+ csr_ack(ctlr, ~WEvs); // Not interested in them
+ if(rc & WRXEv){
+ w_rxdone(ether);
+ csr_ack(ctlr, WRXEv);
+ }
+ if(rc & WTXEv){
+ w_txdone(ctlr, rc);
+ csr_ack(ctlr, WTXEv);
+ }
+ if(rc & WAllocEv){
+ ctlr->nalloc++;
+ txid = csr_ins(ctlr, WR_Alloc);
+ csr_ack(ctlr, WAllocEv);
+ if(txid == ctlr->txdid){
+ if((rc & WTXEv) == 0)
+ w_txdone(ctlr, rc);
+ }
+ }
+ if(rc & WInfoEv){
+ ctlr->ninfo++;
+ w_info(ether, ctlr);
+ csr_ack(ctlr, WInfoEv);
+ }
+ if(rc & WTxErrEv){
+ w_txdone(ctlr, rc);
+ csr_ack(ctlr, WTxErrEv);
+ }
+ if(rc & WIDropEv){
+ ctlr->nidrop++;
+ csr_ack(ctlr, WIDropEv);
+ }
+ w_txstart(ether);
+}
+
+// Watcher to ensure that the card still works properly and
+// to request WStats updates once a minute.
+// BUG: it runs much more often, see the comment below.
+
+static void
+w_timer(void* arg)
+{
+ Ether* ether = (Ether*) arg;
+ Ctlr* ctlr = (Ctlr*)ether->ctlr;
+
+ ctlr->timerproc = up;
+ for(;;){
+ tsleep(&up->sleep, return0, 0, MSperTick);
+ ctlr = (Ctlr*)ether->ctlr;
+ if(ctlr == 0)
+ break;
+ if((ctlr->state & (Attached|Power)) != (Attached|Power))
+ continue;
+ ctlr->ticks++;
+
+ ilock(ctlr);
+
+ // Seems that the card gets frames BUT does
+ // not send the interrupt; this is a problem because
+ // I suspect it runs out of receive buffers and
+ // stops receiving until a transmit watchdog
+ // reenables the card.
+ // The problem is serious because it leads to
+ // poor rtts.
+ // This can be seen clearly by commenting out
+ // the next if and doing a ping: it will stop
+ // receiving (although the icmp replies are being
+ // issued from the remote) after a few seconds.
+ // Of course this `bug' could be because I'm reading
+ // the card frames in the wrong way; due to the
+ // lack of documentation I cannot know.
+
+ if(csr_ins(ctlr, WR_EvSts)&WEvs){
+ ctlr->tickintr++;
+ w_intr(ether);
+ }
+
+ if((ctlr->ticks % 10) == 0) {
+ if(ctlr->txtmout && --ctlr->txtmout == 0){
+ ctlr->nwatchdogs++;
+ w_txdone(ctlr, WTxErrEv);
+ if(w_enable(ether)){
+ DEBUG("wavelan: wdog enable failed\n");
+ }
+ w_txstart(ether);
+ }
+ if((ctlr->ticks % 120) == 0)
+ if(ctlr->txbusy == 0)
+ w_cmd(ctlr, WCmdEnquire, WTyp_Stats);
+ if(ctlr->scanticks > 0)
+ if((ctlr->ticks % ctlr->scanticks) == 0)
+ if(ctlr->txbusy == 0)
+ w_cmd(ctlr, WCmdEnquire, WTyp_Scan);
+ }
+ iunlock(ctlr);
+ }
+ pexit("terminated", 0);
+}
+
+void
+w_multicast(void*, uchar*, int)
+{
+ // BUG: to be added.
+}
+
+void
+w_attach(Ether* ether)
+{
+ Ctlr* ctlr;
+ char name[64];
+ int rc;
+
+ if(ether->ctlr == 0)
+ return;
+
+ snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno);
+ ctlr = (Ctlr*) ether->ctlr;
+ if((ctlr->state & Attached) == 0){
+ ilock(ctlr);
+ rc = w_enable(ether);
+ iunlock(ctlr);
+ if(rc == 0){
+ ctlr->state |= Attached;
+ kproc(name, w_timer, ether);
+ } else
+ print("#l%d: enable failed\n",ether->ctlrno);
+ }
+}
+
+void
+w_detach(Ether* ether)
+{
+ Ctlr* ctlr;
+ char name[64];
+
+ if(ether->ctlr == nil)
+ return;
+
+ snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno);
+ ctlr = (Ctlr*) ether->ctlr;
+ if(ctlr->state & Attached){
+ ilock(ctlr);
+ w_intdis(ctlr);
+ if(ctlr->timerproc){
+ if(!postnote(ctlr->timerproc, 1, "kill", NExit))
+ print("timerproc note not posted\n");
+ print("w_detach, killing 0x%p\n", ctlr->timerproc);
+ }
+ ctlr->state &= ~Attached;
+ iunlock(ctlr);
+ }
+ ether->ctlr = nil;
+}
+
+void
+w_power(Ether* ether, int on)
+{
+ Ctlr *ctlr;
+
+ ctlr = (Ctlr*) ether->ctlr;
+ ilock(ctlr);
+iprint("w_power %d\n", on);
+ if(on){
+ if((ctlr->state & Power) == 0){
+ if (wavelanreset(ether, ctlr) < 0){
+ iprint("w_power: reset failed\n");
+ iunlock(ctlr);
+ w_detach(ether);
+ free(ctlr);
+ return;
+ }
+ if(ctlr->state & Attached)
+ w_enable(ether);
+ ctlr->state |= Power;
+ }
+ }else{
+ if(ctlr->state & Power){
+ if(ctlr->state & Attached)
+ w_intdis(ctlr);
+ ctlr->state &= ~Power;
+ }
+ }
+ iunlock(ctlr);
+}
+
+#define PRINTSTAT(fmt,val) l += snprint(p+l, READSTR-l, (fmt), (val))
+#define PRINTSTR(fmt) l += snprint(p+l, READSTR-l, (fmt))
+
+long
+w_ifstat(Ether* ether, void* a, long n, ulong offset)
+{
+ Ctlr *ctlr = (Ctlr*) ether->ctlr;
+ char *k, *p;
+ int i, l, txid;
+
+ ether->oerrs = ctlr->ntxerr;
+ ether->crcs = ctlr->nrxfcserr;
+ ether->frames = 0;
+ ether->buffs = ctlr->nrxdropnobuf;
+ ether->overflows = 0;
+
+ //
+ // Offset must be zero or there's a possibility the
+ // new data won't match the previous read.
+ //
+ if(n == 0 || offset != 0)
+ return 0;
+
+ p = malloc(READSTR);
+ l = 0;
+
+ PRINTSTAT("Signal: %d\n", ctlr->signal-149);
+ PRINTSTAT("Noise: %d\n", ctlr->noise-149);
+ PRINTSTAT("SNR: %ud\n", ctlr->signal-ctlr->noise);
+ PRINTSTAT("Interrupts: %lud\n", ctlr->nints);
+ PRINTSTAT("Double Interrupts: %lud\n", ctlr->ndoubleint);
+ PRINTSTAT("TxPackets: %lud\n", ctlr->ntx);
+ PRINTSTAT("RxPackets: %lud\n", ctlr->nrx);
+ PRINTSTAT("TxErrors: %lud\n", ctlr->ntxerr);
+ PRINTSTAT("RxErrors: %lud\n", ctlr->nrxerr);
+ PRINTSTAT("TxRequests: %lud\n", ctlr->ntxrq);
+ PRINTSTAT("AllocEvs: %lud\n", ctlr->nalloc);
+ PRINTSTAT("InfoEvs: %lud\n", ctlr->ninfo);
+ PRINTSTAT("InfoDrop: %lud\n", ctlr->nidrop);
+ PRINTSTAT("WatchDogs: %lud\n", ctlr->nwatchdogs);
+ PRINTSTAT("Ticks: %ud\n", ctlr->ticks);
+ PRINTSTAT("TickIntr: %ud\n", ctlr->tickintr);
+ k = ((ctlr->state & Attached) ? "attached" : "not attached");
+ PRINTSTAT("Card %s", k);
+ k = ((ctlr->state & Power) ? "on" : "off");
+ PRINTSTAT(", power %s", k);
+ k = ((ctlr->txbusy)? ", txbusy" : "");
+ PRINTSTAT("%s\n", k);
+
+ if(ctlr->hascrypt){
+ PRINTSTR("Keys: ");
+ for (i = 0; i < WNKeys; i++){
+ if(ctlr->keys.keys[i].len == 0)
+ PRINTSTR("none ");
+ else if(SEEKEYS == 0)
+ PRINTSTR("set ");
+ else
+ PRINTSTAT("%s ", ctlr->keys.keys[i].dat);
+ }
+ PRINTSTR("\n");
+ }
+
+ // real card stats
+ ilock(ctlr);
+ PRINTSTR("\nCard stats: \n");
+ PRINTSTAT("Status: %ux\n", csr_ins(ctlr, WR_Sts));
+ PRINTSTAT("Event status: %ux\n", csr_ins(ctlr, WR_EvSts));
+ i = ltv_ins(ctlr, WTyp_Ptype);
+ PRINTSTAT("Port type: %d\n", i);
+ PRINTSTAT("Transmit rate: %d\n", ltv_ins(ctlr, WTyp_TxRate));
+ PRINTSTAT("Current Transmit rate: %d\n",
+ ltv_ins(ctlr, WTyp_CurTxRate));
+ PRINTSTAT("Channel: %d\n", ltv_ins(ctlr, WTyp_Chan));
+ PRINTSTAT("AP density: %d\n", ltv_ins(ctlr, WTyp_ApDens));
+ PRINTSTAT("Promiscuous mode: %d\n", ltv_ins(ctlr, WTyp_Prom));
+ if(i == WPTypeAdHoc)
+ PRINTSTAT("SSID name: %s\n", ltv_inname(ctlr, WTyp_NetName));
+ else {
+ Wltv ltv;
+ PRINTSTAT("Current name: %s\n", ltv_inname(ctlr, WTyp_CurName));
+ ltv.type = WTyp_BaseID;
+ ltv.len = 4;
+ if(w_inltv(ctlr, &ltv))
+ print("#l%d: unable to read base station mac addr\n", ether->ctlrno);
+ l += snprint(p+l, READSTR-l, "Base station: %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
+ ltv.addr[0], ltv.addr[1], ltv.addr[2], ltv.addr[3], ltv.addr[4], ltv.addr[5]);
+ }
+ PRINTSTAT("Net name: %s\n", ltv_inname(ctlr, WTyp_WantName));
+ PRINTSTAT("Node name: %s\n", ltv_inname(ctlr, WTyp_NodeName));
+ if(ltv_ins(ctlr, WTyp_HasCrypt) == 0)
+ PRINTSTR("WEP: not supported\n");
+ else {
+ if(ltv_ins(ctlr, WTyp_Crypt) == 0)
+ PRINTSTR("WEP: disabled\n");
+ else{
+ PRINTSTR("WEP: enabled\n");
+ k = ((ctlr->xclear)? "excluded": "included");
+ PRINTSTAT("Clear packets: %s\n", k);
+ txid = ltv_ins(ctlr, WTyp_TxKey);
+ PRINTSTAT("Transmit key id: %d\n", txid);
+ }
+ }
+ iunlock(ctlr);
+
+ PRINTSTAT("ntxuframes: %lud\n", ctlr->ntxuframes);
+ PRINTSTAT("ntxmframes: %lud\n", ctlr->ntxmframes);
+ PRINTSTAT("ntxfrags: %lud\n", ctlr->ntxfrags);
+ PRINTSTAT("ntxubytes: %lud\n", ctlr->ntxubytes);
+ PRINTSTAT("ntxmbytes: %lud\n", ctlr->ntxmbytes);
+ PRINTSTAT("ntxdeferred: %lud\n", ctlr->ntxdeferred);
+ PRINTSTAT("ntxsretries: %lud\n", ctlr->ntxsretries);
+ PRINTSTAT("ntxmultiretries: %lud\n", ctlr->ntxmultiretries);
+ PRINTSTAT("ntxretrylimit: %lud\n", ctlr->ntxretrylimit);
+ PRINTSTAT("ntxdiscards: %lud\n", ctlr->ntxdiscards);
+ PRINTSTAT("nrxuframes: %lud\n", ctlr->nrxuframes);
+ PRINTSTAT("nrxmframes: %lud\n", ctlr->nrxmframes);
+ PRINTSTAT("nrxfrags: %lud\n", ctlr->nrxfrags);
+ PRINTSTAT("nrxubytes: %lud\n", ctlr->nrxubytes);
+ PRINTSTAT("nrxmbytes: %lud\n", ctlr->nrxmbytes);
+ PRINTSTAT("nrxfcserr: %lud\n", ctlr->nrxfcserr);
+ PRINTSTAT("nrxdropnobuf: %lud\n", ctlr->nrxdropnobuf);
+ PRINTSTAT("nrxdropnosa: %lud\n", ctlr->nrxdropnosa);
+ PRINTSTAT("nrxcantdecrypt: %lud\n", ctlr->nrxcantdecrypt);
+ PRINTSTAT("nrxmsgfrag: %lud\n", ctlr->nrxmsgfrag);
+ PRINTSTAT("nrxmsgbadfrag: %lud\n", ctlr->nrxmsgbadfrag);
+ USED(l);
+ n = readstr(offset, a, n, p);
+ free(p);
+ return n;
+}
+#undef PRINTSTR
+#undef PRINTSTAT
+
+int
+w_option(Ctlr* ctlr, char* buf, long n)
+{
+ char *p;
+ int i, r;
+ WKey *key;
+ Cmdbuf *cb;
+
+ r = 0;
+
+ cb = parsecmd(buf, n);
+ if(cb->nf < 2)
+ r = -1;
+ else if(cistrcmp(cb->f[0], "essid") == 0){
+ if(cistrcmp(cb->f[1],"default") == 0)
+ p = "";
+ else
+ p = cb->f[1];
+ if(ctlr->ptype == WPTypeAdHoc){
+ memset(ctlr->netname, 0, sizeof(ctlr->netname));
+ strncpy(ctlr->netname, p, WNameLen);
+ }
+ else{
+ memset(ctlr->wantname, 0, sizeof(ctlr->wantname));
+ strncpy(ctlr->wantname, p, WNameLen);
+ }
+ }
+ else if(cistrcmp(cb->f[0], "station") == 0){
+ memset(ctlr->nodename, 0, sizeof(ctlr->nodename));
+ strncpy(ctlr->nodename, cb->f[1], WNameLen);
+ }
+ else if(cistrcmp(cb->f[0], "channel") == 0){
+ if((i = atoi(cb->f[1])) >= 1 && i <= 16)
+ ctlr->chan = i;
+ else
+ r = -1;
+ }
+ else if(cistrcmp(cb->f[0], "mode") == 0){
+ if(cistrcmp(cb->f[1], "managed") == 0)
+ ctlr->ptype = WPTypeManaged;
+ else if(cistrcmp(cb->f[1], "wds") == 0)
+ ctlr->ptype = WPTypeWDS;
+ else if(cistrcmp(cb->f[1], "adhoc") == 0)
+ ctlr->ptype = WPTypeAdHoc;
+ else if((i = atoi(cb->f[1])) >= 1 && i <= 3)
+ ctlr->ptype = i;
+ else
+ r = -1;
+ }
+ else if(cistrcmp(cb->f[0], "ibss") == 0){
+ if(cistrcmp(cb->f[1], "on") == 0)
+ ctlr->createibss = 1;
+ else
+ ctlr->createibss = 0;
+ }
+ else if(cistrcmp(cb->f[0], "crypt") == 0){
+ if(cistrcmp(cb->f[1], "off") == 0)
+ ctlr->crypt = 0;
+ else if(cistrcmp(cb->f[1], "on") == 0 && ctlr->hascrypt)
+ ctlr->crypt = 1;
+ else
+ r = -1;
+ }
+ else if(cistrcmp(cb->f[0], "clear") == 0){
+ if(cistrcmp(cb->f[1], "on") == 0)
+ ctlr->xclear = 0;
+ else if(cistrcmp(cb->f[1], "off") == 0 && ctlr->hascrypt)
+ ctlr->xclear = 1;
+ else
+ r = -1;
+ }
+ else if(cistrncmp(cb->f[0], "key", 3) == 0){
+ if((i = atoi(cb->f[0]+3)) >= 1 && i <= WNKeys){
+ ctlr->txkey = i-1;
+ key = &ctlr->keys.keys[ctlr->txkey];
+ key->len = strlen(cb->f[1]);
+ if(key->len > WKeyLen)
+ key->len = WKeyLen;
+ memset(key->dat, 0, sizeof(key->dat));
+ memmove(key->dat, cb->f[1], key->len);
+ }
+ else
+ r = -1;
+ }
+ else if(cistrcmp(cb->f[0], "txkey") == 0){
+ if((i = atoi(cb->f[1])) >= 1 && i <= WNKeys)
+ ctlr->txkey = i-1;
+ else
+ r = -1;
+ }
+ else if(cistrcmp(cb->f[0], "pm") == 0){
+ if(cistrcmp(cb->f[1], "off") == 0)
+ ctlr->pmena = 0;
+ else if(cistrcmp(cb->f[1], "on") == 0){
+ ctlr->pmena = 1;
+ if(cb->nf == 3){
+ i = atoi(cb->f[2]);
+ // check range here? what are the units?
+ ctlr->pmwait = i;
+ }
+ }
+ else
+ r = -1;
+ }
+ else
+ r = -2;
+ free(cb);
+
+ return r;
+}
+
+long
+w_ctl(Ether* ether, void* buf, long n)
+{
+ Ctlr *ctlr;
+
+ if((ctlr = ether->ctlr) == nil)
+ error(Enonexist);
+ if((ctlr->state & Attached) == 0)
+ error(Eshutdown);
+
+ ilock(ctlr);
+ if(w_option(ctlr, buf, n)){
+ iunlock(ctlr);
+ error(Ebadctl);
+ }
+ if(ctlr->txbusy)
+ w_txdone(ctlr, WTxErrEv);
+ w_enable(ether);
+ w_txstart(ether);
+ iunlock(ctlr);
+
+ return n;
+}
+
+void
+w_transmit(Ether* ether)
+{
+ Ctlr* ctlr = ether->ctlr;
+
+ if(ctlr == 0)
+ return;
+
+ ilock(ctlr);
+ ctlr->ntxrq++;
+ w_txstart(ether);
+ iunlock(ctlr);
+}
+
+void
+w_promiscuous(void* arg, int on)
+{
+ Ether* ether = (Ether*)arg;
+ Ctlr* ctlr = ether->ctlr;
+
+ if(ctlr == nil)
+ error("card not found");
+ if((ctlr->state & Attached) == 0)
+ error("card not attached");
+ ilock(ctlr);
+ ltv_outs(ctlr, WTyp_Prom, (on?1:0));
+ iunlock(ctlr);
+}
+
+void
+w_interrupt(Ureg* ,void* arg)
+{
+ Ether* ether = (Ether*) arg;
+ Ctlr* ctlr = (Ctlr*) ether->ctlr;
+
+ if(ctlr == 0)
+ return;
+ ilock(ctlr);
+ ctlr->nints++;
+ w_intr(ether);
+ iunlock(ctlr);
+}
+
+int
+wavelanreset(Ether* ether, Ctlr *ctlr)
+{
+ Wltv ltv;
+
+ iprint("wavelanreset, iob 0x%ux\n", ctlr->iob);
+ w_intdis(ctlr);
+ if(w_cmd(ctlr,WCmdIni,0)){
+ iprint("#l%d: init failed\n", ether->ctlrno);
+ return -1;
+ }
+ w_intdis(ctlr);
+ ltv_outs(ctlr, WTyp_Tick, 8);
+
+ ctlr->chan = 0;
+ ctlr->ptype = WDfltPType;
+ ctlr->txkey = 0;
+ ctlr->createibss = 0;
+ ctlr->keys.len = sizeof(WKey)*WNKeys/2 + 1;
+ ctlr->keys.type = WTyp_Keys;
+ if(ctlr->hascrypt = ltv_ins(ctlr, WTyp_HasCrypt))
+ ctlr->crypt = 1;
+ *ctlr->netname = *ctlr->wantname = 0;
+ strcpy(ctlr->nodename, "Plan 9 STA");
+
+ ctlr->netname[WNameLen-1] = 0;
+ ctlr->wantname[WNameLen-1] = 0;
+ ctlr->nodename[WNameLen-1] =0;
+
+ ltv.type = WTyp_Mac;
+ ltv.len = 4;
+ if(w_inltv(ctlr, &ltv)){
+ iprint("#l%d: unable to read mac addr\n",
+ ether->ctlrno);
+ return -1;
+ }
+ memmove(ether->ea, ltv.addr, Eaddrlen);
+
+ if(ctlr->chan == 0)
+ ctlr->chan = ltv_ins(ctlr, WTyp_Chan);
+ ctlr->apdensity = WDfltApDens;
+ ctlr->rtsthres = WDfltRtsThres;
+ ctlr->txrate = WDfltTxRate;
+ ctlr->maxlen = WMaxLen;
+ ctlr->pmena = 0;
+ ctlr->pmwait = 100;
+ ctlr->signal = 1;
+ ctlr->noise = 1;
+ ctlr->state |= Power;
+
+ // free old Ctlr struct if resetting after suspend
+ if(ether->ctlr && ether->ctlr != ctlr)
+ free(ether->ctlr);
+
+ // link to ether
+ ether->ctlr = ctlr;
+ ether->mbps = 10;
+ ether->attach = w_attach;
+ ether->detach = w_detach;
+ ether->interrupt = w_interrupt;
+ ether->transmit = w_transmit;
+ ether->ifstat = w_ifstat;
+ ether->ctl = w_ctl;
+ ether->power = w_power;
+ ether->promiscuous = w_promiscuous;
+ ether->multicast = w_multicast;
+ ether->scanbs = w_scanbs;
+ ether->arg = ether;
+
+ DEBUG("#l%d: irq %lud port %lx type %s",
+ ether->ctlrno, ether->intnum, ether->ports[0].port, ether->type);
+ DEBUG(" %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux\n",
+ ether->ea[0], ether->ea[1], ether->ea[2],
+ ether->ea[3], ether->ea[4], ether->ea[5]);
+
+ return 0;
+}
+
+char* wavenames[] = {
+ "WaveLAN/IEEE",
+ "TrueMobile 1150",
+ "Instant Wireless ; Network PC CARD",
+ "Instant Wireless Network PC Card",
+ "Avaya Wireless PC Card",
+ "AirLancer MC-11",
+ nil,
+};
diff --git a/sys/src/9/bitsy/wavelan.h b/sys/src/9/bitsy/wavelan.h
new file mode 100755
index 000000000..c3db893c1
--- /dev/null
+++ b/sys/src/9/bitsy/wavelan.h
@@ -0,0 +1 @@
+#include "../pc/wavelan.h"
diff --git a/sys/src/9/boot/aux.c b/sys/src/9/boot/aux.c
new file mode 100755
index 000000000..b5dec7764
--- /dev/null
+++ b/sys/src/9/boot/aux.c
@@ -0,0 +1,182 @@
+#include <u.h>
+#include <libc.h>
+#include <../boot/boot.h>
+
+/*
+int
+plumb(char *dir, char *dest, int *efd, char *here)
+{
+ char buf[128];
+ char name[128];
+ int n;
+
+ sprint(name, "%s/clone", dir);
+ efd[0] = open(name, ORDWR);
+ if(efd[0] < 0)
+ return -1;
+ n = read(efd[0], buf, sizeof(buf)-1);
+ if(n < 0){
+ close(efd[0]);
+ return -1;
+ }
+ buf[n] = 0;
+ sprint(name, "%s/%s/data", dir, buf);
+ if(here){
+ sprint(buf, "announce %s", here);
+ if(sendmsg(efd[0], buf) < 0){
+ close(efd[0]);
+ return -1;
+ }
+ }
+ sprint(buf, "connect %s", dest);
+ if(sendmsg(efd[0], buf) < 0){
+ close(efd[0]);
+ return -1;
+ }
+ efd[1] = open(name, ORDWR);
+ if(efd[1] < 0){
+ close(efd[0]);
+ return -1;
+ }
+ return efd[1];
+}
+ */
+
+int
+sendmsg(int fd, char *msg)
+{
+ int n;
+
+ n = strlen(msg);
+ if(write(fd, msg, n) != n)
+ return -1;
+ return 0;
+}
+
+void
+warning(char *s)
+{
+ char buf[ERRMAX];
+
+ buf[0] = '\0';
+ errstr(buf, sizeof buf);
+ fprint(2, "boot: %s: %s\n", s, buf);
+}
+
+void
+fatal(char *s)
+{
+ char buf[ERRMAX];
+
+ buf[0] = '\0';
+ errstr(buf, sizeof buf);
+ fprint(2, "boot: %s: %s\n", s, buf);
+ exits(0);
+}
+
+int
+readfile(char *name, char *buf, int len)
+{
+ int f, n;
+
+ buf[0] = 0;
+ f = open(name, OREAD);
+ if(f < 0)
+ return -1;
+ n = read(f, buf, len-1);
+ if(n >= 0)
+ buf[n] = 0;
+ close(f);
+ return 0;
+}
+
+int
+writefile(char *name, char *buf, int len)
+{
+ int f, n;
+
+ f = open(name, OWRITE);
+ if(f < 0)
+ return -1;
+ n = write(f, buf, len);
+ close(f);
+ return (n != len) ? -1 : 0;
+}
+
+void
+setenv(char *name, char *val)
+{
+ int f;
+ char ename[64];
+
+ snprint(ename, sizeof ename, "#e/%s", name);
+ f = create(ename, 1, 0666);
+ if(f < 0){
+ fprint(2, "create %s: %r\n", ename);
+ return;
+ }
+ write(f, val, strlen(val));
+ close(f);
+}
+
+void
+srvcreate(char *name, int fd)
+{
+ char *srvname;
+ int f;
+ char buf[64];
+
+ srvname = strrchr(name, '/');
+ if(srvname)
+ srvname++;
+ else
+ srvname = name;
+
+ snprint(buf, sizeof buf, "#s/%s", srvname);
+ f = create(buf, 1, 0666);
+ if(f < 0)
+ fatal(buf);
+ sprint(buf, "%d", fd);
+ if(write(f, buf, strlen(buf)) != strlen(buf))
+ fatal("write");
+ close(f);
+}
+
+void
+catchint(void *a, char *note)
+{
+ USED(a);
+ if(strcmp(note, "alarm") == 0)
+ noted(NCONT);
+ noted(NDFLT);
+}
+
+int
+outin(char *prompt, char *def, int len)
+{
+ int n;
+ char buf[256];
+
+ if(len >= sizeof buf)
+ len = sizeof(buf)-1;
+
+ if(cpuflag){
+ notify(catchint);
+ alarm(15*1000);
+ }
+ print("%s[%s]: ", prompt, *def ? def : "no default");
+ memset(buf, 0, sizeof buf);
+ n = read(0, buf, len);
+ if(cpuflag){
+ alarm(0);
+ notify(0);
+ }
+
+ if(n < 0)
+ return 1;
+ if(n > 1){
+ buf[n-1] = 0;
+ strcpy(def, buf);
+ }
+ return n;
+}
diff --git a/sys/src/9/boot/boot.c b/sys/src/9/boot/boot.c
new file mode 100755
index 000000000..db181a09d
--- /dev/null
+++ b/sys/src/9/boot/boot.c
@@ -0,0 +1,353 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include "../boot/boot.h"
+
+char cputype[64];
+char sys[2*64];
+char reply[256];
+int printcol;
+int mflag;
+int fflag;
+int kflag;
+
+char *bargv[Nbarg];
+int bargc;
+
+static void swapproc(void);
+static Method *rootserver(char*);
+static void usbinit(void);
+static void kbmap(void);
+
+void
+boot(int argc, char *argv[])
+{
+ int fd, afd;
+ Method *mp;
+ char *cmd, cmdbuf[64], *iargv[16];
+ char rootbuf[64];
+ int islocal, ishybrid;
+ char *rp, *rsp;
+ int iargc, n;
+ char buf[32];
+ AuthInfo *ai;
+
+ fmtinstall('r', errfmt);
+
+ /*
+ * we should inherit the standard fds all referring to /dev/cons,
+ * but we're being paranoid.
+ */
+ close(0);
+ close(1);
+ close(2);
+ bind("#c", "/dev", MBEFORE);
+ open("/dev/cons", OREAD);
+ open("/dev/cons", OWRITE);
+ open("/dev/cons", OWRITE);
+ /*
+ * init will reinitialize its namespace.
+ * #ec gets us plan9.ini settings (*var variables).
+ */
+ bind("#ec", "/env", MREPL);
+ bind("#e", "/env", MBEFORE|MCREATE);
+ bind("#s", "/srv", MREPL|MCREATE);
+#ifdef DEBUG
+ print("argc=%d\n", argc);
+ for(fd = 0; fd < argc; fd++)
+ print("%#p %s ", argv[fd], argv[fd]);
+ print("\n");
+#endif DEBUG
+
+ ARGBEGIN{
+ case 'k':
+ kflag = 1;
+ break;
+ case 'm':
+ mflag = 1;
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ }ARGEND
+
+ readfile("#e/cputype", cputype, sizeof(cputype));
+
+ /*
+ * set up usb keyboard, mouse and disk, if any.
+ */
+ usbinit();
+
+ /*
+ * pick a method and initialize it
+ */
+ if(method[0].name == nil)
+ fatal("no boot methods");
+ mp = rootserver(argc ? *argv : 0);
+ (*mp->config)(mp);
+ islocal = strcmp(mp->name, "local") == 0;
+ ishybrid = strcmp(mp->name, "hybrid") == 0;
+
+ /*
+ * load keymap if it's there.
+ */
+ kbmap();
+
+ /*
+ * authentication agent
+ */
+ authentication(cpuflag);
+
+ /*
+ * connect to the root file system
+ */
+ fd = (*mp->connect)();
+ if(fd < 0)
+ fatal("can't connect to file server");
+ if(getenv("srvold9p"))
+ fd = old9p(fd);
+ if(!islocal && !ishybrid){
+ if(cfs)
+ fd = (*cfs)(fd);
+ }
+ print("version...");
+ buf[0] = '\0';
+ n = fversion(fd, 0, buf, sizeof buf);
+ if(n < 0)
+ fatal("can't init 9P");
+ srvcreate("boot", fd);
+
+ /*
+ * create the name space, mount the root fs
+ */
+ if(bind("/", "/", MREPL) < 0)
+ fatal("bind /");
+ rp = getenv("rootspec");
+ if(rp == nil)
+ rp = "";
+
+ afd = fauth(fd, rp);
+ if(afd >= 0){
+ ai = auth_proxy(afd, auth_getkey, "proto=p9any role=client");
+ if(ai == nil)
+ print("authentication failed (%r), trying mount anyways\n");
+ }
+ if(mount(fd, afd, "/root", MREPL|MCREATE, rp) < 0)
+ fatal("mount /");
+ rsp = rp;
+ rp = getenv("rootdir");
+ if(rp == nil)
+ rp = rootdir;
+ if(bind(rp, "/", MAFTER|MCREATE) < 0){
+ if(strncmp(rp, "/root", 5) == 0){
+ fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
+ fatal("second bind /");
+ }
+ snprint(rootbuf, sizeof rootbuf, "/root/%s", rp);
+ rp = rootbuf;
+ if(bind(rp, "/", MAFTER|MCREATE) < 0){
+ fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
+ if(strcmp(rootbuf, "/root//plan9") == 0){
+ fprint(2, "**** warning: remove rootdir=/plan9 entry from plan9.ini\n");
+ rp = "/root";
+ if(bind(rp, "/", MAFTER|MCREATE) < 0)
+ fatal("second bind /");
+ }else
+ fatal("second bind /");
+ }
+ }
+ close(fd);
+ setenv("rootdir", rp);
+
+ settime(islocal, afd, rsp);
+ if(afd > 0)
+ close(afd);
+ swapproc();
+
+ cmd = getenv("init");
+ if(cmd == nil){
+ sprint(cmdbuf, "/%s/init -%s%s", cputype,
+ cpuflag ? "c" : "t", mflag ? "m" : "");
+ cmd = cmdbuf;
+ }
+ iargc = tokenize(cmd, iargv, nelem(iargv)-1);
+ cmd = iargv[0];
+
+ /* make iargv[0] basename(iargv[0]) */
+ if(iargv[0] = strrchr(iargv[0], '/'))
+ iargv[0]++;
+ else
+ iargv[0] = cmd;
+
+ iargv[iargc] = nil;
+
+ exec(cmd, iargv);
+ fatal(cmd);
+}
+
+static Method*
+findmethod(char *a)
+{
+ Method *mp;
+ int i, j;
+ char *cp;
+
+ if((i = strlen(a)) == 0)
+ return nil;
+ cp = strchr(a, '!');
+ if(cp)
+ i = cp - a;
+ for(mp = method; mp->name; mp++){
+ j = strlen(mp->name);
+ if(j > i)
+ j = i;
+ if(strncmp(a, mp->name, j) == 0)
+ break;
+ }
+ if(mp->name)
+ return mp;
+ return nil;
+}
+
+/*
+ * ask user from whence cometh the root file system
+ */
+static Method*
+rootserver(char *arg)
+{
+ char prompt[256];
+ Method *mp;
+ char *cp;
+ int n;
+
+ /* look for required reply */
+ readfile("#e/nobootprompt", reply, sizeof(reply));
+ if(reply[0]){
+ mp = findmethod(reply);
+ if(mp)
+ goto HaveMethod;
+ print("boot method %s not found\n", reply);
+ reply[0] = 0;
+ }
+
+ /* make list of methods */
+ mp = method;
+ n = sprint(prompt, "root is from (%s", mp->name);
+ for(mp++; mp->name; mp++)
+ n += sprint(prompt+n, ", %s", mp->name);
+ sprint(prompt+n, ")");
+
+ /* create default reply */
+ readfile("#e/bootargs", reply, sizeof(reply));
+ if(reply[0] == 0 && arg != 0)
+ strcpy(reply, arg);
+ if(reply[0]){
+ mp = findmethod(reply);
+ if(mp == 0)
+ reply[0] = 0;
+ }
+ if(reply[0] == 0)
+ strcpy(reply, method->name);
+
+ /* parse replies */
+ do{
+ outin(prompt, reply, sizeof(reply));
+ mp = findmethod(reply);
+ }while(mp == nil);
+
+HaveMethod:
+ bargc = tokenize(reply, bargv, Nbarg-2);
+ bargv[bargc] = nil;
+ cp = strchr(reply, '!');
+ if(cp)
+ strcpy(sys, cp+1);
+ return mp;
+}
+
+static void
+swapproc(void)
+{
+ int fd;
+
+ fd = open("#c/swap", OWRITE);
+ if(fd < 0){
+ warning("opening #c/swap");
+ return;
+ }
+ if(write(fd, "start", 5) <= 0)
+ warning("starting swap kproc");
+ close(fd);
+}
+
+int
+old9p(int fd)
+{
+ int p[2];
+
+ if(pipe(p) < 0)
+ fatal("pipe");
+
+ print("srvold9p...");
+ switch(fork()) {
+ case -1:
+ fatal("rfork srvold9p");
+ case 0:
+ dup(fd, 1);
+ close(fd);
+ dup(p[0], 0);
+ close(p[0]);
+ close(p[1]);
+ execl("/srvold9p", "srvold9p", "-s", 0);
+ fatal("exec srvold9p");
+ default:
+ close(fd);
+ close(p[0]);
+ }
+ return p[1];
+}
+
+static void
+usbinit(void)
+{
+ static char usbd[] = "/boot/usbd";
+
+ if(access("#u/usb/ctl", 0) >= 0 && bind("#u", "/dev", MAFTER) >= 0 &&
+ access(usbd, AEXIST) >= 0)
+ run(usbd, nil);
+}
+
+static void
+kbmap(void)
+{
+ char *f;
+ int n, in, out;
+ char buf[1024];
+
+ f = getenv("kbmap");
+ if(f == nil)
+ return;
+ if(bind("#κ", "/dev", MAFTER) < 0){
+ warning("can't bind #κ");
+ return;
+ }
+
+ in = open(f, OREAD);
+ if(in < 0){
+ warning("can't open kbd map: %r");
+ return;
+ }
+ out = open("/dev/kbmap", OWRITE);
+ if(out < 0) {
+ warning("can't open /dev/kbmap: %r");
+ close(in);
+ return;
+ }
+ while((n = read(in, buf, sizeof(buf))) > 0)
+ if(write(out, buf, n) != n){
+ warning("write to /dev/kbmap failed");
+ break;
+ }
+ close(in);
+ close(out);
+}
diff --git a/sys/src/9/boot/boot.h b/sys/src/9/boot/boot.h
new file mode 100755
index 000000000..65b20abda
--- /dev/null
+++ b/sys/src/9/boot/boot.h
@@ -0,0 +1,73 @@
+typedef struct Method Method;
+struct Method
+{
+ char *name;
+ void (*config)(Method*);
+ int (*connect)(void);
+ char *arg;
+};
+enum
+{
+ Statsz= 256,
+ Nbarg= 16,
+};
+
+extern void authentication(int);
+extern char* bootdisk;
+extern char* rootdir;
+extern int (*cfs)(int);
+extern int cpuflag;
+extern char cputype[];
+extern int fflag;
+extern int kflag;
+extern Method method[];
+extern void (*pword)(int, Method*);
+extern char sys[];
+extern uchar hostkey[];
+extern uchar statbuf[Statsz];
+extern int bargc;
+extern char *bargv[Nbarg];
+extern int pcload;
+
+/* libc equivalent */
+extern int cache(int);
+extern char* checkkey(Method*, char*, char*);
+extern void fatal(char*);
+extern void getpasswd(char*, int);
+extern void key(int, Method*);
+extern int outin(char*, char*, int);
+extern int plumb(char*, char*, int*, char*);
+extern int readfile(char*, char*, int);
+extern long readn(int, void*, long);
+extern void run(char *file, ...);
+extern int sendmsg(int, char*);
+extern void setenv(char*, char*);
+extern void settime(int, int, char*);
+extern void srvcreate(char*, int);
+extern void warning(char*);
+extern int writefile(char*, char*, int);
+extern void boot(int, char **);
+extern void doauthenticate(int, Method*);
+extern int old9p(int);
+extern int parsefields(char*, char**, int, char*);
+
+/* methods */
+extern void configtcp(Method*);
+extern int connecttcp(void);
+
+extern void configlocal(Method*);
+extern int connectlocal(void);
+
+extern void configsac(Method*);
+extern int connectsac(void);
+
+extern void configpaq(Method*);
+extern int connectpaq(void);
+
+extern void configembed(Method*);
+extern int connectembed(void);
+
+extern void configip(int, char**, int);
+
+/* hack for passing authentication address */
+extern char *authaddr;
diff --git a/sys/src/9/boot/bootauth.c b/sys/src/9/boot/bootauth.c
new file mode 100755
index 000000000..c22b9eb4d
--- /dev/null
+++ b/sys/src/9/boot/bootauth.c
@@ -0,0 +1,72 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include "../boot/boot.h"
+
+char *authaddr;
+static void glenda(void);
+
+void
+authentication(int cpuflag)
+{
+ char *s;
+ char *argv[16], **av;
+ int ac;
+
+ if(access("/boot/factotum", AEXEC) < 0){
+ glenda();
+ return;
+ }
+
+ /* start agent */
+ ac = 0;
+ av = argv;
+ av[ac++] = "factotum";
+ if(getenv("debugfactotum"))
+ av[ac++] = "-p";
+ s = getenv("factotumopts");
+ if(s != nil && *s != '\0')
+ av[ac++] = s;
+// av[ac++] = "-d"; /* debug traces */
+// av[ac++] = "-D"; /* 9p messages */
+ if(cpuflag)
+ av[ac++] = "-S";
+ else
+ av[ac++] = "-u";
+ av[ac++] = "-sfactotum";
+ if(authaddr != nil){
+ av[ac++] = "-a";
+ av[ac++] = authaddr;
+ }
+ av[ac] = 0;
+ switch(fork()){
+ case -1:
+ fatal("starting factotum: %r");
+ case 0:
+ exec("/boot/factotum", av);
+ fatal("execing /boot/factotum");
+ }
+
+ /* wait for agent to really be there */
+ while(access("/mnt/factotum", 0) < 0)
+ sleep(250);
+}
+
+static void
+glenda(void)
+{
+ int fd;
+ char *s;
+
+ s = getenv("user");
+ if(s == nil)
+ s = "glenda";
+
+ fd = open("#c/hostowner", OWRITE);
+ if(fd >= 0){
+ if(write(fd, s, strlen(s)) != strlen(s))
+ fprint(2, "setting #c/hostowner to %s: %r\n", s);
+ close(fd);
+ }
+}
diff --git a/sys/src/9/boot/bootcache.c b/sys/src/9/boot/bootcache.c
new file mode 100755
index 000000000..eb748e989
--- /dev/null
+++ b/sys/src/9/boot/bootcache.c
@@ -0,0 +1,80 @@
+#include <u.h>
+#include <libc.h>
+#include <../boot/boot.h>
+
+uchar statbuf[Statsz];
+
+int
+cache(int fd)
+{
+ int argc, i, p[2];
+ char *argv[5], bd[32], buf[256], partition[64], *pp;
+
+ if(stat("/boot/cfs", statbuf, sizeof statbuf) < 0)
+ return fd;
+
+ *partition = 0;
+
+ bind("#S", "/dev", MAFTER);
+ readfile("#e/cfs", buf, sizeof(buf));
+ if(*buf){
+ argc = tokenize(buf, argv, 4);
+ for(i = 0; i < argc; i++){
+ if(strcmp(argv[i], "off") == 0)
+ return fd;
+ else if(stat(argv[i], statbuf, sizeof statbuf) >= 0){
+ strncpy(partition, argv[i], sizeof(partition)-1);
+ partition[sizeof(partition)-1] = 0;
+ }
+ }
+ }
+
+ if(*partition == 0){
+ readfile("#e/bootdisk", bd, sizeof(bd));
+ if(*bd){
+ if(pp = strchr(bd, ':'))
+ *pp = 0;
+ /* damned artificial intelligence */
+ i = strlen(bd);
+ if(strcmp("disk", &bd[i-4]) == 0)
+ bd[i-4] = 0;
+ else if(strcmp("fs", &bd[i-2]) == 0)
+ bd[i-2] = 0;
+ else if(strcmp("fossil", &bd[i-6]) == 0)
+ bd[i-6] = 0;
+ sprint(partition, "%scache", bd);
+ if(stat(partition, statbuf, sizeof statbuf) < 0)
+ *bd = 0;
+ }
+ if(*bd == 0){
+ sprint(partition, "%scache", bootdisk);
+ if(stat(partition, statbuf, sizeof statbuf) < 0)
+ return fd;
+ }
+ }
+
+ print("cfs...");
+ if(pipe(p)<0)
+ fatal("pipe");
+ switch(fork()){
+ case -1:
+ fatal("fork");
+ case 0:
+ close(p[1]);
+ dup(fd, 0);
+ close(fd);
+ dup(p[0], 1);
+ close(p[0]);
+ if(fflag)
+ execl("/boot/cfs", "bootcfs", "-rs", "-f", partition, 0);
+ else
+ execl("/boot/cfs", "bootcfs", "-s", "-f", partition, 0);
+ break;
+ default:
+ close(p[0]);
+ close(fd);
+ fd = p[1];
+ break;
+ }
+ return fd;
+}
diff --git a/sys/src/9/boot/bootip.c b/sys/src/9/boot/bootip.c
new file mode 100755
index 000000000..94ff87026
--- /dev/null
+++ b/sys/src/9/boot/bootip.c
@@ -0,0 +1,203 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+
+#include "boot.h"
+
+static uchar fsip[IPaddrlen];
+ uchar auip[IPaddrlen];
+static char mpoint[32];
+
+static int isvalidip(uchar*);
+static void netndb(char*, uchar*);
+static void netenv(char*, uchar*);
+
+
+void
+configip(int bargc, char **bargv, int needfs)
+{
+ Waitmsg *w;
+ int argc, pid;
+ char **arg, **argv, buf[32], *p;
+
+ fmtinstall('I', eipfmt);
+ fmtinstall('M', eipfmt);
+ fmtinstall('E', eipfmt);
+
+ arg = malloc((bargc+1) * sizeof(char*));
+ if(arg == nil)
+ fatal("%r");
+ memmove(arg, bargv, bargc * sizeof(char*));
+ arg[bargc] = 0;
+
+ argc = bargc;
+ argv = arg;
+ strcpy(mpoint, "/net");
+ ARGBEGIN {
+ case 'x':
+ p = ARGF();
+ if(p != nil)
+ snprint(mpoint, sizeof(mpoint), "/net%s", p);
+ break;
+ case 'g':
+ case 'b':
+ case 'h':
+ case 'm':
+ p = ARGF();
+ USED(p);
+ break;
+ } ARGEND;
+
+ /* bind in an ip interface */
+ if(bind("#I", mpoint, MAFTER) < 0)
+ fatal("bind #I: %r\n");
+ if(access("#l0", 0) == 0 && bind("#l0", mpoint, MAFTER) < 0)
+ print("bind #l0: %r\n");
+ if(access("#l1", 0) == 0 && bind("#l1", mpoint, MAFTER) < 0)
+ print("bind #l1: %r\n");
+ if(access("#l2", 0) == 0 && bind("#l2", mpoint, MAFTER) < 0)
+ print("bind #l2: %r\n");
+ if(access("#l3", 0) == 0 && bind("#l3", mpoint, MAFTER) < 0)
+ print("bind #l3: %r\n");
+ werrstr("");
+
+ /* let ipconfig configure the ip interface */
+ switch(pid = fork()){
+ case -1:
+ fatal("configuring ip: %r");
+ case 0:
+ exec("/boot/ipconfig", arg);
+ fatal("execing /ipconfig");
+ default:
+ break;
+ }
+
+ /* wait for ipconfig to finish */
+ for(;;){
+ w = wait();
+ if(w != nil && w->pid == pid){
+ if(w->msg[0] != 0)
+ fatal(w->msg);
+ free(w);
+ break;
+ } else if(w == nil)
+ fatal("configuring ip");
+ free(w);
+ }
+
+ if(!needfs)
+ return;
+
+ /* if we didn't get a file and auth server, query user */
+ netndb("fs", fsip);
+ if(!isvalidip(fsip))
+ netenv("fs", fsip);
+ while(!isvalidip(fsip)){
+ buf[0] = 0;
+ outin("filesystem IP address", buf, sizeof(buf));
+ if (parseip(fsip, buf) == -1)
+ fprint(2, "configip: can't parse fs ip %s\n", buf);
+ }
+
+ netndb("auth", auip);
+ if(!isvalidip(auip))
+ netenv("auth", auip);
+ while(!isvalidip(auip)){
+ buf[0] = 0;
+ outin("authentication server IP address", buf, sizeof(buf));
+ if (parseip(auip, buf) == -1)
+ fprint(2, "configip: can't parse auth ip %s\n", buf);
+ }
+}
+
+static void
+setauthaddr(char *proto, int port)
+{
+ char buf[128];
+
+ snprint(buf, sizeof buf, "%s!%I!%d", proto, auip, port);
+ authaddr = strdup(buf);
+}
+
+void
+configtcp(Method*)
+{
+ configip(bargc, bargv, 1);
+ setauthaddr("tcp", 567);
+}
+
+int
+connecttcp(void)
+{
+ int fd;
+ char buf[64];
+
+ snprint(buf, sizeof buf, "tcp!%I!564", fsip);
+ fd = dial(buf, 0, 0, 0);
+ if (fd < 0)
+ werrstr("dial %s: %r", buf);
+ return fd;
+}
+
+static int
+isvalidip(uchar *ip)
+{
+ if(ipcmp(ip, IPnoaddr) == 0)
+ return 0;
+ if(ipcmp(ip, v4prefix) == 0)
+ return 0;
+ return 1;
+}
+
+static void
+netenv(char *attr, uchar *ip)
+{
+ int fd, n;
+ char buf[128];
+
+ ipmove(ip, IPnoaddr);
+ snprint(buf, sizeof(buf), "#e/%s", attr);
+ fd = open(buf, OREAD);
+ if(fd < 0)
+ return;
+
+ n = read(fd, buf, sizeof(buf)-1);
+ if(n <= 0)
+ return;
+ buf[n] = 0;
+ if (parseip(ip, buf) == -1)
+ fprint(2, "netenv: can't parse ip %s\n", buf);
+}
+
+static void
+netndb(char *attr, uchar *ip)
+{
+ int fd, n, c;
+ char buf[1024];
+ char *p;
+
+ ipmove(ip, IPnoaddr);
+ snprint(buf, sizeof(buf), "%s/ndb", mpoint);
+ fd = open(buf, OREAD);
+ if(fd < 0)
+ return;
+ n = read(fd, buf, sizeof(buf)-1);
+ close(fd);
+ if(n <= 0)
+ return;
+ buf[n] = 0;
+ n = strlen(attr);
+ for(p = buf; ; p++){
+ p = strstr(p, attr);
+ if(p == nil)
+ break;
+ c = *(p-1);
+ if(*(p + n) == '=' && (p == buf || c == '\n' || c == ' ' || c == '\t')){
+ p += n+1;
+ if (parseip(ip, p) == -1)
+ fprint(2, "netndb: can't parse ip %s\n", p);
+ return;
+ }
+ }
+ return;
+}
diff --git a/sys/src/9/boot/bootmkfile b/sys/src/9/boot/bootmkfile
new file mode 100755
index 000000000..c189b829d
--- /dev/null
+++ b/sys/src/9/boot/bootmkfile
@@ -0,0 +1,27 @@
+BOOTDIR=../boot
+BOOTLIB=$BOOTDIR/libboot.a$O
+
+BOOTFILES=\
+ bootauth.$O\
+ aux.$O\
+ boot.$O\
+ bootcache.$O\
+ bootip.$O\
+ local.$O\
+ embed.$O\
+ settime.$O\
+ sac.$O\
+ paq.$O\
+ printstub.$O\
+
+$BOOTLIB(%.$O):N: %.$O
+
+$BOOTLIB: ${BOOTFILES:%=$BOOTLIB(%)}
+ names=`{membername $newprereq}
+ ar vu $BOOTLIB $names
+ rm $names
+
+$BOOTFILES: $BOOTDIR/boot.h
+
+%.$O: $BOOTDIR/%.c
+ $CC -I$BOOTDIR $CFLAGS $BOOTDIR/$stem.c
diff --git a/sys/src/9/boot/doauthenticate.c b/sys/src/9/boot/doauthenticate.c
new file mode 100755
index 000000000..f632ab08e
--- /dev/null
+++ b/sys/src/9/boot/doauthenticate.c
@@ -0,0 +1,126 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include "../boot/boot.h"
+
+static char *pbmsg = "AS protocol botch";
+static char *ccmsg = "can't connect to AS";
+
+long
+readn(int fd, void *buf, long len)
+{
+ int m, n;
+ char *p;
+
+ p = buf;
+ for(n = 0; n < len; n += m){
+ m = read(fd, p+n, len-n);
+ if(m <= 0)
+ return -1;
+ }
+ return n;
+}
+
+static char*
+fromauth(Method *mp, char *trbuf, char *tbuf)
+{
+ int afd;
+ char t;
+ char *msg;
+ static char error[2*ERRMAX];
+
+ if(mp->auth == 0)
+ fatal("no method for accessing auth server");
+ afd = (*mp->auth)();
+ if(afd < 0) {
+ sprint(error, "%s: %r", ccmsg);
+ return error;
+ }
+
+ if(write(afd, trbuf, TICKREQLEN) < 0 || read(afd, &t, 1) != 1){
+ close(afd);
+ sprint(error, "%s: %r", pbmsg);
+ return error;
+ }
+ switch(t){
+ case AuthOK:
+ msg = 0;
+ if(readn(afd, tbuf, 2*TICKETLEN) < 0) {
+ sprint(error, "%s: %r", pbmsg);
+ msg = error;
+ }
+ break;
+ case AuthErr:
+ if(readn(afd, error, ERRMAX) < 0) {
+ sprint(error, "%s: %r", pbmsg);
+ msg = error;
+ }
+ else {
+ error[ERRMAX-1] = 0;
+ msg = error;
+ }
+ break;
+ default:
+ msg = pbmsg;
+ break;
+ }
+
+ close(afd);
+ return msg;
+}
+
+void
+doauthenticate(int fd, Method *mp)
+{
+ char *msg;
+ char trbuf[TICKREQLEN];
+ char tbuf[2*TICKETLEN];
+
+ print("session...");
+ if(fsession(fd, trbuf, sizeof trbuf) < 0)
+ fatal("session command failed");
+
+ /* no authentication required? */
+ memset(tbuf, 0, 2*TICKETLEN);
+ if(trbuf[0] == 0)
+ return;
+
+ /* try getting to an auth server */
+ print("getting ticket...");
+ msg = fromauth(mp, trbuf, tbuf);
+ print("authenticating...");
+ if(msg == 0)
+ if(fauth(fd, tbuf) >= 0)
+ return;
+
+ /* didn't work, go for the security hole */
+ fprint(2, "no authentication server (%s), using your key as server key\n", msg);
+}
+
+char*
+checkkey(Method *mp, char *name, char *key)
+{
+ char *msg;
+ Ticketreq tr;
+ Ticket t;
+ char trbuf[TICKREQLEN];
+ char tbuf[TICKETLEN];
+
+ memset(&tr, 0, sizeof tr);
+ tr.type = AuthTreq;
+ strcpy(tr.authid, name);
+ strcpy(tr.hostid, name);
+ strcpy(tr.uid, name);
+ convTR2M(&tr, trbuf);
+ msg = fromauth(mp, trbuf, tbuf);
+ if(msg == ccmsg){
+ fprint(2, "boot: can't contact auth server, passwd unchecked\n");
+ return 0;
+ }
+ if(msg)
+ return msg;
+ convM2T(tbuf, &t, key);
+ if(t.num == AuthTc && strcmp(name, t.cuid)==0)
+ return 0;
+ return "no match";
+}
diff --git a/sys/src/9/boot/embed.c b/sys/src/9/boot/embed.c
new file mode 100755
index 000000000..d14de65f5
--- /dev/null
+++ b/sys/src/9/boot/embed.c
@@ -0,0 +1,74 @@
+#include <u.h>
+#include <libc.h>
+#include <../boot/boot.h>
+
+static char *paqfile;
+
+void
+configembed(Method *m)
+{
+ if(*sys == '/' || *sys == '#'){
+ /*
+ * if the user specifies the disk in the boot cmd or
+ * 'root is from' prompt, use it
+ */
+ paqfile = sys;
+ } else if(m->arg){
+ /*
+ * a default is supplied when the kernel is made
+ */
+ paqfile = m->arg;
+ }
+}
+
+int
+connectembed(void)
+{
+ int i, p[2];
+ Dir *dir;
+ char **arg, **argp;
+
+ dir = dirstat("/boot/paqfs");
+ if(dir == nil)
+ return -1;
+ free(dir);
+
+ dir = dirstat(paqfile);
+ if(dir == nil || dir->mode & DMDIR)
+ return -1;
+ free(dir);
+
+ print("paqfs...");
+ if(bind("#c", "/dev", MREPL) < 0)
+ fatal("bind #c");
+ if(bind("#p", "/proc", MREPL) < 0)
+ fatal("bind #p");
+ if(pipe(p)<0)
+ fatal("pipe");
+ switch(fork()){
+ case -1:
+ fatal("fork");
+ case 0:
+ arg = malloc((bargc+5)*sizeof(char*));
+ argp = arg;
+ *argp++ = "/boot/paqfs";
+ *argp++ = "-iv";
+ *argp++ = paqfile;
+ for(i=1; i<bargc; i++)
+ *argp++ = bargv[i];
+ *argp = 0;
+
+ dup(p[0], 0);
+ dup(p[1], 1);
+ close(p[0]);
+ close(p[1]);
+ exec("/boot/paqfs", arg);
+ fatal("can't exec paqfs");
+ default:
+ break;
+ }
+ waitpid();
+
+ close(p[1]);
+ return p[0];
+}
diff --git a/sys/src/9/boot/getpasswd.c b/sys/src/9/boot/getpasswd.c
new file mode 100755
index 000000000..b766e2543
--- /dev/null
+++ b/sys/src/9/boot/getpasswd.c
@@ -0,0 +1,43 @@
+#include <u.h>
+#include <libc.h>
+#include <../boot/boot.h>
+
+void
+getpasswd(char *p, int len)
+{
+ char c;
+ int i, n, fd;
+
+ fd = open("#c/consctl", OWRITE);
+ if(fd < 0)
+ fatal("can't open consctl; please reboot");
+ write(fd, "rawon", 5);
+ Prompt:
+ print("password: ");
+ n = 0;
+ for(;;){
+ do{
+ i = read(0, &c, 1);
+ if(i < 0)
+ fatal("can't read cons; please reboot");
+ }while(i == 0);
+ switch(c){
+ case '\n':
+ p[n] = '\0';
+ close(fd);
+ print("\n");
+ return;
+ case '\b':
+ if(n > 0)
+ n--;
+ break;
+ case 'u' - 'a' + 1: /* cntrl-u */
+ print("\n");
+ goto Prompt;
+ default:
+ if(n < len - 1)
+ p[n++] = c;
+ break;
+ }
+ }
+}
diff --git a/sys/src/9/boot/libboot.a5 b/sys/src/9/boot/libboot.a5
new file mode 100755
index 000000000..c25b07103
--- /dev/null
+++ b/sys/src/9/boot/libboot.a5
Binary files differ
diff --git a/sys/src/9/boot/libboot.a8 b/sys/src/9/boot/libboot.a8
new file mode 100755
index 000000000..b59832380
--- /dev/null
+++ b/sys/src/9/boot/libboot.a8
Binary files differ
diff --git a/sys/src/9/boot/local.c b/sys/src/9/boot/local.c
new file mode 100755
index 000000000..f885b0d83
--- /dev/null
+++ b/sys/src/9/boot/local.c
@@ -0,0 +1,275 @@
+#include <u.h>
+#include <libc.h>
+#include <../boot/boot.h>
+
+static char diskname[64];
+static char *disk;
+static char **args;
+
+void
+configlocal(Method *mp)
+{
+ char *p;
+ int n;
+
+ if(*sys == '/' || *sys == '#'){
+ /*
+ * if the user specifies the disk in the boot cmd or
+ * 'root is from' prompt, use it
+ */
+ disk = sys;
+ } else if(strncmp(argv0, "dksc(0,", 7) == 0){
+ /*
+ * on many mips arg0 of the boot command specifies the
+ * scsi logical unit number
+ */
+ p = strchr(argv0, ',');
+ n = strtoul(p+1, 0, 10);
+ sprint(diskname, "#w%d/sd%dfs", n, n);
+ disk = diskname;
+ } else if(mp->arg){
+ /*
+ * a default is supplied when the kernel is made
+ */
+ disk = mp->arg;
+ } else if(*bootdisk){
+ /*
+ * an environment variable from a pc's plan9.ini or
+ * from the mips nvram or generated by the kernel
+ * is the last resort.
+ */
+ disk = bootdisk;
+ }
+
+ /* if we've decided on one, pass it on to all programs */
+ if(disk)
+ setenv("bootdisk", disk);
+
+ USED(mp);
+}
+
+int
+connectlocalkfs(void)
+{
+ int i, pid, fd, p[2];
+ char partition[64];
+ char *dev;
+ char **arg, **argp;
+ Dir *d;
+
+ if(stat("/boot/kfs", statbuf, sizeof statbuf) < 0)
+ return -1;
+
+ dev = disk ? disk : bootdisk;
+ snprint(partition, sizeof partition, "%sfs", dev);
+ fd = open(partition, OREAD);
+ if(fd < 0){
+ strcpy(partition, dev);
+ fd = open(partition, OREAD);
+ if(fd < 0)
+ return -1;
+ }
+ /*
+ * can't do this check -- might be some other server posing as kfs.
+ *
+ memset(buf, 0, sizeof buf);
+ pread(fd, buf, 512, 0);
+ close(fd);
+ if(memcmp(buf+256, "kfs wren device\n", 16) != 0){
+ if(strstr(partition, "/fs"))
+ print("no kfs file system found on %s\n", partition);
+ return -1;
+ }
+ *
+ */
+ d = dirfstat(fd);
+ close(fd);
+ if(d == nil)
+ return -1;
+ if(d->mode&DMDIR){
+ free(d);
+ return -1;
+ }
+ free(d);
+
+ print("kfs...");
+ if(pipe(p)<0)
+ fatal("pipe");
+ switch(pid = fork()){
+ case -1:
+ fatal("fork");
+ case 0:
+ arg = malloc((bargc+5)*sizeof(char*));
+ argp = arg;
+ *argp++ = "kfs";
+ *argp++ = "-f";
+ *argp++ = partition;
+ *argp++ = "-s";
+ for(i=1; i<bargc; i++)
+ *argp++ = bargv[i];
+ *argp = 0;
+
+ dup(p[0], 0);
+ dup(p[1], 1);
+ close(p[0]);
+ close(p[1]);
+ exec("/boot/kfs", arg);
+ fatal("can't exec kfs");
+ default:
+ break;
+ }
+ for(;;){
+ if((i = waitpid()) == -1)
+ fatal("waitpid for kfs failed");
+ if(i == pid)
+ break;
+ }
+
+ close(p[1]);
+ return p[0];
+}
+
+void
+run(char *file, ...)
+{
+ int i, pid;
+
+ switch(pid = fork()){
+ case -1:
+ fatal("fork");
+ case 0:
+ exec(file, &file);
+ fatal(smprint("can't exec %s: %r", file));
+ default:
+ while ((i = waitpid()) != pid && i != -1)
+ ;
+ if(i == -1)
+ fatal(smprint("wait failed running %s", file));
+ }
+}
+
+static int
+print1(int fd, char *s)
+{
+ return write(fd, s, strlen(s));
+}
+
+void
+configloopback(void)
+{
+ int fd;
+
+ if((fd = open("/net/ipifc/clone", ORDWR)) < 0){
+ bind("#I", "/net", MAFTER);
+ if((fd = open("/net/ipifc/clone", ORDWR)) < 0)
+ fatal("open /net/ipifc/clone for loopback");
+ }
+ if(print1(fd, "bind loopback /dev/null") < 0
+ || print1(fd, "add 127.0.0.1 255.255.255.255") < 0)
+ fatal("write /net/ipifc/clone for loopback");
+}
+
+int
+connectlocalfossil(void)
+{
+ int fd;
+ char *venti, *f[32], *p;
+ int nf;
+ char partition[128], buf[512];
+ char *dev;
+
+ if(stat("/boot/fossil", statbuf, sizeof statbuf) < 0)
+ return -1;
+
+ /* look for fossil partition */
+ dev = disk ? disk : bootdisk;
+ snprint(partition, sizeof partition, "%sfossil", dev);
+ fd = open(partition, OREAD);
+ if(fd < 0){
+ strcpy(partition, dev);
+ fd = open(partition, OREAD);
+ if(fd < 0)
+ return -1;
+ }
+ memset(buf, 0, sizeof buf);
+ pread(fd, buf, 512, 127*1024);
+ close(fd);
+ if(memcmp(buf, "fossil config\n", 14) != 0){
+ if(strstr(partition, "/fossil"))
+ print("no fossil config found on %s\n", partition);
+ return -1;
+ }
+
+ settime(1, -1, nil);
+
+ /* make venti available */
+ if((venti = getenv("venti")) && (nf = tokenize(venti, f, nelem(f)))){
+ if((fd = open(f[0], OREAD)) >= 0){
+ print("venti...");
+ memset(buf, 0, sizeof buf);
+ pread(fd, buf, 512, 248*1024);
+ close(fd);
+ if(memcmp(buf, "venti config\n", 13) != 0){
+ print("no venti config found on %s\n", f[0]);
+ return -1;
+ }
+ if(stat("/boot/venti", statbuf, sizeof statbuf) < 0){
+ print("/boot/venti does not exist\n");
+ return -1;
+ }
+ switch(nf){
+ case 1:
+ f[1] = "tcp!127.1!17034";
+ case 2:
+ f[2] = "tcp!127.1!8000";
+ }
+ configloopback();
+ run("/boot/venti", "-c", f[0], "-a", f[1], "-h", f[2], 0);
+ /*
+ * If the announce address is tcp!*!foo, then set
+ * $venti to tcp!127.1!foo instead, which is actually dialable.
+ */
+ if((p = strstr(f[1], "!*!")) != 0){
+ *p = 0;
+ snprint(buf, sizeof buf, "%s!127.1!%s", f[1], p+3);
+ f[1] = buf;
+ }
+ setenv("venti", f[1]);
+ }else{
+ /* set up the network so we can talk to the venti server */
+ /* this is such a crock. */
+ configip(nf, f, 0);
+ setenv("venti", f[0]);
+ }
+ }
+
+ /* start fossil */
+ print("fossil(%s)...", partition);
+ run("/boot/fossil", "-f", partition, "-c", "srv -A fboot", "-c", "srv -p fscons", 0);
+ fd = open("#s/fboot", ORDWR);
+ if(fd < 0){
+ print("open #s/fboot: %r\n");
+ return -1;
+ }
+ remove("#s/fboot"); /* we'll repost as #s/boot */
+ return fd;
+}
+
+int
+connectlocal(void)
+{
+ int fd;
+
+ if(bind("#c", "/dev", MREPL) < 0)
+ fatal("bind #c");
+ if(bind("#p", "/proc", MREPL) < 0)
+ fatal("bind #p");
+ bind("#S", "/dev", MAFTER);
+ bind("#k", "/dev", MAFTER);
+ bind("#æ", "/dev", MAFTER);
+
+ if((fd = connectlocalfossil()) < 0)
+ if((fd = connectlocalkfs()) < 0)
+ return -1;
+ return fd;
+}
diff --git a/sys/src/9/boot/mkboot b/sys/src/9/boot/mkboot
new file mode 100755
index 000000000..4502830dc
--- /dev/null
+++ b/sys/src/9/boot/mkboot
@@ -0,0 +1,101 @@
+#!/bin/rc
+#
+# this file configures a boot program (/boot) for a kernel.
+#
+if(! ~ $#* 1){
+ echo usage: mkboot file >[1=2]
+ exit 1
+}
+
+cat <<'---'
+#include <u.h>
+#include <libc.h>
+#include "../boot/boot.h"
+
+Method method[]={
+---
+
+#
+# configure all remote methods, i.e. all methods in the 'boot' section
+#
+# EXAMPLE
+# boot
+# incon
+# 9600
+# 19200
+#
+../port/mkextract boot 0 $* | awk '{
+ printf " { \"" "" $1 "\", "\
+ "config" $1 ", "\
+ "connect" $1 ", "
+ print fieldn(2) " },"
+ }
+
+ func fieldn(n, s,i)
+ {
+ s = $0
+ while (n > 1) {
+ sub(/^[ \t]*/, "", s)
+ if (substr(s, 1, 1) == "\"") {
+ sub(/^"[^\"]*"/, "", s)
+ } else {
+ sub(/^[^ \t]*/, "", s)
+ }
+ n--
+ }
+ sub(/^[ \t]*/, "", s)
+ if (substr(s, 1, 1) == "\"") {
+ i = index(substr(s, 2), "\"")
+ if (i > 0)
+ return substr(s, 1, i+1)
+ else
+ return s
+ } else {
+ sub(/[ \t].*/, "", s)
+ return s
+ }
+ }'
+
+cat <<'---'
+ { 0 },
+};
+---
+
+awk '
+ BEGIN { cpuflag = 0; bootprog = "boot"; bootdisk = "#S/sdC0/"; rootdir = "/root"; }
+ $0 ~ "^boot" && $2=="cpu"\
+ { cpuflag = 1
+ if(NF == 4 && $3 == "boot")
+ bootdisk = $4
+ }
+ $0 ~ "^boot" && $2=="rootdir" && NF==3\
+ { rootdir = $3 }
+ $0 ~ "^boot" && ($2=="bboot" || $2=="romboot" || $2=="dosboot")\
+ { cpuflag = 1; bootprog = $2; }
+ $0 ~ "^boot" && $2=="boot" && NF==3\
+ { bootdisk = $3 }
+ END { print "int cpuflag = " cpuflag ";"
+ print "char* rootdir = \"" rootdir "\";"
+ print "char* bootdisk = \"" bootdisk "\";"
+ print "extern void " bootprog "(int, char**);"
+ print "void"
+ print "main(int argc, char **argv)"
+ print "{"
+ print "\t" bootprog "(argc, argv);"
+ print "}"
+ }
+' $1
+
+#
+# configure in a cache file system if a
+# /386/bin/root appears in the bootdir section.
+#
+../port/mkextract bootdir 0 $* | awk '
+ BEGIN { cfs = 0 }
+ $1 ~ "bin/cfs$" { cfs = 1 }
+ END { if(cfs)
+ print "int (*cfs)(int) = cache;"
+ else
+ print "int (*cfs)(int) = 0;"
+ }
+ '
diff --git a/sys/src/9/boot/nopsession.c b/sys/src/9/boot/nopsession.c
new file mode 100755
index 000000000..8893ac35d
--- /dev/null
+++ b/sys/src/9/boot/nopsession.c
@@ -0,0 +1,52 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include "../boot/boot.h"
+
+static Fcall hdr;
+
+static void
+rpc(int fd, int type)
+{
+ int n, l;
+ char buf[128], *p;
+
+ hdr.type = type;
+ hdr.tag = NOTAG;
+ n = convS2M(&hdr, buf);
+ if(write(fd, buf, n) != n)
+ fatal("write rpc");
+
+ print("...");
+ p = buf;
+ l = 0;
+ while(l < 3) {
+ n = read(fd, p, 3);
+ if(n <= 0)
+ fatal("read rpc");
+ if(n == 2 && l == 0 && buf[0] == 'O' && buf[1] == 'K')
+ continue;
+ p += n;
+ l += n;
+ }
+ if(convM2S(buf, &hdr, n) == 0){
+ print("%ux %ux %ux\n", buf[0], buf[1], buf[2]);
+ fatal("rpc format");
+ }
+ if(hdr.tag != NOTAG)
+ fatal("rpc tag not NOTAG");
+ if(hdr.type == Rerror){
+ print("error %s;", hdr.ename);
+ fatal("remote error");
+ }
+ if(hdr.type != type+1)
+ fatal("not reply");
+}
+
+void
+nop(int fd)
+{
+ print("nop");
+ rpc(fd, Tnop);
+}
diff --git a/sys/src/9/boot/paq.c b/sys/src/9/boot/paq.c
new file mode 100755
index 000000000..9536d78aa
--- /dev/null
+++ b/sys/src/9/boot/paq.c
@@ -0,0 +1,67 @@
+#include <u.h>
+#include <libc.h>
+#include <../boot/boot.h>
+
+char *fparts[] =
+{
+ "add bootldr 0x0000000 0x0040000",
+ "add params 0x0040000 0x0080000",
+ "add kernel 0x0080000 0x0140000",
+ "add user 0x0140000 0x0200000",
+ "add ramdisk 0x0200000 0x0600000",
+};
+
+void
+configpaq(Method*)
+{
+ int fd;
+ int i;
+
+ if(bind("#F", "/dev", MAFTER) < 0)
+ fatal("bind #c");
+ if(bind("#p", "/proc", MREPL) < 0)
+ fatal("bind #p");
+ fd = open("/dev/flash/flashctl", OWRITE);
+ if(fd < 0)
+ fatal("opening flashctl");
+ for(i = 0; i < nelem(fparts); i++)
+ if(fprint(fd, fparts[i]) < 0)
+ fatal(fparts[i]);
+ close(fd);
+}
+
+int
+connectpaq(void)
+{
+ int p[2];
+ char **arg, **argp;
+
+ print("paq...");
+ if(pipe(p)<0)
+ fatal("pipe");
+ switch(fork()){
+ case -1:
+ fatal("fork");
+ case 0:
+ arg = malloc(10*sizeof(char*));
+ argp = arg;
+ *argp++ = "paqfs";
+ *argp++ = "-v";
+ *argp++ = "-i";
+ *argp++ = "/dev/flash/ramdisk";
+ *argp = 0;
+
+ dup(p[0], 0);
+ dup(p[1], 1);
+ close(p[0]);
+ close(p[1]);
+ exec("/boot/paqfs", arg);
+ fatal("can't exec paqfs");
+ default:
+ break;
+ }
+ waitpid();
+
+ close(p[1]);
+ return p[0];
+}
diff --git a/sys/src/9/boot/printstub.c b/sys/src/9/boot/printstub.c
new file mode 100755
index 000000000..49dc0f868
--- /dev/null
+++ b/sys/src/9/boot/printstub.c
@@ -0,0 +1,22 @@
+#include <u.h>
+#include <libc.h>
+
+static Lock fmtl;
+
+void
+_fmtlock(void)
+{
+ lock(&fmtl);
+}
+
+void
+_fmtunlock(void)
+{
+ unlock(&fmtl);
+}
+
+int
+_efgfmt(Fmt*)
+{
+ return -1;
+}
diff --git a/sys/src/9/boot/sac.c b/sys/src/9/boot/sac.c
new file mode 100755
index 000000000..d7d6b6166
--- /dev/null
+++ b/sys/src/9/boot/sac.c
@@ -0,0 +1,50 @@
+#include <u.h>
+#include <libc.h>
+#include <../boot/boot.h>
+
+/*
+ * HACK - take over from boot since file system is not
+ * available on a pipe
+ */
+
+void
+configsac(Method *mp)
+{
+ int fd;
+ char cmd[64];
+
+ USED(mp);
+
+ /*
+ * create the name space, mount the root fs
+ */
+ if(bind("/", "/", MREPL) < 0)
+ fatal("bind /");
+ if(bind("#C", "/", MAFTER) < 0)
+ fatal("bind /");
+
+ /* fixed sysname - enables correct namespace file */
+ fd = open("#c/sysname", OWRITE);
+ if(fd < 0)
+ fatal("open sysname");
+ write(fd, "brick", 5);
+ close(fd);
+
+ fd = open("#c/hostowner", OWRITE);
+ if(fd < 0)
+ fatal("open sysname");
+ write(fd, "brick", 5);
+ close(fd);
+
+ sprint(cmd, "/%s/init", cputype);
+ print("starting %s\n", cmd);
+ execl(cmd, "init", "-c", 0);
+ fatal(cmd);
+}
+
+int
+connectsac(void)
+{
+ /* does not get here */
+ return -1;
+}
diff --git a/sys/src/9/boot/settime.c b/sys/src/9/boot/settime.c
new file mode 100755
index 000000000..d9be7585c
--- /dev/null
+++ b/sys/src/9/boot/settime.c
@@ -0,0 +1,149 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include "../boot/boot.h"
+
+static long lusertime(char*);
+
+char *timeserver = "#s/boot";
+
+void
+settime(int islocal, int afd, char *rp)
+{
+ int n, f;
+ int timeset;
+ Dir dir[2];
+ char timebuf[64];
+
+ print("time...");
+ timeset = 0;
+ if(islocal){
+ /*
+ * set the time from the real time clock
+ */
+ f = open("#r/rtc", ORDWR);
+ if(f >= 0){
+ if((n = read(f, timebuf, sizeof(timebuf)-1)) > 0){
+ timebuf[n] = '\0';
+ timeset = 1;
+ }
+ close(f);
+ }else do{
+ strcpy(timebuf, "yymmddhhmm[ss]");
+ outin("\ndate/time ", timebuf, sizeof(timebuf));
+ }while((timeset=lusertime(timebuf)) <= 0);
+ }
+ if(timeset == 0){
+ /*
+ * set the time from the access time of the root
+ */
+ f = open(timeserver, ORDWR);
+ if(f < 0)
+ return;
+ if(mount(f, afd, "/tmp", MREPL, rp) < 0){
+ warning("settime mount");
+ close(f);
+ return;
+ }
+ close(f);
+ if(stat("/tmp", statbuf, sizeof statbuf) < 0)
+ fatal("stat");
+ convM2D(statbuf, sizeof statbuf, &dir[0], (char*)&dir[1]);
+ sprint(timebuf, "%ld", dir[0].atime);
+ unmount(0, "/tmp");
+ }
+
+ f = open("#c/time", OWRITE);
+ if(write(f, timebuf, strlen(timebuf)) < 0)
+ warning("can't set #c/time");
+ close(f);
+ print("\n");
+}
+
+#define SEC2MIN 60L
+#define SEC2HOUR (60L*SEC2MIN)
+#define SEC2DAY (24L*SEC2HOUR)
+
+int
+g2(char **pp)
+{
+ int v;
+
+ v = 10*((*pp)[0]-'0') + (*pp)[1]-'0';
+ *pp += 2;
+ return v;
+}
+
+/*
+ * days per month plus days/year
+ */
+static int dmsize[] =
+{
+ 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+static int ldmsize[] =
+{
+ 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/*
+ * return the days/month for the given year
+ */
+static int *
+yrsize(int y)
+{
+
+ if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
+ return ldmsize;
+ else
+ return dmsize;
+}
+
+/*
+ * compute seconds since Jan 1 1970
+ */
+static long
+lusertime(char *argbuf)
+{
+ char *buf;
+ ulong secs;
+ int i, y, m;
+ int *d2m;
+
+ buf = argbuf;
+ i = strlen(buf);
+ if(i != 10 && i != 12)
+ return -1;
+ secs = 0;
+ y = g2(&buf);
+ m = g2(&buf);
+ if(y < 70)
+ y += 2000;
+ else
+ y += 1900;
+
+ /*
+ * seconds per year
+ */
+ for(i = 1970; i < y; i++){
+ d2m = yrsize(i);
+ secs += d2m[0] * SEC2DAY;
+ }
+
+ /*
+ * seconds per month
+ */
+ d2m = yrsize(y);
+ for(i = 1; i < m; i++)
+ secs += d2m[i] * SEC2DAY;
+
+ secs += (g2(&buf)-1) * SEC2DAY;
+ secs += g2(&buf) * SEC2HOUR;
+ secs += g2(&buf) * SEC2MIN;
+ if(*buf)
+ secs += g2(&buf);
+
+ sprint(argbuf, "%ld", secs);
+ return secs;
+}
diff --git a/sys/src/9/boot/testboot.c b/sys/src/9/boot/testboot.c
new file mode 100755
index 000000000..07333163b
--- /dev/null
+++ b/sys/src/9/boot/testboot.c
@@ -0,0 +1,37 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+
+void
+usage(void)
+{
+ fprint(2, "usage: testboot cmd args...\n");
+ exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ int p[2];
+
+ if(argc == 1)
+ usage();
+
+ pipe(p);
+ switch(rfork(RFPROC|RFFDG|RFNAMEG)){
+ case -1:
+ sysfatal("fork: %r");
+
+ case 0:
+ dup(p[0], 0);
+ dup(p[1], 1);
+ exec(argv[1], argv+1);
+ sysfatal("exec: %r");
+
+ default:
+ if(amount(p[0], "/n/kremvax", MREPL, "") < 0)
+ sysfatal("amount: %r");
+ break;
+ }
+ exits(nil);
+}
diff --git a/sys/src/9/ip/arp.c b/sys/src/9/ip/arp.c
new file mode 100755
index 000000000..7ea27bf23
--- /dev/null
+++ b/sys/src/9/ip/arp.c
@@ -0,0 +1,685 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+#include "ipv6.h"
+
+/*
+ * address resolution tables
+ */
+
+enum
+{
+ NHASH = (1<<6),
+ NCACHE = 256,
+
+ AOK = 1,
+ AWAIT = 2,
+};
+
+char *arpstate[] =
+{
+ "UNUSED",
+ "OK",
+ "WAIT",
+};
+
+/*
+ * one per Fs
+ */
+struct Arp
+{
+ QLock;
+ Fs *f;
+ Arpent *hash[NHASH];
+ Arpent cache[NCACHE];
+ Arpent *rxmt;
+ Proc *rxmitp; /* neib sol re-transmit proc */
+ Rendez rxmtq;
+ Block *dropf, *dropl;
+};
+
+char *Ebadarp = "bad arp";
+
+#define haship(s) ((s)[IPaddrlen-1]%NHASH)
+
+extern int ReTransTimer = RETRANS_TIMER;
+
+static void rxmitproc(void *v);
+
+void
+arpinit(Fs *f)
+{
+ f->arp = smalloc(sizeof(Arp));
+ f->arp->f = f;
+ f->arp->rxmt = nil;
+ f->arp->dropf = f->arp->dropl = nil;
+ kproc("rxmitproc", rxmitproc, f->arp);
+}
+
+/*
+ * create a new arp entry for an ip address.
+ */
+static Arpent*
+newarp6(Arp *arp, uchar *ip, Ipifc *ifc, int addrxt)
+{
+ uint t;
+ Block *next, *xp;
+ Arpent *a, *e, *f, **l;
+ Medium *m = ifc->m;
+ int empty;
+
+ /* find oldest entry */
+ e = &arp->cache[NCACHE];
+ a = arp->cache;
+ t = a->utime;
+ for(f = a; f < e; f++){
+ if(f->utime < t){
+ t = f->utime;
+ a = f;
+ }
+ }
+
+ /* dump waiting packets */
+ xp = a->hold;
+ a->hold = nil;
+
+ if(isv4(a->ip)){
+ while(xp){
+ next = xp->list;
+ freeblist(xp);
+ xp = next;
+ }
+ }
+ else { /* queue icmp unreachable for rxmitproc later on, w/o arp lock */
+ if(xp){
+ if(arp->dropl == nil)
+ arp->dropf = xp;
+ else
+ arp->dropl->list = xp;
+
+ for(next = xp->list; next; next = next->list)
+ xp = next;
+ arp->dropl = xp;
+ wakeup(&arp->rxmtq);
+ }
+ }
+
+ /* take out of current chain */
+ l = &arp->hash[haship(a->ip)];
+ for(f = *l; f; f = f->hash){
+ if(f == a){
+ *l = a->hash;
+ break;
+ }
+ l = &f->hash;
+ }
+
+ /* insert into new chain */
+ l = &arp->hash[haship(ip)];
+ a->hash = *l;
+ *l = a;
+
+ memmove(a->ip, ip, sizeof(a->ip));
+ a->utime = NOW;
+ a->ctime = 0;
+ a->type = m;
+
+ a->rtime = NOW + ReTransTimer;
+ a->rxtsrem = MAX_MULTICAST_SOLICIT;
+ a->ifc = ifc;
+ a->ifcid = ifc->ifcid;
+
+ /* put to the end of re-transmit chain; addrxt is 0 when isv4(a->ip) */
+ if(!ipismulticast(a->ip) && addrxt){
+ l = &arp->rxmt;
+ empty = (*l==nil);
+
+ for(f = *l; f; f = f->nextrxt){
+ if(f == a){
+ *l = a->nextrxt;
+ break;
+ }
+ l = &f->nextrxt;
+ }
+ for(f = *l; f; f = f->nextrxt){
+ l = &f->nextrxt;
+ }
+ *l = a;
+ if(empty)
+ wakeup(&arp->rxmtq);
+ }
+
+ a->nextrxt = nil;
+
+ return a;
+}
+
+/* called with arp qlocked */
+
+void
+cleanarpent(Arp *arp, Arpent *a)
+{
+ Arpent *f, **l;
+
+ a->utime = 0;
+ a->ctime = 0;
+ a->type = 0;
+ a->state = 0;
+
+ /* take out of current chain */
+ l = &arp->hash[haship(a->ip)];
+ for(f = *l; f; f = f->hash){
+ if(f == a){
+ *l = a->hash;
+ break;
+ }
+ l = &f->hash;
+ }
+
+ /* take out of re-transmit chain */
+ l = &arp->rxmt;
+ for(f = *l; f; f = f->nextrxt){
+ if(f == a){
+ *l = a->nextrxt;
+ break;
+ }
+ l = &f->nextrxt;
+ }
+ a->nextrxt = nil;
+ a->hash = nil;
+ a->hold = nil;
+ a->last = nil;
+ a->ifc = nil;
+}
+
+/*
+ * fill in the media address if we have it. Otherwise return an
+ * Arpent that represents the state of the address resolution FSM
+ * for ip. Add the packet to be sent onto the list of packets
+ * waiting for ip->mac to be resolved.
+ */
+Arpent*
+arpget(Arp *arp, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *mac)
+{
+ int hash;
+ Arpent *a;
+ Medium *type = ifc->m;
+ uchar v6ip[IPaddrlen];
+
+ if(version == V4){
+ v4tov6(v6ip, ip);
+ ip = v6ip;
+ }
+
+ qlock(arp);
+ hash = haship(ip);
+ for(a = arp->hash[hash]; a; a = a->hash){
+ if(memcmp(ip, a->ip, sizeof(a->ip)) == 0)
+ if(type == a->type)
+ break;
+ }
+
+ if(a == nil){
+ a = newarp6(arp, ip, ifc, (version != V4));
+ a->state = AWAIT;
+ }
+ a->utime = NOW;
+ if(a->state == AWAIT){
+ if(bp != nil){
+ if(a->hold)
+ a->last->list = bp;
+ else
+ a->hold = bp;
+ a->last = bp;
+ bp->list = nil;
+ }
+ return a; /* return with arp qlocked */
+ }
+
+ memmove(mac, a->mac, a->type->maclen);
+
+ /* remove old entries */
+ if(NOW - a->ctime > 15*60*1000)
+ cleanarpent(arp, a);
+
+ qunlock(arp);
+ return nil;
+}
+
+/*
+ * called with arp locked
+ */
+void
+arprelease(Arp *arp, Arpent*)
+{
+ qunlock(arp);
+}
+
+/*
+ * Copy out the mac address from the Arpent. Return the
+ * block waiting to get sent to this mac address.
+ *
+ * called with arp locked
+ */
+Block*
+arpresolve(Arp *arp, Arpent *a, Medium *type, uchar *mac)
+{
+ Block *bp;
+ Arpent *f, **l;
+
+ if(!isv4(a->ip)){
+ l = &arp->rxmt;
+ for(f = *l; f; f = f->nextrxt){
+ if(f == a){
+ *l = a->nextrxt;
+ break;
+ }
+ l = &f->nextrxt;
+ }
+ }
+
+ memmove(a->mac, mac, type->maclen);
+ a->type = type;
+ a->state = AOK;
+ a->utime = NOW;
+ bp = a->hold;
+ a->hold = nil;
+ qunlock(arp);
+
+ return bp;
+}
+
+void
+arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh)
+{
+ Arp *arp;
+ Route *r;
+ Arpent *a, *f, **l;
+ Ipifc *ifc;
+ Medium *type;
+ Block *bp, *next;
+ uchar v6ip[IPaddrlen];
+
+ arp = fs->arp;
+
+ if(n != 6){
+// print("arp: len = %d\n", n);
+ return;
+ }
+
+ switch(version){
+ case V4:
+ r = v4lookup(fs, ip, nil);
+ v4tov6(v6ip, ip);
+ ip = v6ip;
+ break;
+ case V6:
+ r = v6lookup(fs, ip, nil);
+ break;
+ default:
+ panic("arpenter: version %d", version);
+ return; /* to supress warnings */
+ }
+
+ if(r == nil){
+// print("arp: no route for entry\n");
+ return;
+ }
+
+ ifc = r->ifc;
+ type = ifc->m;
+
+ qlock(arp);
+ for(a = arp->hash[haship(ip)]; a; a = a->hash){
+ if(a->type != type || (a->state != AWAIT && a->state != AOK))
+ continue;
+
+ if(ipcmp(a->ip, ip) == 0){
+ a->state = AOK;
+ memmove(a->mac, mac, type->maclen);
+
+ if(version == V6){
+ /* take out of re-transmit chain */
+ l = &arp->rxmt;
+ for(f = *l; f; f = f->nextrxt){
+ if(f == a){
+ *l = a->nextrxt;
+ break;
+ }
+ l = &f->nextrxt;
+ }
+ }
+
+ a->ifc = ifc;
+ a->ifcid = ifc->ifcid;
+ bp = a->hold;
+ a->hold = nil;
+ if(version == V4)
+ ip += IPv4off;
+ a->utime = NOW;
+ a->ctime = a->utime;
+ qunlock(arp);
+
+ while(bp){
+ next = bp->list;
+ if(ifc != nil){
+ if(waserror()){
+ runlock(ifc);
+ nexterror();
+ }
+ rlock(ifc);
+ if(ifc->m != nil)
+ ifc->m->bwrite(ifc, bp, version, ip);
+ else
+ freeb(bp);
+ runlock(ifc);
+ poperror();
+ } else
+ freeb(bp);
+ bp = next;
+ }
+ return;
+ }
+ }
+
+ if(refresh == 0){
+ a = newarp6(arp, ip, ifc, 0);
+ a->state = AOK;
+ a->type = type;
+ a->ctime = NOW;
+ memmove(a->mac, mac, type->maclen);
+ }
+
+ qunlock(arp);
+}
+
+int
+arpwrite(Fs *fs, char *s, int len)
+{
+ int n;
+ Route *r;
+ Arp *arp;
+ Block *bp;
+ Arpent *a, *fl, **l;
+ Medium *m;
+ char *f[4], buf[256];
+ uchar ip[IPaddrlen], mac[MAClen];
+
+ arp = fs->arp;
+
+ if(len == 0)
+ error(Ebadarp);
+ if(len >= sizeof(buf))
+ len = sizeof(buf)-1;
+ strncpy(buf, s, len);
+ buf[len] = 0;
+ if(len > 0 && buf[len-1] == '\n')
+ buf[len-1] = 0;
+
+ n = getfields(buf, f, 4, 1, " ");
+ if(strcmp(f[0], "flush") == 0){
+ qlock(arp);
+ for(a = arp->cache; a < &arp->cache[NCACHE]; a++){
+ memset(a->ip, 0, sizeof(a->ip));
+ memset(a->mac, 0, sizeof(a->mac));
+ a->hash = nil;
+ a->state = 0;
+ a->utime = 0;
+ while(a->hold != nil){
+ bp = a->hold->list;
+ freeblist(a->hold);
+ a->hold = bp;
+ }
+ }
+ memset(arp->hash, 0, sizeof(arp->hash));
+ /* clear all pkts on these lists (rxmt, dropf/l) */
+ arp->rxmt = nil;
+ arp->dropf = nil;
+ arp->dropl = nil;
+ qunlock(arp);
+ } else if(strcmp(f[0], "add") == 0){
+ switch(n){
+ default:
+ error(Ebadarg);
+ case 3:
+ if (parseip(ip, f[1]) == -1)
+ error(Ebadip);
+ if(isv4(ip))
+ r = v4lookup(fs, ip+IPv4off, nil);
+ else
+ r = v6lookup(fs, ip, nil);
+ if(r == nil)
+ error("Destination unreachable");
+ m = r->ifc->m;
+ n = parsemac(mac, f[2], m->maclen);
+ break;
+ case 4:
+ m = ipfindmedium(f[1]);
+ if(m == nil)
+ error(Ebadarp);
+ if (parseip(ip, f[2]) == -1)
+ error(Ebadip);
+ n = parsemac(mac, f[3], m->maclen);
+ break;
+ }
+
+ if(m->ares == nil)
+ error(Ebadarp);
+
+ m->ares(fs, V6, ip, mac, n, 0);
+ } else if(strcmp(f[0], "del") == 0){
+ if(n != 2)
+ error(Ebadarg);
+
+ if (parseip(ip, f[1]) == -1)
+ error(Ebadip);
+ qlock(arp);
+
+ l = &arp->hash[haship(ip)];
+ for(a = *l; a; a = a->hash){
+ if(memcmp(ip, a->ip, sizeof(a->ip)) == 0){
+ *l = a->hash;
+ break;
+ }
+ l = &a->hash;
+ }
+
+ if(a){
+ /* take out of re-transmit chain */
+ l = &arp->rxmt;
+ for(fl = *l; fl; fl = fl->nextrxt){
+ if(fl == a){
+ *l = a->nextrxt;
+ break;
+ }
+ l = &fl->nextrxt;
+ }
+
+ a->nextrxt = nil;
+ a->hash = nil;
+ a->hold = nil;
+ a->last = nil;
+ a->ifc = nil;
+ memset(a->ip, 0, sizeof(a->ip));
+ memset(a->mac, 0, sizeof(a->mac));
+ }
+ qunlock(arp);
+ } else
+ error(Ebadarp);
+
+ return len;
+}
+
+enum
+{
+ Alinelen= 90,
+};
+
+char *aformat = "%-6.6s %-8.8s %-40.40I %-32.32s\n";
+
+static void
+convmac(char *p, uchar *mac, int n)
+{
+ while(n-- > 0)
+ p += sprint(p, "%2.2ux", *mac++);
+}
+
+int
+arpread(Arp *arp, char *p, ulong offset, int len)
+{
+ Arpent *a;
+ int n;
+ char mac[2*MAClen+1];
+
+ if(offset % Alinelen)
+ return 0;
+
+ offset = offset/Alinelen;
+ len = len/Alinelen;
+
+ n = 0;
+ for(a = arp->cache; len > 0 && a < &arp->cache[NCACHE]; a++){
+ if(a->state == 0)
+ continue;
+ if(offset > 0){
+ offset--;
+ continue;
+ }
+ len--;
+ qlock(arp);
+ convmac(mac, a->mac, a->type->maclen);
+ n += sprint(p+n, aformat, a->type->name, arpstate[a->state], a->ip, mac);
+ qunlock(arp);
+ }
+
+ return n;
+}
+
+extern int
+rxmitsols(Arp *arp)
+{
+ uint sflag;
+ Block *next, *xp;
+ Arpent *a, *b, **l;
+ Fs *f;
+ uchar ipsrc[IPaddrlen];
+ Ipifc *ifc = nil;
+ long nrxt;
+
+ qlock(arp);
+ f = arp->f;
+
+ a = arp->rxmt;
+ if(a==nil){
+ nrxt = 0;
+ goto dodrops; /* return nrxt; */
+ }
+ nrxt = a->rtime - NOW;
+ if(nrxt > 3*ReTransTimer/4)
+ goto dodrops; /* return nrxt; */
+
+ for(; a; a = a->nextrxt){
+ ifc = a->ifc;
+ assert(ifc != nil);
+ if((a->rxtsrem <= 0) || !(canrlock(ifc)) || (a->ifcid != ifc->ifcid)){
+ xp = a->hold;
+ a->hold = nil;
+
+ if(xp){
+ if(arp->dropl == nil)
+ arp->dropf = xp;
+ else
+ arp->dropl->list = xp;
+ }
+
+ cleanarpent(arp, a);
+ }
+ else
+ break;
+ }
+ if(a == nil)
+ goto dodrops;
+
+
+ qunlock(arp); /* for icmpns */
+ if((sflag = ipv6anylocal(ifc, ipsrc)) != SRC_UNSPEC)
+ icmpns(f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac);
+
+ runlock(ifc);
+ qlock(arp);
+
+ /* put to the end of re-transmit chain */
+ l = &arp->rxmt;
+ for(b = *l; b; b = b->nextrxt){
+ if(b == a){
+ *l = a->nextrxt;
+ break;
+ }
+ l = &b->nextrxt;
+ }
+ for(b = *l; b; b = b->nextrxt){
+ l = &b->nextrxt;
+ }
+ *l = a;
+ a->rxtsrem--;
+ a->nextrxt = nil;
+ a->rtime = NOW + ReTransTimer;
+
+ a = arp->rxmt;
+ if(a==nil)
+ nrxt = 0;
+ else
+ nrxt = a->rtime - NOW;
+
+dodrops:
+ xp = arp->dropf;
+ arp->dropf = nil;
+ arp->dropl = nil;
+ qunlock(arp);
+
+ for(; xp; xp = next){
+ next = xp->list;
+ icmphostunr(f, ifc, xp, Icmp6_adr_unreach, 1);
+ }
+
+ return nrxt;
+
+}
+
+static int
+rxready(void *v)
+{
+ Arp *arp = (Arp *) v;
+ int x;
+
+ x = ((arp->rxmt != nil) || (arp->dropf != nil));
+
+ return x;
+}
+
+static void
+rxmitproc(void *v)
+{
+ Arp *arp = v;
+ long wakeupat;
+
+ arp->rxmitp = up;
+ //print("arp rxmitproc started\n");
+ if(waserror()){
+ arp->rxmitp = 0;
+ pexit("hangup", 1);
+ }
+ for(;;){
+ wakeupat = rxmitsols(arp);
+ if(wakeupat == 0)
+ sleep(&arp->rxmtq, rxready, v);
+ else if(wakeupat > ReTransTimer/4)
+ tsleep(&arp->rxmtq, return0, 0, wakeupat);
+ }
+}
+
diff --git a/sys/src/9/ip/chandial.c b/sys/src/9/ip/chandial.c
new file mode 100755
index 000000000..38139ceec
--- /dev/null
+++ b/sys/src/9/ip/chandial.c
@@ -0,0 +1,124 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "../ip/ip.h"
+
+typedef struct DS DS;
+static Chan* call(char*, char*, DS*);
+static void _dial_string_parse(char*, DS*);
+
+enum
+{
+ Maxstring= 128,
+};
+
+struct DS
+{
+ char buf[Maxstring]; /* dist string */
+ char *netdir;
+ char *proto;
+ char *rem;
+ char *local; /* other args */
+ char *dir;
+ Chan **ctlp;
+};
+
+/*
+ * the dialstring is of the form '[/net/]proto!dest'
+ */
+Chan*
+chandial(char *dest, char *local, char *dir, Chan **ctlp)
+{
+ DS ds;
+ char clone[Maxpath];
+
+ ds.local = local;
+ ds.dir = dir;
+ ds.ctlp = ctlp;
+
+ _dial_string_parse(dest, &ds);
+ if(ds.netdir == 0)
+ ds.netdir = "/net";
+
+ /* no connection server, don't translate */
+ snprint(clone, sizeof(clone), "%s/%s/clone", ds.netdir, ds.proto);
+ return call(clone, ds.rem, &ds);
+}
+
+static Chan*
+call(char *clone, char *dest, DS *ds)
+{
+ int n;
+ Chan *dchan, *cchan;
+ char name[Maxpath], data[Maxpath], *p;
+
+ cchan = namec(clone, Aopen, ORDWR, 0);
+
+ /* get directory name */
+ if(waserror()){
+ cclose(cchan);
+ nexterror();
+ }
+ n = devtab[cchan->type]->read(cchan, name, sizeof(name)-1, 0);
+ name[n] = 0;
+ for(p = name; *p == ' '; p++)
+ ;
+ sprint(name, "%lud", strtoul(p, 0, 0));
+ p = strrchr(clone, '/');
+ *p = 0;
+ if(ds->dir)
+ snprint(ds->dir, Maxpath, "%s/%s", clone, name);
+ snprint(data, sizeof(data), "%s/%s/data", clone, name);
+
+ /* connect */
+ if(ds->local)
+ snprint(name, sizeof(name), "connect %s %s", dest, ds->local);
+ else
+ snprint(name, sizeof(name), "connect %s", dest);
+ devtab[cchan->type]->write(cchan, name, strlen(name), 0);
+
+ /* open data connection */
+ dchan = namec(data, Aopen, ORDWR, 0);
+ if(ds->ctlp)
+ *ds->ctlp = cchan;
+ else
+ cclose(cchan);
+ poperror();
+ return dchan;
+
+}
+
+/*
+ * parse a dial string
+ */
+static void
+_dial_string_parse(char *str, DS *ds)
+{
+ char *p, *p2;
+
+ strncpy(ds->buf, str, Maxstring);
+ ds->buf[Maxstring-1] = 0;
+
+ p = strchr(ds->buf, '!');
+ if(p == 0) {
+ ds->netdir = 0;
+ ds->proto = "net";
+ ds->rem = ds->buf;
+ } else {
+ if(*ds->buf != '/' && *ds->buf != '#'){
+ ds->netdir = 0;
+ ds->proto = ds->buf;
+ } else {
+ for(p2 = p; *p2 != '/'; p2--)
+ ;
+ *p2++ = 0;
+ ds->netdir = ds->buf;
+ ds->proto = p2;
+ }
+ *p = 0;
+ ds->rem = p + 1;
+ }
+}
diff --git a/sys/src/9/ip/devip.c b/sys/src/9/ip/devip.c
new file mode 100755
index 000000000..99502df36
--- /dev/null
+++ b/sys/src/9/ip/devip.c
@@ -0,0 +1,1457 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "../ip/ip.h"
+
+enum
+{
+ Qtopdir= 1, /* top level directory */
+ Qtopbase,
+ Qarp= Qtopbase,
+ Qbootp,
+ Qndb,
+ Qiproute,
+ Qipselftab,
+ Qlog,
+
+ Qprotodir, /* directory for a protocol */
+ Qprotobase,
+ Qclone= Qprotobase,
+ Qstats,
+
+ Qconvdir, /* directory for a conversation */
+ Qconvbase,
+ Qctl= Qconvbase,
+ Qdata,
+ Qerr,
+ Qlisten,
+ Qlocal,
+ Qremote,
+ Qstatus,
+ Qsnoop,
+
+ Logtype= 5,
+ Masktype= (1<<Logtype)-1,
+ Logconv= 12,
+ Maskconv= (1<<Logconv)-1,
+ Shiftconv= Logtype,
+ Logproto= 8,
+ Maskproto= (1<<Logproto)-1,
+ Shiftproto= Logtype + Logconv,
+
+ Nfs= 128,
+};
+#define TYPE(x) ( ((ulong)(x).path) & Masktype )
+#define CONV(x) ( (((ulong)(x).path) >> Shiftconv) & Maskconv )
+#define PROTO(x) ( (((ulong)(x).path) >> Shiftproto) & Maskproto )
+#define QID(p, c, y) ( ((p)<<(Shiftproto)) | ((c)<<Shiftconv) | (y) )
+
+static char network[] = "network";
+
+QLock fslock;
+Fs *ipfs[Nfs]; /* attached fs's */
+Queue *qlog;
+
+extern void nullmediumlink(void);
+extern void pktmediumlink(void);
+ long ndbwrite(Fs *f, char *a, ulong off, int n);
+
+static int
+ip3gen(Chan *c, int i, Dir *dp)
+{
+ Qid q;
+ Conv *cv;
+ char *p;
+
+ cv = ipfs[c->dev]->p[PROTO(c->qid)]->conv[CONV(c->qid)];
+ if(cv->owner == nil)
+ kstrdup(&cv->owner, eve);
+ mkqid(&q, QID(PROTO(c->qid), CONV(c->qid), i), 0, QTFILE);
+
+ switch(i) {
+ default:
+ return -1;
+ case Qctl:
+ devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp);
+ return 1;
+ case Qdata:
+ devdir(c, q, "data", qlen(cv->rq), cv->owner, cv->perm, dp);
+ return 1;
+ case Qerr:
+ devdir(c, q, "err", qlen(cv->eq), cv->owner, cv->perm, dp);
+ return 1;
+ case Qlisten:
+ devdir(c, q, "listen", 0, cv->owner, cv->perm, dp);
+ return 1;
+ case Qlocal:
+ p = "local";
+ break;
+ case Qremote:
+ p = "remote";
+ break;
+ case Qsnoop:
+ if(strcmp(cv->p->name, "ipifc") != 0)
+ return -1;
+ devdir(c, q, "snoop", qlen(cv->sq), cv->owner, 0400, dp);
+ return 1;
+ case Qstatus:
+ p = "status";
+ break;
+ }
+ devdir(c, q, p, 0, cv->owner, 0444, dp);
+ return 1;
+}
+
+static int
+ip2gen(Chan *c, int i, Dir *dp)
+{
+ Qid q;
+
+ switch(i) {
+ case Qclone:
+ mkqid(&q, QID(PROTO(c->qid), 0, Qclone), 0, QTFILE);
+ devdir(c, q, "clone", 0, network, 0666, dp);
+ return 1;
+ case Qstats:
+ mkqid(&q, QID(PROTO(c->qid), 0, Qstats), 0, QTFILE);
+ devdir(c, q, "stats", 0, network, 0444, dp);
+ return 1;
+ }
+ return -1;
+}
+
+static int
+ip1gen(Chan *c, int i, Dir *dp)
+{
+ Qid q;
+ char *p;
+ int prot;
+ int len = 0;
+ Fs *f;
+ extern ulong kerndate;
+
+ f = ipfs[c->dev];
+
+ prot = 0666;
+ mkqid(&q, QID(0, 0, i), 0, QTFILE);
+ switch(i) {
+ default:
+ return -1;
+ case Qarp:
+ p = "arp";
+ prot = 0664;
+ break;
+ case Qbootp:
+ p = "bootp";
+ break;
+ case Qndb:
+ p = "ndb";
+ len = strlen(f->ndb);
+ q.vers = f->ndbvers;
+ break;
+ case Qiproute:
+ p = "iproute";
+ prot = 0664;
+ break;
+ case Qipselftab:
+ p = "ipselftab";
+ prot = 0444;
+ break;
+ case Qlog:
+ p = "log";
+ break;
+ }
+ devdir(c, q, p, len, network, prot, dp);
+ if(i == Qndb && f->ndbmtime > kerndate)
+ dp->mtime = f->ndbmtime;
+ return 1;
+}
+
+static int
+ipgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
+{
+ Qid q;
+ Conv *cv;
+ Fs *f;
+
+ f = ipfs[c->dev];
+
+ switch(TYPE(c->qid)) {
+ case Qtopdir:
+ if(s == DEVDOTDOT){
+ mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
+ snprint(up->genbuf, sizeof up->genbuf, "#I%lud", c->dev);
+ devdir(c, q, up->genbuf, 0, network, 0555, dp);
+ return 1;
+ }
+ if(s < f->np) {
+ if(f->p[s]->connect == nil)
+ return 0; /* protocol with no user interface */
+ mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
+ devdir(c, q, f->p[s]->name, 0, network, 0555, dp);
+ return 1;
+ }
+ s -= f->np;
+ return ip1gen(c, s+Qtopbase, dp);
+ case Qarp:
+ case Qbootp:
+ case Qndb:
+ case Qlog:
+ case Qiproute:
+ case Qipselftab:
+ return ip1gen(c, TYPE(c->qid), dp);
+ case Qprotodir:
+ if(s == DEVDOTDOT){
+ mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
+ snprint(up->genbuf, sizeof up->genbuf, "#I%lud", c->dev);
+ devdir(c, q, up->genbuf, 0, network, 0555, dp);
+ return 1;
+ }
+ if(s < f->p[PROTO(c->qid)]->ac) {
+ cv = f->p[PROTO(c->qid)]->conv[s];
+ snprint(up->genbuf, sizeof up->genbuf, "%d", s);
+ mkqid(&q, QID(PROTO(c->qid), s, Qconvdir), 0, QTDIR);
+ devdir(c, q, up->genbuf, 0, cv->owner, 0555, dp);
+ return 1;
+ }
+ s -= f->p[PROTO(c->qid)]->ac;
+ return ip2gen(c, s+Qprotobase, dp);
+ case Qclone:
+ case Qstats:
+ return ip2gen(c, TYPE(c->qid), dp);
+ case Qconvdir:
+ if(s == DEVDOTDOT){
+ s = PROTO(c->qid);
+ mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
+ devdir(c, q, f->p[s]->name, 0, network, 0555, dp);
+ return 1;
+ }
+ return ip3gen(c, s+Qconvbase, dp);
+ case Qctl:
+ case Qdata:
+ case Qerr:
+ case Qlisten:
+ case Qlocal:
+ case Qremote:
+ case Qstatus:
+ case Qsnoop:
+ return ip3gen(c, TYPE(c->qid), dp);
+ }
+ return -1;
+}
+
+static void
+ipreset(void)
+{
+ nullmediumlink();
+ pktmediumlink();
+
+ fmtinstall('i', eipfmt);
+ fmtinstall('I', eipfmt);
+ fmtinstall('E', eipfmt);
+ fmtinstall('V', eipfmt);
+ fmtinstall('M', eipfmt);
+}
+
+static Fs*
+ipgetfs(int dev)
+{
+ extern void (*ipprotoinit[])(Fs*);
+ Fs *f;
+ int i;
+
+ if(dev >= Nfs)
+ return nil;
+
+ qlock(&fslock);
+ if(ipfs[dev] == nil){
+ f = smalloc(sizeof(Fs));
+ ip_init(f);
+ arpinit(f);
+ netloginit(f);
+ for(i = 0; ipprotoinit[i]; i++)
+ ipprotoinit[i](f);
+ f->dev = dev;
+ ipfs[dev] = f;
+ }
+ qunlock(&fslock);
+
+ return ipfs[dev];
+}
+
+IPaux*
+newipaux(char *owner, char *tag)
+{
+ IPaux *a;
+ int n;
+
+ a = smalloc(sizeof(*a));
+ kstrdup(&a->owner, owner);
+ memset(a->tag, ' ', sizeof(a->tag));
+ n = strlen(tag);
+ if(n > sizeof(a->tag))
+ n = sizeof(a->tag);
+ memmove(a->tag, tag, n);
+ return a;
+}
+
+#define ATTACHER(c) (((IPaux*)((c)->aux))->owner)
+
+static Chan*
+ipattach(char* spec)
+{
+ Chan *c;
+ int dev;
+
+ dev = atoi(spec);
+ if(dev >= Nfs)
+ error("bad specification");
+
+ ipgetfs(dev);
+ c = devattach('I', spec);
+ mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR);
+ c->dev = dev;
+
+ c->aux = newipaux(commonuser(), "none");
+
+ return c;
+}
+
+static Walkqid*
+ipwalk(Chan* c, Chan *nc, char **name, int nname)
+{
+ IPaux *a = c->aux;
+ Walkqid* w;
+
+ w = devwalk(c, nc, name, nname, nil, 0, ipgen);
+ if(w != nil && w->clone != nil)
+ w->clone->aux = newipaux(a->owner, a->tag);
+ return w;
+}
+
+
+static int
+ipstat(Chan* c, uchar* db, int n)
+{
+ return devstat(c, db, n, nil, 0, ipgen);
+}
+
+static int
+incoming(void* arg)
+{
+ Conv *conv;
+
+ conv = arg;
+ return conv->incall != nil;
+}
+
+static int m2p[] = {
+ [OREAD] 4,
+ [OWRITE] 2,
+ [ORDWR] 6
+};
+
+static Chan*
+ipopen(Chan* c, int omode)
+{
+ Conv *cv, *nc;
+ Proto *p;
+ int perm;
+ Fs *f;
+
+ perm = m2p[omode&3];
+
+ f = ipfs[c->dev];
+
+ switch(TYPE(c->qid)) {
+ default:
+ break;
+ case Qndb:
+ if(omode & (OWRITE|OTRUNC) && !iseve())
+ error(Eperm);
+ if((omode & (OWRITE|OTRUNC)) == (OWRITE|OTRUNC))
+ f->ndb[0] = 0;
+ break;
+ case Qlog:
+ netlogopen(f);
+ break;
+ case Qiproute:
+ case Qarp:
+ if(omode != OREAD && !iseve())
+ error(Eperm);
+ break;
+ case Qtopdir:
+ case Qprotodir:
+ case Qconvdir:
+ case Qstatus:
+ case Qremote:
+ case Qlocal:
+ case Qstats:
+ case Qbootp:
+ case Qipselftab:
+ if(omode != OREAD)
+ error(Eperm);
+ break;
+ case Qsnoop:
+ if(omode != OREAD)
+ error(Eperm);
+ p = f->p[PROTO(c->qid)];
+ cv = p->conv[CONV(c->qid)];
+ if(strcmp(ATTACHER(c), cv->owner) != 0 && !iseve())
+ error(Eperm);
+ incref(&cv->snoopers);
+ break;
+ case Qclone:
+ p = f->p[PROTO(c->qid)];
+ qlock(p);
+ if(waserror()){
+ qunlock(p);
+ nexterror();
+ }
+ cv = Fsprotoclone(p, ATTACHER(c));
+ qunlock(p);
+ poperror();
+ if(cv == nil) {
+ error(Enodev);
+ break;
+ }
+ mkqid(&c->qid, QID(p->x, cv->x, Qctl), 0, QTFILE);
+ break;
+ case Qdata:
+ case Qctl:
+ case Qerr:
+ p = f->p[PROTO(c->qid)];
+ qlock(p);
+ cv = p->conv[CONV(c->qid)];
+ qlock(cv);
+ if(waserror()) {
+ qunlock(cv);
+ qunlock(p);
+ nexterror();
+ }
+ if((perm & (cv->perm>>6)) != perm) {
+ if(strcmp(ATTACHER(c), cv->owner) != 0)
+ error(Eperm);
+ if((perm & cv->perm) != perm)
+ error(Eperm);
+
+ }
+ cv->inuse++;
+ if(cv->inuse == 1){
+ kstrdup(&cv->owner, ATTACHER(c));
+ cv->perm = 0660;
+ }
+ qunlock(cv);
+ qunlock(p);
+ poperror();
+ break;
+ case Qlisten:
+ cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)];
+ if((perm & (cv->perm>>6)) != perm) {
+ if(strcmp(ATTACHER(c), cv->owner) != 0)
+ error(Eperm);
+ if((perm & cv->perm) != perm)
+ error(Eperm);
+
+ }
+
+ if(cv->state != Announced)
+ error("not announced");
+
+ if(waserror()){
+ closeconv(cv);
+ nexterror();
+ }
+ qlock(cv);
+ cv->inuse++;
+ qunlock(cv);
+
+ nc = nil;
+ while(nc == nil) {
+ /* give up if we got a hangup */
+ if(qisclosed(cv->rq))
+ error("listen hungup");
+
+ qlock(&cv->listenq);
+ if(waserror()) {
+ qunlock(&cv->listenq);
+ nexterror();
+ }
+
+ /* wait for a connect */
+ sleep(&cv->listenr, incoming, cv);
+
+ qlock(cv);
+ nc = cv->incall;
+ if(nc != nil){
+ cv->incall = nc->next;
+ mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE);
+ kstrdup(&cv->owner, ATTACHER(c));
+ }
+ qunlock(cv);
+
+ qunlock(&cv->listenq);
+ poperror();
+ }
+ closeconv(cv);
+ poperror();
+ break;
+ }
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+static void
+ipcreate(Chan*, char*, int, ulong)
+{
+ error(Eperm);
+}
+
+static void
+ipremove(Chan*)
+{
+ error(Eperm);
+}
+
+static int
+ipwstat(Chan *c, uchar *dp, int n)
+{
+ Dir d;
+ Conv *cv;
+ Fs *f;
+ Proto *p;
+
+ f = ipfs[c->dev];
+ switch(TYPE(c->qid)) {
+ default:
+ error(Eperm);
+ break;
+ case Qctl:
+ case Qdata:
+ break;
+ }
+
+ n = convM2D(dp, n, &d, nil);
+ if(n > 0){
+ p = f->p[PROTO(c->qid)];
+ cv = p->conv[CONV(c->qid)];
+ if(!iseve() && strcmp(ATTACHER(c), cv->owner) != 0)
+ error(Eperm);
+ if(d.uid[0])
+ kstrdup(&cv->owner, d.uid);
+ cv->perm = d.mode & 0777;
+ }
+ return n;
+}
+
+void
+closeconv(Conv *cv)
+{
+ Conv *nc;
+ Ipmulti *mp;
+
+ qlock(cv);
+
+ if(--cv->inuse > 0) {
+ qunlock(cv);
+ return;
+ }
+
+ /* close all incoming calls since no listen will ever happen */
+ for(nc = cv->incall; nc; nc = cv->incall){
+ cv->incall = nc->next;
+ closeconv(nc);
+ }
+ cv->incall = nil;
+
+ kstrdup(&cv->owner, network);
+ cv->perm = 0660;
+
+ while((mp = cv->multi) != nil)
+ ipifcremmulti(cv, mp->ma, mp->ia);
+
+ cv->r = nil;
+ cv->rgen = 0;
+ cv->p->close(cv);
+ cv->state = Idle;
+ qunlock(cv);
+}
+
+static void
+ipclose(Chan* c)
+{
+ Fs *f;
+
+ f = ipfs[c->dev];
+ switch(TYPE(c->qid)) {
+ default:
+ break;
+ case Qlog:
+ if(c->flag & COPEN)
+ netlogclose(f);
+ break;
+ case Qdata:
+ case Qctl:
+ case Qerr:
+ if(c->flag & COPEN)
+ closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]);
+ break;
+ case Qsnoop:
+ if(c->flag & COPEN)
+ decref(&f->p[PROTO(c->qid)]->conv[CONV(c->qid)]->snoopers);
+ break;
+ }
+ free(((IPaux*)c->aux)->owner);
+ free(c->aux);
+}
+
+enum
+{
+ Statelen= 32*1024,
+};
+
+static long
+ipread(Chan *ch, void *a, long n, vlong off)
+{
+ Conv *c;
+ Proto *x;
+ char *buf, *p;
+ long rv;
+ Fs *f;
+ ulong offset = off;
+
+ f = ipfs[ch->dev];
+
+ p = a;
+ switch(TYPE(ch->qid)) {
+ default:
+ error(Eperm);
+ case Qtopdir:
+ case Qprotodir:
+ case Qconvdir:
+ return devdirread(ch, a, n, 0, 0, ipgen);
+ case Qarp:
+ return arpread(f->arp, a, offset, n);
+ case Qbootp:
+ return bootpread(a, offset, n);
+ case Qndb:
+ return readstr(offset, a, n, f->ndb);
+ case Qiproute:
+ return routeread(f, a, offset, n);
+ case Qipselftab:
+ return ipselftabread(f, a, offset, n);
+ case Qlog:
+ return netlogread(f, a, offset, n);
+ case Qctl:
+ buf = smalloc(16);
+ snprint(buf, 16, "%lud", CONV(ch->qid));
+ rv = readstr(offset, p, n, buf);
+ free(buf);
+ return rv;
+ case Qremote:
+ buf = smalloc(Statelen);
+ x = f->p[PROTO(ch->qid)];
+ c = x->conv[CONV(ch->qid)];
+ if(x->remote == nil) {
+ snprint(buf, Statelen, "%I!%d\n", c->raddr, c->rport);
+ } else {
+ (*x->remote)(c, buf, Statelen-2);
+ }
+ rv = readstr(offset, p, n, buf);
+ free(buf);
+ return rv;
+ case Qlocal:
+ buf = smalloc(Statelen);
+ x = f->p[PROTO(ch->qid)];
+ c = x->conv[CONV(ch->qid)];
+ if(x->local == nil) {
+ snprint(buf, Statelen, "%I!%d\n", c->laddr, c->lport);
+ } else {
+ (*x->local)(c, buf, Statelen-2);
+ }
+ rv = readstr(offset, p, n, buf);
+ free(buf);
+ return rv;
+ case Qstatus:
+ buf = smalloc(Statelen);
+ x = f->p[PROTO(ch->qid)];
+ c = x->conv[CONV(ch->qid)];
+ (*x->state)(c, buf, Statelen-2);
+ rv = readstr(offset, p, n, buf);
+ free(buf);
+ return rv;
+ case Qdata:
+ c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
+ return qread(c->rq, a, n);
+ case Qerr:
+ c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
+ return qread(c->eq, a, n);
+ case Qsnoop:
+ c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
+ return qread(c->sq, a, n);
+ case Qstats:
+ x = f->p[PROTO(ch->qid)];
+ if(x->stats == nil)
+ error("stats not implemented");
+ buf = smalloc(Statelen);
+ (*x->stats)(x, buf, Statelen);
+ rv = readstr(offset, p, n, buf);
+ free(buf);
+ return rv;
+ }
+}
+
+static Block*
+ipbread(Chan* ch, long n, ulong offset)
+{
+ Conv *c;
+ Proto *x;
+ Fs *f;
+
+ switch(TYPE(ch->qid)){
+ case Qdata:
+ f = ipfs[ch->dev];
+ x = f->p[PROTO(ch->qid)];
+ c = x->conv[CONV(ch->qid)];
+ return qbread(c->rq, n);
+ default:
+ return devbread(ch, n, offset);
+ }
+}
+
+/*
+ * set local address to be that of the ifc closest to remote address
+ */
+static void
+setladdr(Conv* c)
+{
+ findlocalip(c->p->f, c->laddr, c->raddr);
+}
+
+/*
+ * set a local port making sure the quad of raddr,rport,laddr,lport is unique
+ */
+char*
+setluniqueport(Conv* c, int lport)
+{
+ Proto *p;
+ Conv *xp;
+ int x;
+
+ p = c->p;
+
+ qlock(p);
+ for(x = 0; x < p->nc; x++){
+ xp = p->conv[x];
+ if(xp == nil)
+ break;
+ if(xp == c)
+ continue;
+ if((xp->state == Connected || xp->state == Announced)
+ && xp->lport == lport
+ && xp->rport == c->rport
+ && ipcmp(xp->raddr, c->raddr) == 0
+ && ipcmp(xp->laddr, c->laddr) == 0){
+ qunlock(p);
+ return "address in use";
+ }
+ }
+ c->lport = lport;
+ qunlock(p);
+ return nil;
+}
+
+/*
+ * is lport in use by anyone?
+ */
+static int
+lportinuse(Proto *p, ushort lport)
+{
+ int x;
+
+ for(x = 0; x < p->nc && p->conv[x]; x++)
+ if(p->conv[x]->lport == lport)
+ return 1;
+ return 0;
+}
+
+/*
+ * pick a local port and set it
+ */
+char *
+setlport(Conv* c)
+{
+ Proto *p;
+ int i, port;
+
+ p = c->p;
+ qlock(p);
+ if(c->restricted){
+ /* Restricted ports cycle between 600 and 1024. */
+ for(i=0; i<1024-600; i++){
+ if(p->nextrport >= 1024 || p->nextrport < 600)
+ p->nextrport = 600;
+ port = p->nextrport++;
+ if(!lportinuse(p, port))
+ goto chosen;
+ }
+ }else{
+ /*
+ * Unrestricted ports are chosen randomly
+ * between 2^15 and 2^16. There are at most
+ * 4*Nchan = 4096 ports in use at any given time,
+ * so even in the worst case, a random probe has a
+ * 1 - 4096/2^15 = 87% chance of success.
+ * If 64 successive probes fail, there is a bug somewhere
+ * (or a once in 10^58 event has happened, but that's
+ * less likely than a venti collision).
+ */
+ for(i=0; i<64; i++){
+ port = (1<<15) + nrand(1<<15);
+ if(!lportinuse(p, port))
+ goto chosen;
+ }
+ }
+ qunlock(p);
+ /*
+ * debugging: let's see if we ever get this.
+ * if we do (and we're a cpu server), we might as well restart
+ * since we're now unable to service new connections.
+ */
+ panic("setlport: out of ports");
+ return "no ports available";
+
+chosen:
+ c->lport = port;
+ qunlock(p);
+ return nil;
+}
+
+/*
+ * set a local address and port from a string of the form
+ * [address!]port[!r]
+ */
+char*
+setladdrport(Conv* c, char* str, int announcing)
+{
+ char *p;
+ char *rv;
+ ushort lport;
+ uchar addr[IPaddrlen];
+
+ /*
+ * ignore restricted part if it exists. it's
+ * meaningless on local ports.
+ */
+ p = strchr(str, '!');
+ if(p != nil){
+ *p++ = 0;
+ if(strcmp(p, "r") == 0)
+ p = nil;
+ }
+
+ c->lport = 0;
+ if(p == nil){
+ if(announcing)
+ ipmove(c->laddr, IPnoaddr);
+ else
+ setladdr(c);
+ p = str;
+ } else {
+ if(strcmp(str, "*") == 0)
+ ipmove(c->laddr, IPnoaddr);
+ else {
+ if(parseip(addr, str) == -1)
+ return Ebadip;
+ if(ipforme(c->p->f, addr))
+ ipmove(c->laddr, addr);
+ else
+ return "not a local IP address";
+ }
+ }
+
+ /* one process can get all connections */
+ if(announcing && strcmp(p, "*") == 0){
+ if(!iseve())
+ error(Eperm);
+ return setluniqueport(c, 0);
+ }
+
+ lport = atoi(p);
+ if(lport <= 0)
+ rv = setlport(c);
+ else
+ rv = setluniqueport(c, lport);
+ return rv;
+}
+
+static char*
+setraddrport(Conv* c, char* str)
+{
+ char *p;
+
+ p = strchr(str, '!');
+ if(p == nil)
+ return "malformed address";
+ *p++ = 0;
+ if (parseip(c->raddr, str) == -1)
+ return Ebadip;
+ c->rport = atoi(p);
+ p = strchr(p, '!');
+ if(p){
+ if(strstr(p, "!r") != nil)
+ c->restricted = 1;
+ }
+ return nil;
+}
+
+/*
+ * called by protocol connect routine to set addresses
+ */
+char*
+Fsstdconnect(Conv *c, char *argv[], int argc)
+{
+ char *p;
+
+ switch(argc) {
+ default:
+ return "bad args to connect";
+ case 2:
+ p = setraddrport(c, argv[1]);
+ if(p != nil)
+ return p;
+ setladdr(c);
+ p = setlport(c);
+ if (p != nil)
+ return p;
+ break;
+ case 3:
+ p = setraddrport(c, argv[1]);
+ if(p != nil)
+ return p;
+ p = setladdrport(c, argv[2], 0);
+ if(p != nil)
+ return p;
+ }
+
+ if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
+ memcmp(c->laddr, v4prefix, IPv4off) == 0)
+ || ipcmp(c->raddr, IPnoaddr) == 0)
+ c->ipversion = V4;
+ else
+ c->ipversion = V6;
+
+ return nil;
+}
+/*
+ * initiate connection and sleep till its set up
+ */
+static int
+connected(void* a)
+{
+ return ((Conv*)a)->state == Connected;
+}
+static void
+connectctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
+{
+ char *p;
+
+ if(c->state != 0)
+ error(Econinuse);
+ c->state = Connecting;
+ c->cerr[0] = '\0';
+ if(x->connect == nil)
+ error("connect not supported");
+ p = x->connect(c, cb->f, cb->nf);
+ if(p != nil)
+ error(p);
+
+ qunlock(c);
+ if(waserror()){
+ qlock(c);
+ nexterror();
+ }
+ sleep(&c->cr, connected, c);
+ qlock(c);
+ poperror();
+
+ if(c->cerr[0] != '\0')
+ error(c->cerr);
+}
+
+/*
+ * called by protocol announce routine to set addresses
+ */
+char*
+Fsstdannounce(Conv* c, char* argv[], int argc)
+{
+ memset(c->raddr, 0, sizeof(c->raddr));
+ c->rport = 0;
+ switch(argc){
+ default:
+ break;
+ case 2:
+ return setladdrport(c, argv[1], 1);
+ }
+ return "bad args to announce";
+}
+
+/*
+ * initiate announcement and sleep till its set up
+ */
+static int
+announced(void* a)
+{
+ return ((Conv*)a)->state == Announced;
+}
+static void
+announcectlmsg(Proto *x, Conv *c, Cmdbuf *cb)
+{
+ char *p;
+
+ if(c->state != 0)
+ error(Econinuse);
+ c->state = Announcing;
+ c->cerr[0] = '\0';
+ if(x->announce == nil)
+ error("announce not supported");
+ p = x->announce(c, cb->f, cb->nf);
+ if(p != nil)
+ error(p);
+
+ qunlock(c);
+ if(waserror()){
+ qlock(c);
+ nexterror();
+ }
+ sleep(&c->cr, announced, c);
+ qlock(c);
+ poperror();
+
+ if(c->cerr[0] != '\0')
+ error(c->cerr);
+}
+
+/*
+ * called by protocol bind routine to set addresses
+ */
+char*
+Fsstdbind(Conv* c, char* argv[], int argc)
+{
+ switch(argc){
+ default:
+ break;
+ case 2:
+ return setladdrport(c, argv[1], 0);
+ }
+ return "bad args to bind";
+}
+
+static void
+bindctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
+{
+ char *p;
+
+ if(x->bind == nil)
+ p = Fsstdbind(c, cb->f, cb->nf);
+ else
+ p = x->bind(c, cb->f, cb->nf);
+ if(p != nil)
+ error(p);
+}
+
+static void
+tosctlmsg(Conv *c, Cmdbuf *cb)
+{
+ if(cb->nf < 2)
+ c->tos = 0;
+ else
+ c->tos = atoi(cb->f[1]);
+}
+
+static void
+ttlctlmsg(Conv *c, Cmdbuf *cb)
+{
+ if(cb->nf < 2)
+ c->ttl = MAXTTL;
+ else
+ c->ttl = atoi(cb->f[1]);
+}
+
+static long
+ipwrite(Chan* ch, void *v, long n, vlong off)
+{
+ Conv *c;
+ Proto *x;
+ char *p;
+ Cmdbuf *cb;
+ uchar ia[IPaddrlen], ma[IPaddrlen];
+ Fs *f;
+ char *a;
+ ulong offset = off;
+
+ a = v;
+ f = ipfs[ch->dev];
+
+ switch(TYPE(ch->qid)){
+ default:
+ error(Eperm);
+ case Qdata:
+ x = f->p[PROTO(ch->qid)];
+ c = x->conv[CONV(ch->qid)];
+
+ if(c->wq == nil)
+ error(Eperm);
+
+ qwrite(c->wq, a, n);
+ break;
+ case Qarp:
+ return arpwrite(f, a, n);
+ case Qiproute:
+ return routewrite(f, ch, a, n);
+ case Qlog:
+ netlogctl(f, a, n);
+ return n;
+ case Qndb:
+ return ndbwrite(f, a, offset, n);
+ break;
+ case Qctl:
+ x = f->p[PROTO(ch->qid)];
+ c = x->conv[CONV(ch->qid)];
+ cb = parsecmd(a, n);
+
+ qlock(c);
+ if(waserror()) {
+ qunlock(c);
+ free(cb);
+ nexterror();
+ }
+ if(cb->nf < 1)
+ error("short control request");
+ if(strcmp(cb->f[0], "connect") == 0)
+ connectctlmsg(x, c, cb);
+ else if(strcmp(cb->f[0], "announce") == 0)
+ announcectlmsg(x, c, cb);
+ else if(strcmp(cb->f[0], "bind") == 0)
+ bindctlmsg(x, c, cb);
+ else if(strcmp(cb->f[0], "ttl") == 0)
+ ttlctlmsg(c, cb);
+ else if(strcmp(cb->f[0], "tos") == 0)
+ tosctlmsg(c, cb);
+ else if(strcmp(cb->f[0], "ignoreadvice") == 0)
+ c->ignoreadvice = 1;
+ else if(strcmp(cb->f[0], "addmulti") == 0){
+ if(cb->nf < 2)
+ error("addmulti needs interface address");
+ if(cb->nf == 2){
+ if(!ipismulticast(c->raddr))
+ error("addmulti for a non multicast address");
+ if (parseip(ia, cb->f[1]) == -1)
+ error(Ebadip);
+ ipifcaddmulti(c, c->raddr, ia);
+ } else {
+ if (parseip(ia, cb->f[1]) == -1 ||
+ parseip(ma, cb->f[2]) == -1)
+ error(Ebadip);
+ if(!ipismulticast(ma))
+ error("addmulti for a non multicast address");
+ ipifcaddmulti(c, ma, ia);
+ }
+ } else if(strcmp(cb->f[0], "remmulti") == 0){
+ if(cb->nf < 2)
+ error("remmulti needs interface address");
+ if(!ipismulticast(c->raddr))
+ error("remmulti for a non multicast address");
+ if (parseip(ia, cb->f[1]) == -1)
+ error(Ebadip);
+ ipifcremmulti(c, c->raddr, ia);
+ } else if(strcmp(cb->f[0], "maxfragsize") == 0){
+ if(cb->nf < 2)
+ error("maxfragsize needs size");
+
+ c->maxfragsize = (int)strtol(cb->f[1], nil, 0);
+
+ } else if(x->ctl != nil) {
+ p = x->ctl(c, cb->f, cb->nf);
+ if(p != nil)
+ error(p);
+ } else
+ error("unknown control request");
+ qunlock(c);
+ free(cb);
+ poperror();
+ }
+ return n;
+}
+
+static long
+ipbwrite(Chan* ch, Block* bp, ulong offset)
+{
+ Conv *c;
+ Proto *x;
+ Fs *f;
+ int n;
+
+ switch(TYPE(ch->qid)){
+ case Qdata:
+ f = ipfs[ch->dev];
+ x = f->p[PROTO(ch->qid)];
+ c = x->conv[CONV(ch->qid)];
+
+ if(c->wq == nil)
+ error(Eperm);
+
+ if(bp->next)
+ bp = concatblock(bp);
+ n = BLEN(bp);
+ qbwrite(c->wq, bp);
+ return n;
+ default:
+ return devbwrite(ch, bp, offset);
+ }
+}
+
+Dev ipdevtab = {
+ 'I',
+ "ip",
+
+ ipreset,
+ devinit,
+ devshutdown,
+ ipattach,
+ ipwalk,
+ ipstat,
+ ipopen,
+ ipcreate,
+ ipclose,
+ ipread,
+ ipbread,
+ ipwrite,
+ ipbwrite,
+ ipremove,
+ ipwstat,
+};
+
+int
+Fsproto(Fs *f, Proto *p)
+{
+ if(f->np >= Maxproto)
+ return -1;
+
+ p->f = f;
+
+ if(p->ipproto > 0){
+ if(f->t2p[p->ipproto] != nil)
+ return -1;
+ f->t2p[p->ipproto] = p;
+ }
+
+ p->qid.type = QTDIR;
+ p->qid.path = QID(f->np, 0, Qprotodir);
+ p->conv = malloc(sizeof(Conv*)*(p->nc+1));
+ if(p->conv == nil)
+ panic("Fsproto");
+
+ p->x = f->np;
+ p->nextrport = 600;
+ f->p[f->np++] = p;
+
+ return 0;
+}
+
+/*
+ * return true if this protocol is
+ * built in
+ */
+int
+Fsbuiltinproto(Fs* f, uchar proto)
+{
+ return f->t2p[proto] != nil;
+}
+
+/*
+ * called with protocol locked
+ */
+Conv*
+Fsprotoclone(Proto *p, char *user)
+{
+ Conv *c, **pp, **ep;
+
+retry:
+ c = nil;
+ ep = &p->conv[p->nc];
+ for(pp = p->conv; pp < ep; pp++) {
+ c = *pp;
+ if(c == nil){
+ c = malloc(sizeof(Conv));
+ if(c == nil)
+ error(Enomem);
+ qlock(c);
+ c->p = p;
+ c->x = pp - p->conv;
+ if(p->ptclsize != 0){
+ c->ptcl = malloc(p->ptclsize);
+ if(c->ptcl == nil) {
+ free(c);
+ error(Enomem);
+ }
+ }
+ *pp = c;
+ p->ac++;
+ c->eq = qopen(1024, Qmsg, 0, 0);
+ (*p->create)(c);
+ break;
+ }
+ if(canqlock(c)){
+ /*
+ * make sure both processes and protocol
+ * are done with this Conv
+ */
+ if(c->inuse == 0 && (p->inuse == nil || (*p->inuse)(c) == 0))
+ break;
+
+ qunlock(c);
+ }
+ }
+ if(pp >= ep) {
+ if(p->gc)
+ print("Fsprotoclone: garbage collecting Convs\n");
+ if(p->gc != nil && (*p->gc)(p))
+ goto retry;
+ /* debugging: do we ever get here? */
+ if (cpuserver)
+ panic("Fsprotoclone: all conversations in use");
+ return nil;
+ }
+
+ c->inuse = 1;
+ kstrdup(&c->owner, user);
+ c->perm = 0660;
+ c->state = Idle;
+ ipmove(c->laddr, IPnoaddr);
+ ipmove(c->raddr, IPnoaddr);
+ c->r = nil;
+ c->rgen = 0;
+ c->lport = 0;
+ c->rport = 0;
+ c->restricted = 0;
+ c->maxfragsize = 0;
+ c->ttl = MAXTTL;
+ qreopen(c->rq);
+ qreopen(c->wq);
+ qreopen(c->eq);
+
+ qunlock(c);
+ return c;
+}
+
+int
+Fsconnected(Conv* c, char* msg)
+{
+ if(msg != nil && *msg != '\0')
+ strncpy(c->cerr, msg, ERRMAX-1);
+
+ switch(c->state){
+
+ case Announcing:
+ c->state = Announced;
+ break;
+
+ case Connecting:
+ c->state = Connected;
+ break;
+ }
+
+ wakeup(&c->cr);
+ return 0;
+}
+
+Proto*
+Fsrcvpcol(Fs* f, uchar proto)
+{
+ if(f->ipmux)
+ return f->ipmux;
+ else
+ return f->t2p[proto];
+}
+
+Proto*
+Fsrcvpcolx(Fs *f, uchar proto)
+{
+ return f->t2p[proto];
+}
+
+/*
+ * called with protocol locked
+ */
+Conv*
+Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport, uchar version)
+{
+ Conv *nc;
+ Conv **l;
+ int i;
+
+ qlock(c);
+ i = 0;
+ for(l = &c->incall; *l; l = &(*l)->next)
+ i++;
+ if(i >= Maxincall) {
+ static int beenhere;
+
+ qunlock(c);
+ if (!beenhere) {
+ beenhere = 1;
+ print("Fsnewcall: incall queue full (%d) on port %d\n",
+ i, c->lport);
+ }
+ return nil;
+ }
+
+ /* find a free conversation */
+ nc = Fsprotoclone(c->p, network);
+ if(nc == nil) {
+ qunlock(c);
+ return nil;
+ }
+ ipmove(nc->raddr, raddr);
+ nc->rport = rport;
+ ipmove(nc->laddr, laddr);
+ nc->lport = lport;
+ nc->next = nil;
+ *l = nc;
+ nc->state = Connected;
+ nc->ipversion = version;
+
+ qunlock(c);
+
+ wakeup(&c->listenr);
+
+ return nc;
+}
+
+long
+ndbwrite(Fs *f, char *a, ulong off, int n)
+{
+ if(off > strlen(f->ndb))
+ error(Eio);
+ if(off+n >= sizeof(f->ndb))
+ error(Eio);
+ memmove(f->ndb+off, a, n);
+ f->ndb[off+n] = 0;
+ f->ndbvers++;
+ f->ndbmtime = seconds();
+ return n;
+}
+
+ulong
+scalednconv(void)
+{
+ if(cpuserver && conf.npage*BY2PG >= 128*MB)
+ return Nchans*4;
+ return Nchans;
+}
diff --git a/sys/src/9/ip/eipconvtest.c b/sys/src/9/ip/eipconvtest.c
new file mode 100755
index 000000000..06b0f9b50
--- /dev/null
+++ b/sys/src/9/ip/eipconvtest.c
@@ -0,0 +1,152 @@
+#include <u.h>
+#include <libc.h>
+
+enum
+{
+ Isprefix= 16,
+};
+
+uchar prefixvals[256] =
+{
+[0x00] 0 | Isprefix,
+[0x80] 1 | Isprefix,
+[0xC0] 2 | Isprefix,
+[0xE0] 3 | Isprefix,
+[0xF0] 4 | Isprefix,
+[0xF8] 5 | Isprefix,
+[0xFC] 6 | Isprefix,
+[0xFE] 7 | Isprefix,
+[0xFF] 8 | Isprefix,
+};
+
+uchar v4prefix[16] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0xff, 0xff,
+ 0, 0, 0, 0
+};
+
+void
+hnputl(void *p, ulong v)
+{
+ uchar *a;
+
+ a = p;
+ a[0] = v>>24;
+ a[1] = v>>16;
+ a[2] = v>>8;
+ a[3] = v;
+}
+
+int
+eipconv(va_list *arg, Fconv *f)
+{
+ char buf[8*5];
+ static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
+ static char *ifmt = "%d.%d.%d.%d";
+ uchar *p, ip[16];
+ ulong *lp;
+ ushort s;
+ int i, j, n, eln, eli;
+
+ switch(f->chr) {
+ case 'E': /* Ethernet address */
+ p = va_arg(*arg, uchar*);
+ sprint(buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
+ break;
+ case 'I': /* Ip address */
+ p = va_arg(*arg, uchar*);
+common:
+ if(memcmp(p, v4prefix, 12) == 0)
+ sprint(buf, ifmt, p[12], p[13], p[14], p[15]);
+ else {
+ /* find longest elision */
+ eln = eli = -1;
+ for(i = 0; i < 16; i += 2){
+ for(j = i; j < 16; j += 2)
+ if(p[j] != 0 || p[j+1] != 0)
+ break;
+ if(j > i && j - i > eln){
+ eli = i;
+ eln = j - i;
+ }
+ }
+
+ /* print with possible elision */
+ n = 0;
+ for(i = 0; i < 16; i += 2){
+ if(i == eli){
+ n += sprint(buf+n, "::");
+ i += eln;
+ if(i >= 16)
+ break;
+ } else if(i != 0)
+ n += sprint(buf+n, ":");
+ s = (p[i]<<8) + p[i+1];
+ n += sprint(buf+n, "%ux", s);
+ }
+ }
+ break;
+ case 'i': /* v6 address as 4 longs */
+ lp = va_arg(*arg, ulong*);
+ for(i = 0; i < 4; i++)
+ hnputl(ip+4*i, *lp++);
+ p = ip;
+ goto common;
+ case 'V': /* v4 ip address */
+ p = va_arg(*arg, uchar*);
+ sprint(buf, ifmt, p[0], p[1], p[2], p[3]);
+ break;
+ case 'M': /* ip mask */
+ p = va_arg(*arg, uchar*);
+
+ /* look for a prefix mask */
+ for(i = 0; i < 16; i++)
+ if(p[i] != 0xff)
+ break;
+ if(i < 16){
+ if((prefixvals[p[i]] & Isprefix) == 0)
+ goto common;
+ for(j = i+1; j < 16; j++)
+ if(p[j] != 0)
+ goto common;
+ n = 8*i + (prefixvals[p[i]] & ~Isprefix);
+ } else
+ n = 8*16;
+
+ /* got one, use /xx format */
+ sprint(buf, "/%d", n);
+ break;
+ default:
+ strcpy(buf, "(eipconv)");
+ }
+ strconv(buf, f);
+ return sizeof(uchar*);
+}
+
+uchar testvec[11][16] =
+{
+ { 0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 1,3,4,5, },
+ { 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, },
+ { 0xff,0xff,0x80,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, },
+ { 0xff,0xff,0xff,0xc0, 0,0,0,0, 0,0,0,0, 0,0,0,0, },
+ { 0xff,0xff,0xff,0xff, 0xe0,0,0,0, 0,0,0,0, 0,0,0,0, },
+ { 0xff,0xff,0xff,0xff, 0xff,0xf0,0,0, 0,0,0,0, 0,0,0,0, },
+ { 0xff,0xff,0xff,0xff, 0xff,0xff,0xf8,0, 0,0,0,0, 0,0,0,0, },
+ { 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, },
+ { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, },
+ { 0,0,0,0, 0,0x11,0,0, 0,0,0,0, 0,0,0,0, },
+ { 0,0,0,0x11, 0,0,0,0, 0,0,0,0, 0,0,0,0x12, },
+};
+
+void
+main(void)
+{
+ int i;
+
+ fmtinstall('I', eipconv);
+ fmtinstall('M', eipconv);
+ for(i = 0; i < 11; i++)
+ print("%I\n%M\n", testvec[i], testvec[i]);
+ exits(0);
+}
diff --git a/sys/src/9/ip/esp.c b/sys/src/9/ip/esp.c
new file mode 100755
index 000000000..fb3ab2338
--- /dev/null
+++ b/sys/src/9/ip/esp.c
@@ -0,0 +1,1112 @@
+/*
+ * Encapsulating Security Payload for IPsec for IPv4, rfc1827.
+ * extended to IPv6.
+ * rfc2104 defines hmac computation.
+ * currently only implements tunnel mode.
+ * TODO: verify aes algorithms;
+ * transport mode (host-to-host)
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+#include "ipv6.h"
+#include "libsec.h"
+
+#define BITS2BYTES(bi) (((bi) + BI2BY - 1) / BI2BY)
+#define BYTES2BITS(by) ((by) * BI2BY)
+
+typedef struct Algorithm Algorithm;
+typedef struct Esp4hdr Esp4hdr;
+typedef struct Esp6hdr Esp6hdr;
+typedef struct Espcb Espcb;
+typedef struct Esphdr Esphdr;
+typedef struct Esppriv Esppriv;
+typedef struct Esptail Esptail;
+typedef struct Userhdr Userhdr;
+
+enum {
+ Encrypt,
+ Decrypt,
+
+ IP_ESPPROTO = 50, /* IP v4 and v6 protocol number */
+ Esp4hdrlen = IP4HDR + 8,
+ Esp6hdrlen = IP6HDR + 8,
+
+ Esptaillen = 2, /* does not include pad or auth data */
+ Userhdrlen = 4, /* user-visible header size - if enabled */
+
+ Desblk = BITS2BYTES(64),
+ Des3keysz = BITS2BYTES(192),
+
+ Aesblk = BITS2BYTES(128),
+ Aeskeysz = BITS2BYTES(128),
+};
+
+struct Esphdr
+{
+ uchar espspi[4]; /* Security parameter index */
+ uchar espseq[4]; /* Sequence number */
+ uchar payload[];
+};
+
+/*
+ * tunnel-mode (network-to-network, etc.) layout is:
+ * new IP hdrs | ESP hdr |
+ * enc { orig IP hdrs | TCP/UDP hdr | user data | ESP trailer } | ESP ICV
+ *
+ * transport-mode (host-to-host) layout would be:
+ * orig IP hdrs | ESP hdr |
+ * enc { TCP/UDP hdr | user data | ESP trailer } | ESP ICV
+ */
+struct Esp4hdr
+{
+ /* ipv4 header */
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+ uchar Unused;
+ uchar espproto; /* Protocol */
+ uchar espplen[2]; /* Header plus data length */
+ uchar espsrc[4]; /* Ip source */
+ uchar espdst[4]; /* Ip destination */
+
+ Esphdr;
+};
+
+/* tunnel-mode layout */
+struct Esp6hdr
+{
+ IPV6HDR;
+ Esphdr;
+};
+
+struct Esptail
+{
+ uchar pad;
+ uchar nexthdr;
+};
+
+/* IP-version-dependent data */
+typedef struct Versdep Versdep;
+struct Versdep
+{
+ ulong version;
+ ulong iphdrlen;
+ ulong hdrlen; /* iphdrlen + esp hdr len */
+ ulong spi;
+ uchar laddr[IPaddrlen];
+ uchar raddr[IPaddrlen];
+};
+
+/* header as seen by the user */
+struct Userhdr
+{
+ uchar nexthdr; /* next protocol */
+ uchar unused[3];
+};
+
+struct Esppriv
+{
+ uvlong in;
+ ulong inerrors;
+};
+
+/*
+ * protocol specific part of Conv
+ */
+struct Espcb
+{
+ int incoming;
+ int header; /* user-level header */
+ ulong spi;
+ ulong seq; /* last seq sent */
+ ulong window; /* for replay attacks */
+
+ char *espalg;
+ void *espstate; /* other state for esp */
+ int espivlen; /* in bytes */
+ int espblklen;
+ int (*cipher)(Espcb*, uchar *buf, int len);
+
+ char *ahalg;
+ void *ahstate; /* other state for esp */
+ int ahlen; /* auth data length in bytes */
+ int ahblklen;
+ int (*auth)(Espcb*, uchar *buf, int len, uchar *hash);
+ DigestState *ds;
+};
+
+struct Algorithm
+{
+ char *name;
+ int keylen; /* in bits */
+ void (*init)(Espcb*, char* name, uchar *key, unsigned keylen);
+};
+
+static Conv* convlookup(Proto *esp, ulong spi);
+static char *setalg(Espcb *ecb, char **f, int n, Algorithm *alg);
+static void espkick(void *x);
+
+static void nullespinit(Espcb*, char*, uchar *key, unsigned keylen);
+static void des3espinit(Espcb*, char*, uchar *key, unsigned keylen);
+static void aescbcespinit(Espcb*, char*, uchar *key, unsigned keylen);
+static void aesctrespinit(Espcb*, char*, uchar *key, unsigned keylen);
+static void desespinit(Espcb *ecb, char *name, uchar *k, unsigned n);
+
+static void nullahinit(Espcb*, char*, uchar *key, unsigned keylen);
+static void shaahinit(Espcb*, char*, uchar *key, unsigned keylen);
+static void aesahinit(Espcb*, char*, uchar *key, unsigned keylen);
+static void md5ahinit(Espcb*, char*, uchar *key, unsigned keylen);
+
+static Algorithm espalg[] =
+{
+ "null", 0, nullespinit,
+ "des3_cbc", 192, des3espinit, /* new rfc2451, des-ede3 */
+ "aes_128_cbc", 128, aescbcespinit, /* new rfc3602 */
+ "aes_ctr", 128, aesctrespinit, /* new rfc3686 */
+ "des_56_cbc", 64, desespinit, /* rfc2405, deprecated */
+ /* rc4 was never required, was used in original bandt */
+// "rc4_128", 128, rc4espinit,
+ nil, 0, nil,
+};
+
+static Algorithm ahalg[] =
+{
+ "null", 0, nullahinit,
+ "hmac_sha1_96", 128, shaahinit, /* rfc2404 */
+ "aes_xcbc_mac_96", 128, aesahinit, /* new rfc3566 */
+ "hmac_md5_96", 128, md5ahinit, /* rfc2403 */
+ nil, 0, nil,
+};
+
+static char*
+espconnect(Conv *c, char **argv, int argc)
+{
+ char *p, *pp, *e = nil;
+ ulong spi;
+ Espcb *ecb = (Espcb*)c->ptcl;
+
+ switch(argc) {
+ default:
+ e = "bad args to connect";
+ break;
+ case 2:
+ p = strchr(argv[1], '!');
+ if(p == nil){
+ e = "malformed address";
+ break;
+ }
+ *p++ = 0;
+ if (parseip(c->raddr, argv[1]) == -1) {
+ e = Ebadip;
+ break;
+ }
+ findlocalip(c->p->f, c->laddr, c->raddr);
+ ecb->incoming = 0;
+ ecb->seq = 0;
+ if(strcmp(p, "*") == 0) {
+ qlock(c->p);
+ for(;;) {
+ spi = nrand(1<<16) + 256;
+ if(convlookup(c->p, spi) == nil)
+ break;
+ }
+ qunlock(c->p);
+ ecb->spi = spi;
+ ecb->incoming = 1;
+ qhangup(c->wq, nil);
+ } else {
+ spi = strtoul(p, &pp, 10);
+ if(pp == p) {
+ e = "malformed address";
+ break;
+ }
+ ecb->spi = spi;
+ qhangup(c->rq, nil);
+ }
+ nullespinit(ecb, "null", nil, 0);
+ nullahinit(ecb, "null", nil, 0);
+ }
+ Fsconnected(c, e);
+
+ return e;
+}
+
+
+static int
+espstate(Conv *c, char *state, int n)
+{
+ return snprint(state, n, "%s", c->inuse?"Open\n":"Closed\n");
+}
+
+static void
+espcreate(Conv *c)
+{
+ c->rq = qopen(64*1024, Qmsg, 0, 0);
+ c->wq = qopen(64*1024, Qkick, espkick, c);
+}
+
+static void
+espclose(Conv *c)
+{
+ Espcb *ecb;
+
+ qclose(c->rq);
+ qclose(c->wq);
+ qclose(c->eq);
+ ipmove(c->laddr, IPnoaddr);
+ ipmove(c->raddr, IPnoaddr);
+
+ ecb = (Espcb*)c->ptcl;
+ free(ecb->espstate);
+ free(ecb->ahstate);
+ memset(ecb, 0, sizeof(Espcb));
+}
+
+static int
+convipvers(Conv *c)
+{
+ if((memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
+ memcmp(c->laddr, v4prefix, IPv4off) == 0) ||
+ ipcmp(c->raddr, IPnoaddr) == 0)
+ return V4;
+ else
+ return V6;
+}
+
+static int
+pktipvers(Fs *f, Block **bpp)
+{
+ if (*bpp == nil || BLEN(*bpp) == 0) {
+ /* get enough to identify the IP version */
+ *bpp = pullupblock(*bpp, IP4HDR);
+ if(*bpp == nil) {
+ netlog(f, Logesp, "esp: short packet\n");
+ return 0;
+ }
+ }
+ return (((Esp4hdr*)(*bpp)->rp)->vihl & 0xf0) == IP_VER4? V4: V6;
+}
+
+static void
+getverslens(int version, Versdep *vp)
+{
+ vp->version = version;
+ switch(vp->version) {
+ case V4:
+ vp->iphdrlen = IP4HDR;
+ vp->hdrlen = Esp4hdrlen;
+ break;
+ case V6:
+ vp->iphdrlen = IP6HDR;
+ vp->hdrlen = Esp6hdrlen;
+ break;
+ default:
+ panic("esp: getverslens version %d wrong", version);
+ }
+}
+
+static void
+getpktspiaddrs(uchar *pkt, Versdep *vp)
+{
+ Esp4hdr *eh4;
+ Esp6hdr *eh6;
+
+ switch(vp->version) {
+ case V4:
+ eh4 = (Esp4hdr*)pkt;
+ v4tov6(vp->raddr, eh4->espsrc);
+ v4tov6(vp->laddr, eh4->espdst);
+ vp->spi = nhgetl(eh4->espspi);
+ break;
+ case V6:
+ eh6 = (Esp6hdr*)pkt;
+ ipmove(vp->raddr, eh6->src);
+ ipmove(vp->laddr, eh6->dst);
+ vp->spi = nhgetl(eh6->espspi);
+ break;
+ default:
+ panic("esp: getpktspiaddrs vp->version %ld wrong", vp->version);
+ }
+}
+
+/*
+ * encapsulate next IP packet on x's write queue in IP/ESP packet
+ * and initiate output of the result.
+ */
+static void
+espkick(void *x)
+{
+ int nexthdr, payload, pad, align;
+ uchar *auth;
+ Block *bp;
+ Conv *c = x;
+ Esp4hdr *eh4;
+ Esp6hdr *eh6;
+ Espcb *ecb;
+ Esptail *et;
+ Userhdr *uh;
+ Versdep vers;
+
+ getverslens(convipvers(c), &vers);
+ bp = qget(c->wq);
+ if(bp == nil)
+ return;
+
+ qlock(c);
+ ecb = c->ptcl;
+
+ if(ecb->header) {
+ /* make sure the message has a User header */
+ bp = pullupblock(bp, Userhdrlen);
+ if(bp == nil) {
+ qunlock(c);
+ return;
+ }
+ uh = (Userhdr*)bp->rp;
+ nexthdr = uh->nexthdr;
+ bp->rp += Userhdrlen;
+ } else {
+ nexthdr = 0; /* what should this be? */
+ }
+
+ payload = BLEN(bp) + ecb->espivlen;
+
+ /* Make space to fit ip header */
+ bp = padblock(bp, vers.hdrlen + ecb->espivlen);
+ getpktspiaddrs(bp->rp, &vers);
+
+ align = 4;
+ if(ecb->espblklen > align)
+ align = ecb->espblklen;
+ if(align % ecb->ahblklen != 0)
+ panic("espkick: ahblklen is important after all");
+ pad = (align-1) - (payload + Esptaillen-1)%align;
+
+ /*
+ * Make space for tail
+ * this is done by calling padblock with a negative size
+ * Padblock does not change bp->wp!
+ */
+ bp = padblock(bp, -(pad+Esptaillen+ecb->ahlen));
+ bp->wp += pad+Esptaillen+ecb->ahlen;
+
+ et = (Esptail*)(bp->rp + vers.hdrlen + payload + pad);
+
+ /* fill in tail */
+ et->pad = pad;
+ et->nexthdr = nexthdr;
+
+ /* encrypt the payload */
+ ecb->cipher(ecb, bp->rp + vers.hdrlen, payload + pad + Esptaillen);
+ auth = bp->rp + vers.hdrlen + payload + pad + Esptaillen;
+
+ /* fill in head; construct a new IP header and an ESP header */
+ if (vers.version == V4) {
+ eh4 = (Esp4hdr *)bp->rp;
+ eh4->vihl = IP_VER4;
+ v6tov4(eh4->espsrc, c->laddr);
+ v6tov4(eh4->espdst, c->raddr);
+ eh4->espproto = IP_ESPPROTO;
+ eh4->frag[0] = 0;
+ eh4->frag[1] = 0;
+
+ hnputl(eh4->espspi, ecb->spi);
+ hnputl(eh4->espseq, ++ecb->seq);
+ } else {
+ eh6 = (Esp6hdr *)bp->rp;
+ eh6->vcf[0] = IP_VER6;
+ ipmove(eh6->src, c->laddr);
+ ipmove(eh6->dst, c->raddr);
+ eh6->proto = IP_ESPPROTO;
+
+ hnputl(eh6->espspi, ecb->spi);
+ hnputl(eh6->espseq, ++ecb->seq);
+ }
+
+ /* compute secure hash */
+ ecb->auth(ecb, bp->rp + vers.iphdrlen, (vers.hdrlen - vers.iphdrlen) +
+ payload + pad + Esptaillen, auth);
+
+ qunlock(c);
+ /* print("esp: pass down: %uld\n", BLEN(bp)); */
+ if (vers.version == V4)
+ ipoput4(c->p->f, bp, 0, c->ttl, c->tos, c);
+ else
+ ipoput6(c->p->f, bp, 0, c->ttl, c->tos, c);
+}
+
+/*
+ * decapsulate IP packet from IP/ESP packet in bp and
+ * pass the result up the spi's Conv's read queue.
+ */
+void
+espiput(Proto *esp, Ipifc*, Block *bp)
+{
+ int payload, nexthdr;
+ uchar *auth, *espspi;
+ Conv *c;
+ Espcb *ecb;
+ Esptail *et;
+ Fs *f;
+ Userhdr *uh;
+ Versdep vers;
+
+ f = esp->f;
+
+ getverslens(pktipvers(f, &bp), &vers);
+
+ bp = pullupblock(bp, vers.hdrlen + Esptaillen);
+ if(bp == nil) {
+ netlog(f, Logesp, "esp: short packet\n");
+ return;
+ }
+ getpktspiaddrs(bp->rp, &vers);
+
+ qlock(esp);
+ /* Look for a conversation structure for this port */
+ c = convlookup(esp, vers.spi);
+ if(c == nil) {
+ qunlock(esp);
+ netlog(f, Logesp, "esp: no conv %I -> %I!%lud\n", vers.raddr,
+ vers.laddr, vers.spi);
+ icmpnoconv(f, bp);
+ freeblist(bp);
+ return;
+ }
+
+ qlock(c);
+ qunlock(esp);
+
+ ecb = c->ptcl;
+ /* too hard to do decryption/authentication on block lists */
+ if(bp->next)
+ bp = concatblock(bp);
+
+ if(BLEN(bp) < vers.hdrlen + ecb->espivlen + Esptaillen + ecb->ahlen) {
+ qunlock(c);
+ netlog(f, Logesp, "esp: short block %I -> %I!%lud\n", vers.raddr,
+ vers.laddr, vers.spi);
+ freeb(bp);
+ return;
+ }
+
+ auth = bp->wp - ecb->ahlen;
+ espspi = vers.version == V4? ((Esp4hdr*)bp->rp)->espspi:
+ ((Esp6hdr*)bp->rp)->espspi;
+
+ /* compute secure hash and authenticate */
+ if(!ecb->auth(ecb, espspi, auth - espspi, auth)) {
+ qunlock(c);
+print("esp: bad auth %I -> %I!%ld\n", vers.raddr, vers.laddr, vers.spi);
+ netlog(f, Logesp, "esp: bad auth %I -> %I!%lud\n", vers.raddr,
+ vers.laddr, vers.spi);
+ freeb(bp);
+ return;
+ }
+
+ payload = BLEN(bp) - vers.hdrlen - ecb->ahlen;
+ if(payload <= 0 || payload % 4 != 0 || payload % ecb->espblklen != 0) {
+ qunlock(c);
+ netlog(f, Logesp, "esp: bad length %I -> %I!%lud payload=%d BLEN=%lud\n",
+ vers.raddr, vers.laddr, vers.spi, payload, BLEN(bp));
+ freeb(bp);
+ return;
+ }
+
+ /* decrypt payload */
+ if(!ecb->cipher(ecb, bp->rp + vers.hdrlen, payload)) {
+ qunlock(c);
+print("esp: cipher failed %I -> %I!%ld: %s\n", vers.raddr, vers.laddr, vers.spi, up->errstr);
+ netlog(f, Logesp, "esp: cipher failed %I -> %I!%lud: %s\n",
+ vers.raddr, vers.laddr, vers.spi, up->errstr);
+ freeb(bp);
+ return;
+ }
+
+ payload -= Esptaillen;
+ et = (Esptail*)(bp->rp + vers.hdrlen + payload);
+ payload -= et->pad + ecb->espivlen;
+ nexthdr = et->nexthdr;
+ if(payload <= 0) {
+ qunlock(c);
+ netlog(f, Logesp, "esp: short packet after decrypt %I -> %I!%lud\n",
+ vers.raddr, vers.laddr, vers.spi);
+ freeb(bp);
+ return;
+ }
+
+ /* trim packet */
+ bp->rp += vers.hdrlen + ecb->espivlen; /* toss original IP & ESP hdrs */
+ bp->wp = bp->rp + payload;
+ if(ecb->header) {
+ /* assume Userhdrlen < Esp4hdrlen < Esp6hdrlen */
+ bp->rp -= Userhdrlen;
+ uh = (Userhdr*)bp->rp;
+ memset(uh, 0, Userhdrlen);
+ uh->nexthdr = nexthdr;
+ }
+
+ /* ingress filtering here? */
+
+ if(qfull(c->rq)){
+ netlog(f, Logesp, "esp: qfull %I -> %I.%uld\n", vers.raddr,
+ vers.laddr, vers.spi);
+ freeblist(bp);
+ }else {
+// print("esp: pass up: %uld\n", BLEN(bp));
+ qpass(c->rq, bp); /* pass packet up the read queue */
+ }
+
+ qunlock(c);
+}
+
+char*
+espctl(Conv *c, char **f, int n)
+{
+ Espcb *ecb = c->ptcl;
+ char *e = nil;
+
+ if(strcmp(f[0], "esp") == 0)
+ e = setalg(ecb, f, n, espalg);
+ else if(strcmp(f[0], "ah") == 0)
+ e = setalg(ecb, f, n, ahalg);
+ else if(strcmp(f[0], "header") == 0)
+ ecb->header = 1;
+ else if(strcmp(f[0], "noheader") == 0)
+ ecb->header = 0;
+ else
+ e = "unknown control request";
+ return e;
+}
+
+/* called from icmp(v6) for unreachable hosts, time exceeded, etc. */
+void
+espadvise(Proto *esp, Block *bp, char *msg)
+{
+ Conv *c;
+ Versdep vers;
+
+ getverslens(pktipvers(esp->f, &bp), &vers);
+ getpktspiaddrs(bp->rp, &vers);
+
+ qlock(esp);
+ c = convlookup(esp, vers.spi);
+ if(c != nil) {
+ qhangup(c->rq, msg);
+ qhangup(c->wq, msg);
+ }
+ qunlock(esp);
+ freeblist(bp);
+}
+
+int
+espstats(Proto *esp, char *buf, int len)
+{
+ Esppriv *upriv;
+
+ upriv = esp->priv;
+ return snprint(buf, len, "%llud %lud\n",
+ upriv->in,
+ upriv->inerrors);
+}
+
+static int
+esplocal(Conv *c, char *buf, int len)
+{
+ Espcb *ecb = c->ptcl;
+ int n;
+
+ qlock(c);
+ if(ecb->incoming)
+ n = snprint(buf, len, "%I!%uld\n", c->laddr, ecb->spi);
+ else
+ n = snprint(buf, len, "%I\n", c->laddr);
+ qunlock(c);
+ return n;
+}
+
+static int
+espremote(Conv *c, char *buf, int len)
+{
+ Espcb *ecb = c->ptcl;
+ int n;
+
+ qlock(c);
+ if(ecb->incoming)
+ n = snprint(buf, len, "%I\n", c->raddr);
+ else
+ n = snprint(buf, len, "%I!%uld\n", c->raddr, ecb->spi);
+ qunlock(c);
+ return n;
+}
+
+static Conv*
+convlookup(Proto *esp, ulong spi)
+{
+ Conv *c, **p;
+ Espcb *ecb;
+
+ for(p=esp->conv; *p; p++){
+ c = *p;
+ ecb = c->ptcl;
+ if(ecb->incoming && ecb->spi == spi)
+ return c;
+ }
+ return nil;
+}
+
+static char *
+setalg(Espcb *ecb, char **f, int n, Algorithm *alg)
+{
+ uchar *key;
+ int c, nbyte, nchar;
+ uint i;
+
+ if(n < 2 || n > 3)
+ return "bad format";
+ for(; alg->name; alg++)
+ if(strcmp(f[1], alg->name) == 0)
+ break;
+ if(alg->name == nil)
+ return "unknown algorithm";
+
+ nbyte = (alg->keylen + 7) >> 3;
+ if (n == 2)
+ nchar = 0;
+ else
+ nchar = strlen(f[2]);
+ if(nchar != 2 * nbyte) /* TODO: maybe < is ok */
+ return "key not required length";
+ /* convert hex digits from ascii, in place */
+ for(i=0; i<nchar; i++) {
+ c = f[2][i];
+ if(c >= '0' && c <= '9')
+ f[2][i] -= '0';
+ else if(c >= 'a' && c <= 'f')
+ f[2][i] -= 'a'-10;
+ else if(c >= 'A' && c <= 'F')
+ f[2][i] -= 'A'-10;
+ else
+ return "non-hex character in key";
+ }
+ /* collapse hex digits into complete bytes in reverse order in key */
+ key = smalloc(nbyte);
+ for(i = 0; i < nchar && i/2 < nbyte; i++) {
+ c = f[2][nchar-i-1];
+ if(i&1)
+ c <<= 4;
+ key[i/2] |= c;
+ }
+
+ alg->init(ecb, alg->name, key, alg->keylen);
+ free(key);
+ return nil;
+}
+
+
+/*
+ * null encryption
+ */
+
+static int
+nullcipher(Espcb*, uchar*, int)
+{
+ return 1;
+}
+
+static void
+nullespinit(Espcb *ecb, char *name, uchar*, unsigned)
+{
+ ecb->espalg = name;
+ ecb->espblklen = 1;
+ ecb->espivlen = 0;
+ ecb->cipher = nullcipher;
+}
+
+static int
+nullauth(Espcb*, uchar*, int, uchar*)
+{
+ return 1;
+}
+
+static void
+nullahinit(Espcb *ecb, char *name, uchar*, unsigned)
+{
+ ecb->ahalg = name;
+ ecb->ahblklen = 1;
+ ecb->ahlen = 0;
+ ecb->auth = nullauth;
+}
+
+
+/*
+ * sha1
+ */
+
+static void
+seanq_hmac_sha1(uchar hash[SHA1dlen], uchar *t, long tlen, uchar *key, long klen)
+{
+ int i;
+ uchar ipad[Hmacblksz+1], opad[Hmacblksz+1], innerhash[SHA1dlen];
+ DigestState *digest;
+
+ memset(ipad, 0x36, Hmacblksz);
+ memset(opad, 0x5c, Hmacblksz);
+ ipad[Hmacblksz] = opad[Hmacblksz] = 0;
+ for(i = 0; i < klen; i++){
+ ipad[i] ^= key[i];
+ opad[i] ^= key[i];
+ }
+ digest = sha1(ipad, Hmacblksz, nil, nil);
+ sha1(t, tlen, innerhash, digest);
+ digest = sha1(opad, Hmacblksz, nil, nil);
+ sha1(innerhash, SHA1dlen, hash, digest);
+}
+
+static int
+shaauth(Espcb *ecb, uchar *t, int tlen, uchar *auth)
+{
+ int r;
+ uchar hash[SHA1dlen];
+
+ memset(hash, 0, SHA1dlen);
+ seanq_hmac_sha1(hash, t, tlen, (uchar*)ecb->ahstate, BITS2BYTES(128));
+ r = memcmp(auth, hash, ecb->ahlen) == 0;
+ memmove(auth, hash, ecb->ahlen);
+ return r;
+}
+
+static void
+shaahinit(Espcb *ecb, char *name, uchar *key, unsigned klen)
+{
+ if(klen != 128)
+ panic("shaahinit: bad keylen");
+ klen /= BI2BY;
+
+ ecb->ahalg = name;
+ ecb->ahblklen = 1;
+ ecb->ahlen = BITS2BYTES(96);
+ ecb->auth = shaauth;
+ ecb->ahstate = smalloc(klen);
+ memmove(ecb->ahstate, key, klen);
+}
+
+
+/*
+ * aes
+ */
+
+/* ah_aes_xcbc_mac_96, rfc3566 */
+static int
+aesahauth(Espcb *ecb, uchar *t, int tlen, uchar *auth)
+{
+ int r;
+ uchar hash[AESdlen];
+
+ memset(hash, 0, AESdlen);
+ ecb->ds = hmac_aes(t, tlen, (uchar*)ecb->ahstate, BITS2BYTES(96), hash,
+ ecb->ds);
+ r = memcmp(auth, hash, ecb->ahlen) == 0;
+ memmove(auth, hash, ecb->ahlen);
+ return r;
+}
+
+static void
+aesahinit(Espcb *ecb, char *name, uchar *key, unsigned klen)
+{
+ if(klen != 128)
+ panic("aesahinit: keylen not 128");
+ klen /= BI2BY;
+
+ ecb->ahalg = name;
+ ecb->ahblklen = 1;
+ ecb->ahlen = BITS2BYTES(96);
+ ecb->auth = aesahauth;
+ ecb->ahstate = smalloc(klen);
+ memmove(ecb->ahstate, key, klen);
+}
+
+static int
+aescbccipher(Espcb *ecb, uchar *p, int n) /* 128-bit blocks */
+{
+ uchar tmp[AESbsize], q[AESbsize];
+ uchar *pp, *tp, *ip, *eip, *ep;
+ AESstate *ds = ecb->espstate;
+
+ ep = p + n;
+ if(ecb->incoming) {
+ memmove(ds->ivec, p, AESbsize);
+ p += AESbsize;
+ while(p < ep){
+ memmove(tmp, p, AESbsize);
+ aes_decrypt(ds->dkey, ds->rounds, p, q);
+ memmove(p, q, AESbsize);
+ tp = tmp;
+ ip = ds->ivec;
+ for(eip = ip + AESbsize; ip < eip; ){
+ *p++ ^= *ip;
+ *ip++ = *tp++;
+ }
+ }
+ } else {
+ memmove(p, ds->ivec, AESbsize);
+ for(p += AESbsize; p < ep; p += AESbsize){
+ pp = p;
+ ip = ds->ivec;
+ for(eip = ip + AESbsize; ip < eip; )
+ *pp++ ^= *ip++;
+ aes_encrypt(ds->ekey, ds->rounds, p, q);
+ memmove(ds->ivec, q, AESbsize);
+ memmove(p, q, AESbsize);
+ }
+ }
+ return 1;
+}
+
+static void
+aescbcespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
+{
+ uchar key[Aeskeysz], ivec[Aeskeysz];
+ int i;
+
+ n = BITS2BYTES(n);
+ if(n > Aeskeysz)
+ n = Aeskeysz;
+ memset(key, 0, sizeof(key));
+ memmove(key, k, n);
+ for(i = 0; i < Aeskeysz; i++)
+ ivec[i] = nrand(256);
+ ecb->espalg = name;
+ ecb->espblklen = Aesblk;
+ ecb->espivlen = Aesblk;
+ ecb->cipher = aescbccipher;
+ ecb->espstate = smalloc(sizeof(AESstate));
+ setupAESstate(ecb->espstate, key, n /* keybytes */, ivec);
+}
+
+static int
+aesctrcipher(Espcb *ecb, uchar *p, int n) /* 128-bit blocks */
+{
+ uchar tmp[AESbsize], q[AESbsize];
+ uchar *pp, *tp, *ip, *eip, *ep;
+ AESstate *ds = ecb->espstate;
+
+ ep = p + n;
+ if(ecb->incoming) {
+ memmove(ds->ivec, p, AESbsize);
+ p += AESbsize;
+ while(p < ep){
+ memmove(tmp, p, AESbsize);
+ aes_decrypt(ds->dkey, ds->rounds, p, q);
+ memmove(p, q, AESbsize);
+ tp = tmp;
+ ip = ds->ivec;
+ for(eip = ip + AESbsize; ip < eip; ){
+ *p++ ^= *ip;
+ *ip++ = *tp++;
+ }
+ }
+ } else {
+ memmove(p, ds->ivec, AESbsize);
+ for(p += AESbsize; p < ep; p += AESbsize){
+ pp = p;
+ ip = ds->ivec;
+ for(eip = ip + AESbsize; ip < eip; )
+ *pp++ ^= *ip++;
+ aes_encrypt(ds->ekey, ds->rounds, p, q);
+ memmove(ds->ivec, q, AESbsize);
+ memmove(p, q, AESbsize);
+ }
+ }
+ return 1;
+}
+
+static void
+aesctrespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
+{
+ uchar key[Aesblk], ivec[Aesblk];
+ int i;
+
+ n = BITS2BYTES(n);
+ if(n > Aeskeysz)
+ n = Aeskeysz;
+ memset(key, 0, sizeof(key));
+ memmove(key, k, n);
+ for(i = 0; i < Aesblk; i++)
+ ivec[i] = nrand(256);
+ ecb->espalg = name;
+ ecb->espblklen = Aesblk;
+ ecb->espivlen = Aesblk;
+ ecb->cipher = aesctrcipher;
+ ecb->espstate = smalloc(sizeof(AESstate));
+ setupAESstate(ecb->espstate, key, n /* keybytes */, ivec);
+}
+
+
+/*
+ * md5
+ */
+
+static void
+seanq_hmac_md5(uchar hash[MD5dlen], uchar *t, long tlen, uchar *key, long klen)
+{
+ int i;
+ uchar ipad[Hmacblksz+1], opad[Hmacblksz+1], innerhash[MD5dlen];
+ DigestState *digest;
+
+ memset(ipad, 0x36, Hmacblksz);
+ memset(opad, 0x5c, Hmacblksz);
+ ipad[Hmacblksz] = opad[Hmacblksz] = 0;
+ for(i = 0; i < klen; i++){
+ ipad[i] ^= key[i];
+ opad[i] ^= key[i];
+ }
+ digest = md5(ipad, Hmacblksz, nil, nil);
+ md5(t, tlen, innerhash, digest);
+ digest = md5(opad, Hmacblksz, nil, nil);
+ md5(innerhash, MD5dlen, hash, digest);
+}
+
+static int
+md5auth(Espcb *ecb, uchar *t, int tlen, uchar *auth)
+{
+ uchar hash[MD5dlen];
+ int r;
+
+ memset(hash, 0, MD5dlen);
+ seanq_hmac_md5(hash, t, tlen, (uchar*)ecb->ahstate, BITS2BYTES(128));
+ r = memcmp(auth, hash, ecb->ahlen) == 0;
+ memmove(auth, hash, ecb->ahlen);
+ return r;
+}
+
+static void
+md5ahinit(Espcb *ecb, char *name, uchar *key, unsigned klen)
+{
+ if(klen != 128)
+ panic("md5ahinit: bad keylen");
+ klen = BITS2BYTES(klen);
+ ecb->ahalg = name;
+ ecb->ahblklen = 1;
+ ecb->ahlen = BITS2BYTES(96);
+ ecb->auth = md5auth;
+ ecb->ahstate = smalloc(klen);
+ memmove(ecb->ahstate, key, klen);
+}
+
+
+/*
+ * des, single and triple
+ */
+
+static int
+descipher(Espcb *ecb, uchar *p, int n)
+{
+ DESstate *ds = ecb->espstate;
+
+ if(ecb->incoming) {
+ memmove(ds->ivec, p, Desblk);
+ desCBCdecrypt(p + Desblk, n - Desblk, ds);
+ } else {
+ memmove(p, ds->ivec, Desblk);
+ desCBCencrypt(p + Desblk, n - Desblk, ds);
+ }
+ return 1;
+}
+
+static int
+des3cipher(Espcb *ecb, uchar *p, int n)
+{
+ DES3state *ds = ecb->espstate;
+
+ if(ecb->incoming) {
+ memmove(ds->ivec, p, Desblk);
+ des3CBCdecrypt(p + Desblk, n - Desblk, ds);
+ } else {
+ memmove(p, ds->ivec, Desblk);
+ des3CBCencrypt(p + Desblk, n - Desblk, ds);
+ }
+ return 1;
+}
+
+static void
+desespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
+{
+ uchar key[Desblk], ivec[Desblk];
+ int i;
+
+ n = BITS2BYTES(n);
+ if(n > Desblk)
+ n = Desblk;
+ memset(key, 0, sizeof(key));
+ memmove(key, k, n);
+ for(i = 0; i < Desblk; i++)
+ ivec[i] = nrand(256);
+ ecb->espalg = name;
+ ecb->espblklen = Desblk;
+ ecb->espivlen = Desblk;
+
+ ecb->cipher = descipher;
+ ecb->espstate = smalloc(sizeof(DESstate));
+ setupDESstate(ecb->espstate, key, ivec);
+}
+
+static void
+des3espinit(Espcb *ecb, char *name, uchar *k, unsigned n)
+{
+ uchar key[3][Desblk], ivec[Desblk];
+ int i;
+
+ n = BITS2BYTES(n);
+ if(n > Des3keysz)
+ n = Des3keysz;
+ memset(key, 0, sizeof(key));
+ memmove(key, k, n);
+ for(i = 0; i < Desblk; i++)
+ ivec[i] = nrand(256);
+ ecb->espalg = name;
+ ecb->espblklen = Desblk;
+ ecb->espivlen = Desblk;
+
+ ecb->cipher = des3cipher;
+ ecb->espstate = smalloc(sizeof(DES3state));
+ setupDES3state(ecb->espstate, key, ivec);
+}
+
+
+/*
+ * interfacing to devip
+ */
+void
+espinit(Fs *fs)
+{
+ Proto *esp;
+
+ esp = smalloc(sizeof(Proto));
+ esp->priv = smalloc(sizeof(Esppriv));
+ esp->name = "esp";
+ esp->connect = espconnect;
+ esp->announce = nil;
+ esp->ctl = espctl;
+ esp->state = espstate;
+ esp->create = espcreate;
+ esp->close = espclose;
+ esp->rcv = espiput;
+ esp->advise = espadvise;
+ esp->stats = espstats;
+ esp->local = esplocal;
+ esp->remote = espremote;
+ esp->ipproto = IP_ESPPROTO;
+ esp->nc = Nchans;
+ esp->ptclsize = sizeof(Espcb);
+
+ Fsproto(fs, esp);
+}
diff --git a/sys/src/9/ip/ethermedium.c b/sys/src/9/ip/ethermedium.c
new file mode 100755
index 000000000..1aab2b9ec
--- /dev/null
+++ b/sys/src/9/ip/ethermedium.c
@@ -0,0 +1,765 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "../port/netif.h"
+#include "ip.h"
+#include "ipv6.h"
+
+typedef struct Etherhdr Etherhdr;
+struct Etherhdr
+{
+ uchar d[6];
+ uchar s[6];
+ uchar t[2];
+};
+
+static uchar ipbroadcast[IPaddrlen] = {
+ 0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,
+};
+
+static uchar etherbroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+static void etherread4(void *a);
+static void etherread6(void *a);
+static void etherbind(Ipifc *ifc, int argc, char **argv);
+static void etherunbind(Ipifc *ifc);
+static void etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);
+static void etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia);
+static void etherremmulti(Ipifc *ifc, uchar *a, uchar *ia);
+static Block* multicastarp(Fs *f, Arpent *a, Medium*, uchar *mac);
+static void sendarp(Ipifc *ifc, Arpent *a);
+static void sendgarp(Ipifc *ifc, uchar*);
+static int multicastea(uchar *ea, uchar *ip);
+static void recvarpproc(void*);
+static void resolveaddr6(Ipifc *ifc, Arpent *a);
+static void etherpref2addr(uchar *pref, uchar *ea);
+
+Medium ethermedium =
+{
+.name= "ether",
+.hsize= 14,
+.mintu= 60,
+.maxtu= 1514,
+.maclen= 6,
+.bind= etherbind,
+.unbind= etherunbind,
+.bwrite= etherbwrite,
+.addmulti= etheraddmulti,
+.remmulti= etherremmulti,
+.ares= arpenter,
+.areg= sendgarp,
+.pref2addr= etherpref2addr,
+};
+
+Medium gbemedium =
+{
+.name= "gbe",
+.hsize= 14,
+.mintu= 60,
+.maxtu= 9014,
+.maclen= 6,
+.bind= etherbind,
+.unbind= etherunbind,
+.bwrite= etherbwrite,
+.addmulti= etheraddmulti,
+.remmulti= etherremmulti,
+.ares= arpenter,
+.areg= sendgarp,
+.pref2addr= etherpref2addr,
+};
+
+typedef struct Etherrock Etherrock;
+struct Etherrock
+{
+ Fs *f; /* file system we belong to */
+ Proc *arpp; /* arp process */
+ Proc *read4p; /* reading process (v4)*/
+ Proc *read6p; /* reading process (v6)*/
+ Chan *mchan4; /* Data channel for v4 */
+ Chan *achan; /* Arp channel */
+ Chan *cchan4; /* Control channel for v4 */
+ Chan *mchan6; /* Data channel for v6 */
+ Chan *cchan6; /* Control channel for v6 */
+};
+
+/*
+ * ethernet arp request
+ */
+enum
+{
+ ARPREQUEST = 1,
+ ARPREPLY = 2,
+};
+
+typedef struct Etherarp Etherarp;
+struct Etherarp
+{
+ uchar d[6];
+ uchar s[6];
+ uchar type[2];
+ uchar hrd[2];
+ uchar pro[2];
+ uchar hln;
+ uchar pln;
+ uchar op[2];
+ uchar sha[6];
+ uchar spa[4];
+ uchar tha[6];
+ uchar tpa[4];
+};
+
+static char *nbmsg = "nonblocking";
+
+/*
+ * called to bind an IP ifc to an ethernet device
+ * called with ifc wlock'd
+ */
+static void
+etherbind(Ipifc *ifc, int argc, char **argv)
+{
+ Chan *mchan4, *cchan4, *achan, *mchan6, *cchan6, *schan;
+ char addr[Maxpath]; //char addr[2*KNAMELEN];
+ char dir[Maxpath]; //char dir[2*KNAMELEN];
+ char *buf;
+ int n;
+ char *ptr;
+ Etherrock *er;
+
+ if(argc < 2)
+ error(Ebadarg);
+
+ mchan4 = cchan4 = achan = mchan6 = cchan6 = nil;
+ buf = nil;
+ if(waserror()){
+ if(mchan4 != nil)
+ cclose(mchan4);
+ if(cchan4 != nil)
+ cclose(cchan4);
+ if(achan != nil)
+ cclose(achan);
+ if(mchan6 != nil)
+ cclose(mchan6);
+ if(cchan6 != nil)
+ cclose(cchan6);
+ if(buf != nil)
+ free(buf);
+ nexterror();
+ }
+
+ /*
+ * open ipv4 conversation
+ *
+ * the dial will fail if the type is already open on
+ * this device.
+ */
+ snprint(addr, sizeof(addr), "%s!0x800", argv[2]); /* ETIP4 */
+ mchan4 = chandial(addr, nil, dir, &cchan4);
+
+ /*
+ * make it non-blocking
+ */
+ devtab[cchan4->type]->write(cchan4, nbmsg, strlen(nbmsg), 0);
+
+ /*
+ * get mac address and speed
+ */
+ snprint(addr, sizeof(addr), "%s/stats", argv[2]);
+ buf = smalloc(512);
+ schan = namec(addr, Aopen, OREAD, 0);
+ if(waserror()){
+ cclose(schan);
+ nexterror();
+ }
+ n = devtab[schan->type]->read(schan, buf, 511, 0);
+ cclose(schan);
+ poperror();
+ buf[n] = 0;
+
+ ptr = strstr(buf, "addr: ");
+ if(!ptr)
+ error(Eio);
+ ptr += 6;
+ parsemac(ifc->mac, ptr, 6);
+
+ ptr = strstr(buf, "mbps: ");
+ if(ptr){
+ ptr += 6;
+ ifc->mbps = atoi(ptr);
+ } else
+ ifc->mbps = 100;
+
+ /*
+ * open arp conversation
+ */
+ snprint(addr, sizeof(addr), "%s!0x806", argv[2]); /* ETARP */
+ achan = chandial(addr, nil, nil, nil);
+
+ /*
+ * open ipv6 conversation
+ *
+ * the dial will fail if the type is already open on
+ * this device.
+ */
+ snprint(addr, sizeof(addr), "%s!0x86DD", argv[2]); /* ETIP6 */
+ mchan6 = chandial(addr, nil, dir, &cchan6);
+
+ /*
+ * make it non-blocking
+ */
+ devtab[cchan6->type]->write(cchan6, nbmsg, strlen(nbmsg), 0);
+
+ er = smalloc(sizeof(*er));
+ er->mchan4 = mchan4;
+ er->cchan4 = cchan4;
+ er->achan = achan;
+ er->mchan6 = mchan6;
+ er->cchan6 = cchan6;
+ er->f = ifc->conv->p->f;
+ ifc->arg = er;
+
+ free(buf);
+ poperror();
+
+ kproc("etherread4", etherread4, ifc);
+ kproc("recvarpproc", recvarpproc, ifc);
+ kproc("etherread6", etherread6, ifc);
+}
+
+/*
+ * called with ifc wlock'd
+ */
+static void
+etherunbind(Ipifc *ifc)
+{
+ Etherrock *er = ifc->arg;
+
+ if(er->read4p)
+ postnote(er->read4p, 1, "unbind", 0);
+ if(er->read6p)
+ postnote(er->read6p, 1, "unbind", 0);
+ if(er->arpp)
+ postnote(er->arpp, 1, "unbind", 0);
+
+ /* wait for readers to die */
+ while(er->arpp != 0 || er->read4p != 0 || er->read6p != 0)
+ tsleep(&up->sleep, return0, 0, 300);
+
+ if(er->mchan4 != nil)
+ cclose(er->mchan4);
+ if(er->achan != nil)
+ cclose(er->achan);
+ if(er->cchan4 != nil)
+ cclose(er->cchan4);
+ if(er->mchan6 != nil)
+ cclose(er->mchan6);
+ if(er->cchan6 != nil)
+ cclose(er->cchan6);
+
+ free(er);
+}
+
+/*
+ * called by ipoput with a single block to write with ifc rlock'd
+ */
+static void
+etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip)
+{
+ Etherhdr *eh;
+ Arpent *a;
+ uchar mac[6];
+ Etherrock *er = ifc->arg;
+
+ /* get mac address of destination */
+ a = arpget(er->f->arp, bp, version, ifc, ip, mac);
+ if(a){
+ /* check for broadcast or multicast */
+ bp = multicastarp(er->f, a, ifc->m, mac);
+ if(bp==nil){
+ switch(version){
+ case V4:
+ sendarp(ifc, a);
+ break;
+ case V6:
+ resolveaddr6(ifc, a);
+ break;
+ default:
+ panic("etherbwrite: version %d", version);
+ }
+ return;
+ }
+ }
+
+ /* make it a single block with space for the ether header */
+ bp = padblock(bp, ifc->m->hsize);
+ if(bp->next)
+ bp = concatblock(bp);
+ if(BLEN(bp) < ifc->mintu)
+ bp = adjustblock(bp, ifc->mintu);
+ eh = (Etherhdr*)bp->rp;
+
+ /* copy in mac addresses and ether type */
+ memmove(eh->s, ifc->mac, sizeof(eh->s));
+ memmove(eh->d, mac, sizeof(eh->d));
+
+ switch(version){
+ case V4:
+ eh->t[0] = 0x08;
+ eh->t[1] = 0x00;
+ devtab[er->mchan4->type]->bwrite(er->mchan4, bp, 0);
+ break;
+ case V6:
+ eh->t[0] = 0x86;
+ eh->t[1] = 0xDD;
+ devtab[er->mchan6->type]->bwrite(er->mchan6, bp, 0);
+ break;
+ default:
+ panic("etherbwrite2: version %d", version);
+ }
+ ifc->out++;
+}
+
+
+/*
+ * process to read from the ethernet
+ */
+static void
+etherread4(void *a)
+{
+ Ipifc *ifc;
+ Block *bp;
+ Etherrock *er;
+
+ ifc = a;
+ er = ifc->arg;
+ er->read4p = up; /* hide identity under a rock for unbind */
+ if(waserror()){
+ er->read4p = 0;
+ pexit("hangup", 1);
+ }
+ for(;;){
+ bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxtu, 0);
+ if(!canrlock(ifc)){
+ freeb(bp);
+ continue;
+ }
+ if(waserror()){
+ runlock(ifc);
+ nexterror();
+ }
+ ifc->in++;
+ bp->rp += ifc->m->hsize;
+ if(ifc->lifc == nil)
+ freeb(bp);
+ else
+ ipiput4(er->f, ifc, bp);
+ runlock(ifc);
+ poperror();
+ }
+}
+
+
+/*
+ * process to read from the ethernet, IPv6
+ */
+static void
+etherread6(void *a)
+{
+ Ipifc *ifc;
+ Block *bp;
+ Etherrock *er;
+
+ ifc = a;
+ er = ifc->arg;
+ er->read6p = up; /* hide identity under a rock for unbind */
+ if(waserror()){
+ er->read6p = 0;
+ pexit("hangup", 1);
+ }
+ for(;;){
+ bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxtu, 0);
+ if(!canrlock(ifc)){
+ freeb(bp);
+ continue;
+ }
+ if(waserror()){
+ runlock(ifc);
+ nexterror();
+ }
+ ifc->in++;
+ bp->rp += ifc->m->hsize;
+ if(ifc->lifc == nil)
+ freeb(bp);
+ else
+ ipiput6(er->f, ifc, bp);
+ runlock(ifc);
+ poperror();
+ }
+}
+
+static void
+etheraddmulti(Ipifc *ifc, uchar *a, uchar *)
+{
+ uchar mac[6];
+ char buf[64];
+ Etherrock *er = ifc->arg;
+ int version;
+
+ version = multicastea(mac, a);
+ sprint(buf, "addmulti %E", mac);
+ switch(version){
+ case V4:
+ devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0);
+ break;
+ case V6:
+ devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0);
+ break;
+ default:
+ panic("etheraddmulti: version %d", version);
+ }
+}
+
+static void
+etherremmulti(Ipifc *ifc, uchar *a, uchar *)
+{
+ uchar mac[6];
+ char buf[64];
+ Etherrock *er = ifc->arg;
+ int version;
+
+ version = multicastea(mac, a);
+ sprint(buf, "remmulti %E", mac);
+ switch(version){
+ case V4:
+ devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0);
+ break;
+ case V6:
+ devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0);
+ break;
+ default:
+ panic("etherremmulti: version %d", version);
+ }
+}
+
+/*
+ * send an ethernet arp
+ * (only v4, v6 uses the neighbor discovery, rfc1970)
+ */
+static void
+sendarp(Ipifc *ifc, Arpent *a)
+{
+ int n;
+ Block *bp;
+ Etherarp *e;
+ Etherrock *er = ifc->arg;
+
+ /* don't do anything if it's been less than a second since the last */
+ if(NOW - a->ctime < 1000){
+ arprelease(er->f->arp, a);
+ return;
+ }
+
+ /* remove all but the last message */
+ while((bp = a->hold) != nil){
+ if(bp == a->last)
+ break;
+ a->hold = bp->list;
+ freeblist(bp);
+ }
+
+ /* try to keep it around for a second more */
+ a->ctime = NOW;
+ arprelease(er->f->arp, a);
+
+ n = sizeof(Etherarp);
+ if(n < a->type->mintu)
+ n = a->type->mintu;
+ bp = allocb(n);
+ memset(bp->rp, 0, n);
+ e = (Etherarp*)bp->rp;
+ memmove(e->tpa, a->ip+IPv4off, sizeof(e->tpa));
+ ipv4local(ifc, e->spa);
+ memmove(e->sha, ifc->mac, sizeof(e->sha));
+ memset(e->d, 0xff, sizeof(e->d)); /* ethernet broadcast */
+ memmove(e->s, ifc->mac, sizeof(e->s));
+
+ hnputs(e->type, ETARP);
+ hnputs(e->hrd, 1);
+ hnputs(e->pro, ETIP4);
+ e->hln = sizeof(e->sha);
+ e->pln = sizeof(e->spa);
+ hnputs(e->op, ARPREQUEST);
+ bp->wp += n;
+
+ devtab[er->achan->type]->bwrite(er->achan, bp, 0);
+}
+
+static void
+resolveaddr6(Ipifc *ifc, Arpent *a)
+{
+ int sflag;
+ Block *bp;
+ Etherrock *er = ifc->arg;
+ uchar ipsrc[IPaddrlen];
+
+ /* don't do anything if it's been less than a second since the last */
+ if(NOW - a->ctime < ReTransTimer){
+ arprelease(er->f->arp, a);
+ return;
+ }
+
+ /* remove all but the last message */
+ while((bp = a->hold) != nil){
+ if(bp == a->last)
+ break;
+ a->hold = bp->list;
+ freeblist(bp);
+ }
+
+ /* try to keep it around for a second more */
+ a->ctime = NOW;
+ a->rtime = NOW + ReTransTimer;
+ if(a->rxtsrem <= 0) {
+ arprelease(er->f->arp, a);
+ return;
+ }
+
+ a->rxtsrem--;
+ arprelease(er->f->arp, a);
+
+ if(sflag = ipv6anylocal(ifc, ipsrc))
+ icmpns(er->f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac);
+}
+
+/*
+ * send a gratuitous arp to refresh arp caches
+ */
+static void
+sendgarp(Ipifc *ifc, uchar *ip)
+{
+ int n;
+ Block *bp;
+ Etherarp *e;
+ Etherrock *er = ifc->arg;
+
+ /* don't arp for our initial non address */
+ if(ipcmp(ip, IPnoaddr) == 0)
+ return;
+
+ n = sizeof(Etherarp);
+ if(n < ifc->m->mintu)
+ n = ifc->m->mintu;
+ bp = allocb(n);
+ memset(bp->rp, 0, n);
+ e = (Etherarp*)bp->rp;
+ memmove(e->tpa, ip+IPv4off, sizeof(e->tpa));
+ memmove(e->spa, ip+IPv4off, sizeof(e->spa));
+ memmove(e->sha, ifc->mac, sizeof(e->sha));
+ memset(e->d, 0xff, sizeof(e->d)); /* ethernet broadcast */
+ memmove(e->s, ifc->mac, sizeof(e->s));
+
+ hnputs(e->type, ETARP);
+ hnputs(e->hrd, 1);
+ hnputs(e->pro, ETIP4);
+ e->hln = sizeof(e->sha);
+ e->pln = sizeof(e->spa);
+ hnputs(e->op, ARPREQUEST);
+ bp->wp += n;
+
+ devtab[er->achan->type]->bwrite(er->achan, bp, 0);
+}
+
+static void
+recvarp(Ipifc *ifc)
+{
+ int n;
+ Block *ebp, *rbp;
+ Etherarp *e, *r;
+ uchar ip[IPaddrlen];
+ static uchar eprinted[4];
+ Etherrock *er = ifc->arg;
+
+ ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxtu, 0);
+ if(ebp == nil)
+ return;
+
+ e = (Etherarp*)ebp->rp;
+ switch(nhgets(e->op)) {
+ default:
+ break;
+
+ case ARPREPLY:
+ /* check for machine using my ip address */
+ v4tov6(ip, e->spa);
+ if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){
+ if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){
+ print("arprep: 0x%E/0x%E also has ip addr %V\n",
+ e->s, e->sha, e->spa);
+ break;
+ }
+ }
+
+ /* make sure we're not entering broadcast addresses */
+ if(ipcmp(ip, ipbroadcast) == 0 ||
+ !memcmp(e->sha, etherbroadcast, sizeof(e->sha))){
+ print("arprep: 0x%E/0x%E cannot register broadcast address %I\n",
+ e->s, e->sha, e->spa);
+ break;
+ }
+
+ arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 0);
+ break;
+
+ case ARPREQUEST:
+ /* don't answer arps till we know who we are */
+ if(ifc->lifc == 0)
+ break;
+
+ /* check for machine using my ip or ether address */
+ v4tov6(ip, e->spa);
+ if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){
+ if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){
+ if (memcmp(eprinted, e->spa, sizeof(e->spa))){
+ /* print only once */
+ print("arpreq: 0x%E also has ip addr %V\n", e->sha, e->spa);
+ memmove(eprinted, e->spa, sizeof(e->spa));
+ }
+ }
+ } else {
+ if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) == 0){
+ print("arpreq: %V also has ether addr %E\n", e->spa, e->sha);
+ break;
+ }
+ }
+
+ /* refresh what we know about sender */
+ arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 1);
+
+ /* answer only requests for our address or systems we're proxying for */
+ v4tov6(ip, e->tpa);
+ if(!iplocalonifc(ifc, ip))
+ if(!ipproxyifc(er->f, ifc, ip))
+ break;
+
+ n = sizeof(Etherarp);
+ if(n < ifc->mintu)
+ n = ifc->mintu;
+ rbp = allocb(n);
+ r = (Etherarp*)rbp->rp;
+ memset(r, 0, sizeof(Etherarp));
+ hnputs(r->type, ETARP);
+ hnputs(r->hrd, 1);
+ hnputs(r->pro, ETIP4);
+ r->hln = sizeof(r->sha);
+ r->pln = sizeof(r->spa);
+ hnputs(r->op, ARPREPLY);
+ memmove(r->tha, e->sha, sizeof(r->tha));
+ memmove(r->tpa, e->spa, sizeof(r->tpa));
+ memmove(r->sha, ifc->mac, sizeof(r->sha));
+ memmove(r->spa, e->tpa, sizeof(r->spa));
+ memmove(r->d, e->sha, sizeof(r->d));
+ memmove(r->s, ifc->mac, sizeof(r->s));
+ rbp->wp += n;
+
+ devtab[er->achan->type]->bwrite(er->achan, rbp, 0);
+ }
+ freeb(ebp);
+}
+
+static void
+recvarpproc(void *v)
+{
+ Ipifc *ifc = v;
+ Etherrock *er = ifc->arg;
+
+ er->arpp = up;
+ if(waserror()){
+ er->arpp = 0;
+ pexit("hangup", 1);
+ }
+ for(;;)
+ recvarp(ifc);
+}
+
+static int
+multicastea(uchar *ea, uchar *ip)
+{
+ int x;
+
+ switch(x = ipismulticast(ip)){
+ case V4:
+ ea[0] = 0x01;
+ ea[1] = 0x00;
+ ea[2] = 0x5e;
+ ea[3] = ip[13] & 0x7f;
+ ea[4] = ip[14];
+ ea[5] = ip[15];
+ break;
+ case V6:
+ ea[0] = 0x33;
+ ea[1] = 0x33;
+ ea[2] = ip[12];
+ ea[3] = ip[13];
+ ea[4] = ip[14];
+ ea[5] = ip[15];
+ break;
+ }
+ return x;
+}
+
+/*
+ * fill in an arp entry for broadcast or multicast
+ * addresses. Return the first queued packet for the
+ * IP address.
+ */
+static Block*
+multicastarp(Fs *f, Arpent *a, Medium *medium, uchar *mac)
+{
+ /* is it broadcast? */
+ switch(ipforme(f, a->ip)){
+ case Runi:
+ return nil;
+ case Rbcast:
+ memset(mac, 0xff, 6);
+ return arpresolve(f->arp, a, medium, mac);
+ default:
+ break;
+ }
+
+ /* if multicast, fill in mac */
+ switch(multicastea(mac, a->ip)){
+ case V4:
+ case V6:
+ return arpresolve(f->arp, a, medium, mac);
+ }
+
+ /* let arp take care of it */
+ return nil;
+}
+
+void
+ethermediumlink(void)
+{
+ addipmedium(&ethermedium);
+ addipmedium(&gbemedium);
+}
+
+
+static void
+etherpref2addr(uchar *pref, uchar *ea)
+{
+ pref[8] = ea[0] | 0x2;
+ pref[9] = ea[1];
+ pref[10] = ea[2];
+ pref[11] = 0xFF;
+ pref[12] = 0xFE;
+ pref[13] = ea[3];
+ pref[14] = ea[4];
+ pref[15] = ea[5];
+}
diff --git a/sys/src/9/ip/gre.c b/sys/src/9/ip/gre.c
new file mode 100755
index 000000000..b7982dc33
--- /dev/null
+++ b/sys/src/9/ip/gre.c
@@ -0,0 +1,971 @@
+/*
+ * Generic Routing Encapsulation over IPv4, rfc1702
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+
+enum {
+ GRE_IPONLY = 12, /* size of ip header */
+ GRE_IPPLUSGRE = 12, /* minimum size of GRE header */
+ IP_GREPROTO = 47,
+
+ GRErxms = 200,
+ GREtickms = 100,
+ GREmaxxmit = 10,
+
+ K = 1024,
+ GREqlen = 256 * K,
+
+ GRE_cksum = 0x8000,
+ GRE_routing = 0x4000,
+ GRE_key = 0x2000,
+ GRE_seq = 0x1000,
+
+ Nring = 1 << 10, /* power of two, please */
+ Ringmask = Nring - 1,
+
+ GREctlraw = 0,
+ GREctlcooked,
+ GREctlretunnel,
+ GREctlreport,
+ GREctldlsuspend,
+ GREctlulsuspend,
+ GREctldlresume,
+ GREctlulresume,
+ GREctlforward,
+ GREctlulkey,
+ Ncmds,
+};
+
+typedef struct GREhdr GREhdr;
+struct GREhdr{
+ /* ip header */
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar len[2]; /* packet length (including headers) */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+ uchar ttl;
+ uchar proto; /* Protocol */
+ uchar cksum[2]; /* checksum */
+ uchar src[4]; /* Ip source */
+ uchar dst[4]; /* Ip destination */
+
+ /* gre header */
+ uchar flags[2];
+ uchar eproto[2]; /* encapsulation protocol */
+};
+
+typedef struct GREpriv GREpriv;
+struct GREpriv{
+ /* non-MIB stats */
+ ulong lenerr; /* short packet */
+};
+
+typedef struct Bring Bring;
+struct Bring{
+ Block *ring[Nring];
+ long produced;
+ long consumed;
+};
+
+typedef struct GREconv GREconv;
+struct GREconv{
+ int raw;
+
+ /* Retunnelling information. v4 only */
+ uchar north[4]; /* HA */
+ uchar south[4]; /* Base station */
+ uchar hoa[4]; /* Home address */
+ uchar coa[4]; /* Careof address */
+ ulong seq; /* Current sequence # */
+ int dlsusp; /* Downlink suspended? */
+ int ulsusp; /* Uplink suspended? */
+ ulong ulkey; /* GRE key */
+
+ QLock lock; /* Lock for rings */
+ Bring dlpending; /* Ring of pending packets */
+ Bring dlbuffered; /* Received while suspended */
+ Bring ulbuffered; /* Received while suspended */
+};
+
+typedef struct Metablock Metablock;
+struct Metablock{
+ uchar *rp;
+ ulong seq;
+};
+
+static char *grectlcooked(Conv *, int, char **);
+static char *grectldlresume(Conv *, int, char **);
+static char *grectldlsuspend(Conv *, int, char **);
+static char *grectlforward(Conv *, int, char **);
+static char *grectlraw(Conv *, int, char **);
+static char *grectlreport(Conv *, int, char **);
+static char *grectlretunnel(Conv *, int, char **);
+static char *grectlulkey(Conv *, int, char **);
+static char *grectlulresume(Conv *, int, char **);
+static char *grectlulsuspend(Conv *, int, char **);
+
+static struct{
+ char *cmd;
+ int argc;
+ char *(*f)(Conv *, int, char **);
+} grectls[Ncmds] = {
+[GREctlraw] = { "raw", 1, grectlraw, },
+[GREctlcooked] = { "cooked", 1, grectlcooked, },
+[GREctlretunnel]= { "retunnel", 5, grectlretunnel, },
+[GREctlreport] = { "report", 2, grectlreport, },
+[GREctldlsuspend]= { "dlsuspend", 1, grectldlsuspend,},
+[GREctlulsuspend]= { "ulsuspend", 1, grectlulsuspend,},
+[GREctldlresume]= { "dlresume", 1, grectldlresume, },
+[GREctlulresume]= { "ulresume", 1, grectlulresume, },
+[GREctlforward] = { "forward", 2, grectlforward, },
+[GREctlulkey] = { "ulkey", 2, grectlulkey, },
+};
+
+static uchar nulladdr[4];
+static char *sessend = "session end";
+
+static void grekick(void *x, Block *bp);
+static char *gresetup(Conv *, char *, char *, char *);
+
+ulong grepdin, grepdout, grebdin, grebdout;
+ulong grepuin, grepuout, grebuin, grebuout;
+
+static Block *
+getring(Bring *r)
+{
+ Block *bp;
+
+ if(r->consumed == r->produced)
+ return nil;
+
+ bp = r->ring[r->consumed & Ringmask];
+ r->ring[r->consumed & Ringmask] = nil;
+ r->consumed++;
+ return bp;
+}
+
+static void
+addring(Bring *r, Block *bp)
+{
+ Block *tbp;
+
+ if(r->produced - r->consumed > Ringmask){
+ /* Full! */
+ tbp = r->ring[r->produced & Ringmask];
+ assert(tbp);
+ freeb(tbp);
+ r->consumed++;
+ }
+ r->ring[r->produced & Ringmask] = bp;
+ r->produced++;
+}
+
+static char *
+greconnect(Conv *c, char **argv, int argc)
+{
+ Proto *p;
+ char *err;
+ Conv *tc, **cp, **ecp;
+
+ err = Fsstdconnect(c, argv, argc);
+ if(err != nil)
+ return err;
+
+ /* make sure noone's already connected to this other sys */
+ p = c->p;
+ qlock(p);
+ ecp = &p->conv[p->nc];
+ for(cp = p->conv; cp < ecp; cp++){
+ tc = *cp;
+ if(tc == nil)
+ break;
+ if(tc == c)
+ continue;
+ if(tc->rport == c->rport && ipcmp(tc->raddr, c->raddr) == 0){
+ err = "already connected to that addr/proto";
+ ipmove(c->laddr, IPnoaddr);
+ ipmove(c->raddr, IPnoaddr);
+ break;
+ }
+ }
+ qunlock(p);
+
+ if(err != nil)
+ return err;
+ Fsconnected(c, nil);
+
+ return nil;
+}
+
+static void
+grecreate(Conv *c)
+{
+ c->rq = qopen(GREqlen, Qmsg, 0, c);
+ c->wq = qbypass(grekick, c);
+}
+
+static int
+grestate(Conv *c, char *state, int n)
+{
+ GREconv *grec;
+ char *ep, *p;
+
+ grec = c->ptcl;
+ p = state;
+ ep = p + n;
+ p = seprint(p, ep, "%s%s%s%shoa %V north %V south %V seq %ulx "
+ "pending %uld %uld buffered dl %uld %uld ul %uld %uld ulkey %.8ulx\n",
+ c->inuse? "Open ": "Closed ",
+ grec->raw? "raw ": "",
+ grec->dlsusp? "DL suspended ": "",
+ grec->ulsusp? "UL suspended ": "",
+ grec->hoa, grec->north, grec->south, grec->seq,
+ grec->dlpending.consumed, grec->dlpending.produced,
+ grec->dlbuffered.consumed, grec->dlbuffered.produced,
+ grec->ulbuffered.consumed, grec->ulbuffered.produced,
+ grec->ulkey);
+ return p - state;
+}
+
+static char*
+greannounce(Conv*, char**, int)
+{
+ return "gre does not support announce";
+}
+
+static void
+greclose(Conv *c)
+{
+ GREconv *grec;
+ Block *bp;
+
+ grec = c->ptcl;
+
+ /* Make sure we don't forward any more packets */
+ memset(grec->hoa, 0, sizeof grec->hoa);
+ memset(grec->north, 0, sizeof grec->north);
+ memset(grec->south, 0, sizeof grec->south);
+
+ qlock(&grec->lock);
+ while((bp = getring(&grec->dlpending)) != nil)
+ freeb(bp);
+
+ while((bp = getring(&grec->dlbuffered)) != nil)
+ freeb(bp);
+
+ while((bp = getring(&grec->ulbuffered)) != nil)
+ freeb(bp);
+
+ grec->dlpending.produced = grec->dlpending.consumed = 0;
+ grec->dlbuffered.produced = grec->dlbuffered.consumed = 0;
+ grec->ulbuffered.produced = grec->ulbuffered.consumed = 0;
+ qunlock(&grec->lock);
+
+ grec->raw = 0;
+ grec->seq = 0;
+ grec->dlsusp = grec->ulsusp = 1;
+
+ qhangup(c->rq, sessend);
+ qhangup(c->wq, sessend);
+ qhangup(c->eq, sessend);
+ ipmove(c->laddr, IPnoaddr);
+ ipmove(c->raddr, IPnoaddr);
+ c->lport = c->rport = 0;
+}
+
+static void
+grekick(void *x, Block *bp)
+{
+ Conv *c;
+ GREconv *grec;
+ GREhdr *gre;
+ uchar laddr[IPaddrlen], raddr[IPaddrlen];
+
+ if(bp == nil)
+ return;
+
+ c = x;
+ grec = c->ptcl;
+
+ /* Make space to fit ip header (gre header already there) */
+ bp = padblock(bp, GRE_IPONLY);
+ if(bp == nil)
+ return;
+
+ /* make sure the message has a GRE header */
+ bp = pullupblock(bp, GRE_IPONLY+GRE_IPPLUSGRE);
+ if(bp == nil)
+ return;
+
+ gre = (GREhdr *)bp->rp;
+ gre->vihl = IP_VER4;
+
+ if(grec->raw == 0){
+ v4tov6(raddr, gre->dst);
+ if(ipcmp(raddr, v4prefix) == 0)
+ memmove(gre->dst, c->raddr + IPv4off, IPv4addrlen);
+ v4tov6(laddr, gre->src);
+ if(ipcmp(laddr, v4prefix) == 0){
+ if(ipcmp(c->laddr, IPnoaddr) == 0)
+ /* pick interface closest to dest */
+ findlocalip(c->p->f, c->laddr, raddr);
+ memmove(gre->src, c->laddr + IPv4off, sizeof gre->src);
+ }
+ hnputs(gre->eproto, c->rport);
+ }
+
+ gre->proto = IP_GREPROTO;
+ gre->frag[0] = gre->frag[1] = 0;
+
+ grepdout++;
+ grebdout += BLEN(bp);
+ ipoput4(c->p->f, bp, 0, c->ttl, c->tos, nil);
+}
+
+static void
+gredownlink(Conv *c, Block *bp)
+{
+ Metablock *m;
+ GREconv *grec;
+ GREhdr *gre;
+ int hdrlen, suspended, extra;
+ ushort flags;
+ ulong seq;
+
+ gre = (GREhdr *)bp->rp;
+ if(gre->ttl == 1){
+ freeb(bp);
+ return;
+ }
+
+ /*
+ * We've received a packet with a GRE header and we need to
+ * re-adjust the packet header to strip all unwanted parts
+ * but leave room for only a sequence number.
+ */
+ grec = c->ptcl;
+ flags = nhgets(gre->flags);
+ hdrlen = 0;
+ if(flags & GRE_cksum)
+ hdrlen += 2;
+ if(flags & GRE_routing){
+ print("%V routing info present. Discarding packet", gre->src);
+ freeb(bp);
+ return;
+ }
+ if(flags & (GRE_cksum|GRE_routing))
+ hdrlen += 2; /* Offset field */
+ if(flags & GRE_key)
+ hdrlen += 4;
+ if(flags & GRE_seq)
+ hdrlen += 4;
+
+ /*
+ * The outgoing packet only has the sequence number set. Make room
+ * for the sequence number.
+ */
+ if(hdrlen != sizeof(ulong)){
+ extra = hdrlen - sizeof(ulong);
+ if(extra < 0 && bp->rp - bp->base < -extra){
+ print("gredownlink: cannot add sequence number\n");
+ freeb(bp);
+ return;
+ }
+ memmove(bp->rp + extra, bp->rp, sizeof(GREhdr));
+ bp->rp += extra;
+ assert(BLEN(bp) >= sizeof(GREhdr) + sizeof(ulong));
+ gre = (GREhdr *)bp->rp;
+ }
+ seq = grec->seq++;
+ hnputs(gre->flags, GRE_seq);
+ hnputl(bp->rp + sizeof(GREhdr), seq);
+
+ /*
+ * Keep rp and seq at the base. ipoput4 consumes rp for
+ * refragmentation.
+ */
+ assert(bp->rp - bp->base >= sizeof(Metablock));
+ m = (Metablock *)bp->base;
+ m->rp = bp->rp;
+ m->seq = seq;
+
+ /*
+ * Here we make a decision what we're doing with the packet. We're
+ * doing this w/o holding a lock which means that later on in the
+ * process we may discover we've done the wrong thing. I don't want
+ * to call ipoput with the lock held.
+ */
+restart:
+ suspended = grec->dlsusp;
+ if(suspended){
+ if(!canqlock(&grec->lock)){
+ /*
+ * just give up. too bad, we lose a packet. this
+ * is just too hard and my brain already hurts.
+ */
+ freeb(bp);
+ return;
+ }
+
+ if(!grec->dlsusp){
+ /*
+ * suspend race. We though we were suspended, but
+ * we really weren't.
+ */
+ qunlock(&grec->lock);
+ goto restart;
+ }
+
+ /* Undo the incorrect ref count addition */
+ addring(&grec->dlbuffered, bp);
+ qunlock(&grec->lock);
+ return;
+ }
+
+ /*
+ * When we get here, we're not suspended. Proceed to send the
+ * packet.
+ */
+ memmove(gre->src, grec->coa, sizeof gre->dst);
+ memmove(gre->dst, grec->south, sizeof gre->dst);
+
+ /*
+ * Make sure the packet does not go away.
+ */
+ _xinc(&bp->ref);
+ assert(bp->ref == 2);
+
+ ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
+ grepdout++;
+ grebdout += BLEN(bp);
+
+ /*
+ * Now make sure we didn't do the wrong thing.
+ */
+ if(!canqlock(&grec->lock)){
+ freeb(bp); /* The packet just goes away */
+ return;
+ }
+
+ /* We did the right thing */
+ addring(&grec->dlpending, bp);
+ qunlock(&grec->lock);
+}
+
+static void
+greuplink(Conv *c, Block *bp)
+{
+ GREconv *grec;
+ GREhdr *gre;
+ ushort flags;
+
+ gre = (GREhdr *)bp->rp;
+ if(gre->ttl == 1)
+ return;
+
+ grec = c->ptcl;
+ memmove(gre->src, grec->coa, sizeof gre->src);
+ memmove(gre->dst, grec->north, sizeof gre->dst);
+
+ /*
+ * Add a key, if needed.
+ */
+ if(grec->ulkey){
+ flags = nhgets(gre->flags);
+ if(flags & (GRE_cksum|GRE_routing)){
+ print("%V routing info present. Discarding packet\n",
+ gre->src);
+ freeb(bp);
+ return;
+ }
+
+ if((flags & GRE_key) == 0){
+ /* Make room for the key */
+ if(bp->rp - bp->base < sizeof(ulong)){
+ print("%V can't add key\n", gre->src);
+ freeb(bp);
+ return;
+ }
+
+ bp->rp -= 4;
+ memmove(bp->rp, bp->rp + 4, sizeof(GREhdr));
+
+ gre = (GREhdr *)bp->rp;
+ hnputs(gre->flags, flags | GRE_key);
+ }
+
+ /* Add the key */
+ hnputl(bp->rp + sizeof(GREhdr), grec->ulkey);
+ }
+
+ if(!canqlock(&grec->lock)){
+ freeb(bp);
+ return;
+ }
+
+ if(grec->ulsusp)
+ addring(&grec->ulbuffered, bp);
+ else{
+ ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
+ grepuout++;
+ grebuout += BLEN(bp);
+ }
+ qunlock(&grec->lock);
+}
+
+static void
+greiput(Proto *proto, Ipifc *, Block *bp)
+{
+ int len, hdrlen;
+ ushort eproto, flags;
+ uchar raddr[IPaddrlen];
+ Conv *c, **p;
+ GREconv *grec;
+ GREhdr *gre;
+ GREpriv *gpriv;
+ Ip4hdr *ip;
+
+ /*
+ * We don't want to deal with block lists. Ever. The problem is
+ * that when the block is forwarded, devether.c puts the block into
+ * a queue that also uses ->next. Just do not use ->next here!
+ */
+ if(bp->next){
+ len = blocklen(bp);
+ bp = pullupblock(bp, len);
+ assert(BLEN(bp) == len && bp->next == nil);
+ }
+
+ gre = (GREhdr *)bp->rp;
+ if(BLEN(bp) < sizeof(GREhdr) || gre->proto != IP_GREPROTO){
+ freeb(bp);
+ return;
+ }
+
+ v4tov6(raddr, gre->src);
+ eproto = nhgets(gre->eproto);
+ flags = nhgets(gre->flags);
+ hdrlen = sizeof(GREhdr);
+
+ if(flags & GRE_cksum)
+ hdrlen += 2;
+ if(flags & GRE_routing){
+ print("%I routing info present. Discarding packet\n", raddr);
+ freeb(bp);
+ return;
+ }
+ if(flags & (GRE_cksum|GRE_routing))
+ hdrlen += 2; /* Offset field */
+ if(flags & GRE_key)
+ hdrlen += 4;
+ if(flags & GRE_seq)
+ hdrlen += 4;
+
+ if(BLEN(bp) - hdrlen < sizeof(Ip4hdr)){
+ print("greretunnel: packet too short (s=%V d=%V)\n",
+ gre->src, gre->dst);
+ freeb(bp);
+ return;
+ }
+ ip = (Ip4hdr *)(bp->rp + hdrlen);
+
+ qlock(proto);
+ /*
+ * Look for a conversation structure for this port and address, or
+ * match the retunnel part, or match on the raw flag.
+ */
+ for(p = proto->conv; *p; p++) {
+ c = *p;
+
+ if(c->inuse == 0)
+ continue;
+
+ /*
+ * Do not stop this session - blocking here
+ * implies that etherread is blocked.
+ */
+ grec = c->ptcl;
+ if(memcmp(ip->dst, grec->hoa, sizeof ip->dst) == 0){
+ grepdin++;
+ grebdin += BLEN(bp);
+ gredownlink(c, bp);
+ qunlock(proto);
+ return;
+ }
+
+ if(memcmp(ip->src, grec->hoa, sizeof ip->src) == 0){
+ grepuin++;
+ grebuin += BLEN(bp);
+ greuplink(c, bp);
+ qunlock(proto);
+ return;
+ }
+ }
+
+ /*
+ * when we get here, none of the forwarding tunnels matched. now
+ * try to match on raw and conversational sessions.
+ */
+ for(c = nil, p = proto->conv; *p; p++) {
+ c = *p;
+
+ if(c->inuse == 0)
+ continue;
+
+ /*
+ * Do not stop this session - blocking here
+ * implies that etherread is blocked.
+ */
+ grec = c->ptcl;
+ if(c->rport == eproto &&
+ (grec->raw || ipcmp(c->raddr, raddr) == 0))
+ break;
+ }
+
+ qunlock(proto);
+
+ if(*p == nil){
+ freeb(bp);
+ return;
+ }
+
+ /*
+ * Trim the packet down to data size
+ */
+ len = nhgets(gre->len) - GRE_IPONLY;
+ if(len < GRE_IPPLUSGRE){
+ freeb(bp);
+ return;
+ }
+
+ bp = trimblock(bp, GRE_IPONLY, len);
+ if(bp == nil){
+ gpriv = proto->priv;
+ gpriv->lenerr++;
+ return;
+ }
+
+ /*
+ * Can't delimit packet so pull it all into one block.
+ */
+ if(qlen(c->rq) > GREqlen)
+ freeb(bp);
+ else{
+ bp = concatblock(bp);
+ if(bp == 0)
+ panic("greiput");
+ qpass(c->rq, bp);
+ }
+}
+
+int
+grestats(Proto *gre, char *buf, int len)
+{
+ GREpriv *gpriv;
+
+ gpriv = gre->priv;
+ return snprint(buf, len,
+ "gre: %lud %lud %lud %lud %lud %lud %lud %lud, lenerrs %lud\n",
+ grepdin, grepdout, grepuin, grepuout,
+ grebdin, grebdout, grebuin, grebuout, gpriv->lenerr);
+}
+
+static char *
+grectlraw(Conv *c, int, char **)
+{
+ GREconv *grec;
+
+ grec = c->ptcl;
+ grec->raw = 1;
+ return nil;
+}
+
+static char *
+grectlcooked(Conv *c, int, char **)
+{
+ GREconv *grec;
+
+ grec = c->ptcl;
+ grec->raw = 0;
+ return nil;
+}
+
+static char *
+grectlretunnel(Conv *c, int, char **argv)
+{
+ GREconv *grec;
+ uchar ipaddr[4];
+
+ grec = c->ptcl;
+ if(memcmp(grec->hoa, nulladdr, sizeof grec->hoa))
+ return "tunnel already set up";
+
+ v4parseip(ipaddr, argv[1]);
+ if(memcmp(ipaddr, nulladdr, sizeof ipaddr) == 0)
+ return "bad hoa";
+ memmove(grec->hoa, ipaddr, sizeof grec->hoa);
+ v4parseip(ipaddr, argv[2]);
+ memmove(grec->north, ipaddr, sizeof grec->north);
+ v4parseip(ipaddr, argv[3]);
+ memmove(grec->south, ipaddr, sizeof grec->south);
+ v4parseip(ipaddr, argv[4]);
+ memmove(grec->coa, ipaddr, sizeof grec->coa);
+ grec->ulsusp = 1;
+ grec->dlsusp = 0;
+
+ return nil;
+}
+
+static char *
+grectlreport(Conv *c, int, char **argv)
+{
+ ulong seq;
+ Block *bp;
+ Bring *r;
+ GREconv *grec;
+ Metablock *m;
+
+ grec = c->ptcl;
+ seq = strtoul(argv[1], nil, 0);
+
+ qlock(&grec->lock);
+ r = &grec->dlpending;
+ while(r->produced - r->consumed > 0){
+ bp = r->ring[r->consumed & Ringmask];
+
+ assert(bp && bp->rp - bp->base >= sizeof(Metablock));
+ m = (Metablock *)bp->base;
+ if((long)(seq - m->seq) <= 0)
+ break;
+
+ r->ring[r->consumed & Ringmask] = nil;
+ r->consumed++;
+
+ freeb(bp);
+ }
+ qunlock(&grec->lock);
+ return nil;
+}
+
+static char *
+grectldlsuspend(Conv *c, int, char **)
+{
+ GREconv *grec;
+
+ grec = c->ptcl;
+ if(grec->dlsusp)
+ return "already suspended";
+
+ grec->dlsusp = 1;
+ return nil;
+}
+
+static char *
+grectlulsuspend(Conv *c, int, char **)
+{
+ GREconv *grec;
+
+ grec = c->ptcl;
+ if(grec->ulsusp)
+ return "already suspended";
+
+ grec->ulsusp = 1;
+ return nil;
+}
+
+static char *
+grectldlresume(Conv *c, int, char **)
+{
+ GREconv *grec;
+ GREhdr *gre;
+ Block *bp;
+
+ grec = c->ptcl;
+
+ qlock(&grec->lock);
+ if(!grec->dlsusp){
+ qunlock(&grec->lock);
+ return "not suspended";
+ }
+
+ while((bp = getring(&grec->dlbuffered)) != nil){
+ gre = (GREhdr *)bp->rp;
+ qunlock(&grec->lock);
+
+ /*
+ * Make sure the packet does not go away.
+ */
+ _xinc(&bp->ref);
+ assert(bp->ref == 2);
+
+ ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
+
+ qlock(&grec->lock);
+ addring(&grec->dlpending, bp);
+ }
+ grec->dlsusp = 0;
+ qunlock(&grec->lock);
+ return nil;
+}
+
+static char *
+grectlulresume(Conv *c, int, char **)
+{
+ GREconv *grec;
+ GREhdr *gre;
+ Block *bp;
+
+ grec = c->ptcl;
+
+ qlock(&grec->lock);
+ while((bp = getring(&grec->ulbuffered)) != nil){
+ gre = (GREhdr *)bp->rp;
+
+ qunlock(&grec->lock);
+ ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
+ qlock(&grec->lock);
+ }
+ grec->ulsusp = 0;
+ qunlock(&grec->lock);
+ return nil;
+}
+
+static char *
+grectlforward(Conv *c, int, char **argv)
+{
+ int len;
+ Block *bp, *nbp;
+ GREconv *grec;
+ GREhdr *gre;
+ Metablock *m;
+
+ grec = c->ptcl;
+
+ v4parseip(grec->south, argv[1]);
+ memmove(grec->north, grec->south, sizeof grec->north);
+
+ qlock(&grec->lock);
+ if(!grec->dlsusp){
+ qunlock(&grec->lock);
+ return "not suspended";
+ }
+ grec->dlsusp = 0;
+ grec->ulsusp = 0;
+
+ while((bp = getring(&grec->dlpending)) != nil){
+
+ assert(bp->rp - bp->base >= sizeof(Metablock));
+ m = (Metablock *)bp->base;
+ assert(m->rp >= bp->base && m->rp < bp->lim);
+
+ /*
+ * If the packet is still held inside the IP transmit
+ * system, make a copy of the packet first.
+ */
+ if(bp->ref > 1){
+ len = bp->wp - m->rp;
+ nbp = allocb(len);
+ memmove(nbp->wp, m->rp, len);
+ nbp->wp += len;
+ freeb(bp);
+ bp = nbp;
+ }
+ else{
+ /* Patch up rp */
+ bp->rp = m->rp;
+ }
+
+ gre = (GREhdr *)bp->rp;
+ memmove(gre->src, grec->coa, sizeof gre->dst);
+ memmove(gre->dst, grec->south, sizeof gre->dst);
+
+ qunlock(&grec->lock);
+ ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
+ qlock(&grec->lock);
+ }
+
+ while((bp = getring(&grec->dlbuffered)) != nil){
+ gre = (GREhdr *)bp->rp;
+ memmove(gre->src, grec->coa, sizeof gre->dst);
+ memmove(gre->dst, grec->south, sizeof gre->dst);
+
+ qunlock(&grec->lock);
+ ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
+ qlock(&grec->lock);
+ }
+
+ while((bp = getring(&grec->ulbuffered)) != nil){
+ gre = (GREhdr *)bp->rp;
+
+ memmove(gre->src, grec->coa, sizeof gre->dst);
+ memmove(gre->dst, grec->south, sizeof gre->dst);
+
+ qunlock(&grec->lock);
+ ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
+ qlock(&grec->lock);
+ }
+ qunlock(&grec->lock);
+ return nil;
+}
+
+static char *
+grectlulkey(Conv *c, int, char **argv)
+{
+ GREconv *grec;
+
+ grec = c->ptcl;
+ grec->ulkey = strtoul(argv[1], nil, 0);
+ return nil;
+}
+
+char *
+grectl(Conv *c, char **f, int n)
+{
+ int i;
+
+ if(n < 1)
+ return "too few arguments";
+
+ for(i = 0; i < Ncmds; i++)
+ if(strcmp(f[0], grectls[i].cmd) == 0)
+ break;
+
+ if(i == Ncmds)
+ return "no such command";
+ if(grectls[i].argc != 0 && grectls[i].argc != n)
+ return "incorrect number of arguments";
+
+ return grectls[i].f(c, n, f);
+}
+
+void
+greinit(Fs *fs)
+{
+ Proto *gre;
+
+ gre = smalloc(sizeof(Proto));
+ gre->priv = smalloc(sizeof(GREpriv));
+ gre->name = "gre";
+ gre->connect = greconnect;
+ gre->announce = greannounce;
+ gre->state = grestate;
+ gre->create = grecreate;
+ gre->close = greclose;
+ gre->rcv = greiput;
+ gre->ctl = grectl;
+ gre->advise = nil;
+ gre->stats = grestats;
+ gre->ipproto = IP_GREPROTO;
+ gre->nc = 64;
+ gre->ptclsize = sizeof(GREconv);
+
+ Fsproto(fs, gre);
+}
diff --git a/sys/src/9/ip/icmp.c b/sys/src/9/ip/icmp.c
new file mode 100755
index 000000000..9dd5c9414
--- /dev/null
+++ b/sys/src/9/ip/icmp.c
@@ -0,0 +1,492 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+
+typedef struct Icmp {
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+ uchar ttl; /* Time to live */
+ uchar proto; /* Protocol */
+ uchar ipcksum[2]; /* Header checksum */
+ uchar src[4]; /* Ip source */
+ uchar dst[4]; /* Ip destination */
+ uchar type;
+ uchar code;
+ uchar cksum[2];
+ uchar icmpid[2];
+ uchar seq[2];
+ uchar data[1];
+} Icmp;
+
+enum { /* Packet Types */
+ EchoReply = 0,
+ Unreachable = 3,
+ SrcQuench = 4,
+ Redirect = 5,
+ EchoRequest = 8,
+ TimeExceed = 11,
+ InParmProblem = 12,
+ Timestamp = 13,
+ TimestampReply = 14,
+ InfoRequest = 15,
+ InfoReply = 16,
+ AddrMaskRequest = 17,
+ AddrMaskReply = 18,
+
+ Maxtype = 18,
+};
+
+enum
+{
+ MinAdvise = 24, /* minimum needed for us to advise another protocol */
+};
+
+char *icmpnames[Maxtype+1] =
+{
+[EchoReply] "EchoReply",
+[Unreachable] "Unreachable",
+[SrcQuench] "SrcQuench",
+[Redirect] "Redirect",
+[EchoRequest] "EchoRequest",
+[TimeExceed] "TimeExceed",
+[InParmProblem] "InParmProblem",
+[Timestamp] "Timestamp",
+[TimestampReply] "TimestampReply",
+[InfoRequest] "InfoRequest",
+[InfoReply] "InfoReply",
+[AddrMaskRequest] "AddrMaskRequest",
+[AddrMaskReply ] "AddrMaskReply ",
+};
+
+enum {
+ IP_ICMPPROTO = 1,
+ ICMP_IPSIZE = 20,
+ ICMP_HDRSIZE = 8,
+};
+
+enum
+{
+ InMsgs,
+ InErrors,
+ OutMsgs,
+ CsumErrs,
+ LenErrs,
+ HlenErrs,
+
+ Nstats,
+};
+
+static char *statnames[Nstats] =
+{
+[InMsgs] "InMsgs",
+[InErrors] "InErrors",
+[OutMsgs] "OutMsgs",
+[CsumErrs] "CsumErrs",
+[LenErrs] "LenErrs",
+[HlenErrs] "HlenErrs",
+};
+
+typedef struct Icmppriv Icmppriv;
+struct Icmppriv
+{
+ ulong stats[Nstats];
+
+ /* message counts */
+ ulong in[Maxtype+1];
+ ulong out[Maxtype+1];
+};
+
+static void icmpkick(void *x, Block*);
+
+static void
+icmpcreate(Conv *c)
+{
+ c->rq = qopen(64*1024, Qmsg, 0, c);
+ c->wq = qbypass(icmpkick, c);
+}
+
+extern char*
+icmpconnect(Conv *c, char **argv, int argc)
+{
+ char *e;
+
+ e = Fsstdconnect(c, argv, argc);
+ if(e != nil)
+ return e;
+ Fsconnected(c, e);
+
+ return nil;
+}
+
+extern int
+icmpstate(Conv *c, char *state, int n)
+{
+ USED(c);
+ return snprint(state, n, "%s qin %d qout %d\n",
+ "Datagram",
+ c->rq ? qlen(c->rq) : 0,
+ c->wq ? qlen(c->wq) : 0
+ );
+}
+
+extern char*
+icmpannounce(Conv *c, char **argv, int argc)
+{
+ char *e;
+
+ e = Fsstdannounce(c, argv, argc);
+ if(e != nil)
+ return e;
+ Fsconnected(c, nil);
+
+ return nil;
+}
+
+extern void
+icmpclose(Conv *c)
+{
+ qclose(c->rq);
+ qclose(c->wq);
+ ipmove(c->laddr, IPnoaddr);
+ ipmove(c->raddr, IPnoaddr);
+ c->lport = 0;
+}
+
+static void
+icmpkick(void *x, Block *bp)
+{
+ Conv *c = x;
+ Icmp *p;
+ Icmppriv *ipriv;
+
+ if(bp == nil)
+ return;
+
+ if(blocklen(bp) < ICMP_IPSIZE + ICMP_HDRSIZE){
+ freeblist(bp);
+ return;
+ }
+ p = (Icmp *)(bp->rp);
+ p->vihl = IP_VER4;
+ ipriv = c->p->priv;
+ if(p->type <= Maxtype)
+ ipriv->out[p->type]++;
+
+ v6tov4(p->dst, c->raddr);
+ v6tov4(p->src, c->laddr);
+ p->proto = IP_ICMPPROTO;
+ hnputs(p->icmpid, c->lport);
+ memset(p->cksum, 0, sizeof(p->cksum));
+ hnputs(p->cksum, ptclcsum(bp, ICMP_IPSIZE, blocklen(bp) - ICMP_IPSIZE));
+ ipriv->stats[OutMsgs]++;
+ ipoput4(c->p->f, bp, 0, c->ttl, c->tos, nil);
+}
+
+extern void
+icmpttlexceeded(Fs *f, uchar *ia, Block *bp)
+{
+ Block *nbp;
+ Icmp *p, *np;
+
+ p = (Icmp *)bp->rp;
+
+ netlog(f, Logicmp, "sending icmpttlexceeded -> %V\n", p->src);
+ nbp = allocb(ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8);
+ nbp->wp += ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8;
+ np = (Icmp *)nbp->rp;
+ np->vihl = IP_VER4;
+ memmove(np->dst, p->src, sizeof(np->dst));
+ v6tov4(np->src, ia);
+ memmove(np->data, bp->rp, ICMP_IPSIZE + 8);
+ np->type = TimeExceed;
+ np->code = 0;
+ np->proto = IP_ICMPPROTO;
+ hnputs(np->icmpid, 0);
+ hnputs(np->seq, 0);
+ memset(np->cksum, 0, sizeof(np->cksum));
+ hnputs(np->cksum, ptclcsum(nbp, ICMP_IPSIZE, blocklen(nbp) - ICMP_IPSIZE));
+ ipoput4(f, nbp, 0, MAXTTL, DFLTTOS, nil);
+
+}
+
+static void
+icmpunreachable(Fs *f, Block *bp, int code, int seq)
+{
+ Block *nbp;
+ Icmp *p, *np;
+ int i;
+ uchar addr[IPaddrlen];
+
+ p = (Icmp *)bp->rp;
+
+ /* only do this for unicast sources and destinations */
+ v4tov6(addr, p->dst);
+ i = ipforme(f, addr);
+ if((i&Runi) == 0)
+ return;
+ v4tov6(addr, p->src);
+ i = ipforme(f, addr);
+ if(i != 0 && (i&Runi) == 0)
+ return;
+
+ netlog(f, Logicmp, "sending icmpnoconv -> %V\n", p->src);
+ nbp = allocb(ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8);
+ nbp->wp += ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8;
+ np = (Icmp *)nbp->rp;
+ np->vihl = IP_VER4;
+ memmove(np->dst, p->src, sizeof(np->dst));
+ memmove(np->src, p->dst, sizeof(np->src));
+ memmove(np->data, bp->rp, ICMP_IPSIZE + 8);
+ np->type = Unreachable;
+ np->code = code;
+ np->proto = IP_ICMPPROTO;
+ hnputs(np->icmpid, 0);
+ hnputs(np->seq, seq);
+ memset(np->cksum, 0, sizeof(np->cksum));
+ hnputs(np->cksum, ptclcsum(nbp, ICMP_IPSIZE, blocklen(nbp) - ICMP_IPSIZE));
+ ipoput4(f, nbp, 0, MAXTTL, DFLTTOS, nil);
+}
+
+extern void
+icmpnoconv(Fs *f, Block *bp)
+{
+ icmpunreachable(f, bp, 3, 0);
+}
+
+extern void
+icmpcantfrag(Fs *f, Block *bp, int mtu)
+{
+ icmpunreachable(f, bp, 4, mtu);
+}
+
+static void
+goticmpkt(Proto *icmp, Block *bp)
+{
+ Conv **c, *s;
+ Icmp *p;
+ uchar dst[IPaddrlen];
+ ushort recid;
+
+ p = (Icmp *) bp->rp;
+ v4tov6(dst, p->src);
+ recid = nhgets(p->icmpid);
+
+ for(c = icmp->conv; *c; c++) {
+ s = *c;
+ if(s->lport == recid)
+ if(ipcmp(s->raddr, dst) == 0){
+ bp = concatblock(bp);
+ if(bp != nil)
+ qpass(s->rq, bp);
+ return;
+ }
+ }
+ freeblist(bp);
+}
+
+static Block *
+mkechoreply(Block *bp)
+{
+ Icmp *q;
+ uchar ip[4];
+
+ q = (Icmp *)bp->rp;
+ q->vihl = IP_VER4;
+ memmove(ip, q->src, sizeof(q->dst));
+ memmove(q->src, q->dst, sizeof(q->src));
+ memmove(q->dst, ip, sizeof(q->dst));
+ q->type = EchoReply;
+ memset(q->cksum, 0, sizeof(q->cksum));
+ hnputs(q->cksum, ptclcsum(bp, ICMP_IPSIZE, blocklen(bp) - ICMP_IPSIZE));
+
+ return bp;
+}
+
+static char *unreachcode[] =
+{
+[0] "net unreachable",
+[1] "host unreachable",
+[2] "protocol unreachable",
+[3] "port unreachable",
+[4] "fragmentation needed and DF set",
+[5] "source route failed",
+};
+
+static void
+icmpiput(Proto *icmp, Ipifc*, Block *bp)
+{
+ int n, iplen;
+ Icmp *p;
+ Block *r;
+ Proto *pr;
+ char *msg;
+ char m2[128];
+ Icmppriv *ipriv;
+
+ ipriv = icmp->priv;
+
+ ipriv->stats[InMsgs]++;
+
+ p = (Icmp *)bp->rp;
+ netlog(icmp->f, Logicmp, "icmpiput %s (%d) %d\n",
+ (p->type < nelem(icmpnames)? icmpnames[p->type]: ""),
+ p->type, p->code);
+ n = blocklen(bp);
+ if(n < ICMP_IPSIZE+ICMP_HDRSIZE){
+ ipriv->stats[InErrors]++;
+ ipriv->stats[HlenErrs]++;
+ netlog(icmp->f, Logicmp, "icmp hlen %d\n", n);
+ goto raise;
+ }
+ iplen = nhgets(p->length);
+ if(iplen > n){
+ ipriv->stats[LenErrs]++;
+ ipriv->stats[InErrors]++;
+ netlog(icmp->f, Logicmp, "icmp length %d\n", iplen);
+ goto raise;
+ }
+ if(ptclcsum(bp, ICMP_IPSIZE, iplen - ICMP_IPSIZE)){
+ ipriv->stats[InErrors]++;
+ ipriv->stats[CsumErrs]++;
+ netlog(icmp->f, Logicmp, "icmp checksum error\n");
+ goto raise;
+ }
+ if(p->type <= Maxtype)
+ ipriv->in[p->type]++;
+
+ switch(p->type) {
+ case EchoRequest:
+ if (iplen < n)
+ bp = trimblock(bp, 0, iplen);
+ r = mkechoreply(bp);
+ ipriv->out[EchoReply]++;
+ ipoput4(icmp->f, r, 0, MAXTTL, DFLTTOS, nil);
+ break;
+ case Unreachable:
+ if(p->code > 5)
+ msg = unreachcode[1];
+ else
+ msg = unreachcode[p->code];
+
+ bp->rp += ICMP_IPSIZE+ICMP_HDRSIZE;
+ if(blocklen(bp) < MinAdvise){
+ ipriv->stats[LenErrs]++;
+ goto raise;
+ }
+ p = (Icmp *)bp->rp;
+ pr = Fsrcvpcolx(icmp->f, p->proto);
+ if(pr != nil && pr->advise != nil) {
+ (*pr->advise)(pr, bp, msg);
+ return;
+ }
+
+ bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE;
+ goticmpkt(icmp, bp);
+ break;
+ case TimeExceed:
+ if(p->code == 0){
+ sprint(m2, "ttl exceeded at %V", p->src);
+
+ bp->rp += ICMP_IPSIZE+ICMP_HDRSIZE;
+ if(blocklen(bp) < MinAdvise){
+ ipriv->stats[LenErrs]++;
+ goto raise;
+ }
+ p = (Icmp *)bp->rp;
+ pr = Fsrcvpcolx(icmp->f, p->proto);
+ if(pr != nil && pr->advise != nil) {
+ (*pr->advise)(pr, bp, m2);
+ return;
+ }
+ bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE;
+ }
+
+ goticmpkt(icmp, bp);
+ break;
+ default:
+ goticmpkt(icmp, bp);
+ break;
+ }
+ return;
+
+raise:
+ freeblist(bp);
+}
+
+void
+icmpadvise(Proto *icmp, Block *bp, char *msg)
+{
+ Conv **c, *s;
+ Icmp *p;
+ uchar dst[IPaddrlen];
+ ushort recid;
+
+ p = (Icmp *) bp->rp;
+ v4tov6(dst, p->dst);
+ recid = nhgets(p->icmpid);
+
+ for(c = icmp->conv; *c; c++) {
+ s = *c;
+ if(s->lport == recid)
+ if(ipcmp(s->raddr, dst) == 0){
+ qhangup(s->rq, msg);
+ qhangup(s->wq, msg);
+ break;
+ }
+ }
+ freeblist(bp);
+}
+
+int
+icmpstats(Proto *icmp, char *buf, int len)
+{
+ Icmppriv *priv;
+ char *p, *e;
+ int i;
+
+ priv = icmp->priv;
+ p = buf;
+ e = p+len;
+ for(i = 0; i < Nstats; i++)
+ p = seprint(p, e, "%s: %lud\n", statnames[i], priv->stats[i]);
+ for(i = 0; i <= Maxtype; i++){
+ if(icmpnames[i])
+ p = seprint(p, e, "%s: %lud %lud\n", icmpnames[i], priv->in[i], priv->out[i]);
+ else
+ p = seprint(p, e, "%d: %lud %lud\n", i, priv->in[i], priv->out[i]);
+ }
+ return p - buf;
+}
+
+void
+icmpinit(Fs *fs)
+{
+ Proto *icmp;
+
+ icmp = smalloc(sizeof(Proto));
+ icmp->priv = smalloc(sizeof(Icmppriv));
+ icmp->name = "icmp";
+ icmp->connect = icmpconnect;
+ icmp->announce = icmpannounce;
+ icmp->state = icmpstate;
+ icmp->create = icmpcreate;
+ icmp->close = icmpclose;
+ icmp->rcv = icmpiput;
+ icmp->stats = icmpstats;
+ icmp->ctl = nil;
+ icmp->advise = icmpadvise;
+ icmp->gc = nil;
+ icmp->ipproto = IP_ICMPPROTO;
+ icmp->nc = 128;
+ icmp->ptclsize = 0;
+
+ Fsproto(fs, icmp);
+}
diff --git a/sys/src/9/ip/icmp6.c b/sys/src/9/ip/icmp6.c
new file mode 100755
index 000000000..458280b27
--- /dev/null
+++ b/sys/src/9/ip/icmp6.c
@@ -0,0 +1,909 @@
+/*
+ * Internet Control Message Protocol for IPv6
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "ip.h"
+#include "ipv6.h"
+
+enum
+{
+ InMsgs6,
+ InErrors6,
+ OutMsgs6,
+ CsumErrs6,
+ LenErrs6,
+ HlenErrs6,
+ HoplimErrs6,
+ IcmpCodeErrs6,
+ TargetErrs6,
+ OptlenErrs6,
+ AddrmxpErrs6,
+ RouterAddrErrs6,
+
+ Nstats6,
+};
+
+enum {
+ ICMP_USEAD6 = 40,
+};
+
+enum {
+ Oflag = 1<<5,
+ Sflag = 1<<6,
+ Rflag = 1<<7,
+};
+
+enum {
+ /* ICMPv6 types */
+ EchoReply = 0,
+ UnreachableV6 = 1,
+ PacketTooBigV6 = 2,
+ TimeExceedV6 = 3,
+ SrcQuench = 4,
+ ParamProblemV6 = 4,
+ Redirect = 5,
+ EchoRequest = 8,
+ TimeExceed = 11,
+ InParmProblem = 12,
+ Timestamp = 13,
+ TimestampReply = 14,
+ InfoRequest = 15,
+ InfoReply = 16,
+ AddrMaskRequest = 17,
+ AddrMaskReply = 18,
+ EchoRequestV6 = 128,
+ EchoReplyV6 = 129,
+ RouterSolicit = 133,
+ RouterAdvert = 134,
+ NbrSolicit = 135,
+ NbrAdvert = 136,
+ RedirectV6 = 137,
+
+ Maxtype6 = 137,
+};
+
+/* on-the-wire packet formats */
+typedef struct IPICMP IPICMP;
+typedef struct Ndpkt Ndpkt;
+typedef struct NdiscC NdiscC;
+
+/* we do this to avoid possible struct padding */
+#define ICMPHDR \
+ IPV6HDR; \
+ uchar type; \
+ uchar code; \
+ uchar cksum[2]; \
+ uchar icmpid[2]; \
+ uchar seq[2]
+
+struct IPICMP {
+ ICMPHDR;
+ uchar payload[];
+};
+
+#define IPICMPSZ offsetof(IPICMP, payload[0])
+
+struct NdiscC {
+ ICMPHDR;
+ uchar target[IPaddrlen];
+ uchar payload[];
+};
+
+#define NDISCSZ offsetof(NdiscC, payload[0])
+
+struct Ndpkt {
+ ICMPHDR;
+ uchar target[IPaddrlen];
+ uchar otype;
+ uchar olen; /* length in units of 8 octets(incl type, code),
+ * 1 for IEEE 802 addresses */
+ uchar lnaddr[6]; /* link-layer address */
+ uchar payload[];
+};
+
+#define NDPKTSZ offsetof(Ndpkt, payload[0])
+
+typedef struct Icmppriv6
+{
+ ulong stats[Nstats6];
+
+ /* message counts */
+ ulong in[Maxtype6+1];
+ ulong out[Maxtype6+1];
+} Icmppriv6;
+
+typedef struct Icmpcb6
+{
+ QLock;
+ uchar headers;
+} Icmpcb6;
+
+char *icmpnames6[Maxtype6+1] =
+{
+[EchoReply] "EchoReply",
+[UnreachableV6] "UnreachableV6",
+[PacketTooBigV6] "PacketTooBigV6",
+[TimeExceedV6] "TimeExceedV6",
+[SrcQuench] "SrcQuench",
+[Redirect] "Redirect",
+[EchoRequest] "EchoRequest",
+[TimeExceed] "TimeExceed",
+[InParmProblem] "InParmProblem",
+[Timestamp] "Timestamp",
+[TimestampReply] "TimestampReply",
+[InfoRequest] "InfoRequest",
+[InfoReply] "InfoReply",
+[AddrMaskRequest] "AddrMaskRequest",
+[AddrMaskReply] "AddrMaskReply",
+[EchoRequestV6] "EchoRequestV6",
+[EchoReplyV6] "EchoReplyV6",
+[RouterSolicit] "RouterSolicit",
+[RouterAdvert] "RouterAdvert",
+[NbrSolicit] "NbrSolicit",
+[NbrAdvert] "NbrAdvert",
+[RedirectV6] "RedirectV6",
+};
+
+static char *statnames6[Nstats6] =
+{
+[InMsgs6] "InMsgs",
+[InErrors6] "InErrors",
+[OutMsgs6] "OutMsgs",
+[CsumErrs6] "CsumErrs",
+[LenErrs6] "LenErrs",
+[HlenErrs6] "HlenErrs",
+[HoplimErrs6] "HoplimErrs",
+[IcmpCodeErrs6] "IcmpCodeErrs",
+[TargetErrs6] "TargetErrs",
+[OptlenErrs6] "OptlenErrs",
+[AddrmxpErrs6] "AddrmxpErrs",
+[RouterAddrErrs6] "RouterAddrErrs",
+};
+
+static char *unreachcode[] =
+{
+[Icmp6_no_route] "no route to destination",
+[Icmp6_ad_prohib] "comm with destination administratively prohibited",
+[Icmp6_out_src_scope] "beyond scope of source address",
+[Icmp6_adr_unreach] "address unreachable",
+[Icmp6_port_unreach] "port unreachable",
+[Icmp6_gress_src_fail] "source address failed ingress/egress policy",
+[Icmp6_rej_route] "reject route to destination",
+[Icmp6_unknown] "icmp unreachable: unknown code",
+};
+
+static void icmpkick6(void *x, Block *bp);
+
+static void
+icmpcreate6(Conv *c)
+{
+ c->rq = qopen(64*1024, Qmsg, 0, c);
+ c->wq = qbypass(icmpkick6, c);
+}
+
+static void
+set_cksum(Block *bp)
+{
+ IPICMP *p = (IPICMP *)(bp->rp);
+
+ hnputl(p->vcf, 0); /* borrow IP header as pseudoheader */
+ hnputs(p->ploadlen, blocklen(bp) - IP6HDR);
+ p->proto = 0;
+ p->ttl = ICMPv6; /* ttl gets set later */
+ hnputs(p->cksum, 0);
+ hnputs(p->cksum, ptclcsum(bp, 0, blocklen(bp)));
+ p->proto = ICMPv6;
+}
+
+static Block *
+newIPICMP(int packetlen)
+{
+ Block *nbp;
+
+ nbp = allocb(packetlen);
+ nbp->wp += packetlen;
+ memset(nbp->rp, 0, packetlen);
+ return nbp;
+}
+
+void
+icmpadvise6(Proto *icmp, Block *bp, char *msg)
+{
+ ushort recid;
+ Conv **c, *s;
+ IPICMP *p;
+
+ p = (IPICMP *)bp->rp;
+ recid = nhgets(p->icmpid);
+
+ for(c = icmp->conv; *c; c++) {
+ s = *c;
+ if(s->lport == recid && ipcmp(s->raddr, p->dst) == 0){
+ qhangup(s->rq, msg);
+ qhangup(s->wq, msg);
+ break;
+ }
+ }
+ freeblist(bp);
+}
+
+static void
+icmpkick6(void *x, Block *bp)
+{
+ uchar laddr[IPaddrlen], raddr[IPaddrlen];
+ Conv *c = x;
+ IPICMP *p;
+ Icmppriv6 *ipriv = c->p->priv;
+ Icmpcb6 *icb = (Icmpcb6*)c->ptcl;
+
+ if(bp == nil)
+ return;
+
+ if(icb->headers==6) {
+ /* get user specified addresses */
+ bp = pullupblock(bp, ICMP_USEAD6);
+ if(bp == nil)
+ return;
+ bp->rp += 8;
+ ipmove(laddr, bp->rp);
+ bp->rp += IPaddrlen;
+ ipmove(raddr, bp->rp);
+ bp->rp += IPaddrlen;
+ bp = padblock(bp, IP6HDR);
+ }
+
+ if(blocklen(bp) < IPICMPSZ){
+ freeblist(bp);
+ return;
+ }
+ p = (IPICMP *)(bp->rp);
+ if(icb->headers == 6) {
+ ipmove(p->dst, raddr);
+ ipmove(p->src, laddr);
+ } else {
+ ipmove(p->dst, c->raddr);
+ ipmove(p->src, c->laddr);
+ hnputs(p->icmpid, c->lport);
+ }
+
+ set_cksum(bp);
+ p->vcf[0] = 0x06 << 4;
+ if(p->type <= Maxtype6)
+ ipriv->out[p->type]++;
+ ipoput6(c->p->f, bp, 0, c->ttl, c->tos, nil);
+}
+
+char*
+icmpctl6(Conv *c, char **argv, int argc)
+{
+ Icmpcb6 *icb;
+
+ icb = (Icmpcb6*) c->ptcl;
+ if(argc==1 && strcmp(argv[0], "headers")==0) {
+ icb->headers = 6;
+ return nil;
+ }
+ return "unknown control request";
+}
+
+static void
+goticmpkt6(Proto *icmp, Block *bp, int muxkey)
+{
+ ushort recid;
+ uchar *addr;
+ Conv **c, *s;
+ IPICMP *p = (IPICMP *)bp->rp;
+
+ if(muxkey == 0) {
+ recid = nhgets(p->icmpid);
+ addr = p->src;
+ } else {
+ recid = muxkey;
+ addr = p->dst;
+ }
+
+ for(c = icmp->conv; *c; c++){
+ s = *c;
+ if(s->lport == recid && ipcmp(s->raddr, addr) == 0){
+ bp = concatblock(bp);
+ if(bp != nil)
+ qpass(s->rq, bp);
+ return;
+ }
+ }
+
+ freeblist(bp);
+}
+
+static Block *
+mkechoreply6(Block *bp, Ipifc *ifc)
+{
+ uchar addr[IPaddrlen];
+ IPICMP *p = (IPICMP *)(bp->rp);
+
+ ipmove(addr, p->src);
+ if(!isv6mcast(p->dst))
+ ipmove(p->src, p->dst);
+ else if (!ipv6anylocal(ifc, p->src))
+ return nil;
+ ipmove(p->dst, addr);
+ p->type = EchoReplyV6;
+ set_cksum(bp);
+ return bp;
+}
+
+/*
+ * sends out an ICMPv6 neighbor solicitation
+ * suni == SRC_UNSPEC or SRC_UNI,
+ * tuni == TARG_MULTI => multicast for address resolution,
+ * and tuni == TARG_UNI => neighbor reachability.
+ */
+extern void
+icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac)
+{
+ Block *nbp;
+ Ndpkt *np;
+ Proto *icmp = f->t2p[ICMPv6];
+ Icmppriv6 *ipriv = icmp->priv;
+
+ nbp = newIPICMP(NDPKTSZ);
+ np = (Ndpkt*) nbp->rp;
+
+ if(suni == SRC_UNSPEC)
+ memmove(np->src, v6Unspecified, IPaddrlen);
+ else
+ memmove(np->src, src, IPaddrlen);
+
+ if(tuni == TARG_UNI)
+ memmove(np->dst, targ, IPaddrlen);
+ else
+ ipv62smcast(np->dst, targ);
+
+ np->type = NbrSolicit;
+ np->code = 0;
+ memmove(np->target, targ, IPaddrlen);
+ if(suni != SRC_UNSPEC) {
+ np->otype = SRC_LLADDR;
+ np->olen = 1; /* 1+1+6 = 8 = 1 8-octet */
+ memmove(np->lnaddr, mac, sizeof(np->lnaddr));
+ } else
+ nbp->wp -= NDPKTSZ - NDISCSZ;
+
+ set_cksum(nbp);
+ np = (Ndpkt*)nbp->rp;
+ np->ttl = HOP_LIMIT;
+ np->vcf[0] = 0x06 << 4;
+ ipriv->out[NbrSolicit]++;
+ netlog(f, Logicmp, "sending neighbor solicitation %I\n", targ);
+ ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
+}
+
+/*
+ * sends out an ICMPv6 neighbor advertisement. pktflags == RSO flags.
+ */
+extern void
+icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
+{
+ Block *nbp;
+ Ndpkt *np;
+ Proto *icmp = f->t2p[ICMPv6];
+ Icmppriv6 *ipriv = icmp->priv;
+
+ nbp = newIPICMP(NDPKTSZ);
+ np = (Ndpkt*)nbp->rp;
+
+ memmove(np->src, src, IPaddrlen);
+ memmove(np->dst, dst, IPaddrlen);
+
+ np->type = NbrAdvert;
+ np->code = 0;
+ np->icmpid[0] = flags;
+ memmove(np->target, targ, IPaddrlen);
+
+ np->otype = TARGET_LLADDR;
+ np->olen = 1;
+ memmove(np->lnaddr, mac, sizeof(np->lnaddr));
+
+ set_cksum(nbp);
+ np = (Ndpkt*) nbp->rp;
+ np->ttl = HOP_LIMIT;
+ np->vcf[0] = 0x06 << 4;
+ ipriv->out[NbrAdvert]++;
+ netlog(f, Logicmp, "sending neighbor advertisement %I\n", src);
+ ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
+}
+
+extern void
+icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free)
+{
+ int osz = BLEN(bp);
+ int sz = MIN(IPICMPSZ + osz, v6MINTU);
+ Block *nbp;
+ IPICMP *np;
+ Ip6hdr *p;
+ Proto *icmp = f->t2p[ICMPv6];
+ Icmppriv6 *ipriv = icmp->priv;
+
+ p = (Ip6hdr *)bp->rp;
+
+ if(isv6mcast(p->src))
+ goto clean;
+
+ nbp = newIPICMP(sz);
+ np = (IPICMP *)nbp->rp;
+
+ rlock(ifc);
+ if(ipv6anylocal(ifc, np->src))
+ netlog(f, Logicmp, "send icmphostunr -> src %I dst %I\n",
+ p->src, p->dst);
+ else {
+ netlog(f, Logicmp, "icmphostunr fail -> src %I dst %I\n",
+ p->src, p->dst);
+ freeblist(nbp);
+ if(free)
+ goto clean;
+ else
+ return;
+ }
+
+ memmove(np->dst, p->src, IPaddrlen);
+ np->type = UnreachableV6;
+ np->code = code;
+ memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
+ set_cksum(nbp);
+ np->ttl = HOP_LIMIT;
+ np->vcf[0] = 0x06 << 4;
+ ipriv->out[UnreachableV6]++;
+
+ if(free)
+ ipiput6(f, ifc, nbp);
+ else {
+ ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
+ return;
+ }
+
+clean:
+ runlock(ifc);
+ freeblist(bp);
+}
+
+extern void
+icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
+{
+ int osz = BLEN(bp);
+ int sz = MIN(IPICMPSZ + osz, v6MINTU);
+ Block *nbp;
+ IPICMP *np;
+ Ip6hdr *p;
+ Proto *icmp = f->t2p[ICMPv6];
+ Icmppriv6 *ipriv = icmp->priv;
+
+ p = (Ip6hdr *)bp->rp;
+
+ if(isv6mcast(p->src))
+ return;
+
+ nbp = newIPICMP(sz);
+ np = (IPICMP *) nbp->rp;
+
+ if(ipv6anylocal(ifc, np->src))
+ netlog(f, Logicmp, "send icmpttlexceeded6 -> src %I dst %I\n",
+ p->src, p->dst);
+ else {
+ netlog(f, Logicmp, "icmpttlexceeded6 fail -> src %I dst %I\n",
+ p->src, p->dst);
+ return;
+ }
+
+ memmove(np->dst, p->src, IPaddrlen);
+ np->type = TimeExceedV6;
+ np->code = 0;
+ memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
+ set_cksum(nbp);
+ np->ttl = HOP_LIMIT;
+ np->vcf[0] = 0x06 << 4;
+ ipriv->out[TimeExceedV6]++;
+ ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
+}
+
+extern void
+icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
+{
+ int osz = BLEN(bp);
+ int sz = MIN(IPICMPSZ + osz, v6MINTU);
+ Block *nbp;
+ IPICMP *np;
+ Ip6hdr *p;
+ Proto *icmp = f->t2p[ICMPv6];
+ Icmppriv6 *ipriv = icmp->priv;
+
+ p = (Ip6hdr *)bp->rp;
+
+ if(isv6mcast(p->src))
+ return;
+
+ nbp = newIPICMP(sz);
+ np = (IPICMP *)nbp->rp;
+
+ if(ipv6anylocal(ifc, np->src))
+ netlog(f, Logicmp, "send icmppkttoobig6 -> src %I dst %I\n",
+ p->src, p->dst);
+ else {
+ netlog(f, Logicmp, "icmppkttoobig6 fail -> src %I dst %I\n",
+ p->src, p->dst);
+ return;
+ }
+
+ memmove(np->dst, p->src, IPaddrlen);
+ np->type = PacketTooBigV6;
+ np->code = 0;
+ hnputl(np->icmpid, ifc->maxtu - ifc->m->hsize);
+ memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
+ set_cksum(nbp);
+ np->ttl = HOP_LIMIT;
+ np->vcf[0] = 0x06 << 4;
+ ipriv->out[PacketTooBigV6]++;
+ ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
+}
+
+/*
+ * RFC 2461, pages 39-40, pages 57-58.
+ */
+static int
+valid(Proto *icmp, Ipifc *ifc, Block *bp, Icmppriv6 *ipriv)
+{
+ int sz, osz, unsp, n, ttl, iplen;
+ int pktsz = BLEN(bp);
+ uchar *packet = bp->rp;
+ IPICMP *p = (IPICMP *) packet;
+ Ndpkt *np;
+
+ USED(ifc);
+ n = blocklen(bp);
+ if(n < IPICMPSZ) {
+ ipriv->stats[HlenErrs6]++;
+ netlog(icmp->f, Logicmp, "icmp hlen %d\n", n);
+ goto err;
+ }
+
+ iplen = nhgets(p->ploadlen);
+ if(iplen > n - IP6HDR) {
+ ipriv->stats[LenErrs6]++;
+ netlog(icmp->f, Logicmp, "icmp length %d\n", iplen);
+ goto err;
+ }
+
+ /* Rather than construct explicit pseudoheader, overwrite IPv6 header */
+ if(p->proto != ICMPv6) {
+ /* This code assumes no extension headers!!! */
+ netlog(icmp->f, Logicmp, "icmp error: extension header\n");
+ goto err;
+ }
+ memset(packet, 0, 4);
+ ttl = p->ttl;
+ p->ttl = p->proto;
+ p->proto = 0;
+ if(ptclcsum(bp, 0, iplen + IP6HDR)) {
+ ipriv->stats[CsumErrs6]++;
+ netlog(icmp->f, Logicmp, "icmp checksum error\n");
+ goto err;
+ }
+ p->proto = p->ttl;
+ p->ttl = ttl;
+
+ /* additional tests for some pkt types */
+ if (p->type == NbrSolicit || p->type == NbrAdvert ||
+ p->type == RouterAdvert || p->type == RouterSolicit ||
+ p->type == RedirectV6) {
+ if(p->ttl != HOP_LIMIT) {
+ ipriv->stats[HoplimErrs6]++;
+ goto err;
+ }
+ if(p->code != 0) {
+ ipriv->stats[IcmpCodeErrs6]++;
+ goto err;
+ }
+
+ switch (p->type) {
+ case NbrSolicit:
+ case NbrAdvert:
+ np = (Ndpkt*) p;
+ if(isv6mcast(np->target)) {
+ ipriv->stats[TargetErrs6]++;
+ goto err;
+ }
+ if(optexsts(np) && np->olen == 0) {
+ ipriv->stats[OptlenErrs6]++;
+ goto err;
+ }
+
+ if (p->type == NbrSolicit &&
+ ipcmp(np->src, v6Unspecified) == 0)
+ if(!issmcast(np->dst) || optexsts(np)) {
+ ipriv->stats[AddrmxpErrs6]++;
+ goto err;
+ }
+
+ if(p->type == NbrAdvert)
+ if(isv6mcast(np->dst) &&
+ (nhgets(np->icmpid) & Sflag)){
+ ipriv->stats[AddrmxpErrs6]++;
+ goto err;
+ }
+ break;
+
+ case RouterAdvert:
+ if(pktsz - IP6HDR < 16) {
+ ipriv->stats[HlenErrs6]++;
+ goto err;
+ }
+ if(!islinklocal(p->src)) {
+ ipriv->stats[RouterAddrErrs6]++;
+ goto err;
+ }
+ sz = IPICMPSZ + 8;
+ while (sz+1 < pktsz) {
+ osz = packet[sz+1];
+ if(osz <= 0) {
+ ipriv->stats[OptlenErrs6]++;
+ goto err;
+ }
+ sz += 8*osz;
+ }
+ break;
+
+ case RouterSolicit:
+ if(pktsz - IP6HDR < 8) {
+ ipriv->stats[HlenErrs6]++;
+ goto err;
+ }
+ unsp = (ipcmp(p->src, v6Unspecified) == 0);
+ sz = IPICMPSZ + 8;
+ while (sz+1 < pktsz) {
+ osz = packet[sz+1];
+ if(osz <= 0 ||
+ (unsp && packet[sz] == SRC_LLADDR)) {
+ ipriv->stats[OptlenErrs6]++;
+ goto err;
+ }
+ sz += 8*osz;
+ }
+ break;
+
+ case RedirectV6:
+ /* to be filled in */
+ break;
+
+ default:
+ goto err;
+ }
+ }
+ return 1;
+err:
+ ipriv->stats[InErrors6]++;
+ return 0;
+}
+
+static int
+targettype(Fs *f, Ipifc *ifc, uchar *target)
+{
+ Iplifc *lifc;
+ int t;
+
+ rlock(ifc);
+ if(ipproxyifc(f, ifc, target)) {
+ runlock(ifc);
+ return Tuniproxy;
+ }
+
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next)
+ if(ipcmp(lifc->local, target) == 0) {
+ t = (lifc->tentative)? Tunitent: Tunirany;
+ runlock(ifc);
+ return t;
+ }
+
+ runlock(ifc);
+ return 0;
+}
+
+static void
+icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
+{
+ int refresh = 1;
+ char *msg, m2[128];
+ uchar pktflags;
+ uchar *packet = bp->rp;
+ uchar lsrc[IPaddrlen];
+ Block *r;
+ IPICMP *p = (IPICMP *)packet;
+ Icmppriv6 *ipriv = icmp->priv;
+ Iplifc *lifc;
+ Ndpkt* np;
+ Proto *pr;
+
+ if(!valid(icmp, ipifc, bp, ipriv) || p->type > Maxtype6)
+ goto raise;
+
+ ipriv->in[p->type]++;
+
+ switch(p->type) {
+ case EchoRequestV6:
+ r = mkechoreply6(bp, ipifc);
+ if(r == nil)
+ goto raise;
+ ipriv->out[EchoReply]++;
+ ipoput6(icmp->f, r, 0, MAXTTL, DFLTTOS, nil);
+ break;
+
+ case UnreachableV6:
+ if(p->code >= nelem(unreachcode))
+ msg = unreachcode[Icmp6_unknown];
+ else
+ msg = unreachcode[p->code];
+
+ bp->rp += IPICMPSZ;
+ if(blocklen(bp) < 8){
+ ipriv->stats[LenErrs6]++;
+ goto raise;
+ }
+ p = (IPICMP *)bp->rp;
+ pr = Fsrcvpcolx(icmp->f, p->proto);
+ if(pr != nil && pr->advise != nil) {
+ (*pr->advise)(pr, bp, msg);
+ return;
+ }
+
+ bp->rp -= IPICMPSZ;
+ goticmpkt6(icmp, bp, 0);
+ break;
+
+ case TimeExceedV6:
+ if(p->code == 0){
+ sprint(m2, "ttl exceeded at %I", p->src);
+
+ bp->rp += IPICMPSZ;
+ if(blocklen(bp) < 8){
+ ipriv->stats[LenErrs6]++;
+ goto raise;
+ }
+ p = (IPICMP *)bp->rp;
+ pr = Fsrcvpcolx(icmp->f, p->proto);
+ if(pr && pr->advise) {
+ (*pr->advise)(pr, bp, m2);
+ return;
+ }
+ bp->rp -= IPICMPSZ;
+ }
+
+ goticmpkt6(icmp, bp, 0);
+ break;
+
+ case RouterAdvert:
+ case RouterSolicit:
+ /* using lsrc as a temp, munge hdr for goticmp6 */
+ if (0) {
+ memmove(lsrc, p->src, IPaddrlen);
+ memmove(p->src, p->dst, IPaddrlen);
+ memmove(p->dst, lsrc, IPaddrlen);
+ }
+ goticmpkt6(icmp, bp, p->type);
+ break;
+
+ case NbrSolicit:
+ np = (Ndpkt*) p;
+ pktflags = 0;
+ switch (targettype(icmp->f, ipifc, np->target)) {
+ case Tunirany:
+ pktflags |= Oflag;
+ /* fall through */
+
+ case Tuniproxy:
+ if(ipcmp(np->src, v6Unspecified) != 0) {
+ arpenter(icmp->f, V6, np->src, np->lnaddr,
+ 8*np->olen-2, 0);
+ pktflags |= Sflag;
+ }
+ if(ipv6local(ipifc, lsrc))
+ icmpna(icmp->f, lsrc,
+ (ipcmp(np->src, v6Unspecified) == 0?
+ v6allnodesL: np->src),
+ np->target, ipifc->mac, pktflags);
+ else
+ freeblist(bp);
+ break;
+
+ case Tunitent:
+ /* not clear what needs to be done. send up
+ * an icmp mesg saying don't use this address? */
+ default:
+ freeblist(bp);
+ }
+ break;
+
+ case NbrAdvert:
+ np = (Ndpkt*) p;
+
+ /*
+ * if the target address matches one of the local interface
+ * addresses and the local interface address has tentative bit
+ * set, insert into ARP table. this is so the duplicate address
+ * detection part of ipconfig can discover duplication through
+ * the arp table.
+ */
+ lifc = iplocalonifc(ipifc, np->target);
+ if(lifc && lifc->tentative)
+ refresh = 0;
+ arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2,
+ refresh);
+ freeblist(bp);
+ break;
+
+ case PacketTooBigV6:
+ default:
+ goticmpkt6(icmp, bp, 0);
+ break;
+ }
+ return;
+raise:
+ freeblist(bp);
+}
+
+int
+icmpstats6(Proto *icmp6, char *buf, int len)
+{
+ Icmppriv6 *priv;
+ char *p, *e;
+ int i;
+
+ priv = icmp6->priv;
+ p = buf;
+ e = p+len;
+ for(i = 0; i < Nstats6; i++)
+ p = seprint(p, e, "%s: %lud\n", statnames6[i], priv->stats[i]);
+ for(i = 0; i <= Maxtype6; i++)
+ if(icmpnames6[i])
+ p = seprint(p, e, "%s: %lud %lud\n", icmpnames6[i],
+ priv->in[i], priv->out[i]);
+/* else
+ p = seprint(p, e, "%d: %lud %lud\n", i, priv->in[i],
+ priv->out[i]);
+ */
+ return p - buf;
+}
+
+
+/* import from icmp.c */
+extern int icmpstate(Conv *c, char *state, int n);
+extern char* icmpannounce(Conv *c, char **argv, int argc);
+extern char* icmpconnect(Conv *c, char **argv, int argc);
+extern void icmpclose(Conv *c);
+
+void
+icmp6init(Fs *fs)
+{
+ Proto *icmp6 = smalloc(sizeof(Proto));
+
+ icmp6->priv = smalloc(sizeof(Icmppriv6));
+ icmp6->name = "icmpv6";
+ icmp6->connect = icmpconnect;
+ icmp6->announce = icmpannounce;
+ icmp6->state = icmpstate;
+ icmp6->create = icmpcreate6;
+ icmp6->close = icmpclose;
+ icmp6->rcv = icmpiput6;
+ icmp6->stats = icmpstats6;
+ icmp6->ctl = icmpctl6;
+ icmp6->advise = icmpadvise6;
+ icmp6->gc = nil;
+ icmp6->ipproto = ICMPv6;
+ icmp6->nc = 16;
+ icmp6->ptclsize = sizeof(Icmpcb6);
+
+ Fsproto(fs, icmp6);
+}
diff --git a/sys/src/9/ip/igmp.c b/sys/src/9/ip/igmp.c
new file mode 100755
index 000000000..c0c330fac
--- /dev/null
+++ b/sys/src/9/ip/igmp.c
@@ -0,0 +1,299 @@
+/*
+ * igmp - internet group management protocol
+ * unfinished.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+
+enum
+{
+ IGMP_IPHDRSIZE = 20, /* size of ip header */
+ IGMP_HDRSIZE = 8, /* size of IGMP header */
+ IP_IGMPPROTO = 2,
+
+ IGMPquery = 1,
+ IGMPreport = 2,
+
+ MSPTICK = 100,
+ MAXTIMEOUT = 10000/MSPTICK, /* at most 10 secs for a response */
+};
+
+typedef struct IGMPpkt IGMPpkt;
+struct IGMPpkt
+{
+ /* ip header */
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar len[2]; /* packet length (including headers) */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+ uchar Unused;
+ uchar proto; /* Protocol */
+ uchar cksum[2]; /* checksum of ip portion */
+ uchar src[IPaddrlen]; /* Ip source */
+ uchar dst[IPaddrlen]; /* Ip destination */
+
+ /* igmp header */
+ uchar vertype; /* version and type */
+ uchar unused;
+ uchar igmpcksum[2]; /* checksum of igmp portion */
+ uchar group[IPaddrlen]; /* multicast group */
+
+ uchar payload[];
+};
+
+#define IGMPPKTSZ offsetof(IGMPpkt, payload[0])
+
+/*
+ * lists for group reports
+ */
+typedef struct IGMPrep IGMPrep;
+struct IGMPrep
+{
+ IGMPrep *next;
+ Medium *m;
+ int ticks;
+ Multicast *multi;
+};
+
+typedef struct IGMP IGMP;
+struct IGMP
+{
+ Lock;
+ Rendez r;
+ IGMPrep *reports;
+};
+
+IGMP igmpalloc;
+
+ Proto igmp;
+extern Fs fs;
+
+static struct Stats
+{
+ ulong inqueries;
+ ulong outqueries;
+ ulong inreports;
+ ulong outreports;
+} stats;
+
+void
+igmpsendreport(Medium *m, uchar *addr)
+{
+ IGMPpkt *p;
+ Block *bp;
+
+ bp = allocb(sizeof(IGMPpkt));
+ if(bp == nil)
+ return;
+ p = (IGMPpkt*)bp->wp;
+ p->vihl = IP_VER4;
+ bp->wp += IGMPPKTSZ;
+ memset(bp->rp, 0, IGMPPKTSZ);
+ hnputl(p->src, Mediumgetaddr(m));
+ hnputl(p->dst, Ipallsys);
+ p->vertype = (1<<4) | IGMPreport;
+ p->proto = IP_IGMPPROTO;
+ memmove(p->group, addr, IPaddrlen);
+ hnputs(p->igmpcksum, ptclcsum(bp, IGMP_IPHDRSIZE, IGMP_HDRSIZE));
+ netlog(Logigmp, "igmpreport %I\n", p->group);
+ stats.outreports++;
+ ipoput4(bp, 0, 1, DFLTTOS, nil); /* TTL of 1 */
+}
+
+static int
+isreport(void *a)
+{
+ USED(a);
+ return igmpalloc.reports != 0;
+}
+
+
+void
+igmpproc(void *a)
+{
+ IGMPrep *rp, **lrp;
+ Multicast *mp, **lmp;
+ uchar ip[IPaddrlen];
+
+ USED(a);
+
+ for(;;){
+ sleep(&igmpalloc.r, isreport, 0);
+ for(;;){
+ lock(&igmpalloc);
+
+ if(igmpalloc.reports == nil)
+ break;
+
+ /* look for a single report */
+ lrp = &igmpalloc.reports;
+ mp = nil;
+ for(rp = *lrp; rp; rp = *lrp){
+ rp->ticks++;
+ lmp = &rp->multi;
+ for(mp = *lmp; mp; mp = *lmp){
+ if(rp->ticks >= mp->timeout){
+ *lmp = mp->next;
+ break;
+ }
+ lmp = &mp->next;
+ }
+ if(mp != nil)
+ break;
+
+ if(rp->multi != nil){
+ lrp = &rp->next;
+ continue;
+ } else {
+ *lrp = rp->next;
+ free(rp);
+ }
+ }
+ unlock(&igmpalloc);
+
+ if(mp){
+ /* do a single report and try again */
+ hnputl(ip, mp->addr);
+ igmpsendreport(rp->m, ip);
+ free(mp);
+ continue;
+ }
+
+ tsleep(&up->sleep, return0, 0, MSPTICK);
+ }
+ unlock(&igmpalloc);
+ }
+
+}
+
+void
+igmpiput(Medium *m, Ipifc *, Block *bp)
+{
+ int n;
+ IGMPpkt *ghp;
+ Ipaddr group;
+ IGMPrep *rp, **lrp;
+ Multicast *mp, **lmp;
+
+ ghp = (IGMPpkt*)(bp->rp);
+ netlog(Logigmp, "igmpiput: %d %I\n", ghp->vertype, ghp->group);
+
+ n = blocklen(bp);
+ if(n < IGMP_IPHDRSIZE+IGMP_HDRSIZE){
+ netlog(Logigmp, "igmpiput: bad len\n");
+ goto error;
+ }
+ if((ghp->vertype>>4) != 1){
+ netlog(Logigmp, "igmpiput: bad igmp type\n");
+ goto error;
+ }
+ if(ptclcsum(bp, IGMP_IPHDRSIZE, IGMP_HDRSIZE)){
+ netlog(Logigmp, "igmpiput: checksum error %I\n", ghp->src);
+ goto error;
+ }
+
+ group = nhgetl(ghp->group);
+
+ lock(&igmpalloc);
+ switch(ghp->vertype & 0xf){
+ case IGMPquery:
+ /*
+ * start reporting groups that we're a member of.
+ */
+ stats.inqueries++;
+ for(rp = igmpalloc.reports; rp; rp = rp->next)
+ if(rp->m == m)
+ break;
+ if(rp != nil)
+ break; /* already reporting */
+
+ mp = Mediumcopymulti(m);
+ if(mp == nil)
+ break;
+
+ rp = malloc(sizeof(*rp));
+ if(rp == nil)
+ break;
+
+ rp->m = m;
+ rp->multi = mp;
+ rp->ticks = 0;
+ for(; mp; mp = mp->next)
+ mp->timeout = nrand(MAXTIMEOUT);
+ rp->next = igmpalloc.reports;
+ igmpalloc.reports = rp;
+
+ wakeup(&igmpalloc.r);
+
+ break;
+ case IGMPreport:
+ /*
+ * find report list for this medium
+ */
+ stats.inreports++;
+ lrp = &igmpalloc.reports;
+ for(rp = *lrp; rp; rp = *lrp){
+ if(rp->m == m)
+ break;
+ lrp = &rp->next;
+ }
+ if(rp == nil)
+ break;
+
+ /*
+ * if someone else has reported a group,
+ * we don't have to.
+ */
+ lmp = &rp->multi;
+ for(mp = *lmp; mp; mp = *lmp){
+ if(mp->addr == group){
+ *lmp = mp->next;
+ free(mp);
+ break;
+ }
+ lmp = &mp->next;
+ }
+
+ break;
+ }
+ unlock(&igmpalloc);
+
+error:
+ freeb(bp);
+}
+
+int
+igmpstats(char *buf, int len)
+{
+ return snprint(buf, len, "\trcvd %d %d\n\tsent %d %d\n",
+ stats.inqueries, stats.inreports,
+ stats.outqueries, stats.outreports);
+}
+
+void
+igmpinit(Fs *fs)
+{
+ igmp.name = "igmp";
+ igmp.connect = nil;
+ igmp.announce = nil;
+ igmp.ctl = nil;
+ igmp.state = nil;
+ igmp.close = nil;
+ igmp.rcv = igmpiput;
+ igmp.stats = igmpstats;
+ igmp.ipproto = IP_IGMPPROTO;
+ igmp.nc = 0;
+ igmp.ptclsize = 0;
+
+ igmpreportfn = igmpsendreport;
+ kproc("igmpproc", igmpproc, 0);
+
+ Fsproto(fs, &igmp);
+}
diff --git a/sys/src/9/ip/inferno.c b/sys/src/9/ip/inferno.c
new file mode 100755
index 000000000..67b0341a1
--- /dev/null
+++ b/sys/src/9/ip/inferno.c
@@ -0,0 +1,28 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+/*
+ * some hacks for commonality twixt inferno and plan9
+ */
+
+char*
+commonuser(void)
+{
+ return up->user;
+}
+
+char*
+commonerror(void)
+{
+ return up->errstr;
+}
+
+int
+bootpread(char*, ulong, int)
+{
+ return 0;
+}
diff --git a/sys/src/9/ip/ip.c b/sys/src/9/ip/ip.c
new file mode 100755
index 000000000..19aef70a4
--- /dev/null
+++ b/sys/src/9/ip/ip.c
@@ -0,0 +1,706 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+
+#define BLKIPVER(xp) (((Ip4hdr*)((xp)->rp))->vihl&0xF0)
+
+static char *statnames[] =
+{
+[Forwarding] "Forwarding",
+[DefaultTTL] "DefaultTTL",
+[InReceives] "InReceives",
+[InHdrErrors] "InHdrErrors",
+[InAddrErrors] "InAddrErrors",
+[ForwDatagrams] "ForwDatagrams",
+[InUnknownProtos] "InUnknownProtos",
+[InDiscards] "InDiscards",
+[InDelivers] "InDelivers",
+[OutRequests] "OutRequests",
+[OutDiscards] "OutDiscards",
+[OutNoRoutes] "OutNoRoutes",
+[ReasmTimeout] "ReasmTimeout",
+[ReasmReqds] "ReasmReqds",
+[ReasmOKs] "ReasmOKs",
+[ReasmFails] "ReasmFails",
+[FragOKs] "FragOKs",
+[FragFails] "FragFails",
+[FragCreates] "FragCreates",
+};
+
+#define BLKIP(xp) ((Ip4hdr*)((xp)->rp))
+/*
+ * This sleazy macro relies on the media header size being
+ * larger than sizeof(Ipfrag). ipreassemble checks this is true
+ */
+#define BKFG(xp) ((Ipfrag*)((xp)->base))
+
+ushort ipcsum(uchar*);
+Block* ip4reassemble(IP*, int, Block*, Ip4hdr*);
+void ipfragfree4(IP*, Fragment4*);
+Fragment4* ipfragallo4(IP*);
+
+void
+ip_init_6(Fs *f)
+{
+ v6params *v6p;
+
+ v6p = smalloc(sizeof(v6params));
+
+ v6p->rp.mflag = 0; /* default not managed */
+ v6p->rp.oflag = 0;
+ v6p->rp.maxraint = 600000; /* millisecs */
+ v6p->rp.minraint = 200000;
+ v6p->rp.linkmtu = 0; /* no mtu sent */
+ v6p->rp.reachtime = 0;
+ v6p->rp.rxmitra = 0;
+ v6p->rp.ttl = MAXTTL;
+ v6p->rp.routerlt = 3 * v6p->rp.maxraint;
+
+ v6p->hp.rxmithost = 1000; /* v6 RETRANS_TIMER */
+
+ v6p->cdrouter = -1;
+
+ f->v6p = v6p;
+}
+
+void
+initfrag(IP *ip, int size)
+{
+ Fragment4 *fq4, *eq4;
+ Fragment6 *fq6, *eq6;
+
+ ip->fragfree4 = (Fragment4*)malloc(sizeof(Fragment4) * size);
+ if(ip->fragfree4 == nil)
+ panic("initfrag");
+
+ eq4 = &ip->fragfree4[size];
+ for(fq4 = ip->fragfree4; fq4 < eq4; fq4++)
+ fq4->next = fq4+1;
+
+ ip->fragfree4[size-1].next = nil;
+
+ ip->fragfree6 = (Fragment6*)malloc(sizeof(Fragment6) * size);
+ if(ip->fragfree6 == nil)
+ panic("initfrag");
+
+ eq6 = &ip->fragfree6[size];
+ for(fq6 = ip->fragfree6; fq6 < eq6; fq6++)
+ fq6->next = fq6+1;
+
+ ip->fragfree6[size-1].next = nil;
+}
+
+void
+ip_init(Fs *f)
+{
+ IP *ip;
+
+ ip = smalloc(sizeof(IP));
+ initfrag(ip, 100);
+ f->ip = ip;
+
+ ip_init_6(f);
+}
+
+void
+iprouting(Fs *f, int on)
+{
+ f->ip->iprouting = on;
+ if(f->ip->iprouting==0)
+ f->ip->stats[Forwarding] = 2;
+ else
+ f->ip->stats[Forwarding] = 1;
+}
+
+int
+ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c)
+{
+ Ipifc *ifc;
+ uchar *gate;
+ ulong fragoff;
+ Block *xp, *nb;
+ Ip4hdr *eh, *feh;
+ int lid, len, seglen, chunk, dlen, blklen, offset, medialen;
+ Route *r, *sr;
+ IP *ip;
+ int rv = 0;
+
+ ip = f->ip;
+
+ /* Fill out the ip header */
+ eh = (Ip4hdr*)(bp->rp);
+
+ ip->stats[OutRequests]++;
+
+ /* Number of uchars in data and ip header to write */
+ len = blocklen(bp);
+
+ if(gating){
+ chunk = nhgets(eh->length);
+ if(chunk > len){
+ ip->stats[OutDiscards]++;
+ netlog(f, Logip, "short gated packet\n");
+ goto free;
+ }
+ if(chunk < len)
+ len = chunk;
+ }
+ if(len >= IP_MAX){
+ ip->stats[OutDiscards]++;
+ netlog(f, Logip, "exceeded ip max size %V\n", eh->dst);
+ goto free;
+ }
+
+ r = v4lookup(f, eh->dst, c);
+ if(r == nil){
+ ip->stats[OutNoRoutes]++;
+ netlog(f, Logip, "no interface %V\n", eh->dst);
+ rv = -1;
+ goto free;
+ }
+
+ ifc = r->ifc;
+ if(r->type & (Rifc|Runi))
+ gate = eh->dst;
+ else
+ if(r->type & (Rbcast|Rmulti)) {
+ gate = eh->dst;
+ sr = v4lookup(f, eh->src, nil);
+ if(sr != nil && (sr->type & Runi))
+ ifc = sr->ifc;
+ }
+ else
+ gate = r->v4.gate;
+
+ if(!gating)
+ eh->vihl = IP_VER4|IP_HLEN4;
+ eh->ttl = ttl;
+ if(!gating)
+ eh->tos = tos;
+
+ if(!canrlock(ifc))
+ goto free;
+ if(waserror()){
+ runlock(ifc);
+ nexterror();
+ }
+ if(ifc->m == nil)
+ goto raise;
+
+ /* If we dont need to fragment just send it */
+ if(c && c->maxfragsize && c->maxfragsize < ifc->maxtu)
+ medialen = c->maxfragsize - ifc->m->hsize;
+ else
+ medialen = ifc->maxtu - ifc->m->hsize;
+ if(len <= medialen) {
+ if(!gating)
+ hnputs(eh->id, incref(&ip->id4));
+ hnputs(eh->length, len);
+ if(!gating){
+ eh->frag[0] = 0;
+ eh->frag[1] = 0;
+ }
+ eh->cksum[0] = 0;
+ eh->cksum[1] = 0;
+ hnputs(eh->cksum, ipcsum(&eh->vihl));
+ assert(bp->next == nil);
+ ifc->m->bwrite(ifc, bp, V4, gate);
+ runlock(ifc);
+ poperror();
+ return 0;
+ }
+
+if((eh->frag[0] & (IP_DF>>8)) && !gating) print("%V: DF set\n", eh->dst);
+
+ if(eh->frag[0] & (IP_DF>>8)){
+ ip->stats[FragFails]++;
+ ip->stats[OutDiscards]++;
+ icmpcantfrag(f, bp, medialen);
+ netlog(f, Logip, "%V: eh->frag[0] & (IP_DF>>8)\n", eh->dst);
+ goto raise;
+ }
+
+ seglen = (medialen - IP4HDR) & ~7;
+ if(seglen < 8){
+ ip->stats[FragFails]++;
+ ip->stats[OutDiscards]++;
+ netlog(f, Logip, "%V seglen < 8\n", eh->dst);
+ goto raise;
+ }
+
+ dlen = len - IP4HDR;
+ xp = bp;
+ if(gating)
+ lid = nhgets(eh->id);
+ else
+ lid = incref(&ip->id4);
+
+ offset = IP4HDR;
+ while(xp != nil && offset && offset >= BLEN(xp)) {
+ offset -= BLEN(xp);
+ xp = xp->next;
+ }
+ xp->rp += offset;
+
+ if(gating)
+ fragoff = nhgets(eh->frag)<<3;
+ else
+ fragoff = 0;
+ dlen += fragoff;
+ for(; fragoff < dlen; fragoff += seglen) {
+ nb = allocb(IP4HDR+seglen);
+ feh = (Ip4hdr*)(nb->rp);
+
+ memmove(nb->wp, eh, IP4HDR);
+ nb->wp += IP4HDR;
+
+ if((fragoff + seglen) >= dlen) {
+ seglen = dlen - fragoff;
+ hnputs(feh->frag, fragoff>>3);
+ }
+ else
+ hnputs(feh->frag, (fragoff>>3)|IP_MF);
+
+ hnputs(feh->length, seglen + IP4HDR);
+ hnputs(feh->id, lid);
+
+ /* Copy up the data area */
+ chunk = seglen;
+ while(chunk) {
+ if(!xp) {
+ ip->stats[OutDiscards]++;
+ ip->stats[FragFails]++;
+ freeblist(nb);
+ netlog(f, Logip, "!xp: chunk %d\n", chunk);
+ goto raise;
+ }
+ blklen = chunk;
+ if(BLEN(xp) < chunk)
+ blklen = BLEN(xp);
+ memmove(nb->wp, xp->rp, blklen);
+ nb->wp += blklen;
+ xp->rp += blklen;
+ chunk -= blklen;
+ if(xp->rp == xp->wp)
+ xp = xp->next;
+ }
+
+ feh->cksum[0] = 0;
+ feh->cksum[1] = 0;
+ hnputs(feh->cksum, ipcsum(&feh->vihl));
+ ifc->m->bwrite(ifc, nb, V4, gate);
+ ip->stats[FragCreates]++;
+ }
+ ip->stats[FragOKs]++;
+raise:
+ runlock(ifc);
+ poperror();
+free:
+ freeblist(bp);
+ return rv;
+}
+
+void
+ipiput4(Fs *f, Ipifc *ifc, Block *bp)
+{
+ int hl;
+ int hop, tos, proto, olen;
+ Ip4hdr *h;
+ Proto *p;
+ ushort frag;
+ int notforme;
+ uchar *dp, v6dst[IPaddrlen];
+ IP *ip;
+ Route *r;
+ Conv conv;
+
+ if(BLKIPVER(bp) != IP_VER4) {
+ ipiput6(f, ifc, bp);
+ return;
+ }
+
+ ip = f->ip;
+ ip->stats[InReceives]++;
+
+ /*
+ * Ensure we have all the header info in the first
+ * block. Make life easier for other protocols by
+ * collecting up to the first 64 bytes in the first block.
+ */
+ if(BLEN(bp) < 64) {
+ hl = blocklen(bp);
+ if(hl < IP4HDR)
+ hl = IP4HDR;
+ if(hl > 64)
+ hl = 64;
+ bp = pullupblock(bp, hl);
+ if(bp == nil)
+ return;
+ }
+
+ h = (Ip4hdr*)(bp->rp);
+
+ /* dump anything that whose header doesn't checksum */
+ if((bp->flag & Bipck) == 0 && ipcsum(&h->vihl)) {
+ ip->stats[InHdrErrors]++;
+ netlog(f, Logip, "ip: checksum error %V\n", h->src);
+ freeblist(bp);
+ return;
+ }
+ v4tov6(v6dst, h->dst);
+ notforme = ipforme(f, v6dst) == 0;
+
+ /* Check header length and version */
+ if((h->vihl&0x0F) != IP_HLEN4) {
+ hl = (h->vihl&0xF)<<2;
+ if(hl < (IP_HLEN4<<2)) {
+ ip->stats[InHdrErrors]++;
+ netlog(f, Logip, "ip: %V bad hivl %ux\n", h->src, h->vihl);
+ freeblist(bp);
+ return;
+ }
+ /* If this is not routed strip off the options */
+ if(notforme == 0) {
+ olen = nhgets(h->length);
+ dp = bp->rp + (hl - (IP_HLEN4<<2));
+ memmove(dp, h, IP_HLEN4<<2);
+ bp->rp = dp;
+ h = (Ip4hdr*)(bp->rp);
+ h->vihl = (IP_VER4|IP_HLEN4);
+ hnputs(h->length, olen-hl+(IP_HLEN4<<2));
+ }
+ }
+
+ /* route */
+ if(notforme) {
+ if(!ip->iprouting){
+ freeblist(bp);
+ return;
+ }
+
+ /* don't forward to source's network */
+ memmove(&conv, ifc->conv, sizeof conv);
+ conv.r = nil;
+ r = v4lookup(f, h->dst, &conv);
+ if(r == nil || r->ifc == ifc){
+ ip->stats[OutDiscards]++;
+ freeblist(bp);
+ return;
+ }
+
+ /* don't forward if packet has timed out */
+ hop = h->ttl;
+ if(hop < 1) {
+ ip->stats[InHdrErrors]++;
+ icmpttlexceeded(f, ifc->lifc->local, bp);
+ freeblist(bp);
+ return;
+ }
+
+ /* reassemble if the interface expects it */
+if(r->ifc == nil) panic("nil route rfc");
+ if(r->ifc->reassemble){
+ frag = nhgets(h->frag);
+ if(frag) {
+ h->tos = 0;
+ if(frag & IP_MF)
+ h->tos = 1;
+ bp = ip4reassemble(ip, frag, bp, h);
+ if(bp == nil)
+ return;
+ h = (Ip4hdr*)(bp->rp);
+ }
+ }
+
+ ip->stats[ForwDatagrams]++;
+ tos = h->tos;
+ hop = h->ttl;
+ ipoput4(f, bp, 1, hop - 1, tos, &conv);
+ return;
+ }
+
+ frag = nhgets(h->frag);
+ if(frag) {
+ h->tos = 0;
+ if(frag & IP_MF)
+ h->tos = 1;
+ bp = ip4reassemble(ip, frag, bp, h);
+ if(bp == nil)
+ return;
+ h = (Ip4hdr*)(bp->rp);
+ }
+
+ /* don't let any frag info go up the stack */
+ h->frag[0] = 0;
+ h->frag[1] = 0;
+
+ proto = h->proto;
+ p = Fsrcvpcol(f, proto);
+ if(p != nil && p->rcv != nil) {
+ ip->stats[InDelivers]++;
+ (*p->rcv)(p, ifc, bp);
+ return;
+ }
+ ip->stats[InDiscards]++;
+ ip->stats[InUnknownProtos]++;
+ freeblist(bp);
+}
+
+int
+ipstats(Fs *f, char *buf, int len)
+{
+ IP *ip;
+ char *p, *e;
+ int i;
+
+ ip = f->ip;
+ ip->stats[DefaultTTL] = MAXTTL;
+
+ p = buf;
+ e = p+len;
+ for(i = 0; i < Nipstats; i++)
+ p = seprint(p, e, "%s: %llud\n", statnames[i], ip->stats[i]);
+ return p - buf;
+}
+
+Block*
+ip4reassemble(IP *ip, int offset, Block *bp, Ip4hdr *ih)
+{
+ int fend;
+ ushort id;
+ Fragment4 *f, *fnext;
+ ulong src, dst;
+ Block *bl, **l, *last, *prev;
+ int ovlap, len, fragsize, pktposn;
+
+ src = nhgetl(ih->src);
+ dst = nhgetl(ih->dst);
+ id = nhgets(ih->id);
+
+ /*
+ * block lists are too hard, pullupblock into a single block
+ */
+ if(bp->next){
+ bp = pullupblock(bp, blocklen(bp));
+ ih = (Ip4hdr*)(bp->rp);
+ }
+
+ qlock(&ip->fraglock4);
+
+ /*
+ * find a reassembly queue for this fragment
+ */
+ for(f = ip->flisthead4; f; f = fnext){
+ fnext = f->next; /* because ipfragfree4 changes the list */
+ if(f->src == src && f->dst == dst && f->id == id)
+ break;
+ if(f->age < NOW){
+ ip->stats[ReasmTimeout]++;
+ ipfragfree4(ip, f);
+ }
+ }
+
+ /*
+ * if this isn't a fragmented packet, accept it
+ * and get rid of any fragments that might go
+ * with it.
+ */
+ if(!ih->tos && (offset & ~(IP_MF|IP_DF)) == 0) {
+ if(f != nil) {
+ ipfragfree4(ip, f);
+ ip->stats[ReasmFails]++;
+ }
+ qunlock(&ip->fraglock4);
+ return bp;
+ }
+
+ if(bp->base+IPFRAGSZ >= bp->rp){
+ bp = padblock(bp, IPFRAGSZ);
+ bp->rp += IPFRAGSZ;
+ }
+
+ BKFG(bp)->foff = offset<<3;
+ BKFG(bp)->flen = nhgets(ih->length)-IP4HDR;
+
+ /* First fragment allocates a reassembly queue */
+ if(f == nil) {
+ f = ipfragallo4(ip);
+ f->id = id;
+ f->src = src;
+ f->dst = dst;
+
+ f->blist = bp;
+
+ qunlock(&ip->fraglock4);
+ ip->stats[ReasmReqds]++;
+ return nil;
+ }
+
+ /*
+ * find the new fragment's position in the queue
+ */
+ prev = nil;
+ l = &f->blist;
+ bl = f->blist;
+ while(bl != nil && BKFG(bp)->foff > BKFG(bl)->foff) {
+ prev = bl;
+ l = &bl->next;
+ bl = bl->next;
+ }
+
+ /* Check overlap of a previous fragment - trim away as necessary */
+ if(prev) {
+ ovlap = BKFG(prev)->foff + BKFG(prev)->flen - BKFG(bp)->foff;
+ if(ovlap > 0) {
+ if(ovlap >= BKFG(bp)->flen) {
+ freeblist(bp);
+ qunlock(&ip->fraglock4);
+ return nil;
+ }
+ BKFG(prev)->flen -= ovlap;
+ }
+ }
+
+ /* Link onto assembly queue */
+ bp->next = *l;
+ *l = bp;
+
+ /* Check to see if succeeding segments overlap */
+ if(bp->next) {
+ l = &bp->next;
+ fend = BKFG(bp)->foff + BKFG(bp)->flen;
+ /* Take completely covered segments out */
+ while(*l) {
+ ovlap = fend - BKFG(*l)->foff;
+ if(ovlap <= 0)
+ break;
+ if(ovlap < BKFG(*l)->flen) {
+ BKFG(*l)->flen -= ovlap;
+ BKFG(*l)->foff += ovlap;
+ /* move up ih hdrs */
+ memmove((*l)->rp + ovlap, (*l)->rp, IP4HDR);
+ (*l)->rp += ovlap;
+ break;
+ }
+ last = (*l)->next;
+ (*l)->next = nil;
+ freeblist(*l);
+ *l = last;
+ }
+ }
+
+ /*
+ * look for a complete packet. if we get to a fragment
+ * without IP_MF set, we're done.
+ */
+ pktposn = 0;
+ for(bl = f->blist; bl; bl = bl->next) {
+ if(BKFG(bl)->foff != pktposn)
+ break;
+ if((BLKIP(bl)->frag[0]&(IP_MF>>8)) == 0) {
+ bl = f->blist;
+ len = nhgets(BLKIP(bl)->length);
+ bl->wp = bl->rp + len;
+
+ /* Pullup all the fragment headers and
+ * return a complete packet
+ */
+ for(bl = bl->next; bl; bl = bl->next) {
+ fragsize = BKFG(bl)->flen;
+ len += fragsize;
+ bl->rp += IP4HDR;
+ bl->wp = bl->rp + fragsize;
+ }
+
+ bl = f->blist;
+ f->blist = nil;
+ ipfragfree4(ip, f);
+ ih = BLKIP(bl);
+ hnputs(ih->length, len);
+ qunlock(&ip->fraglock4);
+ ip->stats[ReasmOKs]++;
+ return bl;
+ }
+ pktposn += BKFG(bl)->flen;
+ }
+ qunlock(&ip->fraglock4);
+ return nil;
+}
+
+/*
+ * ipfragfree4 - Free a list of fragments - assume hold fraglock4
+ */
+void
+ipfragfree4(IP *ip, Fragment4 *frag)
+{
+ Fragment4 *fl, **l;
+
+ if(frag->blist)
+ freeblist(frag->blist);
+
+ frag->src = 0;
+ frag->id = 0;
+ frag->blist = nil;
+
+ l = &ip->flisthead4;
+ for(fl = *l; fl; fl = fl->next) {
+ if(fl == frag) {
+ *l = frag->next;
+ break;
+ }
+ l = &fl->next;
+ }
+
+ frag->next = ip->fragfree4;
+ ip->fragfree4 = frag;
+
+}
+
+/*
+ * ipfragallo4 - allocate a reassembly queue - assume hold fraglock4
+ */
+Fragment4 *
+ipfragallo4(IP *ip)
+{
+ Fragment4 *f;
+
+ while(ip->fragfree4 == nil) {
+ /* free last entry on fraglist */
+ for(f = ip->flisthead4; f->next; f = f->next)
+ ;
+ ipfragfree4(ip, f);
+ }
+ f = ip->fragfree4;
+ ip->fragfree4 = f->next;
+ f->next = ip->flisthead4;
+ ip->flisthead4 = f;
+ f->age = NOW + 30000;
+
+ return f;
+}
+
+ushort
+ipcsum(uchar *addr)
+{
+ int len;
+ ulong sum;
+
+ sum = 0;
+ len = (addr[0]&0xf)<<2;
+
+ while(len > 0) {
+ sum += addr[0]<<8 | addr[1] ;
+ len -= 2;
+ addr += 2;
+ }
+
+ sum = (sum & 0xffff) + (sum >> 16);
+ sum = (sum & 0xffff) + (sum >> 16);
+
+ return (sum^0xffff);
+}
diff --git a/sys/src/9/ip/ip.h b/sys/src/9/ip/ip.h
new file mode 100755
index 000000000..2d0a48635
--- /dev/null
+++ b/sys/src/9/ip/ip.h
@@ -0,0 +1,744 @@
+typedef struct Conv Conv;
+typedef struct Fragment4 Fragment4;
+typedef struct Fragment6 Fragment6;
+typedef struct Fs Fs;
+typedef union Hwaddr Hwaddr;
+typedef struct IP IP;
+typedef struct IPaux IPaux;
+typedef struct Ip4hdr Ip4hdr;
+typedef struct Ipfrag Ipfrag;
+typedef struct Ipself Ipself;
+typedef struct Ipselftab Ipselftab;
+typedef struct Iplink Iplink;
+typedef struct Iplifc Iplifc;
+typedef struct Ipmulti Ipmulti;
+typedef struct Ipifc Ipifc;
+typedef struct Iphash Iphash;
+typedef struct Ipht Ipht;
+typedef struct Netlog Netlog;
+typedef struct Medium Medium;
+typedef struct Proto Proto;
+typedef struct Arpent Arpent;
+typedef struct Arp Arp;
+typedef struct Route Route;
+
+typedef struct Routerparams Routerparams;
+typedef struct Hostparams Hostparams;
+typedef struct v6router v6router;
+typedef struct v6params v6params;
+
+#pragma incomplete Arp
+#pragma incomplete Ipself
+#pragma incomplete Ipselftab
+#pragma incomplete IP
+#pragma incomplete Netlog
+
+enum
+{
+ Addrlen= 64,
+ Maxproto= 20,
+ Nhash= 64,
+ Maxincall= 10,
+ Nchans= 1024,
+ MAClen= 16, /* longest mac address */
+
+ MAXTTL= 255,
+ DFLTTOS= 0,
+
+ IPaddrlen= 16,
+ IPv4addrlen= 4,
+ IPv4off= 12,
+ IPllen= 4,
+
+ /* ip versions */
+ V4= 4,
+ V6= 6,
+ IP_VER4= 0x40,
+ IP_VER6= 0x60,
+ IP_HLEN4= 5, /* v4: Header length in words */
+ IP_DF= 0x4000, /* v4: Don't fragment */
+ IP_MF= 0x2000, /* v4: More fragments */
+ IP4HDR= 20, /* sizeof(Ip4hdr) */
+ IP_MAX= 64*1024, /* Max. Internet packet size, v4 & v6 */
+
+ /* 2^Lroot trees in the root table */
+ Lroot= 10,
+
+ Maxpath = 64,
+};
+
+enum
+{
+ Idle= 0,
+ Announcing= 1,
+ Announced= 2,
+ Connecting= 3,
+ Connected= 4,
+};
+
+/* MIB II counters */
+enum
+{
+ Forwarding,
+ DefaultTTL,
+ InReceives,
+ InHdrErrors,
+ InAddrErrors,
+ ForwDatagrams,
+ InUnknownProtos,
+ InDiscards,
+ InDelivers,
+ OutRequests,
+ OutDiscards,
+ OutNoRoutes,
+ ReasmTimeout,
+ ReasmReqds,
+ ReasmOKs,
+ ReasmFails,
+ FragOKs,
+ FragFails,
+ FragCreates,
+
+ Nipstats,
+};
+
+struct Fragment4
+{
+ Block* blist;
+ Fragment4* next;
+ ulong src;
+ ulong dst;
+ ushort id;
+ ulong age;
+};
+
+struct Fragment6
+{
+ Block* blist;
+ Fragment6* next;
+ uchar src[IPaddrlen];
+ uchar dst[IPaddrlen];
+ uint id;
+ ulong age;
+};
+
+struct Ipfrag
+{
+ ushort foff;
+ ushort flen;
+
+ uchar payload[];
+};
+
+#define IPFRAGSZ offsetof(Ipfrag, payload[0])
+
+/* an instance of IP */
+struct IP
+{
+ uvlong stats[Nipstats];
+
+ QLock fraglock4;
+ Fragment4* flisthead4;
+ Fragment4* fragfree4;
+ Ref id4;
+
+ QLock fraglock6;
+ Fragment6* flisthead6;
+ Fragment6* fragfree6;
+ Ref id6;
+
+ int iprouting; /* true if we route like a gateway */
+};
+
+/* on the wire packet header */
+struct Ip4hdr
+{
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* ip->identification */
+ uchar frag[2]; /* Fragment information */
+ uchar ttl; /* Time to live */
+ uchar proto; /* Protocol */
+ uchar cksum[2]; /* Header checksum */
+ uchar src[4]; /* IP source */
+ uchar dst[4]; /* IP destination */
+};
+
+/*
+ * one per conversation directory
+ */
+struct Conv
+{
+ QLock;
+
+ int x; /* conversation index */
+ Proto* p;
+
+ int restricted; /* remote port is restricted */
+ uint ttl; /* max time to live */
+ uint tos; /* type of service */
+ int ignoreadvice; /* don't terminate connection on icmp errors */
+
+ uchar ipversion;
+ uchar laddr[IPaddrlen]; /* local IP address */
+ uchar raddr[IPaddrlen]; /* remote IP address */
+ ushort lport; /* local port number */
+ ushort rport; /* remote port number */
+
+ char *owner; /* protections */
+ int perm;
+ int inuse; /* opens of listen/data/ctl */
+ int length;
+ int state;
+
+ int maxfragsize; /* If set, used for fragmentation */
+
+ /* udp specific */
+ int headers; /* data src/dst headers in udp */
+ int reliable; /* true if reliable udp */
+
+ Conv* incall; /* calls waiting to be listened for */
+ Conv* next;
+
+ Queue* rq; /* queued data waiting to be read */
+ Queue* wq; /* queued data waiting to be written */
+ Queue* eq; /* returned error packets */
+ Queue* sq; /* snooping queue */
+ Ref snoopers; /* number of processes with snoop open */
+
+ QLock car;
+ Rendez cr;
+ char cerr[ERRMAX];
+
+ QLock listenq;
+ Rendez listenr;
+
+ Ipmulti *multi; /* multicast bindings for this interface */
+
+ void* ptcl; /* protocol specific stuff */
+
+ Route *r; /* last route used */
+ ulong rgen; /* routetable generation for *r */
+};
+
+struct Medium
+{
+ char *name;
+ int hsize; /* medium header size */
+ int mintu; /* default min mtu */
+ int maxtu; /* default max mtu */
+ int maclen; /* mac address length */
+ void (*bind)(Ipifc*, int, char**);
+ void (*unbind)(Ipifc*);
+ void (*bwrite)(Ipifc *ifc, Block *b, int version, uchar *ip);
+
+ /* for arming interfaces to receive multicast */
+ void (*addmulti)(Ipifc *ifc, uchar *a, uchar *ia);
+ void (*remmulti)(Ipifc *ifc, uchar *a, uchar *ia);
+
+ /* process packets written to 'data' */
+ void (*pktin)(Fs *f, Ipifc *ifc, Block *bp);
+
+ /* routes for router boards */
+ void (*addroute)(Ipifc *ifc, int, uchar*, uchar*, uchar*, int);
+ void (*remroute)(Ipifc *ifc, int, uchar*, uchar*);
+ void (*flushroutes)(Ipifc *ifc);
+
+ /* for routing multicast groups */
+ void (*joinmulti)(Ipifc *ifc, uchar *a, uchar *ia);
+ void (*leavemulti)(Ipifc *ifc, uchar *a, uchar *ia);
+
+ /* address resolution */
+ void (*ares)(Fs*, int, uchar*, uchar*, int, int); /* resolve */
+ void (*areg)(Ipifc*, uchar*); /* register */
+
+ /* v6 address generation */
+ void (*pref2addr)(uchar *pref, uchar *ea);
+
+ int unbindonclose; /* if non-zero, unbind on last close */
+};
+
+/* logical interface associated with a physical one */
+struct Iplifc
+{
+ uchar local[IPaddrlen];
+ uchar mask[IPaddrlen];
+ uchar remote[IPaddrlen];
+ uchar net[IPaddrlen];
+ uchar tentative; /* =1 => v6 dup disc on, =0 => confirmed unique */
+ uchar onlink; /* =1 => onlink, =0 offlink. */
+ uchar autoflag; /* v6 autonomous flag */
+ long validlt; /* v6 valid lifetime */
+ long preflt; /* v6 preferred lifetime */
+ long origint; /* time when addr was added */
+ Iplink *link; /* addresses linked to this lifc */
+ Iplifc *next;
+};
+
+/* binding twixt Ipself and Iplifc */
+struct Iplink
+{
+ Ipself *self;
+ Iplifc *lifc;
+ Iplink *selflink; /* next link for this local address */
+ Iplink *lifclink; /* next link for this ifc */
+ ulong expire;
+ Iplink *next; /* free list */
+ int ref;
+};
+
+/* rfc 2461, pp.40—43. */
+
+/* default values, one per stack */
+struct Routerparams {
+ int mflag; /* flag: managed address configuration */
+ int oflag; /* flag: other stateful configuration */
+ int maxraint; /* max. router adv interval (ms) */
+ int minraint; /* min. router adv interval (ms) */
+ int linkmtu; /* mtu options */
+ int reachtime; /* reachable time */
+ int rxmitra; /* retransmit interval */
+ int ttl; /* cur hop count limit */
+ int routerlt; /* router lifetime */
+};
+
+struct Hostparams {
+ int rxmithost;
+};
+
+struct Ipifc
+{
+ RWlock;
+
+ Conv *conv; /* link to its conversation structure */
+ char dev[64]; /* device we're attached to */
+ Medium *m; /* Media pointer */
+ int maxtu; /* Maximum transfer unit */
+ int mintu; /* Minumum tranfer unit */
+ int mbps; /* megabits per second */
+ void *arg; /* medium specific */
+ int reassemble; /* reassemble IP packets before forwarding */
+
+ /* these are used so that we can unbind on the fly */
+ Lock idlock;
+ uchar ifcid; /* incremented each 'bind/unbind/add/remove' */
+ int ref; /* number of proc's using this ipifc */
+ Rendez wait; /* where unbinder waits for ref == 0 */
+ int unbinding;
+
+ uchar mac[MAClen]; /* MAC address */
+
+ Iplifc *lifc; /* logical interfaces on this physical one */
+
+ ulong in, out; /* message statistics */
+ ulong inerr, outerr; /* ... */
+
+ uchar sendra6; /* flag: send router advs on this ifc */
+ uchar recvra6; /* flag: recv router advs on this ifc */
+ Routerparams rp; /* router parameters as in RFC 2461, pp.40—43.
+ used only if node is router */
+};
+
+/*
+ * one per multicast-lifc pair used by a Conv
+ */
+struct Ipmulti
+{
+ uchar ma[IPaddrlen];
+ uchar ia[IPaddrlen];
+ Ipmulti *next;
+};
+
+/*
+ * hash table for 2 ip addresses + 2 ports
+ */
+enum
+{
+ Nipht= 521, /* convenient prime */
+
+ IPmatchexact= 0, /* match on 4 tuple */
+ IPmatchany, /* *!* */
+ IPmatchport, /* *!port */
+ IPmatchaddr, /* addr!* */
+ IPmatchpa, /* addr!port */
+};
+struct Iphash
+{
+ Iphash *next;
+ Conv *c;
+ int match;
+};
+struct Ipht
+{
+ Lock;
+ Iphash *tab[Nipht];
+};
+void iphtadd(Ipht*, Conv*);
+void iphtrem(Ipht*, Conv*);
+Conv* iphtlook(Ipht *ht, uchar *sa, ushort sp, uchar *da, ushort dp);
+
+/*
+ * one per multiplexed protocol
+ */
+struct Proto
+{
+ QLock;
+ char* name; /* protocol name */
+ int x; /* protocol index */
+ int ipproto; /* ip protocol type */
+
+ char* (*connect)(Conv*, char**, int);
+ char* (*announce)(Conv*, char**, int);
+ char* (*bind)(Conv*, char**, int);
+ int (*state)(Conv*, char*, int);
+ void (*create)(Conv*);
+ void (*close)(Conv*);
+ void (*rcv)(Proto*, Ipifc*, Block*);
+ char* (*ctl)(Conv*, char**, int);
+ void (*advise)(Proto*, Block*, char*);
+ int (*stats)(Proto*, char*, int);
+ int (*local)(Conv*, char*, int);
+ int (*remote)(Conv*, char*, int);
+ int (*inuse)(Conv*);
+ int (*gc)(Proto*); /* returns true if any conversations are freed */
+
+ Fs *f; /* file system this proto is part of */
+ Conv **conv; /* array of conversations */
+ int ptclsize; /* size of per protocol ctl block */
+ int nc; /* number of conversations */
+ int ac;
+ Qid qid; /* qid for protocol directory */
+ ushort nextrport;
+
+ void *priv;
+};
+
+
+/*
+ * one per IP protocol stack
+ */
+struct Fs
+{
+ RWlock;
+ int dev;
+
+ int np;
+ Proto* p[Maxproto+1]; /* list of supported protocols */
+ Proto* t2p[256]; /* vector of all protocols */
+ Proto* ipifc; /* kludge for ipifcremroute & ipifcaddroute */
+ Proto* ipmux; /* kludge for finding an ip multiplexor */
+
+ IP *ip;
+ Ipselftab *self;
+ Arp *arp;
+ v6params *v6p;
+
+ Route *v4root[1<<Lroot]; /* v4 routing forest */
+ Route *v6root[1<<Lroot]; /* v6 routing forest */
+ Route *queue; /* used as temp when reinjecting routes */
+
+ Netlog *alog;
+
+ char ndb[1024]; /* an ndb entry for this interface */
+ int ndbvers;
+ long ndbmtime;
+};
+
+/* one per default router known to host */
+struct v6router {
+ uchar inuse;
+ Ipifc *ifc;
+ int ifcid;
+ uchar routeraddr[IPaddrlen];
+ long ltorigin;
+ Routerparams rp;
+};
+
+struct v6params
+{
+ Routerparams rp; /* v6 params, one copy per node now */
+ Hostparams hp;
+ v6router v6rlist[3]; /* max 3 default routers, currently */
+ int cdrouter; /* uses only v6rlist[cdrouter] if */
+ /* cdrouter >= 0. */
+};
+
+
+int Fsconnected(Conv*, char*);
+Conv* Fsnewcall(Conv*, uchar*, ushort, uchar*, ushort, uchar);
+int Fspcolstats(char*, int);
+int Fsproto(Fs*, Proto*);
+int Fsbuiltinproto(Fs*, uchar);
+Conv* Fsprotoclone(Proto*, char*);
+Proto* Fsrcvpcol(Fs*, uchar);
+Proto* Fsrcvpcolx(Fs*, uchar);
+char* Fsstdconnect(Conv*, char**, int);
+char* Fsstdannounce(Conv*, char**, int);
+char* Fsstdbind(Conv*, char**, int);
+ulong scalednconv(void);
+void closeconv(Conv*);
+/*
+ * logging
+ */
+enum
+{
+ Logip= 1<<1,
+ Logtcp= 1<<2,
+ Logfs= 1<<3,
+ Logicmp= 1<<5,
+ Logudp= 1<<6,
+ Logcompress= 1<<7,
+ Loggre= 1<<9,
+ Logppp= 1<<10,
+ Logtcprxmt= 1<<11,
+ Logigmp= 1<<12,
+ Logudpmsg= 1<<13,
+ Logipmsg= 1<<14,
+ Logrudp= 1<<15,
+ Logrudpmsg= 1<<16,
+ Logesp= 1<<17,
+ Logtcpwin= 1<<18,
+};
+
+void netloginit(Fs*);
+void netlogopen(Fs*);
+void netlogclose(Fs*);
+void netlogctl(Fs*, char*, int);
+long netlogread(Fs*, void*, ulong, long);
+void netlog(Fs*, int, char*, ...);
+void ifcloginit(Fs*);
+long ifclogread(Fs*, Chan *,void*, ulong, long);
+void ifclog(Fs*, uchar *, int);
+void ifclogopen(Fs*, Chan*);
+void ifclogclose(Fs*, Chan*);
+
+#pragma varargck argpos netlog 3
+
+/*
+ * iproute.c
+ */
+typedef struct RouteTree RouteTree;
+typedef struct Routewalk Routewalk;
+typedef struct V4route V4route;
+typedef struct V6route V6route;
+
+enum
+{
+
+ /* type bits */
+ Rv4= (1<<0), /* this is a version 4 route */
+ Rifc= (1<<1), /* this route is a directly connected interface */
+ Rptpt= (1<<2), /* this route is a pt to pt interface */
+ Runi= (1<<3), /* a unicast self address */
+ Rbcast= (1<<4), /* a broadcast self address */
+ Rmulti= (1<<5), /* a multicast self address */
+ Rproxy= (1<<6), /* this route should be proxied */
+};
+
+struct Routewalk
+{
+ int o;
+ int h;
+ char* p;
+ char* e;
+ void* state;
+ void (*walk)(Route*, Routewalk*);
+};
+
+struct RouteTree
+{
+ Route* right;
+ Route* left;
+ Route* mid;
+ uchar depth;
+ uchar type;
+ uchar ifcid; /* must match ifc->id */
+ Ipifc *ifc;
+ char tag[4];
+ int ref;
+};
+
+struct V4route
+{
+ ulong address;
+ ulong endaddress;
+ uchar gate[IPv4addrlen];
+};
+
+struct V6route
+{
+ ulong address[IPllen];
+ ulong endaddress[IPllen];
+ uchar gate[IPaddrlen];
+};
+
+struct Route
+{
+ RouteTree;
+
+ union {
+ V6route v6;
+ V4route v4;
+ };
+};
+extern void v4addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type);
+extern void v6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type);
+extern void v4delroute(Fs *f, uchar *a, uchar *mask, int dolock);
+extern void v6delroute(Fs *f, uchar *a, uchar *mask, int dolock);
+extern Route* v4lookup(Fs *f, uchar *a, Conv *c);
+extern Route* v6lookup(Fs *f, uchar *a, Conv *c);
+extern long routeread(Fs *f, char*, ulong, int);
+extern long routewrite(Fs *f, Chan*, char*, int);
+extern void routetype(int, char*);
+extern void ipwalkroutes(Fs*, Routewalk*);
+extern void convroute(Route*, uchar*, uchar*, uchar*, char*, int*);
+
+/*
+ * devip.c
+ */
+
+/*
+ * Hanging off every ip channel's ->aux is the following structure.
+ * It maintains the state used by devip and iproute.
+ */
+struct IPaux
+{
+ char *owner; /* the user that did the attach */
+ char tag[4];
+};
+
+extern IPaux* newipaux(char*, char*);
+
+/*
+ * arp.c
+ */
+struct Arpent
+{
+ uchar ip[IPaddrlen];
+ uchar mac[MAClen];
+ Medium *type; /* media type */
+ Arpent* hash;
+ Block* hold;
+ Block* last;
+ uint ctime; /* time entry was created or refreshed */
+ uint utime; /* time entry was last used */
+ uchar state;
+ Arpent *nextrxt; /* re-transmit chain */
+ uint rtime; /* time for next retransmission */
+ uchar rxtsrem;
+ Ipifc *ifc;
+ uchar ifcid; /* must match ifc->id */
+};
+
+extern void arpinit(Fs*);
+extern int arpread(Arp*, char*, ulong, int);
+extern int arpwrite(Fs*, char*, int);
+extern Arpent* arpget(Arp*, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *h);
+extern void arprelease(Arp*, Arpent *a);
+extern Block* arpresolve(Arp*, Arpent *a, Medium *type, uchar *mac);
+extern void arpenter(Fs*, int version, uchar *ip, uchar *mac, int len, int norefresh);
+
+/*
+ * ipaux.c
+ */
+
+extern int myetheraddr(uchar*, char*);
+extern vlong parseip(uchar*, char*);
+extern vlong parseipmask(uchar*, char*);
+extern char* v4parseip(uchar*, char*);
+extern void maskip(uchar *from, uchar *mask, uchar *to);
+extern int parsemac(uchar *to, char *from, int len);
+extern uchar* defmask(uchar*);
+extern int isv4(uchar*);
+extern void v4tov6(uchar *v6, uchar *v4);
+extern int v6tov4(uchar *v4, uchar *v6);
+extern int eipfmt(Fmt*);
+
+#define ipmove(x, y) memmove(x, y, IPaddrlen)
+#define ipcmp(x, y) ( (x)[IPaddrlen-1] != (y)[IPaddrlen-1] || memcmp(x, y, IPaddrlen) )
+
+extern uchar IPv4bcast[IPaddrlen];
+extern uchar IPv4bcastobs[IPaddrlen];
+extern uchar IPv4allsys[IPaddrlen];
+extern uchar IPv4allrouter[IPaddrlen];
+extern uchar IPnoaddr[IPaddrlen];
+extern uchar v4prefix[IPaddrlen];
+extern uchar IPallbits[IPaddrlen];
+
+#define NOW TK2MS(MACHP(0)->ticks)
+
+/*
+ * media
+ */
+extern Medium ethermedium;
+extern Medium nullmedium;
+extern Medium pktmedium;
+
+/*
+ * ipifc.c
+ */
+extern Medium* ipfindmedium(char *name);
+extern void addipmedium(Medium *med);
+extern int ipforme(Fs*, uchar *addr);
+extern int iptentative(Fs*, uchar *addr);
+extern int ipisbm(uchar *);
+extern int ipismulticast(uchar *);
+extern Ipifc* findipifc(Fs*, uchar *remote, int type);
+extern void findlocalip(Fs*, uchar *local, uchar *remote);
+extern int ipv4local(Ipifc *ifc, uchar *addr);
+extern int ipv6local(Ipifc *ifc, uchar *addr);
+extern int ipv6anylocal(Ipifc *ifc, uchar *addr);
+extern Iplifc* iplocalonifc(Ipifc *ifc, uchar *ip);
+extern int ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip);
+extern int ipismulticast(uchar *ip);
+extern int ipisbooting(void);
+extern int ipifccheckin(Ipifc *ifc, Medium *med);
+extern void ipifccheckout(Ipifc *ifc);
+extern int ipifcgrab(Ipifc *ifc);
+extern void ipifcaddroute(Fs*, int, uchar*, uchar*, uchar*, int);
+extern void ipifcremroute(Fs*, int, uchar*, uchar*);
+extern void ipifcremmulti(Conv *c, uchar *ma, uchar *ia);
+extern void ipifcaddmulti(Conv *c, uchar *ma, uchar *ia);
+extern char* ipifcrem(Ipifc *ifc, char **argv, int argc);
+extern char* ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp);
+extern long ipselftabread(Fs*, char *a, ulong offset, int n);
+extern char* ipifcadd6(Ipifc *ifc, char**argv, int argc);
+/*
+ * ip.c
+ */
+extern void iprouting(Fs*, int);
+extern void icmpnoconv(Fs*, Block*);
+extern void icmpcantfrag(Fs*, Block*, int);
+extern void icmpttlexceeded(Fs*, uchar*, Block*);
+extern ushort ipcsum(uchar*);
+extern void ipiput4(Fs*, Ipifc*, Block*);
+extern void ipiput6(Fs*, Ipifc*, Block*);
+extern int ipoput4(Fs*, Block*, int, int, int, Conv*);
+extern int ipoput6(Fs*, Block*, int, int, int, Conv*);
+extern int ipstats(Fs*, char*, int);
+extern ushort ptclbsum(uchar*, int);
+extern ushort ptclcsum(Block*, int, int);
+extern void ip_init(Fs*);
+extern void update_mtucache(uchar*, ulong);
+extern ulong restrict_mtu(uchar*, ulong);
+/*
+ * bootp.c
+ */
+extern int bootpread(char*, ulong, int);
+
+/*
+ * resolving inferno/plan9 differences
+ */
+char* commonuser(void);
+char* commonerror(void);
+
+/*
+ * chandial.c
+ */
+extern Chan* chandial(char*, char*, char*, Chan**);
+
+/*
+ * global to all of the stack
+ */
+extern void (*igmpreportfn)(Ipifc*, uchar*);
diff --git a/sys/src/9/ip/ipaux.c b/sys/src/9/ip/ipaux.c
new file mode 100755
index 000000000..75a4fd4f2
--- /dev/null
+++ b/sys/src/9/ip/ipaux.c
@@ -0,0 +1,368 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "ip.h"
+#include "ipv6.h"
+
+char *v6hdrtypes[Maxhdrtype] =
+{
+ [HBH] "HopbyHop",
+ [ICMP] "ICMP",
+ [IGMP] "IGMP",
+ [GGP] "GGP",
+ [IPINIP] "IP",
+ [ST] "ST",
+ [TCP] "TCP",
+ [UDP] "UDP",
+ [ISO_TP4] "ISO_TP4",
+ [RH] "Routinghdr",
+ [FH] "Fraghdr",
+ [IDRP] "IDRP",
+ [RSVP] "RSVP",
+ [AH] "Authhdr",
+ [ESP] "ESP",
+ [ICMPv6] "ICMPv6",
+ [NNH] "Nonexthdr",
+ [ISO_IP] "ISO_IP",
+ [IGRP] "IGRP",
+ [OSPF] "OSPF",
+};
+
+/*
+ * well known IPv6 addresses
+ */
+uchar v6Unspecified[IPaddrlen] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+uchar v6loopback[IPaddrlen] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0x01
+};
+
+uchar v6linklocal[IPaddrlen] = {
+ 0xfe, 0x80, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+uchar v6linklocalmask[IPaddrlen] = {
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+int v6llpreflen = 8; /* link-local prefix length in bytes */
+
+uchar v6multicast[IPaddrlen] = {
+ 0xff, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+uchar v6multicastmask[IPaddrlen] = {
+ 0xff, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+int v6mcpreflen = 1; /* multicast prefix length */
+
+uchar v6allnodesN[IPaddrlen] = {
+ 0xff, 0x01, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0x01
+};
+uchar v6allroutersN[IPaddrlen] = {
+ 0xff, 0x01, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0x02
+};
+uchar v6allnodesNmask[IPaddrlen] = {
+ 0xff, 0xff, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+int v6aNpreflen = 2; /* all nodes (N) prefix */
+
+uchar v6allnodesL[IPaddrlen] = {
+ 0xff, 0x02, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0x01
+};
+uchar v6allroutersL[IPaddrlen] = {
+ 0xff, 0x02, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0x02
+};
+uchar v6allnodesLmask[IPaddrlen] = {
+ 0xff, 0xff, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+int v6aLpreflen = 2; /* all nodes (L) prefix */
+
+uchar v6solicitednode[IPaddrlen] = {
+ 0xff, 0x02, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0x01,
+ 0xff, 0, 0, 0
+};
+uchar v6solicitednodemask[IPaddrlen] = {
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x0, 0x0, 0x0
+};
+int v6snpreflen = 13;
+
+ushort
+ptclcsum(Block *bp, int offset, int len)
+{
+ uchar *addr;
+ ulong losum, hisum;
+ ushort csum;
+ int odd, blocklen, x;
+
+ /* Correct to front of data area */
+ while(bp != nil && offset && offset >= BLEN(bp)) {
+ offset -= BLEN(bp);
+ bp = bp->next;
+ }
+ if(bp == nil)
+ return 0;
+
+ addr = bp->rp + offset;
+ blocklen = BLEN(bp) - offset;
+
+ if(bp->next == nil) {
+ if(blocklen < len)
+ len = blocklen;
+ return ~ptclbsum(addr, len) & 0xffff;
+ }
+
+ losum = 0;
+ hisum = 0;
+
+ odd = 0;
+ while(len) {
+ x = blocklen;
+ if(len < x)
+ x = len;
+
+ csum = ptclbsum(addr, x);
+ if(odd)
+ hisum += csum;
+ else
+ losum += csum;
+ odd = (odd+x) & 1;
+ len -= x;
+
+ bp = bp->next;
+ if(bp == nil)
+ break;
+ blocklen = BLEN(bp);
+ addr = bp->rp;
+ }
+
+ losum += hisum>>8;
+ losum += (hisum&0xff)<<8;
+ while((csum = losum>>16) != 0)
+ losum = csum + (losum & 0xffff);
+
+ return ~losum & 0xffff;
+}
+
+enum
+{
+ Isprefix= 16,
+};
+
+#define CLASS(p) ((*(uchar*)(p))>>6)
+
+void
+ipv62smcast(uchar *smcast, uchar *a)
+{
+ assert(IPaddrlen == 16);
+ memmove(smcast, v6solicitednode, IPaddrlen);
+ smcast[13] = a[13];
+ smcast[14] = a[14];
+ smcast[15] = a[15];
+}
+
+
+/*
+ * parse a hex mac address
+ */
+int
+parsemac(uchar *to, char *from, int len)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ memset(to, 0, len);
+ for(i = 0; i < len; i++){
+ if(p[0] == '\0' || p[1] == '\0')
+ break;
+
+ nip[0] = p[0];
+ nip[1] = p[1];
+ nip[2] = '\0';
+ p += 2;
+
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return i;
+}
+
+/*
+ * hashing tcp, udp, ... connections
+ */
+ulong
+iphash(uchar *sa, ushort sp, uchar *da, ushort dp)
+{
+ return ((sa[IPaddrlen-1]<<24) ^ (sp << 16) ^ (da[IPaddrlen-1]<<8) ^ dp ) % Nhash;
+}
+
+void
+iphtadd(Ipht *ht, Conv *c)
+{
+ ulong hv;
+ Iphash *h;
+
+ hv = iphash(c->raddr, c->rport, c->laddr, c->lport);
+ h = smalloc(sizeof(*h));
+ if(ipcmp(c->raddr, IPnoaddr) != 0)
+ h->match = IPmatchexact;
+ else {
+ if(ipcmp(c->laddr, IPnoaddr) != 0){
+ if(c->lport == 0)
+ h->match = IPmatchaddr;
+ else
+ h->match = IPmatchpa;
+ } else {
+ if(c->lport == 0)
+ h->match = IPmatchany;
+ else
+ h->match = IPmatchport;
+ }
+ }
+ h->c = c;
+
+ lock(ht);
+ h->next = ht->tab[hv];
+ ht->tab[hv] = h;
+ unlock(ht);
+}
+
+void
+iphtrem(Ipht *ht, Conv *c)
+{
+ ulong hv;
+ Iphash **l, *h;
+
+ hv = iphash(c->raddr, c->rport, c->laddr, c->lport);
+ lock(ht);
+ for(l = &ht->tab[hv]; (*l) != nil; l = &(*l)->next)
+ if((*l)->c == c){
+ h = *l;
+ (*l) = h->next;
+ free(h);
+ break;
+ }
+ unlock(ht);
+}
+
+/* look for a matching conversation with the following precedence
+ * connected && raddr,rport,laddr,lport
+ * announced && laddr,lport
+ * announced && *,lport
+ * announced && laddr,*
+ * announced && *,*
+ */
+Conv*
+iphtlook(Ipht *ht, uchar *sa, ushort sp, uchar *da, ushort dp)
+{
+ ulong hv;
+ Iphash *h;
+ Conv *c;
+
+ /* exact 4 pair match (connection) */
+ hv = iphash(sa, sp, da, dp);
+ lock(ht);
+ for(h = ht->tab[hv]; h != nil; h = h->next){
+ if(h->match != IPmatchexact)
+ continue;
+ c = h->c;
+ if(sp == c->rport && dp == c->lport
+ && ipcmp(sa, c->raddr) == 0 && ipcmp(da, c->laddr) == 0){
+ unlock(ht);
+ return c;
+ }
+ }
+
+ /* match local address and port */
+ hv = iphash(IPnoaddr, 0, da, dp);
+ for(h = ht->tab[hv]; h != nil; h = h->next){
+ if(h->match != IPmatchpa)
+ continue;
+ c = h->c;
+ if(dp == c->lport && ipcmp(da, c->laddr) == 0){
+ unlock(ht);
+ return c;
+ }
+ }
+
+ /* match just port */
+ hv = iphash(IPnoaddr, 0, IPnoaddr, dp);
+ for(h = ht->tab[hv]; h != nil; h = h->next){
+ if(h->match != IPmatchport)
+ continue;
+ c = h->c;
+ if(dp == c->lport){
+ unlock(ht);
+ return c;
+ }
+ }
+
+ /* match local address */
+ hv = iphash(IPnoaddr, 0, da, 0);
+ for(h = ht->tab[hv]; h != nil; h = h->next){
+ if(h->match != IPmatchaddr)
+ continue;
+ c = h->c;
+ if(ipcmp(da, c->laddr) == 0){
+ unlock(ht);
+ return c;
+ }
+ }
+
+ /* look for something that matches anything */
+ hv = iphash(IPnoaddr, 0, IPnoaddr, 0);
+ for(h = ht->tab[hv]; h != nil; h = h->next){
+ if(h->match != IPmatchany)
+ continue;
+ c = h->c;
+ unlock(ht);
+ return c;
+ }
+ unlock(ht);
+ return nil;
+}
diff --git a/sys/src/9/ip/ipifc.c b/sys/src/9/ip/ipifc.c
new file mode 100755
index 000000000..cbc349b01
--- /dev/null
+++ b/sys/src/9/ip/ipifc.c
@@ -0,0 +1,1660 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+#include "ipv6.h"
+
+#define DPRINT if(0)print
+
+enum {
+ Maxmedia = 32,
+ Nself = Maxmedia*5,
+ NHASH = 1<<6,
+ NCACHE = 256,
+ QMAX = 192*1024-1,
+};
+
+Medium *media[Maxmedia] = { 0 };
+
+/*
+ * cache of local addresses (addresses we answer to)
+ */
+struct Ipself
+{
+ uchar a[IPaddrlen];
+ Ipself *hnext; /* next address in the hash table */
+ Iplink *link; /* binding twixt Ipself and Ipifc */
+ ulong expire;
+ uchar type; /* type of address */
+ int ref;
+ Ipself *next; /* free list */
+};
+
+struct Ipselftab
+{
+ QLock;
+ int inited;
+ int acceptall; /* true if an interface has the null address */
+ Ipself *hash[NHASH]; /* hash chains */
+};
+
+/*
+ * Multicast addresses are chained onto a Chan so that
+ * we can remove them when the Chan is closed.
+ */
+typedef struct Ipmcast Ipmcast;
+struct Ipmcast
+{
+ Ipmcast *next;
+ uchar ma[IPaddrlen]; /* multicast address */
+ uchar ia[IPaddrlen]; /* interface address */
+};
+
+/* quick hash for ip addresses */
+#define hashipa(a) ( ( ((a)[IPaddrlen-2]<<8) | (a)[IPaddrlen-1] )%NHASH )
+
+static char tifc[] = "ifc ";
+
+static void addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type);
+static void remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a);
+static char* ipifcjoinmulti(Ipifc *ifc, char **argv, int argc);
+static char* ipifcleavemulti(Ipifc *ifc, char **argv, int argc);
+static void ipifcregisterproxy(Fs*, Ipifc*, uchar*);
+static char* ipifcremlifc(Ipifc*, Iplifc*);
+
+/*
+ * link in a new medium
+ */
+void
+addipmedium(Medium *med)
+{
+ int i;
+
+ for(i = 0; i < nelem(media)-1; i++)
+ if(media[i] == nil){
+ media[i] = med;
+ break;
+ }
+}
+
+/*
+ * find the medium with this name
+ */
+Medium*
+ipfindmedium(char *name)
+{
+ Medium **mp;
+
+ for(mp = media; *mp != nil; mp++)
+ if(strcmp((*mp)->name, name) == 0)
+ break;
+ return *mp;
+}
+
+/*
+ * attach a device (or pkt driver) to the interface.
+ * called with c locked
+ */
+static char*
+ipifcbind(Conv *c, char **argv, int argc)
+{
+ Ipifc *ifc;
+ Medium *m;
+
+ if(argc < 2)
+ return Ebadarg;
+
+ ifc = (Ipifc*)c->ptcl;
+
+ /* bind the device to the interface */
+ m = ipfindmedium(argv[1]);
+ if(m == nil)
+ return "unknown interface type";
+
+ wlock(ifc);
+ if(ifc->m != nil){
+ wunlock(ifc);
+ return "interface already bound";
+ }
+ if(waserror()){
+ wunlock(ifc);
+ nexterror();
+ }
+
+ /* do medium specific binding */
+ (*m->bind)(ifc, argc, argv);
+
+ /* set the bound device name */
+ if(argc > 2)
+ strncpy(ifc->dev, argv[2], sizeof(ifc->dev));
+ else
+ snprint(ifc->dev, sizeof ifc->dev, "%s%d", m->name, c->x);
+ ifc->dev[sizeof(ifc->dev)-1] = 0;
+
+ /* set up parameters */
+ ifc->m = m;
+ ifc->mintu = ifc->m->mintu;
+ ifc->maxtu = ifc->m->maxtu;
+ if(ifc->m->unbindonclose == 0)
+ ifc->conv->inuse++;
+ ifc->rp.mflag = 0; /* default not managed */
+ ifc->rp.oflag = 0;
+ ifc->rp.maxraint = 600000; /* millisecs */
+ ifc->rp.minraint = 200000;
+ ifc->rp.linkmtu = 0; /* no mtu sent */
+ ifc->rp.reachtime = 0;
+ ifc->rp.rxmitra = 0;
+ ifc->rp.ttl = MAXTTL;
+ ifc->rp.routerlt = 3 * ifc->rp.maxraint;
+
+ /* any ancillary structures (like routes) no longer pertain */
+ ifc->ifcid++;
+
+ /* reopen all the queues closed by a previous unbind */
+ qreopen(c->rq);
+ qreopen(c->eq);
+ qreopen(c->sq);
+
+ wunlock(ifc);
+ poperror();
+
+ return nil;
+}
+
+/*
+ * detach a device from an interface, close the interface
+ * called with ifc->conv closed
+ */
+static char*
+ipifcunbind(Ipifc *ifc)
+{
+ char *err;
+
+ if(waserror()){
+ wunlock(ifc);
+ nexterror();
+ }
+ wlock(ifc);
+
+ /* dissociate routes */
+ if(ifc->m != nil && ifc->m->unbindonclose == 0)
+ ifc->conv->inuse--;
+ ifc->ifcid++;
+
+ /* disassociate logical interfaces (before zeroing ifc->arg) */
+ while(ifc->lifc){
+ err = ipifcremlifc(ifc, ifc->lifc);
+ /*
+ * note: err non-zero means lifc not found,
+ * which can't happen in this case.
+ */
+ if(err)
+ error(err);
+ }
+
+ /* disassociate device */
+ if(ifc->m && ifc->m->unbind)
+ (*ifc->m->unbind)(ifc);
+ memset(ifc->dev, 0, sizeof(ifc->dev));
+ ifc->arg = nil;
+ ifc->reassemble = 0;
+
+ /* close queues to stop queuing of packets */
+ qclose(ifc->conv->rq);
+ qclose(ifc->conv->wq);
+ qclose(ifc->conv->sq);
+
+ ifc->m = nil;
+ wunlock(ifc);
+ poperror();
+ return nil;
+}
+
+char sfixedformat[] = "device %s maxtu %d sendra %d recvra %d mflag %d oflag"
+" %d maxraint %d minraint %d linkmtu %d reachtime %d rxmitra %d ttl %d routerlt"
+" %d pktin %lud pktout %lud errin %lud errout %lud\n";
+
+char slineformat[] = " %-40I %-10M %-40I %-12lud %-12lud\n";
+
+static int
+ipifcstate(Conv *c, char *state, int n)
+{
+ Ipifc *ifc;
+ Iplifc *lifc;
+ int m;
+
+ ifc = (Ipifc*)c->ptcl;
+ m = snprint(state, n, sfixedformat,
+ ifc->dev, ifc->maxtu, ifc->sendra6, ifc->recvra6,
+ ifc->rp.mflag, ifc->rp.oflag, ifc->rp.maxraint,
+ ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime,
+ ifc->rp.rxmitra, ifc->rp.ttl, ifc->rp.routerlt,
+ ifc->in, ifc->out, ifc->inerr, ifc->outerr);
+
+ rlock(ifc);
+ for(lifc = ifc->lifc; lifc && n > m; lifc = lifc->next)
+ m += snprint(state+m, n - m, slineformat, lifc->local,
+ lifc->mask, lifc->remote, lifc->validlt, lifc->preflt);
+ if(ifc->lifc == nil)
+ m += snprint(state+m, n - m, "\n");
+ runlock(ifc);
+ return m;
+}
+
+static int
+ipifclocal(Conv *c, char *state, int n)
+{
+ Ipifc *ifc;
+ Iplifc *lifc;
+ Iplink *link;
+ int m;
+
+ ifc = (Ipifc*)c->ptcl;
+ m = 0;
+
+ rlock(ifc);
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next){
+ m += snprint(state+m, n - m, "%-40.40I ->", lifc->local);
+ for(link = lifc->link; link; link = link->lifclink)
+ m += snprint(state+m, n - m, " %-40.40I", link->self->a);
+ m += snprint(state+m, n - m, "\n");
+ }
+ runlock(ifc);
+ return m;
+}
+
+static int
+ipifcinuse(Conv *c)
+{
+ Ipifc *ifc;
+
+ ifc = (Ipifc*)c->ptcl;
+ return ifc->m != nil;
+}
+
+/*
+ * called when a process writes to an interface's 'data'
+ */
+static void
+ipifckick(void *x)
+{
+ Conv *c = x;
+ Block *bp;
+ Ipifc *ifc;
+
+ bp = qget(c->wq);
+ if(bp == nil)
+ return;
+
+ ifc = (Ipifc*)c->ptcl;
+ if(!canrlock(ifc)){
+ freeb(bp);
+ return;
+ }
+ if(waserror()){
+ runlock(ifc);
+ nexterror();
+ }
+ if(ifc->m == nil || ifc->m->pktin == nil)
+ freeb(bp);
+ else
+ (*ifc->m->pktin)(c->p->f, ifc, bp);
+ runlock(ifc);
+ poperror();
+}
+
+/*
+ * called when a new ipifc structure is created
+ */
+static void
+ipifccreate(Conv *c)
+{
+ Ipifc *ifc;
+
+ c->rq = qopen(QMAX, 0, 0, 0);
+ c->sq = qopen(QMAX, 0, 0, 0);
+ c->wq = qopen(QMAX, Qkick, ipifckick, c);
+ ifc = (Ipifc*)c->ptcl;
+ ifc->conv = c;
+ ifc->unbinding = 0;
+ ifc->m = nil;
+ ifc->reassemble = 0;
+}
+
+/*
+ * called after last close of ipifc data or ctl
+ * called with c locked, we must unlock
+ */
+static void
+ipifcclose(Conv *c)
+{
+ Ipifc *ifc;
+ Medium *m;
+
+ ifc = (Ipifc*)c->ptcl;
+ m = ifc->m;
+ if(m && m->unbindonclose)
+ ipifcunbind(ifc);
+}
+
+/*
+ * change an interface's mtu
+ */
+char*
+ipifcsetmtu(Ipifc *ifc, char **argv, int argc)
+{
+ int mtu;
+
+ if(argc < 2 || ifc->m == nil)
+ return Ebadarg;
+ mtu = strtoul(argv[1], 0, 0);
+ if(mtu < ifc->m->mintu || mtu > ifc->m->maxtu)
+ return Ebadarg;
+ ifc->maxtu = mtu;
+ return nil;
+}
+
+/*
+ * add an address to an interface.
+ */
+char*
+ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp)
+{
+ int i, type, mtu, sendnbrdisc = 0;
+ uchar ip[IPaddrlen], mask[IPaddrlen], rem[IPaddrlen];
+ uchar bcast[IPaddrlen], net[IPaddrlen];
+ Iplifc *lifc, **l;
+ Fs *f;
+
+ if(ifc->m == nil)
+ return "ipifc not yet bound to device";
+
+ f = ifc->conv->p->f;
+
+ type = Rifc;
+ memset(ip, 0, IPaddrlen);
+ memset(mask, 0, IPaddrlen);
+ memset(rem, 0, IPaddrlen);
+ switch(argc){
+ case 6:
+ if(strcmp(argv[5], "proxy") == 0)
+ type |= Rproxy;
+ /* fall through */
+ case 5:
+ mtu = strtoul(argv[4], 0, 0);
+ if(mtu >= ifc->m->mintu && mtu <= ifc->m->maxtu)
+ ifc->maxtu = mtu;
+ /* fall through */
+ case 4:
+ if (parseip(ip, argv[1]) == -1 || parseip(rem, argv[3]) == -1)
+ return Ebadip;
+ parseipmask(mask, argv[2]);
+ maskip(rem, mask, net);
+ break;
+ case 3:
+ if (parseip(ip, argv[1]) == -1)
+ return Ebadip;
+ parseipmask(mask, argv[2]);
+ maskip(ip, mask, rem);
+ maskip(rem, mask, net);
+ break;
+ case 2:
+ if (parseip(ip, argv[1]) == -1)
+ return Ebadip;
+ memmove(mask, defmask(ip), IPaddrlen);
+ maskip(ip, mask, rem);
+ maskip(rem, mask, net);
+ break;
+ default:
+ return Ebadarg;
+ }
+ if(isv4(ip))
+ tentative = 0;
+ wlock(ifc);
+
+ /* ignore if this is already a local address for this ifc */
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next) {
+ if(ipcmp(lifc->local, ip) == 0) {
+ if(lifc->tentative != tentative)
+ lifc->tentative = tentative;
+ if(lifcp) {
+ lifc->onlink = lifcp->onlink;
+ lifc->autoflag = lifcp->autoflag;
+ lifc->validlt = lifcp->validlt;
+ lifc->preflt = lifcp->preflt;
+ lifc->origint = lifcp->origint;
+ }
+ goto out;
+ }
+ }
+
+ /* add the address to the list of logical ifc's for this ifc */
+ lifc = smalloc(sizeof(Iplifc));
+ ipmove(lifc->local, ip);
+ ipmove(lifc->mask, mask);
+ ipmove(lifc->remote, rem);
+ ipmove(lifc->net, net);
+ lifc->tentative = tentative;
+ if(lifcp) {
+ lifc->onlink = lifcp->onlink;
+ lifc->autoflag = lifcp->autoflag;
+ lifc->validlt = lifcp->validlt;
+ lifc->preflt = lifcp->preflt;
+ lifc->origint = lifcp->origint;
+ } else { /* default values */
+ lifc->onlink = lifc->autoflag = 1;
+ lifc->validlt = lifc->preflt = ~0L;
+ lifc->origint = NOW / 1000;
+ }
+ lifc->next = nil;
+
+ for(l = &ifc->lifc; *l; l = &(*l)->next)
+ ;
+ *l = lifc;
+
+ /* check for point-to-point interface */
+ if(ipcmp(ip, v6loopback)) /* skip v6 loopback, it's a special address */
+ if(ipcmp(mask, IPallbits) == 0)
+ type |= Rptpt;
+
+ /* add local routes */
+ if(isv4(ip))
+ v4addroute(f, tifc, rem+IPv4off, mask+IPv4off, rem+IPv4off, type);
+ else
+ v6addroute(f, tifc, rem, mask, rem, type);
+
+ addselfcache(f, ifc, lifc, ip, Runi);
+
+ if((type & (Rproxy|Rptpt)) == (Rproxy|Rptpt)){
+ ipifcregisterproxy(f, ifc, rem);
+ goto out;
+ }
+
+ if(isv4(ip) || ipcmp(ip, IPnoaddr) == 0) {
+ /* add subnet directed broadcast address to the self cache */
+ for(i = 0; i < IPaddrlen; i++)
+ bcast[i] = (ip[i] & mask[i]) | ~mask[i];
+ addselfcache(f, ifc, lifc, bcast, Rbcast);
+
+ /* add subnet directed network address to the self cache */
+ for(i = 0; i < IPaddrlen; i++)
+ bcast[i] = (ip[i] & mask[i]) & mask[i];
+ addselfcache(f, ifc, lifc, bcast, Rbcast);
+
+ /* add network directed broadcast address to the self cache */
+ memmove(mask, defmask(ip), IPaddrlen);
+ for(i = 0; i < IPaddrlen; i++)
+ bcast[i] = (ip[i] & mask[i]) | ~mask[i];
+ addselfcache(f, ifc, lifc, bcast, Rbcast);
+
+ /* add network directed network address to the self cache */
+ memmove(mask, defmask(ip), IPaddrlen);
+ for(i = 0; i < IPaddrlen; i++)
+ bcast[i] = (ip[i] & mask[i]) & mask[i];
+ addselfcache(f, ifc, lifc, bcast, Rbcast);
+
+ addselfcache(f, ifc, lifc, IPv4bcast, Rbcast);
+ }
+ else {
+ if(ipcmp(ip, v6loopback) == 0) {
+ /* add node-local mcast address */
+ addselfcache(f, ifc, lifc, v6allnodesN, Rmulti);
+
+ /* add route for all node multicast */
+ v6addroute(f, tifc, v6allnodesN, v6allnodesNmask,
+ v6allnodesN, Rmulti);
+ }
+
+ /* add all nodes multicast address */
+ addselfcache(f, ifc, lifc, v6allnodesL, Rmulti);
+
+ /* add route for all nodes multicast */
+ v6addroute(f, tifc, v6allnodesL, v6allnodesLmask, v6allnodesL,
+ Rmulti);
+
+ /* add solicited-node multicast address */
+ ipv62smcast(bcast, ip);
+ addselfcache(f, ifc, lifc, bcast, Rmulti);
+
+ sendnbrdisc = 1;
+ }
+
+ /* register the address on this network for address resolution */
+ if(isv4(ip) && ifc->m->areg != nil)
+ (*ifc->m->areg)(ifc, ip);
+
+out:
+ wunlock(ifc);
+ if(tentative && sendnbrdisc)
+ icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac);
+ return nil;
+}
+
+/*
+ * remove a logical interface from an ifc
+ * always called with ifc wlock'd
+ */
+static char*
+ipifcremlifc(Ipifc *ifc, Iplifc *lifc)
+{
+ Iplifc **l;
+ Fs *f;
+
+ f = ifc->conv->p->f;
+
+ /*
+ * find address on this interface and remove from chain.
+ * for pt to pt we actually specify the remote address as the
+ * addresss to remove.
+ */
+ for(l = &ifc->lifc; *l != nil && *l != lifc; l = &(*l)->next)
+ ;
+ if(*l == nil)
+ return "address not on this interface";
+ *l = lifc->next;
+
+ /* disassociate any addresses */
+ while(lifc->link)
+ remselfcache(f, ifc, lifc, lifc->link->self->a);
+
+ /* remove the route for this logical interface */
+ if(isv4(lifc->local))
+ v4delroute(f, lifc->remote+IPv4off, lifc->mask+IPv4off, 1);
+ else {
+ v6delroute(f, lifc->remote, lifc->mask, 1);
+ if(ipcmp(lifc->local, v6loopback) == 0)
+ /* remove route for all node multicast */
+ v6delroute(f, v6allnodesN, v6allnodesNmask, 1);
+ else if(memcmp(lifc->local, v6linklocal, v6llpreflen) == 0)
+ /* remove route for all link multicast */
+ v6delroute(f, v6allnodesL, v6allnodesLmask, 1);
+ }
+
+ free(lifc);
+ return nil;
+}
+
+/*
+ * remove an address from an interface.
+ * called with c->car locked
+ */
+char*
+ipifcrem(Ipifc *ifc, char **argv, int argc)
+{
+ char *rv;
+ uchar ip[IPaddrlen], mask[IPaddrlen], rem[IPaddrlen];
+ Iplifc *lifc;
+
+ if(argc < 3)
+ return Ebadarg;
+
+ if (parseip(ip, argv[1]) == -1)
+ return Ebadip;
+ parseipmask(mask, argv[2]);
+ if(argc < 4)
+ maskip(ip, mask, rem);
+ else
+ if (parseip(rem, argv[3]) == -1)
+ return Ebadip;
+
+ wlock(ifc);
+
+ /*
+ * find address on this interface and remove from chain.
+ * for pt to pt we actually specify the remote address as the
+ * addresss to remove.
+ */
+ for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next) {
+ if (memcmp(ip, lifc->local, IPaddrlen) == 0
+ && memcmp(mask, lifc->mask, IPaddrlen) == 0
+ && memcmp(rem, lifc->remote, IPaddrlen) == 0)
+ break;
+ }
+
+ rv = ipifcremlifc(ifc, lifc);
+ wunlock(ifc);
+ return rv;
+}
+
+/*
+ * distribute routes to active interfaces like the
+ * TRIP linecards
+ */
+void
+ipifcaddroute(Fs *f, int vers, uchar *addr, uchar *mask, uchar *gate, int type)
+{
+ Medium *m;
+ Conv **cp, **e;
+ Ipifc *ifc;
+
+ e = &f->ipifc->conv[f->ipifc->nc];
+ for(cp = f->ipifc->conv; cp < e; cp++){
+ if(*cp != nil) {
+ ifc = (Ipifc*)(*cp)->ptcl;
+ m = ifc->m;
+ if(m && m->addroute)
+ m->addroute(ifc, vers, addr, mask, gate, type);
+ }
+ }
+}
+
+void
+ipifcremroute(Fs *f, int vers, uchar *addr, uchar *mask)
+{
+ Medium *m;
+ Conv **cp, **e;
+ Ipifc *ifc;
+
+ e = &f->ipifc->conv[f->ipifc->nc];
+ for(cp = f->ipifc->conv; cp < e; cp++){
+ if(*cp != nil) {
+ ifc = (Ipifc*)(*cp)->ptcl;
+ m = ifc->m;
+ if(m && m->remroute)
+ m->remroute(ifc, vers, addr, mask);
+ }
+ }
+}
+
+/*
+ * associate an address with the interface. This wipes out any previous
+ * addresses. This is a macro that means, remove all the old interfaces
+ * and add a new one.
+ */
+static char*
+ipifcconnect(Conv* c, char **argv, int argc)
+{
+ char *err;
+ Ipifc *ifc;
+
+ ifc = (Ipifc*)c->ptcl;
+
+ if(ifc->m == nil)
+ return "ipifc not yet bound to device";
+
+ if(waserror()){
+ wunlock(ifc);
+ nexterror();
+ }
+ wlock(ifc);
+ while(ifc->lifc){
+ err = ipifcremlifc(ifc, ifc->lifc);
+ if(err)
+ error(err);
+ }
+ wunlock(ifc);
+ poperror();
+
+ err = ipifcadd(ifc, argv, argc, 0, nil);
+ if(err)
+ return err;
+
+ Fsconnected(c, nil);
+ return nil;
+}
+
+char*
+ipifcra6(Ipifc *ifc, char **argv, int argc)
+{
+ int i, argsleft, vmax = ifc->rp.maxraint, vmin = ifc->rp.minraint;
+
+ argsleft = argc - 1;
+ i = 1;
+
+ if(argsleft % 2 != 0)
+ return Ebadarg;
+
+ while (argsleft > 1) {
+ if(strcmp(argv[i], "recvra") == 0)
+ ifc->recvra6 = (atoi(argv[i+1]) != 0);
+ else if(strcmp(argv[i], "sendra") == 0)
+ ifc->sendra6 = (atoi(argv[i+1]) != 0);
+ else if(strcmp(argv[i], "mflag") == 0)
+ ifc->rp.mflag = (atoi(argv[i+1]) != 0);
+ else if(strcmp(argv[i], "oflag") == 0)
+ ifc->rp.oflag = (atoi(argv[i+1]) != 0);
+ else if(strcmp(argv[i], "maxraint") == 0)
+ ifc->rp.maxraint = atoi(argv[i+1]);
+ else if(strcmp(argv[i], "minraint") == 0)
+ ifc->rp.minraint = atoi(argv[i+1]);
+ else if(strcmp(argv[i], "linkmtu") == 0)
+ ifc->rp.linkmtu = atoi(argv[i+1]);
+ else if(strcmp(argv[i], "reachtime") == 0)
+ ifc->rp.reachtime = atoi(argv[i+1]);
+ else if(strcmp(argv[i], "rxmitra") == 0)
+ ifc->rp.rxmitra = atoi(argv[i+1]);
+ else if(strcmp(argv[i], "ttl") == 0)
+ ifc->rp.ttl = atoi(argv[i+1]);
+ else if(strcmp(argv[i], "routerlt") == 0)
+ ifc->rp.routerlt = atoi(argv[i+1]);
+ else
+ return Ebadarg;
+
+ argsleft -= 2;
+ i += 2;
+ }
+
+ /* consistency check */
+ if(ifc->rp.maxraint < ifc->rp.minraint) {
+ ifc->rp.maxraint = vmax;
+ ifc->rp.minraint = vmin;
+ return Ebadarg;
+ }
+ return nil;
+}
+
+/*
+ * non-standard control messages.
+ * called with c->car locked.
+ */
+static char*
+ipifcctl(Conv* c, char**argv, int argc)
+{
+ Ipifc *ifc;
+ int i;
+
+ ifc = (Ipifc*)c->ptcl;
+ if(strcmp(argv[0], "add") == 0)
+ return ipifcadd(ifc, argv, argc, 0, nil);
+ else if(strcmp(argv[0], "try") == 0)
+ return ipifcadd(ifc, argv, argc, 1, nil);
+ else if(strcmp(argv[0], "remove") == 0)
+ return ipifcrem(ifc, argv, argc);
+ else if(strcmp(argv[0], "unbind") == 0)
+ return ipifcunbind(ifc);
+ else if(strcmp(argv[0], "joinmulti") == 0)
+ return ipifcjoinmulti(ifc, argv, argc);
+ else if(strcmp(argv[0], "leavemulti") == 0)
+ return ipifcleavemulti(ifc, argv, argc);
+ else if(strcmp(argv[0], "mtu") == 0)
+ return ipifcsetmtu(ifc, argv, argc);
+ else if(strcmp(argv[0], "reassemble") == 0){
+ ifc->reassemble = 1;
+ return nil;
+ }
+ else if(strcmp(argv[0], "iprouting") == 0){
+ i = 1;
+ if(argc > 1)
+ i = atoi(argv[1]);
+ iprouting(c->p->f, i);
+ return nil;
+ }
+ else if(strcmp(argv[0], "add6") == 0)
+ return ipifcadd6(ifc, argv, argc);
+ else if(strcmp(argv[0], "ra6") == 0)
+ return ipifcra6(ifc, argv, argc);
+ return "unsupported ctl";
+}
+
+int
+ipifcstats(Proto *ipifc, char *buf, int len)
+{
+ return ipstats(ipifc->f, buf, len);
+}
+
+void
+ipifcinit(Fs *f)
+{
+ Proto *ipifc;
+
+ ipifc = smalloc(sizeof(Proto));
+ ipifc->name = "ipifc";
+ ipifc->connect = ipifcconnect;
+ ipifc->announce = nil;
+ ipifc->bind = ipifcbind;
+ ipifc->state = ipifcstate;
+ ipifc->create = ipifccreate;
+ ipifc->close = ipifcclose;
+ ipifc->rcv = nil;
+ ipifc->ctl = ipifcctl;
+ ipifc->advise = nil;
+ ipifc->stats = ipifcstats;
+ ipifc->inuse = ipifcinuse;
+ ipifc->local = ipifclocal;
+ ipifc->ipproto = -1;
+ ipifc->nc = Maxmedia;
+ ipifc->ptclsize = sizeof(Ipifc);
+
+ f->ipifc = ipifc; /* hack for ipifcremroute, findipifc, ... */
+ f->self = smalloc(sizeof(Ipselftab)); /* hack for ipforme */
+
+ Fsproto(f, ipifc);
+}
+
+/*
+ * add to self routing cache
+ * called with c->car locked
+ */
+static void
+addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type)
+{
+ Ipself *p;
+ Iplink *lp;
+ int h;
+
+ qlock(f->self);
+
+ /* see if the address already exists */
+ h = hashipa(a);
+ for(p = f->self->hash[h]; p; p = p->next)
+ if(memcmp(a, p->a, IPaddrlen) == 0)
+ break;
+
+ /* allocate a local address and add to hash chain */
+ if(p == nil){
+ p = smalloc(sizeof(*p));
+ ipmove(p->a, a);
+ p->type = type;
+ p->next = f->self->hash[h];
+ f->self->hash[h] = p;
+
+ /* if the null address, accept all packets */
+ if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)
+ f->self->acceptall = 1;
+ }
+
+ /* look for a link for this lifc */
+ for(lp = p->link; lp; lp = lp->selflink)
+ if(lp->lifc == lifc)
+ break;
+
+ /* allocate a lifc-to-local link and link to both */
+ if(lp == nil){
+ lp = smalloc(sizeof(*lp));
+ lp->ref = 1;
+ lp->lifc = lifc;
+ lp->self = p;
+ lp->selflink = p->link;
+ p->link = lp;
+ lp->lifclink = lifc->link;
+ lifc->link = lp;
+
+ /* add to routing table */
+ if(isv4(a))
+ v4addroute(f, tifc, a+IPv4off, IPallbits+IPv4off,
+ a+IPv4off, type);
+ else
+ v6addroute(f, tifc, a, IPallbits, a, type);
+
+ if((type & Rmulti) && ifc->m->addmulti != nil)
+ (*ifc->m->addmulti)(ifc, a, lifc->local);
+ } else
+ lp->ref++;
+
+ qunlock(f->self);
+}
+
+/*
+ * These structures are unlinked from their chains while
+ * other threads may be using them. To avoid excessive locking,
+ * just put them aside for a while before freeing them.
+ * called with f->self locked
+ */
+static Iplink *freeiplink;
+static Ipself *freeipself;
+
+static void
+iplinkfree(Iplink *p)
+{
+ Iplink **l, *np;
+ ulong now = NOW;
+
+ l = &freeiplink;
+ for(np = *l; np; np = *l){
+ if(np->expire > now){
+ *l = np->next;
+ free(np);
+ continue;
+ }
+ l = &np->next;
+ }
+ p->expire = now + 5000; /* give other threads 5 secs to get out */
+ p->next = nil;
+ *l = p;
+}
+
+static void
+ipselffree(Ipself *p)
+{
+ Ipself **l, *np;
+ ulong now = NOW;
+
+ l = &freeipself;
+ for(np = *l; np; np = *l){
+ if(np->expire > now){
+ *l = np->next;
+ free(np);
+ continue;
+ }
+ l = &np->next;
+ }
+ p->expire = now + 5000; /* give other threads 5 secs to get out */
+ p->next = nil;
+ *l = p;
+}
+
+/*
+ * Decrement reference for this address on this link.
+ * Unlink from selftab if this is the last ref.
+ * called with c->car locked
+ */
+static void
+remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a)
+{
+ Ipself *p, **l;
+ Iplink *link, **l_self, **l_lifc;
+
+ qlock(f->self);
+
+ /* find the unique selftab entry */
+ l = &f->self->hash[hashipa(a)];
+ for(p = *l; p; p = *l){
+ if(ipcmp(p->a, a) == 0)
+ break;
+ l = &p->next;
+ }
+
+ if(p == nil)
+ goto out;
+
+ /*
+ * walk down links from an ifc looking for one
+ * that matches the selftab entry
+ */
+ l_lifc = &lifc->link;
+ for(link = *l_lifc; link; link = *l_lifc){
+ if(link->self == p)
+ break;
+ l_lifc = &link->lifclink;
+ }
+
+ if(link == nil)
+ goto out;
+
+ /*
+ * walk down the links from the selftab looking for
+ * the one we just found
+ */
+ l_self = &p->link;
+ for(link = *l_self; link; link = *l_self){
+ if(link == *l_lifc)
+ break;
+ l_self = &link->selflink;
+ }
+
+ if(link == nil)
+ panic("remselfcache");
+
+ if(--(link->ref) != 0)
+ goto out;
+
+ if((p->type & Rmulti) && ifc->m->remmulti != nil)
+ (*ifc->m->remmulti)(ifc, a, lifc->local);
+
+ /* ref == 0, remove from both chains and free the link */
+ *l_lifc = link->lifclink;
+ *l_self = link->selflink;
+ iplinkfree(link);
+
+ if(p->link != nil)
+ goto out;
+
+ /* remove from routing table */
+ if(isv4(a))
+ v4delroute(f, a+IPv4off, IPallbits+IPv4off, 1);
+ else
+ v6delroute(f, a, IPallbits, 1);
+
+ /* no more links, remove from hash and free */
+ *l = p->next;
+ ipselffree(p);
+
+ /* if IPnoaddr, forget */
+ if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)
+ f->self->acceptall = 0;
+
+out:
+ qunlock(f->self);
+}
+
+static char *stformat = "%-44.44I %2.2d %4.4s\n";
+enum
+{
+ Nstformat= 41,
+};
+
+long
+ipselftabread(Fs *f, char *cp, ulong offset, int n)
+{
+ int i, m, nifc, off;
+ Ipself *p;
+ Iplink *link;
+ char state[8];
+
+ m = 0;
+ off = offset;
+ qlock(f->self);
+ for(i = 0; i < NHASH && m < n; i++){
+ for(p = f->self->hash[i]; p != nil && m < n; p = p->next){
+ nifc = 0;
+ for(link = p->link; link; link = link->selflink)
+ nifc++;
+ routetype(p->type, state);
+ m += snprint(cp + m, n - m, stformat, p->a, nifc, state);
+ if(off > 0){
+ off -= m;
+ m = 0;
+ }
+ }
+ }
+ qunlock(f->self);
+ return m;
+}
+
+int
+iptentative(Fs *f, uchar *addr)
+{
+ Ipself *p;
+
+ p = f->self->hash[hashipa(addr)];
+ for(; p; p = p->next){
+ if(ipcmp(addr, p->a) == 0)
+ return p->link->lifc->tentative;
+ }
+ return 0;
+}
+
+/*
+ * returns
+ * 0 - no match
+ * Runi
+ * Rbcast
+ * Rmcast
+ */
+int
+ipforme(Fs *f, uchar *addr)
+{
+ Ipself *p;
+
+ p = f->self->hash[hashipa(addr)];
+ for(; p; p = p->next){
+ if(ipcmp(addr, p->a) == 0)
+ return p->type;
+ }
+
+ /* hack to say accept anything */
+ if(f->self->acceptall)
+ return Runi;
+ return 0;
+}
+
+/*
+ * find the ifc on same net as the remote system. If none,
+ * return nil.
+ */
+Ipifc*
+findipifc(Fs *f, uchar *remote, int type)
+{
+ Ipifc *ifc, *x;
+ Iplifc *lifc;
+ Conv **cp, **e;
+ uchar gnet[IPaddrlen], xmask[IPaddrlen];
+
+ x = nil;
+ memset(xmask, 0, IPaddrlen);
+
+ /* find most specific match */
+ e = &f->ipifc->conv[f->ipifc->nc];
+ for(cp = f->ipifc->conv; cp < e; cp++){
+ if(*cp == 0)
+ continue;
+ ifc = (Ipifc*)(*cp)->ptcl;
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next){
+ maskip(remote, lifc->mask, gnet);
+ if(ipcmp(gnet, lifc->net) == 0){
+ if(x == nil || ipcmp(lifc->mask, xmask) > 0){
+ x = ifc;
+ ipmove(xmask, lifc->mask);
+ }
+ }
+ }
+ }
+ if(x != nil)
+ return x;
+
+ /* for now for broadcast and multicast, just use first interface */
+ if(type & (Rbcast|Rmulti)){
+ for(cp = f->ipifc->conv; cp < e; cp++){
+ if(*cp == 0)
+ continue;
+ ifc = (Ipifc*)(*cp)->ptcl;
+ if(ifc->lifc != nil)
+ return ifc;
+ }
+ }
+ return nil;
+}
+
+enum {
+ unknownv6, /* UGH */
+// multicastv6,
+ unspecifiedv6,
+ linklocalv6,
+ globalv6,
+};
+
+int
+v6addrtype(uchar *addr)
+{
+ if(isv4(addr) || ipcmp(addr, IPnoaddr) == 0)
+ return unknownv6;
+ else if(islinklocal(addr) ||
+ isv6mcast(addr) && (addr[1] & 0xF) <= Link_local_scop)
+ return linklocalv6;
+ else
+ return globalv6;
+}
+
+#define v6addrcurr(lifc) ((lifc)->preflt == ~0L || \
+ (lifc)->origint + (lifc)->preflt >= NOW/1000)
+
+static void
+findprimaryipv6(Fs *f, uchar *local)
+{
+ int atype, atypel;
+ Conv **cp, **e;
+ Ipifc *ifc;
+ Iplifc *lifc;
+
+ ipmove(local, v6Unspecified);
+ atype = unspecifiedv6;
+
+ /*
+ * find "best" (global > link local > unspecified)
+ * local address; address must be current.
+ */
+ e = &f->ipifc->conv[f->ipifc->nc];
+ for(cp = f->ipifc->conv; cp < e; cp++){
+ if(*cp == 0)
+ continue;
+ ifc = (Ipifc*)(*cp)->ptcl;
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next){
+ atypel = v6addrtype(lifc->local);
+ if(atypel > atype && v6addrcurr(lifc)) {
+ ipmove(local, lifc->local);
+ atype = atypel;
+ if(atype == globalv6)
+ return;
+ }
+ }
+ }
+}
+
+/*
+ * returns first ip address configured
+ */
+static void
+findprimaryipv4(Fs *f, uchar *local)
+{
+ Conv **cp, **e;
+ Ipifc *ifc;
+ Iplifc *lifc;
+
+ /* find first ifc local address */
+ e = &f->ipifc->conv[f->ipifc->nc];
+ for(cp = f->ipifc->conv; cp < e; cp++){
+ if(*cp == 0)
+ continue;
+ ifc = (Ipifc*)(*cp)->ptcl;
+ if((lifc = ifc->lifc) != nil){
+ ipmove(local, lifc->local);
+ return;
+ }
+ }
+}
+
+/*
+ * find the local address 'closest' to the remote system, copy it to
+ * local and return the ifc for that address
+ */
+void
+findlocalip(Fs *f, uchar *local, uchar *remote)
+{
+ int version, atype = unspecifiedv6, atypel = unknownv6;
+ int atyper, deprecated;
+ uchar gate[IPaddrlen], gnet[IPaddrlen];
+ Ipifc *ifc;
+ Iplifc *lifc;
+ Route *r;
+
+ USED(atype);
+ USED(atypel);
+ qlock(f->ipifc);
+ r = v6lookup(f, remote, nil);
+ version = (memcmp(remote, v4prefix, IPv4off) == 0)? V4: V6;
+
+ if(r != nil){
+ ifc = r->ifc;
+ if(r->type & Rv4)
+ v4tov6(gate, r->v4.gate);
+ else {
+ ipmove(gate, r->v6.gate);
+ ipmove(local, v6Unspecified);
+ }
+
+ switch(version) {
+ case V4:
+ /* find ifc address closest to the gateway to use */
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next){
+ maskip(gate, lifc->mask, gnet);
+ if(ipcmp(gnet, lifc->net) == 0){
+ ipmove(local, lifc->local);
+ goto out;
+ }
+ }
+ break;
+ case V6:
+ /* find ifc address with scope matching the destination */
+ atyper = v6addrtype(remote);
+ deprecated = 0;
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next){
+ atypel = v6addrtype(lifc->local);
+ /* prefer appropriate scope */
+ if(atypel > atype && atype < atyper ||
+ atypel < atype && atype > atyper){
+ ipmove(local, lifc->local);
+ deprecated = !v6addrcurr(lifc);
+ atype = atypel;
+ } else if(atypel == atype){
+ /* avoid deprecated addresses */
+ if(deprecated && v6addrcurr(lifc)){
+ ipmove(local, lifc->local);
+ atype = atypel;
+ deprecated = 0;
+ }
+ }
+ if(atype == atyper && !deprecated)
+ goto out;
+ }
+ if(atype >= atyper)
+ goto out;
+ break;
+ default:
+ panic("findlocalip: version %d", version);
+ }
+ }
+
+ switch(version){
+ case V4:
+ findprimaryipv4(f, local);
+ break;
+ case V6:
+ findprimaryipv6(f, local);
+ break;
+ default:
+ panic("findlocalip2: version %d", version);
+ }
+
+out:
+ qunlock(f->ipifc);
+}
+
+/*
+ * return first v4 address associated with an interface
+ */
+int
+ipv4local(Ipifc *ifc, uchar *addr)
+{
+ Iplifc *lifc;
+
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next){
+ if(isv4(lifc->local)){
+ memmove(addr, lifc->local+IPv4off, IPv4addrlen);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * return first v6 address associated with an interface
+ */
+int
+ipv6local(Ipifc *ifc, uchar *addr)
+{
+ Iplifc *lifc;
+
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next){
+ if(!isv4(lifc->local) && !(lifc->tentative)){
+ ipmove(addr, lifc->local);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+ipv6anylocal(Ipifc *ifc, uchar *addr)
+{
+ Iplifc *lifc;
+
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next){
+ if(!isv4(lifc->local)){
+ ipmove(addr, lifc->local);
+ return SRC_UNI;
+ }
+ }
+ return SRC_UNSPEC;
+}
+
+/*
+ * see if this address is bound to the interface
+ */
+Iplifc*
+iplocalonifc(Ipifc *ifc, uchar *ip)
+{
+ Iplifc *lifc;
+
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next)
+ if(ipcmp(ip, lifc->local) == 0)
+ return lifc;
+ return nil;
+}
+
+
+/*
+ * See if we're proxying for this address on this interface
+ */
+int
+ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip)
+{
+ Route *r;
+ uchar net[IPaddrlen];
+ Iplifc *lifc;
+
+ /* see if this is a direct connected pt to pt address */
+ r = v6lookup(f, ip, nil);
+ if(r == nil || (r->type & (Rifc|Rproxy)) != (Rifc|Rproxy))
+ return 0;
+
+ /* see if this is on the right interface */
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next){
+ maskip(ip, lifc->mask, net);
+ if(ipcmp(net, lifc->remote) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * return multicast version if any
+ */
+int
+ipismulticast(uchar *ip)
+{
+ if(isv4(ip)){
+ if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
+ return V4;
+ }
+ else if(ip[0] == 0xff)
+ return V6;
+ return 0;
+}
+int
+ipisbm(uchar *ip)
+{
+ if(isv4(ip)){
+ if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
+ return V4;
+ else if(ipcmp(ip, IPv4bcast) == 0)
+ return V4;
+ }
+ else if(ip[0] == 0xff)
+ return V6;
+ return 0;
+}
+
+
+/*
+ * add a multicast address to an interface, called with c->car locked
+ */
+void
+ipifcaddmulti(Conv *c, uchar *ma, uchar *ia)
+{
+ Ipifc *ifc;
+ Iplifc *lifc;
+ Conv **p;
+ Ipmulti *multi, **l;
+ Fs *f;
+
+ f = c->p->f;
+
+ for(l = &c->multi; *l; l = &(*l)->next)
+ if(ipcmp(ma, (*l)->ma) == 0 && ipcmp(ia, (*l)->ia) == 0)
+ return; /* it's already there */
+
+ multi = *l = smalloc(sizeof(*multi));
+ ipmove(multi->ma, ma);
+ ipmove(multi->ia, ia);
+ multi->next = nil;
+
+ for(p = f->ipifc->conv; *p; p++){
+ if((*p)->inuse == 0)
+ continue;
+ ifc = (Ipifc*)(*p)->ptcl;
+ if(waserror()){
+ wunlock(ifc);
+ nexterror();
+ }
+ wlock(ifc);
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next)
+ if(ipcmp(ia, lifc->local) == 0)
+ addselfcache(f, ifc, lifc, ma, Rmulti);
+ wunlock(ifc);
+ poperror();
+ }
+}
+
+
+/*
+ * remove a multicast address from an interface, called with c->car locked
+ */
+void
+ipifcremmulti(Conv *c, uchar *ma, uchar *ia)
+{
+ Ipmulti *multi, **l;
+ Iplifc *lifc;
+ Conv **p;
+ Ipifc *ifc;
+ Fs *f;
+
+ f = c->p->f;
+
+ for(l = &c->multi; *l; l = &(*l)->next)
+ if(ipcmp(ma, (*l)->ma) == 0 && ipcmp(ia, (*l)->ia) == 0)
+ break;
+
+ multi = *l;
+ if(multi == nil)
+ return; /* we don't have it open */
+
+ *l = multi->next;
+
+ for(p = f->ipifc->conv; *p; p++){
+ if((*p)->inuse == 0)
+ continue;
+
+ ifc = (Ipifc*)(*p)->ptcl;
+ if(waserror()){
+ wunlock(ifc);
+ nexterror();
+ }
+ wlock(ifc);
+ for(lifc = ifc->lifc; lifc; lifc = lifc->next)
+ if(ipcmp(ia, lifc->local) == 0)
+ remselfcache(f, ifc, lifc, ma);
+ wunlock(ifc);
+ poperror();
+ }
+
+ free(multi);
+}
+
+/*
+ * make lifc's join and leave multicast groups
+ */
+static char*
+ipifcjoinmulti(Ipifc *ifc, char **argv, int argc)
+{
+ USED(ifc, argv, argc);
+ return nil;
+}
+
+static char*
+ipifcleavemulti(Ipifc *ifc, char **argv, int argc)
+{
+ USED(ifc, argv, argc);
+ return nil;
+}
+
+static void
+ipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip)
+{
+ Conv **cp, **e;
+ Ipifc *nifc;
+ Iplifc *lifc;
+ Medium *m;
+ uchar net[IPaddrlen];
+
+ /* register the address on any network that will proxy for us */
+ e = &f->ipifc->conv[f->ipifc->nc];
+
+ if(!isv4(ip)) { /* V6 */
+ for(cp = f->ipifc->conv; cp < e; cp++){
+ if(*cp == nil || (nifc = (Ipifc*)(*cp)->ptcl) == ifc)
+ continue;
+ rlock(nifc);
+ m = nifc->m;
+ if(m == nil || m->addmulti == nil) {
+ runlock(nifc);
+ continue;
+ }
+ for(lifc = nifc->lifc; lifc; lifc = lifc->next){
+ maskip(ip, lifc->mask, net);
+ if(ipcmp(net, lifc->remote) == 0) {
+ /* add solicited-node multicast addr */
+ ipv62smcast(net, ip);
+ addselfcache(f, nifc, lifc, net, Rmulti);
+ arpenter(f, V6, ip, nifc->mac, 6, 0);
+ // (*m->addmulti)(nifc, net, ip);
+ break;
+ }
+ }
+ runlock(nifc);
+ }
+ }
+ else { /* V4 */
+ for(cp = f->ipifc->conv; cp < e; cp++){
+ if(*cp == nil || (nifc = (Ipifc*)(*cp)->ptcl) == ifc)
+ continue;
+ rlock(nifc);
+ m = nifc->m;
+ if(m == nil || m->areg == nil){
+ runlock(nifc);
+ continue;
+ }
+ for(lifc = nifc->lifc; lifc; lifc = lifc->next){
+ maskip(ip, lifc->mask, net);
+ if(ipcmp(net, lifc->remote) == 0){
+ (*m->areg)(nifc, ip);
+ break;
+ }
+ }
+ runlock(nifc);
+ }
+ }
+}
+
+
+/* added for new v6 mesg types */
+static void
+adddefroute6(Fs *f, uchar *gate, int force)
+{
+ Route *r;
+
+ r = v6lookup(f, v6Unspecified, nil);
+ /*
+ * route entries generated by all other means take precedence
+ * over router announcements.
+ */
+ if (r && !force && strcmp(r->tag, "ra") != 0)
+ return;
+
+ v6delroute(f, v6Unspecified, v6Unspecified, 1);
+ v6addroute(f, "ra", v6Unspecified, v6Unspecified, gate, 0);
+}
+
+enum {
+ Ngates = 3,
+};
+
+char*
+ipifcadd6(Ipifc *ifc, char**argv, int argc)
+{
+ int plen = 64;
+ long origint = NOW / 1000, preflt = ~0L, validlt = ~0L;
+ char addr[40], preflen[6];
+ char *params[3];
+ uchar autoflag = 1, onlink = 1;
+ uchar prefix[IPaddrlen];
+ Iplifc *lifc;
+
+ switch(argc) {
+ case 7:
+ preflt = atoi(argv[6]);
+ /* fall through */
+ case 6:
+ validlt = atoi(argv[5]);
+ /* fall through */
+ case 5:
+ autoflag = atoi(argv[4]);
+ /* fall through */
+ case 4:
+ onlink = atoi(argv[3]);
+ /* fall through */
+ case 3:
+ plen = atoi(argv[2]);
+ /* fall through */
+ case 2:
+ break;
+ default:
+ return Ebadarg;
+ }
+
+ if (parseip(prefix, argv[1]) != 6 || validlt < preflt || plen < 0 ||
+ plen > 64 || islinklocal(prefix))
+ return Ebadarg;
+
+ lifc = smalloc(sizeof(Iplifc));
+ lifc->onlink = (onlink != 0);
+ lifc->autoflag = (autoflag != 0);
+ lifc->validlt = validlt;
+ lifc->preflt = preflt;
+ lifc->origint = origint;
+
+ /* issue "add" ctl msg for v6 link-local addr and prefix len */
+ if(!ifc->m->pref2addr)
+ return Ebadarg;
+ ifc->m->pref2addr(prefix, ifc->mac); /* mac → v6 link-local addr */
+ sprint(addr, "%I", prefix);
+ sprint(preflen, "/%d", plen);
+ params[0] = "add";
+ params[1] = addr;
+ params[2] = preflen;
+
+ return ipifcadd(ifc, params, 3, 0, lifc);
+}
diff --git a/sys/src/9/ip/ipmux.c b/sys/src/9/ip/ipmux.c
new file mode 100755
index 000000000..d8fb35225
--- /dev/null
+++ b/sys/src/9/ip/ipmux.c
@@ -0,0 +1,840 @@
+/*
+ * IP packet filter
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+#include "ipv6.h"
+
+typedef struct Ipmuxrock Ipmuxrock;
+typedef struct Ipmux Ipmux;
+
+typedef struct Myip4hdr Myip4hdr;
+struct Myip4hdr
+{
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* ip->identification */
+ uchar frag[2]; /* Fragment information */
+ uchar ttl; /* Time to live */
+ uchar proto; /* Protocol */
+ uchar cksum[2]; /* Header checksum */
+ uchar src[4]; /* IP source */
+ uchar dst[4]; /* IP destination */
+
+ uchar data[1]; /* start of data */
+};
+Myip4hdr *ipoff = 0;
+
+enum
+{
+ Tproto,
+ Tdata,
+ Tiph,
+ Tdst,
+ Tsrc,
+ Tifc,
+
+ Cother = 0,
+ Cbyte, /* single byte */
+ Cmbyte, /* single byte with mask */
+ Cshort, /* single short */
+ Cmshort, /* single short with mask */
+ Clong, /* single long */
+ Cmlong, /* single long with mask */
+ Cifc,
+ Cmifc,
+};
+
+char *ftname[] =
+{
+[Tproto] "proto",
+[Tdata] "data",
+[Tiph] "iph",
+[Tdst] "dst",
+[Tsrc] "src",
+[Tifc] "ifc",
+};
+
+/*
+ * a node in the decision tree
+ */
+struct Ipmux
+{
+ Ipmux *yes;
+ Ipmux *no;
+ uchar type; /* type of field(Txxxx) */
+ uchar ctype; /* tupe of comparison(Cxxxx) */
+ uchar len; /* length in bytes of item to compare */
+ uchar n; /* number of items val points to */
+ short off; /* offset of comparison */
+ short eoff; /* end offset of comparison */
+ uchar skiphdr; /* should offset start after ipheader */
+ uchar *val;
+ uchar *mask;
+ uchar *e; /* val+n*len*/
+
+ int ref; /* so we can garbage collect */
+ Conv *conv;
+};
+
+/*
+ * someplace to hold per conversation data
+ */
+struct Ipmuxrock
+{
+ Ipmux *chain;
+};
+
+static int ipmuxsprint(Ipmux*, int, char*, int);
+static void ipmuxkick(void *x);
+
+static char*
+skipwhite(char *p)
+{
+ while(*p == ' ' || *p == '\t')
+ p++;
+ return p;
+}
+
+static char*
+follows(char *p, char c)
+{
+ char *f;
+
+ f = strchr(p, c);
+ if(f == nil)
+ return nil;
+ *f++ = 0;
+ f = skipwhite(f);
+ if(*f == 0)
+ return nil;
+ return f;
+}
+
+static Ipmux*
+parseop(char **pp)
+{
+ char *p = *pp;
+ int type, off, end, len;
+ Ipmux *f;
+
+ p = skipwhite(p);
+ if(strncmp(p, "dst", 3) == 0){
+ type = Tdst;
+ off = (ulong)(ipoff->dst);
+ len = IPv4addrlen;
+ p += 3;
+ }
+ else if(strncmp(p, "src", 3) == 0){
+ type = Tsrc;
+ off = (ulong)(ipoff->src);
+ len = IPv4addrlen;
+ p += 3;
+ }
+ else if(strncmp(p, "ifc", 3) == 0){
+ type = Tifc;
+ off = -IPv4addrlen;
+ len = IPv4addrlen;
+ p += 3;
+ }
+ else if(strncmp(p, "proto", 5) == 0){
+ type = Tproto;
+ off = (ulong)&(ipoff->proto);
+ len = 1;
+ p += 5;
+ }
+ else if(strncmp(p, "data", 4) == 0 || strncmp(p, "iph", 3) == 0){
+ if(strncmp(p, "data", 4) == 0) {
+ type = Tdata;
+ p += 4;
+ }
+ else {
+ type = Tiph;
+ p += 3;
+ }
+ p = skipwhite(p);
+ if(*p != '[')
+ return nil;
+ p++;
+ off = strtoul(p, &p, 0);
+ if(off < 0 || off > (64-IP4HDR))
+ return nil;
+ p = skipwhite(p);
+ if(*p != ':')
+ end = off;
+ else {
+ p++;
+ p = skipwhite(p);
+ end = strtoul(p, &p, 0);
+ if(end < off)
+ return nil;
+ p = skipwhite(p);
+ }
+ if(*p != ']')
+ return nil;
+ p++;
+ len = end - off + 1;
+ }
+ else
+ return nil;
+
+ f = smalloc(sizeof(*f));
+ f->type = type;
+ f->len = len;
+ f->off = off;
+ f->val = nil;
+ f->mask = nil;
+ f->n = 1;
+ f->ref = 1;
+ if(type == Tdata)
+ f->skiphdr = 1;
+ else
+ f->skiphdr = 0;
+
+ return f;
+}
+
+static int
+htoi(char x)
+{
+ if(x >= '0' && x <= '9')
+ x -= '0';
+ else if(x >= 'a' && x <= 'f')
+ x -= 'a' - 10;
+ else if(x >= 'A' && x <= 'F')
+ x -= 'A' - 10;
+ else
+ x = 0;
+ return x;
+}
+
+static int
+hextoi(char *p)
+{
+ return (htoi(p[0])<<4) | htoi(p[1]);
+}
+
+static void
+parseval(uchar *v, char *p, int len)
+{
+ while(*p && len-- > 0){
+ *v++ = hextoi(p);
+ p += 2;
+ }
+}
+
+static Ipmux*
+parsemux(char *p)
+{
+ int n, nomask;
+ Ipmux *f;
+ char *val;
+ char *mask;
+ char *vals[20];
+ uchar *v;
+
+ /* parse operand */
+ f = parseop(&p);
+ if(f == nil)
+ return nil;
+
+ /* find value */
+ val = follows(p, '=');
+ if(val == nil)
+ goto parseerror;
+
+ /* parse mask */
+ mask = follows(p, '&');
+ if(mask != nil){
+ switch(f->type){
+ case Tsrc:
+ case Tdst:
+ case Tifc:
+ f->mask = smalloc(f->len);
+ v4parseip(f->mask, mask);
+ break;
+ case Tdata:
+ case Tiph:
+ f->mask = smalloc(f->len);
+ parseval(f->mask, mask, f->len);
+ break;
+ default:
+ goto parseerror;
+ }
+ nomask = 0;
+ } else {
+ nomask = 1;
+ f->mask = smalloc(f->len);
+ memset(f->mask, 0xff, f->len);
+ }
+
+ /* parse vals */
+ f->n = getfields(val, vals, sizeof(vals)/sizeof(char*), 1, "|");
+ if(f->n == 0)
+ goto parseerror;
+ f->val = smalloc(f->n*f->len);
+ v = f->val;
+ for(n = 0; n < f->n; n++){
+ switch(f->type){
+ case Tsrc:
+ case Tdst:
+ case Tifc:
+ v4parseip(v, vals[n]);
+ break;
+ case Tproto:
+ case Tdata:
+ case Tiph:
+ parseval(v, vals[n], f->len);
+ break;
+ }
+ v += f->len;
+ }
+
+ f->eoff = f->off + f->len;
+ f->e = f->val + f->n*f->len;
+ f->ctype = Cother;
+ if(f->n == 1){
+ switch(f->len){
+ case 1:
+ f->ctype = nomask ? Cbyte : Cmbyte;
+ break;
+ case 2:
+ f->ctype = nomask ? Cshort : Cmshort;
+ break;
+ case 4:
+ if(f->type == Tifc)
+ f->ctype = nomask ? Cifc : Cmifc;
+ else
+ f->ctype = nomask ? Clong : Cmlong;
+ break;
+ }
+ }
+ return f;
+
+parseerror:
+ if(f->mask)
+ free(f->mask);
+ if(f->val)
+ free(f->val);
+ free(f);
+ return nil;
+}
+
+/*
+ * Compare relative ordering of two ipmuxs. This doesn't compare the
+ * values, just the fields being looked at.
+ *
+ * returns: <0 if a is a more specific match
+ * 0 if a and b are matching on the same fields
+ * >0 if b is a more specific match
+ */
+static int
+ipmuxcmp(Ipmux *a, Ipmux *b)
+{
+ int n;
+
+ /* compare types, lesser ones are more important */
+ n = a->type - b->type;
+ if(n != 0)
+ return n;
+
+ /* compare offsets, call earlier ones more specific */
+ n = (a->off+((int)a->skiphdr)*(ulong)ipoff->data) -
+ (b->off+((int)b->skiphdr)*(ulong)ipoff->data);
+ if(n != 0)
+ return n;
+
+ /* compare match lengths, longer ones are more specific */
+ n = b->len - a->len;
+ if(n != 0)
+ return n;
+
+ /*
+ * if we get here we have two entries matching
+ * the same bytes of the record. Now check
+ * the mask for equality. Longer masks are
+ * more specific.
+ */
+ if(a->mask != nil && b->mask == nil)
+ return -1;
+ if(a->mask == nil && b->mask != nil)
+ return 1;
+ if(a->mask != nil && b->mask != nil){
+ n = memcmp(b->mask, a->mask, a->len);
+ if(n != 0)
+ return n;
+ }
+ return 0;
+}
+
+/*
+ * Compare the values of two ipmuxs. We're assuming that ipmuxcmp
+ * returned 0 comparing them.
+ */
+static int
+ipmuxvalcmp(Ipmux *a, Ipmux *b)
+{
+ int n;
+
+ n = b->len*b->n - a->len*a->n;
+ if(n != 0)
+ return n;
+ return memcmp(a->val, b->val, a->len*a->n);
+}
+
+/*
+ * add onto an existing ipmux chain in the canonical comparison
+ * order
+ */
+static void
+ipmuxchain(Ipmux **l, Ipmux *f)
+{
+ for(; *l; l = &(*l)->yes)
+ if(ipmuxcmp(f, *l) < 0)
+ break;
+ f->yes = *l;
+ *l = f;
+}
+
+/*
+ * copy a tree
+ */
+static Ipmux*
+ipmuxcopy(Ipmux *f)
+{
+ Ipmux *nf;
+
+ if(f == nil)
+ return nil;
+ nf = smalloc(sizeof *nf);
+ *nf = *f;
+ nf->no = ipmuxcopy(f->no);
+ nf->yes = ipmuxcopy(f->yes);
+ nf->val = smalloc(f->n*f->len);
+ nf->e = nf->val + f->len*f->n;
+ memmove(nf->val, f->val, f->n*f->len);
+ return nf;
+}
+
+static void
+ipmuxfree(Ipmux *f)
+{
+ if(f->val != nil)
+ free(f->val);
+ free(f);
+}
+
+static void
+ipmuxtreefree(Ipmux *f)
+{
+ if(f == nil)
+ return;
+ if(f->no != nil)
+ ipmuxfree(f->no);
+ if(f->yes != nil)
+ ipmuxfree(f->yes);
+ ipmuxfree(f);
+}
+
+/*
+ * merge two trees
+ */
+static Ipmux*
+ipmuxmerge(Ipmux *a, Ipmux *b)
+{
+ int n;
+ Ipmux *f;
+
+ if(a == nil)
+ return b;
+ if(b == nil)
+ return a;
+ n = ipmuxcmp(a, b);
+ if(n < 0){
+ f = ipmuxcopy(b);
+ a->yes = ipmuxmerge(a->yes, b);
+ a->no = ipmuxmerge(a->no, f);
+ return a;
+ }
+ if(n > 0){
+ f = ipmuxcopy(a);
+ b->yes = ipmuxmerge(b->yes, a);
+ b->no = ipmuxmerge(b->no, f);
+ return b;
+ }
+ if(ipmuxvalcmp(a, b) == 0){
+ a->yes = ipmuxmerge(a->yes, b->yes);
+ a->no = ipmuxmerge(a->no, b->no);
+ a->ref++;
+ ipmuxfree(b);
+ return a;
+ }
+ a->no = ipmuxmerge(a->no, b);
+ return a;
+}
+
+/*
+ * remove a chain from a demux tree. This is like merging accept that
+ * we remove instead of insert.
+ */
+static int
+ipmuxremove(Ipmux **l, Ipmux *f)
+{
+ int n, rv;
+ Ipmux *ft;
+
+ if(f == nil)
+ return 0; /* we've removed it all */
+ if(*l == nil)
+ return -1;
+
+ ft = *l;
+ n = ipmuxcmp(ft, f);
+ if(n < 0){
+ /* *l is maching an earlier field, descend both paths */
+ rv = ipmuxremove(&ft->yes, f);
+ rv += ipmuxremove(&ft->no, f);
+ return rv;
+ }
+ if(n > 0){
+ /* f represents an earlier field than *l, this should be impossible */
+ return -1;
+ }
+
+ /* if we get here f and *l are comparing the same fields */
+ if(ipmuxvalcmp(ft, f) != 0){
+ /* different values mean mutually exclusive */
+ return ipmuxremove(&ft->no, f);
+ }
+
+ /* we found a match */
+ if(--(ft->ref) == 0){
+ /*
+ * a dead node implies the whole yes side is also dead.
+ * since our chain is constrained to be on that side,
+ * we're done.
+ */
+ ipmuxtreefree(ft->yes);
+ *l = ft->no;
+ ipmuxfree(ft);
+ return 0;
+ }
+
+ /*
+ * free the rest of the chain. it is constrained to match the
+ * yes side.
+ */
+ return ipmuxremove(&ft->yes, f->yes);
+}
+
+/*
+ * connection request is a semi separated list of filters
+ * e.g. proto=17;data[0:4]=11aa22bb;ifc=135.104.9.2&255.255.255.0
+ *
+ * there's no protection against overlapping specs.
+ */
+static char*
+ipmuxconnect(Conv *c, char **argv, int argc)
+{
+ int i, n;
+ char *field[10];
+ Ipmux *mux, *chain;
+ Ipmuxrock *r;
+ Fs *f;
+
+ f = c->p->f;
+
+ if(argc != 2)
+ return Ebadarg;
+
+ n = getfields(argv[1], field, nelem(field), 1, ";");
+ if(n <= 0)
+ return Ebadarg;
+
+ chain = nil;
+ mux = nil;
+ for(i = 0; i < n; i++){
+ mux = parsemux(field[i]);
+ if(mux == nil){
+ ipmuxtreefree(chain);
+ return Ebadarg;
+ }
+ ipmuxchain(&chain, mux);
+ }
+ if(chain == nil)
+ return Ebadarg;
+ mux->conv = c;
+
+ /* save a copy of the chain so we can later remove it */
+ mux = ipmuxcopy(chain);
+ r = (Ipmuxrock*)(c->ptcl);
+ r->chain = chain;
+
+ /* add the chain to the protocol demultiplexor tree */
+ wlock(f);
+ f->ipmux->priv = ipmuxmerge(f->ipmux->priv, mux);
+ wunlock(f);
+
+ Fsconnected(c, nil);
+ return nil;
+}
+
+static int
+ipmuxstate(Conv *c, char *state, int n)
+{
+ Ipmuxrock *r;
+
+ r = (Ipmuxrock*)(c->ptcl);
+ return ipmuxsprint(r->chain, 0, state, n);
+}
+
+static void
+ipmuxcreate(Conv *c)
+{
+ Ipmuxrock *r;
+
+ c->rq = qopen(64*1024, Qmsg, 0, c);
+ c->wq = qopen(64*1024, Qkick, ipmuxkick, c);
+ r = (Ipmuxrock*)(c->ptcl);
+ r->chain = nil;
+}
+
+static char*
+ipmuxannounce(Conv*, char**, int)
+{
+ return "ipmux does not support announce";
+}
+
+static void
+ipmuxclose(Conv *c)
+{
+ Ipmuxrock *r;
+ Fs *f = c->p->f;
+
+ r = (Ipmuxrock*)(c->ptcl);
+
+ qclose(c->rq);
+ qclose(c->wq);
+ qclose(c->eq);
+ ipmove(c->laddr, IPnoaddr);
+ ipmove(c->raddr, IPnoaddr);
+ c->lport = 0;
+ c->rport = 0;
+
+ wlock(f);
+ ipmuxremove(&(c->p->priv), r->chain);
+ wunlock(f);
+ ipmuxtreefree(r->chain);
+ r->chain = nil;
+}
+
+/*
+ * takes a fully formed ip packet and just passes it down
+ * the stack
+ */
+static void
+ipmuxkick(void *x)
+{
+ Conv *c = x;
+ Block *bp;
+
+ bp = qget(c->wq);
+ if(bp != nil) {
+ Myip4hdr *ih4 = (Myip4hdr*)(bp->rp);
+
+ if((ih4->vihl & 0xF0) != IP_VER6)
+ ipoput4(c->p->f, bp, 0, ih4->ttl, ih4->tos, nil);
+ else
+ ipoput6(c->p->f, bp, 0, ((Ip6hdr*)ih4)->ttl, 0, nil);
+ }
+}
+
+static void
+ipmuxiput(Proto *p, Ipifc *ifc, Block *bp)
+{
+ int len, hl;
+ Fs *f = p->f;
+ uchar *m, *h, *v, *e, *ve, *hp;
+ Conv *c;
+ Ipmux *mux;
+ Myip4hdr *ip;
+ Ip6hdr *ip6;
+
+ ip = (Myip4hdr*)bp->rp;
+ hl = (ip->vihl&0x0F)<<2;
+
+ if(p->priv == nil)
+ goto nomatch;
+
+ h = bp->rp;
+ len = BLEN(bp);
+
+ /* run the v4 filter */
+ rlock(f);
+ c = nil;
+ mux = f->ipmux->priv;
+ while(mux != nil){
+ if(mux->eoff > len){
+ mux = mux->no;
+ continue;
+ }
+ hp = h + mux->off + ((int)mux->skiphdr)*hl;
+ switch(mux->ctype){
+ case Cbyte:
+ if(*mux->val == *hp)
+ goto yes;
+ break;
+ case Cmbyte:
+ if((*hp & *mux->mask) == *mux->val)
+ goto yes;
+ break;
+ case Cshort:
+ if(*((ushort*)mux->val) == *(ushort*)hp)
+ goto yes;
+ break;
+ case Cmshort:
+ if((*(ushort*)hp & (*((ushort*)mux->mask))) == *((ushort*)mux->val))
+ goto yes;
+ break;
+ case Clong:
+ if(*((ulong*)mux->val) == *(ulong*)hp)
+ goto yes;
+ break;
+ case Cmlong:
+ if((*(ulong*)hp & (*((ulong*)mux->mask))) == *((ulong*)mux->val))
+ goto yes;
+ break;
+ case Cifc:
+ if(*((ulong*)mux->val) == *(ulong*)(ifc->lifc->local + IPv4off))
+ goto yes;
+ break;
+ case Cmifc:
+ if((*(ulong*)(ifc->lifc->local + IPv4off) & (*((ulong*)mux->mask))) == *((ulong*)mux->val))
+ goto yes;
+ break;
+ default:
+ v = mux->val;
+ for(e = mux->e; v < e; v = ve){
+ m = mux->mask;
+ hp = h + mux->off;
+ for(ve = v + mux->len; v < ve; v++){
+ if((*hp++ & *m++) != *v)
+ break;
+ }
+ if(v == ve)
+ goto yes;
+ }
+ }
+ mux = mux->no;
+ continue;
+yes:
+ if(mux->conv != nil)
+ c = mux->conv;
+ mux = mux->yes;
+ }
+ runlock(f);
+
+ if(c != nil){
+ /* tack on interface address */
+ bp = padblock(bp, IPaddrlen);
+ ipmove(bp->rp, ifc->lifc->local);
+ bp = concatblock(bp);
+ if(bp != nil)
+ if(qpass(c->rq, bp) < 0)
+ print("Q");
+ return;
+ }
+
+nomatch:
+ /* doesn't match any filter, hand it to the specific protocol handler */
+ ip = (Myip4hdr*)bp->rp;
+ if((ip->vihl & 0xF0) == IP_VER4) {
+ p = f->t2p[ip->proto];
+ } else {
+ ip6 = (Ip6hdr*)bp->rp;
+ p = f->t2p[ip6->proto];
+ }
+ if(p && p->rcv)
+ (*p->rcv)(p, ifc, bp);
+ else
+ freeblist(bp);
+ return;
+}
+
+static int
+ipmuxsprint(Ipmux *mux, int level, char *buf, int len)
+{
+ int i, j, n;
+ uchar *v;
+
+ n = 0;
+ for(i = 0; i < level; i++)
+ n += snprint(buf+n, len-n, " ");
+ if(mux == nil){
+ n += snprint(buf+n, len-n, "\n");
+ return n;
+ }
+ n += snprint(buf+n, len-n, "h[%d:%d]&",
+ mux->off+((int)mux->skiphdr)*((int)ipoff->data),
+ mux->off+(((int)mux->skiphdr)*((int)ipoff->data))+mux->len-1);
+ for(i = 0; i < mux->len; i++)
+ n += snprint(buf+n, len - n, "%2.2ux", mux->mask[i]);
+ n += snprint(buf+n, len-n, "=");
+ v = mux->val;
+ for(j = 0; j < mux->n; j++){
+ for(i = 0; i < mux->len; i++)
+ n += snprint(buf+n, len - n, "%2.2ux", *v++);
+ n += snprint(buf+n, len-n, "|");
+ }
+ n += snprint(buf+n, len-n, "\n");
+ level++;
+ n += ipmuxsprint(mux->no, level, buf+n, len-n);
+ n += ipmuxsprint(mux->yes, level, buf+n, len-n);
+ return n;
+}
+
+static int
+ipmuxstats(Proto *p, char *buf, int len)
+{
+ int n;
+ Fs *f = p->f;
+
+ rlock(f);
+ n = ipmuxsprint(p->priv, 0, buf, len);
+ runlock(f);
+
+ return n;
+}
+
+void
+ipmuxinit(Fs *f)
+{
+ Proto *ipmux;
+
+ ipmux = smalloc(sizeof(Proto));
+ ipmux->priv = nil;
+ ipmux->name = "ipmux";
+ ipmux->connect = ipmuxconnect;
+ ipmux->announce = ipmuxannounce;
+ ipmux->state = ipmuxstate;
+ ipmux->create = ipmuxcreate;
+ ipmux->close = ipmuxclose;
+ ipmux->rcv = ipmuxiput;
+ ipmux->ctl = nil;
+ ipmux->advise = nil;
+ ipmux->stats = ipmuxstats;
+ ipmux->ipproto = -1;
+ ipmux->nc = 64;
+ ipmux->ptclsize = sizeof(Ipmuxrock);
+
+ f->ipmux = ipmux; /* hack for Fsrcvpcol */
+
+ Fsproto(f, ipmux);
+}
diff --git a/sys/src/9/ip/iproute.c b/sys/src/9/ip/iproute.c
new file mode 100755
index 000000000..53e3da988
--- /dev/null
+++ b/sys/src/9/ip/iproute.c
@@ -0,0 +1,854 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+
+static void walkadd(Fs*, Route**, Route*);
+static void addnode(Fs*, Route**, Route*);
+static void calcd(Route*);
+
+/* these are used for all instances of IP */
+static Route* v4freelist;
+static Route* v6freelist;
+static RWlock routelock;
+static ulong v4routegeneration, v6routegeneration;
+
+static void
+freeroute(Route *r)
+{
+ Route **l;
+
+ r->left = nil;
+ r->right = nil;
+ if(r->type & Rv4)
+ l = &v4freelist;
+ else
+ l = &v6freelist;
+ r->mid = *l;
+ *l = r;
+}
+
+static Route*
+allocroute(int type)
+{
+ Route *r;
+ int n;
+ Route **l;
+
+ if(type & Rv4){
+ n = sizeof(RouteTree) + sizeof(V4route);
+ l = &v4freelist;
+ } else {
+ n = sizeof(RouteTree) + sizeof(V6route);
+ l = &v6freelist;
+ }
+
+ r = *l;
+ if(r != nil){
+ *l = r->mid;
+ } else {
+ r = malloc(n);
+ if(r == nil)
+ panic("out of routing nodes");
+ }
+ memset(r, 0, n);
+ r->type = type;
+ r->ifc = nil;
+ r->ref = 1;
+
+ return r;
+}
+
+static void
+addqueue(Route **q, Route *r)
+{
+ Route *l;
+
+ if(r == nil)
+ return;
+
+ l = allocroute(r->type);
+ l->mid = *q;
+ *q = l;
+ l->left = r;
+}
+
+/*
+ * compare 2 v6 addresses
+ */
+static int
+lcmp(ulong *a, ulong *b)
+{
+ int i;
+
+ for(i = 0; i < IPllen; i++){
+ if(a[i] > b[i])
+ return 1;
+ if(a[i] < b[i])
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * compare 2 v4 or v6 ranges
+ */
+enum
+{
+ Rpreceeds,
+ Rfollows,
+ Requals,
+ Rcontains,
+ Rcontained,
+};
+
+static int
+rangecompare(Route *a, Route *b)
+{
+ if(a->type & Rv4){
+ if(a->v4.endaddress < b->v4.address)
+ return Rpreceeds;
+
+ if(a->v4.address > b->v4.endaddress)
+ return Rfollows;
+
+ if(a->v4.address <= b->v4.address
+ && a->v4.endaddress >= b->v4.endaddress){
+ if(a->v4.address == b->v4.address
+ && a->v4.endaddress == b->v4.endaddress)
+ return Requals;
+ return Rcontains;
+ }
+ return Rcontained;
+ }
+
+ if(lcmp(a->v6.endaddress, b->v6.address) < 0)
+ return Rpreceeds;
+
+ if(lcmp(a->v6.address, b->v6.endaddress) > 0)
+ return Rfollows;
+
+ if(lcmp(a->v6.address, b->v6.address) <= 0
+ && lcmp(a->v6.endaddress, b->v6.endaddress) >= 0){
+ if(lcmp(a->v6.address, b->v6.address) == 0
+ && lcmp(a->v6.endaddress, b->v6.endaddress) == 0)
+ return Requals;
+ return Rcontains;
+ }
+
+ return Rcontained;
+}
+
+static void
+copygate(Route *old, Route *new)
+{
+ if(new->type & Rv4)
+ memmove(old->v4.gate, new->v4.gate, IPv4addrlen);
+ else
+ memmove(old->v6.gate, new->v6.gate, IPaddrlen);
+}
+
+/*
+ * walk down a tree adding nodes back in
+ */
+static void
+walkadd(Fs *f, Route **root, Route *p)
+{
+ Route *l, *r;
+
+ l = p->left;
+ r = p->right;
+ p->left = 0;
+ p->right = 0;
+ addnode(f, root, p);
+ if(l)
+ walkadd(f, root, l);
+ if(r)
+ walkadd(f, root, r);
+}
+
+/*
+ * calculate depth
+ */
+static void
+calcd(Route *p)
+{
+ Route *q;
+ int d;
+
+ if(p) {
+ d = 0;
+ q = p->left;
+ if(q)
+ d = q->depth;
+ q = p->right;
+ if(q && q->depth > d)
+ d = q->depth;
+ q = p->mid;
+ if(q && q->depth > d)
+ d = q->depth;
+ p->depth = d+1;
+ }
+}
+
+/*
+ * balance the tree at the current node
+ */
+static void
+balancetree(Route **cur)
+{
+ Route *p, *l, *r;
+ int dl, dr;
+
+ /*
+ * if left and right are
+ * too out of balance,
+ * rotate tree node
+ */
+ p = *cur;
+ dl = 0; if(l = p->left) dl = l->depth;
+ dr = 0; if(r = p->right) dr = r->depth;
+
+ if(dl > dr+1) {
+ p->left = l->right;
+ l->right = p;
+ *cur = l;
+ calcd(p);
+ calcd(l);
+ } else
+ if(dr > dl+1) {
+ p->right = r->left;
+ r->left = p;
+ *cur = r;
+ calcd(p);
+ calcd(r);
+ } else
+ calcd(p);
+}
+
+/*
+ * add a new node to the tree
+ */
+static void
+addnode(Fs *f, Route **cur, Route *new)
+{
+ Route *p;
+
+ p = *cur;
+ if(p == 0) {
+ *cur = new;
+ new->depth = 1;
+ return;
+ }
+
+ switch(rangecompare(new, p)){
+ case Rpreceeds:
+ addnode(f, &p->left, new);
+ break;
+ case Rfollows:
+ addnode(f, &p->right, new);
+ break;
+ case Rcontains:
+ /*
+ * if new node is superset
+ * of tree node,
+ * replace tree node and
+ * queue tree node to be
+ * merged into root.
+ */
+ *cur = new;
+ new->depth = 1;
+ addqueue(&f->queue, p);
+ break;
+ case Requals:
+ /*
+ * supercede the old entry if the old one isn't
+ * a local interface.
+ */
+ if((p->type & Rifc) == 0){
+ p->type = new->type;
+ p->ifcid = -1;
+ copygate(p, new);
+ } else if(new->type & Rifc)
+ p->ref++;
+ freeroute(new);
+ break;
+ case Rcontained:
+ addnode(f, &p->mid, new);
+ break;
+ }
+
+ balancetree(cur);
+}
+
+#define V4H(a) ((a&0x07ffffff)>>(32-Lroot-5))
+
+void
+v4addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type)
+{
+ Route *p;
+ ulong sa;
+ ulong m;
+ ulong ea;
+ int h, eh;
+
+ m = nhgetl(mask);
+ sa = nhgetl(a) & m;
+ ea = sa | ~m;
+
+ eh = V4H(ea);
+ for(h=V4H(sa); h<=eh; h++) {
+ p = allocroute(Rv4 | type);
+ p->v4.address = sa;
+ p->v4.endaddress = ea;
+ memmove(p->v4.gate, gate, sizeof(p->v4.gate));
+ memmove(p->tag, tag, sizeof(p->tag));
+
+ wlock(&routelock);
+ addnode(f, &f->v4root[h], p);
+ while(p = f->queue) {
+ f->queue = p->mid;
+ walkadd(f, &f->v4root[h], p->left);
+ freeroute(p);
+ }
+ wunlock(&routelock);
+ }
+ v4routegeneration++;
+
+ ipifcaddroute(f, Rv4, a, mask, gate, type);
+}
+
+#define V6H(a) (((a)[IPllen-1] & 0x07ffffff)>>(32-Lroot-5))
+#define ISDFLT(a, mask, tag) ((ipcmp((a),v6Unspecified)==0) && (ipcmp((mask),v6Unspecified)==0) && (strcmp((tag), "ra")!=0))
+
+void
+v6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type)
+{
+ Route *p;
+ ulong sa[IPllen], ea[IPllen];
+ ulong x, y;
+ int h, eh;
+
+ /*
+ if(ISDFLT(a, mask, tag))
+ f->v6p->cdrouter = -1;
+ */
+
+
+ for(h = 0; h < IPllen; h++){
+ x = nhgetl(a+4*h);
+ y = nhgetl(mask+4*h);
+ sa[h] = x & y;
+ ea[h] = x | ~y;
+ }
+
+ eh = V6H(ea);
+ for(h = V6H(sa); h <= eh; h++) {
+ p = allocroute(type);
+ memmove(p->v6.address, sa, IPaddrlen);
+ memmove(p->v6.endaddress, ea, IPaddrlen);
+ memmove(p->v6.gate, gate, IPaddrlen);
+ memmove(p->tag, tag, sizeof(p->tag));
+
+ wlock(&routelock);
+ addnode(f, &f->v6root[h], p);
+ while(p = f->queue) {
+ f->queue = p->mid;
+ walkadd(f, &f->v6root[h], p->left);
+ freeroute(p);
+ }
+ wunlock(&routelock);
+ }
+ v6routegeneration++;
+
+ ipifcaddroute(f, 0, a, mask, gate, type);
+}
+
+Route**
+looknode(Route **cur, Route *r)
+{
+ Route *p;
+
+ for(;;){
+ p = *cur;
+ if(p == 0)
+ return 0;
+
+ switch(rangecompare(r, p)){
+ case Rcontains:
+ return 0;
+ case Rpreceeds:
+ cur = &p->left;
+ break;
+ case Rfollows:
+ cur = &p->right;
+ break;
+ case Rcontained:
+ cur = &p->mid;
+ break;
+ case Requals:
+ return cur;
+ }
+ }
+}
+
+void
+v4delroute(Fs *f, uchar *a, uchar *mask, int dolock)
+{
+ Route **r, *p;
+ Route rt;
+ int h, eh;
+ ulong m;
+
+ m = nhgetl(mask);
+ rt.v4.address = nhgetl(a) & m;
+ rt.v4.endaddress = rt.v4.address | ~m;
+ rt.type = Rv4;
+
+ eh = V4H(rt.v4.endaddress);
+ for(h=V4H(rt.v4.address); h<=eh; h++) {
+ if(dolock)
+ wlock(&routelock);
+ r = looknode(&f->v4root[h], &rt);
+ if(r) {
+ p = *r;
+ if(--(p->ref) == 0){
+ *r = 0;
+ addqueue(&f->queue, p->left);
+ addqueue(&f->queue, p->mid);
+ addqueue(&f->queue, p->right);
+ freeroute(p);
+ while(p = f->queue) {
+ f->queue = p->mid;
+ walkadd(f, &f->v4root[h], p->left);
+ freeroute(p);
+ }
+ }
+ }
+ if(dolock)
+ wunlock(&routelock);
+ }
+ v4routegeneration++;
+
+ ipifcremroute(f, Rv4, a, mask);
+}
+
+void
+v6delroute(Fs *f, uchar *a, uchar *mask, int dolock)
+{
+ Route **r, *p;
+ Route rt;
+ int h, eh;
+ ulong x, y;
+
+ for(h = 0; h < IPllen; h++){
+ x = nhgetl(a+4*h);
+ y = nhgetl(mask+4*h);
+ rt.v6.address[h] = x & y;
+ rt.v6.endaddress[h] = x | ~y;
+ }
+ rt.type = 0;
+
+ eh = V6H(rt.v6.endaddress);
+ for(h=V6H(rt.v6.address); h<=eh; h++) {
+ if(dolock)
+ wlock(&routelock);
+ r = looknode(&f->v6root[h], &rt);
+ if(r) {
+ p = *r;
+ if(--(p->ref) == 0){
+ *r = 0;
+ addqueue(&f->queue, p->left);
+ addqueue(&f->queue, p->mid);
+ addqueue(&f->queue, p->right);
+ freeroute(p);
+ while(p = f->queue) {
+ f->queue = p->mid;
+ walkadd(f, &f->v6root[h], p->left);
+ freeroute(p);
+ }
+ }
+ }
+ if(dolock)
+ wunlock(&routelock);
+ }
+ v6routegeneration++;
+
+ ipifcremroute(f, 0, a, mask);
+}
+
+Route*
+v4lookup(Fs *f, uchar *a, Conv *c)
+{
+ Route *p, *q;
+ ulong la;
+ uchar gate[IPaddrlen];
+ Ipifc *ifc;
+
+ if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v4routegeneration)
+ return c->r;
+
+ la = nhgetl(a);
+ q = nil;
+ for(p=f->v4root[V4H(la)]; p;)
+ if(la >= p->v4.address) {
+ if(la <= p->v4.endaddress) {
+ q = p;
+ p = p->mid;
+ } else
+ p = p->right;
+ } else
+ p = p->left;
+
+ if(q && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){
+ if(q->type & Rifc) {
+ hnputl(gate+IPv4off, q->v4.address);
+ memmove(gate, v4prefix, IPv4off);
+ } else
+ v4tov6(gate, q->v4.gate);
+ ifc = findipifc(f, gate, q->type);
+ if(ifc == nil)
+ return nil;
+ q->ifc = ifc;
+ q->ifcid = ifc->ifcid;
+ }
+
+ if(c != nil){
+ c->r = q;
+ c->rgen = v4routegeneration;
+ }
+
+ return q;
+}
+
+Route*
+v6lookup(Fs *f, uchar *a, Conv *c)
+{
+ Route *p, *q;
+ ulong la[IPllen];
+ int h;
+ ulong x, y;
+ uchar gate[IPaddrlen];
+ Ipifc *ifc;
+
+ if(memcmp(a, v4prefix, IPv4off) == 0){
+ q = v4lookup(f, a+IPv4off, c);
+ if(q != nil)
+ return q;
+ }
+
+ if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v6routegeneration)
+ return c->r;
+
+ for(h = 0; h < IPllen; h++)
+ la[h] = nhgetl(a+4*h);
+
+ q = 0;
+ for(p=f->v6root[V6H(la)]; p;){
+ for(h = 0; h < IPllen; h++){
+ x = la[h];
+ y = p->v6.address[h];
+ if(x == y)
+ continue;
+ if(x < y){
+ p = p->left;
+ goto next;
+ }
+ break;
+ }
+ for(h = 0; h < IPllen; h++){
+ x = la[h];
+ y = p->v6.endaddress[h];
+ if(x == y)
+ continue;
+ if(x > y){
+ p = p->right;
+ goto next;
+ }
+ break;
+ }
+ q = p;
+ p = p->mid;
+next: ;
+ }
+
+ if(q && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){
+ if(q->type & Rifc) {
+ for(h = 0; h < IPllen; h++)
+ hnputl(gate+4*h, q->v6.address[h]);
+ ifc = findipifc(f, gate, q->type);
+ } else
+ ifc = findipifc(f, q->v6.gate, q->type);
+ if(ifc == nil)
+ return nil;
+ q->ifc = ifc;
+ q->ifcid = ifc->ifcid;
+ }
+ if(c != nil){
+ c->r = q;
+ c->rgen = v6routegeneration;
+ }
+
+ return q;
+}
+
+void
+routetype(int type, char *p)
+{
+ memset(p, ' ', 4);
+ p[4] = 0;
+ if(type & Rv4)
+ *p++ = '4';
+ else
+ *p++ = '6';
+ if(type & Rifc)
+ *p++ = 'i';
+ if(type & Runi)
+ *p++ = 'u';
+ else if(type & Rbcast)
+ *p++ = 'b';
+ else if(type & Rmulti)
+ *p++ = 'm';
+ if(type & Rptpt)
+ *p = 'p';
+}
+
+static char *rformat = "%-15I %-4M %-15I %4.4s %4.4s %3s\n";
+
+void
+convroute(Route *r, uchar *addr, uchar *mask, uchar *gate, char *t, int *nifc)
+{
+ int i;
+
+ if(r->type & Rv4){
+ memmove(addr, v4prefix, IPv4off);
+ hnputl(addr+IPv4off, r->v4.address);
+ memset(mask, 0xff, IPv4off);
+ hnputl(mask+IPv4off, ~(r->v4.endaddress ^ r->v4.address));
+ memmove(gate, v4prefix, IPv4off);
+ memmove(gate+IPv4off, r->v4.gate, IPv4addrlen);
+ } else {
+ for(i = 0; i < IPllen; i++){
+ hnputl(addr + 4*i, r->v6.address[i]);
+ hnputl(mask + 4*i, ~(r->v6.endaddress[i] ^ r->v6.address[i]));
+ }
+ memmove(gate, r->v6.gate, IPaddrlen);
+ }
+
+ routetype(r->type, t);
+
+ if(r->ifc)
+ *nifc = r->ifc->conv->x;
+ else
+ *nifc = -1;
+}
+
+/*
+ * this code is not in rr to reduce stack size
+ */
+static void
+sprintroute(Route *r, Routewalk *rw)
+{
+ int nifc, n;
+ char t[5], *iname, ifbuf[5];
+ uchar addr[IPaddrlen], mask[IPaddrlen], gate[IPaddrlen];
+ char *p;
+
+ convroute(r, addr, mask, gate, t, &nifc);
+ iname = "-";
+ if(nifc != -1) {
+ iname = ifbuf;
+ snprint(ifbuf, sizeof ifbuf, "%d", nifc);
+ }
+ p = seprint(rw->p, rw->e, rformat, addr, mask, gate, t, r->tag, iname);
+ if(rw->o < 0){
+ n = p - rw->p;
+ if(n > -rw->o){
+ memmove(rw->p, rw->p-rw->o, n+rw->o);
+ rw->p = p + rw->o;
+ }
+ rw->o += n;
+ } else
+ rw->p = p;
+}
+
+/*
+ * recurse descending tree, applying the function in Routewalk
+ */
+static int
+rr(Route *r, Routewalk *rw)
+{
+ int h;
+
+ if(rw->e <= rw->p)
+ return 0;
+ if(r == nil)
+ return 1;
+
+ if(rr(r->left, rw) == 0)
+ return 0;
+
+ if(r->type & Rv4)
+ h = V4H(r->v4.address);
+ else
+ h = V6H(r->v6.address);
+
+ if(h == rw->h)
+ rw->walk(r, rw);
+
+ if(rr(r->mid, rw) == 0)
+ return 0;
+
+ return rr(r->right, rw);
+}
+
+void
+ipwalkroutes(Fs *f, Routewalk *rw)
+{
+ rlock(&routelock);
+ if(rw->e > rw->p) {
+ for(rw->h = 0; rw->h < nelem(f->v4root); rw->h++)
+ if(rr(f->v4root[rw->h], rw) == 0)
+ break;
+ }
+ if(rw->e > rw->p) {
+ for(rw->h = 0; rw->h < nelem(f->v6root); rw->h++)
+ if(rr(f->v6root[rw->h], rw) == 0)
+ break;
+ }
+ runlock(&routelock);
+}
+
+long
+routeread(Fs *f, char *p, ulong offset, int n)
+{
+ Routewalk rw;
+
+ rw.p = p;
+ rw.e = p+n;
+ rw.o = -offset;
+ rw.walk = sprintroute;
+
+ ipwalkroutes(f, &rw);
+
+ return rw.p - p;
+}
+
+/*
+ * this code is not in routeflush to reduce stack size
+ */
+void
+delroute(Fs *f, Route *r, int dolock)
+{
+ uchar addr[IPaddrlen];
+ uchar mask[IPaddrlen];
+ uchar gate[IPaddrlen];
+ char t[5];
+ int nifc;
+
+ convroute(r, addr, mask, gate, t, &nifc);
+ if(r->type & Rv4)
+ v4delroute(f, addr+IPv4off, mask+IPv4off, dolock);
+ else
+ v6delroute(f, addr, mask, dolock);
+}
+
+/*
+ * recurse until one route is deleted
+ * returns 0 if nothing is deleted, 1 otherwise
+ */
+int
+routeflush(Fs *f, Route *r, char *tag)
+{
+ if(r == nil)
+ return 0;
+ if(routeflush(f, r->mid, tag))
+ return 1;
+ if(routeflush(f, r->left, tag))
+ return 1;
+ if(routeflush(f, r->right, tag))
+ return 1;
+ if((r->type & Rifc) == 0){
+ if(tag == nil || strncmp(tag, r->tag, sizeof(r->tag)) == 0){
+ delroute(f, r, 0);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+long
+routewrite(Fs *f, Chan *c, char *p, int n)
+{
+ int h, changed;
+ char *tag;
+ Cmdbuf *cb;
+ uchar addr[IPaddrlen];
+ uchar mask[IPaddrlen];
+ uchar gate[IPaddrlen];
+ IPaux *a, *na;
+
+ cb = parsecmd(p, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+
+ if(strcmp(cb->f[0], "flush") == 0){
+ tag = cb->f[1];
+ for(h = 0; h < nelem(f->v4root); h++)
+ for(changed = 1; changed;){
+ wlock(&routelock);
+ changed = routeflush(f, f->v4root[h], tag);
+ wunlock(&routelock);
+ }
+ for(h = 0; h < nelem(f->v6root); h++)
+ for(changed = 1; changed;){
+ wlock(&routelock);
+ changed = routeflush(f, f->v6root[h], tag);
+ wunlock(&routelock);
+ }
+ } else if(strcmp(cb->f[0], "remove") == 0){
+ if(cb->nf < 3)
+ error(Ebadarg);
+ if (parseip(addr, cb->f[1]) == -1)
+ error(Ebadip);
+ parseipmask(mask, cb->f[2]);
+ if(memcmp(addr, v4prefix, IPv4off) == 0)
+ v4delroute(f, addr+IPv4off, mask+IPv4off, 1);
+ else
+ v6delroute(f, addr, mask, 1);
+ } else if(strcmp(cb->f[0], "add") == 0){
+ if(cb->nf < 4)
+ error(Ebadarg);
+ if(parseip(addr, cb->f[1]) == -1 ||
+ parseip(gate, cb->f[3]) == -1)
+ error(Ebadip);
+ parseipmask(mask, cb->f[2]);
+ tag = "none";
+ if(c != nil){
+ a = c->aux;
+ tag = a->tag;
+ }
+ if(memcmp(addr, v4prefix, IPv4off) == 0)
+ v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0);
+ else
+ v6addroute(f, tag, addr, mask, gate, 0);
+ } else if(strcmp(cb->f[0], "tag") == 0) {
+ if(cb->nf < 2)
+ error(Ebadarg);
+
+ a = c->aux;
+ na = newipaux(a->owner, cb->f[1]);
+ c->aux = na;
+ free(a);
+ }
+
+ poperror();
+ free(cb);
+ return n;
+}
diff --git a/sys/src/9/ip/ipv6.c b/sys/src/9/ip/ipv6.c
new file mode 100755
index 000000000..606f638e9
--- /dev/null
+++ b/sys/src/9/ip/ipv6.c
@@ -0,0 +1,621 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+#include "ipv6.h"
+
+enum
+{
+ IP6FHDR = 8, /* sizeof(Fraghdr6) */
+};
+
+#define IPV6CLASS(hdr) (((hdr)->vcf[0]&0x0F)<<2 | ((hdr)->vcf[1]&0xF0)>>2)
+#define BLKIPVER(xp) (((Ip6hdr*)((xp)->rp))->vcf[0] & 0xF0)
+/*
+ * This sleazy macro is stolen shamelessly from ip.c, see comment there.
+ */
+#define BKFG(xp) ((Ipfrag*)((xp)->base))
+
+Block* ip6reassemble(IP*, int, Block*, Ip6hdr*);
+Fragment6* ipfragallo6(IP*);
+void ipfragfree6(IP*, Fragment6*);
+Block* procopts(Block *bp);
+static Block* procxtns(IP *ip, Block *bp, int doreasm);
+int unfraglen(Block *bp, uchar *nexthdr, int setfh);
+
+int
+ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c)
+{
+ int medialen, len, chunk, uflen, flen, seglen, lid, offset, fragoff;
+ int morefrags, blklen, rv = 0, tentative;
+ uchar *gate, nexthdr;
+ Block *xp, *nb;
+ Fraghdr6 fraghdr;
+ IP *ip;
+ Ip6hdr *eh;
+ Ipifc *ifc;
+ Route *r, *sr;
+
+ ip = f->ip;
+
+ /* Fill out the ip header */
+ eh = (Ip6hdr*)(bp->rp);
+
+ ip->stats[OutRequests]++;
+
+ /* Number of uchars in data and ip header to write */
+ len = blocklen(bp);
+
+ tentative = iptentative(f, eh->src);
+ if(tentative){
+ netlog(f, Logip, "reject tx of packet with tentative src address %I\n",
+ eh->src);
+ goto free;
+ }
+
+ if(gating){
+ chunk = nhgets(eh->ploadlen);
+ if(chunk > len){
+ ip->stats[OutDiscards]++;
+ netlog(f, Logip, "short gated packet\n");
+ goto free;
+ }
+ if(chunk + IP6HDR < len)
+ len = chunk + IP6HDR;
+ }
+
+ if(len >= IP_MAX){
+ ip->stats[OutDiscards]++;
+ netlog(f, Logip, "exceeded ip max size %I\n", eh->dst);
+ goto free;
+ }
+
+ r = v6lookup(f, eh->dst, c);
+ if(r == nil){
+// print("no route for %I, src %I free\n", eh->dst, eh->src);
+ ip->stats[OutNoRoutes]++;
+ netlog(f, Logip, "no interface %I\n", eh->dst);
+ rv = -1;
+ goto free;
+ }
+
+ ifc = r->ifc;
+ if(r->type & (Rifc|Runi))
+ gate = eh->dst;
+ else if(r->type & (Rbcast|Rmulti)) {
+ gate = eh->dst;
+ sr = v6lookup(f, eh->src, nil);
+ if(sr && (sr->type & Runi))
+ ifc = sr->ifc;
+ }
+ else
+ gate = r->v6.gate;
+
+ if(!gating)
+ eh->vcf[0] = IP_VER6;
+ eh->ttl = ttl;
+ if(!gating) {
+ eh->vcf[0] |= tos >> 4;
+ eh->vcf[1] = tos << 4;
+ }
+
+ if(!canrlock(ifc))
+ goto free;
+
+ if(waserror()){
+ runlock(ifc);
+ nexterror();
+ }
+
+ if(ifc->m == nil)
+ goto raise;
+
+ /* If we dont need to fragment just send it */
+ medialen = ifc->maxtu - ifc->m->hsize;
+ if(len <= medialen) {
+ hnputs(eh->ploadlen, len - IP6HDR);
+ ifc->m->bwrite(ifc, bp, V6, gate);
+ runlock(ifc);
+ poperror();
+ return 0;
+ }
+
+ if(gating && ifc->reassemble <= 0) {
+ /*
+ * v6 intermediate nodes are not supposed to fragment pkts;
+ * we fragment if ifc->reassemble is turned on; an exception
+ * needed for nat.
+ */
+ ip->stats[OutDiscards]++;
+ icmppkttoobig6(f, ifc, bp);
+ netlog(f, Logip, "%I: gated pkts not fragmented\n", eh->dst);
+ goto raise;
+ }
+
+ /* start v6 fragmentation */
+ uflen = unfraglen(bp, &nexthdr, 1);
+ if(uflen > medialen) {
+ ip->stats[FragFails]++;
+ ip->stats[OutDiscards]++;
+ netlog(f, Logip, "%I: unfragmentable part too big\n", eh->dst);
+ goto raise;
+ }
+
+ flen = len - uflen;
+ seglen = (medialen - (uflen + IP6FHDR)) & ~7;
+ if(seglen < 8) {
+ ip->stats[FragFails]++;
+ ip->stats[OutDiscards]++;
+ netlog(f, Logip, "%I: seglen < 8\n", eh->dst);
+ goto raise;
+ }
+
+ lid = incref(&ip->id6);
+ fraghdr.nexthdr = nexthdr;
+ fraghdr.res = 0;
+ hnputl(fraghdr.id, lid);
+
+ xp = bp;
+ offset = uflen;
+ while (xp && offset && offset >= BLEN(xp)) {
+ offset -= BLEN(xp);
+ xp = xp->next;
+ }
+ xp->rp += offset;
+
+ fragoff = 0;
+ morefrags = 1;
+
+ for(; fragoff < flen; fragoff += seglen) {
+ nb = allocb(uflen + IP6FHDR + seglen);
+
+ if(fragoff + seglen >= flen) {
+ seglen = flen - fragoff;
+ morefrags = 0;
+ }
+
+ hnputs(eh->ploadlen, seglen+IP6FHDR);
+ memmove(nb->wp, eh, uflen);
+ nb->wp += uflen;
+
+ hnputs(fraghdr.offsetRM, fragoff); /* last 3 bits must be 0 */
+ fraghdr.offsetRM[1] |= morefrags;
+ memmove(nb->wp, &fraghdr, IP6FHDR);
+ nb->wp += IP6FHDR;
+
+ /* Copy data */
+ chunk = seglen;
+ while (chunk) {
+ if(!xp) {
+ ip->stats[OutDiscards]++;
+ ip->stats[FragFails]++;
+ freeblist(nb);
+ netlog(f, Logip, "!xp: chunk in v6%d\n", chunk);
+ goto raise;
+ }
+ blklen = chunk;
+ if(BLEN(xp) < chunk)
+ blklen = BLEN(xp);
+ memmove(nb->wp, xp->rp, blklen);
+
+ nb->wp += blklen;
+ xp->rp += blklen;
+ chunk -= blklen;
+ if(xp->rp == xp->wp)
+ xp = xp->next;
+ }
+
+ ifc->m->bwrite(ifc, nb, V6, gate);
+ ip->stats[FragCreates]++;
+ }
+ ip->stats[FragOKs]++;
+
+raise:
+ runlock(ifc);
+ poperror();
+free:
+ freeblist(bp);
+ return rv;
+}
+
+void
+ipiput6(Fs *f, Ipifc *ifc, Block *bp)
+{
+ int hl, hop, tos, notforme, tentative;
+ uchar proto;
+ uchar v6dst[IPaddrlen];
+ IP *ip;
+ Ip6hdr *h;
+ Proto *p;
+ Route *r, *sr;
+
+ ip = f->ip;
+ ip->stats[InReceives]++;
+
+ /*
+ * Ensure we have all the header info in the first
+ * block. Make life easier for other protocols by
+ * collecting up to the first 64 bytes in the first block.
+ */
+ if(BLEN(bp) < 64) {
+ hl = blocklen(bp);
+ if(hl < IP6HDR)
+ hl = IP6HDR;
+ if(hl > 64)
+ hl = 64;
+ bp = pullupblock(bp, hl);
+ if(bp == nil)
+ return;
+ }
+
+ h = (Ip6hdr *)bp->rp;
+
+ memmove(&v6dst[0], &h->dst[0], IPaddrlen);
+ notforme = ipforme(f, v6dst) == 0;
+ tentative = iptentative(f, v6dst);
+
+ if(tentative && h->proto != ICMPv6) {
+ print("tentative addr, drop\n");
+ freeblist(bp);
+ return;
+ }
+
+ /* Check header version */
+ if(BLKIPVER(bp) != IP_VER6) {
+ ip->stats[InHdrErrors]++;
+ netlog(f, Logip, "ip: bad version %ux\n", (h->vcf[0]&0xF0)>>2);
+ freeblist(bp);
+ return;
+ }
+
+ /* route */
+ if(notforme) {
+ if(!ip->iprouting){
+ freeblist(bp);
+ return;
+ }
+
+ /* don't forward to link-local destinations */
+ if(islinklocal(h->dst) ||
+ (isv6mcast(h->dst) && (h->dst[1]&0xF) <= Link_local_scop)){
+ ip->stats[OutDiscards]++;
+ freeblist(bp);
+ return;
+ }
+
+ /* don't forward to source's network */
+ sr = v6lookup(f, h->src, nil);
+ r = v6lookup(f, h->dst, nil);
+
+ if(r == nil || sr == r){
+ ip->stats[OutDiscards]++;
+ freeblist(bp);
+ return;
+ }
+
+ /* don't forward if packet has timed out */
+ hop = h->ttl;
+ if(hop < 1) {
+ ip->stats[InHdrErrors]++;
+ icmpttlexceeded6(f, ifc, bp);
+ freeblist(bp);
+ return;
+ }
+
+ /* process headers & reassemble if the interface expects it */
+ bp = procxtns(ip, bp, r->ifc->reassemble);
+ if(bp == nil)
+ return;
+
+ ip->stats[ForwDatagrams]++;
+ h = (Ip6hdr *)bp->rp;
+ tos = IPV6CLASS(h);
+ hop = h->ttl;
+ ipoput6(f, bp, 1, hop-1, tos, nil);
+ return;
+ }
+
+ /* reassemble & process headers if needed */
+ bp = procxtns(ip, bp, 1);
+ if(bp == nil)
+ return;
+
+ h = (Ip6hdr *) (bp->rp);
+ proto = h->proto;
+ p = Fsrcvpcol(f, proto);
+ if(p && p->rcv) {
+ ip->stats[InDelivers]++;
+ (*p->rcv)(p, ifc, bp);
+ return;
+ }
+
+ ip->stats[InDiscards]++;
+ ip->stats[InUnknownProtos]++;
+ freeblist(bp);
+}
+
+/*
+ * ipfragfree6 - copied from ipfragfree4 - assume hold fraglock6
+ */
+void
+ipfragfree6(IP *ip, Fragment6 *frag)
+{
+ Fragment6 *fl, **l;
+
+ if(frag->blist)
+ freeblist(frag->blist);
+
+ memset(frag->src, 0, IPaddrlen);
+ frag->id = 0;
+ frag->blist = nil;
+
+ l = &ip->flisthead6;
+ for(fl = *l; fl; fl = fl->next) {
+ if(fl == frag) {
+ *l = frag->next;
+ break;
+ }
+ l = &fl->next;
+ }
+
+ frag->next = ip->fragfree6;
+ ip->fragfree6 = frag;
+}
+
+/*
+ * ipfragallo6 - copied from ipfragalloc4
+ */
+Fragment6*
+ipfragallo6(IP *ip)
+{
+ Fragment6 *f;
+
+ while(ip->fragfree6 == nil) {
+ /* free last entry on fraglist */
+ for(f = ip->flisthead6; f->next; f = f->next)
+ ;
+ ipfragfree6(ip, f);
+ }
+ f = ip->fragfree6;
+ ip->fragfree6 = f->next;
+ f->next = ip->flisthead6;
+ ip->flisthead6 = f;
+ f->age = NOW + 30000;
+
+ return f;
+}
+
+static Block*
+procxtns(IP *ip, Block *bp, int doreasm)
+{
+ int offset;
+ uchar proto;
+ Ip6hdr *h;
+
+ h = (Ip6hdr *)bp->rp;
+ offset = unfraglen(bp, &proto, 0);
+
+ if(proto == FH && doreasm != 0) {
+ bp = ip6reassemble(ip, offset, bp, h);
+ if(bp == nil)
+ return nil;
+ offset = unfraglen(bp, &proto, 0);
+ }
+
+ if(proto == DOH || offset > IP6HDR)
+ bp = procopts(bp);
+ return bp;
+}
+
+/*
+ * returns length of "Unfragmentable part", i.e., sum of lengths of ipv6 hdr,
+ * hop-by-hop & routing headers if present; *nexthdr is set to nexthdr value
+ * of the last header in the "Unfragmentable part"; if setfh != 0, nexthdr
+ * field of the last header in the "Unfragmentable part" is set to FH.
+ */
+int
+unfraglen(Block *bp, uchar *nexthdr, int setfh)
+{
+ uchar *p, *q;
+ int ufl, hs;
+
+ p = bp->rp;
+ q = p+6; /* proto, = p+sizeof(Ip6hdr.vcf)+sizeof(Ip6hdr.ploadlen) */
+ *nexthdr = *q;
+ ufl = IP6HDR;
+ p += ufl;
+
+ while (*nexthdr == HBH || *nexthdr == RH) {
+ *nexthdr = *p;
+ hs = ((int)*(p+1) + 1) * 8;
+ ufl += hs;
+ q = p;
+ p += hs;
+ }
+
+ if(*nexthdr == FH)
+ *q = *p;
+ if(setfh)
+ *q = FH;
+ return ufl;
+}
+
+Block*
+procopts(Block *bp)
+{
+ return bp;
+}
+
+Block*
+ip6reassemble(IP* ip, int uflen, Block* bp, Ip6hdr* ih)
+{
+ int fend, offset, ovlap, len, fragsize, pktposn;
+ uint id;
+ uchar src[IPaddrlen], dst[IPaddrlen];
+ Block *bl, **l, *last, *prev;
+ Fraghdr6 *fraghdr;
+ Fragment6 *f, *fnext;
+
+ fraghdr = (Fraghdr6 *)(bp->rp + uflen);
+ memmove(src, ih->src, IPaddrlen);
+ memmove(dst, ih->dst, IPaddrlen);
+ id = nhgetl(fraghdr->id);
+ offset = nhgets(fraghdr->offsetRM) & ~7;
+
+ /*
+ * block lists are too hard, pullupblock into a single block
+ */
+ if(bp->next){
+ bp = pullupblock(bp, blocklen(bp));
+ ih = (Ip6hdr *)bp->rp;
+ }
+
+ qlock(&ip->fraglock6);
+
+ /*
+ * find a reassembly queue for this fragment
+ */
+ for(f = ip->flisthead6; f; f = fnext){
+ fnext = f->next;
+ if(ipcmp(f->src, src)==0 && ipcmp(f->dst, dst)==0 && f->id == id)
+ break;
+ if(f->age < NOW){
+ ip->stats[ReasmTimeout]++;
+ ipfragfree6(ip, f);
+ }
+ }
+
+ /*
+ * if this isn't a fragmented packet, accept it
+ * and get rid of any fragments that might go
+ * with it.
+ */
+ if(nhgets(fraghdr->offsetRM) == 0) { /* 1st frag is also last */
+ if(f) {
+ ipfragfree6(ip, f);
+ ip->stats[ReasmFails]++;
+ }
+ qunlock(&ip->fraglock6);
+ return bp;
+ }
+
+ if(bp->base+IPFRAGSZ >= bp->rp){
+ bp = padblock(bp, IPFRAGSZ);
+ bp->rp += IPFRAGSZ;
+ }
+
+ BKFG(bp)->foff = offset;
+ BKFG(bp)->flen = nhgets(ih->ploadlen) + IP6HDR - uflen - IP6FHDR;
+
+ /* First fragment allocates a reassembly queue */
+ if(f == nil) {
+ f = ipfragallo6(ip);
+ f->id = id;
+ memmove(f->src, src, IPaddrlen);
+ memmove(f->dst, dst, IPaddrlen);
+
+ f->blist = bp;
+
+ qunlock(&ip->fraglock6);
+ ip->stats[ReasmReqds]++;
+ return nil;
+ }
+
+ /*
+ * find the new fragment's position in the queue
+ */
+ prev = nil;
+ l = &f->blist;
+ bl = f->blist;
+ while(bl != nil && BKFG(bp)->foff > BKFG(bl)->foff) {
+ prev = bl;
+ l = &bl->next;
+ bl = bl->next;
+ }
+
+ /* Check overlap of a previous fragment - trim away as necessary */
+ if(prev) {
+ ovlap = BKFG(prev)->foff + BKFG(prev)->flen - BKFG(bp)->foff;
+ if(ovlap > 0) {
+ if(ovlap >= BKFG(bp)->flen) {
+ freeblist(bp);
+ qunlock(&ip->fraglock6);
+ return nil;
+ }
+ BKFG(prev)->flen -= ovlap;
+ }
+ }
+
+ /* Link onto assembly queue */
+ bp->next = *l;
+ *l = bp;
+
+ /* Check to see if succeeding segments overlap */
+ if(bp->next) {
+ l = &bp->next;
+ fend = BKFG(bp)->foff + BKFG(bp)->flen;
+
+ /* Take completely covered segments out */
+ while(*l) {
+ ovlap = fend - BKFG(*l)->foff;
+ if(ovlap <= 0)
+ break;
+ if(ovlap < BKFG(*l)->flen) {
+ BKFG(*l)->flen -= ovlap;
+ BKFG(*l)->foff += ovlap;
+ /* move up ih hdrs */
+ memmove((*l)->rp + ovlap, (*l)->rp, uflen);
+ (*l)->rp += ovlap;
+ break;
+ }
+ last = (*l)->next;
+ (*l)->next = nil;
+ freeblist(*l);
+ *l = last;
+ }
+ }
+
+ /*
+ * look for a complete packet. if we get to a fragment
+ * with the trailing bit of fraghdr->offsetRM[1] set, we're done.
+ */
+ pktposn = 0;
+ for(bl = f->blist; bl && BKFG(bl)->foff == pktposn; bl = bl->next) {
+ fraghdr = (Fraghdr6 *)(bl->rp + uflen);
+ if((fraghdr->offsetRM[1] & 1) == 0) {
+ bl = f->blist;
+
+ /* get rid of frag header in first fragment */
+ memmove(bl->rp + IP6FHDR, bl->rp, uflen);
+ bl->rp += IP6FHDR;
+ len = nhgets(((Ip6hdr*)bl->rp)->ploadlen) - IP6FHDR;
+ bl->wp = bl->rp + len + IP6HDR;
+ /*
+ * Pullup all the fragment headers and
+ * return a complete packet
+ */
+ for(bl = bl->next; bl; bl = bl->next) {
+ fragsize = BKFG(bl)->flen;
+ len += fragsize;
+ bl->rp += uflen + IP6FHDR;
+ bl->wp = bl->rp + fragsize;
+ }
+
+ bl = f->blist;
+ f->blist = nil;
+ ipfragfree6(ip, f);
+ ih = (Ip6hdr*)bl->rp;
+ hnputs(ih->ploadlen, len);
+ qunlock(&ip->fraglock6);
+ ip->stats[ReasmOKs]++;
+ return bl;
+ }
+ pktposn += BKFG(bl)->flen;
+ }
+ qunlock(&ip->fraglock6);
+ return nil;
+}
diff --git a/sys/src/9/ip/ipv6.h b/sys/src/9/ip/ipv6.h
new file mode 100755
index 000000000..e4a0144b4
--- /dev/null
+++ b/sys/src/9/ip/ipv6.h
@@ -0,0 +1,188 @@
+/*
+ * Internet Protocol Version 6
+ *
+ * rfc2460 defines the protocol, rfc2461 neighbour discovery, and
+ * rfc2462 address autoconfiguration. rfc4443 defines ICMP; was rfc2463.
+ * rfc4291 defines the address architecture (including prefices), was rfc3513.
+ * rfc4007 defines the scoped address architecture.
+ *
+ * global unicast is anything but unspecified (::), loopback (::1),
+ * multicast (ff00::/8), and link-local unicast (fe80::/10).
+ *
+ * site-local (fec0::/10) is now deprecated, originally by rfc3879.
+ *
+ * Unique Local IPv6 Unicast Addresses are defined by rfc4193.
+ * prefix is fc00::/7, scope is global, routing is limited to roughly a site.
+ */
+#define isv6mcast(addr) ((addr)[0] == 0xff)
+#define islinklocal(addr) ((addr)[0] == 0xfe && ((addr)[1] & 0xc0) == 0x80)
+
+#define optexsts(np) (nhgets((np)->ploadlen) > 24)
+#define issmcast(addr) (memcmp((addr), v6solicitednode, 13) == 0)
+
+#ifndef MIN
+#define MIN(a, b) ((a) <= (b)? (a): (b))
+#endif
+
+enum { /* Header Types */
+ HBH = 0, /* hop-by-hop multicast routing protocol */
+ ICMP = 1,
+ IGMP = 2,
+ GGP = 3,
+ IPINIP = 4,
+ ST = 5,
+ TCP = 6,
+ UDP = 17,
+ ISO_TP4 = 29,
+ RH = 43,
+ FH = 44,
+ IDRP = 45,
+ RSVP = 46,
+ AH = 51,
+ ESP = 52,
+ ICMPv6 = 58,
+ NNH = 59,
+ DOH = 60,
+ ISO_IP = 80,
+ IGRP = 88,
+ OSPF = 89,
+
+ Maxhdrtype = 256,
+};
+
+enum {
+ /* multicast flags and scopes */
+
+// Well_known_flg = 0,
+// Transient_flg = 1,
+
+// Interface_local_scop = 1,
+ Link_local_scop = 2,
+// Site_local_scop = 5,
+// Org_local_scop = 8,
+ Global_scop = 14,
+
+ /* various prefix lengths */
+ SOLN_PREF_LEN = 13,
+
+ /* icmpv6 unreachability codes */
+ Icmp6_no_route = 0,
+ Icmp6_ad_prohib = 1,
+ Icmp6_out_src_scope = 2,
+ Icmp6_adr_unreach = 3,
+ Icmp6_port_unreach = 4,
+ Icmp6_gress_src_fail = 5,
+ Icmp6_rej_route = 6,
+ Icmp6_unknown = 7, /* our own invention for internal use */
+
+ /* various flags & constants */
+ v6MINTU = 1280,
+ HOP_LIMIT = 255,
+ IP6HDR = 40, /* sizeof(Ip6hdr) = 8 + 2*16 */
+
+ /* option types */
+
+ /* neighbour discovery */
+ SRC_LLADDR = 1,
+ TARGET_LLADDR = 2,
+ PREFIX_INFO = 3,
+ REDIR_HEADER = 4,
+ MTU_OPTION = 5,
+ /* new since rfc2461; see iana.org/assignments/icmpv6-parameters */
+ V6nd_home = 8,
+ V6nd_srcaddrs = 9, /* rfc3122 */
+ V6nd_ip = 17,
+ /* /lib/rfc/drafts/draft-jeong-dnsop-ipv6-dns-discovery-12.txt */
+ V6nd_rdns = 25,
+ /* plan 9 extensions */
+ V6nd_9fs = 250,
+ V6nd_9auth = 251,
+
+ SRC_UNSPEC = 0,
+ SRC_UNI = 1,
+ TARG_UNI = 2,
+ TARG_MULTI = 3,
+
+ Tunitent = 1,
+ Tuniproxy = 2,
+ Tunirany = 3,
+
+ /* Node constants */
+ MAX_MULTICAST_SOLICIT = 3,
+ RETRANS_TIMER = 1000,
+};
+
+typedef struct Ip6hdr Ip6hdr;
+typedef struct Opthdr Opthdr;
+typedef struct Routinghdr Routinghdr;
+typedef struct Fraghdr6 Fraghdr6;
+
+/* we do this in case there's padding at the end of Ip6hdr */
+#define IPV6HDR \
+ uchar vcf[4]; /* version:4, traffic class:8, flow label:20 */\
+ uchar ploadlen[2]; /* payload length: packet length - 40 */ \
+ uchar proto; /* next header type */ \
+ uchar ttl; /* hop limit */ \
+ uchar src[IPaddrlen]; \
+ uchar dst[IPaddrlen]
+
+struct Ip6hdr {
+ IPV6HDR;
+ uchar payload[];
+};
+
+struct Opthdr { /* unused */
+ uchar nexthdr;
+ uchar len;
+};
+
+/*
+ * Beware routing header type 0 (loose source routing); see
+ * http://www.secdev.org/conf/IPv6_RH_security-csw07.pdf.
+ * Type 1 is unused. Type 2 is for MIPv6 (mobile IPv6) filtering
+ * against type 0 header.
+ */
+struct Routinghdr { /* unused */
+ uchar nexthdr;
+ uchar len;
+ uchar rtetype;
+ uchar segrem;
+};
+
+struct Fraghdr6 {
+ uchar nexthdr;
+ uchar res;
+ uchar offsetRM[2]; /* Offset, Res, M flag */
+ uchar id[4];
+};
+
+extern uchar v6allnodesN[IPaddrlen];
+extern uchar v6allnodesL[IPaddrlen];
+extern uchar v6allroutersN[IPaddrlen];
+extern uchar v6allroutersL[IPaddrlen];
+extern uchar v6allnodesNmask[IPaddrlen];
+extern uchar v6allnodesLmask[IPaddrlen];
+extern uchar v6solicitednode[IPaddrlen];
+extern uchar v6solicitednodemask[IPaddrlen];
+extern uchar v6Unspecified[IPaddrlen];
+extern uchar v6loopback[IPaddrlen];
+extern uchar v6loopbackmask[IPaddrlen];
+extern uchar v6linklocal[IPaddrlen];
+extern uchar v6linklocalmask[IPaddrlen];
+extern uchar v6multicast[IPaddrlen];
+extern uchar v6multicastmask[IPaddrlen];
+
+extern int v6llpreflen;
+extern int v6mcpreflen;
+extern int v6snpreflen;
+extern int v6aNpreflen;
+extern int v6aLpreflen;
+
+extern int ReTransTimer;
+
+void ipv62smcast(uchar *, uchar *);
+void icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac);
+void icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags);
+void icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp);
+void icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp);
+void icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free);
diff --git a/sys/src/9/ip/loopbackmedium.c b/sys/src/9/ip/loopbackmedium.c
new file mode 100755
index 000000000..ec96d7939
--- /dev/null
+++ b/sys/src/9/ip/loopbackmedium.c
@@ -0,0 +1,120 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+
+enum
+{
+ Maxtu= 16*1024,
+};
+
+typedef struct LB LB;
+struct LB
+{
+ Proc *readp;
+ Queue *q;
+ Fs *f;
+};
+
+static void loopbackread(void *a);
+
+static void
+loopbackbind(Ipifc *ifc, int, char**)
+{
+ LB *lb;
+
+ lb = smalloc(sizeof(*lb));
+ lb->f = ifc->conv->p->f;
+ lb->q = qopen(1024*1024, Qmsg, nil, nil);
+ ifc->arg = lb;
+ ifc->mbps = 1000;
+
+ kproc("loopbackread", loopbackread, ifc);
+
+}
+
+static void
+loopbackunbind(Ipifc *ifc)
+{
+ LB *lb = ifc->arg;
+
+ if(lb->readp)
+ postnote(lb->readp, 1, "unbind", 0);
+
+ /* wait for reader to die */
+ while(lb->readp != 0)
+ tsleep(&up->sleep, return0, 0, 300);
+
+ /* clean up */
+ qfree(lb->q);
+ free(lb);
+}
+
+static void
+loopbackbwrite(Ipifc *ifc, Block *bp, int, uchar*)
+{
+ LB *lb;
+
+ lb = ifc->arg;
+ if(qpass(lb->q, bp) < 0)
+ ifc->outerr++;
+ ifc->out++;
+}
+
+static void
+loopbackread(void *a)
+{
+ Ipifc *ifc;
+ Block *bp;
+ LB *lb;
+
+ ifc = a;
+ lb = ifc->arg;
+ lb->readp = up; /* hide identity under a rock for unbind */
+ if(waserror()){
+ lb->readp = 0;
+ pexit("hangup", 1);
+ }
+ for(;;){
+ bp = qbread(lb->q, Maxtu);
+ if(bp == nil)
+ continue;
+ ifc->in++;
+ if(!canrlock(ifc)){
+ freeb(bp);
+ continue;
+ }
+ if(waserror()){
+ runlock(ifc);
+ nexterror();
+ }
+ if(ifc->lifc == nil)
+ freeb(bp);
+ else
+ ipiput4(lb->f, ifc, bp);
+ runlock(ifc);
+ poperror();
+ }
+}
+
+Medium loopbackmedium =
+{
+.hsize= 0,
+.mintu= 0,
+.maxtu= Maxtu,
+.maclen= 0,
+.name= "loopback",
+.bind= loopbackbind,
+.unbind= loopbackunbind,
+.bwrite= loopbackbwrite,
+};
+
+void
+loopbackmediumlink(void)
+{
+ addipmedium(&loopbackmedium);
+}
diff --git a/sys/src/9/ip/netdevmedium.c b/sys/src/9/ip/netdevmedium.c
new file mode 100755
index 000000000..bcbdeeda2
--- /dev/null
+++ b/sys/src/9/ip/netdevmedium.c
@@ -0,0 +1,153 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+
+static void netdevbind(Ipifc *ifc, int argc, char **argv);
+static void netdevunbind(Ipifc *ifc);
+static void netdevbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);
+static void netdevread(void *a);
+
+typedef struct Netdevrock Netdevrock;
+struct Netdevrock
+{
+ Fs *f; /* file system we belong to */
+ Proc *readp; /* reading process */
+ Chan *mchan; /* Data channel */
+};
+
+Medium netdevmedium =
+{
+.name= "netdev",
+.hsize= 0,
+.mintu= 0,
+.maxtu= 64000,
+.maclen= 0,
+.bind= netdevbind,
+.unbind= netdevunbind,
+.bwrite= netdevbwrite,
+.unbindonclose= 0,
+};
+
+/*
+ * called to bind an IP ifc to a generic network device
+ * called with ifc qlock'd
+ */
+static void
+netdevbind(Ipifc *ifc, int argc, char **argv)
+{
+ Chan *mchan;
+ Netdevrock *er;
+
+ if(argc < 2)
+ error(Ebadarg);
+
+ mchan = namec(argv[2], Aopen, ORDWR, 0);
+
+ er = smalloc(sizeof(*er));
+ er->mchan = mchan;
+ er->f = ifc->conv->p->f;
+
+ ifc->arg = er;
+
+ kproc("netdevread", netdevread, ifc);
+}
+
+/*
+ * called with ifc wlock'd
+ */
+static void
+netdevunbind(Ipifc *ifc)
+{
+ Netdevrock *er = ifc->arg;
+
+ if(er->readp != nil)
+ postnote(er->readp, 1, "unbind", 0);
+
+ /* wait for readers to die */
+ while(er->readp != nil)
+ tsleep(&up->sleep, return0, 0, 300);
+
+ if(er->mchan != nil)
+ cclose(er->mchan);
+
+ free(er);
+}
+
+/*
+ * called by ipoput with a single block to write
+ */
+static void
+netdevbwrite(Ipifc *ifc, Block *bp, int, uchar*)
+{
+ Netdevrock *er = ifc->arg;
+
+ if(bp->next)
+ bp = concatblock(bp);
+ if(BLEN(bp) < ifc->mintu)
+ bp = adjustblock(bp, ifc->mintu);
+
+ devtab[er->mchan->type]->bwrite(er->mchan, bp, 0);
+ ifc->out++;
+}
+
+/*
+ * process to read from the device
+ */
+static void
+netdevread(void *a)
+{
+ Ipifc *ifc;
+ Block *bp;
+ Netdevrock *er;
+ char *argv[1];
+
+ ifc = a;
+ er = ifc->arg;
+ er->readp = up; /* hide identity under a rock for unbind */
+ if(waserror()){
+ er->readp = nil;
+ pexit("hangup", 1);
+ }
+ for(;;){
+ bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0);
+ if(bp == nil){
+ /*
+ * get here if mchan is a pipe and other side hangs up
+ * clean up this interface & get out
+ZZZ is this a good idea?
+ */
+ poperror();
+ er->readp = nil;
+ argv[0] = "unbind";
+ if(!waserror())
+ ifc->conv->p->ctl(ifc->conv, argv, 1);
+ pexit("hangup", 1);
+ }
+ if(!canrlock(ifc)){
+ freeb(bp);
+ continue;
+ }
+ if(waserror()){
+ runlock(ifc);
+ nexterror();
+ }
+ ifc->in++;
+ if(ifc->lifc == nil)
+ freeb(bp);
+ else
+ ipiput4(er->f, ifc, bp);
+ runlock(ifc);
+ poperror();
+ }
+}
+
+void
+netdevmediumlink(void)
+{
+ addipmedium(&netdevmedium);
+}
diff --git a/sys/src/9/ip/netlog.c b/sys/src/9/ip/netlog.c
new file mode 100755
index 000000000..889b4039b
--- /dev/null
+++ b/sys/src/9/ip/netlog.c
@@ -0,0 +1,261 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "../ip/ip.h"
+
+enum {
+ Nlog = 16*1024,
+};
+
+/*
+ * action log
+ */
+struct Netlog {
+ Lock;
+ int opens;
+ char* buf;
+ char *end;
+ char *rptr;
+ int len;
+
+ int logmask; /* mask of things to debug */
+ uchar iponly[IPaddrlen]; /* ip address to print debugging for */
+ int iponlyset;
+
+ QLock;
+ Rendez;
+};
+
+typedef struct Netlogflag {
+ char* name;
+ int mask;
+} Netlogflag;
+
+static Netlogflag flags[] =
+{
+ { "ppp", Logppp, },
+ { "ip", Logip, },
+ { "fs", Logfs, },
+ { "tcp", Logtcp, },
+ { "icmp", Logicmp, },
+ { "udp", Logudp, },
+ { "compress", Logcompress, },
+ { "gre", Loggre, },
+ { "tcpwin", Logtcp|Logtcpwin, },
+ { "tcprxmt", Logtcp|Logtcprxmt, },
+ { "udpmsg", Logudp|Logudpmsg, },
+ { "ipmsg", Logip|Logipmsg, },
+ { "esp", Logesp, },
+ { nil, 0, },
+};
+
+char Ebadnetctl[] = "too few arguments for netlog control message";
+
+enum
+{
+ CMset,
+ CMclear,
+ CMonly,
+};
+
+static
+Cmdtab routecmd[] = {
+ CMset, "set", 0,
+ CMclear, "clear", 0,
+ CMonly, "only", 0,
+};
+
+void
+netloginit(Fs *f)
+{
+ f->alog = smalloc(sizeof(Netlog));
+}
+
+void
+netlogopen(Fs *f)
+{
+ lock(f->alog);
+ if(waserror()){
+ unlock(f->alog);
+ nexterror();
+ }
+ if(f->alog->opens == 0){
+ if(f->alog->buf == nil)
+ f->alog->buf = malloc(Nlog);
+ f->alog->rptr = f->alog->buf;
+ f->alog->end = f->alog->buf + Nlog;
+ }
+ f->alog->opens++;
+ unlock(f->alog);
+ poperror();
+}
+
+void
+netlogclose(Fs *f)
+{
+ lock(f->alog);
+ if(waserror()){
+ unlock(f->alog);
+ nexterror();
+ }
+ f->alog->opens--;
+ if(f->alog->opens == 0){
+ free(f->alog->buf);
+ f->alog->buf = nil;
+ }
+ unlock(f->alog);
+ poperror();
+}
+
+static int
+netlogready(void *a)
+{
+ Fs *f = a;
+
+ return f->alog->len;
+}
+
+long
+netlogread(Fs *f, void *a, ulong, long n)
+{
+ int i, d;
+ char *p, *rptr;
+
+ qlock(f->alog);
+ if(waserror()){
+ qunlock(f->alog);
+ nexterror();
+ }
+
+ for(;;){
+ lock(f->alog);
+ if(f->alog->len){
+ if(n > f->alog->len)
+ n = f->alog->len;
+ d = 0;
+ rptr = f->alog->rptr;
+ f->alog->rptr += n;
+ if(f->alog->rptr >= f->alog->end){
+ d = f->alog->rptr - f->alog->end;
+ f->alog->rptr = f->alog->buf + d;
+ }
+ f->alog->len -= n;
+ unlock(f->alog);
+
+ i = n-d;
+ p = a;
+ memmove(p, rptr, i);
+ memmove(p+i, f->alog->buf, d);
+ break;
+ }
+ else
+ unlock(f->alog);
+
+ sleep(f->alog, netlogready, f);
+ }
+
+ qunlock(f->alog);
+ poperror();
+
+ return n;
+}
+
+void
+netlogctl(Fs *f, char* s, int n)
+{
+ int i, set;
+ Netlogflag *fp;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+
+ cb = parsecmd(s, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+
+ if(cb->nf < 2)
+ error(Ebadnetctl);
+
+ ct = lookupcmd(cb, routecmd, nelem(routecmd));
+
+ SET(set);
+
+ switch(ct->index){
+ case CMset:
+ set = 1;
+ break;
+
+ case CMclear:
+ set = 0;
+ break;
+
+ case CMonly:
+ parseip(f->alog->iponly, cb->f[1]);
+ if(ipcmp(f->alog->iponly, IPnoaddr) == 0)
+ f->alog->iponlyset = 0;
+ else
+ f->alog->iponlyset = 1;
+ free(cb);
+ return;
+
+ default:
+ cmderror(cb, "unknown ip control message");
+ }
+
+ for(i = 1; i < cb->nf; i++){
+ for(fp = flags; fp->name; fp++)
+ if(strcmp(fp->name, cb->f[i]) == 0)
+ break;
+ if(fp->name == nil)
+ continue;
+ if(set)
+ f->alog->logmask |= fp->mask;
+ else
+ f->alog->logmask &= ~fp->mask;
+ }
+
+ free(cb);
+ poperror();
+}
+
+void
+netlog(Fs *f, int mask, char *fmt, ...)
+{
+ char buf[256], *t, *fp;
+ int i, n;
+ va_list arg;
+
+ if(!(f->alog->logmask & mask))
+ return;
+
+ if(f->alog->opens == 0)
+ return;
+
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+
+ lock(f->alog);
+ i = f->alog->len + n - Nlog;
+ if(i > 0){
+ f->alog->len -= i;
+ f->alog->rptr += i;
+ if(f->alog->rptr >= f->alog->end)
+ f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
+ }
+ t = f->alog->rptr + f->alog->len;
+ fp = buf;
+ f->alog->len += n;
+ while(n-- > 0){
+ if(t >= f->alog->end)
+ t = f->alog->buf + (t - f->alog->end);
+ *t++ = *fp++;
+ }
+ unlock(f->alog);
+
+ wakeup(f->alog);
+}
diff --git a/sys/src/9/ip/nullmedium.c b/sys/src/9/ip/nullmedium.c
new file mode 100755
index 000000000..bc575c05c
--- /dev/null
+++ b/sys/src/9/ip/nullmedium.c
@@ -0,0 +1,39 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+
+static void
+nullbind(Ipifc*, int, char**)
+{
+ error("cannot bind null device");
+}
+
+static void
+nullunbind(Ipifc*)
+{
+}
+
+static void
+nullbwrite(Ipifc*, Block*, int, uchar*)
+{
+ error("nullbwrite");
+}
+
+Medium nullmedium =
+{
+.name= "null",
+.bind= nullbind,
+.unbind= nullunbind,
+.bwrite= nullbwrite,
+};
+
+void
+nullmediumlink(void)
+{
+ addipmedium(&nullmedium);
+}
diff --git a/sys/src/9/ip/pktmedium.c b/sys/src/9/ip/pktmedium.c
new file mode 100755
index 000000000..81feb3dfb
--- /dev/null
+++ b/sys/src/9/ip/pktmedium.c
@@ -0,0 +1,79 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+
+
+static void pktbind(Ipifc*, int, char**);
+static void pktunbind(Ipifc*);
+static void pktbwrite(Ipifc*, Block*, int, uchar*);
+static void pktin(Fs*, Ipifc*, Block*);
+
+Medium pktmedium =
+{
+.name= "pkt",
+.hsize= 14,
+.mintu= 40,
+.maxtu= 4*1024,
+.maclen= 6,
+.bind= pktbind,
+.unbind= pktunbind,
+.bwrite= pktbwrite,
+.pktin= pktin,
+};
+
+/*
+ * called to bind an IP ifc to an ethernet device
+ * called with ifc wlock'd
+ */
+static void
+pktbind(Ipifc*, int argc, char **argv)
+{
+ USED(argc, argv);
+}
+
+/*
+ * called with ifc wlock'd
+ */
+static void
+pktunbind(Ipifc*)
+{
+}
+
+/*
+ * called by ipoput with a single packet to write
+ */
+static void
+pktbwrite(Ipifc *ifc, Block *bp, int, uchar*)
+{
+ /* enqueue onto the conversation's rq */
+ bp = concatblock(bp);
+ if(ifc->conv->snoopers.ref > 0)
+ qpass(ifc->conv->sq, copyblock(bp, BLEN(bp)));
+ qpass(ifc->conv->rq, bp);
+}
+
+/*
+ * called with ifc rlocked when someone write's to 'data'
+ */
+static void
+pktin(Fs *f, Ipifc *ifc, Block *bp)
+{
+ if(ifc->lifc == nil)
+ freeb(bp);
+ else {
+ if(ifc->conv->snoopers.ref > 0)
+ qpass(ifc->conv->sq, copyblock(bp, BLEN(bp)));
+ ipiput4(f, ifc, bp);
+ }
+}
+
+void
+pktmediumlink(void)
+{
+ addipmedium(&pktmedium);
+}
diff --git a/sys/src/9/ip/ptclbsum.c b/sys/src/9/ip/ptclbsum.c
new file mode 100755
index 000000000..4b895ecff
--- /dev/null
+++ b/sys/src/9/ip/ptclbsum.c
@@ -0,0 +1,72 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "ip.h"
+
+static short endian = 1;
+static uchar* aendian = (uchar*)&endian;
+#define LITTLE *aendian
+
+ushort
+ptclbsum(uchar *addr, int len)
+{
+ ulong losum, hisum, mdsum, x;
+ ulong t1, t2;
+
+ losum = 0;
+ hisum = 0;
+ mdsum = 0;
+
+ x = 0;
+ if((ulong)addr & 1) {
+ if(len) {
+ hisum += addr[0];
+ len--;
+ addr++;
+ }
+ x = 1;
+ }
+ while(len >= 16) {
+ t1 = *(ushort*)(addr+0);
+ t2 = *(ushort*)(addr+2); mdsum += t1;
+ t1 = *(ushort*)(addr+4); mdsum += t2;
+ t2 = *(ushort*)(addr+6); mdsum += t1;
+ t1 = *(ushort*)(addr+8); mdsum += t2;
+ t2 = *(ushort*)(addr+10); mdsum += t1;
+ t1 = *(ushort*)(addr+12); mdsum += t2;
+ t2 = *(ushort*)(addr+14); mdsum += t1;
+ mdsum += t2;
+ len -= 16;
+ addr += 16;
+ }
+ while(len >= 2) {
+ mdsum += *(ushort*)addr;
+ len -= 2;
+ addr += 2;
+ }
+ if(x) {
+ if(len)
+ losum += addr[0];
+ if(LITTLE)
+ losum += mdsum;
+ else
+ hisum += mdsum;
+ } else {
+ if(len)
+ hisum += addr[0];
+ if(LITTLE)
+ hisum += mdsum;
+ else
+ losum += mdsum;
+ }
+
+ losum += hisum >> 8;
+ losum += (hisum & 0xff) << 8;
+ while(hisum = losum>>16)
+ losum = hisum + (losum & 0xffff);
+
+ return losum & 0xffff;
+}
diff --git a/sys/src/9/ip/rudp.c b/sys/src/9/ip/rudp.c
new file mode 100755
index 000000000..f3e205aba
--- /dev/null
+++ b/sys/src/9/ip/rudp.c
@@ -0,0 +1,1055 @@
+/*
+ * Reliable User Datagram Protocol, currently only for IPv4.
+ * This protocol is compatible with UDP's packet format.
+ * It could be done over UDP if need be.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+
+#define DEBUG 0
+#define DPRINT if(DEBUG)print
+
+#define SEQDIFF(a,b) ( (a)>=(b)?\
+ (a)-(b):\
+ 0xffffffffUL-((b)-(a)) )
+#define INSEQ(a,start,end) ( (start)<=(end)?\
+ ((a)>(start)&&(a)<=(end)):\
+ ((a)>(start)||(a)<=(end)) )
+#define UNACKED(r) SEQDIFF(r->sndseq, r->ackrcvd)
+#define NEXTSEQ(a) ( (a)+1 == 0 ? 1 : (a)+1 )
+
+enum
+{
+ UDP_PHDRSIZE = 12, /* pseudo header */
+// UDP_HDRSIZE = 20, /* pseudo header + udp header */
+ UDP_RHDRSIZE = 36, /* pseudo header + udp header + rudp header */
+ UDP_IPHDR = 8, /* ip header */
+ IP_UDPPROTO = 254,
+ UDP_USEAD7 = 52, /* size of new ipv6 headers struct */
+
+ Rudprxms = 200,
+ Rudptickms = 50,
+ Rudpmaxxmit = 10,
+ Maxunacked = 100,
+};
+
+#define Hangupgen 0xffffffff /* used only in hangup messages */
+
+typedef struct Udphdr Udphdr;
+struct Udphdr
+{
+ /* ip header */
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+
+ /* pseudo header starts here */
+ uchar Unused;
+ uchar udpproto; /* Protocol */
+ uchar udpplen[2]; /* Header plus data length */
+ uchar udpsrc[4]; /* Ip source */
+ uchar udpdst[4]; /* Ip destination */
+
+ /* udp header */
+ uchar udpsport[2]; /* Source port */
+ uchar udpdport[2]; /* Destination port */
+ uchar udplen[2]; /* data length */
+ uchar udpcksum[2]; /* Checksum */
+};
+
+typedef struct Rudphdr Rudphdr;
+struct Rudphdr
+{
+ /* ip header */
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+
+ /* pseudo header starts here */
+ uchar Unused;
+ uchar udpproto; /* Protocol */
+ uchar udpplen[2]; /* Header plus data length */
+ uchar udpsrc[4]; /* Ip source */
+ uchar udpdst[4]; /* Ip destination */
+
+ /* udp header */
+ uchar udpsport[2]; /* Source port */
+ uchar udpdport[2]; /* Destination port */
+ uchar udplen[2]; /* data length (includes rudp header) */
+ uchar udpcksum[2]; /* Checksum */
+
+ /* rudp header */
+ uchar relseq[4]; /* id of this packet (or 0) */
+ uchar relsgen[4]; /* generation/time stamp */
+ uchar relack[4]; /* packet being acked (or 0) */
+ uchar relagen[4]; /* generation/time stamp */
+};
+
+
+/*
+ * one state structure per destination
+ */
+typedef struct Reliable Reliable;
+struct Reliable
+{
+ Ref;
+
+ Reliable *next;
+
+ uchar addr[IPaddrlen]; /* always V6 when put here */
+ ushort port;
+
+ Block *unacked; /* unacked msg list */
+ Block *unackedtail; /* and its tail */
+
+ int timeout; /* time since first unacked msg sent */
+ int xmits; /* number of times first unacked msg sent */
+
+ ulong sndseq; /* next packet to be sent */
+ ulong sndgen; /* and its generation */
+
+ ulong rcvseq; /* last packet received */
+ ulong rcvgen; /* and its generation */
+
+ ulong acksent; /* last ack sent */
+ ulong ackrcvd; /* last msg for which ack was rcvd */
+
+ /* flow control */
+ QLock lock;
+ Rendez vous;
+ int blocked;
+};
+
+
+
+/* MIB II counters */
+typedef struct Rudpstats Rudpstats;
+struct Rudpstats
+{
+ ulong rudpInDatagrams;
+ ulong rudpNoPorts;
+ ulong rudpInErrors;
+ ulong rudpOutDatagrams;
+};
+
+typedef struct Rudppriv Rudppriv;
+struct Rudppriv
+{
+ Ipht ht;
+
+ /* MIB counters */
+ Rudpstats ustats;
+
+ /* non-MIB stats */
+ ulong csumerr; /* checksum errors */
+ ulong lenerr; /* short packet */
+ ulong rxmits; /* # of retransmissions */
+ ulong orders; /* # of out of order pkts */
+
+ /* keeping track of the ack kproc */
+ int ackprocstarted;
+ QLock apl;
+};
+
+
+static ulong generation = 0;
+static Rendez rend;
+
+/*
+ * protocol specific part of Conv
+ */
+typedef struct Rudpcb Rudpcb;
+struct Rudpcb
+{
+ QLock;
+ uchar headers;
+ uchar randdrop;
+ Reliable *r;
+};
+
+/*
+ * local functions
+ */
+void relsendack(Conv*, Reliable*, int);
+int reliput(Conv*, Block*, uchar*, ushort);
+Reliable *relstate(Rudpcb*, uchar*, ushort, char*);
+void relput(Reliable*);
+void relforget(Conv *, uchar*, int, int);
+void relackproc(void *);
+void relackq(Reliable *, Block*);
+void relhangup(Conv *, Reliable*);
+void relrexmit(Conv *, Reliable*);
+void relput(Reliable*);
+void rudpkick(void *x);
+
+static void
+rudpstartackproc(Proto *rudp)
+{
+ Rudppriv *rpriv;
+ char kpname[KNAMELEN];
+
+ rpriv = rudp->priv;
+ if(rpriv->ackprocstarted == 0){
+ qlock(&rpriv->apl);
+ if(rpriv->ackprocstarted == 0){
+ sprint(kpname, "#I%drudpack", rudp->f->dev);
+ kproc(kpname, relackproc, rudp);
+ rpriv->ackprocstarted = 1;
+ }
+ qunlock(&rpriv->apl);
+ }
+}
+
+static char*
+rudpconnect(Conv *c, char **argv, int argc)
+{
+ char *e;
+ Rudppriv *upriv;
+
+ upriv = c->p->priv;
+ rudpstartackproc(c->p);
+ e = Fsstdconnect(c, argv, argc);
+ Fsconnected(c, e);
+ iphtadd(&upriv->ht, c);
+
+ return e;
+}
+
+
+static int
+rudpstate(Conv *c, char *state, int n)
+{
+ Rudpcb *ucb;
+ Reliable *r;
+ int m;
+
+ m = snprint(state, n, "%s", c->inuse?"Open":"Closed");
+ ucb = (Rudpcb*)c->ptcl;
+ qlock(ucb);
+ for(r = ucb->r; r; r = r->next)
+ m += snprint(state+m, n-m, " %I/%ld", r->addr, UNACKED(r));
+ m += snprint(state+m, n-m, "\n");
+ qunlock(ucb);
+ return m;
+}
+
+static char*
+rudpannounce(Conv *c, char** argv, int argc)
+{
+ char *e;
+ Rudppriv *upriv;
+
+ upriv = c->p->priv;
+ rudpstartackproc(c->p);
+ e = Fsstdannounce(c, argv, argc);
+ if(e != nil)
+ return e;
+ Fsconnected(c, nil);
+ iphtadd(&upriv->ht, c);
+
+ return nil;
+}
+
+static void
+rudpcreate(Conv *c)
+{
+ c->rq = qopen(64*1024, Qmsg, 0, 0);
+ c->wq = qopen(64*1024, Qkick, rudpkick, c);
+}
+
+static void
+rudpclose(Conv *c)
+{
+ Rudpcb *ucb;
+ Reliable *r, *nr;
+ Rudppriv *upriv;
+
+ upriv = c->p->priv;
+ iphtrem(&upriv->ht, c);
+
+ /* force out any delayed acks */
+ ucb = (Rudpcb*)c->ptcl;
+ qlock(ucb);
+ for(r = ucb->r; r; r = r->next){
+ if(r->acksent != r->rcvseq)
+ relsendack(c, r, 0);
+ }
+ qunlock(ucb);
+
+ qclose(c->rq);
+ qclose(c->wq);
+ qclose(c->eq);
+ ipmove(c->laddr, IPnoaddr);
+ ipmove(c->raddr, IPnoaddr);
+ c->lport = 0;
+ c->rport = 0;
+
+ ucb->headers = 0;
+ ucb->randdrop = 0;
+ qlock(ucb);
+ for(r = ucb->r; r; r = nr){
+ if(r->acksent != r->rcvseq)
+ relsendack(c, r, 0);
+ nr = r->next;
+ relhangup(c, r);
+ relput(r);
+ }
+ ucb->r = 0;
+
+ qunlock(ucb);
+}
+
+/*
+ * randomly don't send packets
+ */
+static void
+doipoput(Conv *c, Fs *f, Block *bp, int x, int ttl, int tos)
+{
+ Rudpcb *ucb;
+
+ ucb = (Rudpcb*)c->ptcl;
+ if(ucb->randdrop && nrand(100) < ucb->randdrop)
+ freeblist(bp);
+ else
+ ipoput4(f, bp, x, ttl, tos, nil);
+}
+
+int
+flow(void *v)
+{
+ Reliable *r = v;
+
+ return UNACKED(r) <= Maxunacked;
+}
+
+void
+rudpkick(void *x)
+{
+ Conv *c = x;
+ Udphdr *uh;
+ ushort rport;
+ uchar laddr[IPaddrlen], raddr[IPaddrlen];
+ Block *bp;
+ Rudpcb *ucb;
+ Rudphdr *rh;
+ Reliable *r;
+ int dlen, ptcllen;
+ Rudppriv *upriv;
+ Fs *f;
+
+ upriv = c->p->priv;
+ f = c->p->f;
+
+ netlog(c->p->f, Logrudp, "rudp: kick\n");
+ bp = qget(c->wq);
+ if(bp == nil)
+ return;
+
+ ucb = (Rudpcb*)c->ptcl;
+ switch(ucb->headers) {
+ case 7:
+ /* get user specified addresses */
+ bp = pullupblock(bp, UDP_USEAD7);
+ if(bp == nil)
+ return;
+ ipmove(raddr, bp->rp);
+ bp->rp += IPaddrlen;
+ ipmove(laddr, bp->rp);
+ bp->rp += IPaddrlen;
+ /* pick interface closest to dest */
+ if(ipforme(f, laddr) != Runi)
+ findlocalip(f, laddr, raddr);
+ bp->rp += IPaddrlen; /* Ignore ifc address */
+ rport = nhgets(bp->rp);
+ bp->rp += 2+2; /* Ignore local port */
+ break;
+ default:
+ ipmove(raddr, c->raddr);
+ ipmove(laddr, c->laddr);
+ rport = c->rport;
+ break;
+ }
+
+ dlen = blocklen(bp);
+
+ /* Make space to fit rudp & ip header */
+ bp = padblock(bp, UDP_IPHDR+UDP_RHDRSIZE);
+ if(bp == nil)
+ return;
+
+ uh = (Udphdr *)(bp->rp);
+ uh->vihl = IP_VER4;
+
+ rh = (Rudphdr*)uh;
+
+ ptcllen = dlen + (UDP_RHDRSIZE-UDP_PHDRSIZE);
+ uh->Unused = 0;
+ uh->udpproto = IP_UDPPROTO;
+ uh->frag[0] = 0;
+ uh->frag[1] = 0;
+ hnputs(uh->udpplen, ptcllen);
+ switch(ucb->headers){
+ case 7:
+ v6tov4(uh->udpdst, raddr);
+ hnputs(uh->udpdport, rport);
+ v6tov4(uh->udpsrc, laddr);
+ break;
+ default:
+ v6tov4(uh->udpdst, c->raddr);
+ hnputs(uh->udpdport, c->rport);
+ if(ipcmp(c->laddr, IPnoaddr) == 0)
+ findlocalip(f, c->laddr, c->raddr);
+ v6tov4(uh->udpsrc, c->laddr);
+ break;
+ }
+ hnputs(uh->udpsport, c->lport);
+ hnputs(uh->udplen, ptcllen);
+ uh->udpcksum[0] = 0;
+ uh->udpcksum[1] = 0;
+
+ qlock(ucb);
+ r = relstate(ucb, raddr, rport, "kick");
+ r->sndseq = NEXTSEQ(r->sndseq);
+ hnputl(rh->relseq, r->sndseq);
+ hnputl(rh->relsgen, r->sndgen);
+
+ hnputl(rh->relack, r->rcvseq); /* ACK last rcvd packet */
+ hnputl(rh->relagen, r->rcvgen);
+
+ if(r->rcvseq != r->acksent)
+ r->acksent = r->rcvseq;
+
+ hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, dlen+UDP_RHDRSIZE));
+
+ relackq(r, bp);
+ qunlock(ucb);
+
+ upriv->ustats.rudpOutDatagrams++;
+
+ DPRINT("sent: %lud/%lud, %lud/%lud\n",
+ r->sndseq, r->sndgen, r->rcvseq, r->rcvgen);
+
+ doipoput(c, f, bp, 0, c->ttl, c->tos);
+
+ if(waserror()) {
+ relput(r);
+ qunlock(&r->lock);
+ nexterror();
+ }
+
+ /* flow control of sorts */
+ qlock(&r->lock);
+ if(UNACKED(r) > Maxunacked){
+ r->blocked = 1;
+ sleep(&r->vous, flow, r);
+ r->blocked = 0;
+ }
+
+ qunlock(&r->lock);
+ relput(r);
+ poperror();
+}
+
+void
+rudpiput(Proto *rudp, Ipifc *ifc, Block *bp)
+{
+ int len, olen, ottl;
+ Udphdr *uh;
+ Conv *c;
+ Rudpcb *ucb;
+ uchar raddr[IPaddrlen], laddr[IPaddrlen];
+ ushort rport, lport;
+ Rudppriv *upriv;
+ Fs *f;
+ uchar *p;
+
+ upriv = rudp->priv;
+ f = rudp->f;
+
+ upriv->ustats.rudpInDatagrams++;
+
+ uh = (Udphdr*)(bp->rp);
+
+ /* Put back pseudo header for checksum
+ * (remember old values for icmpnoconv())
+ */
+ ottl = uh->Unused;
+ uh->Unused = 0;
+ len = nhgets(uh->udplen);
+ olen = nhgets(uh->udpplen);
+ hnputs(uh->udpplen, len);
+
+ v4tov6(raddr, uh->udpsrc);
+ v4tov6(laddr, uh->udpdst);
+ lport = nhgets(uh->udpdport);
+ rport = nhgets(uh->udpsport);
+
+ if(nhgets(uh->udpcksum)) {
+ if(ptclcsum(bp, UDP_IPHDR, len+UDP_PHDRSIZE)) {
+ upriv->ustats.rudpInErrors++;
+ upriv->csumerr++;
+ netlog(f, Logrudp, "rudp: checksum error %I\n", raddr);
+ DPRINT("rudp: checksum error %I\n", raddr);
+ freeblist(bp);
+ return;
+ }
+ }
+
+ qlock(rudp);
+
+ c = iphtlook(&upriv->ht, raddr, rport, laddr, lport);
+ if(c == nil){
+ /* no conversation found */
+ upriv->ustats.rudpNoPorts++;
+ qunlock(rudp);
+ netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,
+ laddr, lport);
+ uh->Unused = ottl;
+ hnputs(uh->udpplen, olen);
+ icmpnoconv(f, bp);
+ freeblist(bp);
+ return;
+ }
+ ucb = (Rudpcb*)c->ptcl;
+ qlock(ucb);
+ qunlock(rudp);
+
+ if(reliput(c, bp, raddr, rport) < 0){
+ qunlock(ucb);
+ freeb(bp);
+ return;
+ }
+
+ /*
+ * Trim the packet down to data size
+ */
+
+ len -= (UDP_RHDRSIZE-UDP_PHDRSIZE);
+ bp = trimblock(bp, UDP_IPHDR+UDP_RHDRSIZE, len);
+ if(bp == nil) {
+ netlog(f, Logrudp, "rudp: len err %I.%d -> %I.%d\n",
+ raddr, rport, laddr, lport);
+ DPRINT("rudp: len err %I.%d -> %I.%d\n",
+ raddr, rport, laddr, lport);
+ upriv->lenerr++;
+ return;
+ }
+
+ netlog(f, Logrudpmsg, "rudp: %I.%d -> %I.%d l %d\n",
+ raddr, rport, laddr, lport, len);
+
+ switch(ucb->headers){
+ case 7:
+ /* pass the src address */
+ bp = padblock(bp, UDP_USEAD7);
+ p = bp->rp;
+ ipmove(p, raddr); p += IPaddrlen;
+ ipmove(p, laddr); p += IPaddrlen;
+ ipmove(p, ifc->lifc->local); p += IPaddrlen;
+ hnputs(p, rport); p += 2;
+ hnputs(p, lport);
+ break;
+ default:
+ /* connection oriented rudp */
+ if(ipcmp(c->raddr, IPnoaddr) == 0){
+ /* save the src address in the conversation */
+ ipmove(c->raddr, raddr);
+ c->rport = rport;
+
+ /* reply with the same ip address (if not broadcast) */
+ if(ipforme(f, laddr) == Runi)
+ ipmove(c->laddr, laddr);
+ else
+ v4tov6(c->laddr, ifc->lifc->local);
+ }
+ break;
+ }
+ if(bp->next)
+ bp = concatblock(bp);
+
+ if(qfull(c->rq)) {
+ netlog(f, Logrudp, "rudp: qfull %I.%d -> %I.%d\n", raddr, rport,
+ laddr, lport);
+ freeblist(bp);
+ }
+ else
+ qpass(c->rq, bp);
+
+ qunlock(ucb);
+}
+
+static char *rudpunknown = "unknown rudp ctl request";
+
+char*
+rudpctl(Conv *c, char **f, int n)
+{
+ Rudpcb *ucb;
+ uchar ip[IPaddrlen];
+ int x;
+
+ ucb = (Rudpcb*)c->ptcl;
+ if(n < 1)
+ return rudpunknown;
+
+ if(strcmp(f[0], "headers") == 0){
+ ucb->headers = 7; /* new headers format */
+ return nil;
+ } else if(strcmp(f[0], "hangup") == 0){
+ if(n < 3)
+ return "bad syntax";
+ if (parseip(ip, f[1]) == -1)
+ return Ebadip;
+ x = atoi(f[2]);
+ qlock(ucb);
+ relforget(c, ip, x, 1);
+ qunlock(ucb);
+ return nil;
+ } else if(strcmp(f[0], "randdrop") == 0){
+ x = 10; /* default is 10% */
+ if(n > 1)
+ x = atoi(f[1]);
+ if(x > 100 || x < 0)
+ return "illegal rudp drop rate";
+ ucb->randdrop = x;
+ return nil;
+ }
+ return rudpunknown;
+}
+
+void
+rudpadvise(Proto *rudp, Block *bp, char *msg)
+{
+ Udphdr *h;
+ uchar source[IPaddrlen], dest[IPaddrlen];
+ ushort psource, pdest;
+ Conv *s, **p;
+
+ h = (Udphdr*)(bp->rp);
+
+ v4tov6(dest, h->udpdst);
+ v4tov6(source, h->udpsrc);
+ psource = nhgets(h->udpsport);
+ pdest = nhgets(h->udpdport);
+
+ /* Look for a connection */
+ for(p = rudp->conv; *p; p++) {
+ s = *p;
+ if(s->rport == pdest)
+ if(s->lport == psource)
+ if(ipcmp(s->raddr, dest) == 0)
+ if(ipcmp(s->laddr, source) == 0){
+ qhangup(s->rq, msg);
+ qhangup(s->wq, msg);
+ break;
+ }
+ }
+ freeblist(bp);
+}
+
+int
+rudpstats(Proto *rudp, char *buf, int len)
+{
+ Rudppriv *upriv;
+
+ upriv = rudp->priv;
+ return snprint(buf, len, "%lud %lud %lud %lud %lud %lud\n",
+ upriv->ustats.rudpInDatagrams,
+ upriv->ustats.rudpNoPorts,
+ upriv->ustats.rudpInErrors,
+ upriv->ustats.rudpOutDatagrams,
+ upriv->rxmits,
+ upriv->orders);
+}
+
+void
+rudpinit(Fs *fs)
+{
+
+ Proto *rudp;
+
+ rudp = smalloc(sizeof(Proto));
+ rudp->priv = smalloc(sizeof(Rudppriv));
+ rudp->name = "rudp";
+ rudp->connect = rudpconnect;
+ rudp->announce = rudpannounce;
+ rudp->ctl = rudpctl;
+ rudp->state = rudpstate;
+ rudp->create = rudpcreate;
+ rudp->close = rudpclose;
+ rudp->rcv = rudpiput;
+ rudp->advise = rudpadvise;
+ rudp->stats = rudpstats;
+ rudp->ipproto = IP_UDPPROTO;
+ rudp->nc = 32;
+ rudp->ptclsize = sizeof(Rudpcb);
+
+ Fsproto(fs, rudp);
+}
+
+/*********************************************/
+/* Here starts the reliable helper functions */
+/*********************************************/
+/*
+ * Enqueue a copy of an unacked block for possible retransmissions
+ */
+void
+relackq(Reliable *r, Block *bp)
+{
+ Block *np;
+
+ np = copyblock(bp, blocklen(bp));
+ if(r->unacked)
+ r->unackedtail->list = np;
+ else {
+ /* restart timer */
+ r->timeout = 0;
+ r->xmits = 1;
+ r->unacked = np;
+ }
+ r->unackedtail = np;
+ np->list = nil;
+}
+
+/*
+ * retransmit unacked blocks
+ */
+void
+relackproc(void *a)
+{
+ Rudpcb *ucb;
+ Proto *rudp;
+ Reliable *r;
+ Conv **s, *c;
+
+ rudp = (Proto *)a;
+
+loop:
+ tsleep(&up->sleep, return0, 0, Rudptickms);
+
+ for(s = rudp->conv; *s; s++) {
+ c = *s;
+ ucb = (Rudpcb*)c->ptcl;
+ qlock(ucb);
+
+ for(r = ucb->r; r; r = r->next) {
+ if(r->unacked != nil){
+ r->timeout += Rudptickms;
+ if(r->timeout > Rudprxms*r->xmits)
+ relrexmit(c, r);
+ }
+ if(r->acksent != r->rcvseq)
+ relsendack(c, r, 0);
+ }
+ qunlock(ucb);
+ }
+ goto loop;
+}
+
+/*
+ * get the state record for a conversation
+ */
+Reliable*
+relstate(Rudpcb *ucb, uchar *addr, ushort port, char *from)
+{
+ Reliable *r, **l;
+
+ l = &ucb->r;
+ for(r = *l; r; r = *l){
+ if(memcmp(addr, r->addr, IPaddrlen) == 0 &&
+ port == r->port)
+ break;
+ l = &r->next;
+ }
+
+ /* no state for this addr/port, create some */
+ if(r == nil){
+ while(generation == 0)
+ generation = rand();
+
+ DPRINT("from %s new state %lud for %I!%ud\n",
+ from, generation, addr, port);
+
+ r = smalloc(sizeof(Reliable));
+ memmove(r->addr, addr, IPaddrlen);
+ r->port = port;
+ r->unacked = 0;
+ if(generation == Hangupgen)
+ generation++;
+ r->sndgen = generation++;
+ r->sndseq = 0;
+ r->ackrcvd = 0;
+ r->rcvgen = 0;
+ r->rcvseq = 0;
+ r->acksent = 0;
+ r->xmits = 0;
+ r->timeout = 0;
+ r->ref = 0;
+ incref(r); /* one reference for being in the list */
+
+ *l = r;
+ }
+
+ incref(r);
+ return r;
+}
+
+void
+relput(Reliable *r)
+{
+ if(decref(r) == 0)
+ free(r);
+}
+
+/*
+ * forget a Reliable state
+ */
+void
+relforget(Conv *c, uchar *ip, int port, int originator)
+{
+ Rudpcb *ucb;
+ Reliable *r, **l;
+
+ ucb = (Rudpcb*)c->ptcl;
+
+ l = &ucb->r;
+ for(r = *l; r; r = *l){
+ if(ipcmp(ip, r->addr) == 0 && port == r->port){
+ *l = r->next;
+ if(originator)
+ relsendack(c, r, 1);
+ relhangup(c, r);
+ relput(r); /* remove from the list */
+ break;
+ }
+ l = &r->next;
+ }
+}
+
+/*
+ * process a rcvd reliable packet. return -1 if not to be passed to user process,
+ * 0 therwise.
+ *
+ * called with ucb locked.
+ */
+int
+reliput(Conv *c, Block *bp, uchar *addr, ushort port)
+{
+ Block *nbp;
+ Rudpcb *ucb;
+ Rudppriv *upriv;
+ Udphdr *uh;
+ Reliable *r;
+ Rudphdr *rh;
+ ulong seq, ack, sgen, agen, ackreal;
+ int rv = -1;
+
+ /* get fields */
+ uh = (Udphdr*)(bp->rp);
+ rh = (Rudphdr*)uh;
+ seq = nhgetl(rh->relseq);
+ sgen = nhgetl(rh->relsgen);
+ ack = nhgetl(rh->relack);
+ agen = nhgetl(rh->relagen);
+
+ upriv = c->p->priv;
+ ucb = (Rudpcb*)c->ptcl;
+ r = relstate(ucb, addr, port, "input");
+
+ DPRINT("rcvd %lud/%lud, %lud/%lud, r->sndgen = %lud\n",
+ seq, sgen, ack, agen, r->sndgen);
+
+ /* if acking an incorrect generation, ignore */
+ if(ack && agen != r->sndgen)
+ goto out;
+
+ /* Look for a hangup */
+ if(sgen == Hangupgen) {
+ if(agen == r->sndgen)
+ relforget(c, addr, port, 0);
+ goto out;
+ }
+
+ /* make sure we're not talking to a new remote side */
+ if(r->rcvgen != sgen){
+ if(seq != 0 && seq != 1)
+ goto out;
+
+ /* new connection */
+ if(r->rcvgen != 0){
+ DPRINT("new con r->rcvgen = %lud, sgen = %lud\n", r->rcvgen, sgen);
+ relhangup(c, r);
+ }
+ r->rcvgen = sgen;
+ }
+
+ /* dequeue acked packets */
+ if(ack && agen == r->sndgen){
+ ackreal = 0;
+ while(r->unacked != nil && INSEQ(ack, r->ackrcvd, r->sndseq)){
+ nbp = r->unacked;
+ r->unacked = nbp->list;
+ DPRINT("%lud/%lud acked, r->sndgen = %lud\n",
+ ack, agen, r->sndgen);
+ freeb(nbp);
+ r->ackrcvd = NEXTSEQ(r->ackrcvd);
+ ackreal = 1;
+ }
+
+ /* flow control */
+ if(UNACKED(r) < Maxunacked/8 && r->blocked)
+ wakeup(&r->vous);
+
+ /*
+ * retransmit next packet if the acked packet
+ * was transmitted more than once
+ */
+ if(ackreal && r->unacked != nil){
+ r->timeout = 0;
+ if(r->xmits > 1){
+ r->xmits = 1;
+ relrexmit(c, r);
+ }
+ }
+
+ }
+
+ /* no message or input queue full */
+ if(seq == 0 || qfull(c->rq))
+ goto out;
+
+ /* refuse out of order delivery */
+ if(seq != NEXTSEQ(r->rcvseq)){
+ relsendack(c, r, 0); /* tell him we got it already */
+ upriv->orders++;
+ DPRINT("out of sequence %lud not %lud\n", seq, NEXTSEQ(r->rcvseq));
+ goto out;
+ }
+ r->rcvseq = seq;
+
+ rv = 0;
+out:
+ relput(r);
+ return rv;
+}
+
+void
+relsendack(Conv *c, Reliable *r, int hangup)
+{
+ Udphdr *uh;
+ Block *bp;
+ Rudphdr *rh;
+ int ptcllen;
+ Fs *f;
+
+ bp = allocb(UDP_IPHDR + UDP_RHDRSIZE);
+ if(bp == nil)
+ return;
+ bp->wp += UDP_IPHDR + UDP_RHDRSIZE;
+ f = c->p->f;
+ uh = (Udphdr *)(bp->rp);
+ uh->vihl = IP_VER4;
+ rh = (Rudphdr*)uh;
+
+ ptcllen = (UDP_RHDRSIZE-UDP_PHDRSIZE);
+ uh->Unused = 0;
+ uh->udpproto = IP_UDPPROTO;
+ uh->frag[0] = 0;
+ uh->frag[1] = 0;
+ hnputs(uh->udpplen, ptcllen);
+
+ v6tov4(uh->udpdst, r->addr);
+ hnputs(uh->udpdport, r->port);
+ hnputs(uh->udpsport, c->lport);
+ if(ipcmp(c->laddr, IPnoaddr) == 0)
+ findlocalip(f, c->laddr, c->raddr);
+ v6tov4(uh->udpsrc, c->laddr);
+ hnputs(uh->udplen, ptcllen);
+
+ if(hangup)
+ hnputl(rh->relsgen, Hangupgen);
+ else
+ hnputl(rh->relsgen, r->sndgen);
+ hnputl(rh->relseq, 0);
+ hnputl(rh->relagen, r->rcvgen);
+ hnputl(rh->relack, r->rcvseq);
+
+ if(r->acksent < r->rcvseq)
+ r->acksent = r->rcvseq;
+
+ uh->udpcksum[0] = 0;
+ uh->udpcksum[1] = 0;
+ hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, UDP_RHDRSIZE));
+
+ DPRINT("sendack: %lud/%lud, %lud/%lud\n", 0L, r->sndgen, r->rcvseq, r->rcvgen);
+ doipoput(c, f, bp, 0, c->ttl, c->tos);
+}
+
+
+/*
+ * called with ucb locked (and c locked if user initiated close)
+ */
+void
+relhangup(Conv *c, Reliable *r)
+{
+ int n;
+ Block *bp;
+ char hup[ERRMAX];
+
+ n = snprint(hup, sizeof(hup), "hangup %I!%d", r->addr, r->port);
+ qproduce(c->eq, hup, n);
+
+ /*
+ * dump any unacked outgoing messages
+ */
+ for(bp = r->unacked; bp != nil; bp = r->unacked){
+ r->unacked = bp->list;
+ bp->list = nil;
+ freeb(bp);
+ }
+
+ r->rcvgen = 0;
+ r->rcvseq = 0;
+ r->acksent = 0;
+ if(generation == Hangupgen)
+ generation++;
+ r->sndgen = generation++;
+ r->sndseq = 0;
+ r->ackrcvd = 0;
+ r->xmits = 0;
+ r->timeout = 0;
+ wakeup(&r->vous);
+}
+
+/*
+ * called with ucb locked
+ */
+void
+relrexmit(Conv *c, Reliable *r)
+{
+ Rudppriv *upriv;
+ Block *np;
+ Fs *f;
+
+ upriv = c->p->priv;
+ f = c->p->f;
+ r->timeout = 0;
+ if(r->xmits++ > Rudpmaxxmit){
+ relhangup(c, r);
+ return;
+ }
+
+ upriv->rxmits++;
+ np = copyblock(r->unacked, blocklen(r->unacked));
+ DPRINT("rxmit r->ackrvcd+1 = %lud\n", r->ackrcvd+1);
+ doipoput(c, f, np, 0, c->ttl, c->tos);
+}
diff --git a/sys/src/9/ip/tcp.c b/sys/src/9/ip/tcp.c
new file mode 100755
index 000000000..f57ef11b3
--- /dev/null
+++ b/sys/src/9/ip/tcp.c
@@ -0,0 +1,3236 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+
+enum
+{
+ QMAX = 64*1024-1,
+ IP_TCPPROTO = 6,
+
+ TCP4_IPLEN = 8,
+ TCP4_PHDRSIZE = 12,
+ TCP4_HDRSIZE = 20,
+ TCP4_TCBPHDRSZ = 40,
+ TCP4_PKT = TCP4_IPLEN+TCP4_PHDRSIZE,
+
+ TCP6_IPLEN = 0,
+ TCP6_PHDRSIZE = 40,
+ TCP6_HDRSIZE = 20,
+ TCP6_TCBPHDRSZ = 60,
+ TCP6_PKT = TCP6_IPLEN+TCP6_PHDRSIZE,
+
+ TcptimerOFF = 0,
+ TcptimerON = 1,
+ TcptimerDONE = 2,
+ MAX_TIME = (1<<20), /* Forever */
+ TCP_ACK = 50, /* Timed ack sequence in ms */
+ MAXBACKMS = 9*60*1000, /* longest backoff time (ms) before hangup */
+
+ URG = 0x20, /* Data marked urgent */
+ ACK = 0x10, /* Acknowledge is valid */
+ PSH = 0x08, /* Whole data pipe is pushed */
+ RST = 0x04, /* Reset connection */
+ SYN = 0x02, /* Pkt. is synchronise */
+ FIN = 0x01, /* Start close down */
+
+ EOLOPT = 0,
+ NOOPOPT = 1,
+ MSSOPT = 2,
+ MSS_LENGTH = 4, /* Maximum segment size */
+ WSOPT = 3,
+ WS_LENGTH = 3, /* Bits to scale window size by */
+ MSL2 = 10,
+ MSPTICK = 50, /* Milliseconds per timer tick */
+ DEF_MSS = 1460, /* Default maximum segment */
+ DEF_MSS6 = 1280, /* Default maximum segment (min) for v6 */
+ DEF_RTT = 500, /* Default round trip */
+ DEF_KAT = 120000, /* Default time (ms) between keep alives */
+ TCP_LISTEN = 0, /* Listen connection */
+ TCP_CONNECT = 1, /* Outgoing connection */
+ SYNACK_RXTIMER = 250, /* ms between SYNACK retransmits */
+
+ TCPREXMTTHRESH = 3, /* dupack threshhold for rxt */
+
+ FORCE = 1,
+ CLONE = 2,
+ RETRAN = 4,
+ ACTIVE = 8,
+ SYNACK = 16,
+
+ LOGAGAIN = 3,
+ LOGDGAIN = 2,
+
+ Closed = 0, /* Connection states */
+ Listen,
+ Syn_sent,
+ Syn_received,
+ Established,
+ Finwait1,
+ Finwait2,
+ Close_wait,
+ Closing,
+ Last_ack,
+ Time_wait,
+
+ Maxlimbo = 1000, /* maximum procs waiting for response to SYN ACK */
+ NLHT = 256, /* hash table size, must be a power of 2 */
+ LHTMASK = NLHT-1,
+
+ HaveWS = 1<<8,
+};
+
+/* Must correspond to the enumeration above */
+char *tcpstates[] =
+{
+ "Closed", "Listen", "Syn_sent", "Syn_received",
+ "Established", "Finwait1", "Finwait2", "Close_wait",
+ "Closing", "Last_ack", "Time_wait"
+};
+
+typedef struct Tcptimer Tcptimer;
+struct Tcptimer
+{
+ Tcptimer *next;
+ Tcptimer *prev;
+ Tcptimer *readynext;
+ int state;
+ int start;
+ int count;
+ void (*func)(void*);
+ void *arg;
+};
+
+/*
+ * v4 and v6 pseudo headers used for
+ * checksuming tcp
+ */
+typedef struct Tcp4hdr Tcp4hdr;
+struct Tcp4hdr
+{
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+ uchar Unused;
+ uchar proto;
+ uchar tcplen[2];
+ uchar tcpsrc[4];
+ uchar tcpdst[4];
+ uchar tcpsport[2];
+ uchar tcpdport[2];
+ uchar tcpseq[4];
+ uchar tcpack[4];
+ uchar tcpflag[2];
+ uchar tcpwin[2];
+ uchar tcpcksum[2];
+ uchar tcpurg[2];
+ /* Options segment */
+ uchar tcpopt[1];
+};
+
+typedef struct Tcp6hdr Tcp6hdr;
+struct Tcp6hdr
+{
+ uchar vcf[4];
+ uchar ploadlen[2];
+ uchar proto;
+ uchar ttl;
+ uchar tcpsrc[IPaddrlen];
+ uchar tcpdst[IPaddrlen];
+ uchar tcpsport[2];
+ uchar tcpdport[2];
+ uchar tcpseq[4];
+ uchar tcpack[4];
+ uchar tcpflag[2];
+ uchar tcpwin[2];
+ uchar tcpcksum[2];
+ uchar tcpurg[2];
+ /* Options segment */
+ uchar tcpopt[1];
+};
+
+/*
+ * this represents the control info
+ * for a single packet. It is derived from
+ * a packet in ntohtcp{4,6}() and stuck into
+ * a packet in htontcp{4,6}().
+ */
+typedef struct Tcp Tcp;
+struct Tcp
+{
+ ushort source;
+ ushort dest;
+ ulong seq;
+ ulong ack;
+ uchar flags;
+ ushort ws; /* window scale option (if not zero) */
+ ulong wnd;
+ ushort urg;
+ ushort mss; /* max segment size option (if not zero) */
+ ushort len; /* size of data */
+};
+
+/*
+ * this header is malloc'd to thread together fragments
+ * waiting to be coalesced
+ */
+typedef struct Reseq Reseq;
+struct Reseq
+{
+ Reseq *next;
+ Tcp seg;
+ Block *bp;
+ ushort length;
+};
+
+/*
+ * the qlock in the Conv locks this structure
+ */
+typedef struct Tcpctl Tcpctl;
+struct Tcpctl
+{
+ uchar state; /* Connection state */
+ uchar type; /* Listening or active connection */
+ uchar code; /* Icmp code */
+ struct {
+ ulong una; /* Unacked data pointer */
+ ulong nxt; /* Next sequence expected */
+ ulong ptr; /* Data pointer */
+ ulong wnd; /* Tcp send window */
+ ulong urg; /* Urgent data pointer */
+ ulong wl2;
+ int scale; /* how much to right shift window in xmitted packets */
+ /* to implement tahoe and reno TCP */
+ ulong dupacks; /* number of duplicate acks rcvd */
+ int recovery; /* loss recovery flag */
+ ulong rxt; /* right window marker for recovery */
+ } snd;
+ struct {
+ ulong nxt; /* Receive pointer to next uchar slot */
+ ulong wnd; /* Receive window incoming */
+ ulong urg; /* Urgent pointer */
+ int blocked;
+ int una; /* unacked data segs */
+ int scale; /* how much to left shift window in rcved packets */
+ } rcv;
+ ulong iss; /* Initial sequence number */
+ int sawwsopt; /* true if we saw a wsopt on the incoming SYN */
+ ulong cwind; /* Congestion window */
+ int scale; /* desired snd.scale */
+ ushort ssthresh; /* Slow start threshold */
+ int resent; /* Bytes just resent */
+ int irs; /* Initial received squence */
+ ushort mss; /* Maximum segment size */
+ int rerecv; /* Overlap of data rerecevived */
+ ulong window; /* Receive window */
+ uchar backoff; /* Exponential backoff counter */
+ int backedoff; /* ms we've backed off for rexmits */
+ uchar flags; /* State flags */
+ Reseq *reseq; /* Resequencing queue */
+ Tcptimer timer; /* Activity timer */
+ Tcptimer acktimer; /* Acknowledge timer */
+ Tcptimer rtt_timer; /* Round trip timer */
+ Tcptimer katimer; /* keep alive timer */
+ ulong rttseq; /* Round trip sequence */
+ int srtt; /* Shortened round trip */
+ int mdev; /* Mean deviation of round trip */
+ int kacounter; /* count down for keep alive */
+ uint sndsyntime; /* time syn sent */
+ ulong time; /* time Finwait2 or Syn_received was sent */
+ int nochecksum; /* non-zero means don't send checksums */
+ int flgcnt; /* number of flags in the sequence (FIN,SEQ) */
+
+ union {
+ Tcp4hdr tcp4hdr;
+ Tcp6hdr tcp6hdr;
+ } protohdr; /* prototype header */
+};
+
+/*
+ * New calls are put in limbo rather than having a conversation structure
+ * allocated. Thus, a SYN attack results in lots of limbo'd calls but not
+ * any real Conv structures mucking things up. Calls in limbo rexmit their
+ * SYN ACK every SYNACK_RXTIMER ms up to 4 times, i.e., they disappear after 1 second.
+ *
+ * In particular they aren't on a listener's queue so that they don't figure
+ * in the input queue limit.
+ *
+ * If 1/2 of a T3 was attacking SYN packets, we'ld have a permanent queue
+ * of 70000 limbo'd calls. Not great for a linear list but doable. Therefore
+ * there is no hashing of this list.
+ */
+typedef struct Limbo Limbo;
+struct Limbo
+{
+ Limbo *next;
+
+ uchar laddr[IPaddrlen];
+ uchar raddr[IPaddrlen];
+ ushort lport;
+ ushort rport;
+ ulong irs; /* initial received sequence */
+ ulong iss; /* initial sent sequence */
+ ushort mss; /* mss from the other end */
+ ushort rcvscale; /* how much to scale rcvd windows */
+ ushort sndscale; /* how much to scale sent windows */
+ ulong lastsend; /* last time we sent a synack */
+ uchar version; /* v4 or v6 */
+ uchar rexmits; /* number of retransmissions */
+};
+
+int tcp_irtt = DEF_RTT; /* Initial guess at round trip time */
+ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent */
+
+enum {
+ /* MIB stats */
+ MaxConn,
+ Mss,
+ ActiveOpens,
+ PassiveOpens,
+ EstabResets,
+ CurrEstab,
+ InSegs,
+ OutSegs,
+ RetransSegs,
+ RetransTimeouts,
+ InErrs,
+ OutRsts,
+
+ /* non-MIB stats */
+ CsumErrs,
+ HlenErrs,
+ LenErrs,
+ OutOfOrder,
+
+ Nstats
+};
+
+static char *statnames[] =
+{
+[MaxConn] "MaxConn",
+[Mss] "MaxSegment",
+[ActiveOpens] "ActiveOpens",
+[PassiveOpens] "PassiveOpens",
+[EstabResets] "EstabResets",
+[CurrEstab] "CurrEstab",
+[InSegs] "InSegs",
+[OutSegs] "OutSegs",
+[RetransSegs] "RetransSegs",
+[RetransTimeouts] "RetransTimeouts",
+[InErrs] "InErrs",
+[OutRsts] "OutRsts",
+[CsumErrs] "CsumErrs",
+[HlenErrs] "HlenErrs",
+[LenErrs] "LenErrs",
+[OutOfOrder] "OutOfOrder",
+};
+
+typedef struct Tcppriv Tcppriv;
+struct Tcppriv
+{
+ /* List of active timers */
+ QLock tl;
+ Tcptimer *timers;
+
+ /* hash table for matching conversations */
+ Ipht ht;
+
+ /* calls in limbo waiting for an ACK to our SYN ACK */
+ int nlimbo;
+ Limbo *lht[NLHT];
+
+ /* for keeping track of tcpackproc */
+ QLock apl;
+ int ackprocstarted;
+
+ uvlong stats[Nstats];
+};
+
+/*
+ * Setting tcpporthogdefense to non-zero enables Dong Lin's
+ * solution to hijacked systems staking out port's as a form
+ * of DoS attack.
+ *
+ * To avoid stateless Conv hogs, we pick a sequence number at random. If
+ * that number gets acked by the other end, we shut down the connection.
+ * Look for tcpporthogdefense in the code.
+ */
+int tcpporthogdefense = 0;
+
+int addreseq(Tcpctl*, Tcppriv*, Tcp*, Block*, ushort);
+void getreseq(Tcpctl*, Tcp*, Block**, ushort*);
+void localclose(Conv*, char*);
+void procsyn(Conv*, Tcp*);
+void tcpiput(Proto*, Ipifc*, Block*);
+void tcpoutput(Conv*);
+int tcptrim(Tcpctl*, Tcp*, Block**, ushort*);
+void tcpstart(Conv*, int);
+void tcptimeout(void*);
+void tcpsndsyn(Conv*, Tcpctl*);
+void tcprcvwin(Conv*);
+void tcpacktimer(void*);
+void tcpkeepalive(void*);
+void tcpsetkacounter(Tcpctl*);
+void tcprxmit(Conv*);
+void tcpsettimer(Tcpctl*);
+void tcpsynackrtt(Conv*);
+void tcpsetscale(Conv*, Tcpctl*, ushort, ushort);
+
+static void limborexmit(Proto*);
+static void limbo(Conv*, uchar*, uchar*, Tcp*, int);
+
+void
+tcpsetstate(Conv *s, uchar newstate)
+{
+ Tcpctl *tcb;
+ uchar oldstate;
+ Tcppriv *tpriv;
+
+ tpriv = s->p->priv;
+
+ tcb = (Tcpctl*)s->ptcl;
+
+ oldstate = tcb->state;
+ if(oldstate == newstate)
+ return;
+
+ if(oldstate == Established)
+ tpriv->stats[CurrEstab]--;
+ if(newstate == Established)
+ tpriv->stats[CurrEstab]++;
+
+ /**
+ print( "%d/%d %s->%s CurrEstab=%d\n", s->lport, s->rport,
+ tcpstates[oldstate], tcpstates[newstate], tpriv->tstats.tcpCurrEstab );
+ **/
+
+ switch(newstate) {
+ case Closed:
+ qclose(s->rq);
+ qclose(s->wq);
+ qclose(s->eq);
+ break;
+
+ case Close_wait: /* Remote closes */
+ qhangup(s->rq, nil);
+ break;
+ }
+
+ tcb->state = newstate;
+
+ if(oldstate == Syn_sent && newstate != Closed)
+ Fsconnected(s, nil);
+}
+
+static char*
+tcpconnect(Conv *c, char **argv, int argc)
+{
+ char *e;
+ Tcpctl *tcb;
+
+ tcb = (Tcpctl*)(c->ptcl);
+ if(tcb->state != Closed)
+ return Econinuse;
+
+ e = Fsstdconnect(c, argv, argc);
+ if(e != nil)
+ return e;
+ tcpstart(c, TCP_CONNECT);
+
+ return nil;
+}
+
+static int
+tcpstate(Conv *c, char *state, int n)
+{
+ Tcpctl *s;
+
+ s = (Tcpctl*)(c->ptcl);
+
+ return snprint(state, n,
+ "%s qin %d qout %d srtt %d mdev %d cwin %lud swin %lud>>%d rwin %lud>>%d timer.start %d timer.count %d rerecv %d katimer.start %d katimer.count %d\n",
+ tcpstates[s->state],
+ c->rq ? qlen(c->rq) : 0,
+ c->wq ? qlen(c->wq) : 0,
+ s->srtt, s->mdev,
+ s->cwind, s->snd.wnd, s->rcv.scale, s->rcv.wnd, s->snd.scale,
+ s->timer.start, s->timer.count, s->rerecv,
+ s->katimer.start, s->katimer.count);
+}
+
+static int
+tcpinuse(Conv *c)
+{
+ Tcpctl *s;
+
+ s = (Tcpctl*)(c->ptcl);
+ return s->state != Closed;
+}
+
+static char*
+tcpannounce(Conv *c, char **argv, int argc)
+{
+ char *e;
+ Tcpctl *tcb;
+
+ tcb = (Tcpctl*)(c->ptcl);
+ if(tcb->state != Closed)
+ return Econinuse;
+
+ e = Fsstdannounce(c, argv, argc);
+ if(e != nil)
+ return e;
+ tcpstart(c, TCP_LISTEN);
+ Fsconnected(c, nil);
+
+ return nil;
+}
+
+/*
+ * tcpclose is always called with the q locked
+ */
+static void
+tcpclose(Conv *c)
+{
+ Tcpctl *tcb;
+
+ tcb = (Tcpctl*)c->ptcl;
+
+ qhangup(c->rq, nil);
+ qhangup(c->wq, nil);
+ qhangup(c->eq, nil);
+ qflush(c->rq);
+
+ switch(tcb->state) {
+ case Listen:
+ /*
+ * reset any incoming calls to this listener
+ */
+ Fsconnected(c, "Hangup");
+
+ localclose(c, nil);
+ break;
+ case Closed:
+ case Syn_sent:
+ localclose(c, nil);
+ break;
+ case Syn_received:
+ case Established:
+ tcb->flgcnt++;
+ tcb->snd.nxt++;
+ tcpsetstate(c, Finwait1);
+ tcpoutput(c);
+ break;
+ case Close_wait:
+ tcb->flgcnt++;
+ tcb->snd.nxt++;
+ tcpsetstate(c, Last_ack);
+ tcpoutput(c);
+ break;
+ }
+}
+
+void
+tcpkick(void *x)
+{
+ Conv *s = x;
+ Tcpctl *tcb;
+
+ tcb = (Tcpctl*)s->ptcl;
+
+ if(waserror()){
+ qunlock(s);
+ nexterror();
+ }
+ qlock(s);
+
+ switch(tcb->state) {
+ case Syn_sent:
+ case Syn_received:
+ case Established:
+ case Close_wait:
+ /*
+ * Push data
+ */
+ tcprcvwin(s);
+ tcpoutput(s);
+ break;
+ default:
+ localclose(s, "Hangup");
+ break;
+ }
+
+ qunlock(s);
+ poperror();
+}
+
+void
+tcprcvwin(Conv *s) /* Call with tcb locked */
+{
+ int w;
+ Tcpctl *tcb;
+
+ tcb = (Tcpctl*)s->ptcl;
+ w = tcb->window - qlen(s->rq);
+ if(w < 0)
+ w = 0;
+ if(w == 0)
+ netlog(s->p->f, Logtcp, "tcprcvwim: window %lud qlen %d\n", tcb->window, qlen(s->rq));
+ tcb->rcv.wnd = w;
+ if(w == 0)
+ tcb->rcv.blocked = 1;
+}
+
+void
+tcpacktimer(void *v)
+{
+ Tcpctl *tcb;
+ Conv *s;
+
+ s = v;
+ tcb = (Tcpctl*)s->ptcl;
+
+ if(waserror()){
+ qunlock(s);
+ nexterror();
+ }
+ qlock(s);
+ if(tcb->state != Closed){
+ tcb->flags |= FORCE;
+ tcprcvwin(s);
+ tcpoutput(s);
+ }
+ qunlock(s);
+ poperror();
+}
+
+static void
+tcpcreate(Conv *c)
+{
+ c->rq = qopen(QMAX, Qcoalesce, tcpacktimer, c);
+ c->wq = qopen((3*QMAX)/2, Qkick, tcpkick, c);
+}
+
+static void
+timerstate(Tcppriv *priv, Tcptimer *t, int newstate)
+{
+ if(newstate != TcptimerON){
+ if(t->state == TcptimerON){
+ /* unchain */
+ if(priv->timers == t){
+ priv->timers = t->next;
+ if(t->prev != nil)
+ panic("timerstate1");
+ }
+ if(t->next)
+ t->next->prev = t->prev;
+ if(t->prev)
+ t->prev->next = t->next;
+ t->next = t->prev = nil;
+ }
+ } else {
+ if(t->state != TcptimerON){
+ /* chain */
+ if(t->prev != nil || t->next != nil)
+ panic("timerstate2");
+ t->prev = nil;
+ t->next = priv->timers;
+ if(t->next)
+ t->next->prev = t;
+ priv->timers = t;
+ }
+ }
+ t->state = newstate;
+}
+
+void
+tcpackproc(void *a)
+{
+ Tcptimer *t, *tp, *timeo;
+ Proto *tcp;
+ Tcppriv *priv;
+ int loop;
+
+ tcp = a;
+ priv = tcp->priv;
+
+ for(;;) {
+ tsleep(&up->sleep, return0, 0, MSPTICK);
+
+ qlock(&priv->tl);
+ timeo = nil;
+ loop = 0;
+ for(t = priv->timers; t != nil; t = tp) {
+ if(loop++ > 10000)
+ panic("tcpackproc1");
+ tp = t->next;
+ if(t->state == TcptimerON) {
+ t->count--;
+ if(t->count == 0) {
+ timerstate(priv, t, TcptimerDONE);
+ t->readynext = timeo;
+ timeo = t;
+ }
+ }
+ }
+ qunlock(&priv->tl);
+
+ loop = 0;
+ for(t = timeo; t != nil; t = t->readynext) {
+ if(loop++ > 10000)
+ panic("tcpackproc2");
+ if(t->state == TcptimerDONE && t->func != nil && !waserror()){
+ (*t->func)(t->arg);
+ poperror();
+ }
+ }
+
+ limborexmit(tcp);
+ }
+}
+
+void
+tcpgo(Tcppriv *priv, Tcptimer *t)
+{
+ if(t == nil || t->start == 0)
+ return;
+
+ qlock(&priv->tl);
+ t->count = t->start;
+ timerstate(priv, t, TcptimerON);
+ qunlock(&priv->tl);
+}
+
+void
+tcphalt(Tcppriv *priv, Tcptimer *t)
+{
+ if(t == nil)
+ return;
+
+ qlock(&priv->tl);
+ timerstate(priv, t, TcptimerOFF);
+ qunlock(&priv->tl);
+}
+
+int
+backoff(int n)
+{
+ return 1 << n;
+}
+
+void
+localclose(Conv *s, char *reason) /* called with tcb locked */
+{
+ Tcpctl *tcb;
+ Reseq *rp,*rp1;
+ Tcppriv *tpriv;
+
+ tpriv = s->p->priv;
+ tcb = (Tcpctl*)s->ptcl;
+
+ iphtrem(&tpriv->ht, s);
+
+ tcphalt(tpriv, &tcb->timer);
+ tcphalt(tpriv, &tcb->rtt_timer);
+ tcphalt(tpriv, &tcb->acktimer);
+ tcphalt(tpriv, &tcb->katimer);
+
+ /* Flush reassembly queue; nothing more can arrive */
+ for(rp = tcb->reseq; rp != nil; rp = rp1) {
+ rp1 = rp->next;
+ freeblist(rp->bp);
+ free(rp);
+ }
+ tcb->reseq = nil;
+
+ if(tcb->state == Syn_sent)
+ Fsconnected(s, reason);
+ if(s->state == Announced)
+ wakeup(&s->listenr);
+
+ qhangup(s->rq, reason);
+ qhangup(s->wq, reason);
+
+ tcpsetstate(s, Closed);
+}
+
+/* mtu (- TCP + IP hdr len) of 1st hop */
+int
+tcpmtu(Proto *tcp, uchar *addr, int version, int *scale)
+{
+ Ipifc *ifc;
+ int mtu;
+
+ ifc = findipifc(tcp->f, addr, 0);
+ switch(version){
+ default:
+ case V4:
+ mtu = DEF_MSS;
+ if(ifc != nil)
+ mtu = ifc->maxtu - ifc->m->hsize - (TCP4_PKT + TCP4_HDRSIZE);
+ break;
+ case V6:
+ mtu = DEF_MSS6;
+ if(ifc != nil)
+ mtu = ifc->maxtu - ifc->m->hsize - (TCP6_PKT + TCP6_HDRSIZE);
+ break;
+ }
+ if(ifc != nil){
+ if(ifc->mbps > 1000)
+ *scale = HaveWS | 4;
+ else if(ifc->mbps > 100)
+ *scale = HaveWS | 3;
+ else if(ifc->mbps > 10)
+ *scale = HaveWS | 1;
+ else
+ *scale = HaveWS | 0;
+ } else
+ *scale = HaveWS | 0;
+
+ return mtu;
+}
+
+void
+inittcpctl(Conv *s, int mode)
+{
+ Tcpctl *tcb;
+ Tcp4hdr* h4;
+ Tcp6hdr* h6;
+ Tcppriv *tpriv;
+ int mss;
+
+ tcb = (Tcpctl*)s->ptcl;
+
+ memset(tcb, 0, sizeof(Tcpctl));
+
+ tcb->ssthresh = 65535;
+ tcb->srtt = tcp_irtt<<LOGAGAIN;
+ tcb->mdev = 0;
+
+ /* setup timers */
+ tcb->timer.start = tcp_irtt / MSPTICK;
+ tcb->timer.func = tcptimeout;
+ tcb->timer.arg = s;
+ tcb->rtt_timer.start = MAX_TIME;
+ tcb->acktimer.start = TCP_ACK / MSPTICK;
+ tcb->acktimer.func = tcpacktimer;
+ tcb->acktimer.arg = s;
+ tcb->katimer.start = DEF_KAT / MSPTICK;
+ tcb->katimer.func = tcpkeepalive;
+ tcb->katimer.arg = s;
+
+ mss = DEF_MSS;
+
+ /* create a prototype(pseudo) header */
+ if(mode != TCP_LISTEN){
+ if(ipcmp(s->laddr, IPnoaddr) == 0)
+ findlocalip(s->p->f, s->laddr, s->raddr);
+
+ switch(s->ipversion){
+ case V4:
+ h4 = &tcb->protohdr.tcp4hdr;
+ memset(h4, 0, sizeof(*h4));
+ h4->proto = IP_TCPPROTO;
+ hnputs(h4->tcpsport, s->lport);
+ hnputs(h4->tcpdport, s->rport);
+ v6tov4(h4->tcpsrc, s->laddr);
+ v6tov4(h4->tcpdst, s->raddr);
+ break;
+ case V6:
+ h6 = &tcb->protohdr.tcp6hdr;
+ memset(h6, 0, sizeof(*h6));
+ h6->proto = IP_TCPPROTO;
+ hnputs(h6->tcpsport, s->lport);
+ hnputs(h6->tcpdport, s->rport);
+ ipmove(h6->tcpsrc, s->laddr);
+ ipmove(h6->tcpdst, s->raddr);
+ mss = DEF_MSS6;
+ break;
+ default:
+ panic("inittcpctl: version %d", s->ipversion);
+ }
+ }
+
+ tcb->mss = tcb->cwind = mss;
+ tpriv = s->p->priv;
+ tpriv->stats[Mss] = tcb->mss;
+
+ /* default is no window scaling */
+ tcb->window = QMAX;
+ tcb->rcv.wnd = QMAX;
+ tcb->rcv.scale = 0;
+ tcb->snd.scale = 0;
+ qsetlimit(s->rq, QMAX);
+}
+
+/*
+ * called with s qlocked
+ */
+void
+tcpstart(Conv *s, int mode)
+{
+ Tcpctl *tcb;
+ Tcppriv *tpriv;
+ char kpname[KNAMELEN];
+
+ tpriv = s->p->priv;
+
+ if(tpriv->ackprocstarted == 0){
+ qlock(&tpriv->apl);
+ if(tpriv->ackprocstarted == 0){
+ sprint(kpname, "#I%dtcpack", s->p->f->dev);
+ kproc(kpname, tcpackproc, s->p);
+ tpriv->ackprocstarted = 1;
+ }
+ qunlock(&tpriv->apl);
+ }
+
+ tcb = (Tcpctl*)s->ptcl;
+
+ inittcpctl(s, mode);
+
+ iphtadd(&tpriv->ht, s);
+ switch(mode) {
+ case TCP_LISTEN:
+ tpriv->stats[PassiveOpens]++;
+ tcb->flags |= CLONE;
+ tcpsetstate(s, Listen);
+ break;
+
+ case TCP_CONNECT:
+ tpriv->stats[ActiveOpens]++;
+ tcb->flags |= ACTIVE;
+ tcpsndsyn(s, tcb);
+ tcpsetstate(s, Syn_sent);
+ tcpoutput(s);
+ break;
+ }
+}
+
+static char*
+tcpflag(ushort flag)
+{
+ static char buf[128];
+
+ sprint(buf, "%d", flag>>10); /* Head len */
+ if(flag & URG)
+ strcat(buf, " URG");
+ if(flag & ACK)
+ strcat(buf, " ACK");
+ if(flag & PSH)
+ strcat(buf, " PSH");
+ if(flag & RST)
+ strcat(buf, " RST");
+ if(flag & SYN)
+ strcat(buf, " SYN");
+ if(flag & FIN)
+ strcat(buf, " FIN");
+
+ return buf;
+}
+
+Block *
+htontcp6(Tcp *tcph, Block *data, Tcp6hdr *ph, Tcpctl *tcb)
+{
+ int dlen;
+ Tcp6hdr *h;
+ ushort csum;
+ ushort hdrlen, optpad = 0;
+ uchar *opt;
+
+ hdrlen = TCP6_HDRSIZE;
+ if(tcph->flags & SYN){
+ if(tcph->mss)
+ hdrlen += MSS_LENGTH;
+ if(tcph->ws)
+ hdrlen += WS_LENGTH;
+ optpad = hdrlen & 3;
+ if(optpad)
+ optpad = 4 - optpad;
+ hdrlen += optpad;
+ }
+
+ if(data) {
+ dlen = blocklen(data);
+ data = padblock(data, hdrlen + TCP6_PKT);
+ if(data == nil)
+ return nil;
+ }
+ else {
+ dlen = 0;
+ data = allocb(hdrlen + TCP6_PKT + 64); /* the 64 pad is to meet mintu's */
+ if(data == nil)
+ return nil;
+ data->wp += hdrlen + TCP6_PKT;
+ }
+
+ /* copy in pseudo ip header plus port numbers */
+ h = (Tcp6hdr *)(data->rp);
+ memmove(h, ph, TCP6_TCBPHDRSZ);
+
+ /* compose pseudo tcp header, do cksum calculation */
+ hnputl(h->vcf, hdrlen + dlen);
+ h->ploadlen[0] = h->ploadlen[1] = h->proto = 0;
+ h->ttl = ph->proto;
+
+ /* copy in variable bits */
+ hnputl(h->tcpseq, tcph->seq);
+ hnputl(h->tcpack, tcph->ack);
+ hnputs(h->tcpflag, (hdrlen<<10) | tcph->flags);
+ hnputs(h->tcpwin, tcph->wnd>>(tcb != nil ? tcb->snd.scale : 0));
+ hnputs(h->tcpurg, tcph->urg);
+
+ if(tcph->flags & SYN){
+ opt = h->tcpopt;
+ if(tcph->mss != 0){
+ *opt++ = MSSOPT;
+ *opt++ = MSS_LENGTH;
+ hnputs(opt, tcph->mss);
+// print("our outgoing mss %d\n", tcph->mss);
+ opt += 2;
+ }
+ if(tcph->ws != 0){
+ *opt++ = WSOPT;
+ *opt++ = WS_LENGTH;
+ *opt++ = tcph->ws;
+ }
+ while(optpad-- > 0)
+ *opt++ = NOOPOPT;
+ }
+
+ if(tcb != nil && tcb->nochecksum){
+ h->tcpcksum[0] = h->tcpcksum[1] = 0;
+ } else {
+ csum = ptclcsum(data, TCP6_IPLEN, hdrlen+dlen+TCP6_PHDRSIZE);
+ hnputs(h->tcpcksum, csum);
+ }
+
+ /* move from pseudo header back to normal ip header */
+ memset(h->vcf, 0, 4);
+ h->vcf[0] = IP_VER6;
+ hnputs(h->ploadlen, hdrlen+dlen);
+ h->proto = ph->proto;
+
+ return data;
+}
+
+Block *
+htontcp4(Tcp *tcph, Block *data, Tcp4hdr *ph, Tcpctl *tcb)
+{
+ int dlen;
+ Tcp4hdr *h;
+ ushort csum;
+ ushort hdrlen, optpad = 0;
+ uchar *opt;
+
+ hdrlen = TCP4_HDRSIZE;
+ if(tcph->flags & SYN){
+ if(tcph->mss)
+ hdrlen += MSS_LENGTH;
+ if(tcph->ws)
+ hdrlen += WS_LENGTH;
+ optpad = hdrlen & 3;
+ if(optpad)
+ optpad = 4 - optpad;
+ hdrlen += optpad;
+ }
+
+ if(data) {
+ dlen = blocklen(data);
+ data = padblock(data, hdrlen + TCP4_PKT);
+ if(data == nil)
+ return nil;
+ }
+ else {
+ dlen = 0;
+ data = allocb(hdrlen + TCP4_PKT + 64); /* the 64 pad is to meet mintu's */
+ if(data == nil)
+ return nil;
+ data->wp += hdrlen + TCP4_PKT;
+ }
+
+ /* copy in pseudo ip header plus port numbers */
+ h = (Tcp4hdr *)(data->rp);
+ memmove(h, ph, TCP4_TCBPHDRSZ);
+
+ /* copy in variable bits */
+ hnputs(h->tcplen, hdrlen + dlen);
+ hnputl(h->tcpseq, tcph->seq);
+ hnputl(h->tcpack, tcph->ack);
+ hnputs(h->tcpflag, (hdrlen<<10) | tcph->flags);
+ hnputs(h->tcpwin, tcph->wnd>>(tcb != nil ? tcb->snd.scale : 0));
+ hnputs(h->tcpurg, tcph->urg);
+
+ if(tcph->flags & SYN){
+ opt = h->tcpopt;
+ if(tcph->mss != 0){
+ *opt++ = MSSOPT;
+ *opt++ = MSS_LENGTH;
+ hnputs(opt, tcph->mss);
+ opt += 2;
+ }
+ if(tcph->ws != 0){
+ *opt++ = WSOPT;
+ *opt++ = WS_LENGTH;
+ *opt++ = tcph->ws;
+ }
+ while(optpad-- > 0)
+ *opt++ = NOOPOPT;
+ }
+
+ if(tcb != nil && tcb->nochecksum){
+ h->tcpcksum[0] = h->tcpcksum[1] = 0;
+ } else {
+ csum = ptclcsum(data, TCP4_IPLEN, hdrlen+dlen+TCP4_PHDRSIZE);
+ hnputs(h->tcpcksum, csum);
+ }
+
+ return data;
+}
+
+int
+ntohtcp6(Tcp *tcph, Block **bpp)
+{
+ Tcp6hdr *h;
+ uchar *optr;
+ ushort hdrlen;
+ ushort optlen;
+ int n;
+
+ *bpp = pullupblock(*bpp, TCP6_PKT+TCP6_HDRSIZE);
+ if(*bpp == nil)
+ return -1;
+
+ h = (Tcp6hdr *)((*bpp)->rp);
+ tcph->source = nhgets(h->tcpsport);
+ tcph->dest = nhgets(h->tcpdport);
+ tcph->seq = nhgetl(h->tcpseq);
+ tcph->ack = nhgetl(h->tcpack);
+ hdrlen = (h->tcpflag[0]>>2) & ~3;
+ if(hdrlen < TCP6_HDRSIZE) {
+ freeblist(*bpp);
+ return -1;
+ }
+
+ tcph->flags = h->tcpflag[1];
+ tcph->wnd = nhgets(h->tcpwin);
+ tcph->urg = nhgets(h->tcpurg);
+ tcph->mss = 0;
+ tcph->ws = 0;
+ tcph->len = nhgets(h->ploadlen) - hdrlen;
+
+ *bpp = pullupblock(*bpp, hdrlen+TCP6_PKT);
+ if(*bpp == nil)
+ return -1;
+
+ optr = h->tcpopt;
+ n = hdrlen - TCP6_HDRSIZE;
+ while(n > 0 && *optr != EOLOPT) {
+ if(*optr == NOOPOPT) {
+ n--;
+ optr++;
+ continue;
+ }
+ optlen = optr[1];
+ if(optlen < 2 || optlen > n)
+ break;
+ switch(*optr) {
+ case MSSOPT:
+ if(optlen == MSS_LENGTH)
+ tcph->mss = nhgets(optr+2);
+ break;
+ case WSOPT:
+ if(optlen == WS_LENGTH && *(optr+2) <= 14)
+ tcph->ws = HaveWS | *(optr+2);
+ break;
+ }
+ n -= optlen;
+ optr += optlen;
+ }
+ return hdrlen;
+}
+
+int
+ntohtcp4(Tcp *tcph, Block **bpp)
+{
+ Tcp4hdr *h;
+ uchar *optr;
+ ushort hdrlen;
+ ushort optlen;
+ int n;
+
+ *bpp = pullupblock(*bpp, TCP4_PKT+TCP4_HDRSIZE);
+ if(*bpp == nil)
+ return -1;
+
+ h = (Tcp4hdr *)((*bpp)->rp);
+ tcph->source = nhgets(h->tcpsport);
+ tcph->dest = nhgets(h->tcpdport);
+ tcph->seq = nhgetl(h->tcpseq);
+ tcph->ack = nhgetl(h->tcpack);
+
+ hdrlen = (h->tcpflag[0]>>2) & ~3;
+ if(hdrlen < TCP4_HDRSIZE) {
+ freeblist(*bpp);
+ return -1;
+ }
+
+ tcph->flags = h->tcpflag[1];
+ tcph->wnd = nhgets(h->tcpwin);
+ tcph->urg = nhgets(h->tcpurg);
+ tcph->mss = 0;
+ tcph->ws = 0;
+ tcph->len = nhgets(h->length) - (hdrlen + TCP4_PKT);
+
+ *bpp = pullupblock(*bpp, hdrlen+TCP4_PKT);
+ if(*bpp == nil)
+ return -1;
+
+ optr = h->tcpopt;
+ n = hdrlen - TCP4_HDRSIZE;
+ while(n > 0 && *optr != EOLOPT) {
+ if(*optr == NOOPOPT) {
+ n--;
+ optr++;
+ continue;
+ }
+ optlen = optr[1];
+ if(optlen < 2 || optlen > n)
+ break;
+ switch(*optr) {
+ case MSSOPT:
+ if(optlen == MSS_LENGTH) {
+ tcph->mss = nhgets(optr+2);
+// print("new incoming mss %d\n", tcph->mss);
+ }
+ break;
+ case WSOPT:
+ if(optlen == WS_LENGTH && *(optr+2) <= 14)
+ tcph->ws = HaveWS | *(optr+2);
+ break;
+ }
+ n -= optlen;
+ optr += optlen;
+ }
+ return hdrlen;
+}
+
+/*
+ * For outgiing calls, generate an initial sequence
+ * number and put a SYN on the send queue
+ */
+void
+tcpsndsyn(Conv *s, Tcpctl *tcb)
+{
+ Tcppriv *tpriv;
+
+ tcb->iss = (nrand(1<<16)<<16)|nrand(1<<16);
+ tcb->rttseq = tcb->iss;
+ tcb->snd.wl2 = tcb->iss;
+ tcb->snd.una = tcb->iss;
+ tcb->snd.ptr = tcb->rttseq;
+ tcb->snd.nxt = tcb->rttseq;
+ tcb->flgcnt++;
+ tcb->flags |= FORCE;
+ tcb->sndsyntime = NOW;
+
+ /* set desired mss and scale */
+ tcb->mss = tcpmtu(s->p, s->laddr, s->ipversion, &tcb->scale);
+ tpriv = s->p->priv;
+ tpriv->stats[Mss] = tcb->mss;
+}
+
+void
+sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg, uchar version, char *reason)
+{
+ Block *hbp;
+ uchar rflags;
+ Tcppriv *tpriv;
+ Tcp4hdr ph4;
+ Tcp6hdr ph6;
+
+ netlog(tcp->f, Logtcp, "sndrst: %s\n", reason);
+
+ tpriv = tcp->priv;
+
+ if(seg->flags & RST)
+ return;
+
+ /* make pseudo header */
+ switch(version) {
+ case V4:
+ memset(&ph4, 0, sizeof(ph4));
+ ph4.vihl = IP_VER4;
+ v6tov4(ph4.tcpsrc, dest);
+ v6tov4(ph4.tcpdst, source);
+ ph4.proto = IP_TCPPROTO;
+ hnputs(ph4.tcplen, TCP4_HDRSIZE);
+ hnputs(ph4.tcpsport, seg->dest);
+ hnputs(ph4.tcpdport, seg->source);
+ break;
+ case V6:
+ memset(&ph6, 0, sizeof(ph6));
+ ph6.vcf[0] = IP_VER6;
+ ipmove(ph6.tcpsrc, dest);
+ ipmove(ph6.tcpdst, source);
+ ph6.proto = IP_TCPPROTO;
+ hnputs(ph6.ploadlen, TCP6_HDRSIZE);
+ hnputs(ph6.tcpsport, seg->dest);
+ hnputs(ph6.tcpdport, seg->source);
+ break;
+ default:
+ panic("sndrst: version %d", version);
+ }
+
+ tpriv->stats[OutRsts]++;
+ rflags = RST;
+
+ /* convince the other end that this reset is in band */
+ if(seg->flags & ACK) {
+ seg->seq = seg->ack;
+ seg->ack = 0;
+ }
+ else {
+ rflags |= ACK;
+ seg->ack = seg->seq;
+ seg->seq = 0;
+ if(seg->flags & SYN)
+ seg->ack++;
+ seg->ack += length;
+ if(seg->flags & FIN)
+ seg->ack++;
+ }
+ seg->flags = rflags;
+ seg->wnd = 0;
+ seg->urg = 0;
+ seg->mss = 0;
+ seg->ws = 0;
+ switch(version) {
+ case V4:
+ hbp = htontcp4(seg, nil, &ph4, nil);
+ if(hbp == nil)
+ return;
+ ipoput4(tcp->f, hbp, 0, MAXTTL, DFLTTOS, nil);
+ break;
+ case V6:
+ hbp = htontcp6(seg, nil, &ph6, nil);
+ if(hbp == nil)
+ return;
+ ipoput6(tcp->f, hbp, 0, MAXTTL, DFLTTOS, nil);
+ break;
+ default:
+ panic("sndrst2: version %d", version);
+ }
+}
+
+/*
+ * send a reset to the remote side and close the conversation
+ * called with s qlocked
+ */
+char*
+tcphangup(Conv *s)
+{
+ Tcp seg;
+ Tcpctl *tcb;
+ Block *hbp;
+
+ tcb = (Tcpctl*)s->ptcl;
+ if(waserror())
+ return commonerror();
+ if(ipcmp(s->raddr, IPnoaddr) != 0) {
+ if(!waserror()){
+ seg.flags = RST | ACK;
+ seg.ack = tcb->rcv.nxt;
+ tcb->rcv.una = 0;
+ seg.seq = tcb->snd.ptr;
+ seg.wnd = 0;
+ seg.urg = 0;
+ seg.mss = 0;
+ seg.ws = 0;
+ switch(s->ipversion) {
+ case V4:
+ tcb->protohdr.tcp4hdr.vihl = IP_VER4;
+ hbp = htontcp4(&seg, nil, &tcb->protohdr.tcp4hdr, tcb);
+ ipoput4(s->p->f, hbp, 0, s->ttl, s->tos, s);
+ break;
+ case V6:
+ tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
+ hbp = htontcp6(&seg, nil, &tcb->protohdr.tcp6hdr, tcb);
+ ipoput6(s->p->f, hbp, 0, s->ttl, s->tos, s);
+ break;
+ default:
+ panic("tcphangup: version %d", s->ipversion);
+ }
+ poperror();
+ }
+ }
+ localclose(s, nil);
+ poperror();
+ return nil;
+}
+
+/*
+ * (re)send a SYN ACK
+ */
+int
+sndsynack(Proto *tcp, Limbo *lp)
+{
+ Block *hbp;
+ Tcp4hdr ph4;
+ Tcp6hdr ph6;
+ Tcp seg;
+ int scale;
+
+ /* make pseudo header */
+ switch(lp->version) {
+ case V4:
+ memset(&ph4, 0, sizeof(ph4));
+ ph4.vihl = IP_VER4;
+ v6tov4(ph4.tcpsrc, lp->laddr);
+ v6tov4(ph4.tcpdst, lp->raddr);
+ ph4.proto = IP_TCPPROTO;
+ hnputs(ph4.tcplen, TCP4_HDRSIZE);
+ hnputs(ph4.tcpsport, lp->lport);
+ hnputs(ph4.tcpdport, lp->rport);
+ break;
+ case V6:
+ memset(&ph6, 0, sizeof(ph6));
+ ph6.vcf[0] = IP_VER6;
+ ipmove(ph6.tcpsrc, lp->laddr);
+ ipmove(ph6.tcpdst, lp->raddr);
+ ph6.proto = IP_TCPPROTO;
+ hnputs(ph6.ploadlen, TCP6_HDRSIZE);
+ hnputs(ph6.tcpsport, lp->lport);
+ hnputs(ph6.tcpdport, lp->rport);
+ break;
+ default:
+ panic("sndrst: version %d", lp->version);
+ }
+
+ seg.seq = lp->iss;
+ seg.ack = lp->irs+1;
+ seg.flags = SYN|ACK;
+ seg.urg = 0;
+ seg.mss = tcpmtu(tcp, lp->laddr, lp->version, &scale);
+// if (seg.mss > lp->mss && lp->mss >= 512)
+// seg.mss = lp->mss;
+ seg.wnd = QMAX;
+
+ /* if the other side set scale, we should too */
+ if(lp->rcvscale){
+ seg.ws = scale;
+ lp->sndscale = scale;
+ } else {
+ seg.ws = 0;
+ lp->sndscale = 0;
+ }
+
+ switch(lp->version) {
+ case V4:
+ hbp = htontcp4(&seg, nil, &ph4, nil);
+ if(hbp == nil)
+ return -1;
+ ipoput4(tcp->f, hbp, 0, MAXTTL, DFLTTOS, nil);
+ break;
+ case V6:
+ hbp = htontcp6(&seg, nil, &ph6, nil);
+ if(hbp == nil)
+ return -1;
+ ipoput6(tcp->f, hbp, 0, MAXTTL, DFLTTOS, nil);
+ break;
+ default:
+ panic("sndsnack: version %d", lp->version);
+ }
+ lp->lastsend = NOW;
+ return 0;
+}
+
+#define hashipa(a, p) ( ( (a)[IPaddrlen-2] + (a)[IPaddrlen-1] + p )&LHTMASK )
+
+/*
+ * put a call into limbo and respond with a SYN ACK
+ *
+ * called with proto locked
+ */
+static void
+limbo(Conv *s, uchar *source, uchar *dest, Tcp *seg, int version)
+{
+ Limbo *lp, **l;
+ Tcppriv *tpriv;
+ int h;
+
+ tpriv = s->p->priv;
+ h = hashipa(source, seg->source);
+
+ for(l = &tpriv->lht[h]; *l != nil; l = &lp->next){
+ lp = *l;
+ if(lp->lport != seg->dest || lp->rport != seg->source || lp->version != version)
+ continue;
+ if(ipcmp(lp->raddr, source) != 0)
+ continue;
+ if(ipcmp(lp->laddr, dest) != 0)
+ continue;
+
+ /* each new SYN restarts the retransmits */
+ lp->irs = seg->seq;
+ break;
+ }
+ lp = *l;
+ if(lp == nil){
+ if(tpriv->nlimbo >= Maxlimbo && tpriv->lht[h]){
+ lp = tpriv->lht[h];
+ tpriv->lht[h] = lp->next;
+ lp->next = nil;
+ } else {
+ lp = malloc(sizeof(*lp));
+ if(lp == nil)
+ return;
+ tpriv->nlimbo++;
+ }
+ *l = lp;
+ lp->version = version;
+ ipmove(lp->laddr, dest);
+ ipmove(lp->raddr, source);
+ lp->lport = seg->dest;
+ lp->rport = seg->source;
+ lp->mss = seg->mss;
+ lp->rcvscale = seg->ws;
+ lp->irs = seg->seq;
+ lp->iss = (nrand(1<<16)<<16)|nrand(1<<16);
+ }
+
+ if(sndsynack(s->p, lp) < 0){
+ *l = lp->next;
+ tpriv->nlimbo--;
+ free(lp);
+ }
+}
+
+/*
+ * resend SYN ACK's once every SYNACK_RXTIMER ms.
+ */
+static void
+limborexmit(Proto *tcp)
+{
+ Tcppriv *tpriv;
+ Limbo **l, *lp;
+ int h;
+ int seen;
+ ulong now;
+
+ tpriv = tcp->priv;
+
+ if(!canqlock(tcp))
+ return;
+ seen = 0;
+ now = NOW;
+ for(h = 0; h < NLHT && seen < tpriv->nlimbo; h++){
+ for(l = &tpriv->lht[h]; *l != nil && seen < tpriv->nlimbo; ){
+ lp = *l;
+ seen++;
+ if(now - lp->lastsend < (lp->rexmits+1)*SYNACK_RXTIMER)
+ continue;
+
+ /* time it out after 1 second */
+ if(++(lp->rexmits) > 5){
+ tpriv->nlimbo--;
+ *l = lp->next;
+ free(lp);
+ continue;
+ }
+
+ /* if we're being attacked, don't bother resending SYN ACK's */
+ if(tpriv->nlimbo > 100)
+ continue;
+
+ if(sndsynack(tcp, lp) < 0){
+ tpriv->nlimbo--;
+ *l = lp->next;
+ free(lp);
+ continue;
+ }
+
+ l = &lp->next;
+ }
+ }
+ qunlock(tcp);
+}
+
+/*
+ * lookup call in limbo. if found, throw it out.
+ *
+ * called with proto locked
+ */
+static void
+limborst(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version)
+{
+ Limbo *lp, **l;
+ int h;
+ Tcppriv *tpriv;
+
+ tpriv = s->p->priv;
+
+ /* find a call in limbo */
+ h = hashipa(src, segp->source);
+ for(l = &tpriv->lht[h]; *l != nil; l = &lp->next){
+ lp = *l;
+ if(lp->lport != segp->dest || lp->rport != segp->source || lp->version != version)
+ continue;
+ if(ipcmp(lp->laddr, dst) != 0)
+ continue;
+ if(ipcmp(lp->raddr, src) != 0)
+ continue;
+
+ /* RST can only follow the SYN */
+ if(segp->seq == lp->irs+1){
+ tpriv->nlimbo--;
+ *l = lp->next;
+ free(lp);
+ }
+ break;
+ }
+}
+
+/*
+ * come here when we finally get an ACK to our SYN-ACK.
+ * lookup call in limbo. if found, create a new conversation
+ *
+ * called with proto locked
+ */
+static Conv*
+tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version)
+{
+ Conv *new;
+ Tcpctl *tcb;
+ Tcppriv *tpriv;
+ Tcp4hdr *h4;
+ Tcp6hdr *h6;
+ Limbo *lp, **l;
+ int h;
+
+ /* unless it's just an ack, it can't be someone coming out of limbo */
+ if((segp->flags & SYN) || (segp->flags & ACK) == 0)
+ return nil;
+
+ tpriv = s->p->priv;
+
+ /* find a call in limbo */
+ h = hashipa(src, segp->source);
+ for(l = &tpriv->lht[h]; (lp = *l) != nil; l = &lp->next){
+ netlog(s->p->f, Logtcp, "tcpincoming s %I!%ud/%I!%ud d %I!%ud/%I!%ud v %d/%d\n",
+ src, segp->source, lp->raddr, lp->rport,
+ dst, segp->dest, lp->laddr, lp->lport,
+ version, lp->version
+ );
+
+ if(lp->lport != segp->dest || lp->rport != segp->source || lp->version != version)
+ continue;
+ if(ipcmp(lp->laddr, dst) != 0)
+ continue;
+ if(ipcmp(lp->raddr, src) != 0)
+ continue;
+
+ /* we're assuming no data with the initial SYN */
+ if(segp->seq != lp->irs+1 || segp->ack != lp->iss+1){
+ netlog(s->p->f, Logtcp, "tcpincoming s %lux/%lux a %lux %lux\n",
+ segp->seq, lp->irs+1, segp->ack, lp->iss+1);
+ lp = nil;
+ } else {
+ tpriv->nlimbo--;
+ *l = lp->next;
+ }
+ break;
+ }
+ if(lp == nil)
+ return nil;
+
+ new = Fsnewcall(s, src, segp->source, dst, segp->dest, version);
+ if(new == nil)
+ return nil;
+
+ memmove(new->ptcl, s->ptcl, sizeof(Tcpctl));
+ tcb = (Tcpctl*)new->ptcl;
+ tcb->flags &= ~CLONE;
+ tcb->timer.arg = new;
+ tcb->timer.state = TcptimerOFF;
+ tcb->acktimer.arg = new;
+ tcb->acktimer.state = TcptimerOFF;
+ tcb->katimer.arg = new;
+ tcb->katimer.state = TcptimerOFF;
+ tcb->rtt_timer.arg = new;
+ tcb->rtt_timer.state = TcptimerOFF;
+
+ tcb->irs = lp->irs;
+ tcb->rcv.nxt = tcb->irs+1;
+ tcb->rcv.urg = tcb->rcv.nxt;
+
+ tcb->iss = lp->iss;
+ tcb->rttseq = tcb->iss;
+ tcb->snd.wl2 = tcb->iss;
+ tcb->snd.una = tcb->iss+1;
+ tcb->snd.ptr = tcb->iss+1;
+ tcb->snd.nxt = tcb->iss+1;
+ tcb->flgcnt = 0;
+ tcb->flags |= SYNACK;
+
+ /* our sending max segment size cannot be bigger than what he asked for */
+ if(lp->mss != 0 && lp->mss < tcb->mss) {
+ tcb->mss = lp->mss;
+ tpriv->stats[Mss] = tcb->mss;
+ }
+
+ /* window scaling */
+ tcpsetscale(new, tcb, lp->rcvscale, lp->sndscale);
+
+ /* the congestion window always starts out as a single segment */
+ tcb->snd.wnd = segp->wnd;
+ tcb->cwind = tcb->mss;
+
+ /* set initial round trip time */
+ tcb->sndsyntime = lp->lastsend+lp->rexmits*SYNACK_RXTIMER;
+ tcpsynackrtt(new);
+
+ free(lp);
+
+ /* set up proto header */
+ switch(version){
+ case V4:
+ h4 = &tcb->protohdr.tcp4hdr;
+ memset(h4, 0, sizeof(*h4));
+ h4->proto = IP_TCPPROTO;
+ hnputs(h4->tcpsport, new->lport);
+ hnputs(h4->tcpdport, new->rport);
+ v6tov4(h4->tcpsrc, dst);
+ v6tov4(h4->tcpdst, src);
+ break;
+ case V6:
+ h6 = &tcb->protohdr.tcp6hdr;
+ memset(h6, 0, sizeof(*h6));
+ h6->proto = IP_TCPPROTO;
+ hnputs(h6->tcpsport, new->lport);
+ hnputs(h6->tcpdport, new->rport);
+ ipmove(h6->tcpsrc, dst);
+ ipmove(h6->tcpdst, src);
+ break;
+ default:
+ panic("tcpincoming: version %d", new->ipversion);
+ }
+
+ tcpsetstate(new, Established);
+
+ iphtadd(&tpriv->ht, new);
+
+ return new;
+}
+
+int
+seq_within(ulong x, ulong low, ulong high)
+{
+ if(low <= high){
+ if(low <= x && x <= high)
+ return 1;
+ }
+ else {
+ if(x >= low || x <= high)
+ return 1;
+ }
+ return 0;
+}
+
+int
+seq_lt(ulong x, ulong y)
+{
+ return (int)(x-y) < 0;
+}
+
+int
+seq_le(ulong x, ulong y)
+{
+ return (int)(x-y) <= 0;
+}
+
+int
+seq_gt(ulong x, ulong y)
+{
+ return (int)(x-y) > 0;
+}
+
+int
+seq_ge(ulong x, ulong y)
+{
+ return (int)(x-y) >= 0;
+}
+
+/*
+ * use the time between the first SYN and it's ack as the
+ * initial round trip time
+ */
+void
+tcpsynackrtt(Conv *s)
+{
+ Tcpctl *tcb;
+ int delta;
+ Tcppriv *tpriv;
+
+ tcb = (Tcpctl*)s->ptcl;
+ tpriv = s->p->priv;
+
+ delta = NOW - tcb->sndsyntime;
+ tcb->srtt = delta<<LOGAGAIN;
+ tcb->mdev = delta<<LOGDGAIN;
+
+ /* halt round trip timer */
+ tcphalt(tpriv, &tcb->rtt_timer);
+}
+
+void
+update(Conv *s, Tcp *seg)
+{
+ int rtt, delta;
+ Tcpctl *tcb;
+ ulong acked;
+ ulong expand;
+ Tcppriv *tpriv;
+
+ tpriv = s->p->priv;
+ tcb = (Tcpctl*)s->ptcl;
+
+ /* if everything has been acked, force output(?) */
+ if(seq_gt(seg->ack, tcb->snd.nxt)) {
+ tcb->flags |= FORCE;
+ return;
+ }
+
+ /* added by Dong Lin for fast retransmission */
+ if(seg->ack == tcb->snd.una
+ && tcb->snd.una != tcb->snd.nxt
+ && seg->len == 0
+ && seg->wnd == tcb->snd.wnd) {
+
+ /* this is a pure ack w/o window update */
+ netlog(s->p->f, Logtcprxmt, "dupack %lud ack %lud sndwnd %lud advwin %lud\n",
+ tcb->snd.dupacks, seg->ack, tcb->snd.wnd, seg->wnd);
+
+ if(++tcb->snd.dupacks == TCPREXMTTHRESH) {
+ /*
+ * tahoe tcp rxt the packet, half sshthresh,
+ * and set cwnd to one packet
+ */
+ tcb->snd.recovery = 1;
+ tcb->snd.rxt = tcb->snd.nxt;
+ netlog(s->p->f, Logtcprxmt, "fast rxt %lud, nxt %lud\n", tcb->snd.una, tcb->snd.nxt);
+ tcprxmit(s);
+ } else {
+ /* do reno tcp here. */
+ }
+ }
+
+ /*
+ * update window
+ */
+ if(seq_gt(seg->ack, tcb->snd.wl2)
+ || (tcb->snd.wl2 == seg->ack && seg->wnd > tcb->snd.wnd)){
+ tcb->snd.wnd = seg->wnd;
+ tcb->snd.wl2 = seg->ack;
+ }
+
+ if(!seq_gt(seg->ack, tcb->snd.una)){
+ /*
+ * don't let us hangup if sending into a closed window and
+ * we're still getting acks
+ */
+ if((tcb->flags&RETRAN) && tcb->snd.wnd == 0){
+ tcb->backedoff = MAXBACKMS/4;
+ }
+ return;
+ }
+
+ /*
+ * any positive ack turns off fast rxt,
+ * (should we do new-reno on partial acks?)
+ */
+ if(!tcb->snd.recovery || seq_ge(seg->ack, tcb->snd.rxt)) {
+ tcb->snd.dupacks = 0;
+ tcb->snd.recovery = 0;
+ } else
+ netlog(s->p->f, Logtcp, "rxt next %lud, cwin %lud\n", seg->ack, tcb->cwind);
+
+ /* Compute the new send window size */
+ acked = seg->ack - tcb->snd.una;
+
+ /* avoid slow start and timers for SYN acks */
+ if((tcb->flags & SYNACK) == 0) {
+ tcb->flags |= SYNACK;
+ acked--;
+ tcb->flgcnt--;
+ goto done;
+ }
+
+ /* slow start as long as we're not recovering from lost packets */
+ if(tcb->cwind < tcb->snd.wnd && !tcb->snd.recovery) {
+ if(tcb->cwind < tcb->ssthresh) {
+ expand = tcb->mss;
+ if(acked < expand)
+ expand = acked;
+ }
+ else
+ expand = ((int)tcb->mss * tcb->mss) / tcb->cwind;
+
+ if(tcb->cwind + expand < tcb->cwind)
+ expand = tcb->snd.wnd - tcb->cwind;
+ if(tcb->cwind + expand > tcb->snd.wnd)
+ expand = tcb->snd.wnd - tcb->cwind;
+ tcb->cwind += expand;
+ }
+
+ /* Adjust the timers according to the round trip time */
+ if(tcb->rtt_timer.state == TcptimerON && seq_ge(seg->ack, tcb->rttseq)) {
+ tcphalt(tpriv, &tcb->rtt_timer);
+ if((tcb->flags&RETRAN) == 0) {
+ tcb->backoff = 0;
+ tcb->backedoff = 0;
+ rtt = tcb->rtt_timer.start - tcb->rtt_timer.count;
+ if(rtt == 0)
+ rtt = 1; /* otherwise all close systems will rexmit in 0 time */
+ rtt *= MSPTICK;
+ if(tcb->srtt == 0) {
+ tcb->srtt = rtt << LOGAGAIN;
+ tcb->mdev = rtt << LOGDGAIN;
+ } else {
+ delta = rtt - (tcb->srtt>>LOGAGAIN);
+ tcb->srtt += delta;
+ if(tcb->srtt <= 0)
+ tcb->srtt = 1;
+
+ delta = abs(delta) - (tcb->mdev>>LOGDGAIN);
+ tcb->mdev += delta;
+ if(tcb->mdev <= 0)
+ tcb->mdev = 1;
+ }
+ tcpsettimer(tcb);
+ }
+ }
+
+done:
+ if(qdiscard(s->wq, acked) < acked)
+ tcb->flgcnt--;
+
+ tcb->snd.una = seg->ack;
+ if(seq_gt(seg->ack, tcb->snd.urg))
+ tcb->snd.urg = seg->ack;
+
+ if(tcb->snd.una != tcb->snd.nxt)
+ tcpgo(tpriv, &tcb->timer);
+ else
+ tcphalt(tpriv, &tcb->timer);
+
+ if(seq_lt(tcb->snd.ptr, tcb->snd.una))
+ tcb->snd.ptr = tcb->snd.una;
+
+ tcb->flags &= ~RETRAN;
+ tcb->backoff = 0;
+ tcb->backedoff = 0;
+}
+
+void
+tcpiput(Proto *tcp, Ipifc*, Block *bp)
+{
+ Tcp seg;
+ Tcp4hdr *h4;
+ Tcp6hdr *h6;
+ int hdrlen;
+ Tcpctl *tcb;
+ ushort length, csum;
+ uchar source[IPaddrlen], dest[IPaddrlen];
+ Conv *s;
+ Fs *f;
+ Tcppriv *tpriv;
+ uchar version;
+
+ f = tcp->f;
+ tpriv = tcp->priv;
+
+ tpriv->stats[InSegs]++;
+
+ h4 = (Tcp4hdr*)(bp->rp);
+ h6 = (Tcp6hdr*)(bp->rp);
+
+ if((h4->vihl&0xF0)==IP_VER4) {
+ version = V4;
+ length = nhgets(h4->length);
+ v4tov6(dest, h4->tcpdst);
+ v4tov6(source, h4->tcpsrc);
+
+ h4->Unused = 0;
+ hnputs(h4->tcplen, length-TCP4_PKT);
+ if(!(bp->flag & Btcpck) && (h4->tcpcksum[0] || h4->tcpcksum[1]) &&
+ ptclcsum(bp, TCP4_IPLEN, length-TCP4_IPLEN)) {
+ tpriv->stats[CsumErrs]++;
+ tpriv->stats[InErrs]++;
+ netlog(f, Logtcp, "bad tcp proto cksum\n");
+ freeblist(bp);
+ return;
+ }
+
+ hdrlen = ntohtcp4(&seg, &bp);
+ if(hdrlen < 0){
+ tpriv->stats[HlenErrs]++;
+ tpriv->stats[InErrs]++;
+ netlog(f, Logtcp, "bad tcp hdr len\n");
+ return;
+ }
+
+ /* trim the packet to the size claimed by the datagram */
+ length -= hdrlen+TCP4_PKT;
+ bp = trimblock(bp, hdrlen+TCP4_PKT, length);
+ if(bp == nil){
+ tpriv->stats[LenErrs]++;
+ tpriv->stats[InErrs]++;
+ netlog(f, Logtcp, "tcp len < 0 after trim\n");
+ return;
+ }
+ }
+ else {
+ int ttl = h6->ttl;
+ int proto = h6->proto;
+
+ version = V6;
+ length = nhgets(h6->ploadlen);
+ ipmove(dest, h6->tcpdst);
+ ipmove(source, h6->tcpsrc);
+
+ h6->ploadlen[0] = h6->ploadlen[1] = h6->proto = 0;
+ h6->ttl = proto;
+ hnputl(h6->vcf, length);
+ if((h6->tcpcksum[0] || h6->tcpcksum[1]) &&
+ (csum = ptclcsum(bp, TCP6_IPLEN, length+TCP6_PHDRSIZE)) != 0) {
+ tpriv->stats[CsumErrs]++;
+ tpriv->stats[InErrs]++;
+ netlog(f, Logtcp,
+ "bad tcpv6 proto cksum: got %#ux, computed %#ux\n",
+ h6->tcpcksum[0]<<8 | h6->tcpcksum[1], csum);
+ freeblist(bp);
+ return;
+ }
+ h6->ttl = ttl;
+ h6->proto = proto;
+ hnputs(h6->ploadlen, length);
+
+ hdrlen = ntohtcp6(&seg, &bp);
+ if(hdrlen < 0){
+ tpriv->stats[HlenErrs]++;
+ tpriv->stats[InErrs]++;
+ netlog(f, Logtcp, "bad tcpv6 hdr len\n");
+ return;
+ }
+
+ /* trim the packet to the size claimed by the datagram */
+ length -= hdrlen;
+ bp = trimblock(bp, hdrlen+TCP6_PKT, length);
+ if(bp == nil){
+ tpriv->stats[LenErrs]++;
+ tpriv->stats[InErrs]++;
+ netlog(f, Logtcp, "tcpv6 len < 0 after trim\n");
+ return;
+ }
+ }
+
+ /* lock protocol while searching for a conversation */
+ qlock(tcp);
+
+ /* Look for a matching conversation */
+ s = iphtlook(&tpriv->ht, source, seg.source, dest, seg.dest);
+ if(s == nil){
+ netlog(f, Logtcp, "iphtlook(src %I!%d, dst %I!%d) failed\n",
+ source, seg.source, dest, seg.dest);
+reset:
+ qunlock(tcp);
+ sndrst(tcp, source, dest, length, &seg, version, "no conversation");
+ freeblist(bp);
+ return;
+ }
+
+ /* if it's a listener, look for the right flags and get a new conv */
+ tcb = (Tcpctl*)s->ptcl;
+ if(tcb->state == Listen){
+ if(seg.flags & RST){
+ limborst(s, &seg, source, dest, version);
+ qunlock(tcp);
+ freeblist(bp);
+ return;
+ }
+
+ /* if this is a new SYN, put the call into limbo */
+ if((seg.flags & SYN) && (seg.flags & ACK) == 0){
+ limbo(s, source, dest, &seg, version);
+ qunlock(tcp);
+ freeblist(bp);
+ return;
+ }
+
+ /*
+ * if there's a matching call in limbo, tcpincoming will
+ * return it in state Syn_received
+ */
+ s = tcpincoming(s, &seg, source, dest, version);
+ if(s == nil)
+ goto reset;
+ }
+
+ /* The rest of the input state machine is run with the control block
+ * locked and implements the state machine directly out of the RFC.
+ * Out-of-band data is ignored - it was always a bad idea.
+ */
+ tcb = (Tcpctl*)s->ptcl;
+ if(waserror()){
+ qunlock(s);
+ nexterror();
+ }
+ qlock(s);
+ qunlock(tcp);
+
+ /* fix up window */
+ seg.wnd <<= tcb->rcv.scale;
+
+ /* every input packet in puts off the keep alive time out */
+ tcpsetkacounter(tcb);
+
+ switch(tcb->state) {
+ case Closed:
+ sndrst(tcp, source, dest, length, &seg, version, "sending to Closed");
+ goto raise;
+ case Syn_sent:
+ if(seg.flags & ACK) {
+ if(!seq_within(seg.ack, tcb->iss+1, tcb->snd.nxt)) {
+ sndrst(tcp, source, dest, length, &seg, version,
+ "bad seq in Syn_sent");
+ goto raise;
+ }
+ }
+ if(seg.flags & RST) {
+ if(seg.flags & ACK)
+ localclose(s, Econrefused);
+ goto raise;
+ }
+
+ if(seg.flags & SYN) {
+ procsyn(s, &seg);
+ if(seg.flags & ACK){
+ update(s, &seg);
+ tcpsynackrtt(s);
+ tcpsetstate(s, Established);
+ tcpsetscale(s, tcb, seg.ws, tcb->scale);
+ }
+ else {
+ tcb->time = NOW;
+ tcpsetstate(s, Syn_received); /* DLP - shouldn't this be a reset? */
+ }
+
+ if(length != 0 || (seg.flags & FIN))
+ break;
+
+ freeblist(bp);
+ goto output;
+ }
+ else
+ freeblist(bp);
+
+ qunlock(s);
+ poperror();
+ return;
+ case Syn_received:
+ /* doesn't matter if it's the correct ack, we're just trying to set timing */
+ if(seg.flags & ACK)
+ tcpsynackrtt(s);
+ break;
+ }
+
+ /*
+ * One DOS attack is to open connections to us and then forget about them,
+ * thereby tying up a conv at no long term cost to the attacker.
+ * This is an attempt to defeat these stateless DOS attacks. See
+ * corresponding code in tcpsendka().
+ */
+ if(tcb->state != Syn_received && (seg.flags & RST) == 0){
+ if(tcpporthogdefense
+ && seq_within(seg.ack, tcb->snd.una-(1<<31), tcb->snd.una-(1<<29))){
+ print("stateless hog %I.%d->%I.%d f %ux %lux - %lux - %lux\n",
+ source, seg.source, dest, seg.dest, seg.flags,
+ tcb->snd.una-(1<<31), seg.ack, tcb->snd.una-(1<<29));
+ localclose(s, "stateless hog");
+ }
+ }
+
+ /* Cut the data to fit the receive window */
+ if(tcptrim(tcb, &seg, &bp, &length) == -1) {
+ netlog(f, Logtcp, "tcptrim, not accept, seq %lud-%lud win %lud-%lud from %I\n",
+ seg.seq, seg.seq + length - 1,
+ tcb->rcv.nxt, tcb->rcv.nxt + tcb->rcv.wnd-1, s->raddr);
+ netlog(f, Logtcp, "tcp len < 0, %lud %d\n", seg.seq, length);
+ update(s, &seg);
+ if(qlen(s->wq)+tcb->flgcnt == 0 && tcb->state == Closing) {
+ tcphalt(tpriv, &tcb->rtt_timer);
+ tcphalt(tpriv, &tcb->acktimer);
+ tcphalt(tpriv, &tcb->katimer);
+ tcpsetstate(s, Time_wait);
+ tcb->timer.start = MSL2*(1000 / MSPTICK);
+ tcpgo(tpriv, &tcb->timer);
+ }
+ if(!(seg.flags & RST)) {
+ tcb->flags |= FORCE;
+ goto output;
+ }
+ qunlock(s);
+ poperror();
+ return;
+ }
+
+ /* Cannot accept so answer with a rst */
+ if(length && tcb->state == Closed) {
+ sndrst(tcp, source, dest, length, &seg, version, "sending to Closed");
+ goto raise;
+ }
+
+ /* The segment is beyond the current receive pointer so
+ * queue the data in the resequence queue
+ */
+ if(seg.seq != tcb->rcv.nxt)
+ if(length != 0 || (seg.flags & (SYN|FIN))) {
+ update(s, &seg);
+ if(addreseq(tcb, tpriv, &seg, bp, length) < 0)
+ print("reseq %I.%d -> %I.%d\n", s->raddr, s->rport, s->laddr, s->lport);
+ tcb->flags |= FORCE;
+ goto output;
+ }
+
+ /*
+ * keep looping till we've processed this packet plus any
+ * adjacent packets in the resequence queue
+ */
+ for(;;) {
+ if(seg.flags & RST) {
+ if(tcb->state == Established) {
+ tpriv->stats[EstabResets]++;
+ if(tcb->rcv.nxt != seg.seq)
+ print("out of order RST rcvd: %I.%d -> %I.%d, rcv.nxt %lux seq %lux\n", s->raddr, s->rport, s->laddr, s->lport, tcb->rcv.nxt, seg.seq);
+ }
+ localclose(s, Econrefused);
+ goto raise;
+ }
+
+ if((seg.flags&ACK) == 0)
+ goto raise;
+
+ switch(tcb->state) {
+ case Syn_received:
+ if(!seq_within(seg.ack, tcb->snd.una+1, tcb->snd.nxt)){
+ sndrst(tcp, source, dest, length, &seg, version,
+ "bad seq in Syn_received");
+ goto raise;
+ }
+ update(s, &seg);
+ tcpsetstate(s, Established);
+ case Established:
+ case Close_wait:
+ update(s, &seg);
+ break;
+ case Finwait1:
+ update(s, &seg);
+ if(qlen(s->wq)+tcb->flgcnt == 0){
+ tcphalt(tpriv, &tcb->rtt_timer);
+ tcphalt(tpriv, &tcb->acktimer);
+ tcpsetkacounter(tcb);
+ tcb->time = NOW;
+ tcpsetstate(s, Finwait2);
+ tcb->katimer.start = MSL2 * (1000 / MSPTICK);
+ tcpgo(tpriv, &tcb->katimer);
+ }
+ break;
+ case Finwait2:
+ update(s, &seg);
+ break;
+ case Closing:
+ update(s, &seg);
+ if(qlen(s->wq)+tcb->flgcnt == 0) {
+ tcphalt(tpriv, &tcb->rtt_timer);
+ tcphalt(tpriv, &tcb->acktimer);
+ tcphalt(tpriv, &tcb->katimer);
+ tcpsetstate(s, Time_wait);
+ tcb->timer.start = MSL2*(1000 / MSPTICK);
+ tcpgo(tpriv, &tcb->timer);
+ }
+ break;
+ case Last_ack:
+ update(s, &seg);
+ if(qlen(s->wq)+tcb->flgcnt == 0) {
+ localclose(s, nil);
+ goto raise;
+ }
+ case Time_wait:
+ tcb->flags |= FORCE;
+ if(tcb->timer.state != TcptimerON)
+ tcpgo(tpriv, &tcb->timer);
+ }
+
+ if((seg.flags&URG) && seg.urg) {
+ if(seq_gt(seg.urg + seg.seq, tcb->rcv.urg)) {
+ tcb->rcv.urg = seg.urg + seg.seq;
+ pullblock(&bp, seg.urg);
+ }
+ }
+ else
+ if(seq_gt(tcb->rcv.nxt, tcb->rcv.urg))
+ tcb->rcv.urg = tcb->rcv.nxt;
+
+ if(length == 0) {
+ if(bp != nil)
+ freeblist(bp);
+ }
+ else {
+ switch(tcb->state){
+ default:
+ /* Ignore segment text */
+ if(bp != nil)
+ freeblist(bp);
+ break;
+
+ case Syn_received:
+ case Established:
+ case Finwait1:
+ /* If we still have some data place on
+ * receive queue
+ */
+ if(bp) {
+ bp = packblock(bp);
+ if(bp == nil)
+ panic("tcp packblock");
+ qpassnolim(s->rq, bp);
+ bp = nil;
+
+ /*
+ * Force an ack every 2 data messages. This is
+ * a hack for rob to make his home system run
+ * faster.
+ *
+ * this also keeps the standard TCP congestion
+ * control working since it needs an ack every
+ * 2 max segs worth. This is not quite that,
+ * but under a real stream is equivalent since
+ * every packet has a max seg in it.
+ */
+ if(++(tcb->rcv.una) >= 2)
+ tcb->flags |= FORCE;
+ }
+ tcb->rcv.nxt += length;
+
+ /*
+ * update our rcv window
+ */
+ tcprcvwin(s);
+
+ /*
+ * turn on the acktimer if there's something
+ * to ack
+ */
+ if(tcb->acktimer.state != TcptimerON)
+ tcpgo(tpriv, &tcb->acktimer);
+
+ break;
+ case Finwait2:
+ /* no process to read the data, send a reset */
+ if(bp != nil)
+ freeblist(bp);
+ sndrst(tcp, source, dest, length, &seg, version,
+ "send to Finwait2");
+ qunlock(s);
+ poperror();
+ return;
+ }
+ }
+
+ if(seg.flags & FIN) {
+ tcb->flags |= FORCE;
+
+ switch(tcb->state) {
+ case Syn_received:
+ case Established:
+ tcb->rcv.nxt++;
+ tcpsetstate(s, Close_wait);
+ break;
+ case Finwait1:
+ tcb->rcv.nxt++;
+ if(qlen(s->wq)+tcb->flgcnt == 0) {
+ tcphalt(tpriv, &tcb->rtt_timer);
+ tcphalt(tpriv, &tcb->acktimer);
+ tcphalt(tpriv, &tcb->katimer);
+ tcpsetstate(s, Time_wait);
+ tcb->timer.start = MSL2*(1000/MSPTICK);
+ tcpgo(tpriv, &tcb->timer);
+ }
+ else
+ tcpsetstate(s, Closing);
+ break;
+ case Finwait2:
+ tcb->rcv.nxt++;
+ tcphalt(tpriv, &tcb->rtt_timer);
+ tcphalt(tpriv, &tcb->acktimer);
+ tcphalt(tpriv, &tcb->katimer);
+ tcpsetstate(s, Time_wait);
+ tcb->timer.start = MSL2 * (1000/MSPTICK);
+ tcpgo(tpriv, &tcb->timer);
+ break;
+ case Close_wait:
+ case Closing:
+ case Last_ack:
+ break;
+ case Time_wait:
+ tcpgo(tpriv, &tcb->timer);
+ break;
+ }
+ }
+
+ /*
+ * get next adjacent segment from the resequence queue.
+ * dump/trim any overlapping segments
+ */
+ for(;;) {
+ if(tcb->reseq == nil)
+ goto output;
+
+ if(seq_ge(tcb->rcv.nxt, tcb->reseq->seg.seq) == 0)
+ goto output;
+
+ getreseq(tcb, &seg, &bp, &length);
+
+ if(tcptrim(tcb, &seg, &bp, &length) == 0)
+ break;
+ }
+ }
+output:
+ tcpoutput(s);
+ qunlock(s);
+ poperror();
+ return;
+raise:
+ qunlock(s);
+ poperror();
+ freeblist(bp);
+ tcpkick(s);
+}
+
+/*
+ * always enters and exits with the s locked. We drop
+ * the lock to ipoput the packet so some care has to be
+ * taken by callers.
+ */
+void
+tcpoutput(Conv *s)
+{
+ Tcp seg;
+ int msgs;
+ Tcpctl *tcb;
+ Block *hbp, *bp;
+ int sndcnt, n;
+ ulong ssize, dsize, usable, sent;
+ Fs *f;
+ Tcppriv *tpriv;
+ uchar version;
+
+ f = s->p->f;
+ tpriv = s->p->priv;
+ version = s->ipversion;
+
+ for(msgs = 0; msgs < 100; msgs++) {
+ tcb = (Tcpctl*)s->ptcl;
+
+ switch(tcb->state) {
+ case Listen:
+ case Closed:
+ case Finwait2:
+ return;
+ }
+
+ /* force an ack when a window has opened up */
+ if(tcb->rcv.blocked && tcb->rcv.wnd > 0){
+ tcb->rcv.blocked = 0;
+ tcb->flags |= FORCE;
+ }
+
+ sndcnt = qlen(s->wq)+tcb->flgcnt;
+ sent = tcb->snd.ptr - tcb->snd.una;
+
+ /* Don't send anything else until our SYN has been acked */
+ if(tcb->snd.ptr != tcb->iss && (tcb->flags & SYNACK) == 0)
+ break;
+
+ /* Compute usable segment based on offered window and limit
+ * window probes to one
+ */
+ if(tcb->snd.wnd == 0){
+ if(sent != 0) {
+ if((tcb->flags&FORCE) == 0)
+ break;
+// tcb->snd.ptr = tcb->snd.una;
+ }
+ usable = 1;
+ }
+ else {
+ usable = tcb->cwind;
+ if(tcb->snd.wnd < usable)
+ usable = tcb->snd.wnd;
+// usable -= sent;
+ usable = usable >= sent? usable - sent: 0;
+ }
+ ssize = sndcnt-sent;
+ if(ssize && usable < 2)
+ netlog(s->p->f, Logtcp, "throttled snd.wnd %lud cwind %lud\n",
+ tcb->snd.wnd, tcb->cwind);
+ if(usable < ssize)
+ ssize = usable;
+ if(tcb->mss < ssize)
+ ssize = tcb->mss;
+ dsize = ssize;
+ seg.urg = 0;
+
+ if(ssize == 0)
+ if((tcb->flags&FORCE) == 0)
+ break;
+
+ tcb->flags &= ~FORCE;
+ tcprcvwin(s);
+
+ /* By default we will generate an ack */
+ tcphalt(tpriv, &tcb->acktimer);
+ tcb->rcv.una = 0;
+ seg.source = s->lport;
+ seg.dest = s->rport;
+ seg.flags = ACK;
+ seg.mss = 0;
+ seg.ws = 0;
+ switch(tcb->state){
+ case Syn_sent:
+ seg.flags = 0;
+ if(tcb->snd.ptr == tcb->iss){
+ seg.flags |= SYN;
+ dsize--;
+ seg.mss = tcb->mss;
+ seg.ws = tcb->scale;
+ }
+ break;
+ case Syn_received:
+ /*
+ * don't send any data with a SYN/ACK packet
+ * because Linux rejects the packet in its
+ * attempt to solve the SYN attack problem
+ */
+ if(tcb->snd.ptr == tcb->iss){
+ seg.flags |= SYN;
+ dsize = 0;
+ ssize = 1;
+ seg.mss = tcb->mss;
+ seg.ws = tcb->scale;
+ }
+ break;
+ }
+ seg.seq = tcb->snd.ptr;
+ seg.ack = tcb->rcv.nxt;
+ seg.wnd = tcb->rcv.wnd;
+
+ /* Pull out data to send */
+ bp = nil;
+ if(dsize != 0) {
+ bp = qcopy(s->wq, dsize, sent);
+ if(BLEN(bp) != dsize) {
+ seg.flags |= FIN;
+ dsize--;
+ }
+ }
+
+ if(sent+dsize == sndcnt)
+ seg.flags |= PSH;
+
+ /* keep track of balance of resent data */
+ if(seq_lt(tcb->snd.ptr, tcb->snd.nxt)) {
+ n = tcb->snd.nxt - tcb->snd.ptr;
+ if(ssize < n)
+ n = ssize;
+ tcb->resent += n;
+ netlog(f, Logtcp, "rexmit: %I!%d -> %I!%d ptr %lux nxt %lux\n",
+ s->raddr, s->rport, s->laddr, s->lport, tcb->snd.ptr, tcb->snd.nxt);
+ tpriv->stats[RetransSegs]++;
+ }
+
+ tcb->snd.ptr += ssize;
+
+ /* Pull up the send pointer so we can accept acks
+ * for this window
+ */
+ if(seq_gt(tcb->snd.ptr,tcb->snd.nxt))
+ tcb->snd.nxt = tcb->snd.ptr;
+
+ /* Build header, link data and compute cksum */
+ switch(version){
+ case V4:
+ tcb->protohdr.tcp4hdr.vihl = IP_VER4;
+ hbp = htontcp4(&seg, bp, &tcb->protohdr.tcp4hdr, tcb);
+ if(hbp == nil) {
+ freeblist(bp);
+ return;
+ }
+ break;
+ case V6:
+ tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
+ hbp = htontcp6(&seg, bp, &tcb->protohdr.tcp6hdr, tcb);
+ if(hbp == nil) {
+ freeblist(bp);
+ return;
+ }
+ break;
+ default:
+ hbp = nil; /* to suppress a warning */
+ panic("tcpoutput: version %d", version);
+ }
+
+ /* Start the transmission timers if there is new data and we
+ * expect acknowledges
+ */
+ if(ssize != 0){
+ if(tcb->timer.state != TcptimerON)
+ tcpgo(tpriv, &tcb->timer);
+
+ /* If round trip timer isn't running, start it.
+ * measure the longest packet only in case the
+ * transmission time dominates RTT
+ */
+ if(tcb->rtt_timer.state != TcptimerON)
+ if(ssize == tcb->mss) {
+ tcpgo(tpriv, &tcb->rtt_timer);
+ tcb->rttseq = tcb->snd.ptr;
+ }
+ }
+
+ tpriv->stats[OutSegs]++;
+
+ /* put off the next keep alive */
+ tcpgo(tpriv, &tcb->katimer);
+
+ switch(version){
+ case V4:
+ if(ipoput4(f, hbp, 0, s->ttl, s->tos, s) < 0){
+ /* a negative return means no route */
+ localclose(s, "no route");
+ }
+ break;
+ case V6:
+ if(ipoput6(f, hbp, 0, s->ttl, s->tos, s) < 0){
+ /* a negative return means no route */
+ localclose(s, "no route");
+ }
+ break;
+ default:
+ panic("tcpoutput2: version %d", version);
+ }
+ if((msgs%4) == 1){
+ qunlock(s);
+ sched();
+ qlock(s);
+ }
+ }
+}
+
+/*
+ * the BSD convention (hack?) for keep alives. resend last uchar acked.
+ */
+void
+tcpsendka(Conv *s)
+{
+ Tcp seg;
+ Tcpctl *tcb;
+ Block *hbp,*dbp;
+
+ tcb = (Tcpctl*)s->ptcl;
+
+ dbp = nil;
+ seg.urg = 0;
+ seg.source = s->lport;
+ seg.dest = s->rport;
+ seg.flags = ACK|PSH;
+ seg.mss = 0;
+ seg.ws = 0;
+ if(tcpporthogdefense)
+ seg.seq = tcb->snd.una-(1<<30)-nrand(1<<20);
+ else
+ seg.seq = tcb->snd.una-1;
+ seg.ack = tcb->rcv.nxt;
+ tcb->rcv.una = 0;
+ seg.wnd = tcb->rcv.wnd;
+ if(tcb->state == Finwait2){
+ seg.flags |= FIN;
+ } else {
+ dbp = allocb(1);
+ dbp->wp++;
+ }
+
+ if(isv4(s->raddr)) {
+ /* Build header, link data and compute cksum */
+ tcb->protohdr.tcp4hdr.vihl = IP_VER4;
+ hbp = htontcp4(&seg, dbp, &tcb->protohdr.tcp4hdr, tcb);
+ if(hbp == nil) {
+ freeblist(dbp);
+ return;
+ }
+ ipoput4(s->p->f, hbp, 0, s->ttl, s->tos, s);
+ }
+ else {
+ /* Build header, link data and compute cksum */
+ tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
+ hbp = htontcp6(&seg, dbp, &tcb->protohdr.tcp6hdr, tcb);
+ if(hbp == nil) {
+ freeblist(dbp);
+ return;
+ }
+ ipoput6(s->p->f, hbp, 0, s->ttl, s->tos, s);
+ }
+}
+
+/*
+ * set connection to time out after 12 minutes
+ */
+void
+tcpsetkacounter(Tcpctl *tcb)
+{
+ tcb->kacounter = (12 * 60 * 1000) / (tcb->katimer.start*MSPTICK);
+ if(tcb->kacounter < 3)
+ tcb->kacounter = 3;
+}
+
+/*
+ * if we've timed out, close the connection
+ * otherwise, send a keepalive and restart the timer
+ */
+void
+tcpkeepalive(void *v)
+{
+ Tcpctl *tcb;
+ Conv *s;
+
+ s = v;
+ tcb = (Tcpctl*)s->ptcl;
+ if(waserror()){
+ qunlock(s);
+ nexterror();
+ }
+ qlock(s);
+ if(tcb->state != Closed){
+ if(--(tcb->kacounter) <= 0) {
+ localclose(s, Etimedout);
+ } else {
+ tcpsendka(s);
+ tcpgo(s->p->priv, &tcb->katimer);
+ }
+ }
+ qunlock(s);
+ poperror();
+}
+
+/*
+ * start keepalive timer
+ */
+char*
+tcpstartka(Conv *s, char **f, int n)
+{
+ Tcpctl *tcb;
+ int x;
+
+ tcb = (Tcpctl*)s->ptcl;
+ if(tcb->state != Established)
+ return "connection must be in Establised state";
+ if(n > 1){
+ x = atoi(f[1]);
+ if(x >= MSPTICK)
+ tcb->katimer.start = x/MSPTICK;
+ }
+ tcpsetkacounter(tcb);
+ tcpgo(s->p->priv, &tcb->katimer);
+
+ return nil;
+}
+
+/*
+ * turn checksums on/off
+ */
+char*
+tcpsetchecksum(Conv *s, char **f, int)
+{
+ Tcpctl *tcb;
+
+ tcb = (Tcpctl*)s->ptcl;
+ tcb->nochecksum = !atoi(f[1]);
+
+ return nil;
+}
+
+void
+tcprxmit(Conv *s)
+{
+ Tcpctl *tcb;
+
+ tcb = (Tcpctl*)s->ptcl;
+
+ tcb->flags |= RETRAN|FORCE;
+ tcb->snd.ptr = tcb->snd.una;
+
+ /*
+ * We should be halving the slow start threshhold (down to one
+ * mss) but leaving it at mss seems to work well enough
+ */
+ tcb->ssthresh = tcb->mss;
+
+ /*
+ * pull window down to a single packet
+ */
+ tcb->cwind = tcb->mss;
+ tcpoutput(s);
+}
+
+void
+tcptimeout(void *arg)
+{
+ Conv *s;
+ Tcpctl *tcb;
+ int maxback;
+ Tcppriv *tpriv;
+
+ s = (Conv*)arg;
+ tpriv = s->p->priv;
+ tcb = (Tcpctl*)s->ptcl;
+
+ if(waserror()){
+ qunlock(s);
+ nexterror();
+ }
+ qlock(s);
+ switch(tcb->state){
+ default:
+ tcb->backoff++;
+ if(tcb->state == Syn_sent)
+ maxback = MAXBACKMS/2;
+ else
+ maxback = MAXBACKMS;
+ tcb->backedoff += tcb->timer.start * MSPTICK;
+ if(tcb->backedoff >= maxback) {
+ localclose(s, Etimedout);
+ break;
+ }
+ netlog(s->p->f, Logtcprxmt, "timeout rexmit %#lux %d/%lud\n", tcb->snd.una, tcb->timer.start, NOW);
+ tcpsettimer(tcb);
+ tcprxmit(s);
+ tpriv->stats[RetransTimeouts]++;
+ tcb->snd.dupacks = 0;
+ break;
+ case Time_wait:
+ localclose(s, nil);
+ break;
+ case Closed:
+ break;
+ }
+ qunlock(s);
+ poperror();
+}
+
+int
+inwindow(Tcpctl *tcb, int seq)
+{
+ return seq_within(seq, tcb->rcv.nxt, tcb->rcv.nxt+tcb->rcv.wnd-1);
+}
+
+/*
+ * set up state for a received SYN (or SYN ACK) packet
+ */
+void
+procsyn(Conv *s, Tcp *seg)
+{
+ Tcpctl *tcb;
+ Tcppriv *tpriv;
+
+ tcb = (Tcpctl*)s->ptcl;
+ tcb->flags |= FORCE;
+
+ tcb->rcv.nxt = seg->seq + 1;
+ tcb->rcv.urg = tcb->rcv.nxt;
+ tcb->irs = seg->seq;
+
+ /* our sending max segment size cannot be bigger than what he asked for */
+ if(seg->mss != 0 && seg->mss < tcb->mss) {
+ tcb->mss = seg->mss;
+ tpriv = s->p->priv;
+ tpriv->stats[Mss] = tcb->mss;
+ }
+
+ /* the congestion window always starts out as a single segment */
+ tcb->snd.wnd = seg->wnd;
+ tcb->cwind = tcb->mss;
+}
+
+int
+addreseq(Tcpctl *tcb, Tcppriv *tpriv, Tcp *seg, Block *bp, ushort length)
+{
+ Reseq *rp, *rp1;
+ int i, rqlen, qmax;
+
+ rp = malloc(sizeof(Reseq));
+ if(rp == nil){
+ freeblist(bp); /* bp always consumed by add_reseq */
+ return 0;
+ }
+
+ rp->seg = *seg;
+ rp->bp = bp;
+ rp->length = length;
+
+ /* Place on reassembly list sorting by starting seq number */
+ rp1 = tcb->reseq;
+ if(rp1 == nil || seq_lt(seg->seq, rp1->seg.seq)) {
+ rp->next = rp1;
+ tcb->reseq = rp;
+ if(rp->next != nil)
+ tpriv->stats[OutOfOrder]++;
+ return 0;
+ }
+
+ rqlen = 0;
+ for(i = 0;; i++) {
+ rqlen += rp1->length;
+ if(rp1->next == nil || seq_lt(seg->seq, rp1->next->seg.seq)) {
+ rp->next = rp1->next;
+ rp1->next = rp;
+ if(rp->next != nil)
+ tpriv->stats[OutOfOrder]++;
+ break;
+ }
+ rp1 = rp1->next;
+ }
+ qmax = QMAX<<tcb->rcv.scale;
+ if(rqlen > qmax){
+ print("resequence queue > window: %d > %d\n", rqlen, qmax);
+ i = 0;
+ for(rp1 = tcb->reseq; rp1 != nil; rp1 = rp1->next){
+ print("%#lux %#lux %#ux\n", rp1->seg.seq,
+ rp1->seg.ack, rp1->seg.flags);
+ if(i++ > 10){
+ print("...\n");
+ break;
+ }
+ }
+
+ /*
+ * delete entire reassembly queue; wait for retransmit.
+ * - should we be smarter and only delete the tail?
+ */
+ for(rp = tcb->reseq; rp != nil; rp = rp1){
+ rp1 = rp->next;
+ freeblist(rp->bp);
+ free(rp);
+ }
+ tcb->reseq = nil;
+
+ return -1;
+ }
+ return 0;
+}
+
+void
+getreseq(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length)
+{
+ Reseq *rp;
+
+ rp = tcb->reseq;
+ if(rp == nil)
+ return;
+
+ tcb->reseq = rp->next;
+
+ *seg = rp->seg;
+ *bp = rp->bp;
+ *length = rp->length;
+
+ free(rp);
+}
+
+int
+tcptrim(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length)
+{
+ ushort len;
+ uchar accept;
+ int dupcnt, excess;
+
+ accept = 0;
+ len = *length;
+ if(seg->flags & SYN)
+ len++;
+ if(seg->flags & FIN)
+ len++;
+
+ if(tcb->rcv.wnd == 0) {
+ if(len == 0 && seg->seq == tcb->rcv.nxt)
+ return 0;
+ }
+ else {
+ /* Some part of the segment should be in the window */
+ if(inwindow(tcb,seg->seq))
+ accept++;
+ else
+ if(len != 0) {
+ if(inwindow(tcb, seg->seq+len-1) ||
+ seq_within(tcb->rcv.nxt, seg->seq,seg->seq+len-1))
+ accept++;
+ }
+ }
+ if(!accept) {
+ freeblist(*bp);
+ return -1;
+ }
+ dupcnt = tcb->rcv.nxt - seg->seq;
+ if(dupcnt > 0){
+ tcb->rerecv += dupcnt;
+ if(seg->flags & SYN){
+ seg->flags &= ~SYN;
+ seg->seq++;
+
+ if(seg->urg > 1)
+ seg->urg--;
+ else
+ seg->flags &= ~URG;
+ dupcnt--;
+ }
+ if(dupcnt > 0){
+ pullblock(bp, (ushort)dupcnt);
+ seg->seq += dupcnt;
+ *length -= dupcnt;
+
+ if(seg->urg > dupcnt)
+ seg->urg -= dupcnt;
+ else {
+ seg->flags &= ~URG;
+ seg->urg = 0;
+ }
+ }
+ }
+ excess = seg->seq + *length - (tcb->rcv.nxt + tcb->rcv.wnd);
+ if(excess > 0) {
+ tcb->rerecv += excess;
+ *length -= excess;
+ *bp = trimblock(*bp, 0, *length);
+ if(*bp == nil)
+ panic("presotto is a boofhead");
+ seg->flags &= ~FIN;
+ }
+ return 0;
+}
+
+void
+tcpadvise(Proto *tcp, Block *bp, char *msg)
+{
+ Tcp4hdr *h4;
+ Tcp6hdr *h6;
+ Tcpctl *tcb;
+ uchar source[IPaddrlen];
+ uchar dest[IPaddrlen];
+ ushort psource, pdest;
+ Conv *s, **p;
+
+ h4 = (Tcp4hdr*)(bp->rp);
+ h6 = (Tcp6hdr*)(bp->rp);
+
+ if((h4->vihl&0xF0)==IP_VER4) {
+ v4tov6(dest, h4->tcpdst);
+ v4tov6(source, h4->tcpsrc);
+ psource = nhgets(h4->tcpsport);
+ pdest = nhgets(h4->tcpdport);
+ }
+ else {
+ ipmove(dest, h6->tcpdst);
+ ipmove(source, h6->tcpsrc);
+ psource = nhgets(h6->tcpsport);
+ pdest = nhgets(h6->tcpdport);
+ }
+
+ /* Look for a connection */
+ qlock(tcp);
+ for(p = tcp->conv; *p; p++) {
+ s = *p;
+ tcb = (Tcpctl*)s->ptcl;
+ if(s->rport == pdest)
+ if(s->lport == psource)
+ if(tcb->state != Closed)
+ if(ipcmp(s->raddr, dest) == 0)
+ if(ipcmp(s->laddr, source) == 0){
+ qlock(s);
+ qunlock(tcp);
+ switch(tcb->state){
+ case Syn_sent:
+ localclose(s, msg);
+ break;
+ }
+ qunlock(s);
+ freeblist(bp);
+ return;
+ }
+ }
+ qunlock(tcp);
+ freeblist(bp);
+}
+
+static char*
+tcpporthogdefensectl(char *val)
+{
+ if(strcmp(val, "on") == 0)
+ tcpporthogdefense = 1;
+ else if(strcmp(val, "off") == 0)
+ tcpporthogdefense = 0;
+ else
+ return "unknown value for tcpporthogdefense";
+ return nil;
+}
+
+/* called with c qlocked */
+char*
+tcpctl(Conv* c, char** f, int n)
+{
+ if(n == 1 && strcmp(f[0], "hangup") == 0)
+ return tcphangup(c);
+ if(n >= 1 && strcmp(f[0], "keepalive") == 0)
+ return tcpstartka(c, f, n);
+ if(n >= 1 && strcmp(f[0], "checksum") == 0)
+ return tcpsetchecksum(c, f, n);
+ if(n >= 1 && strcmp(f[0], "tcpporthogdefense") == 0)
+ return tcpporthogdefensectl(f[1]);
+ return "unknown control request";
+}
+
+int
+tcpstats(Proto *tcp, char *buf, int len)
+{
+ Tcppriv *priv;
+ char *p, *e;
+ int i;
+
+ priv = tcp->priv;
+ p = buf;
+ e = p+len;
+ for(i = 0; i < Nstats; i++)
+ p = seprint(p, e, "%s: %llud\n", statnames[i], priv->stats[i]);
+ return p - buf;
+}
+
+/*
+ * garbage collect any stale conversations:
+ * - SYN received but no SYN-ACK after 5 seconds (could be the SYN attack)
+ * - Finwait2 after 5 minutes
+ *
+ * this is called whenever we run out of channels. Both checks are
+ * of questionable validity so we try to use them only when we're
+ * up against the wall.
+ */
+int
+tcpgc(Proto *tcp)
+{
+ Conv *c, **pp, **ep;
+ int n;
+ Tcpctl *tcb;
+
+
+ n = 0;
+ ep = &tcp->conv[tcp->nc];
+ for(pp = tcp->conv; pp < ep; pp++) {
+ c = *pp;
+ if(c == nil)
+ break;
+ if(!canqlock(c))
+ continue;
+ tcb = (Tcpctl*)c->ptcl;
+ switch(tcb->state){
+ case Syn_received:
+ if(NOW - tcb->time > 5000){
+ localclose(c, "timed out");
+ n++;
+ }
+ break;
+ case Finwait2:
+ if(NOW - tcb->time > 5*60*1000){
+ localclose(c, "timed out");
+ n++;
+ }
+ break;
+ }
+ qunlock(c);
+ }
+ return n;
+}
+
+void
+tcpsettimer(Tcpctl *tcb)
+{
+ int x;
+
+ /* round trip dependency */
+ x = backoff(tcb->backoff) *
+ (tcb->mdev + (tcb->srtt>>LOGAGAIN) + MSPTICK) / MSPTICK;
+
+ /* bounded twixt 1/2 and 64 seconds */
+ if(x < 500/MSPTICK)
+ x = 500/MSPTICK;
+ else if(x > (64000/MSPTICK))
+ x = 64000/MSPTICK;
+ tcb->timer.start = x;
+}
+
+void
+tcpinit(Fs *fs)
+{
+ Proto *tcp;
+ Tcppriv *tpriv;
+
+ tcp = smalloc(sizeof(Proto));
+ tpriv = tcp->priv = smalloc(sizeof(Tcppriv));
+ tcp->name = "tcp";
+ tcp->connect = tcpconnect;
+ tcp->announce = tcpannounce;
+ tcp->ctl = tcpctl;
+ tcp->state = tcpstate;
+ tcp->create = tcpcreate;
+ tcp->close = tcpclose;
+ tcp->rcv = tcpiput;
+ tcp->advise = tcpadvise;
+ tcp->stats = tcpstats;
+ tcp->inuse = tcpinuse;
+ tcp->gc = tcpgc;
+ tcp->ipproto = IP_TCPPROTO;
+ tcp->nc = scalednconv();
+ tcp->ptclsize = sizeof(Tcpctl);
+ tpriv->stats[MaxConn] = tcp->nc;
+
+ Fsproto(fs, tcp);
+}
+
+void
+tcpsetscale(Conv *s, Tcpctl *tcb, ushort rcvscale, ushort sndscale)
+{
+ if(rcvscale){
+ tcb->rcv.scale = rcvscale & 0xff;
+ tcb->snd.scale = sndscale & 0xff;
+ tcb->window = QMAX<<tcb->snd.scale;
+ qsetlimit(s->rq, tcb->window);
+ } else {
+ tcb->rcv.scale = 0;
+ tcb->snd.scale = 0;
+ tcb->window = QMAX;
+ qsetlimit(s->rq, tcb->window);
+ }
+}
diff --git a/sys/src/9/ip/udp.c b/sys/src/9/ip/udp.c
new file mode 100755
index 000000000..0f79b413f
--- /dev/null
+++ b/sys/src/9/ip/udp.c
@@ -0,0 +1,620 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ip.h"
+#include "ipv6.h"
+
+
+#define DPRINT if(0)print
+
+enum
+{
+ UDP_UDPHDR_SZ = 8,
+
+ UDP4_PHDR_OFF = 8,
+ UDP4_PHDR_SZ = 12,
+ UDP4_IPHDR_SZ = 20,
+ UDP6_IPHDR_SZ = 40,
+ UDP6_PHDR_SZ = 40,
+ UDP6_PHDR_OFF = 0,
+
+ IP_UDPPROTO = 17,
+ UDP_USEAD7 = 52,
+
+ Udprxms = 200,
+ Udptickms = 100,
+ Udpmaxxmit = 10,
+};
+
+typedef struct Udp4hdr Udp4hdr;
+struct Udp4hdr
+{
+ /* ip header */
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+ uchar Unused;
+ uchar udpproto; /* Protocol */
+ uchar udpplen[2]; /* Header plus data length */
+ uchar udpsrc[IPv4addrlen]; /* Ip source */
+ uchar udpdst[IPv4addrlen]; /* Ip destination */
+
+ /* udp header */
+ uchar udpsport[2]; /* Source port */
+ uchar udpdport[2]; /* Destination port */
+ uchar udplen[2]; /* data length */
+ uchar udpcksum[2]; /* Checksum */
+};
+
+typedef struct Udp6hdr Udp6hdr;
+struct Udp6hdr {
+ uchar viclfl[4];
+ uchar len[2];
+ uchar nextheader;
+ uchar hoplimit;
+ uchar udpsrc[IPaddrlen];
+ uchar udpdst[IPaddrlen];
+
+ /* udp header */
+ uchar udpsport[2]; /* Source port */
+ uchar udpdport[2]; /* Destination port */
+ uchar udplen[2]; /* data length */
+ uchar udpcksum[2]; /* Checksum */
+};
+
+/* MIB II counters */
+typedef struct Udpstats Udpstats;
+struct Udpstats
+{
+ uvlong udpInDatagrams;
+ ulong udpNoPorts;
+ ulong udpInErrors;
+ uvlong udpOutDatagrams;
+};
+
+typedef struct Udppriv Udppriv;
+struct Udppriv
+{
+ Ipht ht;
+
+ /* MIB counters */
+ Udpstats ustats;
+
+ /* non-MIB stats */
+ ulong csumerr; /* checksum errors */
+ ulong lenerr; /* short packet */
+};
+
+void (*etherprofiler)(char *name, int qlen);
+void udpkick(void *x, Block *bp);
+
+/*
+ * protocol specific part of Conv
+ */
+typedef struct Udpcb Udpcb;
+struct Udpcb
+{
+ QLock;
+ uchar headers;
+};
+
+static char*
+udpconnect(Conv *c, char **argv, int argc)
+{
+ char *e;
+ Udppriv *upriv;
+
+ upriv = c->p->priv;
+ e = Fsstdconnect(c, argv, argc);
+ Fsconnected(c, e);
+ if(e != nil)
+ return e;
+
+ iphtadd(&upriv->ht, c);
+ return nil;
+}
+
+
+static int
+udpstate(Conv *c, char *state, int n)
+{
+ return snprint(state, n, "%s qin %d qout %d\n",
+ c->inuse ? "Open" : "Closed",
+ c->rq ? qlen(c->rq) : 0,
+ c->wq ? qlen(c->wq) : 0
+ );
+}
+
+static char*
+udpannounce(Conv *c, char** argv, int argc)
+{
+ char *e;
+ Udppriv *upriv;
+
+ upriv = c->p->priv;
+ e = Fsstdannounce(c, argv, argc);
+ if(e != nil)
+ return e;
+ Fsconnected(c, nil);
+ iphtadd(&upriv->ht, c);
+
+ return nil;
+}
+
+static void
+udpcreate(Conv *c)
+{
+ c->rq = qopen(128*1024, Qmsg, 0, 0);
+ c->wq = qbypass(udpkick, c);
+}
+
+static void
+udpclose(Conv *c)
+{
+ Udpcb *ucb;
+ Udppriv *upriv;
+
+ upriv = c->p->priv;
+ iphtrem(&upriv->ht, c);
+
+ c->state = 0;
+ qclose(c->rq);
+ qclose(c->wq);
+ qclose(c->eq);
+ ipmove(c->laddr, IPnoaddr);
+ ipmove(c->raddr, IPnoaddr);
+ c->lport = 0;
+ c->rport = 0;
+
+ ucb = (Udpcb*)c->ptcl;
+ ucb->headers = 0;
+}
+
+void
+udpkick(void *x, Block *bp)
+{
+ Conv *c = x;
+ Udp4hdr *uh4;
+ Udp6hdr *uh6;
+ ushort rport;
+ uchar laddr[IPaddrlen], raddr[IPaddrlen];
+ Udpcb *ucb;
+ int dlen, ptcllen;
+ Udppriv *upriv;
+ Fs *f;
+ int version;
+ Conv *rc;
+
+ upriv = c->p->priv;
+ f = c->p->f;
+
+// netlog(c->p->f, Logudp, "udp: kick\n"); /* frequent and uninteresting */
+ if(bp == nil)
+ return;
+
+ ucb = (Udpcb*)c->ptcl;
+ switch(ucb->headers) {
+ case 7:
+ /* get user specified addresses */
+ bp = pullupblock(bp, UDP_USEAD7);
+ if(bp == nil)
+ return;
+ ipmove(raddr, bp->rp);
+ bp->rp += IPaddrlen;
+ ipmove(laddr, bp->rp);
+ bp->rp += IPaddrlen;
+ /* pick interface closest to dest */
+ if(ipforme(f, laddr) != Runi)
+ findlocalip(f, laddr, raddr);
+ bp->rp += IPaddrlen; /* Ignore ifc address */
+ rport = nhgets(bp->rp);
+ bp->rp += 2+2; /* Ignore local port */
+ break;
+ default:
+ rport = 0;
+ break;
+ }
+
+ if(ucb->headers) {
+ if(memcmp(laddr, v4prefix, IPv4off) == 0
+ || ipcmp(laddr, IPnoaddr) == 0)
+ version = 4;
+ else
+ version = 6;
+ } else {
+ if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
+ memcmp(c->laddr, v4prefix, IPv4off) == 0)
+ || ipcmp(c->raddr, IPnoaddr) == 0)
+ version = 4;
+ else
+ version = 6;
+ }
+
+ dlen = blocklen(bp);
+
+ /* fill in pseudo header and compute checksum */
+ switch(version){
+ case V4:
+ bp = padblock(bp, UDP4_IPHDR_SZ+UDP_UDPHDR_SZ);
+ if(bp == nil)
+ return;
+
+ uh4 = (Udp4hdr *)(bp->rp);
+ ptcllen = dlen + UDP_UDPHDR_SZ;
+ uh4->Unused = 0;
+ uh4->udpproto = IP_UDPPROTO;
+ uh4->frag[0] = 0;
+ uh4->frag[1] = 0;
+ hnputs(uh4->udpplen, ptcllen);
+ if(ucb->headers) {
+ v6tov4(uh4->udpdst, raddr);
+ hnputs(uh4->udpdport, rport);
+ v6tov4(uh4->udpsrc, laddr);
+ rc = nil;
+ } else {
+ v6tov4(uh4->udpdst, c->raddr);
+ hnputs(uh4->udpdport, c->rport);
+ if(ipcmp(c->laddr, IPnoaddr) == 0)
+ findlocalip(f, c->laddr, c->raddr);
+ v6tov4(uh4->udpsrc, c->laddr);
+ rc = c;
+ }
+ hnputs(uh4->udpsport, c->lport);
+ hnputs(uh4->udplen, ptcllen);
+ uh4->udpcksum[0] = 0;
+ uh4->udpcksum[1] = 0;
+ hnputs(uh4->udpcksum,
+ ptclcsum(bp, UDP4_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP4_PHDR_SZ));
+ uh4->vihl = IP_VER4;
+ ipoput4(f, bp, 0, c->ttl, c->tos, rc);
+ break;
+
+ case V6:
+ bp = padblock(bp, UDP6_IPHDR_SZ+UDP_UDPHDR_SZ);
+ if(bp == nil)
+ return;
+
+ /*
+ * using the v6 ip header to create pseudo header
+ * first then reset it to the normal ip header
+ */
+ uh6 = (Udp6hdr *)(bp->rp);
+ memset(uh6, 0, 8);
+ ptcllen = dlen + UDP_UDPHDR_SZ;
+ hnputl(uh6->viclfl, ptcllen);
+ uh6->hoplimit = IP_UDPPROTO;
+ if(ucb->headers) {
+ ipmove(uh6->udpdst, raddr);
+ hnputs(uh6->udpdport, rport);
+ ipmove(uh6->udpsrc, laddr);
+ rc = nil;
+ } else {
+ ipmove(uh6->udpdst, c->raddr);
+ hnputs(uh6->udpdport, c->rport);
+ if(ipcmp(c->laddr, IPnoaddr) == 0)
+ findlocalip(f, c->laddr, c->raddr);
+ ipmove(uh6->udpsrc, c->laddr);
+ rc = c;
+ }
+ hnputs(uh6->udpsport, c->lport);
+ hnputs(uh6->udplen, ptcllen);
+ uh6->udpcksum[0] = 0;
+ uh6->udpcksum[1] = 0;
+ hnputs(uh6->udpcksum,
+ ptclcsum(bp, UDP6_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP6_PHDR_SZ));
+ memset(uh6, 0, 8);
+ uh6->viclfl[0] = IP_VER6;
+ hnputs(uh6->len, ptcllen);
+ uh6->nextheader = IP_UDPPROTO;
+ ipoput6(f, bp, 0, c->ttl, c->tos, rc);
+ break;
+
+ default:
+ panic("udpkick: version %d", version);
+ }
+ upriv->ustats.udpOutDatagrams++;
+}
+
+void
+udpiput(Proto *udp, Ipifc *ifc, Block *bp)
+{
+ int len;
+ Udp4hdr *uh4;
+ Udp6hdr *uh6;
+ Conv *c;
+ Udpcb *ucb;
+ uchar raddr[IPaddrlen], laddr[IPaddrlen];
+ ushort rport, lport;
+ Udppriv *upriv;
+ Fs *f;
+ int version;
+ int ottl, oviclfl, olen;
+ uchar *p;
+
+ upriv = udp->priv;
+ f = udp->f;
+ upriv->ustats.udpInDatagrams++;
+
+ uh4 = (Udp4hdr*)(bp->rp);
+ version = ((uh4->vihl&0xF0)==IP_VER6) ? 6 : 4;
+
+ /* Put back pseudo header for checksum
+ * (remember old values for icmpnoconv()) */
+ switch(version) {
+ case V4:
+ ottl = uh4->Unused;
+ uh4->Unused = 0;
+ len = nhgets(uh4->udplen);
+ olen = nhgets(uh4->udpplen);
+ hnputs(uh4->udpplen, len);
+
+ v4tov6(raddr, uh4->udpsrc);
+ v4tov6(laddr, uh4->udpdst);
+ lport = nhgets(uh4->udpdport);
+ rport = nhgets(uh4->udpsport);
+
+ if(nhgets(uh4->udpcksum)) {
+ if(ptclcsum(bp, UDP4_PHDR_OFF, len+UDP4_PHDR_SZ)) {
+ upriv->ustats.udpInErrors++;
+ netlog(f, Logudp, "udp: checksum error %I\n", raddr);
+ DPRINT("udp: checksum error %I\n", raddr);
+ freeblist(bp);
+ return;
+ }
+ }
+ uh4->Unused = ottl;
+ hnputs(uh4->udpplen, olen);
+ break;
+ case V6:
+ uh6 = (Udp6hdr*)(bp->rp);
+ len = nhgets(uh6->udplen);
+ oviclfl = nhgetl(uh6->viclfl);
+ olen = nhgets(uh6->len);
+ ottl = uh6->hoplimit;
+ ipmove(raddr, uh6->udpsrc);
+ ipmove(laddr, uh6->udpdst);
+ lport = nhgets(uh6->udpdport);
+ rport = nhgets(uh6->udpsport);
+ memset(uh6, 0, 8);
+ hnputl(uh6->viclfl, len);
+ uh6->hoplimit = IP_UDPPROTO;
+ if(ptclcsum(bp, UDP6_PHDR_OFF, len+UDP6_PHDR_SZ)) {
+ upriv->ustats.udpInErrors++;
+ netlog(f, Logudp, "udp: checksum error %I\n", raddr);
+ DPRINT("udp: checksum error %I\n", raddr);
+ freeblist(bp);
+ return;
+ }
+ hnputl(uh6->viclfl, oviclfl);
+ hnputs(uh6->len, olen);
+ uh6->nextheader = IP_UDPPROTO;
+ uh6->hoplimit = ottl;
+ break;
+ default:
+ panic("udpiput: version %d", version);
+ return; /* to avoid a warning */
+ }
+
+ qlock(udp);
+
+ c = iphtlook(&upriv->ht, raddr, rport, laddr, lport);
+ if(c == nil){
+ /* no conversation found */
+ upriv->ustats.udpNoPorts++;
+ qunlock(udp);
+ netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,
+ laddr, lport);
+
+ switch(version){
+ case V4:
+ icmpnoconv(f, bp);
+ break;
+ case V6:
+ icmphostunr(f, ifc, bp, Icmp6_port_unreach, 0);
+ break;
+ default:
+ panic("udpiput2: version %d", version);
+ }
+
+ freeblist(bp);
+ return;
+ }
+ ucb = (Udpcb*)c->ptcl;
+
+ if(c->state == Announced){
+ if(ucb->headers == 0){
+ /* create a new conversation */
+ if(ipforme(f, laddr) != Runi) {
+ switch(version){
+ case V4:
+ v4tov6(laddr, ifc->lifc->local);
+ break;
+ case V6:
+ ipmove(laddr, ifc->lifc->local);
+ break;
+ default:
+ panic("udpiput3: version %d", version);
+ }
+ }
+ c = Fsnewcall(c, raddr, rport, laddr, lport, version);
+ if(c == nil){
+ qunlock(udp);
+ freeblist(bp);
+ return;
+ }
+ iphtadd(&upriv->ht, c);
+ ucb = (Udpcb*)c->ptcl;
+ }
+ }
+
+ qlock(c);
+ qunlock(udp);
+
+ /*
+ * Trim the packet down to data size
+ */
+ len -= UDP_UDPHDR_SZ;
+ switch(version){
+ case V4:
+ bp = trimblock(bp, UDP4_IPHDR_SZ+UDP_UDPHDR_SZ, len);
+ break;
+ case V6:
+ bp = trimblock(bp, UDP6_IPHDR_SZ+UDP_UDPHDR_SZ, len);
+ break;
+ default:
+ bp = nil;
+ panic("udpiput4: version %d", version);
+ }
+ if(bp == nil){
+ qunlock(c);
+ netlog(f, Logudp, "udp: len err %I.%d -> %I.%d\n", raddr, rport,
+ laddr, lport);
+ upriv->lenerr++;
+ return;
+ }
+
+ netlog(f, Logudpmsg, "udp: %I.%d -> %I.%d l %d\n", raddr, rport,
+ laddr, lport, len);
+
+ switch(ucb->headers){
+ case 7:
+ /* pass the src address */
+ bp = padblock(bp, UDP_USEAD7);
+ p = bp->rp;
+ ipmove(p, raddr); p += IPaddrlen;
+ ipmove(p, laddr); p += IPaddrlen;
+ ipmove(p, ifc->lifc->local); p += IPaddrlen;
+ hnputs(p, rport); p += 2;
+ hnputs(p, lport);
+ break;
+ }
+
+ if(bp->next)
+ bp = concatblock(bp);
+
+ if(qfull(c->rq)){
+ qunlock(c);
+ netlog(f, Logudp, "udp: qfull %I.%d -> %I.%d\n", raddr, rport,
+ laddr, lport);
+ freeblist(bp);
+ return;
+ }
+
+ qpass(c->rq, bp);
+ qunlock(c);
+
+}
+
+char*
+udpctl(Conv *c, char **f, int n)
+{
+ Udpcb *ucb;
+
+ ucb = (Udpcb*)c->ptcl;
+ if(n == 1){
+ if(strcmp(f[0], "headers") == 0){
+ ucb->headers = 7; /* new headers format */
+ return nil;
+ }
+ }
+ return "unknown control request";
+}
+
+void
+udpadvise(Proto *udp, Block *bp, char *msg)
+{
+ Udp4hdr *h4;
+ Udp6hdr *h6;
+ uchar source[IPaddrlen], dest[IPaddrlen];
+ ushort psource, pdest;
+ Conv *s, **p;
+ int version;
+
+ h4 = (Udp4hdr*)(bp->rp);
+ version = ((h4->vihl&0xF0)==IP_VER6) ? 6 : 4;
+
+ switch(version) {
+ case V4:
+ v4tov6(dest, h4->udpdst);
+ v4tov6(source, h4->udpsrc);
+ psource = nhgets(h4->udpsport);
+ pdest = nhgets(h4->udpdport);
+ break;
+ case V6:
+ h6 = (Udp6hdr*)(bp->rp);
+ ipmove(dest, h6->udpdst);
+ ipmove(source, h6->udpsrc);
+ psource = nhgets(h6->udpsport);
+ pdest = nhgets(h6->udpdport);
+ break;
+ default:
+ panic("udpadvise: version %d", version);
+ return; /* to avoid a warning */
+ }
+
+ /* Look for a connection */
+ qlock(udp);
+ for(p = udp->conv; *p; p++) {
+ s = *p;
+ if(s->rport == pdest)
+ if(s->lport == psource)
+ if(ipcmp(s->raddr, dest) == 0)
+ if(ipcmp(s->laddr, source) == 0){
+ if(s->ignoreadvice)
+ break;
+ qlock(s);
+ qunlock(udp);
+ qhangup(s->rq, msg);
+ qhangup(s->wq, msg);
+ qunlock(s);
+ freeblist(bp);
+ return;
+ }
+ }
+ qunlock(udp);
+ freeblist(bp);
+}
+
+int
+udpstats(Proto *udp, char *buf, int len)
+{
+ Udppriv *upriv;
+
+ upriv = udp->priv;
+ return snprint(buf, len, "InDatagrams: %llud\nNoPorts: %lud\n"
+ "InErrors: %lud\nOutDatagrams: %llud\n",
+ upriv->ustats.udpInDatagrams,
+ upriv->ustats.udpNoPorts,
+ upriv->ustats.udpInErrors,
+ upriv->ustats.udpOutDatagrams);
+}
+
+void
+udpinit(Fs *fs)
+{
+ Proto *udp;
+
+ udp = smalloc(sizeof(Proto));
+ udp->priv = smalloc(sizeof(Udppriv));
+ udp->name = "udp";
+ udp->connect = udpconnect;
+ udp->announce = udpannounce;
+ udp->ctl = udpctl;
+ udp->state = udpstate;
+ udp->create = udpcreate;
+ udp->close = udpclose;
+ udp->rcv = udpiput;
+ udp->advise = udpadvise;
+ udp->stats = udpstats;
+ udp->ipproto = IP_UDPPROTO;
+ udp->nc = Nchans;
+ udp->ptclsize = sizeof(Udpcb);
+
+ Fsproto(fs, udp);
+}
diff --git a/sys/src/9/kw/arch.c b/sys/src/9/kw/arch.c
new file mode 100755
index 000000000..c800ffc77
--- /dev/null
+++ b/sys/src/9/kw/arch.c
@@ -0,0 +1,222 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include <tos.h>
+#include "ureg.h"
+
+#include "arm.h"
+
+/*
+ * A lot of this stuff doesn't belong here
+ * but this is a convenient dumping ground for
+ * later sorting into the appropriate buckets.
+ */
+
+/* Give enough context in the ureg to produce a kernel stack for
+ * a sleeping process
+ */
+void
+setkernur(Ureg* ureg, Proc* p)
+{
+ ureg->pc = p->sched.pc;
+ ureg->sp = p->sched.sp+4;
+ ureg->r14 = PTR2UINT(sched);
+}
+
+/*
+ * called in sysfile.c
+ */
+void
+evenaddr(uintptr addr)
+{
+ if(addr & 3){
+ postnote(up, 1, "sys: odd address", NDebug);
+ error(Ebadarg);
+ }
+}
+
+/* go to user space */
+void
+kexit(Ureg*)
+{
+ uvlong t;
+ Tos *tos;
+
+ /* precise time accounting, kernel exit */
+ tos = (Tos*)(USTKTOP-sizeof(Tos));
+ t = fastticks(nil);
+ tos->kcycles += t - up->kentry;
+ tos->pcycles = up->pcycles;
+ tos->cyclefreq = Frequency;
+ tos->pid = up->pid;
+
+ /* make visible immediately to user proc */
+ cachedwbinvse(tos, sizeof *tos);
+}
+
+/*
+ * return the userpc the last exception happened at
+ */
+uintptr
+userpc(void)
+{
+ Ureg *ureg = up->dbgreg;
+ return ureg->pc;
+}
+
+/* This routine must save the values of registers the user is not permitted
+ * to write from devproc and then restore the saved values before returning.
+ */
+void
+setregisters(Ureg* ureg, char* pureg, char* uva, int n)
+{
+ USED(ureg, pureg, uva, n);
+}
+
+/*
+ * this is the body for all kproc's
+ */
+static void
+linkproc(void)
+{
+ spllo();
+ up->kpfun(up->kparg);
+ pexit("kproc exiting", 0);
+}
+
+/*
+ * setup stack and initial PC for a new kernel proc. This is architecture
+ * dependent because of the starting stack location
+ */
+void
+kprocchild(Proc *p, void (*func)(void*), void *arg)
+{
+ p->sched.pc = PTR2UINT(linkproc);
+ p->sched.sp = PTR2UINT(p->kstack+KSTACK);
+
+ p->kpfun = func;
+ p->kparg = arg;
+}
+
+/*
+ * pc output by dumpaproc
+ */
+uintptr
+dbgpc(Proc* p)
+{
+ Ureg *ureg;
+
+ ureg = p->dbgreg;
+ if(ureg == 0)
+ return 0;
+
+ return ureg->pc;
+}
+
+/*
+ * set mach dependent process state for a new process
+ */
+void
+procsetup(Proc* p)
+{
+ fpusysprocsetup(p);
+}
+
+/*
+ * Save the mach dependent part of the process state.
+ */
+void
+procsave(Proc* p)
+{
+ uvlong t;
+
+ cycles(&t);
+ p->pcycles += t;
+
+ fpuprocsave(p);
+}
+
+void
+procrestore(Proc* p)
+{
+ uvlong t;
+
+ if(p->kp)
+ return;
+ t = lcycles();
+ p->pcycles -= t;
+
+ fpuprocrestore(p);
+}
+
+int
+userureg(Ureg* ureg)
+{
+ return (ureg->psr & PsrMask) == PsrMusr;
+}
+
+/*
+ * atomic ops
+ * make sure that we don't drag in the C library versions
+ */
+
+long
+_xdec(long *p)
+{
+ int s, v;
+
+ s = splhi();
+ v = --*p;
+ splx(s);
+ return v;
+}
+
+void
+_xinc(long *p)
+{
+ int s;
+
+ s = splhi();
+ ++*p;
+ splx(s);
+}
+
+int
+ainc(int *p)
+{
+ int s, v;
+
+ s = splhi();
+ v = ++*p;
+ splx(s);
+ return v;
+}
+
+int
+adec(int *p)
+{
+ int s, v;
+
+ s = splhi();
+ v = --*p;
+ splx(s);
+ return v;
+}
+
+int
+cas32(void* addr, u32int old, u32int new)
+{
+ int r, s;
+
+ s = splhi();
+ if(r = (*(u32int*)addr == old))
+ *(u32int*)addr = new;
+ splx(s);
+ if (r)
+ coherence();
+ return r;
+}
diff --git a/sys/src/9/kw/archkw.c b/sys/src/9/kw/archkw.c
new file mode 100755
index 000000000..d6fd700fa
--- /dev/null
+++ b/sys/src/9/kw/archkw.c
@@ -0,0 +1,519 @@
+/*
+ * stuff specific to marvell's kirkwood architecture
+ * as seen in the sheevaplug
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+#include "../port/netif.h"
+#include "etherif.h"
+#include "../port/flashif.h"
+
+#include "arm.h"
+
+enum {
+ L2writeback = 1,
+ Debug = 0,
+};
+
+typedef struct GpioReg GpioReg;
+struct GpioReg {
+ ulong dataout;
+ ulong dataoutena;
+ ulong blinkena;
+ ulong datainpol;
+ ulong datain;
+ ulong intrcause;
+ ulong intrmask;
+ ulong intrlevelmask;
+};
+
+typedef struct L2uncache L2uncache;
+typedef struct L2win L2win;
+struct L2uncache {
+ struct L2win {
+ ulong base; /* phys addr */
+ ulong size;
+ } win[4];
+};
+
+enum {
+ /* L2win->base bits */
+ L2enable = 1<<0,
+};
+
+typedef struct Dramctl Dramctl;
+struct Dramctl {
+ ulong ctl;
+ ulong ddrctllo;
+ struct {
+ ulong lo;
+ ulong hi;
+ } time;
+ ulong addrctl;
+ ulong opagectl;
+ ulong oper;
+ ulong mode;
+ ulong extmode;
+ ulong ddrctlhi;
+ ulong ddr2timelo;
+ ulong operctl;
+ struct {
+ ulong lo;
+ ulong hi;
+ } mbusctl;
+ ulong mbustimeout;
+ ulong ddrtimehi;
+ ulong sdinitctl;
+ ulong extsdmode1;
+ ulong extsdmode2;
+ struct {
+ ulong lo;
+ ulong hi;
+ } odtctl;
+ ulong ddrodtctl;
+ ulong rbuffsel;
+
+ ulong accalib;
+ ulong dqcalib;
+ ulong dqscalib;
+};
+
+/* unused so far */
+typedef struct SDramdReg SDramdReg;
+struct SDramdReg {
+ struct {
+ ulong base;
+ ulong size;
+ } win[4];
+};
+
+typedef struct Addrmap Addrmap;
+typedef struct Addrwin Addrwin;
+struct Addrmap {
+ struct Addrwin {
+ ulong ctl; /* see Winenable in io.h */
+ ulong base;
+ ulong remaplo;
+ ulong remaphi;
+ } win[8];
+ ulong dirba; /* device internal reg's base addr.: PHYSIO */
+};
+
+Soc soc = {
+ .cpu = PHYSIO+0x20100,
+ .devid = PHYSIO+0x10034,
+ .l2cache = PHYSIO+0x20a00, /* uncachable addrs for L2 */
+ .sdramc = PHYSIO+0x01400,
+// .sdramd = PHYSIO+0x01500, /* unused */
+
+ .iocfg = PHYSIO+0x100e0,
+ .addrmap = PHYSIO+0x20000,
+ .intr = PHYSIO+0x20200,
+ .nand = PHYSIO+0x10418,
+ .cesa = PHYSIO+0x30000, /* crypto accelerator */
+ .ehci = PHYSIO+0x50000,
+ .spi = PHYSIO+0x10600,
+ .twsi = PHYSIO+0x11000,
+
+ .analog = PHYSIO+0x1007c,
+ .pci = PHYSIO+0x40000,
+ .pcibase = PHYSIO+0x41800,
+
+ .rtc = PHYSIO+0x10300,
+ .clock = PHYSIO+0x20300,
+// .clockctl = PHYSIO+0x1004c, /* unused */
+
+ .ether = { PHYSIO+0x72000, PHYSIO+0x76000, },
+ .sata = { PHYSIO+0x80000, /* sata config reg here */
+ PHYSIO+0x82000, /* edma config reg here */
+ PHYSIO+0x84000, /* edma config reg here */
+ },
+ .uart = { PHYSIO+0x12000, PHYSIO+0x12100, },
+ .gpio = { PHYSIO+0x10100, PHYSIO+0x10140, },
+};
+
+/*
+ * sheeva/openrd u-boot leaves us with this address map:
+ *
+ * 0 targ 4 attr 0xe8 size 256MB addr 0x9:: remap addr 0x9:: pci mem
+ * 1 targ 1 attr 0x2f size 8MB addr 0xf9:: remap addr 0xf9:: nand flash
+ * 2 targ 4 attr 0xe0 size 16MB addr 0xf:: remap addr 0xc:: pci i/o
+ * 3 targ 1 attr 0x1e size 16MB addr 0xf8:: remap addr 0x0 spi flash
+ * 4 targ 1 attr 0x1d size 16MB addr 0xff:: boot rom
+ * 5 targ 1 attr 0x1e size 128MB addr 0xe8:: disabled spi flash
+ * 6 targ 1 attr 0x1d size 128MB addr 0xf:: disabled boot rom
+ * 7 targ 3 attr 0x1 size 64K addr 0xfb:: crypto sram
+ */
+#define WINTARG(ctl) (((ctl) >> 4) & 017)
+#define WINATTR(ctl) (((ctl) >> 8) & 0377)
+#define WIN64KSIZE(ctl) (((ctl) >> 16) + 1)
+
+static void
+praddrwin(Addrwin *win, int i)
+{
+ ulong ctl, targ, attr, size64k;
+
+ if (!Debug) {
+ USED(win, i);
+ return;
+ }
+ ctl = win->ctl;
+ targ = WINTARG(ctl);
+ attr = WINATTR(ctl);
+ size64k = WIN64KSIZE(ctl);
+ print("cpu addr map: %s window %d: targ %ld attr %#lux size %,ld addr %#lux",
+ ctl & Winenable? "enabled": "disabled", i, targ, attr,
+ size64k * 64*1024, win->base);
+ if (i < 4)
+ print(" remap addr %#llux", (uvlong)win->remaphi<<32 |
+ win->remaplo);
+ print("\n");
+}
+
+static void
+fixaddrmap(void)
+{
+ int i;
+ ulong ctl, targ, attr, size64k;
+ Addrmap *map;
+ Addrwin *win;
+
+ map = (Addrmap *)soc.addrmap;
+ for (i = 0; i < nelem(map->win); i++) {
+ win = &map->win[i];
+ ctl = win->ctl;
+ targ = WINTARG(ctl);
+ attr = WINATTR(ctl);
+ size64k = WIN64KSIZE(ctl);
+
+ USED(attr, size64k);
+ if (targ == Targcesasram) {
+ win->ctl |= Winenable;
+ win->base = PHYSCESASRAM;
+ coherence();
+ praddrwin(win, i);
+ }
+ }
+ if (map->dirba != PHYSIO)
+ panic("dirba not %#ux", PHYSIO);
+}
+
+static void
+praddrmap(void)
+{
+ int i;
+ Addrmap *map;
+
+ map = (Addrmap *)soc.addrmap;
+ for (i = 0; i < nelem(map->win); i++)
+ praddrwin(&map->win[i], i);
+}
+
+int
+ispow2(uvlong ul)
+{
+ /* see Hacker's Delight if this isn't obvious */
+ return (ul & (ul - 1)) == 0;
+}
+
+/*
+ * return exponent of smallest power of 2 ≥ n
+ */
+int
+log2(ulong n)
+{
+ int i;
+
+ i = 31 - clz(n);
+ if (!ispow2(n) || n == 0)
+ i++;
+ return i;
+}
+
+void
+cacheinfo(int level, int kind, Memcache *cp) /* l1 only */
+{
+ uint len, assoc, size;
+ ulong setsways;
+
+ /* get cache types & sizes (read-only reg) */
+ setsways = cprdsc(0, CpID, CpIDidct, CpIDct);
+
+ cp->level = level;
+ cp->kind = kind;
+
+ if ((setsways & (1<<24)) == 0)
+ kind = Unified;
+ if (kind != Icache)
+ setsways >>= 12;
+
+ assoc = (setsways >> 3) & MASK(3);
+ cp->nways = 1 << assoc;
+ size = (setsways >> 6) & MASK(4);
+ cp->size = 1 << (size + 9);
+ len = setsways & MASK(2);
+ cp->log2linelen = len + 3;
+ cp->linelen = 1 << cp->log2linelen;
+ cp->setsways = setsways;
+
+ cp->nsets = 1 << (size + 6 - assoc - len);
+ cp->setsh = cp->log2linelen;
+ cp->waysh = 32 - log2(cp->nways);
+}
+
+static char *
+wbtype(uint type)
+{
+ static char *types[] = {
+ "write-through",
+ "read data block",
+ "reg 7 ops, no lock-down",
+ [06] "reg 7 ops, format A",
+ [07] "reg 7 ops, format B deprecated",
+ [016] "reg 7 ops, format C",
+ [05] "reg 7 ops, format D",
+ };
+
+ if (type >= nelem(types) || types[type] == nil)
+ return "GOK";
+ return types[type];
+}
+
+static void
+prcache(Memcache *mcp)
+{
+ int type;
+ char id;
+
+ if (mcp->kind == Unified)
+ id = 'U';
+ else if (mcp->kind == Icache)
+ id = 'I';
+ else if (mcp->kind == Dcache)
+ id = 'D';
+ else
+ id = '?';
+ print("l%d %c: %d bytes, %d ways %d sets %d bytes/line",
+ mcp->level, id, mcp->size, mcp->nways, mcp->nsets,
+ mcp->linelen);
+ if (mcp->linelen != CACHELINESZ)
+ print(" *should* be %d", CACHELINESZ);
+ type = (mcp->setsways >> 25) & MASK(4);
+ if (type == 0)
+ print("; write-through only");
+ else
+ print("; write-back type `%s' (%#o) possible",
+ wbtype(type), type);
+ if (mcp->setsways & (1<<11))
+ print("; page table mapping restrictions apply");
+ if (mcp->setsways & (1<<2))
+ print("; M bit is set in cache type reg");
+ print("\n");
+}
+
+static void
+prcachecfg(void)
+{
+ Memcache mc;
+
+ cacheinfo(1, Dcache, &mc);
+ prcache(&mc);
+ cacheinfo(1, Icache, &mc);
+ prcache(&mc);
+}
+
+void
+l2cacheon(void)
+{
+ ulong cfg;
+ CpucsReg *cpu;
+ L2uncache *l2p;
+
+ cacheuwbinv();
+ l2cacheuwbinv();
+ l1cachesoff(); /* turns off L2 as a side effect */
+
+ cpwrsc(CpDef, CpCLD, 0, 0, 0); /* GL-CPU-100: set D cache lockdown reg. */
+
+ /* marvell guideline GL-CPU-130 */
+ cpu = (CpucsReg *)soc.cpu;
+ cfg = cpu->cpucfg | L2exists | L2ecc | Cfgiprefetch | Cfgdprefetch;
+
+ if (L2writeback)
+ cfg &= ~L2writethru; /* see PTE Cached & Buffered bits */
+ else
+ cfg |= L2writethru;
+ cpu->l2cfg = cfg;
+ coherence(); /* force l2 cache to pay attention */
+ cpu->l2tm1 = cpu->l2tm0 = 0x66666666; /* marvell guideline GL-CPU-120 */
+ coherence();
+
+ cpwrsc(CpL2, CpTESTCFG, CpTCl2waylck, CpTCl2waylock, 0);
+
+ cachedinv();
+ l2cacheuinv();
+
+ /* disable l2 caching of i/o registers */
+ l2p = (L2uncache *)soc.l2cache;
+ memset(l2p, 0, sizeof *l2p);
+ /*
+ * l2: don't cache upper half of address space.
+ * the L2 cache is PIPT, so the addresses are physical.
+ */
+ l2p->win[0].base = 0x80000000 | L2enable; /* 64K multiple */
+ l2p->win[0].size = (32*1024-1) << 16; /* 64K multiples */
+ coherence();
+
+ l2cachecfgon();
+ l1cacheson(); /* turns L2 on as a side effect */
+ print("l2 cache: 256K or 512K: 4 ways, 32-byte lines, write-%s, sdram only\n",
+ cpu->l2cfg & L2writethru? "through": "back");
+}
+
+/* called late in main */
+void
+archconfinit(void)
+{
+ m->cpuhz = Frequency;
+ m->delayloop = m->cpuhz/2000; /* initial estimate */
+ fixaddrmap();
+ if (Debug)
+ praddrmap();
+ prcachecfg();
+
+ l2cacheon();
+}
+
+void
+archkwlink(void)
+{
+}
+
+int
+archether(unsigned ctlno, Ether *ether)
+{
+ if(ctlno >= 2)
+ return -1;
+ ether->type = "88e1116";
+ ether->port = ctlno;
+// ether->mbps = 1000;
+ return 1;
+}
+
+/* LED/USB gpios */
+enum {
+ /*
+ * the bit assignments are MPP pin numbers from the last page of the
+ * sheevaplug 6.0.1 schematic.
+ */
+ KWOEValHigh = 1<<(49-32), /* pin 49: LED pin */
+ KWOEValLow = 1<<29, /* pin 29: USB_PWEN, pin 28: usb_pwerr */
+ KWOELow = ~0,
+ KWOEHigh = ~0,
+};
+
+/* called early in main */
+void
+archreset(void)
+{
+ ulong clocks;
+ CpucsReg *cpu;
+ Dramctl *dram;
+ GpioReg *gpio;
+
+ clockshutdown(); /* watchdog disabled */
+
+ /* configure gpios */
+ gpio = (GpioReg*)soc.gpio[0];
+ gpio->dataout = KWOEValLow;
+ coherence();
+ gpio->dataoutena = KWOELow;
+
+ gpio = (GpioReg*)soc.gpio[1];
+ gpio->dataout = KWOEValHigh;
+ coherence();
+ gpio->dataoutena = KWOEHigh;
+ coherence();
+
+ cpu = (CpucsReg *)soc.cpu;
+ cpu->mempm = 0; /* turn everything on */
+ coherence();
+
+ clocks = MASK(10);
+ clocks |= MASK(21) & ~MASK(14);
+ clocks &= ~(1<<18 | 1<<1); /* reserved bits */
+ cpu->clockgate |= clocks; /* enable all the clocks */
+ cpu->l2cfg |= L2exists; /* when L2exists is 0, the l2 ignores us */
+ coherence();
+
+ dram = (Dramctl *)soc.sdramc;
+ dram->ddrctllo &= ~(1<<6); /* marvell guideline GL-MEM-70 */
+
+ *(ulong *)soc.analog = 0x68; /* marvell guideline GL-MISC-40 */
+ coherence();
+}
+
+void
+archreboot(void)
+{
+ CpucsReg *cpu;
+
+ iprint("reset!\n");
+ delay(10);
+
+ cpu = (CpucsReg *)soc.cpu;
+ cpu->rstout = RstoutSoft;
+ cpu->softreset = ResetSystem;
+ coherence();
+ cpu->cpucsr = Reset;
+ coherence();
+ delay(500);
+
+ splhi();
+ iprint("waiting...");
+ for(;;)
+ idlehands();
+}
+
+void
+archconsole(void)
+{
+// uartconsole(0, "b115200");
+//serialputs("uart0 console @ 115200\n", strlen("uart0 console @ 115200\n"));
+}
+
+void
+archflashwp(Flash*, int)
+{
+}
+
+int flashat(Flash *f, uintptr pa);
+
+/*
+ * for ../port/devflash.c:/^flashreset
+ * retrieve flash type, virtual base and length and return 0;
+ * return -1 on error (no flash)
+ */
+int
+archflashreset(int bank, Flash *f)
+{
+ if(bank != 0)
+ return -1;
+ f->type = "nand";
+ if (flashat(f, PHYSNAND1))
+ f->addr = (void*)PHYSNAND1;
+ else if (flashat(f, PHYSNAND2))
+ f->addr = (void*)PHYSNAND2;
+ else
+ f->addr = nil;
+ f->size = 0; /* done by probe */
+ f->width = 1;
+ f->interleave = 0;
+ return 0;
+}
diff --git a/sys/src/9/kw/arm.h b/sys/src/9/kw/arm.h
new file mode 100755
index 000000000..a9e2ff100
--- /dev/null
+++ b/sys/src/9/kw/arm.h
@@ -0,0 +1,194 @@
+/*
+ * Program Status Registers
+ */
+#define PsrMusr 0x00000010 /* mode */
+#define PsrMfiq 0x00000011
+#define PsrMirq 0x00000012
+#define PsrMsvc 0x00000013
+#define PsrMabt 0x00000017
+#define PsrMund 0x0000001B
+#define PsrMsys 0x0000001F
+#define PsrMask 0x0000001F
+
+#define PsrDfiq 0x00000040 /* disable FIQ interrupts */
+#define PsrDirq 0x00000080 /* disable IRQ interrupts */
+
+#define PsrV 0x10000000 /* overflow */
+#define PsrC 0x20000000 /* carry/borrow/extend */
+#define PsrZ 0x40000000 /* zero */
+#define PsrN 0x80000000 /* negative/less than */
+
+/*
+ * Coprocessors
+ */
+#define CpFP 10 /* float FP, VFP cfg. */
+#define CpDFP 11 /* double FP */
+#define CpSC 15 /* System Control */
+
+/*
+ * opcode 1
+ */
+#define CpDef 0 /* default */
+#define CpL2 1 /* L2 cache operations */
+
+/*
+ * Primary (CRn) CpSC registers.
+ */
+#define CpID 0 /* ID and cache type */
+#define CpCONTROL 1 /* miscellaneous control */
+#define CpTTB 2 /* Translation Table Base */
+#define CpDAC 3 /* Domain Access Control */
+#define CpFSR 5 /* Fault Status */
+#define CpFAR 6 /* Fault Address */
+#define CpCACHE 7 /* cache/write buffer control */
+#define CpTLB 8 /* TLB control */
+#define CpCLD 9 /* Cache Lockdown */
+#define CpTLD 10 /* TLB Lockdown */
+#define CpPID 13 /* Process ID */
+#define CpTESTCFG 15 /* test config. (arm926) */
+
+/*
+ * CpID Secondary (CRm) registers.
+ */
+#define CpIDidct 0
+/*
+ * CpID op1==0 opcode2 fields.
+ */
+#define CpIDid 0 /* main ID */
+#define CpIDct 1 /* cache type */
+
+/*
+ * CpCONTROL
+ */
+#define CpCmmu 0x00000001 /* M: MMU enable */
+#define CpCalign 0x00000002 /* A: alignment fault enable */
+#define CpCdcache 0x00000004 /* C: data cache on */
+#define CpCwb 0x00000008 /* W: write buffer turned on */
+#define CpCi32 0x00000010 /* P: 32-bit program space */
+#define CpCd32 0x00000020 /* D: 32-bit data space */
+#define CpCbe 0x00000080 /* B: big-endian operation */
+#define CpCsystem 0x00000100 /* S: system permission */
+#define CpCrom 0x00000200 /* R: ROM permission */
+#define CpCicache 0x00001000 /* I: instruction cache on */
+#define CpChv 0x00002000 /* V: high vectors */
+
+/*
+ * CpCACHE Secondary (CRm) registers and opcode2 fields.
+ * In ARM-speak, 'flush' means invalidate and 'clean' means writeback.
+ * In arm arch v6, these must be available in user mode:
+ * CpCACHEinvi, CpCACHEwait (prefetch flush)
+ * CpCACHEwb, CpCACHEwait (DSB: data sync barrier)
+ * CpCACHEwb, CpCACHEdmbarr (DMB: data memory barrier)
+ */
+#define CpCACHEintr 0 /* interrupt */
+#define CpCACHEinvi 5 /* instruction */
+#define CpCACHEinvd 6 /* data */
+#define CpCACHEinvu 7 /* unified (I+D) */
+#define CpCACHEwb 10 /* writeback D */
+#define CpCACHEwbu 11 /* writeback U (not 926ejs) */
+#define CpCACHEwbi 14 /* writeback D + invalidate */
+#define CpCACHEwbui 15 /* writeback U + inval (not 926ejs) */
+
+/*
+ * the 926ejs manual says that we can't use CpCACHEall nor CpCACHEwait
+ * for writeback operations on the 926ejs, except for CpCACHEwb + CpCACHEwait,
+ * which means `drain write buffer'.
+ */
+#define CpCACHEall 0 /* entire */
+#define CpCACHEse 1 /* single entry */
+#define CpCACHEsi 2 /* set/index */
+#define CpCACHEtest 3 /* test loop */
+#define CpCACHEwait 4 /* wait */
+#define CpCACHEdmbarr 5 /* wb: data memory barrier */
+
+/*
+ * CpTLB Secondary (CRm) registers and opcode2 fields.
+ */
+#define CpTLBinvi 5 /* instruction */
+#define CpTLBinvd 6 /* data */
+#define CpTLBinvu 7 /* unified */
+
+#define CpTLBinv 0 /* invalidate all */
+#define CpTLBinvse 1 /* invalidate single entry */
+
+/*
+ * CpTESTCFG Secondary (CRm) registers and opcode2 fields; sheeva only.
+ * opcode1 == CpL2 (1). L2 cache operations block the CPU until finished.
+ * Specifically, write-back (clean) blocks until all dirty lines have been
+ * drained from the L2 buffers.
+ */
+#define CpTCl2cfg 1
+#define CpTCl2flush 9 /* cpu blocks until flush done */
+#define CpTCl2waylck 10
+#define CpTCl2inv 11
+#define CpTCl2perfctl 12
+#define CpTCl2perfcnt 13
+
+/* CpTCl2cfg */
+#define CpTCl2conf 0
+
+/* CpTCl2conf bits */
+#define CpTCldcstream (1<<29) /* D cache streaming switch */
+#define CpTCl2wralloc (1<<28) /* cache write allocate */
+#define CpTCl2prefdis (1<<24) /* l2 cache prefetch disable */
+#define CpTCl2ena (1<<22) /* l2 cache enable */
+
+/* CpTCl2flush & CpTCl2inv */
+#define CpTCl2all 0
+#define CpTCl2seva 1
+#define CpTCl2way 2
+#define CpTCl2sepa 3
+#define CpTCl2valow 4
+#define CpTCl2vahigh 5 /* also triggers flush or inv */
+
+/* CpTCl2flush
+#define CpTCecccnt 6 /* ecc error count */
+#define CpTCeccthr 7 /* ecc error threshold */
+
+/* CpTCl2waylck */
+#define CpTCl2waylock 7
+
+/* CpTCl2inv */
+#define CpTCl2erraddr 7 /* ecc error address */
+
+/* CpTCl2perfctl */
+#define CpTCl2perf0ctl 0
+#define CpTCl2perf1ctl 1
+
+/* CpTCl2perfcnt */
+#define CpTCl2perf0low 0
+#define CpTCl2perf0high 1
+#define CpTCl2perf1low 2
+#define CpTCl2perf1high 3
+
+/*
+ * MMU page table entries.
+ * Mbo (0x10) bit is implementation-defined and mandatory on some pre-v7 arms.
+ */
+#define Mbo 0x10 /* must be 1 on earlier arms */
+#define Fault 0x00000000 /* L[12] pte: unmapped */
+
+#define Coarse (Mbo|1) /* L1 */
+#define Section (Mbo|2) /* L1 1MB */
+#define Fine (Mbo|3) /* L1 */
+
+#define Large 0x00000001u /* L2 64KB */
+#define Small 0x00000002u /* L2 4KB */
+#define Tiny 0x00000003u /* L2 1KB, deprecated */
+#define Buffered 0x00000004u /* L[12]: write-back not -thru */
+#define Cached 0x00000008u /* L[12] */
+
+#define Dom0 0
+#define Noaccess 0 /* AP, DAC */
+#define Krw 1 /* AP */
+#define Uro 2 /* AP */
+#define Urw 3 /* AP */
+#define Client 1 /* DAC */
+#define Manager 3 /* DAC */
+
+#define AP(n, v) F((v), ((n)*2)+4, 2)
+#define L1AP(ap) (AP(3, (ap))) /* in L1, only Sections have AP */
+#define L2AP(ap) (AP(3, (ap))|AP(2, (ap))|AP(1, (ap))|AP(0, (ap))) /* pre-armv7 */
+#define DAC(n, v) F((v), (n)*2, 2)
+
+#define HVECTORS 0xffff0000 /* addr of vectors */
diff --git a/sys/src/9/kw/arm.s b/sys/src/9/kw/arm.s
new file mode 100755
index 000000000..d48ce4a8e
--- /dev/null
+++ b/sys/src/9/kw/arm.s
@@ -0,0 +1,72 @@
+/*
+ * sheevaplug machine assist, definitions
+ * arm926ej-s processor at 1.2GHz
+ *
+ * loader uses R11 as scratch.
+ */
+#include "mem.h"
+#include "arm.h"
+
+#undef B /* B is for 'botch' */
+
+#define PADDR(a) ((a) & ~KZERO)
+#define KADDR(a) (KZERO|(a))
+
+#define L1X(va) (((((va))>>20) & 0x0fff)<<2)
+
+#define MACHADDR (L1-MACHSIZE)
+
+#define PTEDRAM (Dom0|L1AP(Krw)|Section|Cached|Buffered)
+#define PTEIO (Dom0|L1AP(Krw)|Section)
+
+/* wave at the user; clobbers R1 & R7; needs R12 (SB) set */
+#define WAVE(c) \
+ ISB; \
+ MOVW $PHYSCONS, R7; \
+ MOVW $(c), R1; \
+ MOVW R1, (R7); \
+ ISB
+
+/* new instructions */
+#define CLZ(s, d) WORD $(0xe16f0f10 | (d) << 12 | (s)) /* count leading 0s */
+
+#define DMB \
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEdmbarr
+/*
+ * data synchronisation barrier (formerly drain write buffer).
+ * waits for cache flushes, eviction buffer drain, tlb flushes,
+ * branch-prediction flushes, writes to memory; the lot.
+ * on sheeva, also flushes L2 eviction buffer.
+ * zeroes R0.
+ */
+#define DSB \
+ MOVW $0, R0; \
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
+/*
+ * prefetch flush; zeroes R0.
+ * arm926ej-s manual says we need to sync with l2 cache in isb,
+ * and uncached load is the easiest way. doesn't seem to matter.
+ */
+#define ISB \
+ MOVW $0, R0; \
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEwait
+// MOVW (R0), R0; MOVW $0, R0
+
+/* zeroes R0 */
+#define BARRIERS ISB; DSB
+
+/*
+ * invoked with PTE bits in R2, pa in R3, PTE pointed to by R4.
+ * fill PTE pointed to by R4 and increment R4 past it.
+ * increment R3 by a MB. clobbers R1.
+ */
+#define FILLPTE() \
+ ORR R3, R2, R1; /* pte bits in R2, pa in R3 */ \
+ MOVW R1, (R4); \
+ ADD $4, R4; /* bump PTE address */ \
+ ADD $MiB, R3; /* bump pa */ \
+
+/* zero PTE pointed to by R4 and increment R4 past it. assumes R0 is 0. */
+#define ZEROPTE() \
+ MOVW R0, (R4); \
+ ADD $4, R4; /* bump PTE address */
diff --git a/sys/src/9/kw/cga.c b/sys/src/9/kw/cga.c
new file mode 100755
index 000000000..f9cba1904
--- /dev/null
+++ b/sys/src/9/kw/cga.c
@@ -0,0 +1,132 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+enum {
+ Black,
+ Blue,
+ Green,
+ Cyan,
+ Red,
+ Magenta,
+ Brown,
+ Grey,
+
+ Bright = 0x08,
+ Blinking = 0x80,
+
+ Yellow = Bright|Brown,
+ White = Bright|Grey,
+};
+
+enum {
+ Width = 80*2,
+ Height = 25,
+
+ Attr = (Black<<4)|Grey, /* high nibble background
+ * low foreground
+ */
+};
+
+#define CGASCREENBASE ((uchar*)KADDR(0xB8000))
+
+#define inb(x) 0 /* TODO */
+#define outb(x, y) /* TODO */
+
+static int cgapos;
+static Lock cgascreenlock;
+
+static uchar
+cgaregr(int index)
+{
+ USED(index);
+ outb(0x3D4, index);
+ return inb(0x3D4+1) & 0xFF;
+}
+
+static void
+cgaregw(int index, int data)
+{
+ USED(index, data);
+ outb(0x3D4, index);
+ outb(0x3D4+1, data);
+}
+
+static void
+movecursor(void)
+{
+ cgaregw(0x0E, (cgapos/2>>8) & 0xFF);
+ cgaregw(0x0F, cgapos/2 & 0xFF);
+ CGASCREENBASE[cgapos+1] = Attr;
+}
+
+static void
+cgascreenputc(int c)
+{
+ int i;
+ uchar *p;
+
+ if(c == '\n'){
+ cgapos = cgapos/Width;
+ cgapos = (cgapos+1)*Width;
+ }
+ else if(c == '\t'){
+ i = 8 - ((cgapos/2)&7);
+ while(i-->0)
+ cgascreenputc(' ');
+ }
+ else if(c == '\b'){
+ if(cgapos >= 2)
+ cgapos -= 2;
+ cgascreenputc(' ');
+ cgapos -= 2;
+ }
+ else{
+ CGASCREENBASE[cgapos++] = c;
+ CGASCREENBASE[cgapos++] = Attr;
+ }
+ if(cgapos >= Width*Height){
+ memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
+ p = &CGASCREENBASE[Width*(Height-1)];
+ for(i=0; i<Width/2; i++){
+ *p++ = ' ';
+ *p++ = Attr;
+ }
+ cgapos = Width*(Height-1);
+ }
+ movecursor();
+}
+
+static void
+cgascreenputs(char* s, int n)
+{
+ if(!islo()){
+ /*
+ * Don't deadlock trying to
+ * print in an interrupt.
+ */
+ if(!canlock(&cgascreenlock))
+ return;
+ }
+ else
+ lock(&cgascreenlock);
+
+ while(n-- > 0)
+ cgascreenputc(*s++);
+
+ unlock(&cgascreenlock);
+}
+
+void
+screeninit(void)
+{
+
+ cgapos = cgaregr(0x0E)<<8;
+ cgapos |= cgaregr(0x0F);
+ cgapos *= 2;
+
+ screenputs = cgascreenputs;
+}
diff --git a/sys/src/9/kw/clock.c b/sys/src/9/kw/clock.c
new file mode 100755
index 000000000..2f8bc36a1
--- /dev/null
+++ b/sys/src/9/kw/clock.c
@@ -0,0 +1,205 @@
+/*
+ * kirkwood clocks
+ *
+ * timers count down to zero.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ureg.h"
+
+enum {
+ Tcycles = CLOCKFREQ / HZ, /* cycles per clock tick */
+ Dogperiod = 15 * CLOCKFREQ, /* at most 21 s.; must fit in ulong */
+ MaxPeriod = Tcycles,
+ MinPeriod = MaxPeriod / 100,
+
+ /* timer ctl bits */
+ Tmr0enable = 1<<0,
+ Tmr0reload = 1<<1, /* at 0 count, load timer0 from reload0 */
+ Tmr1enable = 1<<2,
+ Tmr1reload = 1<<3, /* at 0 count, load timer1 from reload1 */
+ TmrWDenable = 1<<4,
+ TmrWDreload = 1<<5,
+};
+
+typedef struct TimerReg TimerReg;
+struct TimerReg
+{
+ ulong ctl;
+ ulong pad[3];
+ ulong reload0;
+ ulong timer0; /* cycles until zero */
+ ulong reload1;
+ ulong timer1; /* cycles until zero */
+ ulong reloadwd;
+ ulong timerwd;
+};
+
+static int ticks; /* for sanity checking; m->ticks doesn't always get updated */
+
+static void
+clockintr(Ureg *ureg, void *arg)
+{
+ TimerReg *tmr = arg;
+ static int nesting;
+
+ tmr->timerwd = Dogperiod; /* reassure the watchdog */
+ ticks++;
+ coherence();
+
+ if (nesting == 0) { /* if the clock interrupted itself, bail out */
+ ++nesting;
+ timerintr(ureg, 0);
+ --nesting;
+ }
+
+ intrclear(Irqbridge, IRQcputimer0);
+}
+
+/* stop clock interrupts and disable the watchdog timer */
+void
+clockshutdown(void)
+{
+ TimerReg *tmr = (TimerReg *)soc.clock;
+
+ tmr->ctl = 0;
+ coherence();
+}
+
+void
+clockinit(void)
+{
+ int i, s;
+ CpucsReg *cpu = (CpucsReg *)soc.cpu;
+ TimerReg *tmr = (TimerReg *)soc.clock;
+
+ clockshutdown();
+
+ /*
+ * verify sanity of timer0
+ */
+
+ intrenable(Irqbridge, IRQcputimer0, clockintr, tmr, "clock0");
+ s = spllo(); /* risky */
+ /* take any deferred clock (& other) interrupts here */
+ splx(s);
+
+ /* adjust m->bootdelay, used by delay()? */
+ m->ticks = ticks = 0;
+ m->fastclock = 0;
+
+ tmr->timer0 = 1;
+ tmr->ctl = Tmr0enable; /* just once */
+ coherence();
+
+ s = spllo(); /* risky */
+ for (i = 0; i < 10 && ticks == 0; i++) {
+ delay(1);
+ coherence();
+ }
+ splx(s);
+ if (ticks == 0) {
+ serialputc('?');
+ if (tmr->timer0 == 0)
+ panic("clock not interrupting");
+ else if (tmr->timer0 == tmr->reload0)
+ panic("clock not ticking");
+ else
+ panic("clock running very slowly");
+ }
+
+ /*
+ * configure all timers
+ */
+ clockshutdown();
+ tmr->reload0 = tmr->timer0 = Tcycles; /* tick clock */
+ tmr->reload1 = tmr->timer1 = ~0; /* cycle clock */
+ tmr->timerwd = Dogperiod; /* watch dog timer */
+ coherence();
+ tmr->ctl = Tmr0enable | Tmr0reload | Tmr1enable | Tmr1reload |
+ TmrWDenable;
+ cpu->rstout |= RstoutWatchdog;
+ coherence();
+}
+
+void
+timerset(Tval next)
+{
+ int offset;
+ TimerReg *tmr = (TimerReg *)soc.clock;
+
+ offset = next - fastticks(nil);
+ if(offset < MinPeriod)
+ offset = MinPeriod;
+ else if(offset > MaxPeriod)
+ offset = MaxPeriod;
+ tmr->timer0 = offset;
+ coherence();
+}
+
+uvlong
+fastticks(uvlong *hz)
+{
+ uvlong now;
+ int s;
+
+ if(hz)
+ *hz = CLOCKFREQ;
+ s = splhi();
+ /* zero low ulong of fastclock */
+ now = (m->fastclock & ~(uvlong)~0ul) | perfticks();
+ if(now < m->fastclock) /* low bits must have wrapped */
+ now += 1ll << 32;
+ m->fastclock = now;
+ splx(s);
+ return now;
+}
+
+ulong
+perfticks(void)
+{
+ TimerReg *tmr = (TimerReg *)soc.clock;
+
+ return ~tmr->timer1;
+}
+
+long
+lcycles(void)
+{
+ return perfticks();
+}
+
+ulong
+µs(void)
+{
+ return fastticks2us(fastticks(nil));
+}
+
+void
+microdelay(int l)
+{
+ int i;
+
+ l *= m->delayloop;
+ l /= 1000;
+ if(l <= 0)
+ l = 1;
+ for(i = 0; i < l; i++)
+ ;
+}
+
+void
+delay(int l)
+{
+ ulong i, j;
+
+ j = m->delayloop;
+ while(l-- > 0)
+ for(i=0; i < j; i++)
+ ;
+}
diff --git a/sys/src/9/kw/coproc.c b/sys/src/9/kw/coproc.c
new file mode 100755
index 000000000..6002649f1
--- /dev/null
+++ b/sys/src/9/kw/coproc.c
@@ -0,0 +1,153 @@
+/*
+ * arm co-processors
+ * CP15 (system control) is the one that gets used the most in practice.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "arm.h"
+
+#define MAP2PCSPACE(va, pc) ((uintptr)(va) & ~KSEGM | (pc) & KSEGM)
+
+enum {
+ /* alternates: 0xe12fff1e BX (R14); last e is R14 */
+ /* 0xe28ef000 B 0(R14); second e is R14 (ken) */
+ Retinst = 0xe1a0f00e, /* MOVW R14, R15 */
+
+ Fpproc = 10, /* for vfp 3+; also 11 for doubles */
+};
+
+void
+cpwr(int cp, int op1, int crn, int crm, int op2, ulong val)
+{
+ int s;
+ volatile ulong instr[2];
+ void *pcaddr;
+ void (*fp)(ulong);
+
+ s = splhi();
+ op1 &= 7;
+ op2 &= 7;
+ crn &= 017;
+ crm &= 017;
+ cp &= 017;
+ /* MCR. Rt will be R0. */
+ instr[0] = 0xee000010 |
+ op1 << 21 | crn << 16 | cp << 8 | op2 << 5 | crm;
+ instr[1] = Retinst;
+ coherence();
+
+ pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&cp));
+ cachedwbse(pcaddr, sizeof instr);
+ cacheiinv();
+
+ fp = (void (*)(ulong))pcaddr;
+ (*fp)(val);
+ coherence();
+ splx(s);
+}
+
+void
+cpwrsc(int op1, int crn, int crm, int op2, ulong val)
+{
+ cpwr(CpSC, op1, crn, crm, op2, val);
+}
+
+ulong
+cprd(int cp, int op1, int crn, int crm, int op2)
+{
+ int s;
+ ulong res;
+ volatile ulong instr[2];
+ void *pcaddr;
+ ulong (*fp)(void);
+
+ s = splhi();
+ op1 &= 7;
+ op2 &= 7;
+ crn &= 017;
+ crm &= 017;
+ /*
+ * MRC. return value will be in R0, which is convenient.
+ * Rt will be R0.
+ */
+ instr[0] = 0xee100010 |
+ op1 << 21 | crn << 16 | cp << 8 | op2 << 5 | crm;
+ instr[1] = Retinst;
+ coherence();
+
+ pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&cp));
+ cachedwbse(pcaddr, sizeof instr);
+ cacheiinv();
+
+ fp = (ulong (*)(void))pcaddr;
+ res = (*fp)();
+ splx(s);
+ return res;
+}
+
+ulong
+cprdsc(int op1, int crn, int crm, int op2)
+{
+ return cprd(CpSC, op1, crn, crm, op2);
+}
+
+/* floating point */
+
+ulong
+fprd(int fpreg)
+{
+ int s;
+ ulong res;
+ volatile ulong instr[2];
+ void *pcaddr;
+ ulong (*fp)(void);
+
+ s = splhi();
+ fpreg &= 017;
+ /*
+ * VMRS. return value will be in R0, which is convenient.
+ * Rt will be R0.
+ */
+ instr[0] = 0xeef00010 | fpreg << 16 | 0 << 12 | Fpproc << 8;
+ instr[1] = Retinst;
+ coherence();
+
+ pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&fpreg));
+ cachedwbse(pcaddr, sizeof instr);
+ cacheiinv();
+
+ fp = (ulong (*)(void))pcaddr;
+ res = (*fp)();
+ splx(s);
+ return res;
+}
+
+void
+fpwr(int fpreg, ulong val)
+{
+ int s;
+ volatile ulong instr[2];
+ void *pcaddr;
+ void (*fp)(ulong);
+
+ s = splhi();
+ fpreg &= 017;
+ /* VMSR. Rt will be R0. */
+ instr[0] = 0xeee00010 | fpreg << 16 | 0 << 12 | Fpproc << 8;
+ instr[1] = Retinst;
+ coherence();
+
+ pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&fpreg));
+ cachedwbse(pcaddr, sizeof instr);
+ cacheiinv();
+
+ fp = (void (*)(ulong))pcaddr;
+ (*fp)(val);
+ coherence();
+ splx(s);
+}
diff --git a/sys/src/9/kw/dat.h b/sys/src/9/kw/dat.h
new file mode 100755
index 000000000..88b901cf6
--- /dev/null
+++ b/sys/src/9/kw/dat.h
@@ -0,0 +1,320 @@
+typedef struct Conf Conf;
+typedef struct Confmem Confmem;
+typedef struct FPsave FPsave;
+typedef struct ISAConf ISAConf;
+typedef struct Label Label;
+typedef struct Lock Lock;
+typedef struct Memcache Memcache;
+typedef struct MMMU MMMU;
+typedef struct Mach Mach;
+typedef struct Notsave Notsave;
+typedef struct Page Page;
+typedef struct Pcidev Pcidev;
+typedef struct PhysUart PhysUart;
+typedef struct PMMU PMMU;
+typedef struct Proc Proc;
+typedef u32int PTE;
+typedef struct Soc Soc;
+typedef struct Uart Uart;
+typedef struct Ureg Ureg;
+typedef uvlong Tval;
+
+#pragma incomplete Pcidev
+#pragma incomplete Ureg
+
+#define MAXSYSARG 5 /* for mount(fd, mpt, flag, arg, srv) */
+
+/*
+ * parameters for sysproc.c
+ */
+#define AOUT_MAGIC (E_MAGIC)
+
+struct Lock
+{
+ ulong key;
+ u32int sr;
+ uintptr pc;
+ Proc* p;
+ Mach* m;
+ int isilock;
+};
+
+struct Label
+{
+ uintptr sp;
+ uintptr pc;
+};
+
+/*
+ * emulated floating point
+ */
+struct FPsave
+{
+ ulong status;
+ ulong control;
+ ulong regs[8][3];
+
+ int fpstate;
+};
+
+/*
+ * FPsave.status
+ */
+enum
+{
+ FPinit,
+ FPactive,
+ FPinactive,
+};
+
+struct Confmem
+{
+ uintptr base;
+ usize npage;
+ uintptr limit;
+ uintptr kbase;
+ uintptr klimit;
+};
+
+struct Conf
+{
+ ulong nmach; /* processors */
+ ulong nproc; /* processes */
+ ulong monitor; /* has monitor? */
+ Confmem mem[1]; /* physical memory */
+ ulong npage; /* total physical pages of memory */
+ usize upages; /* user page pool */
+ ulong copymode; /* 0 is copy on write, 1 is copy on reference */
+ ulong ialloc; /* max interrupt time allocation in bytes */
+ ulong pipeqsize; /* size in bytes of pipe queues */
+ ulong nimage; /* number of page cache image headers */
+ ulong nswap; /* number of swap pages */
+ int nswppo; /* max # of pageouts per segment pass */
+// ulong hz; /* processor cycle freq */
+// ulong mhz;
+};
+
+/*
+ * things saved in the Proc structure during a notify
+ */
+struct Notsave {
+ int emptiness;
+};
+
+/*
+ * MMU stuff in Mach.
+ */
+struct MMMU
+{
+ PTE* mmul1; /* l1 for this processor */
+ int mmul1lo;
+ int mmul1hi;
+ int mmupid;
+};
+
+/*
+ * MMU stuff in proc
+ */
+#define NCOLOR 1 /* 1 level cache, don't worry about VCE's */
+struct PMMU
+{
+ Page* mmul2;
+ Page* mmul2cache; /* free mmu pages */
+};
+
+#include "../port/portdat.h"
+
+struct Mach
+{
+ int machno; /* physical id of processor */
+ uintptr splpc; /* pc of last caller to splhi */
+
+ Proc* proc; /* current process */
+
+ MMMU;
+ int flushmmu; /* flush current proc mmu state */
+
+ ulong ticks; /* of the clock since boot time */
+ Label sched; /* scheduler wakeup */
+ Lock alarmlock; /* access to alarm list */
+ void* alarm; /* alarms bound to this clock */
+ int inclockintr;
+
+ Proc* readied; /* for runproc */
+ ulong schedticks; /* next forced context switch */
+
+ int cputype;
+ int socrev; /* system-on-chip revision */
+ ulong delayloop;
+
+ /* stats */
+ int tlbfault;
+ int tlbpurge;
+ int pfault;
+ int cs;
+ int syscall;
+ int load;
+ int intr;
+ vlong fastclock; /* last sampled value */
+ uvlong inidle; /* time spent in idlehands() */
+ ulong spuriousintr;
+ int lastintr;
+ int ilockdepth;
+ Perf perf; /* performance counters */
+
+// int cpumhz;
+ uvlong cpuhz; /* speed of cpu */
+ uvlong cyclefreq; /* Frequency of user readable cycle counter */
+
+ /* save areas for exceptions */
+ u32int sfiq[5];
+ u32int sirq[5];
+ u32int sund[5];
+ u32int sabt[5];
+#define fiqstack sfiq
+#define irqstack sirq
+#define abtstack sabt
+#define undstack sund
+
+ int stack[1];
+};
+
+/*
+ * Fake kmap.
+ */
+typedef void KMap;
+#define VA(k) ((uintptr)(k))
+#define kmap(p) (KMap*)((p)->pa|kseg0)
+#define kunmap(k)
+
+struct
+{
+ Lock;
+ int machs; /* bitmap of active CPUs */
+ int exiting; /* shutdown */
+ int ispanic; /* shutdown in response to a panic */
+}active;
+
+enum {
+ Frequency = 1200*1000*1000, /* the processor clock */
+};
+
+extern register Mach* m; /* R10 */
+extern register Proc* up; /* R9 */
+
+extern uintptr kseg0;
+extern Mach* machaddr[MAXMACH];
+
+enum {
+ Nvec = 8, /* # of vectors at start of lexception.s */
+};
+
+/*
+ * Layout of physical 0.
+ */
+typedef struct Vectorpage {
+ void (*vectors[Nvec])(void);
+ uint vtable[Nvec];
+} Vectorpage;
+
+/*
+ * a parsed plan9.ini line
+ */
+#define NISAOPT 8
+
+struct ISAConf {
+ char *type;
+ ulong port;
+ int irq;
+ ulong dma;
+ ulong mem;
+ ulong size;
+ ulong freq;
+
+ int nopt;
+ char *opt[NISAOPT];
+};
+
+#define MACHP(n) (machaddr[n])
+
+/*
+ * Horrid. But the alternative is 'defined'.
+ */
+#ifdef _DBGC_
+#define DBGFLG (dbgflg[_DBGC_])
+#else
+#define DBGFLG (0)
+#endif /* _DBGC_ */
+
+int vflag;
+extern char dbgflg[256];
+
+#define dbgprint print /* for now */
+
+/*
+ * hardware info about a device
+ */
+typedef struct {
+ ulong port;
+ int size;
+} Devport;
+
+struct DevConf
+{
+ ulong intnum; /* interrupt number */
+ char *type; /* card type, malloced */
+ int nports; /* Number of ports */
+ Devport *ports; /* The ports themselves */
+};
+
+enum {
+ Dcache,
+ Icache,
+ Unified,
+};
+
+/* characteristics of a given cache level */
+struct Memcache {
+ uint level; /* 1 is nearest processor, 2 further away */
+ uint kind; /* I, D or unified */
+
+ uint size;
+ uint nways; /* associativity */
+ uint nsets;
+ uint linelen; /* bytes per cache line */
+ uint setsways;
+
+ uint log2linelen;
+ uint waysh; /* shifts for set/way register */
+ uint setsh;
+};
+
+struct Soc { /* addr's of SoC controllers */
+ uintptr cpu;
+ uintptr devid;
+ uintptr l2cache;
+ uintptr sdramc;
+// uintptr sdramd; /* unused */
+
+ uintptr iocfg;
+ uintptr addrmap;
+ uintptr intr;
+ uintptr nand;
+ uintptr cesa; /* crypto accel. */
+ uintptr ehci;
+ uintptr spi;
+ uintptr twsi;
+
+ uintptr analog;
+ uintptr pci;
+ uintptr pcibase;
+
+ uintptr rtc; /* real-time clock */
+ uintptr clock;
+
+ uintptr ether[2];
+ uintptr sata[3];
+ uintptr uart[2];
+ uintptr gpio[2];
+} soc;
+extern Soc soc;
diff --git a/sys/src/9/kw/devarch.c b/sys/src/9/kw/devarch.c
new file mode 100755
index 000000000..08c76e02c
--- /dev/null
+++ b/sys/src/9/kw/devarch.c
@@ -0,0 +1,265 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+#include "../ip/ip.h"
+
+enum {
+ Qdir = 0,
+ Qbase,
+
+ Qmax = 16,
+};
+
+typedef long Rdwrfn(Chan*, void*, long, vlong);
+
+static Rdwrfn *readfn[Qmax];
+static Rdwrfn *writefn[Qmax];
+
+static Dirtab archdir[Qmax] = {
+ ".", { Qdir, 0, QTDIR }, 0, 0555,
+};
+
+Lock archwlock; /* the lock is only for changing archdir */
+int narchdir = Qbase;
+
+/*
+ * Add a file to the #P listing. Once added, you can't delete it.
+ * You can't add a file with the same name as one already there,
+ * and you get a pointer to the Dirtab entry so you can do things
+ * like change the Qid version. Changing the Qid path is disallowed.
+ */
+Dirtab*
+addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
+{
+ int i;
+ Dirtab d;
+ Dirtab *dp;
+
+ memset(&d, 0, sizeof d);
+ strcpy(d.name, name);
+ d.perm = perm;
+
+ lock(&archwlock);
+ if(narchdir >= Qmax){
+ unlock(&archwlock);
+ return nil;
+ }
+
+ for(i=0; i<narchdir; i++)
+ if(strcmp(archdir[i].name, name) == 0){
+ unlock(&archwlock);
+ return nil;
+ }
+
+ d.qid.path = narchdir;
+ archdir[narchdir] = d;
+ readfn[narchdir] = rdfn;
+ writefn[narchdir] = wrfn;
+ dp = &archdir[narchdir++];
+ unlock(&archwlock);
+
+ return dp;
+}
+
+static Chan*
+archattach(char* spec)
+{
+ return devattach('P', spec);
+}
+
+Walkqid*
+archwalk(Chan* c, Chan *nc, char** name, int nname)
+{
+ return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
+}
+
+static int
+archstat(Chan* c, uchar* dp, int n)
+{
+ return devstat(c, dp, n, archdir, narchdir, devgen);
+}
+
+static Chan*
+archopen(Chan* c, int omode)
+{
+ return devopen(c, omode, archdir, narchdir, devgen);
+}
+
+static void
+archclose(Chan*)
+{
+}
+
+static long
+archread(Chan *c, void *a, long n, vlong offset)
+{
+ Rdwrfn *fn;
+
+ switch((ulong)c->qid.path){
+ case Qdir:
+ return devdirread(c, a, n, archdir, narchdir, devgen);
+
+ default:
+ if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
+ return fn(c, a, n, offset);
+ error(Eperm);
+ break;
+ }
+
+ return 0;
+}
+
+static long
+archwrite(Chan *c, void *a, long n, vlong offset)
+{
+ Rdwrfn *fn;
+
+ if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
+ return fn(c, a, n, offset);
+ error(Eperm);
+
+ return 0;
+}
+
+void archinit(void);
+
+Dev archdevtab = {
+ 'P',
+ "arch",
+
+ devreset,
+ archinit,
+ devshutdown,
+ archattach,
+ archwalk,
+ archstat,
+ archopen,
+ devcreate,
+ archclose,
+ archread,
+ devbread,
+ archwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+/* convert AddrDevid register to a string in buf and return buf */
+char *
+cputype2name(char *buf, int size)
+{
+ ulong id, archid, rev;
+ char *manu, *arch, *socrev;
+ char unk[32], socnm[32], revname[32];
+ Pciex *pci;
+
+ m->cputype = *(ulong *)soc.devid;
+#ifdef OLD
+ switch(m->cputype & 3) {
+ case 0:
+ socnm = "88F6[12]80";
+ break;
+ case 1:
+ socnm = "88F619[02]";
+ break;
+ case 2:
+ socnm = "88F6281";
+ break;
+ default:
+ socnm = "unknown";
+ break;
+ }
+#endif
+ /* strange way to get this information, but it's what u-boot does */
+ pci = (Pciex *)soc.pci;
+ snprint(socnm, sizeof socnm, "88F%ux", pci->devid);
+ /* stash rev for benefit of later usb initialisation */
+ m->socrev = rev = pci->revid & MASK(4);
+
+ id = cpidget();
+ if ((id >> 24) == 0x56 && pci->venid == 0x11ab)
+ manu = "Marvell";
+ else
+ manu = "unknown";
+ archid = (id >> 16) & MASK(4);
+ switch (archid) {
+ case 5:
+ arch = "v5te";
+ break;
+ default:
+ snprint(unk, sizeof unk, "unknown (%ld)", archid);
+ arch = unk;
+ break;
+ }
+ if (pci->devid != 0x6281)
+ socrev = "unknown";
+ else
+ switch (rev) {
+ case Socrevz0:
+ socrev = "Z0";
+ break;
+ case Socreva0:
+ socrev = "A0";
+ break;
+ case Socreva1:
+ socrev = "A1";
+ break;
+ default:
+ snprint(revname, sizeof revname, "unknown rev (%ld)",
+ rev);
+ socrev = revname;
+ break;
+ }
+ seprint(buf, buf + size,
+ "%s %s %s; arm926ej-s arch %s rev %ld.%ld part %lux",
+ manu, socnm, socrev, arch, (id >> 20) & MASK(4),
+ id & MASK(4), (id >> 4) & MASK(12));
+ return buf;
+}
+
+static long
+cputyperead(Chan*, void *a, long n, vlong offset)
+{
+ char name[64], str[128];
+
+ cputype2name(name, sizeof name);
+ snprint(str, sizeof str, "ARM %s %llud\n", name, m->cpuhz / 1000000);
+ return readstr(offset, a, n, str);
+}
+
+static long
+tbread(Chan*, void *a, long n, vlong offset)
+{
+ char str[16];
+ uvlong tb;
+
+ cycles(&tb);
+
+ snprint(str, sizeof(str), "%16.16llux", tb);
+ return readstr(offset, a, n, str);
+}
+
+static long
+nsread(Chan*, void *a, long n, vlong offset)
+{
+ char str[16];
+ uvlong tb;
+
+ cycles(&tb);
+
+ snprint(str, sizeof(str), "%16.16llux", (tb/700)* 1000);
+ return readstr(offset, a, n, str);
+}
+
+void
+archinit(void)
+{
+ addarchfile("cputype", 0444, cputyperead, nil);
+ addarchfile("timebase",0444, tbread, nil);
+// addarchfile("nsec", 0444, nsread, nil);
+}
diff --git a/sys/src/9/kw/devether.c b/sys/src/9/kw/devether.c
new file mode 100755
index 000000000..4d0a51e4c
--- /dev/null
+++ b/sys/src/9/kw/devether.c
@@ -0,0 +1,528 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#include "../port/netif.h"
+#include "etherif.h"
+
+extern int archether(unsigned ctlno, Ether *ether);
+
+static Ether *etherxx[MaxEther];
+
+Chan*
+etherattach(char* spec)
+{
+ int ctlrno;
+ char *p;
+ Chan *chan;
+
+ ctlrno = 0;
+ if(spec && *spec){
+ ctlrno = strtoul(spec, &p, 0);
+ if((ctlrno == 0 && p == spec) || *p != 0)
+ error(Ebadarg);
+ if(ctlrno < 0 || ctlrno >= MaxEther)
+ error(Ebadarg);
+ }
+ if(etherxx[ctlrno] == 0)
+ error(Enodev);
+
+ chan = devattach('l', spec);
+ if(waserror()){
+ chanfree(chan);
+ nexterror();
+ }
+ chan->dev = ctlrno;
+ if(etherxx[ctlrno]->attach)
+ etherxx[ctlrno]->attach(etherxx[ctlrno]);
+ poperror();
+ return chan;
+}
+
+static Walkqid*
+etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
+{
+ return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
+}
+
+static int
+etherstat(Chan* chan, uchar* dp, int n)
+{
+ return netifstat(etherxx[chan->dev], chan, dp, n);
+}
+
+static Chan*
+etheropen(Chan* chan, int omode)
+{
+ return netifopen(etherxx[chan->dev], chan, omode);
+}
+
+static void
+ethercreate(Chan*, char*, int, ulong)
+{
+}
+
+static void
+etherclose(Chan* chan)
+{
+ netifclose(etherxx[chan->dev], chan);
+}
+
+static long
+etherread(Chan* chan, void* buf, long n, vlong off)
+{
+ Ether *ether;
+ ulong offset = off;
+
+ ether = etherxx[chan->dev];
+ if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
+ /*
+ * With some controllers it is necessary to reach
+ * into the chip to extract statistics.
+ */
+ if(NETTYPE(chan->qid.path) == Nifstatqid)
+ return ether->ifstat(ether, buf, n, offset);
+ else if(NETTYPE(chan->qid.path) == Nstatqid)
+ ether->ifstat(ether, buf, 0, offset);
+ }
+
+ return netifread(ether, chan, buf, n, offset);
+}
+
+static Block*
+etherbread(Chan* chan, long n, ulong offset)
+{
+ return netifbread(etherxx[chan->dev], chan, n, offset);
+}
+
+static int
+etherwstat(Chan* chan, uchar* dp, int n)
+{
+ return netifwstat(etherxx[chan->dev], chan, dp, n);
+}
+
+static void
+etherrtrace(Netfile* f, Etherpkt* pkt, int len)
+{
+ int i, n;
+ Block *bp;
+
+ if(qwindow(f->in) <= 0)
+ return;
+ if(len > 58)
+ n = 58;
+ else
+ n = len;
+ bp = iallocb(64);
+ if(bp == nil)
+ return;
+ memmove(bp->wp, pkt->d, n);
+ i = TK2MS(MACHP(0)->ticks);
+ bp->wp[58] = len>>8;
+ bp->wp[59] = len;
+ bp->wp[60] = i>>24;
+ bp->wp[61] = i>>16;
+ bp->wp[62] = i>>8;
+ bp->wp[63] = i;
+ bp->wp += 64;
+ qpass(f->in, bp);
+}
+
+Block*
+etheriq(Ether* ether, Block* bp, int fromwire)
+{
+ Etherpkt *pkt;
+ ushort type;
+ int len, multi, tome, fromme;
+ Netfile **ep, *f, **fp, *fx;
+ Block *xbp;
+
+ ether->inpackets++;
+
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ type = (pkt->type[0]<<8)|pkt->type[1];
+ fx = 0;
+ ep = &ether->f[Ntypes];
+
+ multi = pkt->d[0] & 1;
+ /* check for valid multicast addresses */
+ if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
+ if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
+ if(fromwire){
+ freeb(bp);
+ bp = 0;
+ }
+ return bp;
+ }
+ }
+
+ /* is it for me? */
+ tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
+ fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
+
+ /*
+ * Multiplex the packet to all the connections which want it.
+ * If the packet is not to be used subsequently (fromwire != 0),
+ * attempt to simply pass it into one of the connections, thereby
+ * saving a copy of the data (usual case hopefully).
+ */
+ for(fp = ether->f; fp < ep; fp++){
+ if(f = *fp)
+ if(f->type == type || f->type < 0)
+ if(tome || multi || f->prom){
+ /* Don't want to hear bridged packets */
+ if(f->bridge && !fromwire && !fromme)
+ continue;
+ if(!f->headersonly){
+ if(fromwire && fx == 0)
+ fx = f;
+ else if(xbp = iallocb(len)){
+ memmove(xbp->wp, pkt, len);
+ xbp->wp += len;
+ if(qpass(f->in, xbp) < 0)
+ ether->soverflows++;
+ }
+ else
+ ether->soverflows++;
+ }
+ else
+ etherrtrace(f, pkt, len);
+ }
+ }
+
+ if(fx){
+ if(qpass(fx->in, bp) < 0)
+ ether->soverflows++;
+ return 0;
+ }
+ if(fromwire){
+ freeb(bp);
+ return 0;
+ }
+
+ return bp;
+}
+
+static int
+etheroq(Ether* ether, Block* bp)
+{
+ int len, loopback, s;
+ Etherpkt *pkt;
+
+ ether->outpackets++;
+
+ /*
+ * Check if the packet has to be placed back onto the input queue,
+ * i.e. if it's a loopback or broadcast packet or the interface is
+ * in promiscuous mode.
+ * If it's a loopback packet indicate to etheriq that the data isn't
+ * needed and return, etheriq will pass-on or free the block.
+ * To enable bridging to work, only packets that were originated
+ * by this interface are fed back.
+ */
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
+ if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
+ s = splhi();
+ etheriq(ether, bp, 0);
+ splx(s);
+ }
+
+ if(!loopback){
+ qbwrite(ether->oq, bp);
+ if(ether->transmit != nil)
+ ether->transmit(ether);
+ } else
+ freeb(bp);
+
+ return len;
+}
+
+static long
+etherwrite(Chan* chan, void* buf, long n, vlong)
+{
+ Ether *ether;
+ Block *bp;
+ int nn, onoff;
+ Cmdbuf *cb;
+
+ ether = etherxx[chan->dev];
+ if(NETTYPE(chan->qid.path) != Ndataqid) {
+ nn = netifwrite(ether, chan, buf, n);
+ if(nn >= 0)
+ return nn;
+ cb = parsecmd(buf, n);
+ if(strcmp(cb->f[0], "nonblocking") == 0){
+ if(cb->nf <= 1)
+ onoff = 1;
+ else
+ onoff = atoi(cb->f[1]);
+ qnoblock(ether->oq, onoff);
+ free(cb);
+ return n;
+ }
+ free(cb);
+ if(ether->ctl!=nil)
+ return ether->ctl(ether,buf,n);
+
+ error(Ebadctl);
+ }
+
+ if(n > ether->maxmtu)
+ error(Etoobig);
+ if(n < ether->minmtu)
+ error(Etoosmall);
+
+ bp = allocb(n);
+ if(waserror()){
+ freeb(bp);
+ nexterror();
+ }
+ memmove(bp->rp, buf, n);
+ memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
+ poperror();
+ bp->wp += n;
+
+ return etheroq(ether, bp);
+}
+
+static long
+etherbwrite(Chan* chan, Block* bp, ulong)
+{
+ Ether *ether;
+ long n;
+
+ n = BLEN(bp);
+ if(NETTYPE(chan->qid.path) != Ndataqid){
+ if(waserror()) {
+ freeb(bp);
+ nexterror();
+ }
+ n = etherwrite(chan, bp->rp, n, 0);
+ poperror();
+ freeb(bp);
+ return n;
+ }
+ ether = etherxx[chan->dev];
+
+ if(n > ether->maxmtu){
+ freeb(bp);
+ error(Etoobig);
+ }
+ if(n < ether->minmtu){
+ freeb(bp);
+ error(Etoosmall);
+ }
+
+ return etheroq(ether, bp);
+}
+
+static struct {
+ char* type;
+ int (*reset)(Ether*);
+} cards[MaxEther+1];
+
+void
+addethercard(char* t, int (*r)(Ether*))
+{
+ static int ncard;
+
+ if(ncard == MaxEther)
+ panic("too many ether cards");
+ cards[ncard].type = t;
+ cards[ncard].reset = r;
+ ncard++;
+}
+
+int
+parseether(uchar *to, char *from)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ for(i = 0; i < Eaddrlen; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+static void
+etherreset(void)
+{
+ Ether *ether;
+ int i, n, ctlrno;
+ char name[KNAMELEN], buf[128];
+
+ for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+ if(ether == 0)
+ ether = malloc(sizeof(Ether));
+ memset(ether, 0, sizeof(Ether));
+ ether->ctlrno = ctlrno;
+ ether->mbps = 10;
+ ether->minmtu = ETHERMINTU;
+ ether->maxmtu = ETHERMAXTU;
+
+ if(archether(ctlrno, ether) <= 0)
+ continue;
+
+ for(n = 0; cards[n].type; n++){
+ if(cistrcmp(cards[n].type, ether->type))
+ continue;
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrncmp(ether->opt[i], "ea=", 3) == 0){
+ if(parseether(ether->ea, &ether->opt[i][3]) == -1)
+ memset(ether->ea, 0, Eaddrlen);
+ }else if(cistrcmp(ether->opt[i], "fullduplex") == 0 ||
+ cistrcmp(ether->opt[i], "10BASE-TFD") == 0)
+ ether->fullduplex = 1;
+ else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
+ ether->mbps = 100;
+ }
+ if(cards[n].reset(ether))
+ break;
+ snprint(name, sizeof(name), "ether%d", ctlrno);
+
+ if(ether->interrupt != nil)
+ intrenable(Irqlo, ether->irq, ether->interrupt,
+ ether, name);
+
+ i = snprint(buf, sizeof buf,
+ "#l%d: %s: %dMbps port %#lux irq %d",
+ ctlrno, ether->type, ether->mbps, ether->port,
+ ether->irq);
+ if(ether->mem)
+ i += snprint(buf+i, sizeof buf - i,
+ " addr %#lux", PADDR(ether->mem));
+ if(ether->size)
+ i += snprint(buf+i, sizeof buf - i,
+ " size %#luX", ether->size);
+ i += snprint(buf+i, sizeof buf - i,
+ ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
+ ether->ea[0], ether->ea[1], ether->ea[2],
+ ether->ea[3], ether->ea[4], ether->ea[5]);
+ snprint(buf+i, sizeof buf - i, "\n");
+ print("%s", buf);
+
+ if(ether->mbps >= 1000)
+ netifinit(ether, name, Ntypes, 4*1024*1024);
+ else if(ether->mbps >= 100)
+ netifinit(ether, name, Ntypes, 1024*1024);
+ else
+ netifinit(ether, name, Ntypes, 65*1024);
+ if(ether->oq == 0)
+ ether->oq = qopen(ether->limit, Qmsg, 0, 0);
+ if(ether->oq == 0)
+ panic("etherreset %s", name);
+ ether->alen = Eaddrlen;
+ memmove(ether->addr, ether->ea, Eaddrlen);
+ memset(ether->bcast, 0xFF, Eaddrlen);
+
+ etherxx[ctlrno] = ether;
+ ether = 0;
+ break;
+ }
+ }
+ if(ether)
+ free(ether);
+}
+
+static void
+ethershutdown(void)
+{
+ Ether *ether;
+ int i;
+
+ for(i = 0; i < MaxEther; i++){
+ ether = etherxx[i];
+ if(ether == nil)
+ continue;
+ if(ether->shutdown == nil) {
+ print("#l%d: no shutdown function\n", i);
+ continue;
+ }
+ (*ether->shutdown)(ether);
+ }
+}
+
+#define POLY 0xedb88320
+
+/* really slow 32 bit crc for ethers */
+ulong
+ethercrc(uchar *p, int len)
+{
+ int i, j;
+ ulong crc, b;
+
+ crc = 0xffffffff;
+ for(i = 0; i < len; i++){
+ b = *p++;
+ for(j = 0; j < 8; j++){
+ crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
+ b >>= 1;
+ }
+ }
+ return crc;
+}
+
+void
+dumpoq(Queue *oq)
+{
+ if (oq == nil)
+ print("no outq! ");
+ else if (qisclosed(oq))
+ print("outq closed ");
+ else if (qfull(oq))
+ print("outq full ");
+ else
+ print("outq %d ", qlen(oq));
+}
+
+void
+dumpnetif(Netif *netif)
+{
+ print("netif %s ", netif->name);
+ print("limit %d mbps %d link %d ",
+ netif->limit, netif->mbps, netif->link);
+ print("inpkts %lld outpkts %lld errs %d\n",
+ netif->inpackets, netif->outpackets,
+ netif->crcs + netif->oerrs + netif->frames + netif->overflows +
+ netif->buffs + netif->soverflows);
+}
+
+Dev etherdevtab = {
+ 'l',
+ "ether",
+
+ etherreset,
+ devinit,
+ ethershutdown,
+ etherattach,
+ etherwalk,
+ etherstat,
+ etheropen,
+ ethercreate,
+ etherclose,
+ etherread,
+ etherbread,
+ etherwrite,
+ etherbwrite,
+ devremove,
+ etherwstat,
+};
diff --git a/sys/src/9/kw/devrtc.c b/sys/src/9/kw/devrtc.c
new file mode 100755
index 000000000..a47fc3033
--- /dev/null
+++ b/sys/src/9/kw/devrtc.c
@@ -0,0 +1,359 @@
+/*
+ * devrtc - real-time clock, for kirkwood
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+typedef struct RtcReg RtcReg;
+typedef struct Rtc Rtc;
+
+struct RtcReg
+{
+ ulong time;
+ ulong date;
+ ulong alarmtm;
+ ulong alarmdt;
+ ulong intrmask;
+ ulong intrcause;
+};
+
+struct Rtc
+{
+ int sec;
+ int min;
+ int hour;
+ int wday;
+ int mday;
+ int mon;
+ int year;
+};
+
+enum {
+ Qdir,
+ Qrtc,
+};
+
+static Dirtab rtcdir[] = {
+ ".", {Qdir, 0, QTDIR}, 0, 0555,
+ "rtc", {Qrtc}, NUMSIZE, 0664,
+};
+static RtcReg *rtcreg; /* filled in by attach */
+static Lock rtclock;
+
+#define SEC2MIN 60
+#define SEC2HOUR (60*SEC2MIN)
+#define SEC2DAY (24L*SEC2HOUR)
+
+/*
+ * days per month plus days/year
+ */
+static int dmsize[] =
+{
+ 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+static int ldmsize[] =
+{
+ 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/*
+ * return the days/month for the given year
+ */
+static int *
+yrsize(int yr)
+{
+ if((yr % 4) == 0)
+ return ldmsize;
+ else
+ return dmsize;
+}
+
+/*
+ * compute seconds since Jan 1 1970
+ */
+static ulong
+rtc2sec(Rtc *rtc)
+{
+ ulong secs;
+ int i;
+ int *d2m;
+
+ /*
+ * seconds per year
+ */
+ secs = 0;
+ for(i = 1970; i < rtc->year; i++){
+ d2m = yrsize(i);
+ secs += d2m[0] * SEC2DAY;
+ }
+
+ /*
+ * seconds per month
+ */
+ d2m = yrsize(rtc->year);
+ for(i = 1; i < rtc->mon; i++)
+ secs += d2m[i] * SEC2DAY;
+
+ secs += (rtc->mday-1) * SEC2DAY;
+ secs += rtc->hour * SEC2HOUR;
+ secs += rtc->min * SEC2MIN;
+ secs += rtc->sec;
+
+ return secs;
+}
+
+/*
+ * compute rtc from seconds since Jan 1 1970
+ */
+static void
+sec2rtc(ulong secs, Rtc *rtc)
+{
+ int d;
+ long hms, day;
+ int *d2m;
+
+ /*
+ * break initial number into days
+ */
+ hms = secs % SEC2DAY;
+ day = secs / SEC2DAY;
+ if(hms < 0) {
+ hms += SEC2DAY;
+ day -= 1;
+ }
+
+ /*
+ * 19700101 was thursday
+ */
+ rtc->wday = (day + 7340036L) % 7;
+
+ /*
+ * generate hours:minutes:seconds
+ */
+ rtc->sec = hms % 60;
+ d = hms / 60;
+ rtc->min = d % 60;
+ d /= 60;
+ rtc->hour = d;
+
+ /*
+ * year number
+ */
+ if(day >= 0)
+ for(d = 1970; day >= *yrsize(d); d++)
+ day -= *yrsize(d);
+ else
+ for (d = 1970; day < 0; d--)
+ day += *yrsize(d-1);
+ rtc->year = d;
+
+ /*
+ * generate month
+ */
+ d2m = yrsize(rtc->year);
+ for(d = 1; day >= d2m[d]; d++)
+ day -= d2m[d];
+ rtc->mday = day + 1;
+ rtc->mon = d;
+}
+
+enum {
+ Rtcsec = 0x00007f,
+ Rtcmin = 0x007f00,
+ Rtcms = 8,
+ Rtchr12 = 0x1f0000,
+ Rtchr24 = 0x3f0000,
+ Rtchrs = 16,
+
+ Rdmday = 0x00003f,
+ Rdmon = 0x001f00,
+ Rdms = 8,
+ Rdyear = 0x7f0000,
+ Rdys = 16,
+
+ Rtcpm = 1<<21, /* pm bit */
+ Rtc12 = 1<<22, /* 12 hr clock */
+};
+
+static ulong
+bcd2dec(ulong bcd)
+{
+ ulong d, m, i;
+
+ d = 0;
+ m = 1;
+ for(i = 0; i < 2 * sizeof d; i++){
+ d += ((bcd >> (4*i)) & 0xf) * m;
+ m *= 10;
+ }
+ return d;
+}
+
+static ulong
+dec2bcd(ulong d)
+{
+ ulong bcd, i;
+
+ bcd = 0;
+ for(i = 0; d != 0; i++){
+ bcd |= (d%10) << (4*i);
+ d /= 10;
+ }
+ return bcd;
+}
+
+static long
+_rtctime(void)
+{
+ ulong t, d;
+ Rtc rtc;
+
+ t = rtcreg->time;
+ d = rtcreg->date;
+
+ rtc.sec = bcd2dec(t & Rtcsec);
+ rtc.min = bcd2dec((t & Rtcmin) >> Rtcms);
+
+ if(t & Rtc12){
+ rtc.hour = bcd2dec((t & Rtchr12) >> Rtchrs) - 1; /* 1—12 */
+ if(t & Rtcpm)
+ rtc.hour += 12;
+ }else
+ rtc.hour = bcd2dec((t & Rtchr24) >> Rtchrs); /* 0—23 */
+
+ rtc.mday = bcd2dec(d & Rdmday); /* 1—31 */
+ rtc.mon = bcd2dec((d & Rdmon) >> Rdms); /* 1—12 */
+ rtc.year = bcd2dec((d & Rdyear) >> Rdys) + 2000; /* year%100 */
+
+// print("%0.2d:%0.2d:%.02d %0.2d/%0.2d/%0.2d\n", /* HH:MM:SS YY/MM/DD */
+// rtc.hour, rtc.min, rtc.sec, rtc.year, rtc.mon, rtc.mday);
+ return rtc2sec(&rtc);
+}
+
+long
+rtctime(void)
+{
+ int i;
+ long t, ot;
+
+ ilock(&rtclock);
+
+ /* loop until we get two reads in a row the same */
+ t = _rtctime();
+ ot = ~t;
+ for(i = 0; i < 100 && ot != t; i++){
+ ot = t;
+ t = _rtctime();
+ }
+ if(ot != t)
+ print("rtctime: we are boofheads\n");
+
+ iunlock(&rtclock);
+ return t;
+}
+
+static void
+setrtc(Rtc *rtc)
+{
+ ilock(&rtclock);
+ rtcreg->time = dec2bcd(rtc->wday) << 24 | dec2bcd(rtc->hour) << 16 |
+ dec2bcd(rtc->min) << 8 | dec2bcd(rtc->sec);
+ rtcreg->date = dec2bcd(rtc->year - 2000) << 16 |
+ dec2bcd(rtc->mon) << 8 | dec2bcd(rtc->mday);
+ iunlock(&rtclock);
+}
+
+static Chan*
+rtcattach(char *spec)
+{
+ rtcreg = (RtcReg*)soc.rtc;
+ return devattach(L'r', spec);
+}
+
+static Walkqid*
+rtcwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, rtcdir, nelem(rtcdir), devgen);
+}
+
+static int
+rtcstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, rtcdir, nelem(rtcdir), devgen);
+}
+
+static Chan*
+rtcopen(Chan *c, int omode)
+{
+ return devopen(c, omode, rtcdir, nelem(rtcdir), devgen);
+}
+
+static void
+rtcclose(Chan*)
+{
+}
+
+static long
+rtcread(Chan *c, void *buf, long n, vlong off)
+{
+ if(c->qid.type & QTDIR)
+ return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen);
+
+ switch((ulong)c->qid.path){
+ default:
+ error(Egreg);
+ case Qrtc:
+ return readnum(off, buf, n, rtctime(), NUMSIZE);
+ }
+}
+
+static long
+rtcwrite(Chan *c, void *buf, long n, vlong off)
+{
+ ulong offset = off;
+ char *cp, sbuf[32];
+ Rtc rtc;
+
+ switch((ulong)c->qid.path){
+ default:
+ error(Egreg);
+ case Qrtc:
+ if(offset != 0 || n >= sizeof(sbuf)-1)
+ error(Ebadarg);
+ memmove(sbuf, buf, n);
+ sbuf[n] = '\0';
+ for(cp = sbuf; *cp != '\0'; cp++)
+ if(*cp >= '0' && *cp <= '9')
+ break;
+ sec2rtc(strtoul(cp, 0, 0), &rtc);
+ setrtc(&rtc);
+ return n;
+ }
+}
+
+Dev rtcdevtab = {
+ L'r',
+ "rtc",
+
+ devreset,
+ devinit,
+ devshutdown,
+ rtcattach,
+ rtcwalk,
+ rtcstat,
+ rtcopen,
+ devcreate,
+ rtcclose,
+ rtcread,
+ devbread,
+ rtcwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+ devpower,
+};
diff --git a/sys/src/9/kw/devtwsi.c b/sys/src/9/kw/devtwsi.c
new file mode 100755
index 000000000..ec4a268c9
--- /dev/null
+++ b/sys/src/9/kw/devtwsi.c
@@ -0,0 +1,305 @@
+/*
+ * kirkwood two-wire serial interface (TWSI) and
+ * inter-integrated circuit (I⁲C) driver
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+enum {
+ Qdir,
+ Qtwsi,
+};
+
+typedef struct Kwtwsi Kwtwsi;
+typedef struct Twsi Twsi;
+
+struct Kwtwsi { /* device registers */
+ ulong saddr;
+ ulong data;
+ ulong ctl;
+ union {
+ ulong status; /* ro */
+ ulong rate; /* wo: baud rate */
+ };
+
+ ulong saddrext;
+ uchar _pad0[0x1c-0x14];
+ ulong reset;
+ uchar _pad1[0x98-0x20];
+ ulong initlastdata;
+};
+
+enum {
+ Twsidowrite,
+ Twsidoread,
+
+ /* ctl bits */
+ Twsiack = 1<<2, /* recv'd data; clear to ack */
+ Twsiint = 1<<3, /* interrupt conditions true */
+ Twsistop = 1<<4,
+ Twsistart = 1<<5,
+ Twsislaveen = 1<<6,
+ Twsiinten = 1<<7, /* interrupts enabled */
+
+ /* status codes */
+ SStart = 0x08,
+ SWa = 0x18,
+ SWda = 0x28,
+ SRa = 0x40,
+ SRda = 0x50,
+ SRna = 0x58,
+};
+
+struct Twsi {
+ QLock;
+ Rendez nextbyte;
+
+ /* remainder is state needed to track the operation in progress */
+ int intr;
+ int done;
+
+ uchar *bp; /* current ptr into buf */
+ uchar *end;
+
+ ulong addr; /* device address */
+ char *error;
+};
+
+static Twsi twsi;
+
+static Dirtab twsidir[] = {
+ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
+ "twsi", {Qtwsi}, 0, 0660,
+};
+
+static char Eabsts[] = "abnormal status";
+
+static void
+twsifinish(void)
+{
+ Kwtwsi *krp = (Kwtwsi *)soc.twsi;
+
+ twsi.done = 1;
+ krp->ctl |= Twsistop;
+ coherence();
+}
+
+static void
+twsidoread(void)
+{
+ Kwtwsi *krp = (Kwtwsi *)soc.twsi;
+
+ switch(krp->status){
+ case SStart:
+ krp->data = twsi.addr << 1 | Twsidoread;
+ break;
+ case SRa:
+ krp->ctl |= Twsiack;
+ break;
+ case SRda:
+ if(twsi.bp < twsi.end) {
+ *twsi.bp++ = krp->data;
+ krp->ctl |= Twsiack;
+ } else
+ krp->ctl &= ~Twsiack;
+ break;
+ case SRna:
+ twsifinish();
+ break;
+ default:
+ twsifinish();
+ twsi.error = Eabsts;
+ break;
+ }
+}
+
+static void
+twsidowrite(void)
+{
+ Kwtwsi *krp = (Kwtwsi *)soc.twsi;
+
+ switch(krp->status){
+ case SStart:
+ krp->data = twsi.addr << 1 | Twsidowrite;
+ break;
+ case SWa:
+ case SWda:
+ if(twsi.bp < twsi.end)
+ krp->data = *twsi.bp++;
+ else
+ twsifinish();
+ break;
+ default:
+ twsifinish();
+ twsi.error = Eabsts;
+ break;
+ }
+}
+
+static int
+twsigotintr(void *)
+{
+ return twsi.intr;
+}
+
+static long
+twsixfer(uchar *buf, ulong len, ulong offset, void (*op)(void))
+{
+ ulong off;
+ char *err;
+ Kwtwsi *krp = (Kwtwsi *)soc.twsi;
+
+ qlock(&twsi);
+ twsi.bp = buf;
+ twsi.end = buf + len;
+
+ twsi.addr = offset;
+ twsi.done = twsi.intr = 0;
+ twsi.error = nil;
+
+ krp->ctl = (krp->ctl & ~Twsiint) | Twsistart;
+ coherence();
+ while (!twsi.done) {
+ sleep(&twsi.nextbyte, twsigotintr, 0);
+ twsi.intr = 0;
+ (*op)();
+ /* signal to start new op & extinguish intr source */
+ krp->ctl &= ~Twsiint;
+ coherence();
+ krp->ctl |= Twsiinten;
+ coherence();
+ }
+ twsifinish();
+ err = twsi.error;
+ off = twsi.bp - buf;
+ twsi.bp = nil; /* prevent accidents */
+ qunlock(&twsi);
+
+ if(err)
+ error(err);
+ return off;
+}
+
+static void
+interrupt(Ureg *, void *)
+{
+ Kwtwsi *krp = (Kwtwsi *)soc.twsi;
+
+ twsi.intr = 1;
+ wakeup(&twsi.nextbyte);
+
+ krp->ctl &= ~Twsiinten; /* stop further interrupts */
+ coherence();
+ intrclear(Irqlo, IRQ0twsi);
+}
+
+static void
+twsiinit(void)
+{
+ Kwtwsi *krp = (Kwtwsi *)soc.twsi;
+
+ intrenable(Irqlo, IRQ0twsi, interrupt, nil, "twsi");
+ krp->ctl &= ~Twsiint;
+ krp->ctl |= Twsiinten;
+ coherence();
+}
+
+static void
+twsishutdown(void)
+{
+ Kwtwsi *krp = (Kwtwsi *)soc.twsi;
+
+ krp->ctl &= ~Twsiinten;
+ coherence();
+ intrdisable(Irqlo, IRQ0twsi, interrupt, nil, "twsi");
+}
+
+static Chan*
+twsiattach(char *param)
+{
+ return devattach(L'⁲', param);
+}
+
+static Walkqid*
+twsiwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, twsidir, nelem(twsidir), devgen);
+}
+
+static int
+twsistat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, twsidir, nelem(twsidir), devgen);
+}
+
+static Chan*
+twsiopen(Chan *c, int omode)
+{
+ switch((ulong)c->qid.path){
+ default:
+ error(Eperm);
+ case Qdir:
+ case Qtwsi:
+ break;
+ }
+ c = devopen(c, omode, twsidir, nelem(twsidir), devgen);
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+static void
+twsiclose(Chan *)
+{
+}
+
+static long
+twsiread(Chan *c, void *v, long n, vlong off)
+{
+ switch((ulong)c->qid.path){
+ default:
+ error(Eperm);
+ case Qdir:
+ return devdirread(c, v, n, twsidir, nelem(twsidir), devgen);
+ case Qtwsi:
+ return twsixfer(v, n, off, twsidoread);
+ }
+}
+
+static long
+twsiwrite(Chan *c, void *v, long n, vlong off)
+{
+ switch((ulong)c->qid.path){
+ default:
+ error(Eperm);
+ case Qtwsi:
+ return twsixfer(v, n, off, twsidowrite);
+ }
+}
+
+Dev twsidevtab = {
+ L'⁲',
+ "twsi",
+
+ devreset,
+ twsiinit,
+ twsishutdown,
+ twsiattach,
+ twsiwalk,
+ twsistat,
+ twsiopen,
+ devcreate,
+ twsiclose,
+ twsiread,
+ devbread,
+ twsiwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/kw/devusb.c b/sys/src/9/kw/devusb.c
new file mode 100755
index 000000000..de5826165
--- /dev/null
+++ b/sys/src/9/kw/devusb.c
@@ -0,0 +1,1460 @@
+/*
+ * USB device driver framework.
+ *
+ * This is in charge of providing access to actual HCIs
+ * and providing I/O to the various endpoints of devices.
+ * A separate user program (usbd) is in charge of
+ * enumerating the bus, setting up endpoints and
+ * starting devices (also user programs).
+ *
+ * The interface provided is a violation of the standard:
+ * you're welcome.
+ *
+ * The interface consists of a root directory with several files
+ * plus a directory (epN.M) with two files per endpoint.
+ * A device is represented by its first endpoint, which
+ * is a control endpoint automatically allocated for each device.
+ * Device control endpoints may be used to create new endpoints.
+ * Devices corresponding to hubs may also allocate new devices,
+ * perhaps also hubs. Initially, a hub device is allocated for
+ * each controller present, to represent its root hub. Those can
+ * never be removed.
+ *
+ * All endpoints refer to the first endpoint (epN.0) of the device,
+ * which keeps per-device information, and also to the HCI used
+ * to reach them. Although all endpoints cache that information.
+ *
+ * epN.M/data files permit I/O and are considered DMEXCL.
+ * epN.M/ctl files provide status info and accept control requests.
+ *
+ * Endpoints may be given file names to be listed also at #u,
+ * for those drivers that have nothing to do after configuring the
+ * device and its endpoints.
+ *
+ * Drivers for different controllers are kept at usb[oue]hci.c
+ * It's likely we could factor out much from controllers into
+ * a generic controller driver, the problem is that details
+ * regarding how to handle toggles, tokens, Tds, etc. will
+ * get in the way. Thus, code is probably easier the way it is.
+ */
+
+#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/usb.h"
+
+typedef struct Hcitype Hcitype;
+
+enum
+{
+ /* Qid numbers */
+ Qdir = 0, /* #u */
+ Qusbdir, /* #u/usb */
+ Qctl, /* #u/usb/ctl - control requests */
+
+ Qep0dir, /* #u/usb/ep0.0 - endpoint 0 dir */
+ Qep0io, /* #u/usb/ep0.0/data - endpoint 0 I/O */
+ Qep0ctl, /* #u/usb/ep0.0/ctl - endpoint 0 ctl. */
+ Qep0dummy, /* give 4 qids to each endpoint */
+
+ Qepdir = 0, /* (qid-qep0dir)&3 is one of these */
+ Qepio, /* to identify which file for the endpoint */
+ Qepctl,
+
+ /* ... */
+
+ /* Usb ctls. */
+ CMdebug = 0, /* debug on|off */
+ CMdump, /* dump (data structures for debug) */
+
+ /* Ep. ctls */
+ CMnew = 0, /* new nb ctl|bulk|intr|iso r|w|rw (endpoint) */
+ CMnewdev, /* newdev full|low|high portnb (allocate new devices) */
+ CMhub, /* hub (set the device as a hub) */
+ CMspeed, /* speed full|low|high|no */
+ CMmaxpkt, /* maxpkt size */
+ CMntds, /* ntds nb (max nb. of tds per µframe) */
+ CMclrhalt, /* clrhalt (halt was cleared on endpoint) */
+ CMpollival, /* pollival interval (interrupt/iso) */
+ CMhz, /* hz n (samples/sec; iso) */
+ CMsamplesz, /* samplesz n (sample size; iso) */
+ CMinfo, /* info infostr (ke.ep info for humans) */
+ CMdetach, /* detach (abort I/O forever on this ep). */
+ CMaddress, /* address (address is assigned) */
+ CMdebugep, /* debug n (set/clear debug for this ep) */
+ CMname, /* name str (show up as #u/name as well) */
+ CMtmout, /* timeout n (activate timeouts for ep) */
+ CMpreset, /* reset the port */
+
+ /* Hub feature selectors */
+ Rportenable = 1,
+ Rportreset = 4,
+
+};
+
+struct Hcitype
+{
+ char* type;
+ int (*reset)(Hci*);
+};
+
+#define QID(q) ((int)(q).path)
+
+static char Edetach[] = "device is detached";
+static char Enotconf[] = "endpoint not configured";
+char Estalled[] = "endpoint stalled";
+
+static Cmdtab usbctls[] =
+{
+ {CMdebug, "debug", 2},
+ {CMdump, "dump", 1},
+};
+
+static Cmdtab epctls[] =
+{
+ {CMnew, "new", 4},
+ {CMnewdev, "newdev", 3},
+ {CMhub, "hub", 1},
+ {CMspeed, "speed", 2},
+ {CMmaxpkt, "maxpkt", 2},
+ {CMntds, "ntds", 2},
+ {CMpollival, "pollival", 2},
+ {CMsamplesz, "samplesz", 2},
+ {CMhz, "hz", 2},
+ {CMinfo, "info", 0},
+ {CMdetach, "detach", 1},
+ {CMaddress, "address", 1},
+ {CMdebugep, "debug", 2},
+ {CMclrhalt, "clrhalt", 1},
+ {CMname, "name", 2},
+ {CMtmout, "timeout", 2},
+ {CMpreset, "reset", 1},
+};
+
+static Dirtab usbdir[] =
+{
+ "ctl", {Qctl}, 0, 0666,
+};
+
+char *usbmodename[] =
+{
+ [OREAD] "r",
+ [OWRITE] "w",
+ [ORDWR] "rw",
+};
+
+static char *ttname[] =
+{
+ [Tnone] "none",
+ [Tctl] "control",
+ [Tiso] "iso",
+ [Tintr] "interrupt",
+ [Tbulk] "bulk",
+};
+
+static char *spname[] =
+{
+ [Fullspeed] "full",
+ [Lowspeed] "low",
+ [Highspeed] "high",
+ [Nospeed] "no",
+};
+
+static int debug;
+static Hcitype hcitypes[Nhcis];
+static Hci* hcis[Nhcis];
+static QLock epslck; /* add, del, lookup endpoints */
+static Ep* eps[Neps]; /* all endpoints known */
+static int epmax; /* 1 + last endpoint index used */
+static int usbidgen; /* device address generator */
+
+/*
+ * Is there something like this in a library? should it be?
+ */
+char*
+seprintdata(char *s, char *se, uchar *d, int n)
+{
+ int i, l;
+
+ s = seprint(s, se, " %#p[%d]: ", d, n);
+ l = n;
+ if(l > 10)
+ l = 10;
+ for(i=0; i<l; i++)
+ s = seprint(s, se, " %2.2ux", d[i]);
+ if(l < n)
+ s = seprint(s, se, "...");
+ return s;
+}
+
+static int
+name2speed(char *name)
+{
+ int i;
+
+ for(i = 0; i < nelem(spname); i++)
+ if(strcmp(name, spname[i]) == 0)
+ return i;
+ return Nospeed;
+}
+
+static int
+name2ttype(char *name)
+{
+ int i;
+
+ for(i = 0; i < nelem(ttname); i++)
+ if(strcmp(name, ttname[i]) == 0)
+ return i;
+ /* may be a std. USB ep. type */
+ i = strtol(name, nil, 0);
+ switch(i+1){
+ case Tctl:
+ case Tiso:
+ case Tbulk:
+ case Tintr:
+ return i+1;
+ default:
+ return Tnone;
+ }
+}
+
+static int
+name2mode(char *mode)
+{
+ int i;
+
+ for(i = 0; i < nelem(usbmodename); i++)
+ if(strcmp(mode, usbmodename[i]) == 0)
+ return i;
+ return -1;
+}
+
+static int
+qid2epidx(int q)
+{
+ q = (q-Qep0dir)/4;
+ if(q < 0 || q >= epmax || eps[q] == nil)
+ return -1;
+ return q;
+}
+
+static int
+isqtype(int q, int type)
+{
+ if(q < Qep0dir)
+ return 0;
+ q -= Qep0dir;
+ return (q & 3) == type;
+}
+
+void
+addhcitype(char* t, int (*r)(Hci*))
+{
+ static int ntype;
+
+ if(ntype == Nhcis)
+ panic("too many USB host interface types");
+ hcitypes[ntype].type = t;
+ hcitypes[ntype].reset = r;
+ ntype++;
+}
+
+static char*
+seprintep(char *s, char *se, Ep *ep, int all)
+{
+ static char* dsnames[] = { "config", "enabled", "detached", "reset" };
+ Udev *d;
+ int i;
+ int di;
+
+ d = ep->dev;
+
+ qlock(ep);
+ if(waserror()){
+ qunlock(ep);
+ nexterror();
+ }
+ di = ep->dev->nb;
+ if(all)
+ s = seprint(s, se, "dev %d ep %d ", di, ep->nb);
+ s = seprint(s, se, "%s", dsnames[ep->dev->state]);
+ s = seprint(s, se, " %s", ttname[ep->ttype]);
+ assert(ep->mode == OREAD || ep->mode == OWRITE || ep->mode == ORDWR);
+ s = seprint(s, se, " %s", usbmodename[ep->mode]);
+ s = seprint(s, se, " speed %s", spname[d->speed]);
+ s = seprint(s, se, " maxpkt %ld", ep->maxpkt);
+ s = seprint(s, se, " pollival %ld", ep->pollival);
+ s = seprint(s, se, " samplesz %ld", ep->samplesz);
+ s = seprint(s, se, " hz %ld", ep->hz);
+ s = seprint(s, se, " hub %d", ep->dev->hub);
+ s = seprint(s, se, " port %d", ep->dev->port);
+ if(ep->inuse)
+ s = seprint(s, se, " busy");
+ else
+ s = seprint(s, se, " idle");
+ if(all){
+ s = seprint(s, se, " load %uld", ep->load);
+ s = seprint(s, se, " ref %ld addr %#p", ep->ref, ep);
+ s = seprint(s, se, " idx %d", ep->idx);
+ if(ep->name != nil)
+ s = seprint(s, se, " name '%s'", ep->name);
+ if(ep->tmout != 0)
+ s = seprint(s, se, " tmout");
+ if(ep == ep->ep0){
+ s = seprint(s, se, " ctlrno %#x", ep->hp->ctlrno);
+ s = seprint(s, se, " eps:");
+ for(i = 0; i < nelem(d->eps); i++)
+ if(d->eps[i] != nil)
+ s = seprint(s, se, " ep%d.%d", di, i);
+ }
+ }
+ if(ep->info != nil)
+ s = seprint(s, se, "\n%s %s\n", ep->info, ep->hp->type);
+ else
+ s = seprint(s, se, "\n");
+ qunlock(ep);
+ poperror();
+ return s;
+}
+
+static Ep*
+epalloc(Hci *hp)
+{
+ Ep *ep;
+ int i;
+
+ ep = smalloc(sizeof(Ep));
+ ep->ref = 1;
+ qlock(&epslck);
+ for(i = 0; i < Neps; i++)
+ if(eps[i] == nil)
+ break;
+ if(i == Neps){
+ qunlock(&epslck);
+ free(ep);
+ print("usb: bug: too few endpoints.\n");
+ return nil;
+ }
+ ep->idx = i;
+ if(epmax <= i)
+ epmax = i+1;
+ eps[i] = ep;
+ ep->hp = hp;
+ ep->maxpkt = 8;
+ ep->ntds = 1;
+ ep->samplesz = ep->pollival = ep->hz = 0; /* make them void */
+ qunlock(&epslck);
+ return ep;
+}
+
+static Ep*
+getep(int i)
+{
+ Ep *ep;
+
+ if(i < 0 || i >= epmax || eps[i] == nil)
+ return nil;
+ qlock(&epslck);
+ ep = eps[i];
+ if(ep != nil)
+ incref(ep);
+ qunlock(&epslck);
+ return ep;
+}
+
+static void
+putep(Ep *ep)
+{
+ Udev *d;
+
+ if(ep != nil && decref(ep) == 0){
+ d = ep->dev;
+ deprint("usb: ep%d.%d %#p released\n", d->nb, ep->nb, ep);
+ qlock(&epslck);
+ eps[ep->idx] = nil;
+ if(ep->idx == epmax-1)
+ epmax--;
+ if(ep == ep->ep0 && ep->dev != nil && ep->dev->nb == usbidgen)
+ usbidgen--;
+ qunlock(&epslck);
+ if(d != nil){
+ qlock(ep->ep0);
+ d->eps[ep->nb] = nil;
+ qunlock(ep->ep0);
+ }
+ if(ep->ep0 != ep){
+ putep(ep->ep0);
+ ep->ep0 = nil;
+ }
+ free(ep->info);
+ free(ep->name);
+ free(ep);
+ }
+}
+
+static void
+dumpeps(void)
+{
+ int i;
+ static char buf[512];
+ char *s;
+ char *e;
+ Ep *ep;
+
+ print("usb dump eps: epmax %d Neps %d (ref=1+ for dump):\n", epmax, Neps);
+ for(i = 0; i < epmax; i++){
+ s = buf;
+ e = buf+sizeof(buf);
+ ep = getep(i);
+ if(ep != nil){
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ s = seprint(s, e, "ep%d.%d ", ep->dev->nb, ep->nb);
+ seprintep(s, e, ep, 1);
+ print("%s", buf);
+ ep->hp->seprintep(buf, e, ep);
+ print("%s", buf);
+ poperror();
+ putep(ep);
+ }
+ }
+ print("usb dump hcis:\n");
+ for(i = 0; i < Nhcis; i++)
+ if(hcis[i] != nil)
+ hcis[i]->dump(hcis[i]);
+}
+
+static int
+newusbid(Hci *)
+{
+ int id;
+
+ qlock(&epslck);
+ id = ++usbidgen;
+ if(id >= 0x7F)
+ print("#u: too many device addresses; reuse them more\n");
+ qunlock(&epslck);
+ return id;
+}
+
+/*
+ * Create endpoint 0 for a new device
+ */
+static Ep*
+newdev(Hci *hp, int ishub, int isroot)
+{
+ Ep *ep;
+ Udev *d;
+
+ ep = epalloc(hp);
+ d = ep->dev = smalloc(sizeof(Udev));
+ d->nb = newusbid(hp);
+ d->eps[0] = ep;
+ ep->nb = 0;
+ ep->toggle[0] = ep->toggle[1] = 0;
+ d->ishub = ishub;
+ d->isroot = isroot;
+ if(hp->highspeed != 0)
+ d->speed = Highspeed;
+ else
+ d->speed = Fullspeed;
+ d->state = Dconfig; /* address not yet set */
+ ep->dev = d;
+ ep->ep0 = ep; /* no ref counted here */
+ ep->ttype = Tctl;
+ ep->tmout = Xfertmout;
+ ep->mode = ORDWR;
+ dprint("newdev %#p ep%d.%d %#p\n", d, d->nb, ep->nb, ep);
+ return ep;
+}
+
+/*
+ * Create a new endpoint for the device
+ * accessed via the given endpoint 0.
+ */
+static Ep*
+newdevep(Ep *ep, int i, int tt, int mode)
+{
+ Ep *nep;
+ Udev *d;
+
+ d = ep->dev;
+ if(d->eps[i] != nil)
+ error("endpoint already in use");
+ nep = epalloc(ep->hp);
+ incref(ep);
+ d->eps[i] = nep;
+ nep->nb = i;
+ nep->toggle[0] = nep->toggle[1] = 0;
+ nep->ep0 = ep;
+ nep->dev = ep->dev;
+ nep->mode = mode;
+ nep->ttype = tt;
+ nep->debug = ep->debug;
+ /* set defaults */
+ switch(tt){
+ case Tctl:
+ nep->tmout = Xfertmout;
+ break;
+ case Tintr:
+ nep->pollival = 10;
+ break;
+ case Tiso:
+ nep->tmout = Xfertmout;
+ nep->pollival = 10;
+ nep->samplesz = 4;
+ nep->hz = 44100;
+ break;
+ }
+ deprint("newdevep ep%d.%d %#p\n", d->nb, nep->nb, nep);
+ return ep;
+}
+
+static int
+epdataperm(int mode)
+{
+
+ switch(mode){
+ case OREAD:
+ return 0440|DMEXCL;
+ break;
+ case OWRITE:
+ return 0220|DMEXCL;
+ break;
+ default:
+ return 0660|DMEXCL;
+ }
+}
+
+static int
+usbgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
+{
+ Qid q;
+ Dirtab *dir;
+ int perm;
+ char *se;
+ Ep *ep;
+ int nb;
+ int mode;
+
+ if(0)ddprint("usbgen q %#x s %d...", QID(c->qid), s);
+ if(s == DEVDOTDOT){
+ if(QID(c->qid) <= Qusbdir){
+ mkqid(&q, Qdir, 0, QTDIR);
+ devdir(c, q, "#u", 0, eve, 0555, dp);
+ }else{
+ mkqid(&q, Qusbdir, 0, QTDIR);
+ devdir(c, q, "usb", 0, eve, 0555, dp);
+ }
+ if(0)ddprint("ok\n");
+ return 1;
+ }
+
+ switch(QID(c->qid)){
+ case Qdir: /* list #u */
+ if(s == 0){
+ mkqid(&q, Qusbdir, 0, QTDIR);
+ devdir(c, q, "usb", 0, eve, 0555, dp);
+ if(0)ddprint("ok\n");
+ return 1;
+ }
+ s--;
+ if(s < 0 || s >= epmax)
+ goto Fail;
+ ep = getep(s);
+ if(ep == nil || ep->name == nil){
+ if(ep != nil)
+ putep(ep);
+ if(0)ddprint("skip\n");
+ return 0;
+ }
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ mkqid(&q, Qep0io+s*4, 0, QTFILE);
+ devdir(c, q, ep->name, 0, eve, epdataperm(ep->mode), dp);
+ putep(ep);
+ poperror();
+ if(0)ddprint("ok\n");
+ return 1;
+
+ case Qusbdir: /* list #u/usb */
+ Usbdir:
+ if(s < nelem(usbdir)){
+ dir = &usbdir[s];
+ mkqid(&q, dir->qid.path, 0, QTFILE);
+ devdir(c, q, dir->name, dir->length, eve, dir->perm, dp);
+ if(0)ddprint("ok\n");
+ return 1;
+ }
+ s -= nelem(usbdir);
+ if(s < 0 || s >= epmax)
+ goto Fail;
+ ep = getep(s);
+ if(ep == nil){
+ if(0)ddprint("skip\n");
+ return 0;
+ }
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ se = up->genbuf+sizeof(up->genbuf);
+ seprint(up->genbuf, se, "ep%d.%d", ep->dev->nb, ep->nb);
+ mkqid(&q, Qep0dir+4*s, 0, QTDIR);
+ putep(ep);
+ poperror();
+ devdir(c, q, up->genbuf, 0, eve, 0755, dp);
+ if(0)ddprint("ok\n");
+ return 1;
+
+ case Qctl:
+ s = 0;
+ goto Usbdir;
+
+ default: /* list #u/usb/epN.M */
+ nb = qid2epidx(QID(c->qid));
+ ep = getep(nb);
+ if(ep == nil)
+ goto Fail;
+ mode = ep->mode;
+ putep(ep);
+ if(isqtype(QID(c->qid), Qepdir)){
+ Epdir:
+ switch(s){
+ case 0:
+ mkqid(&q, Qep0io+nb*4, 0, QTFILE);
+ perm = epdataperm(mode);
+ devdir(c, q, "data", 0, eve, perm, dp);
+ break;
+ case 1:
+ mkqid(&q, Qep0ctl+nb*4, 0, QTFILE);
+ devdir(c, q, "ctl", 0, eve, 0664, dp);
+ break;
+ default:
+ goto Fail;
+ }
+ }else if(isqtype(QID(c->qid), Qepctl)){
+ s = 1;
+ goto Epdir;
+ }else{
+ s = 0;
+ goto Epdir;
+ }
+ if(0)ddprint("ok\n");
+ return 1;
+ }
+Fail:
+ if(0)ddprint("fail\n");
+ return -1;
+}
+
+static Hci*
+hciprobe(int cardno, int ctlrno)
+{
+ Hci *hp;
+ char *type;
+ char name[64];
+ static int epnb = 1; /* guess the endpoint nb. for the controller */
+
+ ddprint("hciprobe %d %d\n", cardno, ctlrno);
+ hp = smalloc(sizeof(Hci));
+ hp->ctlrno = ctlrno;
+ hp->tbdf = BUSUNKNOWN;
+
+ if(cardno < 0)
+ for(cardno = 0; cardno < Nhcis; cardno++){
+ if(hcitypes[cardno].type == nil)
+ break;
+ type = hp->type;
+ if(type==nil || *type==0)
+ type = "uhci";
+ if(cistrcmp(hcitypes[cardno].type, type) == 0)
+ break;
+ }
+
+ if(cardno >= Nhcis || hcitypes[cardno].type == nil){
+ free(hp);
+ return nil;
+ }
+ dprint("%s...", hcitypes[cardno].type);
+ if(hcitypes[cardno].reset(hp) < 0){
+ free(hp);
+ return nil;
+ }
+
+ snprint(name, sizeof(name), "usb%s", hcitypes[cardno].type);
+ intrenable(Irqlo, hp->irq, hp->interrupt, hp, name);
+ print("#u/usb/ep%d.0: %s: port %#luX irq %d\n",
+ epnb, hcitypes[cardno].type, hp->port, hp->irq);
+ epnb++;
+ return hp;
+}
+
+static void
+usbreset(void)
+{
+ int cardno, ctlrno;
+ Hci *hp;
+
+ dprint("usbreset\n");
+
+ for(ctlrno = 0; ctlrno < Nhcis; ctlrno++)
+ if((hp = hciprobe(-1, ctlrno)) != nil)
+ hcis[ctlrno] = hp;
+ cardno = ctlrno = 0;
+ while(cardno < Nhcis && ctlrno < Nhcis && hcitypes[cardno].type != nil)
+ if(hcis[ctlrno] != nil)
+ ctlrno++;
+ else{
+ hp = hciprobe(cardno, ctlrno);
+ if(hp == nil)
+ cardno++;
+ hcis[ctlrno++] = hp;
+ }
+ if(hcis[Nhcis-1] != nil)
+ print("usbreset: bug: Nhcis too small\n");
+}
+
+static void
+usbinit(void)
+{
+ Hci *hp;
+ int ctlrno;
+ Ep *d;
+ char info[40];
+
+ dprint("usbinit\n");
+ for(ctlrno = 0; ctlrno < Nhcis; ctlrno++){
+ hp = hcis[ctlrno];
+ if(hp != nil){
+ if(hp->init != nil)
+ hp->init(hp);
+ d = newdev(hp, 1, 1); /* new root hub */
+ d->dev->state = Denabled; /* although addr == 0 */
+ d->maxpkt = 64;
+ snprint(info, sizeof(info), "ports %d", hp->nports);
+ kstrdup(&d->info, info);
+ }
+ }
+}
+
+static Chan*
+usbattach(char *spec)
+{
+ return devattach(L'u', spec);
+}
+
+static Walkqid*
+usbwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, nil, 0, usbgen);
+}
+
+static int
+usbstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, nil, 0, usbgen);
+}
+
+/*
+ * µs for the given transfer, for bandwidth allocation.
+ * This is a very rough worst case for what 5.11.3
+ * of the usb 2.0 spec says.
+ * Also, we are using maxpkt and not actual transfer sizes.
+ * Only when we are sure we
+ * are not exceeding b/w might we consider adjusting it.
+ */
+static ulong
+usbload(int speed, int maxpkt)
+{
+ enum{ Hostns = 1000, Hubns = 333 };
+ ulong l;
+ ulong bs;
+
+ l = 0;
+ bs = 10UL * maxpkt;
+ switch(speed){
+ case Highspeed:
+ l = 55*8*2 + 2 * (3 + bs) + Hostns;
+ break;
+ case Fullspeed:
+ l = 9107 + 84 * (4 + bs) + Hostns;
+ break;
+ case Lowspeed:
+ l = 64107 + 2 * Hubns + 667 * (3 + bs) + Hostns;
+ break;
+ default:
+ print("usbload: bad speed %d\n", speed);
+ /* let it run */
+ }
+ return l / 1000UL; /* in µs */
+}
+
+static Chan*
+usbopen(Chan *c, int omode)
+{
+ int q;
+ Ep *ep;
+ int mode;
+
+ mode = openmode(omode);
+ q = QID(c->qid);
+
+ if(q >= Qep0dir && qid2epidx(q) < 0)
+ error(Eio);
+ if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
+ return devopen(c, omode, nil, 0, usbgen);
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ deprint("usbopen q %#x fid %d omode %d\n", q, c->fid, mode);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ qlock(ep);
+ if(ep->inuse){
+ qunlock(ep);
+ error(Einuse);
+ }
+ ep->inuse = 1;
+ qunlock(ep);
+ if(waserror()){
+ ep->inuse = 0;
+ nexterror();
+ }
+ if(mode != OREAD && ep->mode == OREAD)
+ error(Eperm);
+ if(mode != OWRITE && ep->mode == OWRITE)
+ error(Eperm);
+ if(ep->ttype == Tnone)
+ error(Enotconf);
+ ep->clrhalt = 0;
+ ep->rhrepl = -1;
+ if(ep->load == 0)
+ ep->load = usbload(ep->dev->speed, ep->maxpkt);
+ ep->hp->epopen(ep);
+
+ poperror(); /* ep->inuse */
+ poperror(); /* don't putep(): ref kept for fid using the ep. */
+
+ c->mode = mode;
+ c->flag |= COPEN;
+ c->offset = 0;
+ c->aux = nil; /* paranoia */
+ return c;
+}
+
+static void
+epclose(Ep *ep)
+{
+ qlock(ep);
+ if(waserror()){
+ qunlock(ep);
+ nexterror();
+ }
+ if(ep->inuse){
+ ep->hp->epclose(ep);
+ ep->inuse = 0;
+ }
+ qunlock(ep);
+ poperror();
+}
+
+static void
+usbclose(Chan *c)
+{
+ int q;
+ Ep *ep;
+
+ q = QID(c->qid);
+ if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
+ return;
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ return;
+ deprint("usbclose q %#x fid %d ref %ld\n", q, c->fid, ep->ref);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(c->flag & COPEN){
+ free(c->aux);
+ c->aux = nil;
+ epclose(ep);
+ putep(ep); /* release ref kept since usbopen */
+ c->flag &= ~COPEN;
+ }
+ poperror();
+ putep(ep);
+}
+
+static long
+ctlread(Chan *c, void *a, long n, vlong offset)
+{
+ int q;
+ char *s;
+ char *us;
+ char *se;
+ Ep *ep;
+ int i;
+
+ q = QID(c->qid);
+ us = s = smalloc(READSTR);
+ se = s + READSTR;
+ if(waserror()){
+ free(us);
+ nexterror();
+ }
+ if(q == Qctl)
+ for(i = 0; i < epmax; i++){
+ ep = getep(i);
+ if(ep != nil){
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ s = seprint(s, se, "ep%d.%d ", ep->dev->nb, ep->nb);
+ s = seprintep(s, se, ep, 0);
+ poperror();
+ }
+ putep(ep);
+ }
+ else{
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(c->aux != nil){
+ /* After a new endpoint request we read
+ * the new endpoint name back.
+ */
+ strecpy(s, se, c->aux);
+ free(c->aux);
+ c->aux = nil;
+ }else
+ seprintep(s, se, ep, 0);
+ poperror();
+ putep(ep);
+ }
+ n = readstr(offset, a, n, us);
+ poperror();
+ free(us);
+ return n;
+}
+
+/*
+ * Fake root hub emulation.
+ */
+static long
+rhubread(Ep *ep, void *a, long n)
+{
+ char *b;
+
+ if(ep->dev->isroot == 0 || ep->nb != 0 || n < 2)
+ return -1;
+ if(ep->rhrepl < 0)
+ return -1;
+
+ b = a;
+ memset(b, 0, n);
+ PUT2(b, ep->rhrepl);
+ ep->rhrepl = -1;
+ return n;
+}
+
+static long
+rhubwrite(Ep *ep, void *a, long n)
+{
+ uchar *s;
+ int cmd;
+ int feature;
+ int port;
+ Hci *hp;
+
+ if(ep->dev == nil || ep->dev->isroot == 0 || ep->nb != 0)
+ return -1;
+ if(n != Rsetuplen)
+ error("root hub is a toy hub");
+ ep->rhrepl = -1;
+ s = a;
+ if(s[Rtype] != (Rh2d|Rclass|Rother) && s[Rtype] != (Rd2h|Rclass|Rother))
+ error("root hub is a toy hub");
+ hp = ep->hp;
+ cmd = s[Rreq];
+ feature = GET2(s+Rvalue);
+ port = GET2(s+Rindex);
+ if(port < 1 || port > hp->nports)
+ error("bad hub port number");
+ switch(feature){
+ case Rportenable:
+ ep->rhrepl = hp->portenable(hp, port, cmd == Rsetfeature);
+ break;
+ case Rportreset:
+ ep->rhrepl = hp->portreset(hp, port, cmd == Rsetfeature);
+ break;
+ case Rgetstatus:
+ ep->rhrepl = hp->portstatus(hp, port);
+ break;
+ default:
+ ep->rhrepl = 0;
+ }
+ return n;
+}
+
+static long
+usbread(Chan *c, void *a, long n, vlong offset)
+{
+ int q;
+ Ep *ep;
+ int nr;
+
+ q = QID(c->qid);
+
+ if(c->qid.type == QTDIR)
+ return devdirread(c, a, n, nil, 0, usbgen);
+
+ if(q == Qctl || isqtype(q, Qepctl))
+ return ctlread(c, a, n, offset);
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(ep->dev->state == Ddetach)
+ error(Edetach);
+ if(ep->mode == OWRITE || ep->inuse == 0)
+ error(Ebadusefd);
+ switch(ep->ttype){
+ case Tnone:
+ error("endpoint not configured");
+ case Tctl:
+ nr = rhubread(ep, a, n);
+ if(nr >= 0){
+ n = nr;
+ break;
+ }
+ /* else fall */
+ default:
+ ddeprint("\nusbread q %#x fid %d cnt %ld off %lld\n",q,c->fid,n,offset);
+ n = ep->hp->epread(ep, a, n);
+ break;
+ }
+ poperror();
+ putep(ep);
+ return n;
+}
+
+static long
+pow2(int n)
+{
+ return 1 << n;
+}
+
+static void
+setmaxpkt(Ep *ep, char* s)
+{
+ long spp; /* samples per packet */
+
+ if(ep->dev->speed == Highspeed)
+ spp = (ep->hz * ep->pollival * ep->ntds + 7999) / 8000;
+ else
+ spp = (ep->hz * ep->pollival + 999) / 1000;
+ ep->maxpkt = spp * ep->samplesz;
+ deprint("usb: %s: setmaxpkt: hz %ld poll %ld"
+ " ntds %d %s speed -> spp %ld maxpkt %ld\n", s,
+ ep->hz, ep->pollival, ep->ntds, spname[ep->dev->speed],
+ spp, ep->maxpkt);
+ if(ep->maxpkt > 1024){
+ print("usb: %s: maxpkt %ld > 1024. truncating\n", s, ep->maxpkt);
+ ep->maxpkt = 1024;
+ }
+}
+
+/*
+ * Many endpoint ctls. simply update the portable representation
+ * of the endpoint. The actual controller driver will look
+ * at them to setup the endpoints as dictated.
+ */
+static long
+epctl(Ep *ep, Chan *c, void *a, long n)
+{
+ int i, l, mode, nb, tt;
+ char *b, *s;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ Ep *nep;
+ Udev *d;
+ static char *Info = "info ";
+
+ d = ep->dev;
+
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, epctls, nelem(epctls));
+ if(ct == nil)
+ error(Ebadctl);
+ i = ct->index;
+ if(i == CMnew || i == CMspeed || i == CMhub || i == CMpreset)
+ if(ep != ep->ep0)
+ error("allowed only on a setup endpoint");
+ if(i != CMclrhalt && i != CMdetach && i != CMdebugep && i != CMname)
+ if(ep != ep->ep0 && ep->inuse != 0)
+ error("must configure before using");
+ switch(i){
+ case CMnew:
+ deprint("usb epctl %s\n", cb->f[0]);
+ nb = strtol(cb->f[1], nil, 0);
+ if(nb < 0 || nb >= Ndeveps)
+ error("bad endpoint number");
+ tt = name2ttype(cb->f[2]);
+ if(tt == Tnone)
+ error("unknown endpoint type");
+ mode = name2mode(cb->f[3]);
+ if(mode < 0)
+ error("unknown i/o mode");
+ newdevep(ep, nb, tt, mode);
+ break;
+ case CMnewdev:
+ deprint("usb epctl %s\n", cb->f[0]);
+ if(ep != ep->ep0 || d->ishub == 0)
+ error("not a hub setup endpoint");
+ l = name2speed(cb->f[1]);
+ if(l == Nospeed)
+ error("speed must be full|low|high");
+ nep = newdev(ep->hp, 0, 0);
+ nep->dev->speed = l;
+ if(nep->dev->speed != Lowspeed)
+ nep->maxpkt = 64; /* assume full speed */
+ nep->dev->hub = d->nb;
+ nep->dev->port = atoi(cb->f[2]);
+ /* next read request will read
+ * the name for the new endpoint
+ */
+ l = sizeof(up->genbuf);
+ snprint(up->genbuf, l, "ep%d.%d", nep->dev->nb, nep->nb);
+ kstrdup(&c->aux, up->genbuf);
+ break;
+ case CMhub:
+ deprint("usb epctl %s\n", cb->f[0]);
+ d->ishub = 1;
+ break;
+ case CMspeed:
+ l = name2speed(cb->f[1]);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l == Nospeed)
+ error("speed must be full|low|high");
+ qlock(ep->ep0);
+ d->speed = l;
+ qunlock(ep->ep0);
+ break;
+ case CMmaxpkt:
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l < 1 || l > 1024)
+ error("maxpkt not in [1:1024]");
+ qlock(ep);
+ ep->maxpkt = l;
+ qunlock(ep);
+ break;
+ case CMntds:
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l < 1 || l > 3)
+ error("ntds not in [1:3]");
+ qlock(ep);
+ ep->ntds = l;
+ qunlock(ep);
+ break;
+ case CMpollival:
+ if(ep->ttype != Tintr && ep->ttype != Tiso)
+ error("not an intr or iso endpoint");
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(ep->ttype == Tiso ||
+ (ep->ttype == Tintr && ep->dev->speed == Highspeed)){
+ if(l < 1 || l > 16)
+ error("pollival power not in [1:16]");
+ l = pow2(l-1);
+ }else
+ if(l < 1 || l > 255)
+ error("pollival not in [1:255]");
+ qlock(ep);
+ ep->pollival = l;
+ if(ep->ttype == Tiso)
+ setmaxpkt(ep, "pollival");
+ qunlock(ep);
+ break;
+ case CMsamplesz:
+ if(ep->ttype != Tiso)
+ error("not an iso endpoint");
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l <= 0 || l > 8)
+ error("samplesz not in [1:8]");
+ qlock(ep);
+ ep->samplesz = l;
+ setmaxpkt(ep, "samplesz");
+ qunlock(ep);
+ break;
+ case CMhz:
+ if(ep->ttype != Tiso)
+ error("not an iso endpoint");
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l <= 0 || l > 100000)
+ error("hz not in [1:100000]");
+ qlock(ep);
+ ep->hz = l;
+ setmaxpkt(ep, "hz");
+ qunlock(ep);
+ break;
+ case CMclrhalt:
+ qlock(ep);
+ deprint("usb epctl %s\n", cb->f[0]);
+ ep->clrhalt = 1;
+ qunlock(ep);
+ break;
+ case CMinfo:
+ deprint("usb epctl %s\n", cb->f[0]);
+ l = strlen(Info);
+ s = a;
+ if(n < l+2 || strncmp(Info, s, l) != 0)
+ error(Ebadctl);
+ if(n > 1024)
+ n = 1024;
+ b = smalloc(n);
+ memmove(b, s+l, n-l);
+ b[n-l] = 0;
+ if(b[n-l-1] == '\n')
+ b[n-l-1] = 0;
+ qlock(ep);
+ free(ep->info);
+ ep->info = b;
+ qunlock(ep);
+ break;
+ case CMaddress:
+ deprint("usb epctl %s\n", cb->f[0]);
+ ep->dev->state = Denabled;
+ break;
+ case CMdetach:
+ if(ep->dev->isroot != 0)
+ error("can't detach a root hub");
+ deprint("usb epctl %s ep%d.%d\n",
+ cb->f[0], ep->dev->nb, ep->nb);
+ ep->dev->state = Ddetach;
+ /* Release file system ref. for its endpoints */
+ for(i = 0; i < nelem(ep->dev->eps); i++)
+ putep(ep->dev->eps[i]);
+ break;
+ case CMdebugep:
+ if(strcmp(cb->f[1], "on") == 0)
+ ep->debug = 1;
+ else if(strcmp(cb->f[1], "off") == 0)
+ ep->debug = 0;
+ else
+ ep->debug = strtoul(cb->f[1], nil, 0);
+ print("usb: ep%d.%d debug %d\n",
+ ep->dev->nb, ep->nb, ep->debug);
+ break;
+ case CMname:
+ deprint("usb epctl %s %s\n", cb->f[0], cb->f[1]);
+ validname(cb->f[1], 0);
+ kstrdup(&ep->name, cb->f[1]);
+ break;
+ case CMtmout:
+ deprint("usb epctl %s\n", cb->f[0]);
+ if(ep->ttype == Tiso || ep->ttype == Tctl)
+ error("ctl ignored for this endpoint type");
+ ep->tmout = strtoul(cb->f[1], nil, 0);
+ if(ep->tmout != 0 && ep->tmout < Xfertmout)
+ ep->tmout = Xfertmout;
+ break;
+ case CMpreset:
+ deprint("usb epctl %s\n", cb->f[0]);
+ if(ep->ttype != Tctl)
+ error("not a control endpoint");
+ if(ep->dev->state != Denabled)
+ error("forbidden on devices not enabled");
+ ep->dev->state = Dreset;
+ break;
+ default:
+ panic("usb: unknown epctl %d", ct->index);
+ }
+ free(cb);
+ poperror();
+ return n;
+}
+
+static long
+usbctl(void *a, long n)
+{
+ Cmdtab *ct;
+ Cmdbuf *cb;
+ Ep *ep;
+ int i;
+
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, usbctls, nelem(usbctls));
+ dprint("usb ctl %s\n", cb->f[0]);
+ switch(ct->index){
+ case CMdebug:
+ if(strcmp(cb->f[1], "on") == 0)
+ debug = 1;
+ else if(strcmp(cb->f[1], "off") == 0)
+ debug = 0;
+ else
+ debug = strtol(cb->f[1], nil, 0);
+ print("usb: debug %d\n", debug);
+ for(i = 0; i < epmax; i++)
+ if((ep = getep(i)) != nil){
+ ep->hp->debug(ep->hp, debug);
+ putep(ep);
+ }
+ break;
+ case CMdump:
+ dumpeps();
+ break;
+ }
+ free(cb);
+ poperror();
+ return n;
+}
+
+static long
+ctlwrite(Chan *c, void *a, long n)
+{
+ int q;
+ Ep *ep;
+
+ q = QID(c->qid);
+ if(q == Qctl)
+ return usbctl(a, n);
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(ep->dev->state == Ddetach)
+ error(Edetach);
+ if(isqtype(q, Qepctl) && c->aux != nil){
+ /* Be sure we don't keep a cloned ep name */
+ free(c->aux);
+ c->aux = nil;
+ error("read, not write, expected");
+ }
+ n = epctl(ep, c, a, n);
+ putep(ep);
+ poperror();
+ return n;
+}
+
+static long
+usbwrite(Chan *c, void *a, long n, vlong off)
+{
+ int nr, q;
+ Ep *ep;
+
+ if(c->qid.type == QTDIR)
+ error(Eisdir);
+
+ q = QID(c->qid);
+
+ if(q == Qctl || isqtype(q, Qepctl))
+ return ctlwrite(c, a, n);
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(ep->dev->state == Ddetach)
+ error(Edetach);
+ if(ep->mode == OREAD || ep->inuse == 0)
+ error(Ebadusefd);
+
+ switch(ep->ttype){
+ case Tnone:
+ error("endpoint not configured");
+ case Tctl:
+ nr = rhubwrite(ep, a, n);
+ if(nr >= 0){
+ n = nr;
+ break;
+ }
+ /* else fall */
+ default:
+ ddeprint("\nusbwrite q %#x fid %d cnt %ld off %lld\n",q, c->fid, n, off);
+ ep->hp->epwrite(ep, a, n);
+ }
+ putep(ep);
+ poperror();
+ return n;
+}
+
+void
+usbshutdown(void)
+{
+ Hci *hp;
+ int i;
+
+ for(i = 0; i < Nhcis; i++){
+ hp = hcis[i];
+ if(hp == nil)
+ continue;
+ if(hp->shutdown == nil)
+ print("#u: no shutdown function for %s\n", hp->type);
+ else
+ hp->shutdown(hp);
+ }
+}
+
+Dev usbdevtab = {
+ L'u',
+ "usb",
+
+ usbreset,
+ usbinit,
+ usbshutdown,
+ usbattach,
+ usbwalk,
+ usbstat,
+ usbopen,
+ devcreate,
+ usbclose,
+ usbread,
+ devbread,
+ usbwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/kw/ether1116.c b/sys/src/9/kw/ether1116.c
new file mode 100755
index 000000000..b60c70a49
--- /dev/null
+++ b/sys/src/9/kw/ether1116.c
@@ -0,0 +1,1747 @@
+/*
+ * marvell kirkwood gigabit ethernet (88e1116 and 88e1121) driver
+ * (as found in the sheevaplug, openrd and guruplug).
+ * the main difference is the flavour of phy kludgery necessary.
+ *
+ * from /public/doc/marvell/88f61xx.kirkwood.pdf,
+ * /public/doc/marvell/88e1116.pdf, and
+ * /public/doc/marvell/88e1121r.pdf.
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+#include "../ip/ip.h"
+
+#define MIIDBG if(0)iprint
+
+#define WINATTR(v) (((v) & MASK(8)) << 8)
+#define WINSIZE(v) (((v)/(64*1024) - 1) << 16)
+
+enum {
+ Nrx = 512,
+ Ntx = 32,
+ Nrxblks = 1024,
+ Rxblklen = 2+1522, /* ifc. supplies first 2 bytes as padding */
+
+ Maxrxintrsec = 20*1000, /* max. rx intrs. / sec */
+ Etherstuck = 70, /* must send or receive a packet in this many sec.s */
+
+ Descralign = 16,
+ Bufalign = 8,
+
+ Pass = 1, /* accept packets */
+
+ Qno = 0, /* do everything on queue zero */
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Gbereg Gbereg;
+typedef struct Mibstats Mibstats;
+typedef struct Rx Rx;
+typedef struct Tx Tx;
+
+static struct {
+ Lock;
+ Block *head;
+} freeblocks;
+
+/* hardware receive buffer descriptor */
+struct Rx {
+ ulong cs;
+ ulong countsize; /* bytes, buffer size */
+ ulong buf; /* phys. addr. of packet buffer */
+ ulong next; /* phys. addr. of next Rx */
+};
+
+/* hardware transmit buffer descriptor */
+struct Tx {
+ ulong cs;
+ ulong countchk; /* bytes, checksum */
+ ulong buf; /* phys. addr. of packet buffer */
+ ulong next; /* phys. addr. of next Tx */
+};
+
+/* fixed by hw; part of Gberegs */
+struct Mibstats {
+ union {
+ uvlong rxby; /* good bytes rcv'd */
+ struct {
+ ulong rxbylo;
+ ulong rxbyhi;
+ };
+ };
+ ulong badrxby; /* bad bytes rcv'd */
+ ulong mactxerr; /* tx err pkts */
+ ulong rxpkt; /* good pkts rcv'd */
+ ulong badrxpkt; /* bad pkts rcv'd */
+ ulong rxbcastpkt; /* b'cast pkts rcv'd */
+ ulong rxmcastpkt; /* m'cast pkts rcv'd */
+
+ ulong rx64; /* pkts <= 64 bytes */
+ ulong rx65_127; /* pkts 65—127 bytes */
+ ulong rx128_255; /* pkts 128—255 bytes */
+ ulong rx256_511; /* pkts 256—511 bytes */
+ ulong rx512_1023; /* pkts 512—1023 bytes */
+ ulong rx1024_max; /* pkts >= 1024 bytes */
+
+ union {
+ uvlong txby; /* good bytes sent */
+ struct {
+ ulong txbylo;
+ ulong txbyhi;
+ };
+ };
+ ulong txpkt; /* good pkts sent */
+ /* half-duplex: pkts dropped due to excessive collisions */
+ ulong txcollpktdrop;
+ ulong txmcastpkt; /* m'cast pkts sent */
+ ulong txbcastpkt; /* b'cast pkts sent */
+
+ ulong badmacctlpkts; /* bad mac ctl pkts */
+ ulong txflctl; /* flow-control pkts sent */
+ ulong rxflctl; /* good flow-control pkts rcv'd */
+ ulong badrxflctl; /* bad flow-control pkts rcv'd */
+
+ ulong rxundersized; /* runts */
+ ulong rxfrags; /* fragments rcv'd */
+ ulong rxtoobig; /* oversized pkts rcv'd */
+ ulong rxjabber; /* jabber pkts rcv'd */
+ ulong rxerr; /* rx error events */
+ ulong crcerr; /* crc error events */
+ ulong collisions; /* collision events */
+ ulong latecoll; /* late collisions */
+};
+
+struct Ctlr {
+ Lock;
+ Ether *ether;
+ Gbereg *reg;
+
+ Lock initlock;
+ int init;
+
+ Rx *rx; /* receive descriptors */
+ Block *rxb[Nrx]; /* blocks belonging to the descriptors */
+ int rxhead; /* descr ethernet will write to next */
+ int rxtail; /* next descr that might need a buffer */
+ Rendez rrendez; /* interrupt wakes up read process */
+ int haveinput;
+
+ Tx *tx;
+ Block *txb[Ntx];
+ int txhead; /* next descr we can use for new packet */
+ int txtail; /* next descr to reclaim on tx complete */
+
+ Mii *mii;
+ int port;
+
+ /* stats */
+ ulong intrs;
+ ulong newintrs;
+ ulong txunderrun;
+ ulong txringfull;
+ ulong rxdiscard;
+ ulong rxoverrun;
+ ulong nofirstlast;
+
+ Mibstats;
+};
+
+#define Rxqon(q) (1<<(q))
+#define Txqon(q) (1<<(q))
+
+enum {
+ /* euc bits */
+ Portreset = 1 << 20,
+
+ /* sdma config, sdc bits */
+ Burst1 = 0,
+ Burst2,
+ Burst4,
+ Burst8,
+ Burst16,
+ SDCrifb = 1<<0, /* rx intr on pkt boundaries */
+#define SDCrxburst(v) ((v)<<1)
+ SDCrxnobyteswap = 1<<4,
+ SDCtxnobyteswap = 1<<5,
+ SDCswap64byte = 1<<6,
+#define SDCtxburst(v) ((v)<<22)
+ /* rx intr ipg (inter packet gap) */
+#define SDCipgintrx(v) ((((v)>>15) & 1)<<25) | (((v) & MASK(15))<<7)
+
+ /* portcfg bits */
+ PCFGupromisc = 1<<0, /* unicast promiscuous mode */
+#define Rxqdefault(q) ((q)<<1)
+#define Rxqarp(q) ((q)<<4)
+ PCFGbcrejectnoiparp = 1<<7,
+ PCFGbcrejectip = 1<<8,
+ PCFGbcrejectarp = 1<<9,
+ PCFGamnotxes = 1<<12, /* auto mode, no summary update on tx */
+ PCFGtcpq = 1<<14, /* capture tcp frames to tcpq */
+ PCFGudpq = 1<<15, /* capture udp frames to udpq */
+#define Rxqtcp(q) ((q)<<16)
+#define Rxqudp(q) ((q)<<19)
+#define Rxqbpdu(q) ((q)<<22)
+ PCFGrxcs = 1<<25, /* rx tcp checksum mode with header */
+
+ /* portcfgx bits */
+ PCFGXspanq = 1<<1,
+ PCFGXcrcoff = 1<<2, /* no ethernet crc */
+
+ /* port serial control0, psc0 bits */
+ PSC0porton = 1<<0,
+ PSC0forcelinkup = 1<<1,
+ PSC0an_dplxoff = 1<<2, /* an_ = auto. negotiate */
+ PSC0an_flctloff = 1<<3,
+ PSC0an_pauseadv = 1<<4,
+ PSC0nofrclinkdown = 1<<10,
+ PSC0an_spdoff = 1<<13,
+ PSC0dteadv = 1<<14, /* dte advertise */
+
+ /* max. input pkt size */
+#define PSC0mru(v) ((v)<<17)
+ PSC0mrumask = PSC0mru(MASK(3)),
+ PSC0mru1518 = 0, /* 1500+2* 6(addrs) +2 + 4(crc) */
+ PSC0mru1522, /* 1518 + 4(vlan tags) */
+ PSC0mru1552, /* `baby giant' */
+ PSC0mru9022, /* `jumbo' */
+ PSC0mru9192, /* bigger jumbo */
+ PSC0mru9700, /* still bigger jumbo */
+
+ PSC0fd_frc = 1<<21, /* force full duplex */
+ PSC0flctlfrc = 1<<22,
+ PSC0gmiispd_gbfrc = 1<<23,
+ PSC0miispdfrc100mbps = 1<<24,
+
+ /* port status 0, ps0 bits */
+ PS0linkup = 1<<1,
+ PS0fd = 1<<2, /* full duplex */
+ PS0flctl = 1<<3,
+ PS0gmii_gb = 1<<4,
+ PS0mii100mbps = 1<<5,
+ PS0txbusy = 1<<7,
+ PS0txfifoempty = 1<<10,
+ PS0rxfifo1empty = 1<<11,
+ PS0rxfifo2empty = 1<<12,
+
+ /* port serial control 1, psc1 bits */
+ PSC1loopback = 1<<1,
+ PSC1mii = 0<<2,
+ PSC1rgmii = 1<<3, /* enable RGMII */
+ PSC1portreset = 1<<4,
+ PSC1clockbypass = 1<<5,
+ PSC1iban = 1<<6,
+ PSC1iban_bypass = 1<<7,
+ PSC1iban_restart= 1<<8,
+ PSC1_gbonly = 1<<11,
+ PSC1encolonbp = 1<<15, /* "collision during back-pressure mib counting" */
+ PSC1coldomlimmask= MASK(6)<<16,
+#define PSC1coldomlim(v) (((v) & MASK(6))<<16)
+ PSC1miiallowoddpreamble = 1<<22,
+
+ /* port status 1, ps1 bits */
+ PS1rxpause = 1<<0,
+ PS1txpause = 1<<1,
+ PS1pressure = 1<<2,
+ PS1syncfail10ms = 1<<3,
+ PS1an_done = 1<<4,
+ PS1inbandan_bypassed = 1<<5,
+ PS1serdesplllocked = 1<<6,
+ PS1syncok = 1<<7,
+ PS1nosquelch = 1<<8,
+
+ /* irq bits */
+ /* rx buf returned to cpu ownership, or frame reception finished */
+ Irx = 1<<0,
+ Iextend = 1<<1, /* IEsum of irqe set */
+#define Irxbufferq(q) (1<<((q)+2)) /* rx buf returned to cpu ownership */
+ Irxerr = 1<<10, /* input ring full, usually */
+#define Irxerrq(q) (1<<((q)+11))
+#define Itxendq(q) (1<<((q)+19)) /* tx dma stopped for q */
+ Isum = 1<<31,
+
+ /* irq extended, irqe bits */
+#define IEtxbufferq(q) (1<<((q)+0)) /* tx buf returned to cpu ownership */
+#define IEtxerrq(q) (1<<((q)+8))
+ IEphystschg = 1<<16,
+ IEptp = 1<<17,
+ IErxoverrun = 1<<18,
+ IEtxunderrun = 1<<19,
+ IElinkchg = 1<<20,
+ IEintaddrerr = 1<<23,
+ IEprbserr = 1<<25,
+ IEsum = 1<<31,
+
+ /* tx fifo urgent threshold (tx interrupt coalescing), pxtfut */
+#define TFUTipginttx(v) (((v) & MASK(16))<<4);
+
+ /* minimal frame size, mfs */
+ MFS40by = 10<<2,
+ MFS44by = 11<<2,
+ MFS48by = 12<<2,
+ MFS52by = 13<<2,
+ MFS56by = 14<<2,
+ MFS60by = 15<<2,
+ MFS64by = 16<<2,
+
+ /* receive descriptor status */
+ RCSmacerr = 1<<0,
+ RCSmacmask = 3<<1,
+ RCSmacce = 0<<1,
+ RCSmacor = 1<<1,
+ RCSmacmf = 2<<1,
+ RCSl4chkshift = 3,
+ RCSl4chkmask = MASK(16),
+ RCSvlan = 1<<17,
+ RCSbpdu = 1<<18,
+ RCSl4mask = 3<<21,
+ RCSl4tcp4 = 0<<21,
+ RCSl4udp4 = 1<<21,
+ RCSl4other = 2<<21,
+ RCSl4rsvd = 3<<21,
+ RCSl2ev2 = 1<<23,
+ RCSl3ip4 = 1<<24,
+ RCSip4headok = 1<<25,
+ RCSlast = 1<<26,
+ RCSfirst = 1<<27,
+ RCSunknownaddr = 1<<28,
+ RCSenableintr = 1<<29,
+ RCSl4chkok = 1<<30,
+ RCSdmaown = 1<<31,
+
+ /* transmit descriptor status */
+ TCSmacerr = 1<<0,
+ TCSmacmask = 3<<1,
+ TCSmaclc = 0<<1,
+ TCSmacur = 1<<1,
+ TCSmacrl = 2<<1,
+ TCSllc = 1<<9,
+ TCSl4chkmode = 1<<10,
+ TCSipv4hdlenshift= 11,
+ TCSvlan = 1<<15,
+ TCSl4type = 1<<16,
+ TCSgl4chk = 1<<17,
+ TCSgip4chk = 1<<18,
+ TCSpadding = 1<<19,
+ TCSlast = 1<<20,
+ TCSfirst = 1<<21,
+ TCSenableintr = 1<<23,
+ TCSautomode = 1<<30,
+ TCSdmaown = 1<<31,
+};
+
+enum {
+ /* SMI regs */
+ PhysmiTimeout = 10000, /* what units? in ms. */
+ Physmidataoff = 0, /* Data */
+ Physmidatamask = 0xffff<<Physmidataoff,
+
+ Physmiaddroff = 16, /* PHY device addr */
+ Physmiaddrmask = 0x1f << Physmiaddroff,
+
+ Physmiop = 26,
+ Physmiopmask = 3<<Physmiop,
+ PhysmiopWr = 0<<Physmiop,
+ PhysmiopRd = 1<<Physmiop,
+
+ PhysmiReadok = 1<<27,
+ PhysmiBusy = 1<<28,
+
+ SmiRegaddroff = 21, /* PHY device register addr */
+ SmiRegaddrmask = 0x1f << SmiRegaddroff,
+};
+
+struct Gbereg {
+ ulong phy; /* PHY address */
+ ulong smi; /* serial mgmt. interface */
+ ulong euda; /* ether default address */
+ ulong eudid; /* ether default id */
+ uchar _pad0[0x80-0x10];
+
+ /* dma stuff */
+ ulong euirq; /* interrupt cause */
+ ulong euirqmask; /* interrupt mask */
+ uchar _pad1[0x94-0x88];
+ ulong euea; /* error address */
+ ulong euiae; /* internal error address */
+ uchar _pad2[0xb0-0x9c];
+ ulong euc; /* control */
+ uchar _pad3[0x200-0xb4];
+ struct {
+ ulong base; /* window base */
+ ulong size; /* window size */
+ } base[6];
+ uchar _pad4[0x280-0x230];
+ ulong harr[4]; /* high address remap */
+ ulong bare; /* base address enable */
+ ulong epap; /* port access protect */
+ uchar _pad5[0x400-0x298];
+
+ ulong portcfg; /* port configuration */
+ ulong portcfgx; /* port config. extend */
+ ulong mii; /* mii serial parameters */
+ ulong _pad6;
+ ulong evlane; /* vlan ether type */
+ ulong macal; /* mac address low */
+ ulong macah; /* mac address high */
+ ulong sdc; /* sdma config. */
+ ulong dscp[7]; /* ip diff. serv. code point -> pri */
+ ulong psc0; /* port serial control 0 */
+ ulong vpt2p; /* vlan priority tag -> pri */
+ ulong ps0; /* ether port status 0 */
+ ulong tqc; /* transmit queue command */
+ ulong psc1; /* port serial control 1 */
+ ulong ps1; /* ether port status 1 */
+ ulong mvhdr; /* marvell header */
+ ulong _pad8[2];
+
+ /* interrupts */
+ ulong irq; /* interrupt cause; some rw0c bits */
+ ulong irqe; /* " " extended; some rw0c bits */
+ ulong irqmask; /* interrupt mask (actually enable) */
+ ulong irqemask; /* " " extended */
+
+ ulong _pad9;
+ ulong pxtfut; /* port tx fifo urgent threshold */
+ ulong _pad10;
+ ulong pxmfs; /* port rx minimum frame size */
+ ulong _pad11;
+
+ /*
+ * # of input frames discarded by addr filtering or lack of resources;
+ * zeroed upon read.
+ */
+ ulong pxdfc; /* port rx discard frame counter */
+ ulong pxofc; /* port overrun frame counter */
+ ulong _pad12[2];
+ ulong piae; /* port internal address error */
+ uchar _pad13[0x4bc-0x498];
+ ulong etherprio; /* ether type priority */
+ uchar _pad14[0x4dc-0x4c0];
+ ulong tqfpc; /* tx queue fixed priority config. */
+ ulong pttbrc; /* port tx token-bucket rate config. */
+ ulong tqc1; /* tx queue command 1 */
+ ulong pmtu; /* port maximum transmit unit */
+ ulong pmtbs; /* port maximum token bucket size */
+ uchar _pad15[0x600-0x4f0];
+
+ struct {
+ ulong _pad[3];
+ ulong r; /* phys. addr.: cur. rx desc. ptrs */
+ } crdp[8];
+ ulong rqc; /* rx queue command */
+ ulong tcsdp; /* phys. addr.: cur. tx desc. ptr */
+ uchar _pad16[0x6c0-0x688];
+
+ ulong tcqdp[8]; /* phys. addr.: cur. tx q. desc. ptr */
+ uchar _pad17[0x700-0x6e0];
+
+ struct {
+ ulong tbctr; /* queue tx token-bucket counter */
+ ulong tbcfg; /* tx queue token-bucket config. */
+ ulong acfg; /* tx queue arbiter config. */
+ ulong _pad;
+ } tq[8];
+ ulong pttbc; /* port tx token-bucket counter */
+ uchar _pad18[0x7a8-0x784];
+
+ ulong ipg2; /* tx queue ipg */
+ ulong _pad19[3];
+ ulong ipg3;
+ ulong _pad20;
+ ulong htlp; /* high token in low packet */
+ ulong htap; /* high token in async packet */
+ ulong ltap; /* low token in async packet */
+ ulong _pad21;
+ ulong ts; /* tx speed */
+ uchar _pad22[0x1000-0x7d4];
+
+ /* mac mib counters: statistics */
+ Mibstats;
+ uchar _pad23[0x1400-0x1080];
+
+ /* multicast filtering; each byte: Qno<<1 | Pass */
+ ulong dfsmt[64]; /* dest addr filter special m'cast table */
+ ulong dfomt[64]; /* dest addr filter other m'cast table */
+ /* unicast filtering */
+ ulong dfut[4]; /* dest addr filter unicast table */
+};
+
+static Ctlr *ctlrs[MaxEther];
+static uchar zeroea[Eaddrlen];
+
+static void getmibstats(Ctlr *);
+
+static void
+rxfreeb(Block *b)
+{
+ /* freeb(b) will have previously decremented b->ref to 0; raise to 1 */
+ _xinc(&b->ref);
+ b->wp = b->rp =
+ (uchar*)((uintptr)(b->lim - Rxblklen) & ~(Bufalign - 1));
+ assert(((uintptr)b->rp & (Bufalign - 1)) == 0);
+ b->free = rxfreeb;
+
+ ilock(&freeblocks);
+ b->next = freeblocks.head;
+ freeblocks.head = b;
+ iunlock(&freeblocks);
+}
+
+static Block *
+rxallocb(void)
+{
+ Block *b;
+
+ ilock(&freeblocks);
+ b = freeblocks.head;
+ if(b != nil) {
+ freeblocks.head = b->next;
+ b->next = nil;
+ b->free = rxfreeb;
+ }
+ iunlock(&freeblocks);
+ return b;
+}
+
+static void
+rxkick(Ctlr *ctlr)
+{
+ Gbereg *reg = ctlr->reg;
+
+ if (reg->crdp[Qno].r == 0)
+ reg->crdp[Qno].r = PADDR(&ctlr->rx[ctlr->rxhead]);
+ if ((reg->rqc & 0xff) == 0) /* all queues are stopped? */
+ reg->rqc = Rxqon(Qno); /* restart */
+ coherence();
+}
+
+static void
+txkick(Ctlr *ctlr)
+{
+ Gbereg *reg = ctlr->reg;
+
+ if (reg->tcqdp[Qno] == 0)
+ reg->tcqdp[Qno] = PADDR(&ctlr->tx[ctlr->txhead]);
+ if ((reg->tqc & 0xff) == 0) /* all q's stopped? */
+ reg->tqc = Txqon(Qno); /* restart */
+ coherence();
+}
+
+static void
+rxreplenish(Ctlr *ctlr)
+{
+ Rx *r;
+ Block *b;
+
+ while(ctlr->rxb[ctlr->rxtail] == nil) {
+ b = rxallocb();
+ if(b == nil) {
+ iprint("#l%d: rxreplenish out of buffers\n",
+ ctlr->ether->ctlrno);
+ break;
+ }
+
+ ctlr->rxb[ctlr->rxtail] = b;
+
+ /* set up uncached receive descriptor */
+ r = &ctlr->rx[ctlr->rxtail];
+ assert(((uintptr)r & (Descralign - 1)) == 0);
+ r->countsize = ROUNDUP(Rxblklen, 8);
+ r->buf = PADDR(b->rp);
+ coherence();
+
+ /* and fire */
+ r->cs = RCSdmaown | RCSenableintr;
+ coherence();
+
+ ctlr->rxtail = NEXT(ctlr->rxtail, Nrx);
+ }
+}
+
+static void
+dump(uchar *bp, long max)
+{
+ if (max > 64)
+ max = 64;
+ for (; max > 0; max--, bp++)
+ iprint("%02.2ux ", *bp);
+ print("...\n");
+}
+
+static void
+etheractive(Ether *ether)
+{
+ ether->starttime = TK2MS(MACHP(0)->ticks)/1000;
+}
+
+static void
+ethercheck(Ether *ether)
+{
+ if (ether->starttime != 0 &&
+ TK2MS(MACHP(0)->ticks)/1000 - ether->starttime > Etherstuck) {
+ etheractive(ether);
+ if (ether->ctlrno == 0) /* only complain about main ether */
+ iprint("#l%d: ethernet stuck\n", ether->ctlrno);
+ }
+}
+
+static void
+receive(Ether *ether)
+{
+ int i;
+ ulong n;
+ Block *b;
+ Ctlr *ctlr = ether->ctlr;
+ Rx *r;
+
+ ethercheck(ether);
+ for (i = Nrx-2; i > 0; i--) {
+ r = &ctlr->rx[ctlr->rxhead]; /* *r is uncached */
+ assert(((uintptr)r & (Descralign - 1)) == 0);
+ if(r->cs & RCSdmaown) /* descriptor busy? */
+ break;
+
+ b = ctlr->rxb[ctlr->rxhead]; /* got input buffer? */
+ if (b == nil)
+ panic("ether1116: nil ctlr->rxb[ctlr->rxhead] "
+ "in receive");
+ ctlr->rxb[ctlr->rxhead] = nil;
+ ctlr->rxhead = NEXT(ctlr->rxhead, Nrx);
+
+ if((r->cs & (RCSfirst|RCSlast)) != (RCSfirst|RCSlast)) {
+ ctlr->nofirstlast++; /* partial packet */
+ freeb(b);
+ continue;
+ }
+ if(r->cs & RCSmacerr) {
+ freeb(b);
+ continue;
+ }
+
+ n = r->countsize >> 16; /* TODO includes 2 pad bytes? */
+ assert(n >= 2 && n < 2048);
+
+ /* clear any cached packet or part thereof */
+ l2cacheuinvse(b->rp, n+2);
+ cachedinvse(b->rp, n+2);
+ b->wp = b->rp + n;
+ /*
+ * skip hardware padding intended to align ipv4 address
+ * in memory (mv-s104860-u0 §8.3.4.1)
+ */
+ b->rp += 2;
+ etheriq(ether, b, 1);
+ etheractive(ether);
+ if (i % (Nrx / 2) == 0) {
+ rxreplenish(ctlr);
+ rxkick(ctlr);
+ }
+ }
+ rxreplenish(ctlr);
+ rxkick(ctlr);
+}
+
+static void
+txreplenish(Ether *ether) /* free transmitted packets */
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ while(ctlr->txtail != ctlr->txhead) {
+ /* ctlr->tx is uncached */
+ if(ctlr->tx[ctlr->txtail].cs & TCSdmaown)
+ break;
+ if(ctlr->txb[ctlr->txtail] == nil)
+ panic("no block for sent packet?!");
+ freeb(ctlr->txb[ctlr->txtail]);
+ ctlr->txb[ctlr->txtail] = nil;
+
+ ctlr->txtail = NEXT(ctlr->txtail, Ntx);
+ etheractive(ether);
+ }
+}
+
+/*
+ * transmit strategy: fill the output ring as far as possible,
+ * perhaps leaving a few spare; kick off the output and take
+ * an interrupt only when the transmit queue is empty.
+ */
+static void
+transmit(Ether *ether)
+{
+ int i, kick, len;
+ Block *b;
+ Ctlr *ctlr = ether->ctlr;
+ Gbereg *reg = ctlr->reg;
+ Tx *t;
+
+ ethercheck(ether);
+ ilock(ctlr);
+ txreplenish(ether); /* reap old packets */
+
+ /* queue new packets; use at most half the tx descs to avoid livelock */
+ kick = 0;
+ for (i = Ntx/2 - 2; i > 0; i--) {
+ t = &ctlr->tx[ctlr->txhead]; /* *t is uncached */
+ assert(((uintptr)t & (Descralign - 1)) == 0);
+ if(t->cs & TCSdmaown) { /* descriptor busy? */
+ ctlr->txringfull++;
+ break;
+ }
+
+ b = qget(ether->oq); /* outgoing packet? */
+ if (b == nil)
+ break;
+ len = BLEN(b);
+ if(len < ether->minmtu || len > ether->maxmtu) {
+ freeb(b);
+ continue;
+ }
+ ctlr->txb[ctlr->txhead] = b;
+
+ /* make sure the whole packet is in memory */
+ cachedwbse(b->rp, len);
+ l2cacheuwbse(b->rp, len);
+
+ /* set up the transmit descriptor */
+ t->buf = PADDR(b->rp);
+ t->countchk = len << 16;
+ coherence();
+
+ /* and fire */
+ t->cs = TCSpadding | TCSfirst | TCSlast | TCSdmaown |
+ TCSenableintr;
+ coherence();
+
+ kick++;
+ ctlr->txhead = NEXT(ctlr->txhead, Ntx);
+ }
+ if (kick) {
+ txkick(ctlr);
+
+ reg->irqmask |= Itxendq(Qno);
+ reg->irqemask |= IEtxerrq(Qno) | IEtxunderrun;
+ }
+ iunlock(ctlr);
+}
+
+static void
+dumprxdescs(Ctlr *ctlr)
+{
+ int i;
+ Gbereg *reg = ctlr->reg;
+
+ iprint("\nrxhead %d rxtail %d; txcdp %#p rxcdp %#p\n",
+ ctlr->rxhead, ctlr->rxtail, reg->tcqdp[Qno], reg->crdp[Qno].r);
+ for (i = 0; i < Nrx; i++) {
+ iprint("rxb %d @ %#p: %#p\n", i, &ctlr->rxb[i], ctlr->rxb[i]);
+ delay(50);
+ }
+ for (i = 0; i < Nrx; i++) {
+ iprint("rx %d @ %#p: cs %#lux countsize %lud buf %#lux next %#lux\n",
+ i, &ctlr->rx[i], ctlr->rx[i].cs,
+ ctlr->rx[i].countsize >> 3, ctlr->rx[i].buf,
+ ctlr->rx[i].next);
+ delay(50);
+ }
+ delay(1000);
+}
+
+static int
+gotinput(void* ctlr)
+{
+ return ((Ctlr*)ctlr)->haveinput != 0;
+}
+
+/*
+ * process any packets in the input ring.
+ * also sum mib stats frequently to avoid the overflow
+ * mentioned in the errata.
+ */
+static void
+rcvproc(void* arg)
+{
+ Ctlr *ctlr;
+ Ether *ether;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+ for(;;){
+ tsleep(&ctlr->rrendez, gotinput, ctlr, 10*1000);
+ ilock(ctlr);
+ getmibstats(ctlr);
+ if (ctlr->haveinput) {
+ ctlr->haveinput = 0;
+ iunlock(ctlr);
+ receive(ether);
+ } else
+ iunlock(ctlr);
+ }
+}
+
+static void
+interrupt(Ureg*, void *arg)
+{
+ ulong irq, irqe, handled;
+ Ether *ether = arg;
+ Ctlr *ctlr = ether->ctlr;
+ Gbereg *reg = ctlr->reg;
+
+ handled = 0;
+ irq = reg->irq;
+ irqe = reg->irqe;
+ reg->irqe = 0; /* extinguish intr causes */
+ reg->irq = 0; /* extinguish intr causes */
+ ethercheck(ether);
+
+ if(irq & (Irx | Irxbufferq(Qno))) {
+ /*
+ * letting a kproc process the input takes far less real time
+ * than doing it all at interrupt level.
+ */
+ ctlr->haveinput = 1;
+ wakeup(&ctlr->rrendez);
+ irq &= ~(Irx | Irxbufferq(Qno));
+ handled++;
+ } else
+ rxkick(ctlr);
+
+ if(irq & Itxendq(Qno)) { /* transmit ring empty? */
+ reg->irqmask &= ~Itxendq(Qno); /* prevent more interrupts */
+ reg->irqemask &= ~(IEtxerrq(Qno) | IEtxunderrun);
+ transmit(ether);
+ irq &= ~Itxendq(Qno);
+ handled++;
+ }
+
+ if(irqe & IEsum) {
+ /*
+ * IElinkchg appears to only be set when unplugging.
+ * autonegotiation is likely not done yet, so linkup not valid,
+ * thus we note the link change here, and check for
+ * that and autonegotiation done below.
+ */
+ if(irqe & IEphystschg) {
+ ether->link = (reg->ps0 & PS0linkup) != 0;
+ ether->linkchg = 1;
+ }
+ if(irqe & IEtxerrq(Qno))
+ ether->oerrs++;
+ if(irqe & IErxoverrun)
+ ether->overflows++;
+ if(irqe & IEtxunderrun)
+ ctlr->txunderrun++;
+ if(irqe & (IEphystschg | IEtxerrq(Qno) | IErxoverrun |
+ IEtxunderrun))
+ handled++;
+ }
+ if (irq & Isum) {
+ if (irq & Irxerr) { /* nil desc. ptr. or desc. owned by cpu */
+ ether->buffs++; /* approx. error */
+
+ /* if the input ring is full, drain it */
+ ctlr->haveinput = 1;
+ wakeup(&ctlr->rrendez);
+ }
+ if(irq & (Irxerr | Irxerrq(Qno)))
+ handled++;
+ irq &= ~(Irxerr | Irxerrq(Qno));
+ }
+
+ if(ether->linkchg && (reg->ps1 & PS1an_done)) {
+ handled++;
+ ether->link = (reg->ps0 & PS0linkup) != 0;
+ ether->linkchg = 0;
+ }
+ ctlr->newintrs++;
+
+ if (!handled) {
+ irq &= ~Isum;
+ irqe &= ~IEtxbufferq(Qno);
+ if (irq == 0 && irqe == 0) {
+ /* seems to be triggered by continuous output */
+ // iprint("ether1116: spurious interrupt\n");
+ } else
+ iprint("ether1116: interrupt cause unknown; "
+ "irq %#lux irqe %#lux\n", irq, irqe);
+ }
+ intrclear(Irqlo, ether->irq);
+}
+
+void
+promiscuous(void *arg, int on)
+{
+ Ether *ether = arg;
+ Ctlr *ctlr = ether->ctlr;
+ Gbereg *reg = ctlr->reg;
+
+ ilock(ctlr);
+ ether->prom = on;
+ if(on)
+ reg->portcfg |= PCFGupromisc;
+ else
+ reg->portcfg &= ~PCFGupromisc;
+ iunlock(ctlr);
+}
+
+void
+multicast(void *, uchar *, int)
+{
+ /* nothing to do; we always accept multicast */
+}
+
+static void quiesce(Gbereg *reg);
+
+static void
+shutdown(Ether *ether)
+{
+ int i;
+ Ctlr *ctlr = ether->ctlr;
+ Gbereg *reg = ctlr->reg;
+
+ ilock(ctlr);
+ quiesce(reg);
+ reg->euc |= Portreset;
+ coherence();
+ iunlock(ctlr);
+ delay(100);
+ ilock(ctlr);
+ reg->euc &= ~Portreset;
+ coherence();
+ delay(20);
+
+ reg->psc0 = 0; /* no PSC0porton */
+ reg->psc1 |= PSC1portreset;
+ coherence();
+ delay(50);
+ reg->psc1 &= ~PSC1portreset;
+ coherence();
+
+ for (i = 0; i < nelem(reg->tcqdp); i++)
+ reg->tcqdp[i] = 0;
+ for (i = 0; i < nelem(reg->crdp); i++)
+ reg->crdp[i].r = 0;
+ coherence();
+
+ iunlock(ctlr);
+}
+
+enum {
+ CMjumbo,
+};
+
+static Cmdtab ctlmsg[] = {
+ CMjumbo, "jumbo", 2,
+};
+
+long
+ctl(Ether *e, void *p, long n)
+{
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ Ctlr *ctlr = e->ctlr;
+ Gbereg *reg = ctlr->reg;
+
+ cb = parsecmd(p, n);
+ if(waserror()) {
+ free(cb);
+ nexterror();
+ }
+
+ ct = lookupcmd(cb, ctlmsg, nelem(ctlmsg));
+ switch(ct->index) {
+ case CMjumbo:
+ if(strcmp(cb->f[1], "on") == 0) {
+ /* incoming packet queue doesn't expect jumbo frames */
+ error("jumbo disabled");
+ reg->psc0 = (reg->psc0 & ~PSC0mrumask) |
+ PSC0mru(PSC0mru9022);
+ e->maxmtu = 9022;
+ } else if(strcmp(cb->f[1], "off") == 0) {
+ reg->psc0 = (reg->psc0 & ~PSC0mrumask) |
+ PSC0mru(PSC0mru1522);
+ e->maxmtu = ETHERMAXTU;
+ } else
+ error(Ebadctl);
+ break;
+ default:
+ error(Ebadctl);
+ break;
+ }
+ free(cb);
+ poperror();
+ return n;
+}
+
+/*
+ * phy/mii goo
+ */
+
+static int
+smibusywait(Gbereg *reg, ulong waitbit)
+{
+ ulong timeout, smi_reg;
+
+ timeout = PhysmiTimeout;
+ /* wait till the SMI is not busy */
+ do {
+ /* read smi register */
+ smi_reg = reg->smi;
+ if (timeout-- == 0) {
+ MIIDBG("SMI busy timeout\n");
+ return -1;
+ }
+// delay(1);
+ } while (smi_reg & waitbit);
+ return 0;
+}
+
+static int
+miird(Mii *mii, int pa, int ra)
+{
+ ulong smi_reg, timeout;
+ Gbereg *reg;
+
+ reg = ((Ctlr*)mii->ctlr)->reg;
+
+ /* check params */
+ if ((pa<<Physmiaddroff) & ~Physmiaddrmask ||
+ (ra<<SmiRegaddroff) & ~SmiRegaddrmask)
+ return -1;
+
+ smibusywait(reg, PhysmiBusy);
+
+ /* fill the phy address and register offset and read opcode */
+ reg->smi = pa << Physmiaddroff | ra << SmiRegaddroff | PhysmiopRd;
+ coherence();
+
+ /* wait til read value is ready */
+ timeout = PhysmiTimeout;
+ do {
+ smi_reg = reg->smi;
+ if (timeout-- == 0) {
+ MIIDBG("SMI read-valid timeout\n");
+ return -1;
+ }
+ } while (!(smi_reg & PhysmiReadok));
+
+ /* Wait for the data to update in the SMI register */
+ for (timeout = 0; timeout < PhysmiTimeout; timeout++)
+ ;
+ return reg->smi & Physmidatamask;
+}
+
+static int
+miiwr(Mii *mii, int pa, int ra, int v)
+{
+ Gbereg *reg;
+ ulong smi_reg;
+
+ reg = ((Ctlr*)mii->ctlr)->reg;
+
+ /* check params */
+ if (((pa<<Physmiaddroff) & ~Physmiaddrmask) ||
+ ((ra<<SmiRegaddroff) & ~SmiRegaddrmask))
+ return -1;
+
+ smibusywait(reg, PhysmiBusy);
+
+ /* fill the phy address and register offset and read opcode */
+ smi_reg = v << Physmidataoff | pa << Physmiaddroff | ra << SmiRegaddroff;
+ reg->smi = smi_reg & ~PhysmiopRd;
+ coherence();
+ return 0;
+}
+
+#define MIIMODEL(idr2) (((idr2) >> 4) & MASK(6))
+
+enum {
+ Hacknone,
+ Hackdual,
+
+ Ouimarvell = 0x005043,
+
+ /* idr2 mii/phy model numbers */
+ Phy1000 = 0x00, /* 88E1000 Gb */
+ Phy1011 = 0x02, /* 88E1011 Gb */
+ Phy1000_3 = 0x03, /* 88E1000 Gb */
+ Phy1000s = 0x04, /* 88E1000S Gb */
+ Phy1000_5 = 0x05, /* 88E1000 Gb */
+ Phy1000_6 = 0x06, /* 88E1000 Gb */
+ Phy3082 = 0x08, /* 88E3082 10/100 */
+ Phy1112 = 0x09, /* 88E1112 Gb */
+ Phy1121r = 0x0b, /* says the 1121r manual */
+ Phy1149 = 0x0b, /* 88E1149 Gb */
+ Phy1111 = 0x0c, /* 88E1111 Gb */
+ Phy1116 = 0x21, /* 88E1116 Gb */
+ Phy1116r = 0x24, /* 88E1116R Gb */
+ Phy1118 = 0x22, /* 88E1118 Gb */
+ Phy3016 = 0x26, /* 88E3016 10/100 */
+};
+
+static int hackflavour;
+
+/*
+ * on openrd, ether0's phy has address 8, ether1's is ether0's 24.
+ * on guruplug, ether0's is phy 0 and ether1's is ether0's phy 1.
+ */
+int
+mymii(Mii* mii, int mask)
+{
+ Ctlr *ctlr;
+ MiiPhy *miiphy;
+ int bit, ctlrno, oui, model, phyno, r, rmask;
+ static int dualport, phyidx;
+ static int phynos[NMiiPhy];
+
+ ctlr = mii->ctlr;
+ ctlrno = ctlr->ether->ctlrno;
+
+ /* first pass: figure out what kind of phy(s) we have. */
+ dualport = 0;
+ if (ctlrno == 0) {
+ for(phyno = 0; phyno < NMiiPhy; phyno++){
+ bit = 1<<phyno;
+ if(!(mask & bit) || mii->mask & bit)
+ continue;
+ if(mii->mir(mii, phyno, Bmsr) == -1)
+ continue;
+ r = mii->mir(mii, phyno, Phyidr1);
+ oui = (r & 0x3FFF)<<6;
+ r = mii->mir(mii, phyno, Phyidr2);
+ oui |= r>>10;
+ model = MIIMODEL(r);
+ if (oui == 0xfffff && model == 0x3f)
+ continue;
+ MIIDBG("ctlrno %d phy %d oui %#ux model %#ux\n",
+ ctlrno, phyno, oui, model);
+ if (oui == Ouimarvell &&
+ (model == Phy1121r || model == Phy1116r))
+ ++dualport;
+ phynos[phyidx++] = phyno;
+ }
+ hackflavour = dualport == 2 && phyidx == 2? Hackdual: Hacknone;
+ MIIDBG("ether1116: %s-port phy\n",
+ hackflavour == Hackdual? "dual": "single");
+ }
+
+ /*
+ * Probe through mii for PHYs in mask;
+ * return the mask of those found in the current probe.
+ * If the PHY has not already been probed, update
+ * the Mii information.
+ */
+ rmask = 0;
+ if (hackflavour == Hackdual && ctlrno < phyidx) {
+ /*
+ * openrd, guruplug or the like: use ether0's phys.
+ * this is a nasty hack, but so is the hardware.
+ */
+ MIIDBG("ctlrno %d using ctlrno 0's phyno %d\n",
+ ctlrno, phynos[ctlrno]);
+ ctlr->mii = mii = ctlrs[0]->mii;
+ mask = 1 << phynos[ctlrno];
+ mii->mask = ~mask;
+ }
+ for(phyno = 0; phyno < NMiiPhy; phyno++){
+ bit = 1<<phyno;
+ if(!(mask & bit))
+ continue;
+ if(mii->mask & bit){
+ rmask |= bit;
+ continue;
+ }
+ if(mii->mir(mii, phyno, Bmsr) == -1)
+ continue;
+ r = mii->mir(mii, phyno, Phyidr1);
+ oui = (r & 0x3FFF)<<6;
+ r = mii->mir(mii, phyno, Phyidr2);
+ oui |= r>>10;
+ if(oui == 0xFFFFF || oui == 0)
+ continue;
+
+ if((miiphy = malloc(sizeof(MiiPhy))) == nil)
+ continue;
+ miiphy->mii = mii;
+ miiphy->oui = oui;
+ miiphy->phyno = phyno;
+
+ miiphy->anar = ~0;
+ miiphy->fc = ~0;
+ miiphy->mscr = ~0;
+
+ mii->phy[phyno] = miiphy;
+ if(ctlrno == 0 || hackflavour != Hackdual && mii->curphy == nil)
+ mii->curphy = miiphy;
+ mii->mask |= bit;
+ mii->nphy++;
+
+ rmask |= bit;
+ }
+ return rmask;
+}
+
+static int
+kirkwoodmii(Ether *ether)
+{
+ int i;
+ Ctlr *ctlr;
+ MiiPhy *phy;
+
+ MIIDBG("mii\n");
+ ctlr = ether->ctlr;
+ if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+ return -1;
+ ctlr->mii->ctlr = ctlr;
+ ctlr->mii->mir = miird;
+ ctlr->mii->miw = miiwr;
+
+ if(mymii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
+ print("#l%d: ether1116: init mii failure\n", ether->ctlrno);
+ free(ctlr->mii);
+ ctlr->mii = nil;
+ return -1;
+ }
+
+ /* oui 005043 is marvell */
+ MIIDBG("oui %#X phyno %d\n", phy->oui, phy->phyno);
+ // TODO: does this make sense? shouldn't each phy be initialised?
+ if((ctlr->ether->ctlrno == 0 || hackflavour != Hackdual) &&
+ miistatus(ctlr->mii) < 0){
+ miireset(ctlr->mii);
+ MIIDBG("miireset\n");
+ if(miiane(ctlr->mii, ~0, 0, ~0) < 0){
+ iprint("miiane failed\n");
+ return -1;
+ }
+ MIIDBG("miistatus\n");
+ miistatus(ctlr->mii);
+ if(miird(ctlr->mii, phy->phyno, Bmsr) & BmsrLs){
+ for(i = 0; ; i++){
+ if(i > 600){
+ iprint("ether1116: autonegotiation failed\n");
+ break;
+ }
+ if(miird(ctlr->mii, phy->phyno, Bmsr) & BmsrAnc)
+ break;
+ delay(10);
+ }
+ if(miistatus(ctlr->mii) < 0)
+ iprint("miistatus failed\n");
+ }else{
+ iprint("ether1116: no link\n");
+ phy->speed = 10; /* simple default */
+ }
+ }
+
+ ether->mbps = phy->speed;
+ MIIDBG("#l%d: kirkwoodmii: fd %d speed %d tfc %d rfc %d\n",
+ ctlr->port, phy->fd, phy->speed, phy->tfc, phy->rfc);
+ MIIDBG("mii done\n");
+ return 0;
+}
+
+enum { /* PHY register pages */
+ Pagcopper,
+ Pagfiber,
+ Pagrgmii,
+ Pagled,
+ Pagrsvd1,
+ Pagvct,
+ Pagtest,
+ Pagrsvd2,
+ Pagfactest,
+};
+
+static void
+miiregpage(Mii *mii, ulong dev, ulong page)
+{
+ miiwr(mii, dev, Eadr, page);
+}
+
+static int
+miiphyinit(Mii *mii)
+{
+ ulong dev;
+ Ctlr *ctlr;
+ Gbereg *reg;
+
+ ctlr = (Ctlr*)mii->ctlr;
+ reg = ctlr->reg;
+ dev = reg->phy;
+ MIIDBG("phy dev addr %lux\n", dev);
+
+ /* leds link & activity */
+ miiregpage(mii, dev, Pagled);
+ /* low 4 bits == 1: on - link, blink - activity, off - no link */
+ miiwr(mii, dev, Scr, (miird(mii, dev, Scr) & ~0xf) | 1);
+
+ miiregpage(mii, dev, Pagrgmii);
+ miiwr(mii, dev, Scr, miird(mii, dev, Scr) | Rgmiipwrup);
+ /* must now do a software reset, says the manual */
+ miireset(ctlr->mii);
+
+ /* enable RGMII delay on Tx and Rx for CPU port */
+ miiwr(mii, dev, Recr, miird(mii, dev, Recr) | Rxtiming | Rxtiming);
+ /* must now do a software reset, says the manual */
+ miireset(ctlr->mii);
+
+ miiregpage(mii, dev, Pagcopper);
+ miiwr(mii, dev, Scr,
+ (miird(mii, dev, Scr) & ~(Pwrdown|Endetect)) | Mdix);
+
+ return 0;
+}
+
+/*
+ * initialisation
+ */
+
+static void
+quiesce(Gbereg *reg)
+{
+ ulong v;
+
+ v = reg->tqc;
+ if (v & 0xFF)
+ reg->tqc = v << 8; /* stop active channels */
+ v = reg->rqc;
+ if (v & 0xFF)
+ reg->rqc = v << 8; /* stop active channels */
+ /* wait for all queues to stop */
+ while (reg->tqc & 0xFF || reg->rqc & 0xFF)
+ ;
+}
+
+static void
+p16(uchar *p, ulong v) /* convert big-endian short to bytes */
+{
+ *p++ = v>>8;
+ *p = v;
+}
+
+static void
+p32(uchar *p, ulong v) /* convert big-endian long to bytes */
+{
+ *p++ = v>>24;
+ *p++ = v>>16;
+ *p++ = v>>8;
+ *p = v;
+}
+
+/*
+ * set ether->ea from hw mac address,
+ * configure unicast filtering to accept it.
+ */
+void
+archetheraddr(Ether *ether, Gbereg *reg, int rxqno)
+{
+ uchar *ea;
+ ulong nibble, ucreg, tbloff, regoff;
+
+ ea = ether->ea;
+ p32(ea, reg->macah);
+ p16(ea+4, reg->macal);
+ if (memcmp(ea, zeroea, sizeof zeroea) == 0 && ether->ctlrno > 0) {
+ /* hack: use ctlr[0]'s + ctlrno */
+ memmove(ea, ctlrs[0]->ether->ea, Eaddrlen);
+ ea[Eaddrlen-1] += ether->ctlrno;
+ reg->macah = ea[0] << 24 | ea[1] << 16 | ea[2] << 8 | ea[3];
+ reg->macal = ea[4] << 8 | ea[5];
+ coherence();
+ }
+
+ /* accept frames on ea */
+ nibble = ea[5] & 0xf;
+ tbloff = nibble / 4;
+ regoff = nibble % 4;
+
+ regoff *= 8;
+ ucreg = reg->dfut[tbloff] & (0xff << regoff);
+ ucreg |= (rxqno << 1 | Pass) << regoff;
+ reg->dfut[tbloff] = ucreg;
+
+ /* accept all multicast too. set up special & other tables. */
+ memset(reg->dfsmt, Qno<<1 | Pass, sizeof reg->dfsmt);
+ memset(reg->dfomt, Qno<<1 | Pass, sizeof reg->dfomt);
+ coherence();
+}
+
+static void
+cfgdramacc(Gbereg *reg)
+{
+ memset(reg->harr, 0, sizeof reg->harr);
+ memset(reg->base, 0, sizeof reg->base);
+
+ reg->bare = MASK(6) - MASK(2); /* disable wins 2-5 */
+ /* this doesn't make any sense, but it's required */
+ reg->epap = 3 << 2 | 3; /* full access for wins 0 & 1 */
+// reg->epap = 0; /* no access on access violation for all wins */
+ coherence();
+
+ reg->base[0].base = PHYSDRAM | WINATTR(Attrcs0) | Targdram;
+ reg->base[0].size = WINSIZE(256*MB);
+ reg->base[1].base = (PHYSDRAM + 256*MB) | WINATTR(Attrcs1) | Targdram;
+ reg->base[1].size = WINSIZE(256*MB);
+ coherence();
+}
+
+static void
+ctlralloc(Ctlr *ctlr)
+{
+ int i;
+ Block *b;
+ Rx *r;
+ Tx *t;
+
+ ilock(&freeblocks);
+ for(i = 0; i < Nrxblks; i++) {
+ b = iallocb(Rxblklen+Bufalign-1);
+ if(b == nil) {
+ iprint("ether1116: no memory for rx buffers\n");
+ break;
+ }
+ assert(b->ref == 1);
+ b->wp = b->rp = (uchar*)
+ ((uintptr)(b->lim - Rxblklen) & ~(Bufalign - 1));
+ assert(((uintptr)b->rp & (Bufalign - 1)) == 0);
+ b->free = rxfreeb;
+ b->next = freeblocks.head;
+ freeblocks.head = b;
+ }
+ iunlock(&freeblocks);
+
+ /*
+ * allocate uncached rx ring descriptors because rings are shared
+ * with the ethernet controller and more than one fits in a cache line.
+ */
+ ctlr->rx = ucallocalign(Nrx * sizeof(Rx), Descralign, 0);
+ if(ctlr->rx == nil)
+ panic("ether1116: no memory for rx ring");
+ for(i = 0; i < Nrx; i++) {
+ r = &ctlr->rx[i];
+ assert(((uintptr)r & (Descralign - 1)) == 0);
+ r->cs = 0; /* owned by software until r->buf is non-nil */
+ r->buf = 0;
+ r->next = PADDR(&ctlr->rx[NEXT(i, Nrx)]);
+ ctlr->rxb[i] = nil;
+ }
+ ctlr->rxtail = ctlr->rxhead = 0;
+ rxreplenish(ctlr);
+
+ /* allocate uncached tx ring descriptors */
+ ctlr->tx = ucallocalign(Ntx * sizeof(Tx), Descralign, 0);
+ if(ctlr->tx == nil)
+ panic("ether1116: no memory for tx ring");
+ for(i = 0; i < Ntx; i++) {
+ t = &ctlr->tx[i];
+ assert(((uintptr)t & (Descralign - 1)) == 0);
+ t->cs = 0;
+ t->buf = 0;
+ t->next = PADDR(&ctlr->tx[NEXT(i, Ntx)]);
+ ctlr->txb[i] = nil;
+ }
+ ctlr->txtail = ctlr->txhead = 0;
+}
+
+static void
+ctlrinit(Ether *ether)
+{
+ int i;
+ Ctlr *ctlr = ether->ctlr;
+ Gbereg *reg = ctlr->reg;
+ static char name[KNAMELEN];
+ static Ctlr fakectlr; /* bigger than 4K; keep off the stack */
+
+ for (i = 0; i < nelem(reg->tcqdp); i++)
+ reg->tcqdp[i] = 0;
+ for (i = 0; i < nelem(reg->crdp); i++)
+ reg->crdp[i].r = 0;
+ coherence();
+
+ cfgdramacc(reg);
+ ctlralloc(ctlr);
+
+ reg->tcqdp[Qno] = PADDR(&ctlr->tx[ctlr->txhead]);
+ reg->crdp[Qno].r = PADDR(&ctlr->rx[ctlr->rxhead]);
+ coherence();
+
+// dumprxdescs(ctlr);
+
+ /* clear stats by reading them into fake ctlr */
+ getmibstats(&fakectlr);
+
+ reg->pxmfs = MFS40by; /* allow runts in */
+
+ /*
+ * ipg's (inter packet gaps) for interrupt coalescing,
+ * values in units of 64 clock cycles. A full-sized
+ * packet (1514 bytes) takes just over 12µs to transmit.
+ */
+ if (CLOCKFREQ/(Maxrxintrsec*64) >= (1<<16))
+ panic("rx coalescing value %d too big for short",
+ CLOCKFREQ/(Maxrxintrsec*64));
+ reg->sdc = SDCrifb | SDCrxburst(Burst16) | SDCtxburst(Burst16) |
+ SDCrxnobyteswap | SDCtxnobyteswap |
+ SDCipgintrx(CLOCKFREQ/(Maxrxintrsec*64));
+ reg->pxtfut = 0; /* TFUTipginttx(CLOCKFREQ/(Maxrxintrsec*64)) */
+
+ /* allow just these interrupts */
+ /* guruplug generates Irxerr interrupts continually */
+ reg->irqmask = Isum | Irx | Irxbufferq(Qno) | Irxerr | Itxendq(Qno);
+ reg->irqemask = IEsum | IEtxerrq(Qno) | IEphystschg | IErxoverrun |
+ IEtxunderrun;
+
+ reg->irqe = 0;
+ reg->euirqmask = 0;
+ coherence();
+ reg->irq = 0;
+ reg->euirq = 0;
+ /* send errors to end of memory */
+// reg->euda = PHYSDRAM + 512*MB - 8*1024;
+ reg->euda = 0;
+ reg->eudid = Attrcs1 << 4 | Targdram;
+
+// archetheraddr(ether, ctlr->reg, Qno); /* 2nd location */
+
+ reg->portcfg = Rxqdefault(Qno) | Rxqarp(Qno);
+ reg->portcfgx = 0;
+ coherence();
+
+ /*
+ * start the controller running.
+ * turn the port on, kick the receiver.
+ */
+
+ reg->psc1 = PSC1rgmii | PSC1encolonbp | PSC1coldomlim(0x23);
+ /* do this only when the controller is quiescent */
+ reg->psc0 = PSC0porton | PSC0an_flctloff |
+ PSC0an_pauseadv | PSC0nofrclinkdown | PSC0mru(PSC0mru1522);
+ coherence();
+ for (i = 0; i < 4000; i++) /* magic delay */
+ ;
+
+ ether->link = (reg->ps0 & PS0linkup) != 0;
+
+ /* set ethernet MTU for leaky bucket mechanism to 0 (disabled) */
+ reg->pmtu = 0;
+ etheractive(ether);
+
+ snprint(name, sizeof name, "#l%drproc", ether->ctlrno);
+ kproc(name, rcvproc, ether);
+
+ reg->rqc = Rxqon(Qno);
+ coherence();
+}
+
+static void
+attach(Ether* ether)
+{
+ Ctlr *ctlr = ether->ctlr;
+
+ lock(&ctlr->initlock);
+ if(ctlr->init == 0) {
+ ctlrinit(ether);
+ ctlr->init = 1;
+ }
+ unlock(&ctlr->initlock);
+}
+
+/*
+ * statistics goo.
+ * mib registers clear on read.
+ */
+
+static void
+getmibstats(Ctlr *ctlr)
+{
+ Gbereg *reg = ctlr->reg;
+
+ /*
+ * Marvell 88f6281 errata FE-ETH-120: high long of rxby and txby
+ * can't be read correctly, so read the low long frequently
+ * (every 30 seconds or less), thus avoiding overflow into high long.
+ */
+ ctlr->rxby += reg->rxbylo;
+ ctlr->txby += reg->txbylo;
+
+ ctlr->badrxby += reg->badrxby;
+ ctlr->mactxerr += reg->mactxerr;
+ ctlr->rxpkt += reg->rxpkt;
+ ctlr->badrxpkt += reg->badrxpkt;
+ ctlr->rxbcastpkt+= reg->rxbcastpkt;
+ ctlr->rxmcastpkt+= reg->rxmcastpkt;
+ ctlr->rx64 += reg->rx64;
+ ctlr->rx65_127 += reg->rx65_127;
+ ctlr->rx128_255 += reg->rx128_255;
+ ctlr->rx256_511 += reg->rx256_511;
+ ctlr->rx512_1023+= reg->rx512_1023;
+ ctlr->rx1024_max+= reg->rx1024_max;
+ ctlr->txpkt += reg->txpkt;
+ ctlr->txcollpktdrop+= reg->txcollpktdrop;
+ ctlr->txmcastpkt+= reg->txmcastpkt;
+ ctlr->txbcastpkt+= reg->txbcastpkt;
+ ctlr->badmacctlpkts+= reg->badmacctlpkts;
+ ctlr->txflctl += reg->txflctl;
+ ctlr->rxflctl += reg->rxflctl;
+ ctlr->badrxflctl+= reg->badrxflctl;
+ ctlr->rxundersized+= reg->rxundersized;
+ ctlr->rxfrags += reg->rxfrags;
+ ctlr->rxtoobig += reg->rxtoobig;
+ ctlr->rxjabber += reg->rxjabber;
+ ctlr->rxerr += reg->rxerr;
+ ctlr->crcerr += reg->crcerr;
+ ctlr->collisions+= reg->collisions;
+ ctlr->latecoll += reg->latecoll;
+}
+
+long
+ifstat(Ether *ether, void *a, long n, ulong off)
+{
+ Ctlr *ctlr = ether->ctlr;
+ Gbereg *reg = ctlr->reg;
+ char *buf, *p, *e;
+
+ buf = p = malloc(READSTR);
+ e = p + READSTR;
+
+ ilock(ctlr);
+ getmibstats(ctlr);
+
+ ctlr->intrs += ctlr->newintrs;
+ p = seprint(p, e, "interrupts: %lud\n", ctlr->intrs);
+ p = seprint(p, e, "new interrupts: %lud\n", ctlr->newintrs);
+ ctlr->newintrs = 0;
+ p = seprint(p, e, "tx underrun: %lud\n", ctlr->txunderrun);
+ p = seprint(p, e, "tx ring full: %lud\n", ctlr->txringfull);
+
+ ctlr->rxdiscard += reg->pxdfc;
+ ctlr->rxoverrun += reg->pxofc;
+ p = seprint(p, e, "rx discarded frames: %lud\n", ctlr->rxdiscard);
+ p = seprint(p, e, "rx overrun frames: %lud\n", ctlr->rxoverrun);
+ p = seprint(p, e, "no first+last flag: %lud\n", ctlr->nofirstlast);
+
+ p = seprint(p, e, "duplex: %s\n", (reg->ps0 & PS0fd)? "full": "half");
+ p = seprint(p, e, "flow control: %s\n", (reg->ps0 & PS0flctl)? "on": "off");
+ /* p = seprint(p, e, "speed: %d mbps\n", ); */
+
+ p = seprint(p, e, "received bytes: %llud\n", ctlr->rxby);
+ p = seprint(p, e, "bad received bytes: %lud\n", ctlr->badrxby);
+ p = seprint(p, e, "internal mac transmit errors: %lud\n", ctlr->mactxerr);
+ p = seprint(p, e, "total received frames: %lud\n", ctlr->rxpkt);
+ p = seprint(p, e, "received broadcast frames: %lud\n", ctlr->rxbcastpkt);
+ p = seprint(p, e, "received multicast frames: %lud\n", ctlr->rxmcastpkt);
+ p = seprint(p, e, "bad received frames: %lud\n", ctlr->badrxpkt);
+ p = seprint(p, e, "received frames 0-64: %lud\n", ctlr->rx64);
+ p = seprint(p, e, "received frames 65-127: %lud\n", ctlr->rx65_127);
+ p = seprint(p, e, "received frames 128-255: %lud\n", ctlr->rx128_255);
+ p = seprint(p, e, "received frames 256-511: %lud\n", ctlr->rx256_511);
+ p = seprint(p, e, "received frames 512-1023: %lud\n", ctlr->rx512_1023);
+ p = seprint(p, e, "received frames 1024-max: %lud\n", ctlr->rx1024_max);
+ p = seprint(p, e, "transmitted bytes: %llud\n", ctlr->txby);
+ p = seprint(p, e, "total transmitted frames: %lud\n", ctlr->txpkt);
+ p = seprint(p, e, "transmitted broadcast frames: %lud\n", ctlr->txbcastpkt);
+ p = seprint(p, e, "transmitted multicast frames: %lud\n", ctlr->txmcastpkt);
+ p = seprint(p, e, "transmit frames dropped by collision: %lud\n", ctlr->txcollpktdrop);
+ p = seprint(p, e, "misaligned buffers: %lud\n", ether->pktsmisaligned);
+
+ p = seprint(p, e, "bad mac control frames: %lud\n", ctlr->badmacctlpkts);
+ p = seprint(p, e, "transmitted flow control messages: %lud\n", ctlr->txflctl);
+ p = seprint(p, e, "received flow control messages: %lud\n", ctlr->rxflctl);
+ p = seprint(p, e, "bad received flow control messages: %lud\n", ctlr->badrxflctl);
+ p = seprint(p, e, "received undersized packets: %lud\n", ctlr->rxundersized);
+ p = seprint(p, e, "received fragments: %lud\n", ctlr->rxfrags);
+ p = seprint(p, e, "received oversized packets: %lud\n", ctlr->rxtoobig);
+ p = seprint(p, e, "received jabber packets: %lud\n", ctlr->rxjabber);
+ p = seprint(p, e, "mac receive errors: %lud\n", ctlr->rxerr);
+ p = seprint(p, e, "crc errors: %lud\n", ctlr->crcerr);
+ p = seprint(p, e, "collisions: %lud\n", ctlr->collisions);
+ p = seprint(p, e, "late collisions: %lud\n", ctlr->latecoll);
+ USED(p);
+ iunlock(ctlr);
+
+ n = readstr(off, a, n, buf);
+ free(buf);
+ return n;
+}
+
+
+static int
+reset(Ether *ether)
+{
+ Ctlr *ctlr;
+
+ ether->ctlr = ctlr = malloc(sizeof *ctlr);
+ switch(ether->ctlrno) {
+ case 0:
+ ether->irq = IRQ0gbe0sum;
+ break;
+ case 1:
+ ether->irq = IRQ0gbe1sum;
+ break;
+ default:
+ panic("ether1116: bad ether ctlr #%d", ether->ctlrno);
+ }
+ ctlr->reg = (Gbereg*)soc.ether[ether->ctlrno];
+
+ /* need this for guruplug, at least */
+ *(ulong *)soc.iocfg |= 1 << 7 | 1 << 15; /* io cfg 0: 1.8v gbe */
+ coherence();
+
+ ctlr->ether = ether;
+ ctlrs[ether->ctlrno] = ctlr;
+
+ shutdown(ether);
+ /* ensure that both interfaces are set to RGMII before calling mii */
+ ((Gbereg*)soc.ether[0])->psc1 |= PSC1rgmii;
+ ((Gbereg*)soc.ether[1])->psc1 |= PSC1rgmii;
+ coherence();
+
+ /* Set phy address of the port */
+ ctlr->port = ether->ctlrno;
+ ctlr->reg->phy = ether->ctlrno;
+ coherence();
+ ether->port = (uintptr)ctlr->reg;
+
+ if(kirkwoodmii(ether) < 0){
+ free(ctlr);
+ ether->ctlr = nil;
+ return -1;
+ }
+ miiphyinit(ctlr->mii);
+ archetheraddr(ether, ctlr->reg, Qno); /* original location */
+ if (memcmp(ether->ea, zeroea, sizeof zeroea) == 0){
+iprint("ether1116: reset: zero ether->ea\n");
+ free(ctlr);
+ ether->ctlr = nil;
+ return -1; /* no rj45 for this ether */
+ }
+
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->ifstat = ifstat;
+ ether->shutdown = shutdown;
+ ether->ctl = ctl;
+
+ ether->arg = ether;
+ ether->promiscuous = promiscuous;
+ ether->multicast = multicast;
+ return 0;
+}
+
+void
+ether1116link(void)
+{
+ addethercard("88e1116", reset);
+}
diff --git a/sys/src/9/kw/etherif.h b/sys/src/9/kw/etherif.h
new file mode 100755
index 000000000..35d131fe3
--- /dev/null
+++ b/sys/src/9/kw/etherif.h
@@ -0,0 +1,55 @@
+enum
+{
+ MaxEther = 2,
+ Ntypes = 8,
+};
+
+typedef struct Ether Ether;
+struct Ether {
+ RWlock; /* TO DO */
+ ISAConf; /* hardware info */
+ int ctlrno;
+ int minmtu;
+ int maxmtu;
+ uchar ea[Eaddrlen];
+ void *address;
+ int tbusy;
+
+ void (*attach)(Ether*); /* filled in by reset routine */
+ void (*closed)(Ether*);
+ void (*detach)(Ether*);
+ void (*transmit)(Ether*);
+ void (*interrupt)(Ureg*, void*);
+ long (*ifstat)(Ether*, void*, long, ulong);
+ long (*ctl)(Ether*, void*, long); /* custom ctl messages */
+ void (*power)(Ether*, int); /* power on/off */
+ void (*shutdown)(Ether*); /* shutdown hardware before reboot */
+ void *ctlr;
+ int pcmslot; /* PCMCIA */
+ int fullduplex; /* non-zero if full duplex */
+ int linkchg; /* link status changed? */
+ uvlong starttime; /* last activity time */
+
+ Queue* oq;
+
+ /* statistics */
+ ulong interrupts;
+ ulong dmarxintr;
+ ulong dmatxintr;
+ ulong promisc;
+ ulong pktsdropped;
+ ulong pktsmisaligned;
+ ulong resets; /* after initialisation */
+ ulong bcasts; /* broadcast pkts rcv'd */
+ ulong mcasts; /* multicast pkts rcv'd */
+
+ Netif;
+};
+
+extern Block* etheriq(Ether*, Block*, int);
+extern void addethercard(char*, int(*)(Ether*));
+extern ulong ethercrc(uchar*, int);
+extern int parseether(uchar*, char*);
+
+#define NEXT(x, l) (((x)+1)%(l))
+#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
diff --git a/sys/src/9/kw/ethermii.c b/sys/src/9/kw/ethermii.c
new file mode 100755
index 000000000..90b219b3f
--- /dev/null
+++ b/sys/src/9/kw/ethermii.c
@@ -0,0 +1,235 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+int
+mii(Mii* mii, int mask)
+{
+ MiiPhy *miiphy;
+ int bit, oui, phyno, r, rmask;
+
+ /*
+ * Probe through mii for PHYs in mask;
+ * return the mask of those found in the current probe.
+ * If the PHY has not already been probed, update
+ * the Mii information.
+ */
+ rmask = 0;
+ for(phyno = 0; phyno < NMiiPhy; phyno++){
+ bit = 1<<phyno;
+ if(!(mask & bit))
+ continue;
+ if(mii->mask & bit){
+ rmask |= bit;
+ continue;
+ }
+ if(mii->mir(mii, phyno, Bmsr) == -1)
+ continue;
+ r = mii->mir(mii, phyno, Phyidr1);
+ oui = (r & 0x3FFF)<<6;
+ r = mii->mir(mii, phyno, Phyidr2);
+ oui |= r>>10;
+ if(oui == 0xFFFFF || oui == 0)
+ continue;
+
+ if((miiphy = malloc(sizeof(MiiPhy))) == nil)
+ continue;
+
+ miiphy->mii = mii;
+ miiphy->oui = oui;
+ miiphy->phyno = phyno;
+
+ miiphy->anar = ~0;
+ miiphy->fc = ~0;
+ miiphy->mscr = ~0;
+
+ mii->phy[phyno] = miiphy;
+ if(mii->curphy == nil)
+ mii->curphy = miiphy;
+ mii->mask |= bit;
+ mii->nphy++;
+
+ rmask |= bit;
+ }
+ return rmask;
+}
+
+int
+miimir(Mii* mii, int r)
+{
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ return mii->mir(mii, mii->curphy->phyno, r);
+}
+
+int
+miimiw(Mii* mii, int r, int data)
+{
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ return mii->miw(mii, mii->curphy->phyno, r, data);
+}
+
+int
+miireset(Mii* mii)
+{
+ int bmcr;
+
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
+ bmcr |= BmcrR;
+ mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
+ microdelay(1);
+
+ return 0;
+}
+
+int
+miiane(Mii* mii, int a, int p, int e)
+{
+ int anar, bmsr, mscr, r, phyno;
+
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ phyno = mii->curphy->phyno;
+
+ bmsr = mii->mir(mii, phyno, Bmsr);
+ if(!(bmsr & BmsrAna))
+ return -1;
+
+ if(a != ~0)
+ anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
+ else if(mii->curphy->anar != ~0)
+ anar = mii->curphy->anar;
+ else{
+ anar = mii->mir(mii, phyno, Anar);
+ anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
+ if(bmsr & Bmsr10THD)
+ anar |= Ana10HD;
+ if(bmsr & Bmsr10TFD)
+ anar |= Ana10FD;
+ if(bmsr & Bmsr100TXHD)
+ anar |= AnaTXHD;
+ if(bmsr & Bmsr100TXFD)
+ anar |= AnaTXFD;
+ }
+ mii->curphy->anar = anar;
+
+ if(p != ~0)
+ anar |= (AnaAP|AnaP) & p;
+ else if(mii->curphy->fc != ~0)
+ anar |= mii->curphy->fc;
+ mii->curphy->fc = (AnaAP|AnaP) & anar;
+
+ if(bmsr & BmsrEs){
+ mscr = mii->mir(mii, phyno, Mscr);
+ mscr &= ~(Mscr1000TFD|Mscr1000THD);
+ if(e != ~0)
+ mscr |= (Mscr1000TFD|Mscr1000THD) & e;
+ else if(mii->curphy->mscr != ~0)
+ mscr = mii->curphy->mscr;
+ else{
+ r = mii->mir(mii, phyno, Esr);
+ if(r & Esr1000THD)
+ mscr |= Mscr1000THD;
+ if(r & Esr1000TFD)
+ mscr |= Mscr1000TFD;
+ }
+ mii->curphy->mscr = mscr;
+ mii->miw(mii, phyno, Mscr, mscr);
+ }
+ mii->miw(mii, phyno, Anar, anar);
+
+ r = mii->mir(mii, phyno, Bmcr);
+ if(!(r & BmcrR)){
+ r |= BmcrAne|BmcrRan;
+ mii->miw(mii, phyno, Bmcr, r);
+ }
+
+ return 0;
+}
+
+int
+miistatus(Mii* mii)
+{
+ MiiPhy *phy;
+ int anlpar, bmsr, p, r, phyno;
+
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ phy = mii->curphy;
+ phyno = phy->phyno;
+
+ /*
+ * Check Auto-Negotiation is complete and link is up.
+ * (Read status twice as the Ls bit is sticky).
+ */
+ bmsr = mii->mir(mii, phyno, Bmsr);
+ if(!(bmsr & (BmsrAnc|BmsrAna))) {
+ // print("miistatus: auto-neg incomplete\n");
+ return -1;
+ }
+
+ bmsr = mii->mir(mii, phyno, Bmsr);
+ if(!(bmsr & BmsrLs)){
+ // print("miistatus: link down\n");
+ phy->link = 0;
+ return -1;
+ }
+
+ phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
+ if(phy->mscr){
+ r = mii->mir(mii, phyno, Mssr);
+ if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
+ phy->speed = 1000;
+ phy->fd = 1;
+ }
+ else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
+ phy->speed = 1000;
+ }
+
+ anlpar = mii->mir(mii, phyno, Anlpar);
+ if(phy->speed == 0){
+ r = phy->anar & anlpar;
+ if(r & AnaTXFD){
+ phy->speed = 100;
+ phy->fd = 1;
+ }
+ else if(r & AnaTXHD)
+ phy->speed = 100;
+ else if(r & Ana10FD){
+ phy->speed = 10;
+ phy->fd = 1;
+ }
+ else if(r & Ana10HD)
+ phy->speed = 10;
+ }
+ if(phy->speed == 0) {
+ // print("miistatus: phy speed 0\n");
+ return -1;
+ }
+
+ if(phy->fd){
+ p = phy->fc;
+ r = anlpar & (AnaAP|AnaP);
+ if(p == AnaAP && r == (AnaAP|AnaP))
+ phy->tfc = 1;
+ else if(p == (AnaAP|AnaP) && r == AnaAP)
+ phy->rfc = 1;
+ else if((p & AnaP) && (r & AnaP))
+ phy->rfc = phy->tfc = 1;
+ }
+
+ phy->link = 1;
+
+ return 0;
+}
diff --git a/sys/src/9/kw/ethermii.h b/sys/src/9/kw/ethermii.h
new file mode 100755
index 000000000..524a5743d
--- /dev/null
+++ b/sys/src/9/kw/ethermii.h
@@ -0,0 +1,143 @@
+typedef struct Mii Mii;
+typedef struct MiiPhy MiiPhy;
+
+enum { /* registers */
+ Bmcr = 0, /* Basic Mode Control */
+ Bmsr = 1, /* Basic Mode Status */
+ Phyidr1 = 2, /* PHY Identifier #1 */
+ Phyidr2 = 3, /* PHY Identifier #2 */
+ Anar = 4, /* Auto-Negotiation Advertisement */
+ Anlpar = 5, /* AN Link Partner Ability */
+ Aner = 6, /* AN Expansion */
+ Annptr = 7, /* AN Next Page TX */
+ Annprr = 8, /* AN Next Page RX */
+ Mscr = 9, /* Gb Control */
+ Mssr = 10, /* Gb Status */
+ Esr = 15, /* Extended Status */
+
+ /* 88e1116-specific paged registers */
+ Scr = 16, /* special control register */
+ Ssr = 17, /* special status register */
+ Ier = 18, /* interrupt enable reg */
+ Isr = 19, /* interrupt status reg */
+ Escr = 20, /* extended special control reg */
+ Recr = 21, /* RX error counter reg */
+ Eadr = 22, /* extended address reg (page select) */
+ Globsts = 23, /* global status */
+ Impover = 24, /* RGMII output impedance override (page 2) */
+ Imptarg = 25, /* RGMII output impedance target (page 2) */
+ Scr2 = 26, /* special control register 2 */
+
+ NMiiPhyr = 32,
+ NMiiPhy = 32,
+};
+
+enum { /* Bmcr */
+ BmcrSs1 = 0x0040, /* Speed Select[1] */
+ BmcrCte = 0x0080, /* Collision Test Enable */
+ BmcrDm = 0x0100, /* Duplex Mode */
+ BmcrRan = 0x0200, /* Restart Auto-Negotiation */
+ BmcrI = 0x0400, /* Isolate */
+ BmcrPd = 0x0800, /* Power Down */
+ BmcrAne = 0x1000, /* Auto-Negotiation Enable */
+ BmcrSs0 = 0x2000, /* Speed Select[0] */
+ BmcrLe = 0x4000, /* Loopback Enable */
+ BmcrR = 0x8000, /* Reset */
+};
+
+enum { /* Bmsr */
+ BmsrEc = 0x0001, /* Extended Capability */
+ BmsrJd = 0x0002, /* Jabber Detect */
+ BmsrLs = 0x0004, /* Link Status */
+ BmsrAna = 0x0008, /* Auto-Negotiation Ability */
+ BmsrRf = 0x0010, /* Remote Fault */
+ BmsrAnc = 0x0020, /* Auto-Negotiation Complete */
+ BmsrPs = 0x0040, /* Preamble Suppression Capable */
+ BmsrEs = 0x0100, /* Extended Status */
+ Bmsr100T2HD = 0x0200, /* 100BASE-T2 HD Capable */
+ Bmsr100T2FD = 0x0400, /* 100BASE-T2 FD Capable */
+ Bmsr10THD = 0x0800, /* 10BASE-T HD Capable */
+ Bmsr10TFD = 0x1000, /* 10BASE-T FD Capable */
+ Bmsr100TXHD = 0x2000, /* 100BASE-TX HD Capable */
+ Bmsr100TXFD = 0x4000, /* 100BASE-TX FD Capable */
+ Bmsr100T4 = 0x8000, /* 100BASE-T4 Capable */
+};
+
+enum { /* Anar/Anlpar */
+ Ana10HD = 0x0020, /* Advertise 10BASE-T */
+ Ana10FD = 0x0040, /* Advertise 10BASE-T FD */
+ AnaTXHD = 0x0080, /* Advertise 100BASE-TX */
+ AnaTXFD = 0x0100, /* Advertise 100BASE-TX FD */
+ AnaT4 = 0x0200, /* Advertise 100BASE-T4 */
+ AnaP = 0x0400, /* Pause */
+ AnaAP = 0x0800, /* Asymmetrical Pause */
+ AnaRf = 0x2000, /* Remote Fault */
+ AnaAck = 0x4000, /* Acknowledge */
+ AnaNp = 0x8000, /* Next Page Indication */
+};
+
+enum { /* Mscr */
+ Mscr1000THD = 0x0100, /* Advertise 1000BASE-T HD */
+ Mscr1000TFD = 0x0200, /* Advertise 1000BASE-T FD */
+};
+
+enum { /* Mssr */
+ Mssr1000THD = 0x0400, /* Link Partner 1000BASE-T HD able */
+ Mssr1000TFD = 0x0800, /* Link Partner 1000BASE-T FD able */
+};
+
+enum { /* Esr */
+ Esr1000THD = 0x1000, /* 1000BASE-T HD Capable */
+ Esr1000TFD = 0x2000, /* 1000BASE-T FD Capable */
+ Esr1000XHD = 0x4000, /* 1000BASE-X HD Capable */
+ Esr1000XFD = 0x8000, /* 1000BASE-X FD Capable */
+};
+
+enum { /* Scr page 0 */
+ Pwrdown = 0x0004, /* power down */
+ Mdix = 0x0060, /* MDI crossover mode */
+ Endetect = 0x0300, /* energy detect */
+};
+enum { /* Scr page 2 */
+ Rgmiipwrup = 0x0008, /* RGMII power up: must sw reset after */
+};
+
+enum { /* Recr page 2 */
+ Txtiming = 1<<4,
+ Rxtiming = 1<<5,
+};
+
+typedef struct Mii {
+ Lock;
+ int nphy;
+ int mask;
+ MiiPhy* phy[NMiiPhy];
+ MiiPhy* curphy;
+
+ void* ctlr;
+ int (*mir)(Mii*, int, int);
+ int (*miw)(Mii*, int, int, int);
+} Mii;
+
+typedef struct MiiPhy {
+ Mii* mii;
+ int oui;
+ int phyno;
+
+ int anar;
+ int fc;
+ int mscr;
+
+ int link;
+ int speed;
+ int fd;
+ int rfc;
+ int tfc;
+};
+
+extern int mii(Mii*, int);
+extern int miiane(Mii*, int, int, int);
+extern int miimir(Mii*, int);
+extern int miimiw(Mii*, int, int);
+extern int miireset(Mii*);
+extern int miistatus(Mii*);
diff --git a/sys/src/9/kw/flashkw.c b/sys/src/9/kw/flashkw.c
new file mode 100755
index 000000000..e45bc29de
--- /dev/null
+++ b/sys/src/9/kw/flashkw.c
@@ -0,0 +1,671 @@
+/*
+ * sheevaplug nand flash driver
+ *
+ * for now separate from (inferno's) os/port/flashnand.c because the flash
+ * seems newer, and has different commands, but that is nand-chip specific,
+ * not sheevaplug-specific. they should be merged in future.
+ *
+ * the sheevaplug has a hynix 4gbit flash chip: hy27uf084g2m.
+ * 2048 byte pages, with 64 spare bytes each; erase block size is 128k.
+ *
+ * it has a "glueless" interface, at 0xf9000000. that's the address
+ * of the data register. the command and address registers are those
+ * or'ed with 1 and 2 respectively.
+ *
+ * linux uses this layout for the nand flash (from address 0 onwards):
+ * 1mb for u-boot
+ * 4mb for kernel
+ * 507mb for file system
+ *
+ * this is not so relevant here except for ecc. the first two areas
+ * (u-boot and kernel) are expected to have 4-bit ecc per 512 bytes
+ * (but calculated from last byte to first), bad erase blocks skipped.
+ * the file system area has 1-bit ecc per 256 bytes.
+ */
+
+#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/flashif.h"
+#include "../port/nandecc.h"
+
+enum {
+ Debug = 0,
+
+ Nopage = ~0ul, /* cache is empty */
+
+ /* vendors */
+ Hynix = 0xad,
+ Samsung = 0xec,
+
+ /* chips */
+ Hy27UF084G2M = 0xdc,
+
+ NandActCEBoot = 1<<1,
+};
+
+typedef struct Nandreg Nandreg;
+typedef struct Nandtab Nandtab;
+typedef struct Cache Cache;
+
+struct Nandreg { /* hw registers */
+ ulong rdparms;
+ ulong wrparms;
+ uchar _pad0[0x70 - 0x20];
+ ulong ctl;
+};
+
+struct Nandtab {
+ int vid;
+ int did;
+ vlong size;
+ char* name;
+};
+
+struct Cache {
+ Flash *flif;
+ ulong pageno;
+ ulong pgsize; /* r->pagesize */
+ char *page; /* of pgsize bytes */
+};
+
+enum {
+ /* commands */
+ Readstatus = 0x70,
+ Readid = 0x90, /* needs 1 0-address write */
+ Resetf = 0xff,
+
+ /*
+ * needs 5 address writes followed by Readstart,
+ * Readstartcache or Restartcopy.
+ */
+ Read = 0x00,
+ Readstart = 0x30,
+ Readstartcache = 0x31,
+ Readstartcopy = 0x35,
+ /* after Readstartcache, to stop reading next pages */
+ Readstopcache = 0x34,
+
+ /* needs 5 address writes, the data, and -start or -cache */
+ Program = 0x80,
+ Programstart = 0x10,
+ Programcache = 0x15,
+
+ Copyback = 0x85, /* followed by Programstart */
+
+ /* 3 address writes for block followed by Erasestart */
+ Erase = 0x60,
+ Erasestart = 0xd0,
+
+ Randomread = 0x85,
+ Randomwrite = 0x05,
+ Randomwritestart= 0xe0,
+
+ /* status bits */
+ SFail = 1<<0,
+ SCachefail = 1<<1,
+ SIdle = 1<<5, /* doesn't seem to come on ever */
+ SReady = 1<<6,
+ SNotprotected = 1<<7,
+
+ Srdymask = SReady, /* was SIdle|SReady */
+};
+
+Nandtab nandtab[] = {
+ {Hynix, Hy27UF084G2M, 512*MB, "Hy27UF084G2M"},
+ {Samsung, 0xdc, 512*MB, "Samsung 2Gb"},
+};
+
+static Cache cache;
+
+static void
+nandcmd(Flash *f, uchar b)
+{
+ uchar *p = (uchar *)((ulong)f->addr|1);
+
+ *p = b;
+ coherence();
+}
+
+static void
+nandaddr(Flash *f, uchar b)
+{
+ uchar *p = (uchar *)((ulong)f->addr|2);
+
+ *p = b;
+ coherence();
+}
+
+static uchar
+nandread(Flash *f)
+{
+ return *(uchar *)f->addr;
+}
+
+static void
+nandreadn(Flash *f, uchar *buf, long n)
+{
+ uchar *p = f->addr;
+
+ while(n-- > 0)
+ *buf++ = *p;
+}
+
+static void
+nandwrite(Flash *f, uchar b)
+{
+ *(uchar *)f->addr = b;
+ coherence();
+}
+
+static void
+nandwriten(Flash *f, uchar *buf, long n)
+{
+ uchar *p = f->addr;
+
+ while(n-- > 0)
+ *p = *buf++;
+ coherence();
+}
+
+static void
+nandclaim(Flash*)
+{
+ Nandreg *nand = (Nandreg*)soc.nand;
+
+ nand->ctl |= NandActCEBoot;
+ coherence();
+}
+
+static void
+nandunclaim(Flash*)
+{
+ Nandreg *nand = (Nandreg*)soc.nand;
+
+ nand->ctl &= ~NandActCEBoot;
+ coherence();
+}
+
+
+void mmuidmap(uintptr phys, int mbs);
+
+Nandtab *
+findflash(Flash *f, uintptr pa, uchar *id4p)
+{
+ int i;
+ ulong sts;
+ uchar maker, device, id3, id4;
+ Nandtab *chip;
+
+ mmuidmap(pa, 16);
+ f->addr = (void *)pa;
+
+ /* make sure controller is idle */
+ nandclaim(f);
+ nandcmd(f, Resetf);
+ nandunclaim(f);
+
+ nandclaim(f);
+ nandcmd(f, Readstatus);
+ sts = nandread(f);
+ nandunclaim(f);
+ for (i = 10; i > 0 && !(sts & SReady); i--) {
+ delay(50);
+ nandclaim(f);
+ nandcmd(f, Readstatus);
+ sts = nandread(f);
+ nandunclaim(f);
+ }
+ if(!(sts & SReady))
+ return nil;
+
+ nandclaim(f);
+ nandcmd(f, Readid);
+ nandaddr(f, 0);
+ maker = nandread(f);
+ device = nandread(f);
+ id3 = nandread(f);
+ USED(id3);
+ id4 = nandread(f);
+ nandunclaim(f);
+ if (id4p)
+ *id4p = id4;
+
+ for(i = 0; i < nelem(nandtab); i++) {
+ chip = &nandtab[i];
+ if(chip->vid == maker && chip->did == device)
+ return chip;
+ }
+ return nil;
+}
+
+int
+flashat(Flash *f, uintptr pa)
+{
+ return findflash(f, pa, nil) != nil;
+}
+
+static int
+idchip(Flash *f)
+{
+ uchar id4;
+ Flashregion *r;
+ Nandtab *chip;
+ static int blocksizes[4] = { 64*1024, 128*1024, 256*1024, 0 };
+ static int pagesizes[4] = { 1024, 2*1024, 0, 0 };
+ static int spares[2] = { 8, 16 }; /* per 512 bytes */
+
+ f->id = 0;
+ f->devid = 0;
+ f->width = 1;
+ chip = findflash(f, (uintptr)f->addr, &id4);
+ if (chip == nil)
+ return -1;
+ f->id = chip->vid;
+ f->devid = chip->did;
+ f->size = chip->size;
+ f->width = 1;
+ f->nr = 1;
+
+ r = &f->regions[0];
+ r->pagesize = pagesizes[id4 & MASK(2)];
+ r->erasesize = blocksizes[(id4 >> 4) & MASK(2)];
+ if (r->pagesize == 0 || r->erasesize == 0) {
+ iprint("flashkw: bogus flash sizes\n");
+ return -1;
+ }
+ r->n = f->size / r->erasesize;
+ r->start = 0;
+ r->end = f->size;
+ assert(ispow2(r->pagesize));
+ r->pageshift = log2(r->pagesize);
+ assert(ispow2(r->erasesize));
+ r->eraseshift = log2(r->erasesize);
+ assert(r->eraseshift >= r->pageshift);
+ if (cache.page == nil) {
+ cache.pgsize = r->pagesize;
+ cache.page = smalloc(r->pagesize);
+ }
+
+ r->spares = r->pagesize / 512 * spares[(id4 >> 2) & 1];
+ print("#F0: kwnand: %s %,lud bytes pagesize %lud erasesize %,lud"
+ " spares per page %lud\n", chip->name, f->size, r->pagesize,
+ r->erasesize, r->spares);
+ return 0;
+}
+
+static int
+ctlrwait(Flash *f)
+{
+ int sts, cnt;
+
+ nandclaim(f);
+ for (;;) {
+ nandcmd(f, Readstatus);
+ for(cnt = 100; cnt > 0 && (nandread(f) & Srdymask) != Srdymask;
+ cnt--)
+ microdelay(50);
+ nandcmd(f, Readstatus);
+ sts = nandread(f);
+ if((sts & Srdymask) == Srdymask)
+ break;
+ print("flashkw: flash ctlr busy, sts %#ux: resetting\n", sts);
+ nandcmd(f, Resetf);
+ }
+ nandunclaim(f);
+ return 0;
+}
+
+static int
+erasezone(Flash *f, Flashregion *r, ulong offset)
+{
+ int i;
+ ulong page, block;
+ uchar s;
+
+ if (Debug) {
+ print("flashkw: erasezone: offset %#lux, region nblocks %d,"
+ " start %#lux, end %#lux\n", offset, r->n, r->start,
+ r->end);
+ print(" erasesize %lud, pagesize %lud\n",
+ r->erasesize, r->pagesize);
+ }
+ assert(r->erasesize != 0);
+ if(offset & (r->erasesize - 1)) {
+ print("flashkw: erase offset %lud not block aligned\n", offset);
+ return -1;
+ }
+ page = offset >> r->pageshift;
+ block = page >> (r->eraseshift - r->pageshift);
+ if (Debug)
+ print("flashkw: erase: block %#lux\n", block);
+
+ /* make sure controller is idle */
+ if(ctlrwait(f) < 0) {
+ print("flashkw: erase: flash busy\n");
+ return -1;
+ }
+
+ /* start erasing */
+ nandclaim(f);
+ nandcmd(f, Erase);
+ nandaddr(f, page>>0);
+ nandaddr(f, page>>8);
+ nandaddr(f, page>>16);
+ nandcmd(f, Erasestart);
+
+ /* invalidate cache on any erasure (slight overkill) */
+ cache.pageno = Nopage;
+
+ /* have to wait until flash is done. typically ~2ms */
+ delay(1);
+ nandcmd(f, Readstatus);
+ for(i = 0; i < 100; i++) {
+ s = nandread(f);
+ if(s & SReady) {
+ nandunclaim(f);
+ if(s & SFail) {
+ print("flashkw: erase: failed, block %#lux\n",
+ block);
+ return -1;
+ }
+ return 0;
+ }
+ microdelay(50);
+ }
+ print("flashkw: erase timeout, block %#lux\n", block);
+ nandunclaim(f);
+ return -1;
+}
+
+static void
+flcachepage(Flash *f, ulong page, uchar *buf)
+{
+ Flashregion *r = &f->regions[0];
+
+ assert(cache.pgsize == r->pagesize);
+ cache.flif = f;
+ cache.pageno = page;
+ /* permit i/o directly to or from the cache */
+ if (buf != (uchar *)cache.page)
+ memmove(cache.page, buf, cache.pgsize);
+}
+
+static int
+write1page(Flash *f, ulong offset, void *buf)
+{
+ int i;
+ ulong page, v;
+ uchar s;
+ uchar *eccp, *p;
+ Flashregion *r = &f->regions[0];
+ static uchar *oob;
+
+ if (oob == nil)
+ oob = smalloc(r->spares);
+
+ page = offset >> r->pageshift;
+ if (Debug)
+ print("flashkw: write nand offset %#lux page %#lux\n",
+ offset, page);
+
+ if(offset & (r->pagesize - 1)) {
+ print("flashkw: write offset %lud not page aligned\n", offset);
+ return -1;
+ }
+
+ p = buf;
+ memset(oob, 0xff, r->spares);
+ assert(r->spares >= 24);
+ eccp = oob + r->spares - 24;
+ for(i = 0; i < r->pagesize / 256; i++) {
+ v = nandecc(p);
+ *eccp++ = v>>8;
+ *eccp++ = v>>0;
+ *eccp++ = v>>16;
+ p += 256;
+ }
+
+ if(ctlrwait(f) < 0) {
+ print("flashkw: write: nand not ready & idle\n");
+ return -1;
+ }
+
+ /* write, only whole pages for now, no sub-pages */
+ nandclaim(f);
+ nandcmd(f, Program);
+ nandaddr(f, 0);
+ nandaddr(f, 0);
+ nandaddr(f, page>>0);
+ nandaddr(f, page>>8);
+ nandaddr(f, page>>16);
+ nandwriten(f, buf, r->pagesize);
+ nandwriten(f, oob, r->spares);
+ nandcmd(f, Programstart);
+
+ microdelay(100);
+ nandcmd(f, Readstatus);
+ for(i = 0; i < 100; i++) {
+ s = nandread(f);
+ if(s & SReady) {
+ nandunclaim(f);
+ if(s & SFail) {
+ print("flashkw: write failed, page %#lux\n",
+ page);
+ return -1;
+ }
+ return 0;
+ }
+ microdelay(10);
+ }
+
+ nandunclaim(f);
+ flcachepage(f, page, buf);
+ print("flashkw: write timeout for page %#lux\n", page);
+ return -1;
+}
+
+static int
+read1page(Flash *f, ulong offset, void *buf)
+{
+ int i;
+ ulong addr, page, w;
+ uchar *eccp, *p;
+ Flashregion *r = &f->regions[0];
+ static uchar *oob;
+
+ if (oob == nil)
+ oob = smalloc(r->spares);
+
+ assert(r->pagesize != 0);
+ addr = offset & (r->pagesize - 1);
+ page = offset >> r->pageshift;
+ if(addr != 0) {
+ print("flashkw: read1page: read addr %#lux:"
+ " must read aligned page\n", addr);
+ return -1;
+ }
+
+ /* satisfy request from cache if possible */
+ if (f == cache.flif && page == cache.pageno &&
+ r->pagesize == cache.pgsize) {
+ memmove(buf, cache.page, r->pagesize);
+ return 0;
+ }
+
+ if (Debug)
+ print("flashkw: read offset %#lux addr %#lux page %#lux\n",
+ offset, addr, page);
+
+ nandclaim(f);
+ nandcmd(f, Read);
+ nandaddr(f, addr>>0);
+ nandaddr(f, addr>>8);
+ nandaddr(f, page>>0);
+ nandaddr(f, page>>8);
+ nandaddr(f, page>>16);
+ nandcmd(f, Readstart);
+
+ microdelay(50);
+
+ nandreadn(f, buf, r->pagesize);
+ nandreadn(f, oob, r->spares);
+
+ nandunclaim(f);
+
+ /* verify/correct data. last 8*3 bytes is ecc, per 256 bytes. */
+ p = buf;
+ assert(r->spares >= 24);
+ eccp = oob + r->spares - 24;
+ for(i = 0; i < r->pagesize / 256; i++) {
+ w = eccp[0] << 8 | eccp[1] << 0 | eccp[2] << 16;
+ eccp += 3;
+ switch(nandecccorrect(p, nandecc(p), &w, 1)) {
+ case NandEccErrorBad:
+ print("(page %d)\n", i);
+ return -1;
+ case NandEccErrorOneBit:
+ case NandEccErrorOneBitInEcc:
+ print("(page %d)\n", i);
+ /* fall through */
+ case NandEccErrorGood:
+ break;
+ }
+ p += 256;
+ }
+
+ flcachepage(f, page, buf);
+ return 0;
+}
+
+/*
+ * read a page at offset into cache, copy fragment from buf into it
+ * at pagoff, and rewrite that page.
+ */
+static int
+rewrite(Flash *f, ulong offset, ulong pagoff, void *buf, ulong size)
+{
+ if (read1page(f, offset, cache.page) < 0)
+ return -1;
+ memmove(&cache.page[pagoff], buf, size);
+ return write1page(f, offset, cache.page);
+}
+
+/* there are no alignment constraints on offset, buf, nor n */
+static int
+write(Flash *f, ulong offset, void *buf, long n)
+{
+ uint un, frag, pagoff;
+ ulong pgsize;
+ uchar *p;
+ Flashregion *r = &f->regions[0];
+
+ if(n <= 0)
+ panic("flashkw: write: non-positive count %ld", n);
+ un = n;
+ assert(r->pagesize != 0);
+ pgsize = r->pagesize;
+
+ /* if a partial first page exists, update the first page with it. */
+ p = buf;
+ pagoff = offset % pgsize;
+ if (pagoff != 0) {
+ frag = pgsize - pagoff;
+ if (frag > un) /* might not extend to end of page */
+ frag = un;
+ if (rewrite(f, offset - pagoff, pagoff, p, frag) < 0)
+ return -1;
+ offset += frag;
+ p += frag;
+ un -= frag;
+ }
+
+ /* copy whole pages */
+ while (un >= pgsize) {
+ if (write1page(f, offset, p) < 0)
+ return -1;
+ offset += pgsize;
+ p += pgsize;
+ un -= pgsize;
+ }
+
+ /* if a partial last page exists, update the last page with it. */
+ if (un > 0)
+ return rewrite(f, offset, 0, p, un);
+ return 0;
+}
+
+/* there are no alignment constraints on offset, buf, nor n */
+static int
+read(Flash *f, ulong offset, void *buf, long n)
+{
+ uint un, frag, pagoff;
+ ulong pgsize;
+ uchar *p;
+ Flashregion *r = &f->regions[0];
+
+ if(n <= 0)
+ panic("flashkw: read: non-positive count %ld", n);
+ un = n;
+ assert(r->pagesize != 0);
+ pgsize = r->pagesize;
+
+ /* if partial 1st page, read it into cache & copy fragment to buf */
+ p = buf;
+ pagoff = offset % pgsize;
+ if (pagoff != 0) {
+ frag = pgsize - pagoff;
+ if (frag > un) /* might not extend to end of page */
+ frag = un;
+ if (read1page(f, offset - pagoff, cache.page) < 0)
+ return -1;
+ offset += frag;
+ memmove(p, &cache.page[pagoff], frag);
+ p += frag;
+ un -= frag;
+ }
+
+ /* copy whole pages */
+ while (un >= pgsize) {
+ if (read1page(f, offset, p) < 0)
+ return -1;
+ offset += pgsize;
+ p += pgsize;
+ un -= pgsize;
+ }
+
+ /* if partial last page, read into cache & copy initial fragment to buf */
+ if (un > 0) {
+ if (read1page(f, offset, cache.page) < 0)
+ return -1;
+ memmove(p, cache.page, un);
+ }
+ return 0;
+}
+
+static int
+reset(Flash *f)
+{
+ if(f->data != nil)
+ return 1;
+ f->write = write;
+ f->read = read;
+ f->eraseall = nil;
+ f->erasezone = erasezone;
+ f->suspend = nil;
+ f->resume = nil;
+ f->sort = "nand";
+ cache.pageno = Nopage;
+ return idchip(f);
+}
+
+void
+flashkwlink(void)
+{
+ addflashcard("nand", reset);
+}
diff --git a/sys/src/9/kw/fns.h b/sys/src/9/kw/fns.h
new file mode 100755
index 000000000..fcaa647da
--- /dev/null
+++ b/sys/src/9/kw/fns.h
@@ -0,0 +1,203 @@
+#define checkmmu(a, b)
+#define countpagerefs(a, b)
+
+#include "../port/portfns.h"
+
+extern int led(int, int);
+extern void ledexit(int);
+extern void delay(int);
+extern void _uartputs(char*, int);
+extern int _uartprint(char*, ...);
+extern void uartkirkwoodconsole(void);
+extern void serialputs(char *, int);
+extern void serialputc(int c);
+
+#pragma varargck argpos _uartprint 1
+
+extern void archreboot(void);
+extern void archconfinit(void);
+extern void archreset(void);
+extern void barriers(void);
+extern void cachedinv(void);
+extern void cachedinvse(void*, int);
+extern void cachedwb(void);
+extern void cachedwbinv(void);
+extern void cachedwbinvse(void*, int);
+extern void cachedwbse(void*, int);
+extern void cacheiinv(void);
+extern void cacheuwbinv(void);
+extern uintptr cankaddr(uintptr pa);
+extern void clockshutdown(void);
+extern int clz(ulong);
+int cmpswap(long*, long, long);
+
+#define coherence barriers
+
+extern u32int controlget(void);
+extern u32int cpctget(void);
+extern u32int cpidget(void);
+extern char *cputype2name(char *, int);
+extern ulong cprd(int cp, int op1, int crn, int crm, int op2);
+extern ulong cprdsc(int op1, int crn, int crm, int op2);
+extern void cpuidprint(void);
+extern void cpwr(int cp, int op1, int crn, int crm, int op2, ulong val);
+extern void cpwrsc(int op1, int crn, int crm, int op2, ulong val);
+#define cycles(ip) *(ip) = lcycles()
+extern u32int dacget(void);
+extern void dacput(u32int);
+extern u32int farget(void);
+extern u32int fsrget(void);
+extern int ispow2(uvlong);
+extern void l1cachesoff(void);
+extern void l1cacheson(void);
+extern void l2cachecfgoff(void);
+extern void l2cachecfgon(void);
+extern void l2cacheon(void);
+extern void l2cacheuinv(void);
+extern void l2cacheuinvse(void*, int);
+extern void l2cacheuwb(void);
+extern void l2cacheuwbinv(void);
+extern void l2cacheuwbinvse(void*, int);
+extern void l2cacheuwbse(void*, int);
+extern void lastresortprint(char *buf, long bp);
+extern int log2(ulong);
+extern void mmuinvalidate(void); /* 'mmu' or 'tlb'? */
+extern void mmuinvalidateaddr(u32int); /* 'mmu' or 'tlb'? */
+extern u32int pidget(void);
+extern void pidput(u32int);
+void procrestore(Proc *);
+void procsave(Proc*);
+void procsetup(Proc*);
+extern void _reset(void);
+extern void setr13(int, u32int*);
+extern void syscallfmt(int syscallno, ulong pc, va_list list);
+extern void sysretfmt(int syscallno, va_list list, long ret, uvlong start, uvlong stop);
+extern int tas(void *);
+extern u32int ttbget(void);
+extern void ttbput(u32int);
+
+extern void intrclear(int sort, int v);
+extern void intrenable(int sort, int v, void (*f)(Ureg*, void*), void *a, char *name);
+extern void intrdisable(int sort, int v, void (*f)(Ureg*, void*), void* a, char *name);
+extern void vectors(void);
+extern void vtable(void);
+
+/*
+ * Things called in main.
+ */
+extern void clockinit(void);
+extern void i8250console(void);
+extern void links(void);
+extern void mmuinit(void);
+extern void touser(uintptr);
+extern void trapinit(void);
+
+extern int fpiarm(Ureg*);
+extern int fpudevprocio(Proc*, void*, long, uintptr, int);
+extern void fpuinit(void);
+extern void fpunoted(void);
+extern void fpunotify(Ureg*);
+extern void fpuprocrestore(Proc*);
+extern void fpuprocsave(Proc*);
+extern void fpusysprocsetup(Proc*);
+extern void fpusysrfork(Ureg*);
+extern void fpusysrforkchild(Proc*, Ureg *, Proc*);
+extern int fpuemu(Ureg*);
+
+/*
+ * Miscellaneous machine dependent stuff.
+ */
+extern char* getenv(char*, char*, int);
+char* getconf(char*);
+uintptr mmukmap(uintptr, uintptr, usize);
+uintptr mmukunmap(uintptr, uintptr, usize);
+extern void* mmuuncache(void*, usize);
+extern void* ucalloc(usize);
+extern void* ucallocalign(usize size, int align, int span);
+extern Block* ucallocb(int);
+extern void ucfree(void*);
+extern void ucfreeb(Block*);
+extern Block* uciallocb(int);
+
+/*
+ * Things called from port.
+ */
+extern void delay(int); /* only scheddump() */
+extern int islo(void);
+extern void microdelay(int); /* only edf.c */
+extern void evenaddr(uintptr);
+extern void idlehands(void);
+extern void setkernur(Ureg*, Proc*); /* only devproc.c */
+extern void spldone(void);
+extern int splfhi(void);
+extern int splflo(void);
+extern void sysprocsetup(Proc*);
+
+/*
+ * PCI
+ */
+ulong pcibarsize(Pcidev*, int);
+void pcibussize(Pcidev*, ulong*, ulong*);
+int pcicfgr8(Pcidev*, int);
+int pcicfgr16(Pcidev*, int);
+int pcicfgr32(Pcidev*, int);
+void pcicfgw8(Pcidev*, int, int);
+void pcicfgw16(Pcidev*, int, int);
+void pcicfgw32(Pcidev*, int, int);
+void pciclrbme(Pcidev*);
+void pciclrioe(Pcidev*);
+void pciclrmwi(Pcidev*);
+int pcigetpms(Pcidev*);
+void pcihinv(Pcidev*);
+uchar pciipin(Pcidev*, uchar);
+Pcidev* pcimatch(Pcidev*, int, int);
+Pcidev* pcimatchtbdf(int);
+void pcireset(void);
+int pciscan(int, Pcidev**);
+void pcisetbme(Pcidev*);
+void pcisetioe(Pcidev*);
+void pcisetmwi(Pcidev*);
+int pcisetpms(Pcidev*, int);
+int cas32(void*, u32int, u32int);
+int tas32(void*);
+
+#define CASU(p, e, n) cas32((p), (u32int)(e), (u32int)(n))
+#define CASV(p, e, n) cas32((p), (u32int)(e), (u32int)(n))
+#define CASW(addr, exp, new) cas32((addr), (exp), (new))
+#define TAS(addr) tas32(addr)
+
+extern void forkret(void);
+extern int userureg(Ureg*);
+void* vmap(uintptr, usize);
+void vunmap(void*, usize);
+
+extern void kexit(Ureg*);
+
+#define getpgcolor(a) 0
+#define kmapinval()
+
+#define PTR2UINT(p) ((uintptr)(p))
+#define UINT2PTR(i) ((void*)(i))
+
+#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
+
+/*
+ * this low-level printing stuff is ugly,
+ * but there appears to be no other way to
+ * print until after #t is populated.
+ */
+#define wave(c) { \
+ coherence(); \
+ while ((*(ulong *)(PHYSCONS+4*5) & (1<<5)) == 0) /* (x->lsr&LSRthre)==0? */ \
+ ; \
+ *(ulong *)PHYSCONS = (c); \
+ coherence(); \
+}
+
+/*
+ * These are not good enough.
+ */
+#define KADDR(pa) UINT2PTR(KZERO|((uintptr)(pa)))
+#define PADDR(va) PTR2UINT(((uintptr)(va)) & ~KSEGM)
+
+#define MASK(v) ((1UL << (v)) - 1) /* mask `v' bits wide */
diff --git a/sys/src/9/kw/fpi.c b/sys/src/9/kw/fpi.c
new file mode 100755
index 000000000..f341f2e4a
--- /dev/null
+++ b/sys/src/9/kw/fpi.c
@@ -0,0 +1,300 @@
+/*
+ * Floating Point Interpreter.
+ * shamelessly stolen from an original by ark.
+ */
+#include "fpi.h"
+
+void
+fpiround(Internal *i)
+{
+ unsigned long guard;
+
+ guard = i->l & GuardMask;
+ i->l &= ~GuardMask;
+ if(guard > (LsBit>>1) || (guard == (LsBit>>1) && (i->l & LsBit))){
+ i->l += LsBit;
+ if(i->l & CarryBit){
+ i->l &= ~CarryBit;
+ i->h++;
+ if(i->h & CarryBit){
+ if (i->h & 0x01)
+ i->l |= CarryBit;
+ i->l >>= 1;
+ i->h >>= 1;
+ i->e++;
+ }
+ }
+ }
+}
+
+static void
+matchexponents(Internal *x, Internal *y)
+{
+ int count;
+
+ count = y->e - x->e;
+ x->e = y->e;
+ if(count >= 2*FractBits){
+ x->l = x->l || x->h;
+ x->h = 0;
+ return;
+ }
+ if(count >= FractBits){
+ count -= FractBits;
+ x->l = x->h|(x->l != 0);
+ x->h = 0;
+ }
+ while(count > 0){
+ count--;
+ if(x->h & 0x01)
+ x->l |= CarryBit;
+ if(x->l & 0x01)
+ x->l |= 2;
+ x->l >>= 1;
+ x->h >>= 1;
+ }
+}
+
+static void
+shift(Internal *i)
+{
+ i->e--;
+ i->h <<= 1;
+ i->l <<= 1;
+ if(i->l & CarryBit){
+ i->l &= ~CarryBit;
+ i->h |= 0x01;
+ }
+}
+
+static void
+normalise(Internal *i)
+{
+ while((i->h & HiddenBit) == 0)
+ shift(i);
+}
+
+static void
+renormalise(Internal *i)
+{
+ if(i->e < -2 * FractBits)
+ i->e = -2 * FractBits;
+ while(i->e < 1){
+ i->e++;
+ if(i->h & 0x01)
+ i->l |= CarryBit;
+ i->h >>= 1;
+ i->l = (i->l>>1)|(i->l & 0x01);
+ }
+ if(i->e >= ExpInfinity)
+ SetInfinity(i);
+}
+
+void
+fpinormalise(Internal *x)
+{
+ if(!IsWeird(x) && !IsZero(x))
+ normalise(x);
+}
+
+void
+fpiadd(Internal *x, Internal *y, Internal *i)
+{
+ Internal *t;
+
+ i->s = x->s;
+ if(IsWeird(x) || IsWeird(y)){
+ if(IsNaN(x) || IsNaN(y))
+ SetQNaN(i);
+ else
+ SetInfinity(i);
+ return;
+ }
+ if(x->e > y->e){
+ t = x;
+ x = y;
+ y = t;
+ }
+ matchexponents(x, y);
+ i->e = x->e;
+ i->h = x->h + y->h;
+ i->l = x->l + y->l;
+ if(i->l & CarryBit){
+ i->h++;
+ i->l &= ~CarryBit;
+ }
+ if(i->h & (HiddenBit<<1)){
+ if(i->h & 0x01)
+ i->l |= CarryBit;
+ i->l = (i->l>>1)|(i->l & 0x01);
+ i->h >>= 1;
+ i->e++;
+ }
+ if(IsWeird(i))
+ SetInfinity(i);
+}
+
+void
+fpisub(Internal *x, Internal *y, Internal *i)
+{
+ Internal *t;
+
+ if(y->e < x->e
+ || (y->e == x->e && (y->h < x->h || (y->h == x->h && y->l < x->l)))){
+ t = x;
+ x = y;
+ y = t;
+ }
+ i->s = y->s;
+ if(IsNaN(y)){
+ SetQNaN(i);
+ return;
+ }
+ if(IsInfinity(y)){
+ if(IsInfinity(x))
+ SetQNaN(i);
+ else
+ SetInfinity(i);
+ return;
+ }
+ matchexponents(x, y);
+ i->e = y->e;
+ i->h = y->h - x->h;
+ i->l = y->l - x->l;
+ if(i->l < 0){
+ i->l += CarryBit;
+ i->h--;
+ }
+ if(i->h == 0 && i->l == 0)
+ SetZero(i);
+ else while(i->e > 1 && (i->h & HiddenBit) == 0)
+ shift(i);
+}
+
+#define CHUNK (FractBits/2)
+#define CMASK ((1<<CHUNK)-1)
+#define HI(x) ((short)((x)>>CHUNK) & CMASK)
+#define LO(x) ((short)(x) & CMASK)
+#define SPILL(x) ((x)>>CHUNK)
+#define M(x, y) ((long)a[x]*(long)b[y])
+#define C(h, l) (((long)((h) & CMASK)<<CHUNK)|((l) & CMASK))
+
+void
+fpimul(Internal *x, Internal *y, Internal *i)
+{
+ long a[4], b[4], c[7], f[4];
+
+ i->s = x->s^y->s;
+ if(IsWeird(x) || IsWeird(y)){
+ if(IsNaN(x) || IsNaN(y) || IsZero(x) || IsZero(y))
+ SetQNaN(i);
+ else
+ SetInfinity(i);
+ return;
+ }
+ else if(IsZero(x) || IsZero(y)){
+ SetZero(i);
+ return;
+ }
+ normalise(x);
+ normalise(y);
+ i->e = x->e + y->e - (ExpBias - 1);
+
+ a[0] = HI(x->h); b[0] = HI(y->h);
+ a[1] = LO(x->h); b[1] = LO(y->h);
+ a[2] = HI(x->l); b[2] = HI(y->l);
+ a[3] = LO(x->l); b[3] = LO(y->l);
+
+ c[6] = M(3, 3);
+ c[5] = M(2, 3) + M(3, 2) + SPILL(c[6]);
+ c[4] = M(1, 3) + M(2, 2) + M(3, 1) + SPILL(c[5]);
+ c[3] = M(0, 3) + M(1, 2) + M(2, 1) + M(3, 0) + SPILL(c[4]);
+ c[2] = M(0, 2) + M(1, 1) + M(2, 0) + SPILL(c[3]);
+ c[1] = M(0, 1) + M(1, 0) + SPILL(c[2]);
+ c[0] = M(0, 0) + SPILL(c[1]);
+
+ f[0] = c[0];
+ f[1] = C(c[1], c[2]);
+ f[2] = C(c[3], c[4]);
+ f[3] = C(c[5], c[6]);
+
+ if((f[0] & HiddenBit) == 0){
+ f[0] <<= 1;
+ f[1] <<= 1;
+ f[2] <<= 1;
+ f[3] <<= 1;
+ if(f[1] & CarryBit){
+ f[0] |= 1;
+ f[1] &= ~CarryBit;
+ }
+ if(f[2] & CarryBit){
+ f[1] |= 1;
+ f[2] &= ~CarryBit;
+ }
+ if(f[3] & CarryBit){
+ f[2] |= 1;
+ f[3] &= ~CarryBit;
+ }
+ i->e--;
+ }
+ i->h = f[0];
+ i->l = f[1];
+ if(f[2] || f[3])
+ i->l |= 1;
+ renormalise(i);
+}
+
+void
+fpidiv(Internal *x, Internal *y, Internal *i)
+{
+ i->s = x->s^y->s;
+ if(IsNaN(x) || IsNaN(y)
+ || (IsInfinity(x) && IsInfinity(y)) || (IsZero(x) && IsZero(y))){
+ SetQNaN(i);
+ return;
+ }
+ else if(IsZero(x) || IsInfinity(y)){
+ SetInfinity(i);
+ return;
+ }
+ else if(IsInfinity(x) || IsZero(y)){
+ SetZero(i);
+ return;
+ }
+ normalise(x);
+ normalise(y);
+ i->h = 0;
+ i->l = 0;
+ i->e = y->e - x->e + (ExpBias + 2*FractBits - 1);
+ do{
+ if(y->h > x->h || (y->h == x->h && y->l >= x->l)){
+ i->l |= 0x01;
+ y->h -= x->h;
+ y->l -= x->l;
+ if(y->l < 0){
+ y->l += CarryBit;
+ y->h--;
+ }
+ }
+ shift(y);
+ shift(i);
+ }while ((i->h & HiddenBit) == 0);
+ if(y->h || y->l)
+ i->l |= 0x01;
+ renormalise(i);
+}
+
+int
+fpicmp(Internal *x, Internal *y)
+{
+ if(IsNaN(x) && IsNaN(y))
+ return 0;
+ if(IsInfinity(x) && IsInfinity(y))
+ return y->s - x->s;
+ if(x->e == y->e && x->h == y->h && x->l == y->l)
+ return y->s - x->s;
+ if(x->e < y->e
+ || (x->e == y->e && (x->h < y->h || (x->h == y->h && x->l < y->l))))
+ return y->s ? 1: -1;
+ return x->s ? -1: 1;
+}
diff --git a/sys/src/9/kw/fpi.h b/sys/src/9/kw/fpi.h
new file mode 100755
index 000000000..abaa7c120
--- /dev/null
+++ b/sys/src/9/kw/fpi.h
@@ -0,0 +1,61 @@
+typedef long Word;
+typedef unsigned long Single;
+typedef struct {
+ unsigned long l;
+ unsigned long h;
+} Double;
+
+enum {
+ FractBits = 28,
+ CarryBit = 0x10000000,
+ HiddenBit = 0x08000000,
+ MsBit = HiddenBit,
+ NGuardBits = 3,
+ GuardMask = 0x07,
+ LsBit = (1<<NGuardBits),
+
+ SingleExpBias = 127,
+ SingleExpMax = 255,
+ DoubleExpBias = 1023,
+ DoubleExpMax = 2047,
+
+ ExpBias = DoubleExpBias,
+ ExpInfinity = DoubleExpMax,
+};
+
+typedef struct {
+ unsigned char s;
+ short e;
+ long l; /* 0000FFFFFFFFFFFFFFFFFFFFFFFFFGGG */
+ long h; /* 0000HFFFFFFFFFFFFFFFFFFFFFFFFFFF */
+} Internal;
+
+#define IsWeird(n) ((n)->e >= ExpInfinity)
+#define IsInfinity(n) (IsWeird(n) && (n)->h == HiddenBit && (n)->l == 0)
+#define SetInfinity(n) ((n)->e = ExpInfinity, (n)->h = HiddenBit, (n)->l = 0)
+#define IsNaN(n) (IsWeird(n) && (((n)->h & ~HiddenBit) || (n)->l))
+#define SetQNaN(n) ((n)->s = 0, (n)->e = ExpInfinity, \
+ (n)->h = HiddenBit|(LsBit<<1), (n)->l = 0)
+#define IsZero(n) ((n)->e == 1 && (n)->h == 0 && (n)->l == 0)
+#define SetZero(n) ((n)->e = 1, (n)->h = 0, (n)->l = 0)
+
+/*
+ * fpi.c
+ */
+extern void fpiround(Internal *);
+extern void fpiadd(Internal *, Internal *, Internal *);
+extern void fpisub(Internal *, Internal *, Internal *);
+extern void fpimul(Internal *, Internal *, Internal *);
+extern void fpidiv(Internal *, Internal *, Internal *);
+extern int fpicmp(Internal *, Internal *);
+extern void fpinormalise(Internal*);
+
+/*
+ * fpimem.c
+ */
+extern void fpis2i(Internal *, void *);
+extern void fpid2i(Internal *, void *);
+extern void fpiw2i(Internal *, void *);
+extern void fpii2s(void *, Internal *);
+extern void fpii2d(void *, Internal *);
+extern void fpii2w(Word *, Internal *);
diff --git a/sys/src/9/kw/fpiarm.c b/sys/src/9/kw/fpiarm.c
new file mode 100755
index 000000000..063d10c52
--- /dev/null
+++ b/sys/src/9/kw/fpiarm.c
@@ -0,0 +1,576 @@
+/*
+ * this doesn't attempt to implement ARM floating-point properties
+ * that aren't visible in the Inferno environment.
+ * all arithmetic is done in double precision.
+ * the FP trap status isn't updated.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#include "ureg.h"
+
+#include "arm.h"
+#include "fpi.h"
+
+/* undef this if correct kernel r13 isn't in Ureg;
+ * check calculation in fpiarm below
+ */
+
+
+#define REG(ur, x) (*(long*)(((char*)(ur))+roff[(x)]))
+#define FR(ufp, x) (*(Internal*)(ufp)->regs[(x)&7])
+
+typedef struct FP2 FP2;
+typedef struct FP1 FP1;
+
+struct FP2 {
+ char* name;
+ void (*f)(Internal, Internal, Internal*);
+};
+
+struct FP1 {
+ char* name;
+ void (*f)(Internal*, Internal*);
+};
+
+enum {
+ N = 1<<31,
+ Z = 1<<30,
+ C = 1<<29,
+ V = 1<<28,
+ REGPC = 15,
+};
+
+enum {
+ fpemudebug = 0,
+};
+
+#undef OFR
+#define OFR(X) ((ulong)&((Ureg*)0)->X)
+
+static int roff[] = {
+ OFR(r0), OFR(r1), OFR(r2), OFR(r3),
+ OFR(r4), OFR(r5), OFR(r6), OFR(r7),
+ OFR(r8), OFR(r9), OFR(r10), OFR(r11),
+ OFR(r12), OFR(r13), OFR(r14), OFR(pc),
+};
+
+static Internal fpconst[8] = { /* indexed by op&7 */
+ /* s, e, l, h */
+ {0, 0x1, 0x00000000, 0x00000000}, /* 0.0 */
+ {0, 0x3FF, 0x00000000, 0x08000000}, /* 1.0 */
+ {0, 0x400, 0x00000000, 0x08000000}, /* 2.0 */
+ {0, 0x400, 0x00000000, 0x0C000000}, /* 3.0 */
+ {0, 0x401, 0x00000000, 0x08000000}, /* 4.0 */
+ {0, 0x401, 0x00000000, 0x0A000000}, /* 5.0 */
+ {0, 0x3FE, 0x00000000, 0x08000000}, /* 0.5 */
+ {0, 0x402, 0x00000000, 0x0A000000}, /* 10.0 */
+};
+
+/*
+ * arm binary operations
+ */
+
+static void
+fadd(Internal m, Internal n, Internal *d)
+{
+ (m.s == n.s? fpiadd: fpisub)(&m, &n, d);
+}
+
+static void
+fsub(Internal m, Internal n, Internal *d)
+{
+ m.s ^= 1;
+ (m.s == n.s? fpiadd: fpisub)(&m, &n, d);
+}
+
+static void
+fsubr(Internal m, Internal n, Internal *d)
+{
+ n.s ^= 1;
+ (n.s == m.s? fpiadd: fpisub)(&n, &m, d);
+}
+
+static void
+fmul(Internal m, Internal n, Internal *d)
+{
+ fpimul(&m, &n, d);
+}
+
+static void
+fdiv(Internal m, Internal n, Internal *d)
+{
+ fpidiv(&m, &n, d);
+}
+
+static void
+fdivr(Internal m, Internal n, Internal *d)
+{
+ fpidiv(&n, &m, d);
+}
+
+/*
+ * arm unary operations
+ */
+
+static void
+fmov(Internal *m, Internal *d)
+{
+ *d = *m;
+}
+
+static void
+fmovn(Internal *m, Internal *d)
+{
+ *d = *m;
+ d->s ^= 1;
+}
+
+static void
+fabsf(Internal *m, Internal *d)
+{
+ *d = *m;
+ d->s = 0;
+}
+
+static void
+frnd(Internal *m, Internal *d)
+{
+ short e;
+
+ (m->s? fsub: fadd)(fpconst[6], *m, d);
+ if(IsWeird(d))
+ return;
+ fpiround(d);
+ e = (d->e - ExpBias) + 1;
+ if(e <= 0)
+ SetZero(d);
+ else if(e > FractBits){
+ if(e < 2*FractBits)
+ d->l &= ~((1<<(2*FractBits - e))-1);
+ }else{
+ d->l = 0;
+ if(e < FractBits)
+ d->h &= ~((1<<(FractBits-e))-1);
+ }
+}
+
+static FP1 optab1[16] = { /* Fd := OP Fm */
+[0] {"MOVF", fmov},
+[1] {"NEGF", fmovn},
+[2] {"ABSF", fabsf},
+[3] {"RNDF", frnd},
+[4] {"SQTF", /*fsqt*/0},
+/* LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN all `deprecated' */
+/* URD and NRM aren't implemented */
+};
+
+static FP2 optab2[16] = { /* Fd := Fn OP Fm */
+[0] {"ADDF", fadd},
+[1] {"MULF", fmul},
+[2] {"SUBF", fsub},
+[3] {"RSUBF", fsubr},
+[4] {"DIVF", fdiv},
+[5] {"RDIVF", fdivr},
+/* POW, RPW deprecated */
+[8] {"REMF", /*frem*/0},
+[9] {"FMF", fmul}, /* fast multiply */
+[10] {"FDV", fdiv}, /* fast divide */
+[11] {"FRD", fdivr}, /* fast reverse divide */
+/* POL deprecated */
+};
+
+static ulong
+fcmp(Internal *n, Internal *m)
+{
+ int i;
+ Internal rm, rn;
+
+ if(IsWeird(m) || IsWeird(n)){
+ /* BUG: should trap if not masked */
+ return V|C;
+ }
+ rn = *n;
+ rm = *m;
+ fpiround(&rn);
+ fpiround(&rm);
+ i = fpicmp(&rn, &rm);
+ if(i > 0)
+ return C;
+ else if(i == 0)
+ return C|Z;
+ else
+ return N;
+}
+
+static void
+fld(void (*f)(Internal*, void*), int d, ulong ea, int n, FPsave *ufp)
+{
+ void *mem;
+
+ mem = (void*)ea;
+ (*f)(&FR(ufp, d), mem);
+ if(fpemudebug)
+ print("MOV%c #%lux, F%d\n", n==8? 'D': 'F', ea, d);
+}
+
+static void
+fst(void (*f)(void*, Internal*), ulong ea, int s, int n, FPsave *ufp)
+{
+ Internal tmp;
+ void *mem;
+
+ mem = (void*)ea;
+ tmp = FR(ufp, s);
+ if(fpemudebug)
+ print("MOV%c F%d,#%lux\n", n==8? 'D': 'F', s, ea);
+ (*f)(mem, &tmp);
+}
+
+static int
+condok(int cc, int c)
+{
+ switch(c){
+ case 0: /* Z set */
+ return cc&Z;
+ case 1: /* Z clear */
+ return (cc&Z) == 0;
+ case 2: /* C set */
+ return cc&C;
+ case 3: /* C clear */
+ return (cc&C) == 0;
+ case 4: /* N set */
+ return cc&N;
+ case 5: /* N clear */
+ return (cc&N) == 0;
+ case 6: /* V set */
+ return cc&V;
+ case 7: /* V clear */
+ return (cc&V) == 0;
+ case 8: /* C set and Z clear */
+ return cc&C && (cc&Z) == 0;
+ case 9: /* C clear or Z set */
+ return (cc&C) == 0 || cc&Z;
+ case 10: /* N set and V set, or N clear and V clear */
+ return (~cc&(N|V))==0 || (cc&(N|V)) == 0;
+ case 11: /* N set and V clear, or N clear and V set */
+ return (cc&(N|V))==N || (cc&(N|V))==V;
+ case 12: /* Z clear, and either N set and V set or N clear and V clear */
+ return (cc&Z) == 0 && ((~cc&(N|V))==0 || (cc&(N|V))==0);
+ case 13: /* Z set, or N set and V clear or N clear and V set */
+ return (cc&Z) || (cc&(N|V))==N || (cc&(N|V))==V;
+ case 14: /* always */
+ return 1;
+ case 15: /* never (reserved) */
+ return 0;
+ }
+ return 0; /* not reached */
+}
+
+static void
+unimp(ulong pc, ulong op)
+{
+ char buf[60];
+
+ snprint(buf, sizeof(buf), "sys: fp: pc=%lux unimp fp 0x%.8lux", pc, op);
+ if(fpemudebug)
+ print("FPE: %s\n", buf);
+ error(buf);
+ /* no return */
+}
+
+static void
+fpemu(ulong pc, ulong op, Ureg *ur, FPsave *ufp)
+{
+ int rn, rd, tag, o;
+ long off;
+ ulong ea;
+ Internal tmp, *fm, *fn;
+
+ /* note: would update fault status here if we noted numeric exceptions */
+
+ /*
+ * LDF, STF; 10.1.1
+ */
+ if(((op>>25)&7) == 6){
+ if(op & (1<<22))
+ unimp(pc, op); /* packed or extended */
+ rn = (op>>16)&0xF;
+ off = (op&0xFF)<<2;
+ if((op & (1<<23)) == 0)
+ off = -off;
+ ea = REG(ur, rn);
+ if(rn == REGPC)
+ ea += 8;
+ if(op & (1<<24))
+ ea += off;
+ rd = (op>>12)&7;
+ if(op & (1<<20)){
+ if(op & (1<<15))
+ fld(fpid2i, rd, ea, 8, ufp);
+ else
+ fld(fpis2i, rd, ea, 4, ufp);
+ }else{
+ if(op & (1<<15))
+ fst(fpii2d, ea, rd, 8, ufp);
+ else
+ fst(fpii2s, ea, rd, 4, ufp);
+ }
+ if((op & (1<<24)) == 0)
+ ea += off;
+ if(op & (1<<21))
+ REG(ur, rn) = ea;
+ return;
+ }
+
+ /*
+ * CPRT/transfer, 10.3
+ */
+ if(op & (1<<4)){
+ rd = (op>>12) & 0xF;
+
+ /*
+ * compare, 10.3.1
+ */
+ if(rd == 15 && op & (1<<20)){
+ rn = (op>>16)&7;
+ fn = &FR(ufp, rn);
+ if(op & (1<<3)){
+ fm = &fpconst[op&7];
+ if(fpemudebug)
+ tag = 'C';
+ }else{
+ fm = &FR(ufp, op&7);
+ if(fpemudebug)
+ tag = 'F';
+ }
+ switch((op>>21)&7){
+ default:
+ unimp(pc, op);
+ case 4: /* CMF: Fn :: Fm */
+ case 6: /* CMFE: Fn :: Fm (with exception) */
+ ur->psr &= ~(N|C|Z|V);
+ ur->psr |= fcmp(fn, fm);
+ break;
+ case 5: /* CNF: Fn :: -Fm */
+ case 7: /* CNFE: Fn :: -Fm (with exception) */
+ tmp = *fm;
+ tmp.s ^= 1;
+ ur->psr &= ~(N|C|Z|V);
+ ur->psr |= fcmp(fn, &tmp);
+ break;
+ }
+ if(fpemudebug)
+ print("CMPF %c%d,F%ld =%#lux\n",
+ tag, rn, op&7, ur->psr>>28);
+ return;
+ }
+
+ /*
+ * other transfer, 10.3
+ */
+ switch((op>>20)&0xF){
+ default:
+ unimp(pc, op);
+ case 0: /* FLT */
+ rn = (op>>16) & 7;
+ fpiw2i(&FR(ufp, rn), &REG(ur, rd));
+ if(fpemudebug)
+ print("MOVW[FD] R%d, F%d\n", rd, rn);
+ break;
+ case 1: /* FIX */
+ if(op & (1<<3))
+ unimp(pc, op);
+ rn = op & 7;
+ tmp = FR(ufp, rn);
+ fpii2w(&REG(ur, rd), &tmp);
+ if(fpemudebug)
+ print("MOV[FD]W F%d, R%d =%ld\n", rn, rd, REG(ur, rd));
+ break;
+ case 2: /* FPSR := Rd */
+ ufp->status = REG(ur, rd);
+ if(fpemudebug)
+ print("MOVW R%d, FPSR\n", rd);
+ break;
+ case 3: /* Rd := FPSR */
+ REG(ur, rd) = ufp->status;
+ if(fpemudebug)
+ print("MOVW FPSR, R%d\n", rd);
+ break;
+ case 4: /* FPCR := Rd */
+ ufp->control = REG(ur, rd);
+ if(fpemudebug)
+ print("MOVW R%d, FPCR\n", rd);
+ break;
+ case 5: /* Rd := FPCR */
+ REG(ur, rd) = ufp->control;
+ if(fpemudebug)
+ print("MOVW FPCR, R%d\n", rd);
+ break;
+ }
+ return;
+ }
+
+ /*
+ * arithmetic
+ */
+
+ if(op & (1<<3)){ /* constant */
+ fm = &fpconst[op&7];
+ if(fpemudebug)
+ tag = 'C';
+ }else{
+ fm = &FR(ufp, op&7);
+ if(fpemudebug)
+ tag = 'F';
+ }
+ rd = (op>>12)&7;
+ o = (op>>20)&0xF;
+ if(op & (1<<15)){ /* monadic */
+ FP1 *fp;
+ fp = &optab1[o];
+ if(fp->f == nil)
+ unimp(pc, op);
+ if(fpemudebug)
+ print("%s %c%ld,F%d\n", fp->name, tag, op&7, rd);
+ (*fp->f)(fm, &FR(ufp, rd));
+ } else {
+ FP2 *fp;
+ fp = &optab2[o];
+ if(fp->f == nil)
+ unimp(pc, op);
+ rn = (op>>16)&7;
+ if(fpemudebug)
+ print("%s %c%ld,F%d,F%d\n", fp->name, tag, op&7, rn, rd);
+ (*fp->f)(*fm, FR(ufp, rn), &FR(ufp, rd));
+ }
+}
+
+void
+casemu(ulong pc, ulong op, Ureg *ur)
+{
+ ulong *rp, ro, rn, *rd;
+
+ USED(pc);
+
+ rp = (ulong*)ur;
+ ro = rp[op>>16 & 0x7];
+ rn = rp[op>>0 & 0x7];
+ rd = rp + (op>>12 & 0x7);
+ rp = (ulong*)*rd;
+ validaddr((ulong)rp, 4, 1);
+ splhi();
+ if(*rd = (*rp == ro))
+ *rp = rn;
+ spllo();
+}
+
+int ldrexvalid;
+
+void
+ldrex(ulong pc, ulong op, Ureg *ur)
+{
+ ulong *rp, *rd, *addr;
+
+ USED(pc);
+
+ rp = (ulong*)ur;
+ rd = rp + (op>>16 & 0x7);
+ addr = (ulong*)*rd;
+ validaddr((ulong)addr, 4, 0);
+ ldrexvalid = 1;
+ rp[op>>12 & 0x7] = *addr;
+ if(fpemudebug)
+ print("ldrex, r%ld = [r%ld]@0x%8.8p = 0x%8.8lux",
+ op>>12 & 0x7, op>>16 & 0x7, addr, rp[op>>12 & 0x7]);
+}
+
+void
+strex(ulong pc, ulong op, Ureg *ur)
+{
+ ulong *rp, rn, *rd, *addr;
+
+ USED(pc);
+
+ rp = (ulong*)ur;
+ rd = rp + (op>>16 & 0x7);
+ rn = rp[op>>0 & 0x7];
+ addr = (ulong*)*rd;
+ validaddr((ulong)addr, 4, 1);
+ splhi();
+ if(ldrexvalid){
+ if(fpemudebug)
+ print("strex valid, [r%ld]@0x%8.8p = r%ld = 0x%8.8lux",
+ op>>16 & 0x7, addr, op>>0 & 0x7, rn);
+ *addr = rn;
+ ldrexvalid = 0;
+ rp[op>>12 & 0x7] = 0;
+ }else{
+ if(fpemudebug)
+ print("strex invalid, r%ld = 1", op>>16 & 0x7);
+ rp[op>>12 & 0x7] = 1;
+ }
+ spllo();
+}
+
+struct {
+ ulong opc;
+ ulong mask;
+ void (*f)(ulong, ulong, Ureg*);
+} specialopc[] = {
+ { 0x01900f9f, 0x0ff00fff, ldrex },
+ { 0x01800f90, 0x0ff00ff0, strex },
+ { 0x0ed00100, 0x0ef08100, casemu },
+ { 0x00000000, 0x00000000, nil }
+};
+
+/*
+ * returns the number of FP instructions emulated
+ */
+int
+fpiarm(Ureg *ur)
+{
+ ulong op, o;
+ FPsave *ufp;
+ int i, n;
+
+ if(up == nil)
+ panic("fpiarm not in a process");
+ ufp = &up->fpsave;
+ /* because all the state is in the proc structure,
+ * it need not be saved/restored
+ */
+ if(up->fpstate != FPactive){
+// assert(sizeof(Internal) == sizeof(ufp->regs[0]));
+ up->fpstate = FPactive;
+ ufp->control = 0;
+ ufp->status = (0x01<<28)|(1<<12); /* software emulation, alternative C flag */
+ for(n = 0; n < 8; n++)
+ FR(ufp, n) = fpconst[0];
+ }
+ for(n=0; ;n++){
+ validaddr(ur->pc, 4, 0);
+ op = *(ulong*)(ur->pc);
+ if(fpemudebug)
+ print("%#lux: %#8.8lux ", ur->pc, op);
+ o = (op>>24) & 0xF;
+ if(condok(ur->psr, op>>28)){
+ for(i = 0; specialopc[i].f; i++)
+ if((op & specialopc[i].mask) == specialopc[i].opc)
+ break;
+ if(specialopc[i].f)
+ specialopc[i].f(ur->pc, op, ur);
+ else if((op & 0xF00) != 0x100 || o != 0xE && (o&~1) != 0xC)
+ break;
+ else
+ fpemu(ur->pc, op, ur, ufp);
+ }else if((op & 0xF00) != 0x100 || o != 0xE && (o&~1) != 0xC)
+ break;
+ ur->pc += 4;
+ }
+ if(fpemudebug) print("\n");
+ return n;
+}
diff --git a/sys/src/9/kw/fpimem.c b/sys/src/9/kw/fpimem.c
new file mode 100755
index 000000000..627ab6355
--- /dev/null
+++ b/sys/src/9/kw/fpimem.c
@@ -0,0 +1,136 @@
+#include "fpi.h"
+
+/*
+ * the following routines depend on memory format, not the machine
+ */
+
+void
+fpis2i(Internal *i, void *v)
+{
+ Single *s = v;
+
+ i->s = (*s & 0x80000000) ? 1: 0;
+ if((*s & ~0x80000000) == 0){
+ SetZero(i);
+ return;
+ }
+ i->e = ((*s>>23) & 0x00FF) - SingleExpBias + ExpBias;
+ i->h = (*s & 0x007FFFFF)<<(1+NGuardBits);
+ i->l = 0;
+ if(i->e)
+ i->h |= HiddenBit;
+ else
+ i->e++;
+}
+
+void
+fpid2i(Internal *i, void *v)
+{
+ Double *d = v;
+
+ i->s = (d->h & 0x80000000) ? 1: 0;
+ i->e = (d->h>>20) & 0x07FF;
+ i->h = ((d->h & 0x000FFFFF)<<(4+NGuardBits))|((d->l>>25) & 0x7F);
+ i->l = (d->l & 0x01FFFFFF)<<NGuardBits;
+ if(i->e)
+ i->h |= HiddenBit;
+ else
+ i->e++;
+}
+
+void
+fpiw2i(Internal *i, void *v)
+{
+ Word w, word = *(Word*)v;
+ short e;
+
+ if(word < 0){
+ i->s = 1;
+ word = -word;
+ }
+ else
+ i->s = 0;
+ if(word == 0){
+ SetZero(i);
+ return;
+ }
+ if(word > 0){
+ for (e = 0, w = word; w; w >>= 1, e++)
+ ;
+ } else
+ e = 32;
+ if(e > FractBits){
+ i->h = word>>(e - FractBits);
+ i->l = (word & ((1<<(e - FractBits)) - 1))<<(2*FractBits - e);
+ }
+ else {
+ i->h = word<<(FractBits - e);
+ i->l = 0;
+ }
+ i->e = (e - 1) + ExpBias;
+}
+
+void
+fpii2s(void *v, Internal *i)
+{
+ short e;
+ Single *s = (Single*)v;
+
+ fpiround(i);
+ if(i->h & HiddenBit)
+ i->h &= ~HiddenBit;
+ else
+ i->e--;
+ *s = i->s ? 0x80000000: 0;
+ e = i->e;
+ if(e < ExpBias){
+ if(e <= (ExpBias - SingleExpBias))
+ return;
+ e = SingleExpBias - (ExpBias - e);
+ }
+ else if(e >= (ExpBias + (SingleExpMax-SingleExpBias))){
+ *s |= SingleExpMax<<23;
+ return;
+ }
+ else
+ e = SingleExpBias + (e - ExpBias);
+ *s |= (e<<23)|(i->h>>(1+NGuardBits));
+}
+
+void
+fpii2d(void *v, Internal *i)
+{
+ Double *d = (Double*)v;
+
+ fpiround(i);
+ if(i->h & HiddenBit)
+ i->h &= ~HiddenBit;
+ else
+ i->e--;
+ i->l = ((i->h & GuardMask)<<25)|(i->l>>NGuardBits);
+ i->h >>= NGuardBits;
+ d->h = i->s ? 0x80000000: 0;
+ d->h |= (i->e<<20)|((i->h & 0x00FFFFFF)>>4);
+ d->l = (i->h<<28)|i->l;
+}
+
+void
+fpii2w(Word *word, Internal *i)
+{
+ Word w;
+ short e;
+
+ fpiround(i);
+ e = (i->e - ExpBias) + 1;
+ if(e <= 0)
+ w = 0;
+ else if(e > 31)
+ w = 0x7FFFFFFF;
+ else if(e > FractBits)
+ w = (i->h<<(e - FractBits))|(i->l>>(2*FractBits - e));
+ else
+ w = i->h>>(FractBits-e);
+ if(i->s)
+ w = -w;
+ *word = w;
+}
diff --git a/sys/src/9/kw/init9.s b/sys/src/9/kw/init9.s
new file mode 100755
index 000000000..1d7f2bec3
--- /dev/null
+++ b/sys/src/9/kw/init9.s
@@ -0,0 +1,25 @@
+/*
+ * This is the same as the C programme:
+ *
+ * void
+ * main(char* argv0)
+ * {
+ * startboot(argv0, &argv0);
+ * }
+ *
+ * It is in assembler because SB needs to be
+ * set and doing this in C drags in too many
+ * other routines.
+ */
+TEXT main(SB), 1, $8
+ MOVW $setR12(SB), R12 /* load the SB */
+ MOVW $boot(SB), R0
+
+ ADD $12, R13, R1 /* pointer to 0(FP) */
+
+ MOVW R0, 4(R13) /* pass argc, argv */
+ MOVW R1, 8(R13)
+
+ BL startboot(SB)
+_loop:
+ B _loop
diff --git a/sys/src/9/kw/io.h b/sys/src/9/kw/io.h
new file mode 100755
index 000000000..f1ad24689
--- /dev/null
+++ b/sys/src/9/kw/io.h
@@ -0,0 +1,425 @@
+enum {
+ BusCBUS = 0, /* Corollary CBUS */
+ BusCBUSII, /* Corollary CBUS II */
+ BusEISA, /* Extended ISA */
+ BusFUTURE, /* IEEE Futurebus */
+ BusINTERN, /* Internal bus */
+ BusISA, /* Industry Standard Architecture */
+ BusMBI, /* Multibus I */
+ BusMBII, /* Multibus II */
+ BusMCA, /* Micro Channel Architecture */
+ BusMPI, /* MPI */
+ BusMPSA, /* MPSA */
+ BusNUBUS, /* Apple Macintosh NuBus */
+ BusPCI, /* Peripheral Component Interconnect */
+ BusPCMCIA, /* PC Memory Card International Association */
+ BusTC, /* DEC TurboChannel */
+ BusVL, /* VESA Local bus */
+ BusVME, /* VMEbus */
+ BusXPRESS, /* Express System Bus */
+ BUSUNKNOWN = -1
+};
+
+#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
+#define BUSFNO(tbdf) (((tbdf)>>8)&0x07)
+#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F)
+#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF)
+#define BUSTYPE(tbdf) ((tbdf)>>24)
+#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00)
+
+/*
+ * PCI support code.
+ */
+enum { /* type 0 & type 1 pre-defined header */
+ PciVID = 0x00, /* vendor ID */
+ PciDID = 0x02, /* device ID */
+ PciPCR = 0x04, /* command */
+ PciPSR = 0x06, /* status */
+ PciRID = 0x08, /* revision ID */
+ PciCCRp = 0x09, /* programming interface class code */
+ PciCCRu = 0x0A, /* sub-class code */
+ PciCCRb = 0x0B, /* base class code */
+ PciCLS = 0x0C, /* cache line size */
+ PciLTR = 0x0D, /* latency timer */
+ PciHDT = 0x0E, /* header type */
+ PciBST = 0x0F, /* BIST */
+};
+
+/* ccrb (base class code) values; controller types */
+enum {
+ Pcibcpci1 = 0, /* pci 1.0; no class codes defined */
+ Pcibcstore = 1, /* mass storage */
+ Pcibcnet = 2, /* network */
+ Pcibcdisp = 3, /* display */
+ Pcibcmmedia = 4, /* multimedia */
+ Pcibcmem = 5, /* memory */
+ Pcibcbridge = 6, /* bridge */
+ Pcibccomm = 7, /* simple comms (e.g., serial) */
+ Pcibcbasesys = 8, /* base system */
+ Pcibcinput = 9, /* input */
+ Pcibcdock = 0xa, /* docking stations */
+ Pcibcproc = 0xb, /* processors */
+ Pcibcserial = 0xc, /* serial bus (e.g., USB) */
+ Pcibcwireless = 0xd, /* wireless */
+ Pcibcintell = 0xe, /* intelligent i/o */
+ Pcibcsatcom = 0xf, /* satellite comms */
+ Pcibccrypto = 0x10, /* encryption/decryption */
+ Pcibcdacq = 0x11, /* data acquisition & signal proc. */
+};
+
+/* ccru (sub-class code) values; common cases only */
+enum {
+ /* mass storage */
+ Pciscscsi = 0, /* SCSI */
+ Pciscide = 1, /* IDE (ATA) */
+
+ /* network */
+ Pciscether = 0, /* Ethernet */
+
+ /* display */
+ Pciscvga = 0, /* VGA */
+ Pciscxga = 1, /* XGA */
+ Pcisc3d = 2, /* 3D */
+
+ /* bridges */
+ Pcischostpci = 0, /* host/pci */
+ Pciscpcicpci = 1, /* pci/pci */
+
+ /* simple comms */
+ Pciscserial = 0, /* 16450, etc. */
+ Pciscmultiser = 1, /* multiport serial */
+
+ /* serial bus */
+ Pciscusb = 3, /* USB */
+};
+
+enum { /* type 0 pre-defined header */
+ PciCIS = 0x28, /* cardbus CIS pointer */
+ PciSVID = 0x2C, /* subsystem vendor ID */
+ PciSID = 0x2E, /* cardbus CIS pointer */
+ PciEBAR0 = 0x30, /* expansion ROM base address */
+ PciMGNT = 0x3E, /* burst period length */
+ PciMLT = 0x3F, /* maximum latency between bursts */
+};
+
+enum { /* type 1 pre-defined header */
+ PciPBN = 0x18, /* primary bus number */
+ PciSBN = 0x19, /* secondary bus number */
+ PciUBN = 0x1A, /* subordinate bus number */
+ PciSLTR = 0x1B, /* secondary latency timer */
+ PciIBR = 0x1C, /* I/O base */
+ PciILR = 0x1D, /* I/O limit */
+ PciSPSR = 0x1E, /* secondary status */
+ PciMBR = 0x20, /* memory base */
+ PciMLR = 0x22, /* memory limit */
+ PciPMBR = 0x24, /* prefetchable memory base */
+ PciPMLR = 0x26, /* prefetchable memory limit */
+ PciPUBR = 0x28, /* prefetchable base upper 32 bits */
+ PciPULR = 0x2C, /* prefetchable limit upper 32 bits */
+ PciIUBR = 0x30, /* I/O base upper 16 bits */
+ PciIULR = 0x32, /* I/O limit upper 16 bits */
+ PciEBAR1 = 0x28, /* expansion ROM base address */
+ PciBCR = 0x3E, /* bridge control register */
+};
+
+enum { /* type 2 pre-defined header */
+ PciCBExCA = 0x10,
+ PciCBSPSR = 0x16,
+ PciCBPBN = 0x18, /* primary bus number */
+ PciCBSBN = 0x19, /* secondary bus number */
+ PciCBUBN = 0x1A, /* subordinate bus number */
+ PciCBSLTR = 0x1B, /* secondary latency timer */
+ PciCBMBR0 = 0x1C,
+ PciCBMLR0 = 0x20,
+ PciCBMBR1 = 0x24,
+ PciCBMLR1 = 0x28,
+ PciCBIBR0 = 0x2C, /* I/O base */
+ PciCBILR0 = 0x30, /* I/O limit */
+ PciCBIBR1 = 0x34, /* I/O base */
+ PciCBILR1 = 0x38, /* I/O limit */
+ PciCBSVID = 0x40, /* subsystem vendor ID */
+ PciCBSID = 0x42, /* subsystem ID */
+ PciCBLMBAR = 0x44, /* legacy mode base address */
+};
+
+typedef struct Pcisiz Pcisiz;
+struct Pcisiz
+{
+ Pcidev* dev;
+ int siz;
+ int bar;
+};
+
+typedef struct Pcidev Pcidev;
+struct Pcidev
+{
+ int tbdf; /* type+bus+device+function */
+ ushort vid; /* vendor ID */
+ ushort did; /* device ID */
+
+ ushort pcr;
+
+ uchar rid;
+ uchar ccrp;
+ uchar ccru;
+ uchar ccrb;
+ uchar cls;
+ uchar ltr;
+
+ struct {
+ ulong bar; /* base address */
+ int size;
+ } mem[6];
+
+ struct {
+ ulong bar;
+ int size;
+ } rom;
+ uchar intl; /* interrupt line */
+
+ Pcidev* list;
+ Pcidev* link; /* next device on this bno */
+
+ Pcidev* bridge; /* down a bus */
+ struct {
+ ulong bar;
+ int size;
+ } ioa, mema;
+
+ int pmrb; /* power management register block */
+};
+
+#define PCIWINDOW 0
+#define PCIWADDR(va) (PADDR(va)+PCIWINDOW)
+
+/*
+ * Kirkwood stuff
+ */
+
+enum {
+ AddrEfuse = PHYSIO+0x1008c,
+ Addrpci = PHYSIO+0x40000, /* for registers below */
+ Addrpcibase = PHYSIO+0x41800, /* for registers below */
+ AddrMpp = PHYSIO+0x10000,
+ AddrSdio = PHYSIO+0x90000,
+};
+
+enum {
+ Socrevz0,
+ Socreva0 = 2,
+ Socreva1,
+};
+
+enum {
+ /* registers; if we actually use these, change to soc.pci(base)->reg */
+ PciBAR0 = Addrpcibase + 4, /* base address */
+ PciBAR1 = Addrpcibase + 8,
+
+ PciCP = Addrpci + 0x64, /* capabilities pointer */
+
+ PciINTL = Addrpci + 0x3c, /* interrupt line */
+ PciINTP = PciINTL + 1, /* interrupt pin */
+};
+
+/*
+ * interrupt stuff
+ */
+
+enum {
+ Irqlo, Irqhi, Irqbridge,
+};
+
+enum {
+ /* main interrupt cause low register bit #s (LE) */
+ IRQ0hisum, /* summary of main intr high cause reg */
+ IRQ0bridge,
+ IRQ0h2cdoorbell,
+ IRQ0c2hdoorbell,
+ _IRQ0reserved0,
+ IRQ0xor0chan0,
+ IRQ0xor0chan1,
+ IRQ0xor1chan0,
+ IRQ0xor1chan1,
+ IRQ0pex0int, /* pex = pci-express */
+ _IRQ0reserved1,
+ IRQ0gbe0sum,
+ IRQ0gbe0rx,
+ IRQ0gbe0tx,
+ IRQ0gbe0misc,
+ IRQ0gbe1sum,
+ IRQ0gbe1rx,
+ IRQ0gbe1tx,
+ IRQ0gbe1misc,
+ IRQ0usb0,
+ _IRQ0reserved2,
+ IRQ0sata,
+ IRQ0crypto,
+ IRQ0spi,
+ IRQ0audio,
+ _IRQ0reserved3,
+ IRQ0ts0,
+ _IRQ0reserved4,
+ IRQ0sdio,
+ IRQ0twsi,
+ IRQ0avb,
+ IRQ0tdm,
+
+ /* main interrupt cause high register bit #s (LE) */
+ _IRQ1reserved0 = 0,
+ IRQ1uart0,
+ IRQ1uart1,
+ IRQ1gpiolo0,
+ IRQ1gpiolo1,
+ IRQ1gpiolo2,
+ IRQ1gpiolo3,
+ IRQ1gpiohi0,
+ IRQ1gpiohi1,
+ IRQ1gpiohi2,
+ IRQ1gpiohi3,
+ IRQ1xor0err,
+ IRQ1xor1err,
+ IRQ1pex0err,
+ _IRQ1reserved1,
+ IRQ1gbe0err,
+ IRQ1gbe1err,
+ IRQ1usberr,
+ IRQ1cryptoerr,
+ IRQ1audioerr,
+ _IRQ1reserved2,
+ _IRQ1reserved3,
+ IRQ1rtc,
+
+ /* bridged-interrupt causes */
+ IRQcpuself = 0,
+ IRQcputimer0,
+ IRQcputimer1,
+ IRQcputimerwd,
+ IRQaccesserr,
+};
+
+/*
+ * interrupt controller
+ */
+typedef struct IntrReg IntrReg;
+struct IntrReg
+{
+ struct {
+ ulong irq; /* main intr cause reg (ro) */
+ ulong irqmask;
+ ulong fiqmask;
+ ulong epmask;
+ } lo, hi;
+};
+
+/*
+ * CPU control & status (archkw.c and trap.c)
+ */
+typedef struct CpucsReg CpucsReg;
+struct CpucsReg
+{
+ ulong cpucfg;
+ ulong cpucsr;
+ ulong rstout;
+ ulong softreset;
+ ulong irq; /* mbus(-l) bridge interrupt cause */
+ ulong irqmask; /* ⋯ mask */
+ ulong mempm; /* memory power mgmt. control */
+ ulong clockgate; /* clock enable bits */
+ ulong biu;
+ ulong pad0;
+ ulong l2cfg; /* turn l2 cache on or off, set coherency */
+ ulong pad1[2];
+ ulong l2tm0;
+ ulong l2tm1;
+ ulong pad2[2];
+ ulong l2pm;
+ ulong ram0;
+ ulong ram1;
+ ulong ram2;
+ ulong ram3;
+};
+
+enum {
+ /* cpucfg bits */
+ Cfgvecinithi = 1<<1, /* boot at 0xffff0000, not 0; default 1 */
+ Cfgbigendreset = 3<<1, /* init. as big-endian at reset; default 0 */
+ Cfgiprefetch = 1<<16, /* instruction prefetch enable */
+ Cfgdprefetch = 1<<17, /* data prefetch enable */
+
+ /* cpucsr bits */
+ Reset = 1<<1, /* reset cpu core */
+
+ /* rstout bits */
+ RstoutPex = 1<<0, /* assert RSTOUTn at pci-e reset */
+ RstoutWatchdog = 1<<1, /* assert RSTOUTn at watchdog timeout */
+ RstoutSoft = 1<<2, /* assert RSTOUTn at sw reset */
+
+ /* softreset bits */
+ ResetSystem = 1<<0, /* assert RSTOUTn pin on SoftRstOutEn */
+
+ /* l2cfg bits */
+ L2ecc = 1<<2,
+ L2exists = 1<<3, /* l2 cache doesn't ignore cpu */
+ L2writethru = 1<<4, /* always WT, else see PTE C & B */
+};
+
+enum {
+ /* from 88f6281 func'l specs (MV-S104860-00), tables 2 & 3, chapter 2 */
+ Targdram = 0, /* ddr sdram */
+ Targflash = 1,
+ Targcesasram = 3, /* security accelerator sram */
+
+ /* attributes */
+ Attrcs0 = 0xe, /* chip select 0 (low dram) */
+ Attrcs1 = 0xd, /* chip select 1 (high dram) */
+ Attrbootrom = 0x1d,
+ Attrspi = 0x1e,
+ Attrnand = 0x2f,
+
+ Winenable = 1<<0,
+};
+
+typedef struct Pciex Pciex;
+struct Pciex {
+ ushort venid; /* 0x11ab means Marvell */
+ ushort devid; /* 0x6281 means 6281 */
+ ulong csr;
+ ulong revid;
+ ulong bistcache; /* bist hdr type & cache-line size */
+ ulong bar0;
+ ulong bar0hi;
+ ulong bar1;
+ ulong bar1hi;
+ ulong bar2;
+ ulong bar2hi;
+ ulong _pad0;
+ ushort ssvenid; /* 0x11ab means Marvell */
+ ushort ssdevid; /* 0x11ab means Marvell */
+ ulong rombar;
+ ulong caplist;
+ ulong _pad1;
+ ulong intrpinline; /* interrupt pin & line */
+ ulong pmcap; /* power mgmt. capability header */
+ ulong pmcsr; /* power mgmt. control & status */
+ ulong _pad2[2];
+ ulong msictl; /* msi message control */
+ ulong msiaddr;
+ ulong msiaddrhi;
+ ulong msidata;
+ ulong cap;
+ ulong devcap;
+ ulong devcsr;
+ ulong linkcap;
+ ulong linkcsr;
+
+ uchar _pad[0x40100-0x40074];
+ ulong errrep; /* advanced error report header */
+ ulong uncorrerr; /* uncorrectable error status */
+ ulong uncorrerrmask; /* uncorrectable error mask */
+ ulong uncorrerrsev; /* uncorrectable error severity */
+ ulong correrr; /* correctable error status */
+ ulong correrrmask; /* correctable error mask */
+ ulong errcap; /* advanced error capability & ctl. */
+ ulong hdrlog[4]; /* header log */
+ /* continues with more rubbish at 0x41a00. some day... */
+};
diff --git a/sys/src/9/kw/l.s b/sys/src/9/kw/l.s
new file mode 100755
index 000000000..f538b5d8d
--- /dev/null
+++ b/sys/src/9/kw/l.s
@@ -0,0 +1,774 @@
+/*
+ * sheevaplug machine assist
+ * arm926ej-s processor at 1.2GHz
+ *
+ * loader uses R11 as scratch.
+ * R9 and R10 are used for `extern register' variables.
+ *
+ * ARM v7 arch. ref. man. (I know, this is v5) §B1.3.3 that
+ * we don't need barriers around moves to CPSR. The ARM v6 manual
+ * seems to be silent on the subject.
+ */
+#include "arm.s"
+
+/*
+ * MCR and MRC are counter-intuitively named.
+ * MCR coproc, opcode1, Rd, CRn, CRm[, opcode2] # arm -> coproc
+ * MRC coproc, opcode1, Rd, CRn, CRm[, opcode2] # coproc -> arm
+ */
+
+/*
+ * Entered here from Das U-Boot with MMU disabled.
+ * Until the MMU is enabled it is OK to call functions provided
+ * they are within ±32MiB relative and do not require any
+ * local variables or more than one argument (i.e. there is
+ * no stack).
+ */
+TEXT _start(SB), 1, $-4
+ MOVW $setR12(SB), R12 /* load the SB */
+_main:
+ /* SVC mode, interrupts disabled */
+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
+ MOVW R1, CPSR
+ BARRIERS
+
+ /*
+ * disable the MMU & caches,
+ * switch to system permission & 32-bit addresses.
+ */
+ MOVW $(CpCsystem|CpCd32|CpCi32), R1
+ MCR CpSC, 0, R1, C(CpCONTROL), C(0)
+ ISB
+
+ /*
+ * disable the Sheevaplug's L2 cache, invalidate all caches
+ */
+
+ /* flush caches. 926ejs manual says we have to do it iteratively. */
+_dwbinv0:
+ MRC CpSC, 0, PC, C(CpCACHE), C(CpCACHEwbi), CpCACHEtest
+ BNE _dwbinv0
+ /* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
+ BARRIERS
+
+ /* make the l2 cache pay attention */
+ MOVW $(PHYSIO+0x20100), R1 /* CPUCSREG */
+ MOVW (4*10)(R1), R2
+ ORR $(1<<3), R2 /* cpu->l2cfg |= L2exists */
+ MOVW R2, (4*10)(R1)
+ ISB
+
+ /* invalidate l2 cache */
+ MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2inv), CpTCl2all
+ ISB
+
+ /* disable l2 cache. do this while l1 caches are off */
+ MRC CpSC, CpL2, R1, C(CpTESTCFG), C(CpTCl2cfg), CpTCl2conf
+ /* disabling write allocation is probably for cortex-a8 errata 460075 */
+ /* l2 off, no wr alloc, no streaming */
+ BIC $(CpTCl2ena | CpTCl2wralloc | CpTCldcstream), R1
+ MCR CpSC, CpL2, R1, C(CpTESTCFG), C(CpTCl2cfg), CpTCl2conf
+ BARRIERS
+
+ /* flush caches. 926ejs manual says we have to do it iteratively. */
+_dwbinv1:
+ MRC CpSC, 0, PC, C(CpCACHE), C(CpCACHEwbi), CpCACHEtest
+ BNE _dwbinv1
+ BARRIERS
+
+WAVE('\r')
+ /* clear Mach */
+ MOVW $PADDR(MACHADDR), R4 /* address of Mach */
+_machZ:
+ MOVW R0, (R4)
+ ADD $4, R4 /* bump PTE address */
+ CMP.S $PADDR(L1+L1X(0)), R4
+ BNE _machZ
+
+ /*
+ * set up the MMU page table
+ */
+
+ /* clear all PTEs first, to provide a default */
+WAVE('\n')
+ MOVW $PADDR(L1+L1X(0)), R4 /* address of PTE for 0 */
+_ptenv0:
+ ZEROPTE()
+ CMP.S $PADDR(L1+16*KiB), R4
+ BNE _ptenv0
+
+ /* double map of PHYSDRAM, KZERO to PHYSDRAM for first few MBs */
+ MOVW $PTEDRAM, R2 /* PTE bits */
+ MOVW $PHYSDRAM, R3 /* pa */
+ MOVW $PADDR(L1+L1X(PHYSDRAM)), R4 /* address of PTE for PHYSDRAM */
+ MOVW $16, R5
+_ptdbl:
+ FILLPTE()
+ SUB.S $1, R5
+ BNE _ptdbl
+
+ /*
+ * back up and fill in PTEs for memory at KZERO
+ * there is 1 bank of 512MB of SDRAM at PHYSDRAM
+ */
+ MOVW $PTEDRAM, R2 /* PTE bits */
+ MOVW $PHYSDRAM, R3
+ MOVW $PADDR(L1+L1X(KZERO)), R4 /* start with PTE for KZERO */
+ MOVW $512, R5 /* inner loop count */
+_ptekrw: /* set PTEs for 512MiB */
+ FILLPTE()
+ SUB.S $1, R5
+ BNE _ptekrw
+
+ /*
+ * back up and fill in PTE for MMIO
+ */
+ MOVW $PTEIO, R2 /* PTE bits */
+ MOVW $PHYSIO, R3
+ MOVW $PADDR(L1+L1X(VIRTIO)), R4 /* start with PTE for VIRTIO */
+ FILLPTE()
+
+ /* mmu.c sets up the vectors later */
+
+ /*
+ * set up a temporary stack; avoid data & bss segments
+ */
+ MOVW $(PHYSDRAM | (128*1024*1024)), R13
+
+WAVE('P')
+ /* set the domain access control */
+ MOVW $Client, R0
+ BL dacput(SB)
+
+ /* set the translation table base */
+ MOVW $PADDR(L1), R0
+ BL ttbput(SB)
+
+ MOVW $0, R0
+ BL pidput(SB) /* paranoia */
+
+ /* the little dance to turn the MMU & caches on */
+WAVE('l')
+ BL cacheuwbinv(SB)
+ BL mmuinvalidate(SB)
+ BL mmuenable(SB)
+
+WAVE('a')
+ /* warp the PC into the virtual map */
+ MOVW $KZERO, R0
+ BL _r15warp(SB)
+
+ /*
+ * now running at KZERO+something!
+ */
+
+ MOVW $setR12(SB), R12 /* reload the SB */
+
+ /*
+ * set up temporary stack again, in case we've just switched
+ * to a new register set.
+ */
+ MOVW $(KZERO|(128*1024*1024)), R13
+
+ /* can now execute arbitrary C code */
+
+ BL cacheuwbinv(SB)
+
+WAVE('n')
+ /* undo double map of 0, KZERO */
+ MOVW $PADDR(L1+L1X(0)), R4 /* address of PTE for 0 */
+ MOVW $0, R0
+ MOVW $16, R5
+_ptudbl:
+ MOVW R0, (R4)
+ ADD $4, R4 /* bump PTE address */
+ ADD $MiB, R0 /* bump pa */
+ SUB.S $1, R5
+ BNE _ptudbl
+ BARRIERS
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvd), CpTLBinvse
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
+ BARRIERS
+
+WAVE(' ')
+ /* pass Mach to main and set up the stack */
+ MOVW $(MACHADDR), R0 /* Mach */
+ MOVW R0, R13
+ ADD $(MACHSIZE), R13 /* stack pointer */
+ SUB $4, R13 /* space for link register */
+
+ BL main(SB) /* void main(Mach*) */
+ /* fall through */
+
+
+/* not used */
+TEXT _reset(SB), 1, $-4
+ /* turn the caches off */
+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R0
+ MOVW R0, CPSR
+ BARRIERS
+ BL cacheuwbinv(SB)
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0)
+ BIC $(CpCwb|CpCicache|CpCdcache|CpCalign), R0
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0)
+ BARRIERS
+WAVE('R')
+
+ /* redo double map of 0, KZERO */
+ MOVW $(L1+L1X(0)), R4 /* address of PTE for 0 */
+ MOVW $PTEDRAM, R2 /* PTE bits */
+ MOVW $0, R3
+ MOVW $16, R5
+_ptrdbl:
+ ORR R3, R2, R1 /* first identity-map 0 to 0, etc. */
+ MOVW R1, (R4)
+ ADD $4, R4 /* bump PTE address */
+ ADD $MiB, R3 /* bump pa */
+ SUB.S $1, R5
+ BNE _ptrdbl
+
+ BARRIERS
+WAVE('e')
+ MOVW $0, R0
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvd), CpTLBinv
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
+ BARRIERS
+
+ /* back to 29- or 26-bit addressing, mainly for SB */
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0)
+ BIC $(CpCd32|CpCi32), R0
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0)
+ BARRIERS
+
+ /* turn the MMU off */
+ MOVW $PHYSDRAM, R0
+ BL _r15warp(SB)
+ BL mmuinvalidate(SB)
+ BL mmudisable(SB)
+
+WAVE('s')
+ /* set new reset vector */
+ MOVW $0, R2
+ MOVW $0xe59ff018, R3 /* MOVW 0x18(R15), R15 */
+ MOVW R3, (R2)
+WAVE('e')
+
+ MOVW $PHYSBOOTROM, R3
+ MOVW R3, 0x20(R2) /* where $0xe59ff018 jumps to */
+ BARRIERS
+WAVE('t')
+WAVE('\r')
+WAVE('\n')
+
+ /* ...and jump to it */
+ MOVW R2, R15 /* software reboot */
+_limbo: /* should not get here... */
+ B _limbo /* ... and can't get out */
+ BL _div(SB) /* hack to load _div, etc. */
+
+TEXT _r15warp(SB), 1, $-4
+ BIC $KSEGM, R14
+ ORR R0, R14
+ BIC $KSEGM, R13
+ ORR R0, R13
+ RET
+
+/* clobbers R1, R6 */
+TEXT myputc(SB), 1, $-4
+ MOVW $PHYSCONS, R6
+_busy:
+ MOVW 20(R6), R1
+ BIC.S $~(1<<5), R1 /* (x->lsr & LSRthre) == 0? */
+ BEQ _busy
+ MOVW R3, (R6) /* print */
+ ISB
+ RET
+
+/*
+ * l1 caches
+ */
+
+TEXT l1cacheson(SB), 1, $-4
+ MOVW CPSR, R5
+ ORR $(PsrDirq|PsrDfiq), R5, R4
+ MOVW R4, CPSR /* splhi */
+
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0)
+ ORR $(CpCdcache|CpCicache|CpCwb), R0
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0)
+ BARRIERS
+
+ MOVW R5, CPSR /* splx */
+ RET
+
+TEXT l1cachesoff(SB), 1, $-4
+ MOVM.DB.W [R14], (SP) /* save lr on stack */
+
+ MOVW CPSR, R5
+ ORR $(PsrDirq|PsrDfiq), R5, R4
+ MOVW R4, CPSR /* splhi */
+
+ BL cacheuwbinv(SB)
+
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0)
+ BIC $(CpCdcache|CpCicache|CpCwb), R0
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0)
+ BARRIERS
+
+ MOVW R5, CPSR /* splx */
+ MOVM.IA.W (SP), [R14] /* restore lr */
+ RET
+
+/*
+ * cache* functions affect only the L1 caches, which are VIVT.
+ */
+
+TEXT cachedwb(SB), 1, $-4 /* D writeback */
+ MOVW CPSR, R3 /* splhi */
+ ORR $(PsrDirq), R3, R1
+ MOVW R1, CPSR
+
+ BARRIERS /* force outstanding stores to cache */
+ /* keep writing back dirty cache lines until no more exist */
+_dwb:
+ MRC CpSC, 0, PC, C(CpCACHE), C(CpCACHEwb), CpCACHEtest
+ BNE _dwb
+ /* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
+ BARRIERS
+
+ MOVW R3, CPSR /* splx */
+ RET
+
+TEXT cachedwbse(SB), 1, $-4 /* D writeback SE */
+ MOVW R0, R2 /* first arg: address */
+
+ MOVW CPSR, R3 /* splhi */
+ ORR $(PsrDirq), R3, R1
+ MOVW R1, CPSR
+
+ BARRIERS /* force outstanding stores to cache */
+ MOVW 4(FP), R1 /* second arg: size */
+
+// CMP.S $(4*1024), R1
+// BGT _dwb
+ ADD R2, R1
+ BIC $(CACHELINESZ-1), R2
+_dwbse:
+ MCR CpSC, 0, R2, C(CpCACHE), C(CpCACHEwb), CpCACHEse
+ ADD $CACHELINESZ, R2
+ CMP.S R2, R1
+ BGT _dwbse
+ /* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
+ BARRIERS
+
+ MOVW R3, CPSR /* splx */
+ RET
+
+TEXT cachedwbinv(SB), 1, $-4 /* D writeback+invalidate */
+ MOVW CPSR, R3 /* splhi */
+ ORR $(PsrDirq), R3, R1
+ MOVW R1, CPSR
+
+ BARRIERS /* force outstanding stores to cache */
+ /* keep writing back dirty cache lines until no more exist */
+_dwbinv:
+ MRC CpSC, 0, PC, C(CpCACHE), C(CpCACHEwbi), CpCACHEtest
+ BNE _dwbinv
+ /* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
+ BARRIERS
+
+ MOVW R3, CPSR /* splx */
+ RET
+
+TEXT cachedwbinvse(SB), 1, $-4 /* D writeback+invalidate SE */
+ MOVW R0, R2 /* first arg: address */
+
+ MOVW CPSR, R3 /* splhi */
+ ORR $(PsrDirq), R3, R1
+ MOVW R1, CPSR
+
+ BARRIERS /* force outstanding stores to cache */
+ MOVW 4(FP), R1 /* second arg: size */
+
+ DSB
+// CMP.S $(4*1024), R1
+// BGT _dwbinv
+ ADD R2, R1
+ BIC $(CACHELINESZ-1), R2
+_dwbinvse:
+ MCR CpSC, 0, R2, C(CpCACHE), C(CpCACHEwbi), CpCACHEse
+ ADD $CACHELINESZ, R2
+ CMP.S R2, R1
+ BGT _dwbinvse
+ /* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
+ BARRIERS
+
+ MOVW R3, CPSR /* splx */
+ RET
+
+TEXT cachedinvse(SB), 1, $-4 /* D invalidate SE */
+ MOVW R0, R2 /* first arg: address */
+
+ MOVW CPSR, R3 /* splhi */
+ ORR $(PsrDirq), R3, R1
+ MOVW R1, CPSR
+
+ MOVW 4(FP), R1 /* second arg: size */
+
+ DSB
+// CMP.S $(4*1024), R1
+// BGT _dinv
+ ADD R2, R1
+ BIC $(CACHELINESZ-1), R2
+_dinvse:
+ MCR CpSC, 0, R2, C(CpCACHE), C(CpCACHEinvd), CpCACHEse
+ ADD $CACHELINESZ, R2
+ CMP.S R2, R1
+ BGT _dinvse
+ /* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
+ BARRIERS
+
+ MOVW R3, CPSR /* splx */
+ RET
+
+TEXT cacheuwbinv(SB), 1, $-4 /* D+I writeback+invalidate */
+ MOVW CPSR, R3 /* splhi */
+ ORR $(PsrDirq), R3, R1
+ MOVW R1, CPSR
+
+ BARRIERS /* force outstanding stores to cache */
+ /* keep writing back dirty cache lines until no more exist */
+_uwbinv: /* D writeback+invalidate */
+ MRC CpSC, 0, PC, C(CpCACHE), C(CpCACHEwbi), CpCACHEtest
+ BNE _uwbinv
+ /* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
+ BARRIERS
+
+ MOVW $0, R0 /* I invalidate */
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
+ /* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
+ BARRIERS
+
+ MOVW R3, CPSR /* splx */
+ RET
+
+TEXT cacheiinv(SB), 1, $-4 /* I invalidate */
+ BARRIERS
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
+ /* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
+ BARRIERS
+ RET
+
+TEXT cachedinv(SB), 1, $-4 /* D invalidate */
+_dinv:
+ BARRIERS
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEall
+ /* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
+ BARRIERS
+ RET
+
+/*
+ * l2 cache
+ *
+ * these functions assume that the necessary l1 cache operations have been
+ * or will be done explicitly by the caller.
+ */
+
+/* enable l2 cache in config coproc. reg. do this while l1 caches are off. */
+TEXT l2cachecfgon(SB), 1, $-4
+ BARRIERS
+ MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2inv), CpTCl2all
+ BARRIERS
+
+ MRC CpSC, CpL2, R1, C(CpTESTCFG), C(CpTCl2cfg), CpTCl2conf
+ ORR $(CpTCl2ena | CpTCl2prefdis), R1 /* l2 on, prefetch off */
+ MCR CpSC, CpL2, R1, C(CpTESTCFG), C(CpTCl2cfg), CpTCl2conf
+ BARRIERS
+ RET
+
+/* disable l2 cache in config coproc. reg. do this while l1 caches are off. */
+TEXT l2cachecfgoff(SB), 1, $-4
+ BARRIERS
+ MRC CpSC, CpL2, R1, C(CpTESTCFG), C(CpTCl2cfg), CpTCl2conf
+ BIC $CpTCl2ena, R1
+ MCR CpSC, CpL2, R1, C(CpTESTCFG), C(CpTCl2cfg), CpTCl2conf
+ BARRIERS
+
+ MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2inv), CpTCl2all
+ BARRIERS
+ RET
+
+TEXT l2cacheuwb(SB), 1, $-4 /* L2 unified writeback */
+ MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2flush), CpTCl2all
+ ISB
+ RET
+
+TEXT l2cacheuwbse(SB), 1, $-4 /* L2 unified writeback SE */
+ MOVW R0, R2 /* first arg: address */
+
+ MOVW CPSR, R3 /* splhi */
+ ORR $(PsrDirq), R3, R1
+ MOVW R1, CPSR
+
+ MOVW 4(FP), R1 /* second arg: size */
+
+ ADD R2, R1
+ BIC $(CACHELINESZ-1), R2
+_l2wbse:
+ MCR CpSC, CpL2, R2, C(CpTESTCFG), C(CpTCl2flush), CpTCl2seva
+ ADD $CACHELINESZ, R2
+ CMP.S R2, R1
+ BGT _l2wbse
+ ISB
+
+ MOVW R3, CPSR /* splx */
+ RET
+
+TEXT l2cacheuwbinv(SB), 1, $-4 /* L2 unified writeback+invalidate */
+ MOVW CPSR, R3 /* splhi */
+ ORR $(PsrDirq), R3, R1
+ MOVW R1, CPSR
+
+ MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2flush), CpTCl2all
+ ISB
+ MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2inv), CpTCl2all
+ ISB
+
+ MOVW R3, CPSR /* splx */
+ RET
+
+TEXT l2cacheuwbinvse(SB), 1, $-4 /* L2 unified writeback+invalidate SE */
+ MOVW R0, R2 /* first arg: address */
+
+ MOVW CPSR, R3 /* splhi */
+ ORR $(PsrDirq), R3, R1
+ MOVW R1, CPSR
+
+ MOVW 4(FP), R1 /* second arg: size */
+
+ ADD R2, R1
+ BIC $(CACHELINESZ-1), R2
+_l2wbinvse:
+ MCR CpSC, CpL2, R2, C(CpTESTCFG), C(CpTCl2flush), CpTCl2seva
+ ISB
+ MCR CpSC, CpL2, R2, C(CpTESTCFG), C(CpTCl2inv), CpTCl2seva
+ ADD $CACHELINESZ, R2
+ CMP.S R2, R1
+ BGT _l2wbinvse
+ ISB
+
+ MOVW R3, CPSR /* splx */
+ RET
+
+TEXT l2cacheuinv(SB), 1, $-4 /* L2 unified invalidate */
+ MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2inv), CpTCl2all
+ ISB
+ RET
+
+TEXT l2cacheuinvse(SB), 1, $-4 /* L2 unified invalidate SE */
+ MOVW R0, R2 /* first arg: address */
+
+ MOVW CPSR, R3 /* splhi */
+ ORR $(PsrDirq), R3, R1
+ MOVW R1, CPSR
+
+ MOVW 4(FP), R1 /* second arg: size */
+
+ ADD R2, R1
+ BIC $(CACHELINESZ-1), R2
+_l2invse:
+ MCR CpSC, CpL2, R2, C(CpTESTCFG), C(CpTCl2inv), CpTCl2seva
+ ADD $CACHELINESZ, R2
+ CMP.S R2, R1
+ BGT _l2invse
+ ISB
+
+ MOVW R3, CPSR /* splx */
+ RET
+
+/*
+ * enable mmu, i and d caches, and high vector
+ */
+TEXT mmuenable(SB), 1, $-4
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0)
+ ORR $(CpChv|CpCmmu|CpCdcache|CpCicache|CpCwb|CpCsystem), R0
+ BIC $(CpCrom), R0
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0)
+ BARRIERS
+ RET
+
+TEXT mmudisable(SB), 1, $-4
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0)
+ BIC $(CpChv|CpCmmu|CpCdcache|CpCicache|CpCwb), R0
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0)
+ BARRIERS
+ RET
+
+TEXT mmuinvalidate(SB), 1, $-4 /* invalidate all */
+ MOVW $0, R0
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
+ BARRIERS
+ RET
+
+TEXT mmuinvalidateaddr(SB), 1, $-4 /* invalidate single entry */
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinvse
+ BARRIERS
+ RET
+
+TEXT cpidget(SB), 1, $-4 /* main ID */
+ MRC CpSC, 0, R0, C(CpID), C(0), CpIDid
+ RET
+
+TEXT cpctget(SB), 1, $-4 /* cache type */
+ MRC CpSC, 0, R0, C(CpID), C(0), CpIDct
+ RET
+
+TEXT controlget(SB), 1, $-4 /* control */
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0)
+ RET
+
+TEXT ttbget(SB), 1, $-4 /* translation table base */
+ MRC CpSC, 0, R0, C(CpTTB), C(0)
+ RET
+
+TEXT ttbput(SB), 1, $-4 /* translation table base */
+ MCR CpSC, 0, R0, C(CpTTB), C(0)
+ ISB
+ RET
+
+TEXT dacget(SB), 1, $-4 /* domain access control */
+ MRC CpSC, 0, R0, C(CpDAC), C(0)
+ RET
+
+TEXT dacput(SB), 1, $-4 /* domain access control */
+ MCR CpSC, 0, R0, C(CpDAC), C(0)
+ ISB
+ RET
+
+TEXT fsrget(SB), 1, $-4 /* fault status */
+ MRC CpSC, 0, R0, C(CpFSR), C(0)
+ RET
+
+TEXT farget(SB), 1, $-4 /* fault address */
+ MRC CpSC, 0, R0, C(CpFAR), C(0x0)
+ RET
+
+TEXT pidget(SB), 1, $-4 /* address translation pid */
+ MRC CpSC, 0, R0, C(CpPID), C(0x0)
+ RET
+
+TEXT pidput(SB), 1, $-4 /* address translation pid */
+ MCR CpSC, 0, R0, C(CpPID), C(0x0)
+ ISB
+ RET
+
+TEXT splhi(SB), 1, $-4
+ MOVW $(MACHADDR+4), R2 /* save caller pc in Mach */
+ MOVW R14, 0(R2)
+
+ MOVW CPSR, R0 /* turn off interrupts */
+ ORR $(PsrDirq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+TEXT spllo(SB), 1, $-4
+ MOVW CPSR, R0
+ BIC $(PsrDirq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+TEXT splx(SB), 1, $-4
+ MOVW $(MACHADDR+0x04), R2 /* save caller pc in Mach */
+ MOVW R14, 0(R2)
+
+ MOVW R0, R1 /* reset interrupt level */
+ MOVW CPSR, R0
+ MOVW R1, CPSR
+ RET
+
+TEXT splxpc(SB), 1, $-4 /* for iunlock */
+ MOVW R0, R1
+ MOVW CPSR, R0
+ MOVW R1, CPSR
+ RET
+
+TEXT spldone(SB), 1, $0
+ RET
+
+TEXT islo(SB), 1, $-4
+ MOVW CPSR, R0
+ AND $(PsrDirq), R0
+ EOR $(PsrDirq), R0
+ RET
+
+TEXT splfhi(SB), $-4
+ MOVW CPSR, R0
+ ORR $(PsrDfiq|PsrDirq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+//TEXT splflo(SB), $-4
+// MOVW CPSR, R0
+// BIC $(PsrDfiq), R0, R1
+// MOVW R1, CPSR
+// RET
+
+TEXT tas(SB), $-4
+TEXT _tas(SB), $-4
+ MOVW R0,R1
+ MOVW $1,R0
+ SWPW R0,(R1) /* fix: deprecated in armv7 */
+ RET
+
+//TEXT tas32(SB), 1, $-4
+// MOVW R0, R1
+// MOVW $0xDEADDEAD, R0
+// MOVW R0, R3
+// SWPW R0, (R1)
+// CMP.S R0, R3
+// BEQ _tasout
+// EOR R3, R3 /* R3 = 0 */
+// CMP.S R0, R3
+// BEQ _tasout
+// MOVW $1, R15 /* abort: lock != 0 && lock != $0xDEADDEAD */
+//_tasout:
+// RET
+
+TEXT clz(SB), 1, $-4
+ CLZ(0, 0) /* 0 is R0 */
+ RET
+
+TEXT setlabel(SB), 1, $-4
+ MOVW R13, 0(R0) /* sp */
+ MOVW R14, 4(R0) /* pc */
+ BARRIERS
+ MOVW $0, R0
+ RET
+
+TEXT gotolabel(SB), 1, $-4
+ MOVW 0(R0), R13 /* sp */
+ MOVW 4(R0), R14 /* pc */
+ BARRIERS
+ MOVW $1, R0
+ RET
+
+TEXT getcallerpc(SB), 1, $-4
+ MOVW 0(R13), R0
+ RET
+
+TEXT _idlehands(SB), 1, $-4
+ MOVW CPSR, R3
+// ORR $PsrDirq, R3, R1 /* splhi */
+ BIC $PsrDirq, R3, R1 /* spllo */
+ MOVW R1, CPSR
+
+ MOVW $0, R0 /* wait for interrupt */
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEintr), CpCACHEwait
+ ISB
+
+ MOVW R3, CPSR /* splx */
+ RET
+
+TEXT barriers(SB), 1, $-4
+ BARRIERS
+ RET
diff --git a/sys/src/9/kw/lexception.s b/sys/src/9/kw/lexception.s
new file mode 100755
index 000000000..e3f330653
--- /dev/null
+++ b/sys/src/9/kw/lexception.s
@@ -0,0 +1,187 @@
+/*
+ * arm exception handlers
+ */
+#include "arm.s"
+
+#undef B /* B is for 'botch' */
+
+/*
+ * exception vectors, copied by trapinit() to somewhere useful
+ */
+TEXT vectors(SB), 1, $-4
+ MOVW 0x18(R15), R15 /* reset */
+ MOVW 0x18(R15), R15 /* undefined instr. */
+ MOVW 0x18(R15), R15 /* SWI & SMC */
+ MOVW 0x18(R15), R15 /* prefetch abort */
+ MOVW 0x18(R15), R15 /* data abort */
+ MOVW 0x18(R15), R15 /* reserved */
+ MOVW 0x18(R15), R15 /* IRQ */
+ MOVW 0x18(R15), R15 /* FIQ */
+
+TEXT vtable(SB), 1, $-4
+ WORD $_vsvc(SB) /* reset, in svc mode already */
+ WORD $_vund(SB) /* undefined, switch to svc mode */
+ WORD $_vsvc(SB) /* swi, in svc mode already */
+ WORD $_vpabt(SB) /* prefetch abort, switch to svc mode */
+ WORD $_vdabt(SB) /* data abort, switch to svc mode */
+ WORD $_vsvc(SB) /* reserved */
+ WORD $_virq(SB) /* IRQ, switch to svc mode */
+// WORD $_vfiq(SB) /* FIQ, switch to svc mode */
+ WORD $_virq(SB) /* FIQ, switch to svc mode */
+
+TEXT _vrst(SB), 1, $-4
+ BL _reset(SB)
+
+TEXT _vsvc(SB), 1, $-4 /* SWI */
+ MOVW.W R14, -4(R13) /* ureg->pc = interrupted PC */
+ MOVW SPSR, R14 /* ureg->psr = SPSR */
+ MOVW.W R14, -4(R13) /* ... */
+ MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */
+ MOVW.W R14, -4(R13) /* ... */
+
+ /* avoid the ambiguity described in notes/movm.w. */
+// MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */
+ MOVM.DB.S [R0-R14], (R13) /* save user level registers */
+ SUB $(15*4), R13 /* r13 now points to ureg */
+
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+
+// MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */
+ MOVW $(L1-MACHSIZE), R10 /* m */
+ MOVW 8(R10), R9 /* up */
+
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $8, R13 /* space for argument+link */
+
+ BL syscall(SB)
+
+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT _vund(SB), 1, $-4 /* undefined */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMund, R0
+ B _vswitch
+
+TEXT _vpabt(SB), 1, $-4 /* prefetch abort */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMabt, R0 /* r0 = type */
+ B _vswitch
+
+TEXT _vdabt(SB), 1, $-4 /* data abort */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $(PsrMabt+1), R0 /* r0 = type */
+ B _vswitch
+
+TEXT _virq(SB), 1, $-4 /* IRQ */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMirq, R0 /* r0 = type */
+ B _vswitch
+
+ /*
+ * come here with type in R0 and R13 pointing above saved [r0-r4].
+ * we'll switch to SVC mode and then call trap.
+ */
+_vswitch:
+ MOVW SPSR, R1 /* save SPSR for ureg */
+ MOVW R14, R2 /* save interrupted pc for ureg */
+ MOVW R13, R3 /* save pointer to where the original [R0-R4] are */
+
+ /*
+ * switch processor to svc mode. this switches the banked registers
+ * (r13 [sp] and r14 [link]) to those of svc mode.
+ */
+ MOVW CPSR, R14
+ BIC $PsrMask, R14
+ ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
+ MOVW R14, CPSR /* switch! */
+
+ AND.S $0xf, R1, R4 /* interrupted code kernel or user? */
+ BEQ _userexcep
+
+ /* here for trap from SVC mode */
+ MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
+ MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
+
+ /*
+ * avoid the ambiguity described in notes/movm.w.
+ * In order to get a predictable value in R13 after the stores,
+ * separate the store-multiple from the stack-pointer adjustment.
+ * We'll assume that the old value of R13 should be stored on the stack.
+ */
+ /* save kernel level registers, at end r13 points to ureg */
+// MOVM.DB.W [R0-R14], (R13)
+ MOVM.DB [R0-R14], (R13)
+ SUB $(15*4), R13 /* SP now points to saved R0 */
+
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $(4*2), R13 /* space for argument+link (for debugger) */
+ MOVW $0xdeaddead, R11 /* marker */
+
+ BL trap(SB)
+
+ ADD $(4*2+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+
+ MOVM.DB (R13), [R0-R14] /* restore registers */
+
+ ADD $(4*2), R13 /* pop past ureg->{type+psr} to pc */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+ /* here for trap from USER mode */
+_userexcep:
+ MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
+ MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
+
+ /* avoid the ambiguity described in notes/movm.w. */
+// MOVM.DB.W.S [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
+ MOVM.DB.S [R0-R14], (R13) /* save kernel level registers */
+ SUB $(15*4), R13 /* r13 now points to ureg */
+
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+
+// MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */
+ MOVW $(L1-MACHSIZE), R10 /* m */
+ MOVW 8(R10), R9 /* up */
+
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $(4*2), R13 /* space for argument+link (for debugger) */
+
+ BL trap(SB)
+
+ ADD $(4*2+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $(4*2), R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT _vfiq(SB), 1, $-4 /* FIQ */
+ RFE /* FIQ is special, ignore it for now */
+
+/*
+ * set the stack value for the mode passed in R0
+ */
+TEXT setr13(SB), 1, $-4
+ MOVW 4(FP), R1
+
+ MOVW CPSR, R2
+ BIC $PsrMask, R2, R3
+ ORR R0, R3
+ MOVW R3, CPSR /* switch to new mode */
+
+ MOVW R13, R0 /* return old sp */
+ MOVW R1, R13 /* install new one */
+
+ MOVW R2, CPSR /* switch back to old mode */
+ RET
diff --git a/sys/src/9/kw/lproc.s b/sys/src/9/kw/lproc.s
new file mode 100755
index 000000000..0b4eac238
--- /dev/null
+++ b/sys/src/9/kw/lproc.s
@@ -0,0 +1,47 @@
+#include "mem.h"
+#include "arm.h"
+
+/*
+ * This is the first jump from kernel to user mode.
+ * Fake a return from interrupt.
+ *
+ * Enter with R0 containing the user stack pointer.
+ * UTZERO + 0x20 is always the entry point.
+ *
+ */
+TEXT touser(SB), 1, $-4
+ /* store the user stack pointer into the USR_r13 */
+ MOVM.DB.W [R0], (R13)
+ /* avoid the ambiguity described in notes/movm.w. */
+// MOVM.S.IA.W (R13), [R13]
+ MOVM.S (R13), [R13]
+ ADD $4, R13
+
+ /* set up a PSR for user level */
+ MOVW $(PsrMusr), R0
+ MOVW R0, SPSR
+
+ /* save the PC on the stack */
+ MOVW $(UTZERO+0x20), R0
+ MOVM.DB.W [R0], (R13)
+
+ /*
+ * note that 5a's RFE is not the v6 arch. instruction (0xe89d0a00,
+ * I think), which loads CPSR from the word after the PC at (R13),
+ * but rather the pre-v6 simulation `MOVM.IA.S.W (R13), [R15]'
+ * (0xe8fd8000 since MOVM is LDM in this case), which loads CPSR
+ * not from memory but from SPSR due to `.S'.
+ */
+ RFE
+
+/*
+ * here to jump to a newly forked process
+ */
+TEXT forkret(SB), 1, $-4
+ ADD $(4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
diff --git a/sys/src/9/kw/main.c b/sys/src/9/kw/main.c
new file mode 100755
index 000000000..2fa13917d
--- /dev/null
+++ b/sys/src/9/kw/main.c
@@ -0,0 +1,678 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#include "init.h"
+#include "arm.h"
+#include <pool.h>
+
+#include "reboot.h"
+
+/*
+ * Where configuration info is left for the loaded programme.
+ * This will turn into a structure as more is done by the boot loader
+ * (e.g. why parse the .ini file twice?).
+ * There are 3584 bytes available at CONFADDR.
+ */
+#define BOOTARGS ((char*)CONFADDR)
+#define BOOTARGSLEN (16*KiB) /* limit in devenv.c */
+#define MAXCONF 64
+#define MAXCONFLINE 160
+
+#define isascii(c) ((uchar)(c) > 0 && (uchar)(c) < 0177)
+
+uintptr kseg0 = KZERO;
+Mach* machaddr[MAXMACH];
+
+/*
+ * Option arguments from the command line.
+ * oargv[0] is the boot file.
+ * Optionsinit() is called from multiboot()
+ * or some other machine-dependent place
+ * to set it all up.
+ */
+static int oargc;
+static char* oargv[20];
+static char oargb[128];
+static int oargblen;
+static char oenv[4096];
+
+static uintptr sp; /* XXX - must go - user stack of init proc */
+
+int vflag;
+char debug[256];
+
+/* store plan9.ini contents here at least until we stash them in #ec */
+static char confname[MAXCONF][KNAMELEN];
+static char confval[MAXCONF][MAXCONFLINE];
+static int nconf;
+
+#ifdef CRYPTOSANDBOX
+uchar sandbox[64*1024+BY2PG];
+#endif
+
+static int
+findconf(char *name)
+{
+ int i;
+
+ for(i = 0; i < nconf; i++)
+ if(cistrcmp(confname[i], name) == 0)
+ return i;
+ return -1;
+}
+
+char*
+getconf(char *name)
+{
+ int i;
+
+ i = findconf(name);
+ if(i >= 0)
+ return confval[i];
+ return nil;
+}
+
+void
+addconf(char *name, char *val)
+{
+ int i;
+
+ i = findconf(name);
+ if(i < 0){
+ if(val == nil || nconf >= MAXCONF)
+ return;
+ i = nconf++;
+ strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
+ }
+// confval[i] = val;
+ strecpy(confval[i], confval[i]+sizeof(confval[i]), val);
+}
+
+static void
+writeconf(void)
+{
+ char *p, *q;
+ int n;
+
+ p = getconfenv();
+
+ if(waserror()) {
+ free(p);
+ nexterror();
+ }
+
+ /* convert to name=value\n format */
+ for(q=p; *q; q++) {
+ q += strlen(q);
+ *q = '=';
+ q += strlen(q);
+ *q = '\n';
+ }
+ n = q - p + 1;
+ if(n >= BOOTARGSLEN)
+ error("kernel configuration too large");
+ memmove(BOOTARGS, p, n);
+ poperror();
+ free(p);
+}
+
+/*
+ * assumes that we have loaded our /cfg/pxe/mac file at 0x1000 with
+ * tftp in u-boot. no longer uses malloc, so can be called early.
+ */
+static void
+plan9iniinit(void)
+{
+ char *k, *v, *next;
+
+ k = (char *)CONFADDR;
+ if(!isascii(*k))
+ return;
+
+ for(; k && *k != '\0'; k = next) {
+ if (!isascii(*k)) /* sanity check */
+ break;
+ next = strchr(k, '\n');
+ if (next)
+ *next++ = '\0';
+
+ if (*k == '\0' || *k == '\n' || *k == '#')
+ continue;
+ v = strchr(k, '=');
+ if(v == nil)
+ continue; /* mal-formed line */
+ *v++ = '\0';
+
+ addconf(k, v);
+ }
+}
+
+static void
+optionsinit(char* s)
+{
+ char *o;
+
+ o = strecpy(oargb, oargb+sizeof(oargb), s)+1;
+ if(getenv("bootargs", o, o - oargb) != nil)
+ *(o-1) = ' ';
+
+ oargblen = strlen(oargb);
+ oargc = tokenize(oargb, oargv, nelem(oargv)-1);
+ oargv[oargc] = nil;
+}
+
+char*
+getenv(char* name, char* buf, int n)
+{
+ char *e, *p, *q;
+
+ p = oenv;
+ while(*p != 0){
+ if((e = strchr(p, '=')) == nil)
+ break;
+ for(q = name; p < e; p++){
+ if(*p != *q)
+ break;
+ q++;
+ }
+ if(p == e && *q == 0){
+ strecpy(buf, buf+n, e+1);
+ return buf;
+ }
+ p += strlen(p)+1;
+ }
+
+ return nil;
+}
+
+#include "io.h"
+
+typedef struct Spiregs Spiregs;
+struct Spiregs {
+ ulong ictl; /* interface ctl */
+ ulong icfg; /* interface config */
+ ulong out; /* data out */
+ ulong in; /* data in */
+ ulong ic; /* interrupt cause */
+ ulong im; /* interrupt mask */
+ ulong _pad[2];
+ ulong dwrcfg; /* direct write config */
+ ulong dwrhdr; /* direct write header */
+};
+
+enum {
+ /* ictl bits */
+ Csnact = 1<<0, /* serial memory activated */
+
+ /* icfg bits */
+ Bytelen = 1<<5, /* 2^(this_bit) bytes per transfer */
+ Dirrdcmd= 1<<10, /* flag: fast read */
+};
+
+static void
+dumpbytes(uchar *bp, long max)
+{
+ iprint("%#p: ", bp);
+ for (; max > 0; max--)
+ iprint("%02.2ux ", *bp++);
+ iprint("...\n");
+}
+
+static void
+spiprobe(void)
+{
+ Spiregs *rp = (Spiregs *)soc.spi;
+
+ rp->ictl |= Csnact;
+ coherence();
+ rp->icfg |= Dirrdcmd | 3<<8; /* fast reads, 4-byte addresses */
+ rp->icfg &= ~Bytelen; /* one-byte reads */
+ coherence();
+
+// print("spi flash at %#ux: memory reads enabled\n", PHYSSPIFLASH);
+}
+
+void archconsole(void);
+
+/*
+ * entered from l.s with mmu enabled.
+ *
+ * we may have to realign the data segment; apparently 5l -H0 -R4096
+ * does not pad the text segment. on the other hand, we may have been
+ * loaded by another kernel.
+ *
+ * be careful not to touch the data segment until we know it's aligned.
+ */
+void
+main(Mach* mach)
+{
+ extern char bdata[], edata[], end[], etext[];
+ static ulong vfy = 0xcafebabe;
+
+ m = mach;
+ if (vfy != 0xcafebabe)
+ memmove(bdata, etext, edata - bdata);
+ if (vfy != 0xcafebabe) {
+ wave('?');
+ panic("misaligned data segment");
+ }
+ memset(edata, 0, end - edata); /* zero bss */
+ vfy = 0;
+
+wave('9');
+ machinit();
+ archreset();
+ mmuinit();
+
+ optionsinit("/boot/boot boot");
+ quotefmtinstall();
+ archconsole();
+wave(' ');
+
+ /* want plan9.ini to be able to affect memory sizing in confinit */
+ plan9iniinit(); /* before we step on plan9.ini in low memory */
+
+ confinit();
+ /* xinit would print if it could */
+ xinit();
+
+ /*
+ * Printinit will cause the first malloc call.
+ * (printinit->qopen->malloc) unless any of the
+ * above (like clockintr) do an irqenable, which
+ * will call malloc.
+ * If the system dies here it's probably due
+ * to malloc(->xalloc) not being initialised
+ * correctly, or the data segment is misaligned
+ * (it's amazing how far you can get with
+ * things like that completely broken).
+ *
+ * (Should be) boilerplate from here on.
+ */
+ trapinit();
+ clockinit();
+
+ printinit();
+ uartkirkwoodconsole();
+ /* only now can we print */
+ print("from Bell Labs\n\n");
+
+#ifdef CRYPTOSANDBOX
+ print("sandbox: 64K at physical %#lux, mapped to 0xf10b0000\n",
+ PADDR((uintptr)sandbox & ~(BY2PG-1)));
+#endif
+
+ archconfinit();
+ cpuidprint();
+ timersinit();
+
+ procinit0();
+ initseg();
+ links();
+ chandevreset(); /* most devices are discovered here */
+
+ pageinit();
+ swapinit();
+ userinit();
+ schedinit();
+ panic("schedinit returned");
+}
+
+void
+cpuidprint(void)
+{
+ char name[64];
+
+ cputype2name(name, sizeof name);
+ print("cpu%d: %lldMHz ARM %s\n", m->machno, m->cpuhz/1000000, name);
+}
+
+void
+machinit(void)
+{
+ memset(m, 0, sizeof(Mach));
+ m->machno = 0;
+ machaddr[m->machno] = m;
+
+ m->ticks = 1;
+ m->perf.period = 1;
+
+ conf.nmach = 1;
+
+ active.machs = 1;
+ active.exiting = 0;
+
+ up = nil;
+}
+
+static void
+shutdown(int ispanic)
+{
+ int ms, once;
+
+ lock(&active);
+ if(ispanic)
+ active.ispanic = ispanic;
+ else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
+ active.ispanic = 0;
+ once = active.machs & (1<<m->machno);
+ active.machs &= ~(1<<m->machno);
+ active.exiting = 1;
+ unlock(&active);
+
+ if(once)
+ iprint("cpu%d: exiting\n", m->machno);
+ spllo();
+ for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
+ delay(TK2MS(2));
+ if(active.machs == 0 && consactive() == 0)
+ break;
+ }
+ delay(1000);
+}
+
+/*
+ * exit kernel either on a panic or user request
+ */
+void
+exit(int code)
+{
+ shutdown(code);
+ splhi();
+ archreboot();
+}
+
+/*
+ * the new kernel is already loaded at address `code'
+ * of size `size' and entry point `entry'.
+ */
+void
+reboot(void *entry, void *code, ulong size)
+{
+ void (*f)(ulong, ulong, ulong);
+
+ iprint("starting reboot...");
+ writeconf();
+
+ shutdown(0);
+
+ /*
+ * should be the only processor running now
+ */
+
+ print("shutting down...\n");
+ delay(200);
+
+ /* turn off buffered serial console */
+ serialoq = nil;
+
+ /* shutdown devices */
+ chandevshutdown();
+
+ /* call off the dog */
+ clockshutdown();
+
+ splhi();
+
+ /* setup reboot trampoline function */
+ f = (void*)REBOOTADDR;
+ memmove(f, rebootcode, sizeof(rebootcode));
+ cacheuwbinv();
+ l2cacheuwb();
+
+ print("rebooting...");
+ iprint("entry %#lux code %#lux size %ld\n",
+ PADDR(entry), PADDR(code), size);
+ delay(100); /* wait for uart to quiesce */
+
+ /* off we go - never to return */
+ cacheuwbinv();
+ l2cacheuwb();
+ (*f)(PADDR(entry), PADDR(code), size);
+
+ iprint("loaded kernel returned!\n");
+ delay(1000);
+ archreboot();
+}
+
+/*
+ * starting place for first process
+ */
+void
+init0(void)
+{
+ int i;
+ char buf[2*KNAMELEN];
+
+ assert(up != nil);
+ up->nerrlab = 0;
+ coherence();
+ spllo();
+
+ /*
+ * These are o.k. because rootinit is null.
+ * Then early kproc's will have a root and dot.
+ */
+ up->slash = namec("#/", Atodir, 0, 0);
+ pathclose(up->slash->path);
+ up->slash->path = newpath("/");
+ up->dot = cclone(up->slash);
+
+ chandevinit();
+
+ if(!waserror()){
+ snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
+ ksetenv("terminal", buf, 0);
+ ksetenv("cputype", "arm", 0);
+ if(cpuserver)
+ ksetenv("service", "cpu", 0);
+ else
+ ksetenv("service", "terminal", 0);
+
+ /* convert plan9.ini variables to #e and #ec */
+ for(i = 0; i < nconf; i++) {
+ ksetenv(confname[i], confval[i], 0);
+ ksetenv(confname[i], confval[i], 1);
+ }
+ poperror();
+ }
+ kproc("alarm", alarmkproc, 0);
+
+ touser(sp);
+}
+
+static void
+bootargs(uintptr base)
+{
+ int i;
+ ulong ssize;
+ char **av, *p;
+
+ /*
+ * Push the boot args onto the stack.
+ * The initial value of the user stack must be such
+ * that the total used is larger than the maximum size
+ * of the argument list checked in syscall.
+ */
+ i = oargblen+1;
+ p = UINT2PTR(STACKALIGN(base + BY2PG - sizeof(up->s.args) - i));
+ memmove(p, oargb, i);
+
+ /*
+ * Now push argc and the argv pointers.
+ * This isn't strictly correct as the code jumped to by
+ * touser in init9.s calls startboot (port/initcode.c) which
+ * expects arguments
+ * startboot(char *argv0, char **argv)
+ * not the usual (int argc, char* argv[]), but argv0 is
+ * unused so it doesn't matter (at the moment...).
+ */
+ av = (char**)(p - (oargc+2)*sizeof(char*));
+ ssize = base + BY2PG - PTR2UINT(av);
+ *av++ = (char*)oargc;
+ for(i = 0; i < oargc; i++)
+ *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
+ *av = nil;
+
+ /*
+ * Leave space for the return PC of the
+ * caller of initcode.
+ */
+ sp = USTKTOP - ssize - sizeof(void*);
+}
+
+/*
+ * create the first process
+ */
+void
+userinit(void)
+{
+ Proc *p;
+ Segment *s;
+ KMap *k;
+ Page *pg;
+
+ /* no processes yet */
+ up = nil;
+
+ p = newproc();
+ p->pgrp = newpgrp();
+ p->egrp = smalloc(sizeof(Egrp));
+ p->egrp->ref = 1;
+ p->fgrp = dupfgrp(nil);
+ p->rgrp = newrgrp();
+ p->procmode = 0640;
+
+ kstrdup(&eve, "");
+ kstrdup(&p->text, "*init*");
+ kstrdup(&p->user, eve);
+
+ /*
+ * Kernel Stack
+ */
+ p->sched.pc = PTR2UINT(init0);
+ p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
+ p->sched.sp = STACKALIGN(p->sched.sp);
+
+ /*
+ * User Stack
+ *
+ * Technically, newpage can't be called here because it
+ * should only be called when in a user context as it may
+ * try to sleep if there are no pages available, but that
+ * shouldn't be the case here.
+ */
+ s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
+ p->seg[SSEG] = s;
+ pg = newpage(1, 0, USTKTOP-BY2PG);
+ segpage(s, pg);
+ k = kmap(pg);
+ bootargs(VA(k));
+ kunmap(k);
+
+ /*
+ * Text
+ */
+ s = newseg(SG_TEXT, UTZERO, 1);
+ s->flushme++;
+ p->seg[TSEG] = s;
+ pg = newpage(1, 0, UTZERO);
+ memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
+ segpage(s, pg);
+ k = kmap(s->map[0]->pages[0]);
+ memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
+ kunmap(k);
+
+ ready(p);
+}
+
+Conf conf; /* XXX - must go - gag */
+
+Confmem sheevamem[] = {
+ /*
+ * Memory available to Plan 9:
+ * the 8K is reserved for ethernet dma access violations to scribble on.
+ */
+ { .base = 0, .limit = 512*MB - 8*1024, },
+};
+
+void
+confinit(void)
+{
+ int i;
+ ulong kpages;
+ uintptr pa;
+
+ /*
+ * Copy the physical memory configuration to Conf.mem.
+ */
+ if(nelem(sheevamem) > nelem(conf.mem)){
+ iprint("memory configuration botch\n");
+ exit(1);
+ }
+ memmove(conf.mem, sheevamem, sizeof(sheevamem));
+
+ conf.npage = 0;
+ pa = PADDR(PGROUND(PTR2UINT(end)));
+
+ /*
+ * we assume that the kernel is at the beginning of one of the
+ * contiguous chunks of memory and fits therein.
+ */
+ for(i=0; i<nelem(conf.mem); i++){
+ /* take kernel out of allocatable space */
+ if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
+ conf.mem[i].base = pa;
+
+ conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
+ conf.npage += conf.mem[i].npage;
+ }
+
+ conf.upages = (conf.npage*90)/100;
+ conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
+
+ /* only one processor */
+ conf.nmach = 1;
+
+ /* set up other configuration parameters */
+ conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
+ if(cpuserver)
+ conf.nproc *= 3;
+ if(conf.nproc > 2000)
+ conf.nproc = 2000;
+ conf.nswap = conf.npage*3;
+ conf.nswppo = 4096;
+ conf.nimage = 200;
+
+ conf.copymode = 0; /* copy on write */
+
+ /*
+ * Guess how much is taken by the large permanent
+ * datastructures. Mntcache and Mntrpc are not accounted for
+ * (probably ~300KB).
+ */
+ kpages = conf.npage - conf.upages;
+ kpages *= BY2PG;
+ kpages -= conf.upages*sizeof(Page)
+ + conf.nproc*sizeof(Proc)
+ + conf.nimage*sizeof(Image)
+ + conf.nswap
+ + conf.nswppo*sizeof(Page);
+ mainmem->maxsize = kpages;
+ if(!cpuserver)
+ /*
+ * give terminals lots of image memory, too; the dynamic
+ * allocation will balance the load properly, hopefully.
+ * be careful with 32-bit overflow.
+ */
+ imagmem->maxsize = kpages;
+}
+
+int
+cmpswap(long *addr, long old, long new)
+{
+ return cas32(addr, old, new);
+}
diff --git a/sys/src/9/kw/mem.h b/sys/src/9/kw/mem.h
new file mode 100755
index 000000000..b35e4dba7
--- /dev/null
+++ b/sys/src/9/kw/mem.h
@@ -0,0 +1,142 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+#define KiB 1024u /* Kibi 0x0000000000000400 */
+#define MiB 1048576u /* Mebi 0x0000000000100000 */
+#define GiB 1073741824u /* Gibi 000000000040000000 */
+
+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) /* ceiling */
+#define ROUNDDN(x, y) (((x)/(y))*(y)) /* floor */
+#define MIN(a, b) ((a) < (b)? (a): (b))
+#define MAX(a, b) ((a) > (b)? (a): (b))
+
+/*
+ * Not sure where these macros should go.
+ * This probably isn't right but will do for now.
+ * The macro names are problematic too.
+ */
+/*
+ * In B(o), 'o' is the bit offset in the register.
+ * For multi-bit fields use F(v, o, w) where 'v' is the value
+ * of the bit-field of width 'w' with LSb at bit offset 'o'.
+ */
+#define B(o) (1<<(o))
+#define F(v, o, w) (((v) & ((1<<(w))-1))<<(o))
+
+#define FCLR(d, o, w) ((d) & ~(((1<<(w))-1)<<(o)))
+#define FEXT(d, o, w) (((d)>>(o)) & ((1<<(w))-1))
+#define FINS(d, o, w, v) (FCLR((d), (o), (w))|F((v), (o), (w)))
+#define FSET(d, o, w) ((d)|(((1<<(w))-1)<<(o)))
+
+#define FMASK(o, w) (((1<<(w))-1)<<(o))
+
+/*
+ * Sizes
+ */
+#define BY2PG (4*KiB) /* bytes per page */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define PGROUND(s) ROUNDUP(s, BY2PG)
+#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
+
+#define MAXMACH 1 /* max # cpus system can run */
+#define MACHSIZE BY2PG
+
+#define KSTKSIZE (8*KiB)
+#define STACKALIGN(sp) ((sp) & ~3) /* bug: assure with alloc */
+
+/*
+ * Address spaces.
+ * KTZERO is used by kprof and dumpstack (if any).
+ *
+ * KZERO is mapped to physical 0.
+ * u-boot claims to take 0 - 8MB.
+ *
+ * vectors are at 0, plan9.ini is at KZERO+4K and is limited to 16K by
+ * devenv. L2 PTEs for trap vectors & i/o regs are stored from KZERO+56K
+ * to L1-MACHSIZE (KZERO+60K). cpu0's Mach struct is at L1 - MACHSIZE(4K)
+ * to L1 (KZERO+60K to KZERO+64K). L1 PTEs are stored from L1 to L1+32K
+ * (KZERO+64K to KZERO+96K). KTZERO may be anywhere after KZERO+96K.
+ */
+
+#define KSEG0 0x60000000 /* kernel segment */
+/* mask to check segment; good for 512MB dram */
+#define KSEGM 0xE0000000
+#define KZERO KSEG0 /* kernel address space */
+#define CONFADDR (KZERO+4*KiB) /* unparsed plan9.ini */
+#define L1 (KZERO+64*KiB) /* tt ptes: 16KiB aligned */
+#define KTZERO (KZERO+0x800000) /* kernel text start */
+
+#define UZERO 0 /* user segment */
+#define UTZERO (UZERO+BY2PG) /* user text start */
+#define USTKTOP KZERO /* user segment end +1 */
+#define USTKSIZE (8*1024*1024) /* user stack size */
+#define TSTKTOP (USTKTOP-USTKSIZE) /* sysexec temporary stack */
+#define TSTKSIZ 256
+
+/* address at which to copy and execute rebootcode */
+#define REBOOTADDR KADDR(0x100)
+
+/*
+ * Time.
+ * Does this need to be here? Used in assembler?
+ */
+#define HZ 100 /* clock frequency */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+
+/*
+ * More accurate time
+ */
+#define CLOCKFREQ (200*1000*1000) /* TCLK on sheeva: 200MHz */
+//#define MS2TMR(t) ((ulong)(((uvlong)(t)*CLOCKFREQ)/1000))
+//#define US2TMR(t) ((ulong)(((uvlong)(t)*CLOCKFREQ)/1000000))
+
+/*
+ * Legacy...
+ */
+#define BLOCKALIGN 32 /* only used in allocb.c */
+#define KSTACK KSTKSIZE
+
+/*
+ * Sizes
+ */
+#define BI2BY 8 /* bits per byte */
+#define BY2SE 4
+#define BY2WD 4
+#define BY2V 8 /* only used in xalloc.c */
+
+#define CACHELINESZ 32
+#define PTEMAPMEM (1024*1024)
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 1984
+#define SSEGMAPSIZE 16
+#define PPN(x) ((x)&~(BY2PG-1))
+
+/*
+ * With a little work these move to port.
+ */
+#define PTEVALID (1<<0)
+#define PTERONLY 0
+#define PTEWRITE (1<<1)
+#define PTEUNCACHED (1<<2)
+#define PTEKERNEL (1<<3)
+
+/*
+ * Physical machine information from here on.
+ */
+#define PHYSDRAM 0
+
+/* from 0x80000000 up is uncached by L2 (see archkw.c) */
+#define PHYSCESASRAM 0xc8010000
+// #define PHYSSPIFLASH 0xe8000000 /* ignore spi flash */
+/* this address is configured by u-boot, and is 0xd0000000 at reset */
+#define PHYSIO 0xf1000000 /* internal registers */
+#define PHYSCONS (PHYSIO + 0x12000) /* uart */
+#define PHYSNAND1 0xf9000000 /* sheeva/openrd (remapped) */
+#define PHYSNAND2 0xd8000000 /* guru */
+#define PHYSBOOTROM 0xffff0000 /* boot rom */
+
+#define FLASHSIZE (512*MiB) /* but not addressed linearly */
+
+#define VIRTIO PHYSIO
diff --git a/sys/src/9/kw/mkfile b/sys/src/9/kw/mkfile
new file mode 100755
index 000000000..8f5402352
--- /dev/null
+++ b/sys/src/9/kw/mkfile
@@ -0,0 +1,156 @@
+CONF=plug
+CONFLIST=plug
+
+# allegedly u-boot uses the bottom 8MB (up to 0x800000)
+# so avoid that
+loadaddr=0x60800000
+
+objtype=arm
+</$objtype/mkfile
+p=9
+
+DEVS=`{rc ../port/mkdevlist $CONF}
+
+PORT=\
+ alarm.$O\
+ alloc.$O\
+ allocb.$O\
+ auth.$O\
+ cache.$O\
+ chan.$O\
+ dev.$O\
+ edf.$O\
+ fault.$O\
+ latin1.$O\
+ mul64fract.$O\
+ rebootcmd.$O\
+ page.$O\
+ parse.$O\
+ pgrp.$O\
+ portclock.$O\
+ print.$O\
+ proc.$O\
+ qio.$O\
+ qlock.$O\
+ segment.$O\
+ swap.$O\
+ syscallfmt.$O\
+ sysfile.$O\
+ sysproc.$O\
+ taslock.$O\
+ tod.$O\
+ xalloc.$O\
+
+OBJ=\
+ l.$O\
+ lexception.$O\
+ lproc.$O\
+ arch.$O\
+ cga.$O\
+ clock.$O\
+ fpi.$O\
+ fpiarm.$O\
+ fpimem.$O\
+ main.$O\
+ mmu.$O\
+ random.$O\
+ trap.$O\
+ $CONF.root.$O\
+ $CONF.rootc.$O\
+ $DEVS\
+ $PORT\
+
+# HFILES=
+
+LIB=\
+ /$objtype/lib/libmemlayer.a\
+ /$objtype/lib/libmemdraw.a\
+ /$objtype/lib/libdraw.a\
+ /$objtype/lib/libip.a\
+ /$objtype/lib/libsec.a\
+ /$objtype/lib/libc.a\
+
+9:V: $p$CONF s$p$CONF
+
+$p$CONF:DQ: $CONF.c $OBJ $LIB mkfile
+ $CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
+ echo '# linking raw kernel'
+# sleep 1 # avoid relinking later
+ $LD -o $target -H0 -R4096 -T$loadaddr -l $OBJ $CONF.$O $LIB
+
+s$p$CONF:DQ: $CONF.$O $OBJ $LIB
+ echo '# linking kernel with symbols'
+# sleep 1 # avoid relinking later
+ $LD -o $target -R4096 -T$loadaddr -l $OBJ $CONF.$O $LIB
+ size $target
+
+$p$CONF.gz:D: $p$CONF
+ gzip -9 <$p$CONF >$target
+
+$OBJ: $HFILES
+
+install:V: /$objtype/$p$CONF
+
+install-in-flash:V: /$objtype/$p$CONF paqdisk
+ plug.flash.cfg
+ echo erase all >/dev/flash/kernelctl
+ cp /$objtype/$p$CONF /dev/flash/kernel
+ echo erase all >/dev/flash/plan9ctl
+ cp paqdisk /dev/flash/plan9
+
+/$objtype/$p$CONF:D: $p$CONF s$p$CONF
+ cp -x $p$CONF s$p$CONF /$objtype &
+ { 9fs lookout && cp -x $p$CONF s$p$CONF /n/lookout/$objtype } &
+# { 9fs piestand && cp -x $p$CONF s$p$CONF /n/piestand/$objtype } &
+ wait
+ touch $target
+
+paqdisk:
+ rm -fr armpaq
+ mkdir armpaq
+ cd armpaq
+ disk/mkfs -d . /sys/lib/sysconfig/proto/armpaqproto
+ mkpaqfs -o ../paqdisk
+ cd ..
+
+<../boot/bootmkfile
+<../port/portmkfile
+<|../port/mkbootrules $CONF
+
+# CFLAGS= -I. -I../port $CFLAGS # hack to compile private sysproc.c (e.g.)
+
+arch.$O clock.$O fpiarm.$O main.$O mmu.$O screen.$O sdscsi.$O syscall.$O \
+ trap.$O: /$objtype/include/ureg.h
+
+archkw.$O devether.$O ether1116.$O ethermii.$O: \
+ etherif.h ethermii.h ../port/netif.h
+archkw.$O devflash.$O flashkw.$O: ../port/flashif.h
+fpi.$O fpiarm.$O fpimem.$O: fpi.h
+l.$O lexception.$O lproc.$O mmu.$O: arm.s arm.h mem.h
+main.$O: errstr.h init.h reboot.h
+mouse.$O: screen.h
+devusb.$O: ../port/usb.h
+usbehci.$O usbohci.$O usbuhci.$O: ../port/usb.h usbehci.h uncached.h
+
+init.h:D: ../port/initcode.c init9.s
+ $CC ../port/initcode.c
+ $AS init9.s
+ $LD -l -R1 -s -o init.out init9.$O initcode.$O /$objtype/lib/libc.a
+ {echo 'uchar initcode[]={'
+ xd -1x <init.out |
+ sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+ echo '};'} > init.h
+
+reboot.h:D: rebootcode.s arm.s arm.h mem.h
+ $AS rebootcode.s
+ # -lc is only for memmove. -T arg is PADDR(REBOOTADDR)
+ $LD -l -a -s -T0x100 -R4 -o reboot.out rebootcode.$O -lc >reboot.list
+ {echo 'uchar rebootcode[]={'
+ xd -1x reboot.out |
+ sed -e '1,2d' -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+ echo '};'} > reboot.h
+errstr.h:D: ../port/mkerrstr ../port/error.h
+ rc ../port/mkerrstr > errstr.h
+
+plug.clean:
+ rm -rf $p$CONF s$p$CONF armpaq paqdisk $CONF.c boot$CONF.c ../boot/libboot.a5
diff --git a/sys/src/9/kw/mmu.c b/sys/src/9/kw/mmu.c
new file mode 100755
index 000000000..2557ff59b
--- /dev/null
+++ b/sys/src/9/kw/mmu.c
@@ -0,0 +1,522 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "arm.h"
+
+#define L1X(va) FEXT((va), 20, 12)
+#define L2X(va) FEXT((va), 12, 8)
+
+enum {
+ L1lo = UZERO/MiB, /* L1X(UZERO)? */
+ L1hi = (USTKTOP+MiB-1)/MiB, /* L1X(USTKTOP+MiB-1)? */
+};
+
+#define ISHOLE(pte) ((pte) == 0)
+
+/* dump level 1 page table at virtual addr l1 */
+void
+mmudump(PTE *l1)
+{
+ int i, type, rngtype;
+ uintptr pa, startva, startpa;
+ uvlong va, endva;
+ PTE pte;
+
+ iprint("\n");
+ endva = startva = startpa = 0;
+ rngtype = 0;
+ /* dump first level of ptes */
+ for (va = i = 0; i < 4096; i++) {
+ pte = l1[i];
+ pa = pte & ~(MB - 1);
+ type = pte & (Fine|Section|Coarse);
+ if (ISHOLE(pte)) {
+ if (endva != 0) { /* open range? close it */
+ iprint("l1 maps va (%#lux-%#llux) -> pa %#lux type %#ux\n",
+ startva, endva-1, startpa, rngtype);
+ endva = 0;
+ }
+ } else {
+ if (endva == 0) { /* no open range? start one */
+ startva = va;
+ startpa = pa;
+ rngtype = type;
+ }
+ endva = va + MB; /* continue the open range */
+ }
+ va += MB;
+ }
+ if (endva != 0) /* close an open range */
+ iprint("l1 maps va (%#lux-%#llux) -> pa %#lux type %#ux\n",
+ startva, endva-1, startpa, rngtype);
+}
+
+#ifdef CRYPTOSANDBOX
+extern uchar sandbox[64*1024+BY2PG];
+#endif
+
+/* identity map `mbs' megabytes from phys */
+void
+mmuidmap(uintptr phys, int mbs)
+{
+ PTE *l1;
+ uintptr pa, fpa;
+
+ pa = ttbget();
+ l1 = KADDR(pa);
+
+ for (fpa = phys; mbs-- > 0; fpa += MiB)
+ l1[L1X(fpa)] = fpa|Dom0|L1AP(Krw)|Section;
+ coherence();
+
+ mmuinvalidate();
+ cacheuwbinv();
+ l2cacheuwbinv();
+}
+
+void
+mmuinit(void)
+{
+ PTE *l1, *l2;
+ uintptr pa, i;
+
+ pa = ttbget();
+ l1 = KADDR(pa);
+
+ /*
+ * map high vectors to start of dram, but only 4K, not 1MB.
+ */
+ pa -= MACHSIZE+2*1024;
+ l2 = KADDR(pa);
+ memset(l2, 0, 1024);
+ /* vectors step on u-boot, but so do page tables */
+ l2[L2X(HVECTORS)] = PHYSDRAM|L2AP(Krw)|Small;
+ l1[L1X(HVECTORS)] = pa|Dom0|Coarse; /* vectors -> ttb-machsize-2k */
+
+ /* double map vectors at virtual 0 so reset will see them */
+ pa -= 1024;
+ l2 = KADDR(pa);
+ memset(l2, 0, 1024);
+ l2[L2X(0)] = PHYSDRAM|L2AP(Krw)|Small;
+ l1[L1X(0)] = pa|Dom0|Coarse;
+
+ /*
+ * set up L2 ptes for PHYSIO (i/o registers), with smaller pages to
+ * enable user-mode access to a few devices.
+ */
+ pa -= 1024;
+ l2 = KADDR(pa);
+ /* identity map by default */
+ for (i = 0; i < 1024/4; i++)
+ l2[L2X(VIRTIO + i*BY2PG)] = (PHYSIO + i*BY2PG)|L2AP(Krw)|Small;
+
+#ifdef CRYPTOSANDBOX
+ /*
+ * rest is to let rae experiment with the crypto hardware
+ */
+ /* access to cycle counter */
+ l2[L2X(soc.clock)] = soc.clock | L2AP(Urw)|Small;
+ /* cesa registers; also visible in user space */
+ for (i = 0; i < 16; i++)
+ l2[L2X(soc.cesa + i*BY2PG)] = (soc.cesa + i*BY2PG) |
+ L2AP(Urw)|Small;
+ /* crypto sram; remapped to unused space and visible in user space */
+ l2[L2X(PHYSIO + 0xa0000)] = PHYSCESASRAM | L2AP(Urw)|Small;
+ /* 64k of scratch dram */
+ for (i = 0; i < 16; i++)
+ l2[L2X(PHYSIO + 0xb0000 + i*BY2PG)] =
+ (PADDR((uintptr)sandbox & ~(BY2PG-1)) + i*BY2PG) |
+ L2AP(Urw) | Small;
+#endif
+
+ l1[L1X(VIRTIO)] = pa|Dom0|Coarse;
+ coherence();
+
+ mmuinvalidate();
+ cacheuwbinv();
+ l2cacheuwbinv();
+
+ m->mmul1 = l1;
+// mmudump(l1); /* DEBUG. too early to print */
+}
+
+static void
+mmul2empty(Proc* proc, int clear)
+{
+ PTE *l1;
+ Page **l2, *page;
+
+ l1 = m->mmul1;
+ l2 = &proc->mmul2;
+ for(page = *l2; page != nil; page = page->next){
+ if(clear)
+ memset(UINT2PTR(page->va), 0, BY2PG);
+ l1[page->daddr] = Fault;
+ l2 = &page->next;
+ }
+ *l2 = proc->mmul2cache;
+ proc->mmul2cache = proc->mmul2;
+ proc->mmul2 = nil;
+}
+
+static void
+mmul1empty(void)
+{
+#ifdef notdef /* there's a bug in here */
+ PTE *l1;
+
+ /* clean out any user mappings still in l1 */
+ if(m->mmul1lo > L1lo){
+ if(m->mmul1lo == 1)
+ m->mmul1[L1lo] = Fault;
+ else
+ memset(&m->mmul1[L1lo], 0, m->mmul1lo*sizeof(PTE));
+ m->mmul1lo = L1lo;
+ }
+ if(m->mmul1hi < L1hi){
+ l1 = &m->mmul1[m->mmul1hi];
+ if((L1hi - m->mmul1hi) == 1)
+ *l1 = Fault;
+ else
+ memset(l1, 0, (L1hi - m->mmul1hi)*sizeof(PTE));
+ m->mmul1hi = L1hi;
+ }
+#else
+ memset(&m->mmul1[L1lo], 0, (L1hi - L1lo)*sizeof(PTE));
+#endif /* notdef */
+}
+
+void
+mmuswitch(Proc* proc)
+{
+ int x;
+ PTE *l1;
+ Page *page;
+
+ /* do kprocs get here and if so, do they need to? */
+ if(m->mmupid == proc->pid && !proc->newtlb)
+ return;
+ m->mmupid = proc->pid;
+
+ /* write back dirty and invalidate l1 caches */
+ cacheuwbinv();
+
+ if(proc->newtlb){
+ mmul2empty(proc, 1);
+ proc->newtlb = 0;
+ }
+
+ mmul1empty();
+
+ /* move in new map */
+ l1 = m->mmul1;
+ for(page = proc->mmul2; page != nil; page = page->next){
+ x = page->daddr;
+ l1[x] = PPN(page->pa)|Dom0|Coarse;
+ /* know here that L1lo < x < L1hi */
+ if(x+1 - m->mmul1lo < m->mmul1hi - x)
+ m->mmul1lo = x+1;
+ else
+ m->mmul1hi = x;
+ }
+
+ /* make sure map is in memory */
+ /* could be smarter about how much? */
+ cachedwbse(&l1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE));
+ l2cacheuwbse(&l1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE));
+
+ /* lose any possible stale tlb entries */
+ mmuinvalidate();
+
+// mmudump(l1);
+ //print("mmuswitch l1lo %d l1hi %d %d\n",
+ // m->mmul1lo, m->mmul1hi, proc->kp);
+//print("\n");
+}
+
+void
+flushmmu(void)
+{
+ int s;
+
+ s = splhi();
+ up->newtlb = 1;
+ mmuswitch(up);
+ splx(s);
+}
+
+void
+mmurelease(Proc* proc)
+{
+ Page *page, *next;
+
+ /* write back dirty and invalidate l1 caches */
+ cacheuwbinv();
+
+ mmul2empty(proc, 0);
+ for(page = proc->mmul2cache; page != nil; page = next){
+ next = page->next;
+ if(--page->ref)
+ panic("mmurelease: page->ref %d", page->ref);
+ pagechainhead(page);
+ }
+ if(proc->mmul2cache && palloc.r.p)
+ wakeup(&palloc.r);
+ proc->mmul2cache = nil;
+
+ mmul1empty();
+
+ /* make sure map is in memory */
+ /* could be smarter about how much? */
+ cachedwbse(&m->mmul1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE));
+ l2cacheuwbse(&m->mmul1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE));
+
+ /* lose any possible stale tlb entries */
+ mmuinvalidate();
+}
+
+void
+putmmu(uintptr va, uintptr pa, Page* page)
+{
+ int x;
+ Page *pg;
+ PTE *l1, *pte;
+
+ x = L1X(va);
+ l1 = &m->mmul1[x];
+ //print("putmmu(%#p, %#p, %#p) ", va, pa, page->pa);
+ //print("mmul1 %#p l1 %#p *l1 %#ux x %d pid %d\n",
+ // m->mmul1, l1, *l1, x, up->pid);
+ if(*l1 == Fault){
+ /* wasteful - l2 pages only have 256 entries - fix */
+ if(up->mmul2cache == nil){
+ /* auxpg since we don't need much? memset if so */
+ pg = newpage(1, 0, 0);
+ pg->va = VA(kmap(pg));
+ }
+ else{
+ pg = up->mmul2cache;
+ up->mmul2cache = pg->next;
+ memset(UINT2PTR(pg->va), 0, BY2PG);
+ }
+ pg->daddr = x;
+ pg->next = up->mmul2;
+ up->mmul2 = pg;
+
+ /* force l2 page to memory */
+ cachedwbse((void *)pg->va, BY2PG);
+ l2cacheuwbse((void *)pg->va, BY2PG);
+
+ *l1 = PPN(pg->pa)|Dom0|Coarse;
+ cachedwbse(l1, sizeof *l1);
+ l2cacheuwbse(l1, sizeof *l1);
+ //print("l1 %#p *l1 %#ux x %d pid %d\n", l1, *l1, x, up->pid);
+
+ if(x >= m->mmul1lo && x < m->mmul1hi){
+ if(x+1 - m->mmul1lo < m->mmul1hi - x)
+ m->mmul1lo = x+1;
+ else
+ m->mmul1hi = x;
+ }
+ }
+ pte = UINT2PTR(KADDR(PPN(*l1)));
+ //print("pte %#p index %ld %#ux\n", pte, L2X(va), *(pte+L2X(va)));
+
+ /* protection bits are
+ * PTERONLY|PTEVALID;
+ * PTEWRITE|PTEVALID;
+ * PTEWRITE|PTEUNCACHED|PTEVALID;
+ */
+ x = Small;
+ if(!(pa & PTEUNCACHED))
+ x |= Cached|Buffered;
+ if(pa & PTEWRITE)
+ x |= L2AP(Urw);
+ else
+ x |= L2AP(Uro);
+ pte[L2X(va)] = PPN(pa)|x;
+ cachedwbse(&pte[L2X(va)], sizeof pte[0]);
+ l2cacheuwbse(&pte[L2X(va)], sizeof pte[0]);
+
+ /* clear out the current entry */
+ mmuinvalidateaddr(PPN(va));
+
+ /*
+ * write back dirty entries - we need this because pio() in
+ * fault.c is writing via a different virt addr and won't clean
+ * its changes out of the dcache. Page coloring doesn't work
+ * on this mmu because the l1 virtual cache is set associative
+ * rather than direct mapped.
+ */
+ cachedwbinv();
+ if(page->cachectl[0] == PG_TXTFLUSH){
+ /* pio() sets PG_TXTFLUSH whenever a text pg has been written */
+ cacheiinv();
+ page->cachectl[0] = PG_NOFLUSH;
+ }
+ //print("putmmu %#p %#p %#p\n", va, pa, PPN(pa)|x);
+}
+
+void*
+mmuuncache(void* v, usize size)
+{
+ int x;
+ PTE *pte;
+ uintptr va;
+
+ /*
+ * Simple helper for ucalloc().
+ * Uncache a Section, must already be
+ * valid in the MMU.
+ */
+ va = PTR2UINT(v);
+ assert(!(va & (1*MiB-1)) && size == 1*MiB);
+
+ x = L1X(va);
+ pte = &m->mmul1[x];
+ if((*pte & (Fine|Section|Coarse)) != Section)
+ return nil;
+ *pte &= ~(Cached|Buffered);
+ mmuinvalidateaddr(va);
+ cachedwbse(pte, 4);
+ l2cacheuwbse(pte, 4);
+
+ return v;
+}
+
+uintptr
+mmukmap(uintptr va, uintptr pa, usize size)
+{
+ int x;
+ PTE *pte;
+
+ /*
+ * Stub.
+ */
+ assert(!(va & (1*MiB-1)) && !(pa & (1*MiB-1)) && size == 1*MiB);
+
+ x = L1X(va);
+ pte = &m->mmul1[x];
+ if(*pte != Fault)
+ return 0;
+ *pte = pa|Dom0|L1AP(Krw)|Section;
+ mmuinvalidateaddr(va);
+ cachedwbse(pte, 4);
+ l2cacheuwbse(pte, 4);
+
+ return va;
+}
+
+uintptr
+mmukunmap(uintptr va, uintptr pa, usize size)
+{
+ int x;
+ PTE *pte;
+
+ /*
+ * Stub.
+ */
+ assert(!(va & (1*MiB-1)) && !(pa & (1*MiB-1)) && size == 1*MiB);
+
+ x = L1X(va);
+ pte = &m->mmul1[x];
+ if(*pte != (pa|Dom0|L1AP(Krw)|Section))
+ return 0;
+ *pte = Fault;
+ mmuinvalidateaddr(va);
+ cachedwbse(pte, 4);
+ l2cacheuwbse(pte, 4);
+
+ return va;
+}
+
+/*
+ * Return the number of bytes that can be accessed via KADDR(pa).
+ * If pa is not a valid argument to KADDR, return 0.
+ */
+uintptr
+cankaddr(uintptr pa)
+{
+ if(pa < PHYSDRAM + 512*MiB) /* assumes PHYSDRAM is 0 */
+ return PHYSDRAM + 512*MiB - pa;
+ return 0;
+}
+
+/* from 386 */
+void*
+vmap(uintptr pa, usize size)
+{
+ uintptr pae, va;
+ usize o, osize;
+
+ /*
+ * XXX - replace with new vm stuff.
+ * Crock after crock - the first 4MB is mapped with 2MB pages
+ * so catch that and return good values because the current mmukmap
+ * will fail.
+ */
+ if(pa+size < 4*MiB)
+ return UINT2PTR(kseg0|pa);
+
+ osize = size;
+ o = pa & (BY2PG-1);
+ pa -= o;
+ size += o;
+ size = ROUNDUP(size, BY2PG);
+
+ va = kseg0|pa;
+ pae = mmukmap(va, pa, size);
+ if(pae == 0 || pae-size != pa)
+ panic("vmap(%#p, %ld) called from %#p: mmukmap fails %#p",
+ pa+o, osize, getcallerpc(&pa), pae);
+
+ return UINT2PTR(va+o);
+}
+
+/* from 386 */
+void
+vunmap(void* v, usize size)
+{
+ /*
+ * XXX - replace with new vm stuff.
+ * Can't do this until do real vmap for all space that
+ * might be used, e.g. stuff below 1MB which is currently
+ * mapped automagically at boot but that isn't used (or
+ * at least shouldn't be used) by the kernel.
+ upafree(PADDR(v), size);
+ */
+ USED(v, size);
+}
+
+/*
+ * Notes.
+ * Everything is in domain 0;
+ * domain 0 access bits in the DAC register are set
+ * to Client, which means access is controlled by the
+ * permission values set in the PTE.
+ *
+ * L1 access control for the kernel is set to 1 (RW,
+ * no user mode access);
+ * L2 access control for the kernel is set to 1 (ditto)
+ * for all 4 AP sets;
+ * L1 user mode access is never set;
+ * L2 access control for user mode is set to either
+ * 2 (RO) or 3 (RW) depending on whether text or data,
+ * for all 4 AP sets.
+ * (To get kernel RO set AP to 0 and S bit in control
+ * register c1).
+ * Coarse L1 page-tables are used. They have 256 entries
+ * and so consume 1024 bytes per table.
+ * Small L2 page-tables are used. They have 1024 entries
+ * and so consume 4096 bytes per table.
+ *
+ * 4KiB. That's the size of 1) a page, 2) the
+ * size allocated for an L2 page-table page (note only 1KiB
+ * is needed per L2 page - to be dealt with later) and
+ * 3) the size of the area in L1 needed to hold the PTEs
+ * to map 1GiB of user space (0 -> 0x3fffffff, 1024 entries).
+ */
diff --git a/sys/src/9/kw/notes/movm.w b/sys/src/9/kw/notes/movm.w
new file mode 100755
index 000000000..a2b22f1e1
--- /dev/null
+++ b/sys/src/9/kw/notes/movm.w
@@ -0,0 +1,22 @@
+gorka writes:
+---
+I have userspace on the gumstix [xscale, not omap]. The problem that
+got me in trouble was that in lexception.s (or l.s),
+
+ MOVM.DB.W [R0-R14], (R13)
+
+works differently for this architecture (and probably for others, as
+it is unclear how it should behave by reading the arm specs). This
+happens only for kernel faults as the others (syscall, user faults)
+use MOVM.DB.W.S which uses the banked user registers.
+
+The problem is that in this arch the value of R13 saved is the value
+after R13 itself has been modified, whereas in the others (bitsy,
+pico...), it was the value before. Adding 4*15 to the stack before
+the RFE solves the problem.
+---
+
+In fact, the 2005 ARM arch. ref. man. (ARM DDI 0100I) says, under STM (1),
+that if Rn appears in the set of registers (and isn't the first one)
+and .W is specified, the stored value of Rn is unpredictable.
+The arm v7-ar arch. ref. man. says such usage is obsolete.
diff --git a/sys/src/9/kw/nvram b/sys/src/9/kw/nvram
new file mode 100755
index 000000000..a64a5a93f
--- /dev/null
+++ b/sys/src/9/kw/nvram
Binary files differ
diff --git a/sys/src/9/kw/openrd.words b/sys/src/9/kw/openrd.words
new file mode 100755
index 000000000..99f041231
--- /dev/null
+++ b/sys/src/9/kw/openrd.words
@@ -0,0 +1,21 @@
+global scale openrd client
+
+like the sheevaplug, and runs the same kernel, but with these additions:
+
+2 Gb ethers
+
+pci bus 0
+00.00.00 vid 11ab did 6281 memory controller sub-class 0x80
+00.01.00 vid 18ca did 0027 display controller sub-class 0
+ XGI Technology; Volari Z11 XGI Compatible SVGA controller (xg27 core)
+
+64MB vga memory, resolution up to 1280x1024 @ 60 Hz. the video
+controller is undocumented and even the Linux driver is only available
+as a binary, so so far this port is only a cpu kernel.
+
+run video as normal svga; get framebuffer addr from pci (implement pci).
+
+uart0 is the shared jtag/uart thing with the usb mini b connector.
+uart1 is the rs232/rs485 ports.
+
+has non-ahci sata without going through pci
diff --git a/sys/src/9/kw/plug b/sys/src/9/kw/plug
new file mode 100755
index 000000000..7fe107ba6
--- /dev/null
+++ b/sys/src/9/kw/plug
@@ -0,0 +1,80 @@
+# sheeva plug, openrd-client, guruplug and others
+# based on marvell's kirkwood soc
+dev
+ root
+ cons
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ rtc
+ arch
+ ssl
+ tls
+ cap
+ kprof
+ aoe
+ sd
+ fs
+ flash
+ twsi
+# pnp pci
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno
+
+## draw screen vga vgax
+## mouse mouse
+## vga
+# kbmap
+## kbin
+
+ uart
+ usb
+
+link
+ ether1116 ethermii
+ archkw
+ ethermedium
+# no flash yet for guruplug
+ flashkw ecc
+ loopbackmedium
+ netdevmedium
+ usbehci usbehcikw
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+ ipmux
+
+misc
+ rdb
+ coproc
+ sdaoe sdscsi
+ softfpu
+ syscall
+ uartkw
+ ucalloc
+## vgavesa
+
+port
+ int cpuserver = 1;
+ int i8250freq = 3686000;
+
+boot cpu
+ tcp
+# paq
+
+bootdir
+ boot$CONF.out boot
+ /arm/bin/ip/ipconfig
+ /arm/bin/auth/factotum
+# /arm/bin/paqfs
+ /arm/bin/usb/usbd
+# nvram not needed any longer, it's in flash
+ nvram
diff --git a/sys/src/9/kw/plug.words b/sys/src/9/kw/plug.words
new file mode 100755
index 000000000..385b459f4
--- /dev/null
+++ b/sys/src/9/kw/plug.words
@@ -0,0 +1,104 @@
+global scale sheevaplug & guruplug
+
+marvell 88f6281 (feroceon kirkwood) SoC
+arm926ej-s rev 1 [56251311] (armv5tejl) 1.2GHz cpu
+
+l1 I & D VIVT caches 16K each: 4-way, 128 sets, 32-byte lines
+ l1 D is write-through, l1 I is write-back
+unified l2 PIPT cache 256K: 4-way, 2048 sets, 32-byte lines
+ potentially 512K: 8-way
+
+apparently the mmu walks the page tables in dram and won't look in the
+l2 cache. there is no hardware cache coherence, thus the l1 caches
+need to be flushed or invalidated when mmu mappings change, but l2
+only needs to be flushed or invalidated around dma operations and page
+table changes, and only the affected dma buffers and descriptors or
+page table entries need to be flushed or invalidated in l2.
+
+we arrange that device registers are uncached.
+
+be aware that cache operations act on cache lines (of CACHELINESZ
+bytes) as atomic units, so if you invalidate one word of a cache line,
+you invalidate the entire cache line, whether it's been written back
+(is clean) or not (is dirty). mixed data structures with parts
+maintained by hardware and other parts by software are especially
+tricky. we try to pad the initial hardware parts so that the software
+parts start in a new cache line.
+
+there are no video controllers so far, so this port is a cpu
+kernel only.
+
+512MB of dram at physical address 0
+512MB of nand flash
+16550 uart for console
+see http://www.marvell.com/files/products/embedded_processors/kirkwood/\
+ FS_88F6180_9x_6281_OpenSource.pdf, stored locally as
+ /public/doc/marvell/88f61xx.kirkwood.pdf
+
+If you plan to use flash, it would be wise to avoid touching the first
+megabyte, which contains u-boot, right up to 0x100000. There's a
+linux kernel from there to 0x400000, if you care. You'll also likely
+want to use paqfs rather than fossil or kfs for file systems in flash
+since there is no wear-levelling.
+
+The code is fairly heavy-handed with the use of barrier instructions
+(BARRIERS in assembler, coherence in C), partly in reaction to bad
+experience doing Power PC ports, but also just as precautions against
+modern processors, which may feel free to execute instructions out of
+order or some time later, store to memory out of order or some time
+later, otherwise break the model of traditional sequential processors,
+or any combination of the above.
+
+this plan 9 port is based on the port of native inferno to the
+sheevaplug by Salva Peiró (saoret.one@gmail.com) and Mechiel Lukkien
+(mechiel@ueber.net).
+
+___
+
+# type this once at u-boot, replacing 00504301c49e with your plug's
+# mac address; thereafter the plug will pxe boot:
+setenv bootdelay 2
+setenv bootcmd 'bootp; bootp; tftp 0x1000 /cfg/pxe/00504301c49e; bootp; tftp 0x800000; go 0x800000'
+saveenv
+
+# see /cfg/pxe/example-kw
+
+
+ physical mem map
+hex addr size what
+----
+0 512MB sdram
+
+80000000 512MB pcie mem # default
+c8010000 2K cesa sram
+d0000000 1MB internal regs default address at reset
+d8000000 128MB nand flash # actually 512MB addressed through this
+e8000000 128MB spi serial flash
+f0000000 128MB boot rom # default
+f0000000 16MB pcie io # mapped from 0xc0000000 by u-boot
+
+f1000000 1MB internal regs as mapped by u-boot
+f1000000 64K dram regs
+f1010000 64K uart, flashes, rtc, gpio, etc.
+f1030000 64K crypto accelerator (cesa)
+f1040000 64K pci-e regs
+f1050000 64K usb otg regs (ehci-like)
+f1070000 64K gbe regs
+f1080000 64K non-ahci sata regs
+f1090000 64K sdio regs
+
+f8000000 128MB boot device # default, mapped to 0 by u-boot
+f8000000 16MB spi flash # mapped by u-boot
+f9000000 8MB nand flash # on sheeva/openrd, mapped by u-boot
+fb000000 64KB crypto engine
+ff000000 16MB boot rom # u-boot
+
+ virtual mem map
+hex addr size what
+----
+0 512MB user process address space
+
+60000000 kzero, mapped to 0
+90000000 256MB pcie mem # mapped by u-boot
+c0000000 64KB pcie i/o # mapped by u-boot
+... as per physical map
diff --git a/sys/src/9/kw/random.c b/sys/src/9/kw/random.c
new file mode 100755
index 000000000..1f7c0983d
--- /dev/null
+++ b/sys/src/9/kw/random.c
@@ -0,0 +1,138 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+
+struct Rb
+{
+ QLock;
+ Rendez producer;
+ Rendez consumer;
+ ulong randomcount;
+ uchar buf[128];
+ uchar *ep;
+ uchar *rp;
+ uchar *wp;
+ uchar next;
+ uchar wakeme;
+ ushort bits;
+ ulong randn;
+} rb;
+
+static int
+rbnotfull(void*)
+{
+ int i;
+
+ i = rb.rp - rb.wp;
+ return i != 1 && i != (1 - sizeof(rb.buf));
+}
+
+static int
+rbnotempty(void*)
+{
+ return rb.wp != rb.rp;
+}
+
+static void
+genrandom(void*)
+{
+ up->basepri = PriNormal;
+ up->priority = up->basepri;
+
+ for(;;){
+ for(;;)
+ if(++rb.randomcount > 100000)
+ break;
+ if(anyhigher())
+ sched();
+ if(!rbnotfull(0))
+ sleep(&rb.producer, rbnotfull, 0);
+ }
+}
+
+/*
+ * produce random bits in a circular buffer
+ */
+static void
+randomclock(void)
+{
+ if(rb.randomcount == 0 || !rbnotfull(0))
+ return;
+
+ rb.bits = (rb.bits<<2) ^ rb.randomcount;
+ rb.randomcount = 0;
+
+ rb.next++;
+ if(rb.next != 8/2)
+ return;
+ rb.next = 0;
+
+ *rb.wp ^= rb.bits;
+ if(rb.wp+1 == rb.ep)
+ rb.wp = rb.buf;
+ else
+ rb.wp = rb.wp+1;
+
+ if(rb.wakeme)
+ wakeup(&rb.consumer);
+}
+
+void
+randominit(void)
+{
+ addclock0link(randomclock, 1000/HZ);
+ rb.ep = rb.buf + sizeof(rb.buf);
+ rb.rp = rb.wp = rb.buf;
+ kproc("genrandom", genrandom, 0);
+}
+
+/*
+ * consume random bytes from a circular buffer
+ */
+ulong
+randomread(void *xp, ulong n)
+{
+ uchar *e, *p;
+ ulong x;
+
+ p = xp;
+
+ if(waserror()){
+ qunlock(&rb);
+ nexterror();
+ }
+
+ qlock(&rb);
+ for(e = p + n; p < e; ){
+ if(rb.wp == rb.rp){
+ rb.wakeme = 1;
+ wakeup(&rb.producer);
+ sleep(&rb.consumer, rbnotempty, 0);
+ rb.wakeme = 0;
+ continue;
+ }
+
+ /*
+ * beating clocks will be predictable if
+ * they are synchronized. Use a cheap pseudo
+ * random number generator to obscure any cycles.
+ */
+ x = rb.randn*1103515245 ^ *rb.rp;
+ *p++ = rb.randn = x;
+
+ if(rb.rp+1 == rb.ep)
+ rb.rp = rb.buf;
+ else
+ rb.rp = rb.rp+1;
+ }
+ qunlock(&rb);
+ poperror();
+
+ wakeup(&rb.producer);
+
+ return n;
+}
diff --git a/sys/src/9/kw/rebootcode.s b/sys/src/9/kw/rebootcode.s
new file mode 100755
index 000000000..0f4a9f98c
--- /dev/null
+++ b/sys/src/9/kw/rebootcode.s
@@ -0,0 +1,172 @@
+/*
+ * sheevaplug reboot code
+ *
+ * R11 is used by the loader as a temporary, so avoid it.
+ */
+#include "arm.s"
+
+/*
+ * Turn off MMU, then copy the new kernel to its correct location
+ * in physical memory. Then jump to the start of the kernel.
+ */
+
+/* main(PADDR(entry), PADDR(code), size); */
+TEXT main(SB), 1, $-4
+ MOVW $setR12(SB), R12
+
+ MOVW R0, p1+0(FP) /* destination, passed in R0 */
+
+ /* copy in arguments from frame */
+ MOVW R0, R8 /* entry point */
+ MOVW p2+4(FP), R9 /* source */
+ MOVW n+8(FP), R10 /* byte count */
+
+WAVE('R')
+ BL cachesoff(SB)
+ /* now back in 29- or 26-bit addressing, mainly for SB */
+
+ /* turn the MMU off */
+WAVE('e')
+ MOVW $KSEGM, R7
+ MOVW $PHYSDRAM, R0
+ BL _r15warp(SB)
+
+ BIC R7, R12 /* SB */
+ BIC R7, R13 /* SP */
+ /* don't care about R14 */
+
+WAVE('b')
+ BL mmuinvalidate(SB)
+WAVE('o')
+ BL mmudisable(SB)
+
+WAVE('o')
+ MOVW R9, R4 /* restore regs across function calls */
+ MOVW R10, R5
+ MOVW R8, R6
+
+ /* set up a new stack for local vars and memmove args */
+ MOVW R6, SP /* tiny trampoline stack */
+ SUB $(0x20 + 4), SP /* back up before a.out header */
+
+ MOVW R14, -48(SP) /* store return addr */
+ SUB $48, SP /* allocate stack frame */
+
+ MOVW R6, 44(SP) /* save dest/entry */
+ MOVW R5, 40(SP) /* save count */
+
+WAVE('t')
+
+ MOVW R6, 0(SP)
+ MOVW R6, 4(SP) /* push dest */
+ MOVW R6, R0
+ MOVW R4, 8(SP) /* push src */
+ MOVW R5, 12(SP) /* push size */
+ BL memmove(SB)
+
+ MOVW 44(SP), R6 /* restore R6 (dest/entry) */
+ MOVW 40(SP), R5 /* restore R5 (count) */
+WAVE('-')
+ /*
+ * flush caches
+ */
+ BL cacheuwbinv(SB)
+
+WAVE('>')
+WAVE('\r');
+WAVE('\n');
+/*
+ * jump to kernel entry point. Note the true kernel entry point is
+ * the virtual address KZERO|R6, but this must wait until
+ * the MMU is enabled by the kernel in l.s
+ */
+ ORR R6, R6 /* NOP: avoid link bug */
+ B (R6)
+
+/*
+ * turn the caches off, double map 0 & KZERO, invalidate TLBs, revert to
+ * tiny addresses. upon return, it will be safe to turn off the mmu.
+ */
+TEXT cachesoff(SB), 1, $-4
+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R0
+ MOVW R0, CPSR
+ MOVW $KADDR(0x100-4), R7 /* just before this code */
+ MOVW R14, (R7) /* save link */
+
+ BL cacheuwbinv(SB)
+
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0)
+ BIC $(CpCwb|CpCicache|CpCdcache|CpCalign), R0
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0)
+ BARRIERS
+
+ /* redo double map of 0, KZERO */
+ MOVW $(L1+L1X(PHYSDRAM)), R4 /* address of PTE for 0 */
+ MOVW $PTEDRAM, R2 /* PTE bits */
+// MOVW $PTEIO, R2 /* PTE bits */
+ MOVW $PHYSDRAM, R3
+ MOVW $512, R5
+_ptrdbl:
+ ORR R3, R2, R1 /* first identity-map 0 to 0, etc. */
+ MOVW R1, (R4)
+ ADD $4, R4 /* bump PTE address */
+ ADD $MiB, R3 /* bump pa */
+ SUB.S $1, R5
+ BNE _ptrdbl
+
+ BARRIERS
+ MOVW $0, R0
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvd), CpTLBinv
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
+ BARRIERS
+
+ /* back to 29- or 26-bit addressing, mainly for SB */
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0)
+ BIC $(CpCd32|CpCi32), R0
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0)
+ BARRIERS
+
+ MOVW $KADDR(0x100-4), R7 /* just before this code */
+ MOVW (R7), R14 /* restore link */
+ RET
+
+TEXT _r15warp(SB), 1, $-4
+ BIC $KSEGM, R14
+ ORR R0, R14
+ RET
+
+TEXT mmudisable(SB), 1, $-4
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0)
+ BIC $(CpChv|CpCmmu|CpCdcache|CpCicache|CpCwb), R0
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0)
+ BARRIERS
+ RET
+
+TEXT mmuinvalidate(SB), 1, $-4 /* invalidate all */
+ MOVW $0, R0
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
+ BARRIERS
+ RET
+
+TEXT cacheuwbinv(SB), 1, $-4 /* D+I writeback+invalidate */
+ BARRIERS
+ MOVW CPSR, R3 /* splhi */
+ ORR $(PsrDirq), R3, R1
+ MOVW R1, CPSR
+
+_uwbinv: /* D writeback+invalidate */
+ MRC CpSC, 0, PC, C(CpCACHE), C(CpCACHEwbi), CpCACHEtest
+ BNE _uwbinv
+
+ MOVW $0, R0 /* I invalidate */
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
+ /* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
+ BARRIERS
+
+ MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2flush), CpTCl2all
+ BARRIERS
+ MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2inv), CpTCl2all
+ BARRIERS
+
+ MOVW R3, CPSR /* splx */
+ RET
diff --git a/sys/src/9/kw/softfpu.c b/sys/src/9/kw/softfpu.c
new file mode 100755
index 000000000..b412a6bf1
--- /dev/null
+++ b/sys/src/9/kw/softfpu.c
@@ -0,0 +1,119 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+int
+fpudevprocio(Proc* proc, void* a, long n, uintptr offset, int write)
+{
+ /*
+ * Called from procdevtab.read and procdevtab.write
+ * allow user process access to the FPU registers.
+ * This is the only FPU routine which is called directly
+ * from the port code; it would be nice to have dynamic
+ * creation of entries in the device file trees...
+ */
+ USED(proc, a, n, offset, write);
+
+ return 0;
+}
+
+void
+fpunotify(Ureg*)
+{
+ /*
+ * Called when a note is about to be delivered to a
+ * user process, usually at the end of a system call.
+ * Note handlers are not allowed to use the FPU so
+ * the state is marked (after saving if necessary) and
+ * checked in the Device Not Available handler.
+ */
+}
+
+void
+fpunoted(void)
+{
+ /*
+ * Called from sysnoted() via the machine-dependent
+ * noted() routine.
+ * Clear the flag set above in fpunotify().
+ */
+}
+
+void
+fpusysrfork(Ureg*)
+{
+ /*
+ * Called early in the non-interruptible path of
+ * sysrfork() via the machine-dependent syscall() routine.
+ * Save the state so that it can be easily copied
+ * to the child process later.
+ */
+}
+
+void
+fpusysrforkchild(Proc*, Ureg*, Proc*)
+{
+ /*
+ * Called later in sysrfork() via the machine-dependent
+ * sysrforkchild() routine.
+ * Copy the parent FPU state to the child.
+ */
+}
+
+void
+fpuprocsave(Proc*)
+{
+ /*
+ * Called from sched() and sleep() via the machine-dependent
+ * procsave() routine.
+ * About to go in to the scheduler.
+ * If the process wasn't using the FPU
+ * there's nothing to do.
+ */
+}
+
+void
+fpuprocrestore(Proc*)
+{
+ /*
+ * The process has been rescheduled and is about to run.
+ * Nothing to do here right now. If the process tries to use
+ * the FPU again it will cause a Device Not Available
+ * exception and the state will then be restored.
+ */
+}
+
+void
+fpusysprocsetup(Proc*)
+{
+ /*
+ * Disable the FPU.
+ * Called from sysexec() via sysprocsetup() to
+ * set the FPU for the new process.
+ */
+}
+
+void
+fpuinit(void)
+{
+}
+
+int
+fpuemu(Ureg* ureg)
+{
+ int nfp;
+
+ if(waserror()){
+ splhi();
+ postnote(up, 1, up->errstr, NDebug);
+ return 1;
+ }
+ spllo();
+ nfp = fpiarm(ureg);
+ splhi();
+ poperror();
+
+ return nfp;
+}
diff --git a/sys/src/9/kw/syscall.c b/sys/src/9/kw/syscall.c
new file mode 100755
index 000000000..d1fcd9fc5
--- /dev/null
+++ b/sys/src/9/kw/syscall.c
@@ -0,0 +1,354 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "../port/systab.h"
+
+#include <tos.h>
+#include "ureg.h"
+
+#include "arm.h"
+
+typedef struct {
+ uintptr ip;
+ Ureg* arg0;
+ char* arg1;
+ char msg[ERRMAX];
+ Ureg* old;
+ Ureg ureg;
+} NFrame;
+
+/*
+ * Return user to state before notify()
+ */
+static void
+noted(Ureg* cur, uintptr arg0)
+{
+ NFrame *nf;
+ Ureg *nur;
+
+ qlock(&up->debug);
+ if(arg0 != NRSTR && !up->notified){
+ qunlock(&up->debug);
+ pprint("call to noted() when not notified\n");
+ pexit("Suicide", 0);
+ }
+ up->notified = 0;
+ fpunoted();
+
+ nf = up->ureg;
+
+ /* sanity clause */
+ if(!okaddr(PTR2UINT(nf), sizeof(NFrame), 0)){
+ qunlock(&up->debug);
+ pprint("bad ureg in noted %#p\n", nf);
+ pexit("Suicide", 0);
+ }
+
+ /* don't let user change system flags */
+ nur = &nf->ureg;
+ nur->psr &= PsrMask|PsrDfiq|PsrDirq;
+ nur->psr |= (cur->psr & ~(PsrMask|PsrDfiq|PsrDirq));
+
+ memmove(cur, nur, sizeof(Ureg));
+
+ switch((int)arg0){
+ case NCONT:
+ case NRSTR:
+ if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->sp, BY2WD, 0)){
+ qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
+ pexit("Suicide", 0);
+ }
+ up->ureg = nf->old;
+ qunlock(&up->debug);
+ break;
+ case NSAVE:
+ if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->sp, BY2WD, 0)){
+ qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
+ pexit("Suicide", 0);
+ }
+ qunlock(&up->debug);
+
+ splhi();
+ nf->arg1 = nf->msg;
+ nf->arg0 = &nf->ureg;
+ nf->ip = 0;
+ cur->sp = PTR2UINT(nf);
+ break;
+ default:
+ pprint("unknown noted arg %#p\n", arg0);
+ up->lastnote.flag = NDebug;
+ /*FALLTHROUGH*/
+ case NDFLT:
+ if(up->lastnote.flag == NDebug){
+ qunlock(&up->debug);
+ pprint("suicide: %s\n", up->lastnote.msg);
+ }
+ else
+ qunlock(&up->debug);
+ pexit(up->lastnote.msg, up->lastnote.flag != NDebug);
+ }
+}
+
+/*
+ * Call user, if necessary, with note.
+ * Pass user the Ureg struct and the note on his stack.
+ */
+int
+notify(Ureg* ureg)
+{
+ int l;
+ Note *n;
+ u32int s;
+ uintptr sp;
+ NFrame *nf;
+
+ if(up->procctl)
+ procctl(up);
+ if(up->nnote == 0)
+ return 0;
+
+ fpunotify(ureg);
+
+ s = spllo();
+ qlock(&up->debug);
+
+ up->notepending = 0;
+ n = &up->note[0];
+ if(strncmp(n->msg, "sys:", 4) == 0){
+ l = strlen(n->msg);
+ if(l > ERRMAX-23) /* " pc=0x0123456789abcdef\0" */
+ l = ERRMAX-23;
+ snprint(n->msg + l, sizeof n->msg - l, " pc=%#lux", ureg->pc);
+ }
+
+ if(n->flag != NUser && (up->notified || up->notify == 0)){
+ if(n->flag == NDebug)
+ pprint("suicide: %s\n", n->msg);
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag != NDebug);
+ }
+
+ if(up->notified){
+ qunlock(&up->debug);
+ splhi();
+ return 0;
+ }
+
+ if(up->notify == nil){
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag != NDebug);
+ }
+ if(!okaddr(PTR2UINT(up->notify), 1, 0)){
+ pprint("suicide: notify function address %#p\n", up->notify);
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+
+ sp = ureg->sp - sizeof(NFrame);
+ if(!okaddr(sp, sizeof(NFrame), 1)){
+ qunlock(&up->debug);
+ pprint("suicide: notify stack address %#p\n", sp);
+ pexit("Suicide", 0);
+ }
+
+ nf = UINT2PTR(sp);
+ memmove(&nf->ureg, ureg, sizeof(Ureg));
+ nf->old = up->ureg;
+ up->ureg = nf;
+ memmove(nf->msg, up->note[0].msg, ERRMAX);
+ nf->arg1 = nf->msg;
+ nf->arg0 = &nf->ureg;
+ nf->ip = 0;
+
+ ureg->sp = sp;
+ ureg->pc = PTR2UINT(up->notify);
+ up->notified = 1;
+ up->nnote--;
+ memmove(&up->lastnote, &up->note[0], sizeof(Note));
+ memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
+
+ qunlock(&up->debug);
+ splx(s);
+
+ return 1;
+}
+
+void
+syscall(Ureg* ureg)
+{
+ char *e;
+ u32int s;
+ ulong sp;
+ long ret;
+ int i, scallnr;
+ vlong startns, stopns;
+
+ if(!userureg(ureg))
+ panic("syscall: from kernel: pc %#lux r14 %#lux psr %#lux",
+ ureg->pc, ureg->r14, ureg->psr);
+
+ cycles(&up->kentry);
+
+ m->syscall++;
+ up->insyscall = 1;
+ up->pc = ureg->pc;
+ up->dbgreg = ureg;
+
+ scallnr = ureg->r0;
+ up->scallnr = scallnr;
+ if(scallnr == RFORK)
+ fpusysrfork(ureg);
+ spllo();
+ sp = ureg->sp;
+
+ if(up->procctl == Proc_tracesyscall){
+ /*
+ * Redundant validaddr. Do we care?
+ * Tracing syscalls is not exactly a fast path...
+ * Beware, validaddr currently does a pexit rather
+ * than an error if there's a problem; that might
+ * change in the future.
+ */
+ if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)-BY2WD))
+ validaddr(sp, sizeof(Sargs)+BY2WD, 0);
+
+ syscallfmt(scallnr, ureg->pc, (va_list)(sp+BY2WD));
+ up->procctl = Proc_stopme;
+ procctl(up);
+ if (up->syscalltrace)
+ free(up->syscalltrace);
+ up->syscalltrace = nil;
+ }
+
+ up->nerrlab = 0;
+ ret = -1;
+ startns = todget(nil);
+ if(!waserror()){
+ if(scallnr >= nsyscall){
+ pprint("bad sys call number %d pc %#lux\n",
+ scallnr, ureg->pc);
+ postnote(up, 1, "sys: bad sys call", NDebug);
+ error(Ebadarg);
+ }
+
+ if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)-BY2WD))
+ validaddr(sp, sizeof(Sargs)+BY2WD, 0);
+
+ up->s = *((Sargs*)(sp+BY2WD));
+ up->psstate = sysctab[scallnr];
+
+ /* iprint("%s: syscall %s\n", up->text, sysctab[scallnr]?sysctab[scallnr]:"huh?"); */
+
+ ret = systab[scallnr](up->s.args);
+ poperror();
+ }else{
+ /* failure: save the error buffer for errstr */
+ e = up->syserrstr;
+ up->syserrstr = up->errstr;
+ up->errstr = e;
+ }
+ if(up->nerrlab){
+ print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
+ for(i = 0; i < NERR; i++)
+ print("sp=%#p pc=%#p\n",
+ up->errlab[i].sp, up->errlab[i].pc);
+ panic("error stack");
+ }
+
+ /*
+ * Put return value in frame. On the x86 the syscall is
+ * just another trap and the return value from syscall is
+ * ignored. On other machines the return value is put into
+ * the results register by caller of syscall.
+ */
+ ureg->r0 = ret;
+
+ if(up->procctl == Proc_tracesyscall){
+ stopns = todget(nil);
+ up->procctl = Proc_stopme;
+ sysretfmt(scallnr, (va_list)(sp+BY2WD), ret, startns, stopns);
+ s = splhi();
+ procctl(up);
+ splx(s);
+ if(up->syscalltrace)
+ free(up->syscalltrace);
+ up->syscalltrace = nil;
+ }
+
+ up->insyscall = 0;
+ up->psstate = 0;
+
+ if(scallnr == NOTED)
+ noted(ureg, *(ulong*)(sp+BY2WD));
+
+ splhi();
+ if(scallnr != RFORK && (up->procctl || up->nnote))
+ notify(ureg);
+
+ /* if we delayed sched because we held a lock, sched now */
+ if(up->delaysched){
+ sched();
+ splhi();
+ }
+ kexit(ureg);
+}
+
+long
+execregs(ulong entry, ulong ssize, ulong nargs)
+{
+ ulong *sp;
+ Ureg *ureg;
+
+ sp = (ulong*)(USTKTOP - ssize);
+ *--sp = nargs;
+
+ ureg = up->dbgreg;
+// memset(ureg, 0, 15*sizeof(ulong));
+ ureg->r13 = (ulong)sp;
+ ureg->pc = entry;
+//print("%lud: EXECREGS pc %#ux sp %#ux nargs %ld\n", up->pid, ureg->pc, ureg->r13, nargs);
+
+ /*
+ * return the address of kernel/user shared data
+ * (e.g. clock stuff)
+ */
+ return USTKTOP-sizeof(Tos);
+}
+
+void
+sysprocsetup(Proc* p)
+{
+ fpusysprocsetup(p);
+}
+
+/*
+ * Craft a return frame which will cause the child to pop out of
+ * the scheduler in user mode with the return register zero. Set
+ * pc to point to a l.s return function.
+ */
+void
+forkchild(Proc *p, Ureg *ureg)
+{
+ Ureg *cureg;
+
+//print("%lud setting up for forking child %lud\n", up->pid, p->pid);
+ p->sched.sp = (ulong)p->kstack+KSTACK-sizeof(Ureg);
+ p->sched.pc = (ulong)forkret;
+
+ cureg = (Ureg*)(p->sched.sp);
+ memmove(cureg, ureg, sizeof(Ureg));
+
+ /* syscall returns 0 for child */
+ cureg->r0 = 0;
+
+ /* Things from bottom of syscall which were never executed */
+ p->psstate = 0;
+ p->insyscall = 0;
+
+ fpusysrforkchild(p, cureg, up);
+}
diff --git a/sys/src/9/kw/trap.c b/sys/src/9/kw/trap.c
new file mode 100755
index 000000000..f4d2c7756
--- /dev/null
+++ b/sys/src/9/kw/trap.c
@@ -0,0 +1,671 @@
+/*
+ * sheevaplug traps, exceptions, interrupts, system calls.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+#include "arm.h"
+
+enum {
+ Ntimevec = 20, /* # of time buckets for each intr */
+ Nvecs = 256,
+};
+
+extern int notify(Ureg*);
+
+extern int ldrexvalid;
+
+typedef struct Vctl Vctl;
+typedef struct Vctl {
+ Vctl* next; /* handlers on this vector */
+ char *name; /* of driver, xallocated */
+ void (*f)(Ureg*, void*); /* handler to call */
+ void* a; /* argument to call it with */
+} Vctl;
+
+static Lock vctllock;
+static Vctl* vctl[32];
+
+uvlong ninterrupt;
+uvlong ninterruptticks;
+ulong intrtimes[Nvecs][Ntimevec];
+
+typedef struct Handler Handler;
+struct Handler {
+ void (*r)(Ureg*, void*);
+ void *a;
+ char name[KNAMELEN];
+};
+
+static Handler irqlo[32];
+static Handler irqhi[32];
+static Handler irqbridge[32];
+static Lock irqlock;
+static int probing, trapped;
+
+typedef struct Irq Irq;
+struct Irq {
+ ulong *irq;
+ ulong *irqmask;
+ Handler *irqvec;
+ int nirqvec;
+ char *name;
+};
+/* irq and irqmask are filled in by trapinit */
+static Irq irqs[] = {
+[Irqlo] {nil, nil, irqlo, nelem(irqlo), "lo"},
+[Irqhi] {nil, nil, irqhi, nelem(irqhi), "hi"},
+[Irqbridge] {nil, nil, irqbridge, nelem(irqbridge), "bridge"},
+};
+
+/*
+ * keep histogram of interrupt service times
+ */
+void
+intrtime(Mach*, int vno)
+{
+ ulong diff, x;
+
+ if (m == nil)
+ return;
+ x = perfticks();
+ diff = x - m->perf.intrts;
+ m->perf.intrts = x;
+
+ m->perf.inintr += diff;
+ if(up == nil && m->perf.inidle > diff)
+ m->perf.inidle -= diff;
+
+ if (m->cpuhz == 0) /* not set yet? */
+ return;
+ diff /= (m->cpuhz/1000000)*100; /* quantum = 100µsec */
+ if(diff >= Ntimevec)
+ diff = Ntimevec-1;
+ assert(vno >= 0 && vno < Nvecs);
+ intrtimes[vno][diff]++;
+}
+
+void
+intrfmtcounts(char *s, char *se)
+{
+ USED(s, se);
+}
+
+static void
+dumpcounts(void)
+{
+}
+
+void
+intrclear(int sort, int v)
+{
+ *irqs[sort].irq = ~(1 << v);
+}
+
+void
+intrmask(int sort, int v)
+{
+ *irqs[sort].irqmask &= ~(1 << v);
+}
+
+void
+intrunmask(int sort, int v)
+{
+ *irqs[sort].irqmask |= 1 << v;
+}
+
+static void
+maskallints(void)
+{
+ CpucsReg *cpu = (CpucsReg *)soc.cpu;
+ IntrReg *intr;
+
+ /* no fiq or ep in use */
+ intr = (IntrReg *)soc.intr;
+ intr->lo.irqmask = 0;
+ intr->hi.irqmask = 0;
+ cpu->irqmask = 0;
+ coherence();
+}
+
+void
+intrset(Handler *h, void (*f)(Ureg*, void*), void *a, char *name)
+{
+ if(h->r != nil) {
+// iprint("duplicate irq: %s (%#p)\n", h->name, h->r);
+ return;
+ }
+ h->r = f;
+ h->a = a;
+ strncpy(h->name, name, KNAMELEN-1);
+ h->name[KNAMELEN-1] = 0;
+}
+
+void
+intrunset(Handler *h)
+{
+ h->r = nil;
+ h->a = nil;
+ h->name[0] = 0;
+}
+
+void
+intrdel(Handler *h, void (*f)(Ureg*, void*), void *a, char *name)
+{
+ if(h->r != f || h->a != a || strcmp(h->name, name) != 0)
+ return;
+ intrunset(h);
+}
+
+void
+intrenable(int sort, int v, void (*f)(Ureg*, void*), void *a, char *name)
+{
+//iprint("enabling intr %d vec %d for %s\n", sort, v, name);
+ ilock(&irqlock);
+ intrset(&irqs[sort].irqvec[v], f, a, name);
+ intrunmask(sort, v);
+ iunlock(&irqlock);
+}
+
+void
+intrdisable(int sort, int v, void (*f)(Ureg*, void*), void* a, char *name)
+{
+ ilock(&irqlock);
+ intrdel(&irqs[sort].irqvec[v], f, a, name);
+ intrmask(sort, v);
+ iunlock(&irqlock);
+}
+
+/*
+ * called by trap to handle interrupts
+ */
+static void
+intrs(Ureg *ur, int sort)
+{
+ int i, s;
+ ulong ibits;
+ Handler *h;
+ Irq irq;
+
+ assert(sort >= 0 && sort < nelem(irqs));
+ irq = irqs[sort];
+ ibits = *irq.irq;
+ ibits &= *irq.irqmask;
+
+ for(i = 0; i < irq.nirqvec && ibits; i++)
+ if(ibits & (1<<i)){
+ h = &irq.irqvec[i];
+ if(h->r != nil){
+ h->r(ur, h->a);
+ splhi();
+ intrtime(m, sort*32 + i);
+ if (sort == Irqbridge && i == IRQcputimer0)
+ m->inclockintr = 1;
+ ibits &= ~(1<<i);
+ }
+ }
+ if(ibits != 0) {
+ iprint("spurious irq%s interrupt: %8.8lux\n", irq.name, ibits);
+ s = splfhi();
+ *irq.irq &= ibits;
+ splx(s);
+ }
+}
+
+void
+intrhi(Ureg *ureg, void*)
+{
+ intrs(ureg, Irqhi);
+}
+
+void
+intrbridge(Ureg *ureg, void*)
+{
+ intrs(ureg, Irqbridge);
+ intrclear(Irqlo, IRQ0bridge);
+}
+
+void
+trapinit(void)
+{
+ int i;
+ CpucsReg *cpu;
+ IntrReg *intr;
+ Vectorpage *page0 = (Vectorpage*)HVECTORS;
+
+ intr = (IntrReg *)soc.intr;
+ cpu = (CpucsReg *)soc.cpu;
+ irqs[Irqlo].irq = &intr->lo.irq;
+ irqs[Irqlo].irqmask = &intr->lo.irqmask;
+ irqs[Irqhi].irq = &intr->hi.irq;
+ irqs[Irqhi].irqmask = &intr->hi.irqmask;
+ irqs[Irqbridge].irq = &cpu->irq;
+ irqs[Irqbridge].irqmask = &cpu->irqmask;
+ coherence();
+
+ setr13(PsrMfiq, m->fiqstack + nelem(m->fiqstack));
+ setr13(PsrMirq, m->irqstack + nelem(m->irqstack));
+ setr13(PsrMabt, m->abtstack + nelem(m->abtstack));
+ setr13(PsrMund, m->undstack + nelem(m->undstack));
+
+ memmove(page0->vectors, vectors, sizeof page0->vectors);
+ memmove(page0->vtable, vtable, sizeof page0->vtable);
+ cacheuwbinv();
+ l2cacheuwbinv();
+
+ cpu->cpucfg &= ~Cfgvecinithi;
+
+ for(i = 0; i < nelem(irqlo); i++)
+ intrunset(&irqlo[i]);
+ for(i = 0; i < nelem(irqhi); i++)
+ intrunset(&irqhi[i]);
+ for(i = 0; i < nelem(irqbridge); i++)
+ intrunset(&irqbridge[i]);
+
+ /* disable all interrupts */
+ intr->lo.fiqmask = intr->hi.fiqmask = 0;
+ intr->lo.irqmask = intr->hi.irqmask = 0;
+ intr->lo.epmask = intr->hi.epmask = 0;
+ cpu->irqmask = 0;
+ coherence();
+
+ /* clear interrupts */
+ intr->lo.irq = intr->hi.irq = ~0;
+ cpu->irq = ~0;
+ coherence();
+
+ intrenable(Irqlo, IRQ0hisum, intrhi, nil, "hi");
+ intrenable(Irqlo, IRQ0bridge, intrbridge, nil, "bridge");
+
+ /* enable watchdog & access-error interrupts */
+ cpu->irqmask |= 1 << IRQcputimerwd | 1 << IRQaccesserr;
+ coherence();
+}
+
+static char *trapnames[PsrMask+1] = {
+ [ PsrMusr ] "user mode",
+ [ PsrMfiq ] "fiq interrupt",
+ [ PsrMirq ] "irq interrupt",
+ [ PsrMsvc ] "svc/swi exception",
+ [ PsrMabt ] "prefetch abort/data abort",
+ [ PsrMabt+1 ] "data abort",
+ [ PsrMund ] "undefined instruction",
+ [ PsrMsys ] "sys trap",
+};
+
+static char *
+trapname(int psr)
+{
+ char *s;
+
+ s = trapnames[psr & PsrMask];
+ if(s == nil)
+ s = "unknown trap number in psr";
+ return s;
+}
+
+/*
+ * called by trap to handle access faults
+ */
+static void
+faultarm(Ureg *ureg, uintptr va, int user, int read)
+{
+ int n, insyscall;
+ char buf[ERRMAX];
+ static int cnt, lastpid;
+ static ulong lastva;
+
+ if(up == nil) {
+ dumpregs(ureg);
+ panic("fault: nil up in faultarm, accessing %#p", va);
+ }
+ insyscall = up->insyscall;
+ up->insyscall = 1;
+
+ /* this is quite helpful during mmu and cache debugging */
+ if(va == lastva && up->pid == lastpid) {
+ ++cnt;
+ if (cnt >= 2)
+ /* fault() isn't fixing the underlying cause */
+ panic("fault: %d consecutive faults for va %#lux",
+ cnt+1, va);
+ } else {
+ cnt = 0;
+ lastva = va;
+ lastpid = up->pid;
+ }
+
+ n = fault(va, read);
+ if(n < 0){
+ if(!user){
+ dumpregs(ureg);
+ panic("fault: kernel accessing %#p", va);
+ }
+ /* don't dump registers; programs suicide all the time */
+ snprint(buf, sizeof buf, "sys: trap: fault %s va=%#p",
+ read? "read": "write", va);
+ postnote(up, 1, buf, NDebug);
+ }
+ up->insyscall = insyscall;
+}
+
+/*
+ * returns 1 if the instruction writes memory, 0 otherwise
+ */
+int
+writetomem(ulong inst)
+{
+ /* swap always write memory */
+ if((inst & 0x0FC00000) == 0x01000000)
+ return 1;
+
+ /* loads and stores are distinguished by bit 20 */
+ if(inst & (1<<20))
+ return 0;
+
+ return 1;
+}
+
+void
+trap(Ureg *ureg)
+{
+ int user, x, rv, rem;
+ ulong inst;
+ u32int fsr;
+ uintptr va;
+ char buf[ERRMAX];
+
+ if(up != nil)
+ rem = (char*)ureg - up->kstack;
+ else
+ rem = (char*)ureg - ((char*)m + sizeof(Mach));
+ if(rem < 256) {
+ dumpstack();
+ panic("trap %d bytes remaining, up %#p ureg %#p at pc %#lux",
+ rem, up, ureg, ureg->pc);
+ }
+
+ user = (ureg->psr & PsrMask) == PsrMusr;
+ if(user){
+ up->dbgreg = ureg;
+ cycles(&up->kentry);
+ }
+
+ if(ureg->type == PsrMabt+1)
+ ureg->pc -= 8;
+ else
+ ureg->pc -= 4;
+
+ m->inclockintr = 0;
+ switch(ureg->type) {
+ default:
+ panic("unknown trap %ld", ureg->type);
+ break;
+ case PsrMirq:
+ ldrexvalid = 0;
+ // splflo(); /* allow fast interrupts */
+ intrs(ureg, Irqlo);
+ m->intr++;
+ break;
+ case PsrMabt: /* prefetch fault */
+ ldrexvalid = 0;
+ faultarm(ureg, ureg->pc, user, 1);
+ break;
+ case PsrMabt+1: /* data fault */
+ ldrexvalid = 0;
+ va = farget();
+ inst = *(ulong*)(ureg->pc);
+ fsr = fsrget() & 0xf;
+ if (probing && !user) {
+ if (trapped++ > 0)
+ panic("trap: recursive probe %#lux", va);
+ ureg->pc += 4; /* continue at next instruction */
+ break;
+ }
+ switch(fsr){
+ case 0x0:
+ panic("vector exception at %#lux", ureg->pc);
+ break;
+ case 0x1:
+ case 0x3:
+ if(user){
+ snprint(buf, sizeof buf,
+ "sys: alignment: pc %#lux va %#p\n",
+ ureg->pc, va);
+ postnote(up, 1, buf, NDebug);
+ } else
+ panic("kernel alignment: pc %#lux va %#p", ureg->pc, va);
+ break;
+ case 0x2:
+ panic("terminal exception at %#lux", ureg->pc);
+ break;
+ case 0x4:
+ case 0x6:
+ case 0x8:
+ case 0xa:
+ case 0xc:
+ case 0xe:
+ panic("external abort %#ux pc %#lux addr %#px",
+ fsr, ureg->pc, va);
+ break;
+ case 0x5: /* translation fault, no section entry */
+ case 0x7: /* translation fault, no page entry */
+ faultarm(ureg, va, user, !writetomem(inst));
+ break;
+ case 0x9:
+ case 0xb:
+ /* domain fault, accessing something we shouldn't */
+ if(user){
+ snprint(buf, sizeof buf,
+ "sys: access violation: pc %#lux va %#p\n",
+ ureg->pc, va);
+ postnote(up, 1, buf, NDebug);
+ } else
+ panic("kernel access violation: pc %#lux va %#p",
+ ureg->pc, va);
+ break;
+ case 0xd:
+ case 0xf:
+ /* permission error, copy on write or real permission error */
+ faultarm(ureg, va, user, !writetomem(inst));
+ break;
+ }
+ break;
+ case PsrMund: /* undefined instruction */
+ if(user){
+ /* look for floating point instructions to interpret */
+ x = spllo();
+ rv = fpiarm(ureg);
+ splx(x);
+ if(rv == 0){
+ ldrexvalid = 0;
+ snprint(buf, sizeof buf,
+ "undefined instruction: pc %#lux",
+ ureg->pc);
+ postnote(up, 1, buf, NDebug);
+ }
+ }else{
+ iprint("undefined instruction: pc %#lux inst %#ux\n",
+ ureg->pc, ((u32int*)ureg->pc)[-2]);
+ panic("undefined instruction");
+ }
+ break;
+ }
+ splhi();
+
+ /* delaysched set because we held a lock or because our quantum ended */
+ if(up && up->delaysched && m->inclockintr){
+ ldrexvalid = 0;
+ sched();
+ splhi();
+ }
+
+ if(user){
+ if(up->procctl || up->nnote)
+ notify(ureg);
+ kexit(ureg);
+ }
+}
+
+int
+isvalidaddr(void *v)
+{
+ return (uintptr)v >= KZERO;
+}
+
+void
+dumplongs(char *msg, ulong *v, int n)
+{
+ int i, l;
+
+ l = 0;
+ iprint("%s at %.8p: ", msg, v);
+ for(i=0; i<n; i++){
+ if(l >= 4){
+ iprint("\n %.8p: ", v);
+ l = 0;
+ }
+ if(isvalidaddr(v)){
+ iprint(" %.8lux", *v++);
+ l++;
+ }else{
+ iprint(" invalid");
+ break;
+ }
+ }
+ iprint("\n");
+}
+
+static void
+dumpstackwithureg(Ureg *ureg)
+{
+ uintptr l, i, v, estack;
+ u32int *p;
+
+ iprint("ktrace /kernel/path %#.8lux %#.8lux %#.8lux # pc, sp, link\n",
+ ureg->pc, ureg->sp, ureg->r14);
+ delay(2000);
+ i = 0;
+ if(up != nil && (uintptr)&l <= (uintptr)up->kstack+KSTACK)
+ estack = (uintptr)up->kstack+KSTACK;
+ else if((uintptr)&l >= (uintptr)m->stack
+ && (uintptr)&l <= (uintptr)m+MACHSIZE)
+ estack = (uintptr)m+MACHSIZE;
+ else{
+ if(up != nil)
+ iprint("&up->kstack %#p &l %#p\n", up->kstack, &l);
+ else
+ iprint("&m %#p &l %#p\n", m, &l);
+ return;
+ }
+ for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
+ v = *(uintptr*)l;
+ if(KTZERO < v && v < (uintptr)etext && !(v & 3)){
+ v -= sizeof(u32int); /* back up an instr */
+ p = (u32int*)v;
+ if((*p & 0x0f000000) == 0x0b000000){ /* BL instr? */
+ iprint("%#8.8lux=%#8.8lux ", l, v);
+ i++;
+ }
+ }
+ if(i == 4){
+ i = 0;
+ iprint("\n");
+ }
+ }
+ if(i)
+ iprint("\n");
+}
+
+/*
+ * Fill in enough of Ureg to get a stack trace, and call a function.
+ * Used by debugging interface rdb.
+ */
+void
+callwithureg(void (*fn)(Ureg*))
+{
+ Ureg ureg;
+
+ ureg.pc = getcallerpc(&fn);
+ ureg.sp = PTR2UINT(&fn);
+ fn(&ureg);
+}
+
+void
+dumpstack(void)
+{
+ callwithureg(dumpstackwithureg);
+}
+
+void
+dumpregs(Ureg* ureg)
+{
+ int s;
+
+ if (ureg == nil) {
+ iprint("trap: no user process\n");
+ return;
+ }
+ s = splhi();
+ iprint("trap: %s", trapname(ureg->type));
+ if(ureg != nil && (ureg->psr & PsrMask) != PsrMsvc)
+ iprint(" in %s", trapname(ureg->psr));
+ iprint("\n");
+ iprint("psr %8.8lux type %2.2lux pc %8.8lux link %8.8lux\n",
+ ureg->psr, ureg->type, ureg->pc, ureg->link);
+ iprint("R14 %8.8lux R13 %8.8lux R12 %8.8lux R11 %8.8lux R10 %8.8lux\n",
+ ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
+ iprint("R9 %8.8lux R8 %8.8lux R7 %8.8lux R6 %8.8lux R5 %8.8lux\n",
+ ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
+ iprint("R4 %8.8lux R3 %8.8lux R2 %8.8lux R1 %8.8lux R0 %8.8lux\n",
+ ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
+ iprint("stack is at %#p\n", ureg);
+ iprint("pc %#lux link %#lux\n", ureg->pc, ureg->link);
+
+ if(up)
+ iprint("user stack: %#p-%#p\n", up->kstack, up->kstack+KSTACK-4);
+ else
+ iprint("kernel stack: %8.8lux-%8.8lux\n",
+ (ulong)(m+1), (ulong)m+BY2PG-4);
+ dumplongs("stack", (ulong *)(ureg + 1), 16);
+ delay(2000);
+ dumpstack();
+ splx(s);
+}
+
+void
+idlehands(void)
+{
+ extern void _idlehands(void);
+
+ _idlehands();
+}
+
+vlong
+probeaddr(uintptr addr)
+{
+ vlong v;
+ static Lock fltlck;
+
+ ilock(&fltlck);
+ trapped = 0;
+ probing = 1;
+ coherence();
+
+ v = *(ulong *)addr; /* this may cause a fault */
+ USED(probing);
+ coherence();
+
+ probing = 0;
+ coherence();
+ if (trapped)
+ v = -1;
+ iunlock(&fltlck);
+ return v;
+}
diff --git a/sys/src/9/kw/uartkw.c b/sys/src/9/kw/uartkw.c
new file mode 100755
index 000000000..0b7e048d0
--- /dev/null
+++ b/sys/src/9/kw/uartkw.c
@@ -0,0 +1,362 @@
+/*
+ * marvell kirkwood uart (supposed to be a 16550)
+ */
+#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/uart.h"
+
+enum {
+ UartFREQ = 0, // xxx
+
+ IERrx = 1<<0,
+ IERtx = 1<<1,
+
+ IRRintrmask = (1<<4)-1,
+ IRRnointr = 1,
+ IRRthrempty = 2,
+ IRRrxdata = 4,
+ IRRrxstatus = 6,
+ IRRtimeout = 12,
+
+ IRRfifomask = 3<<6,
+ IRRfifoenable = 3<<6,
+
+ FCRenable = 1<<0,
+ FCRrxreset = 1<<1,
+ FCRtxreset = 1<<2,
+ /* reserved */
+ FCRrxtriggermask = 3<<6,
+ FCRrxtrigger1 = 0<<6,
+ FCRrxtrigger4 = 1<<6,
+ FCRrxtrigger8 = 2<<6,
+ FCRrxtrigger14 = 3<<6,
+
+ LCRbpcmask = 3<<0,
+ LCRbpc5 = 0<<0,
+ LCRbpc6 = 1<<0,
+ LCRbpc7 = 2<<0,
+ LCRbpc8 = 3<<0,
+ LCRstop2b = 1<<2,
+ LCRparity = 1<<3,
+ LCRparityeven = 1<<4,
+ LCRbreak = 1<<6,
+ LCRdivlatch = 1<<7,
+
+ LSRrx = 1<<0,
+ LSRrunerr = 1<<1,
+ LSRparerr = 1<<2,
+ LSRframeerr = 1<<3,
+ LSRbi = 1<<4,
+ LSRthre = 1<<5,
+ LSRtxempty = 1<<6,
+ LSRfifoerr = 1<<7,
+};
+
+extern PhysUart kwphysuart;
+
+typedef struct UartReg UartReg;
+struct UartReg
+{
+ union {
+ ulong thr;
+ ulong dll;
+ ulong rbr;
+ };
+ union {
+ ulong ier;
+ ulong dlh;
+ };
+ union {
+ ulong iir;
+ ulong fcr;
+ };
+ ulong lcr;
+ ulong mcr;
+ ulong lsr;
+ ulong scr;
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ UartReg*regs;
+ int irq;
+ Lock;
+};
+
+static Ctlr kirkwoodctlr[] = {
+{
+ .regs = nil, /* filled in below */
+ .irq = IRQ1uart0, },
+};
+
+static Uart kirkwooduart[] = {
+{
+ .regs = &kirkwoodctlr[0],
+ .name = "eia0",
+ .freq = UartFREQ,
+ .phys = &kwphysuart,
+ .special= 0,
+ .console= 1,
+ .next = nil, },
+};
+
+static void
+kw_read(Uart *uart)
+{
+ Ctlr *ctlr = uart->regs;
+ UartReg *regs = ctlr->regs;
+ ulong lsr;
+ char c;
+
+ while ((lsr = regs->lsr) & LSRrx) {
+ if(lsr&LSRrunerr)
+ uart->oerr++;
+ if(lsr&LSRparerr)
+ uart->perr++;
+ if(lsr&LSRframeerr)
+ uart->ferr++;
+ c = regs->rbr;
+ if((lsr & (LSRbi|LSRframeerr|LSRparerr)) == 0)
+ uartrecv(uart, c);
+ }
+}
+
+static void
+kw_intr(Ureg*, void *arg)
+{
+ Uart *uart = arg;
+ Ctlr *ctlr = uart->regs;
+ UartReg *regs = ctlr->regs;
+ ulong v;
+
+ if(regs == 0) {
+ kirkwoodctlr[0].regs = (UartReg *)soc.uart[0];
+ regs = (UartReg *)soc.uart[0]; /* caution */
+ coherence();
+ }
+ v = regs->iir;
+ if(v & IRRthrempty)
+ uartkick(uart);
+ if(v & IRRrxdata)
+ kw_read(uart);
+
+ intrclear(Irqhi, ctlr->irq);
+}
+
+static Uart*
+kw_pnp(void)
+{
+ kirkwoodctlr[0].regs = (UartReg *)soc.uart[0];
+ coherence();
+ return kirkwooduart;
+}
+
+static void
+kw_enable(Uart* uart, int ie)
+{
+ Ctlr *ctlr = uart->regs;
+ UartReg *regs = ctlr->regs;
+
+ if(regs == 0) {
+ kirkwoodctlr[0].regs = (UartReg *)soc.uart[0];
+ regs = (UartReg *)soc.uart[0]; /* caution */
+ coherence();
+ }
+ USED(ie);
+ regs->fcr = FCRenable|FCRrxtrigger4;
+ regs->ier = IERrx|IERtx;
+ intrenable(Irqhi, ctlr->irq, kw_intr, uart, uart->name);
+
+ (*uart->phys->dtr)(uart, 1);
+ (*uart->phys->rts)(uart, 1);
+}
+
+static void
+kw_disable(Uart* uart)
+{
+ Ctlr *ctlr = uart->regs;
+
+ (*uart->phys->dtr)(uart, 0);
+ (*uart->phys->rts)(uart, 0);
+ (*uart->phys->fifo)(uart, 0);
+
+ intrdisable(Irqhi, ctlr->irq, kw_intr, uart, uart->name);
+}
+
+static void
+kw_kick(Uart* uart)
+{
+ Ctlr *ctlr = uart->regs;
+ UartReg *regs = ctlr->regs;
+ int i;
+
+ if(uart->cts == 0 || uart->blocked)
+ return;
+
+ for(i = 0; i < 16; i++) {
+ if((regs->lsr & LSRthre) == 0 ||
+ uart->op >= uart->oe && uartstageoutput(uart) == 0)
+ break;
+ regs->thr = *uart->op++;
+ }
+}
+
+static void
+kw_break(Uart* uart, int ms)
+{
+ USED(uart, ms);
+}
+
+static int
+kw_baud(Uart* uart, int baud)
+{
+ USED(uart, baud);
+ return 0;
+}
+
+static int
+kw_bits(Uart* uart, int bits)
+{
+ USED(uart, bits);
+ return 0;
+}
+
+static int
+kw_stop(Uart* uart, int stop)
+{
+ USED(uart, stop);
+ return 0;
+}
+
+static int
+kw_parity(Uart* uart, int parity)
+{
+ USED(uart, parity);
+ return 0;
+}
+
+static void
+kw_modemctl(Uart* uart, int on)
+{
+ USED(uart, on);
+}
+
+static void
+kw_rts(Uart* uart, int on)
+{
+ USED(uart, on);
+}
+
+static void
+kw_dtr(Uart* uart, int on)
+{
+ USED(uart, on);
+}
+
+static long
+kw_status(Uart* uart, void* buf, long n, long offset)
+{
+ USED(uart, buf, n, offset);
+ return 0;
+}
+
+static void
+kw_fifo(Uart* uart, int level)
+{
+ USED(uart, level);
+}
+
+static int
+kw_getc(Uart *uart)
+{
+ Ctlr *ctlr = uart->regs;
+ UartReg *regs = ctlr->regs;
+
+ while((regs->lsr&LSRrx) == 0)
+ ;
+ return regs->rbr;
+}
+
+static void
+kw_putc(Uart *uart, int c)
+{
+ Ctlr *ctlr = uart->regs;
+ UartReg *regs = ctlr->regs;
+
+ /* can be called from iprint, among many other places */
+ if(regs == 0) {
+ kirkwoodctlr[0].regs = (UartReg *)soc.uart[0];
+ regs = (UartReg *)soc.uart[0]; /* caution */
+ coherence();
+ }
+ while((regs->lsr&LSRthre) == 0)
+ ;
+ regs->thr = c;
+ coherence();
+}
+
+PhysUart kwphysuart = {
+ .name = "kirkwood",
+ .pnp = kw_pnp,
+ .enable = kw_enable,
+ .disable = kw_disable,
+ .kick = kw_kick,
+ .dobreak = kw_break,
+ .baud = kw_baud,
+ .bits = kw_bits,
+ .stop = kw_stop,
+ .parity = kw_parity,
+ .modemctl = kw_modemctl,
+ .rts = kw_rts,
+ .dtr = kw_dtr,
+ .status = kw_status,
+ .fifo = kw_fifo,
+ .getc = kw_getc,
+ .putc = kw_putc,
+};
+
+void
+uartkirkwoodconsole(void)
+{
+ Uart *uart;
+
+ uart = &kirkwooduart[0];
+ (*uart->phys->enable)(uart, 0);
+ uartctl(uart, "b115200 l8 pn s1 i1");
+ uart->console = 1;
+ consuart = uart;
+//serialputs("uart0 kirkwood\n", strlen("uart0 kirkwood\n"));
+}
+
+void
+serialputc(int c)
+{
+ int cnt, s;
+ UartReg *regs = (UartReg *)soc.uart[0];
+
+ s = splhi();
+ cnt = m->cpuhz;
+ if (cnt <= 0) /* cpuhz not set yet? */
+ cnt = 1000000;
+ while((regs->lsr & LSRthre) == 0 && --cnt > 0)
+ ;
+ regs->thr = c;
+ coherence();
+ delay(1);
+ splx(s);
+}
+
+void
+serialputs(char *p, int len)
+{
+ while(--len >= 0) {
+ if(*p == '\n')
+ serialputc('\r');
+ serialputc(*p++);
+ }
+}
diff --git a/sys/src/9/kw/ucalloc.c b/sys/src/9/kw/ucalloc.c
new file mode 100755
index 000000000..37e8564c0
--- /dev/null
+++ b/sys/src/9/kw/ucalloc.c
@@ -0,0 +1,135 @@
+/*
+ * allocate uncached memory
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#include <pool.h>
+
+typedef struct Private Private;
+struct Private {
+ Lock;
+ char msg[256];
+ char* cur;
+};
+
+static Private ucprivate;
+
+static void
+ucpoolpanic(Pool* p, char* fmt, ...)
+{
+ va_list v;
+ Private *pv;
+ char msg[sizeof pv->msg];
+
+ pv = p->private;
+ va_start(v, fmt);
+ vseprint(pv->cur, &pv->msg[sizeof pv->msg], fmt, v);
+ va_end(v);
+ memmove(msg, pv->msg, sizeof msg);
+ iunlock(pv);
+ panic("%s", msg);
+}
+
+static void
+ucpoolprint(Pool* p, char* fmt, ...)
+{
+ va_list v;
+ Private *pv;
+
+ pv = p->private;
+ va_start(v, fmt);
+ pv->cur = vseprint(pv->cur, &pv->msg[sizeof pv->msg], fmt, v);
+ va_end(v);
+}
+
+static void
+ucpoolunlock(Pool* p)
+{
+ Private *pv;
+ char msg[sizeof pv->msg];
+
+ pv = p->private;
+ if(pv->cur == pv->msg){
+ iunlock(pv);
+ return;
+ }
+
+ memmove(msg, pv->msg, sizeof msg);
+ pv->cur = pv->msg;
+ iunlock(pv);
+
+ iprint("%.*s", sizeof pv->msg, msg);
+}
+
+static void
+ucpoollock(Pool* p)
+{
+ Private *pv;
+
+ pv = p->private;
+ ilock(pv);
+ pv->pc = getcallerpc(&p);
+ pv->cur = pv->msg;
+}
+
+static void*
+ucarena(usize size)
+{
+ void *uv, *v;
+
+ assert(size == 1*MiB);
+
+ mainmem->maxsize += 1*MiB;
+ if((v = mallocalign(1*MiB, 1*MiB, 0, 0)) == nil ||
+ (uv = mmuuncache(v, 1*MiB)) == nil){
+ free(v);
+ mainmem->maxsize -= 1*MiB;
+ return nil;
+ }
+ return uv;
+}
+
+static Pool ucpool = {
+ .name = "Uncached",
+ .maxsize = 4*MiB,
+ .minarena = 1*MiB-32,
+ .quantum = 32,
+ .alloc = ucarena,
+ .merge = nil,
+ .flags = /*POOL_TOLERANCE|POOL_ANTAGONISM|POOL_PARANOIA|*/0,
+
+ .lock = ucpoollock,
+ .unlock = ucpoolunlock,
+ .print = ucpoolprint,
+ .panic = ucpoolpanic,
+
+ .private = &ucprivate,
+};
+
+void
+ucfree(void* v)
+{
+ if(v == nil)
+ return;
+ poolfree(&ucpool, v);
+}
+
+void*
+ucalloc(usize size)
+{
+ assert(size < ucpool.minarena-128);
+
+ return poolallocalign(&ucpool, size, 32, 0, 0);
+}
+
+void*
+ucallocalign(usize size, int align, int span)
+{
+ assert(size < ucpool.minarena-128);
+
+ return poolallocalign(&ucpool, size, align, 0, span);
+}
diff --git a/sys/src/9/kw/uncached.h b/sys/src/9/kw/uncached.h
new file mode 100755
index 000000000..9fffd31fc
--- /dev/null
+++ b/sys/src/9/kw/uncached.h
@@ -0,0 +1,36 @@
+/*
+ * running the l2 cache as write-back and using cached memory for
+ * usb data structures yields spurious errors such as
+ *
+ * qhintr: td 0x60ee3d80 csw 0x8824a error 0x48 transaction error
+ *
+ * from usbehci. so, at least for now, we will use uncached memory until
+ * we sort out the write-back problems.
+ */
+#define free ucfree
+#define malloc myucalloc
+#define mallocz ucallocz
+#define smalloc myucalloc
+#define xspanalloc ucallocalign
+
+#define allocb ucallocb
+#define iallocb uciallocb
+#define freeb ucfreeb
+
+static void *
+ucallocz(uint n, int)
+{
+ char *p = ucalloc(n);
+
+ if (p)
+ memset(p, 0, n);
+ else
+ panic("ucalloc: out of memory");
+ return p;
+}
+
+static void *
+myucalloc(uint n)
+{
+ return ucallocz(n, 1);
+}
diff --git a/sys/src/9/kw/usbehci.h b/sys/src/9/kw/usbehci.h
new file mode 100755
index 000000000..cd1015a8c
--- /dev/null
+++ b/sys/src/9/kw/usbehci.h
@@ -0,0 +1,242 @@
+/* override default macros from ../port/usb.h */
+#undef dprint
+#undef ddprint
+#undef deprint
+#undef ddeprint
+#define dprint if(ehcidebug)print
+#define ddprint if(ehcidebug>1)print
+#define deprint if(ehcidebug || ep->debug)print
+#define ddeprint if(ehcidebug>1 || ep->debug>1)print
+
+typedef struct Ctlr Ctlr;
+typedef struct Ecapio Ecapio;
+typedef struct Eopio Eopio;
+typedef struct Edbgio Edbgio;
+typedef struct Isoio Isoio;
+typedef struct Poll Poll;
+typedef struct Qh Qh;
+typedef struct Qtree Qtree;
+
+#pragma incomplete Ctlr;
+#pragma incomplete Ecapio;
+#pragma incomplete Eopio;
+#pragma incomplete Edbgio;
+#pragma incomplete Isoio;
+#pragma incomplete Poll;
+#pragma incomplete Qh;
+#pragma incomplete Qtree;
+
+/*
+ * EHCI interface registers and bits
+ */
+enum
+{
+ Cnports = 0xF, /* nport bits in Ecapio parms. */
+ Cdbgportshift = 20, /* debug port in Ecapio parms. */
+ Cdbgportmask = 0xF,
+ C64 = 1, /* 64-bits, in Ecapio capparms. */
+ Ceecpshift = 8, /* extended capabilities ptr. in */
+ Ceecpmask = 8, /* the Ecapio capparms reg. */
+ Clegacy = 1, /* legacy support cap. id */
+ CLbiossem = 2, /* legacy cap. bios sem. */
+ CLossem = 3, /* legacy cap. os sem */
+
+ /* typed links */
+ Lterm = 1,
+ Litd = 0<<1,
+ Lqh = 1<<1,
+ Lsitd = 2<<1,
+ Lfstn = 3<<1, /* we don't use these */
+
+ /* Cmd reg. */
+ Cstop = 0x00000, /* stop running */
+ Crun = 0x00001, /* start operation */
+ Chcreset = 0x00002, /* host controller reset */
+ Cflsmask = 0x0000C, /* frame list size bits */
+ Cfls1024 = 0x00000, /* frame list size 1024 */
+ Cfls512 = 0x00004, /* frame list size 512 frames */
+ Cfls256 = 0x00008, /* frame list size 256 frames */
+ Cpse = 0x00010, /* periodic sched. enable */
+ Case = 0x00020, /* async sched. enable */
+ Ciasync = 0x00040, /* interrupt on async advance doorbell */
+ Citc1 = 0x10000, /* interrupt threshold ctl. 1 µframe */
+ Citc4 = 0x40000, /* same. 2 µframes */
+ /* ... */
+ Citc8 = 0x80000, /* same. 8 µframes (can go up to 64) */
+
+ /* Sts reg. */
+ Sasyncss = 0x08000, /* aync schedule status */
+ Speriodss = 0x04000, /* periodic schedule status */
+ Srecl = 0x02000, /* reclamnation (empty async sched.) */
+ Shalted = 0x01000, /* h.c. is halted */
+ Sasync = 0x00020, /* interrupt on async advance */
+ Sherr = 0x00010, /* host system error */
+ Sfrroll = 0x00008, /* frame list roll over */
+ Sportchg = 0x00004, /* port change detect */
+ Serrintr = 0x00002, /* error interrupt */
+ Sintr = 0x00001, /* interrupt */
+ Sintrs = 0x0003F, /* interrupts status */
+
+ /* Intr reg. */
+ Iusb = 0x01, /* intr. on usb */
+ Ierr = 0x02, /* intr. on usb error */
+ Iportchg = 0x04, /* intr. on port change */
+ Ifrroll = 0x08, /* intr. on frlist roll over */
+ Ihcerr = 0x10, /* intr. on host error */
+ Iasync = 0x20, /* intr. on async advance enable */
+ Iall = 0x3F, /* all interrupts */
+
+ /* Config reg. */
+ Callmine = 1, /* route all ports to us */
+
+ /* Portsc reg. */
+ Pspresent = 0x00000001, /* device present */
+ Psstatuschg = 0x00000002, /* Pspresent changed */
+ Psenable = 0x00000004, /* device enabled */
+ Pschange = 0x00000008, /* Psenable changed */
+ Psresume = 0x00000040, /* resume detected */
+ Pssuspend = 0x00000080, /* port suspended */
+ Psreset = 0x00000100, /* port reset */
+ Pspower = 0x00001000, /* port power on */
+ Psowner = 0x00002000, /* port owned by companion */
+ Pslinemask = 0x00000C00, /* line status bits */
+ Pslow = 0x00000400, /* low speed device */
+
+ /* Debug port csw reg. */
+ Cowner = 0x40000000, /* port owned by ehci */
+ Cenable = 0x10000000, /* debug port enabled */
+ Cdone = 0x00010000, /* request is done */
+ Cbusy = 0x00000400, /* port in use by a driver */
+ Cerrmask= 0x00000380, /* error code bits */
+ Chwerr = 0x00000100, /* hardware error */
+ Cterr = 0x00000080, /* transaction error */
+ Cfailed = 0x00000040, /* transaction did fail */
+ Cgo = 0x00000020, /* execute the transaction */
+ Cwrite = 0x00000010, /* request is a write */
+ Clen = 0x0000000F, /* data len */
+
+ /* Debug port pid reg. */
+ Prpidshift = 16, /* received pid */
+ Prpidmask = 0xFF,
+ Pspidshift = 8, /* sent pid */
+ Pspidmask = 0xFF,
+ Ptokshift = 0, /* token pid */
+ Ptokmask = 0xFF,
+
+ Ptoggle = 0x00008800, /* to update toggles */
+ Ptogglemask = 0x0000FF00,
+
+ /* Debug port addr reg. */
+ Adevshift = 8, /* device address */
+ Adevmask = 0x7F,
+ Aepshift = 0, /* endpoint number */
+ Aepmask = 0xF,
+};
+
+/*
+ * Capability registers (hw)
+ */
+struct Ecapio
+{
+ ulong cap; /* 00 controller capability register */
+ ulong parms; /* 04 structural parameters register */
+ ulong capparms; /* 08 capability parameters */
+ ulong portroute; /* 0c not on the CS5536 */
+};
+
+/*
+ * Debug port registers (hw)
+ */
+struct Edbgio
+{
+ ulong csw; /* control and status */
+ ulong pid; /* USB pid */
+ uchar data[8]; /* data buffer */
+ ulong addr; /* device and endpoint addresses */
+};
+
+struct Poll
+{
+ Lock;
+ Rendez;
+ int must;
+ int does;
+};
+
+struct Ctlr
+{
+ Rendez; /* for waiting to async advance doorbell */
+ Lock; /* for ilock. qh lists and basic ctlr I/O */
+ QLock portlck; /* for port resets/enable... (and doorbell) */
+ int active; /* in use or not */
+ Ecapio* capio; /* Capability i/o regs */
+ Eopio* opio; /* Operational i/o regs */
+
+ int nframes; /* 1024, 512, or 256 frames in the list */
+ ulong* frames; /* periodic frame list (hw) */
+ Qh* qhs; /* async Qh circular list for bulk/ctl */
+ Qtree* tree; /* tree of Qhs for the periodic list */
+ int ntree; /* number of dummy qhs in tree */
+ Qh* intrqhs; /* list of (not dummy) qhs in tree */
+ Isoio* iso; /* list of active Iso I/O */
+ ulong load;
+ ulong isoload;
+ int nintr; /* number of interrupts attended */
+ int ntdintr; /* number of intrs. with something to do */
+ int nqhintr; /* number of async td intrs. */
+ int nisointr; /* number of periodic td intrs. */
+ int nreqs;
+ Poll poll;
+};
+
+/*
+ * Kirkwood-specific stuff
+ */
+
+/*
+ * Operational registers (hw)
+ */
+struct Eopio
+{
+ ulong cmd; /* 00 command */
+ ulong sts; /* 04 status */
+ ulong intr; /* 08 interrupt enable */
+ ulong frno; /* 0c frame index */
+ ulong seg; /* 10 bits 63:32 of EHCI datastructs (unused) */
+ ulong frbase; /* 14 frame list base addr, 4096-byte boundary */
+ ulong link; /* 18 link for async list */
+ uchar d2c[0x40-0x1c]; /* 1c dummy */
+ ulong config; /* 40 1: all ports default-routed to this HC */
+ ulong portsc[1]; /* 44 Port status and control, one per port */
+
+ /*
+ * these are present on the Kirkwood USB controller.
+ * are they standard now? Marvell doesn't document them publically.
+ */
+ uchar _pad0[0x64-0x48];
+ ulong otgsc;
+ ulong usbmode;
+ ulong epsetupsts;
+ ulong epprime;
+ ulong epflush;
+ ulong epsts;
+ ulong epcompl;
+ ulong epctl[6];
+
+ /* freescale registers */
+ uchar _pad1[0x2c0-0x98];
+ ulong snoop1;
+ ulong snoop2;
+ ulong agecntthresh;
+ ulong prictl; /* priority control */
+ ulong sictl; /* system interface control */
+
+ uchar _pad2[0x3c0-0x2d4];
+ ulong ctl;
+};
+
+extern int ehcidebug;
+
+void ehcilinkage(Hci *hp);
+void ehcimeminit(Ctlr *ctlr);
+void ehcirun(Ctlr *ctlr, int on);
diff --git a/sys/src/9/kw/usbehcikw.c b/sys/src/9/kw/usbehcikw.c
new file mode 100755
index 000000000..ca5b9ceb8
--- /dev/null
+++ b/sys/src/9/kw/usbehcikw.c
@@ -0,0 +1,350 @@
+/*
+ * Kirkwood-specific code for
+ * USB Enhanced Host Controller Interface (EHCI) driver
+ * High speed USB 2.0.
+ */
+
+#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/usb.h"
+#include "usbehci.h"
+//#include "uncached.h"
+
+#define WINTARG(ctl) (((ctl) >> 4) & 017)
+#define WINATTR(ctl) (((ctl) >> 8) & 0377)
+#define WIN64KSIZE(ctl) (((ctl) >> 16) + 1)
+
+#define SIZETO64KSIZE(size) ((size) / (64*1024) - 1)
+
+enum {
+ Debug = 0,
+};
+
+typedef struct Kwusb Kwusb;
+typedef struct Kwusbtt Kwusbtt;
+typedef struct Usbwin Usbwin;
+
+/* kirkwood usb transaction translator registers? (undocumented) */
+struct Kwusbtt { /* at soc.ehci */
+ ulong id;
+ ulong hwgeneral;
+ ulong hwhost;
+ ulong hwdevice;
+ ulong hwtxbuf;
+ ulong hwrxbuf;
+ ulong hwtttxbuf;
+ ulong hwttrxbuf;
+};
+
+/* kirkwood usb bridge & phy registers */
+struct Kwusb { /* at offset 0x300 from soc.ehci */
+ ulong bcs; /* bridge ctl & sts */
+ uchar _pad0[0x310-0x304];
+
+ ulong bic; /* bridge intr. cause */
+ ulong bim; /* bridge intr. mask */
+ ulong _pad1;
+ ulong bea; /* bridge error addr. */
+ struct Usbwin {
+ ulong ctl; /* see Winenable in io.h */
+ ulong base;
+ ulong _pad2[2];
+ } win[4];
+ ulong phycfg; /* phy config. */
+ uchar _pad3[0x400-0x364];
+
+ ulong pwrctl; /* power control */
+ uchar _pad4[0x410-0x404];
+ ulong phypll; /* phy pll control */
+ uchar _pad5[0x420-0x414];
+ ulong phytxctl; /* phy transmit control */
+ uchar _pad6[0x430-0x424];
+ ulong phyrxctl; /* phy receive control */
+ uchar _pad7[0x440-0x434];
+ ulong phyivref; /* phy ivref control */
+};
+
+static Ctlr* ctlrs[Nhcis];
+
+static void
+addrmapdump(void)
+{
+ int i;
+ ulong ctl, targ, attr, size64k;
+ Kwusb *map;
+ Usbwin *win;
+
+ if (!Debug)
+ return;
+ map = (Kwusb *)(soc.ehci + 0x300);
+ for (i = 0; i < nelem(map->win); i++) {
+ win = &map->win[i];
+ ctl = win->ctl;
+ if (ctl & Winenable) {
+ targ = WINTARG(ctl);
+ attr = WINATTR(ctl);
+ size64k = WIN64KSIZE(ctl);
+ print("usbehci: address map window %d: "
+ "targ %ld attr %#lux size %,ld addr %#lux\n",
+ i, targ, attr, size64k * 64*1024, win->base);
+ }
+ }
+}
+
+/* assumes ctlr is ilocked */
+static void
+ctlrreset(Ctlr *ctlr)
+{
+ int i;
+ Eopio *opio;
+
+ opio = ctlr->opio;
+ opio->cmd |= Chcreset;
+ coherence();
+ /* wait for it to come out of reset */
+ for(i = 0; i < 100 && opio->cmd & Chcreset; i++)
+ delay(1);
+ if(i >= 100)
+ print("ehci %#p controller reset timed out\n", ctlr->capio);
+ /*
+ * Marvell errata FE-USB-340 workaround: 1 << 4 magic:
+ * disable streaming. Magic 3 (usb host mode) from the linux driver
+ * makes it work. Ick.
+ */
+ opio->usbmode |= 1 << 4 | 3;
+ coherence();
+}
+
+/*
+ * configure window `win' as 256MB dram with attribute `attr' and
+ * base address
+ */
+static void
+setaddrwin(Kwusb *kw, int win, int attr, ulong base)
+{
+ kw->win[win].ctl = Winenable | Targdram << 4 | attr << 8 |
+ SIZETO64KSIZE(256*MB) << 16;
+ kw->win[win].base = base;
+}
+
+static void
+ehcireset(Ctlr *ctlr)
+{
+ int i, amp, txvdd;
+ ulong v;
+ Eopio *opio;
+ Kwusb *kw;
+
+ ilock(ctlr);
+ dprint("ehci %#p reset\n", ctlr->capio);
+ opio = ctlr->opio;
+
+ kw = (Kwusb *)(soc.ehci + 0x300);
+ kw->bic = 0;
+ kw->bim = (1<<4) - 1; /* enable all defined intrs */
+ ctlrreset(ctlr);
+
+ /*
+ * clear high 32 bits of address signals if it's 64 bits capable.
+ * This is probably not needed but it does not hurt and others do it.
+ */
+ if((ctlr->capio->capparms & C64) != 0){
+ dprint("ehci: 64 bits\n");
+ opio->seg = 0;
+ }
+
+ /* requesting more interrupts per µframe may miss interrupts */
+ opio->cmd |= Citc8; /* 1 intr. per ms */
+ switch(opio->cmd & Cflsmask){
+ case Cfls1024:
+ ctlr->nframes = 1024;
+ break;
+ case Cfls512:
+ ctlr->nframes = 512;
+ break;
+ case Cfls256:
+ ctlr->nframes = 256;
+ break;
+ default:
+ panic("ehci: unknown fls %ld", opio->cmd & Cflsmask);
+ }
+ dprint("ehci: %d frames\n", ctlr->nframes);
+
+ /*
+ * set up the USB address map (bridge address decoding)
+ */
+ for (i = 0; i < nelem(kw->win); i++)
+ kw->win[i].ctl = kw->win[i].base = 0;
+ coherence();
+
+ setaddrwin(kw, 0, Attrcs0, 0);
+ setaddrwin(kw, 1, Attrcs1, 256*MB);
+ coherence();
+
+ if (Debug)
+ if (kw->bcs & (1 << 4))
+ print("usbehci: not swapping bytes\n");
+ else
+ print("usbehci: swapping bytes\n");
+ addrmapdump(); /* verify sanity */
+
+ kw->pwrctl |= 1 << 0 | 1 << 1; /* Pu | PuPll */
+ coherence();
+
+ /*
+ * Marvell guideline GL-USB-160.
+ */
+ kw->phypll |= 1 << 21; /* VCOCAL_START: PLL calibration */
+ coherence();
+ microdelay(100);
+ kw->phypll &= ~(1 << 21);
+
+ v = kw->phytxctl & ~(017 << 27 | 7); /* REG_EXT_FS_RCALL & AMP_2_0 */
+ switch (m->socrev) {
+ default:
+ print("usbehci: bad 6281 soc rev %d\n", m->socrev);
+ /* fall through */
+ case Socreva0:
+ amp = 4;
+ txvdd = 1;
+ break;
+ case Socreva1:
+ amp = 3;
+ txvdd = 3;
+ break;
+ }
+ /* REG_EXT_FS_RCALL_EN | REG_RCAL_START | AMP_2_0 */
+ kw->phytxctl = v | 1 << 26 | 1 << 12 | amp;
+ coherence();
+ microdelay(100);
+ kw->phytxctl &= ~(1 << 12);
+
+ v = kw->phyrxctl & ~(3 << 2 | 017 << 4); /* LPF_COEF_1_0 & SQ_THRESH_3_0 */
+ kw->phyrxctl = v | 1 << 2 | 8 << 4;
+
+ v = kw->phyivref & ~(3 << 8); /* TXVDD12 */
+ kw->phyivref = v | txvdd << 8;
+ coherence();
+
+ ehcirun(ctlr, 0);
+ ctlrreset(ctlr);
+
+ iunlock(ctlr);
+}
+
+static void
+setdebug(Hci*, int d)
+{
+ ehcidebug = d;
+}
+
+static void
+shutdown(Hci *hp)
+{
+ Ctlr *ctlr;
+ Eopio *opio;
+
+ ctlr = hp->aux;
+ ilock(ctlr);
+ ctlrreset(ctlr);
+
+ delay(100);
+ ehcirun(ctlr, 0);
+
+ opio = ctlr->opio;
+ opio->frbase = 0;
+ coherence();
+ iunlock(ctlr);
+}
+
+static void
+findehcis(void) /* actually just use fixed addresses on sheeva */
+{
+ int i;
+ Ctlr *ctlr;
+ static int already = 0;
+
+ if(already)
+ return;
+ already = 1;
+
+ ctlr = smalloc(sizeof(Ctlr));
+ /* the sheeva's usb 2.0 otg uses a superset of the ehci registers */
+ ctlr->capio = (Ecapio *)(soc.ehci + 0x100);
+ ctlr->opio = (Eopio *) (soc.ehci + 0x140);
+ dprint("usbehci: port %#p\n", ctlr->capio);
+
+ for(i = 0; i < Nhcis; i++)
+ if(ctlrs[i] == nil){
+ ctlrs[i] = ctlr;
+ break;
+ }
+ if(i == Nhcis)
+ print("ehci: bug: more than %d controllers\n", Nhcis);
+}
+
+static int
+reset(Hci *hp)
+{
+ static Lock resetlck;
+ int i;
+ Ctlr *ctlr;
+ Ecapio *capio;
+
+ ilock(&resetlck);
+ findehcis();
+
+ /*
+ * Any adapter matches if no hp->port is supplied,
+ * otherwise the ports must match.
+ */
+ ctlr = nil;
+ for(i = 0; i < Nhcis && ctlrs[i] != nil; i++){
+ ctlr = ctlrs[i];
+ if(ctlr->active == 0)
+ if(hp->port == 0 || hp->port == (uintptr)ctlr->capio){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ iunlock(&resetlck);
+ if(ctlrs[i] == nil || i == Nhcis)
+ return -1;
+
+ hp->aux = ctlr;
+ hp->port = (uintptr)ctlr->capio;
+ hp->irq = IRQ0usb0;
+ hp->tbdf = 0;
+
+ capio = ctlr->capio;
+ hp->nports = capio->parms & Cnports;
+
+ ddprint("echi: %s, ncc %lud npcc %lud\n",
+ capio->parms & 0x10000 ? "leds" : "no leds",
+ (capio->parms >> 12) & 0xf, (capio->parms >> 8) & 0xf);
+ ddprint("ehci: routing %s, %sport power ctl, %d ports\n",
+ capio->parms & 0x40 ? "explicit" : "automatic",
+ capio->parms & 0x10 ? "" : "no ", hp->nports);
+
+ ehcireset(ctlr);
+ ehcimeminit(ctlr);
+
+ /*
+ * Linkage to the generic HCI driver.
+ */
+ ehcilinkage(hp);
+ hp->shutdown = shutdown;
+ hp->debug = setdebug;
+ return 0;
+}
+
+void
+usbehcilink(void)
+{
+ addhcitype("ehci", reset);
+}
diff --git a/sys/src/9/mkfile b/sys/src/9/mkfile
new file mode 100755
index 000000000..75f58179a
--- /dev/null
+++ b/sys/src/9/mkfile
@@ -0,0 +1,24 @@
+ARCH=\
+ alphapc\
+ bitsy\
+ mtx\
+ pc\
+ ppc\
+
+all:V:
+ for(i in $ARCH)@{
+ cd $i
+ mk
+ }
+
+installall install:V:
+ for(i in $ARCH) @{
+ cd $i
+ mk install
+ }
+
+clean:V:
+ for(i in $ARCH) @{
+ cd $i
+ mk clean
+ }
diff --git a/sys/src/9/mtx/clock.c b/sys/src/9/mtx/clock.c
new file mode 100755
index 000000000..dacef88ed
--- /dev/null
+++ b/sys/src/9/mtx/clock.c
@@ -0,0 +1,112 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+static ulong clkreload;
+
+void
+delayloopinit(void)
+{
+ ulong v;
+ uvlong x;
+
+ m->loopconst = 5000;
+ v = getdec();
+ delay(1000);
+ v -= getdec();
+
+ x = m->loopconst;
+ x *= m->dechz;
+ x /= v;
+ m->loopconst = x;
+}
+
+void
+clockinit(void)
+{
+ /* XXX this should not be hard coded! */
+ m->cpuhz = 300000000;
+ m->bushz = 66666666;
+
+ m->dechz = m->bushz/4; /* true for all 604e */
+ m->tbhz = m->dechz; /* conjecture; manual doesn't say */
+
+ delayloopinit();
+
+ clkreload = m->dechz/HZ-1;
+ putdec(clkreload);
+}
+
+void
+clockintr(Ureg *ureg)
+{
+ long v;
+
+ v = -getdec();
+ if(v > clkreload/2){
+ if(v > clkreload)
+ m->ticks += v/clkreload;
+ v = 0;
+ }
+ putdec(clkreload-v);
+
+ timerintr(ureg, 0);
+}
+
+void
+timerset(Tval)
+{
+}
+
+void
+delay(int l)
+{
+ ulong i, j;
+
+ j = m->loopconst;
+ while(l-- > 0)
+ for(i=0; i < j; i++)
+ ;
+}
+
+void
+microdelay(int l)
+{
+ ulong i;
+
+ l *= m->loopconst;
+ l += 500;
+ l /= 1000;
+ if(l <= 0)
+ l = 1;
+ for(i = 0; i < l; i++)
+ ;
+}
+
+uvlong
+fastticks(uvlong *hz)
+{
+ if(hz)
+ *hz = HZ;
+ return m->ticks;
+}
+
+ulong
+µs(void)
+{
+ return fastticks2us(m->ticks);
+}
+
+/*
+ * performance measurement ticks. must be low overhead.
+ * doesn't have to count over a second.
+ */
+ulong
+perfticks(void)
+{
+ return m->ticks;
+}
diff --git a/sys/src/9/mtx/cycintr.c b/sys/src/9/mtx/cycintr.c
new file mode 100755
index 000000000..d56edba80
--- /dev/null
+++ b/sys/src/9/mtx/cycintr.c
@@ -0,0 +1,27 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+int
+havetimer(void)
+{
+ return 0;
+}
+
+void
+timeradd(Timer *)
+{
+}
+
+void
+timerdel(Timer *)
+{
+}
+
+void
+clockintrsched(void)
+{
+}
diff --git a/sys/src/9/mtx/dat.h b/sys/src/9/mtx/dat.h
new file mode 100755
index 000000000..294bca8c5
--- /dev/null
+++ b/sys/src/9/mtx/dat.h
@@ -0,0 +1,213 @@
+typedef struct Conf Conf;
+typedef struct Confmem Confmem;
+typedef struct FPsave FPsave;
+typedef struct ISAConf ISAConf;
+typedef struct Label Label;
+typedef struct Lock Lock;
+typedef struct Mach Mach;
+typedef struct Notsave Notsave;
+typedef struct Page Page;
+typedef struct PCArch PCArch;
+typedef struct Pcidev Pcidev;
+typedef struct PMMU PMMU;
+typedef struct Proc Proc;
+typedef struct Sys Sys;
+typedef struct Ureg Ureg;
+typedef struct Vctl Vctl;
+typedef long Tval;
+
+#pragma incomplete Ureg
+
+#define MAXSYSARG 5 /* for mount(fd, mpt, flag, arg, srv) */
+
+/*
+ * parameters for sysproc.c
+ */
+#define AOUT_MAGIC Q_MAGIC
+
+/*
+ * machine dependent definitions used by ../port/dat.h
+ */
+
+struct Lock
+{
+ ulong key;
+ ulong sr;
+ ulong pc;
+ Proc *p;
+ Mach *m;
+ ushort isilock;
+};
+
+struct Label
+{
+ ulong sp;
+ ulong pc;
+};
+
+/*
+ * Proc.fpstate
+ */
+enum
+{
+ FPinit,
+ FPactive,
+ FPinactive,
+};
+
+/*
+ * This structure must agree with fpsave and fprestore asm routines
+ */
+struct FPsave
+{
+ double fpreg[32];
+ union {
+ double fpscrd;
+ struct {
+ ulong pad;
+ ulong fpscr;
+ };
+ };
+};
+
+struct Confmem
+{
+ ulong base;
+ ulong npage;
+ ulong kbase;
+ ulong klimit;
+};
+
+struct Conf
+{
+ ulong nmach; /* processors */
+ ulong nproc; /* processes */
+ Confmem mem[1];
+ 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 copymode; /* 0 is copy on write, 1 is copy on reference */
+ int monitor; /* has display? */
+ ulong ialloc; /* bytes available for interrupt time allocation */
+ ulong pipeqsize; /* size in bytes of pipe queues */
+};
+
+/*
+ * mmu goo in the Proc structure
+ */
+#define NCOLOR 1
+struct PMMU
+{
+ int mmupid;
+};
+
+/*
+ * things saved in the Proc structure during a notify
+ */
+struct Notsave
+{
+ ulong UNUSED;
+};
+
+#include "../port/portdat.h"
+
+/*
+ * machine dependent definitions not used by ../port/dat.h
+ */
+/*
+ * Fake kmap
+ */
+typedef void KMap;
+#define VA(k) ((ulong)(k))
+#define kmap(p) (KMap*)((p)->pa|KZERO)
+#define kunmap(k)
+
+struct Mach
+{
+ /* OFFSETS OF THE FOLLOWING KNOWN BY l.s */
+ int machno; /* physical id of processor */
+ ulong splpc; /* pc that called splhi() */
+ Proc *proc; /* current process on this processor */
+
+ /* ordering from here on irrelevant */
+
+ ulong ticks; /* of the clock since boot time */
+ Label sched; /* scheduler wakeup */
+ Lock alarmlock; /* access to alarm list */
+ void *alarm; /* alarms bound to this clock */
+ int inclockintr;
+ int cputype;
+ ulong loopconst;
+
+ Proc* readied; /* for runproc */
+ ulong schedticks; /* next forced context switch */
+
+ vlong cpuhz;
+ ulong bushz;
+ ulong dechz;
+ ulong tbhz;
+ uvlong cyclefreq; /* Frequency of user readable cycle counter */
+
+ ulong pcclast;
+ uvlong fastclock;
+ Perf perf; /* performance counters */
+
+ int tlbfault; /* only used by devproc; no access to tlb */
+ int tlbpurge; /* ... */
+ int pfault;
+ int cs;
+ int syscall;
+ int load;
+ int intr;
+ int flushmmu; /* make current proc flush it's mmu state */
+ int ilockdepth;
+
+ ulong ptabbase; /* start of page table in kernel virtual space */
+ int slotgen; /* next pte (byte offset) when pteg is full */
+ int mmupid; /* next mmu pid to use */
+ int sweepcolor;
+ int trigcolor;
+ Rendez sweepr;
+
+ ulong spuriousintr;
+ int lastintr;
+
+ /* MUST BE LAST */
+ int stack[1];
+};
+
+struct
+{
+ Lock;
+ short machs;
+ short exiting;
+ short ispanic;
+}active;
+
+/*
+ * a parsed plan9.ini line
+ */
+#define NISAOPT 8
+
+struct ISAConf {
+ char *type;
+ ulong port;
+ int irq;
+ ulong dma;
+ ulong mem;
+ ulong size;
+ ulong freq;
+
+ int nopt;
+ char *opt[NISAOPT];
+};
+
+#define MACHP(n) ((Mach *)((int)&mach0+n*BY2PG))
+extern Mach mach0;
+
+extern register Mach *m;
+extern register Proc *up;
+
+extern FPsave initfp;
diff --git a/sys/src/9/mtx/devarch.c b/sys/src/9/mtx/devarch.c
new file mode 100755
index 000000000..cd5eea88f
--- /dev/null
+++ b/sys/src/9/mtx/devarch.c
@@ -0,0 +1,401 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+typedef struct IOMap IOMap;
+struct IOMap
+{
+ IOMap *next;
+ char tag[13];
+ ulong start;
+ ulong end;
+};
+
+static struct
+{
+ Lock;
+ IOMap *m;
+ IOMap *free;
+ IOMap maps[32]; // some initial free maps
+
+ QLock ql; // lock for reading map
+} iomap;
+
+enum {
+ Qdir = 0,
+ Qioalloc = 1,
+ Qiob,
+ Qiow,
+ Qiol,
+ Qbase,
+
+ Qmax = 16,
+};
+
+typedef long Rdwrfn(Chan*, void*, long, vlong);
+
+static Rdwrfn *readfn[Qmax];
+static Rdwrfn *writefn[Qmax];
+
+static Dirtab archdir[] = {
+ ".", { Qdir, 0, QTDIR }, 0, 0555,
+ "ioalloc", { Qioalloc, 0 }, 0, 0444,
+ "iob", { Qiob, 0 }, 0, 0660,
+ "iow", { Qiow, 0 }, 0, 0660,
+ "iol", { Qiol, 0 }, 0, 0660,
+};
+Lock archwlock; /* the lock is only for changing archdir */
+int narchdir = Qbase;
+int (*_pcmspecial)(char *, ISAConf *);
+void (*_pcmspecialclose)(int);
+
+/*
+ * Add a file to the #P listing. Once added, you can't delete it.
+ * You can't add a file with the same name as one already there,
+ * and you get a pointer to the Dirtab entry so you can do things
+ * like change the Qid version. Changing the Qid path is disallowed.
+ */
+Dirtab*
+addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
+{
+ int i;
+ Dirtab d;
+ Dirtab *dp;
+
+ memset(&d, 0, sizeof d);
+ strcpy(d.name, name);
+ d.perm = perm;
+
+ lock(&archwlock);
+ if(narchdir >= Qmax){
+ unlock(&archwlock);
+ return nil;
+ }
+
+ for(i=0; i<narchdir; i++)
+ if(strcmp(archdir[i].name, name) == 0){
+ unlock(&archwlock);
+ return nil;
+ }
+
+ d.qid.path = narchdir;
+ archdir[narchdir] = d;
+ readfn[narchdir] = rdfn;
+ writefn[narchdir] = wrfn;
+ dp = &archdir[narchdir++];
+ unlock(&archwlock);
+
+ return dp;
+}
+
+void
+ioinit(void)
+{
+ int i;
+
+ for(i = 0; i < nelem(iomap.maps)-1; i++)
+ iomap.maps[i].next = &iomap.maps[i+1];
+ iomap.maps[i].next = nil;
+ iomap.free = iomap.maps;
+
+ // a dummy entry at 2^17
+ ioalloc(0x20000, 1, 0, "dummy");
+}
+
+//
+// alloc some io port space and remember who it was
+// alloced to. if port < 0, find a free region.
+//
+int
+ioalloc(int port, int size, int align, char *tag)
+{
+ IOMap *m, **l;
+ int i;
+
+ lock(&iomap);
+ if(port < 0){
+ // find a free port above 0x400 and below 0x1000
+ port = 0x400;
+ for(l = &iomap.m; *l; l = &(*l)->next){
+ m = *l;
+ i = m->start - port;
+ if(i > size)
+ break;
+ if(align > 0)
+ port = ((port+align-1)/align)*align;
+ else
+ port = m->end;
+ }
+ if(*l == nil){
+ unlock(&iomap);
+ return -1;
+ }
+ } else {
+ // see if the space clashes with previously allocated ports
+ for(l = &iomap.m; *l; l = &(*l)->next){
+ m = *l;
+ if(m->end <= port)
+ continue;
+ if(m->start >= port+size)
+ break;
+ unlock(&iomap);
+ return -1;
+ }
+ }
+ m = iomap.free;
+ if(m == nil){
+ print("ioalloc: out of maps");
+ unlock(&iomap);
+ return port;
+ }
+ iomap.free = m->next;
+ m->next = *l;
+ m->start = port;
+ m->end = port + size;
+ strncpy(m->tag, tag, sizeof(m->tag));
+ m->tag[sizeof(m->tag)-1] = 0;
+ *l = m;
+
+ archdir[0].qid.vers++;
+
+ unlock(&iomap);
+ return m->start;
+}
+
+void
+iofree(int port)
+{
+ IOMap *m, **l;
+
+ lock(&iomap);
+ for(l = &iomap.m; *l; l = &(*l)->next){
+ if((*l)->start == port){
+ m = *l;
+ *l = m->next;
+ m->next = iomap.free;
+ iomap.free = m;
+ break;
+ }
+ if((*l)->start > port)
+ break;
+ }
+ archdir[0].qid.vers++;
+ unlock(&iomap);
+}
+
+int
+iounused(int start, int end)
+{
+ IOMap *m;
+
+ for(m = iomap.m; m; m = m->next){
+ if(start >= m->start && start < m->end
+ || start <= m->start && end > m->start)
+ return 0;
+ }
+ return 1;
+}
+
+static void
+checkport(int start, int end)
+{
+ /* standard vga regs are OK */
+ if(start >= 0x2b0 && end <= 0x2df+1)
+ return;
+ if(start >= 0x3c0 && end <= 0x3da+1)
+ return;
+
+ if(iounused(start, end))
+ return;
+ error(Eperm);
+}
+
+static Chan*
+archattach(char* spec)
+{
+ return devattach('P', spec);
+}
+
+Walkqid*
+archwalk(Chan* c, Chan *nc, char** name, int nname)
+{
+ return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
+}
+
+static int
+archstat(Chan* c, uchar* dp, int n)
+{
+ return devstat(c, dp, n, archdir, narchdir, devgen);
+}
+
+static Chan*
+archopen(Chan* c, int omode)
+{
+ return devopen(c, omode, archdir, nelem(archdir), devgen);
+}
+
+static void
+archclose(Chan*)
+{
+}
+
+enum
+{
+ Linelen= 31,
+};
+
+static long
+archread(Chan *c, void *a, long n, vlong offset)
+{
+ char buf[Linelen+1], *p;
+ int port;
+ ushort *sp;
+ ulong *lp;
+ IOMap *m;
+ Rdwrfn *fn;
+
+ switch((ulong)c->qid.path){
+
+ case Qdir:
+ return devdirread(c, a, n, archdir, nelem(archdir), devgen);
+
+ case Qiob:
+ port = offset;
+ checkport(offset, offset+n);
+ for(p = a; port < offset+n; port++)
+ *p++ = inb(port);
+ return n;
+
+ case Qiow:
+ if((n & 0x01) || (offset & 0x01))
+ error(Ebadarg);
+ checkport(offset, offset+n+1);
+ n /= 2;
+ sp = a;
+ for(port = offset; port < offset+n; port += 2)
+ *sp++ = ins(port);
+ return n*2;
+
+ case Qiol:
+ if((n & 0x03) || (offset & 0x03))
+ error(Ebadarg);
+ checkport(offset, offset+n+3);
+ n /= 4;
+ lp = a;
+ for(port = offset; port < offset+n; port += 4)
+ *lp++ = inl(port);
+ return n*4;
+
+ case Qioalloc:
+ break;
+
+ default:
+ if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
+ return fn(c, a, n, offset);
+ error(Eperm);
+ break;
+ }
+
+ offset = offset/Linelen;
+ n = n/Linelen;
+ p = a;
+ lock(&iomap);
+ for(m = iomap.m; n > 0 && m != nil; m = m->next){
+ if(offset-- > 0)
+ continue;
+ if(strcmp(m->tag, "dummy") == 0)
+ break;
+ sprint(buf, "%8lux %8lux %-12.12s\n", m->start, m->end-1, m->tag);
+ memmove(p, buf, Linelen);
+ p += Linelen;
+ n--;
+ }
+ unlock(&iomap);
+
+ return p - (char*)a;
+}
+
+static long
+archwrite(Chan *c, void *a, long n, vlong offset)
+{
+ char *p;
+ int port;
+ ushort *sp;
+ ulong *lp;
+ Rdwrfn *fn;
+
+ switch((ulong)c->qid.path){
+
+ case Qiob:
+ p = a;
+ checkport(offset, offset+n);
+ for(port = offset; port < offset+n; port++)
+ outb(port, *p++);
+ return n;
+
+ case Qiow:
+ if((n & 01) || (offset & 01))
+ error(Ebadarg);
+ checkport(offset, offset+n+1);
+ n /= 2;
+ sp = a;
+ for(port = offset; port < offset+n; port += 2)
+ outs(port, *sp++);
+ return n*2;
+
+ case Qiol:
+ if((n & 0x03) || (offset & 0x03))
+ error(Ebadarg);
+ checkport(offset, offset+n+3);
+ n /= 4;
+ lp = a;
+ for(port = offset; port < offset+n; port += 4)
+ outl(port, *lp++);
+ return n*4;
+
+ default:
+ if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
+ return fn(c, a, n, offset);
+ error(Eperm);
+ break;
+ }
+ return 0;
+}
+
+Dev archdevtab = {
+ 'P',
+ "arch",
+
+ devreset,
+ devinit,
+ devshutdown,
+ archattach,
+ archwalk,
+ archstat,
+ archopen,
+ devcreate,
+ archclose,
+ archread,
+ devbread,
+ archwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+int
+pcmspecial(char *idstr, ISAConf *isa)
+{
+ return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1;
+}
+
+void
+pcmspecialclose(int a)
+{
+ if (_pcmspecialclose != nil)
+ _pcmspecialclose(a);
+}
diff --git a/sys/src/9/mtx/devether.c b/sys/src/9/mtx/devether.c
new file mode 100755
index 000000000..73c8bac4e
--- /dev/null
+++ b/sys/src/9/mtx/devether.c
@@ -0,0 +1,472 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+static Ether *etherxx[MaxEther];
+
+Chan*
+etherattach(char* spec)
+{
+ ulong ctlrno;
+ char *p;
+ Chan *chan;
+
+ ctlrno = 0;
+ if(spec && *spec){
+ ctlrno = strtoul(spec, &p, 0);
+ if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
+ error(Ebadarg);
+ }
+ if(etherxx[ctlrno] == 0)
+ error(Enodev);
+
+ chan = devattach('l', spec);
+ chan->dev = ctlrno;
+ if(etherxx[ctlrno]->attach)
+ etherxx[ctlrno]->attach(etherxx[ctlrno]);
+ return chan;
+}
+
+static Walkqid*
+etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
+{
+ return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
+}
+
+static int
+etherstat(Chan* chan, uchar* dp, int n)
+{
+ return netifstat(etherxx[chan->dev], chan, dp, n);
+}
+
+static Chan*
+etheropen(Chan* chan, int omode)
+{
+ return netifopen(etherxx[chan->dev], chan, omode);
+}
+
+static void
+ethercreate(Chan*, char*, int, ulong)
+{
+}
+
+static void
+etherclose(Chan* chan)
+{
+ netifclose(etherxx[chan->dev], chan);
+}
+
+static long
+etherread(Chan* chan, void* buf, long n, vlong off)
+{
+ Ether *ether;
+ ulong offset = off;
+
+ ether = etherxx[chan->dev];
+ if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
+ /*
+ * With some controllers it is necessary to reach
+ * into the chip to extract statistics.
+ */
+ if(NETTYPE(chan->qid.path) == Nifstatqid)
+ return ether->ifstat(ether, buf, n, offset);
+ else if(NETTYPE(chan->qid.path) == Nstatqid)
+ ether->ifstat(ether, buf, 0, offset);
+ }
+
+ return netifread(ether, chan, buf, n, offset);
+}
+
+static Block*
+etherbread(Chan* chan, long n, ulong offset)
+{
+ return netifbread(etherxx[chan->dev], chan, n, offset);
+}
+
+static int
+etherwstat(Chan* chan, uchar* dp, int n)
+{
+ return netifwstat(etherxx[chan->dev], chan, dp, n);
+}
+
+static void
+etherrtrace(Netfile* f, Etherpkt* pkt, int len)
+{
+ int i, n;
+ Block *bp;
+
+ if(qwindow(f->in) <= 0)
+ return;
+ if(len > 58)
+ n = 58;
+ else
+ n = len;
+ bp = iallocb(64);
+ if(bp == nil)
+ return;
+ memmove(bp->wp, pkt->d, n);
+ i = TK2MS(MACHP(0)->ticks);
+ bp->wp[58] = len>>8;
+ bp->wp[59] = len;
+ bp->wp[60] = i>>24;
+ bp->wp[61] = i>>16;
+ bp->wp[62] = i>>8;
+ bp->wp[63] = i;
+ bp->wp += 64;
+ qpass(f->in, bp);
+}
+
+Block*
+etheriq(Ether* ether, Block* bp, int fromwire)
+{
+ Etherpkt *pkt;
+ ushort type;
+ int len, multi, tome, fromme;
+ Netfile **ep, *f, **fp, *fx;
+ Block *xbp;
+
+ ether->inpackets++;
+
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ type = (pkt->type[0]<<8)|pkt->type[1];
+ fx = 0;
+ ep = &ether->f[Ntypes];
+
+ multi = pkt->d[0] & 1;
+ /* check for valid multicast addresses */
+ if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){
+ if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
+ if(fromwire){
+ freeb(bp);
+ bp = 0;
+ }
+ return bp;
+ }
+ }
+
+ /* is it for me? */
+ tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
+ fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
+
+ /*
+ * Multiplex the packet to all the connections which want it.
+ * If the packet is not to be used subsequently (fromwire != 0),
+ * attempt to simply pass it into one of the connections, thereby
+ * saving a copy of the data (usual case hopefully).
+ */
+ for(fp = ether->f; fp < ep; fp++){
+ if(f = *fp)
+ if(f->type == type || f->type < 0)
+ if(tome || multi || f->prom){
+ /* Don't want to hear bridged packets */
+ if(f->bridge && !fromwire && !fromme)
+ continue;
+ if(!f->headersonly){
+ if(fromwire && fx == 0)
+ fx = f;
+ else if(xbp = iallocb(len)){
+ memmove(xbp->wp, pkt, len);
+ xbp->wp += len;
+ qpass(f->in, xbp);
+ }
+ else
+ ether->soverflows++;
+ }
+ else
+ etherrtrace(f, pkt, len);
+ }
+ }
+
+ if(fx){
+ if(qpass(fx->in, bp) < 0)
+ ether->soverflows++;
+ return 0;
+ }
+ if(fromwire){
+ freeb(bp);
+ return 0;
+ }
+
+ return bp;
+}
+
+static int
+etheroq(Ether* ether, Block* bp)
+{
+ int len, loopback, s;
+ Etherpkt *pkt;
+
+ ether->outpackets++;
+
+ /*
+ * Check if the packet has to be placed back onto the input queue,
+ * i.e. if it's a loopback or broadcast packet or the interface is
+ * in promiscuous mode.
+ * If it's a loopback packet indicate to etheriq that the data isn't
+ * needed and return, etheriq will pass-on or free the block.
+ * To enable bridging to work, only packets that were originated
+ * by this interface are fed back.
+ */
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
+ if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
+ s = splhi();
+ etheriq(ether, bp, 0);
+ splx(s);
+ }
+
+ if(!loopback){
+ qbwrite(ether->oq, bp);
+ ether->transmit(ether);
+ } else
+ freeb(bp);
+
+ return len;
+}
+
+static long
+etherwrite(Chan* chan, void* buf, long n, vlong)
+{
+ Ether *ether;
+ Block *bp;
+ int nn;
+
+ ether = etherxx[chan->dev];
+ if(NETTYPE(chan->qid.path) != Ndataqid) {
+ nn = netifwrite(ether, chan, buf, n);
+ if(nn >= 0)
+ return nn;
+
+ if(n == sizeof("nonblocking")-1 && strncmp((char*)buf, "nonblocking", n) == 0){
+ qnoblock(ether->oq, 1);
+ return n;
+ }
+
+ if(ether->ctl!=nil)
+ return ether->ctl(ether,buf,n);
+
+ error(Ebadctl);
+ }
+
+ if(n > ether->maxmtu)
+ error(Etoobig);
+ if(n < ether->minmtu)
+ error(Etoosmall);
+
+ bp = allocb(n);
+ if(waserror()){
+ freeb(bp);
+ nexterror();
+ }
+ memmove(bp->rp, buf, n);
+ memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
+ poperror();
+ bp->wp += n;
+
+ return etheroq(ether, bp);
+}
+
+static long
+etherbwrite(Chan* chan, Block* bp, ulong)
+{
+ Ether *ether;
+ long n;
+
+ n = BLEN(bp);
+ if(NETTYPE(chan->qid.path) != Ndataqid){
+ if(waserror()) {
+ freeb(bp);
+ nexterror();
+ }
+ n = etherwrite(chan, bp->rp, n, 0);
+ poperror();
+ freeb(bp);
+ return n;
+ }
+ ether = etherxx[chan->dev];
+
+ if(n > ether->maxmtu){
+ freeb(bp);
+ error(Etoobig);
+ }
+ if(n < ether->minmtu){
+ freeb(bp);
+ error(Etoosmall);
+ }
+
+ return etheroq(ether, bp);
+}
+
+static struct {
+ char* type;
+ int (*reset)(Ether*);
+} cards[MaxEther+1];
+
+void
+addethercard(char* t, int (*r)(Ether*))
+{
+ static int ncard;
+
+ if(ncard == MaxEther)
+ panic("too many ether cards");
+ cards[ncard].type = t;
+ cards[ncard].reset = r;
+ ncard++;
+}
+
+int
+parseether(uchar *to, char *from)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ for(i = 0; i < 6; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+static void
+etherreset(void)
+{
+ Ether *ether;
+ int i, n, ctlrno;
+ char name[32], buf[128];
+
+ for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+ if(ether == 0)
+ ether = malloc(sizeof(Ether));
+ memset(ether, 0, sizeof(Ether));
+ ether->ctlrno = ctlrno;
+ ether->tbdf = BUSUNKNOWN;
+ ether->mbps = 10;
+ ether->minmtu = ETHERMINTU;
+ ether->maxmtu = ETHERMAXTU;
+ if(isaconfig("ether", ctlrno, ether) == 0)
+ continue;
+ for(n = 0; cards[n].type; n++){
+ if(cistrcmp(cards[n].type, ether->type))
+ continue;
+ for(i = 0; i < ether->nopt; i++){
+ if(strncmp(ether->opt[i], "ea=", 3))
+ continue;
+ if(parseether(ether->ea, &ether->opt[i][3]) == -1)
+ memset(ether->ea, 0, Eaddrlen);
+ }
+ if(cards[n].reset(ether))
+ break;
+
+ /*
+ * IRQ2 doesn't really exist, it's used to gang the interrupt
+ * controllers together. A device set to IRQ2 will appear on
+ * the second interrupt controller as IRQ9.
+ */
+ if(ether->irq == 2 && BUSTYPE(ether->tbdf) != BusPCI)
+ ether->irq = 9;
+ snprint(name, sizeof(name), "ether%d", ctlrno);
+
+ /*
+ * If ether->irq is <0, it is a hack to indicate no interrupt
+ * used by ethersink.
+ */
+ if(ether->irq >= 0)
+ intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);
+
+ i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
+ ctlrno, ether->type, ether->mbps, ether->port, ether->irq);
+ if(ether->mem)
+ i += sprint(buf+i, " addr 0x%luX", PADDR(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",
+ ether->ea[0], ether->ea[1], ether->ea[2],
+ ether->ea[3], ether->ea[4], ether->ea[5]);
+ sprint(buf+i, "\n");
+ print(buf);
+
+ if(ether->mbps >= 100){
+ netifinit(ether, name, Ntypes, 256*1024);
+ if(ether->oq == 0)
+ ether->oq = qopen(256*1024, Qmsg, 0, 0);
+ }
+ else{
+ netifinit(ether, name, Ntypes, 65*1024);
+ if(ether->oq == 0)
+ ether->oq = qopen(65*1024, Qmsg, 0, 0);
+ }
+ if(ether->oq == 0)
+ panic("etherreset %s", name);
+ ether->alen = Eaddrlen;
+ memmove(ether->addr, ether->ea, Eaddrlen);
+ memset(ether->bcast, 0xFF, Eaddrlen);
+
+ etherxx[ctlrno] = ether;
+ ether = 0;
+ break;
+ }
+ }
+ if(ether)
+ free(ether);
+}
+
+#define POLY 0xedb88320
+
+/* really slow 32 bit crc for ethers */
+ulong
+ethercrc(uchar *p, int len)
+{
+ int i, j;
+ ulong crc, b;
+
+ crc = 0xffffffff;
+ for(i = 0; i < len; i++){
+ b = *p++;
+ for(j = 0; j < 8; j++){
+ crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
+ b >>= 1;
+ }
+ }
+ return crc;
+}
+
+Dev etherdevtab = {
+ 'l',
+ "ether",
+
+ etherreset,
+ devinit,
+ devshutdown,
+ etherattach,
+ etherwalk,
+ etherstat,
+ etheropen,
+ ethercreate,
+ etherclose,
+ etherread,
+ etherbread,
+ etherwrite,
+ etherbwrite,
+ devremove,
+ etherwstat,
+};
diff --git a/sys/src/9/mtx/devrtc.c b/sys/src/9/mtx/devrtc.c
new file mode 100755
index 000000000..5b6a2399c
--- /dev/null
+++ b/sys/src/9/mtx/devrtc.c
@@ -0,0 +1,438 @@
+/*
+ * M48T59/559 Timekeeper
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "io.h"
+
+enum{
+ STB0 = 0x74,
+ STB1 = 0x75,
+ Data = 0x77,
+
+ NVOFF= 0,
+ NVLEN= 0x1ff0, /* length in bytes of NV RAM */
+
+ /*
+ * register offsets into time of day clock
+ */
+ NVflags= 0x1ff0,
+ NVwatchdog= 0x1ff7,
+ NVctl= 0x1ff8,
+ NVsec,
+ NVmin,
+ NVhour,
+ NVday, /* (1 = Sun) */
+ NVmday, /* (1-31) */
+ NVmon, /* (1-12) */
+ NVyear, /* (0-99) */
+
+ /* NVctl */
+ RTwrite = (1<<7),
+ RTread = (1<<6),
+ RTsign = (1<<5),
+ RTcal = 0x1f,
+
+ /* NVwatchdog */
+ WDsteer = (1<<7), /* 0 -> intr, 1 -> reset */
+ WDmult = (1<<2), /* 5 bits of multiplier */
+ WDres0 = (0<<0), /* 1/16 sec resolution */
+ WDres1 = (1<<0), /* 1/4 sec resolution */
+ WDres2 = (2<<0), /* 1 sec resolution */
+ WDres3 = (3<<0), /* 4 sec resolution */
+
+ Qdir = 0,
+ Qrtc,
+ Qnvram,
+};
+
+/*
+ * broken down time
+ */
+typedef struct
+{
+ int sec;
+ int min;
+ int hour;
+ int mday;
+ int mon;
+ int year;
+} Rtc;
+
+QLock rtclock; /* mutex on nvram operations */
+
+static Dirtab rtcdir[]={
+ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
+ "rtc", {Qrtc, 0}, 0, 0644,
+ "nvram", {Qnvram, 0}, 0, 0600,
+};
+
+static ulong rtc2sec(Rtc*);
+static void sec2rtc(ulong, Rtc*);
+static void setrtc(Rtc*);
+static void nvcksum(void);
+static void nvput(int, uchar);
+static uchar nvget(int);
+
+static Chan*
+rtcattach(char *spec)
+{
+ return devattach('r', spec);
+}
+
+static Walkqid*
+rtcwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, rtcdir, nelem(rtcdir), devgen);
+}
+
+static int
+rtcstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, rtcdir, nelem(rtcdir), devgen);
+}
+
+static Chan*
+rtcopen(Chan *c, int omode)
+{
+ omode = openmode(omode);
+ switch((ulong)c->qid.path){
+ case Qrtc:
+ if(strcmp(up->user, eve)!=0 && omode!=OREAD)
+ error(Eperm);
+ break;
+ case Qnvram:
+ if(strcmp(up->user, eve)!=0 || !cpuserver)
+ error(Eperm);
+ }
+ return devopen(c, omode, rtcdir, nelem(rtcdir), devgen);
+}
+
+static void
+rtcclose(Chan*)
+{
+}
+
+static long
+rtcread(Chan *c, void *buf, long n, vlong off)
+{
+ char *p;
+ ulong t;
+ int i;
+ ulong offset = off;
+
+ if(c->qid.type & QTDIR)
+ return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen);
+
+ switch((ulong)c->qid.path){
+ case Qrtc:
+ qlock(&rtclock);
+ t = rtctime();
+ qunlock(&rtclock);
+ n = readnum(offset, buf, n, t, 12);
+ return n;
+ case Qnvram:
+ offset += NVOFF;
+ if(offset > NVLEN)
+ return 0;
+ if(n > NVLEN - offset)
+ n = NVLEN - offset;
+ p = buf;
+ qlock(&rtclock);
+ for(i = 0; i < n; i++)
+ p[i] = nvget(i+offset);
+ qunlock(&rtclock);
+ return n;
+ }
+ error(Egreg);
+ return -1; /* never reached */
+}
+
+static long
+rtcwrite(Chan *c, void *buf, long n, vlong off)
+{
+ Rtc rtc;
+ ulong secs;
+ char *cp, *ep;
+ int i;
+ ulong offset = off;
+
+ switch((ulong)c->qid.path){
+ case Qrtc:
+ if(offset!=0)
+ error(Ebadarg);
+ /*
+ * read the time
+ */
+ cp = ep = buf;
+ ep += n;
+ while(cp < ep){
+ if(*cp>='0' && *cp<='9')
+ break;
+ cp++;
+ }
+ secs = strtoul(cp, 0, 0);
+ /*
+ * convert to bcd
+ */
+ sec2rtc(secs, &rtc);
+ /*
+ * write it
+ */
+ qlock(&rtclock);
+ setrtc(&rtc);
+ qunlock(&rtclock);
+ return n;
+ case Qnvram:
+ offset += NVOFF;
+ if(offset > NVLEN)
+ return 0;
+ if(n > NVLEN - offset)
+ n = NVLEN - offset;
+ qlock(&rtclock);
+ for(i = 0; i < n; i++)
+ nvput(i+offset, ((uchar*)buf)[i]);
+ nvcksum();
+ qunlock(&rtclock);
+ return n;
+ }
+ error(Egreg);
+ return -1; /* never reached */
+}
+
+long
+rtcbwrite(Chan *c, Block *bp, ulong offset)
+{
+ return devbwrite(c, bp, offset);
+}
+
+Dev rtcdevtab = {
+ 'r',
+ "rtc",
+
+ devreset,
+ devinit,
+ devshutdown,
+ rtcattach,
+ rtcwalk,
+ rtcstat,
+ rtcopen,
+ devcreate,
+ rtcclose,
+ rtcread,
+ devbread,
+ rtcwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+static void
+nvput(int offset, uchar val)
+{
+ outb(STB0, offset);
+ outb(STB1, offset>>8);
+ outb(Data, val);
+}
+
+static uchar
+nvget(int offset)
+{
+ outb(STB0, offset);
+ outb(STB1, offset>>8);
+ return inb(Data);
+}
+
+static void
+nvcksum(void)
+{
+}
+
+void
+watchreset(void)
+{
+ splhi();
+ nvput(NVwatchdog, WDsteer|(1*WDmult)|WDres0);
+ for(;;);
+}
+
+static int
+getbcd(int bcd)
+{
+ return (bcd&0x0f) + 10 * (bcd>>4);
+}
+
+static int
+putbcd(int val)
+{
+ return (val % 10) | (((val/10) % 10) << 4);
+}
+
+long
+rtctime(void)
+{
+ int ctl;
+ Rtc rtc;
+
+ /*
+ * convert from BCD
+ */
+ ctl = nvget(NVctl);
+ ctl &= RTsign|RTcal;
+ nvput(NVctl, ctl|RTread);
+
+ rtc.sec = getbcd(nvget(NVsec) & 0x7f);
+ rtc.min = getbcd(nvget(NVmin));
+ rtc.hour = getbcd(nvget(NVhour));
+ rtc.mday = getbcd(nvget(NVmday));
+ rtc.mon = getbcd(nvget(NVmon));
+ rtc.year = getbcd(nvget(NVyear));
+ if(rtc.year < 70)
+ rtc.year += 2000;
+ else
+ rtc.year += 1900;
+
+ nvput(NVctl, ctl);
+
+ return rtc2sec(&rtc);
+}
+
+static void
+setrtc(Rtc *rtc)
+{
+ int ctl;
+
+ ctl = nvget(NVctl);
+ ctl &= RTsign|RTcal;
+ nvput(NVctl, ctl|RTwrite);
+
+ nvput(NVsec, putbcd(rtc->sec));
+ nvput(NVmin, putbcd(rtc->min));
+ nvput(NVhour, putbcd(rtc->hour));
+ nvput(NVmday, putbcd(rtc->mday));
+ nvput(NVmon, putbcd(rtc->mon));
+ nvput(NVyear, putbcd(rtc->year % 100));
+
+ nvput(NVctl, ctl);
+}
+
+#define SEC2MIN 60L
+#define SEC2HOUR (60L*SEC2MIN)
+#define SEC2DAY (24L*SEC2HOUR)
+
+/*
+ * days per month plus days/year
+ */
+static int dmsize[] =
+{
+ 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+static int ldmsize[] =
+{
+ 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/*
+ * return the days/month for the given year
+ */
+static int *
+yrsize(int y)
+{
+
+ if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
+ return ldmsize;
+ else
+ return dmsize;
+}
+
+/*
+ * compute seconds since Jan 1 1970
+ */
+static ulong
+rtc2sec(Rtc *rtc)
+{
+ ulong secs;
+ int i;
+ int *d2m;
+
+ secs = 0;
+
+ /*
+ * seconds per year
+ */
+ for(i = 1970; i < rtc->year; i++){
+ d2m = yrsize(i);
+ secs += d2m[0] * SEC2DAY;
+ }
+
+ /*
+ * seconds per month
+ */
+ d2m = yrsize(rtc->year);
+ for(i = 1; i < rtc->mon; i++)
+ secs += d2m[i] * SEC2DAY;
+
+ secs += (rtc->mday-1) * SEC2DAY;
+ secs += rtc->hour * SEC2HOUR;
+ secs += rtc->min * SEC2MIN;
+ secs += rtc->sec;
+
+ return secs;
+}
+
+/*
+ * compute rtc from seconds since Jan 1 1970
+ */
+static void
+sec2rtc(ulong secs, Rtc *rtc)
+{
+ int d;
+ long hms, day;
+ int *d2m;
+
+ /*
+ * break initial number into days
+ */
+ hms = secs % SEC2DAY;
+ day = secs / SEC2DAY;
+ if(hms < 0) {
+ hms += SEC2DAY;
+ day -= 1;
+ }
+
+ /*
+ * generate hours:minutes:seconds
+ */
+ rtc->sec = hms % 60;
+ d = hms / 60;
+ rtc->min = d % 60;
+ d /= 60;
+ rtc->hour = d;
+
+ /*
+ * year number
+ */
+ if(day >= 0)
+ for(d = 1970; day >= *yrsize(d); d++)
+ day -= *yrsize(d);
+ else
+ for (d = 1970; day < 0; d--)
+ day += *yrsize(d-1);
+ rtc->year = d;
+
+ /*
+ * generate month
+ */
+ d2m = yrsize(rtc->year);
+ for(d = 1; day >= d2m[d]; d++)
+ day -= d2m[d];
+ rtc->mday = day + 1;
+ rtc->mon = d;
+
+ return;
+}
diff --git a/sys/src/9/mtx/ether2114x.c b/sys/src/9/mtx/ether2114x.c
new file mode 100755
index 000000000..b5dbfff06
--- /dev/null
+++ b/sys/src/9/mtx/ether2114x.c
@@ -0,0 +1,1671 @@
+/*
+ * Digital Semiconductor DECchip 2114x PCI Fast Ethernet LAN Controller.
+ * To do:
+ * thresholds;
+ * ring sizing;
+ * handle more error conditions;
+ * tidy setup packet mess;
+ * push initialisation back to attach;
+ * full SROM decoding.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+#define DEBUG (0)
+#define debug if(DEBUG)print
+
+enum {
+ Nrde = 64,
+ Ntde = 64,
+};
+
+#define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4)
+
+enum { /* CRS0 - Bus Mode */
+ Swr = 0x00000001, /* Software Reset */
+ Bar = 0x00000002, /* Bus Arbitration */
+ Dsl = 0x0000007C, /* Descriptor Skip Length (field) */
+ Ble = 0x00000080, /* Big/Little Endian */
+ Pbl = 0x00003F00, /* Programmable Burst Length (field) */
+ Cal = 0x0000C000, /* Cache Alignment (field) */
+ Cal8 = 0x00004000, /* 8 longword boundary alignment */
+ Cal16 = 0x00008000, /* 16 longword boundary alignment */
+ Cal32 = 0x0000C000, /* 32 longword boundary alignment */
+ Tap = 0x000E0000, /* Transmit Automatic Polling (field) */
+ Dbo = 0x00100000, /* Descriptor Byte Ordering Mode */
+ Rml = 0x00200000, /* Read Multiple */
+};
+
+enum { /* CSR[57] - Status and Interrupt Enable */
+ Ti = 0x00000001, /* Transmit Interrupt */
+ Tps = 0x00000002, /* Transmit Process Stopped */
+ Tu = 0x00000004, /* Transmit buffer Unavailable */
+ Tjt = 0x00000008, /* Transmit Jabber Timeout */
+ Unf = 0x00000020, /* transmit UNderFlow */
+ Ri = 0x00000040, /* Receive Interrupt */
+ Ru = 0x00000080, /* Receive buffer Unavailable */
+ Rps = 0x00000100, /* Receive Process Stopped */
+ Rwt = 0x00000200, /* Receive Watchdog Timeout */
+ Eti = 0x00000400, /* Early Transmit Interrupt */
+ Gte = 0x00000800, /* General purpose Timer Expired */
+ Fbe = 0x00002000, /* Fatal Bus Error */
+ Ais = 0x00008000, /* Abnormal Interrupt Summary */
+ Nis = 0x00010000, /* Normal Interrupt Summary */
+ Rs = 0x000E0000, /* Receive process State (field) */
+ Ts = 0x00700000, /* Transmit process State (field) */
+ Eb = 0x03800000, /* Error bits */
+};
+
+enum { /* CSR6 - Operating Mode */
+ Hp = 0x00000001, /* Hash/Perfect receive filtering mode */
+ Sr = 0x00000002, /* Start/stop Receive */
+ Ho = 0x00000004, /* Hash-Only filtering mode */
+ Pb = 0x00000008, /* Pass Bad frames */
+ If = 0x00000010, /* Inverse Filtering */
+ Sb = 0x00000020, /* Start/stop Backoff counter */
+ Pr = 0x00000040, /* Promiscuous Mode */
+ Pm = 0x00000080, /* Pass all Multicast */
+ Fd = 0x00000200, /* Full Duplex mode */
+ Om = 0x00000C00, /* Operating Mode (field) */
+ Fc = 0x00001000, /* Force Collision */
+ St = 0x00002000, /* Start/stop Transmission Command */
+ Tr = 0x0000C000, /* ThReshold control bits (field) */
+ Tr128 = 0x00000000,
+ Tr256 = 0x00004000,
+ Tr512 = 0x00008000,
+ Tr1024 = 0x0000C000,
+ Ca = 0x00020000, /* CApture effect enable */
+ Ps = 0x00040000, /* Port Select */
+ Hbd = 0x00080000, /* HeartBeat Disable */
+ Imm = 0x00100000, /* IMMediate mode */
+ Sf = 0x00200000, /* Store and Forward */
+ Ttm = 0x00400000, /* Transmit Threshold Mode */
+ Pcs = 0x00800000, /* PCS function */
+ Scr = 0x01000000, /* SCRambler mode */
+ Mbo = 0x02000000, /* Must Be One */
+ Ra = 0x40000000, /* Receive All */
+ Sc = 0x80000000, /* Special Capture effect enable */
+
+ TrMODE = Tr512, /* default transmission threshold */
+};
+
+enum { /* CSR9 - ROM and MII Management */
+ Scs = 0x00000001, /* serial ROM chip select */
+ Sclk = 0x00000002, /* serial ROM clock */
+ Sdi = 0x00000004, /* serial ROM data in */
+ Sdo = 0x00000008, /* serial ROM data out */
+ Ss = 0x00000800, /* serial ROM select */
+ Wr = 0x00002000, /* write */
+ Rd = 0x00004000, /* read */
+
+ Mdc = 0x00010000, /* MII management clock */
+ Mdo = 0x00020000, /* MII management write data */
+ Mii = 0x00040000, /* MII management operation mode (W) */
+ Mdi = 0x00080000, /* MII management data in */
+};
+
+enum { /* CSR12 - General-Purpose Port */
+ Gpc = 0x00000100, /* General Purpose Control */
+};
+
+typedef struct Des {
+ int status;
+ int control;
+ ulong addr;
+ Block* bp;
+} Des;
+
+enum { /* status */
+ Of = 0x00000001, /* Rx: OverFlow */
+ Ce = 0x00000002, /* Rx: CRC Error */
+ Db = 0x00000004, /* Rx: Dribbling Bit */
+ Re = 0x00000008, /* Rx: Report on MII Error */
+ Rw = 0x00000010, /* Rx: Receive Watchdog */
+ Ft = 0x00000020, /* Rx: Frame Type */
+ Cs = 0x00000040, /* Rx: Collision Seen */
+ Tl = 0x00000080, /* Rx: Frame too Long */
+ Ls = 0x00000100, /* Rx: Last deScriptor */
+ Fs = 0x00000200, /* Rx: First deScriptor */
+ Mf = 0x00000400, /* Rx: Multicast Frame */
+ Rf = 0x00000800, /* Rx: Runt Frame */
+ Dt = 0x00003000, /* Rx: Data Type (field) */
+ De = 0x00004000, /* Rx: Descriptor Error */
+ Fl = 0x3FFF0000, /* Rx: Frame Length (field) */
+ Ff = 0x40000000, /* Rx: Filtering Fail */
+
+ Def = 0x00000001, /* Tx: DEFerred */
+ Uf = 0x00000002, /* Tx: UnderFlow error */
+ Lf = 0x00000004, /* Tx: Link Fail report */
+ Cc = 0x00000078, /* Tx: Collision Count (field) */
+ Hf = 0x00000080, /* Tx: Heartbeat Fail */
+ Ec = 0x00000100, /* Tx: Excessive Collisions */
+ Lc = 0x00000200, /* Tx: Late Collision */
+ Nc = 0x00000400, /* Tx: No Carrier */
+ Lo = 0x00000800, /* Tx: LOss of carrier */
+ To = 0x00004000, /* Tx: Transmission jabber timeOut */
+
+ Es = 0x00008000, /* [RT]x: Error Summary */
+ Own = 0x80000000, /* [RT]x: OWN bit */
+};
+
+enum { /* control */
+ Bs1 = 0x000007FF, /* [RT]x: Buffer 1 Size */
+ Bs2 = 0x003FF800, /* [RT]x: Buffer 2 Size */
+
+ Ch = 0x01000000, /* [RT]x: second address CHained */
+ Er = 0x02000000, /* [RT]x: End of Ring */
+
+ Ft0 = 0x00400000, /* Tx: Filtering Type 0 */
+ Dpd = 0x00800000, /* Tx: Disabled PaDding */
+ Ac = 0x04000000, /* Tx: Add CRC disable */
+ Set = 0x08000000, /* Tx: SETup packet */
+ Ft1 = 0x10000000, /* Tx: Filtering Type 1 */
+ Fseg = 0x20000000, /* Tx: First SEGment */
+ Lseg = 0x40000000, /* Tx: Last SEGment */
+ Ic = 0x80000000, /* Tx: Interrupt on Completion */
+};
+
+enum { /* PHY registers */
+ Bmcr = 0, /* Basic Mode Control */
+ Bmsr = 1, /* Basic Mode Status */
+ Phyidr1 = 2, /* PHY Identifier #1 */
+ Phyidr2 = 3, /* PHY Identifier #2 */
+ Anar = 4, /* Auto-Negotiation Advertisment */
+ Anlpar = 5, /* Auto-Negotiation Link Partner Ability */
+ Aner = 6, /* Auto-Negotiation Expansion */
+};
+
+enum { /* Variants */
+ Tulip0 = (0x0009<<16)|0x1011,
+ Tulip3 = (0x0019<<16)|0x1011,
+ Pnic = (0x0002<<16)|0x11AD,
+ Pnic2 = (0xC115<<16)|0x11AD,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id; /* (pcidev->did<<16)|pcidev->vid */
+
+ uchar* srom;
+ int sromsz; /* address size in bits */
+ uchar* sromea; /* MAC address */
+ uchar* leaf;
+ int sct; /* selected connection type */
+ int k; /* info block count */
+ uchar* infoblock[16];
+ int sctk; /* sct block index */
+ int curk; /* current block index */
+ uchar* type5block;
+
+ int phy[32]; /* logical to physical map */
+ int phyreset; /* reset bitmap */
+ int curphyad;
+ int fdx;
+ int ttm;
+
+ uchar fd; /* option */
+ int medium; /* option */
+
+ int csr6; /* CSR6 - operating mode */
+ int mask; /* CSR[57] - interrupt mask */
+ int mbps;
+
+ Lock lock;
+
+ Des* rdr; /* receive descriptor ring */
+ int nrdr; /* size of rdr */
+ int rdrx; /* index into rdr */
+
+ Lock tlock;
+ Des* tdr; /* transmit descriptor ring */
+ int ntdr; /* size of tdr */
+ int tdrh; /* host index into tdr */
+ int tdri; /* interface index into tdr */
+ int ntq; /* descriptors active */
+ int ntqmax;
+ Block* setupbp;
+
+ ulong of; /* receive statistics */
+ ulong ce;
+ ulong cs;
+ ulong tl;
+ ulong rf;
+ ulong de;
+
+ ulong ru;
+ ulong rps;
+ ulong rwt;
+
+ ulong uf; /* transmit statistics */
+ ulong ec;
+ ulong lc;
+ ulong nc;
+ ulong lo;
+ ulong to;
+
+ ulong tps;
+ ulong tu;
+ ulong tjt;
+ ulong unf;
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+#define csr32r(c, r) (inl((c)->port+((r)*8)))
+#define csr32w(c, r, l) (outl((c)->port+((r)*8), (ulong)(l)))
+
+static void
+promiscuous(void* arg, int on)
+{
+ Ctlr *ctlr;
+
+ ctlr = ((Ether*)arg)->ctlr;
+ ilock(&ctlr->lock);
+ if(on)
+ ctlr->csr6 |= Pr;
+ else
+ ctlr->csr6 &= ~Pr;
+ csr32w(ctlr, 6, ctlr->csr6);
+ iunlock(&ctlr->lock);
+}
+
+static void
+attach(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(&ctlr->lock);
+ if(!(ctlr->csr6 & Sr)){
+ ctlr->csr6 |= Sr;
+ csr32w(ctlr, 6, ctlr->csr6);
+ }
+ iunlock(&ctlr->lock);
+}
+
+static long
+ifstat(Ether* ether, void* a, long n, ulong offset)
+{
+ Ctlr *ctlr;
+ char *buf, *p;
+ int i, l, len;
+
+ ctlr = ether->ctlr;
+
+ ether->crcs = ctlr->ce;
+ ether->frames = ctlr->rf+ctlr->cs;
+ ether->buffs = ctlr->de+ctlr->tl;
+ ether->overflows = ctlr->of;
+
+ if(n == 0)
+ return 0;
+
+ p = malloc(READSTR);
+ l = snprint(p, READSTR, "Overflow: %lud\n", ctlr->of);
+ l += snprint(p+l, READSTR-l, "Ru: %lud\n", ctlr->ru);
+ l += snprint(p+l, READSTR-l, "Rps: %lud\n", ctlr->rps);
+ l += snprint(p+l, READSTR-l, "Rwt: %lud\n", ctlr->rwt);
+ l += snprint(p+l, READSTR-l, "Tps: %lud\n", ctlr->tps);
+ l += snprint(p+l, READSTR-l, "Tu: %lud\n", ctlr->tu);
+ l += snprint(p+l, READSTR-l, "Tjt: %lud\n", ctlr->tjt);
+ l += snprint(p+l, READSTR-l, "Unf: %lud\n", ctlr->unf);
+ l += snprint(p+l, READSTR-l, "CRC Error: %lud\n", ctlr->ce);
+ l += snprint(p+l, READSTR-l, "Collision Seen: %lud\n", ctlr->cs);
+ l += snprint(p+l, READSTR-l, "Frame Too Long: %lud\n", ctlr->tl);
+ l += snprint(p+l, READSTR-l, "Runt Frame: %lud\n", ctlr->rf);
+ l += snprint(p+l, READSTR-l, "Descriptor Error: %lud\n", ctlr->de);
+ l += snprint(p+l, READSTR-l, "Underflow Error: %lud\n", ctlr->uf);
+ l += snprint(p+l, READSTR-l, "Excessive Collisions: %lud\n", ctlr->ec);
+ l += snprint(p+l, READSTR-l, "Late Collision: %lud\n", ctlr->lc);
+ l += snprint(p+l, READSTR-l, "No Carrier: %lud\n", ctlr->nc);
+ l += snprint(p+l, READSTR-l, "Loss of Carrier: %lud\n", ctlr->lo);
+ l += snprint(p+l, READSTR-l, "Transmit Jabber Timeout: %lud\n",
+ ctlr->to);
+ l += snprint(p+l, READSTR-l, "csr6: %luX %uX\n", csr32r(ctlr, 6),
+ ctlr->csr6);
+ snprint(p+l, READSTR-l, "ntqmax: %d\n", ctlr->ntqmax);
+ ctlr->ntqmax = 0;
+ buf = a;
+ len = readstr(offset, buf, n, p);
+ if(offset > l)
+ offset -= l;
+ else
+ offset = 0;
+ buf += len;
+ n -= len;
+
+ l = snprint(p, READSTR, "srom:");
+ for(i = 0; i < (1<<(ctlr->sromsz)*sizeof(ushort)); i++){
+ if(i && ((i & 0x0F) == 0))
+ l += snprint(p+l, READSTR-l, "\n ");
+ l += snprint(p+l, READSTR-l, " %2.2uX", ctlr->srom[i]);
+ }
+
+ snprint(p+l, READSTR-l, "\n");
+ len += readstr(offset, buf, n, p);
+ free(p);
+
+ return len;
+}
+
+static void
+txstart(Ether* ether)
+{
+ Ctlr *ctlr;
+ Block *bp;
+ Des *des;
+ int control;
+
+ ctlr = ether->ctlr;
+ while(ctlr->ntq < (ctlr->ntdr-1)){
+ if(ctlr->setupbp){
+ bp = ctlr->setupbp;
+ ctlr->setupbp = 0;
+ control = Ic|Set|BLEN(bp);
+ }
+ else{
+ bp = qget(ether->oq);
+ if(bp == nil)
+ break;
+ control = Ic|Lseg|Fseg|BLEN(bp);
+ }
+
+ ctlr->tdr[PREV(ctlr->tdrh, ctlr->ntdr)].control &= ~Ic;
+ des = &ctlr->tdr[ctlr->tdrh];
+ des->bp = bp;
+ des->addr = PCIWADDR(bp->rp);
+ des->control |= control;
+ ctlr->ntq++;
+ coherence();
+ des->status = Own;
+ csr32w(ctlr, 1, 0);
+ ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
+ }
+
+ if(ctlr->ntq > ctlr->ntqmax)
+ ctlr->ntqmax = ctlr->ntq;
+}
+
+static void
+transmit(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(&ctlr->tlock);
+ txstart(ether);
+ iunlock(&ctlr->tlock);
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Ether *ether;
+ int len, status;
+ Des *des;
+ Block *bp;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+
+ while((status = csr32r(ctlr, 5)) & (Nis|Ais)){
+ /*
+ * Acknowledge the interrupts and mask-out
+ * the ones that are implicitly handled.
+ */
+ csr32w(ctlr, 5, status);
+ status &= (ctlr->mask & ~(Nis|Ti));
+
+ if(status & Ais){
+ if(status & Tps)
+ ctlr->tps++;
+ if(status & Tu)
+ ctlr->tu++;
+ if(status & Tjt)
+ ctlr->tjt++;
+ if(status & Ru)
+ ctlr->ru++;
+ if(status & Rps)
+ ctlr->rps++;
+ if(status & Rwt)
+ ctlr->rwt++;
+ status &= ~(Ais|Rwt|Rps|Ru|Tjt|Tu|Tps);
+ }
+
+ /*
+ * Received packets.
+ */
+ if(status & Ri){
+ des = &ctlr->rdr[ctlr->rdrx];
+ while(!(des->status & Own)){
+ if(des->status & Es){
+ if(des->status & Of)
+ ctlr->of++;
+ if(des->status & Ce)
+ ctlr->ce++;
+ if(des->status & Cs)
+ ctlr->cs++;
+ if(des->status & Tl)
+ ctlr->tl++;
+ if(des->status & Rf)
+ ctlr->rf++;
+ if(des->status & De)
+ ctlr->de++;
+ }
+ else if(bp = iallocb(Rbsz)){
+ len = ((des->status & Fl)>>16)-4;
+ des->bp->wp = des->bp->rp+len;
+ etheriq(ether, des->bp, 1);
+ des->bp = bp;
+ des->addr = PCIWADDR(bp->rp);
+ }
+
+ des->control &= Er;
+ des->control |= Rbsz;
+ coherence();
+ des->status = Own;
+
+ ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
+ des = &ctlr->rdr[ctlr->rdrx];
+ }
+ status &= ~Ri;
+ }
+
+ /*
+ * Check the transmit side:
+ * check for Transmit Underflow and Adjust
+ * the threshold upwards;
+ * free any transmitted buffers and try to
+ * top-up the ring.
+ */
+ if(status & Unf){
+ ctlr->unf++;
+ ilock(&ctlr->lock);
+ csr32w(ctlr, 6, ctlr->csr6 & ~St);
+ switch(ctlr->csr6 & Tr){
+ case Tr128:
+ len = Tr256;
+ break;
+ case Tr256:
+ len = Tr512;
+ break;
+ case Tr512:
+ len = Tr1024;
+ break;
+ default:
+ case Tr1024:
+ len = Sf;
+ break;
+ }
+ ctlr->csr6 = (ctlr->csr6 & ~Tr)|len;
+ csr32w(ctlr, 6, ctlr->csr6);
+ iunlock(&ctlr->lock);
+ csr32w(ctlr, 5, Tps);
+ status &= ~(Unf|Tps);
+ }
+
+ ilock(&ctlr->tlock);
+ while(ctlr->ntq){
+ des = &ctlr->tdr[ctlr->tdri];
+ if(des->status & Own)
+ break;
+
+ if(des->status & Es){
+ if(des->status & Uf)
+ ctlr->uf++;
+ if(des->status & Ec)
+ ctlr->ec++;
+ if(des->status & Lc)
+ ctlr->lc++;
+ if(des->status & Nc)
+ ctlr->nc++;
+ if(des->status & Lo)
+ ctlr->lo++;
+ if(des->status & To)
+ ctlr->to++;
+ ether->oerrs++;
+ }
+
+ freeb(des->bp);
+ des->control &= Er;
+
+ ctlr->ntq--;
+ ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
+ }
+ txstart(ether);
+ iunlock(&ctlr->tlock);
+
+ /*
+ * Anything left not catered for?
+ */
+ if(status)
+ panic("#l%d: status %8.8uX\n", ether->ctlrno, status);
+ }
+}
+
+static void
+ctlrinit(Ether* ether)
+{
+ Ctlr *ctlr;
+ Des *des;
+ Block *bp;
+ int i;
+ uchar bi[Eaddrlen*2];
+
+ ctlr = ether->ctlr;
+
+ /*
+ * Allocate and initialise the receive ring;
+ * allocate and initialise the transmit ring;
+ * unmask interrupts and start the transmit side;
+ * create and post a setup packet to initialise
+ * the physical ethernet address.
+ */
+ ctlr->rdr = xspanalloc(ctlr->nrdr*sizeof(Des), 8*sizeof(ulong), 0);
+ for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
+ des->bp = iallocb(Rbsz);
+ if(des->bp == nil)
+ panic("can't allocate ethernet receive ring\n");
+ des->status = Own;
+ des->control = Rbsz;
+ des->addr = PCIWADDR(des->bp->rp);
+ }
+ ctlr->rdr[ctlr->nrdr-1].control |= Er;
+ ctlr->rdrx = 0;
+ csr32w(ctlr, 3, PCIWADDR(ctlr->rdr));
+
+ ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0);
+ ctlr->tdr[ctlr->ntdr-1].control |= Er;
+ ctlr->tdrh = 0;
+ ctlr->tdri = 0;
+ csr32w(ctlr, 4, PCIWADDR(ctlr->tdr));
+
+ /*
+ * Clear any bits in the Status Register (CSR5) as
+ * the PNIC has a different reset value from a true 2114x.
+ */
+ ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti;
+ csr32w(ctlr, 5, ctlr->mask);
+ csr32w(ctlr, 7, ctlr->mask);
+ ctlr->csr6 |= St;
+ csr32w(ctlr, 6, ctlr->csr6);
+
+ for(i = 0; i < Eaddrlen/2; i++){
+ bi[i*4] = ether->ea[i*2];
+ bi[i*4+1] = ether->ea[i*2+1];
+ bi[i*4+2] = ether->ea[i*2+1];
+ bi[i*4+3] = ether->ea[i*2];
+ }
+ bp = iallocb(Eaddrlen*2*16);
+ if(bp == nil)
+ panic("can't allocate ethernet setup buffer\n");
+ memset(bp->rp, 0xFF, sizeof(bi));
+ for(i = sizeof(bi); i < sizeof(bi)*16; i += sizeof(bi))
+ memmove(bp->rp+i, bi, sizeof(bi));
+ bp->wp += sizeof(bi)*16;
+
+ ctlr->setupbp = bp;
+ ether->oq = qopen(256*1024, Qmsg, 0, 0);
+ transmit(ether);
+}
+
+static void
+csr9w(Ctlr* ctlr, int data)
+{
+ csr32w(ctlr, 9, data);
+ microdelay(1);
+}
+
+static int
+miimdi(Ctlr* ctlr, int n)
+{
+ int data, i;
+
+ /*
+ * Read n bits from the MII Management Register.
+ */
+ data = 0;
+ for(i = n-1; i >= 0; i--){
+ if(csr32r(ctlr, 9) & Mdi)
+ data |= (1<<i);
+ csr9w(ctlr, Mii|Mdc);
+ csr9w(ctlr, Mii);
+ }
+ csr9w(ctlr, 0);
+
+ return data;
+}
+
+static void
+miimdo(Ctlr* ctlr, int bits, int n)
+{
+ int i, mdo;
+
+ /*
+ * Write n bits to the MII Management Register.
+ */
+ for(i = n-1; i >= 0; i--){
+ if(bits & (1<<i))
+ mdo = Mdo;
+ else
+ mdo = 0;
+ csr9w(ctlr, mdo);
+ csr9w(ctlr, mdo|Mdc);
+ csr9w(ctlr, mdo);
+ }
+}
+
+static int
+miir(Ctlr* ctlr, int phyad, int regad)
+{
+ int data, i;
+
+ if(ctlr->id == Pnic){
+ i = 1000;
+ csr32w(ctlr, 20, 0x60020000|(phyad<<23)|(regad<<18));
+ do{
+ microdelay(1);
+ data = csr32r(ctlr, 20);
+ }while((data & 0x80000000) && --i);
+
+ if(i == 0)
+ return -1;
+ return data & 0xFFFF;
+ }
+
+ /*
+ * Preamble;
+ * ST+OP+PHYAD+REGAD;
+ * TA + 16 data bits.
+ */
+ miimdo(ctlr, 0xFFFFFFFF, 32);
+ miimdo(ctlr, 0x1800|(phyad<<5)|regad, 14);
+ data = miimdi(ctlr, 18);
+
+ if(data & 0x10000)
+ return -1;
+
+ return data & 0xFFFF;
+}
+
+static void
+miiw(Ctlr* ctlr, int phyad, int regad, int data)
+{
+ /*
+ * Preamble;
+ * ST+OP+PHYAD+REGAD+TA + 16 data bits;
+ * Z.
+ */
+ miimdo(ctlr, 0xFFFFFFFF, 32);
+ data &= 0xFFFF;
+ data |= (0x05<<(5+5+2+16))|(phyad<<(5+2+16))|(regad<<(2+16))|(0x02<<16);
+ miimdo(ctlr, data, 32);
+ csr9w(ctlr, Mdc);
+ csr9w(ctlr, 0);
+}
+
+static int
+sromr(Ctlr* ctlr, int r)
+{
+ int i, op, data, size;
+
+ if(ctlr->id == Pnic){
+ i = 1000;
+ csr32w(ctlr, 19, 0x600|r);
+ do{
+ microdelay(1);
+ data = csr32r(ctlr, 19);
+ }while((data & 0x80000000) && --i);
+
+ if(ctlr->sromsz == 0)
+ ctlr->sromsz = 6;
+
+ return csr32r(ctlr, 9) & 0xFFFF;
+ }
+
+ /*
+ * This sequence for reading a 16-bit register 'r'
+ * in the EEPROM is taken straight from Section
+ * 7.4 of the 21140 Hardware Reference Manual.
+ */
+reread:
+ csr9w(ctlr, Rd|Ss);
+ csr9w(ctlr, Rd|Ss|Scs);
+ csr9w(ctlr, Rd|Ss|Sclk|Scs);
+ csr9w(ctlr, Rd|Ss);
+
+ op = 0x06;
+ for(i = 3-1; i >= 0; i--){
+ data = Rd|Ss|(((op>>i) & 0x01)<<2)|Scs;
+ csr9w(ctlr, data);
+ csr9w(ctlr, data|Sclk);
+ csr9w(ctlr, data);
+ }
+
+ /*
+ * First time through must work out the EEPROM size.
+ */
+ if((size = ctlr->sromsz) == 0)
+ size = 8;
+
+ for(size = size-1; size >= 0; size--){
+ data = Rd|Ss|(((r>>size) & 0x01)<<2)|Scs;
+ csr9w(ctlr, data);
+ csr9w(ctlr, data|Sclk);
+ csr9w(ctlr, data);
+ microdelay(1);
+ if(!(csr32r(ctlr, 9) & Sdo))
+ break;
+ }
+
+ data = 0;
+ for(i = 16-1; i >= 0; i--){
+ csr9w(ctlr, Rd|Ss|Sclk|Scs);
+ if(csr32r(ctlr, 9) & Sdo)
+ data |= (1<<i);
+ csr9w(ctlr, Rd|Ss|Scs);
+ }
+
+ csr9w(ctlr, 0);
+
+ if(ctlr->sromsz == 0){
+ ctlr->sromsz = 8-size;
+ goto reread;
+ }
+
+ return data & 0xFFFF;
+}
+
+static void
+softreset(Ctlr* ctlr)
+{
+ /*
+ * Soft-reset the controller and initialise bus mode.
+ * Delay should be >= 50 PCI cycles (2×S @ 25MHz).
+ */
+ csr32w(ctlr, 0, Swr);
+ microdelay(10);
+ csr32w(ctlr, 0, Rml|Cal16|Dbo);
+ delay(1);
+}
+
+static int
+type5block(Ctlr* ctlr, uchar* block)
+{
+ int csr15, i, len;
+
+ /*
+ * Reset or GPR sequence. Reset should be once only,
+ * before the GPR sequence.
+ * Note 'block' is not a pointer to the block head but
+ * a pointer to the data in the block starting at the
+ * reset length value so type5block can be used for the
+ * sequences contained in type 1 and type 3 blocks.
+ * The SROM docs state the 21140 type 5 block is the
+ * same as that for the 21143, but the two controllers
+ * use different registers and sequence-element lengths
+ * so the 21140 code here is a guess for a real type 5
+ * sequence.
+ */
+ len = *block++;
+ if(ctlr->id != Tulip3){
+ for(i = 0; i < len; i++){
+ csr32w(ctlr, 12, *block);
+ block++;
+ }
+ return len;
+ }
+
+ for(i = 0; i < len; i++){
+ csr15 = *block++<<16;
+ csr15 |= *block++<<24;
+ csr32w(ctlr, 15, csr15);
+ debug("%8.8uX ", csr15);
+ }
+ return 2*len;
+}
+
+static int
+typephylink(Ctlr* ctlr, uchar*)
+{
+ int an, bmcr, bmsr, csr6, x;
+
+ /*
+ * Fail if
+ * auto-negotiataion enabled but not complete;
+ * no valid link established.
+ */
+ bmcr = miir(ctlr, ctlr->curphyad, Bmcr);
+ miir(ctlr, ctlr->curphyad, Bmsr);
+ bmsr = miir(ctlr, ctlr->curphyad, Bmsr);
+ debug("bmcr 0x%2.2uX bmsr 0x%2.2uX\n", bmcr, bmsr);
+ if(((bmcr & 0x1000) && !(bmsr & 0x0020)) || !(bmsr & 0x0004))
+ return 0;
+
+ if(bmcr & 0x1000){
+ an = miir(ctlr, ctlr->curphyad, Anar);
+ an &= miir(ctlr, ctlr->curphyad, Anlpar) & 0x3E0;
+ debug("an 0x%2.uX 0x%2.2uX 0x%2.2uX\n",
+ miir(ctlr, ctlr->curphyad, Anar),
+ miir(ctlr, ctlr->curphyad, Anlpar),
+ an);
+
+ if(an & 0x0100)
+ x = 0x4000;
+ else if(an & 0x0080)
+ x = 0x2000;
+ else if(an & 0x0040)
+ x = 0x1000;
+ else if(an & 0x0020)
+ x = 0x0800;
+ else
+ x = 0;
+ }
+ else if((bmcr & 0x2100) == 0x2100)
+ x = 0x4000;
+ else if(bmcr & 0x2000){
+ /*
+ * If FD capable, force it if necessary.
+ */
+ if((bmsr & 0x4000) && ctlr->fd){
+ miiw(ctlr, ctlr->curphyad, Bmcr, 0x2100);
+ x = 0x4000;
+ }
+ else
+ x = 0x2000;
+ }
+ else if(bmcr & 0x0100)
+ x = 0x1000;
+ else
+ x = 0x0800;
+
+ csr6 = Sc|Mbo|Hbd|Ps|Ca|Sb|TrMODE;
+ if(ctlr->fdx & x)
+ csr6 |= Fd;
+ if(ctlr->ttm & x)
+ csr6 |= Ttm;
+ debug("csr6 0x%8.8uX 0x%8.8uX 0x%8.8luX\n",
+ csr6, ctlr->csr6, csr32r(ctlr, 6));
+ if(csr6 != ctlr->csr6){
+ ctlr->csr6 = csr6;
+ csr32w(ctlr, 6, csr6);
+ }
+
+ return 1;
+}
+
+static int
+typephymode(Ctlr* ctlr, uchar* block, int wait)
+{
+ uchar *p;
+ int len, mc, nway, phyx, timeo;
+
+ if(DEBUG){
+ int i;
+
+ len = (block[0] & ~0x80)+1;
+ for(i = 0; i < len; i++)
+ debug("%2.2uX ", block[i]);
+ debug("\n");
+ }
+
+ if(block[1] == 1)
+ len = 1;
+ else if(block[1] == 3)
+ len = 2;
+ else
+ return -1;
+
+ /*
+ * Snarf the media capabilities, nway advertisment,
+ * FDX and TTM bitmaps.
+ */
+ p = &block[5+len*block[3]+len*block[4+len*block[3]]];
+ mc = *p++;
+ mc |= *p++<<8;
+ nway = *p++;
+ nway |= *p++<<8;
+ ctlr->fdx = *p++;
+ ctlr->fdx |= *p++<<8;
+ ctlr->ttm = *p++;
+ ctlr->ttm |= *p<<8;
+ debug("mc %4.4uX nway %4.4uX fdx %4.4uX ttm %4.4uX\n",
+ mc, nway, ctlr->fdx, ctlr->ttm);
+ USED(mc);
+
+ phyx = block[2];
+ ctlr->curphyad = ctlr->phy[phyx];
+
+ ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|Sb|TrMODE;
+ //csr32w(ctlr, 6, ctlr->csr6);
+ if(typephylink(ctlr, block))
+ return 0;
+
+ if(!(ctlr->phyreset & (1<<phyx))){
+ debug("reset seq: len %d: ", block[3]);
+ if(ctlr->type5block)
+ type5block(ctlr, &ctlr->type5block[2]);
+ else
+ type5block(ctlr, &block[4+len*block[3]]);
+ debug("\n");
+ ctlr->phyreset |= (1<<phyx);
+ }
+
+ /*
+ * GPR sequence.
+ */
+ debug("gpr seq: len %d: ", block[3]);
+ type5block(ctlr, &block[3]);
+ debug("\n");
+
+ ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|Sb|TrMODE;
+ //csr32w(ctlr, 6, ctlr->csr6);
+ if(typephylink(ctlr, block))
+ return 0;
+
+ /*
+ * Turn off auto-negotiation, set the auto-negotiation
+ * advertisment register then start the auto-negotiation
+ * process again.
+ */
+ miiw(ctlr, ctlr->curphyad, Bmcr, 0);
+ miiw(ctlr, ctlr->curphyad, Anar, nway|1);
+ miiw(ctlr, ctlr->curphyad, Bmcr, 0x1000);
+
+ if(!wait)
+ return 0;
+
+ for(timeo = 0; timeo < 30; timeo++){
+ if(typephylink(ctlr, block))
+ return 0;
+ delay(100);
+ }
+
+ return -1;
+}
+
+static int
+typesymmode(Ctlr *ctlr, uchar *block, int wait)
+{
+ uint gpmode, gpdata, command;
+
+ USED(wait);
+ gpmode = block[3] | ((uint) block[4] << 8);
+ gpdata = block[5] | ((uint) block[6] << 8);
+ command = (block[7] | ((uint) block[8] << 8)) & 0x71;
+ if (command & 0x8000) {
+ print("ether2114x.c: FIXME: handle type 4 mode blocks where cmd.active_invalid != 0\n");
+ return -1;
+ }
+ csr32w(ctlr, 15, gpmode);
+ csr32w(ctlr, 15, gpdata);
+ ctlr->csr6 = (command & 0x71) << 18;
+ csr32w(ctlr, 6, ctlr->csr6);
+ return 0;
+}
+
+static int
+type2mode(Ctlr* ctlr, uchar* block, int)
+{
+ uchar *p;
+ int csr6, csr13, csr14, csr15, gpc, gpd;
+
+ csr6 = Sc|Mbo|Ca|Sb|TrMODE;
+ debug("type2mode: medium 0x%2.2uX\n", block[2]);
+
+ /*
+ * Don't attempt full-duplex
+ * unless explicitly requested.
+ */
+ if((block[2] & 0x3F) == 0x04){ /* 10BASE-TFD */
+ if(!ctlr->fd)
+ return -1;
+ csr6 |= Fd;
+ }
+
+ /*
+ * Operating mode programming values from the datasheet
+ * unless media specific data is explicitly given.
+ */
+ p = &block[3];
+ if(block[2] & 0x40){
+ csr13 = (block[4]<<8)|block[3];
+ csr14 = (block[6]<<8)|block[5];
+ csr15 = (block[8]<<8)|block[7];
+ p += 6;
+ }
+ else switch(block[2] & 0x3F){
+ default:
+ return -1;
+ case 0x00: /* 10BASE-T */
+ csr13 = 0x00000001;
+ csr14 = 0x00007F3F;
+ csr15 = 0x00000008;
+ break;
+ case 0x01: /* 10BASE-2 */
+ csr13 = 0x00000009;
+ csr14 = 0x00000705;
+ csr15 = 0x00000006;
+ break;
+ case 0x02: /* 10BASE-5 (AUI) */
+ csr13 = 0x00000009;
+ csr14 = 0x00000705;
+ csr15 = 0x0000000E;
+ break;
+ case 0x04: /* 10BASE-TFD */
+ csr13 = 0x00000001;
+ csr14 = 0x00007F3D;
+ csr15 = 0x00000008;
+ break;
+ }
+ gpc = *p++<<16;
+ gpc |= *p++<<24;
+ gpd = *p++<<16;
+ gpd |= *p<<24;
+
+ csr32w(ctlr, 13, 0);
+ csr32w(ctlr, 14, csr14);
+ csr32w(ctlr, 15, gpc|csr15);
+ delay(10);
+ csr32w(ctlr, 15, gpd|csr15);
+ csr32w(ctlr, 13, csr13);
+
+ ctlr->csr6 = csr6;
+ csr32w(ctlr, 6, ctlr->csr6);
+
+ debug("type2mode: csr13 %8.8uX csr14 %8.8uX csr15 %8.8uX\n",
+ csr13, csr14, csr15);
+ debug("type2mode: gpc %8.8uX gpd %8.8uX csr6 %8.8uX\n",
+ gpc, gpd, csr6);
+
+ return 0;
+}
+
+static int
+type0link(Ctlr* ctlr, uchar* block)
+{
+ int m, polarity, sense;
+
+ m = (block[3]<<8)|block[2];
+ sense = 1<<((m & 0x000E)>>1);
+ if(m & 0x0080)
+ polarity = sense;
+ else
+ polarity = 0;
+
+ return (csr32r(ctlr, 12) & sense)^polarity;
+}
+
+static int
+type0mode(Ctlr* ctlr, uchar* block, int wait)
+{
+ int csr6, m, timeo;
+
+ csr6 = Sc|Mbo|Hbd|Ca|Sb|TrMODE;
+debug("type0: medium 0x%uX, fd %d: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
+ ctlr->medium, ctlr->fd, block[0], block[1], block[2], block[3]);
+ switch(block[0]){
+ default:
+ break;
+
+ case 0x04: /* 10BASE-TFD */
+ case 0x05: /* 100BASE-TXFD */
+ case 0x08: /* 100BASE-FXFD */
+ /*
+ * Don't attempt full-duplex
+ * unless explicitly requested.
+ */
+ if(!ctlr->fd)
+ return -1;
+ csr6 |= Fd;
+ break;
+ }
+
+ m = (block[3]<<8)|block[2];
+ if(m & 0x0001)
+ csr6 |= Ps;
+ if(m & 0x0010)
+ csr6 |= Ttm;
+ if(m & 0x0020)
+ csr6 |= Pcs;
+ if(m & 0x0040)
+ csr6 |= Scr;
+
+ csr32w(ctlr, 12, block[1]);
+ microdelay(10);
+ csr32w(ctlr, 6, csr6);
+ ctlr->csr6 = csr6;
+
+ if(!wait)
+ return 0;
+
+ for(timeo = 0; timeo < 30; timeo++){
+ if(type0link(ctlr, block))
+ return 0;
+ delay(100);
+ }
+
+ return -1;
+}
+
+static int
+mediaxx(Ether* ether, int wait)
+{
+ Ctlr* ctlr;
+ uchar *block;
+
+ ctlr = ether->ctlr;
+ block = ctlr->infoblock[ctlr->curk];
+ if(block[0] & 0x80){
+ switch(block[1]){
+ default:
+ return -1;
+ case 0:
+ if(ctlr->medium >= 0 && block[2] != ctlr->medium)
+ return 0;
+/* need this test? */ if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[2])
+ return 0;
+ if(type0mode(ctlr, block+2, wait))
+ return 0;
+ break;
+ case 1:
+ if(typephymode(ctlr, block, wait))
+ return 0;
+ break;
+ case 2:
+ debug("type2: medium %d block[2] %d\n",
+ ctlr->medium, block[2]);
+ if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
+ return 0;
+ if(type2mode(ctlr, block, wait))
+ return 0;
+ break;
+ case 3:
+ if(typephymode(ctlr, block, wait))
+ return 0;
+ break;
+ case 4:
+ debug("type4: medium %d block[2] %d\n",
+ ctlr->medium, block[2]);
+ if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
+ return 0;
+ if(typesymmode(ctlr, block, wait))
+ return 0;
+ break;
+ }
+ }
+ else{
+ if(ctlr->medium >= 0 && block[0] != ctlr->medium)
+ return 0;
+/* need this test? */if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[0])
+ return 0;
+ if(type0mode(ctlr, block, wait))
+ return 0;
+ }
+
+ if(ctlr->csr6){
+ if(!(ctlr->csr6 & Ps) || (ctlr->csr6 & Ttm))
+ return 10;
+ return 100;
+ }
+
+ return 0;
+}
+
+static int
+media(Ether* ether, int wait)
+{
+ Ctlr* ctlr;
+ int k, mbps;
+
+ ctlr = ether->ctlr;
+ for(k = 0; k < ctlr->k; k++){
+ mbps = mediaxx(ether, wait);
+ if(mbps > 0)
+ return mbps;
+ if(ctlr->curk == 0)
+ ctlr->curk = ctlr->k-1;
+ else
+ ctlr->curk--;
+ }
+
+ return 0;
+}
+
+static char* mediatable[9] = {
+ "10BASE-T", /* TP */
+ "10BASE-2", /* BNC */
+ "10BASE-5", /* AUI */
+ "100BASE-TX",
+ "10BASE-TFD",
+ "100BASE-TXFD",
+ "100BASE-T4",
+ "100BASE-FX",
+ "100BASE-FXFD",
+};
+
+static uchar en1207[] = { /* Accton EN1207-COMBO */
+ 0x00, 0x00, 0xE8, /* [0] vendor ethernet code */
+ 0x00, /* [3] spare */
+
+ 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */
+ 0x1F, /* [6] general purpose control */
+ 2, /* [7] block count */
+
+ 0x00, /* [8] media code (10BASE-TX) */
+ 0x0B, /* [9] general purpose port data */
+ 0x9E, 0x00, /* [10] command (LSB+MSB = 0x009E) */
+
+ 0x03, /* [8] media code (100BASE-TX) */
+ 0x1B, /* [9] general purpose port data */
+ 0x6D, 0x00, /* [10] command (LSB+MSB = 0x006D) */
+
+ /* There is 10BASE-2 as well, but... */
+};
+
+static uchar ana6910fx[] = { /* Adaptec (Cogent) ANA-6910FX */
+ 0x00, 0x00, 0x92, /* [0] vendor ethernet code */
+ 0x00, /* [3] spare */
+
+ 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */
+ 0x3F, /* [6] general purpose control */
+ 1, /* [7] block count */
+
+ 0x07, /* [8] media code (100BASE-FX) */
+ 0x03, /* [9] general purpose port data */
+ 0x2D, 0x00 /* [10] command (LSB+MSB = 0x000D) */
+};
+
+static uchar smc9332[] = { /* SMC 9332 */
+ 0x00, 0x00, 0xC0, /* [0] vendor ethernet code */
+ 0x00, /* [3] spare */
+
+ 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */
+ 0x1F, /* [6] general purpose control */
+ 2, /* [7] block count */
+
+ 0x00, /* [8] media code (10BASE-TX) */
+ 0x00, /* [9] general purpose port data */
+ 0x9E, 0x00, /* [10] command (LSB+MSB = 0x009E) */
+
+ 0x03, /* [8] media code (100BASE-TX) */
+ 0x09, /* [9] general purpose port data */
+ 0x6D, 0x00, /* [10] command (LSB+MSB = 0x006D) */
+};
+
+static uchar* leaf21140[] = {
+ en1207, /* Accton EN1207-COMBO */
+ ana6910fx, /* Adaptec (Cogent) ANA-6910FX */
+ smc9332, /* SMC 9332 */
+ nil,
+};
+
+/*
+ * Copied to ctlr->srom at offset 20.
+ */
+static uchar leafpnic[] = {
+ 0x00, 0x00, 0x00, 0x00, /* MAC address */
+ 0x00, 0x00,
+ 0x00, /* controller 0 device number */
+ 0x1E, 0x00, /* controller 0 info leaf offset */
+ 0x00, /* reserved */
+ 0x00, 0x08, /* selected connection type */
+ 0x00, /* general purpose control */
+ 0x01, /* block count */
+
+ 0x8C, /* format indicator and count */
+ 0x01, /* block type */
+ 0x00, /* PHY number */
+ 0x00, /* GPR sequence length */
+ 0x00, /* reset sequence length */
+ 0x00, 0x78, /* media capabilities */
+ 0xE0, 0x01, /* Nway advertisment */
+ 0x00, 0x50, /* FDX bitmap */
+ 0x00, 0x18, /* TTM bitmap */
+};
+
+static int
+srom(Ctlr* ctlr)
+{
+ int i, k, oui, phy, x;
+ uchar *p;
+
+ /*
+ * This is a partial decoding of the SROM format described in
+ * 'Digital Semiconductor 21X4 Serial ROM Format, Version 4.05,
+ * 2-Mar-98'. Only the 2114[03] are handled, support for other
+ * controllers can be added as needed.
+ * Do a dummy read first to get the size and allocate ctlr->srom.
+ */
+ sromr(ctlr, 0);
+ if(ctlr->srom == nil)
+ ctlr->srom = malloc((1<<ctlr->sromsz)*sizeof(ushort));
+ for(i = 0; i < (1<<ctlr->sromsz); i++){
+ x = sromr(ctlr, i);
+ ctlr->srom[2*i] = x;
+ ctlr->srom[2*i+1] = x>>8;
+ }
+
+ /*
+ * There are 2 SROM layouts:
+ * e.g. Digital EtherWORKS station address at offset 20;
+ * this complies with the 21140A SROM
+ * application note from Digital;
+ * e.g. SMC9332 station address at offset 0 followed by
+ * 2 additional bytes, repeated at offset
+ * 6; the 8 bytes are also repeated in
+ * reverse order at offset 8.
+ * To check which it is, read the SROM and check for the repeating
+ * patterns of the non-compliant cards; if that fails use the one at
+ * offset 20.
+ */
+ ctlr->sromea = ctlr->srom;
+ for(i = 0; i < 8; i++){
+ x = ctlr->srom[i];
+ if(x != ctlr->srom[15-i] || x != ctlr->srom[16+i]){
+ ctlr->sromea = &ctlr->srom[20];
+ break;
+ }
+ }
+
+ /*
+ * Fake up the SROM for the PNIC.
+ * It looks like a 21140 with a PHY.
+ * The MAC address is byte-swapped in the orginal SROM data.
+ */
+ if(ctlr->id == Pnic){
+ memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic));
+ for(i = 0; i < Eaddrlen; i += 2){
+ ctlr->srom[20+i] = ctlr->srom[i+1];
+ ctlr->srom[20+i+1] = ctlr->srom[i];
+ }
+ }
+
+ /*
+ * Next, try to find the info leaf in the SROM for media detection.
+ * If it's a non-conforming card try to match the vendor ethernet code
+ * and point p at a fake info leaf with compact 21140 entries.
+ */
+ if(ctlr->sromea == ctlr->srom){
+ p = nil;
+ for(i = 0; leaf21140[i] != nil; i++){
+ if(memcmp(leaf21140[i], ctlr->sromea, 3) == 0){
+ p = &leaf21140[i][4];
+ break;
+ }
+ }
+ if(p == nil)
+ return -1;
+ }
+ else
+ p = &ctlr->srom[(ctlr->srom[28]<<8)|ctlr->srom[27]];
+
+ /*
+ * Set up the info needed for later media detection.
+ * For the 21140, set the general-purpose mask in CSR12.
+ * The info block entries are stored in order of increasing
+ * precedence, so detection will work backwards through the
+ * stored indexes into ctlr->srom.
+ * If an entry is found which matches the selected connection
+ * type, save the index. Otherwise, start at the last entry.
+ * If any MII entries are found (type 1 and 3 blocks), scan
+ * for PHYs.
+ */
+ ctlr->leaf = p;
+ ctlr->sct = *p++;
+ ctlr->sct |= *p++<<8;
+ if(ctlr->id != Tulip3){
+ csr32w(ctlr, 12, Gpc|*p++);
+ delay(200);
+ }
+ ctlr->k = *p++;
+ if(ctlr->k >= nelem(ctlr->infoblock))
+ ctlr->k = nelem(ctlr->infoblock)-1;
+ ctlr->sctk = ctlr->k-1;
+ phy = 0;
+ for(k = 0; k < ctlr->k; k++){
+ ctlr->infoblock[k] = p;
+ /*
+ * The RAMIX PMC665 has a badly-coded SROM,
+ * hence the test for 21143 and type 3.
+ */
+ if((*p & 0x80) || (ctlr->id == Tulip3 && *(p+1) == 3)){
+ *p |= 0x80;
+ if(*(p+1) == 1 || *(p+1) == 3)
+ phy = 1;
+ if(*(p+1) == 5)
+ ctlr->type5block = p;
+ p += (*p & ~0x80)+1;
+ }
+ else{
+ debug("type0: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
+ p[0], p[1], p[2], p[3]);
+ if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
+ ctlr->sctk = k;
+ p += 4;
+ }
+ }
+ ctlr->curk = ctlr->sctk;
+ debug("sct 0x%uX medium 0x%uX k %d curk %d phy %d\n",
+ ctlr->sct, ctlr->medium, ctlr->k, ctlr->curk, phy);
+
+ if(phy){
+ x = 0;
+ for(k = 0; k < nelem(ctlr->phy); k++){
+ if((oui = miir(ctlr, k, 2)) == -1 || oui == 0)
+ continue;
+ if(DEBUG){
+ oui = (oui & 0x3FF)<<6;
+ oui |= miir(ctlr, k, 3)>>10;
+ miir(ctlr, k, 1);
+ debug("phy%d: index %d oui %uX reg1 %uX\n",
+ x, k, oui, miir(ctlr, k, 1));
+ USED(oui);
+ }
+ ctlr->phy[x] = k;
+ }
+ }
+
+ ctlr->fd = 0;
+ ctlr->medium = -1;
+
+ return 0;
+}
+
+static void
+dec2114xpci(void)
+{
+ Ctlr *ctlr;
+ Pcidev *p;
+ int x;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+ switch((p->did<<16)|p->vid){
+ default:
+ continue;
+
+ case Tulip3: /* 21143 */
+ /*
+ * Exit sleep mode.
+ */
+ x = pcicfgr32(p, 0x40);
+ x &= ~0xc0000000;
+ pcicfgw32(p, 0x40, x);
+ /*FALLTHROUGH*/
+
+ case Pnic: /* PNIC */
+ case Pnic2: /* PNIC-II */
+ case Tulip0: /* 21140 */
+ break;
+ }
+
+ /*
+ * bar[0] is the I/O port register address and
+ * bar[1] is the memory-mapped register address.
+ */
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = p->mem[0].bar & ~0x01;
+ ctlr->pcidev = p;
+ ctlr->id = (p->did<<16)|p->vid;
+
+ if(ioalloc(ctlr->port, p->mem[0].size, 0, "dec2114x") < 0){
+ print("dec2114x: port 0x%uX in use\n", ctlr->port);
+ free(ctlr);
+ continue;
+ }
+
+ /*
+ * Some cards (e.g. ANA-6910FX) seem to need the Ps bit
+ * set or they don't always work right after a hardware
+ * reset.
+ */
+ csr32w(ctlr, 6, Mbo|Ps);
+ softreset(ctlr);
+
+ if(srom(ctlr)){
+ iofree(ctlr->port);
+ free(ctlr);
+ continue;
+ }
+
+ switch(ctlr->id){
+ default:
+ break;
+
+ case Pnic: /* PNIC */
+ /*
+ * Turn off the jabber timer.
+ */
+ csr32w(ctlr, 15, 0x00000001);
+ break;
+ }
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+}
+
+static int
+reset(Ether* ether)
+{
+ Ctlr *ctlr;
+ int i, x;
+ uchar ea[Eaddrlen];
+ static int scandone;
+
+ if(scandone == 0){
+ dec2114xpci();
+ scandone = 1;
+ }
+
+ /*
+ * Any adapter matches if no ether->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(ether->port == 0 || ether->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ ether->ctlr = ctlr;
+ ether->port = ctlr->port;
+// ether->irq = ctlr->pcidev->intl;
+ether->irq = 2; /* arrrrrgh */
+ ether->tbdf = ctlr->pcidev->tbdf;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to
+ * loading the station address in the hardware.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0)
+ memmove(ether->ea, ctlr->sromea, Eaddrlen);
+
+ /*
+ * Look for a medium override in case there's no autonegotiation
+ * (no MII) or the autonegotiation fails.
+ */
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrcmp(ether->opt[i], "FD") == 0){
+ ctlr->fd = 1;
+ continue;
+ }
+ for(x = 0; x < nelem(mediatable); x++){
+ debug("compare <%s> <%s>\n", mediatable[x],
+ ether->opt[i]);
+ if(cistrcmp(mediatable[x], ether->opt[i]))
+ continue;
+ ctlr->medium = x;
+
+ switch(ctlr->medium){
+ default:
+ ctlr->fd = 0;
+ break;
+
+ case 0x04: /* 10BASE-TFD */
+ case 0x05: /* 100BASE-TXFD */
+ case 0x08: /* 100BASE-FXFD */
+ ctlr->fd = 1;
+ break;
+ }
+ break;
+ }
+ }
+
+ ether->mbps = media(ether, 1);
+
+ /*
+ * Initialise descriptor rings, ethernet address.
+ */
+ ctlr->nrdr = Nrde;
+ ctlr->ntdr = Ntde;
+ pcisetbme(ctlr->pcidev);
+ ctlrinit(ether);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->ifstat = ifstat;
+
+ ether->arg = ether;
+ ether->promiscuous = promiscuous;
+
+ return 0;
+}
+
+void
+ether2114xlink(void)
+{
+ addethercard("21140", reset);
+ addethercard("2114x", reset);
+}
diff --git a/sys/src/9/mtx/etherif.h b/sys/src/9/mtx/etherif.h
new file mode 100755
index 000000000..34fa2cc02
--- /dev/null
+++ b/sys/src/9/mtx/etherif.h
@@ -0,0 +1,35 @@
+enum {
+ MaxEther = 24,
+ Ntypes = 8,
+};
+
+typedef struct Ether Ether;
+struct Ether {
+ ISAConf; /* hardware info */
+
+ int ctlrno;
+ int tbdf; /* type+busno+devno+funcno */
+ int minmtu;
+ int maxmtu;
+ uchar ea[Eaddrlen];
+
+ void (*attach)(Ether*); /* filled in by reset routine */
+ void (*transmit)(Ether*);
+ void (*interrupt)(Ureg*, void*);
+ long (*ifstat)(Ether*, void*, long, ulong);
+ long (*ctl)(Ether*, void*, long); /* custom ctl messages */
+ void *ctlr;
+
+ Queue* oq;
+
+ Netif;
+};
+
+extern Block* etheriq(Ether*, Block*, int);
+extern void addethercard(char*, int(*)(Ether*));
+extern ulong ethercrc(uchar*, int);
+
+#define NEXT(x, l) (((x)+1)%(l))
+#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
diff --git a/sys/src/9/mtx/fns.h b/sys/src/9/mtx/fns.h
new file mode 100755
index 000000000..d88d0d636
--- /dev/null
+++ b/sys/src/9/mtx/fns.h
@@ -0,0 +1,110 @@
+#include "../port/portfns.h"
+
+ulong cankaddr(ulong);
+int cistrcmp(char*, char*);
+int cistrncmp(char*, char*, int);
+void clockinit(void);
+void clockintr(Ureg*);
+void clockintrsched(void);
+int cmpswap(long*, long, long);
+#define coherence() eieio()
+void cpuidprint(void);
+#define cycles(x) do{}while(0)
+void dcflush(void*, ulong);
+void delay(int);
+void dumpregs(Ureg*);
+void delayloopinit(void);
+void eieio(void);
+void evenaddr(ulong);
+void faultpower(Ureg*, ulong addr, int read);
+void fprestore(FPsave*);
+void fpsave(FPsave*);
+char* getconf(char*);
+ulong getdar(void);
+ulong getdec(void);
+ulong getdsisr(void);
+ulong gethid0(void);
+ulong gethid1(void);
+ulong getmsr(void);
+ulong getpvr(void);
+void gotopc(ulong);
+int havetimer(void);
+void hwintrinit(void);
+void i8250console(void);
+void i8259init(void);
+int i8259intack(void);
+int i8259enable(Vctl*);
+int i8259vecno(int);
+int i8259disable(int);
+void icflush(void*, ulong);
+#define idlehands() /* nothing to do in the runproc */
+int inb(int);
+void insb(int, void*, int);
+ushort ins(int);
+void inss(int, void*, int);
+ulong inl(int);
+void insl(int, void*, int);
+void intr(Ureg*);
+void intrenable(int, void (*)(Ureg*, void*), void*, int, char*);
+int ioalloc(int, int, int, char*);
+void iofree(int);
+void ioinit(void);
+int iprint(char*, ...);
+int isaconfig(char*, int, ISAConf*);
+void kbdinit(void);
+#define kexit(a)
+#define kmapinval()
+void links(void);
+void mmuinit(void);
+void mmusweep(void*);
+void mpicdisable(int);
+void mpicenable(int, Vctl*);
+int mpiceoi(int);
+int mpicintack(void);
+int newmmupid(void);
+void outb(int, int);
+void outsb(int, void*, int);
+void outs(int, ushort);
+void outss(int, void*, int);
+void outl(int, ulong);
+void outsl(int, void*, int);
+int pciscan(int, Pcidev **);
+ulong pcibarsize(Pcidev *, int);
+int pcicfgr8(Pcidev*, int);
+int pcicfgr16(Pcidev*, int);
+int pcicfgr32(Pcidev*, int);
+void pcicfgw8(Pcidev*, int, int);
+void pcicfgw16(Pcidev*, int, int);
+void pcicfgw32(Pcidev*, int, int);
+void pciclrbme(Pcidev*);
+void pcihinv(Pcidev*);
+uchar pciipin(Pcidev *, uchar);
+Pcidev* pcimatch(Pcidev*, int, int);
+Pcidev* pcimatchtbdf(int);
+void pcireset(void);
+void pcisetbme(Pcidev*);
+#define procrestore(p)
+void procsave(Proc*);
+void procsetup(Proc*);
+void putdec(ulong);
+void puthid0(ulong);
+void puthid1(ulong);
+void putmsr(ulong);
+void putsdr1(ulong);
+void putsr(int, ulong);
+void raveninit(void);
+void sync(void);
+int tas(void*);
+void timeradd(Timer *);
+void timerdel(Timer *);
+void touser(void*);
+void trapinit(void);
+void trapvec(void);
+void tlbflush(ulong);
+void tlbflushall(void);
+#define userureg(ur) (((ur)->status & MSR_PR) != 0)
+void watchreset(void);
+
+#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
+#define KADDR(a) ((void*)((ulong)(a)|KZERO))
+#define PADDR(a) ((ulong)(a)&~KZERO)
diff --git a/sys/src/9/mtx/i8259.c b/sys/src/9/mtx/i8259.c
new file mode 100755
index 000000000..605cd3fc0
--- /dev/null
+++ b/sys/src/9/mtx/i8259.c
@@ -0,0 +1,213 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ * 8259 interrupt controllers
+ */
+enum
+{
+ Int0ctl= 0x20, /* control port (ICW1, OCW2, OCW3) */
+ Int0aux= 0x21, /* everything else (ICW2, ICW3, ICW4, OCW1) */
+ Int1ctl= 0xA0, /* control port */
+ Int1aux= 0xA1, /* everything else (ICW2, ICW3, ICW4, OCW1) */
+
+ Icw1= 0x10, /* select bit in ctl register */
+ Ocw2= 0x00,
+ Ocw3= 0x08,
+
+ EOI= 0x20, /* non-specific end of interrupt */
+
+ Elcr1= 0x4D0, /* Edge/Level Triggered Register */
+ Elcr2= 0x4D1,
+};
+
+static Lock i8259lock;
+static int i8259mask = 0xFFFF; /* disabled interrupts */
+int i8259elcr; /* mask of level-triggered interrupts */
+
+void
+i8259init(void)
+{
+ int x;
+
+ ioalloc(Int0ctl, 2, 0, "i8259.0");
+ ioalloc(Int1ctl, 2, 0, "i8259.1");
+ ilock(&i8259lock);
+
+ /*
+ * Set up the first 8259 interrupt processor.
+ * Make 8259 interrupts start at CPU vector VectorPIC.
+ * Set the 8259 as master with edge triggered
+ * input with fully nested interrupts.
+ */
+ outb(Int0ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered,
+ ICW4 will be sent */
+ outb(Int0aux, VectorPIC); /* ICW2 - interrupt vector offset */
+ outb(Int0aux, 0x04); /* ICW3 - have slave on level 2 */
+ outb(Int0aux, 0x01); /* ICW4 - 8086 mode, not buffered */
+
+ /*
+ * Set up the second 8259 interrupt processor.
+ * Make 8259 interrupts start at CPU vector VectorPIC+8.
+ * Set the 8259 as slave with edge triggered
+ * input with fully nested interrupts.
+ */
+ outb(Int1ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered,
+ ICW4 will be sent */
+ outb(Int1aux, VectorPIC+8); /* ICW2 - interrupt vector offset */
+ outb(Int1aux, 0x02); /* ICW3 - I am a slave on level 2 */
+ outb(Int1aux, 0x01); /* ICW4 - 8086 mode, not buffered */
+ outb(Int1aux, (i8259mask>>8) & 0xFF);
+
+ /*
+ * pass #2 8259 interrupts to #1
+ */
+ i8259mask &= ~0x04;
+ outb(Int0aux, i8259mask & 0xFF);
+
+ /*
+ * Set Ocw3 to return the ISR when ctl read.
+ * After initialisation status read is set to IRR.
+ * Read IRR first to possibly deassert an outstanding
+ * interrupt.
+ */
+ inb(Int0ctl);
+ outb(Int0ctl, Ocw3|0x03);
+ inb(Int1ctl);
+ outb(Int1ctl, Ocw3|0x03);
+
+ /*
+ * Check for Edge/Level register.
+ * This check may not work for all chipsets.
+ * First try a non-intrusive test - the bits for
+ * IRQs 13, 8, 2, 1 and 0 must be edge (0). If
+ * that's OK try a R/W test.
+ */
+ x = (inb(Elcr2)<<8)|inb(Elcr1);
+ if(!(x & 0x2107)){
+ outb(Elcr1, 0);
+ if(inb(Elcr1) == 0){
+ outb(Elcr1, 0x20);
+ if(inb(Elcr1) == 0x20)
+ i8259elcr = x;
+ outb(Elcr1, x & 0xFF);
+ print("ELCR: %4.4uX\n", i8259elcr);
+ }
+ }
+ iunlock(&i8259lock);
+}
+
+int
+i8259isr(int vno)
+{
+ int irq, isr;
+
+ if(vno < VectorPIC || vno > VectorPIC+MaxIrqPIC)
+ return 0;
+ irq = vno-VectorPIC;
+
+ /*
+ * tell the 8259 that we're done with the
+ * highest level interrupt (interrupts are still
+ * off at this point)
+ */
+ ilock(&i8259lock);
+ isr = inb(Int0ctl);
+ outb(Int0ctl, EOI);
+ if(irq >= 8){
+ isr |= inb(Int1ctl)<<8;
+ outb(Int1ctl, EOI);
+ }
+ iunlock(&i8259lock);
+
+ return isr & (1<<irq);
+}
+
+int
+i8259enable(Vctl* v)
+{
+ int irq, irqbit;
+
+ /*
+ * Given an IRQ, enable the corresponding interrupt in the i8259
+ * and return the vector to be used. The i8259 is set to use a fixed
+ * range of vectors starting at VectorPIC.
+ */
+ irq = v->irq;
+ if(irq < 0 || irq > MaxIrqPIC){
+ print("i8259enable: irq %d out of range\n", irq);
+ return -1;
+ }
+ irqbit = 1<<irq;
+
+ ilock(&i8259lock);
+ if(!(i8259mask & irqbit) && !(i8259elcr & irqbit)){
+ print("i8259enable: irq %d shared but not level\n", irq);
+ iunlock(&i8259lock);
+ return -1;
+ }
+ i8259mask &= ~irqbit;
+ if(irq < 8)
+ outb(Int0aux, i8259mask & 0xFF);
+ else
+ outb(Int1aux, (i8259mask>>8) & 0xFF);
+
+ if(i8259elcr & irqbit)
+ v->eoi = i8259isr;
+ else
+ v->isr = i8259isr;
+ iunlock(&i8259lock);
+
+ return VectorPIC+irq;
+}
+
+int
+i8259intack(void)
+{
+ int irq;
+
+ outb(Int0ctl, Ocw3|0x07); /* intr ack on first 8259 */
+ irq = inb(Int0ctl) & 7;
+ if(irq == 2) { /* cascade */
+ outb(Int1ctl, Ocw3|0x07); /* intr ack on second 8259 */
+ irq = (inb(Int1ctl) & 7) + 8;
+ }
+ return irq+VectorPIC;
+}
+
+int
+i8259vecno(int irq)
+{
+ return VectorPIC+irq;
+}
+
+int
+i8259disable(int irq)
+{
+ int irqbit;
+
+ /*
+ * Given an IRQ, disable the corresponding interrupt
+ * in the 8259.
+ */
+ if(irq < 0 || irq > MaxIrqPIC){
+ print("i8259disable: irq %d out of range\n", irq);
+ return -1;
+ }
+ irqbit = 1<<irq;
+
+ ilock(&i8259lock);
+ if(!(i8259mask & irqbit)){
+ i8259mask |= irqbit;
+ if(irq < 8)
+ outb(Int0aux, i8259mask & 0xFF);
+ else
+ outb(Int1aux, (i8259mask>>8) & 0xFF);
+ }
+ iunlock(&i8259lock);
+ return 0;
+}
diff --git a/sys/src/9/mtx/inb.s b/sys/src/9/mtx/inb.s
new file mode 100755
index 000000000..9f32a8de9
--- /dev/null
+++ b/sys/src/9/mtx/inb.s
@@ -0,0 +1,119 @@
+#include "mem.h"
+
+#define BDNZ BC 16,0,
+#define BDNE BC 0,2,
+
+TEXT inb(SB), $0
+ OR $IOMEM, R3
+ MOVBZ (R3), R3
+ RETURN
+
+TEXT insb(SB), $0
+ MOVW v+4(FP), R4
+ MOVW n+8(FP), R5
+ MOVW R5, CTR
+ OR $IOMEM, R3
+ SUB $1, R4
+insb1:
+ MOVBZ (R3), R7
+ MOVBU R7, 1(R4)
+ BDNZ insb1
+ RETURN
+
+TEXT outb(SB), $0
+ MOVW v+4(FP), R4
+ OR $IOMEM, R3
+ EIEIO
+ MOVB R4, (R3)
+ RETURN
+
+TEXT outsb(SB), $0
+ MOVW v+4(FP), R4
+ MOVW n+8(FP), R5
+ MOVW R5, CTR
+ OR $IOMEM, R3
+ SUB $1, R4
+outsb1:
+ EIEIO
+ MOVBZU 1(R4), R7
+ MOVB R7, (R3)
+ BDNZ outsb1
+ RETURN
+
+TEXT ins(SB), $0
+ OR $IOMEM, R3
+ EIEIO
+ MOVHBR (R3), R3
+ RETURN
+
+TEXT inss(SB), $0
+ MOVW v+4(FP), R4
+ MOVW n+8(FP), R5
+ MOVW R5, CTR
+ OR $IOMEM, R3
+ SUB $2, R4
+inss1:
+ EIEIO
+ MOVHZ (R3), R7
+ MOVHU R7, 2(R4)
+ BDNZ inss1
+ RETURN
+
+TEXT outs(SB), $0
+ MOVW v+4(FP), R4
+ OR $IOMEM, R3
+ EIEIO
+ MOVHBR R4, (R3)
+ RETURN
+
+TEXT outss(SB), $0
+ MOVW v+4(FP), R4
+ MOVW n+8(FP), R5
+ MOVW R5, CTR
+ OR $IOMEM, R3
+ SUB $2, R4
+outss1:
+ EIEIO
+ MOVHZU 2(R4), R7
+ MOVH R7, (R3)
+ BDNZ outss1
+ RETURN
+
+TEXT inl(SB), $0
+ OR $IOMEM, R3
+ EIEIO
+ MOVWBR (R3), R3
+ RETURN
+
+TEXT insl(SB), $0
+ MOVW v+4(FP), R4
+ MOVW n+8(FP), R5
+ MOVW R5, CTR
+ OR $IOMEM, R3
+ SUB $4, R4
+insl1:
+ EIEIO
+ MOVW (R3), R7
+ MOVWU R7, 4(R4)
+ BDNZ insl1
+ RETURN
+
+TEXT outl(SB), $0
+ MOVW v+4(FP), R4
+ OR $IOMEM, R3
+ EIEIO
+ MOVWBR R4, (R3)
+ RETURN
+
+TEXT outsl(SB), $0
+ MOVW v+4(FP), R4
+ MOVW n+8(FP), R5
+ MOVW R5, CTR
+ OR $IOMEM, R3
+ SUB $4, R4
+outsl1:
+ EIEIO
+ MOVWU 4(R4), R7
+ MOVW R7, (R3)
+ BDNZ outsl1
+ RETURN
diff --git a/sys/src/9/mtx/initcode b/sys/src/9/mtx/initcode
new file mode 100755
index 000000000..1d846abe5
--- /dev/null
+++ b/sys/src/9/mtx/initcode
@@ -0,0 +1,25 @@
+#include "/sys/src/libc/9syscall/sys.h"
+
+/*
+ * we pass in the argument of the exec parameters as 0(FP)
+ */
+
+TEXT main(SB),$8
+
+ MOVW $setSB(SB), R2
+ MOVW $boot(SB), R3
+ ADD $12, R1, R4 /* get a pointer to 0(FP) */
+ MOVW R3, 4(R1)
+ MOVW R4, 8(R1)
+ MOVW $EXEC, R3
+ SYSCALL
+
+ /* should never get here */
+loop:
+ BR loop
+
+DATA boot+0(SB)/5,$"/boot"
+DATA boot+5(SB)/5,$"/boot"
+DATA bootv+0(SB)/4,$boot+6(SB)
+GLOBL boot+0(SB),$11
+GLOBL bootv+0(SB),$8
diff --git a/sys/src/9/mtx/io.h b/sys/src/9/mtx/io.h
new file mode 100755
index 000000000..59f13d815
--- /dev/null
+++ b/sys/src/9/mtx/io.h
@@ -0,0 +1,180 @@
+enum {
+ IrqCLOCK = 0,
+ IrqKBD = 1,
+ IrqUART1 = 3,
+ IrqUART0 = 4,
+ IrqPCMCIA = 5,
+ IrqFLOPPY = 6,
+ IrqLPT = 7,
+ IrqIRQ7 = 7,
+ IrqAUX = 12, /* PS/2 port */
+ IrqIRQ13 = 13, /* coprocessor on 386 */
+ IrqATA0 = 14,
+ IrqATA1 = 15,
+ MaxIrqPIC = 15,
+
+ VectorPIC = 32,
+ MaxVectorPIC = VectorPIC+MaxIrqPIC,
+};
+
+typedef struct Vctl {
+ Vctl* next; /* handlers on this vector */
+
+ char name[KNAMELEN]; /* of driver */
+ int isintr; /* interrupt or fault/trap */
+ int irq;
+ int tbdf;
+ int (*isr)(int); /* get isr bit for this irq */
+ int (*eoi)(int); /* eoi */
+
+ void (*f)(Ureg*, void*); /* handler to call */
+ void* a; /* argument to call it with */
+} Vctl;
+
+enum {
+ BusCBUS = 0, /* Corollary CBUS */
+ BusCBUSII, /* Corollary CBUS II */
+ BusEISA, /* Extended ISA */
+ BusFUTURE, /* IEEE Futurebus */
+ BusINTERN, /* Internal bus */
+ BusISA, /* Industry Standard Architecture */
+ BusMBI, /* Multibus I */
+ BusMBII, /* Multibus II */
+ BusMCA, /* Micro Channel Architecture */
+ BusMPI, /* MPI */
+ BusMPSA, /* MPSA */
+ BusNUBUS, /* Apple Macintosh NuBus */
+ BusPCI, /* Peripheral Component Interconnect */
+ BusPCMCIA, /* PC Memory Card International Association */
+ BusTC, /* DEC TurboChannel */
+ BusVL, /* VESA Local bus */
+ BusVME, /* VMEbus */
+ BusXPRESS, /* Express System Bus */
+};
+
+#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
+#define BUSFNO(tbdf) (((tbdf)>>8)&0x07)
+#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F)
+#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF)
+#define BUSTYPE(tbdf) ((tbdf)>>24)
+#define BUSDF(tbdf) ((tbdf)&0x000FF00)
+#define BUSBDF(tbdf) ((tbdf)&0x0FFFF00)
+#define BUSUNKNOWN (-1)
+
+enum {
+ MaxEISA = 16,
+ EISAconfig = 0xC80,
+};
+
+/*
+ * PCI support code.
+ */
+enum { /* type 0 and type 1 pre-defined header */
+ PciVID = 0x00, /* vendor ID */
+ PciDID = 0x02, /* device ID */
+ PciPCR = 0x04, /* command */
+ PciPSR = 0x06, /* status */
+ PciRID = 0x08, /* revision ID */
+ PciCCRp = 0x09, /* programming interface class code */
+ PciCCRu = 0x0A, /* sub-class code */
+ PciCCRb = 0x0B, /* base class code */
+ PciCLS = 0x0C, /* cache line size */
+ PciLTR = 0x0D, /* latency timer */
+ PciHDT = 0x0E, /* header type */
+ PciBST = 0x0F, /* BIST */
+
+ PciBAR0 = 0x10, /* base address */
+ PciBAR1 = 0x14,
+
+ PciINTL = 0x3C, /* interrupt line */
+ PciINTP = 0x3D, /* interrupt pin */
+};
+
+enum { /* type 0 pre-defined header */
+ PciCIS = 0x28, /* cardbus CIS pointer */
+ PciSVID = 0x2C, /* subsystem vendor ID */
+ PciSID = 0x2E, /* cardbus CIS pointer */
+ PciEBAR0 = 0x30, /* expansion ROM base address */
+ PciMGNT = 0x3E, /* burst period length */
+ PciMLT = 0x3F, /* maximum latency between bursts */
+};
+
+enum { /* type 1 pre-defined header */
+ PciPBN = 0x18, /* primary bus number */
+ PciSBN = 0x19, /* secondary bus number */
+ PciUBN = 0x1A, /* subordinate bus number */
+ PciSLTR = 0x1B, /* secondary latency timer */
+ PciIBR = 0x1C, /* I/O base */
+ PciILR = 0x1D, /* I/O limit */
+ PciSPSR = 0x1E, /* secondary status */
+ PciMBR = 0x20, /* memory base */
+ PciMLR = 0x22, /* memory limit */
+ PciPMBR = 0x24, /* prefetchable memory base */
+ PciPMLR = 0x26, /* prefetchable memory limit */
+ PciPUBR = 0x28, /* prefetchable base upper 32 bits */
+ PciPULR = 0x2C, /* prefetchable limit upper 32 bits */
+ PciIUBR = 0x30, /* I/O base upper 16 bits */
+ PciIULR = 0x32, /* I/O limit upper 16 bits */
+ PciEBAR1 = 0x28, /* expansion ROM base address */
+ PciBCR = 0x3E, /* bridge control register */
+};
+
+enum { /* type 2 pre-defined header */
+ PciCBExCA = 0x10,
+ PciCBSPSR = 0x16,
+ PciCBPBN = 0x18, /* primary bus number */
+ PciCBSBN = 0x19, /* secondary bus number */
+ PciCBUBN = 0x1A, /* subordinate bus number */
+ PciCBSLTR = 0x1B, /* secondary latency timer */
+ PciCBMBR0 = 0x1C,
+ PciCBMLR0 = 0x20,
+ PciCBMBR1 = 0x24,
+ PciCBMLR1 = 0x28,
+ PciCBIBR0 = 0x2C, /* I/O base */
+ PciCBILR0 = 0x30, /* I/O limit */
+ PciCBIBR1 = 0x34, /* I/O base */
+ PciCBILR1 = 0x38, /* I/O limit */
+ PciCBSVID = 0x40, /* subsystem vendor ID */
+ PciCBSID = 0x42, /* subsystem ID */
+ PciCBLMBAR = 0x44, /* legacy mode base address */
+};
+
+typedef struct Pcisiz Pcisiz;
+struct Pcisiz
+{
+ Pcidev* dev;
+ int siz;
+ int bar;
+};
+
+typedef struct Pcidev Pcidev;
+typedef struct Pcidev {
+ int tbdf; /* type+bus+device+function */
+ ushort vid; /* vendor ID */
+ ushort did; /* device ID */
+
+ uchar rid;
+ uchar ccrp;
+ uchar ccru;
+ uchar ccrb;
+
+ struct {
+ ulong bar; /* base address */
+ int size;
+ } mem[6];
+
+ uchar intl; /* interrupt line */
+
+ Pcidev* list;
+ Pcidev* link; /* next device on this bno */
+
+ Pcidev* bridge; /* down a bus */
+ struct {
+ ulong bar;
+ int size;
+ } ioa, mema;
+ ulong pcr;
+};
+
+#define PCIWINDOW 0x80000000
+#define PCIWADDR(va) (PADDR(va)+PCIWINDOW)
diff --git a/sys/src/9/mtx/kbd.c b/sys/src/9/mtx/kbd.c
new file mode 100755
index 000000000..fe96fc345
--- /dev/null
+++ b/sys/src/9/mtx/kbd.c
@@ -0,0 +1,435 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+enum {
+ Data= 0x60, /* data port */
+
+ Status= 0x64, /* status port */
+ Inready= 0x01, /* input character ready */
+ Outbusy= 0x02, /* output busy */
+ Sysflag= 0x04, /* system flag */
+ Cmddata= 0x08, /* cmd==0, data==1 */
+ Inhibit= 0x10, /* keyboard/mouse inhibited */
+ Minready= 0x20, /* mouse character ready */
+ Rtimeout= 0x40, /* general timeout */
+ Parity= 0x80,
+
+ Cmd= 0x64, /* command port (write only) */
+
+ Spec= 0x80,
+
+ PF= Spec|0x20, /* num pad function key */
+ View= Spec|0x00, /* view (shift window up) */
+ KF= 0xF000, /* function key (begin Unicode private space) */
+ Shift= Spec|0x60,
+ Break= Spec|0x61,
+ Ctrl= Spec|0x62,
+ Latin= Spec|0x63,
+ Caps= Spec|0x64,
+ Num= Spec|0x65,
+ Middle= Spec|0x66,
+ No= 0x00, /* peter */
+
+ Home= KF|13,
+ Up= KF|14,
+ Pgup= KF|15,
+ Print= KF|16,
+ Left= KF|17,
+ Right= KF|18,
+ End= '\r',
+ Down= View,
+ Pgdown= KF|19,
+ Ins= KF|20,
+ Del= 0x7F,
+ Scroll= KF|21,
+};
+
+/*
+ * The codes at 0x79 and 0x81 are produed by the PFU Happy Hacking keyboard.
+ * A 'standard' keyboard doesn't produce anything above 0x58.
+ */
+Rune kbtab[] =
+{
+[0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
+[0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
+[0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
+[0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
+[0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+[0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
+[0x30] 'b', 'n', 'm', ',', '.', '/', Shift, '*',
+[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',
+[0x48] '8', '9', '-', '4', '5', '6', '+', '1',
+[0x50] '2', '3', '0', '.', No, No, No, KF|11,
+[0x58] KF|12, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, View, No, Up, No, No, No, No,
+};
+
+Rune kbtabshift[] =
+{
+[0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
+[0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
+[0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
+[0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
+[0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
+[0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
+[0x30] 'B', 'N', 'M', '<', '>', '?', Shift, '*',
+[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',
+[0x48] '8', '9', '-', '4', '5', '6', '+', '1',
+[0x50] '2', '3', '0', '.', No, No, No, KF|11,
+[0x58] KF|12, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, Up, No, Up, No, No, No, No,
+};
+
+Rune kbtabesc1[] =
+{
+[0x00] No, No, No, No, No, No, No, No,
+[0x08] No, No, No, No, No, No, No, No,
+[0x10] No, No, No, No, No, No, No, No,
+[0x18] No, No, No, No, '\n', Ctrl, No, No,
+[0x20] No, No, No, No, No, No, No, No,
+[0x28] No, No, Shift, No, No, No, No, No,
+[0x30] No, No, No, No, No, '/', No, Print,
+[0x38] Latin, No, No, No, No, No, No, No,
+[0x40] No, No, No, No, No, No, Break, Home,
+[0x48] Up, Pgup, No, Left, No, Right, No, End,
+[0x50] Down, Pgdown, Ins, Del, No, No, No, No,
+[0x58] No, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, Up, No, No, No, No, No, No,
+};
+
+enum
+{
+ /* controller command byte */
+ Cscs1= (1<<6), /* scan code set 1 */
+ Cauxdis= (1<<5), /* mouse disable */
+ Ckbddis= (1<<4), /* kbd disable */
+ Csf= (1<<2), /* system flag */
+ Cauxint= (1<<1), /* mouse interrupt enable */
+ Ckbdint= (1<<0), /* kbd interrupt enable */
+};
+
+static Lock i8042lock;
+static uchar ccc;
+static void (*auxputc)(int, int);
+
+/*
+ * wait for output no longer busy
+ */
+static int
+outready(void)
+{
+ int tries;
+
+ for(tries = 0; (inb(Status) & Outbusy); tries++){
+ if(tries > 500)
+ return -1;
+ delay(2);
+ }
+ return 0;
+}
+
+/*
+ * wait for input
+ */
+static int
+inready(void)
+{
+ int tries;
+
+ for(tries = 0; !(inb(Status) & Inready); tries++){
+ if(tries > 500)
+ return -1;
+ delay(2);
+ }
+ return 0;
+}
+
+/*
+ * ask 8042 to reset the machine
+ */
+void
+i8042reset(void)
+{
+ ushort *s = KADDR(0x472);
+ int i, x;
+
+ *s = 0x1234; /* BIOS warm-boot flag */
+
+ /*
+ * newer reset the machine command
+ */
+ outready();
+ outb(Cmd, 0xFE);
+ outready();
+
+ /*
+ * Pulse it by hand (old somewhat reliable)
+ */
+ x = 0xDF;
+ for(i = 0; i < 5; i++){
+ x ^= 1;
+ outready();
+ outb(Cmd, 0xD1);
+ outready();
+ outb(Data, x); /* toggle reset */
+ delay(100);
+ }
+}
+
+int
+i8042auxcmd(int cmd)
+{
+ unsigned int c;
+ int tries;
+
+ c = 0;
+ tries = 0;
+
+ ilock(&i8042lock);
+ do{
+ if(tries++ > 2)
+ break;
+ if(outready() < 0)
+ break;
+ outb(Cmd, 0xD4);
+ if(outready() < 0)
+ break;
+ outb(Data, cmd);
+ if(outready() < 0)
+ break;
+ if(inready() < 0)
+ break;
+ c = inb(Data);
+ } while(c == 0xFE || c == 0);
+ iunlock(&i8042lock);
+
+ if(c != 0xFA){
+ print("i8042: %2.2ux returned to the %2.2ux command\n", c, cmd);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * keyboard interrupt
+ */
+static void
+i8042intr(Ureg*, void*)
+{
+ int s, c, i;
+ static int esc1, esc2;
+ static int alt, caps, ctl, num, shift;
+ static int collecting, nk;
+ static Rune kc[5];
+ int keyup;
+
+ /*
+ * get status
+ */
+ lock(&i8042lock);
+ s = inb(Status);
+ if(!(s&Inready)){
+ unlock(&i8042lock);
+ return;
+ }
+
+ /*
+ * get the character
+ */
+ c = inb(Data);
+ unlock(&i8042lock);
+
+ /*
+ * if it's the aux port...
+ */
+ if(s & Minready){
+ if(auxputc != nil)
+ auxputc(c, shift);
+ return;
+ }
+
+ /*
+ * e0's is the first of a 2 character sequence
+ */
+ if(c == 0xe0){
+ esc1 = 1;
+ return;
+ } else if(c == 0xe1){
+ esc2 = 2;
+ return;
+ }
+
+ keyup = c&0x80;
+ c &= 0x7f;
+ if(c > sizeof kbtab){
+ c |= keyup;
+ if(c != 0xFF) /* these come fairly often: CAPSLOCK U Y */
+ print("unknown key %ux\n", c);
+ return;
+ }
+
+ if(esc1){
+ c = kbtabesc1[c];
+ esc1 = 0;
+ } else if(esc2){
+ esc2--;
+ return;
+ } else if(shift)
+ c = kbtabshift[c];
+ else
+ c = kbtab[c];
+
+ if(caps && c<='z' && c>='a')
+ c += 'A' - 'a';
+
+ /*
+ * keyup only important for shifts
+ */
+ if(keyup){
+ switch(c){
+ case Latin:
+ alt = 0;
+ break;
+ case Shift:
+ shift = 0;
+ break;
+ case Ctrl:
+ ctl = 0;
+ break;
+ }
+ return;
+ }
+
+ /*
+ * normal character
+ */
+ if(!(c & (Spec|KF))){
+ if(ctl){
+ if(alt && c == Del)
+ exit(0);
+ c &= 0x1f;
+ }
+ if(!collecting){
+ kbdputc(kbdq, c);
+ return;
+ }
+ kc[nk++] = c;
+ c = latin1(kc, nk);
+ if(c < -1) /* need more keystrokes */
+ return;
+ if(c != -1) /* valid sequence */
+ kbdputc(kbdq, c);
+ else /* dump characters */
+ for(i=0; i<nk; i++)
+ kbdputc(kbdq, kc[i]);
+ nk = 0;
+ collecting = 0;
+ return;
+ } else {
+ switch(c){
+ case Caps:
+ caps ^= 1;
+ return;
+ case Num:
+ num ^= 1;
+ return;
+ case Shift:
+ shift = 1;
+ return;
+ case Latin:
+ alt = 1;
+ collecting = 1;
+ nk = 0;
+ return;
+ case Ctrl:
+ ctl = 1;
+ return;
+ }
+ }
+ kbdputc(kbdq, c);
+}
+
+void
+i8042auxenable(void (*putc)(int, int))
+{
+ char *err = "i8042: aux init failed\n";
+
+ /* enable kbd/aux xfers and interrupts */
+ ccc &= ~Cauxdis;
+ ccc |= Cauxint;
+
+ ilock(&i8042lock);
+ if(outready() < 0)
+ print(err);
+ outb(Cmd, 0x60); /* write control register */
+ if(outready() < 0)
+ print(err);
+ outb(Data, ccc);
+ if(outready() < 0)
+ print(err);
+ outb(Cmd, 0xA8); /* auxilliary device enable */
+ if(outready() < 0){
+ iunlock(&i8042lock);
+ return;
+ }
+ auxputc = putc;
+ intrenable(IrqAUX, i8042intr, 0, BUSUNKNOWN, "kbdaux");
+ iunlock(&i8042lock);
+}
+
+void
+kbdinit(void)
+{
+ int c;
+
+ kbdq = qopen(4*1024, 0, 0, 0);
+ if(kbdq == nil)
+ panic("kbdinit");
+ qnoblock(kbdq, 1);
+
+ ioalloc(Data, 1, 0, "kbd");
+ ioalloc(Cmd, 1, 0, "kbd");
+
+ intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "kbd");
+
+ /* wait for a quiescent controller */
+ while((c = inb(Status)) & (Outbusy | Inready))
+ if(c & Inready)
+ inb(Data);
+
+ /* get current controller command byte */
+ outb(Cmd, 0x20);
+ if(inready() < 0){
+ print("kbdinit: can't read ccc\n");
+ ccc = 0;
+ } else
+ ccc = inb(Data);
+
+ /* enable kbd xfers and interrupts */
+ /* disable mouse */
+ ccc &= ~Ckbddis;
+ ccc |= Csf | Ckbdint | Cscs1;
+ if(outready() < 0)
+ print("kbd init failed\n");
+ outb(Cmd, 0x60);
+ if(outready() < 0)
+ print("kbd init failed\n");
+ outb(Data, ccc);
+ outready();
+}
diff --git a/sys/src/9/mtx/l.s b/sys/src/9/mtx/l.s
new file mode 100755
index 000000000..c880c5390
--- /dev/null
+++ b/sys/src/9/mtx/l.s
@@ -0,0 +1,603 @@
+#include "mem.h"
+
+/* use of SPRG registers in save/restore */
+#define SAVER0 SPRG0
+#define SAVER1 SPRG1
+#define SAVELR SPRG2
+#define SAVEXX SPRG3
+
+/* special instruction definitions */
+#define BDNZ BC 16,0,
+#define BDNE BC 0,2,
+
+#define TLBIA WORD $((31<<26)|(307<<1))
+#define TLBSYNC WORD $((31<<26)|(566<<1))
+
+/* on some models mtmsr doesn't synchronise enough (eg, 603e) */
+#define MSRSYNC SYNC; ISYNC
+
+#define UREGSPACE (UREGSIZE+8)
+
+ TEXT start(SB), $-4
+
+ /*
+ * setup MSR
+ * turn off interrupts
+ * use 0x000 as exception prefix
+ * enable machine check
+ */
+ MOVW MSR, R3
+ MOVW $(MSR_EE|MSR_IP), R4
+ ANDN R4, R3
+ OR $(MSR_ME), R3
+ ISYNC
+ MOVW R3, MSR
+ MSRSYNC
+
+ /* except during trap handling, R0 is zero from now on */
+ MOVW $0, R0
+
+ /* setup SB for pre mmu */
+ MOVW $setSB(SB), R2
+ MOVW $KZERO, R3
+ ANDN R3, R2
+
+ BL mmuinit0(SB)
+
+ /* running with MMU on!! */
+
+ /* set R2 to correct value */
+ MOVW $setSB(SB), R2
+
+ /* debugger sets R1 to top of usable memory +1 */
+ MOVW R1, memsize(SB)
+
+ BL kfpinit(SB)
+
+ /* set up Mach */
+ MOVW $mach0(SB), R(MACH)
+ ADD $(MACHSIZE-8), R(MACH), R1 /* set stack */
+
+ MOVW R0, R(USER)
+ MOVW R0, 0(R(MACH))
+
+ BL main(SB)
+
+ RETURN /* not reached */
+
+GLOBL mach0(SB), $(MAXMACH*BY2PG)
+GLOBL memsize(SB), $4
+
+/*
+ * on return from this function we will be running in virtual mode.
+ * We set up the Block Address Translation (BAT) registers thus:
+ * 1) first 3 BATs are 256M blocks, starting from KZERO->0
+ * 2) remaining BAT maps last 256M directly
+ */
+TEXT mmuinit0(SB), $0
+ /* reset all the tlbs */
+ MOVW $64, R3
+ MOVW R3, CTR
+ MOVW $0, R4
+tlbloop:
+ TLBIE R4
+ ADD $BIT(19), R4
+ BDNZ tlbloop
+ TLBSYNC
+
+ /* KZERO -> 0 */
+ MOVW $(KZERO|(0x7ff<<2)|2), R3
+ MOVW $(PTEVALID|PTEWRITE), R4
+ MOVW R3, SPR(IBATU(0))
+ MOVW R4, SPR(IBATL(0))
+ MOVW R3, SPR(DBATU(0))
+ MOVW R4, SPR(DBATL(0))
+
+ /* KZERO+256M -> 256M */
+ ADD $(1<<28), R3
+ ADD $(1<<28), R4
+ MOVW R3, SPR(IBATU(1))
+ MOVW R4, SPR(IBATL(1))
+ MOVW R3, SPR(DBATU(1))
+ MOVW R4, SPR(DBATL(1))
+
+ /* KZERO+512M -> 512M */
+ ADD $(1<<28), R3
+ ADD $(1<<28), R4
+ MOVW R3, SPR(IBATU(2))
+ MOVW R4, SPR(IBATL(2))
+ MOVW R3, SPR(DBATU(2))
+ MOVW R4, SPR(DBATL(2))
+
+ /* direct map last block, uncached, (?guarded) */
+ MOVW $((0xf<<28)|(0x7ff<<2)|2), R3
+ MOVW $((0xf<<28)|PTE1_I|PTE1_G|PTE1_RW), R4
+ MOVW R3, SPR(DBATU(3))
+ MOVW R4, SPR(DBATL(3))
+
+ /* IBAT 3 unused */
+ MOVW R0, SPR(IBATU(3))
+ MOVW R0, SPR(IBATL(3))
+
+ /* enable MMU */
+ MOVW LR, R3
+ OR $KZERO, R3
+ MOVW R3, SPR(SRR0)
+ MOVW MSR, R4
+ OR $(MSR_IR|MSR_DR), R4
+ MOVW R4, SPR(SRR1)
+ RFI /* resume in kernel mode in caller */
+
+ RETURN
+
+TEXT kfpinit(SB), $0
+ MOVFL $0,FPSCR(7)
+ MOVFL $0xD,FPSCR(6) /* VE, OE, ZE */
+ MOVFL $0, FPSCR(5)
+ MOVFL $0, FPSCR(3)
+ MOVFL $0, FPSCR(2)
+ MOVFL $0, FPSCR(1)
+ MOVFL $0, FPSCR(0)
+
+ FMOVD $4503601774854144.0, F27
+ FMOVD $0.5, F29
+ FSUB F29, F29, F28
+ FADD F29, F29, F30
+ FADD F30, F30, F31
+ FMOVD F28, F0
+ FMOVD F28, F1
+ FMOVD F28, F2
+ FMOVD F28, F3
+ FMOVD F28, F4
+ FMOVD F28, F5
+ FMOVD F28, F6
+ FMOVD F28, F7
+ FMOVD F28, F8
+ FMOVD F28, F9
+ FMOVD F28, F10
+ FMOVD F28, F11
+ FMOVD F28, F12
+ FMOVD F28, F13
+ FMOVD F28, F14
+ FMOVD F28, F15
+ FMOVD F28, F16
+ FMOVD F28, F17
+ FMOVD F28, F18
+ FMOVD F28, F19
+ FMOVD F28, F20
+ FMOVD F28, F21
+ FMOVD F28, F22
+ FMOVD F28, F23
+ FMOVD F28, F24
+ FMOVD F28, F25
+ FMOVD F28, F26
+ RETURN
+
+TEXT splhi(SB), $0
+ MOVW LR, R31
+ MOVW R31, 4(R(MACH)) /* save PC in m->splpc */
+ MOVW MSR, R3
+ RLWNM $0, R3, $~MSR_EE, R4
+ SYNC
+ MOVW R4, MSR
+ MSRSYNC
+ RETURN
+
+TEXT splx(SB), $0
+ /* fall though */
+
+TEXT splxpc(SB), $0
+ MOVW LR, R31
+ MOVW R31, 4(R(MACH)) /* save PC in m->splpc */
+ MOVW MSR, R4
+ RLWMI $0, R3, $MSR_EE, R4
+ SYNC
+ MOVW R4, MSR
+ MSRSYNC
+ RETURN
+
+TEXT spllo(SB), $0
+ MOVW MSR, R3
+ OR $MSR_EE, R3, R4
+ SYNC
+ MOVW R4, MSR
+ MSRSYNC
+ RETURN
+
+TEXT spldone(SB), $0
+ RETURN
+
+TEXT islo(SB), $0
+ MOVW MSR, R3
+ RLWNM $0, R3, $MSR_EE, R3
+ RETURN
+
+TEXT setlabel(SB), $-4
+ MOVW LR, R31
+ MOVW R1, 0(R3)
+ MOVW R31, 4(R3)
+ MOVW $0, R3
+ RETURN
+
+TEXT gotolabel(SB), $-4
+ MOVW 4(R3), R31
+ MOVW R31, LR
+ MOVW 0(R3), R1
+ MOVW $1, R3
+ RETURN
+
+TEXT touser(SB), $-4
+ MOVW $(UTZERO+32), R5 /* header appears in text */
+ MOVW $(MSR_EE|MSR_PR|MSR_ME|MSR_IR|MSR_DR|MSR_RI), R4
+ MOVW R4, SPR(SRR1)
+ MOVW R3, R1
+ MOVW R5, SPR(SRR0)
+ RFI
+
+TEXT icflush(SB), $-4 /* icflush(virtaddr, count) */
+ MOVW n+4(FP), R4
+ RLWNM $0, R3, $~(CACHELINESZ-1), R5
+ SUB R5, R3
+ ADD R3, R4
+ ADD $(CACHELINESZ-1), R4
+ SRAW $CACHELINELOG, R4
+ MOVW R4, CTR
+icf0: ICBI (R5)
+ ADD $CACHELINESZ, R5
+ BDNZ icf0
+ ISYNC
+ RETURN
+
+TEXT dcflush(SB), $-4 /* dcflush(virtaddr, count) */
+ MOVW n+4(FP), R4
+ RLWNM $0, R3, $~(CACHELINESZ-1), R5
+ CMP R4, $0
+ BLE dcf1
+ SUB R5, R3
+ ADD R3, R4
+ ADD $(CACHELINESZ-1), R4
+ SRAW $CACHELINELOG, R4
+ MOVW R4, CTR
+dcf0: DCBF (R5)
+ ADD $CACHELINESZ, R5
+ BDNZ dcf0
+dcf1:
+ SYNC
+ RETURN
+
+TEXT tas(SB), $0
+ SYNC
+ MOVW R3, R4
+ MOVW $0xdead,R5
+tas1:
+ DCBF (R4) /* fix for 603x bug */
+ LWAR (R4), R3
+ CMP R3, $0
+ BNE tas0
+ STWCCC R5, (R4)
+ BNE tas1
+tas0:
+ SYNC
+ ISYNC
+ RETURN
+
+TEXT _xinc(SB),$0 /* void _xinc(long *); */
+ MOVW R3, R4
+xincloop:
+ DCBF (R4) /* fix for 603x bug */
+ LWAR (R4), R3
+ ADD $1, R3
+ STWCCC R3, (R4)
+ BNE xincloop
+ RETURN
+
+TEXT _xdec(SB),$0 /* long _xdec(long *); */
+ MOVW R3, R4
+xdecloop:
+ DCBF (R4) /* fix for 603x bug */
+ LWAR (R4), R3
+ ADD $-1, R3
+ STWCCC R3, (R4)
+ BNE xdecloop
+ RETURN
+
+TEXT cmpswap(SB),$0 /* int cmpswap(long*, long, long) */
+ MOVW R3, R4 /* addr */
+ MOVW old+4(FP), R5
+ MOVW new+8(FP), R6
+ DCBF (R4) /* fix for 603x bug? */
+ LWAR (R4), R3
+ CMP R3, R5
+ BNE fail
+ STWCCC R6, (R4)
+ BNE fail
+ MOVW $1, R3
+ RETURN
+fail:
+ MOVW $0, R3
+ RETURN
+
+TEXT getpvr(SB), $0
+ MOVW SPR(PVR), R3
+ RETURN
+
+TEXT getdec(SB), $0
+ MOVW SPR(DEC), R3
+ RETURN
+
+TEXT putdec(SB), $0
+ MOVW R3, SPR(DEC)
+ RETURN
+
+TEXT getdar(SB), $0
+ MOVW SPR(DAR), R3
+ RETURN
+
+TEXT getdsisr(SB), $0
+ MOVW SPR(DSISR), R3
+ RETURN
+
+TEXT getmsr(SB), $0
+ MOVW MSR, R3
+ RETURN
+
+TEXT putmsr(SB), $0
+ SYNC
+ MOVW R3, MSR
+ MSRSYNC
+ RETURN
+
+TEXT putsdr1(SB), $0
+ MOVW R3, SPR(SDR1)
+ RETURN
+
+TEXT putsr(SB), $0
+ MOVW 4(FP), R4
+ MOVW R4, SEG(R3)
+ RETURN
+
+TEXT gethid0(SB), $0
+ MOVW SPR(HID0), R3
+ RETURN
+
+TEXT gethid1(SB), $0
+ MOVW SPR(HID1), R3
+ RETURN
+
+TEXT puthid0(SB), $0
+ MOVW R3, SPR(HID0)
+ RETURN
+
+TEXT puthid1(SB), $0
+ MOVW R3, SPR(HID1)
+ RETURN
+
+TEXT eieio(SB), $0
+ EIEIO
+ RETURN
+
+TEXT sync(SB), $0
+ SYNC
+ RETURN
+
+TEXT tlbflushall(SB), $0
+ MOVW $64, R3
+ MOVW R3, CTR
+ MOVW $0, R4
+tlbflushall0:
+ TLBIE R4
+ ADD $BIT(19), R4
+ BDNZ tlbflushall0
+ EIEIO
+ TLBSYNC
+ SYNC
+ RETURN
+
+TEXT tlbflush(SB), $0
+ TLBIE R3
+ RETURN
+
+TEXT gotopc(SB), $0
+ MOVW R3, CTR
+ MOVW LR, R31 /* for trace back */
+ BR (CTR)
+
+/*
+ * traps force memory mapping off.
+ * the following code has been executed at the exception
+ * vector location
+ * MOVW R0, SPR(SAVER0)
+ * MOVW LR, R0
+ * MOVW R0, SPR(SAVELR)
+ * bl trapvec(SB)
+ */
+TEXT trapvec(SB), $-4
+ MOVW LR, R0
+ MOVW R1, SPR(SAVER1)
+ MOVW R0, SPR(SAVEXX) /* vector */
+
+ /* did we come from user space */
+ MOVW SPR(SRR1), R0
+ MOVW CR, R1
+ MOVW R0, CR
+ BC 4,17,ktrap
+
+ /* switch to kernel stack */
+ MOVW R1, CR
+ MOVW R2, R0
+ MOVW $setSB(SB), R2
+ RLWNM $0, R2, $~KZERO, R2 /* PADDR(setSB) */
+ MOVW $mach0(SB), R1 /* m-> */
+ RLWNM $0, R1, $~KZERO, R1 /* PADDR(m->) */
+ MOVW 8(R1), R1 /* m->proc */
+ RLWNM $0, R1, $~KZERO, R1 /* PADDR(m->proc) */
+ MOVW 8(R1), R1 /* m->proc->kstack */
+ RLWNM $0, R1, $~KZERO, R1 /* PADDR(m->proc->kstack) */
+ ADD $(KSTACK-UREGSIZE), R1
+ MOVW R0, R2
+ BL saveureg(SB)
+ BL trap(SB)
+ BR restoreureg
+ktrap:
+ MOVW R1, CR
+ MOVW SPR(SAVER1), R1
+ RLWNM $0, R1, $~KZERO, R1 /* PADDR(R1) */
+ SUB $UREGSPACE, R1
+ BL saveureg(SB)
+ BL trap(SB)
+ BR restoreureg
+
+/*
+ * enter with stack set and mapped.
+ * on return, SB (R2) has been set, and R3 has the Ureg*,
+ * the MMU has been re-enabled, kernel text and PC are in KSEG,
+ * R(MACH) has been set, and R0 contains 0.
+ *
+ */
+TEXT saveureg(SB), $-4
+/*
+ * save state
+ */
+ MOVMW R2, 48(R1) /* r2:r31 */
+ MOVW $setSB(SB), R2
+ RLWNM $0, R2, $~KZERO, R2 /* PADDR(setSB) */
+ MOVW $mach0(SB), R(MACH)
+ RLWNM $0, R(MACH), $~KZERO, R(MACH) /* PADDR(m->) */
+ MOVW 8(R(MACH)), R(USER)
+ MOVW $mach0(SB), R(MACH)
+ MOVW $setSB(SB), R2
+ MOVW SPR(SAVER1), R4
+ MOVW R4, 44(R1)
+ MOVW SPR(SAVER0), R5
+ MOVW R5, 40(R1)
+ MOVW CTR, R6
+ MOVW R6, 36(R1)
+ MOVW XER, R4
+ MOVW R4, 32(R1)
+ MOVW CR, R5
+ MOVW R5, 28(R1)
+ MOVW SPR(SAVELR), R6 /* LR */
+ MOVW R6, 24(R1)
+ /* pad at 20(R1) */
+ MOVW SPR(SRR0), R0
+ MOVW R0, 16(R1) /* old PC */
+ MOVW SPR(SRR1), R0
+ MOVW R0, 12(R1) /* old status */
+ MOVW SPR(SAVEXX), R0
+ MOVW R0, 8(R1) /* cause/vector */
+ ADD $8, R1, R3 /* Ureg* */
+ OR $KZERO, R3 /* fix ureg */
+ STWCCC R3, (R1) /* break any pending reservations */
+ MOVW $0, R0 /* compiler/linker expect R0 to be zero */
+
+ MOVW MSR, R5
+ OR $(MSR_IR|MSR_DR|MSR_FP|MSR_RI), R5 /* enable MMU */
+ MOVW R5, SPR(SRR1)
+ MOVW LR, R31
+ OR $KZERO, R31 /* return PC in KSEG0 */
+ MOVW R31, SPR(SRR0)
+ OR $KZERO, R1 /* fix stack pointer */
+ RFI /* returns to trap handler */
+
+/*
+ * restore state from Ureg and return from trap/interrupt
+ */
+TEXT forkret(SB), $0
+ BR restoreureg
+
+restoreureg:
+ MOVMW 48(R1), R2 /* r2:r31 */
+ /* defer R1 */
+ MOVW 40(R1), R0
+ MOVW R0, SPR(SAVER0)
+ MOVW 36(R1), R0
+ MOVW R0, CTR
+ MOVW 32(R1), R0
+ MOVW R0, XER
+ MOVW 28(R1), R0
+ MOVW R0, CR /* CR */
+ MOVW 24(R1), R0
+ MOVW R0, LR
+ /* pad, skip */
+ MOVW 16(R1), R0
+ MOVW R0, SPR(SRR0) /* old PC */
+ MOVW 12(R1), R0
+ MOVW R0, SPR(SRR1) /* old MSR */
+ /* cause, skip */
+ MOVW 44(R1), R1 /* old SP */
+ MOVW SPR(SAVER0), R0
+ RFI
+
+TEXT fpsave(SB), $0
+ FMOVD F0, (0*8)(R3)
+ FMOVD F1, (1*8)(R3)
+ FMOVD F2, (2*8)(R3)
+ FMOVD F3, (3*8)(R3)
+ FMOVD F4, (4*8)(R3)
+ FMOVD F5, (5*8)(R3)
+ FMOVD F6, (6*8)(R3)
+ FMOVD F7, (7*8)(R3)
+ FMOVD F8, (8*8)(R3)
+ FMOVD F9, (9*8)(R3)
+ FMOVD F10, (10*8)(R3)
+ FMOVD F11, (11*8)(R3)
+ FMOVD F12, (12*8)(R3)
+ FMOVD F13, (13*8)(R3)
+ FMOVD F14, (14*8)(R3)
+ FMOVD F15, (15*8)(R3)
+ FMOVD F16, (16*8)(R3)
+ FMOVD F17, (17*8)(R3)
+ FMOVD F18, (18*8)(R3)
+ FMOVD F19, (19*8)(R3)
+ FMOVD F20, (20*8)(R3)
+ FMOVD F21, (21*8)(R3)
+ FMOVD F22, (22*8)(R3)
+ FMOVD F23, (23*8)(R3)
+ FMOVD F24, (24*8)(R3)
+ FMOVD F25, (25*8)(R3)
+ FMOVD F26, (26*8)(R3)
+ FMOVD F27, (27*8)(R3)
+ FMOVD F28, (28*8)(R3)
+ FMOVD F29, (29*8)(R3)
+ FMOVD F30, (30*8)(R3)
+ FMOVD F31, (31*8)(R3)
+ MOVFL FPSCR, F0
+ FMOVD F0, (32*8)(R3)
+ RETURN
+
+TEXT fprestore(SB), $0
+ FMOVD (32*8)(R3), F0
+ MOVFL F0, FPSCR
+ FMOVD (0*8)(R3), F0
+ FMOVD (1*8)(R3), F1
+ FMOVD (2*8)(R3), F2
+ FMOVD (3*8)(R3), F3
+ FMOVD (4*8)(R3), F4
+ FMOVD (5*8)(R3), F5
+ FMOVD (6*8)(R3), F6
+ FMOVD (7*8)(R3), F7
+ FMOVD (8*8)(R3), F8
+ FMOVD (9*8)(R3), F9
+ FMOVD (10*8)(R3), F10
+ FMOVD (11*8)(R3), F11
+ FMOVD (12*8)(R3), F12
+ FMOVD (13*8)(R3), F13
+ FMOVD (14*8)(R3), F14
+ FMOVD (15*8)(R3), F15
+ FMOVD (16*8)(R3), F16
+ FMOVD (17*8)(R3), F17
+ FMOVD (18*8)(R3), F18
+ FMOVD (19*8)(R3), F19
+ FMOVD (20*8)(R3), F20
+ FMOVD (21*8)(R3), F21
+ FMOVD (22*8)(R3), F22
+ FMOVD (23*8)(R3), F23
+ FMOVD (24*8)(R3), F24
+ FMOVD (25*8)(R3), F25
+ FMOVD (26*8)(R3), F26
+ FMOVD (27*8)(R3), F27
+ FMOVD (28*8)(R3), F28
+ FMOVD (29*8)(R3), F29
+ FMOVD (30*8)(R3), F30
+ FMOVD (31*8)(R3), F31
+ RETURN
diff --git a/sys/src/9/mtx/main.c b/sys/src/9/mtx/main.c
new file mode 100755
index 000000000..eebad4444
--- /dev/null
+++ b/sys/src/9/mtx/main.c
@@ -0,0 +1,465 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "init.h"
+#include "pool.h"
+
+Conf conf;
+FPsave initfp;
+
+void
+main(void)
+{
+ memset(edata, 0, (ulong)end-(ulong)edata);
+ conf.nmach = 1;
+ machinit();
+ ioinit();
+ i8250console();
+ quotefmtinstall();
+ print("\nPlan 9\n");
+ confinit();
+ xinit();
+ raveninit();
+ trapinit();
+ printinit();
+ cpuidprint();
+ mmuinit();
+ hwintrinit();
+ clockinit();
+ kbdinit();
+ procinit0();
+ initseg();
+ timersinit();
+ links();
+ chandevreset();
+ pageinit();
+ swapinit();
+ fpsave(&initfp);
+ initfp.fpscr = 0;
+ userinit();
+ schedinit();
+}
+
+void
+machinit(void)
+{
+ memset(m, 0, sizeof(Mach));
+ m->cputype = getpvr()>>16;
+
+ /*
+ * For polled uart output at boot, need
+ * a default delay constant. 100000 should
+ * be enough for a while. Cpuidentify will
+ * calculate the real value later.
+ */
+ m->loopconst = 100000;
+
+ /* turn on caches */
+ puthid0(gethid0() | BIT(16) | BIT(17));
+
+ active.machs = 1;
+ active.exiting = 0;
+}
+
+void
+cpuidprint(void)
+{
+ char *id;
+
+ id = "unknown PowerPC";
+ switch(m->cputype) {
+ case 9:
+ id = "PowerPC 604e";
+ break;
+ }
+ print("cpu0: %s\n", id);
+}
+
+static struct
+{
+ char *name;
+ char *val;
+}
+plan9ini[] =
+{
+ { "console", "0" },
+ { "ether0", "type=2114x" },
+};
+
+char*
+getconf(char *name)
+{
+ int i;
+
+ for(i = 0; i < nelem(plan9ini); i++)
+ if(cistrcmp(name, plan9ini[i].name) == 0)
+ return plan9ini[i].val;
+ return nil;
+}
+
+void
+init0(void)
+{
+// char **p, *q, name[KNAMELEN];
+// int n;
+ char buf[2*KNAMELEN];
+
+ up->nerrlab = 0;
+
+ spllo();
+
+ /*
+ * These are o.k. because rootinit is null.
+ * Then early kproc's will have a root and dot.
+ */
+ up->slash = namec("#/", Atodir, 0, 0);
+ pathclose(up->slash->path);
+ up->slash->path = newpath("/");
+ up->dot = cclone(up->slash);
+
+ chandevinit();
+
+ if(!waserror()){
+ snprint(buf, sizeof(buf), "power %s mtx", conffile);
+ ksetenv("terminal", buf, 0);
+ ksetenv("cputype", "power", 0);
+ if(cpuserver)
+ ksetenv("service", "cpu", 0);
+ else
+ ksetenv("service", "terminal", 0);
+
+/*
+ for(p = confenv; *p; p++) {
+ q = strchr(p[0], '=');
+ if(q == 0)
+ continue;
+ n = q-p[0];
+ if(n >= KNAMELEN)
+ n = KNAMELEN-1;
+ memmove(name, p[0], n);
+ name[n] = 0;
+ if(name[0] != '*')
+ ksetenv(name, q+1, 0);
+ ksetenv(name, q+1, 1);
+ }
+*/
+ poperror();
+ }
+ kproc("alarm", alarmkproc, 0);
+ kproc("mmusweep", mmusweep, 0);
+ touser((void*)(USTKTOP-8));
+}
+
+void
+userinit(void)
+{
+ Proc *p;
+ Segment *s;
+ KMap *k;
+ Page *pg;
+
+ p = newproc();
+ p->pgrp = newpgrp();
+ p->egrp = smalloc(sizeof(Egrp));
+ p->egrp->ref = 1;
+ p->fgrp = dupfgrp(nil);
+ p->rgrp = newrgrp();
+ p->procmode = 0640;
+
+ kstrdup(&eve, "");
+ kstrdup(&p->text, "*init*");
+ kstrdup(&p->user, eve);
+
+ p->fpstate = FPinit;
+
+ /*
+ * Kernel Stack
+ *
+ * N.B. The -12 for the stack pointer is important.
+ * 4 bytes for gotolabel's return PC
+ */
+ p->sched.pc = (ulong)init0;
+ p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
+
+ /*
+ * User Stack
+ */
+ s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
+ p->seg[SSEG] = s;
+ pg = newpage(1, 0, USTKTOP-BY2PG);
+ segpage(s, pg);
+
+ /*
+ * Text
+ */
+ s = newseg(SG_TEXT, UTZERO, 1);
+ s->flushme++;
+ p->seg[TSEG] = s;
+ pg = newpage(1, 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);
+
+ ready(p);
+}
+
+/* still to do */
+void
+reboot(void*, void*, ulong)
+{
+ exit(0);
+}
+
+void
+exit(int ispanic)
+{
+ int ms, once;
+
+ lock(&active);
+ if(ispanic)
+ active.ispanic = ispanic;
+ else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
+ active.ispanic = 0;
+ once = active.machs & (1<<m->machno);
+ active.machs &= ~(1<<m->machno);
+ active.exiting = 1;
+ unlock(&active);
+
+ if(once)
+ print("cpu%d: exiting\n", m->machno);
+ spllo();
+ for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
+ delay(TK2MS(2));
+ if(active.machs == 0 && consactive() == 0)
+ break;
+ }
+
+ if(active.ispanic && m->machno == 0){
+ if(cpuserver)
+ delay(10000);
+ else if(conf.monitor)
+ for(;;);
+ }
+ else
+ delay(1000);
+
+ watchreset();
+}
+
+/*
+ * set up floating point for a new process
+ */
+void
+procsetup(Proc *p)
+{
+ p->fpstate = FPinit;
+}
+
+/*
+ * Save the mach dependent part of the process state.
+ */
+void
+procsave(Proc *p)
+{
+ if(p->fpstate == FPactive){
+ if(p->state != Moribund)
+ fpsave(&up->fpsave);
+ p->fpstate = FPinactive;
+ }
+}
+
+void
+confinit(void)
+{
+ char *p;
+ int userpcnt;
+ ulong pa, kpages;
+ extern ulong memsize; /* passed in from ROM monitor */
+
+ if(p = getconf("*kernelpercent"))
+ userpcnt = 100 - strtol(p, 0, 0);
+ else
+ userpcnt = 0;
+
+ pa = PGROUND(PADDR(end));
+
+ 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;
+ if(cpuserver)
+ conf.nproc *= 3;
+ if(conf.nproc > 2000)
+ conf.nproc = 2000;
+ conf.nimage = 200;
+ conf.nswap = conf.nproc*80;
+ conf.nswppo = 4096;
+ conf.copymode = 0; /* copy on write */
+
+ if(cpuserver) {
+ if(userpcnt < 10)
+ userpcnt = 70;
+ kpages = conf.npage - (conf.npage*userpcnt)/100;
+
+ /*
+ * Hack for the big boys. Only good while physmem < 4GB.
+ * Give the kernel a max. of 16MB + enough to allocate the
+ * page pool.
+ * This is an overestimate as conf.upages < conf.npages.
+ * The patch of nimage is a band-aid, scanning the whole
+ * page list in imagereclaim just takes too long.
+ */
+ if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){
+ kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;
+ conf.nimage = 2000;
+ kpages += (conf.nproc*KSTACK)/BY2PG;
+ }
+ } else {
+ if(userpcnt < 10) {
+ if(conf.npage*BY2PG < 16*MB)
+ userpcnt = 40;
+ else
+ userpcnt = 60;
+ }
+ kpages = conf.npage - (conf.npage*userpcnt)/100;
+
+ /*
+ * Make sure terminals with low memory get at least
+ * 4MB on the first Image chunk allocation.
+ */
+ if(conf.npage*BY2PG < 16*MB)
+ imagmem->minarena = 4*1024*1024;
+ }
+ conf.upages = conf.npage - kpages;
+ conf.ialloc = (kpages/2)*BY2PG;
+
+ /*
+ * Guess how much is taken by the large permanent
+ * datastructures. Mntcache and Mntrpc are not accounted for
+ * (probably ~300KB).
+ */
+ kpages *= BY2PG;
+ kpages -= conf.upages*sizeof(Page)
+ + conf.nproc*sizeof(Proc)
+ + conf.nimage*sizeof(Image)
+ + conf.nswap
+ + conf.nswppo*sizeof(Page);
+ mainmem->maxsize = kpages;
+ if(!cpuserver){
+ /*
+ * give terminals lots of image memory, too; the dynamic
+ * allocation will balance the load properly, hopefully.
+ * be careful with 32-bit overflow.
+ */
+ imagmem->maxsize = kpages;
+ }
+
+// conf.monitor = 1; /* BUG */
+}
+
+static int
+getcfields(char* lp, char** fields, int n, char* sep)
+{
+ int i;
+
+ for(i = 0; lp && *lp && i < n; i++){
+ while(*lp && strchr(sep, *lp) != 0)
+ *lp++ = 0;
+ if(*lp == 0)
+ break;
+ fields[i] = lp;
+ while(*lp && strchr(sep, *lp) == 0){
+ if(*lp == '\\' && *(lp+1) == '\n')
+ *lp++ = ' ';
+ lp++;
+ }
+ }
+
+ return i;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ int i;
+ char cc[KNAMELEN], *p;
+
+ sprint(cc, "%s%d", class, ctlrno);
+
+ p = getconf(cc);
+ if(p == 0)
+ return 0;
+ isa->nopt = tokenize(p, isa->opt, NISAOPT);
+ for(i = 0; i < isa->nopt; i++){
+ p = isa->opt[i];
+ if(cistrncmp(p, "type=", 5) == 0)
+ isa->type = p + 5;
+ else if(cistrncmp(p, "port=", 5) == 0)
+ isa->port = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "irq=", 4) == 0)
+ isa->irq = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "dma=", 4) == 0)
+ isa->dma = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "mem=", 4) == 0)
+ isa->mem = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "size=", 5) == 0)
+ isa->size = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "freq=", 5) == 0)
+ isa->freq = strtoul(p+5, &p, 0);
+ }
+ return 1;
+}
+
+int
+cistrcmp(char *a, char *b)
+{
+ int ac, bc;
+
+ for(;;){
+ ac = *a++;
+ bc = *b++;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+ return 0;
+}
+
+int
+cistrncmp(char *a, char *b, int n)
+{
+ unsigned ac, bc;
+
+ while(n > 0){
+ ac = *a++;
+ bc = *b++;
+ n--;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+
+ return 0;
+}
diff --git a/sys/src/9/mtx/mem.h b/sys/src/9/mtx/mem.h
new file mode 100755
index 000000000..05c01ff8a
--- /dev/null
+++ b/sys/src/9/mtx/mem.h
@@ -0,0 +1,195 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+
+#define BI2BY 8 /* bits per byte */
+#define BI2WD 32 /* bits per word */
+#define BY2WD 4 /* bytes per word */
+#define BY2V 8 /* bytes per vlong */
+#define BY2PG 4096 /* bytes per page */
+#define WD2PG (BY2PG/BY2WD) /* words per page */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
+#define PGROUND(s) ROUND(s, BY2PG)
+#define CACHELINELOG 4
+#define CACHELINESZ (1<<CACHELINELOG)
+#define BLOCKALIGN CACHELINESZ
+
+#define MHz 1000000
+
+#define BY2PTE 8 /* bytes per pte entry */
+#define BY2PTEG 64 /* bytes per pte group */
+
+#define MAXMACH 1 /* max # cpus system can run */
+#define MACHSIZE BY2PG
+#define KSTACK 4096 /* Size of kernel stack */
+
+/*
+ * Time
+ */
+#define HZ 100 /* clock frequency */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+
+/*
+ * Standard PPC Special Purpose Registers (OEA and VEA)
+ */
+#define DSISR 18
+#define DAR 19 /* Data Address Register */
+#define DEC 22 /* Decrementer */
+#define SDR1 25
+#define SRR0 26 /* Saved Registers (exception) */
+#define SRR1 27
+#define SPRG0 272 /* Supervisor Private Registers */
+#define SPRG1 273
+#define SPRG2 274
+#define SPRG3 275
+#define ASR 280 /* Address Space Register */
+#define EAR 282 /* External Access Register (optional) */
+#define TBRU 269 /* Time base Upper/Lower (Reading) */
+#define TBRL 268
+#define TBWU 284 /* Time base Upper/Lower (Writing) */
+#define TBWL 285
+#define PVR 287 /* Processor Version */
+#define IABR 1010 /* Instruction Address Breakpoint Register (optional) */
+#define DABR 1013 /* Data Address Breakpoint Register (optional) */
+#define FPECR 1022 /* Floating-Point Exception Cause Register (optional) */
+#define PIR 1023 /* Processor Identification Register (optional) */
+
+#define IBATU(i) (528+2*(i)) /* Instruction BAT register (upper) */
+#define IBATL(i) (529+2*(i)) /* Instruction BAT register (lower) */
+#define DBATU(i) (536+2*(i)) /* Data BAT register (upper) */
+#define DBATL(i) (537+2*(i)) /* Data BAT register (lower) */
+
+/*
+ * PPC604e-specific Special Purpose Registers (OEA)
+ */
+#define HID0 1008 /* Hardware Implementation Dependant Register 0 */
+#define HID1 1009 /* Hardware Implementation Dependant Register 1 */
+#define PMC1 953 /* Performance Monitor Counter 1 */
+#define PMC2 954 /* Performance Monitor Counter 2 */
+#define PMC3 957 /* Performance Monitor Counter 3 */
+#define PMC4 958 /* Performance Monitor Counter 4 */
+#define MMCR0 952 /* Monitor Control Register 0 */
+#define MMCR1 956 /* Monitor Control Register 0 */
+#define SIA 955 /* Sampled Instruction Address */
+#define SDA 959 /* Sampled Data Address */
+
+#define BIT(i) (1<<(31-(i))) /* Silly backwards register bit numbering scheme */
+
+/*
+ * Bit encodings for Machine State Register (MSR)
+ */
+#define MSR_POW BIT(13) /* Enable Power Management */
+#define MSR_ILE BIT(15) /* Interrupt Little-Endian enable */
+#define MSR_EE BIT(16) /* External Interrupt enable */
+#define MSR_PR BIT(17) /* Supervisor/User privelege */
+#define MSR_FP BIT(18) /* Floating Point enable */
+#define MSR_ME BIT(19) /* Machine Check enable */
+#define MSR_FE0 BIT(20) /* Floating Exception mode 0 */
+#define MSR_SE BIT(21) /* Single Step (optional) */
+#define MSR_BE BIT(22) /* Branch Trace (optional) */
+#define MSR_FE1 BIT(23) /* Floating Exception mode 1 */
+#define MSR_IP BIT(25) /* Exception prefix 0x000/0xFFF */
+#define MSR_IR BIT(26) /* Instruction MMU enable */
+#define MSR_DR BIT(27) /* Data MMU enable */
+#define MSR_PM BIT(29) /* Performance Monitor marked mode (604e specific) */
+#define MSR_RI BIT(30) /* Recoverable Exception */
+#define MSR_LE BIT(31) /* Little-Endian enable */
+
+/*
+ * Exception codes (trap vectors)
+ */
+#define CRESET 0x01
+#define CMCHECK 0x02
+#define CDSI 0x03
+#define CISI 0x04
+#define CEI 0x05
+#define CALIGN 0x06
+#define CPROG 0x07
+#define CFPU 0x08
+#define CDEC 0x09
+#define CSYSCALL 0x0C
+#define CTRACE 0x0D /* optional */
+#define CFPA 0x0E /* optional */
+
+/* PPC604e-specific: */
+#define CPERF 0x0F /* performance monitoring */
+#define CIBREAK 0x13
+#define CSMI 0x14
+
+/*
+ * Magic registers
+ */
+
+#define MACH 30 /* R30 is m-> */
+#define USER 29 /* R29 is up-> */
+
+
+/*
+ * virtual MMU
+ */
+#define PTEMAPMEM (1024*1024)
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 1984
+#define SSEGMAPSIZE 16
+#define PPN(x) ((x)&~(BY2PG-1))
+
+/*
+ * First pte word
+ */
+#define PTE0(v, vsid, h, va) (((v)<<31)|((vsid)<<7)|((h)<<6)|(((va)>>22)&0x3f))
+
+/*
+ * Second pte word; WIMG & PP(RW/RO) common to page table and BATs
+ */
+#define PTE1_W BIT(25)
+#define PTE1_I BIT(26)
+#define PTE1_M BIT(27)
+#define PTE1_G BIT(28)
+
+#define PTE1_RW BIT(30)
+#define PTE1_RO BIT(31)
+
+/*
+ * PTE bits for fault.c. These belong to the second PTE word. Validity is
+ * implied for putmmu(), and we always set PTE0_V. PTEVALID is used
+ * here to set cache policy bits on a global basis.
+ */
+#define PTEVALID 0
+#define PTEWRITE PTE1_RW
+#define PTERONLY PTE1_RO
+#define PTEUNCACHED PTE1_I
+
+/*
+ * Address spaces
+ */
+
+#define UZERO 0 /* base of user address space */
+#define UTZERO (UZERO+BY2PG) /* first address in user text */
+#define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */
+#define TSTKTOP KZERO /* top of temporary stack */
+#define TSTKSIZ 100
+#define KZERO 0x80000000 /* base of kernel address space */
+#define KTZERO (KZERO+0x4000) /* first address in kernel text */
+#define USTKSIZE (4*1024*1024) /* size of user stack */
+#define UREGSIZE ((8+32)*4)
+
+#define PCIMEM0 0xf0000000
+#define PCISIZE0 0x0e000000
+#define PCIMEM1 0xc0000000
+#define PCISIZE1 0x30000000
+#define IOMEM 0xfe000000
+#define IOSIZE 0x00800000
+#define FALCON 0xfef80000
+#define RAVEN 0xfeff0000
+#define FLASHA 0xff000000
+#define FLASHB 0xff800000
+#define FLASHAorB 0xfff00000
+
+#define isphys(x) (((ulong)x&KZERO)!=0)
+
+#define getpgcolor(a) 0
diff --git a/sys/src/9/mtx/mkfile b/sys/src/9/mtx/mkfile
new file mode 100755
index 000000000..af7f50f02
--- /dev/null
+++ b/sys/src/9/mtx/mkfile
@@ -0,0 +1,96 @@
+CONF=mtx
+CONFLIST=mtx mtxcpu
+
+objtype=power
+</$objtype/mkfile
+p=9
+
+DEVS=`{rc ../port/mkdevlist $CONF}
+
+PORT=\
+ alarm.$O\
+ alloc.$O\
+ allocb.$O\
+ auth.$O\
+ cache.$O\
+ chan.$O\
+ dev.$O\
+ edf.$O\
+ fault.$O\
+ latin1.$O\
+ log.$O\
+ mul64fract.$O\
+ rebootcmd.$O\
+ page.$O\
+ parse.$O\
+ pgrp.$O\
+ portclock.$O\
+ print.$O\
+ proc.$O\
+ qio.$O\
+ qlock.$O\
+ rdb.$O\
+ segment.$O\
+ swap.$O\
+ sysfile.$O\
+ sysproc.$O\
+ taslock.$O\
+ tod.$O\
+ xalloc.$O\
+
+OBJ=\
+ l.$O\
+ inb.$O\
+ clock.$O\
+ i8259.$O\
+ kbd.$O\
+ main.$O\
+ mmu.$O\
+ random.$O\
+ raven.$O\
+ trap.$O\
+ $CONF.root.$O\
+ $CONF.rootc.$O\
+ $DEVS\
+ $PORT\
+
+LIB=\
+ /$objtype/lib/libmemlayer.a\
+ /$objtype/lib/libmemdraw.a\
+ /$objtype/lib/libdraw.a\
+ /$objtype/lib/libip.a\
+ /$objtype/lib/libc.a\
+ /$objtype/lib/libsec.a\
+
+ETHER=`{echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
+VGA=`{echo devvga.c screen.c vga*.c | sed 's/\.c/.'$O'/g'}
+SDEV=`{echo devsd.c sd*.c | sed 's/\.c/.'$O'/g'}
+
+loadaddr = 0x80004020
+
+$p$CONF: $CONF.c $OBJ $LIB
+ $CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
+ $LD -R4 -o $target -T$loadaddr -l $OBJ $CONF.$O $LIB
+ ls -l $target
+
+install:V: $p$CONF
+ cp $p$CONF /$objtype/$p$CONF
+
+<../boot/bootmkfile
+<../port/portmkfile
+<|../port/mkbootrules $CONF
+
+clock.$O: /$objtype/include/ureg.h
+devether.$O: /$objtype/include/ureg.h
+main.$O: /$objtype/include/ureg.h errstr.h init.h
+trap.$O: /$objtype/include/ureg.h
+
+$ETHER: etherif.h ../port/netif.h
+
+init.h: initcode /sys/src/libc/9syscall/sys.h
+ $AS initcode
+ $LD -l -s -R4 -o init.out initcode.$O -lc
+ {echo 'uchar initcode[]={'
+ xd -r -1x init.out |
+ sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+ echo '};'} > init.h
diff --git a/sys/src/9/mtx/mmu.c b/sys/src/9/mtx/mmu.c
new file mode 100755
index 000000000..c43a1a7dd
--- /dev/null
+++ b/sys/src/9/mtx/mmu.c
@@ -0,0 +1,257 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ * We have one page table per processor.
+ *
+ * Different processes are distinguished via the VSID field in
+ * the segment registers. As flushing the entire page table is an
+ * expensive operation, we implement an aging algorithm for
+ * mmu pids, with a background kproc to purge stale pids en mass.
+ *
+ * This needs modifications to run on a multiprocessor.
+ */
+
+static ulong ptabsize; /* number of bytes in page table */
+static ulong ptabmask; /* hash mask */
+
+/*
+ * VSID is 24 bits. 3 are required to distinguish segments in user
+ * space (kernel space only uses the BATs). pid 0 is reserved.
+ * The top 2 bits of the pid are used as a `color' for the background
+ * pid reclaimation algorithm.
+ */
+
+enum {
+ PIDBASE = 1,
+ PIDBITS = 21,
+ COLBITS = 2,
+ PIDMAX = ((1<<PIDBITS)-1),
+ COLMASK = ((1<<COLBITS)-1),
+};
+
+#define VSID(pid, i) (((pid)<<3)|i)
+#define PIDCOLOR(pid) ((pid)>>(PIDBITS-COLBITS))
+#define PTECOL(color) PTE0(1, VSID(((color)<<(PIDBITS-COLBITS)), 0), 0, 0)
+
+void
+mmuinit(void)
+{
+ int lhash, mem;
+ extern ulong memsize; /* passed in from ROM monitor */
+
+ if(ptabsize == 0) {
+ /* heuristically size the hash table */
+ lhash = 10;
+ mem = (1<<23);
+ while(mem < memsize) {
+ lhash++;
+ mem <<= 1;
+ }
+ ptabsize = (1<<(lhash+6));
+ ptabmask = (1<<lhash)-1;
+ }
+
+ m->ptabbase = (ulong)xspanalloc(ptabsize, 0, ptabsize);
+ putsdr1(PADDR(m->ptabbase) | (ptabmask>>10));
+ m->mmupid = PIDBASE;
+ m->sweepcolor = 0;
+ m->trigcolor = COLMASK;
+}
+
+static int
+work(void*)
+{
+ return PIDCOLOR(m->mmupid) == m->trigcolor;
+}
+
+void
+mmusweep(void*)
+{
+ Proc *p;
+ int i, x, sweepcolor;
+ ulong *ptab, *ptabend, ptecol;
+
+ for(;;) {
+ if(PIDCOLOR(m->mmupid) != m->trigcolor)
+ sleep(&m->sweepr, work, nil);
+
+ sweepcolor = m->sweepcolor;
+ x = splhi();
+ p = proctab(0);
+ for(i = 0; i < conf.nproc; i++, p++)
+ if(PIDCOLOR(p->mmupid) == sweepcolor)
+ p->mmupid = 0;
+ splx(x);
+
+ ptab = (ulong*)m->ptabbase;
+ ptabend = (ulong*)(m->ptabbase+ptabsize);
+ ptecol = PTECOL(sweepcolor);
+ while(ptab < ptabend) {
+ if((*ptab & PTECOL(3)) == ptecol)
+ *ptab = 0;
+ ptab += 2;
+ }
+ tlbflushall();
+
+ m->sweepcolor = (sweepcolor+1) & COLMASK;
+ m->trigcolor = (m->trigcolor+1) & COLMASK;
+ }
+}
+
+int
+newmmupid(void)
+{
+ int pid, newcolor;
+
+ pid = m->mmupid++;
+ if(m->mmupid > PIDMAX)
+ m->mmupid = PIDBASE;
+ newcolor = PIDCOLOR(m->mmupid);
+ if(newcolor != PIDCOLOR(pid)) {
+ if(newcolor == m->sweepcolor) {
+ /* desperation time. can't block here. punt to fault/putmmu */
+ print("newmmupid: %uld: no free mmu pids\n", up->pid);
+ if(m->mmupid == PIDBASE)
+ m->mmupid = PIDMAX;
+ else
+ m->mmupid--;
+ pid = 0;
+ }
+ else if(newcolor == m->trigcolor)
+ wakeup(&m->sweepr);
+ }
+ up->mmupid = pid;
+ return pid;
+}
+
+void
+flushmmu(void)
+{
+ int x;
+
+ x = splhi();
+ up->newtlb = 1;
+ mmuswitch(up);
+ splx(x);
+}
+
+/*
+ * called with splhi
+ */
+void
+mmuswitch(Proc *p)
+{
+ int i, mp;
+
+ if(p->kp) {
+ for(i = 0; i < 8; i++)
+ putsr(i<<28, 0);
+ return;
+ }
+
+ if(p->newtlb) {
+ p->mmupid = 0;
+ p->newtlb = 0;
+ }
+ mp = p->mmupid;
+ if(mp == 0)
+ mp = newmmupid();
+
+ for(i = 0; i < 8; i++)
+ putsr(i<<28, VSID(mp, i)|BIT(1)|BIT(2));
+}
+
+void
+mmurelease(Proc* p)
+{
+ p->mmupid = 0;
+}
+
+void
+putmmu(ulong va, ulong pa, Page *pg)
+{
+ int mp;
+ char *ctl;
+ ulong *p, *ep, *q, pteg;
+ ulong vsid, ptehi, x, hash;
+
+ /*
+ * If mmupid is 0, mmuswitch/newmmupid was unable to assign us
+ * a pid, hence we faulted. Keep calling sched() until the mmusweep
+ * proc catches up, and we are able to get a pid.
+ */
+ while((mp = up->mmupid) == 0)
+ sched();
+
+ vsid = VSID(mp, va>>28);
+ hash = (vsid ^ (va>>12)&0xffff) & ptabmask;
+ ptehi = PTE0(1, vsid, 0, va);
+
+ pteg = m->ptabbase + BY2PTEG*hash;
+ p = (ulong*)pteg;
+ ep = (ulong*)(pteg+BY2PTEG);
+ q = nil;
+ tlbflush(va);
+ while(p < ep) {
+ x = p[0];
+ if(x == ptehi) {
+ q = p;
+ break;
+ }
+ if(q == nil && (x & BIT(0)) == 0)
+ q = p;
+ p += 2;
+ }
+ if(q == nil) {
+ q = (ulong*)(pteg+m->slotgen);
+ m->slotgen = (m->slotgen + BY2PTE) & (BY2PTEG-1);
+ }
+ q[0] = ptehi;
+ q[1] = pa;
+ sync();
+
+ ctl = &pg->cachectl[m->machno];
+ switch(*ctl) {
+ case PG_NEWCOL:
+ default:
+ panic("putmmu: %d\n", *ctl);
+ break;
+ case PG_NOFLUSH:
+ break;
+ case PG_TXTFLUSH:
+ dcflush((void*)pg->va, BY2PG);
+ icflush((void*)pg->va, BY2PG);
+ *ctl = PG_NOFLUSH;
+ break;
+ }
+}
+
+void
+checkmmu(ulong, ulong)
+{
+}
+
+void
+countpagerefs(ulong*, int)
+{
+}
+
+/*
+ * Return the number of bytes that can be accessed via KADDR(pa).
+ * If pa is not a valid argument to KADDR, return 0.
+ */
+ulong
+cankaddr(ulong pa)
+{
+ ulong kzero;
+
+ kzero = -KZERO;
+ if(pa >= kzero)
+ return 0;
+ return kzero - pa;
+}
diff --git a/sys/src/9/mtx/mtx b/sys/src/9/mtx/mtx
new file mode 100755
index 000000000..47c2441f5
--- /dev/null
+++ b/sys/src/9/mtx/mtx
@@ -0,0 +1,46 @@
+dev
+ root
+ cons
+ arch
+ pnp pci
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ ssl
+ cap
+ kprof
+ uart
+ rtc
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netif netlog nullmedium pktmedium ptclbsum inferno
+
+link
+ ether2114x pci
+ ethermedium
+ netdevmedium
+
+misc
+ uarti8250
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+
+port
+ int cpuserver = 0;
+
+boot
+ tcp
+
+bootdir
+ bootmtx.out boot
+ /power/bin/ip/ipconfig
+ /power/bin/auth/factotum
+
diff --git a/sys/src/9/mtx/mtxcpu b/sys/src/9/mtx/mtxcpu
new file mode 100755
index 000000000..b64090725
--- /dev/null
+++ b/sys/src/9/mtx/mtxcpu
@@ -0,0 +1,46 @@
+dev
+ root
+ cons
+ arch
+ pnp pci
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ ssl
+ cap
+ kprof
+ uart
+ rtc
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netif netlog nullmedium pktmedium ptclbsum inferno
+
+link
+ ether2114x pci
+ ethermedium
+ netdevmedium
+
+misc
+ uarti8250
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+
+port
+ int cpuserver = 1;
+
+boot cpu
+ tcp
+
+bootdir
+ bootmtxcpu.out boot
+ ipconfig.hack ipconfig
+ factotum.hack factotum
+
diff --git a/sys/src/9/mtx/pci.c b/sys/src/9/mtx/pci.c
new file mode 100755
index 000000000..73c4d641e
--- /dev/null
+++ b/sys/src/9/mtx/pci.c
@@ -0,0 +1,908 @@
+/*
+ * PCI support code.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define DBG if(0) pcilog
+
+struct
+{
+ char output[16384];
+ int ptr;
+}PCICONS;
+
+int
+pcilog(char *fmt, ...)
+{
+ int n;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+
+ memmove(PCICONS.output+PCICONS.ptr, buf, n);
+ PCICONS.ptr += n;
+ return n;
+}
+
+enum
+{ /* configuration mechanism #1 */
+ PciADDR = 0xCF8, /* CONFIG_ADDRESS */
+ PciDATA = 0xCFC, /* CONFIG_DATA */
+
+ /* configuration mechanism #2 */
+ PciCSE = 0xCF8, /* configuration space enable */
+ PciFORWARD = 0xCFA, /* which bus */
+
+ MaxFNO = 7,
+ MaxUBN = 255,
+};
+
+enum
+{ /* command register */
+ IOen = (1<<0),
+ MEMen = (1<<1),
+ MASen = (1<<2),
+ MemWrInv = (1<<4),
+ PErrEn = (1<<6),
+ SErrEn = (1<<8),
+};
+
+static Lock pcicfglock;
+static QLock pcicfginitlock;
+static int pcicfgmode = -1;
+static int pcimaxbno = 7;
+static int pcimaxdno;
+static Pcidev* pciroot;
+static Pcidev* pcilist;
+static Pcidev* pcitail;
+
+static int pcicfgrw32(int, int, int, int);
+static int pcicfgrw8(int, int, int, int);
+
+static char* bustypes[] = {
+ "CBUSI",
+ "CBUSII",
+ "EISA",
+ "FUTURE",
+ "INTERN",
+ "ISA",
+ "MBI",
+ "MBII",
+ "MCA",
+ "MPI",
+ "MPSA",
+ "NUBUS",
+ "PCI",
+ "PCMCIA",
+ "TC",
+ "VL",
+ "VME",
+ "XPRESS",
+};
+
+#pragma varargck type "T" int
+
+static int
+tbdffmt(Fmt* fmt)
+{
+ char *p;
+ int l, r, type, tbdf;
+
+ if((p = malloc(READSTR)) == nil)
+ return fmtstrcpy(fmt, "(tbdfconv)");
+
+ switch(fmt->r){
+ case 'T':
+ tbdf = va_arg(fmt->args, int);
+ type = BUSTYPE(tbdf);
+ if(type < nelem(bustypes))
+ l = snprint(p, READSTR, bustypes[type]);
+ else
+ l = snprint(p, READSTR, "%d", type);
+ snprint(p+l, READSTR-l, ".%d.%d.%d",
+ BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
+ break;
+
+ default:
+ snprint(p, READSTR, "(tbdfconv)");
+ break;
+ }
+ r = fmtstrcpy(fmt, p);
+ free(p);
+
+ return r;
+}
+
+ulong
+pcibarsize(Pcidev *p, int rno)
+{
+ ulong v, size;
+
+ v = pcicfgrw32(p->tbdf, rno, 0, 1);
+ pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
+ size = pcicfgrw32(p->tbdf, rno, 0, 1);
+ if(v & 1)
+ size |= 0xFFFF0000;
+ pcicfgrw32(p->tbdf, rno, v, 0);
+
+ return -(size & ~0x0F);
+}
+
+static int
+pcisizcmp(void *a, void *b)
+{
+ Pcisiz *aa, *bb;
+
+ aa = a;
+ bb = b;
+ return aa->siz - bb->siz;
+}
+
+static ulong
+pcimask(ulong v)
+{
+ ulong m;
+
+ m = BI2BY*sizeof(v);
+ for(m = 1<<(m-1); m != 0; m >>= 1) {
+ if(m & v)
+ break;
+ }
+
+ m--;
+ if((v & m) == 0)
+ return v;
+
+ v |= m;
+ return v+1;
+}
+
+static void
+pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
+{
+ Pcidev *p;
+ int ntb, i, size, rno, hole;
+ ulong v, mema, ioa, sioa, smema, base, limit;
+ Pcisiz *table, *tptr, *mtb, *itb;
+ extern void qsort(void*, long, long, int (*)(void*, void*));
+
+ ioa = *pioa;
+ mema = *pmema;
+
+ DBG("pcibusmap wr=%d %T mem=%luX io=%luX\n",
+ wrreg, root->tbdf, mema, ioa);
+
+ ntb = 0;
+ for(p = root; p != nil; p = p->link)
+ ntb++;
+
+ ntb *= (PciCIS-PciBAR0)/4;
+ table = malloc(2*ntb*sizeof(Pcisiz));
+ itb = table;
+ mtb = table+ntb;
+
+ /*
+ * Build a table of sizes
+ */
+ for(p = root; p != nil; p = p->link) {
+ if(p->ccrb == 0x06) {
+ if(p->ccru == 0x04 && p->bridge != nil) {
+ sioa = ioa;
+ smema = mema;
+ pcibusmap(p->bridge, &smema, &sioa, 0);
+
+ hole = pcimask(smema-mema);
+ if(hole < (1<<20))
+ hole = 1<<20;
+ p->mema.size = hole;
+
+ hole = pcimask(sioa-ioa);
+ if(hole < (1<<12))
+ hole = 1<<12;
+
+ p->ioa.size = hole;
+
+ itb->dev = p;
+ itb->bar = -1;
+ itb->siz = p->ioa.size;
+ itb++;
+
+ mtb->dev = p;
+ mtb->bar = -1;
+ mtb->siz = p->mema.size;
+ mtb++;
+ }
+ if((pcicfgr8(p, PciHDT)&0x7f) != 0)
+ continue;
+ }
+
+ for(i = 0; i <= 5; i++) {
+ rno = PciBAR0 + i*4;
+ v = pcicfgrw32(p->tbdf, rno, 0, 1);
+ size = pcibarsize(p, rno);
+ if(size == 0)
+ continue;
+
+ if(v & 1) {
+ itb->dev = p;
+ itb->bar = i;
+ itb->siz = size;
+ itb++;
+ }
+ else {
+ mtb->dev = p;
+ mtb->bar = i;
+ mtb->siz = size;
+ mtb++;
+ }
+
+ p->mem[i].size = size;
+ }
+ }
+
+ /*
+ * Sort both tables IO smallest first, Memory largest
+ */
+ qsort(table, itb-table, sizeof(Pcisiz), pcisizcmp);
+ tptr = table+ntb;
+ qsort(tptr, mtb-tptr, sizeof(Pcisiz), pcisizcmp);
+
+ /*
+ * Allocate IO address space on this bus
+ */
+ for(tptr = table; tptr < itb; tptr++) {
+ hole = tptr->siz;
+ if(tptr->bar == -1)
+ hole = 1<<12;
+ ioa = (ioa+hole-1) & ~(hole-1);
+
+ p = tptr->dev;
+ if(tptr->bar == -1)
+ p->ioa.bar = ioa;
+ else {
+ p->pcr |= IOen;
+ p->mem[tptr->bar].bar = ioa|1;
+ if(wrreg)
+ pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), ioa|1, 0);
+ }
+
+ ioa += tptr->siz;
+ }
+
+ /*
+ * Allocate Memory address space on this bus
+ */
+ for(tptr = table+ntb; tptr < mtb; tptr++) {
+ hole = tptr->siz;
+ if(tptr->bar == -1)
+ hole = 1<<20;
+ mema = (mema+hole-1) & ~(hole-1);
+
+ p = tptr->dev;
+ if(tptr->bar == -1)
+ p->mema.bar = mema;
+ else {
+ p->pcr |= MEMen;
+ p->mem[tptr->bar].bar = mema;
+ if(wrreg)
+ pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), mema, 0);
+ }
+ mema += tptr->siz;
+ }
+
+ *pmema = mema;
+ *pioa = ioa;
+ free(table);
+
+ if(wrreg == 0)
+ return;
+
+ /*
+ * Finally set all the bridge addresses & registers
+ */
+ for(p = root; p != nil; p = p->link) {
+ if(p->bridge == nil) {
+ pcicfgrw8(p->tbdf, PciLTR, 64, 0);
+
+ p->pcr |= MASen;
+ pcicfgrw32(p->tbdf, PciPCR, p->pcr, 0);
+ continue;
+ }
+
+ base = p->ioa.bar;
+ limit = base+p->ioa.size-1;
+ v = pcicfgrw32(p->tbdf, PciIBR, 0, 1);
+ v = (v&0xFFFF0000)|(limit & 0xF000)|((base & 0xF000)>>8);
+ pcicfgrw32(p->tbdf, PciIBR, v, 0);
+ v = (limit & 0xFFFF0000)|(base>>16);
+ pcicfgrw32(p->tbdf, PciIUBR, v, 0);
+
+ base = p->mema.bar;
+ limit = base+p->mema.size-1;
+ v = (limit & 0xFFF00000)|((base & 0xFFF00000)>>16);
+ pcicfgrw32(p->tbdf, PciMBR, v, 0);
+
+ /*
+ * Disable memory prefetch
+ */
+ pcicfgrw32(p->tbdf, PciPMBR, 0x0000FFFF, 0);
+ pcicfgrw8(p->tbdf, PciLTR, 64, 0);
+
+ /*
+ * Enable the bridge
+ */
+ v = 0xFFFF0000 | IOen | MEMen | MASen;
+ pcicfgrw32(p->tbdf, PciPCR, v, 0);
+
+ sioa = p->ioa.bar;
+ smema = p->mema.bar;
+ pcibusmap(p->bridge, &smema, &sioa, 1);
+ }
+}
+
+static int
+pcilscan(int bno, Pcidev** list)
+{
+ Pcidev *p, *head, *tail;
+ int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
+
+ maxubn = bno;
+ head = nil;
+ tail = nil;
+ for(dno = 0; dno <= pcimaxdno; dno++){
+ maxfno = 0;
+ for(fno = 0; fno <= maxfno; fno++){
+ /*
+ * For this possible device, form the
+ * bus+device+function triplet needed to address it
+ * and try to read the vendor and device ID.
+ * If successful, allocate a device struct and
+ * start to fill it in with some useful information
+ * from the device's configuration space.
+ */
+ tbdf = MKBUS(BusPCI, bno, dno, fno);
+ l = pcicfgrw32(tbdf, PciVID, 0, 1);
+ if(l == 0xFFFFFFFF || l == 0)
+ continue;
+ p = malloc(sizeof(*p));
+ p->tbdf = tbdf;
+ p->vid = l;
+ p->did = l>>16;
+
+ if(pcilist != nil)
+ pcitail->list = p;
+ else
+ pcilist = p;
+ pcitail = p;
+
+ p->rid = pcicfgr8(p, PciRID);
+ p->ccrp = pcicfgr8(p, PciCCRp);
+ p->ccru = pcicfgr8(p, PciCCRu);
+ p->ccrb = pcicfgr8(p, PciCCRb);
+ p->pcr = pcicfgr32(p, PciPCR);
+
+ p->intl = pcicfgr8(p, PciINTL);
+
+ /*
+ * If the device is a multi-function device adjust the
+ * loop count so all possible functions are checked.
+ */
+ hdt = pcicfgr8(p, PciHDT);
+ if(hdt & 0x80)
+ maxfno = MaxFNO;
+
+ /*
+ * If appropriate, read the base address registers
+ * and work out the sizes.
+ */
+ switch(p->ccrb) {
+ case 0x01: /* mass storage controller */
+ case 0x02: /* network controller */
+ case 0x03: /* display controller */
+ case 0x04: /* multimedia device */
+ case 0x06: /* bridge device */
+ case 0x07: /* simple comm. controllers */
+ case 0x08: /* base system peripherals */
+ case 0x09: /* input devices */
+ case 0x0A: /* docking stations */
+ case 0x0B: /* processors */
+ case 0x0C: /* serial bus controllers */
+ if((hdt & 0x7F) != 0)
+ break;
+ rno = PciBAR0 - 4;
+ for(i = 0; i < nelem(p->mem); i++) {
+ rno += 4;
+ p->mem[i].bar = pcicfgr32(p, rno);
+ p->mem[i].size = pcibarsize(p, rno);
+ }
+ break;
+
+ case 0x00:
+ case 0x05: /* memory controller */
+ default:
+ break;
+ }
+
+ if(head != nil)
+ tail->link = p;
+ else
+ head = p;
+ tail = p;
+ }
+ }
+
+ *list = head;
+ for(p = head; p != nil; p = p->link){
+ /*
+ * Find PCI-PCI bridges and recursively descend the tree.
+ */
+ if(p->ccrb != 0x06 || p->ccru != 0x04)
+ continue;
+
+ /*
+ * If the secondary or subordinate bus number is not
+ * initialised try to do what the PCI BIOS should have
+ * done and fill in the numbers as the tree is descended.
+ * On the way down the subordinate bus number is set to
+ * the maximum as it's not known how many buses are behind
+ * this one; the final value is set on the way back up.
+ */
+ sbn = pcicfgr8(p, PciSBN);
+ ubn = pcicfgr8(p, PciUBN);
+
+ if(sbn == 0 || ubn == 0) {
+ sbn = maxubn+1;
+ /*
+ * Make sure memory, I/O and master enables are
+ * off, set the primary, secondary and subordinate
+ * bus numbers and clear the secondary status before
+ * attempting to scan the secondary bus.
+ *
+ * Initialisation of the bridge should be done here.
+ */
+ pcicfgw32(p, PciPCR, 0xFFFF0000);
+ l = (MaxUBN<<16)|(sbn<<8)|bno;
+ pcicfgw32(p, PciPBN, l);
+ pcicfgw16(p, PciSPSR, 0xFFFF);
+ maxubn = pcilscan(sbn, &p->bridge);
+ l = (maxubn<<16)|(sbn<<8)|bno;
+
+ pcicfgw32(p, PciPBN, l);
+ }
+ else {
+ maxubn = ubn;
+ pcilscan(sbn, &p->bridge);
+ }
+ }
+
+ return maxubn;
+}
+
+int
+pciscan(int bno, Pcidev **list)
+{
+ int ubn;
+
+ qlock(&pcicfginitlock);
+ ubn = pcilscan(bno, list);
+ qunlock(&pcicfginitlock);
+ return ubn;
+}
+
+static void
+pcicfginit(void)
+{
+ char *p;
+ int bno;
+ Pcidev **list;
+ ulong mema, ioa;
+
+ qlock(&pcicfginitlock);
+ if(pcicfgmode != -1)
+ goto out;
+
+ /*
+ * Try to determine which PCI configuration mode is implemented.
+ * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
+ * a DWORD at 0xCF8 and another at 0xCFC and will pass through
+ * any non-DWORD accesses as normal I/O cycles. There shouldn't be
+ * a device behind these addresses so if Mode2 accesses fail try
+ * for Mode1 (which is preferred, Mode2 is deprecated).
+ */
+ outb(PciCSE, 0);
+ if(inb(PciCSE) == 0){
+ pcicfgmode = 2;
+ pcimaxdno = 15;
+ }
+ else {
+ outl(PciADDR, 0);
+ if(inl(PciADDR) == 0){
+ pcicfgmode = 1;
+ pcimaxdno = 31;
+ }
+ }
+
+ if(pcicfgmode < 0)
+ goto out;
+
+ fmtinstall('T', tbdffmt);
+
+ if(p = getconf("*pcimaxbno"))
+ pcimaxbno = strtoul(p, 0, 0);
+ if(p = getconf("*pcimaxdno"))
+ pcimaxdno = strtoul(p, 0, 0);
+
+ list = &pciroot;
+ for(bno = 0; bno <= pcimaxbno; bno++) {
+ int sbno = bno;
+ bno = pcilscan(bno, list);
+
+ while(*list)
+ list = &(*list)->link;
+
+ if (sbno == 0) {
+ Pcidev *pci;
+
+ /*
+ * If we have found a PCI-to-Cardbus bridge, make sure
+ * it has no valid mappings anymore.
+ */
+ pci = pciroot;
+ while (pci) {
+ if (pci->ccrb == 6 && pci->ccru == 7) {
+ ushort bcr;
+
+ /* reset the cardbus */
+ bcr = pcicfgr16(pci, PciBCR);
+ pcicfgw16(pci, PciBCR, 0x40 | bcr);
+ delay(50);
+ }
+ pci = pci->link;
+ }
+ }
+ }
+
+ if(pciroot == nil)
+ goto out;
+
+ /*
+ * Work out how big the top bus is
+ */
+ mema = 0;
+ ioa = 0;
+ pcibusmap(pciroot, &mema, &ioa, 0);
+
+ DBG("Sizes: mem=%8.8lux size=%8.8lux io=%8.8lux\n",
+ mema, pcimask(mema), ioa);
+
+ /*
+ * Align the windows and map it
+ */
+ ioa = 0x1000;
+ mema = 0;
+
+ pcilog("Mask sizes: mem=%lux io=%lux\n", mema, ioa);
+
+ pcibusmap(pciroot, &mema, &ioa, 1);
+ DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa);
+
+out:
+ qunlock(&pcicfginitlock);
+}
+
+static int
+pcicfgrw8(int tbdf, int rno, int data, int read)
+{
+ int o, type, x;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(BUSBNO(tbdf))
+ type = 0x01;
+ else
+ type = 0x00;
+ x = -1;
+ if(BUSDNO(tbdf) > pcimaxdno)
+ return x;
+
+ lock(&pcicfglock);
+ switch(pcicfgmode){
+
+ case 1:
+ o = rno & 0x03;
+ rno &= ~0x03;
+ outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+ if(read)
+ x = inb(PciDATA+o);
+ else
+ outb(PciDATA+o, data);
+ outl(PciADDR, 0);
+ break;
+
+ case 2:
+ outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
+ outb(PciFORWARD, BUSBNO(tbdf));
+ if(read)
+ x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
+ else
+ outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
+ outb(PciCSE, 0);
+ break;
+ }
+ unlock(&pcicfglock);
+
+ return x;
+}
+
+int
+pcicfgr8(Pcidev* pcidev, int rno)
+{
+ return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw8(Pcidev* pcidev, int rno, int data)
+{
+ pcicfgrw8(pcidev->tbdf, rno, data, 0);
+}
+
+static int
+pcicfgrw16(int tbdf, int rno, int data, int read)
+{
+ int o, type, x;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(BUSBNO(tbdf))
+ type = 0x01;
+ else
+ type = 0x00;
+ x = -1;
+ if(BUSDNO(tbdf) > pcimaxdno)
+ return x;
+
+ lock(&pcicfglock);
+ switch(pcicfgmode){
+
+ case 1:
+ o = rno & 0x02;
+ rno &= ~0x03;
+ outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+ if(read)
+ x = ins(PciDATA+o);
+ else
+ outs(PciDATA+o, data);
+ outl(PciADDR, 0);
+ break;
+
+ case 2:
+ outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
+ outb(PciFORWARD, BUSBNO(tbdf));
+ if(read)
+ x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
+ else
+ outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
+ outb(PciCSE, 0);
+ break;
+ }
+ unlock(&pcicfglock);
+
+ return x;
+}
+
+int
+pcicfgr16(Pcidev* pcidev, int rno)
+{
+ return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw16(Pcidev* pcidev, int rno, int data)
+{
+ pcicfgrw16(pcidev->tbdf, rno, data, 0);
+}
+
+static int
+pcicfgrw32(int tbdf, int rno, int data, int read)
+{
+ int type, x;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(BUSBNO(tbdf))
+ type = 0x01;
+ else
+ type = 0x00;
+ x = -1;
+ if(BUSDNO(tbdf) > pcimaxdno)
+ return x;
+
+ lock(&pcicfglock);
+ switch(pcicfgmode){
+
+ case 1:
+ rno &= ~0x03;
+ outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+ if(read)
+ x = inl(PciDATA);
+ else
+ outl(PciDATA, data);
+ outl(PciADDR, 0);
+ break;
+
+ case 2:
+ outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
+ outb(PciFORWARD, BUSBNO(tbdf));
+ if(read)
+ x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
+ else
+ outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
+ outb(PciCSE, 0);
+ break;
+ }
+ unlock(&pcicfglock);
+
+ return x;
+}
+
+int
+pcicfgr32(Pcidev* pcidev, int rno)
+{
+ return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw32(Pcidev* pcidev, int rno, int data)
+{
+ pcicfgrw32(pcidev->tbdf, rno, data, 0);
+}
+
+Pcidev*
+pcimatch(Pcidev* prev, int vid, int did)
+{
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(prev == nil)
+ prev = pcilist;
+ else
+ prev = prev->list;
+
+ while(prev != nil){
+ if((vid == 0 || prev->vid == vid)
+ && (did == 0 || prev->did == did))
+ break;
+ prev = prev->list;
+ }
+ return prev;
+}
+
+Pcidev*
+pcimatchtbdf(int tbdf)
+{
+ Pcidev *pcidev;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
+ if(pcidev->tbdf == tbdf)
+ break;
+ }
+ return pcidev;
+}
+
+uchar
+pciipin(Pcidev *pci, uchar pin)
+{
+ if (pci == nil)
+ pci = pcilist;
+
+ while (pci) {
+ uchar intl;
+
+ if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)
+ return pci->intl;
+
+ if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)
+ return intl;
+
+ pci = pci->list;
+ }
+ return 0;
+}
+
+static void
+pcilhinv(Pcidev* p)
+{
+ int i;
+ Pcidev *t;
+
+ if(p == nil) {
+ putstrn(PCICONS.output, PCICONS.ptr);
+ p = pciroot;
+ print("bus dev type vid did intl memory\n");
+ }
+ for(t = p; t != nil; t = t->link) {
+ print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d ",
+ BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
+ t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
+
+ for(i = 0; i < nelem(p->mem); i++) {
+ if(t->mem[i].size == 0)
+ continue;
+ print("%d:%.8lux %d ", i,
+ t->mem[i].bar, t->mem[i].size);
+ }
+ if(t->ioa.bar || t->ioa.size)
+ print("ioa:%.8lux %d ", t->ioa.bar, t->ioa.size);
+ if(t->mema.bar || t->mema.size)
+ print("mema:%.8lux %d ", t->mema.bar, t->mema.size);
+ if(t->bridge)
+ print("->%d", BUSBNO(t->bridge->tbdf));
+ print("\n");
+ }
+ while(p != nil) {
+ if(p->bridge != nil)
+ pcilhinv(p->bridge);
+ p = p->link;
+ }
+}
+
+void
+pcihinv(Pcidev* p)
+{
+ if(pcicfgmode == -1)
+ pcicfginit();
+ qlock(&pcicfginitlock);
+ pcilhinv(p);
+ qunlock(&pcicfginitlock);
+}
+
+void
+pcireset(void)
+{
+ Pcidev *p;
+ int pcr;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ for(p = pcilist; p != nil; p = p->list){
+ pcr = pcicfgr16(p, PciPCR);
+ pcr &= ~0x0004;
+ pcicfgw16(p, PciPCR, pcr);
+ }
+}
+
+void
+pcisetbme(Pcidev* p)
+{
+ int pcr;
+
+ pcr = pcicfgr16(p, PciPCR);
+ pcr |= MASen;
+ pcicfgw16(p, PciPCR, pcr);
+}
+
+void
+pciclrbme(Pcidev* p)
+{
+ int pcr;
+
+ pcr = pcicfgr16(p, PciPCR);
+ pcr &= ~MASen;
+ pcicfgw16(p, PciPCR, pcr);
+}
diff --git a/sys/src/9/mtx/random.c b/sys/src/9/mtx/random.c
new file mode 100755
index 000000000..3c204b8d1
--- /dev/null
+++ b/sys/src/9/mtx/random.c
@@ -0,0 +1,138 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+
+struct Rb
+{
+ QLock;
+ Rendez producer;
+ Rendez consumer;
+ ulong randomcount;
+ uchar buf[1024];
+ uchar *ep;
+ uchar *rp;
+ uchar *wp;
+ uchar next;
+ uchar wakeme;
+ ushort bits;
+ ulong randn;
+} rb;
+
+static int
+rbnotfull(void*)
+{
+ int i;
+
+ i = rb.rp - rb.wp;
+ return i != 1 && i != (1 - sizeof(rb.buf));
+}
+
+static int
+rbnotempty(void*)
+{
+ return rb.wp != rb.rp;
+}
+
+static void
+genrandom(void*)
+{
+ up->basepri = PriNormal;
+ up->priority = up->basepri;
+
+ for(;;){
+ for(;;)
+ if(++rb.randomcount > 100000)
+ break;
+ if(anyhigher())
+ sched();
+ if(!rbnotfull(0))
+ sleep(&rb.producer, rbnotfull, 0);
+ }
+}
+
+/*
+ * produce random bits in a circular buffer
+ */
+static void
+randomclock(void)
+{
+ if(rb.randomcount == 0 || !rbnotfull(0))
+ return;
+
+ rb.bits = (rb.bits<<2) ^ rb.randomcount;
+ rb.randomcount = 0;
+
+ rb.next++;
+ if(rb.next != 8/2)
+ return;
+ rb.next = 0;
+
+ *rb.wp ^= rb.bits;
+ if(rb.wp+1 == rb.ep)
+ rb.wp = rb.buf;
+ else
+ rb.wp = rb.wp+1;
+
+ if(rb.wakeme)
+ wakeup(&rb.consumer);
+}
+
+void
+randominit(void)
+{
+ addclock0link(randomclock, 1000/HZ);
+ rb.ep = rb.buf + sizeof(rb.buf);
+ rb.rp = rb.wp = rb.buf;
+ kproc("genrandom", genrandom, 0);
+}
+
+/*
+ * consume random bytes from a circular buffer
+ */
+ulong
+randomread(void *xp, ulong n)
+{
+ uchar *e, *p;
+ ulong x;
+
+ p = xp;
+
+ if(waserror()){
+ qunlock(&rb);
+ nexterror();
+ }
+
+ qlock(&rb);
+ for(e = p + n; p < e; ){
+ if(rb.wp == rb.rp){
+ rb.wakeme = 1;
+ wakeup(&rb.producer);
+ sleep(&rb.consumer, rbnotempty, 0);
+ rb.wakeme = 0;
+ continue;
+ }
+
+ /*
+ * beating clocks will be precictable if
+ * they are synchronized. Use a cheap pseudo
+ * random number generator to obscure any cycles.
+ */
+ x = rb.randn*1103515245 ^ *rb.rp;
+ *p++ = rb.randn = x;
+
+ if(rb.rp+1 == rb.ep)
+ rb.rp = rb.buf;
+ else
+ rb.rp = rb.rp+1;
+ }
+ qunlock(&rb);
+ poperror();
+
+ wakeup(&rb.producer);
+
+ return n;
+}
diff --git a/sys/src/9/mtx/raven.c b/sys/src/9/mtx/raven.c
new file mode 100755
index 000000000..d6fcb0179
--- /dev/null
+++ b/sys/src/9/mtx/raven.c
@@ -0,0 +1,153 @@
+/*
+ * ``Nevermore!''
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+typedef struct Raven Raven;
+struct Raven
+{
+ ushort vid;
+ ushort did;
+ uchar _pad4;
+ uchar rev;
+ uchar _pad6[2];
+ ushort gcsr;
+ ushort feat;
+ uchar _padC[7];
+ uchar padj;
+ uchar _pad14[12];
+ ushort errtst;
+ ushort erren;
+ uchar _pad24[3];
+ uchar errst;
+ ulong errad;
+ uchar _pad2C[2];
+ ushort errat;
+ ulong piack;
+ uchar _pad34[12];
+
+ struct {
+ ushort start;
+ ushort end;
+ ushort off;
+ uchar _pad;
+ uchar attr;
+ } map[4];
+
+ struct {
+ ulong cntl;
+ uchar _pad[3];
+ uchar stat;
+ } wdt[2];
+
+ ulong gpr[4];
+};
+
+enum {
+ /* map[] attr bits */
+ Iom = (1<<0),
+ Mem = (1<<1),
+ Wpen = (1<<4),
+ Wen = (1<<6),
+ Ren = (1<<7),
+};
+
+static Raven *raven = (Raven*)RAVEN;
+static ulong mpic;
+
+static void
+setmap(int i, ulong addr, ulong len, ulong busaddr, int attr)
+{
+ raven->map[i].start = addr>>16;
+ raven->map[i].end = (addr+len-1)>>16;
+ raven->map[i].off = (busaddr-addr)>>16;
+ raven->map[i].attr = attr;
+}
+
+static ulong
+swap32(ulong x)
+{
+ return (x>>24)|((x>>8)&0xff00)|((x<<8)&0xff0000)|(x<<24);
+}
+
+static ulong
+mpic32r(int rno)
+{
+ return swap32(*(ulong*)(mpic+rno));
+}
+
+static void
+mpic32w(int rno, ulong x)
+{
+ *(ulong*)(mpic+rno) = swap32(x);
+ eieio();
+}
+
+void
+raveninit(void)
+{
+ int i;
+ Pcidev *p;
+
+ if(raven->vid != 0x1057 || raven->did !=0x4801)
+ panic("raven not found");
+
+ /* set up a sensible hardware memory/IO map */
+ setmap(0, PCIMEM0, PCISIZE0, 0, Wen|Ren|Mem);
+ setmap(1, KZERO, IOSIZE, 0, Wen|Ren); /* keeps PPCbug happy */
+ setmap(2, PCIMEM1, PCISIZE1, PCISIZE0, Wen|Ren|Mem);
+ setmap(3, IOMEM, IOSIZE, 0, Wen|Ren); /* I/O must be slot 3 for PCI cfg space */
+
+ p = pcimatch(nil, 0x1057, 0x4801);
+ if(p == nil)
+ panic("raven PCI regs not found");
+ mpic = (p->mem[1].bar+PCIMEM0);
+
+ /* ensure all interrupts are off, and routed to cpu 0 */
+ for(i = 0; i < 16; i++) {
+ mpic32w(0x10000+0x20*i, (1<<31)); /* mask */
+ mpic32w(0x10010+0x20*i, 1); /* route to cpu 0 */
+ }
+
+ mpic32w(0x20080, 1); /* cpu 0 task pri */
+// mpic32w(0x21080, 1); /* cpu 1 task pri */
+ mpic32w(0x1020, (1<<29)); /* Mixed mode (8259 & Raven intrs both available) */
+}
+
+void
+mpicenable(int vec, Vctl *v)
+{
+ ulong x;
+
+ x = (1<<22)|(15<<16)|vec;
+ if(vec == 0)
+ x |= (1<<23);
+ mpic32w(0x10000+0x20*vec, x);
+ if(vec != 0)
+ v->eoi = mpiceoi;
+}
+
+void
+mpicdisable(int vec)
+{
+ mpic32w(0x10000+0x20*vec, (1<<31));
+}
+
+int
+mpicintack(void)
+{
+ return mpic32r(0x200A0 + (m->machno<<12));
+}
+
+int
+mpiceoi(int vec)
+{
+ USED(vec);
+ mpic32w(0x200B0 + (m->machno<<12), 0);
+ return 0;
+}
diff --git a/sys/src/9/mtx/trap.c b/sys/src/9/mtx/trap.c
new file mode 100755
index 000000000..767e96c3b
--- /dev/null
+++ b/sys/src/9/mtx/trap.c
@@ -0,0 +1,836 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "ureg.h"
+#include "io.h"
+#include "tos.h"
+#include "../port/error.h"
+
+static Lock vctllock;
+static Vctl *vctl[256];
+
+void
+hwintrinit(void)
+{
+ i8259init();
+ mpicenable(0, nil); /* 8259 interrupts are routed through MPIC intr 0 */
+}
+
+static int
+hwintrenable(Vctl *v)
+{
+ int vec, irq;
+
+ irq = v->irq;
+ if(BUSTYPE(v->tbdf) == BusPCI) { /* MPIC? */
+ if(irq > 15) {
+ print("intrenable: pci irq %d out of range\n", v->irq);
+ return -1;
+ }
+ vec = irq;
+ mpicenable(vec, v);
+ }
+ else {
+ if(irq > MaxIrqPIC) {
+ print("intrenable: irq %d out of range\n", v->irq);
+ return -1;
+ }
+ vec = irq+VectorPIC;
+ if(i8259enable(v) == -1)
+ return -1;
+ }
+ return vec;
+}
+
+static int
+hwintrdisable(Vctl *v)
+{
+ int vec, irq;
+
+ irq = v->irq;
+ if(BUSTYPE(v->tbdf) == BusPCI) { /* MPIC? */
+ if(irq > 15) {
+ print("intrdisable: pci irq %d out of range\n", v->irq);
+ return -1;
+ }
+ vec = irq;
+ mpicdisable(vec);
+ }
+ else {
+ if(irq > MaxIrqPIC) {
+ print("intrdisable: irq %d out of range\n", v->irq);
+ return -1;
+ }
+ vec = irq+VectorPIC;
+ if(i8259disable(irq) == -1)
+ return -1;
+ }
+ return vec;
+}
+
+static int
+hwvecno(int irq, int tbdf)
+{
+ if(BUSTYPE(tbdf) == BusPCI) /* MPIC? */
+ return irq;
+ else
+ return irq+VectorPIC;
+}
+
+void
+intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
+{
+ int vno;
+ Vctl *v;
+
+ if(f == nil){
+ print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n",
+ irq, tbdf, name);
+ return;
+ }
+
+ v = xalloc(sizeof(Vctl));
+ v->isintr = 1;
+ v->irq = irq;
+ v->tbdf = tbdf;
+ v->f = f;
+ v->a = a;
+ strncpy(v->name, name, KNAMELEN-1);
+ v->name[KNAMELEN-1] = 0;
+
+ ilock(&vctllock);
+ vno = hwintrenable(v);
+ if(vno == -1){
+ iunlock(&vctllock);
+ print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n",
+ irq, tbdf, v->name);
+ xfree(v);
+ return;
+ }
+ if(vctl[vno]){
+ if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)
+ panic("intrenable: handler: %s %s %#p %#p %#p %#p",
+ vctl[vno]->name, v->name,
+ vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);
+ v->next = vctl[vno];
+ }
+ vctl[vno] = v;
+ iunlock(&vctllock);
+}
+
+void
+intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
+{
+ Vctl **pv, *v;
+ int vno;
+
+ vno = hwvecno(irq, tbdf);
+ ilock(&vctllock);
+ pv = &vctl[vno];
+ while (*pv &&
+ ((*pv)->irq != irq || (*pv)->tbdf != tbdf || (*pv)->f != f || (*pv)->a != a ||
+ strcmp((*pv)->name, name)))
+ pv = &((*pv)->next);
+ assert(*pv);
+
+ v = *pv;
+ *pv = (*pv)->next; /* Link out the entry */
+
+ if(vctl[vno] == nil)
+ hwintrdisable(v);
+ iunlock(&vctllock);
+ xfree(v);
+}
+
+void syscall(Ureg*);
+void noted(Ureg*, ulong);
+static void _dumpstack(Ureg*);
+
+char *excname[] =
+{
+ "reserved 0",
+ "system reset",
+ "machine check",
+ "data access",
+ "instruction access",
+ "external interrupt",
+ "alignment",
+ "program exception",
+ "floating-point unavailable",
+ "decrementer",
+ "reserved A",
+ "reserved B",
+ "system call",
+ "trace trap",
+ "floating point assist",
+ "reserved F",
+ "reserved 10",
+ "reserved 11",
+ "reserved 12",
+ "instruction address breakpoint",
+ "system management interrupt",
+};
+
+char *fpcause[] =
+{
+ "inexact operation",
+ "division by zero",
+ "underflow",
+ "overflow",
+ "invalid operation",
+};
+char *fpexcname(Ureg*, ulong, char*);
+#define FPEXPMASK 0xfff80300 /* Floating exception bits in fpscr */
+
+
+char *regname[]={
+ "CAUSE", "SRR1",
+ "PC", "GOK",
+ "LR", "CR",
+ "XER", "CTR",
+ "R0", "R1",
+ "R2", "R3",
+ "R4", "R5",
+ "R6", "R7",
+ "R8", "R9",
+ "R10", "R11",
+ "R12", "R13",
+ "R14", "R15",
+ "R16", "R17",
+ "R18", "R19",
+ "R20", "R21",
+ "R22", "R23",
+ "R24", "R25",
+ "R26", "R27",
+ "R28", "R29",
+ "R30", "R31",
+};
+
+void
+trap(Ureg *ureg)
+{
+ ulong dsisr;
+ int ecode, user;
+ char buf[ERRMAX], *s;
+
+ ecode = (ureg->cause >> 8) & 0xff;
+ user = (ureg->srr1 & MSR_PR) != 0;
+ if(user)
+ up->dbgreg = ureg;
+
+ if(ureg->status & MSR_RI == 0)
+ print("double fault?: ecode = %d\n", ecode);
+
+ switch(ecode) {
+ case CEI:
+ intr(ureg);
+ break;
+ case CDEC:
+ clockintr(ureg);
+ break;
+ case CSYSCALL:
+ if(!user)
+ panic("syscall in kernel: srr1 0x%4.4luX", ureg->srr1);
+ syscall(ureg);
+ return; /* syscall() calls notify itself, don't do it again */
+ case CFPU:
+ if(!user || up == nil) {
+ dumpregs(ureg);
+ panic("floating point in kernel");
+ }
+ switch(up->fpstate){
+ case FPinit:
+ fprestore(&initfp);
+ up->fpstate = FPactive;
+ break;
+ case FPinactive:
+ fprestore(&up->fpsave);
+ up->fpstate = FPactive;
+ break;
+ default:
+ panic("fpstate");
+ }
+ ureg->srr1 |= MSR_FP;
+ break;
+ case CISI:
+ faultpower(ureg, ureg->pc, 1);
+ break;
+ case CDSI:
+ dsisr = getdsisr();
+ if(dsisr & BIT(6))
+ faultpower(ureg, getdar(), 0);
+ else
+ faultpower(ureg, getdar(), 1);
+ break;
+ case CPROG:
+ if(ureg->status & (1<<19))
+ s = "floating point exception";
+ else if(ureg->status & (1<<18))
+ s = "illegal instruction";
+ else if(ureg->status & (1<<17))
+ s = "privileged instruction";
+ else
+ s = "undefined program exception";
+ if(user){
+ spllo();
+ sprint(buf, "sys: trap: %s", s);
+ postnote(up, 1, buf, NDebug);
+ break;
+ }
+ dumpregs(ureg);
+ panic(s);
+ break;
+ default:
+ if(ecode < nelem(excname) && user){
+ spllo();
+ sprint(buf, "sys: trap: %s", excname[ecode]);
+ postnote(up, 1, buf, NDebug);
+ break;
+ }
+ dumpregs(ureg);
+ if(ecode < nelem(excname))
+ panic("%s", excname[ecode]);
+ panic("unknown trap/intr: %d", ecode);
+ }
+
+ /* restoreureg must execute at high IPL */
+ splhi();
+
+ /* delaysched set because we held a lock or because our quantum ended */
+ if(up && up->delaysched && ecode == CDEC){
+ sched();
+ splhi();
+ }
+
+ if(user) {
+ notify(ureg);
+ if(up->fpstate == FPinactive)
+ ureg->srr1 &= ~MSR_FP;
+ kexit(ureg);
+ }
+}
+
+void
+faultpower(Ureg *ureg, ulong addr, int read)
+{
+ int user, insyscall, n;
+ char buf[ERRMAX];
+
+ user = (ureg->srr1 & MSR_PR) != 0;
+ insyscall = up->insyscall;
+ up->insyscall = 1;
+ n = fault(addr, read);
+ if(n < 0){
+ if(!user){
+ dumpregs(ureg);
+ panic("fault: 0x%lux", addr);
+ }
+ sprint(buf, "sys: trap: fault %s addr=0x%lux", read? "read" : "write", addr);
+ postnote(up, 1, buf, NDebug);
+ }
+ up->insyscall = insyscall;
+}
+
+void
+sethvec(int v, void (*r)(void))
+{
+ ulong *vp, pa, o;
+
+ vp = KADDR(v);
+ vp[0] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */
+ vp[1] = 0x7c0802a6; /* MOVW LR, R0 */
+ vp[2] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */
+ pa = PADDR(r);
+ o = pa >> 25;
+ if(o != 0 && o != 0x7F){
+ /* a branch too far */
+ vp[3] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */
+ vp[4] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
+ vp[5] = 0x7c0803a6; /* MOVW R0, LR */
+ vp[6] = 0x4e800021; /* BL (LR) */
+ }else
+ vp[3] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */
+ dcflush(vp, 8*sizeof(ulong));
+}
+
+void
+trapinit(void)
+{
+ int i;
+
+ /*
+ * set all exceptions to trap
+ */
+ for(i = 0; i < 0x2000; i += 0x100)
+ sethvec(i, trapvec);
+
+ putmsr(getmsr() & ~MSR_IP);
+}
+
+void
+intr(Ureg *ureg)
+{
+ int vno;
+ Vctl *ctl, *v;
+
+ vno = mpicintack();
+ if(vno == 0) { /* 8259, wired through MPIC vec 0 */
+ vno = i8259intack();
+ mpiceoi(0);
+ }
+
+ if(vno > nelem(vctl) || (ctl = vctl[vno]) == 0) {
+ panic("spurious intr %d", vno);
+ return;
+ }
+
+ if(ctl->isr)
+ ctl->isr(vno);
+ for(v = ctl; v != nil; v = v->next){
+ if(v->f)
+ v->f(ureg, v->a);
+ }
+ if(ctl->eoi)
+ ctl->eoi(vno);
+
+ if(up)
+ preempted();
+}
+
+char*
+fpexcname(Ureg *ur, ulong fpscr, char *buf)
+{
+ int i;
+ char *s;
+ ulong fppc;
+
+ fppc = ur->pc;
+ s = 0;
+ fpscr >>= 3; /* trap enable bits */
+ fpscr &= (fpscr>>22); /* anded with exceptions */
+ for(i=0; i<5; i++)
+ if(fpscr & (1<<i))
+ s = fpcause[i];
+ if(s == 0)
+ return "no floating point exception";
+ sprint(buf, "%s fppc=0x%lux", s, fppc);
+ return buf;
+}
+
+/*
+ * Fill in enough of Ureg to get a stack trace, and call a function.
+ * Used by debugging interface rdb.
+ */
+
+static void
+getpcsp(ulong *pc, ulong *sp)
+{
+ *pc = getcallerpc(&pc);
+ *sp = (ulong)&pc-4;
+}
+
+void
+callwithureg(void (*fn)(Ureg*))
+{
+ Ureg ureg;
+
+ getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
+ ureg.lr = getcallerpc(&fn);
+ fn(&ureg);
+}
+
+static void
+_dumpstack(Ureg *ureg)
+{
+ ulong l, sl, el, v;
+ int i;
+
+ l = (ulong)&l;
+ if(up == 0){
+ el = (ulong)m+BY2PG;
+ sl = el-KSTACK;
+ }
+ else{
+ sl = (ulong)up->kstack;
+ el = sl + KSTACK;
+ }
+ if(l > el || l < sl){
+ el = (ulong)m+BY2PG;
+ sl = el-KSTACK;
+ }
+ if(l > el || l < sl)
+ return;
+ print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->lr);
+ i = 0;
+ for(; l < el; l += 4){
+ v = *(ulong*)l;
+ if(KTZERO < v && v < (ulong)etext){
+ print("%.8lux=%.8lux ", l, v);
+ if(i++ == 4){
+ print("\n");
+ i = 0;
+ }
+ }
+ }
+}
+
+void
+dumpstack(void)
+{
+ callwithureg(_dumpstack);
+}
+
+void
+dumpregs(Ureg *ur)
+{
+ int i;
+ ulong *l;
+
+ if(up) {
+ print("registers for %s %ld\n", up->text, up->pid);
+ if(ur->srr1 & MSR_PR == 0)
+ if(ur->usp < (ulong)up->kstack || ur->usp > (ulong)up->kstack+KSTACK)
+ print("invalid stack ptr\n");
+ }
+ else
+ print("registers for kernel\n");
+
+ print("dsisr\t%.8lux\tdar\t%.8lux\n", getdsisr(), getdar());
+ l = &ur->cause;
+ for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
+ print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
+}
+
+static void
+linkproc(void)
+{
+ spllo();
+ (*up->kpfun)(up->kparg);
+ pexit("", 0);
+}
+
+void
+kprocchild(Proc *p, void (*func)(void*), void *arg)
+{
+ p->sched.pc = (ulong)linkproc;
+ p->sched.sp = (ulong)p->kstack+KSTACK;
+
+ p->kpfun = func;
+ p->kparg = arg;
+}
+
+/*
+ * called in sysfile.c
+ */
+void
+evenaddr(ulong addr)
+{
+ if(addr & 3){
+ postnote(up, 1, "sys: odd address", NDebug);
+ error(Ebadarg);
+ }
+}
+
+long
+execregs(ulong entry, ulong ssize, ulong nargs)
+{
+ ulong *sp;
+ Ureg *ureg;
+
+ sp = (ulong*)(USTKTOP - ssize);
+ *--sp = nargs;
+
+ ureg = up->dbgreg;
+ ureg->usp = (ulong)sp;
+ ureg->pc = entry;
+ ureg->srr1 &= ~MSR_FP;
+ return USTKTOP-sizeof(Tos); /* address of kernel/user shared data */
+}
+
+void
+forkchild(Proc *p, Ureg *ur)
+{
+ Ureg *cur;
+
+ p->sched.sp = (ulong)p->kstack+KSTACK-UREGSIZE;
+ p->sched.pc = (ulong)forkret;
+
+ cur = (Ureg*)(p->sched.sp+2*BY2WD);
+ memmove(cur, ur, sizeof(Ureg));
+ cur->r3 = 0;
+
+ /* Things from bottom of syscall we never got to execute */
+ p->psstate = 0;
+ p->insyscall = 0;
+}
+
+ulong
+userpc(void)
+{
+ Ureg *ureg;
+
+ ureg = (Ureg*)up->dbgreg;
+ return ureg->pc;
+}
+
+
+/* This routine must save the values of registers the user is not
+ * permitted to write from devproc and then restore the saved values
+ * before returning
+ */
+void
+setregisters(Ureg *xp, char *pureg, char *uva, int n)
+{
+ ulong status;
+
+ status = xp->status;
+ memmove(pureg, uva, n);
+ xp->status = status;
+}
+
+/* Give enough context in the ureg to produce a kernel stack for
+ * a sleeping process
+ */
+void
+setkernur(Ureg* ureg, Proc* p)
+{
+ ureg->pc = p->sched.pc;
+ ureg->sp = p->sched.sp+4;
+}
+
+ulong
+dbgpc(Proc *p)
+{
+ Ureg *ureg;
+
+ ureg = p->dbgreg;
+ if(ureg == 0)
+ return 0;
+
+ return ureg->pc;
+}
+
+/*
+ * system calls
+ */
+#include "../port/systab.h"
+
+/* TODO: make this trap a separate asm entry point, like on other RISC architectures */
+void
+syscall(Ureg* ureg)
+{
+ int i;
+ char *e;
+ long ret;
+ ulong sp, scallnr;
+
+ m->syscall++;
+ up->insyscall = 1;
+ up->pc = ureg->pc;
+ up->dbgreg = ureg;
+
+ scallnr = ureg->r3;
+ up->scallnr = ureg->r3;
+ spllo();
+
+ sp = ureg->usp;
+ up->nerrlab = 0;
+ ret = -1;
+ if(!waserror()){
+ if(scallnr >= nsyscall || systab[scallnr] == nil){
+ pprint("bad sys call number %d pc %lux\n", scallnr, ureg->pc);
+ postnote(up, 1, "sys: bad sys call", NDebug);
+ error(Ebadarg);
+ }
+
+ if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
+ validaddr(sp, sizeof(Sargs)+BY2WD, 0);
+
+ up->s = *((Sargs*)(sp+BY2WD));
+ up->psstate = sysctab[scallnr];
+
+ ret = systab[scallnr](up->s.args);
+ poperror();
+ }else{
+ /* failure: save the error buffer for errstr */
+ e = up->syserrstr;
+ up->syserrstr = up->errstr;
+ up->errstr = e;
+ }
+ if(up->nerrlab){
+ print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
+ print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr);
+ for(i = 0; i < NERR; i++)
+ print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
+ panic("error stack");
+ }
+
+ up->insyscall = 0;
+ up->psstate = 0;
+
+ /*
+ * Put return value in frame. On the x86 the syscall is
+ * just another trap and the return value from syscall is
+ * ignored. On other machines the return value is put into
+ * the results register by caller of syscall.
+ */
+ ureg->r3 = ret;
+
+ if(scallnr == NOTED)
+ noted(ureg, *(ulong*)(sp+BY2WD));
+
+ /* restoreureg must execute at high IPL */
+ splhi();
+ if(scallnr!=RFORK)
+ notify(ureg);
+ if(up->fpstate == FPinactive)
+ ureg->srr1 &= ~MSR_FP;
+}
+
+/*
+ * Call user, if necessary, with note.
+ * Pass user the Ureg struct and the note on his stack.
+ */
+int
+notify(Ureg* ur)
+{
+ int l;
+ ulong s, sp;
+ Note *n;
+
+ if(up->procctl)
+ procctl(up);
+ if(up->nnote == 0)
+ return 0;
+
+ s = spllo();
+ qlock(&up->debug);
+ up->notepending = 0;
+ n = &up->note[0];
+ if(strncmp(n->msg, "sys:", 4) == 0){
+ l = strlen(n->msg);
+ if(l > ERRMAX-15) /* " pc=0x12345678\0" */
+ l = ERRMAX-15;
+ sprint(n->msg+l, " pc=0x%.8lux", ur->pc);
+ }
+
+ if(n->flag!=NUser && (up->notified || up->notify==0)){
+ if(n->flag == NDebug)
+ pprint("suicide: %s\n", n->msg);
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag!=NDebug);
+ }
+
+ if(up->notified) {
+ qunlock(&up->debug);
+ splhi();
+ return 0;
+ }
+
+ if(!up->notify) {
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag!=NDebug);
+ }
+ sp = ur->usp & ~(BY2V-1);
+ sp -= sizeof(Ureg);
+
+ if(!okaddr((ulong)up->notify, BY2WD, 0) ||
+ !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)) {
+ pprint("suicide: bad address or sp in notify\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+
+ memmove((Ureg*)sp, ur, sizeof(Ureg));
+ *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
+ up->ureg = (void*)sp;
+ sp -= BY2WD+ERRMAX;
+ memmove((char*)sp, up->note[0].msg, ERRMAX);
+ sp -= 3*BY2WD;
+ *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */
+ ur->r1 = (long)up->ureg; /* arg 1 is ureg* */
+ ((ulong*)sp)[1] = (ulong)up->ureg; /* arg 1 0(FP) is ureg* */
+ ((ulong*)sp)[0] = 0; /* arg 0 is pc */
+ ur->usp = sp;
+ ur->pc = (ulong)up->notify;
+ up->notified = 1;
+ up->nnote--;
+ memmove(&up->lastnote, &up->note[0], sizeof(Note));
+ memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
+
+ qunlock(&up->debug);
+ splx(s);
+ return 1;
+}
+
+
+/*
+ * Return user to state before notify()
+ */
+void
+noted(Ureg* ureg, ulong arg0)
+{
+ Ureg *nureg;
+ ulong oureg, sp;
+
+ qlock(&up->debug);
+ if(arg0!=NRSTR && !up->notified) {
+ qunlock(&up->debug);
+ pprint("call to noted() when not notified\n");
+ pexit("Suicide", 0);
+ }
+ up->notified = 0;
+
+ nureg = up->ureg; /* pointer to user returned Ureg struct */
+
+ /* sanity clause */
+ oureg = (ulong)nureg;
+ if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
+ pprint("bad ureg in noted or call to noted when not notified\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+
+ memmove(ureg, nureg, sizeof(Ureg));
+
+ switch(arg0){
+ case NCONT:
+ case NRSTR:
+ if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->usp, BY2WD, 0)){
+ pprint("suicide: trap in noted\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+ up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
+ qunlock(&up->debug);
+ break;
+
+ case NSAVE:
+ if(!okaddr(nureg->pc, BY2WD, 0)
+ || !okaddr(nureg->usp, BY2WD, 0)){
+ pprint("suicide: trap in noted\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+ qunlock(&up->debug);
+ sp = oureg-4*BY2WD-ERRMAX;
+ splhi();
+ ureg->sp = sp;
+ ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
+ ((ulong*)sp)[0] = 0; /* arg 0 is pc */
+ break;
+
+ default:
+ pprint("unknown noted arg 0x%lux\n", arg0);
+ up->lastnote.flag = NDebug;
+ /* fall through */
+
+ case NDFLT:
+ if(up->lastnote.flag == NDebug)
+ pprint("suicide: %s\n", up->lastnote.msg);
+ qunlock(&up->debug);
+ pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
+ }
+}
diff --git a/sys/src/9/mtx/uarti8250.c b/sys/src/9/mtx/uarti8250.c
new file mode 100755
index 000000000..ce68e6868
--- /dev/null
+++ b/sys/src/9/mtx/uarti8250.c
@@ -0,0 +1,636 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+/*
+ * 8250 UART and compatibles.
+ */
+enum {
+ Uart0 = 0x3F8, /* COM1 */
+ Uart0IRQ = 4,
+ Uart1 = 0x2F8, /* COM2 */
+ Uart1IRQ = 3,
+
+ UartFREQ = 1843200,
+};
+
+enum { /* I/O ports */
+ Rbr = 0, /* Receiver Buffer (RO) */
+ Thr = 0, /* Transmitter Holding (WO) */
+ Ier = 1, /* Interrupt Enable */
+ Iir = 2, /* Interrupt Identification (RO) */
+ Fcr = 2, /* FIFO Control (WO) */
+ Lcr = 3, /* Line Control */
+ Mcr = 4, /* Modem Control */
+ Lsr = 5, /* Line Status */
+ Msr = 6, /* Modem Status */
+ Scr = 7, /* Scratch Pad */
+ Dll = 0, /* Divisor Latch LSB */
+ Dlm = 1, /* Divisor Latch MSB */
+};
+
+enum { /* Ier */
+ Erda = 0x01, /* Enable Received Data Available */
+ Ethre = 0x02, /* Enable Thr Empty */
+ Erls = 0x04, /* Enable Receiver Line Status */
+ Ems = 0x08, /* Enable Modem Status */
+};
+
+enum { /* Iir */
+ Ims = 0x00, /* Ms interrupt */
+ Ip = 0x01, /* Interrupt Pending (not) */
+ Ithre = 0x02, /* Thr Empty */
+ Irda = 0x04, /* Received Data Available */
+ Irls = 0x06, /* Receiver Line Status */
+ Ictoi = 0x0C, /* Character Time-out Indication */
+ IirMASK = 0x3F,
+ Ife = 0xC0, /* FIFOs enabled */
+};
+
+enum { /* Fcr */
+ FIFOena = 0x01, /* FIFO enable */
+ FIFOrclr = 0x02, /* clear Rx FIFO */
+ FIFOtclr = 0x04, /* clear Tx FIFO */
+ FIFO1 = 0x00, /* Rx FIFO trigger level 1 byte */
+ FIFO4 = 0x40, /* 4 bytes */
+ FIFO8 = 0x80, /* 8 bytes */
+ FIFO14 = 0xC0, /* 14 bytes */
+};
+
+enum { /* Lcr */
+ Wls5 = 0x00, /* Word Length Select 5 bits/byte */
+ Wls6 = 0x01, /* 6 bits/byte */
+ Wls7 = 0x02, /* 7 bits/byte */
+ Wls8 = 0x03, /* 8 bits/byte */
+ WlsMASK = 0x03,
+ Stb = 0x04, /* 2 stop bits */
+ Pen = 0x08, /* Parity Enable */
+ Eps = 0x10, /* Even Parity Select */
+ Stp = 0x20, /* Stick Parity */
+ Brk = 0x40, /* Break */
+ Dlab = 0x80, /* Divisor Latch Access Bit */
+};
+
+enum { /* Mcr */
+ Dtr = 0x01, /* Data Terminal Ready */
+ Rts = 0x02, /* Ready To Send */
+ Out1 = 0x04, /* no longer in use */
+ Ie = 0x08, /* IRQ Enable */
+ Dm = 0x10, /* Diagnostic Mode loopback */
+};
+
+enum { /* Lsr */
+ Dr = 0x01, /* Data Ready */
+ Oe = 0x02, /* Overrun Error */
+ Pe = 0x04, /* Parity Error */
+ Fe = 0x08, /* Framing Error */
+ Bi = 0x10, /* Break Interrupt */
+ Thre = 0x20, /* Thr Empty */
+ Temt = 0x40, /* Tramsmitter Empty */
+ FIFOerr = 0x80, /* error in receiver FIFO */
+};
+
+enum { /* Msr */
+ Dcts = 0x01, /* Delta Cts */
+ Ddsr = 0x02, /* Delta Dsr */
+ Teri = 0x04, /* Trailing Edge of Ri */
+ Ddcd = 0x08, /* Delta Dcd */
+ Cts = 0x10, /* Clear To Send */
+ Dsr = 0x20, /* Data Set Ready */
+ Ri = 0x40, /* Ring Indicator */
+ Dcd = 0x80, /* Data Set Ready */
+};
+
+typedef struct Ctlr {
+ int io;
+ int irq;
+ int tbdf;
+ int iena;
+
+ uchar sticky[8];
+
+ Lock;
+ int fifo;
+ int fena;
+} Ctlr;
+
+extern PhysUart i8250physuart;
+
+static Ctlr i8250ctlr[2] = {
+{ .io = Uart0,
+ .irq = Uart0IRQ,
+ .tbdf = BUSUNKNOWN, },
+
+{ .io = Uart1,
+ .irq = Uart1IRQ,
+ .tbdf = BUSUNKNOWN, },
+};
+
+static Uart i8250uart[2] = {
+{ .regs = &i8250ctlr[0],
+ .name = "COM1",
+ .freq = UartFREQ,
+ .phys = &i8250physuart,
+ .special=0,
+ .next = &i8250uart[1], },
+
+{ .regs = &i8250ctlr[1],
+ .name = "COM2",
+ .freq = UartFREQ,
+ .phys = &i8250physuart,
+ .special=0,
+ .next = nil, },
+};
+
+#define csr8r(c, r) inb((c)->io+(r))
+#define csr8w(c, r, v) outb((c)->io+(r), (c)->sticky[(r)]|(v))
+
+static long
+i8250status(Uart* uart, void* buf, long n, long offset)
+{
+ char *p;
+ Ctlr *ctlr;
+ uchar ier, lcr, mcr, msr;
+
+ ctlr = uart->regs;
+ p = malloc(READSTR);
+ mcr = ctlr->sticky[Mcr];
+ msr = csr8r(ctlr, Msr);
+ ier = ctlr->sticky[Ier];
+ lcr = ctlr->sticky[Lcr];
+ snprint(p, READSTR,
+ "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
+ "dev(%d) type(%d) framing(%d) overruns(%d)%s%s%s%s\n",
+
+ uart->baud,
+ uart->hup_dcd,
+ (msr & Dsr) != 0,
+ uart->hup_dsr,
+ (lcr & WlsMASK) + 5,
+ (ier & Ems) != 0,
+ (lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n',
+ (mcr & Rts) != 0,
+ (lcr & Stb) ? 2: 1,
+ ctlr->fena,
+
+ uart->dev,
+ uart->type,
+ uart->ferr,
+ uart->oerr,
+ (msr & Cts) ? " cts": "",
+ (msr & Dsr) ? " dsr": "",
+ (msr & Dcd) ? " dcd": "",
+ (msr & Ri) ? " ring": ""
+ );
+ n = readstr(offset, buf, n, p);
+ free(p);
+
+ return n;
+}
+
+static void
+i8250fifo(Uart* uart, int on)
+{
+ int i;
+ Ctlr *ctlr;
+
+ /*
+ * Toggle FIFOs:
+ * if none, do nothing;
+ * reset the Rx and Tx FIFOs;
+ * empty the Rx buffer and clear any interrupt conditions;
+ * if enabling, try to turn them on.
+ */
+ ctlr = uart->regs;
+
+ ilock(ctlr);
+ if(!ctlr->fifo){
+ csr8w(ctlr, Fcr, FIFOtclr|FIFOrclr);
+ for(i = 0; i < 16; i++){
+ csr8r(ctlr, Iir);
+ csr8r(ctlr, Rbr);
+ }
+
+ ctlr->fena = 0;
+ if(on){
+ csr8w(ctlr, Fcr, FIFO4|FIFOena);
+ if(!(csr8r(ctlr, Iir) & Ife))
+ ctlr->fifo = 1;
+ ctlr->fena = 1;
+ }
+ }
+ iunlock(ctlr);
+}
+
+static void
+i8250dtr(Uart* uart, int on)
+{
+ Ctlr *ctlr;
+
+ /*
+ * Toggle DTR.
+ */
+ ctlr = uart->regs;
+ if(on)
+ ctlr->sticky[Mcr] |= Dtr;
+ else
+ ctlr->sticky[Mcr] &= ~Dtr;
+ csr8w(ctlr, Mcr, 0);
+}
+
+static void
+i8250rts(Uart* uart, int on)
+{
+ Ctlr *ctlr;
+
+ /*
+ * Toggle RTS.
+ */
+ ctlr = uart->regs;
+ if(on)
+ ctlr->sticky[Mcr] |= Rts;
+ else
+ ctlr->sticky[Mcr] &= ~Rts;
+ csr8w(ctlr, Mcr, 0);
+}
+
+static void
+i8250modemctl(Uart* uart, int on)
+{
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ ilock(&uart->tlock);
+ if(on){
+ ctlr->sticky[Ier] |= Ems;
+ csr8w(ctlr, Ier, 0);
+ uart->modem = 1;
+ uart->cts = csr8r(ctlr, Msr) & Cts;
+ }
+ else{
+ ctlr->sticky[Ier] &= ~Ems;
+ csr8w(ctlr, Ier, 0);
+ uart->modem = 0;
+ uart->cts = 1;
+ }
+ iunlock(&uart->tlock);
+
+ /* modem needs fifo */
+ (*uart->phys->fifo)(uart, on);
+}
+
+static int
+i8250parity(Uart* uart, int parity)
+{
+ int lcr;
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ lcr = ctlr->sticky[Lcr] & ~(Eps|Pen);
+
+ switch(parity){
+ case 'e':
+ lcr |= Eps|Pen;
+ break;
+ case 'o':
+ lcr |= Pen;
+ break;
+ case 'n':
+ default:
+ break;
+ }
+ ctlr->sticky[Lcr] = lcr;
+ csr8w(ctlr, Lcr, 0);
+
+ uart->parity = parity;
+
+ return 0;
+}
+
+static int
+i8250stop(Uart* uart, int stop)
+{
+ int lcr;
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ lcr = ctlr->sticky[Lcr] & ~Stb;
+
+ switch(stop){
+ case 1:
+ break;
+ case 2:
+ lcr |= Stb;
+ break;
+ default:
+ return -1;
+ }
+ ctlr->sticky[Lcr] = lcr;
+ csr8w(ctlr, Lcr, 0);
+
+ uart->stop = stop;
+
+ return 0;
+}
+
+static int
+i8250bits(Uart* uart, int bits)
+{
+ int lcr;
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ lcr = ctlr->sticky[Lcr] & ~WlsMASK;
+
+ switch(bits){
+ case 5:
+ lcr |= Wls5;
+ break;
+ case 6:
+ lcr |= Wls6;
+ break;
+ case 7:
+ lcr |= Wls7;
+ break;
+ case 8:
+ lcr |= Wls8;
+ break;
+ default:
+ return -1;
+ }
+ ctlr->sticky[Lcr] = lcr;
+ csr8w(ctlr, Lcr, 0);
+
+ uart->bits = bits;
+
+ return 0;
+}
+
+static int
+i8250baud(Uart* uart, int baud)
+{
+ ulong bgc;
+ Ctlr *ctlr;
+
+ /*
+ * Set the Baud rate by calculating and setting the Baud rate
+ * Generator Constant. This will work with fairly non-standard
+ * Baud rates.
+ */
+ if(uart->freq == 0 || baud <= 0)
+ return -1;
+ bgc = (uart->freq+8*baud-1)/(16*baud);
+
+ ctlr = uart->regs;
+ csr8w(ctlr, Lcr, Dlab);
+ outb(ctlr->io+Dlm, bgc>>8);
+ outb(ctlr->io+Dll, bgc);
+ csr8w(ctlr, Lcr, 0);
+
+ uart->baud = baud;
+
+ return 0;
+}
+
+static void
+i8250break(Uart* uart, int ms)
+{
+ Ctlr *ctlr;
+
+ /*
+ * Send a break.
+ */
+ if(ms == 0)
+ ms = 200;
+
+ ctlr = uart->regs;
+ csr8w(ctlr, Lcr, Brk);
+ tsleep(&up->sleep, return0, 0, ms);
+ csr8w(ctlr, Lcr, 0);
+}
+
+static void
+i8250kick(Uart* uart)
+{
+ int i;
+ Ctlr *ctlr;
+
+ if(uart->cts == 0 || uart->blocked)
+ return;
+
+ /*
+ * 128 here is an arbitrary limit to make sure
+ * we don't stay in this loop too long. If the
+ * chip's output queue is longer than 128, too
+ * bad -- presotto
+ */
+ ctlr = uart->regs;
+ for(i = 0; i < 128; i++){
+ if(!(csr8r(ctlr, Lsr) & Thre))
+ break;
+ if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
+ break;
+ outb(ctlr->io+Thr, *(uart->op++));
+ }
+}
+
+static void
+i8250interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Uart *uart;
+ int iir, lsr, old, r;
+
+ uart = arg;
+
+ ctlr = uart->regs;
+ for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){
+ switch(iir & IirMASK){
+ case Ims: /* Ms interrupt */
+ r = csr8r(ctlr, Msr);
+ if(r & Dcts){
+ ilock(&uart->tlock);
+ old = uart->cts;
+ uart->cts = r & Cts;
+ if(old == 0 && uart->cts)
+ uart->ctsbackoff = 2;
+ iunlock(&uart->tlock);
+ }
+ if(r & Ddsr){
+ old = r & Dsr;
+ if(uart->hup_dsr && uart->dsr && !old)
+ uart->dohup = 1;
+ uart->dsr = old;
+ }
+ if(r & Ddcd){
+ old = r & Dcd;
+ if(uart->hup_dcd && uart->dcd && !old)
+ uart->dohup = 1;
+ uart->dcd = old;
+ }
+ break;
+ case Ithre: /* Thr Empty */
+ uartkick(uart);
+ break;
+ case Irda: /* Received Data Available */
+ case Ictoi: /* Character Time-out Indication */
+ /*
+ * Consume any received data.
+ * If the received byte came in with a break,
+ * parity or framing error, throw it away;
+ * overrun is an indication that something has
+ * already been tossed.
+ */
+ while((lsr = csr8r(ctlr, Lsr)) & Dr){
+ if(lsr & Oe)
+ uart->oerr++;
+ if(lsr & Pe)
+ uart->perr++;
+ if(lsr & Fe)
+ uart->ferr++;
+ r = csr8r(ctlr, Rbr);
+ if(!(lsr & (Bi|Fe|Pe)))
+ uartrecv(uart, r);
+ }
+ break;
+ default:
+ iprint("weird uart interrupt 0x%2.2uX\n", iir);
+ break;
+ }
+ }
+}
+
+static void
+i8250disable(Uart* uart)
+{
+ Ctlr *ctlr;
+
+ /*
+ * Turn off DTR and RTS, disable interrupts and fifos.
+ */
+ (*uart->phys->dtr)(uart, 0);
+ (*uart->phys->rts)(uart, 0);
+ (*uart->phys->fifo)(uart, 0);
+
+ ctlr = uart->regs;
+ ctlr->sticky[Ier] = 0;
+ csr8w(ctlr, Ier, 0);
+}
+
+static void
+i8250enable(Uart* uart, int ie)
+{
+ Ctlr *ctlr;
+
+ /*
+ * Enable interrupts and turn on DTR and RTS.
+ * Be careful if this is called to set up a polled serial line
+ * early on not to try to enable interrupts as interrupt-
+ * -enabling mechanisms might not be set up yet.
+ */
+ ctlr = uart->regs;
+ if(ie){
+ if(ctlr->iena == 0){
+ intrenable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name);
+ ctlr->iena = 1;
+ }
+ ctlr->sticky[Ier] = Ethre|Erda;
+ ctlr->sticky[Mcr] |= Ie;
+ }
+ else{
+ ctlr->sticky[Ier] = 0;
+ ctlr->sticky[Mcr] = 0;
+ }
+ csr8w(ctlr, Ier, ctlr->sticky[Ier]);
+ csr8w(ctlr, Mcr, ctlr->sticky[Mcr]);
+
+ (*uart->phys->dtr)(uart, 1);
+ (*uart->phys->rts)(uart, 1);
+}
+
+static Uart*
+i8250pnp(void)
+{
+ return i8250uart;
+}
+
+static int
+i8250getc(Uart *uart)
+{
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ while(!(csr8r(ctlr, Lsr)&Dr))
+ delay(1);
+ return csr8r(ctlr, Rbr);
+}
+
+static void
+i8250putc(Uart *uart, int c)
+{
+ int i;
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
+ delay(1);
+ outb(ctlr->io+Thr, c);
+ for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
+ delay(1);
+}
+
+PhysUart i8250physuart = {
+ .name = "i8250",
+ .pnp = i8250pnp,
+ .enable = i8250enable,
+ .disable = i8250disable,
+ .kick = i8250kick,
+ .dobreak = i8250break,
+ .baud = i8250baud,
+ .bits = i8250bits,
+ .stop = i8250stop,
+ .parity = i8250parity,
+ .modemctl = i8250modemctl,
+ .rts = i8250rts,
+ .dtr = i8250dtr,
+ .status = i8250status,
+ .fifo = i8250fifo,
+ .getc = i8250getc,
+ .putc = i8250putc,
+};
+
+void
+i8250console(void)
+{
+ Uart *uart;
+ int n;
+ char *cmd, *p;
+
+ if((p = getconf("console")) == nil)
+ return;
+ n = strtoul(p, &cmd, 0);
+ if(p == cmd)
+ return;
+ switch(n){
+ default:
+ return;
+ case 0:
+ uart = &i8250uart[0];
+ break;
+ case 1:
+ uart = &i8250uart[1];
+ break;
+ }
+
+ uartctl(uart, "b9600 l8 pn s1");
+ if(*cmd != '\0')
+ uartctl(uart, cmd);
+ (*uart->phys->enable)(uart, 0);
+
+ consuart = uart;
+ uart->console = 1;
+}
diff --git a/sys/src/9/omap/arch.c b/sys/src/9/omap/arch.c
new file mode 100755
index 000000000..a9b9537a9
--- /dev/null
+++ b/sys/src/9/omap/arch.c
@@ -0,0 +1,223 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include <tos.h>
+#include "ureg.h"
+
+#include "arm.h"
+
+/*
+ * A lot of this stuff doesn't belong here
+ * but this is a convenient dumping ground for
+ * later sorting into the appropriate buckets.
+ */
+
+/* Give enough context in the ureg to produce a kernel stack for
+ * a sleeping process
+ */
+void
+setkernur(Ureg* ureg, Proc* p)
+{
+ ureg->pc = p->sched.pc;
+ ureg->sp = p->sched.sp+4;
+ ureg->r14 = PTR2UINT(sched);
+}
+
+/*
+ * called in sysfile.c
+ */
+void
+evenaddr(uintptr addr)
+{
+ if(addr & 3){
+ postnote(up, 1, "sys: odd address", NDebug);
+ error(Ebadarg);
+ }
+}
+
+/* go to user space */
+void
+kexit(Ureg*)
+{
+ uvlong t;
+ Tos *tos;
+
+ /* precise time accounting, kernel exit */
+ tos = (Tos*)(USTKTOP-sizeof(Tos));
+ cycles(&t);
+ tos->kcycles += t - up->kentry;
+ tos->pcycles = up->pcycles;
+ tos->cyclefreq = m->cpuhz;
+ tos->pid = up->pid;
+
+ /* make visible immediately to user proc */
+ cachedwbinvse(tos, sizeof *tos);
+}
+
+/*
+ * return the userpc the last exception happened at
+ */
+uintptr
+userpc(void)
+{
+ Ureg *ureg = up->dbgreg;
+ return ureg->pc;
+}
+
+/* This routine must save the values of registers the user is not permitted
+ * to write from devproc and then restore the saved values before returning.
+ */
+void
+setregisters(Ureg* ureg, char* pureg, char* uva, int n)
+{
+ USED(ureg, pureg, uva, n);
+}
+
+/*
+ * this is the body for all kproc's
+ */
+static void
+linkproc(void)
+{
+ spllo();
+ up->kpfun(up->kparg);
+ pexit("kproc exiting", 0);
+}
+
+/*
+ * setup stack and initial PC for a new kernel proc. This is architecture
+ * dependent because of the starting stack location
+ */
+void
+kprocchild(Proc *p, void (*func)(void*), void *arg)
+{
+ p->sched.pc = PTR2UINT(linkproc);
+ p->sched.sp = PTR2UINT(p->kstack+KSTACK);
+
+ p->kpfun = func;
+ p->kparg = arg;
+}
+
+/*
+ * pc output by dumpaproc
+ */
+uintptr
+dbgpc(Proc* p)
+{
+ Ureg *ureg;
+
+ ureg = p->dbgreg;
+ if(ureg == 0)
+ return 0;
+
+ return ureg->pc;
+}
+
+/*
+ * set mach dependent process state for a new process
+ */
+void
+procsetup(Proc* p)
+{
+ fpusysprocsetup(p);
+}
+
+/*
+ * Save the mach dependent part of the process state.
+ */
+void
+procsave(Proc* p)
+{
+ uvlong t;
+
+ cycles(&t);
+ p->pcycles += t;
+
+// TODO: save and restore VFPv3 FP state once 5[cal] know the new registers.
+ fpuprocsave(p);
+}
+
+void
+procrestore(Proc* p)
+{
+ uvlong t;
+
+ if(p->kp)
+ return;
+ cycles(&t);
+ p->pcycles -= t;
+
+ fpuprocrestore(p);
+}
+
+int
+userureg(Ureg* ureg)
+{
+ return (ureg->psr & PsrMask) == PsrMusr;
+}
+
+/*
+ * atomic ops
+ * make sure that we don't drag in the C library versions
+ */
+
+long
+_xdec(long *p)
+{
+ int s, v;
+
+ s = splhi();
+ v = --*p;
+ splx(s);
+ return v;
+}
+
+void
+_xinc(long *p)
+{
+ int s;
+
+ s = splhi();
+ ++*p;
+ splx(s);
+}
+
+int
+ainc(int *p)
+{
+ int s, v;
+
+ s = splhi();
+ v = ++*p;
+ splx(s);
+ return v;
+}
+
+int
+adec(int *p)
+{
+ int s, v;
+
+ s = splhi();
+ v = --*p;
+ splx(s);
+ return v;
+}
+
+int
+cas32(void* addr, u32int old, u32int new)
+{
+ int r, s;
+
+ s = splhi();
+ if(r = (*(u32int*)addr == old))
+ *(u32int*)addr = new;
+ splx(s);
+ if (r)
+ coherence();
+ return r;
+}
diff --git a/sys/src/9/omap/archomap.c b/sys/src/9/omap/archomap.c
new file mode 100755
index 000000000..0f20d50a6
--- /dev/null
+++ b/sys/src/9/omap/archomap.c
@@ -0,0 +1,1389 @@
+/*
+ * omap3530 SoC (e.g. beagleboard) architecture-specific stuff
+ *
+ * errata: usb port 3 cannot operate in ulpi mode, only serial or
+ * ulpi tll mode
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+#include "arm.h"
+
+#include "../port/netif.h"
+#include "etherif.h"
+#include "../port/flashif.h"
+#include "../port/usb.h"
+#include "usbehci.h"
+
+#define FREQSEL(x) ((x) << 4)
+
+typedef struct Cm Cm;
+typedef struct Cntrl Cntrl;
+typedef struct Gen Gen;
+typedef struct Gpio Gpio;
+typedef struct L3agent L3agent;
+typedef struct L3protreg L3protreg;
+typedef struct L3regs L3regs;
+typedef struct Prm Prm;
+typedef struct Usbotg Usbotg;
+typedef struct Usbtll Usbtll;
+
+/* omap3 non-standard usb stuff */
+struct Usbotg {
+ uchar faddr;
+ uchar power;
+ ushort intrtx;
+ ushort intrrx;
+ ushort intrtxe;
+ ushort intrrxe;
+ uchar intrusb;
+ uchar intrusbe;
+ ushort frame;
+ uchar index;
+ uchar testmode;
+
+ /* indexed registers follow; ignore for now */
+ uchar _pad0[0x400 - 0x10];
+
+ ulong otgrev;
+ ulong otgsyscfg;
+ ulong otgsyssts;
+ ulong otgifcsel; /* interface selection */
+ uchar _pad1[0x414 - 0x410];
+ ulong otgforcestdby;
+};
+
+enum {
+ /* power bits */
+ Hsen = 1<<5, /* high-speed enable */
+
+ /* testmode bits */
+ Forcehost = 1<<7, /* force host (vs peripheral) mode */
+ Forcehs = 1<<4, /* force high-speed at reset */
+
+ /* otgsyscfg bits */
+ Midle = 1<<12, /* no standby mode */
+ Sidle = 1<<3, /* no idle mode */
+// Softreset = 1<<1,
+
+ /* otgsyssts bits, per sysstatus */
+};
+
+struct Usbtll {
+ ulong revision; /* ro */
+ uchar _pad0[0x10-0x4];
+ ulong sysconfig;
+ ulong sysstatus; /* ro */
+
+ ulong irqstatus;
+ ulong irqenable;
+};
+
+enum {
+ /* sysconfig bits */
+ Softreset = 1<<1,
+
+ /* sysstatus bits */
+ Resetdone = 1<<0,
+ /* only in uhh->sysstatus */
+ Ehci_resetdone = 1<<2,
+ Ohci_resetdone = 1<<1,
+};
+
+/*
+ * an array of these structs is preceded by error_log at 0x20, control,
+ * error_clear_single, error_clear_multi. first struct is at offset 0x48.
+ */
+struct L3protreg { /* hw: an L3 protection region */
+ uvlong req_info_perm;
+ uvlong read_perm;
+ uvlong write_perm;
+ uvlong addr_match; /* ro? write this one last, then flush */
+};
+
+// TODO: set these permission bits (e.g., for usb)?
+enum {
+ Permusbhost = 1<<9,
+ Permusbotg = 1<<4,
+ Permsysdma = 1<<3,
+ Permmpu = 1<<1,
+};
+
+struct L3agent { /* hw registers */
+ uchar _pad0[0x20];
+ uvlong ctl;
+ uvlong sts;
+ uchar _pad1[0x58 - 0x30];
+ uvlong errlog;
+ uvlong errlogaddr;
+};
+
+struct L3regs {
+ L3protreg *base; /* base of array */
+ int upper; /* index maximum */
+ char *name;
+};
+L3regs l3regs[] = {
+ (L3protreg *)(PHYSL3GPMCPM+0x48), 7, "gpmc", /* known to be first */
+ (L3protreg *)(PHYSL3PMRT+0x48), 1, "rt", /* l3 config */
+ (L3protreg *)(PHYSL3OCTRAM+0x48), 7, "ocm ram",
+ (L3protreg *)(PHYSL3OCTROM+0x48), 1, "ocm rom",
+ (L3protreg *)(PHYSL3MAD2D+0x48), 7, "mad2d", /* die-to-die */
+ (L3protreg *)(PHYSL3IVA+0x48), 3, "iva2.2", /* a/v */
+};
+
+/*
+ * PRM_CLKSEL (0x48306d40) low 3 bits are system clock speed, assuming
+ * units of MHz: 0 = 12, 1 = 13, 2 = 19.2, 3 = 26, 4 = 38.4, 5 = 16.8
+ */
+
+struct Cm { /* clock management */
+ ulong fclken; /* ``functional'' clock enable */
+ ulong fclken2;
+ ulong fclken3;
+ uchar _pad0[0x10 - 0xc];
+
+ ulong iclken; /* ``interface'' clock enable */
+ ulong iclken2;
+ ulong iclken3;
+ uchar _pad1[0x20 - 0x1c];
+
+ ulong idlest; /* idle status */
+ ulong idlest2;
+ ulong idlest3;
+ uchar _pad2[0x30 - 0x2c];
+
+ ulong autoidle;
+ ulong autoidle2;
+ ulong autoidle3;
+ uchar _pad3[0x40 - 0x3c];
+
+ union {
+ ulong clksel[5];
+ struct unused {
+ ulong sleepdep;
+ ulong clkstctrl;
+ ulong clkstst;
+ };
+ uchar _pad4[0x70 - 0x40];
+ };
+ ulong clkoutctrl;
+};
+
+struct Prm { /* power & reset management */
+ uchar _pad[0x50];
+ ulong rstctrl;
+};
+
+struct Gpio {
+ ulong _pad0[4];
+ ulong sysconfig;
+ ulong sysstatus;
+
+ ulong irqsts1; /* for mpu */
+ ulong irqen1;
+ ulong wkupen;
+ ulong _pad1;
+ ulong irqsts2; /* for iva */
+ ulong irqen2;
+
+ ulong ctrl;
+
+ ulong oe;
+ ulong datain;
+ ulong dataout;
+
+ ulong lvldet0;
+ ulong lvldet1;
+ ulong risingdet;
+ ulong fallingdet;
+
+ /* rest are uninteresting */
+ ulong deben; /* debouncing enable */
+ ulong debtime;
+ ulong _pad2[2];
+
+ ulong clrirqen1;
+ ulong setirqen1;
+ ulong _pad3[2];
+
+ ulong clrirqen2;
+ ulong setirqen2;
+ ulong _pad4[2];
+
+ ulong clrwkupen;
+ ulong setwkupen;
+ ulong _pad5[2];
+
+ ulong clrdataout;
+ ulong setdataout;
+};
+
+enum {
+ /* clock enable & idle status bits */
+ Wkusimocp = 1 << 9, /* SIM card: uses 120MHz clock */
+ Wkwdt2 = 1 << 5, /* wdt2 clock enable bit for wakeup */
+ Wkgpio1 = 1 << 3, /* gpio1 " */
+ Wkgpt1 = 1 << 0, /* gpt1 " */
+
+ Dssl3l4 = 1 << 0, /* dss l3, l4 i clks */
+ Dsstv = 1 << 2, /* dss tv f clock */
+ Dss2 = 1 << 1, /* dss clock 2 */
+ Dss1 = 1 << 0, /* dss clock 1 */
+
+ Pergpio6 = 1 << 17,
+ Pergpio5 = 1 << 16,
+ Pergpio4 = 1 << 15,
+ Pergpio3 = 1 << 14,
+ Pergpio2 = 1 << 13,
+ Perwdt3 = 1 << 12, /* wdt3 clock enable bit for periphs */
+ Peruart3 = 1 << 11, /* console uart */
+ Pergpt9 = 1 << 10,
+ Pergpt8 = 1 << 9,
+ Pergpt7 = 1 << 8,
+ Pergpt6 = 1 << 7,
+ Pergpt5 = 1 << 6,
+ Pergpt4 = 1 << 5,
+ Pergpt3 = 1 << 4,
+ Pergpt2 = 1 << 3, /* gpt2 clock enable bit for periphs */
+
+ Perenable = Pergpio6 | Pergpio5 | Perwdt3 | Pergpt2 | Peruart3,
+
+ Usbhost2 = 1 << 1, /* 120MHz clock enable */
+ Usbhost1 = 1 << 0, /* 48MHz clock enable */
+ Usbhost = Usbhost1, /* iclock enable */
+ Usbhostidle = 1 << 1,
+ Usbhoststdby = 1 << 0,
+
+ Coreusbhsotg = 1 << 4, /* usb hs otg enable bit */
+ Core3usbtll = 1 << 2, /* usb tll enable bit */
+
+ /* core->idlest bits */
+ Coreusbhsotgidle = 1 << 5,
+ Coreusbhsotgstdby= 1 << 4,
+
+ Dplllock = 7,
+
+ /* mpu->idlest2 bits */
+ Dplllocked = 1,
+ Dpllbypassed = 0,
+
+ /* wkup->idlest bits */
+ Gpio1idle = 1 << 3,
+
+ /* dss->idlest bits */
+ Dssidle = 1 << 1,
+
+ Gpio1vidmagic = 1<<24 | 1<<8 | 1<<5, /* gpio 1 pins for video */
+};
+enum {
+ Rstgs = 1 << 1, /* global sw. reset */
+
+ /* fp control regs. most are read-only */
+ Fpsid = 0,
+ Fpscr, /* rw */
+ Mvfr1 = 6,
+ Mvfr0,
+ Fpexc, /* rw */
+};
+
+/* see ether9221.c for explanation */
+enum {
+ Ethergpio = 176,
+ Etherchanbit = 1 << (Ethergpio % 32),
+};
+
+/*
+ * these shift values are for the Cortex-A8 L1 cache (A=2, L=6) and
+ * the Cortex-A8 L2 cache (A=3, L=6).
+ * A = log2(# of ways), L = log2(bytes per cache line).
+ * see armv7 arch ref p. 1403.
+ *
+ * #define L1WAYSH 30
+ * #define L1SETSH 6
+ * #define L2WAYSH 29
+ * #define L2SETSH 6
+ */
+enum {
+ /*
+ * cache capabilities. write-back vs write-through is controlled
+ * by the Buffered bit in PTEs.
+ */
+ Cawt = 1 << 31,
+ Cawb = 1 << 30,
+ Cara = 1 << 29,
+ Cawa = 1 << 28,
+};
+
+struct Gen {
+ ulong padconf_off;
+ ulong devconf0;
+ uchar _pad0[0x68 - 8];
+ ulong devconf1;
+};
+
+struct Cntrl {
+ ulong _pad0;
+ ulong id;
+ ulong _pad1;
+ ulong skuid;
+};
+
+
+static char *
+devidstr(ulong)
+{
+ return "ARM Cortex-A8";
+}
+
+void
+archomaplink(void)
+{
+}
+
+int
+ispow2(uvlong ul)
+{
+ /* see Hacker's Delight if this isn't obvious */
+ return (ul & (ul - 1)) == 0;
+}
+
+/*
+ * return exponent of smallest power of 2 ≥ n
+ */
+int
+log2(ulong n)
+{
+ int i;
+
+ i = 31 - clz(n);
+ if (n == 0 || !ispow2(n))
+ i++;
+ return i;
+}
+
+void
+archconfinit(void)
+{
+ char *p;
+ ulong mhz;
+
+ assert(m != nil);
+ m->cpuhz = 500 * Mhz; /* beagle speed */
+ p = getconf("*cpumhz");
+ if (p) {
+ mhz = atoi(p) * Mhz;
+ if (mhz >= 100*Mhz && mhz <= 3000UL*Mhz)
+ m->cpuhz = mhz;
+ }
+ m->delayloop = m->cpuhz/2000; /* initial estimate */
+}
+
+static void
+prperm(uvlong perm)
+{
+ if (perm == MASK(16))
+ print("all");
+ else
+ print("%#llux", perm);
+}
+
+static void
+prl3region(L3protreg *pr, int r)
+{
+ int level, size, addrspace;
+ uvlong am, base;
+
+ if (r == 0)
+ am = 0;
+ else
+ am = pr->addr_match;
+ size = (am >> 3) & MASK(5);
+ if (r > 0 && size == 0) /* disabled? */
+ return;
+
+ print(" %d: perms req ", r);
+ prperm(pr->req_info_perm);
+ if (pr->read_perm == pr->write_perm && pr->read_perm == MASK(16))
+ print(" rw all");
+ else {
+ print(" read ");
+ prperm(pr->read_perm);
+ print(" write ");
+ prperm(pr->write_perm);
+ }
+ if (r == 0)
+ print(", all addrs level 0");
+ else {
+ size = 1 << size; /* 2^size */
+ level = (am >> 9) & 1;
+ if (r == 1)
+ level = 3;
+ else
+ level++;
+ addrspace = am & 7;
+ base = am & ~MASK(10);
+ print(", base %#llux size %dKB level %d addrspace %d",
+ base, size, level, addrspace);
+ }
+ print("\n");
+ delay(100);
+}
+
+
+/*
+ * dump the l3 interconnect firewall settings by protection region.
+ * mpu, sys dma and both usbs (0x21a) should be set in all read & write
+ * permission registers.
+ */
+static void
+dumpl3pr(void)
+{
+ int r;
+ L3regs *reg;
+ L3protreg *pr;
+
+ for (reg = l3regs; reg < l3regs + nelem(l3regs); reg++) {
+ print("%#p (%s) enabled l3 regions:\n", reg->base, reg->name);
+ for (r = 0; r <= reg->upper; r++)
+ prl3region(reg->base + r, r);
+ }
+if (0) { // TODO
+ /* touch up gpmc perms */
+ reg = l3regs; /* first entry is gpmc */
+ for (r = 0; r <= reg->upper; r++) {
+ pr = reg->base + r;
+ // TODO
+ }
+ print("%#p (%s) modified l3 regions:\n", reg->base, reg->name);
+ for (r = 0; r <= reg->upper; r++)
+ prl3region(reg->base + r, r);
+}
+}
+
+static void
+p16(uchar *p, ulong v)
+{
+ *p++ = v>>8;
+ *p = v;
+}
+
+static void
+p32(uchar *p, ulong v)
+{
+ *p++ = v>>24;
+ *p++ = v>>16;
+ *p++ = v>>8;
+ *p = v;
+}
+
+int
+archether(unsigned ctlrno, Ether *ether)
+{
+ switch(ctlrno) {
+ case 0:
+ /* there's no built-in ether on the beagle but igepv2 has 1 */
+ ether->type = "9221";
+ ether->ctlrno = ctlrno;
+ ether->irq = 34;
+ ether->nopt = 0;
+ ether->mbps = 100;
+ return 1;
+ }
+ return -1;
+}
+
+/*
+ * turn on all the necessary clocks on the SoC.
+ *
+ * a ``functional'' clock drives a device; an ``interface'' clock drives
+ * its communication with the rest of the system. so the interface
+ * clock must be enabled to reach the device's registers.
+ *
+ * dplls: 1 mpu, 2 iva2, 3 core, 4 per, 5 per2.
+ */
+
+static void
+configmpu(void)
+{
+ ulong clk, mhz, nmhz, maxmhz;
+ Cm *mpu = (Cm *)PHYSSCMMPU;
+ Cntrl *id = (Cntrl *)PHYSCNTRL;
+
+ if ((id->skuid & MASK(4)) == 8)
+ maxmhz = 720;
+ else
+ maxmhz = 600;
+ iprint("cpu capable of %ldMHz operation", maxmhz);
+
+ clk = mpu->clksel[0];
+ mhz = (clk >> 8) & MASK(11); /* configured speed */
+// iprint("\tfclk src %ld; dpll1 mult %ld (MHz) div %ld",
+// (clk >> 19) & MASK(3), mhz, clk & MASK(7));
+ iprint("; at %ldMHz", mhz);
+ nmhz = m->cpuhz / Mhz; /* nominal speed */
+ if (mhz == nmhz) {
+ iprint("\n");
+ return;
+ }
+
+ mhz = nmhz;
+ if (mhz > maxmhz) {
+ mhz = maxmhz;
+ iprint("; limiting operation to %ldMHz", mhz);
+ }
+
+ /* disable dpll1 lock mode; put into low-power bypass mode */
+ mpu->fclken2 = mpu->fclken2 & ~MASK(3) | 5;
+ coherence();
+ while (mpu->idlest2 != Dpllbypassed)
+ ;
+
+ /*
+ * there's a dance to change processor speed,
+ * prescribed in spruf98d §4.7.6.9.
+ */
+
+ /* just change multiplier; leave divider alone at 12 (meaning 13?) */
+ mpu->clksel[0] = clk & ~(MASK(11) << 8) | mhz << 8;
+ coherence();
+
+ /* set output divider (M2) in clksel[1]: leave at 1 */
+
+ /*
+ * u-boot calls us with just freqsel 3 (~1MHz) & dpll1 lock mode.
+ */
+ /* set FREQSEL */
+ mpu->fclken2 = mpu->fclken2 & ~FREQSEL(MASK(4)) | FREQSEL(3);
+ coherence();
+
+ /* set ramp-up delay to `fast' */
+ mpu->fclken2 = mpu->fclken2 & ~(MASK(2) << 8) | 3 << 8;
+ coherence();
+
+ /* set auto-recalibration (off) */
+ mpu->fclken2 &= ~(1 << 3);
+ coherence();
+
+ /* disable auto-idle: ? */
+ /* unmask clock intr: later */
+
+ /* enable dpll lock mode */
+ mpu->fclken2 |= Dplllock;
+ coherence();
+ while (mpu->idlest2 != Dplllocked)
+ ;
+ delay(200); /* allow time for speed to ramp up */
+
+ if (((mpu->clksel[0] >> 8) & MASK(11)) != mhz)
+ panic("mpu clock speed change didn't stick");
+ iprint("; now at %ldMHz\n", mhz);
+}
+
+static void
+configpll(void)
+{
+ int i;
+ Cm *pll = (Cm *)PHYSSCMPLL;
+
+ pll->clkoutctrl |= 1 << 7; /* enable sys_clkout2 */
+ coherence();
+ delay(10);
+
+ /*
+ * u-boot calls us with just freqsel 3 (~1MHz) & lock mode
+ * for both dplls (3 & 4). ensure that.
+ */
+ if ((pll->idlest & 3) != 3) {
+ /* put dpll[34] into low-power bypass mode */
+ pll->fclken = pll->fclken & ~(MASK(3) << 16 | MASK(3)) |
+ 1 << 16 | 5;
+ coherence();
+ while (pll->idlest & 3) /* wait for both to bypass or stop */
+ ;
+
+ pll->fclken = (FREQSEL(3) | Dplllock) << 16 |
+ FREQSEL(3) | Dplllock;
+ coherence();
+ while ((pll->idlest & 3) != 3) /* wait for both to lock */
+ ;
+ }
+
+ /*
+ * u-boot calls us with just freqsel 1 (default but undefined)
+ * & stop mode for dpll5. try to lock it at 120MHz.
+ */
+ if (!(pll->idlest2 & Dplllocked)) {
+ /* force dpll5 into low-power bypass mode */
+ pll->fclken2 = 3 << 8 | FREQSEL(1) | 1;
+ coherence();
+ for (i = 0; pll->idlest2 & Dplllocked && i < 20; i++)
+ delay(50);
+ if (i >= 20)
+ iprint(" [dpll5 failed to stop]");
+
+ /*
+ * CORE_CLK is 26MHz.
+ */
+ pll->clksel[4-1] = 120 << 8 | 12; /* M=120, N=12+1 */
+ /* M2 divisor: 120MHz clock is exactly the DPLL5 clock */
+ pll->clksel[5-1] = 1;
+ coherence();
+
+ pll->fclken2 = 3 << 8 | FREQSEL(1) | Dplllock; /* def. freq */
+ coherence();
+
+ for (i = 0; !(pll->idlest2 & Dplllocked) && i < 20; i++)
+ delay(50);
+ if (i >= 20)
+ iprint(" [dpll5 failed to lock]");
+ }
+ if (!(pll->idlest2 & (1<<1)))
+ iprint(" [no 120MHz clock]");
+ if (!(pll->idlest2 & (1<<3)))
+ iprint(" [no dpll5 120MHz clock output]");
+}
+
+static void
+configper(void)
+{
+ Cm *per = (Cm *)PHYSSCMPER;
+
+ per->clksel[0] &= ~MASK(8); /* select 32kHz clock for GPTIMER2-9 */
+
+ per->iclken |= Perenable;
+ coherence();
+ per->fclken |= Perenable;
+ coherence();
+ while (per->idlest & Perenable)
+ ;
+
+ per->autoidle = 0;
+ coherence();
+}
+
+static void
+configwkup(void)
+{
+ Cm *wkup = (Cm *)PHYSSCMWKUP;
+
+ /* select 32kHz clock (not system clock) for GPTIMER1 */
+ wkup->clksel[0] &= ~1;
+
+ wkup->iclken |= Wkusimocp | Wkwdt2 | Wkgpt1;
+ coherence();
+ wkup->fclken |= Wkusimocp | Wkwdt2 | Wkgpt1;
+ coherence();
+ while (wkup->idlest & (Wkusimocp | Wkwdt2 | Wkgpt1))
+ ;
+}
+
+static void
+configusb(void)
+{
+ int i;
+ Cm *usb = (Cm *)PHYSSCMUSB;
+
+ /*
+ * make the usb registers accessible without address faults,
+ * notably uhh, ochi & ehci. tll seems to be separate & otg is okay.
+ */
+ usb->iclken |= Usbhost;
+ coherence();
+ usb->fclken |= Usbhost1 | Usbhost2; /* includes 120MHz clock */
+ coherence();
+ for (i = 0; usb->idlest & Usbhostidle && i < 20; i++)
+ delay(50);
+ if (i >= 20)
+ iprint(" [usb inaccessible]");
+}
+
+static void
+configcore(void)
+{
+ Cm *core = (Cm *)PHYSSCMCORE;
+
+ /*
+ * make the usb tll registers accessible.
+ */
+ core->iclken |= Coreusbhsotg;
+ core->iclken3 |= Core3usbtll;
+ coherence();
+ core->fclken3 |= Core3usbtll;
+ coherence();
+ delay(100);
+ while (core->idlest & Coreusbhsotgidle)
+ ;
+ if (core->idlest3 & Core3usbtll)
+ iprint(" [no usb tll]");
+}
+
+static void
+configclks(void)
+{
+ int s;
+ Gen *gen = (Gen *)PHYSSCMPCONF;
+
+ delay(20);
+ s = splhi();
+ configmpu(); /* sets cpu clock rate, turns on dplls 1 & 2 */
+
+ /*
+ * the main goal is to get enough clocks running, in the right order,
+ * so that usb has all the necessary clock signals.
+ */
+ iprint("clocks:");
+ iprint(" usb");
+ configusb(); /* starts usb clocks & 120MHz clock */
+ iprint(", pll");
+ configpll(); /* starts dplls 3, 4 & 5 & 120MHz clock */
+ iprint(", wakeup");
+ configwkup(); /* starts timer clocks and usim clock */
+ iprint(", per");
+ configper(); /* starts timer & gpio (ether) clocks */
+ iprint(", core");
+ configcore(); /* starts usb tll */
+ iprint("\n");
+
+ gen->devconf0 |= 1 << 1 | 1 << 0; /* dmareq[01] edge sensitive */
+ /* make dmareq[2-6] edge sensitive */
+ gen->devconf1 |= 1 << 23 | 1 << 22 | 1 << 21 | 1 << 8 | 1 << 7;
+ coherence();
+ splx(s);
+ delay(20);
+}
+
+static void
+resetwait(ulong *reg)
+{
+ long bound;
+
+ for (bound = 400*Mhz; !(*reg & Resetdone) && bound > 0; bound--)
+ ;
+ if (bound <= 0)
+ iprint("archomap: Resetdone didn't come ready\n");
+}
+
+/*
+ * gpio irq 1 goes to the mpu intr ctlr; irq 2 goes to the iva's.
+ * this stuff is magic and without it, we won't get irq 34 interrupts
+ * from the 9221 ethernet controller.
+ */
+static void
+configgpio(void)
+{
+ Gpio *gpio = (Gpio *)PHYSGPIO6;
+
+ gpio->sysconfig = Softreset;
+ coherence();
+ resetwait(&gpio->sysstatus);
+
+ gpio->ctrl = 1<<1 | 0; /* enable this gpio module, gating ratio 1 */
+ gpio->oe |= Etherchanbit; /* cfg ether pin as input */
+ coherence();
+
+ gpio->irqen1 = Etherchanbit; /* channel # == pin # */
+ gpio->irqen2 = 0;
+
+ gpio->lvldet0 = Etherchanbit; /* enable irq ass'n on low det'n */
+ gpio->lvldet1 = 0; /* disable irq ass'n on high det'n */
+ gpio->risingdet = 0; /* enable irq rising edge det'n */
+ gpio->fallingdet = 0; /* disable irq falling edge det'n */
+
+ gpio->wkupen = 0;
+
+ gpio->deben = 0; /* no de-bouncing */
+ gpio->debtime = 0;
+ coherence();
+
+ gpio->irqsts1 = ~0; /* dismiss all outstanding intrs */
+ gpio->irqsts2 = ~0;
+ coherence();
+}
+
+void
+configscreengpio(void)
+{
+ Cm *wkup = (Cm *)PHYSSCMWKUP;
+ Gpio *gpio = (Gpio *)PHYSGPIO1;
+
+ /* no clocksel needed */
+ wkup->iclken |= Wkgpio1;
+ coherence();
+ wkup->fclken |= Wkgpio1; /* turn gpio clock on */
+ coherence();
+ // wkup->autoidle |= Wkgpio1; /* set gpio clock on auto */
+ wkup->autoidle = 0;
+ coherence();
+ while (wkup->idlest & Gpio1idle)
+ ;
+
+ /*
+ * 0 bits in oe are output signals.
+ * enable output for gpio 1 (first gpio) video magic pins.
+ */
+ gpio->oe &= ~Gpio1vidmagic;
+ coherence();
+ gpio->dataout |= Gpio1vidmagic; /* set output pins to 1 */
+ coherence();
+ delay(50);
+}
+
+void
+screenclockson(void)
+{
+ Cm *dss = (Cm *)PHYSSCMDSS;
+
+ dss->iclken |= Dssl3l4;
+ coherence();
+ dss->fclken = Dsstv | Dss2 | Dss1;
+ coherence();
+ /* tv fclk is dpll4 clk; dpll4 m4 divide factor for dss1 fclk is 2 */
+ dss->clksel[0] = 1<<12 | 2;
+ coherence();
+ delay(50);
+ while (dss->idlest & Dssidle)
+ ;
+}
+
+void
+gpioirqclr(void)
+{
+ Gpio *gpio = (Gpio *)PHYSGPIO6;
+
+ gpio->irqsts1 = gpio->irqsts1;
+ coherence();
+}
+
+static char *
+l1iptype(uint type)
+{
+ static char *types[] = {
+ "reserved",
+ "asid-tagged VIVT",
+ "VIPT",
+ "PIPT",
+ };
+
+ if (type >= nelem(types) || types[type] == nil)
+ return "GOK";
+ return types[type];
+}
+
+void
+cacheinfo(int level, Memcache *cp)
+{
+ ulong setsways;
+
+ /* select cache level */
+ cpwrsc(CpIDcssel, CpID, CpIDid, 0, (level - 1) << 1);
+
+ setsways = cprdsc(CpIDcsize, CpID, CpIDid, 0);
+ cp->l1ip = cprdsc(0, CpID, CpIDidct, CpIDct);
+ cp->level = level;
+ cp->nways = ((setsways >> 3) & MASK(10)) + 1;
+ cp->nsets = ((setsways >> 13) & MASK(15)) + 1;
+ cp->log2linelen = (setsways & MASK(2)) + 2 + 2;
+ cp->linelen = 1 << cp->log2linelen;
+ cp->setsways = setsways;
+
+ cp->setsh = cp->log2linelen;
+ cp->waysh = 32 - log2(cp->nways);
+}
+
+static void
+prcachecfg(void)
+{
+ int cache;
+ Memcache mc;
+
+ for (cache = 1; cache <= 2; cache++) {
+ cacheinfo(cache, &mc);
+ iprint("l%d: %d ways %d sets %d bytes/line",
+ mc.level, mc.nways, mc.nsets, mc.linelen);
+ if (mc.linelen != CACHELINESZ)
+ iprint(" *should* be %d", CACHELINESZ);
+ if (mc.setsways & Cawt)
+ iprint("; can WT");
+ if (mc.setsways & Cawb)
+ iprint("; can WB");
+#ifdef COMPULSIVE /* both caches can do this */
+ if (mc.setsways & Cara)
+ iprint("; can read-allocate");
+#endif
+ if (mc.setsways & Cawa)
+ iprint("; can write-allocate");
+ if (cache == 1)
+ iprint("; l1 I policy %s",
+ l1iptype((mc.l1ip >> 14) & MASK(2)));
+ iprint("\n");
+ }
+}
+
+static char *
+subarch(int impl, uint sa)
+{
+ static char *armarchs[] = {
+ "VFPv1 (pre-armv7)",
+ "VFPv2 (pre-armv7)",
+ "VFPv3+ with common VFP subarch v2",
+ "VFPv3+ with null subarch",
+ "VFPv3+ with common VFP subarch v3",
+ };
+
+ if (impl != 'A' || sa >= nelem(armarchs))
+ return "GOK";
+ else
+ return armarchs[sa];
+}
+
+/*
+ * padconf bits in a short, 2 per long register
+ * 15 wakeupevent
+ * 14 wakeupenable
+ * 13 offpulltypeselect
+ * 12 offpulludenable
+ * 11 offoutvalue
+ * 10 offoutenable
+ * 9 offenable
+ * 8 inputenable
+ * 4 pulltypeselect
+ * 3 pulludenable
+ * 2-0 muxmode
+ *
+ * see table 7-5 in §7.4.4.3 of spruf98d
+ */
+
+enum {
+ /* pad config register bits */
+ Inena = 1 << 8, /* input enable */
+ Indis = 0 << 8, /* input disable */
+ Ptup = 1 << 4, /* pull type up */
+ Ptdown = 0 << 4, /* pull type down */
+ Ptena = 1 << 3, /* pull type selection is active */
+ Ptdis = 0 << 3, /* pull type selection is inactive */
+ Muxmode = MASK(3),
+
+ /* pad config registers relevant to flash */
+ GpmcA1 = 0x4800207A,
+ GpmcA2 = 0x4800207C,
+ GpmcA3 = 0x4800207E,
+ GpmcA4 = 0x48002080,
+ GpmcA5 = 0x48002082,
+ GpmcA6 = 0x48002084,
+ GpmcA7 = 0x48002086,
+ GpmcA8 = 0x48002088,
+ GpmcA9 = 0x4800208A,
+ GpmcA10 = 0x4800208C,
+ GpmcD0 = 0x4800208E,
+ GpmcD1 = 0x48002090,
+ GpmcD2 = 0x48002092,
+ GpmcD3 = 0x48002094,
+ GpmcD4 = 0x48002096,
+ GpmcD5 = 0x48002098,
+ GpmcD6 = 0x4800209A,
+ GpmcD7 = 0x4800209C,
+ GpmcD8 = 0x4800209E,
+ GpmcD9 = 0x480020A0,
+ GpmcD10 = 0x480020A2,
+ GpmcD11 = 0x480020A4,
+ GpmcD12 = 0x480020A6,
+ GpmcD13 = 0x480020A8,
+ GpmcD14 = 0x480020AA,
+ GpmcD15 = 0x480020AC,
+ GpmcNCS0 = 0x480020AE,
+ GpmcNCS1 = 0x480020B0,
+ GpmcNCS2 = 0x480020B2,
+ GpmcNCS3 = 0x480020B4,
+ GpmcNCS4 = 0x480020B6,
+ GpmcNCS5 = 0x480020B8,
+ GpmcNCS6 = 0x480020BA,
+ GpmcNCS7 = 0x480020BC,
+ GpmcCLK = 0x480020BE,
+ GpmcNADV_ALE = 0x480020C0,
+ GpmcNOE = 0x480020C2,
+ GpmcNWE = 0x480020C4,
+ GpmcNBE0_CLE = 0x480020C6,
+ GpmcNBE1 = 0x480020C8,
+ GpmcNWP = 0x480020CA,
+ GpmcWAIT0 = 0x480020CC,
+ GpmcWAIT1 = 0x480020CE,
+ GpmcWAIT2 = 0x480020D0,
+ GpmcWAIT3 = 0x480020D2,
+};
+
+/* set SCM pad config mux mode */
+void
+setmuxmode(ulong addr, int shorts, int mode)
+{
+ int omode;
+ ushort *ptr;
+
+ mode &= Muxmode;
+ for (ptr = (ushort *)addr; shorts-- > 0; ptr++) {
+ omode = *ptr & Muxmode;
+ if (omode != mode)
+ *ptr = *ptr & ~Muxmode | mode;
+ }
+ coherence();
+}
+
+static void
+setpadmodes(void)
+{
+ int off;
+
+ /* set scm pad modes for usb; hasn't made any difference yet */
+ setmuxmode(0x48002166, 7, 5); /* hsusb3_tll* in mode 5; is mode 4 */
+ setmuxmode(0x48002180, 1, 5); /* hsusb3_tll_clk; is mode 4 */
+ setmuxmode(0x48002184, 4, 5); /* hsusb3_tll_data?; is mode 1 */
+ setmuxmode(0x480021a2, 12, 0); /* hsusb0 (console) in mode 0 */
+ setmuxmode(0x480021d4, 6, 2); /* hsusb2_tll* (ehci port 2) in mode 2 */
+ /* mode 3 is hsusb2_data* */
+ setmuxmode(0x480025d8, 18, 6); /* hsusb[12]_tll*; mode 3 is */
+ /* hsusb1_data*, hsusb2* */
+
+ setmuxmode(0x480020e4, 2, 5); /* uart3_rx_* in mode 5 */
+ setmuxmode(0x4800219a, 4, 0); /* uart3_* in mode 0 */
+ /* uart3_* in mode 2; TODO: conflicts with hsusb0 */
+ setmuxmode(0x480021aa, 4, 2);
+ setmuxmode(0x48002240, 2, 3); /* uart3_* in mode 3 */
+
+ /*
+ * igep/gumstix only: mode 4 of 21d2 is gpio_176 (smsc9221 ether irq).
+ * see ether9221.c for more.
+ */
+ *(ushort *)0x480021d2 = Inena | Ptup | Ptena | 4;
+
+ /* magic from u-boot for flash */
+ *(ushort *)GpmcA1 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcA2 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcA3 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcA4 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcA5 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcA6 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcA7 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcA8 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcA9 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcA10 = Indis | Ptup | Ptena | 0;
+
+ *(ushort *)GpmcD0 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD1 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD2 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD3 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD4 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD5 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD6 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD7 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD8 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD9 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD10 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD11 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD12 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD13 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD14 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcD15 = Inena | Ptup | Ptena | 0;
+
+ *(ushort *)GpmcNCS0 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcNCS1 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcNCS2 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcNCS3 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcNCS4 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcNCS5 = Indis | Ptup | Ptena | 0;
+ *(ushort *)GpmcNCS6 = Indis | Ptup | Ptena | 0;
+
+ *(ushort *)GpmcNOE = Indis | Ptdown | Ptdis | 0;
+ *(ushort *)GpmcNWE = Indis | Ptdown | Ptdis | 0;
+
+ *(ushort *)GpmcWAIT2 = Inena | Ptup | Ptena | 4; /* GPIO_64 -ETH_NRESET */
+ *(ushort *)GpmcNCS7 = Inena | Ptup | Ptena | 1; /* SYS_nDMA_REQ3 */
+
+ *(ushort *)GpmcCLK = Indis | Ptdown | Ptdis | 0;
+
+ *(ushort *)GpmcNBE1 = Inena | Ptdown | Ptdis | 0;
+
+ *(ushort *)GpmcNADV_ALE = Indis | Ptdown | Ptdis | 0;
+ *(ushort *)GpmcNBE0_CLE = Indis | Ptdown | Ptdis | 0;
+
+ *(ushort *)GpmcNWP = Inena | Ptdown | Ptdis | 0;
+
+ *(ushort *)GpmcWAIT0 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcWAIT1 = Inena | Ptup | Ptena | 0;
+ *(ushort *)GpmcWAIT3 = Inena | Ptup | Ptena | 0;
+
+ /*
+ * magic from u-boot: set 0xe00 bits in gpmc_(nwe|noe|nadv_ale)
+ * to enable `off' mode for each.
+ */
+ for (off = 0xc0; off <= 0xc4; off += sizeof(short))
+ *((ushort *)(PHYSSCM + off)) |= 0xe00;
+ coherence();
+}
+
+static char *
+implement(uchar impl)
+{
+ if (impl == 'A')
+ return "arm";
+ else
+ return "unknown";
+}
+
+static void
+fpon(void)
+{
+ int gotfp, impl;
+ ulong acc, scr;
+
+ gotfp = 1 << CpFP | 1 << CpDFP;
+ cpwrsc(0, CpCONTROL, 0, CpCPaccess, MASK(28));
+ acc = cprdsc(0, CpCONTROL, 0, CpCPaccess);
+ if ((acc & (MASK(2) << (2*CpFP))) == 0) {
+ gotfp &= ~(1 << CpFP);
+ print("fpon: no single FP coprocessor\n");
+ }
+ if ((acc & (MASK(2) << (2*CpDFP))) == 0) {
+ gotfp &= ~(1 << CpDFP);
+ print("fpon: no double FP coprocessor\n");
+ }
+ if (!gotfp) {
+ print("fpon: no FP coprocessors\n");
+ return;
+ }
+
+ /* enable fp. must be first operation on the FPUs. */
+ fpwr(Fpexc, fprd(Fpexc) | 1 << 30);
+
+ scr = fprd(Fpsid);
+ impl = scr >> 24;
+ print("fp: %s arch %s", implement(impl),
+ subarch(impl, (scr >> 16) & MASK(7)));
+
+ scr = fprd(Fpscr);
+ // TODO configure Fpscr further
+ scr |= 1 << 9; /* div-by-0 exception */
+ scr &= ~(MASK(2) << 20 | MASK(3) << 16); /* all ops are scalar */
+ fpwr(Fpscr, scr);
+ print("\n");
+ /* we should now be able to execute VFP-style FP instr'ns natively */
+}
+
+static void
+resetusb(void)
+{
+ int bound;
+ Uhh *uhh;
+ Usbotg *otg;
+ Usbtll *tll;
+
+ iprint("resetting usb: otg...");
+ otg = (Usbotg *)PHYSUSBOTG;
+ otg->otgsyscfg = Softreset; /* see omap35x errata 3.1.1.144 */
+ coherence();
+ resetwait(&otg->otgsyssts);
+ otg->otgsyscfg |= Sidle | Midle;
+ coherence();
+
+ iprint("uhh...");
+ uhh = (Uhh *)PHYSUHH;
+ uhh->sysconfig |= Softreset;
+ coherence();
+ resetwait(&uhh->sysstatus);
+ for (bound = 400*Mhz; !(uhh->sysstatus & Resetdone) && bound > 0;
+ bound--)
+ ;
+ uhh->sysconfig |= Sidle | Midle;
+
+ /*
+ * using the TLL seems to be an optimisation when talking
+ * to another identical SoC, thus not very useful, so
+ * force PHY (ULPI) mode.
+ */
+ /* this bit is normally off when we get here */
+ uhh->hostconfig &= ~P1ulpi_bypass;
+ coherence();
+ if (uhh->hostconfig & P1ulpi_bypass)
+ iprint("utmi (tll) mode..."); /* via tll */
+ else
+ /* external transceiver (phy), no tll */
+ iprint("ulpi (phy) mode...");
+
+ tll = (Usbtll *)PHYSUSBTLL;
+ if (probeaddr(PHYSUSBTLL) >= 0) {
+ iprint("tll...");
+ tll->sysconfig |= Softreset;
+ coherence();
+ resetwait(&tll->sysstatus);
+ tll->sysconfig |= Sidle;
+ coherence();
+ } else
+ iprint("no tll...");
+ iprint("\n");
+}
+
+/*
+ * there are secure sdrc registers at 0x48002460
+ * sdrc regs at PHYSSDRC; see spruf98c §1.2.8.2.
+ * set or dump l4 prot regs at PHYSL4?
+ */
+void
+archreset(void)
+{
+ static int beenhere;
+
+ if (beenhere)
+ return;
+ beenhere = 1;
+
+ /* conservative temporary values until archconfinit runs */
+ m->cpuhz = 500 * Mhz; /* beagle speed */
+ m->delayloop = m->cpuhz/2000; /* initial estimate */
+
+// dumpl3pr();
+ prcachecfg();
+ /* fight omap35x errata 2.0.1.104 */
+ memset((void *)PHYSSWBOOTCFG, 0, 240);
+ coherence();
+
+ setpadmodes();
+ configclks(); /* may change cpu speed */
+ configgpio();
+
+ archconfinit();
+
+ resetusb();
+ fpon();
+}
+
+void
+archreboot(void)
+{
+ Prm *prm = (Prm *)PHYSPRMGLBL;
+
+ iprint("archreboot: reset!\n");
+ delay(20);
+
+ prm->rstctrl |= Rstgs;
+ coherence();
+ delay(500);
+
+ /* shouldn't get here */
+ splhi();
+ iprint("awaiting reset");
+ for(;;) {
+ delay(1000);
+ print(".");
+ }
+}
+
+void
+kbdinit(void)
+{
+}
+
+void
+lastresortprint(char *buf, long bp)
+{
+ iprint("%.*s", (int)bp, buf); /* nothing else seems to work */
+}
+
+static void
+scmdump(ulong addr, int shorts)
+{
+ ushort reg;
+ ushort *ptr;
+
+ ptr = (ushort *)addr;
+ print("scm regs:\n");
+ while (shorts-- > 0) {
+ reg = *ptr++;
+ print("%#p: %#ux\tinputenable %d pulltypeselect %d "
+ "pulludenable %d muxmode %d\n",
+ ptr, reg, (reg>>8) & 1, (reg>>4) & 1, (reg>>3) & 1,
+ reg & 7);
+ }
+}
+
+char *cputype2name(char *buf, int size);
+
+void
+cpuidprint(void)
+{
+ char name[64];
+
+ cputype2name(name, sizeof name);
+ delay(250); /* let uart catch up */
+ iprint("cpu%d: %lldMHz ARM %s\n", m->machno, m->cpuhz / Mhz, name);
+}
+
+static void
+missing(ulong addr, char *name)
+{
+ static int firstmiss = 1;
+
+ if (probeaddr(addr) >= 0)
+ return;
+ if (firstmiss) {
+ iprint("missing:");
+ firstmiss = 0;
+ } else
+ iprint(",\n\t");
+ iprint(" %s at %#lux", name, addr);
+}
+
+/* verify that all the necessary device registers are accessible */
+void
+chkmissing(void)
+{
+ delay(20);
+ missing(PHYSSCM, "scm");
+ missing(KZERO, "dram");
+ missing(PHYSL3, "l3 config");
+ missing(PHYSINTC, "intr ctlr");
+ missing(PHYSTIMER1, "timer1");
+ missing(PHYSCONS, "console uart2");
+ missing(PHYSUART0, "uart0");
+ missing(PHYSUART1, "uart1");
+ missing(PHYSETHER, "smc9221"); /* not on beagle */
+ missing(PHYSUSBOTG, "usb otg");
+ missing(PHYSUHH, "usb uhh");
+ missing(PHYSOHCI, "usb ohci");
+ missing(PHYSEHCI, "usb ehci");
+ missing(PHYSSDMA, "dma");
+ missing(PHYSWDOG, "watchdog timer");
+ missing(PHYSUSBTLL, "usb tll");
+ iprint("\n");
+ delay(20);
+}
+
+void
+archflashwp(Flash*, int)
+{
+}
+
+/*
+ * for ../port/devflash.c:/^flashreset
+ * retrieve flash type, virtual base and length and return 0;
+ * return -1 on error (no flash)
+ */
+int
+archflashreset(int bank, Flash *f)
+{
+ if(bank != 0)
+ return -1;
+ /*
+ * this is set up for the igepv2 board.
+ * if the beagleboard ever works, we'll have to sort this out.
+ */
+ f->type = "onenand";
+ f->addr = (void*)PHYSNAND; /* mapped here by archreset */
+ f->size = 0; /* done by probe */
+ f->width = 1;
+ f->interleave = 0;
+ return 0;
+}
diff --git a/sys/src/9/omap/arm.h b/sys/src/9/omap/arm.h
new file mode 100755
index 000000000..12443d849
--- /dev/null
+++ b/sys/src/9/omap/arm.h
@@ -0,0 +1,246 @@
+/*
+ * arm-specific definitions for cortex-a8
+ * these are used in C and assembler
+ *
+ * `cortex' refers specifically to the cortex-a8.
+ */
+
+/*
+ * Program Status Registers
+ */
+#define PsrMusr 0x00000010 /* mode */
+#define PsrMfiq 0x00000011
+#define PsrMirq 0x00000012
+#define PsrMsvc 0x00000013 /* `protected mode for OS' */
+#define PsrMmon 0x00000016 /* `secure monitor' (trustzone hyper) */
+#define PsrMabt 0x00000017
+#define PsrMund 0x0000001B
+#define PsrMsys 0x0000001F /* `privileged user mode for OS' (trustzone) */
+#define PsrMask 0x0000001F
+
+#define PsrDfiq 0x00000040 /* disable FIQ interrupts */
+#define PsrDirq 0x00000080 /* disable IRQ interrupts */
+
+#define PsrV 0x10000000 /* overflow */
+#define PsrC 0x20000000 /* carry/borrow/extend */
+#define PsrZ 0x40000000 /* zero */
+#define PsrN 0x80000000 /* negative/less than */
+
+/*
+ * Coprocessors
+ */
+#define CpFP 10 /* float FP, VFP cfg. */
+#define CpDFP 11 /* double FP */
+#define CpSC 15 /* System Control */
+
+/*
+ * Primary (CRn) CpSC registers.
+ */
+#define CpID 0 /* ID and cache type */
+#define CpCONTROL 1 /* miscellaneous control */
+#define CpTTB 2 /* Translation Table Base(s) */
+#define CpDAC 3 /* Domain Access Control */
+#define CpFSR 5 /* Fault Status */
+#define CpFAR 6 /* Fault Address */
+#define CpCACHE 7 /* cache/write buffer control */
+#define CpTLB 8 /* TLB control */
+#define CpCLD 9 /* L2 Cache Lockdown, op1==1 */
+#define CpTLD 10 /* TLB Lockdown, with op2 */
+#define CpVECS 12 /* vector bases, op1==0, Crm==0, op2s (cortex) */
+#define CpPID 13 /* Process ID */
+#define CpDTLB 15 /* TLB, L1 cache stuff (cortex) */
+
+/*
+ * CpTTB op1==0, Crm==0 opcode2 values.
+ */
+#define CpTTB0 0
+#define CpTTB1 1 /* cortex */
+#define CpTTBctl 2 /* cortex */
+
+/*
+ * CpID Secondary (CRm) registers.
+ */
+#define CpIDidct 0
+
+/*
+ * CpID op1==0 opcode2 fields.
+ * the cortex has more op1 codes for cache size, etc.
+ */
+#define CpIDid 0 /* main ID */
+#define CpIDct 1 /* cache type */
+#define CpIDtlb 3 /* tlb type (cortex) */
+#define CpIDmpid 5 /* multiprocessor id (cortex) */
+
+/* CpIDid op1 values */
+#define CpIDcsize 1 /* cache size (cortex) */
+#define CpIDcssel 2 /* cache size select (cortex) */
+
+/*
+ * CpCONTROL op2 codes, op1==0, Crm==0.
+ */
+#define CpMainctl 0
+#define CpAuxctl 1
+#define CpCPaccess 2
+
+/*
+ * CpCONTROL: op1==0, CRm==0, op2==CpMainctl.
+ * main control register.
+ * cortex/armv7 has more ops and CRm values.
+ */
+#define CpCmmu 0x00000001 /* M: MMU enable */
+#define CpCalign 0x00000002 /* A: alignment fault enable */
+#define CpCdcache 0x00000004 /* C: data cache on */
+#define CpCsbo (3<<22|1<<18|1<<16|017<<3) /* must be 1 (armv7) */
+#define CpCsbz (CpCtre|1<<26|CpCve|1<<15|7<<7) /* must be 0 (armv7) */
+#define CpCsw (1<<10) /* SW: SWP(B) enable (deprecated in v7) */
+#define CpCpredict 0x00000800 /* Z: branch prediction (armv7) */
+#define CpCicache 0x00001000 /* I: instruction cache on */
+#define CpChv 0x00002000 /* V: high vectors */
+#define CpCrr (1<<14) /* RR: round robin vs random cache replacement */
+#define CpCha (1<<17) /* HA: hw access flag enable */
+#define CpCdz (1<<19) /* DZ: divide by zero fault enable */
+#define CpCfi (1<<21) /* FI: fast intrs */
+#define CpCve (1<<24) /* VE: intr vectors enable */
+#define CpCee (1<<25) /* EE: exception endianness */
+#define CpCnmfi (1<<27) /* NMFI: non-maskable fast intrs. */
+#define CpCtre (1<<28) /* TRE: TEX remap enable */
+#define CpCafe (1<<29) /* AFE: access flag (ttb) enable */
+
+/*
+ * CpCONTROL: op1==0, CRm==0, op2==CpAuxctl.
+ * Auxiliary control register on cortex at least.
+ */
+#define CpACcachenopipe (1<<20) /* don't pipeline cache maint. */
+#define CpACcp15serial (1<<18) /* serialise CP1[45] ops. */
+#define CpACcp15waitidle (1<<17) /* CP1[45] wait-on-idle */
+#define CpACcp15pipeflush (1<<16) /* CP1[45] flush pipeline */
+#define CpACneonissue1 (1<<12) /* neon single issue */
+#define CpACldstissue1 (1<<11) /* force single issue ld, st */
+#define CpACissue1 (1<<10) /* force single issue */
+#define CpACnobsm (1<<7) /* no branch size mispredicts */
+#define CpACibe (1<<6) /* cp15 invalidate & btb enable */
+#define CpACl1neon (1<<5) /* cache neon (FP) data in L1 cache */
+#define CpACasa (1<<4) /* enable speculative accesses */
+#define CpACl1pe (1<<3) /* l1 cache parity enable */
+#define CpACl2en (1<<1) /* l2 cache enable; default 1 */
+/*
+ * CpCONTROL Secondary (CRm) registers and opcode2 fields.
+ */
+#define CpCONTROLscr 1
+
+#define CpSCRscr 0
+
+/*
+ * CpCACHE Secondary (CRm) registers and opcode2 fields. op1==0.
+ * In ARM-speak, 'flush' means invalidate and 'clean' means writeback.
+ */
+#define CpCACHEintr 0 /* interrupt (op2==4) */
+#define CpCACHEisi 1 /* inner-sharable I cache (v7) */
+#define CpCACHEpaddr 4 /* 0: phys. addr (cortex) */
+#define CpCACHEinvi 5 /* instruction, branch table */
+#define CpCACHEinvd 6 /* data or unified */
+// #define CpCACHEinvu 7 /* unified (not on cortex) */
+#define CpCACHEva2pa 8 /* va -> pa translation (cortex) */
+#define CpCACHEwb 10 /* writeback */
+#define CpCACHEinvdse 11 /* data or unified by mva */
+#define CpCACHEwbi 14 /* writeback+invalidate */
+
+#define CpCACHEall 0 /* entire (not for invd nor wb(i) on cortex) */
+#define CpCACHEse 1 /* single entry */
+#define CpCACHEsi 2 /* set/index (set/way) */
+#define CpCACHEtest 3 /* test loop */
+#define CpCACHEwait 4 /* wait (prefetch flush on cortex) */
+#define CpCACHEdmbarr 5 /* wb only (cortex) */
+#define CpCACHEflushbtc 6 /* flush branch-target cache (cortex) */
+#define CpCACHEflushbtse 7 /* ⋯ or just one entry in it (cortex) */
+
+/*
+ * CpTLB Secondary (CRm) registers and opcode2 fields.
+ */
+#define CpTLBinvi 5 /* instruction */
+#define CpTLBinvd 6 /* data */
+#define CpTLBinvu 7 /* unified */
+
+#define CpTLBinv 0 /* invalidate all */
+#define CpTLBinvse 1 /* invalidate single entry */
+#define CpTBLasid 2 /* by ASID (cortex) */
+
+/*
+ * CpCLD Secondary (CRm) registers and opcode2 fields for op1==0. (cortex)
+ */
+#define CpCLDena 12 /* enables */
+#define CpCLDcyc 13 /* cycle counter */
+#define CpCLDuser 14 /* user enable */
+
+#define CpCLDenapmnc 0
+#define CpCLDenacyc 1
+
+/*
+ * CpCLD Secondary (CRm) registers and opcode2 fields for op1==1.
+ */
+#define CpCLDl2 0 /* l2 cache */
+
+#define CpCLDl2aux 2 /* auxiliary control */
+
+/*
+ * l2 cache aux. control
+ */
+#define CpCl2ecc (1<<28) /* use ecc, not parity */
+#define CpCl2noldforw (1<<27) /* no ld forwarding */
+#define CpCl2nowrcomb (1<<25) /* no write combining */
+#define CpCl2nowralldel (1<<24) /* no write allocate delay */
+#define CpCl2nowrallcomb (1<<23) /* no write allocate combine */
+#define CpCl2nowralloc (1<<22) /* no write allocate */
+#define CpCl2eccparity (1<<21) /* enable ecc or parity */
+#define CpCl2inner (1<<16) /* inner cacheability */
+/* other bits are tag ram & data ram latencies */
+
+/*
+ * CpTLD Secondary (CRm) registers and opcode2 fields.
+ */
+#define CpTLDlock 0 /* TLB lockdown registers */
+#define CpTLDpreload 1 /* TLB preload */
+
+#define CpTLDi 0 /* TLB instr. lockdown reg. */
+#define CpTLDd 1 /* " data " " */
+
+/*
+ * CpVECS Secondary (CRm) registers and opcode2 fields.
+ */
+#define CpVECSbase 0
+
+#define CpVECSnorm 0 /* (non-)secure base addr */
+#define CpVECSmon 1 /* secure monitor base addr */
+
+/*
+ * MMU page table entries.
+ * Mbz (0x10) bit is implementation-defined and must be 0 on the cortex.
+ */
+#define Mbz (0<<4)
+#define Fault 0x00000000 /* L[12] pte: unmapped */
+
+#define Coarse (Mbz|1) /* L1 */
+#define Section (Mbz|2) /* L1 1MB */
+#define Fine (Mbz|3) /* L1 */
+
+#define Large 0x00000001 /* L2 64KB */
+#define Small 0x00000002 /* L2 4KB */
+#define Tiny 0x00000003 /* L2 1KB: not in v7 */
+#define Buffered 0x00000004 /* L[12]: write-back not -thru */
+#define Cached 0x00000008 /* L[12] */
+#define Dom0 0
+
+#define Noaccess 0 /* AP, DAC */
+#define Krw 1 /* AP */
+/* armv7 deprecates AP[2] == 1 & AP[1:0] == 2 (Uro), prefers 3 (new in v7) */
+#define Uro 2 /* AP */
+#define Urw 3 /* AP */
+#define Client 1 /* DAC */
+#define Manager 3 /* DAC */
+
+#define AP(n, v) F((v), ((n)*2)+4, 2)
+#define L1AP(ap) (AP(3, (ap)))
+#define L2AP(ap) (AP(0, (ap))) /* armv7 */
+#define DAC(n, v) F((v), (n)*2, 2)
+
+#define HVECTORS 0xffff0000
diff --git a/sys/src/9/omap/arm.s b/sys/src/9/omap/arm.s
new file mode 100755
index 000000000..829e36234
--- /dev/null
+++ b/sys/src/9/omap/arm.s
@@ -0,0 +1,95 @@
+/*
+ * omap3530 machine assist, definitions
+ * cortex-a8 processor
+ *
+ * loader uses R11 as scratch.
+ */
+
+#include "mem.h"
+#include "arm.h"
+
+#undef B /* B is for 'botch' */
+
+#define KADDR(pa) (KZERO | ((pa) & ~KSEGM))
+#define PADDR(va) (PHYSDRAM | ((va) & ~KSEGM))
+
+#define L1X(va) (((((va))>>20) & 0x0fff)<<2)
+
+#define MACHADDR (L1-MACHSIZE)
+
+#define PTEDRAM (Dom0|L1AP(Krw)|Section|Cached|Buffered)
+#define PTEIO (Dom0|L1AP(Krw)|Section)
+
+#define DOUBLEMAPMBS 256 /* megabytes of low dram to double-map */
+
+/* steps on R0 */
+#define DELAY(label, mloops) \
+ MOVW $((mloops)*1000000), R0; \
+label: \
+ SUB.S $1, R0; \
+ BNE label
+
+/* wave at the user; clobbers R0, R1 & R6; needs R12 (SB) set */
+#define WAVE(c) \
+ BARRIERS; \
+ MOVW $(c), R1; \
+ MOVW $PHYSCONS, R6; \
+ MOVW R1, (R6); \
+ BARRIERS
+
+/*
+ * new instructions
+ */
+
+#define SMC WORD $0xe1600070 /* low 4-bits are call # (trustzone) */
+/* flush branch-target cache; zeroes R0 (cortex) */
+#define FLBTC \
+ MOVW $0, R0; \
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEflushbtc
+/* flush one entry of the branch-target cache, va in R0 (cortex) */
+#define FLBTSE \
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEflushbtse
+
+/* arm v7 arch defines these */
+#define WFI WORD $0xe320f003 /* wait for interrupt */
+#define DMB WORD $0xf57ff05f /* data mem. barrier; last f = SY */
+#define DSB WORD $0xf57ff04f /* data synch. barrier; last f = SY */
+#define ISB WORD $0xf57ff06f /* instr. sync. barrier; last f = SY */
+#define NOOP WORD $0xe320f000
+#define CLZ(s, d) WORD $(0xe16f0f10 | (d) << 12 | (s)) /* count leading 0s */
+#define CPSIE WORD $0xf1080080 /* intr enable: zeroes I bit */
+#define CPSID WORD $0xf10c0080 /* intr disable: sets I bit */
+
+/* floating point */
+#define VMRS(fp, cpu) WORD $(0xeef00a10 | (fp)<<16 | (cpu)<<12) /* FP → arm */
+#define VMSR(cpu, fp) WORD $(0xeee00a10 | (fp)<<16 | (cpu)<<12) /* arm → FP */
+
+/*
+ * a popular code sequence used to write a pte for va is:
+ *
+ * MOVW R(n), TTB[LnX(va)]
+ * // clean the cache line
+ * DSB
+ * // invalidate tlb entry for va
+ * FLBTC
+ * DSB
+ * PFF (now ISB)
+ */
+/* zeroes R0 */
+#define BARRIERS FLBTC; DSB; ISB
+
+/*
+ * invoked with PTE bits in R2, pa in R3, PTE pointed to by R4.
+ * fill PTE pointed to by R4 and increment R4 past it.
+ * increment R3 by a MB. clobbers R1.
+ */
+#define FILLPTE() \
+ ORR R3, R2, R1; /* pte bits in R2, pa in R3 */ \
+ MOVW R1, (R4); \
+ ADD $4, R4; /* bump PTE address */ \
+ ADD $MiB, R3; /* bump pa */ \
+
+/* zero PTE pointed to by R4 and increment R4 past it. assumes R0 is 0. */
+#define ZEROPTE() \
+ MOVW R0, (R4); \
+ ADD $4, R4; /* bump PTE address */
diff --git a/sys/src/9/omap/beagle b/sys/src/9/omap/beagle
new file mode 100755
index 000000000..887395443
--- /dev/null
+++ b/sys/src/9/omap/beagle
@@ -0,0 +1,82 @@
+# beagle, igepv2, gumstix overo omap35 boards
+dev
+ root
+ cons
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ arch
+ ssl
+ tls
+ bridge log
+ sdp thwack unthwack
+ cap
+ kprof
+# aoe
+# sd
+ fs
+# flash
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno
+
+ draw screen
+ dss
+ kbmap
+ kbin
+ mouse
+
+ uart
+# usb
+
+link
+ archomap
+ ethermedium
+# flashbeagle ecc
+# flashigep
+ loopbackmedium
+ netdevmedium
+
+ ether9221
+## avoid tickling errata 3.1.1.183
+## usbohci
+# usbehci usbehciomap
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+ ipmux
+ gre
+ esp
+
+misc
+ rdb
+ coproc
+ dma
+ mouse
+# sdaoe sdscsi
+ softfpu
+ syscall
+ uarti8250
+ ucalloc
+ ucallocb
+
+port
+ int cpuserver = 1;
+ int i8250freq = 3686000;
+
+boot cpu
+ tcp
+
+bootdir
+ boot$CONF.out boot
+ /arm/bin/ip/ipconfig ipconfig
+ /arm/bin/auth/factotum factotum
+ /arm/bin/usb/usbd
+ nvram
diff --git a/sys/src/9/omap/cache.v7.s b/sys/src/9/omap/cache.v7.s
new file mode 100755
index 000000000..d6a6eef6e
--- /dev/null
+++ b/sys/src/9/omap/cache.v7.s
@@ -0,0 +1,208 @@
+/*
+ * cortex arm arch v7 cache flushing and invalidation
+ * shared by l.s and rebootcode.s
+ */
+
+TEXT cacheiinv(SB), $-4 /* I invalidate */
+ MOVW $0, R0
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall /* ok on cortex */
+ ISB
+ RET
+
+/*
+ * set/way operators, passed a suitable set/way value in R0.
+ */
+TEXT cachedwb_sw(SB), $-4
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEsi
+ RET
+
+TEXT cachedwbinv_sw(SB), $-4
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEsi
+ RET
+
+TEXT cachedinv_sw(SB), $-4
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEsi
+ RET
+
+ /* set cache size select */
+TEXT setcachelvl(SB), $-4
+ MCR CpSC, CpIDcssel, R0, C(CpID), C(CpIDid), 0
+ ISB
+ RET
+
+ /* return cache sizes */
+TEXT getwayssets(SB), $-4
+ MRC CpSC, CpIDcsize, R0, C(CpID), C(CpIDid), 0
+ RET
+
+/*
+ * l1 cache operations.
+ * l1 and l2 ops are intended to be called from C, thus need save no
+ * caller's regs, only those we need to preserve across calls.
+ */
+
+TEXT cachedwb(SB), $-4
+ MOVW.W R14, -8(R13)
+ MOVW $cachedwb_sw(SB), R0
+ MOVW $1, R8
+ BL wholecache(SB)
+ MOVW.P 8(R13), R15
+
+TEXT cachedwbinv(SB), $-4
+ MOVW.W R14, -8(R13)
+ MOVW $cachedwbinv_sw(SB), R0
+ MOVW $1, R8
+ BL wholecache(SB)
+ MOVW.P 8(R13), R15
+
+TEXT cachedinv(SB), $-4
+ MOVW.W R14, -8(R13)
+ MOVW $cachedinv_sw(SB), R0
+ MOVW $1, R8
+ BL wholecache(SB)
+ MOVW.P 8(R13), R15
+
+TEXT cacheuwbinv(SB), $-4
+ MOVM.DB.W [R14], (R13) /* save lr on stack */
+ MOVW CPSR, R1
+ CPSID /* splhi */
+
+ MOVM.DB.W [R1], (R13) /* save R1 on stack */
+
+ BL cachedwbinv(SB)
+ BL cacheiinv(SB)
+
+ MOVM.IA.W (R13), [R1] /* restore R1 (saved CPSR) */
+ MOVW R1, CPSR
+ MOVM.IA.W (R13), [R14] /* restore lr */
+ RET
+
+/*
+ * l2 cache operations
+ */
+
+TEXT l2cacheuwb(SB), $-4
+ MOVW.W R14, -8(R13)
+ MOVW $cachedwb_sw(SB), R0
+ MOVW $2, R8
+ BL wholecache(SB)
+ MOVW.P 8(R13), R15
+
+TEXT l2cacheuwbinv(SB), $-4
+ MOVW.W R14, -8(R13)
+ MOVW CPSR, R1
+ CPSID /* splhi */
+
+ MOVM.DB.W [R1], (R13) /* save R1 on stack */
+
+ MOVW $cachedwbinv_sw(SB), R0
+ MOVW $2, R8
+ BL wholecache(SB)
+ BL l2cacheuinv(SB)
+
+ MOVM.IA.W (R13), [R1] /* restore R1 (saved CPSR) */
+ MOVW R1, CPSR
+ MOVW.P 8(R13), R15
+
+TEXT l2cacheuinv(SB), $-4
+ MOVW.W R14, -8(R13)
+ MOVW $cachedinv_sw(SB), R0
+ MOVW $2, R8
+ BL wholecache(SB)
+ MOVW.P 8(R13), R15
+
+/*
+ * these shift values are for the Cortex-A8 L1 cache (A=2, L=6) and
+ * the Cortex-A8 L2 cache (A=3, L=6).
+ * A = log2(# of ways), L = log2(bytes per cache line).
+ * see armv7 arch ref p. 1403.
+ */
+#define L1WAYSH 30
+#define L1SETSH 6
+#define L2WAYSH 29
+#define L2SETSH 6
+
+/*
+ * callers are assumed to be the above l1 and l2 ops.
+ * R0 is the function to call in the innermost loop.
+ * R8 is the cache level (one-origin: 1 or 2).
+ *
+ * initial translation by 5c, then massaged by hand.
+ */
+TEXT wholecache+0(SB), $-4
+ MOVW R0, R1 /* save argument for inner loop in R1 */
+ SUB $1, R8 /* convert cache level to zero origin */
+
+ /* we may not have the MMU on yet, so map R1 to PC's space */
+ BIC $KSEGM, R1 /* strip segment from address */
+ MOVW PC, R2 /* get PC's segment ... */
+ AND $KSEGM, R2
+ CMP $0, R2 /* PC segment should be non-zero on omap */
+ BEQ buggery
+ ORR R2, R1 /* combine them */
+
+ /* drain write buffers */
+ BARRIERS
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
+ ISB
+
+ MOVW CPSR, R2
+ MOVM.DB.W [R2,R14], (SP) /* save regs on stack */
+ CPSID /* splhi to make entire op atomic */
+
+ /* get cache sizes */
+ SLL $1, R8, R0 /* R0 = (cache - 1) << 1 */
+ MCR CpSC, CpIDcssel, R0, C(CpID), C(CpIDid), 0 /* set cache size select */
+ ISB
+ MRC CpSC, CpIDcsize, R0, C(CpID), C(CpIDid), 0 /* get cache sizes */
+
+ /* compute # of ways and sets for this cache level */
+ SRA $3, R0, R5 /* R5 (ways) = R0 >> 3 */
+ AND $1023, R5 /* R5 = (R0 >> 3) & MASK(10) */
+ ADD $1, R5 /* R5 (ways) = ((R0 >> 3) & MASK(10)) + 1 */
+
+ SRA $13, R0, R2 /* R2 = R0 >> 13 */
+ AND $32767, R2 /* R2 = (R0 >> 13) & MASK(15) */
+ ADD $1, R2 /* R2 (sets) = ((R0 >> 13) & MASK(15)) + 1 */
+
+ /* precompute set/way shifts for inner loop */
+ CMP $0, R8 /* cache == 1? */
+ MOVW.EQ $L1WAYSH, R3 /* yes */
+ MOVW.EQ $L1SETSH, R4
+ MOVW.NE $L2WAYSH, R3 /* no */
+ MOVW.NE $L2SETSH, R4
+
+ /* iterate over ways */
+ MOVW $0, R7 /* R7: way */
+outer:
+ /* iterate over sets */
+ MOVW $0, R6 /* R6: set */
+inner:
+ /* compute set/way register contents */
+ SLL R3, R7, R0 /* R0 = way << R3 (L?WAYSH) */
+ ORR R8<<1, R0 /* R0 = way << L?WAYSH | (cache - 1) << 1 */
+ ORR R6<<R4, R0 /* R0 = way<<L?WAYSH | (cache-1)<<1 |set<<R4 */
+
+ BL (R1) /* call set/way operation with R0 */
+
+ ADD $1, R6 /* set++ */
+ CMP R2, R6 /* set >= sets? */
+ BLT inner /* no, do next set */
+
+ ADD $1, R7 /* way++ */
+ CMP R5, R7 /* way >= ways? */
+ BLT outer /* no, do next way */
+
+ MOVM.IA.W (SP), [R2,R14] /* restore regs */
+ MOVW R2, CPSR /* splx */
+
+ /* drain write buffers */
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
+ ISB
+ RET
+
+buggery:
+WAVE('?')
+ MOVW PC, R0
+// B pczeroseg(SB)
+ RET
diff --git a/sys/src/9/omap/clock.c b/sys/src/9/omap/clock.c
new file mode 100755
index 000000000..eaab1e270
--- /dev/null
+++ b/sys/src/9/omap/clock.c
@@ -0,0 +1,489 @@
+/*
+ * omap3530 clocks
+ *
+ * timers count up to zero.
+ *
+ * the source clock signals for the timers are sometimes selectable. for
+ * WDTIMER[23] and GPTIMER12, it's always the 32kHz clock. for the
+ * others, it can be the 32kHz clock or the system clock. we use only
+ * WDTIMER2 and GPTIMER[12], and configure GPTIMER[12] in archomap.c to
+ * use the 32kHZ clock. WDTIMER1 is not accessible to us on GP
+ * (general-purpose) omaps.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "arm.h"
+
+enum {
+ Debug = 0,
+
+ Tn0 = PHYSTIMER1,
+ Tn1 = PHYSTIMER2,
+
+ /* irq 36 is watchdog timer module 3 overflow */
+ Tn0irq = 37, /* base IRQ for all timers */
+
+ Freebase = 1, /* base of free-running timer */
+
+ /*
+ * clock is 32K (32,768) Hz, so one tick is 30.517µs,
+ * so 327.68 ticks is 10ms, 32.768 ticks is 1ms.
+ */
+ Clockfreqbase = 32 * 1024, /* base rate in Hz */
+ Tcycles = Clockfreqbase / HZ, /* cycles per clock tick */
+
+ MinPeriod = (Tcycles / 100 < 2? 2: Tcycles / 100),
+ MaxPeriod = Tcycles,
+
+ Dogtimeout = 20 * Clockfreqbase, /* was 4 s.; must be ≤ 21 s. */
+};
+
+enum {
+ /* ticpcfg bits */
+ Noidle = 1<<3,
+ Softreset = 1<<1,
+
+ /* tistat bits */
+ Resetdone = 1<<0,
+
+ /* tisr/tier bits */
+ Ovf_it = 1<<1, /* gp: overflow intr */
+ Mat_it = 1<<0, /* gp: match intr */
+ Wdovf_it = 1<<0, /* wdog: overflow intr */
+
+ /* tclr bits */
+ Ar = 1<<1, /* gp only: autoreload mode overflow */
+ St = 1<<0, /* gp only: start the timer */
+};
+
+/* omap35x timer registers */
+typedef struct Timerregs Timerregs;
+struct Timerregs {
+ /* common to all timers, gp and watchdog */
+ uchar pad0[0x10];
+ ulong ticpcfg;
+ ulong tistat; /* ro: low bit: reset done */
+ ulong tisr;
+ ulong tier;
+ ulong twer;
+ ulong tclr;
+ ulong tcrr; /* counter: cycles to zero */
+ ulong tldr;
+ ulong ttgr; /* trigger */
+ ulong twps; /* ro: write posted pending */
+
+ /* gp timers only, unused by us */
+ ulong tmar; /* value to compare with counter */
+ ulong tcar1; /* ro */
+ ulong tsicr;
+ ulong tcar2; /* ro */
+ union {
+ ulong tpir; /* gp: 1 ms tick generation: +ve */
+ ulong wspr; /* wdog: start/stop control */
+ };
+ ulong tnir; /* 1 ms tick generation: -ve */
+ ulong tcvr; /* 1 ms tick generation: next counter value */
+ ulong tocr; /* intr mask for n ticks */
+ ulong towr;
+};
+
+static int ticks; /* for sanity checking; m->ticks doesn't always get called */
+static Lock clklck;
+
+static ulong rdcycles(void), rdbaseticks(void);
+
+/* write a watchdog timer's start/stop register */
+static void
+wdogwrss(Timerregs *tn, ulong val)
+{
+ while (tn->twps & (1 << 4)) /* pending write to start/stop reg? */
+ ;
+ tn->wspr = val;
+ coherence();
+ while (tn->twps & (1 << 4)) /* pending write to start/stop reg? */
+ ;
+}
+
+static void
+resetwait(Timerregs *tn)
+{
+ long bound;
+
+ for (bound = 400*Mhz; !(tn->tistat & Resetdone) && bound > 0; bound--)
+ ;
+ if (bound <= 0)
+ iprint("clock reset didn't complete\n");
+}
+
+
+static void
+wdogoff(Timerregs *tn)
+{
+ resetwait(tn);
+
+ wdogwrss(tn, 0xaaaa); /* magic off sequence */
+ wdogwrss(tn, 0x5555);
+
+ tn->tldr = 1;
+ coherence();
+ tn->tcrr = 1; /* paranoia */
+ coherence();
+}
+
+static void wdogassure(void);
+
+static void
+wdogon(Timerregs *tn)
+{
+ static int beenhere;
+
+ resetwait(tn);
+ tn->tldr = -Dogtimeout;
+ tn->tcrr = -Dogtimeout;
+ coherence();
+ wdogwrss(tn, 0xbbbb); /* magic on sequence */
+ wdogwrss(tn, 0x4444); /* magic on sequence */
+
+ if (!beenhere) {
+ beenhere = 1;
+ /* touching the dog is not quick, so do it infrequently */
+ addclock0link(wdogassure, HZ);
+ }
+}
+
+static void
+wdogassure(void) /* reset the watch dog's counter */
+{
+ Timerregs *tn;
+
+ tn = (Timerregs *)PHYSWDOG;
+ wdogoff(tn);
+
+ tn->tcrr = -Dogtimeout;
+ coherence();
+
+ wdogon(tn);
+}
+
+static void
+clockintr(Ureg* ureg, void *arg)
+{
+ Timerregs *tn;
+ static int nesting;
+
+ ticks++;
+ coherence();
+
+ if (nesting == 0) { /* if the clock interrupted itself, bail out */
+ ++nesting;
+ timerintr(ureg, 0);
+ --nesting;
+ }
+
+ tn = arg;
+ tn->tisr = Ovf_it; /* dismiss the interrupt */
+ coherence();
+}
+
+static void
+clockreset(Timerregs *tn)
+{
+ if (probeaddr((uintptr)&tn->ticpcfg) < 0)
+ panic("no clock at %#p", tn);
+ tn->ticpcfg = Softreset | Noidle;
+ coherence();
+ resetwait(tn);
+ tn->tier = tn->tclr = 0;
+ coherence();
+}
+
+/* stop clock interrupts and disable the watchdog timer */
+void
+clockshutdown(void)
+{
+ clockreset((Timerregs *)PHYSWDT2);
+ wdogoff((Timerregs *)PHYSWDT2);
+ clockreset((Timerregs *)PHYSWDT3);
+ wdogoff((Timerregs *)PHYSWDT3);
+
+ clockreset((Timerregs *)Tn0);
+ clockreset((Timerregs *)Tn1);
+}
+
+enum {
+ Instrs = 10*Mhz,
+};
+
+static long
+issue1loop(void)
+{
+ register int i;
+ long st;
+
+ st = rdbaseticks();
+ i = Instrs;
+ do {
+ --i; --i; --i; --i; --i;
+ --i; --i; --i; --i;
+ } while(--i >= 0);
+ return rdbaseticks() - st;
+}
+
+static long
+issue2loop(void)
+{
+ register int i, j;
+ long st;
+
+ st = rdbaseticks();
+ i = Instrs / 2;
+ j = 0;
+ do {
+ --i; --j; --i; --j;
+ --i; --j; --i; --j;
+ --j;
+ } while(--i >= 0);
+ return rdbaseticks() - st;
+}
+
+/* estimate instructions/s. using 32kHz clock */
+static void
+guessmips(long (*loop)(void), char *lab)
+{
+ int s;
+ long tcks;
+
+ do {
+ s = splhi();
+ tcks = loop();
+ splx(s);
+ if (tcks < 0)
+ iprint("again...");
+ } while (tcks < 0);
+ /*
+ * Instrs instructions took tcks ticks @ Clockfreqbase Hz.
+ */
+ s = ((vlong)Clockfreqbase * Instrs) / tcks / 1000000;
+ if (Debug)
+ iprint("%ud mips (%s-issue)", s, lab);
+ USED(s);
+}
+
+void
+clockinit(void)
+{
+ int i, s;
+ Timerregs *tn;
+
+ clockshutdown();
+
+ /* turn cycle counter on */
+ cpwrsc(0, CpCLD, CpCLDena, CpCLDenacyc, 1<<31);
+
+ /* turn all counters on and clear the cycle counter */
+ cpwrsc(0, CpCLD, CpCLDena, CpCLDenapmnc, 1<<2 | 1);
+
+ /* let users read the cycle counter directly */
+ cpwrsc(0, CpCLD, CpCLDena, CpCLDenapmnc, 1);
+
+ ilock(&clklck);
+ m->fastclock = 1;
+ m->ticks = ticks = 0;
+
+ /*
+ * T0 is a freerunning timer (cycle counter); it wraps,
+ * automatically reloads, and does not dispatch interrupts.
+ */
+ tn = (Timerregs *)Tn0;
+ tn->tcrr = Freebase; /* count up to 0 */
+ tn->tldr = Freebase;
+ coherence();
+ tn->tclr = Ar | St;
+ iunlock(&clklck);
+
+ /*
+ * T1 is the interrupting timer and does not participate
+ * in measuring time. It is initially set to HZ.
+ */
+ tn = (Timerregs *)Tn1;
+ irqenable(Tn0irq+1, clockintr, tn, "clock");
+ ilock(&clklck);
+ tn->tcrr = -Tcycles; /* approx.; count up to 0 */
+ tn->tldr = -Tcycles;
+ coherence();
+ tn->tclr = Ar | St;
+ coherence();
+ tn->tier = Ovf_it;
+ coherence();
+ iunlock(&clklck);
+
+ /*
+ * verify sanity of timer1
+ */
+ s = spllo(); /* risky */
+ for (i = 0; i < 5 && ticks == 0; i++) {
+ delay(10);
+ cachedwbinvse(&ticks, sizeof ticks);
+ }
+ splx(s);
+ if (ticks == 0) {
+ if (tn->tcrr == 0)
+ panic("clock not interrupting");
+ else if (tn->tcrr == tn->tldr)
+ panic("clock not ticking at all");
+#ifdef PARANOID
+ else
+ panic("clock running very slowly");
+#endif
+ }
+
+ guessmips(issue1loop, "single");
+ if (Debug)
+ iprint(", ");
+ guessmips(issue2loop, "dual");
+ if (Debug)
+ iprint("\n");
+
+ /*
+ * m->delayloop should be the number of delay loop iterations
+ * needed to consume 1 ms. 2 is min. instructions in the delay loop.
+ */
+ m->delayloop = m->cpuhz / (1000 * 2);
+// iprint("m->delayloop = %lud\n", m->delayloop);
+
+ /*
+ * desynchronize the processor clocks so that they all don't
+ * try to resched at the same time.
+ */
+ delay(m->machno*2);
+}
+
+void
+watchdoginit(void)
+{
+ wdogassure();
+}
+
+ulong
+µs(void)
+{
+ return fastticks2us(fastticks(nil));
+}
+
+void
+timerset(Tval next)
+{
+ long offset;
+ Timerregs *tn = (Timerregs *)Tn1;
+ static Lock setlck;
+
+ ilock(&setlck);
+ offset = next - fastticks(nil);
+ if(offset < MinPeriod)
+ offset = MinPeriod;
+ else if(offset > MaxPeriod)
+ offset = MaxPeriod;
+ tn->tcrr = -offset;
+ coherence();
+ iunlock(&setlck);
+}
+
+static ulong
+rdcycles(void)
+{
+ ulong v;
+
+ /* reads 32-bit cycle counter (counting up) */
+ v = cprdsc(0, CpCLD, CpCLDcyc, 0);
+ /* keep it positive; prevent m->fastclock ever going to 0 */
+ return v == 0? 1: v;
+}
+
+static ulong
+rdbaseticks(void)
+{
+ ulong v;
+
+ v = ((Timerregs *)Tn0)->tcrr; /* tcrr should be counting up */
+ /* keep it positive; prevent m->fastclock ever going to 0 */
+ return v == 0? 1: v;
+}
+
+ulong
+perfticks(void)
+{
+ return rdcycles();
+}
+
+long
+lcycles(void)
+{
+ return perfticks();
+}
+
+/*
+ * until 5[cal] inline vlong ops, avoid them where possible,
+ * they are currently slow function calls.
+ */
+typedef union Counter Counter;
+union Counter {
+ uvlong uvl;
+ struct { /* little-endian */
+ ulong low;
+ ulong high;
+ };
+};
+
+enum {
+ Fastvlongops = 0,
+};
+
+uvlong
+fastticks(uvlong *hz)
+{
+ Counter now, sclnow;
+
+ if(hz)
+ *hz = m->cpuhz;
+ ilock(&clklck);
+ if (m->ticks > HZ/10 && m->fastclock == 0)
+ panic("fastticks: zero m->fastclock; ticks %lud fastclock %#llux",
+ m->ticks, m->fastclock);
+
+ now.uvl = m->fastclock;
+ now.low = rdcycles();
+ if(now.uvl < m->fastclock) /* low bits must have wrapped */
+ now.high++;
+ m->fastclock = now.uvl;
+ coherence();
+
+ sclnow.uvl = now.uvl;
+ iunlock(&clklck);
+ return sclnow.uvl;
+}
+
+void
+microdelay(int l)
+{
+ int i;
+
+ l = l * (vlong)m->delayloop / 1000;
+ if(l <= 0)
+ l = 1;
+ for(i = 0; i < l; i++)
+ ;
+}
+
+void
+delay(int l)
+{
+ ulong i, j;
+
+ j = m->delayloop;
+ while(l-- > 0)
+ for(i=0; i < j; i++)
+ ;
+}
diff --git a/sys/src/9/omap/coproc.c b/sys/src/9/omap/coproc.c
new file mode 100755
index 000000000..411f0fef7
--- /dev/null
+++ b/sys/src/9/omap/coproc.c
@@ -0,0 +1,133 @@
+/*
+ * arm co-processors
+ * CP15 (system control) is the one that gets used the most in practice.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "arm.h"
+
+#define MAP2PCSPACE(va, pc) ((uintptr)(va) & ~KSEGM | (pc) & KSEGM)
+
+enum {
+ /* alternates: 0xe12fff1e BX (R14); last e is R14 */
+ /* 0xe28ef000 B 0(R14); second e is R14 (ken) */
+ Retinst = 0xe1a0f00e, /* MOV R14, R15 */
+};
+
+void
+cpwr(int cp, int op1, int crn, int crm, int op2, ulong val)
+{
+ volatile ulong instr[2];
+ void *pcaddr;
+ void (*fp)(ulong);
+
+ op1 &= 7;
+ op2 &= 7;
+ crn &= 017;
+ crm &= 017;
+ cp &= 017;
+ /* MCR. Rt will be R0. */
+ instr[0] = 0xee000010 |
+ op1 << 21 | crn << 16 | cp << 8 | op2 << 5 | crm;
+ instr[1] = Retinst;
+
+ pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&cp));
+ cachedwbse(pcaddr, sizeof instr);
+ cacheiinv();
+
+ fp = (void (*)(ulong))pcaddr;
+ (*fp)(val);
+ coherence();
+}
+
+void
+cpwrsc(int op1, int crn, int crm, int op2, ulong val)
+{
+ cpwr(CpSC, op1, crn, crm, op2, val);
+}
+
+ulong
+cprd(int cp, int op1, int crn, int crm, int op2)
+{
+ volatile ulong instr[2];
+ void *pcaddr;
+ ulong (*fp)(void);
+
+ op1 &= 7;
+ op2 &= 7;
+ crn &= 017;
+ crm &= 017;
+ /*
+ * MRC. return value will be in R0, which is convenient.
+ * Rt will be R0.
+ */
+ instr[0] = 0xee100010 |
+ op1 << 21 | crn << 16 | cp << 8 | op2 << 5 | crm;
+ instr[1] = Retinst;
+
+ pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&cp));
+ cachedwbse(pcaddr, sizeof instr);
+ cacheiinv();
+
+ fp = (ulong (*)(void))pcaddr;
+ return (*fp)();
+}
+
+ulong
+cprdsc(int op1, int crn, int crm, int op2)
+{
+ return cprd(CpSC, op1, crn, crm, op2);
+}
+
+/* floating point */
+
+ulong
+fprd(int fpreg)
+{
+ volatile ulong instr[2];
+ void *pcaddr;
+ ulong (*fp)(void);
+
+ fpreg &= 017;
+ /*
+ * VMRS. return value will be in R0, which is convenient.
+ * Rt will be R0.
+ */
+ instr[0] = 0xeef00a10 | fpreg << 16 | 0 << 12;
+ instr[1] = Retinst;
+ coherence();
+
+ pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&fpreg));
+ cachedwbse(pcaddr, sizeof instr);
+ cacheiinv();
+
+ fp = (ulong (*)(void))pcaddr;
+ return (*fp)();
+}
+
+void
+fpwr(int fpreg, ulong val)
+{
+ volatile ulong instr[2];
+ void *pcaddr;
+ void (*fp)(ulong);
+
+ fpreg &= 017;
+ /* VMSR. Rt will be R0. */
+ instr[0] = 0xeee00a10 | fpreg << 16 | 0 << 12;
+ instr[1] = Retinst;
+ coherence();
+
+ pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&fpreg));
+ cachedwbse(pcaddr, sizeof instr);
+ cacheiinv();
+
+ fp = (void (*)(ulong))pcaddr;
+ (*fp)(val);
+ coherence();
+}
diff --git a/sys/src/9/omap/dat.h b/sys/src/9/omap/dat.h
new file mode 100755
index 000000000..37114691d
--- /dev/null
+++ b/sys/src/9/omap/dat.h
@@ -0,0 +1,303 @@
+/*
+ * Time.
+ *
+ * HZ should divide 1000 evenly, ideally.
+ * 100, 125, 200, 250 and 333 are okay.
+ */
+#define HZ 100 /* clock frequency */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+
+enum {
+ Mhz = 1000 * 1000,
+};
+
+/*
+ * More accurate time
+ */
+#define MS2TMR(t) ((ulong)(((uvlong)(t) * m->cpuhz)/1000))
+#define US2TMR(t) ((ulong)(((uvlong)(t) * m->cpuhz)/1000000))
+
+/*
+ * we ignore the first 2 uarts on the omap3530 (see uarti8250.c) and use the
+ * third one but call it 0.
+ */
+#define CONSOLE 0
+
+typedef struct Conf Conf;
+typedef struct Confmem Confmem;
+typedef struct FPsave FPsave;
+typedef struct ISAConf ISAConf;
+typedef struct Label Label;
+typedef struct Lock Lock;
+typedef struct Memcache Memcache;
+typedef struct MMMU MMMU;
+typedef struct Mach Mach;
+typedef u32int Mreg; /* Msr - bloody UART */
+typedef struct Notsave Notsave;
+typedef struct Page Page;
+typedef struct PhysUart PhysUart;
+typedef struct PMMU PMMU;
+typedef struct Proc Proc;
+typedef u32int PTE;
+typedef struct Uart Uart;
+typedef struct Ureg Ureg;
+typedef uvlong Tval;
+
+#pragma incomplete Ureg
+
+#define MAXSYSARG 5 /* for mount(fd, mpt, flag, arg, srv) */
+
+/*
+ * parameters for sysproc.c
+ */
+#define AOUT_MAGIC (E_MAGIC)
+
+struct Lock
+{
+ ulong key;
+ u32int sr;
+ uintptr pc;
+ Proc* p;
+ Mach* m;
+ int isilock;
+};
+
+struct Label
+{
+ uintptr sp;
+ uintptr pc;
+};
+
+/*
+ * emulated floating point
+ */
+struct FPsave
+{
+ ulong status;
+ ulong control;
+ ulong regs[8][3];
+
+ int fpstate;
+};
+
+/*
+ * FPsave.status
+ */
+enum
+{
+ FPinit,
+ FPactive,
+ FPinactive,
+};
+
+struct Confmem
+{
+ uintptr base;
+ usize npage;
+ uintptr limit;
+ uintptr kbase;
+ uintptr klimit;
+};
+
+struct Conf
+{
+ ulong nmach; /* processors */
+ ulong nproc; /* processes */
+ Confmem mem[1]; /* physical memory */
+ ulong npage; /* total physical pages of memory */
+ usize upages; /* user page pool */
+ ulong copymode; /* 0 is copy on write, 1 is copy on reference */
+ ulong ialloc; /* max interrupt time allocation in bytes */
+ ulong pipeqsize; /* size in bytes of pipe queues */
+ ulong nimage; /* number of page cache image headers */
+ ulong nswap; /* number of swap pages */
+ int nswppo; /* max # of pageouts per segment pass */
+ ulong hz; /* processor cycle freq */
+ ulong mhz;
+ int monitor; /* flag */
+};
+
+/*
+ * things saved in the Proc structure during a notify
+ */
+struct Notsave {
+ int emptiness;
+};
+
+/*
+ * MMU stuff in Mach.
+ */
+struct MMMU
+{
+ PTE* mmul1; /* l1 for this processor */
+ int mmul1lo;
+ int mmul1hi;
+ int mmupid;
+};
+
+/*
+ * MMU stuff in proc
+ */
+#define NCOLOR 1 /* 1 level cache, don't worry about VCE's */
+struct PMMU
+{
+ Page* mmul2;
+ Page* mmul2cache; /* free mmu pages */
+};
+
+#include "../port/portdat.h"
+
+struct Mach
+{
+ int machno; /* physical id of processor */
+ uintptr splpc; /* pc of last caller to splhi */
+
+ Proc* proc; /* current process */
+
+ MMMU;
+ int flushmmu; /* flush current proc mmu state */
+
+ ulong ticks; /* of the clock since boot time */
+ Label sched; /* scheduler wakeup */
+ Lock alarmlock; /* access to alarm list */
+ void* alarm; /* alarms bound to this clock */
+ int inclockintr;
+
+ Proc* readied; /* for runproc */
+ ulong schedticks; /* next forced context switch */
+
+ int cputype;
+ ulong delayloop;
+
+ /* stats */
+ int tlbfault;
+ int tlbpurge;
+ int pfault;
+ int cs;
+ int syscall;
+ int load;
+ int intr;
+ uvlong fastclock; /* last sampled value */
+ uvlong inidle; /* time spent in idlehands() */
+ ulong spuriousintr;
+ int lastintr;
+ int ilockdepth;
+ Perf perf; /* performance counters */
+
+
+ int cpumhz;
+ uvlong cpuhz; /* speed of cpu */
+ uvlong cyclefreq; /* Frequency of user readable cycle counter */
+
+ /* save areas for exceptions, hold R0-R4 */
+ u32int sfiq[5];
+ u32int sirq[5];
+ u32int sund[5];
+ u32int sabt[5];
+ u32int smon[5]; /* probably not needed */
+ u32int ssys[5];
+
+ int stack[1];
+};
+
+/*
+ * Fake kmap.
+ */
+typedef void KMap;
+#define VA(k) ((uintptr)(k))
+#define kmap(p) (KMap*)((p)->pa|kseg0)
+#define kunmap(k)
+
+struct
+{
+ Lock;
+ int machs; /* bitmap of active CPUs */
+ int exiting; /* shutdown */
+ int ispanic; /* shutdown in response to a panic */
+}active;
+
+extern register Mach* m; /* R10 */
+extern register Proc* up; /* R9 */
+extern uintptr kseg0;
+extern Mach* machaddr[MAXMACH];
+extern ulong memsize;
+extern int normalprint;
+
+/*
+ * a parsed plan9.ini line
+ */
+#define NISAOPT 8
+
+struct ISAConf {
+ char *type;
+ ulong port;
+ int irq;
+ ulong dma;
+ ulong mem;
+ ulong size;
+ ulong freq;
+
+ int nopt;
+ char *opt[NISAOPT];
+};
+
+#define MACHP(n) (machaddr[n])
+
+/*
+ * Horrid. But the alternative is 'defined'.
+ */
+#ifdef _DBGC_
+#define DBGFLG (dbgflg[_DBGC_])
+#else
+#define DBGFLG (0)
+#endif /* _DBGC_ */
+
+int vflag;
+extern char dbgflg[256];
+
+#define dbgprint print /* for now */
+
+/*
+ * hardware info about a device
+ */
+typedef struct {
+ ulong port;
+ int size;
+} Devport;
+
+struct DevConf
+{
+ ulong intnum; /* interrupt number */
+ char *type; /* card type, malloced */
+ int nports; /* Number of ports */
+ Devport *ports; /* The ports themselves */
+};
+
+enum {
+ Dcache,
+ Icache,
+ Unified,
+};
+
+/* characteristics of a given cache level */
+struct Memcache {
+ uint level; /* 1 is nearest processor, 2 further away */
+ uint l1ip; /* l1 I policy */
+
+ uint nways; /* associativity */
+ uint nsets;
+ uint linelen; /* bytes per cache line */
+ uint setsways;
+
+ uint log2linelen;
+ uint waysh; /* shifts for set/way register */
+ uint setsh;
+};
+
+enum Dmamode {
+ Const,
+ Postincr,
+ Index,
+ Index2,
+};
diff --git a/sys/src/9/omap/devarch.c b/sys/src/9/omap/devarch.c
new file mode 100755
index 000000000..06b18d829
--- /dev/null
+++ b/sys/src/9/omap/devarch.c
@@ -0,0 +1,200 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+#include "../ip/ip.h"
+
+enum {
+ Qdir = 0,
+ Qbase,
+
+ Qmax = 16,
+};
+
+typedef long Rdwrfn(Chan*, void*, long, vlong);
+
+static Rdwrfn *readfn[Qmax];
+static Rdwrfn *writefn[Qmax];
+
+static Dirtab archdir[Qmax] = {
+ ".", { Qdir, 0, QTDIR }, 0, 0555,
+};
+
+Lock archwlock; /* the lock is only for changing archdir */
+int narchdir = Qbase;
+
+/*
+ * Add a file to the #P listing. Once added, you can't delete it.
+ * You can't add a file with the same name as one already there,
+ * and you get a pointer to the Dirtab entry so you can do things
+ * like change the Qid version. Changing the Qid path is disallowed.
+ */
+Dirtab*
+addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
+{
+ int i;
+ Dirtab d;
+ Dirtab *dp;
+
+ memset(&d, 0, sizeof d);
+ strcpy(d.name, name);
+ d.perm = perm;
+
+ lock(&archwlock);
+ if(narchdir >= Qmax){
+ unlock(&archwlock);
+ return nil;
+ }
+
+ for(i=0; i<narchdir; i++)
+ if(strcmp(archdir[i].name, name) == 0){
+ unlock(&archwlock);
+ return nil;
+ }
+
+ d.qid.path = narchdir;
+ archdir[narchdir] = d;
+ readfn[narchdir] = rdfn;
+ writefn[narchdir] = wrfn;
+ dp = &archdir[narchdir++];
+ unlock(&archwlock);
+
+ return dp;
+}
+
+static Chan*
+archattach(char* spec)
+{
+ return devattach('P', spec);
+}
+
+Walkqid*
+archwalk(Chan* c, Chan *nc, char** name, int nname)
+{
+ return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
+}
+
+static int
+archstat(Chan* c, uchar* dp, int n)
+{
+ return devstat(c, dp, n, archdir, narchdir, devgen);
+}
+
+static Chan*
+archopen(Chan* c, int omode)
+{
+ return devopen(c, omode, archdir, narchdir, devgen);
+}
+
+static void
+archclose(Chan*)
+{
+}
+
+static long
+archread(Chan *c, void *a, long n, vlong offset)
+{
+ Rdwrfn *fn;
+
+ switch((ulong)c->qid.path){
+ case Qdir:
+ return devdirread(c, a, n, archdir, narchdir, devgen);
+
+ default:
+ if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
+ return fn(c, a, n, offset);
+ error(Eperm);
+ break;
+ }
+
+ return 0;
+}
+
+static long
+archwrite(Chan *c, void *a, long n, vlong offset)
+{
+ Rdwrfn *fn;
+
+ if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
+ return fn(c, a, n, offset);
+ error(Eperm);
+
+ return 0;
+}
+
+void archinit(void);
+
+Dev archdevtab = {
+ 'P',
+ "arch",
+
+ devreset,
+ archinit,
+ devshutdown,
+ archattach,
+ archwalk,
+ archstat,
+ archopen,
+ devcreate,
+ archclose,
+ archread,
+ devbread,
+ archwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+/* convert AddrDevid register to a string in buf and return buf */
+char *
+cputype2name(char *buf, int size)
+{
+ seprint(buf, buf + size, "Cortex-A8");
+ return buf;
+}
+
+static long
+cputyperead(Chan*, void *a, long n, vlong offset)
+{
+ char name[64], str[128];
+
+ cputype2name(name, sizeof name);
+ snprint(str, sizeof str, "ARM %s %llud\n", name, m->cpuhz / Mhz);
+ return readstr(offset, a, n, str);
+}
+
+static long
+tbread(Chan*, void *a, long n, vlong offset)
+{
+ char str[16];
+ uvlong tb;
+
+ cycles(&tb);
+
+ snprint(str, sizeof(str), "%16.16llux", tb);
+ return readstr(offset, a, n, str);
+}
+
+static long
+nsread(Chan*, void *a, long n, vlong offset)
+{
+ char str[16];
+ uvlong tb;
+
+ cycles(&tb);
+
+ snprint(str, sizeof(str), "%16.16llux", (tb/700)* 1000);
+ return readstr(offset, a, n, str);
+}
+
+void
+archinit(void)
+{
+ addarchfile("cputype", 0444, cputyperead, nil);
+ addarchfile("timebase",0444, tbread, nil);
+// addarchfile("nsec", 0444, nsread, nil);
+}
diff --git a/sys/src/9/omap/devcons.c b/sys/src/9/omap/devcons.c
new file mode 100755
index 000000000..f94f12d53
--- /dev/null
+++ b/sys/src/9/omap/devcons.c
@@ -0,0 +1,1354 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "pool.h"
+#include <authsrv.h>
+
+void (*consdebug)(void) = nil;
+void (*screenputs)(char*, int) = nil;
+
+Queue* kbdq; /* unprocessed console input */
+Queue* lineq; /* processed console input */
+Queue* serialoq; /* serial console output */
+Queue* kprintoq; /* console output, for /dev/kprint */
+ulong kprintinuse; /* test and set whether /dev/kprint is open */
+int iprintscreenputs = 1;
+
+int panicking;
+
+static struct
+{
+ QLock;
+
+ int raw; /* true if we shouldn't process input */
+ Ref ctl; /* number of opens to the control file */
+ int x; /* index into line */
+ char line[1024]; /* current input line */
+
+ int count;
+ int ctlpoff;
+
+ /* a place to save up characters at interrupt time before dumping them in the queue */
+ Lock lockputc;
+ char istage[1024];
+ char *iw;
+ char *ir;
+ char *ie;
+} kbd = {
+ .iw = kbd.istage,
+ .ir = kbd.istage,
+ .ie = kbd.istage + sizeof(kbd.istage),
+};
+
+char *sysname;
+vlong fasthz;
+
+static void seedrand(void);
+static int readtime(ulong, char*, int);
+static int readbintime(char*, int);
+static int writetime(char*, int);
+static int writebintime(char*, int);
+
+enum
+{
+ CMhalt,
+ CMreboot,
+ CMpanic,
+};
+
+Cmdtab rebootmsg[] =
+{
+ CMhalt, "halt", 1,
+ CMreboot, "reboot", 0,
+ CMpanic, "panic", 0,
+};
+
+void
+printinit(void)
+{
+ lineq = qopen(2*1024, 0, nil, nil);
+ if(lineq == nil)
+ panic("printinit");
+ qnoblock(lineq, 1);
+}
+
+int
+consactive(void)
+{
+ if(serialoq)
+ return qlen(serialoq) > 0;
+ return 0;
+}
+
+void
+prflush(void)
+{
+ ulong now;
+
+ now = m->ticks;
+ while(consactive())
+ if(m->ticks - now >= HZ)
+ break;
+}
+
+/*
+ * Log console output so it can be retrieved via /dev/kmesg.
+ * This is good for catching boot-time messages after the fact.
+ */
+struct {
+ Lock lk;
+// char buf[16384]; /* normal */
+ char buf[256*1024]; /* for acpi debugging */
+ uint n;
+} kmesg;
+
+static void
+kmesgputs(char *str, int n)
+{
+ uint nn, d;
+
+ ilock(&kmesg.lk);
+ /* take the tail of huge writes */
+ if(n > sizeof kmesg.buf){
+ d = n - sizeof kmesg.buf;
+ str += d;
+ n -= d;
+ }
+
+ /* slide the buffer down to make room */
+ nn = kmesg.n;
+ if(nn + n >= sizeof kmesg.buf){
+ d = nn + n - sizeof kmesg.buf;
+ if(d)
+ memmove(kmesg.buf, kmesg.buf+d, sizeof kmesg.buf-d);
+ nn -= d;
+ }
+
+ /* copy the data in */
+ memmove(kmesg.buf+nn, str, n);
+ nn += n;
+ kmesg.n = nn;
+ iunlock(&kmesg.lk);
+}
+
+/*
+ * Print a string on the console. Convert \n to \r\n for serial
+ * line consoles. Locking of the queues is left up to the screen
+ * or uart code. Multi-line messages to serial consoles may get
+ * interspersed with other messages.
+ */
+static void
+putstrn0(char *str, int n, int usewrite)
+{
+ int m;
+ char *t;
+
+ if(!islo())
+ usewrite = 0;
+
+ /*
+ * how many different output devices do we need?
+ */
+ kmesgputs(str, n);
+
+ /*
+ * if someone is reading /dev/kprint,
+ * put the message there.
+ * if not and there's an attached bit mapped display,
+ * put the message there.
+ *
+ * if there's a serial line being used as a console,
+ * put the message there.
+ */
+ if(kprintoq != nil && !qisclosed(kprintoq)){
+ if(usewrite)
+ qwrite(kprintoq, str, n);
+ else
+ qiwrite(kprintoq, str, n);
+ }else if(screenputs != nil)
+ screenputs(str, n);
+
+ if(serialoq == nil){
+ uartputs(str, n);
+ return;
+ }
+
+ while(n > 0) {
+ t = memchr(str, '\n', n);
+ if(t && !kbd.raw) {
+ m = t-str;
+ if(usewrite){
+ qwrite(serialoq, str, m);
+ qwrite(serialoq, "\r\n", 2);
+ } else {
+ qiwrite(serialoq, str, m);
+ qiwrite(serialoq, "\r\n", 2);
+ }
+ n -= m+1;
+ str = t+1;
+ } else {
+ if(usewrite)
+ qwrite(serialoq, str, n);
+ else
+ qiwrite(serialoq, str, n);
+ break;
+ }
+ }
+}
+
+void
+putstrn(char *str, int n)
+{
+ putstrn0(str, n, 0);
+}
+
+int noprint;
+
+int
+print(char *fmt, ...)
+{
+ int n;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ if(noprint)
+ return -1;
+
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+
+ if(!normalprint) {
+ if(0) iprint("\nprint called too early from %#lux\n",
+ getcallerpc(&fmt));
+ iprint("%.*s", n, buf);
+ } else
+ putstrn(buf, n);
+
+ return n;
+}
+
+/*
+ * Want to interlock iprints to avoid interlaced output on
+ * multiprocessor, but don't want to deadlock if one processor
+ * dies during print and another has something important to say.
+ * Make a good faith effort.
+ */
+static Lock iprintlock;
+static int
+iprintcanlock(Lock *l)
+{
+ int i;
+
+ for(i=0; i<1000; i++){
+ if(canlock(l))
+ return 1;
+ if(l->m == MACHP(m->machno))
+ return 0;
+ microdelay(100);
+ }
+ return 0;
+}
+
+int
+iprint(char *fmt, ...)
+{
+ int n, s, locked;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ s = splhi();
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+ locked = iprintcanlock(&iprintlock);
+ if(screenputs != nil && iprintscreenputs)
+ screenputs(buf, n);
+ if(consuart == nil || consuart->phys == nil ||
+ consuart->phys->putc == nil)
+ _uartputs(buf, n);
+ else
+ uartputs(buf, n);
+ if(locked)
+ unlock(&iprintlock);
+ splx(s);
+
+ return n;
+}
+
+void
+panic(char *fmt, ...)
+{
+ int n, s;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ kprintoq = nil; /* don't try to write to /dev/kprint */
+
+ if(panicking)
+ for(;;);
+ panicking = 1;
+
+ delay(20);
+ s = splhi();
+ strcpy(buf, "panic: ");
+ va_start(arg, fmt);
+ n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+ iprint("%s\n", buf);
+ if(consdebug)
+ (*consdebug)();
+ splx(s);
+ prflush();
+ buf[n] = '\n';
+// putstrn(buf, n+1);
+// dumpstack();
+
+ exit(1);
+}
+
+/* libmp at least contains a few calls to sysfatal; simulate with panic */
+void
+sysfatal(char *fmt, ...)
+{
+ char err[256];
+ va_list arg;
+
+ va_start(arg, fmt);
+ vseprint(err, err + sizeof err, fmt, arg);
+ va_end(arg);
+ panic("sysfatal: %s", err);
+}
+
+void
+_assert(char *fmt)
+{
+ panic("assert failed at %#p: %s", getcallerpc(&fmt), fmt);
+}
+
+int
+pprint(char *fmt, ...)
+{
+ int n;
+ Chan *c;
+ va_list arg;
+ char buf[2*PRINTSIZE];
+
+ if(up == nil || up->fgrp == nil)
+ return 0;
+
+ c = up->fgrp->fd[2];
+ if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR))
+ return 0;
+ n = snprint(buf, sizeof buf, "%s %lud: ", up->text, up->pid);
+ va_start(arg, fmt);
+ n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+
+ if(waserror())
+ return 0;
+ devtab[c->type]->write(c, buf, n, c->offset);
+ poperror();
+
+ lock(c);
+ c->offset += n;
+ unlock(c);
+
+ return n;
+}
+
+static void
+echoscreen(char *buf, int n)
+{
+ char *e, *p;
+ char ebuf[128];
+ int x;
+
+ p = ebuf;
+ e = ebuf + sizeof(ebuf) - 4;
+ while(n-- > 0){
+ if(p >= e){
+ screenputs(ebuf, p - ebuf);
+ p = ebuf;
+ }
+ x = *buf++;
+ if(x == 0x15){
+ *p++ = '^';
+ *p++ = 'U';
+ *p++ = '\n';
+ } else
+ *p++ = x;
+ }
+ if(p != ebuf)
+ screenputs(ebuf, p - ebuf);
+}
+
+static void
+echoserialoq(char *buf, int n)
+{
+ int x;
+ char *e, *p;
+ char ebuf[128];
+
+ p = ebuf;
+ e = ebuf + sizeof(ebuf) - 4;
+ while(n-- > 0){
+ if(p >= e){
+ qiwrite(serialoq, ebuf, p - ebuf);
+ p = ebuf;
+ }
+ x = *buf++;
+ if(x == '\n'){
+ *p++ = '\r';
+ *p++ = '\n';
+ } else if(x == 0x15){
+ *p++ = '^';
+ *p++ = 'U';
+ *p++ = '\n';
+ } else
+ *p++ = x;
+ }
+ if(p != ebuf)
+ qiwrite(serialoq, ebuf, p - ebuf);
+}
+
+static void
+echo(char *buf, int n)
+{
+ static int ctrlt, pid;
+ int x;
+ char *e, *p;
+
+ if(n == 0)
+ return;
+
+ e = buf+n;
+ for(p = buf; p < e; p++){
+ switch(*p){
+ case 0x10: /* ^P */
+ if(cpuserver && !kbd.ctlpoff){
+ active.exiting = 1;
+ return;
+ }
+ break;
+ case 0x14: /* ^T */
+ ctrlt++;
+ if(ctrlt > 2)
+ ctrlt = 2;
+ continue;
+ }
+
+ if(ctrlt != 2)
+ continue;
+
+ /* ^T escapes */
+ ctrlt = 0;
+ switch(*p){
+ case 'S':
+ x = splhi();
+ dumpstack();
+ procdump();
+ splx(x);
+ return;
+ case 's':
+ dumpstack();
+ return;
+ case 'x':
+ xsummary();
+ ixsummary();
+ mallocsummary();
+ // memorysummary();
+ pagersummary();
+ return;
+ case 'd':
+ if(consdebug == nil)
+ consdebug = rdb;
+ else
+ consdebug = nil;
+ print("consdebug now %#p\n", consdebug);
+ return;
+ case 'D':
+ if(consdebug == nil)
+ consdebug = rdb;
+ consdebug();
+ return;
+ case 'p':
+ x = spllo();
+ procdump();
+ splx(x);
+ return;
+ case 'q':
+ scheddump();
+ return;
+ case 'k':
+ killbig("^t ^t k");
+ return;
+ case 'r':
+ exit(0);
+ return;
+ }
+ }
+
+ qproduce(kbdq, buf, n);
+ if(kbd.raw)
+ return;
+ kmesgputs(buf, n);
+ if(screenputs != nil)
+ echoscreen(buf, n);
+ if(serialoq)
+ echoserialoq(buf, n);
+}
+
+/*
+ * Called by a uart interrupt for console input.
+ *
+ * turn '\r' into '\n' before putting it into the queue.
+ */
+int
+kbdcr2nl(Queue*, int ch)
+{
+ char *next;
+
+ ilock(&kbd.lockputc); /* just a mutex */
+ if(ch == '\r' && !kbd.raw)
+ ch = '\n';
+ next = kbd.iw+1;
+ if(next >= kbd.ie)
+ next = kbd.istage;
+ if(next != kbd.ir){
+ *kbd.iw = ch;
+ kbd.iw = next;
+ }
+ iunlock(&kbd.lockputc);
+ return 0;
+}
+
+/*
+ * Put character, possibly a rune, into read queue at interrupt time.
+ * Called at interrupt time to process a character.
+ */
+int
+kbdputc(Queue*, int ch)
+{
+ int i, n;
+ char buf[3];
+ Rune r;
+ char *next;
+
+ if(kbd.ir == nil)
+ return 0; /* in case we're not inited yet */
+
+ ilock(&kbd.lockputc); /* just a mutex */
+ r = ch;
+ n = runetochar(buf, &r);
+ for(i = 0; i < n; i++){
+ next = kbd.iw+1;
+ if(next >= kbd.ie)
+ next = kbd.istage;
+ if(next == kbd.ir)
+ break;
+ *kbd.iw = buf[i];
+ kbd.iw = next;
+ }
+ iunlock(&kbd.lockputc);
+ return 0;
+}
+
+/*
+ * we save up input characters till clock time to reduce
+ * per character interrupt overhead.
+ */
+static void
+kbdputcclock(void)
+{
+ char *iw;
+
+ /* this amortizes cost of qproduce */
+ if(kbd.iw != kbd.ir){
+ iw = kbd.iw;
+ if(iw < kbd.ir){
+ echo(kbd.ir, kbd.ie-kbd.ir);
+ kbd.ir = kbd.istage;
+ }
+ if(kbd.ir != iw){
+ echo(kbd.ir, iw-kbd.ir);
+ kbd.ir = iw;
+ }
+ }
+}
+
+enum{
+ Qdir,
+ Qbintime,
+ Qcons,
+ Qconsctl,
+ Qcputime,
+ Qdrivers,
+ Qkmesg,
+ Qkprint,
+ Qhostdomain,
+ Qhostowner,
+ Qnull,
+ Qosversion,
+ Qpgrpid,
+ Qpid,
+ Qppid,
+ Qrandom,
+ Qreboot,
+ Qswap,
+ Qsysname,
+ Qsysstat,
+ Qtime,
+ Quser,
+ Qzero,
+};
+
+enum
+{
+ VLNUMSIZE= 22,
+};
+
+static Dirtab consdir[]={
+ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
+ "bintime", {Qbintime}, 24, 0664,
+ "cons", {Qcons}, 0, 0660,
+ "consctl", {Qconsctl}, 0, 0220,
+ "cputime", {Qcputime}, 6*NUMSIZE, 0444,
+ "drivers", {Qdrivers}, 0, 0444,
+ "hostdomain", {Qhostdomain}, DOMLEN, 0664,
+ "hostowner", {Qhostowner}, 0, 0664,
+ "kmesg", {Qkmesg}, 0, 0440,
+ "kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL|0440,
+ "null", {Qnull}, 0, 0666,
+ "osversion", {Qosversion}, 0, 0444,
+ "pgrpid", {Qpgrpid}, NUMSIZE, 0444,
+ "pid", {Qpid}, NUMSIZE, 0444,
+ "ppid", {Qppid}, NUMSIZE, 0444,
+ "random", {Qrandom}, 0, 0444,
+ "reboot", {Qreboot}, 0, 0664,
+ "swap", {Qswap}, 0, 0664,
+ "sysname", {Qsysname}, 0, 0664,
+ "sysstat", {Qsysstat}, 0, 0666,
+ "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664,
+ "user", {Quser}, 0, 0666,
+ "zero", {Qzero}, 0, 0444,
+};
+
+int
+readnum(ulong off, char *buf, ulong n, ulong val, int size)
+{
+ char tmp[64];
+
+ snprint(tmp, sizeof(tmp), "%*lud", size-1, val);
+ tmp[size-1] = ' ';
+ if(off >= size)
+ return 0;
+ if(off+n > size)
+ n = size-off;
+ memmove(buf, tmp+off, n);
+ return n;
+}
+
+int
+readstr(ulong off, char *buf, ulong n, char *str)
+{
+ int size;
+
+ size = strlen(str);
+ if(off >= size)
+ return 0;
+ if(off+n > size)
+ n = size-off;
+ memmove(buf, str+off, n);
+ return n;
+}
+
+static void
+consinit(void)
+{
+ todinit();
+ randominit();
+ /*
+ * at 115200 baud, the 1024 char buffer takes 56 ms to process,
+ * processing it every 22 ms should be fine
+ */
+ addclock0link(kbdputcclock, 22);
+}
+
+static Chan*
+consattach(char *spec)
+{
+ return devattach('c', spec);
+}
+
+static Walkqid*
+conswalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);
+}
+
+static int
+consstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, consdir, nelem(consdir), devgen);
+}
+
+static Chan*
+consopen(Chan *c, int omode)
+{
+ c->aux = nil;
+ c = devopen(c, omode, consdir, nelem(consdir), devgen);
+ switch((ulong)c->qid.path){
+ case Qconsctl:
+ incref(&kbd.ctl);
+ break;
+
+ case Qkprint:
+ if(tas(&kprintinuse) != 0){
+ c->flag &= ~COPEN;
+ error(Einuse);
+ }
+ if(kprintoq == nil){
+ kprintoq = qopen(8*1024, Qcoalesce, 0, 0);
+ if(kprintoq == nil){
+ c->flag &= ~COPEN;
+ error(Enomem);
+ }
+ qnoblock(kprintoq, 1);
+ }else
+ qreopen(kprintoq);
+ c->iounit = qiomaxatomic;
+ break;
+ }
+ return c;
+}
+
+static void
+consclose(Chan *c)
+{
+ switch((ulong)c->qid.path){
+ /* last close of control file turns off raw */
+ case Qconsctl:
+ if(c->flag&COPEN){
+ if(decref(&kbd.ctl) == 0)
+ kbd.raw = 0;
+ }
+ break;
+
+ /* close of kprint allows other opens */
+ case Qkprint:
+ if(c->flag & COPEN){
+ kprintinuse = 0;
+ qhangup(kprintoq, nil);
+ }
+ break;
+ }
+}
+
+static long
+consread(Chan *c, void *buf, long n, vlong off)
+{
+ ulong l;
+ Mach *mp;
+ char *b, *bp, ch;
+ char tmp[256]; /* must be >= 18*NUMSIZE (Qswap) */
+ int i, k, id, send;
+ vlong offset = off;
+
+ if(n <= 0)
+ return n;
+
+ switch((ulong)c->qid.path){
+ case Qdir:
+ return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
+
+ case Qcons:
+ qlock(&kbd);
+ if(waserror()) {
+ qunlock(&kbd);
+ nexterror();
+ }
+ while(!qcanread(lineq)){
+ if(qread(kbdq, &ch, 1) == 0)
+ continue;
+ send = 0;
+ if(ch == 0){
+ /* flush output on rawoff -> rawon */
+ if(kbd.x > 0)
+ send = !qcanread(kbdq);
+ }else if(kbd.raw){
+ kbd.line[kbd.x++] = ch;
+ send = !qcanread(kbdq);
+ }else{
+ switch(ch){
+ case '\b':
+ if(kbd.x > 0)
+ kbd.x--;
+ break;
+ case 0x15: /* ^U */
+ kbd.x = 0;
+ break;
+ case '\n':
+ case 0x04: /* ^D */
+ send = 1;
+ default:
+ if(ch != 0x04)
+ kbd.line[kbd.x++] = ch;
+ break;
+ }
+ }
+ if(send || kbd.x == sizeof kbd.line){
+ qwrite(lineq, kbd.line, kbd.x);
+ kbd.x = 0;
+ }
+ }
+ n = qread(lineq, buf, n);
+ qunlock(&kbd);
+ poperror();
+ return n;
+
+ case Qcputime:
+ k = offset;
+ if(k >= 6*NUMSIZE)
+ return 0;
+ if(k+n > 6*NUMSIZE)
+ n = 6*NUMSIZE - k;
+ /* easiest to format in a separate buffer and copy out */
+ for(i=0; i<6 && NUMSIZE*i<k+n; i++){
+ l = up->time[i];
+ if(i == TReal)
+ l = MACHP(0)->ticks - l;
+ l = TK2MS(l);
+ readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
+ }
+ memmove(buf, tmp+k, n);
+ return n;
+
+ case Qkmesg:
+ /*
+ * This is unlocked to avoid tying up a process
+ * that's writing to the buffer. kmesg.n never
+ * gets smaller, so worst case the reader will
+ * see a slurred buffer.
+ */
+ if(off >= kmesg.n)
+ n = 0;
+ else{
+ if(off+n > kmesg.n)
+ n = kmesg.n - off;
+ memmove(buf, kmesg.buf+off, n);
+ }
+ return n;
+
+ case Qkprint:
+ return qread(kprintoq, buf, n);
+
+ case Qpgrpid:
+ return readnum((ulong)offset, buf, n, up->pgrp->pgrpid, NUMSIZE);
+
+ case Qpid:
+ return readnum((ulong)offset, buf, n, up->pid, NUMSIZE);
+
+ case Qppid:
+ return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE);
+
+ case Qtime:
+ return readtime((ulong)offset, buf, n);
+
+ case Qbintime:
+ return readbintime(buf, n);
+
+ case Qhostowner:
+ return readstr((ulong)offset, buf, n, eve);
+
+ case Qhostdomain:
+ return readstr((ulong)offset, buf, n, hostdomain);
+
+ case Quser:
+ return readstr((ulong)offset, buf, n, up->user);
+
+ case Qnull:
+ return 0;
+
+ case Qsysstat:
+ b = smalloc(conf.nmach*(NUMSIZE*11+1) + 1); /* +1 for NUL */
+ bp = b;
+ for(id = 0; id < 32; id++) {
+ if(active.machs & (1<<id)) {
+ mp = MACHP(id);
+ readnum(0, bp, NUMSIZE, id, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->load, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE,
+ (mp->perf.avg_inidle*100)/mp->perf.period,
+ NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE,
+ (mp->perf.avg_inintr*100)/mp->perf.period,
+ NUMSIZE);
+ bp += NUMSIZE;
+ *bp++ = '\n';
+ }
+ }
+ if(waserror()){
+ free(b);
+ nexterror();
+ }
+ n = readstr((ulong)offset, buf, n, b);
+ free(b);
+ poperror();
+ return n;
+
+ case Qswap:
+ snprint(tmp, sizeof tmp,
+ "%lud memory\n"
+ "%d pagesize\n"
+ "%lud kernel\n"
+ "%lud/%lud user\n"
+ "%lud/%lud swap\n"
+ "%lud/%lud kernel malloc\n"
+ "%lud/%lud kernel draw\n",
+ conf.npage*BY2PG,
+ BY2PG,
+ conf.npage-conf.upages,
+ palloc.user-palloc.freecount, palloc.user,
+ conf.nswap-swapalloc.free, conf.nswap,
+ mainmem->cursize, mainmem->maxsize,
+ imagmem->cursize, imagmem->maxsize);
+
+ return readstr((ulong)offset, buf, n, tmp);
+
+ case Qsysname:
+ if(sysname == nil)
+ return 0;
+ return readstr((ulong)offset, buf, n, sysname);
+
+ case Qrandom:
+ return randomread(buf, n);
+
+ case Qdrivers:
+ b = malloc(READSTR);
+ if(b == nil)
+ error(Enomem);
+ k = 0;
+ for(i = 0; devtab[i] != nil; i++)
+ k += snprint(b+k, READSTR-k, "#%C %s\n",
+ devtab[i]->dc, devtab[i]->name);
+ if(waserror()){
+ free(b);
+ nexterror();
+ }
+ n = readstr((ulong)offset, buf, n, b);
+ free(b);
+ poperror();
+ return n;
+
+ case Qzero:
+ memset(buf, 0, n);
+ return n;
+
+ case Qosversion:
+ snprint(tmp, sizeof tmp, "2000");
+ n = readstr((ulong)offset, buf, n, tmp);
+ return n;
+
+ default:
+ print("consread %#llux\n", c->qid.path);
+ error(Egreg);
+ }
+ return -1; /* never reached */
+}
+
+static long
+conswrite(Chan *c, void *va, long n, vlong off)
+{
+ char buf[256], ch;
+ long l, bp;
+ char *a;
+ Mach *mp;
+ int id, fd;
+ Chan *swc;
+ ulong offset;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+
+ a = va;
+ offset = off;
+
+ switch((ulong)c->qid.path){
+ case Qcons:
+ /*
+ * Can't page fault in putstrn, so copy the data locally.
+ */
+ l = n;
+ while(l > 0){
+ bp = l;
+ if(bp > sizeof buf)
+ bp = sizeof buf;
+ memmove(buf, a, bp);
+ putstrn0(buf, bp, 1);
+ a += bp;
+ l -= bp;
+ }
+ break;
+
+ case Qconsctl:
+ if(n >= sizeof(buf))
+ n = sizeof(buf)-1;
+ strncpy(buf, a, n);
+ buf[n] = 0;
+ for(a = buf; a;){
+ if(strncmp(a, "rawon", 5) == 0){
+ kbd.raw = 1;
+ /* clumsy hack - wake up reader */
+ ch = 0;
+ qwrite(kbdq, &ch, 1);
+ } else if(strncmp(a, "rawoff", 6) == 0){
+ kbd.raw = 0;
+ } else if(strncmp(a, "ctlpon", 6) == 0){
+ kbd.ctlpoff = 0;
+ } else if(strncmp(a, "ctlpoff", 7) == 0){
+ kbd.ctlpoff = 1;
+ }
+ if(a = strchr(a, ' '))
+ a++;
+ }
+ break;
+
+ case Qtime:
+ if(!iseve())
+ error(Eperm);
+ return writetime(a, n);
+
+ case Qbintime:
+ if(!iseve())
+ error(Eperm);
+ return writebintime(a, n);
+
+ case Qhostowner:
+ return hostownerwrite(a, n);
+
+ case Qhostdomain:
+ return hostdomainwrite(a, n);
+
+ case Quser:
+ return userwrite(a, n);
+
+ case Qnull:
+ break;
+
+ case Qreboot:
+ if(!iseve())
+ error(Eperm);
+ cb = parsecmd(a, n);
+
+ if(waserror()) {
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
+ switch(ct->index) {
+ case CMhalt:
+ reboot(nil, 0, 0);
+ break;
+ case CMreboot:
+ rebootcmd(cb->nf-1, cb->f+1);
+ break;
+ case CMpanic:
+ *(ulong*)0=0;
+ panic("/dev/reboot");
+ }
+ poperror();
+ free(cb);
+ break;
+
+ case Qsysstat:
+ for(id = 0; id < 32; id++) {
+ if(active.machs & (1<<id)) {
+ mp = MACHP(id);
+ mp->cs = 0;
+ mp->intr = 0;
+ mp->syscall = 0;
+ mp->pfault = 0;
+ mp->tlbfault = 0;
+ mp->tlbpurge = 0;
+ }
+ }
+ break;
+
+ case Qswap:
+ if(n >= sizeof buf)
+ error(Egreg);
+ memmove(buf, va, n); /* so we can NUL-terminate */
+ buf[n] = 0;
+ /* start a pager if not already started */
+ if(strncmp(buf, "start", 5) == 0){
+ kickpager();
+ break;
+ }
+ if(!iseve())
+ error(Eperm);
+ if(buf[0]<'0' || '9'<buf[0])
+ error(Ebadarg);
+ fd = strtoul(buf, 0, 0);
+ swc = fdtochan(fd, -1, 1, 1);
+ setswapchan(swc);
+ break;
+
+ case Qsysname:
+ if(offset != 0)
+ error(Ebadarg);
+ if(n <= 0 || n >= sizeof buf)
+ error(Ebadarg);
+ strncpy(buf, a, n);
+ buf[n] = 0;
+ if(buf[n-1] == '\n')
+ buf[n-1] = 0;
+ kstrdup(&sysname, buf);
+ break;
+
+ default:
+ print("conswrite: %#llux\n", c->qid.path);
+ error(Egreg);
+ }
+ return n;
+}
+
+Dev consdevtab = {
+ 'c',
+ "cons",
+
+ devreset,
+ consinit,
+ devshutdown,
+ consattach,
+ conswalk,
+ consstat,
+ consopen,
+ devcreate,
+ consclose,
+ consread,
+ devbread,
+ conswrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+static ulong randn;
+
+static void
+seedrand(void)
+{
+ if(!waserror()){
+ randomread((void*)&randn, sizeof(randn));
+ poperror();
+ }
+}
+
+int
+nrand(int n)
+{
+ if(randn == 0)
+ seedrand();
+ randn = randn*1103515245 + 12345 + MACHP(0)->ticks;
+ return (randn>>16) % n;
+}
+
+int
+rand(void)
+{
+ nrand(1);
+ return randn;
+}
+
+static uvlong uvorder = 0x0001020304050607ULL;
+
+static uchar*
+le2vlong(vlong *to, uchar *f)
+{
+ uchar *t, *o;
+ int i;
+
+ t = (uchar*)to;
+ o = (uchar*)&uvorder;
+ for(i = 0; i < sizeof(vlong); i++)
+ t[o[i]] = f[i];
+ return f+sizeof(vlong);
+}
+
+static uchar*
+vlong2le(uchar *t, vlong from)
+{
+ uchar *f, *o;
+ int i;
+
+ f = (uchar*)&from;
+ o = (uchar*)&uvorder;
+ for(i = 0; i < sizeof(vlong); i++)
+ t[i] = f[o[i]];
+ return t+sizeof(vlong);
+}
+
+static long order = 0x00010203;
+
+static uchar*
+le2long(long *to, uchar *f)
+{
+ uchar *t, *o;
+ int i;
+
+ t = (uchar*)to;
+ o = (uchar*)&order;
+ for(i = 0; i < sizeof(long); i++)
+ t[o[i]] = f[i];
+ return f+sizeof(long);
+}
+
+static uchar*
+long2le(uchar *t, long from)
+{
+ uchar *f, *o;
+ int i;
+
+ f = (uchar*)&from;
+ o = (uchar*)&order;
+ for(i = 0; i < sizeof(long); i++)
+ t[i] = f[o[i]];
+ return t+sizeof(long);
+}
+
+char *Ebadtimectl = "bad time control";
+
+/*
+ * like the old #c/time but with added info. Return
+ *
+ * secs nanosecs fastticks fasthz
+ */
+static int
+readtime(ulong off, char *buf, int n)
+{
+ vlong nsec, ticks;
+ long sec;
+ char str[7*NUMSIZE];
+
+ nsec = todget(&ticks);
+ if(fasthz == 0LL)
+ fastticks((uvlong*)&fasthz);
+ sec = nsec/1000000000ULL;
+ snprint(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
+ NUMSIZE-1, sec,
+ VLNUMSIZE-1, nsec,
+ VLNUMSIZE-1, ticks,
+ VLNUMSIZE-1, fasthz);
+ return readstr(off, buf, n, str);
+}
+
+/*
+ * set the time in seconds
+ */
+static int
+writetime(char *buf, int n)
+{
+ char b[13];
+ long i;
+ vlong now;
+
+ if(n >= sizeof(b))
+ error(Ebadtimectl);
+ strncpy(b, buf, n);
+ b[n] = 0;
+ i = strtol(b, 0, 0);
+ if(i <= 0)
+ error(Ebadtimectl);
+ now = i*1000000000LL;
+ todset(now, 0, 0);
+ return n;
+}
+
+/*
+ * read binary time info. all numbers are little endian.
+ * ticks and nsec are syncronized.
+ */
+static int
+readbintime(char *buf, int n)
+{
+ int i;
+ vlong nsec, ticks;
+ uchar *b = (uchar*)buf;
+
+ i = 0;
+ if(fasthz == 0LL)
+ fastticks((uvlong*)&fasthz);
+ nsec = todget(&ticks);
+ if(n >= 3*sizeof(uvlong)){
+ vlong2le(b+2*sizeof(uvlong), fasthz);
+ i += sizeof(uvlong);
+ }
+ if(n >= 2*sizeof(uvlong)){
+ vlong2le(b+sizeof(uvlong), ticks);
+ i += sizeof(uvlong);
+ }
+ if(n >= 8){
+ vlong2le(b, nsec);
+ i += sizeof(vlong);
+ }
+ return i;
+}
+
+/*
+ * set any of the following
+ * - time in nsec
+ * - nsec trim applied over some seconds
+ * - clock frequency
+ */
+static int
+writebintime(char *buf, int n)
+{
+ uchar *p;
+ vlong delta;
+ long period;
+
+ n--;
+ p = (uchar*)buf + 1;
+ switch(*buf){
+ case 'n':
+ if(n < sizeof(vlong))
+ error(Ebadtimectl);
+ le2vlong(&delta, p);
+ todset(delta, 0, 0);
+ break;
+ case 'd':
+ if(n < sizeof(vlong)+sizeof(long))
+ error(Ebadtimectl);
+ p = le2vlong(&delta, p);
+ le2long(&period, p);
+ todset(-1, delta, period);
+ break;
+ case 'f':
+ if(n < sizeof(uvlong))
+ error(Ebadtimectl);
+ le2vlong(&fasthz, p);
+ if(fasthz <= 0)
+ error(Ebadtimectl);
+ todsetfreq(fasthz);
+ break;
+ }
+ return n;
+}
diff --git a/sys/src/9/omap/devdss.c b/sys/src/9/omap/devdss.c
new file mode 100755
index 000000000..17ad06abd
--- /dev/null
+++ b/sys/src/9/omap/devdss.c
@@ -0,0 +1,180 @@
+/*
+ * omap35 display subsystem (dss) device interface to screen.c.
+ * implements #v/vgactl
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+// #include "gamma.h"
+
+enum {
+ Qdir,
+ Qdss,
+};
+
+extern OScreen oscreen;
+extern Settings settings[];
+extern Omap3fb *framebuf;
+
+static QLock dsslck;
+static Dirtab dsstab[] = {
+ ".", {Qdir, 0, QTDIR}, 0, 0555|DMDIR,
+ "vgactl", {Qdss, 0}, 0, 0666,
+};
+
+static Chan*
+screenattach(char *spec)
+{
+ return devattach('v', spec);
+}
+
+static Walkqid*
+screenwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, dsstab, nelem(dsstab), devgen);
+}
+
+static int
+screenstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, dsstab, nelem(dsstab), devgen);
+}
+
+static Chan*
+screenopen(Chan *c, int omode)
+{
+ if ((ulong)c->qid.path == Qdss) {
+ qlock(&dsslck);
+ oscreen.open = 1;
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ }
+ return c;
+}
+
+static void
+screenclose(Chan *c)
+{
+ if ((c->qid.type & QTDIR) == 0 && c->flag & COPEN)
+ if (c->qid.path == Qdss) {
+ oscreen.open = 0;
+ qunlock(&dsslck);
+ }
+}
+
+static ulong
+getchans(char *p)
+{
+ if (strncmp("x24" , p, 3) == 0)
+ return RGB24; /* can't work yet, pixels are shorts */
+ else if (strncmp("x16", p, 3) == 0)
+ return RGB16;
+ else
+ return RGB16;
+}
+
+static long
+settingswrite(OScreen *scr, char *p)
+{
+ if (strncmp("800x600", p, 7) == 0) {
+ p += 7;
+ scr->settings = &settings[Res800x600];
+ } else if (strncmp("1024x768", p, 8) == 0) {
+ p += 8;
+ scr->settings = &settings[Res1024x768];
+ } else if (strncmp("1280x1024", p, 9) == 0) {
+ p += 9;
+ scr->settings = &settings[Res1280x1024];
+ } else
+ return -1;
+ scr->settings->chan = getchans(p);
+ return 1;
+}
+
+static long
+screenread(Chan *c, void *a, long n, vlong off)
+{
+ int len, depth;
+ char *p;
+ Settings *set;
+
+ switch ((ulong)c->qid.path) {
+ case Qdir:
+ return devdirread(c, a, n, dsstab, nelem(dsstab), devgen);
+ case Qdss:
+ set = oscreen.settings;
+ p = malloc(READSTR);
+ if(waserror()){
+ free(p);
+ nexterror();
+ }
+ if (set->chan == RGB16)
+ depth = 16;
+ else if (set->chan == RGB24)
+ depth = 24;
+ else
+ depth = 0;
+ len = snprint(p, READSTR, "size %dx%dx%d @ %d Hz\n"
+ "addr %#p size %ud\n", set->wid, set->ht, depth,
+ set->freq, framebuf, sizeof *framebuf);
+ USED(len);
+ n = readstr(off, a, n, p);
+ poperror();
+ free(p);
+ return n;
+ default:
+ error(Egreg);
+ }
+ return 0;
+}
+
+static long
+screenwrite(Chan *c, void *a, long n, vlong off)
+{
+ switch ((ulong)c->qid.path) {
+ case Qdss:
+ if(off)
+ error(Ebadarg);
+ n = settingswrite(&oscreen, a);
+ if (n < 0)
+ error(Ebadctl);
+ screeninit();
+ return n;
+ default:
+ error(Egreg);
+ }
+ return 0;
+}
+
+Dev dssdevtab = {
+ L'v',
+ "dss",
+
+ devreset,
+ devinit,
+ devshutdown, // TODO add a shutdown to stop dma to monitor
+ screenattach,
+ screenwalk,
+ screenstat,
+ screenopen,
+ devcreate,
+ screenclose,
+ screenread,
+ devbread,
+ screenwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/omap/devether.c b/sys/src/9/omap/devether.c
new file mode 100755
index 000000000..f6c32b9f0
--- /dev/null
+++ b/sys/src/9/omap/devether.c
@@ -0,0 +1,530 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#include "../port/netif.h"
+#include "etherif.h"
+
+extern int archether(unsigned ctlno, Ether *ether);
+
+static Ether *etherxx[MaxEther];
+
+Chan*
+etherattach(char* spec)
+{
+ int ctlrno;
+ char *p;
+ Chan *chan;
+
+ ctlrno = 0;
+ if(spec && *spec){
+ ctlrno = strtoul(spec, &p, 0);
+ if((ctlrno == 0 && p == spec) || *p != 0)
+ error(Ebadarg);
+ if(ctlrno < 0 || ctlrno >= MaxEther)
+ error(Ebadarg);
+ }
+ if(etherxx[ctlrno] == 0)
+ error(Enodev);
+
+ chan = devattach('l', spec);
+ if(waserror()){
+ chanfree(chan);
+ nexterror();
+ }
+ chan->dev = ctlrno;
+ if(etherxx[ctlrno]->attach)
+ etherxx[ctlrno]->attach(etherxx[ctlrno]);
+ poperror();
+ return chan;
+}
+
+static Walkqid*
+etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
+{
+ return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
+}
+
+static int
+etherstat(Chan* chan, uchar* dp, int n)
+{
+ return netifstat(etherxx[chan->dev], chan, dp, n);
+}
+
+static Chan*
+etheropen(Chan* chan, int omode)
+{
+ return netifopen(etherxx[chan->dev], chan, omode);
+}
+
+static void
+ethercreate(Chan*, char*, int, ulong)
+{
+}
+
+static void
+etherclose(Chan* chan)
+{
+ netifclose(etherxx[chan->dev], chan);
+}
+
+static long
+etherread(Chan* chan, void* buf, long n, vlong off)
+{
+ Ether *ether;
+ ulong offset = off;
+
+ ether = etherxx[chan->dev];
+ if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
+ /*
+ * With some controllers it is necessary to reach
+ * into the chip to extract statistics.
+ */
+ if(NETTYPE(chan->qid.path) == Nifstatqid)
+ return ether->ifstat(ether, buf, n, offset);
+ else if(NETTYPE(chan->qid.path) == Nstatqid)
+ ether->ifstat(ether, buf, 0, offset);
+ }
+
+ return netifread(ether, chan, buf, n, offset);
+}
+
+static Block*
+etherbread(Chan* chan, long n, ulong offset)
+{
+ return netifbread(etherxx[chan->dev], chan, n, offset);
+}
+
+static int
+etherwstat(Chan* chan, uchar* dp, int n)
+{
+ return netifwstat(etherxx[chan->dev], chan, dp, n);
+}
+
+static void
+etherrtrace(Netfile* f, Etherpkt* pkt, int len)
+{
+ int i, n;
+ Block *bp;
+
+ if(qwindow(f->in) <= 0)
+ return;
+ if(len > 58)
+ n = 58;
+ else
+ n = len;
+ bp = iallocb(64);
+ if(bp == nil)
+ return;
+ memmove(bp->wp, pkt->d, n);
+ i = TK2MS(MACHP(0)->ticks);
+ bp->wp[58] = len>>8;
+ bp->wp[59] = len;
+ bp->wp[60] = i>>24;
+ bp->wp[61] = i>>16;
+ bp->wp[62] = i>>8;
+ bp->wp[63] = i;
+ bp->wp += 64;
+ qpass(f->in, bp);
+}
+
+Block*
+etheriq(Ether* ether, Block* bp, int fromwire)
+{
+ Etherpkt *pkt;
+ ushort type;
+ int len, multi, tome, fromme;
+ Netfile **ep, *f, **fp, *fx;
+ Block *xbp;
+
+ ether->inpackets++;
+
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ type = (pkt->type[0]<<8)|pkt->type[1];
+ fx = 0;
+ ep = &ether->f[Ntypes];
+
+ multi = pkt->d[0] & 1;
+ /* check for valid multicast addresses */
+ if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 &&
+ ether->prom == 0){
+ if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
+ if(fromwire){
+ freeb(bp);
+ bp = 0;
+ }
+ return bp;
+ }
+ }
+ /* is it for me? */
+ tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
+ fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
+
+ /*
+ * Multiplex the packet to all the connections which want it.
+ * If the packet is not to be used subsequently (fromwire != 0),
+ * attempt to simply pass it into one of the connections, thereby
+ * saving a copy of the data (usual case hopefully).
+ */
+ for(fp = ether->f; fp < ep; fp++){
+ if((f = *fp) != nil && (f->type == type || f->type < 0) &&
+ (tome || multi || f->prom)){
+ /* Don't want to hear bridged packets */
+ if(f->bridge && !fromwire && !fromme)
+ continue;
+ if(!f->headersonly){
+ if(fromwire && fx == 0)
+ fx = f;
+ else if(xbp = iallocb(len)){
+ memmove(xbp->wp, pkt, len);
+ xbp->wp += len;
+ if(qpass(f->in, xbp) < 0)
+ ether->soverflows++;
+ }
+ else
+ ether->soverflows++;
+ }
+ else
+ etherrtrace(f, pkt, len);
+ }
+ }
+
+ if(fx){
+ if(qpass(fx->in, bp) < 0)
+ ether->soverflows++;
+ return 0;
+ }
+ if(fromwire){
+ freeb(bp);
+ return 0;
+ }
+ return bp;
+}
+
+static int
+etheroq(Ether* ether, Block* bp)
+{
+ int len, loopback, s;
+ Etherpkt *pkt;
+
+ ether->outpackets++;
+
+ /*
+ * Check if the packet has to be placed back onto the input queue,
+ * i.e. if it's a loopback or broadcast packet or the interface is
+ * in promiscuous mode.
+ * If it's a loopback packet indicate to etheriq that the data isn't
+ * needed and return, etheriq will pass-on or free the block.
+ * To enable bridging to work, only packets that were originated
+ * by this interface are fed back.
+ */
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
+ if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
+ s = splhi();
+ etheriq(ether, bp, 0);
+ splx(s);
+ }
+
+ if(!loopback){
+ qbwrite(ether->oq, bp);
+ if(ether->transmit != nil)
+ ether->transmit(ether);
+ } else
+ freeb(bp);
+
+ return len;
+}
+
+static long
+etherwrite(Chan* chan, void* buf, long n, vlong)
+{
+ Ether *ether;
+ Block *bp;
+ int nn, onoff;
+ Cmdbuf *cb;
+
+ ether = etherxx[chan->dev];
+ if(NETTYPE(chan->qid.path) != Ndataqid) {
+ nn = netifwrite(ether, chan, buf, n);
+ if(nn >= 0)
+ return nn;
+ cb = parsecmd(buf, n);
+ if(cb->f[0] && strcmp(cb->f[0], "nonblocking") == 0){
+ if(cb->nf <= 1)
+ onoff = 1;
+ else
+ onoff = atoi(cb->f[1]);
+ qnoblock(ether->oq, onoff);
+ free(cb);
+ return n;
+ }
+ free(cb);
+ if(ether->ctl!=nil)
+ return ether->ctl(ether,buf,n);
+
+ error(Ebadctl);
+ }
+
+ if(n > ether->maxmtu)
+ error(Etoobig);
+ if(n < ether->minmtu)
+ error(Etoosmall);
+
+ bp = allocb(n);
+ if(waserror()){
+ freeb(bp);
+ nexterror();
+ }
+ memmove(bp->rp, buf, n);
+ memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
+ poperror();
+ bp->wp += n;
+
+ return etheroq(ether, bp);
+}
+
+static long
+etherbwrite(Chan* chan, Block* bp, ulong)
+{
+ Ether *ether;
+ long n;
+
+ n = BLEN(bp);
+ if(NETTYPE(chan->qid.path) != Ndataqid){
+ if(waserror()) {
+ freeb(bp);
+ nexterror();
+ }
+ n = etherwrite(chan, bp->rp, n, 0);
+ poperror();
+ freeb(bp);
+ return n;
+ }
+ ether = etherxx[chan->dev];
+
+ if(n > ether->maxmtu){
+ freeb(bp);
+ error(Etoobig);
+ }
+ if(n < ether->minmtu){
+ freeb(bp);
+ error(Etoosmall);
+ }
+
+ return etheroq(ether, bp);
+}
+
+static struct {
+ char* type;
+ int (*reset)(Ether*);
+} cards[MaxEther+1];
+
+void
+addethercard(char* t, int (*r)(Ether*))
+{
+ static int ncard;
+
+ if(ncard == MaxEther)
+ panic("too many ether cards");
+ cards[ncard].type = t;
+ cards[ncard].reset = r;
+ ncard++;
+}
+
+int
+parseether(uchar *to, char *from)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ for(i = 0; i < Eaddrlen; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+static void
+etherreset(void)
+{
+ Ether *ether;
+ int i, n, ctlrno;
+ char name[KNAMELEN], buf[128];
+
+ for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+ if(ether == 0)
+ ether = malloc(sizeof(Ether));
+ memset(ether, 0, sizeof(Ether));
+ ether->ctlrno = ctlrno;
+ ether->mbps = 10;
+ ether->minmtu = ETHERMINTU;
+ ether->maxmtu = ETHERMAXTU;
+
+ if(archether(ctlrno, ether) <= 0)
+ continue;
+
+ if(isaconfig("ether", ctlrno, ether) == 0){
+ free(ether);
+// return nil;
+ continue;
+ }
+ for(n = 0; cards[n].type; n++){
+ if(cistrcmp(cards[n].type, ether->type))
+ continue;
+ for(i = 0; i < ether->nopt; i++)
+ if(cistrncmp(ether->opt[i], "ea=", 3) == 0){
+ if(parseether(ether->ea,
+ &ether->opt[i][3]) == -1)
+ memset(ether->ea, 0, Eaddrlen);
+ } else if(cistrcmp(ether->opt[i],
+ "100BASE-TXFD") == 0)
+ ether->mbps = 100;
+ if(cards[n].reset(ether))
+ break;
+ snprint(name, sizeof(name), "ether%d", ctlrno);
+
+ if(ether->interrupt != nil && ether->irq >= 0)
+ intrenable(ether->irq, ether->interrupt,
+ ether, 0, name);
+
+ i = snprint(buf, sizeof buf,
+ "#l%d: %s: %dMbps port %#lux irq %d",
+ ctlrno, ether->type, ether->mbps, ether->port,
+ ether->irq);
+ if(ether->mem)
+ i += snprint(buf+i, sizeof buf - i,
+ " addr %#lux", PADDR(ether->mem));
+ if(ether->size)
+ i += snprint(buf+i, sizeof buf - i,
+ " size %#luX", ether->size);
+ i += snprint(buf+i, sizeof buf - i,
+ ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
+ ether->ea[0], ether->ea[1], ether->ea[2],
+ ether->ea[3], ether->ea[4], ether->ea[5]);
+ snprint(buf+i, sizeof buf - i, "\n");
+ iprint("%s", buf); /* it may be too early for print */
+
+ if(ether->mbps >= 1000)
+ netifinit(ether, name, Ntypes, 4*1024*1024);
+ else if(ether->mbps >= 100)
+ netifinit(ether, name, Ntypes, 1024*1024);
+ else
+ netifinit(ether, name, Ntypes, 65*1024);
+ if(ether->oq == 0)
+ ether->oq = qopen(ether->limit, Qmsg, 0, 0);
+ if(ether->oq == 0)
+ panic("etherreset %s", name);
+ ether->alen = Eaddrlen;
+ memmove(ether->addr, ether->ea, Eaddrlen);
+ memset(ether->bcast, 0xFF, Eaddrlen);
+
+ etherxx[ctlrno] = ether;
+ ether = 0;
+ break;
+ }
+ }
+ if(ether)
+ free(ether);
+}
+
+static void
+ethershutdown(void)
+{
+ Ether *ether;
+ int i;
+
+ for(i = 0; i < MaxEther; i++){
+ ether = etherxx[i];
+ if(ether == nil)
+ continue;
+ if(ether->shutdown == nil) {
+ print("#l%d: no shutdown function\n", i);
+ continue;
+ }
+ (*ether->shutdown)(ether);
+ }
+}
+
+
+#define POLY 0xedb88320
+
+/* really slow 32 bit crc for ethers */
+ulong
+ethercrc(uchar *p, int len)
+{
+ int i, j;
+ ulong crc, b;
+
+ crc = 0xffffffff;
+ for(i = 0; i < len; i++){
+ b = *p++;
+ for(j = 0; j < 8; j++){
+ crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
+ b >>= 1;
+ }
+ }
+ return crc;
+}
+
+void
+dumpoq(Queue *oq)
+{
+ if (oq == nil)
+ print("no outq! ");
+ else if (qisclosed(oq))
+ print("outq closed ");
+ else if (qfull(oq))
+ print("outq full ");
+ else
+ print("outq %d ", qlen(oq));
+}
+
+void
+dumpnetif(Netif *netif)
+{
+ print("netif %s ", netif->name);
+ print("limit %d mbps %d link %d ",
+ netif->limit, netif->mbps, netif->link);
+ print("inpkts %lld outpkts %lld errs %d\n",
+ netif->inpackets, netif->outpackets,
+ netif->crcs + netif->oerrs + netif->frames + netif->overflows +
+ netif->buffs + netif->soverflows);
+}
+
+Dev etherdevtab = {
+ 'l',
+ "ether",
+
+ etherreset,
+ devinit,
+ ethershutdown,
+ etherattach,
+ etherwalk,
+ etherstat,
+ etheropen,
+ ethercreate,
+ etherclose,
+ etherread,
+ etherbread,
+ etherwrite,
+ etherbwrite,
+ devremove,
+ etherwstat,
+};
diff --git a/sys/src/9/omap/devuart.c b/sys/src/9/omap/devuart.c
new file mode 100755
index 000000000..af4fce768
--- /dev/null
+++ b/sys/src/9/omap/devuart.c
@@ -0,0 +1,789 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#include "../port/netif.h"
+
+enum
+{
+ /* soft flow control chars */
+ CTLS= 023,
+ CTLQ= 021,
+};
+
+extern Dev uartdevtab;
+extern PhysUart* physuart[];
+
+static Uart* uartlist;
+static Uart** uart;
+static int uartnuart;
+static Dirtab *uartdir;
+static int uartndir;
+static Timer *uarttimer;
+
+struct Uartalloc {
+ Lock;
+ Uart *elist; /* list of enabled interfaces */
+} uartalloc;
+
+static void uartclock(void);
+static void uartflow(void*);
+
+/*
+ * enable/disable uart and add/remove to list of enabled uarts
+ */
+//static
+Uart*
+uartenable(Uart *p)
+{
+ Uart **l;
+
+ if (up == nil)
+ return p; /* too soon; try again later */
+// return nil;
+
+ if(p->iq == nil){
+ if((p->iq = qopen(8*1024, 0, uartflow, p)) == nil)
+ return nil;
+ }
+ else
+ qreopen(p->iq);
+ if(p->oq == nil){
+ if((p->oq = qopen(8*1024, 0, uartkick, p)) == nil){
+ qfree(p->iq);
+ p->iq = nil;
+ return nil;
+ }
+ }
+ else
+ qreopen(p->oq);
+
+ p->ir = p->istage;
+ p->iw = p->istage;
+ p->ie = &p->istage[Stagesize];
+ p->op = p->ostage;
+ p->oe = p->ostage;
+
+ p->hup_dsr = p->hup_dcd = 0;
+ p->dsr = p->dcd = 0;
+
+ /* assume we can send */
+ p->cts = 1;
+ p->ctsbackoff = 0;
+
+if (up) {
+ if(p->bits == 0)
+ uartctl(p, "l8");
+ if(p->stop == 0)
+ uartctl(p, "s1");
+ if(p->parity == 0)
+ uartctl(p, "pn");
+ if(p->baud == 0)
+ uartctl(p, "b9600");
+ (*p->phys->enable)(p, 1);
+}
+
+ /*
+ * use ilock because uartclock can otherwise interrupt here
+ * and would hang on an attempt to lock uartalloc.
+ */
+ ilock(&uartalloc);
+ for(l = &uartalloc.elist; *l; l = &(*l)->elist){
+ if(*l == p)
+ break;
+ }
+ if(*l == 0){
+ p->elist = uartalloc.elist;
+ uartalloc.elist = p;
+ }
+ p->enabled = 1;
+ iunlock(&uartalloc);
+
+ return p;
+}
+
+static void
+uartdisable(Uart *p)
+{
+ Uart **l;
+
+ (*p->phys->disable)(p);
+
+ ilock(&uartalloc);
+ for(l = &uartalloc.elist; *l; l = &(*l)->elist){
+ if(*l == p){
+ *l = p->elist;
+ break;
+ }
+ }
+ p->enabled = 0;
+ iunlock(&uartalloc);
+}
+
+void
+uartmouse(Uart* p, int (*putc)(Queue*, int), int setb1200)
+{
+ qlock(p);
+ if(p->opens++ == 0 && uartenable(p) == nil){
+ qunlock(p);
+ error(Enodev);
+ }
+ if(setb1200)
+ uartctl(p, "b1200");
+ p->putc = putc;
+ p->special = 1;
+ qunlock(p);
+}
+
+void
+uartsetmouseputc(Uart* p, int (*putc)(Queue*, int))
+{
+ qlock(p);
+ if(p->opens == 0 || p->special == 0){
+ qunlock(p);
+ error(Enodev);
+ }
+ p->putc = putc;
+ qunlock(p);
+}
+
+static void
+setlength(int i)
+{
+ Uart *p;
+
+ if(i > 0){
+ p = uart[i];
+ if(p && p->opens && p->iq)
+ uartdir[1+3*i].length = qlen(p->iq);
+ } else for(i = 0; i < uartnuart; i++){
+ p = uart[i];
+ if(p && p->opens && p->iq)
+ uartdir[1+3*i].length = qlen(p->iq);
+ }
+}
+
+/*
+ * set up the '#t' directory
+ */
+static void
+uartreset(void)
+{
+ int i;
+ Dirtab *dp;
+ Uart *p, *tail;
+
+ tail = nil;
+ for(i = 0; physuart[i] != nil; i++){
+ if(physuart[i]->pnp == nil)
+ continue;
+ if((p = physuart[i]->pnp()) == nil)
+ continue;
+ if(uartlist != nil)
+ tail->next = p;
+ else
+ uartlist = p;
+ for(tail = p; tail->next != nil; tail = tail->next)
+ uartnuart++;
+ uartnuart++;
+ }
+
+ if(uartnuart)
+ uart = xalloc(uartnuart*sizeof(Uart*));
+
+ uartndir = 1 + 3*uartnuart;
+ uartdir = xalloc(uartndir * sizeof(Dirtab));
+ if (uart == nil || uartdir == nil)
+ panic("uartreset: no memory");
+ dp = uartdir;
+ strcpy(dp->name, ".");
+ mkqid(&dp->qid, 0, 0, QTDIR);
+ dp->length = 0;
+ dp->perm = DMDIR|0555;
+ dp++;
+ p = uartlist;
+ for(i = 0; i < uartnuart; i++){
+ /* 3 directory entries per port */
+ snprint(dp->name, sizeof dp->name, "eia%d", i);
+ dp->qid.path = NETQID(i, Ndataqid);
+ dp->perm = 0660;
+ dp++;
+ snprint(dp->name, sizeof dp->name, "eia%dctl", i);
+ dp->qid.path = NETQID(i, Nctlqid);
+ dp->perm = 0660;
+ dp++;
+ snprint(dp->name, sizeof dp->name, "eia%dstatus", i);
+ dp->qid.path = NETQID(i, Nstatqid);
+ dp->perm = 0444;
+ dp++;
+
+ uart[i] = p;
+ p->dev = i;
+ if(p->console || p->special){
+ if(uartenable(p) != nil){
+ if(p->console && up){
+ kbdq = p->iq;
+ serialoq = p->oq;
+ p->putc = kbdcr2nl;
+ }
+ p->opens++;
+ }
+ }
+ p = p->next;
+ }
+
+ if(uartnuart){
+ /*
+ * at 115200 baud, the 1024 char buffer takes 56 ms to process,
+ * processing it every 22 ms should be fine.
+ */
+ uarttimer = addclock0link(uartclock, 22);
+ }
+}
+
+
+static Chan*
+uartattach(char *spec)
+{
+ return devattach('t', spec);
+}
+
+static Walkqid*
+uartwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, uartdir, uartndir, devgen);
+}
+
+static int
+uartstat(Chan *c, uchar *dp, int n)
+{
+ if(NETTYPE(c->qid.path) == Ndataqid)
+ setlength(NETID(c->qid.path));
+ return devstat(c, dp, n, uartdir, uartndir, devgen);
+}
+
+static Chan*
+uartopen(Chan *c, int omode)
+{
+ Uart *p;
+
+ c = devopen(c, omode, uartdir, uartndir, devgen);
+
+ switch(NETTYPE(c->qid.path)){
+ case Nctlqid:
+ case Ndataqid:
+ p = uart[NETID(c->qid.path)];
+ qlock(p);
+ if(p->opens++ == 0 && uartenable(p) == nil){
+ qunlock(p);
+ c->flag &= ~COPEN;
+ error(Enodev);
+ }
+ qunlock(p);
+ break;
+ }
+
+ c->iounit = qiomaxatomic;
+ return c;
+}
+
+static int
+uartdrained(void* arg)
+{
+ Uart *p;
+
+ p = arg;
+ return qlen(p->oq) == 0 && p->op == p->oe;
+}
+
+static void
+uartdrainoutput(Uart *p)
+{
+ if(!p->enabled || up == nil)
+ return;
+
+ p->drain = 1;
+ if(waserror()){
+ p->drain = 0;
+ nexterror();
+ }
+ sleep(&p->r, uartdrained, p);
+ poperror();
+}
+
+static void
+uartclose(Chan *c)
+{
+ Uart *p;
+
+ if(c->qid.type & QTDIR)
+ return;
+ if((c->flag & COPEN) == 0)
+ return;
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ case Nctlqid:
+ p = uart[NETID(c->qid.path)];
+ qlock(p);
+ if(--(p->opens) == 0){
+ qclose(p->iq);
+ ilock(&p->rlock);
+ p->ir = p->iw = p->istage;
+ iunlock(&p->rlock);
+
+ /*
+ */
+ qhangup(p->oq, nil);
+ if(!waserror()){
+ uartdrainoutput(p);
+ poperror();
+ }
+ qclose(p->oq);
+ uartdisable(p);
+ p->dcd = p->dsr = p->dohup = 0;
+ }
+ qunlock(p);
+ break;
+ }
+}
+
+static long
+uartread(Chan *c, void *buf, long n, vlong off)
+{
+ Uart *p;
+ ulong offset = off;
+
+ if(c->qid.type & QTDIR){
+ setlength(-1);
+ return devdirread(c, buf, n, uartdir, uartndir, devgen);
+ }
+
+ p = uart[NETID(c->qid.path)];
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ return qread(p->iq, buf, n);
+ case Nctlqid:
+ return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE);
+ case Nstatqid:
+ return (*p->phys->status)(p, buf, n, offset);
+ }
+
+ return 0;
+}
+
+int
+uartctl(Uart *p, char *cmd)
+{
+ char *f[16];
+ int i, n, nf;
+
+ nf = tokenize(cmd, f, nelem(f));
+ for(i = 0; i < nf; i++){
+ if(strncmp(f[i], "break", 5) == 0){
+ (*p->phys->dobreak)(p, 0);
+ continue;
+ }
+
+ n = atoi(f[i]+1);
+ switch(*f[i]){
+ case 'B':
+ case 'b':
+ uartdrainoutput(p);
+ if((*p->phys->baud)(p, n) < 0)
+ return -1;
+ break;
+ case 'C':
+ case 'c':
+ p->hup_dcd = n;
+ break;
+ case 'D':
+ case 'd':
+ uartdrainoutput(p);
+ (*p->phys->dtr)(p, n);
+ break;
+ case 'E':
+ case 'e':
+ p->hup_dsr = n;
+ break;
+ case 'f':
+ case 'F':
+ if(p->oq != nil)
+ qflush(p->oq);
+ break;
+ case 'H':
+ case 'h':
+ if(p->iq != nil)
+ qhangup(p->iq, 0);
+ if(p->oq != nil)
+ qhangup(p->oq, 0);
+ break;
+ case 'i':
+ case 'I':
+ uartdrainoutput(p);
+ (*p->phys->fifo)(p, n);
+ break;
+ case 'K':
+ case 'k':
+ uartdrainoutput(p);
+ (*p->phys->dobreak)(p, n);
+ break;
+ case 'L':
+ case 'l':
+ uartdrainoutput(p);
+ if((*p->phys->bits)(p, n) < 0)
+ return -1;
+ break;
+ case 'm':
+ case 'M':
+ uartdrainoutput(p);
+ (*p->phys->modemctl)(p, n);
+ break;
+ case 'n':
+ case 'N':
+ if(p->oq != nil)
+ qnoblock(p->oq, n);
+ break;
+ case 'P':
+ case 'p':
+ uartdrainoutput(p);
+ if((*p->phys->parity)(p, *(f[i]+1)) < 0)
+ return -1;
+ break;
+ case 'Q':
+ case 'q':
+ if(p->iq != nil)
+ qsetlimit(p->iq, n);
+ if(p->oq != nil)
+ qsetlimit(p->oq, n);
+ break;
+ case 'R':
+ case 'r':
+ uartdrainoutput(p);
+ (*p->phys->rts)(p, n);
+ break;
+ case 'S':
+ case 's':
+ uartdrainoutput(p);
+ if((*p->phys->stop)(p, n) < 0)
+ return -1;
+ break;
+ case 'W':
+ case 'w':
+ if(uarttimer == nil || n < 1)
+ return -1;
+ uarttimer->tns = (vlong)n * 100000LL;
+ break;
+ case 'X':
+ case 'x':
+ if(p->enabled){
+ ilock(&p->tlock);
+ p->xonoff = n;
+ iunlock(&p->tlock);
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+static long
+uartwrite(Chan *c, void *buf, long n, vlong)
+{
+ Uart *p;
+ char *cmd;
+
+ if(c->qid.type & QTDIR)
+ error(Eperm);
+
+ p = uart[NETID(c->qid.path)];
+
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ qlock(p);
+ if(waserror()){
+ qunlock(p);
+ nexterror();
+ }
+
+ n = qwrite(p->oq, buf, n);
+
+ qunlock(p);
+ poperror();
+ break;
+ case Nctlqid:
+ cmd = malloc(n+1);
+ memmove(cmd, buf, n);
+ cmd[n] = 0;
+ qlock(p);
+ if(waserror()){
+ qunlock(p);
+ free(cmd);
+ nexterror();
+ }
+
+ /* let output drain */
+ if(uartctl(p, cmd) < 0)
+ error(Ebadarg);
+
+ qunlock(p);
+ poperror();
+ free(cmd);
+ break;
+ }
+
+ return n;
+}
+
+static int
+uartwstat(Chan *c, uchar *dp, int n)
+{
+ Dir d;
+ Dirtab *dt;
+
+ if(!iseve())
+ error(Eperm);
+ if(QTDIR & c->qid.type)
+ error(Eperm);
+ if(NETTYPE(c->qid.path) == Nstatqid)
+ error(Eperm);
+
+ dt = &uartdir[1 + 3 * NETID(c->qid.path)];
+ n = convM2D(dp, n, &d, nil);
+ if(n == 0)
+ error(Eshortstat);
+ if(d.mode != ~0UL)
+ dt[0].perm = dt[1].perm = d.mode;
+ return n;
+}
+
+void
+uartpower(int on)
+{
+ Uart *p;
+
+ for(p = uartlist; p != nil; p = p->next) {
+ if(p->phys->power)
+ (*p->phys->power)(p, on);
+ }
+}
+
+Dev uartdevtab = {
+ 't',
+ "uart",
+
+ uartreset,
+ devinit,
+ devshutdown,
+ uartattach,
+ uartwalk,
+ uartstat,
+ uartopen,
+ devcreate,
+ uartclose,
+ uartread,
+ devbread,
+ uartwrite,
+ devbwrite,
+ devremove,
+ uartwstat,
+ uartpower,
+};
+
+/*
+ * restart input if it's off
+ */
+static void
+uartflow(void *v)
+{
+ Uart *p;
+
+ p = v;
+ if(p->modem)
+ (*p->phys->rts)(p, 1);
+}
+
+/*
+ * put some bytes into the local queue to avoid calling
+ * qconsume for every character
+ */
+int
+uartstageoutput(Uart *p)
+{
+ int n;
+
+ n = qconsume(p->oq, p->ostage, Stagesize);
+ if(n <= 0)
+// n = 0; /* experiment */
+ return 0;
+ p->op = p->ostage;
+ p->oe = p->ostage + n;
+ return n;
+}
+
+/*
+ * restart output
+ */
+void
+uartkick(void *v)
+{
+ Uart *p = v;
+
+ if(p->blocked)
+ return;
+
+ ilock(&p->tlock);
+ (*p->phys->kick)(p);
+ iunlock(&p->tlock);
+
+ if(p->drain && uartdrained(p)){
+ p->drain = 0;
+ wakeup(&p->r);
+ }
+}
+
+/*
+ * Move data from the interrupt staging area to
+ * the input Queue.
+ */
+static void
+uartstageinput(Uart *p)
+{
+ int n;
+ uchar *ir, *iw;
+
+ while(p->ir != p->iw){
+ ir = p->ir;
+ if(p->ir > p->iw){
+ iw = p->ie;
+ p->ir = p->istage;
+ }
+ else{
+ iw = p->iw;
+ p->ir = p->iw;
+ }
+ if((n = qproduce(p->iq, ir, iw - ir)) < 0){
+ p->serr++;
+ (*p->phys->rts)(p, 0);
+ }
+ else if(n == 0)
+ p->berr++;
+ }
+}
+
+/*
+ * receive a character at interrupt time
+ */
+void
+uartrecv(Uart *p, char ch)
+{
+ uchar *next;
+
+ /* software flow control */
+ if(p->xonoff){
+ if(ch == CTLS){
+ p->blocked = 1;
+ }else if(ch == CTLQ){
+ p->blocked = 0;
+ p->ctsbackoff = 2; /* clock gets output going again */
+ }
+ }
+
+ /* receive the character */
+ if(p->putc)
+ p->putc(p->iq, ch);
+ else if (p->iw) { /* maybe the line isn't enabled yet */
+ ilock(&p->rlock);
+ next = p->iw + 1;
+ if(next == p->ie)
+ next = p->istage;
+ if(next == p->ir)
+ uartstageinput(p);
+ if(next != p->ir){
+ *p->iw = ch;
+ p->iw = next;
+ }
+ iunlock(&p->rlock);
+ }
+}
+
+/*
+ * we save up input characters till clock time to reduce
+ * per character interrupt overhead.
+ */
+static void
+uartclock(void)
+{
+ Uart *p;
+
+ ilock(&uartalloc);
+ for(p = uartalloc.elist; p; p = p->elist){
+
+ /* this hopefully amortizes cost of qproduce to many chars */
+ if(p->iw != p->ir){
+ ilock(&p->rlock);
+ uartstageinput(p);
+ iunlock(&p->rlock);
+ }
+
+ /* hang up if requested */
+ if(p->dohup){
+ qhangup(p->iq, 0);
+ qhangup(p->oq, 0);
+ p->dohup = 0;
+ }
+
+ /* this adds hysteresis to hardware/software flow control */
+ if(p->ctsbackoff){
+ ilock(&p->tlock);
+ if(p->ctsbackoff){
+ if(--(p->ctsbackoff) == 0)
+ (*p->phys->kick)(p);
+ }
+ iunlock(&p->tlock);
+ }
+ uartkick(p); /* keep it moving */
+ }
+ iunlock(&uartalloc);
+}
+
+/*
+ * polling console input, output
+ */
+
+Uart* consuart;
+
+int
+uartgetc(void)
+{
+ if(consuart == nil || consuart->phys->getc == nil)
+ return -1;
+ return consuart->phys->getc(consuart);
+}
+
+void
+uartputc(int c)
+{
+ if(consuart == nil || consuart->phys->putc == nil)
+ return;
+ consuart->phys->putc(consuart, c);
+}
+
+void
+uartputs(char *s, int n)
+{
+ char *e;
+
+ if(consuart == nil || consuart->phys->putc == nil)
+ return;
+
+ e = s+n;
+ for(; s<e; s++){
+ if(*s == '\n')
+ consuart->phys->putc(consuart, '\r');
+ consuart->phys->putc(consuart, *s);
+ }
+}
diff --git a/sys/src/9/omap/devusb.c b/sys/src/9/omap/devusb.c
new file mode 100755
index 000000000..efe93a931
--- /dev/null
+++ b/sys/src/9/omap/devusb.c
@@ -0,0 +1,1461 @@
+/*
+ * USB device driver framework.
+ *
+ * This is in charge of providing access to actual HCIs
+ * and providing I/O to the various endpoints of devices.
+ * A separate user program (usbd) is in charge of
+ * enumerating the bus, setting up endpoints and
+ * starting devices (also user programs).
+ *
+ * The interface provided is a violation of the standard:
+ * you're welcome.
+ *
+ * The interface consists of a root directory with several files
+ * plus a directory (epN.M) with two files per endpoint.
+ * A device is represented by its first endpoint, which
+ * is a control endpoint automatically allocated for each device.
+ * Device control endpoints may be used to create new endpoints.
+ * Devices corresponding to hubs may also allocate new devices,
+ * perhaps also hubs. Initially, a hub device is allocated for
+ * each controller present, to represent its root hub. Those can
+ * never be removed.
+ *
+ * All endpoints refer to the first endpoint (epN.0) of the device,
+ * which keeps per-device information, and also to the HCI used
+ * to reach them. Although all endpoints cache that information.
+ *
+ * epN.M/data files permit I/O and are considered DMEXCL.
+ * epN.M/ctl files provide status info and accept control requests.
+ *
+ * Endpoints may be given file names to be listed also at #u,
+ * for those drivers that have nothing to do after configuring the
+ * device and its endpoints.
+ *
+ * Drivers for different controllers are kept at usb[oue]hci.c
+ * It's likely we could factor out much from controllers into
+ * a generic controller driver, the problem is that details
+ * regarding how to handle toggles, tokens, Tds, etc. will
+ * get in the way. Thus, code is probably easier the way it is.
+ */
+
+#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/usb.h"
+
+typedef struct Hcitype Hcitype;
+
+enum
+{
+ /* Qid numbers */
+ Qdir = 0, /* #u */
+ Qusbdir, /* #u/usb */
+ Qctl, /* #u/usb/ctl - control requests */
+
+ Qep0dir, /* #u/usb/ep0.0 - endpoint 0 dir */
+ Qep0io, /* #u/usb/ep0.0/data - endpoint 0 I/O */
+ Qep0ctl, /* #u/usb/ep0.0/ctl - endpoint 0 ctl. */
+ Qep0dummy, /* give 4 qids to each endpoint */
+
+ Qepdir = 0, /* (qid-qep0dir)&3 is one of these */
+ Qepio, /* to identify which file for the endpoint */
+ Qepctl,
+
+ /* ... */
+
+ /* Usb ctls. */
+ CMdebug = 0, /* debug on|off */
+ CMdump, /* dump (data structures for debug) */
+
+ /* Ep. ctls */
+ CMnew = 0, /* new nb ctl|bulk|intr|iso r|w|rw (endpoint) */
+ CMnewdev, /* newdev full|low|high portnb (allocate new devices) */
+ CMhub, /* hub (set the device as a hub) */
+ CMspeed, /* speed full|low|high|no */
+ CMmaxpkt, /* maxpkt size */
+ CMntds, /* ntds nb (max nb. of tds per µframe) */
+ CMclrhalt, /* clrhalt (halt was cleared on endpoint) */
+ CMpollival, /* pollival interval (interrupt/iso) */
+ CMhz, /* hz n (samples/sec; iso) */
+ CMsamplesz, /* samplesz n (sample size; iso) */
+ CMinfo, /* info infostr (ke.ep info for humans) */
+ CMdetach, /* detach (abort I/O forever on this ep). */
+ CMaddress, /* address (address is assigned) */
+ CMdebugep, /* debug n (set/clear debug for this ep) */
+ CMname, /* name str (show up as #u/name as well) */
+ CMtmout, /* timeout n (activate timeouts for ep) */
+ CMpreset, /* reset the port */
+
+ /* Hub feature selectors */
+ Rportenable = 1,
+ Rportreset = 4,
+
+};
+
+struct Hcitype
+{
+ char* type;
+ int (*reset)(Hci*);
+};
+
+#define QID(q) ((int)(q).path)
+
+static char Edetach[] = "device is detached";
+static char Enotconf[] = "endpoint not configured";
+char Estalled[] = "endpoint stalled";
+
+static Cmdtab usbctls[] =
+{
+ {CMdebug, "debug", 2},
+ {CMdump, "dump", 1},
+};
+
+static Cmdtab epctls[] =
+{
+ {CMnew, "new", 4},
+ {CMnewdev, "newdev", 3},
+ {CMhub, "hub", 1},
+ {CMspeed, "speed", 2},
+ {CMmaxpkt, "maxpkt", 2},
+ {CMntds, "ntds", 2},
+ {CMpollival, "pollival", 2},
+ {CMsamplesz, "samplesz", 2},
+ {CMhz, "hz", 2},
+ {CMinfo, "info", 0},
+ {CMdetach, "detach", 1},
+ {CMaddress, "address", 1},
+ {CMdebugep, "debug", 2},
+ {CMclrhalt, "clrhalt", 1},
+ {CMname, "name", 2},
+ {CMtmout, "timeout", 2},
+ {CMpreset, "reset", 1},
+};
+
+static Dirtab usbdir[] =
+{
+ "ctl", {Qctl}, 0, 0666,
+};
+
+char *usbmodename[] =
+{
+ [OREAD] "r",
+ [OWRITE] "w",
+ [ORDWR] "rw",
+};
+
+static char *ttname[] =
+{
+ [Tnone] "none",
+ [Tctl] "control",
+ [Tiso] "iso",
+ [Tintr] "interrupt",
+ [Tbulk] "bulk",
+};
+
+static char *spname[] =
+{
+ [Fullspeed] "full",
+ [Lowspeed] "low",
+ [Highspeed] "high",
+ [Nospeed] "no",
+};
+
+static int debug;
+static Hcitype hcitypes[Nhcis];
+static Hci* hcis[Nhcis];
+static QLock epslck; /* add, del, lookup endpoints */
+static Ep* eps[Neps]; /* all endpoints known */
+static int epmax; /* 1 + last endpoint index used */
+static int usbidgen; /* device address generator */
+
+/*
+ * Is there something like this in a library? should it be?
+ */
+char*
+seprintdata(char *s, char *se, uchar *d, int n)
+{
+ int i, l;
+
+ s = seprint(s, se, " %#p[%d]: ", d, n);
+ l = n;
+ if(l > 10)
+ l = 10;
+ for(i=0; i<l; i++)
+ s = seprint(s, se, " %2.2ux", d[i]);
+ if(l < n)
+ s = seprint(s, se, "...");
+ return s;
+}
+
+static int
+name2speed(char *name)
+{
+ int i;
+
+ for(i = 0; i < nelem(spname); i++)
+ if(strcmp(name, spname[i]) == 0)
+ return i;
+ return Nospeed;
+}
+
+static int
+name2ttype(char *name)
+{
+ int i;
+
+ for(i = 0; i < nelem(ttname); i++)
+ if(strcmp(name, ttname[i]) == 0)
+ return i;
+ /* may be a std. USB ep. type */
+ i = strtol(name, nil, 0);
+ switch(i+1){
+ case Tctl:
+ case Tiso:
+ case Tbulk:
+ case Tintr:
+ return i+1;
+ default:
+ return Tnone;
+ }
+}
+
+static int
+name2mode(char *mode)
+{
+ int i;
+
+ for(i = 0; i < nelem(usbmodename); i++)
+ if(strcmp(mode, usbmodename[i]) == 0)
+ return i;
+ return -1;
+}
+
+static int
+qid2epidx(int q)
+{
+ q = (q-Qep0dir)/4;
+ if(q < 0 || q >= epmax || eps[q] == nil)
+ return -1;
+ return q;
+}
+
+static int
+isqtype(int q, int type)
+{
+ if(q < Qep0dir)
+ return 0;
+ q -= Qep0dir;
+ return (q & 3) == type;
+}
+
+void
+addhcitype(char* t, int (*r)(Hci*))
+{
+ static int ntype;
+
+ if(ntype == Nhcis)
+ panic("too many USB host interface types");
+ hcitypes[ntype].type = t;
+ hcitypes[ntype].reset = r;
+ ntype++;
+}
+
+static char*
+seprintep(char *s, char *se, Ep *ep, int all)
+{
+ static char* dsnames[] = { "config", "enabled", "detached", "reset" };
+ Udev *d;
+ int i;
+ int di;
+
+ d = ep->dev;
+
+ qlock(ep);
+ if(waserror()){
+ qunlock(ep);
+ nexterror();
+ }
+ di = ep->dev->nb;
+ if(all)
+ s = seprint(s, se, "dev %d ep %d ", di, ep->nb);
+ s = seprint(s, se, "%s", dsnames[ep->dev->state]);
+ s = seprint(s, se, " %s", ttname[ep->ttype]);
+ assert(ep->mode == OREAD || ep->mode == OWRITE || ep->mode == ORDWR);
+ s = seprint(s, se, " %s", usbmodename[ep->mode]);
+ s = seprint(s, se, " speed %s", spname[d->speed]);
+ s = seprint(s, se, " maxpkt %ld", ep->maxpkt);
+ s = seprint(s, se, " pollival %ld", ep->pollival);
+ s = seprint(s, se, " samplesz %ld", ep->samplesz);
+ s = seprint(s, se, " hz %ld", ep->hz);
+ s = seprint(s, se, " hub %d", ep->dev->hub);
+ s = seprint(s, se, " port %d", ep->dev->port);
+ if(ep->inuse)
+ s = seprint(s, se, " busy");
+ else
+ s = seprint(s, se, " idle");
+ if(all){
+ s = seprint(s, se, " load %uld", ep->load);
+ s = seprint(s, se, " ref %ld addr %#p", ep->ref, ep);
+ s = seprint(s, se, " idx %d", ep->idx);
+ if(ep->name != nil)
+ s = seprint(s, se, " name '%s'", ep->name);
+ if(ep->tmout != 0)
+ s = seprint(s, se, " tmout");
+ if(ep == ep->ep0){
+ s = seprint(s, se, " ctlrno %#x", ep->hp->ctlrno);
+ s = seprint(s, se, " eps:");
+ for(i = 0; i < nelem(d->eps); i++)
+ if(d->eps[i] != nil)
+ s = seprint(s, se, " ep%d.%d", di, i);
+ }
+ }
+ if(ep->info != nil)
+ s = seprint(s, se, "\n%s %s\n", ep->info, ep->hp->type);
+ else
+ s = seprint(s, se, "\n");
+ qunlock(ep);
+ poperror();
+ return s;
+}
+
+static Ep*
+epalloc(Hci *hp)
+{
+ Ep *ep;
+ int i;
+
+ ep = smalloc(sizeof(Ep));
+ ep->ref = 1;
+ qlock(&epslck);
+ for(i = 0; i < Neps; i++)
+ if(eps[i] == nil)
+ break;
+ if(i == Neps){
+ qunlock(&epslck);
+ free(ep);
+ print("usb: bug: too few endpoints.\n");
+ return nil;
+ }
+ ep->idx = i;
+ if(epmax <= i)
+ epmax = i+1;
+ eps[i] = ep;
+ ep->hp = hp;
+ ep->maxpkt = 8;
+ ep->ntds = 1;
+ ep->samplesz = ep->pollival = ep->hz = 0; /* make them void */
+ qunlock(&epslck);
+ return ep;
+}
+
+static Ep*
+getep(int i)
+{
+ Ep *ep;
+
+ if(i < 0 || i >= epmax || eps[i] == nil)
+ return nil;
+ qlock(&epslck);
+ ep = eps[i];
+ if(ep != nil)
+ incref(ep);
+ qunlock(&epslck);
+ return ep;
+}
+
+static void
+putep(Ep *ep)
+{
+ Udev *d;
+
+ if(ep != nil && decref(ep) == 0){
+ d = ep->dev;
+ deprint("usb: ep%d.%d %#p released\n", d->nb, ep->nb, ep);
+ qlock(&epslck);
+ eps[ep->idx] = nil;
+ if(ep->idx == epmax-1)
+ epmax--;
+ if(ep == ep->ep0 && ep->dev != nil && ep->dev->nb == usbidgen)
+ usbidgen--;
+ qunlock(&epslck);
+ if(d != nil){
+ qlock(ep->ep0);
+ d->eps[ep->nb] = nil;
+ qunlock(ep->ep0);
+ }
+ if(ep->ep0 != ep){
+ putep(ep->ep0);
+ ep->ep0 = nil;
+ }
+ free(ep->info);
+ free(ep->name);
+ free(ep);
+ }
+}
+
+static void
+dumpeps(void)
+{
+ int i;
+ static char buf[512];
+ char *s;
+ char *e;
+ Ep *ep;
+
+ print("usb dump eps: epmax %d Neps %d (ref=1+ for dump):\n", epmax, Neps);
+ for(i = 0; i < epmax; i++){
+ s = buf;
+ e = buf+sizeof(buf);
+ ep = getep(i);
+ if(ep != nil){
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ s = seprint(s, e, "ep%d.%d ", ep->dev->nb, ep->nb);
+ seprintep(s, e, ep, 1);
+ print("%s", buf);
+ ep->hp->seprintep(buf, e, ep);
+ print("%s", buf);
+ poperror();
+ putep(ep);
+ }
+ }
+ print("usb dump hcis:\n");
+ for(i = 0; i < Nhcis; i++)
+ if(hcis[i] != nil)
+ hcis[i]->dump(hcis[i]);
+}
+
+static int
+newusbid(Hci *)
+{
+ int id;
+
+ qlock(&epslck);
+ id = ++usbidgen;
+ if(id >= 0x7F)
+ print("#u: too many device addresses; reuse them more\n");
+ qunlock(&epslck);
+ return id;
+}
+
+/*
+ * Create endpoint 0 for a new device
+ */
+static Ep*
+newdev(Hci *hp, int ishub, int isroot)
+{
+ Ep *ep;
+ Udev *d;
+
+ ep = epalloc(hp);
+ d = ep->dev = smalloc(sizeof(Udev));
+ d->nb = newusbid(hp);
+ d->eps[0] = ep;
+ ep->nb = 0;
+ ep->toggle[0] = ep->toggle[1] = 0;
+ d->ishub = ishub;
+ d->isroot = isroot;
+ if(hp->highspeed != 0)
+ d->speed = Highspeed;
+ else
+ d->speed = Fullspeed;
+ d->state = Dconfig; /* address not yet set */
+ ep->dev = d;
+ ep->ep0 = ep; /* no ref counted here */
+ ep->ttype = Tctl;
+ ep->tmout = Xfertmout;
+ ep->mode = ORDWR;
+ dprint("newdev %#p ep%d.%d %#p\n", d, d->nb, ep->nb, ep);
+ return ep;
+}
+
+/*
+ * Create a new endpoint for the device
+ * accessed via the given endpoint 0.
+ */
+static Ep*
+newdevep(Ep *ep, int i, int tt, int mode)
+{
+ Ep *nep;
+ Udev *d;
+
+ d = ep->dev;
+ if(d->eps[i] != nil)
+ error("endpoint already in use");
+ nep = epalloc(ep->hp);
+ incref(ep);
+ d->eps[i] = nep;
+ nep->nb = i;
+ nep->toggle[0] = nep->toggle[1] = 0;
+ nep->ep0 = ep;
+ nep->dev = ep->dev;
+ nep->mode = mode;
+ nep->ttype = tt;
+ nep->debug = ep->debug;
+ /* set defaults */
+ switch(tt){
+ case Tctl:
+ nep->tmout = Xfertmout;
+ break;
+ case Tintr:
+ nep->pollival = 10;
+ break;
+ case Tiso:
+ nep->tmout = Xfertmout;
+ nep->pollival = 10;
+ nep->samplesz = 4;
+ nep->hz = 44100;
+ break;
+ }
+ deprint("newdevep ep%d.%d %#p\n", d->nb, nep->nb, nep);
+ return ep;
+}
+
+static int
+epdataperm(int mode)
+{
+
+ switch(mode){
+ case OREAD:
+ return 0440|DMEXCL;
+ break;
+ case OWRITE:
+ return 0220|DMEXCL;
+ break;
+ default:
+ return 0660|DMEXCL;
+ }
+}
+
+static int
+usbgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
+{
+ Qid q;
+ Dirtab *dir;
+ int perm;
+ char *se;
+ Ep *ep;
+ int nb;
+ int mode;
+
+ if(0)ddprint("usbgen q %#x s %d...", QID(c->qid), s);
+ if(s == DEVDOTDOT){
+ if(QID(c->qid) <= Qusbdir){
+ mkqid(&q, Qdir, 0, QTDIR);
+ devdir(c, q, "#u", 0, eve, 0555, dp);
+ }else{
+ mkqid(&q, Qusbdir, 0, QTDIR);
+ devdir(c, q, "usb", 0, eve, 0555, dp);
+ }
+ if(0)ddprint("ok\n");
+ return 1;
+ }
+
+ switch(QID(c->qid)){
+ case Qdir: /* list #u */
+ if(s == 0){
+ mkqid(&q, Qusbdir, 0, QTDIR);
+ devdir(c, q, "usb", 0, eve, 0555, dp);
+ if(0)ddprint("ok\n");
+ return 1;
+ }
+ s--;
+ if(s < 0 || s >= epmax)
+ goto Fail;
+ ep = getep(s);
+ if(ep == nil || ep->name == nil){
+ if(ep != nil)
+ putep(ep);
+ if(0)ddprint("skip\n");
+ return 0;
+ }
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ mkqid(&q, Qep0io+s*4, 0, QTFILE);
+ devdir(c, q, ep->name, 0, eve, epdataperm(ep->mode), dp);
+ putep(ep);
+ poperror();
+ if(0)ddprint("ok\n");
+ return 1;
+
+ case Qusbdir: /* list #u/usb */
+ Usbdir:
+ if(s < nelem(usbdir)){
+ dir = &usbdir[s];
+ mkqid(&q, dir->qid.path, 0, QTFILE);
+ devdir(c, q, dir->name, dir->length, eve, dir->perm, dp);
+ if(0)ddprint("ok\n");
+ return 1;
+ }
+ s -= nelem(usbdir);
+ if(s < 0 || s >= epmax)
+ goto Fail;
+ ep = getep(s);
+ if(ep == nil){
+ if(0)ddprint("skip\n");
+ return 0;
+ }
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ se = up->genbuf+sizeof(up->genbuf);
+ seprint(up->genbuf, se, "ep%d.%d", ep->dev->nb, ep->nb);
+ mkqid(&q, Qep0dir+4*s, 0, QTDIR);
+ putep(ep);
+ poperror();
+ devdir(c, q, up->genbuf, 0, eve, 0755, dp);
+ if(0)ddprint("ok\n");
+ return 1;
+
+ case Qctl:
+ s = 0;
+ goto Usbdir;
+
+ default: /* list #u/usb/epN.M */
+ nb = qid2epidx(QID(c->qid));
+ ep = getep(nb);
+ if(ep == nil)
+ goto Fail;
+ mode = ep->mode;
+ putep(ep);
+ if(isqtype(QID(c->qid), Qepdir)){
+ Epdir:
+ switch(s){
+ case 0:
+ mkqid(&q, Qep0io+nb*4, 0, QTFILE);
+ perm = epdataperm(mode);
+ devdir(c, q, "data", 0, eve, perm, dp);
+ break;
+ case 1:
+ mkqid(&q, Qep0ctl+nb*4, 0, QTFILE);
+ devdir(c, q, "ctl", 0, eve, 0664, dp);
+ break;
+ default:
+ goto Fail;
+ }
+ }else if(isqtype(QID(c->qid), Qepctl)){
+ s = 1;
+ goto Epdir;
+ }else{
+ s = 0;
+ goto Epdir;
+ }
+ if(0)ddprint("ok\n");
+ return 1;
+ }
+Fail:
+ if(0)ddprint("fail\n");
+ return -1;
+}
+
+static Hci*
+hciprobe(int cardno, int ctlrno)
+{
+ Hci *hp;
+ char *type;
+ char name[64];
+ static int epnb = 1; /* guess the endpoint nb. for the controller */
+
+ ddprint("hciprobe %d %d\n", cardno, ctlrno);
+ hp = smalloc(sizeof(Hci));
+ hp->ctlrno = ctlrno;
+
+ if(cardno < 0)
+ for(cardno = 0; cardno < Nhcis; cardno++){
+ if(hcitypes[cardno].type == nil)
+ break;
+ type = hp->type;
+ if(type==nil || *type==0)
+ type = "uhci";
+ if(cistrcmp(hcitypes[cardno].type, type) == 0)
+ break;
+ }
+
+ if(cardno >= Nhcis || hcitypes[cardno].type == nil){
+ free(hp);
+ return nil;
+ }
+ dprint("%s...", hcitypes[cardno].type);
+ if(hcitypes[cardno].reset(hp) < 0){
+ free(hp);
+ return nil;
+ }
+
+ snprint(name, sizeof(name), "usb%s", hcitypes[cardno].type);
+ intrenable(hp->irq, hp->interrupt, hp, UNKNOWN, name);
+
+ print("#u/usb/ep%d.0: %s: port %#luX irq %d\n",
+ epnb, hcitypes[cardno].type, hp->port, hp->irq);
+ epnb++;
+
+ return hp;
+}
+
+static void
+usbreset(void)
+{
+ int cardno, ctlrno;
+ Hci *hp;
+
+ dprint("usbreset\n");
+
+ for(ctlrno = 0; ctlrno < Nhcis; ctlrno++)
+ if((hp = hciprobe(-1, ctlrno)) != nil)
+ hcis[ctlrno] = hp;
+ cardno = ctlrno = 0;
+ while(cardno < Nhcis && ctlrno < Nhcis && hcitypes[cardno].type != nil)
+ if(hcis[ctlrno] != nil)
+ ctlrno++;
+ else{
+ hp = hciprobe(cardno, ctlrno);
+ if(hp == nil)
+ cardno++;
+ hcis[ctlrno++] = hp;
+ }
+ if(hcis[Nhcis-1] != nil)
+ print("usbreset: bug: Nhcis too small\n");
+}
+
+static void
+usbinit(void)
+{
+ Hci *hp;
+ int ctlrno;
+ Ep *d;
+ char info[40];
+
+ dprint("usbinit\n");
+ for(ctlrno = 0; ctlrno < Nhcis; ctlrno++){
+ hp = hcis[ctlrno];
+ if(hp != nil){
+ if(hp->init != nil)
+ hp->init(hp);
+ d = newdev(hp, 1, 1); /* new root hub */
+ d->dev->state = Denabled; /* although addr == 0 */
+ d->maxpkt = 64;
+ snprint(info, sizeof(info), "ports %d", hp->nports);
+ kstrdup(&d->info, info);
+ }
+ }
+}
+
+static Chan*
+usbattach(char *spec)
+{
+ return devattach(L'u', spec);
+}
+
+static Walkqid*
+usbwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, nil, 0, usbgen);
+}
+
+static int
+usbstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, nil, 0, usbgen);
+}
+
+/*
+ * µs for the given transfer, for bandwidth allocation.
+ * This is a very rough worst case for what 5.11.3
+ * of the usb 2.0 spec says.
+ * Also, we are using maxpkt and not actual transfer sizes.
+ * Only when we are sure we
+ * are not exceeding b/w might we consider adjusting it.
+ */
+static ulong
+usbload(int speed, int maxpkt)
+{
+ enum{ Hostns = 1000, Hubns = 333 };
+ ulong l;
+ ulong bs;
+
+ l = 0;
+ bs = 10UL * maxpkt;
+ switch(speed){
+ case Highspeed:
+ l = 55*8*2 + 2 * (3 + bs) + Hostns;
+ break;
+ case Fullspeed:
+ l = 9107 + 84 * (4 + bs) + Hostns;
+ break;
+ case Lowspeed:
+ l = 64107 + 2 * Hubns + 667 * (3 + bs) + Hostns;
+ break;
+ default:
+ print("usbload: bad speed %d\n", speed);
+ /* let it run */
+ }
+ return l / 1000UL; /* in µs */
+}
+
+static Chan*
+usbopen(Chan *c, int omode)
+{
+ int q;
+ Ep *ep;
+ int mode;
+
+ mode = openmode(omode);
+ q = QID(c->qid);
+
+ if(q >= Qep0dir && qid2epidx(q) < 0)
+ error(Eio);
+ if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
+ return devopen(c, omode, nil, 0, usbgen);
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ deprint("usbopen q %#x fid %d omode %d\n", q, c->fid, mode);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ qlock(ep);
+ if(ep->inuse){
+ qunlock(ep);
+ error(Einuse);
+ }
+ ep->inuse = 1;
+ qunlock(ep);
+ if(waserror()){
+ ep->inuse = 0;
+ nexterror();
+ }
+ if(mode != OREAD && ep->mode == OREAD)
+ error(Eperm);
+ if(mode != OWRITE && ep->mode == OWRITE)
+ error(Eperm);
+ if(ep->ttype == Tnone)
+ error(Enotconf);
+ ep->clrhalt = 0;
+ ep->rhrepl = -1;
+ if(ep->load == 0)
+ ep->load = usbload(ep->dev->speed, ep->maxpkt);
+ ep->hp->epopen(ep);
+
+ poperror(); /* ep->inuse */
+ poperror(); /* don't putep(): ref kept for fid using the ep. */
+
+ c->mode = mode;
+ c->flag |= COPEN;
+ c->offset = 0;
+ c->aux = nil; /* paranoia */
+ return c;
+}
+
+static void
+epclose(Ep *ep)
+{
+ qlock(ep);
+ if(waserror()){
+ qunlock(ep);
+ nexterror();
+ }
+ if(ep->inuse){
+ ep->hp->epclose(ep);
+ ep->inuse = 0;
+ }
+ qunlock(ep);
+ poperror();
+}
+
+static void
+usbclose(Chan *c)
+{
+ int q;
+ Ep *ep;
+
+ q = QID(c->qid);
+ if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
+ return;
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ return;
+ deprint("usbclose q %#x fid %d ref %ld\n", q, c->fid, ep->ref);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(c->flag & COPEN){
+ free(c->aux);
+ c->aux = nil;
+ epclose(ep);
+ putep(ep); /* release ref kept since usbopen */
+ c->flag &= ~COPEN;
+ }
+ poperror();
+ putep(ep);
+}
+
+static long
+ctlread(Chan *c, void *a, long n, vlong offset)
+{
+ int q;
+ char *s;
+ char *us;
+ char *se;
+ Ep *ep;
+ int i;
+
+ q = QID(c->qid);
+ us = s = smalloc(READSTR);
+ se = s + READSTR;
+ if(waserror()){
+ free(us);
+ nexterror();
+ }
+ if(q == Qctl)
+ for(i = 0; i < epmax; i++){
+ ep = getep(i);
+ if(ep != nil){
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ s = seprint(s, se, "ep%d.%d ", ep->dev->nb, ep->nb);
+ s = seprintep(s, se, ep, 0);
+ poperror();
+ }
+ putep(ep);
+ }
+ else{
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(c->aux != nil){
+ /* After a new endpoint request we read
+ * the new endpoint name back.
+ */
+ strecpy(s, se, c->aux);
+ free(c->aux);
+ c->aux = nil;
+ }else
+ seprintep(s, se, ep, 0);
+ poperror();
+ putep(ep);
+ }
+ n = readstr(offset, a, n, us);
+ poperror();
+ free(us);
+ return n;
+}
+
+/*
+ * Fake root hub emulation.
+ */
+static long
+rhubread(Ep *ep, void *a, long n)
+{
+ char *b;
+
+ if(ep->dev->isroot == 0 || ep->nb != 0 || n < 2)
+ return -1;
+ if(ep->rhrepl < 0)
+ return -1;
+
+ b = a;
+ memset(b, 0, n);
+ PUT2(b, ep->rhrepl);
+ ep->rhrepl = -1;
+ return n;
+}
+
+static long
+rhubwrite(Ep *ep, void *a, long n)
+{
+ uchar *s;
+ int cmd;
+ int feature;
+ int port;
+ Hci *hp;
+
+ if(ep->dev == nil || ep->dev->isroot == 0 || ep->nb != 0)
+ return -1;
+ if(n != Rsetuplen)
+ error("root hub is a toy hub");
+ ep->rhrepl = -1;
+ s = a;
+ if(s[Rtype] != (Rh2d|Rclass|Rother) && s[Rtype] != (Rd2h|Rclass|Rother))
+ error("root hub is a toy hub");
+ hp = ep->hp;
+ cmd = s[Rreq];
+ feature = GET2(s+Rvalue);
+ port = GET2(s+Rindex);
+ if(port < 1 || port > hp->nports)
+ error("bad hub port number");
+ switch(feature){
+ case Rportenable:
+ ep->rhrepl = hp->portenable(hp, port, cmd == Rsetfeature);
+ break;
+ case Rportreset:
+ ep->rhrepl = hp->portreset(hp, port, cmd == Rsetfeature);
+ break;
+ case Rgetstatus:
+ ep->rhrepl = hp->portstatus(hp, port);
+ break;
+ default:
+ ep->rhrepl = 0;
+ }
+ return n;
+}
+
+static long
+usbread(Chan *c, void *a, long n, vlong offset)
+{
+ int q;
+ Ep *ep;
+ int nr;
+
+ q = QID(c->qid);
+
+ if(c->qid.type == QTDIR)
+ return devdirread(c, a, n, nil, 0, usbgen);
+
+ if(q == Qctl || isqtype(q, Qepctl))
+ return ctlread(c, a, n, offset);
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(ep->dev->state == Ddetach)
+ error(Edetach);
+ if(ep->mode == OWRITE || ep->inuse == 0)
+ error(Ebadusefd);
+ switch(ep->ttype){
+ case Tnone:
+ error("endpoint not configured");
+ case Tctl:
+ nr = rhubread(ep, a, n);
+ if(nr >= 0){
+ n = nr;
+ break;
+ }
+ /* else fall */
+ default:
+ ddeprint("\nusbread q %#x fid %d cnt %ld off %lld\n",q,c->fid,n,offset);
+ n = ep->hp->epread(ep, a, n);
+ break;
+ }
+ poperror();
+ putep(ep);
+ return n;
+}
+
+static long
+pow2(int n)
+{
+ return 1 << n;
+}
+
+static void
+setmaxpkt(Ep *ep, char* s)
+{
+ long spp; /* samples per packet */
+
+ if(ep->dev->speed == Highspeed)
+ spp = (ep->hz * ep->pollival * ep->ntds + 7999) / 8000;
+ else
+ spp = (ep->hz * ep->pollival + 999) / 1000;
+ ep->maxpkt = spp * ep->samplesz;
+ deprint("usb: %s: setmaxpkt: hz %ld poll %ld"
+ " ntds %d %s speed -> spp %ld maxpkt %ld\n", s,
+ ep->hz, ep->pollival, ep->ntds, spname[ep->dev->speed],
+ spp, ep->maxpkt);
+ if(ep->maxpkt > 1024){
+ print("usb: %s: maxpkt %ld > 1024. truncating\n", s, ep->maxpkt);
+ ep->maxpkt = 1024;
+ }
+}
+
+/*
+ * Many endpoint ctls. simply update the portable representation
+ * of the endpoint. The actual controller driver will look
+ * at them to setup the endpoints as dictated.
+ */
+static long
+epctl(Ep *ep, Chan *c, void *a, long n)
+{
+ int i, l, mode, nb, tt;
+ char *b, *s;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ Ep *nep;
+ Udev *d;
+ static char *Info = "info ";
+
+ d = ep->dev;
+
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, epctls, nelem(epctls));
+ if(ct == nil)
+ error(Ebadctl);
+ i = ct->index;
+ if(i == CMnew || i == CMspeed || i == CMhub || i == CMpreset)
+ if(ep != ep->ep0)
+ error("allowed only on a setup endpoint");
+ if(i != CMclrhalt && i != CMdetach && i != CMdebugep && i != CMname)
+ if(ep != ep->ep0 && ep->inuse != 0)
+ error("must configure before using");
+ switch(i){
+ case CMnew:
+ deprint("usb epctl %s\n", cb->f[0]);
+ nb = strtol(cb->f[1], nil, 0);
+ if(nb < 0 || nb >= Ndeveps)
+ error("bad endpoint number");
+ tt = name2ttype(cb->f[2]);
+ if(tt == Tnone)
+ error("unknown endpoint type");
+ mode = name2mode(cb->f[3]);
+ if(mode < 0)
+ error("unknown i/o mode");
+ newdevep(ep, nb, tt, mode);
+ break;
+ case CMnewdev:
+ deprint("usb epctl %s\n", cb->f[0]);
+ if(ep != ep->ep0 || d->ishub == 0)
+ error("not a hub setup endpoint");
+ l = name2speed(cb->f[1]);
+ if(l == Nospeed)
+ error("speed must be full|low|high");
+ nep = newdev(ep->hp, 0, 0);
+ nep->dev->speed = l;
+ if(nep->dev->speed != Lowspeed)
+ nep->maxpkt = 64; /* assume full speed */
+ nep->dev->hub = d->nb;
+ nep->dev->port = atoi(cb->f[2]);
+ /* next read request will read
+ * the name for the new endpoint
+ */
+ l = sizeof(up->genbuf);
+ snprint(up->genbuf, l, "ep%d.%d", nep->dev->nb, nep->nb);
+ kstrdup(&c->aux, up->genbuf);
+ break;
+ case CMhub:
+ deprint("usb epctl %s\n", cb->f[0]);
+ d->ishub = 1;
+ break;
+ case CMspeed:
+ l = name2speed(cb->f[1]);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l == Nospeed)
+ error("speed must be full|low|high");
+ qlock(ep->ep0);
+ d->speed = l;
+ qunlock(ep->ep0);
+ break;
+ case CMmaxpkt:
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l < 1 || l > 1024)
+ error("maxpkt not in [1:1024]");
+ qlock(ep);
+ ep->maxpkt = l;
+ qunlock(ep);
+ break;
+ case CMntds:
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l < 1 || l > 3)
+ error("ntds not in [1:3]");
+ qlock(ep);
+ ep->ntds = l;
+ qunlock(ep);
+ break;
+ case CMpollival:
+ if(ep->ttype != Tintr && ep->ttype != Tiso)
+ error("not an intr or iso endpoint");
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(ep->ttype == Tiso ||
+ (ep->ttype == Tintr && ep->dev->speed == Highspeed)){
+ if(l < 1 || l > 16)
+ error("pollival power not in [1:16]");
+ l = pow2(l-1);
+ }else
+ if(l < 1 || l > 255)
+ error("pollival not in [1:255]");
+ qlock(ep);
+ ep->pollival = l;
+ if(ep->ttype == Tiso)
+ setmaxpkt(ep, "pollival");
+ qunlock(ep);
+ break;
+ case CMsamplesz:
+ if(ep->ttype != Tiso)
+ error("not an iso endpoint");
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l <= 0 || l > 8)
+ error("samplesz not in [1:8]");
+ qlock(ep);
+ ep->samplesz = l;
+ setmaxpkt(ep, "samplesz");
+ qunlock(ep);
+ break;
+ case CMhz:
+ if(ep->ttype != Tiso)
+ error("not an iso endpoint");
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l <= 0 || l > 100000)
+ error("hz not in [1:100000]");
+ qlock(ep);
+ ep->hz = l;
+ setmaxpkt(ep, "hz");
+ qunlock(ep);
+ break;
+ case CMclrhalt:
+ qlock(ep);
+ deprint("usb epctl %s\n", cb->f[0]);
+ ep->clrhalt = 1;
+ qunlock(ep);
+ break;
+ case CMinfo:
+ deprint("usb epctl %s\n", cb->f[0]);
+ l = strlen(Info);
+ s = a;
+ if(n < l+2 || strncmp(Info, s, l) != 0)
+ error(Ebadctl);
+ if(n > 1024)
+ n = 1024;
+ b = smalloc(n);
+ memmove(b, s+l, n-l);
+ b[n-l] = 0;
+ if(b[n-l-1] == '\n')
+ b[n-l-1] = 0;
+ qlock(ep);
+ free(ep->info);
+ ep->info = b;
+ qunlock(ep);
+ break;
+ case CMaddress:
+ deprint("usb epctl %s\n", cb->f[0]);
+ ep->dev->state = Denabled;
+ break;
+ case CMdetach:
+ if(ep->dev->isroot != 0)
+ error("can't detach a root hub");
+ deprint("usb epctl %s ep%d.%d\n",
+ cb->f[0], ep->dev->nb, ep->nb);
+ ep->dev->state = Ddetach;
+ /* Release file system ref. for its endpoints */
+ for(i = 0; i < nelem(ep->dev->eps); i++)
+ putep(ep->dev->eps[i]);
+ break;
+ case CMdebugep:
+ if(strcmp(cb->f[1], "on") == 0)
+ ep->debug = 1;
+ else if(strcmp(cb->f[1], "off") == 0)
+ ep->debug = 0;
+ else
+ ep->debug = strtoul(cb->f[1], nil, 0);
+ print("usb: ep%d.%d debug %d\n",
+ ep->dev->nb, ep->nb, ep->debug);
+ break;
+ case CMname:
+ deprint("usb epctl %s %s\n", cb->f[0], cb->f[1]);
+ validname(cb->f[1], 0);
+ kstrdup(&ep->name, cb->f[1]);
+ break;
+ case CMtmout:
+ deprint("usb epctl %s\n", cb->f[0]);
+ if(ep->ttype == Tiso || ep->ttype == Tctl)
+ error("ctl ignored for this endpoint type");
+ ep->tmout = strtoul(cb->f[1], nil, 0);
+ if(ep->tmout != 0 && ep->tmout < Xfertmout)
+ ep->tmout = Xfertmout;
+ break;
+ case CMpreset:
+ deprint("usb epctl %s\n", cb->f[0]);
+ if(ep->ttype != Tctl)
+ error("not a control endpoint");
+ if(ep->dev->state != Denabled)
+ error("forbidden on devices not enabled");
+ ep->dev->state = Dreset;
+ break;
+ default:
+ panic("usb: unknown epctl %d", ct->index);
+ }
+ free(cb);
+ poperror();
+ return n;
+}
+
+static long
+usbctl(void *a, long n)
+{
+ Cmdtab *ct;
+ Cmdbuf *cb;
+ Ep *ep;
+ int i;
+
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, usbctls, nelem(usbctls));
+ dprint("usb ctl %s\n", cb->f[0]);
+ switch(ct->index){
+ case CMdebug:
+ if(strcmp(cb->f[1], "on") == 0)
+ debug = 1;
+ else if(strcmp(cb->f[1], "off") == 0)
+ debug = 0;
+ else
+ debug = strtol(cb->f[1], nil, 0);
+ print("usb: debug %d\n", debug);
+ for(i = 0; i < epmax; i++)
+ if((ep = getep(i)) != nil){
+ ep->hp->debug(ep->hp, debug);
+ putep(ep);
+ }
+ break;
+ case CMdump:
+ dumpeps();
+ break;
+ }
+ free(cb);
+ poperror();
+ return n;
+}
+
+static long
+ctlwrite(Chan *c, void *a, long n)
+{
+ int q;
+ Ep *ep;
+
+ q = QID(c->qid);
+ if(q == Qctl)
+ return usbctl(a, n);
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(ep->dev->state == Ddetach)
+ error(Edetach);
+ if(isqtype(q, Qepctl) && c->aux != nil){
+ /* Be sure we don't keep a cloned ep name */
+ free(c->aux);
+ c->aux = nil;
+ error("read, not write, expected");
+ }
+ n = epctl(ep, c, a, n);
+ putep(ep);
+ poperror();
+ return n;
+}
+
+static long
+usbwrite(Chan *c, void *a, long n, vlong off)
+{
+ int nr, q;
+ Ep *ep;
+
+ if(c->qid.type == QTDIR)
+ error(Eisdir);
+
+ q = QID(c->qid);
+
+ if(q == Qctl || isqtype(q, Qepctl))
+ return ctlwrite(c, a, n);
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(ep->dev->state == Ddetach)
+ error(Edetach);
+ if(ep->mode == OREAD || ep->inuse == 0)
+ error(Ebadusefd);
+
+ switch(ep->ttype){
+ case Tnone:
+ error("endpoint not configured");
+ case Tctl:
+ nr = rhubwrite(ep, a, n);
+ if(nr >= 0){
+ n = nr;
+ break;
+ }
+ /* else fall */
+ default:
+ ddeprint("\nusbwrite q %#x fid %d cnt %ld off %lld\n",q, c->fid, n, off);
+ ep->hp->epwrite(ep, a, n);
+ }
+ putep(ep);
+ poperror();
+ return n;
+}
+
+void
+usbshutdown(void)
+{
+ Hci *hp;
+ int i;
+
+ for(i = 0; i < Nhcis; i++){
+ hp = hcis[i];
+ if(hp == nil)
+ continue;
+ if(hp->shutdown == nil)
+ print("#u: no shutdown function for %s\n", hp->type);
+ else
+ hp->shutdown(hp);
+ }
+}
+
+Dev usbdevtab = {
+ L'u',
+ "usb",
+
+ usbreset,
+ usbinit,
+ usbshutdown,
+ usbattach,
+ usbwalk,
+ usbstat,
+ usbopen,
+ devcreate,
+ usbclose,
+ usbread,
+ devbread,
+ usbwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/omap/dma.c b/sys/src/9/omap/dma.c
new file mode 100755
index 000000000..385fcd45d
--- /dev/null
+++ b/sys/src/9/omap/dma.c
@@ -0,0 +1,263 @@
+/*
+ * omap3530 system dma controller
+ *
+ * terminology: a block consist of frame(s), a frame consist of elements
+ * (uchar, ushort, or ulong sized).
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+enum {
+ Nirq = 4,
+ Baseirq = 12,
+
+ Nchan = 32,
+};
+
+/*
+ * has a sw reset bit
+ * dma req lines 1, 2, 6, 63 are available for `system expansion'
+ */
+
+typedef struct Regs Regs;
+typedef struct Dchan Dchan;
+struct Regs {
+ uchar _pad0[8];
+ /* bitfield of intrs pending, by Dchan; write 1s to clear */
+ ulong irqsts[Nirq];
+ ulong irqen[Nirq]; /* bitfield of intrs enabled, by Dchan */
+ ulong syssts; /* 1<<0 is Resetdone */
+ ulong syscfg; /* 1<<1 is Softreset */
+ uchar _pad1[0x64 - 0x30];
+
+ ulong caps[5]; /* caps[1] not defined */
+ ulong gcr; /* knobs */
+ ulong _pad2;
+
+ struct Dchan {
+ ulong ccr; /* chan ctrl: incr, etc. */
+ ulong clnkctrl; /* link ctrl */
+ ulong cicr; /* intr ctrl */
+ ulong csr; /* status */
+ ulong csdp; /* src & dest params */
+ ulong cen; /* element # */
+ ulong cfn; /* frame # */
+ ulong cssa; /* src start addr */
+ ulong cdsa; /* dest start addr */
+ ulong csei; /* src element index */
+ ulong csfi; /* src frame index | pkt size */
+ ulong cdei; /* dest element index */
+ ulong cdfi; /* dest frame index | pkt size */
+ ulong csac; /* src addr value (read-only?) */
+ ulong cdac; /* dest addr value */
+ ulong ccen; /* curr transferred element # (in frame) */
+ ulong ccfn; /* curr transferred frame # (in xfer) */
+ ulong color;
+ uchar _pad3[24];
+ } chan[Nchan];
+};
+
+enum {
+ /* cicr/csr bits */
+ Blocki = 1 << 5,
+
+ /* ccr bits */
+ Enable = 1 << 7,
+};
+
+typedef struct Xfer Xfer;
+static struct Xfer {
+ Rendez *rend;
+ int *done; /* flag to set on intr */
+} xfer[Nirq];
+
+int
+isdmadone(int irq)
+{
+ Dchan *cp;
+ Regs *regs = (Regs *)PHYSSDMA;
+
+ cp = regs->chan + irq;
+ return cp->csr & Blocki;
+}
+
+static void
+dmaintr(Ureg *, void *a)
+{
+ int i = (int)a; /* dma request & chan # */
+ Dchan *cp;
+ Regs *regs = (Regs *)PHYSSDMA;
+
+ assert(i >= 0 && i < Nirq);
+
+ *xfer[i].done = 1;
+ assert(xfer[i].rend != nil);
+ wakeup(xfer[i].rend);
+
+ cp = regs->chan + i;
+ if(!(cp->csr & Blocki))
+ iprint("dmaintr: req %d: Blocki not set; csr %#lux\n",
+ i, cp->csr);
+ cp->csr |= cp->csr; /* extinguish intr source */
+ coherence();
+ regs->irqsts[i] = regs->irqsts[i]; /* extinguish intr source */
+ coherence();
+ regs->irqen[i] &= ~(1 << i);
+ coherence();
+
+ xfer[i].rend = nil;
+ coherence();
+}
+
+void
+zerowds(ulong *wdp, int cnt)
+{
+ while (cnt-- > 0)
+ *wdp++ = 0;
+}
+
+static int
+istestdmadone(void *arg)
+{
+ return *(int *)arg;
+}
+
+void
+dmainit(void)
+{
+ int n;
+ char name[16];
+ Dchan *cp;
+ Regs *regs = (Regs *)PHYSSDMA;
+
+ if (probeaddr((uintptr)&regs->syssts) < 0)
+ panic("dmainit: no syssts reg");
+ regs->syssts = 0;
+ coherence();
+ regs->syscfg |= 1<<1; /* Softreset */
+ coherence();
+ while(!(regs->syssts & (1<<0))) /* Resetdone? */
+ ;
+
+ for (n = 0; n < Nchan; n++) {
+ cp = regs->chan + n;
+ cp->ccr = 0;
+ cp->clnkctrl = 0;
+ cp->cicr = 0;
+ cp->csr = 0;
+ cp->csdp = 0;
+ cp->cen = cp->cfn = 0;
+ cp->cssa = cp->cdsa = 0;
+ cp->csei = cp->csfi = 0;
+ cp->cdei = cp->cdfi = 0;
+// cp->csac = cp->cdac = 0; // ro
+ cp->ccen = cp->ccfn = 0;
+ cp->color = 0;
+ }
+ zerowds((void *)regs->irqsts, sizeof regs->irqsts / sizeof(ulong));
+ zerowds((void *)regs->irqen, sizeof regs->irqen / sizeof(ulong));
+ coherence();
+
+ regs->gcr = 65; /* burst size + 1 */
+ coherence();
+
+ for (n = 0; n < Nirq; n++) {
+ snprint(name, sizeof name, "dma%d", n);
+ intrenable(Baseirq + n, dmaintr, (void *)n, nil, name);
+ }
+}
+
+enum {
+ Testbyte = 0252,
+ Testsize = 256,
+ Scratch = MB,
+};
+
+/*
+ * try to confirm sane operation
+ */
+void
+dmatest(void)
+{
+ int n, done;
+ uchar *bp;
+ static ulong pat = 0x87654321;
+ static Rendez trendez;
+
+ if (up == nil)
+ panic("dmatest: up not set yet");
+ bp = (uchar *)KADDR(PHYSDRAM + 128*MB);
+ memset(bp, Testbyte, Scratch);
+ done = 0;
+ dmastart((void *)PADDR(bp), Postincr, (void *)PADDR(&pat), Const,
+ Testsize, &trendez, &done);
+ sleep(&trendez, istestdmadone, &done);
+ cachedinvse(bp, Scratch);
+
+ if (((ulong *)bp)[0] != pat)
+ panic("dmainit: copied incorrect data %#lux != %#lux",
+ ((ulong *)bp)[0], pat);
+ for (n = Testsize; n < Scratch && bp[n] != Testbyte; n++)
+ ;
+ if (n >= Scratch)
+ panic("dmainit: ran wild over memory, clobbered ≥%,d bytes", n);
+ if (bp[n] == Testbyte && n != Testsize)
+ iprint("dma: %d-byte dma stopped after %d bytes!\n",
+ Testsize, n);
+}
+
+/* addresses are physical */
+int
+dmastart(void *to, int tmode, void *from, int fmode, uint len, Rendez *rend,
+ int *done)
+{
+ int irq, chan;
+ uint ruplen;
+ Dchan *cp;
+ Regs *regs = (Regs *)PHYSSDMA;
+ static Lock alloclck;
+
+ /* allocate free irq (and chan) */
+ ilock(&alloclck);
+ for (irq = 0; irq < Nirq && xfer[irq].rend != nil; irq++)
+ ;
+ if (irq >= Nirq)
+ panic("dmastart: no available irqs; too many concurrent dmas");
+ chan = irq;
+ xfer[irq].rend = rend; /* for wakeup at intr time */
+ xfer[irq].done = done;
+ *done = 0;
+ iunlock(&alloclck);
+
+ ruplen = ROUNDUP(len, sizeof(ulong));
+ assert(to != from);
+
+ cp = regs->chan + chan;
+ cp->ccr &= ~Enable; /* paranoia */
+ cp->cicr = 0;
+ regs->irqen[irq] &= ~(1 << chan);
+ coherence();
+
+ cp->csdp = 2; /* 2 = log2(sizeof(ulong)) */
+ cp->cssa = (uintptr)from;
+ cp->cdsa = (uintptr)to;
+ cp->ccr = tmode << 14 | fmode << 12;
+ cp->csei = cp->csfi = cp->cdei = cp->cdfi = 1;
+ cp->cen = ruplen / sizeof(ulong); /* ulongs / frame */
+ cp->cfn = 1; /* 1 frame / xfer */
+ cp->cicr = Blocki; /* intr at end of block */
+
+ regs->irqen[irq] |= 1 << chan;
+ coherence();
+
+ cp->ccr |= Enable; /* fire! */
+ coherence();
+
+ return irq;
+}
diff --git a/sys/src/9/omap/ether9221.c b/sys/src/9/omap/ether9221.c
new file mode 100755
index 000000000..9f7a571aa
--- /dev/null
+++ b/sys/src/9/omap/ether9221.c
@@ -0,0 +1,961 @@
+/*
+ * SMSC 9221 Ethernet driver
+ * specifically for the ISEE IGEPv2 board,
+ * where it is assigned to Chip Select 5,
+ * its registers are at 0x2c000000 (inherited from u-boot),
+ * and irq is 34 from gpio pin 176, thus gpio module 6.
+ *
+ * it's slow due to the use of fifos instead of buffer rings.
+ * the slow system dma just makes it worse.
+ *
+ * igepv2 u-boot uses pin 64 on gpio 3 as an output pin to reset the 9221.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+/* currently using kprocs is a lot slower than not (87 s. to boot vs 60) */
+#undef USE_KPROCS
+
+enum {
+ Vid9221 = 0x9221,
+ Slop = 4, /* beyond ETHERMAXTU */
+};
+
+typedef struct Regs Regs;
+struct Regs {
+ /* fifo ports */
+ ulong rxdata;
+ uchar _pad0[0x20 - 4];
+ ulong txdata;
+ uchar _pad1[0x40 - 0x24];
+ ulong rxsts;
+ ulong rxstspeek;
+ ulong txsts;
+ ulong txstspeek;
+
+ /* control & status */
+ ushort rev; /* chip revision */
+ ushort id; /* chip id, 0x9221 */
+ ulong irqcfg;
+ ulong intsts;
+ ulong inten;
+ ulong _pad2;
+ ulong bytetest;
+ ulong fifoint; /* fifo level interrupts */
+ ulong rxcfg;
+ ulong txcfg;
+ ulong hwcfg;
+ ulong rxdpctl; /* rx data path control */
+ ulong rxfifoinf;
+ ulong txfifoinf;
+ ulong pmtctl; /* power mgmt. control */
+ ulong gpiocfg;
+ ulong gptcfg; /* timer */
+ ulong gptcnt;
+ ulong _pad3;
+ ulong wordswap;
+ ulong freerun; /* counters */
+ ulong rxdrop;
+
+ /*
+ * mac registers are accessed indirectly via the mac csr registers.
+ * phy registers are doubly indirect, via the mac csr mii_acc &
+ * mii_data mac csr registers.
+ */
+ ulong maccsrcmd; /* mac csr synchronizer */
+ ulong maccsrdata;
+ ulong afccfg; /* automatic flow control cfg. */
+ ulong eepcmd; /* eeprom */
+ ulong eepdata;
+ /* 0xb8 */
+};
+
+enum {
+ Nstatistics = 128,
+};
+
+enum {
+ /* txcmda bits */
+ Intcompl = 1<<31,
+ Bufendalign = 3<<24, /* mask */
+ Datastoff = 037<<16, /* mask */
+ Firstseg = 1<<13,
+ Lastseg = 1<<12,
+ Bufsize = MASK(11),
+
+ /* txcmdb bits */
+ Pkttag = MASK(16) << 16,
+ Txcksumen = 1<<14,
+ Addcrcdis = 1<<13,
+ Framepaddis = 1<<12,
+ Pktlen = (1<<1) - 1, /* mask */
+
+ /* txcfg bits */
+ Txsdump = 1<<15, /* flush tx status fifo */
+ Txddump = 1<<14, /* flush tx data fifo */
+ Txon = 1<<1,
+ Stoptx = 1<<0,
+
+ /* hwcfg bits */
+ Mbo = 1<<20, /* must be one */
+ Srstto = 1<<1, /* soft reset time-out */
+ Srst = 1<<0,
+
+ /* rxcfg bits */
+ Rxdmacntshift = 16, /* ulong count, 12 bits wide */
+ Rxdmacntmask = MASK(12) << Rxdmacntshift,
+ Rxdump = 1<<15, /* flush rx fifos */
+
+ /* rxsts bits */
+ Rxpktlenshift = 16, /* byte count */
+ Rxpktlenmask = MASK(14) << Rxpktlenshift,
+ Rxerr = 1<<15,
+
+ /* rxfifoinf bits */
+ Rxstsusedshift = 16, /* ulong count */
+ Rxstsusedmask = MASK(8) << Rxstsusedshift,
+ Rxdatausedmask = MASK(16), /* byte count */
+
+ /* txfifoinf bits */
+ Txstsusedshift = 16, /* ulong count */
+ Txstsusedmask = MASK(8) << Txstsusedshift,
+ Txdatafreemask = MASK(16), /* byte count */
+
+ /* pmtctl bits */
+ Dready = 1<<0,
+
+ /* maccsrcmd bits */
+ Csrbusy = 1<<31,
+ Csrread = 1<<30, /* not write */
+ Csraddrshift = 0,
+ Csraddrmask = MASK(8) - 1,
+
+ /* mac registers' indices */
+ Maccr = 1,
+ Macaddrh,
+ Macaddrl,
+ Machashh,
+ Machashl,
+ Macmiiacc, /* for doubly-indirect phy access */
+ Macmiidata,
+ Macflow,
+ Macvlan1,
+ Macvlan2,
+ Macwuff,
+ Macwucsr,
+ Maccoe,
+
+ /* Maccr bits */
+ Rxall = 1<<31,
+ Rcvown = 1<<23, /* don't receive own transmissions */
+ Fdpx = 1<<20, /* full duplex */
+ Mcpas = 1<<19, /* pass all multicast */
+ Prms = 1<<18, /* promiscuous */
+ Ho = 1<<15, /* hash-only filtering */
+ Hpfilt = 1<<13, /* hash/perfect filtering */
+ Padstr = 1<<8, /* strip padding & fcs (crc) */
+ Txen = 1<<3,
+ Rxen = 1<<2,
+
+ /* irqcfg bits */
+ Irqdeasclr = 1<<14, /* deassertion intv'l clear */
+ Irqdeassts = 1<<13, /* deassertion intv'l status */
+ Irqint = 1<<12, /* intr being asserted? (ro) */
+ Irqen = 1<<8,
+ Irqpol = 1<<4, /* irq output is active high */
+ Irqpushpull = 1<<0, /* irq output is push/pull driver */
+
+ /* intsts/inten bits */
+ Swint = 1<<31, /* generate an interrupt */
+ Txstop = 1<<25,
+ Rxstop = 1<<24,
+ Txioc = 1<<21,
+ Rxdma = 1<<20,
+ Gptimer = 1<<19,
+ Phy = 1<<18,
+ Rxe = 1<<14, /* errors */
+ Txe = 1<<13,
+ Tdfo = 1<<10, /* tx data fifo overrun */
+ Tdfa = 1<<9, /* tx data fifo available */
+ Tsff = 1<<8, /* tx status fifo full */
+ Tsfl = 1<<7, /* tx status fifo level */
+ Rsff = 1<<4, /* rx status fifo full */
+ Rsfl = 1<<3, /* rx status fifo level */
+
+ /* eepcmd bits */
+ Epcbusy = 1<<31,
+ Epccmdshift = 28, /* interesting one is Reload (7) */
+ Epctimeout = 1<<9,
+ Epcmacloaded = 1<<8,
+ Epcaddrshift = 0,
+};
+
+enum {
+ Rxintrs = Rsff | Rsfl | Rxe,
+ Txintrs = Tsff | Tsfl | Txe | Txioc,
+};
+
+/* wake-up frame filter */
+struct Wakeup {
+ ulong bytemask[4]; /* index is filter # */
+ uchar filt0cmd; /* filter 0 command */
+ uchar _pad0;
+ uchar filt1cmd;
+ uchar _pad1;
+ uchar filt2cmd;
+ uchar _pad2;
+ uchar filt3cmd;
+ uchar _pad3;
+ uchar offset[4]; /* index is filter # */
+ ushort crc16[4]; /* " */
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ int port;
+ Ctlr* next;
+ Ether* edev;
+ Regs* regs;
+ int active;
+ int started;
+ int inited;
+ int id;
+ int cls;
+ ushort eeprom[0x40];
+
+ QLock alock; /* attach */
+ int nrb; /* how many this Ctlr has in the pool */
+
+ int* nic;
+ Lock imlock;
+ int im; /* interrupt mask */
+
+// Mii* mii;
+// Rendez lrendez;
+ int lim;
+
+ int link;
+
+ QLock slock;
+ uint statistics[Nstatistics];
+ uint lsleep;
+ uint lintr;
+ uint rsleep;
+ uint rintr;
+ int tsleep;
+ uint tintr;
+
+ uchar ra[Eaddrlen]; /* receive address */
+ ulong mta[128]; /* multicast table array */
+
+ Rendez rrendez;
+ int gotinput;
+ int rdcpydone;
+
+ Rendez trendez;
+ int gotoutput;
+ int wrcpydone;
+
+ Lock tlock;
+};
+
+#define csr32r(c, r) (*((c)->nic+((r)/4)))
+#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
+
+static Ctlr *smcctlrhead, *smcctlrtail;
+
+static char* statistics[Nstatistics] = { "dummy", };
+
+static uchar mymac[] = { 0xb0, 0x0f, 0xba, 0xbe, 0x00, 0x00, };
+
+static void etherclock(void);
+static void smcreceive(Ether *edev);
+static void smcinterrupt(Ureg*, void* arg);
+
+static Ether *thisether;
+static int attached;
+
+static void
+smconce(Ether *edev)
+{
+ static int beenhere;
+ static Lock l;
+
+ ilock(&l);
+ if (!beenhere && edev != nil) {
+ beenhere = 1;
+ /* simulate interrupts if we don't know the irq */
+ if (edev->irq < 0) { /* poll as backup */
+ thisether = edev;
+ addclock0link(etherclock, 1000/HZ);
+ iprint(" polling");
+ }
+ }
+ iunlock(&l);
+}
+
+/*
+ * indirect (mac) register access
+ */
+
+static void
+macwait(Regs *regs)
+{
+ long bound;
+
+ for (bound = 400*Mhz; regs->maccsrcmd & Csrbusy && bound > 0; bound--)
+ ;
+ if (bound <= 0)
+ iprint("smc: mac registers didn't come ready\n");
+}
+
+static ulong
+macrd(Regs *regs, uchar index)
+{
+ macwait(regs);
+ regs->maccsrcmd = Csrbusy | Csrread | index;
+ coherence(); /* back-to-back write/read delay per §6.2.1 */
+ macwait(regs);
+ return regs->maccsrdata;
+}
+
+static void
+macwr(Regs *regs, uchar index, ulong val)
+{
+ macwait(regs);
+ regs->maccsrdata = val;
+ regs->maccsrcmd = Csrbusy | index; /* fire */
+ macwait(regs);
+}
+
+
+static long
+smcifstat(Ether* edev, void* a, long n, ulong offset)
+{
+ Ctlr *ctlr;
+ char *p, *s;
+ int i, l, r;
+
+ ctlr = edev->ctlr;
+ qlock(&ctlr->slock);
+ p = malloc(READSTR);
+ l = 0;
+ for(i = 0; i < Nstatistics; i++){
+ // read regs->rxdrop TODO
+ r = 0;
+ if((s = statistics[i]) == nil)
+ continue;
+ switch(i){
+ default:
+ ctlr->statistics[i] += r;
+ if(ctlr->statistics[i] == 0)
+ continue;
+ l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
+ s, ctlr->statistics[i], r);
+ break;
+ }
+ }
+
+ l += snprint(p+l, READSTR-l, "lintr: %ud %ud\n",
+ ctlr->lintr, ctlr->lsleep);
+ l += snprint(p+l, READSTR-l, "rintr: %ud %ud\n",
+ ctlr->rintr, ctlr->rsleep);
+ l += snprint(p+l, READSTR-l, "tintr: %ud %ud\n",
+ ctlr->tintr, ctlr->tsleep);
+
+ l += snprint(p+l, READSTR-l, "eeprom:");
+ for(i = 0; i < 0x40; i++){
+ if(i && ((i & 0x07) == 0))
+ l += snprint(p+l, READSTR-l, "\n ");
+ l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
+ }
+ l += snprint(p+l, READSTR-l, "\n");
+ USED(l);
+
+ n = readstr(offset, a, n, p);
+ free(p);
+ qunlock(&ctlr->slock);
+
+ return n;
+}
+
+static void
+smcpromiscuous(void* arg, int on)
+{
+ int rctl;
+ Ctlr *ctlr;
+ Ether *edev;
+ Regs *regs;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+ regs = ctlr->regs;
+ rctl = macrd(regs, Maccr);
+ if(on)
+ rctl |= Prms;
+ else
+ rctl &= ~Prms;
+ macwr(regs, Maccr, rctl);
+}
+
+static void
+smcmulticast(void*, uchar*, int)
+{
+ /* nothing to do, we allow all multicast packets in */
+}
+
+static int
+iswrcpydone(void *arg)
+{
+ return ((Ctlr *)arg)->wrcpydone;
+}
+
+static int
+smctxstart(Ctlr *ctlr, uchar *ubuf, uint len)
+{
+ uint wds, ruplen;
+ ulong *wdp, *txdp;
+ Regs *regs;
+ static ulong buf[ROUNDUP(ETHERMAXTU, sizeof(ulong)) / sizeof(ulong)];
+
+ if (!ctlr->inited) {
+ iprint("smctxstart: too soon to send\n");
+ return -1; /* toss it */
+ }
+ regs = ctlr->regs;
+
+ /* is there room for a packet in the tx data fifo? */
+ if (len < ETHERMINTU)
+ iprint("sending too-short (%d) pkt\n", len);
+ else if (len > ETHERMAXTU)
+ iprint("sending jumbo (%d) pkt\n", len);
+
+ ruplen = ROUNDUP(len, sizeof(ulong));
+ coherence(); /* back-to-back read/read delay per §6.2.2 */
+ if ((regs->txfifoinf & Txdatafreemask) < ruplen + 2*sizeof(ulong))
+ return -1; /* not enough room for data + command words */
+
+ if ((uintptr)ubuf & MASK(2)) { /* ensure word alignment */
+ memmove(buf, ubuf, len);
+ ubuf = (uchar *)buf;
+ }
+
+ /* tx cmd a: length is bytes in this buffer */
+ txdp = &regs->txdata;
+ *txdp = Intcompl | Firstseg | Lastseg | len;
+ /* tx cmd b: length is bytes in this packet (could be multiple buf.s) */
+ *txdp = len;
+
+ /* shovel pkt into tx fifo, which triggers transmission due to Txon */
+ wdp = (ulong *)ubuf;
+ for (wds = ruplen / sizeof(ulong) + 1; --wds > 0; )
+ *txdp = *wdp++;
+
+ regs->intsts = Txintrs; /* dismiss intr */
+ coherence();
+ regs->inten |= Txintrs;
+ coherence(); /* back-to-back write/read delay per §6.2.1 */
+ return 0;
+}
+
+static void
+smctransmit(Ether* edev)
+{
+ Block *bp;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ if (ctlr == nil)
+ panic("smctransmit: nil ctlr");
+ ilock(&ctlr->tlock);
+ /*
+ * Try to fill the chip's buffers back up, via the tx fifo.
+ */
+ while ((bp = qget(edev->oq)) != nil)
+ if (smctxstart(ctlr, bp->rp, BLEN(bp)) < 0) {
+ qputback(edev->oq, bp); /* retry the block later */
+ iprint("smctransmit: tx data fifo full\n");
+ break;
+ } else
+ freeb(bp);
+ iunlock(&ctlr->tlock);
+}
+
+static void
+smctransmitcall(Ether *edev) /* called from devether.c */
+{
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ ctlr->gotoutput = 1;
+#ifdef USE_KPROCS
+ wakeup(&ctlr->trendez);
+#else
+ smctransmit(edev);
+#endif
+}
+
+static int
+smcrim(void* ctlr)
+{
+ return ((Ctlr*)ctlr)->gotinput;
+}
+
+static void
+smcrproc(void* arg)
+{
+ Ctlr *ctlr;
+ Ether *edev;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+ for(;;){
+ ctlr->rsleep++;
+ sleep(&ctlr->rrendez, smcrim, ctlr);
+
+ /* process any newly-arrived packets and pass to etheriq */
+ ctlr->gotinput = 0;
+ smcreceive(edev);
+ }
+}
+
+static int
+smcgotout(void* ctlr)
+{
+ return ((Ctlr*)ctlr)->gotoutput;
+}
+
+static void
+smctproc(void* arg)
+{
+ Ctlr *ctlr;
+ Ether *edev;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+ for(;;){
+ ctlr->tsleep++;
+ sleep(&ctlr->trendez, smcgotout, ctlr);
+
+ /* process any newly-arrived packets and pass to etheriq */
+ ctlr->gotoutput = 0;
+ smctransmit(edev);
+ }
+}
+
+void gpioirqclr(void);
+
+static void
+smcattach(Ether* edev)
+{
+#ifdef USE_KPROCS
+ char name[KNAMELEN];
+#endif
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ qlock(&ctlr->alock);
+ if(waserror()){
+ qunlock(&ctlr->alock);
+ nexterror();
+ }
+ if (!ctlr->inited) {
+ ctlr->inited = 1;
+#ifdef USE_KPROCS
+ snprint(name, KNAMELEN, "#l%drproc", edev->ctlrno);
+ kproc(name, smcrproc, edev);
+
+ snprint(name, KNAMELEN, "#l%dtproc", edev->ctlrno);
+ kproc(name, smctproc, edev);
+#endif
+
+iprint("smcattach:");
+#ifdef USE_KPROCS
+iprint(" with kprocs");
+#else
+iprint(" no kprocs");
+#endif
+iprint(", no dma");
+ /* can now accept real or simulated interrupts */
+
+ smconce(edev);
+ attached = 1;
+iprint("\n");
+ }
+ qunlock(&ctlr->alock);
+ poperror();
+}
+
+static int
+isrdcpydone(void *arg)
+{
+ return ((Ctlr *)arg)->rdcpydone;
+}
+
+static void
+smcreceive(Ether *edev)
+{
+ uint wds, len, sts;
+ ulong *wdp, *rxdp;
+ Block *bp;
+ Ctlr *ctlr;
+ Regs *regs;
+
+ ctlr = edev->ctlr;
+ regs = ctlr->regs;
+ coherence(); /* back-to-back read/read delay per §6.2.2 */
+ /*
+ * is there a full packet in the rx data fifo?
+ */
+ while (((regs->rxfifoinf & Rxstsusedmask) >> Rxstsusedshift) != 0) {
+ coherence();
+ sts = regs->rxsts; /* pop rx status */
+ if(sts & Rxerr)
+ iprint("smcreceive: rx error\n");
+ len = (sts & Rxpktlenmask) >> Rxpktlenshift;
+ if (len > ETHERMAXTU + Slop)
+ iprint("smcreceive: oversized rx pkt (%d)\n", len);
+ else if (len < ETHERMINTU)
+ iprint("smcreceive: too-short (%d) pkt\n", len);
+ wds = ROUNDUP(len, sizeof(ulong)) / sizeof(ulong);
+ if (wds > 0) {
+ /* copy aligned words from rx fifo into a Block */
+ bp = iallocb(len + sizeof(ulong) /* - 1 */);
+ if (bp == nil)
+ panic("smcreceive: nil Block*");
+
+ /* bp->rp should be 32-byte aligned, more than we need */
+ assert(((uintptr)bp->rp & (sizeof(ulong) - 1)) == 0);
+ wdp = (ulong *)bp->rp;
+ rxdp = &regs->rxdata;
+ wds = ROUNDUP(len, sizeof(ulong)) / sizeof(ulong) + 1;
+ while (--wds > 0)
+ *wdp++ = *rxdp;
+ bp->wp = bp->rp + len;
+
+ /* and push the Block upstream */
+ if (ctlr->inited)
+ etheriq(edev, bp, 1);
+ else
+ freeb(bp);
+
+ regs->intsts = Rxintrs; /* dismiss intr */
+ coherence();
+ regs->inten |= Rxintrs;
+ }
+ coherence();
+ }
+ regs->inten |= Rxintrs;
+ coherence();
+}
+
+/*
+ * disable the stsclr bits in inten and write them to intsts to ack and dismiss
+ * the interrupt source.
+ */
+void
+ackintr(Regs *regs, ulong stsclr)
+{
+ if (stsclr == 0)
+ return;
+
+ regs->inten &= ~stsclr;
+ coherence();
+
+// regs->intsts = stsclr; /* acknowledge & clear intr(s) */
+// coherence();
+}
+
+static void
+smcinterrupt(Ureg*, void* arg)
+{
+ int junk;
+ unsigned intsts, intr;
+ Ctlr *ctlr;
+ Ether *edev;
+ Regs *regs;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+ ilock(&ctlr->imlock);
+ regs = ctlr->regs;
+
+ gpioirqclr();
+
+ coherence(); /* back-to-back read/read delay per §6.2.2 */
+ intsts = regs->intsts;
+ coherence();
+
+ intsts &= ~MASK(3); /* ignore gpio bits */
+ if (0 && intsts == 0) {
+ coherence();
+ iprint("smc: interrupt without a cause; insts %#ux (vs inten %#lux)\n",
+ intsts, regs->inten);
+ }
+
+ intr = intsts & Rxintrs;
+ if(intr) {
+ /* disable interrupt sources; kproc/smcreceive will reenable */
+ ackintr(regs, intr);
+
+ ctlr->rintr++;
+ ctlr->gotinput = 1;
+#ifdef USE_KPROCS
+ wakeup(&ctlr->rrendez);
+#else
+ smcreceive(edev);
+#endif
+ }
+
+ while(((regs->txfifoinf & Txstsusedmask) >> Txstsusedshift) != 0) {
+ /* probably indicates tx completion, just toss it */
+ junk = regs->txsts; /* pop tx sts */
+ USED(junk);
+ coherence();
+ }
+
+ intr = intsts & Txintrs;
+ if (ctlr->gotoutput || intr) {
+ /* disable interrupt sources; kproc/smctransmit will reenable */
+ ackintr(regs, intr);
+
+ ctlr->tintr++;
+ ctlr->gotoutput = 1;
+#ifdef USE_KPROCS
+ wakeup(&ctlr->trendez);
+#else
+ smctransmit(edev);
+#endif
+ }
+
+ iunlock(&ctlr->imlock);
+}
+
+static void
+etherclock(void)
+{
+ smcinterrupt(nil, thisether);
+}
+
+static int
+smcmii(Ctlr *)
+{
+ return 0;
+}
+
+static int
+smcdetach(Ctlr* ctlr)
+{
+ Regs *regs;
+
+ if (ctlr == nil || ctlr->regs == nil)
+ return -1;
+ regs = ctlr->regs;
+ /* verify that it's real by reading a few registers */
+ switch (regs->id) {
+ case Vid9221:
+ break;
+ default:
+ print("smc: unknown chip id %#ux\n", regs->id);
+ return -1;
+ }
+ regs->inten = 0; /* no interrupts */
+ regs->intsts = ~0; /* clear any pending */
+ regs->gptcfg = 0;
+ coherence();
+ regs->rxcfg = Rxdump;
+ regs->txcfg = Txsdump | Txddump;
+ regs->irqcfg &= ~Irqen;
+ coherence();
+ return 0;
+}
+
+static void
+smcshutdown(Ether* ether)
+{
+ smcdetach(ether->ctlr);
+}
+
+static void
+powerwait(Regs *regs)
+{
+ long bound;
+
+ regs->bytetest = 0; /* bring power on */
+ for (bound = 400*Mhz; !(regs->pmtctl & Dready) && bound > 0; bound--)
+ ;
+ if (bound <= 0)
+ iprint("smc: pmtctl didn't come ready\n");
+}
+
+static int
+smcreset(Ctlr* ctlr)
+{
+ int r;
+ Regs *regs;
+ static char zea[Eaddrlen];
+
+ regs = ctlr->regs;
+ powerwait(regs);
+
+ if(smcdetach(ctlr))
+ return -1;
+
+ /* verify that it's real by reading a few registers */
+ switch (regs->id) {
+ case Vid9221:
+ break;
+ default:
+ print("smc: unknown chip id %#ux\n", regs->id);
+ return -1;
+ }
+ if (regs->bytetest != 0x87654321) {
+ print("smc: bytetest reg %#p (%#lux) != 0x87654321\n",
+ &regs->bytetest, regs->bytetest);
+ return -1;
+ }
+
+#ifdef TODO /* read MAC from EEPROM */
+// int ctrl, i, pause, swdpio, txcw;
+ /*
+ * Snarf and set up the receive addresses.
+ * There are 16 addresses. The first should be the MAC address.
+ * The others are cleared and not marked valid (MS bit of Rah).
+ */
+ for(i = Ea; i < Eaddrlen/2; i++){
+ ctlr->ra[2*i] = ctlr->eeprom[i];
+ ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
+ }
+
+ /*
+ * Clear the Multicast Table Array.
+ * It's a 4096 bit vector accessed as 128 32-bit registers.
+ */
+ memset(ctlr->mta, 0, sizeof(ctlr->mta));
+ for(i = 0; i < 128; i++)
+ csr32w(ctlr, Mta+i*4, 0);
+#endif
+ regs->hwcfg |= Mbo;
+
+ /* don't overwrite existing ea */
+// if (memcmp(edev->ea, zea, Eaddrlen) == 0)
+// memmove(edev->ea, ctlr->ra, Eaddrlen);
+
+ r = ctlr->ra[3]<<24 | ctlr->ra[2]<<16 | ctlr->ra[1]<<8 | ctlr->ra[0];
+ macwr(regs, Macaddrl, r);
+ macwr(regs, Macaddrh, ctlr->ra[5]<<8 | ctlr->ra[4]);
+
+ /* turn on the controller */
+ macwr(regs, Maccoe, 0);
+ regs->inten = 0; /* no interrupts yet */
+ regs->intsts = ~0; /* clear any pending */
+ regs->gptcfg = 0;
+ coherence();
+ regs->rxcfg = Rxdump;
+ regs->txcfg = Txsdump | Txddump | Txon;
+ regs->fifoint = 72<<24; /* default values */
+ macwr(regs, Maccr, Rxall | Rcvown | Fdpx | Mcpas | Txen | Rxen);
+ coherence(); /* back-to-back write/read delay per §6.2.1 */
+ regs->irqcfg = 1<<24 | Irqen | Irqpushpull; /* deas for 10µs (linux) */
+ coherence(); /* back-to-back write/read delay per §6.2.1 */
+ regs->inten = Rxintrs | Txintrs;
+ coherence();
+
+ if(smcmii(ctlr) < 0)
+ return -1;
+ return 0;
+}
+
+static void
+smcpci(void)
+{
+ Ctlr *ctlr;
+ static int beenhere;
+
+ if (beenhere)
+ return;
+ beenhere = 1;
+
+ if (probeaddr(PHYSETHER) < 0)
+ return;
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->id = Vid9221<<16 | 0x0424; /* smsc 9221 */
+ ctlr->port = PHYSETHER;
+ ctlr->nic = (int *)PHYSETHER;
+ ctlr->regs = (Regs *)PHYSETHER;
+
+ if(smcreset(ctlr)){
+ free(ctlr);
+ return;
+ }
+ if(smcctlrhead != nil)
+ smcctlrtail->next = ctlr;
+ else
+ smcctlrhead = ctlr;
+ smcctlrtail = ctlr;
+}
+
+static int
+smcpnp(Ether* edev)
+{
+ Ctlr *ctlr;
+ static char zea[Eaddrlen];
+
+ if(smcctlrhead == nil)
+ smcpci();
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = smcctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ ctlr->edev = edev; /* point back to Ether* */
+ edev->port = ctlr->port;
+ edev->irq = 34;
+// TODO: verify speed (100Mb/s) and duplicity (full-duplex)
+ edev->mbps = 100;
+
+ /* don't overwrite existing ea */
+ if (memcmp(edev->ea, zea, Eaddrlen) == 0)
+ memmove(edev->ea, ctlr->ra, Eaddrlen);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ edev->attach = smcattach;
+ edev->transmit = smctransmitcall;
+ edev->interrupt = smcinterrupt;
+ edev->ifstat = smcifstat;
+/* edev->ctl = smcctl; /* no ctl msgs supported */
+
+ edev->arg = edev;
+ edev->promiscuous = smcpromiscuous;
+ edev->multicast = smcmulticast;
+ edev->shutdown = smcshutdown;
+ return 0;
+}
+
+void
+ether9221link(void)
+{
+ addethercard("9221", smcpnp);
+}
diff --git a/sys/src/9/omap/etherif.h b/sys/src/9/omap/etherif.h
new file mode 100755
index 000000000..dbc1721bf
--- /dev/null
+++ b/sys/src/9/omap/etherif.h
@@ -0,0 +1,41 @@
+enum
+{
+ MaxEther = 4,
+ Ntypes = 8,
+};
+
+typedef struct Ether Ether;
+struct Ether {
+ RWlock;
+ ISAConf; /* hardware info */
+
+ int ctlrno;
+ int minmtu;
+ int maxmtu;
+
+ Netif;
+
+ void (*attach)(Ether*); /* filled in by reset routine */
+ void (*detach)(Ether*);
+ void (*transmit)(Ether*);
+ void (*interrupt)(Ureg*, void*);
+ long (*ifstat)(Ether*, void*, long, ulong);
+ long (*ctl)(Ether*, void*, long); /* custom ctl messages */
+ void (*power)(Ether*, int); /* power on/off */
+ void (*shutdown)(Ether*); /* shutdown hardware before reboot */
+
+ void* ctlr;
+ uchar ea[Eaddrlen];
+ void* address;
+ int irq;
+
+ Queue* oq;
+};
+
+extern Block* etheriq(Ether*, Block*, int);
+extern void addethercard(char*, int(*)(Ether*));
+extern ulong ethercrc(uchar*, int);
+extern int parseether(uchar*, char*);
+
+#define NEXT(x, l) (((x)+1)%(l))
+#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
diff --git a/sys/src/9/omap/fns.h b/sys/src/9/omap/fns.h
new file mode 100755
index 000000000..6fe173108
--- /dev/null
+++ b/sys/src/9/omap/fns.h
@@ -0,0 +1,178 @@
+#define checkmmu(a, b)
+#define countpagerefs(a, b)
+
+#include "../port/portfns.h"
+
+extern int led(int, int);
+extern void ledexit(int);
+extern void delay(int);
+extern void _uartputs(char*, int);
+extern int _uartprint(char*, ...);
+
+#pragma varargck argpos _uartprint 1
+
+extern void archreboot(void);
+extern void archreset(void);
+extern void cachedinv(void);
+extern void cachedinvse(void*, int);
+extern void cachedwb(void);
+extern void cachedwbinv(void);
+extern void cachedwbinvse(void*, int);
+extern void cachedwbse(void*, int);
+extern void cacheiinv(void);
+extern void cacheinfo(int level, Memcache *cp);
+extern void cacheuwbinv(void);
+extern uintptr cankaddr(uintptr pa);
+extern void chkmissing(void);
+extern void clockshutdown(void);
+extern int clz(ulong);
+extern int cmpswap(long*, long, long);
+extern void coherence(void);
+extern void configscreengpio(void);
+extern u32int controlget(void);
+extern u32int cpctget(void);
+extern u32int cpidget(void);
+extern ulong cprd(int cp, int op1, int crn, int crm, int op2);
+extern ulong cprdsc(int op1, int crn, int crm, int op2);
+extern void cpuidprint(void);
+extern void cpwr(int cp, int op1, int crn, int crm, int op2, ulong val);
+extern void cpwrsc(int op1, int crn, int crm, int op2, ulong val);
+#define cycles(ip) *(ip) = lcycles()
+extern u32int dacget(void);
+extern void dacput(u32int);
+extern void dmainit(void);
+extern int dmastart(void *, int, void *, int, uint, Rendez *, int *);
+extern void dmatest(void);
+extern u32int farget(void);
+extern ulong fprd(int fpreg);
+extern void fpwr(int fpreg, ulong val);
+extern u32int fsrget(void);
+extern u32int getscr(void);
+extern u32int getpsr(void);
+extern ulong getwayssets(void);
+extern void intrsoff(void);
+extern int isaconfig(char*, int, ISAConf*);
+extern int isdmadone(int);
+extern int ispow2(uvlong);
+extern void kbdenable(void);
+extern void l2cacheuinv(void);
+extern void l2cacheuwb(void);
+extern void l2cacheuwbinv(void);
+extern void lastresortprint(char *buf, long bp);
+extern int log2(ulong);
+extern void machinit(void);
+extern void mmuidmap(uintptr phys, int mbs);
+extern void mmuinvalidate(void); /* 'mmu' or 'tlb'? */
+extern void mmuinvalidateaddr(u32int); /* 'mmu' or 'tlb'? */
+extern void mousectl(Cmdbuf *cb);
+extern u32int pidget(void);
+extern void pidput(u32int);
+extern vlong probeaddr(uintptr);
+extern void procrestore(Proc *);
+extern void procsave(Proc*);
+extern void procsetup(Proc*);
+extern void _reset(void);
+extern void screenclockson(void);
+extern void screeninit(void);
+extern void serialputs(char* s, int n);
+extern void setcachelvl(int);
+extern void setr13(int, u32int*);
+extern int tas(void *);
+extern u32int ttbget(void);
+extern void ttbput(u32int);
+extern void watchdoginit(void);
+
+extern int irqenable(int, void (*)(Ureg*, void*), void*, char*);
+extern int irqdisable(int, void (*)(Ureg*, void*), void*, char*);
+#define intrenable(i, f, a, b, n) irqenable((i), (f), (a), (n))
+#define intrdisable(i, f, a, b, n) irqdisable((i), (f), (a), (n))
+extern void vectors(void);
+extern void vtable(void);
+
+/* dregs, going away */
+extern int inb(int);
+extern void outb(int, int);
+
+/*
+ * Things called in main.
+ */
+extern void archconfinit(void);
+extern void clockinit(void);
+extern int i8250console(void);
+extern void links(void);
+extern void mmuinit(void);
+extern void touser(uintptr);
+extern void trapinit(void);
+
+
+extern int fpiarm(Ureg*);
+extern int fpudevprocio(Proc*, void*, long, uintptr, int);
+extern void fpuinit(void);
+extern void fpunoted(void);
+extern void fpunotify(Ureg*);
+extern void fpuprocrestore(Proc*);
+extern void fpuprocsave(Proc*);
+extern void fpusysprocsetup(Proc*);
+extern void fpusysrfork(Ureg*);
+extern void fpusysrforkchild(Proc*, Ureg*, Proc*);
+extern int fpuemu(Ureg*);
+
+/*
+ * Miscellaneous machine dependent stuff.
+ */
+extern char* getenv(char*, char*, int);
+char* getconf(char*);
+uintptr mmukmap(uintptr, uintptr, usize);
+uintptr mmukunmap(uintptr, uintptr, usize);
+extern void* mmuuncache(void*, usize);
+extern void* ucalloc(usize);
+extern Block* ucallocb(int);
+extern void* ucallocalign(usize size, int align, int span);
+extern void ucfree(void*);
+extern void ucfreeb(Block*);
+
+/*
+ * Things called from port.
+ */
+extern void delay(int); /* only scheddump() */
+extern int islo(void);
+extern void microdelay(int); /* only edf.c */
+extern void evenaddr(uintptr);
+extern void idlehands(void);
+extern void setkernur(Ureg*, Proc*); /* only devproc.c */
+extern void* sysexecregs(uintptr, ulong, int);
+extern void sysprocsetup(Proc*);
+
+/*
+ * PCI stuff.
+ */
+
+int cas32(void*, u32int, u32int);
+int tas32(void*);
+
+#define CASU(p, e, n) cas32((p), (u32int)(e), (u32int)(n))
+#define CASV(p, e, n) cas32((p), (u32int)(e), (u32int)(n))
+#define CASW(addr, exp, new) cas32((addr), (exp), (new))
+#define TAS(addr) tas32(addr)
+
+extern void forkret(void);
+extern int userureg(Ureg*);
+void* vmap(uintptr, usize);
+void vunmap(void*, usize);
+
+extern void kexit(Ureg*);
+
+#define getpgcolor(a) 0
+#define kmapinval()
+
+#define PTR2UINT(p) ((uintptr)(p))
+#define UINT2PTR(i) ((void*)(i))
+
+#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
+
+#define KADDR(pa) UINT2PTR(KZERO | ((uintptr)(pa) & ~KSEGM))
+#define PADDR(va) PTR2UINT(PHYSDRAM | ((uintptr)(va) & ~KSEGM))
+
+#define wave(c) *(ulong *)PHYSCONS = (c)
+
+#define MASK(v) ((1UL << (v)) - 1) /* mask `v' bits wide */
diff --git a/sys/src/9/omap/fpi.c b/sys/src/9/omap/fpi.c
new file mode 100755
index 000000000..f341f2e4a
--- /dev/null
+++ b/sys/src/9/omap/fpi.c
@@ -0,0 +1,300 @@
+/*
+ * Floating Point Interpreter.
+ * shamelessly stolen from an original by ark.
+ */
+#include "fpi.h"
+
+void
+fpiround(Internal *i)
+{
+ unsigned long guard;
+
+ guard = i->l & GuardMask;
+ i->l &= ~GuardMask;
+ if(guard > (LsBit>>1) || (guard == (LsBit>>1) && (i->l & LsBit))){
+ i->l += LsBit;
+ if(i->l & CarryBit){
+ i->l &= ~CarryBit;
+ i->h++;
+ if(i->h & CarryBit){
+ if (i->h & 0x01)
+ i->l |= CarryBit;
+ i->l >>= 1;
+ i->h >>= 1;
+ i->e++;
+ }
+ }
+ }
+}
+
+static void
+matchexponents(Internal *x, Internal *y)
+{
+ int count;
+
+ count = y->e - x->e;
+ x->e = y->e;
+ if(count >= 2*FractBits){
+ x->l = x->l || x->h;
+ x->h = 0;
+ return;
+ }
+ if(count >= FractBits){
+ count -= FractBits;
+ x->l = x->h|(x->l != 0);
+ x->h = 0;
+ }
+ while(count > 0){
+ count--;
+ if(x->h & 0x01)
+ x->l |= CarryBit;
+ if(x->l & 0x01)
+ x->l |= 2;
+ x->l >>= 1;
+ x->h >>= 1;
+ }
+}
+
+static void
+shift(Internal *i)
+{
+ i->e--;
+ i->h <<= 1;
+ i->l <<= 1;
+ if(i->l & CarryBit){
+ i->l &= ~CarryBit;
+ i->h |= 0x01;
+ }
+}
+
+static void
+normalise(Internal *i)
+{
+ while((i->h & HiddenBit) == 0)
+ shift(i);
+}
+
+static void
+renormalise(Internal *i)
+{
+ if(i->e < -2 * FractBits)
+ i->e = -2 * FractBits;
+ while(i->e < 1){
+ i->e++;
+ if(i->h & 0x01)
+ i->l |= CarryBit;
+ i->h >>= 1;
+ i->l = (i->l>>1)|(i->l & 0x01);
+ }
+ if(i->e >= ExpInfinity)
+ SetInfinity(i);
+}
+
+void
+fpinormalise(Internal *x)
+{
+ if(!IsWeird(x) && !IsZero(x))
+ normalise(x);
+}
+
+void
+fpiadd(Internal *x, Internal *y, Internal *i)
+{
+ Internal *t;
+
+ i->s = x->s;
+ if(IsWeird(x) || IsWeird(y)){
+ if(IsNaN(x) || IsNaN(y))
+ SetQNaN(i);
+ else
+ SetInfinity(i);
+ return;
+ }
+ if(x->e > y->e){
+ t = x;
+ x = y;
+ y = t;
+ }
+ matchexponents(x, y);
+ i->e = x->e;
+ i->h = x->h + y->h;
+ i->l = x->l + y->l;
+ if(i->l & CarryBit){
+ i->h++;
+ i->l &= ~CarryBit;
+ }
+ if(i->h & (HiddenBit<<1)){
+ if(i->h & 0x01)
+ i->l |= CarryBit;
+ i->l = (i->l>>1)|(i->l & 0x01);
+ i->h >>= 1;
+ i->e++;
+ }
+ if(IsWeird(i))
+ SetInfinity(i);
+}
+
+void
+fpisub(Internal *x, Internal *y, Internal *i)
+{
+ Internal *t;
+
+ if(y->e < x->e
+ || (y->e == x->e && (y->h < x->h || (y->h == x->h && y->l < x->l)))){
+ t = x;
+ x = y;
+ y = t;
+ }
+ i->s = y->s;
+ if(IsNaN(y)){
+ SetQNaN(i);
+ return;
+ }
+ if(IsInfinity(y)){
+ if(IsInfinity(x))
+ SetQNaN(i);
+ else
+ SetInfinity(i);
+ return;
+ }
+ matchexponents(x, y);
+ i->e = y->e;
+ i->h = y->h - x->h;
+ i->l = y->l - x->l;
+ if(i->l < 0){
+ i->l += CarryBit;
+ i->h--;
+ }
+ if(i->h == 0 && i->l == 0)
+ SetZero(i);
+ else while(i->e > 1 && (i->h & HiddenBit) == 0)
+ shift(i);
+}
+
+#define CHUNK (FractBits/2)
+#define CMASK ((1<<CHUNK)-1)
+#define HI(x) ((short)((x)>>CHUNK) & CMASK)
+#define LO(x) ((short)(x) & CMASK)
+#define SPILL(x) ((x)>>CHUNK)
+#define M(x, y) ((long)a[x]*(long)b[y])
+#define C(h, l) (((long)((h) & CMASK)<<CHUNK)|((l) & CMASK))
+
+void
+fpimul(Internal *x, Internal *y, Internal *i)
+{
+ long a[4], b[4], c[7], f[4];
+
+ i->s = x->s^y->s;
+ if(IsWeird(x) || IsWeird(y)){
+ if(IsNaN(x) || IsNaN(y) || IsZero(x) || IsZero(y))
+ SetQNaN(i);
+ else
+ SetInfinity(i);
+ return;
+ }
+ else if(IsZero(x) || IsZero(y)){
+ SetZero(i);
+ return;
+ }
+ normalise(x);
+ normalise(y);
+ i->e = x->e + y->e - (ExpBias - 1);
+
+ a[0] = HI(x->h); b[0] = HI(y->h);
+ a[1] = LO(x->h); b[1] = LO(y->h);
+ a[2] = HI(x->l); b[2] = HI(y->l);
+ a[3] = LO(x->l); b[3] = LO(y->l);
+
+ c[6] = M(3, 3);
+ c[5] = M(2, 3) + M(3, 2) + SPILL(c[6]);
+ c[4] = M(1, 3) + M(2, 2) + M(3, 1) + SPILL(c[5]);
+ c[3] = M(0, 3) + M(1, 2) + M(2, 1) + M(3, 0) + SPILL(c[4]);
+ c[2] = M(0, 2) + M(1, 1) + M(2, 0) + SPILL(c[3]);
+ c[1] = M(0, 1) + M(1, 0) + SPILL(c[2]);
+ c[0] = M(0, 0) + SPILL(c[1]);
+
+ f[0] = c[0];
+ f[1] = C(c[1], c[2]);
+ f[2] = C(c[3], c[4]);
+ f[3] = C(c[5], c[6]);
+
+ if((f[0] & HiddenBit) == 0){
+ f[0] <<= 1;
+ f[1] <<= 1;
+ f[2] <<= 1;
+ f[3] <<= 1;
+ if(f[1] & CarryBit){
+ f[0] |= 1;
+ f[1] &= ~CarryBit;
+ }
+ if(f[2] & CarryBit){
+ f[1] |= 1;
+ f[2] &= ~CarryBit;
+ }
+ if(f[3] & CarryBit){
+ f[2] |= 1;
+ f[3] &= ~CarryBit;
+ }
+ i->e--;
+ }
+ i->h = f[0];
+ i->l = f[1];
+ if(f[2] || f[3])
+ i->l |= 1;
+ renormalise(i);
+}
+
+void
+fpidiv(Internal *x, Internal *y, Internal *i)
+{
+ i->s = x->s^y->s;
+ if(IsNaN(x) || IsNaN(y)
+ || (IsInfinity(x) && IsInfinity(y)) || (IsZero(x) && IsZero(y))){
+ SetQNaN(i);
+ return;
+ }
+ else if(IsZero(x) || IsInfinity(y)){
+ SetInfinity(i);
+ return;
+ }
+ else if(IsInfinity(x) || IsZero(y)){
+ SetZero(i);
+ return;
+ }
+ normalise(x);
+ normalise(y);
+ i->h = 0;
+ i->l = 0;
+ i->e = y->e - x->e + (ExpBias + 2*FractBits - 1);
+ do{
+ if(y->h > x->h || (y->h == x->h && y->l >= x->l)){
+ i->l |= 0x01;
+ y->h -= x->h;
+ y->l -= x->l;
+ if(y->l < 0){
+ y->l += CarryBit;
+ y->h--;
+ }
+ }
+ shift(y);
+ shift(i);
+ }while ((i->h & HiddenBit) == 0);
+ if(y->h || y->l)
+ i->l |= 0x01;
+ renormalise(i);
+}
+
+int
+fpicmp(Internal *x, Internal *y)
+{
+ if(IsNaN(x) && IsNaN(y))
+ return 0;
+ if(IsInfinity(x) && IsInfinity(y))
+ return y->s - x->s;
+ if(x->e == y->e && x->h == y->h && x->l == y->l)
+ return y->s - x->s;
+ if(x->e < y->e
+ || (x->e == y->e && (x->h < y->h || (x->h == y->h && x->l < y->l))))
+ return y->s ? 1: -1;
+ return x->s ? -1: 1;
+}
diff --git a/sys/src/9/omap/fpi.h b/sys/src/9/omap/fpi.h
new file mode 100755
index 000000000..abaa7c120
--- /dev/null
+++ b/sys/src/9/omap/fpi.h
@@ -0,0 +1,61 @@
+typedef long Word;
+typedef unsigned long Single;
+typedef struct {
+ unsigned long l;
+ unsigned long h;
+} Double;
+
+enum {
+ FractBits = 28,
+ CarryBit = 0x10000000,
+ HiddenBit = 0x08000000,
+ MsBit = HiddenBit,
+ NGuardBits = 3,
+ GuardMask = 0x07,
+ LsBit = (1<<NGuardBits),
+
+ SingleExpBias = 127,
+ SingleExpMax = 255,
+ DoubleExpBias = 1023,
+ DoubleExpMax = 2047,
+
+ ExpBias = DoubleExpBias,
+ ExpInfinity = DoubleExpMax,
+};
+
+typedef struct {
+ unsigned char s;
+ short e;
+ long l; /* 0000FFFFFFFFFFFFFFFFFFFFFFFFFGGG */
+ long h; /* 0000HFFFFFFFFFFFFFFFFFFFFFFFFFFF */
+} Internal;
+
+#define IsWeird(n) ((n)->e >= ExpInfinity)
+#define IsInfinity(n) (IsWeird(n) && (n)->h == HiddenBit && (n)->l == 0)
+#define SetInfinity(n) ((n)->e = ExpInfinity, (n)->h = HiddenBit, (n)->l = 0)
+#define IsNaN(n) (IsWeird(n) && (((n)->h & ~HiddenBit) || (n)->l))
+#define SetQNaN(n) ((n)->s = 0, (n)->e = ExpInfinity, \
+ (n)->h = HiddenBit|(LsBit<<1), (n)->l = 0)
+#define IsZero(n) ((n)->e == 1 && (n)->h == 0 && (n)->l == 0)
+#define SetZero(n) ((n)->e = 1, (n)->h = 0, (n)->l = 0)
+
+/*
+ * fpi.c
+ */
+extern void fpiround(Internal *);
+extern void fpiadd(Internal *, Internal *, Internal *);
+extern void fpisub(Internal *, Internal *, Internal *);
+extern void fpimul(Internal *, Internal *, Internal *);
+extern void fpidiv(Internal *, Internal *, Internal *);
+extern int fpicmp(Internal *, Internal *);
+extern void fpinormalise(Internal*);
+
+/*
+ * fpimem.c
+ */
+extern void fpis2i(Internal *, void *);
+extern void fpid2i(Internal *, void *);
+extern void fpiw2i(Internal *, void *);
+extern void fpii2s(void *, Internal *);
+extern void fpii2d(void *, Internal *);
+extern void fpii2w(Word *, Internal *);
diff --git a/sys/src/9/omap/fpiarm.c b/sys/src/9/omap/fpiarm.c
new file mode 100755
index 000000000..063d10c52
--- /dev/null
+++ b/sys/src/9/omap/fpiarm.c
@@ -0,0 +1,576 @@
+/*
+ * this doesn't attempt to implement ARM floating-point properties
+ * that aren't visible in the Inferno environment.
+ * all arithmetic is done in double precision.
+ * the FP trap status isn't updated.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#include "ureg.h"
+
+#include "arm.h"
+#include "fpi.h"
+
+/* undef this if correct kernel r13 isn't in Ureg;
+ * check calculation in fpiarm below
+ */
+
+
+#define REG(ur, x) (*(long*)(((char*)(ur))+roff[(x)]))
+#define FR(ufp, x) (*(Internal*)(ufp)->regs[(x)&7])
+
+typedef struct FP2 FP2;
+typedef struct FP1 FP1;
+
+struct FP2 {
+ char* name;
+ void (*f)(Internal, Internal, Internal*);
+};
+
+struct FP1 {
+ char* name;
+ void (*f)(Internal*, Internal*);
+};
+
+enum {
+ N = 1<<31,
+ Z = 1<<30,
+ C = 1<<29,
+ V = 1<<28,
+ REGPC = 15,
+};
+
+enum {
+ fpemudebug = 0,
+};
+
+#undef OFR
+#define OFR(X) ((ulong)&((Ureg*)0)->X)
+
+static int roff[] = {
+ OFR(r0), OFR(r1), OFR(r2), OFR(r3),
+ OFR(r4), OFR(r5), OFR(r6), OFR(r7),
+ OFR(r8), OFR(r9), OFR(r10), OFR(r11),
+ OFR(r12), OFR(r13), OFR(r14), OFR(pc),
+};
+
+static Internal fpconst[8] = { /* indexed by op&7 */
+ /* s, e, l, h */
+ {0, 0x1, 0x00000000, 0x00000000}, /* 0.0 */
+ {0, 0x3FF, 0x00000000, 0x08000000}, /* 1.0 */
+ {0, 0x400, 0x00000000, 0x08000000}, /* 2.0 */
+ {0, 0x400, 0x00000000, 0x0C000000}, /* 3.0 */
+ {0, 0x401, 0x00000000, 0x08000000}, /* 4.0 */
+ {0, 0x401, 0x00000000, 0x0A000000}, /* 5.0 */
+ {0, 0x3FE, 0x00000000, 0x08000000}, /* 0.5 */
+ {0, 0x402, 0x00000000, 0x0A000000}, /* 10.0 */
+};
+
+/*
+ * arm binary operations
+ */
+
+static void
+fadd(Internal m, Internal n, Internal *d)
+{
+ (m.s == n.s? fpiadd: fpisub)(&m, &n, d);
+}
+
+static void
+fsub(Internal m, Internal n, Internal *d)
+{
+ m.s ^= 1;
+ (m.s == n.s? fpiadd: fpisub)(&m, &n, d);
+}
+
+static void
+fsubr(Internal m, Internal n, Internal *d)
+{
+ n.s ^= 1;
+ (n.s == m.s? fpiadd: fpisub)(&n, &m, d);
+}
+
+static void
+fmul(Internal m, Internal n, Internal *d)
+{
+ fpimul(&m, &n, d);
+}
+
+static void
+fdiv(Internal m, Internal n, Internal *d)
+{
+ fpidiv(&m, &n, d);
+}
+
+static void
+fdivr(Internal m, Internal n, Internal *d)
+{
+ fpidiv(&n, &m, d);
+}
+
+/*
+ * arm unary operations
+ */
+
+static void
+fmov(Internal *m, Internal *d)
+{
+ *d = *m;
+}
+
+static void
+fmovn(Internal *m, Internal *d)
+{
+ *d = *m;
+ d->s ^= 1;
+}
+
+static void
+fabsf(Internal *m, Internal *d)
+{
+ *d = *m;
+ d->s = 0;
+}
+
+static void
+frnd(Internal *m, Internal *d)
+{
+ short e;
+
+ (m->s? fsub: fadd)(fpconst[6], *m, d);
+ if(IsWeird(d))
+ return;
+ fpiround(d);
+ e = (d->e - ExpBias) + 1;
+ if(e <= 0)
+ SetZero(d);
+ else if(e > FractBits){
+ if(e < 2*FractBits)
+ d->l &= ~((1<<(2*FractBits - e))-1);
+ }else{
+ d->l = 0;
+ if(e < FractBits)
+ d->h &= ~((1<<(FractBits-e))-1);
+ }
+}
+
+static FP1 optab1[16] = { /* Fd := OP Fm */
+[0] {"MOVF", fmov},
+[1] {"NEGF", fmovn},
+[2] {"ABSF", fabsf},
+[3] {"RNDF", frnd},
+[4] {"SQTF", /*fsqt*/0},
+/* LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN all `deprecated' */
+/* URD and NRM aren't implemented */
+};
+
+static FP2 optab2[16] = { /* Fd := Fn OP Fm */
+[0] {"ADDF", fadd},
+[1] {"MULF", fmul},
+[2] {"SUBF", fsub},
+[3] {"RSUBF", fsubr},
+[4] {"DIVF", fdiv},
+[5] {"RDIVF", fdivr},
+/* POW, RPW deprecated */
+[8] {"REMF", /*frem*/0},
+[9] {"FMF", fmul}, /* fast multiply */
+[10] {"FDV", fdiv}, /* fast divide */
+[11] {"FRD", fdivr}, /* fast reverse divide */
+/* POL deprecated */
+};
+
+static ulong
+fcmp(Internal *n, Internal *m)
+{
+ int i;
+ Internal rm, rn;
+
+ if(IsWeird(m) || IsWeird(n)){
+ /* BUG: should trap if not masked */
+ return V|C;
+ }
+ rn = *n;
+ rm = *m;
+ fpiround(&rn);
+ fpiround(&rm);
+ i = fpicmp(&rn, &rm);
+ if(i > 0)
+ return C;
+ else if(i == 0)
+ return C|Z;
+ else
+ return N;
+}
+
+static void
+fld(void (*f)(Internal*, void*), int d, ulong ea, int n, FPsave *ufp)
+{
+ void *mem;
+
+ mem = (void*)ea;
+ (*f)(&FR(ufp, d), mem);
+ if(fpemudebug)
+ print("MOV%c #%lux, F%d\n", n==8? 'D': 'F', ea, d);
+}
+
+static void
+fst(void (*f)(void*, Internal*), ulong ea, int s, int n, FPsave *ufp)
+{
+ Internal tmp;
+ void *mem;
+
+ mem = (void*)ea;
+ tmp = FR(ufp, s);
+ if(fpemudebug)
+ print("MOV%c F%d,#%lux\n", n==8? 'D': 'F', s, ea);
+ (*f)(mem, &tmp);
+}
+
+static int
+condok(int cc, int c)
+{
+ switch(c){
+ case 0: /* Z set */
+ return cc&Z;
+ case 1: /* Z clear */
+ return (cc&Z) == 0;
+ case 2: /* C set */
+ return cc&C;
+ case 3: /* C clear */
+ return (cc&C) == 0;
+ case 4: /* N set */
+ return cc&N;
+ case 5: /* N clear */
+ return (cc&N) == 0;
+ case 6: /* V set */
+ return cc&V;
+ case 7: /* V clear */
+ return (cc&V) == 0;
+ case 8: /* C set and Z clear */
+ return cc&C && (cc&Z) == 0;
+ case 9: /* C clear or Z set */
+ return (cc&C) == 0 || cc&Z;
+ case 10: /* N set and V set, or N clear and V clear */
+ return (~cc&(N|V))==0 || (cc&(N|V)) == 0;
+ case 11: /* N set and V clear, or N clear and V set */
+ return (cc&(N|V))==N || (cc&(N|V))==V;
+ case 12: /* Z clear, and either N set and V set or N clear and V clear */
+ return (cc&Z) == 0 && ((~cc&(N|V))==0 || (cc&(N|V))==0);
+ case 13: /* Z set, or N set and V clear or N clear and V set */
+ return (cc&Z) || (cc&(N|V))==N || (cc&(N|V))==V;
+ case 14: /* always */
+ return 1;
+ case 15: /* never (reserved) */
+ return 0;
+ }
+ return 0; /* not reached */
+}
+
+static void
+unimp(ulong pc, ulong op)
+{
+ char buf[60];
+
+ snprint(buf, sizeof(buf), "sys: fp: pc=%lux unimp fp 0x%.8lux", pc, op);
+ if(fpemudebug)
+ print("FPE: %s\n", buf);
+ error(buf);
+ /* no return */
+}
+
+static void
+fpemu(ulong pc, ulong op, Ureg *ur, FPsave *ufp)
+{
+ int rn, rd, tag, o;
+ long off;
+ ulong ea;
+ Internal tmp, *fm, *fn;
+
+ /* note: would update fault status here if we noted numeric exceptions */
+
+ /*
+ * LDF, STF; 10.1.1
+ */
+ if(((op>>25)&7) == 6){
+ if(op & (1<<22))
+ unimp(pc, op); /* packed or extended */
+ rn = (op>>16)&0xF;
+ off = (op&0xFF)<<2;
+ if((op & (1<<23)) == 0)
+ off = -off;
+ ea = REG(ur, rn);
+ if(rn == REGPC)
+ ea += 8;
+ if(op & (1<<24))
+ ea += off;
+ rd = (op>>12)&7;
+ if(op & (1<<20)){
+ if(op & (1<<15))
+ fld(fpid2i, rd, ea, 8, ufp);
+ else
+ fld(fpis2i, rd, ea, 4, ufp);
+ }else{
+ if(op & (1<<15))
+ fst(fpii2d, ea, rd, 8, ufp);
+ else
+ fst(fpii2s, ea, rd, 4, ufp);
+ }
+ if((op & (1<<24)) == 0)
+ ea += off;
+ if(op & (1<<21))
+ REG(ur, rn) = ea;
+ return;
+ }
+
+ /*
+ * CPRT/transfer, 10.3
+ */
+ if(op & (1<<4)){
+ rd = (op>>12) & 0xF;
+
+ /*
+ * compare, 10.3.1
+ */
+ if(rd == 15 && op & (1<<20)){
+ rn = (op>>16)&7;
+ fn = &FR(ufp, rn);
+ if(op & (1<<3)){
+ fm = &fpconst[op&7];
+ if(fpemudebug)
+ tag = 'C';
+ }else{
+ fm = &FR(ufp, op&7);
+ if(fpemudebug)
+ tag = 'F';
+ }
+ switch((op>>21)&7){
+ default:
+ unimp(pc, op);
+ case 4: /* CMF: Fn :: Fm */
+ case 6: /* CMFE: Fn :: Fm (with exception) */
+ ur->psr &= ~(N|C|Z|V);
+ ur->psr |= fcmp(fn, fm);
+ break;
+ case 5: /* CNF: Fn :: -Fm */
+ case 7: /* CNFE: Fn :: -Fm (with exception) */
+ tmp = *fm;
+ tmp.s ^= 1;
+ ur->psr &= ~(N|C|Z|V);
+ ur->psr |= fcmp(fn, &tmp);
+ break;
+ }
+ if(fpemudebug)
+ print("CMPF %c%d,F%ld =%#lux\n",
+ tag, rn, op&7, ur->psr>>28);
+ return;
+ }
+
+ /*
+ * other transfer, 10.3
+ */
+ switch((op>>20)&0xF){
+ default:
+ unimp(pc, op);
+ case 0: /* FLT */
+ rn = (op>>16) & 7;
+ fpiw2i(&FR(ufp, rn), &REG(ur, rd));
+ if(fpemudebug)
+ print("MOVW[FD] R%d, F%d\n", rd, rn);
+ break;
+ case 1: /* FIX */
+ if(op & (1<<3))
+ unimp(pc, op);
+ rn = op & 7;
+ tmp = FR(ufp, rn);
+ fpii2w(&REG(ur, rd), &tmp);
+ if(fpemudebug)
+ print("MOV[FD]W F%d, R%d =%ld\n", rn, rd, REG(ur, rd));
+ break;
+ case 2: /* FPSR := Rd */
+ ufp->status = REG(ur, rd);
+ if(fpemudebug)
+ print("MOVW R%d, FPSR\n", rd);
+ break;
+ case 3: /* Rd := FPSR */
+ REG(ur, rd) = ufp->status;
+ if(fpemudebug)
+ print("MOVW FPSR, R%d\n", rd);
+ break;
+ case 4: /* FPCR := Rd */
+ ufp->control = REG(ur, rd);
+ if(fpemudebug)
+ print("MOVW R%d, FPCR\n", rd);
+ break;
+ case 5: /* Rd := FPCR */
+ REG(ur, rd) = ufp->control;
+ if(fpemudebug)
+ print("MOVW FPCR, R%d\n", rd);
+ break;
+ }
+ return;
+ }
+
+ /*
+ * arithmetic
+ */
+
+ if(op & (1<<3)){ /* constant */
+ fm = &fpconst[op&7];
+ if(fpemudebug)
+ tag = 'C';
+ }else{
+ fm = &FR(ufp, op&7);
+ if(fpemudebug)
+ tag = 'F';
+ }
+ rd = (op>>12)&7;
+ o = (op>>20)&0xF;
+ if(op & (1<<15)){ /* monadic */
+ FP1 *fp;
+ fp = &optab1[o];
+ if(fp->f == nil)
+ unimp(pc, op);
+ if(fpemudebug)
+ print("%s %c%ld,F%d\n", fp->name, tag, op&7, rd);
+ (*fp->f)(fm, &FR(ufp, rd));
+ } else {
+ FP2 *fp;
+ fp = &optab2[o];
+ if(fp->f == nil)
+ unimp(pc, op);
+ rn = (op>>16)&7;
+ if(fpemudebug)
+ print("%s %c%ld,F%d,F%d\n", fp->name, tag, op&7, rn, rd);
+ (*fp->f)(*fm, FR(ufp, rn), &FR(ufp, rd));
+ }
+}
+
+void
+casemu(ulong pc, ulong op, Ureg *ur)
+{
+ ulong *rp, ro, rn, *rd;
+
+ USED(pc);
+
+ rp = (ulong*)ur;
+ ro = rp[op>>16 & 0x7];
+ rn = rp[op>>0 & 0x7];
+ rd = rp + (op>>12 & 0x7);
+ rp = (ulong*)*rd;
+ validaddr((ulong)rp, 4, 1);
+ splhi();
+ if(*rd = (*rp == ro))
+ *rp = rn;
+ spllo();
+}
+
+int ldrexvalid;
+
+void
+ldrex(ulong pc, ulong op, Ureg *ur)
+{
+ ulong *rp, *rd, *addr;
+
+ USED(pc);
+
+ rp = (ulong*)ur;
+ rd = rp + (op>>16 & 0x7);
+ addr = (ulong*)*rd;
+ validaddr((ulong)addr, 4, 0);
+ ldrexvalid = 1;
+ rp[op>>12 & 0x7] = *addr;
+ if(fpemudebug)
+ print("ldrex, r%ld = [r%ld]@0x%8.8p = 0x%8.8lux",
+ op>>12 & 0x7, op>>16 & 0x7, addr, rp[op>>12 & 0x7]);
+}
+
+void
+strex(ulong pc, ulong op, Ureg *ur)
+{
+ ulong *rp, rn, *rd, *addr;
+
+ USED(pc);
+
+ rp = (ulong*)ur;
+ rd = rp + (op>>16 & 0x7);
+ rn = rp[op>>0 & 0x7];
+ addr = (ulong*)*rd;
+ validaddr((ulong)addr, 4, 1);
+ splhi();
+ if(ldrexvalid){
+ if(fpemudebug)
+ print("strex valid, [r%ld]@0x%8.8p = r%ld = 0x%8.8lux",
+ op>>16 & 0x7, addr, op>>0 & 0x7, rn);
+ *addr = rn;
+ ldrexvalid = 0;
+ rp[op>>12 & 0x7] = 0;
+ }else{
+ if(fpemudebug)
+ print("strex invalid, r%ld = 1", op>>16 & 0x7);
+ rp[op>>12 & 0x7] = 1;
+ }
+ spllo();
+}
+
+struct {
+ ulong opc;
+ ulong mask;
+ void (*f)(ulong, ulong, Ureg*);
+} specialopc[] = {
+ { 0x01900f9f, 0x0ff00fff, ldrex },
+ { 0x01800f90, 0x0ff00ff0, strex },
+ { 0x0ed00100, 0x0ef08100, casemu },
+ { 0x00000000, 0x00000000, nil }
+};
+
+/*
+ * returns the number of FP instructions emulated
+ */
+int
+fpiarm(Ureg *ur)
+{
+ ulong op, o;
+ FPsave *ufp;
+ int i, n;
+
+ if(up == nil)
+ panic("fpiarm not in a process");
+ ufp = &up->fpsave;
+ /* because all the state is in the proc structure,
+ * it need not be saved/restored
+ */
+ if(up->fpstate != FPactive){
+// assert(sizeof(Internal) == sizeof(ufp->regs[0]));
+ up->fpstate = FPactive;
+ ufp->control = 0;
+ ufp->status = (0x01<<28)|(1<<12); /* software emulation, alternative C flag */
+ for(n = 0; n < 8; n++)
+ FR(ufp, n) = fpconst[0];
+ }
+ for(n=0; ;n++){
+ validaddr(ur->pc, 4, 0);
+ op = *(ulong*)(ur->pc);
+ if(fpemudebug)
+ print("%#lux: %#8.8lux ", ur->pc, op);
+ o = (op>>24) & 0xF;
+ if(condok(ur->psr, op>>28)){
+ for(i = 0; specialopc[i].f; i++)
+ if((op & specialopc[i].mask) == specialopc[i].opc)
+ break;
+ if(specialopc[i].f)
+ specialopc[i].f(ur->pc, op, ur);
+ else if((op & 0xF00) != 0x100 || o != 0xE && (o&~1) != 0xC)
+ break;
+ else
+ fpemu(ur->pc, op, ur, ufp);
+ }else if((op & 0xF00) != 0x100 || o != 0xE && (o&~1) != 0xC)
+ break;
+ ur->pc += 4;
+ }
+ if(fpemudebug) print("\n");
+ return n;
+}
diff --git a/sys/src/9/omap/fpimem.c b/sys/src/9/omap/fpimem.c
new file mode 100755
index 000000000..627ab6355
--- /dev/null
+++ b/sys/src/9/omap/fpimem.c
@@ -0,0 +1,136 @@
+#include "fpi.h"
+
+/*
+ * the following routines depend on memory format, not the machine
+ */
+
+void
+fpis2i(Internal *i, void *v)
+{
+ Single *s = v;
+
+ i->s = (*s & 0x80000000) ? 1: 0;
+ if((*s & ~0x80000000) == 0){
+ SetZero(i);
+ return;
+ }
+ i->e = ((*s>>23) & 0x00FF) - SingleExpBias + ExpBias;
+ i->h = (*s & 0x007FFFFF)<<(1+NGuardBits);
+ i->l = 0;
+ if(i->e)
+ i->h |= HiddenBit;
+ else
+ i->e++;
+}
+
+void
+fpid2i(Internal *i, void *v)
+{
+ Double *d = v;
+
+ i->s = (d->h & 0x80000000) ? 1: 0;
+ i->e = (d->h>>20) & 0x07FF;
+ i->h = ((d->h & 0x000FFFFF)<<(4+NGuardBits))|((d->l>>25) & 0x7F);
+ i->l = (d->l & 0x01FFFFFF)<<NGuardBits;
+ if(i->e)
+ i->h |= HiddenBit;
+ else
+ i->e++;
+}
+
+void
+fpiw2i(Internal *i, void *v)
+{
+ Word w, word = *(Word*)v;
+ short e;
+
+ if(word < 0){
+ i->s = 1;
+ word = -word;
+ }
+ else
+ i->s = 0;
+ if(word == 0){
+ SetZero(i);
+ return;
+ }
+ if(word > 0){
+ for (e = 0, w = word; w; w >>= 1, e++)
+ ;
+ } else
+ e = 32;
+ if(e > FractBits){
+ i->h = word>>(e - FractBits);
+ i->l = (word & ((1<<(e - FractBits)) - 1))<<(2*FractBits - e);
+ }
+ else {
+ i->h = word<<(FractBits - e);
+ i->l = 0;
+ }
+ i->e = (e - 1) + ExpBias;
+}
+
+void
+fpii2s(void *v, Internal *i)
+{
+ short e;
+ Single *s = (Single*)v;
+
+ fpiround(i);
+ if(i->h & HiddenBit)
+ i->h &= ~HiddenBit;
+ else
+ i->e--;
+ *s = i->s ? 0x80000000: 0;
+ e = i->e;
+ if(e < ExpBias){
+ if(e <= (ExpBias - SingleExpBias))
+ return;
+ e = SingleExpBias - (ExpBias - e);
+ }
+ else if(e >= (ExpBias + (SingleExpMax-SingleExpBias))){
+ *s |= SingleExpMax<<23;
+ return;
+ }
+ else
+ e = SingleExpBias + (e - ExpBias);
+ *s |= (e<<23)|(i->h>>(1+NGuardBits));
+}
+
+void
+fpii2d(void *v, Internal *i)
+{
+ Double *d = (Double*)v;
+
+ fpiround(i);
+ if(i->h & HiddenBit)
+ i->h &= ~HiddenBit;
+ else
+ i->e--;
+ i->l = ((i->h & GuardMask)<<25)|(i->l>>NGuardBits);
+ i->h >>= NGuardBits;
+ d->h = i->s ? 0x80000000: 0;
+ d->h |= (i->e<<20)|((i->h & 0x00FFFFFF)>>4);
+ d->l = (i->h<<28)|i->l;
+}
+
+void
+fpii2w(Word *word, Internal *i)
+{
+ Word w;
+ short e;
+
+ fpiround(i);
+ e = (i->e - ExpBias) + 1;
+ if(e <= 0)
+ w = 0;
+ else if(e > 31)
+ w = 0x7FFFFFFF;
+ else if(e > FractBits)
+ w = (i->h<<(e - FractBits))|(i->l>>(2*FractBits - e));
+ else
+ w = i->h>>(FractBits-e);
+ if(i->s)
+ w = -w;
+ *word = w;
+}
diff --git a/sys/src/9/omap/init9.s b/sys/src/9/omap/init9.s
new file mode 100755
index 000000000..1d7f2bec3
--- /dev/null
+++ b/sys/src/9/omap/init9.s
@@ -0,0 +1,25 @@
+/*
+ * This is the same as the C programme:
+ *
+ * void
+ * main(char* argv0)
+ * {
+ * startboot(argv0, &argv0);
+ * }
+ *
+ * It is in assembler because SB needs to be
+ * set and doing this in C drags in too many
+ * other routines.
+ */
+TEXT main(SB), 1, $8
+ MOVW $setR12(SB), R12 /* load the SB */
+ MOVW $boot(SB), R0
+
+ ADD $12, R13, R1 /* pointer to 0(FP) */
+
+ MOVW R0, 4(R13) /* pass argc, argv */
+ MOVW R1, 8(R13)
+
+ BL startboot(SB)
+_loop:
+ B _loop
diff --git a/sys/src/9/omap/io.h b/sys/src/9/omap/io.h
new file mode 100755
index 000000000..19afa7670
--- /dev/null
+++ b/sys/src/9/omap/io.h
@@ -0,0 +1,82 @@
+/*
+ * the ``general-purpose'' memory controller.
+ * only works with flash memory.
+ */
+
+enum {
+ /* syscfg bits */
+ Idlemask = MASK(2) << 3,
+ Noidle = 1 << 3,
+
+ /* config bits */
+ Postnandwrites = 1<<0, /* force nand reg. writes to be posted */
+
+ /* indices of cscfg[].cfg[] */
+ Csctl = 1 - 1, /* chip-select signal ctl */
+ Csmap = 7 - 1, /* chip-select addr map cfg */
+
+ /* Csctl bits */
+ Muxadddata = 1 << 9,
+ Devtypemask = MASK(2) << 10,
+ Devtypenor = 0 << 10,
+ Devtypenand = 2 << 10,
+ Devsizemask = 1 << 12,
+ Devsize8 = 0 << 12,
+ Devsize16 = 1 << 12,
+ Writesync = 1 << 27,
+ Readsync = 1 << 29,
+
+ /* Csmap bits */
+ Csvalid = 1 << 6,
+ MB16 = 017 << 8, /* 16MB size */
+ MB128 = 010 << 8, /* 128MB size */
+};
+
+typedef struct Gpmc Gpmc;
+typedef struct Gpmccs Gpmccs;
+
+/*
+ * configuration for non-dram (e.g., flash) memory
+ */
+struct Gpmc { /* hw registers */
+ uchar _pad0[0x10];
+ ulong syscfg;
+ ulong syssts;
+ ulong irqsts;
+ ulong irqenable;
+ uchar _pad1[0x40 - 0x20];
+ ulong tmout_ctl;
+ ulong erraddr;
+ ulong errtype;
+ ulong _pad7;
+ ulong config;
+ ulong sts;
+ uchar _pad2[0x60 - 0x58];
+
+ /* chip-select config */
+ struct Gpmccs {
+ ulong cfg[7];
+ ulong nandcmd;
+ ulong nandaddr;
+ ulong nanddata;
+ ulong _pad6[2];
+ } cscfg[8];
+
+ /* prefetch */
+ ulong prefcfg[2];
+ ulong _pad8;
+ ulong prefctl;
+ ulong prefsts;
+
+ /* ecc */
+ ulong ecccfg;
+ ulong eccctl;
+ ulong eccsize;
+ ulong eccres[9];
+ uchar _pad3[0x240 - 0x224];
+
+ /* bch */
+ ulong bchres[8][4];
+ uchar _pad4[0x2d0 - 0x2c0];
+ ulong bchswdata;
+};
diff --git a/sys/src/9/omap/kbd.c b/sys/src/9/omap/kbd.c
new file mode 100755
index 000000000..e81b352d2
--- /dev/null
+++ b/sys/src/9/omap/kbd.c
@@ -0,0 +1,410 @@
+/*
+ * simulated keyboard input for omap35 with no keyboard (except via uart or usb)
+ *
+ * gutted version of ps2 version from ../pc
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+enum {
+ Spec= 0xF800, /* Unicode private space */
+ PF= Spec|0x20, /* num pad function key */
+ View= Spec|0x00, /* view (shift window up) */
+ KF= 0xF000, /* function key (begin Unicode private space) */
+ Shift= Spec|0x60,
+ Break= Spec|0x61,
+ Ctrl= Spec|0x62,
+ Latin= Spec|0x63,
+ Caps= Spec|0x64,
+ Num= Spec|0x65,
+ Middle= Spec|0x66,
+ Altgr= Spec|0x67,
+ Kmouse= Spec|0x100,
+ No= 0x00, /* peter */
+
+ Home= KF|13,
+ Up= KF|14,
+ Pgup= KF|15,
+ Print= KF|16,
+ Left= KF|17,
+ Right= KF|18,
+ End= KF|24,
+ Down= View,
+ Pgdown= KF|19,
+ Ins= KF|20,
+ Del= 0x7F,
+ Scroll= KF|21,
+
+ Nscan= 128,
+
+ Int= 0, /* kbscans indices */
+ Ext,
+ Nscans,
+};
+
+/*
+ * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard.
+ * A 'standard' keyboard doesn't produce anything above 0x58.
+ */
+Rune kbtab[Nscan] =
+{
+[0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
+[0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
+[0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
+[0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
+[0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+[0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
+[0x30] 'b', 'n', 'm', ',', '.', '/', Shift, '*',
+[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',
+[0x48] '8', '9', '-', '4', '5', '6', '+', '1',
+[0x50] '2', '3', '0', '.', No, No, No, KF|11,
+[0x58] KF|12, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, View, No, Up, No, No, No, No,
+};
+
+Rune kbtabshift[Nscan] =
+{
+[0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
+[0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
+[0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
+[0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
+[0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
+[0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
+[0x30] 'B', 'N', 'M', '<', '>', '?', Shift, '*',
+[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',
+[0x48] '8', '9', '-', '4', '5', '6', '+', '1',
+[0x50] '2', '3', '0', '.', No, No, No, KF|11,
+[0x58] KF|12, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, Up, No, Up, No, No, No, No,
+};
+
+Rune kbtabesc1[Nscan] =
+{
+[0x00] No, No, No, No, No, No, No, No,
+[0x08] No, No, No, No, No, No, No, No,
+[0x10] No, No, No, No, No, No, No, No,
+[0x18] No, No, No, No, '\n', Ctrl, No, No,
+[0x20] No, No, No, No, No, No, No, No,
+[0x28] No, No, Shift, No, No, No, No, No,
+[0x30] No, No, No, No, No, '/', No, Print,
+[0x38] Altgr, No, No, No, No, No, No, No,
+[0x40] No, No, No, No, No, No, Break, Home,
+[0x48] Up, Pgup, No, Left, No, Right, No, End,
+[0x50] Down, Pgdown, Ins, Del, No, No, No, No,
+[0x58] No, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, Up, No, No, No, No, No, No,
+};
+
+Rune kbtabaltgr[Nscan] =
+{
+[0x00] No, No, No, No, No, No, No, No,
+[0x08] No, No, No, No, No, No, No, No,
+[0x10] No, No, No, No, No, No, No, No,
+[0x18] No, No, No, No, '\n', Ctrl, No, No,
+[0x20] No, No, No, No, No, No, No, No,
+[0x28] No, No, Shift, No, No, No, No, No,
+[0x30] No, No, No, No, No, '/', No, Print,
+[0x38] Altgr, No, No, No, No, No, No, No,
+[0x40] No, No, No, No, No, No, Break, Home,
+[0x48] Up, Pgup, No, Left, No, Right, No, End,
+[0x50] Down, Pgdown, Ins, Del, No, No, No, No,
+[0x58] No, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, Up, No, No, No, No, No, No,
+};
+
+Rune kbtabctrl[Nscan] =
+{
+[0x00] No, '', '', '', '', '', '', '',
+[0x08] '', '', '', '', ' ', '', '\b', '\t',
+[0x10] '', '', '', '', '', '', '', '\t',
+[0x18] '', '', '', '', '\n', Ctrl, '', '',
+[0x20] '', '', '', '\b', '\n', ' ', ' ', '',
+[0x28] '', No, Shift, '', '', '', '', '',
+[0x30] '', '', ' ', ' ', '', '', Shift, '\n',
+[0x38] Latin, No, Ctrl, '', '', '', '', '',
+[0x40] '', '', ' ', ' ', '', '', '', '',
+[0x48] '', '', ' ', '', '', '', ' ', '',
+[0x50] '', '', '', '', No, No, No, '',
+[0x58] ' ', No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, '', No, '\b', No, No, No, No,
+};
+
+int mouseshifted;
+void (*kbdmouse)(int);
+
+static int kdebug;
+
+typedef struct Kbscan Kbscan;
+struct Kbscan {
+ int esc1;
+ int esc2;
+ int alt;
+ int altgr;
+ int caps;
+ int ctl;
+ int num;
+ int shift;
+ int collecting;
+ int nk;
+ Rune kc[5];
+ int buttons;
+};
+
+Kbscan kbscans[Nscans]; /* kernel and external scan code state */
+
+/*
+ * Scan code processing
+ */
+void
+kbdputsc(int c, int external)
+{
+ int i, keyup;
+ Kbscan *kbscan;
+
+ if(external)
+ kbscan = &kbscans[Ext];
+ else
+ kbscan = &kbscans[Int];
+
+ if(kdebug)
+ print("sc %x ms %d\n", c, mouseshifted);
+ /*
+ * e0's is the first of a 2 character sequence, e1 the first
+ * of a 3 character sequence (on the safari)
+ */
+ if(c == 0xe0){
+ kbscan->esc1 = 1;
+ return;
+ } else if(c == 0xe1){
+ kbscan->esc2 = 2;
+ return;
+ }
+
+ keyup = c & 0x80;
+ c &= 0x7f;
+ if(c > sizeof kbtab){
+ c |= keyup;
+ if(c != 0xFF) /* these come fairly often: CAPSLOCK U Y */
+ print("unknown key %ux\n", c);
+ return;
+ }
+
+ if(kbscan->esc1){
+ c = kbtabesc1[c];
+ kbscan->esc1 = 0;
+ } else if(kbscan->esc2){
+ kbscan->esc2--;
+ return;
+ } else if(kbscan->shift)
+ c = kbtabshift[c];
+ else if(kbscan->altgr)
+ c = kbtabaltgr[c];
+ else if(kbscan->ctl)
+ c = kbtabctrl[c];
+ else
+ c = kbtab[c];
+
+ if(kbscan->caps && c<='z' && c>='a')
+ c += 'A' - 'a';
+
+ /*
+ * keyup only important for shifts
+ */
+ if(keyup){
+ switch(c){
+ case Latin:
+ kbscan->alt = 0;
+ break;
+ case Shift:
+ kbscan->shift = 0;
+ mouseshifted = 0;
+ if(kdebug)
+ print("shiftclr\n");
+ break;
+ case Ctrl:
+ kbscan->ctl = 0;
+ break;
+ case Altgr:
+ kbscan->altgr = 0;
+ break;
+ case Kmouse|1:
+ case Kmouse|2:
+ case Kmouse|3:
+ case Kmouse|4:
+ case Kmouse|5:
+ kbscan->buttons &= ~(1<<(c-Kmouse-1));
+ if(kbdmouse)
+ kbdmouse(kbscan->buttons);
+ break;
+ }
+ return;
+ }
+
+ /*
+ * normal character
+ */
+ if(!(c & (Spec|KF))){
+ if(kbscan->ctl)
+ if(kbscan->alt && c == Del)
+ exit(0);
+ if(!kbscan->collecting){
+ kbdputc(kbdq, c);
+ return;
+ }
+ kbscan->kc[kbscan->nk++] = c;
+ c = latin1(kbscan->kc, kbscan->nk);
+ if(c < -1) /* need more keystrokes */
+ return;
+ if(c != -1) /* valid sequence */
+ kbdputc(kbdq, c);
+ else /* dump characters */
+ for(i=0; i<kbscan->nk; i++)
+ kbdputc(kbdq, kbscan->kc[i]);
+ kbscan->nk = 0;
+ kbscan->collecting = 0;
+ return;
+ } else {
+ switch(c){
+ case Caps:
+ kbscan->caps ^= 1;
+ return;
+ case Num:
+ kbscan->num ^= 1;
+ return;
+ case Shift:
+ kbscan->shift = 1;
+ if(kdebug)
+ print("shift\n");
+ mouseshifted = 1;
+ return;
+ case Latin:
+ kbscan->alt = 1;
+ /*
+ * VMware and Qemu use Ctl-Alt as the key combination
+ * to make the VM give up keyboard and mouse focus.
+ * This has the unfortunate side effect that when you
+ * come back into focus, Plan 9 thinks you want to type
+ * a compose sequence (you just typed alt).
+ *
+ * As a clumsy hack around this, we look for ctl-alt
+ * and don't treat it as the start of a compose sequence.
+ */
+ if(!kbscan->ctl){
+ kbscan->collecting = 1;
+ kbscan->nk = 0;
+ }
+ return;
+ case Ctrl:
+ kbscan->ctl = 1;
+ return;
+ case Altgr:
+ kbscan->altgr = 1;
+ return;
+ case Kmouse|1:
+ case Kmouse|2:
+ case Kmouse|3:
+ case Kmouse|4:
+ case Kmouse|5:
+ kbscan->buttons |= 1<<(c-Kmouse-1);
+ if(kbdmouse)
+ kbdmouse(kbscan->buttons);
+ return;
+ case KF|11:
+ print("kbd debug on, F12 turns it off\n");
+ kdebug = 1;
+ break;
+ case KF|12:
+ kdebug = 0;
+ break;
+ }
+ }
+ kbdputc(kbdq, c);
+}
+
+void
+kbdenable(void)
+{
+#ifdef notdef
+ kbdq = qopen(4*1024, 0, 0, 0);
+ if(kbdq == nil)
+ panic("kbdinit");
+ qnoblock(kbdq, 1);
+#endif
+ kbscans[Int].num = 0;
+}
+
+void
+kbdputmap(ushort m, ushort scanc, Rune r)
+{
+ if(scanc >= Nscan)
+ error(Ebadarg);
+ switch(m) {
+ default:
+ error(Ebadarg);
+ case 0:
+ kbtab[scanc] = r;
+ break;
+ case 1:
+ kbtabshift[scanc] = r;
+ break;
+ case 2:
+ kbtabesc1[scanc] = r;
+ break;
+ case 3:
+ kbtabaltgr[scanc] = r;
+ break;
+ case 4:
+ kbtabctrl[scanc] = r;
+ break;
+ }
+}
+
+int
+kbdgetmap(uint offset, int *t, int *sc, Rune *r)
+{
+ if ((int)offset < 0)
+ error(Ebadarg);
+ *t = offset/Nscan;
+ *sc = offset%Nscan;
+ switch(*t) {
+ default:
+ return 0;
+ case 0:
+ *r = kbtab[*sc];
+ return 1;
+ case 1:
+ *r = kbtabshift[*sc];
+ return 1;
+ case 2:
+ *r = kbtabesc1[*sc];
+ return 1;
+ case 3:
+ *r = kbtabaltgr[*sc];
+ return 1;
+ case 4:
+ *r = kbtabctrl[*sc];
+ return 1;
+ }
+}
diff --git a/sys/src/9/omap/l.s b/sys/src/9/omap/l.s
new file mode 100755
index 000000000..9950cd2ad
--- /dev/null
+++ b/sys/src/9/omap/l.s
@@ -0,0 +1,569 @@
+/*
+ * ti omap3530 SoC machine assist
+ * arm cortex-a8 processor
+ *
+ * loader uses R11 as scratch.
+ * R9 and R10 are used for `extern register' variables.
+ *
+ * ARM v7 arch. ref. man. §B1.3.3 that we don't need barriers
+ * around moves to CPSR.
+ */
+
+#include "arm.s"
+
+/*
+ * MCR and MRC are counter-intuitively named.
+ * MCR coproc, opcode1, Rd, CRn, CRm[, opcode2] # arm -> coproc
+ * MRC coproc, opcode1, Rd, CRn, CRm[, opcode2] # coproc -> arm
+ */
+
+/*
+ * Entered here from Das U-Boot or another Plan 9 kernel with MMU disabled.
+ * Until the MMU is enabled it is OK to call functions provided
+ * they are within ±32MiB relative and do not require any
+ * local variables or more than one argument (i.e. there is
+ * no stack).
+ */
+TEXT _start(SB), 1, $-4
+ MOVW $setR12(SB), R12 /* load the SB */
+ SUB $KZERO, R12
+ ADD $PHYSDRAM, R12
+
+ /* SVC mode, interrupts disabled */
+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
+ MOVW R1, CPSR
+ BARRIERS
+
+ DELAY(printloopret, 1)
+WAVE('\r')
+ DELAY(printloopnl, 1)
+WAVE('\n')
+ /*
+ * work around errata
+ */
+ MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
+ ORR $(CpACissue1|CpACldstissue1), R1 /* fight omap35x errata 3.1.1.9 */
+ ORR $CpACibe, R1 /* enable cp15 invalidate */
+ ORR $CpACl1pe, R1 /* enable l1 parity checking */
+ ORR $CpCalign, R1 /* catch alignment errors */
+ BIC $CpACasa, R1 /* no speculative accesses */
+ /* go faster with fewer restrictions */
+ BIC $(CpACcachenopipe|CpACcp15serial|CpACcp15waitidle|CpACcp15pipeflush), R1
+ MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
+ ISB
+
+ MRC CpSC, 1, R1, C(CpCLD), C(CpCLDl2), CpCLDl2aux
+ ORR $CpCl2nowralloc, R1 /* fight cortex errata 460075 */
+ ORR $(CpCl2ecc|CpCl2eccparity), R1
+#ifdef TEDIUM
+ /*
+ * I don't know why this clobbers the system, but I'm tired
+ * of arguing with this fussy processor. To hell with it.
+ */
+ MCR CpSC, 1, R1, C(CpCLD), C(CpCLDl2), CpCLDl2aux
+ ISB
+#endif
+ DELAY(printloops, 1)
+WAVE('P')
+ /*
+ * disable the MMU & caches
+ */
+ MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
+ BIC $(CpCdcache|CpCicache|CpCmmu), R1
+ ORR $CpCsbo, R1
+ BIC $CpCsbz, R1
+ MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
+ ISB
+
+ MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
+ BIC $CpACl2en, R1 /* turn l2 cache off */
+ MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
+ ISB
+
+WAVE('l')
+ DELAY(printloop3, 1)
+
+WAVE('a')
+ /* clear Mach */
+ MOVW $PADDR(MACHADDR), R4 /* address of Mach */
+ MOVW $0, R0
+_machZ:
+ MOVW R0, (R4)
+ ADD $4, R4
+ CMP.S $PADDR(L1+L1X(0)), R4 /* end at top-level page table */
+ BNE _machZ
+
+ /*
+ * set up the MMU page table
+ */
+
+WAVE('n')
+ /* clear all PTEs first, to provide a default */
+// MOVW $PADDR(L1+L1X(0)), R4 /* address of PTE for 0 */
+_ptenv0:
+ ZEROPTE()
+ CMP.S $PADDR(L1+16*KiB), R4
+ BNE _ptenv0
+
+ DELAY(printloop4, 2)
+WAVE(' ')
+ /*
+ * set up double map of PHYSDRAM, KZERO to PHYSDRAM for first few MBs,
+ * but only if KZERO and PHYSDRAM differ.
+ */
+ MOVW $PTEDRAM, R2 /* PTE bits */
+ MOVW $PHYSDRAM, R3 /* pa */
+ CMP $KZERO, R3
+ BEQ no2map
+ MOVW $PADDR(L1+L1X(PHYSDRAM)), R4 /* address of PTE for PHYSDRAM */
+ MOVW $DOUBLEMAPMBS, R5
+_ptdbl:
+ FILLPTE()
+ SUB.S $1, R5
+ BNE _ptdbl
+no2map:
+
+ /*
+ * back up and fill in PTEs for memory at KZERO.
+ * beagle has 1 bank of 256MB of SDRAM at PHYSDRAM;
+ * igepv2 has 1 bank of 512MB at PHYSDRAM.
+ * Map the maximum (512MB).
+ */
+WAVE('9')
+ MOVW $PTEDRAM, R2 /* PTE bits */
+ MOVW $PHYSDRAM, R3
+ MOVW $PADDR(L1+L1X(KZERO)), R4 /* start with PTE for KZERO */
+ MOVW $512, R5 /* inner loop count (MBs) */
+_ptekrw: /* set PTEs */
+ FILLPTE()
+ SUB.S $1, R5 /* decrement inner loop count */
+ BNE _ptekrw
+
+ /*
+ * back up and fill in PTEs for MMIO
+ * stop somewhere after uarts
+ */
+WAVE(' ')
+ MOVW $PTEIO, R2 /* PTE bits */
+ MOVW $PHYSIO, R3
+ MOVW $PADDR(L1+L1X(VIRTIO)), R4 /* start with PTE for VIRTIO */
+_ptenv2:
+ FILLPTE()
+ CMP.S $PADDR(L1+L1X(PHYSIOEND)), R4
+ BNE _ptenv2
+
+ /* mmu.c sets up the trap vectors later */
+
+ /*
+ * set up a temporary stack; avoid data & bss segments
+ */
+ MOVW $(PHYSDRAM | (128*1024*1024)), R13
+
+ /* invalidate caches */
+ BL cachedinv(SB)
+ MOVW $KZERO, R0
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
+ ISB
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
+ BARRIERS
+
+WAVE('f')
+ /*
+ * turn caches on
+ */
+ MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
+ ORR $CpACl2en, R1 /* turn l2 cache on */
+ MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
+ BARRIERS
+
+ MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
+ ORR $(CpCdcache|CpCicache), R1
+ MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
+ BARRIERS
+
+WAVE('r')
+ /* set the domain access control */
+ MOVW $Client, R0
+ BL dacput(SB)
+
+ DELAY(printloop5, 2)
+WAVE('o')
+ /* set the translation table base */
+ MOVW $PADDR(L1), R0
+ BL ttbput(SB)
+
+ MOVW $0, R0
+ BL pidput(SB) /* paranoia */
+
+WAVE('m')
+ /*
+ * the little dance to turn the MMU on
+ */
+ BL cacheuwbinv(SB)
+ BL mmuinvalidate(SB)
+ BL mmuenable(SB)
+
+WAVE(' ')
+ /* warp the PC into the virtual map */
+ MOVW $KZERO, R0
+ BL _r15warp(SB)
+
+ /*
+ * now running at KZERO+something!
+ */
+
+ MOVW $setR12(SB), R12 /* reload the SB */
+
+ /*
+ * set up temporary stack again, in case we've just switched
+ * to a new register set.
+ */
+ MOVW $(KZERO|(128*1024*1024)), R13
+
+ /* can now execute arbitrary C code */
+
+ BL cacheuwbinv(SB)
+
+WAVE('B')
+ MOVW $PHYSDRAM, R3 /* pa */
+ CMP $KZERO, R3
+ BEQ no2unmap
+ /* undo double map of PHYSDRAM, KZERO & first few MBs */
+ MOVW $(L1+L1X(PHYSDRAM)), R4 /* addr. of PTE for PHYSDRAM */
+ MOVW $0, R0
+ MOVW $DOUBLEMAPMBS, R5
+_ptudbl:
+ ZEROPTE()
+ SUB.S $1, R5
+ BNE _ptudbl
+no2unmap:
+ BARRIERS
+ MOVW $KZERO, R0
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
+ BARRIERS
+
+#ifdef HIGH_SECURITY /* i.e., not GP omap */
+ /* hack: set `secure monitor' vector base addr for cortex */
+// MOVW $HVECTORS, R0
+ MOVW $PADDR(L1), R0
+ SUB $(MACHSIZE+(2*1024)), R0
+ MCR CpSC, 0, R0, C(CpVECS), C(CpVECSbase), CpVECSmon
+ ISB
+#endif
+
+ /*
+ * call main in C
+ * pass Mach to main and set up the stack in it
+ */
+ MOVW $(MACHADDR), R0 /* Mach */
+ MOVW R0, R13
+ ADD $(MACHSIZE), R13 /* stack pointer */
+ SUB $4, R13 /* space for link register */
+ MOVW R0, R10 /* m = MACHADDR */
+WAVE('e')
+ BL main(SB) /* void main(Mach*) */
+ /*FALLTHROUGH*/
+
+/*
+ * reset the system
+ */
+
+TEXT _reset(SB), 1, $-4
+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R0
+ MOVW R0, CPSR
+ BARRIERS
+
+ DELAY(printloopr, 2)
+WAVE('!')
+WAVE('r')
+WAVE('e')
+WAVE('s')
+WAVE('e')
+WAVE('t')
+WAVE('!')
+WAVE('\r')
+WAVE('\n')
+
+ /* turn the caches off */
+ BL cacheuwbinv(SB)
+
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
+ BIC $(CpCicache|CpCdcache|CpCalign), R0
+ ORR $CpCsw, R0 /* enable SWP */
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
+ BARRIERS
+
+ /* redo double map of PHYSDRAM, KZERO & first few MBs */
+ MOVW $PTEDRAM, R2 /* PTE bits */
+ MOVW $PHYSDRAM, R3 /* pa */
+ MOVW $(L1+L1X(PHYSDRAM)), R4 /* address of PHYSDRAM's PTE */
+ MOVW $DOUBLEMAPMBS, R5
+_ptrdbl:
+ FILLPTE()
+ SUB.S $1, R5
+ BNE _ptrdbl
+
+ MOVW $PHYSDRAM, R0
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
+ BARRIERS
+
+ /* turn the MMU off */
+ MOVW $PHYSDRAM, R0
+ BL _r15warp(SB)
+ BL mmuinvalidate(SB)
+ BL mmudisable(SB)
+
+ /* set new reset vector */
+ MOVW $HVECTORS, R2
+ MOVW $0xe59ff018, R3 /* MOVW 0x18(R15), R15 */
+ MOVW R3, (R2)
+ BARRIERS
+
+// MOVW $PHYSFLASH, R3 /* TODO */
+// MOVW R3, 0x20(R2) /* where $0xe59ff018 jumps to */
+
+ /* ...and jump to it */
+// MOVW R2, R15 /* software reboot */
+_limbo: /* should not get here... */
+ BL idlehands(SB)
+ B _limbo /* ... and can't get out */
+ BL _div(SB) /* hack to load _div, etc. */
+
+TEXT _r15warp(SB), 1, $-4
+ BIC $KSEGM, R14 /* link reg, will become PC */
+ ORR R0, R14
+ BIC $KSEGM, R13 /* SP too */
+ ORR R0, R13
+ RET
+
+/*
+ * `single-element' cache operations.
+ * in arm arch v7, they operate on all cache levels, so separate
+ * l2 functions are unnecessary.
+ */
+
+TEXT cachedwbse(SB), $-4 /* D writeback SE */
+ MOVW R0, R2
+
+ MOVW CPSR, R3
+ CPSID /* splhi */
+
+ BARRIERS /* force outstanding stores to cache */
+ MOVW R2, R0
+ MOVW 4(FP), R1
+ ADD R0, R1 /* R1 is end address */
+ BIC $(CACHELINESZ-1), R0 /* cache line start */
+_dwbse:
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEse
+ /* can't have a BARRIER here since it zeroes R0 */
+ ADD $CACHELINESZ, R0
+ CMP.S R0, R1
+ BGT _dwbse
+ B _wait
+
+TEXT cachedwbinvse(SB), $-4 /* D writeback+invalidate SE */
+ MOVW R0, R2
+
+ MOVW CPSR, R3
+ CPSID /* splhi */
+
+ BARRIERS /* force outstanding stores to cache */
+ MOVW R2, R0
+ MOVW 4(FP), R1
+ ADD R0, R1 /* R1 is end address */
+ BIC $(CACHELINESZ-1), R0 /* cache line start */
+_dwbinvse:
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEse
+ /* can't have a BARRIER here since it zeroes R0 */
+ ADD $CACHELINESZ, R0
+ CMP.S R0, R1
+ BGT _dwbinvse
+_wait: /* drain write buffer */
+ BARRIERS
+ /* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
+ ISB
+
+ MOVW R3, CPSR /* splx */
+ RET
+
+TEXT cachedinvse(SB), $-4 /* D invalidate SE */
+ MOVW R0, R2
+
+ MOVW CPSR, R3
+ CPSID /* splhi */
+
+ BARRIERS /* force outstanding stores to cache */
+ MOVW R2, R0
+ MOVW 4(FP), R1
+ ADD R0, R1 /* R1 is end address */
+ BIC $(CACHELINESZ-1), R0 /* cache line start */
+_dinvse:
+ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEse
+ /* can't have a BARRIER here since it zeroes R0 */
+ ADD $CACHELINESZ, R0
+ CMP.S R0, R1
+ BGT _dinvse
+ B _wait
+
+/*
+ * enable mmu and high vectors
+ */
+TEXT mmuenable(SB), 1, $-4
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
+ ORR $(CpChv|CpCmmu), R0
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
+ BARRIERS
+ RET
+
+TEXT mmudisable(SB), 1, $-4
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
+ BIC $(CpChv|CpCmmu), R0
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
+ BARRIERS
+ RET
+
+/*
+ * If one of these MCR instructions crashes or hangs the machine,
+ * check your Level 1 page table (at TTB) closely.
+ */
+TEXT mmuinvalidate(SB), $-4 /* invalidate all */
+ MOVW CPSR, R2
+ CPSID /* interrupts off */
+
+ BARRIERS
+ MOVW PC, R0 /* some valid virtual address */
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
+ BARRIERS
+ MOVW R2, CPSR /* interrupts restored */
+ RET
+
+TEXT mmuinvalidateaddr(SB), $-4 /* invalidate single entry */
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinvse
+ BARRIERS
+ RET
+
+TEXT cpidget(SB), 1, $-4 /* main ID */
+ MRC CpSC, 0, R0, C(CpID), C(0), CpIDid
+ RET
+
+TEXT cpctget(SB), 1, $-4 /* cache type */
+ MRC CpSC, 0, R0, C(CpID), C(0), CpIDct
+ RET
+
+TEXT controlget(SB), 1, $-4 /* control */
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
+ RET
+
+TEXT ttbget(SB), 1, $-4 /* translation table base */
+ MRC CpSC, 0, R0, C(CpTTB), C(0), CpTTB0
+ RET
+
+TEXT ttbput(SB), 1, $-4 /* translation table base */
+ MCR CpSC, 0, R0, C(CpTTB), C(0), CpTTB0
+ MCR CpSC, 0, R0, C(CpTTB), C(0), CpTTB1 /* cortex has two */
+ ISB
+ RET
+
+TEXT dacget(SB), 1, $-4 /* domain access control */
+ MRC CpSC, 0, R0, C(CpDAC), C(0)
+ RET
+
+TEXT dacput(SB), 1, $-4 /* domain access control */
+ MCR CpSC, 0, R0, C(CpDAC), C(0)
+ ISB
+ RET
+
+TEXT fsrget(SB), 1, $-4 /* fault status */
+ MRC CpSC, 0, R0, C(CpFSR), C(0)
+ RET
+
+TEXT farget(SB), 1, $-4 /* fault address */
+ MRC CpSC, 0, R0, C(CpFAR), C(0x0)
+ RET
+
+TEXT getpsr(SB), 1, $-4
+ MOVW CPSR, R0
+ RET
+
+TEXT getscr(SB), 1, $-4
+ MRC CpSC, 0, R0, C(CpCONTROL), C(CpCONTROLscr), CpSCRscr
+ RET
+
+TEXT pidget(SB), 1, $-4 /* address translation pid */
+ MRC CpSC, 0, R0, C(CpPID), C(0x0)
+ RET
+
+TEXT pidput(SB), 1, $-4 /* address translation pid */
+ MCR CpSC, 0, R0, C(CpPID), C(0x0)
+ ISB
+ RET
+
+TEXT splhi(SB), 1, $-4
+ MOVW CPSR, R0
+ CPSID /* turn off interrupts */
+
+ MOVW $(MACHADDR+4), R2 /* save caller pc in Mach */
+ MOVW R14, 0(R2)
+ RET
+
+TEXT spllo(SB), 1, $-4 /* start marker for devkprof.c */
+ MOVW CPSR, R0
+ CPSIE
+ RET
+
+TEXT splx(SB), 1, $-4
+ MOVW $(MACHADDR+0x04), R2 /* save caller pc in Mach */
+ MOVW R14, 0(R2)
+
+ MOVW CPSR, R3
+ MOVW R0, CPSR /* reset interrupt level */
+ MOVW R3, R0 /* must return old CPSR */
+ RET
+
+TEXT spldone(SB), 1, $0 /* end marker for devkprof.c */
+ RET
+
+TEXT islo(SB), 1, $-4
+ MOVW CPSR, R0
+ AND $(PsrDirq), R0
+ EOR $(PsrDirq), R0
+ RET
+
+TEXT tas(SB), $-4
+TEXT _tas(SB), $-4
+ MOVW R0,R1
+ MOVW $1,R0
+ SWPW R0,(R1) /* fix: deprecated in armv7 */
+ RET
+
+TEXT clz(SB), $-4
+ CLZ(0, 0) /* 0 is R0 */
+ RET
+
+TEXT setlabel(SB), 1, $-4
+ MOVW R13, 0(R0) /* sp */
+ MOVW R14, 4(R0) /* pc */
+ MOVW $0, R0
+ RET
+
+TEXT gotolabel(SB), 1, $-4
+ MOVW 0(R0), R13 /* sp */
+ MOVW 4(R0), R14 /* pc */
+ MOVW $1, R0
+ RET
+
+TEXT getcallerpc(SB), 1, $-4
+ MOVW 0(R13), R0
+ RET
+
+TEXT idlehands(SB), $-4
+ BARRIERS
+ WFI
+ RET
+
+TEXT coherence(SB), $-4
+ BARRIERS
+ RET
+
+#include "cache.v7.s"
diff --git a/sys/src/9/omap/lexception.s b/sys/src/9/omap/lexception.s
new file mode 100755
index 000000000..e3f330653
--- /dev/null
+++ b/sys/src/9/omap/lexception.s
@@ -0,0 +1,187 @@
+/*
+ * arm exception handlers
+ */
+#include "arm.s"
+
+#undef B /* B is for 'botch' */
+
+/*
+ * exception vectors, copied by trapinit() to somewhere useful
+ */
+TEXT vectors(SB), 1, $-4
+ MOVW 0x18(R15), R15 /* reset */
+ MOVW 0x18(R15), R15 /* undefined instr. */
+ MOVW 0x18(R15), R15 /* SWI & SMC */
+ MOVW 0x18(R15), R15 /* prefetch abort */
+ MOVW 0x18(R15), R15 /* data abort */
+ MOVW 0x18(R15), R15 /* reserved */
+ MOVW 0x18(R15), R15 /* IRQ */
+ MOVW 0x18(R15), R15 /* FIQ */
+
+TEXT vtable(SB), 1, $-4
+ WORD $_vsvc(SB) /* reset, in svc mode already */
+ WORD $_vund(SB) /* undefined, switch to svc mode */
+ WORD $_vsvc(SB) /* swi, in svc mode already */
+ WORD $_vpabt(SB) /* prefetch abort, switch to svc mode */
+ WORD $_vdabt(SB) /* data abort, switch to svc mode */
+ WORD $_vsvc(SB) /* reserved */
+ WORD $_virq(SB) /* IRQ, switch to svc mode */
+// WORD $_vfiq(SB) /* FIQ, switch to svc mode */
+ WORD $_virq(SB) /* FIQ, switch to svc mode */
+
+TEXT _vrst(SB), 1, $-4
+ BL _reset(SB)
+
+TEXT _vsvc(SB), 1, $-4 /* SWI */
+ MOVW.W R14, -4(R13) /* ureg->pc = interrupted PC */
+ MOVW SPSR, R14 /* ureg->psr = SPSR */
+ MOVW.W R14, -4(R13) /* ... */
+ MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */
+ MOVW.W R14, -4(R13) /* ... */
+
+ /* avoid the ambiguity described in notes/movm.w. */
+// MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */
+ MOVM.DB.S [R0-R14], (R13) /* save user level registers */
+ SUB $(15*4), R13 /* r13 now points to ureg */
+
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+
+// MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */
+ MOVW $(L1-MACHSIZE), R10 /* m */
+ MOVW 8(R10), R9 /* up */
+
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $8, R13 /* space for argument+link */
+
+ BL syscall(SB)
+
+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT _vund(SB), 1, $-4 /* undefined */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMund, R0
+ B _vswitch
+
+TEXT _vpabt(SB), 1, $-4 /* prefetch abort */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMabt, R0 /* r0 = type */
+ B _vswitch
+
+TEXT _vdabt(SB), 1, $-4 /* data abort */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $(PsrMabt+1), R0 /* r0 = type */
+ B _vswitch
+
+TEXT _virq(SB), 1, $-4 /* IRQ */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMirq, R0 /* r0 = type */
+ B _vswitch
+
+ /*
+ * come here with type in R0 and R13 pointing above saved [r0-r4].
+ * we'll switch to SVC mode and then call trap.
+ */
+_vswitch:
+ MOVW SPSR, R1 /* save SPSR for ureg */
+ MOVW R14, R2 /* save interrupted pc for ureg */
+ MOVW R13, R3 /* save pointer to where the original [R0-R4] are */
+
+ /*
+ * switch processor to svc mode. this switches the banked registers
+ * (r13 [sp] and r14 [link]) to those of svc mode.
+ */
+ MOVW CPSR, R14
+ BIC $PsrMask, R14
+ ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
+ MOVW R14, CPSR /* switch! */
+
+ AND.S $0xf, R1, R4 /* interrupted code kernel or user? */
+ BEQ _userexcep
+
+ /* here for trap from SVC mode */
+ MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
+ MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
+
+ /*
+ * avoid the ambiguity described in notes/movm.w.
+ * In order to get a predictable value in R13 after the stores,
+ * separate the store-multiple from the stack-pointer adjustment.
+ * We'll assume that the old value of R13 should be stored on the stack.
+ */
+ /* save kernel level registers, at end r13 points to ureg */
+// MOVM.DB.W [R0-R14], (R13)
+ MOVM.DB [R0-R14], (R13)
+ SUB $(15*4), R13 /* SP now points to saved R0 */
+
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $(4*2), R13 /* space for argument+link (for debugger) */
+ MOVW $0xdeaddead, R11 /* marker */
+
+ BL trap(SB)
+
+ ADD $(4*2+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+
+ MOVM.DB (R13), [R0-R14] /* restore registers */
+
+ ADD $(4*2), R13 /* pop past ureg->{type+psr} to pc */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+ /* here for trap from USER mode */
+_userexcep:
+ MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
+ MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
+
+ /* avoid the ambiguity described in notes/movm.w. */
+// MOVM.DB.W.S [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
+ MOVM.DB.S [R0-R14], (R13) /* save kernel level registers */
+ SUB $(15*4), R13 /* r13 now points to ureg */
+
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+
+// MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */
+ MOVW $(L1-MACHSIZE), R10 /* m */
+ MOVW 8(R10), R9 /* up */
+
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $(4*2), R13 /* space for argument+link (for debugger) */
+
+ BL trap(SB)
+
+ ADD $(4*2+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $(4*2), R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT _vfiq(SB), 1, $-4 /* FIQ */
+ RFE /* FIQ is special, ignore it for now */
+
+/*
+ * set the stack value for the mode passed in R0
+ */
+TEXT setr13(SB), 1, $-4
+ MOVW 4(FP), R1
+
+ MOVW CPSR, R2
+ BIC $PsrMask, R2, R3
+ ORR R0, R3
+ MOVW R3, CPSR /* switch to new mode */
+
+ MOVW R13, R0 /* return old sp */
+ MOVW R1, R13 /* install new one */
+
+ MOVW R2, CPSR /* switch back to old mode */
+ RET
diff --git a/sys/src/9/omap/lproc.s b/sys/src/9/omap/lproc.s
new file mode 100755
index 000000000..0b4eac238
--- /dev/null
+++ b/sys/src/9/omap/lproc.s
@@ -0,0 +1,47 @@
+#include "mem.h"
+#include "arm.h"
+
+/*
+ * This is the first jump from kernel to user mode.
+ * Fake a return from interrupt.
+ *
+ * Enter with R0 containing the user stack pointer.
+ * UTZERO + 0x20 is always the entry point.
+ *
+ */
+TEXT touser(SB), 1, $-4
+ /* store the user stack pointer into the USR_r13 */
+ MOVM.DB.W [R0], (R13)
+ /* avoid the ambiguity described in notes/movm.w. */
+// MOVM.S.IA.W (R13), [R13]
+ MOVM.S (R13), [R13]
+ ADD $4, R13
+
+ /* set up a PSR for user level */
+ MOVW $(PsrMusr), R0
+ MOVW R0, SPSR
+
+ /* save the PC on the stack */
+ MOVW $(UTZERO+0x20), R0
+ MOVM.DB.W [R0], (R13)
+
+ /*
+ * note that 5a's RFE is not the v6 arch. instruction (0xe89d0a00,
+ * I think), which loads CPSR from the word after the PC at (R13),
+ * but rather the pre-v6 simulation `MOVM.IA.S.W (R13), [R15]'
+ * (0xe8fd8000 since MOVM is LDM in this case), which loads CPSR
+ * not from memory but from SPSR due to `.S'.
+ */
+ RFE
+
+/*
+ * here to jump to a newly forked process
+ */
+TEXT forkret(SB), 1, $-4
+ ADD $(4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
diff --git a/sys/src/9/omap/main.c b/sys/src/9/omap/main.c
new file mode 100755
index 000000000..6f04f765a
--- /dev/null
+++ b/sys/src/9/omap/main.c
@@ -0,0 +1,698 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "init.h"
+#include <pool.h>
+
+#include "reboot.h"
+
+/*
+ * Where configuration info is left for the loaded programme.
+ * This will turn into a structure as more is done by the boot loader
+ * (e.g. why parse the .ini file twice?).
+ * There are 3584 bytes available at CONFADDR.
+ */
+#define BOOTARGS ((char*)CONFADDR)
+#define BOOTARGSLEN (16*KiB) /* limit in devenv.c */
+#define MAXCONF 64
+#define MAXCONFLINE 160
+
+enum {
+ Minmem = 256*MB, /* conservative default */
+};
+
+#define isascii(c) ((uchar)(c) > 0 && (uchar)(c) < 0177)
+
+uintptr kseg0 = KZERO;
+Mach* machaddr[MAXMACH];
+
+/*
+ * Option arguments from the command line.
+ * oargv[0] is the boot file.
+ * Optionsinit() is called from multiboot()
+ * or some other machine-dependent place
+ * to set it all up.
+ */
+static int oargc;
+static char* oargv[20];
+static char oargb[128];
+static int oargblen;
+static char oenv[4096];
+
+static uintptr sp; /* XXX - must go - user stack of init proc */
+
+int vflag;
+int normalprint;
+char debug[256];
+
+/* store plan9.ini contents here at least until we stash them in #ec */
+static char confname[MAXCONF][KNAMELEN];
+static char confval[MAXCONF][MAXCONFLINE];
+static int nconf;
+
+static int
+findconf(char *name)
+{
+ int i;
+
+ for(i = 0; i < nconf; i++)
+ if(cistrcmp(confname[i], name) == 0)
+ return i;
+ return -1;
+}
+
+char*
+getconf(char *name)
+{
+ int i;
+
+ i = findconf(name);
+ if(i >= 0)
+ return confval[i];
+ return nil;
+}
+
+void
+addconf(char *name, char *val)
+{
+ int i;
+
+ i = findconf(name);
+ if(i < 0){
+ if(val == nil || nconf >= MAXCONF)
+ return;
+ i = nconf++;
+ strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
+ }
+// confval[i] = val;
+ strecpy(confval[i], confval[i]+sizeof(confval[i]), val);
+}
+
+static void
+writeconf(void)
+{
+ char *p, *q;
+ int n;
+
+ p = getconfenv();
+
+ if(waserror()) {
+ free(p);
+ nexterror();
+ }
+
+ /* convert to name=value\n format */
+ for(q=p; *q; q++) {
+ q += strlen(q);
+ *q = '=';
+ q += strlen(q);
+ *q = '\n';
+ }
+ n = q - p + 1;
+ if(n >= BOOTARGSLEN)
+ error("kernel configuration too large");
+ memmove(BOOTARGS, p, n);
+ memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);
+ poperror();
+ free(p);
+}
+
+/*
+ * assumes that we have loaded our /cfg/pxe/mac file at 0x1000 with
+ * tftp in u-boot. no longer uses malloc, so can be called early.
+ */
+static void
+plan9iniinit(void)
+{
+ char *k, *v, *next;
+
+ k = (char *)CONFADDR;
+ if(!isascii(*k))
+ return;
+
+ for(; k && *k != '\0'; k = next) {
+ if (!isascii(*k)) /* sanity check */
+ break;
+ next = strchr(k, '\n');
+ if (next)
+ *next++ = '\0';
+
+ if (*k == '\0' || *k == '\n' || *k == '#')
+ continue;
+ v = strchr(k, '=');
+ if(v == nil)
+ continue; /* mal-formed line */
+ *v++ = '\0';
+
+ addconf(k, v);
+ }
+}
+
+static void
+optionsinit(char* s)
+{
+ char *o;
+
+ strcpy(oenv, "");
+ o = strecpy(oargb, oargb+sizeof(oargb), s)+1;
+ if(getenv("bootargs", o, o - oargb) != nil)
+ *(o-1) = ' ';
+
+ oargblen = strlen(oargb);
+ oargc = tokenize(oargb, oargv, nelem(oargv)-1);
+ oargv[oargc] = nil;
+}
+
+char*
+getenv(char* name, char* buf, int n)
+{
+ char *e, *p, *q;
+
+ p = oenv;
+ while(*p != 0){
+ if((e = strchr(p, '=')) == nil)
+ break;
+ for(q = name; p < e; p++){
+ if(*p != *q)
+ break;
+ q++;
+ }
+ if(p == e && *q == 0){
+ strecpy(buf, buf+n, e+1);
+ return buf;
+ }
+ p += strlen(p)+1;
+ }
+
+ return nil;
+}
+
+void
+main(void)
+{
+// int i;
+ extern char bdata[], edata[], end[], etext[];
+ static ulong vfy = 0xcafebabe;
+
+ /* l.s has already printed "Plan 9 from Be" */
+// m = mach; /* now done in l.s */
+
+ /* realign data seg; apparently -H0 -R4096 does not pad the text seg */
+ if (vfy != 0xcafebabe) {
+// wave('<'); wave('-');
+ memmove(bdata, etext, edata - bdata);
+ }
+ /*
+ * once data segment is in place, always zero bss since we may
+ * have been loaded by another Plan 9 kernel.
+ */
+ memset(edata, 0, end - edata); /* zero BSS */
+ cacheuwbinv();
+ l2cacheuwbinv();
+
+ if (vfy != 0xcafebabe)
+ panic("data segment misaligned");
+ vfy = 0;
+
+wave('l');
+ machinit();
+ mmuinit();
+
+ optionsinit("/boot/boot boot");
+ quotefmtinstall();
+
+ /* want plan9.ini to be able to affect memory sizing in confinit */
+ plan9iniinit(); /* before we step on plan9.ini in low memory */
+
+ trapinit(); /* so confinit can probe memory to size it */
+ confinit(); /* figures out amount of memory */
+ /* xinit prints (if it can), so finish up the banner here. */
+ delay(500);
+ iprint("l Labs\n\n");
+ delay(500);
+ xinit();
+
+ mainmem->flags |= POOL_ANTAGONISM /* | POOL_PARANOIA */ ;
+
+ /*
+ * Printinit will cause the first malloc call.
+ * (printinit->qopen->malloc) unless any of the
+ * above (like clockinit) do an irqenable, which
+ * will call malloc.
+ * If the system dies here it's probably due
+ * to malloc(->xalloc) not being initialised
+ * correctly, or the data segment is misaligned
+ * (it's amazing how far you can get with
+ * things like that completely broken).
+ *
+ * (Should be) boilerplate from here on.
+ */
+
+ archreset(); /* configure clock signals */
+ clockinit(); /* start clocks */
+ timersinit();
+ watchdoginit();
+
+ delay(250); /* let uart catch up */
+ printinit();
+ kbdenable();
+
+ cpuidprint();
+// chkmissing();
+
+ procinit0();
+ initseg();
+
+ dmainit();
+ links();
+ conf.monitor = 1;
+ screeninit();
+ chandevreset(); /* most devices are discovered here */
+
+// i8250console(); /* too early; see init0 */
+
+ pageinit();
+ swapinit();
+ userinit();
+ schedinit();
+}
+
+void
+machinit(void)
+{
+ if (m == 0)
+ wave('?');
+// memset(m, 0, sizeof(Mach)); /* done by l.s, now contains stack */
+ m->machno = 0;
+ machaddr[m->machno] = m;
+
+ m->ticks = 1;
+ m->perf.period = 1;
+
+ conf.nmach = 1;
+
+ active.machs = 1;
+ active.exiting = 0;
+
+ up = nil;
+}
+
+static void
+shutdown(int ispanic)
+{
+ int ms, once;
+
+ lock(&active);
+ if(ispanic)
+ active.ispanic = ispanic;
+ else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
+ active.ispanic = 0;
+ once = active.machs & (1<<m->machno);
+ active.machs &= ~(1<<m->machno);
+ active.exiting = 1;
+ unlock(&active);
+
+ if(once)
+ iprint("cpu%d: exiting\n", m->machno);
+ spllo();
+ for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
+ delay(TK2MS(2));
+ if(active.machs == 0 && consactive() == 0)
+ break;
+ }
+ delay(1000);
+}
+
+/*
+ * exit kernel either on a panic or user request
+ */
+void
+exit(int code)
+{
+ shutdown(code);
+ splhi();
+ archreboot();
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ char cc[32], *p;
+ int i;
+
+ snprint(cc, sizeof cc, "%s%d", class, ctlrno);
+ p = getconf(cc);
+ if(p == nil)
+ return 0;
+
+ isa->type = "";
+ isa->nopt = tokenize(p, isa->opt, NISAOPT);
+ for(i = 0; i < isa->nopt; i++){
+ p = isa->opt[i];
+ if(cistrncmp(p, "type=", 5) == 0)
+ isa->type = p + 5;
+ else if(cistrncmp(p, "port=", 5) == 0)
+ isa->port = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "irq=", 4) == 0)
+ isa->irq = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "dma=", 4) == 0)
+ isa->dma = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "mem=", 4) == 0)
+ isa->mem = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "size=", 5) == 0)
+ isa->size = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "freq=", 5) == 0)
+ isa->freq = strtoul(p+5, &p, 0);
+ }
+ return 1;
+}
+
+/*
+ * the new kernel is already loaded at address `code'
+ * of size `size' and entry point `entry'.
+ */
+void
+reboot(void *entry, void *code, ulong size)
+{
+ void (*f)(ulong, ulong, ulong);
+
+ print("starting reboot...");
+ writeconf();
+ shutdown(0);
+
+ /*
+ * should be the only processor running now
+ */
+
+ print("reboot entry %#lux code %#lux size %ld\n",
+ PADDR(entry), PADDR(code), size);
+ delay(100);
+
+ /* turn off buffered serial console */
+ serialoq = nil;
+ kprintoq = nil;
+ screenputs = nil;
+
+ /* shutdown devices */
+ chandevshutdown();
+
+ /* call off the dog */
+ clockshutdown();
+
+ splhi();
+ intrsoff();
+
+ /* setup reboot trampoline function */
+ f = (void*)REBOOTADDR;
+ memmove(f, rebootcode, sizeof(rebootcode));
+ cacheuwbinv();
+ l2cacheuwbinv();
+
+ /* off we go - never to return */
+ (*f)(PADDR(entry), PADDR(code), size);
+
+ iprint("loaded kernel returned!\n");
+ delay(1000);
+ archreboot();
+}
+
+/*
+ * starting place for first process
+ */
+void
+init0(void)
+{
+ int i;
+ char buf[2*KNAMELEN];
+
+ up->nerrlab = 0;
+ coherence();
+ spllo();
+
+ /*
+ * These are o.k. because rootinit is null.
+ * Then early kproc's will have a root and dot.
+ */
+ up->slash = namec("#/", Atodir, 0, 0);
+ pathclose(up->slash->path);
+ up->slash->path = newpath("/");
+ up->dot = cclone(up->slash);
+
+ dmatest(); /* needs `up' set, so can't do it earlier */
+ chandevinit();
+ i8250console(); /* might be redundant, but harmless */
+ if(kbdq == nil)
+ panic("init0: nil kbdq");
+ if(serialoq == nil)
+ panic("init0: nil serialoq");
+ normalprint = 1;
+
+ if(!waserror()){
+ snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
+ ksetenv("terminal", buf, 0);
+ ksetenv("cputype", "arm", 0);
+ if(cpuserver)
+ ksetenv("service", "cpu", 0);
+ else
+ ksetenv("service", "terminal", 0);
+
+ /* convert plan9.ini variables to #e and #ec */
+ for(i = 0; i < nconf; i++) {
+ ksetenv(confname[i], confval[i], 0);
+ ksetenv(confname[i], confval[i], 1);
+ }
+ poperror();
+ }
+ kproc("alarm", alarmkproc, 0);
+ touser(sp);
+}
+
+static void
+bootargs(uintptr base)
+{
+ int i;
+ ulong ssize;
+ char **av, *p;
+
+ /*
+ * Push the boot args onto the stack.
+ * The initial value of the user stack must be such
+ * that the total used is larger than the maximum size
+ * of the argument list checked in syscall.
+ */
+ i = oargblen+1;
+ p = UINT2PTR(STACKALIGN(base + BY2PG - sizeof(up->s.args) - i));
+ memmove(p, oargb, i);
+
+ /*
+ * Now push argc and the argv pointers.
+ * This isn't strictly correct as the code jumped to by
+ * touser in init9.s calls startboot (port/initcode.c) which
+ * expects arguments
+ * startboot(char *argv0, char **argv)
+ * not the usual (int argc, char* argv[]), but argv0 is
+ * unused so it doesn't matter (at the moment...).
+ */
+ av = (char**)(p - (oargc+2)*sizeof(char*));
+ ssize = base + BY2PG - PTR2UINT(av);
+ *av++ = (char*)oargc;
+ for(i = 0; i < oargc; i++)
+ *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
+ *av = nil;
+
+ /*
+ * Leave space for the return PC of the
+ * caller of initcode.
+ */
+ sp = USTKTOP - ssize - sizeof(void*);
+}
+
+/*
+ * create the first process
+ */
+void
+userinit(void)
+{
+ Proc *p;
+ Segment *s;
+ KMap *k;
+ Page *pg;
+
+ /* no processes yet */
+ up = nil;
+
+ p = newproc();
+ p->pgrp = newpgrp();
+ p->egrp = smalloc(sizeof(Egrp));
+ p->egrp->ref = 1;
+ p->fgrp = dupfgrp(nil);
+ p->rgrp = newrgrp();
+ p->procmode = 0640;
+
+ kstrdup(&eve, "");
+ kstrdup(&p->text, "*init*");
+ kstrdup(&p->user, eve);
+
+ /*
+ * Kernel Stack
+ */
+ p->sched.pc = PTR2UINT(init0);
+ p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
+ p->sched.sp = STACKALIGN(p->sched.sp);
+
+ /*
+ * User Stack
+ *
+ * Technically, newpage can't be called here because it
+ * should only be called when in a user context as it may
+ * try to sleep if there are no pages available, but that
+ * shouldn't be the case here.
+ */
+ s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
+ s->flushme++;
+ p->seg[SSEG] = s;
+ pg = newpage(1, 0, USTKTOP-BY2PG);
+ segpage(s, pg);
+ k = kmap(pg);
+ bootargs(VA(k));
+ kunmap(k);
+
+ /*
+ * Text
+ */
+ s = newseg(SG_TEXT, UTZERO, 1);
+ p->seg[TSEG] = s;
+ pg = newpage(1, 0, UTZERO);
+ memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
+ segpage(s, pg);
+ k = kmap(s->map[0]->pages[0]);
+ memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
+ kunmap(k);
+
+ ready(p);
+}
+
+Conf conf; /* XXX - must go - gag */
+
+Confmem omapmem[nelem(conf.mem)] = {
+ /*
+ * Memory available to Plan 9:
+ */
+ { .base = PHYSDRAM, .limit = PHYSDRAM + Minmem, },
+};
+ulong memsize = Minmem;
+
+static int
+gotmem(uintptr sz)
+{
+ uintptr addr;
+
+ addr = PHYSDRAM + sz - BY2WD;
+ mmuidmap(addr, 1);
+ if (probeaddr(addr) >= 0) {
+ memsize = sz;
+ return 0;
+ }
+ return -1;
+}
+
+void
+confinit(void)
+{
+ int i;
+ ulong kpages;
+ uintptr pa;
+ char *p;
+
+ /*
+ * Copy the physical memory configuration to Conf.mem.
+ */
+ if(nelem(omapmem) > nelem(conf.mem)){
+ iprint("memory configuration botch\n");
+ exit(1);
+ }
+ if((p = getconf("*maxmem")) != nil) {
+ memsize = strtoul(p, 0, 0) - PHYSDRAM;
+ if (memsize < 16*MB) /* sanity */
+ memsize = 16*MB;
+ }
+
+ /*
+ * see if all that memory exists; if not, find out how much does.
+ * trapinit must have been called first.
+ */
+ if (gotmem(memsize) < 0 && gotmem(256*MB) < 0 && gotmem(128*MB) < 0) {
+ iprint("can't find any memory, assuming %dMB\n", Minmem / MB);
+ memsize = Minmem;
+ }
+
+ omapmem[0].limit = PHYSDRAM + memsize;
+ memmove(conf.mem, omapmem, sizeof(omapmem));
+
+ conf.npage = 0;
+ pa = PADDR(PGROUND(PTR2UINT(end)));
+
+ /*
+ * we assume that the kernel is at the beginning of one of the
+ * contiguous chunks of memory and fits therein.
+ */
+ for(i=0; i<nelem(conf.mem); i++){
+ /* take kernel out of allocatable space */
+ if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
+ conf.mem[i].base = pa;
+
+ conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
+ conf.npage += conf.mem[i].npage;
+ }
+
+ conf.upages = (conf.npage*80)/100;
+ conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
+
+ /* only one processor */
+ conf.nmach = 1;
+
+ /* set up other configuration parameters */
+ conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
+ if(cpuserver)
+ conf.nproc *= 3;
+ if(conf.nproc > 2000)
+ conf.nproc = 2000;
+ conf.nswap = conf.npage*3;
+ conf.nswppo = 4096;
+ conf.nimage = 200;
+
+ conf.copymode = 0; /* copy on write */
+
+ /*
+ * Guess how much is taken by the large permanent
+ * datastructures. Mntcache and Mntrpc are not accounted for
+ * (probably ~300KB).
+ */
+ kpages = conf.npage - conf.upages;
+ kpages *= BY2PG;
+ kpages -= conf.upages*sizeof(Page)
+ + conf.nproc*sizeof(Proc)
+ + conf.nimage*sizeof(Image)
+ + conf.nswap
+ + conf.nswppo*sizeof(Page);
+ mainmem->maxsize = kpages;
+ if(!cpuserver)
+ /*
+ * give terminals lots of image memory, too; the dynamic
+ * allocation will balance the load properly, hopefully.
+ * be careful with 32-bit overflow.
+ */
+ imagmem->maxsize = kpages;
+
+// archconfinit();
+}
+
+int
+cmpswap(long *addr, long old, long new)
+{
+ return cas32(addr, old, new);
+}
diff --git a/sys/src/9/omap/mem.h b/sys/src/9/omap/mem.h
new file mode 100755
index 000000000..1e5c570c9
--- /dev/null
+++ b/sys/src/9/omap/mem.h
@@ -0,0 +1,212 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+#define KiB 1024u /* Kibi 0x0000000000000400 */
+#define MiB 1048576u /* Mebi 0x0000000000100000 */
+#define GiB 1073741824u /* Gibi 000000000040000000 */
+
+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) /* ceiling */
+#define ROUNDDN(x, y) (((x)/(y))*(y)) /* floor */
+#define MIN(a, b) ((a) < (b)? (a): (b))
+#define MAX(a, b) ((a) > (b)? (a): (b))
+
+/*
+ * Not sure where these macros should go.
+ * This probably isn't right but will do for now.
+ * The macro names are problematic too.
+ */
+/*
+ * In B(o), 'o' is the bit offset in the register.
+ * For multi-bit fields use F(v, o, w) where 'v' is the value
+ * of the bit-field of width 'w' with LSb at bit offset 'o'.
+ */
+#define B(o) (1<<(o))
+#define F(v, o, w) (((v) & ((1<<(w))-1))<<(o))
+
+#define FCLR(d, o, w) ((d) & ~(((1<<(w))-1)<<(o)))
+#define FEXT(d, o, w) (((d)>>(o)) & ((1<<(w))-1))
+#define FINS(d, o, w, v) (FCLR((d), (o), (w))|F((v), (o), (w)))
+#define FSET(d, o, w) ((d)|(((1<<(w))-1)<<(o)))
+
+#define FMASK(o, w) (((1<<(w))-1)<<(o))
+
+/*
+ * Sizes
+ */
+#define BY2PG (4*KiB) /* bytes per page */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define PGROUND(s) ROUNDUP(s, BY2PG)
+#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
+
+#define MAXMACH 1 /* max # cpus system can run */
+#define MACHSIZE BY2PG
+
+#define KSTKSIZE (16*KiB) /* was 8K */
+#define STACKALIGN(sp) ((sp) & ~3) /* bug: assure with alloc */
+
+/*
+ * Address spaces.
+ * KTZERO is used by kprof and dumpstack (if any).
+ *
+ * KZERO (0xc0000000) is mapped to physical 0x80000000 (start of dram).
+ * u-boot claims to occupy the first 3 MB of dram, but we're willing to
+ * step on it once we're loaded. Expect plan9.ini in the first 64K past 3MB.
+ *
+ * L2 PTEs are stored in 1K before Mach (11K to 12K above KZERO).
+ * cpu0's Mach struct is at L1 - MACHSIZE(4K) to L1 (12K to 16K above KZERO).
+ * L1 PTEs are stored from L1 to L1+32K (16K to 48K above KZERO).
+ * KTZERO may be anywhere after that (but probably shouldn't collide with
+ * u-boot).
+ * This should leave over 8K from KZERO to L2 PTEs.
+ */
+#define KSEG0 0xC0000000 /* kernel segment */
+/* mask to check segment; good for 512MB dram */
+#define KSEGM 0xE0000000
+#define KZERO KSEG0 /* kernel address space */
+#define L1 (KZERO+16*KiB) /* tt ptes: 16KiB aligned */
+#define CONFADDR (KZERO+0x300000) /* unparsed plan9.ini */
+/* KTZERO must match loadaddr in mkfile */
+#define KTZERO (KZERO+0x310000) /* kernel text start */
+
+#define UZERO 0 /* user segment */
+#define UTZERO (UZERO+BY2PG) /* user text start */
+#define UTROUND(t) ROUNDUP((t), BY2PG)
+/* moved USTKTOP down to 512MB to keep MMIO space out of user space. */
+#define USTKTOP 0x20000000 /* user segment end +1 */
+#define USTKSIZE (8*1024*1024) /* user stack size */
+#define TSTKTOP (USTKTOP-USTKSIZE) /* sysexec temporary stack */
+#define TSTKSIZ 256
+
+/* address at which to copy and execute rebootcode */
+#define REBOOTADDR KADDR(0x100)
+
+/*
+ * Legacy...
+ */
+#define BLOCKALIGN 32 /* only used in allocb.c */
+#define KSTACK KSTKSIZE
+
+/*
+ * Sizes
+ */
+#define BI2BY 8 /* bits per byte */
+#define BY2SE 4
+#define BY2WD 4
+#define BY2V 8 /* only used in xalloc.c */
+
+#define CACHELINESZ 64 /* bytes per cache line */
+#define PTEMAPMEM (1024*1024)
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 1984 /* magic 16*124 */
+#define SSEGMAPSIZE 16 /* magic */
+#define PPN(x) ((x)&~(BY2PG-1)) /* pure page number? */
+
+/*
+ * With a little work these move to port.
+ */
+#define PTEVALID (1<<0)
+#define PTERONLY 0
+#define PTEWRITE (1<<1)
+#define PTEUNCACHED (1<<2)
+#define PTEKERNEL (1<<3)
+
+/*
+ * Physical machine information from here on.
+ */
+
+/* gpmc-controlled address space 0—1G */
+#define PHYSNAND 1 /* cs0 is onenand flash */
+#define PHYSETHER 0x2c000000
+
+#define PHYSIO 0x48000000 /* L4 ctl */
+
+#define PHYSSCM 0x48002000 /* system control module */
+
+/* core control pad cfg 0x48002030—0x480021e4, */
+/* core control d2d pad cfg 0x480021e4—0x48002264 */
+#define PHYSSCMPCONF 0x48002270 /* general device config */
+#define PHYSOMAPSTS 0x4800244c /* standalone short: has l2 size */
+/* core control pad cfg (2) 0x480025d8—0x480025fc */
+#define PHYSSWBOOTCFG 0x48002910 /* sw booting config */
+/* wakeup control pad cfg 0x48002a00—0x48002a54 */
+
+#define PHYSSCMMPU 0x48004900 /* actually CPU */
+#define PHYSSCMCORE 0x48004a00
+#define PHYSSCMWKUP 0x48004c00
+#define PHYSSCMPLL 0x48004d00 /* clock ctl for dpll[3-5] */
+#define PHYSSCMDSS 0x48004e00
+#define PHYSSCMPER 0x48005000
+#define PHYSSCMUSB 0x48005400
+
+#define PHYSL4CORE 0x48040100 /* l4 ap */
+#define PHYSDSS 0x48050000 /* start of dss registers */
+#define PHYSDISPC 0x48050400
+#define PHYSGFX 0x48050480 /* part of dispc */
+
+#define PHYSSDMA 0x48056000 /* system dma */
+#define PHYSDMA 0x48060000
+
+#define PHYSUSBTLL 0x48062000 /* usb: transceiver-less link */
+#define PHYSUHH 0x48064000 /* usb: `high-speed usb host' ctlr or subsys */
+#define PHYSOHCI 0x48064400 /* usb 1.0: slow */
+#define PHYSEHCI 0x48064800 /* usb 2.0: medium */
+#define PHYSUART0 0x4806a000
+#define PHYSUART1 0x4806c000
+#define PHYSMMCHS1 0x4809c000 /* mmc/sdio */
+#define PHYSUSBOTG 0x480ab000 /* on-the-go usb */
+#define PHYSMMCHS3 0x480ad000
+#define PHYSMMCHS2 0x480b4000
+
+#define PHYSINTC 0x48200000 /* interrupt controller */
+
+#define PHYSPRMIVA2 0x48206000 /* prm iva2 regs */
+/* 48306d40 sys_clkin_sel */
+#define PHYSPRMGLBL 0x48307200 /* prm global regs */
+#define PHYSPRMWKUSB 0x48307400
+
+#define PHYSCNTRL 0x4830a200 /* SoC id, etc. */
+#define PHYSWDT1 0x4830c000 /* wdt1, not on GP omaps */
+
+#define PHYSGPIO1 0x48310000 /* contains dss gpio */
+
+#define PHYSWDOG 0x48314000 /* watchdog timer, wdt2 */
+#define PHYSWDT2 0x48314000 /* watchdog timer, wdt2 */
+#define PHYSTIMER1 0x48318000
+
+#define PHYSL4WKUP 0x48328100 /* l4 wkup */
+#define PHYSL4PER 0x49000100 /* l4 per */
+
+#define PHYSCONS 0x49020000 /* uart console (third one) */
+
+#define PHYSWDT3 0x49030000 /* wdt3 */
+#define PHYSTIMER2 0x49032000
+#define PHYSTIMER3 0x49034000
+#define PHYSGPIO5 0x49056000
+#define PHYSGPIO6 0x49058000 /* contains igep ether gpio */
+
+#define PHYSIOEND 0x49100000 /* end of PHYSIO identity map */
+
+#define PHYSL4EMU 0x54006100 /* l4 emu */
+#define PHYSL4PROT 0x54728000 /* l4 protection regs */
+
+#define PHYSL3 0x68000000 /* l3 interconnect control */
+#define PHYSL3GPMCCFG 0x68002000 /* l3 gpmc target port agent cfg */
+#define PHYSL3USB 0x68004000 /* l3 regs for usb */
+#define PHYSL3USBOTG 0x68004400 /* l3 regs for usb otg */
+/* (target port) protection registers */
+#define PHYSL3PMRT 0x68010000 /* l3 PM register target prot. */
+#define PHYSL3GPMCPM 0x68012400 /* l3 gpmc target port protection */
+#define PHYSL3OCTRAM 0x68012800 /* l3 ocm ram */
+#define PHYSL3OCTROM 0x68012c00 /* l3 ocm rom */
+#define PHYSL3MAD2D 0x68013000 /* l3 die-to-die */
+#define PHYSL3IVA 0x68014000 /* l3 die-to-die */
+
+#define PHYSSMS 0x6c000000 /* cfg regs: sms addr space 2 */
+#define PHYSDRC 0x6d000000 /* sdram ctlr, addr space 3 */
+#define PHYSGPMC 0x6e000000 /* flash, non-dram memory ctlr */
+
+#define PHYSDRAM 0x80000000
+
+#define VIRTNAND 0x20000000 /* fixed by u-boot */
+#define VIRTIO PHYSIO
diff --git a/sys/src/9/omap/mkfile b/sys/src/9/omap/mkfile
new file mode 100755
index 000000000..de353a776
--- /dev/null
+++ b/sys/src/9/omap/mkfile
@@ -0,0 +1,136 @@
+CONF=beagle
+CONFLIST=beagle
+
+# allegedly u-boot uses the bottom 3MB (up to 0x300000) so avoid that,
+# and leave 64K for plan9.ini. loadaddr must match KTZERO in mem.h.
+# 0xc0310000 has worked, 0x80310000 should work but doesn't yet.
+loadaddr=0xc0310000
+
+objtype=arm
+</$objtype/mkfile
+p=9
+
+DEVS=`{rc ../port/mkdevlist $CONF}
+
+PORT=\
+ alarm.$O\
+ alloc.$O\
+ allocb.$O\
+ auth.$O\
+ cache.$O\
+ chan.$O\
+ dev.$O\
+ edf.$O\
+ fault.$O\
+ latin1.$O\
+ mul64fract.$O\
+ rebootcmd.$O\
+ page.$O\
+ parse.$O\
+ pgrp.$O\
+ portclock.$O\
+ print.$O\
+ proc.$O\
+ qio.$O\
+ qlock.$O\
+ segment.$O\
+ swap.$O\
+ sysfile.$O\
+ sysproc.$O\
+ taslock.$O\
+ tod.$O\
+ xalloc.$O\
+
+OBJ=\
+ l.$O\
+ lexception.$O\
+ lproc.$O\
+ arch.$O\
+ clock.$O\
+ fpi.$O\
+ fpiarm.$O\
+ fpimem.$O\
+ kbd.$O\
+ main.$O\
+ mmu.$O\
+ random.$O\
+ trap.$O\
+ $CONF.root.$O\
+ $CONF.rootc.$O\
+ $DEVS\
+ $PORT\
+
+LIB=\
+ /$objtype/lib/libmemlayer.a\
+ /$objtype/lib/libmemdraw.a\
+ /$objtype/lib/libdraw.a\
+ /$objtype/lib/libip.a\
+ /$objtype/lib/libsec.a\
+ /$objtype/lib/libmp.a\
+ /$objtype/lib/libc.a\
+
+9:V: $p$CONF s$p$CONF
+
+$p$CONF:DQ: $CONF.c $OBJ $LIB mkfile
+ $CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
+ echo '# linking raw kernel'
+ $LD -o $target -H0 -R4096 -T$loadaddr -l $OBJ $CONF.$O $LIB
+
+s$p$CONF:DQ: $CONF.$O $OBJ $LIB
+ echo '# linking kernel with symbols'
+# $LD -o $target -R4096 -T$loadaddr -l -a $OBJ $CONF.$O $LIB >$target.list
+ $LD -o $target -R4096 -T$loadaddr -l $OBJ $CONF.$O $LIB
+ size $target
+
+$p$CONF.gz:D: $p$CONF
+ gzip -9 <$p$CONF >$target
+
+$OBJ: $HFILES
+
+install:V: /$objtype/$p$CONF
+
+/$objtype/$p$CONF:D: $p$CONF s$p$CONF
+ { cp -x $p$CONF s$p$CONF /$objtype } &
+ wait
+ touch $target
+
+<../boot/bootmkfile
+<../port/portmkfile
+<|../port/mkbootrules $CONF
+
+CFLAGS= -I. -I../port $CFLAGS # hack to compile private sysproc.c (e.g.)
+
+arch.$O clock.$O fpiarm.$O main.$O mmu.$O screen.$O sdscsi.$O syscall.$O \
+ trap.$O: /$objtype/include/ureg.h
+
+archomap.$O devether.$0 ether9221.$O: etherif.h ../port/netif.h
+archomap.$O devflash.$O flashbeagle.$O flashigep.$O: ../port/flashif.h
+ecc.$O flashbeagle.$O flashigep.$O: ../port/nandecc.h io.h
+fpi.$O fpiarm.$O fpimem.$O: fpi.h
+l.$O lexception.$O lproc.$O mmu.$O: arm.s arm.h mem.h
+l.$O rebootcode.$O: cache.v7.s
+main.$O: errstr.h init.h reboot.h
+devdss.$O devmouse.$O mouse.$O screen.$O: screen.h
+devusb.$O: ../port/usb.h
+usbehci.$O usbohci.$O usbuhci.$O: ../port/usb.h usbehci.h uncached.h
+
+init.h:D: ../port/initcode.c init9.s
+ $CC ../port/initcode.c
+ $AS init9.s
+ $LD -l -R1 -s -o init.out init9.$O initcode.$O /$objtype/lib/libc.a
+ {echo 'uchar initcode[]={'
+ xd -1x <init.out |
+ sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+ echo '};'} > init.h
+
+reboot.h:D: rebootcode.s cache.v7.s arm.s arm.h mem.h
+ $AS rebootcode.s
+ # -lc is only for memmove. -T arg is PADDR(REBOOTADDR)
+# $LD -l -a -s -T0x100 -R4 -o reboot.out rebootcode.$O -lc >reboot.list
+ $LD -l -s -T0x100 -R4 -o reboot.out rebootcode.$O -lc
+ {echo 'uchar rebootcode[]={'
+ xd -1x reboot.out |
+ sed -e '1,2d' -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+ echo '};'} > reboot.h
+errstr.h:D: ../port/mkerrstr ../port/error.h
+ rc ../port/mkerrstr > errstr.h
diff --git a/sys/src/9/omap/mmu.c b/sys/src/9/omap/mmu.c
new file mode 100755
index 000000000..05b4dc38c
--- /dev/null
+++ b/sys/src/9/omap/mmu.c
@@ -0,0 +1,496 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#include "arm.h"
+
+#define L1X(va) FEXT((va), 20, 12)
+#define L2X(va) FEXT((va), 12, 8)
+
+enum {
+ L1lo = UZERO/MiB, /* L1X(UZERO)? */
+ L1hi = (USTKTOP+MiB-1)/MiB, /* L1X(USTKTOP+MiB-1)? */
+};
+
+#define ISHOLE(pte) ((pte) == 0)
+
+/* dump level 1 page table at virtual addr l1 */
+void
+mmudump(PTE *l1)
+{
+ int i, type, rngtype;
+ uintptr pa, startva, startpa;
+ uvlong va, endva;
+ PTE pte;
+
+// pa -= MACHSIZE+1024; /* put level 2 entries below level 1 */
+// l2 = KADDR(pa);
+
+ print("\n");
+ endva = startva = startpa = 0;
+ rngtype = 0;
+ /* dump first level of ptes */
+ for (va = i = 0; i < 4096; i++) {
+ pte = l1[i];
+ pa = pte & ~(MB - 1);
+ type = pte & (Fine|Section|Coarse);
+ if (ISHOLE(pte)) {
+ if (endva != 0) { /* open range? close it */
+ print("l1 maps va (%#lux-%#llux) -> pa %#lux type %#ux\n",
+ startva, endva-1, startpa, rngtype);
+ endva = 0;
+ }
+ } else {
+ if (endva == 0) { /* no open range? start one */
+ startva = va;
+ startpa = pa;
+ rngtype = type;
+ }
+ endva = va + MB; /* continue the open range */
+// if (type == Coarse) {
+// // could dump the l2 table for this l1 entry
+// }
+ }
+ va += MB;
+ }
+ if (endva != 0) /* close an open range */
+ print("l1 maps va (%#lux-%#llux) -> pa %#lux type %#ux\n",
+ startva, endva-1, startpa, rngtype);
+}
+
+/* identity map the megabyte containing va, uncached */
+static void
+idmap(PTE *l1, ulong va)
+{
+ va &= ~(MB-1);
+ l1[L1X(va)] = va | Dom0 | L1AP(Krw) | Section;
+}
+
+/* map `mbs' megabytes from virt to phys */
+void
+mmumap(uintptr virt, uintptr phys, int mbs)
+{
+ uint off;
+ PTE *l1;
+
+ phys &= ~(MB-1);
+ virt &= ~(MB-1);
+ l1 = KADDR(ttbget());
+ for (off = 0; mbs-- > 0; off += MB)
+ l1[L1X(virt + off)] = (phys + off) | Dom0 | L1AP(Krw) | Section;
+ cacheuwbinv();
+ l2cacheuwbinv();
+ mmuinvalidate();
+}
+
+/* identity map `mbs' megabytes from phys */
+void
+mmuidmap(uintptr phys, int mbs)
+{
+ mmumap(phys, phys, mbs);
+}
+
+void
+mmuinit(void)
+{
+ uintptr pa;
+ PTE *l1, *l2;
+
+ pa = ttbget();
+ l1 = KADDR(pa);
+
+ /* redundant with l.s; only covers first MB of 17MB */
+ l1[L1X(VIRTIO)] = PHYSIO|Dom0|L1AP(Krw)|Section;
+
+ idmap(l1, PHYSETHER); /* igep 9221 ethernet regs */
+ idmap(l1, PHYSL4PROT);
+ idmap(l1, PHYSL3);
+ idmap(l1, PHYSSMS);
+ idmap(l1, PHYSDRC);
+ idmap(l1, PHYSGPMC);
+
+ /* map high vectors to start of dram, but only 4K, not 1MB */
+ pa -= MACHSIZE+2*1024;
+ l2 = KADDR(pa);
+ memset(l2, 0, 1024);
+ /* vectors step on u-boot, but so do page tables */
+ l2[L2X(HVECTORS)] = PHYSDRAM|L2AP(Krw)|Small;
+ l1[L1X(HVECTORS)] = pa|Dom0|Coarse; /* vectors -> ttb-machsize-2k */
+ coherence();
+
+ cacheuwbinv();
+ l2cacheuwbinv();
+ mmuinvalidate();
+
+ m->mmul1 = l1;
+// mmudump(l1); /* DEBUG */
+}
+
+static void
+mmul2empty(Proc* proc, int clear)
+{
+ PTE *l1;
+ Page **l2, *page;
+
+ l1 = m->mmul1;
+ l2 = &proc->mmul2;
+ for(page = *l2; page != nil; page = page->next){
+ if(clear)
+ memset(UINT2PTR(page->va), 0, BY2PG);
+ l1[page->daddr] = Fault;
+ l2 = &page->next;
+ }
+ *l2 = proc->mmul2cache;
+ proc->mmul2cache = proc->mmul2;
+ proc->mmul2 = nil;
+}
+
+static void
+mmul1empty(void)
+{
+#ifdef notdef
+/* there's a bug in here */
+ PTE *l1;
+
+ /* clean out any user mappings still in l1 */
+ if(m->mmul1lo > L1lo){
+ if(m->mmul1lo == 1)
+ m->mmul1[L1lo] = Fault;
+ else
+ memset(&m->mmul1[L1lo], 0, m->mmul1lo*sizeof(PTE));
+ m->mmul1lo = L1lo;
+ }
+ if(m->mmul1hi < L1hi){
+ l1 = &m->mmul1[m->mmul1hi];
+ if((L1hi - m->mmul1hi) == 1)
+ *l1 = Fault;
+ else
+ memset(l1, 0, (L1hi - m->mmul1hi)*sizeof(PTE));
+ m->mmul1hi = L1hi;
+ }
+#else
+ memset(&m->mmul1[L1lo], 0, (L1hi - L1lo)*sizeof(PTE));
+#endif /* notdef */
+}
+
+void
+mmuswitch(Proc* proc)
+{
+ int x;
+ PTE *l1;
+ Page *page;
+
+ /* do kprocs get here and if so, do they need to? */
+ if(m->mmupid == proc->pid && !proc->newtlb)
+ return;
+ m->mmupid = proc->pid;
+
+ /* write back dirty and invalidate l1 caches */
+ cacheuwbinv();
+
+ if(proc->newtlb){
+ mmul2empty(proc, 1);
+ proc->newtlb = 0;
+ }
+
+ mmul1empty();
+
+ /* move in new map */
+ l1 = m->mmul1;
+ for(page = proc->mmul2; page != nil; page = page->next){
+ x = page->daddr;
+ l1[x] = PPN(page->pa)|Dom0|Coarse;
+ /* know here that L1lo < x < L1hi */
+ if(x+1 - m->mmul1lo < m->mmul1hi - x)
+ m->mmul1lo = x+1;
+ else
+ m->mmul1hi = x;
+ }
+
+ /* make sure map is in memory */
+ /* could be smarter about how much? */
+ cachedwbse(&l1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE));
+
+ /* lose any possible stale tlb entries */
+ mmuinvalidate();
+
+ //print("mmuswitch l1lo %d l1hi %d %d\n",
+ // m->mmul1lo, m->mmul1hi, proc->kp);
+}
+
+void
+flushmmu(void)
+{
+ int s;
+
+ s = splhi();
+ up->newtlb = 1;
+ mmuswitch(up);
+ splx(s);
+}
+
+void
+mmurelease(Proc* proc)
+{
+ Page *page, *next;
+
+ /* write back dirty and invalidate l1 caches */
+ cacheuwbinv();
+
+ mmul2empty(proc, 0);
+ for(page = proc->mmul2cache; page != nil; page = next){
+ next = page->next;
+ if(--page->ref)
+ panic("mmurelease: page->ref %d", page->ref);
+ pagechainhead(page);
+ }
+ if(proc->mmul2cache && palloc.r.p)
+ wakeup(&palloc.r);
+ proc->mmul2cache = nil;
+
+ mmul1empty();
+
+ /* make sure map is in memory */
+ /* could be smarter about how much? */
+ cachedwbse(&m->mmul1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE));
+
+ /* lose any possible stale tlb entries */
+ mmuinvalidate();
+}
+
+void
+putmmu(uintptr va, uintptr pa, Page* page)
+{
+ int x;
+ Page *pg;
+ PTE *l1, *pte;
+
+ x = L1X(va);
+ l1 = &m->mmul1[x];
+ //print("putmmu(%#p, %#p, %#p) ", va, pa, page->pa);
+ //print("mmul1 %#p l1 %#p *l1 %#ux x %d pid %d\n",
+ // m->mmul1, l1, *l1, x, up->pid);
+ if(*l1 == Fault){
+ /* wasteful - l2 pages only have 256 entries - fix */
+ if(up->mmul2cache == nil){
+ /* auxpg since we don't need much? memset if so */
+ pg = newpage(1, 0, 0);
+ pg->va = VA(kmap(pg));
+ }
+ else{
+ pg = up->mmul2cache;
+ up->mmul2cache = pg->next;
+ memset(UINT2PTR(pg->va), 0, BY2PG);
+ }
+ pg->daddr = x;
+ pg->next = up->mmul2;
+ up->mmul2 = pg;
+
+ /* force l2 page to memory */
+ cachedwbse((void *)pg->va, BY2PG);
+
+ *l1 = PPN(pg->pa)|Dom0|Coarse;
+ cachedwbse(l1, sizeof *l1);
+ //print("l1 %#p *l1 %#ux x %d pid %d\n", l1, *l1, x, up->pid);
+
+ if(x >= m->mmul1lo && x < m->mmul1hi){
+ if(x+1 - m->mmul1lo < m->mmul1hi - x)
+ m->mmul1lo = x+1;
+ else
+ m->mmul1hi = x;
+ }
+ }
+ pte = UINT2PTR(KADDR(PPN(*l1)));
+ //print("pte %#p index %ld was %#ux\n", pte, L2X(va), *(pte+L2X(va)));
+
+ /* protection bits are
+ * PTERONLY|PTEVALID;
+ * PTEWRITE|PTEVALID;
+ * PTEWRITE|PTEUNCACHED|PTEVALID;
+ */
+ x = Small;
+ if(!(pa & PTEUNCACHED))
+ x |= Cached|Buffered;
+ if(pa & PTEWRITE)
+ x |= L2AP(Urw);
+ else
+ x |= L2AP(Uro);
+ pte[L2X(va)] = PPN(pa)|x;
+ cachedwbse(&pte[L2X(va)], sizeof pte[0]);
+
+ /* clear out the current entry */
+ mmuinvalidateaddr(PPN(va));
+
+ /* write back dirty entries - we need this because the pio() in
+ * fault.c is writing via a different virt addr and won't clean
+ * its changes out of the dcache. Page coloring doesn't work
+ * on this mmu because the virtual cache is set associative
+ * rather than direct mapped.
+ */
+ cachedwbinv();
+ if(page->cachectl[0] == PG_TXTFLUSH){
+ /* pio() sets PG_TXTFLUSH whenever a text pg has been written */
+ cacheiinv();
+ page->cachectl[0] = PG_NOFLUSH;
+ }
+ //print("putmmu %#p %#p %#p\n", va, pa, PPN(pa)|x);
+}
+
+void*
+mmuuncache(void* v, usize size)
+{
+ int x;
+ PTE *pte;
+ uintptr va;
+
+ /*
+ * Simple helper for ucalloc().
+ * Uncache a Section, must already be
+ * valid in the MMU.
+ */
+ va = PTR2UINT(v);
+ assert(!(va & (1*MiB-1)) && size == 1*MiB);
+
+ x = L1X(va);
+ pte = &m->mmul1[x];
+ if((*pte & (Fine|Section|Coarse)) != Section)
+ return nil;
+ *pte &= ~(Cached|Buffered);
+ mmuinvalidateaddr(va);
+ cachedwbinvse(pte, 4);
+
+ return v;
+}
+
+uintptr
+mmukmap(uintptr va, uintptr pa, usize size)
+{
+ int x;
+ PTE *pte;
+
+ /*
+ * Stub.
+ */
+ assert(!(va & (1*MiB-1)) && !(pa & (1*MiB-1)) && size == 1*MiB);
+
+ x = L1X(va);
+ pte = &m->mmul1[x];
+ if(*pte != Fault)
+ return 0;
+ *pte = pa|Dom0|L1AP(Krw)|Section;
+ mmuinvalidateaddr(va);
+ cachedwbinvse(pte, 4);
+
+ return va;
+}
+
+uintptr
+mmukunmap(uintptr va, uintptr pa, usize size)
+{
+ int x;
+ PTE *pte;
+
+ /*
+ * Stub.
+ */
+ assert(!(va & (1*MiB-1)) && !(pa & (1*MiB-1)) && size == 1*MiB);
+
+ x = L1X(va);
+ pte = &m->mmul1[x];
+ if(*pte != (pa|Dom0|L1AP(Krw)|Section))
+ return 0;
+ *pte = Fault;
+ mmuinvalidateaddr(va);
+ cachedwbinvse(pte, 4);
+
+ return va;
+}
+
+/*
+ * Return the number of bytes that can be accessed via KADDR(pa).
+ * If pa is not a valid argument to KADDR, return 0.
+ */
+uintptr
+cankaddr(uintptr pa)
+{
+ if(pa >= PHYSDRAM && pa < PHYSDRAM+memsize)
+ return PHYSDRAM+memsize - pa;
+ return 0;
+}
+
+/* from 386 */
+void*
+vmap(uintptr pa, usize size)
+{
+ uintptr pae, va;
+ usize o, osize;
+
+ /*
+ * XXX - replace with new vm stuff.
+ * Crock after crock - the first 4MB is mapped with 2MB pages
+ * so catch that and return good values because the current mmukmap
+ * will fail.
+ */
+ if(pa+size < 4*MiB)
+ return UINT2PTR(kseg0|pa);
+
+ osize = size;
+ o = pa & (BY2PG-1);
+ pa -= o;
+ size += o;
+ size = ROUNDUP(size, BY2PG);
+
+ va = kseg0|pa;
+ pae = mmukmap(va, pa, size);
+ if(pae == 0 || pae-size != pa)
+ panic("vmap(%#p, %ld) called from %#p: mmukmap fails %#p",
+ pa+o, osize, getcallerpc(&pa), pae);
+
+ return UINT2PTR(va+o);
+}
+
+/* from 386 */
+void
+vunmap(void* v, usize size)
+{
+ /*
+ * XXX - replace with new vm stuff.
+ * Can't do this until do real vmap for all space that
+ * might be used, e.g. stuff below 1MB which is currently
+ * mapped automagically at boot but that isn't used (or
+ * at least shouldn't be used) by the kernel.
+ upafree(PADDR(v), size);
+ */
+ USED(v, size);
+}
+
+/*
+ * Notes.
+ * Everything is in domain 0;
+ * domain 0 access bits in the DAC register are set
+ * to Client, which means access is controlled by the
+ * permission values set in the PTE.
+ *
+ * L1 access control for the kernel is set to 1 (RW,
+ * no user mode access);
+ * L2 access control for the kernel is set to 1 (ditto)
+ * for all 4 AP sets;
+ * L1 user mode access is never set;
+ * L2 access control for user mode is set to either
+ * 2 (RO) or 3 (RW) depending on whether text or data,
+ * for all 4 AP sets.
+ * (To get kernel RO set AP to 0 and S bit in control
+ * register c1).
+ * Coarse L1 page-tables are used. They have 256 entries
+ * and so consume 1024 bytes per table.
+ * Small L2 page-tables are used. They have 1024 entries
+ * and so consume 4096 bytes per table.
+ *
+ * 4KiB. That's the size of 1) a page, 2) the
+ * size allocated for an L2 page-table page (note only 1KiB
+ * is needed per L2 page - to be dealt with later) and
+ * 3) the size of the area in L1 needed to hold the PTEs
+ * to map 1GiB of user space (0 -> 0x3fffffff, 1024 entries).
+ */
diff --git a/sys/src/9/omap/mouse.c b/sys/src/9/omap/mouse.c
new file mode 100755
index 000000000..f0f62c8a1
--- /dev/null
+++ b/sys/src/9/omap/mouse.c
@@ -0,0 +1,255 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+/*
+ * mouse types
+ */
+enum
+{
+ Mouseother= 0,
+ Mouseserial= 1,
+ MousePS2= 2,
+};
+
+extern int mouseshifted;
+
+static QLock mousectlqlock;
+static int mousetype;
+static int intellimouse;
+static int packetsize;
+static int resolution;
+static int accelerated;
+static int mousehwaccel;
+static char mouseport[5];
+
+enum
+{
+ CMaccelerated,
+ CMhwaccel,
+ CMintellimouse,
+ CMlinear,
+ CMps2,
+ CMps2intellimouse,
+ CMres,
+ CMreset,
+ CMserial,
+};
+
+static Cmdtab mousectlmsg[] =
+{
+ CMaccelerated, "accelerated", 0,
+ CMhwaccel, "hwaccel", 2,
+ CMintellimouse, "intellimouse", 1,
+ CMlinear, "linear", 1,
+ CMps2, "ps2", 1,
+ CMps2intellimouse, "ps2intellimouse", 1,
+ CMres, "res", 0,
+ CMreset, "reset", 1,
+ CMserial, "serial", 0,
+};
+
+/*
+ * ps/2 mouse message is three bytes
+ *
+ * byte 0 - 0 0 SDY SDX 1 M R L
+ * byte 1 - DX
+ * byte 2 - DY
+ *
+ * shift & right button is the same as middle button
+ *
+ * Intellimouse and AccuPoint with extra buttons deliver
+ * byte 3 - 00 or 01 or FF according to extra button state.
+ * extra buttons are mapped in this code to buttons 4 and 5.
+ * AccuPoint generates repeated events for these buttons;
+* it and Intellimouse generate 'down' events only, so
+ * user-level code is required to generate button 'up' events
+ * if they are needed by the application.
+ * Also on laptops with AccuPoint AND external mouse, the
+ * controller may deliver 3 or 4 bytes according to the type
+ * of the external mouse; code must adapt.
+ *
+ * On the NEC Versa series (and perhaps others?) we seem to
+ * lose a byte from the packet every once in a while, which
+ * means we lose where we are in the instruction stream.
+ * To resynchronize, if we get a byte more than two seconds
+ * after the previous byte, we assume it's the first in a packet.
+ */
+static void
+ps2mouseputc(int c, int shift)
+{
+ static short msg[4];
+ static int nb;
+ static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 3, 2, 3, 6, 7 };
+ static ulong lasttick;
+ ulong m;
+ int buttons, dx, dy;
+
+ shift |= mouseshifted;
+ m = MACHP(0)->ticks;
+ if(TK2SEC(m - lasttick) > 2)
+ nb = 0;
+ lasttick = m;
+ if(nb==0 && (c&0xc8)!=0x08)
+ if(intellimouse && (c==0x00 || c==0x01 || c==0xFF)){
+ packetsize = 4;
+ return;
+ }
+
+ msg[nb] = c;
+ if(++nb == packetsize){
+ nb = 0;
+ if(msg[0] & 0x10)
+ msg[1] |= 0xFF00;
+ if(msg[0] & 0x20)
+ msg[2] |= 0xFF00;
+
+ buttons = b[(msg[0]&7) | (shift ? 8 : 0)];
+ if(intellimouse && packetsize==4){
+ if((msg[3]&0xc8) == 0x08){
+ packetsize = 3;
+ msg[0] = msg[3];
+ nb = 1;
+ }else{
+ if((msg[3] >> 3) & 1)
+ buttons |= 1<<3;
+ else if(msg[3] & 0x7)
+ buttons |= 1<<4;
+ }
+ }
+ dx = msg[1];
+ dy = -msg[2];
+ mousetrack(dx, dy, buttons, TK2MS(MACHP(0)->ticks));
+ }
+}
+
+/*
+ * set up a ps2 mouse
+ */
+static void
+ps2mouse(void)
+{
+ if(mousetype == MousePS2)
+ return;
+
+// i8042auxenable(ps2mouseputc);
+// i8042auxcmd(0xEA); // TODO
+// i8042auxcmd(0xF4);
+
+ mousetype = MousePS2;
+ packetsize = 3;
+ mousehwaccel = 1;
+}
+
+/*
+ * The PS/2 Trackpoint multiplexor on the IBM Thinkpad T23 ignores
+ * acceleration commands. It is supposed to pass them on
+ * to the attached device, but my Logitech mouse is simply
+ * not behaving any differently. For such devices, we allow
+ * the user to use "hwaccel off" to tell us to back off to
+ * software acceleration even if we're using the PS/2 port.
+ * (Serial mice are always software accelerated.)
+ * For more information on the Thinkpad multiplexor, see
+ * http://wwwcssrv.almaden.ibm.com/trackpoint/
+ */
+static void
+setaccelerated(int x)
+{
+ accelerated = x;
+ mouseaccelerate(x);
+}
+
+static void
+setlinear(void)
+{
+ accelerated = 0;
+ mouseaccelerate(0);
+}
+
+static void
+setres(int n)
+{
+ resolution = n;
+}
+
+static void
+setintellimouse(void)
+{
+ intellimouse = 1;
+ packetsize = 4;
+}
+
+static void
+resetmouse(void)
+{
+ packetsize = 3;
+}
+
+void
+mousectl(Cmdbuf *cb)
+{
+ Cmdtab *ct;
+
+ qlock(&mousectlqlock);
+ if(waserror()){
+ qunlock(&mousectlqlock);
+ nexterror();
+ }
+
+ ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg));
+ switch(ct->index){
+ case CMaccelerated:
+ setaccelerated(cb->nf == 1? 1: atoi(cb->f[1]));
+ break;
+ case CMintellimouse:
+ setintellimouse();
+ break;
+ case CMlinear:
+ setlinear();
+ break;
+ case CMps2:
+ intellimouse = 0;
+ break;
+ case CMps2intellimouse:
+ setintellimouse();
+ break;
+ case CMres:
+ if(cb->nf >= 2)
+ setres(atoi(cb->f[1]));
+ else
+ setres(1);
+ break;
+ case CMreset:
+ resetmouse();
+ if(accelerated)
+ setaccelerated(accelerated);
+ if(resolution)
+ setres(resolution);
+ if(intellimouse)
+ setintellimouse();
+ break;
+ case CMserial:
+ error("serial mice not supported");
+ break;
+ case CMhwaccel:
+ if(strcmp(cb->f[1], "on")==0)
+ mousehwaccel = 1;
+ else if(strcmp(cb->f[1], "off")==0)
+ mousehwaccel = 0;
+ else
+ cmderror(cb, "bad mouse control message");
+ }
+
+ qunlock(&mousectlqlock);
+ poperror();
+}
diff --git a/sys/src/9/omap/notes/movm.w b/sys/src/9/omap/notes/movm.w
new file mode 100755
index 000000000..a2b22f1e1
--- /dev/null
+++ b/sys/src/9/omap/notes/movm.w
@@ -0,0 +1,22 @@
+gorka writes:
+---
+I have userspace on the gumstix [xscale, not omap]. The problem that
+got me in trouble was that in lexception.s (or l.s),
+
+ MOVM.DB.W [R0-R14], (R13)
+
+works differently for this architecture (and probably for others, as
+it is unclear how it should behave by reading the arm specs). This
+happens only for kernel faults as the others (syscall, user faults)
+use MOVM.DB.W.S which uses the banked user registers.
+
+The problem is that in this arch the value of R13 saved is the value
+after R13 itself has been modified, whereas in the others (bitsy,
+pico...), it was the value before. Adding 4*15 to the stack before
+the RFE solves the problem.
+---
+
+In fact, the 2005 ARM arch. ref. man. (ARM DDI 0100I) says, under STM (1),
+that if Rn appears in the set of registers (and isn't the first one)
+and .W is specified, the stored value of Rn is unpredictable.
+The arm v7-ar arch. ref. man. says such usage is obsolete.
diff --git a/sys/src/9/omap/nvram b/sys/src/9/omap/nvram
new file mode 100755
index 000000000..a64a5a93f
--- /dev/null
+++ b/sys/src/9/omap/nvram
Binary files differ
diff --git a/sys/src/9/omap/random.c b/sys/src/9/omap/random.c
new file mode 100755
index 000000000..1f7c0983d
--- /dev/null
+++ b/sys/src/9/omap/random.c
@@ -0,0 +1,138 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+
+struct Rb
+{
+ QLock;
+ Rendez producer;
+ Rendez consumer;
+ ulong randomcount;
+ uchar buf[128];
+ uchar *ep;
+ uchar *rp;
+ uchar *wp;
+ uchar next;
+ uchar wakeme;
+ ushort bits;
+ ulong randn;
+} rb;
+
+static int
+rbnotfull(void*)
+{
+ int i;
+
+ i = rb.rp - rb.wp;
+ return i != 1 && i != (1 - sizeof(rb.buf));
+}
+
+static int
+rbnotempty(void*)
+{
+ return rb.wp != rb.rp;
+}
+
+static void
+genrandom(void*)
+{
+ up->basepri = PriNormal;
+ up->priority = up->basepri;
+
+ for(;;){
+ for(;;)
+ if(++rb.randomcount > 100000)
+ break;
+ if(anyhigher())
+ sched();
+ if(!rbnotfull(0))
+ sleep(&rb.producer, rbnotfull, 0);
+ }
+}
+
+/*
+ * produce random bits in a circular buffer
+ */
+static void
+randomclock(void)
+{
+ if(rb.randomcount == 0 || !rbnotfull(0))
+ return;
+
+ rb.bits = (rb.bits<<2) ^ rb.randomcount;
+ rb.randomcount = 0;
+
+ rb.next++;
+ if(rb.next != 8/2)
+ return;
+ rb.next = 0;
+
+ *rb.wp ^= rb.bits;
+ if(rb.wp+1 == rb.ep)
+ rb.wp = rb.buf;
+ else
+ rb.wp = rb.wp+1;
+
+ if(rb.wakeme)
+ wakeup(&rb.consumer);
+}
+
+void
+randominit(void)
+{
+ addclock0link(randomclock, 1000/HZ);
+ rb.ep = rb.buf + sizeof(rb.buf);
+ rb.rp = rb.wp = rb.buf;
+ kproc("genrandom", genrandom, 0);
+}
+
+/*
+ * consume random bytes from a circular buffer
+ */
+ulong
+randomread(void *xp, ulong n)
+{
+ uchar *e, *p;
+ ulong x;
+
+ p = xp;
+
+ if(waserror()){
+ qunlock(&rb);
+ nexterror();
+ }
+
+ qlock(&rb);
+ for(e = p + n; p < e; ){
+ if(rb.wp == rb.rp){
+ rb.wakeme = 1;
+ wakeup(&rb.producer);
+ sleep(&rb.consumer, rbnotempty, 0);
+ rb.wakeme = 0;
+ continue;
+ }
+
+ /*
+ * beating clocks will be predictable if
+ * they are synchronized. Use a cheap pseudo
+ * random number generator to obscure any cycles.
+ */
+ x = rb.randn*1103515245 ^ *rb.rp;
+ *p++ = rb.randn = x;
+
+ if(rb.rp+1 == rb.ep)
+ rb.rp = rb.buf;
+ else
+ rb.rp = rb.rp+1;
+ }
+ qunlock(&rb);
+ poperror();
+
+ wakeup(&rb.producer);
+
+ return n;
+}
diff --git a/sys/src/9/omap/rebootcode.s b/sys/src/9/omap/rebootcode.s
new file mode 100755
index 000000000..f07146f81
--- /dev/null
+++ b/sys/src/9/omap/rebootcode.s
@@ -0,0 +1,209 @@
+/*
+ * omap3530 reboot code
+ *
+ * must fit in 11K to avoid stepping on PTEs; see mem.h.
+ *
+ * R11 is used by the loader as a temporary, so avoid it.
+ */
+#include "arm.s"
+
+/*
+ * Turn off MMU, then copy the new kernel to its correct location
+ * in physical memory. Then jump to the start of the kernel.
+ */
+
+/* main(PADDR(entry), PADDR(code), size); */
+TEXT main(SB), 1, $-4
+ MOVW $setR12(SB), R12
+
+ MOVW R0, p1+0(FP) /* destination, passed in R0 */
+
+ MOVW CPSR, R0
+ ORR $(PsrDirq|PsrDfiq), R0
+ MOVW R0, CPSR /* splhi */
+ BARRIERS
+
+WAVE('R')
+ MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
+ BIC $CpACasa, R1 /* no speculative I access forwarding to mem */
+ /* slow down */
+ ORR $(CpACcachenopipe|CpACcp15serial|CpACcp15waitidle|CpACcp15pipeflush), R1
+ MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
+ BARRIERS
+
+ BL cachesoff(SB)
+ /* now back in 29- or 26-bit addressing, mainly for SB */
+ /* double mapping of PHYSDRAM & KZERO now in effect */
+
+ /*
+ * turn the MMU off
+ */
+
+WAVE('e')
+ /* first switch to PHYSDRAM-based addresses */
+ DMB
+
+ MOVW $KSEGM, R7 /* clear segment bits */
+ MOVW $PHYSDRAM, R0 /* set dram base bits */
+ BIC R7, R12 /* adjust SB */
+ ORR R0, R12
+
+ BL _r15warp(SB)
+ /* don't care about saving R14; we're not returning */
+
+ /*
+ * now running in PHYSDRAM segment, not KZERO.
+ */
+
+WAVE('b')
+ SUB $12, SP /* paranoia */
+ BL cacheuwbinv(SB)
+ ADD $12, SP /* paranoia */
+
+ /* invalidate mmu mappings */
+ MOVW $KZERO, R0 /* some valid virtual address */
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
+ BARRIERS
+
+WAVE('o')
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0)
+ BIC $(CpCmmu|CpCdcache|CpCicache), R0
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0) /* mmu off */
+ BARRIERS
+
+WAVE('o')
+ /* copy in arguments from stack frame before moving stack */
+ MOVW p2+4(FP), R4 /* phys source */
+ MOVW n+8(FP), R5 /* byte count */
+ MOVW p1+0(FP), R6 /* phys destination */
+
+ /* set up a new stack for local vars and memmove args */
+ MOVW R6, SP /* tiny trampoline stack */
+ SUB $(0x20 + 4), SP /* back up before a.out header */
+
+// MOVW R14, -48(SP) /* store return addr */
+ SUB $48, SP /* allocate stack frame */
+
+ MOVW R5, 40(SP) /* save count */
+ MOVW R6, 44(SP) /* save dest/entry */
+
+ DELAY(printloop2, 2)
+WAVE('t')
+
+ MOVW 40(SP), R5 /* restore count */
+ MOVW 44(SP), R6 /* restore dest/entry */
+ MOVW R6, 0(SP) /* normally saved LR goes here */
+ MOVW R6, 4(SP) /* push dest */
+ MOVW R6, R0
+ MOVW R4, 8(SP) /* push src */
+ MOVW R5, 12(SP) /* push size */
+ BL memmove(SB)
+
+WAVE('-')
+ /*
+ * flush caches
+ */
+ BL cacheuwbinv(SB)
+
+WAVE('>')
+ DELAY(printloopret, 1)
+WAVE('\r')
+ DELAY(printloopnl, 1)
+WAVE('\n')
+/*
+ * jump to kernel entry point. Note the true kernel entry point is
+ * the virtual address KZERO|R6, but this must wait until
+ * the MMU is enabled by the kernel in l.s
+ */
+ MOVW 44(SP), R6 /* restore R6 (dest/entry) */
+ ORR R6, R6 /* NOP: avoid link bug */
+ B (R6)
+WAVE('?')
+ B 0(PC)
+
+/*
+ * turn the caches off, double map PHYSDRAM & KZERO, invalidate TLBs, revert
+ * to tiny addresses. upon return, it will be safe to turn off the mmu.
+ */
+TEXT cachesoff(SB), 1, $-4
+ MOVM.DB.W [R14,R1-R10], (R13) /* save regs on stack */
+ MOVW CPSR, R0
+ ORR $(PsrDirq|PsrDfiq), R0
+ MOVW R0, CPSR
+ BARRIERS
+
+ SUB $12, SP /* paranoia */
+ BL cacheuwbinv(SB)
+ ADD $12, SP /* paranoia */
+
+ MRC CpSC, 0, R0, C(CpCONTROL), C(0)
+ BIC $(CpCicache|CpCdcache), R0
+ MCR CpSC, 0, R0, C(CpCONTROL), C(0) /* caches off */
+ BARRIERS
+
+ /*
+ * caches are off
+ */
+
+ /* invalidate stale TLBs before changing them */
+ MOVW $KZERO, R0 /* some valid virtual address */
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
+ BARRIERS
+
+ /* redo double map of PHYSDRAM, KZERO */
+ MOVW $PHYSDRAM, R3
+ CMP $KZERO, R3
+ BEQ noun2map
+ MOVW $(L1+L1X(PHYSDRAM)), R4 /* address of PHYSDRAM's PTE */
+ MOVW $PTEDRAM, R2 /* PTE bits */
+ MOVW $DOUBLEMAPMBS, R5
+_ptrdbl:
+ ORR R3, R2, R1 /* first identity-map 0 to 0, etc. */
+ MOVW R1, (R4)
+ ADD $4, R4 /* bump PTE address */
+ ADD $MiB, R3 /* bump pa */
+ SUB.S $1, R5
+ BNE _ptrdbl
+noun2map:
+
+ /*
+ * flush stale TLB entries
+ */
+
+ BARRIERS
+ MOVW $KZERO, R0 /* some valid virtual address */
+ MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
+ BARRIERS
+
+ /* switch back to PHYSDRAM addressing, mainly for SB */
+ MOVW $KSEGM, R7 /* clear segment bits */
+ MOVW $PHYSDRAM, R0 /* set dram base bits */
+ BIC R7, R12 /* adjust SB */
+ ORR R0, R12
+ BIC R7, SP
+ ORR R0, SP
+
+ MOVM.IA.W (R13), [R14,R1-R10] /* restore regs from stack */
+
+ MOVW $KSEGM, R0 /* clear segment bits */
+ BIC R0, R14 /* adjust link */
+ MOVW $PHYSDRAM, R0 /* set dram base bits */
+ ORR R0, R14
+
+ RET
+
+TEXT _r15warp(SB), 1, $-4
+ BIC R7, R14 /* link */
+ ORR R0, R14
+
+ BIC R7, R13 /* SP */
+ ORR R0, R13
+ RET
+
+TEXT panic(SB), 1, $-4 /* stub */
+WAVE('?')
+ RET
+TEXT pczeroseg(SB), 1, $-4 /* stub */
+ RET
+
+#include "cache.v7.s"
diff --git a/sys/src/9/omap/screen.c b/sys/src/9/omap/screen.c
new file mode 100755
index 000000000..e47fd2821
--- /dev/null
+++ b/sys/src/9/omap/screen.c
@@ -0,0 +1,791 @@
+/*
+ * ti omap35 display subsystem (dss)
+ *
+ * can handle 2ⁿ bits per pixel for 0 < n ≤ 4, and 12 and 24 bits.
+ * can handle 1024×768 at 60 Hz with pixel clock of 63.5 MHz
+ * 1280×800 at 59.91 Hz with pixel clock of 71 MHz
+ * 1400×1050 lcd at 50 MHz with pixel clock of 75 MHz
+ * has 256 24-bit entries in RGB palette
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+// #include "gamma.h"
+
+enum {
+ Tabstop = 4, /* should be 8 */
+ Scroll = 8, /* lines to scroll at one time */
+ /*
+ * screen settings for Wid and Ht, should a bit more dynamic?
+ * http://www.epanorama.net/faq/vga2rgb/calc.html
+ * used to calculate settings.
+ */
+
+// Hbp = (248-1) << 20,
+// Hfp = (48-1) << 8,
+// Hsw = 112-1,
+
+// Vbp = 38 << 20,
+// Vfp = 1 << 8,
+// Vsw = 3,
+
+ Tft = 0x60,
+
+ Loadmode = 2 << 1,
+ Fifosize = 0x400,
+
+ /* dispc sysconfig */
+ Midlemode = 2 << 12,
+ Sidlemode = 2 << 3,
+ EnableWakeup = 1 << 2,
+ Autoidle = 1 << 0,
+
+ /* dispc pool_freq */
+ Ipc = 1 << 14,
+ Ihs = 1 << 13,
+ Ivs = 1 << 12,
+ Acb = 0x28,
+
+ /* gfx attribs */
+ Burstsize = 2 << 6,
+ Format = 6 << 1,
+ Gfxenable = 1 << 0,
+
+ /* dispc control */
+ Gpout1 = 1 << 16,
+ Gpout0 = 1 << 15,
+ Tftdata = 3 << 8,
+ Digital = 1 << 6,
+ Lcd = 1 << 5,
+ Stntft = 1 << 3,
+ Digitalen = 1 << 1,
+// Lcden = 1 << 0, /* unused */
+};
+
+typedef struct Dispcregs Dispc;
+typedef struct Dssregs Dss;
+typedef struct Ioregs Ioregs;
+
+struct Ioregs { /* common registers, 68 (0x44) bytes */
+ ulong rev;
+ uchar _pad0[0x10-0x4];
+ ulong sysconf;
+ ulong sysstat;
+ ulong irqstat1;
+
+ /* Dispc only regs */
+ ulong irqen1;
+ ulong wkupen;
+ ulong _pad1;
+ ulong irqsts2;
+ ulong irqen2;
+ ulong _pad2[4];
+
+ ulong ctrl;
+};
+
+struct Dssregs { /* display subsys at 0x48050000 */
+ Ioregs;
+ ulong sdicrtl;
+ ulong pllcrtl;
+ uchar _pad3[0x5c-0x4c];
+ ulong sdistat;
+};
+
+struct Dispcregs { /* display ctlr at 0x48050400 */
+ Ioregs;
+ ulong config;
+ ulong _pad3;
+ ulong defaultcolor[2];
+ ulong transcolor[2];
+ ulong linestat;
+ ulong linenum;
+ ulong timing_h;
+ ulong timing_v;
+ ulong pol_req;
+ ulong divisor;
+ ulong alpha;
+ ulong digsize;
+ ulong lcdsize;
+
+ ulong base[2]; /* should allocate both to avoid dithering */
+ ulong pos;
+ ulong size;
+ ulong _pad4[4];
+ ulong attrib;
+ ulong fifothr;
+ ulong fifosize;
+ ulong rowinc;
+ ulong pixelinc;
+ ulong winskip;
+ ulong palette; /* gfx_table_ba */
+ uchar _pad5[0x5d4 - 0x4bc];
+
+ ulong datacycle[3];
+ uchar _pad5[0x620 - 0x5e0];
+
+ ulong cprcoefr;
+ ulong cprcoefg;
+ ulong cprcoefb;
+ ulong preload;
+};
+
+int drawdebug;
+Point ZP = {0, 0};
+Cursor arrow = {
+ { -1, -1 },
+ { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
+ 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
+ 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
+ 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
+ },
+ { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
+ 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
+ 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
+ 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
+ },
+};
+
+OScreen oscreen;
+Settings settings[] = {
+[Res800x600] { 800, 600, 60, RGB16, 40000, 88, 40, 128, 23, 1, 5, },
+[Res1024x768] { 1024, 768, 60, RGB16, 65000, 160, 24, 136, 29, 3, 7, },
+[Res1280x1024] { 1280, 1024, 60, RGB16, 108000, 248, 48, 112, 38, 1, 4, },
+[Res1400x1050] { 1400, 1050, 50, RGB16, 108000, 248, 48, 112, 38, 1, 4, }, // TODO
+};
+Omap3fb *framebuf;
+Memimage *gscreen;
+
+static Memdata xgdata;
+
+static Memimage xgscreen =
+{
+ { 0, 0, Wid, Ht }, /* r */
+ { 0, 0, Wid, Ht }, /* clipr */
+ Depth, /* depth */
+ 3, /* nchan */
+ RGB16, /* chan */
+ nil, /* cmap */
+ &xgdata, /* data */
+ 0, /* zero */
+ Wid*(Depth/BI2BY)/BY2WD, /* width in words of a single scan line */
+ 0, /* layer */
+ 0, /* flags */
+};
+
+static Memimage *conscol;
+static Memimage *back;
+
+static Memsubfont *memdefont;
+
+static Lock screenlock;
+
+static Point curpos;
+static int h, w;
+static int landscape = 0; /* screen orientation, default is 0: portrait */
+static ushort *vscreen; /* virtual screen */
+static Rectangle window;
+
+static Dispc *dispc = (Dispc *)PHYSDISPC;
+static Dss *dss = (Dss *)PHYSDSS;
+
+static void omapscreenputs(char *s, int n);
+static ulong rep(ulong, int);
+static void screenputc(char *buf);
+static void screenwin(void);
+
+/*
+ * 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 */
+
+static void
+lcdoff(void)
+{
+ dispc->ctrl &= ~1; /* disable the lcd */
+ coherence();
+
+ dispc->irqstat1 |= 1; /* set framedone */
+ coherence();
+
+ /* the lcd never comes ready, so don't bother with this */
+#ifdef notdef
+ /* spin until the frame is complete, but not forever */
+ for(cnt = 50; !(dispc->irqstat1 & 1) && cnt-- > 0; )
+ delay(10);
+#endif
+ delay(20); /* worst case for 1 frame, 50Hz */
+}
+
+static void
+dssstart(void)
+{
+ /* should reset the dss system */
+ dss->sysconf |= 1;
+ coherence();
+}
+
+/* see spruf98i §15.6.7.4.2 */
+static void
+configdispc(void)
+{
+ Settings *sp;
+
+ sp = oscreen.settings;
+ dss->ctrl &= 0x78; /* choose dss clock */
+ dispc->sysconf = Midlemode | Sidlemode | EnableWakeup | Autoidle;
+ dispc->config = Loadmode;
+ coherence();
+
+ /* pll */
+ dispc->defaultcolor[0] = 0; /* set background color to black? */
+ dispc->defaultcolor[1] = 0;
+ dispc->transcolor[0] = 0; /* set transparency to full */
+ dispc->transcolor[1] = 0;
+
+ dispc->timing_h = (sp->hbp-1) << 20 | (sp->hfp-1) << 8 |
+ (sp->hsw-1);
+ dispc->timing_v = sp->vbp << 20 | sp->vfp << 8 |
+ (sp->vsw-1);
+
+ dispc->pol_req = Ipc | Ihs | Ivs | Acb;
+ dispc->divisor = 1 << 16 | HOWMANY(432000, sp->pixelclock);
+
+ dispc->lcdsize = (sp->ht - 1) << 16 | (sp->wid - 1);
+ coherence();
+
+ dispc->base[0] = PADDR(framebuf->pixel);
+ dispc->base[1] = PADDR(framebuf->pixel);
+
+ dispc->pos = 0; /* place screen in the left corner */
+ /* use the whole screen */
+ dispc->size = (sp->ht - 1) << 16 | (sp->wid - 1);
+
+ /* what mode does plan 9 use for fb? */
+ dispc->attrib = Burstsize | Format | Gfxenable;
+
+ dispc->preload = Tft;
+ dispc->fifosize = Fifosize;
+ /* 1008 is max for our Burstsize */
+ dispc->fifothr = (Fifosize - 1) << 16 | (1008 - 1);
+
+ /* 1 byte is one pixel (not true, we use 2 bytes per pixel) */
+ dispc->rowinc = 1;
+ dispc->pixelinc = 1;
+ dispc->winskip = 0; /* don't skip anything */
+ coherence();
+
+ // dispc->palette = PADDR(framebuf->palette);
+}
+
+static void
+lcdon(int enable)
+{
+ dispc->ctrl = Gpout1 | Gpout0 | Tftdata | Digital | Lcd | Stntft |
+ Digitalen | enable;
+ coherence();
+ delay(10);
+}
+
+static void
+lcdstop(void)
+{
+ configscreengpio();
+ screenclockson();
+
+ lcdoff();
+}
+
+static void
+lcdinit(void)
+{
+ lcdstop();
+
+ dssstart();
+ configdispc();
+}
+
+/* Paint the image data with blue pixels */
+void
+screentest(void)
+{
+ int i;
+
+ for (i = nelem(framebuf->pixel) - 1; i >= 0; i--)
+ framebuf->pixel[i] = 0x1f; /* blue */
+// memset(framebuf->pixel, ~0, sizeof framebuf->pixel); /* white */
+}
+
+void
+screenpower(int on)
+{
+ blankscreen(on == 0);
+}
+
+/*
+ * 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);
+ flushmemscreen(swrect);
+}
+
+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)); // assertion fails on omap
+ 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);
+ flushmemscreen(swrect);
+ swvisible = 1;
+}
+
+int
+cursoron(int dolock)
+{
+ if (dolock)
+ lock(&oscreen);
+ cursoroff(0);
+ swcursordraw();
+ if (dolock)
+ unlock(&oscreen);
+ return 0;
+}
+
+void
+cursoroff(int dolock)
+{
+ if (dolock)
+ lock(&oscreen);
+ swcursorhide();
+ if (dolock)
+ unlock(&oscreen);
+}
+
+void
+swload(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);
+}
+
+/* called from devmouse */
+void
+setcursor(Cursor* curs)
+{
+ cursoroff(1);
+ oscreen.Cursor = *curs;
+ swload(curs);
+ cursoron(1);
+}
+
+int
+swmove(Point p)
+{
+ swpt = addpt(p, swoffset);
+ return 0;
+}
+
+void
+swcursorclock(void)
+{
+ int x;
+
+ if(!swenabled)
+ return;
+ swmove(mousexy());
+ 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;
+
+ if(!init){
+ init = 1;
+ addclock0link(swcursorclock, 10);
+ }
+ 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 fails\n");
+ return;
+ }
+
+ memfillcolor(swmask, DOpaque);
+ memfillcolor(swmask1, DOpaque);
+ memfillcolor(swimg, DBlack);
+ memfillcolor(swimg1, DBlack);
+}
+
+/* called from main and possibly later from devdss to change resolution */
+void
+screeninit(void)
+{
+ static int first = 1;
+
+ if (first) {
+ iprint("screeninit...");
+ oscreen.settings = &settings[Res1280x1024];
+
+ lcdstop();
+ if (framebuf)
+ free(framebuf);
+ /* mode is 16*32 = 512 */
+ framebuf = xspanalloc(sizeof *framebuf, 16*32, 0);
+ }
+
+ lcdinit();
+ lcdon(1);
+ if (first) {
+ memimageinit();
+ memdefont = getmemdefont();
+ screentest();
+ }
+
+ xgdata.ref = 1;
+ xgdata.bdata = (uchar *)framebuf->pixel;
+
+ gscreen = &xgscreen;
+ gscreen->r = Rect(0, 0, Wid, Ht);
+ gscreen->clipr = gscreen->r;
+ /* width, in words, of a single scan line */
+ gscreen->width = Wid * (Depth / BI2BY) / BY2WD;
+ flushmemscreen(gscreen->r);
+
+ blanktime = 3; /* minutes */
+
+ if (first) {
+ iprint("on: blue for 3 seconds...");
+ delay(3*1000);
+ iprint("\n");
+
+ screenwin(); /* draw border & top orange bar */
+ screenputs = omapscreenputs;
+ iprint("screen: frame buffer at %#p for %dx%d\n",
+ framebuf, oscreen.settings->wid, oscreen.settings->ht);
+
+ swenabled = 1;
+ swcursorinit(); /* needs gscreen set */
+ setcursor(&arrow);
+
+ first = 0;
+ }
+}
+
+/* flushmemscreen should change buffer? */
+void
+flushmemscreen(Rectangle r)
+{
+ ulong start, end;
+
+ if (r.min.x < 0)
+ r.min.x = 0;
+ if (r.max.x > Wid)
+ r.max.x = Wid;
+ if (r.min.y < 0)
+ r.min.y = 0;
+ if (r.max.y > Ht)
+ r.max.y = Ht;
+ if (rectclip(&r, gscreen->r) == 0)
+ return;
+ start = (ulong)&framebuf->pixel[r.min.y*Wid + r.min.x];
+ end = (ulong)&framebuf->pixel[(r.max.y - 1)*Wid + r.max.x -1];
+ cachedwbse((ulong *)start, end - start);
+}
+
+/*
+ * export screen to devdraw
+ */
+uchar*
+attachscreen(Rectangle *r, ulong *chan, int *d, int *width, int *softscreen)
+{
+ *r = gscreen->r;
+ *d = gscreen->depth;
+ *chan = gscreen->chan;
+ *width = gscreen->width;
+ *softscreen = (landscape == 0);
+ return (uchar *)gscreen->data->bdata;
+}
+
+void
+getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
+{
+ USED(p, pr, pg, pb);
+}
+
+int
+setcolor(ulong p, ulong r, ulong g, ulong b)
+{
+ USED(p, r, g, b);
+ return 0;
+}
+
+void
+blankscreen(int blank)
+{
+ if (blank)
+ lcdon(0);
+ else {
+ lcdinit();
+ lcdon(1);
+ }
+}
+
+static void
+omapscreenputs(char *s, int n)
+{
+ int i;
+ Rune r;
+ char buf[4];
+
+ if (!islo()) {
+ /* don't deadlock trying to print in interrupt */
+ if (!canlock(&screenlock))
+ return; /* discard s */
+ } else
+ lock(&screenlock);
+
+ while (n > 0) {
+ i = chartorune(&r, s);
+ if (i == 0) {
+ s++;
+ --n;
+ continue;
+ }
+ memmove(buf, s, i);
+ buf[i] = 0;
+ n -= i;
+ s += i;
+ screenputc(buf);
+ }
+ unlock(&screenlock);
+}
+
+static void
+screenwin(void)
+{
+ char *greet;
+ Memimage *orange;
+ Point p, q;
+ Rectangle r;
+
+ memsetchan(gscreen, RGB16);
+
+ back = memwhite;
+ conscol = memblack;
+
+ orange = allocmemimage(Rect(0, 0, 1, 1), RGB16);
+ orange->flags |= Frepl;
+ orange->clipr = gscreen->r;
+ orange->data->bdata[0] = 0x40; /* magic: colour? */
+ orange->data->bdata[1] = 0xfd; /* magic: colour? */
+
+ w = memdefont->info[' '].width;
+ h = memdefont->height;
+
+ r = insetrect(gscreen->r, 4);
+
+ memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S);
+ window = insetrect(r, 4);
+ memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
+
+ memimagedraw(gscreen, Rect(window.min.x, window.min.y,
+ window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S);
+ freememimage(orange);
+ window = insetrect(window, 5);
+
+ greet = " Plan 9 Console ";
+ p = addpt(window.min, Pt(10, 0));
+ q = memsubfontwidth(memdefont, greet);
+ memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
+ flushmemscreen(r);
+ window.min.y += h + 6;
+ curpos = window.min;
+ window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h;
+}
+
+static void
+scroll(void)
+{
+ int o;
+ Point p;
+ Rectangle r;
+
+ /* move window contents up Scroll text lines */
+ o = Scroll * h;
+ r = Rpt(window.min, Pt(window.max.x, window.max.y - o));
+ p = Pt(window.min.x, window.min.y + o);
+ memimagedraw(gscreen, r, gscreen, p, nil, p, S);
+ flushmemscreen(r);
+
+ /* clear the bottom Scroll text lines */
+ r = Rpt(Pt(window.min.x, window.max.y - o), window.max);
+ memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
+ flushmemscreen(r);
+
+ curpos.y -= o;
+}
+
+static void
+screenputc(char *buf)
+{
+ int w;
+ uint pos;
+ Point p;
+ Rectangle r;
+ static int *xp;
+ static int xbuf[256];
+
+ if (xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
+ xp = xbuf;
+
+ switch (buf[0]) {
+ case '\n':
+ if (curpos.y + h >= window.max.y)
+ scroll();
+ curpos.y += h;
+ screenputc("\r");
+ break;
+ case '\r':
+ xp = xbuf;
+ curpos.x = window.min.x;
+ break;
+ case '\t':
+ p = memsubfontwidth(memdefont, " ");
+ w = p.x;
+ if (curpos.x >= window.max.x - Tabstop * w)
+ screenputc("\n");
+
+ pos = (curpos.x - window.min.x) / w;
+ pos = Tabstop - pos % Tabstop;
+ *xp++ = curpos.x;
+ r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h);
+ memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
+ flushmemscreen(r);
+ curpos.x += pos * w;
+ break;
+ case '\b':
+ if (xp <= xbuf)
+ break;
+ xp--;
+ r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
+ memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
+ flushmemscreen(r);
+ curpos.x = *xp;
+ break;
+ case '\0':
+ break;
+ default:
+ p = memsubfontwidth(memdefont, buf);
+ w = p.x;
+
+ if (curpos.x >= window.max.x - w)
+ screenputc("\n");
+
+ *xp++ = curpos.x;
+ r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h);
+ memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
+ memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
+ flushmemscreen(r);
+ curpos.x += w;
+ }
+}
diff --git a/sys/src/9/omap/screen.h b/sys/src/9/omap/screen.h
new file mode 100755
index 000000000..ba9b36bd3
--- /dev/null
+++ b/sys/src/9/omap/screen.h
@@ -0,0 +1,105 @@
+typedef struct Cursor Cursor;
+typedef struct Cursorinfo Cursorinfo;
+typedef struct OScreen OScreen;
+typedef struct Omap3fb Omap3fb;
+typedef struct Settings Settings;
+
+struct Cursorinfo
+{
+ Cursor;
+ Lock;
+};
+
+extern Cursor arrow;
+extern Cursorinfo cursor;
+
+/* devmouse.c */
+extern void mousetrack(int, int, int, int);
+extern Point mousexy(void);
+
+extern void mouseaccelerate(int);
+extern void mouseresize(void);
+
+/* screen.c */
+extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*);
+extern void flushmemscreen(Rectangle);
+extern int cursoron(int);
+extern void cursoroff(int);
+extern void setcursor(Cursor*);
+extern int screensize(int, int, int, ulong);
+extern int screenaperture(int, int);
+extern Rectangle physgscreenr; /* actual monitor size */
+extern void blankscreen(int);
+
+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;
+
+#define ishwimage(i) 0 /* for ../port/devdraw.c */
+
+/* for communication between devdss.c and screen.c */
+
+enum {
+ /* maxima */
+ Wid = 1280,
+ Ht = 1024,
+ Depth = 16, /* bits per pixel */
+
+ Pcolours = 256, /* Palette */
+ Pred = 0,
+ Pgreen = 1,
+ Pblue = 2,
+
+ Pblack = 0x00,
+ Pwhite = 0xFF,
+
+ /* settings indices */
+ Res800x600 = 0,
+ Res1024x768,
+ Res1280x1024,
+ Res1400x1050,
+};
+
+struct Settings {
+ uint wid; /* width in pixels */
+ uint ht; /* height in pixels */
+ uint freq; /* refresh frequency; only printed */
+ uint chan; /* draw chan */
+
+ /* shouldn't be needed? */
+ uint pixelclock;
+
+ /* horizontal timing */
+ uint hbp; /* back porch: pixel clocks before scan line */
+ uint hfp; /* front porch: pixel clocks after scan line */
+ uint hsw; /* sync pulse width: more hfp */
+
+ /* vertical timing */
+ uint vbp; /* back porch: line clocks before frame */
+ uint vfp; /* front porch: line clocks after frame */
+ uint vsw; /* sync pulse width: more vfp */
+};
+
+struct OScreen {
+ Lock;
+ Cursor;
+ Settings *settings;
+ int open;
+};
+
+struct Omap3fb { /* frame buffer for 24-bit active color */
+// short palette[256];
+ /* pixel data, even; base type's width must match Depth */
+ ushort pixel[Wid*Ht];
+};
diff --git a/sys/src/9/omap/softfpu.c b/sys/src/9/omap/softfpu.c
new file mode 100755
index 000000000..7f01446c0
--- /dev/null
+++ b/sys/src/9/omap/softfpu.c
@@ -0,0 +1,119 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+int
+fpudevprocio(Proc* proc, void* a, long n, uintptr offset, int write)
+{
+ /*
+ * Called from procdevtab.read and procdevtab.write
+ * allow user process access to the FPU registers.
+ * This is the only FPU routine which is called directly
+ * from the port code; it would be nice to have dynamic
+ * creation of entries in the device file trees...
+ */
+ USED(proc, a, n, offset, write);
+
+ return 0;
+}
+
+void
+fpunotify(Ureg*)
+{
+ /*
+ * Called when a note is about to be delivered to a
+ * user process, usually at the end of a system call.
+ * Note handlers are not allowed to use the FPU so
+ * the state is marked (after saving if necessary) and
+ * checked in the Device Not Available handler.
+ */
+}
+
+void
+fpunoted(void)
+{
+ /*
+ * Called from sysnoted() via the machine-dependent
+ * noted() routine.
+ * Clear the flag set above in fpunotify().
+ */
+}
+
+void
+fpusysrfork(Ureg*)
+{
+ /*
+ * Called early in the non-interruptible path of
+ * sysrfork() via the machine-dependent syscall() routine.
+ * Save the state so that it can be easily copied
+ * to the child process later.
+ */
+}
+
+void
+fpusysrforkchild(Proc*, Ureg *, Proc*)
+{
+ /*
+ * Called later in sysrfork() via the machine-dependent
+ * sysrforkchild() routine.
+ * Copy the parent FPU state to the child.
+ */
+}
+
+void
+fpuprocsave(Proc*)
+{
+ /*
+ * Called from sched() and sleep() via the machine-dependent
+ * procsave() routine.
+ * About to go in to the scheduler.
+ * If the process wasn't using the FPU
+ * there's nothing to do.
+ */
+}
+
+void
+fpuprocrestore(Proc*)
+{
+ /*
+ * The process has been rescheduled and is about to run.
+ * Nothing to do here right now. If the process tries to use
+ * the FPU again it will cause a Device Not Available
+ * exception and the state will then be restored.
+ */
+}
+
+void
+fpusysprocsetup(Proc*)
+{
+ /*
+ * Disable the FPU.
+ * Called from sysexec() via sysprocsetup() to
+ * set the FPU for the new process.
+ */
+}
+
+void
+fpuinit(void)
+{
+}
+
+int
+fpuemu(Ureg* ureg)
+{
+ int nfp;
+
+ if(waserror()){
+ splhi();
+ postnote(up, 1, up->errstr, NDebug);
+ return 1;
+ }
+ spllo();
+ nfp = fpiarm(ureg);
+ splhi();
+ poperror();
+
+ return nfp;
+}
diff --git a/sys/src/9/omap/syscall.c b/sys/src/9/omap/syscall.c
new file mode 100755
index 000000000..f9f390e2b
--- /dev/null
+++ b/sys/src/9/omap/syscall.c
@@ -0,0 +1,333 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "../port/systab.h"
+
+#include <tos.h>
+#include "ureg.h"
+
+#include "arm.h"
+
+typedef struct {
+ uintptr ip;
+ Ureg* arg0;
+ char* arg1;
+ char msg[ERRMAX];
+ Ureg* old;
+ Ureg ureg;
+} NFrame;
+
+/*
+ * Return user to state before notify()
+ */
+static void
+noted(Ureg* cur, uintptr arg0)
+{
+ NFrame *nf;
+ Ureg *nur;
+
+ qlock(&up->debug);
+ if(arg0 != NRSTR && !up->notified){
+ qunlock(&up->debug);
+ pprint("call to noted() when not notified\n");
+ pexit("Suicide", 0);
+ }
+ up->notified = 0;
+ fpunoted();
+
+ nf = up->ureg;
+
+ /* sanity clause */
+ if(!okaddr(PTR2UINT(nf), sizeof(NFrame), 0)){
+ qunlock(&up->debug);
+ pprint("bad ureg in noted %#p\n", nf);
+ pexit("Suicide", 0);
+ }
+
+ /* don't let user change system flags */
+ nur = &nf->ureg;
+ nur->psr &= PsrMask|PsrDfiq|PsrDirq;
+ nur->psr |= (cur->psr & ~(PsrMask|PsrDfiq|PsrDirq));
+
+ memmove(cur, nur, sizeof(Ureg));
+
+ switch((int)arg0){
+ case NCONT:
+ case NRSTR:
+ if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->sp, BY2WD, 0)){
+ qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
+ pexit("Suicide", 0);
+ }
+ up->ureg = nf->old;
+ qunlock(&up->debug);
+ break;
+ case NSAVE:
+ if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->sp, BY2WD, 0)){
+ qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
+ pexit("Suicide", 0);
+ }
+ qunlock(&up->debug);
+
+ splhi();
+ nf->arg1 = nf->msg;
+ nf->arg0 = &nf->ureg;
+ nf->ip = 0;
+ cur->sp = PTR2UINT(nf);
+ break;
+ default:
+ pprint("unknown noted arg %#p\n", arg0);
+ up->lastnote.flag = NDebug;
+ /*FALLTHROUGH*/
+ case NDFLT:
+ if(up->lastnote.flag == NDebug){
+ qunlock(&up->debug);
+ pprint("suicide: %s\n", up->lastnote.msg);
+ }
+ else
+ qunlock(&up->debug);
+ pexit(up->lastnote.msg, up->lastnote.flag != NDebug);
+ }
+}
+
+/*
+ * Call user, if necessary, with note.
+ * Pass user the Ureg struct and the note on his stack.
+ */
+int
+notify(Ureg* ureg)
+{
+ int l;
+ Note *n;
+ u32int s;
+ uintptr sp;
+ NFrame *nf;
+
+ if(up->procctl)
+ procctl(up);
+ if(up->nnote == 0)
+ return 0;
+
+ fpunotify(ureg);
+
+ s = spllo();
+ qlock(&up->debug);
+
+ up->notepending = 0;
+ n = &up->note[0];
+ if(strncmp(n->msg, "sys:", 4) == 0){
+ l = strlen(n->msg);
+ if(l > ERRMAX-23) /* " pc=0x0123456789abcdef\0" */
+ l = ERRMAX-23;
+ snprint(n->msg + l, sizeof n->msg - l, " pc=%#lux", ureg->pc);
+ }
+
+ if(n->flag != NUser && (up->notified || up->notify == 0)){
+ if(n->flag == NDebug)
+ pprint("suicide: %s\n", n->msg);
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag != NDebug);
+ }
+
+ if(up->notified){
+ qunlock(&up->debug);
+ splhi();
+ return 0;
+ }
+
+ if(up->notify == nil){
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag != NDebug);
+ }
+ if(!okaddr(PTR2UINT(up->notify), 1, 0)){
+ pprint("suicide: notify function address %#p\n", up->notify);
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+
+ sp = ureg->sp - sizeof(NFrame);
+ if(!okaddr(sp, sizeof(NFrame), 1)){
+ qunlock(&up->debug);
+ pprint("suicide: notify stack address %#p\n", sp);
+ pexit("Suicide", 0);
+ }
+
+ nf = UINT2PTR(sp);
+ memmove(&nf->ureg, ureg, sizeof(Ureg));
+ nf->old = up->ureg;
+ up->ureg = nf;
+ memmove(nf->msg, up->note[0].msg, ERRMAX);
+ nf->arg1 = nf->msg;
+ nf->arg0 = &nf->ureg;
+ nf->ip = 0;
+
+ ureg->sp = sp;
+ ureg->pc = PTR2UINT(up->notify);
+ up->notified = 1;
+ up->nnote--;
+ memmove(&up->lastnote, &up->note[0], sizeof(Note));
+ memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
+
+ qunlock(&up->debug);
+ splx(s);
+
+ return 1;
+}
+
+void
+syscall(Ureg* ureg)
+{
+ char *e;
+ u32int s;
+ ulong sp;
+ long ret;
+ int i, scallnr;
+
+ if(!userureg(ureg))
+ panic("syscall: from kernel: pc %#lux r14 %#lux psr %#lux",
+ ureg->pc, ureg->r14, ureg->psr);
+
+ cycles(&up->kentry);
+
+ m->syscall++;
+ up->insyscall = 1;
+ up->pc = ureg->pc;
+ up->dbgreg = ureg;
+
+ if(up->procctl == Proc_tracesyscall){
+ up->procctl = Proc_stopme;
+ procctl(up);
+ }
+
+ scallnr = ureg->r0;
+ up->scallnr = scallnr;
+ if(scallnr == RFORK)
+ fpusysrfork(ureg);
+ spllo();
+
+ sp = ureg->sp;
+ up->nerrlab = 0;
+ ret = -1;
+ if(!waserror()){
+ if(scallnr >= nsyscall){
+ pprint("bad sys call number %d pc %#lux\n",
+ scallnr, ureg->pc);
+ postnote(up, 1, "sys: bad sys call", NDebug);
+ error(Ebadarg);
+ }
+
+ if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)-BY2WD))
+ validaddr(sp, sizeof(Sargs)+BY2WD, 0);
+
+ up->s = *((Sargs*)(sp+BY2WD));
+ up->psstate = sysctab[scallnr];
+
+ /* iprint("%s: syscall %s\n", up->text, sysctab[scallnr]?sysctab[scallnr]:"huh?"); */
+
+ ret = systab[scallnr](up->s.args);
+ poperror();
+ }else{
+ /* failure: save the error buffer for errstr */
+ e = up->syserrstr;
+ up->syserrstr = up->errstr;
+ up->errstr = e;
+ }
+ if(up->nerrlab){
+ print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
+ for(i = 0; i < NERR; i++)
+ print("sp=%#p pc=%#p\n",
+ up->errlab[i].sp, up->errlab[i].pc);
+ panic("error stack");
+ }
+
+ /*
+ * Put return value in frame. On the x86 the syscall is
+ * just another trap and the return value from syscall is
+ * ignored. On other machines the return value is put into
+ * the results register by caller of syscall.
+ */
+ ureg->r0 = ret;
+
+ if(up->procctl == Proc_tracesyscall){
+ up->procctl = Proc_stopme;
+ s = splhi();
+ procctl(up);
+ splx(s);
+ }
+
+ up->insyscall = 0;
+ up->psstate = 0;
+
+ if(scallnr == NOTED)
+ noted(ureg, *(ulong*)(sp+BY2WD));
+
+ splhi();
+ if(scallnr != RFORK && (up->procctl || up->nnote))
+ notify(ureg);
+
+ /* if we delayed sched because we held a lock, sched now */
+ if(up->delaysched){
+ sched();
+ splhi();
+ }
+ kexit(ureg);
+}
+
+long /* void* */
+execregs(ulong entry, ulong ssize, ulong nargs)
+{
+ ulong *sp;
+ Ureg *ureg;
+
+ sp = (ulong*)(USTKTOP - ssize);
+ *--sp = nargs;
+
+ ureg = up->dbgreg;
+// memset(ureg, 0, 15*sizeof(ulong));
+ ureg->r13 = (ulong)sp;
+ ureg->pc = entry;
+//print("%lud: EXECREGS pc %#ux sp %#ux nargs %ld\n", up->pid, ureg->pc, ureg->r13, nargs);
+
+ /*
+ * return the address of kernel/user shared data
+ * (e.g. clock stuff)
+ */
+ return USTKTOP-sizeof(Tos);
+}
+
+void
+sysprocsetup(Proc* p)
+{
+ fpusysprocsetup(p);
+}
+
+/*
+ * Craft a return frame which will cause the child to pop out of
+ * the scheduler in user mode with the return register zero. Set
+ * pc to point to a l.s return function.
+ */
+void
+forkchild(Proc *p, Ureg *ureg)
+{
+ Ureg *cureg;
+
+//print("%lud setting up for forking child %lud\n", up->pid, p->pid);
+ p->sched.sp = (ulong)p->kstack+KSTACK-sizeof(Ureg);
+ p->sched.pc = (ulong)forkret;
+
+ cureg = (Ureg*)(p->sched.sp);
+ memmove(cureg, ureg, sizeof(Ureg));
+
+ /* syscall returns 0 for child */
+ cureg->r0 = 0;
+
+ /* Things from bottom of syscall which were never executed */
+ p->psstate = 0;
+ p->insyscall = 0;
+
+ fpusysrforkchild(p, cureg, up);
+}
diff --git a/sys/src/9/omap/trap.c b/sys/src/9/omap/trap.c
new file mode 100755
index 000000000..6b0911e1b
--- /dev/null
+++ b/sys/src/9/omap/trap.c
@@ -0,0 +1,769 @@
+/*
+ * omap3530 traps, exceptions, interrupts, system calls.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "ureg.h"
+#include "arm.h"
+
+enum {
+ Nirqs = 96,
+ Nvec = 8, /* # of vectors at start of lexception.s */
+ Bi2long = BI2BY * sizeof(long),
+};
+
+extern int notify(Ureg*);
+
+extern int ldrexvalid;
+
+/* omap35x intc (aka mpu_intc) */
+typedef struct Intrregs Intrregs;
+struct Intrregs {
+ /*
+ * the manual inserts "INTCPS_" before each register name;
+ * we'll just assume the prefix.
+ */
+ uchar _pad0[4*4];
+ ulong sysconfig;
+ ulong sysstatus; /* ro */
+ uchar _pad1[0x40 - 0x18];
+ ulong sir_irq; /* ro */
+ ulong sir_fiq; /* ro */
+ ulong control;
+ ulong protection;
+ ulong idle;
+ uchar _pad2[0x60 - 0x54];
+ ulong irq_priority;
+ ulong fiq_priority;
+ ulong threshold;
+ uchar _pad3[0x80 - 0x6c];
+ struct Bits { /* bitmaps */
+ ulong itr; /* ro: pending intrs (no mask) */
+ ulong mir; /* interrupt mask: 1 means masked */
+ ulong mir_clear; /* wo: 1 sets the bit */
+ ulong mir_set; /* wo: 1 clears the bit */
+ ulong isr_set; /* software interrupts */
+ ulong isr_clear; /* wo */
+ ulong pending_irq; /* ro */
+ ulong pending_fiq; /* ro */
+ } bits[3]; /* 3*32 = 96 (Nirqs) */
+ ulong ilr[Nirqs];
+};
+
+enum {
+ /* sysconfig bits */
+ Softreset = 1<<1,
+
+ /* sysstatus bits */
+ Resetdone = 1<<0,
+
+ /* sir_irq/fiq bits */
+ Activeirq = MASK(7),
+
+ /* control bits */
+ Newirqagr = 1<<0,
+
+ /* protection bits */
+ Protection = 1<<0,
+
+ /* irq/fiq_priority bits */
+ Irqpriority = MASK(6),
+
+ /* threshold bits */
+ Prioritythreshold = MASK(8),
+
+ /* ilr bits */
+ Priority = MASK(8) - MASK(2),
+};
+
+typedef struct Vctl Vctl;
+typedef struct Vctl {
+ Vctl* next; /* handlers on this vector */
+ char *name; /* of driver, xallocated */
+ void (*f)(Ureg*, void*); /* handler to call */
+ void* a; /* argument to call it with */
+} Vctl;
+
+static Lock vctllock;
+static Vctl* vctl[Nirqs];
+
+/*
+ * Layout at virtual address 0.
+ */
+typedef struct Vpage0 {
+ void (*vectors[Nvec])(void);
+ u32int vtable[Nvec];
+} Vpage0;
+static Vpage0 *vpage0;
+
+uvlong ninterrupt;
+uvlong ninterruptticks;
+int irqtooearly = 1;
+
+static volatile int probing, trapped;
+
+static int
+irqinuse(uint irq)
+{
+ Intrregs *ip = (Intrregs *)PHYSINTC;
+
+ /*
+ * mir registers are odd: a 0 bit means intr unmasked (i.e.,
+ * we've unmasked it because it's in use).
+ */
+ return (ip->bits[irq / Bi2long].mir & (1 << (irq % Bi2long))) == 0;
+}
+
+static void
+intcmask(uint irq)
+{
+ Intrregs *ip = (Intrregs *)PHYSINTC;
+
+ ip->bits[irq / Bi2long].mir_set = 1 << (irq % Bi2long);
+ coherence();
+}
+
+static void
+intcunmask(uint irq)
+{
+ Intrregs *ip = (Intrregs *)PHYSINTC;
+
+ ip->bits[irq / Bi2long].mir_clear = 1 << (irq % Bi2long);
+ coherence();
+}
+
+static void
+intcmaskall(void)
+{
+ int i;
+ Intrregs *ip = (Intrregs *)PHYSINTC;
+
+ for (i = 0; i < 3; i++)
+ ip->bits[i].mir_set = ~0;
+ coherence();
+}
+
+static void
+intcunmaskall(void)
+{
+ int i;
+ Intrregs *ip = (Intrregs *)PHYSINTC;
+
+ for (i = 0; i < 3; i++)
+ ip->bits[i].mir_clear = ~0;
+ coherence();
+}
+
+static void
+intcinvertall(void)
+{
+ int i, s;
+ ulong bits;
+ Intrregs *ip = (Intrregs *)PHYSINTC;
+
+ s = splhi();
+ for (i = 0; i < 3; i++) {
+ bits = ip->bits[i].mir;
+ ip->bits[i].mir_set = ~0; /* mask all */
+ coherence();
+ /* clearing enables only those intrs. that were disabled */
+ ip->bits[i].mir_clear = bits;
+ }
+ coherence();
+ splx(s);
+}
+
+static void
+intrsave(ulong buf[3])
+{
+ int i;
+ Intrregs *ip = (Intrregs *)PHYSINTC;
+
+ for (i = 0; i < nelem(buf); i++)
+ buf[i] = ip->bits[i].mir;
+ coherence();
+}
+
+static void
+intrrestore(ulong buf[3])
+{
+ int i, s;
+ Intrregs *ip = (Intrregs *)PHYSINTC;
+
+ s = splhi();
+ for (i = 0; i < nelem(buf); i++) {
+ ip->bits[i].mir_clear = ~0; /* unmask all */
+ coherence();
+ ip->bits[i].mir_set = buf[i]; /* mask previously disabled */
+ }
+ coherence();
+ splx(s);
+}
+
+/*
+ * set up for exceptions
+ */
+void
+trapinit(void)
+{
+ int i;
+ Intrregs *ip = (Intrregs *)PHYSINTC;
+
+ /* set up the exception vectors */
+ vpage0 = (Vpage0*)HVECTORS;
+ memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
+ memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
+ cacheuwbinv();
+ l2cacheuwbinv();
+
+ /* set up the stacks for the interrupt modes */
+ setr13(PsrMfiq, m->sfiq);
+ setr13(PsrMirq, m->sirq);
+ setr13(PsrMabt, m->sabt);
+ setr13(PsrMund, m->sund);
+#ifdef HIGH_SECURITY
+ setr13(PsrMmon, m->smon);
+#endif
+ setr13(PsrMsys, m->ssys);
+
+ intcmaskall();
+ ip->control = 0;
+ ip->threshold = Prioritythreshold; /* disable threshold */
+ for (i = 0; i < Nirqs; i++)
+ ip->ilr[i] = 0<<2 | 0; /* all intrs pri 0 & to irq, not fiq */
+ irqtooearly = 0;
+ coherence();
+}
+
+void
+intrsoff(void)
+{
+ Intrregs *ip = (Intrregs *)PHYSINTC;
+
+ intcmaskall();
+ ip->control = Newirqagr; /* dismiss interrupt */
+ coherence();
+}
+
+/*
+ * enable an irq interrupt
+ */
+int
+irqenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
+{
+ Vctl *v;
+
+ if(irq >= nelem(vctl) || irq < 0)
+ panic("irqenable irq %d", irq);
+
+ if (irqtooearly) {
+ iprint("irqenable for %d %s called too early\n", irq, name);
+ return -1;
+ }
+ if(irqinuse(irq))
+ print("irqenable: %s: irq %d already in use, chaining\n",
+ name, irq);
+ v = malloc(sizeof(Vctl));
+ if (v == nil)
+ panic("irqenable: malloc Vctl");
+ v->f = f;
+ v->a = a;
+ v->name = malloc(strlen(name)+1);
+ if (v->name == nil)
+ panic("irqenable: malloc name");
+ strcpy(v->name, name);
+
+ lock(&vctllock);
+ v->next = vctl[irq];
+ vctl[irq] = v;
+
+ intcunmask(irq);
+ unlock(&vctllock);
+ return 0;
+}
+
+/*
+ * disable an irq interrupt
+ */
+int
+irqdisable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
+{
+ Vctl **vp, *v;
+
+ if(irq >= nelem(vctl) || irq < 0)
+ panic("irqdisable irq %d", irq);
+
+ lock(&vctllock);
+ for(vp = &vctl[irq]; v = *vp; vp = &v->next)
+ if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
+ print("irqdisable: remove %s\n", name);
+ *vp = v->next;
+ free(v);
+ break;
+ }
+
+ if(v == nil)
+ print("irqdisable: irq %d, name %s not enabled\n", irq, name);
+ if(vctl[irq] == nil){
+ print("irqdisable: clear icmr bit %d\n", irq);
+ intcmask(irq);
+ }
+ unlock(&vctllock);
+
+ return 0;
+}
+
+/*
+ * called by trap to handle access faults
+ */
+static void
+faultarm(Ureg *ureg, uintptr va, int user, int read)
+{
+ int n, insyscall;
+ char buf[ERRMAX];
+
+ if(up == nil) {
+ dumpregs(ureg);
+ panic("fault: nil up in faultarm, accessing %#p", va);
+ }
+ insyscall = up->insyscall;
+ up->insyscall = 1;
+ n = fault(va, read);
+ if(n < 0){
+ if(!user){
+ dumpregs(ureg);
+ panic("fault: kernel accessing %#p", va);
+ }
+ /* don't dump registers; programs suicide all the time */
+ snprint(buf, sizeof buf, "sys: trap: fault %s va=%#p",
+ read? "read": "write", va);
+ postnote(up, 1, buf, NDebug);
+ }
+ up->insyscall = insyscall;
+}
+
+/*
+ * called by trap to handle interrupts.
+ * returns true iff a clock interrupt, thus maybe reschedule.
+ */
+static int
+irq(Ureg* ureg)
+{
+ int clockintr;
+ uint irqno, handled, t, ticks = perfticks();
+ Intrregs *ip = (Intrregs *)PHYSINTC;
+ Vctl *v;
+ static int nesting, lastirq = -1;
+
+ handled = 0;
+ irqno = ip->sir_irq & Activeirq;
+
+ if (irqno >= 37 && irqno <= 47) /* this is a clock intr? */
+ m->inclockintr++; /* yes, count nesting */
+ lastirq = irqno;
+
+ if (irqno >= nelem(vctl)) {
+ iprint("trap: irq %d >= # vectors (%d)\n", irqno, nelem(vctl));
+ ip->control = Newirqagr; /* dismiss interrupt */
+ return 0;
+ }
+
+ ++nesting;
+ for(v = vctl[irqno]; v != nil; v = v->next)
+ if (v->f) {
+ if (islo())
+ panic("trap: pl0 before trap handler for %s",
+ v->name);
+ v->f(ureg, v->a);
+ if (islo())
+ panic("trap: %s lowered pl", v->name);
+// splhi(); /* in case v->f lowered pl */
+ handled++;
+ }
+ if(!handled) {
+ iprint("unexpected interrupt: irq %d", irqno);
+ switch (irqno) {
+ case 56:
+ case 57:
+ iprint(" (I⁲C)");
+ break;
+ case 83:
+ case 86:
+ case 94:
+ iprint(" (MMC)");
+ break;
+ }
+
+ if(irqno < nelem(vctl)) {
+ intcmask(irqno);
+ iprint(", now masked");
+ }
+ iprint("\n");
+ }
+ t = perfticks();
+ ninterrupt++;
+ if(t < ticks)
+ ninterruptticks += ticks-t;
+ else
+ ninterruptticks += t-ticks;
+ ip->control = Newirqagr; /* dismiss interrupt */
+ coherence();
+
+ --nesting;
+ clockintr = m->inclockintr == 1;
+ if (irqno >= 37 && irqno <= 47)
+ m->inclockintr--;
+ return clockintr;
+}
+
+/*
+ * returns 1 if the instruction writes memory, 0 otherwise
+ */
+int
+writetomem(ulong inst)
+{
+ /* swap always write memory */
+ if((inst & 0x0FC00000) == 0x01000000)
+ return 1;
+
+ /* loads and stores are distinguished by bit 20 */
+ if(inst & (1<<20))
+ return 0;
+
+ return 1;
+}
+
+void prgpmcerrs(void);
+
+/*
+ * here on all exceptions other than syscall (SWI)
+ */
+void
+trap(Ureg *ureg)
+{
+ int clockintr, user, x, rv, rem;
+ ulong inst, fsr;
+ uintptr va;
+ char buf[ERRMAX];
+
+ splhi(); /* paranoia */
+ if(up != nil)
+ rem = ((char*)ureg)-up->kstack;
+ else
+ rem = ((char*)ureg)-((char*)m+sizeof(Mach));
+ if(rem < 1024) {
+ iprint("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux\n",
+ rem, up, ureg, ureg->pc);
+ delay(1000);
+ dumpstack();
+ panic("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux",
+ rem, up, ureg, ureg->pc);
+ }
+
+ user = (ureg->psr & PsrMask) == PsrMusr;
+ if(user){
+ up->dbgreg = ureg;
+ cycles(&up->kentry);
+ }
+
+ /*
+ * All interrupts/exceptions should be resumed at ureg->pc-4,
+ * except for Data Abort which resumes at ureg->pc-8.
+ */
+ if(ureg->type == (PsrMabt+1))
+ ureg->pc -= 8;
+ else
+ ureg->pc -= 4;
+
+ clockintr = 0; /* if set, may call sched() before return */
+ switch(ureg->type){
+ default:
+ panic("unknown trap; type %#lux, psr mode %#lux", ureg->type,
+ ureg->psr & PsrMask);
+ break;
+ case PsrMirq:
+ ldrexvalid = 0;
+ clockintr = irq(ureg);
+ m->intr++;
+ break;
+ case PsrMabt: /* prefetch fault */
+ ldrexvalid = 0;
+ faultarm(ureg, ureg->pc, user, 1);
+ break;
+ case PsrMabt+1: /* data fault */
+ ldrexvalid = 0;
+ va = farget();
+ inst = *(ulong*)(ureg->pc);
+ /* bits 12 and 10 have to be concatenated with status */
+ x = fsrget();
+ fsr = (x>>7) & 0x20 | (x>>6) & 0x10 | x & 0xf;
+ if (probing && !user) {
+ if (trapped++ > 0)
+ panic("trap: recursive probe %#lux", va);
+ ureg->pc += 4; /* continue at next instruction */
+ break;
+ }
+ switch(fsr){
+ default:
+ case 0xa: /* ? was under external abort */
+ panic("unknown data fault, 6b fsr %#lux", fsr);
+ break;
+ case 0x0:
+ panic("vector exception at %#lux", ureg->pc);
+ break;
+ case 0x1: /* alignment fault */
+ case 0x3: /* access flag fault (section) */
+ if(user){
+ snprint(buf, sizeof buf,
+ "sys: alignment: pc %#lux va %#p\n",
+ ureg->pc, va);
+ postnote(up, 1, buf, NDebug);
+ } else
+ panic("kernel alignment: pc %#lux va %#p", ureg->pc, va);
+ break;
+ case 0x2:
+ panic("terminal exception at %#lux", ureg->pc);
+ break;
+ case 0x4: /* icache maint fault */
+ case 0x6: /* access flag fault (page) */
+ case 0x8: /* precise external abort, non-xlat'n */
+ case 0x28:
+ case 0xc: /* l1 translation, precise ext. abort */
+ case 0x2c:
+ case 0xe: /* l2 translation, precise ext. abort */
+ case 0x2e:
+ case 0x16: /* imprecise ext. abort, non-xlt'n */
+ case 0x36:
+ panic("external abort %#lux pc %#lux addr %#p",
+ fsr, ureg->pc, va);
+ break;
+ case 0x1c: /* l1 translation, precise parity err */
+ case 0x1e: /* l2 translation, precise parity err */
+ case 0x18: /* imprecise parity or ecc err */
+ panic("translation parity error %#lux pc %#lux addr %#p",
+ fsr, ureg->pc, va);
+ break;
+ case 0x5: /* translation fault, no section entry */
+ case 0x7: /* translation fault, no page entry */
+ faultarm(ureg, va, user, !writetomem(inst));
+ break;
+ case 0x9:
+ case 0xb:
+ /* domain fault, accessing something we shouldn't */
+ if(user){
+ snprint(buf, sizeof buf,
+ "sys: access violation: pc %#lux va %#p\n",
+ ureg->pc, va);
+ postnote(up, 1, buf, NDebug);
+ } else
+ panic("kernel access violation: pc %#lux va %#p",
+ ureg->pc, va);
+ break;
+ case 0xd:
+ case 0xf:
+ /* permission error, copy on write or real permission error */
+ faultarm(ureg, va, user, !writetomem(inst));
+ break;
+ }
+ break;
+ case PsrMund: /* undefined instruction */
+ if(user){
+ /* look for floating point instructions to interpret */
+ x = spllo();
+ rv = fpiarm(ureg);
+ splx(x);
+ if(rv == 0){
+ ldrexvalid = 0;
+ snprint(buf, sizeof buf,
+ "undefined instruction: pc %#lux\n",
+ ureg->pc);
+ postnote(up, 1, buf, NDebug);
+ }
+ }else{
+ if (ureg->pc & 3) {
+ iprint("rounding fault pc %#lux down to word\n",
+ ureg->pc);
+ ureg->pc &= ~3;
+ }
+ iprint("undefined instruction: pc %#lux inst %#ux\n",
+ ureg->pc, ((u32int*)ureg->pc)[-2]);
+ panic("undefined instruction");
+ }
+ break;
+ }
+ splhi();
+
+ /* delaysched set because we held a lock or because our quantum ended */
+ if(up && up->delaysched && clockintr){
+ ldrexvalid = 0;
+ sched(); /* can cause more traps */
+ splhi();
+ }
+
+ if(user){
+ if(up->procctl || up->nnote)
+ notify(ureg);
+ kexit(ureg);
+ }
+}
+
+/*
+ * Fill in enough of Ureg to get a stack trace, and call a function.
+ * Used by debugging interface rdb.
+ */
+void
+callwithureg(void (*fn)(Ureg*))
+{
+ Ureg ureg;
+
+ ureg.pc = getcallerpc(&fn);
+ ureg.sp = PTR2UINT(&fn);
+ fn(&ureg);
+}
+
+static void
+dumpstackwithureg(Ureg *ureg)
+{
+ int x;
+ uintptr l, v, i, estack;
+ char *s;
+
+ dumpregs(ureg);
+ if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){
+ iprint("dumpstack disabled\n");
+ return;
+ }
+ iprint("dumpstack\n");
+
+ x = 0;
+ x += iprint("ktrace /kernel/path %#.8lux %#.8lux %#.8lux # pc, sp, link\n",
+ ureg->pc, ureg->sp, ureg->r14);
+ delay(20);
+ i = 0;
+ if(up
+ && (uintptr)&l >= (uintptr)up->kstack
+ && (uintptr)&l <= (uintptr)up->kstack+KSTACK)
+ estack = (uintptr)up->kstack+KSTACK;
+ else if((uintptr)&l >= (uintptr)m->stack
+ && (uintptr)&l <= (uintptr)m+MACHSIZE)
+ estack = (uintptr)m+MACHSIZE;
+ else
+ return;
+ x += iprint("estackx %p\n", estack);
+
+ for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
+ v = *(uintptr*)l;
+ if((KTZERO < v && v < (uintptr)etext) || estack-l < 32){
+ x += iprint("%.8p ", v);
+ delay(20);
+ i++;
+ }
+ if(i == 8){
+ i = 0;
+ x += iprint("\n");
+ delay(20);
+ }
+ }
+ if(i)
+ iprint("\n");
+}
+
+void
+dumpstack(void)
+{
+ callwithureg(dumpstackwithureg);
+}
+
+/*
+ * dump system control coprocessor registers
+ */
+static void
+dumpscr(void)
+{
+ iprint("0:\t%#8.8ux id\n", cpidget());
+ iprint("\t%8.8#ux ct\n", cpctget());
+ iprint("1:\t%#8.8ux control\n", controlget());
+ iprint("2:\t%#8.8ux ttb\n", ttbget());
+ iprint("3:\t%#8.8ux dac\n", dacget());
+ iprint("4:\t(reserved)\n");
+ iprint("5:\t%#8.8ux fsr\n", fsrget());
+ iprint("6:\t%#8.8ux far\n", farget());
+ iprint("7:\twrite-only cache\n");
+ iprint("8:\twrite-only tlb\n");
+ iprint("13:\t%#8.8ux pid\n", pidget());
+ delay(10);
+}
+
+/*
+ * dump general registers
+ */
+static void
+dumpgpr(Ureg* ureg)
+{
+ if(up != nil)
+ iprint("cpu%d: registers for %s %lud\n",
+ m->machno, up->text, up->pid);
+ else
+ iprint("cpu%d: registers for kernel\n", m->machno);
+
+ delay(20);
+ iprint("%#8.8lux\tr0\n", ureg->r0);
+ iprint("%#8.8lux\tr1\n", ureg->r1);
+ iprint("%#8.8lux\tr2\n", ureg->r2);
+ delay(20);
+ iprint("%#8.8lux\tr3\n", ureg->r3);
+ iprint("%#8.8lux\tr4\n", ureg->r4);
+ iprint("%#8.8lux\tr5\n", ureg->r5);
+ delay(20);
+ iprint("%#8.8lux\tr6\n", ureg->r6);
+ iprint("%#8.8lux\tr7\n", ureg->r7);
+ iprint("%#8.8lux\tr8\n", ureg->r8);
+ delay(20);
+ iprint("%#8.8lux\tr9 (up)\n", ureg->r9);
+ iprint("%#8.8lux\tr10 (m)\n", ureg->r10);
+ iprint("%#8.8lux\tr11 (loader temporary)\n", ureg->r11);
+ iprint("%#8.8lux\tr12 (SB)\n", ureg->r12);
+ delay(20);
+ iprint("%#8.8lux\tr13 (sp)\n", ureg->r13);
+ iprint("%#8.8lux\tr14 (link)\n", ureg->r14);
+ iprint("%#8.8lux\tr15 (pc)\n", ureg->pc);
+ delay(20);
+ iprint("%10.10lud\ttype\n", ureg->type);
+ iprint("%#8.8lux\tpsr\n", ureg->psr);
+ delay(20);
+}
+
+void
+dumpregs(Ureg* ureg)
+{
+ dumpgpr(ureg);
+ dumpscr();
+}
+
+vlong
+probeaddr(uintptr addr)
+{
+ vlong v;
+ static Lock fltlck;
+
+ ilock(&fltlck);
+ trapped = 0;
+ probing = 1;
+ coherence();
+
+ v = *(ulong *)addr; /* this may cause a fault */
+ USED(probing);
+ coherence();
+
+ probing = 0;
+ coherence();
+ if (trapped)
+ v = -1;
+ iunlock(&fltlck);
+ return v;
+}
diff --git a/sys/src/9/omap/uarti8250.c b/sys/src/9/omap/uarti8250.c
new file mode 100755
index 000000000..7642a2685
--- /dev/null
+++ b/sys/src/9/omap/uarti8250.c
@@ -0,0 +1,850 @@
+/*
+ * omap35 8250-like UART
+ *
+ * we ignore the first 2 uarts on the omap35 (see below) and use the
+ * third one but call it 0.
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+enum { /* registers */
+ Rbr = 0, /* Receiver Buffer (RO) */
+ Thr = 0, /* Transmitter Holding (WO) */
+ Ier = 1, /* Interrupt Enable */
+ Iir = 2, /* Interrupt Identification (RO) */
+ Fcr = 2, /* FIFO Control (WO) */
+ Lcr = 3, /* Line Control */
+ Mcr = 4, /* Modem Control */
+ Lsr = 5, /* Line Status */
+ Msr = 6, /* Modem Status */
+ Scr = 7, /* Scratch Pad */
+ Mdr = 8, /* Mode Def'n (omap rw) */
+// Usr = 31, /* Uart Status Register; missing in omap? */
+ Dll = 0, /* Divisor Latch LSB */
+ Dlm = 1, /* Divisor Latch MSB */
+};
+
+enum { /* Usr */
+ Busy = 0x01,
+};
+
+enum { /* Ier */
+ Erda = 0x01, /* Enable Received Data Available */
+ Ethre = 0x02, /* Enable Thr Empty */
+ Erls = 0x04, /* Enable Receiver Line Status */
+ Ems = 0x08, /* Enable Modem Status */
+};
+
+enum { /* Iir */
+ Ims = 0x00, /* Ms interrupt */
+ Ip = 0x01, /* Interrupt Pending (not) */
+ Ithre = 0x02, /* Thr Empty */
+ Irda = 0x04, /* Received Data Available */
+ Irls = 0x06, /* Receiver Line Status */
+ Ictoi = 0x0C, /* Character Time-out Indication */
+ IirMASK = 0x3F,
+ Ifena = 0xC0, /* FIFOs enabled */
+};
+
+enum { /* Fcr */
+ FIFOena = 0x01, /* FIFO enable */
+ FIFOrclr = 0x02, /* clear Rx FIFO */
+ FIFOtclr = 0x04, /* clear Tx FIFO */
+// FIFOdma = 0x08,
+ FIFO1 = 0x00, /* Rx FIFO trigger level 1 byte */
+ FIFO4 = 0x40, /* 4 bytes */
+ FIFO8 = 0x80, /* 8 bytes */
+ FIFO14 = 0xC0, /* 14 bytes */
+};
+
+enum { /* Lcr */
+ Wls5 = 0x00, /* Word Length Select 5 bits/byte */
+ Wls6 = 0x01, /* 6 bits/byte */
+ Wls7 = 0x02, /* 7 bits/byte */
+ Wls8 = 0x03, /* 8 bits/byte */
+ WlsMASK = 0x03,
+ Stb = 0x04, /* 2 stop bits */
+ Pen = 0x08, /* Parity Enable */
+ Eps = 0x10, /* Even Parity Select */
+ Stp = 0x20, /* Stick Parity */
+ Brk = 0x40, /* Break */
+ Dlab = 0x80, /* Divisor Latch Access Bit */
+};
+
+enum { /* Mcr */
+ Dtr = 0x01, /* Data Terminal Ready */
+ Rts = 0x02, /* Ready To Send */
+ Out1 = 0x04, /* no longer in use */
+// Ie = 0x08, /* IRQ Enable (cd_sts_ch on omap) */
+ Dm = 0x10, /* Diagnostic Mode loopback */
+};
+
+enum { /* Lsr */
+ Dr = 0x01, /* Data Ready */
+ Oe = 0x02, /* Overrun Error */
+ Pe = 0x04, /* Parity Error */
+ Fe = 0x08, /* Framing Error */
+ Bi = 0x10, /* Break Interrupt */
+ Thre = 0x20, /* Thr Empty */
+ Temt = 0x40, /* Transmitter Empty */
+ FIFOerr = 0x80, /* error in receiver FIFO */
+};
+
+enum { /* Msr */
+ Dcts = 0x01, /* Delta Cts */
+ Ddsr = 0x02, /* Delta Dsr */
+ Teri = 0x04, /* Trailing Edge of Ri */
+ Ddcd = 0x08, /* Delta Dcd */
+ Cts = 0x10, /* Clear To Send */
+ Dsr = 0x20, /* Data Set Ready */
+ Ri = 0x40, /* Ring Indicator */
+ Dcd = 0x80, /* Carrier Detect */
+};
+
+enum { /* Mdr */
+ Modemask = 7,
+ Modeuart = 0,
+};
+
+
+typedef struct Ctlr {
+ u32int* io;
+ int irq;
+ int tbdf;
+ int iena;
+ int poll;
+
+ uchar sticky[Scr+1];
+
+ Lock;
+ int hasfifo;
+ int checkfifo;
+ int fena;
+} Ctlr;
+
+extern PhysUart i8250physuart;
+
+static Ctlr i8250ctlr[] = {
+{ .io = (u32int*)PHYSCONS, /* UART3 in TI terminology */
+ .irq = 74,
+ .tbdf = -1,
+ .poll = 0, },
+
+/* these exist, but I don't think they're connected to anything external */
+//{ .io = (u32int*)PHYSUART0,
+// .irq = 72,
+// .tbdf = -1,
+// .poll = 0, },
+//
+//{ .io = (u32int*)PHYSUART1,
+// .irq = 73,
+// .tbdf = -1,
+// .poll = 0, },
+};
+
+static Uart i8250uart[] = {
+{ .regs = &i8250ctlr[0], /* not [2] */
+ .name = "COM3",
+ .freq = 3686000, /* Not used, we use the global i8250freq */
+ .phys = &i8250physuart,
+ .console= 1,
+ .next = nil, },
+
+/* these exist, but I don't think they're connected to anything external */
+//{ .regs = &i8250ctlr[0],
+// .name = "COM1",
+// .freq = 3686000, /* Not used, we use the global i8250freq */
+// .phys = &i8250physuart,
+// .special= 0,
+// .next = &i8250uart[1], },
+//
+//{ .regs = &i8250ctlr[1],
+// .name = "COM2",
+// .freq = 3686000, /* Not used, we use the global i8250freq */
+// .phys = &i8250physuart,
+// .special= 0,
+// .next = &i8250uart[2], },
+};
+
+#define csr8r(c, r) ((c)->io[r])
+#define csr8w(c, r, v) ((c)->io[r] = (c)->sticky[r] | (v), coherence())
+#define csr8o(c, r, v) ((c)->io[r] = (v), coherence())
+
+static long
+i8250status(Uart* uart, void* buf, long n, long offset)
+{
+ char *p;
+ Ctlr *ctlr;
+ uchar ier, lcr, mcr, msr;
+
+ ctlr = uart->regs;
+ p = malloc(READSTR);
+ mcr = ctlr->sticky[Mcr];
+ msr = csr8r(ctlr, Msr);
+ ier = ctlr->sticky[Ier];
+ lcr = ctlr->sticky[Lcr];
+ snprint(p, READSTR,
+ "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
+ "dev(%d) type(%d) framing(%d) overruns(%d) "
+ "berr(%d) serr(%d)%s%s%s%s\n",
+
+ uart->baud,
+ uart->hup_dcd,
+ (msr & Dsr) != 0,
+ uart->hup_dsr,
+ (lcr & WlsMASK) + 5,
+ (ier & Ems) != 0,
+ (lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n',
+ (mcr & Rts) != 0,
+ (lcr & Stb) ? 2: 1,
+ ctlr->fena,
+
+ uart->dev,
+ uart->type,
+ uart->ferr,
+ uart->oerr,
+ uart->berr,
+ uart->serr,
+ (msr & Cts) ? " cts": "",
+ (msr & Dsr) ? " dsr": "",
+ (msr & Dcd) ? " dcd": "",
+ (msr & Ri) ? " ring": ""
+ );
+ n = readstr(offset, buf, n, p);
+ free(p);
+
+ return n;
+}
+
+static void
+i8250fifo(Uart* uart, int level)
+{
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ if(ctlr->hasfifo == 0)
+ return;
+
+ /*
+ * Changing the FIFOena bit in Fcr flushes data
+ * from both receive and transmit FIFOs; there's
+ * no easy way to guarantee not losing data on
+ * the receive side, but it's possible to wait until
+ * the transmitter is really empty.
+ */
+ ilock(ctlr);
+ while(!(csr8r(ctlr, Lsr) & Temt))
+ ;
+
+ /*
+ * Set the trigger level, default is the max.
+ * value.
+ * Some UARTs require FIFOena to be set before
+ * other bits can take effect, so set it twice.
+ */
+ ctlr->fena = level;
+ switch(level){
+ case 0:
+ break;
+ case 1:
+ level = FIFO1|FIFOena;
+ break;
+ case 4:
+ level = FIFO4|FIFOena;
+ break;
+ case 8:
+ level = FIFO8|FIFOena;
+ break;
+ default:
+ level = FIFO14|FIFOena;
+ break;
+ }
+ csr8w(ctlr, Fcr, level);
+ csr8w(ctlr, Fcr, level);
+ iunlock(ctlr);
+}
+
+static void
+i8250dtr(Uart* uart, int on)
+{
+ Ctlr *ctlr;
+
+ /*
+ * Toggle DTR.
+ */
+ ctlr = uart->regs;
+ if(on)
+ ctlr->sticky[Mcr] |= Dtr;
+ else
+ ctlr->sticky[Mcr] &= ~Dtr;
+ csr8w(ctlr, Mcr, 0);
+}
+
+static void
+i8250rts(Uart* uart, int on)
+{
+ Ctlr *ctlr;
+
+ /*
+ * Toggle RTS.
+ */
+ ctlr = uart->regs;
+ if(on)
+ ctlr->sticky[Mcr] |= Rts;
+ else
+ ctlr->sticky[Mcr] &= ~Rts;
+ csr8w(ctlr, Mcr, 0);
+}
+
+static void
+i8250modemctl(Uart* uart, int on)
+{
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ ilock(&uart->tlock);
+ if(on){
+ ctlr->sticky[Ier] |= Ems;
+ csr8w(ctlr, Ier, 0);
+ uart->modem = 1;
+ uart->cts = csr8r(ctlr, Msr) & Cts;
+ }
+ else{
+ ctlr->sticky[Ier] &= ~Ems;
+ csr8w(ctlr, Ier, 0);
+ uart->modem = 0;
+ uart->cts = 1;
+ }
+ iunlock(&uart->tlock);
+
+ /* modem needs fifo */
+ (*uart->phys->fifo)(uart, on);
+}
+
+static int
+i8250parity(Uart* uart, int parity)
+{
+ int lcr;
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ lcr = ctlr->sticky[Lcr] & ~(Eps|Pen);
+
+ switch(parity){
+ case 'e':
+ lcr |= Eps|Pen;
+ break;
+ case 'o':
+ lcr |= Pen;
+ break;
+ case 'n':
+ break;
+ default:
+ return -1;
+ }
+ ctlr->sticky[Lcr] = lcr;
+ csr8w(ctlr, Lcr, 0);
+
+ uart->parity = parity;
+
+ return 0;
+}
+
+static int
+i8250stop(Uart* uart, int stop)
+{
+ int lcr;
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ lcr = ctlr->sticky[Lcr] & ~Stb;
+
+ switch(stop){
+ case 1:
+ break;
+ case 2:
+ lcr |= Stb;
+ break;
+ default:
+ return -1;
+ }
+ ctlr->sticky[Lcr] = lcr;
+ csr8w(ctlr, Lcr, 0);
+
+ uart->stop = stop;
+
+ return 0;
+}
+
+static int
+i8250bits(Uart* uart, int bits)
+{
+ int lcr;
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ lcr = ctlr->sticky[Lcr] & ~WlsMASK;
+
+ switch(bits){
+ case 5:
+ lcr |= Wls5;
+ break;
+ case 6:
+ lcr |= Wls6;
+ break;
+ case 7:
+ lcr |= Wls7;
+ break;
+ case 8:
+ lcr |= Wls8;
+ break;
+ default:
+ return -1;
+ }
+ ctlr->sticky[Lcr] = lcr;
+ csr8w(ctlr, Lcr, 0);
+
+ uart->bits = bits;
+
+ return 0;
+}
+
+static int
+i8250baud(Uart* uart, int baud)
+{
+#ifdef notdef /* don't change the speed */
+ ulong bgc;
+ Ctlr *ctlr;
+ extern int i8250freq; /* In the config file */
+
+ /*
+ * Set the Baud rate by calculating and setting the Baud rate
+ * Generator Constant. This will work with fairly non-standard
+ * Baud rates.
+ */
+ if(i8250freq == 0 || baud <= 0)
+ return -1;
+ bgc = (i8250freq+8*baud-1)/(16*baud);
+
+ ctlr = uart->regs;
+ while(csr8r(ctlr, Usr) & Busy)
+ delay(1);
+ csr8w(ctlr, Lcr, Dlab); /* begin kludge */
+ csr8o(ctlr, Dlm, bgc>>8);
+ csr8o(ctlr, Dll, bgc);
+ csr8w(ctlr, Lcr, 0);
+#endif
+ uart->baud = baud;
+ return 0;
+}
+
+static void
+i8250break(Uart* uart, int ms)
+{
+ Ctlr *ctlr;
+
+ if (up == nil)
+ panic("i8250break: nil up");
+ /*
+ * Send a break.
+ */
+ if(ms <= 0)
+ ms = 200;
+
+ ctlr = uart->regs;
+ csr8w(ctlr, Lcr, Brk);
+ tsleep(&up->sleep, return0, 0, ms);
+ csr8w(ctlr, Lcr, 0);
+}
+
+static void
+emptyoutstage(Uart *uart, int n)
+{
+ _uartputs((char *)uart->op, n);
+ uart->op = uart->oe = uart->ostage;
+}
+
+static void
+i8250kick(Uart* uart)
+{
+ int i;
+ Ctlr *ctlr;
+
+ if(/* uart->cts == 0 || */ uart->blocked)
+ return;
+
+ if(!normalprint) { /* early */
+ if (uart->op < uart->oe)
+ emptyoutstage(uart, uart->oe - uart->op);
+ while ((i = uartstageoutput(uart)) > 0)
+ emptyoutstage(uart, i);
+ return;
+ }
+
+ /* nothing more to send? then disable xmit intr */
+ ctlr = uart->regs;
+ if (uart->op >= uart->oe && qlen(uart->oq) == 0 &&
+ csr8r(ctlr, Lsr) & Temt) {
+ ctlr->sticky[Ier] &= ~Ethre;
+ csr8w(ctlr, Ier, 0);
+ return;
+ }
+
+ /*
+ * 128 here is an arbitrary limit to make sure
+ * we don't stay in this loop too long. If the
+ * chip's output queue is longer than 128, too
+ * bad -- presotto
+ */
+ for(i = 0; i < 128; i++){
+ if(!(csr8r(ctlr, Lsr) & Thre))
+ break;
+ if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
+ break;
+ csr8o(ctlr, Thr, *uart->op++); /* start tx */
+ ctlr->sticky[Ier] |= Ethre;
+ csr8w(ctlr, Ier, 0); /* intr when done */
+ }
+}
+
+void
+serialkick(void)
+{
+ uartkick(&i8250uart[CONSOLE]);
+}
+
+static void
+i8250interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Uart *uart;
+ int iir, lsr, old, r;
+
+ uart = arg;
+ ctlr = uart->regs;
+ for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){
+ switch(iir & IirMASK){
+ case Ims: /* Ms interrupt */
+ r = csr8r(ctlr, Msr);
+ if(r & Dcts){
+ ilock(&uart->tlock);
+ old = uart->cts;
+ uart->cts = r & Cts;
+ if(old == 0 && uart->cts)
+ uart->ctsbackoff = 2;
+ iunlock(&uart->tlock);
+ }
+ if(r & Ddsr){
+ old = r & Dsr;
+ if(uart->hup_dsr && uart->dsr && !old)
+ uart->dohup = 1;
+ uart->dsr = old;
+ }
+ if(r & Ddcd){
+ old = r & Dcd;
+ if(uart->hup_dcd && uart->dcd && !old)
+ uart->dohup = 1;
+ uart->dcd = old;
+ }
+ break;
+ case Ithre: /* Thr Empty */
+ uartkick(uart);
+ break;
+ case Irda: /* Received Data Available */
+ case Irls: /* Receiver Line Status */
+ case Ictoi: /* Character Time-out Indication */
+ /*
+ * Consume any received data.
+ * If the received byte came in with a break,
+ * parity or framing error, throw it away;
+ * overrun is an indication that something has
+ * already been tossed.
+ */
+ while((lsr = csr8r(ctlr, Lsr)) & Dr){
+ if(lsr & (FIFOerr|Oe))
+ uart->oerr++;
+ if(lsr & Pe)
+ uart->perr++;
+ if(lsr & Fe)
+ uart->ferr++;
+ r = csr8r(ctlr, Rbr);
+ if(!(lsr & (Bi|Fe|Pe)))
+ uartrecv(uart, r);
+ }
+ break;
+
+ default:
+ iprint("weird uart interrupt type %#2.2uX\n", iir);
+ break;
+ }
+ }
+}
+
+static void
+i8250disable(Uart* uart)
+{
+ Ctlr *ctlr;
+
+ /*
+ * Turn off DTR and RTS, disable interrupts and fifos.
+ */
+ (*uart->phys->dtr)(uart, 0);
+ (*uart->phys->rts)(uart, 0);
+ (*uart->phys->fifo)(uart, 0);
+
+ ctlr = uart->regs;
+ ctlr->sticky[Ier] = 0;
+ csr8w(ctlr, Ier, 0);
+
+ if(ctlr->iena != 0){
+ if(irqdisable(ctlr->irq, i8250interrupt, uart, uart->name) == 0)
+ ctlr->iena = 0;
+ }
+}
+
+static void
+i8250enable(Uart* uart, int ie)
+{
+ int mode;
+ Ctlr *ctlr;
+
+ if (up == nil)
+ return; /* too soon */
+
+ ctlr = uart->regs;
+
+ /* omap only: set uart/irda/cir mode to uart */
+ mode = csr8r(ctlr, Mdr);
+ csr8o(ctlr, Mdr, (mode & ~Modemask) | Modeuart);
+
+ ctlr->sticky[Lcr] = Wls8; /* no parity */
+ csr8w(ctlr, Lcr, 0);
+
+ /*
+ * Check if there is a FIFO.
+ * Changing the FIFOena bit in Fcr flushes data
+ * from both receive and transmit FIFOs; there's
+ * no easy way to guarantee not losing data on
+ * the receive side, but it's possible to wait until
+ * the transmitter is really empty.
+ * Also, reading the Iir outwith i8250interrupt()
+ * can be dangerous, but this should only happen
+ * once, before interrupts are enabled.
+ */
+ ilock(ctlr);
+ if(!ctlr->checkfifo){
+ /*
+ * Wait until the transmitter is really empty.
+ */
+ while(!(csr8r(ctlr, Lsr) & Temt))
+ ;
+ csr8w(ctlr, Fcr, FIFOena);
+ if(csr8r(ctlr, Iir) & Ifena)
+ ctlr->hasfifo = 1;
+ csr8w(ctlr, Fcr, 0);
+ ctlr->checkfifo = 1;
+ }
+ iunlock(ctlr);
+
+ /*
+ * Enable interrupts and turn on DTR and RTS.
+ * Be careful if this is called to set up a polled serial line
+ * early on not to try to enable interrupts as interrupt-
+ * -enabling mechanisms might not be set up yet.
+ */
+ if(ie){
+ if(ctlr->iena == 0 && !ctlr->poll){
+ irqenable(ctlr->irq, i8250interrupt, uart, uart->name);
+ ctlr->iena = 1;
+ }
+ ctlr->sticky[Ier] = Erda;
+// ctlr->sticky[Mcr] |= Ie; /* not on omap */
+ ctlr->sticky[Mcr] = 0;
+ }
+ else{
+ ctlr->sticky[Ier] = 0;
+ ctlr->sticky[Mcr] = 0;
+ }
+ csr8w(ctlr, Ier, 0);
+ csr8w(ctlr, Mcr, 0);
+
+ (*uart->phys->dtr)(uart, 1);
+ (*uart->phys->rts)(uart, 1);
+
+ /*
+ * During startup, the i8259 interrupt controller is reset.
+ * This may result in a lost interrupt from the i8250 uart.
+ * The i8250 thinks the interrupt is still outstanding and does not
+ * generate any further interrupts. The workaround is to call the
+ * interrupt handler to clear any pending interrupt events.
+ * Note: this must be done after setting Ier.
+ */
+ if(ie)
+ i8250interrupt(nil, uart);
+}
+
+static Uart*
+i8250pnp(void)
+{
+ return i8250uart;
+}
+
+static int
+i8250getc(Uart* uart)
+{
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ while(!(csr8r(ctlr, Lsr) & Dr))
+ delay(1);
+ return csr8r(ctlr, Rbr);
+}
+
+static void
+i8250putc(Uart* uart, int c)
+{
+ int i;
+ Ctlr *ctlr;
+
+ if (!normalprint) { /* too early; use brute force */
+ int s = splhi();
+
+ while (!(((ulong *)PHYSCONS)[Lsr] & Thre))
+ ;
+ ((ulong *)PHYSCONS)[Thr] = c;
+ coherence();
+ splx(s);
+ return;
+ }
+
+ ctlr = uart->regs;
+ for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 128; i++)
+ delay(1);
+ csr8o(ctlr, Thr, (uchar)c);
+ for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 128; i++)
+ delay(1);
+}
+
+void
+serialputc(int c)
+{
+ i8250putc(&i8250uart[CONSOLE], c);
+}
+
+void
+serialputs(char* s, int n)
+{
+ _uartputs(s, n);
+}
+
+#ifdef notdef
+static void
+i8250poll(Uart* uart)
+{
+ Ctlr *ctlr;
+
+ /*
+ * If PhysUart has a non-nil .poll member, this
+ * routine will be called from the uartclock timer.
+ * If the Ctlr .poll member is non-zero, when the
+ * Uart is enabled interrupts will not be enabled
+ * and the result is polled input and output.
+ * Not very useful here, but ports to new hardware
+ * or simulators can use this to get serial I/O
+ * without setting up the interrupt mechanism.
+ */
+ ctlr = uart->regs;
+ if(ctlr->iena || !ctlr->poll)
+ return;
+ i8250interrupt(nil, uart);
+}
+#endif
+
+PhysUart i8250physuart = {
+ .name = "i8250",
+ .pnp = i8250pnp,
+ .enable = i8250enable,
+ .disable = i8250disable,
+ .kick = i8250kick,
+ .dobreak = i8250break,
+ .baud = i8250baud,
+ .bits = i8250bits,
+ .stop = i8250stop,
+ .parity = i8250parity,
+ .modemctl = i8250modemctl,
+ .rts = i8250rts,
+ .dtr = i8250dtr,
+ .status = i8250status,
+ .fifo = i8250fifo,
+ .getc = i8250getc,
+ .putc = i8250putc,
+// .poll = i8250poll, /* only in 9k, not 9 */
+};
+
+static void
+i8250dumpregs(Ctlr* ctlr)
+{
+ int dlm, dll;
+ int _uartprint(char*, ...);
+
+ csr8w(ctlr, Lcr, Dlab);
+ dlm = csr8r(ctlr, Dlm);
+ dll = csr8r(ctlr, Dll);
+ csr8w(ctlr, Lcr, 0);
+
+ _uartprint("dlm %#ux dll %#ux\n", dlm, dll);
+}
+
+Uart* uartenable(Uart *p);
+
+/* must call this from a process's context */
+int
+i8250console(void)
+{
+ Uart *uart = &i8250uart[CONSOLE];
+
+ if (up == nil)
+ return -1; /* too early */
+
+ if(uartenable(uart) != nil /* && uart->console */){
+ // iprint("i8250console: enabling console uart\n");
+ kbdq = uart->iq;
+ serialoq = uart->oq;
+ uart->putc = kbdcr2nl;
+ uart->opens++;
+ consuart = uart;
+ }
+ uartctl(uart, "b115200 l8 pn r1 s1 i1");
+ return 0;
+}
+
+void
+_uartputs(char* s, int n)
+{
+ char *e;
+
+ for(e = s+n; s < e; s++){
+ if(*s == '\n')
+ i8250putc(&i8250uart[CONSOLE], '\r');
+ i8250putc(&i8250uart[CONSOLE], *s);
+ }
+}
+
+int
+_uartprint(char* fmt, ...)
+{
+ int n;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+ _uartputs(buf, n);
+
+ return n;
+}
diff --git a/sys/src/9/omap/ucalloc.c b/sys/src/9/omap/ucalloc.c
new file mode 100755
index 000000000..37e8564c0
--- /dev/null
+++ b/sys/src/9/omap/ucalloc.c
@@ -0,0 +1,135 @@
+/*
+ * allocate uncached memory
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#include <pool.h>
+
+typedef struct Private Private;
+struct Private {
+ Lock;
+ char msg[256];
+ char* cur;
+};
+
+static Private ucprivate;
+
+static void
+ucpoolpanic(Pool* p, char* fmt, ...)
+{
+ va_list v;
+ Private *pv;
+ char msg[sizeof pv->msg];
+
+ pv = p->private;
+ va_start(v, fmt);
+ vseprint(pv->cur, &pv->msg[sizeof pv->msg], fmt, v);
+ va_end(v);
+ memmove(msg, pv->msg, sizeof msg);
+ iunlock(pv);
+ panic("%s", msg);
+}
+
+static void
+ucpoolprint(Pool* p, char* fmt, ...)
+{
+ va_list v;
+ Private *pv;
+
+ pv = p->private;
+ va_start(v, fmt);
+ pv->cur = vseprint(pv->cur, &pv->msg[sizeof pv->msg], fmt, v);
+ va_end(v);
+}
+
+static void
+ucpoolunlock(Pool* p)
+{
+ Private *pv;
+ char msg[sizeof pv->msg];
+
+ pv = p->private;
+ if(pv->cur == pv->msg){
+ iunlock(pv);
+ return;
+ }
+
+ memmove(msg, pv->msg, sizeof msg);
+ pv->cur = pv->msg;
+ iunlock(pv);
+
+ iprint("%.*s", sizeof pv->msg, msg);
+}
+
+static void
+ucpoollock(Pool* p)
+{
+ Private *pv;
+
+ pv = p->private;
+ ilock(pv);
+ pv->pc = getcallerpc(&p);
+ pv->cur = pv->msg;
+}
+
+static void*
+ucarena(usize size)
+{
+ void *uv, *v;
+
+ assert(size == 1*MiB);
+
+ mainmem->maxsize += 1*MiB;
+ if((v = mallocalign(1*MiB, 1*MiB, 0, 0)) == nil ||
+ (uv = mmuuncache(v, 1*MiB)) == nil){
+ free(v);
+ mainmem->maxsize -= 1*MiB;
+ return nil;
+ }
+ return uv;
+}
+
+static Pool ucpool = {
+ .name = "Uncached",
+ .maxsize = 4*MiB,
+ .minarena = 1*MiB-32,
+ .quantum = 32,
+ .alloc = ucarena,
+ .merge = nil,
+ .flags = /*POOL_TOLERANCE|POOL_ANTAGONISM|POOL_PARANOIA|*/0,
+
+ .lock = ucpoollock,
+ .unlock = ucpoolunlock,
+ .print = ucpoolprint,
+ .panic = ucpoolpanic,
+
+ .private = &ucprivate,
+};
+
+void
+ucfree(void* v)
+{
+ if(v == nil)
+ return;
+ poolfree(&ucpool, v);
+}
+
+void*
+ucalloc(usize size)
+{
+ assert(size < ucpool.minarena-128);
+
+ return poolallocalign(&ucpool, size, 32, 0, 0);
+}
+
+void*
+ucallocalign(usize size, int align, int span)
+{
+ assert(size < ucpool.minarena-128);
+
+ return poolallocalign(&ucpool, size, align, 0, span);
+}
diff --git a/sys/src/9/omap/ucallocb.c b/sys/src/9/omap/ucallocb.c
new file mode 100755
index 000000000..954c5d96a
--- /dev/null
+++ b/sys/src/9/omap/ucallocb.c
@@ -0,0 +1,152 @@
+/*
+ * allocate Blocks from uncached memory
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+
+enum
+{
+ Hdrspc = 64, /* leave room for high-level headers */
+ Bdead = 0x51494F42, /* "QIOB" */
+};
+
+struct
+{
+ Lock;
+ ulong bytes;
+} ucialloc;
+
+static Block*
+_ucallocb(int size)
+{
+ Block *b;
+ ulong addr;
+
+ if((b = ucalloc(sizeof(Block)+size+Hdrspc)) == nil)
+ return nil;
+
+ b->next = nil;
+ b->list = nil;
+ b->free = 0;
+ b->flag = 0;
+ b->ref = 0;
+ _xinc(&b->ref);
+
+ /* align start of data portion by rounding up */
+ addr = (ulong)b;
+ addr = ROUND(addr + sizeof(Block), BLOCKALIGN);
+ b->base = (uchar*)addr;
+
+ /* align end of data portion by rounding down */
+ b->lim = ((uchar*)b) + msize(b);
+ addr = (ulong)(b->lim);
+ addr = addr & ~(BLOCKALIGN-1);
+ b->lim = (uchar*)addr;
+
+ /* leave sluff at beginning for added headers */
+ b->rp = b->lim - ROUND(size, BLOCKALIGN);
+ if(b->rp < b->base)
+ panic("_ucallocb");
+ b->wp = b->rp;
+
+ return b;
+}
+
+Block*
+ucallocb(int size)
+{
+ Block *b;
+
+ /*
+ * Check in a process and wait until successful.
+ * Can still error out of here, though.
+ */
+ if(up == nil)
+ panic("ucallocb without up: %#p", getcallerpc(&size));
+ if((b = _ucallocb(size)) == nil)
+ panic("ucallocb: no memory for %d bytes", size);
+ setmalloctag(b, getcallerpc(&size));
+
+ return b;
+}
+
+Block*
+uciallocb(int size)
+{
+ Block *b;
+ static int m1, m2, mp;
+
+ if(0 && ucialloc.bytes > conf.ialloc){
+ if((m1++%10000)==0){
+ if(mp++ > 1000){
+ active.exiting = 1;
+ exit(0);
+ }
+ iprint("uciallocb: limited %lud/%lud\n",
+ ucialloc.bytes, conf.ialloc);
+ }
+ return nil;
+ }
+
+ if((b = _ucallocb(size)) == nil){
+ if(0 && (m2++%10000)==0){
+ if(mp++ > 1000){
+ active.exiting = 1;
+ exit(0);
+ }
+ iprint("uciallocb: no memory %lud/%lud\n",
+ ucialloc.bytes, conf.ialloc);
+ }
+ return nil;
+ }
+ setmalloctag(b, getcallerpc(&size));
+ b->flag = BINTR;
+
+ ilock(&ucialloc);
+ ucialloc.bytes += b->lim - b->base;
+ iunlock(&ucialloc);
+
+ return b;
+}
+
+void
+ucfreeb(Block *b)
+{
+ void *dead = (void*)Bdead;
+ long ref;
+
+ if(b == nil || (ref = _xdec(&b->ref)) > 0)
+ return;
+
+ if(ref < 0){
+ dumpstack();
+ panic("ucfreeb: ref %ld; caller pc %#p", ref, getcallerpc(&b));
+ }
+
+ /*
+ * drivers which perform non cache coherent DMA manage their own buffer
+ * pool of uncached buffers and provide their own free routine.
+ */
+ if(b->free) {
+ b->free(b);
+ return;
+ }
+ if(b->flag & BINTR) {
+ ilock(&ucialloc);
+ ucialloc.bytes -= b->lim - b->base;
+ iunlock(&ucialloc);
+ }
+
+ /* poison the block in case someone is still holding onto it */
+ b->next = dead;
+ b->rp = dead;
+ b->wp = dead;
+ b->lim = dead;
+ b->base = dead;
+
+ ucfree(b);
+}
diff --git a/sys/src/9/omap/uncached.h b/sys/src/9/omap/uncached.h
new file mode 100755
index 000000000..9fffd31fc
--- /dev/null
+++ b/sys/src/9/omap/uncached.h
@@ -0,0 +1,36 @@
+/*
+ * running the l2 cache as write-back and using cached memory for
+ * usb data structures yields spurious errors such as
+ *
+ * qhintr: td 0x60ee3d80 csw 0x8824a error 0x48 transaction error
+ *
+ * from usbehci. so, at least for now, we will use uncached memory until
+ * we sort out the write-back problems.
+ */
+#define free ucfree
+#define malloc myucalloc
+#define mallocz ucallocz
+#define smalloc myucalloc
+#define xspanalloc ucallocalign
+
+#define allocb ucallocb
+#define iallocb uciallocb
+#define freeb ucfreeb
+
+static void *
+ucallocz(uint n, int)
+{
+ char *p = ucalloc(n);
+
+ if (p)
+ memset(p, 0, n);
+ else
+ panic("ucalloc: out of memory");
+ return p;
+}
+
+static void *
+myucalloc(uint n)
+{
+ return ucallocz(n, 1);
+}
diff --git a/sys/src/9/omap/usbehci.h b/sys/src/9/omap/usbehci.h
new file mode 100755
index 000000000..279b30a09
--- /dev/null
+++ b/sys/src/9/omap/usbehci.h
@@ -0,0 +1,243 @@
+/* override default macros from ../port/usb.h */
+#undef dprint
+#undef ddprint
+#undef deprint
+#undef ddeprint
+#define dprint if(ehcidebug)print
+#define ddprint if(ehcidebug>1)print
+#define deprint if(ehcidebug || ep->debug)print
+#define ddeprint if(ehcidebug>1 || ep->debug>1)print
+
+typedef struct Ctlr Ctlr;
+typedef struct Ecapio Ecapio;
+typedef struct Eopio Eopio;
+typedef struct Edbgio Edbgio;
+typedef struct Isoio Isoio;
+typedef struct Poll Poll;
+typedef struct Qh Qh;
+typedef struct Qtree Qtree;
+
+#pragma incomplete Ctlr;
+#pragma incomplete Ecapio;
+#pragma incomplete Eopio;
+#pragma incomplete Edbgio;
+#pragma incomplete Isoio;
+#pragma incomplete Poll;
+#pragma incomplete Qh;
+#pragma incomplete Qtree;
+
+
+/*
+ * EHCI interface registers and bits
+ */
+enum
+{
+ Cnports = 0xF, /* nport bits in Ecapio parms. */
+ Cdbgportshift = 20, /* debug port in Ecapio parms. */
+ Cdbgportmask = 0xF,
+ C64 = 1, /* 64-bits, in Ecapio capparms. */
+ Ceecpshift = 8, /* extended capabilities ptr. in */
+ Ceecpmask = 8, /* the Ecapio capparms reg. */
+ Clegacy = 1, /* legacy support cap. id */
+ CLbiossem = 2, /* legacy cap. bios sem. */
+ CLossem = 3, /* legacy cap. os sem */
+ CLcontrol = 4, /* legacy support control & status */
+
+ /* typed links */
+ Lterm = 1,
+ Litd = 0<<1,
+ Lqh = 1<<1,
+ Lsitd = 2<<1,
+ Lfstn = 3<<1, /* we don't use these */
+
+ /* Cmd reg. */
+ Cstop = 0x00000, /* stop running */
+ Crun = 0x00001, /* start operation */
+ Chcreset = 0x00002, /* host controller reset */
+ Cflsmask = 0x0000C, /* frame list size bits */
+ Cfls1024 = 0x00000, /* frame list size 1024 */
+ Cfls512 = 0x00004, /* frame list size 512 frames */
+ Cfls256 = 0x00008, /* frame list size 256 frames */
+ Cpse = 0x00010, /* periodic sched. enable */
+ Case = 0x00020, /* async sched. enable */
+ Ciasync = 0x00040, /* interrupt on async advance doorbell */
+ Citc1 = 0x10000, /* interrupt threshold ctl. 1 µframe */
+ Citc4 = 0x40000, /* same. 2 µframes */
+ /* ... */
+ Citc8 = 0x80000, /* same. 8 µframes (can go up to 64) */
+
+ /* Sts reg. */
+ Sasyncss = 0x08000, /* aync schedule status */
+ Speriodss = 0x04000, /* periodic schedule status */
+ Srecl = 0x02000, /* reclamnation (empty async sched.) */
+ Shalted = 0x01000, /* h.c. is halted */
+ Sasync = 0x00020, /* interrupt on async advance */
+ Sherr = 0x00010, /* host system error */
+ Sfrroll = 0x00008, /* frame list roll over */
+ Sportchg = 0x00004, /* port change detect */
+ Serrintr = 0x00002, /* error interrupt */
+ Sintr = 0x00001, /* interrupt */
+ Sintrs = 0x0003F, /* interrupts status */
+
+ /* Intr reg. */
+ Iusb = 0x01, /* intr. on usb */
+ Ierr = 0x02, /* intr. on usb error */
+ Iportchg = 0x04, /* intr. on port change */
+ Ifrroll = 0x08, /* intr. on frlist roll over */
+ Ihcerr = 0x10, /* intr. on host error */
+ Iasync = 0x20, /* intr. on async advance enable */
+ Iall = 0x3F, /* all interrupts */
+
+ /* Config reg. */
+ Callmine = 1, /* route all ports to us */
+
+ /* Portsc reg. */
+ Pspresent = 0x00000001, /* device present */
+ Psstatuschg = 0x00000002, /* Pspresent changed */
+ Psenable = 0x00000004, /* device enabled */
+ Pschange = 0x00000008, /* Psenable changed */
+ Psresume = 0x00000040, /* resume detected */
+ Pssuspend = 0x00000080, /* port suspended */
+ Psreset = 0x00000100, /* port reset */
+ Pspower = 0x00001000, /* port power on */
+ Psowner = 0x00002000, /* port owned by companion */
+ Pslinemask = 0x00000C00, /* line status bits */
+ Pslow = 0x00000400, /* low speed device */
+
+ /* Debug port csw reg. */
+ Cowner = 0x40000000, /* port owned by ehci */
+ Cenable = 0x10000000, /* debug port enabled */
+ Cdone = 0x00010000, /* request is done */
+ Cbusy = 0x00000400, /* port in use by a driver */
+ Cerrmask= 0x00000380, /* error code bits */
+ Chwerr = 0x00000100, /* hardware error */
+ Cterr = 0x00000080, /* transaction error */
+ Cfailed = 0x00000040, /* transaction did fail */
+ Cgo = 0x00000020, /* execute the transaction */
+ Cwrite = 0x00000010, /* request is a write */
+ Clen = 0x0000000F, /* data len */
+
+ /* Debug port pid reg. */
+ Prpidshift = 16, /* received pid */
+ Prpidmask = 0xFF,
+ Pspidshift = 8, /* sent pid */
+ Pspidmask = 0xFF,
+ Ptokshift = 0, /* token pid */
+ Ptokmask = 0xFF,
+
+ Ptoggle = 0x00008800, /* to update toggles */
+ Ptogglemask = 0x0000FF00,
+
+ /* Debug port addr reg. */
+ Adevshift = 8, /* device address */
+ Adevmask = 0x7F,
+ Aepshift = 0, /* endpoint number */
+ Aepmask = 0xF,
+};
+
+/*
+ * Capability registers (hw)
+ */
+struct Ecapio
+{
+ ulong cap; /* 00 controller capability register */
+ ulong parms; /* 04 structural parameters register */
+ ulong capparms; /* 08 capability parameters */
+ ulong portroute; /* 0c not on the CS5536 */
+};
+
+/*
+ * Debug port registers (hw)
+ */
+struct Edbgio
+{
+ ulong csw; /* control and status */
+ ulong pid; /* USB pid */
+ uchar data[8]; /* data buffer */
+ ulong addr; /* device and endpoint addresses */
+};
+
+struct Poll
+{
+ Lock;
+ Rendez;
+ int must;
+ int does;
+};
+
+struct Ctlr
+{
+ Rendez; /* for waiting to async advance doorbell */
+ Lock; /* for ilock. qh lists and basic ctlr I/O */
+ QLock portlck; /* for port resets/enable... (and doorbell) */
+ int active; /* in use or not */
+ Ecapio* capio; /* Capability i/o regs */
+ Eopio* opio; /* Operational i/o regs */
+
+ int nframes; /* 1024, 512, or 256 frames in the list */
+ ulong* frames; /* periodic frame list (hw) */
+ Qh* qhs; /* async Qh circular list for bulk/ctl */
+ Qtree* tree; /* tree of Qhs for the periodic list */
+ int ntree; /* number of dummy qhs in tree */
+ Qh* intrqhs; /* list of (not dummy) qhs in tree */
+ Isoio* iso; /* list of active Iso I/O */
+ ulong load;
+ ulong isoload;
+ int nintr; /* number of interrupts attended */
+ int ntdintr; /* number of intrs. with something to do */
+ int nqhintr; /* number of async td intrs. */
+ int nisointr; /* number of periodic td intrs. */
+ int nreqs;
+ Poll poll;
+};
+
+/*
+ * OMAP3-specific stuff
+ */
+
+enum {
+ /* hostconfig bits */
+ P1ulpi_bypass = 1<<0, /* utmi if set; else ulpi */
+};
+
+/*
+ * Operational registers (hw)
+ */
+struct Eopio
+{
+ ulong cmd; /* 00 command */
+ ulong sts; /* 04 status */
+ ulong intr; /* 08 interrupt enable */
+ ulong frno; /* 0c frame index */
+ ulong seg; /* 10 bits 63:32 of EHCI datastructs (unused) */
+ ulong frbase; /* 14 frame list base addr, 4096-byte boundary */
+ ulong link; /* 18 link for async list */
+ uchar d2c[0x40-0x1c]; /* 1c dummy */
+ ulong config; /* 40 1: all ports default-routed to this HC */
+ ulong portsc[3]; /* 44 Port status and control, one per port */
+
+ /* defined for omap35 ehci at least */
+ uchar _pad0[0x80 - 0x50];
+ ulong insn[6]; /* implementation-specific */
+};
+
+typedef struct Uhh Uhh;
+struct Uhh {
+ ulong revision; /* ro */
+ uchar _pad0[0x10-0x4];
+ ulong sysconfig;
+ ulong sysstatus; /* ro */
+
+ uchar _pad1[0x40-0x18];
+ ulong hostconfig;
+ ulong debug_csr;
+};
+
+extern Ecapio *ehcidebugcapio;
+extern int ehcidebugport;
+
+extern int ehcidebug;
+
+void ehcilinkage(Hci *hp);
+void ehcimeminit(Ctlr *ctlr);
+void ehcirun(Ctlr *ctlr, int on);
diff --git a/sys/src/9/omap/usbehciomap.c b/sys/src/9/omap/usbehciomap.c
new file mode 100755
index 000000000..a1592bb54
--- /dev/null
+++ b/sys/src/9/omap/usbehciomap.c
@@ -0,0 +1,224 @@
+/*
+ * OMAP3-specific code for
+ * USB Enhanced Host Controller Interface (EHCI) driver
+ * High speed USB 2.0.
+ */
+
+#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/usb.h"
+#include "usbehci.h"
+
+static Ctlr* ctlrs[Nhcis];
+
+static void
+ehcireset(Ctlr *ctlr)
+{
+ Eopio *opio;
+ int i;
+
+ ilock(ctlr);
+ dprint("ehci %#p reset\n", ctlr->capio);
+ opio = ctlr->opio;
+
+ /*
+ * Turn off legacy mode. Some controllers won't
+ * interrupt us as expected otherwise.
+ */
+ ehcirun(ctlr, 0);
+
+ /* clear high 32 bits of address signals if it's 64 bits capable.
+ * This is probably not needed but it does not hurt and others do it.
+ */
+ if((ctlr->capio->capparms & C64) != 0){
+ dprint("ehci: 64 bits\n");
+ opio->seg = 0;
+ }
+
+ if(ehcidebugcapio != ctlr->capio){
+ opio->cmd |= Chcreset; /* controller reset */
+ coherence();
+ for(i = 0; i < 100; i++){
+ if((opio->cmd & Chcreset) == 0)
+ break;
+ delay(1);
+ }
+ if(i == 100)
+ print("ehci %#p controller reset timed out\n", ctlr->capio);
+ }
+
+ /* requesting more interrupts per µframe may miss interrupts */
+ opio->cmd |= Citc8; /* 1 intr. per ms */
+ coherence();
+ switch(opio->cmd & Cflsmask){
+ case Cfls1024:
+ ctlr->nframes = 1024;
+ break;
+ case Cfls512:
+ ctlr->nframes = 512;
+ break;
+ case Cfls256:
+ ctlr->nframes = 256;
+ break;
+ default:
+ panic("ehci: unknown fls %ld", opio->cmd & Cflsmask);
+ }
+ coherence();
+ dprint("ehci: %d frames\n", ctlr->nframes);
+ iunlock(ctlr);
+}
+
+static void
+setdebug(Hci*, int d)
+{
+ ehcidebug = d;
+}
+
+static void
+shutdown(Hci *hp)
+{
+ int i;
+ Ctlr *ctlr;
+ Eopio *opio;
+
+ ctlr = hp->aux;
+ ilock(ctlr);
+ opio = ctlr->opio;
+ opio->cmd |= Chcreset; /* controller reset */
+ coherence();
+ for(i = 0; i < 100; i++){
+ if((opio->cmd & Chcreset) == 0)
+ break;
+ delay(1);
+ }
+ if(i >= 100)
+ print("ehci %#p controller reset timed out\n", ctlr->capio);
+ delay(100);
+ ehcirun(ctlr, 0);
+ opio->frbase = 0;
+ coherence();
+ iunlock(ctlr);
+}
+
+/*
+ * omap3-specific ehci code
+ */
+
+enum {
+ /* opio->insn[5] bits */
+ Control = 1<<31, /* set to start access, cleared when done */
+ Write = 2<<22,
+ Read = 3<<22,
+ Portsh = 24,
+ Regaddrsh = 16, /* 0x2f means use extended reg addr */
+ Eregaddrsh = 8,
+
+ /* phy reg addresses */
+ Funcctlreg = 4,
+ Ifcctlreg = 7,
+
+ Phystppullupoff = 0x90, /* on is 0x10 */
+
+ Phyrstport2 = 147, /* gpio # */
+
+};
+
+static void
+wrulpi(Eopio *opio, int port, int reg, uchar data)
+{
+ opio->insn[5] = Control | port << Portsh | Write | reg << Regaddrsh |
+ data;
+ coherence();
+ /*
+ * this seems contrary to the skimpy documentation in the manual
+ * but inverting the test hangs forever.
+ */
+ while (!(opio->insn[5] & Control))
+ ;
+}
+
+static int
+reset(Hci *hp)
+{
+ Ctlr *ctlr;
+ Ecapio *capio;
+ Eopio *opio;
+ Uhh *uhh;
+ static int beenhere;
+
+ if (beenhere)
+ return -1;
+ beenhere = 1;
+
+ if(getconf("*nousbehci") != nil || probeaddr(PHYSEHCI) < 0)
+ return -1;
+
+ ctlr = smalloc(sizeof(Ctlr));
+ /*
+ * don't bother with vmap; i/o space is all mapped anyway,
+ * and a size less than 1MB will blow an assertion in mmukmap.
+ */
+ ctlr->capio = capio = (Ecapio *)PHYSEHCI;
+ ctlr->opio = opio = (Eopio*)((uintptr)capio + (capio->cap & 0xff));
+
+ hp->aux = ctlr;
+ hp->port = (uintptr)ctlr->capio;
+ hp->irq = 77;
+ hp->nports = capio->parms & Cnports;
+
+ ddprint("echi: %s, ncc %lud npcc %lud\n",
+ capio->parms & 0x10000 ? "leds" : "no leds",
+ (capio->parms >> 12) & 0xf, (capio->parms >> 8) & 0xf);
+ ddprint("ehci: routing %s, %sport power ctl, %d ports\n",
+ capio->parms & 0x40 ? "explicit" : "automatic",
+ capio->parms & 0x10 ? "" : "no ", hp->nports);
+
+ ehcireset(ctlr);
+ ehcimeminit(ctlr);
+
+ /* omap35-specific set up */
+ /* bit 5 `must be set to 1 for proper behavior', spruf98d §23.2.6.7.17 */
+ opio->insn[4] |= 1<<5;
+ coherence();
+
+ /* insn[5] is for both utmi and ulpi, depending on hostconfig mode */
+ uhh = (Uhh *)PHYSUHH;
+ if (uhh->hostconfig & P1ulpi_bypass) { /* utmi port 1 active */
+ /* not doing this */
+ iprint("usbehci: bypassing ulpi on port 1!\n");
+ opio->insn[5] &= ~(MASK(4) << 13);
+ opio->insn[5] |= 1 << 13; /* select port 1 */
+ coherence();
+ } else { /* ulpi port 1 active */
+ /* TODO may need to reset gpio port2 here */
+
+ /* disable integrated stp pull-up resistor */
+ wrulpi(opio, 1, Ifcctlreg, Phystppullupoff);
+
+ /* force phy to `high-speed' */
+ wrulpi(opio, 1, Funcctlreg, 0x40);
+ }
+
+ /*
+ * Linkage to the generic HCI driver.
+ */
+ ehcilinkage(hp);
+ hp->shutdown = shutdown;
+ hp->debug = setdebug;
+
+ intrenable(78, hp->interrupt, hp, UNKNOWN, "usbtll");
+ intrenable(92, hp->interrupt, hp, UNKNOWN, "usb otg");
+ intrenable(93, hp->interrupt, hp, UNKNOWN, "usb otg dma");
+ return 0;
+}
+
+void
+usbehcilink(void)
+{
+ addhcitype("ehci", reset);
+}
diff --git a/sys/src/9/omap/words b/sys/src/9/omap/words
new file mode 100755
index 000000000..d55b335da
--- /dev/null
+++ b/sys/src/9/omap/words
@@ -0,0 +1,202 @@
+beagleboard rev c3:
+cortex-a8 cpu: arm v7-a arch. rev 3, 500MHz, dual-issue
+OMAP3530-GP rev 2, CPU-OPP2 L3-165MHz
+OMAP3 Beagle board + LPDDR/NAND
+DRAM: 256 MB
+NAND: 256 MiB
+Board revision C
+Serial #784200230000000004013f790401d018
+
+igepv2 board:
+cortex-a8 cpu: arm v7-a arch. rev 3, 720MHz, dual-issue
+OMAP3530-GP ES3.1, CPU-OPP2 L3-165MHz
+IGEP v2.x rev. B + LPDDR/ONENAND
+DRAM: 512 MB
+Muxed OneNAND(DDP) 512MB 1.8V 16-bit (0x58)
+OneNAND version = 0x0031
+Chip support all block unlock
+Chip has 2 plane
+Scanning device for bad blocks
+Bad eraseblock 3134 at 0x187c0000
+Bad eraseblock 3135 at 0x187e0000
+OneNAND: 512 MB
+
+omap3530 SoC
+CORE_CLK runs at 26MHz
+see spruf98d from ti.com (/public/doc/ti/omap35x.ref.spruf98d.pdf)
+
+separate i & d tlbs, each 32 entries
+ can invalidate i, d or both tlbs by { all, mva, or asid match }
+
+i & d L1 caches, 16K each, 4 ways, 64 sets, 64-byte lines
+ i is VIPT, d is PIPT
+ no `test and clean D & U all' operations
+ no prefetching, no cache maintenance
+ can invalidate i, d or both cache but not D & U all
+ can invalidate entire i-cache only
+ can clean or invalidate by set and way data/unified cache
+unified L2 PIPT cache, 256K, 8 ways, 512 sets, 64-byte lines
+no hardware cache coherence
+
+l3 interconnect firewalls are all off at boot time, except for a bit of
+ secure ram
+sram at 0x40200000 size 1MB
+l4 interconnect firewalls seem to be sane at boot time
+
+___
+The state of the Beagleboard/IGEPv2 (TI OMAP35 SoC, Cortex-A8) port.
+
+Plan 9 runs on the IGEPv2 and Gumstix Overo boards.
+
+On the Beagleboard, Plan 9 is not yet usable but it gets as far as
+trying to access the USB ethernet (since the Beagleboard has no
+built-in ethernet and must use USB ethernet).
+
+IGEP & Gumstix Ethernet
+
+The smsc9221 ethernet consumes a lot of system time. The design
+decision to use fifos rather than buffer rings and to not incorporate
+dma into the ethernet controller is probably responsible. With only a
+single core, running the 9221 consumes a lot of the available CPU
+time. It's probably worth trying to use the system dma controller again.
+
+USB
+
+The ohci and ehci controllers are seen, but no devices yet.
+
+There are four USB errata that need to be looked into for the igepv2
+(silicon 3.1) at least. From the omap3530 errata (rev e):
+
+- 3.1.1.130 only one usb dma channel (rx or tx) can be active
+ at one time: use interrupt mode instead
+- 3.1.1.144 otg soft reset doesn't work right
+- 3.1.1.183 ohci and ehci controllers cannot work concurrently
+- §3.1.3 usb limitations: all ports must be configured to identical speeds
+ (high vs full/low)
+
+Flash
+
+access to nand flash would be handy for nvram and paqfs or sacfs file
+systems.
+
+In the flash, x-loader occupies up to 0x20000, then u-boot from
+0x80000 to 0x1e0000, and there's a linux kernel after that (if you
+care). The beagle's flash chip is a micron pop 2Gb nand
+mt29f2g16abdhc-et (physical marking jw256), and the igep's is a
+samsung onenand.
+
+VFPv3 Floating Point
+
+The Cortex-A8 has VFPv3 floating point, which uses different opcodes
+than 5c/5l currently generate. New 5c or 5l is in the works.
+
+Video
+
+The display subsystem for omap3 (dss) is divided into 3 parts, called lcd,
+video and dsi (ignoring the various accelerators). The system only
+supports the lcd via dvi interface so far because it's the only one we
+have been able to test. 1280x1024x16 is the default resolution, this
+might be changed. Writing to /dev/dssctl (e.g., echo 1024x768x16
+>/dev/dssctl) changes the resolution. Currently the system does not
+use the rfbi since it seems like an unnecessary optimisation at this
+point. Per Odlund wrote the first draft of the video driver for a
+Google Summer of Code project.
+
+Stray Interrupts
+
+IRQs 56 and 57 are I2C. 83, 86 and 94 are MMC.
+
+___
+
+The code is fairly heavy-handed with the use of barrier instructions
+(BARRIERS in assembler, coherence in C), partly in reaction to bad
+experience doing Power PC ports, but also just as precautions against
+modern processors, which may feel free to execute instructions out of
+order or some time later, store to memory out of order or some time
+later, otherwise break the model of traditional sequential processors,
+or any combination of the above.
+___
+
+There are a few rough edges:
+
+- the clock.c scheduling rate (HZ) is quite approximate. The OMAP
+timers are complex, but one could eventually do better (or just let
+timesync compensate).
+
+- User processes are limited to 512MB virtual (mainly by the IGEPv2 Ethernet
+being at 0x2c000000), which isn't a problem since Beagleboards only
+have 256MB of dram and IGEPv2s have 512MB, and we don't want to swap.
+
+- might use ucalloc.c to allocate uncached scratch space for generated code
+in coproc.c.
+
+- the C implementation of cache primitives failed with mmu off; still true?
+
+- unlock, setup: protect module register target APE (PM_RT) per spruf98c §1.6.7
+
+- setup mpp (multi-purpose pins)?
+
+___
+ memory map (mostly from omap35x ref)
+hex addr size what
+----
+0 16MB physical address of flash registers, buffers
+20000000 16MB virtual address of flash registers, buffers
+2c000000 ? smc 9221 ethernet
+38000000 16MB 256MB (beagle) or 512MB (igep) nand flash mapped here
+
+40000000 112K boot rom, top of user space
+40200000 64K sram
+
+48000000 16MB L4 core
+48002000 8K system control (scm)
+48004000 16K clock manager
+48040000 8K L4-core config
+48050000 4K graphics
+48062000 4K usb tll
+48064000 1K usb uhh_config
+48064400 1K ohci
+48064800 1K ehci
+4806a000 8K 8250 uart0
+4806c000 8K 8250 uart1
+48086000 4K gptimer10
+48088000 4K gptimer11
+4809c000 8K mmc/sd goo
+480ab000 8K hs usb otg
+480ad000 8K mmc/sd goo
+480b4000 8K mmc/sd goo
+480c7000 device intr controller
+48200000 2K intr ctlr (intc)
+
+48300000 256K L4-wakeup
+48304000 4K gptimer12
+48318000 8K gptimer1
+
+49000000 1MB L4 peripherals
+49020000 8K 8250 uart2 (with exposed connector for console)
+49032000 4K gptimer2
+49034000 4K gptimer3
+⋯
+49040000 4K gptimer9
+49050000 8K gpio2
+⋯
+49058000 8K gpio6
+
+50000000 64K graphics accelerator
+
+68000000 1K L3 config (rt)
+68004000 1K L3 hs usb host
+68004400 1K L3 hs usb otg
+68005400 1K L3 graphics
+68006800 1K L4-core config
+68010000 L3 protection mechanism
+
+6e000000 ? gpmc
+
+80000000 256MB dram on beagle
+ 512MB dram on igep
+
+c0000000 1GB kernel virtual space, mapped to 80000000
+
+apparently the vector address (0 or 0xffff0000) is virtual,
+so we're expected to map it to ram.
diff --git a/sys/src/9/pc/a100p.cp b/sys/src/9/pc/a100p.cp
new file mode 100755
index 000000000..f607a1ddc
--- /dev/null
+++ b/sys/src/9/pc/a100p.cp
Binary files differ
diff --git a/sys/src/9/pc/ahci.h b/sys/src/9/pc/ahci.h
new file mode 100755
index 000000000..cfe28352d
--- /dev/null
+++ b/sys/src/9/pc/ahci.h
@@ -0,0 +1,275 @@
+/*
+ * advanced host controller interface (sata)
+ * © 2007 coraid, inc
+ */
+
+/* ata errors */
+enum {
+ Emed = 1<<0, /* media error */
+ Enm = 1<<1, /* no media */
+ Eabrt = 1<<2, /* abort */
+ Emcr = 1<<3, /* media change request */
+ Eidnf = 1<<4, /* no user-accessible address */
+ Emc = 1<<5, /* media change */
+ Eunc = 1<<6, /* data error */
+ Ewp = 1<<6, /* write protect */
+ Eicrc = 1<<7, /* interface crc error */
+
+ Efatal = Eidnf|Eicrc, /* must sw reset */
+};
+
+/* ata status */
+enum {
+ ASerr = 1<<0, /* error */
+ ASdrq = 1<<3, /* request */
+ ASdf = 1<<5, /* fault */
+ ASdrdy = 1<<6, /* ready */
+ ASbsy = 1<<7, /* busy */
+
+ ASobs = 1<<1|1<<2|1<<4,
+};
+
+/* pci configuration */
+enum {
+ Abar = 5,
+};
+
+/*
+ * ahci memory configuration
+ *
+ * 0000-0023 generic host control
+ * 0024-009f reserved
+ * 00a0-00ff vendor specific.
+ * 0100-017f port 0
+ * ...
+ * 1080-1100 port 31
+ */
+
+/* cap bits: supported features */
+enum {
+ Hs64a = 1<<31, /* 64-bit addressing */
+ Hsncq = 1<<30, /* ncq */
+ Hssntf = 1<<29, /* snotification reg. */
+ Hsmps = 1<<28, /* mech pres switch */
+ Hsss = 1<<27, /* staggered spinup */
+ Hsalp = 1<<26, /* aggressive link pm */
+ Hsal = 1<<25, /* activity led */
+ Hsclo = 1<<24, /* command-list override */
+ Hiss = 1<<20, /* for interface speed */
+// Hsnzo = 1<<19,
+ Hsam = 1<<18, /* ahci-mode only */
+ Hspm = 1<<17, /* port multiplier */
+// Hfbss = 1<<16,
+ Hpmb = 1<<15, /* multiple-block pio */
+ Hssc = 1<<14, /* slumber state */
+ Hpsc = 1<<13, /* partial-slumber state */
+ Hncs = 1<<8, /* n command slots */
+ Hcccs = 1<<7, /* coal */
+ Hems = 1<<6, /* enclosure mgmt. */
+ Hsxs = 1<<5, /* external sata */
+ Hnp = 1<<0, /* n ports */
+};
+
+/* ghc bits */
+enum {
+ Hae = 1<<31, /* enable ahci */
+ Hie = 1<<1, /* " interrupts */
+ Hhr = 1<<0, /* hba reset */
+};
+
+typedef struct {
+ ulong cap;
+ ulong ghc;
+ ulong isr;
+ ulong pi; /* ports implemented */
+ ulong ver;
+ ulong ccc; /* coaleasing control */
+ ulong cccports;
+ ulong emloc;
+ ulong emctl;
+} Ahba;
+
+enum {
+ Acpds = 1<<31, /* cold port detect status */
+ Atfes = 1<<30, /* task file error status */
+ Ahbfs = 1<<29, /* hba fatal */
+ Ahbds = 1<<28, /* hba error (parity error) */
+ Aifs = 1<<27, /* interface fatal §6.1.2 */
+ Ainfs = 1<<26, /* interface error (recovered) */
+ Aofs = 1<<24, /* too many bytes from disk */
+ Aipms = 1<<23, /* incorrect prt mul status */
+ Aprcs = 1<<22, /* PhyRdy change status Pxserr.diag.n */
+ Adpms = 1<<7, /* mechanical presence status */
+ Apcs = 1<<6, /* port connect diag.x */
+ Adps = 1<<5, /* descriptor processed */
+ Aufs = 1<<4, /* unknown fis diag.f */
+ Asdbs = 1<<3, /* set device bits fis received w/ i bit set */
+ Adss = 1<<2, /* dma setup */
+ Apio = 1<<1, /* pio setup fis */
+ Adhrs = 1<<0, /* device to host register fis */
+
+ IEM = Acpds|Atfes|Ahbds|Ahbfs|Ahbds|Aifs|Ainfs|Aprcs|Apcs|Adps|
+ Aufs|Asdbs|Adss|Adhrs,
+ Ifatal = Atfes|Ahbfs|Ahbds|Aifs,
+};
+
+/* serror bits */
+enum {
+ SerrX = 1<<26, /* exchanged */
+ SerrF = 1<<25, /* unknown fis */
+ SerrT = 1<<24, /* transition error */
+ SerrS = 1<<23, /* link sequence */
+ SerrH = 1<<22, /* handshake */
+ SerrC = 1<<21, /* crc */
+ SerrD = 1<<20, /* not used by ahci */
+ SerrB = 1<<19, /* 10-tp-8 decode */
+ SerrW = 1<<18, /* comm wake */
+ SerrI = 1<<17, /* phy internal */
+ SerrN = 1<<16, /* phyrdy change */
+
+ ErrE = 1<<11, /* internal */
+ ErrP = 1<<10, /* ata protocol violation */
+ ErrC = 1<<9, /* communication */
+ ErrT = 1<<8, /* transient */
+ ErrM = 1<<1, /* recoverd comm */
+ ErrI = 1<<0, /* recovered data integrety */
+
+ ErrAll = ErrE|ErrP|ErrC|ErrT|ErrM|ErrI,
+ SerrAll = SerrX|SerrF|SerrT|SerrS|SerrH|SerrC|SerrD|SerrB|SerrW|
+ SerrI|SerrN|ErrAll,
+ SerrBad = 0x7f<<19,
+};
+
+/* cmd register bits */
+enum {
+ Aicc = 1<<28, /* interface communcations control. 4 bits */
+ Aasp = 1<<27, /* aggressive slumber & partial sleep */
+ Aalpe = 1<<26, /* aggressive link pm enable */
+ Adlae = 1<<25, /* drive led on atapi */
+ Aatapi = 1<<24, /* device is atapi */
+ Aesp = 1<<21, /* external sata port */
+ Acpd = 1<<20, /* cold presence detect */
+ Ampsp = 1<<19, /* mechanical pres. */
+ Ahpcp = 1<<18, /* hot plug capable */
+ Apma = 1<<17, /* pm attached */
+ Acps = 1<<16, /* cold presence state */
+ Acr = 1<<15, /* cmdlist running */
+ Afr = 1<<14, /* fis running */
+ Ampss = 1<<13, /* mechanical presence switch state */
+ Accs = 1<<8, /* current command slot 12:08 */
+ Afre = 1<<4, /* fis enable receive */
+ Aclo = 1<<3, /* command list override */
+ Apod = 1<<2, /* power on dev (requires cold-pres. detect) */
+ Asud = 1<<1, /* spin-up device; requires ss capability */
+ Ast = 1<<0, /* start */
+
+ Arun = Ast|Acr|Afre|Afr,
+};
+
+/* ctl register bits */
+enum {
+ Aipm = 1<<8, /* interface power mgmt. 3=off */
+ Aspd = 1<<4,
+ Adet = 1<<0, /* device detection */
+};
+
+#define sstatus scr0
+#define sctl scr2
+#define serror scr1
+#define sactive scr3
+
+typedef struct {
+ ulong list; /* PxCLB must be 1kb aligned. */
+ ulong listhi;
+ ulong fis; /* 256-byte aligned */
+ ulong fishi;
+ ulong isr;
+ ulong ie; /* interrupt enable */
+ ulong cmd;
+ ulong res1;
+ ulong task;
+ ulong sig;
+ ulong scr0;
+ ulong scr2;
+ ulong scr1;
+ ulong scr3;
+ ulong ci; /* command issue */
+ ulong ntf;
+ uchar res2[8];
+ ulong vendor;
+} Aport;
+
+/* in host's memory; not memory mapped */
+typedef struct {
+ uchar *base;
+ uchar *d;
+ uchar *p;
+ uchar *r;
+ uchar *u;
+ ulong *devicebits;
+} Afis;
+
+enum {
+ Lprdtl = 1<<16, /* physical region descriptor table len */
+ Lpmp = 1<<12, /* port multiplier port */
+ Lclear = 1<<10, /* clear busy on R_OK */
+ Lbist = 1<<9,
+ Lreset = 1<<8,
+ Lpref = 1<<7, /* prefetchable */
+ Lwrite = 1<<6,
+ Latapi = 1<<5,
+ Lcfl = 1<<0, /* command fis length in double words */
+};
+
+/* in hosts memory; memory mapped */
+typedef struct {
+ ulong flags;
+ ulong len;
+ ulong ctab;
+ ulong ctabhi;
+ uchar reserved[16];
+} Alist;
+
+typedef struct {
+ ulong dba;
+ ulong dbahi;
+ ulong pad;
+ ulong count;
+} Aprdt;
+
+typedef struct {
+ uchar cfis[0x40];
+ uchar atapi[0x10];
+ uchar pad[0x30];
+ Aprdt prdt;
+} Actab;
+
+enum {
+ Ferror = 1,
+ Fdone = 2,
+};
+
+enum {
+ Dllba = 1,
+ Dsmart = 1<<1,
+ Dpower = 1<<2,
+ Dnop = 1<<3,
+ Datapi = 1<<4,
+ Datapi16= 1<<5,
+};
+
+typedef struct {
+ QLock;
+ Rendez;
+ uchar flag;
+ uchar feat;
+ uchar smart;
+ Afis fis;
+ Alist *list;
+ Actab *ctab;
+} Aportm;
+
+typedef struct {
+ Aport *p;
+ Aportm *m;
+} Aportc;
diff --git a/sys/src/9/pc/apbootstrap.s b/sys/src/9/pc/apbootstrap.s
new file mode 100755
index 000000000..5407530f0
--- /dev/null
+++ b/sys/src/9/pc/apbootstrap.s
@@ -0,0 +1,110 @@
+/*
+ * 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 */
+#define LGDT(gdtptr) BYTE $0x0F; /* LGDT */ \
+ BYTE $0x01; BYTE $0x16; \
+ WORD $gdtptr
+#define FARJUMP16(s, o) BYTE $0xEA; /* far jump to ptr16:16 */ \
+ WORD $o; WORD $s; \
+ NOP; NOP; NOP
+#define FARJUMP32(s, o) BYTE $0x66; /* far jump to ptr32:16 */ \
+ BYTE $0xEA; LONG $o; WORD $s
+
+#define DELAY BYTE $0xEB; /* JMP .+2 */ \
+ BYTE $0x00
+#define INVD BYTE $0x0F; BYTE $0x08
+#define WBINVD BYTE $0x0F; BYTE $0x09
+
+/*
+ * Macros for calculating offsets within the page directory base
+ * and page tables. Note that these are assembler-specific hence
+ * the '<<2'.
+ */
+#define PDO(a) (((((a))>>22) & 0x03FF)<<2)
+#define PTO(a) (((((a))>>12) & 0x03FF)<<2)
+
+TEXT apbootstrap(SB), $0
+ FARJUMP16(0, _apbootstrap(SB))
+TEXT _apvector(SB), $0 /* address APBOOTSTRAP+0x08 */
+ LONG $0
+TEXT _appdb(SB), $0 /* address APBOOTSTRAP+0x0C */
+ LONG $0
+TEXT _apapic(SB), $0 /* address APBOOTSTRAP+0x10 */
+ LONG $0
+TEXT _apbootstrap(SB), $0 /* address APBOOTSTRAP+0x14 */
+ MOVW CS, AX
+ MOVW AX, DS /* initialise DS */
+
+ LGDT(gdtptr(SB)) /* load a basic gdt */
+
+ MOVL CR0, AX
+ ORL $1, AX
+ MOVL AX, CR0 /* turn on protected mode */
+ DELAY /* JMP .+2 */
+
+ BYTE $0xB8; WORD $SELECTOR(1, SELGDT, 0)/* MOVW $SELECTOR(1, SELGDT, 0), AX */
+ MOVW AX, DS
+ MOVW AX, ES
+ MOVW AX, FS
+ MOVW AX, GS
+ MOVW AX, SS
+
+ FARJUMP32(SELECTOR(2, SELGDT, 0), _ap32-KZERO(SB))
+
+/*
+ * For Pentiums and higher, the code that enables paging must come from
+ * pages that are identity mapped.
+ * To this end double map KZERO at virtual 0 and undo the mapping once virtual
+ * nirvana has been obtained.
+ */
+TEXT _ap32(SB), $0
+ MOVL _appdb-KZERO(SB), CX /* physical address of PDB */
+ MOVL (PDO(KZERO))(CX), DX /* double-map KZERO at 0 */
+ MOVL DX, (PDO(0))(CX)
+ MOVL CX, CR3 /* load and flush the mmu */
+
+ MOVL CR0, DX
+ ORL $0x80010000, DX /* PG|WP */
+ ANDL $~0x6000000A, DX /* ~(CD|NW|TS|MP) */
+
+ MOVL $_appg(SB), AX
+ MOVL DX, CR0 /* turn on paging */
+ JMP* AX
+
+TEXT _appg(SB), $0
+ MOVL CX, AX /* physical address of PDB */
+ ORL $KZERO, AX
+ MOVL $0, (PDO(0))(AX) /* undo double-map of KZERO at 0 */
+ MOVL CX, CR3 /* load and flush the mmu */
+
+ MOVL $(MACHADDR+MACHSIZE-4), SP
+
+ MOVL $0, AX
+ PUSHL AX
+ POPFL
+
+ MOVL _apapic(SB), AX
+ MOVL AX, (SP)
+ MOVL _apvector(SB), AX
+ CALL* AX
+_aphalt:
+ HLT
+ JMP _aphalt
+
+TEXT gdt(SB), $0
+ LONG $0x0000; LONG $0
+ LONG $0xFFFF; LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
+ LONG $0xFFFF; LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
+TEXT gdtptr(SB), $0
+ WORD $(3*8-1)
+ LONG $gdt-KZERO(SB)
diff --git a/sys/src/9/pc/apic.c b/sys/src/9/pc/apic.c
new file mode 100755
index 000000000..ccaa8b5c7
--- /dev/null
+++ b/sys/src/9/pc/apic.c
@@ -0,0 +1,421 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "mp.h"
+
+enum { /* Local APIC registers */
+ LapicID = 0x0020, /* ID */
+ LapicVER = 0x0030, /* Version */
+ LapicTPR = 0x0080, /* Task Priority */
+ LapicAPR = 0x0090, /* Arbitration Priority */
+ LapicPPR = 0x00A0, /* Processor Priority */
+ LapicEOI = 0x00B0, /* EOI */
+ LapicLDR = 0x00D0, /* Logical Destination */
+ LapicDFR = 0x00E0, /* Destination Format */
+ LapicSVR = 0x00F0, /* Spurious Interrupt Vector */
+ LapicISR = 0x0100, /* Interrupt Status (8 registers) */
+ LapicTMR = 0x0180, /* Trigger Mode (8 registers) */
+ LapicIRR = 0x0200, /* Interrupt Request (8 registers) */
+ LapicESR = 0x0280, /* Error Status */
+ LapicICRLO = 0x0300, /* Interrupt Command */
+ LapicICRHI = 0x0310, /* Interrupt Command [63:32] */
+ LapicTIMER = 0x0320, /* Local Vector Table 0 (TIMER) */
+ LapicPCINT = 0x0340, /* Performance Counter LVT */
+ LapicLINT0 = 0x0350, /* Local Vector Table 1 (LINT0) */
+ LapicLINT1 = 0x0360, /* Local Vector Table 2 (LINT1) */
+ LapicERROR = 0x0370, /* Local Vector Table 3 (ERROR) */
+ LapicTICR = 0x0380, /* Timer Initial Count */
+ LapicTCCR = 0x0390, /* Timer Current Count */
+ LapicTDCR = 0x03E0, /* Timer Divide Configuration */
+};
+
+enum { /* LapicSVR */
+ LapicENABLE = 0x00000100, /* Unit Enable */
+ LapicFOCUS = 0x00000200, /* Focus Processor Checking Disable */
+};
+
+enum { /* LapicICRLO */
+ /* [14] IPI Trigger Mode Level (RW) */
+ LapicDEASSERT = 0x00000000, /* Deassert level-sensitive interrupt */
+ LapicASSERT = 0x00004000, /* Assert level-sensitive interrupt */
+
+ /* [17:16] Remote Read Status */
+ LapicINVALID = 0x00000000, /* Invalid */
+ LapicWAIT = 0x00010000, /* In-Progress */
+ LapicVALID = 0x00020000, /* Valid */
+
+ /* [19:18] Destination Shorthand */
+ LapicFIELD = 0x00000000, /* No shorthand */
+ LapicSELF = 0x00040000, /* Self is single destination */
+ LapicALLINC = 0x00080000, /* All including self */
+ LapicALLEXC = 0x000C0000, /* All Excluding self */
+};
+
+enum { /* LapicESR */
+ LapicSENDCS = 0x00000001, /* Send CS Error */
+ LapicRCVCS = 0x00000002, /* Receive CS Error */
+ LapicSENDACCEPT = 0x00000004, /* Send Accept Error */
+ LapicRCVACCEPT = 0x00000008, /* Receive Accept Error */
+ LapicSENDVECTOR = 0x00000020, /* Send Illegal Vector */
+ LapicRCVVECTOR = 0x00000040, /* Receive Illegal Vector */
+ LapicREGISTER = 0x00000080, /* Illegal Register Address */
+};
+
+enum { /* LapicTIMER */
+ /* [17] Timer Mode (RW) */
+ LapicONESHOT = 0x00000000, /* One-shot */
+ LapicPERIODIC = 0x00020000, /* Periodic */
+
+ /* [19:18] Timer Base (RW) */
+ LapicCLKIN = 0x00000000, /* use CLKIN as input */
+ LapicTMBASE = 0x00040000, /* use TMBASE */
+ LapicDIVIDER = 0x00080000, /* use output of the divider */
+};
+
+enum { /* LapicTDCR */
+ LapicX2 = 0x00000000, /* divide by 2 */
+ LapicX4 = 0x00000001, /* divide by 4 */
+ LapicX8 = 0x00000002, /* divide by 8 */
+ LapicX16 = 0x00000003, /* divide by 16 */
+ LapicX32 = 0x00000008, /* divide by 32 */
+ LapicX64 = 0x00000009, /* divide by 64 */
+ LapicX128 = 0x0000000A, /* divide by 128 */
+ LapicX1 = 0x0000000B, /* divide by 1 */
+};
+
+static ulong* lapicbase;
+
+struct
+{
+ uvlong hz;
+ ulong max;
+ ulong min;
+ ulong div;
+} lapictimer;
+
+static ulong
+lapicr(int r)
+{
+ return *(lapicbase+(r/sizeof(*lapicbase)));
+}
+
+static void
+lapicw(int r, ulong data)
+{
+ *(lapicbase+(r/sizeof(*lapicbase))) = data;
+ data = *(lapicbase+(LapicID/sizeof(*lapicbase)));
+ USED(data);
+}
+
+void
+lapiconline(void)
+{
+ /*
+ * Reload the timer to de-synchronise the processors,
+ * then lower the task priority to allow interrupts to be
+ * accepted by the APIC.
+ */
+ microdelay((TK2MS(1)*1000/conf.nmach) * m->machno);
+ lapicw(LapicTICR, lapictimer.max);
+ lapicw(LapicTIMER, LapicCLKIN|LapicPERIODIC|(VectorPIC+IrqTIMER));
+
+ lapicw(LapicTPR, 0);
+}
+
+/*
+ * use the i8253 clock to figure out our lapic timer rate.
+ */
+static void
+lapictimerinit(void)
+{
+ uvlong x, v, hz;
+
+ v = m->cpuhz/1000;
+ lapicw(LapicTDCR, LapicX1);
+ lapicw(LapicTIMER, ApicIMASK|LapicCLKIN|LapicONESHOT|(VectorPIC+IrqTIMER));
+
+ if(lapictimer.hz == 0ULL){
+ x = fastticks(&hz);
+ x += hz/10;
+ lapicw(LapicTICR, 0xffffffff);
+ do{
+ v = fastticks(nil);
+ }while(v < x);
+
+ lapictimer.hz = (0xffffffffUL-lapicr(LapicTCCR))*10;
+ lapictimer.max = lapictimer.hz/HZ;
+ lapictimer.min = lapictimer.hz/(100*HZ);
+
+ if(lapictimer.hz > hz-(hz/10)){
+ if(lapictimer.hz > hz+(hz/10))
+ panic("lapic clock %lld > cpu clock > %lld\n",
+ lapictimer.hz, hz);
+ lapictimer.hz = hz;
+ }
+ lapictimer.div = hz/lapictimer.hz;
+ }
+}
+
+void
+lapicinit(Apic* apic)
+{
+ ulong dfr, ldr, lvt;
+
+ if(lapicbase == 0)
+ lapicbase = apic->addr;
+
+ /*
+ * These don't really matter in Physical mode;
+ * set the defaults anyway.
+ */
+ if(strncmp(m->cpuidid, "AuthenticAMD", 12) == 0)
+ dfr = 0xf0000000;
+ else
+ dfr = 0xffffffff;
+ ldr = 0x00000000;
+
+ lapicw(LapicDFR, dfr);
+ lapicw(LapicLDR, ldr);
+ lapicw(LapicTPR, 0xff);
+ lapicw(LapicSVR, LapicENABLE|(VectorPIC+IrqSPURIOUS));
+
+ lapictimerinit();
+
+ /*
+ * Some Pentium revisions have a bug whereby spurious
+ * interrupts are generated in the through-local mode.
+ */
+ switch(m->cpuidax & 0xFFF){
+ case 0x526: /* stepping cB1 */
+ case 0x52B: /* stepping E0 */
+ case 0x52C: /* stepping cC0 */
+ wrmsr(0x0E, 1<<14); /* TR12 */
+ break;
+ }
+
+ /*
+ * Set the local interrupts. It's likely these should just be
+ * masked off for SMP mode as some Pentium Pros have problems if
+ * LINT[01] are set to ExtINT.
+ * Acknowledge any outstanding interrupts.
+ lapicw(LapicLINT0, apic->lintr[0]);
+ lapicw(LapicLINT1, apic->lintr[1]);
+ */
+ lapiceoi(0);
+
+ lvt = (lapicr(LapicVER)>>16) & 0xFF;
+ if(lvt >= 4)
+ lapicw(LapicPCINT, ApicIMASK);
+ lapicw(LapicERROR, VectorPIC+IrqERROR);
+ lapicw(LapicESR, 0);
+ lapicr(LapicESR);
+
+ /*
+ * Issue an INIT Level De-Assert to synchronise arbitration ID's.
+ */
+ lapicw(LapicICRHI, 0);
+ lapicw(LapicICRLO, LapicALLINC|ApicLEVEL|LapicDEASSERT|ApicINIT);
+ while(lapicr(LapicICRLO) & ApicDELIVS)
+ ;
+
+ /*
+ * Do not allow acceptance of interrupts until all initialisation
+ * for this processor is done. For the bootstrap processor this can be
+ * early duing initialisation. For the application processors this should
+ * be after the bootstrap processor has lowered priority and is accepting
+ * interrupts.
+ lapicw(LapicTPR, 0);
+ */
+}
+
+void
+lapicstartap(Apic* apic, int v)
+{
+ int i;
+ ulong crhi;
+
+ crhi = apic->apicno<<24;
+ lapicw(LapicICRHI, crhi);
+ lapicw(LapicICRLO, LapicFIELD|ApicLEVEL|LapicASSERT|ApicINIT);
+ microdelay(200);
+ lapicw(LapicICRLO, LapicFIELD|ApicLEVEL|LapicDEASSERT|ApicINIT);
+ delay(10);
+
+ for(i = 0; i < 2; i++){
+ lapicw(LapicICRHI, crhi);
+ lapicw(LapicICRLO, LapicFIELD|ApicEDGE|ApicSTARTUP|(v/BY2PG));
+ microdelay(200);
+ }
+}
+
+void
+lapicerror(Ureg*, void*)
+{
+ ulong esr;
+
+ lapicw(LapicESR, 0);
+ esr = lapicr(LapicESR);
+ switch(m->cpuidax & 0xFFF){
+ case 0x526: /* stepping cB1 */
+ case 0x52B: /* stepping E0 */
+ case 0x52C: /* stepping cC0 */
+ return;
+ }
+ print("cpu%d: lapicerror: 0x%8.8luX\n", m->machno, esr);
+}
+
+void
+lapicspurious(Ureg*, void*)
+{
+ print("cpu%d: lapicspurious\n", m->machno);
+}
+
+int
+lapicisr(int v)
+{
+ ulong isr;
+
+ isr = lapicr(LapicISR + (v/32));
+
+ return isr & (1<<(v%32));
+}
+
+int
+lapiceoi(int v)
+{
+ lapicw(LapicEOI, 0);
+
+ return v;
+}
+
+void
+lapicicrw(ulong hi, ulong lo)
+{
+ lapicw(LapicICRHI, hi);
+ lapicw(LapicICRLO, lo);
+}
+
+void
+ioapicrdtr(Apic* apic, int sel, int* hi, int* lo)
+{
+ ulong *iowin;
+
+ iowin = apic->addr+(0x10/sizeof(ulong));
+ sel = IoapicRDT + 2*sel;
+
+ lock(apic);
+ *apic->addr = sel+1;
+ if(hi)
+ *hi = *iowin;
+ *apic->addr = sel;
+ if(lo)
+ *lo = *iowin;
+ unlock(apic);
+}
+
+void
+ioapicrdtw(Apic* apic, int sel, int hi, int lo)
+{
+ ulong *iowin;
+
+ iowin = apic->addr+(0x10/sizeof(ulong));
+ sel = IoapicRDT + 2*sel;
+
+ lock(apic);
+ *apic->addr = sel+1;
+ *iowin = hi;
+ *apic->addr = sel;
+ *iowin = lo;
+ unlock(apic);
+}
+
+void
+ioapicinit(Apic* apic, int apicno)
+{
+ int hi, lo, v;
+ ulong *iowin;
+
+ /*
+ * Initialise the I/O APIC.
+ * The MultiProcessor Specification says it is the responsibility
+ * of the O/S to set the APIC id.
+ * Make sure interrupts are all masked off for now.
+ */
+ iowin = apic->addr+(0x10/sizeof(ulong));
+ lock(apic);
+ *apic->addr = IoapicVER;
+ apic->mre = (*iowin>>16) & 0xFF;
+
+ *apic->addr = IoapicID;
+ *iowin = apicno<<24;
+ unlock(apic);
+
+ hi = 0;
+ lo = ApicIMASK;
+ for(v = 0; v <= apic->mre; v++)
+ ioapicrdtw(apic, v, hi, lo);
+}
+
+void
+lapictimerset(uvlong next)
+{
+ vlong period;
+ int x;
+
+ x = splhi();
+ lock(&m->apictimerlock);
+
+ period = lapictimer.max;
+ if(next != 0){
+ period = next - fastticks(nil);
+ period /= lapictimer.div;
+
+ if(period < lapictimer.min)
+ period = lapictimer.min;
+ else if(period > lapictimer.max - lapictimer.min)
+ period = lapictimer.max;
+ }
+ lapicw(LapicTICR, period);
+
+ unlock(&m->apictimerlock);
+ splx(x);
+}
+
+void
+lapicclock(Ureg *u, void*)
+{
+ /*
+ * since the MTRR updates need to be synchronized across processors,
+ * we want to do this within the clock tick.
+ */
+ mtrrclock();
+ timerintr(u, 0);
+}
+
+void
+lapicintron(void)
+{
+ lapicw(LapicTPR, 0);
+}
+
+void
+lapicintroff(void)
+{
+ lapicw(LapicTPR, 0xFF);
+}
+
+void
+lapicnmienable(void)
+{
+ lapicw(LapicPCINT, ApicNMI);
+}
+
+void
+lapicnmidisable(void)
+{
+ lapicw(LapicPCINT, ApicIMASK);
+}
diff --git a/sys/src/9/pc/apm.c b/sys/src/9/pc/apm.c
new file mode 100755
index 000000000..65d6c60bc
--- /dev/null
+++ b/sys/src/9/pc/apm.c
@@ -0,0 +1,153 @@
+/*
+ * Interface to Advanced Power Management 1.2 BIOS
+ *
+ * This is, in many ways, a giant hack, and when things settle down
+ * a bit and standardize, hopefully we can write a driver that deals
+ * more directly with the hardware and thus might be a bit cleaner.
+ *
+ * ACPI might be the answer, but at the moment this is simpler
+ * and more widespread.
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+extern int apmfarcall(ushort, ulong, Ureg*); /* apmjump.s */
+
+static int
+getreg(ulong *reg, ISAConf *isa, char *name)
+{
+ int i;
+ int nl;
+
+ nl = strlen(name);
+ for(i=0; i<isa->nopt; i++){
+ if(cistrncmp(isa->opt[i], name, nl)==0 && isa->opt[i][nl] == '='){
+ *reg = strtoul(isa->opt[i]+nl+1, nil, 16);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+/*
+ * Segment descriptors look like this.
+ *
+ * d1: [base 31:24] [gran] [is32bit] [0] [unused] [limit 19:16]
+ [present] [privlev] [type 3:0] [base 23:16]
+ * d0: [base 15:00] [limit 15:00]
+ *
+ * gran is 0 for 1-byte granularity, 1 for 4k granularity
+ * type is 0 for system segment, 1 for code/data.
+ *
+ * clearly we know way too much about the memory unit.
+ * however, knowing this much about the memory unit
+ * means that the memory unit need not know anything
+ * about us.
+ *
+ * what a crock.
+ */
+static void
+setgdt(int sel, ulong base, ulong limit, int flag)
+{
+ if(sel < 0 || sel >= NGDT)
+ panic("setgdt");
+
+ base = (ulong)KADDR(base);
+ m->gdt[sel].d0 = (base<<16) | (limit&0xFFFF);
+ m->gdt[sel].d1 = (base&0xFF000000) | (limit&0x000F0000) |
+ ((base>>16)&0xFF) | SEGP | SEGPL(0) | flag;
+}
+
+static ulong ax, cx, dx, di, ebx, esi;
+static Ureg apmu;
+static long
+apmread(Chan*, void *a, long n, vlong off)
+{
+ if(off < 0)
+ error("badarg");
+
+ if(n+off > sizeof apmu)
+ n = sizeof apmu - off;
+ if(n <= 0)
+ return 0;
+ memmove(a, (char*)&apmu+off, n);
+ return n;
+}
+
+static long
+apmwrite(Chan*, void *a, long n, vlong off)
+{
+ int s;
+ if(off || n != sizeof apmu)
+ error("write a Ureg");
+
+ memmove(&apmu, a, sizeof apmu);
+ s = splhi();
+ apmfarcall(APMCSEL, ebx, &apmu);
+ splx(s);
+ return n;
+}
+
+void
+apmlink(void)
+{
+ ISAConf isa;
+ char *s;
+
+ 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.
+ *
+ * AX = 32-bit code segment base address
+ * EBX = 32-bit code segment offset
+ * CX = 16-bit code segment base address
+ * DX = 32-bit data segment base address
+ * ESI = <16-bit code segment length> <32-bit code segment length> (hi then lo)
+ * DI = 32-bit data segment length
+ */
+
+ if(getreg(&ax, &isa, s="ax") < 0
+ || getreg(&ebx, &isa, s="ebx") < 0
+ || getreg(&cx, &isa, s="cx") < 0
+ || getreg(&dx, &isa, s="dx") < 0
+ || getreg(&esi, &isa, s="esi") < 0
+ || getreg(&di, &isa, s="di") < 0){
+ print("apm: missing register %s\n", s);
+ return;
+ }
+
+ /*
+ * The NEC Versa SX bios does not report the correct 16-bit code
+ * segment length when loaded directly from mbr -> 9load (as compared
+ * with going through ld.com). We'll make both code segments 64k-1 bytes.
+ */
+ esi = 0xFFFFFFFF;
+
+ /*
+ * We are required by the BIOS to set up three consecutive segments,
+ * one for the APM 32-bit code, one for the APM 16-bit code, and
+ * one for the APM data. The BIOS handler uses the code segment it
+ * get called with to determine the other two segment selector.
+ */
+ setgdt(APMCSEG, ax<<4, ((esi&0xFFFF)-1)&0xFFFF, SEGEXEC|SEGR|SEGD);
+ setgdt(APMCSEG16, cx<<4, ((esi>>16)-1)&0xFFFF, SEGEXEC|SEGR);
+ setgdt(APMDSEG, dx<<4, (di-1)&0xFFFF, SEGDATA|SEGW|SEGD);
+
+ addarchfile("apm", 0660, apmread, apmwrite);
+
+print("apm0: configured cbase %.8lux off %.8lux\n", ax<<4, ebx);
+
+ return;
+}
+
diff --git a/sys/src/9/pc/apmjump.s b/sys/src/9/pc/apmjump.s
new file mode 100755
index 000000000..6dbd19d0b
--- /dev/null
+++ b/sys/src/9/pc/apmjump.s
@@ -0,0 +1,98 @@
+/*
+ * Far call, absolute indirect.
+ * The argument is the offset.
+ * We use a global structure for the jump params,
+ * so this is *not* reentrant or thread safe.
+ */
+
+#include "mem.h"
+
+#define SSOVERRIDE BYTE $0x36
+#define CSOVERRIDE BYTE $0x2E
+#define RETF BYTE $0xCB
+
+GLOBL apmjumpstruct+0(SB), $8
+
+TEXT fortytwo(SB), $0
+ MOVL $42, AX
+ RETF
+
+TEXT getcs(SB), $0
+ PUSHL CS
+ POPL AX
+ RET
+
+TEXT apmfarcall(SB), $0
+ /*
+ * We call push and pop ourselves.
+ * As soon as we do the first push or pop,
+ * we can't use FP anymore.
+ */
+ MOVL off+4(FP), BX
+ MOVL seg+0(FP), CX
+ MOVL BX, apmjumpstruct+0(SB)
+ MOVL CX, apmjumpstruct+4(SB)
+
+ /* load necessary registers from Ureg */
+ MOVL ureg+8(FP), DI
+ MOVL 28(DI), AX
+ MOVL 16(DI), BX
+ MOVL 24(DI), CX
+ MOVL 20(DI), DX
+
+ /* save registers, segments */
+ PUSHL DS
+ PUSHL ES
+ PUSHL FS
+ PUSHL GS
+ PUSHL BP
+ PUSHL DI
+
+ /*
+ * paranoia: zero the segments, since it's the
+ * BIOS's responsibility to initialize them.
+ * (trick picked up from Linux driver).
+ PUSHL DX
+ XORL DX, DX
+ PUSHL DX
+ POPL DS
+ PUSHL DX
+ POPL ES
+ PUSHL DX
+ POPL FS
+ PUSHL DX
+ POPL GS
+ POPL DX
+ */
+
+ PUSHL $APMDSEG
+ POPL DS
+
+ /*
+ * The actual call.
+ */
+ CSOVERRIDE; BYTE $0xFF; BYTE $0x1D
+ LONG $apmjumpstruct+0(SB)
+
+ /* restore segments, registers */
+ POPL DI
+ POPL BP
+ POPL GS
+ POPL FS
+ POPL ES
+ POPL DS
+
+ PUSHFL
+ POPL 64(DI)
+
+ /* store interesting registers back in Ureg */
+ MOVL AX, 28(DI)
+ MOVL BX, 16(DI)
+ MOVL CX, 24(DI)
+ MOVL DX, 20(DI)
+ MOVL SI, 4(DI)
+
+ PUSHFL
+ POPL AX
+ ANDL $1, AX /* carry flag */
+ RET
diff --git a/sys/src/9/pc/archmp.c b/sys/src/9/pc/archmp.c
new file mode 100755
index 000000000..b94097cea
--- /dev/null
+++ b/sys/src/9/pc/archmp.c
@@ -0,0 +1,139 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "mp.h"
+
+_MP_ *_mp_;
+
+static _MP_*
+mpscan(uchar *addr, int len)
+{
+ uchar *e, *p, sum;
+ int i;
+
+ e = addr+len;
+ for(p = addr; p < e; p += sizeof(_MP_)){
+ if(memcmp(p, "_MP_", 4))
+ continue;
+ sum = 0;
+ for(i = 0; i < sizeof(_MP_); i++)
+ sum += p[i];
+ if(sum == 0)
+ return (_MP_*)p;
+ }
+ return 0;
+}
+
+static _MP_*
+mpsearch(void)
+{
+ uchar *bda;
+ ulong p;
+ _MP_ *mp;
+
+ /*
+ * Search for the MP Floating Pointer Structure:
+ * 1) in the first KB of the EBDA;
+ * 2) in the last KB of system base memory;
+ * 3) in the BIOS ROM between 0xE0000 and 0xFFFFF.
+ */
+ bda = KADDR(0x400);
+ if((p = (bda[0x0F]<<8)|bda[0x0E])){
+ if(mp = mpscan(KADDR(p<<4), 1024))
+ return mp;
+ }
+ else{
+ p = ((bda[0x14]<<8)|bda[0x13])*1024;
+ if(mp = mpscan(KADDR(p-1024), 1024))
+ return mp;
+ }
+ return mpscan(KADDR(0xF0000), 0x10000);
+}
+
+static int identify(void);
+
+PCArch archmp = {
+.id= "_MP_",
+.ident= identify,
+.reset= mpshutdown,
+.intrinit= mpinit,
+.intrenable= mpintrenable,
+.intron= lapicintron,
+.introff= lapicintroff,
+.fastclock= i8253read,
+.timerset= lapictimerset,
+};
+
+static int
+identify(void)
+{
+ char *cp;
+ PCMP *pcmp;
+ uchar *p, sum;
+ ulong length;
+
+ if((cp = getconf("*nomp")) != nil && strtol(cp, 0, 0) != 0)
+ return 1;
+
+ /*
+ * Search for an MP configuration table. For now,
+ * don't accept the default configurations (physaddr == 0).
+ * Check for correct signature, calculate the checksum and,
+ * if correct, check the version.
+ * To do: check extended table checksum.
+ */
+ if((_mp_ = mpsearch()) == 0 || _mp_->physaddr == 0)
+ return 1;
+
+ pcmp = KADDR(_mp_->physaddr);
+ if(memcmp(pcmp, "PCMP", 4))
+ return 1;
+
+ length = pcmp->length;
+ sum = 0;
+ for(p = (uchar*)pcmp; length; length--)
+ sum += *p++;
+
+ if(sum || (pcmp->version != 1 && pcmp->version != 4))
+ return 1;
+
+ if(cpuserver && m->havetsc)
+ archmp.fastclock = tscticks;
+ return 0;
+}
+
+Lock mpsynclock;
+
+void
+syncclock(void)
+{
+ uvlong x;
+
+ if(arch->fastclock != tscticks)
+ return;
+
+ if(m->machno == 0){
+ wrmsr(0x10, 0);
+ m->tscticks = 0;
+ } else {
+ x = MACHP(0)->tscticks;
+ while(x == MACHP(0)->tscticks)
+ ;
+ wrmsr(0x10, MACHP(0)->tscticks);
+ cycles(&m->tscticks);
+ }
+}
+
+uvlong
+tscticks(uvlong *hz)
+{
+ if(hz != nil)
+ *hz = m->cpuhz;
+
+ cycles(&m->tscticks); /* Uses the rdtsc instruction */
+ return m->tscticks;
+}
diff --git a/sys/src/9/pc/audio.h b/sys/src/9/pc/audio.h
new file mode 100755
index 000000000..d06c7bccb
--- /dev/null
+++ b/sys/src/9/pc/audio.h
@@ -0,0 +1,15 @@
+enum
+{
+ Bufsize = 1024, /* 5.8 ms each, must be power of two */
+ Nbuf = 128, /* .74 seconds total */
+ Dma = 6,
+ IrqAUDIO = 7,
+ SBswab = 0,
+};
+
+#define seteisadma(a, b) dmainit(a, Bufsize);
+#define CACHELINESZ 8
+#define UNCACHED(type, v) (type*)((ulong)(v))
+
+#define Int0vec
+#define setvec(v, f, a) intrenable(v, f, a, BUSUNKNOWN, "audio")
diff --git a/sys/src/9/pc/bios32.c b/sys/src/9/pc/bios32.c
new file mode 100755
index 000000000..e0858b9ab
--- /dev/null
+++ b/sys/src/9/pc/bios32.c
@@ -0,0 +1,155 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#define VFLAG(...) if(vflag) print(__VA_ARGS__)
+
+#define BIOSSEG(a) KADDR(((uint)(a))<<4)
+#define UPTR2INT(p) ((uintptr)(p))
+
+#define l16get(p) (((p)[1]<<8)|(p)[0])
+#define l32get(p) (((u32int)l16get(p+2)<<16)|l16get(p))
+
+static int vflag = 0;
+
+typedef struct BIOS32sdh { /* BIOS32 Service Directory Header */
+ u8int signature[4]; /* "_32_" */
+ u8int physaddr[4]; /* physical address of entry point */
+ u8int revision;
+ u8int length; /* of header in paragraphs */
+ u8int checksum; /* */
+ u8int reserved[5];
+} BIOS32sdh;
+
+typedef struct BIOS32si { /* BIOS32 Service Interface */
+ u8int* base; /* base address of service */
+ int length; /* length of service */
+ u32int offset; /* service entry-point from base */
+
+ u16int ptr[3]; /* far pointer m16:32 */
+} BIOS32si;
+
+static Lock bios32lock;
+static u16int bios32ptr[3];
+static void* bios32entry;
+
+int
+bios32ci(BIOS32si* si, BIOS32ci* ci)
+{
+ int r;
+
+ lock(&bios32lock);
+ r = bios32call(ci, si->ptr);
+ unlock(&bios32lock);
+
+ return r;
+}
+
+static void*
+rsdchecksum(void* addr, int length)
+{
+ u8int *p, sum;
+
+ sum = 0;
+ for(p = addr; length-- > 0; p++)
+ sum += *p;
+ if(sum == 0)
+ return addr;
+
+ return nil;
+}
+
+static void*
+rsdscan(u8int* addr, int len, char* signature)
+{
+ int sl;
+ u8int *e, *p;
+
+ e = addr+len;
+ sl = strlen(signature);
+ for(p = addr; p+sl < e; p += 16){
+ if(memcmp(p, signature, sl))
+ continue;
+ return p;
+ }
+
+ return nil;
+}
+
+static int
+bios32locate(void)
+{
+ uintptr ptr;
+ BIOS32sdh *sdh;
+
+ VFLAG("bios32link\n");
+ if((sdh = rsdscan(BIOSSEG(0xE000), 0x20000, "_32_")) == nil)
+ return -1;
+ if(rsdchecksum(sdh, sizeof(BIOS32sdh)) == nil)
+ return -1;
+ VFLAG("sdh @ %#p, entry %#ux\n", sdh, l32get(sdh->physaddr));
+
+ bios32entry = vmap(l32get(sdh->physaddr), 4096+1);
+ VFLAG("entry @ %#p\n", bios32entry);
+ ptr = UPTR2INT(bios32entry);
+ bios32ptr[0] = ptr & 0xffff;
+ bios32ptr[1] = (ptr>>16) & 0xffff;
+ bios32ptr[2] = KESEL;
+ VFLAG("bios32link: ptr %ux %ux %ux\n",
+ bios32ptr[0], bios32ptr[1], bios32ptr[2]);
+
+ return 0;
+}
+
+void
+BIOS32close(BIOS32si* si)
+{
+ vunmap(si->base, si->length);
+ free(si);
+}
+
+BIOS32si*
+bios32open(char* id)
+{
+ uint ptr;
+ BIOS32ci ci;
+ BIOS32si *si;
+
+ lock(&bios32lock);
+ if(bios32ptr[2] == 0 && bios32locate() < 0){
+ unlock(&bios32lock);
+ return nil;
+ }
+
+ VFLAG("bios32si: %s\n", id);
+ memset(&ci, 0, sizeof(BIOS32ci));
+ ci.eax = (id[3]<<24|(id[2]<<16)|(id[1]<<8)|id[0]);
+
+ bios32call(&ci, bios32ptr);
+ unlock(&bios32lock);
+
+ VFLAG("bios32si: eax %ux\n", ci.eax);
+ if(ci.eax & 0xff)
+ return nil;
+ VFLAG("bios32si: base %#ux length %#ux offset %#ux\n",
+ ci.ebx, ci.ecx, ci.edx);
+
+ if((si = malloc(sizeof(BIOS32si))) == nil)
+ return nil;
+ if((si->base = vmap(ci.ebx, ci.ecx)) == nil){
+ free(si);
+ return nil;
+ }
+ si->length = ci.ecx;
+
+ ptr = UPTR2INT(si->base)+ci.edx;
+ si->ptr[0] = ptr & 0xffff;
+ si->ptr[1] = (ptr>>16) & 0xffff;
+ si->ptr[2] = KESEL;
+ VFLAG("bios32si: eax entry %ux\n", ptr);
+
+ return si;
+}
diff --git a/sys/src/9/pc/boot.fs b/sys/src/9/pc/boot.fs
new file mode 100755
index 000000000..732e31642
--- /dev/null
+++ b/sys/src/9/pc/boot.fs
@@ -0,0 +1,202 @@
+#!/boot/rc -m /boot/rcmain
+# boot script for file servers, including standalone ones
+path=(/boot /$cputype/bin /rc/bin .)
+fn diskparts {
+ # set up any /dev/sd partitions
+ for(disk in /dev/sd*) {
+ if(test -f $disk/data && test -f $disk/ctl)
+ fdisk -p $disk/data >$disk/ctl >[2]/dev/null
+ if(test -f $disk/plan9)
+ parts=($disk/plan9*)
+ if not
+ parts=($disk/data)
+ for(part in $parts)
+ if(test -f $part)
+ prep -p $part >$disk/ctl >[2]/dev/null
+ }
+}
+
+cd /boot
+echo -n boot...
+if (! test -e /env/vmpc)
+ vmpc=23 # % of free memory for venti
+cp '#r/rtc' '#c/time'
+bind -a '#I0' /net
+bind -a '#l0' /net
+bind -a '#¤' /dev
+bind -a '#S' /dev
+bind -a '#k' /dev
+bind -a '#æ' /dev
+bind -a '#u' /dev
+bind '#p' /proc
+bind '#d' /fd
+bind -c '#s' /srv
+# bind -a /boot /
+
+# start usb for keyboard, disks, etc.
+if (test -e /dev/usb/ctl) {
+ echo -n usb...
+ usbd
+}
+if not if (test -e /dev/usb0) {
+ echo -n old usb...
+ usbd
+ if (test -e '#m/mouse')
+ kb -a2
+ if not
+ kb -k
+ disk -l -s usbdisk -m /mnt # mounts on /mnt/<lun>
+}
+
+echo -n disks...
+if(! ~ $dmaon no)
+ for (ctl in /dev/sd[C-H]?/ctl)
+ if (test -e $ctl)
+ echo 'dma on' >$ctl
+
+diskparts
+
+# set up any fs(3) partitions (HACK)
+# don't match AoE disks, as those may be shared.
+if (test ! -e /env/fscfg)
+ fscfg=`{ls -d /dev/sd[~e-h]?/fscfg >[2]/dev/null | sed 1q}
+if (~ $#fscfg 1 && test -r $fscfg)
+ zerotrunc <$fscfg | read -m >/dev/fs/ctl
+
+# figure out which arenas and fossil partitions to use.
+# don't match AoE disks, as those may be shared.
+if(! test -e /env/arena0){
+ if (test -e /dev/fs/arena0)
+ arena0= /dev/fs/arena0
+ if not if (test -e /dev/sd[~e-h]?/arena0)
+ arena0= /dev/sd[~e-h]?/arena0
+ if not
+ arena0=/dev/null
+}
+if (test -e /dev/fs/fossil)
+ fossil= /dev/fs/fossil
+if not if (test -e /dev/sd[~e-h]?/fossil)
+ fossil= /dev/sd[~e-h]?/fossil
+if not
+ fossil=/dev/null
+
+#
+# the local disks are now sorted out.
+# set up the network, auth, venti and fossil.
+#
+
+echo -n ip...
+if (~ $#ip 1 && ! ~ $ip '') {
+ # need to supply ip, ipmask and ipgw in plan9.ini to use this
+ ipconfig -g $ipgw ether /net/ether0 $ip $ipmask
+ echo 'add 0 0 '^$ipgw >>/net/iproute
+}
+if not
+ ipconfig
+switch (`{sed '/\.(0|255)[ ]/d' /net/ipselftab}) {
+case 204.178.31.*
+ echo 'add 135.104.9.0 255.255.255.0 204.178.31.10' >>/net/iproute
+}
+ipconfig loopback /dev/null 127.1
+
+# local hackery: add extra sr luns
+if (test -e /dev/aoe/1.1 && ! test -e /dev/sdf0)
+ echo config switch on spec f type aoe//dev/aoe/1.1 >/dev/sdctl
+if (test -e /dev/aoe/1.2 && ! test -e /dev/sdg0)
+ echo config switch on spec g type aoe//dev/aoe/1.2 >/dev/sdctl
+diskparts
+
+# so far we're using the default key from $nvram, usually
+# for insideout.plan9.bell-labs.com on outside machines,
+# and have mounted our root over the net, if running diskless.
+# factotum always mounts itself (on /mnt by default).
+
+echo -n factotum...
+if(~ $#auth 1){
+ echo start factotum on $auth
+ factotum -sfactotum -S -a $auth
+}
+if not
+ factotum -sfactotum -S
+mount -b /srv/factotum /mnt
+
+# if a keys partition exists, add its contents to factotum's
+keys=`{ls -d /dev/sd*/keys >[2]/dev/null | sed 1q}
+if (~ $#keys 1 && test -r $keys) {
+ echo -n add keys...
+ zerotrunc <$keys | aescbc -n -d | read -m >/mnt/factotum/ctl
+}
+
+# get root from network if fsaddr set in plan9.ini, and bail out here
+if (test -e /env/fs) {
+ echo -n fs root...
+ if(! srv tcp!$fs!564 boot)
+ exec ./rc -m/boot/rcmain -i
+ if(! mount -c /srv/boot /root)
+ exec ./rc -m/boot/rcmain -i
+}
+
+# start venti store
+if (! ~ $arena0 /dev/null && test -r $arena0) {
+ echo -n start venti on $arena0...
+ venti=tcp!127.0.0.1!17034
+ vcfg=`{ls -d /dev/sd*/venticfg >[2]/dev/null | sed 1q}
+ if (~ $#vcfg 1 && test -r $vcfg)
+ venti -m $vmpc -c $vcfg
+ if not
+ venti -m $vmpc -c $arena0
+ sleep 10
+}
+if not if (! test -e /env/venti)
+ venti=tcp!135.104.9.33!17034 # local default
+
+# start root fossil, may serve /srv/boot
+if (! ~ $fossil /dev/null && test -r $fossil) {
+ echo -n root fossil on $fossil...
+ fossil -m 2 -f $fossil
+ sleep 3
+}
+
+#
+# normal start up on local fossil root
+#
+
+rootdir=/root
+rootspec=main/active
+
+# factotum is now mounted in /mnt; keep it visible.
+# newns() needs it, among others.
+
+# mount new root
+if (test -e /srv/boot)
+ srv=boot
+if not if (test -e /srv/fossil)
+ srv=fossil
+if not if (test -e /srv/fsmain)
+ srv=fsmain
+if not {
+ echo cannot find a root in /srv:
+ ls -l /srv
+}
+echo -n mount -cC /srv/$srv $rootdir...
+ mount -cC /srv/$srv $rootdir
+bind -a $rootdir /
+
+if (test -d $rootdir/mnt)
+ bind -ac $rootdir/mnt /mnt
+mount -b /srv/factotum /mnt
+
+# standard bin
+if (! test -d /$cputype) {
+ echo /$cputype missing!
+ exec ./rc -m/boot/rcmain -i
+}
+bind /$cputype/bin /bin
+bind -a /rc/bin /bin
+
+# run cpurc
+echo cpurc...
+path=(/bin . /boot)
+/$cputype/init -c
+
+exec ./rc -m/boot/rcmain -i
diff --git a/sys/src/9/pc/cga.c b/sys/src/9/pc/cga.c
new file mode 100755
index 000000000..6365d44cc
--- /dev/null
+++ b/sys/src/9/pc/cga.c
@@ -0,0 +1,127 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+enum {
+ Black,
+ Blue,
+ Green,
+ Cyan,
+ Red,
+ Magenta,
+ Brown,
+ Grey,
+
+ Bright = 0x08,
+ Blinking = 0x80,
+
+ Yellow = Bright|Brown,
+ White = Bright|Grey,
+};
+
+enum {
+ Width = 80*2,
+ Height = 25,
+
+ Attr = (Black<<4)|Grey, /* high nibble background
+ * low foreground
+ */
+};
+
+#define CGASCREENBASE ((uchar*)KADDR(0xB8000))
+
+static int cgapos;
+static Lock cgascreenlock;
+
+static uchar
+cgaregr(int index)
+{
+ outb(0x3D4, index);
+ return inb(0x3D4+1) & 0xFF;
+}
+
+static void
+cgaregw(int index, int data)
+{
+ outb(0x3D4, index);
+ outb(0x3D4+1, data);
+}
+
+static void
+movecursor(void)
+{
+ cgaregw(0x0E, (cgapos/2>>8) & 0xFF);
+ cgaregw(0x0F, cgapos/2 & 0xFF);
+ CGASCREENBASE[cgapos+1] = Attr;
+}
+
+static void
+cgascreenputc(int c)
+{
+ int i;
+ uchar *p;
+
+ if(c == '\n'){
+ cgapos = cgapos/Width;
+ cgapos = (cgapos+1)*Width;
+ }
+ else if(c == '\t'){
+ i = 8 - ((cgapos/2)&7);
+ while(i-->0)
+ cgascreenputc(' ');
+ }
+ else if(c == '\b'){
+ if(cgapos >= 2)
+ cgapos -= 2;
+ cgascreenputc(' ');
+ cgapos -= 2;
+ }
+ else{
+ CGASCREENBASE[cgapos++] = c;
+ CGASCREENBASE[cgapos++] = Attr;
+ }
+ if(cgapos >= Width*Height){
+ memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
+ p = &CGASCREENBASE[Width*(Height-1)];
+ for(i=0; i<Width/2; i++){
+ *p++ = ' ';
+ *p++ = Attr;
+ }
+ cgapos = Width*(Height-1);
+ }
+ movecursor();
+}
+
+static void
+cgascreenputs(char* s, int n)
+{
+ if(!islo()){
+ /*
+ * Don't deadlock trying to
+ * print in an interrupt.
+ */
+ if(!canlock(&cgascreenlock))
+ return;
+ }
+ else
+ lock(&cgascreenlock);
+
+ while(n-- > 0)
+ cgascreenputc(*s++);
+
+ unlock(&cgascreenlock);
+}
+
+void
+screeninit(void)
+{
+
+ cgapos = cgaregr(0x0E)<<8;
+ cgapos |= cgaregr(0x0F);
+ cgapos *= 2;
+
+ screenputs = cgascreenputs;
+}
diff --git a/sys/src/9/pc/dat.h b/sys/src/9/pc/dat.h
new file mode 100755
index 000000000..4786d8967
--- /dev/null
+++ b/sys/src/9/pc/dat.h
@@ -0,0 +1,350 @@
+typedef struct BIOS32si BIOS32si;
+typedef struct BIOS32ci BIOS32ci;
+typedef struct Conf Conf;
+typedef struct Confmem Confmem;
+typedef struct FPsave FPsave;
+typedef struct ISAConf ISAConf;
+typedef struct Label Label;
+typedef struct Lock Lock;
+typedef struct MMU MMU;
+typedef struct Mach Mach;
+typedef struct Notsave Notsave;
+typedef struct PCArch PCArch;
+typedef struct Pcidev Pcidev;
+typedef struct PCMmap PCMmap;
+typedef struct PCMslot PCMslot;
+typedef struct Page Page;
+typedef struct PMMU PMMU;
+typedef struct Proc Proc;
+typedef struct Segdesc Segdesc;
+typedef vlong Tval;
+typedef struct Ureg Ureg;
+typedef struct Vctl Vctl;
+
+#pragma incomplete BIOS32si
+#pragma incomplete Pcidev
+#pragma incomplete Ureg
+
+#define MAXSYSARG 5 /* for mount(fd, afd, mpt, flag, arg) */
+
+/*
+ * parameters for sysproc.c
+ */
+#define AOUT_MAGIC (I_MAGIC)
+
+struct Lock
+{
+ ulong key;
+ ulong sr;
+ ulong pc;
+ Proc *p;
+ Mach *m;
+ ushort isilock;
+ long lockcycles;
+};
+
+struct Label
+{
+ ulong sp;
+ ulong pc;
+};
+
+
+/*
+ * FPsave.status
+ */
+enum
+{
+ /* this is a state */
+ FPinit= 0,
+ FPactive= 1,
+ FPinactive= 2,
+
+ /* the following is a bit that can be or'd into the state */
+ FPillegal= 0x100,
+};
+
+struct FPsave
+{
+ ushort control;
+ ushort r1;
+ ushort status;
+ ushort r2;
+ ushort tag;
+ ushort r3;
+ ulong pc;
+ ushort selector;
+ ushort r4;
+ ulong operand;
+ ushort oselector;
+ ushort r5;
+ 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? */
+ 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 */
+ 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 */
+ ulong ialloc; /* max interrupt time allocation in bytes */
+ ulong pipeqsize; /* size in bytes of pipe queues */
+ int nuart; /* number of uart devices */
+};
+
+/*
+ * MMU stuff in proc
+ */
+#define NCOLOR 1
+struct PMMU
+{
+ Page* mmupdb; /* page directory base */
+ Page* mmufree; /* unused page table pages */
+ Page* mmuused; /* used page table pages */
+ Page* kmaptable; /* page table used by kmap */
+ uint lastkmap; /* last entry used by kmap */
+ int nkmap; /* number of current kmaps */
+};
+
+/*
+ * things saved in the Proc structure during a notify
+ */
+struct Notsave
+{
+ ulong svflags;
+ ulong svcs;
+ ulong svss;
+};
+
+#include "../port/portdat.h"
+
+typedef struct {
+ ulong link; /* link (old TSS selector) */
+ ulong esp0; /* privilege level 0 stack pointer */
+ ulong ss0; /* privilege level 0 stack selector */
+ ulong esp1; /* privilege level 1 stack pointer */
+ ulong ss1; /* privilege level 1 stack selector */
+ ulong esp2; /* privilege level 2 stack pointer */
+ ulong ss2; /* privilege level 2 stack selector */
+ ulong xcr3; /* page directory base register - not used because we don't use trap gates */
+ ulong eip; /* instruction pointer */
+ ulong eflags; /* flags register */
+ ulong eax; /* general registers */
+ ulong ecx;
+ ulong edx;
+ ulong ebx;
+ ulong esp;
+ ulong ebp;
+ ulong esi;
+ ulong edi;
+ ulong es; /* segment selectors */
+ ulong cs;
+ ulong ss;
+ ulong ds;
+ ulong fs;
+ ulong gs;
+ ulong ldt; /* selector for task's LDT */
+ ulong iomap; /* I/O map base address + T-bit */
+} Tss;
+
+struct Segdesc
+{
+ ulong d0;
+ ulong d1;
+};
+
+struct Mach
+{
+ int machno; /* physical id of processor (KNOWN TO ASSEMBLY) */
+ ulong splpc; /* pc of last caller to splhi */
+
+ ulong* pdb; /* page directory base for this processor (va) */
+ Tss* tss; /* tss for this processor */
+ Segdesc *gdt; /* gdt for this processor */
+
+ Proc* proc; /* current process on this processor */
+ Proc* externup; /* extern register Proc *up */
+
+ Page* pdbpool;
+ int pdbcnt;
+
+ ulong ticks; /* of the clock since boot time */
+ Label sched; /* scheduler wakeup */
+ Lock alarmlock; /* access to alarm list */
+ void* alarm; /* alarms bound to this clock */
+ int inclockintr;
+
+ Proc* readied; /* for runproc */
+ ulong schedticks; /* next forced context switch */
+
+ int tlbfault;
+ int tlbpurge;
+ int pfault;
+ int cs;
+ int syscall;
+ int load;
+ int intr;
+ int flushmmu; /* make current proc flush it's mmu state */
+ int ilockdepth;
+ Perf perf; /* performance counters */
+
+ ulong spuriousintr;
+ int lastintr;
+
+ int loopconst;
+
+ Lock apictimerlock;
+ int cpumhz;
+ uvlong cyclefreq; /* Frequency of user readable cycle counter */
+ uvlong cpuhz;
+ int cpuidax;
+ int cpuiddx;
+ char cpuidid[16];
+ char* cpuidtype;
+ int havetsc;
+ int havepge;
+ uvlong tscticks;
+ int pdballoc;
+ int pdbfree;
+
+ vlong mtrrcap;
+ vlong mtrrdef;
+ vlong mtrrfix[11];
+ vlong mtrrvar[32]; /* 256 max. */
+
+ int stack[1];
+};
+
+/*
+ * KMap the structure doesn't exist, but the functions do.
+ */
+typedef struct KMap KMap;
+#define VA(k) ((void*)(k))
+KMap* kmap(Page*);
+void kunmap(KMap*);
+
+struct
+{
+ Lock;
+ int machs; /* bitmap of active CPUs */
+ int exiting; /* shutdown */
+ int ispanic; /* shutdown in response to a panic */
+ int thunderbirdsarego; /* lets the added processors continue to schedinit */
+}active;
+
+/*
+ * routines for things outside the PC model, like power management
+ */
+struct PCArch
+{
+ char* id;
+ int (*ident)(void); /* this should be in the model */
+ void (*reset)(void); /* this should be in the model */
+ int (*serialpower)(int); /* 1 == on, 0 == off */
+ int (*modempower)(int); /* 1 == on, 0 == off */
+
+ void (*intrinit)(void);
+ int (*intrenable)(Vctl*);
+ int (*intrvecno)(int);
+ int (*intrdisable)(int);
+ void (*introff)(void);
+ void (*intron)(void);
+
+ void (*clockenable)(void);
+ uvlong (*fastclock)(uvlong*);
+ void (*timerset)(uvlong);
+};
+
+/* cpuid instruction result register bits */
+enum {
+ /* dx */
+ Fpuonchip = 1<<0,
+// Pse = 1<<3, /* page size extensions */
+ Tsc = 1<<4, /* time-stamp counter */
+ Cpumsr = 1<<5, /* model-specific registers, rdmsr/wrmsr */
+ Pae = 1<<6, /* physical-addr extensions */
+ Mce = 1<<7, /* machine-check exception */
+ Cmpxchg8b = 1<<8,
+ Cpuapic = 1<<9,
+ Mtrr = 1<<12, /* memory-type range regs. */
+ Pge = 1<<13, /* page global extension */
+// Pse2 = 1<<17, /* more page size extensions */
+ Clflush = 1<<19,
+ Mmx = 1<<23,
+ Sse = 1<<25, /* thus sfence instr. */
+ Sse2 = 1<<26, /* thus mfence & lfence instr.s */
+};
+
+/*
+ * a parsed plan9.ini line
+ */
+#define NISAOPT 8
+
+struct ISAConf {
+ char *type;
+ ulong port;
+ int irq;
+ ulong dma;
+ ulong mem;
+ ulong size;
+ ulong freq;
+
+ int nopt;
+ char *opt[NISAOPT];
+};
+
+extern PCArch *arch; /* PC architecture */
+
+/*
+ * Each processor sees its own Mach structure at address MACHADDR.
+ * However, the Mach structures must also be available via the per-processor
+ * MMU information array machp, mainly for disambiguation and access to
+ * the clock which is only maintained by the bootstrap processor (0).
+ */
+Mach* machp[MAXMACH];
+
+#define MACHP(n) (machp[n])
+
+extern Mach *m;
+#define up (((Mach*)MACHADDR)->externup)
+
+/*
+ * hardware info about a device
+ */
+typedef struct {
+ ulong port;
+ int size;
+} Devport;
+
+struct DevConf
+{
+ ulong intnum; /* interrupt number */
+ char *type; /* card type, malloced */
+ int nports; /* Number of ports */
+ Devport *ports; /* The ports themselves */
+};
+
+typedef struct BIOS32ci { /* BIOS32 Calling Interface */
+ u32int eax;
+ u32int ebx;
+ u32int ecx;
+ u32int edx;
+ u32int esi;
+ u32int edi;
+} BIOS32ci;
diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c
new file mode 100755
index 000000000..bd216c2ad
--- /dev/null
+++ b/sys/src/9/pc/devarch.c
@@ -0,0 +1,1062 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+typedef struct IOMap IOMap;
+struct IOMap
+{
+ IOMap *next;
+ int reserved;
+ char tag[13];
+ ulong start;
+ ulong end;
+};
+
+static struct
+{
+ Lock;
+ IOMap *m;
+ IOMap *free;
+ IOMap maps[32]; /* some initial free maps */
+
+ QLock ql; /* lock for reading map */
+} iomap;
+
+enum {
+ Qdir = 0,
+ Qioalloc = 1,
+ Qiob,
+ Qiow,
+ Qiol,
+ Qbase,
+
+ Qmax = 16,
+};
+enum { /* cpuid standard function codes */
+ Highstdfunc = 0, /* also returns vendor string */
+ Procsig,
+ Proctlbcache,
+ Procserial,
+};
+
+typedef long Rdwrfn(Chan*, void*, long, vlong);
+
+static Rdwrfn *readfn[Qmax];
+static Rdwrfn *writefn[Qmax];
+
+static Dirtab archdir[Qmax] = {
+ ".", { Qdir, 0, QTDIR }, 0, 0555,
+ "ioalloc", { Qioalloc, 0 }, 0, 0444,
+ "iob", { Qiob, 0 }, 0, 0660,
+ "iow", { Qiow, 0 }, 0, 0660,
+ "iol", { Qiol, 0 }, 0, 0660,
+};
+Lock archwlock; /* the lock is only for changing archdir */
+int narchdir = Qbase;
+int (*_pcmspecial)(char*, ISAConf*);
+void (*_pcmspecialclose)(int);
+
+static int doi8253set = 1;
+
+/*
+ * Add a file to the #P listing. Once added, you can't delete it.
+ * You can't add a file with the same name as one already there,
+ * and you get a pointer to the Dirtab entry so you can do things
+ * like change the Qid version. Changing the Qid path is disallowed.
+ */
+Dirtab*
+addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
+{
+ int i;
+ Dirtab d;
+ Dirtab *dp;
+
+ memset(&d, 0, sizeof d);
+ strcpy(d.name, name);
+ d.perm = perm;
+
+ lock(&archwlock);
+ if(narchdir >= Qmax){
+ unlock(&archwlock);
+ return nil;
+ }
+
+ for(i=0; i<narchdir; i++)
+ if(strcmp(archdir[i].name, name) == 0){
+ unlock(&archwlock);
+ return nil;
+ }
+
+ d.qid.path = narchdir;
+ archdir[narchdir] = d;
+ readfn[narchdir] = rdfn;
+ writefn[narchdir] = wrfn;
+ dp = &archdir[narchdir++];
+ unlock(&archwlock);
+
+ return dp;
+}
+
+void
+ioinit(void)
+{
+ char *excluded;
+ int i;
+
+ for(i = 0; i < nelem(iomap.maps)-1; i++)
+ iomap.maps[i].next = &iomap.maps[i+1];
+ iomap.maps[i].next = nil;
+ iomap.free = iomap.maps;
+
+ /*
+ * This is necessary to make the IBM X20 boot.
+ * Have not tracked down the reason.
+ * i82557 is at 0x1000, the dummy entry is needed for swappable devs.
+ */
+ ioalloc(0x0fff, 1, 0, "dummy");
+
+ if ((excluded = getconf("ioexclude")) != nil) {
+ char *s;
+
+ s = excluded;
+ while (s && *s != '\0' && *s != '\n') {
+ char *ends;
+ int io_s, io_e;
+
+ io_s = (int)strtol(s, &ends, 0);
+ if (ends == nil || ends == s || *ends != '-') {
+ print("ioinit: cannot parse option string\n");
+ break;
+ }
+ s = ++ends;
+
+ io_e = (int)strtol(s, &ends, 0);
+ if (ends && *ends == ',')
+ *ends++ = '\0';
+ s = ends;
+
+ ioalloc(io_s, io_e - io_s + 1, 0, "pre-allocated");
+ }
+ }
+
+}
+
+/*
+ * Reserve a range to be ioalloced later.
+ * This is in particular useful for exchangable cards, such
+ * as pcmcia and cardbus cards.
+ */
+int
+ioreserve(int, int size, int align, char *tag)
+{
+ IOMap *m, **l;
+ int i, port;
+
+ lock(&iomap);
+ /* find a free port above 0x400 and below 0x1000 */
+ port = 0x400;
+ for(l = &iomap.m; *l; l = &(*l)->next){
+ m = *l;
+ if (m->start < 0x400) continue;
+ i = m->start - port;
+ if(i > size)
+ break;
+ if(align > 0)
+ port = ((port+align-1)/align)*align;
+ else
+ port = m->end;
+ }
+ if(*l == nil){
+ unlock(&iomap);
+ return -1;
+ }
+ m = iomap.free;
+ if(m == nil){
+ print("ioalloc: out of maps");
+ unlock(&iomap);
+ return port;
+ }
+ iomap.free = m->next;
+ m->next = *l;
+ m->start = port;
+ m->end = port + size;
+ m->reserved = 1;
+ strncpy(m->tag, tag, sizeof(m->tag));
+ m->tag[sizeof(m->tag)-1] = 0;
+ *l = m;
+
+ archdir[0].qid.vers++;
+
+ unlock(&iomap);
+ return m->start;
+}
+
+/*
+ * alloc some io port space and remember who it was
+ * alloced to. if port < 0, find a free region.
+ */
+int
+ioalloc(int port, int size, int align, char *tag)
+{
+ IOMap *m, **l;
+ int i;
+
+ lock(&iomap);
+ if(port < 0){
+ /* find a free port above 0x400 and below 0x1000 */
+ port = 0x400;
+ for(l = &iomap.m; *l; l = &(*l)->next){
+ m = *l;
+ if (m->start < 0x400) continue;
+ i = m->start - port;
+ if(i > size)
+ break;
+ if(align > 0)
+ port = ((port+align-1)/align)*align;
+ else
+ port = m->end;
+ }
+ if(*l == nil){
+ unlock(&iomap);
+ return -1;
+ }
+ } else {
+ /* Only 64KB I/O space on the x86. */
+ if((port+size) > 0x10000){
+ unlock(&iomap);
+ return -1;
+ }
+ /* see if the space clashes with previously allocated ports */
+ for(l = &iomap.m; *l; l = &(*l)->next){
+ m = *l;
+ if(m->end <= port)
+ continue;
+ if(m->reserved && m->start == port && m->end == port + size) {
+ m->reserved = 0;
+ unlock(&iomap);
+ return m->start;
+ }
+ if(m->start >= port+size)
+ break;
+ unlock(&iomap);
+ return -1;
+ }
+ }
+ m = iomap.free;
+ if(m == nil){
+ print("ioalloc: out of maps");
+ unlock(&iomap);
+ return port;
+ }
+ iomap.free = m->next;
+ m->next = *l;
+ m->start = port;
+ m->end = port + size;
+ strncpy(m->tag, tag, sizeof(m->tag));
+ m->tag[sizeof(m->tag)-1] = 0;
+ *l = m;
+
+ archdir[0].qid.vers++;
+
+ unlock(&iomap);
+ return m->start;
+}
+
+void
+iofree(int port)
+{
+ IOMap *m, **l;
+
+ lock(&iomap);
+ for(l = &iomap.m; *l; l = &(*l)->next){
+ if((*l)->start == port){
+ m = *l;
+ *l = m->next;
+ m->next = iomap.free;
+ iomap.free = m;
+ break;
+ }
+ if((*l)->start > port)
+ break;
+ }
+ archdir[0].qid.vers++;
+ unlock(&iomap);
+}
+
+int
+iounused(int start, int end)
+{
+ IOMap *m;
+
+ for(m = iomap.m; m; m = m->next){
+ if(start >= m->start && start < m->end
+ || start <= m->start && end > m->start)
+ return 0;
+ }
+ return 1;
+}
+
+static void
+checkport(int start, int end)
+{
+ /* standard vga regs are OK */
+ if(start >= 0x2b0 && end <= 0x2df+1)
+ return;
+ if(start >= 0x3c0 && end <= 0x3da+1)
+ return;
+
+ if(iounused(start, end))
+ return;
+ error(Eperm);
+}
+
+static Chan*
+archattach(char* spec)
+{
+ return devattach('P', spec);
+}
+
+Walkqid*
+archwalk(Chan* c, Chan *nc, char** name, int nname)
+{
+ return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
+}
+
+static int
+archstat(Chan* c, uchar* dp, int n)
+{
+ return devstat(c, dp, n, archdir, narchdir, devgen);
+}
+
+static Chan*
+archopen(Chan* c, int omode)
+{
+ return devopen(c, omode, archdir, narchdir, devgen);
+}
+
+static void
+archclose(Chan*)
+{
+}
+
+enum
+{
+ Linelen= 31,
+};
+
+static long
+archread(Chan *c, void *a, long n, vlong offset)
+{
+ char *buf, *p;
+ int port;
+ ushort *sp;
+ ulong *lp;
+ IOMap *m;
+ Rdwrfn *fn;
+
+ switch((ulong)c->qid.path){
+
+ case Qdir:
+ return devdirread(c, a, n, archdir, narchdir, devgen);
+
+ case Qiob:
+ port = offset;
+ checkport(offset, offset+n);
+ for(p = a; port < offset+n; port++)
+ *p++ = inb(port);
+ return n;
+
+ case Qiow:
+ if(n & 1)
+ error(Ebadarg);
+ checkport(offset, offset+n);
+ sp = a;
+ for(port = offset; port < offset+n; port += 2)
+ *sp++ = ins(port);
+ return n;
+
+ case Qiol:
+ if(n & 3)
+ error(Ebadarg);
+ checkport(offset, offset+n);
+ lp = a;
+ for(port = offset; port < offset+n; port += 4)
+ *lp++ = inl(port);
+ return n;
+
+ case Qioalloc:
+ break;
+
+ default:
+ if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
+ return fn(c, a, n, offset);
+ error(Eperm);
+ break;
+ }
+
+ if((buf = malloc(n)) == nil)
+ error(Enomem);
+ p = buf;
+ n = n/Linelen;
+ offset = offset/Linelen;
+
+ lock(&iomap);
+ for(m = iomap.m; n > 0 && m != nil; m = m->next){
+ if(offset-- > 0)
+ continue;
+ sprint(p, "%8lux %8lux %-12.12s\n", m->start, m->end-1, m->tag);
+ p += Linelen;
+ n--;
+ }
+ unlock(&iomap);
+
+ n = p - buf;
+ memmove(a, buf, n);
+ free(buf);
+
+ return n;
+}
+
+static long
+archwrite(Chan *c, void *a, long n, vlong offset)
+{
+ char *p;
+ int port;
+ ushort *sp;
+ ulong *lp;
+ Rdwrfn *fn;
+
+ switch((ulong)c->qid.path){
+
+ case Qiob:
+ p = a;
+ checkport(offset, offset+n);
+ for(port = offset; port < offset+n; port++)
+ outb(port, *p++);
+ return n;
+
+ case Qiow:
+ if(n & 1)
+ error(Ebadarg);
+ checkport(offset, offset+n);
+ sp = a;
+ for(port = offset; port < offset+n; port += 2)
+ outs(port, *sp++);
+ return n;
+
+ case Qiol:
+ if(n & 3)
+ error(Ebadarg);
+ checkport(offset, offset+n);
+ lp = a;
+ for(port = offset; port < offset+n; port += 4)
+ outl(port, *lp++);
+ return n;
+
+ default:
+ if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
+ return fn(c, a, n, offset);
+ error(Eperm);
+ break;
+ }
+ return 0;
+}
+
+Dev archdevtab = {
+ 'P',
+ "arch",
+
+ devreset,
+ devinit,
+ devshutdown,
+ archattach,
+ archwalk,
+ archstat,
+ archopen,
+ devcreate,
+ archclose,
+ archread,
+ devbread,
+ archwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+/*
+ * the following is a generic version of the
+ * architecture specific stuff
+ */
+
+static int
+unimplemented(int)
+{
+ return 0;
+}
+
+static void
+nop(void)
+{
+}
+
+static void
+archreset(void)
+{
+ i8042reset();
+
+ /*
+ * Often the BIOS hangs during restart if a conventional 8042
+ * warm-boot sequence is tried. The following is Intel specific and
+ * seems to perform a cold-boot, but at least it comes back.
+ * And sometimes there is no keyboard...
+ *
+ * The reset register (0xcf9) is usually in one of the bridge
+ * chips. The actual location and sequence could be extracted from
+ * ACPI but why bother, this is the end of the line anyway.
+ */
+ print("Takes a licking and keeps on ticking...\n");
+ *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */
+ outb(0xcf9, 0x02);
+ outb(0xcf9, 0x06);
+
+ for(;;)
+ idle();
+}
+
+/*
+ * 386 has no compare-and-swap instruction.
+ * Run it with interrupts turned off instead.
+ */
+static int
+cmpswap386(long *addr, long old, long new)
+{
+ int r, s;
+
+ s = splhi();
+ if(r = (*addr == old))
+ *addr = new;
+ splx(s);
+ return r;
+}
+
+/*
+ * On a uniprocessor, you'd think that coherence could be nop,
+ * but it can't. We still need a barrier when using coherence() in
+ * device drivers.
+ *
+ * On VMware, it's safe (and a huge win) to set this to nop.
+ * Aux/vmware does this via the #P/archctl file.
+ */
+void (*coherence)(void) = nop;
+
+int (*cmpswap)(long*, long, long) = cmpswap386;
+
+PCArch* arch;
+extern PCArch* knownarch[];
+
+PCArch archgeneric = {
+.id= "generic",
+.ident= 0,
+.reset= archreset,
+.serialpower= unimplemented,
+.modempower= unimplemented,
+
+.intrinit= i8259init,
+.intrenable= i8259enable,
+.intrvecno= i8259vecno,
+.intrdisable= i8259disable,
+.intron= i8259on,
+.introff= i8259off,
+
+.clockenable= i8253enable,
+.fastclock= i8253read,
+.timerset= i8253timerset,
+};
+
+typedef struct X86type X86type;
+struct X86type {
+ int family;
+ int model;
+ int aalcycles;
+ char* name;
+};
+
+static X86type x86intel[] =
+{
+ { 4, 0, 22, "486DX", }, /* known chips */
+ { 4, 1, 22, "486DX50", },
+ { 4, 2, 22, "486SX", },
+ { 4, 3, 22, "486DX2", },
+ { 4, 4, 22, "486SL", },
+ { 4, 5, 22, "486SX2", },
+ { 4, 7, 22, "DX2WB", }, /* P24D */
+ { 4, 8, 22, "DX4", }, /* P24C */
+ { 4, 9, 22, "DX4WB", }, /* P24CT */
+ { 5, 0, 23, "P5", },
+ { 5, 1, 23, "P5", },
+ { 5, 2, 23, "P54C", },
+ { 5, 3, 23, "P24T", },
+ { 5, 4, 23, "P55C MMX", },
+ { 5, 7, 23, "P54C VRT", },
+ { 6, 1, 16, "PentiumPro", },/* trial and error */
+ { 6, 3, 16, "PentiumII", },
+ { 6, 5, 16, "PentiumII/Xeon", },
+ { 6, 6, 16, "Celeron", },
+ { 6, 7, 16, "PentiumIII/Xeon", },
+ { 6, 8, 16, "PentiumIII/Xeon", },
+ { 6, 0xB, 16, "PentiumIII/Xeon", },
+ { 6, 0xF, 16, "Xeon5000-series", },
+ { 6, 0x16, 16, "Celeron", },
+ { 6, 0x17, 16, "Core 2/Xeon", },
+ { 6, 0x1A, 16, "Core i7/Xeon", },
+ { 6, 0x1C, 16, "Atom", },
+ { 6, 0x1D, 16, "Xeon MP", },
+ { 0xF, 1, 16, "P4", }, /* P4 */
+ { 0xF, 2, 16, "PentiumIV/Xeon", },
+ { 0xF, 6, 16, "PentiumIV/Xeon", },
+
+ { 3, -1, 32, "386", }, /* family defaults */
+ { 4, -1, 22, "486", },
+ { 5, -1, 23, "P5", },
+ { 6, -1, 16, "P6", },
+ { 0xF, -1, 16, "P4", }, /* P4 */
+
+ { -1, -1, 16, "unknown", }, /* total default */
+};
+
+/*
+ * The AMD processors all implement the CPUID instruction.
+ * The later ones also return the processor name via functions
+ * 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX
+ * and DX:
+ * K5 "AMD-K5(tm) Processor"
+ * K6 "AMD-K6tm w/ multimedia extensions"
+ * K6 3D "AMD-K6(tm) 3D processor"
+ * K6 3D+ ?
+ */
+static X86type x86amd[] =
+{
+ { 5, 0, 23, "AMD-K5", }, /* guesswork */
+ { 5, 1, 23, "AMD-K5", }, /* guesswork */
+ { 5, 2, 23, "AMD-K5", }, /* guesswork */
+ { 5, 3, 23, "AMD-K5", }, /* guesswork */
+ { 5, 4, 23, "AMD Geode GX1", }, /* guesswork */
+ { 5, 5, 23, "AMD Geode GX2", }, /* guesswork */
+ { 5, 6, 11, "AMD-K6", }, /* trial and error */
+ { 5, 7, 11, "AMD-K6", }, /* trial and error */
+ { 5, 8, 11, "AMD-K6-2", }, /* trial and error */
+ { 5, 9, 11, "AMD-K6-III", },/* trial and error */
+ { 5, 0xa, 23, "AMD Geode LX", }, /* guesswork */
+
+ { 6, 1, 11, "AMD-Athlon", },/* trial and error */
+ { 6, 2, 11, "AMD-Athlon", },/* trial and error */
+
+ { 0x1F, 9, 11, "AMD-K10 Opteron G34", },/* guesswork */
+
+ { 4, -1, 22, "Am486", }, /* guesswork */
+ { 5, -1, 23, "AMD-K5/K6", }, /* guesswork */
+ { 6, -1, 11, "AMD-Athlon", },/* guesswork */
+ { 0xF, -1, 11, "AMD-K8", }, /* guesswork */
+ { 0x1F, -1, 11, "AMD-K10", }, /* guesswork */
+
+ { -1, -1, 11, "unknown", }, /* total default */
+};
+
+/*
+ * WinChip 240MHz
+ */
+static X86type x86winchip[] =
+{
+ {5, 4, 23, "Winchip",}, /* guesswork */
+ {6, 7, 23, "Via C3 Samuel 2 or Ezra",},
+ {6, 8, 23, "Via C3 Ezra-T",},
+ {6, 9, 23, "Via C3 Eden-N",},
+ { -1, -1, 23, "unknown", }, /* total default */
+};
+
+/*
+ * SiS 55x
+ */
+static X86type x86sis[] =
+{
+ {5, 0, 23, "SiS 55x",}, /* guesswork */
+ { -1, -1, 23, "unknown", }, /* total default */
+};
+
+static X86type *cputype;
+
+static void simplecycles(uvlong*);
+void (*cycles)(uvlong*) = simplecycles;
+void _cycles(uvlong*); /* in l.s */
+
+static void
+simplecycles(uvlong*x)
+{
+ *x = m->ticks;
+}
+
+void
+cpuidprint(void)
+{
+ int i;
+ char buf[128];
+
+ i = sprint(buf, "cpu%d: %dMHz ", m->machno, m->cpumhz);
+ if(m->cpuidid[0])
+ i += sprint(buf+i, "%12.12s ", m->cpuidid);
+ seprint(buf+i, buf + sizeof buf - 1,
+ "%s (cpuid: AX 0x%4.4uX DX 0x%4.4uX)\n",
+ m->cpuidtype, m->cpuidax, m->cpuiddx);
+ print(buf);
+}
+
+/*
+ * figure out:
+ * - cpu type
+ * - whether or not we have a TSC (cycle counter)
+ * - whether or not it supports page size extensions
+ * (if so turn it on)
+ * - whether or not it supports machine check exceptions
+ * (if so turn it on)
+ * - whether or not it supports the page global flag
+ * (if so turn it on)
+ */
+int
+cpuidentify(void)
+{
+ char *p;
+ int family, model, nomce;
+ X86type *t, *tab;
+ ulong cr4;
+ ulong regs[4];
+ vlong mca, mct;
+
+ cpuid(Highstdfunc, regs);
+ memmove(m->cpuidid, &regs[1], BY2WD); /* bx */
+ memmove(m->cpuidid+4, &regs[3], BY2WD); /* dx */
+ memmove(m->cpuidid+8, &regs[2], BY2WD); /* cx */
+ m->cpuidid[12] = '\0';
+
+ cpuid(Procsig, regs);
+ m->cpuidax = regs[0];
+ m->cpuiddx = regs[3];
+
+ if(strncmp(m->cpuidid, "AuthenticAMD", 12) == 0 ||
+ strncmp(m->cpuidid, "Geode by NSC", 12) == 0)
+ tab = x86amd;
+ else if(strncmp(m->cpuidid, "CentaurHauls", 12) == 0)
+ tab = x86winchip;
+ else if(strncmp(m->cpuidid, "SiS SiS SiS ", 12) == 0)
+ tab = x86sis;
+ else
+ tab = x86intel;
+
+ family = X86FAMILY(m->cpuidax);
+ model = X86MODEL(m->cpuidax);
+ for(t=tab; t->name; t++)
+ if((t->family == family && t->model == model)
+ || (t->family == family && t->model == -1)
+ || (t->family == -1))
+ break;
+
+ m->cpuidtype = t->name;
+
+ /*
+ * if there is one, set tsc to a known value
+ */
+ if(m->cpuiddx & Tsc){
+ m->havetsc = 1;
+ cycles = _cycles;
+ if(m->cpuiddx & Cpumsr)
+ wrmsr(0x10, 0);
+ }
+
+ /*
+ * use i8253 to guess our cpu speed
+ */
+ guesscpuhz(t->aalcycles);
+
+ /*
+ * If machine check exception, page size extensions or page global bit
+ * are supported enable them in CR4 and clear any other set extensions.
+ * If machine check was enabled clear out any lingering status.
+ */
+ if(m->cpuiddx & (Pge|Mce|0x8)){
+ cr4 = 0;
+ if(m->cpuiddx & 0x08)
+ cr4 |= 0x10; /* page size extensions */
+ if(p = getconf("*nomce"))
+ nomce = strtoul(p, 0, 0);
+ else
+ nomce = 0;
+ if((m->cpuiddx & Mce) && !nomce){
+ cr4 |= 0x40; /* machine check enable */
+ if(family == 5){
+ rdmsr(0x00, &mca);
+ rdmsr(0x01, &mct);
+ }
+ }
+
+ /*
+ * Detect whether the chip supports the global bit
+ * in page directory and page table entries. When set
+ * in a particular entry, it means ``don't bother removing
+ * this from the TLB when CR3 changes.''
+ *
+ * We flag all kernel pages with this bit. Doing so lessens the
+ * overhead of switching processes on bare hardware,
+ * even more so on VMware. See mmu.c:/^memglobal.
+ *
+ * For future reference, should we ever need to do a
+ * full TLB flush, it can be accomplished by clearing
+ * the PGE bit in CR4, writing to CR3, and then
+ * restoring the PGE bit.
+ */
+ if(m->cpuiddx & Pge){
+ cr4 |= 0x80; /* page global enable bit */
+ m->havepge = 1;
+ }
+
+ putcr4(cr4);
+ if(m->cpuiddx & Mce)
+ rdmsr(0x01, &mct);
+ }
+
+ cputype = t;
+ return t->family;
+}
+
+static long
+cputyperead(Chan*, void *a, long n, vlong offset)
+{
+ char str[32];
+ ulong mhz;
+
+ mhz = (m->cpuhz+999999)/1000000;
+
+ snprint(str, sizeof(str), "%s %lud\n", cputype->name, mhz);
+ return readstr(offset, a, n, str);
+}
+
+static long
+archctlread(Chan*, void *a, long nn, vlong offset)
+{
+ int n;
+ char *buf, *p, *ep;
+
+ p = buf = malloc(READSTR);
+ ep = p + READSTR;
+ p = seprint(p, ep, "cpu %s %lud%s\n",
+ cputype->name, (ulong)(m->cpuhz+999999)/1000000,
+ m->havepge ? " pge" : "");
+ p = seprint(p, ep, "pge %s\n", getcr4()&0x80 ? "on" : "off");
+ p = seprint(p, ep, "coherence ");
+ if(coherence == mb386)
+ p = seprint(p, ep, "mb386\n");
+ else if(coherence == mb586)
+ p = seprint(p, ep, "mb586\n");
+ else if(coherence == mfence)
+ p = seprint(p, ep, "mfence\n");
+ else if(coherence == nop)
+ p = seprint(p, ep, "nop\n");
+ else
+ p = seprint(p, ep, "0x%p\n", coherence);
+ p = seprint(p, ep, "cmpswap ");
+ if(cmpswap == cmpswap386)
+ p = seprint(p, ep, "cmpswap386\n");
+ else if(cmpswap == cmpswap486)
+ p = seprint(p, ep, "cmpswap486\n");
+ else
+ p = seprint(p, ep, "0x%p\n", cmpswap);
+ p = seprint(p, ep, "i8253set %s\n", doi8253set ? "on" : "off");
+ n = p - buf;
+ n += mtrrprint(p, ep - p);
+ buf[n] = '\0';
+
+ n = readstr(offset, a, nn, buf);
+ free(buf);
+ return n;
+}
+
+enum
+{
+ CMpge,
+ CMcoherence,
+ CMi8253set,
+ CMcache,
+};
+
+static Cmdtab archctlmsg[] =
+{
+ CMpge, "pge", 2,
+ CMcoherence, "coherence", 2,
+ CMi8253set, "i8253set", 2,
+ CMcache, "cache", 4,
+};
+
+static long
+archctlwrite(Chan*, void *a, long n, vlong)
+{
+ uvlong base, size;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ char *ep;
+
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, archctlmsg, nelem(archctlmsg));
+ switch(ct->index){
+ case CMpge:
+ if(!m->havepge)
+ error("processor does not support pge");
+ if(strcmp(cb->f[1], "on") == 0)
+ putcr4(getcr4() | 0x80);
+ else if(strcmp(cb->f[1], "off") == 0)
+ putcr4(getcr4() & ~0x80);
+ else
+ cmderror(cb, "invalid pge ctl");
+ break;
+ case CMcoherence:
+ if(strcmp(cb->f[1], "mb386") == 0)
+ coherence = mb386;
+ else if(strcmp(cb->f[1], "mb586") == 0){
+ if(X86FAMILY(m->cpuidax) < 5)
+ error("invalid coherence ctl on this cpu family");
+ coherence = mb586;
+ }else if(strcmp(cb->f[1], "mfence") == 0){
+ if((m->cpuiddx & Sse2) == 0)
+ error("invalid coherence ctl on this cpu family");
+ coherence = mfence;
+ }else if(strcmp(cb->f[1], "nop") == 0){
+ /* only safe on vmware */
+ if(conf.nmach > 1)
+ error("cannot disable coherence on a multiprocessor");
+ coherence = nop;
+ }else
+ cmderror(cb, "invalid coherence ctl");
+ break;
+ case CMi8253set:
+ if(strcmp(cb->f[1], "on") == 0)
+ doi8253set = 1;
+ else if(strcmp(cb->f[1], "off") == 0){
+ doi8253set = 0;
+ (*arch->timerset)(0);
+ }else
+ cmderror(cb, "invalid i2853set ctl");
+ break;
+ case CMcache:
+ base = strtoull(cb->f[1], &ep, 0);
+ if(*ep)
+ error("cache: parse error: base not a number?");
+ size = strtoull(cb->f[2], &ep, 0);
+ if(*ep)
+ error("cache: parse error: size not a number?");
+ mtrr(base, size, cb->f[3]);
+ break;
+ }
+ free(cb);
+ poperror();
+ return n;
+}
+
+void
+archinit(void)
+{
+ PCArch **p;
+
+ arch = 0;
+ for(p = knownarch; *p; p++){
+ if((*p)->ident && (*p)->ident() == 0){
+ arch = *p;
+ break;
+ }
+ }
+ if(arch == 0)
+ arch = &archgeneric;
+ else{
+ if(arch->id == 0)
+ arch->id = archgeneric.id;
+ if(arch->reset == 0)
+ arch->reset = archgeneric.reset;
+ if(arch->serialpower == 0)
+ arch->serialpower = archgeneric.serialpower;
+ if(arch->modempower == 0)
+ arch->modempower = archgeneric.modempower;
+ if(arch->intrinit == 0)
+ arch->intrinit = archgeneric.intrinit;
+ if(arch->intrenable == 0)
+ arch->intrenable = archgeneric.intrenable;
+ }
+
+ /*
+ * Decide whether to use copy-on-reference (386 and mp).
+ * We get another chance to set it in mpinit() for a
+ * multiprocessor.
+ */
+ if(X86FAMILY(m->cpuidax) == 3)
+ conf.copymode = 1;
+
+ if(X86FAMILY(m->cpuidax) >= 4)
+ cmpswap = cmpswap486;
+
+ if(X86FAMILY(m->cpuidax) >= 5)
+ coherence = mb586;
+
+ if(m->cpuiddx & Sse2)
+ coherence = mfence;
+
+ addarchfile("cputype", 0444, cputyperead, nil);
+ addarchfile("archctl", 0664, archctlread, archctlwrite);
+}
+
+/*
+ * call either the pcmcia or pccard device setup
+ */
+int
+pcmspecial(char *idstr, ISAConf *isa)
+{
+ return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1;
+}
+
+/*
+ * call either the pcmcia or pccard device teardown
+ */
+void
+pcmspecialclose(int a)
+{
+ if (_pcmspecialclose != nil)
+ _pcmspecialclose(a);
+}
+
+/*
+ * return value and speed of timer set in arch->clockenable
+ */
+uvlong
+fastticks(uvlong *hz)
+{
+ return (*arch->fastclock)(hz);
+}
+
+ulong
+µs(void)
+{
+ return fastticks2us((*arch->fastclock)(nil));
+}
+
+/*
+ * set next timer interrupt
+ */
+void
+timerset(Tval x)
+{
+ if(doi8253set)
+ (*arch->timerset)(x);
+}
diff --git a/sys/src/9/pc/devether.c b/sys/src/9/pc/devether.c
new file mode 100755
index 000000000..d81c9ec48
--- /dev/null
+++ b/sys/src/9/pc/devether.c
@@ -0,0 +1,558 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "pool.h"
+#include "ureg.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+static Ether *etherxx[MaxEther];
+
+Chan*
+etherattach(char* spec)
+{
+ ulong ctlrno;
+ char *p;
+ Chan *chan;
+
+ ctlrno = 0;
+ if(spec && *spec){
+ ctlrno = strtoul(spec, &p, 0);
+ if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
+ error(Ebadarg);
+ }
+ if(etherxx[ctlrno] == 0)
+ error(Enodev);
+
+ chan = devattach('l', spec);
+ if(waserror()){
+ chanfree(chan);
+ nexterror();
+ }
+ chan->dev = ctlrno;
+ if(etherxx[ctlrno]->attach)
+ etherxx[ctlrno]->attach(etherxx[ctlrno]);
+ poperror();
+ return chan;
+}
+
+static Walkqid*
+etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
+{
+ return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
+}
+
+static int
+etherstat(Chan* chan, uchar* dp, int n)
+{
+ return netifstat(etherxx[chan->dev], chan, dp, n);
+}
+
+static Chan*
+etheropen(Chan* chan, int omode)
+{
+ return netifopen(etherxx[chan->dev], chan, omode);
+}
+
+static void
+ethercreate(Chan*, char*, int, ulong)
+{
+}
+
+static void
+etherclose(Chan* chan)
+{
+ netifclose(etherxx[chan->dev], chan);
+}
+
+static long
+etherread(Chan* chan, void* buf, long n, vlong off)
+{
+ Ether *ether;
+ ulong offset = off;
+
+ ether = etherxx[chan->dev];
+ if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
+ /*
+ * With some controllers it is necessary to reach
+ * into the chip to extract statistics.
+ */
+ if(NETTYPE(chan->qid.path) == Nifstatqid)
+ return ether->ifstat(ether, buf, n, offset);
+ else if(NETTYPE(chan->qid.path) == Nstatqid)
+ ether->ifstat(ether, buf, 0, offset);
+ }
+
+ return netifread(ether, chan, buf, n, offset);
+}
+
+static Block*
+etherbread(Chan* chan, long n, ulong offset)
+{
+ return netifbread(etherxx[chan->dev], chan, n, offset);
+}
+
+static int
+etherwstat(Chan* chan, uchar* dp, int n)
+{
+ return netifwstat(etherxx[chan->dev], chan, dp, n);
+}
+
+static void
+etherrtrace(Netfile* f, Etherpkt* pkt, int len)
+{
+ int i, n;
+ Block *bp;
+
+ if(qwindow(f->in) <= 0)
+ return;
+ if(len > 58)
+ n = 58;
+ else
+ n = len;
+ bp = iallocb(64);
+ if(bp == nil)
+ return;
+ memmove(bp->wp, pkt->d, n);
+ i = TK2MS(MACHP(0)->ticks);
+ bp->wp[58] = len>>8;
+ bp->wp[59] = len;
+ bp->wp[60] = i>>24;
+ bp->wp[61] = i>>16;
+ bp->wp[62] = i>>8;
+ bp->wp[63] = i;
+ bp->wp += 64;
+ qpass(f->in, bp);
+}
+
+Block*
+etheriq(Ether* ether, Block* bp, int fromwire)
+{
+ Etherpkt *pkt;
+ ushort type;
+ int len, multi, tome, fromme;
+ Netfile **ep, *f, **fp, *fx;
+ Block *xbp;
+
+ ether->inpackets++;
+
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ type = (pkt->type[0]<<8)|pkt->type[1];
+ fx = 0;
+ ep = &ether->f[Ntypes];
+
+ multi = pkt->d[0] & 1;
+ /* check for valid multicast addresses */
+ if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
+ if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
+ if(fromwire){
+ freeb(bp);
+ bp = 0;
+ }
+ return bp;
+ }
+ }
+
+ /* is it for me? */
+ tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
+ fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
+
+ /*
+ * Multiplex the packet to all the connections which want it.
+ * If the packet is not to be used subsequently (fromwire != 0),
+ * attempt to simply pass it into one of the connections, thereby
+ * saving a copy of the data (usual case hopefully).
+ */
+ for(fp = ether->f; fp < ep; fp++){
+ if(f = *fp)
+ if(f->type == type || f->type < 0)
+ if(tome || multi || f->prom){
+ /* Don't want to hear bridged packets */
+ if(f->bridge && !fromwire && !fromme)
+ continue;
+ if(!f->headersonly){
+ if(fromwire && fx == 0)
+ fx = f;
+ else if(xbp = iallocb(len)){
+ memmove(xbp->wp, pkt, len);
+ xbp->wp += len;
+ if(qpass(f->in, xbp) < 0) {
+ // print("soverflow for f->in\n");
+ ether->soverflows++;
+ }
+ }
+ else {
+ // print("soverflow iallocb\n");
+ ether->soverflows++;
+ }
+ }
+ else
+ etherrtrace(f, pkt, len);
+ }
+ }
+
+ if(fx){
+ if(qpass(fx->in, bp) < 0) {
+ // print("soverflow for fx->in\n");
+ ether->soverflows++;
+ }
+ return 0;
+ }
+ if(fromwire){
+ freeb(bp);
+ return 0;
+ }
+
+ return bp;
+}
+
+static int
+etheroq(Ether* ether, Block* bp)
+{
+ int len, loopback, s;
+ Etherpkt *pkt;
+
+ ether->outpackets++;
+
+ /*
+ * Check if the packet has to be placed back onto the input queue,
+ * i.e. if it's a loopback or broadcast packet or the interface is
+ * in promiscuous mode.
+ * If it's a loopback packet indicate to etheriq that the data isn't
+ * needed and return, etheriq will pass-on or free the block.
+ * To enable bridging to work, only packets that were originated
+ * by this interface are fed back.
+ */
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
+ if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
+ s = splhi();
+ etheriq(ether, bp, 0);
+ splx(s);
+ }
+
+ if(!loopback){
+ if(qfull(ether->oq))
+ print("etheroq: WARNING: ether->oq full!\n");
+ qbwrite(ether->oq, bp);
+ if(ether->transmit != nil)
+ ether->transmit(ether);
+ } else
+ freeb(bp);
+
+ return len;
+}
+
+static long
+etherwrite(Chan* chan, void* buf, long n, vlong)
+{
+ Ether *ether;
+ Block *bp;
+ int nn, onoff;
+ Cmdbuf *cb;
+
+ ether = etherxx[chan->dev];
+ if(NETTYPE(chan->qid.path) != Ndataqid) {
+ nn = netifwrite(ether, chan, buf, n);
+ if(nn >= 0)
+ return nn;
+ cb = parsecmd(buf, n);
+ if(cb->f[0] && strcmp(cb->f[0], "nonblocking") == 0){
+ if(cb->nf <= 1)
+ onoff = 1;
+ else
+ onoff = atoi(cb->f[1]);
+ qnoblock(ether->oq, onoff);
+ free(cb);
+ return n;
+ }
+ free(cb);
+ if(ether->ctl!=nil)
+ return ether->ctl(ether,buf,n);
+
+ error(Ebadctl);
+ }
+
+ if(n > ether->maxmtu)
+ error(Etoobig);
+ if(n < ether->minmtu)
+ error(Etoosmall);
+
+ bp = allocb(n);
+ if(waserror()){
+ freeb(bp);
+ nexterror();
+ }
+ memmove(bp->rp, buf, n);
+ memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
+ poperror();
+ bp->wp += n;
+
+ return etheroq(ether, bp);
+}
+
+static long
+etherbwrite(Chan* chan, Block* bp, ulong)
+{
+ Ether *ether;
+ long n;
+
+ n = BLEN(bp);
+ if(NETTYPE(chan->qid.path) != Ndataqid){
+ if(waserror()) {
+ freeb(bp);
+ nexterror();
+ }
+ n = etherwrite(chan, bp->rp, n, 0);
+ poperror();
+ freeb(bp);
+ return n;
+ }
+ ether = etherxx[chan->dev];
+
+ if(n > ether->maxmtu){
+ freeb(bp);
+ error(Etoobig);
+ }
+ if(n < ether->minmtu){
+ freeb(bp);
+ error(Etoosmall);
+ }
+
+ return etheroq(ether, bp);
+}
+
+static struct {
+ char* type;
+ int (*reset)(Ether*);
+} cards[MaxEther+1];
+
+void
+addethercard(char* t, int (*r)(Ether*))
+{
+ static int ncard;
+
+ if(ncard == MaxEther)
+ panic("too many ether cards");
+ cards[ncard].type = t;
+ cards[ncard].reset = r;
+ ncard++;
+}
+
+int
+parseether(uchar *to, char *from)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ for(i = 0; i < Eaddrlen; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+static Ether*
+etherprobe(int cardno, int ctlrno)
+{
+ int i, lg;
+ ulong mb, bsz;
+ Ether *ether;
+ char buf[128], name[32];
+
+ ether = malloc(sizeof(Ether));
+ memset(ether, 0, sizeof(Ether));
+ ether->ctlrno = ctlrno;
+ ether->tbdf = BUSUNKNOWN;
+ ether->mbps = 10;
+ ether->minmtu = ETHERMINTU;
+ ether->maxmtu = ETHERMAXTU;
+
+ if(cardno < 0){
+ if(isaconfig("ether", ctlrno, ether) == 0){
+ free(ether);
+ return nil;
+ }
+ for(cardno = 0; cards[cardno].type; cardno++){
+ if(cistrcmp(cards[cardno].type, ether->type))
+ continue;
+ for(i = 0; i < ether->nopt; i++){
+ if(strncmp(ether->opt[i], "ea=", 3))
+ continue;
+ if(parseether(ether->ea, &ether->opt[i][3]))
+ memset(ether->ea, 0, Eaddrlen);
+ }
+ break;
+ }
+ }
+
+ if(cardno >= MaxEther || cards[cardno].type == nil){
+ free(ether);
+ return nil;
+ }
+ if(cards[cardno].reset(ether) < 0){
+ free(ether);
+ return nil;
+ }
+
+ /*
+ * IRQ2 doesn't really exist, it's used to gang the interrupt
+ * controllers together. A device set to IRQ2 will appear on
+ * the second interrupt controller as IRQ9.
+ */
+ if(ether->irq == 2)
+ ether->irq = 9;
+ snprint(name, sizeof(name), "ether%d", ctlrno);
+
+ /*
+ * If ether->irq is <0, it is a hack to indicate no interrupt
+ * used by ethersink.
+ */
+ if(ether->irq >= 0)
+ intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);
+
+ 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", 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",
+ ether->ea[0], ether->ea[1], ether->ea[2],
+ ether->ea[3], ether->ea[4], ether->ea[5]);
+ sprint(buf+i, "\n");
+ print(buf);
+
+ /* compute log10(ether->mbps) into lg */
+ for(lg = 0, mb = ether->mbps; mb >= 10; lg++)
+ mb /= 10;
+ if (lg > 0)
+ lg--;
+ if (lg > 14) /* 2^(14+17) = 2⁳ⁱ */
+ lg = 14;
+ /* allocate larger output queues for higher-speed interfaces */
+ bsz = 1UL << (lg + 17); /* 2ⁱ⁷ = 128K, bsz = 2ⁿ × 128K */
+ while (bsz > mainmem->maxsize / 8 && bsz > 128*1024)
+ bsz /= 2;
+
+ netifinit(ether, name, Ntypes, bsz);
+ if(ether->oq == nil) {
+ ether->oq = qopen(bsz, Qmsg, 0, 0);
+ ether->limit = bsz;
+ }
+ if(ether->oq == nil)
+ panic("etherreset %s: can't allocate output queue of %ld bytes",
+ name, bsz);
+ ether->alen = Eaddrlen;
+ memmove(ether->addr, ether->ea, Eaddrlen);
+ memset(ether->bcast, 0xFF, Eaddrlen);
+
+ return ether;
+}
+
+static void
+etherreset(void)
+{
+ Ether *ether;
+ int cardno, ctlrno;
+
+ for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+ if((ether = etherprobe(-1, ctlrno)) == nil)
+ continue;
+ etherxx[ctlrno] = ether;
+ }
+
+ if(getconf("*noetherprobe"))
+ return;
+
+ cardno = ctlrno = 0;
+ while(cards[cardno].type != nil && ctlrno < MaxEther){
+ if(etherxx[ctlrno] != nil){
+ ctlrno++;
+ continue;
+ }
+ if((ether = etherprobe(cardno, ctlrno)) == nil){
+ cardno++;
+ continue;
+ }
+ etherxx[ctlrno] = ether;
+ ctlrno++;
+ }
+}
+
+static void
+ethershutdown(void)
+{
+ Ether *ether;
+ int i;
+
+ for(i = 0; i < MaxEther; i++){
+ ether = etherxx[i];
+ if(ether == nil)
+ continue;
+ if(ether->shutdown == nil) {
+ print("#l%d: no shutdown fuction\n", i);
+ continue;
+ }
+ (*ether->shutdown)(ether);
+ }
+}
+
+
+#define POLY 0xedb88320
+
+/* really slow 32 bit crc for ethers */
+ulong
+ethercrc(uchar *p, int len)
+{
+ int i, j;
+ ulong crc, b;
+
+ crc = 0xffffffff;
+ for(i = 0; i < len; i++){
+ b = *p++;
+ for(j = 0; j < 8; j++){
+ crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
+ b >>= 1;
+ }
+ }
+ return crc;
+}
+
+Dev etherdevtab = {
+ 'l',
+ "ether",
+
+ etherreset,
+ devinit,
+ ethershutdown,
+ etherattach,
+ etherwalk,
+ etherstat,
+ etheropen,
+ ethercreate,
+ etherclose,
+ etherread,
+ etherbread,
+ etherwrite,
+ etherbwrite,
+ devremove,
+ etherwstat,
+};
diff --git a/sys/src/9/pc/devfloppy.c b/sys/src/9/pc/devfloppy.c
new file mode 100755
index 000000000..4a85fa63d
--- /dev/null
+++ b/sys/src/9/pc/devfloppy.c
@@ -0,0 +1,1087 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#include "floppy.h"
+
+/* Intel 82077A (8272A compatible) floppy controller */
+
+/* This module expects the following functions to be defined
+ * elsewhere:
+ *
+ * inb()
+ * outb()
+ * floppyexec()
+ * floppyeject()
+ * floppysetup0()
+ * floppysetup1()
+ * dmainit()
+ * dmasetup()
+ * dmaend()
+ *
+ * On DMA systems, floppyexec() should be an empty function;
+ * on non-DMA systems, dmaend() should be an empty function;
+ * dmasetup() may enforce maximum transfer sizes.
+ */
+
+enum {
+ /* file types */
+ Qdir= 0,
+ Qdata= (1<<2),
+ Qctl= (2<<2),
+ Qmask= (3<<2),
+
+ DMAchan= 2, /* floppy dma channel */
+};
+
+#define DPRINT if(floppydebug)print
+int floppydebug = 0;
+
+/*
+ * types of drive (from PC equipment byte)
+ */
+enum
+{
+ Tnone= 0,
+ T360kb= 1,
+ T1200kb= 2,
+ T720kb= 3,
+ T1440kb= 4,
+};
+
+FType floppytype[] =
+{
+ { "3½HD", T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54, 0, },
+ { "3½DD", T1440kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
+ { "3½DD", T720kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
+ { "5¼HD", T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, },
+ { "5¼DD", T1200kb, 512, 9, 2, 2, 40, 0x2A, 0x50, 1, },
+ { "ATT3B1", T1200kb, 512, 8, 2, 2, 48, 0x2A, 0x50, 1, },
+ { "5¼DD", T360kb, 512, 9, 2, 1, 40, 0x2A, 0x50, 2, },
+};
+
+/*
+ * bytes per sector encoding for the controller.
+ * - index for b2c is is (bytes per sector/128).
+ * - index for c2b is code from b2c
+ */
+static int b2c[] =
+{
+[1] 0,
+[2] 1,
+[4] 2,
+[8] 3,
+};
+static int c2b[] =
+{
+ 128,
+ 256,
+ 512,
+ 1024,
+};
+
+FController fl;
+
+#define MOTORBIT(i) (1<<((i)+4))
+
+/*
+ * predeclared
+ */
+static int cmddone(void*);
+static void floppyformat(FDrive*, Cmdbuf*);
+static void floppykproc(void*);
+static void floppypos(FDrive*,long);
+static int floppyrecal(FDrive*);
+static int floppyresult(void);
+static void floppyrevive(void);
+static long floppyseek(FDrive*, long);
+static int floppysense(void);
+static void floppywait(int);
+static long floppyxfer(FDrive*, int, void*, long, long);
+
+Dirtab floppydir[]={
+ ".", {Qdir, 0, QTDIR}, 0, 0550,
+ "fd0disk", {Qdata + 0}, 0, 0660,
+ "fd0ctl", {Qctl + 0}, 0, 0660,
+ "fd1disk", {Qdata + 1}, 0, 0660,
+ "fd1ctl", {Qctl + 1}, 0, 0660,
+ "fd2disk", {Qdata + 2}, 0, 0660,
+ "fd2ctl", {Qctl + 2}, 0, 0660,
+ "fd3disk", {Qdata + 3}, 0, 0660,
+ "fd3ctl", {Qctl + 3}, 0, 0660,
+};
+#define NFDIR 2 /* directory entries/drive */
+
+enum
+{
+ CMdebug,
+ CMnodebug,
+ CMeject,
+ CMformat,
+ CMreset,
+};
+
+static Cmdtab floppyctlmsg[] =
+{
+ CMdebug, "debug", 1,
+ CMnodebug, "nodebug", 1,
+ CMeject, "eject", 1,
+ CMformat, "format", 0,
+ CMreset, "reset", 1,
+};
+
+static void
+fldump(void)
+{
+ DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb),
+ inb(Pdor), inb(Pmsr), inb(Pdir));
+}
+
+/*
+ * set floppy drive to its default type
+ */
+static void
+floppysetdef(FDrive *dp)
+{
+ FType *t;
+
+ for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++)
+ if(dp->dt == t->dt){
+ dp->t = t;
+ floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
+ break;
+ }
+}
+
+static void
+floppyreset(void)
+{
+ FDrive *dp;
+ FType *t;
+ ulong maxtsize;
+
+ floppysetup0(&fl);
+ if(fl.ndrive == 0)
+ return;
+
+ /*
+ * init dependent parameters
+ */
+ maxtsize = 0;
+ for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
+ t->cap = t->bytes * t->heads * t->sectors * t->tracks;
+ t->bcode = b2c[t->bytes/128];
+ t->tsize = t->bytes * t->sectors;
+ if(maxtsize < t->tsize)
+ maxtsize = t->tsize;
+ }
+
+ /*
+ * Should check if this fails. Can do so
+ * if there is no space <= 16MB for the DMA
+ * bounce buffer.
+ */
+ dmainit(DMAchan, maxtsize);
+
+ /*
+ * allocate the drive storage
+ */
+ fl.d = xalloc(fl.ndrive*sizeof(FDrive));
+ fl.selected = fl.d;
+
+ /*
+ * stop the motors
+ */
+ fl.motor = 0;
+ delay(10);
+ outb(Pdor, fl.motor | Fintena | Fena);
+ delay(10);
+
+ /*
+ * init drives
+ */
+ for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
+ dp->dev = dp - fl.d;
+ dp->dt = T1440kb;
+ floppysetdef(dp);
+ dp->cyl = -1; /* because we don't know */
+ dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024);
+ dp->ccyl = -1;
+ dp->vers = 0;
+ }
+
+ /*
+ * first operation will recalibrate
+ */
+ fl.confused = 1;
+
+ floppysetup1(&fl);
+}
+
+static Chan*
+floppyattach(char *spec)
+{
+ static int kstarted;
+
+ if(fl.ndrive == 0)
+ error(Enodev);
+
+ if(kstarted == 0){
+ /*
+ * watchdog to turn off the motors
+ */
+ kstarted = 1;
+ kproc("floppy", floppykproc, 0);
+ }
+ return devattach('f', spec);
+}
+
+static Walkqid*
+floppywalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, floppydir, 1+fl.ndrive*NFDIR, devgen);
+}
+
+static int
+floppystat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, floppydir, 1+fl.ndrive*NFDIR, devgen);
+}
+
+static Chan*
+floppyopen(Chan *c, int omode)
+{
+ return devopen(c, omode, floppydir, 1+fl.ndrive*NFDIR, devgen);
+}
+
+static void
+floppyclose(Chan *)
+{
+}
+
+static void
+islegal(ulong offset, long n, FDrive *dp)
+{
+ if(offset % dp->t->bytes)
+ error(Ebadarg);
+ if(n % dp->t->bytes)
+ error(Ebadarg);
+}
+
+/*
+ * check if the floppy has been replaced under foot. cause
+ * an error if it has.
+ *
+ * a seek and a read clears the condition. this was determined
+ * experimentally, there has to be a better way.
+ *
+ * if the read fails, cycle through the possible floppy
+ * density till one works or we've cycled through all
+ * possibilities for this drive.
+ */
+static void
+changed(Chan *c, FDrive *dp)
+{
+ ulong old;
+ FType *start;
+
+ /*
+ * if floppy has changed or first time through
+ */
+ if((inb(Pdir)&Fchange) || dp->vers == 0){
+ DPRINT("changed\n");
+ fldump();
+ dp->vers++;
+ start = dp->t;
+ dp->maxtries = 3; /* limit it when we're probing */
+
+ /* floppyon will fail if there's a controller but no drive */
+ dp->confused = 1; /* make floppyon recal */
+ if(floppyon(dp) < 0)
+ error(Eio);
+
+ /* seek to the first track */
+ floppyseek(dp, dp->t->heads*dp->t->tsize);
+ while(waserror()){
+ /*
+ * if first attempt doesn't reset changed bit, there's
+ * no floppy there
+ */
+ if(inb(Pdir)&Fchange)
+ nexterror();
+
+ while(++dp->t){
+ if(dp->t == &floppytype[nelem(floppytype)])
+ dp->t = floppytype;
+ if(dp->dt == dp->t->dt)
+ break;
+ }
+ floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
+
+ /* floppyon will fail if there's a controller but no drive */
+ if(floppyon(dp) < 0)
+ error(Eio);
+
+ DPRINT("changed: trying %s\n", dp->t->name);
+ fldump();
+ if(dp->t == start)
+ nexterror();
+ }
+
+ /* if the read succeeds, we've got the density right */
+ floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize);
+ poperror();
+ dp->maxtries = 20;
+ }
+
+ old = c->qid.vers;
+ c->qid.vers = dp->vers;
+ if(old && old != dp->vers)
+ error(Eio);
+}
+
+static int
+readtrack(FDrive *dp, int cyl, int head)
+{
+ int i, nn, sofar;
+ ulong pos;
+
+ nn = dp->t->tsize;
+ if(dp->ccyl==cyl && dp->chead==head)
+ return nn;
+ pos = (cyl*dp->t->heads+head) * nn;
+ for(sofar = 0; sofar < nn; sofar += i){
+ dp->ccyl = -1;
+ i = floppyxfer(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar);
+ if(i <= 0)
+ return -1;
+ }
+ dp->ccyl = cyl;
+ dp->chead = head;
+ return nn;
+}
+
+static long
+floppyread(Chan *c, void *a, long n, vlong off)
+{
+ FDrive *dp;
+ long rv;
+ int sec, head, cyl;
+ long len;
+ uchar *aa;
+ ulong offset = off;
+
+ if(c->qid.type & QTDIR)
+ return devdirread(c, a, n, floppydir, 1+fl.ndrive*NFDIR, devgen);
+
+ rv = 0;
+ dp = &fl.d[c->qid.path & ~Qmask];
+ switch ((int)(c->qid.path & Qmask)) {
+ case Qdata:
+ islegal(offset, n, dp);
+ aa = a;
+
+ qlock(&fl);
+ if(waserror()){
+ qunlock(&fl);
+ nexterror();
+ }
+ floppyon(dp);
+ changed(c, dp);
+ for(rv = 0; rv < n; rv += len){
+ /*
+ * all xfers come out of the track cache
+ */
+ dp->len = n - rv;
+ floppypos(dp, offset+rv);
+ cyl = dp->tcyl;
+ head = dp->thead;
+ len = dp->len;
+ sec = dp->tsec;
+ if(readtrack(dp, cyl, head) < 0)
+ break;
+ memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len);
+ }
+ qunlock(&fl);
+ poperror();
+
+ break;
+ case Qctl:
+ return readstr(offset, a, n, dp->t->name);
+ default:
+ panic("floppyread: bad qid");
+ }
+
+ return rv;
+}
+
+static long
+floppywrite(Chan *c, void *a, long n, vlong off)
+{
+ FDrive *dp;
+ long rv, i;
+ char *aa = a;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ ulong offset = off;
+
+ rv = 0;
+ dp = &fl.d[c->qid.path & ~Qmask];
+ switch ((int)(c->qid.path & Qmask)) {
+ case Qdata:
+ islegal(offset, n, dp);
+ qlock(&fl);
+ if(waserror()){
+ qunlock(&fl);
+ nexterror();
+ }
+ floppyon(dp);
+ changed(c, dp);
+ for(rv = 0; rv < n; rv += i){
+ floppypos(dp, offset+rv);
+ if(dp->tcyl == dp->ccyl)
+ dp->ccyl = -1;
+ i = floppyxfer(dp, Fwrite, aa+rv, offset+rv, n-rv);
+ if(i < 0)
+ break;
+ if(i == 0)
+ error(Eio);
+ }
+ qunlock(&fl);
+ poperror();
+ break;
+ case Qctl:
+ rv = n;
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ qlock(&fl);
+ if(waserror()){
+ qunlock(&fl);
+ nexterror();
+ }
+ ct = lookupcmd(cb, floppyctlmsg, nelem(floppyctlmsg));
+ switch(ct->index){
+ case CMeject:
+ floppyeject(dp);
+ break;
+ case CMformat:
+ floppyformat(dp, cb);
+ break;
+ case CMreset:
+ fl.confused = 1;
+ floppyon(dp);
+ break;
+ case CMdebug:
+ floppydebug = 1;
+ break;
+ case CMnodebug:
+ floppydebug = 0;
+ break;
+ }
+ poperror();
+ qunlock(&fl);
+ poperror();
+ free(cb);
+ break;
+ default:
+ panic("floppywrite: bad qid");
+ }
+
+ return rv;
+}
+
+static void
+floppykproc(void *)
+{
+ FDrive *dp;
+
+ while(waserror())
+ ;
+ for(;;){
+ for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
+ if((fl.motor&MOTORBIT(dp->dev))
+ && TK2SEC(m->ticks - dp->lasttouched) > 5
+ && canqlock(&fl)){
+ if(TK2SEC(m->ticks - dp->lasttouched) > 5)
+ floppyoff(dp);
+ qunlock(&fl);
+ }
+ }
+ tsleep(&up->sleep, return0, 0, 1000);
+ }
+}
+
+/*
+ * start a floppy drive's motor.
+ */
+static int
+floppyon(FDrive *dp)
+{
+ int alreadyon;
+ int tries;
+
+ if(fl.confused)
+ floppyrevive();
+
+ /* start motor and select drive */
+ alreadyon = fl.motor & MOTORBIT(dp->dev);
+ fl.motor |= MOTORBIT(dp->dev);
+ outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
+ if(!alreadyon){
+ /* wait for drive to spin up */
+ tsleep(&up->sleep, return0, 0, 750);
+
+ /* clear any pending interrupts */
+ floppysense();
+ }
+
+ /* set transfer rate */
+ if(fl.rate != dp->t->rate){
+ fl.rate = dp->t->rate;
+ outb(Pdsr, fl.rate);
+ }
+
+ /* get drive to a known cylinder */
+ if(dp->confused)
+ for(tries = 0; tries < 4; tries++)
+ if(floppyrecal(dp) >= 0)
+ break;
+ dp->lasttouched = m->ticks;
+ fl.selected = dp;
+
+ /* return -1 if this didn't work */
+ if(dp->confused)
+ return -1;
+ return 0;
+}
+
+/*
+ * stop the floppy if it hasn't been used in 5 seconds
+ */
+static void
+floppyoff(FDrive *dp)
+{
+ fl.motor &= ~MOTORBIT(dp->dev);
+ outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
+}
+
+/*
+ * send a command to the floppy
+ */
+static int
+floppycmd(void)
+{
+ int i;
+ int tries;
+
+ fl.nstat = 0;
+ for(i = 0; i < fl.ncmd; i++){
+ for(tries = 0; ; tries++){
+ if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
+ break;
+ if(tries > 1000){
+ DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);
+ fldump();
+
+ /* empty fifo, might have been a bad command */
+ floppyresult();
+ return -1;
+ }
+ microdelay(8); /* for machine independence */
+ }
+ outb(Pfdata, fl.cmd[i]);
+ }
+ return 0;
+}
+
+/*
+ * get a command result from the floppy
+ *
+ * when the controller goes ready waiting for a command
+ * (instead of sending results), we're done
+ *
+ */
+static int
+floppyresult(void)
+{
+ int i, s;
+ int tries;
+
+ /* get the result of the operation */
+ for(i = 0; i < sizeof(fl.stat); i++){
+ /* wait for status byte */
+ for(tries = 0; ; tries++){
+ s = inb(Pmsr)&(Ffrom|Fready);
+ if(s == Fready){
+ fl.nstat = i;
+ return fl.nstat;
+ }
+ if(s == (Ffrom|Fready))
+ break;
+ if(tries > 1000){
+ DPRINT("floppyresult: %d stats\n", i);
+ fldump();
+ fl.confused = 1;
+ return -1;
+ }
+ microdelay(8); /* for machine independence */
+ }
+ fl.stat[i] = inb(Pfdata);
+ }
+ fl.nstat = sizeof(fl.stat);
+ return fl.nstat;
+}
+
+/*
+ * calculate physical address of a logical byte offset into the disk
+ *
+ * truncate dp->length if it crosses a track boundary
+ */
+static void
+floppypos(FDrive *dp, long off)
+{
+ int lsec;
+ int ltrack;
+ int end;
+
+ lsec = off/dp->t->bytes;
+ ltrack = lsec/dp->t->sectors;
+ dp->tcyl = ltrack/dp->t->heads;
+ dp->tsec = (lsec % dp->t->sectors) + 1;
+ dp->thead = (lsec/dp->t->sectors) % dp->t->heads;
+
+ /*
+ * can't read across track boundaries.
+ * if so, decrement the bytes to be read.
+ */
+ end = (ltrack+1)*dp->t->sectors*dp->t->bytes;
+ if(off+dp->len > end)
+ dp->len = end - off;
+}
+
+/*
+ * get the interrupt cause from the floppy.
+ */
+static int
+floppysense(void)
+{
+ fl.ncmd = 0;
+ fl.cmd[fl.ncmd++] = Fsense;
+ if(floppycmd() < 0)
+ return -1;
+ if(floppyresult() < 2){
+ DPRINT("can't read sense response\n");
+ fldump();
+ fl.confused = 1;
+ return -1;
+ }
+ return 0;
+}
+
+static int
+cmddone(void *)
+{
+ return fl.ncmd == 0;
+}
+
+/*
+ * Wait for a floppy interrupt. If none occurs in 5 seconds, we
+ * may have missed one. This only happens on some portables which
+ * do power management behind our backs. Call the interrupt
+ * routine to try to clear any conditions.
+ */
+static void
+floppywait(int slow)
+{
+ tsleep(&fl.r, cmddone, 0, slow ? 5000 : 1000);
+ if(!cmddone(0)){
+ floppyintr(0);
+ fl.confused = 1;
+ }
+}
+
+/*
+ * we've lost the floppy position, go to cylinder 0.
+ */
+static int
+floppyrecal(FDrive *dp)
+{
+ dp->ccyl = -1;
+ dp->cyl = -1;
+
+ fl.ncmd = 0;
+ fl.cmd[fl.ncmd++] = Frecal;
+ fl.cmd[fl.ncmd++] = dp->dev;
+ if(floppycmd() < 0)
+ return -1;
+ floppywait(1);
+ if(fl.nstat < 2){
+ DPRINT("recalibrate: confused %ux\n", inb(Pmsr));
+ fl.confused = 1;
+ return -1;
+ }
+ if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
+ DPRINT("recalibrate: failed\n");
+ dp->confused = 1;
+ return -1;
+ }
+ dp->cyl = fl.stat[1];
+ if(dp->cyl != 0){
+ DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl);
+ dp->cyl = -1;
+ dp->confused = 1;
+ return -1;
+ }
+
+ dp->confused = 0;
+ return 0;
+}
+
+/*
+ * if the controller or a specific drive is in a confused state,
+ * reset it and get back to a known state
+ */
+static void
+floppyrevive(void)
+{
+ FDrive *dp;
+
+ /*
+ * reset the controller if it's confused
+ */
+ if(fl.confused){
+ DPRINT("floppyrevive in\n");
+ fldump();
+
+ /* reset controller and turn all motors off */
+ splhi();
+ fl.ncmd = 1;
+ fl.cmd[0] = 0;
+ outb(Pdor, 0);
+ delay(10);
+ outb(Pdor, Fintena|Fena);
+ delay(10);
+ spllo();
+ fl.motor = 0;
+ fl.confused = 0;
+ floppywait(0);
+
+ /* mark all drives in an unknown state */
+ for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)
+ dp->confused = 1;
+
+ /* set rate to a known value */
+ outb(Pdsr, 0);
+ fl.rate = 0;
+
+ DPRINT("floppyrevive out\n");
+ fldump();
+ }
+}
+
+/*
+ * seek to the target cylinder
+ *
+ * interrupt, no results
+ */
+static long
+floppyseek(FDrive *dp, long off)
+{
+ floppypos(dp, off);
+ if(dp->cyl == dp->tcyl)
+ return dp->tcyl;
+ dp->cyl = -1;
+
+ fl.ncmd = 0;
+ fl.cmd[fl.ncmd++] = Fseek;
+ fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
+ fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
+ if(floppycmd() < 0)
+ return -1;
+ floppywait(1);
+ if(fl.nstat < 2){
+ DPRINT("seek: confused\n");
+ fl.confused = 1;
+ return -1;
+ }
+ if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
+ DPRINT("seek: failed\n");
+ dp->confused = 1;
+ return -1;
+ }
+
+ dp->cyl = dp->tcyl;
+ return dp->tcyl;
+}
+
+/*
+ * read or write to floppy. try up to three times.
+ */
+static long
+floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
+{
+ long offset;
+ int tries;
+
+ if(off >= dp->t->cap)
+ return 0;
+ if(off + n > dp->t->cap)
+ n = dp->t->cap - off;
+
+ /* retry on error (until it gets ridiculous) */
+ tries = 0;
+ while(waserror()){
+ if(tries++ >= dp->maxtries)
+ nexterror();
+ DPRINT("floppyxfer: retrying\n");
+ }
+
+ dp->len = n;
+ if(floppyseek(dp, off) < 0){
+ DPRINT("xfer: seek failed\n");
+ dp->confused = 1;
+ error(Eio);
+ }
+
+ /*
+ * set up the dma (dp->len may be trimmed)
+ */
+ if(waserror()){
+ dmaend(DMAchan);
+ nexterror();
+ }
+ dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
+ if(dp->len < 0)
+ error(Eio);
+
+ /*
+ * start operation
+ */
+ fl.ncmd = 0;
+ fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0);
+ fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
+ fl.cmd[fl.ncmd++] = dp->tcyl;
+ fl.cmd[fl.ncmd++] = dp->thead;
+ fl.cmd[fl.ncmd++] = dp->tsec;
+ fl.cmd[fl.ncmd++] = dp->t->bcode;
+ fl.cmd[fl.ncmd++] = dp->t->sectors;
+ fl.cmd[fl.ncmd++] = dp->t->gpl;
+ fl.cmd[fl.ncmd++] = 0xFF;
+ if(floppycmd() < 0)
+ error(Eio);
+
+ /* Poll ready bits and transfer data */
+ floppyexec((char*)a, dp->len, cmd==Fread);
+
+ /*
+ * give bus to DMA, floppyintr() will read result
+ */
+ floppywait(0);
+ dmaend(DMAchan);
+ poperror();
+
+ /*
+ * check for errors
+ */
+ if(fl.nstat < 7){
+ DPRINT("xfer: confused\n");
+ fl.confused = 1;
+ error(Eio);
+ }
+ if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
+ DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0],
+ fl.stat[1], fl.stat[2]);
+ DPRINT("offset %lud len %ld\n", off, dp->len);
+ if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){
+ DPRINT("DMA overrun: retry\n");
+ } else
+ dp->confused = 1;
+ error(Eio);
+ }
+
+ /*
+ * check for correct cylinder
+ */
+ offset = fl.stat[3] * dp->t->heads + fl.stat[4];
+ offset = offset*dp->t->sectors + fl.stat[5] - 1;
+ offset = offset * c2b[fl.stat[6]];
+ if(offset != off+dp->len){
+ DPRINT("xfer: ends on wrong cyl\n");
+ dp->confused = 1;
+ error(Eio);
+ }
+ poperror();
+
+ dp->lasttouched = m->ticks;
+ return dp->len;
+}
+
+/*
+ * format a track
+ */
+static void
+floppyformat(FDrive *dp, Cmdbuf *cb)
+{
+ int cyl, h, sec;
+ ulong track;
+ uchar *buf, *bp;
+ FType *t;
+
+ /*
+ * set the type
+ */
+ if(cb->nf == 2){
+ for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
+ if(strcmp(cb->f[1], t->name)==0 && t->dt==dp->dt){
+ dp->t = t;
+ floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
+ break;
+ }
+ }
+ if(t >= &floppytype[nelem(floppytype)])
+ error(Ebadarg);
+ } else if(cb->nf == 1){
+ floppysetdef(dp);
+ t = dp->t;
+ } else {
+ cmderror(cb, "invalid floppy format command");
+ SET(t);
+ }
+
+ /*
+ * buffer for per track info
+ */
+ buf = smalloc(t->sectors*4);
+ if(waserror()){
+ free(buf);
+ nexterror();
+ }
+
+ /* force a recalibrate to cylinder 0 */
+ dp->confused = 1;
+ if(!waserror()){
+ floppyon(dp);
+ poperror();
+ }
+
+ /*
+ * format a track at time
+ */
+ for(track = 0; track < t->tracks*t->heads; track++){
+ cyl = track/t->heads;
+ h = track % t->heads;
+
+ /*
+ * seek to track, ignore errors
+ */
+ floppyseek(dp, track*t->tsize);
+ dp->cyl = cyl;
+ dp->confused = 0;
+
+ /*
+ * set up the dma (dp->len may be trimmed)
+ */
+ bp = buf;
+ for(sec = 1; sec <= t->sectors; sec++){
+ *bp++ = cyl;
+ *bp++ = h;
+ *bp++ = sec;
+ *bp++ = t->bcode;
+ }
+ if(waserror()){
+ dmaend(DMAchan);
+ nexterror();
+ }
+ if(dmasetup(DMAchan, buf, bp-buf, 0) < 0)
+ error(Eio);
+
+ /*
+ * start operation
+ */
+ fl.ncmd = 0;
+ fl.cmd[fl.ncmd++] = Fformat;
+ fl.cmd[fl.ncmd++] = (h<<2) | dp->dev;
+ fl.cmd[fl.ncmd++] = t->bcode;
+ fl.cmd[fl.ncmd++] = t->sectors;
+ fl.cmd[fl.ncmd++] = t->fgpl;
+ fl.cmd[fl.ncmd++] = 0x5a;
+ if(floppycmd() < 0)
+ error(Eio);
+
+ /* Poll ready bits and transfer data */
+ floppyexec((char *)buf, bp-buf, 0);
+
+ /*
+ * give bus to DMA, floppyintr() will read result
+ */
+ floppywait(1);
+ dmaend(DMAchan);
+ poperror();
+
+ /*
+ * check for errors
+ */
+ if(fl.nstat < 7){
+ DPRINT("format: confused\n");
+ fl.confused = 1;
+ error(Eio);
+ }
+ if((fl.stat[0]&Codemask)!=0 || fl.stat[1]|| fl.stat[2]){
+ DPRINT("format: failed %ux %ux %ux\n",
+ fl.stat[0], fl.stat[1], fl.stat[2]);
+ dp->confused = 1;
+ error(Eio);
+ }
+ }
+ free(buf);
+ dp->confused = 1;
+ poperror();
+}
+
+static void
+floppyintr(Ureg *)
+{
+ switch(fl.cmd[0]&~Fmulti){
+ case Fread:
+ case Fwrite:
+ case Fformat:
+ case Fdumpreg:
+ floppyresult();
+ break;
+ case Fseek:
+ case Frecal:
+ default:
+ floppysense(); /* to clear interrupt */
+ break;
+ }
+ fl.ncmd = 0;
+ wakeup(&fl.r);
+}
+
+Dev floppydevtab = {
+ 'f',
+ "floppy",
+
+ floppyreset,
+ devinit,
+ devshutdown,
+ floppyattach,
+ floppywalk,
+ floppystat,
+ floppyopen,
+ devcreate,
+ floppyclose,
+ floppyread,
+ devbread,
+ floppywrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/pc/devi82365.c b/sys/src/9/pc/devi82365.c
new file mode 100755
index 000000000..6a34e19be
--- /dev/null
+++ b/sys/src/9/pc/devi82365.c
@@ -0,0 +1,1044 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+/*
+ * Intel 82365SL PCIC controller and compatibles.
+ */
+enum
+{
+ /*
+ * registers indices
+ */
+ Rid= 0x0, /* identification and revision */
+ Ris= 0x1, /* interface status */
+ Rpc= 0x2, /* power control */
+ Foutena= (1<<7), /* output enable */
+ Fautopower= (1<<5), /* automatic power switching */
+ Fcardena= (1<<4), /* PC card enable */
+ Rigc= 0x3, /* interrupt and general control */
+ Fiocard= (1<<5), /* I/O card (vs memory) */
+ Fnotreset= (1<<6), /* reset if not set */
+ FSMIena= (1<<4), /* enable change interrupt on SMI */
+ Rcsc= 0x4, /* card status change */
+ Rcscic= 0x5, /* card status change interrupt config */
+ Fchangeena= (1<<3), /* card changed */
+ Fbwarnena= (1<<1), /* card battery warning */
+ Fbdeadena= (1<<0), /* card battery dead */
+ Rwe= 0x6, /* address window enable */
+ Fmem16= (1<<5), /* use A23-A12 to decode address */
+ Rio= 0x7, /* I/O control */
+ Fwidth16= (1<<0), /* 16 bit data width */
+ Fiocs16= (1<<1), /* IOCS16 determines data width */
+ Fzerows= (1<<2), /* zero wait state */
+ Ftiming= (1<<3), /* timing register to use */
+ Riobtm0lo= 0x8, /* I/O address 0 start low byte */
+ Riobtm0hi= 0x9, /* I/O address 0 start high byte */
+ Riotop0lo= 0xa, /* I/O address 0 stop low byte */
+ Riotop0hi= 0xb, /* I/O address 0 stop high byte */
+ Riobtm1lo= 0xc, /* I/O address 1 start low byte */
+ Riobtm1hi= 0xd, /* I/O address 1 start high byte */
+ Riotop1lo= 0xe, /* I/O address 1 stop low byte */
+ Riotop1hi= 0xf, /* I/O address 1 stop high byte */
+ Rmap= 0x10, /* map 0 */
+
+ /*
+ * CL-PD67xx extension registers
+ */
+ Rmisc1= 0x16, /* misc control 1 */
+ F5Vdetect= (1<<0),
+ Fvcc3V= (1<<1),
+ Fpmint= (1<<2),
+ Fpsirq= (1<<3),
+ Fspeaker= (1<<4),
+ Finpack= (1<<7),
+ Rfifo= 0x17, /* fifo control */
+ Fflush= (1<<7), /* flush fifo */
+ Rmisc2= 0x1E, /* misc control 2 */
+ Flowpow= (1<<1), /* low power mode */
+ Rchipinfo= 0x1F, /* chip information */
+ Ratactl= 0x26, /* ATA control */
+
+ /*
+ * offsets into the system memory address maps
+ */
+ Mbtmlo= 0x0, /* System mem addr mapping start low byte */
+ Mbtmhi= 0x1, /* System mem addr mapping start high byte */
+ F16bit= (1<<7), /* 16-bit wide data path */
+ Mtoplo= 0x2, /* System mem addr mapping stop low byte */
+ Mtophi= 0x3, /* System mem addr mapping stop high byte */
+ Ftimer1= (1<<6), /* timer set 1 */
+ Mofflo= 0x4, /* Card memory offset address low byte */
+ Moffhi= 0x5, /* Card memory offset address high byte */
+ Fregactive= (1<<6), /* attribute memory */
+
+ /*
+ * configuration registers - they start at an offset in attribute
+ * memory found in the CIS.
+ */
+ Rconfig= 0,
+ Creset= (1<<7), /* reset device */
+ Clevel= (1<<6), /* level sensitive interrupt line */
+ Cirq= (1<<2), /* IRQ enable */
+ Cdecode= (1<<1), /* address decode */
+ Cfunc= (1<<0), /* function enable */
+ Riobase0= 5,
+ Riobase1= 6,
+ Riosize= 9,
+};
+
+#define MAP(x,o) (Rmap + (x)*0x8 + o)
+
+typedef struct I82365 I82365;
+
+/* a controller */
+enum
+{
+ Ti82365,
+ Tpd6710,
+ Tpd6720,
+ Tvg46x,
+};
+struct I82365
+{
+ int type;
+ int dev;
+ int nslot;
+ int xreg; /* index register address */
+ int dreg; /* data register address */
+ int irq;
+};
+static I82365 *controller[4];
+static int ncontroller;
+static PCMslot *slot;
+static PCMslot *lastslot;
+static nslot;
+
+static void i82365intr(Ureg*, void*);
+static int pcmio(int, ISAConf*);
+static long pcmread(int, int, void*, long, vlong);
+static long pcmwrite(int, int, void*, long, vlong);
+
+static void i82365dump(PCMslot*);
+
+/*
+ * reading and writing card registers
+ */
+static uchar
+rdreg(PCMslot *pp, int index)
+{
+ outb(((I82365*)pp->cp)->xreg, pp->base + index);
+ return inb(((I82365*)pp->cp)->dreg);
+}
+static void
+wrreg(PCMslot *pp, int index, uchar val)
+{
+ outb(((I82365*)pp->cp)->xreg, pp->base + index);
+ outb(((I82365*)pp->cp)->dreg, val);
+}
+
+/*
+ * get info about card
+ */
+static void
+slotinfo(PCMslot *pp)
+{
+ uchar isr;
+
+ isr = rdreg(pp, Ris);
+ pp->occupied = (isr & (3<<2)) == (3<<2);
+ pp->powered = isr & (1<<6);
+ pp->battery = (isr & 3) == 3;
+ pp->wrprot = isr & (1<<4);
+ pp->busy = isr & (1<<5);
+ pp->msec = TK2MS(MACHP(0)->ticks);
+}
+
+static int
+vcode(int volt)
+{
+ switch(volt){
+ case 5:
+ return 1;
+ case 12:
+ return 2;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * enable the slot card
+ */
+static void
+slotena(PCMslot *pp)
+{
+ if(pp->enabled)
+ return;
+
+ /* power up and unreset, wait's are empirical (???) */
+ wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
+ delay(300);
+ wrreg(pp, Rigc, 0);
+ delay(100);
+ wrreg(pp, Rigc, Fnotreset);
+ delay(500);
+
+ /* get configuration */
+ slotinfo(pp);
+ if(pp->occupied){
+ pcmcisread(pp);
+ pp->enabled = 1;
+ } else
+ wrreg(pp, Rpc, Fautopower);
+}
+
+/*
+ * disable the slot card
+ */
+static void
+slotdis(PCMslot *pp)
+{
+ wrreg(pp, Rpc, 0); /* turn off card power */
+ wrreg(pp, Rwe, 0); /* no windows */
+ pp->enabled = 0;
+}
+
+/*
+ * status change interrupt
+ */
+static void
+i82365intr(Ureg *, void *)
+{
+ uchar csc, was;
+ PCMslot *pp;
+
+ if(slot == 0)
+ return;
+
+ for(pp = slot; pp < lastslot; pp++){
+ csc = rdreg(pp, Rcsc);
+ was = pp->occupied;
+ slotinfo(pp);
+ if(csc & (1<<3) && was != pp->occupied){
+ if(!pp->occupied)
+ slotdis(pp);
+ }
+ }
+}
+
+enum
+{
+ Mshift= 12,
+ Mgran= (1<<Mshift), /* granularity of maps */
+ Mmask= ~(Mgran-1), /* mask for address bits important to the chip */
+};
+
+/*
+ * get a map for pc card region, return corrected len
+ */
+PCMmap*
+pcmmap(int slotno, ulong offset, int len, int attr)
+{
+ PCMslot *pp;
+ uchar we, bit;
+ PCMmap *m, *nm;
+ int i;
+ ulong e;
+
+ pp = slot + slotno;
+ lock(&pp->mlock);
+
+ /* convert offset to granularity */
+ if(len <= 0)
+ len = 1;
+ e = ROUND(offset+len, Mgran);
+ offset &= Mmask;
+ len = e - offset;
+
+ /* look for a map that covers the right area */
+ we = rdreg(pp, Rwe);
+ bit = 1;
+ nm = 0;
+ for(m = pp->mmap; m < &pp->mmap[nelem(pp->mmap)]; m++){
+ if((we & bit))
+ if(m->attr == attr)
+ if(offset >= m->ca && e <= m->cea){
+
+ m->ref++;
+ unlock(&pp->mlock);
+ return m;
+ }
+ bit <<= 1;
+ if(nm == 0 && m->ref == 0)
+ nm = m;
+ }
+ m = nm;
+ if(m == 0){
+ unlock(&pp->mlock);
+ return 0;
+ }
+
+ /* if isa space isn't big enough, free it and get more */
+ if(m->len < len){
+ if(m->isa){
+ umbfree(m->isa, m->len);
+ m->len = 0;
+ }
+ m->isa = PADDR(umbmalloc(0, len, Mgran));
+ if(m->isa == 0){
+ print("pcmmap: out of isa space\n");
+ unlock(&pp->mlock);
+ return 0;
+ }
+ m->len = len;
+ }
+
+ /* set up new map */
+ m->ca = offset;
+ m->cea = m->ca + m->len;
+ m->attr = attr;
+ i = m-pp->mmap;
+ bit = 1<<i;
+ wrreg(pp, Rwe, we & ~bit); /* disable map before changing it */
+ wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift);
+ wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
+ wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
+ wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
+ offset -= m->isa;
+ offset &= (1<<25)-1;
+ offset >>= Mshift;
+ wrreg(pp, MAP(i, Mofflo), offset);
+ wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
+ wrreg(pp, Rwe, we | bit); /* enable map */
+ m->ref = 1;
+
+ unlock(&pp->mlock);
+ return m;
+}
+
+void
+pcmunmap(int slotno, PCMmap* m)
+{
+ PCMslot *pp;
+
+ pp = slot + slotno;
+ lock(&pp->mlock);
+ m->ref--;
+ unlock(&pp->mlock);
+}
+
+static void
+increfp(PCMslot *pp)
+{
+ lock(pp);
+ if(pp->ref++ == 0)
+ slotena(pp);
+ unlock(pp);
+}
+
+static void
+decrefp(PCMslot *pp)
+{
+ lock(pp);
+ if(pp->ref-- == 1)
+ slotdis(pp);
+ unlock(pp);
+}
+
+/*
+ * look for a card whose version contains 'idstr'
+ */
+static int
+pcmcia_pcmspecial(char *idstr, ISAConf *isa)
+{
+ PCMslot *pp;
+ extern char *strstr(char*, char*);
+ int enabled;
+
+ for(pp = slot; pp < lastslot; pp++){
+ if(pp->special)
+ continue; /* already taken */
+
+ /*
+ * make sure we don't power on cards when we already know what's
+ * in them. We'll reread every two minutes if necessary
+ */
+ enabled = 0;
+ if (pp->msec == ~0 || TK2MS(MACHP(0)->ticks) - pp->msec > 120000){
+ increfp(pp);
+ enabled++;
+ }
+
+ if(pp->occupied) {
+ if(strstr(pp->verstr, idstr)){
+ if (!enabled){
+ enabled = 1;
+ increfp(pp);
+ }
+ if(isa == 0 || pcmio(pp->slotno, isa) == 0){
+ pp->special = 1;
+ return pp->slotno;
+ }
+ }
+ } else
+ pp->special = 1;
+ if (enabled)
+ decrefp(pp);
+ }
+ return -1;
+}
+
+static void
+pcmcia_pcmspecialclose(int slotno)
+{
+ PCMslot *pp;
+
+ if(slotno >= nslot)
+ panic("pcmspecialclose");
+ pp = slot + slotno;
+ pp->special = 0;
+ decrefp(pp);
+}
+
+enum
+{
+ Qdir,
+ Qmem,
+ Qattr,
+ Qctl,
+
+ Nents = 3,
+};
+
+#define SLOTNO(c) ((ulong)((c->qid.path>>8)&0xff))
+#define TYPE(c) ((ulong)(c->qid.path&0xff))
+#define QID(s,t) (((s)<<8)|(t))
+
+static int
+pcmgen(Chan *c, char*, Dirtab *, int , int i, Dir *dp)
+{
+ int slotno;
+ Qid qid;
+ long len;
+ PCMslot *pp;
+
+ if(i == DEVDOTDOT){
+ mkqid(&qid, Qdir, 0, QTDIR);
+ devdir(c, qid, "#y", 0, eve, 0555, dp);
+ return 1;
+ }
+
+ if(i >= Nents*nslot)
+ return -1;
+ slotno = i/Nents;
+ pp = slot + slotno;
+ len = 0;
+ switch(i%Nents){
+ case 0:
+ qid.path = QID(slotno, Qmem);
+ snprint(up->genbuf, sizeof up->genbuf, "pcm%dmem", slotno);
+ len = pp->memlen;
+ break;
+ case 1:
+ qid.path = QID(slotno, Qattr);
+ snprint(up->genbuf, sizeof up->genbuf, "pcm%dattr", slotno);
+ len = pp->memlen;
+ break;
+ case 2:
+ qid.path = QID(slotno, Qctl);
+ snprint(up->genbuf, sizeof up->genbuf, "pcm%dctl", slotno);
+ break;
+ }
+ qid.vers = 0;
+ qid.type = QTFILE;
+ devdir(c, qid, up->genbuf, len, eve, 0660, dp);
+ return 1;
+}
+
+static char *chipname[] =
+{
+[Ti82365] "Intel 82365SL",
+[Tpd6710] "Cirrus Logic CL-PD6710",
+[Tpd6720] "Cirrus Logic CL-PD6720",
+[Tvg46x] "Vadem VG-46x",
+};
+
+static I82365*
+i82365probe(int x, int d, int dev)
+{
+ uchar c, id;
+ I82365 *cp;
+ ISAConf isa;
+ int i, nslot;
+
+ outb(x, Rid + (dev<<7));
+ id = inb(d);
+ if((id & 0xf0) != 0x80)
+ return 0; /* not a memory & I/O card */
+ if((id & 0x0f) == 0x00)
+ return 0; /* no revision number, not possible */
+
+ cp = xalloc(sizeof(I82365));
+ cp->xreg = x;
+ cp->dreg = d;
+ cp->dev = dev;
+ cp->type = Ti82365;
+ cp->nslot = 2;
+
+ switch(id){
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ /* could be a cirrus */
+ outb(x, Rchipinfo + (dev<<7));
+ outb(d, 0);
+ c = inb(d);
+ if((c & 0xc0) != 0xc0)
+ break;
+ c = inb(d);
+ if((c & 0xc0) != 0x00)
+ break;
+ if(c & 0x20){
+ cp->type = Tpd6720;
+ } else {
+ cp->type = Tpd6710;
+ cp->nslot = 1;
+ }
+
+ /* low power mode */
+ outb(x, Rmisc2 + (dev<<7));
+ c = inb(d);
+ outb(d, c & ~Flowpow);
+ break;
+ }
+
+ /* if it's not a Cirrus, it could be a Vadem... */
+ if(cp->type == Ti82365){
+ /* unlock the Vadem extended regs */
+ outb(x, 0x0E + (dev<<7));
+ outb(x, 0x37 + (dev<<7));
+
+ /* make the id register show the Vadem id */
+ outb(x, 0x3A + (dev<<7));
+ c = inb(d);
+ outb(d, c|0xC0);
+ outb(x, Rid + (dev<<7));
+ c = inb(d);
+ if(c & 0x08)
+ cp->type = Tvg46x;
+
+ /* go back to Intel compatible id */
+ outb(x, 0x3A + (dev<<7));
+ c = inb(d);
+ outb(d, c & ~0xC0);
+ }
+
+ memset(&isa, 0, sizeof(ISAConf));
+ if(isaconfig("pcmcia", ncontroller, &isa) && isa.irq)
+ cp->irq = isa.irq;
+ else
+ cp->irq = IrqPCMCIA;
+
+ for(i = 0; i < isa.nopt; i++){
+ if(cistrncmp(isa.opt[i], "nslot=", 6))
+ continue;
+ nslot = strtol(&isa.opt[i][6], nil, 0);
+ if(nslot > 0 && nslot <= 2)
+ cp->nslot = nslot;
+ }
+
+ controller[ncontroller++] = cp;
+ return cp;
+}
+
+static void
+i82365dump(PCMslot *pp)
+{
+ int i;
+
+ for(i = 0; i < 0x40; i++){
+ if((i&0x0F) == 0)
+ print("\n%2.2uX: ", i);
+ print("%2.2uX ", rdreg(pp, i));
+ if(((i+1) & 0x0F) == 0x08)
+ print(" - ");
+ }
+ print("\n");
+}
+
+/*
+ * set up for slot cards
+ */
+void
+devi82365link(void)
+{
+ static int already;
+ int i, j;
+ I82365 *cp;
+ PCMslot *pp;
+ char buf[32], *p;
+
+ if(already)
+ return;
+ already = 1;
+
+ if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0)
+ return;
+
+ if(_pcmspecial)
+ return;
+
+ /* look for controllers if the ports aren't already taken */
+ if(ioalloc(0x3E0, 2, 0, "i82365.0") >= 0){
+ i82365probe(0x3E0, 0x3E1, 0);
+ i82365probe(0x3E0, 0x3E1, 1);
+ if(ncontroller == 0)
+ iofree(0x3E0);
+ }
+ if(ioalloc(0x3E2, 2, 0, "i82365.1") >= 0){
+ i = ncontroller;
+ i82365probe(0x3E2, 0x3E3, 0);
+ i82365probe(0x3E2, 0x3E3, 1);
+ if(ncontroller == i)
+ iofree(0x3E2);
+ }
+
+ if(ncontroller == 0)
+ return;
+
+ _pcmspecial = pcmcia_pcmspecial;
+ _pcmspecialclose = pcmcia_pcmspecialclose;
+
+ for(i = 0; i < ncontroller; i++)
+ nslot += controller[i]->nslot;
+ slot = xalloc(nslot * sizeof(PCMslot));
+
+ lastslot = slot;
+ for(i = 0; i < ncontroller; i++){
+ cp = controller[i];
+ print("#y%d: %d slot %s: port 0x%uX irq %d\n",
+ i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq);
+ for(j = 0; j < cp->nslot; j++){
+ pp = lastslot++;
+ pp->slotno = pp - slot;
+ pp->memlen = 64*MB;
+ pp->base = (cp->dev<<7) | (j<<6);
+ pp->cp = cp;
+ pp->msec = ~0;
+ pp->verstr[0] = 0;
+ slotdis(pp);
+
+ /* interrupt on status change */
+ wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena);
+ rdreg(pp, Rcsc);
+ }
+
+ /* for card management interrupts */
+ snprint(buf, sizeof buf, "i82365.%d", i);
+ intrenable(cp->irq, i82365intr, 0, BUSUNKNOWN, buf);
+ }
+}
+
+static Chan*
+i82365attach(char *spec)
+{
+ return devattach('y', spec);
+}
+
+static Walkqid*
+i82365walk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, 0, 0, pcmgen);
+}
+
+static int
+i82365stat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, 0, 0, pcmgen);
+}
+
+static Chan*
+i82365open(Chan *c, int omode)
+{
+ if(c->qid.type & QTDIR){
+ if(omode != OREAD)
+ error(Eperm);
+ } else
+ increfp(slot + SLOTNO(c));
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+static void
+i82365close(Chan *c)
+{
+ if(c->flag & COPEN)
+ if((c->qid.type & QTDIR) == 0)
+ decrefp(slot+SLOTNO(c));
+}
+
+/* a memmove using only bytes */
+static void
+memmoveb(uchar *to, uchar *from, int n)
+{
+ while(n-- > 0)
+ *to++ = *from++;
+}
+
+/* a memmove using only shorts & bytes */
+static void
+memmoves(uchar *to, uchar *from, int n)
+{
+ ushort *t, *f;
+
+ if((((ulong)to) & 1) || (((ulong)from) & 1) || (n & 1)){
+ while(n-- > 0)
+ *to++ = *from++;
+ } else {
+ n = n/2;
+ t = (ushort*)to;
+ f = (ushort*)from;
+ while(n-- > 0)
+ *t++ = *f++;
+ }
+}
+
+static long
+pcmread(int slotno, int attr, void *a, long n, vlong off)
+{
+ int i, len;
+ PCMmap *m;
+ uchar *ac;
+ PCMslot *pp;
+ ulong offset = off;
+
+ pp = slot + slotno;
+ if(pp->memlen < offset)
+ return 0;
+ if(pp->memlen < offset + n)
+ n = pp->memlen - offset;
+
+ m = 0;
+ if(waserror()){
+ if(m)
+ pcmunmap(pp->slotno, m);
+ nexterror();
+ }
+
+ ac = a;
+ for(len = n; len > 0; len -= i){
+ m = pcmmap(pp->slotno, offset, 0, attr);
+ if(m == 0)
+ error("cannot map PCMCIA card");
+ if(offset + len > m->cea)
+ i = m->cea - offset;
+ else
+ i = len;
+ memmoveb(ac, KADDR(m->isa + offset - m->ca), i);
+ pcmunmap(pp->slotno, m);
+ offset += i;
+ ac += i;
+ }
+
+ poperror();
+ return n;
+}
+
+static long
+i82365read(Chan *c, void *a, long n, vlong off)
+{
+ char *p, *buf, *e;
+ PCMslot *pp;
+ ulong offset = off;
+
+ switch(TYPE(c)){
+ case Qdir:
+ return devdirread(c, a, n, 0, 0, pcmgen);
+ case Qmem:
+ case Qattr:
+ return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, off);
+ case Qctl:
+ buf = p = malloc(READSTR);
+ e = p + READSTR;
+ pp = slot + SLOTNO(c);
+
+ buf[0] = 0;
+ if(pp->occupied){
+ p = seprint(p, e, "occupied\n");
+ if(pp->verstr[0])
+ p = seprint(p, e, "version %s\n", pp->verstr);
+ }
+ if(pp->enabled)
+ p = seprint(p, e, "enabled\n");
+ if(pp->powered)
+ p = seprint(p, e, "powered\n");
+ if(pp->configed)
+ p = seprint(p, e, "configed\n");
+ if(pp->wrprot)
+ p = seprint(p, e, "write protected\n");
+ if(pp->busy)
+ p = seprint(p, e, "busy\n");
+ seprint(p, e, "battery lvl %d\n", pp->battery);
+
+ n = readstr(offset, a, n, buf);
+ free(buf);
+
+ return n;
+ }
+ error(Ebadarg);
+ return -1; /* not reached */
+}
+
+static long
+pcmwrite(int dev, int attr, void *a, long n, vlong off)
+{
+ int i, len;
+ PCMmap *m;
+ uchar *ac;
+ PCMslot *pp;
+ ulong offset = off;
+
+ pp = slot + dev;
+ if(pp->memlen < offset)
+ return 0;
+ if(pp->memlen < offset + n)
+ n = pp->memlen - offset;
+
+ m = 0;
+ if(waserror()){
+ if(m)
+ pcmunmap(pp->slotno, m);
+ nexterror();
+ }
+
+ ac = a;
+ for(len = n; len > 0; len -= i){
+ m = pcmmap(pp->slotno, offset, 0, attr);
+ if(m == 0)
+ error("cannot map PCMCIA card");
+ if(offset + len > m->cea)
+ i = m->cea - offset;
+ else
+ i = len;
+ memmoveb(KADDR(m->isa + offset - m->ca), ac, i);
+ pcmunmap(pp->slotno, m);
+ offset += i;
+ ac += i;
+ }
+
+ poperror();
+ return n;
+}
+
+static long
+i82365write(Chan *c, void *a, long n, vlong off)
+{
+ PCMslot *pp;
+ char buf[32];
+
+ switch(TYPE(c)){
+ case Qctl:
+ if(n >= sizeof(buf))
+ n = sizeof(buf) - 1;
+ strncpy(buf, a, n);
+ buf[n] = 0;
+ pp = slot + SLOTNO(c);
+ if(!pp->occupied)
+ error(Eio);
+
+ /* set vpp on card */
+ if(strncmp(buf, "vpp", 3) == 0)
+ wrreg(pp, Rpc, vcode(atoi(buf+3))|Fautopower|Foutena|Fcardena);
+ return n;
+ case Qmem:
+ case Qattr:
+ pp = slot + SLOTNO(c);
+ if(pp->occupied == 0 || pp->enabled == 0)
+ error(Eio);
+ n = pcmwrite(pp->slotno, TYPE(c) == Qattr, a, n, off);
+ if(n < 0)
+ error(Eio);
+ return n;
+ }
+ error(Ebadarg);
+ return -1; /* not reached */
+}
+
+Dev i82365devtab = {
+ 'y',
+ "i82365",
+
+ devreset,
+ devinit,
+ devshutdown,
+ i82365attach,
+ i82365walk,
+ i82365stat,
+ i82365open,
+ devcreate,
+ i82365close,
+ i82365read,
+ devbread,
+ i82365write,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+/*
+ * configure the PCMslot for IO. We assume very heavily that we can read
+ * configuration info from the CIS. If not, we won't set up correctly.
+ */
+static int
+pcmio(int slotno, ISAConf *isa)
+{
+ uchar we, x, *p;
+ PCMslot *pp;
+ PCMconftab *ct, *et, *t;
+ PCMmap *m;
+ int i, index, irq;
+ char *cp;
+
+ irq = isa->irq;
+ if(irq == 2)
+ irq = 9;
+
+ if(slotno > nslot)
+ return -1;
+ pp = slot + slotno;
+
+ if(!pp->occupied)
+ return -1;
+
+ et = &pp->ctab[pp->nctab];
+
+ ct = 0;
+ for(i = 0; i < isa->nopt; i++){
+ if(strncmp(isa->opt[i], "index=", 6))
+ continue;
+ index = strtol(&isa->opt[i][6], &cp, 0);
+ if(cp == &isa->opt[i][6] || index >= pp->nctab)
+ return -1;
+ ct = &pp->ctab[index];
+ }
+
+ if(ct == 0){
+ /* assume default is right */
+ if(pp->def)
+ ct = pp->def;
+ else
+ ct = pp->ctab;
+
+ /* try for best match */
+ if(ct->nio == 0
+ || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
+ for(t = pp->ctab; t < et; t++)
+ if(t->nio
+ && t->io[0].start == isa->port
+ && ((1<<irq) & t->irqs)){
+ ct = t;
+ break;
+ }
+ }
+ if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
+ for(t = pp->ctab; t < et; t++)
+ if(t->nio && ((1<<irq) & t->irqs)){
+ ct = t;
+ break;
+ }
+ }
+ if(ct->nio == 0){
+ for(t = pp->ctab; t < et; t++)
+ if(t->nio){
+ ct = t;
+ break;
+ }
+ }
+ }
+
+ if(ct == et || ct->nio == 0)
+ return -1;
+ if(isa->port == 0 && ct->io[0].start == 0)
+ return -1;
+
+ /* route interrupts */
+ isa->irq = irq;
+ wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
+
+ /* set power and enable device */
+ x = vcode(ct->vpp1);
+ wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
+
+ /* 16-bit data path */
+ if(ct->bit16)
+ x = Ftiming|Fiocs16|Fwidth16;
+ else
+ x = Ftiming;
+ if(ct->nio == 2 && ct->io[1].start)
+ x |= x<<4;
+ wrreg(pp, Rio, x);
+
+ /*
+ * enable io port map 0
+ * the 'top' register value includes the last valid address
+ */
+ if(isa->port == 0)
+ isa->port = ct->io[0].start;
+ we = rdreg(pp, Rwe);
+ wrreg(pp, Riobtm0lo, isa->port);
+ wrreg(pp, Riobtm0hi, isa->port>>8);
+ i = isa->port+ct->io[0].len-1;
+ wrreg(pp, Riotop0lo, i);
+ wrreg(pp, Riotop0hi, i>>8);
+ we |= 1<<6;
+ if(ct->nio >= 2 && ct->io[1].start){
+ wrreg(pp, Riobtm1lo, ct->io[1].start);
+ wrreg(pp, Riobtm1hi, ct->io[1].start>>8);
+ i = ct->io[1].start+ct->io[1].len-1;
+ wrreg(pp, Riotop1lo, i);
+ wrreg(pp, Riotop1hi, i>>8);
+ we |= 1<<7;
+ }
+ wrreg(pp, Rwe, we);
+
+ /* only touch Rconfig if it is present */
+ m = pcmmap(slotno, pp->cfg[0].caddr + Rconfig, 0x20, 1);
+ p = KADDR(m->isa + pp->cfg[0].caddr - m->ca);
+ if(pp->cfg[0].cpresent & (1<<Rconfig)){
+ /* Reset adapter */
+
+ /* set configuration and interrupt type.
+ * if level is possible on the card, use it.
+ */
+ x = ct->index;
+ if(ct->irqtype & 0x20)
+ x |= Clevel;
+
+ /* enable the device, enable address decode and
+ * irq enable.
+ */
+ x |= Cfunc|Cdecode|Cirq;
+
+ p[0] = x;
+ //delay(5);
+ microdelay(40);
+ }
+
+ if(pp->cfg[0].cpresent & (1<<Riobase0)){
+ /* set up the iobase 0 */
+ p[Riobase0 << 1] = isa->port;
+ p[Riobase1 << 1] = isa->port >> 8;
+ }
+
+ if(pp->cfg[0].cpresent & (1<<Riosize))
+ p[Riosize << 1] = ct->io[0].len;
+ pcmunmap(slotno, m);
+ return 0;
+}
diff --git a/sys/src/9/pc/devlm78.c b/sys/src/9/pc/devlm78.c
new file mode 100755
index 000000000..617d5cb92
--- /dev/null
+++ b/sys/src/9/pc/devlm78.c
@@ -0,0 +1,346 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+/* this driver doesn't implement the management interrupts. we
+ * leave the LM78 interrupts set to whatever the BIOS did. we do
+ * allow reading and writing the the readouts and alarm values.
+ * Read(2)ing or write(2)ing at offset 0x0-0x1f, is
+ * equivalent to reading or writing lm78 registers 0x20-0x3f.
+ */
+enum
+{
+ /* address of chip on serial interface */
+ Serialaddr= 0x2d,
+
+ /* parallel access registers */
+ Rpaddr= 0x5,
+ Bbusy= (1<<7),
+ Rpdata= 0x6,
+
+ /* internal register addresses */
+ Rconfig= 0x40,
+ Bstart= (1<<0),
+ Bsmiena= (1<<1),
+ Birqena= (1<<2),
+ Bintclr= (1<<3),
+ Breset= (1<<4),
+ Bnmi= (1<<5), /* if set, use nmi, else irq */
+ Bpowbypass= (1<<6),
+ Binit= (1<<7),
+ Ristat1= 0x41,
+ Ristat2= 0x42,
+ Rsmimask1= 0x43,
+ Rsmimask2= 0x44,
+ Rnmimask1= 0x45,
+ Rnmimask2= 0x46,
+ Rvidfan= 0x47, /* set fan counter, and read voltage level */
+ Mvid= 0x0f,
+ Mfan= 0xf0,
+ Raddr= 0x48, /* address used on serial bus */
+ Rresetid= 0x49, /* chip reset and ID register */
+ Rpost= 0x00, /* start of post ram */
+ Rvalue= 0x20, /* start of value ram */
+
+ VRsize= 0x20, /* size of value ram */
+};
+
+enum
+{
+ Qdir,
+ Qlm78vram,
+};
+
+static Dirtab lm78dir[] = {
+ ".", { Qdir, 0, QTDIR}, 0, 0555,
+ "lm78vram", { Qlm78vram, 0 }, 0, 0444,
+};
+
+/* interface type */
+enum
+{
+ None= 0,
+ Smbus,
+ Parallel,
+};
+
+static struct {
+ QLock;
+ int probed;
+ int ifc; /* which interface is connected */
+ SMBus *smbus; /* serial interface */
+ int port; /* parallel interface */
+} lm78;
+
+extern SMBus* piix4smbus(void);
+
+/* wait for device to become quiescent and then set the */
+/* register address */
+static void
+setreg(int reg)
+{
+ int tries;
+
+ for(tries = 0; tries < 1000000; tries++)
+ if((inb(lm78.port+Rpaddr) & Bbusy) == 0){
+ outb(lm78.port+Rpaddr, reg);
+ return;
+ }
+ error("lm78 broken");
+}
+
+/* routines that actually touch the device */
+static void
+lm78wrreg(int reg, uchar val)
+{
+ if(waserror()){
+ qunlock(&lm78);
+ nexterror();
+ }
+ qlock(&lm78);
+
+ switch(lm78.ifc){
+ case Smbus:
+ lm78.smbus->transact(lm78.smbus, SMBbytewrite, Serialaddr, reg, &val);
+ break;
+ case Parallel:
+ setreg(reg);
+ outb(lm78.port+Rpdata, val);
+ break;
+ default:
+ error(Enodev);
+ break;
+ }
+
+ qunlock(&lm78);
+ poperror();
+}
+
+static int
+lm78rdreg(int reg)
+{
+ uchar val;
+
+ if(waserror()){
+ qunlock(&lm78);
+ nexterror();
+ }
+ qlock(&lm78);
+
+ switch(lm78.ifc){
+ case Smbus:
+ lm78.smbus->transact(lm78.smbus, SMBsend, Serialaddr, reg, nil);
+ lm78.smbus->transact(lm78.smbus, SMBrecv, Serialaddr, 0, &val);
+ break;
+ case Parallel:
+ setreg(reg);
+ val = inb(lm78.port+Rpdata);
+ break;
+ default:
+ error(Enodev);
+ break;
+ }
+
+ qunlock(&lm78);
+ poperror();
+ return val;
+}
+
+/* start the chip monitoring but don't change any smi
+ * interrupts and/or alarms that the BIOS may have set up.
+ * this isn't locked because it's thought to be idempotent
+ */
+static void
+lm78enable(void)
+{
+ uchar config;
+
+ if(lm78.ifc == None)
+ error(Enodev);
+
+ if(lm78.probed == 0){
+ /* make sure its really there */
+ if(lm78rdreg(Raddr) != Serialaddr){
+ lm78.ifc = None;
+ error(Enodev);
+ } else {
+ /* start the sampling */
+ config = lm78rdreg(Rconfig);
+ config = (config | Bstart) & ~(Bintclr|Binit);
+ lm78wrreg(Rconfig, config);
+pprint("Rvidfan %2.2ux\n", lm78rdreg(Rconfig), lm78rdreg(Rvidfan));
+ }
+ lm78.probed = 1;
+ }
+}
+
+enum
+{
+ IntelVendID= 0x8086,
+ PiixID= 0x122E,
+ Piix3ID= 0x7000,
+
+ Piix4PMID= 0x7113, /* PIIX4 power management function */
+
+ PCSC= 0x78, /* programmable chip select control register */
+ PCSC8bytes= 0x01,
+};
+
+/* figure out what kind of interface we could have */
+void
+lm78reset(void)
+{
+ int pcs;
+ Pcidev *p;
+
+ lm78.ifc = None;
+ p = nil;
+ while((p = pcimatch(p, IntelVendID, 0)) != nil){
+ switch(p->did){
+ /* these bridges use the PCSC to map the lm78 into port space. */
+ /* for this case the lm78's CS# select is connected to the PIIX's */
+ /* PCS# output and the bottom 3 bits of address are passed to the */
+ /* LM78's A0-A2 inputs. */
+ case PiixID:
+ case Piix3ID:
+ pcs = pcicfgr16(p, PCSC);
+ if(pcs & 3) {
+ /* already enabled */
+ lm78.port = pcs & ~3;
+ lm78.ifc = Parallel;
+ return;
+ }
+
+ /* enable the chip, use default address 0x50 */
+ pcicfgw16(p, PCSC, 0x50|PCSC8bytes);
+ pcs = pcicfgr16(p, PCSC);
+ lm78.port = pcs & ~3;
+ lm78.ifc = Parallel;
+ return;
+
+ /* this bridge puts the lm78's serial interface on the smbus */
+ case Piix4PMID:
+ lm78.smbus = piix4smbus();
+ if(lm78.smbus == nil)
+ continue;
+ print("found piix4 smbus, base %lud\n", lm78.smbus->base);
+ lm78.ifc = Smbus;
+ return;
+ }
+ }
+}
+
+Walkqid *
+lm78walk(Chan* c, Chan *nc, char** name, int nname)
+{
+ return devwalk(c, nc, name, nname, lm78dir, nelem(lm78dir), devgen);
+}
+
+static int
+lm78stat(Chan* c, uchar* dp, int n)
+{
+ return devstat(c, dp, n, lm78dir, nelem(lm78dir), devgen);
+}
+
+static Chan*
+lm78open(Chan* c, int omode)
+{
+ return devopen(c, omode, lm78dir, nelem(lm78dir), devgen);
+}
+
+static void
+lm78close(Chan*)
+{
+}
+
+enum
+{
+ Linelen= 25,
+};
+
+static long
+lm78read(Chan *c, void *a, long n, vlong offset)
+{
+ uchar *va = a;
+ int off, e;
+
+ off = offset;
+
+ switch((ulong)c->qid.path){
+ case Qdir:
+ return devdirread(c, a, n, lm78dir, nelem(lm78dir), devgen);
+
+ case Qlm78vram:
+ if(off >= VRsize)
+ return 0;
+ e = off + n;
+ if(e > VRsize)
+ e = VRsize;
+ for(; off < e; off++)
+ *va++ = lm78rdreg(Rvalue+off);
+ return (int)(va - (uchar*)a);
+ }
+ return 0;
+}
+
+static long
+lm78write(Chan *c, void *a, long n, vlong offset)
+{
+ uchar *va = a;
+ int off, e;
+
+ off = offset;
+
+ switch((ulong)c->qid.path){
+ default:
+ error(Eperm);
+
+ case Qlm78vram:
+ if(off >= VRsize)
+ return 0;
+ e = off + n;
+ if(e > VRsize)
+ e = VRsize;
+ for(; off < e; off++)
+ lm78wrreg(Rvalue+off, *va++);
+ return va - (uchar*)a;
+ }
+ return 0;
+}
+
+extern Dev lm78devtab;
+
+static Chan*
+lm78attach(char* spec)
+{
+ lm78enable();
+
+ return devattach(lm78devtab.dc, spec);
+}
+
+Dev lm78devtab = {
+ 'T',
+ "lm78",
+
+ lm78reset,
+ devinit,
+ devshutdown,
+ lm78attach,
+ lm78walk,
+ lm78stat,
+ lm78open,
+ devcreate,
+ lm78close,
+ lm78read,
+ devbread,
+ lm78write,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
diff --git a/sys/src/9/pc/devlml.c b/sys/src/9/pc/devlml.c
new file mode 100755
index 000000000..df96bbda2
--- /dev/null
+++ b/sys/src/9/pc/devlml.c
@@ -0,0 +1,403 @@
+/*
+ * Lml 22 driver
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+#include "devlml.h"
+
+#define DBGREAD 0x01
+#define DBGWRIT 0x02
+#define DBGINTR 0x04
+#define DBGINTS 0x08
+#define DBGFS 0x10
+
+int debug = DBGREAD|DBGWRIT|DBGFS;
+
+enum{
+ Qdir,
+ Qctl0,
+ Qjpg0,
+ Qraw0,
+ Qctl1,
+ Qjpg1,
+ Qraw1,
+};
+
+static Dirtab lmldir[] = {
+ ".", {Qdir, 0, QTDIR}, 0, 0555,
+ "lml0ctl", {Qctl0}, 0, 0666,
+ "lml0jpg", {Qjpg0}, 0, 0444,
+ "lml0raw", {Qraw0}, 0, 0444,
+ "lml1ctl", {Qctl1}, 0, 0666,
+ "lml1jpg", {Qjpg1}, 0, 0444,
+ "lml1raw", {Qraw1}, 0, 0444,
+};
+
+typedef struct LML LML;
+
+struct LML {
+ /* Hardware */
+ Pcidev *pcidev;
+ ulong pciBaseAddr;
+
+ /* Allocated memory */
+ CodeData *codedata;
+
+ /* Software state */
+ ulong jpgframeno;
+ int frameNo;
+ Rendez sleepjpg;
+ int jpgopens;
+} lmls[NLML];
+
+int nlml;
+
+static FrameHeader jpgheader = {
+ MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8,
+ { 'L', 'M', 'L', '\0'},
+ -1, 0, 0, 0
+};
+
+#define writel(v, a) *(ulong *)(a) = (v)
+#define readl(a) *(ulong*)(a)
+
+static int
+getbuffer(void *x)
+{
+ static last = NBUF-1;
+ int l = last;
+ LML *lml;
+
+ lml = x;
+ for(;;){
+ last = (last+1) % NBUF;
+ if(lml->codedata->statCom[last] & STAT_BIT)
+ return last + 1;
+ if(last == l)
+ return 0;
+ }
+}
+
+static long
+jpgread(LML *lml, void *va, long nbytes, vlong, int dosleep)
+{
+ int bufno;
+ FrameHeader *jpgheader;
+
+ /*
+ * reads should be of size 1 or sizeof(FrameHeader).
+ * Frameno is the number of the buffer containing the data.
+ */
+ while((bufno = getbuffer(lml)) == 0 && dosleep)
+ sleep(&lml->sleepjpg, getbuffer, lml);
+ if(--bufno < 0)
+ return 0;
+
+ jpgheader = (FrameHeader*)(lml->codedata->frag[bufno].hdr+2);
+ if(nbytes == sizeof(FrameHeader)){
+ memmove(va, jpgheader, sizeof(FrameHeader));
+ return sizeof(FrameHeader);
+ }
+ if(nbytes == 1){
+ *(char *)va = bufno;
+ return 1;
+ }
+ return 0;
+}
+
+static void lmlintr(Ureg *, void *);
+
+static void
+prepbuf(LML *lml)
+{
+ int i;
+ CodeData *cd;
+
+ cd = lml->codedata;
+ for(i = 0; i < NBUF; i++){
+ cd->statCom[i] = PADDR(&(cd->fragdesc[i]));
+ cd->fragdesc[i].addr = PADDR(cd->frag[i].fb);
+ /* Length is in double words, in position 1..20 */
+ cd->fragdesc[i].leng = FRAGSIZE >> 1 | FRAGM_FINAL_B;
+ memmove(cd->frag[i].hdr+2, &jpgheader, sizeof(FrameHeader)-2);
+ }
+}
+
+static void
+lmlreset(void)
+{
+ ulong regpa;
+ char name[32];
+ void *regva;
+ LML *lml;
+ Pcidev *pcidev;
+ Physseg segbuf;
+
+ pcidev = nil;
+
+ for(nlml = 0; nlml < NLML && (pcidev = pcimatch(pcidev, VENDOR_ZORAN,
+ ZORAN_36067)); nlml++){
+ lml = &lmls[nlml];
+ lml->pcidev = pcidev;
+ lml->codedata = (CodeData*)(((ulong)xalloc(Codedatasize+ BY2PG)
+ + BY2PG-1) & ~(BY2PG-1));
+ if(lml->codedata == nil){
+ print("devlml: xalloc(%ux, %ux, 0)\n", Codedatasize, BY2PG);
+ return;
+ }
+
+ print("Installing Motion JPEG driver %s, irq %d\n",
+ MJPG_VERSION, pcidev->intl);
+ print("MJPG buffer at 0x%.8p, size 0x%.8ux\n", lml->codedata,
+ Codedatasize);
+
+ /* Get access to DMA memory buffer */
+ lml->codedata->pamjpg = PADDR(lml->codedata->statCom);
+
+ prepbuf(lml);
+
+ print("zr36067 found at 0x%.8lux", pcidev->mem[0].bar & ~0x0F);
+
+ regpa = pcidev->mem[0].bar & ~0x0F;
+ regva = vmap(regpa, pcidev->mem[0].size);
+ if(regva == 0){
+ print("lml: failed to map registers\n");
+ return;
+ }
+ lml->pciBaseAddr = (ulong)regva;
+ print(", mapped at 0x%.8lux\n", lml->pciBaseAddr);
+
+ memset(&segbuf, 0, sizeof(segbuf));
+ segbuf.attr = SG_PHYSICAL;
+ sprint(name, "lml%d.mjpg", nlml);
+ kstrdup(&segbuf.name, name);
+ segbuf.pa = PADDR(lml->codedata);
+ segbuf.size = Codedatasize;
+ if(addphysseg(&segbuf) == -1){
+ print("lml: physsegment: %s\n", name);
+ return;
+ }
+
+ memset(&segbuf, 0, sizeof(segbuf));
+ segbuf.attr = SG_PHYSICAL;
+ sprint(name, "lml%d.regs", nlml);
+ kstrdup(&segbuf.name, name);
+ segbuf.pa = (ulong)regpa;
+ segbuf.size = pcidev->mem[0].size;
+ if(addphysseg(&segbuf) == -1){
+ print("lml: physsegment: %s\n", name);
+ return;
+ }
+
+ /* set up interrupt handler */
+ intrenable(pcidev->intl, lmlintr, lml, pcidev->tbdf, "lml");
+ }
+}
+
+static Chan*
+lmlattach(char *spec)
+{
+ if(debug&DBGFS)
+ print("lmlattach\n");
+ return devattach(L'Λ', spec);
+}
+
+static Walkqid*
+lmlwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ if(debug&DBGFS)
+ print("lmlwalk\n");
+ return devwalk(c, nc, name, nname, lmldir, 3*nlml+1, devgen);
+}
+
+static int
+lmlstat(Chan *c, uchar *db, int n)
+{
+ if(debug&DBGFS)
+ print("lmlstat\n");
+ return devstat(c, db, n, lmldir, 3*nlml+1, devgen);
+}
+
+static Chan*
+lmlopen(Chan *c, int omode)
+{
+ int i;
+ LML *lml;
+
+ if(debug&DBGFS)
+ print("lmlopen\n");
+ if(omode != OREAD)
+ error(Eperm);
+ c->aux = 0;
+ i = 0;
+ switch((ulong)c->qid.path){
+ case Qctl1:
+ i++;
+ /* fall through */
+ case Qctl0:
+ if(i >= nlml)
+ error(Eio);
+ break;
+ case Qjpg1:
+ case Qraw1:
+ i++;
+ /* fall through */
+ case Qjpg0:
+ case Qraw0:
+ /* allow one open */
+ if(i >= nlml)
+ error(Eio);
+ lml = lmls+i;
+ if(lml->jpgopens)
+ error(Einuse);
+ lml->jpgopens = 1;
+ lml->jpgframeno = 0;
+ prepbuf(lml);
+ break;
+ }
+ return devopen(c, omode, lmldir, 3*nlml+1, devgen);
+}
+
+static void
+lmlclose(Chan *c)
+{
+ int i;
+
+ if(debug&DBGFS)
+ print("lmlclose\n");
+ i = 0;
+ switch((ulong)c->qid.path){
+ case Qjpg1:
+ case Qraw1:
+ i++;
+ /* fall through */
+ case Qjpg0:
+ case Qraw0:
+ lmls[i].jpgopens = 0;
+ break;
+ }
+}
+
+static long
+lmlread(Chan *c, void *va, long n, vlong voff)
+{
+ int i, len;
+ long off = voff;
+ uchar *buf = va;
+ LML *lml;
+ static char lmlinfo[1024];
+
+ i = 0;
+ switch((ulong)c->qid.path){
+ case Qdir:
+ n = devdirread(c, (char *)buf, n, lmldir, 3*nlml+1, devgen);
+ if(debug&(DBGFS|DBGREAD))
+ print("lmlread %ld\n", n);
+ return n;
+ case Qctl1:
+ i++;
+ /* fall through */
+ case Qctl0:
+ if(i >= nlml)
+ error(Eio);
+ lml = lmls+i;
+ len = snprint(lmlinfo, sizeof lmlinfo, "lml%djpg lml%draw\nlml%d.regs 0x%lux 0x%ux\nlml%d.mjpg 0x%lux 0x%ux\n",
+ i, i,
+ i, lml->pcidev->mem[0].bar & ~0x0F, lml->pcidev->mem[0].size,
+ i, PADDR(lml->codedata), Codedatasize);
+ if(voff > len)
+ return 0;
+ if(n > len - voff)
+ n = len - voff;
+ memmove(va, lmlinfo+voff, n);
+ return n;
+ case Qjpg1:
+ i++;
+ /* fall through */
+ case Qjpg0:
+ if(i >= nlml)
+ error(Eio);
+ return jpgread(lmls+i, buf, n, off, 1);
+ case Qraw1:
+ i++;
+ /* fall through */
+ case Qraw0:
+ if(i >= nlml)
+ error(Eio);
+ return jpgread(lmls+i, buf, n, off, 0);
+ }
+ return -1;
+}
+
+static long
+lmlwrite(Chan *, void *, long, vlong)
+{
+ error(Eperm);
+ return 0;
+}
+
+Dev lmldevtab = {
+ L'Λ',
+ "video",
+
+ lmlreset,
+ devinit,
+ devshutdown,
+ lmlattach,
+ lmlwalk,
+ lmlstat,
+ lmlopen,
+ devcreate,
+ lmlclose,
+ lmlread,
+ devbread,
+ lmlwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+static void
+lmlintr(Ureg *, void *x)
+{
+ ulong fstart, fno, flags, statcom;
+ FrameHeader *jpgheader;
+ LML *lml;
+
+ lml = x;
+ flags = readl(lml->pciBaseAddr+INTR_STAT);
+ /* Reset all interrupts from 067 */
+ writel(0xff000000, lml->pciBaseAddr + INTR_STAT);
+
+ if(flags & INTR_JPEGREP){
+
+ if(debug&DBGINTR)
+ print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags);
+
+ fstart = lml->jpgframeno & 3;
+ for(;;){
+ lml->jpgframeno++;
+ fno = lml->jpgframeno & 3;
+ if(lml->codedata->statCom[fno] & STAT_BIT)
+ break;
+ if(fno == fstart){
+ if(debug & DBGINTR)
+ print("Spurious lml jpg intr?\n");
+ return;
+ }
+ }
+ statcom = lml->codedata->statCom[fno];
+ jpgheader = (FrameHeader *)(lml->codedata->frag[fno].hdr + 2);
+ jpgheader->frameNo = lml->jpgframeno;
+ jpgheader->ftime = todget(nil);
+ jpgheader->frameSize = (statcom & 0x00ffffff) >> 1;
+ jpgheader->frameSeqNo = statcom >> 24;
+ wakeup(&lml->sleepjpg);
+ }
+}
diff --git a/sys/src/9/pc/devlml.h b/sys/src/9/pc/devlml.h
new file mode 100755
index 000000000..85c0c013a
--- /dev/null
+++ b/sys/src/9/pc/devlml.h
@@ -0,0 +1,124 @@
+/* Lml 22 driver */
+
+#define MJPG_VERSION "LML33 v0.2"
+#define NLML 2
+
+/*
+ * The following values can be modified to tune/set default behaviour of the
+ * driver.
+ */
+
+/* The number of uS delay in I2C state transitions (probably >= 10) */
+#define I2C_DELAY 50
+
+/* The amount of spinning to do before the I2C bus is timed out */
+#define I2C_TIMEOUT 10000000
+
+/* The amount of spinning to do before the guest bus is timed out */
+#define GUEST_TIMEOUT 10000000
+
+/*
+ * The amount of spinning to do before the polling of the still
+ * transfer port is aborted.
+ */
+#define STILL_TIMEOUT 1000000
+
+/*
+ * The following number is the maximum number of cards permited. Each
+ * card found is mapped to a device minor number starting from 0.
+ */
+#define MAX_CARDS 1
+
+/* The following are the datastructures needed by the device. */
+#define I2C_BUS 0x044
+/* which bit of I2C_BUS is which */
+#define I2C_SCL 1
+#define I2C_SDA 2
+#define INTR_JPEGREP 0x08000000
+#define INTR_GIRQ0 0x20000000
+#define INTR_STAT 0x03c
+
+/* A Device records the properties of the various card types supported. */
+typedef struct {
+ int number; /* The H33_CARDTYPE_ assigned */
+ char *card_name; /* A string name */
+ int zr060addr; /* Which guest bus address for the ZR36060 */
+} Device;
+
+/*
+ * The remainder of the #defs are constants which should not need changing.
+ *
+ * The PCI vendor and device ids of the zoran chipset on the dc30.
+ * these really belong in pci.h.
+ */
+#define VENDOR_ZORAN 0x11de
+#define ZORAN_36057 0x6057
+#define ZORAN_36067 ZORAN_36057
+
+#define BT819Addr 0x8a
+#define BT856Addr 0x88
+
+#define NBUF 4
+
+#define FRAGM_FINAL_B 1
+#define STAT_BIT 1
+
+typedef struct HdrFragment HdrFragment;
+typedef struct FrameHeader FrameHeader;
+typedef union Fragment Fragment;
+typedef struct FragmentTable FragmentTable;
+typedef struct CodeData CodeData;
+
+/* If we're on a little endian architecture, then 0xFF, 0xD8 byte sequence is */
+#define MRK_SOI 0xD8FF
+#define MRK_APP3 0xE3FF
+#define APP_NAME "LML"
+
+struct FrameHeader { /* Don't modify this struct, used by h/w */
+ ushort mrkSOI;
+ ushort mrkAPP3;
+ ushort lenAPP3;
+ char nm[4];
+ ushort frameNo;
+ vlong ftime;
+ ulong frameSize;
+ ushort frameSeqNo;
+ ushort SOIfiller;
+};
+
+#define FRAGSIZE (128*1024)
+
+union Fragment {
+ FrameHeader fh;
+ char fb[FRAGSIZE];
+};
+
+struct HdrFragment {
+ uchar hdr[sizeof(FrameHeader)];
+ Fragment;
+};
+
+struct FragmentTable { /* Don't modify this struct, used by h/w */
+ ulong addr; /* Physical address */
+ ulong leng;
+};
+
+struct CodeData { /* Don't modify this struct, used by h/w */
+ ulong pamjpg; /* Physical addr of statCom[0] */
+ ulong pagrab; /* Physical addr of grab buffer */
+ ulong statCom[4]; /* Physical addresses of fragdescs */
+ FragmentTable fragdesc[4];
+ HdrFragment frag[4];
+};
+
+enum{
+ Codedatasize = (sizeof(CodeData) + BY2PG - 1) & ~(BY2PG - 1),
+ Grabdatasize = (730 * 568 * 2 * 2 + BY2PG - 1) & ~(BY2PG - 1),
+};
+
+#define POST_OFFICE 0x200
+#define POST_PEND 0x02000000
+#define POST_TIME 0x01000000
+#define POST_DIR 0x00800000
+
+#define GID060 0
diff --git a/sys/src/9/pc/devlpt.c b/sys/src/9/pc/devlpt.c
new file mode 100755
index 000000000..dc06622b9
--- /dev/null
+++ b/sys/src/9/pc/devlpt.c
@@ -0,0 +1,241 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+/* Centronix parallel (printer) port */
+
+/* base addresses */
+static int lptbase[] = {
+ 0x378, /* lpt1 */
+ 0x3bc, /* lpt2 */
+ 0x278 /* lpt3 (sic) */
+};
+#define NDEV nelem(lptbase)
+static int lptallocd[NDEV];
+
+/* offsets, and bits in the registers */
+enum
+{
+ Qdir= 0x8000,
+ /* data latch register */
+ Qdlr= 0x0,
+ /* printer status register */
+ Qpsr= 0x1,
+ Fnotbusy= 0x80,
+ Fack= 0x40,
+ Fpe= 0x20,
+ Fselect= 0x10,
+ Fnoerror= 0x08,
+ /* printer control register */
+ Qpcr= 0x2,
+ Fie= 0x10,
+ Fselectin= 0x08,
+ Finitbar= 0x04,
+ Faf= 0x02,
+ Fstrobe= 0x01,
+ /* fake `data register' */
+ Qdata= 0x3,
+};
+
+static int lptready(void*);
+static void outch(int, int);
+static void lptintr(Ureg*, void*);
+
+static Rendez lptrendez;
+
+Dirtab lptdir[]={
+ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
+ "dlr", {Qdlr}, 1, 0666,
+ "psr", {Qpsr}, 5, 0444,
+ "pcr", {Qpcr}, 0, 0222,
+ "data", {Qdata}, 0, 0222,
+};
+
+static int
+lptgen(Chan *c, char*, Dirtab *tab, int ntab, int i, Dir *dp)
+{
+ Qid qid;
+
+ if(i == DEVDOTDOT){
+ mkqid(&qid, Qdir, 0, QTDIR);
+ devdir(c, qid, ".", 0, eve, 0555, dp);
+ return 1;
+ }
+ i++; /* skip first element for . itself */
+ if(tab==0 || i>=ntab)
+ return -1;
+ tab += i;
+ qid = tab->qid;
+ qid.path &= ~Qdir;
+ if(qid.path < Qdata)
+ qid.path += lptbase[c->dev];
+ qid.vers = c->dev;
+ snprint(up->genbuf, sizeof up->genbuf, "lpt%lud%s", c->dev+1, tab->name);
+ devdir(c, qid, up->genbuf, tab->length, eve, tab->perm, dp);
+ return 1;
+}
+
+static Chan*
+lptattach(char *spec)
+{
+ Chan *c;
+ int i = (spec && *spec) ? strtol(spec, 0, 0) : 1;
+ char name[8];
+ static int set;
+
+ if(!set){
+ outb(lptbase[i-1]+Qpcr, 0); /* turn off interrupts */
+ set = 1;
+ intrenable(IrqLPT, lptintr, 0, BUSUNKNOWN, "lpt");
+ }
+ if(i < 1 || i > NDEV)
+ error(Ebadarg);
+ if(lptallocd[i-1] == 0){
+ int ecr;
+ snprint(name, sizeof name, "lpt%d", i-1);
+ if(ioalloc(lptbase[i-1], 3, 0, name) < 0)
+ error("lpt port space in use");
+ lptallocd[i-1] = 1;
+ /* Detect ECP - if found, put into PS/2 mode to suit style of driver */
+ ecr = lptbase[i-1] + 0x402;
+ if ((inb(ecr) & 3) == 1) {
+ outb(ecr, 0x34);
+ if (inb(ecr) == 0x35) {
+ outb(ecr, (inb(ecr) & 0x1f) | (1 << 5));
+ if(ioalloc(ecr, 1, 0, name) < 0)
+ error("lpt ecr port space in use");
+ }
+ }
+ }
+ c = devattach('L', spec);
+ c->qid.path = Qdir;
+ c->dev = i-1;
+ return c;
+}
+
+static Walkqid*
+lptwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, lptdir, nelem(lptdir), lptgen);
+}
+
+static int
+lptstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, lptdir, nelem(lptdir), lptgen);
+}
+
+static Chan*
+lptopen(Chan *c, int omode)
+{
+ return devopen(c, omode, lptdir, nelem(lptdir), lptgen);
+}
+
+static void
+lptclose(Chan *)
+{
+}
+
+static long
+lptread(Chan *c, void *a, long n, vlong)
+{
+ char str[16];
+ int size;
+ ulong o;
+
+ if(c->qid.path == Qdir)
+ return devdirread(c, a, n, lptdir, nelem(lptdir), lptgen);
+ size = snprint(str, sizeof str, "0x%2.2ux\n", inb(c->qid.path));
+ o = c->offset;
+ if(o >= size)
+ return 0;
+ if(o+n > size)
+ n = size-c->offset;
+ memmove(a, str+o, n);
+ return n;
+}
+
+static long
+lptwrite(Chan *c, void *a, long n, vlong)
+{
+ char str[16], *p;
+ long base, k;
+
+ if(n <= 0)
+ return 0;
+ if(c->qid.path != Qdata){
+ if(n > sizeof str-1)
+ n = sizeof str-1;
+ memmove(str, a, n);
+ str[n] = 0;
+ outb(c->qid.path, strtoul(str, 0, 0));
+ return n;
+ }
+ p = a;
+ k = n;
+ base = lptbase[c->dev];
+ if(waserror()){
+ outb(base+Qpcr, Finitbar);
+ nexterror();
+ }
+ while(--k >= 0)
+ outch(base, *p++);
+ poperror();
+ return n;
+}
+
+static void
+outch(int base, int c)
+{
+ int status, tries;
+
+ for(tries=0;; tries++) {
+ status = inb(base+Qpsr);
+ if(status&Fnotbusy)
+ break;
+ if((status&Fpe)==0 && (status&(Fselect|Fnoerror)) != (Fselect|Fnoerror))
+ error(Eio);
+ outb(base+Qpcr, Finitbar|Fie);
+ tsleep(&lptrendez, lptready, (void *)base, 100);
+ }
+ outb(base+Qdlr, c);
+ outb(base+Qpcr, Finitbar|Fstrobe);
+ outb(base+Qpcr, Finitbar);
+}
+
+static int
+lptready(void *base)
+{
+ return inb((int)base+Qpsr)&Fnotbusy;
+}
+
+static void
+lptintr(Ureg *, void *)
+{
+ wakeup(&lptrendez);
+}
+
+Dev lptdevtab = {
+ 'L',
+ "lpt",
+
+ devreset,
+ devinit,
+ devshutdown,
+ lptattach,
+ lptwalk,
+ lptstat,
+ lptopen,
+ devcreate,
+ lptclose,
+ lptread,
+ devbread,
+ lptwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/pc/devpccard.c b/sys/src/9/pc/devpccard.c
new file mode 100755
index 000000000..cd7321de9
--- /dev/null
+++ b/sys/src/9/pc/devpccard.c
@@ -0,0 +1,1918 @@
+/*
+ cardbus and pcmcia (grmph) support.
+*/
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+#define DEBUG 0
+
+#pragma varargck type "T" int
+
+#define MAP(x,o) (Rmap + (x)*0x8 + o)
+
+enum {
+ TI_vid = 0x104c,
+ TI_1131_did = 0xAC15,
+ TI_1250_did = 0xAC16,
+ TI_1450_did = 0xAC1B,
+ TI_1251A_did = 0xAC1D,
+ TI_1420_did = 0xAC51,
+
+ Ricoh_vid = 0x1180,
+ Ricoh_475_did = 0x0475,
+ Ricoh_476_did = 0x0476,
+ Ricoh_478_did = 0x0478,
+
+ O2_vid = 0x1217,
+ O2_OZ711M3_did = 0x7134,
+
+ Nslots = 4, /* Maximum number of CardBus slots to use */
+
+ K = 1024,
+ M = K * K,
+
+ LegacyAddr = 0x3e0,
+ NUMEVENTS = 10,
+
+ TI1131xSC = 0x80, /* system control */
+ TI122X_SC_INTRTIE = 1 << 29,
+ TI12xxIM = 0x8c, /* */
+ TI1131xCC = 0x91, /* card control */
+ TI113X_CC_RIENB = 1 << 7,
+ TI113X_CC_ZVENABLE = 1 << 6,
+ TI113X_CC_PCI_IRQ_ENA = 1 << 5,
+ TI113X_CC_PCI_IREQ = 1 << 4,
+ TI113X_CC_PCI_CSC = 1 << 3,
+ TI113X_CC_SPKROUTEN = 1 << 1,
+ TI113X_CC_IFG = 1 << 0,
+ TI1131xDC = 0x92, /* device control */
+};
+
+typedef struct Variant Variant;
+struct Variant {
+ ushort vid;
+ ushort did;
+ char *name;
+};
+
+static Variant variant[] = {
+{ Ricoh_vid, Ricoh_475_did, "Ricoh 475 PCI/Cardbus bridge", },
+{ Ricoh_vid, Ricoh_476_did, "Ricoh 476 PCI/Cardbus bridge", },
+{ Ricoh_vid, Ricoh_478_did, "Ricoh 478 PCI/Cardbus bridge", },
+{ TI_vid, TI_1131_did, "TI PCI-1131 Cardbus Controller", },
+{ TI_vid, TI_1250_did, "TI PCI-1250 Cardbus Controller", },
+{ TI_vid, TI_1450_did, "TI PCI-1450 Cardbus Controller", },
+{ TI_vid, TI_1251A_did, "TI PCI-1251A Cardbus Controller", },
+{ TI_vid, TI_1420_did, "TI PCI-1420 Cardbus Controller", },
+{ O2_vid, O2_OZ711M3_did, "O2Micro OZ711M3 MemoryCardBus", },
+};
+
+/* Cardbus registers */
+enum {
+ SocketEvent = 0,
+ SE_CCD = 3 << 1,
+ SE_POWER = 1 << 3,
+ SocketMask = 1,
+ SocketState = 2,
+ SS_CCD = 3 << 1,
+ SS_POWER = 1 << 3,
+ SS_PC16 = 1 << 4,
+ SS_CBC = 1 << 5,
+ SS_NOTCARD = 1 << 7,
+ SS_BADVCC = 1 << 9,
+ SS_5V = 1 << 10,
+ SS_3V = 1 << 11,
+ SocketForce = 3,
+ SocketControl = 4,
+ SC_5V = 0x22,
+ SC_3V = 0x33,
+};
+
+enum {
+ PciPCR_IO = 1 << 0,
+ PciPCR_MEM = 1 << 1,
+ PciPCR_Master = 1 << 2,
+
+ PciPMC = 0xa4,
+
+ Nbars = 6,
+ Ncmd = 10,
+ CBIRQ = 9,
+
+ PC16,
+ PC32,
+};
+
+enum {
+ Ti82365,
+ Tpd6710,
+ Tpd6720,
+ Tvg46x,
+};
+
+/*
+ * Intel 82365SL PCIC controller for the PCMCIA or
+ * Cirrus Logic PD6710/PD6720 which is mostly register compatible
+ */
+enum
+{
+ /*
+ * registers indices
+ */
+ Rid= 0x0, /* identification and revision */
+ Ris= 0x1, /* interface status */
+ Rpc= 0x2, /* power control */
+ Foutena= (1<<7), /* output enable */
+ Fautopower= (1<<5), /* automatic power switching */
+ Fcardena= (1<<4), /* PC card enable */
+ Rigc= 0x3, /* interrupt and general control */
+ Fiocard= (1<<5), /* I/O card (vs memory) */
+ Fnotreset= (1<<6), /* reset if not set */
+ FSMIena= (1<<4), /* enable change interrupt on SMI */
+ Rcsc= 0x4, /* card status change */
+ Rcscic= 0x5, /* card status change interrupt config */
+ Fchangeena= (1<<3), /* card changed */
+ Fbwarnena= (1<<1), /* card battery warning */
+ Fbdeadena= (1<<0), /* card battery dead */
+ Rwe= 0x6, /* address window enable */
+ Fmem16= (1<<5), /* use A23-A12 to decode address */
+ Rio= 0x7, /* I/O control */
+ Fwidth16= (1<<0), /* 16 bit data width */
+ Fiocs16= (1<<1), /* IOCS16 determines data width */
+ Fzerows= (1<<2), /* zero wait state */
+ Ftiming= (1<<3), /* timing register to use */
+ Riobtm0lo= 0x8, /* I/O address 0 start low byte */
+ Riobtm0hi= 0x9, /* I/O address 0 start high byte */
+ Riotop0lo= 0xa, /* I/O address 0 stop low byte */
+ Riotop0hi= 0xb, /* I/O address 0 stop high byte */
+ Riobtm1lo= 0xc, /* I/O address 1 start low byte */
+ Riobtm1hi= 0xd, /* I/O address 1 start high byte */
+ Riotop1lo= 0xe, /* I/O address 1 stop low byte */
+ Riotop1hi= 0xf, /* I/O address 1 stop high byte */
+ Rmap= 0x10, /* map 0 */
+
+ /*
+ * CL-PD67xx extension registers
+ */
+ Rmisc1= 0x16, /* misc control 1 */
+ F5Vdetect= (1<<0),
+ Fvcc3V= (1<<1),
+ Fpmint= (1<<2),
+ Fpsirq= (1<<3),
+ Fspeaker= (1<<4),
+ Finpack= (1<<7),
+ Rfifo= 0x17, /* fifo control */
+ Fflush= (1<<7), /* flush fifo */
+ Rmisc2= 0x1E, /* misc control 2 */
+ Flowpow= (1<<1), /* low power mode */
+ Rchipinfo= 0x1F, /* chip information */
+ Ratactl= 0x26, /* ATA control */
+
+ /*
+ * offsets into the system memory address maps
+ */
+ Mbtmlo= 0x0, /* System mem addr mapping start low byte */
+ Mbtmhi= 0x1, /* System mem addr mapping start high byte */
+ F16bit= (1<<7), /* 16-bit wide data path */
+ Mtoplo= 0x2, /* System mem addr mapping stop low byte */
+ Mtophi= 0x3, /* System mem addr mapping stop high byte */
+ Ftimer1= (1<<6), /* timer set 1 */
+ Mofflo= 0x4, /* Card memory offset address low byte */
+ Moffhi= 0x5, /* Card memory offset address high byte */
+ Fregactive= (1<<6), /* attribute memory */
+
+ /*
+ * configuration registers - they start at an offset in attribute
+ * memory found in the CIS.
+ */
+ Rconfig= 0,
+ Creset= (1<<7), /* reset device */
+ Clevel= (1<<6), /* level sensitive interrupt line */
+};
+
+/*
+ * read and crack the card information structure enough to set
+ * important parameters like power
+ */
+/* cis memory walking */
+typedef struct Cisdat Cisdat;
+struct Cisdat {
+ uchar *cisbase;
+ int cispos;
+ int cisskip;
+ int cislen;
+};
+
+typedef struct Pcminfo Pcminfo;
+struct Pcminfo {
+ char verstr[512]; /* Version string */
+ PCMmap mmap[4]; /* maps, last is always for the kernel */
+ ulong conf_addr; /* Config address */
+ uchar conf_present; /* Config register present */
+ int nctab; /* In use configuration tables */
+ PCMconftab ctab[8]; /* Configuration tables */
+ PCMconftab *defctab; /* Default conftab */
+
+ int port; /* Actual port usage */
+ int irq; /* Actual IRQ usage */
+};
+
+typedef struct Cardbus Cardbus;
+struct Cardbus {
+ Lock;
+ Variant *variant; /* Which CardBus chipset */
+ Pcidev *pci; /* The bridge itself */
+ ulong *regs; /* Cardbus registers */
+ int ltype; /* Legacy type */
+ int lindex; /* Legacy port index address */
+ int ldata; /* Legacy port data address */
+ int lbase; /* Base register for this socket */
+
+ int state; /* Current state of card */
+ int type; /* Type of card */
+ Pcminfo linfo; /* PCMCIA slot info */
+
+ int special; /* card is allocated to a driver */
+
+ int refs; /* Number of refs to slot */
+ Lock refslock; /* inc/dev ref lock */
+};
+
+static int managerstarted;
+
+enum {
+ Mshift= 12,
+ Mgran= (1<<Mshift), /* granularity of maps */
+ Mmask= ~(Mgran-1), /* mask for address bits important to the chip */
+};
+
+static Cardbus cbslots[Nslots];
+static int nslots;
+
+static ulong exponent[8] = {
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
+};
+
+static ulong vmant[16] = {
+ 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
+};
+
+static ulong mantissa[16] = {
+ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80,
+};
+
+static char Enocard[] = "No card in slot";
+
+enum
+{
+ CMdown,
+ CMpower,
+};
+
+static Cmdtab pccardctlmsg[] =
+{
+ CMdown, "down", 2,
+ CMpower, "power", 1,
+};
+
+static int powerup(Cardbus *);
+static void configure(Cardbus *);
+static void powerdown(Cardbus *cb);
+static void unconfigure(Cardbus *cb);
+
+static void i82365probe(Cardbus *cb, int lindex, int ldata);
+static void i82365configure(Cardbus *cb);
+static PCMmap *isamap(Cardbus *cb, ulong offset, int len, int attr);
+static void isaunmap(PCMmap* m);
+static uchar rdreg(Cardbus *cb, int index);
+static void wrreg(Cardbus *cb, int index, uchar val);
+static int readc(Cisdat *cis, uchar *x);
+static void tvers1(Cardbus *cb, Cisdat *cis, int );
+static void tcfig(Cardbus *cb, Cisdat *cis, int );
+static void tentry(Cardbus *cb, Cisdat *cis, int );
+static int vcode(int volt);
+static int pccard_pcmspecial(char *idstr, ISAConf *isa);
+static void pccard_pcmspecialclose(int slotno);
+
+enum {
+ CardDetected,
+ CardPowered,
+ CardEjected,
+ CardConfigured,
+};
+
+static char *messages[] = {
+[CardDetected] "CardDetected",
+[CardPowered] "CardPowered",
+[CardEjected] "CardEjected",
+[CardConfigured] "CardConfigured",
+};
+
+enum {
+ SlotEmpty,
+ SlotFull,
+ SlotPowered,
+ SlotConfigured,
+};
+
+static char *states[] = {
+[SlotEmpty] "SlotEmpty",
+[SlotFull] "SlotFull",
+[SlotPowered] "SlotPowered",
+[SlotConfigured] "SlotConfigured",
+};
+
+static void
+engine(Cardbus *cb, int message)
+{
+ if(DEBUG)
+ print("engine(%ld): %s(%s)\n", cb - cbslots,
+ states[cb->state], messages[message]);
+ switch (cb->state) {
+ case SlotEmpty:
+
+ switch (message) {
+ case CardDetected:
+ cb->state = SlotFull;
+ powerup(cb);
+ break;
+ case CardEjected:
+ break;
+ default:
+ if(DEBUG)
+ print("#Y%ld: Invalid message %s in SlotEmpty state\n",
+ cb - cbslots, messages[message]);
+ break;
+ }
+ break;
+
+ case SlotFull:
+
+ switch (message) {
+ case CardPowered:
+ cb->state = SlotPowered;
+ configure(cb);
+ break;
+ case CardEjected:
+ cb->state = SlotEmpty;
+ powerdown(cb);
+ break;
+ default:
+ if(DEBUG)
+ print("#Y%ld: Invalid message %s in SlotFull state\n",
+ cb - cbslots, messages[message]);
+ break;
+ }
+ break;
+
+ case SlotPowered:
+
+ switch (message) {
+ case CardConfigured:
+ cb->state = SlotConfigured;
+ break;
+ case CardEjected:
+ cb->state = SlotEmpty;
+ unconfigure(cb);
+ powerdown(cb);
+ break;
+ default:
+ print("#Y%ld: Invalid message %s in SlotPowered state\n",
+ cb - cbslots, messages[message]);
+ break;
+ }
+ break;
+
+ case SlotConfigured:
+
+ switch (message) {
+ case CardEjected:
+ cb->state = SlotEmpty;
+ unconfigure(cb);
+ powerdown(cb);
+ break;
+ default:
+ if(DEBUG)
+ print("#Y%ld: Invalid message %s in SlotConfigured state\n",
+ cb - cbslots, messages[message]);
+ break;
+ }
+ break;
+ }
+}
+
+static void
+qengine(Cardbus *cb, int message)
+{
+ lock(cb);
+ engine(cb, message);
+ unlock(cb);
+}
+
+typedef struct Events Events;
+struct Events {
+ Cardbus *cb;
+ int message;
+};
+
+static Lock levents;
+static Events events[NUMEVENTS];
+static Rendez revents;
+static int nevents;
+
+static void
+iengine(Cardbus *cb, int message)
+{
+ if (nevents >= NUMEVENTS) {
+ print("#Y: Too many events queued, discarding request\n");
+ return;
+ }
+ ilock(&levents);
+ events[nevents].cb = cb;
+ events[nevents].message = message;
+ nevents++;
+ iunlock(&levents);
+ wakeup(&revents);
+}
+
+static int
+eventoccured(void)
+{
+ return nevents > 0;
+}
+
+static void
+processevents(void *)
+{
+ while (1) {
+ int message;
+ Cardbus *cb;
+
+ sleep(&revents, (int (*)(void *))eventoccured, nil);
+
+ cb = nil;
+ message = 0;
+ ilock(&levents);
+ if (nevents > 0) {
+ cb = events[0].cb;
+ message = events[0].message;
+ nevents--;
+ if (nevents > 0)
+ memmove(events, &events[1], nevents * sizeof(Events));
+ }
+ iunlock(&levents);
+
+ if (cb)
+ qengine(cb, message);
+ }
+}
+
+static void
+cbinterrupt(Ureg *, void *)
+{
+ int i;
+
+ for (i = 0; i != nslots; i++) {
+ Cardbus *cb = &cbslots[i];
+ ulong event, state;
+
+ event = cb->regs[SocketEvent];
+ if(!(event & (SE_POWER|SE_CCD)))
+ continue;
+ state = cb->regs[SocketState];
+ rdreg(cb, Rcsc); /* Ack the interrupt */
+
+ if(DEBUG)
+ print("#Y%ld: interrupt: event %.8lX, state %.8lX, (%s)\n",
+ cb - cbslots, event, state, states[cb->state]);
+
+ if (event & SE_CCD) {
+ cb->regs[SocketEvent] |= SE_CCD; /* Ack interrupt */
+ if (state & SE_CCD) {
+ if (cb->state != SlotEmpty) {
+ print("#Y: take cardejected interrupt\n");
+ iengine(cb, CardEjected);
+ }
+ }
+ else
+ iengine(cb, CardDetected);
+ }
+
+ if (event & SE_POWER) {
+ cb->regs[SocketEvent] |= SE_POWER; /* Ack interrupt */
+ iengine(cb, CardPowered);
+ }
+ }
+}
+
+void
+devpccardlink(void)
+{
+ static int initialized;
+ Pcidev *pci;
+ int i;
+ uchar intl;
+ char *p;
+ void *baddrva;
+
+ if (initialized)
+ return;
+ initialized = 1;
+
+ if((p=getconf("pccard0")) && strncmp(p, "disabled", 8)==0)
+ return;
+
+ if(_pcmspecial)
+ return;
+
+ /* Allocate legacy space */
+ if (ioalloc(LegacyAddr, 2, 0, "i82365.0") < 0)
+ print("#Y: WARNING: Cannot allocate legacy ports\n");
+
+ /* Find all CardBus controllers */
+ pci = nil;
+ intl = 0xff;
+ while ((pci = pcimatch(pci, 0, 0)) != nil) {
+ ulong baddr;
+ Cardbus *cb;
+ int slot;
+ uchar pin;
+
+ if(pci->ccrb != 6 || pci->ccru != 7)
+ continue;
+ for (i = 0; i != nelem(variant); i++)
+ if (pci->vid == variant[i].vid && pci->did == variant[i].did)
+ break;
+ if (i == nelem(variant))
+ continue;
+
+ /* initialize this slot */
+ slot = nslots++;
+ cb = &cbslots[slot];
+
+ cb->pci = pci;
+ cb->variant = &variant[i];
+
+ if (pci->vid != TI_vid) {
+ /*
+ * Gross hack, needs a fix. Inherit the mappings from
+ * 9load for the TIs (pb)
+ */
+ pcicfgw32(pci, PciCBMBR0, 0xffffffff);
+ pcicfgw32(pci, PciCBMLR0, 0);
+ pcicfgw32(pci, PciCBMBR1, 0xffffffff);
+ pcicfgw32(pci, PciCBMLR1, 0);
+ pcicfgw32(pci, PciCBIBR0, 0xffffffff);
+ pcicfgw32(pci, PciCBILR0, 0);
+ pcicfgw32(pci, PciCBIBR1, 0xffffffff);
+ pcicfgw32(pci, PciCBILR1, 0);
+ }
+
+ /* Set up PCI bus numbers if needed. */
+ if (pcicfgr8(pci, PciSBN) == 0) {
+ static int busbase = 0x20;
+
+ pcicfgw8(pci, PciSBN, busbase);
+ pcicfgw8(pci, PciUBN, busbase + 2);
+ busbase += 3;
+ }
+
+ /* Patch up intl if needed. */
+ if ((pin = pcicfgr8(pci, PciINTP)) != 0 &&
+ (pci->intl == 0xff || pci->intl == 0)) {
+ pci->intl = pciipin(nil, pin);
+ pcicfgw8(pci, PciINTL, pci->intl);
+
+ if (pci->intl == 0xff || pci->intl == 0)
+ print("#Y%ld: No interrupt?\n", cb - cbslots);
+ }
+
+ /* Don't you love standards! */
+ if (pci->vid == TI_vid) {
+ if (pci->did <= TI_1131_did) {
+ uchar cc;
+
+ cc = pcicfgr8(pci, TI1131xCC);
+ cc &= ~(TI113X_CC_PCI_IRQ_ENA |
+ TI113X_CC_PCI_IREQ |
+ TI113X_CC_PCI_CSC |
+ TI113X_CC_ZVENABLE);
+ cc |= TI113X_CC_PCI_IRQ_ENA |
+ TI113X_CC_PCI_IREQ |
+ TI113X_CC_SPKROUTEN;
+ pcicfgw8(pci, TI1131xCC, cc);
+
+ /* PCI interrupts only */
+ pcicfgw8(pci, TI1131xDC,
+ pcicfgr8(pci, TI1131xDC) & ~6);
+
+ /* CSC ints to PCI bus. */
+ wrreg(cb, Rigc, rdreg(cb, Rigc) | 0x10);
+ }
+ else if (pci->did == TI_1250_did) {
+ print("No support yet for the TI_1250_did, prod pb\n");
+ }
+ else if (pci->did == TI_1420_did) {
+ /* Disable Vcc protection */
+ pcicfgw32(cb->pci, 0x80,
+ pcicfgr32(cb->pci, 0x80) | (1 << 21));
+ }
+
+ pcicfgw16(cb->pci, PciPMC, pcicfgr16(cb->pci, PciPMC) & ~3);
+ }
+ if (pci->vid == O2_vid) {
+ if(DEBUG)
+ print("writing O2 config\n");
+ pcicfgw8(cb->pci, 0x94, 0xCA);
+ pcicfgw8(cb->pci, 0xD4, 0xCA);
+ }
+
+ if (intl != 0xff && intl != pci->intl)
+ intrenable(pci->intl, cbinterrupt, cb, pci->tbdf, "cardbus");
+ intl = pci->intl;
+
+ if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) {
+ int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;
+
+ baddr = upaalloc(size, size);
+ baddrva = vmap(baddr, size);
+ pcicfgw32(cb->pci, PciBAR0, baddr);
+ cb->regs = (ulong *)baddrva;
+ }
+ else
+ cb->regs = (ulong *)vmap(baddr, 4096);
+ cb->state = SlotEmpty;
+
+ /* Don't really know what to do with this... */
+ i82365probe(cb, LegacyAddr, LegacyAddr + 1);
+
+ print("#Y%ld: %s, %.8ulX intl %d\n", cb - cbslots,
+ variant[i].name, baddr, pci->intl);
+ }
+
+ if (nslots == 0){
+ iofree(LegacyAddr);
+ return;
+ }
+
+ _pcmspecial = pccard_pcmspecial;
+ _pcmspecialclose = pccard_pcmspecialclose;
+
+ for (i = 0; i != nslots; i++) {
+ Cardbus *cb = &cbslots[i];
+
+ if ((cb->regs[SocketState] & SE_CCD) == 0)
+ engine(cb, CardDetected);
+ }
+
+ delay(500); /* Allow time for power up */
+
+ for (i = 0; i != nslots; i++) {
+ Cardbus *cb = &cbslots[i];
+
+ if (cb->regs[SocketState] & SE_POWER)
+ engine(cb, CardPowered);
+
+ /* Ack and enable interrupts on all events */
+ // cb->regs[SocketEvent] = cb->regs[SocketEvent];
+ cb->regs[SocketMask] |= 0xF;
+ wrreg(cb, Rcscic, 0xC);
+ }
+}
+
+static int
+powerup(Cardbus *cb)
+{
+ ulong state;
+ ushort bcr;
+
+ state = cb->regs[SocketState];
+ if (state & SS_PC16) {
+ if(DEBUG)
+ print("#Y%ld: Probed a PC16 card, powering up card\n",
+ cb - cbslots);
+ cb->type = PC16;
+ memset(&cb->linfo, 0, sizeof(Pcminfo));
+
+ /* power up and unreset, wait's are empirical (???) */
+ wrreg(cb, Rpc, Fautopower|Foutena|Fcardena);
+ delay(300);
+ wrreg(cb, Rigc, 0);
+ delay(100);
+ wrreg(cb, Rigc, Fnotreset);
+ delay(500);
+
+// return 1;
+ }
+
+ if (state & SS_CCD)
+ return 0;
+
+ if (state & SS_NOTCARD) {
+ print("#Y%ld: No card inserted\n", cb - cbslots);
+ return 0;
+ }
+
+ if ((state & SS_3V) == 0 && (state & SS_5V) == 0) {
+ print("#Y%ld: Unsupported voltage, powering down card!\n",
+ cb - cbslots);
+ cb->regs[SocketControl] = 0;
+ return 0;
+ }
+
+ if(DEBUG)
+ print("#Y%ld: card %spowered at %d volt\n", cb - cbslots,
+ (state & SS_POWER)? "": "not ",
+ (state & SS_3V)? 3: (state & SS_5V)? 5: -1);
+
+ /* Power up the card
+ * and make sure the secondary bus is not in reset.
+ */
+ cb->regs[SocketControl] = (state & SS_5V)? SC_5V: SC_3V;
+ delay(50);
+ bcr = pcicfgr16(cb->pci, PciBCR);
+ bcr &= ~0x40;
+ pcicfgw16(cb->pci, PciBCR, bcr);
+ delay(100);
+
+ if (state & SS_PC16)
+ cb->type = PC16;
+ else
+ cb->type = PC32;
+
+ return 1;
+}
+
+static void
+powerdown(Cardbus *cb)
+{
+ ushort bcr;
+
+ if (cb->type == PC16) {
+
+ wrreg(cb, Rpc, 0); /* turn off card power */
+ wrreg(cb, Rwe, 0); /* no windows */
+
+ cb->type = -1;
+ return;
+ }
+
+ bcr = pcicfgr16(cb->pci, PciBCR);
+ bcr |= 0x40;
+ pcicfgw16(cb->pci, PciBCR, bcr);
+ cb->regs[SocketControl] = 0;
+ cb->type = -1;
+}
+
+static void
+configure(Cardbus *cb)
+{
+ int i, r;
+ ulong size, bar;
+ Pcidev *pci;
+ ulong membase, iobase, memlen, iolen, rombase, romlen;
+
+ if(DEBUG)
+ print("configuring slot %ld (%s)\n", cb - cbslots, states[cb->state]);
+ if (cb->state == SlotConfigured)
+ return;
+ engine(cb, CardConfigured);
+
+ delay(50); /* Emperically established */
+
+ if (cb->type == PC16) {
+ i82365configure(cb);
+ return;
+ }
+
+ /* Scan the CardBus for new PCI devices */
+ pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge);
+
+ /*
+ * size the devices on the bus, reserve a minimum for devices arriving later,
+ * allow for ROM space, allocate space, and set the cardbus mapping registers
+ */
+ pcibussize(cb->pci->bridge, &memlen, &iolen); /* TO DO: need initial alignments */
+
+ romlen = 0;
+ for(pci = cb->pci->bridge; pci != nil; pci = pci->list){
+ size = pcibarsize(pci, PciEBAR0);
+ if(size > 0){
+ pci->rom.bar = -1;
+ pci->rom.size = size;
+ romlen += size;
+ }
+ }
+
+ if(iolen < 512)
+ iolen = 512;
+ iobase = ioreserve(~0, iolen, 0, "cardbus");
+ pcicfgw32(cb->pci, PciCBIBR0, iobase);
+ pcicfgw32(cb->pci, PciCBILR0, iobase + iolen-1);
+ pcicfgw32(cb->pci, PciCBIBR1, 0);
+ pcicfgw32(cb->pci, PciCBILR1, 0);
+
+ rombase = memlen;
+ memlen += romlen;
+ if(memlen < 1*1024*1024)
+ memlen = 1*1024*1024;
+ membase = upaalloc(memlen, 4*1024*1024); /* TO DO: better alignment */
+ pcicfgw32(cb->pci, PciCBMBR0, membase);
+ pcicfgw32(cb->pci, PciCBMLR0, membase + memlen-1);
+ pcicfgw32(cb->pci, PciCBMBR1, 0);
+ pcicfgw32(cb->pci, PciCBMLR1, 0);
+
+// pcibussize(cb->pci->bridge, &membase, &iobase); /* now assign them */
+ rombase += membase;
+
+ for(pci = cb->pci->bridge; pci != nil; pci = pci->list){
+ r = pcicfgr16(pci, PciPCR);
+ r &= ~(PciPCR_IO|PciPCR_MEM);
+ pcicfgw16(pci, PciPCR, r);
+
+ /*
+ * Treat the found device as an ordinary PCI card.
+ * It seems that the CIS is not always present in
+ * CardBus cards.
+ * XXX, need to support multifunction cards
+ */
+ for(i = 0; i < Nbars; i++) {
+ if(pci->mem[i].size == 0)
+ continue;
+ bar = pci->mem[i].bar;
+ if(bar & 1)
+ bar += iobase;
+ else
+ bar += membase;
+ pci->mem[i].bar = bar;
+ pcicfgw32(pci, PciBAR0 + 4*i, bar);
+ if((bar & 1) == 0){
+ print("%T mem[%d] %8.8lux %d\n", pci->tbdf, i, bar, pci->mem[i].size);
+ if(bar & 0x80){ /* TO DO: enable prefetch */
+ ;
+ }
+ }
+ }
+ if((size = pcibarsize(pci, PciEBAR0)) > 0) { /* TO DO: can this be done by pci.c? */
+ pci->rom.bar = rombase;
+ pci->rom.size = size;
+ rombase += size;
+ pcicfgw32(pci, PciEBAR0, pci->rom.bar);
+ }
+
+ /* Set the basic PCI registers for the device */
+ pci->pcr = pcicfgr16(pci, PciPCR);
+ pci->pcr |= PciPCR_IO|PciPCR_MEM|PciPCR_Master;
+ pci->cls = 8;
+ pci->ltr = 64;
+ pcicfgw16(pci, PciPCR, pci->pcr);
+ pcicfgw8(pci, PciCLS, pci->cls);
+ pcicfgw8(pci, PciLTR, pci->ltr);
+
+ if (pcicfgr8(pci, PciINTP)) {
+ pci->intl = pcicfgr8(cb->pci, PciINTL);
+ pcicfgw8(pci, PciINTL, pci->intl);
+
+ /* Route interrupts to INTA#/B# */
+ pcicfgw16(cb->pci, PciBCR,
+ pcicfgr16(cb->pci, PciBCR) & ~(1 << 7));
+ }
+ }
+}
+
+static void
+unconfigure(Cardbus *cb)
+{
+ Pcidev *pci;
+ int i, ioindex, memindex, r;
+
+ if (cb->type == PC16) {
+ print("#Y%d: Don't know how to unconfigure a PC16 card\n",
+ (int)(cb - cbslots));
+
+ memset(&cb->linfo, 0, sizeof(Pcminfo));
+ return;
+ }
+
+ pci = cb->pci->bridge;
+ if (pci == nil)
+ return; /* Not configured */
+ cb->pci->bridge = nil;
+
+ memindex = ioindex = 0;
+ while (pci) {
+ Pcidev *_pci;
+
+ for (i = 0; i != Nbars; i++) {
+ if (pci->mem[i].size == 0)
+ continue;
+ if (pci->mem[i].bar & 1) {
+ iofree(pci->mem[i].bar & ~1);
+ pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8,
+ (ushort)-1);
+ pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0);
+ ioindex++;
+ continue;
+ }
+
+ upafree(pci->mem[i].bar & ~0xF, pci->mem[i].size);
+ pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
+ pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
+ r = pcicfgr16(cb->pci, PciBCR);
+ r &= ~(1 << (8 + memindex));
+ pcicfgw16(cb->pci, PciBCR, r);
+ memindex++;
+ }
+
+ if (pci->rom.bar && memindex < 2) {
+ upafree(pci->rom.bar & ~0xF, pci->rom.size);
+ pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
+ pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
+ memindex++;
+ }
+
+ _pci = pci->list;
+ free(_pci);
+ pci = _pci;
+ }
+}
+
+static void
+i82365configure(Cardbus *cb)
+{
+ int this;
+ Cisdat cis;
+ PCMmap *m;
+ uchar type, link;
+
+ /*
+ * Read all tuples in attribute space.
+ */
+ m = isamap(cb, 0, 0, 1);
+ if(m == 0)
+ return;
+
+ cis.cisbase = KADDR(m->isa);
+ cis.cispos = 0;
+ cis.cisskip = 2;
+ cis.cislen = m->len;
+
+ /* loop through all the tuples */
+ for(;;){
+ this = cis.cispos;
+ if(readc(&cis, &type) != 1)
+ break;
+ if(type == 0xFF)
+ break;
+ if(readc(&cis, &link) != 1)
+ break;
+
+ switch(type){
+ default:
+ break;
+ case 0x15:
+ tvers1(cb, &cis, type);
+ break;
+ case 0x1A:
+ tcfig(cb, &cis, type);
+ break;
+ case 0x1B:
+ tentry(cb, &cis, type);
+ break;
+ }
+
+ if(link == 0xFF)
+ break;
+ cis.cispos = this + (2+link);
+ }
+ isaunmap(m);
+}
+
+/*
+ * look for a card whose version contains 'idstr'
+ */
+static int
+pccard_pcmspecial(char *idstr, ISAConf *isa)
+{
+ int i, irq;
+ PCMconftab *ct, *et;
+ Pcminfo *pi;
+ Cardbus *cb;
+ uchar x, we, *p;
+
+ cb = nil;
+ for (i = 0; i != nslots; i++) {
+ cb = &cbslots[i];
+
+ lock(cb);
+ if (cb->state == SlotConfigured &&
+ cb->type == PC16 &&
+ !cb->special &&
+ strstr(cb->linfo.verstr, idstr))
+ break;
+ unlock(cb);
+ }
+
+ if (i == nslots) {
+ if(0 && DEBUG)
+ print("#Y: %s not found\n", idstr);
+ return -1;
+ }
+
+ pi = &cb->linfo;
+
+ /*
+ * configure the PCMslot for IO. We assume very heavily that we can read
+ * configuration info from the CIS. If not, we won't set up correctly.
+ */
+ irq = isa->irq;
+ if(irq == 2)
+ irq = 9;
+
+ et = &pi->ctab[pi->nctab];
+ ct = nil;
+ for(i = 0; i < isa->nopt; i++){
+ int index;
+ char *cp;
+
+ if(strncmp(isa->opt[i], "index=", 6))
+ continue;
+ index = strtol(&isa->opt[i][6], &cp, 0);
+ if(cp == &isa->opt[i][6] || index >= pi->nctab) {
+ unlock(cb);
+ print("#Y%d: Cannot find index %d in conf table\n",
+ (int)(cb - cbslots), index);
+ return -1;
+ }
+ ct = &pi->ctab[index];
+ }
+
+ if(ct == nil){
+ PCMconftab *t;
+
+ /* assume default is right */
+ if(pi->defctab)
+ ct = pi->defctab;
+ else
+ ct = pi->ctab;
+
+ /* try for best match */
+ if(ct->nio == 0
+ || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
+ for(t = pi->ctab; t < et; t++)
+ if(t->nio
+ && t->io[0].start == isa->port
+ && ((1<<irq) & t->irqs)){
+ ct = t;
+ break;
+ }
+ }
+ if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
+ for(t = pi->ctab; t < et; t++)
+ if(t->nio && ((1<<irq) & t->irqs)){
+ ct = t;
+ break;
+ }
+ }
+ if(ct->nio == 0){
+ for(t = pi->ctab; t < et; t++)
+ if(t->nio){
+ ct = t;
+ break;
+ }
+ }
+ }
+
+ if(ct == et || ct->nio == 0) {
+ unlock(cb);
+ print("#Y%d: No configuration?\n", (int)(cb - cbslots));
+ return -1;
+ }
+ if(isa->port == 0 && ct->io[0].start == 0) {
+ unlock(cb);
+ print("#Y%d: No part or start address\n", (int)(cb - cbslots));
+ return -1;
+ }
+
+ cb->special = 1; /* taken */
+
+ /* route interrupts */
+ isa->irq = irq;
+ wrreg(cb, Rigc, irq | Fnotreset | Fiocard);
+
+ /* set power and enable device */
+ x = vcode(ct->vpp1);
+ wrreg(cb, Rpc, x|Fautopower|Foutena|Fcardena);
+
+ /* 16-bit data path */
+ if(ct->bit16)
+ x = Ftiming|Fiocs16|Fwidth16;
+ else
+ x = Ftiming;
+ if(ct->nio == 2 && ct->io[1].start)
+ x |= x<<4;
+ wrreg(cb, Rio, x);
+
+ /*
+ * enable io port map 0
+ * the 'top' register value includes the last valid address
+ */
+ if(isa->port == 0)
+ isa->port = ct->io[0].start;
+ we = rdreg(cb, Rwe);
+ wrreg(cb, Riobtm0lo, isa->port);
+ wrreg(cb, Riobtm0hi, isa->port>>8);
+ i = isa->port+ct->io[0].len-1;
+ wrreg(cb, Riotop0lo, i);
+ wrreg(cb, Riotop0hi, i>>8);
+ we |= 1<<6;
+ if(ct->nio == 2 && ct->io[1].start){
+ wrreg(cb, Riobtm1lo, ct->io[1].start);
+ wrreg(cb, Riobtm1hi, ct->io[1].start>>8);
+ i = ct->io[1].start+ct->io[1].len-1;
+ wrreg(cb, Riotop1lo, i);
+ wrreg(cb, Riotop1hi, i>>8);
+ we |= 1<<7;
+ }
+ wrreg(cb, Rwe, we);
+
+ /* only touch Rconfig if it is present */
+ if(pi->conf_present & (1<<Rconfig)){
+ PCMmap *m;
+
+ /* Reset adapter */
+ m = isamap(cb, pi->conf_addr + Rconfig, 1, 1);
+ p = KADDR(m->isa + pi->conf_addr + Rconfig - m->ca);
+
+ /* set configuration and interrupt type */
+ x = ct->index;
+ if(ct->irqtype & 0x20)
+ x |= Clevel;
+ *p = x;
+ delay(5);
+
+ isaunmap(m);
+ }
+
+ pi->port = isa->port;
+ pi->irq = isa->irq;
+ unlock(cb);
+
+ print("#Y%ld: %s irq %d, port %lX\n", cb - cbslots, pi->verstr, isa->irq, isa->port);
+ return (int)(cb - cbslots);
+}
+
+static void
+pccard_pcmspecialclose(int slotno)
+{
+ Cardbus *cb = &cbslots[slotno];
+
+ wrreg(cb, Rwe, 0); /* no windows */
+ cb->special = 0;
+}
+
+static Chan*
+pccardattach(char *spec)
+{
+ if (!managerstarted) {
+ managerstarted = 1;
+ kproc("cardbus", processevents, nil);
+ }
+ return devattach('Y', spec);
+}
+
+enum
+{
+ Qdir,
+ Qctl,
+
+ Nents = 1,
+};
+
+#define SLOTNO(c) ((ulong)((c->qid.path>>8)&0xff))
+#define TYPE(c) ((ulong)(c->qid.path&0xff))
+#define QID(s,t) (((s)<<8)|(t))
+
+static int
+pccardgen(Chan *c, char*, Dirtab *, int , int i, Dir *dp)
+{
+ int slotno;
+ Qid qid;
+ long len;
+ int entry;
+
+ if(i == DEVDOTDOT){
+ mkqid(&qid, Qdir, 0, QTDIR);
+ devdir(c, qid, "#Y", 0, eve, 0555, dp);
+ return 1;
+ }
+
+ len = 0;
+ if(i >= Nents * nslots) return -1;
+ slotno = i / Nents;
+ entry = i % Nents;
+ if (entry == 0) {
+ qid.path = QID(slotno, Qctl);
+ snprint(up->genbuf, sizeof up->genbuf, "cb%dctl", slotno);
+ }
+ else {
+ /* Entries for memory regions. I'll implement them when
+ needed. (pb) */
+ }
+ qid.vers = 0;
+ qid.type = QTFILE;
+ devdir(c, qid, up->genbuf, len, eve, 0660, dp);
+ return 1;
+}
+
+static Walkqid*
+pccardwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, 0, 0, pccardgen);
+}
+
+static int
+pccardstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, 0, 0, pccardgen);
+}
+
+static void
+increfp(Cardbus *cb)
+{
+ lock(&cb->refslock);
+ cb->refs++;
+ unlock(&cb->refslock);
+}
+
+static void
+decrefp(Cardbus *cb)
+{
+ lock(&cb->refslock);
+ cb->refs--;
+ unlock(&cb->refslock);
+}
+
+static Chan*
+pccardopen(Chan *c, int omode)
+{
+ if (c->qid.type & QTDIR){
+ if(omode != OREAD)
+ error(Eperm);
+ } else
+ increfp(&cbslots[SLOTNO(c)]);
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+static void
+pccardclose(Chan *c)
+{
+ if(c->flag & COPEN)
+ if((c->qid.type & QTDIR) == 0)
+ decrefp(&cbslots[SLOTNO(c)]);
+}
+
+static long
+pccardread(Chan *c, void *a, long n, vlong offset)
+{
+ Cardbus *cb;
+ char *buf, *p, *e;
+ int i;
+
+ switch(TYPE(c)){
+ case Qdir:
+ return devdirread(c, a, n, 0, 0, pccardgen);
+
+ case Qctl:
+ buf = p = malloc(READSTR);
+ buf[0] = 0;
+ e = p + READSTR;
+
+ cb = &cbslots[SLOTNO(c)];
+ lock(cb);
+ p = seprint(p, e, "slot %ld: %s; ", cb - cbslots, states[cb->state]);
+
+ switch (cb->type) {
+ case -1:
+ seprint(p, e, "\n");
+ break;
+
+ case PC32:
+ if (cb->pci->bridge) {
+ Pcidev *pci = cb->pci->bridge;
+ int i;
+
+ while (pci) {
+ p = seprint(p, e, "%.4uX %.4uX; irq %d\n",
+ pci->vid, pci->did, pci->intl);
+ for (i = 0; i != Nbars; i++)
+ if (pci->mem[i].size)
+ p = seprint(p, e,
+ "\tmem[%d] %.8ulX (%.8uX)\n",
+ i, pci->mem[i].bar,
+ pci->mem[i].size);
+ if (pci->rom.size)
+ p = seprint(p, e, "\tROM %.8ulX (%.8uX)\n",
+ pci->rom.bar, pci->rom.size);
+ pci = pci->list;
+ }
+ }
+ break;
+
+ case PC16:
+ if (cb->state == SlotConfigured) {
+ Pcminfo *pi = &cb->linfo;
+
+ p = seprint(p, e, "%s port %X; irq %d;\n",
+ pi->verstr, pi->port,
+ pi->irq);
+ for (i = 0; i != pi->nctab; i++) {
+ PCMconftab *ct;
+ int j;
+
+ ct = &pi->ctab[i];
+ p = seprint(p, e,
+ "\tconfiguration[%d] irqs %.4uX; vpp %d, %d; %s\n",
+ i, ct->irqs, ct->vpp1, ct->vpp2,
+ (ct == pi->defctab)? "(default);": "");
+ for (j = 0; j != ct->nio; j++)
+ if (ct->io[j].len > 0)
+ p = seprint(p, e, "\t\tio[%d] %.8ulX %uld\n",
+ j, ct->io[j].start, ct->io[j].len);
+ }
+ }
+ break;
+ }
+ unlock(cb);
+
+ n = readstr(offset, a, n, buf);
+ free(buf);
+ return n;
+ }
+ return 0;
+}
+
+static long
+pccardwrite(Chan *c, void *v, long n, vlong)
+{
+ Rune r;
+ ulong n0;
+ char *device;
+ Cmdbuf *cbf;
+ Cmdtab *ct;
+ Cardbus *cb;
+
+ n0 = n;
+ switch(TYPE(c)){
+ case Qctl:
+ cb = &cbslots[SLOTNO(c)];
+
+ cbf = parsecmd(v, n);
+ if(waserror()){
+ free(cbf);
+ nexterror();
+ }
+ ct = lookupcmd(cbf, pccardctlmsg, nelem(pccardctlmsg));
+ switch(ct->index){
+ case CMdown:
+ device = cbf->f[1];
+ device += chartorune(&r, device);
+ if ((n = devno(r, 1)) >= 0 && devtab[n]->config)
+ devtab[n]->config(0, device, nil);
+ qengine(cb, CardEjected);
+ break;
+ case CMpower:
+ if ((cb->regs[SocketState] & SS_CCD) == 0)
+ qengine(cb, CardDetected);
+ break;
+ }
+ poperror();
+ free(cbf);
+ break;
+ }
+ return n0 - n;
+}
+
+Dev pccarddevtab = {
+ 'Y',
+ "cardbus",
+
+ devreset,
+ devinit,
+ devshutdown,
+ pccardattach,
+ pccardwalk,
+ pccardstat,
+ pccardopen,
+ devcreate,
+ pccardclose,
+ pccardread,
+ devbread,
+ pccardwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+static PCMmap *
+isamap(Cardbus *cb, ulong offset, int len, int attr)
+{
+ uchar we, bit;
+ PCMmap *m, *nm;
+ Pcminfo *pi;
+ int i;
+ ulong e;
+
+ pi = &cb->linfo;
+
+ /* convert offset to granularity */
+ if(len <= 0)
+ len = 1;
+ e = ROUND(offset+len, Mgran);
+ offset &= Mmask;
+ len = e - offset;
+
+ /* look for a map that covers the right area */
+ we = rdreg(cb, Rwe);
+ bit = 1;
+ nm = 0;
+ for(m = pi->mmap; m < &pi->mmap[nelem(pi->mmap)]; m++){
+ if((we & bit))
+ if(m->attr == attr)
+ if(offset >= m->ca && e <= m->cea){
+
+ m->ref++;
+ return m;
+ }
+ bit <<= 1;
+ if(nm == 0 && m->ref == 0)
+ nm = m;
+ }
+ m = nm;
+ if(m == 0)
+ return 0;
+
+ /* if isa space isn't big enough, free it and get more */
+ if(m->len < len){
+ if(m->isa){
+ umbfree(m->isa, m->len);
+ m->len = 0;
+ }
+ m->isa = PADDR(umbmalloc(0, len, Mgran));
+ if(m->isa == 0){
+ print("isamap: out of isa space\n");
+ return 0;
+ }
+ m->len = len;
+ }
+
+ /* set up new map */
+ m->ca = offset;
+ m->cea = m->ca + m->len;
+ m->attr = attr;
+ i = m - pi->mmap;
+ bit = 1<<i;
+ wrreg(cb, Rwe, we & ~bit); /* disable map before changing it */
+ wrreg(cb, MAP(i, Mbtmlo), m->isa>>Mshift);
+ wrreg(cb, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
+ wrreg(cb, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
+ wrreg(cb, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
+ offset -= m->isa;
+ offset &= (1<<25)-1;
+ offset >>= Mshift;
+ wrreg(cb, MAP(i, Mofflo), offset);
+ wrreg(cb, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
+ wrreg(cb, Rwe, we | bit); /* enable map */
+ m->ref = 1;
+
+ return m;
+}
+
+static void
+isaunmap(PCMmap* m)
+{
+ m->ref--;
+}
+
+/*
+ * reading and writing card registers
+ */
+static uchar
+rdreg(Cardbus *cb, int index)
+{
+ outb(cb->lindex, cb->lbase + index);
+ return inb(cb->ldata);
+}
+
+static void
+wrreg(Cardbus *cb, int index, uchar val)
+{
+ outb(cb->lindex, cb->lbase + index);
+ outb(cb->ldata, val);
+}
+
+static int
+readc(Cisdat *cis, uchar *x)
+{
+ if(cis->cispos >= cis->cislen)
+ return 0;
+ *x = cis->cisbase[cis->cisskip*cis->cispos];
+ cis->cispos++;
+ return 1;
+}
+
+static ulong
+getlong(Cisdat *cis, int size)
+{
+ uchar c;
+ int i;
+ ulong x;
+
+ x = 0;
+ for(i = 0; i < size; i++){
+ if(readc(cis, &c) != 1)
+ break;
+ x |= c<<(i*8);
+ }
+ return x;
+}
+
+static void
+tcfig(Cardbus *cb, Cisdat *cis, int )
+{
+ uchar size, rasize, rmsize;
+ uchar last;
+ Pcminfo *pi;
+
+ if(readc(cis, &size) != 1)
+ return;
+ rasize = (size&0x3) + 1;
+ rmsize = ((size>>2)&0xf) + 1;
+ if(readc(cis, &last) != 1)
+ return;
+
+ pi = &cb->linfo;
+ pi->conf_addr = getlong(cis, rasize);
+ pi->conf_present = getlong(cis, rmsize);
+}
+
+static void
+tvers1(Cardbus *cb, Cisdat *cis, int )
+{
+ uchar c, major, minor, last;
+ int i;
+ Pcminfo *pi;
+
+ pi = &cb->linfo;
+ if(readc(cis, &major) != 1)
+ return;
+ if(readc(cis, &minor) != 1)
+ return;
+ last = 0;
+ for(i = 0; i < sizeof(pi->verstr) - 1; i++){
+ if(readc(cis, &c) != 1)
+ return;
+ if(c == 0)
+ c = ';';
+ if(c == '\n')
+ c = ';';
+ if(c == 0xff)
+ break;
+ if(c == ';' && last == ';')
+ continue;
+ pi->verstr[i] = c;
+ last = c;
+ }
+ pi->verstr[i] = 0;
+}
+
+static ulong
+microvolt(Cisdat *cis)
+{
+ uchar c;
+ ulong microvolts;
+ ulong exp;
+
+ if(readc(cis, &c) != 1)
+ return 0;
+ exp = exponent[c&0x7];
+ microvolts = vmant[(c>>3)&0xf]*exp;
+ while(c & 0x80){
+ if(readc(cis, &c) != 1)
+ return 0;
+ switch(c){
+ case 0x7d:
+ break; /* high impedence when sleeping */
+ case 0x7e:
+ case 0x7f:
+ microvolts = 0; /* no connection */
+ break;
+ default:
+ exp /= 10;
+ microvolts += exp*(c&0x7f);
+ }
+ }
+ return microvolts;
+}
+
+static ulong
+nanoamps(Cisdat *cis)
+{
+ uchar c;
+ ulong nanoamps;
+
+ if(readc(cis, &c) != 1)
+ return 0;
+ nanoamps = exponent[c&0x7]*vmant[(c>>3)&0xf];
+ while(c & 0x80){
+ if(readc(cis, &c) != 1)
+ return 0;
+ if(c == 0x7d || c == 0x7e || c == 0x7f)
+ nanoamps = 0;
+ }
+ return nanoamps;
+}
+
+/*
+ * only nominal voltage (feature 1) is important for config,
+ * other features must read card to stay in sync.
+ */
+static ulong
+power(Cisdat *cis)
+{
+ uchar feature;
+ ulong mv;
+
+ mv = 0;
+ if(readc(cis, &feature) != 1)
+ return 0;
+ if(feature & 1)
+ mv = microvolt(cis);
+ if(feature & 2)
+ microvolt(cis);
+ if(feature & 4)
+ microvolt(cis);
+ if(feature & 8)
+ nanoamps(cis);
+ if(feature & 0x10)
+ nanoamps(cis);
+ if(feature & 0x20)
+ nanoamps(cis);
+ if(feature & 0x40)
+ nanoamps(cis);
+ return mv/1000000;
+}
+
+static ulong
+ttiming(Cisdat *cis, int scale)
+{
+ uchar unscaled;
+ ulong nanosecs;
+
+ if(readc(cis, &unscaled) != 1)
+ return 0;
+ nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
+ nanosecs = nanosecs * exponent[scale];
+ return nanosecs;
+}
+
+static void
+timing(Cisdat *cis, PCMconftab *ct)
+{
+ uchar c, i;
+
+ if(readc(cis, &c) != 1)
+ return;
+ i = c&0x3;
+ if(i != 3)
+ ct->maxwait = ttiming(cis, i); /* max wait */
+ i = (c>>2)&0x7;
+ if(i != 7)
+ ct->readywait = ttiming(cis, i); /* max ready/busy wait */
+ i = (c>>5)&0x7;
+ if(i != 7)
+ ct->otherwait = ttiming(cis, i); /* reserved wait */
+}
+
+static void
+iospaces(Cisdat *cis, PCMconftab *ct)
+{
+ uchar c;
+ int i, nio;
+
+ ct->nio = 0;
+ if(readc(cis, &c) != 1)
+ return;
+
+ ct->bit16 = ((c>>5)&3) >= 2;
+ if(!(c & 0x80)){
+ ct->io[0].start = 0;
+ ct->io[0].len = 1<<(c&0x1f);
+ ct->nio = 1;
+ return;
+ }
+
+ if(readc(cis, &c) != 1)
+ return;
+
+ /*
+ * For each of the range descriptions read the
+ * start address and the length (value is length-1).
+ */
+ nio = (c&0xf)+1;
+ for(i = 0; i < nio; i++){
+ ct->io[i].start = getlong(cis, (c>>4)&0x3);
+ ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
+ }
+ ct->nio = nio;
+}
+
+static void
+irq(Cisdat *cis, PCMconftab *ct)
+{
+ uchar c;
+
+ if(readc(cis, &c) != 1)
+ return;
+ ct->irqtype = c & 0xe0;
+ if(c & 0x10)
+ ct->irqs = getlong(cis, 2);
+ else
+ ct->irqs = 1<<(c&0xf);
+ ct->irqs &= 0xDEB8; /* levels available to card */
+}
+
+static void
+memspace(Cisdat *cis, int asize, int lsize, int host)
+{
+ ulong haddress, address, len;
+
+ len = getlong(cis, lsize)*256;
+ address = getlong(cis, asize)*256;
+ USED(len, address);
+ if(host){
+ haddress = getlong(cis, asize)*256;
+ USED(haddress);
+ }
+}
+
+static void
+tentry(Cardbus *cb, Cisdat *cis, int )
+{
+ uchar c, i, feature;
+ PCMconftab *ct;
+ Pcminfo *pi;
+
+ pi = &cb->linfo;
+ if(pi->nctab >= nelem(pi->ctab))
+ return;
+ if(readc(cis, &c) != 1)
+ return;
+ ct = &pi->ctab[pi->nctab++];
+
+ /* copy from last default config */
+ if(pi->defctab)
+ *ct = *pi->defctab;
+
+ ct->index = c & 0x3f;
+
+ /* is this the new default? */
+ if(c & 0x40)
+ pi->defctab = ct;
+
+ /* memory wait specified? */
+ if(c & 0x80){
+ if(readc(cis, &i) != 1)
+ return;
+ if(i&0x80)
+ ct->memwait = 1;
+ }
+
+ if(readc(cis, &feature) != 1)
+ return;
+ switch(feature&0x3){
+ case 1:
+ ct->vpp1 = ct->vpp2 = power(cis);
+ break;
+ case 2:
+ power(cis);
+ ct->vpp1 = ct->vpp2 = power(cis);
+ break;
+ case 3:
+ power(cis);
+ ct->vpp1 = power(cis);
+ ct->vpp2 = power(cis);
+ break;
+ default:
+ break;
+ }
+ if(feature&0x4)
+ timing(cis, ct);
+ if(feature&0x8)
+ iospaces(cis, ct);
+ if(feature&0x10)
+ irq(cis, ct);
+ switch((feature>>5)&0x3){
+ case 1:
+ memspace(cis, 0, 2, 0);
+ break;
+ case 2:
+ memspace(cis, 2, 2, 0);
+ break;
+ case 3:
+ if(readc(cis, &c) != 1)
+ return;
+ for(i = 0; i <= (c&0x7); i++)
+ memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
+ break;
+ }
+}
+
+static void
+i82365probe(Cardbus *cb, int lindex, int ldata)
+{
+ uchar c, id;
+ int dev = 0; /* According to the Ricoh spec 00->3F _and_ 80->BF seem
+ to be the same socket A (ditto for B). */
+
+ outb(lindex, Rid + (dev<<7));
+ id = inb(ldata);
+ if((id & 0xf0) != 0x80)
+ return; /* not a memory & I/O card */
+ if((id & 0x0f) == 0x00)
+ return; /* no revision number, not possible */
+
+ cb->lindex = lindex;
+ cb->ldata = ldata;
+ cb->ltype = Ti82365;
+ cb->lbase = (int)(cb - cbslots) * 0x40;
+
+ switch(id){
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ /* could be a cirrus */
+ outb(cb->lindex, Rchipinfo + (dev<<7));
+ outb(cb->ldata, 0);
+ c = inb(cb->ldata);
+ if((c & 0xc0) != 0xc0)
+ break;
+ c = inb(cb->ldata);
+ if((c & 0xc0) != 0x00)
+ break;
+ if(c & 0x20){
+ cb->ltype = Tpd6720;
+ } else {
+ cb->ltype = Tpd6710;
+ }
+
+ /* low power mode */
+ outb(cb->lindex, Rmisc2 + (dev<<7));
+ c = inb(cb->ldata);
+ outb(cb->ldata, c & ~Flowpow);
+ break;
+ break;
+ }
+
+ /* if it's not a Cirrus, it could be a Vadem... */
+ if(cb->ltype == Ti82365){
+ /* unlock the Vadem extended regs */
+ outb(cb->lindex, 0x0E + (dev<<7));
+ outb(cb->lindex, 0x37 + (dev<<7));
+
+ /* make the id register show the Vadem id */
+ outb(cb->lindex, 0x3A + (dev<<7));
+ c = inb(cb->ldata);
+ outb(cb->ldata, c|0xC0);
+ outb(cb->lindex, Rid + (dev<<7));
+ c = inb(cb->ldata);
+ if(c & 0x08)
+ cb->ltype = Tvg46x;
+
+ /* go back to Intel compatible id */
+ outb(cb->lindex, 0x3A + (dev<<7));
+ c = inb(cb->ldata);
+ outb(cb->ldata, c & ~0xC0);
+ }
+}
+
+static int
+vcode(int volt)
+{
+ switch(volt){
+ case 5:
+ return 1;
+ case 12:
+ return 2;
+ default:
+ return 0;
+ }
+}
diff --git a/sys/src/9/pc/devrtc.c b/sys/src/9/pc/devrtc.c
new file mode 100755
index 000000000..5d092066f
--- /dev/null
+++ b/sys/src/9/pc/devrtc.c
@@ -0,0 +1,461 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+/*
+ * real time clock and non-volatile ram
+ */
+
+enum {
+ Paddr= 0x70, /* address port */
+ Pdata= 0x71, /* data port */
+
+ Seconds= 0x00,
+ Minutes= 0x02,
+ Hours= 0x04,
+ Mday= 0x07,
+ Month= 0x08,
+ Year= 0x09,
+ Status= 0x0A,
+
+ Nvoff= 128, /* where usable nvram lives */
+ Nvsize= 256,
+
+ Nbcd= 6,
+};
+
+typedef struct Rtc Rtc;
+struct Rtc
+{
+ int sec;
+ int min;
+ int hour;
+ int mday;
+ int mon;
+ int year;
+};
+
+
+enum{
+ Qdir = 0,
+ Qrtc,
+ Qnvram,
+};
+
+Dirtab rtcdir[]={
+ ".", {Qdir, 0, QTDIR}, 0, 0555,
+ "nvram", {Qnvram, 0}, Nvsize, 0664,
+ "rtc", {Qrtc, 0}, 0, 0664,
+};
+
+static ulong rtc2sec(Rtc*);
+static void sec2rtc(ulong, Rtc*);
+
+void
+rtcinit(void)
+{
+ if(ioalloc(Paddr, 2, 0, "rtc/nvr") < 0)
+ panic("rtcinit: ioalloc failed");
+}
+
+static Chan*
+rtcattach(char* spec)
+{
+ return devattach('r', spec);
+}
+
+static Walkqid*
+rtcwalk(Chan* c, Chan *nc, char** name, int nname)
+{
+ return devwalk(c, nc, name, nname, rtcdir, nelem(rtcdir), devgen);
+}
+
+static int
+rtcstat(Chan* c, uchar* dp, int n)
+{
+ return devstat(c, dp, n, rtcdir, nelem(rtcdir), devgen);
+}
+
+static Chan*
+rtcopen(Chan* c, int omode)
+{
+ omode = openmode(omode);
+ switch((ulong)c->qid.path){
+ case Qrtc:
+ if(strcmp(up->user, eve)!=0 && omode!=OREAD)
+ error(Eperm);
+ break;
+ case Qnvram:
+ if(strcmp(up->user, eve)!=0)
+ error(Eperm);
+ }
+ return devopen(c, omode, rtcdir, nelem(rtcdir), devgen);
+}
+
+static void
+rtcclose(Chan*)
+{
+}
+
+#define GETBCD(o) ((bcdclock[o]&0xf) + 10*(bcdclock[o]>>4))
+
+static long
+_rtctime(void)
+{
+ uchar bcdclock[Nbcd];
+ Rtc rtc;
+ int i;
+
+ /* don't do the read until the clock is no longer busy */
+ for(i = 0; i < 10000; i++){
+ outb(Paddr, Status);
+ if(inb(Pdata) & 0x80)
+ continue;
+
+ /* read clock values */
+ outb(Paddr, Seconds); bcdclock[0] = inb(Pdata);
+ outb(Paddr, Minutes); bcdclock[1] = inb(Pdata);
+ outb(Paddr, Hours); bcdclock[2] = inb(Pdata);
+ outb(Paddr, Mday); bcdclock[3] = inb(Pdata);
+ outb(Paddr, Month); bcdclock[4] = inb(Pdata);
+ outb(Paddr, Year); bcdclock[5] = inb(Pdata);
+
+ outb(Paddr, Status);
+ if((inb(Pdata) & 0x80) == 0)
+ break;
+ }
+
+ /*
+ * convert from BCD
+ */
+ rtc.sec = GETBCD(0);
+ rtc.min = GETBCD(1);
+ rtc.hour = GETBCD(2);
+ rtc.mday = GETBCD(3);
+ rtc.mon = GETBCD(4);
+ rtc.year = GETBCD(5);
+
+ /*
+ * the world starts jan 1 1970
+ */
+ if(rtc.year < 70)
+ rtc.year += 2000;
+ else
+ rtc.year += 1900;
+ return rtc2sec(&rtc);
+}
+
+static Lock nvrtlock;
+
+long
+rtctime(void)
+{
+ int i;
+ long t, ot;
+
+ ilock(&nvrtlock);
+
+ /* loop till we get two reads in a row the same */
+ t = _rtctime();
+ for(i = 0; i < 100; i++){
+ ot = t;
+ t = _rtctime();
+ if(ot == t)
+ break;
+ }
+ if(i == 100) print("we are boofheads\n");
+
+ iunlock(&nvrtlock);
+
+ return t;
+}
+
+static long
+rtcread(Chan* c, void* buf, long n, vlong off)
+{
+ ulong t;
+ char *a, *start;
+ ulong offset = off;
+
+ if(c->qid.type & QTDIR)
+ return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen);
+
+ switch((ulong)c->qid.path){
+ case Qrtc:
+ t = rtctime();
+ n = readnum(offset, buf, n, t, 12);
+ return n;
+ case Qnvram:
+ if(n == 0)
+ return 0;
+ if(n > Nvsize)
+ n = Nvsize;
+ a = start = smalloc(n);
+
+ ilock(&nvrtlock);
+ for(t = offset; t < offset + n; t++){
+ if(t >= Nvsize)
+ break;
+ outb(Paddr, Nvoff+t);
+ *a++ = inb(Pdata);
+ }
+ iunlock(&nvrtlock);
+
+ if(waserror()){
+ free(start);
+ nexterror();
+ }
+ memmove(buf, start, t - offset);
+ poperror();
+
+ free(start);
+ return t - offset;
+ }
+ error(Ebadarg);
+ return 0;
+}
+
+#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4)
+
+static long
+rtcwrite(Chan* c, void* buf, long n, vlong off)
+{
+ int t;
+ char *a, *start;
+ Rtc rtc;
+ ulong secs;
+ uchar bcdclock[Nbcd];
+ char *cp, *ep;
+ ulong offset = off;
+
+ if(offset!=0)
+ error(Ebadarg);
+
+
+ switch((ulong)c->qid.path){
+ case Qrtc:
+ /*
+ * read the time
+ */
+ cp = ep = buf;
+ ep += n;
+ while(cp < ep){
+ if(*cp>='0' && *cp<='9')
+ break;
+ cp++;
+ }
+ secs = strtoul(cp, 0, 0);
+
+ /*
+ * convert to bcd
+ */
+ sec2rtc(secs, &rtc);
+ PUTBCD(rtc.sec, 0);
+ PUTBCD(rtc.min, 1);
+ PUTBCD(rtc.hour, 2);
+ PUTBCD(rtc.mday, 3);
+ PUTBCD(rtc.mon, 4);
+ PUTBCD(rtc.year, 5);
+
+ /*
+ * write the clock
+ */
+ ilock(&nvrtlock);
+ outb(Paddr, Seconds); outb(Pdata, bcdclock[0]);
+ outb(Paddr, Minutes); outb(Pdata, bcdclock[1]);
+ outb(Paddr, Hours); outb(Pdata, bcdclock[2]);
+ outb(Paddr, Mday); outb(Pdata, bcdclock[3]);
+ outb(Paddr, Month); outb(Pdata, bcdclock[4]);
+ outb(Paddr, Year); outb(Pdata, bcdclock[5]);
+ iunlock(&nvrtlock);
+ return n;
+ case Qnvram:
+ if(n == 0)
+ return 0;
+ if(n > Nvsize)
+ n = Nvsize;
+
+ start = a = smalloc(n);
+ if(waserror()){
+ free(start);
+ nexterror();
+ }
+ memmove(a, buf, n);
+ poperror();
+
+ ilock(&nvrtlock);
+ for(t = offset; t < offset + n; t++){
+ if(t >= Nvsize)
+ break;
+ outb(Paddr, Nvoff+t);
+ outb(Pdata, *a++);
+ }
+ iunlock(&nvrtlock);
+
+ free(start);
+ return t - offset;
+ }
+ error(Ebadarg);
+ return 0;
+}
+
+Dev rtcdevtab = {
+ 'r',
+ "rtc",
+
+ devreset,
+ rtcinit,
+ devshutdown,
+ rtcattach,
+ rtcwalk,
+ rtcstat,
+ rtcopen,
+ devcreate,
+ rtcclose,
+ rtcread,
+ devbread,
+ rtcwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+#define SEC2MIN 60L
+#define SEC2HOUR (60L*SEC2MIN)
+#define SEC2DAY (24L*SEC2HOUR)
+
+/*
+ * days per month plus days/year
+ */
+static int dmsize[] =
+{
+ 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+static int ldmsize[] =
+{
+ 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/*
+ * return the days/month for the given year
+ */
+static int*
+yrsize(int y)
+{
+ if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
+ return ldmsize;
+ else
+ return dmsize;
+}
+
+/*
+ * compute seconds since Jan 1 1970
+ */
+static ulong
+rtc2sec(Rtc *rtc)
+{
+ ulong secs;
+ int i;
+ int *d2m;
+
+ secs = 0;
+
+ /*
+ * seconds per year
+ */
+ for(i = 1970; i < rtc->year; i++){
+ d2m = yrsize(i);
+ secs += d2m[0] * SEC2DAY;
+ }
+
+ /*
+ * seconds per month
+ */
+ d2m = yrsize(rtc->year);
+ for(i = 1; i < rtc->mon; i++)
+ secs += d2m[i] * SEC2DAY;
+
+ secs += (rtc->mday-1) * SEC2DAY;
+ secs += rtc->hour * SEC2HOUR;
+ secs += rtc->min * SEC2MIN;
+ secs += rtc->sec;
+
+ return secs;
+}
+
+/*
+ * compute rtc from seconds since Jan 1 1970
+ */
+static void
+sec2rtc(ulong secs, Rtc *rtc)
+{
+ int d;
+ long hms, day;
+ int *d2m;
+
+ /*
+ * break initial number into days
+ */
+ hms = secs % SEC2DAY;
+ day = secs / SEC2DAY;
+ if(hms < 0) {
+ hms += SEC2DAY;
+ day -= 1;
+ }
+
+ /*
+ * generate hours:minutes:seconds
+ */
+ rtc->sec = hms % 60;
+ d = hms / 60;
+ rtc->min = d % 60;
+ d /= 60;
+ rtc->hour = d;
+
+ /*
+ * year number
+ */
+ if(day >= 0)
+ for(d = 1970; day >= *yrsize(d); d++)
+ day -= *yrsize(d);
+ else
+ for (d = 1970; day < 0; d--)
+ day += *yrsize(d-1);
+ rtc->year = d;
+
+ /*
+ * generate month
+ */
+ d2m = yrsize(rtc->year);
+ for(d = 1; day >= d2m[d]; d++)
+ day -= d2m[d];
+ rtc->mday = day + 1;
+ rtc->mon = d;
+
+ return;
+}
+
+uchar
+nvramread(int addr)
+{
+ uchar data;
+
+ ilock(&nvrtlock);
+ outb(Paddr, addr);
+ data = inb(Pdata);
+ iunlock(&nvrtlock);
+
+ return data;
+}
+
+void
+nvramwrite(int addr, uchar data)
+{
+ ilock(&nvrtlock);
+ outb(Paddr, addr);
+ outb(Pdata, data);
+ iunlock(&nvrtlock);
+}
diff --git a/sys/src/9/pc/devtv.c b/sys/src/9/pc/devtv.c
new file mode 100755
index 000000000..7dd729004
--- /dev/null
+++ b/sys/src/9/pc/devtv.c
@@ -0,0 +1,2194 @@
+/*
+ * Driver for Bt848 TV tuner.
+ *
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+#include "hcwAMC.h"
+
+#define max(a, b) (((a) > (b))? (a): (b))
+
+enum {
+ Qdir = 0,
+ Qsubdir,
+ Qsubbase,
+ Qvdata = Qsubbase,
+ Qadata,
+ Qctl,
+ Qregs,
+
+ Brooktree_vid = 0x109e,
+ Brooktree_848_did = 0x0350,
+ Brooktree_878_did = 0x036E,
+ Intel_vid = 0x8086,
+ Intel_82437_did = 0x122d,
+
+ K = 1024,
+ M = K * K,
+
+ Ntvs = 4,
+
+ Numring = 16,
+
+ ntsc_rawpixels = 910,
+ ntsc_sqpixels = 780, /* Including blanking & inactive */
+ ntsc_hactive = 640,
+ ntsc_vactive = 480,
+ ntsc_clkx1delay = 135, /* Clock ticks. */
+ ntsc_clkx1hactive = 754,
+ ntsc_vdelay = 26, /* # of scan lines. */
+ ntsc_vscale = 0,
+
+ i2c_nostop = 1 << 5,
+ i2c_nos1b = 1 << 4,
+ i2c_timing = 7 << 4,
+ i2c_bt848w3b = 1 << 2,
+ i2c_bt848scl = 1 << 1,
+ i2c_bt848sda = 1 << 0,
+ i2c_scl = i2c_bt848scl,
+ i2c_sda = i2c_bt848sda,
+
+ i2c_miroproee = 0x80, /* MIRO PRO EEPROM */
+ i2c_tea6300 = 0x80,
+ i2c_tda8425 = 0x82,
+ i2c_tda9840 = 0x84,
+ i2c_tda9850 = 0xb6,
+ i2c_haupee = 0xa0, /* Hauppage EEPROM */
+ i2c_stbee = 0xae, /* STB EEPROM */
+ i2c_msp3400 = 0x80,
+
+ i2c_timeout = 1000,
+ i2c_delay = 10,
+
+ Bt848_miropro = 0,
+ Bt848_miro,
+ Bt878_hauppauge,
+
+ /* Bit fields. */
+ iform_muxsel1 = 3 << 5, /* 004 */
+ iform_muxsel0 = 2 << 5,
+ iform_xtselmask = 3 << 3,
+ iform_xtauto = 3 << 3,
+ iform_formatmask = 7 << 0,
+ iform_ntsc = 1 << 0,
+
+ control_ldec = 1 << 5, /* 02C */
+ contrast_100percent = 0xd8, /* 030 */
+
+ vscale_interlaced = 1 << 5, /* 04C */
+
+ adelay_ntsc = 104, /* 060 */
+ bdelay_ntsc = 93, /* 064 */
+ adc_crush = 1 << 0, /* 068 */
+
+ colorfmt_rgb16 = 2 << 4 | 2 << 0, /* 0D4 */
+ colorfmt_YCbCr422 = 8 << 4 | 8 << 0,
+ colorfmt_YCbCr411 = 9 << 4 | 9 << 0,
+ colorctl_gamma = 1 << 4, /* 0D8 */
+ capctl_fullframe = 1 << 4, /* 0DC */
+ capctl_captureodd = 1 << 1,
+ capctl_captureeven = 1 << 0,
+ vbipacksize = 0x190, /* 0E0 */
+
+ intstat_riscstatshift = 28, /* 100 */
+ intstat_i2crack = 1 << 25,
+ intstat_scerr = 1 << 19,
+ intstat_ocerr = 1 << 18,
+ intstat_pabort = 1 << 17,
+ intstat_riperr = 1 << 16,
+ intstat_pperr = 1 << 15,
+ intstat_fdsr = 1 << 14,
+ intstat_ftrgt = 1 << 13,
+ intstat_fbus = 1 << 12,
+ intstat_risci = 1 << 11,
+ intstat_i2cdone = 1 << 8,
+ intstat_vpress = 1 << 5,
+ intstat_hlock = 1 << 4,
+ intstat_vsync = 1 << 1,
+ intstat_fmtchg = 1 << 0,
+ intmask_etbf = 1 << 23, /* 104 */
+
+ gpiodmactl_apwrdn = 1 << 26, /* 10C */
+ gpiodmactl_daes2 = 1 << 13,
+ gpiodmactl_daiomda = 1 << 6,
+ gpiodmactl_pltp23_16 = 2 << 6,
+ gpiodmactl_pltp23_0 = 0 << 6,
+ gpiodmactl_pltp1_16 = 2 << 4,
+ gpiodmactl_pltp1_0 = 0 << 4,
+ gpiodmactl_acapenable = 1 << 4,
+ gpiodmactl_pktp_32 = 3 << 2,
+ gpiodmactl_pktp_0 = 0 << 2,
+ gpiodmactl_riscenable = 1 << 1,
+ gpiodmactl_fifoenable = 1 << 0,
+
+ /* RISC instructions and parameters. */
+ fifo_vre = 0x4,
+ fifo_vro = 0xc,
+ fifo_fm1 = 0x6,
+ fifo_fm3 = 0xe,
+
+ riscirq = 1 << 24,
+ riscwrite = 1 << 28,
+ riscwrite123 = 9 << 28,
+ riscwrite1s23 = 11 << 28,
+ riscwrite_sol = 1 << 27,
+ riscwrite_eol = 1 << 26,
+ riscskip = 0x2 << 28,
+ riscjmp = 0x7 << 28,
+ riscsync = 0x8 << 28,
+ riscsync_resync = 1 << 15,
+ riscsync_vre = fifo_vre << 0,
+ riscsync_vro = fifo_vro << 0,
+ riscsync_fm1 = fifo_fm1 << 0,
+ riscsync_fm3 = fifo_fm3 << 0,
+ risclabelshift_set = 16,
+ risclabelshift_reset = 20,
+
+ AudioTuner = 0,
+ AudioRadio,
+ AudioExtern,
+ AudioIntern,
+ AudioOff,
+ AudioOn,
+
+ asel_tv = 0,
+ asel_radio,
+ asel_mic,
+ asel_smxc,
+
+ Hwbase_ad = 448000,
+
+ msp_dem = 0x10,
+ msp_bbp = 0x12,
+
+ /* Altera definitions. */
+ gpio_altera_data = 1 << 0,
+ gpio_altera_clock = 1 << 20,
+ gpio_altera_nconfig = 1 << 23,
+
+ Ial = 0x140001,
+ Idma = 0x100002,
+
+ Adsp = 0x7fd8,
+ Adsp_verifysystem = 1,
+ Adsp_querysupportplay,
+ Adsp_setstyle,
+ Adsp_setsrate,
+ Adsp_setchannels,
+ Adsp_setresolution,
+ Adsp_setcrcoptions,
+ Adsp_bufenqfor,
+ Adsp_logbuffer,
+ Adsp_startplay,
+ Adsp_stopplay,
+ Adsp_autostop,
+ Adsp_startrecord,
+ Adsp_stoprecord,
+ Adsp_getlastprocessed,
+ Adsp_pause,
+ Adsp_resume,
+ Adsp_setvolume,
+ Adsp_querysupportrecord,
+ Adsp_generalbufenq,
+ Adsp_setdownmixtype,
+ Adsp_setigain,
+ Adsp_setlineout,
+ Adsp_setlangmixtype,
+
+ Kfir_gc = 0,
+ Kfir_dsp_riscmc,
+ Kfir_dsp_risccram,
+ Kfir_dsp_unitmc,
+ Kfir_bsm_mc,
+ Kfir_mux_mc,
+
+ Kfir_devid_gc = 7,
+ Kfir_devid_dsp = 4,
+ Kfir_devid_bsm = 5,
+ Kfir_devid_mux = 8,
+
+ Kfir_200 = 200,
+ Kfir_dev_inst = Kfir_200,
+ Kfir_201 = 201,
+ Kfir_exec = Kfir_201,
+ Kfir_202 = 202,
+ Kfir_adr_eready = 254,
+
+ Kfir_d_eready_encoding = 0,
+ Kfir_d_eready_ready,
+ Kfir_d_eready_test,
+ Kfir_d_eready_stopdetect,
+ Kfir_d_eready_seqend,
+
+ VT_KFIR_OFF = 0,
+ VT_KFIR_ON,
+
+ VT_KFIR_LAYER_II = 1,
+ VT_KFIR_STEREO = 1,
+
+ Gpioinit = 0,
+ Gpiooutput,
+ Gpioinput,
+
+ Srate_5512 = 0,
+ Srate_11025 = 2,
+ Srate_16000 = 3,
+ Srate_22050 = 4,
+ Srate_32000 = 5,
+ Srate_44100 = 6,
+ Srate_48000 = 7,
+
+};
+
+typedef struct Variant Variant;
+struct Variant {
+ ushort vid;
+ ushort did;
+ char *name;
+};
+
+typedef struct Bt848 Bt848;
+struct Bt848 {
+ ulong devstat; /* 000 */
+ ulong iform; /* 004 */
+ ulong tdec; /* 008 */
+ ulong ecrop; /* 00C */
+ ulong evdelaylo; /* 010 */
+ ulong evactivelo; /* 014 */
+ ulong ehdelaylo; /* 018 */
+ ulong ehactivelo; /* 01C */
+ ulong ehscalehi; /* 020 */
+ ulong ehscalelo; /* 024 */
+ ulong bright; /* 028 */
+ ulong econtrol; /* 02C */
+ ulong contrastlo; /* 030 */
+ ulong satulo; /* 034 */
+ ulong satvlo; /* 038 */
+ ulong hue; /* 03C */
+ ulong escloop; /* 040 */
+ ulong pad0; /* 044 */
+ ulong oform; /* 048 */
+ ulong evscalehi; /* 04C */
+ ulong evscalelo; /* 050 */
+ ulong test; /* 054 */
+ ulong pad1[2]; /* 058-05C */
+ ulong adelay; /* 060 */
+ ulong bdelay; /* 064 */
+ ulong adc; /* 068 */
+ ulong evtc; /* 06C */
+ ulong pad2[3]; /* 070-078 */
+ ulong sreset; /* 07C */
+ ulong tglb; /* 080 */
+ ulong tgctrl; /* 084 */
+ ulong pad3; /* 088 */
+ ulong ocrop; /* 08C */
+ ulong ovdelaylo; /* 090 */
+ ulong ovactivelo; /* 094 */
+ ulong ohdelaylo; /* 098 */
+ ulong ohactivelo; /* 09C */
+ ulong ohscalehi; /* 0A0 */
+ ulong ohscalelo; /* 0A4 */
+ ulong pad4; /* 0A8 */
+ ulong ocontrol; /* 0AC */
+ ulong pad5[4]; /* 0B0-0BC */
+ ulong oscloop; /* 0C0 */
+ ulong pad6[2]; /* 0C4-0C8 */
+ ulong ovscalehi; /* 0CC */
+ ulong ovscalelo; /* 0D0 */
+ ulong colorfmt; /* 0D4 */
+ ulong colorctl; /* 0D8 */
+ ulong capctl; /* 0DC */
+ ulong vbipacksize; /* 0E0 */
+ ulong vbipackdel; /* 0E4 */
+ ulong fcap; /* 0E8 */
+ ulong ovtc; /* 0EC */
+ ulong pllflo; /* 0F0 */
+ ulong pllfhi; /* 0F4 */
+ ulong pllxci; /* 0F8 */
+ ulong dvsif; /* 0FC */
+ ulong intstat; /* 100 */
+ ulong intmask; /* 104 */
+ ulong pad7; /* 108 */
+ ulong gpiodmactl; /* 10C */
+ ulong i2c; /* 110 */
+ ulong riscstrtadd; /* 114 */
+ ulong gpioouten; /* 118 */
+ ulong gpioreginp; /* 11C */
+ ulong risccount; /* 120 */
+ ulong pad8[55]; /* 124-1FC */
+ ulong gpiodata[64]; /* 200-2FC */
+};
+
+#define packetlen i2c
+
+typedef struct Tuner Tuner;
+struct Tuner {
+ char *name;
+ ushort freq_vhfh; /* Start frequency */
+ ushort freq_uhf;
+ uchar VHF_L;
+ uchar VHF_H;
+ uchar UHF;
+ uchar cfg;
+ ushort offs;
+};
+
+typedef struct Frame Frame;
+struct Frame {
+ ulong *fstart;
+ ulong *fjmp;
+ uchar *fbase;
+};
+
+typedef struct Tv Tv;
+struct Tv {
+ Lock;
+ Rendez;
+ Bt848 *bt848;
+ Bt848 *bt878; /* Really only audio control registers */
+ Variant *variant;
+ Tuner *tuner;
+ Pcidev *pci;
+ uchar i2ctuneraddr;
+ uchar i2ccmd; /* I2C command */
+ int board; /* What board is this? */
+ ulong cfmt; /* Current color format. */
+ int channel; /* Current channel */
+ Ref fref; /* Copying images? */
+ int nframes; /* Number of frames to capture. */
+ Frame *frames; /* DMA program */
+ int lvframe; /* Last video frame DMAed */
+ uchar *amux; /* Audio multiplexer. */
+ int nablocks; /* Number of audio blocks allocated */
+ int absize; /* Audio block size */
+ int narblocks; /* Number of audio blocks received */
+ ulong *arisc; /* Audio risc bloc */
+ uchar *abuf; /* Audio data buffers */
+ char ainfo[128];
+
+ /* WinTV/PVR stuff. */
+ int msp;
+ Lock kfirlock;
+ ulong i2cstate; /* Last i2c state. */
+ int gpiostate; /* Current GPIO state */
+ ulong alterareg; /* Last used altera register */
+ ulong alteraclock; /* Used to clock the altera */
+ int asrate; /* Audio sample rate */
+ uchar aleft, aright; /* Left and right audio volume */
+ ulong kfirclock;
+ Ref aref; /* Copying audio? */
+};
+
+enum {
+ TemicPAL = 0,
+ PhilipsPAL,
+ PhilipsNTSC,
+ PhilipsSECAM,
+ Notuner,
+ PhilipsPALI,
+ TemicNTSC,
+ TemicPALI,
+ Temic4036,
+ AlpsTSBH1,
+ AlpsTSBE1,
+
+ Freqmultiplier = 16,
+};
+
+static Tuner tuners[] = {
+ {"Temic PAL", Freqmultiplier * 140.25, Freqmultiplier * 463.25,
+ 0x02, 0x04, 0x01, 0x8e, 623 },
+ {"Philips PAL_I", Freqmultiplier * 140.25, Freqmultiplier * 463.25,
+ 0xa0, 0x90, 0x30, 0x8e, 623 },
+ {"Philips NTSC", Freqmultiplier * 157.25, Freqmultiplier * 451.25,
+ 0xA0, 0x90, 0x30, 0x8e, 732 },
+ {"Philips SECAM", Freqmultiplier * 168.25, Freqmultiplier * 447.25,
+ 0xA7, 0x97, 0x37, 0x8e, 623 },
+ {"NoTuner", 0, 0,
+ 0x00, 0x00, 0x00, 0x00, 0 },
+ {"Philips PAL", Freqmultiplier * 168.25, Freqmultiplier * 447.25,
+ 0xA0, 0x90, 0x30, 0x8e, 623 },
+ {"Temic NTSC", Freqmultiplier * 157.25, Freqmultiplier * 463.25,
+ 0x02, 0x04, 0x01, 0x8e, 732 },
+ {"TEMIC PAL_I", Freqmultiplier * 170.00, Freqmultiplier * 450.00,
+ 0x02, 0x04, 0x01, 0x8e, 623 },
+ {"Temic 4036 FY5 NTSC", Freqmultiplier * 157.25, Freqmultiplier * 463.25,
+ 0xa0, 0x90, 0x30, 0x8e, 732 },
+ {"Alps TSBH1", Freqmultiplier * 137.25, Freqmultiplier * 385.25,
+ 0x01, 0x02, 0x08, 0x8e, 732 },
+ {"Alps TSBE1", Freqmultiplier * 137.25, Freqmultiplier * 385.25,
+ 0x01, 0x02, 0x08, 0x8e, 732 },
+};
+
+static int hp_tuners[] = {
+ Notuner,
+ Notuner,
+ Notuner,
+ Notuner,
+ Notuner,
+ PhilipsNTSC,
+ Notuner,
+ Notuner,
+ PhilipsPAL,
+ PhilipsSECAM,
+ PhilipsNTSC,
+ PhilipsPALI,
+ Notuner,
+ Notuner,
+ TemicPAL,
+ TemicPALI,
+ Notuner,
+ PhilipsSECAM,
+ PhilipsNTSC,
+ PhilipsPALI,
+ Notuner,
+ PhilipsPAL,
+ Notuner,
+ PhilipsNTSC,
+};
+
+enum {
+ CMvstart,
+ CMastart,
+ CMastop,
+ CMvgastart,
+ CMvstop,
+ CMchannel,
+ CMcolormode,
+ CMvolume,
+ CMmute,
+};
+
+static Cmdtab tvctlmsg[] = {
+ CMvstart, "vstart", 2,
+ CMastart, "astart", 5,
+ CMastop, "astop", 1,
+ CMvgastart, "vgastart", 3,
+ CMvstop, "vstop", 1,
+ CMchannel, "channel", 3,
+ CMcolormode, "colormode", 2,
+ CMvolume, "volume", 3,
+ CMmute, "mute", 1,
+};
+
+static Variant variant[] = {
+ { Brooktree_vid, Brooktree_848_did, "Brooktree 848 TV tuner", },
+ { Brooktree_vid, Brooktree_878_did, "Brooktree 878 TV tuner", },
+};
+
+static char *boards[] = {
+ "MIRO PRO",
+ "MIRO",
+ "Hauppauge Bt878",
+};
+
+static ushort Adspfsample[] = {
+ 0x500, 0x700, 0x400, 0x600, 0x300, 0x200, 0x000, 0x100
+};
+static ushort Adspstereorates[] = {
+ 64, 96, 112, 128, 160, 192, 224, 256, 320, 384
+};
+
+static uchar miroamux[] = { 2, 0, 0, 0, 10, 0 };
+static uchar hauppaugeamux[] = { 0, 1, 2, 3, 4, 0 };
+static char *nicamstate[] = {
+ "analog", "???", "digital", "bad digital receiption"
+};
+
+
+static Tv tvs[Ntvs];
+static int ntvs;
+
+static int i2cread(Tv *, uchar, uchar *);
+static int i2cwrite(Tv *, uchar, uchar, uchar, int);
+static void tvinterrupt(Ureg *, Tv *);
+static void vgastart(Tv *, ulong, int);
+static void vstart(Tv *, int, int, int, int);
+static void astart(Tv *, char *, uint, uint, uint);
+static void vstop(Tv *);
+static void astop(Tv *);
+static void colormode(Tv *, char *);
+static void frequency(Tv *, int, int);
+static int getbitspp(Tv *);
+static char *getcolormode(ulong);
+static int mspreset(Tv *);
+static void i2cscan(Tv *);
+static int kfirinitialize(Tv *);
+static void msptune(Tv *);
+static void mspvolume(Tv *, int, int, int);
+static void gpioenable(Tv *, ulong, ulong);
+static void gpiowrite(Tv *, ulong, ulong);
+
+static void
+tvinit(void)
+{
+ Pcidev *pci;
+ ulong intmask;
+
+ /* Test for a triton memory controller. */
+ intmask = 0;
+ if (pcimatch(nil, Intel_vid, Intel_82437_did))
+ intmask = intmask_etbf;
+
+ pci = nil;
+ while ((pci = pcimatch(pci, 0, 0)) != nil) {
+ int i, t;
+ Tv *tv;
+ Bt848 *bt848;
+ ushort hscale, hdelay;
+ uchar v;
+
+ for (i = 0; i != nelem(variant); i++)
+ if (pci->vid == variant[i].vid && pci->did == variant[i].did)
+ break;
+ if (i == nelem(variant))
+ continue;
+
+ if (ntvs >= Ntvs) {
+ print("#V: Too many TV cards found\n");
+ continue;
+ }
+
+ tv = &tvs[ntvs++];
+ tv->variant = &variant[i];
+ tv->pci = pci;
+ 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;
+
+ /* i2c stuff. */
+ if (pci->did >= 878)
+ tv->i2ccmd = 0x83;
+ else
+ tv->i2ccmd = i2c_timing | i2c_bt848scl | i2c_bt848sda;
+
+ t = 0;
+ if (i2cread(tv, i2c_haupee, &v)) {
+ uchar ee[256];
+ Pcidev *pci878;
+ Bt848 *bt878;
+
+ tv->board = Bt878_hauppauge;
+ if (!i2cwrite(tv, i2c_haupee, 0, 0, 0))
+ panic("#V: Cannot write to Hauppauge EEPROM");
+ for (i = 0; i != sizeof ee; i++)
+ if (!i2cread(tv, i2c_haupee + 1, &ee[i]))
+ panic("#V: Cannot read from Hauppauge EEPROM");
+
+ if (ee[9] > sizeof hp_tuners / sizeof hp_tuners[0])
+ panic("#V: Tuner out of range (max %d, this %d)",
+ sizeof hp_tuners / sizeof hp_tuners[0], ee[9]);
+ t = hp_tuners[ee[9]];
+
+ /* Initialize the audio channel. */
+ if ((pci878 = pcimatch(nil, Brooktree_vid, 0x878)) == nil)
+ panic("#V: Unsupported Hauppage board");
+
+ tv->bt878 = bt878 =
+ (Bt848 *)vmap(pci878->mem[0].bar & ~0x0F, 4 * K);
+ if (bt878 == nil)
+ panic("#V: Cannot allocate memory for the Bt878");
+
+ kfirinitialize(tv);
+ // i2cscan(tv);
+ mspreset(tv);
+
+ bt878->gpiodmactl = 0;
+ bt878->intstat = (ulong)-1;
+ intrenable(pci878->intl, (void (*)(Ureg *, void *))tvinterrupt,
+ tv, pci878->tbdf, "tv");
+
+ tv->amux = hauppaugeamux;
+ }
+ else if (i2cread(tv, i2c_stbee, &v)) {
+ USED(t);
+ panic("#V: Cannot deal with STB cards\n");
+ }
+ else if (i2cread(tv, i2c_miroproee, &v)) {
+ tv->board = Bt848_miropro;
+ t = ((bt848->gpiodata[0] >> 10) - 1) & 7;
+ tv->amux = miroamux;
+ }
+ else {
+ tv->board = Bt848_miro;
+ tv->amux = miroamux;
+ t = ((bt848->gpiodata[0] >> 10) - 1) & 7;
+ }
+
+ if (t >= nelem(tuners))
+ t = 4;
+ tv->tuner = &tuners[t];
+ tv->i2ctuneraddr =
+ i2cread(tv, 0xc1, &v)? 0xc0:
+ i2cread(tv, 0xc3, &v)? 0xc2:
+ i2cread(tv, 0xc5, &v)? 0xc4:
+ i2cread(tv, 0xc7, &v)? 0xc6: -1;
+
+ bt848->capctl = capctl_fullframe;
+ bt848->adelay = adelay_ntsc;
+ bt848->bdelay = bdelay_ntsc;
+ bt848->iform = iform_muxsel0|iform_xtauto|iform_ntsc;
+ bt848->vbipacksize = vbipacksize & 0xff;
+ bt848->vbipackdel = (vbipacksize >> 8) & 1;
+
+ // setpll(bt848);
+
+ tv->cfmt = bt848->colorfmt = colorfmt_rgb16;
+
+ hscale = (ntsc_rawpixels * 4096) / ntsc_sqpixels - 4096;
+ hdelay = (ntsc_clkx1delay * ntsc_hactive) / ntsc_clkx1hactive;
+
+ bt848->ovtc = bt848->evtc = 0;
+ bt848->ehscalehi = bt848->ohscalehi = (hscale >> 8) & 0xff;
+ bt848->ehscalelo = bt848->ohscalelo = hscale & 0xff;
+ bt848->evscalehi &= ~0x1f;
+ bt848->ovscalehi &= ~0x1f;
+ bt848->evscalehi |= vscale_interlaced | ((ntsc_vscale >> 8) & 0x1f);
+ bt848->ovscalehi |= vscale_interlaced | (ntsc_vscale >> 8) & 0x1f;
+ bt848->evscalelo = bt848->ovscalelo = ntsc_vscale & 0xff;
+ bt848->ehactivelo = bt848->ohactivelo = ntsc_hactive & 0xff;
+ bt848->ehdelaylo = bt848->ohdelaylo = hdelay & 0xff;
+ bt848->evactivelo = bt848->ovactivelo = ntsc_vactive & 0xff;
+ bt848->evdelaylo = bt848->ovdelaylo = ntsc_vdelay & 0xff;
+ bt848->ecrop = bt848->ocrop =
+ ((ntsc_hactive >> 8) & 0x03) |
+ ((hdelay >> 6) & 0x0C) |
+ ((ntsc_vactive >> 4) & 0x30) |
+ ((ntsc_vdelay >> 2) & 0xC0);
+
+ bt848->colorctl = colorctl_gamma;
+ bt848->capctl = 0;
+ bt848->gpiodmactl = gpiodmactl_pltp23_16 |
+ gpiodmactl_pltp1_16 | gpiodmactl_pktp_32;
+ bt848->gpioreginp = 0;
+ bt848->contrastlo = contrast_100percent;
+ bt848->bright = 16;
+ bt848->adc = (2 << 6) | adc_crush;
+ bt848->econtrol = bt848->ocontrol = control_ldec;
+ bt848->escloop = bt848->oscloop = 0;
+ bt848->intstat = (ulong)-1;
+ bt848->intmask = intmask |
+ intstat_vsync | intstat_scerr | intstat_risci | intstat_ocerr |
+ intstat_vpress | intstat_fmtchg;
+
+
+ if (tv->amux) {
+ gpioenable(tv, ~0xfff, 0xfff);
+ gpiowrite(tv, ~0xfff, tv->amux[AudioRadio]);
+ }
+
+ print("#V%ld: %s (rev %d) (%s/%s) intl %d\n",
+ tv - tvs, tv->variant->name, pci->rid, boards[tv->board],
+ tv->tuner->name, pci->intl);
+
+ intrenable(pci->intl, (void (*)(Ureg *, void *))tvinterrupt,
+ tv, pci->tbdf, "tv");
+ }
+}
+
+static Chan*
+tvattach(char *spec)
+{
+ return devattach('V', spec);
+}
+
+#define TYPE(q) ((int)((q).path & 0xff))
+#define DEV(q) ((int)(((q).path >> 8) & 0xff))
+#define QID(d, t) ((((d) & 0xff) << 8) | (t))
+
+static int
+tv1gen(Chan *c, int i, Dir *dp)
+{
+ Qid qid;
+
+ switch (i) {
+ case Qvdata:
+ mkqid(&qid, QID(DEV(c->qid), Qvdata), 0, QTFILE);
+ devdir(c, qid, "video", 0, eve, 0444, dp);
+ return 1;
+ case Qadata:
+ mkqid(&qid, QID(DEV(c->qid), Qadata), 0, QTFILE);
+ devdir(c, qid, "audio", 0, eve, 0444, dp);
+ return 1;
+ case Qctl:
+ mkqid(&qid, QID(DEV(c->qid), Qctl), 0, QTFILE);
+ devdir(c, qid, "ctl", 0, eve, 0444, dp);
+ return 1;
+ case Qregs:
+ mkqid(&qid, QID(DEV(c->qid), Qregs), 0, QTFILE);
+ devdir(c, qid, "regs", 0, eve, 0444, dp);
+ return 1;
+ }
+ return -1;
+}
+
+static int
+tvgen(Chan *c, char *, Dirtab *, int, int i, Dir *dp)
+{
+ Qid qid;
+ int dev;
+
+ dev = DEV(c->qid);
+ switch (TYPE(c->qid)) {
+ case Qdir:
+ if (i == DEVDOTDOT) {
+ mkqid(&qid, Qdir, 0, QTDIR);
+ devdir(c, qid, "#V", 0, eve, 0555, dp);
+ return 1;
+ }
+
+ if (i >= ntvs)
+ return -1;
+
+ mkqid(&qid, QID(i, Qsubdir), 0, QTDIR);
+ snprint(up->genbuf, sizeof(up->genbuf), "tv%d", i);
+ devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+
+ case Qsubdir:
+ if (i == DEVDOTDOT) {
+ mkqid(&qid, QID(dev, Qdir), 0, QTDIR);
+ snprint(up->genbuf, sizeof(up->genbuf), "tv%d", dev);
+ devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+ }
+
+ return tv1gen(c, i + Qsubbase, dp);
+
+ case Qvdata:
+ case Qadata:
+ case Qctl:
+ case Qregs:
+ return tv1gen(c, TYPE(c->qid), dp);
+
+ default:
+ return -1;
+ }
+}
+
+static Walkqid *
+tvwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, 0, 0, tvgen);
+}
+
+static int
+tvstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, 0, 0, tvgen);
+}
+
+static Chan*
+tvopen(Chan *c, int omode)
+{
+ if (omode != OREAD &&
+ TYPE(c->qid) != Qctl && TYPE(c->qid) != Qvdata)
+ error(Eperm);
+
+ switch (TYPE(c->qid)) {
+ case Qdir:
+ return devopen(c, omode, nil, 0, tvgen);
+ case Qadata:
+ if (tvs[DEV(c->qid)].bt878 == nil)
+ error(Enonexist);
+ break;
+ }
+
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+
+ if (TYPE(c->qid) == Qadata)
+ c->aux = nil;
+ return c;
+}
+
+static void
+tvclose(Chan *)
+{
+}
+
+static int
+audioblock(void *)
+{
+ return 1;
+}
+
+static long
+tvread(Chan *c, void *a, long n, vlong offset)
+{
+ static char regs[10 * K];
+ static int regslen;
+ Tv *tv;
+ char *e, *p;
+ uchar *src;
+
+ USED(offset);
+
+ switch(TYPE(c->qid)) {
+ case Qdir:
+ case Qsubdir:
+ return devdirread(c, a, n, 0, 0, tvgen);
+
+ case Qvdata: {
+ int bpf, nb;
+
+ tv = &tvs[DEV(c->qid)];
+ bpf = ntsc_hactive * ntsc_vactive * getbitspp(tv) / 8;
+
+ if (offset >= bpf)
+ return 0;
+
+ nb = n;
+ if (offset + nb > bpf)
+ nb = bpf - offset;
+
+ ilock(tv);
+ if (tv->frames == nil || tv->lvframe >= tv->nframes ||
+ tv->frames[tv->lvframe].fbase == nil) {
+ iunlock(tv);
+ return 0;
+ }
+
+ src = tv->frames[tv->lvframe].fbase;
+ incref(&tv->fref);
+ iunlock(tv);
+
+ memmove(a, src + offset, nb);
+ decref(&tv->fref);
+ return nb;
+ }
+
+ case Qadata: {
+ ulong uablock = (ulong)c->aux, bnum, tvablock;
+ int boffs, nbytes;
+
+ tv = &tvs[DEV(c->qid)];
+ if (tv->bt878 == nil)
+ error("#V: No audio device");
+ if (tv->absize == 0)
+ error("#V: audio not initialized");
+
+ bnum = offset / tv->absize;
+ boffs = offset % tv->absize;
+ nbytes = tv->absize - boffs;
+
+ incref(&tv->aref);
+ for (;;) {
+ tvablock = tv->narblocks; /* Current tv block. */
+
+ if (uablock == 0)
+ uablock = tvablock - 1;
+
+ if (tvablock >= uablock + bnum + tv->narblocks)
+ uablock = tvablock - 1 - bnum;
+
+ if (uablock + bnum == tvablock) {
+ sleep(tv, audioblock, nil);
+ continue;
+ }
+ break;
+ }
+
+ print("uablock %ld, bnum %ld, boffs %d, nbytes %d, tvablock %ld\n",
+ uablock, bnum, boffs, nbytes, tvablock);
+ src = tv->abuf + ((uablock + bnum) % tv->nablocks) * tv->absize;
+ print("copying from %#p (abuf %#p), nbytes %d (block %ld.%ld)\n",
+ src + boffs, tv->abuf, nbytes, uablock, bnum);
+
+ memmove(a, src + boffs, nbytes);
+ decref(&tv->aref);
+
+ uablock += (boffs + nbytes) % tv->absize;
+ c->aux = (void*)uablock;
+
+ return nbytes;
+ }
+
+ case Qctl: {
+ char str[128];
+
+ tv = &tvs[DEV(c->qid)];
+ snprint(str, sizeof str, "%dx%dx%d %s channel %d %s\n",
+ ntsc_hactive, ntsc_vactive, getbitspp(tv),
+ getcolormode(tv->cfmt), tv->channel, tv->ainfo);
+ return readstr(offset, a, strlen(str) + 1, str);
+ }
+
+ case Qregs:
+ if (offset == 0) {
+ Bt848 *bt848;
+ int i;
+
+ tv = &tvs[DEV(c->qid)];
+ bt848 = tv->bt848;
+
+ e = regs + sizeof(regs);
+ p = regs;
+ for (i = 0; i < 0x300 >> 2; i++)
+ p = seprint(p, e, "%.3X %.8ulX\n", i << 2,
+ ((ulong *)bt848)[i]);
+ if (tv->bt878) {
+ bt848 = tv->bt878;
+
+ for (i = 0; i < 0x300 >> 2; i++)
+ p = seprint(p, e, "%.3X %.8ulX\n",
+ i << 2, ((ulong *)bt848)[i]);
+ }
+
+ regslen = p - regs;
+ }
+
+ if (offset >= regslen)
+ return 0;
+ if (offset + n > regslen)
+ n = regslen - offset;
+
+ return readstr(offset, a, n, &regs[offset]);
+
+ default:
+ n = 0;
+ break;
+ }
+ return n;
+}
+
+static long
+tvwrite(Chan *c, void *a, long n, vlong)
+{
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ Tv *tv;
+
+ tv = &tvs[DEV(c->qid)];
+ switch(TYPE(c->qid)) {
+ case Qctl:
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, tvctlmsg, nelem(tvctlmsg));
+ switch (ct->index) {
+ case CMvstart:
+ vstart(tv, (int)strtol(cb->f[1], (char **)nil, 0),
+ ntsc_hactive, ntsc_vactive, ntsc_hactive);
+ break;
+
+ case CMastart:
+ astart(tv, cb->f[1], (uint)strtol(cb->f[2], (char **)nil, 0),
+ (uint)strtol(cb->f[3], (char **)nil, 0),
+ (uint)strtol(cb->f[4], (char **)nil, 0));
+ break;
+
+ case CMastop:
+ astop(tv);
+ break;
+
+ case CMvgastart:
+ vgastart(tv, strtoul(cb->f[1], (char **)nil, 0),
+ (int)strtoul(cb->f[2], (char **)nil, 0));
+ break;
+
+ case CMvstop:
+ vstop(tv);
+ break;
+
+ case CMchannel:
+ frequency(tv, (int)strtol(cb->f[1], (char **)nil, 0),
+ (int)strtol(cb->f[2], (char **)nil, 0));
+ break;
+
+ case CMcolormode:
+ colormode(tv, cb->f[1]);
+ break;
+
+ case CMvolume:
+ if (!tv->msp)
+ error("#V: No volume control");
+
+ mspvolume(tv, 0, (int)strtol(cb->f[1], (char **)nil, 0),
+ (int)strtol(cb->f[2], (char **)nil, 0));
+ break;
+
+ case CMmute:
+ if (!tv->msp)
+ error("#V: No volume control");
+
+ mspvolume(tv, 1, 0, 0);
+ break;
+ }
+ poperror();
+ free(cb);
+ break;
+
+ default:
+ error(Eio);
+ }
+ return n;
+}
+
+Dev tvdevtab = {
+ 'V',
+ "tv",
+
+ devreset,
+ tvinit,
+ devshutdown,
+ tvattach,
+ tvwalk,
+ tvstat,
+ tvopen,
+ devcreate,
+ tvclose,
+ tvread,
+ devbread,
+ tvwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+static void
+tvinterrupt(Ureg *, Tv *tv)
+{
+ Bt848 *bt848 = tv->bt848, *bt878 = tv->bt878;
+
+ for (;;) {
+ ulong vstat, astat;
+ uchar fnum;
+
+ vstat = bt848->intstat;
+ fnum = (vstat >> intstat_riscstatshift) & 0xf;
+ vstat &= bt848->intmask;
+
+ if (bt878)
+ astat = bt878->intstat & bt878->intmask;
+ else
+ astat = 0;
+
+ if (vstat == 0 && astat == 0)
+ break;
+
+ if (astat)
+ print("vstat %.8luX, astat %.8luX\n", vstat, astat);
+
+ bt848->intstat = vstat;
+ if (bt878)
+ bt878->intstat = astat;
+
+ if ((vstat & intstat_fmtchg) == intstat_fmtchg) {
+ iprint("int: fmtchg\n");
+ vstat &= ~intstat_fmtchg;
+ }
+
+ if ((vstat & intstat_vpress) == intstat_vpress) {
+// iprint("int: vpress\n");
+ vstat &= ~intstat_vpress;
+ }
+
+ if ((vstat & intstat_vsync) == intstat_vsync)
+ vstat &= ~intstat_vsync;
+
+ if ((vstat & intstat_scerr) == intstat_scerr) {
+ iprint("int: scerr\n");
+ bt848->gpiodmactl &=
+ ~(gpiodmactl_riscenable|gpiodmactl_fifoenable);
+ bt848->gpiodmactl |= gpiodmactl_fifoenable;
+ bt848->gpiodmactl |= gpiodmactl_riscenable;
+ vstat &= ~intstat_scerr;
+ }
+
+ if ((vstat & intstat_risci) == intstat_risci) {
+ tv->lvframe = fnum;
+ vstat &= ~intstat_risci;
+ }
+
+ if ((vstat & intstat_ocerr) == intstat_ocerr) {
+ iprint("int: ocerr\n");
+ vstat &= ~intstat_ocerr;
+ }
+
+ if ((vstat & intstat_fbus) == intstat_fbus) {
+ iprint("int: fbus\n");
+ vstat &= ~intstat_fbus;
+ }
+
+ if (vstat)
+ iprint("int: (v) ignored interrupts %.8ulX\n", vstat);
+
+ if ((astat & intstat_risci) == intstat_risci) {
+ tv->narblocks++;
+ if ((tv->narblocks % 100) == 0)
+ print("a");
+ wakeup(tv);
+ astat &= ~intstat_risci;
+ }
+
+ if ((astat & intstat_fdsr) == intstat_fdsr) {
+ iprint("int: (a) fdsr\n");
+ bt848->gpiodmactl &=
+ ~(gpiodmactl_acapenable |
+ gpiodmactl_riscenable | gpiodmactl_fifoenable);
+ astat &= ~intstat_fdsr;
+ }
+
+ if (astat)
+ iprint("int: (a) ignored interrupts %.8ulX\n", astat);
+ }
+}
+
+static int
+i2cread(Tv *tv, uchar off, uchar *v)
+{
+ Bt848 *bt848 = tv->bt848;
+ ulong intstat;
+ int i;
+
+ bt848->intstat = intstat_i2cdone;
+ bt848->i2c = (off << 24) | tv->i2ccmd;
+
+ intstat = -1;
+ for (i = 0; i != 1000; i++) {
+ if ((intstat = bt848->intstat) & intstat_i2cdone)
+ break;
+ microdelay(1000);
+ }
+
+ if (i == 1000) {
+ print("i2cread: timeout\n");
+ return 0;
+ }
+
+ if ((intstat & intstat_i2crack) == 0)
+ return 0;
+
+ *v = bt848->i2c >> 8;
+ return 1;
+}
+
+static int
+i2cwrite(Tv *tv, uchar addr, uchar sub, uchar data, int both)
+{
+ Bt848 *bt848 = tv->bt848;
+ ulong intstat, d;
+ int i;
+
+ bt848->intstat = intstat_i2cdone;
+ d = (addr << 24) | (sub << 16) | tv->i2ccmd;
+ if (both)
+ d |= (data << 8) | i2c_bt848w3b;
+ bt848->i2c = d;
+
+ intstat = 0;
+ for (i = 0; i != 1000; i++) {
+ if ((intstat = bt848->intstat) & intstat_i2cdone)
+ break;
+ microdelay(1000);
+ }
+
+ if (i == i2c_timeout) {
+ print("i2cwrite: timeout\n");
+ return 0;
+ }
+
+ if ((intstat & intstat_i2crack) == 0)
+ return 0;
+
+ return 1;
+}
+
+static ulong *
+riscpacked(ulong pa, int fnum, int w, int h, int stride, ulong **lastjmp)
+{
+ ulong *p, *pbase;
+ int i;
+
+ pbase = p = (ulong *)malloc((h + 6) * 2 * sizeof(ulong));
+ assert(p);
+
+ assert(w <= 0x7FF);
+
+ *p++ = riscsync | riscsync_resync | riscsync_vre;
+ *p++ = 0;
+
+ *p++ = riscsync | riscsync_fm1;
+ *p++ = 0;
+
+ for (i = 0; i != h / 2; i++) {
+ *p++ = riscwrite | w | riscwrite_sol | riscwrite_eol;
+ *p++ = pa + i * 2 * stride;
+ }
+
+ *p++ = riscsync | riscsync_resync | riscsync_vro;
+ *p++ = 0;
+
+ *p++ = riscsync | riscsync_fm1;
+ *p++ = 0;
+
+ for (i = 0; i != h / 2; i++) {
+ *p++ = riscwrite | w | riscwrite_sol | riscwrite_eol;
+ *p++ = pa + (i * 2 + 1) * stride;
+ }
+
+ /* reset status. you really need two instructions ;-(. */
+ *p++ = riscjmp | (0xf << risclabelshift_reset);
+ *p++ = PADDR(p);
+ *p++ = riscjmp | riscirq | (fnum << risclabelshift_set);
+ *lastjmp = p;
+
+ return pbase;
+}
+
+static ulong *
+riscplanar411(ulong pa, int fnum, int w, int h, ulong **lastjmp)
+{
+ ulong *p, *pbase, Cw, Yw, Ch;
+ uchar *Ybase, *Cbbase, *Crbase;
+ int i, bitspp;
+
+ bitspp = 6;
+ assert(w * bitspp / 8 <= 0x7FF);
+ pbase = p = (ulong *)malloc((h + 6) * 5 * sizeof(ulong));
+ assert(p);
+
+ Yw = w;
+ Ybase = (uchar *)pa;
+ Cw = w >> 1;
+ Ch = h >> 1;
+ Cbbase = Ybase + Yw * h;
+ Crbase = Cbbase + Cw * Ch;
+
+ *p++ = riscsync | riscsync_resync | riscsync_vre;
+ *p++ = 0;
+
+ *p++ = riscsync | riscsync_fm3;
+ *p++ = 0;
+
+ for (i = 0; i != h / 2; i++) {
+ *p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;
+ *p++ = (Cw << 16) | Cw;
+ *p++ = (ulong)(Ybase + i * 2 * Yw);
+ *p++ = (ulong)(Cbbase + i * Cw); /* Do not interlace */
+ *p++ = (ulong)(Crbase + i * Cw);
+ }
+
+ *p++ = riscsync | riscsync_resync | riscsync_vro;
+ *p++ = 0;
+
+ *p++ = riscsync | riscsync_fm3;
+ *p++ = 0;
+
+ for (i = 0; i != h / 2; i++) {
+ *p++ = riscwrite1s23 | Yw | riscwrite_sol | riscwrite_eol;
+ *p++ = (Cw << 16) | Cw;
+ *p++ = (ulong)(Ybase + (i * 2 + 1) * Yw);
+ }
+
+ /* reset status. you really need two instructions ;-(. */
+ *p++ = riscjmp | (0xf << risclabelshift_reset);
+ *p++ = PADDR(p);
+ *p++ = riscjmp | riscirq | (fnum << risclabelshift_set);
+ *lastjmp = p;
+
+ return pbase;
+}
+
+static ulong *
+riscplanar422(ulong pa, int fnum, int w, int h, ulong **lastjmp)
+{
+ ulong *p, *pbase, Cw, Yw;
+ uchar *Ybase, *Cbbase, *Crbase;
+ int i, bpp;
+
+ bpp = 2;
+ assert(w * bpp <= 0x7FF);
+ pbase = p = (ulong *)malloc((h + 6) * 5 * sizeof(ulong));
+ assert(p);
+
+ Yw = w;
+ Ybase = (uchar *)pa;
+ Cw = w >> 1;
+ Cbbase = Ybase + Yw * h;
+ Crbase = Cbbase + Cw * h;
+
+ *p++ = riscsync | riscsync_resync | riscsync_vre;
+ *p++ = 0;
+
+ *p++ = riscsync | riscsync_fm3;
+ *p++ = 0;
+
+ for (i = 0; i != h / 2; i++) {
+ *p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;
+ *p++ = (Cw << 16) | Cw;
+ *p++ = (ulong)(Ybase + i * 2 * Yw);
+ *p++ = (ulong)(Cbbase + i * 2 * Cw);
+ *p++ = (ulong)(Crbase + i * 2 * Cw);
+ }
+
+ *p++ = riscsync | riscsync_resync | riscsync_vro;
+ *p++ = 0;
+
+ *p++ = riscsync | riscsync_fm3;
+ *p++ = 0;
+
+ for (i = 0; i != h / 2; i++) {
+ *p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;
+ *p++ = (Cw << 16) | Cw;
+ *p++ = (ulong)(Ybase + (i * 2 + 1) * Yw);
+ *p++ = (ulong)(Cbbase + (i * 2 + 1) * Cw);
+ *p++ = (ulong)(Crbase + (i * 2 + 1) * Cw);
+ }
+
+ /* reset status. you really need two instructions ;-(. */
+ *p++ = riscjmp | (0xf << risclabelshift_reset);
+ *p++ = PADDR(p);
+ *p++ = riscjmp | riscirq | (fnum << risclabelshift_set);
+ *lastjmp = p;
+
+ return pbase;
+}
+
+static ulong *
+riscaudio(ulong pa, int nblocks, int bsize)
+{
+ ulong *p, *pbase;
+ int i;
+
+ pbase = p = (ulong *)malloc((nblocks + 3) * 2 * sizeof(ulong));
+ assert(p);
+
+ *p++ = riscsync|riscsync_fm1;
+ *p++ = 0;
+
+ for (i = 0; i != nblocks; i++) {
+ *p++ = riscwrite | riscwrite_sol | riscwrite_eol | bsize | riscirq |
+ ((i & 0xf) << risclabelshift_set) |
+ ((~i & 0xf) << risclabelshift_reset);
+ *p++ = pa + i * bsize;
+ }
+
+ *p++ = riscsync | riscsync_vro;
+ *p++ = 0;
+ *p++ = riscjmp;
+ *p++ = PADDR(pbase);
+ USED(p);
+
+ return pbase;
+}
+
+
+static void
+vactivate(Tv *tv, Frame *frames, int nframes)
+{
+ Bt848 *bt848 = tv->bt848;
+
+ ilock(tv);
+ if (tv->frames) {
+ iunlock(tv);
+ error(Einuse);
+ }
+ poperror();
+
+ tv->frames = frames;
+ tv->nframes = nframes;
+
+ bt848->riscstrtadd = PADDR(tv->frames[0].fstart);
+ bt848->capctl |= capctl_captureodd|capctl_captureeven;
+ bt848->gpiodmactl |= gpiodmactl_fifoenable;
+ bt848->gpiodmactl |= gpiodmactl_riscenable;
+
+ iunlock(tv);
+}
+
+static void
+vstart(Tv *tv, int nframes, int w, int h, int stride)
+{
+ Frame *frames;
+ int bitspp, i, bpf;
+
+ if (nframes >= 0x10)
+ error(Ebadarg);
+
+ bitspp = getbitspp(tv);
+ bpf = w * h * bitspp / 8;
+
+ /* Add one as a spare. */
+ frames = (Frame *)malloc(nframes * sizeof(Frame));
+ assert(frames);
+ if (waserror()) {
+ for (i = 0; i != nframes; i++)
+ if (frames[i].fbase)
+ free(frames[i].fbase);
+ free(frames);
+ nexterror();
+ }
+ memset(frames, 0, nframes * sizeof(Frame));
+
+ for (i = 0; i != nframes; i++) {
+ if ((frames[i].fbase = (uchar *)malloc(bpf)) == nil)
+ error(Enomem);
+
+ switch (tv->cfmt) {
+ case colorfmt_YCbCr422:
+ frames[i].fstart = riscplanar422(PADDR(frames[i].fbase), i, w, h, &frames[i].fjmp);
+ break;
+ case colorfmt_YCbCr411:
+ frames[i].fstart = riscplanar411(PADDR(frames[i].fbase),
+ i, w, h, &frames[i].fjmp);
+ break;
+ case colorfmt_rgb16:
+ frames[i].fstart = riscpacked(PADDR(frames[i].fbase), i,
+ w * bitspp / 8, h, stride * bitspp / 8,
+ &frames[i].fjmp);
+ break;
+ default:
+ panic("vstart: Unsupport colorformat\n");
+ }
+ }
+
+ for (i = 0; i != nframes; i++)
+ *frames[i].fjmp = PADDR(i == nframes - 1? frames[0].fstart:
+ frames[i + 1].fstart);
+
+ vactivate(tv, frames, nframes);
+}
+
+static void
+astart(Tv *tv, char *input, uint rate, uint nab, uint nasz)
+{
+ Bt848 *bt878 = tv->bt878;
+ ulong *arisc;
+ int selector;
+ uchar *abuf;
+ int s, d;
+
+ if (bt878 == nil || tv->amux == nil)
+ error("#V: Card does not support audio");
+
+ selector = 0;
+ if (!strcmp(input, "tv"))
+ selector = asel_tv;
+ else if (!strcmp(input, "radio"))
+ selector = asel_radio;
+ else if (!strcmp(input, "mic"))
+ selector = asel_mic;
+ else if (!strcmp(input, "smxc"))
+ selector = asel_smxc;
+ else
+ error("#V: Invalid input");
+
+ if (nasz > 0xfff)
+ error("#V: Audio block size too big (max 0xfff)");
+
+ abuf = (uchar *)malloc(nab * nasz * sizeof(uchar));
+ assert(abuf);
+ arisc = riscaudio(PADDR(abuf), nab, nasz);
+
+ ilock(tv);
+ if (tv->arisc) {
+ iunlock(tv);
+ free(abuf);
+ free(arisc);
+ error(Einuse);
+ }
+
+ tv->arisc = arisc;
+ tv->abuf = abuf;
+ tv->nablocks = nab;
+ tv->absize = nasz;
+
+ bt878->riscstrtadd = PADDR(tv->arisc);
+ bt878->packetlen = (nab << 16) | nasz;
+ bt878->intmask = intstat_scerr | intstat_ocerr | intstat_risci |
+ intstat_pabort | intstat_riperr | intstat_pperr |
+ intstat_fdsr | intstat_ftrgt | intstat_fbus;
+
+ /* Assume analog, 16bpp */
+ for (s = 0; s < 16; s++)
+ if (rate << s > Hwbase_ad * 4 / 15)
+ break;
+ for (d = 15; d >= 4; d--)
+ if (rate << s < Hwbase_ad * 4 / d)
+ break;
+
+ print("astart: sampleshift %d, decimation %d\n", s, d);
+
+ tv->narblocks = 0;
+ bt878->gpiodmactl = gpiodmactl_fifoenable |
+ gpiodmactl_riscenable | gpiodmactl_acapenable |
+ gpiodmactl_daes2 | /* gpiodmactl_apwrdn | */
+ gpiodmactl_daiomda | d << 8 | 9 << 28 | selector << 24;
+ print("dmactl %.8ulX\n", bt878->gpiodmactl);
+ iunlock(tv);
+}
+
+static void
+astop(Tv *tv)
+{
+ Bt848 *bt878 = tv->bt878;
+
+ ilock(tv);
+ if (tv->aref.ref > 0) {
+ iunlock(tv);
+ error(Einuse);
+ }
+
+ if (tv->abuf) {
+ bt878->gpiodmactl &= ~gpiodmactl_riscenable;
+ bt878->gpiodmactl &= ~gpiodmactl_fifoenable;
+
+ free(tv->abuf);
+ tv->abuf = nil;
+ free(tv->arisc);
+ tv->arisc = nil;
+ }
+ iunlock(tv);
+}
+
+static void
+vgastart(Tv *tv, ulong pa, int stride)
+{
+ Frame *frame;
+
+ frame = (Frame *)malloc(sizeof(Frame));
+ assert(frame);
+ if (waserror()) {
+ free(frame);
+ nexterror();
+ }
+
+ frame->fbase = nil;
+ frame->fstart = riscpacked(pa, 0, ntsc_hactive * getbitspp(tv) / 8,
+ ntsc_vactive, stride * getbitspp(tv) / 8, &frame->fjmp);
+ *frame->fjmp = PADDR(frame->fstart);
+
+ vactivate(tv, frame, 1);
+}
+
+static void
+vstop(Tv *tv)
+{
+ Bt848 *bt848 = tv->bt848;
+
+ ilock(tv);
+ if (tv->fref.ref > 0) {
+ iunlock(tv);
+ error(Einuse);
+ }
+
+ if (tv->frames) {
+ int i;
+
+ bt848->gpiodmactl &= ~gpiodmactl_riscenable;
+ bt848->gpiodmactl &= ~gpiodmactl_fifoenable;
+ bt848->capctl &= ~(capctl_captureodd|capctl_captureeven);
+
+ for (i = 0; i != tv->nframes; i++)
+ if (tv->frames[i].fbase)
+ free(tv->frames[i].fbase);
+ free(tv->frames);
+ tv->frames = nil;
+ }
+ iunlock(tv);
+}
+
+static long hrcfreq[] = { /* HRC CATV frequencies */
+ 0, 7200, 5400, 6000, 6600, 7800, 8400, 17400,
+ 18000, 18600, 19200, 19800, 20400, 21000, 12000, 12600,
+ 13200, 13800, 14400, 15000, 15600, 16200, 16800, 21600,
+ 22200, 22800, 23400, 24000, 24600, 25200, 25800, 26400,
+ 27000, 27600, 28200, 28800, 29400, 30000, 30600, 31200,
+ 31800, 32400, 33000, 33600, 34200, 34800, 35400, 36000,
+ 36600, 37200, 37800, 38400, 39000, 39600, 40200, 40800,
+ 41400, 42000, 42600, 43200, 43800, 44400, 45000, 45600,
+ 46200, 46800, 47400, 48000, 48600, 49200, 49800, 50400,
+ 51000, 51600, 52200, 52800, 53400, 54000, 54600, 55200,
+ 55800, 56400, 57000, 57600, 58200, 58800, 59400, 60000,
+ 60600, 61200, 61800, 62400, 63000, 63600, 64200, 9000,
+ 9600, 10200, 10800, 11400, 64800, 65400, 66000, 66600,
+ 67200, 67800, 68400, 69000, 69600, 70200, 70800, 71400,
+ 72000, 72600, 73200, 73800, 74400, 75000, 75600, 76200,
+ 76800, 77400, 78000, 78600, 79200, 79800,
+};
+
+static void
+frequency(Tv *tv, int channel, int finetune)
+{
+ Tuner *tuner = tv->tuner;
+ long freq;
+ ushort div;
+ uchar cfg;
+
+ if (channel < 0 || channel > nelem(hrcfreq))
+ error(Ebadarg);
+
+ freq = (hrcfreq[channel] * Freqmultiplier) / 100;
+
+ if (freq < tuner->freq_vhfh)
+ cfg = tuner->VHF_L;
+ else if (freq < tuner->freq_uhf)
+ cfg = tuner->VHF_H;
+ else
+ cfg = tuner->UHF;
+
+ div = (freq + tuner->offs + finetune) & 0x7fff;
+
+ if (!i2cwrite(tv, tv->i2ctuneraddr, (div >> 8) & 0x7f, div, 1))
+ error(Eio);
+
+ if (!i2cwrite(tv, tv->i2ctuneraddr, tuner->cfg, cfg, 1))
+ error(Eio);
+
+ tv->channel = channel;
+ if (tv->msp)
+ msptune(tv);
+}
+
+static struct {
+ char *cmode;
+ ulong realmode;
+ ulong cbits;
+} colormodes[] = {
+ { "RGB16", colorfmt_rgb16, colorfmt_rgb16, },
+ { "YCbCr422", colorfmt_YCbCr422, colorfmt_YCbCr422, },
+ { "YCbCr411", colorfmt_YCbCr411, colorfmt_YCbCr422, },
+};
+
+static void
+colormode(Tv *tv, char *colormode)
+{
+ Bt848 *bt848 = tv->bt848;
+ int i;
+
+ for (i = 0; i != nelem(colormodes); i++)
+ if (!strcmp(colormodes[i].cmode, colormode))
+ break;
+
+ if (i == nelem(colormodes))
+ error(Ebadarg);
+
+ tv->cfmt = colormodes[i].realmode;
+ bt848->colorfmt = colormodes[i].cbits;
+}
+
+static int
+getbitspp(Tv *tv)
+{
+ switch (tv->cfmt) {
+ case colorfmt_rgb16:
+ case colorfmt_YCbCr422:
+ return 16;
+ case colorfmt_YCbCr411:
+ return 12;
+ default:
+ error("getbitspp: Unsupport color format\n");
+ }
+ return -1;
+}
+
+static char *
+getcolormode(ulong cmode)
+{
+ switch (cmode) {
+ case colorfmt_rgb16:
+ return "RGB16";
+ case colorfmt_YCbCr411:
+ return "YCbCr411";
+ case colorfmt_YCbCr422:
+ return (cmode == colorfmt_YCbCr422)? "YCbCr422": "YCbCr411";
+ default:
+ error("getcolormode: Unsupport color format\n");
+ }
+ return nil;
+}
+
+static void
+i2c_set(Tv *tv, int scl, int sda)
+{
+ Bt848 *bt848 = tv->bt848;
+ ulong d;
+
+ bt848->i2c = (scl << 1) | sda;
+ d = bt848->i2c;
+ USED(d);
+ microdelay(i2c_delay);
+}
+
+static uchar
+i2c_getsda(Tv *tv)
+{
+ Bt848 *bt848 = tv->bt848;
+
+ return bt848->i2c & i2c_sda;
+}
+
+static void
+i2c_start(Tv *tv)
+{
+ i2c_set(tv, 0, 1);
+ i2c_set(tv, 1, 1);
+ i2c_set(tv, 1, 0);
+ i2c_set(tv, 0, 0);
+}
+
+static void
+i2c_stop(Tv *tv)
+{
+ i2c_set(tv, 0, 0);
+ i2c_set(tv, 1, 0);
+ i2c_set(tv, 1, 1);
+}
+
+static void
+i2c_bit(Tv *tv, int sda)
+{
+ i2c_set(tv, 0, sda);
+ i2c_set(tv, 1, sda);
+ i2c_set(tv, 0, sda);
+}
+
+static int
+i2c_getack(Tv *tv)
+{
+ int ack;
+
+ i2c_set(tv, 0, 1);
+ i2c_set(tv, 1, 1);
+ ack = i2c_getsda(tv);
+ i2c_set(tv, 0, 1);
+ return ack;
+}
+
+static int
+i2c_wr8(Tv *tv, uchar d, int wait)
+{
+ int i, ack;
+
+ i2c_set(tv, 0, 0);
+ for (i = 0; i != 8; i++) {
+ i2c_bit(tv, (d & 0x80)? 1: 0);
+ d <<= 1;
+ }
+ if (wait)
+ microdelay(wait);
+
+ ack = i2c_getack(tv);
+ return ack == 0;
+}
+
+static uchar
+i2c_rd8(Tv *tv, int lastbyte)
+{
+ int i;
+ uchar d;
+
+ d = 0;
+ i2c_set(tv, 0, 1);
+ for (i = 0; i != 8; i++) {
+ i2c_set(tv, 1, 1);
+ d <<= 1;
+ if (i2c_getsda(tv))
+ d |= 1;
+ i2c_set(tv, 0, 1);
+ }
+
+ i2c_bit(tv, lastbyte? 1: 0);
+ return d;
+}
+
+static int
+mspsend(Tv *tv, uchar *cmd, int ncmd)
+{
+ int i, j, delay;
+
+ for (i = 0; i != 3; i++) {
+ delay = 2000;
+
+ i2c_start(tv);
+ for (j = 0; j != ncmd; j++) {
+ if (!i2c_wr8(tv, cmd[j], delay))
+ break;
+ delay = 0;
+ }
+ i2c_stop(tv);
+
+ if (j == ncmd)
+ return 1;
+
+ microdelay(10000);
+ print("mspsend: retrying\n");
+ }
+
+ return 0;
+}
+
+static int
+mspwrite(Tv *tv, uchar sub, ushort reg, ushort v)
+{
+ uchar b[6];
+
+ b[0] = i2c_msp3400;
+ b[1] = sub;
+ b[2] = reg >> 8;
+ b[3] = reg;
+ b[4] = v >> 8;
+ b[5] = v;
+ return mspsend(tv, b, sizeof b);
+}
+
+static int
+mspread(Tv *tv, uchar sub, ushort reg, ushort *data)
+{
+ uchar b[4];
+ int i;
+
+ b[0] = i2c_msp3400;
+ b[1] = sub;
+ b[2] = reg >> 8;
+ b[3] = reg;
+
+ for (i = 0; i != 3; i++) {
+ i2c_start(tv);
+ if (!i2c_wr8(tv, b[0], 2000) ||
+ !i2c_wr8(tv, b[1] | 1, 0) ||
+ !i2c_wr8(tv, b[2], 0) ||
+ !i2c_wr8(tv, b[3], 0)) {
+
+ i2c_stop(tv);
+ microdelay(10000);
+ print("retrying\n");
+ continue;
+ }
+
+ i2c_start(tv);
+
+ if (!i2c_wr8(tv, b[0] | 1, 2000)) {
+ i2c_stop(tv);
+ continue;
+ }
+
+ *data = i2c_rd8(tv, 0) << 8;
+ *data |= i2c_rd8(tv, 1);
+ i2c_stop(tv);
+ return 1;
+ }
+ return 0;
+}
+
+static uchar mspt_reset[] = { i2c_msp3400, 0, 0x80, 0 };
+static uchar mspt_on[] = { i2c_msp3400, 0, 0, 0 };
+
+static int
+mspreset(Tv *tv)
+{
+ ushort v, p;
+ Bt848 *bt848 = tv->bt848;
+ ulong b;
+
+ b = 1 << 5;
+ gpioenable(tv, ~b, b);
+ gpiowrite(tv, ~b, 0);
+ microdelay(2500);
+ gpiowrite(tv, ~b, b);
+
+ bt848->i2c = 0x80;
+
+ microdelay(2000);
+ mspsend(tv, mspt_reset, sizeof mspt_reset);
+
+ microdelay(2000);
+ if (!mspsend(tv, mspt_on, sizeof mspt_on)) {
+ print("#V: Cannot find MSP34x5G on the I2C bus (on)\n");
+ return 0;
+ }
+ microdelay(2000);
+
+ if (!mspread(tv, msp_bbp, 0x001e, &v)) {
+ print("#V: Cannot read MSP34xG5 chip version\n");
+ return 0;
+ }
+
+ if (!mspread(tv, msp_bbp, 0x001f, &p)) {
+ print("#V: Cannot read MSP34xG5 product code\n");
+ return 0;
+ }
+
+ print("#V: MSP34%dg ROM %.d, %d.%d\n",
+ (uchar)(p >> 8), (uchar)p, (uchar)(v >> 8), (uchar)v);
+
+ tv->msp = 1;
+ return 1;
+}
+
+static void
+mspvolume(Tv *tv, int mute, int l, int r)
+{
+ short v, d;
+ ushort b;
+
+ if (mute) {
+ v = 0;
+ b = 0;
+ }
+ else {
+ tv->aleft = l;
+ tv->aright = r;
+ d = v = max(l, r);
+ if (d == 0)
+ d++;
+ b = ((r - l) * 0x7f) / d;
+ }
+
+ mspwrite(tv, msp_bbp, 0, v << 8);
+ mspwrite(tv, msp_bbp, 7, v? 0x4000: 0);
+ mspwrite(tv, msp_bbp, 1, b << 8);
+}
+
+static char *
+mspaformat(int f)
+{
+ switch (f) {
+ case 0:
+ return "unknown";
+ case 2:
+ case 0x20:
+ case 0x30:
+ return "M-BTSC";
+ case 3:
+ return "B/G-FM";
+ case 4:
+ case 9:
+ case 0xB:
+ return "L-AM/NICAM D/Kn";
+ case 8:
+ return "B/G-NICAM";
+ case 0xA:
+ return "I";
+ case 0x40:
+ return "FM-Radio";
+ }
+ return "unknown format";
+}
+
+
+static void
+msptune(Tv *tv)
+{
+ ushort d, s, nicam;
+ int i;
+
+ mspvolume(tv, 1, 0, 0);
+ if (!mspwrite(tv, msp_dem, 0x0030, 0x2033))
+ error("#V: Cannot set MODUS register");
+
+ if (!mspwrite(tv, msp_bbp, 0x0008, 0x0320))
+ error("#V: Cannot set loadspeaker input");
+
+ if (!mspwrite(tv, msp_dem, 0x0040, 0x0001))
+ error("#V: Cannot set I2S clock freq");
+ if (!mspwrite(tv, msp_bbp, 0x000d, 0x1900))
+ error("#V: Cannot set SCART prescale");
+ if (!mspwrite(tv, msp_bbp, 0x000e, 0x2403))
+ error("#V: Cannot set FM/AM prescale");
+ if (!mspwrite(tv, msp_bbp, 0x0010, 0x5a00))
+ error("#V: Cannot set NICAM prescale");
+ if (!mspwrite(tv, msp_dem, 0x0020, 0x0001))
+ error("#V: Cannot start auto detect");
+
+ for (d = (ushort)-1, i = 0; i != 10; i++) {
+ if (!mspread(tv, msp_dem, 0x007e, &d))
+ error("#V: Cannot get autodetect info MSP34xG5");
+
+ if (d == 0 || d < 0x800)
+ break;
+ delay(50);
+ }
+
+ if (!mspread(tv, msp_dem, 0x0200, &s))
+ error("#V: Cannot get status info MSP34xG5");
+
+ mspvolume(tv, 0, tv->aleft, tv->aright);
+
+ nicam = ((s >> 4) & 2) | ((s >> 9) & 1);
+ snprint(tv->ainfo, sizeof tv->ainfo, "%s %s %s",
+ mspaformat(d), (s & (1 << 6))? "stereo": "mono",
+ nicamstate[nicam]);
+}
+
+static void
+i2cscan(Tv *tv)
+{
+ int i, ack;
+
+ for (i = 0; i < 0x100; i += 2) {
+ i2c_start(tv);
+ ack = i2c_wr8(tv, i, 0);
+ i2c_stop(tv);
+ if (ack)
+ print("i2c device @%.2uX\n", i);
+ }
+
+ for (i = 0xf0; i != 0xff; i++) {
+ i2c_start(tv);
+ ack = i2c_wr8(tv, i, 0);
+ i2c_stop(tv);
+ if (ack)
+ print("i2c device may be at @%.2uX\n", i);
+ }
+}
+
+static void
+gpioenable(Tv *tv, ulong mask, ulong data)
+{
+ Bt848 *bt848 = tv->bt848;
+
+ bt848->gpioouten = (bt848->gpioouten & mask) | data;
+}
+
+static void
+gpiowrite(Tv *tv, ulong mask, ulong data)
+{
+ Bt848 *bt848 = tv->bt848;
+
+ bt848->gpiodata[0] = (bt848->gpiodata[0] & mask) | data;
+}
+
+static void
+alteraoutput(Tv *tv)
+{
+ if (tv->gpiostate == Gpiooutput)
+ return;
+
+ gpioenable(tv, ~0xffffff, 0x56ffff);
+ microdelay(10);
+ tv->gpiostate = Gpiooutput;
+}
+
+static void
+alterainput(Tv *tv)
+{
+ if (tv->gpiostate == Gpioinput)
+ return;
+
+ gpioenable(tv, ~0xffffff, 0x570000);
+ microdelay(10);
+ tv->gpiostate = Gpioinput;
+}
+
+static void
+alterareg(Tv *tv, ulong reg)
+{
+ if (tv->alterareg == reg)
+ return;
+
+ gpiowrite(tv, ~0x56ffff, (reg & 0x54ffff) | tv->alteraclock);
+ microdelay(10);
+ tv->alterareg = reg;
+}
+
+static void
+alterawrite(Tv *tv, ulong reg, ushort data)
+{
+ alteraoutput(tv);
+ alterareg(tv, reg);
+
+ tv->alteraclock ^= 0x20000;
+ gpiowrite(tv, ~0x56ffff, (reg & 0x540000) | data | tv->alteraclock);
+ microdelay(10);
+}
+
+static void
+alteraread(Tv *tv, int reg, ushort *data)
+{
+ Bt848 *bt848 = tv->bt848;
+
+ if (tv->alterareg != reg) {
+ alteraoutput(tv);
+ alterareg(tv, reg);
+ }
+ else {
+ gpioenable(tv, ~0xffffff, 0x560000);
+ microdelay(10);
+ }
+
+ alterainput(tv);
+ gpiowrite(tv, ~0x570000, (reg & 0x560000) | tv->alteraclock);
+ microdelay(10);
+ *data = (ushort)bt848->gpiodata[0];
+ microdelay(10);
+}
+
+static void
+kfirloadu(Tv *tv, uchar *u, int ulen)
+{
+ Bt848 *bt848 = tv->bt848;
+ int i, j;
+
+ ilock(&tv->kfirlock);
+ bt848->gpioouten &= 0xff000000;
+ bt848->gpioouten |= gpio_altera_data |
+ gpio_altera_clock | gpio_altera_nconfig;
+ bt848->gpiodata[0] &= 0xff000000;
+ microdelay(10);
+ bt848->gpiodata[0] |= gpio_altera_nconfig;
+ microdelay(10);
+
+ /* Download the microcode */
+ for (i = 0; i != ulen; i++)
+ for (j = 0; j != 8; j++) {
+ bt848->gpiodata[0] &= ~(gpio_altera_clock|gpio_altera_data);
+ if (u[i] & 1)
+ bt848->gpiodata[0] |= gpio_altera_data;
+ bt848->gpiodata[0] |= gpio_altera_clock;
+ u[i] >>= 1;
+ }
+ bt848->gpiodata[0] &= ~gpio_altera_clock;
+ microdelay(100);
+
+ /* Initialize. */
+ for (i = 0; i != 30; i++) {
+ bt848->gpiodata[0] &= ~gpio_altera_clock;
+ bt848->gpiodata[0] |= gpio_altera_clock;
+ }
+ bt848->gpiodata[0] &= ~(gpio_altera_clock|gpio_altera_data);
+ iunlock(&tv->kfirlock);
+
+ tv->gpiostate = Gpioinit;
+}
+
+static void
+kfirreset(Tv *tv)
+{
+ alterawrite(tv, 0, 0);
+ microdelay(10);
+ alterawrite(tv, 0x40000, 0);
+ microdelay(10);
+ alterawrite(tv, 0x40006, 0x80);
+ microdelay(10);
+ alterawrite(tv, 8, 1);
+ microdelay(10);
+ alterawrite(tv, 0x40004, 2);
+ microdelay(10);
+ alterawrite(tv, 4, 3);
+ microdelay(3);
+}
+
+static int
+kfirinitialize(Tv *tv)
+{
+ /* Initialize parameters? */
+
+ tv->gpiostate = Gpioinit;
+ tv->alterareg = -1;
+ tv->alteraclock = 0x20000;
+ kfirloadu(tv, hcwAMC, sizeof hcwAMC);
+ kfirreset(tv);
+ return 1;
+}
diff --git a/sys/src/9/pc/devusb.c b/sys/src/9/pc/devusb.c
new file mode 100755
index 000000000..fc87bbcca
--- /dev/null
+++ b/sys/src/9/pc/devusb.c
@@ -0,0 +1,1479 @@
+/*
+ * USB device driver framework.
+ *
+ * This is in charge of providing access to actual HCIs
+ * and providing I/O to the various endpoints of devices.
+ * A separate user program (usbd) is in charge of
+ * enumerating the bus, setting up endpoints and
+ * starting devices (also user programs).
+ *
+ * The interface provided is a violation of the standard:
+ * you're welcome.
+ *
+ * The interface consists of a root directory with several files
+ * plus a directory (epN.M) with two files per endpoint.
+ * A device is represented by its first endpoint, which
+ * is a control endpoint automatically allocated for each device.
+ * Device control endpoints may be used to create new endpoints.
+ * Devices corresponding to hubs may also allocate new devices,
+ * perhaps also hubs. Initially, a hub device is allocated for
+ * each controller present, to represent its root hub. Those can
+ * never be removed.
+ *
+ * All endpoints refer to the first endpoint (epN.0) of the device,
+ * which keeps per-device information, and also to the HCI used
+ * to reach them. Although all endpoints cache that information.
+ *
+ * epN.M/data files permit I/O and are considered DMEXCL.
+ * epN.M/ctl files provide status info and accept control requests.
+ *
+ * Endpoints may be given file names to be listed also at #u,
+ * for those drivers that have nothing to do after configuring the
+ * device and its endpoints.
+ *
+ * Drivers for different controllers are kept at usb[oue]hci.c
+ * It's likely we could factor out much from controllers into
+ * a generic controller driver, the problem is that details
+ * regarding how to handle toggles, tokens, Tds, etc. will
+ * get in the way. Thus, code is probably easier the way it is.
+ */
+
+#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/usb.h"
+
+typedef struct Hcitype Hcitype;
+
+enum
+{
+ /* Qid numbers */
+ Qdir = 0, /* #u */
+ Qusbdir, /* #u/usb */
+ Qctl, /* #u/usb/ctl - control requests */
+
+ Qep0dir, /* #u/usb/ep0.0 - endpoint 0 dir */
+ Qep0io, /* #u/usb/ep0.0/data - endpoint 0 I/O */
+ Qep0ctl, /* #u/usb/ep0.0/ctl - endpoint 0 ctl. */
+ Qep0dummy, /* give 4 qids to each endpoint */
+
+ Qepdir = 0, /* (qid-qep0dir)&3 is one of these */
+ Qepio, /* to identify which file for the endpoint */
+ Qepctl,
+
+ /* ... */
+
+ /* Usb ctls. */
+ CMdebug = 0, /* debug on|off */
+ CMdump, /* dump (data structures for debug) */
+
+ /* Ep. ctls */
+ CMnew = 0, /* new nb ctl|bulk|intr|iso r|w|rw (endpoint) */
+ CMnewdev, /* newdev full|low|high portnb (allocate new devices) */
+ CMhub, /* hub (set the device as a hub) */
+ CMspeed, /* speed full|low|high|no */
+ CMmaxpkt, /* maxpkt size */
+ CMntds, /* ntds nb (max nb. of tds per µframe) */
+ CMclrhalt, /* clrhalt (halt was cleared on endpoint) */
+ CMpollival, /* pollival interval (interrupt/iso) */
+ CMhz, /* hz n (samples/sec; iso) */
+ CMsamplesz, /* samplesz n (sample size; iso) */
+ CMinfo, /* info infostr (ke.ep info for humans) */
+ CMdetach, /* detach (abort I/O forever on this ep). */
+ CMaddress, /* address (address is assigned) */
+ CMdebugep, /* debug n (set/clear debug for this ep) */
+ CMname, /* name str (show up as #u/name as well) */
+ CMtmout, /* timeout n (activate timeouts for ep) */
+ CMpreset, /* reset the port */
+
+ /* Hub feature selectors */
+ Rportenable = 1,
+ Rportreset = 4,
+
+};
+
+struct Hcitype
+{
+ char* type;
+ int (*reset)(Hci*);
+};
+
+#define QID(q) ((int)(q).path)
+
+static char Edetach[] = "device is detached";
+static char Enotconf[] = "endpoint not configured";
+char Estalled[] = "endpoint stalled";
+
+static Cmdtab usbctls[] =
+{
+ {CMdebug, "debug", 2},
+ {CMdump, "dump", 1},
+};
+
+static Cmdtab epctls[] =
+{
+ {CMnew, "new", 4},
+ {CMnewdev, "newdev", 3},
+ {CMhub, "hub", 1},
+ {CMspeed, "speed", 2},
+ {CMmaxpkt, "maxpkt", 2},
+ {CMntds, "ntds", 2},
+ {CMpollival, "pollival", 2},
+ {CMsamplesz, "samplesz", 2},
+ {CMhz, "hz", 2},
+ {CMinfo, "info", 0},
+ {CMdetach, "detach", 1},
+ {CMaddress, "address", 1},
+ {CMdebugep, "debug", 2},
+ {CMclrhalt, "clrhalt", 1},
+ {CMname, "name", 2},
+ {CMtmout, "timeout", 2},
+ {CMpreset, "reset", 1},
+};
+
+static Dirtab usbdir[] =
+{
+ "ctl", {Qctl}, 0, 0666,
+};
+
+char *usbmodename[] =
+{
+ [OREAD] "r",
+ [OWRITE] "w",
+ [ORDWR] "rw",
+};
+
+static char *ttname[] =
+{
+ [Tnone] "none",
+ [Tctl] "control",
+ [Tiso] "iso",
+ [Tintr] "interrupt",
+ [Tbulk] "bulk",
+};
+
+static char *spname[] =
+{
+ [Fullspeed] "full",
+ [Lowspeed] "low",
+ [Highspeed] "high",
+ [Nospeed] "no",
+};
+
+static int debug;
+static Hcitype hcitypes[Nhcis];
+static Hci* hcis[Nhcis];
+static QLock epslck; /* add, del, lookup endpoints */
+static Ep* eps[Neps]; /* all endpoints known */
+static int epmax; /* 1 + last endpoint index used */
+static int usbidgen; /* device address generator */
+
+/*
+ * Is there something like this in a library? should it be?
+ */
+char*
+seprintdata(char *s, char *se, uchar *d, int n)
+{
+ int i, l;
+
+ s = seprint(s, se, " %#p[%d]: ", d, n);
+ l = n;
+ if(l > 10)
+ l = 10;
+ for(i=0; i<l; i++)
+ s = seprint(s, se, " %2.2ux", d[i]);
+ if(l < n)
+ s = seprint(s, se, "...");
+ return s;
+}
+
+static int
+name2speed(char *name)
+{
+ int i;
+
+ for(i = 0; i < nelem(spname); i++)
+ if(strcmp(name, spname[i]) == 0)
+ return i;
+ return Nospeed;
+}
+
+static int
+name2ttype(char *name)
+{
+ int i;
+
+ for(i = 0; i < nelem(ttname); i++)
+ if(strcmp(name, ttname[i]) == 0)
+ return i;
+ /* may be a std. USB ep. type */
+ i = strtol(name, nil, 0);
+ switch(i+1){
+ case Tctl:
+ case Tiso:
+ case Tbulk:
+ case Tintr:
+ return i+1;
+ default:
+ return Tnone;
+ }
+}
+
+static int
+name2mode(char *mode)
+{
+ int i;
+
+ for(i = 0; i < nelem(usbmodename); i++)
+ if(strcmp(mode, usbmodename[i]) == 0)
+ return i;
+ return -1;
+}
+
+static int
+qid2epidx(int q)
+{
+ q = (q-Qep0dir)/4;
+ if(q < 0 || q >= epmax || eps[q] == nil)
+ return -1;
+ return q;
+}
+
+static int
+isqtype(int q, int type)
+{
+ if(q < Qep0dir)
+ return 0;
+ q -= Qep0dir;
+ return (q & 3) == type;
+}
+
+void
+addhcitype(char* t, int (*r)(Hci*))
+{
+ static int ntype;
+
+ if(ntype == Nhcis)
+ panic("too many USB host interface types");
+ hcitypes[ntype].type = t;
+ hcitypes[ntype].reset = r;
+ ntype++;
+}
+
+static char*
+seprintep(char *s, char *se, Ep *ep, int all)
+{
+ static char* dsnames[] = { "config", "enabled", "detached", "reset" };
+ Udev *d;
+ int i;
+ int di;
+
+ d = ep->dev;
+
+ qlock(ep);
+ if(waserror()){
+ qunlock(ep);
+ nexterror();
+ }
+ di = ep->dev->nb;
+ if(all)
+ s = seprint(s, se, "dev %d ep %d ", di, ep->nb);
+ s = seprint(s, se, "%s", dsnames[ep->dev->state]);
+ s = seprint(s, se, " %s", ttname[ep->ttype]);
+ assert(ep->mode == OREAD || ep->mode == OWRITE || ep->mode == ORDWR);
+ s = seprint(s, se, " %s", usbmodename[ep->mode]);
+ s = seprint(s, se, " speed %s", spname[d->speed]);
+ s = seprint(s, se, " maxpkt %ld", ep->maxpkt);
+ s = seprint(s, se, " pollival %ld", ep->pollival);
+ s = seprint(s, se, " samplesz %ld", ep->samplesz);
+ s = seprint(s, se, " hz %ld", ep->hz);
+ s = seprint(s, se, " hub %d", ep->dev->hub);
+ s = seprint(s, se, " port %d", ep->dev->port);
+ if(ep->inuse)
+ s = seprint(s, se, " busy");
+ else
+ s = seprint(s, se, " idle");
+ if(all){
+ s = seprint(s, se, " load %uld", ep->load);
+ s = seprint(s, se, " ref %ld addr %#p", ep->ref, ep);
+ s = seprint(s, se, " idx %d", ep->idx);
+ if(ep->name != nil)
+ s = seprint(s, se, " name '%s'", ep->name);
+ if(ep->tmout != 0)
+ s = seprint(s, se, " tmout");
+ if(ep == ep->ep0){
+ s = seprint(s, se, " ctlrno %#x", ep->hp->ctlrno);
+ s = seprint(s, se, " eps:");
+ for(i = 0; i < nelem(d->eps); i++)
+ if(d->eps[i] != nil)
+ s = seprint(s, se, " ep%d.%d", di, i);
+ }
+ }
+ if(ep->info != nil)
+ s = seprint(s, se, "\n%s %s\n", ep->info, ep->hp->type);
+ else
+ s = seprint(s, se, "\n");
+ qunlock(ep);
+ poperror();
+ return s;
+}
+
+static Ep*
+epalloc(Hci *hp)
+{
+ Ep *ep;
+ int i;
+
+ ep = smalloc(sizeof(Ep));
+ ep->ref = 1;
+ qlock(&epslck);
+ for(i = 0; i < Neps; i++)
+ if(eps[i] == nil)
+ break;
+ if(i == Neps){
+ qunlock(&epslck);
+ free(ep);
+ print("usb: bug: too few endpoints.\n");
+ return nil;
+ }
+ ep->idx = i;
+ if(epmax <= i)
+ epmax = i+1;
+ eps[i] = ep;
+ ep->hp = hp;
+ ep->maxpkt = 8;
+ ep->ntds = 1;
+ ep->samplesz = ep->pollival = ep->hz = 0; /* make them void */
+ qunlock(&epslck);
+ return ep;
+}
+
+static Ep*
+getep(int i)
+{
+ Ep *ep;
+
+ if(i < 0 || i >= epmax || eps[i] == nil)
+ return nil;
+ qlock(&epslck);
+ ep = eps[i];
+ if(ep != nil)
+ incref(ep);
+ qunlock(&epslck);
+ return ep;
+}
+
+static void
+putep(Ep *ep)
+{
+ Udev *d;
+
+ if(ep != nil && decref(ep) == 0){
+ d = ep->dev;
+ deprint("usb: ep%d.%d %#p released\n", d->nb, ep->nb, ep);
+ qlock(&epslck);
+ eps[ep->idx] = nil;
+ if(ep->idx == epmax-1)
+ epmax--;
+ if(ep == ep->ep0 && ep->dev != nil && ep->dev->nb == usbidgen)
+ usbidgen--;
+ qunlock(&epslck);
+ if(d != nil){
+ qlock(ep->ep0);
+ d->eps[ep->nb] = nil;
+ qunlock(ep->ep0);
+ }
+ if(ep->ep0 != ep){
+ putep(ep->ep0);
+ ep->ep0 = nil;
+ }
+ free(ep->info);
+ free(ep->name);
+ free(ep);
+ }
+}
+
+static void
+dumpeps(void)
+{
+ int i;
+ static char buf[512];
+ char *s;
+ char *e;
+ Ep *ep;
+
+ print("usb dump eps: epmax %d Neps %d (ref=1+ for dump):\n", epmax, Neps);
+ for(i = 0; i < epmax; i++){
+ s = buf;
+ e = buf+sizeof(buf);
+ ep = getep(i);
+ if(ep != nil){
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ s = seprint(s, e, "ep%d.%d ", ep->dev->nb, ep->nb);
+ seprintep(s, e, ep, 1);
+ print("%s", buf);
+ ep->hp->seprintep(buf, e, ep);
+ print("%s", buf);
+ poperror();
+ putep(ep);
+ }
+ }
+ print("usb dump hcis:\n");
+ for(i = 0; i < Nhcis; i++)
+ if(hcis[i] != nil)
+ hcis[i]->dump(hcis[i]);
+}
+
+static int
+newusbid(Hci *)
+{
+ int id;
+
+ qlock(&epslck);
+ id = ++usbidgen;
+ if(id >= 0x7F)
+ print("#u: too many device addresses; reuse them more\n");
+ qunlock(&epslck);
+ return id;
+}
+
+/*
+ * Create endpoint 0 for a new device
+ */
+static Ep*
+newdev(Hci *hp, int ishub, int isroot)
+{
+ Ep *ep;
+ Udev *d;
+
+ ep = epalloc(hp);
+ d = ep->dev = smalloc(sizeof(Udev));
+ d->nb = newusbid(hp);
+ d->eps[0] = ep;
+ ep->nb = 0;
+ ep->toggle[0] = ep->toggle[1] = 0;
+ d->ishub = ishub;
+ d->isroot = isroot;
+ if(hp->highspeed != 0)
+ d->speed = Highspeed;
+ else
+ d->speed = Fullspeed;
+ d->state = Dconfig; /* address not yet set */
+ ep->dev = d;
+ ep->ep0 = ep; /* no ref counted here */
+ ep->ttype = Tctl;
+ ep->tmout = Xfertmout;
+ ep->mode = ORDWR;
+ dprint("newdev %#p ep%d.%d %#p\n", d, d->nb, ep->nb, ep);
+ return ep;
+}
+
+/*
+ * Create a new endpoint for the device
+ * accessed via the given endpoint 0.
+ */
+static Ep*
+newdevep(Ep *ep, int i, int tt, int mode)
+{
+ Ep *nep;
+ Udev *d;
+
+ d = ep->dev;
+ if(d->eps[i] != nil)
+ error("endpoint already in use");
+ nep = epalloc(ep->hp);
+ incref(ep);
+ d->eps[i] = nep;
+ nep->nb = i;
+ nep->toggle[0] = nep->toggle[1] = 0;
+ nep->ep0 = ep;
+ nep->dev = ep->dev;
+ nep->mode = mode;
+ nep->ttype = tt;
+ nep->debug = ep->debug;
+ /* set defaults */
+ switch(tt){
+ case Tctl:
+ nep->tmout = Xfertmout;
+ break;
+ case Tintr:
+ nep->pollival = 10;
+ break;
+ case Tiso:
+ nep->tmout = Xfertmout;
+ nep->pollival = 10;
+ nep->samplesz = 4;
+ nep->hz = 44100;
+ break;
+ }
+ deprint("newdevep ep%d.%d %#p\n", d->nb, nep->nb, nep);
+ return ep;
+}
+
+static int
+epdataperm(int mode)
+{
+
+ switch(mode){
+ case OREAD:
+ return 0440|DMEXCL;
+ break;
+ case OWRITE:
+ return 0220|DMEXCL;
+ break;
+ default:
+ return 0660|DMEXCL;
+ }
+}
+
+static int
+usbgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
+{
+ Qid q;
+ Dirtab *dir;
+ int perm;
+ char *se;
+ Ep *ep;
+ int nb;
+ int mode;
+
+ if(0)ddprint("usbgen q %#x s %d...", QID(c->qid), s);
+ if(s == DEVDOTDOT){
+ if(QID(c->qid) <= Qusbdir){
+ mkqid(&q, Qdir, 0, QTDIR);
+ devdir(c, q, "#u", 0, eve, 0555, dp);
+ }else{
+ mkqid(&q, Qusbdir, 0, QTDIR);
+ devdir(c, q, "usb", 0, eve, 0555, dp);
+ }
+ if(0)ddprint("ok\n");
+ return 1;
+ }
+
+ switch(QID(c->qid)){
+ case Qdir: /* list #u */
+ if(s == 0){
+ mkqid(&q, Qusbdir, 0, QTDIR);
+ devdir(c, q, "usb", 0, eve, 0555, dp);
+ if(0)ddprint("ok\n");
+ return 1;
+ }
+ s--;
+ if(s < 0 || s >= epmax)
+ goto Fail;
+ ep = getep(s);
+ if(ep == nil || ep->name == nil){
+ if(ep != nil)
+ putep(ep);
+ if(0)ddprint("skip\n");
+ return 0;
+ }
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ mkqid(&q, Qep0io+s*4, 0, QTFILE);
+ devdir(c, q, ep->name, 0, eve, epdataperm(ep->mode), dp);
+ putep(ep);
+ poperror();
+ if(0)ddprint("ok\n");
+ return 1;
+
+ case Qusbdir: /* list #u/usb */
+ Usbdir:
+ if(s < nelem(usbdir)){
+ dir = &usbdir[s];
+ mkqid(&q, dir->qid.path, 0, QTFILE);
+ devdir(c, q, dir->name, dir->length, eve, dir->perm, dp);
+ if(0)ddprint("ok\n");
+ return 1;
+ }
+ s -= nelem(usbdir);
+ if(s < 0 || s >= epmax)
+ goto Fail;
+ ep = getep(s);
+ if(ep == nil){
+ if(0)ddprint("skip\n");
+ return 0;
+ }
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ se = up->genbuf+sizeof(up->genbuf);
+ seprint(up->genbuf, se, "ep%d.%d", ep->dev->nb, ep->nb);
+ mkqid(&q, Qep0dir+4*s, 0, QTDIR);
+ putep(ep);
+ poperror();
+ devdir(c, q, up->genbuf, 0, eve, 0755, dp);
+ if(0)ddprint("ok\n");
+ return 1;
+
+ case Qctl:
+ s = 0;
+ goto Usbdir;
+
+ default: /* list #u/usb/epN.M */
+ nb = qid2epidx(QID(c->qid));
+ ep = getep(nb);
+ if(ep == nil)
+ goto Fail;
+ mode = ep->mode;
+ putep(ep);
+ if(isqtype(QID(c->qid), Qepdir)){
+ Epdir:
+ switch(s){
+ case 0:
+ mkqid(&q, Qep0io+nb*4, 0, QTFILE);
+ perm = epdataperm(mode);
+ devdir(c, q, "data", 0, eve, perm, dp);
+ break;
+ case 1:
+ mkqid(&q, Qep0ctl+nb*4, 0, QTFILE);
+ devdir(c, q, "ctl", 0, eve, 0664, dp);
+ break;
+ default:
+ goto Fail;
+ }
+ }else if(isqtype(QID(c->qid), Qepctl)){
+ s = 1;
+ goto Epdir;
+ }else{
+ s = 0;
+ goto Epdir;
+ }
+ if(0)ddprint("ok\n");
+ return 1;
+ }
+Fail:
+ if(0)ddprint("fail\n");
+ return -1;
+}
+
+static Hci*
+hciprobe(int cardno, int ctlrno)
+{
+ Hci *hp;
+ char *type;
+ char name[64];
+ static int epnb = 1; /* guess the endpoint nb. for the controller */
+
+ ddprint("hciprobe %d %d\n", cardno, ctlrno);
+ hp = smalloc(sizeof(Hci));
+ hp->ctlrno = ctlrno;
+ hp->tbdf = BUSUNKNOWN;
+
+ if(cardno < 0){
+ if(isaconfig("usb", ctlrno, hp) == 0){
+ free(hp);
+ return nil;
+ }
+ for(cardno = 0; cardno < Nhcis; cardno++){
+ if(hcitypes[cardno].type == nil)
+ break;
+ type = hp->type;
+ if(type==nil || *type==0)
+ type = "uhci";
+ if(cistrcmp(hcitypes[cardno].type, type) == 0)
+ break;
+ }
+ }
+
+ if(cardno >= Nhcis || hcitypes[cardno].type == nil){
+ free(hp);
+ return nil;
+ }
+ dprint("%s...", hcitypes[cardno].type);
+ if(hcitypes[cardno].reset(hp) < 0){
+ free(hp);
+ return nil;
+ }
+
+ /*
+ * IRQ2 doesn't really exist, it's used to gang the interrupt
+ * controllers together. A device set to IRQ2 will appear on
+ * the second interrupt controller as IRQ9.
+ */
+ if(hp->irq == 2)
+ hp->irq = 9;
+ snprint(name, sizeof(name), "usb%s", hcitypes[cardno].type);
+ intrenable(hp->irq, hp->interrupt, hp, hp->tbdf, name);
+
+ /*
+ * modern machines have too many usb controllers to list on
+ * the console.
+ */
+ dprint("#u/usb/ep%d.0: %s: port 0x%luX irq %d\n",
+ epnb, hcitypes[cardno].type, hp->port, hp->irq);
+ epnb++;
+ return hp;
+}
+
+static void
+usbreset(void)
+{
+ int cardno, ctlrno;
+ Hci *hp;
+
+ if(getconf("*nousbprobe"))
+ return;
+ dprint("usbreset\n");
+
+ for(ctlrno = 0; ctlrno < Nhcis; ctlrno++)
+ if((hp = hciprobe(-1, ctlrno)) != nil)
+ hcis[ctlrno] = hp;
+ cardno = ctlrno = 0;
+ while(cardno < Nhcis && ctlrno < Nhcis && hcitypes[cardno].type != nil)
+ if(hcis[ctlrno] != nil)
+ ctlrno++;
+ else{
+ hp = hciprobe(cardno, ctlrno);
+ if(hp == nil)
+ cardno++;
+ hcis[ctlrno++] = hp;
+ }
+ if(hcis[Nhcis-1] != nil)
+ print("usbreset: bug: Nhcis (%d) too small\n", Nhcis);
+}
+
+static void
+usbinit(void)
+{
+ Hci *hp;
+ int ctlrno;
+ Ep *d;
+ char info[40];
+
+ dprint("usbinit\n");
+ for(ctlrno = 0; ctlrno < Nhcis; ctlrno++){
+ hp = hcis[ctlrno];
+ if(hp != nil){
+ if(hp->init != nil)
+ hp->init(hp);
+ d = newdev(hp, 1, 1); /* new root hub */
+ d->dev->state = Denabled; /* although addr == 0 */
+ d->maxpkt = 64;
+ snprint(info, sizeof(info), "ports %d", hp->nports);
+ kstrdup(&d->info, info);
+ }
+ }
+}
+
+static Chan*
+usbattach(char *spec)
+{
+ return devattach(L'u', spec);
+}
+
+static Walkqid*
+usbwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, nil, 0, usbgen);
+}
+
+static int
+usbstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, nil, 0, usbgen);
+}
+
+/*
+ * µs for the given transfer, for bandwidth allocation.
+ * This is a very rough worst case for what 5.11.3
+ * of the usb 2.0 spec says.
+ * Also, we are using maxpkt and not actual transfer sizes.
+ * Only when we are sure we
+ * are not exceeding b/w might we consider adjusting it.
+ */
+static ulong
+usbload(int speed, int maxpkt)
+{
+ enum{ Hostns = 1000, Hubns = 333 };
+ ulong l;
+ ulong bs;
+
+ l = 0;
+ bs = 10UL * maxpkt;
+ switch(speed){
+ case Highspeed:
+ l = 55*8*2 + 2 * (3 + bs) + Hostns;
+ break;
+ case Fullspeed:
+ l = 9107 + 84 * (4 + bs) + Hostns;
+ break;
+ case Lowspeed:
+ l = 64107 + 2 * Hubns + 667 * (3 + bs) + Hostns;
+ break;
+ default:
+ print("usbload: bad speed %d\n", speed);
+ /* let it run */
+ }
+ return l / 1000UL; /* in µs */
+}
+
+static Chan*
+usbopen(Chan *c, int omode)
+{
+ int q;
+ Ep *ep;
+ int mode;
+
+ mode = openmode(omode);
+ q = QID(c->qid);
+
+ if(q >= Qep0dir && qid2epidx(q) < 0)
+ error(Eio);
+ if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
+ return devopen(c, omode, nil, 0, usbgen);
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ deprint("usbopen q %#x fid %d omode %d\n", q, c->fid, mode);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ qlock(ep);
+ if(ep->inuse){
+ qunlock(ep);
+ error(Einuse);
+ }
+ ep->inuse = 1;
+ qunlock(ep);
+ if(waserror()){
+ ep->inuse = 0;
+ nexterror();
+ }
+ if(mode != OREAD && ep->mode == OREAD)
+ error(Eperm);
+ if(mode != OWRITE && ep->mode == OWRITE)
+ error(Eperm);
+ if(ep->ttype == Tnone)
+ error(Enotconf);
+ ep->clrhalt = 0;
+ ep->rhrepl = -1;
+ if(ep->load == 0)
+ ep->load = usbload(ep->dev->speed, ep->maxpkt);
+ ep->hp->epopen(ep);
+
+ poperror(); /* ep->inuse */
+ poperror(); /* don't putep(): ref kept for fid using the ep. */
+
+ c->mode = mode;
+ c->flag |= COPEN;
+ c->offset = 0;
+ c->aux = nil; /* paranoia */
+ return c;
+}
+
+static void
+epclose(Ep *ep)
+{
+ qlock(ep);
+ if(waserror()){
+ qunlock(ep);
+ nexterror();
+ }
+ if(ep->inuse){
+ ep->hp->epclose(ep);
+ ep->inuse = 0;
+ }
+ qunlock(ep);
+ poperror();
+}
+
+static void
+usbclose(Chan *c)
+{
+ int q;
+ Ep *ep;
+
+ q = QID(c->qid);
+ if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
+ return;
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ return;
+ deprint("usbclose q %#x fid %d ref %ld\n", q, c->fid, ep->ref);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(c->flag & COPEN){
+ free(c->aux);
+ c->aux = nil;
+ epclose(ep);
+ putep(ep); /* release ref kept since usbopen */
+ c->flag &= ~COPEN;
+ }
+ poperror();
+ putep(ep);
+}
+
+static long
+ctlread(Chan *c, void *a, long n, vlong offset)
+{
+ int q;
+ char *s;
+ char *us;
+ char *se;
+ Ep *ep;
+ int i;
+
+ q = QID(c->qid);
+ us = s = smalloc(READSTR);
+ se = s + READSTR;
+ if(waserror()){
+ free(us);
+ nexterror();
+ }
+ if(q == Qctl)
+ for(i = 0; i < epmax; i++){
+ ep = getep(i);
+ if(ep != nil){
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ s = seprint(s, se, "ep%d.%d ", ep->dev->nb, ep->nb);
+ s = seprintep(s, se, ep, 0);
+ poperror();
+ }
+ putep(ep);
+ }
+ else{
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(c->aux != nil){
+ /* After a new endpoint request we read
+ * the new endpoint name back.
+ */
+ strecpy(s, se, c->aux);
+ free(c->aux);
+ c->aux = nil;
+ }else
+ seprintep(s, se, ep, 0);
+ poperror();
+ putep(ep);
+ }
+ n = readstr(offset, a, n, us);
+ poperror();
+ free(us);
+ return n;
+}
+
+/*
+ * Fake root hub emulation.
+ */
+static long
+rhubread(Ep *ep, void *a, long n)
+{
+ char *b;
+
+ if(ep->dev->isroot == 0 || ep->nb != 0 || n < 2)
+ return -1;
+ if(ep->rhrepl < 0)
+ return -1;
+
+ b = a;
+ memset(b, 0, n);
+ PUT2(b, ep->rhrepl);
+ ep->rhrepl = -1;
+ return n;
+}
+
+static long
+rhubwrite(Ep *ep, void *a, long n)
+{
+ uchar *s;
+ int cmd;
+ int feature;
+ int port;
+ Hci *hp;
+
+ if(ep->dev == nil || ep->dev->isroot == 0 || ep->nb != 0)
+ return -1;
+ if(n != Rsetuplen)
+ error("root hub is a toy hub");
+ ep->rhrepl = -1;
+ s = a;
+ if(s[Rtype] != (Rh2d|Rclass|Rother) && s[Rtype] != (Rd2h|Rclass|Rother))
+ error("root hub is a toy hub");
+ hp = ep->hp;
+ cmd = s[Rreq];
+ feature = GET2(s+Rvalue);
+ port = GET2(s+Rindex);
+ if(port < 1 || port > hp->nports)
+ error("bad hub port number");
+ switch(feature){
+ case Rportenable:
+ ep->rhrepl = hp->portenable(hp, port, cmd == Rsetfeature);
+ break;
+ case Rportreset:
+ ep->rhrepl = hp->portreset(hp, port, cmd == Rsetfeature);
+ break;
+ case Rgetstatus:
+ ep->rhrepl = hp->portstatus(hp, port);
+ break;
+ default:
+ ep->rhrepl = 0;
+ }
+ return n;
+}
+
+static long
+usbread(Chan *c, void *a, long n, vlong offset)
+{
+ int q;
+ Ep *ep;
+ int nr;
+
+ q = QID(c->qid);
+
+ if(c->qid.type == QTDIR)
+ return devdirread(c, a, n, nil, 0, usbgen);
+
+ if(q == Qctl || isqtype(q, Qepctl))
+ return ctlread(c, a, n, offset);
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(ep->dev->state == Ddetach)
+ error(Edetach);
+ if(ep->mode == OWRITE || ep->inuse == 0)
+ error(Ebadusefd);
+ switch(ep->ttype){
+ case Tnone:
+ error("endpoint not configured");
+ case Tctl:
+ nr = rhubread(ep, a, n);
+ if(nr >= 0){
+ n = nr;
+ break;
+ }
+ /* else fall */
+ default:
+ ddeprint("\nusbread q %#x fid %d cnt %ld off %lld\n",q,c->fid,n,offset);
+ n = ep->hp->epread(ep, a, n);
+ break;
+ }
+ poperror();
+ putep(ep);
+ return n;
+}
+
+static long
+pow2(int n)
+{
+ return 1 << n;
+}
+
+static void
+setmaxpkt(Ep *ep, char* s)
+{
+ long spp; /* samples per packet */
+
+ if(ep->dev->speed == Highspeed)
+ spp = (ep->hz * ep->pollival * ep->ntds + 7999) / 8000;
+ else
+ spp = (ep->hz * ep->pollival + 999) / 1000;
+ ep->maxpkt = spp * ep->samplesz;
+ deprint("usb: %s: setmaxpkt: hz %ld poll %ld"
+ " ntds %d %s speed -> spp %ld maxpkt %ld\n", s,
+ ep->hz, ep->pollival, ep->ntds, spname[ep->dev->speed],
+ spp, ep->maxpkt);
+ if(ep->maxpkt > 1024){
+ print("usb: %s: maxpkt %ld > 1024. truncating\n", s, ep->maxpkt);
+ ep->maxpkt = 1024;
+ }
+}
+
+/*
+ * Many endpoint ctls. simply update the portable representation
+ * of the endpoint. The actual controller driver will look
+ * at them to setup the endpoints as dictated.
+ */
+static long
+epctl(Ep *ep, Chan *c, void *a, long n)
+{
+ int i, l, mode, nb, tt;
+ char *b, *s;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ Ep *nep;
+ Udev *d;
+ static char *Info = "info ";
+
+ d = ep->dev;
+
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, epctls, nelem(epctls));
+ if(ct == nil)
+ error(Ebadctl);
+ i = ct->index;
+ if(i == CMnew || i == CMspeed || i == CMhub || i == CMpreset)
+ if(ep != ep->ep0)
+ error("allowed only on a setup endpoint");
+ if(i != CMclrhalt && i != CMdetach && i != CMdebugep && i != CMname)
+ if(ep != ep->ep0 && ep->inuse != 0)
+ error("must configure before using");
+ switch(i){
+ case CMnew:
+ deprint("usb epctl %s\n", cb->f[0]);
+ nb = strtol(cb->f[1], nil, 0);
+ if(nb < 0 || nb >= Ndeveps)
+ error("bad endpoint number");
+ tt = name2ttype(cb->f[2]);
+ if(tt == Tnone)
+ error("unknown endpoint type");
+ mode = name2mode(cb->f[3]);
+ if(mode < 0)
+ error("unknown i/o mode");
+ newdevep(ep, nb, tt, mode);
+ break;
+ case CMnewdev:
+ deprint("usb epctl %s\n", cb->f[0]);
+ if(ep != ep->ep0 || d->ishub == 0)
+ error("not a hub setup endpoint");
+ l = name2speed(cb->f[1]);
+ if(l == Nospeed)
+ error("speed must be full|low|high");
+ nep = newdev(ep->hp, 0, 0);
+ nep->dev->speed = l;
+ if(nep->dev->speed != Lowspeed)
+ nep->maxpkt = 64; /* assume full speed */
+ nep->dev->hub = d->nb;
+ nep->dev->port = atoi(cb->f[2]);
+ /* next read request will read
+ * the name for the new endpoint
+ */
+ l = sizeof(up->genbuf);
+ snprint(up->genbuf, l, "ep%d.%d", nep->dev->nb, nep->nb);
+ kstrdup(&c->aux, up->genbuf);
+ break;
+ case CMhub:
+ deprint("usb epctl %s\n", cb->f[0]);
+ d->ishub = 1;
+ break;
+ case CMspeed:
+ l = name2speed(cb->f[1]);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l == Nospeed)
+ error("speed must be full|low|high");
+ qlock(ep->ep0);
+ d->speed = l;
+ qunlock(ep->ep0);
+ break;
+ case CMmaxpkt:
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l < 1 || l > 1024)
+ error("maxpkt not in [1:1024]");
+ qlock(ep);
+ ep->maxpkt = l;
+ qunlock(ep);
+ break;
+ case CMntds:
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l < 1 || l > 3)
+ error("ntds not in [1:3]");
+ qlock(ep);
+ ep->ntds = l;
+ qunlock(ep);
+ break;
+ case CMpollival:
+ if(ep->ttype != Tintr && ep->ttype != Tiso)
+ error("not an intr or iso endpoint");
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(ep->ttype == Tiso ||
+ (ep->ttype == Tintr && ep->dev->speed == Highspeed)){
+ if(l < 1 || l > 16)
+ error("pollival power not in [1:16]");
+ l = pow2(l-1);
+ }else
+ if(l < 1 || l > 255)
+ error("pollival not in [1:255]");
+ qlock(ep);
+ ep->pollival = l;
+ if(ep->ttype == Tiso)
+ setmaxpkt(ep, "pollival");
+ qunlock(ep);
+ break;
+ case CMsamplesz:
+ if(ep->ttype != Tiso)
+ error("not an iso endpoint");
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l <= 0 || l > 8)
+ error("samplesz not in [1:8]");
+ qlock(ep);
+ ep->samplesz = l;
+ setmaxpkt(ep, "samplesz");
+ qunlock(ep);
+ break;
+ case CMhz:
+ if(ep->ttype != Tiso)
+ error("not an iso endpoint");
+ l = strtoul(cb->f[1], nil, 0);
+ deprint("usb epctl %s %d\n", cb->f[0], l);
+ if(l <= 0 || l > 100000)
+ error("hz not in [1:100000]");
+ qlock(ep);
+ ep->hz = l;
+ setmaxpkt(ep, "hz");
+ qunlock(ep);
+ break;
+ case CMclrhalt:
+ qlock(ep);
+ deprint("usb epctl %s\n", cb->f[0]);
+ ep->clrhalt = 1;
+ qunlock(ep);
+ break;
+ case CMinfo:
+ deprint("usb epctl %s\n", cb->f[0]);
+ l = strlen(Info);
+ s = a;
+ if(n < l+2 || strncmp(Info, s, l) != 0)
+ error(Ebadctl);
+ if(n > 1024)
+ n = 1024;
+ b = smalloc(n);
+ memmove(b, s+l, n-l);
+ b[n-l] = 0;
+ if(b[n-l-1] == '\n')
+ b[n-l-1] = 0;
+ qlock(ep);
+ free(ep->info);
+ ep->info = b;
+ qunlock(ep);
+ break;
+ case CMaddress:
+ deprint("usb epctl %s\n", cb->f[0]);
+ ep->dev->state = Denabled;
+ break;
+ case CMdetach:
+ if(ep->dev->isroot != 0)
+ error("can't detach a root hub");
+ deprint("usb epctl %s ep%d.%d\n",
+ cb->f[0], ep->dev->nb, ep->nb);
+ ep->dev->state = Ddetach;
+ /* Release file system ref. for its endpoints */
+ for(i = 0; i < nelem(ep->dev->eps); i++)
+ putep(ep->dev->eps[i]);
+ break;
+ case CMdebugep:
+ if(strcmp(cb->f[1], "on") == 0)
+ ep->debug = 1;
+ else if(strcmp(cb->f[1], "off") == 0)
+ ep->debug = 0;
+ else
+ ep->debug = strtoul(cb->f[1], nil, 0);
+ print("usb: ep%d.%d debug %d\n",
+ ep->dev->nb, ep->nb, ep->debug);
+ break;
+ case CMname:
+ deprint("usb epctl %s %s\n", cb->f[0], cb->f[1]);
+ validname(cb->f[1], 0);
+ kstrdup(&ep->name, cb->f[1]);
+ break;
+ case CMtmout:
+ deprint("usb epctl %s\n", cb->f[0]);
+ if(ep->ttype == Tiso || ep->ttype == Tctl)
+ error("ctl ignored for this endpoint type");
+ ep->tmout = strtoul(cb->f[1], nil, 0);
+ if(ep->tmout != 0 && ep->tmout < Xfertmout)
+ ep->tmout = Xfertmout;
+ break;
+ case CMpreset:
+ deprint("usb epctl %s\n", cb->f[0]);
+ if(ep->ttype != Tctl)
+ error("not a control endpoint");
+ if(ep->dev->state != Denabled)
+ error("forbidden on devices not enabled");
+ ep->dev->state = Dreset;
+ break;
+ default:
+ panic("usb: unknown epctl %d", ct->index);
+ }
+ free(cb);
+ poperror();
+ return n;
+}
+
+static long
+usbctl(void *a, long n)
+{
+ Cmdtab *ct;
+ Cmdbuf *cb;
+ Ep *ep;
+ int i;
+
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, usbctls, nelem(usbctls));
+ dprint("usb ctl %s\n", cb->f[0]);
+ switch(ct->index){
+ case CMdebug:
+ if(strcmp(cb->f[1], "on") == 0)
+ debug = 1;
+ else if(strcmp(cb->f[1], "off") == 0)
+ debug = 0;
+ else
+ debug = strtol(cb->f[1], nil, 0);
+ print("usb: debug %d\n", debug);
+ for(i = 0; i < epmax; i++)
+ if((ep = getep(i)) != nil){
+ ep->hp->debug(ep->hp, debug);
+ putep(ep);
+ }
+ break;
+ case CMdump:
+ dumpeps();
+ break;
+ }
+ free(cb);
+ poperror();
+ return n;
+}
+
+static long
+ctlwrite(Chan *c, void *a, long n)
+{
+ int q;
+ Ep *ep;
+
+ q = QID(c->qid);
+ if(q == Qctl)
+ return usbctl(a, n);
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(ep->dev->state == Ddetach)
+ error(Edetach);
+ if(isqtype(q, Qepctl) && c->aux != nil){
+ /* Be sure we don't keep a cloned ep name */
+ free(c->aux);
+ c->aux = nil;
+ error("read, not write, expected");
+ }
+ n = epctl(ep, c, a, n);
+ putep(ep);
+ poperror();
+ return n;
+}
+
+static long
+usbwrite(Chan *c, void *a, long n, vlong off)
+{
+ int nr, q;
+ Ep *ep;
+
+ if(c->qid.type == QTDIR)
+ error(Eisdir);
+
+ q = QID(c->qid);
+
+ if(q == Qctl || isqtype(q, Qepctl))
+ return ctlwrite(c, a, n);
+
+ ep = getep(qid2epidx(q));
+ if(ep == nil)
+ error(Eio);
+ if(waserror()){
+ putep(ep);
+ nexterror();
+ }
+ if(ep->dev->state == Ddetach)
+ error(Edetach);
+ if(ep->mode == OREAD || ep->inuse == 0)
+ error(Ebadusefd);
+
+ switch(ep->ttype){
+ case Tnone:
+ error("endpoint not configured");
+ case Tctl:
+ nr = rhubwrite(ep, a, n);
+ if(nr >= 0){
+ n = nr;
+ break;
+ }
+ /* else fall */
+ default:
+ ddeprint("\nusbwrite q %#x fid %d cnt %ld off %lld\n",q, c->fid, n, off);
+ ep->hp->epwrite(ep, a, n);
+ }
+ putep(ep);
+ poperror();
+ return n;
+}
+
+void
+usbshutdown(void)
+{
+ Hci *hp;
+ int i;
+
+ for(i = 0; i < Nhcis; i++){
+ hp = hcis[i];
+ if(hp == nil)
+ continue;
+ if(hp->shutdown == nil)
+ print("#u: no shutdown function for %s\n", hp->type);
+ else
+ hp->shutdown(hp);
+ }
+}
+
+Dev usbdevtab = {
+ L'u',
+ "usb",
+
+ usbreset,
+ usbinit,
+ usbshutdown,
+ usbattach,
+ usbwalk,
+ usbstat,
+ usbopen,
+ devcreate,
+ usbclose,
+ usbread,
+ devbread,
+ usbwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/pc/devvga.c b/sys/src/9/pc/devvga.c
new file mode 100755
index 000000000..ae28fdd79
--- /dev/null
+++ b/sys/src/9/pc/devvga.c
@@ -0,0 +1,498 @@
+/*
+ * VGA controller
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+enum {
+ Qdir,
+ Qvgabios,
+ Qvgactl,
+ Qvgaovl,
+ Qvgaovlctl,
+};
+
+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,
+};
+
+enum {
+ CMactualsize,
+ CMblank,
+ CMblanktime,
+ CMdrawinit,
+ CMhwaccel,
+ CMhwblank,
+ CMhwgc,
+ CMlinear,
+ CMpalettedepth,
+ CMpanning,
+ CMsize,
+ CMtextmode,
+ CMtype,
+ CMunblank,
+};
+
+static Cmdtab vgactlmsg[] = {
+ CMactualsize, "actualsize", 2,
+ CMblank, "blank", 1,
+ CMblanktime, "blanktime", 2,
+ CMdrawinit, "drawinit", 1,
+ CMhwaccel, "hwaccel", 2,
+ CMhwblank, "hwblank", 2,
+ CMhwgc, "hwgc", 2,
+ CMlinear, "linear", 0,
+ CMpalettedepth, "palettedepth", 2,
+ CMpanning, "panning", 2,
+ CMsize, "size", 3,
+ CMtextmode, "textmode", 1,
+ CMtype, "type", 2,
+ CMunblank, "unblank", 1,
+};
+
+static void
+vgareset(void)
+{
+ /* reserve the 'standard' vga registers */
+ if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0)
+ panic("vga ports already allocated");
+ if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0)
+ panic("vga ports already allocated");
+ conf.monitor = 1;
+}
+
+static Chan*
+vgaattach(char* spec)
+{
+ if(*spec && strcmp(spec, "0"))
+ error(Eio);
+ return devattach('v', spec);
+}
+
+Walkqid*
+vgawalk(Chan* c, Chan *nc, char** name, int nname)
+{
+ return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
+}
+
+static int
+vgastat(Chan* c, uchar* dp, int n)
+{
+ return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
+}
+
+static Chan*
+vgaopen(Chan* c, int omode)
+{
+ VGAscr *scr;
+ static char *openctl = "openctl\n";
+
+ scr = &vgascreen[0];
+ if ((ulong)c->qid.path == Qvgaovlctl) {
+ if (scr->dev && scr->dev->ovlctl)
+ scr->dev->ovlctl(scr, c, openctl, strlen(openctl));
+ else
+ error(Enonexist);
+ }
+ return devopen(c, omode, vgadir, nelem(vgadir), devgen);
+}
+
+static void
+vgaclose(Chan* c)
+{
+ VGAscr *scr;
+ static char *closectl = "closectl\n";
+
+ scr = &vgascreen[0];
+ if((ulong)c->qid.path == Qvgaovlctl)
+ if(scr->dev && scr->dev->ovlctl){
+ if(waserror()){
+ print("ovlctl error: %s\n", up->errstr);
+ return;
+ }
+ scr->dev->ovlctl(scr, c, closectl, strlen(closectl));
+ poperror();
+ }
+}
+
+static void
+checkport(int start, int end)
+{
+ /* standard vga regs are OK */
+ if(start >= 0x2b0 && end <= 0x2df+1)
+ return;
+ if(start >= 0x3c0 && end <= 0x3da+1)
+ return;
+
+ if(iounused(start, end))
+ return;
+ error(Eperm);
+}
+
+static long
+vgaread(Chan* c, void* a, long n, vlong off)
+{
+ int len;
+ char *p, *s;
+ VGAscr *scr;
+ ulong offset = off;
+ char chbuf[30];
+
+ switch((ulong)c->qid.path){
+
+ 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];
+
+ p = malloc(READSTR);
+ if(waserror()){
+ free(p);
+ nexterror();
+ }
+
+ len = 0;
+
+ if(scr->dev)
+ s = scr->dev->name;
+ else
+ s = "cga";
+ len += snprint(p+len, READSTR-len, "type %s\n", s);
+
+ if(scr->gscreen) {
+ len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n",
+ scr->gscreen->r.max.x, scr->gscreen->r.max.y,
+ scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
+
+ if(Dx(scr->gscreen->r) != Dx(physgscreenr)
+ || Dy(scr->gscreen->r) != Dy(physgscreenr))
+ len += snprint(p+len, READSTR-len, "actualsize %dx%d\n",
+ physgscreenr.max.x, physgscreenr.max.y);
+ }
+
+ len += snprint(p+len, READSTR-len, "blank time %lud idle %d state %s\n",
+ blanktime, drawidletime(), scr->isblank ? "off" : "on");
+ 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");
+ 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);
+
+ return n;
+
+ case Qvgaovl:
+ case Qvgaovlctl:
+ error(Ebadusefd);
+ break;
+
+ default:
+ error(Egreg);
+ break;
+ }
+
+ return 0;
+}
+
+static char Ebusy[] = "vga already configured";
+
+static void
+vgactl(Cmdbuf *cb)
+{
+ int align, i, size, x, y, z;
+ char *chanstr, *p;
+ ulong chan;
+ Cmdtab *ct;
+ VGAscr *scr;
+ extern VGAdev *vgadev[];
+ extern VGAcur *vgacur[];
+
+ scr = &vgascreen[0];
+ ct = lookupcmd(cb, vgactlmsg, nelem(vgactlmsg));
+ switch(ct->index){
+ case CMhwgc:
+ if(strcmp(cb->f[1], "off") == 0){
+ lock(&cursor);
+ if(scr->cur){
+ if(scr->cur->disable)
+ scr->cur->disable(scr);
+ scr->cur = nil;
+ }
+ 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;
+ lock(&cursor);
+ if(scr->cur && scr->cur->disable)
+ scr->cur->disable(scr);
+ scr->cur = vgacur[i];
+ if(scr->cur->enable)
+ scr->cur->enable(scr);
+ unlock(&cursor);
+ return;
+ }
+ break;
+
+ case CMtype:
+ for(i = 0; vgadev[i]; i++){
+ if(strcmp(cb->f[1], vgadev[i]->name))
+ continue;
+ if(scr->dev && scr->dev->disable)
+ scr->dev->disable(scr);
+ scr->dev = vgadev[i];
+ if(scr->dev->enable)
+ scr->dev->enable(scr);
+ return;
+ }
+ break;
+
+ case CMtextmode:
+ screeninit();
+ return;
+
+ case CMsize:
+ x = strtoul(cb->f[1], &p, 0);
+ if(x == 0 || x > 10240)
+ error(Ebadarg);
+ if(*p)
+ p++;
+
+ y = strtoul(p, &p, 0);
+ if(y == 0 || y > 10240)
+ error(Ebadarg);
+ if(*p)
+ p++;
+
+ z = strtoul(p, &p, 0);
+
+ chanstr = cb->f[2];
+ if((chan = strtochan(chanstr)) == 0)
+ error("bad channel");
+
+ if(chantodepth(chan) != z)
+ error("depth, channel do not match");
+
+ cursoroff(1);
+ deletescreenimage();
+ if(screensize(x, y, z, chan))
+ error(Egreg);
+ vgascreenwin(scr);
+ resetscreenimage();
+ cursoron(1);
+ return;
+
+ case CMactualsize:
+ if(scr->gscreen == nil)
+ error("set the screen size first");
+
+ x = strtoul(cb->f[1], &p, 0);
+ if(x == 0 || x > 2048)
+ error(Ebadarg);
+ if(*p)
+ p++;
+
+ y = strtoul(p, nil, 0);
+ if(y == 0 || y > 2048)
+ error(Ebadarg);
+
+ if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y)
+ error("physical screen bigger than virtual");
+
+ physgscreenr = Rect(0,0,x,y);
+ scr->gscreen->clipr = physgscreenr;
+ return;
+
+ case CMpalettedepth:
+ x = strtoul(cb->f[1], &p, 0);
+ if(x != 8 && x != 6)
+ error(Ebadarg);
+
+ scr->palettedepth = x;
+ return;
+
+ case CMdrawinit:
+ if(scr->gscreen == nil)
+ error("drawinit: no gscreen");
+ if(scr->dev && scr->dev->drawinit)
+ scr->dev->drawinit(scr);
+ return;
+
+ case CMlinear:
+ if(cb->nf!=2 && cb->nf!=3)
+ error(Ebadarg);
+ size = strtoul(cb->f[1], 0, 0);
+ if(cb->nf == 2)
+ align = 0;
+ else
+ align = strtoul(cb->f[2], 0, 0);
+ if(screenaperture(size, align) < 0)
+ error("not enough free address space");
+ return;
+/*
+ case CMmemset:
+ memset((void*)strtoul(cb->f[1], 0, 0), atoi(cb->f[2]), atoi(cb->f[3]));
+ return;
+*/
+
+ case CMblank:
+ drawblankscreen(1);
+ return;
+
+ case CMunblank:
+ drawblankscreen(0);
+ return;
+
+ case CMblanktime:
+ blanktime = strtoul(cb->f[1], 0, 0);
+ return;
+
+ case CMpanning:
+ if(strcmp(cb->f[1], "on") == 0){
+ if(scr == nil || scr->cur == nil)
+ error("set screen first");
+ if(!scr->cur->doespanning)
+ error("panning not supported");
+ scr->gscreen->clipr = scr->gscreen->r;
+ panning = 1;
+ }
+ else if(strcmp(cb->f[1], "off") == 0){
+ scr->gscreen->clipr = physgscreenr;
+ panning = 0;
+ }else
+ break;
+ return;
+
+ case CMhwaccel:
+ if(strcmp(cb->f[1], "on") == 0)
+ hwaccel = 1;
+ else if(strcmp(cb->f[1], "off") == 0)
+ hwaccel = 0;
+ else
+ break;
+ return;
+
+ case CMhwblank:
+ if(strcmp(cb->f[1], "on") == 0)
+ hwblank = 1;
+ else if(strcmp(cb->f[1], "off") == 0)
+ hwblank = 0;
+ else
+ break;
+ return;
+ }
+
+ cmderror(cb, "bad VGA control message");
+}
+
+char Enooverlay[] = "No overlay support";
+
+static long
+vgawrite(Chan* c, void* a, long n, vlong off)
+{
+ ulong offset = off;
+ Cmdbuf *cb;
+ VGAscr *scr;
+
+ switch((ulong)c->qid.path){
+
+ case Qdir:
+ error(Eperm);
+
+ case Qvgactl:
+ if(offset || n >= READSTR)
+ error(Ebadarg);
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ vgactl(cb);
+ poperror();
+ free(cb);
+ return n;
+
+ case Qvgaovl:
+ scr = &vgascreen[0];
+ if (scr->dev == nil || scr->dev->ovlwrite == nil) {
+ error(Enooverlay);
+ break;
+ }
+ return scr->dev->ovlwrite(scr, a, n, off);
+
+ case Qvgaovlctl:
+ scr = &vgascreen[0];
+ if (scr->dev == nil || scr->dev->ovlctl == nil) {
+ error(Enooverlay);
+ break;
+ }
+ scr->dev->ovlctl(scr, c, a, n);
+ return n;
+
+ default:
+ error(Egreg);
+ break;
+ }
+
+ return 0;
+}
+
+Dev vgadevtab = {
+ 'v',
+ "vga",
+
+ vgareset,
+ devinit,
+ devshutdown,
+ vgaattach,
+ vgawalk,
+ vgastat,
+ vgaopen,
+ devcreate,
+ vgaclose,
+ vgaread,
+ devbread,
+ vgawrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/pc/dma.c b/sys/src/9/pc/dma.c
new file mode 100755
index 000000000..7ecbc5f4a
--- /dev/null
+++ b/sys/src/9/pc/dma.c
@@ -0,0 +1,264 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+typedef struct DMAport DMAport;
+typedef struct DMA DMA;
+typedef struct DMAxfer DMAxfer;
+
+/*
+ * state of a dma transfer
+ */
+struct DMAxfer
+{
+ ulong bpa; /* bounce buffer physical address */
+ void* bva; /* bounce buffer virtual address */
+ int blen; /* bounce buffer length */
+ void* va; /* virtual address destination/src */
+ long len; /* bytes to be transferred */
+ int isread;
+};
+
+/*
+ * the dma controllers. the first half of this structure specifies
+ * the I/O ports used by the DMA controllers.
+ */
+struct DMAport
+{
+ uchar addr[4]; /* current address (4 channels) */
+ uchar count[4]; /* current count (4 channels) */
+ uchar page[4]; /* page registers (4 channels) */
+ uchar cmd; /* command status register */
+ uchar req; /* request registers */
+ uchar sbm; /* single bit mask register */
+ uchar mode; /* mode register */
+ uchar cbp; /* clear byte pointer */
+ uchar mc; /* master clear */
+ uchar cmask; /* clear mask register */
+ uchar wam; /* write all mask register bit */
+};
+
+struct DMA
+{
+ DMAport;
+ int shift;
+ Lock;
+ DMAxfer x[4];
+};
+
+DMA dma[2] = {
+ { 0x00, 0x02, 0x04, 0x06,
+ 0x01, 0x03, 0x05, 0x07,
+ 0x87, 0x83, 0x81, 0x82,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0 },
+
+ { 0xc0, 0xc4, 0xc8, 0xcc,
+ 0xc2, 0xc6, 0xca, 0xce,
+ 0x8f, 0x8b, 0x89, 0x8a,
+ 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
+ 1 },
+};
+
+extern int i8237dma;
+static void* i8237bva[2];
+static int i8237used;
+
+/*
+ * DMA must be in the first 16MB. This gets called early by the
+ * initialisation routines of any devices which require DMA to ensure
+ * the allocated bounce buffers are below the 16MB limit.
+ */
+void
+_i8237alloc(void)
+{
+ void* bva;
+
+ if(i8237dma <= 0)
+ return;
+ if(i8237dma > 2)
+ i8237dma = 2;
+
+ bva = xspanalloc(64*1024*i8237dma, BY2PG, 64*1024);
+ if(bva == nil || PADDR(bva)+64*1024*i8237dma > 16*MB){
+ /*
+ * This will panic with the current
+ * implementation of xspanalloc().
+ if(bva != nil)
+ xfree(bva);
+ */
+ return;
+ }
+
+ i8237bva[0] = bva;
+ if(i8237dma == 2)
+ i8237bva[1] = ((uchar*)i8237bva[0])+64*1024;
+}
+
+/*
+ * DMA must be in the first 16MB. This gets called early by the
+ * initialisation routines of any devices which require DMA to ensure
+ * the allocated bounce buffers are below the 16MB limit.
+ */
+int
+dmainit(int chan, int maxtransfer)
+{
+ DMA *dp;
+ DMAxfer *xp;
+ static int once;
+
+ if(once == 0){
+ if(ioalloc(0x00, 0x10, 0, "dma") < 0
+ || ioalloc(0x80, 0x10, 0, "dma") < 0
+ || ioalloc(0xd0, 0x10, 0, "dma") < 0)
+ panic("dmainit");
+ once = 1;
+ }
+
+ if(maxtransfer > 64*1024)
+ maxtransfer = 64*1024;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+ xp = &dp->x[chan];
+ if(xp->bva != nil){
+ if(xp->blen < maxtransfer)
+ return 1;
+ return 0;
+ }
+
+ if(i8237used >= i8237dma || i8237bva[i8237used] == nil){
+ print("no i8237 DMA bounce buffer < 16MB\n");
+ return 1;
+ }
+ xp->bva = i8237bva[i8237used++];
+ xp->bpa = PADDR(xp->bva);
+ xp->blen = maxtransfer;
+ xp->len = 0;
+ xp->isread = 0;
+
+ return 0;
+}
+
+/*
+ * setup a dma transfer. if the destination is not in kernel
+ * memory, allocate a page for the transfer.
+ *
+ * we assume BIOS has set up the command register before we
+ * are booted.
+ *
+ * return the updated transfer length (we can't transfer across 64k
+ * boundaries)
+ */
+long
+dmasetup(int chan, void *va, long len, int isread)
+{
+ DMA *dp;
+ ulong pa;
+ uchar mode;
+ DMAxfer *xp;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+ xp = &dp->x[chan];
+
+ /*
+ * if this isn't kernel memory or crossing 64k boundary or above 16 meg
+ * use the bounce buffer.
+ */
+ if((ulong)va < KZERO
+ || ((pa=PADDR(va))&0xFFFF0000) != ((pa+len)&0xFFFF0000)
+ || pa >= 16*MB){
+ if(xp->bva == nil)
+ return -1;
+ if(len > xp->blen)
+ len = xp->blen;
+ if(!isread)
+ memmove(xp->bva, va, len);
+ xp->va = va;
+ xp->len = len;
+ xp->isread = isread;
+ pa = xp->bpa;
+ }
+ else
+ xp->len = 0;
+
+ /*
+ * this setup must be atomic
+ */
+ ilock(dp);
+ mode = (isread ? 0x44 : 0x48) | chan;
+ outb(dp->mode, mode); /* single mode dma (give CPU a chance at mem) */
+ outb(dp->page[chan], pa>>16);
+ outb(dp->cbp, 0); /* set count & address to their first byte */
+ outb(dp->addr[chan], pa>>dp->shift); /* set address */
+ outb(dp->addr[chan], pa>>(8+dp->shift));
+ outb(dp->count[chan], (len>>dp->shift)-1); /* set count */
+ outb(dp->count[chan], ((len>>dp->shift)-1)>>8);
+ outb(dp->sbm, chan); /* enable the channel */
+ iunlock(dp);
+
+ return len;
+}
+
+int
+dmadone(int chan)
+{
+ DMA *dp;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+
+ return inb(dp->cmd) & (1<<chan);
+}
+
+/*
+ * this must be called after a dma has been completed.
+ *
+ * if a page has been allocated for the dma,
+ * copy the data into the actual destination
+ * and free the page.
+ */
+void
+dmaend(int chan)
+{
+ DMA *dp;
+ DMAxfer *xp;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+
+ /*
+ * disable the channel
+ */
+ ilock(dp);
+ outb(dp->sbm, 4|chan);
+ iunlock(dp);
+
+ xp = &dp->x[chan];
+ if(xp->len == 0 || !xp->isread)
+ return;
+
+ /*
+ * copy out of temporary page
+ */
+ memmove(xp->va, xp->bva, xp->len);
+ xp->len = 0;
+}
+
+/*
+int
+dmacount(int chan)
+{
+ int retval;
+ DMA *dp;
+
+ dp = &dma[(chan>>2)&1];
+ outb(dp->cbp, 0);
+ retval = inb(dp->count[chan]);
+ retval |= inb(dp->count[chan]) << 8;
+ return((retval<<dp->shift)+1);
+}
+ */
diff --git a/sys/src/9/pc/ether2000.c b/sys/src/9/pc/ether2000.c
new file mode 100755
index 000000000..8fc8911e1
--- /dev/null
+++ b/sys/src/9/pc/ether2000.c
@@ -0,0 +1,232 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "ether8390.h"
+
+/*
+ * Driver written for the 'Notebook Computer Ethernet LAN Adapter',
+ * a plug-in to the bus-slot on the rear of the Gateway NOMAD 425DXL
+ * laptop. The manual says NE2000 compatible.
+ * The interface appears to be pretty well described in the National
+ * Semiconductor Local Area Network Databook (1992) as one of the
+ * AT evaluation cards.
+ *
+ * The NE2000 is really just a DP8390[12] plus a data port
+ * and a reset port.
+ */
+enum {
+ Data = 0x10, /* offset from I/O base of data port */
+ Reset = 0x1F, /* offset from I/O base of reset port */
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+static struct {
+ char* name;
+ int id;
+} ne2000pci[] = {
+ { "Realtek 8029", (0x8029<<16)|0x10EC, },
+ { "Winbond 89C940", (0x0940<<16)|0x1050, },
+ { nil },
+};
+
+static Ctlr*
+ne2000match(Ether* edev, int id)
+{
+ int port;
+ Pcidev *p;
+ Ctlr *ctlr;
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ p = ctlr->pcidev;
+ if(((p->did<<16)|p->vid) != id)
+ continue;
+ port = p->mem[0].bar & ~0x01;
+ if(edev->port != 0 && edev->port != port)
+ continue;
+
+ /*
+ * It suffices to fill these in,
+ * the rest is gleaned from the card.
+ */
+ edev->port = port;
+ edev->irq = p->intl;
+
+ ctlr->active = 1;
+
+ return ctlr;
+ }
+
+ return nil;
+}
+
+static void
+ne2000pnp(Ether* edev)
+{
+ int i, id;
+ Pcidev *p;
+ Ctlr *ctlr;
+
+ /*
+ * Make a list of all ethernet controllers
+ * if not already done.
+ */
+ if(ctlrhead == nil){
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->pcidev = p;
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+ }
+
+ /*
+ * Is it a card with an unrecognised vid+did?
+ * Normally a search is made through all the found controllers
+ * for one which matches any of the known vid+did pairs.
+ * If a vid+did pair is specified a search is made for that
+ * specific controller only.
+ */
+ id = 0;
+ for(i = 0; i < edev->nopt; i++){
+ if(cistrncmp(edev->opt[i], "id=", 3) == 0)
+ id = strtol(&edev->opt[i][3], nil, 0);
+ }
+
+ if(id != 0)
+ ne2000match(edev, id);
+ else for(i = 0; ne2000pci[i].name; i++){
+ if(ne2000match(edev, ne2000pci[i].id) != nil)
+ break;
+ }
+}
+
+static int
+ne2000reset(Ether* edev)
+{
+ ushort buf[16];
+ ulong port;
+ Dp8390 *dp8390;
+ int i;
+ uchar ea[Eaddrlen];
+
+ if(edev->port == 0)
+ ne2000pnp(edev);
+
+ /*
+ * Set up the software configuration.
+ * Use defaults for irq, mem and size
+ * if not specified.
+ * Must have a port, no more default.
+ */
+ if(edev->port == 0)
+ return -1;
+ if(edev->irq == 0)
+ edev->irq = 2;
+ if(edev->mem == 0)
+ edev->mem = 0x4000;
+ if(edev->size == 0)
+ edev->size = 16*1024;
+ port = edev->port;
+
+ if(ioalloc(edev->port, 0x20, 0, "ne2000") < 0)
+ return -1;
+
+ edev->ctlr = malloc(sizeof(Dp8390));
+ dp8390 = edev->ctlr;
+ dp8390->width = 2;
+ dp8390->ram = 0;
+
+ dp8390->port = port;
+ dp8390->data = port+Data;
+
+ dp8390->tstart = HOWMANY(edev->mem, Dp8390BufSz);
+ dp8390->pstart = dp8390->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
+ dp8390->pstop = dp8390->tstart + HOWMANY(edev->size, Dp8390BufSz);
+
+ dp8390->dummyrr = 1;
+ for(i = 0; i < edev->nopt; i++){
+ if(strcmp(edev->opt[i], "nodummyrr"))
+ continue;
+ dp8390->dummyrr = 0;
+ break;
+ }
+
+ /*
+ * Reset the board. This is done by doing a read
+ * followed by a write to the Reset address.
+ */
+ buf[0] = inb(port+Reset);
+ delay(2);
+ outb(port+Reset, buf[0]);
+ delay(2);
+
+ /*
+ * Init the (possible) chip, then use the (possible)
+ * chip to read the (possible) PROM for ethernet address
+ * and a marker byte.
+ * Could just look at the DP8390 command register after
+ * initialisation has been tried, but that wouldn't be
+ * enough, there are other ethernet boards which could
+ * match.
+ * Parallels has buf[0x0E] == 0x00 whereas real hardware
+ * usually has 0x57.
+ */
+ dp8390reset(edev);
+ memset(buf, 0, sizeof(buf));
+ dp8390read(dp8390, buf, 0, sizeof(buf));
+ i = buf[0x0E] & 0xFF;
+ if((i != 0x00 && i != 0x57) || (buf[0x0F] & 0xFF) != 0x57){
+ iofree(edev->port);
+ free(edev->ctlr);
+ return -1;
+ }
+
+ /*
+ * Stupid machine. Shorts were asked for,
+ * shorts were delivered, although the PROM is a byte array.
+ * Set the ethernet address.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, edev->ea, Eaddrlen) == 0){
+ for(i = 0; i < sizeof(edev->ea); i++)
+ edev->ea[i] = buf[i];
+ }
+ dp8390setea(edev);
+
+ return 0;
+}
+
+void
+ether2000link(void)
+{
+ addethercard("NE2000", ne2000reset);
+}
diff --git a/sys/src/9/pc/ether2114x.c b/sys/src/9/pc/ether2114x.c
new file mode 100755
index 000000000..554ce7634
--- /dev/null
+++ b/sys/src/9/pc/ether2114x.c
@@ -0,0 +1,1830 @@
+/*
+ * Digital Semiconductor DECchip 2114x PCI Fast Ethernet LAN Controller.
+ * To do:
+ * thresholds;
+ * ring sizing;
+ * handle more error conditions;
+ * tidy setup packet mess;
+ * push initialisation back to attach;
+ * full SROM decoding.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+#define DEBUG (0)
+#define debug if(DEBUG)print
+
+enum {
+ Nrde = 64,
+ Ntde = 64,
+};
+
+#define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4)
+
+enum { /* CRS0 - Bus Mode */
+ Swr = 0x00000001, /* Software Reset */
+ Bar = 0x00000002, /* Bus Arbitration */
+ Dsl = 0x0000007C, /* Descriptor Skip Length (field) */
+ Ble = 0x00000080, /* Big/Little Endian */
+ Pbl = 0x00003F00, /* Programmable Burst Length (field) */
+ Cal = 0x0000C000, /* Cache Alignment (field) */
+ Cal8 = 0x00004000, /* 8 longword boundary alignment */
+ Cal16 = 0x00008000, /* 16 longword boundary alignment */
+ Cal32 = 0x0000C000, /* 32 longword boundary alignment */
+ Tap = 0x000E0000, /* Transmit Automatic Polling (field) */
+ Dbo = 0x00100000, /* Descriptor Byte Ordering Mode */
+ Rml = 0x00200000, /* Read Multiple */
+};
+
+enum { /* CSR[57] - Status and Interrupt Enable */
+ Ti = 0x00000001, /* Transmit Interrupt */
+ Tps = 0x00000002, /* Transmit Process Stopped */
+ Tu = 0x00000004, /* Transmit buffer Unavailable */
+ Tjt = 0x00000008, /* Transmit Jabber Timeout */
+ Unf = 0x00000020, /* transmit UNderFlow */
+ Ri = 0x00000040, /* Receive Interrupt */
+ Ru = 0x00000080, /* Receive buffer Unavailable */
+ Rps = 0x00000100, /* Receive Process Stopped */
+ Rwt = 0x00000200, /* Receive Watchdog Timeout */
+ Eti = 0x00000400, /* Early Transmit Interrupt */
+ Gte = 0x00000800, /* General purpose Timer Expired */
+ Fbe = 0x00002000, /* Fatal Bit Error */
+ Ais = 0x00008000, /* Abnormal Interrupt Summary */
+ Nis = 0x00010000, /* Normal Interrupt Summary */
+ Rs = 0x000E0000, /* Receive process State (field) */
+ Ts = 0x00700000, /* Transmit process State (field) */
+ Eb = 0x03800000, /* Error bits */
+};
+
+enum { /* CSR6 - Operating Mode */
+ Hp = 0x00000001, /* Hash/Perfect receive filtering mode */
+ Sr = 0x00000002, /* Start/stop Receive */
+ Ho = 0x00000004, /* Hash-Only filtering mode */
+ Pb = 0x00000008, /* Pass Bad frames */
+ If = 0x00000010, /* Inverse Filtering */
+ Sb = 0x00000020, /* Start/stop Backoff counter */
+ Pr = 0x00000040, /* Promiscuous Mode */
+ Pm = 0x00000080, /* Pass all Multicast */
+ Fd = 0x00000200, /* Full Duplex mode */
+ Om = 0x00000C00, /* Operating Mode (field) */
+ Fc = 0x00001000, /* Force Collision */
+ St = 0x00002000, /* Start/stop Transmission Command */
+ Tr = 0x0000C000, /* ThReshold control bits (field) */
+ Tr128 = 0x00000000,
+ Tr256 = 0x00004000,
+ Tr512 = 0x00008000,
+ Tr1024 = 0x0000C000,
+ Ca = 0x00020000, /* CApture effect enable */
+ Ps = 0x00040000, /* Port Select */
+ Hbd = 0x00080000, /* HeartBeat Disable */
+ Imm = 0x00100000, /* IMMediate mode */
+ Sf = 0x00200000, /* Store and Forward */
+ Ttm = 0x00400000, /* Transmit Threshold Mode */
+ Pcs = 0x00800000, /* PCS function */
+ Scr = 0x01000000, /* SCRambler mode */
+ Mbo = 0x02000000, /* Must Be One */
+ Ra = 0x40000000, /* Receive All */
+ Sc = 0x80000000, /* Special Capture effect enable */
+
+ TrMODE = Tr512, /* default transmission threshold */
+};
+
+enum { /* CSR9 - ROM and MII Management */
+ Scs = 0x00000001, /* serial ROM chip select */
+ Sclk = 0x00000002, /* serial ROM clock */
+ Sdi = 0x00000004, /* serial ROM data in */
+ Sdo = 0x00000008, /* serial ROM data out */
+ Ss = 0x00000800, /* serial ROM select */
+ Wr = 0x00002000, /* write */
+ Rd = 0x00004000, /* read */
+
+ Mdc = 0x00010000, /* MII management clock */
+ Mdo = 0x00020000, /* MII management write data */
+ Mii = 0x00040000, /* MII management operation mode (W) */
+ Mdi = 0x00080000, /* MII management data in */
+};
+
+enum { /* CSR12 - General-Purpose Port */
+ Gpc = 0x00000100, /* General Purpose Control */
+};
+
+typedef struct Des {
+ int status;
+ int control;
+ ulong addr;
+ Block* bp;
+} Des;
+
+enum { /* status */
+ Of = 0x00000001, /* Rx: OverFlow */
+ Ce = 0x00000002, /* Rx: CRC Error */
+ Db = 0x00000004, /* Rx: Dribbling Bit */
+ Re = 0x00000008, /* Rx: Report on MII Error */
+ Rw = 0x00000010, /* Rx: Receive Watchdog */
+ Ft = 0x00000020, /* Rx: Frame Type */
+ Cs = 0x00000040, /* Rx: Collision Seen */
+ Tl = 0x00000080, /* Rx: Frame too Long */
+ Ls = 0x00000100, /* Rx: Last deScriptor */
+ Fs = 0x00000200, /* Rx: First deScriptor */
+ Mf = 0x00000400, /* Rx: Multicast Frame */
+ Rf = 0x00000800, /* Rx: Runt Frame */
+ Dt = 0x00003000, /* Rx: Data Type (field) */
+ De = 0x00004000, /* Rx: Descriptor Error */
+ Fl = 0x3FFF0000, /* Rx: Frame Length (field) */
+ Ff = 0x40000000, /* Rx: Filtering Fail */
+
+ Def = 0x00000001, /* Tx: DEFerred */
+ Uf = 0x00000002, /* Tx: UnderFlow error */
+ Lf = 0x00000004, /* Tx: Link Fail report */
+ Cc = 0x00000078, /* Tx: Collision Count (field) */
+ Hf = 0x00000080, /* Tx: Heartbeat Fail */
+ Ec = 0x00000100, /* Tx: Excessive Collisions */
+ Lc = 0x00000200, /* Tx: Late Collision */
+ Nc = 0x00000400, /* Tx: No Carrier */
+ Lo = 0x00000800, /* Tx: LOss of carrier */
+ To = 0x00004000, /* Tx: Transmission jabber timeOut */
+
+ Es = 0x00008000, /* [RT]x: Error Summary */
+ Own = 0x80000000, /* [RT]x: OWN bit */
+};
+
+enum { /* control */
+ Bs1 = 0x000007FF, /* [RT]x: Buffer 1 Size */
+ Bs2 = 0x003FF800, /* [RT]x: Buffer 2 Size */
+
+ Ch = 0x01000000, /* [RT]x: second address CHained */
+ Er = 0x02000000, /* [RT]x: End of Ring */
+
+ Ft0 = 0x00400000, /* Tx: Filtering Type 0 */
+ Dpd = 0x00800000, /* Tx: Disabled PaDding */
+ Ac = 0x04000000, /* Tx: Add CRC disable */
+ Set = 0x08000000, /* Tx: SETup packet */
+ Ft1 = 0x10000000, /* Tx: Filtering Type 1 */
+ Fseg = 0x20000000, /* Tx: First SEGment */
+ Lseg = 0x40000000, /* Tx: Last SEGment */
+ Ic = 0x80000000, /* Tx: Interrupt on Completion */
+};
+
+enum { /* PHY registers */
+ Bmcr = 0, /* Basic Mode Control */
+ Bmsr = 1, /* Basic Mode Status */
+ Phyidr1 = 2, /* PHY Identifier #1 */
+ Phyidr2 = 3, /* PHY Identifier #2 */
+ Anar = 4, /* Auto-Negotiation Advertisment */
+ Anlpar = 5, /* Auto-Negotiation Link Partner Ability */
+ Aner = 6, /* Auto-Negotiation Expansion */
+};
+
+enum { /* Variants */
+ Tulip0 = (0x0009<<16)|0x1011,
+ Tulip1 = (0x0014<<16)|0x1011,
+ Tulip3 = (0x0019<<16)|0x1011,
+ Pnic = (0x0002<<16)|0x11AD,
+ Pnic2 = (0xC115<<16)|0x11AD,
+ CentaurP = (0x0985<<16)|0x1317,
+ CentaurPcb = (0x1985<<16)|0x1317,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id; /* (pcidev->did<<16)|pcidev->vid */
+
+ uchar* srom;
+ int sromsz; /* address size in bits */
+ uchar* sromea; /* MAC address */
+ uchar* leaf;
+ int sct; /* selected connection type */
+ int k; /* info block count */
+ uchar* infoblock[16];
+ int sctk; /* sct block index */
+ int curk; /* current block index */
+ uchar* type5block;
+
+ int phy[32]; /* logical to physical map */
+ int phyreset; /* reset bitmap */
+ int curphyad;
+ int fdx;
+ int ttm;
+
+ uchar fd; /* option */
+ int medium; /* option */
+
+ int csr6; /* CSR6 - operating mode */
+ int mask; /* CSR[57] - interrupt mask */
+ int mbps;
+
+ Lock lock;
+
+ Des* rdr; /* receive descriptor ring */
+ int nrdr; /* size of rdr */
+ int rdrx; /* index into rdr */
+
+ Lock tlock;
+ Des* tdr; /* transmit descriptor ring */
+ int ntdr; /* size of tdr */
+ int tdrh; /* host index into tdr */
+ int tdri; /* interface index into tdr */
+ int ntq; /* descriptors active */
+ int ntqmax;
+ Block* setupbp;
+
+ ulong of; /* receive statistics */
+ ulong ce;
+ ulong cs;
+ ulong tl;
+ ulong rf;
+ ulong de;
+
+ ulong ru;
+ ulong rps;
+ ulong rwt;
+
+ ulong uf; /* transmit statistics */
+ ulong ec;
+ ulong lc;
+ ulong nc;
+ ulong lo;
+ ulong to;
+
+ ulong tps;
+ ulong tu;
+ ulong tjt;
+ ulong unf;
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+#define csr32r(c, r) (inl((c)->port+((r)*8)))
+#define csr32w(c, r, l) (outl((c)->port+((r)*8), (ulong)(l)))
+
+static void
+promiscuous(void* arg, int on)
+{
+ Ctlr *ctlr;
+
+ ctlr = ((Ether*)arg)->ctlr;
+ ilock(&ctlr->lock);
+ if(on)
+ ctlr->csr6 |= Pr;
+ else
+ ctlr->csr6 &= ~Pr;
+ csr32w(ctlr, 6, ctlr->csr6);
+ iunlock(&ctlr->lock);
+}
+
+/* multicast already on, don't need to do anything */
+static void
+multicast(void*, uchar*, int)
+{
+}
+
+static void
+attach(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(&ctlr->lock);
+ if(!(ctlr->csr6 & Sr)){
+ ctlr->csr6 |= Sr;
+ csr32w(ctlr, 6, ctlr->csr6);
+ }
+ iunlock(&ctlr->lock);
+}
+
+static long
+ifstat(Ether* ether, void* a, long n, ulong offset)
+{
+ Ctlr *ctlr;
+ char *buf, *p;
+ int i, l, len;
+
+ ctlr = ether->ctlr;
+
+ ether->crcs = ctlr->ce;
+ ether->frames = ctlr->rf+ctlr->cs;
+ ether->buffs = ctlr->de+ctlr->tl;
+ ether->overflows = ctlr->of;
+
+ if(n == 0)
+ return 0;
+
+ p = malloc(READSTR);
+ l = snprint(p, READSTR, "Overflow: %lud\n", ctlr->of);
+ l += snprint(p+l, READSTR-l, "Ru: %lud\n", ctlr->ru);
+ l += snprint(p+l, READSTR-l, "Rps: %lud\n", ctlr->rps);
+ l += snprint(p+l, READSTR-l, "Rwt: %lud\n", ctlr->rwt);
+ l += snprint(p+l, READSTR-l, "Tps: %lud\n", ctlr->tps);
+ l += snprint(p+l, READSTR-l, "Tu: %lud\n", ctlr->tu);
+ l += snprint(p+l, READSTR-l, "Tjt: %lud\n", ctlr->tjt);
+ l += snprint(p+l, READSTR-l, "Unf: %lud\n", ctlr->unf);
+ l += snprint(p+l, READSTR-l, "CRC Error: %lud\n", ctlr->ce);
+ l += snprint(p+l, READSTR-l, "Collision Seen: %lud\n", ctlr->cs);
+ l += snprint(p+l, READSTR-l, "Frame Too Long: %lud\n", ctlr->tl);
+ l += snprint(p+l, READSTR-l, "Runt Frame: %lud\n", ctlr->rf);
+ l += snprint(p+l, READSTR-l, "Descriptor Error: %lud\n", ctlr->de);
+ l += snprint(p+l, READSTR-l, "Underflow Error: %lud\n", ctlr->uf);
+ l += snprint(p+l, READSTR-l, "Excessive Collisions: %lud\n", ctlr->ec);
+ l += snprint(p+l, READSTR-l, "Late Collision: %lud\n", ctlr->lc);
+ l += snprint(p+l, READSTR-l, "No Carrier: %lud\n", ctlr->nc);
+ l += snprint(p+l, READSTR-l, "Loss of Carrier: %lud\n", ctlr->lo);
+ l += snprint(p+l, READSTR-l, "Transmit Jabber Timeout: %lud\n",
+ ctlr->to);
+ l += snprint(p+l, READSTR-l, "csr6: %luX %uX\n", csr32r(ctlr, 6),
+ ctlr->csr6);
+ snprint(p+l, READSTR-l, "ntqmax: %d\n", ctlr->ntqmax);
+ ctlr->ntqmax = 0;
+ buf = a;
+ len = readstr(offset, buf, n, p);
+ if(offset > l)
+ offset -= l;
+ else
+ offset = 0;
+ buf += len;
+ n -= len;
+
+ l = snprint(p, READSTR, "srom:");
+ for(i = 0; i < (1<<(ctlr->sromsz)*sizeof(ushort)); i++){
+ if(i && ((i & 0x0F) == 0))
+ l += snprint(p+l, READSTR-l, "\n ");
+ l += snprint(p+l, READSTR-l, " %2.2uX", ctlr->srom[i]);
+ }
+
+ snprint(p+l, READSTR-l, "\n");
+ len += readstr(offset, buf, n, p);
+ free(p);
+
+ return len;
+}
+
+static void
+txstart(Ether* ether)
+{
+ Ctlr *ctlr;
+ Block *bp;
+ Des *des;
+ int control;
+
+ ctlr = ether->ctlr;
+ while(ctlr->ntq < (ctlr->ntdr-1)){
+ if(ctlr->setupbp){
+ bp = ctlr->setupbp;
+ ctlr->setupbp = 0;
+ control = Ic|Set|BLEN(bp);
+ }
+ else{
+ bp = qget(ether->oq);
+ if(bp == nil)
+ break;
+ control = Ic|Lseg|Fseg|BLEN(bp);
+ }
+
+ ctlr->tdr[PREV(ctlr->tdrh, ctlr->ntdr)].control &= ~Ic;
+ des = &ctlr->tdr[ctlr->tdrh];
+ des->bp = bp;
+ des->addr = PCIWADDR(bp->rp);
+ des->control |= control;
+ ctlr->ntq++;
+ coherence();
+ des->status = Own;
+ csr32w(ctlr, 1, 0);
+ ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
+ }
+
+ if(ctlr->ntq > ctlr->ntqmax)
+ ctlr->ntqmax = ctlr->ntq;
+}
+
+static void
+transmit(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(&ctlr->tlock);
+ txstart(ether);
+ iunlock(&ctlr->tlock);
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Ether *ether;
+ int len, status;
+ Des *des;
+ Block *bp;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+
+ while((status = csr32r(ctlr, 5)) & (Nis|Ais)){
+ /*
+ * Acknowledge the interrupts and mask-out
+ * the ones that are implicitly handled.
+ */
+ csr32w(ctlr, 5, status);
+ status &= (ctlr->mask & ~(Nis|Ti));
+
+ if(status & Ais){
+ if(status & Tps)
+ ctlr->tps++;
+ if(status & Tu)
+ ctlr->tu++;
+ if(status & Tjt)
+ ctlr->tjt++;
+ if(status & Ru)
+ ctlr->ru++;
+ if(status & Rps)
+ ctlr->rps++;
+ if(status & Rwt)
+ ctlr->rwt++;
+ status &= ~(Ais|Rwt|Rps|Ru|Tjt|Tu|Tps);
+ }
+
+ /*
+ * Received packets.
+ */
+ if(status & Ri){
+ des = &ctlr->rdr[ctlr->rdrx];
+ while(!(des->status & Own)){
+ if(des->status & Es){
+ if(des->status & Of)
+ ctlr->of++;
+ if(des->status & Ce)
+ ctlr->ce++;
+ if(des->status & Cs)
+ ctlr->cs++;
+ if(des->status & Tl)
+ ctlr->tl++;
+ if(des->status & Rf)
+ ctlr->rf++;
+ if(des->status & De)
+ ctlr->de++;
+ }
+ else if(bp = iallocb(Rbsz)){
+ len = ((des->status & Fl)>>16)-4;
+ des->bp->wp = des->bp->rp+len;
+ etheriq(ether, des->bp, 1);
+ des->bp = bp;
+ des->addr = PCIWADDR(bp->rp);
+ }
+
+ des->control &= Er;
+ des->control |= Rbsz;
+ coherence();
+ des->status = Own;
+
+ ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
+ des = &ctlr->rdr[ctlr->rdrx];
+ }
+ status &= ~Ri;
+ }
+
+ /*
+ * Check the transmit side:
+ * check for Transmit Underflow and Adjust
+ * the threshold upwards;
+ * free any transmitted buffers and try to
+ * top-up the ring.
+ */
+ if(status & Unf){
+ ctlr->unf++;
+ ilock(&ctlr->lock);
+ csr32w(ctlr, 6, ctlr->csr6 & ~St);
+ switch(ctlr->csr6 & Tr){
+ case Tr128:
+ len = Tr256;
+ break;
+ case Tr256:
+ len = Tr512;
+ break;
+ case Tr512:
+ len = Tr1024;
+ break;
+ default:
+ case Tr1024:
+ len = Sf;
+ break;
+ }
+ ctlr->csr6 = (ctlr->csr6 & ~Tr)|len;
+ csr32w(ctlr, 6, ctlr->csr6);
+ iunlock(&ctlr->lock);
+ csr32w(ctlr, 5, Tps);
+ status &= ~(Unf|Tps);
+ }
+
+ ilock(&ctlr->tlock);
+ while(ctlr->ntq){
+ des = &ctlr->tdr[ctlr->tdri];
+ if(des->status & Own)
+ break;
+
+ if(des->status & Es){
+ if(des->status & Uf)
+ ctlr->uf++;
+ if(des->status & Ec)
+ ctlr->ec++;
+ if(des->status & Lc)
+ ctlr->lc++;
+ if(des->status & Nc)
+ ctlr->nc++;
+ if(des->status & Lo)
+ ctlr->lo++;
+ if(des->status & To)
+ ctlr->to++;
+ ether->oerrs++;
+ }
+
+ freeb(des->bp);
+ des->control &= Er;
+
+ ctlr->ntq--;
+ ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
+ }
+ txstart(ether);
+ iunlock(&ctlr->tlock);
+
+ /*
+ * Anything left not catered for?
+ */
+ if(status)
+ panic("#l%d: status %8.8uX\n", ether->ctlrno, status);
+ }
+}
+
+static void
+ctlrinit(Ether* ether)
+{
+ Ctlr *ctlr;
+ Des *des;
+ Block *bp;
+ int i;
+ uchar bi[Eaddrlen*2];
+
+ ctlr = ether->ctlr;
+
+ /*
+ * Allocate and initialise the receive ring;
+ * allocate and initialise the transmit ring;
+ * unmask interrupts and start the transmit side;
+ * create and post a setup packet to initialise
+ * the physical ethernet address.
+ */
+ ctlr->rdr = xspanalloc(ctlr->nrdr*sizeof(Des), 8*sizeof(ulong), 0);
+ for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
+ des->bp = iallocb(Rbsz);
+ if(des->bp == nil)
+ panic("can't allocate ethernet receive ring\n");
+ des->status = Own;
+ des->control = Rbsz;
+ des->addr = PCIWADDR(des->bp->rp);
+ }
+ ctlr->rdr[ctlr->nrdr-1].control |= Er;
+ ctlr->rdrx = 0;
+ csr32w(ctlr, 3, PCIWADDR(ctlr->rdr));
+
+ ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0);
+ ctlr->tdr[ctlr->ntdr-1].control |= Er;
+ ctlr->tdrh = 0;
+ ctlr->tdri = 0;
+ csr32w(ctlr, 4, PCIWADDR(ctlr->tdr));
+
+ /*
+ * Clear any bits in the Status Register (CSR5) as
+ * the PNIC has a different reset value from a true 2114x.
+ */
+ ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti;
+ csr32w(ctlr, 5, ctlr->mask);
+ csr32w(ctlr, 7, ctlr->mask);
+ ctlr->csr6 |= St|Pm;
+ csr32w(ctlr, 6, ctlr->csr6);
+
+ for(i = 0; i < Eaddrlen/2; i++){
+ bi[i*4] = ether->ea[i*2];
+ bi[i*4+1] = ether->ea[i*2+1];
+ bi[i*4+2] = ether->ea[i*2+1];
+ bi[i*4+3] = ether->ea[i*2];
+ }
+ bp = iallocb(Eaddrlen*2*16);
+ if(bp == nil)
+ panic("can't allocate ethernet setup buffer\n");
+ memset(bp->rp, 0xFF, sizeof(bi));
+ for(i = sizeof(bi); i < sizeof(bi)*16; i += sizeof(bi))
+ memmove(bp->rp+i, bi, sizeof(bi));
+ bp->wp += sizeof(bi)*16;
+
+ ctlr->setupbp = bp;
+ ether->oq = qopen(256*1024, Qmsg, 0, 0);
+ transmit(ether);
+}
+
+static void
+csr9w(Ctlr* ctlr, int data)
+{
+ csr32w(ctlr, 9, data);
+ microdelay(1);
+}
+
+static int
+miimdi(Ctlr* ctlr, int n)
+{
+ int data, i;
+
+ /*
+ * Read n bits from the MII Management Register.
+ */
+ data = 0;
+ for(i = n-1; i >= 0; i--){
+ if(csr32r(ctlr, 9) & Mdi)
+ data |= (1<<i);
+ csr9w(ctlr, Mii|Mdc);
+ csr9w(ctlr, Mii);
+ }
+ csr9w(ctlr, 0);
+
+ return data;
+}
+
+static void
+miimdo(Ctlr* ctlr, int bits, int n)
+{
+ int i, mdo;
+
+ /*
+ * Write n bits to the MII Management Register.
+ */
+ for(i = n-1; i >= 0; i--){
+ if(bits & (1<<i))
+ mdo = Mdo;
+ else
+ mdo = 0;
+ csr9w(ctlr, mdo);
+ csr9w(ctlr, mdo|Mdc);
+ csr9w(ctlr, mdo);
+ }
+}
+
+static int
+miir(Ctlr* ctlr, int phyad, int regad)
+{
+ int data, i;
+
+ if(ctlr->id == Pnic){
+ i = 1000;
+ csr32w(ctlr, 20, 0x60020000|(phyad<<23)|(regad<<18));
+ do{
+ microdelay(1);
+ data = csr32r(ctlr, 20);
+ }while((data & 0x80000000) && --i);
+
+ if(i == 0)
+ return -1;
+ return data & 0xFFFF;
+ }
+
+ /*
+ * Preamble;
+ * ST+OP+PHYAD+REGAD;
+ * TA + 16 data bits.
+ */
+ miimdo(ctlr, 0xFFFFFFFF, 32);
+ miimdo(ctlr, 0x1800|(phyad<<5)|regad, 14);
+ data = miimdi(ctlr, 18);
+
+ if(data & 0x10000)
+ return -1;
+
+ return data & 0xFFFF;
+}
+
+static void
+miiw(Ctlr* ctlr, int phyad, int regad, int data)
+{
+ /*
+ * Preamble;
+ * ST+OP+PHYAD+REGAD+TA + 16 data bits;
+ * Z.
+ */
+ miimdo(ctlr, 0xFFFFFFFF, 32);
+ data &= 0xFFFF;
+ data |= (0x05<<(5+5+2+16))|(phyad<<(5+2+16))|(regad<<(2+16))|(0x02<<16);
+ miimdo(ctlr, data, 32);
+ csr9w(ctlr, Mdc);
+ csr9w(ctlr, 0);
+}
+
+static int
+sromr(Ctlr* ctlr, int r)
+{
+ int i, op, data, size;
+
+ if(ctlr->id == Pnic){
+ i = 1000;
+ csr32w(ctlr, 19, 0x600|r);
+ do{
+ microdelay(1);
+ data = csr32r(ctlr, 19);
+ }while((data & 0x80000000) && --i);
+
+ if(ctlr->sromsz == 0)
+ ctlr->sromsz = 6;
+
+ return csr32r(ctlr, 9) & 0xFFFF;
+ }
+
+ /*
+ * This sequence for reading a 16-bit register 'r'
+ * in the EEPROM is taken (pretty much) straight from Section
+ * 7.4 of the 21140 Hardware Reference Manual.
+ */
+reread:
+ csr9w(ctlr, Rd|Ss);
+ csr9w(ctlr, Rd|Ss|Scs);
+ csr9w(ctlr, Rd|Ss|Sclk|Scs);
+ csr9w(ctlr, Rd|Ss);
+
+ op = 0x06;
+ for(i = 3-1; i >= 0; i--){
+ data = Rd|Ss|(((op>>i) & 0x01)<<2)|Scs;
+ csr9w(ctlr, data);
+ csr9w(ctlr, data|Sclk);
+ csr9w(ctlr, data);
+ }
+
+ /*
+ * First time through must work out the EEPROM size.
+ * This doesn't seem to work on the 21041 as implemented
+ * in Virtual PC for the Mac, so wire any 21041 to 6,
+ * it's the only 21041 this code will ever likely see.
+ */
+ if((size = ctlr->sromsz) == 0){
+ if(ctlr->id == Tulip1)
+ ctlr->sromsz = size = 6;
+ else
+ size = 8;
+ }
+
+ for(size = size-1; size >= 0; size--){
+ data = Rd|Ss|(((r>>size) & 0x01)<<2)|Scs;
+ csr9w(ctlr, data);
+ csr9w(ctlr, data|Sclk);
+ csr9w(ctlr, data);
+ microdelay(1);
+ if(ctlr->sromsz == 0 && !(csr32r(ctlr, 9) & Sdo))
+ break;
+ }
+
+ data = 0;
+ for(i = 16-1; i >= 0; i--){
+ csr9w(ctlr, Rd|Ss|Sclk|Scs);
+ if(csr32r(ctlr, 9) & Sdo)
+ data |= (1<<i);
+ csr9w(ctlr, Rd|Ss|Scs);
+ }
+
+ csr9w(ctlr, 0);
+
+ if(ctlr->sromsz == 0){
+ ctlr->sromsz = 8-size;
+ goto reread;
+ }
+
+ return data & 0xFFFF;
+}
+
+static void
+shutdown(Ether* ether)
+{
+ Ctlr *ctlr = ether->ctlr;
+
+print("ether2114x shutting down\n");
+ csr32w(ctlr, 0, Swr);
+}
+
+static void
+softreset(Ctlr* ctlr)
+{
+ /*
+ * Soft-reset the controller and initialise bus mode.
+ * Delay should be >= 50 PCI cycles (2×S @ 25MHz).
+ */
+ csr32w(ctlr, 0, Swr);
+ microdelay(10);
+ csr32w(ctlr, 0, Rml|Cal16);
+ delay(1);
+}
+
+static int
+type5block(Ctlr* ctlr, uchar* block)
+{
+ int csr15, i, len;
+
+ /*
+ * Reset or GPR sequence. Reset should be once only,
+ * before the GPR sequence.
+ * Note 'block' is not a pointer to the block head but
+ * a pointer to the data in the block starting at the
+ * reset length value so type5block can be used for the
+ * sequences contained in type 1 and type 3 blocks.
+ * The SROM docs state the 21140 type 5 block is the
+ * same as that for the 21143, but the two controllers
+ * use different registers and sequence-element lengths
+ * so the 21140 code here is a guess for a real type 5
+ * sequence.
+ */
+ len = *block++;
+ if(ctlr->id != Tulip3){
+ for(i = 0; i < len; i++){
+ csr32w(ctlr, 12, *block);
+ block++;
+ }
+ return len;
+ }
+
+ for(i = 0; i < len; i++){
+ csr15 = *block++<<16;
+ csr15 |= *block++<<24;
+ csr32w(ctlr, 15, csr15);
+ debug("%8.8uX ", csr15);
+ }
+ return 2*len;
+}
+
+static int
+typephylink(Ctlr* ctlr, uchar*)
+{
+ int an, bmcr, bmsr, csr6, x;
+
+ /*
+ * Fail if
+ * auto-negotiataion enabled but not complete;
+ * no valid link established.
+ */
+ bmcr = miir(ctlr, ctlr->curphyad, Bmcr);
+ miir(ctlr, ctlr->curphyad, Bmsr);
+ bmsr = miir(ctlr, ctlr->curphyad, Bmsr);
+ debug("bmcr 0x%2.2uX bmsr 0x%2.2uX\n", bmcr, bmsr);
+ if(((bmcr & 0x1000) && !(bmsr & 0x0020)) || !(bmsr & 0x0004))
+ return 0;
+
+ if(bmcr & 0x1000){
+ an = miir(ctlr, ctlr->curphyad, Anar);
+ an &= miir(ctlr, ctlr->curphyad, Anlpar) & 0x3E0;
+ debug("an 0x%2.uX 0x%2.2uX 0x%2.2uX\n",
+ miir(ctlr, ctlr->curphyad, Anar),
+ miir(ctlr, ctlr->curphyad, Anlpar),
+ an);
+
+ if(an & 0x0100)
+ x = 0x4000;
+ else if(an & 0x0080)
+ x = 0x2000;
+ else if(an & 0x0040)
+ x = 0x1000;
+ else if(an & 0x0020)
+ x = 0x0800;
+ else
+ x = 0;
+ }
+ else if((bmcr & 0x2100) == 0x2100)
+ x = 0x4000;
+ else if(bmcr & 0x2000){
+ /*
+ * If FD capable, force it if necessary.
+ */
+ if((bmsr & 0x4000) && ctlr->fd){
+ miiw(ctlr, ctlr->curphyad, Bmcr, 0x2100);
+ x = 0x4000;
+ }
+ else
+ x = 0x2000;
+ }
+ else if(bmcr & 0x0100)
+ x = 0x1000;
+ else
+ x = 0x0800;
+
+ csr6 = Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
+ if(ctlr->fdx & x)
+ csr6 |= Fd;
+ if(ctlr->ttm & x)
+ csr6 |= Ttm;
+ debug("csr6 0x%8.8uX 0x%8.8uX 0x%8.8luX\n",
+ csr6, ctlr->csr6, csr32r(ctlr, 6));
+ if(csr6 != ctlr->csr6){
+ ctlr->csr6 = csr6;
+ csr32w(ctlr, 6, csr6);
+ }
+
+ return 1;
+}
+
+static int
+typephymode(Ctlr* ctlr, uchar* block, int wait)
+{
+ uchar *p;
+ int len, mc, nway, phyx, timeo;
+
+ if(DEBUG){
+ int i;
+
+ len = (block[0] & ~0x80)+1;
+ for(i = 0; i < len; i++)
+ debug("%2.2uX ", block[i]);
+ debug("\n");
+ }
+
+ if(block[1] == 1)
+ len = 1;
+ else if(block[1] == 3)
+ len = 2;
+ else
+ return -1;
+
+ /*
+ * Snarf the media capabilities, nway advertisment,
+ * FDX and TTM bitmaps.
+ */
+ p = &block[5+len*block[3]+len*block[4+len*block[3]]];
+ mc = *p++;
+ mc |= *p++<<8;
+ nway = *p++;
+ nway |= *p++<<8;
+ ctlr->fdx = *p++;
+ ctlr->fdx |= *p++<<8;
+ ctlr->ttm = *p++;
+ ctlr->ttm |= *p<<8;
+ debug("mc %4.4uX nway %4.4uX fdx %4.4uX ttm %4.4uX\n",
+ mc, nway, ctlr->fdx, ctlr->ttm);
+ USED(mc);
+
+ phyx = block[2];
+ ctlr->curphyad = ctlr->phy[phyx];
+
+ ctlr->csr6 = 0; /* Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb; */
+ // csr32w(ctlr, 6, ctlr->csr6);
+ if(typephylink(ctlr, block))
+ return 0;
+
+ if(!(ctlr->phyreset & (1<<phyx))){
+ debug("reset seq: len %d: ", block[3]);
+ if(ctlr->type5block)
+ type5block(ctlr, &ctlr->type5block[2]);
+ else
+ type5block(ctlr, &block[4+len*block[3]]);
+ debug("\n");
+ ctlr->phyreset |= (1<<phyx);
+ }
+
+ /*
+ * GPR sequence.
+ */
+ debug("gpr seq: len %d: ", block[3]);
+ type5block(ctlr, &block[3]);
+ debug("\n");
+
+ ctlr->csr6 = 0; /* Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb; */
+ // csr32w(ctlr, 6, ctlr->csr6);
+ if(typephylink(ctlr, block))
+ return 0;
+
+ /*
+ * Turn off auto-negotiation, set the auto-negotiation
+ * advertisment register then start the auto-negotiation
+ * process again.
+ */
+ miiw(ctlr, ctlr->curphyad, Bmcr, 0);
+ miiw(ctlr, ctlr->curphyad, Anar, nway|1);
+ miiw(ctlr, ctlr->curphyad, Bmcr, 0x1000);
+
+ if(!wait)
+ return 0;
+
+ for(timeo = 0; timeo < 45; timeo++){
+ if(typephylink(ctlr, block))
+ return 0;
+ delay(100);
+ }
+
+ return -1;
+}
+
+static int
+typesymmode(Ctlr *ctlr, uchar *block, int wait)
+{
+ uint gpmode, gpdata, command;
+
+ USED(wait);
+ gpmode = block[3] | ((uint) block[4] << 8);
+ gpdata = block[5] | ((uint) block[6] << 8);
+ command = (block[7] | ((uint) block[8] << 8)) & 0x71;
+ if (command & 0x8000) {
+ print("ether2114x.c: FIXME: handle type 4 mode blocks where cmd.active_invalid != 0\n");
+ return -1;
+ }
+ csr32w(ctlr, 15, gpmode);
+ csr32w(ctlr, 15, gpdata);
+ ctlr->csr6 = (command & 0x71) << 18;
+ csr32w(ctlr, 6, ctlr->csr6);
+ return 0;
+}
+
+static int
+type2mode(Ctlr* ctlr, uchar* block, int)
+{
+ uchar *p;
+ int csr6, csr13, csr14, csr15, gpc, gpd;
+
+ csr6 = Sc|Mbo|Ca|TrMODE|Sb;
+ debug("type2mode: medium 0x%2.2uX\n", block[2]);
+
+ /*
+ * Don't attempt full-duplex
+ * unless explicitly requested.
+ */
+ if((block[2] & 0x3F) == 0x04){ /* 10BASE-TFD */
+ if(!ctlr->fd)
+ return -1;
+ csr6 |= Fd;
+ }
+
+ /*
+ * Operating mode programming values from the datasheet
+ * unless media specific data is explicitly given.
+ */
+ p = &block[3];
+ if(block[2] & 0x40){
+ csr13 = (block[4]<<8)|block[3];
+ csr14 = (block[6]<<8)|block[5];
+ csr15 = (block[8]<<8)|block[7];
+ p += 6;
+ }
+ else switch(block[2] & 0x3F){
+ default:
+ return -1;
+ case 0x00: /* 10BASE-T */
+ csr13 = 0x00000001;
+ csr14 = 0x00007F3F;
+ csr15 = 0x00000008;
+ break;
+ case 0x01: /* 10BASE-2 */
+ csr13 = 0x00000009;
+ csr14 = 0x00000705;
+ csr15 = 0x00000006;
+ break;
+ case 0x02: /* 10BASE-5 (AUI) */
+ csr13 = 0x00000009;
+ csr14 = 0x00000705;
+ csr15 = 0x0000000E;
+ break;
+ case 0x04: /* 10BASE-TFD */
+ csr13 = 0x00000001;
+ csr14 = 0x00007F3D;
+ csr15 = 0x00000008;
+ break;
+ }
+ gpc = *p++<<16;
+ gpc |= *p++<<24;
+ gpd = *p++<<16;
+ gpd |= *p<<24;
+
+ csr32w(ctlr, 13, 0);
+ csr32w(ctlr, 14, csr14);
+ csr32w(ctlr, 15, gpc|csr15);
+ delay(10);
+ csr32w(ctlr, 15, gpd|csr15);
+ csr32w(ctlr, 13, csr13);
+
+ ctlr->csr6 = csr6;
+ csr32w(ctlr, 6, ctlr->csr6);
+
+ debug("type2mode: csr13 %8.8uX csr14 %8.8uX csr15 %8.8uX\n",
+ csr13, csr14, csr15);
+ debug("type2mode: gpc %8.8uX gpd %8.8uX csr6 %8.8uX\n",
+ gpc, gpd, csr6);
+
+ return 0;
+}
+
+static int
+type0link(Ctlr* ctlr, uchar* block)
+{
+ int m, polarity, sense;
+
+ m = (block[3]<<8)|block[2];
+ sense = 1<<((m & 0x000E)>>1);
+ if(m & 0x0080)
+ polarity = sense;
+ else
+ polarity = 0;
+
+ return (csr32r(ctlr, 12) & sense)^polarity;
+}
+
+static int
+type0mode(Ctlr* ctlr, uchar* block, int wait)
+{
+ int csr6, m, timeo;
+
+ csr6 = Sc|Mbo|Hbd|Ca|TrMODE|Sb;
+debug("type0: medium 0x%uX, fd %d: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
+ ctlr->medium, ctlr->fd, block[0], block[1], block[2], block[3]);
+ switch(block[0]){
+ default:
+ break;
+
+ case 0x04: /* 10BASE-TFD */
+ case 0x05: /* 100BASE-TXFD */
+ case 0x08: /* 100BASE-FXFD */
+ /*
+ * Don't attempt full-duplex
+ * unless explicitly requested.
+ */
+ if(!ctlr->fd)
+ return -1;
+ csr6 |= Fd;
+ break;
+ }
+
+ m = (block[3]<<8)|block[2];
+ if(m & 0x0001)
+ csr6 |= Ps;
+ if(m & 0x0010)
+ csr6 |= Ttm;
+ if(m & 0x0020)
+ csr6 |= Pcs;
+ if(m & 0x0040)
+ csr6 |= Scr;
+
+ csr32w(ctlr, 12, block[1]);
+ microdelay(10);
+ csr32w(ctlr, 6, csr6);
+ ctlr->csr6 = csr6;
+
+ if(!wait)
+ return 0;
+
+ for(timeo = 0; timeo < 30; timeo++){
+ if(type0link(ctlr, block))
+ return 0;
+ delay(100);
+ }
+
+ return -1;
+}
+
+static int
+media21041(Ether* ether, int wait)
+{
+ Ctlr* ctlr;
+ uchar *block;
+ int csr6, csr13, csr14, csr15, medium, timeo;
+
+ ctlr = ether->ctlr;
+ block = ctlr->infoblock[ctlr->curk];
+ debug("media21041: block[0] %2.2uX, medium %4.4uX sct %4.4uX\n",
+ block[0], ctlr->medium, ctlr->sct);
+
+ medium = block[0] & 0x3F;
+ if(ctlr->medium >= 0 && medium != ctlr->medium)
+ return 0;
+ if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != medium)
+ return 0;
+
+ csr6 = Sc|Mbo|Ca|TrMODE|Sb;
+ if(block[0] & 0x40){
+ csr13 = (block[2]<<8)|block[1];
+ csr14 = (block[4]<<8)|block[3];
+ csr15 = (block[6]<<8)|block[5];
+ }
+ else switch(medium){
+ default:
+ return -1;
+ case 0x00: /* 10BASE-T */
+ csr13 = 0xEF01;
+ csr14 = 0xFF3F;
+ csr15 = 0x0008;
+ break;
+ case 0x01: /* 10BASE-2 */
+ csr13 = 0xEF09;
+ csr14 = 0xF73D;
+ csr15 = 0x0006;
+ break;
+ case 0x02: /* 10BASE-5 */
+ csr13 = 0xEF09;
+ csr14 = 0xF73D;
+ csr15 = 0x000E;
+ break;
+ case 0x04: /* 10BASE-TFD */
+ csr13 = 0xEF01;
+ csr14 = 0xFF3D;
+ csr15 = 0x0008;
+ break;
+ }
+
+ csr32w(ctlr, 13, 0);
+ csr32w(ctlr, 14, csr14);
+ csr32w(ctlr, 15, csr15);
+ csr32w(ctlr, 13, csr13);
+ delay(10);
+
+ if(medium == 0x04)
+ csr6 |= Fd;
+ ctlr->csr6 = csr6;
+ csr32w(ctlr, 6, ctlr->csr6);
+
+ debug("media21041: csr6 %8.8uX csr13 %4.4uX csr14 %4.4uX csr15 %4.4uX\n",
+ csr6, csr13, csr14, csr15);
+
+ if(!wait)
+ return 0;
+
+ for(timeo = 0; timeo < 30; timeo++){
+ if(!(csr32r(ctlr, 12) & 0x0002)){
+ debug("media21041: ok: csr12 %4.4luX timeo %d\n",
+ csr32r(ctlr, 12), timeo);
+ return 10;
+ }
+ delay(100);
+ }
+ debug("media21041: !ok: csr12 %4.4luX\n", csr32r(ctlr, 12));
+
+ return -1;
+}
+
+static int
+mediaxx(Ether* ether, int wait)
+{
+ Ctlr* ctlr;
+ uchar *block;
+
+ ctlr = ether->ctlr;
+ block = ctlr->infoblock[ctlr->curk];
+ if(block[0] & 0x80){
+ switch(block[1]){
+ default:
+ return -1;
+ case 0:
+ if(ctlr->medium >= 0 && block[2] != ctlr->medium)
+ return 0;
+/* need this test? */ if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[2])
+ return 0;
+ if(type0mode(ctlr, block+2, wait))
+ return 0;
+ break;
+ case 1:
+ if(typephymode(ctlr, block, wait))
+ return 0;
+ break;
+ case 2:
+ debug("type2: medium %d block[2] %d\n",
+ ctlr->medium, block[2]);
+ if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
+ return 0;
+ if(type2mode(ctlr, block, wait))
+ return 0;
+ break;
+ case 3:
+ if(typephymode(ctlr, block, wait))
+ return 0;
+ break;
+ case 4:
+ debug("type4: medium %d block[2] %d\n",
+ ctlr->medium, block[2]);
+ if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
+ return 0;
+ if(typesymmode(ctlr, block, wait))
+ return 0;
+ break;
+ }
+ }
+ else{
+ if(ctlr->medium >= 0 && block[0] != ctlr->medium)
+ return 0;
+/* need this test? */if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[0])
+ return 0;
+ if(type0mode(ctlr, block, wait))
+ return 0;
+ }
+
+ if(ctlr->csr6){
+ if(!(ctlr->csr6 & Ps) || (ctlr->csr6 & Ttm))
+ return 10;
+ return 100;
+ }
+
+ return 0;
+}
+
+static int
+media(Ether* ether, int wait)
+{
+ Ctlr* ctlr;
+ int k, mbps;
+
+ ctlr = ether->ctlr;
+ for(k = 0; k < ctlr->k; k++){
+ switch(ctlr->id){
+ default:
+ mbps = mediaxx(ether, wait);
+ break;
+ case Tulip1: /* 21041 */
+ mbps = media21041(ether, wait);
+ break;
+ }
+ if(mbps > 0)
+ return mbps;
+ if(ctlr->curk == 0)
+ ctlr->curk = ctlr->k-1;
+ else
+ ctlr->curk--;
+ }
+
+ return 0;
+}
+
+static char* mediatable[9] = {
+ "10BASE-T", /* TP */
+ "10BASE-2", /* BNC */
+ "10BASE-5", /* AUI */
+ "100BASE-TX",
+ "10BASE-TFD",
+ "100BASE-TXFD",
+ "100BASE-T4",
+ "100BASE-FX",
+ "100BASE-FXFD",
+};
+
+static uchar en1207[] = { /* Accton EN1207-COMBO */
+ 0x00, 0x00, 0xE8, /* [0] vendor ethernet code */
+ 0x00, /* [3] spare */
+
+ 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */
+ 0x1F, /* [6] general purpose control */
+ 2, /* [7] block count */
+
+ 0x00, /* [8] media code (10BASE-TX) */
+ 0x0B, /* [9] general purpose port data */
+ 0x9E, 0x00, /* [10] command (LSB+MSB = 0x009E) */
+
+ 0x03, /* [8] media code (100BASE-TX) */
+ 0x1B, /* [9] general purpose port data */
+ 0x6D, 0x00, /* [10] command (LSB+MSB = 0x006D) */
+
+ /* There is 10BASE-2 as well, but... */
+};
+
+static uchar ana6910fx[] = { /* Adaptec (Cogent) ANA-6910FX */
+ 0x00, 0x00, 0x92, /* [0] vendor ethernet code */
+ 0x00, /* [3] spare */
+
+ 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */
+ 0x3F, /* [6] general purpose control */
+ 1, /* [7] block count */
+
+ 0x07, /* [8] media code (100BASE-FX) */
+ 0x03, /* [9] general purpose port data */
+ 0x2D, 0x00 /* [10] command (LSB+MSB = 0x000D) */
+};
+
+static uchar smc9332[] = { /* SMC 9332 */
+ 0x00, 0x00, 0xC0, /* [0] vendor ethernet code */
+ 0x00, /* [3] spare */
+
+ 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */
+ 0x1F, /* [6] general purpose control */
+ 2, /* [7] block count */
+
+ 0x00, /* [8] media code (10BASE-TX) */
+ 0x00, /* [9] general purpose port data */
+ 0x9E, 0x00, /* [10] command (LSB+MSB = 0x009E) */
+
+ 0x03, /* [8] media code (100BASE-TX) */
+ 0x09, /* [9] general purpose port data */
+ 0x6D, 0x00, /* [10] command (LSB+MSB = 0x006D) */
+};
+
+static uchar* leaf21140[] = {
+ en1207, /* Accton EN1207-COMBO */
+ ana6910fx, /* Adaptec (Cogent) ANA-6910FX */
+ smc9332, /* SMC 9332 */
+ nil,
+};
+
+/*
+ * Copied to ctlr->srom at offset 20.
+ */
+static uchar leafpnic[] = {
+ 0x00, 0x00, 0x00, 0x00, /* MAC address */
+ 0x00, 0x00,
+ 0x00, /* controller 0 device number */
+ 0x1E, 0x00, /* controller 0 info leaf offset */
+ 0x00, /* reserved */
+ 0x00, 0x08, /* selected connection type */
+ 0x00, /* general purpose control */
+ 0x01, /* block count */
+
+ 0x8C, /* format indicator and count */
+ 0x01, /* block type */
+ 0x00, /* PHY number */
+ 0x00, /* GPR sequence length */
+ 0x00, /* reset sequence length */
+ 0x00, 0x78, /* media capabilities */
+ 0xE0, 0x01, /* Nway advertisment */
+ 0x00, 0x50, /* FDX bitmap */
+ 0x00, 0x18, /* TTM bitmap */
+};
+
+static int
+srom(Ctlr* ctlr)
+{
+ int i, k, oui, phy, x;
+ uchar *p;
+
+ /*
+ * This is a partial decoding of the SROM format described in
+ * 'Digital Semiconductor 21X4 Serial ROM Format, Version 4.05,
+ * 2-Mar-98'. Only the 2114[03] are handled, support for other
+ * controllers can be added as needed.
+ * Do a dummy read first to get the size and allocate ctlr->srom.
+ */
+ sromr(ctlr, 0);
+ if(ctlr->srom == nil)
+ ctlr->srom = malloc((1<<ctlr->sromsz)*sizeof(ushort));
+ for(i = 0; i < (1<<ctlr->sromsz); i++){
+ x = sromr(ctlr, i);
+ ctlr->srom[2*i] = x;
+ ctlr->srom[2*i+1] = x>>8;
+ }
+
+ if(DEBUG){
+ print("srom:");
+ for(i = 0; i < ((1<<ctlr->sromsz)*sizeof(ushort)); i++){
+ if(i && ((i & 0x0F) == 0))
+ print("\n ");
+ print(" %2.2uX", ctlr->srom[i]);
+ }
+ print("\n");
+ }
+
+ /*
+ * There are at least 2 SROM layouts:
+ * e.g. Digital EtherWORKS station address at offset 20;
+ * this complies with the 21140A SROM
+ * application note from Digital;
+ * e.g. SMC9332 station address at offset 0 followed by
+ * 2 additional bytes, repeated at offset
+ * 6; the 8 bytes are also repeated in
+ * reverse order at offset 8.
+ * To check which it is, read the SROM and check for the repeating
+ * patterns of the non-compliant cards; if that fails use the one at
+ * offset 20.
+ */
+ ctlr->sromea = ctlr->srom;
+ for(i = 0; i < 8; i++){
+ x = ctlr->srom[i];
+ if(x != ctlr->srom[15-i] || x != ctlr->srom[16+i]){
+ ctlr->sromea = &ctlr->srom[20];
+ break;
+ }
+ }
+
+ /*
+ * Fake up the SROM for the PNIC and AMDtek.
+ * They look like a 21140 with a PHY.
+ * The MAC address is byte-swapped in the orginal
+ * PNIC SROM data.
+ */
+ if(ctlr->id == Pnic){
+ memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic));
+ for(i = 0; i < Eaddrlen; i += 2){
+ ctlr->srom[20+i] = ctlr->srom[i+1];
+ ctlr->srom[20+i+1] = ctlr->srom[i];
+ }
+ }
+ if(ctlr->id == CentaurP || ctlr->id == CentaurPcb){
+ memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic));
+ for(i = 0; i < Eaddrlen; i += 2){
+ ctlr->srom[20+i] = ctlr->srom[8+i];
+ ctlr->srom[20+i+1] = ctlr->srom[8+i+1];
+ }
+ }
+
+ /*
+ * Next, try to find the info leaf in the SROM for media detection.
+ * If it's a non-conforming card try to match the vendor ethernet code
+ * and point p at a fake info leaf with compact 21140 entries.
+ */
+ if(ctlr->sromea == ctlr->srom){
+ p = nil;
+ for(i = 0; leaf21140[i] != nil; i++){
+ if(memcmp(leaf21140[i], ctlr->sromea, 3) == 0){
+ p = &leaf21140[i][4];
+ break;
+ }
+ }
+ if(p == nil)
+ return -1;
+ }
+ else
+ p = &ctlr->srom[(ctlr->srom[28]<<8)|ctlr->srom[27]];
+
+ /*
+ * Set up the info needed for later media detection.
+ * For the 21140, set the general-purpose mask in CSR12.
+ * The info block entries are stored in order of increasing
+ * precedence, so detection will work backwards through the
+ * stored indexes into ctlr->srom.
+ * If an entry is found which matches the selected connection
+ * type, save the index. Otherwise, start at the last entry.
+ * If any MII entries are found (type 1 and 3 blocks), scan
+ * for PHYs.
+ */
+ ctlr->leaf = p;
+ ctlr->sct = *p++;
+ ctlr->sct |= *p++<<8;
+ if(ctlr->id != Tulip3 && ctlr->id != Tulip1){
+ csr32w(ctlr, 12, Gpc|*p++);
+ delay(200);
+ }
+ ctlr->k = *p++;
+ if(ctlr->k >= nelem(ctlr->infoblock))
+ ctlr->k = nelem(ctlr->infoblock)-1;
+ ctlr->sctk = ctlr->k-1;
+ phy = 0;
+ for(k = 0; k < ctlr->k; k++){
+ ctlr->infoblock[k] = p;
+ if(ctlr->id == Tulip1){
+ debug("type21041: 0x%2.2uX\n", p[0]);
+ if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
+ ctlr->sctk = k;
+ if(*p & 0x40)
+ p += 7;
+ else
+ p += 1;
+ }
+ /*
+ * The RAMIX PMC665 has a badly-coded SROM,
+ * hence the test for 21143 and type 3.
+ */
+ else if((*p & 0x80) || (ctlr->id == Tulip3 && *(p+1) == 3)){
+ *p |= 0x80;
+ if(*(p+1) == 1 || *(p+1) == 3)
+ phy = 1;
+ if(*(p+1) == 5)
+ ctlr->type5block = p;
+ p += (*p & ~0x80)+1;
+ }
+ else{
+ debug("type0: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
+ p[0], p[1], p[2], p[3]);
+ if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
+ ctlr->sctk = k;
+ p += 4;
+ }
+ }
+ ctlr->curk = ctlr->sctk;
+ debug("sct 0x%uX medium 0x%uX k %d curk %d phy %d\n",
+ ctlr->sct, ctlr->medium, ctlr->k, ctlr->curk, phy);
+
+ if(phy){
+ x = 0;
+ for(k = 0; k < nelem(ctlr->phy); k++){
+ if((ctlr->id == CentaurP || ctlr->id == CentaurPcb) && k != 1)
+ continue;
+ if((oui = miir(ctlr, k, 2)) == -1 || oui == 0)
+ continue;
+ debug("phy reg 2 %4.4uX\n", oui);
+ if(DEBUG){
+ oui = (oui & 0x3FF)<<6;
+ oui |= miir(ctlr, k, 3)>>10;
+ miir(ctlr, k, 1);
+ debug("phy%d: index %d oui %uX reg1 %uX\n",
+ x, k, oui, miir(ctlr, k, 1));
+ USED(oui);
+ }
+ ctlr->phy[x] = k;
+ }
+ }
+
+ ctlr->fd = 0;
+ ctlr->medium = -1;
+
+ return 0;
+}
+
+static void
+dec2114xpci(void)
+{
+ Ctlr *ctlr;
+ Pcidev *p;
+ int x;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+ switch((p->did<<16)|p->vid){
+ default:
+ continue;
+
+ case Tulip3: /* 21143 */
+ /*
+ * Exit sleep mode.
+ */
+ x = pcicfgr32(p, 0x40);
+ x &= ~0xC0000000;
+ pcicfgw32(p, 0x40, x);
+ /*FALLTHROUGH*/
+
+ case Tulip0: /* 21140 */
+ case Tulip1: /* 21041 */
+ case Pnic: /* PNIC */
+ case Pnic2: /* PNIC-II */
+ case CentaurP: /* ADMtek */
+ case CentaurPcb: /* ADMtek CardBus */
+ break;
+ }
+
+ /*
+ * bar[0] is the I/O port register address and
+ * bar[1] is the memory-mapped register address.
+ */
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = p->mem[0].bar & ~0x01;
+ ctlr->pcidev = p;
+ ctlr->id = (p->did<<16)|p->vid;
+
+ if(ioalloc(ctlr->port, p->mem[0].size, 0, "dec2114x") < 0){
+ print("dec2114x: port 0x%uX in use\n", ctlr->port);
+ free(ctlr);
+ continue;
+ }
+
+ /*
+ * Some cards (e.g. ANA-6910FX) seem to need the Ps bit
+ * set or they don't always work right after a hardware
+ * reset.
+ */
+ csr32w(ctlr, 6, Mbo|Ps);
+ softreset(ctlr);
+
+ if(srom(ctlr)){
+ iofree(ctlr->port);
+ free(ctlr);
+ continue;
+ }
+
+ switch(ctlr->id){
+ default:
+ break;
+ case Pnic: /* PNIC */
+ /*
+ * Turn off the jabber timer.
+ */
+ csr32w(ctlr, 15, 0x00000001);
+ break;
+ case CentaurP:
+ case CentaurPcb:
+ /*
+ * Nice - the register offsets change from *8 to *4
+ * for CSR16 and up...
+ * CSR25/26 give the MAC address read from the SROM.
+ * Don't really need to use this other than as a check,
+ * the SROM will be read in anyway so the value there
+ * can be used directly.
+ */
+ debug("csr25 %8.8luX csr26 %8.8luX\n",
+ inl(ctlr->port+0xA4), inl(ctlr->port+0xA8));
+ debug("phyidr1 %4.4luX phyidr2 %4.4luX\n",
+ inl(ctlr->port+0xBC), inl(ctlr->port+0xC0));
+ break;
+ }
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+}
+
+static int
+reset(Ether* ether)
+{
+ Ctlr *ctlr;
+ int i, x;
+ uchar ea[Eaddrlen];
+ static int scandone;
+
+ if(scandone == 0){
+ dec2114xpci();
+ scandone = 1;
+ }
+
+ /*
+ * Any adapter matches if no ether->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(ether->port == 0 || ether->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ ether->ctlr = ctlr;
+ ether->port = ctlr->port;
+ ether->irq = ctlr->pcidev->intl;
+ ether->tbdf = ctlr->pcidev->tbdf;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to
+ * loading the station address in the hardware.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0)
+ memmove(ether->ea, ctlr->sromea, Eaddrlen);
+
+ /*
+ * Look for a medium override in case there's no autonegotiation
+ * (no MII) or the autonegotiation fails.
+ */
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrcmp(ether->opt[i], "FD") == 0){
+ ctlr->fd = 1;
+ continue;
+ }
+ for(x = 0; x < nelem(mediatable); x++){
+ debug("compare <%s> <%s>\n", mediatable[x],
+ ether->opt[i]);
+ if(cistrcmp(mediatable[x], ether->opt[i]))
+ continue;
+ ctlr->medium = x;
+
+ switch(ctlr->medium){
+ default:
+ ctlr->fd = 0;
+ break;
+
+ case 0x04: /* 10BASE-TFD */
+ case 0x05: /* 100BASE-TXFD */
+ case 0x08: /* 100BASE-FXFD */
+ ctlr->fd = 1;
+ break;
+ }
+ break;
+ }
+ }
+
+ ether->mbps = media(ether, 1);
+
+ /*
+ * Initialise descriptor rings, ethernet address.
+ */
+ ctlr->nrdr = Nrde;
+ ctlr->ntdr = Ntde;
+ pcisetbme(ctlr->pcidev);
+ ctlrinit(ether);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->ifstat = ifstat;
+
+ ether->arg = ether;
+ ether->shutdown = shutdown;
+ ether->multicast = multicast;
+ ether->promiscuous = promiscuous;
+
+ return 0;
+}
+
+void
+ether2114xlink(void)
+{
+ addethercard("2114x", reset);
+ addethercard("21140", reset);
+}
diff --git a/sys/src/9/pc/ether589.c b/sys/src/9/pc/ether589.c
new file mode 100755
index 000000000..4cc03fd69
--- /dev/null
+++ b/sys/src/9/pc/ether589.c
@@ -0,0 +1,215 @@
+/*
+ * 3C589 and 3C562.
+ * To do:
+ * check xcvr10Base2 still works (is GlobalReset necessary?).
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+enum { /* all windows */
+ CommandR = 0x000E,
+ IntStatusR = 0x000E,
+};
+
+enum { /* Commands */
+ GlobalReset = 0x0000,
+ SelectRegisterWindow = 0x0001,
+ RxReset = 0x0005,
+ TxReset = 0x000B,
+ AcknowledgeInterrupt = 0x000D,
+};
+
+enum { /* IntStatus bits */
+ commandInProgress = 0x1000,
+};
+
+#define COMMAND(port, cmd, a) outs((port)+CommandR, ((cmd)<<11)|(a))
+#define STATUS(port) ins((port)+IntStatusR)
+
+enum { /* Window 0 - setup */
+ Wsetup = 0x0000,
+ /* registers */
+ ManufacturerID = 0x0000, /* 3C5[08]*, 3C59[27] */
+ ProductID = 0x0002, /* 3C5[08]*, 3C59[27] */
+ ConfigControl = 0x0004, /* 3C5[08]*, 3C59[27] */
+ AddressConfig = 0x0006, /* 3C5[08]*, 3C59[27] */
+ ResourceConfig = 0x0008, /* 3C5[08]*, 3C59[27] */
+ EepromCommand = 0x000A,
+ EepromData = 0x000C,
+ /* AddressConfig Bits */
+ autoSelect9 = 0x0080,
+ xcvrMask9 = 0xC000,
+ /* ConfigControl bits */
+ Ena = 0x0001,
+ base10TAvailable9 = 0x0200,
+ coaxAvailable9 = 0x1000,
+ auiAvailable9 = 0x2000,
+ /* EepromCommand bits */
+ EepromReadRegister = 0x0080,
+ EepromBusy = 0x8000,
+};
+
+enum { /* Window 1 - operating set */
+ Wop = 0x0001,
+};
+
+enum { /* Window 3 - FIFO management */
+ Wfifo = 0x0003,
+ /* registers */
+ InternalConfig = 0x0000, /* 3C509B, 3C589, 3C59[0257] */
+ /* InternalConfig bits */
+ xcvr10BaseT = 0x00000000,
+ xcvr10Base2 = 0x00300000,
+};
+
+enum { /* Window 4 - diagnostic */
+ Wdiagnostic = 0x0004,
+ /* registers */
+ MediaStatus = 0x000A,
+ /* MediaStatus bits */
+ linkBeatDetect = 0x0800,
+};
+
+extern int etherelnk3reset(Ether*);
+
+static char *tcmpcmcia[] = {
+ "3C589", /* 3COM 589[ABCD] */
+ "3C562", /* 3COM 562 */
+ "589E", /* 3COM Megahertz 589E */
+ nil,
+};
+
+static int
+configASIC(Ether* ether, int port, int xcvr)
+{
+ int x;
+
+ /* set Window 0 configuration registers */
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ outs(port+ConfigControl, Ena);
+
+ /* IRQ must be 3 on 3C589/3C562 */
+ outs(port + ResourceConfig, 0x3F00);
+
+ x = ins(port+AddressConfig) & ~xcvrMask9;
+ x |= (xcvr>>20)<<14;
+ outs(port+AddressConfig, x);
+
+ COMMAND(port, TxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, RxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+
+ return etherelnk3reset(ether);
+}
+
+static int
+reset(Ether* ether)
+{
+ int i, t, slot;
+ char *type;
+ int port;
+ enum { WantAny, Want10BT, Want10B2 };
+ int want;
+ uchar ea[6];
+ char *p;
+
+ if(ether->irq == 0)
+ ether->irq = 10;
+ if(ether->port == 0)
+ ether->port = 0x240;
+ port = ether->port;
+
+ if(ioalloc(port, 0x10, 0, "3C589") < 0)
+ return -1;
+
+ type = nil;
+ slot = -1;
+ for(i = 0; tcmpcmcia[i] != nil; i++){
+ type = tcmpcmcia[i];
+ if((slot = pcmspecial(type, ether)) >= 0)
+ break;
+ }
+ ether->type = type; /* must be set before calling configASIC */
+ if(slot < 0){
+ iofree(port);
+ return -1;
+ }
+
+ /*
+ * Read Ethernet address from card memory
+ * on 3C562, but only if the user has not
+ * overridden it.
+ */
+ memset(ea, 0, sizeof ea);
+ if(memcmp(ea, ether->ea, 6) == 0 && strcmp(type, "3C562") == 0) {
+ if(pcmcistuple(slot, 0x88, -1, ea, 6) == 6) {
+ for(i = 0; i < 6; i += 2){
+ t = ea[i];
+ ea[i] = ea[i+1];
+ ea[i+1] = t;
+ }
+ memmove(ether->ea, ea, 6);
+ }
+ }
+ /*
+ * Allow user to specify desired media in plan9.ini
+ */
+ want = WantAny;
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrncmp(ether->opt[i], "media=", 6) != 0)
+ continue;
+ p = ether->opt[i]+6;
+ if(cistrcmp(p, "10base2") == 0)
+ want = Want10B2;
+ else if(cistrcmp(p, "10baseT") == 0)
+ want = Want10BT;
+ }
+
+ /* try configuring as a 10BaseT */
+ if(want==WantAny || want==Want10BT){
+ if(configASIC(ether, port, xcvr10BaseT) < 0){
+ pcmspecialclose(slot);
+ iofree(port);
+ return -1;
+ }
+ delay(100);
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ if((ins(port+MediaStatus)&linkBeatDetect) || want==Want10BT){
+ COMMAND(port, SelectRegisterWindow, Wop);
+ print("#l%d: xcvr10BaseT %s\n", ether->ctlrno, type);
+ return 0;
+ }
+ }
+
+ /* try configuring as a 10base2 */
+ if(want==WantAny || want==Want10B2){
+ COMMAND(port, GlobalReset, 0);
+ if(configASIC(ether, port, xcvr10Base2) < 0){
+ pcmspecialclose(slot);
+ iofree(port);
+ return -1;
+ }
+ print("#l%d: xcvr10Base2 %s\n", ether->ctlrno, type);
+ return 0;
+ }
+ return -1; /* not reached */
+}
+
+void
+ether589link(void)
+{
+ addethercard("3C589", reset);
+ addethercard("3C562", reset);
+ addethercard("589E", reset);
+}
diff --git a/sys/src/9/pc/ether79c970.c b/sys/src/9/pc/ether79c970.c
new file mode 100755
index 000000000..5e682847d
--- /dev/null
+++ b/sys/src/9/pc/ether79c970.c
@@ -0,0 +1,646 @@
+/*
+ * AMD79C970
+ * PCnet-PCI Single-Chip Ethernet Controller for PCI Local Bus
+ * To do:
+ * finish this rewrite
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+enum {
+ Lognrdre = 6,
+ Nrdre = (1<<Lognrdre),/* receive descriptor ring entries */
+ Logntdre = 4,
+ Ntdre = (1<<Logntdre),/* transmit descriptor ring entries */
+
+ Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
+};
+
+enum { /* DWIO I/O resource map */
+ Aprom = 0x0000, /* physical address */
+ Rdp = 0x0010, /* register data port */
+ Rap = 0x0014, /* register address port */
+ Sreset = 0x0018, /* software reset */
+ Bdp = 0x001C, /* bus configuration register data port */
+};
+
+enum { /* CSR0 */
+ Init = 0x0001, /* begin initialisation */
+ Strt = 0x0002, /* enable chip */
+ Stop = 0x0004, /* disable chip */
+ Tdmd = 0x0008, /* transmit demand */
+ Txon = 0x0010, /* transmitter on */
+ Rxon = 0x0020, /* receiver on */
+ Iena = 0x0040, /* interrupt enable */
+ Intr = 0x0080, /* interrupt flag */
+ Idon = 0x0100, /* initialisation done */
+ Tint = 0x0200, /* transmit interrupt */
+ Rint = 0x0400, /* receive interrupt */
+ Merr = 0x0800, /* memory error */
+ Miss = 0x1000, /* missed frame */
+ Cerr = 0x2000, /* collision */
+ Babl = 0x4000, /* transmitter timeout */
+ Err = 0x8000, /* Babl|Cerr|Miss|Merr */
+};
+
+enum { /* CSR3 */
+ Bswp = 0x0004, /* byte swap */
+ Emba = 0x0008, /* enable modified back-off algorithm */
+ Dxmt2pd = 0x0010, /* disable transmit two part deferral */
+ Lappen = 0x0020, /* look-ahead packet processing enable */
+};
+
+enum { /* CSR4 */
+ ApadXmt = 0x0800, /* auto pad transmit */
+};
+
+enum { /* CSR15 */
+ Prom = 0x8000, /* promiscuous mode */
+};
+
+typedef struct Iblock Iblock;
+struct Iblock { /* Initialisation Block */
+ ushort mode;
+ uchar rlen; /* upper 4 bits */
+ uchar tlen; /* upper 4 bits */
+ uchar padr[6];
+ uchar res[2];
+ uchar ladr[8];
+ ulong rdra;
+ ulong tdra;
+};
+
+typedef struct Dre Dre;
+struct Dre { /* descriptor ring entry */
+ ulong addr;
+ ulong md1; /* status|bcnt */
+ ulong md2; /* rcc|rpc|mcnt */
+ Block* bp;
+};
+
+enum { /* md1 */
+ Enp = 0x01000000, /* end of packet */
+ Stp = 0x02000000, /* start of packet */
+ RxBuff = 0x04000000, /* buffer error */
+ Def = 0x04000000, /* deferred */
+ Crc = 0x08000000, /* CRC error */
+ One = 0x08000000, /* one retry needed */
+ Oflo = 0x10000000, /* overflow error */
+ More = 0x10000000, /* more than one retry needed */
+ Fram = 0x20000000, /* framing error */
+ RxErr = 0x40000000, /* Fram|Oflo|Crc|RxBuff */
+ TxErr = 0x40000000, /* Uflo|Lcol|Lcar|Rtry */
+ Own = 0x80000000,
+};
+
+enum { /* md2 */
+ Rtry = 0x04000000, /* failed after repeated retries */
+ Lcar = 0x08000000, /* loss of carrier */
+ Lcol = 0x10000000, /* late collision */
+ Uflo = 0x40000000, /* underflow error */
+ TxBuff = 0x80000000, /* buffer error */
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ Lock;
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+
+ int init; /* initialisation in progress */
+ Iblock iblock;
+
+ Dre* rdr; /* receive descriptor ring */
+ int rdrx;
+
+ Dre* tdr; /* transmit descriptor ring */
+ int tdrh; /* host index into tdr */
+ int tdri; /* interface index into tdr */
+ int ntq; /* descriptors active */
+
+ ulong rxbuff; /* receive statistics */
+ ulong crc;
+ ulong oflo;
+ ulong fram;
+
+ ulong rtry; /* transmit statistics */
+ ulong lcar;
+ ulong lcol;
+ ulong uflo;
+ ulong txbuff;
+
+ ulong merr; /* bobf is such a whiner */
+ ulong miss;
+ ulong babl;
+
+ int (*ior)(Ctlr*, int);
+ void (*iow)(Ctlr*, int, int);
+};
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+/*
+ * The Rdp, Rap, Sreset, Bdp ports are 32-bit port offset in the enumeration above.
+ * To get to 16-bit offsets, scale down with 0x10 staying the same.
+ */
+static int
+io16r(Ctlr *c, int r)
+{
+ if(r >= Rdp)
+ r = (r-Rdp)/2+Rdp;
+ return ins(c->port+r);
+}
+
+static void
+io16w(Ctlr *c, int r, int v)
+{
+ if(r >= Rdp)
+ r = (r-Rdp)/2+Rdp;
+ outs(c->port+r, v);
+}
+
+static int
+io32r(Ctlr *c, int r)
+{
+ return inl(c->port+r);
+}
+
+static void
+io32w(Ctlr *c, int r, int v)
+{
+ outl(c->port+r, v);
+}
+
+static void
+attach(Ether*)
+{
+}
+
+static long
+ifstat(Ether* ether, void* a, long n, ulong offset)
+{
+ char *p;
+ int len;
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+
+ ether->crcs = ctlr->crc;
+ ether->frames = ctlr->fram;
+ ether->buffs = ctlr->rxbuff+ctlr->txbuff;
+ ether->overflows = ctlr->oflo;
+
+ if(n == 0)
+ return 0;
+
+ p = malloc(READSTR);
+ len = snprint(p, READSTR, "Rxbuff: %ld\n", ctlr->rxbuff);
+ len += snprint(p+len, READSTR-len, "Crc: %ld\n", ctlr->crc);
+ len += snprint(p+len, READSTR-len, "Oflo: %ld\n", ctlr->oflo);
+ len += snprint(p+len, READSTR-len, "Fram: %ld\n", ctlr->fram);
+ len += snprint(p+len, READSTR-len, "Rtry: %ld\n", ctlr->rtry);
+ len += snprint(p+len, READSTR-len, "Lcar: %ld\n", ctlr->lcar);
+ len += snprint(p+len, READSTR-len, "Lcol: %ld\n", ctlr->lcol);
+ len += snprint(p+len, READSTR-len, "Uflo: %ld\n", ctlr->uflo);
+ len += snprint(p+len, READSTR-len, "Txbuff: %ld\n", ctlr->txbuff);
+ len += snprint(p+len, READSTR-len, "Merr: %ld\n", ctlr->merr);
+ len += snprint(p+len, READSTR-len, "Miss: %ld\n", ctlr->miss);
+ snprint(p+len, READSTR-len, "Babl: %ld\n", ctlr->babl);
+
+ n = readstr(offset, a, n, p);
+ free(p);
+
+ return n;
+}
+
+static void
+ringinit(Ctlr* ctlr)
+{
+ Dre *dre;
+
+ /*
+ * Initialise the receive and transmit buffer rings.
+ * The ring entries must be aligned on 16-byte boundaries.
+ *
+ * This routine is protected by ctlr->init.
+ */
+ if(ctlr->rdr == 0){
+ ctlr->rdr = xspanalloc(Nrdre*sizeof(Dre), 0x10, 0);
+ for(dre = ctlr->rdr; dre < &ctlr->rdr[Nrdre]; dre++){
+ dre->bp = iallocb(Rbsize);
+ if(dre->bp == nil)
+ panic("can't allocate ethernet receive ring\n");
+ dre->addr = PADDR(dre->bp->rp);
+ dre->md2 = 0;
+ dre->md1 = Own|(-Rbsize & 0xFFFF);
+ }
+ }
+ ctlr->rdrx = 0;
+
+ if(ctlr->tdr == 0)
+ ctlr->tdr = xspanalloc(Ntdre*sizeof(Dre), 0x10, 0);
+ memset(ctlr->tdr, 0, Ntdre*sizeof(Dre));
+ ctlr->tdrh = ctlr->tdri = 0;
+}
+
+static void
+promiscuous(void* arg, int on)
+{
+ Ether *ether;
+ int x;
+ Ctlr *ctlr;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+
+ /*
+ * Put the chip into promiscuous mode. First must wait until
+ * anyone transmitting is done, then stop the chip and put
+ * it in promiscuous mode. Restarting is made harder by the chip
+ * reloading the transmit and receive descriptor pointers with their
+ * base addresses when Strt is set (unlike the older Lance chip),
+ * so the rings must be re-initialised.
+ */
+ ilock(ctlr);
+ if(ctlr->init){
+ iunlock(ctlr);
+ return;
+ }
+ ctlr->init = 1;
+ iunlock(ctlr);
+
+ while(ctlr->ntq)
+ ;
+
+ ctlr->iow(ctlr, Rdp, Stop);
+
+ ctlr->iow(ctlr, Rap, 15);
+ x = ctlr->ior(ctlr, Rdp) & ~Prom;
+ if(on)
+ x |= Prom;
+ ctlr->iow(ctlr, Rdp, x);
+ ctlr->iow(ctlr, Rap, 0);
+
+ ringinit(ctlr);
+
+ ilock(ctlr);
+ ctlr->init = 0;
+ ctlr->iow(ctlr, Rdp, Iena|Strt);
+ iunlock(ctlr);
+}
+
+static void
+multicast(void* arg, uchar*, int)
+{
+ promiscuous(arg, 1);
+}
+
+static void
+txstart(Ether* ether)
+{
+ Ctlr *ctlr;
+ Block *bp;
+ Dre *dre;
+
+ ctlr = ether->ctlr;
+
+ if(ctlr->init)
+ return;
+
+ while(ctlr->ntq < (Ntdre-1)){
+ bp = qget(ether->oq);
+ if(bp == nil)
+ break;
+
+ /*
+ * Give ownership of the descriptor to the chip,
+ * increment the software ring descriptor pointer
+ * and tell the chip to poll.
+ * There's no need to pad to ETHERMINTU
+ * here as ApadXmt is set in CSR4.
+ */
+ dre = &ctlr->tdr[ctlr->tdrh];
+ dre->bp = bp;
+ dre->addr = PADDR(bp->rp);
+ dre->md2 = 0;
+ dre->md1 = Own|Stp|Enp|(-BLEN(bp) & 0xFFFF);
+ ctlr->ntq++;
+ ctlr->iow(ctlr, Rdp, Iena|Tdmd);
+ ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
+ }
+}
+
+static void
+transmit(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(ctlr);
+ txstart(ether);
+ iunlock(ctlr);
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Ether *ether;
+ int csr0, len;
+ Dre *dre;
+ Block *bp;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+
+ /*
+ * Acknowledge all interrupts and whine about those that shouldn't
+ * happen.
+ */
+intrloop:
+ csr0 = ctlr->ior(ctlr, Rdp) & 0xFFFF;
+ ctlr->iow(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena);
+ if(csr0 & Merr)
+ ctlr->merr++;
+ if(csr0 & Miss)
+ ctlr->miss++;
+ if(csr0 & Babl)
+ ctlr->babl++;
+ //if(csr0 & (Babl|Miss|Merr))
+ // print("#l%d: csr0 = 0x%uX\n", ether->ctlrno, csr0);
+ if(!(csr0 & (Rint|Tint)))
+ return;
+
+ /*
+ * Receiver interrupt: run round the descriptor ring logging
+ * errors and passing valid receive data up to the higher levels
+ * until a descriptor is encountered still owned by the chip.
+ */
+ if(csr0 & Rint){
+ dre = &ctlr->rdr[ctlr->rdrx];
+ while(!(dre->md1 & Own)){
+ if(dre->md1 & RxErr){
+ if(dre->md1 & RxBuff)
+ ctlr->rxbuff++;
+ if(dre->md1 & Crc)
+ ctlr->crc++;
+ if(dre->md1 & Oflo)
+ ctlr->oflo++;
+ if(dre->md1 & Fram)
+ ctlr->fram++;
+ }
+ else if(bp = iallocb(Rbsize)){
+ len = (dre->md2 & 0x0FFF)-4;
+ dre->bp->wp = dre->bp->rp+len;
+ etheriq(ether, dre->bp, 1);
+ dre->bp = bp;
+ dre->addr = PADDR(bp->rp);
+ }
+
+ /*
+ * Finished with this descriptor, reinitialise it,
+ * give it back to the chip, then on to the next...
+ */
+ dre->md2 = 0;
+ dre->md1 = Own|(-Rbsize & 0xFFFF);
+
+ ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
+ dre = &ctlr->rdr[ctlr->rdrx];
+ }
+ }
+
+ /*
+ * Transmitter interrupt: wakeup anyone waiting for a free descriptor.
+ */
+ if(csr0 & Tint){
+ lock(ctlr);
+ while(ctlr->ntq){
+ dre = &ctlr->tdr[ctlr->tdri];
+ if(dre->md1 & Own)
+ break;
+
+ if(dre->md1 & TxErr){
+ if(dre->md2 & Rtry)
+ ctlr->rtry++;
+ if(dre->md2 & Lcar)
+ ctlr->lcar++;
+ if(dre->md2 & Lcol)
+ ctlr->lcol++;
+ if(dre->md2 & Uflo)
+ ctlr->uflo++;
+ if(dre->md2 & TxBuff)
+ ctlr->txbuff++;
+ ether->oerrs++;
+ }
+
+ freeb(dre->bp);
+
+ ctlr->ntq--;
+ ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
+ }
+ txstart(ether);
+ unlock(ctlr);
+ }
+ goto intrloop;
+}
+
+static void
+amd79c970pci(void)
+{
+ int port;
+ Ctlr *ctlr;
+ Pcidev *p;
+
+ p = nil;
+ while(p = pcimatch(p, 0x1022, 0x2000)){
+ port = p->mem[0].bar & ~0x01;
+ if(ioalloc(port, p->mem[0].size, 0, "amd79c970") < 0){
+ print("amd79c970: port 0x%uX in use\n", port);
+ continue;
+ }
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = p->mem[0].bar & ~0x01;
+ ctlr->pcidev = p;
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+}
+
+static int
+reset(Ether* ether)
+{
+ int x;
+ uchar ea[Eaddrlen];
+ Ctlr *ctlr;
+
+ if(ctlrhead == nil)
+ amd79c970pci();
+
+ /*
+ * Any adapter matches if no port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(ether->port == 0 || ether->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ /*
+ * Allocate a controller structure and start to initialise it.
+ */
+ ether->ctlr = ctlr;
+ ether->port = ctlr->port;
+ ether->irq = ctlr->pcidev->intl;
+ ether->tbdf = ctlr->pcidev->tbdf;
+ pcisetbme(ctlr->pcidev);
+ ilock(ctlr);
+ ctlr->init = 1;
+
+ io32r(ctlr, Sreset);
+ io16r(ctlr, Sreset);
+
+ if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){
+ ctlr->ior = io16r;
+ ctlr->iow = io16w;
+ }else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){
+ ctlr->ior = io32r;
+ ctlr->iow = io32w;
+ }else{
+ print("#l%d: card doesn't talk right\n", ether->ctlrno);
+ iunlock(ctlr);
+ return -1;
+ }
+
+ ctlr->iow(ctlr, Rap, 88);
+ x = ctlr->ior(ctlr, Rdp);
+ ctlr->iow(ctlr, Rap, 89);
+ x |= ctlr->ior(ctlr, Rdp)<<16;
+
+ switch(x&0xFFFFFFF){
+ case 0x2420003: /* PCnet/PCI 79C970 */
+ case 0x2621003: /* PCnet/PCI II 79C970A */
+ case 0x2625003: /* PCnet-FAST III 79C973 */
+ break;
+ default:
+ print("#l%d: unknown PCnet card version 0x%.7ux\n",
+ ether->ctlrno, x&0xFFFFFFF);
+ iunlock(ctlr);
+ return -1;
+ }
+
+ /*
+ * Set the software style in BCR20 to be PCnet-PCI to ensure 32-bit access.
+ * Set the auto pad transmit in CSR4.
+ */
+ ctlr->iow(ctlr, Rap, 20);
+ ctlr->iow(ctlr, Bdp, 0x0002);
+
+ ctlr->iow(ctlr, Rap, 4);
+ x = ctlr->ior(ctlr, Rdp) & 0xFFFF;
+ ctlr->iow(ctlr, Rdp, ApadXmt|x);
+
+ ctlr->iow(ctlr, Rap, 0);
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the I/O-space and set in ether->ea prior to
+ * loading the station address in the initialisation block.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(!memcmp(ea, ether->ea, Eaddrlen)){
+ x = ctlr->ior(ctlr, Aprom);
+ ether->ea[0] = x;
+ ether->ea[1] = x>>8;
+ if(ctlr->ior == io16r)
+ x = ctlr->ior(ctlr, Aprom+2);
+ else
+ x >>= 16;
+ ether->ea[2] = x;
+ ether->ea[3] = x>>8;
+ x = ctlr->ior(ctlr, Aprom+4);
+ ether->ea[4] = x;
+ ether->ea[5] = x>>8;
+ }
+
+ /*
+ * Start to fill in the initialisation block
+ * (must be DWORD aligned).
+ */
+ ctlr->iblock.rlen = Lognrdre<<4;
+ ctlr->iblock.tlen = Logntdre<<4;
+ memmove(ctlr->iblock.padr, ether->ea, sizeof(ctlr->iblock.padr));
+
+ ringinit(ctlr);
+ ctlr->iblock.rdra = PADDR(ctlr->rdr);
+ ctlr->iblock.tdra = PADDR(ctlr->tdr);
+
+ /*
+ * Point the chip at the initialisation block and tell it to go.
+ * Mask the Idon interrupt and poll for completion. Strt and interrupt
+ * enables will be set later when attaching to the network.
+ */
+ x = PADDR(&ctlr->iblock);
+ ctlr->iow(ctlr, Rap, 1);
+ ctlr->iow(ctlr, Rdp, x & 0xFFFF);
+ ctlr->iow(ctlr, Rap, 2);
+ ctlr->iow(ctlr, Rdp, (x>>16) & 0xFFFF);
+ ctlr->iow(ctlr, Rap, 3);
+ ctlr->iow(ctlr, Rdp, Idon);
+ ctlr->iow(ctlr, Rap, 0);
+ ctlr->iow(ctlr, Rdp, Init);
+
+ while(!(ctlr->ior(ctlr, Rdp) & Idon))
+ ;
+
+ /*
+ * We used to set CSR0 to Idon|Stop here, and then
+ * in attach change it to Iena|Strt. Apparently the simulated
+ * 79C970 in VMware never enables after a write of Idon|Stop,
+ * so we enable the device here now.
+ */
+ ctlr->iow(ctlr, Rdp, Iena|Strt);
+ ctlr->init = 0;
+ iunlock(ctlr);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->ifstat = ifstat;
+
+ ether->arg = ether;
+ ether->promiscuous = promiscuous;
+ ether->multicast = multicast;
+// ether->shutdown = shutdown;
+
+ return 0;
+}
+
+void
+ether79c970link(void)
+{
+ addethercard("AMD79C970", reset);
+}
diff --git a/sys/src/9/pc/ether8003.c b/sys/src/9/pc/ether8003.c
new file mode 100755
index 000000000..41244c094
--- /dev/null
+++ b/sys/src/9/pc/ether8003.c
@@ -0,0 +1,271 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "ether8390.h"
+
+/*
+ * Western Digital/Standard Microsystems Corporation cards (WD80[01]3).
+ * Also handles 8216 cards (Elite Ultra).
+ * Configuration code based on that provided by SMC a long time ago.
+ */
+enum { /* 83C584 Bus Interface Controller */
+ Msr = 0x00, /* Memory Select Register */
+ Icr = 0x01, /* Interface Configuration Register */
+ Iar = 0x02, /* I/O Address Register */
+ Bio = 0x03, /* BIOS ROM Address Register */
+ Ear = 0x03, /* EEROM Address Register (shared with Bio) */
+ Irr = 0x04, /* Interrupt Request Register */
+ Hcr = 0x04, /* 8216 hardware control */
+ Laar = 0x05, /* LA Address Register */
+ Ijr = 0x06, /* Initialisation Jumpers */
+ Gp2 = 0x07, /* General Purpose Data Register */
+ Lar = 0x08, /* LAN Address Registers */
+ Id = 0x0E, /* Card ID byte */
+ Cksum = 0x0F, /* Checksum */
+};
+
+enum { /* Msr */
+ Rst = 0x80, /* software reset */
+ Menb = 0x40, /* memory enable */
+};
+
+enum { /* Icr */
+ Bit16 = 0x01, /* 16-bit bus */
+ Other = 0x02, /* other register access */
+ Ir2 = 0x04, /* IR2 */
+ Msz = 0x08, /* SRAM size */
+ Rla = 0x10, /* recall LAN address */
+ Rx7 = 0x20, /* recall all but I/O and LAN address */
+ Rio = 0x40, /* recall I/O address from EEROM */
+ Sto = 0x80, /* non-volatile EEROM store */
+};
+
+enum { /* Laar */
+ ZeroWS16 = 0x20, /* zero wait states for 16-bit ops */
+ L16en = 0x40, /* enable 16-bit LAN operation */
+ M16en = 0x80, /* enable 16-bit memory access */
+};
+
+enum { /* Ijr */
+ Ienable = 0x01, /* 8216 interrupt enable */
+};
+
+/*
+ * Mapping from configuration bits to interrupt level.
+ */
+static int irq8003[8] = {
+ 9, 3, 5, 7, 10, 11, 15, 4,
+};
+
+static int irq8216[8] = {
+ 0, 9, 3, 5, 7, 10, 11, 15,
+};
+
+static void
+reset8003(Ether* ether, uchar ea[Eaddrlen], uchar ic[8])
+{
+ Dp8390 *ctlr;
+ ulong port;
+
+ ctlr = ether->ctlr;
+ port = ether->port;
+
+ /*
+ * Check for old, dumb 8003E, which doesn't have an interface
+ * chip. Only Msr exists out of the 1st eight registers, reads
+ * of the others just alias the 2nd eight registers, the LAN
+ * address ROM. Can check Icr, Irr and Laar against the ethernet
+ * address read above and if they match it's an 8003E (or an
+ * 8003EBT, 8003S, 8003SH or 8003WT, doesn't matter), in which
+ * case the default irq gets used.
+ */
+ if(memcmp(&ea[1], &ic[1], 5) == 0){
+ memset(ic, 0, sizeof(ic));
+ ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
+ }
+ else{
+ /*
+ * As a final sanity check for the 8013EBT, which doesn't have
+ * the 83C584 interface chip, but has 2 real registers, write Gp2
+ * and if it reads back the same, it's not an 8013EBT.
+ */
+ outb(port+Gp2, 0xAA);
+ inb(port+Msr); /* wiggle bus */
+ if(inb(port+Gp2) != 0xAA){
+ memset(ic, 0, sizeof(ic));
+ ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
+ }
+ else
+ ether->irq = irq8003[((ic[Irr]>>5) & 0x3)|(ic[Icr] & 0x4)];
+
+ /*
+ * Check if 16-bit card.
+ * If Bit16 is read/write, then it's an 8-bit card.
+ * If Bit16 is set, it's in a 16-bit slot.
+ */
+ outb(port+Icr, ic[Icr]^Bit16);
+ inb(port+Msr); /* wiggle bus */
+ if((inb(port+Icr) & Bit16) == (ic[Icr] & Bit16)){
+ ctlr->width = 2;
+ ic[Icr] &= ~Bit16;
+ }
+ outb(port+Icr, ic[Icr]);
+
+ if(ctlr->width == 2 && (inb(port+Icr) & Bit16) == 0)
+ ctlr->width = 1;
+ }
+
+ ether->mem = (ulong)KADDR((ic[Msr] & 0x3F)<<13);
+ if(ctlr->width == 2)
+ ether->mem |= (ic[Laar] & 0x1F)<<19;
+ else
+ ether->mem |= 0x80000;
+
+ if(ic[Icr] & (1<<3))
+ ether->size = 32*1024;
+ if(ctlr->width == 2)
+ ether->size <<= 1;
+
+ /*
+ * Enable interface RAM, set interface width.
+ */
+ outb(port+Msr, ic[Msr]|Menb);
+ if(ctlr->width == 2)
+ outb(port+Laar, ic[Laar]|L16en|M16en|ZeroWS16);
+}
+
+static void
+reset8216(Ether* ether, uchar[8])
+{
+ uchar hcr, irq, x;
+ ulong addr, port;
+ Dp8390 *ctlr;
+
+ ctlr = ether->ctlr;
+ port = ether->port;
+
+ ctlr->width = 2;
+
+ /*
+ * Switch to the alternate register set and retrieve the memory
+ * and irq information.
+ */
+ hcr = inb(port+Hcr);
+ outb(port+Hcr, 0x80|hcr);
+ addr = inb(port+0x0B) & 0xFF;
+ irq = inb(port+0x0D);
+ outb(port+Hcr, hcr);
+
+ ether->mem = (ulong)KADDR(0xC0000+((((addr>>2) & 0x30)|(addr & 0x0F))<<13));
+ ether->size = 8192*(1<<((addr>>4) & 0x03));
+ ether->irq = irq8216[((irq>>4) & 0x04)|((irq>>2) & 0x03)];
+
+ /*
+ * Enable interface RAM, set interface width, and enable interrupts.
+ */
+ x = inb(port+Msr) & ~Rst;
+ outb(port+Msr, Menb|x);
+ x = inb(port+Laar);
+ outb(port+Laar, M16en|x);
+ outb(port+Ijr, Ienable);
+}
+
+/*
+ * Get configuration parameters, enable memory.
+ * There are opportunities here for buckets of code, try to resist.
+ */
+static int
+reset(Ether* ether)
+{
+ int i;
+ uchar ea[Eaddrlen], ic[8], id, nullea[Eaddrlen], sum;
+ ulong port;
+ Dp8390 *ctlr;
+
+ /*
+ * Set up the software configuration.
+ * Use defaults for port, irq, mem and size if not specified.
+ * Defaults are set for the dumb 8003E which can't be
+ * autoconfigured.
+ */
+ if(ether->port == 0)
+ ether->port = 0x280;
+ if(ether->irq == 0)
+ ether->irq = 3;
+ if(ether->mem == 0)
+ ether->mem = 0xD0000;
+ if(ether->size == 0)
+ ether->size = 8*1024;
+ if(ioalloc(ether->port, 0x20, 0, "wd8003") < 0)
+ return -1;
+
+ /*
+ * Look for the interface. Read the LAN address ROM
+ * and validate the checksum - the sum of all 8 bytes
+ * should be 0xFF.
+ * At the same time, get the (possible) interface chip
+ * registers, they'll be used later to check for aliasing.
+ */
+ port = ether->port;
+ sum = 0;
+ for(i = 0; i < sizeof(ea); i++){
+ ea[i] = inb(port+Lar+i);
+ sum += ea[i];
+ ic[i] = inb(port+i);
+ }
+ id = inb(port+Id);
+ sum += id;
+ sum += inb(port+Cksum);
+ if(sum != 0xFF){
+ iofree(ether->port);
+ return -1;
+ }
+
+ ether->ctlr = malloc(sizeof(Dp8390));
+ ctlr = ether->ctlr;
+ ctlr->ram = 1;
+
+ if((id & 0xFE) == 0x2A)
+ reset8216(ether, ic);
+ else
+ reset8003(ether, ea, ic);
+
+ /*
+ * Set the DP8390 ring addresses.
+ */
+ ctlr->port = port+0x10;
+ ctlr->tstart = 0;
+ ctlr->pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
+ ctlr->pstop = HOWMANY(ether->size, Dp8390BufSz);
+
+ /*
+ * Finally, init the 8390, set the ethernet address
+ * and claim the memory used.
+ */
+ dp8390reset(ether);
+ memset(nullea, 0, Eaddrlen);
+ if(memcmp(nullea, ether->ea, Eaddrlen) == 0){
+ for(i = 0; i < sizeof(ether->ea); i++)
+ ether->ea[i] = ea[i];
+ }
+ dp8390setea(ether);
+
+ if(umbrwmalloc(PADDR(ether->mem), ether->size, 0) == 0)
+ print("ether8003: warning - 0x%luX unavailable\n",
+ PADDR(ether->mem));
+
+ return 0;
+}
+
+void
+ether8003link(void)
+{
+ addethercard("WD8003", reset);
+}
diff --git a/sys/src/9/pc/ether8139.c b/sys/src/9/pc/ether8139.c
new file mode 100755
index 000000000..20f09cbd6
--- /dev/null
+++ b/sys/src/9/pc/ether8139.c
@@ -0,0 +1,833 @@
+/*
+ * Realtek 8139 (but not the 8129).
+ * Error recovery for the various over/under -flow conditions
+ * may need work.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+enum { /* registers */
+ Idr0 = 0x0000, /* MAC address */
+ Mar0 = 0x0008, /* Multicast address */
+ Tsd0 = 0x0010, /* Transmit Status Descriptor0 */
+ Tsad0 = 0x0020, /* Transmit Start Address Descriptor0 */
+ Rbstart = 0x0030, /* Receive Buffer Start Address */
+ Erbcr = 0x0034, /* Early Receive Byte Count */
+ Ersr = 0x0036, /* Early Receive Status */
+ Cr = 0x0037, /* Command Register */
+ Capr = 0x0038, /* Current Address of Packet Read */
+ Cbr = 0x003A, /* Current Buffer Address */
+ Imr = 0x003C, /* Interrupt Mask */
+ Isr = 0x003E, /* Interrupt Status */
+ Tcr = 0x0040, /* Transmit Configuration */
+ Rcr = 0x0044, /* Receive Configuration */
+ Tctr = 0x0048, /* Timer Count */
+ Mpc = 0x004C, /* Missed Packet Counter */
+ Cr9346 = 0x0050, /* 9346 Command Register */
+ Config0 = 0x0051, /* Configuration Register 0 */
+ Config1 = 0x0052, /* Configuration Register 1 */
+ TimerInt = 0x0054, /* Timer Interrupt */
+ Msr = 0x0058, /* Media Status */
+ Config3 = 0x0059, /* Configuration Register 3 */
+ Config4 = 0x005A, /* Configuration Register 4 */
+ Mulint = 0x005C, /* Multiple Interrupt Select */
+ RerID = 0x005E, /* PCI Revision ID */
+ Tsad = 0x0060, /* Transmit Status of all Descriptors */
+
+ Bmcr = 0x0062, /* Basic Mode Control */
+ Bmsr = 0x0064, /* Basic Mode Status */
+ Anar = 0x0066, /* Auto-Negotiation Advertisment */
+ Anlpar = 0x0068, /* Auto-Negotiation Link Partner */
+ Aner = 0x006A, /* Auto-Negotiation Expansion */
+ Dis = 0x006C, /* Disconnect Counter */
+ Fcsc = 0x006E, /* False Carrier Sense Counter */
+ Nwaytr = 0x0070, /* N-way Test */
+ Rec = 0x0072, /* RX_ER Counter */
+ Cscr = 0x0074, /* CS Configuration */
+ Phy1parm = 0x0078, /* PHY Parameter 1 */
+ Twparm = 0x007C, /* Twister Parameter */
+ Phy2parm = 0x0080, /* PHY Parameter 2 */
+};
+
+enum { /* Cr */
+ Bufe = 0x01, /* Rx Buffer Empty */
+ Te = 0x04, /* Transmitter Enable */
+ Re = 0x08, /* Receiver Enable */
+ Rst = 0x10, /* Software Reset */
+};
+
+enum { /* Imr/Isr */
+ Rok = 0x0001, /* Receive OK */
+ Rer = 0x0002, /* Receive Error */
+ Tok = 0x0004, /* Transmit OK */
+ Ter = 0x0008, /* Transmit Error */
+ Rxovw = 0x0010, /* Receive Buffer Overflow */
+ PunLc = 0x0020, /* Packet Underrun or Link Change */
+ Fovw = 0x0040, /* Receive FIFO Overflow */
+ Clc = 0x2000, /* Cable Length Change */
+ Timerbit = 0x4000, /* Timer */
+ Serr = 0x8000, /* System Error */
+};
+
+enum { /* Tcr */
+ Clrabt = 0x00000001, /* Clear Abort */
+ TxrrSHIFT = 4, /* Transmit Retry Count */
+ TxrrMASK = 0x000000F0,
+ MtxdmaSHIFT = 8, /* Max. DMA Burst Size */
+ MtxdmaMASK = 0x00000700,
+ Mtxdma2048 = 0x00000700,
+ Acrc = 0x00010000, /* Append CRC (not) */
+ LbkSHIFT = 17, /* Loopback Test */
+ LbkMASK = 0x00060000,
+ Rtl8139ArevG = 0x00800000, /* RTL8139A Rev. G ID */
+ IfgSHIFT = 24, /* Interframe Gap */
+ IfgMASK = 0x03000000,
+ HwveridSHIFT = 26, /* Hardware Version ID */
+ HwveridMASK = 0x7C000000,
+};
+
+enum { /* Rcr */
+ Aap = 0x00000001, /* Accept All Packets */
+ Apm = 0x00000002, /* Accept Physical Match */
+ Am = 0x00000004, /* Accept Multicast */
+ Ab = 0x00000008, /* Accept Broadcast */
+ Ar = 0x00000010, /* Accept Runt */
+ Aer = 0x00000020, /* Accept Error */
+ Sel9356 = 0x00000040, /* 9356 EEPROM used */
+ Wrap = 0x00000080, /* Rx Buffer Wrap Control */
+ MrxdmaSHIFT = 8, /* Max. DMA Burst Size */
+ MrxdmaMASK = 0x00000700,
+ Mrxdmaunlimited = 0x00000700,
+ RblenSHIFT = 11, /* Receive Buffer Length */
+ RblenMASK = 0x00001800,
+ Rblen8K = 0x00000000, /* 8KB+16 */
+ Rblen16K = 0x00000800, /* 16KB+16 */
+ Rblen32K = 0x00001000, /* 32KB+16 */
+ Rblen64K = 0x00001800, /* 64KB+16 */
+ RxfthSHIFT = 13, /* Receive Buffer Length */
+ RxfthMASK = 0x0000E000,
+ Rxfth256 = 0x00008000,
+ Rxfthnone = 0x0000E000,
+ Rer8 = 0x00010000, /* Accept Error Packets > 8 bytes */
+ MulERINT = 0x00020000, /* Multiple Early Interrupt Select */
+ ErxthSHIFT = 24, /* Early Rx Threshold */
+ ErxthMASK = 0x0F000000,
+ Erxthnone = 0x00000000,
+};
+
+enum { /* Received Packet Status */
+ Rcok = 0x0001, /* Receive Completed OK */
+ Fae = 0x0002, /* Frame Alignment Error */
+ Crc = 0x0004, /* CRC Error */
+ Long = 0x0008, /* Long Packet */
+ Runt = 0x0010, /* Runt Packet Received */
+ Ise = 0x0020, /* Invalid Symbol Error */
+ Bar = 0x2000, /* Broadcast Address Received */
+ Pam = 0x4000, /* Physical Address Matched */
+ Mar = 0x8000, /* Multicast Address Received */
+};
+
+enum { /* Media Status Register */
+ Rxpf = 0x01, /* Pause Flag */
+ Txpf = 0x02, /* Pause Flag */
+ Linkb = 0x04, /* Inverse of Link Status */
+ Speed10 = 0x08, /* 10Mbps */
+ Auxstatus = 0x10, /* Aux. Power Present Status */
+ Rxfce = 0x40, /* Receive Flow Control Enable */
+ Txfce = 0x80, /* Transmit Flow Control Enable */
+};
+
+typedef struct Td Td;
+struct Td { /* Soft Transmit Descriptor */
+ int tsd;
+ int tsad;
+ uchar* data;
+ Block* bp;
+};
+
+enum { /* Tsd0 */
+ SizeSHIFT = 0, /* Descriptor Size */
+ SizeMASK = 0x00001FFF,
+ Own = 0x00002000,
+ Tun = 0x00004000, /* Transmit FIFO Underrun */
+ Tcok = 0x00008000, /* Transmit COmpleted OK */
+ EtxthSHIFT = 16, /* Early Tx Threshold */
+ EtxthMASK = 0x001F0000,
+ NccSHIFT = 24, /* Number of Collisions Count */
+ NccMASK = 0x0F000000,
+ Cdh = 0x10000000, /* CD Heartbeat */
+ Owc = 0x20000000, /* Out of Window Collision */
+ Tabt = 0x40000000, /* Transmit Abort */
+ Crs = 0x80000000, /* Carrier Sense Lost */
+};
+
+enum {
+ Rblen = Rblen64K, /* Receive Buffer Length */
+ Ntd = 4, /* Number of Transmit Descriptors */
+ Tdbsz = ROUNDUP(sizeof(Etherpkt), 4),
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id;
+
+ QLock alock; /* attach */
+ Lock ilock; /* init */
+ void* alloc; /* base of per-Ctlr allocated data */
+
+ int pcie; /* flag: pci-express device? */
+
+ uvlong mchash; /* multicast hash */
+
+ int rcr; /* receive configuration register */
+ uchar* rbstart; /* receive buffer */
+ int rblen; /* receive buffer length */
+ int ierrs; /* receive errors */
+
+ Lock tlock; /* transmit */
+ Td td[Ntd];
+ int ntd; /* descriptors active */
+ int tdh; /* host index into td */
+ int tdi; /* interface index into td */
+ int etxth; /* early transmit threshold */
+ int taligned; /* packet required no alignment */
+ int tunaligned; /* packet required alignment */
+
+ int dis; /* disconnect counter */
+ int fcsc; /* false carrier sense counter */
+ int rec; /* RX_ER counter */
+ uint mcast;
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+#define csr8r(c, r) (inb((c)->port+(r)))
+#define csr16r(c, r) (ins((c)->port+(r)))
+#define csr32r(c, r) (inl((c)->port+(r)))
+#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
+#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
+#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
+
+static void
+rtl8139promiscuous(void* arg, int on)
+{
+ Ether *edev;
+ Ctlr * ctlr;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+ ilock(&ctlr->ilock);
+
+ if(on)
+ ctlr->rcr |= Aap;
+ else
+ ctlr->rcr &= ~Aap;
+ csr32w(ctlr, Rcr, ctlr->rcr);
+ iunlock(&ctlr->ilock);
+}
+
+enum {
+ /* everyone else uses 0x04c11db7, but they both produce the same crc */
+ Etherpolybe = 0x04c11db6,
+ Bytemask = (1<<8) - 1,
+};
+
+static ulong
+ethercrcbe(uchar *addr, long len)
+{
+ int i, j;
+ ulong c, crc, carry;
+
+ crc = ~0UL;
+ for (i = 0; i < len; i++) {
+ c = addr[i];
+ for (j = 0; j < 8; j++) {
+ carry = ((crc & (1UL << 31))? 1: 0) ^ (c & 1);
+ crc <<= 1;
+ c >>= 1;
+ if (carry)
+ crc = (crc ^ Etherpolybe) | carry;
+ }
+ }
+ return crc;
+}
+
+static ulong
+swabl(ulong l)
+{
+ return l>>24 | (l>>8) & (Bytemask<<8) |
+ (l<<8) & (Bytemask<<16) | l<<24;
+}
+
+static void
+rtl8139multicast(void* ether, uchar *eaddr, int add)
+{
+ Ether *edev;
+ Ctlr *ctlr;
+
+ if (!add)
+ return; /* ok to keep receiving on old mcast addrs */
+
+ edev = ether;
+ ctlr = edev->ctlr;
+ ilock(&ctlr->ilock);
+
+ ctlr->mchash |= 1ULL << (ethercrcbe(eaddr, Eaddrlen) >> 26);
+
+ ctlr->rcr |= Am;
+ csr32w(ctlr, Rcr, ctlr->rcr);
+
+ /* pci-e variants reverse the order of the hash byte registers */
+ if (0 && ctlr->pcie) {
+ csr32w(ctlr, Mar0, swabl(ctlr->mchash>>32));
+ csr32w(ctlr, Mar0+4, swabl(ctlr->mchash));
+ } else {
+ csr32w(ctlr, Mar0, ctlr->mchash);
+ csr32w(ctlr, Mar0+4, ctlr->mchash>>32);
+ }
+
+ iunlock(&ctlr->ilock);
+}
+
+static long
+rtl8139ifstat(Ether* edev, void* a, long n, ulong offset)
+{
+ int l;
+ char *p;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ p = malloc(READSTR);
+ l = snprint(p, READSTR, "rcr %#8.8ux\n", ctlr->rcr);
+ l += snprint(p+l, READSTR-l, "multicast %ud\n", ctlr->mcast);
+ 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);
+ l += snprint(p+l, READSTR-l, "tunaligned %d\n", ctlr->tunaligned);
+ ctlr->dis += csr16r(ctlr, Dis);
+ l += snprint(p+l, READSTR-l, "dis %d\n", ctlr->dis);
+ ctlr->fcsc += csr16r(ctlr, Fcsc);
+ l += snprint(p+l, READSTR-l, "fcscnt %d\n", ctlr->fcsc);
+ 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));
+ n = readstr(offset, a, n, p);
+ free(p);
+
+ return n;
+}
+
+static int
+rtl8139reset(Ctlr* ctlr)
+{
+ int timeo;
+
+ /*
+ * Soft reset the controller.
+ */
+ csr8w(ctlr, Cr, Rst);
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!(csr8r(ctlr, Cr) & Rst))
+ return 0;
+ delay(1);
+ }
+
+ return -1;
+}
+
+static void
+rtl8139halt(Ctlr* ctlr)
+{
+ int i;
+
+ csr8w(ctlr, Cr, 0);
+ csr16w(ctlr, Imr, 0);
+ csr16w(ctlr, Isr, ~0);
+
+ for(i = 0; i < Ntd; i++){
+ if(ctlr->td[i].bp == nil)
+ continue;
+ freeb(ctlr->td[i].bp);
+ ctlr->td[i].bp = nil;
+ }
+}
+
+static void
+rtl8139init(Ether* edev)
+{
+ int i;
+ ulong r;
+ Ctlr *ctlr;
+ uchar *alloc;
+
+ ctlr = edev->ctlr;
+ ilock(&ctlr->ilock);
+
+ rtl8139halt(ctlr);
+
+ /*
+ * MAC Address.
+ */
+ r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
+ csr32w(ctlr, Idr0, r);
+ r = (edev->ea[5]<<8)|edev->ea[4];
+ csr32w(ctlr, Idr0+4, r);
+
+ /*
+ * Receiver
+ */
+ alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 32);
+ ctlr->rbstart = alloc;
+ alloc += ctlr->rblen+16;
+ memset(ctlr->rbstart, 0, ctlr->rblen+16);
+ csr32w(ctlr, Rbstart, PCIWADDR(ctlr->rbstart));
+ ctlr->rcr = Rxfth256|Rblen|Mrxdmaunlimited|Ab|Am|Apm;
+
+ /*
+ * Transmitter.
+ */
+ for(i = 0; i < Ntd; i++){
+ ctlr->td[i].tsd = Tsd0+i*4;
+ ctlr->td[i].tsad = Tsad0+i*4;
+ ctlr->td[i].data = alloc;
+ alloc += Tdbsz;
+ ctlr->td[i].bp = nil;
+ }
+ ctlr->ntd = ctlr->tdh = ctlr->tdi = 0;
+ ctlr->etxth = 128/32;
+
+ /*
+ * Interrupts.
+ */
+ csr32w(ctlr, TimerInt, 0);
+ csr16w(ctlr, Imr, Serr|Timerbit|Fovw|PunLc|Rxovw|Ter|Tok|Rer|Rok);
+ csr32w(ctlr, Mpc, 0);
+
+ /*
+ * Enable receiver/transmitter.
+ * Need to enable before writing the Rcr or it won't take.
+ */
+ csr8w(ctlr, Cr, Te|Re);
+ csr32w(ctlr, Tcr, Mtxdma2048);
+ csr32w(ctlr, Rcr, ctlr->rcr);
+ csr32w(ctlr, Mar0, 0);
+ csr32w(ctlr, Mar0+4, 0);
+ ctlr->mchash = 0;
+
+ iunlock(&ctlr->ilock);
+}
+
+static void
+rtl8139attach(Ether* edev)
+{
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ qlock(&ctlr->alock);
+ if(ctlr->alloc == nil){
+ ctlr->rblen = 1<<((Rblen>>RblenSHIFT)+13);
+ ctlr->alloc = mallocz(ctlr->rblen+16 + Ntd*Tdbsz + 32, 0);
+ rtl8139init(edev);
+ }
+ qunlock(&ctlr->alock);
+}
+
+static void
+rtl8139txstart(Ether* edev)
+{
+ Td *td;
+ int size;
+ Block *bp;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ while(ctlr->ntd < Ntd){
+ bp = qget(edev->oq);
+ if(bp == nil)
+ break;
+ size = BLEN(bp);
+
+ td = &ctlr->td[ctlr->tdh];
+ if(((int)bp->rp) & 0x03){
+ memmove(td->data, bp->rp, size);
+ freeb(bp);
+ csr32w(ctlr, td->tsad, PCIWADDR(td->data));
+ ctlr->tunaligned++;
+ }
+ else{
+ td->bp = bp;
+ csr32w(ctlr, td->tsad, PCIWADDR(bp->rp));
+ ctlr->taligned++;
+ }
+ csr32w(ctlr, td->tsd, (ctlr->etxth<<EtxthSHIFT)|size);
+
+ ctlr->ntd++;
+ ctlr->tdh = NEXT(ctlr->tdh, Ntd);
+ }
+}
+
+static void
+rtl8139transmit(Ether* edev)
+{
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ ilock(&ctlr->tlock);
+ rtl8139txstart(edev);
+ iunlock(&ctlr->tlock);
+}
+
+static void
+rtl8139receive(Ether* edev)
+{
+ Block *bp;
+ Ctlr *ctlr;
+ ushort capr;
+ uchar cr, *p;
+ int l, length, status;
+
+ ctlr = edev->ctlr;
+
+ /*
+ * Capr is where the host is reading from,
+ * Cbr is where the NIC is currently writing.
+ */
+ capr = (csr16r(ctlr, Capr)+16) % ctlr->rblen;
+ while(!(csr8r(ctlr, Cr) & Bufe)){
+ p = ctlr->rbstart+capr;
+
+ /*
+ * Apparently the packet length may be 0xFFF0 if
+ * the NIC is still copying the packet into memory.
+ */
+ length = (*(p+3)<<8)|*(p+2);
+ if(length == 0xFFF0)
+ break;
+ status = (*(p+1)<<8)|*p;
+
+ if(!(status & Rcok)){
+ if(status & (Ise|Fae))
+ edev->frames++;
+ if(status & Crc)
+ edev->crcs++;
+ if(status & (Runt|Long))
+ edev->buffs++;
+
+ /*
+ * Reset the receiver.
+ * Also may have to restore the multicast list
+ * here too if it ever gets used.
+ */
+ cr = csr8r(ctlr, Cr);
+ csr8w(ctlr, Cr, cr & ~Re);
+ csr32w(ctlr, Rbstart, PCIWADDR(ctlr->rbstart));
+ csr8w(ctlr, Cr, cr);
+ csr32w(ctlr, Rcr, ctlr->rcr);
+
+ continue;
+ }
+
+ /*
+ * Receive Completed OK.
+ * Very simplistic; there are ways this could be done
+ * without copying, but the juice probably isn't worth
+ * the squeeze.
+ * The packet length includes a 4 byte CRC on the end.
+ */
+ capr = (capr+4) % ctlr->rblen;
+ p = ctlr->rbstart+capr;
+ capr = (capr+length) % ctlr->rblen;
+ if(status & Mar)
+ ctlr->mcast++;
+
+ if((bp = iallocb(length)) != nil){
+ if(p+length >= ctlr->rbstart+ctlr->rblen){
+ l = ctlr->rbstart+ctlr->rblen - p;
+ memmove(bp->wp, p, l);
+ bp->wp += l;
+ length -= l;
+ p = ctlr->rbstart;
+ }
+ if(length > 0){
+ memmove(bp->wp, p, length);
+ bp->wp += length;
+ }
+ bp->wp -= 4;
+ etheriq(edev, bp, 1);
+ }
+
+ capr = ROUNDUP(capr, 4);
+ csr16w(ctlr, Capr, capr-16);
+ }
+}
+
+static void
+rtl8139interrupt(Ureg*, void* arg)
+{
+ Td *td;
+ Ctlr *ctlr;
+ Ether *edev;
+ int isr, msr, tsd;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ while((isr = csr16r(ctlr, Isr)) != 0){
+ csr16w(ctlr, Isr, isr);
+ if(isr & (Fovw|PunLc|Rxovw|Rer|Rok)){
+ rtl8139receive(edev);
+ if(!(isr & Rok))
+ ctlr->ierrs++;
+ isr &= ~(Fovw|Rxovw|Rer|Rok);
+ }
+
+ if(isr & (Ter|Tok)){
+ ilock(&ctlr->tlock);
+ while(ctlr->ntd){
+ td = &ctlr->td[ctlr->tdi];
+ tsd = csr32r(ctlr, td->tsd);
+ if(!(tsd & (Tabt|Tun|Tcok)))
+ break;
+
+ if(!(tsd & Tcok)){
+ if(tsd & Tun){
+ if(ctlr->etxth < ETHERMAXTU/32)
+ ctlr->etxth++;
+ }
+ edev->oerrs++;
+ }
+
+ if(td->bp != nil){
+ freeb(td->bp);
+ td->bp = nil;
+ }
+
+ ctlr->ntd--;
+ ctlr->tdi = NEXT(ctlr->tdi, Ntd);
+ }
+ rtl8139txstart(edev);
+ iunlock(&ctlr->tlock);
+ isr &= ~(Ter|Tok);
+ }
+
+ if(isr & PunLc){
+ /*
+ * Maybe the link changed - do we care very much?
+ */
+ msr = csr8r(ctlr, Msr);
+ if(!(msr & Linkb)){
+ if(!(msr & Speed10) && edev->mbps != 100){
+ edev->mbps = 100;
+ qsetlimit(edev->oq, 256*1024);
+ }
+ else if((msr & Speed10) && edev->mbps != 10){
+ edev->mbps = 10;
+ qsetlimit(edev->oq, 65*1024);
+ }
+ }
+ isr &= ~(Clc|PunLc);
+ }
+
+ /*
+ * Only Serr|Timerbit should be left by now.
+ * Should anything be done to tidy up? TimerInt isn't
+ * used so that can be cleared. A PCI bus error is indicated
+ * by Serr, that's pretty serious; is there anyhing to do
+ * other than try to reinitialise the chip?
+ */
+ if((isr & (Serr|Timerbit)) != 0){
+ iprint("rtl8139interrupt: imr %#4.4ux isr %#4.4ux\n",
+ csr16r(ctlr, Imr), isr);
+ if(isr & Timerbit)
+ csr32w(ctlr, TimerInt, 0);
+ if(isr & Serr)
+ rtl8139init(edev);
+ }
+ }
+}
+
+static Ctlr*
+rtl8139match(Ether* edev, int id)
+{
+ Pcidev *p;
+ Ctlr *ctlr;
+ int i, port;
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ p = ctlr->pcidev;
+ if(((p->did<<16)|p->vid) != id)
+ continue;
+ port = p->mem[0].bar & ~0x01;
+ if(edev->port != 0 && edev->port != port)
+ continue;
+
+ if(ioalloc(port, p->mem[0].size, 0, "rtl8139") < 0){
+ print("rtl8139: port %#ux in use\n", port);
+ continue;
+ }
+
+ if(pcigetpms(p) > 0){
+ pcisetpms(p, 0);
+
+ for(i = 0; i < 6; i++)
+ pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
+ pcicfgw8(p, PciINTL, p->intl);
+ pcicfgw8(p, PciLTR, p->ltr);
+ pcicfgw8(p, PciCLS, p->cls);
+ pcicfgw16(p, PciPCR, p->pcr);
+ }
+
+ ctlr->port = port;
+ if(rtl8139reset(ctlr)) {
+ iofree(port);
+ continue;
+ }
+ pcisetbme(p);
+
+ ctlr->active = 1;
+ return ctlr;
+ }
+ return nil;
+}
+
+static struct {
+ char* name;
+ int id;
+} rtl8139pci[] = {
+ { "rtl8139", (0x8139<<16)|0x10EC, }, /* generic */
+ { "smc1211", (0x1211<<16)|0x1113, }, /* SMC EZ-Card */
+ { "dfe-538tx", (0x1300<<16)|0x1186, }, /* D-Link DFE-538TX */
+ { "dfe-560txd", (0x1340<<16)|0x1186, }, /* D-Link DFE-560TXD */
+ { nil },
+};
+
+static int
+rtl8139pnp(Ether* edev)
+{
+ int i, id;
+ Pcidev *p;
+ Ctlr *ctlr;
+ uchar ea[Eaddrlen];
+
+ /*
+ * Make a list of all ethernet controllers
+ * if not already done.
+ */
+ if(ctlrhead == nil){
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->pcidev = p;
+ ctlr->id = (p->did<<16)|p->vid;
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+ }
+
+ /*
+ * Is it an RTL8139 under a different name?
+ * Normally a search is made through all the found controllers
+ * for one which matches any of the known vid+did pairs.
+ * If a vid+did pair is specified a search is made for that
+ * specific controller only.
+ */
+ id = 0;
+ for(i = 0; i < edev->nopt; i++){
+ if(cistrncmp(edev->opt[i], "id=", 3) == 0)
+ id = strtol(&edev->opt[i][3], nil, 0);
+ }
+
+ ctlr = nil;
+ if(id != 0)
+ ctlr = rtl8139match(edev, id);
+ else for(i = 0; rtl8139pci[i].name; i++){
+ if((ctlr = rtl8139match(edev, rtl8139pci[i].id)) != nil)
+ break;
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the device and set in edev->ea.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, edev->ea, Eaddrlen) == 0){
+ i = csr32r(ctlr, Idr0);
+ edev->ea[0] = i;
+ edev->ea[1] = i>>8;
+ edev->ea[2] = i>>16;
+ edev->ea[3] = i>>24;
+ i = csr32r(ctlr, Idr0+4);
+ edev->ea[4] = i;
+ edev->ea[5] = i>>8;
+ }
+
+ edev->attach = rtl8139attach;
+ edev->transmit = rtl8139transmit;
+ edev->interrupt = rtl8139interrupt;
+ edev->ifstat = rtl8139ifstat;
+
+ edev->arg = edev;
+ edev->promiscuous = rtl8139promiscuous;
+ edev->multicast = rtl8139multicast;
+// edev->shutdown = rtl8139shutdown;
+
+ /*
+ * This should be much more dynamic but will do for now.
+ */
+ if((csr8r(ctlr, Msr) & (Speed10|Linkb)) == 0)
+ edev->mbps = 100;
+
+ return 0;
+}
+
+void
+ether8139link(void)
+{
+ addethercard("rtl8139", rtl8139pnp);
+}
diff --git a/sys/src/9/pc/ether8169.c b/sys/src/9/pc/ether8169.c
new file mode 100755
index 000000000..24aae673d
--- /dev/null
+++ b/sys/src/9/pc/ether8169.c
@@ -0,0 +1,1245 @@
+/*
+ * Realtek RTL8110S/8169S Gigabit Ethernet Controllers.
+ * Mostly there. There are some magic register values used
+ * which are not described in any datasheet or driver but seem
+ * to be necessary.
+ * No tuning has been done. Only tested on an RTL8110S, there
+ * are slight differences between the chips in the series so some
+ * tweaks may be needed.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+enum { /* registers */
+ Idr0 = 0x00, /* MAC address */
+ Mar0 = 0x08, /* Multicast address */
+ Dtccr = 0x10, /* Dump Tally Counter Command */
+ Tnpds = 0x20, /* Transmit Normal Priority Descriptors */
+ Thpds = 0x28, /* Transmit High Priority Descriptors */
+ Flash = 0x30, /* Flash Memory Read/Write */
+ Erbcr = 0x34, /* Early Receive Byte Count */
+ Ersr = 0x36, /* Early Receive Status */
+ Cr = 0x37, /* Command Register */
+ Tppoll = 0x38, /* Transmit Priority Polling */
+ Imr = 0x3C, /* Interrupt Mask */
+ Isr = 0x3E, /* Interrupt Status */
+ Tcr = 0x40, /* Transmit Configuration */
+ Rcr = 0x44, /* Receive Configuration */
+ Tctr = 0x48, /* Timer Count */
+ Mpc = 0x4C, /* Missed Packet Counter */
+ Cr9346 = 0x50, /* 9346 Command Register */
+ Config0 = 0x51, /* Configuration Register 0 */
+ Config1 = 0x52, /* Configuration Register 1 */
+ Config2 = 0x53, /* Configuration Register 2 */
+ Config3 = 0x54, /* Configuration Register 3 */
+ Config4 = 0x55, /* Configuration Register 4 */
+ Config5 = 0x56, /* Configuration Register 5 */
+ Timerint = 0x58, /* Timer Interrupt */
+ Mulint = 0x5C, /* Multiple Interrupt Select */
+ Phyar = 0x60, /* PHY Access */
+ Tbicsr0 = 0x64, /* TBI Control and Status */
+ Tbianar = 0x68, /* TBI Auto-Negotiation Advertisment */
+ Tbilpar = 0x6A, /* TBI Auto-Negotiation Link Partner */
+ Phystatus = 0x6C, /* PHY Status */
+
+ Rms = 0xDA, /* Receive Packet Maximum Size */
+ Cplusc = 0xE0, /* C+ Command */
+ Coal = 0xE2, /* Interrupt Mitigation (Coalesce) */
+ Rdsar = 0xE4, /* Receive Descriptor Start Address */
+ Etx = 0xEC, /* Early Transmit Threshold */
+};
+
+enum { /* Dtccr */
+ Cmd = 0x00000008, /* Command */
+};
+
+enum { /* Cr */
+ Te = 0x04, /* Transmitter Enable */
+ Re = 0x08, /* Receiver Enable */
+ Rst = 0x10, /* Software Reset */
+};
+
+enum { /* Tppoll */
+ Fswint = 0x01, /* Forced Software Interrupt */
+ Npq = 0x40, /* Normal Priority Queue polling */
+ Hpq = 0x80, /* High Priority Queue polling */
+};
+
+enum { /* Imr/Isr */
+ Rok = 0x0001, /* Receive OK */
+ Rer = 0x0002, /* Receive Error */
+ Tok = 0x0004, /* Transmit OK */
+ Ter = 0x0008, /* Transmit Error */
+ Rdu = 0x0010, /* Receive Descriptor Unavailable */
+ Punlc = 0x0020, /* Packet Underrun or Link Change */
+ Fovw = 0x0040, /* Receive FIFO Overflow */
+ Tdu = 0x0080, /* Transmit Descriptor Unavailable */
+ Swint = 0x0100, /* Software Interrupt */
+ Timeout = 0x4000, /* Timer */
+ Serr = 0x8000, /* System Error */
+};
+
+enum { /* Tcr */
+ MtxdmaSHIFT = 8, /* Max. DMA Burst Size */
+ MtxdmaMASK = 0x00000700,
+ Mtxdmaunlimited = 0x00000700,
+ Acrc = 0x00010000, /* Append CRC (not) */
+ Lbk0 = 0x00020000, /* Loopback Test 0 */
+ Lbk1 = 0x00040000, /* Loopback Test 1 */
+ Ifg2 = 0x00080000, /* Interframe Gap 2 */
+ HwveridSHIFT = 23, /* Hardware Version ID */
+ HwveridMASK = 0x7C800000,
+ Macv01 = 0x00000000, /* RTL8169 */
+ Macv02 = 0x00800000, /* RTL8169S/8110S */
+ Macv03 = 0x04000000, /* RTL8169S/8110S */
+ Macv04 = 0x10000000, /* RTL8169SB/8110SB */
+ Macv05 = 0x18000000, /* RTL8169SC/8110SC */
+ Macv07 = 0x24800000, /* RTL8102e */
+ Macv07a = 0x34800000, /* RTL8102e */
+ Macv11 = 0x30000000, /* RTL8168B/8111B */
+ Macv12 = 0x38000000, /* RTL8169B/8111B */
+ Macv12a = 0x3c000000, /* RTL8169C/8111C */
+ Macv13 = 0x34000000, /* RTL8101E */
+ Macv14 = 0x30800000, /* RTL8100E */
+ Macv15 = 0x38800000, /* RTL8100E */
+// Macv19 = 0x3c000000, /* dup Macv12a: RTL8111c-gr */
+ Macv25 = 0x28000000, /* RTL8168D */
+ Ifg0 = 0x01000000, /* Interframe Gap 0 */
+ Ifg1 = 0x02000000, /* Interframe Gap 1 */
+};
+
+enum { /* Rcr */
+ Aap = 0x00000001, /* Accept All Packets */
+ Apm = 0x00000002, /* Accept Physical Match */
+ Am = 0x00000004, /* Accept Multicast */
+ Ab = 0x00000008, /* Accept Broadcast */
+ Ar = 0x00000010, /* Accept Runt */
+ Aer = 0x00000020, /* Accept Error */
+ Sel9356 = 0x00000040, /* 9356 EEPROM used */
+ MrxdmaSHIFT = 8, /* Max. DMA Burst Size */
+ MrxdmaMASK = 0x00000700,
+ Mrxdmaunlimited = 0x00000700,
+ RxfthSHIFT = 13, /* Receive Buffer Length */
+ RxfthMASK = 0x0000E000,
+ Rxfth256 = 0x00008000,
+ Rxfthnone = 0x0000E000,
+ Rer8 = 0x00010000, /* Accept Error Packets > 8 bytes */
+ MulERINT = 0x01000000, /* Multiple Early Interrupt Select */
+};
+
+enum { /* Cr9346 */
+ Eedo = 0x01, /* */
+ Eedi = 0x02, /* */
+ Eesk = 0x04, /* */
+ Eecs = 0x08, /* */
+ Eem0 = 0x40, /* Operating Mode */
+ Eem1 = 0x80,
+};
+
+enum { /* Phyar */
+ DataMASK = 0x0000FFFF, /* 16-bit GMII/MII Register Data */
+ DataSHIFT = 0,
+ RegaddrMASK = 0x001F0000, /* 5-bit GMII/MII Register Address */
+ RegaddrSHIFT = 16,
+ Flag = 0x80000000, /* */
+};
+
+enum { /* Phystatus */
+ Fd = 0x01, /* Full Duplex */
+ Linksts = 0x02, /* Link Status */
+ Speed10 = 0x04, /* */
+ Speed100 = 0x08, /* */
+ Speed1000 = 0x10, /* */
+ Rxflow = 0x20, /* */
+ Txflow = 0x40, /* */
+ Entbi = 0x80, /* */
+};
+
+enum { /* Cplusc */
+ Mulrw = 0x0008, /* PCI Multiple R/W Enable */
+ Dac = 0x0010, /* PCI Dual Address Cycle Enable */
+ Rxchksum = 0x0020, /* Receive Checksum Offload Enable */
+ Rxvlan = 0x0040, /* Receive VLAN De-tagging Enable */
+ Endian = 0x0200, /* Endian Mode */
+};
+
+typedef struct D D; /* Transmit/Receive Descriptor */
+struct D {
+ u32int control;
+ u32int vlan;
+ u32int addrlo;
+ u32int addrhi;
+};
+
+enum { /* Transmit Descriptor control */
+ TxflMASK = 0x0000FFFF, /* Transmit Frame Length */
+ TxflSHIFT = 0,
+ Tcps = 0x00010000, /* TCP Checksum Offload */
+ Udpcs = 0x00020000, /* UDP Checksum Offload */
+ Ipcs = 0x00040000, /* IP Checksum Offload */
+ Lgsen = 0x08000000, /* TSO; WARNING: contains lark's vomit */
+};
+
+enum { /* Receive Descriptor control */
+ RxflMASK = 0x00001FFF, /* Receive Frame Length */
+ Tcpf = 0x00004000, /* TCP Checksum Failure */
+ Udpf = 0x00008000, /* UDP Checksum Failure */
+ Ipf = 0x00010000, /* IP Checksum Failure */
+ Pid0 = 0x00020000, /* Protocol ID0 */
+ Pid1 = 0x00040000, /* Protocol ID1 */
+ Crce = 0x00080000, /* CRC Error */
+ Runt = 0x00100000, /* Runt Packet */
+ Res = 0x00200000, /* Receive Error Summary */
+ Rwt = 0x00400000, /* Receive Watchdog Timer Expired */
+ Fovf = 0x00800000, /* FIFO Overflow */
+ Bovf = 0x01000000, /* Buffer Overflow */
+ Bar = 0x02000000, /* Broadcast Address Received */
+ Pam = 0x04000000, /* Physical Address Matched */
+ Mar = 0x08000000, /* Multicast Address Received */
+};
+
+enum { /* General Descriptor control */
+ Ls = 0x10000000, /* Last Segment Descriptor */
+ Fs = 0x20000000, /* First Segment Descriptor */
+ Eor = 0x40000000, /* End of Descriptor Ring */
+ Own = 0x80000000, /* Ownership */
+};
+
+/*
+ */
+enum { /* Ring sizes (<= 1024) */
+ Ntd = 64, /* Transmit Ring */
+ Nrd = 256, /* Receive Ring */
+
+ Mtu = ETHERMAXTU,
+ Mps = ROUNDUP(ETHERMAXTU+4, 128),
+// Mps = Mtu + 8 + 14, /* if(mtu>ETHERMAXTU) */
+};
+
+typedef struct Dtcc Dtcc;
+struct Dtcc {
+ u64int txok;
+ u64int rxok;
+ u64int txer;
+ u32int rxer;
+ u16int misspkt;
+ u16int fae;
+ u32int tx1col;
+ u32int txmcol;
+ u64int rxokph;
+ u64int rxokbrd;
+ u32int rxokmu;
+ u16int txabt;
+ u16int txundrn;
+};
+
+enum { /* Variants */
+ Rtl8100e = (0x8136<<16)|0x10EC, /* RTL810[01]E: pci -e */
+ Rtl8169c = (0x0116<<16)|0x16EC, /* RTL8169C+ (USR997902) */
+ Rtl8169sc = (0x8167<<16)|0x10EC, /* RTL8169SC */
+ Rtl8168b = (0x8168<<16)|0x10EC, /* RTL8168B: pci-e */
+ Rtl8169 = (0x8169<<16)|0x10EC, /* RTL8169 */
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+
+ QLock alock; /* attach */
+ Lock ilock; /* init */
+ int init; /* */
+
+ int pciv; /* */
+ int macv; /* MAC version */
+ int phyv; /* PHY version */
+ int pcie; /* flag: pci-express device? */
+
+ uvlong mchash; /* multicast hash */
+
+ Mii* mii;
+
+ Lock tlock; /* transmit */
+ D* td; /* descriptor ring */
+ Block** tb; /* transmit buffers */
+ int ntd;
+
+ int tdh; /* head - producer index (host) */
+ int tdt; /* tail - consumer index (NIC) */
+ int ntdfree;
+ int ntq;
+
+// int rbsz; /* receive buffer size */
+
+ Lock rlock; /* receive */
+ D* rd; /* descriptor ring */
+ Block** rb; /* receive buffers */
+ int nrd;
+
+ int rdh; /* head - producer index (NIC) */
+ int rdt; /* tail - consumer index (host) */
+ int nrdfree;
+
+ int tcr; /* transmit configuration register */
+ int rcr; /* receive configuration register */
+ int imr;
+
+ QLock slock; /* statistics */
+ Dtcc* dtcc;
+ uint txdu;
+ uint tcpf;
+ uint udpf;
+ uint ipf;
+ uint fovf;
+ uint ierrs;
+ uint rer;
+ uint rdu;
+ uint punlc;
+ uint fovw;
+ uint mcast;
+ uint frag; /* partial packets; rb was too small */
+} Ctlr;
+
+static Ctlr* rtl8169ctlrhead;
+static Ctlr* rtl8169ctlrtail;
+
+#define csr8r(c, r) (inb((c)->port+(r)))
+#define csr16r(c, r) (ins((c)->port+(r)))
+#define csr32r(c, r) (inl((c)->port+(r)))
+#define csr8w(c, r, b) (outb((c)->port+(r), (u8int)(b)))
+#define csr16w(c, r, w) (outs((c)->port+(r), (u16int)(w)))
+#define csr32w(c, r, l) (outl((c)->port+(r), (u32int)(l)))
+
+static int
+rtl8169miimir(Mii* mii, int pa, int ra)
+{
+ uint r;
+ int timeo;
+ Ctlr *ctlr;
+
+ if(pa != 1)
+ return -1;
+ ctlr = mii->ctlr;
+
+ r = (ra<<16) & RegaddrMASK;
+ csr32w(ctlr, Phyar, r);
+ delay(1);
+ for(timeo = 0; timeo < 2000; timeo++){
+ if((r = csr32r(ctlr, Phyar)) & Flag)
+ break;
+ microdelay(100);
+ }
+ if(!(r & Flag))
+ return -1;
+
+ return (r & DataMASK)>>DataSHIFT;
+}
+
+static int
+rtl8169miimiw(Mii* mii, int pa, int ra, int data)
+{
+ uint r;
+ int timeo;
+ Ctlr *ctlr;
+
+ if(pa != 1)
+ return -1;
+ ctlr = mii->ctlr;
+
+ r = Flag|((ra<<16) & RegaddrMASK)|((data<<DataSHIFT) & DataMASK);
+ csr32w(ctlr, Phyar, r);
+ delay(1);
+ for(timeo = 0; timeo < 2000; timeo++){
+ if(!((r = csr32r(ctlr, Phyar)) & Flag))
+ break;
+ microdelay(100);
+ }
+ if(r & Flag)
+ return -1;
+
+ return 0;
+}
+
+static int
+rtl8169mii(Ctlr* ctlr)
+{
+ MiiPhy *phy;
+
+ /*
+ * Link management.
+ */
+ if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+ return -1;
+ ctlr->mii->mir = rtl8169miimir;
+ ctlr->mii->miw = rtl8169miimiw;
+ ctlr->mii->ctlr = ctlr;
+
+ /*
+ * Get rev number out of Phyidr2 so can config properly.
+ * There's probably more special stuff for Macv0[234] needed here.
+ */
+ ctlr->phyv = rtl8169miimir(ctlr->mii, 1, Phyidr2) & 0x0F;
+ if(ctlr->macv == Macv02){
+ csr8w(ctlr, 0x82, 1); /* magic */
+ rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000); /* magic */
+ }
+
+ if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil){
+ free(ctlr->mii);
+ ctlr->mii = nil;
+ return -1;
+ }
+ print("oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n",
+ phy->oui, phy->phyno, ctlr->macv, ctlr->phyv);
+
+ miiane(ctlr->mii, ~0, ~0, ~0);
+
+ return 0;
+}
+
+static void
+rtl8169promiscuous(void* arg, int on)
+{
+ Ether *edev;
+ Ctlr * ctlr;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+ ilock(&ctlr->ilock);
+
+ if(on)
+ ctlr->rcr |= Aap;
+ else
+ ctlr->rcr &= ~Aap;
+ csr32w(ctlr, Rcr, ctlr->rcr);
+ iunlock(&ctlr->ilock);
+}
+
+enum {
+ /* everyone else uses 0x04c11db7, but they both produce the same crc */
+ Etherpolybe = 0x04c11db6,
+ Bytemask = (1<<8) - 1,
+};
+
+static ulong
+ethercrcbe(uchar *addr, long len)
+{
+ int i, j;
+ ulong c, crc, carry;
+
+ crc = ~0UL;
+ for (i = 0; i < len; i++) {
+ c = addr[i];
+ for (j = 0; j < 8; j++) {
+ carry = ((crc & (1UL << 31))? 1: 0) ^ (c & 1);
+ crc <<= 1;
+ c >>= 1;
+ if (carry)
+ crc = (crc ^ Etherpolybe) | carry;
+ }
+ }
+ return crc;
+}
+
+static ulong
+swabl(ulong l)
+{
+ return l>>24 | (l>>8) & (Bytemask<<8) |
+ (l<<8) & (Bytemask<<16) | l<<24;
+}
+
+static void
+rtl8169multicast(void* ether, uchar *eaddr, int add)
+{
+ Ether *edev;
+ Ctlr *ctlr;
+
+ if (!add)
+ return; /* ok to keep receiving on old mcast addrs */
+
+ edev = ether;
+ ctlr = edev->ctlr;
+ ilock(&ctlr->ilock);
+
+ ctlr->mchash |= 1ULL << (ethercrcbe(eaddr, Eaddrlen) >> 26);
+
+ ctlr->rcr |= Am;
+ csr32w(ctlr, Rcr, ctlr->rcr);
+
+ /* pci-e variants reverse the order of the hash byte registers */
+ if (ctlr->pcie) {
+ csr32w(ctlr, Mar0, swabl(ctlr->mchash>>32));
+ csr32w(ctlr, Mar0+4, swabl(ctlr->mchash));
+ } else {
+ csr32w(ctlr, Mar0, ctlr->mchash);
+ csr32w(ctlr, Mar0+4, ctlr->mchash>>32);
+ }
+
+ iunlock(&ctlr->ilock);
+}
+
+static long
+rtl8169ifstat(Ether* edev, void* a, long n, ulong offset)
+{
+ char *p;
+ Ctlr *ctlr;
+ Dtcc *dtcc;
+ int i, l, r, timeo;
+
+ ctlr = edev->ctlr;
+ qlock(&ctlr->slock);
+
+ p = nil;
+ if(waserror()){
+ qunlock(&ctlr->slock);
+ free(p);
+ nexterror();
+ }
+
+ csr32w(ctlr, Dtccr+4, 0);
+ csr32w(ctlr, Dtccr, PCIWADDR(ctlr->dtcc)|Cmd);
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!(csr32r(ctlr, Dtccr) & Cmd))
+ break;
+ delay(1);
+ }
+ if(csr32r(ctlr, Dtccr) & Cmd)
+ error(Eio);
+ dtcc = ctlr->dtcc;
+
+ edev->oerrs = dtcc->txer;
+ edev->crcs = dtcc->rxer;
+ edev->frames = dtcc->fae;
+ edev->buffs = dtcc->misspkt;
+ edev->overflows = ctlr->txdu+ctlr->rdu;
+
+ if(n == 0){
+ qunlock(&ctlr->slock);
+ poperror();
+ return 0;
+ }
+
+ if((p = malloc(READSTR)) == nil)
+ error(Enomem);
+
+ l = snprint(p, READSTR, "TxOk: %llud\n", dtcc->txok);
+ l += snprint(p+l, READSTR-l, "RxOk: %llud\n", dtcc->rxok);
+ l += snprint(p+l, READSTR-l, "TxEr: %llud\n", dtcc->txer);
+ l += snprint(p+l, READSTR-l, "RxEr: %ud\n", dtcc->rxer);
+ l += snprint(p+l, READSTR-l, "MissPkt: %ud\n", dtcc->misspkt);
+ l += snprint(p+l, READSTR-l, "FAE: %ud\n", dtcc->fae);
+ l += snprint(p+l, READSTR-l, "Tx1Col: %ud\n", dtcc->tx1col);
+ l += snprint(p+l, READSTR-l, "TxMCol: %ud\n", dtcc->txmcol);
+ l += snprint(p+l, READSTR-l, "RxOkPh: %llud\n", dtcc->rxokph);
+ l += snprint(p+l, READSTR-l, "RxOkBrd: %llud\n", dtcc->rxokbrd);
+ l += snprint(p+l, READSTR-l, "RxOkMu: %ud\n", dtcc->rxokmu);
+ l += snprint(p+l, READSTR-l, "TxAbt: %ud\n", dtcc->txabt);
+ l += snprint(p+l, READSTR-l, "TxUndrn: %ud\n", dtcc->txundrn);
+
+ l += snprint(p+l, READSTR-l, "txdu: %ud\n", ctlr->txdu);
+ l += snprint(p+l, READSTR-l, "tcpf: %ud\n", ctlr->tcpf);
+ l += snprint(p+l, READSTR-l, "udpf: %ud\n", ctlr->udpf);
+ l += snprint(p+l, READSTR-l, "ipf: %ud\n", ctlr->ipf);
+ l += snprint(p+l, READSTR-l, "fovf: %ud\n", ctlr->fovf);
+ l += snprint(p+l, READSTR-l, "ierrs: %ud\n", ctlr->ierrs);
+ l += snprint(p+l, READSTR-l, "rer: %ud\n", ctlr->rer);
+ l += snprint(p+l, READSTR-l, "rdu: %ud\n", ctlr->rdu);
+ 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, "multicast: %ud\n", ctlr->mcast);
+
+ if(ctlr->mii != nil && ctlr->mii->curphy != nil){
+ l += snprint(p+l, READSTR, "phy: ");
+ for(i = 0; i < NMiiPhyr; i++){
+ 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);
+ }
+ snprint(p+l, READSTR-l, "\n");
+ }
+
+ n = readstr(offset, a, n, p);
+
+ qunlock(&ctlr->slock);
+ poperror();
+ free(p);
+
+ return n;
+}
+
+static void
+rtl8169halt(Ctlr* ctlr)
+{
+ csr8w(ctlr, Cr, 0);
+ csr16w(ctlr, Imr, 0);
+ csr16w(ctlr, Isr, ~0);
+}
+
+static int
+rtl8169reset(Ctlr* ctlr)
+{
+ u32int r;
+ int timeo;
+
+ /*
+ * Soft reset the controller.
+ */
+ csr8w(ctlr, Cr, Rst);
+ for(r = timeo = 0; timeo < 1000; timeo++){
+ r = csr8r(ctlr, Cr);
+ if(!(r & Rst))
+ break;
+ delay(1);
+ }
+ rtl8169halt(ctlr);
+
+ if(r & Rst)
+ return -1;
+ return 0;
+}
+
+static void
+rtl8169replenish(Ctlr* ctlr)
+{
+ D *d;
+ int rdt;
+ Block *bp;
+
+ rdt = ctlr->rdt;
+ while(NEXT(rdt, ctlr->nrd) != ctlr->rdh){
+ d = &ctlr->rd[rdt];
+ if(ctlr->rb[rdt] == nil){
+ /*
+ * Simple allocation for now.
+ * This better be aligned on 8.
+ */
+ bp = iallocb(Mps);
+ if(bp == nil){
+ iprint("no available buffers\n");
+ break;
+ }
+ ctlr->rb[rdt] = bp;
+ d->addrlo = PCIWADDR(bp->rp);
+ d->addrhi = 0;
+ coherence();
+ }else
+ iprint("i8169: rx overrun\n");
+ d->control |= Own|Mps;
+ rdt = NEXT(rdt, ctlr->nrd);
+ ctlr->nrdfree++;
+ }
+ ctlr->rdt = rdt;
+}
+
+static int
+rtl8169init(Ether* edev)
+{
+ int i;
+ u32int r;
+ Block *bp;
+ Ctlr *ctlr;
+ u8int cplusc;
+
+ ctlr = edev->ctlr;
+ ilock(&ctlr->ilock);
+
+ rtl8169halt(ctlr);
+
+ /*
+ * MAC Address is not settable on some (all?) chips.
+ * Must put chip into config register write enable mode.
+ */
+ csr8w(ctlr, Cr9346, Eem1|Eem0);
+
+ /*
+ * Transmitter.
+ */
+ memset(ctlr->td, 0, sizeof(D)*ctlr->ntd);
+ ctlr->tdh = ctlr->tdt = 0;
+ ctlr->td[ctlr->ntd-1].control = Eor;
+
+ /*
+ * Receiver.
+ * Need to do something here about the multicast filter.
+ */
+ memset(ctlr->rd, 0, sizeof(D)*ctlr->nrd);
+ ctlr->nrdfree = ctlr->rdh = ctlr->rdt = 0;
+ ctlr->rd[ctlr->nrd-1].control = Eor;
+
+ for(i = 0; i < ctlr->nrd; i++)
+ if((bp = ctlr->rb[i]) != nil){
+ ctlr->rb[i] = nil;
+ freeb(bp);
+ }
+ rtl8169replenish(ctlr);
+ ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Am|Apm;
+
+ /*
+ * Setting Mulrw in Cplusc disables the Tx/Rx DMA burst
+ * settings in Tcr/Rcr; the (1<<14) is magic.
+ */
+ cplusc = csr16r(ctlr, Cplusc) & ~(1<<14);
+ cplusc |= /*Rxchksum|*/Mulrw;
+ switch(ctlr->macv){
+ default:
+ panic("ether8169: unknown macv %#08ux for vid %#ux did %#ux",
+ ctlr->macv, ctlr->pcidev->vid, ctlr->pcidev->did);
+ case Macv01:
+ break;
+ case Macv02:
+ case Macv03:
+ cplusc |= 1<<14; /* magic */
+ break;
+ case Macv05:
+ /*
+ * This is interpreted from clearly bogus code
+ * in the manufacturer-supplied driver, it could
+ * be wrong. Untested.
+ */
+ r = csr8r(ctlr, Config2) & 0x07;
+ if(r == 0x01) /* 66MHz PCI */
+ csr32w(ctlr, 0x7C, 0x0007FFFF); /* magic */
+ else
+ csr32w(ctlr, 0x7C, 0x0007FF00); /* magic */
+ pciclrmwi(ctlr->pcidev);
+ break;
+ case Macv13:
+ /*
+ * This is interpreted from clearly bogus code
+ * in the manufacturer-supplied driver, it could
+ * be wrong. Untested.
+ */
+ pcicfgw8(ctlr->pcidev, 0x68, 0x00); /* magic */
+ pcicfgw8(ctlr->pcidev, 0x69, 0x08); /* magic */
+ break;
+ case Macv04:
+ case Macv07:
+ case Macv07a:
+ case Macv11:
+ case Macv12:
+ case Macv12a:
+ case Macv14:
+ case Macv15:
+ case Macv25:
+ break;
+ }
+
+ /*
+ * Enable receiver/transmitter.
+ * Need to do this first or some of the settings below
+ * won't take.
+ */
+ switch(ctlr->pciv){
+ default:
+ csr8w(ctlr, Cr, Te|Re);
+ csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
+ csr32w(ctlr, Rcr, ctlr->rcr);
+ csr32w(ctlr, Mar0, 0);
+ csr32w(ctlr, Mar0+4, 0);
+ ctlr->mchash = 0;
+ case Rtl8169sc:
+ case Rtl8168b:
+ break;
+ }
+
+ /*
+ * Interrupts.
+ * Disable Tdu|Tok for now, the transmit routine will tidy.
+ * Tdu means the NIC ran out of descriptors to send, so it
+ * doesn't really need to ever be on.
+ */
+ csr32w(ctlr, Timerint, 0);
+ ctlr->imr = Serr|Timeout|Fovw|Punlc|Rdu|Ter|Rer|Rok;
+ csr16w(ctlr, Imr, ctlr->imr);
+
+ /*
+ * Clear missed-packet counter;
+ * clear early transmit threshold value;
+ * set the descriptor ring base addresses;
+ * set the maximum receive packet size;
+ * no early-receive interrupts.
+ *
+ * note: the maximum rx size is a filter. the size of the buffer
+ * in the descriptor ring is still honored. we will toss >Mtu
+ * packets because they've been fragmented into multiple
+ * rx buffers.
+ */
+ csr32w(ctlr, Mpc, 0);
+ csr8w(ctlr, Etx, 0x3f); /* magic */
+ csr32w(ctlr, Tnpds+4, 0);
+ csr32w(ctlr, Tnpds, PCIWADDR(ctlr->td));
+ csr32w(ctlr, Rdsar+4, 0);
+ csr32w(ctlr, Rdsar, PCIWADDR(ctlr->rd));
+ csr16w(ctlr, Rms, 16383); /* was Mps; see above comment */
+ r = csr16r(ctlr, Mulint) & 0xF000; /* no early rx interrupts */
+ csr16w(ctlr, Mulint, r);
+ csr16w(ctlr, Cplusc, cplusc);
+ csr16w(ctlr, Coal, 0);
+
+ /*
+ * Set configuration.
+ */
+ switch(ctlr->pciv){
+ case Rtl8169sc:
+ csr8w(ctlr, Cr, Te|Re);
+ csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
+ csr32w(ctlr, Rcr, ctlr->rcr);
+ break;
+ case Rtl8168b:
+ case Rtl8169c:
+ csr16w(ctlr, Cplusc, 0x2000); /* magic */
+ csr8w(ctlr, Cr, Te|Re);
+ csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
+ csr32w(ctlr, Rcr, ctlr->rcr);
+ break;
+ }
+ ctlr->tcr = csr32r(ctlr, Tcr);
+ csr8w(ctlr, Cr9346, 0);
+
+ iunlock(&ctlr->ilock);
+
+// rtl8169mii(ctlr);
+
+ return 0;
+}
+
+static void
+rtl8169attach(Ether* edev)
+{
+ int timeo;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ qlock(&ctlr->alock);
+ if(ctlr->init == 0){
+ /*
+ * Handle allocation/init errors here.
+ */
+ ctlr->td = mallocalign(sizeof(D)*Ntd, 256, 0, 0);
+ ctlr->tb = malloc(Ntd*sizeof(Block*));
+ ctlr->ntd = Ntd;
+ ctlr->rd = mallocalign(sizeof(D)*Nrd, 256, 0, 0);
+ ctlr->rb = malloc(Nrd*sizeof(Block*));
+ ctlr->nrd = Nrd;
+ ctlr->dtcc = mallocalign(sizeof(Dtcc), 64, 0, 0);
+ rtl8169init(edev);
+ ctlr->init = 1;
+ }
+ qunlock(&ctlr->alock);
+
+ /*
+ * Wait for link to be ready.
+ */
+ for(timeo = 0; timeo < 35; timeo++){
+ if(miistatus(ctlr->mii) == 0)
+ break;
+ delay(100); /* print fewer miistatus messages */
+ }
+}
+
+static void
+rtl8169link(Ether* edev)
+{
+ uint r;
+ int limit;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+
+ /*
+ * Maybe the link changed - do we care very much?
+ * Could stall transmits if no link, maybe?
+ */
+ if(!((r = csr8r(ctlr, Phystatus)) & Linksts)){
+ edev->link = 0;
+ return;
+ }
+ edev->link = 1;
+
+ limit = 256*1024;
+ if(r & Speed10){
+ edev->mbps = 10;
+ limit = 65*1024;
+ } else if(r & Speed100)
+ edev->mbps = 100;
+ else if(r & Speed1000)
+ edev->mbps = 1000;
+
+ if(edev->oq != nil)
+ qsetlimit(edev->oq, limit);
+}
+
+static void
+rtl8169transmit(Ether* edev)
+{
+ D *d;
+ Block *bp;
+ Ctlr *ctlr;
+ int control, x;
+
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->tlock);
+ for(x = ctlr->tdh; ctlr->ntq > 0; x = NEXT(x, ctlr->ntd)){
+ d = &ctlr->td[x];
+ if((control = d->control) & Own)
+ break;
+
+ /*
+ * Check errors and log here.
+ */
+ USED(control);
+
+ /*
+ * Free it up.
+ * Need to clean the descriptor here? Not really.
+ * Simple freeb for now (no chain and freeblist).
+ * Use ntq count for now.
+ */
+ freeb(ctlr->tb[x]);
+ ctlr->tb[x] = nil;
+ d->control &= Eor;
+
+ ctlr->ntq--;
+ }
+ ctlr->tdh = x;
+
+ x = ctlr->tdt;
+ while(ctlr->ntq < (ctlr->ntd-1)){
+ if((bp = qget(edev->oq)) == nil)
+ break;
+
+ d = &ctlr->td[x];
+ d->addrlo = PCIWADDR(bp->rp);
+ d->addrhi = 0;
+ ctlr->tb[x] = bp;
+ coherence();
+ d->control |= Own | Fs | Ls | BLEN(bp);
+
+ x = NEXT(x, ctlr->ntd);
+ ctlr->ntq++;
+ }
+ if(x != ctlr->tdt){
+ ctlr->tdt = x;
+ csr8w(ctlr, Tppoll, Npq);
+ }
+ else if(ctlr->ntq >= (ctlr->ntd-1))
+ ctlr->txdu++;
+
+ iunlock(&ctlr->tlock);
+}
+
+static void
+rtl8169receive(Ether* edev)
+{
+ D *d;
+ int rdh;
+ Block *bp;
+ Ctlr *ctlr;
+ u32int control;
+
+ ctlr = edev->ctlr;
+
+ rdh = ctlr->rdh;
+ for(;;){
+ d = &ctlr->rd[rdh];
+
+ if(d->control & Own)
+ break;
+
+ control = d->control;
+ if((control & (Fs|Ls|Res)) == (Fs|Ls)){
+ bp = ctlr->rb[rdh];
+ bp->wp = bp->rp + (control & RxflMASK) - 4;
+
+ if(control & Fovf)
+ ctlr->fovf++;
+ if(control & Mar)
+ ctlr->mcast++;
+
+ switch(control & (Pid1|Pid0)){
+ default:
+ break;
+ case Pid0:
+ if(control & Tcpf){
+ ctlr->tcpf++;
+ break;
+ }
+ bp->flag |= Btcpck;
+ break;
+ case Pid1:
+ if(control & Udpf){
+ ctlr->udpf++;
+ break;
+ }
+ bp->flag |= Budpck;
+ break;
+ case Pid1|Pid0:
+ if(control & Ipf){
+ ctlr->ipf++;
+ break;
+ }
+ bp->flag |= Bipck;
+ break;
+ }
+ etheriq(edev, bp, 1);
+ }else{
+ if(!(control & Res))
+ ctlr->frag++;
+ /* iprint("i8169: control %#.8ux\n", control); */
+ freeb(ctlr->rb[rdh]);
+ }
+ ctlr->rb[rdh] = nil;
+ d->control &= Eor;
+ ctlr->nrdfree--;
+ rdh = NEXT(rdh, ctlr->nrd);
+
+ if(ctlr->nrdfree < ctlr->nrd/2)
+ rtl8169replenish(ctlr);
+ }
+ ctlr->rdh = rdh;
+}
+
+static void
+rtl8169interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Ether *edev;
+ u32int isr;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ while((isr = csr16r(ctlr, Isr)) != 0 && isr != 0xFFFF){
+ csr16w(ctlr, Isr, isr);
+ if((isr & ctlr->imr) == 0)
+ break;
+ if(isr & (Fovw|Punlc|Rdu|Rer|Rok)){
+ rtl8169receive(edev);
+ if(!(isr & (Punlc|Rok)))
+ ctlr->ierrs++;
+ if(isr & Rer)
+ ctlr->rer++;
+ if(isr & Rdu)
+ ctlr->rdu++;
+ if(isr & Punlc)
+ ctlr->punlc++;
+ if(isr & Fovw)
+ ctlr->fovw++;
+ isr &= ~(Fovw|Rdu|Rer|Rok);
+ }
+
+ if(isr & (Tdu|Ter|Tok)){
+ rtl8169transmit(edev);
+ isr &= ~(Tdu|Ter|Tok);
+ }
+
+ if(isr & Punlc){
+ rtl8169link(edev);
+ isr &= ~Punlc;
+ }
+
+ /*
+ * 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",
+ csr16r(ctlr, Imr), isr);
+ }
+}
+
+int
+vetmacv(Ctlr *ctlr, uint *macv)
+{
+ *macv = csr32r(ctlr, Tcr) & HwveridMASK;
+ switch(*macv){
+ default:
+ return -1;
+ case Macv01:
+ case Macv02:
+ case Macv03:
+ case Macv04:
+ case Macv05:
+ case Macv07:
+ case Macv07a:
+ case Macv11:
+ case Macv12:
+ case Macv12a:
+ case Macv13:
+ case Macv14:
+ case Macv15:
+ case Macv25:
+ break;
+ }
+ return 0;
+}
+
+static void
+rtl8169pci(void)
+{
+ Pcidev *p;
+ Ctlr *ctlr;
+ int i, port, pcie;
+ uint macv;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+
+ pcie = 0;
+ switch(i = ((p->did<<16)|p->vid)){
+ default:
+ continue;
+ case Rtl8100e: /* RTL810[01]E ? */
+ case Rtl8168b: /* RTL8168B */
+ pcie = 1;
+ break;
+ case Rtl8169c: /* RTL8169C */
+ case Rtl8169sc: /* RTL8169SC */
+ case Rtl8169: /* RTL8169 */
+ break;
+ case (0xC107<<16)|0x1259: /* Corega CG-LAPCIGT */
+ i = Rtl8169;
+ break;
+ }
+
+ port = p->mem[0].bar & ~0x01;
+ if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){
+ print("rtl8169: port %#ux in use\n", port);
+ continue;
+ }
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = port;
+ ctlr->pcidev = p;
+ ctlr->pciv = i;
+ ctlr->pcie = pcie;
+
+ if(vetmacv(ctlr, &macv) == -1){
+ iofree(port);
+ free(ctlr);
+ print("rtl8169: unknown mac %.4ux %.8ux\n", p->did, macv);
+ continue;
+ }
+
+ if(pcigetpms(p) > 0){
+ pcisetpms(p, 0);
+
+ for(i = 0; i < 6; i++)
+ pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
+ pcicfgw8(p, PciINTL, p->intl);
+ pcicfgw8(p, PciLTR, p->ltr);
+ pcicfgw8(p, PciCLS, p->cls);
+ pcicfgw16(p, PciPCR, p->pcr);
+ }
+
+ if(rtl8169reset(ctlr)){
+ iofree(port);
+ free(ctlr);
+ continue;
+ }
+
+ /*
+ * Extract the chip hardware version,
+ * needed to configure each properly.
+ */
+ ctlr->macv = macv;
+
+ rtl8169mii(ctlr);
+
+ pcisetbme(p);
+
+ if(rtl8169ctlrhead != nil)
+ rtl8169ctlrtail->next = ctlr;
+ else
+ rtl8169ctlrhead = ctlr;
+ rtl8169ctlrtail = ctlr;
+ }
+}
+
+static int
+rtl8169pnp(Ether* edev)
+{
+ u32int r;
+ Ctlr *ctlr;
+ uchar ea[Eaddrlen];
+ static int once;
+
+ if(once == 0){
+ once = 1;
+ rtl8169pci();
+ }
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = rtl8169ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+ edev->mbps = 100;
+ edev->maxmtu = Mtu;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the device and set in edev->ea.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, edev->ea, Eaddrlen) == 0){
+ r = csr32r(ctlr, Idr0);
+ edev->ea[0] = r;
+ edev->ea[1] = r>>8;
+ edev->ea[2] = r>>16;
+ edev->ea[3] = r>>24;
+ r = csr32r(ctlr, Idr0+4);
+ edev->ea[4] = r;
+ edev->ea[5] = r>>8;
+ }
+
+ edev->attach = rtl8169attach;
+ edev->transmit = rtl8169transmit;
+ edev->interrupt = rtl8169interrupt;
+ edev->ifstat = rtl8169ifstat;
+
+ edev->arg = edev;
+ edev->promiscuous = rtl8169promiscuous;
+ edev->multicast = rtl8169multicast;
+// edev->shutdown = rtl8169shutdown;
+
+ rtl8169link(edev);
+
+ return 0;
+}
+
+void
+ether8169link(void)
+{
+ addethercard("rtl8169", rtl8169pnp);
+}
diff --git a/sys/src/9/pc/ether82543gc.c b/sys/src/9/pc/ether82543gc.c
new file mode 100755
index 000000000..2079d8458
--- /dev/null
+++ b/sys/src/9/pc/ether82543gc.c
@@ -0,0 +1,1368 @@
+/*
+ * Intel RS-82543GC Gigabit Ethernet Controller
+ * as found on the Intel PRO/1000[FT] Server Adapter.
+ * The older non-[FT] cards use the 82542 (LSI L2A1157) chip; no attempt
+ * is made to handle the older chip although it should be possible.
+ * The datasheet is not very clear about running on a big-endian system
+ * and this driver assumes little-endian throughout.
+ * To do:
+ * GMII/MII
+ * receive tuning
+ * transmit tuning
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+enum {
+ Ctrl = 0x00000000, /* Device Control */
+ Status = 0x00000008, /* Device Status */
+ Eecd = 0x00000010, /* EEPROM/Flash Control/Data */
+ Ctrlext = 0x00000018, /* Extended Device Control */
+ Mdic = 0x00000020, /* MDI Control */
+ Fcal = 0x00000028, /* Flow Control Address Low */
+ Fcah = 0x0000002C, /* Flow Control Address High */
+ Fct = 0x00000030, /* Flow Control Type */
+ Icr = 0x000000C0, /* Interrupt Cause Read */
+ Ics = 0x000000C8, /* Interrupt Cause Set */
+ Ims = 0x000000D0, /* Interrupt Mask Set/Read */
+ Imc = 0x000000D8, /* Interrupt mask Clear */
+ Rctl = 0x00000100, /* Receive Control */
+ Fcttv = 0x00000170, /* Flow Control Transmit Timer Value */
+ Txcw = 0x00000178, /* Transmit configuration word reg. */
+ Rxcw = 0x00000180, /* Receive configuration word reg. */
+ Tctl = 0x00000400, /* Transmit Control */
+ Tipg = 0x00000410, /* Transmit IPG */
+ Tbt = 0x00000448, /* Transmit Burst Timer */
+ Ait = 0x00000458, /* Adaptive IFS Throttle */
+ Fcrtl = 0x00002160, /* Flow Control RX Threshold Low */
+ Fcrth = 0x00002168, /* Flow Control Rx Threshold High */
+ Rdfh = 0x00002410, /* Receive data fifo head */
+ Rdft = 0x00002418, /* Receive data fifo tail */
+ Rdfhs = 0x00002420, /* Receive data fifo head saved */
+ Rdfts = 0x00002428, /* Receive data fifo tail saved */
+ Rdfpc = 0x00002430, /* Receive data fifo packet count */
+ Rdbal = 0x00002800, /* Rdesc Base Address Low */
+ Rdbah = 0x00002804, /* Rdesc Base Address High */
+ Rdlen = 0x00002808, /* Receive Descriptor Length */
+ Rdh = 0x00002810, /* Receive Descriptor Head */
+ Rdt = 0x00002818, /* Receive Descriptor Tail */
+ Rdtr = 0x00002820, /* Receive Descriptor Timer Ring */
+ Rxdctl = 0x00002828, /* Receive Descriptor Control */
+ Txdmac = 0x00003000, /* Transfer DMA Control */
+ Ett = 0x00003008, /* Early Transmit Control */
+ Tdfh = 0x00003410, /* Transmit data fifo head */
+ Tdft = 0x00003418, /* Transmit data fifo tail */
+ Tdfhs = 0x00003420, /* Transmit data Fifo Head saved */
+ Tdfts = 0x00003428, /* Transmit data fifo tail saved */
+ Tdfpc = 0x00003430, /* Trasnmit data Fifo packet count */
+ Tdbal = 0x00003800, /* Tdesc Base Address Low */
+ Tdbah = 0x00003804, /* Tdesc Base Address High */
+ Tdlen = 0x00003808, /* Transmit Descriptor Length */
+ Tdh = 0x00003810, /* Transmit Descriptor Head */
+ Tdt = 0x00003818, /* Transmit Descriptor Tail */
+ Tidv = 0x00003820, /* Transmit Interrupt Delay Value */
+ Txdctl = 0x00003828, /* Transmit Descriptor Control */
+
+ Statistics = 0x00004000, /* Start of Statistics Area */
+ Gorcl = 0x88/4, /* Good Octets Received Count */
+ Gotcl = 0x90/4, /* Good Octets Transmitted Count */
+ Torl = 0xC0/4, /* Total Octets Received */
+ Totl = 0xC8/4, /* Total Octets Transmitted */
+ Nstatistics = 64,
+
+ Rxcsum = 0x00005000, /* Receive Checksum Control */
+ Mta = 0x00005200, /* Multicast Table Array */
+ Ral = 0x00005400, /* Receive Address Low */
+ Rah = 0x00005404, /* Receive Address High */
+};
+
+enum { /* Ctrl */
+ Bem = 0x00000002, /* Big Endian Mode */
+ Prior = 0x00000004, /* Priority on the PCI bus */
+ Lrst = 0x00000008, /* Link Reset */
+ Asde = 0x00000020, /* Auto-Speed Detection Enable */
+ Slu = 0x00000040, /* Set Link Up */
+ Ilos = 0x00000080, /* Invert Loss of Signal (LOS) */
+ Frcspd = 0x00000800, /* Force Speed */
+ Frcdplx = 0x00001000, /* Force Duplex */
+ Swdpinslo = 0x003C0000, /* Software Defined Pins - lo nibble */
+ Swdpin0 = 0x00040000,
+ Swdpin1 = 0x00080000,
+ Swdpin2 = 0x00100000,
+ Swdpin3 = 0x00200000,
+ Swdpiolo = 0x03C00000, /* Software Defined I/O Pins */
+ Swdpio0 = 0x00400000,
+ Swdpio1 = 0x00800000,
+ Swdpio2 = 0x01000000,
+ Swdpio3 = 0x02000000,
+ Devrst = 0x04000000, /* Device Reset */
+ Rfce = 0x08000000, /* Receive Flow Control Enable */
+ Tfce = 0x10000000, /* Transmit Flow Control Enable */
+ Vme = 0x40000000, /* VLAN Mode Enable */
+};
+
+enum { /* Status */
+ Lu = 0x00000002, /* Link Up */
+ Tckok = 0x00000004, /* Transmit clock is running */
+ Rbcok = 0x00000008, /* Receive clock is running */
+ Txoff = 0x00000010, /* Transmission Paused */
+ Tbimode = 0x00000020, /* TBI Mode Indication */
+ SpeedMASK = 0x000000C0,
+ Speed10 = 0x00000000, /* 10Mb/s */
+ Speed100 = 0x00000040, /* 100Mb/s */
+ Speed1000 = 0x00000080, /* 1000Mb/s */
+ Mtxckok = 0x00000400, /* MTX clock is running */
+ Pci66 = 0x00000800, /* PCI Bus speed indication */
+ Bus64 = 0x00001000, /* PCI Bus width indication */
+};
+
+enum { /* Ctrl and Status */
+ Fd = 0x00000001, /* Full-Duplex */
+ AsdvMASK = 0x00000300,
+ Asdv10 = 0x00000000, /* 10Mb/s */
+ Asdv100 = 0x00000100, /* 100Mb/s */
+ Asdv1000 = 0x00000200, /* 1000Mb/s */
+};
+
+enum { /* Eecd */
+ Sk = 0x00000001, /* Clock input to the EEPROM */
+ Cs = 0x00000002, /* Chip Select */
+ Di = 0x00000004, /* Data Input to the EEPROM */
+ Do = 0x00000008, /* Data Output from the EEPROM */
+};
+
+enum { /* Ctrlext */
+ Gpien = 0x0000000F, /* General Purpose Interrupt Enables */
+ Swdpinshi = 0x000000F0, /* Software Defined Pins - hi nibble */
+ Swdpiohi = 0x00000F00, /* Software Defined Pins - I or O */
+ Asdchk = 0x00001000, /* ASD Check */
+ Eerst = 0x00002000, /* EEPROM Reset */
+ Ips = 0x00004000, /* Invert Power State */
+ Spdbyps = 0x00008000, /* Speed Select Bypass */
+};
+
+enum { /* EEPROM content offsets */
+ Ea = 0x00, /* Ethernet Address */
+ Cf = 0x03, /* Compatibility Field */
+ Pba = 0x08, /* Printed Board Assembly number */
+ Icw1 = 0x0A, /* Initialization Control Word 1 */
+ Sid = 0x0B, /* Subsystem ID */
+ Svid = 0x0C, /* Subsystem Vendor ID */
+ Did = 0x0D, /* Device ID */
+ Vid = 0x0E, /* Vendor ID */
+ Icw2 = 0x0F, /* Initialization Control Word 2 */
+};
+
+enum { /* Mdic */
+ MDIdMASK = 0x0000FFFF, /* Data */
+ MDIdSHIFT = 0,
+ MDIrMASK = 0x001F0000, /* PHY Register Address */
+ MDIrSHIFT = 16,
+ MDIpMASK = 0x03E00000, /* PHY Address */
+ MDIpSHIFT = 21,
+ MDIwop = 0x04000000, /* Write Operation */
+ MDIrop = 0x08000000, /* Read Operation */
+ MDIready = 0x10000000, /* End of Transaction */
+ MDIie = 0x20000000, /* Interrupt Enable */
+ MDIe = 0x40000000, /* Error */
+};
+
+enum { /* Icr, Ics, Ims, Imc */
+ Txdw = 0x00000001, /* Transmit Descriptor Written Back */
+ Txqe = 0x00000002, /* Transmit Queue Empty */
+ Lsc = 0x00000004, /* Link Status Change */
+ Rxseq = 0x00000008, /* Receive Sequence Error */
+ Rxdmt0 = 0x00000010, /* Rdesc Minimum Threshold Reached */
+ Rxo = 0x00000040, /* Receiver Overrun */
+ Rxt0 = 0x00000080, /* Receiver Timer Interrupt */
+ Mdac = 0x00000200, /* MDIO Access Completed */
+ Rxcfg = 0x00000400, /* Receiving /C/ ordered sets */
+ Gpi0 = 0x00000800, /* General Purpose Interrupts */
+ Gpi1 = 0x00001000,
+ Gpi2 = 0x00002000,
+ Gpi3 = 0x00004000,
+};
+
+enum { /* Txcw */
+ Ane = 0x80000000, /* Autonegotiate enable */
+ Np = 0x00008000, /* Next Page */
+ As = 0x00000100, /* Asymmetric Flow control desired */
+ Ps = 0x00000080, /* Pause supported */
+ Hd = 0x00000040, /* Half duplex supported */
+ TxcwFd = 0x00000020, /* Full Duplex supported */
+};
+
+enum { /* Rxcw */
+ Rxword = 0x0000FFFF, /* Data from auto-negotiation process */
+ Rxnocarrier = 0x04000000, /* Carrier Sense indication */
+ Rxinvalid = 0x08000000, /* Invalid Symbol during configuration */
+ Rxchange = 0x10000000, /* Change to the Rxword indication */
+ Rxconfig = 0x20000000, /* /C/ order set reception indication */
+ Rxsync = 0x40000000, /* Lost bit synchronization indication */
+ Anc = 0x80000000, /* Auto Negotiation Complete */
+};
+
+enum { /* Rctl */
+ Rrst = 0x00000001, /* Receiver Software Reset */
+ Ren = 0x00000002, /* Receiver Enable */
+ Sbp = 0x00000004, /* Store Bad Packets */
+ Upe = 0x00000008, /* Unicast Promiscuous Enable */
+ Mpe = 0x00000010, /* Multicast Promiscuous Enable */
+ Lpe = 0x00000020, /* Long Packet Reception Enable */
+ LbmMASK = 0x000000C0, /* Loopback Mode */
+ LbmOFF = 0x00000000, /* No Loopback */
+ LbmTBI = 0x00000040, /* TBI Loopback */
+ LbmMII = 0x00000080, /* GMII/MII Loopback */
+ LbmXCVR = 0x000000C0, /* Transceiver Loopback */
+ RdtmsMASK = 0x00000300, /* Rdesc Minimum Threshold Size */
+ RdtmsHALF = 0x00000000, /* Threshold is 1/2 Rdlen */
+ RdtmsQUARTER = 0x00000100, /* Threshold is 1/4 Rdlen */
+ RdtmsEIGHTH = 0x00000200, /* Threshold is 1/8 Rdlen */
+ MoMASK = 0x00003000, /* Multicast Offset */
+ Bam = 0x00008000, /* Broadcast Accept Mode */
+ BsizeMASK = 0x00030000, /* Receive Buffer Size */
+ Bsize2048 = 0x00000000, /* Bsex = 0 */
+ Bsize1024 = 0x00010000, /* Bsex = 0 */
+ Bsize512 = 0x00020000, /* Bsex = 0 */
+ Bsize256 = 0x00030000, /* Bsex = 0 */
+ Bsize16384 = 0x00010000, /* Bsex = 1 */
+ Vfe = 0x00040000, /* VLAN Filter Enable */
+ Cfien = 0x00080000, /* Canonical Form Indicator Enable */
+ Cfi = 0x00100000, /* Canonical Form Indicator value */
+ Dpf = 0x00400000, /* Discard Pause Frames */
+ Pmcf = 0x00800000, /* Pass MAC Control Frames */
+ Bsex = 0x02000000, /* Buffer Size Extension */
+ Secrc = 0x04000000, /* Strip CRC from incoming packet */
+};
+
+enum { /* Tctl */
+ Trst = 0x00000001, /* Transmitter Software Reset */
+ Ten = 0x00000002, /* Transmit Enable */
+ Psp = 0x00000008, /* Pad Short Packets */
+ CtMASK = 0x00000FF0, /* Collision Threshold */
+ CtSHIFT = 4,
+ ColdMASK = 0x003FF000, /* Collision Distance */
+ ColdSHIFT = 12,
+ Swxoff = 0x00400000, /* Sofware XOFF Transmission */
+ Pbe = 0x00800000, /* Packet Burst Enable */
+ Rtlc = 0x01000000, /* Re-transmit on Late Collision */
+ Nrtu = 0x02000000, /* No Re-transmit on Underrrun */
+};
+
+enum { /* [RT]xdctl */
+ PthreshMASK = 0x0000003F, /* Prefetch Threshold */
+ PthreshSHIFT = 0,
+ HthreshMASK = 0x00003F00, /* Host Threshold */
+ HthreshSHIFT = 8,
+ WthreshMASK = 0x003F0000, /* Writeback Threshold */
+ WthreshSHIFT = 16,
+ Gran = 0x00000000, /* Granularity */
+ RxGran = 0x01000000, /* Granularity */
+};
+
+enum { /* Rxcsum */
+ PcssMASK = 0x000000FF, /* Packet Checksum Start */
+ PcssSHIFT = 0,
+ Ipofl = 0x00000100, /* IP Checksum Off-load Enable */
+ Tuofl = 0x00000200, /* TCP/UDP Checksum Off-load Enable */
+};
+
+enum { /* Receive Delay Timer Ring */
+ Fpd = 0x80000000, /* Flush partial Descriptor Block */
+};
+
+typedef struct Rdesc { /* Receive Descriptor */
+ uint addr[2];
+ ushort length;
+ ushort checksum;
+ uchar status;
+ uchar errors;
+ ushort special;
+} Rdesc;
+
+enum { /* Rdesc status */
+ Rdd = 0x01, /* Descriptor Done */
+ Reop = 0x02, /* End of Packet */
+ Ixsm = 0x04, /* Ignore Checksum Indication */
+ Vp = 0x08, /* Packet is 802.1Q (matched VET) */
+ Tcpcs = 0x20, /* TCP Checksum Calculated on Packet */
+ Ipcs = 0x40, /* IP Checksum Calculated on Packet */
+ Pif = 0x80, /* Passed in-exact filter */
+};
+
+enum { /* Rdesc errors */
+ Ce = 0x01, /* CRC Error or Alignment Error */
+ Se = 0x02, /* Symbol Error */
+ Seq = 0x04, /* Sequence Error */
+ Cxe = 0x10, /* Carrier Extension Error */
+ Tcpe = 0x20, /* TCP/UDP Checksum Error */
+ Ipe = 0x40, /* IP Checksum Error */
+ Rxe = 0x80, /* RX Data Error */
+};
+
+typedef struct Tdesc { /* Legacy+Normal Transmit Descriptor */
+ uint addr[2];
+ uint control; /* varies with descriptor type */
+ uint status; /* varies with descriptor type */
+} Tdesc;
+
+enum { /* Tdesc control */
+ CsoMASK = 0x00000F00, /* Checksum Offset */
+ CsoSHIFT = 16,
+ Teop = 0x01000000, /* End of Packet */
+ Ifcs = 0x02000000, /* Insert FCS */
+ Ic = 0x04000000, /* Insert Checksum (Dext == 0) */
+ Tse = 0x04000000, /* TCP Segmentaion Enable (Dext == 1) */
+ Rs = 0x08000000, /* Report Status */
+ Rps = 0x10000000, /* Report Status Sent */
+ Dext = 0x20000000, /* Extension (!legacy) */
+ Vle = 0x40000000, /* VLAN Packet Enable */
+ Ide = 0x80000000, /* Interrupt Delay Enable */
+};
+
+enum { /* Tdesc status */
+ Tdd = 0x00000001, /* Descriptor Done */
+ Ec = 0x00000002, /* Excess Collisions */
+ Lc = 0x00000004, /* Late Collision */
+ Tu = 0x00000008, /* Transmit Underrun */
+ CssMASK = 0x0000FF00, /* Checksum Start Field */
+ CssSHIFT = 8,
+};
+
+enum {
+ Nrdesc = 256, /* multiple of 8 */
+ Ntdesc = 256, /* multiple of 8 */
+ Nblocks = 4098, /* total number of blocks to use */
+
+ SBLOCKSIZE = 2048,
+ JBLOCKSIZE = 16384,
+
+ NORMAL = 1,
+ JUMBO = 2,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int started;
+ int id;
+ ushort eeprom[0x40];
+
+ int* nic;
+ int im; /* interrupt mask */
+
+ Lock slock;
+ uint statistics[Nstatistics];
+
+ Lock rdlock;
+ Rdesc* rdba; /* receive descriptor base address */
+ Block* rb[Nrdesc]; /* receive buffers */
+ int rdh; /* receive descriptor head */
+ int rdt; /* receive descriptor tail */
+ Block** freehead; /* points to long or short head */
+
+ Lock tdlock;
+ Tdesc* tdba; /* transmit descriptor base address */
+ Block* tb[Ntdesc]; /* transmit buffers */
+ int tdh; /* transmit descriptor head */
+ int tdt; /* transmit descriptor tail */
+ int txstalled; /* count of times unable to send */
+
+ int txcw;
+ int fcrtl;
+ int fcrth;
+
+ ulong multimask[128]; /* bit mask for multicast addresses */
+} Ctlr;
+
+static Ctlr* gc82543ctlrhead;
+static Ctlr* gc82543ctlrtail;
+
+static Lock freelistlock;
+static Block* freeShortHead;
+static Block* freeJumboHead;
+
+#define csr32r(c, r) (*((c)->nic+((r)/4)))
+#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
+
+static void gc82543watchdog(void* arg);
+
+static void
+gc82543attach(Ether* edev)
+{
+ int ctl;
+ Ctlr *ctlr;
+ char name[KNAMELEN];
+
+ /*
+ * To do here:
+ * one-time stuff;
+ * adjust queue length depending on speed;
+ * flow control.
+ * more needed here...
+ */
+ ctlr = edev->ctlr;
+ lock(&ctlr->slock);
+ if(ctlr->started == 0){
+ ctlr->started = 1;
+ snprint(name, KNAMELEN, "#l%d82543", edev->ctlrno);
+ kproc(name, gc82543watchdog, edev);
+ }
+ unlock(&ctlr->slock);
+
+ ctl = csr32r(ctlr, Rctl)|Ren;
+ csr32w(ctlr, Rctl, ctl);
+ ctl = csr32r(ctlr, Tctl)|Ten;
+ csr32w(ctlr, Tctl, ctl);
+
+ csr32w(ctlr, Ims, ctlr->im);
+}
+
+static char* statistics[Nstatistics] = {
+ "CRC Error",
+ "Alignment Error",
+ "Symbol Error",
+ "RX Error",
+ "Missed Packets",
+ "Single Collision",
+ "Excessive Collisions",
+ "Multiple Collision",
+ "Late Collisions",
+ nil,
+ "Collision",
+ "Transmit Underrun",
+ "Defer",
+ "Transmit - No CRS",
+ "Sequence Error",
+ "Carrier Extension Error",
+ "Receive Error Length",
+ nil,
+ "XON Received",
+ "XON Transmitted",
+ "XOFF Received",
+ "XOFF Transmitted",
+ "FC Received Unsupported",
+ "Packets Received (64 Bytes)",
+ "Packets Received (65-127 Bytes)",
+ "Packets Received (128-255 Bytes)",
+ "Packets Received (256-511 Bytes)",
+ "Packets Received (512-1023 Bytes)",
+ "Packets Received (1024-1522 Bytes)",
+ "Good Packets Received",
+ "Broadcast Packets Received",
+ "Multicast Packets Received",
+ "Good Packets Transmitted",
+ nil,
+ "Good Octets Received",
+ nil,
+ "Good Octets Transmitted",
+ nil,
+ nil,
+ nil,
+ "Receive No Buffers",
+ "Receive Undersize",
+ "Receive Fragment",
+ "Receive Oversize",
+ "Receive Jabber",
+ nil,
+ nil,
+ nil,
+ "Total Octets Received",
+ nil,
+ "Total Octets Transmitted",
+ nil,
+ "Total Packets Received",
+ "Total Packets Transmitted",
+ "Packets Transmitted (64 Bytes)",
+ "Packets Transmitted (65-127 Bytes)",
+ "Packets Transmitted (128-255 Bytes)",
+ "Packets Transmitted (256-511 Bytes)",
+ "Packets Transmitted (512-1023 Bytes)",
+ "Packets Transmitted (1024-1522 Bytes)",
+ "Multicast Packets Transmitted",
+ "Broadcast Packets Transmitted",
+ "TCP Segmentation Context Transmitted",
+ "TCP Segmentation Context Fail",
+};
+
+static long
+gc82543ifstat(Ether* edev, void* a, long n, ulong offset)
+{
+ Ctlr *ctlr;
+ char *p, *s;
+ int i, l, r;
+ uvlong tuvl, ruvl;
+
+ ctlr = edev->ctlr;
+ lock(&ctlr->slock);
+ p = malloc(READSTR);
+ l = 0;
+ for(i = 0; i < Nstatistics; i++){
+ r = csr32r(ctlr, Statistics+i*4);
+ if((s = statistics[i]) == nil)
+ continue;
+ switch(i){
+ case Gorcl:
+ case Gotcl:
+ case Torl:
+ case Totl:
+ ruvl = r;
+ ruvl += ((uvlong)csr32r(ctlr, Statistics+(i+1)*4))<<32;
+ tuvl = ruvl;
+ tuvl += ctlr->statistics[i];
+ tuvl += ((uvlong)ctlr->statistics[i+1])<<32;
+ if(tuvl == 0)
+ continue;
+ ctlr->statistics[i] = tuvl;
+ ctlr->statistics[i+1] = tuvl>>32;
+ l += snprint(p+l, READSTR-l, "%s: %llud %llud\n",
+ s, tuvl, ruvl);
+ i++;
+ break;
+
+ default:
+ ctlr->statistics[i] += r;
+ if(ctlr->statistics[i] == 0)
+ continue;
+ l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
+ s, ctlr->statistics[i], r);
+ break;
+ }
+ }
+
+ l += snprint(p+l, READSTR-l, "eeprom:");
+ for(i = 0; i < 0x40; i++){
+ if(i && ((i & 0x07) == 0))
+ l += snprint(p+l, READSTR-l, "\n ");
+ l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
+ }
+
+ snprint(p+l, READSTR-l, "\ntxstalled %d\n", ctlr->txstalled);
+ n = readstr(offset, a, n, p);
+ free(p);
+ unlock(&ctlr->slock);
+
+ return n;
+}
+
+static void
+gc82543promiscuous(void* arg, int on)
+{
+ int rctl;
+ Ctlr *ctlr;
+ Ether *edev;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ rctl = csr32r(ctlr, Rctl);
+ rctl &= ~MoMASK; /* make sure we're using bits 47:36 */
+ if(on)
+ rctl |= Upe|Mpe;
+ else
+ rctl &= ~(Upe|Mpe);
+ csr32w(ctlr, Rctl, rctl);
+}
+
+static void
+gc82543multicast(void* arg, uchar* addr, int on)
+{
+ int bit, x;
+ Ctlr *ctlr;
+ Ether *edev;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+ x = addr[5]>>1;
+ bit = ((addr[5] & 1)<<4)|(addr[4]>>4);
+ if(on)
+ ctlr->multimask[x] |= 1<<bit;
+ else
+ ctlr->multimask[x] &= ~(1<<bit);
+
+ csr32w(ctlr, Mta+x*4, ctlr->multimask[x]);
+}
+
+static long
+gc82543ctl(Ether* edev, void* buf, long n)
+{
+ Cmdbuf *cb;
+ Ctlr *ctlr;
+ int ctrl, i, r;
+
+ ctlr = edev->ctlr;
+ if(ctlr == nil)
+ error(Enonexist);
+
+ lock(&ctlr->slock);
+ r = 0;
+ cb = parsecmd(buf, n);
+ if(cb->nf < 2)
+ r = -1;
+ else if(cistrcmp(cb->f[0], "auto") == 0){
+ ctrl = csr32r(ctlr, Ctrl);
+ if(cistrcmp(cb->f[1], "off") == 0){
+ csr32w(ctlr, Txcw, ctlr->txcw & ~Ane);
+ ctrl |= (Slu|Fd);
+ if(ctlr->txcw & As)
+ ctrl |= Rfce;
+ if(ctlr->txcw & Ps)
+ ctrl |= Tfce;
+ csr32w(ctlr, Ctrl, ctrl);
+ }
+ else if(cistrcmp(cb->f[1], "on") == 0){
+ csr32w(ctlr, Txcw, ctlr->txcw);
+ ctrl &= ~(Slu|Fd);
+ csr32w(ctlr, Ctrl, ctrl);
+ }
+ else
+ r = -1;
+ }
+ else if(cistrcmp(cb->f[0], "clear") == 0){
+ if(cistrcmp(cb->f[1], "stats") == 0){
+ for(i = 0; i < Nstatistics; i++)
+ ctlr->statistics[i] = 0;
+ }
+ else
+ r = -1;
+ }
+ else
+ r = -1;
+ unlock(&ctlr->slock);
+
+ free(cb);
+ return (r == 0) ? n : r;
+}
+
+static void
+gc82543txinit(Ctlr* ctlr)
+{
+ int i;
+ int tdsize;
+ Block *bp, **bpp;
+
+ tdsize = ROUND(Ntdesc*sizeof(Tdesc), 4096);
+
+ if(ctlr->tdba == nil)
+ ctlr->tdba = xspanalloc(tdsize, 32, 0);
+
+ for(i = 0; i < Ntdesc; i++){
+ bpp = &ctlr->tb[i];
+ bp = *bpp;
+ if(bp != nil){
+ *bpp = nil;
+ freeb(bp);
+ }
+ memset(&ctlr->tdba[i], 0, sizeof(Tdesc));
+ }
+
+ csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
+ csr32w(ctlr, Tdbah, 0);
+ csr32w(ctlr, Tdlen, Ntdesc*sizeof(Tdesc));
+
+ /*
+ * set the ring head and tail pointers.
+ */
+ ctlr->tdh = 0;
+ csr32w(ctlr, Tdh, ctlr->tdh);
+ ctlr->tdt = 0;
+ csr32w(ctlr, Tdt, ctlr->tdt);
+
+ csr32w(ctlr, Tipg, (6<<20)|(8<<10)|6);
+ csr32w(ctlr, Tidv, 128);
+ csr32w(ctlr, Ait, 0);
+ csr32w(ctlr, Txdmac, 0);
+ csr32w(ctlr, Txdctl, Gran|(4<<WthreshSHIFT)|(1<<HthreshSHIFT)|16);
+ csr32w(ctlr, Tctl, (0x0F<<CtSHIFT)|Psp|(6<<ColdSHIFT));
+
+ ctlr->im |= Txdw;
+}
+
+static void
+gc82543transmit(Ether* edev)
+{
+ Block *bp, **bpp;
+ Ctlr *ctlr;
+ Tdesc *tdesc;
+ int tdh, tdt, s;
+
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->tdlock);
+ tdh = ctlr->tdh;
+ for(;;){
+ /*
+ * Free any completed packets
+ */
+ tdesc = &ctlr->tdba[tdh];
+ if(!(tdesc->status & Tdd))
+ break;
+ memset(tdesc, 0, sizeof(Tdesc));
+ bpp = &ctlr->tb[tdh];
+ bp = *bpp;
+ if(bp != nil){
+ *bpp = nil;
+ freeb(bp);
+ }
+ tdh = NEXT(tdh, Ntdesc);
+ }
+ ctlr->tdh = tdh;
+ s = csr32r(ctlr, Status);
+
+ /*
+ * Try to fill the ring back up
+ * but only if link is up and transmission isn't paused.
+ */
+ if((s & (Txoff|Lu)) == Lu){
+ tdt = ctlr->tdt;
+ while(NEXT(tdt, Ntdesc) != tdh){
+ if((bp = qget(edev->oq)) == nil)
+ break;
+
+ tdesc = &ctlr->tdba[tdt];
+ tdesc->addr[0] = PCIWADDR(bp->rp);
+ tdesc->control = Ide|Rs|Ifcs|Teop|BLEN(bp);
+ ctlr->tb[tdt] = bp;
+ tdt = NEXT(tdt, Ntdesc);
+ }
+
+ if(tdt != ctlr->tdt){
+ ctlr->tdt = tdt;
+ csr32w(ctlr, Tdt, tdt);
+ }
+ }
+ else
+ ctlr->txstalled++;
+
+ iunlock(&ctlr->tdlock);
+}
+
+static Block *
+gc82543allocb(Ctlr* ctlr)
+{
+ Block *bp;
+
+ ilock(&freelistlock);
+ if((bp = *(ctlr->freehead)) != nil){
+ *(ctlr->freehead) = bp->next;
+ bp->next = nil;
+ _xinc(&bp->ref); /* prevent bp from being freed */
+ }
+ iunlock(&freelistlock);
+ return bp;
+}
+
+static void
+gc82543replenish(Ctlr* ctlr)
+{
+ int rdt;
+ Block *bp;
+ Rdesc *rdesc;
+
+ ilock(&ctlr->rdlock);
+ rdt = ctlr->rdt;
+ while(NEXT(rdt, Nrdesc) != ctlr->rdh){
+ rdesc = &ctlr->rdba[rdt];
+ if(ctlr->rb[rdt] == nil){
+ bp = gc82543allocb(ctlr);
+ if(bp == nil){
+ iprint("no available buffers\n");
+ break;
+ }
+ ctlr->rb[rdt] = bp;
+ rdesc->addr[0] = PCIWADDR(bp->rp);
+ rdesc->addr[1] = 0;
+ }
+ coherence();
+ rdesc->status = 0;
+ rdt = NEXT(rdt, Nrdesc);
+ }
+ ctlr->rdt = rdt;
+ csr32w(ctlr, Rdt, rdt);
+ iunlock(&ctlr->rdlock);
+}
+
+static void
+gc82543rxinit(Ctlr* ctlr)
+{
+ int rdsize, i;
+
+ csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF);
+
+ /*
+ * Allocate the descriptor ring and load its
+ * address and length into the NIC.
+ */
+ rdsize = ROUND(Nrdesc*sizeof(Rdesc), 4096);
+ if(ctlr->rdba == nil)
+ ctlr->rdba = xspanalloc(rdsize, 32, 0);
+ memset(ctlr->rdba, 0, rdsize);
+
+ ctlr->rdh = 0;
+ ctlr->rdt = 0;
+
+ csr32w(ctlr, Rdtr, Fpd|64);
+ csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
+ csr32w(ctlr, Rdbah, 0);
+ csr32w(ctlr, Rdlen, Nrdesc*sizeof(Rdesc));
+ csr32w(ctlr, Rdh, 0);
+ csr32w(ctlr, Rdt, 0);
+ for(i = 0; i < Nrdesc; i++){
+ if(ctlr->rb[i] != nil){
+ freeb(ctlr->rb[i]);
+ ctlr->rb[i] = nil;
+ }
+ }
+ gc82543replenish(ctlr);
+
+ csr32w(ctlr, Rxdctl, RxGran|(8<<WthreshSHIFT)|(4<<HthreshSHIFT)|1);
+ ctlr->im |= Rxt0|Rxo|Rxdmt0|Rxseq;
+}
+
+static void
+gc82543recv(Ether* edev, int icr)
+{
+ Block *bp;
+ Ctlr *ctlr;
+ Rdesc *rdesc;
+ int rdh;
+
+ ctlr = edev->ctlr;
+
+ rdh = ctlr->rdh;
+ for(;;){
+ rdesc = &ctlr->rdba[rdh];
+
+ if(!(rdesc->status & Rdd))
+ break;
+
+ if((rdesc->status & Reop) && rdesc->errors == 0){
+ bp = ctlr->rb[rdh];
+ ctlr->rb[rdh] = nil;
+ bp->wp += rdesc->length;
+ bp->next = nil;
+ etheriq(edev, bp, 1);
+ }
+
+ if(ctlr->rb[rdh] != nil){
+ /* either non eop packet, or error */
+ freeb(ctlr->rb[rdh]);
+ ctlr->rb[rdh] = nil;
+ }
+ memset(rdesc, 0, sizeof(Rdesc));
+ coherence();
+ rdh = NEXT(rdh, Nrdesc);
+ }
+ ctlr->rdh = rdh;
+
+ if(icr & Rxdmt0)
+ gc82543replenish(ctlr);
+}
+
+static void
+freegc82543short(Block *bp)
+{
+ ilock(&freelistlock);
+ /* reset read/write pointer to proper positions */
+ bp->rp = bp->lim - ROUND(SBLOCKSIZE, BLOCKALIGN);
+ bp->wp = bp->rp;
+ bp->next = freeShortHead;
+ freeShortHead = bp;
+ iunlock(&freelistlock);
+}
+
+static void
+freegc82532jumbo(Block *bp)
+{
+ ilock(&freelistlock);
+ /* reset read/write pointer to proper positions */
+ bp->rp = bp->lim - ROUND(JBLOCKSIZE, BLOCKALIGN);
+ bp->wp = bp->rp;
+ bp->next = freeJumboHead;
+ freeJumboHead = bp;
+ iunlock(&freelistlock);
+}
+
+static void
+linkintr(Ctlr* ctlr)
+{
+ int ctrl;
+
+ ctrl = csr32r(ctlr, Ctrl);
+
+ if((ctrl & Swdpin1) ||
+ ((csr32r(ctlr, Rxcw) & Rxconfig) && !(csr32r(ctlr, Txcw) & Ane))){
+ csr32w(ctlr, Txcw, ctlr->txcw);
+ ctrl &= ~(Slu|Fd|Frcdplx);
+ csr32w(ctlr, Ctrl, ctrl);
+ }
+}
+
+static void
+gc82543interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Ether *edev;
+ int icr;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ while((icr = csr32r(ctlr, Icr) & ctlr->im) != 0){
+ /*
+ * Link status changed.
+ */
+ if(icr & (Lsc|Rxseq))
+ linkintr(ctlr);
+
+ /*
+ * Process recv buffers.
+ */
+ gc82543recv(edev, icr);
+
+ /*
+ * Refill transmit ring and free packets.
+ */
+ gc82543transmit(edev);
+ }
+}
+
+static int
+gc82543init(Ether* edev)
+{
+ int csr, i;
+ Block *bp;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+
+ /*
+ * Allocate private buffer pool to use for receiving packets.
+ */
+ ilock(&freelistlock);
+ if (ctlr->freehead == nil){
+ for(i = 0; i < Nblocks; i++){
+ bp = iallocb(SBLOCKSIZE);
+ if(bp != nil){
+ bp->next = freeShortHead;
+ bp->free = freegc82543short;
+ freeShortHead = bp;
+ }
+ else{
+ print("82543gc: no memory\n");
+ break;
+ }
+ }
+ ctlr->freehead = &freeShortHead;
+ }
+ iunlock(&freelistlock);
+
+ /*
+ * Set up the receive addresses.
+ * There are 16 addresses. The first should be the MAC address.
+ * The others are cleared and not marked valid (MS bit of Rah).
+ */
+ csr = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
+ csr32w(ctlr, Ral, csr);
+ csr = 0x80000000|(edev->ea[5]<<8)|edev->ea[4];
+ csr32w(ctlr, Rah, csr);
+ for(i = 1; i < 16; i++){
+ csr32w(ctlr, Ral+i*8, 0);
+ csr32w(ctlr, Rah+i*8, 0);
+ }
+
+ /*
+ * Clear the Multicast Table Array.
+ * It's a 4096 bit vector accessed as 128 32-bit registers.
+ */
+ for(i = 0; i < 128; i++)
+ csr32w(ctlr, Mta+i*4, 0);
+
+ gc82543txinit(ctlr);
+ gc82543rxinit(ctlr);
+
+ return 0;
+}
+
+static int
+at93c46io(Ctlr* ctlr, char* op, int data)
+{
+ char *lp, *p;
+ int i, loop, eecd, r;
+
+ eecd = csr32r(ctlr, Eecd);
+
+ r = 0;
+ loop = -1;
+ lp = nil;
+ for(p = op; *p != '\0'; p++){
+ switch(*p){
+ default:
+ return -1;
+ case ' ':
+ continue;
+ case ':': /* start of loop */
+ if(lp != nil){
+ if(p != (lp+1) || loop != 7)
+ return -1;
+ lp = p;
+ loop = 15;
+ continue;
+ }
+ lp = p;
+ loop = 7;
+ continue;
+ case ';': /* end of loop */
+ if(lp == nil)
+ return -1;
+ loop--;
+ if(loop >= 0)
+ p = lp;
+ else
+ lp = nil;
+ continue;
+ case 'C': /* assert clock */
+ eecd |= Sk;
+ break;
+ case 'c': /* deassert clock */
+ eecd &= ~Sk;
+ break;
+ case 'D': /* next bit in 'data' byte */
+ if(loop < 0)
+ return -1;
+ if(data & (1<<loop))
+ eecd |= Di;
+ else
+ eecd &= ~Di;
+ break;
+ case 'O': /* collect data output */
+ i = (csr32r(ctlr, Eecd) & Do) != 0;
+ if(loop >= 0)
+ r |= (i<<loop);
+ else
+ r = i;
+ continue;
+ case 'I': /* assert data input */
+ eecd |= Di;
+ break;
+ case 'i': /* deassert data input */
+ eecd &= ~Di;
+ break;
+ case 'S': /* enable chip select */
+ eecd |= Cs;
+ break;
+ case 's': /* disable chip select */
+ eecd &= ~Cs;
+ break;
+ }
+ csr32w(ctlr, Eecd, eecd);
+ microdelay(1);
+ }
+ if(loop >= 0)
+ return -1;
+ return r;
+}
+
+static int
+at93c46r(Ctlr* ctlr)
+{
+ ushort sum;
+ int addr, data;
+
+ sum = 0;
+ for(addr = 0; addr < 0x40; addr++){
+ /*
+ * Read a word at address 'addr' from the Atmel AT93C46
+ * 3-Wire Serial EEPROM or compatible. The EEPROM access is
+ * controlled by 4 bits in Eecd. See the AT93C46 datasheet
+ * for protocol details.
+ */
+ if(at93c46io(ctlr, "S ICc :DCc;", (0x02<<6)|addr) != 0)
+ break;
+ data = at93c46io(ctlr, "::COc;", 0);
+ at93c46io(ctlr, "sic", 0);
+ ctlr->eeprom[addr] = data;
+ sum += data;
+ }
+
+ return sum;
+}
+
+static void
+gc82543detach(Ctlr* ctlr)
+{
+ /*
+ * Perform a device reset to get the chip back to the
+ * power-on state, followed by an EEPROM reset to read
+ * the defaults for some internal registers.
+ */
+ csr32w(ctlr, Imc, ~0);
+ csr32w(ctlr, Rctl, 0);
+ csr32w(ctlr, Tctl, 0);
+
+ delay(10);
+
+ csr32w(ctlr, Ctrl, Devrst);
+ while(csr32r(ctlr, Ctrl) & Devrst)
+ ;
+
+ csr32w(ctlr, Ctrlext, Eerst);
+ while(csr32r(ctlr, Ctrlext) & Eerst)
+ ;
+
+ csr32w(ctlr, Imc, ~0);
+ while(csr32r(ctlr, Icr))
+ ;
+}
+
+static void
+gc82543checklink(Ctlr* ctlr)
+{
+ int ctrl, status, rxcw;
+
+ ctrl = csr32r(ctlr, Ctrl);
+ status = csr32r(ctlr, Status);
+ rxcw = csr32r(ctlr, Rxcw);
+
+ if(!(status & Lu)){
+ if(!(ctrl & (Swdpin1|Slu)) && !(rxcw & Rxconfig)){
+ csr32w(ctlr, Txcw, ctlr->txcw & ~Ane);
+ ctrl |= (Slu|Fd);
+ if(ctlr->txcw & As)
+ ctrl |= Rfce;
+ if(ctlr->txcw & Ps)
+ ctrl |= Tfce;
+ csr32w(ctlr, Ctrl, ctrl);
+ }
+ }
+ else if((ctrl & Slu) && (rxcw & Rxconfig)){
+ csr32w(ctlr, Txcw, ctlr->txcw);
+ ctrl &= ~(Slu|Fd);
+ csr32w(ctlr, Ctrl, ctrl);
+ }
+}
+
+static void
+gc82543shutdown(Ether* ether)
+{
+ gc82543detach(ether->ctlr);
+}
+
+static int
+gc82543reset(Ctlr* ctlr)
+{
+ int ctl;
+ int te;
+
+ /*
+ * Read the EEPROM, validate the checksum
+ * then get the device back to a power-on state.
+ */
+ if(at93c46r(ctlr) != 0xBABA)
+ return -1;
+
+ gc82543detach(ctlr);
+
+ te = ctlr->eeprom[Icw2];
+ if((te & 0x3000) == 0){
+ ctlr->fcrtl = 0x00002000;
+ ctlr->fcrth = 0x00004000;
+ ctlr->txcw = Ane|TxcwFd;
+ }
+ else if((te & 0x3000) == 0x2000){
+ ctlr->fcrtl = 0;
+ ctlr->fcrth = 0;
+ ctlr->txcw = Ane|TxcwFd|As;
+ }
+ else{
+ ctlr->fcrtl = 0x00002000;
+ ctlr->fcrth = 0x00004000;
+ ctlr->txcw = Ane|TxcwFd|As|Ps;
+ }
+
+ csr32w(ctlr, Txcw, ctlr->txcw);
+
+ csr32w(ctlr, Ctrlext, (te & 0x00f0)<<4);
+
+ csr32w(ctlr, Tctl, csr32r(ctlr, Tctl)|(64<<ColdSHIFT));
+
+ te = ctlr->eeprom[Icw1];
+ ctl = ((te & 0x01E0)<<17)|(te & 0x0010)<<3;
+ csr32w(ctlr, Ctrl, ctl);
+
+ delay(10);
+
+ /*
+ * Flow control - values from the datasheet.
+ */
+ csr32w(ctlr, Fcal, 0x00C28001);
+ csr32w(ctlr, Fcah, 0x00000100);
+ csr32w(ctlr, Fct, 0x00008808);
+ csr32w(ctlr, Fcttv, 0x00000100);
+
+ csr32w(ctlr, Fcrtl, ctlr->fcrtl);
+ csr32w(ctlr, Fcrth, ctlr->fcrth);
+
+ ctlr->im = Lsc;
+ gc82543checklink(ctlr);
+
+ return 0;
+}
+
+static void
+gc82543watchdog(void* arg)
+{
+ Ether *edev;
+ Ctlr *ctlr;
+
+ edev = arg;
+ for(;;){
+ tsleep(&up->sleep, return0, 0, 1000);
+
+ ctlr = edev->ctlr;
+ if(ctlr == nil){
+ print("%s: exiting\n", up->text);
+ pexit("disabled", 0);
+ }
+
+ gc82543checklink(ctlr);
+ gc82543replenish(ctlr);
+ }
+}
+
+static void
+gc82543pci(void)
+{
+ int cls;
+ void *mem;
+ Pcidev *p;
+ Ctlr *ctlr;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+
+ switch((p->did<<16)|p->vid){
+ case (0x1000<<16)|0x8086: /* LSI L2A1157 (82542) */
+ case (0x1004<<16)|0x8086: /* Intel PRO/1000 T */
+ case (0x1008<<16)|0x8086: /* Intel PRO/1000 XT */
+ default:
+ continue;
+ case (0x1001<<16)|0x8086: /* Intel PRO/1000 F */
+ break;
+ }
+
+ 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;
+ }
+ cls = pcicfgr8(p, PciCLS);
+ switch(cls){
+ case 0x00:
+ case 0xFF:
+ print("82543gc: unusable cache line size\n");
+ continue;
+ case 0x08:
+ break;
+ default:
+ print("82543gc: cache line size %d, expected 32\n",
+ cls*4);
+ }
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = p->mem[0].bar & ~0x0F;
+ ctlr->pcidev = p;
+ ctlr->id = (p->did<<16)|p->vid;
+ ctlr->nic = mem;
+
+ if(gc82543reset(ctlr)){
+ free(ctlr);
+ continue;
+ }
+
+ if(gc82543ctlrhead != nil)
+ gc82543ctlrtail->next = ctlr;
+ else
+ gc82543ctlrhead = ctlr;
+ gc82543ctlrtail = ctlr;
+ }
+}
+
+static int
+gc82543pnp(Ether* edev)
+{
+ int i;
+ Ctlr *ctlr;
+ uchar ea[Eaddrlen];
+
+ if(gc82543ctlrhead == nil)
+ gc82543pci();
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = gc82543ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+ edev->mbps = 1000;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to
+ * loading the station address in the hardware.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, edev->ea, Eaddrlen) == 0){
+ for(i = Ea; i < Eaddrlen/2; i++){
+ edev->ea[2*i] = ctlr->eeprom[i];
+ edev->ea[2*i+1] = ctlr->eeprom[i]>>8;
+ }
+ }
+ gc82543init(edev);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ edev->attach = gc82543attach;
+ edev->transmit = gc82543transmit;
+ edev->interrupt = gc82543interrupt;
+ edev->ifstat = gc82543ifstat;
+ edev->shutdown = gc82543shutdown;
+ edev->ctl = gc82543ctl;
+ edev->arg = edev;
+ edev->promiscuous = gc82543promiscuous;
+ edev->multicast = gc82543multicast;
+
+ return 0;
+}
+
+void
+ether82543gclink(void)
+{
+ addethercard("82543GC", gc82543pnp);
+}
diff --git a/sys/src/9/pc/ether82557.c b/sys/src/9/pc/ether82557.c
new file mode 100755
index 000000000..2db2a7cdd
--- /dev/null
+++ b/sys/src/9/pc/ether82557.c
@@ -0,0 +1,1336 @@
+/*
+ * Intel 82557 Fast Ethernet PCI Bus LAN Controller
+ * as found on the Intel EtherExpress PRO/100B. This chip is full
+ * of smarts, unfortunately they're not all in the right place.
+ * To do:
+ * the PCI scanning code could be made common to other adapters;
+ * auto-negotiation, full-duplex;
+ * optionally use memory-mapped registers;
+ * detach for PCI reset problems (also towards loadable drivers).
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+enum {
+ Nrfd = 64, /* receive frame area */
+ Ncb = 64, /* maximum control blocks queued */
+
+ NullPointer = 0xFFFFFFFF, /* 82557 NULL pointer */
+};
+
+enum { /* CSR */
+ Status = 0x00, /* byte or word (word includes Ack) */
+ Ack = 0x01, /* byte */
+ CommandR = 0x02, /* byte or word (word includes Interrupt) */
+ Interrupt = 0x03, /* byte */
+ General = 0x04, /* dword */
+ Port = 0x08, /* dword */
+ Fcr = 0x0C, /* Flash control register */
+ Ecr = 0x0E, /* EEPROM control register */
+ Mcr = 0x10, /* MDI control register */
+ Gstatus = 0x1D, /* General status register */
+};
+
+enum { /* Status */
+ RUidle = 0x0000,
+ RUsuspended = 0x0004,
+ RUnoresources = 0x0008,
+ RUready = 0x0010,
+ RUrbd = 0x0020, /* bit */
+ RUstatus = 0x003F, /* mask */
+
+ CUidle = 0x0000,
+ CUsuspended = 0x0040,
+ CUactive = 0x0080,
+ CUstatus = 0x00C0, /* mask */
+
+ StatSWI = 0x0400, /* SoftWare generated Interrupt */
+ StatMDI = 0x0800, /* MDI r/w done */
+ StatRNR = 0x1000, /* Receive unit Not Ready */
+ StatCNA = 0x2000, /* Command unit Not Active (Active->Idle) */
+ StatFR = 0x4000, /* Finished Receiving */
+ StatCX = 0x8000, /* Command eXecuted */
+ StatTNO = 0x8000, /* Transmit NOT OK */
+};
+
+enum { /* Command (byte) */
+ CUnop = 0x00,
+ CUstart = 0x10,
+ CUresume = 0x20,
+ LoadDCA = 0x40, /* Load Dump Counters Address */
+ DumpSC = 0x50, /* Dump Statistical Counters */
+ LoadCUB = 0x60, /* Load CU Base */
+ ResetSA = 0x70, /* Dump and Reset Statistical Counters */
+
+ RUstart = 0x01,
+ RUresume = 0x02,
+ RUabort = 0x04,
+ LoadHDS = 0x05, /* Load Header Data Size */
+ LoadRUB = 0x06, /* Load RU Base */
+ RBDresume = 0x07, /* Resume frame reception */
+};
+
+enum { /* Interrupt (byte) */
+ InterruptM = 0x01, /* interrupt Mask */
+ InterruptSI = 0x02, /* Software generated Interrupt */
+};
+
+enum { /* Ecr */
+ EEsk = 0x01, /* serial clock */
+ EEcs = 0x02, /* chip select */
+ EEdi = 0x04, /* serial data in */
+ EEdo = 0x08, /* serial data out */
+
+ EEstart = 0x04, /* start bit */
+ EEread = 0x02, /* read opcode */
+};
+
+enum { /* Mcr */
+ MDIread = 0x08000000, /* read opcode */
+ MDIwrite = 0x04000000, /* write opcode */
+ MDIready = 0x10000000, /* ready bit */
+ MDIie = 0x20000000, /* interrupt enable */
+};
+
+typedef struct Rfd {
+ int field;
+ ulong link;
+ ulong rbd;
+ ushort count;
+ ushort size;
+
+ uchar data[1700];
+} Rfd;
+
+enum { /* field */
+ RfdCollision = 0x00000001,
+ RfdIA = 0x00000002, /* IA match */
+ RfdRxerr = 0x00000010, /* PHY character error */
+ RfdType = 0x00000020, /* Type frame */
+ RfdRunt = 0x00000080,
+ RfdOverrun = 0x00000100,
+ RfdBuffer = 0x00000200,
+ RfdAlignment = 0x00000400,
+ RfdCRC = 0x00000800,
+
+ RfdOK = 0x00002000, /* frame received OK */
+ RfdC = 0x00008000, /* reception Complete */
+ RfdSF = 0x00080000, /* Simplified or Flexible (1) Rfd */
+ RfdH = 0x00100000, /* Header RFD */
+
+ RfdI = 0x20000000, /* Interrupt after completion */
+ RfdS = 0x40000000, /* Suspend after completion */
+ RfdEL = 0x80000000, /* End of List */
+};
+
+enum { /* count */
+ RfdF = 0x4000,
+ RfdEOF = 0x8000,
+};
+
+typedef struct Cb Cb;
+typedef struct Cb {
+ ushort status;
+ ushort command;
+ ulong link;
+ union {
+ uchar data[24]; /* CbIAS + CbConfigure */
+ struct {
+ ulong tbd;
+ ushort count;
+ uchar threshold;
+ uchar number;
+
+ ulong tba;
+ ushort tbasz;
+ ushort pad;
+ };
+ };
+
+ Block* bp;
+ Cb* next;
+} Cb;
+
+enum { /* action command */
+ CbU = 0x1000, /* transmit underrun */
+ CbOK = 0x2000, /* DMA completed OK */
+ CbC = 0x8000, /* execution Complete */
+
+ CbNOP = 0x0000,
+ CbIAS = 0x0001, /* Individual Address Setup */
+ CbConfigure = 0x0002,
+ CbMAS = 0x0003, /* Multicast Address Setup */
+ CbTransmit = 0x0004,
+ CbDump = 0x0006,
+ CbDiagnose = 0x0007,
+ CbCommand = 0x0007, /* mask */
+
+ CbSF = 0x0008, /* Flexible-mode CbTransmit */
+
+ CbI = 0x2000, /* Interrupt after completion */
+ CbS = 0x4000, /* Suspend after completion */
+ CbEL = 0x8000, /* End of List */
+};
+
+enum { /* CbTransmit count */
+ CbEOF = 0x8000,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ Lock slock; /* attach */
+ int state;
+
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+
+ int eepromsz; /* address size in bits */
+ ushort* eeprom;
+
+ Lock miilock;
+
+ int tick;
+
+ Lock rlock; /* registers */
+ int command; /* last command issued */
+
+ Block* rfdhead; /* receive side */
+ Block* rfdtail;
+ int nrfd;
+
+ Lock cblock; /* transmit side */
+ int action;
+ int nop;
+ uchar configdata[24];
+ int threshold;
+ int ncb;
+ Cb* cbr;
+ Cb* cbhead;
+ Cb* cbtail;
+ int cbq;
+ int cbqmax;
+ int cbqmaxhw;
+
+ Lock dlock; /* dump statistical counters */
+ ulong dump[17];
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+static uchar configdata[24] = {
+ 0x16, /* byte count */
+ 0x08, /* Rx/Tx FIFO limit */
+ 0x00, /* adaptive IFS */
+ 0x00,
+ 0x00, /* Rx DMA maximum byte count */
+// 0x80, /* Tx DMA maximum byte count */
+ 0x00, /* Tx DMA maximum byte count */
+ 0x32, /* !late SCB, CNA interrupts */
+ 0x03, /* discard short Rx frames */
+ 0x00, /* 503/MII */
+
+ 0x00,
+ 0x2E, /* normal operation, NSAI */
+ 0x00, /* linear priority */
+ 0x60, /* inter-frame spacing */
+ 0x00,
+ 0xF2,
+ 0xC8, /* 503, promiscuous mode off */
+ 0x00,
+ 0x40,
+ 0xF3, /* transmit padding enable */
+ 0x80, /* full duplex pin enable */
+ 0x3F, /* no Multi IA */
+ 0x05, /* no Multi Cast ALL */
+};
+
+#define csr8r(c, r) (inb((c)->port+(r)))
+#define csr16r(c, r) (ins((c)->port+(r)))
+#define csr32r(c, r) (inl((c)->port+(r)))
+#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
+#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
+#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
+
+static void
+command(Ctlr* ctlr, int c, int v)
+{
+ int timeo;
+
+ ilock(&ctlr->rlock);
+
+ /*
+ * Only back-to-back CUresume can be done
+ * without waiting for any previous command to complete.
+ * This should be the common case.
+ * Unfortunately there's a chip errata where back-to-back
+ * CUresumes can be lost, the fix is to always wait.
+ if(c == CUresume && ctlr->command == CUresume){
+ csr8w(ctlr, CommandR, c);
+ iunlock(&ctlr->rlock);
+ return;
+ }
+ */
+
+ for(timeo = 0; timeo < 100; timeo++){
+ if(!csr8r(ctlr, CommandR))
+ break;
+ microdelay(1);
+ }
+ if(timeo >= 100){
+ ctlr->command = -1;
+ iunlock(&ctlr->rlock);
+ iprint("i82557: command %#ux %#ux timeout\n", c, v);
+ return;
+ }
+
+ switch(c){
+
+ case CUstart:
+ case LoadDCA:
+ case LoadCUB:
+ case RUstart:
+ case LoadHDS:
+ case LoadRUB:
+ csr32w(ctlr, General, v);
+ break;
+
+ /*
+ case CUnop:
+ case CUresume:
+ case DumpSC:
+ case ResetSA:
+ case RUresume:
+ case RUabort:
+ */
+ default:
+ break;
+ }
+ csr8w(ctlr, CommandR, c);
+ ctlr->command = c;
+
+ iunlock(&ctlr->rlock);
+}
+
+static Block*
+rfdalloc(ulong link)
+{
+ Block *bp;
+ Rfd *rfd;
+
+ if(bp = iallocb(sizeof(Rfd))){
+ rfd = (Rfd*)bp->rp;
+ rfd->field = 0;
+ rfd->link = link;
+ rfd->rbd = NullPointer;
+ rfd->count = 0;
+ rfd->size = sizeof(Etherpkt);
+ }
+
+ return bp;
+}
+
+static void
+watchdog(void* arg)
+{
+ Ether *ether;
+ Ctlr *ctlr;
+ static void txstart(Ether*);
+
+ ether = arg;
+ for(;;){
+ tsleep(&up->sleep, return0, 0, 4000);
+
+ /*
+ * Hmmm. This doesn't seem right. Currently
+ * the device can't be disabled but it may be in
+ * the future.
+ */
+ ctlr = ether->ctlr;
+ if(ctlr == nil || ctlr->state == 0){
+ print("%s: exiting\n", up->text);
+ pexit("disabled", 0);
+ }
+
+ ilock(&ctlr->cblock);
+ if(ctlr->tick++){
+ ctlr->action = CbMAS;
+ txstart(ether);
+ }
+ iunlock(&ctlr->cblock);
+ }
+}
+
+static void
+attach(Ether* ether)
+{
+ Ctlr *ctlr;
+ char name[KNAMELEN];
+
+ ctlr = ether->ctlr;
+ lock(&ctlr->slock);
+ if(ctlr->state == 0){
+ ilock(&ctlr->rlock);
+ csr8w(ctlr, Interrupt, 0);
+ iunlock(&ctlr->rlock);
+ command(ctlr, RUstart, PADDR(ctlr->rfdhead->rp));
+ ctlr->state = 1;
+
+ /*
+ * Start the watchdog timer for the receive lockup errata
+ * unless the EEPROM compatibility word indicates it may be
+ * omitted.
+ */
+ if((ctlr->eeprom[0x03] & 0x0003) != 0x0003){
+ snprint(name, KNAMELEN, "#l%dwatchdog", ether->ctlrno);
+ kproc(name, watchdog, ether);
+ }
+ }
+ unlock(&ctlr->slock);
+}
+
+static long
+ifstat(Ether* ether, void* a, long n, ulong offset)
+{
+ char *p;
+ int i, len, phyaddr;
+ Ctlr *ctlr;
+ ulong dump[17];
+
+ ctlr = ether->ctlr;
+ lock(&ctlr->dlock);
+
+ /*
+ * Start the command then
+ * wait for completion status,
+ * should be 0xA005.
+ */
+ ctlr->dump[16] = 0;
+ command(ctlr, DumpSC, 0);
+ while(ctlr->dump[16] == 0)
+ ;
+
+ ether->oerrs = ctlr->dump[1]+ctlr->dump[2]+ctlr->dump[3];
+ ether->crcs = ctlr->dump[10];
+ ether->frames = ctlr->dump[11];
+ ether->buffs = ctlr->dump[12]+ctlr->dump[15];
+ ether->overflows = ctlr->dump[13];
+
+ if(n == 0){
+ unlock(&ctlr->dlock);
+ return 0;
+ }
+
+ memmove(dump, ctlr->dump, sizeof(dump));
+ unlock(&ctlr->dlock);
+
+ p = malloc(READSTR);
+ len = snprint(p, READSTR, "transmit good frames: %lud\n", dump[0]);
+ len += snprint(p+len, READSTR-len, "transmit maximum collisions errors: %lud\n", dump[1]);
+ len += snprint(p+len, READSTR-len, "transmit late collisions errors: %lud\n", dump[2]);
+ len += snprint(p+len, READSTR-len, "transmit underrun errors: %lud\n", dump[3]);
+ len += snprint(p+len, READSTR-len, "transmit lost carrier sense: %lud\n", dump[4]);
+ len += snprint(p+len, READSTR-len, "transmit deferred: %lud\n", dump[5]);
+ len += snprint(p+len, READSTR-len, "transmit single collisions: %lud\n", dump[6]);
+ len += snprint(p+len, READSTR-len, "transmit multiple collisions: %lud\n", dump[7]);
+ len += snprint(p+len, READSTR-len, "transmit total collisions: %lud\n", dump[8]);
+ len += snprint(p+len, READSTR-len, "receive good frames: %lud\n", dump[9]);
+ len += snprint(p+len, READSTR-len, "receive CRC errors: %lud\n", dump[10]);
+ len += snprint(p+len, READSTR-len, "receive alignment errors: %lud\n", dump[11]);
+ len += snprint(p+len, READSTR-len, "receive resource errors: %lud\n", dump[12]);
+ len += snprint(p+len, READSTR-len, "receive overrun errors: %lud\n", dump[13]);
+ len += snprint(p+len, READSTR-len, "receive collision detect errors: %lud\n", dump[14]);
+ len += snprint(p+len, READSTR-len, "receive short frame errors: %lud\n", dump[15]);
+ len += snprint(p+len, READSTR-len, "nop: %d\n", ctlr->nop);
+ if(ctlr->cbqmax > ctlr->cbqmaxhw)
+ ctlr->cbqmaxhw = ctlr->cbqmax;
+ len += snprint(p+len, READSTR-len, "cbqmax: %d\n", ctlr->cbqmax);
+ ctlr->cbqmax = 0;
+ len += snprint(p+len, READSTR-len, "threshold: %d\n", ctlr->threshold);
+
+ len += snprint(p+len, READSTR-len, "eeprom:");
+ for(i = 0; i < (1<<ctlr->eepromsz); i++){
+ if(i && ((i & 0x07) == 0))
+ len += snprint(p+len, READSTR-len, "\n ");
+ len += snprint(p+len, READSTR-len, " %4.4ux", ctlr->eeprom[i]);
+ }
+
+ if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000)){
+ phyaddr = ctlr->eeprom[6] & 0x00FF;
+ len += snprint(p+len, READSTR-len, "\nphy %2d:", phyaddr);
+ for(i = 0; i < 6; i++){
+ static int miir(Ctlr*, int, int);
+
+ len += snprint(p+len, READSTR-len, " %4.4ux",
+ miir(ctlr, phyaddr, i));
+ }
+ }
+
+ snprint(p+len, READSTR-len, "\n");
+ n = readstr(offset, a, n, p);
+ free(p);
+
+ return n;
+}
+
+static void
+txstart(Ether* ether)
+{
+ Ctlr *ctlr;
+ Block *bp;
+ Cb *cb;
+
+ ctlr = ether->ctlr;
+ while(ctlr->cbq < (ctlr->ncb-1)){
+ cb = ctlr->cbhead->next;
+ if(ctlr->action == 0){
+ bp = qget(ether->oq);
+ if(bp == nil)
+ break;
+
+ cb->command = CbS|CbSF|CbTransmit;
+ cb->tbd = PADDR(&cb->tba);
+ cb->count = 0;
+ cb->threshold = ctlr->threshold;
+ cb->number = 1;
+ cb->tba = PADDR(bp->rp);
+ cb->bp = bp;
+ cb->tbasz = BLEN(bp);
+ }
+ else if(ctlr->action == CbConfigure){
+ cb->command = CbS|CbConfigure;
+ memmove(cb->data, ctlr->configdata, sizeof(ctlr->configdata));
+ ctlr->action = 0;
+ }
+ else if(ctlr->action == CbIAS){
+ cb->command = CbS|CbIAS;
+ memmove(cb->data, ether->ea, Eaddrlen);
+ ctlr->action = 0;
+ }
+ else if(ctlr->action == CbMAS){
+ cb->command = CbS|CbMAS;
+ memset(cb->data, 0, sizeof(cb->data));
+ ctlr->action = 0;
+ }
+ else{
+ print("#l%d: action %#ux\n", ether->ctlrno, ctlr->action);
+ ctlr->action = 0;
+ break;
+ }
+ cb->status = 0;
+
+ coherence();
+ ctlr->cbhead->command &= ~CbS;
+ ctlr->cbhead = cb;
+ ctlr->cbq++;
+ }
+
+ /*
+ * Workaround for some broken HUB chips
+ * when connected at 10Mb/s half-duplex.
+ */
+ if(ctlr->nop){
+ command(ctlr, CUnop, 0);
+ microdelay(1);
+ }
+ command(ctlr, CUresume, 0);
+
+ if(ctlr->cbq > ctlr->cbqmax)
+ ctlr->cbqmax = ctlr->cbq;
+}
+
+static void
+configure(Ether* ether, int promiscuous)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(&ctlr->cblock);
+ if(promiscuous){
+ ctlr->configdata[6] |= 0x80; /* Save Bad Frames */
+ //ctlr->configdata[6] &= ~0x40; /* !Discard Overrun Rx Frames */
+ ctlr->configdata[7] &= ~0x01; /* !Discard Short Rx Frames */
+ ctlr->configdata[15] |= 0x01; /* Promiscuous mode */
+ ctlr->configdata[18] &= ~0x01; /* (!Padding enable?), !stripping enable */
+ ctlr->configdata[21] |= 0x08; /* Multi Cast ALL */
+ }
+ else{
+ ctlr->configdata[6] &= ~0x80;
+ //ctlr->configdata[6] |= 0x40;
+ ctlr->configdata[7] |= 0x01;
+ ctlr->configdata[15] &= ~0x01;
+ ctlr->configdata[18] |= 0x01; /* 0x03? */
+ ctlr->configdata[21] &= ~0x08;
+ }
+ ctlr->action = CbConfigure;
+ txstart(ether);
+ iunlock(&ctlr->cblock);
+}
+
+static void
+promiscuous(void* arg, int on)
+{
+ configure(arg, on);
+}
+
+static void
+multicast(void* ether, uchar *addr, int add)
+{
+ USED(addr);
+ /*
+ * TODO: if (add) add addr to list of mcast addrs in controller
+ * else remove addr from list of mcast addrs in controller
+ * enable multicast input (see CbMAS) instead of promiscuous mode.
+ */
+ if (add)
+ configure(ether, 1);
+}
+
+static void
+transmit(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(&ctlr->cblock);
+ txstart(ether);
+ iunlock(&ctlr->cblock);
+}
+
+static void
+receive(Ether* ether)
+{
+ Rfd *rfd;
+ Ctlr *ctlr;
+ int count;
+ Block *bp, *pbp, *xbp;
+
+ ctlr = ether->ctlr;
+ bp = ctlr->rfdhead;
+ for(rfd = (Rfd*)bp->rp; rfd->field & RfdC; rfd = (Rfd*)bp->rp){
+ /*
+ * If it's an OK receive frame
+ * 1) save the count
+ * 2) if it's small, try to allocate a block and copy
+ * the data, then adjust the necessary fields for reuse;
+ * 3) if it's big, try to allocate a new Rfd and if
+ * successful
+ * adjust the received buffer pointers for the
+ * actual data received;
+ * initialise the replacement buffer to point to
+ * the next in the ring;
+ * initialise bp to point to the replacement;
+ * 4) if there's a good packet, pass it on for disposal.
+ */
+ if(rfd->field & RfdOK){
+ pbp = nil;
+ count = rfd->count & 0x3FFF;
+ if((count < ETHERMAXTU/4) && (pbp = iallocb(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 += offsetof(Rfd, data[0]);
+ bp->wp = bp->rp + count;
+
+ xbp->next = bp->next;
+ bp->next = 0;
+
+ pbp = bp;
+ bp = xbp;
+ }
+ if(pbp != nil)
+ etheriq(ether, pbp, 1);
+ }
+ else{
+ rfd->count = 0;
+ rfd->field = 0;
+ }
+
+ /*
+ * The ring tail pointer follows the head with with one
+ * unused buffer in between to defeat hardware prefetch;
+ * once the tail pointer has been bumped on to the next
+ * and the new tail has the Suspend bit set, it can be
+ * removed from the old tail buffer.
+ * As a replacement for the current head buffer may have
+ * been allocated above, ensure that the new tail points
+ * to it (next and link).
+ */
+ rfd = (Rfd*)ctlr->rfdtail->rp;
+ ctlr->rfdtail = ctlr->rfdtail->next;
+ ctlr->rfdtail->next = bp;
+ ((Rfd*)ctlr->rfdtail->rp)->link = PADDR(bp->rp);
+ ((Rfd*)ctlr->rfdtail->rp)->field |= RfdS;
+ coherence();
+ rfd->field &= ~RfdS;
+
+ /*
+ * Finally done with the current (possibly replaced)
+ * head, move on to the next and maintain the sentinel
+ * between tail and head.
+ */
+ ctlr->rfdhead = bp->next;
+ bp = ctlr->rfdhead;
+ }
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ Cb* cb;
+ Ctlr *ctlr;
+ Ether *ether;
+ int status;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+
+ for(;;){
+ ilock(&ctlr->rlock);
+ status = csr16r(ctlr, Status);
+ csr8w(ctlr, Ack, (status>>8) & 0xFF);
+ iunlock(&ctlr->rlock);
+
+ if(!(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI)))
+ break;
+
+ /*
+ * If the watchdog timer for the receiver lockup errata is running,
+ * let it know the receiver is active.
+ */
+ if(status & (StatFR|StatRNR)){
+ ilock(&ctlr->cblock);
+ ctlr->tick = 0;
+ iunlock(&ctlr->cblock);
+ }
+
+ if(status & StatFR){
+ receive(ether);
+ status &= ~StatFR;
+ }
+
+ if(status & StatRNR){
+ command(ctlr, RUresume, 0);
+ status &= ~StatRNR;
+ }
+
+ if(status & StatCNA){
+ ilock(&ctlr->cblock);
+
+ cb = ctlr->cbtail;
+ while(ctlr->cbq){
+ if(!(cb->status & CbC))
+ break;
+ if(cb->bp){
+ freeb(cb->bp);
+ cb->bp = nil;
+ }
+ if((cb->status & CbU) && ctlr->threshold < 0xE0)
+ ctlr->threshold++;
+
+ ctlr->cbq--;
+ cb = cb->next;
+ }
+ ctlr->cbtail = cb;
+
+ txstart(ether);
+ iunlock(&ctlr->cblock);
+
+ status &= ~StatCNA;
+ }
+
+ if(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI))
+ panic("#l%d: status %#ux\n", ether->ctlrno, status);
+ }
+}
+
+static void
+ctlrinit(Ctlr* ctlr)
+{
+ int i;
+ Block *bp;
+ Rfd *rfd;
+ ulong link;
+
+ /*
+ * Create the Receive Frame Area (RFA) as a ring of allocated
+ * buffers.
+ * A sentinel buffer is maintained between the last buffer in
+ * the ring (marked with RfdS) and the head buffer to defeat the
+ * hardware prefetch of the next RFD and allow dynamic buffer
+ * allocation.
+ */
+ link = NullPointer;
+ for(i = 0; i < Nrfd; i++){
+ bp = rfdalloc(link);
+ if(ctlr->rfdhead == nil)
+ ctlr->rfdtail = bp;
+ bp->next = ctlr->rfdhead;
+ ctlr->rfdhead = bp;
+ link = PADDR(bp->rp);
+ }
+ ctlr->rfdtail->next = ctlr->rfdhead;
+ rfd = (Rfd*)ctlr->rfdtail->rp;
+ rfd->link = PADDR(ctlr->rfdhead->rp);
+ rfd->field |= RfdS;
+ ctlr->rfdhead = ctlr->rfdhead->next;
+
+ /*
+ * Create a ring of control blocks for the
+ * transmit side.
+ */
+ ilock(&ctlr->cblock);
+ ctlr->cbr = malloc(ctlr->ncb*sizeof(Cb));
+ for(i = 0; i < ctlr->ncb; i++){
+ ctlr->cbr[i].status = CbC|CbOK;
+ ctlr->cbr[i].command = CbS|CbNOP;
+ ctlr->cbr[i].link = PADDR(&ctlr->cbr[NEXT(i, ctlr->ncb)].status);
+ ctlr->cbr[i].next = &ctlr->cbr[NEXT(i, ctlr->ncb)];
+ }
+ ctlr->cbhead = ctlr->cbr;
+ ctlr->cbtail = ctlr->cbr;
+ ctlr->cbq = 0;
+
+ memmove(ctlr->configdata, configdata, sizeof(configdata));
+ ctlr->threshold = 80;
+ ctlr->tick = 0;
+
+ iunlock(&ctlr->cblock);
+}
+
+static int
+miir(Ctlr* ctlr, int phyadd, int regadd)
+{
+ int mcr, timo;
+
+ lock(&ctlr->miilock);
+ csr32w(ctlr, Mcr, MDIread|(phyadd<<21)|(regadd<<16));
+ mcr = 0;
+ for(timo = 64; timo; timo--){
+ mcr = csr32r(ctlr, Mcr);
+ if(mcr & MDIready)
+ break;
+ microdelay(1);
+ }
+ unlock(&ctlr->miilock);
+
+ if(mcr & MDIready)
+ return mcr & 0xFFFF;
+
+ return -1;
+}
+
+static int
+miiw(Ctlr* ctlr, int phyadd, int regadd, int data)
+{
+ int mcr, timo;
+
+ lock(&ctlr->miilock);
+ csr32w(ctlr, Mcr, MDIwrite|(phyadd<<21)|(regadd<<16)|(data & 0xFFFF));
+ mcr = 0;
+ for(timo = 64; timo; timo--){
+ mcr = csr32r(ctlr, Mcr);
+ if(mcr & MDIready)
+ break;
+ microdelay(1);
+ }
+ unlock(&ctlr->miilock);
+
+ if(mcr & MDIready)
+ return 0;
+
+ return -1;
+}
+
+static int
+hy93c46r(Ctlr* ctlr, int r)
+{
+ int data, i, op, size;
+
+ /*
+ * Hyundai HY93C46 or equivalent serial EEPROM.
+ * This sequence for reading a 16-bit register 'r'
+ * in the EEPROM is taken straight from Section
+ * 3.3.4.2 of the Intel 82557 User's Guide.
+ */
+reread:
+ csr16w(ctlr, Ecr, EEcs);
+ op = EEstart|EEread;
+ for(i = 2; i >= 0; i--){
+ data = (((op>>i) & 0x01)<<2)|EEcs;
+ csr16w(ctlr, Ecr, data);
+ csr16w(ctlr, Ecr, data|EEsk);
+ microdelay(1);
+ csr16w(ctlr, Ecr, data);
+ microdelay(1);
+ }
+
+ /*
+ * First time through must work out the EEPROM size.
+ */
+ if((size = ctlr->eepromsz) == 0)
+ size = 8;
+
+ for(size = size-1; size >= 0; size--){
+ data = (((r>>size) & 0x01)<<2)|EEcs;
+ csr16w(ctlr, Ecr, data);
+ csr16w(ctlr, Ecr, data|EEsk);
+ delay(1);
+ csr16w(ctlr, Ecr, data);
+ microdelay(1);
+ if(!(csr16r(ctlr, Ecr) & EEdo))
+ break;
+ }
+
+ data = 0;
+ for(i = 15; i >= 0; i--){
+ csr16w(ctlr, Ecr, EEcs|EEsk);
+ microdelay(1);
+ if(csr16r(ctlr, Ecr) & EEdo)
+ data |= (1<<i);
+ csr16w(ctlr, Ecr, EEcs);
+ microdelay(1);
+ }
+
+ csr16w(ctlr, Ecr, 0);
+
+ if(ctlr->eepromsz == 0){
+ ctlr->eepromsz = 8-size;
+ ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
+ goto reread;
+ }
+
+ return data;
+}
+
+static void
+i82557pci(void)
+{
+ Pcidev *p;
+ Ctlr *ctlr;
+ int i, nop, port;
+
+ p = nil;
+ nop = 0;
+ while(p = pcimatch(p, 0x8086, 0)){
+ switch(p->did){
+ default:
+ continue;
+ case 0x1031: /* Intel 82562EM */
+ case 0x103B: /* Intel 82562EM */
+ case 0x103C: /* Intel 82562EM */
+ case 0x1050: /* Intel 82562EZ */
+ case 0x1039: /* Intel 82801BD PRO/100 VE */
+ case 0x103A: /* Intel 82562 PRO/100 VE */
+ case 0x103D: /* Intel 82562 PRO/100 VE */
+ case 0x1064: /* Intel 82562 PRO/100 VE */
+ case 0x2449: /* Intel 82562ET */
+ case 0x27DC: /* Intel 82801G PRO/100 VE */
+ nop = 1;
+ /*FALLTHROUGH*/
+ case 0x1209: /* Intel 82559ER */
+ case 0x1229: /* Intel 8255[789] */
+ case 0x1030: /* Intel 82559 InBusiness 10/100 */
+ break;
+ }
+
+ if(pcigetpms(p) > 0){
+ pcisetpms(p, 0);
+
+ for(i = 0; i < 6; i++)
+ pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
+ pcicfgw8(p, PciINTL, p->intl);
+ pcicfgw8(p, PciLTR, p->ltr);
+ pcicfgw8(p, PciCLS, p->cls);
+ pcicfgw16(p, PciPCR, p->pcr);
+ }
+
+ /*
+ * bar[0] is the memory-mapped register address (4KB),
+ * bar[1] is the I/O port register address (32 bytes) and
+ * bar[2] is for the flash ROM (1MB).
+ */
+ port = p->mem[1].bar & ~0x01;
+ if(ioalloc(port, p->mem[1].size, 0, "i82557") < 0){
+ print("i82557: port %#ux in use\n", port);
+ continue;
+ }
+
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = port;
+ ctlr->pcidev = p;
+ ctlr->nop = nop;
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+
+ pcisetbme(p);
+ }
+}
+
+static char* mediatable[9] = {
+ "10BASE-T", /* TP */
+ "10BASE-2", /* BNC */
+ "10BASE-5", /* AUI */
+ "100BASE-TX",
+ "10BASE-TFD",
+ "100BASE-TXFD",
+ "100BASE-T4",
+ "100BASE-FX",
+ "100BASE-FXFD",
+};
+
+static int
+scanphy(Ctlr* ctlr)
+{
+ int i, oui, x;
+
+ for(i = 0; i < 32; i++){
+ if((oui = miir(ctlr, i, 2)) == -1 || oui == 0 || oui == 0xFFFF)
+ continue;
+ oui <<= 6;
+ x = miir(ctlr, i, 3);
+ oui |= x>>10;
+ //print("phy%d: oui %#ux reg1 %#ux\n", i, oui, miir(ctlr, i, 1));
+
+ ctlr->eeprom[6] = i;
+ if(oui == 0xAA00)
+ ctlr->eeprom[6] |= 0x07<<8;
+ else if(oui == 0x80017){
+ if(x & 0x01)
+ ctlr->eeprom[6] |= 0x0A<<8;
+ else
+ ctlr->eeprom[6] |= 0x04<<8;
+ }
+ return i;
+ }
+ return -1;
+}
+
+static void
+shutdown(Ether* ether)
+{
+ Ctlr *ctlr = ether->ctlr;
+
+print("ether82557 shutting down\n");
+ csr32w(ctlr, Port, 0);
+ delay(1);
+ csr8w(ctlr, Interrupt, InterruptM);
+}
+
+
+static int
+reset(Ether* ether)
+{
+ int anar, anlpar, bmcr, bmsr, i, k, medium, phyaddr, x;
+ unsigned short sum;
+ uchar ea[Eaddrlen];
+ Ctlr *ctlr;
+
+ if(ctlrhead == nil)
+ i82557pci();
+
+ /*
+ * Any adapter matches if no ether->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(ether->port == 0 || ether->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ /*
+ * Initialise the Ctlr structure.
+ * Perform a software reset after which should ensure busmastering
+ * is still enabled. The EtherExpress PRO/100B appears to leave
+ * the PCI configuration alone (see the 'To do' list above) so punt
+ * for now.
+ * Load the RUB and CUB registers for linear addressing (0).
+ */
+ ether->ctlr = ctlr;
+ ether->port = ctlr->port;
+ ether->irq = ctlr->pcidev->intl;
+ ether->tbdf = ctlr->pcidev->tbdf;
+
+ ilock(&ctlr->rlock);
+ csr32w(ctlr, Port, 0);
+ delay(1);
+ csr8w(ctlr, Interrupt, InterruptM);
+ iunlock(&ctlr->rlock);
+
+ command(ctlr, LoadRUB, 0);
+ command(ctlr, LoadCUB, 0);
+ command(ctlr, LoadDCA, PADDR(ctlr->dump));
+
+ /*
+ * Initialise the receive frame, transmit ring and configuration areas.
+ */
+ ctlr->ncb = Ncb;
+ ctlrinit(ctlr);
+
+ /*
+ * Read the EEPROM.
+ * Do a dummy read first to get the size
+ * and allocate ctlr->eeprom.
+ */
+ hy93c46r(ctlr, 0);
+ sum = 0;
+ for(i = 0; i < (1<<ctlr->eepromsz); i++){
+ x = hy93c46r(ctlr, i);
+ ctlr->eeprom[i] = x;
+ sum += x;
+ }
+ if(sum != 0xBABA)
+ print("#l%d: EEPROM checksum - %#4.4ux\n", ether->ctlrno, sum);
+
+ /*
+ * Eeprom[6] indicates whether there is a PHY and whether
+ * it's not 10Mb-only, in which case use the given PHY address
+ * to set any PHY specific options and determine the speed.
+ * Unfortunately, sometimes the EEPROM is blank except for
+ * the ether address and checksum; in this case look at the
+ * controller type and if it's am 82558 or 82559 it has an
+ * embedded PHY so scan for that.
+ * If no PHY, assume 82503 (serial) operation.
+ */
+ if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000))
+ phyaddr = ctlr->eeprom[6] & 0x00FF;
+ else
+ switch(ctlr->pcidev->rid){
+ case 0x01: /* 82557 A-step */
+ case 0x02: /* 82557 B-step */
+ case 0x03: /* 82557 C-step */
+ default:
+ phyaddr = -1;
+ break;
+ case 0x04: /* 82558 A-step */
+ case 0x05: /* 82558 B-step */
+ case 0x06: /* 82559 A-step */
+ case 0x07: /* 82559 B-step */
+ case 0x08: /* 82559 C-step */
+ case 0x09: /* 82559ER A-step */
+ phyaddr = scanphy(ctlr);
+ break;
+ }
+ if(phyaddr >= 0){
+ /*
+ * Resolve the highest common ability of the two
+ * link partners. In descending order:
+ * 0x0100 100BASE-TX Full Duplex
+ * 0x0200 100BASE-T4
+ * 0x0080 100BASE-TX
+ * 0x0040 10BASE-T Full Duplex
+ * 0x0020 10BASE-T
+ */
+ anar = miir(ctlr, phyaddr, 0x04);
+ anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;
+ anar &= anlpar;
+ bmcr = 0;
+ if(anar & 0x380)
+ bmcr = 0x2000;
+ if(anar & 0x0140)
+ bmcr |= 0x0100;
+
+ switch((ctlr->eeprom[6]>>8) & 0x001F){
+
+ case 0x04: /* DP83840 */
+ case 0x0A: /* DP83840A */
+ /*
+ * The DP83840[A] requires some tweaking for
+ * reliable operation.
+ * The manual says bit 10 should be unconditionally
+ * set although it supposedly only affects full-duplex
+ * operation (an & 0x0140).
+ */
+ x = miir(ctlr, phyaddr, 0x17) & ~0x0520;
+ x |= 0x0420;
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrcmp(ether->opt[i], "congestioncontrol"))
+ continue;
+ x |= 0x0100;
+ break;
+ }
+ miiw(ctlr, phyaddr, 0x17, x);
+
+ /*
+ * If the link partner can't autonegotiate, determine
+ * the speed from elsewhere.
+ */
+ if(anlpar == 0){
+ miir(ctlr, phyaddr, 0x01);
+ bmsr = miir(ctlr, phyaddr, 0x01);
+ x = miir(ctlr, phyaddr, 0x19);
+ if((bmsr & 0x0004) && !(x & 0x0040))
+ bmcr = 0x2000;
+ }
+ break;
+
+ case 0x07: /* Intel 82555 */
+ /*
+ * Auto-negotiation may fail if the other end is
+ * a DP83840A and the cable is short.
+ */
+ miir(ctlr, phyaddr, 0x01);
+ bmsr = miir(ctlr, phyaddr, 0x01);
+ if((miir(ctlr, phyaddr, 0) & 0x1000) && !(bmsr & 0x0020)){
+ miiw(ctlr, phyaddr, 0x1A, 0x2010);
+ x = miir(ctlr, phyaddr, 0);
+ miiw(ctlr, phyaddr, 0, 0x0200|x);
+ for(i = 0; i < 3000; i++){
+ delay(1);
+ if(miir(ctlr, phyaddr, 0x01) & 0x0020)
+ break;
+ }
+ miiw(ctlr, phyaddr, 0x1A, 0x2000);
+
+ anar = miir(ctlr, phyaddr, 0x04);
+ anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;
+ anar &= anlpar;
+ bmcr = 0;
+ if(anar & 0x380)
+ bmcr = 0x2000;
+ if(anar & 0x0140)
+ bmcr |= 0x0100;
+ }
+ break;
+ }
+
+ /*
+ * Force speed and duplex if no auto-negotiation.
+ */
+ if(anlpar == 0){
+ medium = -1;
+ for(i = 0; i < ether->nopt; i++){
+ for(k = 0; k < nelem(mediatable); k++){
+ if(cistrcmp(mediatable[k], ether->opt[i]))
+ continue;
+ medium = k;
+ break;
+ }
+
+ switch(medium){
+ default:
+ break;
+
+ case 0x00: /* 10BASE-T */
+ case 0x01: /* 10BASE-2 */
+ case 0x02: /* 10BASE-5 */
+ bmcr &= ~(0x2000|0x0100);
+ ctlr->configdata[19] &= ~0x40;
+ break;
+
+ case 0x03: /* 100BASE-TX */
+ case 0x06: /* 100BASE-T4 */
+ case 0x07: /* 100BASE-FX */
+ ctlr->configdata[19] &= ~0x40;
+ bmcr |= 0x2000;
+ break;
+
+ case 0x04: /* 10BASE-TFD */
+ bmcr = (bmcr & ~0x2000)|0x0100;
+ ctlr->configdata[19] |= 0x40;
+ break;
+
+ case 0x05: /* 100BASE-TXFD */
+ case 0x08: /* 100BASE-FXFD */
+ bmcr |= 0x2000|0x0100;
+ ctlr->configdata[19] |= 0x40;
+ break;
+ }
+ }
+ if(medium != -1)
+ miiw(ctlr, phyaddr, 0x00, bmcr);
+ }
+
+ if(bmcr & 0x2000)
+ ether->mbps = 100;
+
+ ctlr->configdata[8] = 1;
+ ctlr->configdata[15] &= ~0x80;
+ }
+ else{
+ ctlr->configdata[8] = 0;
+ ctlr->configdata[15] |= 0x80;
+ }
+
+ /*
+ * Workaround for some broken HUB chips when connected at 10Mb/s
+ * half-duplex.
+ * This is a band-aid, but as there's no dynamic auto-negotiation
+ * code at the moment, only deactivate the workaround code in txstart
+ * if the link is 100Mb/s.
+ */
+ if(ether->mbps != 10)
+ ctlr->nop = 0;
+
+ /*
+ * Load the chip configuration and start it off.
+ */
+ if(ether->oq == 0)
+ ether->oq = qopen(256*1024, Qmsg, 0, 0);
+ configure(ether, 0);
+ command(ctlr, CUstart, PADDR(&ctlr->cbr->status));
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to loading
+ * the station address with the Individual Address Setup command.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+ for(i = 0; i < Eaddrlen/2; i++){
+ x = ctlr->eeprom[i];
+ ether->ea[2*i] = x;
+ ether->ea[2*i+1] = x>>8;
+ }
+ }
+
+ ilock(&ctlr->cblock);
+ ctlr->action = CbIAS;
+ txstart(ether);
+ iunlock(&ctlr->cblock);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->ifstat = ifstat;
+ ether->shutdown = shutdown;
+
+ ether->promiscuous = promiscuous;
+ ether->multicast = multicast;
+ ether->arg = ether;
+
+ return 0;
+}
+
+void
+ether82557link(void)
+{
+ addethercard("i82557", reset);
+}
diff --git a/sys/src/9/pc/ether82563.c b/sys/src/9/pc/ether82563.c
new file mode 100755
index 000000000..385840ff3
--- /dev/null
+++ b/sys/src/9/pc/ether82563.c
@@ -0,0 +1,1773 @@
+/*
+ * Intel Gigabit Ethernet PCI-Express Controllers.
+ * 8256[36], 8257[12], 82573[ev]
+ * 82575eb, 82576
+ * Pretty basic, does not use many of the chip smarts.
+ * The interrupt mitigation tuning for each chip variant
+ * is probably different. The reset/initialisation
+ * sequence needs straightened out. Doubt the PHY code
+ * for the 82575eb is right.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+/*
+ * these are in the order they appear in the manual, not numeric order.
+ * It was too hard to find them in the book. Ref 21489, rev 2.6
+ */
+
+enum {
+ /* General */
+
+ Ctrl = 0x0000, /* Device Control */
+ Status = 0x0008, /* Device Status */
+ Eec = 0x0010, /* EEPROM/Flash Control/Data */
+ Eerd = 0x0014, /* EEPROM Read */
+ Ctrlext = 0x0018, /* Extended Device Control */
+ Fla = 0x001c, /* Flash Access */
+ Mdic = 0x0020, /* MDI Control */
+ Seresctl = 0x0024, /* Serdes ana */
+ Fcal = 0x0028, /* Flow Control Address Low */
+ Fcah = 0x002C, /* Flow Control Address High */
+ Fct = 0x0030, /* Flow Control Type */
+ Kumctrlsta = 0x0034, /* MAC-PHY Interface */
+ Vet = 0x0038, /* VLAN EtherType */
+ Fcttv = 0x0170, /* Flow Control Transmit Timer Value */
+ Txcw = 0x0178, /* Transmit Configuration Word */
+ Rxcw = 0x0180, /* Receive Configuration Word */
+ Ledctl = 0x0E00, /* LED control */
+ Pba = 0x1000, /* Packet Buffer Allocation */
+ Pbs = 0x1008, /* Packet Buffer Size */
+
+ /* Interrupt */
+
+ Icr = 0x00C0, /* Interrupt Cause Read */
+ Itr = 0x00c4, /* Interrupt Throttling Rate */
+ Ics = 0x00C8, /* Interrupt Cause Set */
+ Ims = 0x00D0, /* Interrupt Mask Set/Read */
+ Imc = 0x00D8, /* Interrupt mask Clear */
+ Iam = 0x00E0, /* Interrupt acknowledge Auto Mask */
+
+ /* Receive */
+
+ Rctl = 0x0100, /* Control */
+ Ert = 0x2008, /* Early Receive Threshold (573[EVL] only) */
+ Fcrtl = 0x2160, /* Flow Control RX Threshold Low */
+ Fcrth = 0x2168, /* Flow Control Rx Threshold High */
+ Psrctl = 0x2170, /* Packet Split Receive Control */
+ Rdbal = 0x2800, /* Rdesc Base Address Low Queue 0 */
+ Rdbah = 0x2804, /* Rdesc Base Address High Queue 0 */
+ Rdlen = 0x2808, /* Descriptor Length Queue 0 */
+ Rdh = 0x2810, /* Descriptor Head Queue 0 */
+ Rdt = 0x2818, /* Descriptor Tail Queue 0 */
+ Rdtr = 0x2820, /* Descriptor Timer Ring */
+ Rxdctl = 0x2828, /* Descriptor Control */
+ Radv = 0x282C, /* Interrupt Absolute Delay Timer */
+ Rdbal1 = 0x2900, /* Rdesc Base Address Low Queue 1 */
+ Rdbah1 = 0x2804, /* Rdesc Base Address High Queue 1 */
+ Rdlen1 = 0x2908, /* Descriptor Length Queue 1 */
+ Rdh1 = 0x2910, /* Descriptor Head Queue 1 */
+ Rdt1 = 0x2918, /* Descriptor Tail Queue 1 */
+ Rxdctl1 = 0x2928, /* Descriptor Control Queue 1 */
+ Rsrpd = 0x2c00, /* Small Packet Detect */
+ Raid = 0x2c08, /* ACK interrupt delay */
+ Cpuvec = 0x2c10, /* CPU Vector */
+ Rxcsum = 0x5000, /* Checksum Control */
+ Rfctl = 0x5008, /* Filter Control */
+ Mta = 0x5200, /* Multicast Table Array */
+ Ral = 0x5400, /* Receive Address Low */
+ Rah = 0x5404, /* Receive Address High */
+ Vfta = 0x5600, /* VLAN Filter Table Array */
+ Mrqc = 0x5818, /* Multiple Receive Queues Command */
+ Rssim = 0x5864, /* RSS Interrupt Mask */
+ Rssir = 0x5868, /* RSS Interrupt Request */
+ Reta = 0x5c00, /* Redirection Table */
+ Rssrk = 0x5c80, /* RSS Random Key */
+
+ /* Transmit */
+
+ Tctl = 0x0400, /* Transmit Control */
+ Tipg = 0x0410, /* Transmit IPG */
+ Tkabgtxd = 0x3004, /* glci afe band gap transmit ref data, or something */
+ Tdbal = 0x3800, /* Tdesc Base Address Low */
+ Tdbah = 0x3804, /* Tdesc Base Address High */
+ Tdlen = 0x3808, /* Descriptor Length */
+ Tdh = 0x3810, /* Descriptor Head */
+ Tdt = 0x3818, /* Descriptor Tail */
+ Tidv = 0x3820, /* Interrupt Delay Value */
+ Txdctl = 0x3828, /* Descriptor Control */
+ Tadv = 0x382C, /* Interrupt Absolute Delay Timer */
+ Tarc0 = 0x3840, /* Arbitration Counter Queue 0 */
+ Tdbal1 = 0x3900, /* Descriptor Base Low Queue 1 */
+ Tdbah1 = 0x3904, /* Descriptor Base High Queue 1 */
+ Tdlen1 = 0x3908, /* Descriptor Length Queue 1 */
+ Tdh1 = 0x3910, /* Descriptor Head Queue 1 */
+ Tdt1 = 0x3918, /* Descriptor Tail Queue 1 */
+ Txdctl1 = 0x3928, /* Descriptor Control 1 */
+ Tarc1 = 0x3940, /* Arbitration Counter Queue 1 */
+
+ /* Statistics */
+
+ Statistics = 0x4000, /* Start of Statistics Area */
+ Gorcl = 0x88/4, /* Good Octets Received Count */
+ Gotcl = 0x90/4, /* Good Octets Transmitted Count */
+ Torl = 0xC0/4, /* Total Octets Received */
+ Totl = 0xC8/4, /* Total Octets Transmitted */
+ Nstatistics = 0x124/4,
+};
+
+enum { /* Ctrl */
+ GIOmd = 1<<2, /* BIO master disable */
+ Lrst = 1<<3, /* link reset */
+ Slu = 1<<6, /* Set Link Up */
+ SspeedMASK = 3<<8, /* Speed Selection */
+ SspeedSHIFT = 8,
+ Sspeed10 = 0x00000000, /* 10Mb/s */
+ Sspeed100 = 0x00000100, /* 100Mb/s */
+ Sspeed1000 = 0x00000200, /* 1000Mb/s */
+ Frcspd = 1<<11, /* Force Speed */
+ Frcdplx = 1<<12, /* Force Duplex */
+ SwdpinsloMASK = 0x003C0000, /* Software Defined Pins - lo nibble */
+ SwdpinsloSHIFT = 18,
+ SwdpioloMASK = 0x03C00000, /* Software Defined Pins - I or O */
+ SwdpioloSHIFT = 22,
+ Devrst = 1<<26, /* Device Reset */
+ Rfce = 1<<27, /* Receive Flow Control Enable */
+ Tfce = 1<<28, /* Transmit Flow Control Enable */
+ Vme = 1<<30, /* VLAN Mode Enable */
+ Phyrst = 1<<31, /* Phy Reset */
+};
+
+enum { /* Status */
+ Lu = 1<<1, /* Link Up */
+ Lanid = 3<<2, /* mask for Lan ID. */
+ Txoff = 1<<4, /* Transmission Paused */
+ Tbimode = 1<<5, /* TBI Mode Indication */
+ Phyra = 1<<10, /* PHY Reset Asserted */
+ GIOme = 1<<19, /* GIO Master Enable Status */
+};
+
+enum { /* Eerd */
+ EEstart = 1<<0, /* Start Read */
+ EEdone = 1<<1, /* Read done */
+};
+
+enum { /* Ctrlext */
+ Asdchk = 1<<12, /* ASD Check */
+ Eerst = 1<<13, /* EEPROM Reset */
+ Spdbyps = 1<<15, /* Speed Select Bypass */
+};
+
+enum { /* EEPROM content offsets */
+ Ea = 0x00, /* Ethernet Address */
+ Cf = 0x03, /* Compatibility Field */
+ Icw1 = 0x0A, /* Initialization Control Word 1 */
+ Sid = 0x0B, /* Subsystem ID */
+ Svid = 0x0C, /* Subsystem Vendor ID */
+ Did = 0x0D, /* Device ID */
+ Vid = 0x0E, /* Vendor ID */
+ Icw2 = 0x0F, /* Initialization Control Word 2 */
+};
+
+enum { /* Mdic */
+ MDIdMASK = 0x0000FFFF, /* Data */
+ MDIdSHIFT = 0,
+ MDIrMASK = 0x001F0000, /* PHY Register Address */
+ MDIrSHIFT = 16,
+ MDIpMASK = 0x03E00000, /* PHY Address */
+ MDIpSHIFT = 21,
+ MDIwop = 0x04000000, /* Write Operation */
+ MDIrop = 0x08000000, /* Read Operation */
+ MDIready = 0x10000000, /* End of Transaction */
+ MDIie = 0x20000000, /* Interrupt Enable */
+ MDIe = 0x40000000, /* Error */
+};
+
+enum { /* phy interface registers */
+ Phyctl = 0, /* phy ctl */
+ Physsr = 17, /* phy secondary status */
+ Phyier = 18, /* 82573 phy interrupt enable */
+ Phyisr = 19, /* 82563 phy interrupt status */
+ Phylhr = 19, /* 8257[12] link health */
+
+ Rtlink = 1<<10, /* realtime link status */
+ Phyan = 1<<11, /* phy has auto-negotiated */
+
+ /* Phyctl bits */
+ Ran = 1<<9, /* restart auto-negotiation */
+ Ean = 1<<12, /* enable auto-negotiation */
+
+ /* 82573 Phyier bits */
+ Lscie = 1<<10, /* link status changed ie */
+ Ancie = 1<<11, /* auto-negotiation complete ie */
+ Spdie = 1<<14, /* speed changed ie */
+ Panie = 1<<15, /* phy auto-negotiation error ie */
+
+ /* Phylhr/Phyisr bits */
+ Anf = 1<<6, /* lhr: auto-negotiation fault */
+ Ane = 1<<15, /* isr: auto-negotiation error */
+};
+
+enum { /* Icr, Ics, Ims, Imc */
+ Txdw = 0x00000001, /* Transmit Descriptor Written Back */
+ Txqe = 0x00000002, /* Transmit Queue Empty */
+ Lsc = 0x00000004, /* Link Status Change */
+ Rxseq = 0x00000008, /* Receive Sequence Error */
+ Rxdmt0 = 0x00000010, /* Rdesc Minimum Threshold Reached */
+ Rxo = 0x00000040, /* Receiver Overrun */
+ Rxt0 = 0x00000080, /* Receiver Timer Interrupt */
+ Mdac = 0x00000200, /* MDIO Access Completed */
+ Rxcfg = 0x00000400, /* Receiving /C/ ordered sets */
+ Gpi0 = 0x00000800, /* General Purpose Interrupts */
+ Gpi1 = 0x00001000,
+ Gpi2 = 0x00002000,
+ Gpi3 = 0x00004000,
+ Ack = 0x00020000, /* Receive ACK frame */
+};
+
+enum { /* Txcw */
+ TxcwFd = 0x00000020, /* Full Duplex */
+ TxcwHd = 0x00000040, /* Half Duplex */
+ TxcwPauseMASK = 0x00000180, /* Pause */
+ TxcwPauseSHIFT = 7,
+ TxcwPs = 1<<TxcwPauseSHIFT, /* Pause Supported */
+ TxcwAs = 2<<TxcwPauseSHIFT, /* Asymmetric FC desired */
+ TxcwRfiMASK = 0x00003000, /* Remote Fault Indication */
+ TxcwRfiSHIFT = 12,
+ TxcwNpr = 0x00008000, /* Next Page Request */
+ TxcwConfig = 0x40000000, /* Transmit Config Control */
+ TxcwAne = 0x80000000, /* Auto-Negotiation Enable */
+};
+
+enum { /* Rctl */
+ Rrst = 0x00000001, /* Receiver Software Reset */
+ Ren = 0x00000002, /* Receiver Enable */
+ Sbp = 0x00000004, /* Store Bad Packets */
+ Upe = 0x00000008, /* Unicast Promiscuous Enable */
+ Mpe = 0x00000010, /* Multicast Promiscuous Enable */
+ Lpe = 0x00000020, /* Long Packet Reception Enable */
+ LbmMASK = 0x000000C0, /* Loopback Mode */
+ LbmOFF = 0x00000000, /* No Loopback */
+ LbmTBI = 0x00000040, /* TBI Loopback */
+ LbmMII = 0x00000080, /* GMII/MII Loopback */
+ LbmXCVR = 0x000000C0, /* Transceiver Loopback */
+ RdtmsMASK = 0x00000300, /* Rdesc Minimum Threshold Size */
+ RdtmsHALF = 0x00000000, /* Threshold is 1/2 Rdlen */
+ RdtmsQUARTER = 0x00000100, /* Threshold is 1/4 Rdlen */
+ RdtmsEIGHTH = 0x00000200, /* Threshold is 1/8 Rdlen */
+ MoMASK = 0x00003000, /* Multicast Offset */
+ Bam = 0x00008000, /* Broadcast Accept Mode */
+ BsizeMASK = 0x00030000, /* Receive Buffer Size */
+ Bsize16384 = 0x00010000, /* Bsex = 1 */
+ Bsize8192 = 0x00020000, /* Bsex = 1 */
+ Bsize2048 = 0x00000000,
+ Bsize1024 = 0x00010000,
+ Bsize512 = 0x00020000,
+ Bsize256 = 0x00030000,
+ BsizeFlex = 0x08000000, /* Flexible Bsize in 1KB increments */
+ Vfe = 0x00040000, /* VLAN Filter Enable */
+ Cfien = 0x00080000, /* Canonical Form Indicator Enable */
+ Cfi = 0x00100000, /* Canonical Form Indicator value */
+ Dpf = 0x00400000, /* Discard Pause Frames */
+ Pmcf = 0x00800000, /* Pass MAC Control Frames */
+ Bsex = 0x02000000, /* Buffer Size Extension */
+ Secrc = 0x04000000, /* Strip CRC from incoming packet */
+};
+
+enum { /* Tctl */
+ Trst = 0x00000001, /* Transmitter Software Reset */
+ Ten = 0x00000002, /* Transmit Enable */
+ Psp = 0x00000008, /* Pad Short Packets */
+ Mulr = 0x10000000, /* Allow multiple concurrent requests */
+ CtMASK = 0x00000FF0, /* Collision Threshold */
+ CtSHIFT = 4,
+ ColdMASK = 0x003FF000, /* Collision Distance */
+ ColdSHIFT = 12,
+ Swxoff = 0x00400000, /* Sofware XOFF Transmission */
+ Pbe = 0x00800000, /* Packet Burst Enable */
+ Rtlc = 0x01000000, /* Re-transmit on Late Collision */
+ Nrtu = 0x02000000, /* No Re-transmit on Underrrun */
+};
+
+enum { /* [RT]xdctl */
+ PthreshMASK = 0x0000003F, /* Prefetch Threshold */
+ PthreshSHIFT = 0,
+ HthreshMASK = 0x00003F00, /* Host Threshold */
+ HthreshSHIFT = 8,
+ WthreshMASK = 0x003F0000, /* Writeback Threshold */
+ WthreshSHIFT = 16,
+ Gran = 0x01000000, /* Granularity */
+ Qenable = 0x02000000, /* Queue Enable (82575) */
+};
+
+enum { /* Rxcsum */
+ PcssMASK = 0x00FF, /* Packet Checksum Start */
+ PcssSHIFT = 0,
+ Ipofl = 0x0100, /* IP Checksum Off-load Enable */
+ Tuofl = 0x0200, /* TCP/UDP Checksum Off-load Enable */
+};
+
+enum { /* Receive Delay Timer Ring */
+ DelayMASK = 0xFFFF, /* delay timer in 1.024nS increments */
+ DelaySHIFT = 0,
+ Fpd = 0x80000000, /* Flush partial Descriptor Block */
+};
+
+typedef struct Rd { /* Receive Descriptor */
+ u32int addr[2];
+ u16int length;
+ u16int checksum;
+ u8int status;
+ u8int errors;
+ u16int special;
+} Rd;
+
+enum { /* Rd status */
+ Rdd = 0x01, /* Descriptor Done */
+ Reop = 0x02, /* End of Packet */
+ Ixsm = 0x04, /* Ignore Checksum Indication */
+ Vp = 0x08, /* Packet is 802.1Q (matched VET) */
+ Tcpcs = 0x20, /* TCP Checksum Calculated on Packet */
+ Ipcs = 0x40, /* IP Checksum Calculated on Packet */
+ Pif = 0x80, /* Passed in-exact filter */
+};
+
+enum { /* Rd errors */
+ Ce = 0x01, /* CRC Error or Alignment Error */
+ Se = 0x02, /* Symbol Error */
+ Seq = 0x04, /* Sequence Error */
+ Cxe = 0x10, /* Carrier Extension Error */
+ Tcpe = 0x20, /* TCP/UDP Checksum Error */
+ Ipe = 0x40, /* IP Checksum Error */
+ Rxe = 0x80, /* RX Data Error */
+};
+
+typedef struct { /* Transmit Descriptor */
+ u32int addr[2]; /* Data */
+ u32int control;
+ u32int status;
+} Td;
+
+enum { /* Tdesc control */
+ LenMASK = 0x000FFFFF, /* Data/Packet Length Field */
+ LenSHIFT = 0,
+ DtypeCD = 0x00000000, /* Data Type 'Context Descriptor' */
+ DtypeDD = 0x00100000, /* Data Type 'Data Descriptor' */
+ PtypeTCP = 0x01000000, /* TCP/UDP Packet Type (CD) */
+ Teop = 0x01000000, /* End of Packet (DD) */
+ PtypeIP = 0x02000000, /* IP Packet Type (CD) */
+ Ifcs = 0x02000000, /* Insert FCS (DD) */
+ Tse = 0x04000000, /* TCP Segmentation Enable */
+ Rs = 0x08000000, /* Report Status */
+ Rps = 0x10000000, /* Report Status Sent */
+ Dext = 0x20000000, /* Descriptor Extension */
+ Vle = 0x40000000, /* VLAN Packet Enable */
+ Ide = 0x80000000, /* Interrupt Delay Enable */
+};
+
+enum { /* Tdesc status */
+ Tdd = 0x0001, /* Descriptor Done */
+ Ec = 0x0002, /* Excess Collisions */
+ Lc = 0x0004, /* Late Collision */
+ Tu = 0x0008, /* Transmit Underrun */
+ CssMASK = 0xFF00, /* Checksum Start Field */
+ CssSHIFT = 8,
+};
+
+typedef struct {
+ u16int *reg;
+ u32int *reg32;
+ int sz;
+} Flash;
+
+enum {
+ /* 16 and 32-bit flash registers for ich flash parts */
+ Bfpr = 0x00/4, /* flash base 0:12; lim 16:28 */
+ Fsts = 0x04/2, /* flash status; Hsfsts */
+ Fctl = 0x06/2, /* flash control; Hsfctl */
+ Faddr = 0x08/4, /* flash address to r/w */
+ Fdata = 0x10/4, /* data @ address */
+
+ /* status register */
+ Fdone = 1<<0, /* flash cycle done */
+ Fcerr = 1<<1, /* cycle error; write 1 to clear */
+ Ael = 1<<2, /* direct access error log; 1 to clear */
+ Scip = 1<<5, /* spi cycle in progress */
+ Fvalid = 1<<14, /* flash descriptor valid */
+
+ /* control register */
+ Fgo = 1<<0, /* start cycle */
+ Flcycle = 1<<1, /* two bits: r=0; w=2 */
+ Fdbc = 1<<8, /* bytes to read; 5 bits */
+};
+
+enum {
+ Nrd = 256, /* power of two */
+ Ntd = 128, /* power of two */
+ Nrb = 1024, /* private receive buffers per Ctlr */
+};
+
+enum {
+ Iany,
+ i82563,
+ i82566,
+ i82567,
+ i82571,
+ i82572,
+ i82573,
+ i82575,
+ i82576,
+};
+
+static int rbtab[] = {
+ 0,
+ 9014,
+ 1514,
+ 1514,
+ 9234,
+ 9234,
+ 8192, /* terrible performance above 8k */
+ 1514,
+ 1514,
+};
+
+static char *tname[] = {
+ "any",
+ "i82563",
+ "i82566",
+ "i82567",
+ "i82571",
+ "i82572",
+ "i82573",
+ "i82575",
+ "i82576",
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ int port;
+ Pcidev *pcidev;
+ Ctlr *next;
+ Ether *edev;
+ int active;
+ int type;
+ ushort eeprom[0x40];
+
+ QLock alock; /* attach */
+ int attached;
+ int nrd;
+ int ntd;
+ int nrb; /* how many this Ctlr has in the pool */
+ unsigned rbsz; /* unsigned for % and / by 1024 */
+
+ int *nic;
+ Lock imlock;
+ int im; /* interrupt mask */
+
+ Rendez lrendez;
+ int lim;
+
+ QLock slock;
+ uint statistics[Nstatistics];
+ uint lsleep;
+ uint lintr;
+ uint rsleep;
+ uint rintr;
+ uint txdw;
+ uint tintr;
+ uint ixsm;
+ uint ipcs;
+ uint tcpcs;
+ uint speeds[4];
+
+ uchar ra[Eaddrlen]; /* receive address */
+ ulong mta[128]; /* multicast table array */
+
+ Rendez rrendez;
+ int rim;
+ int rdfree;
+ Rd *rdba; /* receive descriptor base address */
+ Block **rb; /* receive buffers */
+ int rdh; /* receive descriptor head */
+ int rdt; /* receive descriptor tail */
+ int rdtr; /* receive delay timer ring value */
+ int radv; /* receive interrupt absolute delay timer */
+
+ Rendez trendez;
+ QLock tlock;
+ int tbusy;
+ Td *tdba; /* transmit descriptor base address */
+ Block **tb; /* transmit buffers */
+ int tdh; /* transmit descriptor head */
+ int tdt; /* transmit descriptor tail */
+
+ int fcrtl;
+ int fcrth;
+
+ uint pba; /* packet buffer allocation */
+};
+
+#define csr32r(c, r) (*((c)->nic+((r)/4)))
+#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
+
+static Ctlr* i82563ctlrhead;
+static Ctlr* i82563ctlrtail;
+
+static Lock i82563rblock; /* free receive Blocks */
+static Block* i82563rbpool;
+
+static char* statistics[] = {
+ "CRC Error",
+ "Alignment Error",
+ "Symbol Error",
+ "RX Error",
+ "Missed Packets",
+ "Single Collision",
+ "Excessive Collisions",
+ "Multiple Collision",
+ "Late Collisions",
+ nil,
+ "Collision",
+ "Transmit Underrun",
+ "Defer",
+ "Transmit - No CRS",
+ "Sequence Error",
+ "Carrier Extension Error",
+ "Receive Error Length",
+ nil,
+ "XON Received",
+ "XON Transmitted",
+ "XOFF Received",
+ "XOFF Transmitted",
+ "FC Received Unsupported",
+ "Packets Received (64 Bytes)",
+ "Packets Received (65-127 Bytes)",
+ "Packets Received (128-255 Bytes)",
+ "Packets Received (256-511 Bytes)",
+ "Packets Received (512-1023 Bytes)",
+ "Packets Received (1024-mtu Bytes)",
+ "Good Packets Received",
+ "Broadcast Packets Received",
+ "Multicast Packets Received",
+ "Good Packets Transmitted",
+ nil,
+ "Good Octets Received",
+ nil,
+ "Good Octets Transmitted",
+ nil,
+ nil,
+ nil,
+ "Receive No Buffers",
+ "Receive Undersize",
+ "Receive Fragment",
+ "Receive Oversize",
+ "Receive Jabber",
+ "Management Packets Rx",
+ "Management Packets Drop",
+ "Management Packets Tx",
+ "Total Octets Received",
+ nil,
+ "Total Octets Transmitted",
+ nil,
+ "Total Packets Received",
+ "Total Packets Transmitted",
+ "Packets Transmitted (64 Bytes)",
+ "Packets Transmitted (65-127 Bytes)",
+ "Packets Transmitted (128-255 Bytes)",
+ "Packets Transmitted (256-511 Bytes)",
+ "Packets Transmitted (512-1023 Bytes)",
+ "Packets Transmitted (1024-mtu Bytes)",
+ "Multicast Packets Transmitted",
+ "Broadcast Packets Transmitted",
+ "TCP Segmentation Context Transmitted",
+ "TCP Segmentation Context Fail",
+ "Interrupt Assertion",
+ "Interrupt Rx Pkt Timer",
+ "Interrupt Rx Abs Timer",
+ "Interrupt Tx Pkt Timer",
+ "Interrupt Tx Abs Timer",
+ "Interrupt Tx Queue Empty",
+ "Interrupt Tx Desc Low",
+ "Interrupt Rx Min",
+ "Interrupt Rx Overrun",
+};
+
+static long
+i82563ifstat(Ether* edev, void* a, long n, ulong offset)
+{
+ Ctlr *ctlr;
+ char *s, *p, *e, *stat;
+ int i, r;
+ uvlong tuvl, ruvl;
+
+ ctlr = edev->ctlr;
+ qlock(&ctlr->slock);
+ p = s = malloc(READSTR);
+ e = p + READSTR;
+
+ for(i = 0; i < Nstatistics; i++){
+ r = csr32r(ctlr, Statistics + i*4);
+ if((stat = statistics[i]) == nil)
+ continue;
+ switch(i){
+ case Gorcl:
+ case Gotcl:
+ case Torl:
+ case Totl:
+ ruvl = r;
+ ruvl += (uvlong)csr32r(ctlr, Statistics+(i+1)*4) << 32;
+ tuvl = ruvl;
+ tuvl += ctlr->statistics[i];
+ tuvl += (uvlong)ctlr->statistics[i+1] << 32;
+ if(tuvl == 0)
+ continue;
+ ctlr->statistics[i] = tuvl;
+ ctlr->statistics[i+1] = tuvl >> 32;
+ p = seprint(p, e, "%s: %llud %llud\n", stat, tuvl, ruvl);
+ i++;
+ break;
+
+ default:
+ ctlr->statistics[i] += r;
+ if(ctlr->statistics[i] == 0)
+ continue;
+ p = seprint(p, e, "%s: %ud %ud\n", stat,
+ ctlr->statistics[i], r);
+ break;
+ }
+ }
+
+ p = seprint(p, e, "lintr: %ud %ud\n", ctlr->lintr, ctlr->lsleep);
+ p = seprint(p, e, "rintr: %ud %ud\n", ctlr->rintr, ctlr->rsleep);
+ p = seprint(p, e, "tintr: %ud %ud\n", ctlr->tintr, ctlr->txdw);
+ p = seprint(p, e, "ixcs: %ud %ud %ud\n", ctlr->ixsm, ctlr->ipcs, ctlr->tcpcs);
+ p = seprint(p, e, "rdtr: %ud\n", ctlr->rdtr);
+ p = seprint(p, e, "radv: %ud\n", ctlr->radv);
+ p = seprint(p, e, "ctrl: %.8ux\n", csr32r(ctlr, Ctrl));
+ p = seprint(p, e, "ctrlext: %.8ux\n", csr32r(ctlr, Ctrlext));
+ p = seprint(p, e, "status: %.8ux\n", csr32r(ctlr, Status));
+ p = seprint(p, e, "txcw: %.8ux\n", csr32r(ctlr, Txcw));
+ p = seprint(p, e, "txdctl: %.8ux\n", csr32r(ctlr, Txdctl));
+ p = seprint(p, e, "pba: %.8ux\n", ctlr->pba);
+
+ p = seprint(p, e, "speeds: 10:%ud 100:%ud 1000:%ud ?:%ud\n",
+ ctlr->speeds[0], ctlr->speeds[1], ctlr->speeds[2], ctlr->speeds[3]);
+ p = seprint(p, e, "type: %s\n", tname[ctlr->type]);
+
+// p = seprint(p, e, "eeprom:");
+// for(i = 0; i < 0x40; i++){
+// if(i && ((i & 7) == 0))
+// p = seprint(p, e, "\n ");
+// p = seprint(p, e, " %4.4ux", ctlr->eeprom[i]);
+// }
+// p = seprint(p, e, "\n");
+
+ USED(p);
+ n = readstr(offset, a, n, s);
+ free(s);
+ qunlock(&ctlr->slock);
+
+ return n;
+}
+
+enum {
+ CMrdtr,
+ CMradv,
+};
+
+static Cmdtab i82563ctlmsg[] = {
+ CMrdtr, "rdtr", 2,
+ CMradv, "radv", 2,
+};
+
+static long
+i82563ctl(Ether* edev, void* buf, long n)
+{
+ ulong v;
+ char *p;
+ Ctlr *ctlr;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+
+ if((ctlr = edev->ctlr) == nil)
+ error(Enonexist);
+
+ cb = parsecmd(buf, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+
+ ct = lookupcmd(cb, i82563ctlmsg, nelem(i82563ctlmsg));
+ switch(ct->index){
+ case CMrdtr:
+ v = strtoul(cb->f[1], &p, 0);
+ if(p == cb->f[1] || v > 0xFFFF)
+ error(Ebadarg);
+ ctlr->rdtr = v;
+ csr32w(ctlr, Rdtr, v);
+ break;
+ case CMradv:
+ v = strtoul(cb->f[1], &p, 0);
+ if(p == cb->f[1] || v > 0xFFFF)
+ error(Ebadarg);
+ ctlr->radv = v;
+ csr32w(ctlr, Radv, v);
+ }
+ free(cb);
+ poperror();
+
+ return n;
+}
+
+static void
+i82563promiscuous(void* arg, int on)
+{
+ int rctl;
+ Ctlr *ctlr;
+ Ether *edev;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ rctl = csr32r(ctlr, Rctl);
+ rctl &= ~MoMASK;
+ if(on)
+ rctl |= Upe|Mpe;
+ else
+ rctl &= ~(Upe|Mpe);
+ csr32w(ctlr, Rctl, rctl);
+}
+
+static void
+i82563multicast(void* arg, uchar* addr, int on)
+{
+ int bit, x;
+ Ctlr *ctlr;
+ Ether *edev;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ x = addr[5]>>1;
+ if(ctlr->type == i82566 || ctlr->type == i82567)
+ x &= 31;
+ bit = ((addr[5] & 1)<<4)|(addr[4]>>4);
+ /*
+ * multiple ether addresses can hash to the same filter bit,
+ * so it's never safe to clear a filter bit.
+ * if we want to clear filter bits, we need to keep track of
+ * all the multicast addresses in use, clear all the filter bits,
+ * then set the ones corresponding to in-use addresses.
+ */
+ if(on)
+ ctlr->mta[x] |= 1<<bit;
+// else
+// ctlr->mta[x] &= ~(1<<bit);
+
+ csr32w(ctlr, Mta+x*4, ctlr->mta[x]);
+}
+
+static Block*
+i82563rballoc(void)
+{
+ Block *bp;
+
+ ilock(&i82563rblock);
+ if((bp = i82563rbpool) != nil){
+ i82563rbpool = bp->next;
+ bp->next = nil;
+ _xinc(&bp->ref); /* prevent bp from being freed */
+ }
+ iunlock(&i82563rblock);
+
+ return bp;
+}
+
+static void
+i82563rbfree(Block* b)
+{
+ b->rp = b->wp = (uchar*)PGROUND((uintptr)b->base);
+ b->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
+ ilock(&i82563rblock);
+ b->next = i82563rbpool;
+ i82563rbpool = b;
+ iunlock(&i82563rblock);
+}
+
+static void
+i82563im(Ctlr* ctlr, int im)
+{
+ ilock(&ctlr->imlock);
+ ctlr->im |= im;
+ csr32w(ctlr, Ims, ctlr->im);
+ iunlock(&ctlr->imlock);
+}
+
+static void
+i82563txinit(Ctlr* ctlr)
+{
+ int i, r;
+ Block *bp;
+
+ csr32w(ctlr, Tctl, 0x0F<<CtSHIFT | Psp | 66<<ColdSHIFT | Mulr);
+ csr32w(ctlr, Tipg, 6<<20 | 8<<10 | 8); /* yb sez: 0x702008 */
+ csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
+ csr32w(ctlr, Tdbah, 0);
+ csr32w(ctlr, Tdlen, ctlr->ntd * sizeof(Td));
+ ctlr->tdh = PREV(0, ctlr->ntd);
+ csr32w(ctlr, Tdh, 0);
+ ctlr->tdt = 0;
+ csr32w(ctlr, Tdt, 0);
+ for(i = 0; i < ctlr->ntd; i++){
+ if((bp = ctlr->tb[i]) != nil){
+ ctlr->tb[i] = nil;
+ freeb(bp);
+ }
+ memset(&ctlr->tdba[i], 0, sizeof(Td));
+ }
+ csr32w(ctlr, Tidv, 128);
+ r = csr32r(ctlr, Txdctl);
+ r &= ~(WthreshMASK|PthreshMASK);
+ r |= 4<<WthreshSHIFT | 4<<PthreshSHIFT;
+ if(ctlr->type == i82575 || ctlr->type == i82576)
+ r |= Qenable;
+ csr32w(ctlr, Tadv, 64);
+ csr32w(ctlr, Txdctl, r);
+ r = csr32r(ctlr, Tctl);
+ r |= Ten;
+ csr32w(ctlr, Tctl, r);
+// if(ctlr->type == i82671)
+// csr32w(ctlr, Tarc0, csr32r(ctlr, Tarc0) | 7<<24); /* yb sez? */
+}
+
+#define Next(x, m) (((x)+1) & (m))
+
+static int
+i82563cleanup(Ctlr *c)
+{
+ Block *b;
+ int tdh, m, n;
+
+ tdh = c->tdh;
+ m = c->ntd-1;
+ while(c->tdba[n = Next(tdh, m)].status & Tdd){
+ tdh = n;
+ if((b = c->tb[tdh]) != nil){
+ c->tb[tdh] = nil;
+ freeb(b);
+ }else
+ iprint("82563 tx underrun!\n");
+ c->tdba[tdh].status = 0;
+ }
+
+ return c->tdh = tdh;
+}
+
+static void
+i82563transmit(Ether* edev)
+{
+ Td *td;
+ Block *bp;
+ Ctlr *ctlr;
+ int tdh, tdt, m;
+
+ ctlr = edev->ctlr;
+
+ qlock(&ctlr->tlock);
+
+ /*
+ * Free any completed packets
+ */
+ tdh = i82563cleanup(ctlr);
+
+ /*
+ * Try to fill the ring back up.
+ */
+ tdt = ctlr->tdt;
+ m = ctlr->ntd-1;
+ for(;;){
+ if(Next(tdt, m) == tdh){
+ ctlr->txdw++;
+ i82563im(ctlr, Txdw);
+ break;
+ }
+ if((bp = qget(edev->oq)) == nil)
+ break;
+ td = &ctlr->tdba[tdt];
+ td->addr[0] = PCIWADDR(bp->rp);
+ td->control = Ide|Rs|Ifcs|Teop|BLEN(bp);
+ ctlr->tb[tdt] = bp;
+ tdt = Next(tdt, m);
+ }
+ if(ctlr->tdt != tdt){
+ ctlr->tdt = tdt;
+ csr32w(ctlr, Tdt, tdt);
+ }
+ qunlock(&ctlr->tlock);
+}
+
+static void
+i82563replenish(Ctlr* ctlr)
+{
+ Rd *rd;
+ int rdt, m;
+ Block *bp;
+
+ rdt = ctlr->rdt;
+ m = ctlr->nrd-1;
+ while(Next(rdt, m) != ctlr->rdh){
+ rd = &ctlr->rdba[rdt];
+ if(ctlr->rb[rdt] != nil){
+ iprint("82563: tx overrun\n");
+ break;
+ }
+ bp = i82563rballoc();
+ if(bp == nil){
+ vlong now;
+ static vlong lasttime;
+
+ /* don't flood the console */
+ now = tk2ms(MACHP(0)->ticks);
+ if (now - lasttime > 2000)
+ iprint("#l%d: 82563: all %d rx buffers in use\n",
+ ctlr->edev->ctlrno, ctlr->nrb);
+ lasttime = now;
+ break;
+ }
+ ctlr->rb[rdt] = bp;
+ rd->addr[0] = PCIWADDR(bp->rp);
+// rd->addr[1] = 0;
+ rd->status = 0;
+ ctlr->rdfree++;
+ rdt = Next(rdt, m);
+ }
+ ctlr->rdt = rdt;
+ csr32w(ctlr, Rdt, rdt);
+}
+
+static void
+i82563rxinit(Ctlr* ctlr)
+{
+ Block *bp;
+ int i, r, rctl;
+
+ if(ctlr->rbsz <= 2048)
+ rctl = Dpf|Bsize2048|Bam|RdtmsHALF;
+ else if(ctlr->rbsz <= 8192)
+ rctl = Lpe|Dpf|Bsize8192|Bsex|Bam|RdtmsHALF|Secrc;
+ else if(ctlr->rbsz <= 12*1024){
+ i = ctlr->rbsz / 1024;
+ if(ctlr->rbsz % 1024)
+ i++;
+ rctl = Lpe|Dpf|BsizeFlex*i|Bam|RdtmsHALF|Secrc;
+ }
+ else
+ rctl = Lpe|Dpf|Bsize16384|Bsex|Bam|RdtmsHALF|Secrc;
+
+ if(ctlr->type == i82575 || ctlr->type == i82576){
+ /*
+ * Setting Qenable in Rxdctl does not
+ * appear to stick unless Ren is on.
+ */
+ csr32w(ctlr, Rctl, Ren|rctl);
+ r = csr32r(ctlr, Rxdctl);
+ r |= Qenable;
+ csr32w(ctlr, Rxdctl, r);
+ }
+ csr32w(ctlr, Rctl, rctl);
+
+ if(ctlr->type == i82573)
+ csr32w(ctlr, Ert, 1024/8);
+
+ if(ctlr->type == i82566 || ctlr->type == i82567)
+ csr32w(ctlr, Pbs, 16);
+
+ csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
+ csr32w(ctlr, Rdbah, 0);
+ csr32w(ctlr, Rdlen, ctlr->nrd * sizeof(Rd));
+ ctlr->rdh = 0;
+ csr32w(ctlr, Rdh, 0);
+ ctlr->rdt = 0;
+ csr32w(ctlr, Rdt, 0);
+ /* to hell with interrupt moderation, we've got fast cpus */
+// ctlr->rdtr = 25; /* µs units? */
+// ctlr->radv = 500; /* µs units? */
+ ctlr->radv = ctlr->rdtr = 0;
+ csr32w(ctlr, Rdtr, ctlr->rdtr);
+ csr32w(ctlr, Radv, ctlr->radv);
+
+ for(i = 0; i < ctlr->nrd; i++){
+ if((bp = ctlr->rb[i]) != nil){
+ ctlr->rb[i] = nil;
+ freeb(bp);
+ }
+ }
+ i82563replenish(ctlr);
+
+ if(ctlr->type != i82575 || ctlr->type == i82576){
+ /*
+ * See comment above for Qenable.
+ * Could shuffle the code?
+ */
+ r = csr32r(ctlr, Rxdctl);
+ r &= ~(WthreshMASK|PthreshMASK);
+ r |= (2<<WthreshSHIFT)|(2<<PthreshSHIFT);
+ csr32w(ctlr, Rxdctl, r);
+ }
+
+ /*
+ * Don't enable checksum offload. In practice, it interferes with
+ * tftp booting on at least the 82575.
+ */
+// csr32w(ctlr, Rxcsum, Tuofl | Ipofl | ETHERHDRSIZE<<PcssSHIFT);
+ csr32w(ctlr, Rxcsum, 0);
+}
+
+static int
+i82563rim(void* ctlr)
+{
+ return ((Ctlr*)ctlr)->rim != 0;
+}
+
+static void
+i82563rproc(void* arg)
+{
+ Rd *rd;
+ Block *bp;
+ Ctlr *ctlr;
+ int r, m, rdh, rim;
+ Ether *edev;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ i82563rxinit(ctlr);
+ r = csr32r(ctlr, Rctl);
+ r |= Ren;
+ csr32w(ctlr, Rctl, r);
+ m = ctlr->nrd-1;
+
+ for(;;){
+ i82563im(ctlr, Rxt0|Rxo|Rxdmt0|Rxseq|Ack);
+ ctlr->rsleep++;
+// coherence();
+ sleep(&ctlr->rrendez, i82563rim, ctlr);
+
+ rdh = ctlr->rdh;
+ for(;;){
+ rd = &ctlr->rdba[rdh];
+ rim = ctlr->rim;
+ ctlr->rim = 0;
+ if(!(rd->status & Rdd))
+ break;
+
+ /*
+ * Accept eop packets with no errors.
+ * With no errors and the Ixsm bit set,
+ * the descriptor status Tpcs and Ipcs bits give
+ * an indication of whether the checksums were
+ * calculated and valid.
+ */
+ bp = ctlr->rb[rdh];
+ if((rd->status & Reop) && rd->errors == 0){
+ bp->wp += rd->length;
+ bp->lim = bp->wp; /* lie like a dog. */
+ if(!(rd->status & Ixsm)){
+ ctlr->ixsm++;
+ if(rd->status & Ipcs){
+ /*
+ * IP checksum calculated
+ * (and valid as errors == 0).
+ */
+ ctlr->ipcs++;
+ bp->flag |= Bipck;
+ }
+ if(rd->status & Tcpcs){
+ /*
+ * TCP/UDP checksum calculated
+ * (and valid as errors == 0).
+ */
+ ctlr->tcpcs++;
+ bp->flag |= Btcpck|Budpck;
+ }
+ bp->checksum = rd->checksum;
+ bp->flag |= Bpktck;
+ }
+ etheriq(edev, bp, 1);
+ } else if (rd->status & Reop && rd->errors)
+ print("%s: input packet error %#ux\n",
+ tname[ctlr->type], rd->errors);
+ else
+ freeb(bp);
+ ctlr->rb[rdh] = nil;
+
+ rd->status = 0;
+ ctlr->rdfree--;
+ ctlr->rdh = rdh = Next(rdh, m);
+ if(ctlr->nrd-ctlr->rdfree >= 32 || (rim & Rxdmt0))
+ i82563replenish(ctlr);
+ }
+ }
+}
+
+static int
+i82563lim(void* c)
+{
+ return ((Ctlr*)c)->lim != 0;
+}
+
+static int speedtab[] = {
+ 10, 100, 1000, 0
+};
+
+static uint
+phyread(Ctlr *c, int reg)
+{
+ uint phy, i;
+
+ csr32w(c, Mdic, MDIrop | 1<<MDIpSHIFT | reg<<MDIrSHIFT);
+ phy = 0;
+ for(i = 0; i < 64; i++){
+ phy = csr32r(c, Mdic);
+ if(phy & (MDIe|MDIready))
+ break;
+ microdelay(1);
+ }
+ if((phy & (MDIe|MDIready)) != MDIready)
+ return ~0;
+ return phy & 0xffff;
+}
+
+static uint
+phywrite(Ctlr *c, int reg, ushort val)
+{
+ uint phy, i;
+
+ csr32w(c, Mdic, MDIwop | 1<<MDIpSHIFT | reg<<MDIrSHIFT | val);
+ phy = 0;
+ for(i = 0; i < 64; i++){
+ phy = csr32r(c, Mdic);
+ if(phy & (MDIe|MDIready))
+ break;
+ microdelay(1);
+ }
+ if((phy & (MDIe|MDIready)) != MDIready)
+ return ~0;
+ return 0;
+}
+
+/*
+ * watch for changes of link state
+ */
+static void
+i82563lproc(void *v)
+{
+ uint phy, i, a;
+ Ctlr *c;
+ Ether *e;
+
+ e = v;
+ c = e->ctlr;
+
+ if(c->type == i82573 && (phy = phyread(c, Phyier)) != ~0)
+ phywrite(c, Phyier, phy | Lscie | Ancie | Spdie | Panie);
+ for(;;){
+ phy = phyread(c, Physsr);
+ if(phy == ~0)
+ goto next;
+ i = (phy>>14) & 3;
+
+ switch(c->type){
+ case i82563:
+ a = phyread(c, Phyisr) & Ane;
+ break;
+ case i82571:
+ case i82572:
+ a = phyread(c, Phylhr) & Anf;
+ i = (i-1) & 3;
+ break;
+ default:
+ a = 0;
+ break;
+ }
+ if(a)
+ phywrite(c, Phyctl, phyread(c, Phyctl) | Ran | Ean);
+ e->link = (phy & Rtlink) != 0;
+ if(e->link){
+ c->speeds[i]++;
+ if (speedtab[i])
+ e->mbps = speedtab[i];
+ }
+next:
+ c->lim = 0;
+ i82563im(c, Lsc);
+ c->lsleep++;
+ sleep(&c->lrendez, i82563lim, c);
+ }
+}
+
+static void
+i82563tproc(void *v)
+{
+ Ether *e;
+ Ctlr *c;
+
+ e = v;
+ c = e->ctlr;
+ for(;;){
+ sleep(&c->trendez, return0, 0);
+ i82563transmit(e);
+ }
+}
+
+static void
+i82563attach(Ether* edev)
+{
+ Block *bp;
+ Ctlr *ctlr;
+ char name[KNAMELEN];
+
+ ctlr = edev->ctlr;
+ ctlr->edev = edev; /* point back to Ether* */
+ qlock(&ctlr->alock);
+ if(ctlr->attached){
+ qunlock(&ctlr->alock);
+ return;
+ }
+
+ ctlr->nrd = Nrd;
+ ctlr->ntd = Ntd;
+
+ if(waserror()){
+ while(ctlr->nrb > 0){
+ bp = i82563rballoc();
+ bp->free = nil;
+ freeb(bp);
+ ctlr->nrb--;
+ }
+ free(ctlr->tb);
+ ctlr->tb = nil;
+ free(ctlr->rb);
+ ctlr->rb = nil;
+ free(ctlr->tdba);
+ ctlr->tdba = nil;
+ free(ctlr->rdba);
+ ctlr->rdba = nil;
+ qunlock(&ctlr->alock);
+ nexterror();
+ }
+
+ if((ctlr->rdba = mallocalign(ctlr->nrd*sizeof(Rd), 128, 0, 0)) == nil ||
+ (ctlr->tdba = mallocalign(ctlr->ntd*sizeof(Td), 128, 0, 0)) == nil ||
+ (ctlr->rb = malloc(ctlr->nrd*sizeof(Block*))) == nil ||
+ (ctlr->tb = malloc(ctlr->ntd*sizeof(Block*))) == nil)
+ error(Enomem);
+
+ for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){
+ if((bp = allocb(ctlr->rbsz + BY2PG)) == nil)
+ break;
+ bp->free = i82563rbfree;
+ freeb(bp);
+ }
+
+ ctlr->attached = 1;
+
+ snprint(name, sizeof name, "#l%dl", edev->ctlrno);
+ kproc(name, i82563lproc, edev);
+
+ snprint(name, sizeof name, "#l%dr", edev->ctlrno);
+ kproc(name, i82563rproc, edev);
+
+ snprint(name, sizeof name, "#l%dt", edev->ctlrno);
+ kproc(name, i82563tproc, edev);
+
+ i82563txinit(ctlr);
+
+ qunlock(&ctlr->alock);
+ poperror();
+}
+
+static void
+i82563interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Ether *edev;
+ int icr, im;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->imlock);
+ csr32w(ctlr, Imc, ~0);
+ im = ctlr->im;
+
+ for(icr = csr32r(ctlr, Icr); icr & ctlr->im; icr = csr32r(ctlr, Icr)){
+ if(icr & Lsc){
+ im &= ~Lsc;
+ ctlr->lim = icr & Lsc;
+ wakeup(&ctlr->lrendez);
+ ctlr->lintr++;
+ }
+ if(icr & (Rxt0|Rxo|Rxdmt0|Rxseq|Ack)){
+ ctlr->rim = icr & (Rxt0|Rxo|Rxdmt0|Rxseq|Ack);
+ im &= ~(Rxt0|Rxo|Rxdmt0|Rxseq|Ack);
+ wakeup(&ctlr->rrendez);
+ ctlr->rintr++;
+ }
+ if(icr & Txdw){
+ im &= ~Txdw;
+ ctlr->tintr++;
+ wakeup(&ctlr->trendez);
+ }
+ }
+
+ ctlr->im = im;
+ csr32w(ctlr, Ims, im);
+ iunlock(&ctlr->imlock);
+}
+
+/* assume misrouted interrupts and check all controllers */
+static void
+i82575interrupt(Ureg*, void *)
+{
+ Ctlr *ctlr;
+
+ for (ctlr = i82563ctlrhead; ctlr != nil; ctlr = ctlr->next)
+ i82563interrupt(nil, ctlr->edev);
+}
+
+static int
+i82563detach(Ctlr* ctlr)
+{
+ int r, timeo;
+
+ /*
+ * Perform a device reset to get the chip back to the
+ * power-on state, followed by an EEPROM reset to read
+ * the defaults for some internal registers.
+ */
+ csr32w(ctlr, Imc, ~0);
+ csr32w(ctlr, Rctl, 0);
+ csr32w(ctlr, Tctl, 0);
+
+ delay(10);
+
+ r = csr32r(ctlr, Ctrl);
+ if(ctlr->type == i82566 || ctlr->type == i82567)
+ r |= Phyrst;
+ csr32w(ctlr, Ctrl, Devrst | r);
+ delay(1);
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!(csr32r(ctlr, Ctrl) & Devrst))
+ break;
+ delay(1);
+ }
+ if(csr32r(ctlr, Ctrl) & Devrst)
+ return -1;
+
+ r = csr32r(ctlr, Ctrlext);
+ csr32w(ctlr, Ctrlext, r|Eerst);
+ delay(1);
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!(csr32r(ctlr, Ctrlext) & Eerst))
+ break;
+ delay(1);
+ }
+ if(csr32r(ctlr, Ctrlext) & Eerst)
+ return -1;
+
+ csr32w(ctlr, Imc, ~0);
+ delay(1);
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!csr32r(ctlr, Icr))
+ break;
+ delay(1);
+ }
+ if(csr32r(ctlr, Icr))
+ return -1;
+
+ /*
+ * Balance Rx/Tx packet buffer.
+ * No need to set PBA register unless using jumbo, defaults to 32KB
+ * for receive. If it is changed, then have to do a MAC reset,
+ * and need to do that at the the right time as it will wipe stuff.
+ */
+ if(ctlr->rbsz > 8192 && (ctlr->type == i82563 || ctlr->type == i82571 ||
+ ctlr->type == i82572)){
+ ctlr->pba = csr32r(ctlr, Pba);
+ r = ctlr->pba >> 16;
+ r += ctlr->pba & 0xffff;
+ r >>= 1;
+ csr32w(ctlr, Pba, r);
+ } else if(ctlr->type == i82573 && ctlr->rbsz > 1514)
+ csr32w(ctlr, Pba, 14);
+ ctlr->pba = csr32r(ctlr, Pba);
+
+ r = csr32r(ctlr, Ctrl);
+ csr32w(ctlr, Ctrl, Slu|r);
+
+ return 0;
+}
+
+static void
+i82563shutdown(Ether* ether)
+{
+ i82563detach(ether->ctlr);
+}
+
+static ushort
+eeread(Ctlr *ctlr, int adr)
+{
+ csr32w(ctlr, Eerd, EEstart | adr << 2);
+ while ((csr32r(ctlr, Eerd) & EEdone) == 0)
+ ;
+ return csr32r(ctlr, Eerd) >> 16;
+}
+
+static int
+eeload(Ctlr *ctlr)
+{
+ ushort sum;
+ int data, adr;
+
+ sum = 0;
+ for (adr = 0; adr < 0x40; adr++) {
+ data = eeread(ctlr, adr);
+ ctlr->eeprom[adr] = data;
+ sum += data;
+ }
+ return sum;
+}
+
+static int
+fcycle(Ctlr *, Flash *f)
+{
+ ushort s, i;
+
+ s = f->reg[Fsts];
+ if((s&Fvalid) == 0)
+ return -1;
+ f->reg[Fsts] |= Fcerr | Ael;
+ for(i = 0; i < 10; i++){
+ if((s&Scip) == 0)
+ return 0;
+ delay(1);
+ s = f->reg[Fsts];
+ }
+ return -1;
+}
+
+static int
+fread(Ctlr *c, Flash *f, int ladr)
+{
+ ushort s;
+
+ delay(1);
+ if(fcycle(c, f) == -1)
+ return -1;
+ f->reg[Fsts] |= Fdone;
+ f->reg32[Faddr] = ladr;
+
+ /* setup flash control register */
+ s = f->reg[Fctl];
+ s &= ~(0x1f << 8);
+ s |= (2-1) << 8; /* 2 bytes */
+ s &= ~(2*Flcycle); /* read */
+ f->reg[Fctl] = s | Fgo;
+
+ while((f->reg[Fsts] & Fdone) == 0)
+ ;
+ if(f->reg[Fsts] & (Fcerr|Ael))
+ return -1;
+ return f->reg32[Fdata] & 0xffff;
+}
+
+static int
+fload(Ctlr *c)
+{
+ ulong data, io, r, adr;
+ ushort sum;
+ Flash f;
+
+ io = c->pcidev->mem[1].bar & ~0x0f;
+ f.reg = vmap(io, c->pcidev->mem[1].size);
+ if(f.reg == nil)
+ return -1;
+ f.reg32 = (void*)f.reg;
+ f.sz = f.reg32[Bfpr];
+ r = f.sz & 0x1fff;
+ if(csr32r(c, Eec) & (1<<22))
+ ++r;
+ r <<= 12;
+
+ sum = 0;
+ for (adr = 0; adr < 0x40; adr++) {
+ data = fread(c, &f, r + adr*2);
+ if(data == -1)
+ break;
+ c->eeprom[adr] = data;
+ sum += data;
+ }
+ vunmap(f.reg, c->pcidev->mem[1].size);
+ return sum;
+}
+
+static int
+i82563reset(Ctlr *ctlr)
+{
+ int i, r;
+
+ if(i82563detach(ctlr))
+ return -1;
+ if(ctlr->type == i82566 || ctlr->type == i82567)
+ r = fload(ctlr);
+ else
+ r = eeload(ctlr);
+ if (r != 0 && r != 0xBABA){
+ print("%s: bad EEPROM checksum - %#.4ux\n",
+ tname[ctlr->type], r);
+ return -1;
+ }
+
+ for(i = 0; i < Eaddrlen/2; i++){
+ ctlr->ra[2*i] = ctlr->eeprom[Ea+i];
+ ctlr->ra[2*i+1] = ctlr->eeprom[Ea+i] >> 8;
+ }
+ r = (csr32r(ctlr, Status) & Lanid) >> 2;
+ ctlr->ra[5] += r; /* ea ctlr[1] = ea ctlr[0]+1 */
+
+ r = ctlr->ra[3]<<24 | ctlr->ra[2]<<16 | ctlr->ra[1]<<8 | ctlr->ra[0];
+ csr32w(ctlr, Ral, r);
+ r = 0x80000000 | ctlr->ra[5]<<8 | ctlr->ra[4];
+ csr32w(ctlr, Rah, r);
+ for(i = 1; i < 16; i++){
+ csr32w(ctlr, Ral+i*8, 0);
+ csr32w(ctlr, Rah+i*8, 0);
+ }
+ memset(ctlr->mta, 0, sizeof(ctlr->mta));
+ for(i = 0; i < 128; i++)
+ csr32w(ctlr, Mta + i*4, 0);
+
+ /*
+ * Does autonegotiation affect this manual setting?
+ * The correct values here should depend on the PBA value
+ * and maximum frame length, no?
+ * ctlr->fcrt[lh] are never set, so default to 0.
+ */
+ csr32w(ctlr, Fcal, 0x00C28001);
+ csr32w(ctlr, Fcah, 0x0100);
+ csr32w(ctlr, Fct, 0x8808);
+ csr32w(ctlr, Fcttv, 0x0100);
+
+ ctlr->fcrtl = ctlr->fcrth = 0;
+ // ctlr->fcrtl = 0x00002000;
+ // ctlr->fcrth = 0x00004000;
+ csr32w(ctlr, Fcrtl, ctlr->fcrtl);
+ csr32w(ctlr, Fcrth, ctlr->fcrth);
+
+ return 0;
+}
+
+static void
+i82563pci(void)
+{
+ int type;
+ ulong io;
+ void *mem;
+ Pcidev *p;
+ Ctlr *ctlr;
+
+ p = nil;
+ while(p = pcimatch(p, 0x8086, 0)){
+ switch(p->did){
+ default:
+ continue;
+ case 0x1096:
+ case 0x10ba:
+ type = i82563;
+ break;
+ case 0x1049: /* mm */
+ case 0x104a: /* dm */
+ case 0x104b: /* dc */
+ case 0x104d: /* mc */
+ case 0x10bd: /* dm */
+ case 0x294c: /* dc-2 */
+ type = i82566;
+ break;
+ case 0x10cd: /* lf */
+ case 0x10ce: /* v-2 */
+ case 0x10de: /* lm-3 */
+ case 0x10f5: /* lm-2 */
+ type = i82567;
+ break;
+ case 0x10a4:
+ case 0x105e:
+ type = i82571;
+ break;
+ case 0x10b9: /* sic, 82572gi */
+ type = i82572;
+ break;
+ case 0x108b: /* v */
+ case 0x108c: /* e (iamt) */
+ case 0x109a: /* l */
+ type = i82573;
+ break;
+// case 0x10d3: /* l */
+// type = i82574; /* never heard of it */
+// break;
+ case 0x10a7: /* 82575eb: one of a pair of controllers */
+ type = i82575;
+ break;
+ case 0x10c9: /* 82576 copper */
+ case 0x10e6: /* 82576 fiber */
+ case 0x10e7: /* 82576 serdes */
+ type = i82576;
+ break;
+ }
+
+ io = p->mem[0].bar & ~0x0F;
+ mem = vmap(io, p->mem[0].size);
+ if(mem == nil){
+ print("%s: can't map %.8lux\n", tname[type], io);
+ continue;
+ }
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = io;
+ ctlr->pcidev = p;
+ ctlr->type = type;
+ ctlr->rbsz = rbtab[type];
+ ctlr->nic = mem;
+
+ if(i82563reset(ctlr)){
+ vunmap(mem, p->mem[0].size);
+ free(ctlr);
+ continue;
+ }
+ pcisetbme(p);
+
+ if(i82563ctlrhead != nil)
+ i82563ctlrtail->next = ctlr;
+ else
+ i82563ctlrhead = ctlr;
+ i82563ctlrtail = ctlr;
+ }
+}
+
+static int
+pnp(Ether* edev, int type)
+{
+ Ctlr *ctlr;
+ static int done;
+
+ if(!done) {
+ i82563pci();
+ done = 1;
+ }
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = i82563ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(type != Iany && ctlr->type != type)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ ctlr->edev = edev; /* point back to Ether* */
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+ edev->mbps = 1000;
+ edev->maxmtu = ctlr->rbsz;
+ memmove(edev->ea, ctlr->ra, Eaddrlen);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ edev->attach = i82563attach;
+ edev->transmit = i82563transmit;
+ edev->interrupt = (ctlr->type == i82575?
+ i82575interrupt: i82563interrupt);
+ edev->ifstat = i82563ifstat;
+ edev->ctl = i82563ctl;
+
+ edev->arg = edev;
+ edev->promiscuous = i82563promiscuous;
+ edev->shutdown = i82563shutdown;
+ edev->multicast = i82563multicast;
+
+ return 0;
+}
+
+static int
+anypnp(Ether *e)
+{
+ return pnp(e, Iany);
+}
+
+static int
+i82563pnp(Ether *e)
+{
+ return pnp(e, i82563);
+}
+
+static int
+i82566pnp(Ether *e)
+{
+ return pnp(e, i82566);
+}
+
+static int
+i82571pnp(Ether *e)
+{
+ return pnp(e, i82571);
+}
+
+static int
+i82572pnp(Ether *e)
+{
+ return pnp(e, i82572);
+}
+
+static int
+i82573pnp(Ether *e)
+{
+ return pnp(e, i82573);
+}
+
+static int
+i82575pnp(Ether *e)
+{
+ return pnp(e, i82575);
+}
+
+void
+ether82563link(void)
+{
+ /* recognise lots of model numbers for debugging assistance */
+ addethercard("i82563", i82563pnp);
+ addethercard("i82566", i82566pnp);
+ addethercard("i82571", i82571pnp);
+ addethercard("i82572", i82572pnp);
+ addethercard("i82573", i82573pnp);
+ addethercard("i82575", i82575pnp);
+ addethercard("igbepcie", anypnp);
+}
diff --git a/sys/src/9/pc/ether82598.c b/sys/src/9/pc/ether82598.c
new file mode 100755
index 000000000..459b1fb0f
--- /dev/null
+++ b/sys/src/9/pc/ether82598.c
@@ -0,0 +1,984 @@
+/*
+ * intel 10GB ethernet pci-express driver
+ * copyright © 2007, coraid, inc.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+#include "etherif.h"
+
+/*
+ * // comments note conflicts with 82563-style drivers,
+ * and the registers are all different.
+ */
+
+enum {
+ /* general */
+ Ctrl = 0x00000/4, /* Device Control */
+ Status = 0x00008/4, /* Device Status */
+ Ctrlext = 0x00018/4, /* Extended Device Control */
+ Esdp = 0x00020/4, /* extended sdp control */
+ Esodp = 0x00028/4, /* extended od sdp control */
+ Ledctl = 0x00200/4, /* led control */
+ Tcptimer = 0x0004c/4, /* tcp timer */
+ Ecc = 0x110b0/4, /* errata ecc control magic */
+
+ /* nvm */
+ Eec = 0x10010/4, /* eeprom/flash control */
+ Eerd = 0x10014/4, /* eeprom read */
+ Fla = 0x1001c/4, /* flash access */
+ Flop = 0x1013c/4, /* flash opcode */
+ Grc = 0x10200/4, /* general rx control */
+
+ /* interrupt */
+ Icr = 0x00800/4, /* interrupt cause read */
+ Ics = 0x00808/4, /* " set */
+ Ims = 0x00880/4, /* " mask read/set */
+ Imc = 0x00888/4, /* " mask clear */
+ Iac = 0x00810/4, /* " ayto clear */
+ Iam = 0x00890/4, /* " auto mask enable */
+ Itr = 0x00820/4, /* " throttling rate (0-19) */
+ Ivar = 0x00900/4, /* " vector allocation regs. */
+ /* msi interrupt */
+ Msixt = 0x0000/4, /* msix table (bar3) */
+ Msipba = 0x2000/4, /* msix pending bit array (bar3) */
+ Pbacl = 0x11068/4, /* pba clear */
+ Gpie = 0x00898/4, /* general purpose int enable */
+
+ /* flow control */
+ Pfctop = 0x03008/4, /* priority flow ctl type opcode */
+ Fcttv = 0x03200/4, /* " transmit timer value (0-3) */
+ Fcrtl = 0x03220/4, /* " rx threshold low (0-7) +8n */
+ Fcrth = 0x03260/4, /* " rx threshold high (0-7) +8n */
+ Rcrtv = 0x032a0/4, /* " refresh value threshold */
+ Tfcs = 0x0ce00/4, /* " tx status */
+
+ /* rx dma */
+ Rbal = 0x01000/4, /* rx desc base low (0-63) +0x40n */
+ Rbah = 0x01004/4, /* " high */
+ Rdlen = 0x01008/4, /* " length */
+ Rdh = 0x01010/4, /* " head */
+ Rdt = 0x01018/4, /* " tail */
+ Rxdctl = 0x01028/4, /* " control */
+
+ Srrctl = 0x02100/4, /* split and replication rx ctl. */
+ Dcarxctl = 0x02200/4, /* rx dca control */
+ Rdrxctl = 0x02f00/4, /* rx dma control */
+ Rxpbsize = 0x03c00/4, /* rx packet buffer size */
+ Rxctl = 0x03000/4, /* rx control */
+ Dropen = 0x03d04/4, /* drop enable control */
+
+ /* rx */
+ Rxcsum = 0x05000/4, /* rx checksum control */
+ Rfctl = 0x04008/4, /* rx filter control */
+ Mta = 0x05200/4, /* multicast table array (0-127) */
+ Ral = 0x05400/4, /* rx address low */
+ Rah = 0x05404/4,
+ Psrtype = 0x05480/4, /* packet split rx type. */
+ Vfta = 0x0a000/4, /* vlan filter table array. */
+ Fctrl = 0x05080/4, /* filter control */
+ Vlnctrl = 0x05088/4, /* vlan control */
+ Msctctrl = 0x05090/4, /* multicast control */
+ Mrqc = 0x05818/4, /* multiple rx queues cmd */
+ Vmdctl = 0x0581c/4, /* vmdq control */
+ Imir = 0x05a80/4, /* immediate irq rx (0-7) */
+ Imirext = 0x05aa0/4, /* immediate irq rx ext */
+ Imirvp = 0x05ac0/4, /* immediate irq vlan priority */
+ Reta = 0x05c00/4, /* redirection table */
+ Rssrk = 0x05c80/4, /* rss random key */
+
+ /* tx */
+ Tdbal = 0x06000/4, /* tx desc base low +0x40n */
+ Tdbah = 0x06004/4, /* " high */
+ Tdlen = 0x06008/4, /* " len */
+ Tdh = 0x06010/4, /* " head */
+ Tdt = 0x06018/4, /* " tail */
+ Txdctl = 0x06028/4, /* " control */
+ Tdwbal = 0x06038/4, /* " write-back address low */
+ Tdwbah = 0x0603c/4,
+
+ Dtxctl = 0x07e00/4, /* tx dma control */
+ Tdcatxctrl = 0x07200/4, /* tx dca register (0-15) */
+ Tipg = 0x0cb00/4, /* tx inter-packet gap */
+ Txpbsize = 0x0cc00/4, /* tx packet-buffer size (0-15) */
+
+ /* mac */
+ Hlreg0 = 0x04240/4, /* highlander control reg 0 */
+ Hlreg1 = 0x04244/4, /* highlander control reg 1 (ro) */
+ Msca = 0x0425c/4, /* mdi signal cmd & addr */
+ Msrwd = 0x04260/4, /* mdi single rw data */
+ Mhadd = 0x04268/4, /* mac addr high & max frame */
+ Pcss1 = 0x04288/4, /* xgxs status 1 */
+ Pcss2 = 0x0428c/4,
+ Xpcss = 0x04290/4, /* 10gb-x pcs status */
+ Serdesc = 0x04298/4, /* serdes control */
+ Macs = 0x0429c/4, /* fifo control & report */
+ Autoc = 0x042a0/4, /* autodetect control & status */
+ Links = 0x042a4/4, /* link status */
+ Autoc2 = 0x042a8/4,
+};
+
+enum {
+ /* Ctrl */
+ Rst = 1<<26, /* full nic reset */
+
+ /* Txdctl */
+ Ten = 1<<25,
+
+ /* Fctrl */
+ Bam = 1<<10, /* broadcast accept mode */
+ Upe = 1<<9, /* unicast promiscuous */
+ Mpe = 1<<8, /* multicast promiscuous */
+
+ /* Rxdctl */
+ Pthresh = 0, /* prefresh threshold shift in bits */
+ Hthresh = 8, /* host buffer minimum threshold " */
+ Wthresh = 16, /* writeback threshold */
+ Renable = 1<<25,
+
+ /* Rxctl */
+ Rxen = 1<<0,
+ Dmbyps = 1<<1,
+
+ /* Rdrxctl */
+ Rdmt½ = 0,
+ Rdmt¼ = 1,
+ Rdmt⅛ = 2,
+
+ /* Rxcsum */
+ Ippcse = 1<<12, /* ip payload checksum enable */
+
+ /* Eerd */
+ EEstart = 1<<0, /* Start Read */
+ EEdone = 1<<1, /* Read done */
+
+ /* interrupts */
+ Irx0 = 1<<0, /* driver defined */
+ Itx0 = 1<<1, /* driver defined */
+ Lsc = 1<<20, /* link status change */
+
+ /* Links */
+ Lnkup = 1<<30,
+ Lnkspd = 1<<29,
+
+ /* Hlreg0 */
+ Jumboen = 1<<2,
+};
+
+typedef struct {
+ uint reg;
+ char *name;
+} Stat;
+
+Stat stattab[] = {
+ 0x4000, "crc error",
+ 0x4004, "illegal byte",
+ 0x4008, "short packet",
+ 0x3fa0, "missed pkt0",
+ 0x4034, "mac local flt",
+ 0x4038, "mac rmt flt",
+ 0x4040, "rx length err",
+ 0x3f60, "xon tx",
+ 0xcf60, "xon rx",
+ 0x3f68, "xoff tx",
+ 0xcf68, "xoff rx",
+ 0x405c, "rx 040",
+ 0x4060, "rx 07f",
+ 0x4064, "rx 100",
+ 0x4068, "rx 200",
+ 0x406c, "rx 3ff",
+ 0x4070, "rx big",
+ 0x4074, "rx ok",
+ 0x4078, "rx bcast",
+ 0x3fc0, "rx no buf0",
+ 0x40a4, "rx runt",
+ 0x40a8, "rx frag",
+ 0x40ac, "rx ovrsz",
+ 0x40b0, "rx jab",
+ 0x40d0, "rx pkt",
+
+ 0x40d4, "tx pkt",
+ 0x40d8, "tx 040",
+ 0x40dc, "tx 07f",
+ 0x40e0, "tx 100",
+ 0x40e4, "tx 200",
+ 0x40e8, "tx 3ff",
+ 0x40ec, "tx big",
+ 0x40f4, "tx bcast",
+ 0x4120, "xsum err",
+};
+
+/* status */
+enum {
+ Pif = 1<<7, /* past exact filter (sic) */
+ Ipcs = 1<<6, /* ip checksum calcuated */
+ L4cs = 1<<5, /* layer 2 */
+ Tcpcs = 1<<4, /* tcp checksum calcuated */
+ Vp = 1<<3, /* 802.1q packet matched vet */
+ Ixsm = 1<<2, /* ignore checksum */
+ Reop = 1<<1, /* end of packet */
+ Rdd = 1<<0, /* descriptor done */
+};
+
+typedef struct {
+ u32int addr[2];
+ ushort length;
+ ushort cksum;
+ uchar status;
+ uchar errors;
+ ushort vlan;
+} Rd;
+
+enum {
+ /* Td cmd */
+ Rs = 1<<3,
+ Ic = 1<<2,
+ Ifcs = 1<<1,
+ Teop = 1<<0,
+
+ /* Td status */
+ Tdd = 1<<0,
+};
+
+typedef struct {
+ u32int addr[2];
+ ushort length;
+ uchar cso;
+ uchar cmd;
+ uchar status;
+ uchar css;
+ ushort vlan;
+} Td;
+
+enum {
+ Factive = 1<<0,
+ Fstarted = 1<<1,
+};
+
+typedef struct {
+ Pcidev *p;
+ Ether *edev;
+ u32int *reg;
+ u32int *reg3;
+ uchar flag;
+ int nrd;
+ int ntd;
+ int nrb;
+ int rbsz;
+ Lock slock;
+ Lock alock;
+ QLock tlock;
+ Rendez lrendez;
+ Rendez trendez;
+ Rendez rrendez;
+ uint im;
+ uint lim;
+ uint rim;
+ uint tim;
+ Lock imlock;
+ char *alloc;
+
+ Rd *rdba;
+ Block **rb;
+ uint rdt;
+ uint rdfree;
+
+ Td *tdba;
+ uint tdh;
+ uint tdt;
+ Block **tb;
+
+ uchar ra[Eaddrlen];
+ uchar mta[128];
+ ulong stats[nelem(stattab)];
+ uint speeds[3];
+} Ctlr;
+
+/* tweakable paramaters */
+enum {
+ Rbsz = 12*1024,
+ Nrd = 256,
+ Ntd = 256,
+ Nrb = 256,
+};
+
+static Ctlr *ctlrtab[4];
+static int nctlr;
+static Lock rblock;
+static Block *rbpool;
+
+static void
+readstats(Ctlr *c)
+{
+ int i;
+
+ lock(&c->slock);
+ for(i = 0; i < nelem(c->stats); i++)
+ c->stats[i] += c->reg[stattab[i].reg >> 2];
+ unlock(&c->slock);
+}
+
+static int speedtab[] = {
+ 0,
+ 1000,
+ 10000,
+};
+
+static long
+ifstat(Ether *e, void *a, long n, ulong offset)
+{
+ uint i, *t;
+ char *s, *p, *q;
+ Ctlr *c;
+
+ c = e->ctlr;
+ p = s = malloc(READSTR);
+ q = p + READSTR;
+
+ readstats(c);
+ for(i = 0; i < nelem(stattab); i++)
+ if(c->stats[i] > 0)
+ p = seprint(p, q, "%.10s %uld\n", stattab[i].name, c->stats[i]);
+ t = c->speeds;
+ p = seprint(p, q, "speeds: 0:%d 1000:%d 10000:%d\n", t[0], t[1], t[2]);
+ seprint(p, q, "rdfree %d rdh %d rdt %d\n", c->rdfree, c->reg[Rdt],
+ c->reg[Rdh]);
+ n = readstr(offset, a, n, s);
+ free(s);
+
+ return n;
+}
+
+static void
+im(Ctlr *c, int i)
+{
+ ilock(&c->imlock);
+ c->im |= i;
+ c->reg[Ims] = c->im;
+ iunlock(&c->imlock);
+}
+
+static int
+lim(void *v)
+{
+ return ((Ctlr*)v)->lim != 0;
+}
+
+static void
+lproc(void *v)
+{
+ int r, i;
+ Ctlr *c;
+ Ether *e;
+
+ e = v;
+ c = e->ctlr;
+ for (;;) {
+ r = c->reg[Links];
+ e->link = (r & Lnkup) != 0;
+ i = 0;
+ if(e->link)
+ i = 1 + ((r & Lnkspd) != 0);
+ c->speeds[i]++;
+ e->mbps = speedtab[i];
+ c->lim = 0;
+ im(c, Lsc);
+ sleep(&c->lrendez, lim, c);
+ c->lim = 0;
+ }
+}
+
+static long
+ctl(Ether *, void *, long)
+{
+ error(Ebadarg);
+ return -1;
+}
+
+static Block*
+rballoc(void)
+{
+ Block *bp;
+
+ ilock(&rblock);
+ if((bp = rbpool) != nil){
+ rbpool = bp->next;
+ bp->next = 0;
+ _xinc(&bp->ref); /* prevent bp from being freed */
+ }
+ iunlock(&rblock);
+ return bp;
+}
+
+void
+rbfree(Block *b)
+{
+ b->rp = b->wp = (uchar*)PGROUND((uintptr)b->base);
+ b->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
+ ilock(&rblock);
+ b->next = rbpool;
+ rbpool = b;
+ iunlock(&rblock);
+}
+
+#define Next(x, m) (((x)+1) & (m))
+
+static int
+cleanup(Ctlr *c, int tdh)
+{
+ Block *b;
+ uint m, n;
+
+ m = c->ntd - 1;
+ while(c->tdba[n = Next(tdh, m)].status & Tdd){
+ tdh = n;
+ b = c->tb[tdh];
+ c->tb[tdh] = 0;
+ freeb(b);
+ c->tdba[tdh].status = 0;
+ }
+ return tdh;
+}
+
+void
+transmit(Ether *e)
+{
+ uint i, m, tdt, tdh;
+ Ctlr *c;
+ Block *b;
+ Td *t;
+
+ c = e->ctlr;
+ if(!canqlock(&c->tlock)){
+ im(c, Itx0);
+ return;
+ }
+ tdh = c->tdh = cleanup(c, c->tdh);
+ tdt = c->tdt;
+ m = c->ntd - 1;
+ for(i = 0; i < 8; i++){
+ if(Next(tdt, m) == tdh){
+ im(c, Itx0);
+ break;
+ }
+ if(!(b = qget(e->oq)))
+ break;
+ t = c->tdba + tdt;
+ t->addr[0] = PCIWADDR(b->rp);
+ t->length = BLEN(b);
+ t->cmd = Rs | Ifcs | Teop;
+ c->tb[tdt] = b;
+ tdt = Next(tdt, m);
+ }
+ if(i){
+ c->tdt = tdt;
+ c->reg[Tdt] = tdt;
+ }
+ qunlock(&c->tlock);
+}
+
+static int
+tim(void *c)
+{
+ return ((Ctlr*)c)->tim != 0;
+}
+
+static void
+tproc(void *v)
+{
+ Ctlr *c;
+ Ether *e;
+
+ e = v;
+ c = e->ctlr;
+ for (;;) {
+ sleep(&c->trendez, tim, c); /* transmit kicks us */
+ c->tim = 0;
+ transmit(e);
+ }
+}
+
+static void
+rxinit(Ctlr *c)
+{
+ int i;
+ Block *b;
+
+ c->reg[Rxctl] &= ~Rxen;
+ for(i = 0; i < c->nrd; i++){
+ b = c->rb[i];
+ c->rb[i] = 0;
+ if(b)
+ freeb(b);
+ }
+ c->rdfree = 0;
+
+ c->reg[Fctrl] |= Bam;
+ c->reg[Rxcsum] |= Ipcs;
+ c->reg[Srrctl] = (c->rbsz + 1023)/1024;
+ c->reg[Mhadd] = c->rbsz << 16;
+ c->reg[Hlreg0] |= Jumboen;
+
+ c->reg[Rbal] = PCIWADDR(c->rdba);
+ c->reg[Rbah] = 0;
+ c->reg[Rdlen] = c->nrd*sizeof(Rd);
+ c->reg[Rdh] = 0;
+ c->reg[Rdt] = c->rdt = 0;
+
+ c->reg[Rdrxctl] = Rdmt¼;
+ c->reg[Rxdctl] = 8<<Wthresh | 8<<Pthresh | 4<<Hthresh | Renable;
+ c->reg[Rxctl] |= Rxen | Dmbyps;
+}
+
+static void
+replenish(Ctlr *c, uint rdh)
+{
+ int rdt, m, i;
+ Block *b;
+ Rd *r;
+
+ m = c->nrd - 1;
+ i = 0;
+ for(rdt = c->rdt; Next(rdt, m) != rdh; rdt = Next(rdt, m)){
+ r = c->rdba + rdt;
+ if(!(b = rballoc())){
+ print("82598: no buffers\n");
+ break;
+ }
+ c->rb[rdt] = b;
+ r->addr[0] = PCIWADDR(b->rp);
+ r->status = 0;
+ c->rdfree++;
+ i++;
+ }
+ if(i)
+ c->reg[Rdt] = c->rdt = rdt;
+}
+
+static int
+rim(void *v)
+{
+ return ((Ctlr*)v)->rim != 0;
+}
+
+static uchar zeroea[Eaddrlen];
+
+void
+rproc(void *v)
+{
+ uint m, rdh;
+ Block *b;
+ Ctlr *c;
+ Ether *e;
+ Rd *r;
+
+ e = v;
+ c = e->ctlr;
+ m = c->nrd - 1;
+ rdh = 0;
+loop:
+ replenish(c, rdh);
+ im(c, Irx0);
+ sleep(&c->rrendez, rim, c);
+loop1:
+ c->rim = 0;
+ if(c->nrd - c->rdfree >= 16)
+ replenish(c, rdh);
+ r = c->rdba + rdh;
+ if(!(r->status & Rdd))
+ goto loop; /* UGH */
+ b = c->rb[rdh];
+ c->rb[rdh] = 0;
+ b->wp += r->length;
+ b->lim = b->wp; /* lie like a dog */
+ if(!(r->status & Ixsm)){
+ if(r->status & Ipcs)
+ b->flag |= Bipck;
+ if(r->status & Tcpcs)
+ b->flag |= Btcpck | Budpck;
+ b->checksum = r->cksum;
+ }
+// r->status = 0;
+ etheriq(e, b, 1);
+ c->rdfree--;
+ rdh = Next(rdh, m);
+ goto loop1; /* UGH */
+}
+
+static void
+promiscuous(void *a, int on)
+{
+ Ctlr *c;
+ Ether *e;
+
+ e = a;
+ c = e->ctlr;
+ if(on)
+ c->reg[Fctrl] |= Upe | Mpe;
+ else
+ c->reg[Fctrl] &= ~(Upe | Mpe);
+}
+
+static void
+multicast(void *a, uchar *ea, int on)
+{
+ int b, i;
+ Ctlr *c;
+ Ether *e;
+
+ e = a;
+ c = e->ctlr;
+
+ /*
+ * multiple ether addresses can hash to the same filter bit,
+ * so it's never safe to clear a filter bit.
+ * if we want to clear filter bits, we need to keep track of
+ * all the multicast addresses in use, clear all the filter bits,
+ * then set the ones corresponding to in-use addresses.
+ */
+ i = ea[5] >> 1;
+ b = (ea[5]&1)<<4 | ea[4]>>4;
+ b = 1 << b;
+ if(on)
+ c->mta[i] |= b;
+// else
+// c->mta[i] &= ~b;
+ c->reg[Mta+i] = c->mta[i];
+}
+
+static int
+detach(Ctlr *c)
+{
+ int i;
+
+ c->reg[Imc] = ~0;
+ c->reg[Ctrl] |= Rst;
+ for(i = 0; i < 100; i++){
+ delay(1);
+ if((c->reg[Ctrl] & Rst) == 0)
+ break;
+ }
+ if (i >= 100)
+ return -1;
+ /* errata */
+ delay(50);
+ c->reg[Ecc] &= ~(1<<21 | 1<<18 | 1<<9 | 1<<6);
+
+ /* not cleared by reset; kill it manually. */
+ for(i = 1; i < 16; i++)
+ c->reg[Rah] &= ~(1 << 31);
+ for(i = 0; i < 128; i++)
+ c->reg[Mta + i] = 0;
+ for(i = 1; i < 640; i++)
+ c->reg[Vfta + i] = 0;
+ return 0;
+}
+
+static void
+shutdown(Ether *e)
+{
+ detach(e->ctlr);
+}
+
+/* ≤ 20ms */
+static ushort
+eeread(Ctlr *c, int i)
+{
+ c->reg[Eerd] = EEstart | i<<2;
+ while((c->reg[Eerd] & EEdone) == 0)
+ ;
+ return c->reg[Eerd] >> 16;
+}
+
+static int
+eeload(Ctlr *c)
+{
+ ushort u, v, p, l, i, j;
+
+ if((eeread(c, 0) & 0xc0) != 0x40)
+ return -1;
+ u = 0;
+ for(i = 0; i < 0x40; i++)
+ u += eeread(c, i);
+ for(i = 3; i < 0xf; i++){
+ p = eeread(c, i);
+ l = eeread(c, p++);
+ if((int)p + l + 1 > 0xffff)
+ continue;
+ for(j = p; j < p + l; j++)
+ u += eeread(c, j);
+ }
+ if(u != 0xbaba)
+ return -1;
+ if(c->reg[Status] & (1<<3))
+ u = eeread(c, 10);
+ else
+ u = eeread(c, 9);
+ u++;
+ for(i = 0; i < Eaddrlen;){
+ v = eeread(c, u + i/2);
+ c->ra[i++] = v;
+ c->ra[i++] = v>>8;
+ }
+ c->ra[5] += (c->reg[Status] & 0xc) >> 2;
+ return 0;
+}
+
+static int
+reset(Ctlr *c)
+{
+ int i;
+ uchar *p;
+
+ if(detach(c)){
+ print("82598: reset timeout\n");
+ return -1;
+ }
+ if(eeload(c)){
+ print("82598: eeprom failure\n");
+ return -1;
+ }
+ p = c->ra;
+ c->reg[Ral] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
+ c->reg[Rah] = p[5]<<8 | p[4] | 1<<31;
+
+ readstats(c);
+ for(i = 0; i<nelem(c->stats); i++)
+ c->stats[i] = 0;
+
+ c->reg[Ctrlext] |= 1 << 16;
+ /* make some guesses for flow control */
+ c->reg[Fcrtl] = 0x10000 | 1<<31;
+ c->reg[Fcrth] = 0x40000 | 1<<31;
+ c->reg[Rcrtv] = 0x6000;
+
+ /* configure interrupt mapping (don't ask) */
+ c->reg[Ivar+0] = 0 | 1<<7;
+ c->reg[Ivar+64/4] = 1 | 1<<7;
+// c->reg[Ivar+97/4] = (2 | 1<<7) << (8*(97%4));
+
+ /* interrupt throttling goes here. */
+ for(i = Itr; i < Itr + 20; i++)
+ c->reg[i] = 128; /* ¼µs intervals */
+ c->reg[Itr + Itx0] = 256;
+ return 0;
+}
+
+static void
+txinit(Ctlr *c)
+{
+ Block *b;
+ int i;
+
+ c->reg[Txdctl] = 16<<Wthresh | 16<<Pthresh;
+ for(i = 0; i < c->ntd; i++){
+ b = c->tb[i];
+ c->tb[i] = 0;
+ if(b)
+ freeb(b);
+ }
+ memset(c->tdba, 0, c->ntd * sizeof(Td));
+ c->reg[Tdbal] = PCIWADDR(c->tdba);
+ c->reg[Tdbah] = 0;
+ c->reg[Tdlen] = c->ntd*sizeof(Td);
+ c->reg[Tdh] = 0;
+ c->reg[Tdt] = 0;
+ c->tdh = c->ntd - 1;
+ c->tdt = 0;
+ c->reg[Txdctl] |= Ten;
+}
+
+static void
+attach(Ether *e)
+{
+ Block *b;
+ Ctlr *c;
+ int t;
+ char buf[KNAMELEN];
+
+ c = e->ctlr;
+ c->edev = e; /* point back to Ether* */
+ lock(&c->alock);
+ if(c->alloc){
+ unlock(&c->alock);
+ return;
+ }
+
+ c->nrd = Nrd;
+ c->ntd = Ntd;
+ t = c->nrd * sizeof *c->rdba + 255;
+ t += c->ntd * sizeof *c->tdba + 255;
+ t += (c->ntd + c->nrd) * sizeof(Block*);
+ c->alloc = malloc(t);
+ unlock(&c->alock);
+ if(c->alloc == nil)
+ error(Enomem);
+
+ c->rdba = (Rd*)ROUNDUP((uintptr)c->alloc, 256);
+ c->tdba = (Td*)ROUNDUP((uintptr)(c->rdba + c->nrd), 256);
+ c->rb = (Block**)(c->tdba + c->ntd);
+ c->tb = (Block**)(c->rb + c->nrd);
+
+ if(waserror()){
+ while(b = rballoc()){
+ b->free = 0;
+ freeb(b);
+ }
+ free(c->alloc);
+ c->alloc = nil;
+ nexterror();
+ }
+ for(c->nrb = 0; c->nrb < 2*Nrb; c->nrb++){
+ if(!(b = allocb(c->rbsz+BY2PG)))
+ error(Enomem);
+ b->free = rbfree;
+ freeb(b);
+ }
+ poperror();
+
+ rxinit(c);
+ txinit(c);
+
+ snprint(buf, sizeof buf, "#l%dl", e->ctlrno);
+ kproc(buf, lproc, e);
+ snprint(buf, sizeof buf, "#l%dr", e->ctlrno);
+ kproc(buf, rproc, e);
+ snprint(buf, sizeof buf, "#l%dt", e->ctlrno);
+ kproc(buf, tproc, e);
+}
+
+static void
+interrupt(Ureg*, void *v)
+{
+ int icr, im;
+ Ctlr *c;
+ Ether *e;
+
+ e = v;
+ c = e->ctlr;
+ ilock(&c->imlock);
+ c->reg[Imc] = ~0;
+ im = c->im;
+ while((icr = c->reg[Icr] & c->im) != 0){
+ if(icr & Lsc){
+ im &= ~Lsc;
+ c->lim = icr & Lsc;
+ wakeup(&c->lrendez);
+ }
+ if(icr & Irx0){
+ im &= ~Irx0;
+ c->rim = icr & Irx0;
+ wakeup(&c->rrendez);
+ }
+ if(icr & Itx0){
+ im &= ~Itx0;
+ c->tim = icr & Itx0;
+ wakeup(&c->trendez);
+ }
+ }
+ c->reg[Ims] = c->im = im;
+ iunlock(&c->imlock);
+}
+
+static void
+scan(void)
+{
+ ulong io, io3;
+ void *mem, *mem3;
+ Ctlr *c;
+ Pcidev *p;
+
+ p = 0;
+ while(p = pcimatch(p, 0x8086, 0)){
+ switch(p->did){
+ case 0x10c6: /* 82598 af dual port */
+ case 0x10c7: /* 82598 af single port */
+ case 0x10b6: /* 82598 backplane */
+ case 0x10dd: /* 82598 at cx4 */
+ case 0x10ec: /* 82598 at cx4 dual port */
+ break;
+ default:
+ continue;
+ }
+ if(nctlr == nelem(ctlrtab)){
+ print("i82598: too many controllers\n");
+ return;
+ }
+ io = p->mem[0].bar & ~0xf;
+ mem = vmap(io, p->mem[0].size);
+ if(mem == nil){
+ print("i82598: can't map %#p\n", p->mem[0].bar);
+ continue;
+ }
+ io3 = p->mem[3].bar & ~0xf;
+ mem3 = vmap(io3, p->mem[3].size);
+ if(mem3 == nil){
+ print("i82598: can't map %#p\n", p->mem[3].bar);
+ vunmap(mem, p->mem[0].size);
+ continue;
+ }
+ c = malloc(sizeof *c);
+ c->p = p;
+ c->reg = (u32int*)mem;
+ c->reg3 = (u32int*)mem3;
+ c->rbsz = Rbsz;
+ if(reset(c)){
+ print("i82598: can't reset\n");
+ free(c);
+ vunmap(mem, p->mem[0].size);
+ vunmap(mem3, p->mem[3].size);
+ continue;
+ }
+ pcisetbme(p);
+ ctlrtab[nctlr++] = c;
+ }
+}
+
+static int
+pnp(Ether *e)
+{
+ int i;
+ Ctlr *c = nil;
+
+ if(nctlr == 0)
+ scan();
+ for(i = 0; i < nctlr; i++){
+ c = ctlrtab[i];
+ if(c == nil || c->flag & Factive)
+ continue;
+ if(e->port == 0 || e->port == (ulong)c->reg)
+ break;
+ }
+ if (i >= nctlr)
+ return -1;
+ c->flag |= Factive;
+ e->ctlr = c;
+ e->port = (uintptr)c->reg;
+ e->irq = c->p->intl;
+ e->tbdf = c->p->tbdf;
+ e->mbps = 10000;
+ e->maxmtu = c->rbsz;
+ memmove(e->ea, c->ra, Eaddrlen);
+ e->arg = e;
+ e->attach = attach;
+ e->ctl = ctl;
+ e->ifstat = ifstat;
+ e->interrupt = interrupt;
+ e->multicast = multicast;
+ e->promiscuous = promiscuous;
+ e->shutdown = shutdown;
+ e->transmit = transmit;
+
+ return 0;
+}
+
+void
+ether82598link(void)
+{
+ addethercard("i82598", pnp);
+}
diff --git a/sys/src/9/pc/ether83815.c b/sys/src/9/pc/ether83815.c
new file mode 100755
index 000000000..6b7bd19c8
--- /dev/null
+++ b/sys/src/9/pc/ether83815.c
@@ -0,0 +1,1214 @@
+/*
+ * National Semiconductor DP83815
+ *
+ * Supports only internal PHY and has been tested on:
+ * Netgear FA311TX (using Netgear DS108 10/100 hub)
+ * SiS 900 within SiS 630
+ * To do:
+ * check Ethernet address;
+ * test autonegotiation on 10 Mbit, and 100 Mbit full duplex;
+ * external PHY via MII (should be common code for MII);
+ * thresholds;
+ * ring sizing;
+ * physical link changes/disconnect;
+ * push initialisation back to attach.
+ *
+ * C H Forsyth, forsyth@vitanuova.com, 18th June 2001.
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+#define DEBUG 0
+#define debug if(DEBUG)print
+
+enum {
+ Nrde = 64,
+ Ntde = 64,
+};
+
+#define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4)
+
+typedef struct Des {
+ ulong next;
+ int cmdsts;
+ ulong addr;
+ Block* bp;
+} Des;
+
+enum { /* cmdsts */
+ Own = 1<<31, /* set by data producer to hand to consumer */
+ More = 1<<30, /* more of packet in next descriptor */
+ Intr = 1<<29, /* interrupt when device is done with it */
+ Supcrc = 1<<28, /* suppress crc on transmit */
+ Inccrc = 1<<28, /* crc included on receive (always) */
+ Ok = 1<<27, /* packet ok */
+ Size = 0xFFF, /* packet size in bytes */
+
+ /* transmit */
+ Txa = 1<<26, /* transmission aborted */
+ Tfu = 1<<25, /* transmit fifo underrun */
+ Crs = 1<<24, /* carrier sense lost */
+ Td = 1<<23, /* transmission deferred */
+ Ed = 1<<22, /* excessive deferral */
+ Owc = 1<<21, /* out of window collision */
+ Ec = 1<<20, /* excessive collisions */
+ /* 19-16 collision count */
+
+ /* receive */
+ Rxa = 1<<26, /* receive aborted (same as Rxo) */
+ Rxo = 1<<25, /* receive overrun */
+ Dest = 3<<23, /* destination class */
+ Drej= 0<<23, /* packet was rejected */
+ Duni= 1<<23, /* unicast */
+ Dmulti= 2<<23, /* multicast */
+ Dbroad= 3<<23, /* broadcast */
+ Long = 1<<22, /* too long packet received */
+ Runt = 1<<21, /* packet less than 64 bytes */
+ Ise = 1<<20, /* invalid symbol */
+ Crce = 1<<19, /* invalid crc */
+ Fae = 1<<18, /* frame alignment error */
+ Lbp = 1<<17, /* loopback packet */
+ Col = 1<<16, /* collision during receive */
+};
+
+enum { /* PCI vendor & device IDs */
+ Nat83815 = (0x0020<<16)|0x100B,
+ SiS = 0x1039,
+ SiS900 = (0x0900<<16)|SiS,
+ SiS7016 = (0x7016<<16)|SiS,
+
+ SiS630bridge = 0x0008,
+
+ /* SiS 900 PCI revision codes */
+ SiSrev630s = 0x81,
+ SiSrev630e = 0x82,
+ SiSrev630ea1 = 0x83,
+
+ SiSeenodeaddr = 8, /* short addr of SiS eeprom mac addr */
+ SiS630eenodeaddr = 9, /* likewise for the 630 */
+ Nseenodeaddr = 6, /* " for NS eeprom */
+ Nat83815avng = 0x403,
+ Nat83816avng = 0x505, /* 83816 acts like submodel of 83815 */
+ /* using reg. 0x58 to disambiguate. */
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id; /* (pcidev->did<<16)|pcidev->vid */
+
+ ushort srom[0xB+1];
+ uchar sromea[Eaddrlen]; /* MAC address */
+
+ uchar fd; /* option or auto negotiation */
+
+ int mbps;
+
+ Lock lock;
+
+ Des* rdr; /* receive descriptor ring */
+ int nrdr; /* size of rdr */
+ int rdrx; /* index into rdr */
+
+ Lock tlock;
+ Des* tdr; /* transmit descriptor ring */
+ int ntdr; /* size of tdr */
+ int tdrh; /* host index into tdr */
+ int tdri; /* interface index into tdr */
+ int ntq; /* descriptors active */
+ int ntqmax;
+
+ ulong rxa; /* receive statistics */
+ ulong rxo;
+ ulong rlong;
+ ulong runt;
+ ulong ise;
+ ulong crce;
+ ulong fae;
+ ulong lbp;
+ ulong col;
+ ulong rxsovr;
+ ulong rxorn;
+
+ ulong txa; /* transmit statistics */
+ ulong tfu;
+ ulong crs;
+ ulong td;
+ ulong ed;
+ ulong owc;
+ ulong ec;
+ ulong txurn;
+
+ ulong dperr; /* system errors */
+ ulong rmabt;
+ ulong rtabt;
+ ulong sserr;
+ ulong rxsover;
+
+ ulong version; /* silicon version; register 0x58h */
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+enum {
+ /* registers (could memory map) */
+ Rcr= 0x00, /* command register */
+ Rst= 1<<8,
+ Rxr= 1<<5, /* receiver reset */
+ Txr= 1<<4, /* transmitter reset */
+ Rxd= 1<<3, /* receiver disable */
+ Rxe= 1<<2, /* receiver enable */
+ Txd= 1<<1, /* transmitter disable */
+ Txe= 1<<0, /* transmitter enable */
+ Rcfg= 0x04, /* configuration */
+ Lnksts= 1<<31, /* link good */
+ Speed100= 1<<30, /* 100 Mb/s link */
+ Fdup= 1<<29, /* full duplex */
+ Pol= 1<<28, /* polarity reversal (10baseT) */
+ Aneg_dn= 1<<27, /* autonegotiation done */
+ Pint_acen= 1<<17, /* PHY interrupt auto clear enable */
+ Pause_adv= 1<<16, /* advertise pause during auto neg */
+ Paneg_ena= 1<<13, /* auto negotiation enable */
+ Paneg_all= 7<<13, /* auto negotiation enable 10/100 half & full */
+ Ext_phy= 1<<12, /* enable MII for external PHY */
+ Phy_rst= 1<<10, /* reset internal PHY */
+ Phy_dis= 1<<9, /* disable internal PHY (eg, low power) */
+ Req_alg= 1<<7, /* PCI bus request: set means less aggressive */
+ Sb= 1<<6, /* single slot back-off not random */
+ Pow= 1<<5, /* out of window timer selection */
+ Exd= 1<<4, /* disable excessive deferral timer */
+ Pesel= 1<<3, /* parity error algorithm selection */
+ Brom_dis= 1<<2, /* disable boot rom interface */
+ Bem= 1<<0, /* big-endian mode */
+ Rmear= 0x08, /* eeprom access */
+ Mdc= 1<<6, /* MII mangement check */
+ Mddir= 1<<5, /* MII management direction */
+ Mdio= 1<<4, /* MII mangement data */
+ Eesel= 1<<3, /* EEPROM chip select */
+ Eeclk= 1<<2, /* EEPROM clock */
+ Eedo= 1<<1, /* EEPROM data out (from chip) */
+ Eedi= 1<<0, /* EEPROM data in (to chip) */
+ Rptscr= 0x0C, /* pci test control */
+ Risr= 0x10, /* interrupt status */
+ Txrcmp= 1<<25, /* transmit reset complete */
+ Rxrcmp= 1<<24, /* receiver reset complete */
+ Dperr= 1<<23, /* detected parity error */
+ Sserr= 1<<22, /* signalled system error */
+ Rmabt= 1<<21, /* received master abort */
+ Rtabt= 1<<20, /* received target abort */
+ Rxsovr= 1<<16, /* RX status FIFO overrun */
+ Hiberr= 1<<15, /* high bits error set (OR of 25-16) */
+ Phy= 1<<14, /* PHY interrupt */
+ Pme= 1<<13, /* power management event (wake online) */
+ Swi= 1<<12, /* software interrupt */
+ Mib= 1<<11, /* MIB service */
+ Txurn= 1<<10, /* TX underrun */
+ Txidle= 1<<9, /* TX idle */
+ Txerr= 1<<8, /* TX packet error */
+ Txdesc= 1<<7, /* TX descriptor (with Intr bit done) */
+ Txok= 1<<6, /* TX ok */
+ Rxorn= 1<<5, /* RX overrun */
+ Rxidle= 1<<4, /* RX idle */
+ Rxearly= 1<<3, /* RX early threshold */
+ Rxerr= 1<<2, /* RX packet error */
+ Rxdesc= 1<<1, /* RX descriptor (with Intr bit done) */
+ Rxok= 1<<0, /* RX ok */
+ Rimr= 0x14, /* interrupt mask */
+ Rier= 0x18, /* interrupt enable */
+ Ie= 1<<0, /* interrupt enable */
+ Rtxdp= 0x20, /* transmit descriptor pointer */
+ Rtxcfg= 0x24, /* transmit configuration */
+ Csi= 1<<31, /* carrier sense ignore (needed for full duplex) */
+ Hbi= 1<<30, /* heartbeat ignore (needed for full duplex) */
+ Atp= 1<<28, /* automatic padding of runt packets */
+ Mxdma= 7<<20, /* maximum dma transfer field */
+ Mxdma32= 4<<20, /* 4x32-bit words (32 bytes) */
+ Mxdma64= 5<<20, /* 8x32-bit words (64 bytes) */
+ Flth= 0x3F<<8,/* Tx fill threshold, units of 32 bytes (must be > Mxdma) */
+ Drth= 0x3F<<0,/* Tx drain threshold (units of 32 bytes) */
+ Flth128= 4<<8, /* fill at 128 bytes */
+ Drth512= 16<<0, /* drain at 512 bytes */
+ Rrxdp= 0x30, /* receive descriptor pointer */
+ Rrxcfg= 0x34, /* receive configuration */
+ Atx= 1<<28, /* accept transmit packets (needed for full duplex) */
+ Rdrth= 0x1F<<1,/* Rx drain threshold (units of 32 bytes) */
+ Rdrth64= 2<<1, /* drain at 64 bytes */
+ Rccsr= 0x3C, /* CLKRUN control/status */
+ Pmests= 1<<15, /* PME status */
+ Rwcsr= 0x40, /* wake on lan control/status */
+ Rpcr= 0x44, /* pause control/status */
+ Rrfcr= 0x48, /* receive filter/match control */
+ Rfen= 1<<31, /* receive filter enable */
+ Aab= 1<<30, /* accept all broadcast */
+ Aam= 1<<29, /* accept all multicast */
+ Aau= 1<<28, /* accept all unicast */
+ Apm= 1<<27, /* accept on perfect match */
+ Apat= 0xF<<23,/* accept on pattern match */
+ Aarp= 1<<22, /* accept ARP */
+ Mhen= 1<<21, /* multicast hash enable */
+ Uhen= 1<<20, /* unicast hash enable */
+ Ulm= 1<<19, /* U/L bit mask */
+ /* bits 0-9 are rfaddr */
+ Rrfdr= 0x4C, /* receive filter/match data */
+ Rbrar= 0x50, /* boot rom address */
+ Rbrdr= 0x54, /* boot rom data */
+ Rsrr= 0x58, /* silicon revision */
+ Rmibc= 0x5C, /* MIB control */
+ /* 60-78 MIB data */
+
+ /* PHY registers */
+ Rbmcr= 0x80, /* basic mode configuration */
+ Reset= 1<<15,
+ Sel100= 1<<13, /* select 100Mb/sec if no auto neg */
+ Anena= 1<<12, /* auto negotiation enable */
+ Anrestart= 1<<9, /* restart auto negotiation */
+ Selfdx= 1<<8, /* select full duplex if no auto neg */
+ Rbmsr= 0x84, /* basic mode status */
+ Ancomp= 1<<5, /* autonegotiation complete */
+ Rphyidr1= 0x88,
+ Rphyidr2= 0x8C,
+ Ranar= 0x90, /* autonegotiation advertisement */
+ Ranlpar= 0x94, /* autonegotiation link partner ability */
+ Raner= 0x98, /* autonegotiation expansion */
+ Rannptr= 0x9C, /* autonegotiation next page TX */
+ Rphysts= 0xC0, /* PHY status */
+ Rmicr= 0xC4, /* MII control */
+ Inten= 1<<1, /* PHY interrupt enable */
+ Rmisr= 0xC8, /* MII status */
+ Rfcscr= 0xD0, /* false carrier sense counter */
+ Rrecr= 0xD4, /* receive error counter */
+ Rpcsr= 0xD8, /* 100Mb config/status */
+ Rphycr= 0xE4, /* PHY control */
+ Rtbscr= 0xE8, /* 10BaseT status/control */
+};
+
+/*
+ * eeprom addresses
+ * 7 to 9 (16 bit words): mac address, shifted and reversed
+ */
+
+#define csr32r(c, r) (inl((c)->port+(r)))
+#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
+#define csr16r(c, r) (ins((c)->port+(r)))
+#define csr16w(c, r, l) (outs((c)->port+(r), (ulong)(l)))
+
+static void
+dumpcregs(Ctlr *ctlr)
+{
+ int i;
+
+ for(i=0; i<=0x5C; i+=4)
+ print("%2.2ux %8.8lux\n", i, csr32r(ctlr, i));
+}
+
+static void
+promiscuous(void* arg, int on)
+{
+ Ctlr *ctlr;
+ ulong w;
+
+ ctlr = ((Ether*)arg)->ctlr;
+ ilock(&ctlr->lock);
+ w = csr32r(ctlr, Rrfcr);
+ if(on != ((w&Aau)!=0)){
+ csr32w(ctlr, Rrfcr, w & ~Rfen);
+ csr32w(ctlr, Rrfcr, Rfen | (w ^ Aau));
+ }
+ iunlock(&ctlr->lock);
+}
+
+static void
+attach(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(&ctlr->lock);
+ if(0)
+ dumpcregs(ctlr);
+ csr32w(ctlr, Rcr, Rxe);
+ iunlock(&ctlr->lock);
+}
+
+static long
+ifstat(Ether* ether, void* a, long n, ulong offset)
+{
+ Ctlr *ctlr;
+ char *buf, *p;
+ int i, l, len;
+
+ ctlr = ether->ctlr;
+
+ ether->crcs = ctlr->crce;
+ ether->frames = ctlr->runt+ctlr->ise+ctlr->rlong+ctlr->fae;
+ ether->buffs = ctlr->rxorn+ctlr->tfu;
+ ether->overflows = ctlr->rxsovr;
+
+ if(n == 0)
+ return 0;
+
+ p = malloc(READSTR);
+ l = snprint(p, READSTR, "Rxa: %lud\n", ctlr->rxa);
+ l += snprint(p+l, READSTR-l, "Rxo: %lud\n", ctlr->rxo);
+ l += snprint(p+l, READSTR-l, "Rlong: %lud\n", ctlr->rlong);
+ l += snprint(p+l, READSTR-l, "Runt: %lud\n", ctlr->runt);
+ l += snprint(p+l, READSTR-l, "Ise: %lud\n", ctlr->ise);
+ l += snprint(p+l, READSTR-l, "Fae: %lud\n", ctlr->fae);
+ l += snprint(p+l, READSTR-l, "Lbp: %lud\n", ctlr->lbp);
+ l += snprint(p+l, READSTR-l, "Tfu: %lud\n", ctlr->tfu);
+ l += snprint(p+l, READSTR-l, "Txa: %lud\n", ctlr->txa);
+ l += snprint(p+l, READSTR-l, "CRC Error: %lud\n", ctlr->crce);
+ l += snprint(p+l, READSTR-l, "Collision Seen: %lud\n", ctlr->col);
+ l += snprint(p+l, READSTR-l, "Frame Too Long: %lud\n", ctlr->rlong);
+ l += snprint(p+l, READSTR-l, "Runt Frame: %lud\n", ctlr->runt);
+ l += snprint(p+l, READSTR-l, "Rx Underflow Error: %lud\n", ctlr->rxorn);
+ l += snprint(p+l, READSTR-l, "Tx Underrun: %lud\n", ctlr->txurn);
+ l += snprint(p+l, READSTR-l, "Excessive Collisions: %lud\n", ctlr->ec);
+ l += snprint(p+l, READSTR-l, "Late Collision: %lud\n", ctlr->owc);
+ l += snprint(p+l, READSTR-l, "Loss of Carrier: %lud\n", ctlr->crs);
+ l += snprint(p+l, READSTR-l, "Parity: %lud\n", ctlr->dperr);
+ l += snprint(p+l, READSTR-l, "Aborts: %lud\n", ctlr->rmabt+ctlr->rtabt);
+ l += snprint(p+l, READSTR-l, "RX Status overrun: %lud\n", ctlr->rxsover);
+ snprint(p+l, READSTR-l, "ntqmax: %d\n", ctlr->ntqmax);
+ ctlr->ntqmax = 0;
+ buf = a;
+ len = readstr(offset, buf, n, p);
+ if(offset > l)
+ offset -= l;
+ else
+ offset = 0;
+ buf += len;
+ n -= len;
+
+ l = snprint(p, READSTR, "srom:");
+ for(i = 0; i < nelem(ctlr->srom); i++){
+ if(i && ((i & 0x0F) == 0))
+ l += snprint(p+l, READSTR-l, "\n ");
+ l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->srom[i]);
+ }
+
+ snprint(p+l, READSTR-l, "\n");
+ len += readstr(offset, buf, n, p);
+ free(p);
+
+ return len;
+}
+
+static void
+txstart(Ether* ether)
+{
+ Ctlr *ctlr;
+ Block *bp;
+ Des *des;
+ int started;
+
+ ctlr = ether->ctlr;
+ started = 0;
+ while(ctlr->ntq < ctlr->ntdr-1){
+ bp = qget(ether->oq);
+ if(bp == nil)
+ break;
+ des = &ctlr->tdr[ctlr->tdrh];
+ des->bp = bp;
+ des->addr = PADDR(bp->rp);
+ ctlr->ntq++;
+ coherence();
+ des->cmdsts = Own | BLEN(bp);
+ ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
+ started = 1;
+ }
+ if(started){
+ coherence();
+ csr32w(ctlr, Rcr, Txe); /* prompt */
+ }
+
+ if(ctlr->ntq > ctlr->ntqmax)
+ ctlr->ntqmax = ctlr->ntq;
+}
+
+static void
+transmit(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(&ctlr->tlock);
+ txstart(ether);
+ iunlock(&ctlr->tlock);
+}
+
+static void
+txrxcfg(Ctlr *ctlr, int txdrth)
+{
+ ulong rx, tx;
+
+ rx = csr32r(ctlr, Rrxcfg);
+ tx = csr32r(ctlr, Rtxcfg);
+ if(ctlr->fd){
+ rx |= Atx;
+ tx |= Csi | Hbi;
+ }else{
+ rx &= ~Atx;
+ tx &= ~(Csi | Hbi);
+ }
+ tx &= ~(Mxdma|Drth|Flth);
+ tx |= Mxdma64 | Flth128 | txdrth;
+ csr32w(ctlr, Rtxcfg, tx);
+ rx &= ~(Mxdma|Rdrth);
+ rx |= Mxdma64 | Rdrth64;
+ csr32w(ctlr, Rrxcfg, rx);
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ int len, status, cmdsts, n;
+ Ctlr *ctlr;
+ Ether *ether;
+ Des *des;
+ Block *bp;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+
+ while((status = csr32r(ctlr, Risr)) != 0){
+
+ status &= ~(Pme|Mib);
+
+ if(status & Hiberr){
+ if(status & Rxsovr)
+ ctlr->rxsover++;
+ if(status & Sserr)
+ ctlr->sserr++;
+ if(status & Dperr)
+ ctlr->dperr++;
+ if(status & Rmabt)
+ ctlr->rmabt++;
+ if(status & Rtabt)
+ ctlr->rtabt++;
+ status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt);
+ }
+
+ /* update link state */
+ if(status&Phy){
+ status &= ~Phy;
+ csr32r(ctlr, Rcfg);
+ n = csr32r(ctlr, Rcfg);
+// iprint("83815 phy %x %x\n", n, n&Lnksts);
+ ether->link = (n&Lnksts) != 0;
+ }
+
+ /*
+ * Received packets.
+ */
+ if(status & (Rxdesc|Rxok|Rxerr|Rxearly|Rxorn)){
+ des = &ctlr->rdr[ctlr->rdrx];
+ while((cmdsts = des->cmdsts) & Own){
+ if((cmdsts&Ok) == 0){
+ if(cmdsts & Rxa)
+ ctlr->rxa++;
+ if(cmdsts & Rxo)
+ ctlr->rxo++;
+ if(cmdsts & Long)
+ ctlr->rlong++;
+ if(cmdsts & Runt)
+ ctlr->runt++;
+ if(cmdsts & Ise)
+ ctlr->ise++;
+ if(cmdsts & Crce)
+ ctlr->crce++;
+ if(cmdsts & Fae)
+ ctlr->fae++;
+ if(cmdsts & Lbp)
+ ctlr->lbp++;
+ if(cmdsts & Col)
+ ctlr->col++;
+ }
+ else if(bp = iallocb(Rbsz)){
+ len = (cmdsts&Size)-4;
+ if(len <= 0){
+ debug("ns83815: packet len %d <=0\n", len);
+ freeb(des->bp);
+ }else{
+ des->bp->wp = des->bp->rp+len;
+ etheriq(ether, des->bp, 1);
+ }
+ des->bp = bp;
+ des->addr = PADDR(bp->rp);
+ coherence();
+ }else{
+ debug("ns83815: interrupt: iallocb for input buffer failed\n");
+ des->bp->next = 0;
+ }
+
+ des->cmdsts = Rbsz;
+ coherence();
+
+ ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
+ des = &ctlr->rdr[ctlr->rdrx];
+ }
+ status &= ~(Rxdesc|Rxok|Rxerr|Rxearly|Rxorn);
+ }
+
+ /*
+ * Check the transmit side:
+ * check for Transmit Underflow and Adjust
+ * the threshold upwards;
+ * free any transmitted buffers and try to
+ * top-up the ring.
+ */
+ if(status & Txurn){
+ ctlr->txurn++;
+ ilock(&ctlr->lock);
+ /* change threshold */
+ iunlock(&ctlr->lock);
+ status &= ~(Txurn);
+ }
+
+ ilock(&ctlr->tlock);
+ while(ctlr->ntq){
+ des = &ctlr->tdr[ctlr->tdri];
+ cmdsts = des->cmdsts;
+ if(cmdsts & Own)
+ break;
+
+ if((cmdsts & Ok) == 0){
+ if(cmdsts & Txa)
+ ctlr->txa++;
+ if(cmdsts & Tfu)
+ ctlr->tfu++;
+ if(cmdsts & Td)
+ ctlr->td++;
+ if(cmdsts & Ed)
+ ctlr->ed++;
+ if(cmdsts & Owc)
+ ctlr->owc++;
+ if(cmdsts & Ec)
+ ctlr->ec++;
+ ether->oerrs++;
+ }
+
+ freeb(des->bp);
+ des->bp = nil;
+ des->cmdsts = 0;
+
+ ctlr->ntq--;
+ ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
+ }
+ txstart(ether);
+ iunlock(&ctlr->tlock);
+
+ status &= ~(Txurn|Txidle|Txerr|Txdesc|Txok);
+
+ /*
+ * Anything left not catered for?
+ */
+ if(status)
+ print("#l%d: status %8.8uX\n", ether->ctlrno, status);
+ }
+}
+
+static void
+ctlrinit(Ether* ether)
+{
+ Ctlr *ctlr;
+ Des *des, *last;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * Allocate suitable aligned descriptors
+ * for the transmit and receive rings;
+ * initialise the receive ring;
+ * initialise the transmit ring;
+ * unmask interrupts and start the transmit side.
+ */
+ des = xspanalloc((ctlr->nrdr+ctlr->ntdr)*sizeof(Des), 32, 0);
+ ctlr->tdr = des;
+ ctlr->rdr = des+ctlr->ntdr;
+
+ last = nil;
+ for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
+ des->bp = iallocb(Rbsz);
+ if(des->bp == nil)
+ error(Enomem);
+ des->cmdsts = Rbsz;
+ des->addr = PADDR(des->bp->rp);
+ if(last != nil)
+ last->next = PADDR(des);
+ last = des;
+ }
+ ctlr->rdr[ctlr->nrdr-1].next = PADDR(ctlr->rdr);
+ ctlr->rdrx = 0;
+ csr32w(ctlr, Rrxdp, PADDR(ctlr->rdr));
+
+ last = nil;
+ for(des = ctlr->tdr; des < &ctlr->tdr[ctlr->ntdr]; des++){
+ des->cmdsts = 0;
+ des->bp = nil;
+ des->addr = ~0;
+ if(last != nil)
+ last->next = PADDR(des);
+ last = des;
+ }
+ ctlr->tdr[ctlr->ntdr-1].next = PADDR(ctlr->tdr);
+ ctlr->tdrh = 0;
+ ctlr->tdri = 0;
+ csr32w(ctlr, Rtxdp, PADDR(ctlr->tdr));
+
+ txrxcfg(ctlr, Drth512);
+
+ csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr|
+ Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok); /* Phy|Pme|Mib */
+ csr32w(ctlr, Rmicr, Inten); /* enable phy interrupts */
+ csr32r(ctlr, Risr); /* clear status */
+ csr32w(ctlr, Rier, Ie);
+}
+
+static void
+eeclk(Ctlr *ctlr, int clk)
+{
+ csr32w(ctlr, Rmear, Eesel | clk);
+ microdelay(2);
+}
+
+static void
+eeidle(Ctlr *ctlr)
+{
+ int i;
+
+ eeclk(ctlr, 0);
+ eeclk(ctlr, Eeclk);
+ for(i=0; i<25; i++){
+ eeclk(ctlr, 0);
+ eeclk(ctlr, Eeclk);
+ }
+ eeclk(ctlr, 0);
+ csr32w(ctlr, Rmear, 0);
+ microdelay(2);
+}
+
+static ushort
+eegetw(Ctlr *ctlr, int a)
+{
+ int d, i, w;
+
+ eeidle(ctlr);
+ eeclk(ctlr, 0);
+ eeclk(ctlr, Eeclk);
+ d = 0x180 | a;
+ for(i=0x400; i; i>>=1){
+ if(d & i)
+ csr32w(ctlr, Rmear, Eesel|Eedi);
+ else
+ csr32w(ctlr, Rmear, Eesel);
+ eeclk(ctlr, Eeclk);
+ eeclk(ctlr, 0);
+ microdelay(2);
+ }
+ w = 0;
+ for(i=0x8000; i; i >>= 1){
+ eeclk(ctlr, Eeclk);
+ if(csr32r(ctlr, Rmear) & Eedo)
+ w |= i;
+ microdelay(2);
+ eeclk(ctlr, 0);
+ }
+ eeidle(ctlr);
+ return w;
+}
+
+static int
+resetctlr(Ctlr *ctlr)
+{
+ int i;
+
+ /*
+ * Soft-reset the controller
+ */
+ csr32w(ctlr, Rcr, Rst);
+ for(i=0;; i++){
+ if(i > 100){
+ print("ns83815: soft reset did not complete\n");
+ return -1;
+ }
+ microdelay(250);
+ if((csr32r(ctlr, Rcr) & Rst) == 0)
+ break;
+ delay(1);
+ }
+ return 0;
+}
+
+static void
+shutdown(Ether* ether)
+{
+ Ctlr *ctlr = ether->ctlr;
+
+print("ether83815 shutting down\n");
+ csr32w(ctlr, Rcr, Rxd|Txd); /* disable transceiver */
+ resetctlr(ctlr);
+}
+
+static int
+softreset(Ctlr* ctlr, int resetphys)
+{
+ int i, w;
+
+ /*
+ * Soft-reset the controller
+ */
+ resetctlr(ctlr);
+ csr32w(ctlr, Rccsr, Pmests);
+ csr32w(ctlr, Rccsr, 0);
+ csr32w(ctlr, Rcfg, csr32r(ctlr, Rcfg) | Pint_acen);
+ ctlr->version = csr32r(ctlr, Rsrr);
+ if(resetphys){
+ /*
+ * Soft-reset the PHY
+ */
+ csr32w(ctlr, Rbmcr, Reset);
+ for(i=0;; i++){
+ if(i > 100){
+ print("ns83815: PHY soft reset time out\n");
+ return -1;
+ }
+ if((csr32r(ctlr, Rbmcr) & Reset) == 0)
+ break;
+ delay(1);
+ }
+ }
+
+ /*
+ * Initialisation values, in sequence (see 4.4 Recommended Registers Configuration)
+ */
+ csr16w(ctlr, 0xCC, 0x0001); /* PGSEL */
+ csr16w(ctlr, 0xE4, 0x189C); /* PMCCSR */
+ csr16w(ctlr, 0xFC, 0x0000); /* TSTDAT */
+ csr16w(ctlr, 0xF4, 0x5040); /* DSPCFG */
+ csr16w(ctlr, 0xF8, 0x008C); /* SDCFG */
+
+ /*
+ * Auto negotiate
+ */
+ csr16r(ctlr, Rbmsr); /* clear latched bits */
+ debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
+ csr16w(ctlr, Rbmcr, Anena);
+ if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){
+ csr16w(ctlr, Rbmcr, Anena|Anrestart);
+ for(i=0;; i++){
+ if(i > 3000){
+ print("ns83815: auto neg timed out\n");
+ return -1;
+ }
+ if((w = csr16r(ctlr, Rbmsr)) & Ancomp)
+ break;
+ delay(1);
+ }
+ debug("%d ms\n", i);
+ w &= 0xFFFF;
+ debug("bmsr: %4.4ux\n", w);
+ USED(w);
+ }
+ debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
+ debug("anlpar: %4.4ux\n", csr16r(ctlr, Ranlpar));
+ debug("aner: %4.4ux\n", csr16r(ctlr, Raner));
+ debug("physts: %4.4ux\n", csr16r(ctlr, Rphysts));
+ debug("tbscr: %4.4ux\n", csr16r(ctlr, Rtbscr));
+ return 0;
+}
+
+static int
+media(Ether* ether)
+{
+ Ctlr* ctlr;
+ ulong cfg;
+
+ ctlr = ether->ctlr;
+ cfg = csr32r(ctlr, Rcfg);
+ ctlr->fd = (cfg & Fdup) != 0;
+ ether->link = (cfg&Lnksts) != 0;
+ return (cfg&(Lnksts|Speed100)) == Lnksts? 10: 100;
+}
+
+static char* mediatable[9] = {
+ "10BASE-T", /* TP */
+ "10BASE-2", /* BNC */
+ "10BASE-5", /* AUI */
+ "100BASE-TX",
+ "10BASE-TFD",
+ "100BASE-TXFD",
+ "100BASE-T4",
+ "100BASE-FX",
+ "100BASE-FXFD",
+};
+
+static int
+is630(ulong id, Pcidev *p)
+{
+ if(id == SiS900)
+ switch (p->rid) {
+ case SiSrev630s:
+ case SiSrev630e:
+ case SiSrev630ea1:
+ return 1;
+ }
+ return 0;
+}
+
+enum {
+ MagicReg = 0x48,
+ MagicRegSz = 1,
+ Magicrden = 0x40, /* read enable, apparently */
+ Paddr= 0x70, /* address port */
+ Pdata= 0x71, /* data port */
+};
+
+/* rcmos() originally from LANL's SiS 900 driver's rcmos() */
+static int
+sisrdcmos(Ctlr *ctlr)
+{
+ int i;
+ unsigned reg;
+ ulong port;
+ Pcidev *p;
+
+ debug("ns83815: SiS 630 rev. %ux reading mac address from cmos\n", ctlr->pcidev->rid);
+ p = pcimatch(nil, SiS, SiS630bridge);
+ if(p == nil) {
+ print("ns83815: no SiS 630 rev. %ux bridge for mac addr\n",
+ ctlr->pcidev->rid);
+ return 0;
+ }
+ port = p->mem[0].bar & ~0x01;
+ debug("ns83815: SiS 630 rev. %ux reading mac addr from cmos via bridge at port 0x%lux\n", ctlr->pcidev->rid, port);
+
+ reg = pcicfgr8(p, MagicReg);
+ pcicfgw8(p, MagicReg, reg|Magicrden);
+
+ for (i = 0; i < Eaddrlen; i++) {
+ outb(port+Paddr, SiS630eenodeaddr + i);
+ ctlr->sromea[i] = inb(port+Pdata);
+ }
+
+ pcicfgw8(p, MagicReg, reg & ~Magicrden);
+ return 1;
+}
+
+/*
+ * If this is a SiS 630E chipset with an embedded SiS 900 controller,
+ * we have to read the MAC address from the APC CMOS RAM. - sez freebsd.
+ * However, CMOS *is* NVRAM normally. See devrtc.c:440, memory.c:88.
+ */
+static void
+sissrom(Ctlr *ctlr)
+{
+ union {
+ uchar eaddr[Eaddrlen];
+ ushort alignment;
+ } ee;
+ int i, off = SiSeenodeaddr, cnt = sizeof ee.eaddr / sizeof(short);
+ ushort *shp = (ushort *)ee.eaddr;
+
+ if(!is630(ctlr->id, ctlr->pcidev) || !sisrdcmos(ctlr)) {
+ for (i = 0; i < cnt; i++)
+ *shp++ = eegetw(ctlr, off++);
+ memmove(ctlr->sromea, ee.eaddr, sizeof ctlr->sromea);
+ }
+}
+
+ushort
+søkrisee(Ctlr *c, int n)
+{
+ int i;
+ uint cmd;
+ ushort r;
+
+ csr32w(c, Rmear, Eesel);
+
+ cmd = 0x180|n;
+ for(i = 10; i >= 0; i--){
+ n = 1<<3;
+ if(cmd&(1<<i))
+ n |= 1;
+ csr32w(c, Rmear, n);
+ csr32r(c, Rmear);
+ csr32w(c, Rmear, n|4);
+ csr32r(c, Rmear);
+ }
+
+ csr32w(c, Rmear, 1<<3);
+ csr32r(c, Rmear);
+
+ r = 0;
+ for(i = 0; i < 16; i++){
+ csr32w(c, Rmear, 1<<3 | 1<<2);
+ csr32r(c, Rmear);
+ if(csr32r(c, Rmear) & 2)
+ r |= 1<<i;
+ csr32w(c, Rmear, 1<<3);
+ csr32r(c, Rmear);
+ }
+
+ csr32w(c, Rmear, 1<<3);
+ csr32w(c, Rmear, 0);
+
+ return r;
+}
+
+static void
+nsnormalea(Ctlr *ctlr)
+{
+ int i, j;
+
+ /*
+ * the MAC address is reversed, straddling word boundaries
+ */
+ j = Nseenodeaddr*16 + 15;
+ for(i = 0; i < 48; i++){
+ ctlr->sromea[i>>3] |= ((ctlr->srom[j>>4] >> (15-(j&0xF))) & 1) << (i&7);
+ j++;
+ }
+}
+
+static void
+ns403ea(Ctlr *ctlr)
+{
+ int i;
+ ushort s, t;
+
+ s = ctlr->srom[6];
+ for(i = 0; i < 3; i++){
+ t = ctlr->srom[i+7];
+ ctlr->sromea[i*2] = t<<1 | s>>15;
+ ctlr->sromea[i*2+1] = t>>7;
+ s = t;
+ }
+}
+
+static void
+nssrom(Ctlr* ctlr)
+{
+ int i, ns403;
+ ulong vers;
+ ushort (*ee)(Ctlr*, int);
+
+ vers = ctlr->version;
+ ns403 = vers == Nat83815avng || vers == Nat83816avng;
+ if(ns403){
+ ee = søkrisee;
+ print("soekris %lx\n", vers);
+ }else
+ ee = eegetw;
+
+ for(i = 0; i < nelem(ctlr->srom); i++)
+ ctlr->srom[i] = ee(ctlr, i);
+
+ if(ns403)
+ ns403ea(ctlr);
+ else
+ nsnormalea(ctlr);
+}
+
+static void
+srom(Ctlr* ctlr)
+{
+ memset(ctlr->sromea, 0, sizeof(ctlr->sromea));
+ switch (ctlr->id) {
+ case SiS900:
+ case SiS7016:
+ sissrom(ctlr);
+ break;
+ case Nat83815:
+ nssrom(ctlr);
+ break;
+ default:
+ print("ns83815: srom: unknown id 0x%ux\n", ctlr->id);
+ break;
+ }
+}
+
+static void
+scanpci83815(void)
+{
+ Ctlr *ctlr;
+ Pcidev *p;
+ ulong id;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != Pcibcnet || p->ccru != 0)
+ continue;
+ id = (p->did<<16)|p->vid;
+ switch(id){
+ default:
+ continue;
+
+ case Nat83815:
+ break;
+ case SiS900:
+ break;
+ }
+
+ /*
+ * bar[0] is the I/O port register address and
+ * bar[1] is the memory-mapped register address.
+ */
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = p->mem[0].bar & ~0x01;
+ ctlr->pcidev = p;
+ ctlr->id = id;
+
+ if(ioalloc(ctlr->port, p->mem[0].size, 0, "ns83815") < 0){
+ print("ns83815: port 0x%uX in use\n", ctlr->port);
+ free(ctlr);
+ continue;
+ }
+
+ if(softreset(ctlr, 0) == -1){
+ free(ctlr);
+ continue;
+ }
+ srom(ctlr);
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+}
+
+/* multicast already on, don't need to do anything */
+static void
+multicast(void*, uchar*, int)
+{
+}
+
+static int
+reset(Ether* ether)
+{
+ Ctlr *ctlr;
+ int i, x;
+ ulong ctladdr;
+ uchar ea[Eaddrlen];
+ static int scandone;
+
+ if(scandone == 0){
+ scanpci83815();
+ scandone = 1;
+ }
+
+ /*
+ * Any adapter matches if no ether->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(ether->port == 0 || ether->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ ether->ctlr = ctlr;
+ ether->port = ctlr->port;
+ ether->irq = ctlr->pcidev->intl;
+ ether->tbdf = ctlr->pcidev->tbdf;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to
+ * loading the station address in the hardware.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0)
+ memmove(ether->ea, ctlr->sromea, Eaddrlen);
+ for(i=0; i<Eaddrlen; i+=2){
+ x = ether->ea[i] | (ether->ea[i+1]<<8);
+ ctladdr = (ctlr->id == Nat83815? i: i<<15);
+ csr32w(ctlr, Rrfcr, ctladdr);
+ csr32w(ctlr, Rrfdr, x);
+ }
+ csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam);
+
+ ether->mbps = media(ether);
+
+ /*
+ * Look for a medium override in case there's no autonegotiation
+ * the autonegotiation fails.
+ */
+
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrcmp(ether->opt[i], "FD") == 0){
+ ctlr->fd = 1;
+ continue;
+ }
+ for(x = 0; x < nelem(mediatable); x++){
+ debug("compare <%s> <%s>\n", mediatable[x],
+ ether->opt[i]);
+ if(cistrcmp(mediatable[x], ether->opt[i]) == 0){
+ if(x != 4 && x >= 3)
+ ether->mbps = 100;
+ else
+ ether->mbps = 10;
+ switch(x){
+ default:
+ ctlr->fd = 0;
+ break;
+
+ case 0x04: /* 10BASE-TFD */
+ case 0x05: /* 100BASE-TXFD */
+ case 0x08: /* 100BASE-FXFD */
+ ctlr->fd = 1;
+ break;
+ }
+ break;
+ }
+ }
+ }
+
+ /*
+ * Initialise descriptor rings, ethernet address.
+ */
+ ctlr->nrdr = Nrde;
+ ctlr->ntdr = Ntde;
+ pcisetbme(ctlr->pcidev);
+ ctlrinit(ether);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->ifstat = ifstat;
+
+ ether->arg = ether;
+ ether->promiscuous = promiscuous;
+ ether->multicast = multicast;
+ ether->shutdown = shutdown;
+ return 0;
+}
+
+void
+ether83815link(void)
+{
+ addethercard("83815", reset);
+}
diff --git a/sys/src/9/pc/ether8390.c b/sys/src/9/pc/ether8390.c
new file mode 100755
index 000000000..50d7ce396
--- /dev/null
+++ b/sys/src/9/pc/ether8390.c
@@ -0,0 +1,812 @@
+/*
+ * National Semiconductor DP8390 and clone
+ * Network Interface Controller.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "ether8390.h"
+
+enum { /* NIC core registers */
+ Cr = 0x00, /* command register, all pages */
+
+ /* Page 0, read */
+ Clda0 = 0x01, /* current local DMA address 0 */
+ Clda1 = 0x02, /* current local DMA address 1 */
+ Bnry = 0x03, /* boundary pointer (R/W) */
+ Tsr = 0x04, /* transmit status register */
+ Ncr = 0x05, /* number of collisions register */
+ Fifo = 0x06, /* FIFO */
+ Isr = 0x07, /* interrupt status register (R/W) */
+ Crda0 = 0x08, /* current remote DMA address 0 */
+ Crda1 = 0x09, /* current remote DMA address 1 */
+ Rsr = 0x0C, /* receive status register */
+ Ref0 = 0x0D, /* frame alignment errors */
+ Ref1 = 0x0E, /* CRC errors */
+ Ref2 = 0x0F, /* missed packet errors */
+
+ /* Page 0, write */
+ Pstart = 0x01, /* page start register */
+ Pstop = 0x02, /* page stop register */
+ Tpsr = 0x04, /* transmit page start address */
+ Tbcr0 = 0x05, /* transmit byte count register 0 */
+ Tbcr1 = 0x06, /* transmit byte count register 1 */
+ Rsar0 = 0x08, /* remote start address register 0 */
+ Rsar1 = 0x09, /* remote start address register 1 */
+ Rbcr0 = 0x0A, /* remote byte count register 0 */
+ Rbcr1 = 0x0B, /* remote byte count register 1 */
+ Rcr = 0x0C, /* receive configuration register */
+ Tcr = 0x0D, /* transmit configuration register */
+ Dcr = 0x0E, /* data configuration register */
+ Imr = 0x0F, /* interrupt mask */
+
+ /* Page 1, read/write */
+ Par0 = 0x01, /* physical address register 0 */
+ Curr = 0x07, /* current page register */
+ Mar0 = 0x08, /* multicast address register 0 */
+};
+
+enum { /* Cr */
+ Stp = 0x01, /* stop */
+ Sta = 0x02, /* start */
+ Txp = 0x04, /* transmit packet */
+ Rd0 = 0x08, /* remote DMA command */
+ Rd1 = 0x10,
+ Rd2 = 0x20,
+ RdREAD = Rd0, /* remote read */
+ RdWRITE = Rd1, /* remote write */
+ RdSEND = Rd1|Rd0, /* send packet */
+ RdABORT = Rd2, /* abort/complete remote DMA */
+ Ps0 = 0x40, /* page select */
+ Ps1 = 0x80,
+ Page0 = 0x00,
+ Page1 = Ps0,
+ Page2 = Ps1,
+};
+
+enum { /* Isr/Imr */
+ Prx = 0x01, /* packet received */
+ Ptx = 0x02, /* packet transmitted */
+ Rxe = 0x04, /* receive error */
+ Txe = 0x08, /* transmit error */
+ Ovw = 0x10, /* overwrite warning */
+ Cnt = 0x20, /* counter overflow */
+ Rdc = 0x40, /* remote DMA complete */
+ Rst = 0x80, /* reset status */
+};
+
+enum { /* Dcr */
+ Wts = 0x01, /* word transfer select */
+ Bos = 0x02, /* byte order select */
+ Las = 0x04, /* long address select */
+ Ls = 0x08, /* loopback select */
+ Arm = 0x10, /* auto-initialise remote */
+ Ft0 = 0x20, /* FIFO threshold select */
+ Ft1 = 0x40,
+ Ft1WORD = 0x00,
+ Ft2WORD = Ft0,
+ Ft4WORD = Ft1,
+ Ft6WORD = Ft1|Ft0,
+};
+
+enum { /* Tcr */
+ Crc = 0x01, /* inhibit CRC */
+ Lb0 = 0x02, /* encoded loopback control */
+ Lb1 = 0x04,
+ LpbkNORMAL = 0x00, /* normal operation */
+ LpbkNIC = Lb0, /* internal NIC module loopback */
+ LpbkENDEC = Lb1, /* internal ENDEC module loopback */
+ LpbkEXTERNAL = Lb1|Lb0, /* external loopback */
+ Atd = 0x08, /* auto transmit disable */
+ Ofst = 0x10, /* collision offset enable */
+};
+
+enum { /* Tsr */
+ Ptxok = 0x01, /* packet transmitted */
+ Col = 0x04, /* transmit collided */
+ Abt = 0x08, /* tranmit aborted */
+ Crs = 0x10, /* carrier sense lost */
+ Fu = 0x20, /* FIFO underrun */
+ Cdh = 0x40, /* CD heartbeat */
+ Owc = 0x80, /* out of window collision */
+};
+
+enum { /* Rcr */
+ Sep = 0x01, /* save errored packets */
+ Ar = 0x02, /* accept runt packets */
+ Ab = 0x04, /* accept broadcast */
+ Am = 0x08, /* accept multicast */
+ Pro = 0x10, /* promiscuous physical */
+ Mon = 0x20, /* monitor mode */
+};
+
+enum { /* Rsr */
+ Prxok = 0x01, /* packet received intact */
+ Crce = 0x02, /* CRC error */
+ Fae = 0x04, /* frame alignment error */
+ Fo = 0x08, /* FIFO overrun */
+ Mpa = 0x10, /* missed packet */
+ Phy = 0x20, /* physical/multicast address */
+ Dis = 0x40, /* receiver disabled */
+ Dfr = 0x80, /* deferring */
+};
+
+typedef struct Hdr Hdr;
+struct Hdr {
+ uchar status;
+ uchar next;
+ uchar len0;
+ uchar len1;
+};
+
+void
+dp8390getea(Ether* ether, uchar* ea)
+{
+ Dp8390 *ctlr;
+ uchar cr;
+ int i;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * Get the ethernet address from the chip.
+ * Take care to restore the command register
+ * afterwards.
+ */
+ ilock(ctlr);
+ cr = regr(ctlr, Cr) & ~Txp;
+ regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
+ for(i = 0; i < Eaddrlen; i++)
+ ea[i] = regr(ctlr, Par0+i);
+ regw(ctlr, Cr, cr);
+ iunlock(ctlr);
+}
+
+void
+dp8390setea(Ether* ether)
+{
+ int i;
+ uchar cr;
+ Dp8390 *ctlr;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * Set the ethernet address into the chip.
+ * Take care to restore the command register
+ * afterwards. Don't care about multicast
+ * addresses as multicast is never enabled
+ * (currently).
+ */
+ ilock(ctlr);
+ cr = regr(ctlr, Cr) & ~Txp;
+ regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
+ for(i = 0; i < Eaddrlen; i++)
+ regw(ctlr, Par0+i, ether->ea[i]);
+ regw(ctlr, Cr, cr);
+ iunlock(ctlr);
+}
+
+static void*
+_dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len)
+{
+ uchar cr;
+ int timo;
+
+ /*
+ * Read some data at offset 'from' in the card's memory
+ * using the DP8390 remote DMA facility, and place it at
+ * 'to' in main memory, via the I/O data port.
+ */
+ cr = regr(ctlr, Cr) & ~Txp;
+ regw(ctlr, Cr, Page0|RdABORT|Sta);
+ regw(ctlr, Isr, Rdc);
+
+ /*
+ * Set up the remote DMA address and count.
+ */
+ len = ROUNDUP(len, ctlr->width);
+ regw(ctlr, Rbcr0, len & 0xFF);
+ regw(ctlr, Rbcr1, (len>>8) & 0xFF);
+ regw(ctlr, Rsar0, from & 0xFF);
+ regw(ctlr, Rsar1, (from>>8) & 0xFF);
+
+ /*
+ * Start the remote DMA read and suck the data
+ * out of the I/O port.
+ */
+ regw(ctlr, Cr, Page0|RdREAD|Sta);
+ rdread(ctlr, to, len);
+
+ /*
+ * Wait for the remote DMA to complete. The timeout
+ * is necessary because this routine may be called on
+ * a non-existent chip during initialisation and, due
+ * to the miracles of the bus, it's possible to get this
+ * far and still be talking to a slot full of nothing.
+ */
+ for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--)
+ ;
+
+ regw(ctlr, Isr, Rdc);
+ regw(ctlr, Cr, cr);
+
+ return to;
+}
+
+void*
+dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len)
+{
+ void *v;
+
+ ilock(ctlr);
+ v = _dp8390read(ctlr, to, from, len);
+ iunlock(ctlr);
+
+ return v;
+}
+
+static void*
+dp8390write(Dp8390* ctlr, ulong to, void* from, ulong len)
+{
+ ulong crda;
+ uchar cr;
+ int timo, width;
+
+top:
+ /*
+ * Write some data to offset 'to' in the card's memory
+ * using the DP8390 remote DMA facility, reading it at
+ * 'from' in main memory, via the I/O data port.
+ */
+ cr = regr(ctlr, Cr) & ~Txp;
+ regw(ctlr, Cr, Page0|RdABORT|Sta);
+ regw(ctlr, Isr, Rdc);
+
+ len = ROUNDUP(len, ctlr->width);
+
+ /*
+ * Set up the remote DMA address and count.
+ * This is straight from the DP8390[12D] datasheet,
+ * hence the initial set up for read.
+ * Assumption here that the A7000 EtherV card will
+ * never need a dummyrr.
+ */
+ if(ctlr->dummyrr && (ctlr->width == 1 || ctlr->width == 2)){
+ if(ctlr->width == 2)
+ width = 1;
+ else
+ width = 0;
+ crda = to-1-width;
+ regw(ctlr, Rbcr0, (len+1+width) & 0xFF);
+ regw(ctlr, Rbcr1, ((len+1+width)>>8) & 0xFF);
+ regw(ctlr, Rsar0, crda & 0xFF);
+ regw(ctlr, Rsar1, (crda>>8) & 0xFF);
+ regw(ctlr, Cr, Page0|RdREAD|Sta);
+
+ for(timo=0;; timo++){
+ if(timo > 10000){
+ print("ether8390: dummyrr timeout; assuming nodummyrr\n");
+ ctlr->dummyrr = 0;
+ goto top;
+ }
+ crda = regr(ctlr, Crda0);
+ crda |= regr(ctlr, Crda1)<<8;
+ if(crda == to){
+ /*
+ * Start the remote DMA write and make sure
+ * the registers are correct.
+ */
+ regw(ctlr, Cr, Page0|RdWRITE|Sta);
+
+ crda = regr(ctlr, Crda0);
+ crda |= regr(ctlr, Crda1)<<8;
+ if(crda != to)
+ panic("crda write %lud to %lud\n", crda, to);
+
+ break;
+ }
+ }
+ }
+ else{
+ regw(ctlr, Rsar0, to & 0xFF);
+ regw(ctlr, Rsar1, (to>>8) & 0xFF);
+ regw(ctlr, Rbcr0, len & 0xFF);
+ regw(ctlr, Rbcr1, (len>>8) & 0xFF);
+ regw(ctlr, Cr, Page0|RdWRITE|Sta);
+ }
+
+ /*
+ * Pump the data into the I/O port
+ * then wait for the remote DMA to finish.
+ */
+ rdwrite(ctlr, from, len);
+ for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--)
+ ;
+
+ regw(ctlr, Isr, Rdc);
+ regw(ctlr, Cr, cr);
+
+ return (void*)to;
+}
+
+static void
+ringinit(Dp8390* ctlr)
+{
+ regw(ctlr, Pstart, ctlr->pstart);
+ regw(ctlr, Pstop, ctlr->pstop);
+ regw(ctlr, Bnry, ctlr->pstop-1);
+
+ regw(ctlr, Cr, Page1|RdABORT|Stp);
+ regw(ctlr, Curr, ctlr->pstart);
+ regw(ctlr, Cr, Page0|RdABORT|Stp);
+
+ ctlr->nxtpkt = ctlr->pstart;
+}
+
+static uchar
+getcurr(Dp8390* ctlr)
+{
+ uchar cr, curr;
+
+ cr = regr(ctlr, Cr) & ~Txp;
+ regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
+ curr = regr(ctlr, Curr);
+ regw(ctlr, Cr, cr);
+
+ return curr;
+}
+
+static void
+receive(Ether* ether)
+{
+ Dp8390 *ctlr;
+ uchar curr, *p;
+ Hdr hdr;
+ ulong count, data, len;
+ Block *bp;
+
+ ctlr = ether->ctlr;
+ for(curr = getcurr(ctlr); ctlr->nxtpkt != curr; curr = getcurr(ctlr)){
+ data = ctlr->nxtpkt*Dp8390BufSz;
+ if(ctlr->ram)
+ memmove(&hdr, (void*)(ether->mem+data), sizeof(Hdr));
+ else
+ _dp8390read(ctlr, &hdr, data, sizeof(Hdr));
+
+ /*
+ * Don't believe the upper byte count, work it
+ * out from the software next-page pointer and
+ * the current next-page pointer.
+ */
+ if(hdr.next > ctlr->nxtpkt)
+ len = hdr.next - ctlr->nxtpkt - 1;
+ else
+ len = (ctlr->pstop-ctlr->nxtpkt) + (hdr.next-ctlr->pstart) - 1;
+ if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr)))
+ len--;
+
+ len = ((len<<8)|hdr.len0)-4;
+
+ /*
+ * Chip is badly scrogged, reinitialise the ring.
+ */
+ 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",
+ hdr.status, hdr.next, hdr.len0, hdr.len1, len);
+ regw(ctlr, Cr, Page0|RdABORT|Stp);
+ ringinit(ctlr);
+ regw(ctlr, Cr, Page0|RdABORT|Sta);
+
+ return;
+ }
+
+ /*
+ * If it's a good packet read it in to the software buffer.
+ * If the packet wraps round the hardware ring, read it in
+ * two pieces.
+ */
+ if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && (bp = iallocb(len))){
+ p = bp->rp;
+ bp->wp = p+len;
+ data += sizeof(Hdr);
+
+ if((data+len) >= ctlr->pstop*Dp8390BufSz){
+ count = ctlr->pstop*Dp8390BufSz - data;
+ if(ctlr->ram)
+ memmove(p, (void*)(ether->mem+data), count);
+ else
+ _dp8390read(ctlr, p, data, count);
+ p += count;
+ data = ctlr->pstart*Dp8390BufSz;
+ len -= count;
+ }
+ if(len){
+ if(ctlr->ram)
+ memmove(p, (void*)(ether->mem+data), len);
+ else
+ _dp8390read(ctlr, p, data, len);
+ }
+
+ /*
+ * Copy the packet to whoever wants it.
+ */
+ etheriq(ether, bp, 1);
+ }
+
+ /*
+ * Finished with this packet, update the
+ * hardware and software ring pointers.
+ */
+ ctlr->nxtpkt = hdr.next;
+
+ hdr.next--;
+ if(hdr.next < ctlr->pstart)
+ hdr.next = ctlr->pstop-1;
+ regw(ctlr, Bnry, hdr.next);
+ }
+}
+
+static void
+txstart(Ether* ether)
+{
+ int len;
+ Dp8390 *ctlr;
+ Block *bp;
+ uchar minpkt[ETHERMINTU], *rp;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * This routine is called both from the top level and from interrupt
+ * level and expects to be called with ctlr already locked.
+ */
+ if(ctlr->txbusy)
+ return;
+ bp = qget(ether->oq);
+ if(bp == nil)
+ return;
+
+ /*
+ * Make sure the packet is of minimum length;
+ * copy it to the card's memory by the appropriate means;
+ * start the transmission.
+ */
+ len = BLEN(bp);
+ rp = bp->rp;
+ if(len < ETHERMINTU){
+ rp = minpkt;
+ memmove(rp, bp->rp, len);
+ memset(rp+len, 0, ETHERMINTU-len);
+ len = ETHERMINTU;
+ }
+
+ if(ctlr->ram)
+ memmove((void*)(ether->mem+ctlr->tstart*Dp8390BufSz), rp, len);
+ else
+ dp8390write(ctlr, ctlr->tstart*Dp8390BufSz, rp, len);
+ freeb(bp);
+
+ regw(ctlr, Tbcr0, len & 0xFF);
+ regw(ctlr, Tbcr1, (len>>8) & 0xFF);
+ regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);
+
+ ether->outpackets++;
+ ctlr->txbusy = 1;
+}
+
+static void
+transmit(Ether* ether)
+{
+ Dp8390 *ctlr;
+
+ ctlr = ether->ctlr;
+
+ ilock(ctlr);
+ txstart(ether);
+ iunlock(ctlr);
+}
+
+static void
+overflow(Ether *ether)
+{
+ Dp8390 *ctlr;
+ uchar txp;
+ int resend;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * The following procedure is taken from the DP8390[12D] datasheet,
+ * it seems pretty adamant that this is what has to be done.
+ */
+ txp = regr(ctlr, Cr) & Txp;
+ regw(ctlr, Cr, Page0|RdABORT|Stp);
+ delay(2);
+ regw(ctlr, Rbcr0, 0);
+ regw(ctlr, Rbcr1, 0);
+
+ resend = 0;
+ if(txp && (regr(ctlr, Isr) & (Txe|Ptx)) == 0)
+ resend = 1;
+
+ regw(ctlr, Tcr, LpbkNIC);
+ regw(ctlr, Cr, Page0|RdABORT|Sta);
+ receive(ether);
+ regw(ctlr, Isr, Ovw);
+ regw(ctlr, Tcr, LpbkNORMAL);
+
+ if(resend)
+ regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ Ether *ether;
+ Dp8390 *ctlr;
+ uchar isr, r;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+
+ /*
+ * While there is something of interest,
+ * clear all the interrupts and process.
+ */
+ ilock(ctlr);
+ regw(ctlr, Imr, 0x00);
+ while(isr = (regr(ctlr, Isr) & (Cnt|Ovw|Txe|Rxe|Ptx|Prx))){
+ if(isr & Ovw){
+ overflow(ether);
+ regw(ctlr, Isr, Ovw);
+ ether->overflows++;
+ }
+
+ /*
+ * Packets have been received.
+ * Take a spin round the ring.
+ */
+ if(isr & (Rxe|Prx)){
+ receive(ether);
+ regw(ctlr, Isr, Rxe|Prx);
+ }
+
+ /*
+ * A packet completed transmission, successfully or
+ * not. Start transmission on the next buffered packet,
+ * and wake the output routine.
+ */
+ if(isr & (Txe|Ptx)){
+ r = regr(ctlr, Tsr);
+ if((isr & Txe) && (r & (Cdh|Fu|Crs|Abt))){
+ print("dp8390: Tsr %#2.2ux", r);
+ ether->oerrs++;
+ }
+
+ regw(ctlr, Isr, Txe|Ptx);
+
+ if(isr & Ptx)
+ ether->outpackets++;
+ ctlr->txbusy = 0;
+ txstart(ether);
+ }
+
+ if(isr & Cnt){
+ ether->frames += regr(ctlr, Ref0);
+ ether->crcs += regr(ctlr, Ref1);
+ ether->buffs += regr(ctlr, Ref2);
+ regw(ctlr, Isr, Cnt);
+ }
+ }
+ regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);
+ iunlock(ctlr);
+}
+
+static uchar allmar[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+static void
+setfilter(Ether *ether, Dp8390 *ctlr)
+{
+ uchar r, cr;
+ int i;
+ uchar *mar;
+
+ r = Ab;
+ mar = 0;
+ if(ether->prom){
+ r |= Pro|Am;
+ mar = allmar;
+ } else if(ether->nmaddr){
+ r |= Am;
+ mar = ctlr->mar;
+ }
+ if(mar){
+ cr = regr(ctlr, Cr) & ~Txp;
+ regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
+ for(i = 0; i < 8; i++)
+ regw(ctlr, Mar0+i, *(mar++));
+ regw(ctlr, Cr, cr);
+ }
+ regw(ctlr, Rcr, r);
+}
+
+static void
+promiscuous(void *arg, int )
+{
+ Ether *ether;
+ Dp8390 *ctlr;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+
+ ilock(ctlr);
+ setfilter(ether, ctlr);
+ iunlock(ctlr);
+}
+
+static void
+setbit(Dp8390 *ctlr, int bit, int on)
+{
+ int i, h;
+
+ i = bit/8;
+ h = bit%8;
+ if(on){
+ if(++(ctlr->mref[bit]) == 1)
+ ctlr->mar[i] |= 1<<h;
+ } else {
+ if(--(ctlr->mref[bit]) <= 0){
+ ctlr->mref[bit] = 0;
+ ctlr->mar[i] &= ~(1<<h);
+ }
+ }
+}
+
+static uchar reverse[64];
+
+static void
+multicast(void* arg, uchar *addr, int on)
+{
+ Ether *ether;
+ Dp8390 *ctlr;
+ int i;
+ ulong h;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+ 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);
+ }
+
+ /*
+ * change filter bits
+ */
+ h = ethercrc(addr, 6);
+ ilock(ctlr);
+ setbit(ctlr, reverse[h&0x3f], on);
+ setfilter(ether, ctlr);
+ iunlock(ctlr);
+}
+
+static void
+attach(Ether* ether)
+{
+ Dp8390 *ctlr;
+ uchar r;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * Enable the chip for transmit/receive.
+ * The init routine leaves the chip in monitor
+ * mode. Clear the missed-packet counter, it
+ * increments while in monitor mode.
+ * Sometimes there's an interrupt pending at this
+ * point but there's nothing in the Isr, so
+ * any pending interrupts are cleared and the
+ * mask of acceptable interrupts is enabled here.
+ */
+ r = Ab;
+ if(ether->prom)
+ r |= Pro;
+ if(ether->nmaddr)
+ r |= Am;
+ ilock(ctlr);
+ regw(ctlr, Isr, 0xFF);
+ regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);
+ regw(ctlr, Rcr, r);
+ r = regr(ctlr, Ref2);
+ regw(ctlr, Tcr, LpbkNORMAL);
+ iunlock(ctlr);
+ USED(r);
+}
+
+static void
+disable(Dp8390* ctlr)
+{
+ int timo;
+
+ /*
+ * Stop the chip. Set the Stp bit and wait for the chip
+ * to finish whatever was on its tiny mind before it sets
+ * the Rst bit.
+ * The timeout is needed because there may not be a real
+ * chip there if this is called when probing for a device
+ * at boot.
+ */
+ regw(ctlr, Cr, Page0|RdABORT|Stp);
+ regw(ctlr, Rbcr0, 0);
+ regw(ctlr, Rbcr1, 0);
+ for(timo = 10000; (regr(ctlr, Isr) & Rst) == 0 && timo; timo--)
+ ;
+}
+
+int
+dp8390reset(Ether* ether)
+{
+ Dp8390 *ctlr;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * This is the initialisation procedure described
+ * as 'mandatory' in the datasheet, with references
+ * to the 3C503 technical reference manual.
+ */
+ disable(ctlr);
+ if(ctlr->width != 1)
+ regw(ctlr, Dcr, Ft4WORD|Ls|Wts);
+ else
+ regw(ctlr, Dcr, Ft4WORD|Ls);
+
+ regw(ctlr, Rbcr0, 0);
+ regw(ctlr, Rbcr1, 0);
+
+ regw(ctlr, Tcr, LpbkNIC);
+ regw(ctlr, Rcr, Mon);
+
+ /*
+ * Init the ring hardware and software ring pointers.
+ * Can't initialise ethernet address as it may not be
+ * known yet.
+ */
+ ringinit(ctlr);
+ regw(ctlr, Tpsr, ctlr->tstart);
+
+ /*
+ * Clear any pending interrupts and mask then all off.
+ */
+ regw(ctlr, Isr, 0xFF);
+ regw(ctlr, Imr, 0);
+
+ /*
+ * Leave the chip initialised,
+ * but in monitor mode.
+ */
+ regw(ctlr, Cr, Page0|RdABORT|Sta);
+
+ /*
+ * Set up the software configuration.
+ */
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->ifstat = 0;
+
+ ether->promiscuous = promiscuous;
+ ether->multicast = multicast;
+ ether->arg = ether;
+
+ return 0;
+}
diff --git a/sys/src/9/pc/ether8390.h b/sys/src/9/pc/ether8390.h
new file mode 100755
index 000000000..b5bf6e555
--- /dev/null
+++ b/sys/src/9/pc/ether8390.h
@@ -0,0 +1,74 @@
+/*
+ * Ctlr for the boards using the National Semiconductor DP8390
+ * and SMC 83C90 Network Interface Controller.
+ * Common code is in ether8390.c.
+ */
+typedef struct {
+ Lock;
+
+ ulong port; /* I/O address of 8390 */
+ ulong data; /* I/O data port if no shared memory */
+
+ uchar width; /* data transfer width in bytes */
+ uchar ram; /* true if card has shared memory */
+ uchar dummyrr; /* do dummy remote read */
+
+ uchar nxtpkt; /* receive: software bndry */
+ uchar pstart;
+ uchar pstop;
+
+ int txbusy; /* transmit */
+ uchar tstart; /* 8390 ring addresses */
+
+ uchar mar[8]; /* shadow multicast address registers */
+ int mref[64]; /* reference counts for multicast groups */
+} Dp8390;
+
+#define Dp8390BufSz 256
+
+extern int dp8390reset(Ether*);
+extern void *dp8390read(Dp8390*, void*, ulong, ulong);
+extern void dp8390getea(Ether*, uchar*);
+extern void dp8390setea(Ether*);
+
+/*
+ * x86-specific code.
+ */
+#define regr(c, r) inb((c)->port+(r))
+#define regw(c, r, v) outb((c)->port+(r), (v))
+
+static void
+rdread(Dp8390* ctlr, void* to, int len)
+{
+ switch(ctlr->width){
+ default:
+ panic("dp8390 rdread: width %d\n", ctlr->width);
+ break;
+
+ case 2:
+ inss(ctlr->data, to, len/2);
+ break;
+
+ case 1:
+ insb(ctlr->data, to, len);
+ break;
+ }
+}
+
+static void
+rdwrite(Dp8390* ctlr, void* from, int len)
+{
+ switch(ctlr->width){
+ default:
+ panic("dp8390 rdwrite: width %d\n", ctlr->width);
+ break;
+
+ case 2:
+ outss(ctlr->data, from, len/2);
+ break;
+
+ case 1:
+ outsb(ctlr->data, from, len);
+ break;
+ }
+}
diff --git a/sys/src/9/pc/etherdp83820.c b/sys/src/9/pc/etherdp83820.c
new file mode 100755
index 000000000..98938e6d7
--- /dev/null
+++ b/sys/src/9/pc/etherdp83820.c
@@ -0,0 +1,1247 @@
+/*
+ * National Semiconductor DP83820
+ * 10/100/1000 Mb/s Ethernet Network Interface Controller
+ * (Gig-NIC).
+ * Driver assumes little-endian and 32-bit host throughout.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+enum { /* Registers */
+ Cr = 0x00, /* Command */
+ Cfg = 0x04, /* Configuration and Media Status */
+ Mear = 0x08, /* MII/EEPROM Access */
+ Ptscr = 0x0C, /* PCI Test Control */
+ Isr = 0x10, /* Interrupt Status */
+ Imr = 0x14, /* Interrupt Mask */
+ Ier = 0x18, /* Interrupt Enable */
+ Ihr = 0x1C, /* Interrupt Holdoff */
+ Txdp = 0x20, /* Transmit Descriptor Pointer */
+ Txdphi = 0x24, /* Transmit Descriptor Pointer Hi */
+ Txcfg = 0x28, /* Transmit Configuration */
+ Gpior = 0x2C, /* General Purpose I/O Control */
+ Rxdp = 0x30, /* Receive Descriptor Pointer */
+ Rxdphi = 0x34, /* Receive Descriptor Pointer Hi */
+ Rxcfg = 0x38, /* Receive Configuration */
+ Pqcr = 0x3C, /* Priority Queueing Control */
+ Wcsr = 0x40, /* Wake on LAN Control/Status */
+ Pcr = 0x44, /* Pause Control/Status */
+ Rfcr = 0x48, /* Receive Filter/Match Control */
+ Rfdr = 0x4C, /* Receive Filter/Match Data */
+ Brar = 0x50, /* Boot ROM Address */
+ Brdr = 0x54, /* Boot ROM Data */
+ Srr = 0x58, /* Silicon Revision */
+ Mibc = 0x5C, /* MIB Control */
+ Mibd = 0x60, /* MIB Data */
+ Txdp1 = 0xA0, /* Txdp Priority 1 */
+ Txdp2 = 0xA4, /* Txdp Priority 2 */
+ Txdp3 = 0xA8, /* Txdp Priority 3 */
+ Rxdp1 = 0xB0, /* Rxdp Priority 1 */
+ Rxdp2 = 0xB4, /* Rxdp Priority 2 */
+ Rxdp3 = 0xB8, /* Rxdp Priority 3 */
+ Vrcr = 0xBC, /* VLAN/IP Receive Control */
+ Vtcr = 0xC0, /* VLAN/IP Transmit Control */
+ Vdr = 0xC4, /* VLAN Data */
+ Ccsr = 0xCC, /* Clockrun Control/Status */
+ Tbicr = 0xE0, /* TBI Control */
+ Tbisr = 0xE4, /* TBI Status */
+ Tanar = 0xE8, /* TBI ANAR */
+ Tanlpar = 0xEC, /* TBI ANLPAR */
+ Taner = 0xF0, /* TBI ANER */
+ Tesr = 0xF4, /* TBI ESR */
+};
+
+enum { /* Cr */
+ Txe = 0x00000001, /* Transmit Enable */
+ Txd = 0x00000002, /* Transmit Disable */
+ Rxe = 0x00000004, /* Receiver Enable */
+ Rxd = 0x00000008, /* Receiver Disable */
+ Txr = 0x00000010, /* Transmitter Reset */
+ Rxr = 0x00000020, /* Receiver Reset */
+ Swien = 0x00000080, /* Software Interrupt Enable */
+ Rst = 0x00000100, /* Reset */
+ TxpriSHFT = 9, /* Tx Priority Queue Select */
+ TxpriMASK = 0x00001E00,
+ RxpriSHFT = 13, /* Rx Priority Queue Select */
+ RxpriMASK = 0x0001E000,
+};
+
+enum { /* Configuration and Media Status */
+ Bem = 0x00000001, /* Big Endian Mode */
+ Ext125 = 0x00000002, /* External 125MHz reference Select */
+ Bromdis = 0x00000004, /* Disable Boot ROM interface */
+ Pesel = 0x00000008, /* Parity Error Detection Action */
+ Exd = 0x00000010, /* Excessive Deferral Abort */
+ Pow = 0x00000020, /* Program Out of Window Timer */
+ Sb = 0x00000040, /* Single Back-off */
+ Reqalg = 0x00000080, /* PCI Bus Request Algorithm */
+ Extstsen = 0x00000100, /* Extended Status Enable */
+ Phydis = 0x00000200, /* Disable PHY */
+ Phyrst = 0x00000400, /* Reset PHY */
+ M64addren = 0x00000800, /* Master 64-bit Addressing Enable */
+ Data64en = 0x00001000, /* 64-bit Data Enable */
+ Pci64det = 0x00002000, /* PCI 64-bit Bus Detected */
+ T64addren = 0x00004000, /* Target 64-bit Addressing Enable */
+ Mwidis = 0x00008000, /* MWI Disable */
+ Mrmdis = 0x00010000, /* MRM Disable */
+ Tmrtest = 0x00020000, /* Timer Test Mode */
+ Spdstsien = 0x00040000, /* PHY Spdsts Interrupt Enable */
+ Lnkstsien = 0x00080000, /* PHY Lnksts Interrupt Enable */
+ Dupstsien = 0x00100000, /* PHY Dupsts Interrupt Enable */
+ Mode1000 = 0x00400000, /* 1000Mb/s Mode Control */
+ Tbien = 0x01000000, /* Ten-Bit Interface Enable */
+ Dupsts = 0x10000000, /* Full Duplex Status */
+ Spdsts100 = 0x20000000, /* SPEED100 Input Pin Status */
+ Spdsts1000 = 0x40000000, /* SPEED1000 Input Pin Status */
+ Lnksts = 0x80000000, /* Link Status */
+};
+
+enum { /* MII/EEPROM Access */
+ Eedi = 0x00000001, /* EEPROM Data In */
+ Eedo = 0x00000002, /* EEPROM Data Out */
+ Eeclk = 0x00000004, /* EEPROM Serial Clock */
+ Eesel = 0x00000008, /* EEPROM Chip Select */
+ Mdio = 0x00000010, /* MII Management Data */
+ Mddir = 0x00000020, /* MII Management Direction */
+ Mdc = 0x00000040, /* MII Management Clock */
+};
+
+enum { /* Interrupts */
+ Rxok = 0x00000001, /* Rx OK */
+ Rxdesc = 0x00000002, /* Rx Descriptor */
+ Rxerr = 0x00000004, /* Rx Packet Error */
+ Rxearly = 0x00000008, /* Rx Early Threshold */
+ Rxidle = 0x00000010, /* Rx Idle */
+ Rxorn = 0x00000020, /* Rx Overrun */
+ Txok = 0x00000040, /* Tx Packet OK */
+ Txdesc = 0x00000080, /* Tx Descriptor */
+ Txerr = 0x00000100, /* Tx Packet Error */
+ Txidle = 0x00000200, /* Tx Idle */
+ Txurn = 0x00000400, /* Tx Underrun */
+ Mib = 0x00000800, /* MIB Service */
+ Swi = 0x00001000, /* Software Interrupt */
+ Pme = 0x00002000, /* Power Management Event */
+ Phy = 0x00004000, /* PHY Interrupt */
+ Hibint = 0x00008000, /* High Bits Interrupt Set */
+ Rxsovr = 0x00010000, /* Rx Status FIFO Overrun */
+ Rtabt = 0x00020000, /* Received Target Abort */
+ Rmabt = 0x00040000, /* Received Master Abort */
+ Sserr = 0x00080000, /* Signalled System Error */
+ Dperr = 0x00100000, /* Detected Parity Error */
+ Rxrcmp = 0x00200000, /* Receive Reset Complete */
+ Txrcmp = 0x00400000, /* Transmit Reset Complete */
+ Rxdesc0 = 0x00800000, /* Rx Descriptor for Priority Queue 0 */
+ Rxdesc1 = 0x01000000, /* Rx Descriptor for Priority Queue 1 */
+ Rxdesc2 = 0x02000000, /* Rx Descriptor for Priority Queue 2 */
+ Rxdesc3 = 0x04000000, /* Rx Descriptor for Priority Queue 3 */
+ Txdesc0 = 0x08000000, /* Tx Descriptor for Priority Queue 0 */
+ Txdesc1 = 0x10000000, /* Tx Descriptor for Priority Queue 1 */
+ Txdesc2 = 0x20000000, /* Tx Descriptor for Priority Queue 2 */
+ Txdesc3 = 0x40000000, /* Tx Descriptor for Priority Queue 3 */
+};
+
+enum { /* Interrupt Enable */
+ Ien = 0x00000001, /* Interrupt Enable */
+};
+
+enum { /* Interrupt Holdoff */
+ IhSHFT = 0, /* Interrupt Holdoff */
+ IhMASK = 0x000000FF,
+ Ihctl = 0x00000100, /* Interrupt Holdoff Control */
+};
+
+enum { /* Transmit Configuration */
+ TxdrthSHFT = 0, /* Tx Drain Threshold */
+ TxdrthMASK = 0x000000FF,
+ FlthSHFT = 16, /* Tx Fill Threshold */
+ FlthMASK = 0x0000FF00,
+ Brstdis = 0x00080000, /* 1000Mb/s Burst Disable */
+ MxdmaSHFT = 20, /* Max Size per Tx DMA Burst */
+ MxdmaMASK = 0x00700000,
+ Ecretryen = 0x00800000, /* Excessive Collision Retry Enable */
+ Atp = 0x10000000, /* Automatic Transmit Padding */
+ Mlb = 0x20000000, /* MAC Loopback */
+ Hbi = 0x40000000, /* Heartbeat Ignore */
+ Csi = 0x80000000, /* Carrier Sense Ignore */
+};
+
+enum { /* Receive Configuration */
+ RxdrthSHFT = 1, /* Rx Drain Threshold */
+ RxdrthMASK = 0x0000003E,
+ Airl = 0x04000000, /* Accept In-Range Length Errored */
+ Alp = 0x08000000, /* Accept Long Packets */
+ Rxfd = 0x10000000, /* Receive Full Duplex */
+ Stripcrc = 0x20000000, /* Strip CRC */
+ Arp = 0x40000000, /* Accept Runt Packets */
+ Aep = 0x80000000, /* Accept Errored Packets */
+};
+
+enum { /* Priority Queueing Control */
+ Txpqen = 0x00000001, /* Transmit Priority Queuing Enable */
+ Txfairen = 0x00000002, /* Transmit Fairness Enable */
+ RxpqenSHFT = 2, /* Receive Priority Queue Enable */
+ RxpqenMASK = 0x0000000C,
+};
+
+enum { /* Pause Control/Status */
+ PscntSHFT = 0, /* Pause Counter Value */
+ PscntMASK = 0x0000FFFF,
+ Pstx = 0x00020000, /* Transmit Pause Frame */
+ PsffloSHFT = 18, /* Rx Data FIFO Lo Threshold */
+ PsffloMASK = 0x000C0000,
+ PsffhiSHFT = 20, /* Rx Data FIFO Hi Threshold */
+ PsffhiMASK = 0x00300000,
+ PsstloSHFT = 22, /* Rx Stat FIFO Hi Threshold */
+ PsstloMASK = 0x00C00000,
+ PssthiSHFT = 24, /* Rx Stat FIFO Hi Threshold */
+ PssthiMASK = 0x03000000,
+ Psrcvd = 0x08000000, /* Pause Frame Received */
+ Psact = 0x10000000, /* Pause Active */
+ Psda = 0x20000000, /* Pause on Destination Address */
+ Psmcast = 0x40000000, /* Pause on Multicast */
+ Psen = 0x80000000, /* Pause Enable */
+};
+
+enum { /* Receive Filter/Match Control */
+ RfaddrSHFT = 0, /* Extended Register Address */
+ RfaddrMASK = 0x000003FF,
+ Ulm = 0x00080000, /* U/L bit mask */
+ Uhen = 0x00100000, /* Unicast Hash Enable */
+ Mhen = 0x00200000, /* Multicast Hash Enable */
+ Aarp = 0x00400000, /* Accept ARP Packets */
+ ApatSHFT = 23, /* Accept on Pattern Match */
+ ApatMASK = 0x07800000,
+ Apm = 0x08000000, /* Accept on Perfect Match */
+ Aau = 0x10000000, /* Accept All Unicast */
+ Aam = 0x20000000, /* Accept All Multicast */
+ Aab = 0x40000000, /* Accept All Broadcast */
+ Rfen = 0x80000000, /* Rx Filter Enable */
+};
+
+enum { /* Receive Filter/Match Data */
+ RfdataSHFT = 0, /* Receive Filter Data */
+ RfdataMASK = 0x0000FFFF,
+ BmaskSHFT = 16, /* Byte Mask */
+ BmaskMASK = 0x00030000,
+};
+
+enum { /* MIB Control */
+ Wrn = 0x00000001, /* Warning Test Indicator */
+ Frz = 0x00000002, /* Freeze All Counters */
+ Aclr = 0x00000004, /* Clear All Counters */
+ Mibs = 0x00000008, /* MIB Counter Strobe */
+};
+
+enum { /* MIB Data */
+ Nmibd = 11, /* Number of MIB Data Registers */
+};
+
+enum { /* VLAN/IP Receive Control */
+ Vtden = 0x00000001, /* VLAN Tag Detection Enable */
+ Vtren = 0x00000002, /* VLAN Tag Removal Enable */
+ Dvtf = 0x00000004, /* Discard VLAN Tagged Frames */
+ Dutf = 0x00000008, /* Discard Untagged Frames */
+ Ipen = 0x00000010, /* IP Checksum Enable */
+ Ripe = 0x00000020, /* Reject IP Checksum Errors */
+ Rtcpe = 0x00000040, /* Reject TCP Checksum Errors */
+ Rudpe = 0x00000080, /* Reject UDP Checksum Errors */
+};
+
+enum { /* VLAN/IP Transmit Control */
+ Vgti = 0x00000001, /* VLAN Global Tag Insertion */
+ Vppti = 0x00000002, /* VLAN Per-Packet Tag Insertion */
+ Gchk = 0x00000004, /* Global Checksum Generation */
+ Ppchk = 0x00000008, /* Per-Packet Checksum Generation */
+};
+
+enum { /* VLAN Data */
+ VtypeSHFT = 0, /* VLAN Type Field */
+ VtypeMASK = 0x0000FFFF,
+ VtciSHFT = 16, /* VLAN Tag Control Information */
+ VtciMASK = 0xFFFF0000,
+};
+
+enum { /* Clockrun Control/Status */
+ Clkrunen = 0x00000001, /* CLKRUN Enable */
+ Pmeen = 0x00000100, /* PME Enable */
+ Pmests = 0x00008000, /* PME Status */
+};
+
+typedef struct {
+ u32int link; /* Link to the next descriptor */
+ u32int bufptr; /* pointer to data Buffer */
+ int cmdsts; /* Command/Status */
+ int extsts; /* optional Extended Status */
+
+ Block* bp; /* Block containing bufptr */
+ u32int unused; /* pad to 64-bit */
+} Desc;
+
+enum { /* Common cmdsts bits */
+ SizeMASK = 0x0000FFFF, /* Descriptor Byte Count */
+ SizeSHFT = 0,
+ Ok = 0x08000000, /* Packet OK */
+ Crc = 0x10000000, /* Suppress/Include CRC */
+ Intr = 0x20000000, /* Interrupt on ownership transfer */
+ More = 0x40000000, /* not last descriptor in a packet */
+ Own = 0x80000000, /* Descriptor Ownership */
+};
+
+enum { /* Transmit cmdsts bits */
+ CcntMASK = 0x000F0000, /* Collision Count */
+ CcntSHFT = 16,
+ Ec = 0x00100000, /* Excessive Collisions */
+ Owc = 0x00200000, /* Out of Window Collision */
+ Ed = 0x00400000, /* Excessive Deferral */
+ Td = 0x00800000, /* Transmit Deferred */
+ Crs = 0x01000000, /* Carrier Sense Lost */
+ Tfu = 0x02000000, /* Transmit FIFO Underrun */
+ Txa = 0x04000000, /* Transmit Abort */
+};
+
+enum { /* Receive cmdsts bits */
+ Irl = 0x00010000, /* In-Range Length Error */
+ Lbp = 0x00020000, /* Loopback Packet */
+ Fae = 0x00040000, /* Frame Alignment Error */
+ Crce = 0x00080000, /* CRC Error */
+ Ise = 0x00100000, /* Invalid Symbol Error */
+ Runt = 0x00200000, /* Runt Packet Received */
+ Long = 0x00400000, /* Too Long Packet Received */
+ DestMASK = 0x01800000, /* Destination Class */
+ DestSHFT = 23,
+ Rxo = 0x02000000, /* Receive Overrun */
+ Rxa = 0x04000000, /* Receive Aborted */
+};
+
+enum { /* extsts bits */
+ EvtciMASK = 0x0000FFFF, /* VLAN Tag Control Information */
+ EvtciSHFT = 0,
+ Vpkt = 0x00010000, /* VLAN Packet */
+ Ippkt = 0x00020000, /* IP Packet */
+ Iperr = 0x00040000, /* IP Checksum Error */
+ Tcppkt = 0x00080000, /* TCP Packet */
+ Tcperr = 0x00100000, /* TCP Checksum Error */
+ Udppkt = 0x00200000, /* UDP Packet */
+ Udperr = 0x00400000, /* UDP Checksum Error */
+};
+
+enum {
+ Nrd = 256,
+ Nrb = 4*Nrd,
+ Rbsz = ROUNDUP(sizeof(Etherpkt)+8, 8),
+ Ntd = 128,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id;
+
+ int eepromsz; /* address size in bits */
+ ushort* eeprom;
+
+ int* nic;
+ int cfg;
+ int imr;
+
+ QLock alock; /* attach */
+ Lock ilock; /* init */
+ void* alloc; /* base of per-Ctlr allocated data */
+
+ Mii* mii;
+
+ Lock rdlock; /* receive */
+ Desc* rd;
+ int nrd;
+ int nrb;
+ int rdx;
+ int rxcfg;
+
+ Lock tlock; /* transmit */
+ Desc* td;
+ int ntd;
+ int tdh;
+ int tdt;
+ int ntq;
+ int txcfg;
+
+ int rxidle;
+
+ uint mibd[Nmibd];
+
+ int ec;
+ int owc;
+ int ed;
+ int crs;
+ int tfu;
+ int txa;
+} Ctlr;
+
+#define csr32r(c, r) (*((c)->nic+((r)/4)))
+#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
+
+static Ctlr* dp83820ctlrhead;
+static Ctlr* dp83820ctlrtail;
+
+static Lock dp83820rblock; /* free receive Blocks */
+static Block* dp83820rbpool;
+
+static char* dp83820mibs[Nmibd] = {
+ "RXErroredPkts",
+ "RXFCSErrors",
+ "RXMsdPktErrors",
+ "RXFAErrors",
+ "RXSymbolErrors",
+ "RXFrameToLong",
+ "RXIRLErrors",
+ "RXBadOpcodes",
+ "RXPauseFrames",
+ "TXPauseFrames",
+ "TXSQEErrors",
+};
+
+static int
+mdior(Ctlr* ctlr, int n)
+{
+ int data, i, mear, r;
+
+ mear = csr32r(ctlr, Mear);
+ r = ~(Mdc|Mddir) & mear;
+ data = 0;
+ for(i = n-1; i >= 0; i--){
+ if(csr32r(ctlr, Mear) & Mdio)
+ data |= (1<<i);
+ csr32w(ctlr, Mear, Mdc|r);
+ csr32w(ctlr, Mear, r);
+ }
+ csr32w(ctlr, Mear, mear);
+
+ return data;
+}
+
+static void
+mdiow(Ctlr* ctlr, int bits, int n)
+{
+ int i, mear, r;
+
+ mear = csr32r(ctlr, Mear);
+ r = Mddir|(~Mdc & mear);
+ for(i = n-1; i >= 0; i--){
+ if(bits & (1<<i))
+ r |= Mdio;
+ else
+ r &= ~Mdio;
+ csr32w(ctlr, Mear, r);
+ csr32w(ctlr, Mear, Mdc|r);
+ }
+ csr32w(ctlr, Mear, mear);
+}
+
+static int
+dp83820miimir(Mii* mii, int pa, int ra)
+{
+ int data;
+ Ctlr *ctlr;
+
+ ctlr = mii->ctlr;
+
+ /*
+ * MII Management Interface Read.
+ *
+ * Preamble;
+ * ST+OP+PA+RA;
+ * LT + 16 data bits.
+ */
+ mdiow(ctlr, 0xFFFFFFFF, 32);
+ mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
+ data = mdior(ctlr, 18);
+
+ if(data & 0x10000)
+ return -1;
+
+ return data & 0xFFFF;
+}
+
+static int
+dp83820miimiw(Mii* mii, int pa, int ra, int data)
+{
+ Ctlr *ctlr;
+
+ ctlr = mii->ctlr;
+
+ /*
+ * MII Management Interface Write.
+ *
+ * Preamble;
+ * ST+OP+PA+RA+LT + 16 data bits;
+ * Z.
+ */
+ mdiow(ctlr, 0xFFFFFFFF, 32);
+ data &= 0xFFFF;
+ data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
+ mdiow(ctlr, data, 32);
+
+ return 0;
+}
+
+static Block *
+dp83820rballoc(Desc* desc)
+{
+ Block *bp;
+
+ if(desc->bp == nil){
+ ilock(&dp83820rblock);
+ if((bp = dp83820rbpool) == nil){
+ iunlock(&dp83820rblock);
+ desc->bp = nil;
+ desc->cmdsts = Own;
+ return nil;
+ }
+ dp83820rbpool = bp->next;
+ bp->next = nil;
+ _xinc(&bp->ref); /* prevent bp from being freed */
+ iunlock(&dp83820rblock);
+
+ desc->bufptr = PCIWADDR(bp->rp);
+ desc->bp = bp;
+ }
+ else{
+ bp = desc->bp;
+ bp->rp = bp->lim - Rbsz;
+ bp->wp = bp->rp;
+ }
+
+ coherence();
+ desc->cmdsts = Intr|Rbsz;
+
+ return bp;
+}
+
+static void
+dp83820rbfree(Block *bp)
+{
+ bp->rp = bp->lim - Rbsz;
+ bp->wp = bp->rp;
+
+ ilock(&dp83820rblock);
+ bp->next = dp83820rbpool;
+ dp83820rbpool = bp;
+ iunlock(&dp83820rblock);
+}
+
+static void
+dp83820halt(Ctlr* ctlr)
+{
+ int i, timeo;
+
+ ilock(&ctlr->ilock);
+ csr32w(ctlr, Imr, 0);
+ csr32w(ctlr, Ier, 0);
+ csr32w(ctlr, Cr, Rxd|Txd);
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
+ break;
+ microdelay(1);
+ }
+ csr32w(ctlr, Mibc, Frz);
+ iunlock(&ctlr->ilock);
+
+ if(ctlr->rd != nil){
+ for(i = 0; i < ctlr->nrd; i++){
+ if(ctlr->rd[i].bp == nil)
+ continue;
+ freeb(ctlr->rd[i].bp);
+ ctlr->rd[i].bp = nil;
+ }
+ }
+ if(ctlr->td != nil){
+ for(i = 0; i < ctlr->ntd; i++){
+ if(ctlr->td[i].bp == nil)
+ continue;
+ freeb(ctlr->td[i].bp);
+ ctlr->td[i].bp = nil;
+ }
+ }
+}
+
+static void
+dp83820cfg(Ctlr* ctlr)
+{
+ int cfg;
+
+ /*
+ * Don't know how to deal with a TBI yet.
+ */
+ if(ctlr->mii == nil)
+ return;
+
+ /*
+ * The polarity of these bits is at the mercy
+ * of the board designer.
+ * The correct answer for all speed and duplex questions
+ * should be to query the phy.
+ */
+ cfg = csr32r(ctlr, Cfg);
+ if(!(cfg & Dupsts)){
+ ctlr->rxcfg |= Rxfd;
+ ctlr->txcfg |= Csi|Hbi;
+ iprint("83820: full duplex, ");
+ }
+ else{
+ ctlr->rxcfg &= ~Rxfd;
+ ctlr->txcfg &= ~(Csi|Hbi);
+ iprint("83820: half duplex, ");
+ }
+ csr32w(ctlr, Rxcfg, ctlr->rxcfg);
+ csr32w(ctlr, Txcfg, ctlr->txcfg);
+
+ switch(cfg & (Spdsts1000|Spdsts100)){
+ case Spdsts1000: /* 100Mbps */
+ default: /* 10Mbps */
+ ctlr->cfg &= ~Mode1000;
+ if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
+ iprint("100Mb/s\n");
+ else
+ iprint("10Mb/s\n");
+ break;
+ case Spdsts100: /* 1Gbps */
+ ctlr->cfg |= Mode1000;
+ iprint("1Gb/s\n");
+ break;
+ }
+ csr32w(ctlr, Cfg, ctlr->cfg);
+}
+
+static void
+dp83820init(Ether* edev)
+{
+ int i;
+ Ctlr *ctlr;
+ Desc *desc;
+ uchar *alloc;
+
+ ctlr = edev->ctlr;
+
+ dp83820halt(ctlr);
+
+ /*
+ * Receiver
+ */
+ alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
+ ctlr->rd = (Desc*)alloc;
+ alloc += ctlr->nrd*sizeof(Desc);
+ memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
+ ctlr->rdx = 0;
+ for(i = 0; i < ctlr->nrd; i++){
+ desc = &ctlr->rd[i];
+ desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
+ if(dp83820rballoc(desc) == nil)
+ continue;
+ }
+ csr32w(ctlr, Rxdphi, 0);
+ csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
+
+ for(i = 0; i < Eaddrlen; i += 2){
+ csr32w(ctlr, Rfcr, i);
+ csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
+ }
+ csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
+
+ ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
+ ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
+
+ /*
+ * Transmitter.
+ */
+ ctlr->td = (Desc*)alloc;
+ memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
+ ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
+ for(i = 0; i < ctlr->ntd; i++){
+ desc = &ctlr->td[i];
+ desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
+ }
+ csr32w(ctlr, Txdphi, 0);
+ csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
+
+ ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
+ ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
+
+ ilock(&ctlr->ilock);
+
+ dp83820cfg(ctlr);
+
+ csr32w(ctlr, Mibc, Aclr);
+ ctlr->imr |= Mib;
+
+ csr32w(ctlr, Imr, ctlr->imr);
+
+ /* try coalescing adjacent interrupts; use hold-off interval of 100µs */
+ csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
+
+ csr32w(ctlr, Ier, Ien);
+ csr32w(ctlr, Cr, Rxe|Txe);
+
+ iunlock(&ctlr->ilock);
+}
+
+static void
+dp83820attach(Ether* edev)
+{
+ Block *bp;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ qlock(&ctlr->alock);
+ if(ctlr->alloc != nil){
+ qunlock(&ctlr->alock);
+ return;
+ }
+
+ if(waserror()){
+ if(ctlr->mii != nil){
+ free(ctlr->mii);
+ ctlr->mii = nil;
+ }
+ if(ctlr->alloc != nil){
+ free(ctlr->alloc);
+ ctlr->alloc = nil;
+ }
+ qunlock(&ctlr->alock);
+ nexterror();
+ }
+
+ if(!(ctlr->cfg & Tbien)){
+ if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+ error(Enomem);
+ ctlr->mii->ctlr = ctlr;
+ ctlr->mii->mir = dp83820miimir;
+ ctlr->mii->miw = dp83820miimiw;
+ if(mii(ctlr->mii, ~0) == 0)
+ error("no PHY");
+ ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
+ ctlr->imr |= Phy;
+ }
+
+ ctlr->nrd = Nrd;
+ ctlr->nrb = Nrb;
+ ctlr->ntd = Ntd;
+ ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
+ if(ctlr->alloc == nil)
+ error(Enomem);
+
+ for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){
+ if((bp = allocb(Rbsz)) == nil)
+ break;
+ bp->free = dp83820rbfree;
+ dp83820rbfree(bp);
+ }
+
+ dp83820init(edev);
+
+ qunlock(&ctlr->alock);
+ poperror();
+}
+
+static void
+dp83820transmit(Ether* edev)
+{
+ Block *bp;
+ Ctlr *ctlr;
+ Desc *desc;
+ int cmdsts, r, x;
+
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->tlock);
+
+ bp = nil;
+ for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
+ desc = &ctlr->td[x];
+ if((cmdsts = desc->cmdsts) & Own)
+ break;
+ if(!(cmdsts & Ok)){
+ if(cmdsts & Ec)
+ ctlr->ec++;
+ if(cmdsts & Owc)
+ ctlr->owc++;
+ if(cmdsts & Ed)
+ ctlr->ed++;
+ if(cmdsts & Crs)
+ ctlr->crs++;
+ if(cmdsts & Tfu)
+ ctlr->tfu++;
+ if(cmdsts & Txa)
+ ctlr->txa++;
+ edev->oerrs++;
+ }
+ desc->bp->next = bp;
+ bp = desc->bp;
+ desc->bp = nil;
+
+ ctlr->ntq--;
+ }
+ ctlr->tdh = x;
+ if(bp != nil)
+ freeblist(bp);
+
+ x = ctlr->tdt;
+ while(ctlr->ntq < (ctlr->ntd-1)){
+ if((bp = qget(edev->oq)) == nil)
+ break;
+
+ desc = &ctlr->td[x];
+ desc->bufptr = PCIWADDR(bp->rp);
+ desc->bp = bp;
+ ctlr->ntq++;
+ coherence();
+ desc->cmdsts = Own|Intr|BLEN(bp);
+
+ x = NEXT(x, ctlr->ntd);
+ }
+ if(x != ctlr->tdt){
+ ctlr->tdt = x;
+ r = csr32r(ctlr, Cr);
+ csr32w(ctlr, Cr, Txe|r);
+ }
+
+ iunlock(&ctlr->tlock);
+}
+
+static void
+dp83820interrupt(Ureg*, void* arg)
+{
+ Block *bp;
+ Ctlr *ctlr;
+ Desc *desc;
+ Ether *edev;
+ int cmdsts, i, isr, r, x;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
+ if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
+ x = ctlr->rdx;
+ desc = &ctlr->rd[x];
+ while((cmdsts = desc->cmdsts) & Own){
+ if((cmdsts & Ok) && desc->bp != nil){
+ bp = desc->bp;
+ desc->bp = nil;
+ bp->wp += cmdsts & SizeMASK;
+ etheriq(edev, bp, 1);
+ }
+ else if(0 && !(cmdsts & Ok)){
+ iprint("dp83820: rx %8.8uX:", cmdsts);
+ bp = desc->bp;
+ for(i = 0; i < 20; i++)
+ iprint(" %2.2uX", bp->rp[i]);
+ iprint("\n");
+ }
+ dp83820rballoc(desc);
+
+ x = NEXT(x, ctlr->nrd);
+ desc = &ctlr->rd[x];
+ }
+ ctlr->rdx = x;
+
+ if(isr & Rxidle){
+ r = csr32r(ctlr, Cr);
+ csr32w(ctlr, Cr, Rxe|r);
+ ctlr->rxidle++;
+ }
+
+ isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
+ }
+
+ if(isr & Txurn){
+ x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
+ r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
+ if(x < ((TxdrthMASK)>>TxdrthSHFT)
+ && x < (2048/32 - r)){
+ ctlr->txcfg &= ~TxdrthMASK;
+ x++;
+ ctlr->txcfg |= x<<TxdrthSHFT;
+ csr32w(ctlr, Txcfg, ctlr->txcfg);
+ }
+ }
+
+ if(isr & (Txurn|Txidle|Txdesc|Txok)){
+ dp83820transmit(edev);
+ isr &= ~(Txurn|Txidle|Txdesc|Txok);
+ }
+
+ if(isr & Mib){
+ for(i = 0; i < Nmibd; i++){
+ r = csr32r(ctlr, Mibd+(i*sizeof(int)));
+ ctlr->mibd[i] += r & 0xFFFF;
+ }
+ isr &= ~Mib;
+ }
+
+ if((isr & Phy) && ctlr->mii != nil){
+ ctlr->mii->mir(ctlr->mii, 1, Bmsr);
+ print("phy: cfg %8.8uX bmsr %4.4uX\n",
+ csr32r(ctlr, Cfg),
+ ctlr->mii->mir(ctlr->mii, 1, Bmsr));
+ dp83820cfg(ctlr);
+ isr &= ~Phy;
+ }
+ if(isr)
+ iprint("dp83820: isr %8.8uX\n", isr);
+ }
+}
+
+static long
+dp83820ifstat(Ether* edev, void* a, long n, ulong offset)
+{
+ char *p;
+ Ctlr *ctlr;
+ int i, l, r;
+
+ ctlr = edev->ctlr;
+
+ edev->crcs = ctlr->mibd[Mibd+(1*sizeof(int))];
+ edev->frames = ctlr->mibd[Mibd+(3*sizeof(int))];
+ edev->buffs = ctlr->mibd[Mibd+(5*sizeof(int))];
+ edev->overflows = ctlr->mibd[Mibd+(2*sizeof(int))];
+
+ if(n == 0)
+ return 0;
+
+ p = malloc(READSTR);
+ l = 0;
+ for(i = 0; i < Nmibd; i++){
+ r = csr32r(ctlr, Mibd+(i*sizeof(int)));
+ ctlr->mibd[i] += r & 0xFFFF;
+ if(ctlr->mibd[i] != 0 && dp83820mibs[i] != nil)
+ l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
+ dp83820mibs[i], ctlr->mibd[i], r);
+ }
+ l += snprint(p+l, READSTR-l, "rxidle %d\n", ctlr->rxidle);
+ l += snprint(p+l, READSTR-l, "ec %d\n", ctlr->ec);
+ l += snprint(p+l, READSTR-l, "owc %d\n", ctlr->owc);
+ l += snprint(p+l, READSTR-l, "ed %d\n", ctlr->ed);
+ l += snprint(p+l, READSTR-l, "crs %d\n", ctlr->crs);
+ l += snprint(p+l, READSTR-l, "tfu %d\n", ctlr->tfu);
+ l += snprint(p+l, READSTR-l, "txa %d\n", ctlr->txa);
+
+ l += snprint(p+l, READSTR, "rom:");
+ for(i = 0; i < 0x10; i++){
+ if(i && ((i & 0x07) == 0))
+ l += snprint(p+l, READSTR-l, "\n ");
+ l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
+ }
+ l += snprint(p+l, READSTR-l, "\n");
+
+ if(ctlr->mii != nil && ctlr->mii->curphy != nil){
+ l += snprint(p+l, READSTR, "phy:");
+ for(i = 0; i < NMiiPhyr; i++){
+ 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);
+ }
+ snprint(p+l, READSTR-l, "\n");
+ }
+
+ n = readstr(offset, a, n, p);
+ free(p);
+
+ return n;
+}
+
+static void
+dp83820promiscuous(void* arg, int on)
+{
+ USED(arg, on);
+}
+
+/* multicast already on, don't need to do anything */
+static void
+dp83820multicast(void*, uchar*, int)
+{
+}
+
+static int
+dp83820detach(Ctlr* ctlr)
+{
+ /*
+ * Soft reset the controller.
+ */
+ csr32w(ctlr, Cr, Rst);
+ delay(1);
+ while(csr32r(ctlr, Cr) & Rst)
+ delay(1);
+ return 0;
+}
+
+static void
+dp83820shutdown(Ether* ether)
+{
+print("dp83820shutdown\n");
+ dp83820detach(ether->ctlr);
+}
+
+static int
+atc93c46r(Ctlr* ctlr, int address)
+{
+ int data, i, mear, r, size;
+
+ /*
+ * Analog Technology, Inc. ATC93C46
+ * or equivalent serial EEPROM.
+ */
+ mear = csr32r(ctlr, Mear);
+ mear &= ~(Eesel|Eeclk|Eedo|Eedi);
+ r = Eesel|mear;
+
+reread:
+ csr32w(ctlr, Mear, r);
+ data = 0x06;
+ for(i = 3-1; i >= 0; i--){
+ if(data & (1<<i))
+ r |= Eedi;
+ else
+ r &= ~Eedi;
+ csr32w(ctlr, Mear, r);
+ csr32w(ctlr, Mear, Eeclk|r);
+ microdelay(1);
+ csr32w(ctlr, Mear, r);
+ microdelay(1);
+ }
+
+ /*
+ * First time through must work out the EEPROM size.
+ */
+ if((size = ctlr->eepromsz) == 0)
+ size = 8;
+
+ for(size = size-1; size >= 0; size--){
+ if(address & (1<<size))
+ r |= Eedi;
+ else
+ r &= ~Eedi;
+ csr32w(ctlr, Mear, r);
+ microdelay(1);
+ csr32w(ctlr, Mear, Eeclk|r);
+ microdelay(1);
+ csr32w(ctlr, Mear, r);
+ microdelay(1);
+ if(!(csr32r(ctlr, Mear) & Eedo))
+ break;
+ }
+ r &= ~Eedi;
+
+ data = 0;
+ for(i = 16-1; i >= 0; i--){
+ csr32w(ctlr, Mear, Eeclk|r);
+ microdelay(1);
+ if(csr32r(ctlr, Mear) & Eedo)
+ data |= (1<<i);
+ csr32w(ctlr, Mear, r);
+ microdelay(1);
+ }
+
+ csr32w(ctlr, Mear, mear);
+
+ if(ctlr->eepromsz == 0){
+ ctlr->eepromsz = 8-size;
+ ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
+ goto reread;
+ }
+
+ return data;
+}
+
+static int
+dp83820reset(Ctlr* ctlr)
+{
+ int i, r;
+ unsigned char sum;
+
+ /*
+ * Soft reset the controller;
+ * read the EEPROM to get the initial settings
+ * of the Cfg and Gpior bits which should be cleared by
+ * the reset.
+ */
+ dp83820detach(ctlr);
+
+ atc93c46r(ctlr, 0);
+ if(ctlr->eeprom == nil) {
+ print("dp83820reset: no eeprom\n");
+ return -1;
+ }
+ sum = 0;
+ for(i = 0; i < 0x0E; i++){
+ r = atc93c46r(ctlr, i);
+ ctlr->eeprom[i] = r;
+ sum += r;
+ sum += r>>8;
+ }
+
+ if(sum != 0){
+ print("dp83820reset: bad EEPROM checksum\n");
+ return -1;
+ }
+
+#ifdef notdef
+ csr32w(ctlr, Gpior, ctlr->eeprom[4]);
+
+ cfg = Extstsen|Exd;
+ r = csr32r(ctlr, Cfg);
+ if(ctlr->eeprom[5] & 0x0001)
+ cfg |= Ext125;
+ if(ctlr->eeprom[5] & 0x0002)
+ cfg |= M64addren;
+ if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
+ cfg |= Data64en;
+ if(ctlr->eeprom[5] & 0x0008)
+ cfg |= T64addren;
+ if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
+ cfg |= Mwidis;
+ if(ctlr->eeprom[5] & 0x0020)
+ cfg |= Mrmdis;
+ if(ctlr->eeprom[5] & 0x0080)
+ cfg |= Mode1000;
+ if(ctlr->eeprom[5] & 0x0200)
+ cfg |= Tbien|Mode1000;
+ /*
+ * What about RO bits we might have destroyed with Rst?
+ * What about Exd, Tmrtest, Extstsen, Pintctl?
+ * Why does it think it has detected a 64-bit bus when
+ * it hasn't?
+ */
+#else
+ // r = csr32r(ctlr, Cfg);
+ // r &= ~(Mode1000|T64addren|Data64en|M64addren);
+ // csr32w(ctlr, Cfg, r);
+ // csr32w(ctlr, Cfg, 0x2000);
+#endif /* notdef */
+ ctlr->cfg = csr32r(ctlr, Cfg);
+print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
+ ctlr->cfg &= ~(T64addren|Data64en|M64addren);
+ csr32w(ctlr, Cfg, ctlr->cfg);
+ csr32w(ctlr, Mibc, Aclr|Frz);
+
+ return 0;
+}
+
+static void
+dp83820pci(void)
+{
+ void *mem;
+ Pcidev *p;
+ Ctlr *ctlr;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
+ continue;
+
+ switch((p->did<<16)|p->vid){
+ default:
+ continue;
+ case (0x0022<<16)|0x100B: /* DP83820 (Gig-NIC) */
+ break;
+ }
+
+ 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 = p->mem[1].bar & ~0x0F;
+ ctlr->pcidev = p;
+ ctlr->id = (p->did<<16)|p->vid;
+
+ ctlr->nic = mem;
+ if(dp83820reset(ctlr)){
+ free(ctlr);
+ continue;
+ }
+ pcisetbme(p);
+
+ if(dp83820ctlrhead != nil)
+ dp83820ctlrtail->next = ctlr;
+ else
+ dp83820ctlrhead = ctlr;
+ dp83820ctlrtail = ctlr;
+ }
+}
+
+static int
+dp83820pnp(Ether* edev)
+{
+ int i;
+ Ctlr *ctlr;
+ uchar ea[Eaddrlen];
+
+ if(dp83820ctlrhead == nil)
+ dp83820pci();
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+ edev->mbps = 1000;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to
+ * loading the station address in the hardware.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, edev->ea, Eaddrlen) == 0)
+ for(i = 0; i < Eaddrlen/2; i++){
+ edev->ea[2*i] = ctlr->eeprom[0x0C-i];
+ edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
+ }
+
+ edev->attach = dp83820attach;
+ edev->transmit = dp83820transmit;
+ edev->interrupt = dp83820interrupt;
+ edev->ifstat = dp83820ifstat;
+
+ edev->arg = edev;
+ edev->promiscuous = dp83820promiscuous;
+ edev->multicast = dp83820multicast;
+ edev->shutdown = dp83820shutdown;
+
+ return 0;
+}
+
+void
+etherdp83820link(void)
+{
+ addethercard("DP83820", dp83820pnp);
+}
diff --git a/sys/src/9/pc/etherec2t.c b/sys/src/9/pc/etherec2t.c
new file mode 100755
index 000000000..4359e399b
--- /dev/null
+++ b/sys/src/9/pc/etherec2t.c
@@ -0,0 +1,175 @@
+/*
+ * Supposed NE2000 PCMCIA clones, see the comments in ether2000.c
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "ether8390.h"
+
+enum {
+ Data = 0x10, /* offset from I/O base of data port */
+ Reset = 0x1F, /* offset from I/O base of reset port */
+};
+
+typedef struct Ec2t {
+ char* name;
+ int iochecksum;
+} Ec2t;
+
+static Ec2t ec2tpcmcia[] = {
+ { "EC2T", 0, }, /* Linksys Combo PCMCIA EthernetCard */
+ { "PCMPC100", 1, }, /* EtherFast 10/100 PC Card */
+ { "PCM100", 1, }, /* EtherFast PCM100 Card */
+ { "EN2216", 0, }, /* Accton EtherPair-PCMCIA */
+ { "FA410TX", 1, }, /* Netgear FA410TX */
+ { "FA411", 0 }, /* Netgear FA411 PCMCIA */
+ { "Network Everywhere", 0, }, /* Linksys NP10T 10BaseT Card */
+ { "10/100 Port Attached", 1, }, /* SMC 8040TX */
+ { "8041TX-10/100-PC-Card-V2", 0 }, /* SMC 8041TX */
+ { "SMC8022", 0}, /* SMC 8022 / EZCard-10-PCMCIA */
+ { nil, 0, },
+};
+
+static int
+reset(Ether* ether)
+{
+ ushort buf[16];
+ ulong port;
+ Dp8390 *ctlr;
+ int i, slot;
+ uchar ea[Eaddrlen], sum, x;
+ Ec2t *ec2t, tmpec2t;
+
+ /*
+ * Set up the software configuration.
+ * Use defaults for port, irq, mem and size
+ * if not specified.
+ * The manual says 16KB memory, the box
+ * says 32KB. The manual seems to be correct.
+ */
+ if(ether->port == 0)
+ ether->port = 0x300;
+ if(ether->irq == 0)
+ ether->irq = 9;
+ if(ether->mem == 0)
+ ether->mem = 0x4000;
+ if(ether->size == 0)
+ ether->size = 16*1024;
+ port = ether->port;
+
+ if(ioalloc(ether->port, 0x20, 0, "ec2t") < 0)
+ return -1;
+ slot = -1;
+ for(ec2t = ec2tpcmcia; ec2t->name != nil; ec2t++){
+ if((slot = pcmspecial(ec2t->name, ether)) >= 0)
+ break;
+ }
+ if(ec2t->name == nil){
+ ec2t = &tmpec2t;
+ ec2t->name = nil;
+ ec2t->iochecksum = 0;
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrncmp(ether->opt[i], "id=", 3) == 0){
+ ec2t->name = &ether->opt[i][3];
+ slot = pcmspecial(ec2t->name, ether);
+ }
+ else if(cistrncmp(ether->opt[i], "iochecksum", 10) == 0)
+ ec2t->iochecksum = 1;
+ }
+ }
+ if(slot < 0){
+ iofree(port);
+ return -1;
+ }
+
+ ether->ctlr = malloc(sizeof(Dp8390));
+ ctlr = ether->ctlr;
+ ctlr->width = 2;
+ ctlr->ram = 0;
+
+ ctlr->port = port;
+ ctlr->data = port+Data;
+
+ ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz);
+ ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
+ ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz);
+
+ ctlr->dummyrr = 0;
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrcmp(ether->opt[i], "nodummyrr") == 0)
+ ctlr->dummyrr = 0;
+ else if(cistrncmp(ether->opt[i], "dummyrr=", 8) == 0)
+ ctlr->dummyrr = strtol(&ether->opt[i][8], nil, 0);
+ }
+
+ /*
+ * Reset the board. This is done by doing a read
+ * followed by a write to the Reset address.
+ */
+ buf[0] = inb(port+Reset);
+ delay(2);
+ outb(port+Reset, buf[0]);
+ delay(2);
+
+ /*
+ * Init the (possible) chip, then use the (possible)
+ * chip to read the (possible) PROM for ethernet address
+ * and a marker byte.
+ * Could just look at the DP8390 command register after
+ * initialisation has been tried, but that wouldn't be
+ * enough, there are other ethernet boards which could
+ * match.
+ */
+ dp8390reset(ether);
+ sum = 0;
+ if(ec2t->iochecksum){
+ /*
+ * These cards have the ethernet address in I/O space.
+ * There's a checksum over 8 bytes which sums to 0xFF.
+ */
+ for(i = 0; i < 8; i++){
+ x = inb(port+0x14+i);
+ sum += x;
+ buf[i] = (x<<8)|x;
+ }
+ }
+ else{
+ memset(buf, 0, sizeof(buf));
+ dp8390read(ctlr, buf, 0, sizeof(buf));
+ if((buf[0x0E] & 0xFF) == 0x57 && (buf[0x0F] & 0xFF) == 0x57)
+ sum = 0xFF;
+ }
+ if(sum != 0xFF){
+ pcmspecialclose(slot);
+ iofree(ether->port);
+ free(ether->ctlr);
+ return -1;
+ }
+
+ /*
+ * Stupid machine. Shorts were asked for,
+ * shorts were delivered, although the PROM is a byte array.
+ * Set the ethernet address.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+ for(i = 0; i < sizeof(ether->ea); i++)
+ ether->ea[i] = buf[i];
+ }
+ dp8390setea(ether);
+
+ return 0;
+}
+
+void
+etherec2tlink(void)
+{
+ addethercard("EC2T", reset);
+}
diff --git a/sys/src/9/pc/etherelnk3.c b/sys/src/9/pc/etherelnk3.c
new file mode 100755
index 000000000..9c612b136
--- /dev/null
+++ b/sys/src/9/pc/etherelnk3.c
@@ -0,0 +1,2134 @@
+/*
+ * Etherlink III, Fast EtherLink and Fast EtherLink XL adapters.
+ * To do:
+ * check robustness in the face of errors (e.g. busmaster & rxUnderrun);
+ * RxEarly and busmaster;
+ * autoSelect;
+ * PCI latency timer and master enable;
+ * errata list;
+ * rewrite all initialisation.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+#define XCVRDEBUG if(0)print
+
+enum {
+ IDport = 0x0110, /* anywhere between 0x0100 and 0x01F0 */
+};
+
+enum { /* all windows */
+ CommandR = 0x000E,
+ IntStatusR = 0x000E,
+};
+
+enum { /* Commands */
+ GlobalReset = 0x0000,
+ SelectRegisterWindow = 0x0001,
+ EnableDcConverter = 0x0002,
+ RxDisable = 0x0003,
+ RxEnable = 0x0004,
+ RxReset = 0x0005,
+ Stall = 0x0006, /* 3C90x */
+ TxDone = 0x0007,
+ RxDiscard = 0x0008,
+ TxEnable = 0x0009,
+ TxDisable = 0x000A,
+ TxReset = 0x000B,
+ RequestInterrupt = 0x000C,
+ AcknowledgeInterrupt = 0x000D,
+ SetInterruptEnable = 0x000E,
+ SetIndicationEnable = 0x000F, /* SetReadZeroMask */
+ SetRxFilter = 0x0010,
+ SetRxEarlyThresh = 0x0011,
+ SetTxAvailableThresh = 0x0012,
+ SetTxStartThresh = 0x0013,
+ StartDma = 0x0014, /* initiate busmaster operation */
+ StatisticsEnable = 0x0015,
+ StatisticsDisable = 0x0016,
+ DisableDcConverter = 0x0017,
+ SetTxReclaimThresh = 0x0018, /* PIO-only adapters */
+ PowerUp = 0x001B, /* not all adapters */
+ PowerDownFull = 0x001C, /* not all adapters */
+ PowerAuto = 0x001D, /* not all adapters */
+};
+
+enum { /* (Global|Rx|Tx)Reset command bits */
+ tpAuiReset = 0x0001, /* 10BaseT and AUI transceivers */
+ endecReset = 0x0002, /* internal Ethernet encoder/decoder */
+ networkReset = 0x0004, /* network interface logic */
+ fifoReset = 0x0008, /* FIFO control logic */
+ aismReset = 0x0010, /* autoinitialise state-machine logic */
+ hostReset = 0x0020, /* bus interface logic */
+ dmaReset = 0x0040, /* bus master logic */
+ vcoReset = 0x0080, /* on-board 10Mbps VCO */
+ updnReset = 0x0100, /* upload/download (Rx/TX) logic */
+
+ resetMask = 0x01FF,
+};
+
+enum { /* Stall command bits */
+ upStall = 0x0000,
+ upUnStall = 0x0001,
+ dnStall = 0x0002,
+ dnUnStall = 0x0003,
+};
+
+enum { /* SetRxFilter command bits */
+ receiveIndividual = 0x0001, /* match station address */
+ receiveMulticast = 0x0002,
+ receiveBroadcast = 0x0004,
+ receiveAllFrames = 0x0008, /* promiscuous */
+};
+
+enum { /* StartDma command bits */
+ Upload = 0x0000, /* transfer data from adapter to memory */
+ Download = 0x0001, /* transfer data from memory to adapter */
+};
+
+enum { /* IntStatus bits */
+ interruptLatch = 0x0001,
+ hostError = 0x0002, /* Adapter Failure */
+ txComplete = 0x0004,
+ txAvailable = 0x0008,
+ rxComplete = 0x0010,
+ rxEarly = 0x0020,
+ intRequested = 0x0040,
+ updateStats = 0x0080,
+ transferInt = 0x0100, /* Bus Master Transfer Complete */
+ dnComplete = 0x0200,
+ upComplete = 0x0400,
+ busMasterInProgress = 0x0800,
+ commandInProgress = 0x1000,
+
+ interruptMask = 0x07FE,
+};
+
+#define COMMAND(port, cmd, a) outs((port)+CommandR, ((cmd)<<11)|(a))
+#define STATUS(port) ins((port)+IntStatusR)
+
+enum { /* Window 0 - setup */
+ Wsetup = 0x0000,
+ /* registers */
+ ManufacturerID = 0x0000, /* 3C5[08]*, 3C59[27] */
+ ProductID = 0x0002, /* 3C5[08]*, 3C59[27] */
+ ConfigControl = 0x0004, /* 3C5[08]*, 3C59[27] */
+ AddressConfig = 0x0006, /* 3C5[08]*, 3C59[27] */
+ ResourceConfig = 0x0008, /* 3C5[08]*, 3C59[27] */
+ EepromCommand = 0x000A,
+ EepromData = 0x000C,
+ /* AddressConfig Bits */
+ autoSelect9 = 0x0080,
+ xcvrMask9 = 0xC000,
+ /* ConfigControl bits */
+ Ena = 0x0001,
+ base10TAvailable9 = 0x0200,
+ coaxAvailable9 = 0x1000,
+ auiAvailable9 = 0x2000,
+ /* EepromCommand bits */
+ EepromReadRegister = 0x0080,
+ EepromReadOffRegister = 0x00B0,
+ EepromRead8bRegister = 0x0230,
+ EepromBusy = 0x8000,
+};
+
+#define EEPROMCMD(port, cmd, a) outs((port)+EepromCommand, (cmd)|(a))
+#define EEPROMBUSY(port) (ins((port)+EepromCommand) & EepromBusy)
+#define EEPROMDATA(port) ins((port)+EepromData)
+
+enum { /* Window 1 - operating set */
+ Wop = 0x0001,
+ /* registers */
+ Fifo = 0x0000,
+ RxError = 0x0004, /* 3C59[0257] only */
+ RxStatus = 0x0008,
+ TIMER = 0x000A,
+ TxStatus = 0x000B,
+ TxFree = 0x000C,
+ /* RxError bits */
+ rxOverrun = 0x0001,
+ runtFrame = 0x0002,
+ alignmentError = 0x0004, /* Framing */
+ crcError = 0x0008,
+ oversizedFrame = 0x0010,
+ dribbleBits = 0x0080,
+ /* RxStatus bits */
+ rxBytes = 0x1FFF, /* 3C59[0257] mask */
+ rxBytes9 = 0x07FF, /* 3C5[078]9 mask */
+ rxError9 = 0x3800, /* 3C5[078]9 error mask */
+ rxOverrun9 = 0x0000,
+ oversizedFrame9 = 0x0800,
+ dribbleBits9 = 0x1000,
+ runtFrame9 = 0x1800,
+ alignmentError9 = 0x2000, /* Framing */
+ crcError9 = 0x2800,
+ rxError = 0x4000,
+ rxIncomplete = 0x8000,
+ /* TxStatus Bits */
+ txStatusOverflow = 0x0004,
+ maxCollisions = 0x0008,
+ txUnderrun = 0x0010,
+ txJabber = 0x0020,
+ interruptRequested = 0x0040,
+ txStatusComplete = 0x0080,
+};
+
+enum { /* Window 2 - station address */
+ Wstation = 0x0002,
+
+ ResetOp905B = 0x000C,
+};
+
+enum { /* Window 3 - FIFO management */
+ Wfifo = 0x0003,
+ /* registers */
+ InternalConfig = 0x0000, /* 3C509B, 3C589, 3C59[0257] */
+ OtherInt = 0x0004, /* 3C59[0257] */
+ RomControl = 0x0006, /* 3C509B, 3C59[27] */
+ MacControl = 0x0006, /* 3C59[0257] */
+ ResetOptions = 0x0008, /* 3C59[0257] */
+ MediaOptions = 0x0008, /* 3C905B */
+ RxFree = 0x000A,
+ /* InternalConfig bits */
+ disableBadSsdDetect = 0x00000100,
+ ramLocation = 0x00000200, /* 0 external, 1 internal */
+ ramPartition5to3 = 0x00000000,
+ ramPartition3to1 = 0x00010000,
+ ramPartition1to1 = 0x00020000,
+ ramPartition3to5 = 0x00030000,
+ ramPartitionMask = 0x00030000,
+ xcvr10BaseT = 0x00000000,
+ xcvrAui = 0x00100000, /* 10BASE5 */
+ xcvr10Base2 = 0x00300000,
+ xcvr100BaseTX = 0x00400000,
+ xcvr100BaseFX = 0x00500000,
+ xcvrMii = 0x00600000,
+ xcvrMask = 0x00700000,
+ autoSelect = 0x01000000,
+ /* MacControl bits */
+ deferExtendEnable = 0x0001,
+ deferTIMERSelect = 0x001E, /* mask */
+ fullDuplexEnable = 0x0020,
+ allowLargePackets = 0x0040,
+ extendAfterCollision = 0x0080, /* 3C90xB */
+ flowControlEnable = 0x0100, /* 3C90xB */
+ vltEnable = 0x0200, /* 3C90xB */
+ /* ResetOptions bits */
+ baseT4Available = 0x0001,
+ baseTXAvailable = 0x0002,
+ baseFXAvailable = 0x0004,
+ base10TAvailable = 0x0008,
+ coaxAvailable = 0x0010,
+ auiAvailable = 0x0020,
+ miiConnector = 0x0040,
+};
+
+enum { /* Window 4 - diagnostic */
+ Wdiagnostic = 0x0004,
+ /* registers */
+ VcoDiagnostic = 0x0002,
+ FifoDiagnostic = 0x0004,
+ NetworkDiagnostic = 0x0006,
+ PhysicalMgmt = 0x0008,
+ MediaStatus = 0x000A,
+ BadSSD = 0x000C,
+ UpperBytesOk = 0x000D,
+ /* FifoDiagnostic bits */
+ txOverrun = 0x0400,
+ rxUnderrun = 0x2000,
+ receiving = 0x8000,
+ /* PhysicalMgmt bits */
+ mgmtClk = 0x0001,
+ mgmtData = 0x0002,
+ mgmtDir = 0x0004,
+ cat5LinkTestDefeat = 0x8000,
+ /* MediaStatus bits */
+ dataRate100 = 0x0002,
+ crcStripDisable = 0x0004,
+ enableSqeStats = 0x0008,
+ collisionDetect = 0x0010,
+ carrierSense = 0x0020,
+ jabberGuardEnable = 0x0040,
+ linkBeatEnable = 0x0080,
+ jabberDetect = 0x0200,
+ polarityReversed = 0x0400,
+ linkBeatDetect = 0x0800,
+ txInProg = 0x1000,
+ dcConverterEnabled = 0x4000,
+ auiDisable = 0x8000, /* 10BaseT transceiver selected */
+};
+
+enum { /* Window 5 - internal state */
+ Wstate = 0x0005,
+ /* registers */
+ TxStartThresh = 0x0000,
+ TxAvailableThresh = 0x0002,
+ RxEarlyThresh = 0x0006,
+ RxFilter = 0x0008,
+ InterruptEnable = 0x000A,
+ IndicationEnable = 0x000C,
+};
+
+enum { /* Window 6 - statistics */
+ Wstatistics = 0x0006,
+ /* registers */
+ CarrierLost = 0x0000,
+ SqeErrors = 0x0001,
+ MultipleColls = 0x0002,
+ SingleCollFrames = 0x0003,
+ LateCollisions = 0x0004,
+ RxOverruns = 0x0005,
+ FramesXmittedOk = 0x0006,
+ FramesRcvdOk = 0x0007,
+ FramesDeferred = 0x0008,
+ UpperFramesOk = 0x0009,
+ BytesRcvdOk = 0x000A,
+ BytesXmittedOk = 0x000C,
+};
+
+enum { /* Window 7 - bus master operations */
+ Wmaster = 0x0007,
+ /* registers */
+ MasterAddress = 0x0000,
+ MasterLen = 0x0006,
+ MasterStatus = 0x000C,
+ /* MasterStatus bits */
+ masterAbort = 0x0001,
+ targetAbort = 0x0002,
+ targetRetry = 0x0004,
+ targetDisc = 0x0008,
+ masterDownload = 0x1000,
+ masterUpload = 0x4000,
+ masterInProgress = 0x8000,
+
+ masterMask = 0xD00F,
+};
+
+enum { /* 3C90x extended register set */
+ TIMER905 = 0x001A, /* 8-bits */
+ TxStatus905 = 0x001B, /* 8-bits */
+ PktStatus = 0x0020, /* 32-bits */
+ DnListPtr = 0x0024, /* 32-bits, 8-byte aligned */
+ FragAddr = 0x0028, /* 32-bits */
+ FragLen = 0x002C, /* 16-bits */
+ ListOffset = 0x002E, /* 8-bits */
+ TxFreeThresh = 0x002F, /* 8-bits */
+ UpPktStatus = 0x0030, /* 32-bits */
+ FreeTIMER = 0x0034, /* 16-bits */
+ UpListPtr = 0x0038, /* 32-bits, 8-byte aligned */
+
+ /* PktStatus bits */
+ fragLast = 0x00000001,
+ dnCmplReq = 0x00000002,
+ dnStalled = 0x00000004,
+ upCompleteX = 0x00000008,
+ dnCompleteX = 0x00000010,
+ upRxEarlyEnable = 0x00000020,
+ armCountdown = 0x00000040,
+ dnInProg = 0x00000080,
+ counterSpeed = 0x00000010, /* 0 3.2uS, 1 320nS */
+ countdownMode = 0x00000020,
+ /* UpPktStatus bits (dpd->control) */
+ upPktLenMask = 0x00001FFF,
+ upStalled = 0x00002000,
+ upError = 0x00004000,
+ upPktComplete = 0x00008000,
+ upOverrun = 0x00010000, /* RxError<<16 */
+ upRuntFrame = 0x00020000,
+ upAlignmentError = 0x00040000,
+ upCRCError = 0x00080000,
+ upOversizedFrame = 0x00100000,
+ upDribbleBits = 0x00800000,
+ upOverflow = 0x01000000,
+
+ dnIndicate = 0x80000000, /* FrameStartHeader (dpd->control) */
+
+ updnLastFrag = 0x80000000, /* (dpd->len) */
+
+ Nup = 32,
+ Ndn = 64,
+};
+
+/*
+ * Up/Dn Packet Descriptors.
+ * The hardware info (np, control, addr, len) must be 8-byte aligned
+ * and this structure size must be a multiple of 8.
+ */
+typedef struct Pd Pd;
+typedef struct Pd {
+ ulong np; /* next pointer */
+ ulong control; /* FSH or UpPktStatus */
+ ulong addr;
+ ulong len;
+
+ Pd* next;
+ Block* bp;
+} Pd;
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ int irq;
+ Ctlr* next;
+ int active;
+ int did;
+
+ Lock wlock; /* window access */
+
+ int attached;
+ int busmaster;
+ Block* rbp; /* receive buffer */
+
+ Block* txbp; /* FIFO -based transmission */
+ int txthreshold;
+ int txbusy;
+
+ int nup; /* full-busmaster -based reception */
+ void* upbase;
+ Pd* upr;
+ Pd* uphead;
+
+ int ndn; /* full-busmaster -based transmission */
+ void* dnbase;
+ Pd* dnr;
+ Pd* dnhead;
+ Pd* dntail;
+ int dnq;
+
+ long interrupts; /* statistics */
+ long bogusinterrupts;
+ long timer[2];
+ long stats[BytesRcvdOk+3];
+
+ int upqmax;
+ int upqmaxhw;
+ ulong upinterrupts;
+ ulong upqueued;
+ ulong upstalls;
+ int dnqmax;
+ int dnqmaxhw;
+ ulong dninterrupts;
+ ulong dnqueued;
+
+ int xcvr; /* transceiver type */
+ int eepromcmd; /* EEPROM read command */
+ int rxstatus9; /* old-style RxStatus register */
+ int rxearly; /* RxEarlyThreshold */
+ int ts; /* threshold shift */
+ int upenabled;
+ int dnenabled;
+ ulong cbfnpa; /* CardBus functions */
+ ulong* cbfn;
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+static void
+init905(Ctlr* ctlr)
+{
+ Block *bp;
+ Pd *pd, *prev;
+
+ /*
+ * Create rings for the receive and transmit sides.
+ * Take care with alignment:
+ * make sure ring base is 8-byte aligned;
+ * make sure each entry is 8-byte aligned.
+ */
+ ctlr->upbase = malloc((ctlr->nup+1)*sizeof(Pd));
+ ctlr->upr = (Pd*)ROUNDUP((ulong)ctlr->upbase, 8);
+
+ prev = ctlr->upr;
+ for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){
+ pd->np = PADDR(&prev->np);
+ pd->control = 0;
+ bp = iallocb(sizeof(Etherpkt));
+ if(bp == nil)
+ panic("can't allocate ethernet receive ring");
+ pd->addr = PADDR(bp->rp);
+ pd->len = updnLastFrag|sizeof(Etherpkt);
+
+ pd->next = prev;
+ prev = pd;
+ pd->bp = bp;
+ }
+ ctlr->uphead = ctlr->upr;
+
+ ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd));
+ ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8);
+
+ prev = ctlr->dnr;
+ for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){
+ pd->next = prev;
+ prev = pd;
+ }
+ ctlr->dnhead = ctlr->dnr;
+ ctlr->dntail = ctlr->dnr;
+ ctlr->dnq = 0;
+}
+
+static Block*
+rbpalloc(Block* (*f)(int))
+{
+ Block *bp;
+ ulong addr;
+
+ /*
+ * The receive buffers must be on a 32-byte
+ * boundary for EISA busmastering.
+ */
+ if(bp = f(ROUNDUP(sizeof(Etherpkt), 4) + 31)){
+ addr = (ulong)bp->base;
+ addr = ROUNDUP(addr, 32);
+ bp->rp = (uchar*)addr;
+ }
+
+ return bp;
+}
+
+static uchar*
+startdma(Ether* ether, ulong address)
+{
+ int port, status, w;
+ uchar *wp;
+
+ port = ether->port;
+
+ w = (STATUS(port)>>13) & 0x07;
+ COMMAND(port, SelectRegisterWindow, Wmaster);
+
+ wp = KADDR(inl(port+MasterAddress));
+ status = ins(port+MasterStatus);
+ if(status & (masterInProgress|targetAbort|masterAbort))
+ print("#l%d: BM status 0x%uX\n", ether->ctlrno, status);
+ outs(port+MasterStatus, masterMask);
+ outl(port+MasterAddress, address);
+ outs(port+MasterLen, sizeof(Etherpkt));
+ COMMAND(port, StartDma, Upload);
+
+ COMMAND(port, SelectRegisterWindow, w);
+ return wp;
+}
+
+static void
+promiscuous(void* arg, int on)
+{
+ int filter, port;
+ Ether *ether;
+
+ ether = (Ether*)arg;
+ port = ether->port;
+
+ filter = receiveBroadcast|receiveIndividual;
+ if(ether->nmaddr)
+ filter |= receiveMulticast;
+ if(on)
+ filter |= receiveAllFrames;
+ COMMAND(port, SetRxFilter, filter);
+}
+
+static void
+multicast(void* arg, uchar *addr, int on)
+{
+ int filter, port;
+ Ether *ether;
+
+ USED(addr, on);
+
+ ether = (Ether*)arg;
+ port = ether->port;
+
+ filter = receiveBroadcast|receiveIndividual;
+ if(ether->nmaddr)
+ filter |= receiveMulticast;
+ if(ether->prom)
+ filter |= receiveAllFrames;
+ COMMAND(port, SetRxFilter, filter);
+}
+
+/* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
+static void
+intrackcb(ulong *cbfn)
+{
+ cbfn[1] = 0x8000;
+}
+
+static void
+attach(Ether* ether)
+{
+ int port, x;
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(&ctlr->wlock);
+ if(ctlr->attached){
+ iunlock(&ctlr->wlock);
+ return;
+ }
+
+ port = ether->port;
+
+ /*
+ * Set the receiver packet filter for this and broadcast addresses,
+ * set the interrupt masks for all interrupts, enable the receiver
+ * and transmitter.
+ */
+ promiscuous(ether, ether->prom);
+
+ x = interruptMask;
+ if(ctlr->busmaster == 1)
+ x &= ~(rxEarly|rxComplete);
+ else{
+ if(ctlr->dnenabled)
+ x &= ~transferInt;
+ if(ctlr->upenabled)
+ x &= ~(rxEarly|rxComplete);
+ }
+ COMMAND(port, SetIndicationEnable, x);
+ COMMAND(port, SetInterruptEnable, x);
+ COMMAND(port, RxEnable, 0);
+ COMMAND(port, TxEnable, 0);
+
+ /*
+ * If this is a CardBus card, acknowledge any interrupts.
+ */
+ if(ctlr->cbfn != nil)
+ intrackcb(ctlr->cbfn);
+
+ /*
+ * Prime the busmaster channel for receiving directly into a
+ * receive packet buffer if necessary.
+ */
+ if(ctlr->busmaster == 1)
+ startdma(ether, PADDR(ctlr->rbp->rp));
+ else{
+ if(ctlr->upenabled)
+ outl(port+UpListPtr, PADDR(&ctlr->uphead->np));
+ }
+
+ ctlr->attached = 1;
+ iunlock(&ctlr->wlock);
+}
+
+static void
+statistics(Ether* ether)
+{
+ int port, i, u, w;
+ Ctlr *ctlr;
+
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ /*
+ * 3C59[27] require a read between a PIO write and
+ * reading a statistics register.
+ */
+ w = (STATUS(port)>>13) & 0x07;
+ COMMAND(port, SelectRegisterWindow, Wstatistics);
+ STATUS(port);
+
+ for(i = 0; i < UpperFramesOk; i++)
+ ctlr->stats[i] += inb(port+i) & 0xFF;
+ u = inb(port+UpperFramesOk) & 0xFF;
+ ctlr->stats[FramesXmittedOk] += (u & 0x30)<<4;
+ ctlr->stats[FramesRcvdOk] += (u & 0x03)<<8;
+ ctlr->stats[BytesRcvdOk] += ins(port+BytesRcvdOk) & 0xFFFF;
+ ctlr->stats[BytesRcvdOk+1] += ins(port+BytesXmittedOk) & 0xFFFF;
+
+ switch(ctlr->xcvr){
+
+ case xcvrMii:
+ case xcvr100BaseTX:
+ case xcvr100BaseFX:
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ STATUS(port);
+ ctlr->stats[BytesRcvdOk+2] += inb(port+BadSSD);
+ break;
+ }
+
+ COMMAND(port, SelectRegisterWindow, w);
+}
+
+static void
+txstart(Ether* ether)
+{
+ int port, len;
+ Ctlr *ctlr;
+ Block *bp;
+
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ /*
+ * Attempt to top-up the transmit FIFO. If there's room simply
+ * stuff in the packet length (unpadded to a dword boundary), the
+ * packet data (padded) and remove the packet from the queue.
+ * If there's no room post an interrupt for when there is.
+ * This routine is called both from the top level and from interrupt
+ * level and expects to be called with ctlr->wlock already locked
+ * and the correct register window (Wop) in place.
+ */
+ for(;;){
+ if(ctlr->txbp){
+ bp = ctlr->txbp;
+ ctlr->txbp = 0;
+ }
+ else{
+ bp = qget(ether->oq);
+ if(bp == nil)
+ break;
+ }
+
+ len = ROUNDUP(BLEN(bp), 4);
+ if(len+4 <= ins(port+TxFree)){
+ outl(port+Fifo, BLEN(bp));
+ outsl(port+Fifo, bp->rp, len/4);
+
+ freeb(bp);
+
+ ether->outpackets++;
+ }
+ else{
+ ctlr->txbp = bp;
+ if(ctlr->txbusy == 0){
+ ctlr->txbusy = 1;
+ COMMAND(port, SetTxAvailableThresh, len>>ctlr->ts);
+ }
+ break;
+ }
+ }
+}
+
+static void
+txstart905(Ether* ether)
+{
+ Ctlr *ctlr;
+ int port, stalled, timeo;
+ Block *bp;
+ Pd *pd;
+
+ ctlr = ether->ctlr;
+ port = ether->port;
+
+ /*
+ * Free any completed packets.
+ */
+ pd = ctlr->dntail;
+ while(ctlr->dnq){
+ if(PADDR(&pd->np) == inl(port+DnListPtr))
+ break;
+ if(pd->bp){
+ freeb(pd->bp);
+ pd->bp = nil;
+ }
+ ctlr->dnq--;
+ pd = pd->next;
+ }
+ ctlr->dntail = pd;
+
+ stalled = 0;
+ while(ctlr->dnq < (ctlr->ndn-1)){
+ bp = qget(ether->oq);
+ if(bp == nil)
+ break;
+
+ pd = ctlr->dnhead->next;
+ pd->np = 0;
+ pd->control = dnIndicate|BLEN(bp);
+ pd->addr = PADDR(bp->rp);
+ pd->len = updnLastFrag|BLEN(bp);
+ pd->bp = bp;
+
+ if(stalled == 0 && ctlr->dnq && inl(port+DnListPtr)){
+ COMMAND(port, Stall, dnStall);
+ for(timeo = 100; (STATUS(port) & commandInProgress) && timeo; timeo--)
+ ;
+ if(timeo == 0)
+ print("#l%d: dnstall %d\n", ether->ctlrno, timeo);
+ stalled = 1;
+ }
+
+ coherence();
+ ctlr->dnhead->np = PADDR(&pd->np);
+ ctlr->dnhead->control &= ~dnIndicate;
+ ctlr->dnhead = pd;
+ if(ctlr->dnq == 0)
+ ctlr->dntail = pd;
+ ctlr->dnq++;
+
+ ctlr->dnqueued++;
+ }
+
+ if(ctlr->dnq > ctlr->dnqmax)
+ ctlr->dnqmax = ctlr->dnq;
+
+ /*
+ * If the adapter is not currently processing anything
+ * and there is something on the queue, start it processing.
+ */
+ if(inl(port+DnListPtr) == 0 && ctlr->dnq)
+ outl(port+DnListPtr, PADDR(&ctlr->dnhead->np));
+ if(stalled)
+ COMMAND(port, Stall, dnUnStall);
+}
+
+static void
+transmit(Ether* ether)
+{
+ Ctlr *ctlr;
+ int port, w;
+
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ ilock(&ctlr->wlock);
+ if(ctlr->dnenabled)
+ txstart905(ether);
+ else{
+ w = (STATUS(port)>>13) & 0x07;
+ COMMAND(port, SelectRegisterWindow, Wop);
+ txstart(ether);
+ COMMAND(port, SelectRegisterWindow, w);
+ }
+ iunlock(&ctlr->wlock);
+}
+
+static void
+receive905(Ether* ether)
+{
+ Ctlr *ctlr;
+ int len, port, q;
+ Pd *pd;
+ Block *bp;
+
+ ctlr = ether->ctlr;
+ port = ether->port;
+
+ if(inl(port+UpPktStatus) & upStalled)
+ ctlr->upstalls++;
+ q = 0;
+ for(pd = ctlr->uphead; pd->control & upPktComplete; pd = pd->next){
+ if(pd->control & upError){
+ if(pd->control & upOverrun)
+ ether->overflows++;
+ if(pd->control & (upOversizedFrame|upRuntFrame))
+ ether->buffs++;
+ if(pd->control & upAlignmentError)
+ ether->frames++;
+ if(pd->control & upCRCError)
+ ether->crcs++;
+ }
+ else if(bp = iallocb(sizeof(Etherpkt)+4)){
+ len = pd->control & rxBytes;
+ pd->bp->wp = pd->bp->rp+len;
+ etheriq(ether, pd->bp, 1);
+ pd->bp = bp;
+ pd->addr = PADDR(bp->rp);
+ coherence();
+ }
+
+ pd->control = 0;
+ COMMAND(port, Stall, upUnStall);
+
+ q++;
+ }
+ ctlr->uphead = pd;
+
+ ctlr->upqueued += q;
+ if(q > ctlr->upqmax)
+ ctlr->upqmax = q;
+}
+
+static void
+receive(Ether* ether)
+{
+ int len, port, rxerror, rxstatus;
+ Ctlr *ctlr;
+ Block *bp;
+
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
+ if(ctlr->busmaster == 1 && (STATUS(port) & busMasterInProgress))
+ break;
+
+ /*
+ * If there was an error, log it and continue.
+ * Unfortunately the 3C5[078]9 has the error info in the status register
+ * and the 3C59[0257] implement a separate RxError register.
+ */
+ if(rxstatus & rxError){
+ if(ctlr->rxstatus9){
+ switch(rxstatus & rxError9){
+
+ case rxOverrun9:
+ ether->overflows++;
+ break;
+
+ case oversizedFrame9:
+ case runtFrame9:
+ ether->buffs++;
+ break;
+
+ case alignmentError9:
+ ether->frames++;
+ break;
+
+ case crcError9:
+ ether->crcs++;
+ break;
+
+ }
+ }
+ else{
+ rxerror = inb(port+RxError);
+ if(rxerror & rxOverrun)
+ ether->overflows++;
+ if(rxerror & (oversizedFrame|runtFrame))
+ ether->buffs++;
+ if(rxerror & alignmentError)
+ ether->frames++;
+ if(rxerror & crcError)
+ ether->crcs++;
+ }
+ }
+
+ /*
+ * If there was an error or a new receive buffer can't be
+ * allocated, discard the packet and go on to the next.
+ */
+ if((rxstatus & rxError) || (bp = rbpalloc(iallocb)) == 0){
+ COMMAND(port, RxDiscard, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+
+ if(ctlr->busmaster == 1)
+ startdma(ether, PADDR(ctlr->rbp->rp));
+
+ continue;
+ }
+
+ /*
+ * A valid receive packet awaits:
+ * if using PIO, read it into the buffer;
+ * discard the packet from the FIFO;
+ * if using busmastering, start a new transfer for
+ * the next packet and as a side-effect get the
+ * end-pointer of the one just received;
+ * pass the packet on to whoever wants it.
+ */
+ if(ctlr->busmaster == 0 || ctlr->busmaster == 2){
+ len = (rxstatus & rxBytes9);
+ ctlr->rbp->wp = ctlr->rbp->rp + len;
+ insl(port+Fifo, ctlr->rbp->rp, HOWMANY(len, 4));
+ }
+
+ COMMAND(port, RxDiscard, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+
+ if(ctlr->busmaster == 1)
+ ctlr->rbp->wp = startdma(ether, PADDR(bp->rp));
+
+ etheriq(ether, ctlr->rbp, 1);
+ ctlr->rbp = bp;
+ }
+}
+
+static int
+ejectable(int did)
+{
+ switch (did) {
+ case 0x5157:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ Ether *ether;
+ int port, status, s, txstatus, w, x;
+ Ctlr *ctlr;
+
+ ether = arg;
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ ilock(&ctlr->wlock);
+ status = STATUS(port);
+ if(!(status & (interruptMask|interruptLatch))){
+ ctlr->bogusinterrupts++;
+ iunlock(&ctlr->wlock);
+ return;
+ }
+ w = (status>>13) & 0x07;
+ COMMAND(port, SelectRegisterWindow, Wop);
+
+ ctlr->interrupts++;
+ if(ctlr->busmaster == 2)
+ ctlr->timer[0] += inb(port+TIMER905) & 0xFF;
+ else
+ ctlr->timer[0] += inb(port+TIMER) & 0xFF;
+
+ do{
+ if(status & hostError){
+ /*
+ * Adapter failure, try to find out why, reset if
+ * necessary. What happens if Tx is active and a reset
+ * occurs, need to retransmit? This probably isn't right.
+ */
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+FifoDiagnostic);
+ COMMAND(port, SelectRegisterWindow, Wop);
+
+ if (status == 0xFFFF && x == 0xFFFF && ejectable(ctlr->did)) {
+ print("#l%d: Card ejected?\n", ether->ctlrno);
+ iunlock(&ctlr->wlock);
+ return;
+ }
+
+ print("#l%d: status 0x%uX, diag 0x%uX\n",
+ ether->ctlrno, status, x);
+
+ if(x & txOverrun){
+ if(ctlr->busmaster == 0)
+ COMMAND(port, TxReset, 0);
+ else
+ COMMAND(port, TxReset, (updnReset|dmaReset));
+ COMMAND(port, TxEnable, 0);
+ }
+
+ if(x & rxUnderrun){
+ /*
+ * This shouldn't happen...
+ * Reset the receiver and restore the filter and RxEarly
+ * threshold before re-enabling.
+ * Need to restart any busmastering?
+ */
+ COMMAND(port, SelectRegisterWindow, Wstate);
+ s = (port+RxFilter) & 0x000F;
+ COMMAND(port, SelectRegisterWindow, Wop);
+ COMMAND(port, RxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, SetRxFilter, s);
+ COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
+ COMMAND(port, RxEnable, 0);
+ }
+
+ status &= ~hostError;
+ }
+
+ if(status & (transferInt|rxComplete)){
+ receive(ether);
+ status &= ~(transferInt|rxComplete);
+ }
+
+ if(status & (upComplete)){
+ COMMAND(port, AcknowledgeInterrupt, upComplete);
+ receive905(ether);
+ status &= ~upComplete;
+ ctlr->upinterrupts++;
+ }
+
+ if(status & txComplete){
+ /*
+ * Pop the TxStatus stack, accumulating errors.
+ * Adjust the TX start threshold if there was an underrun.
+ * If there was a Jabber or Underrun error, reset
+ * the transmitter, taking care not to reset the dma logic
+ * as a busmaster receive may be in progress.
+ * For all conditions enable the transmitter.
+ */
+ if(ctlr->busmaster == 2)
+ txstatus = port+TxStatus905;
+ else
+ txstatus = port+TxStatus;
+ s = 0;
+ do{
+ if(x = inb(txstatus))
+ outb(txstatus, 0);
+ s |= x;
+ }while(STATUS(port) & txComplete);
+
+ if(s & txUnderrun){
+ if(ctlr->dnenabled){
+ while(inl(port+PktStatus) & dnInProg)
+ ;
+ }
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ while(ins(port+MediaStatus) & txInProg)
+ ;
+ COMMAND(port, SelectRegisterWindow, Wop);
+ if(ctlr->txthreshold < ETHERMAXTU)
+ ctlr->txthreshold += ETHERMINTU;
+ }
+
+ /*
+ * According to the manual, maxCollisions does not require
+ * a TxReset, merely a TxEnable. However, evidence points to
+ * it being necessary on the 3C905. The jury is still out.
+ * On busy or badly configured networks maxCollisions can
+ * happen frequently enough for messages to be annoying so
+ * keep quiet about them by popular request.
+ */
+ if(s & (txJabber|txUnderrun|maxCollisions)){
+ if(ctlr->busmaster == 0)
+ COMMAND(port, TxReset, 0);
+ else
+ COMMAND(port, TxReset, (updnReset|dmaReset));
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
+ if(ctlr->busmaster == 2)
+ outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
+ if(ctlr->dnenabled)
+ status |= dnComplete;
+ }
+
+ if(s & ~(txStatusComplete|maxCollisions))
+ print("#l%d: txstatus 0x%uX, threshold %d\n",
+ ether->ctlrno, s, ctlr->txthreshold);
+ COMMAND(port, TxEnable, 0);
+ ether->oerrs++;
+ status &= ~txComplete;
+ status |= txAvailable;
+ }
+
+ if(status & txAvailable){
+ COMMAND(port, AcknowledgeInterrupt, txAvailable);
+ ctlr->txbusy = 0;
+ txstart(ether);
+ status &= ~txAvailable;
+ }
+
+ if(status & dnComplete){
+ COMMAND(port, AcknowledgeInterrupt, dnComplete);
+ txstart905(ether);
+ status &= ~dnComplete;
+ ctlr->dninterrupts++;
+ }
+
+ if(status & updateStats){
+ statistics(ether);
+ status &= ~updateStats;
+ }
+
+ /*
+ * Currently, this shouldn't happen.
+ */
+ if(status & rxEarly){
+ COMMAND(port, AcknowledgeInterrupt, rxEarly);
+ status &= ~rxEarly;
+ }
+
+ /*
+ * Panic if there are any interrupts not dealt with.
+ */
+ if(status & interruptMask)
+ panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
+
+ COMMAND(port, AcknowledgeInterrupt, interruptLatch);
+ if(ctlr->cbfn != nil)
+ intrackcb(ctlr->cbfn);
+
+ }while((status = STATUS(port)) & (interruptMask|interruptLatch));
+
+ if(ctlr->busmaster == 2)
+ ctlr->timer[1] += inb(port+TIMER905) & 0xFF;
+ else
+ ctlr->timer[1] += inb(port+TIMER) & 0xFF;
+
+ COMMAND(port, SelectRegisterWindow, w);
+ iunlock(&ctlr->wlock);
+}
+
+static long
+ifstat(Ether* ether, void* a, long n, ulong offset)
+{
+ char *p;
+ int len;
+ Ctlr *ctlr;
+
+ if(n == 0)
+ return 0;
+
+ ctlr = ether->ctlr;
+
+ ilock(&ctlr->wlock);
+ statistics(ether);
+ iunlock(&ctlr->wlock);
+
+ p = malloc(READSTR);
+ len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts);
+ len += snprint(p+len, READSTR-len, "bogusinterrupts: %lud\n", ctlr->bogusinterrupts);
+ len += snprint(p+len, READSTR-len, "timer: %lud %lud\n",
+ ctlr->timer[0], ctlr->timer[1]);
+ len += snprint(p+len, READSTR-len, "carrierlost: %lud\n",
+ ctlr->stats[CarrierLost]);
+ len += snprint(p+len, READSTR-len, "sqeerrors: %lud\n",
+ ctlr->stats[SqeErrors]);
+ len += snprint(p+len, READSTR-len, "multiplecolls: %lud\n",
+ ctlr->stats[MultipleColls]);
+ len += snprint(p+len, READSTR-len, "singlecollframes: %lud\n",
+ ctlr->stats[SingleCollFrames]);
+ len += snprint(p+len, READSTR-len, "latecollisions: %lud\n",
+ ctlr->stats[LateCollisions]);
+ len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n",
+ ctlr->stats[RxOverruns]);
+ len += snprint(p+len, READSTR-len, "framesxmittedok: %lud\n",
+ ctlr->stats[FramesXmittedOk]);
+ len += snprint(p+len, READSTR-len, "framesrcvdok: %lud\n",
+ ctlr->stats[FramesRcvdOk]);
+ len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n",
+ ctlr->stats[FramesDeferred]);
+ len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n",
+ ctlr->stats[BytesRcvdOk]);
+ len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n",
+ ctlr->stats[BytesRcvdOk+1]);
+
+ if(ctlr->upenabled){
+ if(ctlr->upqmax > ctlr->upqmaxhw)
+ ctlr->upqmaxhw = ctlr->upqmax;
+ len += snprint(p+len, READSTR-len, "up: q %lud i %lud m %d h %d s %lud\n",
+ ctlr->upqueued, ctlr->upinterrupts,
+ ctlr->upqmax, ctlr->upqmaxhw, ctlr->upstalls);
+ ctlr->upqmax = 0;
+ }
+ if(ctlr->dnenabled){
+ if(ctlr->dnqmax > ctlr->dnqmaxhw)
+ ctlr->dnqmaxhw = ctlr->dnqmax;
+ len += snprint(p+len, READSTR-len, "dn: q %lud i %lud m %d h %d\n",
+ ctlr->dnqueued, ctlr->dninterrupts, ctlr->dnqmax, ctlr->dnqmaxhw);
+ ctlr->dnqmax = 0;
+ }
+
+ snprint(p+len, READSTR-len, "badssd: %lud\n", ctlr->stats[BytesRcvdOk+2]);
+
+ n = readstr(offset, a, n, p);
+ free(p);
+
+ return n;
+}
+
+static void
+txrxreset(int port)
+{
+ COMMAND(port, TxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, RxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+}
+
+static Ctlr*
+tcmadapter(int port, int irq, Pcidev* pcidev)
+{
+ Ctlr *ctlr;
+
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = port;
+ ctlr->irq = irq;
+ ctlr->pcidev = pcidev;
+ ctlr->eepromcmd = EepromReadRegister;
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+
+ return ctlr;
+}
+
+/*
+ * Write two 0 bytes to identify the IDport and then reset the
+ * ID sequence. Then send the ID sequence to the card to get
+ * the card into command state.
+ */
+static void
+idseq(void)
+{
+ int i;
+ uchar al;
+ static int reset, untag;
+
+ /*
+ * One time only:
+ * reset any adapters listening
+ */
+ if(reset == 0){
+ outb(IDport, 0);
+ outb(IDport, 0);
+ outb(IDport, 0xC0);
+ delay(20);
+ reset = 1;
+ }
+
+ outb(IDport, 0);
+ outb(IDport, 0);
+ for(al = 0xFF, i = 0; i < 255; i++){
+ outb(IDport, al);
+ if(al & 0x80){
+ al <<= 1;
+ al ^= 0xCF;
+ }
+ else
+ al <<= 1;
+ }
+
+ /*
+ * One time only:
+ * write ID sequence to get the attention of all adapters;
+ * untag all adapters.
+ * If a global reset is done here on all adapters it will confuse
+ * any ISA cards configured for EISA mode.
+ */
+ if(untag == 0){
+ outb(IDport, 0xD0);
+ untag = 1;
+ }
+}
+
+static ulong
+activate(void)
+{
+ int i;
+ ushort x, acr;
+
+ /*
+ * Do the little configuration dance:
+ *
+ * 2. write the ID sequence to get to command state.
+ */
+ idseq();
+
+ /*
+ * 3. Read the Manufacturer ID from the EEPROM.
+ * This is done by writing the IDPort with 0x87 (0x80
+ * is the 'read EEPROM' command, 0x07 is the offset of
+ * the Manufacturer ID field in the EEPROM).
+ * The data comes back 1 bit at a time.
+ * A delay seems necessary between reading the bits.
+ *
+ * If the ID doesn't match, there are no more adapters.
+ */
+ outb(IDport, 0x87);
+ delay(20);
+ for(x = 0, i = 0; i < 16; i++){
+ delay(20);
+ x <<= 1;
+ x |= inb(IDport) & 0x01;
+ }
+ if(x != 0x6D50)
+ return 0;
+
+ /*
+ * 3. Read the Address Configuration from the EEPROM.
+ * The Address Configuration field is at offset 0x08 in the EEPROM).
+ */
+ outb(IDport, 0x88);
+ for(acr = 0, i = 0; i < 16; i++){
+ delay(20);
+ acr <<= 1;
+ acr |= inb(IDport) & 0x01;
+ }
+
+ return (acr & 0x1F)*0x10 + 0x200;
+}
+
+static void
+tcm509isa(void)
+{
+ int irq, port;
+
+ /*
+ * Attempt to activate all adapters. If adapter is set for
+ * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
+ * it fully.
+ */
+ while(port = activate()){
+ if(ioalloc(port, 0x10, 0, "tcm509isa") < 0){
+ print("tcm509isa: port 0x%uX in use\n", port);
+ continue;
+ }
+
+ /*
+ * 6. Tag the adapter so it won't respond in future.
+ */
+ outb(IDport, 0xD1);
+ if(port == 0x3F0){
+ iofree(port);
+ continue;
+ }
+
+ /*
+ * 6. Activate the adapter by writing the Activate command
+ * (0xFF).
+ */
+ outb(IDport, 0xFF);
+ delay(20);
+
+ /*
+ * 8. Can now talk to the adapter's I/O base addresses.
+ * Use the I/O base address from the acr just read.
+ *
+ * Enable the adapter and clear out any lingering status
+ * and interrupts.
+ */
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ outs(port+ConfigControl, Ena);
+
+ txrxreset(port);
+ COMMAND(port, AcknowledgeInterrupt, 0xFF);
+
+ irq = (ins(port+ResourceConfig)>>12) & 0x0F;
+ tcmadapter(port, irq, nil);
+ }
+}
+
+static void
+tcm5XXeisa(void)
+{
+ ushort x;
+ int irq, port, slot;
+
+ /*
+ * Check if this is an EISA machine.
+ * If not, nothing to do.
+ */
+ if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4))
+ return;
+
+ /*
+ * Continue through the EISA slots looking for a match on both
+ * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
+ * If an adapter is found, select window 0, enable it and clear
+ * out any lingering status and interrupts.
+ */
+ for(slot = 1; slot < MaxEISA; slot++){
+ port = slot*0x1000;
+ if(ioalloc(port, 0x1000, 0, "tcm5XXeisa") < 0){
+ print("tcm5XXeisa: port 0x%uX in use\n", port);
+ continue;
+ }
+ if(ins(port+0xC80+ManufacturerID) != 0x6D50){
+ iofree(port);
+ continue;
+ }
+ x = ins(port+0xC80+ProductID);
+ if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900){
+ iofree(port);
+ continue;
+ }
+
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ outs(port+ConfigControl, Ena);
+
+ txrxreset(port);
+ COMMAND(port, AcknowledgeInterrupt, 0xFF);
+
+ irq = (ins(port+ResourceConfig)>>12) & 0x0F;
+ tcmadapter(port, irq, nil);
+ }
+}
+
+static void
+tcm59Xpci(void)
+{
+ Pcidev *p;
+ Ctlr *ctlr;
+ int irq, port;
+
+ p = nil;
+ while(p = pcimatch(p, 0x10B7, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+ /*
+ * Not prepared to deal with memory-mapped
+ * devices yet.
+ */
+ if(!(p->mem[0].bar & 0x01))
+ continue;
+ port = p->mem[0].bar & ~0x01;
+ if((port = ioalloc((port == 0)? -1: port, p->mem[0].size,
+ 0, "tcm59Xpci")) < 0){
+ print("tcm59Xpci: port 0x%uX in use\n", port);
+ continue;
+ }
+ irq = p->intl;
+
+ txrxreset(port);
+ COMMAND(port, AcknowledgeInterrupt, 0xFF);
+
+ ctlr = tcmadapter(port, irq, p);
+ switch(p->did){
+ default:
+ break;
+ case 0x5157:
+ ctlr->eepromcmd = EepromRead8bRegister;
+ 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 = p->mem[2].bar&~0x0F;
+ ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
+ break;
+ }
+ pcisetbme(p);
+ }
+}
+
+static char* tcmpcmcia[] = {
+ "3C589", /* 3COM 589[ABCD] */
+ "3C562", /* 3COM 562 */
+ "589E", /* 3COM Megahertz 589E */
+ nil,
+};
+
+static Ctlr*
+tcm5XXpcmcia(Ether* ether)
+{
+ int i;
+ Ctlr *ctlr;
+
+ if(ether->type == nil)
+ return nil;
+
+ for(i = 0; tcmpcmcia[i] != nil; i++){
+ if(cistrcmp(ether->type, tcmpcmcia[i]))
+ continue;
+ ctlr = tcmadapter(ether->port, ether->irq, nil);
+ ctlr->active = 1;
+ return ctlr;
+ }
+
+ return nil;
+}
+
+static void
+setxcvr(Ctlr* ctlr, int xcvr)
+{
+ int port, x;
+
+ port = ctlr->port;
+ if(ctlr->rxstatus9){
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ x = ins(port+AddressConfig) & ~xcvrMask9;
+ x |= (xcvr>>20)<<14;
+ outs(port+AddressConfig, x);
+ }
+ else{
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ x = inl(port+InternalConfig) & ~xcvrMask;
+ x |= xcvr;
+ outl(port+InternalConfig, x);
+ }
+
+ txrxreset(port);
+}
+
+static void
+setfullduplex(int port)
+{
+ int x;
+
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ x = ins(port+MacControl);
+ outs(port+MacControl, fullDuplexEnable|x);
+
+ txrxreset(port);
+}
+
+static int
+miimdi(int port, int n)
+{
+ int data, i;
+
+ /*
+ * Read n bits from the MII Management Register.
+ */
+ data = 0;
+ for(i = n-1; i >= 0; i--){
+ if(ins(port) & mgmtData)
+ data |= (1<<i);
+ microdelay(1);
+ outs(port, mgmtClk);
+ microdelay(1);
+ outs(port, 0);
+ microdelay(1);
+ }
+
+ return data;
+}
+
+static void
+miimdo(int port, int bits, int n)
+{
+ int i, mdo;
+
+ /*
+ * Write n bits to the MII Management Register.
+ */
+ for(i = n-1; i >= 0; i--){
+ if(bits & (1<<i))
+ mdo = mgmtDir|mgmtData;
+ else
+ mdo = mgmtDir;
+ outs(port, mdo);
+ microdelay(1);
+ outs(port, mdo|mgmtClk);
+ microdelay(1);
+ outs(port, mdo);
+ microdelay(1);
+ }
+}
+
+static int
+miir(int port, int phyad, int regad)
+{
+ int data, w;
+
+ w = (STATUS(port)>>13) & 0x07;
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ port += PhysicalMgmt;
+
+ /*
+ * Preamble;
+ * ST+OP+PHYAD+REGAD;
+ * TA + 16 data bits.
+ */
+ miimdo(port, 0xFFFFFFFF, 32);
+ miimdo(port, 0x1800|(phyad<<5)|regad, 14);
+ data = miimdi(port, 18);
+
+ port -= PhysicalMgmt;
+ COMMAND(port, SelectRegisterWindow, w);
+
+ if(data & 0x10000)
+ return -1;
+
+ return data & 0xFFFF;
+}
+
+static int
+scanphy(int port)
+{
+ int i, x;
+
+ for(i = 0; i < 32; i++){
+ if((x = miir(port, i, 2)) == -1 || x == 0)
+ continue;
+ x <<= 6;
+ x |= miir(port, i, 3)>>10;
+ XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
+ USED(x);
+
+ return i;
+ }
+ return 24;
+}
+
+static struct {
+ char *name;
+ int avail;
+ int xcvr;
+} media[] = {
+ "10BaseT", base10TAvailable, xcvr10BaseT,
+ "10Base2", coaxAvailable, xcvr10Base2,
+ "100BaseTX", baseTXAvailable, xcvr100BaseTX,
+ "100BaseFX", baseFXAvailable, xcvr100BaseFX,
+ "aui", auiAvailable, xcvrAui,
+ "mii", miiConnector, xcvrMii
+};
+
+static int
+autoselect(Ctlr* ctlr)
+{
+ int media, port, x;
+
+ /*
+ * Pathetic attempt at automatic media selection.
+ * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
+ * cards operational.
+ * It's a bonus if it works for anything else.
+ */
+ port = ctlr->port;
+ if(ctlr->rxstatus9){
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ x = ins(port+ConfigControl);
+ media = 0;
+ if(x & base10TAvailable9)
+ media |= base10TAvailable;
+ if(x & coaxAvailable9)
+ media |= coaxAvailable;
+ if(x & auiAvailable9)
+ media |= auiAvailable;
+ }
+ else{
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ media = ins(port+ResetOptions);
+ }
+ XCVRDEBUG("autoselect: media %uX\n", media);
+
+ if(media & miiConnector)
+ return xcvrMii;
+
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ XCVRDEBUG("autoselect: media status %uX\n", ins(port+MediaStatus));
+
+ if(media & baseTXAvailable){
+ /*
+ * Must have InternalConfig register.
+ */
+ setxcvr(ctlr, xcvr100BaseTX);
+
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
+ outs(port+MediaStatus, linkBeatEnable|x);
+ delay(10);
+
+ if(ins(port+MediaStatus) & linkBeatDetect)
+ return xcvr100BaseTX;
+ outs(port+MediaStatus, x);
+ }
+
+ if(media & base10TAvailable){
+ setxcvr(ctlr, xcvr10BaseT);
+
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~dcConverterEnabled;
+ outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
+ delay(100);
+
+ XCVRDEBUG("autoselect: 10BaseT media status %uX\n", ins(port+MediaStatus));
+ if(ins(port+MediaStatus) & linkBeatDetect)
+ return xcvr10BaseT;
+ outs(port+MediaStatus, x);
+ }
+
+ /*
+ * Botch.
+ */
+ return autoSelect;
+}
+
+static int
+eepromdata(Ctlr* ctlr, int offset)
+{
+ int port;
+
+ port = ctlr->port;
+
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ while(EEPROMBUSY(port))
+ ;
+ EEPROMCMD(port, ctlr->eepromcmd, offset);
+ while(EEPROMBUSY(port))
+ ;
+ return EEPROMDATA(port);
+}
+
+static void
+resetctlr(Ctlr *ctlr)
+{
+ int x, port = ctlr->port;
+
+ txrxreset(port);
+ x = ins(port+ResetOp905B);
+ XCVRDEBUG("905[BC] reset ops 0x%uX\n", x);
+ x &= ~0x4010;
+ if(ctlr->did == 0x5157){
+ x |= 0x0010; /* Invert LED */
+ outs(port+ResetOp905B, x);
+ }
+ if(ctlr->did == 0x6056){
+ x |= 0x4000;
+ outs(port+ResetOp905B, x);
+
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ outs(port, 0x0800);
+ }
+}
+
+static void
+shutdown(Ether *ether)
+{
+print("etherelnk3 shutting down\n");
+ resetctlr(ether->ctlr);
+}
+
+int
+etherelnk3reset(Ether* ether)
+{
+ char *p;
+ Ctlr *ctlr;
+ uchar ea[Eaddrlen];
+ static int scandone;
+ int anar, anlpar, i, j, phyaddr, phystat, port, timeo, x;
+
+ /*
+ * Scan for adapter on PCI, EISA and finally
+ * using the little ISA configuration dance.
+ */
+ if(scandone == 0){
+ tcm59Xpci();
+ tcm5XXeisa();
+ tcm509isa();
+ scandone = 1;
+ }
+
+ /*
+ * Any adapter matches if no ether->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(ether->port == 0 || ether->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil && (ctlr = tcm5XXpcmcia(ether)) == 0)
+ return -1;
+
+ ether->ctlr = ctlr;
+ port = ctlr->port;
+ ether->port = port;
+ ether->irq = ctlr->irq;
+ if(ctlr->pcidev != nil)
+ ether->tbdf = ctlr->pcidev->tbdf;
+ else
+ ether->tbdf = BUSUNKNOWN;
+
+ /*
+ * Read the DeviceID from the EEPROM, it's at offset 0x03,
+ * and do something depending on capabilities.
+ */
+ switch(ctlr->did = eepromdata(ctlr, 0x03)){
+ case 0x5157: /* 3C575 Cyclone */
+ case 0x6056:
+ /*FALLTHROUGH*/
+ case 0x4500: /* 3C450 HomePNA Tornado */
+ case 0x7646: /* 3CSOHO100-TX */
+ case 0x9055: /* 3C905B-TX */
+ case 0x9200: /* 3C905C-TX */
+ case 0x9201: /* 3C920 */
+ case 0x9805: /* 3C9805: 3C980-TX Python-T 10/100baseTX */
+ /*FALLTHROUGH*/
+ case 0x9000: /* 3C900-TPO */
+ case 0x9001: /* 3C900-COMBO */
+ case 0x9005: /* 3C900B-COMBO */
+ case 0x9050: /* 3C905-TX */
+ case 0x9051: /* 3C905-T4 */
+ if(BUSTYPE(ether->tbdf) != BusPCI)
+ goto buggery;
+ ctlr->busmaster = 2;
+ goto vortex;
+ case 0x5900: /* 3C590-[TP|COMBO|TPO] */
+ case 0x5920: /* 3C592-[TP|COMBO|TPO] */
+ case 0x5950: /* 3C595-TX */
+ case 0x5951: /* 3C595-T4 */
+ case 0x5952: /* 3C595-MII */
+ case 0x5970: /* 3C597-TX */
+ case 0x5971: /* 3C597-T4 */
+ case 0x5972: /* 3C597-MII */
+ ctlr->busmaster = 1;
+ vortex:
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ ctlr->xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
+ ctlr->rxearly = 8188;
+ ctlr->rxstatus9 = 0;
+ break;
+ buggery:
+ default:
+ ctlr->busmaster = 0;
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ x = ins(port+AddressConfig);
+ ctlr->xcvr = ((x & xcvrMask9)>>14)<<20;
+ if(x & autoSelect9)
+ ctlr->xcvr |= autoSelect;
+ ctlr->rxearly = 2044;
+ ctlr->rxstatus9 = 1;
+ break;
+ }
+ if(ctlr->rxearly >= 2048)
+ ctlr->ts = 2;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to
+ * loading the station address in Wstation.
+ * The EEPROM returns 16-bits at a time.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+ for(i = 0; i < Eaddrlen/2; i++){
+ x = eepromdata(ctlr, i);
+ ether->ea[2*i] = x>>8;
+ ether->ea[2*i+1] = x;
+ }
+ }
+
+ COMMAND(port, SelectRegisterWindow, Wstation);
+ for(i = 0; i < Eaddrlen; i++)
+ outb(port+i, ether->ea[i]);
+
+ /*
+ * Enable the transceiver if necessary and determine whether
+ * busmastering can be used. Due to bugs in the first revision
+ * of the 3C59[05], don't use busmastering at 10Mbps.
+ */
+ XCVRDEBUG("reset: xcvr %uX\n", ctlr->xcvr);
+
+ /*
+ * Allow user to specify desired media in plan9.ini
+ */
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrncmp(ether->opt[i], "media=", 6) != 0)
+ continue;
+ p = ether->opt[i]+6;
+ for(j = 0; j < nelem(media); j++)
+ if(cistrcmp(p, media[j].name) == 0)
+ ctlr->xcvr = media[j].xcvr;
+ }
+
+ /*
+ * forgive me, but i am weak
+ */
+ switch(ctlr->did){
+ default:
+ if(ctlr->xcvr & autoSelect)
+ ctlr->xcvr = autoselect(ctlr);
+ break;
+ case 0x5157:
+ case 0x6056:
+ case 0x4500:
+ case 0x7646:
+ case 0x9055:
+ case 0x9200:
+ case 0x9201:
+ case 0x9805:
+ ctlr->xcvr = xcvrMii;
+ resetctlr(ctlr);
+ break;
+ }
+ XCVRDEBUG("xcvr selected: %uX, did 0x%uX\n", ctlr->xcvr, ctlr->did);
+
+ switch(ctlr->xcvr){
+ case xcvrMii:
+ /*
+ * Quick hack.
+ */
+ if(ctlr->did == 0x5157)
+ phyaddr = 0;
+ else if(ctlr->did == 0x6056)
+ phyaddr = scanphy(port);
+ else
+ phyaddr = 24;
+ for(i = 0; i < 7; i++)
+ XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
+ XCVRDEBUG("\n");
+
+ for(timeo = 0; timeo < 30; timeo++){
+ phystat = miir(port, phyaddr, 0x01);
+ if(phystat & 0x20)
+ break;
+ XCVRDEBUG(" %2.2uX", phystat);
+ delay(100);
+ }
+ XCVRDEBUG(" %2.2uX", miir(port, phyaddr, 0x01));
+ XCVRDEBUG("\n");
+
+ anar = miir(port, phyaddr, 0x04);
+ anlpar = miir(port, phyaddr, 0x05) & 0x03E0;
+ anar &= anlpar;
+ miir(port, phyaddr, 0x00);
+ XCVRDEBUG("mii an: %uX anlp: %uX r0:%uX r1:%uX\n",
+ anar, anlpar, miir(port, phyaddr, 0x00),
+ miir(port, phyaddr, 0x01));
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrcmp(ether->opt[i], "fullduplex") == 0)
+ anar |= 0x0100;
+ else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
+ anar |= 0x0100;
+ else if(cistrcmp(ether->opt[i], "force100") == 0)
+ anar |= 0x0080;
+ }
+ XCVRDEBUG("mii anar: %uX\n", anar);
+ if(anar & 0x0100){ /* 100BASE-TXFD */
+ ether->mbps = 100;
+ setfullduplex(port);
+ }
+ else if(anar & 0x0200){ /* 100BASE-T4 */
+ /* nothing to do */
+ }
+ else if(anar & 0x0080) /* 100BASE-TX */
+ ether->mbps = 100;
+ else if(anar & 0x0040) /* 10BASE-TFD */
+ setfullduplex(port);
+ else{ /* 10BASE-T */
+ /* nothing to do */
+ }
+ break;
+ case xcvr100BaseTX:
+ case xcvr100BaseFX:
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ x = inl(port+InternalConfig) & ~ramPartitionMask;
+ outl(port+InternalConfig, x|ramPartition1to1);
+
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
+ x |= linkBeatEnable;
+ outs(port+MediaStatus, x);
+
+ if(x & dataRate100)
+ ether->mbps = 100;
+ break;
+ case xcvr10BaseT:
+ /*
+ * Enable Link Beat and Jabber to start the
+ * transceiver.
+ */
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~dcConverterEnabled;
+ x |= linkBeatEnable|jabberGuardEnable;
+ outs(port+MediaStatus, x);
+
+ if((ctlr->did & 0xFF00) == 0x5900)
+ ctlr->busmaster = 0;
+ break;
+ case xcvr10Base2:
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
+ outs(port+MediaStatus, x);
+
+ /*
+ * Start the DC-DC converter.
+ * Wait > 800 microseconds.
+ */
+ COMMAND(port, EnableDcConverter, 0);
+ delay(1);
+ break;
+ }
+
+ /*
+ * Wop is the normal operating register set.
+ * The 3C59[0257] adapters allow access to more than one register window
+ * at a time, but there are situations where switching still needs to be
+ * done, so just do it.
+ * Clear out any lingering Tx status.
+ */
+ COMMAND(port, SelectRegisterWindow, Wop);
+ if(ctlr->busmaster == 2)
+ x = port+TxStatus905;
+ else
+ x = port+TxStatus;
+ while(inb(x))
+ outb(x, 0);
+
+ /*
+ * Clear out the
+ * adapter statistics, clear the statistics logged into ctlr
+ * and enable statistics collection.
+ */
+ ilock(&ctlr->wlock);
+ statistics(ether);
+ memset(ctlr->stats, 0, sizeof(ctlr->stats));
+
+ COMMAND(port, StatisticsEnable, 0);
+
+ /*
+ * Allocate any receive buffers.
+ */
+ switch(ctlr->busmaster){
+ case 2:
+ ctlr->dnenabled = 1;
+
+ /*
+ * 10MUpldBug.
+ * Disabling is too severe, can use receive busmastering at
+ * 100Mbps OK, but how to tell which rate is actually being used -
+ * the 3c905 always seems to have dataRate100 set?
+ * Believe the bug doesn't apply if upRxEarlyEnable is set
+ * and the threshold is set such that uploads won't start
+ * until the whole packet has been received.
+ */
+ ctlr->upenabled = 1;
+ x = eepromdata(ctlr, 0x0F);
+ if(!(x & 0x01))
+ outl(port+PktStatus, upRxEarlyEnable);
+
+ if(ctlr->upenabled || ctlr->dnenabled){
+ ctlr->nup = Nup;
+ ctlr->ndn = Ndn;
+ init905(ctlr);
+ }
+ else {
+ ctlr->rbp = rbpalloc(iallocb);
+ if(ctlr->rbp == nil)
+ panic("can't reset ethernet: out of memory");
+ }
+ outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
+ break;
+ default:
+ ctlr->rbp = rbpalloc(iallocb);
+ if(ctlr->rbp == nil)
+ panic("can't reset ethernet: out of memory");
+ break;
+ }
+
+ /*
+ * Set a base TxStartThresh which will be incremented
+ * if any txUnderrun errors occur and ensure no RxEarly
+ * interrupts happen.
+ */
+ ctlr->txthreshold = ETHERMAXTU/2;
+ COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
+ COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
+
+ iunlock(&ctlr->wlock);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->ifstat = ifstat;
+
+ ether->promiscuous = promiscuous;
+ ether->multicast = multicast;
+ ether->shutdown = shutdown;
+ ether->arg = ether;
+
+ return 0;
+}
+
+void
+etherelnk3link(void)
+{
+ addethercard("elnk3", etherelnk3reset);
+ addethercard("3C509", etherelnk3reset);
+ addethercard("3C575", etherelnk3reset);
+}
diff --git a/sys/src/9/pc/etherga620.c b/sys/src/9/pc/etherga620.c
new file mode 100755
index 000000000..d7047b8a7
--- /dev/null
+++ b/sys/src/9/pc/etherga620.c
@@ -0,0 +1,1275 @@
+/*
+ * Netgear GA620 Gigabit Ethernet Card.
+ * Specific for the Alteon Tigon 2 and Intel Pentium or later.
+ * To Do:
+ * cache alignment for PCI Write-and-Invalidate
+ * mini ring (what size)?
+ * tune coalescing values
+ * statistics formatting
+ * don't update Spi if nothing to send
+ * receive ring alignment
+ * watchdog for link management?
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#define malign(n) xspanalloc((n), 32, 0)
+
+#include "etherif.h"
+#include "etherga620fw.h"
+
+enum {
+ Mhc = 0x0040, /* Miscellaneous Host Control */
+ Mlc = 0x0044, /* Miscellaneous Local Control */
+ Mc = 0x0050, /* Miscellaneous Configuration */
+ Ps = 0x005C, /* PCI State */
+ Wba = 0x0068, /* Window Base Address */
+ Wd = 0x006C, /* Window Data */
+
+ DMAas = 0x011C, /* DMA Assist State */
+
+ CPUAstate = 0x0140, /* CPU A State */
+ CPUApc = 0x0144, /* CPU A Programme Counter */
+
+ CPUBstate = 0x0240, /* CPU B State */
+
+ Hi = 0x0504, /* Host In Interrupt Handler */
+ Cpi = 0x050C, /* Command Producer Index */
+ Spi = 0x0514, /* Send Producer Index */
+ Rspi = 0x051C, /* Receive Standard Producer Index */
+ Rjpi = 0x0524, /* Receive Jumbo Producer Index */
+ Rmpi = 0x052C, /* Receive Mini Producer Index */
+
+ Mac = 0x0600, /* MAC Address */
+ Gip = 0x0608, /* General Information Pointer */
+ Om = 0x0618, /* Operating Mode */
+ DMArc = 0x061C, /* DMA Read Configuration */
+ DMAwc = 0x0620, /* DMA Write Configuration */
+ Tbr = 0x0624, /* Transmit Buffer Ratio */
+ Eci = 0x0628, /* Event Consumer Index */
+ Cci = 0x062C, /* Command Consumer Index */
+
+ Rct = 0x0630, /* Receive Coalesced Ticks */
+ Sct = 0x0634, /* Send Coalesced Ticks */
+ St = 0x0638, /* Stat Ticks */
+ SmcBD = 0x063C, /* Send Max. Coalesced BDs */
+ RmcBD = 0x0640, /* Receive Max. Coalesced BDs */
+ Nt = 0x0644, /* NIC Tracing */
+ Gln = 0x0648, /* Gigabit Link Negotiation */
+ Fln = 0x064C, /* 10/100 Link Negotiation */
+ Ifx = 0x065C, /* Interface Index */
+ IfMTU = 0x0660, /* Interface MTU */
+ Mi = 0x0664, /* Mask Interrupts */
+ Gls = 0x0668, /* Gigabit Link State */
+ Fls = 0x066C, /* 10/100 Link State */
+
+ Cr = 0x0700, /* Command Ring */
+
+ Lmw = 0x0800, /* Local Memory Window */
+};
+
+enum { /* Mhc */
+ Is = 0x00000001, /* Interrupt State */
+ Ci = 0x00000002, /* Clear Interrupt */
+ Hr = 0x00000008, /* Hard Reset */
+ Eebs = 0x00000010, /* Enable Endian Byte Swap */
+ Eews = 0x00000020, /* Enable Endian Word (64-bit) swap */
+ Mpio = 0x00000040, /* Mask PCI Interrupt Output */
+};
+
+enum { /* Mlc */
+ SRAM512 = 0x00000200, /* SRAM Bank Size of 512KB */
+ SRAMmask = 0x00000300,
+ EEclk = 0x00100000, /* Serial EEPROM Clock Output */
+ EEdoe = 0x00200000, /* Serial EEPROM Data Out Enable */
+ EEdo = 0x00400000, /* Serial EEPROM Data Out Value */
+ EEdi = 0x00800000, /* Serial EEPROM Data Input */
+};
+
+enum { /* Mc */
+ SyncSRAM = 0x00100000, /* Set Synchronous SRAM Timing */
+};
+
+enum { /* Ps */
+ PCIwm32 = 0x000000C0, /* Write Max DMA 32 */
+ PCImrm = 0x00020000, /* Use Memory Read Multiple Command */
+ PCI66 = 0x00080000,
+ PCI32 = 0x00100000,
+ PCIrcmd = 0x06000000, /* PCI Read Command */
+ PCIwcmd = 0x70000000, /* PCI Write Command */
+};
+
+enum { /* CPUAstate */
+ CPUrf = 0x00000010, /* ROM Fail */
+ CPUhalt = 0x00010000, /* Halt the internal CPU */
+ CPUhie = 0x00040000, /* HALT instruction executed */
+};
+
+enum { /* Om */
+ BswapBD = 0x00000002, /* Byte Swap Buffer Descriptors */
+ WswapBD = 0x00000004, /* Word Swap Buffer Descriptors */
+ Warn = 0x00000008,
+ BswapDMA = 0x00000010, /* Byte Swap DMA Data */
+ Only1DMA = 0x00000040, /* Only One DMA Active at a time */
+ NoJFrag = 0x00000200, /* Don't Fragment Jumbo Frames */
+ Fatal = 0x40000000,
+};
+
+enum { /* Lmw */
+ Lmwsz = 2*1024, /* Local Memory Window Size */
+
+ /*
+ * legal values are 0x3800 iff Nsr is 128, 0x3000 iff Nsr is 256,
+ * or 0x2000 iff Nsr is 512.
+ */
+ Sr = 0x2000, /* Send Ring (accessed via Lmw) */
+};
+
+enum { /* Link */
+ Lpref = 0x00008000, /* Preferred Link */
+ L10MB = 0x00010000,
+ L100MB = 0x00020000,
+ L1000MB = 0x00040000,
+ Lfd = 0x00080000, /* Full Duplex */
+ Lhd = 0x00100000, /* Half Duplex */
+ Lefc = 0x00200000, /* Emit Flow Control Packets */
+ Lofc = 0x00800000, /* Obey Flow Control Packets */
+ Lean = 0x20000000, /* Enable Autonegotiation/Sensing */
+ Le = 0x40000000, /* Link Enable */
+};
+
+typedef struct Host64 {
+ uint hi;
+ uint lo;
+} Host64;
+
+typedef struct Ere { /* Event Ring Element */
+ int event; /* event<<24 | code<<12 | index */
+ int unused;
+} Ere;
+
+typedef int Cmd; /* cmd<<24 | flags<<12 | index */
+
+typedef struct Rbd { /* Receive Buffer Descriptor */
+ Host64 addr;
+ int indexlen; /* ring-index<<16 | buffer-length */
+ int flags; /* only lower 16-bits */
+ int checksum; /* ip<<16 | tcp/udp */
+ int error; /* only upper 16-bits */
+ int reserved;
+ void* opaque; /* passed to receive return ring */
+} Rbd;
+
+typedef struct Sbd { /* Send Buffer Descriptor */
+ Host64 addr;
+ int lenflags; /* len<<16 | flags */
+ int reserved;
+} Sbd;
+
+enum { /* Buffer Descriptor Flags */
+ Fend = 0x00000004, /* Frame Ends in this Buffer */
+ Frjr = 0x00000010, /* Receive Jumbo Ring Buffer */
+ Funicast = 0x00000020, /* Unicast packet (2-bit field) */
+ Fmulticast = 0x00000040, /* Multicast packet */
+ Fbroadcast = 0x00000060, /* Broadcast packet */
+ Ferror = 0x00000400, /* Frame Has Error */
+ Frmr = 0x00001000, /* Receive Mini Ring Buffer */
+};
+
+enum { /* Buffer Error Flags */
+ Ecrc = 0x00010000, /* bad CRC */
+ Ecollision = 0x00020000, /* collision */
+ Elink = 0x00040000, /* link lost */
+ Ephy = 0x00080000, /* unspecified PHY frame decode error */
+ Eodd = 0x00100000, /* odd number of nibbles */
+ Emac = 0x00200000, /* unspecified MAC abort */
+ Elen64 = 0x00400000, /* short packet */
+ Eresources = 0x00800000, /* MAC out of internal resources */
+ Egiant = 0x01000000, /* packet too big */
+};
+
+typedef struct Rcb { /* Ring Control Block */
+ Host64 addr; /* points to the Rbd ring */
+ int control; /* max_len<<16 | flags */
+ int unused;
+} Rcb;
+
+enum {
+ TcpUdpCksum = 0x0001, /* Perform TCP or UDP checksum */
+ IpCksum = 0x0002, /* Perform IP checksum */
+ NoPseudoHdrCksum= 0x0008, /* Don't include the pseudo header */
+ VlanAssist = 0x0010, /* Enable VLAN tagging */
+ CoalUpdateOnly = 0x0020, /* Coalesce transmit interrupts */
+ HostRing = 0x0040, /* Sr in host memory */
+ SnapCksum = 0x0080, /* Parse + offload 802.3 SNAP frames */
+ UseExtRxBd = 0x0100, /* Extended Rbd for Jumbo frames */
+ RingDisabled = 0x0200, /* Jumbo or Mini RCB only */
+};
+
+typedef struct Gib { /* General Information Block */
+ int statistics[256]; /* Statistics */
+ Rcb ercb; /* Event Ring */
+ Rcb crcb; /* Command Ring */
+ Rcb srcb; /* Send Ring */
+ Rcb rsrcb; /* Receive Standard Ring */
+ Rcb rjrcb; /* Receive Jumbo Ring */
+ Rcb rmrcb; /* Receive Mini Ring */
+ Rcb rrrcb; /* Receive Return Ring */
+ Host64 epp; /* Event Producer */
+ Host64 rrrpp; /* Receive Return Ring Producer */
+ Host64 scp; /* Send Consumer */
+ Host64 rsp; /* Refresh Stats */
+} Gib;
+
+/*
+ * these sizes are all fixed in the card,
+ * except for Nsr, which has only 3 valid sizes.
+ */
+enum { /* Host/NIC Interface ring sizes */
+ Ner = 256, /* event ring */
+ Ncr = 64, /* command ring */
+ Nsr = 512, /* send ring: 128, 256 or 512 */
+ Nrsr = 512, /* receive standard ring */
+ Nrjr = 256, /* receive jumbo ring */
+ Nrmr = 1024, /* receive mini ring, optional */
+ Nrrr = 2048, /* receive return ring */
+};
+
+enum {
+ NrsrHI = 72, /* Fill-level of Rsr (m.b. < Nrsr) */
+ NrsrLO = 54, /* Level at which to top-up ring */
+ NrjrHI = 0, /* Fill-level of Rjr (m.b. < Nrjr) */
+ NrjrLO = 0, /* Level at which to top-up ring */
+ NrmrHI = 0, /* Fill-level of Rmr (m.b. < Nrmr) */
+ NrmrLO = 0, /* Level at which to top-up ring */
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id;
+
+ uchar ea[Eaddrlen];
+
+ int* nic;
+ Gib* gib;
+
+ Ere* er;
+
+ Lock srlock;
+ Sbd* sr;
+ Block** srb;
+ int nsr; /* currently in send ring */
+
+ Rbd* rsr;
+ int nrsr; /* currently in Receive Standard Ring */
+ Rbd* rjr;
+ int nrjr; /* currently in Receive Jumbo Ring */
+ Rbd* rmr;
+ int nrmr; /* currently in Receive Mini Ring */
+ Rbd* rrr;
+ int rrrci; /* Receive Return Ring Consumer Index */
+
+ int epi[2]; /* Event Producer Index */
+ int rrrpi[2]; /* Receive Return Ring Producer Index */
+ int sci[3]; /* Send Consumer Index ([2] is host) */
+
+ int interrupts; /* statistics */
+ int mi;
+ uvlong ticks;
+
+ int coalupdateonly; /* tuning */
+ int hardwarecksum;
+ int rct; /* Receive Coalesce Ticks */
+ int sct; /* Send Coalesce Ticks */
+ int st; /* Stat Ticks */
+ int smcbd; /* Send Max. Coalesced BDs */
+ int rmcbd; /* Receive Max. Coalesced BDs */
+};
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+#define csr32r(c, r) (*((c)->nic+((r)/4)))
+#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
+
+static void
+sethost64(Host64* host64, void* addr)
+{
+ uvlong uvl;
+
+ uvl = PCIWADDR(addr);
+ host64->hi = uvl>>32;
+ host64->lo = uvl & 0xFFFFFFFFL;
+}
+
+static void
+ga620command(Ctlr* ctlr, int cmd, int flags, int index)
+{
+ int cpi;
+
+ cpi = csr32r(ctlr, Cpi);
+ csr32w(ctlr, Cr+(cpi*4), cmd<<24 | flags<<12 | index);
+ cpi = NEXT(cpi, Ncr);
+ csr32w(ctlr, Cpi, cpi);
+}
+
+static void
+ga620attach(Ether* edev)
+{
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ USED(ctlr);
+}
+
+static long
+ga620ifstat(Ether* edev, void* a, long n, ulong offset)
+{
+ char *p;
+ Ctlr *ctlr;
+ int i, l, r;
+
+ ctlr = edev->ctlr;
+
+ if(n == 0)
+ return 0;
+ p = malloc(READSTR);
+ l = 0;
+ for(i = 0; i < 256; i++){
+ if((r = ctlr->gib->statistics[i]) == 0)
+ continue;
+ l += snprint(p+l, READSTR-l, "%d: %ud\n", i, r);
+ }
+
+ l += snprint(p+l, READSTR-l, "interrupts: %ud\n", ctlr->interrupts);
+ l += snprint(p+l, READSTR-l, "mi: %ud\n", ctlr->mi);
+ l += snprint(p+l, READSTR-l, "ticks: %llud\n", ctlr->ticks);
+ l += snprint(p+l, READSTR-l, "coalupdateonly: %d\n", ctlr->coalupdateonly);
+ l += snprint(p+l, READSTR-l, "hardwarecksum: %d\n", ctlr->hardwarecksum);
+ l += snprint(p+l, READSTR-l, "rct: %d\n", ctlr->rct);
+ l += snprint(p+l, READSTR-l, "sct: %d\n", ctlr->sct);
+ l += snprint(p+l, READSTR-l, "smcbd: %d\n", ctlr->smcbd);
+ snprint(p+l, READSTR-l, "rmcbd: %d\n", ctlr->rmcbd);
+
+ n = readstr(offset, a, n, p);
+ free(p);
+
+ return n;
+}
+
+static long
+ga620ctl(Ether* edev, void* buf, long n)
+{
+ char *p;
+ Cmdbuf *cb;
+ Ctlr *ctlr;
+ int control, i, r;
+
+ ctlr = edev->ctlr;
+ if(ctlr == nil)
+ error(Enonexist);
+ r = 0;
+ cb = parsecmd(buf, n);
+ if(cb->nf < 2)
+ r = -1;
+ else if(cistrcmp(cb->f[0], "coalupdateonly") == 0){
+ if(cistrcmp(cb->f[1], "off") == 0){
+ control = ctlr->gib->srcb.control;
+ control &= ~CoalUpdateOnly;
+ ctlr->gib->srcb.control = control;
+ ctlr->coalupdateonly = 0;
+ }
+ else if(cistrcmp(cb->f[1], "on") == 0){
+ control = ctlr->gib->srcb.control;
+ control |= CoalUpdateOnly;
+ ctlr->gib->srcb.control = control;
+ ctlr->coalupdateonly = 1;
+ }
+ else
+ r = -1;
+ }
+ else if(cistrcmp(cb->f[0], "hardwarecksum") == 0){
+ if(cistrcmp(cb->f[1], "off") == 0){
+ control = ctlr->gib->srcb.control;
+ control &= ~(TcpUdpCksum|NoPseudoHdrCksum);
+ ctlr->gib->srcb.control = control;
+
+ control = ctlr->gib->rsrcb.control;
+ control &= ~(TcpUdpCksum|NoPseudoHdrCksum);
+ ctlr->gib->rsrcb.control = control;
+
+ ctlr->hardwarecksum = 0;
+ }
+ else if(cistrcmp(cb->f[1], "on") == 0){
+ control = ctlr->gib->srcb.control;
+ control |= (TcpUdpCksum|NoPseudoHdrCksum);
+ ctlr->gib->srcb.control = control;
+
+ control = ctlr->gib->rsrcb.control;
+ control |= (TcpUdpCksum|NoPseudoHdrCksum);
+ ctlr->gib->rsrcb.control = control;
+
+ ctlr->hardwarecksum = 1;
+ }
+ else
+ r = -1;
+ }
+ else if(cistrcmp(cb->f[0], "rct") == 0){
+ i = strtol(cb->f[1], &p, 0);
+ if(i < 0 || p == cb->f[1])
+ r = -1;
+ else{
+ ctlr->rct = i;
+ csr32w(ctlr, Rct, ctlr->rct);
+ }
+ }
+ else if(cistrcmp(cb->f[0], "sct") == 0){
+ i = strtol(cb->f[1], &p, 0);
+ if(i < 0 || p == cb->f[1])
+ r = -1;
+ else{
+ ctlr->sct = i;
+ csr32w(ctlr, Sct, ctlr->sct);
+ }
+ }
+ else if(cistrcmp(cb->f[0], "st") == 0){
+ i = strtol(cb->f[1], &p, 0);
+ if(i < 0 || p == cb->f[1])
+ r = -1;
+ else{
+ ctlr->st = i;
+ csr32w(ctlr, St, ctlr->st);
+ }
+ }
+ else if(cistrcmp(cb->f[0], "smcbd") == 0){
+ i = strtol(cb->f[1], &p, 0);
+ if(i < 0 || p == cb->f[1])
+ r = -1;
+ else{
+ ctlr->smcbd = i;
+ csr32w(ctlr, SmcBD, ctlr->smcbd);
+ }
+ }
+ else if(cistrcmp(cb->f[0], "rmcbd") == 0){
+ i = strtol(cb->f[1], &p, 0);
+ if(i < 0 || p == cb->f[1])
+ r = -1;
+ else{
+ ctlr->rmcbd = i;
+ csr32w(ctlr, RmcBD, ctlr->rmcbd);
+ }
+ }
+ else
+ r = -1;
+
+ free(cb);
+ if(r == 0)
+ return n;
+ return r;
+}
+
+static int
+_ga620transmit(Ether* edev)
+{
+ Sbd *sbd;
+ Block *bp;
+ Ctlr *ctlr;
+ int sci, spi, work;
+
+ /*
+ * For now there are no smarts here, just empty the
+ * ring and try to fill it back up. Tuning comes later.
+ */
+ ctlr = edev->ctlr;
+ ilock(&ctlr->srlock);
+
+ /*
+ * Free any completed packets.
+ * Ctlr->sci[0] is where the NIC has got to consuming the ring.
+ * Ctlr->sci[2] is where the host has got to tidying up after the
+ * NIC has done with the packets.
+ */
+ work = 0;
+ for(sci = ctlr->sci[2]; sci != ctlr->sci[0]; sci = NEXT(sci, Nsr)){
+ if(ctlr->srb[sci] == nil)
+ continue;
+ freeb(ctlr->srb[sci]);
+ ctlr->srb[sci] = nil;
+ work++;
+ }
+ ctlr->sci[2] = sci;
+
+ sci = PREV(sci, Nsr);
+ for(spi = csr32r(ctlr, Spi); spi != sci; spi = NEXT(spi, Nsr)){
+ if((bp = qget(edev->oq)) == nil)
+ break;
+
+ sbd = &ctlr->sr[spi];
+ sethost64(&sbd->addr, bp->rp);
+ sbd->lenflags = BLEN(bp)<<16 | Fend;
+
+ ctlr->srb[spi] = bp;
+ work++;
+ }
+ csr32w(ctlr, Spi, spi);
+
+ iunlock(&ctlr->srlock);
+
+ return work;
+}
+
+static void
+ga620transmit(Ether* edev)
+{
+ _ga620transmit(edev);
+}
+
+static void
+ga620replenish(Ctlr* ctlr)
+{
+ Rbd *rbd;
+ int rspi;
+ Block *bp;
+
+ rspi = csr32r(ctlr, Rspi);
+ while(ctlr->nrsr < NrsrHI){
+ if((bp = iallocb(ETHERMAXTU+4)) == nil)
+ break;
+ rbd = &ctlr->rsr[rspi];
+ sethost64(&rbd->addr, bp->rp);
+ rbd->indexlen = rspi<<16 | (ETHERMAXTU+4);
+ rbd->flags = 0;
+ rbd->opaque = bp;
+
+ rspi = NEXT(rspi, Nrsr);
+ ctlr->nrsr++;
+ }
+ csr32w(ctlr, Rspi, rspi);
+}
+
+static void
+ga620event(Ether *edev, int eci, int epi)
+{
+ unsigned event, code;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ while(eci != epi){
+ event = ctlr->er[eci].event;
+ code = (event >> 12) & ((1<<12)-1);
+ switch(event>>24){
+ case 0x01: /* firmware operational */
+ /* host stack (us) is up. 3rd arg of 2 means down. */
+ ga620command(ctlr, 0x01, 0x01, 0x00);
+ /*
+ * link negotiation: any speed is okay.
+ * 3rd arg of 1 selects gigabit only; 2 10/100 only.
+ */
+ ga620command(ctlr, 0x0B, 0x00, 0x00);
+ print("#l%d: ga620: port %8.8uX: firmware is up\n",
+ edev->ctlrno, ctlr->port);
+ break;
+ case 0x04: /* statistics updated */
+ break;
+ case 0x06: /* link state changed */
+ switch (code) {
+ case 1:
+ edev->mbps = 1000;
+ break;
+ case 2:
+ print("#l%d: link down\n", edev->ctlrno);
+ break;
+ case 3:
+ edev->mbps = 100; /* it's 10 or 100 */
+ break;
+ }
+ if (code != 2)
+ print("#l%d: %dMbps link up\n",
+ edev->ctlrno, edev->mbps);
+ break;
+ case 0x07: /* event error */
+ default:
+ print("#l%d: ga620: er[%d] = %8.8uX\n", edev->ctlrno,
+ eci, event);
+ break;
+ }
+ eci = NEXT(eci, Ner);
+ }
+ csr32w(ctlr, Eci, eci);
+}
+
+static void
+ga620receive(Ether* edev)
+{
+ int len;
+ Rbd *rbd;
+ Block *bp;
+ Ctlr* ctlr;
+
+ ctlr = edev->ctlr;
+ while(ctlr->rrrci != ctlr->rrrpi[0]){
+ rbd = &ctlr->rrr[ctlr->rrrci];
+ /*
+ * Errors are collected in the statistics block so
+ * no need to tally them here, let ifstat do the work.
+ */
+ len = rbd->indexlen & 0xFFFF;
+ if(!(rbd->flags & Ferror) && len != 0){
+ bp = rbd->opaque;
+ bp->wp = bp->rp+len;
+ etheriq(edev, bp, 1);
+ }
+ else
+ freeb(rbd->opaque);
+ rbd->opaque = nil;
+
+ if(rbd->flags & Frjr)
+ ctlr->nrjr--;
+ else if(rbd->flags & Frmr)
+ ctlr->nrmr--;
+ else
+ ctlr->nrsr--;
+
+ ctlr->rrrci = NEXT(ctlr->rrrci, Nrrr);
+ }
+}
+
+static void
+ga620interrupt(Ureg*, void* arg)
+{
+ int csr, ie, work;
+ Ctlr *ctlr;
+ Ether *edev;
+ uvlong tsc0, tsc1;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ if(!(csr32r(ctlr, Mhc) & Is))
+ return;
+ cycles(&tsc0);
+
+ ctlr->interrupts++;
+ csr32w(ctlr, Hi, 1);
+
+ ie = 0;
+ work = 0;
+ while(ie < 2){
+ if(ctlr->rrrci != ctlr->rrrpi[0]){
+ ga620receive(edev);
+ work = 1;
+ }
+
+ if(_ga620transmit(edev) != 0)
+ work = 1;
+
+ csr = csr32r(ctlr, Eci);
+ if(csr != ctlr->epi[0]){
+ ga620event(edev, csr, ctlr->epi[0]);
+ work = 1;
+ }
+
+ if(ctlr->nrsr <= NrsrLO)
+ ga620replenish(ctlr);
+ if(work == 0){
+ if(ie == 0)
+ csr32w(ctlr, Hi, 0);
+ ie++;
+ }
+ work = 0;
+ }
+
+ cycles(&tsc1);
+ ctlr->ticks += tsc1-tsc0;
+}
+
+static void
+ga620lmw(Ctlr* ctlr, int addr, int* data, int len)
+{
+ int i, l, lmw, v;
+
+ /*
+ * Write to or clear ('data' == nil) 'len' bytes of the NIC
+ * local memory at address 'addr'.
+ * The destination address and count should be 32-bit aligned.
+ */
+ v = 0;
+ while(len > 0){
+ /*
+ * 1) Set the window. The (Lmwsz-1) bits are ignored
+ * in Wba when accessing through the local memory window;
+ * 2) Find the minimum of how many bytes still to
+ * transfer and how many left in this window;
+ * 3) Create the offset into the local memory window in the
+ * shared memory space then copy (or zero) the data;
+ * 4) Bump the counts.
+ */
+ csr32w(ctlr, Wba, addr);
+
+ l = ROUNDUP(addr+1, Lmwsz) - addr;
+ if(l > len)
+ l = len;
+
+ lmw = Lmw + (addr & (Lmwsz-1));
+ for(i = 0; i < l; i += 4){
+ if(data != nil)
+ v = *data++;
+ csr32w(ctlr, lmw+i, v);
+ }
+
+ len -= l;
+ addr += l;
+ }
+}
+
+static int
+ga620init(Ether* edev)
+{
+ Ctlr *ctlr;
+ Host64 host64;
+ int csr, ea, i, flags;
+
+ ctlr = edev->ctlr;
+
+ /*
+ * Load the MAC address.
+ */
+ ea = edev->ea[0]<<8 | edev->ea[1];
+ csr32w(ctlr, Mac, ea);
+ ea = edev->ea[2]<<24 | edev->ea[3]<<16 | edev->ea[4]<<8 | edev->ea[5];
+ csr32w(ctlr, Mac+4, ea);
+
+ /*
+ * General Information Block.
+ */
+ ctlr->gib = malloc(sizeof(Gib));
+ sethost64(&host64, ctlr->gib);
+ csr32w(ctlr, Gip, host64.hi);
+ csr32w(ctlr, Gip+4, host64.lo);
+
+ /*
+ * Event Ring.
+ * This is located in host memory. Allocate the ring,
+ * tell the NIC where it is and initialise the indices.
+ */
+ ctlr->er = malign(sizeof(Ere)*Ner);
+ sethost64(&ctlr->gib->ercb.addr, ctlr->er);
+ sethost64(&ctlr->gib->epp, ctlr->epi);
+ csr32w(ctlr, Eci, 0);
+
+ /*
+ * Command Ring.
+ * This is located in the General Communications Region
+ * and so the value placed in the Rcb is unused, the NIC
+ * knows where it is. Stick in the value according to
+ * the datasheet anyway.
+ * Initialise the ring and indices.
+ */
+ ctlr->gib->crcb.addr.lo = Cr-0x400;
+ for(i = 0; i < Ncr*4; i += 4)
+ csr32w(ctlr, Cr+i, 0);
+ csr32w(ctlr, Cpi, 0);
+ csr32w(ctlr, Cci, 0);
+
+ /*
+ * Send Ring.
+ * This ring is either in NIC memory at a fixed location depending
+ * on how big the ring is or it is in host memory. If in NIC
+ * 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 = (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
+ * with this entry so an external array must be kept.
+ */
+ ctlr->sr = malign(sizeof(Sbd)*Nsr);
+ sethost64(&ctlr->gib->srcb.addr, ctlr->sr);
+ if(ctlr->hardwarecksum)
+ flags = TcpUdpCksum|NoPseudoHdrCksum|HostRing;
+ else
+ flags = HostRing;
+ if(ctlr->coalupdateonly)
+ flags |= CoalUpdateOnly;
+ ctlr->gib->srcb.control = Nsr<<16 | flags;
+ sethost64(&ctlr->gib->scp, ctlr->sci);
+ csr32w(ctlr, Spi, 0);
+ ctlr->srb = malloc(sizeof(Block*)*Nsr);
+
+ /*
+ * Receive Standard Ring.
+ */
+ ctlr->rsr = malign(sizeof(Rbd)*Nrsr);
+ sethost64(&ctlr->gib->rsrcb.addr, ctlr->rsr);
+ if(ctlr->hardwarecksum)
+ flags = TcpUdpCksum|NoPseudoHdrCksum;
+ else
+ flags = 0;
+ ctlr->gib->rsrcb.control = (ETHERMAXTU+4)<<16 | flags;
+ csr32w(ctlr, Rspi, 0);
+
+ /*
+ * Jumbo and Mini Rings. Unused for now.
+ */
+ ctlr->gib->rjrcb.control = RingDisabled;
+ ctlr->gib->rmrcb.control = RingDisabled;
+
+ /*
+ * Receive Return Ring.
+ * This is located in host memory. Allocate the ring,
+ * tell the NIC where it is and initialise the indices.
+ */
+ ctlr->rrr = malign(sizeof(Rbd)*Nrrr);
+ sethost64(&ctlr->gib->rrrcb.addr, ctlr->rrr);
+ ctlr->gib->rrrcb.control = Nrrr<<16 | 0;
+ sethost64(&ctlr->gib->rrrpp, ctlr->rrrpi);
+ ctlr->rrrci = 0;
+
+ /*
+ * Refresh Stats Pointer.
+ * For now just point it at the existing statistics block.
+ */
+ sethost64(&ctlr->gib->rsp, ctlr->gib->statistics);
+
+ /*
+ * DMA configuration.
+ * Use the recommended values.
+ */
+ csr32w(ctlr, DMArc, 0x80);
+ csr32w(ctlr, DMAwc, 0x80);
+
+ /*
+ * Transmit Buffer Ratio.
+ * Set to 1/3 of available buffer space (units are 1/64ths)
+ * if using Jumbo packets, ~64KB otherwise (assume 1MB on NIC).
+ */
+ if(NrjrHI > 0 || Nsr > 128)
+ csr32w(ctlr, Tbr, 64/3);
+ else
+ csr32w(ctlr, Tbr, 4);
+
+ /*
+ * Tuneable parameters.
+ * These defaults are based on the tuning hints in the Alteon
+ * Host/NIC Software Interface Definition and example software.
+ */
+ ctlr->rct = 1/*100*/;
+ csr32w(ctlr, Rct, ctlr->rct);
+ ctlr->sct = 0;
+ csr32w(ctlr, Sct, ctlr->sct);
+ ctlr->st = 1000000;
+ csr32w(ctlr, St, ctlr->st);
+ ctlr->smcbd = Nsr/4;
+ csr32w(ctlr, SmcBD, ctlr->smcbd);
+ ctlr->rmcbd = 4/*6*/;
+ csr32w(ctlr, RmcBD, ctlr->rmcbd);
+
+ /*
+ * Enable DMA Assist Logic.
+ */
+ csr = csr32r(ctlr, DMAas) & ~0x03;
+ csr32w(ctlr, DMAas, csr|0x01);
+
+ /*
+ * Link negotiation.
+ * The bits are set here but the NIC must be given a command
+ * once it is running to set negotiation in motion.
+ */
+ csr32w(ctlr, Gln, Le|Lean|Lofc|Lfd|L1000MB|Lpref);
+ csr32w(ctlr, Fln, Le|Lean|Lhd|Lfd|L100MB|L10MB);
+
+ /*
+ * A unique index for this controller and the maximum packet
+ * length expected.
+ * For now only standard packets are expected.
+ */
+ csr32w(ctlr, Ifx, 1);
+ csr32w(ctlr, IfMTU, ETHERMAXTU+4);
+
+ /*
+ * Enable Interrupts.
+ * There are 3 ways to mask interrupts - a bit in the Mhc (which
+ * is already cleared), the Mi register and the Hi mailbox.
+ * Writing to the Hi mailbox has the side-effect of clearing the
+ * PCI interrupt.
+ */
+ csr32w(ctlr, Mi, 0);
+ csr32w(ctlr, Hi, 0);
+
+ /*
+ * Start the firmware.
+ */
+ csr32w(ctlr, CPUApc, tigon2FwStartAddr);
+ csr = csr32r(ctlr, CPUAstate) & ~CPUhalt;
+ csr32w(ctlr, CPUAstate, csr);
+
+ return 0;
+}
+
+static int
+at24c32io(Ctlr* ctlr, char* op, int data)
+{
+ char *lp, *p;
+ int i, loop, mlc, r;
+
+ mlc = csr32r(ctlr, Mlc);
+
+ r = 0;
+ loop = -1;
+ lp = nil;
+ for(p = op; *p != '\0'; p++){
+ switch(*p){
+ default:
+ return -1;
+ case ' ':
+ continue;
+ case ':': /* start of 8-bit loop */
+ if(lp != nil)
+ return -1;
+ lp = p;
+ loop = 7;
+ continue;
+ case ';': /* end of 8-bit loop */
+ if(lp == nil)
+ return -1;
+ loop--;
+ if(loop >= 0)
+ p = lp;
+ else
+ lp = nil;
+ continue;
+ case 'C': /* assert clock */
+ mlc |= EEclk;
+ break;
+ case 'c': /* deassert clock */
+ mlc &= ~EEclk;
+ break;
+ case 'D': /* next bit in 'data' byte */
+ if(loop < 0)
+ return -1;
+ if(data & (1<<loop))
+ mlc |= EEdo;
+ else
+ mlc &= ~EEdo;
+ break;
+ case 'E': /* enable data output */
+ mlc |= EEdoe;
+ break;
+ case 'e': /* disable data output */
+ mlc &= ~EEdoe;
+ break;
+ case 'I': /* input bit */
+ i = (csr32r(ctlr, Mlc) & EEdi) != 0;
+ if(loop >= 0)
+ r |= (i<<loop);
+ else
+ r = i;
+ continue;
+ case 'O': /* assert data output */
+ mlc |= EEdo;
+ break;
+ case 'o': /* deassert data output */
+ mlc &= ~EEdo;
+ break;
+ }
+ csr32w(ctlr, Mlc, mlc);
+ microdelay(1);
+ }
+ if(loop >= 0)
+ return -1;
+ return r;
+}
+
+static int
+at24c32r(Ctlr* ctlr, int addr)
+{
+ int data;
+
+ /*
+ * Read a byte at address 'addr' from the Atmel AT24C32
+ * Serial EEPROM. The 2-wire EEPROM access is controlled
+ * by 4 bits in Mlc. See the AT24C32 datasheet for
+ * protocol details.
+ */
+ /*
+ * Start condition - a high to low transition of data
+ * with the clock high must precede any other command.
+ */
+ at24c32io(ctlr, "OECoc", 0);
+
+ /*
+ * Perform a random read at 'addr'. A dummy byte
+ * write sequence is performed to clock in the device
+ * and data word addresses (0 and 'addr' respectively).
+ */
+ data = -1;
+ if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA0) != 0)
+ goto stop;
+ if(at24c32io(ctlr, "oE :DCc; oeCIc", addr>>8) != 0)
+ goto stop;
+ if(at24c32io(ctlr, "oE :DCc; oeCIc", addr) != 0)
+ goto stop;
+
+ /*
+ * Now send another start condition followed by a
+ * request to read the device. The EEPROM responds
+ * by clocking out the data.
+ */
+ at24c32io(ctlr, "OECoc", 0);
+ if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA1) != 0)
+ goto stop;
+ data = at24c32io(ctlr, ":CIc;", 0xA1);
+
+stop:
+ /*
+ * Stop condition - a low to high transition of data
+ * with the clock high is a stop condition. After a read
+ * sequence, the stop command will place the EEPROM in
+ * a standby power mode.
+ */
+ at24c32io(ctlr, "oECOc", 0);
+
+ return data;
+}
+
+static int
+ga620detach(Ctlr* ctlr)
+{
+ int timeo;
+
+ /*
+ * Hard reset (don't know which endian so catch both);
+ * enable for little-endian mode;
+ * wait for code to be loaded from serial EEPROM or flash;
+ * make sure CPU A is halted.
+ */
+ csr32w(ctlr, Mhc, Hr<<24 | Hr);
+ csr32w(ctlr, Mhc, (Eews|Ci)<<24 | Eews|Ci);
+
+ microdelay(1);
+ for(timeo = 0; timeo < 500000; timeo++){
+ if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) == CPUhie)
+ break;
+ microdelay(1);
+ }
+ if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) != CPUhie)
+ return -1;
+ csr32w(ctlr, CPUAstate, CPUhalt);
+
+ /*
+ * After reset, CPU B seems to be stuck in 'CPUrf'.
+ * Worry about it later.
+ */
+ csr32w(ctlr, CPUBstate, CPUhalt);
+
+ return 0;
+}
+
+static void
+ga620shutdown(Ether* ether)
+{
+print("ga620shutdown\n");
+ ga620detach(ether->ctlr);
+}
+
+static int
+ga620reset(Ctlr* ctlr)
+{
+ int cls, csr, i, r;
+
+ if(ga620detach(ctlr) < 0)
+ return -1;
+
+ /*
+ * Tigon 2 PCI NICs have 512KB SRAM per bank.
+ * Clear out any lingering serial EEPROM state
+ * bits.
+ */
+ csr = csr32r(ctlr, Mlc) & ~(EEdi|EEdo|EEdoe|EEclk|SRAMmask);
+ csr32w(ctlr, Mlc, SRAM512|csr);
+ csr = csr32r(ctlr, Mc);
+ csr32w(ctlr, Mc, SyncSRAM|csr);
+
+ /*
+ * Initialise PCI State register.
+ * If PCI Write-and-Invalidate is enabled set the max write DMA
+ * value to the host cache-line size (32 on Pentium or later).
+ */
+ csr = csr32r(ctlr, Ps) & (PCI32|PCI66);
+ csr |= PCIwcmd|PCIrcmd|PCImrm;
+ if(ctlr->pcidev->pcr & 0x0010){
+ cls = pcicfgr8(ctlr->pcidev, PciCLS) * 4;
+ if(cls != 32)
+ pcicfgw8(ctlr->pcidev, PciCLS, 32/4);
+ csr |= PCIwm32;
+ }
+ csr32w(ctlr, Ps, csr);
+
+ /*
+ * Operating Mode.
+ */
+ csr32w(ctlr, Om, Fatal|NoJFrag|BswapDMA|WswapBD);
+
+ /*
+ * Snarf the MAC address from the serial EEPROM.
+ */
+ for(i = 0; i < Eaddrlen; i++){
+ if((r = at24c32r(ctlr, 0x8E+i)) == -1)
+ return -1;
+ ctlr->ea[i] = r;
+ }
+
+ /*
+ * Load the firmware.
+ */
+ ga620lmw(ctlr, tigon2FwTextAddr, tigon2FwText, tigon2FwTextLen);
+ ga620lmw(ctlr, tigon2FwRodataAddr, tigon2FwRodata, tigon2FwRodataLen);
+ ga620lmw(ctlr, tigon2FwDataAddr, tigon2FwData, tigon2FwDataLen);
+ ga620lmw(ctlr, tigon2FwSbssAddr, nil, tigon2FwSbssLen);
+ ga620lmw(ctlr, tigon2FwBssAddr, nil, tigon2FwBssLen);
+
+ return 0;
+}
+
+static void
+ga620pci(void)
+{
+ void *mem;
+ Pcidev *p;
+ Ctlr *ctlr;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+
+ switch(p->did<<16 | p->vid){
+ default:
+ continue;
+ case 0x620A<<16 | 0x1385: /* Netgear GA620 fiber */
+ case 0x630A<<16 | 0x1385: /* Netgear GA620T copper */
+ case 0x0001<<16 | 0x12AE: /* Alteon Acenic fiber
+ * and DEC DEGPA-SA */
+ case 0x0002<<16 | 0x12AE: /* Alteon Acenic copper */
+ case 0x0009<<16 | 0x10A9: /* SGI Acenic */
+ break;
+ }
+
+ 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 = p->mem[0].bar & ~0x0F;
+ ctlr->pcidev = p;
+ ctlr->id = p->did<<16 | p->vid;
+
+ ctlr->nic = mem;
+ if(ga620reset(ctlr)){
+ free(ctlr);
+ continue;
+ }
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+}
+
+static void
+ga620promiscuous(void *arg, int on)
+{
+ Ether *ether = arg;
+
+ /* 3rd arg: 1 enables, 2 disables */
+ ga620command(ether->ctlr, 0xa, (on? 1: 2), 0);
+}
+
+static void
+ga620multicast(void *arg, uchar *addr, int add)
+{
+ Ether *ether = arg;
+
+ USED(addr);
+ if (add)
+ ga620command(ether->ctlr, 0xe, 1, 0); /* 1 == enable */
+}
+
+static int
+ga620pnp(Ether* edev)
+{
+ Ctlr *ctlr;
+ uchar ea[Eaddrlen];
+
+ if(ctlrhead == nil)
+ ga620pci();
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+ edev->mbps = 1000; /* placeholder */
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to
+ * loading the station address in the hardware.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, edev->ea, Eaddrlen) == 0)
+ memmove(edev->ea, ctlr->ea, Eaddrlen);
+
+ ga620init(edev);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ edev->attach = ga620attach;
+ edev->transmit = ga620transmit;
+ edev->interrupt = ga620interrupt;
+ edev->ifstat = ga620ifstat;
+ edev->ctl = ga620ctl;
+
+ edev->arg = edev;
+ edev->promiscuous = ga620promiscuous;
+ edev->multicast = ga620multicast;
+ edev->shutdown = ga620shutdown;
+
+ return 0;
+}
+
+void
+etherga620link(void)
+{
+ addethercard("GA620", ga620pnp);
+}
diff --git a/sys/src/9/pc/etherga620fw.h b/sys/src/9/pc/etherga620fw.h
new file mode 100755
index 000000000..c30859e75
--- /dev/null
+++ b/sys/src/9/pc/etherga620fw.h
@@ -0,0 +1,4858 @@
+/* Generated by genfw.c */
+#define tigon2FwReleaseMajor 0xc
+#define tigon2FwReleaseMinor 0x4
+#define tigon2FwReleaseFix 0xb
+#define tigon2FwStartAddr 0x00004000
+#define tigon2FwTextAddr 0x00004000
+#define tigon2FwTextLen 0x11bc0
+#define tigon2FwRodataAddr 0x00015bc0
+#define tigon2FwRodataLen 0x10d0
+#define tigon2FwDataAddr 0x00016cc0
+#define tigon2FwDataLen 0x1c0
+#define tigon2FwSbssAddr 0x00016e80
+#define tigon2FwSbssLen 0xcc
+#define tigon2FwBssAddr 0x00016f50
+#define tigon2FwBssLen 0x20c0
+static int tigon2FwText[/*(MAX_TEXT_LEN/4) + 1*/] = {
+0x0,
+0x10000003, 0x0, 0xd, 0xd,
+0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 0x3c100000,
+0x26104000, 0xc0010c0, 0x0, 0xd,
+0x3c1d0001, 0x8fbd6d24, 0x3a0f021, 0x3c100000,
+0x26104000, 0xc0017e0, 0x0, 0xd,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x2000008,
+0x0, 0x800172f, 0x3c0a0001, 0x800172f,
+0x3c0a0002, 0x800172f, 0x0, 0x8002cac,
+0x0, 0x8002c4f, 0x0, 0x800172f,
+0x3c0a0004, 0x800328a, 0x0, 0x8001a52,
+0x0, 0x800394d, 0x0, 0x80038f4,
+0x0, 0x800172f, 0x3c0a0006, 0x80039bb,
+0x3c0a0007, 0x800172f, 0x3c0a0008, 0x800172f,
+0x3c0a0009, 0x8003a13, 0x0, 0x8002ea6,
+0x0, 0x800172f, 0x3c0a000b, 0x800172f,
+0x3c0a000c, 0x800172f, 0x3c0a000d, 0x80028fb,
+0x0, 0x8002890, 0x0, 0x800172f,
+0x3c0a000e, 0x800208c, 0x0, 0x8001964,
+0x0, 0x8001a04, 0x0, 0x8003ca6,
+0x0, 0x8003c94, 0x0, 0x800172f,
+0x0, 0x800191a, 0x0, 0x800172f,
+0x0, 0x800172f, 0x3c0a0013, 0x800172f,
+0x3c0a0014, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x27bdffe0,
+0x3c1cc000, 0xafbf001c, 0xafb00018, 0x8f820140,
+0x24030003, 0xaf8300ec, 0x34420004, 0xc002b20,
+0xaf820140, 0x3c0100c0, 0xc001763, 0xac203ffc,
+0x401821, 0x3c020010, 0x3c010001, 0xac236e9c,
+0x10620011, 0x43102b, 0x14400002, 0x3c020020,
+0x3c020008, 0x1062000c, 0x24050100, 0x3c060001,
+0x8cc66e9c, 0x3c040001, 0x24845c74, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020020,
+0x3c010001, 0xac226e9c, 0x24020008, 0x3c010001,
+0xac226eb4, 0x2402001f, 0x3c010001, 0xac226ec4,
+0x24020016, 0x3c010001, 0xac226e98, 0x3c05fffe,
+0x34a56f08, 0x3c020001, 0x8c426e9c, 0x3c030002,
+0x24639010, 0x3c040001, 0x8c846cc4, 0x431023,
+0x14800002, 0x458021, 0x2610fa38, 0x2402f000,
+0x2028024, 0xc001785, 0x2002021, 0x2022823,
+0x3c040020, 0x821823, 0x651823, 0x247bb000,
+0x3c03fffe, 0x3463bf08, 0x363b821, 0x3c0600bf,
+0x34c6f000, 0x3c070001, 0x8ce76cc0, 0x3c0300bf,
+0x3463e000, 0x852023, 0x3c010001, 0xac246ea8,
+0x822023, 0x3c010001, 0xac256e90, 0x52842,
+0x3c010001, 0xac226e84, 0x27620ffc, 0x3c010001,
+0xac226d20, 0x27621ffc, 0xdb3023, 0x7b1823,
+0x3c010001, 0xac246e88, 0x3c010001, 0xac256eac,
+0x3c010001, 0xac226d24, 0xaf860150, 0x10e00011,
+0xaf830250, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021,
+0xc001749, 0x0, 0x3c020001, 0x8c426cd0,
+0x3c030001, 0x8c636cd4, 0x2442fe00, 0x24630200,
+0x3c010001, 0xac226cd0, 0x3c010001, 0x10000004,
+0xac236cd4, 0x3c1d0001, 0x8fbd6d20, 0x3a0f021,
+0x3c020001, 0x8c426cc4, 0x1040000d, 0x26fafa38,
+0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4,
+0x3c1a0001, 0x8f5a6cd4, 0x2442fa38, 0x246305c8,
+0x3c010001, 0xac226cd0, 0x3c010001, 0xac236cd4,
+0x3c020001, 0x8c426cc8, 0x14400003, 0x0,
+0x3c010001, 0xac206cd0, 0xc001151, 0x0,
+0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020,
+0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4,
+0x27bdff98, 0xafb00048, 0x3c100001, 0x8e1066b8,
+0xafb20050, 0x3c120000, 0x26524100, 0xafbf0060,
+0xafbe005c, 0xafb50058, 0xafb30054, 0xafb1004c,
+0xafa20034, 0xafa30030, 0xafa00010, 0xafa00014,
+0x8f860040, 0x3c040001, 0x24845c80, 0x24050200,
+0x3c010001, 0xac326e80, 0xc002b3b, 0x2003821,
+0x8f830040, 0x3c02f000, 0x621824, 0x3c026000,
+0x1062000b, 0xa3a0003f, 0x240e0001, 0x3c040001,
+0x24845c88, 0xa3ae003f, 0xafa00010, 0xafa00014,
+0x8f860040, 0x24050300, 0xc002b3b, 0x2003821,
+0x8f820240, 0x3c030001, 0x431025, 0xaf820240,
+0xaf800048, 0x8f820048, 0x14400005, 0x0,
+0xaf800048, 0x8f820048, 0x10400004, 0x0,
+0xaf800048, 0x10000003, 0x2e02021, 0xaf80004c,
+0x2e02021, 0x3c050001, 0xc002ba8, 0x34a540f8,
+0x3402021, 0xc002ba8, 0x240505c8, 0x3c020001,
+0x8c426ea8, 0x3c0d0001, 0x8dad6e88, 0x3c030001,
+0x8c636e84, 0x3c080001, 0x8d086e90, 0x3c090001,
+0x8d296eac, 0x3c0a0001, 0x8d4a6eb4, 0x3c0b0001,
+0x8d6b6ec4, 0x3c0c0001, 0x8d8c6e98, 0x3c040001,
+0x24845c94, 0x24050400, 0xaf42013c, 0x8f42013c,
+0x24060001, 0x24070001, 0xaf400000, 0xaf4d0138,
+0xaf430144, 0xaf480148, 0xaf49014c, 0xaf4a0150,
+0xaf4b0154, 0xaf4c0158, 0x2442ff80, 0xaf420140,
+0x24020001, 0xafa20010, 0xc002b3b, 0xafa00014,
+0x8f420138, 0xafa20010, 0x8f42013c, 0xafa20014,
+0x8f460144, 0x8f470148, 0x3c040001, 0x24845ca0,
+0xc002b3b, 0x24050500, 0xafb70010, 0xafba0014,
+0x8f46014c, 0x8f470150, 0x3c040001, 0x24845cac,
+0xc002b3b, 0x24050600, 0x3c020001, 0x8c426e9c,
+0x3603821, 0x3c060002, 0x24c69010, 0x2448ffff,
+0x1061824, 0xe81024, 0x43102b, 0x10400006,
+0x24050900, 0x3c040001, 0x24845cb8, 0xafa80010,
+0xc002b3b, 0xafa00014, 0x8f82000c, 0xafa20010,
+0x8f82003c, 0xafa20014, 0x8f860000, 0x8f870004,
+0x3c040001, 0x24845cc4, 0xc002b3b, 0x24051000,
+0x8c020220, 0x8c030224, 0x8c060218, 0x8c07021c,
+0x3c040001, 0x24845ccc, 0x24051100, 0xafa20010,
+0xc002b3b, 0xafa30014, 0xaf800054, 0xaf80011c,
+0x8c020218, 0x30420002, 0x10400009, 0x0,
+0x8c020220, 0x3c030002, 0x34630004, 0x431025,
+0xaf42000c, 0x8c02021c, 0x10000008, 0x34420004,
+0x8c020220, 0x3c030002, 0x34630006, 0x431025,
+0xaf42000c, 0x8c02021c, 0x34420006, 0xaf420014,
+0x8c020218, 0x30420010, 0x1040000a, 0x0,
+0x8c02021c, 0x34420004, 0xaf420010, 0x8c020220,
+0x3c03000a, 0x34630004, 0x431025, 0x10000009,
+0xaf420008, 0x8c020220, 0x3c03000a, 0x34630006,
+0x431025, 0xaf420008, 0x8c02021c, 0x34420006,
+0xaf420010, 0x24020001, 0xaf8200a0, 0xaf8200b0,
+0x8f830054, 0x8f820054, 0xaf8000d0, 0xaf8000c0,
+0x10000002, 0x24630064, 0x8f820054, 0x621023,
+0x2c420065, 0x1440fffc, 0x0, 0x8c040208,
+0x8c05020c, 0x26e20028, 0xaee20020, 0x24020490,
+0xaee20010, 0xaee40008, 0xaee5000c, 0x26e40008,
+0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094,
+0x8c820018, 0xaf8200b4, 0x9482000a, 0xaf82009c,
+0x8f420014, 0xaf8200b0, 0x8f8200b0, 0x30420004,
+0x1440fffd, 0x0, 0x8f8200b0, 0x3c03ef00,
+0x431024, 0x10400021, 0x0, 0x8f8200b4,
+0xafa20010, 0x8f820090, 0x8f830094, 0x3c040001,
+0x24845cd4, 0xafa30014, 0x8f8600b0, 0x8f87009c,
+0x3c050001, 0xc002b3b, 0x34a5200d, 0x3c040001,
+0x24845ce0, 0x240203c0, 0xafa20010, 0xafa00014,
+0x8f860144, 0x3c070001, 0x24e75ce8, 0xc002b3b,
+0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c,
+0x8f820220, 0x34420004, 0xaf820220, 0x8f820140,
+0x3c030001, 0x431025, 0xaf820140, 0x96e20472,
+0x96e60452, 0x96e70462, 0xafa20010, 0x96e20482,
+0x3c040001, 0x24845d14, 0x24051200, 0xc002b3b,
+0xafa20014, 0x96f00452, 0x32020001, 0x10400002,
+0xb021, 0x24160001, 0x32020002, 0x54400001,
+0x36d60002, 0x32020008, 0x54400001, 0x36d60004,
+0x32020010, 0x54400001, 0x36d60008, 0x32020020,
+0x54400001, 0x36d60010, 0x32020040, 0x54400001,
+0x36d60020, 0x32020080, 0x54400001, 0x36d60040,
+0x96e60482, 0x30c20200, 0x54400001, 0x36d64000,
+0x96e30472, 0x30620200, 0x10400003, 0x30620100,
+0x10000003, 0x36d62000, 0x54400001, 0x36d61000,
+0x96f00462, 0x32c24000, 0x14400004, 0x3207009b,
+0x30c2009b, 0x14e20007, 0x240e0001, 0x32c22000,
+0x1440000d, 0x32020001, 0x3062009b, 0x10e20009,
+0x240e0001, 0x3c040001, 0x24845d20, 0x24051300,
+0x2003821, 0xa3ae003f, 0xafa30010, 0xc002b3b,
+0xafa00014, 0x32020001, 0x54400001, 0x36d60080,
+0x32020002, 0x54400001, 0x36d60100, 0x32020008,
+0x54400001, 0x36d60200, 0x32020010, 0x54400001,
+0x36d60400, 0x32020080, 0x54400001, 0x36d60800,
+0x8c020218, 0x30420200, 0x10400002, 0x3c020008,
+0x2c2b025, 0x8c020218, 0x30420800, 0x10400002,
+0x3c020080, 0x2c2b025, 0x8c020218, 0x30420400,
+0x10400002, 0x3c020100, 0x2c2b025, 0x8c020218,
+0x30420100, 0x10400002, 0x3c020200, 0x2c2b025,
+0x8c020218, 0x30420080, 0x10400002, 0x3c020400,
+0x2c2b025, 0x8c020218, 0x30422000, 0x10400002,
+0x3c020010, 0x2c2b025, 0x8c020218, 0x30424000,
+0x10400002, 0x3c020020, 0x2c2b025, 0x8c020218,
+0x30421000, 0x10400002, 0x3c020040, 0x2c2b025,
+0x8ee20498, 0x8ee3049c, 0xaf420160, 0xaf430164,
+0x8ee204a0, 0x8ee304a4, 0xaf420168, 0xaf43016c,
+0x8ee204a8, 0x8ee304ac, 0xaf420170, 0xaf430174,
+0x8ee20428, 0x8ee3042c, 0xaf420178, 0xaf43017c,
+0x8ee20448, 0x8ee3044c, 0xaf420180, 0xaf430184,
+0x8ee20458, 0x8ee3045c, 0xaf420188, 0xaf43018c,
+0x8ee20468, 0x8ee3046c, 0xaf420190, 0xaf430194,
+0x8ee20478, 0x8ee3047c, 0xaf420198, 0xaf43019c,
+0x8ee20488, 0x8ee3048c, 0xaf4201a0, 0xaf4301a4,
+0x8ee204b0, 0x8ee304b4, 0x24040080, 0xaf4201a8,
+0xaf4301ac, 0xc002ba8, 0x24050080, 0x8c02025c,
+0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200,
+0x24060008, 0xc002bbf, 0xaf4201f8, 0x3c043b9a,
+0x3484ca00, 0x3821, 0x24020006, 0x24030002,
+0xaf4201f4, 0x240203e8, 0xaf430204, 0xaf430200,
+0xaf4401fc, 0xaf420294, 0x24020001, 0xaf430290,
+0xaf42029c, 0x3c030001, 0x671821, 0x90636cd8,
+0x3471021, 0x24e70001, 0xa043022c, 0x2ce2000f,
+0x1440fff8, 0x3471821, 0x24e70001, 0x3c080001,
+0x350840f8, 0x8f820040, 0x3c040001, 0x24845d2c,
+0x24051400, 0x21702, 0x24420030, 0xa062022c,
+0x3471021, 0xa040022c, 0x8c070218, 0x2c03021,
+0x240205c8, 0xafa20010, 0xc002b3b, 0xafa80014,
+0x3c040001, 0x24845d38, 0x3c050000, 0x24a55c80,
+0x24060010, 0x27b10030, 0x2203821, 0x27b30034,
+0xc0017a3, 0xafb30010, 0x3c030001, 0x8c636cc8,
+0x1060000a, 0x408021, 0x8fa30030, 0x2405ff00,
+0x8fa20034, 0x246400ff, 0x852024, 0x831823,
+0x431023, 0xafa20034, 0xafa40030, 0x3c040001,
+0x24845d44, 0x3c050000, 0x24a54100, 0x24060108,
+0x2203821, 0xc0017a3, 0xafb30010, 0x409021,
+0x32c20003, 0x3c010001, 0xac326e80, 0x10400045,
+0x2203821, 0x8f820050, 0x3c030010, 0x431024,
+0x10400016, 0x0, 0x8c020218, 0x30420040,
+0x1040000f, 0x24020001, 0x8f820050, 0x8c030218,
+0x240e0001, 0x3c040001, 0x24845d50, 0xa3ae003f,
+0xafa20010, 0xafa30014, 0x8f870040, 0x24051500,
+0xc002b3b, 0x2c03021, 0x10000004, 0x0,
+0x3c010001, 0x370821, 0xa02240f4, 0x3c040001,
+0x24845d5c, 0x3c050001, 0x24a55b40, 0x3c060001,
+0x24c65bac, 0xc53023, 0x8f420010, 0x27b30030,
+0x2603821, 0x27b10034, 0x34420a00, 0xaf420010,
+0xc0017a3, 0xafb10010, 0x3c040001, 0x24845d70,
+0x3c050001, 0x24a5b714, 0x3c060001, 0x24c6ba90,
+0xc53023, 0x2603821, 0xaf420108, 0xc0017a3,
+0xafb10010, 0x3c040001, 0x24845d8c, 0x3c050001,
+0x24a5be58, 0x3c060001, 0x24c6c900, 0xc53023,
+0x2603821, 0x3c010001, 0xac226ef4, 0xc0017a3,
+0xafb10010, 0x3c040001, 0x24845da4, 0x10000024,
+0x24051600, 0x3c040001, 0x24845dac, 0x3c050001,
+0x24a5a10c, 0x3c060001, 0x24c6a238, 0xc53023,
+0xc0017a3, 0xafb30010, 0x3c040001, 0x24845dbc,
+0x3c050001, 0x24a5b2b0, 0x3c060001, 0x24c6b70c,
+0xc53023, 0x2203821, 0xaf420108, 0xc0017a3,
+0xafb30010, 0x3c040001, 0x24845dd0, 0x3c050001,
+0x24a5ba98, 0x3c060001, 0x24c6be50, 0xc53023,
+0x2203821, 0x3c010001, 0xac226ef4, 0xc0017a3,
+0xafb30010, 0x3c040001, 0x24845de4, 0x24051650,
+0x2c03021, 0x3821, 0x3c010001, 0xac226ef8,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x32c20020,
+0x10400021, 0x27a70030, 0x3c040001, 0x24845df0,
+0x3c050001, 0x24a5b13c, 0x3c060001, 0x24c6b2a8,
+0xc53023, 0x24022000, 0xaf42001c, 0x27a20034,
+0xc0017a3, 0xafa20010, 0x21900, 0x31982,
+0x3c040800, 0x641825, 0xae430028, 0x24030010,
+0xaf43003c, 0x96e30450, 0xaf430040, 0x8f430040,
+0x3c040001, 0x24845e04, 0xafa00014, 0xafa30010,
+0x8f47001c, 0x24051660, 0x3c010001, 0xac226ef0,
+0x10000025, 0x32c60020, 0x8ee20448, 0x8ee3044c,
+0xaf43001c, 0x8f42001c, 0x2442e000, 0x2c422001,
+0x1440000a, 0x240e0001, 0x3c040001, 0x24845e10,
+0xa3ae003f, 0xafa00010, 0xafa00014, 0x8f46001c,
+0x24051700, 0xc002b3b, 0x3821, 0x3c020000,
+0x24425cbc, 0x21100, 0x21182, 0x3c030800,
+0x431025, 0xae420028, 0x24020008, 0xaf42003c,
+0x96e20450, 0xaf420040, 0x8f420040, 0x3c040001,
+0x24845e1c, 0xafa00014, 0xafa20010, 0x8f47001c,
+0x24051800, 0x32c60020, 0xc002b3b, 0x0,
+0x3c050fff, 0x3c030001, 0x8c636ef4, 0x34a5ffff,
+0x2403021, 0x3c020001, 0x8c426ef8, 0x3c040800,
+0x651824, 0x31882, 0x641825, 0x451024,
+0x21082, 0x441025, 0xacc20080, 0x32c20180,
+0x10400056, 0xacc30020, 0x8f82005c, 0x3c030080,
+0x431024, 0x1040000d, 0x0, 0x8f820050,
+0xafa20010, 0x8f82005c, 0x240e0001, 0x3c040001,
+0x24845e28, 0xa3ae003f, 0xafa20014, 0x8f870040,
+0x24051900, 0xc002b3b, 0x2c03021, 0x8f820050,
+0x3c030010, 0x431024, 0x10400016, 0x0,
+0x8c020218, 0x30420040, 0x1040000f, 0x24020001,
+0x8f820050, 0x8c030218, 0x240e0001, 0x3c040001,
+0x24845d50, 0xa3ae003f, 0xafa20010, 0xafa30014,
+0x8f870040, 0x24052000, 0xc002b3b, 0x2c03021,
+0x10000004, 0x0, 0x3c010001, 0x370821,
+0xa02240f4, 0x3c040001, 0x24845e34, 0x3c050001,
+0x24a55ac0, 0x3c060001, 0x24c65b38, 0xc53023,
+0x8f420008, 0x27b30030, 0x2603821, 0x27b10034,
+0x34420e00, 0xaf420008, 0xc0017a3, 0xafb10010,
+0x3c040001, 0x24845e4c, 0x3c050001, 0x24a5d8b4,
+0x3c060001, 0x24c6e3c8, 0xc53023, 0x2603821,
+0xaf42010c, 0xc0017a3, 0xafb10010, 0x3c040001,
+0x24845e64, 0x3c050001, 0x24a5e9ac, 0x3c060001,
+0x24c6f0f0, 0xc53023, 0x2603821, 0x3c010001,
+0xac226f04, 0xc0017a3, 0xafb10010, 0x3c040001,
+0x24845e7c, 0x10000027, 0x24052100, 0x3c040001,
+0x24845e84, 0x3c050001, 0x24a59fc8, 0x3c060001,
+0x24c6a104, 0xc53023, 0x27b10030, 0x2203821,
+0x27b30034, 0xc0017a3, 0xafb30010, 0x3c040001,
+0x24845e94, 0x3c050001, 0x24a5cad4, 0x3c060001,
+0x24c6d8ac, 0xc53023, 0x2203821, 0xaf42010c,
+0xc0017a3, 0xafb30010, 0x3c040001, 0x24845ea4,
+0x3c050001, 0x24a5e84c, 0x3c060001, 0x24c6e9a4,
+0xc53023, 0x2203821, 0x3c010001, 0xac226f04,
+0xc0017a3, 0xafb30010, 0x3c040001, 0x24845eb8,
+0x24052150, 0x2c03021, 0x3821, 0x3c010001,
+0xac226f10, 0xafa00010, 0xc002b3b, 0xafa00014,
+0x3c110fff, 0x3c030001, 0x8c636f04, 0x3631ffff,
+0x2409821, 0x3c020001, 0x8c426f10, 0x3c0e0800,
+0x711824, 0x31882, 0x6e1825, 0x511024,
+0x21082, 0x4e1025, 0xae630038, 0xae620078,
+0x8c020218, 0x30420040, 0x14400004, 0x24020001,
+0x3c010001, 0x370821, 0xa02240f4, 0x3c040001,
+0x24845ec4, 0x3c050001, 0x24a5e3d0, 0x3c060001,
+0x24c6e52c, 0xc53023, 0x27be0030, 0x3c03821,
+0x27b50034, 0xc0017a3, 0xafb50010, 0x3c010001,
+0xac226efc, 0x511024, 0x21082, 0x3c0e0800,
+0x4e1025, 0xae620050, 0x32c22000, 0x10400006,
+0x3c03821, 0x3c020000, 0x24425cbc, 0x2221024,
+0x1000000f, 0x21082, 0x3c040001, 0x24845ed8,
+0x3c050001, 0x24a5e534, 0x3c060001, 0x24c6e6e4,
+0xc53023, 0xc0017a3, 0xafb50010, 0x3c010001,
+0xac226f14, 0x511024, 0x21082, 0x3c0e0800,
+0x4e1025, 0xae620048, 0x32c24000, 0x10400005,
+0x27a70030, 0x3c020000, 0x24425cbc, 0x1000000e,
+0x21100, 0x3c040001, 0x24845ef0, 0x3c050001,
+0x24a5e6ec, 0x3c060001, 0x24c6e844, 0xc53023,
+0x27a20034, 0xc0017a3, 0xafa20010, 0x3c010001,
+0xac226f08, 0x21100, 0x21182, 0x3c030800,
+0x431025, 0xae420060, 0x3c040001, 0x24845f08,
+0x3c050001, 0x24a58230, 0x3c060001, 0x24c68650,
+0xc53023, 0x27b10030, 0x2203821, 0x27b30034,
+0xc0017a3, 0xafb30010, 0x3c0e0fff, 0x35ceffff,
+0x3c040001, 0x24845f14, 0x3c050000, 0x24a56468,
+0x3c060000, 0x24c66588, 0xc53023, 0x2203821,
+0x240f021, 0x3c010001, 0xac226edc, 0x4e1024,
+0x21082, 0x3c150800, 0x551025, 0xafae0044,
+0xafc200b8, 0xc0017a3, 0xafb30010, 0x3c040001,
+0x24845f20, 0x3c050000, 0x24a56590, 0x3c060000,
+0x24c66808, 0x8fae0044, 0xc53023, 0x2203821,
+0x3c010001, 0xac226ed0, 0x4e1024, 0x21082,
+0x551025, 0xafc200e8, 0xc0017a3, 0xafb30010,
+0x3c040001, 0x24845f38, 0x3c050000, 0x24a56810,
+0x3c060000, 0x24c66940, 0x8fae0044, 0xc53023,
+0x2203821, 0x3c010001, 0xac226ec8, 0x4e1024,
+0x21082, 0x551025, 0xafc200c0, 0xc0017a3,
+0xafb30010, 0x3c040001, 0x24845f50, 0x3c050001,
+0x24a5fad0, 0x3c060001, 0x24c6fba8, 0x8fae0044,
+0xc53023, 0x2203821, 0x3c010001, 0xac226ed4,
+0x4e1024, 0x21082, 0x551025, 0xafc200c8,
+0xc0017a3, 0xafb30010, 0x3c040001, 0x24845f5c,
+0x3c050001, 0x24a5c93c, 0x3c060001, 0x24c6ca20,
+0xc53023, 0x2203821, 0xaf420110, 0xc0017a3,
+0xafb30010, 0x3c040001, 0x24845f6c, 0x3c050001,
+0x24a5c910, 0x3c060001, 0x24c6c934, 0xc53023,
+0x2203821, 0xaf420124, 0xc0017a3, 0xafb30010,
+0x3c040001, 0x24845f7c, 0x3c050001, 0x24a55a80,
+0x3c060001, 0x24c65aac, 0xc53023, 0x2203821,
+0xaf420120, 0xaf420114, 0xc0017a3, 0xafb30010,
+0x3c040001, 0x24845f88, 0x3c050001, 0x24a5f298,
+0x3c060001, 0x24c6f6b4, 0xc53023, 0x2203821,
+0xaf420118, 0xc0017a3, 0xafb30010, 0x8fae0044,
+0x3c010001, 0xac226f18, 0x4e1024, 0x21082,
+0x551025, 0xc003fc3, 0xafc200d0, 0xc003c40,
+0x0, 0xc0027a8, 0x0, 0xac000228,
+0xac00022c, 0x96e20450, 0x2442ffff, 0xaf420038,
+0x96e20460, 0xaf420080, 0x32c24000, 0x14400003,
+0x0, 0x96e20480, 0xaf420084, 0x96e70490,
+0x50e00001, 0x24070800, 0x24e2ffff, 0xaf420088,
+0xaf42007c, 0x24020800, 0x10e2000f, 0x32c24000,
+0x10400003, 0x24020400, 0x10e2000b, 0x0,
+0x240e0001, 0x3c040001, 0x24845f98, 0xa3ae003f,
+0x96e60490, 0x24052170, 0x2c03821, 0xafa00010,
+0xc002b3b, 0xafa00014, 0x8f430138, 0x8f440138,
+0x24020001, 0xa34205c2, 0xaf430094, 0xaf440098,
+0xafa00010, 0xafa00014, 0x8f460080, 0x8f470084,
+0x3c040001, 0x24845fa4, 0xc002b3b, 0x24052200,
+0xc0024a4, 0x3c110800, 0x3c1433d8, 0x3694cb58,
+0x3c020800, 0x34420080, 0x3c040001, 0x24845fb0,
+0x3c050000, 0x24a55d00, 0x3c060000, 0x24c65d1c,
+0xc53023, 0x27a70030, 0xaf820060, 0x2402ffff,
+0xaf820064, 0x27a20034, 0xc0017a3, 0xafa20010,
+0x3c010001, 0xac226eb8, 0x21100, 0x21182,
+0x511025, 0xc0018fc, 0xae420000, 0x8f820240,
+0x3c030001, 0x431025, 0xaf820240, 0x3c020000,
+0x24424034, 0xaf820244, 0xaf800240, 0x8f820060,
+0x511024, 0x14400005, 0x3c030800, 0x8f820060,
+0x431024, 0x1040fffd, 0x0, 0xc003c4d,
+0x8821, 0x3c020100, 0xafa20020, 0x8f530018,
+0x240200ff, 0x56620001, 0x26710001, 0x8c020228,
+0x1622000e, 0x1330c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x24845c24, 0x3c050009, 0xafa00014, 0xafa20010,
+0x8fa60020, 0x1000003f, 0x34a50100, 0xd71021,
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
+0xc01821, 0x8f440178, 0x8f45017c, 0x1021,
+0x24070004, 0xafa70010, 0xafb10014, 0x8f48000c,
+0x24c604c0, 0x2e63021, 0xafa80018, 0x8f48010c,
+0x24070008, 0xa32821, 0xa3482b, 0x822021,
+0x100f809, 0x892021, 0x1440000b, 0x24070008,
+0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001,
+0x24845c2c, 0x3c050009, 0xafa20014, 0x8fa60020,
+0x1000001c, 0x34a50200, 0x8f440160, 0x8f450164,
+0x8f43000c, 0xaf510018, 0x8f860120, 0x24020010,
+0xafa20010, 0xafb10014, 0xafa30018, 0x8f42010c,
+0x40f809, 0x24c6001c, 0x14400010, 0x0,
+0x8f420340, 0x24420001, 0xaf420340, 0x8f420340,
+0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001,
+0x24845c34, 0x3c050009, 0xafa20014, 0x8fa60020,
+0x34a50300, 0xc002b3b, 0x2603821, 0x8f4202e4,
+0x24420001, 0xaf4202e4, 0x8f4202e4, 0x93a2003f,
+0x10400069, 0x3c020700, 0x34423000, 0xafa20028,
+0x8f530018, 0x240200ff, 0x12620002, 0x8821,
+0x26710001, 0x8c020228, 0x1622000e, 0x1330c0,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x24845c24, 0x3c050009,
+0xafa00014, 0xafa20010, 0x8fa60028, 0x1000003f,
+0x34a50100, 0xd71021, 0x8fa30028, 0x8fa4002c,
+0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
+0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
+0xafb10014, 0x8f48000c, 0x24c604c0, 0x2e63021,
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24845c2c, 0x3c050009,
+0xafa20014, 0x8fa60028, 0x1000001c, 0x34a50200,
+0x8f440160, 0x8f450164, 0x8f43000c, 0xaf510018,
+0x8f860120, 0x24020010, 0xafa20010, 0xafb10014,
+0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x14400010, 0x0, 0x8f420340, 0x24420001,
+0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24845c34, 0x3c050009,
+0xafa20014, 0x8fa60028, 0x34a50300, 0xc002b3b,
+0x2603821, 0x8f4202f0, 0x24420001, 0xaf4202f0,
+0x8f4202f0, 0x3c040001, 0x24845fc0, 0xafa00010,
+0xafa00014, 0x8fa60028, 0x24052300, 0xc002b3b,
+0x3821, 0x10000004, 0x0, 0x8c020264,
+0x10400005, 0x0, 0x8f8200a0, 0x30420004,
+0x1440fffa, 0x0, 0x8f820044, 0x34420004,
+0xaf820044, 0x8f420308, 0x24420001, 0xaf420308,
+0x8f420308, 0x8f8200d8, 0x8f8300d4, 0x431023,
+0x2442ff80, 0xaf420090, 0x8f420090, 0x2842ff81,
+0x10400006, 0x24020001, 0x8f420090, 0x8f430144,
+0x431021, 0xaf420090, 0x24020001, 0xaf42008c,
+0x32c20008, 0x10400006, 0x0, 0x8f820214,
+0x3c038100, 0x3042ffff, 0x431025, 0xaf820214,
+0x3c030001, 0x8c636d94, 0x30620002, 0x10400009,
+0x30620001, 0x3c040001, 0x24845fcc, 0x3c050000,
+0x24a56d50, 0x3c060000, 0x24c671c8, 0x10000012,
+0xc53023, 0x10400009, 0x0, 0x3c040001,
+0x24845fdc, 0x3c050000, 0x24a571d0, 0x3c060000,
+0x24c67678, 0x10000008, 0xc53023, 0x3c040001,
+0x24845fec, 0x3c050000, 0x24a56948, 0x3c060000,
+0x24c66d48, 0xc53023, 0x27a70030, 0x27a20034,
+0xc0017a3, 0xafa20010, 0x3c010001, 0xac226ecc,
+0x3c020001, 0x8c426ecc, 0x3c030800, 0x21100,
+0x21182, 0x431025, 0xae420040, 0x8f8200a0,
+0xafa20010, 0x8f8200b0, 0xafa20014, 0x8f86005c,
+0x8f87011c, 0x3c040001, 0x24845ffc, 0x3c010001,
+0xac366ea4, 0x3c010001, 0xac206e94, 0x3c010001,
+0xac3c6e8c, 0x3c010001, 0xac3b6ebc, 0x3c010001,
+0xac376ec0, 0x3c010001, 0xac3a6ea0, 0xc002b3b,
+0x24052400, 0x8f820200, 0xafa20010, 0x8f820220,
+0xafa20014, 0x8f860044, 0x8f870050, 0x3c040001,
+0x24846008, 0xc002b3b, 0x24052500, 0x8f830060,
+0x74100b, 0x242000a, 0x200f821, 0x0,
+0xd, 0x8fbf0060, 0x8fbe005c, 0x8fb50058,
+0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048,
+0x3e00008, 0x27bd0068, 0x27bdffe0, 0x3c040001,
+0x24846014, 0x24052600, 0x3021, 0x3821,
+0xafbf0018, 0xafa00010, 0xc002b3b, 0xafa00014,
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008,
+0x0, 0x3e00008, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x3e00008, 0x0, 0x3e00008, 0x0,
+0x27bdfde0, 0x27a50018, 0x3c04dead, 0x3484beef,
+0xafbf0218, 0x8f820150, 0x3c03001f, 0x3463ffff,
+0xafa40018, 0xa22823, 0xa32824, 0x8ca20000,
+0x1044000a, 0x0, 0xafa50010, 0x8ca20000,
+0xafa20014, 0x8f860150, 0x8f870250, 0x3c040001,
+0x2484601c, 0xc002b3b, 0x24052700, 0x8fbf0218,
+0x3e00008, 0x27bd0220, 0x27bdffe0, 0x3c06abba,
+0x34c6babe, 0xafb00018, 0x3c100004, 0x3c07007f,
+0x34e7ffff, 0xafbf001c, 0x102840, 0x8e040000,
+0x8ca30000, 0xaca00000, 0xae060000, 0x8ca20000,
+0xaca30000, 0x10460005, 0xae040000, 0xa08021,
+0xf0102b, 0x1040fff5, 0x102840, 0x3c040001,
+0x24846028, 0x24052800, 0x2003021, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x2001021,
+0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020,
+0x8c020224, 0x3047003f, 0x10e00010, 0x803021,
+0x2821, 0x24030020, 0xe31024, 0x10400002,
+0x63042, 0xa62821, 0x31842, 0x1460fffb,
+0xe31024, 0x2402f000, 0xa22824, 0x3402ffff,
+0x45102b, 0x14400003, 0x3c020001, 0x10000008,
+0x3c020001, 0x3442ffff, 0x851823, 0x43102b,
+0x14400003, 0xa01021, 0x3c02fffe, 0x821021,
+0x3e00008, 0x0, 0x27bdffd0, 0xafb50028,
+0x8fb50040, 0xafb20020, 0xa09021, 0xafb1001c,
+0x24c60003, 0xafbf002c, 0xafb30024, 0xafb00018,
+0x8ea20000, 0x2403fffc, 0xc38024, 0x50102b,
+0x1440001b, 0xe08821, 0x8e330000, 0xafb00010,
+0x8ea20000, 0xafa20014, 0x8e270000, 0x24053000,
+0xc002b3b, 0x2403021, 0x8e230000, 0x702021,
+0x64102b, 0x10400007, 0x2402821, 0x8ca20000,
+0xac620000, 0x24630004, 0x64102b, 0x1440fffb,
+0x24a50004, 0x8ea20000, 0x501023, 0xaea20000,
+0x8e220000, 0x501021, 0x1000000b, 0xae220000,
+0x2402002d, 0xa0820000, 0xafb00010, 0x8ea20000,
+0x2409821, 0xafa20014, 0x8e270000, 0x24053100,
+0xc002b3b, 0x2603021, 0x2601021, 0x8fbf002c,
+0x8fb50028, 0x8fb30024, 0x8fb20020, 0x8fb1001c,
+0x8fb00018, 0x3e00008, 0x27bd0030, 0x27bdffe8,
+0x3c1cc000, 0x3c05fffe, 0x3c030001, 0x8c636e84,
+0x3c040001, 0x8c846e90, 0x34a5bf08, 0x24021ffc,
+0x3c010001, 0xac226cd0, 0x3c0200c0, 0x3c010001,
+0xac226cd4, 0x3c020020, 0xafbf0010, 0x3c0100c0,
+0xac201ffc, 0x431023, 0x441023, 0x245bb000,
+0x365b821, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021,
+0x3c0400c0, 0x34840200, 0x3c1a00c0, 0x3c0300c0,
+0x346307c8, 0x24021dfc, 0x3c010001, 0xac226cd0,
+0x24021834, 0x3c010001, 0xac246cd4, 0x3c010001,
+0xac226cd0, 0x3c010001, 0xac236cd4, 0xc00180d,
+0x375a0200, 0x8fbf0010, 0x3e00008, 0x27bd0018,
+0x27bdffc8, 0x3c040001, 0x24846034, 0x24053200,
+0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4,
+0x3021, 0x3603821, 0xafbf0030, 0xafb3002c,
+0xafb20028, 0xafb10024, 0xafb00020, 0xafa2001c,
+0xafa30018, 0xafb70010, 0xc002b3b, 0xafba0014,
+0xc001916, 0x0, 0x8f820240, 0x34420004,
+0xaf820240, 0x24020001, 0xaf420000, 0x3c020001,
+0x571021, 0x904240f4, 0x10400092, 0x2403fffc,
+0x3c100001, 0x2610ac73, 0x3c120001, 0x2652a84c,
+0x2121023, 0x438024, 0x8fa3001c, 0x3c040001,
+0x24846040, 0x70102b, 0x1440001a, 0x27b30018,
+0x8fb10018, 0x24053000, 0x2403021, 0xafb00010,
+0xafa30014, 0xc002b3b, 0x2203821, 0x8fa30018,
+0x702021, 0x64102b, 0x10400007, 0x2403021,
+0x8cc20000, 0xac620000, 0x24630004, 0x64102b,
+0x1440fffb, 0x24c60004, 0x8fa2001c, 0x501023,
+0xafa2001c, 0x8e620000, 0x501021, 0x1000000a,
+0xae620000, 0x2408821, 0x24053100, 0xafb00010,
+0xafa30014, 0x8fa70018, 0x2203021, 0x2402002d,
+0xc002b3b, 0xa0820000, 0x24070020, 0x8fa3001c,
+0x3c040001, 0x2484605c, 0x24120020, 0x3c010001,
+0xac316eb0, 0x2c620020, 0x1440001d, 0x27b10018,
+0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f50,
+0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821,
+0x8fa30018, 0x3c040001, 0x24846f50, 0x24650020,
+0x65102b, 0x10400007, 0x0, 0x8c820000,
+0xac620000, 0x24630004, 0x65102b, 0x1440fffb,
+0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c,
+0x8e220000, 0x521021, 0x1000000b, 0xae220000,
+0x3c100001, 0x26106f50, 0x24053100, 0xafa70010,
+0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d,
+0xc002b3b, 0xa0820000, 0x24070020, 0x3c040001,
+0x24846070, 0x8fa3001c, 0x24120020, 0x3c010001,
+0xac306ee4, 0x2c620020, 0x1440001d, 0x27b10018,
+0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f70,
+0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821,
+0x8fa30018, 0x3c040001, 0x24846f70, 0x24650020,
+0x65102b, 0x10400007, 0x0, 0x8c820000,
+0xac620000, 0x24630004, 0x65102b, 0x1440fffb,
+0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c,
+0x8e220000, 0x521021, 0x1000000b, 0xae220000,
+0x3c100001, 0x26106f70, 0x24053100, 0xafa70010,
+0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d,
+0xc002b3b, 0xa0820000, 0x3c010001, 0x10000031,
+0xac306ee0, 0x3c100001, 0x2610821f, 0x3c120001,
+0x2652809c, 0x2121023, 0x438024, 0x8fa3001c,
+0x3c040001, 0x24846084, 0x70102b, 0x1440001a,
+0x27b30018, 0x8fb10018, 0x24053000, 0x2403021,
+0xafb00010, 0xafa30014, 0xc002b3b, 0x2203821,
+0x8fa30018, 0x702021, 0x64102b, 0x10400007,
+0x2403021, 0x8cc20000, 0xac620000, 0x24630004,
+0x64102b, 0x1440fffb, 0x24c60004, 0x8fa2001c,
+0x501023, 0xafa2001c, 0x8e620000, 0x501021,
+0x1000000a, 0xae620000, 0x2408821, 0x24053100,
+0xafb00010, 0xafa30014, 0x8fa70018, 0x2203021,
+0x2402002d, 0xc002b3b, 0xa0820000, 0x3c010001,
+0xac316eb0, 0x3c030001, 0x8c636eb0, 0x24020400,
+0x60f809, 0xaf820070, 0x8fbf0030, 0x8fb3002c,
+0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008,
+0x27bd0038, 0x0, 0x0, 0x8f820040,
+0x3c03f000, 0x431024, 0x3c036000, 0x14430006,
+0x0, 0x8f820050, 0x2403ff80, 0x431024,
+0x34420055, 0xaf820050, 0x8f820054, 0x244203e8,
+0xaf820058, 0x240201f4, 0xaf4200e0, 0x24020004,
+0xaf4200e8, 0x24020002, 0xaf4001b0, 0xaf4000e4,
+0xaf4200dc, 0xaf4000d8, 0xaf4000d4, 0x3e00008,
+0xaf4000d0, 0x8f820054, 0x24420005, 0x3e00008,
+0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054,
+0x244203e8, 0xaf820058, 0x3c020800, 0x2c21024,
+0x10400004, 0x3c02f7ff, 0x3442ffff, 0x2c2b024,
+0x36940040, 0x3c020001, 0x8c426da8, 0x10400017,
+0x3c020200, 0x3c030001, 0x8c636f1c, 0x10600016,
+0x282a025, 0x3c020001, 0x8c426e44, 0x14400012,
+0x3c020200, 0x3c020001, 0x8c426d94, 0x30420003,
+0x1440000d, 0x3c020200, 0x8f830224, 0x3c020002,
+0x8c428fec, 0x10620008, 0x3c020200, 0xc003daf,
+0x0, 0x10000004, 0x3c020200, 0xc004196,
+0x0, 0x3c020200, 0x2c21024, 0x10400003,
+0x0, 0xc001f4b, 0x0, 0x8f4200d8,
+0x8f4300dc, 0x24420001, 0xaf4200d8, 0x43102b,
+0x14400003, 0x0, 0xaf4000d8, 0x36940080,
+0x8c030238, 0x1060000c, 0x0, 0x8f4201b0,
+0x244203e8, 0xaf4201b0, 0x43102b, 0x14400006,
+0x0, 0x934205c5, 0x14400003, 0x0,
+0xc001da0, 0x0, 0x8fbf0010, 0x3e00008,
+0x27bd0018, 0x3e00008, 0x0, 0x27bdffd8,
+0xafbf0020, 0x8f43002c, 0x8f420038, 0x10620059,
+0x0, 0x3c020001, 0x571021, 0x904240f0,
+0x10400026, 0x24070008, 0x8f440170, 0x8f450174,
+0x8f48000c, 0x8f860120, 0x24020020, 0xafa20010,
+0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809,
+0x24c6001c, 0x14400011, 0x24020001, 0x3c010001,
+0x370821, 0xa02240f0, 0x8f820124, 0xafa20010,
+0x8f820128, 0x3c040001, 0x24846128, 0xafa20014,
+0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b,
+0x34a50900, 0x1000005c, 0x0, 0x8f420300,
+0x24420001, 0xaf420300, 0x8f420300, 0x8f42002c,
+0xa34005c1, 0x10000027, 0xaf420038, 0x8f440170,
+0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
+0x24020080, 0xafa20010, 0xafa30014, 0xafa80018,
+0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
+0x24020001, 0x3c010001, 0x370821, 0xa02240f1,
+0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
+0x24846134, 0xafa20014, 0x8f46002c, 0x8f870120,
+0x3c050009, 0xc002b3b, 0x34a51100, 0x10000036,
+0x0, 0x8f420300, 0x8f43002c, 0x24420001,
+0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1,
+0xaf430038, 0x3c010001, 0x370821, 0xa02040f1,
+0x3c010001, 0x370821, 0xa02040f0, 0x10000026,
+0xaf400034, 0x934205c1, 0x1040001d, 0x0,
+0xa34005c1, 0x8f820040, 0x30420001, 0x14400008,
+0x2021, 0x8c030104, 0x24020001, 0x50620005,
+0x24040001, 0x8c020264, 0x10400003, 0x801021,
+0x24040001, 0x801021, 0x10400006, 0x0,
+0x8f42030c, 0x24420001, 0xaf42030c, 0x10000008,
+0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044,
+0x8f420308, 0x24420001, 0xaf420308, 0x8f420308,
+0x3c010001, 0x370821, 0xa02040f0, 0x3c010001,
+0x370821, 0xa02040f1, 0x8f420000, 0x10400007,
+0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
+0x0, 0x10000005, 0x0, 0xaf800048,
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
+0x3c03ff7f, 0x3463ffff, 0x431024, 0xaf820060,
+0x8f420000, 0x10400003, 0x0, 0x10000002,
+0xaf80004c, 0xaf800048, 0x8fbf0020, 0x3e00008,
+0x27bd0028, 0x3e00008, 0x0, 0x27bdffd8,
+0xafbf0020, 0x8f430044, 0x8f42007c, 0x10620029,
+0x24070008, 0x8f440168, 0x8f45016c, 0x8f48000c,
+0x8f860120, 0x24020040, 0xafa20010, 0xafa30014,
+0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x14400011, 0x24020001, 0x3c010001, 0x370821,
+0xa02240f2, 0x8f820124, 0xafa20010, 0x8f820128,
+0x3c040001, 0x2484613c, 0xafa20014, 0x8f460044,
+0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51300,
+0x1000000f, 0x0, 0x8f420304, 0x24420001,
+0xaf420304, 0x8f420304, 0x8f420044, 0xaf42007c,
+0x3c010001, 0x370821, 0xa02040f2, 0x10000004,
+0xaf400078, 0x3c010001, 0x370821, 0xa02040f2,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x3c03feff, 0x3463ffff,
+0x431024, 0xaf820060, 0x8f420000, 0x10400003,
+0x0, 0x10000002, 0xaf80004c, 0xaf800048,
+0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008,
+0x0, 0x3c020001, 0x8c426da8, 0x27bdffa8,
+0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044,
+0xafb20040, 0xafb1003c, 0xafb00038, 0x104000d5,
+0x8f900044, 0x8f4200d0, 0x24430001, 0x2842000b,
+0x144000e4, 0xaf4300d0, 0x8f420004, 0x30420002,
+0x1440009c, 0xaf4000d0, 0x8f420004, 0x3c030001,
+0x8c636d98, 0x34420002, 0xaf420004, 0x24020001,
+0x14620003, 0x3c020600, 0x10000002, 0x34423000,
+0x34421000, 0xafa20020, 0x8f4a0018, 0xafaa0034,
+0x27aa0020, 0xafaa002c, 0x8faa0034, 0x240200ff,
+0x11420002, 0x1821, 0x25430001, 0x8c020228,
+0x609821, 0x1662000e, 0x3c050009, 0x8f42033c,
+0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228,
+0x8fa70034, 0x3c040001, 0x2484610c, 0xafa00014,
+0xafa20010, 0x8fa60020, 0x10000070, 0x34a50500,
+0x8faa0034, 0xa38c0, 0xf71021, 0x8fa30020,
+0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054,
+0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9,
+0x1040001b, 0xa821, 0xe09021, 0x265e04c0,
+0x8f440178, 0x8f45017c, 0x2401821, 0x240a0004,
+0xafaa0010, 0xafb30014, 0x8f48000c, 0x1021,
+0x2fe3021, 0xafa80018, 0x8f48010c, 0x24070008,
+0xa32821, 0xa3482b, 0x822021, 0x100f809,
+0x892021, 0x54400006, 0x24150001, 0x8f820054,
+0x2221023, 0x2c4203e9, 0x1440ffe9, 0x0,
+0x32a200ff, 0x54400018, 0xaf530018, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
+0x8faa002c, 0x8fa70034, 0xafa20010, 0x8f820124,
+0x3c040001, 0x24846118, 0xafa20014, 0x8d460000,
+0x3c050009, 0x10000035, 0x34a50600, 0x8f420308,
+0x24150001, 0x24420001, 0xaf420308, 0x8f420308,
+0x1000001e, 0x32a200ff, 0x8f830054, 0x8f820054,
+0x247103e8, 0x2221023, 0x2c4203e9, 0x10400016,
+0xa821, 0x3c1e0020, 0x24120010, 0x8f42000c,
+0x8f440160, 0x8f450164, 0x8f860120, 0xafb20010,
+0xafb30014, 0x5e1025, 0xafa20018, 0x8f42010c,
+0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3,
+0x0, 0x8f820054, 0x2221023, 0x2c4203e9,
+0x1440ffee, 0x0, 0x32a200ff, 0x14400011,
+0x3c050009, 0x8f420378, 0x24420001, 0xaf420378,
+0x8f420378, 0x8f820120, 0x8faa002c, 0x8fa70034,
+0xafa20010, 0x8f820124, 0x3c040001, 0x24846120,
+0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b,
+0x0, 0x8f4202ec, 0x24420001, 0xaf4202ec,
+0x8f4202ec, 0x8f420004, 0x30420001, 0x50400029,
+0x36100040, 0x3c020400, 0x2c21024, 0x10400013,
+0x2404ffdf, 0x8f420250, 0x8f430254, 0x8f4401b4,
+0x14640006, 0x36100040, 0x8f420270, 0x8f430274,
+0x8f4401b8, 0x10640007, 0x2402ffdf, 0x8f420250,
+0x8f430254, 0x8f440270, 0x8f450274, 0x10000012,
+0x3a100020, 0x1000002b, 0x2028024, 0x8f420250,
+0x8f430254, 0x8f4501b4, 0x14650006, 0x2048024,
+0x8f420270, 0x8f430274, 0x8f4401b8, 0x50640021,
+0x36100040, 0x8f420250, 0x8f430254, 0x8f440270,
+0x8f450274, 0x3a100040, 0xaf4301b4, 0x10000019,
+0xaf4501b8, 0x8f4200d4, 0x24430001, 0x10000011,
+0x28420033, 0x8f420004, 0x30420001, 0x10400009,
+0x3c020400, 0x2c21024, 0x10400004, 0x2402ffdf,
+0x2028024, 0x1000000b, 0x36100040, 0x10000009,
+0x36100060, 0x8f4200d4, 0x36100040, 0x24430001,
+0x284201f5, 0x14400003, 0xaf4300d4, 0xaf4000d4,
+0x3a100020, 0xaf900044, 0x2402ff7f, 0x282a024,
+0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044,
+0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008,
+0x27bd0058, 0x3e00008, 0x0, 0x3c020001,
+0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
+0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
+0x104000c7, 0xafb00030, 0x8f4200d0, 0x24430001,
+0x2842000b, 0x144000da, 0xaf4300d0, 0x8f420004,
+0x30420002, 0x14400097, 0xaf4000d0, 0x8f420004,
+0x3c030001, 0x8c636d98, 0x34420002, 0xaf420004,
+0x24020001, 0x14620003, 0x3c020600, 0x10000002,
+0x34423000, 0x34421000, 0xafa20020, 0x1821,
+0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
+0xafaa002c, 0x27c30001, 0x8c020228, 0x609021,
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010,
+0x8fa60020, 0x1000006d, 0x34a50500, 0xf71021,
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
+0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
+0x24070008, 0xa32821, 0xa3482b, 0x822021,
+0x100f809, 0x892021, 0x54400006, 0x24130001,
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
+0x0, 0x326200ff, 0x54400017, 0xaf520018,
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
+0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124,
+0x3c040001, 0x24846118, 0x3c050009, 0xafa20014,
+0x8d460000, 0x10000035, 0x34a50600, 0x8f420308,
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
+0x1000001e, 0x326200ff, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400016,
+0x9821, 0x3c150020, 0x24110010, 0x8f42000c,
+0x8f440160, 0x8f450164, 0x8f860120, 0xafb10010,
+0xafb20014, 0x551025, 0xafa20018, 0x8f42010c,
+0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3,
+0x0, 0x8f820054, 0x2021023, 0x2c4203e9,
+0x1440ffee, 0x0, 0x326200ff, 0x14400011,
+0x0, 0x8f420378, 0x24420001, 0xaf420378,
+0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24846120, 0x3c050009,
+0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b,
+0x3c03821, 0x8f4202ec, 0x24420001, 0xaf4202ec,
+0x8f4202ec, 0x8f420004, 0x30420001, 0x10400018,
+0x24040001, 0x8f420250, 0x8f430254, 0x8f4501b4,
+0x3c010001, 0x14650006, 0xa0246cf1, 0x8f420270,
+0x8f430274, 0x8f4401b8, 0x10640021, 0x0,
+0x8f420250, 0x8f430254, 0x3c040001, 0x90846cf0,
+0x8f460270, 0x8f470274, 0x38840001, 0xaf4301b4,
+0xaf4701b8, 0x3c010001, 0x10000025, 0xa0246cf0,
+0x8f4200d4, 0x3c010001, 0xa0206cf0, 0x24430001,
+0x28420033, 0x1440001e, 0xaf4300d4, 0x3c020001,
+0x90426cf1, 0xaf4000d4, 0x10000017, 0x38420001,
+0x8f420004, 0x30420001, 0x10400008, 0x0,
+0xc00565a, 0x2021, 0x3c010001, 0xa0206cf1,
+0x3c010001, 0x1000000e, 0xa0206cf0, 0x8f4200d4,
+0x3c010001, 0xa0206cf0, 0x24430001, 0x284201f5,
+0x14400007, 0xaf4300d4, 0x3c020001, 0x90426cf1,
+0xaf4000d4, 0x421026, 0x3c010001, 0xa0226cf1,
+0x3c030001, 0x8c636d98, 0x24020002, 0x1462000c,
+0x3c030002, 0x3c030001, 0x90636cf1, 0x24020001,
+0x5462001f, 0x2021, 0x3c020001, 0x90426cf0,
+0x1443001b, 0x24040005, 0x10000019, 0x24040006,
+0x3c020002, 0x8c428ff4, 0x431024, 0x1040000b,
+0x24020001, 0x3c030001, 0x90636cf1, 0x54620010,
+0x2021, 0x3c020001, 0x90426cf0, 0x1443000c,
+0x24040003, 0x1000000a, 0x24040004, 0x3c030001,
+0x90636cf1, 0x14620006, 0x2021, 0x3c020001,
+0x90426cf0, 0x24040001, 0x50440001, 0x24040002,
+0xc00565a, 0x0, 0x2402ff7f, 0x282a024,
+0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
+0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
+0x27bd0050, 0x3e00008, 0x0, 0x3c020001,
+0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
+0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
+0x104000de, 0xafb00030, 0x8f4200d0, 0x3c040001,
+0x8c846d98, 0x24430001, 0x2842000b, 0xaf4400e8,
+0x144000fe, 0xaf4300d0, 0x8f420004, 0x30420002,
+0x14400095, 0xaf4000d0, 0x8f420004, 0x34420002,
+0xaf420004, 0x24020001, 0x14820003, 0x3c020600,
+0x10000002, 0x34423000, 0x34421000, 0xafa20020,
+0x1821, 0x8f5e0018, 0x27aa0020, 0x240200ff,
+0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228,
+0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c,
+0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228,
+0x3c040001, 0x2484610c, 0x3c050009, 0xafa00014,
+0xafa20010, 0x8fa60020, 0x1000006d, 0x34a50500,
+0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0,
+0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8,
+0x2021023, 0x2c4203e9, 0x1040001b, 0x9821,
+0xe08821, 0x263504c0, 0x8f440178, 0x8f45017c,
+0x2201821, 0x240a0004, 0xafaa0010, 0xafb20014,
+0x8f48000c, 0x1021, 0x2f53021, 0xafa80018,
+0x8f48010c, 0x24070008, 0xa32821, 0xa3482b,
+0x822021, 0x100f809, 0x892021, 0x54400006,
+0x24130001, 0x8f820054, 0x2021023, 0x2c4203e9,
+0x1440ffe9, 0x0, 0x326200ff, 0x54400017,
+0xaf520018, 0x8f420378, 0x24420001, 0xaf420378,
+0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24846118, 0x3c050009,
+0xafa20014, 0x8d460000, 0x10000035, 0x34a50600,
+0x8f420308, 0x24130001, 0x24420001, 0xaf420308,
+0x8f420308, 0x1000001e, 0x326200ff, 0x8f830054,
+0x8f820054, 0x247003e8, 0x2021023, 0x2c4203e9,
+0x10400016, 0x9821, 0x3c150020, 0x24110010,
+0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120,
+0xafb10010, 0xafb20014, 0x551025, 0xafa20018,
+0x8f42010c, 0x24070008, 0x40f809, 0x24c6001c,
+0x1440ffe3, 0x0, 0x8f820054, 0x2021023,
+0x2c4203e9, 0x1440ffee, 0x0, 0x326200ff,
+0x14400011, 0x0, 0x8f420378, 0x24420001,
+0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
+0xafa20010, 0x8f820124, 0x3c040001, 0x24846120,
+0x3c050009, 0xafa20014, 0x8d460000, 0x34a50700,
+0xc002b3b, 0x3c03821, 0x8f4202ec, 0x24420001,
+0xaf4202ec, 0x8f4202ec, 0x8f420004, 0x30420001,
+0x10400033, 0x3c020400, 0x2c21024, 0x10400017,
+0x0, 0x934205c0, 0x8f440250, 0x8f450254,
+0x8f4301b4, 0x34420020, 0x14a30006, 0xa34205c0,
+0x8f420270, 0x8f430274, 0x8f4401b8, 0x10640008,
+0x0, 0x8f420250, 0x8f430254, 0x934405c0,
+0x8f460270, 0x8f470274, 0x10000016, 0x38840040,
+0x934205c0, 0x10000048, 0x304200bf, 0x934205c0,
+0x8f440250, 0x8f450254, 0x8f4301b4, 0x304200bf,
+0x14a30006, 0xa34205c0, 0x8f420270, 0x8f430274,
+0x8f4401b8, 0x1064000b, 0x0, 0x8f420250,
+0x8f430254, 0x934405c0, 0x8f460270, 0x8f470274,
+0x38840020, 0xaf4301b4, 0xaf4701b8, 0x10000033,
+0xa34405c0, 0x934205c0, 0x1000002f, 0x34420020,
+0x934205c0, 0x8f4300d4, 0x34420020, 0xa34205c0,
+0x24620001, 0x10000023, 0x28630033, 0x8f4200e4,
+0x8f4300e0, 0x24420001, 0xaf4200e4, 0x43102a,
+0x14400006, 0x24030001, 0x8f4200e8, 0x14430002,
+0xaf4000e4, 0x24030004, 0xaf4300e8, 0x8f420004,
+0x30420001, 0x1040000d, 0x3c020400, 0x2c21024,
+0x10400007, 0x0, 0x934205c0, 0x34420040,
+0xa34205c0, 0x934205c0, 0x1000000f, 0x304200df,
+0x934205c0, 0x1000000c, 0x34420060, 0x934205c0,
+0x8f4300d4, 0x34420020, 0xa34205c0, 0x24620001,
+0x286300fb, 0x14600005, 0xaf4200d4, 0x934205c0,
+0xaf4000d4, 0x38420040, 0xa34205c0, 0x934205c0,
+0x8f4300e8, 0x3042007f, 0xa34205c0, 0x24020001,
+0x14620005, 0x0, 0x934405c0, 0x42102,
+0x10000003, 0x348400f0, 0x934405c0, 0x3484000f,
+0xc005640, 0x0, 0x2402ff7f, 0x282a024,
+0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
+0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
+0x27bd0050, 0x3e00008, 0x0, 0x27bdffb0,
+0x274401c0, 0x26e30028, 0x24650400, 0x65102b,
+0xafbf0048, 0xafbe0044, 0xafb50040, 0xafb3003c,
+0xafb20038, 0xafb10034, 0x10400007, 0xafb00030,
+0x8c820000, 0xac620000, 0x24630004, 0x65102b,
+0x1440fffb, 0x24840004, 0x8c020080, 0xaee20044,
+0x8c0200c0, 0xaee20040, 0x8c020084, 0xaee20030,
+0x8c020084, 0xaee2023c, 0x8c020088, 0xaee20240,
+0x8c02008c, 0xaee20244, 0x8c020090, 0xaee20248,
+0x8c020094, 0xaee2024c, 0x8c020098, 0xaee20250,
+0x8c02009c, 0xaee20254, 0x8c0200a0, 0xaee20258,
+0x8c0200a4, 0xaee2025c, 0x8c0200a8, 0xaee20260,
+0x8c0200ac, 0xaee20264, 0x8c0200b0, 0xaee20268,
+0x8c0200b4, 0xaee2026c, 0x8c0200b8, 0xaee20270,
+0x8c0200bc, 0x24040001, 0xaee20274, 0xaee00034,
+0x41080, 0x571021, 0x8ee30034, 0x8c42023c,
+0x24840001, 0x621821, 0x2c82000f, 0xaee30034,
+0x1440fff8, 0x41080, 0x8c0200cc, 0xaee20048,
+0x8c0200d0, 0xaee2004c, 0x8c0200e0, 0xaee201f8,
+0x8c0200e4, 0xaee201fc, 0x8c0200e8, 0xaee20200,
+0x8c0200ec, 0xaee20204, 0x8c0200f0, 0xaee20208,
+0x8ee400c0, 0x8ee500c4, 0x8c0200fc, 0x45102b,
+0x1040000b, 0x0, 0x8ee200c0, 0x8ee300c4,
+0x24040001, 0x24050000, 0x651821, 0x65302b,
+0x441021, 0x461021, 0xaee200c0, 0xaee300c4,
+0x8c0200fc, 0x8ee400c0, 0x8ee500c4, 0x2408ffff,
+0x24090000, 0x401821, 0x1021, 0x882024,
+0xa92824, 0x822025, 0xa32825, 0xaee400c0,
+0xaee500c4, 0x8ee400d0, 0x8ee500d4, 0x8c0200f4,
+0x45102b, 0x1040000b, 0x0, 0x8ee200d0,
+0x8ee300d4, 0x24040001, 0x24050000, 0x651821,
+0x65302b, 0x441021, 0x461021, 0xaee200d0,
+0xaee300d4, 0x8c0200f4, 0x8ee400d0, 0x8ee500d4,
+0x401821, 0x1021, 0x882024, 0xa92824,
+0x822025, 0xa32825, 0xaee400d0, 0xaee500d4,
+0x8ee400c8, 0x8ee500cc, 0x8c0200f8, 0x45102b,
+0x1040000b, 0x0, 0x8ee200c8, 0x8ee300cc,
+0x24040001, 0x24050000, 0x651821, 0x65302b,
+0x441021, 0x461021, 0xaee200c8, 0xaee300cc,
+0x8c0200f8, 0x8ee400c8, 0x8ee500cc, 0x401821,
+0x1021, 0x882024, 0xa92824, 0x822025,
+0xa32825, 0x24020008, 0xaee400c8, 0xaee500cc,
+0xafa20010, 0xafa00014, 0x8f42000c, 0x8c040208,
+0x8c05020c, 0xafa20018, 0x8f42010c, 0x26e60028,
+0x40f809, 0x24070400, 0x104000f0, 0x3c020400,
+0xafa20020, 0x934205c6, 0x10400089, 0x1821,
+0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
+0xafaa002c, 0x27c30001, 0x8c020228, 0x609021,
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010,
+0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
+0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
+0x24070008, 0xa32821, 0xa3482b, 0x822021,
+0x100f809, 0x892021, 0x54400006, 0x24130001,
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
+0x0, 0x326200ff, 0x54400017, 0xaf520018,
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
+0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124,
+0x3c040001, 0x24846118, 0x3c050009, 0xafa20014,
+0x8d460000, 0x10000033, 0x34a50600, 0x8f420308,
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
+0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
+0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
+0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
+0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
+0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
+0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
+0x326200ff, 0x54400012, 0x24020001, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
+0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001,
+0x24846120, 0x3c050009, 0xafa20014, 0x8d460000,
+0x34a50700, 0xc002b3b, 0x3c03821, 0x1021,
+0x1440005b, 0x24020001, 0x10000065, 0x0,
+0x8f510018, 0x240200ff, 0x12220002, 0x8021,
+0x26300001, 0x8c020228, 0x1602000e, 0x1130c0,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x248460f4, 0x3c050009,
+0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f,
+0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024,
+0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
+0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
+0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021,
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x248460fc, 0x3c050009,
+0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200,
+0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018,
+0x8f860120, 0x24020010, 0xafa20010, 0xafb00014,
+0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x54400011, 0x24020001, 0x8f420340, 0x24420001,
+0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24846104, 0x3c050009,
+0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b,
+0x2203821, 0x1021, 0x1040000d, 0x24020001,
+0x8f4202e8, 0xa34005c6, 0xaf4001b0, 0x24420001,
+0xaf4202e8, 0x8f4202e8, 0x8ee20150, 0x24420001,
+0xaee20150, 0x10000003, 0x8ee20150, 0x24020001,
+0xa34205c6, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
+0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
+0x3e00008, 0x27bd0050, 0x27bdffd8, 0xafbf0020,
+0x8f8200b0, 0x30420004, 0x10400068, 0x0,
+0x8f430128, 0x8f820104, 0x14620005, 0x0,
+0x8f430130, 0x8f8200b4, 0x10620006, 0x0,
+0x8f820104, 0xaf420128, 0x8f8200b4, 0x1000005b,
+0xaf420130, 0x8f8200b0, 0x3c030080, 0x431024,
+0x1040000d, 0x0, 0x8f82011c, 0x34420002,
+0xaf82011c, 0x8f8200b0, 0x2403fffb, 0x431024,
+0xaf8200b0, 0x8f82011c, 0x2403fffd, 0x431024,
+0x1000004a, 0xaf82011c, 0x8f430128, 0x8f820104,
+0x14620005, 0x0, 0x8f430130, 0x8f8200b4,
+0x10620010, 0x0, 0x8f820104, 0xaf420128,
+0x8f8200b4, 0x8f430128, 0xaf420130, 0xafa30010,
+0x8f420130, 0x3c040001, 0x24846144, 0xafa20014,
+0x8f86011c, 0x8f8700b0, 0x3c050005, 0x10000031,
+0x34a50900, 0x8f420128, 0xafa20010, 0x8f420130,
+0x3c040001, 0x24846150, 0xafa20014, 0x8f86011c,
+0x8f8700b0, 0x3c050005, 0xc002b3b, 0x34a51000,
+0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104,
+0x8f8200b0, 0x34420001, 0xaf8200b0, 0x24020008,
+0xaf830104, 0xafa20010, 0xafa00014, 0x8f42000c,
+0x8c040208, 0x8c05020c, 0xafa20018, 0x8f42010c,
+0x26e60028, 0x40f809, 0x24070400, 0x8f82011c,
+0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc,
+0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f420128,
+0xafa20010, 0x8f420130, 0x3c040001, 0x2484615c,
+0xafa20014, 0x8f86011c, 0x8f8700b0, 0x3c050005,
+0x34a51100, 0xc002b3b, 0x0, 0x8f8200a0,
+0x30420004, 0x10400069, 0x0, 0x8f43012c,
+0x8f820124, 0x14620005, 0x0, 0x8f430134,
+0x8f8200a4, 0x10620006, 0x0, 0x8f820124,
+0xaf42012c, 0x8f8200a4, 0x1000005c, 0xaf420134,
+0x8f8200a0, 0x3c030080, 0x431024, 0x1040000d,
+0x0, 0x8f82011c, 0x34420002, 0xaf82011c,
+0x8f8200a0, 0x2403fffb, 0x431024, 0xaf8200a0,
+0x8f82011c, 0x2403fffd, 0x431024, 0x1000004b,
+0xaf82011c, 0x8f43012c, 0x8f820124, 0x14620005,
+0x0, 0x8f430134, 0x8f8200a4, 0x10620010,
+0x0, 0x8f820124, 0xaf42012c, 0x8f8200a4,
+0x8f43012c, 0xaf420134, 0xafa30010, 0x8f420134,
+0x3c040001, 0x24846168, 0xafa20014, 0x8f86011c,
+0x8f8700a0, 0x3c050005, 0x10000032, 0x34a51200,
+0x8f42012c, 0xafa20010, 0x8f420134, 0x3c040001,
+0x24846174, 0xafa20014, 0x8f86011c, 0x8f8700a0,
+0x3c050005, 0xc002b3b, 0x34a51300, 0x8f82011c,
+0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0,
+0x34420001, 0xaf8200a0, 0x24020080, 0xaf830124,
+0xafa20010, 0xafa00014, 0x8f420014, 0x8c040208,
+0x8c05020c, 0xafa20018, 0x8f420108, 0x3c060001,
+0x24c66ed8, 0x40f809, 0x24070004, 0x8f82011c,
+0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc,
+0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f42012c,
+0xafa20010, 0x8f420134, 0x3c040001, 0x24846180,
+0xafa20014, 0x8f86011c, 0x8f8700a0, 0x3c050005,
+0x34a51400, 0xc002b3b, 0x0, 0x8fbf0020,
+0x3e00008, 0x27bd0028, 0x3c081000, 0x24070001,
+0x3c060080, 0x3c050100, 0x8f820070, 0x481024,
+0x1040fffd, 0x0, 0x8f820054, 0x24420005,
+0xaf820078, 0x8c040234, 0x10800016, 0x1821,
+0x3c020001, 0x571021, 0x8c4240e8, 0x24420005,
+0x3c010001, 0x370821, 0xac2240e8, 0x3c020001,
+0x571021, 0x8c4240e8, 0x44102b, 0x14400009,
+0x0, 0x3c030080, 0x3c010001, 0x370821,
+0xac2040e8, 0x3c010001, 0x370821, 0x1000000b,
+0xa02740f0, 0x3c020001, 0x571021, 0x904240f0,
+0x54400006, 0x661825, 0x3c020001, 0x571021,
+0x904240f1, 0x54400001, 0x661825, 0x8c040230,
+0x10800013, 0x0, 0x3c020001, 0x571021,
+0x8c4240ec, 0x24420005, 0x3c010001, 0x370821,
+0xac2240ec, 0x3c020001, 0x571021, 0x8c4240ec,
+0x44102b, 0x14400006, 0x0, 0x3c010001,
+0x370821, 0xac2040ec, 0x10000006, 0x651825,
+0x3c020001, 0x571021, 0x904240f2, 0x54400001,
+0x651825, 0x1060ffbc, 0x0, 0x8f420000,
+0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x431025, 0xaf820060, 0x8f420000,
+0x10400003, 0x0, 0x1000ffa7, 0xaf80004c,
+0x1000ffa5, 0xaf800048, 0x3e00008, 0x0,
+0x0, 0x0, 0x0, 0x27bdffe0,
+0xafbf0018, 0x8f860064, 0x30c20004, 0x10400025,
+0x24040004, 0x8c020114, 0xaf420020, 0xaf840064,
+0x8f4202fc, 0x24420001, 0xaf4202fc, 0x8f4202fc,
+0x8f820064, 0x30420004, 0x14400005, 0x0,
+0x8c030114, 0x8f420020, 0x1462fff2, 0x0,
+0x8f420000, 0x10400007, 0x8f43003c, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x431025, 0xaf820060,
+0x8f420000, 0x10400073, 0x0, 0x1000006f,
+0x0, 0x30c20008, 0x10400020, 0x24040008,
+0x8c02011c, 0xaf420048, 0xaf840064, 0x8f4202a8,
+0x24420001, 0xaf4202a8, 0x8f4202a8, 0x8f820064,
+0x30420008, 0x14400005, 0x0, 0x8c03011c,
+0x8f420048, 0x1462fff2, 0x0, 0x8f420000,
+0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x1000ffd9, 0x34420200, 0x30c20020,
+0x10400023, 0x24040020, 0x8c02012c, 0xaf420068,
+0xaf840064, 0x8f4202d8, 0x24420001, 0xaf4202d8,
+0x8f4202d8, 0x8f820064, 0x30420020, 0x14400005,
+0x32c24000, 0x8c03012c, 0x8f420068, 0x1462fff2,
+0x32c24000, 0x14400002, 0x3c020001, 0x2c2b025,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x1000ffb4, 0x34420800,
+0x30c20010, 0x10400029, 0x24040010, 0x8c020124,
+0xaf420058, 0xaf840064, 0x8f4202d4, 0x24420001,
+0xaf4202d4, 0x8f4202d4, 0x8f820064, 0x30420010,
+0x14400005, 0x32c22000, 0x8c030124, 0x8f420058,
+0x1462fff2, 0x32c22000, 0x50400001, 0x36d68000,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x34420100, 0xaf820060,
+0x8f420000, 0x10400003, 0x0, 0x1000006c,
+0xaf80004c, 0x1000006a, 0xaf800048, 0x30c20001,
+0x10400004, 0x24020001, 0xaf820064, 0x10000064,
+0x0, 0x30c20002, 0x1440000b, 0x3c050003,
+0x3c040001, 0x24846244, 0x34a50500, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x2402ffc0,
+0x10000057, 0xaf820064, 0x8c05022c, 0x8c02010c,
+0x10a20048, 0x51080, 0x8c460300, 0x24a20001,
+0x3045003f, 0x24020003, 0xac05022c, 0x61e02,
+0x10620005, 0x24020010, 0x1062001d, 0x30c20fff,
+0x10000039, 0x0, 0x8f4302a8, 0x8f440000,
+0x30c20fff, 0xaf420048, 0x24630001, 0xaf4302a8,
+0x10800007, 0x8f4202a8, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x34420200, 0xaf820060, 0x8f420000,
+0x1040001f, 0x0, 0x1000001b, 0x0,
+0xaf420058, 0x32c22000, 0x50400001, 0x36d68000,
+0x8f4202d4, 0x8f430000, 0x24420001, 0xaf4202d4,
+0x10600007, 0x8f4202d4, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x34420100, 0xaf820060, 0x8f420000,
+0x10400003, 0x0, 0x10000006, 0xaf80004c,
+0x10000004, 0xaf800048, 0xc002196, 0xc02021,
+0x402821, 0x8c02010c, 0x14a20002, 0x24020002,
+0xaf820064, 0x8f820064, 0x30420002, 0x14400004,
+0x0, 0x8c02010c, 0x14a2ffac, 0x0,
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008,
+0x0, 0x27bdffa0, 0xafb00040, 0x808021,
+0x101602, 0x2442ffff, 0x304300ff, 0x2c620013,
+0xafbf0058, 0xafbe0054, 0xafb50050, 0xafb3004c,
+0xafb20048, 0xafb10044, 0x104001f3, 0xafa50034,
+0x31080, 0x3c010001, 0x220821, 0x8c226288,
+0x400008, 0x0, 0x101302, 0x30440fff,
+0x24020001, 0x10820005, 0x24020002, 0x1082000c,
+0x2402fffe, 0x10000024, 0x3c050003, 0x8f430004,
+0x3c020001, 0x8c426f04, 0xaf440200, 0xaf440204,
+0x3c040001, 0x8c846e80, 0x10000009, 0x34630001,
+0x8f430004, 0xaf440200, 0xaf440204, 0x3c040001,
+0x8c846e80, 0x621824, 0x3c020001, 0x2442ca28,
+0x21100, 0x21182, 0xaf430004, 0x3c030800,
+0x431025, 0xac820038, 0x8f840054, 0x41442,
+0x41c82, 0x431021, 0x41cc2, 0x431023,
+0x41d02, 0x431021, 0x41d42, 0x431023,
+0x10000009, 0xaf420208, 0x3c040001, 0x24846250,
+0x34a51000, 0x2003021, 0x3821, 0xafa00010,
+0xc002b3b, 0xafa00014, 0x8f4202a0, 0x24420001,
+0xaf4202a0, 0x1000021f, 0x8f4202a0, 0x27b00028,
+0x2002021, 0x24050210, 0xc002bbf, 0x24060008,
+0xc002518, 0x2002021, 0x10000216, 0x0,
+0x8faa0034, 0x27a40028, 0xa1880, 0x25420001,
+0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034,
+0x21080, 0x8c430300, 0x25420001, 0x3042003f,
+0xafa20034, 0xac02022c, 0xafa50028, 0xc002518,
+0xafa3002c, 0x10000203, 0x0, 0x27b00028,
+0x2002021, 0x24050210, 0xc002bbf, 0x24060008,
+0xc002657, 0x2002021, 0x100001fa, 0x0,
+0x8faa0034, 0x27a40028, 0xa1880, 0x25420001,
+0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034,
+0x21080, 0x8c430300, 0x25420001, 0x3042003f,
+0xafa20034, 0xac02022c, 0xafa50028, 0xc002657,
+0xafa3002c, 0x100001e7, 0x0, 0x101302,
+0x30430fff, 0x24020001, 0x10620005, 0x24020002,
+0x1062001e, 0x3c020002, 0x10000033, 0x3c050003,
+0x3c030002, 0x2c31024, 0x54400037, 0x2c3b025,
+0x8f820228, 0x3c010001, 0x370821, 0xac2238d8,
+0x8f82022c, 0x3c010001, 0x370821, 0xac2238dc,
+0x8f820230, 0x3c010001, 0x370821, 0xac2238e0,
+0x8f820234, 0x3c010001, 0x370821, 0xac2238e4,
+0x2402ffff, 0xaf820228, 0xaf82022c, 0xaf820230,
+0xaf820234, 0x10000020, 0x2c3b025, 0x2c21024,
+0x10400012, 0x3c02fffd, 0x3c020001, 0x571021,
+0x8c4238d8, 0xaf820228, 0x3c020001, 0x571021,
+0x8c4238dc, 0xaf82022c, 0x3c020001, 0x571021,
+0x8c4238e0, 0xaf820230, 0x3c020001, 0x571021,
+0x8c4238e4, 0xaf820234, 0x3c02fffd, 0x3442ffff,
+0x10000009, 0x2c2b024, 0x3c040001, 0x2484625c,
+0x34a51100, 0x2003021, 0x3821, 0xafa00010,
+0xc002b3b, 0xafa00014, 0x8f4202cc, 0x24420001,
+0xaf4202cc, 0x1000019f, 0x8f4202cc, 0x101302,
+0x30450fff, 0x24020001, 0x10a20005, 0x24020002,
+0x10a2000d, 0x3c0408ff, 0x10000014, 0x3c050003,
+0x3c0208ff, 0x3442ffff, 0x8f830220, 0x3c040004,
+0x2c4b025, 0x621824, 0x34630008, 0xaf830220,
+0x10000012, 0xaf450298, 0x3484fff7, 0x3c03fffb,
+0x8f820220, 0x3463ffff, 0x2c3b024, 0x441024,
+0xaf820220, 0x10000009, 0xaf450298, 0x3c040001,
+0x24846268, 0x34a51200, 0x2003021, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202bc,
+0x24420001, 0xaf4202bc, 0x10000176, 0x8f4202bc,
+0x27840208, 0x24050200, 0xc002bbf, 0x24060008,
+0x27440224, 0x24050200, 0xc002bbf, 0x24060008,
+0x8f4202c4, 0x24420001, 0xaf4202c4, 0x10000169,
+0x8f4202c4, 0x101302, 0x30430fff, 0x24020001,
+0x10620011, 0x28620002, 0x50400005, 0x24020002,
+0x10600007, 0x0, 0x10000017, 0x0,
+0x1062000f, 0x0, 0x10000013, 0x0,
+0x8c060248, 0x2021, 0xc005104, 0x24050004,
+0x10000007, 0x0, 0x8c060248, 0x2021,
+0xc005104, 0x24050004, 0x10000010, 0x0,
+0x8c06024c, 0x2021, 0xc005104, 0x24050001,
+0x1000000a, 0x0, 0x3c040001, 0x24846274,
+0x3c050003, 0x34a51300, 0x2003021, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202c0,
+0x24420001, 0xaf4202c0, 0x1000013a, 0x8f4202c0,
+0xc002426, 0x0, 0x10000136, 0x0,
+0x24020001, 0xa34205c5, 0x24100100, 0x8f4401a8,
+0x8f4501ac, 0xafb00010, 0xafa00014, 0x8f420014,
+0xafa20018, 0x8f420108, 0x26e60028, 0x40f809,
+0x24070400, 0x1040fff5, 0x0, 0x10000125,
+0x0, 0x3c03ffff, 0x34637fff, 0x8f420368,
+0x8f440360, 0x2c3b024, 0x1821, 0xaf400058,
+0xaf40005c, 0xaf400060, 0xaf400064, 0x441023,
+0xaf420368, 0x3c020900, 0xaf400360, 0xafa20020,
+0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
+0xafaa003c, 0x27c30001, 0x8c020228, 0x609021,
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x2484620c, 0x3c050009, 0xafa00014, 0xafa20010,
+0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
+0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
+0x24070008, 0xa32821, 0xa3482b, 0x822021,
+0x100f809, 0x892021, 0x54400006, 0x24130001,
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
+0x0, 0x326200ff, 0x54400017, 0xaf520018,
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
+0x8f820120, 0x8faa003c, 0xafa20010, 0x8f820124,
+0x3c040001, 0x24846218, 0x3c050009, 0xafa20014,
+0x8d460000, 0x10000033, 0x34a50600, 0x8f420308,
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
+0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
+0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
+0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
+0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
+0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
+0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
+0x326200ff, 0x14400011, 0x0, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
+0x8faa003c, 0xafa20010, 0x8f820124, 0x3c040001,
+0x24846220, 0x3c050009, 0xafa20014, 0x8d460000,
+0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b0,
+0x24420001, 0xaf4202b0, 0x8f4202b0, 0x8f4202f8,
+0x24420001, 0xaf4202f8, 0x1000008a, 0x8f4202f8,
+0x8c02025c, 0x27440224, 0xaf4201f0, 0x8c020260,
+0x24050200, 0x24060008, 0xc002bbf, 0xaf4201f8,
+0x8f820220, 0x30420008, 0x14400002, 0x24020001,
+0x24020002, 0xaf420298, 0x8f4202ac, 0x24420001,
+0xaf4202ac, 0x10000077, 0x8f4202ac, 0x3c0200ff,
+0x3442ffff, 0x2021824, 0x32c20180, 0x14400006,
+0x3402fffb, 0x43102b, 0x14400003, 0x0,
+0x1000006c, 0xaf4300bc, 0x3c040001, 0x24846280,
+0x3c050003, 0x34a51500, 0x2003021, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020700,
+0x34421000, 0x101e02, 0x621825, 0xafa30020,
+0x8f510018, 0x240200ff, 0x12220002, 0x8021,
+0x26300001, 0x8c020228, 0x1602000e, 0x1130c0,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x248461f4, 0x3c050009,
+0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f,
+0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024,
+0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
+0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
+0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021,
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x248461fc, 0x3c050009,
+0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200,
+0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018,
+0x8f860120, 0x24020010, 0xafa20010, 0xafb00014,
+0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x14400010, 0x0, 0x8f420340, 0x24420001,
+0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24846204, 0x3c050009,
+0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b,
+0x2203821, 0x8f4202e0, 0x24420001, 0xaf4202e0,
+0x8f4202e0, 0x8f4202f0, 0x24420001, 0xaf4202f0,
+0x8f4202f0, 0x8fa20034, 0x8fbf0058, 0x8fbe0054,
+0x8fb50050, 0x8fb3004c, 0x8fb20048, 0x8fb10044,
+0x8fb00040, 0x3e00008, 0x27bd0060, 0x27bdfff8,
+0x2408ffff, 0x10a00014, 0x4821, 0x3c0aedb8,
+0x354a8320, 0x90870000, 0x24840001, 0x3021,
+0x1071026, 0x30420001, 0x10400002, 0x81842,
+0x6a1826, 0x604021, 0x24c60001, 0x2cc20008,
+0x1440fff7, 0x73842, 0x25290001, 0x125102b,
+0x1440fff0, 0x0, 0x1001021, 0x3e00008,
+0x27bd0008, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
+0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
+0xafb00030, 0x8f870220, 0xafa70024, 0x8f870200,
+0xafa7002c, 0x8f820220, 0x3c0308ff, 0x3463ffff,
+0x431024, 0x34420004, 0xaf820220, 0x8f820200,
+0x3c03c0ff, 0x3463ffff, 0x431024, 0x34420004,
+0xaf820200, 0x8f530358, 0x8f55035c, 0x8f5e0360,
+0x8f470364, 0xafa70014, 0x8f470368, 0xafa7001c,
+0x8f4202d0, 0x274401c0, 0x24420001, 0xaf4202d0,
+0x8f5002d0, 0x8f510204, 0x8f520200, 0xc002ba8,
+0x24050400, 0xaf530358, 0xaf55035c, 0xaf5e0360,
+0x8fa70014, 0xaf470364, 0x8fa7001c, 0xaf470368,
+0xaf5002d0, 0xaf510204, 0xaf520200, 0x8c02025c,
+0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200,
+0x24060008, 0xaf4201f8, 0x24020006, 0xc002bbf,
+0xaf4201f4, 0x3c023b9a, 0x3442ca00, 0xaf4201fc,
+0x240203e8, 0x24040002, 0x24030001, 0xaf420294,
+0xaf440290, 0xaf43029c, 0x8f820220, 0x30420008,
+0x10400004, 0x0, 0xaf430298, 0x10000003,
+0x3021, 0xaf440298, 0x3021, 0x3c030001,
+0x661821, 0x90636d00, 0x3461021, 0x24c60001,
+0xa043022c, 0x2cc2000f, 0x1440fff8, 0x3461821,
+0x24c60001, 0x8f820040, 0x24040080, 0x24050080,
+0x21702, 0x24420030, 0xa062022c, 0x3461021,
+0xc002ba8, 0xa040022c, 0x8fa70024, 0x30e20004,
+0x14400006, 0x0, 0x8f820220, 0x3c0308ff,
+0x3463fffb, 0x431024, 0xaf820220, 0x8fa7002c,
+0x30e20004, 0x14400006, 0x0, 0x8f820200,
+0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200,
+0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
+0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
+0x27bd0050, 0x0, 0x0, 0xaf400104,
+0x24040001, 0x410c0, 0x2e21821, 0x24820001,
+0x3c010001, 0x230821, 0xa42234d0, 0x402021,
+0x2c820080, 0x1440fff8, 0x410c0, 0x24020001,
+0x3c010001, 0x370821, 0xa42038d0, 0xaf420100,
+0xaf800228, 0xaf80022c, 0xaf800230, 0xaf800234,
+0x3e00008, 0x0, 0x27bdffe8, 0xafbf0014,
+0xafb00010, 0x8f420104, 0x28420005, 0x10400026,
+0x808021, 0x3c020001, 0x8f430104, 0x344230d0,
+0x2e22021, 0x318c0, 0x621821, 0x2e31821,
+0x83102b, 0x10400015, 0x1021, 0x96070000,
+0x24840006, 0x24660006, 0x9482fffc, 0x14470009,
+0x2821, 0x9483fffe, 0x96020002, 0x14620006,
+0xa01021, 0x94820000, 0x96030004, 0x431026,
+0x2c450001, 0xa01021, 0x14400009, 0x24840008,
+0x86102b, 0x1440fff0, 0x1021, 0x304200ff,
+0x14400030, 0x24020001, 0x1000002e, 0x1021,
+0x1000fffa, 0x24020001, 0x2002021, 0xc00240c,
+0x24050006, 0x3042007f, 0x218c0, 0x2e31021,
+0x3c010001, 0x220821, 0x942230d0, 0x1040fff2,
+0x2e31021, 0x3c060001, 0xc23021, 0x94c630d0,
+0x10c0ffed, 0x3c080001, 0x350834d2, 0x96070000,
+0x610c0, 0x572021, 0x882021, 0x94820000,
+0x14470009, 0x2821, 0x94830002, 0x96020002,
+0x14620006, 0xa01021, 0x94820004, 0x96030004,
+0x431026, 0x2c450001, 0xa01021, 0x14400007,
+0x610c0, 0x2e21021, 0x3c060001, 0xc23021,
+0x94c634d0, 0x14c0ffeb, 0x610c0, 0x10c0ffd2,
+0x24020001, 0x8fbf0014, 0x8fb00010, 0x3e00008,
+0x27bd0018, 0x3e00008, 0x0, 0x27bdffb0,
+0x801021, 0xafb00030, 0x24500002, 0x2002021,
+0x24050006, 0xafb10034, 0x408821, 0xafbf0048,
+0xafbe0044, 0xafb50040, 0xafb3003c, 0xc00240c,
+0xafb20038, 0x3047007f, 0x710c0, 0x2e21021,
+0x3c050001, 0xa22821, 0x94a530d0, 0x50a0001c,
+0xa03021, 0x3c090001, 0x352934d2, 0x96280002,
+0x510c0, 0x572021, 0x892021, 0x94820000,
+0x14480009, 0x3021, 0x94830002, 0x96020002,
+0x14620006, 0xc01021, 0x94820004, 0x96030004,
+0x431026, 0x2c460001, 0xc01021, 0x14400007,
+0x510c0, 0x2e21021, 0x3c050001, 0xa22821,
+0x94a534d0, 0x14a0ffeb, 0x510c0, 0xa03021,
+0x10c00014, 0x610c0, 0x571821, 0x3c010001,
+0x230821, 0x8c2334d0, 0x571021, 0xafa30010,
+0x3c010001, 0x220821, 0x8c2234d4, 0x3c040001,
+0x24846394, 0xafa20014, 0x8e260000, 0x8e270004,
+0x3c050004, 0xc002b3b, 0x34a50400, 0x10000063,
+0x3c020800, 0x8f450100, 0x10a00006, 0x510c0,
+0x2e21021, 0x3c010001, 0x220821, 0x942234d0,
+0xaf420100, 0xa03021, 0x14c00011, 0x628c0,
+0x710c0, 0x2e21021, 0xafa70010, 0x3c010001,
+0x220821, 0x942230d0, 0x3c040001, 0x248463a0,
+0xafa20014, 0x8e260000, 0x8e270004, 0x3c050004,
+0xc002b3b, 0x34a50500, 0x10000048, 0x3c020800,
+0xb71821, 0x3c020001, 0x96040000, 0x344234d2,
+0x621821, 0xa4640000, 0x8e020002, 0x720c0,
+0xac620002, 0x2e41021, 0x3c030001, 0x621821,
+0x946330d0, 0x2e51021, 0x3c010001, 0x220821,
+0xa42334d0, 0x2e41021, 0x3c010001, 0x220821,
+0xa42630d0, 0x8f420104, 0x24420001, 0x28420080,
+0x1040000f, 0x3c020002, 0x8f420104, 0x3c040001,
+0x348430d2, 0x96030000, 0x210c0, 0x571021,
+0x441021, 0xa4430000, 0x8e030002, 0xac430002,
+0x8f420104, 0x24420001, 0xaf420104, 0x3c020002,
+0x2c21024, 0x10400011, 0x72142, 0x3c030001,
+0x346338d8, 0x24020003, 0x441023, 0x21080,
+0x572021, 0x832021, 0x571021, 0x431021,
+0x30e5001f, 0x8c430000, 0x24020001, 0xa21004,
+0x621825, 0x1000000c, 0xac830000, 0x24020003,
+0x441023, 0x21080, 0x5c2821, 0x5c1021,
+0x30e4001f, 0x8c430228, 0x24020001, 0x821004,
+0x621825, 0xaca30228, 0x3c020800, 0x34421000,
+0x1821, 0xafa20020, 0x8f5e0018, 0x27aa0020,
+0x240200ff, 0x13c20002, 0xafaa002c, 0x27c30001,
+0x8c020228, 0x609021, 0x1642000e, 0x1e38c0,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x2484635c, 0x3c050009,
+0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006b,
+0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024,
+0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b,
+0x9821, 0xe08821, 0x263504c0, 0x8f440178,
+0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010,
+0xafb20014, 0x8f48000c, 0x1021, 0x2f53021,
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x54400006, 0x24130001, 0x8f820054, 0x2021023,
+0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff,
+0x54400017, 0xaf520018, 0x8f420378, 0x24420001,
+0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
+0xafa20010, 0x8f820124, 0x3c040001, 0x24846368,
+0x3c050009, 0xafa20014, 0x8d460000, 0x10000033,
+0x34a50600, 0x8f420308, 0x24130001, 0x24420001,
+0xaf420308, 0x8f420308, 0x1000001c, 0x326200ff,
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
+0x2c4203e9, 0x10400014, 0x9821, 0x24110010,
+0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120,
+0xafb10010, 0xafb20014, 0xafa20018, 0x8f42010c,
+0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe5,
+0x0, 0x8f820054, 0x2021023, 0x2c4203e9,
+0x1440ffef, 0x0, 0x326200ff, 0x14400011,
+0x0, 0x8f420378, 0x24420001, 0xaf420378,
+0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24846370, 0x3c050009,
+0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b,
+0x3c03821, 0x8f4202b4, 0x24420001, 0xaf4202b4,
+0x8f4202b4, 0x8f4202f4, 0x24420001, 0xaf4202f4,
+0x8f4202f4, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
+0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
+0x3e00008, 0x27bd0050, 0x27bdffa0, 0x801021,
+0xafb00040, 0x24500002, 0x2002021, 0x24050006,
+0xafb10044, 0x408821, 0xafbf0058, 0xafbe0054,
+0xafb50050, 0xafb3004c, 0xc00240c, 0xafb20048,
+0x3048007f, 0x810c0, 0x2e21021, 0x3c060001,
+0xc23021, 0x94c630d0, 0x10c0001c, 0x3821,
+0x3c0a0001, 0x354a34d2, 0x96290002, 0x610c0,
+0x572021, 0x8a2021, 0x94820000, 0x14490009,
+0x2821, 0x94830002, 0x96020002, 0x14620006,
+0xa01021, 0x94820004, 0x96030004, 0x431026,
+0x2c450001, 0xa01021, 0x14400008, 0x610c0,
+0xc03821, 0x2e21021, 0x3c060001, 0xc23021,
+0x94c634d0, 0x14c0ffea, 0x610c0, 0x14c00011,
+0xafa70028, 0x810c0, 0x2e21021, 0xafa80010,
+0x3c010001, 0x220821, 0x942230d0, 0x3c040001,
+0x248463ac, 0xafa20014, 0x8e260000, 0x8e270004,
+0x3c050004, 0xc002b3b, 0x34a50900, 0x10000075,
+0x3c020800, 0x10e0000c, 0x610c0, 0x2e21021,
+0x3c030001, 0x621821, 0x946334d0, 0x710c0,
+0x2e21021, 0x3c010001, 0x220821, 0xa42334d0,
+0x1000000b, 0x3c040001, 0x2e21021, 0x3c030001,
+0x621821, 0x946334d0, 0x810c0, 0x2e21021,
+0x3c010001, 0x220821, 0xa42330d0, 0x3c040001,
+0x348430d0, 0x8f430100, 0x610c0, 0x2e21021,
+0x3c010001, 0x220821, 0xa42334d0, 0x8f420104,
+0x2e43821, 0x2821, 0x18400029, 0xaf460100,
+0x24e60006, 0x94c3fffc, 0x96020000, 0x14620009,
+0x2021, 0x94c3fffe, 0x96020002, 0x14620006,
+0x801021, 0x94c20000, 0x96030004, 0x431026,
+0x2c440001, 0x801021, 0x50400014, 0x24a50001,
+0x8f420104, 0x2442ffff, 0xa2102a, 0x1040000b,
+0x24e40004, 0x94820006, 0x8c830008, 0xa482fffe,
+0xac830000, 0x8f420104, 0x24a50001, 0x2442ffff,
+0xa2102a, 0x1440fff7, 0x24840008, 0x8f420104,
+0x2442ffff, 0x10000006, 0xaf420104, 0x8f420104,
+0x24c60008, 0xa2102a, 0x1440ffda, 0x24e70008,
+0x810c0, 0x2e21021, 0x3c010001, 0x220821,
+0x942230d0, 0x14400023, 0x3c020800, 0x3c020002,
+0x2c21024, 0x10400012, 0x82142, 0x3c030001,
+0x346338d8, 0x24020003, 0x441023, 0x21080,
+0x572021, 0x832021, 0x571021, 0x431021,
+0x3105001f, 0x24030001, 0x8c420000, 0xa31804,
+0x31827, 0x431024, 0x1000000d, 0xac820000,
+0x24020003, 0x441023, 0x21080, 0x5c2821,
+0x5c1021, 0x3104001f, 0x24030001, 0x8c420228,
+0x831804, 0x31827, 0x431024, 0xaca20228,
+0x3c020800, 0x34422000, 0x1821, 0xafa20020,
+0x8f5e0018, 0x27ab0020, 0x240200ff, 0x13c20002,
+0xafab0034, 0x27c30001, 0x8c020228, 0x609021,
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x2484635c, 0x3c050009, 0xafa00014, 0xafa20010,
+0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
+0x240b0004, 0xafab0010, 0xafb20014, 0x8f48000c,
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
+0x24070008, 0xa32821, 0xa3482b, 0x822021,
+0x100f809, 0x892021, 0x54400006, 0x24130001,
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
+0x0, 0x326200ff, 0x54400017, 0xaf520018,
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
+0x8f820120, 0x8fab0034, 0xafa20010, 0x8f820124,
+0x3c040001, 0x24846368, 0x3c050009, 0xafa20014,
+0x8d660000, 0x10000033, 0x34a50600, 0x8f420308,
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
+0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
+0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
+0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
+0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
+0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
+0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
+0x326200ff, 0x14400011, 0x0, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
+0x8fab0034, 0xafa20010, 0x8f820124, 0x3c040001,
+0x24846370, 0x3c050009, 0xafa20014, 0x8d660000,
+0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b8,
+0x24420001, 0xaf4202b8, 0x8f4202b8, 0x8f4202f4,
+0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8fbf0058,
+0x8fbe0054, 0x8fb50050, 0x8fb3004c, 0x8fb20048,
+0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0060,
+0x0, 0x0, 0x0, 0x27bdffe0,
+0x27644000, 0xafbf0018, 0xc002ba8, 0x24051000,
+0x3c030001, 0x34632cc0, 0x3c040001, 0x34842ec8,
+0x24020020, 0xaf82011c, 0x2e31021, 0xaf800100,
+0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114,
+0xaf800118, 0xaf800120, 0xaf800124, 0xaf800128,
+0xaf800130, 0xaf800134, 0xaf800138, 0xaf4200ec,
+0x2e31021, 0xaf4200f0, 0x2e41021, 0xaf4200f4,
+0x2e41021, 0xaf4200f8, 0x3c020001, 0x571021,
+0x904240f4, 0x1440001c, 0x3c050001, 0x8f82011c,
+0x3c040001, 0x24846470, 0x3c050001, 0x34420001,
+0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c,
+0x34a50100, 0xc002b3b, 0x3821, 0x8c020218,
+0x30420040, 0x10400014, 0x0, 0x8f82011c,
+0x3c040001, 0x2484647c, 0x3c050001, 0x34420004,
+0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c,
+0x10000007, 0x34a50200, 0x3c040001, 0x24846484,
+0xafa00010, 0xafa00014, 0x8f86011c, 0x34a50300,
+0xc002b3b, 0x3821, 0x8fbf0018, 0x3e00008,
+0x27bd0020, 0x8fa90010, 0x8f83012c, 0x8faa0014,
+0x8fab0018, 0x1060000a, 0x27624fe0, 0x14620002,
+0x24680020, 0x27684800, 0x8f820128, 0x11020004,
+0x0, 0x8f820124, 0x15020007, 0x0,
+0x8f430334, 0x1021, 0x24630001, 0xaf430334,
+0x10000039, 0x8f430334, 0xac640000, 0xac650004,
+0xac660008, 0xa467000e, 0xac690018, 0xac6a001c,
+0xac6b0010, 0xac620014, 0xaf880120, 0x8f4200fc,
+0x8f4400f4, 0x2442ffff, 0xaf4200fc, 0x8c820000,
+0x10490005, 0x3042ff8f, 0x10400019, 0x3122ff8f,
+0x10400018, 0x3c020001, 0x8c830004, 0x2c620010,
+0x10400013, 0x3c020001, 0x24630001, 0xac830004,
+0x8f4300f8, 0x344230c8, 0x2e21021, 0x54620004,
+0x24620008, 0x3c020001, 0x34422ec8, 0x2e21021,
+0x14440015, 0x24020001, 0x8f820128, 0x24420020,
+0xaf820128, 0x8f820128, 0x1000000f, 0x24020001,
+0x3c020001, 0x344230c8, 0x2e21021, 0x54820004,
+0x24820008, 0x3c020001, 0x34422ec8, 0x2e21021,
+0x402021, 0x24020001, 0xaf4400f4, 0xac890000,
+0xac820004, 0x24020001, 0x3e00008, 0x0,
+0x3e00008, 0x0, 0x8fa90010, 0x8f83010c,
+0x8faa0014, 0x8fab0018, 0x1060000a, 0x276247e0,
+0x14620002, 0x24680020, 0x27684000, 0x8f820108,
+0x11020004, 0x0, 0x8f820104, 0x15020007,
+0x0, 0x8f430338, 0x1021, 0x24630001,
+0xaf430338, 0x10000035, 0x8f430338, 0xac640000,
+0xac650004, 0xac660008, 0xa467000e, 0xac690018,
+0xac6a001c, 0xac6b0010, 0xac620014, 0xaf880100,
+0x8f4400ec, 0x8c820000, 0x30420006, 0x10400019,
+0x31220006, 0x10400018, 0x3c020001, 0x8c830004,
+0x2c620010, 0x10400013, 0x3c020001, 0x24630001,
+0xac830004, 0x8f4300f0, 0x34422ec0, 0x2e21021,
+0x54620004, 0x24620008, 0x3c020001, 0x34422cc0,
+0x2e21021, 0x14440015, 0x24020001, 0x8f820108,
+0x24420020, 0xaf820108, 0x8f820108, 0x1000000f,
+0x24020001, 0x3c020001, 0x34422ec0, 0x2e21021,
+0x54820004, 0x24820008, 0x3c020001, 0x34422cc0,
+0x2e21021, 0x402021, 0x24020001, 0xaf4400ec,
+0xac890000, 0xac820004, 0x24020001, 0x3e00008,
+0x0, 0x3e00008, 0x0, 0x27bdffd8,
+0x3c040001, 0x2484648c, 0x3c050001, 0xafbf0024,
+0xafb20020, 0xafb1001c, 0xafb00018, 0x8f900104,
+0x8f9100b0, 0x8f92011c, 0x34a52500, 0x8f820100,
+0x2403021, 0x2203821, 0xafa20010, 0xc002b3b,
+0xafb00014, 0x8e020008, 0xafa20010, 0x8e02000c,
+0x3c040001, 0x24846498, 0xafa20014, 0x8e060000,
+0x8e070004, 0x3c050001, 0xc002b3b, 0x34a52510,
+0x8e020018, 0xafa20010, 0x8e02001c, 0x3c040001,
+0x248464a4, 0xafa20014, 0x8e060010, 0x8e070014,
+0x3c050001, 0xc002b3b, 0x34a52520, 0x3c027f00,
+0x2221024, 0x3c030800, 0x54430016, 0x3c030200,
+0x8f82009c, 0x3042ffff, 0x14400012, 0x3c030200,
+0x3c040001, 0x248464b0, 0x3c050002, 0x34a5f030,
+0x3021, 0x3821, 0x36420002, 0xaf82011c,
+0x36220001, 0xaf8200b0, 0xaf900104, 0xaf92011c,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x10000024,
+0x0, 0x2c31024, 0x1040000d, 0x2231024,
+0x1040000b, 0x36420002, 0xaf82011c, 0x36220001,
+0xaf8200b0, 0xaf900104, 0xaf92011c, 0x8f420330,
+0x24420001, 0xaf420330, 0x10000015, 0x8f420330,
+0x3c040001, 0x248464b8, 0x240202a9, 0xafa20010,
+0xafa00014, 0x8f860144, 0x3c070001, 0x24e764c0,
+0xc002b3b, 0x3405dead, 0x8f82011c, 0x34420002,
+0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220,
+0x8f820140, 0x3c030001, 0x431025, 0xaf820140,
+0x8fbf0024, 0x8fb20020, 0x8fb1001c, 0x8fb00018,
+0x3e00008, 0x27bd0028, 0x27bdffd8, 0x3c040001,
+0x248464e8, 0x3c050001, 0xafbf0024, 0xafb20020,
+0xafb1001c, 0xafb00018, 0x8f900124, 0x8f9100a0,
+0x8f92011c, 0x34a52600, 0x8f820120, 0x2403021,
+0x2203821, 0xafa20010, 0xc002b3b, 0xafb00014,
+0x8e020008, 0xafa20010, 0x8e02000c, 0x3c040001,
+0x248464f4, 0xafa20014, 0x8e060000, 0x8e070004,
+0x3c050001, 0xc002b3b, 0x34a52610, 0x8e020018,
+0xafa20010, 0x8e02001c, 0x3c040001, 0x24846500,
+0xafa20014, 0x8e060010, 0x8e070014, 0x3c050001,
+0xc002b3b, 0x34a52620, 0x3c027f00, 0x2221024,
+0x3c030800, 0x54430016, 0x3c030200, 0x8f8200ac,
+0x3042ffff, 0x14400012, 0x3c030200, 0x3c040001,
+0x2484650c, 0x3c050001, 0x34a5f030, 0x3021,
+0x3821, 0x36420002, 0xaf82011c, 0x36220001,
+0xaf8200a0, 0xaf900124, 0xaf92011c, 0xafa00010,
+0xc002b3b, 0xafa00014, 0x10000024, 0x0,
+0x2c31024, 0x1040000d, 0x2231024, 0x1040000b,
+0x36420002, 0xaf82011c, 0x36220001, 0xaf8200a0,
+0xaf900124, 0xaf92011c, 0x8f42032c, 0x24420001,
+0xaf42032c, 0x10000015, 0x8f42032c, 0x3c040001,
+0x248464b8, 0x240202e2, 0xafa20010, 0xafa00014,
+0x8f860144, 0x3c070001, 0x24e764c0, 0xc002b3b,
+0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c,
+0x8f820220, 0x34420004, 0xaf820220, 0x8f820140,
+0x3c030001, 0x431025, 0xaf820140, 0x8fbf0024,
+0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008,
+0x27bd0028, 0x6021, 0x5021, 0x3021,
+0x2821, 0x6821, 0x4821, 0x7821,
+0x7021, 0x8f880124, 0x8f870104, 0x1580002e,
+0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120,
+0x10460029, 0x0, 0x3c040001, 0x8c846ee4,
+0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004,
+0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e,
+0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014,
+0x10000012, 0x24c60020, 0x10400017, 0x0,
+0x3c040001, 0x8c846ee4, 0x8d020000, 0x8d030004,
+0xac820000, 0xac830004, 0x8d020008, 0xac820008,
+0x9502000e, 0xa482000e, 0x8d020010, 0x25060020,
+0xac820010, 0x8d020014, 0x240c0001, 0xc01821,
+0xac820014, 0x27624fe0, 0x43102b, 0x54400001,
+0x27634800, 0x603021, 0x1540002f, 0x31620100,
+0x11200014, 0x31628000, 0x8f820100, 0x1045002a,
+0x31620100, 0x3c040001, 0x8c846ee0, 0x8ca20000,
+0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008,
+0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010,
+0x240a0001, 0xac820010, 0x8ca20014, 0x10000012,
+0x24a50020, 0x10400018, 0x31620100, 0x3c040001,
+0x8c846ee0, 0x8ce20000, 0x8ce30004, 0xac820000,
+0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e,
+0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010,
+0x8ce20014, 0x240a0001, 0xa01821, 0xac820014,
+0x276247e0, 0x43102b, 0x54400001, 0x27634000,
+0x602821, 0x31620100, 0x5440001d, 0x31621000,
+0x11a00009, 0x31a20800, 0x10400004, 0x25020020,
+0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124,
+0x8f880124, 0x6821, 0x11800011, 0x31621000,
+0x3c040001, 0x8c846ee4, 0x8c820000, 0x8c830004,
+0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4,
+0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021,
+0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000,
+0x1440ff82, 0x0, 0x1120000f, 0x31220800,
+0x10400004, 0x3c020002, 0x8f8200b8, 0xa5c20000,
+0x3c020002, 0x1221024, 0x10400004, 0x24e20020,
+0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104,
+0x8f870104, 0x4821, 0x1140ff70, 0x0,
+0x3c040001, 0x8c846ee0, 0x8c820000, 0x8c830004,
+0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4,
+0x9482000e, 0xaf82009c, 0x8c820010, 0x5021,
+0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014,
+0x3e00008, 0x0, 0x6021, 0x5821,
+0x3021, 0x2821, 0x6821, 0x5021,
+0x7821, 0x7021, 0x8f880124, 0x8f870104,
+0x3c180100, 0x1580002e, 0x8f89011c, 0x11a00014,
+0x31220800, 0x8f820120, 0x10460029, 0x0,
+0x3c040001, 0x8c846ee4, 0x8cc20000, 0x8cc30004,
+0xac820000, 0xac830004, 0x8cc20008, 0xac820008,
+0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001,
+0xac820010, 0x8cc20014, 0x10000012, 0x24c60020,
+0x10400017, 0x0, 0x3c040001, 0x8c846ee4,
+0x8d020000, 0x8d030004, 0xac820000, 0xac830004,
+0x8d020008, 0xac820008, 0x9502000e, 0xa482000e,
+0x8d020010, 0x25060020, 0xac820010, 0x8d020014,
+0x240c0001, 0xc01821, 0xac820014, 0x27624fe0,
+0x43102b, 0x54400001, 0x27634800, 0x603021,
+0x1560002f, 0x31220100, 0x11400014, 0x31228000,
+0x8f820100, 0x1045002a, 0x31220100, 0x3c040001,
+0x8c846ee0, 0x8ca20000, 0x8ca30004, 0xac820000,
+0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e,
+0xa482000e, 0x8ca20010, 0x240b0001, 0xac820010,
+0x8ca20014, 0x10000012, 0x24a50020, 0x10400018,
+0x31220100, 0x3c040001, 0x8c846ee0, 0x8ce20000,
+0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008,
+0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010,
+0x24e50020, 0xac820010, 0x8ce20014, 0x240b0001,
+0xa01821, 0xac820014, 0x276247e0, 0x43102b,
+0x54400001, 0x27634000, 0x602821, 0x31220100,
+0x5440001d, 0x31221000, 0x11a00009, 0x31a20800,
+0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000,
+0x25020020, 0xaf820124, 0x8f880124, 0x6821,
+0x11800011, 0x31221000, 0x3c040001, 0x8c846ee4,
+0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084,
+0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac,
+0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010,
+0x8c8f0014, 0x31221000, 0x14400022, 0x0,
+0x1140000f, 0x31420800, 0x10400004, 0x3c020002,
+0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1421024,
+0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4,
+0x24e20020, 0xaf820104, 0x8f870104, 0x5021,
+0x11600010, 0x0, 0x3c040001, 0x8c846ee0,
+0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094,
+0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c,
+0x8c820010, 0x5821, 0xaf8200b0, 0x8c8a0010,
+0x8c8e0014, 0x8f820070, 0x3c031000, 0x431024,
+0x1040ff5c, 0x0, 0x8f820054, 0x24420005,
+0xaf820078, 0x8c040234, 0x10800016, 0x1821,
+0x3c020001, 0x571021, 0x8c4240e8, 0x24420005,
+0x3c010001, 0x370821, 0xac2240e8, 0x3c020001,
+0x571021, 0x8c4240e8, 0x44102b, 0x14400009,
+0x24020001, 0x3c030080, 0x3c010001, 0x370821,
+0xac2040e8, 0x3c010001, 0x370821, 0x1000000c,
+0xa02240f0, 0x3c020001, 0x571021, 0x904240f0,
+0x14400006, 0x3c020080, 0x3c020001, 0x571021,
+0x904240f1, 0x10400002, 0x3c020080, 0x621825,
+0x8c040230, 0x10800013, 0x0, 0x3c020001,
+0x571021, 0x8c4240ec, 0x24420005, 0x3c010001,
+0x370821, 0xac2240ec, 0x3c020001, 0x571021,
+0x8c4240ec, 0x44102b, 0x14400006, 0x0,
+0x3c010001, 0x370821, 0xac2040ec, 0x10000006,
+0x781825, 0x3c020001, 0x571021, 0x904240f2,
+0x54400001, 0x781825, 0x1060ff1a, 0x0,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x431025, 0xaf820060,
+0x8f420000, 0x10400003, 0x0, 0x1000ff05,
+0xaf80004c, 0x1000ff03, 0xaf800048, 0x3e00008,
+0x0, 0x0, 0x0, 0x3c020001,
+0x8c426d28, 0x27bdffe8, 0xafbf0014, 0x14400012,
+0xafb00010, 0x3c100001, 0x26106f90, 0x2002021,
+0xc002ba8, 0x24052000, 0x26021fe0, 0x3c010001,
+0xac226eec, 0x3c010001, 0xac226ee8, 0xac020250,
+0x24022000, 0xac100254, 0xac020258, 0x24020001,
+0x3c010001, 0xac226d28, 0x8fbf0014, 0x8fb00010,
+0x3e00008, 0x27bd0018, 0x3c090001, 0x8d296eec,
+0x8c820000, 0x8fa30010, 0x8fa80014, 0xad220000,
+0x8c820004, 0xad250008, 0xad220004, 0x8f820054,
+0xad260010, 0xad270014, 0xad230018, 0xad28001c,
+0xad22000c, 0x2529ffe0, 0x3c020001, 0x24426f90,
+0x122102b, 0x10400003, 0x0, 0x3c090001,
+0x8d296ee8, 0x3c020001, 0x8c426d10, 0xad220000,
+0x3c020001, 0x8c426d10, 0x3c010001, 0xac296eec,
+0xad220004, 0xac090250, 0x3e00008, 0x0,
+0x27bdffd0, 0xafb00010, 0x3c100001, 0x8e106eec,
+0x3c020001, 0x8c426d10, 0xafb10014, 0x808821,
+0xafbe0024, 0x8fbe0040, 0x8fa40048, 0xafb20018,
+0xa09021, 0xafbf0028, 0xafb50020, 0xafb3001c,
+0xae020000, 0x3c020001, 0x8c426d10, 0xc09821,
+0xe0a821, 0x10800006, 0xae020004, 0x26050008,
+0xc002bb3, 0x24060018, 0x10000005, 0x2610ffe0,
+0x26040008, 0xc002ba8, 0x24050018, 0x2610ffe0,
+0x3c030001, 0x24636f90, 0x203102b, 0x10400003,
+0x0, 0x3c100001, 0x8e106ee8, 0x8e220000,
+0xae020000, 0x8e220004, 0xae120008, 0xae020004,
+0x8f820054, 0xae130010, 0xae150014, 0xae1e0018,
+0x8fa80044, 0xae08001c, 0xae02000c, 0x2610ffe0,
+0x203102b, 0x10400003, 0x0, 0x3c100001,
+0x8e106ee8, 0x3c020001, 0x8c426d10, 0xae020000,
+0x3c020001, 0x8c426d10, 0x3c010001, 0xac306eec,
+0xae020004, 0xac100250, 0x8fbf0028, 0x8fbe0024,
+0x8fb50020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0030, 0x851821,
+0x83102b, 0x10400006, 0x0, 0xac800000,
+0x24840004, 0x83102b, 0x5440fffd, 0xac800000,
+0x3e00008, 0x0, 0xa61821, 0xa3102b,
+0x10400007, 0x0, 0x8c820000, 0xaca20000,
+0x24a50004, 0xa3102b, 0x1440fffb, 0x24840004,
+0x3e00008, 0x0, 0x861821, 0x83102b,
+0x10400007, 0x0, 0x8ca20000, 0xac820000,
+0x24840004, 0x83102b, 0x1440fffb, 0x24a50004,
+0x3e00008, 0x0, 0x63080, 0x861821,
+0x83102b, 0x10400006, 0x0, 0xac850000,
+0x24840004, 0x83102b, 0x5440fffd, 0xac850000,
+0x3e00008, 0x0, 0x0, 0x26e50028,
+0xa03021, 0x274301c0, 0x8f4d0358, 0x8f47035c,
+0x8f480360, 0x8f490364, 0x8f4a0368, 0x8f4b0204,
+0x8f4c0200, 0x24640400, 0x64102b, 0x10400008,
+0x3c0208ff, 0x8cc20000, 0xac620000, 0x24630004,
+0x64102b, 0x1440fffb, 0x24c60004, 0x3c0208ff,
+0x3442ffff, 0x3c03c0ff, 0xaf4d0358, 0xaf47035c,
+0xaf480360, 0xaf490364, 0xaf4a0368, 0xaf4b0204,
+0xaf4c0200, 0x8f840220, 0x3463ffff, 0x8f860200,
+0x821024, 0x34420004, 0xc31824, 0x34630004,
+0xaf820220, 0xaf830200, 0x8ca20214, 0xac020084,
+0x8ca20218, 0xac020088, 0x8ca2021c, 0xac02008c,
+0x8ca20220, 0xac020090, 0x8ca20224, 0xac020094,
+0x8ca20228, 0xac020098, 0x8ca2022c, 0xac02009c,
+0x8ca20230, 0xac0200a0, 0x8ca20234, 0xac0200a4,
+0x8ca20238, 0xac0200a8, 0x8ca2023c, 0xac0200ac,
+0x8ca20240, 0xac0200b0, 0x8ca20244, 0xac0200b4,
+0x8ca20248, 0xac0200b8, 0x8ca2024c, 0xac0200bc,
+0x8ca2001c, 0xac020080, 0x8ca20018, 0xac0200c0,
+0x8ca20020, 0xac0200cc, 0x8ca20024, 0xac0200d0,
+0x8ca201d0, 0xac0200e0, 0x8ca201d4, 0xac0200e4,
+0x8ca201d8, 0xac0200e8, 0x8ca201dc, 0xac0200ec,
+0x8ca201e0, 0xac0200f0, 0x8ca20098, 0x8ca3009c,
+0xac0300fc, 0x8ca200a8, 0x8ca300ac, 0xac0300f4,
+0x8ca200a0, 0x8ca300a4, 0x30840004, 0xac0300f8,
+0x14800007, 0x30c20004, 0x8f820220, 0x3c0308ff,
+0x3463fffb, 0x431024, 0xaf820220, 0x30c20004,
+0x14400006, 0x0, 0x8f820200, 0x3c03c0ff,
+0x3463fffb, 0x431024, 0xaf820200, 0x8f4202dc,
+0xa34005c5, 0x24420001, 0xaf4202dc, 0x8f4202dc,
+0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024,
+0xafb00020, 0x8f430024, 0x8f420020, 0x10620038,
+0x0, 0x8f430020, 0x8f420024, 0x622023,
+0x4810003, 0x0, 0x8f420040, 0x822021,
+0x8f430030, 0x8f420024, 0x43102b, 0x14400005,
+0x0, 0x8f430040, 0x8f420024, 0x10000005,
+0x621023, 0x8f420030, 0x8f430024, 0x431023,
+0x2442ffff, 0x406021, 0x8c102a, 0x54400001,
+0x806021, 0x8f4a0024, 0x8f490040, 0x8f480024,
+0x8f440180, 0x8f450184, 0x8f460024, 0x8f4b001c,
+0x24070001, 0xafa70010, 0x84100, 0x1001821,
+0x14c5021, 0x2529ffff, 0x1498024, 0xafb00014,
+0x8f470014, 0x1021, 0x63100, 0xafa70018,
+0xa32821, 0xa3382b, 0x822021, 0x872021,
+0x8f420108, 0x1663021, 0x40f809, 0xc3900,
+0x54400001, 0xaf500024, 0x8f430024, 0x8f420020,
+0x14620018, 0x0, 0x8f420000, 0x10400007,
+0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
+0x0, 0x10000005, 0x0, 0xaf800048,
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
+0x2403ffef, 0x431024, 0xaf820060, 0x8f420000,
+0x10400003, 0x0, 0x10000002, 0xaf80004c,
+0xaf800048, 0x8fbf0024, 0x8fb00020, 0x3e00008,
+0x27bd0028, 0x3e00008, 0x0, 0x27bdffc0,
+0x32c20020, 0xafbf0038, 0xafb30034, 0xafb20030,
+0xafb1002c, 0x10400004, 0xafb00028, 0x8f530028,
+0x10000002, 0x0, 0x8f530020, 0x8f420030,
+0x105300eb, 0x21100, 0x8f43001c, 0x628021,
+0x8e040000, 0x8e050004, 0x96120008, 0x8f420090,
+0x9611000a, 0x3246ffff, 0x46102a, 0x10400017,
+0x0, 0x8f8200d8, 0x8f430098, 0x431023,
+0x2442dcbe, 0xaf420090, 0x8f420090, 0x2842dcbf,
+0x10400005, 0x0, 0x8f420090, 0x8f430144,
+0x431021, 0xaf420090, 0x8f420090, 0x46102a,
+0x10400006, 0x0, 0x8f420348, 0x24420001,
+0xaf420348, 0x100000e1, 0x8f420348, 0x8f8200fc,
+0x14400006, 0x0, 0x8f420344, 0x24420001,
+0xaf420344, 0x100000d9, 0x8f420344, 0x934205c2,
+0x1040000b, 0x32c20008, 0x10400008, 0x32220200,
+0x10400006, 0x3c034000, 0x9602000e, 0xaf4300ac,
+0x21400, 0x10000002, 0xaf4200b0, 0xaf4000ac,
+0x32220004, 0x1040007f, 0x32220800, 0x10400003,
+0x3247ffff, 0x10000002, 0x24020020, 0x24020004,
+0xafa20010, 0x8f420030, 0xafa20014, 0x8f420010,
+0x3c030002, 0x431025, 0xafa20018, 0x8f460098,
+0x8f420108, 0x40f809, 0x0, 0x104000b7,
+0x0, 0x8f42009c, 0x8f430094, 0x2421021,
+0xaf42009c, 0xae03000c, 0x8f4200ac, 0x10400008,
+0x3c034000, 0x8f420094, 0x431025, 0xafa20020,
+0x8f42009c, 0x8f4300b0, 0x10000004, 0x431025,
+0x8f420094, 0xafa20020, 0x8f42009c, 0xafa20024,
+0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000,
+0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c,
+0x8f440270, 0x8f450274, 0x401821, 0x1021,
+0xa32821, 0xa3302b, 0x822021, 0x862021,
+0x32230060, 0x24020040, 0xaf440270, 0xaf450274,
+0x10620017, 0x2c620041, 0x10400005, 0x24020020,
+0x10620008, 0x24020001, 0x10000026, 0x0,
+0x24020060, 0x10620019, 0x24020001, 0x10000021,
+0x0, 0x8f420278, 0x8f43027c, 0x24630001,
+0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
+0x8f420278, 0x8f43027c, 0x10000016, 0x24020001,
+0x8f420280, 0x8f430284, 0x24630001, 0x2c640001,
+0x441021, 0xaf420280, 0xaf430284, 0x8f420280,
+0x8f430284, 0x1000000b, 0x24020001, 0x8f420288,
+0x8f43028c, 0x24630001, 0x2c640001, 0x441021,
+0xaf420288, 0xaf43028c, 0x8f420288, 0x8f43028c,
+0x24020001, 0xa34205c2, 0x8f420098, 0x3244ffff,
+0x2406fff8, 0x8f45013c, 0x441021, 0x24420007,
+0x461024, 0x24840007, 0xaf420094, 0x8f420090,
+0x8f430094, 0x862024, 0x441023, 0x65182b,
+0x14600005, 0xaf420090, 0x8f420094, 0x8f430144,
+0x431023, 0xaf420094, 0x8f420094, 0x10000023,
+0xaf40009c, 0x3247ffff, 0x50e00022, 0x32c20020,
+0x14400002, 0x24020010, 0x24020002, 0xafa20010,
+0x8f420030, 0xafa20014, 0x8f420010, 0xafa20018,
+0x8f460098, 0x8f420108, 0x40f809, 0x0,
+0x1040003a, 0x3245ffff, 0x8f420098, 0x8f430090,
+0x8f46013c, 0x451021, 0xaf420098, 0x8f42009c,
+0x8f440098, 0xa34005c2, 0x651823, 0xaf430090,
+0x451021, 0x86202b, 0x14800005, 0xaf42009c,
+0x8f420098, 0x8f430144, 0x431023, 0xaf420098,
+0x32c20020, 0x10400005, 0x0, 0x8f420358,
+0x2442ffff, 0xaf420358, 0x8f420358, 0x8f420030,
+0x8f430040, 0x24420001, 0x2463ffff, 0x431024,
+0xaf420030, 0x8f420030, 0x14530018, 0x0,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x2403fff7, 0x431024,
+0xaf820060, 0x8f420000, 0x10400003, 0x0,
+0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0038,
+0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028,
+0x3e00008, 0x27bd0040, 0x3e00008, 0x0,
+0x27bdffd0, 0x32c20020, 0xafbf002c, 0xafb20028,
+0xafb10024, 0x10400004, 0xafb00020, 0x8f520028,
+0x10000002, 0x0, 0x8f520020, 0x8f420030,
+0x105200b5, 0x21100, 0x8f43001c, 0x628021,
+0x8e040000, 0x8e050004, 0x96110008, 0x8f420090,
+0x9607000a, 0x3226ffff, 0x46102a, 0x10400017,
+0x0, 0x8f8200d8, 0x8f430098, 0x431023,
+0x2442dc46, 0xaf420090, 0x8f420090, 0x2842dc47,
+0x10400005, 0x0, 0x8f420090, 0x8f430144,
+0x431021, 0xaf420090, 0x8f420090, 0x46102a,
+0x10400006, 0x0, 0x8f420348, 0x24420001,
+0xaf420348, 0x100000ab, 0x8f420348, 0x8f8600fc,
+0x10c0000c, 0x0, 0x8f8200f4, 0x2403fff8,
+0x431024, 0x461023, 0x218c3, 0x58600001,
+0x24630100, 0x8f42008c, 0x43102b, 0x14400006,
+0x712c2, 0x8f420344, 0x24420001, 0xaf420344,
+0x10000098, 0x8f420344, 0x934305c2, 0x1060000f,
+0x30460001, 0x8f420010, 0x34480400, 0x32c20008,
+0x10400008, 0x30e20200, 0x10400006, 0x3c034000,
+0x9602000e, 0xaf4300ac, 0x21400, 0x10000004,
+0xaf4200b0, 0x10000002, 0xaf4000ac, 0x8f480010,
+0x30e20004, 0x10400045, 0x3227ffff, 0x8f4900ac,
+0x11200005, 0x30c200ff, 0x14400006, 0x24020040,
+0x10000004, 0x24020008, 0x14400002, 0x24020020,
+0x24020004, 0xafa20010, 0x8f430030, 0x11200004,
+0xafa30014, 0x8f4200b0, 0x621025, 0xafa20014,
+0x3c020002, 0x1021025, 0xafa20018, 0x8f460098,
+0x8f420108, 0x40f809, 0x0, 0x10400069,
+0x3224ffff, 0x8f42008c, 0x8f430094, 0x24420001,
+0xaf42008c, 0x24020001, 0xae03000c, 0xa34205c2,
+0x8f420098, 0x2406fff8, 0x8f45013c, 0x441021,
+0x24420007, 0x461024, 0x24840007, 0xaf420094,
+0x8f420090, 0x8f430094, 0x862024, 0x441023,
+0x65182b, 0x14600005, 0xaf420090, 0x8f420094,
+0x8f430144, 0x431023, 0xaf420094, 0x8f430094,
+0x8f420140, 0x43102b, 0x10400009, 0x0,
+0x8f43013c, 0x8f440094, 0x8f420090, 0x8f450138,
+0x641823, 0x431023, 0xaf420090, 0xaf450094,
+0x8f420094, 0x1000001f, 0xaf420098, 0x10e0001d,
+0x30c200ff, 0x14400002, 0x24020010, 0x24020002,
+0xafa20010, 0x8f420030, 0xafa80018, 0xafa20014,
+0x8f460098, 0x8f420108, 0x40f809, 0x0,
+0x10400030, 0x3225ffff, 0x8f420098, 0x8f44013c,
+0x451021, 0xaf420098, 0x8f420090, 0x8f430098,
+0xa34005c2, 0x451023, 0x64182b, 0x14600005,
+0xaf420090, 0x8f420098, 0x8f430144, 0x431023,
+0xaf420098, 0x8f420030, 0x8f430040, 0x24420001,
+0x2463ffff, 0x431024, 0xaf420030, 0x8f420030,
+0x14520018, 0x0, 0x8f420000, 0x10400007,
+0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
+0x0, 0x10000005, 0x0, 0xaf800048,
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
+0x2403fff7, 0x431024, 0xaf820060, 0x8f420000,
+0x10400003, 0x0, 0x10000002, 0xaf80004c,
+0xaf800048, 0x8fbf002c, 0x8fb20028, 0x8fb10024,
+0x8fb00020, 0x3e00008, 0x27bd0030, 0x3e00008,
+0x0, 0x27bdffd8, 0x3c020001, 0x34422ec0,
+0xafbf0020, 0x8f4300f0, 0x8f840108, 0x2e21021,
+0x54620004, 0x24620008, 0x3c020001, 0x34422cc0,
+0x2e21021, 0x401821, 0xaf4300f0, 0xac600000,
+0x8f4200ec, 0x8c660004, 0x14620004, 0x3c020001,
+0x24820020, 0x1000000f, 0xaf820108, 0x8f4300f0,
+0x34422ec0, 0x2e21021, 0x54620004, 0x24620008,
+0x3c020001, 0x34422cc0, 0x2e21021, 0x401821,
+0x8c620004, 0x21140, 0x821021, 0xaf820108,
+0xac600000, 0x8c850018, 0x30a20036, 0x1040006c,
+0x30a20001, 0x8c82001c, 0x8f430040, 0x8f440034,
+0x24420001, 0x2463ffff, 0x431024, 0x862021,
+0xaf42002c, 0x30a20030, 0x14400006, 0xaf440034,
+0x8f420034, 0x8c03023c, 0x43102b, 0x144000b4,
+0x0, 0x32c20010, 0x10400028, 0x24070008,
+0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c,
+0x8f860120, 0x24020080, 0xafa20010, 0xafa30014,
+0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x14400011, 0x24020001, 0x3c010001, 0x370821,
+0xa02240f1, 0x8f820124, 0xafa20010, 0x8f820128,
+0x3c040001, 0x248467c4, 0xafa20014, 0x8f46002c,
+0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51100,
+0x10000036, 0x0, 0x8f420300, 0x8f43002c,
+0x24420001, 0xaf420300, 0x8f420300, 0x24020001,
+0xa34205c1, 0x10000026, 0xaf430038, 0x8f440170,
+0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
+0x24020020, 0xafa20010, 0xafa30014, 0xafa80018,
+0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
+0x24020001, 0x3c010001, 0x370821, 0xa02240f0,
+0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
+0x248467b8, 0xafa20014, 0x8f46002c, 0x8f870120,
+0x3c050009, 0xc002b3b, 0x34a50900, 0x1000000f,
+0x0, 0x8f420300, 0x24420001, 0xaf420300,
+0x8f420300, 0x8f42002c, 0xa34005c1, 0xaf420038,
+0x3c010001, 0x370821, 0xa02040f1, 0x3c010001,
+0x370821, 0xa02040f0, 0xaf400034, 0x8f420314,
+0x24420001, 0xaf420314, 0x10000059, 0x8f420314,
+0x10400022, 0x30a27000, 0x8c85001c, 0x8f420028,
+0xa22023, 0x4810003, 0x0, 0x8f420040,
+0x822021, 0x8f420358, 0x8f430000, 0xaf450028,
+0x441021, 0x10600007, 0xaf420358, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x34420008, 0xaf820060,
+0x8f420000, 0x10400003, 0x0, 0x10000038,
+0xaf80004c, 0x10000036, 0xaf800048, 0x1040002f,
+0x30a21000, 0x1040000c, 0x30a24000, 0x8c83001c,
+0x8f420050, 0x622023, 0x4820001, 0x24840200,
+0x8f42035c, 0x441021, 0xaf42035c, 0x8f420368,
+0x1000001a, 0xaf430050, 0x1040000c, 0x32c28000,
+0x8c83001c, 0x8f420070, 0x622023, 0x4820001,
+0x24840400, 0x8f420364, 0x441021, 0xaf420364,
+0x8f420368, 0x1000000d, 0xaf430070, 0x1040000e,
+0x3c020800, 0x8c83001c, 0x8f420060, 0x622023,
+0x4820001, 0x24840100, 0x8f420360, 0x441021,
+0xaf420360, 0x8f420368, 0xaf430060, 0x441021,
+0xaf420368, 0x3c020800, 0x2c21024, 0x50400008,
+0x36940040, 0x10000006, 0x0, 0x30a20100,
+0x10400003, 0x0, 0xc002bd8, 0x0,
+0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008,
+0x0, 0x27bdffa8, 0xafbf0050, 0xafbe004c,
+0xafb50048, 0xafb30044, 0xafb20040, 0xafb1003c,
+0xafb00038, 0x8f910108, 0x26220020, 0xaf820108,
+0x8e320018, 0xa821, 0x32420024, 0x104001ba,
+0xf021, 0x8e26001c, 0x8f43001c, 0x61100,
+0x621821, 0x8c70000c, 0x9604000c, 0x962d0016,
+0x9473000a, 0x2c8305dd, 0x38828870, 0x2c420001,
+0x621825, 0x10600015, 0x2821, 0x32c20040,
+0x10400015, 0x24020800, 0x96030014, 0x14620012,
+0x3402aaaa, 0x9603000e, 0x14620007, 0x2021,
+0x96030010, 0x24020300, 0x14620004, 0x801021,
+0x96020012, 0x2c440001, 0x801021, 0x54400006,
+0x24050016, 0x10000004, 0x0, 0x24020800,
+0x50820001, 0x2405000e, 0x934205c3, 0x14400008,
+0x5821, 0x240b0001, 0x32620180, 0xaf4500a8,
+0xaf5000a0, 0x10400002, 0xaf4600a4, 0xa34b05c3,
+0x10a00085, 0x2054021, 0x91020000, 0x3821,
+0x3042000f, 0x25080, 0x32c20002, 0x10400012,
+0x10a1821, 0x32620002, 0x10400010, 0x32c20001,
+0x1002021, 0x94820000, 0x24840002, 0xe23821,
+0x83102b, 0x1440fffb, 0x30e2ffff, 0x71c02,
+0x623821, 0x71c02, 0x30e2ffff, 0x623821,
+0x71027, 0xa502000a, 0x32c20001, 0x1040006a,
+0x32620001, 0x10400068, 0x0, 0x8f4200a8,
+0x10400065, 0x0, 0x8f4200a0, 0x8f4300a8,
+0x431021, 0x904c0009, 0x318900ff, 0x39230006,
+0x3182b, 0x39220011, 0x2102b, 0x621824,
+0x1060000c, 0x3c050006, 0x8f4200a4, 0x3c040001,
+0x248467d4, 0xafa20010, 0x8f4200a0, 0x34a54600,
+0x1203821, 0xc002b3b, 0xafa20014, 0x1000004e,
+0x0, 0x32c20004, 0x14400013, 0x2821,
+0x316200ff, 0x14400004, 0x0, 0x95020002,
+0x1000000d, 0x4a2823, 0x9505000c, 0x9502000e,
+0x95030010, 0xa22821, 0xa32821, 0x95030012,
+0x91040009, 0x95020002, 0xa32821, 0xa42821,
+0x4a1023, 0xa22821, 0x2002021, 0x94820000,
+0x24840002, 0xe23821, 0x88102b, 0x1440fffb,
+0x71c02, 0x30e2ffff, 0x623821, 0x71c02,
+0x30e2ffff, 0x623821, 0x1a52821, 0x51c02,
+0x30a2ffff, 0x622821, 0x51c02, 0x30a2ffff,
+0x622821, 0xa72823, 0x51402, 0xa22821,
+0x30a5ffff, 0x50a00001, 0x3405ffff, 0x316200ff,
+0x14400008, 0x318300ff, 0x8f4300a0, 0x8f4200a8,
+0x624021, 0x91020000, 0x3042000f, 0x25080,
+0x318300ff, 0x24020006, 0x14620003, 0x10a1021,
+0x10000002, 0x24440010, 0x24440006, 0x316200ff,
+0x14400006, 0x0, 0x94820000, 0xa22821,
+0x51c02, 0x30a2ffff, 0x622821, 0x934205c3,
+0x10400003, 0x32620100, 0x50400003, 0xa4850000,
+0x52827, 0xa4850000, 0x9622000e, 0x8f43009c,
+0x621821, 0x32a200ff, 0x10400007, 0xaf43009c,
+0x3c024000, 0x2021025, 0xafa20020, 0x8f42009c,
+0x10000003, 0x5e1025, 0xafb00020, 0x8f42009c,
+0xafa20024, 0x32620080, 0x10400010, 0x32620100,
+0x8f4200b4, 0x24430001, 0x210c0, 0x571021,
+0xaf4300b4, 0x8fa30020, 0x8fa40024, 0x3c010001,
+0x220821, 0xac2338e8, 0x3c010001, 0x220821,
+0xac2438ec, 0x100000a5, 0x32c20020, 0x10400064,
+0x0, 0x8f4200b4, 0x24430001, 0x210c0,
+0x571021, 0xaf4300b4, 0x8fa30020, 0x8fa40024,
+0x3c010001, 0x220821, 0xac2338e8, 0x3c010001,
+0x220821, 0xac2438ec, 0x8f4200b4, 0x10400051,
+0x3821, 0x3c090001, 0x352938e8, 0x3c08001f,
+0x3508ffff, 0x240bffff, 0x340affff, 0x710c0,
+0x571021, 0x491021, 0x8c430000, 0x8c440004,
+0xafa30028, 0xafa4002c, 0x8f8200fc, 0x8fa30028,
+0x8fa4002c, 0xac430000, 0xac440004, 0x24420008,
+0xaf8200f0, 0x8f42008c, 0x2442ffff, 0xaf42008c,
+0x97a2002e, 0x8f440270, 0x8f450274, 0x401821,
+0x1021, 0xa32821, 0xa3302b, 0x822021,
+0x862021, 0xaf440270, 0xaf450274, 0x8fa20028,
+0x481024, 0x90430000, 0x30630001, 0x1460000b,
+0x402021, 0x8f420278, 0x8f43027c, 0x24630001,
+0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
+0x8f420278, 0x1000001a, 0x8f43027c, 0x8c820000,
+0x144b000e, 0x0, 0x94820004, 0x144a000b,
+0x0, 0x8f420288, 0x8f43028c, 0x24630001,
+0x2c640001, 0x441021, 0xaf420288, 0xaf43028c,
+0x8f420288, 0x1000000a, 0x8f43028c, 0x8f420280,
+0x8f430284, 0x24630001, 0x2c640001, 0x441021,
+0xaf420280, 0xaf430284, 0x8f420280, 0x8f430284,
+0x8f4200b4, 0x24e70001, 0xe2102b, 0x1440ffb8,
+0x710c0, 0xa34005c3, 0x1000003f, 0xaf4000b4,
+0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000,
+0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c,
+0x8f46008c, 0x8f440270, 0x8f450274, 0x401821,
+0x1021, 0x24c6ffff, 0xaf46008c, 0xa32821,
+0xa3302b, 0x822021, 0x862021, 0xaf440270,
+0xaf450274, 0x92020000, 0x30420001, 0x1440000c,
+0x2402ffff, 0x8f420278, 0x8f43027c, 0x24630001,
+0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
+0x8f420278, 0x8f43027c, 0x1000001c, 0x32c20020,
+0x8e030000, 0x1462000f, 0x3402ffff, 0x96030004,
+0x1462000c, 0x0, 0x8f420288, 0x8f43028c,
+0x24630001, 0x2c640001, 0x441021, 0xaf420288,
+0xaf43028c, 0x8f420288, 0x8f43028c, 0x1000000b,
+0x32c20020, 0x8f420280, 0x8f430284, 0x24630001,
+0x2c640001, 0x441021, 0xaf420280, 0xaf430284,
+0x8f420280, 0x8f430284, 0x32c20020, 0x10400005,
+0xaf40009c, 0x8f420358, 0x2442ffff, 0xaf420358,
+0x8f420358, 0x8e22001c, 0x8f430040, 0x24420001,
+0x2463ffff, 0x431024, 0xaf42002c, 0x32420060,
+0x14400008, 0x32c20010, 0x8f420034, 0x24420001,
+0xaf420034, 0x8c03023c, 0x43102b, 0x14400102,
+0x32c20010, 0x10400018, 0x24070008, 0x8f440170,
+0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
+0x24020080, 0xafa20010, 0xafa30014, 0xafa80018,
+0x8f42010c, 0x40f809, 0x24c6001c, 0x10400047,
+0x24020001, 0x8f420300, 0x8f43002c, 0x24420001,
+0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1,
+0x1000007c, 0xaf430038, 0x8f440170, 0x8f450174,
+0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020,
+0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c,
+0x40f809, 0x24c6001c, 0x10400057, 0x24020001,
+0x10000065, 0x0, 0x32420012, 0x10400075,
+0x32420001, 0x9622000e, 0x8f43009c, 0x621821,
+0x32c20020, 0x10400005, 0xaf43009c, 0x8f420358,
+0x2442ffff, 0xaf420358, 0x8f420358, 0x8e22001c,
+0x8f430040, 0x24420001, 0x2463ffff, 0x431024,
+0xaf42002c, 0x32420010, 0x14400008, 0x32c20010,
+0x8f420034, 0x24420001, 0xaf420034, 0x8c03023c,
+0x43102b, 0x144000bc, 0x32c20010, 0x10400028,
+0x24070008, 0x8f440170, 0x8f450174, 0x8f43002c,
+0x8f48000c, 0x8f860120, 0x24020080, 0xafa20010,
+0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809,
+0x24c6001c, 0x14400011, 0x24020001, 0x3c010001,
+0x370821, 0xa02240f1, 0x8f820124, 0xafa20010,
+0x8f820128, 0x3c040001, 0x248467c4, 0xafa20014,
+0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b,
+0x34a51100, 0x10000036, 0x0, 0x8f420300,
+0x8f43002c, 0x24420001, 0xaf420300, 0x8f420300,
+0x24020001, 0xa34205c1, 0x10000026, 0xaf430038,
+0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c,
+0x8f860120, 0x24020020, 0xafa20010, 0xafa30014,
+0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x14400011, 0x24020001, 0x3c010001, 0x370821,
+0xa02240f0, 0x8f820124, 0xafa20010, 0x8f820128,
+0x3c040001, 0x248467b8, 0xafa20014, 0x8f46002c,
+0x8f870120, 0x3c050009, 0xc002b3b, 0x34a50900,
+0x1000000f, 0x0, 0x8f420300, 0x24420001,
+0xaf420300, 0x8f420300, 0x8f42002c, 0xa34005c1,
+0xaf420038, 0x3c010001, 0x370821, 0xa02040f1,
+0x3c010001, 0x370821, 0xa02040f0, 0xaf400034,
+0x8f420314, 0x24420001, 0xaf420314, 0x10000062,
+0x8f420314, 0x10400022, 0x32427000, 0x8e25001c,
+0x8f420028, 0xa22023, 0x4810003, 0x0,
+0x8f420040, 0x822021, 0x8f420358, 0x8f430000,
+0xaf450028, 0x441021, 0x10600007, 0xaf420358,
+0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
+0x10000005, 0x0, 0xaf800048, 0x8f820048,
+0x1040fffd, 0x0, 0x8f820060, 0x34420008,
+0xaf820060, 0x8f420000, 0x10400003, 0x0,
+0x10000041, 0xaf80004c, 0x1000003f, 0xaf800048,
+0x1040002f, 0x32421000, 0x1040000c, 0x32424000,
+0x8e23001c, 0x8f420050, 0x622023, 0x4820001,
+0x24840200, 0x8f42035c, 0x441021, 0xaf42035c,
+0x8f420368, 0x1000001a, 0xaf430050, 0x1040000c,
+0x32c28000, 0x8e23001c, 0x8f420070, 0x622023,
+0x4820001, 0x24840400, 0x8f420364, 0x441021,
+0xaf420364, 0x8f420368, 0x1000000d, 0xaf430070,
+0x1040000e, 0x3c020800, 0x8e23001c, 0x8f420060,
+0x622023, 0x4820001, 0x24840100, 0x8f420360,
+0x441021, 0xaf420360, 0x8f420368, 0xaf430060,
+0x441021, 0xaf420368, 0x3c020800, 0x2c21024,
+0x50400011, 0x36940040, 0x1000000f, 0x0,
+0x32420048, 0x10400007, 0x24150001, 0x8e22001c,
+0x3c03ffff, 0x43f024, 0x3042ffff, 0x1000fd75,
+0xae22001c, 0x32420100, 0x10400003, 0x0,
+0xc002bd8, 0x0, 0x8fbf0050, 0x8fbe004c,
+0x8fb50048, 0x8fb30044, 0x8fb20040, 0x8fb1003c,
+0x8fb00038, 0x3e00008, 0x27bd0058, 0x3e00008,
+0x0, 0x0, 0x0, 0x8f8300e4,
+0x8f8200e0, 0x2404fff8, 0x441024, 0x621026,
+0x2102b, 0x21023, 0x3e00008, 0x621024,
+0x3e00008, 0x0, 0x27bdffe0, 0xafbf001c,
+0xafb00018, 0x8f8600c4, 0x8f8400e0, 0x8f8500e4,
+0x2402fff8, 0x821824, 0x10a30009, 0x27623ff8,
+0x14a20002, 0x24a20008, 0x27623000, 0x408021,
+0x16030005, 0x30820004, 0x10400004, 0xc02021,
+0x10000022, 0x1021, 0x8e040000, 0x8f42011c,
+0x14a20003, 0x0, 0x8f420120, 0xaf420114,
+0x8ca30000, 0x8f420148, 0x831823, 0x43102b,
+0x10400003, 0x0, 0x8f420148, 0x621821,
+0x94a20006, 0x24420050, 0x62102b, 0x1440000f,
+0xa01021, 0xafa40010, 0xafa30014, 0x8ca60000,
+0x8ca70004, 0x3c040001, 0xc002b3b, 0x24846894,
+0x8f42020c, 0x24420001, 0xaf42020c, 0x8f42020c,
+0x1021, 0xaf9000e8, 0xaf9000e4, 0x8fbf001c,
+0x8fb00018, 0x3e00008, 0x27bd0020, 0x3e00008,
+0x0, 0x8f8400e0, 0x8f8800c4, 0x8f8300e8,
+0x2402fff8, 0x823824, 0xe32023, 0x2c821000,
+0x50400001, 0x24841000, 0x420c2, 0x801821,
+0x8f440258, 0x8f45025c, 0x1021, 0xa32821,
+0xa3302b, 0x822021, 0x862021, 0xaf440258,
+0xaf45025c, 0x8f8300c8, 0x8f420148, 0x1032023,
+0x82102b, 0x14400004, 0x801821, 0x8f420148,
+0x822021, 0x801821, 0x8f440250, 0x8f450254,
+0x1021, 0xa32821, 0xa3302b, 0x822021,
+0x862021, 0xaf440250, 0xaf450254, 0xaf8800c8,
+0xaf8700e4, 0xaf8700e8, 0x3e00008, 0x0,
+0x27bdff30, 0x240a0001, 0xafbf00c8, 0xafbe00c4,
+0xafb500c0, 0xafb300bc, 0xafb200b8, 0xafb100b4,
+0xafb000b0, 0xa3a00097, 0xafa00044, 0xafaa005c,
+0x934205c4, 0xa7a0008e, 0x1040000a, 0xa7a00086,
+0x8f4b00c4, 0xafab0064, 0x8f4a00c0, 0xafaa006c,
+0x8f4b00cc, 0xafab0074, 0x8f4a00c8, 0x10000129,
+0xafaa007c, 0x8f420114, 0x40f809, 0x0,
+0x403021, 0x10c0034f, 0x0, 0x8cc20000,
+0x8cc30004, 0xafa20020, 0xafa30024, 0x8fab0024,
+0x8faa0020, 0x3162ffff, 0x2442fffc, 0xafa2006c,
+0x3c020006, 0x2c21024, 0xafab007c, 0x14400015,
+0xafaa0064, 0x91420000, 0x30420001, 0x10400011,
+0x2402ffff, 0x8d430000, 0x14620004, 0x3402ffff,
+0x95430004, 0x1062000b, 0x0, 0xc0024bb,
+0x8fa40064, 0x304200ff, 0x14400006, 0x0,
+0x8f420118, 0x40f809, 0x0, 0x1000032d,
+0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff,
+0x431024, 0x3c03ffff, 0x431824, 0x14600003,
+0xafa20024, 0x10000040, 0x1821, 0x3c020080,
+0x621024, 0x10400007, 0x0, 0x8f42038c,
+0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036,
+0x24030001, 0x8f420210, 0x24420001, 0xaf420210,
+0x8f420210, 0x3c020001, 0x621024, 0x10400006,
+0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4,
+0x8f4201c4, 0x3c020002, 0x621024, 0x10400006,
+0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c,
+0x8f42037c, 0x3c020004, 0x621024, 0x10400006,
+0x3c020008, 0x8f420380, 0x24420001, 0xaf420380,
+0x8f420380, 0x3c020008, 0x621024, 0x10400006,
+0x3c020010, 0x8f420384, 0x24420001, 0xaf420384,
+0x8f420384, 0x3c020010, 0x621024, 0x10400006,
+0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0,
+0x8f4201c0, 0x3c020020, 0x621024, 0x10400006,
+0x24030001, 0x8f420388, 0x24420001, 0xaf420388,
+0x8f420388, 0x24030001, 0x8c020260, 0x8fab006c,
+0x4b102b, 0x10400014, 0x307000ff, 0x8f4201e8,
+0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8faa007c,
+0x8f8200e0, 0x354a0100, 0xafaa007c, 0xafa20010,
+0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0,
+0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007,
+0xc002b3b, 0x34a50800, 0x12000010, 0x3c020080,
+0x2c21024, 0x1440000e, 0x32c20400, 0x8fab007c,
+0x3c020080, 0x34420100, 0x1621024, 0x10400005,
+0x0, 0x8f42020c, 0x24420001, 0xaf42020c,
+0x8f42020c, 0x100002b0, 0x8fa3006c, 0x32c20400,
+0x10400015, 0x34028100, 0x8faa0064, 0x9543000c,
+0x14620012, 0x3c020100, 0x240b0200, 0xa7ab008e,
+0x9542000e, 0x8d430008, 0x8d440004, 0x8d450000,
+0x8faa006c, 0x8fab0064, 0x254afffc, 0xafaa006c,
+0xa7a20086, 0xad63000c, 0xad640008, 0xad650004,
+0x256b0004, 0xafab0064, 0x3c020100, 0x2c21024,
+0x10400004, 0x0, 0x8faa006c, 0x254a0004,
+0xafaa006c, 0x8f4200bc, 0x5040000a, 0xafa00074,
+0x8fab006c, 0x4b102b, 0x50400006, 0xafa00074,
+0x8f4200bc, 0x1621023, 0xafa20074, 0x8f4a00bc,
+0xafaa006c, 0x8f420080, 0x8fab006c, 0x4b102b,
+0x10400056, 0x32c28000, 0x1040005e, 0x240a0003,
+0x32c21000, 0x1040005b, 0xafaa005c, 0x10000058,
+0x240b0004, 0x8f420350, 0x2403ffbf, 0x283a024,
+0x24420001, 0xaf420350, 0x1000024f, 0x8f420350,
+0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128,
+0x3c040001, 0x248468d0, 0x26620001, 0xafa20014,
+0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007,
+0xc002b3b, 0x34a52250, 0x1000023f, 0x0,
+0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128,
+0x3c040001, 0x248468d0, 0x24020002, 0xafa20014,
+0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007,
+0xc002b3b, 0x34a52450, 0x1000022f, 0x0,
+0x8ea20000, 0x8ea30004, 0x3c040001, 0x248468e8,
+0xafb00010, 0xafbe0014, 0x8ea70018, 0x34a52800,
+0xc002b3b, 0x603021, 0x10000223, 0x0,
+0xa6b1000a, 0x8f820124, 0x3c040001, 0x248468f0,
+0xafbe0014, 0xafa20010, 0x8f460044, 0x8f870120,
+0x3c050007, 0xc002b3b, 0x34a53000, 0x10000216,
+0x0, 0xa6b1000a, 0xa6b2000e, 0x8f820124,
+0x3c040001, 0x248468fc, 0xafbe0014, 0xafa20010,
+0x8f460044, 0x8f870120, 0x3c050007, 0xc002b3b,
+0x34a53200, 0x10000208, 0x0, 0x8f420084,
+0x8faa006c, 0x4a102b, 0x14400007, 0x3c020001,
+0x2c21024, 0x10400004, 0x0, 0x240b0002,
+0xafab005c, 0x8faa006c, 0x1140021b, 0x27ab0020,
+0xafab00a4, 0x3c0a001f, 0x354affff, 0xafaa009c,
+0x8fab005c, 0x240a0001, 0x556a0021, 0x240a0002,
+0x8f430054, 0x8f420050, 0x1062000b, 0x274b0054,
+0x8f5e0054, 0x3403ecc0, 0xafab004c, 0x27c20001,
+0x304201ff, 0xafa20054, 0x1e1140, 0x431021,
+0x1000006b, 0x2e2a821, 0x8f420044, 0x8faa006c,
+0x3c040001, 0x248468ac, 0xafaa0014, 0xafa20010,
+0x8f460054, 0x8f470050, 0x3c050007, 0xc002b3b,
+0x34a51300, 0x8f430350, 0x2402ffbf, 0x282a024,
+0x24630001, 0xaf430350, 0x100001d3, 0x8f420350,
+0x156a001d, 0x0, 0x8f430074, 0x8f420070,
+0x1062000a, 0x274b0074, 0x8f5e0074, 0xafab004c,
+0x27c20001, 0x304203ff, 0xafa20054, 0x1e1140,
+0x24426cc0, 0x1000004a, 0x2e2a821, 0x8f420044,
+0x8faa006c, 0x3c040001, 0x248468b8, 0x3c050007,
+0xafaa0014, 0xafa20010, 0x8f460074, 0x8f470070,
+0x34a51500, 0x240b0001, 0xc002b3b, 0xafab005c,
+0x1000ffc3, 0x0, 0x8f430064, 0x8f420060,
+0x1062001a, 0x274a0064, 0x8f5e0064, 0x8fab005c,
+0xafaa004c, 0x27c20001, 0x304200ff, 0xafa20054,
+0x24020004, 0x1562000e, 0x1e1140, 0x1e1180,
+0x24420cc0, 0x2e21021, 0xafa20044, 0x9442002a,
+0x8faa0044, 0x8fab006c, 0x4b102b, 0x10400024,
+0x25550020, 0x240a0001, 0x10000021, 0xa3aa0097,
+0x24424cc0, 0x1000001e, 0x2e2a821, 0x8f420044,
+0x8fab006c, 0x3c040001, 0x248468c4, 0xafab0014,
+0xafa20010, 0x8f460064, 0x8f470060, 0x3c050007,
+0xc002b3b, 0x34a51800, 0x3c020008, 0x2c21024,
+0x1440ff34, 0x0, 0x8f420370, 0x240a0001,
+0xafaa005c, 0x24420001, 0xaf420370, 0x1000ff90,
+0x8f420370, 0x27a30036, 0x131040, 0x621821,
+0x94620000, 0x441021, 0x10000020, 0xa4620000,
+0x8fab0064, 0xaeab0018, 0x93a20097, 0x10400072,
+0x9821, 0x8faa0044, 0x8fa4006c, 0x8fa300a4,
+0x25420020, 0xafa20028, 0x25420008, 0xafa20030,
+0x25420010, 0xafaa002c, 0xafa20034, 0x9542002a,
+0xa7a20038, 0x95420018, 0xa7a2003a, 0x9542001a,
+0xa7a2003c, 0x9542001c, 0xa7a2003e, 0x94620018,
+0x24630002, 0x822023, 0x1880ffde, 0x26730001,
+0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc,
+0x26650001, 0xa2102a, 0x1440002b, 0x24030001,
+0x8f83012c, 0x10600023, 0x0, 0x8f820124,
+0x431023, 0x22143, 0x58800001, 0x24840040,
+0x8f820128, 0x431023, 0x21943, 0x58600001,
+0x24630040, 0x64102a, 0x54400001, 0x602021,
+0xaf4400fc, 0x8f4200fc, 0xa2102a, 0x10400011,
+0x24030001, 0x10000015, 0x306200ff, 0x8fab0064,
+0x96070018, 0xafab0010, 0x8e220008, 0x3c040001,
+0x248468dc, 0x8c430004, 0x8c420000, 0x34a52400,
+0x2403021, 0xc002b3b, 0xafa30014, 0x1000002b,
+0x0, 0x8f420334, 0x1821, 0x24420001,
+0xaf420334, 0x8f420334, 0x306200ff, 0x5040fedc,
+0x3c020800, 0x12600021, 0x9021, 0x8fb100a4,
+0x2208021, 0x8e220008, 0x96070018, 0x8fa60064,
+0x8c440000, 0x8c450004, 0x240a0001, 0xafaa0010,
+0xafbe0014, 0x8f420008, 0xafa20018, 0x8f42010c,
+0x40f809, 0x0, 0x1040ffd8, 0x3c050007,
+0x96020018, 0x8fab0064, 0x8faa009c, 0x1625821,
+0x14b102b, 0x10400004, 0xafab0064, 0x8f420148,
+0x1625823, 0xafab0064, 0x26100002, 0x26520001,
+0x253102b, 0x1440ffe3, 0x26310004, 0x8fb0006c,
+0x10000036, 0x97b10038, 0x8f4200fc, 0x24050002,
+0xa2102a, 0x1440001b, 0x24030001, 0x8f83012c,
+0x10600013, 0x0, 0x8f820124, 0x431023,
+0x22143, 0x58800001, 0x24840040, 0x8f820128,
+0x431023, 0x21943, 0x58600001, 0x24630040,
+0x64102a, 0x54400001, 0x602021, 0xaf4400fc,
+0x8f4200fc, 0xa2102a, 0x14400006, 0x24030001,
+0x8f420334, 0x1821, 0x24420001, 0xaf420334,
+0x8f420334, 0x306200ff, 0x1040fea5, 0x3c020800,
+0x96b1000a, 0x8fb0006c, 0x3223ffff, 0x70102b,
+0x54400001, 0x608021, 0x8ea40000, 0x8ea50004,
+0x240b0001, 0xafab0010, 0xafbe0014, 0x8f420008,
+0x8fa60064, 0xafa20018, 0x8f42010c, 0x40f809,
+0x2003821, 0x1040fea2, 0x3c050007, 0x96a3000e,
+0x97aa008e, 0x11400007, 0x609021, 0x934205c4,
+0x14400004, 0x0, 0x97ab0086, 0x6a1825,
+0xa6ab0016, 0x8faa007c, 0x3c02ffff, 0x1421024,
+0x10400003, 0xa1402, 0x34630400, 0xa6a20014,
+0x8fab006c, 0x560b0072, 0xa6a3000e, 0x34620004,
+0xa6a2000e, 0x8faa0074, 0x16a1021, 0xa6a2000a,
+0x8f430044, 0x8f4401a0, 0x8f4501a4, 0x34028000,
+0xafa20010, 0x8f420044, 0x2a03021, 0x24070020,
+0xafa20014, 0x8f42000c, 0x31940, 0x604821,
+0xafa20018, 0x8f42010c, 0x4021, 0xa92821,
+0xa9182b, 0x882021, 0x40f809, 0x832021,
+0x5040fe7f, 0xa6b2000e, 0x8f420368, 0xafa0006c,
+0xa34005c4, 0x2442ffff, 0xaf420368, 0x8fab005c,
+0x240a0001, 0x8f420368, 0x156a0006, 0x240a0002,
+0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c,
+0x8f42035c, 0x156a0006, 0x0, 0x8f420364,
+0x2442ffff, 0xaf420364, 0x10000005, 0x8f420364,
+0x8f420360, 0x2442ffff, 0xaf420360, 0x8f420360,
+0x8faa0054, 0x8fab004c, 0xad6a0000, 0x8f420044,
+0x8f440088, 0x8f430078, 0x24420001, 0x441024,
+0x24630001, 0xaf420044, 0xaf430078, 0x8c020240,
+0x62182b, 0x14600075, 0x24070008, 0x8f440168,
+0x8f45016c, 0x8f430044, 0x8f48000c, 0x8f860120,
+0x24020040, 0xafa20010, 0xafa30014, 0xafa80018,
+0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
+0x240b0001, 0x3c010001, 0x370821, 0xa02b40f2,
+0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
+0x2484688c, 0xafa20014, 0x8f460044, 0x8f870120,
+0x3c050009, 0xc002b3b, 0x34a51300, 0x1000000b,
+0x0, 0x8f420304, 0x24420001, 0xaf420304,
+0x8f420304, 0x8f420044, 0xaf42007c, 0x3c010001,
+0x370821, 0xa02040f2, 0xaf400078, 0x8f420318,
+0x24420001, 0xaf420318, 0x10000048, 0x8f420318,
+0xa6b0000a, 0x8f430044, 0x8f4401a0, 0x8f4501a4,
+0x34028000, 0xafa20010, 0x8f420044, 0x2a03021,
+0x24070020, 0xafa20014, 0x8f42000c, 0x31940,
+0x604821, 0xafa20018, 0x8f42010c, 0x4021,
+0xa92821, 0xa9182b, 0x882021, 0x40f809,
+0x832021, 0x1040fe1f, 0x240a0001, 0xa34a05c4,
+0x8fab006c, 0x8faa0064, 0x1705823, 0xafab006c,
+0x8fab009c, 0x1505021, 0x16a102b, 0x10400004,
+0xafaa0064, 0x8f420148, 0x1425023, 0xafaa0064,
+0x8f420368, 0x2442ffff, 0xaf420368, 0x8faa005c,
+0x240b0001, 0x8f420368, 0x154b0006, 0x240b0002,
+0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c,
+0x8f42035c, 0x114b0006, 0x0, 0x8f420360,
+0x2442ffff, 0xaf420360, 0x10000005, 0x8f420360,
+0x8f420364, 0x2442ffff, 0xaf420364, 0x8f420364,
+0x8fab0054, 0x8faa004c, 0xad4b0000, 0x8f420044,
+0x8f440088, 0x8f430078, 0x24420001, 0x441024,
+0x24630001, 0xaf420044, 0xaf430078, 0x8faa006c,
+0x1540fe0b, 0x0, 0x8fab006c, 0x1160001e,
+0x0, 0x934205c4, 0x10400009, 0x0,
+0x8faa0064, 0xaf4a00c4, 0xaf4b00c0, 0x8fab007c,
+0xaf4b00c8, 0x8faa0074, 0x1000000e, 0xaf4a00cc,
+0x97ab008e, 0x1160000b, 0x34038100, 0x8fa20020,
+0x8c46000c, 0xa443000c, 0x97aa0086, 0x8c440004,
+0x8c450008, 0xa44a000e, 0xac440000, 0xac450004,
+0xac460008, 0x8f42034c, 0x24420001, 0xaf42034c,
+0x10000010, 0x8f42034c, 0x8fab007c, 0x3164ffff,
+0x2484fffc, 0x801821, 0x8f440250, 0x8f450254,
+0x8f460118, 0x1021, 0xa32821, 0xa3382b,
+0x822021, 0x872021, 0xaf440250, 0xc0f809,
+0xaf450254, 0x8fbf00c8, 0x8fbe00c4, 0x8fb500c0,
+0x8fb300bc, 0x8fb200b8, 0x8fb100b4, 0x8fb000b0,
+0x3e00008, 0x27bd00d0, 0x3e00008, 0x0,
+0x27bdff38, 0x240b0001, 0xafbf00c0, 0xafbe00bc,
+0xafb500b8, 0xafb300b4, 0xafb200b0, 0xafb100ac,
+0xafb000a8, 0xa3a00087, 0xafa00044, 0xafab005c,
+0x934205c4, 0xa7a00076, 0x10400007, 0xa7a0007e,
+0x8f4c00c0, 0xafac0064, 0x8f4b00c8, 0x8f5e00c4,
+0x10000130, 0xafab006c, 0x8f420114, 0x40f809,
+0x0, 0x403021, 0x10c002a1, 0x0,
+0x8cc20000, 0x8cc30004, 0xafa20020, 0xafa30024,
+0x8fac0024, 0x8fbe0020, 0x3182ffff, 0x2442fffc,
+0xafa20064, 0x3c020006, 0x2c21024, 0x14400015,
+0xafac006c, 0x93c20000, 0x30420001, 0x10400011,
+0x2402ffff, 0x8fc30000, 0x14620004, 0x3402ffff,
+0x97c30004, 0x1062000b, 0x0, 0xc0024bb,
+0x3c02021, 0x304200ff, 0x14400006, 0x0,
+0x8f420118, 0x40f809, 0x0, 0x10000280,
+0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff,
+0x431024, 0x3c03ffff, 0x431824, 0x14600003,
+0xafa20024, 0x10000040, 0x8021, 0x3c020080,
+0x621024, 0x10400007, 0x0, 0x8f42038c,
+0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036,
+0x24100001, 0x8f420210, 0x24420001, 0xaf420210,
+0x8f420210, 0x3c020001, 0x621024, 0x10400006,
+0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4,
+0x8f4201c4, 0x3c020002, 0x621024, 0x10400006,
+0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c,
+0x8f42037c, 0x3c020004, 0x621024, 0x10400006,
+0x3c020008, 0x8f420380, 0x24420001, 0xaf420380,
+0x8f420380, 0x3c020008, 0x621024, 0x10400006,
+0x3c020010, 0x8f420384, 0x24420001, 0xaf420384,
+0x8f420384, 0x3c020010, 0x621024, 0x10400006,
+0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0,
+0x8f4201c0, 0x3c020020, 0x621024, 0x10400006,
+0x24100001, 0x8f420388, 0x24420001, 0xaf420388,
+0x8f420388, 0x24100001, 0x8c020260, 0x8fab0064,
+0x4b102b, 0x10400015, 0x320200ff, 0x8f4201e8,
+0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8fac006c,
+0x8f8200e0, 0x358c0100, 0xafac006c, 0xafa20010,
+0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0,
+0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007,
+0xc002b3b, 0x34a53600, 0x320200ff, 0x10400010,
+0x3c020080, 0x2c21024, 0x1440000e, 0x32c20400,
+0x8fab006c, 0x3c020080, 0x34420100, 0x1621024,
+0x10400005, 0x0, 0x8f42020c, 0x24420001,
+0xaf42020c, 0x8f42020c, 0x10000202, 0x8fa30064,
+0x32c20400, 0x10400012, 0x34028100, 0x97c3000c,
+0x1462000f, 0x0, 0x240c0200, 0xa7ac0076,
+0x97c2000e, 0x8fc30008, 0x8fc40004, 0x8fab0064,
+0x8fc50000, 0x256bfffc, 0xafab0064, 0xa7a2007e,
+0xafc3000c, 0xafc40008, 0xafc50004, 0x27de0004,
+0x8fa70064, 0x320200ff, 0x14400034, 0x3c020100,
+0x97c4000c, 0x2c8305dd, 0x38828870, 0x2c420001,
+0x621825, 0x10600015, 0x2821, 0x32c20800,
+0x10400015, 0x24020800, 0x97c30014, 0x14620012,
+0x3402aaaa, 0x97c3000e, 0x14620007, 0x2021,
+0x97c30010, 0x24020300, 0x14620004, 0x801021,
+0x97c20012, 0x2c440001, 0x801021, 0x54400006,
+0x24050016, 0x10000004, 0x0, 0x24020800,
+0x50820001, 0x2405000e, 0x10a00013, 0x3c52021,
+0x24830009, 0x3c02001f, 0x3442ffff, 0x43102b,
+0x10400003, 0x0, 0x8f420148, 0x621823,
+0x90620000, 0x38430006, 0x2c630001, 0x38420011,
+0x2c420001, 0x621825, 0x10600004, 0x3c020100,
+0x94820002, 0x453821, 0x3c020100, 0x2c21024,
+0x5040000e, 0xafa70064, 0x8fac0064, 0x10ec0008,
+0x3c050007, 0x3c040001, 0x24846908, 0x8fa60064,
+0x34a54000, 0xafa00010, 0xc002b3b, 0xafa00014,
+0x8fab0064, 0x256b0004, 0xafab0064, 0x8f420080,
+0x8fac0064, 0x4c102b, 0x1040002c, 0x32c28000,
+0x10400034, 0x240b0003, 0x32c21000, 0x10400031,
+0xafab005c, 0x1000002e, 0x240c0004, 0x8f420350,
+0x2403ffbf, 0x283a024, 0x24420001, 0xaf420350,
+0x10000173, 0x8f420350, 0x3c020800, 0x2c2b025,
+0x2402ffbf, 0x282a024, 0x8f830128, 0x3c040001,
+0x248468d0, 0x26620001, 0xafa20014, 0xafa30010,
+0x8f860120, 0x8f870124, 0x3c050007, 0xc002b3b,
+0x34a55300, 0x10000162, 0x0, 0x8ea20000,
+0x8ea30004, 0x3c040001, 0x248468e8, 0xafb00010,
+0xafb10014, 0x8ea70018, 0x34a55900, 0xc002b3b,
+0x603021, 0x10000156, 0x0, 0x8f420084,
+0x8fab0064, 0x4b102b, 0x14400007, 0x3c020001,
+0x2c21024, 0x10400004, 0x0, 0x240c0002,
+0xafac005c, 0x8fab0064, 0x11600166, 0x27ac0020,
+0xafac008c, 0x8fab005c, 0x240c0001, 0x556c0021,
+0x240c0002, 0x8f430054, 0x8f420050, 0x1062000b,
+0x274b0054, 0x8f510054, 0x3403ecc0, 0xafab004c,
+0x26220001, 0x304201ff, 0xafa20054, 0x111140,
+0x431021, 0x1000006b, 0x2e2a821, 0x8f420044,
+0x8fac0064, 0x3c040001, 0x248468ac, 0xafac0014,
+0xafa20010, 0x8f460054, 0x8f470050, 0x3c050007,
+0xc002b3b, 0x34a54300, 0x8f430350, 0x2402ffbf,
+0x282a024, 0x24630001, 0xaf430350, 0x10000124,
+0x8f420350, 0x156c001d, 0x0, 0x8f430074,
+0x8f420070, 0x1062000a, 0x274b0074, 0x8f510074,
+0xafab004c, 0x26220001, 0x304203ff, 0xafa20054,
+0x111140, 0x24426cc0, 0x1000004a, 0x2e2a821,
+0x8f420044, 0x8fac0064, 0x3c040001, 0x248468b8,
+0x3c050007, 0xafac0014, 0xafa20010, 0x8f460074,
+0x8f470070, 0x34a54500, 0x240b0001, 0xc002b3b,
+0xafab005c, 0x1000ffc3, 0x0, 0x8f430064,
+0x8f420060, 0x1062001a, 0x274c0064, 0x8f510064,
+0x8fab005c, 0xafac004c, 0x26220001, 0x304200ff,
+0xafa20054, 0x24020004, 0x1562000e, 0x111140,
+0x111180, 0x24420cc0, 0x2e21021, 0xafa20044,
+0x9442002a, 0x8fac0044, 0x8fab0064, 0x4b102b,
+0x10400024, 0x25950020, 0x240c0001, 0x10000021,
+0xa3ac0087, 0x24424cc0, 0x1000001e, 0x2e2a821,
+0x8f420044, 0x8fab0064, 0x3c040001, 0x248468c4,
+0xafab0014, 0xafa20010, 0x8f460064, 0x8f470060,
+0x3c050007, 0xc002b3b, 0x34a54800, 0x3c020008,
+0x2c21024, 0x1440ff61, 0x0, 0x8f420370,
+0x240c0001, 0xafac005c, 0x24420001, 0xaf420370,
+0x1000ff90, 0x8f420370, 0x27a30036, 0x131040,
+0x621821, 0x94620000, 0x441021, 0x1000001f,
+0xa4620000, 0xaebe0018, 0x93a20087, 0x10400084,
+0x9821, 0x8fab0044, 0x8fa40064, 0x8fa3008c,
+0x25620020, 0xafa20028, 0x25620008, 0xafa20030,
+0x25620010, 0xafab002c, 0xafa20034, 0x9562002a,
+0xa7a20038, 0x95620018, 0xa7a2003a, 0x9562001a,
+0xa7a2003c, 0x9562001c, 0xa7a2003e, 0x94620018,
+0x24630002, 0x822023, 0x1880ffdf, 0x26730001,
+0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc,
+0x262102a, 0x14400030, 0x24030001, 0x8f83012c,
+0x10600028, 0x0, 0x8f820124, 0x431023,
+0x22143, 0x58800001, 0x24840040, 0x8f820128,
+0x431023, 0x21943, 0x58600001, 0x24630040,
+0x64102a, 0x54400001, 0x602021, 0xaf4400fc,
+0x8f4200fc, 0x262102a, 0x10400016, 0x24030001,
+0x1000001a, 0x306200ff, 0x8fac008c, 0x101040,
+0x4c1021, 0x94470018, 0x101080, 0x4c1021,
+0xafbe0010, 0x8c420008, 0x3c040001, 0x248468dc,
+0x3c050007, 0x8c430004, 0x8c420000, 0x34a55500,
+0x2003021, 0xc002b3b, 0xafa30014, 0x10000039,
+0x0, 0x8f420334, 0x1821, 0x24420001,
+0xaf420334, 0x8f420334, 0x306200ff, 0x1040ff06,
+0x8021, 0x8f430008, 0x2402fbff, 0x1260002d,
+0x625024, 0x3c0b4000, 0x22b4025, 0x8fb1008c,
+0x2669ffff, 0x2209021, 0x8e420008, 0x96270018,
+0x8c440000, 0x8c450004, 0x56090004, 0x240b0001,
+0x240c0002, 0x10000002, 0xafac0010, 0xafab0010,
+0x16000004, 0xafa80014, 0x8f420008, 0x10000002,
+0xafa20018, 0xafaa0018, 0x8f42010c, 0x3c03021,
+0xafa80098, 0xafa9009c, 0x40f809, 0xafaa00a0,
+0x8fa80098, 0x8fa9009c, 0x8faa00a0, 0x1040ffc2,
+0x3c02001f, 0x96230018, 0x3442ffff, 0x3c3f021,
+0x5e102b, 0x10400003, 0x26310002, 0x8f420148,
+0x3c2f023, 0x26100001, 0x213102b, 0x1440ffda,
+0x26520004, 0x8fb00064, 0x1000001a, 0x0,
+0x96a3000a, 0x8fb00064, 0x70102b, 0x54400001,
+0x608021, 0x8ea40000, 0x8ea50004, 0x8fab005c,
+0x240c0002, 0xafac0010, 0x934305c4, 0xb1700,
+0x10600003, 0x2223025, 0x3c020800, 0xc23025,
+0xafa60014, 0x8f420008, 0xafa20018, 0x8f42010c,
+0x3c03021, 0x40f809, 0x2003821, 0x1040fecb,
+0x3c050007, 0x97ac0076, 0x11800007, 0x96a3000e,
+0x934205c4, 0x14400004, 0x0, 0x97ab007e,
+0x6c1825, 0xa6ab0016, 0x8fac006c, 0x3c02ffff,
+0x1821024, 0x10400003, 0xc1402, 0x34630400,
+0xa6a20014, 0xa6b0000a, 0x8fab0064, 0x560b0006,
+0x3d0f021, 0x34620004, 0xafa00064, 0xa6a2000e,
+0x1000000d, 0xa34005c4, 0x8fac0064, 0x3c02001f,
+0x3442ffff, 0x5e102b, 0x1906023, 0xafac0064,
+0xa6a3000e, 0x240b0001, 0x10400003, 0xa34b05c4,
+0x8f420148, 0x3c2f023, 0x8fab0054, 0x8fac004c,
+0xad8b0000, 0x8fac0064, 0x1580feba, 0x0,
+0x8fab0064, 0x1160001b, 0x0, 0x934205c4,
+0x10400006, 0x0, 0xaf5e00c4, 0xaf4b00c0,
+0x8fac006c, 0x1000000e, 0xaf4c00c8, 0x97ab0076,
+0x1160000b, 0x34038100, 0x8fa20020, 0x8c46000c,
+0xa443000c, 0x97ac007e, 0x8c440004, 0x8c450008,
+0xa44c000e, 0xac440000, 0xac450004, 0xac460008,
+0x8f42034c, 0x24420001, 0xaf42034c, 0x10000010,
+0x8f42034c, 0x8fab006c, 0x3164ffff, 0x2484fffc,
+0x801821, 0x8f440250, 0x8f450254, 0x8f460118,
+0x1021, 0xa32821, 0xa3382b, 0x822021,
+0x872021, 0xaf440250, 0xc0f809, 0xaf450254,
+0x8fbf00c0, 0x8fbe00bc, 0x8fb500b8, 0x8fb300b4,
+0x8fb200b0, 0x8fb100ac, 0x8fb000a8, 0x3e00008,
+0x27bd00c8, 0x3e00008, 0x0, 0x27bdffd8,
+0xafbf0024, 0xafb00020, 0x8f43004c, 0x8f420048,
+0x10620034, 0x0, 0x8f430048, 0x8f42004c,
+0x622023, 0x4820001, 0x24840200, 0x8f430054,
+0x8f42004c, 0x43102b, 0x14400004, 0x24020200,
+0x8f43004c, 0x10000005, 0x431023, 0x8f420054,
+0x8f43004c, 0x431023, 0x2442ffff, 0x405021,
+0x8a102a, 0x54400001, 0x805021, 0x8f49004c,
+0x8f48004c, 0x8f440188, 0x8f45018c, 0x8f46004c,
+0x24071000, 0xafa70010, 0x84140, 0x1001821,
+0x12a4821, 0x313001ff, 0xafb00014, 0x8f470014,
+0x1021, 0x63140, 0xafa70018, 0xa32821,
+0xa3382b, 0x822021, 0x872021, 0x3402ecc0,
+0xc23021, 0x8f420108, 0x2e63021, 0x40f809,
+0xa3940, 0x54400001, 0xaf50004c, 0x8f43004c,
+0x8f420048, 0x14620018, 0x0, 0x8f420000,
+0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x2403fdff, 0x431024, 0xaf820060,
+0x8f420000, 0x10400003, 0x0, 0x10000002,
+0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb00020,
+0x3e00008, 0x27bd0028, 0x3e00008, 0x0,
+0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f43005c,
+0x8f420058, 0x10620049, 0x0, 0x8f430058,
+0x8f42005c, 0x622023, 0x4820001, 0x24840100,
+0x8f430064, 0x8f42005c, 0x43102b, 0x14400004,
+0x24020100, 0x8f43005c, 0x10000005, 0x431023,
+0x8f420064, 0x8f43005c, 0x431023, 0x2442ffff,
+0x403821, 0x87102a, 0x54400001, 0x803821,
+0x8f42005c, 0x471021, 0x305000ff, 0x32c21000,
+0x10400015, 0x24082000, 0x8f49005c, 0x8f440190,
+0x8f450194, 0x8f46005c, 0x73980, 0xafa80010,
+0xafb00014, 0x8f480014, 0x94980, 0x1201821,
+0x1021, 0xa32821, 0xa3482b, 0x822021,
+0x892021, 0x63180, 0xafa80018, 0x8f420108,
+0x10000014, 0x24c60cc0, 0x8f49005c, 0x8f440190,
+0x8f450194, 0x8f46005c, 0x73940, 0xafa80010,
+0xafb00014, 0x8f480014, 0x94940, 0x1201821,
+0x1021, 0xa32821, 0xa3482b, 0x822021,
+0x892021, 0x63140, 0xafa80018, 0x8f420108,
+0x24c64cc0, 0x40f809, 0x2e63021, 0x54400001,
+0xaf50005c, 0x8f43005c, 0x8f420058, 0x14620018,
+0x0, 0x8f420000, 0x10400007, 0x0,
+0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
+0x10000005, 0x0, 0xaf800048, 0x8f820048,
+0x1040fffd, 0x0, 0x8f820060, 0x2403feff,
+0x431024, 0xaf820060, 0x8f420000, 0x10400003,
+0x0, 0x10000002, 0xaf80004c, 0xaf800048,
+0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028,
+0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024,
+0xafb00020, 0x8f43006c, 0x8f420068, 0x10620033,
+0x0, 0x8f430068, 0x8f42006c, 0x622023,
+0x4820001, 0x24840400, 0x8f430074, 0x8f42006c,
+0x43102b, 0x14400004, 0x24020400, 0x8f43006c,
+0x10000005, 0x431023, 0x8f420074, 0x8f43006c,
+0x431023, 0x2442ffff, 0x405021, 0x8a102a,
+0x54400001, 0x805021, 0x8f49006c, 0x8f48006c,
+0x8f440198, 0x8f45019c, 0x8f46006c, 0x24074000,
+0xafa70010, 0x84140, 0x1001821, 0x12a4821,
+0x313003ff, 0xafb00014, 0x8f470014, 0x1021,
+0x63140, 0x24c66cc0, 0xafa70018, 0xa32821,
+0xa3382b, 0x822021, 0x872021, 0x8f420108,
+0x2e63021, 0x40f809, 0xa3940, 0x54400001,
+0xaf50006c, 0x8f43006c, 0x8f420068, 0x14620018,
+0x0, 0x8f420000, 0x10400007, 0x0,
+0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
+0x10000005, 0x0, 0xaf800048, 0x8f820048,
+0x1040fffd, 0x0, 0x8f820060, 0x2403f7ff,
+0x431024, 0xaf820060, 0x8f420000, 0x10400003,
+0x0, 0x10000002, 0xaf80004c, 0xaf800048,
+0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028,
+0x3e00008, 0x0, 0x8f4200fc, 0x3c030001,
+0x8f4400f8, 0x346330c8, 0x24420001, 0xaf4200fc,
+0x8f850128, 0x2e31021, 0x54820004, 0x24820008,
+0x3c020001, 0x34422ec8, 0x2e21021, 0x401821,
+0xaf4300f8, 0xac600000, 0x8f4200f4, 0x14620004,
+0x3c020001, 0x24a20020, 0x1000000f, 0xaf820128,
+0x8f4300f8, 0x344230c8, 0x2e21021, 0x54620004,
+0x24620008, 0x3c020001, 0x34422ec8, 0x2e21021,
+0x401821, 0x8c620004, 0x21140, 0xa21021,
+0xaf820128, 0xac600000, 0x8ca30018, 0x30620070,
+0x1040002d, 0x30620020, 0x10400004, 0x3c020010,
+0x2c21024, 0x1040000d, 0x0, 0x30620040,
+0x10400004, 0x3c020020, 0x2c21024, 0x10400007,
+0x0, 0x30620010, 0x1040001f, 0x3c020040,
+0x2c21024, 0x1440001c, 0x0, 0x8f820040,
+0x30420001, 0x14400008, 0x2021, 0x8c030104,
+0x24020001, 0x50620005, 0x24040001, 0x8c020264,
+0x10400003, 0x801021, 0x24040001, 0x801021,
+0x10400006, 0x0, 0x8f42030c, 0x24420001,
+0xaf42030c, 0x10000008, 0x8f42030c, 0x8f820044,
+0x34420004, 0xaf820044, 0x8f420308, 0x24420001,
+0xaf420308, 0x8f420308, 0x3e00008, 0x0,
+0x3e00008, 0x0, 0x27bdff98, 0xafbf0060,
+0xafbe005c, 0xafb50058, 0xafb30054, 0xafb20050,
+0xafb1004c, 0xafb00048, 0x8f4200fc, 0x24420001,
+0xaf4200fc, 0x8f880128, 0x25020020, 0xaf820128,
+0x8d030018, 0x30620070, 0x1040002e, 0x30620020,
+0x10400004, 0x3c020010, 0x2c21024, 0x1040000d,
+0x0, 0x30620040, 0x10400004, 0x3c020020,
+0x2c21024, 0x10400007, 0x0, 0x30620010,
+0x104001a9, 0x3c020040, 0x2c21024, 0x144001a6,
+0x0, 0x8f820040, 0x30420001, 0x14400008,
+0x2021, 0x8c030104, 0x24020001, 0x50620005,
+0x24040001, 0x8c020264, 0x10400003, 0x801021,
+0x24040001, 0x801021, 0x10400006, 0x0,
+0x8f42030c, 0x24420001, 0xaf42030c, 0x10000192,
+0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044,
+0x8f420308, 0x24420001, 0xaf420308, 0x1000018a,
+0x8f420308, 0x30620002, 0x1040014b, 0x3c020800,
+0x8d1e001c, 0x1e5702, 0xafaa0034, 0x950a0016,
+0x3c22024, 0xafaa0024, 0x8faa0034, 0x24020001,
+0x15420006, 0x33deffff, 0x1e1140, 0x3403ecc0,
+0x431021, 0x10000010, 0x2e2a821, 0x24020002,
+0x15420005, 0x24020003, 0x1e1140, 0x24426cc0,
+0x10000009, 0x2e2a821, 0x15420005, 0x1e1180,
+0x1e1140, 0x24424cc0, 0x10000003, 0x2e2a821,
+0x571021, 0x24550ce0, 0x96a2000e, 0x304afffc,
+0x30420400, 0x10400003, 0xafaa002c, 0x100000e1,
+0x8821, 0x10800004, 0x8821, 0x97b10026,
+0x100000dd, 0xa6b10012, 0x8eb30018, 0x966a000c,
+0xa7aa003e, 0x97a5003e, 0x2ca305dd, 0x38a28870,
+0x2c420001, 0x621825, 0x10600015, 0x2021,
+0x32c20800, 0x10400015, 0x24020800, 0x96630014,
+0x14620012, 0x3402aaaa, 0x9663000e, 0x14620007,
+0x2821, 0x96630010, 0x24020300, 0x14620004,
+0xa01021, 0x96620012, 0x2c450001, 0xa01021,
+0x54400006, 0x24040016, 0x10000004, 0x0,
+0x24020800, 0x50a20001, 0x2404000e, 0x108000b9,
+0x2649021, 0x92420000, 0x3042000f, 0x28080,
+0x32c20100, 0x10400020, 0x2501821, 0x3c020020,
+0x43102b, 0x1440000e, 0x2402021, 0x2821,
+0x94820000, 0x24840002, 0xa22821, 0x83102b,
+0x1440fffb, 0x30a2ffff, 0x51c02, 0x622821,
+0x51c02, 0x30a2ffff, 0x10000009, 0x622821,
+0x8f470148, 0x8f420110, 0x102842, 0x3c060020,
+0x40f809, 0xafa80040, 0x3045ffff, 0x8fa80040,
+0x50a00001, 0x3405ffff, 0x8faa002c, 0x354a0002,
+0x10000002, 0xafaa002c, 0x2821, 0x32c20080,
+0x10400090, 0xa6a50010, 0x26430009, 0x3c02001f,
+0x3442ffff, 0x43102b, 0x10400003, 0x0,
+0x8f420148, 0x621823, 0x90660000, 0x30c200ff,
+0x38430006, 0x2c630001, 0x38420011, 0x2c420001,
+0x621825, 0x1060007f, 0x24020800, 0x8821,
+0x97a3003e, 0x1462000f, 0x2602021, 0x96710000,
+0x96620002, 0x96630004, 0x96640006, 0x2228821,
+0x2238821, 0x2248821, 0x96620008, 0x9663000a,
+0x9664000c, 0x2228821, 0x2238821, 0x10000007,
+0x2248821, 0x94820000, 0x24840002, 0x2228821,
+0x92102b, 0x1440fffb, 0x0, 0x111c02,
+0x3222ffff, 0x628821, 0x111c02, 0x3222ffff,
+0x628821, 0x32c20200, 0x10400003, 0x26440006,
+0x1000003e, 0x8021, 0x3c05001f, 0x34a5ffff,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
+0x822023, 0x94820000, 0x30421fff, 0x10400004,
+0x2644000c, 0x96420002, 0x10000030, 0x508023,
+0x96420002, 0x26430014, 0x508023, 0x3c020020,
+0x43102b, 0x1440000a, 0xd08021, 0x9642000c,
+0x2028021, 0x9642000e, 0x96430010, 0x96440012,
+0x2028021, 0x2038021, 0x10000020, 0x2048021,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
+0x822023, 0x94820000, 0x24840002, 0x2028021,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
+0x822023, 0x94820000, 0x24840002, 0x2028021,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
+0x822023, 0x94820000, 0x24840002, 0x2028021,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
+0x822023, 0x94820000, 0x2028021, 0x3c020100,
+0x2c21024, 0x1040000e, 0x0, 0x8faa002c,
+0x31420004, 0x1040000a, 0x0, 0x9504000e,
+0x2642021, 0xc003eec, 0x2484fffc, 0x3042ffff,
+0x2228821, 0x111c02, 0x3222ffff, 0x628821,
+0x8faa0024, 0x1518823, 0x111402, 0x2228821,
+0x2308821, 0x111402, 0x2228821, 0x3231ffff,
+0x52200001, 0x3411ffff, 0x8faa002c, 0x354a0001,
+0xafaa002c, 0xa6b10012, 0x97aa002e, 0xa6aa000e,
+0x8faa002c, 0x31420004, 0x10400002, 0x24091000,
+0x34098000, 0x8f480044, 0x8f4401a0, 0x8f4501a4,
+0xafa90010, 0x8f490044, 0x84140, 0x1001821,
+0xafa90014, 0x8f48000c, 0x2a03021, 0x24070020,
+0xafa80018, 0x8f48010c, 0x1021, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x1440000b, 0x0, 0x8f820128, 0x3c040001,
+0x24846914, 0xafbe0014, 0xafa20010, 0x8f860124,
+0x8f870120, 0x3c050007, 0xc002b3b, 0x34a59920,
+0x8f420368, 0x2442ffff, 0xaf420368, 0x8f420044,
+0x8f430088, 0x24420001, 0x431024, 0xaf420044,
+0x8faa0034, 0x8f440368, 0x24020001, 0x15420006,
+0x24020002, 0x8f42035c, 0x2442ffff, 0xaf42035c,
+0x10000049, 0x8f42035c, 0x15420006, 0x0,
+0x8f420364, 0x2442ffff, 0xaf420364, 0x10000042,
+0x8f420364, 0x8f420360, 0x2442ffff, 0xaf420360,
+0x1000003d, 0x8f420360, 0x30621000, 0x10400005,
+0x30628000, 0x8f420078, 0x24420001, 0x10000036,
+0xaf420078, 0x10400034, 0x0, 0x8f420078,
+0x24420001, 0xaf420078, 0x8c030240, 0x43102b,
+0x1440002d, 0x24070008, 0x8f440168, 0x8f45016c,
+0x8f430044, 0x8f48000c, 0x8f860120, 0x24020040,
+0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c,
+0x40f809, 0x24c6001c, 0x14400011, 0x24020001,
+0x3c010001, 0x370821, 0xa02240f2, 0x8f820124,
+0xafa20010, 0x8f820128, 0x3c040001, 0x2484688c,
+0xafa20014, 0x8f460044, 0x8f870120, 0x3c050009,
+0xc002b3b, 0x34a51300, 0x1000000b, 0x0,
+0x8f420304, 0x24420001, 0xaf420304, 0x8f420304,
+0x8f420044, 0xaf42007c, 0x3c010001, 0x370821,
+0xa02040f2, 0xaf400078, 0x8f420318, 0x24420001,
+0xaf420318, 0x8f420318, 0x8fbf0060, 0x8fbe005c,
+0x8fb50058, 0x8fb30054, 0x8fb20050, 0x8fb1004c,
+0x8fb00048, 0x3e00008, 0x27bd0068, 0x3e00008,
+0x0, 0x0, 0x0, 0x8f42013c,
+0xaf8200c0, 0x8f42013c, 0xaf8200c4, 0x8f42013c,
+0xaf8200c8, 0x8f420138, 0xaf8200d0, 0x8f420138,
+0xaf8200d4, 0x8f420138, 0x3e00008, 0xaf8200d8,
+0x27bdffe0, 0x27840208, 0x24050200, 0xafbf0018,
+0xc002bbf, 0x24060008, 0x8c020204, 0xc004012,
+0xaf820210, 0x3c020001, 0x8c426d94, 0x30420002,
+0x1040000e, 0x2021, 0x8c060248, 0x24020002,
+0x3c010001, 0xac226d98, 0xc005104, 0x24050002,
+0x2021, 0x8c060248, 0x24020001, 0x3c010001,
+0xac226d98, 0x10000011, 0x24050001, 0x8c060248,
+0x24020004, 0x3c010001, 0xac226d98, 0xc005104,
+0x24050004, 0x3c020001, 0x8c426d94, 0x30420001,
+0x10400008, 0x24020001, 0x3c010001, 0xac226d98,
+0x2021, 0x24050001, 0x3c06601b, 0xc005104,
+0x0, 0x3c040001, 0x248469d0, 0x8f420150,
+0x8f430154, 0x3c050008, 0x8f460158, 0x21640,
+0x31940, 0x34630403, 0x431025, 0x633c0,
+0x461025, 0xaf82021c, 0xafa00010, 0xafa00014,
+0x8f86021c, 0x34a50200, 0xc002b3b, 0x3821,
+0x3c010001, 0xac206d90, 0x3c010001, 0xac206da8,
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0,
+0x3c050008, 0x34a50300, 0xafbf0018, 0xafa00010,
+0xafa00014, 0x8f860200, 0x3c040001, 0x248469dc,
+0xc002b3b, 0x3821, 0x8f420410, 0x24420001,
+0xaf420410, 0x8f420410, 0x8fbf0018, 0x3e00008,
+0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb1001c,
+0xafb00018, 0x8f4203a4, 0x24420001, 0xaf4203a4,
+0x8f4203a4, 0x8f900220, 0x8f8200e0, 0xafa20010,
+0x8f8200e4, 0xafa20014, 0x8f8600c4, 0x8f8700c8,
+0x3c040001, 0x248469e8, 0xc002b3b, 0x2002821,
+0x3c044000, 0x2041024, 0x504000b4, 0x3c040100,
+0x8f4203bc, 0x24420001, 0xaf4203bc, 0x8f4203bc,
+0x8f8700c4, 0x8f8300c8, 0x8f420148, 0x671823,
+0x43102b, 0x10400003, 0x0, 0x8f420148,
+0x621821, 0x10600005, 0x0, 0x8f42014c,
+0x43102b, 0x1040000b, 0x0, 0x8f8200e0,
+0x8f430124, 0xaf42011c, 0xaf430114, 0x8f820220,
+0x3c0308ff, 0x3463fffb, 0x431024, 0x100000ce,
+0x441025, 0x8f820220, 0x3c0308ff, 0x3463ffff,
+0x431024, 0x34420004, 0xaf820220, 0x8f8200e0,
+0x8f430124, 0xaf42011c, 0xaf430114, 0x8f8600c8,
+0x8f840120, 0x8f830124, 0x10000005, 0x2821,
+0x14620002, 0x24620020, 0x27624800, 0x401821,
+0x1064000c, 0x30a200ff, 0x8c620018, 0x30420003,
+0x1040fff7, 0x27624fe0, 0x8f4203d0, 0x24050001,
+0x24420001, 0xaf4203d0, 0x8f4203d0, 0x8c660008,
+0x30a200ff, 0x14400058, 0x0, 0x934205c4,
+0x14400055, 0x0, 0x8f8700c4, 0x8f8800e0,
+0x8f8400e4, 0x2402fff8, 0x1024024, 0x1041023,
+0x218c3, 0x4620001, 0x24630200, 0x10600005,
+0x24020001, 0x10620009, 0x0, 0x1000001f,
+0x0, 0x8f4203c0, 0xe03021, 0x24420001,
+0xaf4203c0, 0x10000040, 0x8f4203c0, 0x8f4203c4,
+0x24420001, 0xaf4203c4, 0x8c860000, 0x8f420148,
+0x8f4303c4, 0xe61823, 0x43102b, 0x10400004,
+0x2c62233f, 0x8f420148, 0x621821, 0x2c62233f,
+0x14400031, 0x0, 0x8f42020c, 0x24420001,
+0xaf42020c, 0x8f42020c, 0xe03021, 0x24820008,
+0xaf8200e4, 0x10000028, 0xaf8200e8, 0x8f4203c8,
+0x24420001, 0xaf4203c8, 0x8f4203c8, 0x8c850000,
+0x8f420148, 0xa71823, 0x43102b, 0x10400003,
+0x0, 0x8f420148, 0x621821, 0x8f42014c,
+0x43102b, 0x5440000a, 0xa03021, 0x8f42020c,
+0x24420001, 0xaf42020c, 0x8f42020c, 0x24820008,
+0xaf8200e4, 0x8f8400e4, 0x1488ffec, 0xaf8400e8,
+0x1488000d, 0x27623000, 0x14820002, 0x2482fff8,
+0x27623ff8, 0x94430006, 0x3c02001f, 0x3442ffff,
+0xc33021, 0x46102b, 0x10400003, 0x0,
+0x8f420148, 0xc23023, 0xaf8600c8, 0x8f8300c4,
+0x8f420148, 0xc31823, 0x43102b, 0x10400003,
+0x0, 0x8f420148, 0x621821, 0x10600005,
+0x0, 0x8f42014c, 0x43102b, 0x50400008,
+0x3c02fdff, 0x8f820220, 0x3c0308ff, 0x3463fffb,
+0x431024, 0x3c034000, 0x1000003f, 0x431025,
+0x8f4303cc, 0x3442ffff, 0x282a024, 0x24630001,
+0xaf4303cc, 0x10000039, 0x8f4203cc, 0x2041024,
+0x1040000e, 0x3c110200, 0x8f4203a8, 0x24420001,
+0xaf4203a8, 0x8f4203a8, 0x8f820220, 0x3c0308ff,
+0x3463ffff, 0x431024, 0x441025, 0xc003daf,
+0xaf820220, 0x10000029, 0x0, 0x2111024,
+0x50400008, 0x3c110400, 0x8f4203ac, 0x24420001,
+0xaf4203ac, 0xc003daf, 0x8f4203ac, 0x10000019,
+0x0, 0x2111024, 0x1040001c, 0x0,
+0x8f830224, 0x24021402, 0x14620009, 0x3c050008,
+0x3c040001, 0x248469f4, 0xafa00010, 0xafa00014,
+0x8f860224, 0x34a50500, 0xc002b3b, 0x3821,
+0x8f4203b0, 0x24420001, 0xaf4203b0, 0x8f4203b0,
+0x8f820220, 0x2002021, 0x34420002, 0xc004e9c,
+0xaf820220, 0x8f820220, 0x3c0308ff, 0x3463ffff,
+0x431024, 0x511025, 0xaf820220, 0x8fbf0020,
+0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028,
+0x3e00008, 0x0, 0x3c020001, 0x8c426da8,
+0x27bdffb0, 0xafbf0048, 0xafbe0044, 0xafb50040,
+0xafb3003c, 0xafb20038, 0xafb10034, 0x1040000f,
+0xafb00030, 0x3c040001, 0x24846a00, 0x3c050008,
+0xafa00010, 0xafa00014, 0x8f860220, 0x34a50600,
+0x24020001, 0x3c010001, 0xac206da8, 0x3c010001,
+0xac226d9c, 0xc002b3b, 0x3821, 0x3c037fff,
+0x8c020268, 0x3463ffff, 0x3c04fdff, 0x431024,
+0xac020268, 0x8f420004, 0x3484ffff, 0x30420002,
+0x10400092, 0x284a024, 0x3c040600, 0x34842000,
+0x8f420004, 0x2821, 0x2403fffd, 0x431024,
+0xaf420004, 0xafa40020, 0x8f5e0018, 0x27aa0020,
+0x240200ff, 0x13c20002, 0xafaa002c, 0x27c50001,
+0x8c020228, 0xa09021, 0x1642000e, 0x1e38c0,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x24846998, 0x3c050009,
+0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d,
+0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024,
+0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b,
+0x9821, 0xe08821, 0x263504c0, 0x8f440178,
+0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010,
+0xafb20014, 0x8f48000c, 0x1021, 0x2f53021,
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x54400006, 0x24130001, 0x8f820054, 0x2021023,
+0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff,
+0x54400017, 0xaf520018, 0x8f420378, 0x24420001,
+0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
+0xafa20010, 0x8f820124, 0x3c040001, 0x248469a4,
+0x3c050009, 0xafa20014, 0x8d460000, 0x10000035,
+0x34a50600, 0x8f420308, 0x24130001, 0x24420001,
+0xaf420308, 0x8f420308, 0x1000001e, 0x326200ff,
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
+0x2c4203e9, 0x10400016, 0x9821, 0x3c150020,
+0x24110010, 0x8f42000c, 0x8f440160, 0x8f450164,
+0x8f860120, 0xafb10010, 0xafb20014, 0x551025,
+0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
+0x24c6001c, 0x1440ffe3, 0x0, 0x8f820054,
+0x2021023, 0x2c4203e9, 0x1440ffee, 0x0,
+0x326200ff, 0x14400011, 0x0, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
+0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001,
+0x248469ac, 0x3c050009, 0xafa20014, 0x8d460000,
+0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202ec,
+0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8fbf0048,
+0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb20038,
+0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050,
+0x3c020001, 0x8c426da8, 0x27bdffe0, 0x1440000d,
+0xafbf0018, 0x3c040001, 0x24846a0c, 0x3c050008,
+0xafa00010, 0xafa00014, 0x8f860220, 0x34a50700,
+0x24020001, 0x3c010001, 0xac226da8, 0xc002b3b,
+0x3821, 0x3c020004, 0x2c21024, 0x10400007,
+0x0, 0x8f820220, 0x3c0308ff, 0x3463ffff,
+0x431024, 0x34420008, 0xaf820220, 0x3c050001,
+0x8ca56d98, 0x24020001, 0x14a20007, 0x2021,
+0xc00529b, 0x24050001, 0xac02026c, 0x8c03026c,
+0x10000006, 0x3c020007, 0xc00529b, 0x2021,
+0xac020268, 0x8c030268, 0x3c020007, 0x621824,
+0x3c020002, 0x5062000d, 0x3c0205f5, 0x43102b,
+0x14400006, 0x3c020004, 0x3c020001, 0x10620009,
+0x3c020098, 0x1000000b, 0x0, 0x14620009,
+0x3c023b9a, 0x10000004, 0x3442ca00, 0x10000002,
+0x3442e100, 0x34429680, 0xaf4201fc, 0x8f4201fc,
+0xaee20064, 0x8fbf0018, 0x3e00008, 0x27bd0020,
+0x0, 0x0, 0x0, 0x86102b,
+0x50400001, 0x872023, 0xc41023, 0x24843,
+0x125102b, 0x1040001b, 0x91040, 0x824021,
+0x88102b, 0x10400007, 0x1821, 0x94820000,
+0x24840002, 0x621821, 0x88102b, 0x1440fffb,
+0x0, 0x602021, 0xc73023, 0xa91023,
+0x21040, 0xc22821, 0xc5102b, 0x10400007,
+0x1821, 0x94c20000, 0x24c60002, 0x621821,
+0xc5102b, 0x1440fffb, 0x0, 0x1000000d,
+0x832021, 0x51040, 0x822821, 0x85102b,
+0x10400007, 0x1821, 0x94820000, 0x24840002,
+0x621821, 0x85102b, 0x1440fffb, 0x0,
+0x602021, 0x41c02, 0x3082ffff, 0x622021,
+0x41c02, 0x3082ffff, 0x622021, 0x3e00008,
+0x3082ffff, 0x3e00008, 0x0, 0x802821,
+0x30a20001, 0x1040002b, 0x3c03001f, 0x3463ffff,
+0x24a20004, 0x62102b, 0x54400007, 0x65102b,
+0x90a20001, 0x90a40003, 0x90a30000, 0x90a50002,
+0x1000002a, 0x441021, 0x10400003, 0x0,
+0x8f420148, 0xa22823, 0x90a40000, 0x24a50001,
+0x65102b, 0x10400003, 0x0, 0x8f420148,
+0xa22823, 0x90a20000, 0x24a50001, 0x21200,
+0x822021, 0x65102b, 0x10400003, 0x0,
+0x8f420148, 0xa22823, 0x90a20000, 0x24a50001,
+0x822021, 0x65102b, 0x10400003, 0x0,
+0x8f420148, 0xa22823, 0x90a20000, 0x1000002d,
+0x21200, 0x3463ffff, 0x24a20004, 0x62102b,
+0x5440000a, 0x65102b, 0x90a20000, 0x90a40002,
+0x90a30001, 0x90a50003, 0x441021, 0x21200,
+0x651821, 0x10000020, 0x432021, 0x10400003,
+0x0, 0x8f420148, 0xa22823, 0x90a20000,
+0x24a50001, 0x22200, 0x65102b, 0x10400003,
+0x0, 0x8f420148, 0xa22823, 0x90a20000,
+0x24a50001, 0x822021, 0x65102b, 0x10400003,
+0x0, 0x8f420148, 0xa22823, 0x90a20000,
+0x24a50001, 0x21200, 0x822021, 0x65102b,
+0x10400003, 0x0, 0x8f420148, 0xa22823,
+0x90a20000, 0x822021, 0x41c02, 0x3082ffff,
+0x622021, 0x41c02, 0x3082ffff, 0x622021,
+0x3e00008, 0x3082ffff, 0x0, 0x8f820220,
+0x34420002, 0xaf820220, 0x3c020002, 0x8c428ff8,
+0x30424000, 0x10400054, 0x24040001, 0x8f820200,
+0x24067fff, 0x8f830200, 0x30450002, 0x2402fffd,
+0x621824, 0xaf830200, 0xaf840204, 0x8f830054,
+0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
+0x621023, 0x2c420002, 0x1440fffc, 0x0,
+0x8f820224, 0x1444004d, 0x42040, 0xc4102b,
+0x1040fff1, 0x0, 0x8f820200, 0x451025,
+0xaf820200, 0x8f820220, 0x34428000, 0xaf820220,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x8f820220, 0x3c030004, 0x431024,
+0x1440000f, 0x0, 0x8f820220, 0x3c03ffff,
+0x34637fff, 0x431024, 0xaf820220, 0x8f830054,
+0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
+0x621023, 0x2c420002, 0x1440fffc, 0x0,
+0x8f820220, 0x3c030004, 0x431024, 0x1440000d,
+0x0, 0x8f820220, 0x34428000, 0xaf820220,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x8f820220, 0x3c030004, 0x431024,
+0x1040001b, 0x1021, 0x8f830220, 0x24020001,
+0x10000015, 0x3c04f700, 0x8f820220, 0x3c04f700,
+0x441025, 0xaf820220, 0x8f820220, 0x2403fffd,
+0x431024, 0xaf820220, 0x8f820220, 0x3c030300,
+0x431024, 0x14400003, 0x0, 0x10000008,
+0x1021, 0x8f820220, 0x34420002, 0xaf820220,
+0x8f830220, 0x24020001, 0x641825, 0xaf830220,
+0x3e00008, 0x0, 0x2021, 0x3c050100,
+0x24020001, 0xaf80021c, 0xaf820200, 0xaf820220,
+0x27625000, 0xaf8200c0, 0x27625000, 0xaf8200c4,
+0x27625000, 0xaf8200c8, 0x27625000, 0xaf8200d0,
+0x27625000, 0xaf8200d4, 0x27625000, 0xaf8200d8,
+0x27623000, 0xaf8200e0, 0x27623000, 0xaf8200e4,
+0x27623000, 0xaf8200e8, 0x27622800, 0xaf8200f0,
+0x27622800, 0xaf8200f4, 0x27622800, 0xaf8200f8,
+0x418c0, 0x24840001, 0x3631021, 0xac453004,
+0x3631021, 0xac403000, 0x28820200, 0x1440fff9,
+0x418c0, 0x2021, 0x418c0, 0x24840001,
+0x3631021, 0xac402804, 0x3631021, 0xac402800,
+0x28820100, 0x1440fff9, 0x418c0, 0xaf80023c,
+0x24030080, 0x24040100, 0xac600000, 0x24630004,
+0x64102b, 0x5440fffd, 0xac600000, 0x8f830040,
+0x3c02f000, 0x621824, 0x3c025000, 0x1062000c,
+0x43102b, 0x14400006, 0x3c026000, 0x3c024000,
+0x10620008, 0x24020800, 0x10000008, 0x0,
+0x10620004, 0x24020800, 0x10000004, 0x0,
+0x24020700, 0x3c010001, 0xac226dac, 0x3e00008,
+0x0, 0x3c020001, 0x8c426dbc, 0x27bdffd0,
+0xafbf002c, 0xafb20028, 0xafb10024, 0xafb00020,
+0x3c010001, 0x10400005, 0xac206d94, 0xc004d9e,
+0x0, 0x3c010001, 0xac206dbc, 0x8f830054,
+0x8f820054, 0x10000002, 0x24630064, 0x8f820054,
+0x621023, 0x2c420065, 0x1440fffc, 0x0,
+0xc004db9, 0x0, 0x24040001, 0x2821,
+0x27a60018, 0x34028000, 0xc0045be, 0xa7a20018,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
+0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
+0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
+0x24040001, 0x3c060001, 0x24c66f24, 0xc00457c,
+0x24050002, 0x8f830054, 0x8f820054, 0x10000002,
+0x24630064, 0x8f820054, 0x621023, 0x2c420065,
+0x1440fffc, 0x24040001, 0x24050003, 0x3c100001,
+0x26106f26, 0xc00457c, 0x2003021, 0x97a60018,
+0x3c070001, 0x94e76f24, 0x3c040001, 0x24846ae0,
+0xafa00014, 0x96020000, 0x3c05000d, 0x34a50100,
+0xc002b3b, 0xafa20010, 0x97a20018, 0x1040004d,
+0x24036040, 0x96020000, 0x3042fff0, 0x1443000c,
+0x24020020, 0x3c030001, 0x94636f24, 0x1462000b,
+0x24027830, 0x24020003, 0x3c010001, 0xac226d94,
+0x24020005, 0x3c010001, 0x1000003f, 0xac226f34,
+0x3c030001, 0x94636f24, 0x24027830, 0x1462000c,
+0x24030010, 0x3c020001, 0x94426f26, 0x3042fff0,
+0x14430007, 0x24020003, 0x3c010001, 0xac226d94,
+0x24020006, 0x3c010001, 0x1000002f, 0xac226f34,
+0x3c020001, 0x8c426d94, 0x3c030001, 0x94636f24,
+0x34420001, 0x3c010001, 0xac226d94, 0x24020015,
+0x1462000b, 0x0, 0x3c020001, 0x94426f26,
+0x3042fff0, 0x3843f420, 0x2c630001, 0x3842f430,
+0x2c420001, 0x621825, 0x1460001b, 0x24020003,
+0x3c030001, 0x94636f24, 0x24027810, 0x14620016,
+0x24020002, 0x3c020001, 0x94426f26, 0x3042fff0,
+0x14400011, 0x24020002, 0x1000000f, 0x24020004,
+0x3c020001, 0x8c426d94, 0x34420008, 0x3c010001,
+0xac226d94, 0x1000005e, 0x24020004, 0x3c020001,
+0x8c426d94, 0x34420004, 0x3c010001, 0x100000af,
+0xac226d94, 0x24020001, 0x3c010001, 0xac226f40,
+0x3c020001, 0x8c426d94, 0x30420002, 0x144000b2,
+0x3c09fff0, 0x24020e00, 0xaf820238, 0x8f840054,
+0x8f820054, 0x24030008, 0x3c010001, 0xac236d98,
+0x10000002, 0x248401f4, 0x8f820054, 0x821023,
+0x2c4201f5, 0x1440fffc, 0x3c0200c8, 0x344201fb,
+0xaf820238, 0x8f830054, 0x8f820054, 0x10000002,
+0x246301f4, 0x8f820054, 0x621023, 0x2c4201f5,
+0x1440fffc, 0x8021, 0x24120001, 0x24110009,
+0xc004482, 0x0, 0x3c010001, 0xac326db4,
+0xc004547, 0x0, 0x3c020001, 0x8c426db4,
+0x1451fffb, 0x3c0200c8, 0x344201f6, 0xaf820238,
+0x8f830054, 0x8f820054, 0x10000002, 0x2463000a,
+0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc,
+0x0, 0x8f820220, 0x24040001, 0x34420002,
+0xaf820220, 0x8f830200, 0x24057fff, 0x2402fffd,
+0x621824, 0xaf830200, 0xaf840204, 0x8f830054,
+0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
+0x621023, 0x2c420002, 0x1440fffc, 0x0,
+0x8f820224, 0x14440005, 0x34028000, 0x42040,
+0xa4102b, 0x1040fff0, 0x34028000, 0x1082ffa0,
+0x26100001, 0x2e020014, 0x1440ffcd, 0x24020004,
+0x3c010001, 0xac226d98, 0x8021, 0x24120009,
+0x3c11ffff, 0x36313f7f, 0xc004482, 0x0,
+0x24020001, 0x3c010001, 0xac226db4, 0xc004547,
+0x0, 0x3c020001, 0x8c426db4, 0x1452fffb,
+0x0, 0x8f820044, 0x511024, 0x34425080,
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
+0x2463000a, 0x8f820054, 0x621023, 0x2c42000b,
+0x1440fffc, 0x0, 0x8f820044, 0x511024,
+0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054,
+0x10000002, 0x2463000a, 0x8f820054, 0x621023,
+0x2c42000b, 0x1440fffc, 0x0, 0x8f820220,
+0x3c03f700, 0x431025, 0xaf820220, 0x8f830054,
+0x8f820054, 0x10000002, 0x24630064, 0x8f820054,
+0x621023, 0x2c420065, 0x1440fffc, 0x0,
+0x8f820220, 0x24040001, 0x34420002, 0xaf820220,
+0x8f830200, 0x24057fff, 0x2402fffd, 0x621824,
+0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054,
+0x10000002, 0x24630001, 0x8f820054, 0x621023,
+0x2c420002, 0x1440fffc, 0x0, 0x8f820224,
+0x14440005, 0x34028000, 0x42040, 0xa4102b,
+0x1040fff0, 0x34028000, 0x1082ff50, 0x26100001,
+0x2e020064, 0x1440ffb0, 0x0, 0x3c020001,
+0x8c426d94, 0x30420004, 0x14400007, 0x3c09fff0,
+0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024,
+0xaf820044, 0x3c09fff0, 0x3529bdc0, 0x3c060001,
+0x8cc66d94, 0x3c040001, 0x24846ae0, 0x24020001,
+0x3c010001, 0xac226d9c, 0x8f820054, 0x3c070001,
+0x8ce76f40, 0x3c030001, 0x94636f24, 0x3c080001,
+0x95086f26, 0x3c05000d, 0x34a50100, 0x3c010001,
+0xac206d98, 0x491021, 0x3c010001, 0xac226f30,
+0xafa30010, 0xc002b3b, 0xafa80014, 0x8fbf002c,
+0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008,
+0x27bd0030, 0x27bdffe8, 0x3c050001, 0x8ca56d98,
+0x24060004, 0x24020001, 0x14a20014, 0xafbf0010,
+0x3c020002, 0x8c428ffc, 0x30428000, 0x10400005,
+0x3c04000f, 0x3c030001, 0x8c636f40, 0x10000005,
+0x34844240, 0x3c040004, 0x3c030001, 0x8c636f40,
+0x348493e0, 0x24020005, 0x14620016, 0x0,
+0x3c04003d, 0x10000013, 0x34840900, 0x3c020002,
+0x8c428ff8, 0x30428000, 0x10400005, 0x3c04001e,
+0x3c030001, 0x8c636f40, 0x10000005, 0x34848480,
+0x3c04000f, 0x3c030001, 0x8c636f40, 0x34844240,
+0x24020005, 0x14620003, 0x0, 0x3c04007a,
+0x34841200, 0x3c020001, 0x8c426f30, 0x8f830054,
+0x441021, 0x431023, 0x44102b, 0x1440004c,
+0x0, 0x3c020001, 0x8c426da0, 0x14400048,
+0x0, 0x3c010001, 0x10c00025, 0xac206db0,
+0x3c090001, 0x8d296d94, 0x24070001, 0x3c044000,
+0x3c080002, 0x25088ffc, 0x250afffc, 0x52842,
+0x14a00002, 0x24c6ffff, 0x24050008, 0xa91024,
+0x10400010, 0x0, 0x14a70008, 0x0,
+0x8d020000, 0x441024, 0x1040000a, 0x0,
+0x3c010001, 0x10000007, 0xac256db0, 0x8d420000,
+0x441024, 0x10400003, 0x0, 0x3c010001,
+0xac276db0, 0x3c020001, 0x8c426db0, 0x6182b,
+0x2c420001, 0x431024, 0x5440ffe5, 0x52842,
+0x8f820054, 0x3c030001, 0x8c636db0, 0x3c010001,
+0xac226f30, 0x1060003b, 0x24020005, 0x3c030001,
+0x8c636f40, 0x3c010001, 0xac256d98, 0x14620012,
+0x24020001, 0x3c020002, 0x8c428ff8, 0x3c032000,
+0x34635000, 0x431024, 0x14400006, 0x24020001,
+0x3c010001, 0xac206f1c, 0x3c010001, 0xac226d98,
+0x24020001, 0x3c010001, 0xac226e24, 0x3c010001,
+0xac226da4, 0x24020001, 0x3c010001, 0xac226d9c,
+0x3c020001, 0x8c426db0, 0x1040001e, 0x0,
+0x3c020001, 0x8c426d9c, 0x10400008, 0x24020001,
+0x3c010001, 0xac206d9c, 0xaee204b8, 0x3c010001,
+0xac206e1c, 0x3c010001, 0xac226dd4, 0x8ee304b8,
+0x24020008, 0x10620005, 0x24020001, 0xc004239,
+0x0, 0x1000000b, 0x0, 0x3c030001,
+0x8c636d98, 0x10620007, 0x2402000e, 0x3c030002,
+0x8c638f90, 0x10620003, 0x0, 0xc004e9c,
+0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018,
+0x27bdffe0, 0x3c03fdff, 0x3c040001, 0x8c846d98,
+0x3c020001, 0x8c426dc0, 0x3463ffff, 0x283a024,
+0x14820006, 0xafbf0018, 0x8ee304b8, 0x3c020001,
+0x8c426dc4, 0x10620006, 0x0, 0x8ee204b8,
+0x3c010001, 0xac246dc0, 0x3c010001, 0xac226dc4,
+0x3c030001, 0x8c636d98, 0x24020002, 0x1062019c,
+0x2c620003, 0x10400005, 0x24020001, 0x1062000a,
+0x0, 0x10000226, 0x0, 0x24020004,
+0x106200b6, 0x24020008, 0x1062010a, 0x24020001,
+0x1000021f, 0x0, 0x8ee204b8, 0x2443ffff,
+0x2c620008, 0x1040021c, 0x31080, 0x3c010001,
+0x220821, 0x8c226af8, 0x400008, 0x0,
+0x3c030001, 0x8c636f40, 0x24020005, 0x14620010,
+0x0, 0x3c020001, 0x8c426da4, 0x10400008,
+0x24020003, 0xc004482, 0x0, 0x24020002,
+0xaee204b8, 0x3c010001, 0x10000002, 0xac206da4,
+0xaee204b8, 0x3c010001, 0x10000203, 0xac206d30,
+0xc004482, 0x0, 0x3c020001, 0x8c426da4,
+0x3c010001, 0xac206d30, 0x1440017a, 0x24020002,
+0x1000019d, 0x24020007, 0x3c030001, 0x8c636f40,
+0x24020005, 0x14620003, 0x24020001, 0x3c010001,
+0xac226dd0, 0xc0045ff, 0x0, 0x3c030001,
+0x8c636dd0, 0x10000174, 0x24020011, 0x3c050001,
+0x8ca56d98, 0x3c060002, 0x8cc68ffc, 0xc005104,
+0x2021, 0x24020005, 0x3c010001, 0xac206da4,
+0x100001e1, 0xaee204b8, 0x3c040001, 0x24846aec,
+0x3c05000f, 0x34a50100, 0x3021, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x100001d6,
+0x0, 0x8f820220, 0x3c030004, 0x431024,
+0x14400175, 0x24020007, 0x8f830054, 0x3c020001,
+0x8c426f28, 0x2463d8f0, 0x431023, 0x2c422710,
+0x14400003, 0x24020001, 0x3c010001, 0xac226d9c,
+0x3c020002, 0x8c428ffc, 0x30425000, 0x104001c2,
+0x0, 0x8f820220, 0x30428000, 0x1040017d,
+0x0, 0x10000175, 0x0, 0x3c050001,
+0x8ca56d98, 0xc00529b, 0x2021, 0xc00551b,
+0x2021, 0x3c030002, 0x8c638ff4, 0x46101b0,
+0x24020001, 0x3c020008, 0x621024, 0x10400006,
+0x0, 0x8f820214, 0x3c03ffff, 0x431024,
+0x10000005, 0x3442251f, 0x8f820214, 0x3c03ffff,
+0x431024, 0x3442241f, 0xaf820214, 0x8f820220,
+0x3c030200, 0x34420002, 0xaf820220, 0x24020008,
+0xaee204b8, 0x8f820220, 0x283a025, 0x3c030004,
+0x431024, 0x14400016, 0x0, 0x3c020002,
+0x8c428ffc, 0x30425000, 0x1040000d, 0x0,
+0x8f820220, 0x30428000, 0x10400006, 0x0,
+0x8f820220, 0x3c03ffff, 0x34637fff, 0x10000003,
+0x431024, 0x8f820220, 0x34428000, 0xaf820220,
+0x8f820220, 0x3c03f700, 0x431025, 0xaf820220,
+0x3c030001, 0x8c636f40, 0x24020005, 0x1462000a,
+0x0, 0x3c020001, 0x94426f26, 0x24429fbc,
+0x2c420004, 0x10400004, 0x24040018, 0x24050002,
+0xc004ddb, 0x24060020, 0xc003e6d, 0x0,
+0x3c010001, 0x10000170, 0xac206e20, 0x8ee204b8,
+0x2443ffff, 0x2c620008, 0x1040016b, 0x31080,
+0x3c010001, 0x220821, 0x8c226b18, 0x400008,
+0x0, 0xc004547, 0x0, 0x3c030001,
+0x8c636db4, 0x100000e8, 0x24020009, 0x3c020002,
+0x8c428ff8, 0x30424000, 0x10400004, 0x0,
+0x8f820044, 0x10000006, 0x3442f080, 0x8f820044,
+0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080,
+0xaf820044, 0x8f830054, 0x100000ea, 0x24020004,
+0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0,
+0x431023, 0x2c422710, 0x14400147, 0x24020005,
+0x100000d8, 0x0, 0x8f820220, 0x3c03f700,
+0x431025, 0xaf820220, 0xaf800204, 0x3c010002,
+0x100000d6, 0xac208fe0, 0x8f830054, 0x3c020001,
+0x8c426f28, 0x2463fff6, 0x431023, 0x2c42000a,
+0x14400135, 0x24020007, 0x100000d7, 0x0,
+0xc003f50, 0x0, 0x1040012d, 0x24020001,
+0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c846f1c,
+0x431024, 0x3442251f, 0xaf820214, 0x24020008,
+0x10800005, 0xaee204b8, 0x3c020001, 0x8c426e44,
+0x10400064, 0x24020001, 0x8f820220, 0x3c030008,
+0x431024, 0x1040006a, 0x3c020200, 0x10000078,
+0x0, 0x8ee204b8, 0x2443ffff, 0x2c620007,
+0x10400115, 0x31080, 0x3c010001, 0x220821,
+0x8c226b38, 0x400008, 0x0, 0xc003daf,
+0x0, 0x3c010001, 0xac206d9c, 0xaf800204,
+0x3c010002, 0xc004482, 0xac208fe0, 0x24020001,
+0x3c010001, 0xac226db4, 0x24020002, 0x10000102,
+0xaee204b8, 0xc004547, 0x0, 0x3c030001,
+0x8c636db4, 0x10000084, 0x24020009, 0x3c020002,
+0x8c428ff8, 0x30424000, 0x10400003, 0x3c0200c8,
+0x10000002, 0x344201f6, 0x344201fe, 0xaf820238,
+0x8f830054, 0x1000008b, 0x24020004, 0x8f830054,
+0x3c020001, 0x8c426f28, 0x2463d8f0, 0x431023,
+0x2c422710, 0x144000e8, 0x24020005, 0x10000079,
+0x0, 0x8f820220, 0x3c03f700, 0x431025,
+0xaf820220, 0xaf800204, 0x3c010002, 0x10000077,
+0xac208fe0, 0x8f830054, 0x3c020001, 0x8c426f28,
+0x2463fff6, 0x431023, 0x2c42000a, 0x144000d6,
+0x24020007, 0x10000078, 0x0, 0xc003f50,
+0x0, 0x104000ce, 0x24020001, 0x8f820214,
+0x3c03ffff, 0x3c040001, 0x8c846f1c, 0x431024,
+0x3442251f, 0xaf820214, 0x24020008, 0x1080000f,
+0xaee204b8, 0x3c020001, 0x8c426e44, 0x1440000b,
+0x0, 0x8f820220, 0x34420002, 0xaf820220,
+0x24020001, 0x3c010002, 0xac228f90, 0xc004e9c,
+0x8f840220, 0x10000016, 0x0, 0x8f820220,
+0x3c030008, 0x431024, 0x14400011, 0x3c020200,
+0x282a025, 0x2402000e, 0x3c010002, 0xac228f90,
+0xc00551b, 0x2021, 0x8f820220, 0x34420002,
+0xc003e6d, 0xaf820220, 0x3c050001, 0x8ca56d98,
+0xc00529b, 0x2021, 0x100000a3, 0x0,
+0x3c020001, 0x8c426e44, 0x1040009f, 0x0,
+0x3c020001, 0x8c426e40, 0x2442ffff, 0x3c010001,
+0xac226e40, 0x14400098, 0x24020002, 0x3c010001,
+0xac206e44, 0x3c010001, 0x10000093, 0xac226e40,
+0x8ee204b8, 0x2443ffff, 0x2c620007, 0x1040008e,
+0x31080, 0x3c010001, 0x220821, 0x8c226b58,
+0x400008, 0x0, 0x3c020001, 0x8c426da4,
+0x10400018, 0x24020005, 0xc004482, 0x0,
+0x24020002, 0xaee204b8, 0x3c010001, 0x1000007e,
+0xac206da4, 0xc004963, 0x0, 0x3c030001,
+0x8c636dd4, 0x24020006, 0x14620077, 0x24020003,
+0x10000075, 0xaee204b8, 0x3c050001, 0x8ca56d98,
+0x3c060002, 0x8cc68ff8, 0xc005104, 0x2021,
+0x24020005, 0x1000006c, 0xaee204b8, 0x8f820220,
+0x3c03f700, 0x431025, 0xaf820220, 0x8f830054,
+0x24020006, 0xaee204b8, 0x3c010001, 0x10000062,
+0xac236f28, 0x8f820220, 0x3c030004, 0x431024,
+0x10400003, 0x24020007, 0x1000005b, 0xaee204b8,
+0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0,
+0x431023, 0x2c422710, 0x14400003, 0x24020001,
+0x3c010001, 0xac226d9c, 0x3c020002, 0x8c428ff8,
+0x30425000, 0x1040004c, 0x0, 0x8f820220,
+0x30428000, 0x10400007, 0x0, 0x8f820220,
+0x3c03ffff, 0x34637fff, 0x431024, 0x10000042,
+0xaf820220, 0x8f820220, 0x34428000, 0x1000003e,
+0xaf820220, 0x3c050001, 0x8ca56d98, 0xc00529b,
+0x2021, 0xc00551b, 0x2021, 0x3c020002,
+0x8c428ff0, 0x4410032, 0x24020001, 0x8f820214,
+0x3c03ffff, 0x431024, 0x3442251f, 0xaf820214,
+0x24020008, 0xaee204b8, 0x8f820220, 0x34420002,
+0xaf820220, 0x8f820220, 0x3c030004, 0x431024,
+0x14400016, 0x0, 0x3c020002, 0x8c428ff8,
+0x30425000, 0x1040000d, 0x0, 0x8f820220,
+0x30428000, 0x10400006, 0x0, 0x8f820220,
+0x3c03ffff, 0x34637fff, 0x10000003, 0x431024,
+0x8f820220, 0x34428000, 0xaf820220, 0x8f820220,
+0x3c03f700, 0x431025, 0xaf820220, 0x3c020001,
+0x94426f26, 0x24429fbc, 0x2c420004, 0x10400004,
+0x24040018, 0x24050002, 0xc004ddb, 0x24060020,
+0xc003e6d, 0x0, 0x10000003, 0x0,
+0x3c010001, 0xac226d9c, 0x8fbf0018, 0x3e00008,
+0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220,
+0x34420004, 0xaf820220, 0x8f820200, 0x3c050001,
+0x8ca56d98, 0x34420004, 0xaf820200, 0x24020002,
+0x10a2004b, 0x2ca20003, 0x10400005, 0x24020001,
+0x10a2000a, 0x0, 0x100000b1, 0x0,
+0x24020004, 0x10a20072, 0x24020008, 0x10a20085,
+0x3c02f0ff, 0x100000aa, 0x0, 0x8f830050,
+0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c846f40,
+0x621824, 0x3c020700, 0x621825, 0x24020e00,
+0x2484fffb, 0x2c840002, 0xaf830050, 0xaf850200,
+0xaf850220, 0x14800006, 0xaf820238, 0x8f820044,
+0x3c03ffff, 0x34633f7f, 0x431024, 0xaf820044,
+0x3c030001, 0x8c636f40, 0x24020005, 0x14620004,
+0x0, 0x8f820044, 0x34425000, 0xaf820044,
+0x3c020001, 0x8c426d88, 0x3c030001, 0x8c636f40,
+0x34420022, 0x2463fffc, 0x2c630002, 0x1460000c,
+0xaf820200, 0x3c020001, 0x8c426dac, 0x3c030001,
+0x8c636d90, 0x3c040001, 0x8c846d8c, 0x34428000,
+0x621825, 0x641825, 0x1000000a, 0x34620002,
+0x3c020001, 0x8c426d90, 0x3c030001, 0x8c636dac,
+0x3c040001, 0x8c846d8c, 0x431025, 0x441025,
+0x34420002, 0xaf820220, 0x1000002f, 0x24020001,
+0x24020e01, 0xaf820238, 0x8f830050, 0x3c02f0ff,
+0x3442ffff, 0x3c040001, 0x8c846f1c, 0x621824,
+0x3c020d00, 0x621825, 0x24020001, 0xaf830050,
+0xaf820200, 0xaf820220, 0x10800005, 0x3c033f00,
+0x3c020001, 0x8c426d80, 0x10000004, 0x34630070,
+0x3c020001, 0x8c426d80, 0x34630072, 0x431025,
+0xaf820200, 0x3c030001, 0x8c636d84, 0x3c02f700,
+0x621825, 0x3c020001, 0x8c426d90, 0x3c040001,
+0x8c846dac, 0x3c050001, 0x8ca56f40, 0x431025,
+0x441025, 0xaf820220, 0x24020005, 0x14a20006,
+0x24020001, 0x8f820044, 0x2403afff, 0x431024,
+0xaf820044, 0x24020001, 0x1000003d, 0xaf820238,
+0x8f830050, 0x3c02f0ff, 0x3442ffff, 0x3c040001,
+0x8c846f1c, 0x621824, 0x3c020a00, 0x621825,
+0x24020001, 0xaf830050, 0xaf820200, 0x1080001e,
+0xaf820220, 0x3c020001, 0x8c426e44, 0x1440001a,
+0x3c033f00, 0x3c020001, 0x8c426d80, 0x1000001a,
+0x346300e0, 0x8f830050, 0x3c040001, 0x8c846f1c,
+0x3442ffff, 0x621824, 0x1080000f, 0xaf830050,
+0x3c020001, 0x8c426e44, 0x1440000b, 0x3c043f00,
+0x3c030001, 0x8c636d80, 0x348400e0, 0x24020001,
+0xaf820200, 0xaf820220, 0x641825, 0xaf830200,
+0x10000008, 0x3c05f700, 0x3c020001, 0x8c426d80,
+0x3c033f00, 0x346300e2, 0x431025, 0xaf820200,
+0x3c05f700, 0x34a58000, 0x3c030001, 0x8c636d84,
+0x3c020001, 0x8c426d90, 0x3c040001, 0x8c846dac,
+0x651825, 0x431025, 0x441025, 0xaf820220,
+0x3e00008, 0x0, 0x3c030001, 0x8c636db4,
+0x3c020001, 0x8c426db8, 0x10620003, 0x24020002,
+0x3c010001, 0xac236db8, 0x1062001d, 0x2c620003,
+0x10400025, 0x24020001, 0x14620023, 0x24020004,
+0x3c030001, 0x8c636d98, 0x10620006, 0x24020008,
+0x1462000c, 0x3c0200c8, 0x344201fb, 0x10000009,
+0xaf820238, 0x24020e01, 0xaf820238, 0x8f820044,
+0x3c03ffff, 0x34633f7f, 0x431024, 0x34420080,
+0xaf820044, 0x8f830054, 0x24020002, 0x3c010001,
+0xac226db4, 0x3c010001, 0x1000000b, 0xac236f2c,
+0x8f830054, 0x3c020001, 0x8c426f2c, 0x2463d8f0,
+0x431023, 0x2c422710, 0x14400003, 0x24020009,
+0x3c010001, 0xac226db4, 0x3e00008, 0x0,
+0x0, 0x0, 0x0, 0x27bdffd8,
+0xafb20018, 0x809021, 0xafb3001c, 0xa09821,
+0xafb10014, 0xc08821, 0xafb00010, 0x8021,
+0xafbf0020, 0xa6200000, 0xc004d78, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x24100010, 0x2501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x2501024, 0x24100010, 0x2701024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x2701024, 0xc004db9, 0x34108000,
+0xc004db9, 0x0, 0xc004d58, 0x0,
+0x50400005, 0x108042, 0x96220000, 0x501025,
+0xa6220000, 0x108042, 0x1600fff7, 0x0,
+0xc004db9, 0x0, 0x8fbf0020, 0x8fb3001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821,
+0xafb20018, 0xa09021, 0xafb3001c, 0xc09821,
+0xafb00010, 0x8021, 0xafbf0020, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0x24100010, 0x2301024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x2301024, 0x24100010, 0x2501024,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x2501024, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x34108000,
+0x96620000, 0x501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
+0x0, 0xc004db9, 0x0, 0x8fbf0020,
+0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+0x3e00008, 0x27bd0028, 0x3c040001, 0x8c846dd0,
+0x3c020001, 0x8c426e18, 0x27bdffd8, 0xafbf0020,
+0xafb1001c, 0x10820003, 0xafb00018, 0x3c010001,
+0xac246e18, 0x3c030001, 0x8c636f40, 0x24020005,
+0x14620005, 0x2483ffff, 0xc004963, 0x0,
+0x1000034c, 0x0, 0x2c620013, 0x10400349,
+0x31080, 0x3c010001, 0x220821, 0x8c226b80,
+0x400008, 0x0, 0xc004db9, 0x8021,
+0x34028000, 0xa7a20010, 0x27b10010, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0xc004d78,
+0x2021, 0x108042, 0x1600fffc, 0x0,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x96220000, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x1000030e, 0x24020002, 0x27b10010, 0xa7a00010,
+0x8021, 0xc004d78, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
+0x2021, 0xc004d78, 0x24040001, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0xc004d78, 0x2021, 0x108042,
+0x1600fffc, 0x0, 0xc004db9, 0x34108000,
+0xc004db9, 0x0, 0xc004d58, 0x0,
+0x50400005, 0x108042, 0x96220000, 0x501025,
+0xa6220000, 0x108042, 0x1600fff7, 0x0,
+0xc004db9, 0x0, 0x97a20010, 0x30428000,
+0x144002dc, 0x24020003, 0x100002d8, 0x0,
+0x24021200, 0xa7a20010, 0x27b10010, 0x8021,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0xc004d78, 0x2021, 0x108042, 0x1600fffc,
+0x0, 0xc004d78, 0x24040001, 0xc004d78,
+0x2021, 0x34108000, 0x96220000, 0x501024,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fff8, 0x0, 0xc004db9,
+0x0, 0x8f830054, 0x10000296, 0x24020004,
+0x8f830054, 0x3c020001, 0x8c426f3c, 0x2463ff9c,
+0x431023, 0x2c420064, 0x1440029e, 0x24020002,
+0x3c030001, 0x8c636f40, 0x10620297, 0x2c620003,
+0x14400296, 0x24020011, 0x24020003, 0x10620005,
+0x24020004, 0x10620291, 0x2402000f, 0x1000028f,
+0x24020011, 0x1000028d, 0x24020005, 0x24020014,
+0xa7a20010, 0x27b10010, 0x8021, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x32020012,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020012, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x34108000,
+0x96220000, 0x501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
+0x0, 0xc004db9, 0x0, 0x8f830054,
+0x10000248, 0x24020006, 0x8f830054, 0x3c020001,
+0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064,
+0x14400250, 0x24020007, 0x1000024c, 0x0,
+0x24020006, 0xa7a20010, 0x27b10010, 0x8021,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020013, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020013,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x96220000, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x8f830054, 0x10000207, 0x24020008, 0x8f830054,
+0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
+0x2c420064, 0x1440020f, 0x24020009, 0x1000020b,
+0x0, 0x27b10010, 0xa7a00010, 0x8021,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020018, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x96220000, 0x501025, 0xa6220000, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x8021,
+0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020018, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x96220000, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x8f830054, 0x10000193, 0x2402000a, 0x8f830054,
+0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
+0x2c420064, 0x1440019b, 0x2402000b, 0x10000197,
+0x0, 0x27b10010, 0xa7a00010, 0x8021,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020017, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020017,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x96220000, 0x501025, 0xa6220000, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x8021,
+0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020017, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020017,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x96220000, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x8f830054, 0x1000011f, 0x2402000c, 0x8f830054,
+0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
+0x2c420064, 0x14400127, 0x24020012, 0x10000123,
+0x0, 0x27b10010, 0xa7a00010, 0x8021,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020014, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020014,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x96220000, 0x501025, 0xa6220000, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x8021,
+0x97a20010, 0x27b10010, 0x34420010, 0xa7a20010,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020014, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020014,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x96220000, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x8f830054, 0x100000ab, 0x24020013, 0x8f830054,
+0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
+0x2c420064, 0x144000b3, 0x2402000d, 0x100000af,
+0x0, 0x27b10010, 0xa7a00010, 0x8021,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020018, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x96220000, 0x501025, 0xa6220000, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x8021,
+0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020018, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x96220000, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x8f830054, 0x10000037, 0x2402000e, 0x24020840,
+0xa7a20010, 0x27b10010, 0x8021, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x32020013,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020013, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x34108000,
+0x96220000, 0x501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
+0x0, 0xc004db9, 0x0, 0x8f830054,
+0x24020010, 0x3c010001, 0xac226dd0, 0x3c010001,
+0x1000000c, 0xac236f3c, 0x8f830054, 0x3c020001,
+0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064,
+0x14400004, 0x0, 0x24020011, 0x3c010001,
+0xac226dd0, 0x8fbf0020, 0x8fb1001c, 0x8fb00018,
+0x3e00008, 0x27bd0028, 0x3c030001, 0x8c636d98,
+0x27bdffc8, 0x24020002, 0xafbf0034, 0xafb20030,
+0xafb1002c, 0x14620004, 0xafb00028, 0x3c120002,
+0x10000003, 0x8e528ff8, 0x3c120002, 0x8e528ffc,
+0x3c030001, 0x8c636dd4, 0x3c020001, 0x8c426e1c,
+0x50620004, 0x2463ffff, 0x3c010001, 0xac236e1c,
+0x2463ffff, 0x2c620006, 0x10400377, 0x31080,
+0x3c010001, 0x220821, 0x8c226bd8, 0x400008,
+0x0, 0x2021, 0x2821, 0xc004ddb,
+0x34068000, 0x24040010, 0x24050002, 0x24060002,
+0x24020002, 0xc004ddb, 0xa7a20018, 0x24020002,
+0x3c010001, 0x10000364, 0xac226dd4, 0x27b10018,
+0xa7a00018, 0x8021, 0xc004d78, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x32020001, 0x24100010, 0xc004d78, 0x2021,
+0x108042, 0x1600fffc, 0x0, 0xc004db9,
+0x34108000, 0xc004db9, 0x0, 0xc004d58,
+0x0, 0x50400005, 0x108042, 0x96220000,
+0x501025, 0xa6220000, 0x108042, 0x1600fff7,
+0x0, 0xc004db9, 0x0, 0x97a20018,
+0x30428000, 0x14400004, 0x24020003, 0x3c010001,
+0xac226dd4, 0x24020003, 0x3c010001, 0x1000032a,
+0xac226dd4, 0x24040010, 0x24050002, 0x24060002,
+0x24020002, 0xc004ddb, 0xa7a20018, 0x3c030001,
+0x8c636e20, 0x24020001, 0x146201e1, 0x8021,
+0x27b10018, 0xa7a00018, 0xc004d78, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x32020001, 0x24100010, 0x32020018, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020018, 0xc004db9, 0x34108000,
+0xc004db9, 0x0, 0xc004d58, 0x0,
+0x50400005, 0x108042, 0x96220000, 0x501025,
+0xa6220000, 0x108042, 0x1600fff7, 0x0,
+0xc004db9, 0x8021, 0x27b10018, 0xa7a00018,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020018, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x96220000, 0x501025, 0xa6220000, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x8021,
+0x24040018, 0x2821, 0xc004ddb, 0x24060404,
+0xa7a0001a, 0xc004d78, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
+0x2021, 0xc004d78, 0x24040001, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0x32020018, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x32020018, 0xc004db9, 0x34108000, 0xc004db9,
+0x0, 0xc004d58, 0x0, 0x50400005,
+0x108042, 0x97a2001a, 0x501025, 0xa7a2001a,
+0x108042, 0x1600fff7, 0x0, 0xc004db9,
+0x8021, 0xa7a0001a, 0xc004d78, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x32020001, 0x24100010, 0x32020018, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020018, 0xc004db9, 0x34108000,
+0xc004db9, 0x0, 0xc004d58, 0x0,
+0x50400005, 0x108042, 0x97a2001a, 0x501025,
+0xa7a2001a, 0x108042, 0x1600fff7, 0x0,
+0xc004db9, 0x8021, 0xa7a0001c, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x24040001, 0xc004d78,
+0x2021, 0x24100010, 0xc004d78, 0x2021,
+0x108042, 0x1600fffc, 0x0, 0x24100010,
+0x3202001e, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x3202001e,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x97a2001c, 0x501025, 0xa7a2001c, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x8021,
+0xa7a0001c, 0xc004d78, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
+0x2021, 0xc004d78, 0x24040001, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x24100010,
+0xc004d78, 0x2021, 0x108042, 0x1600fffc,
+0x0, 0x24100010, 0x3202001e, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x3202001e, 0xc004db9, 0x34108000,
+0xc004db9, 0x0, 0xc004d58, 0x0,
+0x50400005, 0x108042, 0x97a2001c, 0x501025,
+0xa7a2001c, 0x108042, 0x1600fff7, 0x0,
+0xc004db9, 0x8021, 0x24020002, 0xa7a2001e,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0xc004d78,
+0x2021, 0x108042, 0x1600fffc, 0x0,
+0x24100010, 0x3202001e, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x3202001e, 0xc004d78, 0x24040001, 0xc004d78,
+0x2021, 0x34108000, 0x97a2001e, 0x501024,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fff8, 0x0, 0xc004db9,
+0x8021, 0xa7a00020, 0xc004d78, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x24100010, 0xc004d78, 0x2021, 0x108042,
+0x1600fffc, 0x0, 0x24100010, 0x3202001e,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x3202001e, 0xc004db9,
+0x34108000, 0xc004db9, 0x0, 0xc004d58,
+0x0, 0x50400005, 0x108042, 0x97a20020,
+0x501025, 0xa7a20020, 0x108042, 0x1600fff7,
+0x0, 0xc004db9, 0x8021, 0xa7a00020,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0x24100010, 0xc004d78,
+0x2021, 0x108042, 0x1600fffc, 0x0,
+0x24100010, 0x3202001e, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x3202001e, 0xc004db9, 0x34108000, 0xc004db9,
+0x0, 0xc004d58, 0x0, 0x50400005,
+0x108042, 0x97a20020, 0x501025, 0xa7a20020,
+0x108042, 0x1600fff7, 0x0, 0xc004db9,
+0x8021, 0xa7a00022, 0xc004d78, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0x24100010, 0xc004d78, 0x2021, 0x108042,
+0x1600fffc, 0x0, 0x24100010, 0xc004d78,
+0x2021, 0x108042, 0x1600fffc, 0x0,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x97a20022, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x24040018, 0x24050002, 0xc004ddb, 0x24060004,
+0x3c100001, 0x8e106e24, 0x24020001, 0x1602011d,
+0x0, 0x3c020001, 0x94426f26, 0x3c010001,
+0xac206e24, 0x24429fbc, 0x2c420004, 0x1040000c,
+0x24040009, 0x24050001, 0xc004ddb, 0x24060400,
+0x24040018, 0x24050001, 0xc004ddb, 0x24060020,
+0x24040018, 0x24050001, 0xc004ddb, 0x24062000,
+0x3c024000, 0x2421024, 0x10400123, 0x3c022000,
+0x2421024, 0x10400004, 0x0, 0x3c010001,
+0x10000003, 0xac306f1c, 0x3c010001, 0xac206f1c,
+0x3c030001, 0x8c636f34, 0x24020005, 0x146200f9,
+0x0, 0x3c020001, 0x8c426f1c, 0x10400067,
+0x3c020004, 0x2421024, 0x10400011, 0xa7a00018,
+0x3c020008, 0x2421024, 0x10400002, 0x24020200,
+0xa7a20018, 0x3c020010, 0x2421024, 0x10400004,
+0x0, 0x97a20018, 0x34420100, 0xa7a20018,
+0x97a60018, 0x24040009, 0x10000004, 0x2821,
+0x24040009, 0x2821, 0x3021, 0xc004ddb,
+0x0, 0x24020001, 0xa7a2001a, 0x3c020008,
+0x2421024, 0x1040000c, 0x3c020002, 0x2421024,
+0x10400002, 0x24020101, 0xa7a2001a, 0x3c020001,
+0x2421024, 0x10400005, 0x3c020010, 0x97a2001a,
+0x34420040, 0xa7a2001a, 0x3c020010, 0x2421024,
+0x1040000e, 0x3c020002, 0x2421024, 0x10400005,
+0x3c020001, 0x97a2001a, 0x34420080, 0xa7a2001a,
+0x3c020001, 0x2421024, 0x10400005, 0x3c0300a0,
+0x97a2001a, 0x34420020, 0xa7a2001a, 0x3c0300a0,
+0x2431024, 0x54430004, 0x3c020020, 0x97a2001a,
+0x1000000c, 0x34420400, 0x2421024, 0x50400004,
+0x3c020080, 0x97a2001a, 0x10000006, 0x34420800,
+0x2421024, 0x10400004, 0x0, 0x97a2001a,
+0x34420c00, 0xa7a2001a, 0x97a6001a, 0x24040004,
+0xc004ddb, 0x2821, 0x3c020004, 0x2421024,
+0x10400004, 0xa7a0001c, 0x32425000, 0x14400004,
+0x0, 0x32424000, 0x10400005, 0x2021,
+0xc004cf9, 0x2402021, 0x10000096, 0x0,
+0x97a6001c, 0x2821, 0x34c61200, 0xc004ddb,
+0xa7a6001c, 0x1000008f, 0x0, 0x2421024,
+0x10400004, 0xa7a00018, 0x32425000, 0x14400004,
+0x0, 0x32424000, 0x10400005, 0x3c020010,
+0xc004cf9, 0x2402021, 0x10000019, 0xa7a0001a,
+0x2421024, 0x10400004, 0x0, 0x97a20018,
+0x10000004, 0xa7a20018, 0x97a20018, 0x34420100,
+0xa7a20018, 0x3c020001, 0x2421024, 0x10400004,
+0x0, 0x97a20018, 0x10000004, 0xa7a20018,
+0x97a20018, 0x34422000, 0xa7a20018, 0x97a60018,
+0x2021, 0xc004ddb, 0x2821, 0xa7a0001a,
+0x8021, 0xc004d78, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
+0x2021, 0xc004d78, 0x24040001, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0xc004d78, 0x2021, 0x108042,
+0x1600fffc, 0x0, 0xc004db9, 0x34108000,
+0xc004db9, 0x0, 0xc004d58, 0x0,
+0x50400005, 0x108042, 0x97a2001a, 0x501025,
+0xa7a2001a, 0x108042, 0x1600fff7, 0x0,
+0xc004db9, 0x8021, 0xa7a0001a, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x24040001, 0xc004d78,
+0x2021, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0xc004d78,
+0x2021, 0x108042, 0x1600fffc, 0x0,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x97a2001a, 0x501025, 0xa7a2001a, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x0,
+0x3c040001, 0x24846bcc, 0x97a60018, 0x97a7001a,
+0x3c020001, 0x8c426d98, 0x3c030001, 0x8c636f1c,
+0x3c05000d, 0x34a50205, 0xafa20010, 0xc002b3b,
+0xafa30014, 0x8f830054, 0x24020004, 0x3c010001,
+0xac226dd4, 0x3c010001, 0x10000017, 0xac236f38,
+0x8f830054, 0x3c020001, 0x8c426f38, 0x2463ff9c,
+0x431023, 0x2c420064, 0x1440000f, 0x0,
+0x8f820220, 0x24030005, 0x3c010001, 0xac236dd4,
+0x3c03f700, 0x431025, 0x10000007, 0xaf820220,
+0x24020006, 0x3c010001, 0xac226dd4, 0x24020011,
+0x3c010001, 0xac226dd0, 0x8fbf0034, 0x8fb20030,
+0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0038,
+0x27bdffd8, 0xafb00018, 0x808021, 0xafb1001c,
+0x8821, 0x32024000, 0x10400013, 0xafbf0020,
+0x3c020010, 0x2021024, 0x2c420001, 0x21023,
+0x30434100, 0x3c020001, 0x2021024, 0x14400006,
+0x34714000, 0x3c020002, 0x2021024, 0x14400002,
+0x34716000, 0x34714040, 0x2021, 0x2821,
+0x10000036, 0x2203021, 0x32021000, 0x10400035,
+0x2021, 0x2821, 0xc004ddb, 0x24060040,
+0x24040018, 0x2821, 0xc004ddb, 0x24060c00,
+0x24040017, 0x2821, 0xc004ddb, 0x24060400,
+0x24040016, 0x2821, 0xc004ddb, 0x24060006,
+0x24040017, 0x2821, 0xc004ddb, 0x24062500,
+0x24040016, 0x2821, 0xc004ddb, 0x24060006,
+0x24040017, 0x2821, 0xc004ddb, 0x24064600,
+0x24040016, 0x2821, 0xc004ddb, 0x24060006,
+0x24040017, 0x2821, 0xc004ddb, 0x24066700,
+0x24040016, 0x2821, 0xc004ddb, 0x24060006,
+0x2404001f, 0x2821, 0xc004ddb, 0x24060010,
+0x24040009, 0x2821, 0xc004ddb, 0x24061500,
+0x24040009, 0x2821, 0x24061d00, 0xc004ddb,
+0x0, 0x3c040001, 0x24846bf0, 0x3c05000e,
+0x34a50100, 0x2003021, 0x2203821, 0xafa00010,
+0xc002b3b, 0xafa00014, 0x8fbf0020, 0x8fb1001c,
+0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044,
+0x8f820044, 0x3c030001, 0x431025, 0x3c030008,
+0xaf820044, 0x8f840054, 0x8f820054, 0xa32824,
+0x10000002, 0x24840001, 0x8f820054, 0x821023,
+0x2c420002, 0x1440fffc, 0x0, 0x8f820044,
+0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x3e00008, 0xa01021, 0x8f830044,
+0x3c02fff0, 0x3442ffff, 0x42480, 0x621824,
+0x3c020002, 0x822025, 0x641825, 0xaf830044,
+0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024,
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
+0x24630001, 0x8f820054, 0x621023, 0x2c420002,
+0x1440fffc, 0x0, 0x8f820044, 0x3c030001,
+0x431025, 0xaf820044, 0x8f830054, 0x8f820054,
+0x10000002, 0x24630001, 0x8f820054, 0x621023,
+0x2c420002, 0x1440fffc, 0x0, 0x3e00008,
+0x0, 0x8f820044, 0x2403ff7f, 0x431024,
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
+0x24630001, 0x8f820054, 0x621023, 0x2c420002,
+0x1440fffc, 0x0, 0x8f820044, 0x34420080,
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
+0x24630001, 0x8f820054, 0x621023, 0x2c420002,
+0x1440fffc, 0x0, 0x3e00008, 0x0,
+0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024,
+0xaf820044, 0x8f820044, 0x3c030001, 0x431025,
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
+0x24630001, 0x8f820054, 0x621023, 0x2c420002,
+0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe,
+0x3463ffff, 0x431024, 0xaf820044, 0x8f830054,
+0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
+0x621023, 0x2c420002, 0x1440fffc, 0x0,
+0x3e00008, 0x0, 0x27bdffc8, 0xafb30024,
+0x809821, 0xafbe002c, 0xa0f021, 0xafb20020,
+0xc09021, 0x33c2ffff, 0xafbf0030, 0xafb50028,
+0xafb1001c, 0xafb00018, 0x14400034, 0xa7b20010,
+0x3271ffff, 0x27b20010, 0x8021, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x2301024,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x2301024, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x34108000,
+0x96420000, 0x501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x12000075,
+0x0, 0x1000fff6, 0x0, 0x3275ffff,
+0x27b10010, 0xa7a00010, 0x8021, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x24040001, 0xc004d78,
+0x2021, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x2b01024,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x2b01024, 0xc004db9,
+0x34108000, 0xc004db9, 0x0, 0xc004d58,
+0x0, 0x50400005, 0x108042, 0x96220000,
+0x501025, 0xa6220000, 0x108042, 0x1600fff7,
+0x0, 0xc004db9, 0x0, 0x33c5ffff,
+0x24020001, 0x54a20004, 0x24020002, 0x97a20010,
+0x10000006, 0x521025, 0x14a20006, 0x3271ffff,
+0x97a20010, 0x121827, 0x431024, 0xa7a20010,
+0x3271ffff, 0x27b20010, 0x8021, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x2301024,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x2301024, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x34108000,
+0x96420000, 0x501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
+0x0, 0xc004db9, 0x0, 0x8fbf0030,
+0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb20020,
+0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038,
+0x0, 0x0, 0x0, 0x27bdffe8,
+0xafbf0010, 0x8ee304b8, 0x24020008, 0x146201e0,
+0x0, 0x3c020001, 0x8c426f1c, 0x14400005,
+0x0, 0xc003daf, 0x8f840224, 0x100001d8,
+0x0, 0x8f820220, 0x3c030008, 0x431024,
+0x10400026, 0x24020001, 0x8f840224, 0x8f820220,
+0x3c030400, 0x431024, 0x10400006, 0x0,
+0x3c010002, 0xac208fa0, 0x3c010002, 0x1000000b,
+0xac208fc0, 0x3c030002, 0x24638fa0, 0x8c620000,
+0x24420001, 0xac620000, 0x2c420002, 0x14400003,
+0x24020001, 0x3c010002, 0xac228fc0, 0x3c020002,
+0x8c428fc0, 0x10400006, 0x30820040, 0x10400004,
+0x24020001, 0x3c010002, 0x10000003, 0xac228fc4,
+0x3c010002, 0xac208fc4, 0x3c010002, 0xac248f9c,
+0x3c010002, 0x1000000b, 0xac208fd0, 0x3c010002,
+0xac228fd0, 0x3c010002, 0xac208fc0, 0x3c010002,
+0xac208fa0, 0x3c010002, 0xac208fc4, 0x3c010002,
+0xac208f9c, 0x3c030002, 0x8c638f90, 0x3c020002,
+0x8c428f94, 0x50620004, 0x2463ffff, 0x3c010002,
+0xac238f94, 0x2463ffff, 0x2c62000e, 0x10400194,
+0x31080, 0x3c010001, 0x220821, 0x8c226c00,
+0x400008, 0x0, 0x24020002, 0x3c010002,
+0xac208fc0, 0x3c010002, 0xac208fa0, 0x3c010002,
+0xac208f9c, 0x3c010002, 0xac208fc4, 0x3c010002,
+0xac208fb8, 0x3c010002, 0xac208fb0, 0xaf800224,
+0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fd0,
+0x1440004f, 0x3c02fdff, 0x3442ffff, 0xc003daf,
+0x282a024, 0xaf800204, 0x8f820200, 0x2403fffd,
+0x431024, 0xaf820200, 0x3c010002, 0xac208fe0,
+0x8f830054, 0x3c020002, 0x8c428fb8, 0x24040001,
+0x3c010002, 0xac248fcc, 0x24420001, 0x3c010002,
+0xac228fb8, 0x2c420004, 0x3c010002, 0xac238fb4,
+0x14400006, 0x24020003, 0x3c010001, 0xac246d9c,
+0x3c010002, 0x1000015e, 0xac208fb8, 0x3c010002,
+0x1000015b, 0xac228f90, 0x8f830054, 0x3c020002,
+0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710,
+0x14400003, 0x24020004, 0x3c010002, 0xac228f90,
+0x3c020002, 0x8c428fd0, 0x14400021, 0x3c02fdff,
+0x3442ffff, 0x1000014a, 0x282a024, 0x3c040001,
+0x8c846f20, 0x3c010002, 0xc005084, 0xac208fa8,
+0x3c020002, 0x8c428fdc, 0xaf820204, 0x3c020002,
+0x8c428fd0, 0x14400012, 0x3c03fdff, 0x8f820204,
+0x3463ffff, 0x30420030, 0x1440012f, 0x283a024,
+0x3c030002, 0x8c638fdc, 0x24020005, 0x3c010002,
+0xac228f90, 0x3c010002, 0x10000131, 0xac238fe0,
+0x3c020002, 0x8c428fd0, 0x10400010, 0x3c02fdff,
+0x3c020001, 0x8c426e3c, 0x24420001, 0x3c010001,
+0xac226e3c, 0x2c420002, 0x14400125, 0x24020001,
+0x3c010001, 0xac226e44, 0x3c010001, 0xac206e3c,
+0x3c010001, 0x1000011e, 0xac226d9c, 0x3c030002,
+0x8c638fc0, 0x3442ffff, 0x10600119, 0x282a024,
+0x3c020002, 0x8c428f9c, 0x10400115, 0x0,
+0x3c010002, 0xac228fc8, 0x24020003, 0x3c010002,
+0xac228fa0, 0x100000b8, 0x24020006, 0x3c010002,
+0xac208fa8, 0x8f820204, 0x34420040, 0xaf820204,
+0x3c020002, 0x8c428fe0, 0x24030007, 0x3c010002,
+0xac238f90, 0x34420040, 0x3c010002, 0xac228fe0,
+0x3c020002, 0x8c428fc0, 0x10400005, 0x0,
+0x3c020002, 0x8c428f9c, 0x104000f0, 0x24020002,
+0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21,
+0x104000ea, 0x24020002, 0x3c020002, 0x8c428fc4,
+0x104000ef, 0x2404ffbf, 0x3c020002, 0x8c428f9c,
+0x3c030002, 0x8c638fc8, 0x441024, 0x641824,
+0x10430004, 0x24020001, 0x3c010002, 0x100000e4,
+0xac228f90, 0x24020003, 0xaca20000, 0x24020008,
+0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fcc,
+0x1040000c, 0x24020001, 0x3c040002, 0xc005091,
+0x8c848f9c, 0x3c020002, 0x8c428fe8, 0x14400005,
+0x24020001, 0x3c020002, 0x8c428fe4, 0x10400006,
+0x24020001, 0x3c010001, 0xac226d9c, 0x3c010002,
+0x100000cb, 0xac208fb8, 0x3c020002, 0x8c428fb0,
+0x3c030002, 0x8c638f9c, 0x2c420001, 0x210c0,
+0x30630008, 0x3c010002, 0xac228fb0, 0x3c010002,
+0xac238fac, 0x8f830054, 0x24020009, 0x3c010002,
+0xac228f90, 0x3c010002, 0x100000b9, 0xac238fb4,
+0x8f830054, 0x3c020002, 0x8c428fb4, 0x2463d8f0,
+0x431023, 0x2c422710, 0x1440009f, 0x0,
+0x3c020002, 0x8c428fc0, 0x10400005, 0x0,
+0x3c020002, 0x8c428f9c, 0x104000a0, 0x24020002,
+0x3c030002, 0x24638fa0, 0x8c620000, 0x2c424e21,
+0x1040009a, 0x24020002, 0x3c020002, 0x8c428fcc,
+0x1040000e, 0x0, 0x3c020002, 0x8c428f9c,
+0x3c010002, 0xac208fcc, 0x30420080, 0x1040002f,
+0x2402000c, 0x8f820204, 0x30420080, 0x1440000c,
+0x24020003, 0x10000029, 0x2402000c, 0x3c020002,
+0x8c428f9c, 0x30420080, 0x14400005, 0x24020003,
+0x8f820204, 0x30420080, 0x1040001f, 0x24020003,
+0xac620000, 0x2402000a, 0x3c010002, 0xac228f90,
+0x3c040002, 0x24848fd8, 0x8c820000, 0x3c030002,
+0x8c638fb0, 0x431025, 0xaf820204, 0x8c830000,
+0x3c040002, 0x8c848fb0, 0x2402000b, 0x3c010002,
+0xac228f90, 0x641825, 0x3c010002, 0xac238fe0,
+0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21,
+0x10400066, 0x24020002, 0x3c020002, 0x8c428fd0,
+0x10400005, 0x0, 0x2402000c, 0x3c010002,
+0x10000067, 0xac228f90, 0x3c020002, 0x8c428fc0,
+0x10400063, 0x0, 0x3c040002, 0x8c848f9c,
+0x10800055, 0x30820008, 0x3c030002, 0x8c638fac,
+0x1062005b, 0x24020003, 0x3c010002, 0xac248fc8,
+0xaca20000, 0x24020006, 0x3c010002, 0x10000054,
+0xac228f90, 0x8f820200, 0x34420002, 0xaf820200,
+0x8f830054, 0x2402000d, 0x3c010002, 0xac228f90,
+0x3c010002, 0xac238fb4, 0x8f830054, 0x3c020002,
+0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710,
+0x14400031, 0x0, 0x3c020002, 0x8c428fd0,
+0x10400020, 0x2402000e, 0x3c030002, 0x8c638fe4,
+0x3c010002, 0x14600015, 0xac228f90, 0xc003e6d,
+0x0, 0x3c050001, 0x8ca56d98, 0xc00529b,
+0x2021, 0x3c030001, 0x8c636d98, 0x24020004,
+0x14620005, 0x2403fffb, 0x3c020001, 0x8c426d94,
+0x10000003, 0x2403fff7, 0x3c020001, 0x8c426d94,
+0x431024, 0x3c010001, 0xac226d94, 0x8f830224,
+0x3c020200, 0x3c010002, 0xac238fec, 0x10000020,
+0x282a025, 0x3c020002, 0x8c428fc0, 0x10400005,
+0x0, 0x3c020002, 0x8c428f9c, 0x1040000f,
+0x24020002, 0x3c020002, 0x8c428fa0, 0x2c424e21,
+0x1040000a, 0x24020002, 0x3c020002, 0x8c428fc0,
+0x1040000f, 0x0, 0x3c020002, 0x8c428f9c,
+0x1440000b, 0x0, 0x24020002, 0x3c010002,
+0x10000007, 0xac228f90, 0x3c020002, 0x8c428fc0,
+0x10400003, 0x0, 0xc003daf, 0x0,
+0x8f820220, 0x3c03f700, 0x431025, 0xaf820220,
+0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c030002,
+0x24638fe8, 0x8c620000, 0x10400005, 0x34422000,
+0x3c010002, 0xac228fdc, 0x10000003, 0xac600000,
+0x3c010002, 0xac248fdc, 0x3e00008, 0x0,
+0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010002,
+0xac228fe4, 0x14400067, 0x3c02ffff, 0x34421f0e,
+0x821024, 0x14400061, 0x24020030, 0x30822000,
+0x1040005d, 0x30838000, 0x31a02, 0x30820001,
+0x21200, 0x3c040001, 0x8c846f20, 0x621825,
+0x331c2, 0x3c030001, 0x24636e48, 0x30828000,
+0x21202, 0x30840001, 0x42200, 0x441025,
+0x239c2, 0x61080, 0x431021, 0x471021,
+0x90430000, 0x24020001, 0x10620025, 0x0,
+0x10600007, 0x24020002, 0x10620013, 0x24020003,
+0x1062002c, 0x3c05000f, 0x10000037, 0x0,
+0x8f820200, 0x2403feff, 0x431024, 0xaf820200,
+0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024,
+0xaf820220, 0x3c010002, 0xac209004, 0x3c010002,
+0x10000034, 0xac20900c, 0x8f820200, 0x34420100,
+0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff,
+0x431024, 0xaf820220, 0x24020100, 0x3c010002,
+0xac229004, 0x3c010002, 0x10000026, 0xac20900c,
+0x8f820200, 0x2403feff, 0x431024, 0xaf820200,
+0x8f820220, 0x3c030001, 0x431025, 0xaf820220,
+0x3c010002, 0xac209004, 0x3c010002, 0x10000019,
+0xac23900c, 0x8f820200, 0x34420100, 0xaf820200,
+0x8f820220, 0x3c030001, 0x431025, 0xaf820220,
+0x24020100, 0x3c010002, 0xac229004, 0x3c010002,
+0x1000000c, 0xac23900c, 0x34a5ffff, 0x3c040001,
+0x24846c38, 0xafa30010, 0xc002b3b, 0xafa00014,
+0x10000004, 0x0, 0x24020030, 0x3c010002,
+0xac228fe8, 0x8fbf0018, 0x3e00008, 0x27bd0020,
+0x0, 0x0, 0x0, 0x27bdffc8,
+0xafb20028, 0x809021, 0xafb3002c, 0xa09821,
+0xafb00020, 0xc08021, 0x3c040001, 0x24846c50,
+0x3c050009, 0x3c020001, 0x8c426d98, 0x34a59001,
+0x2403021, 0x2603821, 0xafbf0030, 0xafb10024,
+0xa7a0001a, 0xafb00014, 0xc002b3b, 0xafa20010,
+0x24020002, 0x12620083, 0x2e620003, 0x10400005,
+0x24020001, 0x1262000a, 0x0, 0x10000173,
+0x0, 0x24020004, 0x126200f8, 0x24020008,
+0x126200f7, 0x3c02ffec, 0x1000016c, 0x0,
+0x3c020001, 0x8c426d94, 0x30420002, 0x14400004,
+0x128940, 0x3c02fffb, 0x3442ffff, 0x2028024,
+0x3c010002, 0x310821, 0xac308ffc, 0x3c024000,
+0x2021024, 0x1040004e, 0x1023c2, 0x30840030,
+0x101382, 0x3042001c, 0x3c030001, 0x24636dd8,
+0x431021, 0x823821, 0x3c020020, 0x2021024,
+0x10400006, 0x24020100, 0x3c010002, 0x310821,
+0xac229000, 0x10000005, 0x3c020080, 0x3c010002,
+0x310821, 0xac209000, 0x3c020080, 0x2021024,
+0x10400006, 0x121940, 0x3c020001, 0x3c010002,
+0x230821, 0x10000005, 0xac229008, 0x121140,
+0x3c010002, 0x220821, 0xac209008, 0x94e40000,
+0x3c030001, 0x8c636f40, 0x24020005, 0x10620010,
+0xa7a40018, 0x32024000, 0x10400002, 0x34824000,
+0xa7a20018, 0x24040001, 0x94e20002, 0x24050004,
+0x24e60002, 0x34420001, 0xc0045be, 0xa4e20002,
+0x24040001, 0x2821, 0xc0045be, 0x27a60018,
+0x3c020001, 0x8c426d98, 0x24110001, 0x3c010001,
+0xac316da4, 0x14530004, 0x32028000, 0xc003daf,
+0x0, 0x32028000, 0x1040011c, 0x0,
+0xc003daf, 0x0, 0x3c030001, 0x8c636f40,
+0x24020005, 0x10620115, 0x24020002, 0x3c010001,
+0xac316d9c, 0x3c010001, 0x10000110, 0xac226d98,
+0x24040001, 0x24050004, 0x27b0001a, 0xc0045be,
+0x2003021, 0x24040001, 0x2821, 0xc0045be,
+0x2003021, 0x3c020002, 0x511021, 0x8c428ff4,
+0x3c040001, 0x8c846d98, 0x3c03bfff, 0x3463ffff,
+0x3c010001, 0xac336da4, 0x431024, 0x3c010002,
+0x310821, 0x109300f7, 0xac228ff4, 0x100000f7,
+0x0, 0x3c022000, 0x2021024, 0x10400005,
+0x24020001, 0x3c010001, 0xac226f1c, 0x10000004,
+0x128940, 0x3c010001, 0xac206f1c, 0x128940,
+0x3c010002, 0x310821, 0xac308ff8, 0x3c024000,
+0x2021024, 0x14400014, 0x0, 0x3c020001,
+0x8c426f1c, 0x10400006, 0x24040004, 0x24050001,
+0xc004ddb, 0x24062000, 0x24020001, 0xaee204b8,
+0x3c020002, 0x511021, 0x8c428ff0, 0x3c03bfff,
+0x3463ffff, 0x431024, 0x3c010002, 0x310821,
+0x100000d0, 0xac228ff0, 0x3c020001, 0x8c426f1c,
+0x10400028, 0x3c0300a0, 0x2031024, 0x5443000d,
+0x3c020020, 0x3c020001, 0x8c426f20, 0x24030100,
+0x3c010002, 0x310821, 0xac239004, 0x3c030001,
+0x3c010002, 0x310821, 0xac23900c, 0x10000015,
+0x34420400, 0x2021024, 0x10400008, 0x24030100,
+0x3c020001, 0x8c426f20, 0x3c010002, 0x310821,
+0xac239004, 0x1000000b, 0x34420800, 0x3c020080,
+0x2021024, 0x1040002e, 0x3c030001, 0x3c020001,
+0x8c426f20, 0x3c010002, 0x310821, 0xac23900c,
+0x34420c00, 0x3c010001, 0xac226f20, 0x10000025,
+0x24040001, 0x3c020020, 0x2021024, 0x10400006,
+0x24020100, 0x3c010002, 0x310821, 0xac229004,
+0x10000005, 0x3c020080, 0x3c010002, 0x310821,
+0xac209004, 0x3c020080, 0x2021024, 0x10400007,
+0x121940, 0x3c020001, 0x3c010002, 0x230821,
+0xac22900c, 0x10000006, 0x24040001, 0x121140,
+0x3c010002, 0x220821, 0xac20900c, 0x24040001,
+0x2821, 0x27b0001e, 0xc00457c, 0x2003021,
+0x24040001, 0x2821, 0xc00457c, 0x2003021,
+0x24040001, 0x24050001, 0x27b0001c, 0xc00457c,
+0x2003021, 0x24040001, 0x24050001, 0xc00457c,
+0x2003021, 0x10000077, 0x0, 0x3c02ffec,
+0x3442ffff, 0x2028024, 0x3c020008, 0x2028025,
+0x121140, 0x3c010002, 0x220821, 0xac308ff8,
+0x3c022000, 0x2021024, 0x10400009, 0x0,
+0x3c020001, 0x8c426e44, 0x14400005, 0x24020001,
+0x3c010001, 0xac226f1c, 0x10000004, 0x3c024000,
+0x3c010001, 0xac206f1c, 0x3c024000, 0x2021024,
+0x1440001d, 0x24020e01, 0x3c030001, 0x8c636f1c,
+0xaf820238, 0x3c010001, 0xac206db0, 0x10600005,
+0x24022020, 0x3c010001, 0xac226f20, 0x24020001,
+0xaee204b8, 0x3c04bfff, 0x121940, 0x3c020002,
+0x431021, 0x8c428ff0, 0x3c050001, 0x8ca56d98,
+0x3484ffff, 0x441024, 0x3c010002, 0x230821,
+0xac228ff0, 0x24020001, 0x10a20044, 0x0,
+0x10000040, 0x0, 0x3c020001, 0x8c426f1c,
+0x1040001c, 0x24022000, 0x3c010001, 0xac226f20,
+0x3c0300a0, 0x2031024, 0x14430005, 0x121140,
+0x3402a000, 0x3c010001, 0x1000002d, 0xac226f20,
+0x3c030002, 0x621821, 0x8c638ff8, 0x3c020020,
+0x621024, 0x10400004, 0x24022001, 0x3c010001,
+0x10000023, 0xac226f20, 0x3c020080, 0x621024,
+0x1040001f, 0x3402a001, 0x3c010001, 0x1000001c,
+0xac226f20, 0x3c020020, 0x2021024, 0x10400007,
+0x121940, 0x24020100, 0x3c010002, 0x230821,
+0xac229004, 0x10000006, 0x3c020080, 0x121140,
+0x3c010002, 0x220821, 0xac209004, 0x3c020080,
+0x2021024, 0x10400006, 0x121940, 0x3c020001,
+0x3c010002, 0x230821, 0x10000005, 0xac22900c,
+0x121140, 0x3c010002, 0x220821, 0xac20900c,
+0x3c030001, 0x8c636d98, 0x24020001, 0x10620003,
+0x0, 0xc003daf, 0x0, 0x8fbf0030,
+0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
+0x3e00008, 0x27bd0038, 0x27bdffb0, 0xafb3003c,
+0x9821, 0xafb50040, 0xa821, 0xafb10034,
+0x8821, 0x24020002, 0xafbf0048, 0xafbe0044,
+0xafb20038, 0xafb00030, 0xafa4002c, 0xa7a0001a,
+0xa7a00018, 0xa7a00020, 0xa7a0001e, 0xa7a00022,
+0x10a20130, 0xa7a0001c, 0x2ca20003, 0x10400005,
+0x24020001, 0x10a2000a, 0x3c024000, 0x1000025d,
+0x2201021, 0x24020004, 0x10a2020a, 0x24020008,
+0x10a20208, 0x2201021, 0x10000256, 0x0,
+0x8fa8002c, 0x88140, 0x3c030002, 0x701821,
+0x8c638ffc, 0x621024, 0x14400009, 0x24040001,
+0x3c027fff, 0x3442ffff, 0x628824, 0x3c010002,
+0x300821, 0xac318ff4, 0x10000246, 0x2201021,
+0x24050001, 0xc00457c, 0x27a60018, 0x24040001,
+0x24050001, 0xc00457c, 0x27a60018, 0x97a20018,
+0x30420004, 0x104000d9, 0x3c114000, 0x3c020001,
+0x8c426f40, 0x2443ffff, 0x2c620006, 0x104000d9,
+0x31080, 0x3c010001, 0x220821, 0x8c226c68,
+0x400008, 0x0, 0x24040001, 0x24050011,
+0x27b0001a, 0xc00457c, 0x2003021, 0x24040001,
+0x24050011, 0xc00457c, 0x2003021, 0x97a3001a,
+0x30624000, 0x10400002, 0x3c150010, 0x3c150008,
+0x30628000, 0x104000aa, 0x3c130001, 0x100000a8,
+0x3c130002, 0x24040001, 0x24050014, 0x27b0001a,
+0xc00457c, 0x2003021, 0x24040001, 0x24050014,
+0xc00457c, 0x2003021, 0x97a3001a, 0x30621000,
+0x10400002, 0x3c150010, 0x3c150008, 0x30620800,
+0x10400097, 0x3c130001, 0x10000095, 0x3c130002,
+0x24040001, 0x24050019, 0x27b0001c, 0xc00457c,
+0x2003021, 0x24040001, 0x24050019, 0xc00457c,
+0x2003021, 0x97a2001c, 0x30430700, 0x24020400,
+0x10620027, 0x28620401, 0x1040000e, 0x24020200,
+0x1062001f, 0x28620201, 0x10400005, 0x24020100,
+0x5062001e, 0x3c130001, 0x1000001e, 0x24040001,
+0x24020300, 0x50620019, 0x3c130002, 0x10000019,
+0x24040001, 0x24020600, 0x1062000d, 0x28620601,
+0x10400005, 0x24020500, 0x5062000b, 0x3c130002,
+0x10000010, 0x24040001, 0x24020700, 0x1462000d,
+0x24040001, 0x3c130004, 0x1000000a, 0x3c150008,
+0x10000006, 0x3c130004, 0x10000005, 0x3c150008,
+0x3c130001, 0x10000002, 0x3c150008, 0x3c150010,
+0x24040001, 0x24050018, 0x27b0001e, 0xc00457c,
+0x2003021, 0x24040001, 0x24050018, 0xc00457c,
+0x2003021, 0x8fa8002c, 0x97a7001e, 0x81140,
+0x3c060002, 0xc23021, 0x8cc68ff4, 0x97a20022,
+0x3c100001, 0x26106c5c, 0x2002021, 0xafa20010,
+0x97a2001c, 0x3c05000c, 0x34a50303, 0xc002b3b,
+0xafa20014, 0x3c020004, 0x16620010, 0x3c020001,
+0x8f840054, 0x24030001, 0x24020002, 0x3c010001,
+0xac236d9c, 0x3c010001, 0xac226d98, 0x3c010001,
+0xac236da4, 0x3c010001, 0xac236e24, 0x3c010001,
+0xac246f30, 0x1000004f, 0x2b38825, 0x16620039,
+0x3c028000, 0x3c020001, 0x8c426e20, 0x1440001e,
+0x24040018, 0x2021, 0x2821, 0xc004ddb,
+0x34068000, 0x8f830054, 0x8f820054, 0x2b38825,
+0x10000002, 0x24630032, 0x8f820054, 0x621023,
+0x2c420033, 0x1440fffc, 0x0, 0x8f830054,
+0x24020001, 0x3c010001, 0xac226e20, 0x3c010001,
+0xac226d9c, 0x3c010001, 0xac226d98, 0x3c010001,
+0xac226da4, 0x3c010001, 0xac226e24, 0x3c010001,
+0x1000002c, 0xac236f30, 0x2821, 0xc004ddb,
+0x24060404, 0x2021, 0x2405001e, 0x27a60018,
+0x24020002, 0xc0045be, 0xa7a20018, 0x2021,
+0x2821, 0x27a60018, 0xc0045be, 0xa7a00018,
+0x24040018, 0x24050002, 0xc004ddb, 0x24060004,
+0x3c028000, 0x2221025, 0x2b31825, 0x10000015,
+0x438825, 0x2221025, 0x2751825, 0x438825,
+0x2002021, 0x97a6001c, 0x3c070001, 0x8ce76d98,
+0x3c05000c, 0x34a50326, 0xafb30010, 0xc002b3b,
+0xafb10014, 0x10000007, 0x0, 0x3c110002,
+0x2308821, 0x8e318ffc, 0x3c027fff, 0x3442ffff,
+0x2228824, 0x3c020001, 0x8c426da8, 0x1040001e,
+0x0, 0x3c020001, 0x8c426f1c, 0x10400002,
+0x3c022000, 0x2228825, 0x8fa8002c, 0x81140,
+0x3c010002, 0x220821, 0x8c229000, 0x10400003,
+0x3c020020, 0x10000005, 0x2228825, 0x3c02ffdf,
+0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140,
+0x3c010002, 0x220821, 0x8c229008, 0x10400003,
+0x3c020080, 0x10000004, 0x2228825, 0x3c02ff7f,
+0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140,
+0x3c010002, 0x220821, 0xac318ff4, 0x10000135,
+0x2201021, 0x8fa8002c, 0x8f140, 0x3c030002,
+0x7e1821, 0x8c638ff8, 0x3c024000, 0x621024,
+0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff,
+0x628824, 0x3c010002, 0x3e0821, 0xac318ff0,
+0x10000124, 0x2201021, 0x2821, 0xc00457c,
+0x27a60018, 0x24040001, 0x2821, 0xc00457c,
+0x27a60018, 0x24040001, 0x24050001, 0x27b20020,
+0xc00457c, 0x2403021, 0x24040001, 0x24050001,
+0xc00457c, 0x2403021, 0x24040001, 0x24050004,
+0x27b1001e, 0xc00457c, 0x2203021, 0x24040001,
+0x24050004, 0xc00457c, 0x2203021, 0x24040001,
+0x24050005, 0x27b00022, 0xc00457c, 0x2003021,
+0x24040001, 0x24050005, 0xc00457c, 0x2003021,
+0x24040001, 0x24050010, 0xc00457c, 0x27a60018,
+0x24040001, 0x24050010, 0xc00457c, 0x27a60018,
+0x24040001, 0x2405000a, 0xc00457c, 0x2403021,
+0x24040001, 0x2405000a, 0xc00457c, 0x2403021,
+0x24040001, 0x24050018, 0xc00457c, 0x2203021,
+0x24040001, 0x24050018, 0xc00457c, 0x2203021,
+0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
+0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
+0x97a20018, 0x30420004, 0x10400066, 0x3c114000,
+0x3c030001, 0x8c636f34, 0x24020005, 0x14620067,
+0x24040001, 0x24050019, 0x27b0001c, 0xc00457c,
+0x2003021, 0x24040001, 0x24050019, 0xc00457c,
+0x2003021, 0x97a2001c, 0x30430700, 0x24020400,
+0x10620027, 0x28620401, 0x1040000e, 0x24020200,
+0x1062001f, 0x28620201, 0x10400005, 0x24020100,
+0x5062001e, 0x3c130001, 0x1000001e, 0x3c020004,
+0x24020300, 0x50620019, 0x3c130002, 0x10000019,
+0x3c020004, 0x24020600, 0x1062000d, 0x28620601,
+0x10400005, 0x24020500, 0x5062000b, 0x3c130002,
+0x10000010, 0x3c020004, 0x24020700, 0x1462000d,
+0x3c020004, 0x3c130004, 0x1000000a, 0x3c150008,
+0x10000006, 0x3c130004, 0x10000005, 0x3c150008,
+0x3c130001, 0x10000002, 0x3c150008, 0x3c150010,
+0x3c020004, 0x12620017, 0x3c028000, 0x8f820054,
+0x24100001, 0x3c010001, 0xac306d9c, 0x3c010001,
+0xac306d98, 0x3c010001, 0xac306da4, 0x3c010001,
+0xac306e24, 0x3c010001, 0xac226f30, 0x3c020001,
+0x16620022, 0x2758825, 0x2021, 0x2821,
+0xc004ddb, 0x34068000, 0x3c010001, 0x1000001b,
+0xac306e20, 0x2221025, 0x2b31825, 0x438825,
+0x97a6001c, 0x3c020001, 0x8c426f1c, 0x3c070001,
+0x8ce76d98, 0x3c040001, 0x24846c5c, 0xafa20010,
+0x97a2001e, 0x3c05000c, 0x34a50323, 0x3c010001,
+0xac206e20, 0xc002b3b, 0xafa20014, 0x10000007,
+0x0, 0x3c110002, 0x23e8821, 0x8e318ff0,
+0x3c027fff, 0x3442ffff, 0x2228824, 0x3c020001,
+0x8c426da8, 0x10400069, 0x0, 0x3c020001,
+0x8c426f1c, 0x10400002, 0x3c022000, 0x2228825,
+0x8fa8002c, 0x81140, 0x3c010002, 0x220821,
+0x8c229004, 0x10400003, 0x3c020020, 0x10000005,
+0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824,
+0x8fa8002c, 0x81140, 0x3c010002, 0x220821,
+0x8c22900c, 0x10400003, 0x3c020080, 0x1000004f,
+0x2228825, 0x3c02ff7f, 0x3442ffff, 0x1000004b,
+0x2228824, 0x8fa8002c, 0x82940, 0x3c030002,
+0x651821, 0x8c638ff8, 0x3c024000, 0x621024,
+0x14400008, 0x3c027fff, 0x3442ffff, 0x628824,
+0x3c010002, 0x250821, 0xac318ff0, 0x10000041,
+0x2201021, 0x3c020001, 0x8c426da8, 0x10400034,
+0x3c11c00c, 0x3c020001, 0x8c426e44, 0x3c04c00c,
+0x34842000, 0x3c030001, 0x8c636f1c, 0x2102b,
+0x21023, 0x441024, 0x10600003, 0x518825,
+0x3c022000, 0x2228825, 0x3c020002, 0x451021,
+0x8c429004, 0x10400003, 0x3c020020, 0x10000004,
+0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824,
+0x8fa8002c, 0x81140, 0x3c010002, 0x220821,
+0x8c22900c, 0x10400003, 0x3c020080, 0x10000004,
+0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824,
+0x3c020001, 0x8c426e30, 0x10400002, 0x3c020800,
+0x2228825, 0x3c020001, 0x8c426e34, 0x10400002,
+0x3c020400, 0x2228825, 0x3c020001, 0x8c426e38,
+0x10400006, 0x3c020100, 0x10000004, 0x2228825,
+0x3c027fff, 0x3442ffff, 0x628824, 0x8fa8002c,
+0x81140, 0x3c010002, 0x220821, 0xac318ff0,
+0x2201021, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
+0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
+0x3e00008, 0x27bd0050, 0x27bdffd0, 0xafb20028,
+0x809021, 0xafbf002c, 0xafb10024, 0xafb00020,
+0x8f840200, 0x3c100001, 0x8e106d98, 0x8f860220,
+0x24020002, 0x1202005c, 0x2e020003, 0x10400005,
+0x24020001, 0x1202000a, 0x121940, 0x1000010c,
+0x0, 0x24020004, 0x120200bf, 0x24020008,
+0x120200be, 0x128940, 0x10000105, 0x0,
+0x3c050002, 0xa32821, 0x8ca58ffc, 0x3c100002,
+0x2038021, 0x8e108ff4, 0x3c024000, 0xa21024,
+0x10400038, 0x3c020008, 0x2021024, 0x10400020,
+0x34840002, 0x3c020002, 0x431021, 0x8c429000,
+0x10400005, 0x34840020, 0x34840100, 0x3c020020,
+0x10000006, 0x2028025, 0x2402feff, 0x822024,
+0x3c02ffdf, 0x3442ffff, 0x2028024, 0x121140,
+0x3c010002, 0x220821, 0x8c229008, 0x10400005,
+0x3c020001, 0xc23025, 0x3c020080, 0x10000016,
+0x2028025, 0x3c02fffe, 0x3442ffff, 0xc23024,
+0x3c02ff7f, 0x3442ffff, 0x1000000f, 0x2028024,
+0x2402fedf, 0x822024, 0x3c02fffe, 0x3442ffff,
+0xc23024, 0x3c02ff5f, 0x3442ffff, 0x2028024,
+0x3c010002, 0x230821, 0xac209000, 0x3c010002,
+0x230821, 0xac209008, 0xaf840200, 0xaf860220,
+0x8f820220, 0x34420002, 0xaf820220, 0x1000000a,
+0x121140, 0x3c02bfff, 0x3442ffff, 0x8f830200,
+0x2028024, 0x2402fffd, 0x621824, 0xc003daf,
+0xaf830200, 0x121140, 0x3c010002, 0x220821,
+0x100000b7, 0xac308ff4, 0x3c020001, 0x8c426f1c,
+0x10400069, 0x24050004, 0x24040001, 0xc00457c,
+0x27a60018, 0x24040001, 0x24050005, 0xc00457c,
+0x27a6001a, 0x97a30018, 0x97a2001a, 0x3c040001,
+0x24846e48, 0x30630c00, 0x31a82, 0x30420c00,
+0x21282, 0xa7a2001a, 0x21080, 0x441021,
+0x431021, 0xa7a30018, 0x90480000, 0x24020001,
+0x3103ffff, 0x10620029, 0x28620002, 0x10400005,
+0x0, 0x10600009, 0x0, 0x1000003d,
+0x0, 0x10700013, 0x24020003, 0x1062002c,
+0x0, 0x10000037, 0x0, 0x8f820200,
+0x2403feff, 0x431024, 0xaf820200, 0x8f820220,
+0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220,
+0x3c010002, 0xac209004, 0x3c010002, 0x10000032,
+0xac20900c, 0x8f820200, 0x34420100, 0xaf820200,
+0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024,
+0xaf820220, 0x24020100, 0x3c010002, 0xac229004,
+0x3c010002, 0x10000024, 0xac20900c, 0x8f820200,
+0x2403feff, 0x431024, 0xaf820200, 0x8f820220,
+0x3c030001, 0x431025, 0xaf820220, 0x3c010002,
+0xac209004, 0x3c010002, 0x10000017, 0xac23900c,
+0x8f820200, 0x34420100, 0xaf820200, 0x8f820220,
+0x3c030001, 0x431025, 0xaf820220, 0x24020100,
+0x3c010002, 0xac229004, 0x3c010002, 0x1000000a,
+0xac23900c, 0x3c040001, 0x24846c80, 0x97a6001a,
+0x97a70018, 0x3c050001, 0x34a5ffff, 0xafa80010,
+0xc002b3b, 0xafa00014, 0x8f820200, 0x34420002,
+0x1000004b, 0xaf820200, 0x128940, 0x3c050002,
+0xb12821, 0x8ca58ff8, 0x3c100002, 0x2118021,
+0x8e108ff0, 0x3c024000, 0xa21024, 0x14400010,
+0x0, 0x3c020001, 0x8c426f1c, 0x14400005,
+0x3c02bfff, 0x8f820200, 0x34420002, 0xaf820200,
+0x3c02bfff, 0x3442ffff, 0xc003daf, 0x2028024,
+0x3c010002, 0x310821, 0x10000031, 0xac308ff0,
+0x3c020001, 0x8c426f1c, 0x10400005, 0x3c020020,
+0x3c020001, 0x8c426e44, 0x10400025, 0x3c020020,
+0xa21024, 0x10400007, 0x34840020, 0x24020100,
+0x3c010002, 0x310821, 0xac229004, 0x10000006,
+0x34840100, 0x3c010002, 0x310821, 0xac209004,
+0x2402feff, 0x822024, 0x3c020080, 0xa21024,
+0x10400007, 0x121940, 0x3c020001, 0x3c010002,
+0x230821, 0xac22900c, 0x10000008, 0xc23025,
+0x121140, 0x3c010002, 0x220821, 0xac20900c,
+0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200,
+0xaf860220, 0x8f820220, 0x34420002, 0xaf820220,
+0x121140, 0x3c010002, 0x220821, 0xac308ff0,
+0x8fbf002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
+0x3e00008, 0x27bd0030, 0x0, 0x1821,
+0x308400ff, 0x2405ffdf, 0x2406ffbf, 0x641007,
+0x30420001, 0x10400004, 0x0, 0x8f820044,
+0x10000003, 0x34420040, 0x8f820044, 0x461024,
+0xaf820044, 0x8f820044, 0x34420020, 0xaf820044,
+0x8f820044, 0x451024, 0xaf820044, 0x24630001,
+0x28620008, 0x5440ffee, 0x641007, 0x3e00008,
+0x0, 0x2c820008, 0x1040001b, 0x0,
+0x2405ffdf, 0x2406ffbf, 0x41880, 0x3c020001,
+0x24426e60, 0x621821, 0x24640004, 0x90620000,
+0x10400004, 0x0, 0x8f820044, 0x10000003,
+0x34420040, 0x8f820044, 0x461024, 0xaf820044,
+0x8f820044, 0x34420020, 0xaf820044, 0x8f820044,
+0x451024, 0xaf820044, 0x24630001, 0x64102b,
+0x1440ffee, 0x0, 0x3e00008, 0x0,
+0x0, 0x0, 0x0, 0x8f8400c4,
+0x8f8600e0, 0x8f8700e4, 0x2402fff8, 0xc22824,
+0x10e5001a, 0x27623ff8, 0x14e20002, 0x24e80008,
+0x27683000, 0x55050004, 0x8d0a0000, 0x30c20004,
+0x14400012, 0x805021, 0x8ce90000, 0x8f42013c,
+0x1494823, 0x49182b, 0x94eb0006, 0x10600002,
+0x25630050, 0x494821, 0x123182b, 0x50400003,
+0x8f4201fc, 0x3e00008, 0xe01021, 0xaf8800e8,
+0x24420001, 0xaf4201fc, 0xaf8800e4, 0x3e00008,
+0x1021, 0x3e00008, 0x0, 0x8f8300e4,
+0x27623ff8, 0x10620004, 0x24620008, 0xaf8200e8,
+0x3e00008, 0xaf8200e4, 0x27623000, 0xaf8200e8,
+0x3e00008, 0xaf8200e4, 0x3e00008, 0x0,
+0x0, 0x0, 0x0, 0x8f880120,
+0x27624fe0, 0x8f830128, 0x15020002, 0x25090020,
+0x27694800, 0x11230012, 0x8fa20010, 0xad040000,
+0xad050004, 0xad060008, 0xa507000e, 0x8fa30014,
+0xad020018, 0x8fa20018, 0xad03001c, 0x25030016,
+0xad020010, 0xad030014, 0xaf890120, 0x8f4300fc,
+0x24020001, 0x2463ffff, 0x3e00008, 0xaf4300fc,
+0x8f430324, 0x1021, 0x24630001, 0x3e00008,
+0xaf430324, 0x3e00008, 0x0, 0x8f880100,
+0x276247e0, 0x8f830108, 0x15020002, 0x25090020,
+0x27694000, 0x1123000f, 0x8fa20010, 0xad040000,
+0xad050004, 0xad060008, 0xa507000e, 0x8fa30014,
+0xad020018, 0x8fa20018, 0xad03001c, 0x25030016,
+0xad020010, 0xad030014, 0xaf890100, 0x3e00008,
+0x24020001, 0x8f430328, 0x1021, 0x24630001,
+0x3e00008, 0xaf430328, 0x3e00008, 0x0,
+0x0, 0x0, 0x0, 0x0 };
+static int tigon2FwRodata[/*(MAX_RODATA_LEN/4) + 1*/] = {
+0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f6677, 0x6d61696e, 0x2e632c76, 0x20312e31,
+0x2e322e34, 0x35203139, 0x39392f30, 0x312f3234,
+0x2030303a, 0x31303a35, 0x35207368, 0x75616e67,
+0x20457870, 0x20240000, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x6261644d, 0x656d537a,
+0x0, 0x68775665, 0x72000000, 0x62616448,
+0x77566572, 0x0, 0x2a2a4441, 0x574e5f41,
+0x0, 0x74785278, 0x4266537a, 0x0,
+0x62664174, 0x6e4d726b, 0x0, 0x7265645a,
+0x6f6e6531, 0x0, 0x70636943, 0x6f6e6600,
+0x67656e43, 0x6f6e6600, 0x2a646d61, 0x5244666c,
+0x0, 0x2a50414e, 0x49432a00, 0x2e2e2f2e,
+0x2e2f2e2e, 0x2f2e2e2f, 0x2e2e2f73, 0x72632f6e,
+0x69632f66, 0x77322f63, 0x6f6d6d6f, 0x6e2f6677,
+0x6d61696e, 0x2e630000, 0x72636246, 0x6c616773,
+0x0, 0x62616452, 0x78526362, 0x0,
+0x676c6f62, 0x466c6773, 0x0, 0x2b5f6469,
+0x73705f6c, 0x6f6f7000, 0x2b65765f, 0x68616e64,
+0x6c657200, 0x63616e74, 0x31446d61, 0x0,
+0x2b715f64, 0x6d615f74, 0x6f5f6e69, 0x635f636b,
+0x73756d00, 0x2b685f73, 0x656e645f, 0x64617461,
+0x5f726561, 0x64795f63, 0x6b73756d, 0x0,
+0x2b685f64, 0x6d615f72, 0x645f6173, 0x73697374,
+0x5f636b73, 0x756d0000, 0x74436b73, 0x6d4f6e00,
+0x2b715f64, 0x6d615f74, 0x6f5f6e69, 0x63000000,
+0x2b685f73, 0x656e645f, 0x64617461, 0x5f726561,
+0x64790000, 0x2b685f64, 0x6d615f72, 0x645f6173,
+0x73697374, 0x0, 0x74436b73, 0x6d4f6666,
+0x0, 0x2b685f73, 0x656e645f, 0x62645f72,
+0x65616479, 0x0, 0x68737453, 0x52696e67,
+0x0, 0x62616453, 0x52696e67, 0x0,
+0x6e696353, 0x52696e67, 0x0, 0x77446d61,
+0x416c6c41, 0x0, 0x2b715f64, 0x6d615f74,
+0x6f5f686f, 0x73745f63, 0x6b73756d, 0x0,
+0x2b685f6d, 0x61635f72, 0x785f636f, 0x6d705f63,
+0x6b73756d, 0x0, 0x2b685f64, 0x6d615f77,
+0x725f6173, 0x73697374, 0x5f636b73, 0x756d0000,
+0x72436b73, 0x6d4f6e00, 0x2b715f64, 0x6d615f74,
+0x6f5f686f, 0x73740000, 0x2b685f6d, 0x61635f72,
+0x785f636f, 0x6d700000, 0x2b685f64, 0x6d615f77,
+0x725f6173, 0x73697374, 0x0, 0x72436b73,
+0x6d4f6666, 0x0, 0x2b685f72, 0x6563765f,
+0x62645f72, 0x65616479, 0x0, 0x2b685f72,
+0x6563765f, 0x6a756d62, 0x6f5f6264, 0x5f726561,
+0x64790000, 0x2b685f72, 0x6563765f, 0x6d696e69,
+0x5f62645f, 0x72656164, 0x79000000, 0x2b6d685f,
+0x636f6d6d, 0x616e6400, 0x2b685f74, 0x696d6572,
+0x0, 0x2b685f64, 0x6f5f7570, 0x64617465,
+0x5f74785f, 0x636f6e73, 0x0, 0x2b685f64,
+0x6f5f7570, 0x64617465, 0x5f72785f, 0x70726f64,
+0x0, 0x2b636b73, 0x756d3136, 0x0,
+0x2b706565, 0x6b5f6d61, 0x635f7278, 0x5f776100,
+0x2b706565, 0x6b5f6d61, 0x635f7278, 0x0,
+0x2b646571, 0x5f6d6163, 0x5f727800, 0x2b685f6d,
+0x61635f72, 0x785f6174, 0x746e0000, 0x62616452,
+0x6574537a, 0x0, 0x72784264, 0x4266537a,
+0x0, 0x2b6e756c, 0x6c5f6861, 0x6e646c65,
+0x72000000, 0x66774f70, 0x4661696c, 0x0,
+0x2b685f75, 0x70646174, 0x655f6c65, 0x64340000,
+0x2b685f75, 0x70646174, 0x655f6c65, 0x64360000,
+0x2b685f75, 0x70646174, 0x655f6c65, 0x64320000,
+0x696e7453, 0x74617465, 0x0, 0x2a2a696e,
+0x69744370, 0x0, 0x23736372, 0x65616d00,
+0x69537461, 0x636b4572, 0x0, 0x70726f62,
+0x654d656d, 0x0, 0x2a2a4441, 0x574e5f42,
+0x0, 0x2b73775f, 0x646d615f, 0x61737369,
+0x73745f70, 0x6c75735f, 0x74696d65, 0x72000000,
+0x2b267072, 0x656c6f61, 0x645f7772, 0x5f646573,
+0x63720000, 0x2b267072, 0x656c6f61, 0x645f7264,
+0x5f646573, 0x63720000, 0x2b685f68, 0x665f7469,
+0x6d657200, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f7469, 0x6d65722e, 0x632c7620, 0x312e312e,
+0x322e3335, 0x20313939, 0x392f3031, 0x2f323720,
+0x31393a30, 0x393a3530, 0x20686179, 0x65732045,
+0x78702024, 0x0, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x542d446d, 0x61526432,
+0x0, 0x542d446d, 0x61526431, 0x0,
+0x542d446d, 0x61526442, 0x0, 0x542d446d,
+0x61577232, 0x0, 0x542d446d, 0x61577231,
+0x0, 0x542d446d, 0x61577242, 0x0,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f636f, 0x6d6d616e, 0x642e632c, 0x7620312e,
+0x312e322e, 0x32382031, 0x3939392f, 0x30312f32,
+0x30203139, 0x3a34393a, 0x34392073, 0x6875616e,
+0x67204578, 0x70202400, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x3f48636d, 0x644d6278,
+0x0, 0x3f636d64, 0x48737453, 0x0,
+0x3f636d64, 0x4d634d64, 0x0, 0x3f636d64,
+0x50726f6d, 0x0, 0x3f636d64, 0x4c696e6b,
+0x0, 0x3f636d64, 0x45727200, 0x86ac,
+0x8e5c, 0x8e5c, 0x8de4, 0x8b78,
+0x8e30, 0x8e5c, 0x8790, 0x8800,
+0x8990, 0x8a68, 0x8a34, 0x8e5c,
+0x8870, 0x8b24, 0x8e5c, 0x8b34,
+0x87b4, 0x8824, 0x0, 0x0,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f6d63, 0x6173742e, 0x632c7620, 0x312e312e,
+0x322e3820, 0x31393938, 0x2f31322f, 0x30382030,
+0x323a3336, 0x3a333620, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x6164644d, 0x63447570,
+0x0, 0x6164644d, 0x6346756c, 0x0,
+0x64656c4d, 0x634e6f45, 0x0, 0x0,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f646d, 0x612e632c, 0x7620312e, 0x312e322e,
+0x32342031, 0x3939382f, 0x31322f32, 0x31203030,
+0x3a33333a, 0x30392073, 0x6875616e, 0x67204578,
+0x70202400, 0x65767452, 0x6e674600, 0x51657674,
+0x46000000, 0x51657674, 0x505f4600, 0x4d657674,
+0x526e6746, 0x0, 0x4d516576, 0x74460000,
+0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46,
+0x0, 0x5173436f, 0x6e734600, 0x51725072,
+0x6f644600, 0x7377446d, 0x614f6666, 0x0,
+0x31446d61, 0x4f6e0000, 0x7377446d, 0x614f6e00,
+0x2372446d, 0x6141544e, 0x0, 0x72446d61,
+0x41544e30, 0x0, 0x72446d61, 0x41544e31,
+0x0, 0x72446d61, 0x34476200, 0x2a50414e,
+0x49432a00, 0x2e2e2f2e, 0x2e2f2e2e, 0x2f2e2e2f,
+0x2e2e2f73, 0x72632f6e, 0x69632f66, 0x77322f63,
+0x6f6d6d6f, 0x6e2f646d, 0x612e6300, 0x2377446d,
+0x6141544e, 0x0, 0x77446d61, 0x41544e30,
+0x0, 0x77446d61, 0x41544e31, 0x0,
+0x77446d61, 0x34476200, 0x0, 0x0,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f7472, 0x6163652e, 0x632c7620, 0x312e312e,
+0x322e3520, 0x31393938, 0x2f30392f, 0x33302031,
+0x383a3530, 0x3a323820, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x0, 0x0,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f6461, 0x74612e63, 0x2c762031, 0x2e312e32,
+0x2e313220, 0x31393939, 0x2f30312f, 0x32302031,
+0x393a3439, 0x3a353120, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x46575f56, 0x45525349,
+0x4f4e3a20, 0x23312046, 0x72692041, 0x70722037,
+0x2031373a, 0x35373a35, 0x32205044, 0x54203230,
+0x30300000, 0x46575f43, 0x4f4d5049, 0x4c455f54,
+0x494d453a, 0x2031373a, 0x35373a35, 0x32000000,
+0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064,
+0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049,
+0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465,
+0x0, 0x46575f43, 0x4f4d5049, 0x4c455f44,
+0x4f4d4149, 0x4e3a2065, 0x6e672e61, 0x6374656f,
+0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049,
+0x4c45523a, 0x20676363, 0x20766572, 0x73696f6e,
+0x20322e37, 0x2e320000, 0x0, 0x12041100,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f6d65, 0x6d2e632c, 0x7620312e, 0x312e322e,
+0x35203139, 0x39382f30, 0x392f3330, 0x2031383a,
+0x35303a30, 0x38207368, 0x75616e67, 0x20457870,
+0x20240000, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f7365, 0x6e642e63, 0x2c762031, 0x2e312e32,
+0x2e343420, 0x31393938, 0x2f31322f, 0x32312030,
+0x303a3333, 0x3a313820, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x69736e74, 0x54637055,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f7265, 0x63762e63, 0x2c762031, 0x2e312e32,
+0x2e353320, 0x31393939, 0x2f30312f, 0x31362030,
+0x323a3535, 0x3a343320, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x724d6163, 0x43686b30,
+0x0, 0x72784672, 0x6d324c67, 0x0,
+0x72784e6f, 0x53744264, 0x0, 0x72784e6f,
+0x4d694264, 0x0, 0x72784e6f, 0x4a6d4264,
+0x0, 0x7278436b, 0x446d6146, 0x0,
+0x72785144, 0x6d457846, 0x0, 0x72785144,
+0x6d614600, 0x72785144, 0x4c426446, 0x0,
+0x72785144, 0x6d426446, 0x0, 0x72784372,
+0x63506164, 0x0, 0x72536d51, 0x446d6146,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f6d61, 0x632e632c, 0x7620312e, 0x312e322e,
+0x32322031, 0x3939382f, 0x31322f30, 0x38203032,
+0x3a33363a, 0x33302073, 0x6875616e, 0x67204578,
+0x70202400, 0x65767452, 0x6e674600, 0x51657674,
+0x46000000, 0x51657674, 0x505f4600, 0x4d657674,
+0x526e6746, 0x0, 0x4d516576, 0x74460000,
+0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46,
+0x0, 0x5173436f, 0x6e734600, 0x51725072,
+0x6f644600, 0x6d616354, 0x68726573, 0x0,
+0x23744d61, 0x6341544e, 0x0, 0x23724d61,
+0x6341544e, 0x0, 0x72656d41, 0x73737274,
+0x0, 0x6c696e6b, 0x444f574e, 0x0,
+0x6c696e6b, 0x55500000, 0x0, 0x0,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f636b, 0x73756d2e, 0x632c7620, 0x312e312e,
+0x322e3920, 0x31393939, 0x2f30312f, 0x31342030,
+0x303a3033, 0x3a343820, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x0, 0x0,
+0x0, 0x50726f62, 0x65506879, 0x0,
+0x6c6e6b41, 0x53535254, 0x0, 0x109a4,
+0x10a1c, 0x10a50, 0x10a7c, 0x11050,
+0x10aa8, 0x10b10, 0x111fc, 0x10dc0,
+0x10c68, 0x10c80, 0x10cc4, 0x10cec,
+0x10d0c, 0x10d34, 0x111fc, 0x10dc0,
+0x10df8, 0x10e10, 0x10e40, 0x10e68,
+0x10e88, 0x10eb0, 0x0, 0x10fdc,
+0x11008, 0x1102c, 0x111fc, 0x11050,
+0x11078, 0x11108, 0x0, 0x0,
+0x0, 0x1186c, 0x1193c, 0x11a14,
+0x11ae4, 0x11b40, 0x11c1c, 0x11c44,
+0x11d20, 0x11d48, 0x11ef0, 0x11f18,
+0x120c0, 0x122b8, 0x1254c, 0x12460,
+0x1254c, 0x12578, 0x120e8, 0x12290,
+0x7273745f, 0x676d6969, 0x0, 0x12608,
+0x12640, 0x12728, 0x13374, 0x133b4,
+0x133cc, 0x7365746c, 0x6f6f7000, 0x0,
+0x0, 0x13bbc, 0x13bfc, 0x13c8c,
+0x13cd0, 0x13d34, 0x13dc0, 0x13df4,
+0x13e7c, 0x13f14, 0x13fe4, 0x14024,
+0x140a8, 0x140cc, 0x141dc, 0x646f4261,
+0x73655067, 0x0, 0x0, 0x0,
+0x0, 0x73746d61, 0x634c4e4b, 0x0,
+0x6765746d, 0x636c6e6b, 0x0, 0x14ed8,
+0x14ed8, 0x14b8c, 0x14bd8, 0x14c24,
+0x14ed8, 0x7365746d, 0x61636163, 0x74000000,
+0x0, 0x0 };
+static int tigon2FwData[/*(MAX_DATA_LEN/4) + 1*/] = {
+0x1,
+0x1, 0x1, 0xc001fc, 0x3ffc,
+0xc00000, 0x416c7465, 0x6f6e2041, 0x63654e49,
+0x43205600, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x416c7465,
+0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242,
+0x0, 0x0, 0x0, 0x1ffffc,
+0x1fff7c, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x60cf00,
+0x60, 0xcf000000, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x3, 0x0,
+0x1, 0x0, 0x0, 0x0,
+0x1, 0x0, 0x1, 0x0,
+0x0, 0x0, 0x0, 0x1,
+0x1, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x1000000, 0x21000000,
+0x12000140, 0x0, 0x0, 0x20000000,
+0x120000a0, 0x0, 0x12000060, 0x12000180,
+0x120001e0, 0x0, 0x0, 0x0,
+0x1, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x2,
+0x0, 0x0, 0x30001, 0x1,
+0x30201, 0x0, 0x0, 0x1010101,
+0x1010100, 0x10100, 0x1010001, 0x10001,
+0x1000101, 0x101, 0x0, 0x0 };
diff --git a/sys/src/9/pc/etherif.h b/sys/src/9/pc/etherif.h
new file mode 100755
index 000000000..94c16267d
--- /dev/null
+++ b/sys/src/9/pc/etherif.h
@@ -0,0 +1,39 @@
+enum {
+ MaxEther = 48,
+ Ntypes = 8,
+};
+
+typedef struct Ether Ether;
+struct Ether {
+ ISAConf; /* hardware info */
+
+ int ctlrno;
+ int tbdf; /* type+busno+devno+funcno */
+ int minmtu;
+ int maxmtu;
+ uchar ea[Eaddrlen];
+
+ void (*attach)(Ether*); /* filled in by reset routine */
+ void (*detach)(Ether*);
+ void (*transmit)(Ether*);
+ void (*interrupt)(Ureg*, void*);
+ long (*ifstat)(Ether*, void*, long, ulong);
+ long (*ctl)(Ether*, void*, long); /* custom ctl messages */
+ void (*power)(Ether*, int); /* power on/off */
+ void (*shutdown)(Ether*); /* shutdown hardware before reboot */
+ void *ctlr;
+
+ Queue* oq;
+
+ Netif;
+};
+
+extern Block* etheriq(Ether*, Block*, int);
+extern void addethercard(char*, int(*)(Ether*));
+extern ulong ethercrc(uchar*, int);
+extern int parseether(uchar*, char*);
+
+#define NEXT(x, l) (((x)+1)%(l))
+#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
diff --git a/sys/src/9/pc/etherigbe.c b/sys/src/9/pc/etherigbe.c
new file mode 100755
index 000000000..bf08020d5
--- /dev/null
+++ b/sys/src/9/pc/etherigbe.c
@@ -0,0 +1,2042 @@
+/*
+ * Intel 8254[340]NN Gigabit Ethernet PCI Controllers
+ * as found on the Intel PRO/1000 series of adapters:
+ * 82543GC Intel PRO/1000 T
+ * 82544EI Intel PRO/1000 XT
+ * 82540EM Intel PRO/1000 MT
+ * 82541[GP]I
+ * 82547GI
+ * 82546GB
+ * 82546EB
+ * To Do:
+ * finish autonegotiation code;
+ * integrate fiber stuff back in (this ONLY handles
+ * the CAT5 cards at the moment);
+ * add checksum-offload;
+ * add tuning control via ctl file;
+ * this driver is little-endian specific.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+enum {
+ i82542 = (0x1000<<16)|0x8086,
+ i82543gc = (0x1004<<16)|0x8086,
+ i82544ei = (0x1008<<16)|0x8086,
+ i82544eif = (0x1009<<16)|0x8086,
+ i82544gc = (0x100d<<16)|0x8086,
+ i82540em = (0x100E<<16)|0x8086,
+ i82540eplp = (0x101E<<16)|0x8086,
+ i82545em = (0x100F<<16)|0x8086,
+ i82545gmc = (0x1026<<16)|0x8086,
+ i82547ei = (0x1019<<16)|0x8086,
+ i82547gi = (0x1075<<16)|0x8086,
+ i82541ei = (0x1013<<16)|0x8086,
+ i82541gi = (0x1076<<16)|0x8086,
+ i82541gi2 = (0x1077<<16)|0x8086,
+ i82541pi = (0x107c<<16)|0x8086,
+ i82546gb = (0x1079<<16)|0x8086,
+ i82546eb = (0x1010<<16)|0x8086,
+};
+
+enum {
+ Ctrl = 0x00000000, /* Device Control */
+ Ctrldup = 0x00000004, /* Device Control Duplicate */
+ Status = 0x00000008, /* Device Status */
+ Eecd = 0x00000010, /* EEPROM/Flash Control/Data */
+ Ctrlext = 0x00000018, /* Extended Device Control */
+ Mdic = 0x00000020, /* MDI Control */
+ Fcal = 0x00000028, /* Flow Control Address Low */
+ Fcah = 0x0000002C, /* Flow Control Address High */
+ Fct = 0x00000030, /* Flow Control Type */
+ Icr = 0x000000C0, /* Interrupt Cause Read */
+ Ics = 0x000000C8, /* Interrupt Cause Set */
+ Ims = 0x000000D0, /* Interrupt Mask Set/Read */
+ Imc = 0x000000D8, /* Interrupt mask Clear */
+ Rctl = 0x00000100, /* Receive Control */
+ Fcttv = 0x00000170, /* Flow Control Transmit Timer Value */
+ Txcw = 0x00000178, /* Transmit Configuration Word */
+ Rxcw = 0x00000180, /* Receive Configuration Word */
+ /* on the oldest cards (8254[23]), the Mta register is at 0x200 */
+ Tctl = 0x00000400, /* Transmit Control */
+ Tipg = 0x00000410, /* Transmit IPG */
+ Tbt = 0x00000448, /* Transmit Burst Timer */
+ Ait = 0x00000458, /* Adaptive IFS Throttle */
+ Fcrtl = 0x00002160, /* Flow Control RX Threshold Low */
+ Fcrth = 0x00002168, /* Flow Control Rx Threshold High */
+ Rdfh = 0x00002410, /* Receive data fifo head */
+ Rdft = 0x00002418, /* Receive data fifo tail */
+ Rdfhs = 0x00002420, /* Receive data fifo head saved */
+ Rdfts = 0x00002428, /* Receive data fifo tail saved */
+ Rdfpc = 0x00002430, /* Receive data fifo packet count */
+ Rdbal = 0x00002800, /* Rd Base Address Low */
+ Rdbah = 0x00002804, /* Rd Base Address High */
+ Rdlen = 0x00002808, /* Receive Descriptor Length */
+ Rdh = 0x00002810, /* Receive Descriptor Head */
+ Rdt = 0x00002818, /* Receive Descriptor Tail */
+ Rdtr = 0x00002820, /* Receive Descriptor Timer Ring */
+ Rxdctl = 0x00002828, /* Receive Descriptor Control */
+ Radv = 0x0000282C, /* Receive Interrupt Absolute Delay Timer */
+ Txdmac = 0x00003000, /* Transfer DMA Control */
+ Ett = 0x00003008, /* Early Transmit Control */
+ Tdfh = 0x00003410, /* Transmit data fifo head */
+ Tdft = 0x00003418, /* Transmit data fifo tail */
+ Tdfhs = 0x00003420, /* Transmit data Fifo Head saved */
+ Tdfts = 0x00003428, /* Transmit data fifo tail saved */
+ Tdfpc = 0x00003430, /* Trasnmit data Fifo packet count */
+ Tdbal = 0x00003800, /* Td Base Address Low */
+ Tdbah = 0x00003804, /* Td Base Address High */
+ Tdlen = 0x00003808, /* Transmit Descriptor Length */
+ Tdh = 0x00003810, /* Transmit Descriptor Head */
+ Tdt = 0x00003818, /* Transmit Descriptor Tail */
+ Tidv = 0x00003820, /* Transmit Interrupt Delay Value */
+ Txdctl = 0x00003828, /* Transmit Descriptor Control */
+ Tadv = 0x0000382C, /* Transmit Interrupt Absolute Delay Timer */
+
+ Statistics = 0x00004000, /* Start of Statistics Area */
+ Gorcl = 0x88/4, /* Good Octets Received Count */
+ Gotcl = 0x90/4, /* Good Octets Transmitted Count */
+ Torl = 0xC0/4, /* Total Octets Received */
+ Totl = 0xC8/4, /* Total Octets Transmitted */
+ Nstatistics = 64,
+
+ Rxcsum = 0x00005000, /* Receive Checksum Control */
+ Mta = 0x00005200, /* Multicast Table Array */
+ Ral = 0x00005400, /* Receive Address Low */
+ Rah = 0x00005404, /* Receive Address High */
+ Manc = 0x00005820, /* Management Control */
+};
+
+enum { /* Ctrl */
+ Bem = 0x00000002, /* Big Endian Mode */
+ Prior = 0x00000004, /* Priority on the PCI bus */
+ Lrst = 0x00000008, /* Link Reset */
+ Asde = 0x00000020, /* Auto-Speed Detection Enable */
+ Slu = 0x00000040, /* Set Link Up */
+ Ilos = 0x00000080, /* Invert Loss of Signal (LOS) */
+ SspeedMASK = 0x00000300, /* Speed Selection */
+ SspeedSHIFT = 8,
+ Sspeed10 = 0x00000000, /* 10Mb/s */
+ Sspeed100 = 0x00000100, /* 100Mb/s */
+ Sspeed1000 = 0x00000200, /* 1000Mb/s */
+ Frcspd = 0x00000800, /* Force Speed */
+ Frcdplx = 0x00001000, /* Force Duplex */
+ SwdpinsloMASK = 0x003C0000, /* Software Defined Pins - lo nibble */
+ SwdpinsloSHIFT = 18,
+ SwdpioloMASK = 0x03C00000, /* Software Defined Pins - I or O */
+ SwdpioloSHIFT = 22,
+ Devrst = 0x04000000, /* Device Reset */
+ Rfce = 0x08000000, /* Receive Flow Control Enable */
+ Tfce = 0x10000000, /* Transmit Flow Control Enable */
+ Vme = 0x40000000, /* VLAN Mode Enable */
+};
+
+/*
+ * can't find Tckok nor Rbcok in any Intel docs,
+ * but even 82543gc docs define Lanid.
+ */
+enum { /* Status */
+ Lu = 0x00000002, /* Link Up */
+ Lanid = 0x0000000C, /* mask for Lan ID. (function id) */
+// Tckok = 0x00000004, /* Transmit clock is running */
+// Rbcok = 0x00000008, /* Receive clock is running */
+ Txoff = 0x00000010, /* Transmission Paused */
+ Tbimode = 0x00000020, /* TBI Mode Indication */
+ LspeedMASK = 0x000000C0, /* Link Speed Setting */
+ LspeedSHIFT = 6,
+ Lspeed10 = 0x00000000, /* 10Mb/s */
+ Lspeed100 = 0x00000040, /* 100Mb/s */
+ Lspeed1000 = 0x00000080, /* 1000Mb/s */
+ Mtxckok = 0x00000400, /* MTX clock is running */
+ Pci66 = 0x00000800, /* PCI Bus speed indication */
+ Bus64 = 0x00001000, /* PCI Bus width indication */
+ Pcixmode = 0x00002000, /* PCI-X mode */
+ PcixspeedMASK = 0x0000C000, /* PCI-X bus speed */
+ PcixspeedSHIFT = 14,
+ Pcix66 = 0x00000000, /* 50-66MHz */
+ Pcix100 = 0x00004000, /* 66-100MHz */
+ Pcix133 = 0x00008000, /* 100-133MHz */
+};
+
+enum { /* Ctrl and Status */
+ Fd = 0x00000001, /* Full-Duplex */
+ AsdvMASK = 0x00000300,
+ AsdvSHIFT = 8,
+ Asdv10 = 0x00000000, /* 10Mb/s */
+ Asdv100 = 0x00000100, /* 100Mb/s */
+ Asdv1000 = 0x00000200, /* 1000Mb/s */
+};
+
+enum { /* Eecd */
+ Sk = 0x00000001, /* Clock input to the EEPROM */
+ Cs = 0x00000002, /* Chip Select */
+ Di = 0x00000004, /* Data Input to the EEPROM */
+ Do = 0x00000008, /* Data Output from the EEPROM */
+ Areq = 0x00000040, /* EEPROM Access Request */
+ Agnt = 0x00000080, /* EEPROM Access Grant */
+ Eepresent = 0x00000100, /* EEPROM Present */
+ Eesz256 = 0x00000200, /* EEPROM is 256 words not 64 */
+ Eeszaddr = 0x00000400, /* EEPROM size for 8254[17] */
+ Spi = 0x00002000, /* EEPROM is SPI not Microwire */
+};
+
+enum { /* Ctrlext */
+ Gpien = 0x0000000F, /* General Purpose Interrupt Enables */
+ SwdpinshiMASK = 0x000000F0, /* Software Defined Pins - hi nibble */
+ SwdpinshiSHIFT = 4,
+ SwdpiohiMASK = 0x00000F00, /* Software Defined Pins - I or O */
+ SwdpiohiSHIFT = 8,
+ Asdchk = 0x00001000, /* ASD Check */
+ Eerst = 0x00002000, /* EEPROM Reset */
+ Ips = 0x00004000, /* Invert Power State */
+ Spdbyps = 0x00008000, /* Speed Select Bypass */
+};
+
+enum { /* EEPROM content offsets */
+ Ea = 0x00, /* Ethernet Address */
+ Cf = 0x03, /* Compatibility Field */
+ Pba = 0x08, /* Printed Board Assembly number */
+ Icw1 = 0x0A, /* Initialization Control Word 1 */
+ Sid = 0x0B, /* Subsystem ID */
+ Svid = 0x0C, /* Subsystem Vendor ID */
+ Did = 0x0D, /* Device ID */
+ Vid = 0x0E, /* Vendor ID */
+ Icw2 = 0x0F, /* Initialization Control Word 2 */
+};
+
+enum { /* Mdic */
+ MDIdMASK = 0x0000FFFF, /* Data */
+ MDIdSHIFT = 0,
+ MDIrMASK = 0x001F0000, /* PHY Register Address */
+ MDIrSHIFT = 16,
+ MDIpMASK = 0x03E00000, /* PHY Address */
+ MDIpSHIFT = 21,
+ MDIwop = 0x04000000, /* Write Operation */
+ MDIrop = 0x08000000, /* Read Operation */
+ MDIready = 0x10000000, /* End of Transaction */
+ MDIie = 0x20000000, /* Interrupt Enable */
+ MDIe = 0x40000000, /* Error */
+};
+
+enum { /* Icr, Ics, Ims, Imc */
+ Txdw = 0x00000001, /* Transmit Descriptor Written Back */
+ Txqe = 0x00000002, /* Transmit Queue Empty */
+ Lsc = 0x00000004, /* Link Status Change */
+ Rxseq = 0x00000008, /* Receive Sequence Error */
+ Rxdmt0 = 0x00000010, /* Rd Minimum Threshold Reached */
+ Rxo = 0x00000040, /* Receiver Overrun */
+ Rxt0 = 0x00000080, /* Receiver Timer Interrupt */
+ Mdac = 0x00000200, /* MDIO Access Completed */
+ Rxcfg = 0x00000400, /* Receiving /C/ ordered sets */
+ Gpi0 = 0x00000800, /* General Purpose Interrupts */
+ Gpi1 = 0x00001000,
+ Gpi2 = 0x00002000,
+ Gpi3 = 0x00004000,
+};
+
+/*
+ * The Mdic register isn't implemented on the 82543GC,
+ * the software defined pins are used instead.
+ * These definitions work for the Intel PRO/1000 T Server Adapter.
+ * The direction pin bits are read from the EEPROM.
+ */
+enum {
+ Mdd = ((1<<2)<<SwdpinsloSHIFT), /* data */
+ Mddo = ((1<<2)<<SwdpioloSHIFT), /* pin direction */
+ Mdc = ((1<<3)<<SwdpinsloSHIFT), /* clock */
+ Mdco = ((1<<3)<<SwdpioloSHIFT), /* pin direction */
+ Mdr = ((1<<0)<<SwdpinshiSHIFT), /* reset */
+ Mdro = ((1<<0)<<SwdpiohiSHIFT), /* pin direction */
+};
+
+enum { /* Txcw */
+ TxcwFd = 0x00000020, /* Full Duplex */
+ TxcwHd = 0x00000040, /* Half Duplex */
+ TxcwPauseMASK = 0x00000180, /* Pause */
+ TxcwPauseSHIFT = 7,
+ TxcwPs = (1<<TxcwPauseSHIFT), /* Pause Supported */
+ TxcwAs = (2<<TxcwPauseSHIFT), /* Asymmetric FC desired */
+ TxcwRfiMASK = 0x00003000, /* Remote Fault Indication */
+ TxcwRfiSHIFT = 12,
+ TxcwNpr = 0x00008000, /* Next Page Request */
+ TxcwConfig = 0x40000000, /* Transmit COnfig Control */
+ TxcwAne = 0x80000000, /* Auto-Negotiation Enable */
+};
+
+enum { /* Rxcw */
+ Rxword = 0x0000FFFF, /* Data from auto-negotiation process */
+ Rxnocarrier = 0x04000000, /* Carrier Sense indication */
+ Rxinvalid = 0x08000000, /* Invalid Symbol during configuration */
+ Rxchange = 0x10000000, /* Change to the Rxword indication */
+ Rxconfig = 0x20000000, /* /C/ order set reception indication */
+ Rxsync = 0x40000000, /* Lost bit synchronization indication */
+ Anc = 0x80000000, /* Auto Negotiation Complete */
+};
+
+enum { /* Rctl */
+ Rrst = 0x00000001, /* Receiver Software Reset */
+ Ren = 0x00000002, /* Receiver Enable */
+ Sbp = 0x00000004, /* Store Bad Packets */
+ Upe = 0x00000008, /* Unicast Promiscuous Enable */
+ Mpe = 0x00000010, /* Multicast Promiscuous Enable */
+ Lpe = 0x00000020, /* Long Packet Reception Enable */
+ LbmMASK = 0x000000C0, /* Loopback Mode */
+ LbmOFF = 0x00000000, /* No Loopback */
+ LbmTBI = 0x00000040, /* TBI Loopback */
+ LbmMII = 0x00000080, /* GMII/MII Loopback */
+ LbmXCVR = 0x000000C0, /* Transceiver Loopback */
+ RdtmsMASK = 0x00000300, /* Rd Minimum Threshold Size */
+ RdtmsHALF = 0x00000000, /* Threshold is 1/2 Rdlen */
+ RdtmsQUARTER = 0x00000100, /* Threshold is 1/4 Rdlen */
+ RdtmsEIGHTH = 0x00000200, /* Threshold is 1/8 Rdlen */
+ MoMASK = 0x00003000, /* Multicast Offset */
+ Mo47b36 = 0x00000000, /* bits [47:36] of received address */
+ Mo46b35 = 0x00001000, /* bits [46:35] of received address */
+ Mo45b34 = 0x00002000, /* bits [45:34] of received address */
+ Mo43b32 = 0x00003000, /* bits [43:32] of received address */
+ Bam = 0x00008000, /* Broadcast Accept Mode */
+ BsizeMASK = 0x00030000, /* Receive Buffer Size */
+ Bsize2048 = 0x00000000, /* Bsex = 0 */
+ Bsize1024 = 0x00010000, /* Bsex = 0 */
+ Bsize512 = 0x00020000, /* Bsex = 0 */
+ Bsize256 = 0x00030000, /* Bsex = 0 */
+ Bsize16384 = 0x00010000, /* Bsex = 1 */
+ Vfe = 0x00040000, /* VLAN Filter Enable */
+ Cfien = 0x00080000, /* Canonical Form Indicator Enable */
+ Cfi = 0x00100000, /* Canonical Form Indicator value */
+ Dpf = 0x00400000, /* Discard Pause Frames */
+ Pmcf = 0x00800000, /* Pass MAC Control Frames */
+ Bsex = 0x02000000, /* Buffer Size Extension */
+ Secrc = 0x04000000, /* Strip CRC from incoming packet */
+};
+
+enum { /* Tctl */
+ Trst = 0x00000001, /* Transmitter Software Reset */
+ Ten = 0x00000002, /* Transmit Enable */
+ Psp = 0x00000008, /* Pad Short Packets */
+ CtMASK = 0x00000FF0, /* Collision Threshold */
+ CtSHIFT = 4,
+ ColdMASK = 0x003FF000, /* Collision Distance */
+ ColdSHIFT = 12,
+ Swxoff = 0x00400000, /* Sofware XOFF Transmission */
+ Pbe = 0x00800000, /* Packet Burst Enable */
+ Rtlc = 0x01000000, /* Re-transmit on Late Collision */
+ Nrtu = 0x02000000, /* No Re-transmit on Underrrun */
+};
+
+enum { /* [RT]xdctl */
+ PthreshMASK = 0x0000003F, /* Prefetch Threshold */
+ PthreshSHIFT = 0,
+ HthreshMASK = 0x00003F00, /* Host Threshold */
+ HthreshSHIFT = 8,
+ WthreshMASK = 0x003F0000, /* Writeback Threshold */
+ WthreshSHIFT = 16,
+ Gran = 0x01000000, /* Granularity */
+ LthreshMASK = 0xFE000000, /* Low Threshold */
+ LthreshSHIFT = 25,
+};
+
+enum { /* Rxcsum */
+ PcssMASK = 0x000000FF, /* Packet Checksum Start */
+ PcssSHIFT = 0,
+ Ipofl = 0x00000100, /* IP Checksum Off-load Enable */
+ Tuofl = 0x00000200, /* TCP/UDP Checksum Off-load Enable */
+};
+
+enum { /* Manc */
+ Arpen = 0x00002000, /* Enable ARP Request Filtering */
+};
+
+enum { /* Receive Delay Timer Ring */
+ DelayMASK = 0x0000FFFF, /* delay timer in 1.024nS increments */
+ DelaySHIFT = 0,
+ Fpd = 0x80000000, /* Flush partial Descriptor Block */
+};
+
+typedef struct Rd { /* Receive Descriptor */
+ uint addr[2];
+ ushort length;
+ ushort checksum;
+ uchar status;
+ uchar errors;
+ ushort special;
+} Rd;
+
+enum { /* Rd status */
+ Rdd = 0x01, /* Descriptor Done */
+ Reop = 0x02, /* End of Packet */
+ Ixsm = 0x04, /* Ignore Checksum Indication */
+ Vp = 0x08, /* Packet is 802.1Q (matched VET) */
+ Tcpcs = 0x20, /* TCP Checksum Calculated on Packet */
+ Ipcs = 0x40, /* IP Checksum Calculated on Packet */
+ Pif = 0x80, /* Passed in-exact filter */
+};
+
+enum { /* Rd errors */
+ Ce = 0x01, /* CRC Error or Alignment Error */
+ Se = 0x02, /* Symbol Error */
+ Seq = 0x04, /* Sequence Error */
+ Cxe = 0x10, /* Carrier Extension Error */
+ Tcpe = 0x20, /* TCP/UDP Checksum Error */
+ Ipe = 0x40, /* IP Checksum Error */
+ Rxe = 0x80, /* RX Data Error */
+};
+
+typedef struct Td Td;
+struct Td { /* Transmit Descriptor */
+ union {
+ uint addr[2]; /* Data */
+ struct { /* Context */
+ uchar ipcss;
+ uchar ipcso;
+ ushort ipcse;
+ uchar tucss;
+ uchar tucso;
+ ushort tucse;
+ };
+ };
+ uint control;
+ uint status;
+};
+
+enum { /* Td control */
+ LenMASK = 0x000FFFFF, /* Data/Packet Length Field */
+ LenSHIFT = 0,
+ DtypeCD = 0x00000000, /* Data Type 'Context Descriptor' */
+ DtypeDD = 0x00100000, /* Data Type 'Data Descriptor' */
+ PtypeTCP = 0x01000000, /* TCP/UDP Packet Type (CD) */
+ Teop = 0x01000000, /* End of Packet (DD) */
+ PtypeIP = 0x02000000, /* IP Packet Type (CD) */
+ Ifcs = 0x02000000, /* Insert FCS (DD) */
+ Tse = 0x04000000, /* TCP Segmentation Enable */
+ Rs = 0x08000000, /* Report Status */
+ Rps = 0x10000000, /* Report Status Sent */
+ Dext = 0x20000000, /* Descriptor Extension */
+ Vle = 0x40000000, /* VLAN Packet Enable */
+ Ide = 0x80000000, /* Interrupt Delay Enable */
+};
+
+enum { /* Td status */
+ Tdd = 0x00000001, /* Descriptor Done */
+ Ec = 0x00000002, /* Excess Collisions */
+ Lc = 0x00000004, /* Late Collision */
+ Tu = 0x00000008, /* Transmit Underrun */
+ Iixsm = 0x00000100, /* Insert IP Checksum */
+ Itxsm = 0x00000200, /* Insert TCP/UDP Checksum */
+ HdrlenMASK = 0x0000FF00, /* Header Length (Tse) */
+ HdrlenSHIFT = 8,
+ VlanMASK = 0x0FFF0000, /* VLAN Identifier */
+ VlanSHIFT = 16,
+ Tcfi = 0x10000000, /* Canonical Form Indicator */
+ PriMASK = 0xE0000000, /* User Priority */
+ PriSHIFT = 29,
+ MssMASK = 0xFFFF0000, /* Maximum Segment Size (Tse) */
+ MssSHIFT = 16,
+};
+
+enum {
+ Nrd = 256, /* multiple of 8 */
+ Ntd = 64, /* multiple of 8 */
+ Nrb = 1024, /* private receive buffers per Ctlr */
+ Rbsz = 2048,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ Ether* edev;
+ int active;
+ int started;
+ int id;
+ int cls;
+ ushort eeprom[0x40];
+
+ QLock alock; /* attach */
+ void* alloc; /* receive/transmit descriptors */
+ int nrd;
+ int ntd;
+ int nrb; /* how many this Ctlr has in the pool */
+
+ int* nic;
+ Lock imlock;
+ int im; /* interrupt mask */
+
+ Mii* mii;
+ Rendez lrendez;
+ int lim;
+
+ int link;
+
+ QLock slock;
+ uint statistics[Nstatistics];
+ uint lsleep;
+ uint lintr;
+ uint rsleep;
+ uint rintr;
+ uint txdw;
+ uint tintr;
+ uint ixsm;
+ uint ipcs;
+ uint tcpcs;
+
+ uchar ra[Eaddrlen]; /* receive address */
+ ulong mta[128]; /* multicast table array */
+
+ Rendez rrendez;
+ int rim;
+ int rdfree;
+ Rd* rdba; /* receive descriptor base address */
+ Block** rb; /* receive buffers */
+ int rdh; /* receive descriptor head */
+ int rdt; /* receive descriptor tail */
+ int rdtr; /* receive delay timer ring value */
+
+ Lock tlock;
+ int tbusy;
+ int tdfree;
+ Td* tdba; /* transmit descriptor base address */
+ Block** tb; /* transmit buffers */
+ int tdh; /* transmit descriptor head */
+ int tdt; /* transmit descriptor tail */
+
+ int txcw;
+ int fcrtl;
+ int fcrth;
+} Ctlr;
+
+#define csr32r(c, r) (*((c)->nic+((r)/4)))
+#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
+
+static Ctlr* igbectlrhead;
+static Ctlr* igbectlrtail;
+
+static Lock igberblock; /* free receive Blocks */
+static Block* igberbpool; /* receive Blocks for all igbe controllers */
+
+static char* statistics[Nstatistics] = {
+ "CRC Error",
+ "Alignment Error",
+ "Symbol Error",
+ "RX Error",
+ "Missed Packets",
+ "Single Collision",
+ "Excessive Collisions",
+ "Multiple Collision",
+ "Late Collisions",
+ nil,
+ "Collision",
+ "Transmit Underrun",
+ "Defer",
+ "Transmit - No CRS",
+ "Sequence Error",
+ "Carrier Extension Error",
+ "Receive Error Length",
+ nil,
+ "XON Received",
+ "XON Transmitted",
+ "XOFF Received",
+ "XOFF Transmitted",
+ "FC Received Unsupported",
+ "Packets Received (64 Bytes)",
+ "Packets Received (65-127 Bytes)",
+ "Packets Received (128-255 Bytes)",
+ "Packets Received (256-511 Bytes)",
+ "Packets Received (512-1023 Bytes)",
+ "Packets Received (1024-1522 Bytes)",
+ "Good Packets Received",
+ "Broadcast Packets Received",
+ "Multicast Packets Received",
+ "Good Packets Transmitted",
+ nil,
+ "Good Octets Received",
+ nil,
+ "Good Octets Transmitted",
+ nil,
+ nil,
+ nil,
+ "Receive No Buffers",
+ "Receive Undersize",
+ "Receive Fragment",
+ "Receive Oversize",
+ "Receive Jabber",
+ nil,
+ nil,
+ nil,
+ "Total Octets Received",
+ nil,
+ "Total Octets Transmitted",
+ nil,
+ "Total Packets Received",
+ "Total Packets Transmitted",
+ "Packets Transmitted (64 Bytes)",
+ "Packets Transmitted (65-127 Bytes)",
+ "Packets Transmitted (128-255 Bytes)",
+ "Packets Transmitted (256-511 Bytes)",
+ "Packets Transmitted (512-1023 Bytes)",
+ "Packets Transmitted (1024-1522 Bytes)",
+ "Multicast Packets Transmitted",
+ "Broadcast Packets Transmitted",
+ "TCP Segmentation Context Transmitted",
+ "TCP Segmentation Context Fail",
+};
+
+static long
+igbeifstat(Ether* edev, void* a, long n, ulong offset)
+{
+ Ctlr *ctlr;
+ char *p, *s;
+ int i, l, r;
+ uvlong tuvl, ruvl;
+
+ ctlr = edev->ctlr;
+ qlock(&ctlr->slock);
+ p = malloc(READSTR);
+ l = 0;
+ for(i = 0; i < Nstatistics; i++){
+ r = csr32r(ctlr, Statistics+i*4);
+ if((s = statistics[i]) == nil)
+ continue;
+ switch(i){
+ case Gorcl:
+ case Gotcl:
+ case Torl:
+ case Totl:
+ ruvl = r;
+ ruvl += ((uvlong)csr32r(ctlr, Statistics+(i+1)*4))<<32;
+ tuvl = ruvl;
+ tuvl += ctlr->statistics[i];
+ tuvl += ((uvlong)ctlr->statistics[i+1])<<32;
+ if(tuvl == 0)
+ continue;
+ ctlr->statistics[i] = tuvl;
+ ctlr->statistics[i+1] = tuvl>>32;
+ l += snprint(p+l, READSTR-l, "%s: %llud %llud\n",
+ s, tuvl, ruvl);
+ i++;
+ break;
+
+ default:
+ ctlr->statistics[i] += r;
+ if(ctlr->statistics[i] == 0)
+ continue;
+ l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
+ s, ctlr->statistics[i], r);
+ break;
+ }
+ }
+
+ l += snprint(p+l, READSTR-l, "lintr: %ud %ud\n",
+ ctlr->lintr, ctlr->lsleep);
+ l += snprint(p+l, READSTR-l, "rintr: %ud %ud\n",
+ ctlr->rintr, ctlr->rsleep);
+ l += snprint(p+l, READSTR-l, "tintr: %ud %ud\n",
+ ctlr->tintr, ctlr->txdw);
+ l += snprint(p+l, READSTR-l, "ixcs: %ud %ud %ud\n",
+ ctlr->ixsm, ctlr->ipcs, ctlr->tcpcs);
+ l += snprint(p+l, READSTR-l, "rdtr: %ud\n", ctlr->rdtr);
+ l += snprint(p+l, READSTR-l, "Ctrlext: %08x\n", csr32r(ctlr, Ctrlext));
+
+ l += snprint(p+l, READSTR-l, "eeprom:");
+ for(i = 0; i < 0x40; i++){
+ if(i && ((i & 0x07) == 0))
+ l += snprint(p+l, READSTR-l, "\n ");
+ l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
+ }
+ l += snprint(p+l, READSTR-l, "\n");
+
+ if(ctlr->mii != nil && ctlr->mii->curphy != nil){
+ l += snprint(p+l, READSTR-l, "phy: ");
+ for(i = 0; i < NMiiPhyr; i++){
+ 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);
+ }
+ snprint(p+l, READSTR-l, "\n");
+ }
+ n = readstr(offset, a, n, p);
+ free(p);
+ qunlock(&ctlr->slock);
+
+ return n;
+}
+
+enum {
+ CMrdtr,
+};
+
+static Cmdtab igbectlmsg[] = {
+ CMrdtr, "rdtr", 2,
+};
+
+static long
+igbectl(Ether* edev, void* buf, long n)
+{
+ int v;
+ char *p;
+ Ctlr *ctlr;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+
+ if((ctlr = edev->ctlr) == nil)
+ error(Enonexist);
+
+ cb = parsecmd(buf, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+
+ ct = lookupcmd(cb, igbectlmsg, nelem(igbectlmsg));
+ switch(ct->index){
+ case CMrdtr:
+ v = strtol(cb->f[1], &p, 0);
+ if(v < 0 || p == cb->f[1] || v > 0xFFFF)
+ error(Ebadarg);
+ ctlr->rdtr = v;;
+ csr32w(ctlr, Rdtr, Fpd|v);
+ break;
+ }
+ free(cb);
+ poperror();
+
+ return n;
+}
+
+static void
+igbepromiscuous(void* arg, int on)
+{
+ int rctl;
+ Ctlr *ctlr;
+ Ether *edev;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ rctl = csr32r(ctlr, Rctl);
+ rctl &= ~MoMASK;
+ rctl |= Mo47b36;
+ if(on)
+ rctl |= Upe|Mpe;
+ else
+ rctl &= ~(Upe|Mpe);
+ csr32w(ctlr, Rctl, rctl|Mpe); /* temporarily keep Mpe on */
+}
+
+static void
+igbemulticast(void* arg, uchar* addr, int add)
+{
+ int bit, x;
+ Ctlr *ctlr;
+ Ether *edev;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ x = addr[5]>>1;
+ bit = ((addr[5] & 1)<<4)|(addr[4]>>4);
+ /*
+ * multiple ether addresses can hash to the same filter bit,
+ * so it's never safe to clear a filter bit.
+ * if we want to clear filter bits, we need to keep track of
+ * all the multicast addresses in use, clear all the filter bits,
+ * then set the ones corresponding to in-use addresses.
+ */
+ if(add)
+ ctlr->mta[x] |= 1<<bit;
+// else
+// ctlr->mta[x] &= ~(1<<bit);
+
+ csr32w(ctlr, Mta+x*4, ctlr->mta[x]);
+}
+
+static Block*
+igberballoc(void)
+{
+ Block *bp;
+
+ ilock(&igberblock);
+ if((bp = igberbpool) != nil){
+ igberbpool = bp->next;
+ bp->next = nil;
+ _xinc(&bp->ref); /* prevent bp from being freed */
+ }
+ iunlock(&igberblock);
+
+ return bp;
+}
+
+static void
+igberbfree(Block* bp)
+{
+ bp->rp = bp->lim - Rbsz;
+ bp->wp = bp->rp;
+ bp->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
+
+ ilock(&igberblock);
+ bp->next = igberbpool;
+ igberbpool = bp;
+ iunlock(&igberblock);
+}
+
+static void
+igbeim(Ctlr* ctlr, int im)
+{
+ ilock(&ctlr->imlock);
+ ctlr->im |= im;
+ csr32w(ctlr, Ims, ctlr->im);
+ iunlock(&ctlr->imlock);
+}
+
+static int
+igbelim(void* ctlr)
+{
+ return ((Ctlr*)ctlr)->lim != 0;
+}
+
+static void
+igbelproc(void* arg)
+{
+ Ctlr *ctlr;
+ Ether *edev;
+ MiiPhy *phy;
+ int ctrl, r;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+ for(;;){
+ if(ctlr->mii == nil || ctlr->mii->curphy == nil)
+ continue;
+
+ /*
+ * To do:
+ * logic to manage status change,
+ * this is incomplete but should work
+ * one time to set up the hardware.
+ *
+ * MiiPhy.speed, etc. should be in Mii.
+ */
+ if(miistatus(ctlr->mii) < 0)
+ //continue;
+ goto enable;
+
+ phy = ctlr->mii->curphy;
+ ctrl = csr32r(ctlr, Ctrl);
+
+ switch(ctlr->id){
+ case i82543gc:
+ case i82544ei:
+ case i82544eif:
+ default:
+ if(!(ctrl & Asde)){
+ ctrl &= ~(SspeedMASK|Ilos|Fd);
+ ctrl |= Frcdplx|Frcspd;
+ if(phy->speed == 1000)
+ ctrl |= Sspeed1000;
+ else if(phy->speed == 100)
+ ctrl |= Sspeed100;
+ if(phy->fd)
+ ctrl |= Fd;
+ }
+ break;
+
+ case i82540em:
+ case i82540eplp:
+ case i82547gi:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ break;
+ }
+
+ /*
+ * Collision Distance.
+ */
+ r = csr32r(ctlr, Tctl);
+ r &= ~ColdMASK;
+ if(phy->fd)
+ r |= 64<<ColdSHIFT;
+ else
+ r |= 512<<ColdSHIFT;
+ csr32w(ctlr, Tctl, r);
+
+ /*
+ * Flow control.
+ */
+ if(phy->rfc)
+ ctrl |= Rfce;
+ if(phy->tfc)
+ ctrl |= Tfce;
+ csr32w(ctlr, Ctrl, ctrl);
+
+enable:
+ ctlr->lim = 0;
+ igbeim(ctlr, Lsc);
+
+ ctlr->lsleep++;
+ sleep(&ctlr->lrendez, igbelim, ctlr);
+ }
+}
+
+static void
+igbetxinit(Ctlr* ctlr)
+{
+ int i, r;
+ Block *bp;
+
+ csr32w(ctlr, Tctl, (0x0F<<CtSHIFT)|Psp|(66<<ColdSHIFT));
+ switch(ctlr->id){
+ default:
+ r = 6;
+ break;
+ case i82543gc:
+ case i82544ei:
+ case i82544eif:
+ case i82544gc:
+ case i82540em:
+ case i82540eplp:
+ case i82541ei:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82545em:
+ case i82545gmc:
+ case i82546gb:
+ case i82546eb:
+ case i82547ei:
+ case i82547gi:
+ r = 8;
+ break;
+ }
+ csr32w(ctlr, Tipg, (6<<20)|(8<<10)|r);
+ csr32w(ctlr, Ait, 0);
+ csr32w(ctlr, Txdmac, 0);
+
+ csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
+ csr32w(ctlr, Tdbah, 0);
+ csr32w(ctlr, Tdlen, ctlr->ntd*sizeof(Td));
+ ctlr->tdh = PREV(0, ctlr->ntd);
+ csr32w(ctlr, Tdh, 0);
+ ctlr->tdt = 0;
+ csr32w(ctlr, Tdt, 0);
+
+ for(i = 0; i < ctlr->ntd; i++){
+ if((bp = ctlr->tb[i]) != nil){
+ ctlr->tb[i] = nil;
+ freeb(bp);
+ }
+ memset(&ctlr->tdba[i], 0, sizeof(Td));
+ }
+ ctlr->tdfree = ctlr->ntd;
+
+ csr32w(ctlr, Tidv, 128);
+ r = (4<<WthreshSHIFT)|(4<<HthreshSHIFT)|(8<<PthreshSHIFT);
+
+ switch(ctlr->id){
+ default:
+ break;
+ case i82540em:
+ case i82540eplp:
+ case i82547gi:
+ case i82545em:
+ case i82545gmc:
+ case i82546gb:
+ case i82546eb:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ r = csr32r(ctlr, Txdctl);
+ r &= ~WthreshMASK;
+ r |= Gran|(4<<WthreshSHIFT);
+
+ csr32w(ctlr, Tadv, 64);
+ break;
+ }
+
+ csr32w(ctlr, Txdctl, r);
+
+ r = csr32r(ctlr, Tctl);
+ r |= Ten;
+ csr32w(ctlr, Tctl, r);
+}
+
+static void
+igbetransmit(Ether* edev)
+{
+ Td *td;
+ Block *bp;
+ Ctlr *ctlr;
+ int tdh, tdt;
+
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->tlock);
+
+ /*
+ * Free any completed packets
+ */
+ tdh = ctlr->tdh;
+ while(NEXT(tdh, ctlr->ntd) != csr32r(ctlr, Tdh)){
+ if((bp = ctlr->tb[tdh]) != nil){
+ ctlr->tb[tdh] = nil;
+ freeb(bp);
+ }
+ memset(&ctlr->tdba[tdh], 0, sizeof(Td));
+ tdh = NEXT(tdh, ctlr->ntd);
+ }
+ ctlr->tdh = tdh;
+
+ /*
+ * Try to fill the ring back up.
+ */
+ tdt = ctlr->tdt;
+ while(NEXT(tdt, ctlr->ntd) != tdh){
+ if((bp = qget(edev->oq)) == nil)
+ break;
+ td = &ctlr->tdba[tdt];
+ td->addr[0] = PCIWADDR(bp->rp);
+ td->control = ((BLEN(bp) & LenMASK)<<LenSHIFT);
+ td->control |= Dext|Ifcs|Teop|DtypeDD;
+ ctlr->tb[tdt] = bp;
+ tdt = NEXT(tdt, ctlr->ntd);
+ if(NEXT(tdt, ctlr->ntd) == tdh){
+ td->control |= Rs;
+ ctlr->txdw++;
+ ctlr->tdt = tdt;
+ csr32w(ctlr, Tdt, tdt);
+ igbeim(ctlr, Txdw);
+ break;
+ }
+ ctlr->tdt = tdt;
+ csr32w(ctlr, Tdt, tdt);
+ }
+
+ iunlock(&ctlr->tlock);
+}
+
+static void
+igbereplenish(Ctlr* ctlr)
+{
+ Rd *rd;
+ int rdt;
+ Block *bp;
+
+ rdt = ctlr->rdt;
+ while(NEXT(rdt, ctlr->nrd) != ctlr->rdh){
+ rd = &ctlr->rdba[rdt];
+ if(ctlr->rb[rdt] == nil){
+ bp = igberballoc();
+ if(bp == nil){
+ iprint("#l%d: igbereplenish: no available buffers\n",
+ ctlr->edev->ctlrno);
+ break;
+ }
+ ctlr->rb[rdt] = bp;
+ rd->addr[0] = PCIWADDR(bp->rp);
+ rd->addr[1] = 0;
+ }
+ coherence();
+ rd->status = 0;
+ rdt = NEXT(rdt, ctlr->nrd);
+ ctlr->rdfree++;
+ }
+ ctlr->rdt = rdt;
+ csr32w(ctlr, Rdt, rdt);
+}
+
+static void
+igberxinit(Ctlr* ctlr)
+{
+ int i;
+ Block *bp;
+
+ /* temporarily keep Mpe on */
+ csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF|Mpe);
+
+ csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
+ csr32w(ctlr, Rdbah, 0);
+ csr32w(ctlr, Rdlen, ctlr->nrd*sizeof(Rd));
+ ctlr->rdh = 0;
+ csr32w(ctlr, Rdh, 0);
+ ctlr->rdt = 0;
+ csr32w(ctlr, Rdt, 0);
+ ctlr->rdtr = 0;
+ csr32w(ctlr, Rdtr, Fpd|0);
+
+ for(i = 0; i < ctlr->nrd; i++){
+ if((bp = ctlr->rb[i]) != nil){
+ ctlr->rb[i] = nil;
+ freeb(bp);
+ }
+ }
+ igbereplenish(ctlr);
+
+ switch(ctlr->id){
+ case i82540em:
+ case i82540eplp:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82545em:
+ case i82545gmc:
+ case i82546gb:
+ case i82546eb:
+ case i82547gi:
+ csr32w(ctlr, Radv, 64);
+ break;
+ }
+ csr32w(ctlr, Rxdctl, (8<<WthreshSHIFT)|(8<<HthreshSHIFT)|4);
+
+ /*
+ * Enable checksum offload.
+ */
+ csr32w(ctlr, Rxcsum, Tuofl|Ipofl|(ETHERHDRSIZE<<PcssSHIFT));
+}
+
+static int
+igberim(void* ctlr)
+{
+ return ((Ctlr*)ctlr)->rim != 0;
+}
+
+static void
+igberproc(void* arg)
+{
+ Rd *rd;
+ Block *bp;
+ Ctlr *ctlr;
+ int r, rdh;
+ Ether *edev;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ igberxinit(ctlr);
+ r = csr32r(ctlr, Rctl);
+ r |= Ren;
+ csr32w(ctlr, Rctl, r);
+
+ for(;;){
+ ctlr->rim = 0;
+ igbeim(ctlr, Rxt0|Rxo|Rxdmt0|Rxseq);
+ ctlr->rsleep++;
+ sleep(&ctlr->rrendez, igberim, ctlr);
+
+ rdh = ctlr->rdh;
+ for(;;){
+ rd = &ctlr->rdba[rdh];
+
+ if(!(rd->status & Rdd))
+ break;
+
+ /*
+ * Accept eop packets with no errors.
+ * With no errors and the Ixsm bit set,
+ * the descriptor status Tpcs and Ipcs bits give
+ * an indication of whether the checksums were
+ * calculated and valid.
+ */
+ if((rd->status & Reop) && rd->errors == 0){
+ bp = ctlr->rb[rdh];
+ ctlr->rb[rdh] = nil;
+ bp->wp += rd->length;
+ bp->next = nil;
+ if(!(rd->status & Ixsm)){
+ ctlr->ixsm++;
+ if(rd->status & Ipcs){
+ /*
+ * IP checksum calculated
+ * (and valid as errors == 0).
+ */
+ ctlr->ipcs++;
+ bp->flag |= Bipck;
+ }
+ if(rd->status & Tcpcs){
+ /*
+ * TCP/UDP checksum calculated
+ * (and valid as errors == 0).
+ */
+ ctlr->tcpcs++;
+ bp->flag |= Btcpck|Budpck;
+ }
+ bp->checksum = rd->checksum;
+ bp->flag |= Bpktck;
+ }
+ etheriq(edev, bp, 1);
+ }
+ else if(ctlr->rb[rdh] != nil){
+ freeb(ctlr->rb[rdh]);
+ ctlr->rb[rdh] = nil;
+ }
+
+ memset(rd, 0, sizeof(Rd));
+ coherence();
+ ctlr->rdfree--;
+ rdh = NEXT(rdh, ctlr->nrd);
+ }
+ ctlr->rdh = rdh;
+
+ if(ctlr->rdfree < ctlr->nrd/2 || (ctlr->rim & Rxdmt0))
+ igbereplenish(ctlr);
+ }
+}
+
+static void
+igbeattach(Ether* edev)
+{
+ Block *bp;
+ Ctlr *ctlr;
+ char name[KNAMELEN];
+
+ ctlr = edev->ctlr;
+ ctlr->edev = edev; /* point back to Ether* */
+ qlock(&ctlr->alock);
+ if(ctlr->alloc != nil){ /* already allocated? */
+ qunlock(&ctlr->alock);
+ return;
+ }
+
+ ctlr->nrd = ROUND(Nrd, 8);
+ ctlr->ntd = ROUND(Ntd, 8);
+ ctlr->alloc = malloc(ctlr->nrd*sizeof(Rd)+ctlr->ntd*sizeof(Td) + 127);
+ if(ctlr->alloc == nil){
+ print("igbe: can't allocate ctlr->alloc\n");
+ qunlock(&ctlr->alock);
+ return;
+ }
+ ctlr->rdba = (Rd*)ROUNDUP((uintptr)ctlr->alloc, 128);
+ ctlr->tdba = (Td*)(ctlr->rdba+ctlr->nrd);
+
+ ctlr->rb = malloc(ctlr->nrd*sizeof(Block*));
+ ctlr->tb = malloc(ctlr->ntd*sizeof(Block*));
+ if (ctlr->rb == nil || ctlr->tb == nil) {
+ print("igbe: can't allocate ctlr->rb or ctlr->tb\n");
+ qunlock(&ctlr->alock);
+ return;
+ }
+
+ if(waserror()){
+ while(ctlr->nrb > 0){
+ bp = igberballoc();
+ bp->free = nil;
+ freeb(bp);
+ ctlr->nrb--;
+ }
+ free(ctlr->tb);
+ ctlr->tb = nil;
+ free(ctlr->rb);
+ ctlr->rb = nil;
+ free(ctlr->alloc);
+ ctlr->alloc = nil;
+ qunlock(&ctlr->alock);
+ nexterror();
+ }
+
+ for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){
+ if((bp = allocb(Rbsz)) == nil)
+ break;
+ bp->free = igberbfree;
+ freeb(bp);
+ }
+
+ snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno);
+ kproc(name, igbelproc, edev);
+
+ snprint(name, KNAMELEN, "#l%drproc", edev->ctlrno);
+ kproc(name, igberproc, edev);
+
+ igbetxinit(ctlr);
+
+ qunlock(&ctlr->alock);
+ poperror();
+}
+
+static void
+igbeinterrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Ether *edev;
+ int icr, im, txdw;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->imlock);
+ csr32w(ctlr, Imc, ~0);
+ im = ctlr->im;
+ txdw = 0;
+
+ while((icr = csr32r(ctlr, Icr) & ctlr->im) != 0){
+ if(icr & Lsc){
+ im &= ~Lsc;
+ ctlr->lim = icr & Lsc;
+ wakeup(&ctlr->lrendez);
+ ctlr->lintr++;
+ }
+ if(icr & (Rxt0|Rxo|Rxdmt0|Rxseq)){
+ im &= ~(Rxt0|Rxo|Rxdmt0|Rxseq);
+ ctlr->rim = icr & (Rxt0|Rxo|Rxdmt0|Rxseq);
+ wakeup(&ctlr->rrendez);
+ ctlr->rintr++;
+ }
+ if(icr & Txdw){
+ im &= ~Txdw;
+ txdw++;
+ ctlr->tintr++;
+ }
+ }
+
+ ctlr->im = im;
+ csr32w(ctlr, Ims, im);
+ iunlock(&ctlr->imlock);
+
+ if(txdw)
+ igbetransmit(edev);
+}
+
+static int
+i82543mdior(Ctlr* ctlr, int n)
+{
+ int ctrl, data, i, r;
+
+ /*
+ * Read n bits from the Management Data I/O Interface.
+ */
+ ctrl = csr32r(ctlr, Ctrl);
+ r = (ctrl & ~Mddo)|Mdco;
+ data = 0;
+ for(i = n-1; i >= 0; i--){
+ if(csr32r(ctlr, Ctrl) & Mdd)
+ data |= (1<<i);
+ csr32w(ctlr, Ctrl, Mdc|r);
+ csr32w(ctlr, Ctrl, r);
+ }
+ csr32w(ctlr, Ctrl, ctrl);
+
+ return data;
+}
+
+static int
+i82543mdiow(Ctlr* ctlr, int bits, int n)
+{
+ int ctrl, i, r;
+
+ /*
+ * Write n bits to the Management Data I/O Interface.
+ */
+ ctrl = csr32r(ctlr, Ctrl);
+ r = Mdco|Mddo|ctrl;
+ for(i = n-1; i >= 0; i--){
+ if(bits & (1<<i))
+ r |= Mdd;
+ else
+ r &= ~Mdd;
+ csr32w(ctlr, Ctrl, Mdc|r);
+ csr32w(ctlr, Ctrl, r);
+ }
+ csr32w(ctlr, Ctrl, ctrl);
+
+ return 0;
+}
+
+static int
+i82543miimir(Mii* mii, int pa, int ra)
+{
+ int data;
+ Ctlr *ctlr;
+
+ ctlr = mii->ctlr;
+
+ /*
+ * MII Management Interface Read.
+ *
+ * Preamble;
+ * ST+OP+PHYAD+REGAD;
+ * TA + 16 data bits.
+ */
+ i82543mdiow(ctlr, 0xFFFFFFFF, 32);
+ i82543mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
+ data = i82543mdior(ctlr, 18);
+
+ if(data & 0x10000)
+ return -1;
+
+ return data & 0xFFFF;
+}
+
+static int
+i82543miimiw(Mii* mii, int pa, int ra, int data)
+{
+ Ctlr *ctlr;
+
+ ctlr = mii->ctlr;
+
+ /*
+ * MII Management Interface Write.
+ *
+ * Preamble;
+ * ST+OP+PHYAD+REGAD+TA + 16 data bits;
+ * Z.
+ */
+ i82543mdiow(ctlr, 0xFFFFFFFF, 32);
+ data &= 0xFFFF;
+ data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
+ i82543mdiow(ctlr, data, 32);
+
+ return 0;
+}
+
+static int
+igbemiimir(Mii* mii, int pa, int ra)
+{
+ Ctlr *ctlr;
+ int mdic, timo;
+
+ ctlr = mii->ctlr;
+
+ csr32w(ctlr, Mdic, MDIrop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT));
+ mdic = 0;
+ for(timo = 64; timo; timo--){
+ mdic = csr32r(ctlr, Mdic);
+ if(mdic & (MDIe|MDIready))
+ break;
+ microdelay(1);
+ }
+
+ if((mdic & (MDIe|MDIready)) == MDIready)
+ return mdic & 0xFFFF;
+ return -1;
+}
+
+static int
+igbemiimiw(Mii* mii, int pa, int ra, int data)
+{
+ Ctlr *ctlr;
+ int mdic, timo;
+
+ ctlr = mii->ctlr;
+
+ data &= MDIdMASK;
+ csr32w(ctlr, Mdic, MDIwop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT)|data);
+ mdic = 0;
+ for(timo = 64; timo; timo--){
+ mdic = csr32r(ctlr, Mdic);
+ if(mdic & (MDIe|MDIready))
+ break;
+ microdelay(1);
+ }
+ if((mdic & (MDIe|MDIready)) == MDIready)
+ return 0;
+ return -1;
+}
+
+static int
+igbemii(Ctlr* ctlr)
+{
+ MiiPhy *phy;
+ int ctrl, p, r;
+
+ r = csr32r(ctlr, Status);
+ if(r & Tbimode)
+ return -1;
+ if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+ return -1;
+ ctlr->mii->ctlr = ctlr;
+
+ ctrl = csr32r(ctlr, Ctrl);
+ ctrl |= Slu;
+
+ switch(ctlr->id){
+ case i82543gc:
+ ctrl |= Frcdplx|Frcspd;
+ csr32w(ctlr, Ctrl, ctrl);
+
+ /*
+ * The reset pin direction (Mdro) should already
+ * be set from the EEPROM load.
+ * If it's not set this configuration is unexpected
+ * so bail.
+ */
+ r = csr32r(ctlr, Ctrlext);
+ if(!(r & Mdro))
+ return -1;
+ csr32w(ctlr, Ctrlext, r);
+ delay(20);
+ r = csr32r(ctlr, Ctrlext);
+ r &= ~Mdr;
+ csr32w(ctlr, Ctrlext, r);
+ delay(20);
+ r = csr32r(ctlr, Ctrlext);
+ r |= Mdr;
+ csr32w(ctlr, Ctrlext, r);
+ delay(20);
+
+ ctlr->mii->mir = i82543miimir;
+ ctlr->mii->miw = i82543miimiw;
+ break;
+ case i82544ei:
+ case i82544eif:
+ case i82544gc:
+ case i82540em:
+ case i82540eplp:
+ case i82547ei:
+ case i82547gi:
+ case i82541ei:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82545em:
+ case i82545gmc:
+ case i82546gb:
+ case i82546eb:
+ ctrl &= ~(Frcdplx|Frcspd);
+ csr32w(ctlr, Ctrl, ctrl);
+ ctlr->mii->mir = igbemiimir;
+ ctlr->mii->miw = igbemiimiw;
+ break;
+ default:
+ free(ctlr->mii);
+ ctlr->mii = nil;
+ return -1;
+ }
+
+ if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
+ free(ctlr->mii);
+ ctlr->mii = nil;
+ return -1;
+ }
+ USED(phy);
+ // print("oui %X phyno %d\n", phy->oui, phy->phyno);
+
+ /*
+ * 8254X-specific PHY registers not in 802.3:
+ * 0x10 PHY specific control
+ * 0x14 extended PHY specific control
+ * Set appropriate values then reset the PHY to have
+ * changes noted.
+ */
+ switch(ctlr->id){
+ case i82547gi:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82545em:
+ case i82545gmc:
+ case i82546gb:
+ case i82546eb:
+ break;
+ default:
+ r = miimir(ctlr->mii, 16);
+ r |= 0x0800; /* assert CRS on Tx */
+ r |= 0x0060; /* auto-crossover all speeds */
+ r |= 0x0002; /* polarity reversal enabled */
+ miimiw(ctlr->mii, 16, r);
+
+ r = miimir(ctlr->mii, 20);
+ r |= 0x0070; /* +25MHz clock */
+ r &= ~0x0F00;
+ r |= 0x0100; /* 1x downshift */
+ miimiw(ctlr->mii, 20, r);
+
+ miireset(ctlr->mii);
+ p = 0;
+ if(ctlr->txcw & TxcwPs)
+ p |= AnaP;
+ if(ctlr->txcw & TxcwAs)
+ p |= AnaAP;
+ miiane(ctlr->mii, ~0, p, ~0);
+ break;
+ }
+ return 0;
+}
+
+static int
+at93c46io(Ctlr* ctlr, char* op, int data)
+{
+ char *lp, *p;
+ int i, loop, eecd, r;
+
+ eecd = csr32r(ctlr, Eecd);
+
+ r = 0;
+ loop = -1;
+ lp = nil;
+ for(p = op; *p != '\0'; p++){
+ switch(*p){
+ default:
+ return -1;
+ case ' ':
+ continue;
+ case ':': /* start of loop */
+ loop = strtol(p+1, &lp, 0)-1;
+ lp--;
+ if(p == lp)
+ loop = 7;
+ p = lp;
+ continue;
+ case ';': /* end of loop */
+ if(lp == nil)
+ return -1;
+ loop--;
+ if(loop >= 0)
+ p = lp;
+ else
+ lp = nil;
+ continue;
+ case 'C': /* assert clock */
+ eecd |= Sk;
+ break;
+ case 'c': /* deassert clock */
+ eecd &= ~Sk;
+ break;
+ case 'D': /* next bit in 'data' byte */
+ if(loop < 0)
+ return -1;
+ if(data & (1<<loop))
+ eecd |= Di;
+ else
+ eecd &= ~Di;
+ break;
+ case 'O': /* collect data output */
+ i = (csr32r(ctlr, Eecd) & Do) != 0;
+ if(loop >= 0)
+ r |= (i<<loop);
+ else
+ r = i;
+ continue;
+ case 'I': /* assert data input */
+ eecd |= Di;
+ break;
+ case 'i': /* deassert data input */
+ eecd &= ~Di;
+ break;
+ case 'S': /* enable chip select */
+ eecd |= Cs;
+ break;
+ case 's': /* disable chip select */
+ eecd &= ~Cs;
+ break;
+ }
+ csr32w(ctlr, Eecd, eecd);
+ microdelay(50);
+ }
+ if(loop >= 0)
+ return -1;
+ return r;
+}
+
+static int
+at93c46r(Ctlr* ctlr)
+{
+ ushort sum;
+ char rop[20];
+ int addr, areq, bits, data, eecd, i;
+
+ eecd = csr32r(ctlr, Eecd);
+ if(eecd & Spi){
+ print("igbe: SPI EEPROM access not implemented\n");
+ return 0;
+ }
+ if(eecd & (Eeszaddr|Eesz256))
+ bits = 8;
+ else
+ bits = 6;
+
+ sum = 0;
+
+ switch(ctlr->id){
+ default:
+ areq = 0;
+ break;
+ case i82540em:
+ case i82540eplp:
+ case i82541ei:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82545em:
+ case i82545gmc:
+ case i82546gb:
+ case i82546eb:
+ case i82547ei:
+ case i82547gi:
+ areq = 1;
+ csr32w(ctlr, Eecd, eecd|Areq);
+ for(i = 0; i < 1000; i++){
+ if((eecd = csr32r(ctlr, Eecd)) & Agnt)
+ break;
+ microdelay(5);
+ }
+ if(!(eecd & Agnt)){
+ print("igbe: not granted EEPROM access\n");
+ goto release;
+ }
+ break;
+ }
+ snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
+
+ for(addr = 0; addr < 0x40; addr++){
+ /*
+ * Read a word at address 'addr' from the Atmel AT93C46
+ * 3-Wire Serial EEPROM or compatible. The EEPROM access is
+ * controlled by 4 bits in Eecd. See the AT93C46 datasheet
+ * for protocol details.
+ */
+ if(at93c46io(ctlr, rop, (0x06<<bits)|addr) != 0){
+ print("igbe: can't set EEPROM address 0x%2.2X\n", addr);
+ goto release;
+ }
+ data = at93c46io(ctlr, ":16COc;", 0);
+ at93c46io(ctlr, "sic", 0);
+ ctlr->eeprom[addr] = data;
+ sum += data;
+ }
+
+release:
+ if(areq)
+ csr32w(ctlr, Eecd, eecd & ~Areq);
+ return sum;
+}
+
+static int
+igbedetach(Ctlr* ctlr)
+{
+ int r, timeo;
+
+ /*
+ * Perform a device reset to get the chip back to the
+ * power-on state, followed by an EEPROM reset to read
+ * the defaults for some internal registers.
+ */
+ csr32w(ctlr, Imc, ~0);
+ csr32w(ctlr, Rctl, 0);
+ csr32w(ctlr, Tctl, 0);
+
+ delay(10);
+
+ csr32w(ctlr, Ctrl, Devrst);
+ delay(1);
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!(csr32r(ctlr, Ctrl) & Devrst))
+ break;
+ delay(1);
+ }
+ if(csr32r(ctlr, Ctrl) & Devrst)
+ return -1;
+ r = csr32r(ctlr, Ctrlext);
+ csr32w(ctlr, Ctrlext, r|Eerst);
+ delay(1);
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!(csr32r(ctlr, Ctrlext) & Eerst))
+ break;
+ delay(1);
+ }
+ if(csr32r(ctlr, Ctrlext) & Eerst)
+ return -1;
+
+ switch(ctlr->id){
+ default:
+ break;
+ case i82540em:
+ case i82540eplp:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82545em:
+ case i82545gmc:
+ case i82547gi:
+ case i82546gb:
+ case i82546eb:
+ r = csr32r(ctlr, Manc);
+ r &= ~Arpen;
+ csr32w(ctlr, Manc, r);
+ break;
+ }
+
+ csr32w(ctlr, Imc, ~0);
+ delay(1);
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!csr32r(ctlr, Icr))
+ break;
+ delay(1);
+ }
+ if(csr32r(ctlr, Icr))
+ return -1;
+
+ return 0;
+}
+
+static void
+igbeshutdown(Ether* ether)
+{
+ igbedetach(ether->ctlr);
+}
+
+static int
+igbereset(Ctlr* ctlr)
+{
+ int ctrl, i, pause, r, swdpio, txcw;
+
+ if(igbedetach(ctlr))
+ return -1;
+
+ /*
+ * Read the EEPROM, validate the checksum
+ * then get the device back to a power-on state.
+ */
+ if((r = at93c46r(ctlr)) != 0xBABA){
+ print("igbe: bad EEPROM checksum - 0x%4.4uX\n", r);
+ return -1;
+ }
+
+ /*
+ * Snarf and set up the receive addresses.
+ * There are 16 addresses. The first should be the MAC address.
+ * The others are cleared and not marked valid (MS bit of Rah).
+ */
+ if ((ctlr->id == i82546gb || ctlr->id == i82546eb) &&
+ BUSFNO(ctlr->pcidev->tbdf) == 1)
+ ctlr->eeprom[Ea+2] += 0x100; /* second interface */
+ if(ctlr->id == i82541gi && ctlr->eeprom[Ea] == 0xFFFF)
+ ctlr->eeprom[Ea] = 0xD000;
+ for(i = Ea; i < Eaddrlen/2; i++){
+ ctlr->ra[2*i] = ctlr->eeprom[i];
+ ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
+ }
+ /* lan id seems to vary on 82543gc; don't use it */
+ if (ctlr->id != i82543gc) {
+ r = (csr32r(ctlr, Status) & Lanid) >> 2;
+ ctlr->ra[5] += r; /* ea ctlr[1] = ea ctlr[0]+1 */
+ }
+
+ r = (ctlr->ra[3]<<24)|(ctlr->ra[2]<<16)|(ctlr->ra[1]<<8)|ctlr->ra[0];
+ csr32w(ctlr, Ral, r);
+ r = 0x80000000|(ctlr->ra[5]<<8)|ctlr->ra[4];
+ csr32w(ctlr, Rah, r);
+ for(i = 1; i < 16; i++){
+ csr32w(ctlr, Ral+i*8, 0);
+ csr32w(ctlr, Rah+i*8, 0);
+ }
+
+ /*
+ * Clear the Multicast Table Array.
+ * It's a 4096 bit vector accessed as 128 32-bit registers.
+ */
+ memset(ctlr->mta, 0, sizeof(ctlr->mta));
+ for(i = 0; i < 128; i++)
+ csr32w(ctlr, Mta+i*4, 0);
+
+ /*
+ * Just in case the Eerst didn't load the defaults
+ * (doesn't appear to fully on the 82543GC), do it manually.
+ */
+ if (ctlr->id == i82543gc) {
+ txcw = csr32r(ctlr, Txcw);
+ txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);
+ ctrl = csr32r(ctlr, Ctrl);
+ ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);
+
+ if(ctlr->eeprom[Icw1] & 0x0400){
+ ctrl |= Fd;
+ txcw |= TxcwFd;
+ }
+ if(ctlr->eeprom[Icw1] & 0x0200)
+ ctrl |= Lrst;
+ if(ctlr->eeprom[Icw1] & 0x0010)
+ ctrl |= Ilos;
+ if(ctlr->eeprom[Icw1] & 0x0800)
+ ctrl |= Frcspd;
+ swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;
+ ctrl |= swdpio<<SwdpioloSHIFT;
+ csr32w(ctlr, Ctrl, ctrl);
+
+ ctrl = csr32r(ctlr, Ctrlext);
+ ctrl &= ~(Ips|SwdpiohiMASK);
+ swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;
+ if(ctlr->eeprom[Icw1] & 0x1000)
+ ctrl |= Ips;
+ ctrl |= swdpio<<SwdpiohiSHIFT;
+ csr32w(ctlr, Ctrlext, ctrl);
+
+ if(ctlr->eeprom[Icw2] & 0x0800)
+ txcw |= TxcwAne;
+ pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;
+ txcw |= pause<<TxcwPauseSHIFT;
+ switch(pause){
+ default:
+ ctlr->fcrtl = 0x00002000;
+ ctlr->fcrth = 0x00004000;
+ txcw |= TxcwAs|TxcwPs;
+ break;
+ case 0:
+ ctlr->fcrtl = 0x00002000;
+ ctlr->fcrth = 0x00004000;
+ break;
+ case 2:
+ ctlr->fcrtl = 0;
+ ctlr->fcrth = 0;
+ txcw |= TxcwAs;
+ break;
+ }
+ ctlr->txcw = txcw;
+ csr32w(ctlr, Txcw, txcw);
+ }
+
+
+ /*
+ * Flow control - values from the datasheet.
+ */
+ csr32w(ctlr, Fcal, 0x00C28001);
+ csr32w(ctlr, Fcah, 0x00000100);
+ csr32w(ctlr, Fct, 0x00008808);
+ csr32w(ctlr, Fcttv, 0x00000100);
+
+ csr32w(ctlr, Fcrtl, ctlr->fcrtl);
+ csr32w(ctlr, Fcrth, ctlr->fcrth);
+
+ if(!(csr32r(ctlr, Status) & Tbimode) && igbemii(ctlr) < 0)
+ return -1;
+
+ return 0;
+}
+
+static void
+igbepci(void)
+{
+ int cls;
+ Pcidev *p;
+ Ctlr *ctlr;
+ void *mem;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+
+ switch((p->did<<16)|p->vid){
+ default:
+ continue;
+ case i82543gc:
+ case i82544ei:
+ case i82544eif:
+ case i82544gc:
+ case i82547ei:
+ case i82547gi:
+ case i82540em:
+ case i82540eplp:
+ case i82541ei:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82545em:
+ case i82545gmc:
+ case i82546gb:
+ case i82546eb:
+ break;
+ }
+
+ 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;
+ }
+ cls = pcicfgr8(p, PciCLS);
+ switch(cls){
+ default:
+ print("igbe: unexpected CLS - %d\n", cls*4);
+ break;
+ case 0x00:
+ case 0xFF:
+ print("igbe: unusable CLS - %d\n", cls*4);
+ continue;
+ case 0x08:
+ case 0x10:
+ break;
+ }
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = p->mem[0].bar & ~0x0F;
+ ctlr->pcidev = p;
+ ctlr->id = (p->did<<16)|p->vid;
+ ctlr->cls = cls*4;
+ ctlr->nic = mem;
+
+ if(igbereset(ctlr)){
+ free(ctlr);
+ vunmap(mem, p->mem[0].size);
+ continue;
+ }
+ pcisetbme(p);
+
+ if(igbectlrhead != nil)
+ igbectlrtail->next = ctlr;
+ else
+ igbectlrhead = ctlr;
+ igbectlrtail = ctlr;
+ }
+}
+
+static int
+igbepnp(Ether* edev)
+{
+ Ctlr *ctlr;
+
+ if(igbectlrhead == nil)
+ igbepci();
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = igbectlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+ edev->mbps = 1000;
+ memmove(edev->ea, ctlr->ra, Eaddrlen);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ edev->attach = igbeattach;
+ edev->transmit = igbetransmit;
+ edev->interrupt = igbeinterrupt;
+ edev->ifstat = igbeifstat;
+ edev->ctl = igbectl;
+
+ edev->arg = edev;
+ edev->promiscuous = igbepromiscuous;
+ edev->shutdown = igbeshutdown;
+ edev->multicast = igbemulticast;
+
+ return 0;
+}
+
+void
+etherigbelink(void)
+{
+ addethercard("i82543", igbepnp);
+ addethercard("igbe", igbepnp);
+}
+
diff --git a/sys/src/9/pc/etherm10g.c b/sys/src/9/pc/etherm10g.c
new file mode 100755
index 000000000..630376350
--- /dev/null
+++ b/sys/src/9/pc/etherm10g.c
@@ -0,0 +1,1636 @@
+/*
+ * myricom 10g-pcie-8a 10 Gb ethernet driver
+ * © 2007 erik quanstrom, coraid
+ *
+ * the card is big endian.
+ * we use uvlong rather than uintptr to hold addresses so that
+ * we don't get "warning: stupid shift" on 32-bit architectures.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "../pc/etherif.h"
+
+#ifndef KiB
+#define KiB 1024u /* Kibi 0x0000000000000400 */
+#define MiB 1048576u /* Mebi 0x0000000000100000 */
+#endif /* KiB */
+
+#define dprint(...) if(debug) print(__VA_ARGS__)
+#define pcicapdbg(...)
+#define malign(n) mallocalign((n), 4*KiB, 0, 0)
+
+#include "etherm10g2k.i"
+#include "etherm10g4k.i"
+
+static int debug = 0;
+static char Etimeout[] = "timeout";
+
+enum {
+ Epromsz = 256,
+ Maxslots= 1024,
+ Align = 4096,
+ Maxmtu = 9000,
+ Noconf = 0xffffffff,
+
+ Fwoffset= 1*MiB,
+ Cmdoff = 0xf80000, /* command port offset */
+ Fwsubmt = 0xfc0000, /* firmware submission command port offset */
+ Rdmaoff = 0xfc01c0, /* rdma command port offset */
+};
+
+enum {
+ CZero,
+ Creset,
+ Cversion,
+
+ CSintrqdma, /* issue these before Cetherup */
+ CSbigsz, /* in bytes bigsize = 2^n */
+ CSsmallsz,
+
+ CGsendoff,
+ CGsmallrxoff,
+ CGbigrxoff,
+ CGirqackoff,
+ CGirqdeassoff,
+ CGsendrgsz,
+ CGrxrgsz,
+
+ CSintrqsz, /* 2^n */
+ Cetherup, /* above parameters + mtu/mac addr must be set first. */
+ Cetherdn,
+
+ CSmtu, /* below may be issued live */
+ CGcoaloff, /* in µs */
+ CSstatsrate, /* in µs */
+ CSstatsdma,
+
+ Cpromisc,
+ Cnopromisc,
+ CSmac,
+
+ Cenablefc,
+ Cdisablefc,
+
+ Cdmatest, /* address in d[0-1], d[2]=length */
+
+ Cenableallmc,
+ Cdisableallmc,
+
+ CSjoinmc,
+ CSleavemc,
+ Cleaveallmc,
+
+ CSstatsdma2, /* adds (unused) multicast stats */
+};
+
+typedef union {
+ uint i[2];
+ uchar c[8];
+} Cmd;
+
+typedef ulong Slot;
+typedef struct {
+ ushort cksum;
+ ushort len;
+} Slotparts;
+
+enum {
+ SFsmall = 1,
+ SFfirst = 2,
+ SFalign = 4,
+ SFnotso = 16,
+};
+
+typedef struct {
+ ulong high;
+ ulong low;
+ ushort hdroff;
+ ushort len;
+ uchar pad;
+ uchar nrdma;
+ uchar chkoff;
+ uchar flags;
+} Send;
+
+typedef struct {
+ QLock;
+ Send *lanai; /* tx ring (cksum+len in lanai memory) */
+ Send *host; /* tx ring (data in our memory) */
+ Block **bring;
+// uchar *wcfifo; /* what the heck is a w/c fifo? */
+ int size; /* of buffers in the z8's memory */
+ ulong segsz;
+ uint n; /* rxslots */
+ uint m; /* mask; rxslots must be a power of two */
+ uint i; /* number of segments (not frames) queued */
+ uint cnt; /* number of segments sent by the card */
+
+ ulong npkt;
+ vlong nbytes;
+} Tx;
+
+typedef struct {
+ Lock;
+ Block *head;
+ uint size; /* buffer size of each block */
+ uint n; /* n free buffers */
+ uint cnt;
+} Bpool;
+
+static Bpool smpool = { .size = 128, };
+static Bpool bgpool = { .size = Maxmtu, };
+
+typedef struct {
+ Bpool *pool; /* free buffers */
+ ulong *lanai; /* rx ring; we have no permanent host shadow */
+ Block **host; /* called "info" in myricom driver */
+// uchar *wcfifo; /* cmd submission fifo */
+ uint m;
+ uint n; /* rxslots */
+ uint i;
+ uint cnt; /* number of buffers allocated (lifetime) */
+ uint allocfail;
+} Rx;
+
+/* dma mapped. unix network byte order. */
+typedef struct {
+ uchar txcnt[4];
+ uchar linkstat[4];
+ uchar dlink[4];
+ uchar derror[4];
+ uchar drunt[4];
+ uchar doverrun[4];
+ uchar dnosm[4];
+ uchar dnobg[4];
+ uchar nrdma[4];
+ uchar txstopped;
+ uchar down;
+ uchar updated;
+ uchar valid;
+} Stats;
+
+enum {
+ Detached,
+ Attached,
+ Runed,
+};
+
+typedef struct {
+ Slot *entry;
+ uvlong busaddr;
+ uint m;
+ uint n;
+ uint i;
+} Done;
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ QLock;
+ int state;
+ int kprocs;
+ uvlong port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id; /* do we need this? */
+
+ uchar ra[Eaddrlen];
+
+ int ramsz;
+ uchar *ram;
+
+ ulong *irqack;
+ ulong *irqdeass;
+ ulong *coal;
+
+ char eprom[Epromsz];
+ ulong serial; /* unit serial number */
+
+ QLock cmdl;
+ Cmd *cmd; /* address of command return */
+ uvlong cprt; /* bus address of command */
+
+ uvlong boot; /* boot address */
+
+ Done done;
+ Tx tx;
+ Rx sm;
+ Rx bg;
+ Stats *stats;
+ uvlong statsprt;
+
+ Rendez rxrendez;
+ Rendez txrendez;
+
+ int msi;
+ ulong linkstat;
+ ulong nrdma;
+} Ctlr;
+
+static Ctlr *ctlrs;
+
+enum {
+ PciCapPMG = 0x01, /* power management */
+ PciCapAGP = 0x02,
+ PciCapVPD = 0x03, /* vital product data */
+ PciCapSID = 0x04, /* slot id */
+ PciCapMSI = 0x05,
+ PciCapCHS = 0x06, /* compact pci hot swap */
+ PciCapPCIX = 0x07,
+ PciCapHTC = 0x08, /* hypertransport irq conf */
+ PciCapVND = 0x09, /* vendor specific information */
+ PciCapHSW = 0x0C, /* hot swap */
+ PciCapPCIe = 0x10,
+ PciCapMSIX = 0x11,
+};
+
+enum {
+ PcieAERC = 1,
+ PcieVC,
+ PcieSNC,
+ PciePBC,
+};
+
+enum {
+ AercCCR = 0x18, /* control register */
+};
+
+enum {
+ PcieCTL = 8,
+ PcieLCR = 12,
+ PcieMRD = 0x7000, /* maximum read size */
+};
+
+static int
+pcicap(Pcidev *p, int cap)
+{
+ int i, c, off;
+
+ pcicapdbg("pcicap: %x:%d\n", p->vid, p->did);
+ off = 0x34; /* 0x14 for cardbus */
+ for(i = 48; i--; ){
+ pcicapdbg("\t" "loop %x\n", off);
+ off = pcicfgr8(p, off);
+ pcicapdbg("\t" "pcicfgr8 %x\n", off);
+ if(off < 0x40)
+ break;
+ off &= ~3;
+ c = pcicfgr8(p, off);
+ pcicapdbg("\t" "pcicfgr8 %x\n", c);
+ if(c == 0xff)
+ break;
+ if(c == cap)
+ return off;
+ off++;
+ }
+ return 0;
+}
+
+/*
+ * this function doesn't work because pcicgr32 doesn't have access
+ * to the pcie extended configuration space.
+ */
+static int
+pciecap(Pcidev *p, int cap)
+{
+ uint off, i;
+
+ off = 0x100;
+ while(((i = pcicfgr32(p, off)) & 0xffff) != cap){
+ off = i >> 20;
+ print("m10g: pciecap offset = %ud", off);
+ if(off < 0x100 || off >= 4*KiB - 1)
+ return 0;
+ }
+ print("m10g: pciecap found = %ud", off);
+ return off;
+}
+
+static int
+setpcie(Pcidev *p)
+{
+ int off;
+
+ /* set 4k writes */
+ off = pcicap(p, PciCapPCIe);
+ if(off < 64)
+ return -1;
+ off += PcieCTL;
+ pcicfgw16(p, off, (pcicfgr16(p, off) & ~PcieMRD) | 5<<12);
+ return 0;
+}
+
+static int
+whichfw(Pcidev *p)
+{
+ char *s;
+ int i, off, lanes, ecrc;
+ ulong cap;
+
+ /* check the number of configured lanes. */
+ off = pcicap(p, PciCapPCIe);
+ if(off < 64)
+ return -1;
+ off += PcieLCR;
+ cap = pcicfgr16(p, off);
+ lanes = (cap>>4) & 0x3f;
+
+ /* check AERC register. we need it on. */
+ off = pciecap(p, PcieAERC);
+ print("; offset %d returned\n", off);
+ cap = 0;
+ if(off != 0){
+ off += AercCCR;
+ cap = pcicfgr32(p, off);
+ print("m10g: %lud cap\n", cap);
+ }
+ ecrc = (cap>>4) & 0xf;
+ /* if we don't like the aerc, kick it here. */
+
+ print("m10g: %d lanes; ecrc=%d; ", lanes, ecrc);
+ if(s = getconf("myriforce")){
+ i = atoi(s);
+ if(i != 4*KiB || i != 2*KiB)
+ i = 2*KiB;
+ print("fw = %d [forced]\n", i);
+ return i;
+ }
+ if(lanes <= 4)
+ print("fw = 4096 [lanes]\n");
+ else if(ecrc & 10)
+ print("fw = 4096 [ecrc set]\n");
+ else
+ print("fw = 4096 [default]\n");
+ return 4*KiB;
+}
+
+static int
+parseeprom(Ctlr *c)
+{
+ int i, j, k, l, bits;
+ char *s;
+
+ dprint("m10g eprom:\n");
+ s = c->eprom;
+ bits = 3;
+ for(i = 0; s[i] && i < Epromsz; i++){
+ l = strlen(s+i);
+ dprint("\t%s\n", s+i);
+ if(strncmp(s+i, "MAC=", 4) == 0 && l == 4+12+5){
+ bits ^= 1;
+ j = i + 4;
+ for(k = 0; k < 6; k++)
+ c->ra[k] = strtoul(s+j+3*k, 0, 16);
+ }else if(strncmp(s+i, "SN=", 3) == 0){
+ bits ^= 2;
+ c->serial = atoi(s+i+3);
+ }
+ i += l;
+ }
+ if(bits)
+ return -1;
+ return 0;
+}
+
+static ushort
+pbit16(ushort i)
+{
+ ushort j;
+ uchar *p;
+
+ p = (uchar*)&j;
+ p[1] = i;
+ p[0] = i>>8;
+ return j;
+}
+
+static ushort
+gbit16(uchar i[2])
+{
+ ushort j;
+
+ j = i[1];
+ j |= i[0]<<8;
+ return j;
+}
+
+static ulong
+pbit32(ulong i)
+{
+ ulong j;
+ uchar *p;
+
+ p = (uchar*)&j;
+ p[3] = i;
+ p[2] = i>>8;
+ p[1] = i>>16;
+ p[0] = i>>24;
+ return j;
+}
+
+static ulong
+gbit32(uchar i[4])
+{
+ ulong j;
+
+ j = i[3];
+ j |= i[2]<<8;
+ j |= i[1]<<16;
+ j |= i[0]<<24;
+ return j;
+}
+
+static void
+prepcmd(ulong *cmd, int i)
+{
+ while(i-- > 0)
+ cmd[i] = pbit32(cmd[i]);
+}
+
+/*
+ * the command looks like this (int 32bit integers)
+ * cmd type
+ * addr (low)
+ * addr (high)
+ * pad (used for dma testing)
+ * response (high)
+ * response (low)
+ * 40 byte = 5 int pad.
+ */
+
+ulong
+cmd(Ctlr *c, int type, uvlong data)
+{
+ ulong buf[16], i;
+ Cmd *cmd;
+
+ qlock(&c->cmdl);
+ cmd = c->cmd;
+ cmd->i[1] = Noconf;
+ memset(buf, 0, sizeof buf);
+ buf[0] = type;
+ buf[1] = data;
+ buf[2] = data >> 32;
+ buf[4] = c->cprt >> 32;
+ buf[5] = c->cprt;
+ prepcmd(buf, 6);
+ coherence();
+ memmove(c->ram + Cmdoff, buf, sizeof buf);
+
+ if(waserror())
+ nexterror();
+ for(i = 0; i < 15; i++){
+ if(cmd->i[1] != Noconf){
+ poperror();
+ i = gbit32(cmd->c);
+ qunlock(&c->cmdl);
+ if(cmd->i[1] != 0)
+ dprint("[%lux]", i);
+ return i;
+ }
+ tsleep(&up->sleep, return0, 0, 1);
+ }
+ qunlock(&c->cmdl);
+ iprint("m10g: cmd timeout [%ux %ux] cmd=%d\n",
+ cmd->i[0], cmd->i[1], type);
+ error(Etimeout);
+ return ~0; /* silence! */
+}
+
+ulong
+maccmd(Ctlr *c, int type, uchar *m)
+{
+ ulong buf[16], i;
+ Cmd *cmd;
+
+ qlock(&c->cmdl);
+ cmd = c->cmd;
+ cmd->i[1] = Noconf;
+ memset(buf, 0, sizeof buf);
+ buf[0] = type;
+ buf[1] = m[0]<<24 | m[1]<<16 | m[2]<<8 | m[3];
+ buf[2] = m[4]<< 8 | m[5];
+ buf[4] = c->cprt >> 32;
+ buf[5] = c->cprt;
+ prepcmd(buf, 6);
+ coherence();
+ memmove(c->ram + Cmdoff, buf, sizeof buf);
+
+ if(waserror())
+ nexterror();
+ for(i = 0; i < 15; i++){
+ if(cmd->i[1] != Noconf){
+ poperror();
+ i = gbit32(cmd->c);
+ qunlock(&c->cmdl);
+ if(cmd->i[1] != 0)
+ dprint("[%lux]", i);
+ return i;
+ }
+ tsleep(&up->sleep, return0, 0, 1);
+ }
+ qunlock(&c->cmdl);
+ iprint("m10g: maccmd timeout [%ux %ux] cmd=%d\n",
+ cmd->i[0], cmd->i[1], type);
+ error(Etimeout);
+ return ~0; /* silence! */
+}
+
+/* remove this garbage after testing */
+enum {
+ DMAread = 0x10000,
+ DMAwrite= 0x1,
+};
+
+ulong
+dmatestcmd(Ctlr *c, int type, uvlong addr, int len)
+{
+ ulong buf[16], i;
+
+ memset(buf, 0, sizeof buf);
+ memset(c->cmd, Noconf, sizeof *c->cmd);
+ buf[0] = Cdmatest;
+ buf[1] = addr;
+ buf[2] = addr >> 32;
+ buf[3] = len * type;
+ buf[4] = c->cprt >> 32;
+ buf[5] = c->cprt;
+ prepcmd(buf, 6);
+ coherence();
+ memmove(c->ram + Cmdoff, buf, sizeof buf);
+
+ if(waserror())
+ nexterror();
+ for(i = 0; i < 15; i++){
+ if(c->cmd->i[1] != Noconf){
+ i = gbit32(c->cmd->c);
+ if(i == 0)
+ error(Eio);
+ poperror();
+ return i;
+ }
+ tsleep(&up->sleep, return0, 0, 5);
+ }
+ error(Etimeout);
+ return ~0; /* silence! */
+}
+
+ulong
+rdmacmd(Ctlr *c, int on)
+{
+ ulong buf[16], i;
+
+ memset(buf, 0, sizeof buf);
+ c->cmd->i[0] = 0;
+ coherence();
+ buf[0] = c->cprt >> 32;
+ buf[1] = c->cprt;
+ buf[2] = Noconf;
+ buf[3] = c->cprt >> 32;
+ buf[4] = c->cprt;
+ buf[5] = on;
+ prepcmd(buf, 6);
+ memmove(c->ram + Rdmaoff, buf, sizeof buf);
+
+ if(waserror())
+ nexterror();
+ for(i = 0; i < 20; i++){
+ if(c->cmd->i[0] == Noconf){
+ poperror();
+ return gbit32(c->cmd->c);
+ }
+ tsleep(&up->sleep, return0, 0, 1);
+ }
+ error(Etimeout);
+ iprint("m10g: rdmacmd timeout\n");
+ return ~0; /* silence! */
+}
+
+static int
+loadfw(Ctlr *c, int *align)
+{
+ ulong *f, *s, sz;
+ int i;
+
+ if((*align = whichfw(c->pcidev)) == 4*KiB){
+ f = (ulong*)fw4k;
+ sz = sizeof fw4k;
+ }else{
+ f = (ulong*)fw2k;
+ sz = sizeof fw2k;
+ }
+
+ s = (ulong*)(c->ram + Fwoffset);
+ for(i = 0; i < sz / 4; i++)
+ s[i] = f[i];
+ return sz & ~3;
+}
+
+static int
+bootfw(Ctlr *c)
+{
+ int i, sz, align;
+ ulong buf[16];
+ Cmd* cmd;
+
+ if((sz = loadfw(c, &align)) == 0)
+ return 0;
+ dprint("bootfw %d bytes ... ", sz);
+ cmd = c->cmd;
+
+ memset(buf, 0, sizeof buf);
+ c->cmd->i[0] = 0;
+ coherence();
+ buf[0] = c->cprt >> 32; /* upper dma target address */
+ buf[1] = c->cprt; /* lower */
+ buf[2] = Noconf; /* writeback */
+ buf[3] = Fwoffset + 8,
+ buf[4] = sz - 8;
+ buf[5] = 8;
+ buf[6] = 0;
+ prepcmd(buf, 7);
+ coherence();
+ memmove(c->ram + Fwsubmt, buf, sizeof buf);
+
+ for(i = 0; i < 20; i++){
+ if(cmd->i[0] == Noconf)
+ break;
+ delay(1);
+ }
+ dprint("[%lux %lux]", gbit32(cmd->c), gbit32(cmd->c+4));
+ if(i == 20){
+ print("m10g: cannot load fw\n");
+ return -1;
+ }
+ dprint("\n");
+ c->tx.segsz = align;
+ return 0;
+}
+
+static int
+kickthebaby(Pcidev *p, Ctlr *c)
+{
+ /* don't kick the baby! */
+ ulong code;
+
+ pcicfgw8(p, 0x10 + c->boot, 0x3);
+ pcicfgw32(p, 0x18 + c->boot, 0xfffffff0);
+ code = pcicfgr32(p, 0x14 + c->boot);
+
+ dprint("reboot status = %lux\n", code);
+ if(code != 0xfffffff0)
+ return -1;
+ return 0;
+}
+
+typedef struct {
+ uchar len[4];
+ uchar type[4];
+ char version[128];
+ uchar globals[4];
+ uchar ramsz[4];
+ uchar specs[4];
+ uchar specssz[4];
+} Fwhdr;
+
+enum {
+ Tmx = 0x4d582020,
+ Tpcie = 0x70636965,
+ Teth = 0x45544820,
+ Tmcp0 = 0x4d435030,
+};
+
+static char *
+fwtype(ulong type)
+{
+ switch(type){
+ case Tmx:
+ return "mx";
+ case Tpcie:
+ return "PCIe";
+ case Teth:
+ return "eth";
+ case Tmcp0:
+ return "mcp0";
+ }
+ return "*GOK*";
+}
+
+static int
+chkfw(Ctlr *c)
+{
+ ulong off, type;
+ Fwhdr *h;
+
+ off = gbit32(c->ram+0x3c);
+ dprint("firmware %lux\n", off);
+ if((off&3) || off + sizeof *h > c->ramsz){
+ print("!m10g: bad firmware %lux\n", off);
+ return -1;
+ }
+ h = (Fwhdr*)(c->ram + off);
+ type = gbit32(h->type);
+ dprint("\t" "type %s\n", fwtype(type));
+ dprint("\t" "vers %s\n", h->version);
+ dprint("\t" "ramsz %lux\n", gbit32(h->ramsz));
+ if(type != Teth){
+ print("!m10g: bad card type %s\n", fwtype(type));
+ return -1;
+ }
+
+ return bootfw(c) || rdmacmd(c, 0);
+}
+
+static int
+reset(Ether *e, Ctlr *c)
+{
+ ulong i, sz;
+
+ if(waserror()){
+ print("m10g: reset error\n");
+ nexterror();
+ return -1;
+ }
+
+ chkfw(c);
+ cmd(c, Creset, 0);
+
+ cmd(c, CSintrqsz, c->done.n * sizeof *c->done.entry);
+ cmd(c, CSintrqdma, c->done.busaddr);
+ c->irqack = (ulong*)(c->ram + cmd(c, CGirqackoff, 0));
+ /* required only if we're not doing msi? */
+ c->irqdeass = (ulong*)(c->ram + cmd(c, CGirqdeassoff, 0));
+ /* this is the driver default, why fiddle with this? */
+ c->coal = (ulong*)(c->ram + cmd(c, CGcoaloff, 0));
+ *c->coal = pbit32(25);
+
+ dprint("dma stats:\n");
+ rdmacmd(c, 1);
+ sz = c->tx.segsz;
+ i = dmatestcmd(c, DMAread, c->done.busaddr, sz);
+ print("m10g: read %lud MB/s;", ((i>>16)*sz*2) / (i&0xffff));
+ i = dmatestcmd(c, DMAwrite, c->done.busaddr, sz);
+ print(" write %lud MB/s;", ((i>>16)*sz*2) / (i&0xffff));
+ i = dmatestcmd(c, DMAwrite|DMAread, c->done.busaddr, sz);
+ print(" r/w %lud MB/s\n", ((i>>16)*sz*2*2) / (i&0xffff));
+ memset(c->done.entry, 0, c->done.n * sizeof *c->done.entry);
+
+ maccmd(c, CSmac, c->ra);
+// cmd(c, Cnopromisc, 0);
+ cmd(c, Cenablefc, 0);
+ e->maxmtu = Maxmtu;
+ cmd(c, CSmtu, e->maxmtu);
+ dprint("CSmtu %d...\n", e->maxmtu);
+
+ poperror();
+ return 0;
+}
+
+static void
+ctlrfree(Ctlr *c)
+{
+ /* free up all the Block*s, too */
+ free(c->tx.host);
+ free(c->sm.host);
+ free(c->bg.host);
+ free(c->cmd);
+ free(c->done.entry);
+ free(c->stats);
+ free(c);
+}
+
+static int
+setmem(Pcidev *p, Ctlr *c)
+{
+ ulong i;
+ uvlong raddr;
+ Done *d;
+ void *mem;
+
+ c->tx.segsz = 2048;
+ c->ramsz = 2*MiB - (2*48*KiB + 32*KiB) - 0x100;
+ if(c->ramsz > p->mem[0].size)
+ return -1;
+
+ raddr = p->mem[0].bar & ~0x0F;
+ mem = vmap(raddr, p->mem[0].size);
+ if(mem == nil){
+ print("m10g: can't map %8.8lux\n", p->mem[0].bar);
+ return -1;
+ }
+ dprint("%llux <- vmap(mem[0].size = %ux)\n", raddr, p->mem[0].size);
+ c->port = raddr;
+ c->ram = mem;
+ c->cmd = malign(sizeof *c->cmd);
+ c->cprt = PCIWADDR(c->cmd);
+
+ d = &c->done;
+ d->n = Maxslots;
+ d->m = d->n - 1;
+ i = d->n * sizeof *d->entry;
+ d->entry = malign(i);
+ memset(d->entry, 0, i);
+ d->busaddr = PCIWADDR(d->entry);
+
+ c->stats = malign(sizeof *c->stats);
+ memset(c->stats, 0, sizeof *c->stats);
+ c->statsprt = PCIWADDR(c->stats);
+
+ memmove(c->eprom, c->ram + c->ramsz - Epromsz, Epromsz-2);
+ return setpcie(p) || parseeprom(c);
+}
+
+static Rx*
+whichrx(Ctlr *c, int sz)
+{
+ if(sz <= smpool.size)
+ return &c->sm;
+ return &c->bg;
+}
+
+static Block*
+balloc(Rx* rx)
+{
+ Block *bp;
+
+ ilock(rx->pool);
+ if((bp = rx->pool->head) != nil){
+ rx->pool->head = bp->next;
+ bp->next = nil;
+ _xinc(&bp->ref); /* prevent bp from being freed */
+ rx->pool->n--;
+ }
+ iunlock(rx->pool);
+ return bp;
+}
+
+static void
+rbfree(Block *b, Bpool *p)
+{
+ b->rp = b->wp = (uchar*)PGROUND((uintptr)b->base);
+ b->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
+
+ ilock(p);
+ b->next = p->head;
+ p->head = b;
+ p->n++;
+ p->cnt++;
+ iunlock(p);
+}
+
+static void
+smbfree(Block *b)
+{
+ rbfree(b, &smpool);
+}
+
+static void
+bgbfree(Block *b)
+{
+ rbfree(b, &bgpool);
+}
+
+static void
+replenish(Rx *rx)
+{
+ ulong buf[16], i, idx, e;
+ Bpool *p;
+ Block *b;
+
+ p = rx->pool;
+ if(p->n < 8)
+ return;
+ memset(buf, 0, sizeof buf);
+ e = (rx->i - rx->cnt) & ~7;
+ e += rx->n;
+ while(p->n >= 8 && e){
+ idx = rx->cnt & rx->m;
+ for(i = 0; i < 8; i++){
+ b = balloc(rx);
+ buf[i*2] = pbit32((uvlong)PCIWADDR(b->wp) >> 32);
+ buf[i*2+1] = pbit32(PCIWADDR(b->wp));
+ rx->host[idx+i] = b;
+ assert(b);
+ }
+ memmove(rx->lanai + 2*idx, buf, sizeof buf);
+ coherence();
+ rx->cnt += 8;
+ e -= 8;
+ }
+ if(e && p->n > 7+1)
+ print("m10g: should panic? pool->n = %d\n", p->n);
+}
+
+/*
+ * future:
+ * if (c->mtrr >= 0) {
+ * c->tx.wcfifo = c->ram+0x200000;
+ * c->sm.wcfifo = c->ram+0x300000;
+ * c->bg.wcfifo = c->ram+0x340000;
+ * }
+ */
+
+static int
+nextpow(int j)
+{
+ int i;
+
+ for(i = 0; j > (1 << i); i++)
+ ;
+ return 1 << i;
+}
+
+static void*
+emalign(int sz)
+{
+ void *v;
+
+ v = malign(sz);
+ if(v == nil)
+ error(Enomem);
+ memset(v, 0, sz);
+ return v;
+}
+
+static void
+open0(Ether *e, Ctlr *c)
+{
+ Block *b;
+ int i, sz, entries;
+
+ entries = cmd(c, CGsendrgsz, 0) / sizeof *c->tx.lanai;
+ c->tx.lanai = (Send*)(c->ram + cmd(c, CGsendoff, 0));
+ c->tx.host = emalign(entries * sizeof *c->tx.host);
+ c->tx.bring = emalign(entries * sizeof *c->tx.bring);
+ c->tx.n = entries;
+ c->tx.m = entries-1;
+
+ entries = cmd(c, CGrxrgsz, 0)/8;
+ c->sm.pool = &smpool;
+ cmd(c, CSsmallsz, c->sm.pool->size);
+ c->sm.lanai = (ulong*)(c->ram + cmd(c, CGsmallrxoff, 0));
+ c->sm.n = entries;
+ c->sm.m = entries-1;
+ c->sm.host = emalign(entries * sizeof *c->sm.host);
+
+ c->bg.pool = &bgpool;
+ c->bg.pool->size = nextpow(2 + e->maxmtu); /* 2-byte alignment pad */
+ cmd(c, CSbigsz, c->bg.pool->size);
+ c->bg.lanai = (ulong*)(c->ram + cmd(c, CGbigrxoff, 0));
+ c->bg.n = entries;
+ c->bg.m = entries-1;
+ c->bg.host = emalign(entries * sizeof *c->bg.host);
+
+ sz = c->sm.pool->size + BY2PG;
+ for(i = 0; i < c->sm.n; i++){
+ if((b = allocb(sz)) == 0)
+ break;
+ b->free = smbfree;
+ freeb(b);
+ }
+ sz = c->bg.pool->size + BY2PG;
+ for(i = 0; i < c->bg.n; i++){
+ if((b = allocb(sz)) == 0)
+ break;
+ b->free = bgbfree;
+ freeb(b);
+ }
+
+ cmd(c, CSstatsdma, c->statsprt);
+ c->linkstat = ~0;
+ c->nrdma = 15;
+
+ cmd(c, Cetherup, 0);
+}
+
+static Block*
+nextblock(Ctlr *c)
+{
+ uint i;
+ ushort l, k;
+ Block *b;
+ Done *d;
+ Rx *rx;
+ Slot *s;
+ Slotparts *sp;
+
+ d = &c->done;
+ s = d->entry;
+ i = d->i & d->m;
+ sp = (Slotparts *)(s + i);
+ l = sp->len;
+ if(l == 0)
+ return 0;
+ k = sp->cksum;
+ s[i] = 0;
+ d->i++;
+ l = gbit16((uchar*)&l);
+//dprint("nextb: i=%d l=%d\n", d->i, l);
+ rx = whichrx(c, l);
+ if(rx->i >= rx->cnt){
+ iprint("m10g: overrun\n");
+ return 0;
+ }
+ i = rx->i & rx->m;
+ b = rx->host[i];
+ rx->host[i] = 0;
+ if(b == 0){
+ iprint("m10g: error rx to no block. memory is hosed.\n");
+ return 0;
+ }
+ rx->i++;
+
+ b->flag |= Bipck|Btcpck|Budpck;
+ b->checksum = k;
+ b->rp += 2;
+ b->wp += 2+l;
+ b->lim = b->wp; /* lie like a dog. */
+ return b;
+}
+
+static int
+rxcansleep(void *v)
+{
+ Ctlr *c;
+ Slot *s;
+ Slotparts *sp;
+ Done *d;
+
+ c = v;
+ d = &c->done;
+ s = c->done.entry;
+ sp = (Slotparts *)(s + (d->i & d->m));
+ if(sp->len != 0)
+ return -1;
+ c->irqack[0] = pbit32(3);
+ return 0;
+}
+
+static void
+m10rx(void *v)
+{
+ Ether *e;
+ Ctlr *c;
+ Block *b;
+
+ e = v;
+ c = e->ctlr;
+ for(;;){
+ replenish(&c->sm);
+ replenish(&c->bg);
+ sleep(&c->rxrendez, rxcansleep, c);
+ while(b = nextblock(c))
+ etheriq(e, b, 1);
+ }
+}
+
+static void
+txcleanup(Tx *tx, ulong n)
+{
+ Block *b;
+ uint j, l, m;
+
+ if(tx->npkt == n)
+ return;
+ l = 0;
+ m = tx->m;
+ /*
+ * if tx->cnt == tx->i, yet tx->npkt == n-1, we just
+ * caught ourselves and myricom card updating.
+ */
+ for(;; tx->cnt++){
+ j = tx->cnt & tx->m;
+ if(b = tx->bring[j]){
+ tx->bring[j] = 0;
+ tx->nbytes += BLEN(b);
+ freeb(b);
+ if(++tx->npkt == n)
+ return;
+ }
+ if(tx->cnt == tx->i)
+ return;
+ if(l++ == m){
+ iprint("m10g: tx ovrun: %lud %lud\n", n, tx->npkt);
+ return;
+ }
+ }
+}
+
+static int
+txcansleep(void *v)
+{
+ Ctlr *c;
+
+ c = v;
+ if(c->tx.cnt != c->tx.i && c->tx.npkt != gbit32(c->stats->txcnt))
+ return -1;
+ return 0;
+}
+
+static void
+txproc(void *v)
+{
+ Ether *e;
+ Ctlr *c;
+ Tx *tx;
+
+ e = v;
+ c = e->ctlr;
+ tx = &c->tx;
+ for(;;){
+ sleep(&c->txrendez, txcansleep, c);
+ txcleanup(tx, gbit32(c->stats->txcnt));
+ }
+}
+
+static void
+submittx(Tx *tx, int n)
+{
+ Send *l, *h;
+ int i0, i, m;
+
+ m = tx->m;
+ i0 = tx->i & m;
+ l = tx->lanai;
+ h = tx->host;
+ for(i = n-1; i >= 0; i--)
+ memmove(l+(i + i0 & m), h+(i + i0 & m), sizeof *h);
+ tx->i += n;
+// coherence();
+}
+
+static int
+nsegments(Block *b, int segsz)
+{
+ uintptr bus, end, slen, len;
+ int i;
+
+ bus = PCIWADDR(b->rp);
+ i = 0;
+ for(len = BLEN(b); len; len -= slen){
+ end = bus + segsz & ~(segsz-1);
+ slen = end - bus;
+ if(slen > len)
+ slen = len;
+ bus += slen;
+ i++;
+ }
+ return i;
+}
+
+static void
+m10gtransmit(Ether *e)
+{
+ ushort slen;
+ ulong i, cnt, rdma, nseg, count, end, bus, len, segsz;
+ uchar flags;
+ Block *b;
+ Ctlr *c;
+ Send *s, *s0, *s0m8;
+ Tx *tx;
+
+ c = e->ctlr;
+ tx = &c->tx;
+ segsz = tx->segsz;
+
+ qlock(tx);
+ count = 0;
+ s = tx->host + (tx->i & tx->m);
+ cnt = tx->cnt;
+ s0 = tx->host + (cnt & tx->m);
+ s0m8 = tx->host + ((cnt - 8) & tx->m);
+ i = tx->i;
+ for(; s >= s0 || s < s0m8; i += nseg){
+ if((b = qget(e->oq)) == nil)
+ break;
+ flags = SFfirst|SFnotso;
+ if((len = BLEN(b)) < 1520)
+ flags |= SFsmall;
+ rdma = nseg = nsegments(b, segsz);
+ bus = PCIWADDR(b->rp);
+ for(; len; len -= slen){
+ end = (bus + segsz) & ~(segsz-1);
+ slen = end - bus;
+ if(slen > len)
+ slen = len;
+ s->low = pbit32(bus);
+ s->len = pbit16(slen);
+ s->nrdma = rdma;
+ s->flags = flags;
+
+ bus += slen;
+ if(++s == tx->host + tx->n)
+ s = tx->host;
+ count++;
+ flags &= ~SFfirst;
+ rdma = 1;
+ }
+ tx->bring[(i + nseg - 1) & tx->m] = b;
+ if(1 || count > 0){
+ submittx(tx, count);
+ count = 0;
+ cnt = tx->cnt;
+ s0 = tx->host + (cnt & tx->m);
+ s0m8 = tx->host + ((cnt - 8) & tx->m);
+ }
+ }
+ qunlock(tx);
+}
+
+static void
+checkstats(Ether *e, Ctlr *c, Stats *s)
+{
+ ulong i;
+
+ if(s->updated == 0)
+ return;
+
+ i = gbit32(s->linkstat);
+ if(c->linkstat != i){
+ e->link = i;
+ if(c->linkstat = i)
+ dprint("m10g: link up\n");
+ else
+ dprint("m10g: link down\n");
+ }
+ i = gbit32(s->nrdma);
+ if(i != c->nrdma){
+ dprint("m10g: rdma timeout %ld\n", i);
+ c->nrdma = i;
+ }
+}
+
+static void
+waitintx(Ctlr *c)
+{
+ int i;
+
+ for(i = 0; i < 1024*1024; i++){
+ if(c->stats->valid == 0)
+ break;
+ coherence();
+ }
+}
+
+static void
+m10ginterrupt(Ureg *, void *v)
+{
+ Ether *e;
+ Ctlr *c;
+
+ e = v;
+ c = e->ctlr;
+
+ if(c->state != Runed || c->stats->valid == 0) /* not ready for us? */
+ return;
+
+ if(c->stats->valid & 1)
+ wakeup(&c->rxrendez);
+ if(gbit32(c->stats->txcnt) != c->tx.npkt)
+ wakeup(&c->txrendez);
+ if(c->msi == 0)
+ *c->irqdeass = 0;
+ else
+ c->stats->valid = 0;
+ waitintx(c);
+ checkstats(e, c, c->stats);
+ c->irqack[1] = pbit32(3);
+}
+
+static void
+m10gattach(Ether *e)
+{
+ Ctlr *c;
+ char name[12];
+
+ dprint("m10gattach\n");
+
+ qlock(e->ctlr);
+ c = e->ctlr;
+ if(c->state != Detached){
+ qunlock(c);
+ return;
+ }
+ if(waserror()){
+ c->state = Detached;
+ qunlock(c);
+ nexterror();
+ }
+ reset(e, c);
+ c->state = Attached;
+ open0(e, c);
+ if(c->kprocs == 0){
+ c->kprocs++;
+ snprint(name, sizeof name, "#l%drxproc", e->ctlrno);
+ kproc(name, m10rx, e);
+ snprint(name, sizeof name, "#l%dtxproc", e->ctlrno);
+ kproc(name, txproc, e);
+ }
+ c->state = Runed;
+ qunlock(c);
+ poperror();
+}
+
+static int
+m10gdetach(Ctlr *c)
+{
+ dprint("m10gdetach\n");
+// reset(e->ctlr);
+ vunmap(c->ram, c->pcidev->mem[0].size);
+ ctlrfree(c);
+ return -1;
+}
+
+static int
+lstcount(Block *b)
+{
+ int i;
+
+ i = 0;
+ for(; b; b = b->next)
+ i++;
+ return i;
+}
+
+static long
+m10gifstat(Ether *e, void *v, long n, ulong off)
+{
+ int l;
+ char *p;
+ Ctlr *c;
+ Stats s;
+
+ c = e->ctlr;
+ p = malloc(READSTR+1);
+ l = 0;
+ /* no point in locking this because this is done via dma. */
+ memmove(&s, c->stats, sizeof s);
+
+ // l +=
+ snprint(p+l, READSTR,
+ "txcnt = %lud\n" "linkstat = %lud\n" "dlink = %lud\n"
+ "derror = %lud\n" "drunt = %lud\n" "doverrun = %lud\n"
+ "dnosm = %lud\n" "dnobg = %lud\n" "nrdma = %lud\n"
+ "txstopped = %ud\n" "down = %ud\n" "updated = %ud\n"
+ "valid = %ud\n\n"
+ "tx pkt = %lud\n" "tx bytes = %lld\n"
+ "tx cnt = %ud\n" "tx n = %ud\n" "tx i = %ud\n"
+ "sm cnt = %ud\n" "sm i = %ud\n" "sm n = %ud\n"
+ "sm lst = %ud\n"
+ "bg cnt = %ud\n" "bg i = %ud\n" "bg n = %ud\n"
+ "bg lst = %ud\n"
+ "segsz = %lud\n" "coal = %lud\n",
+ gbit32(s.txcnt), gbit32(s.linkstat), gbit32(s.dlink),
+ gbit32(s.derror), gbit32(s.drunt), gbit32(s.doverrun),
+ gbit32(s.dnosm), gbit32(s.dnobg), gbit32(s.nrdma),
+ s.txstopped, s.down, s.updated, s.valid,
+ c->tx.npkt, c->tx.nbytes,
+ c->tx.cnt, c->tx.n, c->tx.i,
+ c->sm.cnt, c->sm.i, c->sm.pool->n, lstcount(c->sm.pool->head),
+ c->bg.cnt, c->bg.i, c->bg.pool->n, lstcount(c->bg.pool->head),
+ c->tx.segsz, gbit32((uchar*)c->coal));
+
+ n = readstr(off, v, n, p);
+ free(p);
+ return n;
+}
+
+//static void
+//summary(Ether *e)
+//{
+// char *buf;
+// int n, i, j;
+//
+// if(e == 0)
+// return;
+// buf = malloc(n=250);
+// if(buf == 0)
+// return;
+//
+// snprint(buf, n, "oq\n");
+// qsummary(e->oq, buf+3, n-3-1);
+// iprint("%s", buf);
+//
+// if(e->f) for(i = 0; e->f[i]; i++){
+// j = snprint(buf, n, "f%d %d\n", i, e->f[i]->type);
+// qsummary(e->f[i]->in, buf+j, n-j-1);
+// print("%s", buf);
+// }
+//
+// free(buf);
+//}
+
+static void
+rxring(Ctlr *c)
+{
+ Done *d;
+ Slot *s;
+ Slotparts *sp;
+ int i;
+
+ d = &c->done;
+ s = d->entry;
+ for(i = 0; i < d->n; i++) {
+ sp = (Slotparts *)(s + i);
+ if(sp->len)
+ iprint("s[%d] = %d\n", i, sp->len);
+ }
+}
+
+enum {
+ CMdebug,
+ CMcoal,
+ CMwakeup,
+ CMtxwakeup,
+ CMqsummary,
+ CMrxring,
+};
+
+static Cmdtab ctab[] = {
+ CMdebug, "debug", 2,
+ CMcoal, "coal", 2,
+ CMwakeup, "wakeup", 1,
+ CMtxwakeup, "txwakeup", 1,
+// CMqsummary, "q", 1,
+ CMrxring, "rxring", 1,
+};
+
+static long
+m10gctl(Ether *e, void *v, long n)
+{
+ int i;
+ Cmdbuf *c;
+ Cmdtab *t;
+
+ dprint("m10gctl\n");
+ if(e->ctlr == nil)
+ error(Enonexist);
+
+ c = parsecmd(v, n);
+ if(waserror()){
+ free(c);
+ nexterror();
+ }
+ t = lookupcmd(c, ctab, nelem(ctab));
+ switch(t->index){
+ case CMdebug:
+ debug = (strcmp(c->f[1], "on") == 0);
+ break;
+ case CMcoal:
+ i = atoi(c->f[1]);
+ if(i < 0 || i > 1000)
+ error(Ebadarg);
+ *((Ctlr*)e->ctlr)->coal = pbit32(i);
+ break;
+ case CMwakeup:
+ wakeup(&((Ctlr*)e->ctlr)->rxrendez); /* you're kidding, right? */
+ break;
+ case CMtxwakeup:
+ wakeup(&((Ctlr*)e->ctlr)->txrendez); /* you're kidding, right? */
+ break;
+// case CMqsummary:
+// summary(e);
+// break;
+ case CMrxring:
+ rxring(e->ctlr);
+ break;
+ default:
+ error(Ebadarg);
+ }
+ free(c);
+ poperror();
+ return n;
+}
+
+static void
+m10gshutdown(Ether *e)
+{
+ dprint("m10gshutdown\n");
+ m10gdetach(e->ctlr);
+}
+
+static void
+m10gpromiscuous(void *v, int on)
+{
+ Ether *e;
+ int i;
+
+ dprint("m10gpromiscuous\n");
+ e = v;
+ if(on)
+ i = Cpromisc;
+ else
+ i = Cnopromisc;
+ cmd(e->ctlr, i, 0);
+}
+
+static int mcctab[] = { CSleavemc, CSjoinmc };
+static char *mcntab[] = { "leave", "join" };
+
+static void
+m10gmulticast(void *v, uchar *ea, int on)
+{
+ Ether *e;
+ int i;
+
+ dprint("m10gmulticast\n");
+ e = v;
+ if((i = maccmd(e->ctlr, mcctab[on], ea)) != 0)
+ print("m10g: can't %s %E: %d\n", mcntab[on], ea, i);
+}
+
+static void
+m10gpci(void)
+{
+ Pcidev *p;
+ Ctlr *t, *c;
+
+ t = 0;
+ for(p = 0; p = pcimatch(p, Vmyricom, 0); ){
+ switch(p->did){
+ case 0x8: /* 8a */
+ break;
+ case 0x9: /* 8a with msi-x fw */
+ case 0xa: /* 8b */
+ case 0xb: /* 8b2 */
+ case 0xc: /* 2-8b2 */
+ /* untested */
+ break;
+ default:
+ print("etherm10g: unknown myricom did %#ux\n", p->did);
+ continue;
+ }
+ c = malloc(sizeof *c);
+ if(c == nil)
+ continue;
+ c->pcidev = p;
+ c->id = p->did<<16 | p->vid;
+ c->boot = pcicap(p, PciCapVND);
+// kickthebaby(p, c);
+ pcisetbme(p);
+ if(setmem(p, c) == -1){
+ print("m10g: setmem failed\n");
+ free(c);
+ /* cleanup */
+ continue;
+ }
+ if(t)
+ t->next = c;
+ else
+ ctlrs = c;
+ t = c;
+ }
+}
+
+static int
+m10gpnp(Ether *e)
+{
+ Ctlr *c;
+
+ if(ctlrs == nil)
+ m10gpci();
+
+ for(c = ctlrs; c != nil; c = c->next)
+ if(c->active)
+ continue;
+ else if(e->port == 0 || e->port == c->port)
+ break;
+ if(c == nil)
+ return -1;
+ c->active = 1;
+
+ e->ctlr = c;
+ e->port = c->port;
+ e->irq = c->pcidev->intl;
+ e->tbdf = c->pcidev->tbdf;
+ e->mbps = 10000;
+ memmove(e->ea, c->ra, Eaddrlen);
+
+ e->attach = m10gattach;
+ e->detach = m10gshutdown;
+ e->transmit = m10gtransmit;
+ e->interrupt = m10ginterrupt;
+ e->ifstat = m10gifstat;
+ e->ctl = m10gctl;
+// e->power = m10gpower;
+ e->shutdown = m10gshutdown;
+
+ e->arg = e;
+ e->promiscuous = m10gpromiscuous;
+ e->multicast = m10gmulticast;
+
+ return 0;
+}
+
+void
+etherm10glink(void)
+{
+ addethercard("m10g", m10gpnp);
+}
diff --git a/sys/src/9/pc/etherm10g2k.i b/sys/src/9/pc/etherm10g2k.i
new file mode 100755
index 000000000..a12ed3d9c
--- /dev/null
+++ b/sys/src/9/pc/etherm10g2k.i
@@ -0,0 +1,11174 @@
+static char fw2k[] ={
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xb8, 0x88,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf2, 0x02, 0x04, 0x00, 0xc2, 0x90, 0x00, 0x00, 0xf7, 0x82, 0x08, 0x18, 0xe0, 0x01, 0x0b, 0x50,
+ 0x97, 0x93, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x08, 0x18, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x73, 0x18, 0xff, 0xfe, 0x7f, 0x19, 0x00, 0x04, 0xff, 0x8a, 0xa2, 0x68, 0xfe, 0x82, 0xff, 0x00,
+ 0xcf, 0x78, 0xf8, 0x00, 0x20, 0x1a, 0x00, 0x7f, 0xe2, 0x00, 0x08, 0x78, 0xf4, 0x02, 0x00, 0x00,
+ 0x8e, 0x7a, 0x00, 0x08, 0x7f, 0x70, 0xff, 0xf8, 0xcf, 0x78, 0xec, 0x00, 0xce, 0xf0, 0xec, 0x00,
+ 0x7f, 0xf0, 0xff, 0xe8, 0xcf, 0xfc, 0xf5, 0x00, 0x7e, 0xf5, 0x00, 0x08, 0xcf, 0xfc, 0xed, 0x00,
+ 0x7e, 0x71, 0x00, 0x18, 0xc4, 0x7c, 0xe5, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x02, 0xff, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf8, 0xcf, 0x78, 0xe4, 0x00, 0xce, 0x9c, 0xe4, 0x00, 0x7f, 0x9c, 0xff, 0xe8,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x7e, 0xf5, 0x00, 0x08, 0xcf, 0xfc, 0xed, 0x00, 0x7f, 0x1d, 0x00, 0x18,
+ 0xcd, 0xfc, 0xf5, 0x00, 0xff, 0x82, 0x00, 0x0f, 0x74, 0x98, 0xff, 0xfe, 0xc4, 0x20, 0xfc, 0x00,
+ 0xfc, 0x0a, 0xa2, 0x68, 0x7c, 0xa5, 0x00, 0x04, 0x7f, 0x21, 0x00, 0x02, 0xcd, 0x64, 0xc0, 0x00,
+ 0x20, 0x26, 0x00, 0x7f, 0xe2, 0x00, 0x09, 0x40, 0xf4, 0x02, 0x00, 0x00, 0x84, 0x6a, 0x00, 0x08,
+ 0xa3, 0x66, 0xc0, 0x02, 0xff, 0x8a, 0xaa, 0x68, 0xae, 0xfa, 0xf8, 0x02, 0x83, 0xea, 0x00, 0x04,
+ 0xc3, 0x18, 0x44, 0x00, 0xc3, 0x18, 0xdc, 0x00, 0xcf, 0x98, 0x3d, 0x00, 0xcf, 0xf4, 0xfc, 0x00,
+ 0x8e, 0x6a, 0x00, 0x0c, 0xc3, 0xf4, 0x3c, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xc4, 0x20, 0xfc, 0x00,
+ 0xcf, 0x6c, 0x3c, 0x00, 0xc4, 0x20, 0xf5, 0x00, 0xc3, 0x18, 0xec, 0x00, 0x20, 0x72, 0x00, 0x00,
+ 0xe6, 0x00, 0x09, 0x30, 0x94, 0x6a, 0x00, 0x08, 0xe0, 0x00, 0x09, 0x40, 0xf4, 0x02, 0x00, 0x01,
+ 0xf7, 0x82, 0x09, 0x3c, 0xc1, 0x70, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xf4, 0x02, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10, 0x93, 0x16, 0xff, 0xec, 0xff, 0x02, 0x00, 0x00,
+ 0x83, 0x16, 0xff, 0xec, 0x9f, 0x16, 0xff, 0xe8, 0x23, 0x94, 0x00, 0x14, 0xf4, 0x02, 0x00, 0x10,
+ 0xf7, 0x82, 0x09, 0x7c, 0xe0, 0x02, 0x9b, 0xe8, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xe8,
+ 0x2f, 0x94, 0x00, 0x10, 0xb4, 0x7e, 0xf0, 0x04, 0x8f, 0x96, 0xff, 0xec, 0x0f, 0x78, 0x00, 0x01,
+ 0x20, 0x7a, 0x00, 0x05, 0x0f, 0xfc, 0x00, 0x01, 0xe2, 0x00, 0x09, 0x61, 0x9f, 0x96, 0xff, 0xec,
+ 0x23, 0x14, 0x00, 0x10, 0xf7, 0x82, 0x09, 0xb0, 0xe0, 0x00, 0x94, 0xe0, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x17, 0x5b, 0xf1, 0xfe, 0x17, 0x5b, 0xf0, 0xfe, 0x97, 0x5b, 0xf2, 0xff, 0x97, 0x5b, 0xf3,
+ 0xfd, 0x97, 0x5b, 0xf4, 0x7f, 0x79, 0x00, 0x08, 0xfd, 0x17, 0x5b, 0xf5, 0xce, 0x70, 0xf5, 0x00,
+ 0x7e, 0xf5, 0x00, 0x10, 0xce, 0x70, 0xed, 0x00, 0x7f, 0xfd, 0x00, 0x08, 0x7d, 0xed, 0x00, 0x10,
+ 0x5e, 0x71, 0xff, 0x00, 0xcf, 0xfc, 0xdd, 0x00, 0x7d, 0x69, 0x00, 0x18, 0xfe, 0x09, 0xa9, 0x20,
+ 0xcf, 0xfc, 0xd5, 0x00, 0x5e, 0x7c, 0x00, 0xff, 0xfe, 0x09, 0xa9, 0x30, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf3, 0x0a, 0xaa, 0xa8, 0xf3, 0x82, 0x00, 0x00, 0xf4, 0x02, 0x08, 0x00, 0xf7, 0x82, 0x0a, 0x28,
+ 0xe0, 0x02, 0x9c, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x0a, 0xb2, 0xa8, 0xf3, 0x82, 0x00, 0x00,
+ 0xf4, 0x02, 0x00, 0x10, 0xf7, 0x82, 0x0a, 0x40, 0xe0, 0x02, 0x9c, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x0a, 0xaa, 0xb4, 0xff, 0x82, 0x00, 0x7f, 0x0e, 0x81, 0x01, 0x00, 0x9e, 0xfa, 0x00, 0x00,
+ 0x2f, 0xfe, 0x00, 0x01, 0xea, 0x00, 0x0a, 0x4c, 0x0f, 0x78, 0x00, 0x10, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x52, 0x45, 0x56, 0x3d, 0x00, 0x4d, 0x41, 0x43,
+ 0x3d, 0x00, 0x50, 0x57, 0x52, 0x3d, 0x00, 0x50, 0x43, 0x3d, 0x31, 0x30, 0x47, 0x2d, 0x50, 0x43,
+ 0x49, 0x45, 0x2d, 0x38, 0x41, 0x00, 0x2d, 0x43, 0x00, 0x4c, 0x2d, 0x43, 0x00, 0x2d, 0x49, 0x00,
+ 0x2d, 0x51, 0x00, 0x4c, 0x2d, 0x51, 0x00, 0x2d, 0x52, 0x00, 0x4c, 0x2d, 0x52, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0xff, 0x76, 0xfe, 0x00,
+ 0x9f, 0x16, 0xff, 0xf4, 0xff, 0xfb, 0x48, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x0d, 0x0d,
+ 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0xf4, 0xf3, 0x82, 0x0a, 0x68, 0xf4, 0x02, 0x00, 0x04,
+ 0xf7, 0x82, 0x0a, 0xdc, 0xe0, 0x02, 0x9c, 0x48, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0x0b, 0x3c, 0xc3, 0xa0, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xf4, 0xf4, 0x02, 0x00, 0x10,
+ 0x03, 0x7c, 0x00, 0x04, 0xf7, 0x82, 0x0b, 0x00, 0xe0, 0x02, 0x9b, 0xe8, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x0a, 0xa2, 0x90, 0xf4, 0x7b, 0x68, 0x03, 0x83, 0x16, 0xff, 0xf4, 0xf7, 0x82, 0x0b, 0x18,
+ 0xe0, 0x02, 0x9d, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4, 0xc4, 0x7c, 0x40, 0x00,
+ 0xff, 0xa3, 0x48, 0x01, 0x04, 0x20, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x0a, 0xc4,
+ 0x94, 0x16, 0xff, 0xf4, 0xe0, 0x00, 0x0d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0xf4,
+ 0xf3, 0x82, 0x0a, 0x6d, 0xf4, 0x02, 0x00, 0x04, 0xf7, 0x82, 0x0b, 0x54, 0xe0, 0x02, 0x9c, 0x48,
+ 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0b, 0x7c, 0xf3, 0x82, 0x0a, 0x72,
+ 0x8f, 0x96, 0xff, 0xf4, 0x03, 0x7c, 0x00, 0x04, 0xf7, 0x82, 0x0b, 0x74, 0xe0, 0x00, 0x09, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0xf4,
+ 0xf4, 0x02, 0x00, 0x04, 0xf7, 0x82, 0x0b, 0x90, 0xe0, 0x02, 0x9c, 0x48, 0x97, 0x93, 0xff, 0xfc,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0b, 0xbc, 0xc3, 0xa0, 0x00, 0x00, 0x8f, 0x16, 0xff, 0xf4,
+ 0xf4, 0x02, 0x00, 0x0a, 0x03, 0x78, 0x00, 0x04, 0xf7, 0x82, 0x0b, 0xb4, 0xe0, 0x02, 0x9b, 0xe8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x0b, 0x08, 0xf4, 0x09, 0xbc, 0x10, 0x83, 0x16, 0xff, 0xf4,
+ 0xf3, 0x82, 0x0a, 0x77, 0xf4, 0x02, 0x00, 0x0e, 0xf7, 0x82, 0x0b, 0xd4, 0xe0, 0x02, 0x9c, 0x48,
+ 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0b, 0x08, 0x94, 0x16, 0xff, 0xf0,
+ 0x8f, 0x96, 0xff, 0xf4, 0xf3, 0x82, 0x0a, 0x86, 0xf4, 0x02, 0x00, 0x02, 0x0f, 0xfc, 0x00, 0x0e,
+ 0x9f, 0x96, 0xff, 0xec, 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x0c, 0x04, 0xe0, 0x02, 0x9c, 0x48,
+ 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0c, 0x1c, 0xf3, 0x82, 0x0a, 0x89,
+ 0xff, 0x02, 0x00, 0x01, 0xe0, 0x00, 0x0b, 0x08, 0xff, 0x09, 0xb2, 0xb8, 0x83, 0x16, 0xff, 0xec,
+ 0xf4, 0x02, 0x00, 0x03, 0xf7, 0x82, 0x0c, 0x30, 0xe0, 0x02, 0x9c, 0x48, 0x97, 0x93, 0xff, 0xfc,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0c, 0x15, 0xff, 0x02, 0x00, 0x01, 0x83, 0x16, 0xff, 0xec,
+ 0xf3, 0x82, 0x0a, 0x8d, 0xf4, 0x02, 0x00, 0x02, 0xf7, 0x82, 0x0c, 0x54, 0xe0, 0x02, 0x9c, 0x48,
+ 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0c, 0x68, 0xff, 0x82, 0x00, 0x04,
+ 0xe0, 0x00, 0x0b, 0x08, 0xff, 0x89, 0xb2, 0xb8, 0x83, 0x16, 0xff, 0xec, 0xf3, 0x82, 0x0a, 0x90,
+ 0xf4, 0x02, 0x00, 0x02, 0xf7, 0x82, 0x0c, 0x80, 0xe0, 0x02, 0x9c, 0x48, 0x97, 0x93, 0xff, 0xfc,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0c, 0x94, 0xf3, 0x82, 0x0a, 0x93, 0xe0, 0x00, 0x0c, 0x14,
+ 0xff, 0x02, 0x00, 0x02, 0x83, 0x16, 0xff, 0xec, 0xf4, 0x02, 0x00, 0x03, 0xf7, 0x82, 0x0c, 0xa8,
+ 0xe0, 0x02, 0x9c, 0x48, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0c, 0x15,
+ 0xff, 0x02, 0x00, 0x02, 0x83, 0x16, 0xff, 0xec, 0xf3, 0x82, 0x0a, 0x97, 0xf4, 0x02, 0x00, 0x02,
+ 0xf7, 0x82, 0x0c, 0xcc, 0xe0, 0x02, 0x9c, 0x48, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0x0c, 0xe0, 0xf3, 0x82, 0x0a, 0x9a, 0xe0, 0x00, 0x0c, 0x60, 0xff, 0x82, 0x00, 0x03,
+ 0x83, 0x16, 0xff, 0xec, 0xf4, 0x02, 0x00, 0x03, 0xf7, 0x82, 0x0c, 0xf4, 0xe0, 0x02, 0x9c, 0x48,
+ 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0c, 0x61, 0xff, 0x82, 0x00, 0x03,
+ 0x8f, 0x16, 0xff, 0xf0, 0xe0, 0x00, 0x0b, 0x08, 0xff, 0x09, 0xb2, 0xb8, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfb, 0x02, 0x14, 0xc1, 0xff, 0x8a, 0xa2, 0x72, 0xfb, 0x7f, 0x28, 0x00, 0xff, 0x88, 0xa2, 0x80,
+ 0x2d, 0x00, 0x00, 0x02, 0x2c, 0x80, 0x00, 0x09, 0xcf, 0xfc, 0xd4, 0x00, 0x4f, 0xfc, 0xff, 0xfd,
+ 0x4f, 0xfc, 0xff, 0xfb, 0x29, 0x00, 0x00, 0x11, 0xcf, 0xfc, 0xcc, 0x00, 0x27, 0x00, 0x00, 0x21,
+ 0xcf, 0xfc, 0x94, 0x00, 0xcf, 0xfc, 0x74, 0x00, 0x4f, 0xfc, 0xff, 0xbf, 0x23, 0x00, 0x01, 0x01,
+ 0x4f, 0xfc, 0xff, 0x7f, 0x29, 0x80, 0x02, 0x01, 0xcf, 0xfc, 0x34, 0x00, 0xcf, 0xfc, 0x9c, 0x00,
+ 0x24, 0x00, 0x04, 0x01, 0x46, 0x85, 0xff, 0xf7, 0xcf, 0xfc, 0x44, 0x00, 0xcf, 0xfc, 0x6c, 0x00,
+ 0x5f, 0xfd, 0x00, 0x10, 0x4c, 0x05, 0xff, 0x7f, 0x4f, 0xfd, 0xff, 0xdf, 0x46, 0x05, 0xfe, 0xff,
+ 0xcf, 0xfc, 0xc4, 0x00, 0xcf, 0xfc, 0x64, 0x00, 0x4f, 0xfd, 0xf9, 0xff, 0x4f, 0xfd, 0xf7, 0xff,
+ 0x4f, 0xfd, 0xef, 0xff, 0x4f, 0xfd, 0xdf, 0xff, 0x4f, 0xfd, 0xbf, 0xff, 0x4f, 0xfd, 0x7f, 0xff,
+ 0xff, 0x89, 0xa2, 0x80, 0xfb, 0x82, 0x00, 0x00, 0xff, 0x8a, 0xa2, 0x90, 0xfb, 0xff, 0x68, 0x03,
+ 0xff, 0x88, 0xa2, 0x90, 0xf3, 0x82, 0x00, 0xff, 0xff, 0x0a, 0xa2, 0xa0, 0xcf, 0xfc, 0x3c, 0x00,
+ 0x5f, 0xfd, 0x02, 0x00, 0xff, 0x89, 0xa2, 0x90, 0xfb, 0xfb, 0x68, 0x03, 0xff, 0x8a, 0xa2, 0x9f,
+ 0xfb, 0xff, 0x68, 0x03, 0xff, 0x0a, 0xa2, 0x9e, 0xfb, 0xfb, 0x68, 0x03, 0xff, 0x88, 0xa2, 0xb0,
+ 0xff, 0x08, 0xa2, 0xa0, 0x2d, 0x80, 0x00, 0x07, 0xcf, 0xfc, 0xd4, 0x00, 0xfe, 0x02, 0x00, 0x04,
+ 0xcf, 0xfc, 0xdc, 0x00, 0xcf, 0xfc, 0xe5, 0x00, 0x4f, 0x79, 0xf0, 0xff, 0xcf, 0xfc, 0xcc, 0x00,
+ 0x0e, 0x81, 0xff, 0x00, 0x4f, 0x79, 0xbf, 0xff, 0x0e, 0xf4, 0x00, 0x0f, 0x4f, 0x79, 0x7f, 0xff,
+ 0x5f, 0xfc, 0x00, 0x08, 0xff, 0x09, 0xa2, 0xa0, 0xcf, 0xfc, 0xec, 0x00, 0xff, 0x89, 0xa2, 0xb0,
+ 0xff, 0x0a, 0xa2, 0xad, 0xfb, 0xfb, 0x68, 0x03, 0xff, 0x88, 0xa2, 0xd0, 0x0e, 0x81, 0xff, 0xf0,
+ 0x0e, 0xf4, 0x00, 0x0f, 0xcf, 0xfc, 0xd4, 0x00, 0xcf, 0xfc, 0xdc, 0x00, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xcf, 0xfc, 0xcc, 0x00, 0xcf, 0xfc, 0xec, 0x00, 0x4f, 0xfd, 0x00, 0x0f, 0xff, 0x89, 0xa2, 0xd0,
+ 0xfb, 0x89, 0xa2, 0xc0, 0xfb, 0x89, 0xa2, 0xe0, 0xfb, 0x89, 0xa3, 0x10, 0xff, 0x0a, 0xa3, 0x22,
+ 0xfb, 0x7b, 0x28, 0x00, 0xff, 0x88, 0xa3, 0x30, 0xff, 0x0a, 0xa3, 0x40, 0xf8, 0x82, 0x00, 0x01,
+ 0xcf, 0xfc, 0xd4, 0x00, 0x4f, 0xfd, 0x00, 0x07, 0xff, 0x89, 0xa3, 0x30, 0xf7, 0x82, 0x00, 0x44,
+ 0xf7, 0xfb, 0x68, 0x03, 0xff, 0x8a, 0xa3, 0x60, 0xfb, 0xff, 0x68, 0x03, 0xff, 0x8a, 0xa3, 0x5f,
+ 0xf8, 0xff, 0x68, 0x03, 0xff, 0x0a, 0xa3, 0x5e, 0xfb, 0xfb, 0x68, 0x03, 0xff, 0x8a, 0xa3, 0x5d,
+ 0xfb, 0xff, 0x68, 0x03, 0xf4, 0x82, 0x00, 0x05, 0xff, 0x8a, 0xa3, 0x80, 0xf4, 0xff, 0x68, 0x03,
+ 0xff, 0x0a, 0xa3, 0x7f, 0xf7, 0x82, 0x00, 0x54, 0xf7, 0xfb, 0x68, 0x03, 0xff, 0x88, 0xa3, 0x80,
+ 0xff, 0x08, 0xa3, 0x90, 0xfe, 0x82, 0x00, 0x03, 0x4f, 0xfd, 0xff, 0x80, 0xcf, 0xfc, 0xc4, 0x00,
+ 0x5f, 0xfd, 0x00, 0x80, 0xcf, 0x78, 0xec, 0x00, 0xcf, 0xfc, 0x64, 0x00, 0xff, 0x89, 0xa3, 0x80,
+ 0xff, 0x09, 0xa3, 0x90, 0xfb, 0x89, 0xa3, 0xa0, 0xff, 0x8a, 0xa3, 0xb2, 0xfb, 0xff, 0x28, 0x00,
+ 0xff, 0x0a, 0xa3, 0xc0, 0xf8, 0xfb, 0x68, 0x03, 0xff, 0x8a, 0xa3, 0xbf, 0xf7, 0x82, 0x00, 0x5c,
+ 0xf7, 0xff, 0x68, 0x03, 0xff, 0x08, 0xa3, 0xc0, 0xff, 0x88, 0xa3, 0xd0, 0xfa, 0x02, 0x20, 0x00,
+ 0x4f, 0x79, 0xff, 0xf8, 0x4f, 0xfc, 0x81, 0xfc, 0x5f, 0x79, 0x00, 0x02, 0xcf, 0xfc, 0xa5, 0x00,
+ 0x28, 0x00, 0x80, 0x01, 0xcf, 0x78, 0x6c, 0x00, 0xcf, 0xfc, 0x84, 0x00, 0x4f, 0x79, 0xff, 0xdf,
+ 0x4f, 0x79, 0x00, 0x12, 0x4f, 0xfd, 0xff, 0xbf, 0xff, 0x09, 0xa3, 0xc0, 0xcf, 0xfc, 0xc4, 0x00,
+ 0xff, 0x89, 0xa3, 0xd0, 0xff, 0x0a, 0xa3, 0xcd, 0xf7, 0x82, 0x00, 0x64, 0xf7, 0xfb, 0x68, 0x03,
+ 0xfa, 0x82, 0x00, 0x10, 0xff, 0x0a, 0xa3, 0xe0, 0xfa, 0xfb, 0x68, 0x03, 0xff, 0x88, 0xa4, 0x00,
+ 0xfe, 0x88, 0xa4, 0x20, 0xfe, 0x08, 0xa4, 0x10, 0xcf, 0xfc, 0xd4, 0x00, 0x4f, 0xfc, 0xff, 0xfd,
+ 0x4f, 0xfc, 0xff, 0xfb, 0xcf, 0xfc, 0xcc, 0x00, 0xcf, 0xfc, 0x94, 0x00, 0xcf, 0xfc, 0xad, 0x00,
+ 0x4f, 0xfc, 0xff, 0x10, 0xcf, 0xfc, 0x34, 0x00, 0xcf, 0xfc, 0x9c, 0x00, 0xfd, 0x88, 0xa3, 0xf0,
+ 0x2b, 0x00, 0x00, 0x10, 0x4e, 0xf4, 0xff, 0xfc, 0xcf, 0xfc, 0x44, 0x00, 0x2f, 0x00, 0x70, 0x01,
+ 0xce, 0xf4, 0xcc, 0x00, 0x5f, 0xfc, 0x08, 0x00, 0xce, 0x70, 0xb4, 0x00, 0x29, 0x80, 0x00, 0x08,
+ 0xcf, 0xfc, 0xf4, 0x00, 0xce, 0xf4, 0x94, 0x00, 0xce, 0x70, 0x8d, 0x00, 0xcf, 0xfc, 0xa5, 0x00,
+ 0xce, 0xf4, 0x74, 0x00, 0xcd, 0xec, 0x9c, 0x00, 0x4e, 0x70, 0xf4, 0x81, 0xfd, 0x08, 0xa4, 0x70,
+ 0xcd, 0xec, 0x4d, 0x00, 0x4e, 0xf4, 0xff, 0xbf, 0x4f, 0xfd, 0xff, 0xfe, 0x5e, 0x70, 0x04, 0x80,
+ 0x4a, 0x05, 0xff, 0xf0, 0xce, 0x70, 0xf4, 0x00, 0x4e, 0xf4, 0xff, 0x7f, 0xcd, 0xec, 0x74, 0x00,
+ 0x4f, 0xfd, 0xff, 0xfd, 0xfc, 0x88, 0xa3, 0xe0, 0xfc, 0x08, 0xa4, 0x80, 0x4d, 0xec, 0x80, 0x05,
+ 0xce, 0xf4, 0xa4, 0x00, 0x4f, 0xfd, 0xff, 0xfb, 0x0f, 0x01, 0xff, 0xfc, 0x0f, 0x78, 0x7f, 0xff,
+ 0xcd, 0xec, 0x84, 0x00, 0x5e, 0xf5, 0x00, 0x01, 0xcd, 0x68, 0xb4, 0x00, 0xcf, 0xfc, 0x6c, 0x00,
+ 0x5e, 0x70, 0x70, 0x00, 0xce, 0x70, 0xf4, 0x00, 0x4e, 0xf5, 0xfc, 0x0f, 0x5d, 0xec, 0x80, 0x00,
+ 0x5d, 0x68, 0x00, 0x0e, 0x4f, 0xfd, 0xff, 0xef, 0x4f, 0xfd, 0xff, 0xdf, 0xff, 0x0e, 0x80, 0x00,
+ 0xcc, 0xe4, 0x64, 0x00, 0x4d, 0xed, 0xfc, 0x03, 0x4e, 0xf5, 0xfb, 0xff, 0xcc, 0x60, 0x94, 0x00,
+ 0xcd, 0x68, 0x94, 0x00, 0xff, 0x89, 0xa4, 0x00, 0xce, 0x70, 0xf5, 0x00, 0x4d, 0xed, 0xf3, 0xff,
+ 0x4e, 0xf5, 0xf7, 0xff, 0xcd, 0x68, 0xad, 0x00, 0xcc, 0x60, 0xb4, 0x00, 0x4c, 0xe5, 0xc0, 0x0f,
+ 0xfd, 0x89, 0xa3, 0xf0, 0xfe, 0x09, 0xa4, 0x10, 0xfe, 0x89, 0xa4, 0x20, 0xfc, 0x89, 0xa3, 0xe0,
+ 0xfd, 0x09, 0xa4, 0x70, 0xfc, 0x09, 0xa4, 0x80, 0xff, 0x8a, 0xa4, 0xf0, 0xf7, 0x82, 0x00, 0x09,
+ 0xf7, 0xff, 0x68, 0x03, 0xff, 0x0a, 0xa4, 0xee, 0xf7, 0x82, 0x00, 0x1c, 0xf7, 0xfb, 0x68, 0x03,
+ 0xff, 0x08, 0xa5, 0x00, 0xff, 0x88, 0xa5, 0x20, 0xfb, 0x89, 0xa5, 0x10, 0xcf, 0x78, 0x3c, 0x00,
+ 0xff, 0x09, 0xa5, 0x00, 0xcf, 0xfc, 0x3c, 0x00, 0xff, 0x89, 0xa5, 0x20, 0xff, 0x0a, 0xa5, 0x20,
+ 0xfb, 0xfb, 0x68, 0x03, 0xff, 0x8a, 0xa5, 0x30, 0xfb, 0xff, 0x68, 0x03, 0xfb, 0x89, 0xa5, 0x40,
+ 0xfb, 0x89, 0xa5, 0x50, 0xff, 0x8a, 0xa5, 0xb0, 0xf7, 0x82, 0x00, 0x11, 0xf7, 0xff, 0x68, 0x03,
+ 0xff, 0x0a, 0xa5, 0xaf, 0xfb, 0xfb, 0x68, 0x03, 0xfe, 0x08, 0xa5, 0xb0, 0xfe, 0x88, 0xa5, 0xc0,
+ 0xff, 0x08, 0xa5, 0xd0, 0xff, 0x82, 0x00, 0x02, 0x4e, 0x71, 0xf8, 0x00, 0xce, 0xf4, 0x9c, 0x00,
+ 0xcf, 0x78, 0x9c, 0x00, 0xcf, 0x78, 0xfd, 0x00, 0xce, 0xf4, 0xfd, 0x00, 0xfd, 0x82, 0x00, 0x07,
+ 0x5e, 0x71, 0x00, 0x7f, 0xff, 0xbe, 0x90, 0x00, 0x4e, 0x71, 0xbf, 0xff, 0xcf, 0x78, 0xdc, 0x00,
+ 0xce, 0xf4, 0xdc, 0x00, 0xcf, 0x78, 0xfd, 0x00, 0x4e, 0x71, 0x7f, 0xff, 0x5e, 0xf5, 0x00, 0x0f,
+ 0xfe, 0x09, 0xa5, 0xb0, 0xfe, 0x89, 0xa5, 0xc0, 0xff, 0x09, 0xa5, 0xd0, 0xff, 0x8a, 0xa6, 0x72,
+ 0xf8, 0xff, 0x28, 0x00, 0xff, 0x88, 0xa6, 0x70, 0xff, 0x08, 0xa6, 0xd0, 0xfe, 0x06, 0x00, 0x00,
+ 0xcf, 0xfc, 0xa4, 0x00, 0xfe, 0xbe, 0xff, 0xff, 0xcf, 0xfc, 0xe5, 0x00, 0xcf, 0xfc, 0xec, 0x00,
+ 0x5f, 0xfd, 0x1a, 0x80, 0x5f, 0x78, 0x00, 0xa0, 0xff, 0x89, 0xa6, 0x70, 0xff, 0x09, 0xa6, 0xd0,
+ 0xff, 0x8a, 0xa9, 0x12, 0xff, 0x02, 0x00, 0x03, 0xff, 0x7f, 0x28, 0x00, 0xff, 0x88, 0xa9, 0x10,
+ 0xfb, 0x89, 0xa9, 0x30, 0xfb, 0x89, 0xa9, 0x20, 0xcf, 0xfc, 0xa4, 0x00, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xcf, 0xfc, 0xec, 0x00, 0xff, 0x89, 0xa9, 0x10, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x08,
+ 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x07, 0x08, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf7, 0x82, 0x11, 0xdc, 0xe0, 0x00, 0xb8, 0x2c, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x11, 0xe8,
+ 0xe0, 0x00, 0xb9, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x11, 0xf4, 0xe0, 0x00, 0x9e, 0xc8,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xa2, 0x80, 0x70, 0x7e, 0x00, 0x15, 0xea, 0x00, 0x12, 0xa8,
+ 0xfd, 0x82, 0x00, 0x00, 0x70, 0x7e, 0x00, 0x0c, 0xea, 0x00, 0x12, 0xac, 0x4f, 0x29, 0xbf, 0xff,
+ 0xfe, 0x88, 0xe6, 0xd8, 0x4f, 0xfd, 0xff, 0xf7, 0xff, 0x89, 0xa2, 0x80, 0xff, 0x82, 0x34, 0x00,
+ 0xf7, 0x82, 0x00, 0x40, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0xf7, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6,
+ 0xff, 0xfb, 0x18, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0x24,
+ 0xff, 0xf7, 0x28, 0x12, 0x9d, 0xf6, 0x00, 0x14, 0x9d, 0xf6, 0x00, 0x18, 0x9d, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x9d, 0xf6, 0x00, 0x30, 0xff, 0x77, 0x18, 0x0a, 0x8e, 0x76, 0x00, 0x2c,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x0f, 0x81, 0x10, 0x00, 0x0f, 0xfc, 0x00, 0x14,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0xec, 0x9f, 0xf6, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0xfd, 0xf7, 0x28, 0x02, 0xff, 0x88, 0xa2, 0x80,
+ 0x4f, 0xfd, 0xff, 0xf7, 0xff, 0x89, 0xa2, 0x80, 0x4f, 0x29, 0xbf, 0xff, 0x70, 0x7e, 0x00, 0x1d,
+ 0xea, 0x00, 0x12, 0xbc, 0x55, 0x79, 0x40, 0x00, 0xc5, 0x78, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf7, 0x82, 0x12, 0xdc, 0xe0, 0x00, 0xb8, 0x2c, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf7, 0x82, 0x12, 0xfc, 0xe0, 0x00, 0xb9, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf7, 0x82, 0x13, 0x1c, 0xe0, 0x00, 0x9e, 0xc8, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x04, 0xff, 0x88, 0xa4, 0x00, 0xfd, 0x76, 0xff, 0xf0, 0x8f, 0x6a, 0x00, 0x00,
+ 0x7f, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xe3, 0xfd, 0x82, 0x00, 0x80, 0x7e, 0xfd, 0x00, 0x1d,
+ 0x4f, 0x79, 0x1f, 0xff, 0xcf, 0xec, 0xff, 0xc0, 0xcf, 0x78, 0xed, 0x00, 0x9f, 0x6a, 0x00, 0x00,
+ 0x7e, 0x7c, 0xff, 0xfe, 0xff, 0x89, 0xb2, 0xcc, 0xf3, 0x76, 0xff, 0xfc, 0x9d, 0x96, 0xff, 0xf4,
+ 0xfe, 0x09, 0xb2, 0xd0, 0xf7, 0x82, 0x13, 0x80, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xa4, 0x00, 0x8d, 0x96, 0xff, 0xf4, 0xf3, 0x08, 0xb2, 0xcc, 0x7f, 0xfd, 0x00, 0x11,
+ 0x7f, 0xfc, 0xff, 0xe3, 0xcd, 0xec, 0xff, 0xc0, 0xfd, 0x89, 0xb2, 0xd4, 0xf7, 0x82, 0x13, 0xa8,
+ 0xe0, 0x00, 0xc5, 0x0c, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xa4, 0x80,
+ 0xf3, 0x02, 0x00, 0x00, 0x7f, 0x7d, 0x00, 0x1c, 0x70, 0x7e, 0x00, 0x1b, 0xea, 0x00, 0x14, 0x1d,
+ 0x7f, 0x78, 0xff, 0xe6, 0xff, 0x82, 0x13, 0xb4, 0xa3, 0x7a, 0xf8, 0x02, 0xf7, 0x82, 0x14, 0x28,
+ 0xe0, 0x00, 0x8f, 0xd0, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xa4, 0x20,
+ 0xfe, 0xf6, 0xff, 0xe8, 0x8f, 0x76, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xe1,
+ 0x4f, 0x79, 0xfe, 0xff, 0x7f, 0xfd, 0x00, 0x18, 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x76, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x82, 0x14, 0x70, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xff, 0x88, 0xb2, 0xe0, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0x14, 0xd0, 0xff, 0x82, 0xff, 0x00, 0xc0, 0x1e, 0xfc, 0x00, 0xe6, 0x00, 0x14, 0xd1,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa5, 0x10, 0xf3, 0x08, 0xa5, 0x00, 0x7f, 0xfd, 0x00, 0x08,
+ 0x9f, 0x96, 0xff, 0xf4, 0x73, 0x18, 0xff, 0xf8, 0xf7, 0x82, 0x14, 0xc4, 0xe0, 0x00, 0x1c, 0x58,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4, 0xcf, 0xfc, 0x45, 0x00, 0xff, 0x89, 0xa5, 0x10,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x14, 0xff, 0x88, 0xb2, 0xe0, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0x17, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa5, 0x20, 0xff, 0x08, 0xbc, 0x54,
+ 0x7e, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xf8, 0x7e, 0xf4, 0xff, 0xe8, 0x9f, 0x96, 0xff, 0xf4,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe4, 0x00, 0x17, 0xc0, 0x9e, 0x96, 0xff, 0xf0, 0xff, 0x88, 0xbc, 0x48,
+ 0x8e, 0x96, 0xff, 0xf4, 0xc0, 0x76, 0xfa, 0x00, 0xe4, 0x00, 0x17, 0xc1, 0xff, 0x82, 0x00, 0xff,
+ 0xc0, 0x1e, 0xfc, 0x00, 0xe6, 0x00, 0x17, 0xc1, 0xf3, 0x02, 0x00, 0x17, 0x8f, 0x16, 0xff, 0xf0,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x7c, 0x00, 0x03, 0x9f, 0x96, 0xff, 0xec, 0xf7, 0x82, 0x15, 0x58,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x82, 0x00, 0xaa, 0xf3, 0x02, 0x55, 0x55,
+ 0xf7, 0x82, 0x15, 0x6c, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15,
+ 0xf7, 0x82, 0x15, 0x7c, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17,
+ 0xf7, 0x82, 0x15, 0x8c, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x82, 0x00, 0x55,
+ 0xf3, 0x02, 0x2a, 0xaa, 0xf7, 0x82, 0x15, 0xa0, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x15, 0xb0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x15, 0xc0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8e, 0x96, 0xff, 0xec, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0x17, 0x81, 0xf3, 0x82, 0x00, 0xa0,
+ 0xf3, 0x82, 0x00, 0x80, 0xf3, 0x02, 0x55, 0x55, 0xf7, 0x82, 0x15, 0xe4, 0xe0, 0x00, 0x32, 0x70,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x15, 0xf4, 0xe0, 0x00, 0x31, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x16, 0x04, 0xe0, 0x00, 0x31, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x82, 0x00, 0xaa, 0xf3, 0x02, 0x55, 0x55, 0xf7, 0x82, 0x16, 0x18,
+ 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x16, 0x28,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x16, 0x38,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x82, 0x00, 0x55, 0xf3, 0x02, 0x2a, 0xaa,
+ 0xf7, 0x82, 0x16, 0x4c, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15,
+ 0xf7, 0x82, 0x16, 0x5c, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17,
+ 0xf7, 0x82, 0x16, 0x6c, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0xf3, 0x82, 0x00, 0x30, 0xf7, 0x82, 0x16, 0x80, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x16, 0x90, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x16, 0xa0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x13, 0xf7, 0x82, 0x16, 0xb0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x96, 0xff, 0xf4, 0xfe, 0x82, 0x00, 0xff, 0xf3, 0x82, 0x00, 0x00, 0x7f, 0x7d, 0x00, 0x08,
+ 0xff, 0x88, 0xa5, 0x00, 0xcf, 0xfc, 0xec, 0x00, 0xcf, 0xfc, 0xf5, 0x00, 0x73, 0x7c, 0xff, 0xf8,
+ 0xff, 0x89, 0xa5, 0x00, 0xf7, 0x82, 0x16, 0xe0, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xa5, 0x10, 0xf3, 0x08, 0xa5, 0x00, 0xf3, 0x82, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x08,
+ 0x9f, 0x96, 0xff, 0xe8, 0x73, 0x18, 0xff, 0xf8, 0xf7, 0x82, 0x17, 0x04, 0xe0, 0x00, 0x32, 0x70,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x02, 0x00, 0xff, 0xc4, 0x20, 0xf4, 0x00, 0x8e, 0x96, 0xff, 0xe8,
+ 0x8f, 0x16, 0xff, 0xec, 0xcf, 0xf4, 0x45, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0x17, 0x48,
+ 0xff, 0x89, 0xa5, 0x10, 0x8f, 0x96, 0xff, 0xf4, 0xfe, 0x82, 0x00, 0xff, 0x0f, 0x7c, 0x00, 0x01,
+ 0xff, 0x88, 0xa5, 0x20, 0x7f, 0x79, 0x00, 0x08, 0xcf, 0xfc, 0xec, 0x00, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xe0, 0x00, 0x17, 0xc0, 0xff, 0x89, 0xa5, 0x20, 0xf3, 0x08, 0xa5, 0x00, 0x7f, 0xfd, 0x00, 0x08,
+ 0x9f, 0x96, 0xff, 0xe4, 0xf3, 0x82, 0x00, 0x00, 0x73, 0x18, 0xff, 0xf8, 0xf7, 0x82, 0x17, 0x68,
+ 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xe4, 0xff, 0x82, 0x00, 0xff,
+ 0xc4, 0x20, 0xfc, 0x00, 0xcf, 0xf4, 0x45, 0x00, 0xe0, 0x00, 0x17, 0xc0, 0xff, 0x89, 0xa5, 0x10,
+ 0xf3, 0x02, 0x55, 0x55, 0xf7, 0x82, 0x17, 0x90, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x17, 0xa0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x17, 0xb0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0x83, 0x16, 0xff, 0xf4, 0x83, 0x96, 0xff, 0xf0, 0xe0, 0x00, 0x16, 0x74, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x08, 0xa3, 0xd0, 0x7f, 0xf9, 0x00, 0x1e, 0x7f, 0xfe, 0xff, 0xe2,
+ 0xe6, 0x00, 0x18, 0x45, 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x00, 0x18, 0x45, 0xfe, 0x82, 0x00, 0x03,
+ 0x4f, 0xf8, 0xff, 0xfc, 0xff, 0x08, 0xb8, 0x24, 0xcf, 0x78, 0xec, 0x00, 0xcf, 0x7c, 0xf5, 0x00,
+ 0xff, 0x09, 0xa3, 0xd0, 0x7f, 0xf9, 0x00, 0x13, 0x7f, 0xfe, 0xff, 0xe4, 0xe6, 0x00, 0x18, 0x35,
+ 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x00, 0x18, 0x35, 0x20, 0x7e, 0x00, 0x04, 0xe6, 0x00, 0x18, 0x35,
+ 0x20, 0x7e, 0x00, 0x07, 0xe6, 0x00, 0x18, 0x35, 0xff, 0x8a, 0xa3, 0xcd, 0xe0, 0x00, 0x18, 0x4c,
+ 0xf0, 0x7f, 0x68, 0x03, 0xff, 0x08, 0xbc, 0x10, 0xff, 0x8a, 0xa3, 0xcd, 0xe0, 0x00, 0x18, 0x4c,
+ 0xff, 0x7f, 0x68, 0x03, 0xe0, 0x00, 0x18, 0x04, 0xff, 0x89, 0xb8, 0x24, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf7, 0x82, 0x18, 0x6c, 0xe0, 0x00, 0x9e, 0xc8, 0x97, 0x93, 0xff, 0xfc, 0xfe, 0x88, 0xa6, 0xd0,
+ 0xfd, 0xf6, 0xff, 0xec, 0x8f, 0x6e, 0x00, 0x00, 0x7f, 0xf5, 0x00, 0x17, 0xfe, 0x02, 0x00, 0x1f,
+ 0xcd, 0x00, 0xe2, 0x00, 0xcd, 0x7c, 0xd7, 0x80, 0x7f, 0xe9, 0x00, 0x13, 0x4f, 0x79, 0xff, 0xf7,
+ 0xcf, 0x78, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x19, 0xcf, 0x80, 0xe2, 0x00, 0xcf, 0xf4, 0xff, 0x80,
+ 0x9f, 0x6e, 0x00, 0x00, 0xff, 0x89, 0xb2, 0xe4, 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x82, 0x18, 0xb8,
+ 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xa5, 0x50,
+ 0x20, 0x7e, 0x00, 0x02, 0xe6, 0x00, 0x19, 0x25, 0xf3, 0x82, 0x00, 0x00, 0xe2, 0x00, 0x19, 0x10,
+ 0x20, 0x7e, 0x00, 0x03, 0x20, 0x7e, 0x00, 0x01, 0xe6, 0x00, 0x19, 0x01, 0xff, 0xf6, 0xff, 0x5c,
+ 0xff, 0x82, 0x00, 0x00, 0xff, 0x89, 0xa5, 0x40, 0xe0, 0x00, 0x19, 0x3c, 0xff, 0x89, 0xa5, 0x50,
+ 0xff, 0x89, 0xa5, 0x50, 0xff, 0x82, 0x00, 0x60, 0xe0, 0x00, 0x19, 0x3c, 0xff, 0x89, 0xa5, 0x40,
+ 0xe6, 0x00, 0x18, 0xf0, 0xff, 0xf6, 0xfe, 0x00, 0xff, 0x89, 0xa5, 0x50, 0xe0, 0x00, 0x19, 0x08,
+ 0xff, 0x82, 0x01, 0x00, 0xf3, 0x76, 0xff, 0xbc, 0xf7, 0x82, 0x19, 0x34, 0xe0, 0x00, 0x28, 0x78,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x19, 0x00, 0xff, 0xf6, 0xff, 0x5c, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0xa5, 0x40, 0xff, 0x02, 0x00, 0x00, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x19, 0x9d,
+ 0x20, 0x7e, 0x01, 0x00, 0xe2, 0x00, 0x19, 0x71, 0x00, 0x00, 0x00, 0x01, 0xff, 0x82, 0x01, 0x00,
+ 0x9f, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x88, 0xa5, 0x50, 0x9e, 0x82, 0xfe, 0x68,
+ 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x8a, 0xba, 0x40, 0x9e, 0x82, 0xfe, 0x68, 0x9f, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x89, 0xa5, 0x40, 0xfe, 0x89, 0xa5, 0x50, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x82, 0x00, 0xff, 0xc0, 0x1e, 0xfc, 0x00, 0xe6, 0x00, 0x1a, 0x49, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xa5, 0x30, 0xfe, 0x08, 0xa5, 0x50, 0x7f, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xe8,
+ 0x20, 0x7e, 0x00, 0x09, 0xe2, 0x00, 0x1a, 0x48, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x02, 0x19, 0xec,
+ 0xae, 0xfe, 0xf0, 0x02, 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x48,
+ 0x00, 0x00, 0x1a, 0x48, 0x00, 0x00, 0x1a, 0x48, 0x00, 0x00, 0x1a, 0x48, 0x00, 0x00, 0x1a, 0x48,
+ 0x00, 0x00, 0x1a, 0x14, 0x00, 0x00, 0x1a, 0x24, 0x00, 0x00, 0x1a, 0x30, 0x00, 0x00, 0x1a, 0x48,
+ 0x00, 0x00, 0x1a, 0x3c, 0xff, 0x88, 0xa5, 0x40, 0xff, 0xf3, 0x64, 0x01, 0xe0, 0x00, 0x1a, 0x48,
+ 0xfe, 0x09, 0xa5, 0x50, 0xff, 0x88, 0xa5, 0x40, 0xe0, 0x00, 0x1a, 0x1c, 0xff, 0xf3, 0x24, 0x02,
+ 0xff, 0x88, 0xa5, 0x40, 0xe0, 0x00, 0x1a, 0x1c, 0x9f, 0xf1, 0x00, 0x04, 0xf7, 0x82, 0x1a, 0x48,
+ 0xe0, 0x00, 0x19, 0x48, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x82, 0x00, 0xff,
+ 0xc0, 0x1e, 0xfc, 0x00, 0xe6, 0x00, 0x1b, 0x05, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa5, 0x30,
+ 0xfe, 0x08, 0xa5, 0x40, 0x7f, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xe8, 0x20, 0x7e, 0x00, 0x08,
+ 0xe2, 0x00, 0x1b, 0x04, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x02, 0x1a, 0x98, 0xae, 0xfe, 0xf0, 0x02,
+ 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x04, 0x00, 0x00, 0x1a, 0xd0,
+ 0x00, 0x00, 0x1a, 0xe8, 0x00, 0x00, 0x1a, 0xf8, 0x00, 0x00, 0x1b, 0x04, 0x00, 0x00, 0x1b, 0x04,
+ 0x00, 0x00, 0x1b, 0x04, 0x00, 0x00, 0x1b, 0x04, 0x00, 0x00, 0x1a, 0xbc, 0xf7, 0x82, 0x1a, 0xc8,
+ 0xe0, 0x00, 0x18, 0xc4, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x08, 0xa5, 0x50, 0x7f, 0xf1, 0x00, 0x08, 0xfe, 0xfb, 0x58, 0x00, 0xcf, 0xfc, 0xed, 0x00,
+ 0xe0, 0x00, 0x1b, 0x04, 0xff, 0x89, 0xa5, 0x40, 0xff, 0x08, 0xa5, 0x50, 0xfe, 0xfb, 0x18, 0x00,
+ 0xe0, 0x00, 0x1a, 0xdc, 0x7f, 0xf1, 0x00, 0x10, 0xff, 0x88, 0xa5, 0x50, 0x8f, 0xfe, 0x00, 0x00,
+ 0xff, 0x89, 0xa5, 0x40, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf7, 0x82, 0x1b, 0x24, 0xe0, 0x00, 0x9e, 0xc8,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x08, 0xa5, 0xb0, 0x20, 0x7a, 0x00, 0x00, 0xec, 0x00, 0x1c, 0x30,
+ 0x7f, 0xf9, 0x00, 0x01, 0xff, 0x88, 0xbb, 0x40, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x1c, 0x31,
+ 0x7f, 0xf9, 0x00, 0x01, 0x7f, 0xfe, 0xff, 0xe1, 0xe6, 0x00, 0x1c, 0x2c, 0xcd, 0x7c, 0x00, 0x00,
+ 0xfa, 0x8a, 0xb2, 0xa8, 0xfb, 0x02, 0x00, 0x07, 0xfa, 0x02, 0x00, 0x40, 0xfc, 0x8a, 0xe6, 0xfc,
+ 0xfc, 0x0a, 0xaa, 0xb4, 0xcf, 0xe8, 0xb4, 0x00, 0xce, 0xfc, 0xb2, 0x00, 0x20, 0x6a, 0x00, 0x00,
+ 0xec, 0x00, 0x1c, 0x25, 0xcf, 0x68, 0x00, 0x00, 0x7f, 0x79, 0xff, 0xfd, 0xaf, 0xfa, 0xa8, 0x04,
+ 0xcf, 0xfc, 0xef, 0xc0, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x00, 0x1c, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0x8b, 0xe2, 0x00, 0x00, 0x20, 0x5e, 0x00, 0x00, 0xe6, 0x00, 0x1c, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x08, 0xe6, 0xd8, 0x8e, 0x66, 0xff, 0xfc, 0x8e, 0xe6, 0xff, 0xf4, 0xff, 0xfb, 0x18, 0x0a,
+ 0x8d, 0xfa, 0x00, 0x2c, 0x9a, 0x7a, 0x00, 0x30, 0x9c, 0xfa, 0x00, 0x24, 0x9e, 0xfa, 0x00, 0x28,
+ 0xff, 0xe7, 0x28, 0x02, 0x9c, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0x0e, 0x70, 0x00, 0x08, 0x9e, 0x7a, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xfd, 0x89, 0xe6, 0xd8,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0xef, 0x28, 0x00, 0x9f, 0xee, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0xfb, 0xfb, 0x28, 0x02, 0xff, 0x88, 0xb3, 0x44, 0x0f, 0xfc, 0x00, 0x01,
+ 0xff, 0x89, 0xb3, 0x44, 0x0d, 0x68, 0x00, 0x01, 0x0c, 0x60, 0x00, 0x10, 0x20, 0x6a, 0x00, 0x7f,
+ 0xee, 0x00, 0x1b, 0x65, 0x0c, 0xe4, 0x00, 0x24, 0xff, 0x08, 0xa5, 0xb0, 0xe0, 0x00, 0x1c, 0x30,
+ 0x7f, 0xf9, 0x00, 0x01, 0xe0, 0x00, 0x1b, 0x78, 0x0f, 0x68, 0x00, 0x07, 0x7f, 0xf9, 0x00, 0x01,
+ 0x7f, 0xfc, 0xff, 0xe1, 0xff, 0x89, 0xbb, 0x40, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x08,
+ 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x07, 0x08, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x04, 0x93, 0x16, 0xff, 0xf4, 0xf3, 0x02, 0x00, 0x13, 0xf7, 0x82, 0x1c, 0x78,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4, 0xf3, 0x82, 0x00, 0x00,
+ 0xf7, 0x82, 0x1c, 0x8c, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0x74, 0x21, 0x00, 0x18,
+ 0x74, 0x20, 0xff, 0xe8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10, 0x93, 0x16, 0xff, 0xf4,
+ 0x93, 0x96, 0xff, 0xf0, 0x94, 0x16, 0xff, 0xec, 0xc3, 0x1c, 0x00, 0x00, 0xf7, 0x82, 0x1c, 0xc8,
+ 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xec, 0xff, 0x82, 0x00, 0x00,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe4, 0x00, 0x1d, 0x1d, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xf0,
+ 0x9f, 0x96, 0xff, 0xe8, 0x0f, 0x78, 0x00, 0x01, 0x9f, 0x16, 0xff, 0xf0, 0xc3, 0x78, 0x00, 0x00,
+ 0xf7, 0x82, 0x1c, 0xfc, 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xe8,
+ 0x8f, 0x16, 0xff, 0xf4, 0xb4, 0x7a, 0xf8, 0x04, 0x8f, 0x16, 0xff, 0xec, 0x0f, 0xfc, 0x00, 0x01,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe4, 0x00, 0x1c, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x0c, 0xff, 0x88, 0xbc, 0x38, 0xce, 0x9c, 0x00, 0x00, 0xce, 0x20, 0x00, 0x00,
+ 0xcd, 0x9c, 0x40, 0x00, 0xc0, 0x1e, 0xfa, 0x00, 0x93, 0x16, 0xff, 0xf4, 0xe2, 0x00, 0x1d, 0x64,
+ 0xff, 0x02, 0x00, 0x00, 0xc0, 0x6e, 0xfa, 0x00, 0xe2, 0x00, 0x1d, 0x64, 0xcf, 0x7c, 0x3a, 0x00,
+ 0xcf, 0x20, 0x00, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0x1d, 0x9c, 0xc4, 0x78, 0x00, 0x00,
+ 0x8f, 0x96, 0xff, 0xf4, 0xc4, 0x70, 0xf2, 0x00, 0xf3, 0x82, 0x00, 0xff, 0xc0, 0x72, 0xf2, 0x00,
+ 0xe6, 0x00, 0x1d, 0xc9, 0xc3, 0x7c, 0xf0, 0x00, 0xf7, 0x82, 0x1d, 0x94, 0xe0, 0x02, 0x9c, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x1d, 0xc8, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x88, 0xbc, 0x30,
+ 0x9e, 0x16, 0xff, 0xf0, 0x9f, 0x16, 0xff, 0xec, 0xc3, 0xf4, 0x38, 0x00, 0xf7, 0x82, 0x1d, 0xb8,
+ 0xe0, 0x00, 0x1c, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xec, 0x8e, 0x16, 0xff, 0xf0,
+ 0xe0, 0x00, 0x1d, 0x70, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10,
+ 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1d, 0xf0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x82, 0x00, 0xaa, 0xf3, 0x02, 0x05, 0x55, 0xf7, 0x82, 0x1e, 0x04, 0xe0, 0x00, 0x32, 0x70,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x1e, 0x14, 0xe0, 0x00, 0x31, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1e, 0x24, 0xe0, 0x00, 0x31, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x82, 0x00, 0x55, 0xf3, 0x02, 0x02, 0xaa, 0xf7, 0x82, 0x1e, 0x38,
+ 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x1e, 0x48,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1e, 0x58,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x82, 0x00, 0x90, 0xf3, 0x02, 0x05, 0x55,
+ 0xf7, 0x82, 0x1e, 0x6c, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15,
+ 0xf7, 0x82, 0x1e, 0x7c, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17,
+ 0xf7, 0x82, 0x1e, 0x8c, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00,
+ 0xf7, 0x82, 0x1e, 0x9c, 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x01,
+ 0xf7, 0x82, 0x1e, 0xac, 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x02,
+ 0x94, 0x16, 0xff, 0xf0, 0xf7, 0x82, 0x1e, 0xc0, 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc,
+ 0xfe, 0x82, 0x00, 0x00, 0x9e, 0x96, 0xff, 0xf4, 0x94, 0x16, 0xff, 0xec, 0xf3, 0x02, 0x00, 0x17,
+ 0xf7, 0x82, 0x1e, 0xdc, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0xf3, 0x82, 0x00, 0xf0, 0xf7, 0x82, 0x1e, 0xf0, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x1f, 0x00, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1f, 0x10, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x16, 0xff, 0xf0, 0x20, 0x7a, 0x00, 0xc2, 0xe6, 0x00, 0x1f, 0xe8, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x96, 0xff, 0xec, 0x20, 0x7e, 0x00, 0x4f, 0xe6, 0x00, 0x1f, 0xe8, 0xf3, 0x82, 0x00, 0x98,
+ 0xf3, 0x02, 0x00, 0xaa, 0xf7, 0x82, 0x1f, 0x40, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x1f, 0x50, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1f, 0x60, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x10, 0xf7, 0x82, 0x1f, 0x70, 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x10, 0x03, 0x18, 0x00, 0x01, 0x93, 0x16, 0xff, 0xe8, 0xf7, 0x82, 0x1f, 0x88,
+ 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf4, 0x83, 0x16, 0xff, 0xe8,
+ 0x7f, 0xf5, 0x00, 0x08, 0xcf, 0xfc, 0x40, 0x00, 0x20, 0x1a, 0x00, 0x12, 0xe2, 0x00, 0x1f, 0x75,
+ 0x9f, 0x96, 0xff, 0xf4, 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1f, 0xb4, 0xe0, 0x00, 0x31, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0xf0, 0xf7, 0x82, 0x1f, 0xc8,
+ 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x1f, 0xd8,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1f, 0xe8,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4, 0x0f, 0x81, 0x00, 0x51,
+ 0x0f, 0xfc, 0x52, 0x59, 0xc0, 0x7a, 0xfa, 0x00, 0x8f, 0x96, 0xff, 0xf0, 0x8e, 0x96, 0xff, 0xec,
+ 0x7f, 0x7d, 0x00, 0x18, 0x7f, 0xf5, 0x00, 0x10, 0xcf, 0x78, 0xf8, 0x00, 0xe6, 0x74, 0x00, 0x03,
+ 0xcf, 0x78, 0xe8, 0x00, 0xff, 0x09, 0xb3, 0x40, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10,
+ 0xf3, 0x0a, 0xbc, 0x40, 0xf3, 0x82, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x20, 0xf7, 0x82, 0x20, 0x48,
+ 0xe0, 0x00, 0x1c, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x20, 0x54, 0xe0, 0x00, 0x1d, 0xd4,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x8a, 0xb8, 0x88, 0xff, 0x7f, 0x58, 0x98, 0x20, 0x7a, 0x00, 0x01,
+ 0xe6, 0x00, 0x21, 0x3d, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xbc, 0x54, 0x9f, 0x96, 0xff, 0xe8,
+ 0x83, 0x96, 0xff, 0xe8, 0x23, 0x14, 0x00, 0x0c, 0xf4, 0x02, 0x00, 0x04, 0xf7, 0x82, 0x20, 0x88,
+ 0xe0, 0x00, 0x1c, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4, 0x20, 0x7a, 0x3f, 0xff,
+ 0xe2, 0x00, 0x21, 0x49, 0x23, 0x14, 0x00, 0x10, 0x8e, 0x96, 0xff, 0xe8, 0xff, 0x88, 0xbc, 0x48,
+ 0xc3, 0xf4, 0xf0, 0x00, 0xcf, 0xfc, 0xea, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe2, 0x00, 0x21, 0x48,
+ 0xf4, 0x02, 0x00, 0x04, 0xf7, 0x82, 0x20, 0xc0, 0xe0, 0x00, 0x1c, 0xa0, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x16, 0xff, 0xf0, 0x8f, 0x96, 0xff, 0xf4, 0x8e, 0x96, 0xff, 0xe8, 0xf4, 0x02, 0x00, 0x04,
+ 0x2f, 0xfc, 0x00, 0x04, 0xc3, 0xf4, 0xf0, 0x00, 0x23, 0x14, 0x00, 0x14, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x00, 0x21, 0x49, 0xc3, 0x9c, 0x40, 0x00, 0xf7, 0x82, 0x20, 0xf4, 0xe0, 0x00, 0x1c, 0xa0,
+ 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf0, 0x8f, 0x96, 0xff, 0xf4, 0x0f, 0x74, 0x00, 0x04,
+ 0x2e, 0x7c, 0x00, 0x04, 0xc0, 0x7a, 0xe2, 0x00, 0xe2, 0x00, 0x21, 0x48, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x96, 0xff, 0xe8, 0x8d, 0x96, 0xff, 0xec, 0xcf, 0x7c, 0xe8, 0x00, 0xcf, 0xf4, 0xd8, 0x00,
+ 0x0f, 0xfc, 0x00, 0x04, 0xc0, 0x7e, 0xe2, 0x00, 0xe6, 0x00, 0x21, 0x48, 0x03, 0xf8, 0x00, 0x08,
+ 0xf3, 0x89, 0xbc, 0x30, 0xe0, 0x00, 0x21, 0x48, 0xfd, 0x89, 0xbc, 0x38, 0xfe, 0x88, 0xbc, 0x50,
+ 0xe0, 0x00, 0x20, 0x70, 0x9e, 0x96, 0xff, 0xe8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xcf, 0xfe, 0xf4, 0x00, 0xe6, 0x00, 0x21, 0x74,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x89, 0xb2, 0xc0, 0xff, 0x82, 0xbf, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xf7, 0x82, 0x21, 0xb0, 0xe0, 0x00, 0x21, 0x68, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xb2, 0xc0, 0x20, 0x7e, 0x00, 0xfa, 0xe6, 0x00, 0x22, 0x49, 0x20, 0x7e, 0x00, 0xfb,
+ 0xe6, 0x00, 0x22, 0x2d, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x21, 0xc8, 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x21, 0xe0, 0x0f, 0x81, 0x00, 0xfa,
+ 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x21, 0xfc, 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0x14,
+ 0xff, 0x82, 0x00, 0xfa, 0xe0, 0x00, 0x22, 0x48, 0xff, 0x89, 0xb2, 0xc0, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0x2c, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x21, 0xc8, 0xff, 0x02, 0x00, 0x0f, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xb2, 0xc0,
+ 0x73, 0x19, 0x00, 0x18, 0x20, 0x7e, 0x00, 0xf9, 0xe6, 0x00, 0x22, 0xe1, 0x73, 0x18, 0xff, 0xe8,
+ 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x23, 0x35, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0x7c, 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0x94,
+ 0x0f, 0x81, 0x00, 0xf9, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0xb0, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x02, 0x03, 0x52, 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0xcc, 0xff, 0x82, 0x00, 0xf9, 0xff, 0x89, 0xb2, 0xc0,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0xe4,
+ 0x7f, 0x99, 0x00, 0x10, 0xff, 0x02, 0x00, 0x52, 0x9f, 0x02, 0xfe, 0xd8, 0x53, 0x7c, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x23, 0x04,
+ 0x0f, 0x98, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x23, 0x1c, 0xff, 0x82, 0x07, 0x53, 0xe0, 0x00, 0x23, 0x54,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x23, 0x34,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x0e, 0x54, 0x9f, 0x02, 0xfe, 0xd8, 0xe0, 0x00, 0x22, 0x7c,
+ 0xff, 0x02, 0x00, 0x0f, 0x9f, 0x82, 0xfe, 0xd8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04,
+ 0x93, 0x16, 0xff, 0xf4, 0x73, 0x18, 0xff, 0xe8, 0xf7, 0x82, 0x23, 0x84, 0xe0, 0x00, 0x22, 0x54,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4, 0x73, 0x7c, 0xff, 0xf0, 0x73, 0x19, 0x00, 0x18,
+ 0x73, 0x18, 0xff, 0xe8, 0xf7, 0x82, 0x23, 0xa0, 0xe0, 0x00, 0x22, 0x54, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x96, 0xff, 0xf4, 0x73, 0x7c, 0xff, 0xf8, 0x73, 0x19, 0x00, 0x18, 0x73, 0x18, 0xff, 0xe8,
+ 0xf7, 0x82, 0x23, 0xbc, 0xe0, 0x00, 0x22, 0x54, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4,
+ 0x73, 0x7d, 0x00, 0x18, 0x73, 0x18, 0xff, 0xe8, 0xf7, 0x82, 0x23, 0xd4, 0xe0, 0x00, 0x22, 0x54,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xb2, 0xc0, 0x73, 0x19, 0x00, 0x18,
+ 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x24, 0x79, 0x73, 0x18, 0xff, 0xe8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0x00, 0xff, 0x82, 0x01, 0x53,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x24, 0x18, 0x0f, 0x81, 0x00, 0xfb, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0x34,
+ 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0x4c, 0xff, 0x92, 0x00, 0x53, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0x64,
+ 0xff, 0x82, 0x00, 0xfb, 0xff, 0x89, 0xb2, 0xc0, 0x7f, 0x99, 0x00, 0x10, 0x53, 0x7c, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0x84,
+ 0x0f, 0x98, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xb2, 0xc0,
+ 0x73, 0x19, 0x00, 0x18, 0x20, 0x7e, 0x00, 0xfd, 0xe6, 0x00, 0x25, 0x2d, 0x73, 0x18, 0xff, 0xe8,
+ 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x25, 0x79, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0xcc, 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0xe4,
+ 0x0f, 0x81, 0x00, 0xfd, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x25, 0x00, 0xff, 0x82, 0x03, 0x52,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x25, 0x18, 0xff, 0x82, 0x00, 0xfd, 0xff, 0x89, 0xb2, 0xc0, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x25, 0x30, 0xff, 0x82, 0x00, 0x52,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x25, 0x48, 0xff, 0x82, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x25, 0x60, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xe0, 0x00, 0x25, 0x94, 0x7f, 0xfd, 0x00, 0x18, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x25, 0x78, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8, 0xe0, 0x00, 0x24, 0xcc,
+ 0xff, 0x02, 0x00, 0x0f, 0x7f, 0xfc, 0xff, 0xe8, 0xc0, 0x7e, 0x32, 0x00, 0xff, 0x82, 0x03, 0x52,
+ 0xe6, 0x20, 0x00, 0x02, 0x9f, 0x82, 0xfe, 0xd8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xb2, 0xc0,
+ 0x20, 0x7e, 0x00, 0xef, 0xe6, 0x00, 0x26, 0x39, 0xfe, 0x02, 0x01, 0xa4, 0x20, 0x7e, 0x00, 0xfb,
+ 0xe6, 0x00, 0x26, 0xe9, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x25, 0xd8, 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x25, 0xf0, 0x0f, 0x81, 0x00, 0xef,
+ 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x26, 0x0c, 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x26, 0x24,
+ 0xff, 0x82, 0x00, 0xef, 0xff, 0x89, 0xb2, 0xc0, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x26, 0x3c, 0xff, 0x82, 0x00, 0x52, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xfe, 0x82, 0x00, 0x0f, 0xff, 0x9b, 0x5f, 0xff, 0x2e, 0x70, 0x00, 0x08, 0x7f, 0xfd, 0x00, 0x10,
+ 0x0f, 0x7c, 0x00, 0x08, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x26, 0x64,
+ 0x0f, 0xf8, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0x20, 0x72, 0x00, 0x08, 0xee, 0x00, 0x26, 0x54,
+ 0xff, 0x02, 0x00, 0x01, 0xff, 0x9b, 0x5b, 0xff, 0x0e, 0xf0, 0x00, 0x07, 0x7f, 0xfd, 0x00, 0x10,
+ 0xcf, 0x78, 0xef, 0xc0, 0xcf, 0xfc, 0xe0, 0x00, 0xc3, 0x7c, 0xf0, 0x00, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x26, 0xa0, 0x0f, 0x98, 0x00, 0x50,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x26, 0xb8, 0xff, 0x82, 0x03, 0x92, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x26, 0xd0, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0x27, 0x04, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x26, 0xe8, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8, 0xe0, 0x00, 0x25, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0xb2, 0xc0, 0x20, 0x7e, 0x00, 0xef, 0xe6, 0x00, 0x27, 0xd9, 0x20, 0x7e, 0x00, 0xfb,
+ 0xe6, 0x00, 0x27, 0xbd, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x27, 0x58, 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x27, 0x70, 0x0f, 0x81, 0x00, 0xef,
+ 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x27, 0x8c, 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x27, 0xa4,
+ 0xff, 0x82, 0x00, 0xef, 0xe0, 0x00, 0x27, 0xd8, 0xff, 0x89, 0xb2, 0xc0, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x27, 0xbc, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x27, 0x58, 0xff, 0x02, 0x00, 0x0f, 0xff, 0x82, 0x06, 0x13, 0x9f, 0x82, 0xfe, 0xd8,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x82, 0x00, 0x01, 0x9f, 0x9a, 0x00, 0x00, 0xff, 0x82, 0x01, 0x21, 0x9f, 0x82, 0xfe, 0xd8,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x90, 0x1a, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfe, 0x02, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x01, 0xe6, 0x00, 0x28, 0x9d, 0xfe, 0x82, 0x00, 0xd8,
+ 0x20, 0x1e, 0x00, 0x02, 0xe6, 0x00, 0x2a, 0x45, 0xfe, 0x82, 0x02, 0x7c, 0xff, 0x88, 0xb2, 0xc0,
+ 0x20, 0x7e, 0x00, 0xdf, 0xe6, 0x00, 0x29, 0x19, 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x2a, 0x25,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x28, 0xb4,
+ 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x28, 0xcc, 0x0f, 0x81, 0x00, 0xdf, 0x0f, 0xfc, 0x80, 0x58,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x28, 0xe8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x03, 0x52, 0x9f, 0x02, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x29, 0x04,
+ 0xff, 0x82, 0x00, 0xdf, 0xff, 0x89, 0xb2, 0xc0, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x29, 0x1c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x83,
+ 0x9f, 0x02, 0xfe, 0xd8, 0x20, 0x72, 0x00, 0x00, 0xe6, 0x00, 0x29, 0x8d, 0xff, 0x02, 0x00, 0x0f,
+ 0x20, 0x72, 0x00, 0x08, 0xee, 0x00, 0x29, 0x75, 0x00, 0x00, 0x00, 0x01, 0x2e, 0x70, 0x00, 0x08,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x29, 0x50, 0xff, 0x82, 0x00, 0x58,
+ 0x9f, 0x82, 0xfe, 0xd8, 0x20, 0x72, 0x00, 0x08, 0xee, 0x00, 0x29, 0x4c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x29, 0x74,
+ 0x0f, 0xf0, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x29, 0x8c, 0x00, 0x00, 0x00, 0x01, 0x2e, 0xf4, 0x00, 0x08,
+ 0xfe, 0x02, 0x00, 0x58, 0x9e, 0x02, 0xfe, 0xd8, 0x20, 0x76, 0x00, 0x00, 0xee, 0x00, 0x29, 0xe1,
+ 0xff, 0x02, 0x00, 0x0f, 0x2e, 0xf4, 0x00, 0x08, 0x23, 0x18, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x29, 0xbc, 0xfe, 0x02, 0x00, 0x58, 0x9e, 0x02, 0xfe, 0xd8,
+ 0x7f, 0xfc, 0xff, 0xf0, 0x20, 0x76, 0x00, 0x00, 0xee, 0x00, 0x29, 0xb4, 0xff, 0x9b, 0x68, 0x00,
+ 0x23, 0x18, 0x00, 0x01, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x29, 0xe8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x07, 0x53, 0x9f, 0x02, 0xfe, 0xd8,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x00, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2a, 0x0c, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x2a, 0x50,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2a, 0x24,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x0e, 0x54, 0x9f, 0x02, 0xfe, 0xd8, 0xe0, 0x00, 0x28, 0xb4,
+ 0xff, 0x02, 0x00, 0x0f, 0xfe, 0x82, 0x01, 0xa4, 0xe0, 0x00, 0x28, 0x9c, 0xfe, 0x02, 0x00, 0xd8,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xb2, 0xc0,
+ 0x20, 0x7e, 0x00, 0xdf, 0xe6, 0x00, 0x2b, 0x25, 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x2b, 0x09,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2a, 0xa4,
+ 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2a, 0xbc, 0x0f, 0x81, 0x00, 0xdf, 0x0f, 0xfc, 0x80, 0x58,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2a, 0xd8, 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2a, 0xf0, 0xff, 0x82, 0x00, 0xdf,
+ 0xe0, 0x00, 0x2b, 0x24, 0xff, 0x89, 0xb2, 0xc0, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2b, 0x08, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8, 0xe0, 0x00, 0x2a, 0xa4,
+ 0xff, 0x02, 0x00, 0x0f, 0xff, 0x82, 0x00, 0x11, 0x9f, 0x82, 0xfe, 0xd8, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x82, 0x07, 0x13, 0x9f, 0x82, 0xfe, 0xd8, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x82, 0x00, 0x01, 0x9f, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x00, 0x2b, 0xb0, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x38,
+ 0xff, 0x88, 0xb2, 0xc0, 0xce, 0x18, 0x00, 0x00, 0x20, 0x7e, 0x00, 0x7f, 0xe6, 0x00, 0x2c, 0x31,
+ 0xc3, 0x1c, 0x00, 0x00, 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x2c, 0xed, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2b, 0xd0, 0xff, 0x82, 0x01, 0x53,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2b, 0xe8, 0x0f, 0x81, 0x00, 0x7f, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0x04,
+ 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0x1c, 0xff, 0x82, 0x00, 0x7f, 0xff, 0x89, 0xb2, 0xc0,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0x34,
+ 0xff, 0x82, 0x00, 0x52, 0x20, 0x1e, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0xd8, 0xee, 0x00, 0x2c, 0x85,
+ 0xfe, 0x82, 0x00, 0x0f, 0xff, 0xf3, 0x5f, 0xff, 0x23, 0x18, 0x00, 0x08, 0x7f, 0xfd, 0x00, 0x10,
+ 0x0f, 0x7c, 0x00, 0x08, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x2c, 0x64,
+ 0x0f, 0xf8, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0x20, 0x1a, 0x00, 0x08, 0xee, 0x00, 0x2c, 0x54,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0xf3, 0x5b, 0xff, 0x0e, 0x98, 0x00, 0x07, 0xff, 0x02, 0x00, 0x01,
+ 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xef, 0xc0, 0xcf, 0xfc, 0x30, 0x00, 0xc3, 0x7c, 0xf0, 0x00,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0xa4,
+ 0x0f, 0x98, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0xbc, 0xff, 0x82, 0x03, 0x92, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0xd4,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x2d, 0x08, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0xec, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x2b, 0xd0, 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xb2, 0xc0, 0x20, 0x7e, 0x00, 0x8f, 0xe6, 0x00, 0x2d, 0xc1,
+ 0xfe, 0x02, 0x01, 0x80, 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x2e, 0x71, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2d, 0x60, 0xff, 0x82, 0x01, 0x53,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2d, 0x78, 0x0f, 0x81, 0x00, 0x8f, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2d, 0x94,
+ 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2d, 0xac, 0xff, 0x82, 0x00, 0x8f, 0xff, 0x89, 0xb2, 0xc0,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2d, 0xc4,
+ 0xff, 0x82, 0x00, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xfe, 0x82, 0x00, 0x0f, 0xff, 0x9b, 0x5f, 0xff,
+ 0x2e, 0x70, 0x00, 0x08, 0x7f, 0xfd, 0x00, 0x10, 0x0f, 0x7c, 0x00, 0x08, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x2d, 0xec, 0x0f, 0xf8, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8,
+ 0x20, 0x72, 0x00, 0x08, 0xee, 0x00, 0x2d, 0xdc, 0xff, 0x02, 0x00, 0x01, 0xff, 0x9b, 0x5b, 0xff,
+ 0x0e, 0xf0, 0x00, 0x07, 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xef, 0xc0, 0xcf, 0xfc, 0xe0, 0x00,
+ 0xc3, 0x7c, 0xf0, 0x00, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2e, 0x28, 0x0f, 0x98, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2e, 0x40, 0xff, 0x82, 0x03, 0x92,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2e, 0x58, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x2e, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2e, 0x70, 0xff, 0x82, 0x0e, 0x54,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xe0, 0x00, 0x2d, 0x60, 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x88, 0xb2, 0xc0, 0x20, 0x76, 0x00, 0x9f,
+ 0xe6, 0x00, 0x2f, 0x49, 0x20, 0x76, 0x00, 0xfb, 0xe6, 0x00, 0x30, 0xf9, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2e, 0xe0, 0xff, 0x82, 0x01, 0x53,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2e, 0xf8, 0x0f, 0x81, 0x00, 0x9f, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2f, 0x14,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x03, 0x52, 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2f, 0x30, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x82, 0x00, 0x9f, 0xfe, 0x89, 0xb2, 0xc0, 0x7f, 0x99, 0x00, 0x12, 0x53, 0x7c, 0xe0, 0x08,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2f, 0x54,
+ 0x0f, 0x98, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0x20, 0x76, 0x00, 0xaf, 0xe6, 0x00, 0x2f, 0xe5,
+ 0x20, 0x76, 0x00, 0xfb, 0xe6, 0x00, 0x30, 0xdd, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x01, 0x53,
+ 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2f, 0x98, 0x0f, 0x81, 0x00, 0xaf, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2f, 0xb4,
+ 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2f, 0xcc, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0xaf,
+ 0xff, 0x09, 0xb2, 0xc0, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2f, 0xe8, 0xff, 0x82, 0x00, 0x53, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x02, 0x00, 0x58, 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x82, 0x00, 0x0f, 0x8f, 0x02, 0xfe, 0xd8,
+ 0xc0, 0x7a, 0xfc, 0x00, 0xe6, 0x00, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x81, 0x00, 0xff,
+ 0xcf, 0xf8, 0xfc, 0x00, 0xff, 0x02, 0x00, 0x58, 0x74, 0x7c, 0xff, 0xf0, 0x9f, 0x02, 0xfe, 0xd8,
+ 0xff, 0x82, 0x00, 0x0f, 0x8f, 0x02, 0xfe, 0xd8, 0xc0, 0x7a, 0xfc, 0x00, 0xe6, 0x00, 0x30, 0x44,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x81, 0x00, 0xff, 0xcf, 0xf8, 0xfc, 0x00, 0x7f, 0xfc, 0xff, 0xf8,
+ 0xff, 0x02, 0x00, 0x58, 0xc4, 0x20, 0xfd, 0x00, 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x82, 0x00, 0x0f,
+ 0x8f, 0x02, 0xfe, 0xd8, 0xc0, 0x7a, 0xfc, 0x00, 0xe6, 0x00, 0x30, 0x70, 0x00, 0x00, 0x00, 0x01,
+ 0x0f, 0x81, 0x00, 0xff, 0xcf, 0xf8, 0xfc, 0x00, 0xff, 0x02, 0x00, 0x58, 0xc4, 0x20, 0xfd, 0x00,
+ 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x82, 0x00, 0x0f, 0x8f, 0x02, 0xfe, 0xd8, 0xc0, 0x7a, 0xfc, 0x00,
+ 0xe6, 0x00, 0x30, 0x98, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x81, 0x00, 0xff, 0xcf, 0xf8, 0xfc, 0x00,
+ 0xff, 0x02, 0x07, 0x53, 0x7f, 0xfd, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0xd8, 0xc4, 0x20, 0xfd, 0x00,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x30, 0xc4,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x31, 0x18, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x30, 0xdc, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x2f, 0x7c, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x30, 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x0e, 0x54, 0x9f, 0x02, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x2e, 0xe0, 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xb2, 0xc0, 0x20, 0x7e, 0x00, 0xbf, 0xe6, 0x00, 0x31, 0xcd,
+ 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x32, 0x21, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x31, 0x6c, 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x31, 0x84,
+ 0x0f, 0x81, 0x00, 0xbf, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x31, 0xa0, 0xff, 0x82, 0x03, 0x52,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x31, 0xb8, 0xff, 0x82, 0x00, 0xbf, 0xff, 0x89, 0xb2, 0xc0, 0x7f, 0x99, 0x00, 0x12,
+ 0x53, 0x7c, 0x40, 0x07, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x31, 0xd8, 0x0f, 0x98, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x31, 0xf0, 0xff, 0x82, 0x03, 0x52,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x32, 0x08, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x32, 0x3c, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x32, 0x20, 0xff, 0x82, 0x0e, 0x54,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xe0, 0x00, 0x31, 0x6c, 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xb2, 0xc0, 0x20, 0x7e, 0x00, 0xcf,
+ 0xe6, 0x00, 0x32, 0xf5, 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x33, 0xd9, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x32, 0x90, 0xff, 0x82, 0x01, 0x53,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x32, 0xa8, 0x0f, 0x81, 0x00, 0xcf, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x32, 0xc4,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x03, 0x52, 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x32, 0xe0, 0xff, 0x82, 0x00, 0xcf,
+ 0xff, 0x89, 0xb2, 0xc0, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x32, 0xf8, 0x7f, 0x9d, 0x00, 0x10, 0xff, 0x02, 0x00, 0x53, 0x9f, 0x02, 0xfe, 0xd8,
+ 0x53, 0xfc, 0x00, 0x08, 0xfe, 0x82, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xec, 0x00,
+ 0xe6, 0x00, 0x33, 0x18, 0xff, 0x82, 0x00, 0xff, 0x0f, 0x1c, 0x00, 0x50, 0xcf, 0x98, 0xfc, 0x00,
+ 0x7f, 0xfd, 0x00, 0x10, 0x9f, 0x02, 0xfe, 0xd8, 0x5f, 0x7c, 0x00, 0x08, 0xff, 0x82, 0x00, 0x0f,
+ 0x84, 0x02, 0xfe, 0xd8, 0xc0, 0x22, 0xfc, 0x00, 0xe6, 0x00, 0x33, 0x40, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x82, 0xff, 0x00, 0x0f, 0x78, 0x00, 0x50, 0xcf, 0x98, 0xfc, 0x00, 0x7f, 0xfd, 0x00, 0x08,
+ 0x9f, 0x02, 0xfe, 0xd8, 0x5f, 0x7c, 0x00, 0x08, 0xfe, 0x82, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x33, 0x6c, 0x0f, 0x81, 0x00, 0xff, 0x0f, 0x78, 0x00, 0x50,
+ 0xcf, 0x98, 0xfc, 0x00, 0x9f, 0x02, 0xfe, 0xd8, 0x53, 0x7c, 0x80, 0x08, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x33, 0x90, 0x0f, 0x98, 0x00, 0x50,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x33, 0xa8, 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x33, 0xc0, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0x33, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x33, 0xd8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x0e, 0x54, 0x9f, 0x02, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x32, 0x90, 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x74, 0x20, 0xff, 0xf0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x83, 0x5b, 0xd8, 0x70, 0x7e, 0x00, 0x1e,
+ 0xea, 0x00, 0x34, 0x95, 0x00, 0x00, 0x00, 0x01, 0xff, 0x83, 0x5b, 0xd8, 0x0e, 0x81, 0x01, 0x00,
+ 0x5f, 0xfc, 0x00, 0x02, 0xff, 0x83, 0x6b, 0xd8, 0x0f, 0x81, 0x01, 0x00, 0x9f, 0x82, 0xff, 0xf8,
+ 0x8f, 0x02, 0xff, 0xd0, 0x8f, 0x82, 0xff, 0xd0, 0xcf, 0xfc, 0xf2, 0x00, 0x20, 0x7e, 0x00, 0x13,
+ 0xe2, 0x00, 0x34, 0x65, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xf8, 0xc0, 0x7e, 0xec, 0x00,
+ 0xe6, 0x00, 0x34, 0x5c, 0x0f, 0x81, 0x01, 0x00, 0xf7, 0x82, 0x34, 0x94, 0xe0, 0x00, 0x21, 0x68,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x83, 0x5b, 0xd8, 0x4f, 0xfc, 0xff, 0xfd,
+ 0xff, 0x83, 0x6b, 0xd8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0x93, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x34, 0xdc, 0xe0, 0x00, 0x34, 0x30, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x34, 0xec, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x34, 0xf8,
+ 0xe0, 0x00, 0x34, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0x93, 0x16, 0xff, 0xf4, 0x93, 0x96, 0xff, 0xf0, 0xf7, 0x82, 0x35, 0x24, 0xe0, 0x00, 0x34, 0x30,
+ 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4, 0x83, 0x96, 0xff, 0xf0, 0xf7, 0x82, 0x35, 0x38,
+ 0xe0, 0x00, 0x28, 0x78, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x35, 0x44, 0xe0, 0x00, 0x34, 0xa0,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0x93, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x35, 0x6c, 0xe0, 0x00, 0x34, 0x30, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x35, 0x7c, 0xe0, 0x00, 0x2d, 0x3c, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x35, 0x88,
+ 0xe0, 0x00, 0x34, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x02, 0x00, 0x0f,
+ 0x84, 0x02, 0xfe, 0xd8, 0xc0, 0x22, 0xf4, 0x00, 0xe6, 0x00, 0x35, 0xa0, 0x0f, 0x98, 0x00, 0x50,
+ 0x9f, 0x82, 0xfe, 0xd8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xb2, 0xc0, 0xc0, 0x7e, 0x32, 0x00,
+ 0xe6, 0x00, 0x36, 0x91, 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x36, 0x71, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x35, 0xe0, 0x7f, 0x99, 0x00, 0x10,
+ 0xff, 0x02, 0x01, 0x53, 0x9f, 0x02, 0xfe, 0xd8, 0x5e, 0xfc, 0x80, 0x08, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x36, 0x00, 0x0f, 0xf4, 0x00, 0x50,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x36, 0x18, 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0x20, 0x1a, 0x00, 0xfb,
+ 0xe6, 0x00, 0x36, 0x51, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x36, 0x38, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x36, 0x90, 0xf3, 0x09, 0xb2, 0xc0,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x36, 0x50, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x12, 0x00, 0x53, 0x9f, 0x02, 0xfe, 0xd8, 0xe0, 0x00, 0x36, 0x38, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x36, 0x70, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x02, 0x0e, 0x54, 0x9f, 0x02, 0xfe, 0xd8, 0xe0, 0x00, 0x35, 0xe0, 0xff, 0x02, 0x00, 0x0f,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xb2, 0xc0, 0xc0, 0x7e, 0x32, 0x00, 0xe6, 0x00, 0x37, 0x29,
+ 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x38, 0x09, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x36, 0xbc, 0x7f, 0x99, 0x00, 0x10, 0xff, 0x02, 0x01, 0x53,
+ 0x9f, 0x02, 0xfe, 0xd8, 0x5e, 0xfc, 0x80, 0x08, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x36, 0xdc, 0x0f, 0xf4, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x36, 0xf4,
+ 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0x20, 0x1a, 0x00, 0xfb, 0xe6, 0x00, 0x37, 0xe9,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x37, 0x14,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x09, 0xb2, 0xc0, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x37, 0x2c, 0xff, 0x82, 0x00, 0x52, 0x9f, 0x82, 0xfe, 0xd8,
+ 0x20, 0x22, 0x00, 0x08, 0xee, 0x00, 0x37, 0x7d, 0xfe, 0x82, 0x00, 0x0f, 0xff, 0x9f, 0x5f, 0xff,
+ 0x24, 0x20, 0x00, 0x08, 0x7f, 0xfd, 0x00, 0x10, 0x0f, 0x7c, 0x00, 0x08, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x37, 0x5c, 0x0f, 0xf8, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8,
+ 0x20, 0x22, 0x00, 0x08, 0xee, 0x00, 0x37, 0x4c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x9f, 0x5b, 0xff,
+ 0x0e, 0xa0, 0x00, 0x07, 0xff, 0x02, 0x00, 0x01, 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xef, 0xc0,
+ 0xcf, 0xfc, 0x40, 0x00, 0xc3, 0xfc, 0xf0, 0x00, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x37, 0x9c, 0x0f, 0x9c, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x37, 0xb4,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x03, 0x92, 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x37, 0xd0, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0x38, 0x28, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x37, 0xe8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x12, 0x00, 0x53, 0x9f, 0x02, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x37, 0x14, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x38, 0x08, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x0e, 0x54, 0x9f, 0x02, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x36, 0xbc, 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x03, 0x03, 0x02, 0x03, 0x01, 0x02, 0x01, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x07, 0x03, 0x04, 0x03, 0x05, 0x03, 0x04, 0x03, 0x06, 0x03, 0x04, 0x03, 0x05, 0x03, 0x04, 0x03,
+ 0x07, 0x02, 0x03, 0x02, 0x04, 0x02, 0x03, 0x02, 0x05, 0x02, 0x03, 0x02, 0x04, 0x02, 0x03, 0x02,
+ 0x06, 0x02, 0x03, 0x02, 0x04, 0x02, 0x03, 0x02, 0x05, 0x02, 0x03, 0x02, 0x04, 0x02, 0x03, 0x02,
+ 0x07, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01,
+ 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01,
+ 0x06, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01,
+ 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01,
+ 0x07, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x06, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x07, 0x08,
+ 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x61, 0x63,
+ 0x63, 0x65, 0x73, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x42, 0x41, 0x52, 0x32, 0x3a, 0x20, 0x30, 0x78,
+ 0x25, 0x78, 0x2c, 0x20, 0x6c, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x4d, 0x77, 0x72, 0x20, 0x74, 0x6f,
+ 0x20, 0x4d, 0x53, 0x49, 0x58, 0x20, 0x50, 0x42, 0x41, 0x3a, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2c,
+ 0x20, 0x6c, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x72,
+ 0x65, 0x61, 0x64, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x42, 0x41,
+ 0x52, 0x32, 0x3a, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x6c, 0x3d, 0x25, 0x64, 0x0a, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x40, 0x88, 0x96, 0x00, 0x00,
+ 0x8d, 0x16, 0x00, 0x04, 0x93, 0x16, 0xff, 0xe4, 0xcd, 0xa0, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x00,
+ 0xe6, 0x00, 0x54, 0xf5, 0xcc, 0xa4, 0x00, 0x00, 0xff, 0xfa, 0x7f, 0xff, 0xc0, 0x22, 0xfa, 0x00,
+ 0xe2, 0x00, 0x3a, 0x2d, 0x00, 0x00, 0x00, 0x01, 0x2d, 0xa0, 0x80, 0x00, 0x70, 0x66, 0x00, 0x0c,
+ 0xea, 0x00, 0x3a, 0x49, 0xff, 0xbe, 0xf0, 0x00, 0x20, 0x46, 0x00, 0x02, 0xe2, 0x00, 0x73, 0x31,
+ 0xc4, 0x44, 0x00, 0x00, 0xff, 0xbe, 0xf0, 0x00, 0xcf, 0xe4, 0xfc, 0x00, 0x20, 0x7f, 0x00, 0x08,
+ 0xe6, 0x00, 0x54, 0xa1, 0x20, 0x46, 0x00, 0x01, 0xff, 0x3e, 0xfe, 0x00, 0xcf, 0xe4, 0xf4, 0x00,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x3d, 0x55, 0x20, 0x46, 0x00, 0x01, 0xff, 0xbe, 0x80, 0x00,
+ 0xcf, 0xe4, 0xfc, 0x00, 0x20, 0x7f, 0x00, 0x0f, 0xe6, 0x00, 0x3a, 0xf1, 0xff, 0xbe, 0xff, 0x00,
+ 0xcf, 0xe4, 0xfc, 0x00, 0xff, 0x3e, 0x90, 0x00, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x3a, 0xc1,
+ 0xff, 0x02, 0x39, 0x80, 0x22, 0x10, 0x00, 0x0c, 0x98, 0x92, 0x00, 0x08, 0x98, 0x96, 0xff, 0xdc,
+ 0x9c, 0x92, 0x00, 0x04, 0x9f, 0x12, 0x00, 0x00, 0xf7, 0x82, 0x3a, 0xb4, 0xe0, 0x02, 0x99, 0xf4,
+ 0x97, 0x93, 0xff, 0xfc, 0x88, 0x96, 0xff, 0xdc, 0xe0, 0x00, 0x73, 0x30, 0xc4, 0x44, 0x00, 0x00,
+ 0x22, 0x10, 0x00, 0x0c, 0xfe, 0x02, 0x39, 0xaa, 0x98, 0x92, 0x00, 0x08, 0x9c, 0x92, 0x00, 0x04,
+ 0x9e, 0x12, 0x00, 0x00, 0x98, 0x96, 0xff, 0xdc, 0xf7, 0x82, 0x3a, 0xe4, 0xe0, 0x02, 0x99, 0xf4,
+ 0x97, 0x93, 0xff, 0xfc, 0x88, 0x96, 0xff, 0xdc, 0xe0, 0x00, 0x3a, 0xb8, 0x02, 0x10, 0x00, 0x0c,
+ 0x4e, 0xe5, 0x00, 0x0f, 0x0f, 0xf5, 0xff, 0xf1, 0x7a, 0x7c, 0xff, 0xfc, 0xff, 0x0a, 0xaa, 0xa8,
+ 0x79, 0x51, 0x00, 0x04, 0xcf, 0xc8, 0xf0, 0x00, 0x8d, 0x7e, 0x00, 0x0c, 0xce, 0xf4, 0xf0, 0x00,
+ 0x2e, 0x44, 0x00, 0x01, 0xcf, 0x84, 0x00, 0x00, 0xc8, 0x78, 0x00, 0x00, 0xc0, 0x72, 0xfa, 0x00,
+ 0xe6, 0x00, 0x3b, 0x41, 0x03, 0x75, 0xff, 0xf1, 0x4d, 0xec, 0x7f, 0xff, 0x8f, 0x6d, 0x00, 0x04,
+ 0x2e, 0x70, 0x00, 0x01, 0xc0, 0x72, 0xfa, 0x00, 0xe6, 0x00, 0x3b, 0x28, 0x9f, 0x19, 0x00, 0x04,
+ 0x0f, 0x01, 0x01, 0x00, 0xc0, 0x6a, 0xf4, 0x00, 0xe6, 0x00, 0x3c, 0x69, 0x7c, 0x51, 0xff, 0xfd,
+ 0xc9, 0xc8, 0x80, 0x00, 0x8f, 0xce, 0x00, 0x0c, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x3c, 0x6c,
+ 0xfb, 0x8a, 0xb2, 0xa8, 0xff, 0x8a, 0xb2, 0xe6, 0x8e, 0xce, 0x00, 0x04, 0xfa, 0xff, 0x18, 0x00,
+ 0xff, 0x02, 0xff, 0x00, 0xab, 0xca, 0x80, 0x02, 0x7f, 0xf4, 0xff, 0xf8, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x7c, 0x74, 0xff, 0xe8, 0xcc, 0x60, 0xfd, 0x00, 0xff, 0x8a, 0xb2, 0xde, 0xf6, 0xff, 0x18, 0x00,
+ 0xce, 0x74, 0xf4, 0x00, 0x7d, 0xdc, 0xff, 0xf8, 0x87, 0x4e, 0x00, 0x08, 0x20, 0x76, 0x00, 0x00,
+ 0xcd, 0xec, 0xf4, 0x00, 0x7e, 0x71, 0x00, 0x08, 0x7d, 0x51, 0x00, 0x03, 0xe6, 0x58, 0x00, 0x02,
+ 0xcd, 0x68, 0xa0, 0x00, 0xcf, 0x5c, 0xf4, 0x00, 0x7c, 0xdc, 0xff, 0xe8, 0xcc, 0x60, 0xe5, 0x00,
+ 0xce, 0x68, 0xb0, 0x00, 0x5f, 0xd8, 0x00, 0x02, 0xcc, 0xe4, 0xdd, 0x00, 0x7f, 0x79, 0x00, 0x08,
+ 0xfd, 0x8a, 0xe6, 0xf0, 0x7e, 0xf5, 0x00, 0x18, 0x7d, 0x69, 0x00, 0x02, 0xcc, 0xe4, 0xf5, 0x00,
+ 0x79, 0xfd, 0x00, 0x0d, 0x7a, 0xd5, 0x00, 0x0f, 0xcf, 0xe8, 0xd8, 0x00, 0xcc, 0x60, 0xed, 0x00,
+ 0x5a, 0xd4, 0x00, 0x01, 0x7e, 0x71, 0x00, 0x02, 0x7b, 0xdd, 0x00, 0x18, 0x7b, 0x59, 0x00, 0x02,
+ 0xff, 0x02, 0x40, 0x00, 0x9c, 0x7e, 0x00, 0x18, 0xff, 0x7f, 0x28, 0x0c, 0xf9, 0xff, 0x28, 0x10,
+ 0xfa, 0xff, 0x28, 0x12, 0xf6, 0xff, 0x28, 0x14, 0xce, 0x70, 0xd8, 0x00, 0xcc, 0xe4, 0xbd, 0x00,
+ 0x0e, 0xd8, 0x00, 0x14, 0xbe, 0xea, 0xd8, 0x02, 0x97, 0x72, 0x00, 0x1c, 0x20, 0x52, 0x00, 0x00,
+ 0xe6, 0x00, 0x3c, 0x64, 0x9c, 0xf2, 0x00, 0x18, 0xff, 0x8a, 0xbc, 0x70, 0xfe, 0x02, 0x40, 0x00,
+ 0xf9, 0xff, 0x28, 0x10, 0xfa, 0xff, 0x28, 0x12, 0xf6, 0xff, 0x28, 0x14, 0xfc, 0x09, 0xbc, 0x88,
+ 0xcf, 0x58, 0xf8, 0x00, 0xfe, 0x7f, 0x28, 0x0c, 0x97, 0x7a, 0x00, 0x1c, 0x9c, 0xfa, 0x00, 0x18,
+ 0xfe, 0x89, 0xbc, 0x70, 0x7c, 0x51, 0xff, 0xfd, 0xfb, 0x8a, 0xb2, 0xa8, 0xfe, 0x82, 0x00, 0x07,
+ 0xaf, 0x62, 0xb8, 0x04, 0xcf, 0xd0, 0xec, 0x00, 0xcd, 0xf4, 0xfa, 0x00, 0xce, 0x00, 0xda, 0x00,
+ 0xcf, 0x78, 0xe7, 0xc0, 0xab, 0x62, 0xb8, 0x05, 0xfe, 0x02, 0x00, 0x01, 0xc0, 0x7a, 0xe4, 0x00,
+ 0xe6, 0x00, 0x73, 0x31, 0xc4, 0x44, 0x00, 0x00, 0xcf, 0xc8, 0x80, 0x00, 0x8f, 0x7e, 0x00, 0x0c,
+ 0x70, 0x7a, 0x00, 0x07, 0xea, 0x00, 0x73, 0x31, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa5, 0xb0,
+ 0xcf, 0xfc, 0xe7, 0xc0, 0x7a, 0xfe, 0xff, 0xe1, 0xe6, 0x00, 0x73, 0x30, 0x7e, 0xd1, 0x00, 0x03,
+ 0xce, 0xf4, 0xa0, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xfd, 0x0a, 0xe6, 0xf0, 0xcf, 0xf4, 0xd0, 0x00,
+ 0xcf, 0x70, 0xdf, 0xc0, 0xfe, 0x08, 0xe6, 0xd8, 0x8c, 0xfe, 0x00, 0x08, 0xad, 0xf6, 0xd0, 0x02,
+ 0xcf, 0x04, 0xf6, 0x00, 0xcf, 0x58, 0xf4, 0x00, 0xbf, 0x62, 0xb8, 0x04, 0xff, 0x8a, 0xe6, 0xfc,
+ 0xff, 0x02, 0x00, 0x40, 0xce, 0xf4, 0xf8, 0x00, 0x9f, 0x72, 0x00, 0x30, 0xff, 0xf3, 0x18, 0x0a,
+ 0x8f, 0x72, 0x00, 0x2c, 0x9e, 0xf2, 0x00, 0x24, 0x9d, 0xf2, 0x00, 0x28, 0xff, 0xf7, 0x28, 0x02,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0x0c, 0xe4, 0x00, 0x08,
+ 0x9c, 0xf2, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x09, 0xe6, 0xd8, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0xfb, 0x28, 0x00, 0x9f, 0xfa, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0xfa, 0xf3, 0x28, 0x02, 0xff, 0x88, 0xb3, 0x44, 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x89, 0xb3, 0x44, 0xe2, 0x00, 0x3a, 0x70, 0xff, 0xbe, 0x80, 0x00, 0x8c, 0x6e, 0x00, 0x04,
+ 0x83, 0xee, 0x00, 0x00, 0x2f, 0x80, 0x02, 0x00, 0x20, 0x6a, 0x00, 0xff, 0xe2, 0x00, 0x3a, 0xb8,
+ 0xc3, 0x64, 0xfd, 0x00, 0x7f, 0xe9, 0x00, 0x02, 0xff, 0x02, 0x3d, 0x88, 0xae, 0xfe, 0xf0, 0x02,
+ 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x3a, 0xb8, 0x00, 0x00, 0x41, 0x94,
+ 0x00, 0x00, 0x41, 0xa0, 0x00, 0x00, 0x41, 0xac, 0x00, 0x00, 0x41, 0xb8, 0x00, 0x00, 0x41, 0xc4,
+ 0x00, 0x00, 0x41, 0xd8, 0x00, 0x00, 0x41, 0xec, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x42, 0x08,
+ 0x00, 0x00, 0x42, 0x18, 0x00, 0x00, 0x42, 0x28, 0x00, 0x00, 0x42, 0x30, 0x00, 0x00, 0x42, 0x38,
+ 0x00, 0x00, 0x42, 0x40, 0x00, 0x00, 0x42, 0x48, 0x00, 0x00, 0x42, 0x50, 0x00, 0x00, 0x42, 0x5c,
+ 0x00, 0x00, 0x42, 0x70, 0x00, 0x00, 0x42, 0x84, 0x00, 0x00, 0x42, 0x98, 0x00, 0x00, 0x42, 0xac,
+ 0x00, 0x00, 0x42, 0xc8, 0x00, 0x00, 0x42, 0xe4, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x43, 0x10,
+ 0x00, 0x00, 0x43, 0x28, 0x00, 0x00, 0x43, 0x40, 0x00, 0x00, 0x43, 0x48, 0x00, 0x00, 0x43, 0x58,
+ 0x00, 0x00, 0x43, 0x60, 0x00, 0x00, 0x43, 0x68, 0x00, 0x00, 0x43, 0x70, 0x00, 0x00, 0x43, 0x7c,
+ 0x00, 0x00, 0x43, 0x90, 0x00, 0x00, 0x43, 0xa4, 0x00, 0x00, 0x43, 0xb8, 0x00, 0x00, 0x43, 0xcc,
+ 0x00, 0x00, 0x43, 0xe8, 0x00, 0x00, 0x44, 0x04, 0x00, 0x00, 0x44, 0x20, 0x00, 0x00, 0x44, 0x30,
+ 0x00, 0x00, 0x44, 0x48, 0x00, 0x00, 0x44, 0x60, 0x00, 0x00, 0x44, 0x68, 0x00, 0x00, 0x44, 0x78,
+ 0x00, 0x00, 0x44, 0x80, 0x00, 0x00, 0x44, 0x88, 0x00, 0x00, 0x44, 0x90, 0x00, 0x00, 0x44, 0x9c,
+ 0x00, 0x00, 0x44, 0xb0, 0x00, 0x00, 0x44, 0xc4, 0x00, 0x00, 0x44, 0xd8, 0x00, 0x00, 0x44, 0xec,
+ 0x00, 0x00, 0x45, 0x08, 0x00, 0x00, 0x45, 0x24, 0x00, 0x00, 0x45, 0x40, 0x00, 0x00, 0x45, 0x50,
+ 0x00, 0x00, 0x45, 0x68, 0x00, 0x00, 0x45, 0x80, 0x00, 0x00, 0x45, 0x88, 0x00, 0x00, 0x45, 0x98,
+ 0x00, 0x00, 0x45, 0xa0, 0x00, 0x00, 0x45, 0xa8, 0x00, 0x00, 0x45, 0xb0, 0x00, 0x00, 0x45, 0xbc,
+ 0x00, 0x00, 0x45, 0xd0, 0x00, 0x00, 0x45, 0xe4, 0x00, 0x00, 0x45, 0xf8, 0x00, 0x00, 0x46, 0x0c,
+ 0x00, 0x00, 0x46, 0x28, 0x00, 0x00, 0x46, 0x44, 0x00, 0x00, 0x46, 0x60, 0x00, 0x00, 0x46, 0x70,
+ 0x00, 0x00, 0x46, 0x88, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x00, 0x46, 0xa8, 0x00, 0x00, 0x46, 0xb8,
+ 0x00, 0x00, 0x46, 0xc0, 0x00, 0x00, 0x46, 0xc8, 0x00, 0x00, 0x46, 0xd0, 0x00, 0x00, 0x46, 0xe4,
+ 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x47, 0x1c, 0x00, 0x00, 0x47, 0x38, 0x00, 0x00, 0x47, 0x54,
+ 0x00, 0x00, 0x47, 0x78, 0x00, 0x00, 0x47, 0x9c, 0x00, 0x00, 0x47, 0xc0, 0x00, 0x00, 0x47, 0xd8,
+ 0x00, 0x00, 0x47, 0xf8, 0x00, 0x00, 0x48, 0x18, 0x00, 0x00, 0x48, 0x20, 0x00, 0x00, 0x48, 0x38,
+ 0x00, 0x00, 0x48, 0x40, 0x00, 0x00, 0x48, 0x48, 0x00, 0x00, 0x48, 0x50, 0x00, 0x00, 0x48, 0x64,
+ 0x00, 0x00, 0x48, 0x80, 0x00, 0x00, 0x48, 0x9c, 0x00, 0x00, 0x48, 0xb8, 0x00, 0x00, 0x48, 0xd4,
+ 0x00, 0x00, 0x48, 0xf8, 0x00, 0x00, 0x49, 0x1c, 0x00, 0x00, 0x49, 0x40, 0x00, 0x00, 0x49, 0x58,
+ 0x00, 0x00, 0x49, 0x78, 0x00, 0x00, 0x49, 0x98, 0x00, 0x00, 0x49, 0xa0, 0x00, 0x00, 0x49, 0xb8,
+ 0x00, 0x00, 0x49, 0xc0, 0x00, 0x00, 0x49, 0xc8, 0x00, 0x00, 0x49, 0xd0, 0x00, 0x00, 0x49, 0xe4,
+ 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x4a, 0x1c, 0x00, 0x00, 0x4a, 0x38, 0x00, 0x00, 0x4a, 0x54,
+ 0x00, 0x00, 0x4a, 0x78, 0x00, 0x00, 0x4a, 0x9c, 0x00, 0x00, 0x4a, 0xc0, 0x00, 0x00, 0x4a, 0xd8,
+ 0x00, 0x00, 0x4a, 0xf8, 0x00, 0x00, 0x4b, 0x18, 0x00, 0x00, 0x4b, 0x20, 0x00, 0x00, 0x4b, 0x38,
+ 0x00, 0x00, 0x4b, 0x40, 0x00, 0x00, 0x4b, 0x48, 0x00, 0x00, 0x4b, 0x50, 0x00, 0x00, 0x4b, 0x58,
+ 0x00, 0x00, 0x4b, 0x68, 0x00, 0x00, 0x4b, 0x78, 0x00, 0x00, 0x4b, 0x88, 0x00, 0x00, 0x4b, 0x98,
+ 0x00, 0x00, 0x4b, 0xb0, 0x00, 0x00, 0x4b, 0xc8, 0x00, 0x00, 0x4b, 0xe0, 0x00, 0x00, 0x4b, 0xec,
+ 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4c, 0x14, 0x00, 0x00, 0x4c, 0x1c, 0x00, 0x00, 0x4c, 0x28,
+ 0x00, 0x00, 0x4c, 0x30, 0x00, 0x00, 0x4c, 0x38, 0x00, 0x00, 0x4c, 0x40, 0x00, 0x00, 0x4c, 0x50,
+ 0x00, 0x00, 0x4c, 0x68, 0x00, 0x00, 0x4c, 0x80, 0x00, 0x00, 0x4c, 0x98, 0x00, 0x00, 0x4c, 0xb0,
+ 0x00, 0x00, 0x4c, 0xd0, 0x00, 0x00, 0x4c, 0xf0, 0x00, 0x00, 0x4d, 0x10, 0x00, 0x00, 0x4d, 0x24,
+ 0x00, 0x00, 0x4d, 0x40, 0x00, 0x00, 0x4d, 0x5c, 0x00, 0x00, 0x4d, 0x64, 0x00, 0x00, 0x4d, 0x78,
+ 0x00, 0x00, 0x4d, 0x80, 0x00, 0x00, 0x4d, 0x88, 0x00, 0x00, 0x4d, 0x90, 0x00, 0x00, 0x4d, 0xa0,
+ 0x00, 0x00, 0x4d, 0xb8, 0x00, 0x00, 0x4d, 0xd0, 0x00, 0x00, 0x4d, 0xe8, 0x00, 0x00, 0x4e, 0x00,
+ 0x00, 0x00, 0x4e, 0x20, 0x00, 0x00, 0x4e, 0x40, 0x00, 0x00, 0x4e, 0x60, 0x00, 0x00, 0x4e, 0x74,
+ 0x00, 0x00, 0x4e, 0x90, 0x00, 0x00, 0x4e, 0xac, 0x00, 0x00, 0x4e, 0xb4, 0x00, 0x00, 0x4e, 0xc8,
+ 0x00, 0x00, 0x4e, 0xd0, 0x00, 0x00, 0x4e, 0xd8, 0x00, 0x00, 0x4e, 0xe0, 0x00, 0x00, 0x4e, 0xf0,
+ 0x00, 0x00, 0x4f, 0x08, 0x00, 0x00, 0x4f, 0x20, 0x00, 0x00, 0x4f, 0x38, 0x00, 0x00, 0x4f, 0x50,
+ 0x00, 0x00, 0x4f, 0x70, 0x00, 0x00, 0x4f, 0x90, 0x00, 0x00, 0x4f, 0xb0, 0x00, 0x00, 0x4f, 0xc4,
+ 0x00, 0x00, 0x4f, 0xe0, 0x00, 0x00, 0x4f, 0xfc, 0x00, 0x00, 0x50, 0x04, 0x00, 0x00, 0x50, 0x18,
+ 0x00, 0x00, 0x50, 0x20, 0x00, 0x00, 0x50, 0x28, 0x00, 0x00, 0x50, 0x30, 0x00, 0x00, 0x50, 0x38,
+ 0x00, 0x00, 0x50, 0x48, 0x00, 0x00, 0x50, 0x58, 0x00, 0x00, 0x50, 0x68, 0x00, 0x00, 0x50, 0x78,
+ 0x00, 0x00, 0x50, 0x90, 0x00, 0x00, 0x50, 0xa8, 0x00, 0x00, 0x50, 0xc0, 0x00, 0x00, 0x50, 0xcc,
+ 0x00, 0x00, 0x50, 0xe0, 0x00, 0x00, 0x50, 0xf4, 0x00, 0x00, 0x50, 0xfc, 0x00, 0x00, 0x51, 0x08,
+ 0x00, 0x00, 0x51, 0x10, 0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x51, 0x20, 0x00, 0x00, 0x51, 0x30,
+ 0x00, 0x00, 0x51, 0x48, 0x00, 0x00, 0x51, 0x60, 0x00, 0x00, 0x51, 0x78, 0x00, 0x00, 0x51, 0x90,
+ 0x00, 0x00, 0x51, 0xb0, 0x00, 0x00, 0x51, 0xd0, 0x00, 0x00, 0x51, 0xf0, 0x00, 0x00, 0x52, 0x04,
+ 0x00, 0x00, 0x52, 0x20, 0x00, 0x00, 0x52, 0x3c, 0x00, 0x00, 0x52, 0x44, 0x00, 0x00, 0x52, 0x58,
+ 0x00, 0x00, 0x52, 0x60, 0x00, 0x00, 0x52, 0x68, 0x00, 0x00, 0x52, 0x70, 0x00, 0x00, 0x52, 0x80,
+ 0x00, 0x00, 0x52, 0x98, 0x00, 0x00, 0x52, 0xb0, 0x00, 0x00, 0x52, 0xc8, 0x00, 0x00, 0x52, 0xe0,
+ 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x53, 0x20, 0x00, 0x00, 0x53, 0x40, 0x00, 0x00, 0x53, 0x54,
+ 0x00, 0x00, 0x53, 0x70, 0x00, 0x00, 0x53, 0x8c, 0x00, 0x00, 0x53, 0x94, 0x00, 0x00, 0x53, 0xa8,
+ 0x00, 0x00, 0x53, 0xb0, 0x00, 0x00, 0x53, 0xb8, 0x00, 0x00, 0x41, 0x8c, 0x00, 0x00, 0x53, 0xc0,
+ 0x00, 0x00, 0x53, 0xd0, 0x00, 0x00, 0x53, 0xe0, 0x00, 0x00, 0x53, 0xf0, 0x00, 0x00, 0x54, 0x00,
+ 0x00, 0x00, 0x54, 0x18, 0x00, 0x00, 0x54, 0x30, 0x00, 0x00, 0x54, 0x48, 0x00, 0x00, 0x54, 0x54,
+ 0x00, 0x00, 0x54, 0x68, 0x00, 0x00, 0x54, 0x7c, 0x00, 0x00, 0x54, 0x84, 0x00, 0x00, 0x54, 0x90,
+ 0x00, 0x00, 0x54, 0x98, 0x00, 0x00, 0x41, 0x88, 0x93, 0x9a, 0x00, 0x00, 0xe0, 0x00, 0x3a, 0xb8,
+ 0x9c, 0x1a, 0x00, 0x04, 0x7f, 0x9c, 0xff, 0xe8, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00,
+ 0x7f, 0x9c, 0xff, 0xf0, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00, 0x7f, 0x9c, 0xff, 0xf8, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x9b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x1c, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8,
+ 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x1c, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x01,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x41, 0xac, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x41, 0x94, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x41, 0xa0, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x04, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xe8,
+ 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04, 0xfe, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x1b, 0x68, 0x04, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8,
+ 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x42, 0x84, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x42, 0x5c, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x42, 0x70, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x42, 0x50, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x05, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05, 0xfe, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x1b, 0x68, 0x05, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x43, 0xa4, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x43, 0x7c, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x43, 0x90, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x43, 0x70, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x04, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x28, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04, 0xfe, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x1b, 0x28, 0x04, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x44, 0xc4, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x44, 0x9c, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x44, 0xb0, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x44, 0x90, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf8, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x06, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x06, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x06, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xf8,
+ 0xff, 0x9b, 0x68, 0x06, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x60, 0xff, 0xf8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x06, 0xfe, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x06, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x1b, 0x68, 0x06, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x06, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x06, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf8,
+ 0xff, 0x9b, 0x68, 0x06, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x45, 0xe4, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x45, 0xbc, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x45, 0xd0, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x45, 0xb0, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0xe0, 0xff, 0xf8,
+ 0xff, 0x1b, 0x68, 0x04, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04, 0xff, 0x9b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xf8, 0x7f, 0x60, 0xff, 0xe8,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xe8, 0x7f, 0x1c, 0xff, 0xf8,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x02, 0xfe, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x02,
+ 0xfe, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xf0,
+ 0x7f, 0xe0, 0xff, 0xe8, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x04,
+ 0xff, 0x1b, 0x68, 0x02, 0xfe, 0x1b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06,
+ 0x7f, 0xe0, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x04, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xe8,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04, 0xff, 0x9b, 0x68, 0x00, 0xfe, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04, 0xff, 0x9b, 0x68, 0x01, 0xfe, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x47, 0x1c, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0xe0, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x04, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x06, 0xe0, 0x00, 0x46, 0xe4, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x47, 0x00, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x46, 0xd0, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0xe0, 0xff, 0xf8,
+ 0xff, 0x1b, 0x68, 0x05, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05, 0xff, 0x9b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xf8, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x02, 0xfe, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x02,
+ 0xfe, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xf0,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x05,
+ 0xff, 0x1b, 0x68, 0x02, 0xfe, 0x1b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x05, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05, 0xff, 0x9b, 0x68, 0x00, 0xfe, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05, 0xff, 0x9b, 0x68, 0x01, 0xfe, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x48, 0x9c, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x05, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x06, 0xe0, 0x00, 0x48, 0x64, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x48, 0x80, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x48, 0x50, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x04, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0xe0, 0xff, 0xf8,
+ 0xff, 0x1b, 0x28, 0x04, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04,
+ 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04, 0xff, 0x9b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xf8, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x02, 0xfe, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x02,
+ 0xfe, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xf0,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x04,
+ 0xff, 0x1b, 0x68, 0x02, 0xfe, 0x1b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x04, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04, 0xff, 0x9b, 0x68, 0x00, 0xfe, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04, 0xff, 0x9b, 0x68, 0x01, 0xfe, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x4a, 0x1c, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x04, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x06, 0xe0, 0x00, 0x49, 0xe4, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x4a, 0x00, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x49, 0xd0, 0x93, 0x9a, 0x00, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x9c, 0xff, 0xe8, 0xfc, 0x1b, 0x68, 0x07,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00, 0x7f, 0x9c, 0xff, 0xf0, 0xfc, 0x1b, 0x68, 0x07,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xfc, 0x1b, 0x68, 0x07,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00, 0x7f, 0x9c, 0xff, 0xf8, 0xfc, 0x1b, 0x68, 0x07,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x02, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfc, 0x1b, 0x68, 0x07, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8, 0xfc, 0x1b, 0x68, 0x07, 0xff, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfc, 0x1b, 0x68, 0x07, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00,
+ 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xe8,
+ 0xfc, 0x1b, 0x68, 0x07, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0x9c, 0xff, 0xf0, 0xfc, 0x1b, 0x68, 0x07, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x4b, 0x78, 0xf3, 0x9b, 0x68, 0x03, 0xfc, 0x1b, 0x68, 0x07,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x4b, 0x58, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x4b, 0x68, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x4b, 0x50, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8,
+ 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xe8,
+ 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04,
+ 0xff, 0x1b, 0x68, 0x00, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x01,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x4c, 0x80,
+ 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x4c, 0x50, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x4c, 0x68, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x4c, 0x40, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05,
+ 0xff, 0x1b, 0x68, 0x00, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x01,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x4d, 0xd0,
+ 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x4d, 0xa0, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x4d, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x4d, 0x90, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04,
+ 0xff, 0x1b, 0x68, 0x00, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x01,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x4f, 0x20,
+ 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x4e, 0xf0, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x4f, 0x08, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x4e, 0xe0, 0x93, 0x9a, 0x00, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0xfc, 0x1b, 0x28, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00, 0x7f, 0x9c, 0xff, 0xf0, 0xfc, 0x1b, 0x28, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xfc, 0x1b, 0x28, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00, 0x7f, 0x9c, 0xff, 0xf8, 0xfc, 0x1b, 0x28, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x02, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfc, 0x1b, 0x28, 0x06, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8, 0xfc, 0x1b, 0x28, 0x06, 0xff, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfc, 0x1b, 0x28, 0x06, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00,
+ 0xfc, 0x1b, 0x28, 0x06, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xe8,
+ 0xfc, 0x1b, 0x28, 0x06, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0x9c, 0xff, 0xf0, 0xfc, 0x1b, 0x28, 0x06, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x50, 0x58, 0xf3, 0x9b, 0x68, 0x03, 0xfc, 0x1b, 0x28, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x50, 0x38, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x50, 0x48, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x50, 0x30, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8,
+ 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xe8,
+ 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04,
+ 0xff, 0x1b, 0x68, 0x00, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x01,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0xe0, 0x00, 0x51, 0x60,
+ 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0xe0, 0x00, 0x51, 0x30, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x51, 0x48, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x51, 0x20, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05,
+ 0xff, 0x1b, 0x68, 0x00, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x01,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0xe0, 0x00, 0x52, 0xb0,
+ 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0xe0, 0x00, 0x52, 0x80, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x52, 0x98, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x52, 0x70, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x9c, 0x1a, 0x00, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x9c, 0x1a, 0x00, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x9c, 0x1a, 0x00, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00,
+ 0x7f, 0x9c, 0xff, 0xf8, 0x9c, 0x1a, 0x00, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x02,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0x9c, 0xff, 0xf8, 0x9c, 0x1a, 0x00, 0x04, 0xff, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0x9c, 0x1a, 0x00, 0x04, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8, 0x9c, 0x1a, 0x00, 0x04, 0xff, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00, 0x9c, 0x1a, 0x00, 0x04, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xe8, 0x9c, 0x1a, 0x00, 0x04, 0xff, 0x9b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xf0, 0x9c, 0x1a, 0x00, 0x04,
+ 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x53, 0xe0,
+ 0xf3, 0x9b, 0x68, 0x03, 0x9c, 0x1a, 0x00, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x53, 0xc0, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x53, 0xd0, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe2, 0x00, 0x3a, 0x5c, 0xff, 0x3e, 0xfe, 0x00, 0xf3, 0x02, 0x0f, 0xff, 0xc3, 0x64, 0x34, 0x00,
+ 0x98, 0x96, 0xff, 0xdc, 0x9d, 0x16, 0xff, 0xc8, 0x9d, 0x96, 0xff, 0xc4, 0xf7, 0x82, 0x54, 0xc8,
+ 0xe0, 0x00, 0x7c, 0x68, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x96, 0xff, 0xc4, 0x8d, 0x16, 0xff, 0xc8,
+ 0xc3, 0x20, 0x00, 0x00, 0x83, 0xee, 0x00, 0x00, 0xc4, 0x68, 0x00, 0x00, 0xf7, 0x82, 0x54, 0xe8,
+ 0xe0, 0x00, 0x08, 0x84, 0x97, 0x93, 0xff, 0xfc, 0x88, 0x96, 0xff, 0xdc, 0xe0, 0x00, 0x73, 0x30,
+ 0xc4, 0x44, 0x00, 0x00, 0xff, 0x82, 0x38, 0x60, 0xfe, 0x82, 0x00, 0x0f, 0xae, 0x7e, 0xd0, 0x05,
+ 0xff, 0x02, 0x39, 0x60, 0xce, 0xe8, 0xec, 0x00, 0xac, 0x7a, 0xe8, 0x05, 0x7f, 0xc5, 0x00, 0x02,
+ 0xcf, 0xfc, 0xe2, 0x00, 0x2f, 0x14, 0x00, 0x18, 0x93, 0x96, 0xff, 0xf0, 0x9f, 0x96, 0xff, 0xe0,
+ 0x93, 0x96, 0xff, 0xe8, 0x93, 0x96, 0xff, 0xec, 0x70, 0x7a, 0x00, 0x1d, 0xea, 0x00, 0x55, 0x39,
+ 0x2b, 0x94, 0x00, 0x14, 0xcb, 0xf8, 0x00, 0x00, 0x70, 0x66, 0x00, 0x0c, 0xea, 0x00, 0x55, 0x51,
+ 0xff, 0xbe, 0xf0, 0x00, 0x20, 0x46, 0x00, 0x02, 0xe2, 0x00, 0x72, 0xfd, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xcf, 0xe4, 0xfc, 0x00, 0x20, 0x7f, 0x00, 0x08, 0xe6, 0x00, 0x72, 0xa9, 0x20, 0x46, 0x00, 0x01,
+ 0xff, 0x3e, 0xfe, 0x00, 0xcf, 0xe4, 0xf4, 0x00, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x58, 0x4d,
+ 0x20, 0x46, 0x00, 0x01, 0xff, 0xbe, 0xff, 0xfc, 0xcf, 0xe4, 0xfc, 0x00, 0xff, 0x3e, 0xfd, 0xf8,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x58, 0x35, 0x20, 0x46, 0x00, 0x01, 0xff, 0xbe, 0xff, 0xfc,
+ 0xcf, 0xe4, 0xfc, 0x00, 0xff, 0x3e, 0xfd, 0xf0, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x57, 0x6d,
+ 0x20, 0x46, 0x00, 0x01, 0xff, 0xbe, 0x80, 0x00, 0xce, 0xe4, 0xfc, 0x00, 0x20, 0x77, 0x00, 0x0f,
+ 0xe6, 0x00, 0x57, 0x51, 0xff, 0xbe, 0xff, 0x00, 0xce, 0x64, 0xfc, 0x00, 0xff, 0x3e, 0x90, 0x00,
+ 0xc0, 0x72, 0xf2, 0x00, 0xe6, 0x00, 0x57, 0x35, 0xff, 0xa2, 0x80, 0x00, 0xc0, 0x76, 0xfa, 0x00,
+ 0xe6, 0x00, 0x56, 0xf1, 0x20, 0x46, 0x00, 0x02, 0xff, 0xbe, 0x00, 0x00, 0xcf, 0xe4, 0xfc, 0x00,
+ 0x20, 0x7f, 0x00, 0x09, 0xe6, 0x00, 0x56, 0xb1, 0x20, 0x46, 0x00, 0x02, 0x90, 0xde, 0x00, 0x04,
+ 0x90, 0xde, 0x00, 0x00, 0x22, 0x10, 0x00, 0x0c, 0xfe, 0x02, 0x39, 0xc7, 0x9c, 0x92, 0x00, 0x04,
+ 0x98, 0x92, 0x00, 0x08, 0x9e, 0x12, 0x00, 0x00, 0x9b, 0x96, 0xff, 0xd4, 0x9c, 0x16, 0xff, 0xd0,
+ 0x9c, 0x96, 0xff, 0xcc, 0xf7, 0x82, 0x56, 0x20, 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc,
+ 0x8c, 0x16, 0xff, 0xd0, 0x8c, 0x96, 0xff, 0xcc, 0x8b, 0x96, 0xff, 0xd4, 0x02, 0x10, 0x00, 0x0c,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xca, 0xdc, 0xc0, 0x00, 0x8f, 0x16, 0xff, 0xe4, 0xff, 0x88, 0xb2, 0xe4,
+ 0xfe, 0x02, 0x30, 0x00, 0x8e, 0xfa, 0x00, 0x04, 0x7f, 0xfd, 0x00, 0x0f, 0x84, 0x96, 0xff, 0xe0,
+ 0x0f, 0x01, 0x00, 0x70, 0xcf, 0x74, 0xf4, 0x00, 0xcf, 0x78, 0xfd, 0x00, 0x8f, 0x96, 0xff, 0xe4,
+ 0xce, 0x74, 0xe4, 0x00, 0x7e, 0xf5, 0x00, 0x16, 0x83, 0xfe, 0x00, 0x08, 0xcf, 0x78, 0xe5, 0x00,
+ 0x7e, 0xf4, 0xff, 0xea, 0xcf, 0x78, 0xed, 0x00, 0x22, 0x10, 0x00, 0x0c, 0x5f, 0x79, 0x4a, 0x00,
+ 0xfe, 0x02, 0x00, 0x01, 0xc4, 0x54, 0x00, 0x00, 0x73, 0x9c, 0xff, 0xf8, 0x9f, 0x12, 0x00, 0x00,
+ 0x9e, 0x12, 0x00, 0x04, 0x90, 0x12, 0x00, 0x08, 0xc3, 0x6c, 0x00, 0x00, 0xf7, 0x82, 0x56, 0xa8,
+ 0xe0, 0x00, 0xa3, 0x30, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x73, 0x30, 0xf4, 0x02, 0x00, 0x00,
+ 0xe2, 0x00, 0x55, 0xec, 0xff, 0x82, 0xff, 0xf8, 0xcf, 0xe4, 0xfc, 0x00, 0x0f, 0xfd, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x82, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x68, 0x9b, 0x82, 0xfe, 0x68,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x82, 0x00, 0x04, 0xcf, 0xe4, 0xfc, 0x00,
+ 0xcf, 0xdc, 0xf8, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xca, 0xfc, 0xc0, 0x00,
+ 0xe2, 0x00, 0x55, 0xdc, 0xff, 0xbe, 0x00, 0x00, 0xff, 0x82, 0x7f, 0xf8, 0xcf, 0xe4, 0xfc, 0x00,
+ 0x0f, 0xfd, 0x80, 0x01, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68,
+ 0x9b, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x82, 0x00, 0x04,
+ 0xcf, 0xe4, 0xfc, 0x00, 0xcf, 0xdc, 0xf8, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xca, 0xfc, 0xc0, 0x00, 0xff, 0x0a, 0xb2, 0xa8, 0xca, 0xe0, 0xf0, 0x00, 0x4f, 0xe5, 0x00, 0x0f,
+ 0xcf, 0xd4, 0xf8, 0x00, 0xca, 0xfc, 0xe2, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xff, 0x0a, 0xaa, 0xa8, 0xca, 0xe0, 0xf0, 0x00, 0x4f, 0xe5, 0x00, 0x0f, 0xcf, 0xd4, 0xf8, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0x0a, 0xfd, 0xff, 0xf1, 0xe2, 0x00, 0x55, 0xa8,
+ 0xff, 0xbe, 0x80, 0x00, 0xff, 0x88, 0xa2, 0x80, 0xfd, 0x82, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x0c,
+ 0x7f, 0xfc, 0xff, 0xe1, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x00, 0x58, 0x29, 0x9f, 0xde, 0x00, 0x00,
+ 0xff, 0x88, 0xa2, 0x80, 0x70, 0x7e, 0x00, 0x0c, 0xea, 0x00, 0x58, 0x28, 0x4f, 0xfd, 0xff, 0xf7,
+ 0xfe, 0x88, 0xe6, 0xd8, 0xff, 0x89, 0xa2, 0x80, 0xff, 0x82, 0x34, 0x00, 0xf7, 0x82, 0x00, 0x40,
+ 0xf7, 0xf7, 0x68, 0x08, 0xff, 0xf7, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00,
+ 0xfe, 0x02, 0x00, 0x24, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xfe, 0x77, 0x28, 0x12,
+ 0x9d, 0xf6, 0x00, 0x14, 0x9d, 0xf6, 0x00, 0x18, 0x9d, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0x9d, 0xf6, 0x00, 0x30, 0xff, 0x77, 0x18, 0x0a, 0x8e, 0x76, 0x00, 0x2c, 0x0f, 0xf4, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0f, 0x81, 0x10, 0x00, 0x0f, 0xfc, 0x00, 0x14, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0xa2, 0xec, 0x9f, 0xf6, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28,
+ 0x9e, 0x02, 0xff, 0xb0, 0xfd, 0xf7, 0x28, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xca, 0xdc, 0xc0, 0x00, 0xe2, 0x00, 0x55, 0x90, 0xff, 0xbe, 0xff, 0xfc, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x95, 0x5e, 0x00, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xca, 0xdc, 0xc0, 0x00, 0xe2, 0x00, 0x55, 0x78,
+ 0xff, 0xbe, 0xff, 0xfc, 0x2f, 0x80, 0x02, 0x00, 0xcf, 0x64, 0xfd, 0x00, 0xab, 0x66, 0xfd, 0x02,
+ 0x8a, 0x7a, 0x00, 0x04, 0x20, 0x6a, 0x00, 0xff, 0xca, 0xdc, 0xc0, 0x00, 0xe2, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xe9, 0x00, 0x02, 0xff, 0x02, 0x58, 0x88, 0xae, 0xfe, 0xf0, 0x02,
+ 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x5c, 0x98, 0x00, 0x00, 0x5c, 0xa0,
+ 0x00, 0x00, 0x5c, 0xb0, 0x00, 0x00, 0x5c, 0xc0, 0x00, 0x00, 0x5c, 0xd0, 0x00, 0x00, 0x5c, 0xe0,
+ 0x00, 0x00, 0x5c, 0xf8, 0x00, 0x00, 0x5d, 0x10, 0x00, 0x00, 0x5d, 0x28, 0x00, 0x00, 0x5d, 0x34,
+ 0x00, 0x00, 0x5d, 0x48, 0x00, 0x00, 0x5d, 0x5c, 0x00, 0x00, 0x5d, 0x64, 0x00, 0x00, 0x5d, 0x70,
+ 0x00, 0x00, 0x5d, 0x78, 0x00, 0x00, 0x5d, 0x80, 0x00, 0x00, 0x5d, 0x8c, 0x00, 0x00, 0x5d, 0x9c,
+ 0x00, 0x00, 0x5d, 0xb4, 0x00, 0x00, 0x5d, 0xcc, 0x00, 0x00, 0x5d, 0xe4, 0x00, 0x00, 0x5d, 0xfc,
+ 0x00, 0x00, 0x5e, 0x1c, 0x00, 0x00, 0x5e, 0x3c, 0x00, 0x00, 0x5e, 0x5c, 0x00, 0x00, 0x5e, 0x70,
+ 0x00, 0x00, 0x5e, 0x8c, 0x00, 0x00, 0x5e, 0xa8, 0x00, 0x00, 0x5e, 0xb0, 0x00, 0x00, 0x5e, 0xc4,
+ 0x00, 0x00, 0x5e, 0xcc, 0x00, 0x00, 0x5e, 0xd4, 0x00, 0x00, 0x5e, 0xdc, 0x00, 0x00, 0x5e, 0xec,
+ 0x00, 0x00, 0x5f, 0x04, 0x00, 0x00, 0x5f, 0x1c, 0x00, 0x00, 0x5f, 0x34, 0x00, 0x00, 0x5f, 0x4c,
+ 0x00, 0x00, 0x5f, 0x6c, 0x00, 0x00, 0x5f, 0x8c, 0x00, 0x00, 0x5f, 0xac, 0x00, 0x00, 0x5f, 0xc0,
+ 0x00, 0x00, 0x5f, 0xdc, 0x00, 0x00, 0x5f, 0xf8, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x14,
+ 0x00, 0x00, 0x60, 0x1c, 0x00, 0x00, 0x60, 0x24, 0x00, 0x00, 0x60, 0x2c, 0x00, 0x00, 0x60, 0x3c,
+ 0x00, 0x00, 0x60, 0x54, 0x00, 0x00, 0x60, 0x6c, 0x00, 0x00, 0x60, 0x84, 0x00, 0x00, 0x60, 0x9c,
+ 0x00, 0x00, 0x60, 0xbc, 0x00, 0x00, 0x60, 0xdc, 0x00, 0x00, 0x60, 0xfc, 0x00, 0x00, 0x61, 0x10,
+ 0x00, 0x00, 0x61, 0x2c, 0x00, 0x00, 0x61, 0x48, 0x00, 0x00, 0x61, 0x50, 0x00, 0x00, 0x61, 0x64,
+ 0x00, 0x00, 0x61, 0x6c, 0x00, 0x00, 0x61, 0x74, 0x00, 0x00, 0x61, 0x7c, 0x00, 0x00, 0x61, 0x8c,
+ 0x00, 0x00, 0x61, 0xa4, 0x00, 0x00, 0x61, 0xbc, 0x00, 0x00, 0x61, 0xd4, 0x00, 0x00, 0x61, 0xec,
+ 0x00, 0x00, 0x62, 0x0c, 0x00, 0x00, 0x62, 0x2c, 0x00, 0x00, 0x62, 0x4c, 0x00, 0x00, 0x62, 0x60,
+ 0x00, 0x00, 0x62, 0x7c, 0x00, 0x00, 0x62, 0x98, 0x00, 0x00, 0x62, 0xa0, 0x00, 0x00, 0x62, 0xb4,
+ 0x00, 0x00, 0x62, 0xbc, 0x00, 0x00, 0x62, 0xc4, 0x00, 0x00, 0x62, 0xcc, 0x00, 0x00, 0x62, 0xe4,
+ 0x00, 0x00, 0x63, 0x04, 0x00, 0x00, 0x63, 0x24, 0x00, 0x00, 0x63, 0x44, 0x00, 0x00, 0x63, 0x64,
+ 0x00, 0x00, 0x63, 0x8c, 0x00, 0x00, 0x63, 0xb4, 0x00, 0x00, 0x63, 0xdc, 0x00, 0x00, 0x63, 0xf8,
+ 0x00, 0x00, 0x64, 0x1c, 0x00, 0x00, 0x64, 0x40, 0x00, 0x00, 0x64, 0x48, 0x00, 0x00, 0x64, 0x64,
+ 0x00, 0x00, 0x64, 0x6c, 0x00, 0x00, 0x64, 0x74, 0x00, 0x00, 0x64, 0x7c, 0x00, 0x00, 0x64, 0x94,
+ 0x00, 0x00, 0x64, 0xb4, 0x00, 0x00, 0x64, 0xd4, 0x00, 0x00, 0x64, 0xf4, 0x00, 0x00, 0x65, 0x14,
+ 0x00, 0x00, 0x65, 0x3c, 0x00, 0x00, 0x65, 0x64, 0x00, 0x00, 0x65, 0x8c, 0x00, 0x00, 0x65, 0xa8,
+ 0x00, 0x00, 0x65, 0xcc, 0x00, 0x00, 0x65, 0xf0, 0x00, 0x00, 0x65, 0xf8, 0x00, 0x00, 0x66, 0x14,
+ 0x00, 0x00, 0x66, 0x1c, 0x00, 0x00, 0x66, 0x24, 0x00, 0x00, 0x66, 0x2c, 0x00, 0x00, 0x66, 0x44,
+ 0x00, 0x00, 0x66, 0x64, 0x00, 0x00, 0x66, 0x84, 0x00, 0x00, 0x66, 0xa4, 0x00, 0x00, 0x66, 0xc4,
+ 0x00, 0x00, 0x66, 0xec, 0x00, 0x00, 0x67, 0x14, 0x00, 0x00, 0x67, 0x3c, 0x00, 0x00, 0x67, 0x58,
+ 0x00, 0x00, 0x67, 0x7c, 0x00, 0x00, 0x67, 0xa0, 0x00, 0x00, 0x67, 0xa8, 0x00, 0x00, 0x67, 0xc4,
+ 0x00, 0x00, 0x67, 0xcc, 0x00, 0x00, 0x67, 0xd4, 0x00, 0x00, 0x67, 0xdc, 0x00, 0x00, 0x67, 0xe8,
+ 0x00, 0x00, 0x67, 0xfc, 0x00, 0x00, 0x68, 0x10, 0x00, 0x00, 0x68, 0x24, 0x00, 0x00, 0x68, 0x38,
+ 0x00, 0x00, 0x68, 0x54, 0x00, 0x00, 0x68, 0x70, 0x00, 0x00, 0x68, 0x8c, 0x00, 0x00, 0x68, 0x9c,
+ 0x00, 0x00, 0x68, 0xb4, 0x00, 0x00, 0x68, 0xcc, 0x00, 0x00, 0x68, 0xd4, 0x00, 0x00, 0x68, 0xe4,
+ 0x00, 0x00, 0x68, 0xec, 0x00, 0x00, 0x68, 0xf4, 0x00, 0x00, 0x68, 0xfc, 0x00, 0x00, 0x69, 0x10,
+ 0x00, 0x00, 0x69, 0x2c, 0x00, 0x00, 0x69, 0x48, 0x00, 0x00, 0x69, 0x64, 0x00, 0x00, 0x69, 0x80,
+ 0x00, 0x00, 0x69, 0xa4, 0x00, 0x00, 0x69, 0xc8, 0x00, 0x00, 0x69, 0xec, 0x00, 0x00, 0x6a, 0x04,
+ 0x00, 0x00, 0x6a, 0x24, 0x00, 0x00, 0x6a, 0x44, 0x00, 0x00, 0x6a, 0x4c, 0x00, 0x00, 0x6a, 0x64,
+ 0x00, 0x00, 0x6a, 0x6c, 0x00, 0x00, 0x6a, 0x74, 0x00, 0x00, 0x6a, 0x7c, 0x00, 0x00, 0x6a, 0x90,
+ 0x00, 0x00, 0x6a, 0xac, 0x00, 0x00, 0x6a, 0xc8, 0x00, 0x00, 0x6a, 0xe4, 0x00, 0x00, 0x6b, 0x00,
+ 0x00, 0x00, 0x6b, 0x24, 0x00, 0x00, 0x6b, 0x48, 0x00, 0x00, 0x6b, 0x6c, 0x00, 0x00, 0x6b, 0x84,
+ 0x00, 0x00, 0x6b, 0xa4, 0x00, 0x00, 0x6b, 0xc4, 0x00, 0x00, 0x6b, 0xcc, 0x00, 0x00, 0x6b, 0xe4,
+ 0x00, 0x00, 0x6b, 0xec, 0x00, 0x00, 0x6b, 0xf4, 0x00, 0x00, 0x6b, 0xfc, 0x00, 0x00, 0x6c, 0x10,
+ 0x00, 0x00, 0x6c, 0x2c, 0x00, 0x00, 0x6c, 0x48, 0x00, 0x00, 0x6c, 0x64, 0x00, 0x00, 0x6c, 0x80,
+ 0x00, 0x00, 0x6c, 0xa4, 0x00, 0x00, 0x6c, 0xc8, 0x00, 0x00, 0x6c, 0xec, 0x00, 0x00, 0x6d, 0x04,
+ 0x00, 0x00, 0x6d, 0x24, 0x00, 0x00, 0x6d, 0x44, 0x00, 0x00, 0x6d, 0x4c, 0x00, 0x00, 0x6d, 0x64,
+ 0x00, 0x00, 0x6d, 0x6c, 0x00, 0x00, 0x6d, 0x74, 0x00, 0x00, 0x6d, 0x7c, 0x00, 0x00, 0x6d, 0x88,
+ 0x00, 0x00, 0x6d, 0x9c, 0x00, 0x00, 0x6d, 0xb0, 0x00, 0x00, 0x6d, 0xc4, 0x00, 0x00, 0x6d, 0xd8,
+ 0x00, 0x00, 0x6d, 0xf4, 0x00, 0x00, 0x6e, 0x10, 0x00, 0x00, 0x6e, 0x2c, 0x00, 0x00, 0x6e, 0x3c,
+ 0x00, 0x00, 0x6e, 0x54, 0x00, 0x00, 0x6e, 0x6c, 0x00, 0x00, 0x6e, 0x74, 0x00, 0x00, 0x6e, 0x84,
+ 0x00, 0x00, 0x6e, 0x8c, 0x00, 0x00, 0x6e, 0x94, 0x00, 0x00, 0x6e, 0x9c, 0x00, 0x00, 0x6e, 0xb0,
+ 0x00, 0x00, 0x6e, 0xcc, 0x00, 0x00, 0x6e, 0xe8, 0x00, 0x00, 0x6f, 0x04, 0x00, 0x00, 0x6f, 0x20,
+ 0x00, 0x00, 0x6f, 0x44, 0x00, 0x00, 0x6f, 0x68, 0x00, 0x00, 0x6f, 0x8c, 0x00, 0x00, 0x6f, 0xa4,
+ 0x00, 0x00, 0x6f, 0xc4, 0x00, 0x00, 0x6f, 0xe4, 0x00, 0x00, 0x6f, 0xec, 0x00, 0x00, 0x70, 0x04,
+ 0x00, 0x00, 0x70, 0x0c, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x00, 0x70, 0x30,
+ 0x00, 0x00, 0x70, 0x4c, 0x00, 0x00, 0x70, 0x68, 0x00, 0x00, 0x70, 0x84, 0x00, 0x00, 0x70, 0xa0,
+ 0x00, 0x00, 0x70, 0xc4, 0x00, 0x00, 0x70, 0xe8, 0x00, 0x00, 0x71, 0x0c, 0x00, 0x00, 0x71, 0x24,
+ 0x00, 0x00, 0x71, 0x44, 0x00, 0x00, 0x71, 0x64, 0x00, 0x00, 0x71, 0x6c, 0x00, 0x00, 0x71, 0x84,
+ 0x00, 0x00, 0x71, 0x8c, 0x00, 0x00, 0x71, 0x94, 0x00, 0x00, 0x5c, 0x8c, 0x00, 0x00, 0x71, 0x9c,
+ 0x00, 0x00, 0x71, 0xb0, 0x00, 0x00, 0x71, 0xc4, 0x00, 0x00, 0x71, 0xd8, 0x00, 0x00, 0x71, 0xec,
+ 0x00, 0x00, 0x72, 0x08, 0x00, 0x00, 0x72, 0x24, 0x00, 0x00, 0x72, 0x40, 0x00, 0x00, 0x72, 0x50,
+ 0x00, 0x00, 0x72, 0x68, 0x00, 0x00, 0x72, 0x80, 0x00, 0x00, 0x72, 0x88, 0x00, 0x00, 0x72, 0x98,
+ 0x00, 0x00, 0x72, 0xa0, 0x00, 0x00, 0x5c, 0x88, 0x9b, 0x5e, 0x00, 0x00, 0x9a, 0x5e, 0x00, 0x04,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x58, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x00, 0xff, 0x5f, 0x68, 0x02,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8,
+ 0xff, 0xdf, 0x68, 0x01, 0xff, 0x5f, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8, 0xff, 0xdf, 0x28, 0x00, 0xff, 0x5f, 0x68, 0x02,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x01,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x5c, 0xc0,
+ 0xfb, 0x5f, 0x68, 0x03, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x5c, 0xa0, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x5c, 0xb0, 0xfb, 0x5f, 0x28, 0x02,
+ 0x9b, 0x5e, 0x00, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8,
+ 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x5d, 0xcc, 0xfb, 0x5f, 0x68, 0x03,
+ 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x5d, 0x9c, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x5d, 0xb4,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x5d, 0x8c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x5f, 0x1c, 0xfb, 0x5f, 0x68, 0x03,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x5e, 0xec, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x5f, 0x04,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x5e, 0xdc, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x28, 0x04, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04,
+ 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x28, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x60, 0x6c, 0xfb, 0x5f, 0x68, 0x03,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x60, 0x3c, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x60, 0x54,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x60, 0x2c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf8,
+ 0xff, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8,
+ 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06, 0xff, 0x5f, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06,
+ 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06, 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06,
+ 0xff, 0x5f, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0x7f, 0x50, 0xff, 0xf8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x06, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x06, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x06, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xf8,
+ 0xff, 0xdf, 0x68, 0x06, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x61, 0xbc, 0xfb, 0x5f, 0x68, 0x03,
+ 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x61, 0x8c, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x61, 0xa4,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x61, 0x7c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xe8,
+ 0x7f, 0x50, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x04, 0xff, 0xdf, 0x68, 0x00, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x04, 0xff, 0xdf, 0x68, 0x01, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x04, 0xff, 0xdf, 0x28, 0x00, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf8, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x04, 0xff, 0xdf, 0x68, 0x02, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xe8, 0x7f, 0x58, 0xff, 0xf8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x68, 0x00,
+ 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xe8, 0x7f, 0x58, 0xff, 0xf8, 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x68, 0x01, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xe8, 0x7f, 0x58, 0xff, 0xf8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x28, 0x00,
+ 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xe8,
+ 0x7f, 0x50, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xff, 0x5f, 0x68, 0x06,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xe8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xff, 0xdf, 0x68, 0x00, 0xfe, 0xdf, 0x68, 0x06,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xff, 0xdf, 0x68, 0x01,
+ 0xfe, 0xdf, 0x68, 0x06, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03,
+ 0xe0, 0x00, 0x63, 0x24, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf8,
+ 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xff, 0x5f, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x62, 0xe4, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x63, 0x04,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x62, 0xcc, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x05, 0xff, 0xdf, 0x68, 0x00, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x05, 0xff, 0xdf, 0x68, 0x01, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x05, 0xff, 0xdf, 0x28, 0x00, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x05, 0xff, 0xdf, 0x68, 0x02, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x68, 0x00,
+ 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8, 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x68, 0x01, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x28, 0x00,
+ 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x68, 0x03, 0xff, 0x5f, 0x68, 0x06,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xff, 0xdf, 0x68, 0x00, 0xfe, 0xdf, 0x68, 0x06,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xff, 0xdf, 0x68, 0x01,
+ 0xfe, 0xdf, 0x68, 0x06, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03,
+ 0xe0, 0x00, 0x64, 0xd4, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf8,
+ 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x28, 0x02, 0xff, 0x5f, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x64, 0x94, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x64, 0xb4,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x64, 0x7c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf8, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x28, 0x04, 0xff, 0xdf, 0x68, 0x00, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x28, 0x04, 0xff, 0xdf, 0x68, 0x01, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x28, 0x04, 0xff, 0xdf, 0x28, 0x00, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x28, 0x04, 0xff, 0xdf, 0x68, 0x02, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x68, 0x00,
+ 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8, 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x28, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x68, 0x01, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x28, 0x00,
+ 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf8, 0xff, 0xdf, 0x28, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xff, 0x5f, 0x68, 0x06,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04, 0xff, 0xdf, 0x68, 0x00, 0xfe, 0xdf, 0x68, 0x06,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04, 0xff, 0xdf, 0x68, 0x01,
+ 0xfe, 0xdf, 0x68, 0x06, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03,
+ 0xe0, 0x00, 0x66, 0x84, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf8,
+ 0xff, 0xdf, 0x28, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xff, 0x5f, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x66, 0x44, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x66, 0x64,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x66, 0x2c, 0x9b, 0x5e, 0x00, 0x00, 0xfa, 0x5f, 0x68, 0x07,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0xfa, 0x5f, 0x68, 0x07,
+ 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf0, 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf8, 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x68, 0x02,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd8, 0xff, 0xf8,
+ 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd8, 0xff, 0xf8, 0xfa, 0x5f, 0x68, 0x07,
+ 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd8, 0xff, 0xf8, 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x68, 0x02,
+ 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0xfa, 0x5f, 0x68, 0x07,
+ 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0, 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x68, 0x01,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x68, 0x10,
+ 0xfb, 0x5f, 0x68, 0x03, 0xfa, 0x5f, 0x68, 0x07, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x67, 0xe8, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x67, 0xfc,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x67, 0xdc, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x28, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04,
+ 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xe8,
+ 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x28, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0xe0, 0x00, 0x69, 0x48, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0xe0, 0x00, 0x69, 0x10, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x69, 0x2c,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x68, 0xfc, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x28, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05,
+ 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0,
+ 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x28, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x68, 0x03, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0xe0, 0x00, 0x6a, 0xc8, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x28, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0xe0, 0x00, 0x6a, 0x90, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6a, 0xac,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6a, 0x7c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x28, 0x04, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x28, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04,
+ 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8,
+ 0xff, 0x5f, 0x28, 0x04, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0,
+ 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x28, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x28, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04,
+ 0xff, 0x5f, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04,
+ 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0xe0, 0x00, 0x6c, 0x48, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x28, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0xe0, 0x00, 0x6c, 0x10, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6c, 0x2c,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6b, 0xfc, 0x9b, 0x5e, 0x00, 0x00, 0xfa, 0x5f, 0x28, 0x06,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0xfa, 0x5f, 0x28, 0x06,
+ 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf0, 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf8, 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x68, 0x02,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd8, 0xff, 0xf8,
+ 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd8, 0xff, 0xf8, 0xfa, 0x5f, 0x28, 0x06,
+ 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd8, 0xff, 0xf8, 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x68, 0x02,
+ 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0xfa, 0x5f, 0x28, 0x06,
+ 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0, 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x68, 0x01,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x6d, 0xb0,
+ 0xfb, 0x5f, 0x68, 0x03, 0xfa, 0x5f, 0x28, 0x06, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x6d, 0x88, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6d, 0x9c,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6d, 0x7c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x28, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04,
+ 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xe8,
+ 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x28, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0xe0, 0x00, 0x6e, 0xe8, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0xe0, 0x00, 0x6e, 0xb0, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6e, 0xcc,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6e, 0x9c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x28, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05,
+ 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0,
+ 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x28, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x68, 0x03, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0xe0, 0x00, 0x70, 0x68, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x28, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0xe0, 0x00, 0x70, 0x30, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x70, 0x4c,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x70, 0x1c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0x9a, 0x5e, 0x00, 0x04, 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf0, 0x9a, 0x5e, 0x00, 0x04, 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x9a, 0x5e, 0x00, 0x04, 0xff, 0xdf, 0x28, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf8, 0x9a, 0x5e, 0x00, 0x04,
+ 0xff, 0xdf, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8,
+ 0x7f, 0xd8, 0xff, 0xf8, 0x9a, 0x5e, 0x00, 0x04, 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x68, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd8, 0xff, 0xf8,
+ 0x9a, 0x5e, 0x00, 0x04, 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd8, 0xff, 0xf8, 0x9a, 0x5e, 0x00, 0x04,
+ 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x9a, 0x5e, 0x00, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x9a, 0x5e, 0x00, 0x04, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0, 0x9a, 0x5e, 0x00, 0x04,
+ 0xff, 0xdf, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03,
+ 0xe0, 0x00, 0x71, 0xc4, 0xfb, 0x5f, 0x68, 0x03, 0x9a, 0x5e, 0x00, 0x04, 0xfb, 0x5f, 0x28, 0x02,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x71, 0x9c, 0xfb, 0x5f, 0x28, 0x02,
+ 0xe0, 0x00, 0x71, 0xb0, 0xfb, 0x5f, 0x28, 0x02, 0xe2, 0x00, 0x55, 0x64, 0xff, 0x3e, 0xfe, 0x00,
+ 0xf3, 0x02, 0x0f, 0xff, 0xc3, 0x64, 0x34, 0x00, 0x9b, 0x96, 0xff, 0xd4, 0x9c, 0x16, 0xff, 0xd0,
+ 0x9c, 0x96, 0xff, 0xcc, 0xf7, 0x82, 0x72, 0xd0, 0xe0, 0x00, 0x7c, 0x68, 0x97, 0x93, 0xff, 0xfc,
+ 0xc3, 0x20, 0x00, 0x00, 0xf7, 0x82, 0x72, 0xe0, 0xe0, 0x00, 0x08, 0x28, 0x97, 0x93, 0xff, 0xfc,
+ 0x8b, 0x96, 0xff, 0xd4, 0x94, 0x5e, 0x00, 0x00, 0x8c, 0x16, 0xff, 0xd0, 0x8c, 0x96, 0xff, 0xcc,
+ 0xca, 0xdc, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x84, 0x16, 0xff, 0xe0,
+ 0xca, 0xdc, 0xc0, 0x00, 0x43, 0xed, 0x00, 0x07, 0xc3, 0x54, 0x00, 0x00, 0x9a, 0x96, 0xff, 0xd8,
+ 0x9d, 0x96, 0xff, 0xc4, 0xf7, 0x82, 0x73, 0x20, 0xe0, 0x00, 0x1c, 0xa0, 0x97, 0x93, 0xff, 0xfc,
+ 0x8a, 0x96, 0xff, 0xd8, 0x8d, 0x96, 0xff, 0xc4, 0xe0, 0x00, 0x56, 0x38, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x82, 0x00, 0x1f, 0xfd, 0x02, 0x00, 0x01,
+ 0xcf, 0x80, 0xda, 0x00, 0xcf, 0x98, 0xff, 0x80, 0xce, 0xfc, 0xd4, 0x00, 0x5e, 0x74, 0x00, 0x02,
+ 0xfe, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8, 0x2f, 0x7c, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xc8,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x73, 0x6d, 0x5f, 0xf4, 0x00, 0x06, 0xff, 0x83, 0x6b, 0xe1,
+ 0x8f, 0x02, 0xff, 0xc8, 0x0f, 0x78, 0x00, 0x09, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xea, 0x00, 0x73, 0x89, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8,
+ 0x0f, 0x7c, 0x00, 0x02, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x73, 0xa5,
+ 0x00, 0x00, 0x00, 0x01, 0x2d, 0xee, 0x00, 0x01, 0xea, 0x00, 0x73, 0x50, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0x82, 0x00, 0x1f, 0xfd, 0x02, 0x00, 0x01, 0xcf, 0x80, 0xda, 0x00,
+ 0xcf, 0x98, 0xff, 0x80, 0xce, 0xfc, 0xd4, 0x00, 0x5e, 0x74, 0x00, 0x02, 0xfe, 0x03, 0x6b, 0xe1,
+ 0x8f, 0x82, 0xff, 0xc8, 0x2f, 0x7c, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xea, 0x00, 0x73, 0xf9, 0x5f, 0xf4, 0x00, 0x06, 0xff, 0x83, 0x6b, 0xe1, 0x8f, 0x02, 0xff, 0xc8,
+ 0x0f, 0x78, 0x00, 0x09, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0x15,
+ 0x00, 0x00, 0x00, 0x01, 0xfe, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8, 0x0f, 0x7c, 0x00, 0x02,
+ 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0x31, 0x00, 0x00, 0x00, 0x01,
+ 0x2d, 0xec, 0x00, 0x01, 0x20, 0x6e, 0x00, 0x11, 0xee, 0x00, 0x73, 0xdc, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8, 0x2f, 0x7c, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xc8,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0x5d, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x00, 0x04,
+ 0xf7, 0x83, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8, 0x0f, 0x7c, 0x00, 0x09, 0x8f, 0x82, 0xff, 0xc8,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0x7d, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x6b, 0xe1,
+ 0x8f, 0x82, 0xff, 0xc8, 0x0f, 0x7c, 0x00, 0x02, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xea, 0x00, 0x74, 0x99, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8,
+ 0x2f, 0x7c, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0xb5,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x00, 0x04, 0xf7, 0x83, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8,
+ 0x0f, 0x7c, 0x00, 0x09, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0xd5,
+ 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8, 0x0f, 0x7c, 0x00, 0x02,
+ 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0xf1, 0xf4, 0x02, 0x00, 0x00,
+ 0xfd, 0x82, 0x00, 0x0f, 0xfe, 0x02, 0x00, 0x01, 0xf0, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8,
+ 0x2e, 0xfc, 0x00, 0x05, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xea, 0x00, 0xea, 0x00, 0x75, 0x15,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x83, 0x5b, 0xe1, 0x7f, 0x21, 0x00, 0x01, 0x7f, 0xfd, 0x00, 0x18,
+ 0x7f, 0xfc, 0xff, 0xe8, 0x8e, 0x82, 0xff, 0xc8, 0xcf, 0xfc, 0xe4, 0x00, 0xcf, 0x78, 0xfd, 0x00,
+ 0x44, 0x79, 0x00, 0x00, 0x2e, 0xf4, 0x00, 0x05, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xea, 0x00,
+ 0xea, 0x00, 0x75, 0x49, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x00, 0x04, 0xf7, 0x83, 0x6b, 0xe1,
+ 0x8f, 0x82, 0xff, 0xc8, 0x0e, 0xfc, 0x00, 0x09, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xea, 0x00,
+ 0xea, 0x00, 0x75, 0x69, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8,
+ 0x0e, 0xfc, 0x00, 0x02, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xea, 0x00, 0xea, 0x00, 0x75, 0x85,
+ 0x00, 0x00, 0x00, 0x01, 0x2d, 0xee, 0x00, 0x01, 0xea, 0x00, 0x75, 0x08, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0xcf, 0x98, 0x00, 0x00, 0x44, 0x21, 0x00, 0x00,
+ 0xc3, 0x04, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xec, 0x94, 0x16, 0xff, 0xf4, 0x93, 0x96, 0xff, 0xf0,
+ 0xf7, 0x82, 0x75, 0xdc, 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf0,
+ 0x8f, 0x96, 0xff, 0xec, 0xff, 0x02, 0x00, 0x1f, 0xce, 0xf4, 0xf4, 0x00, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x8f, 0x16, 0xff, 0xf4, 0x7f, 0xfd, 0x00, 0x17, 0x7e, 0xf5, 0x00, 0x12, 0xcf, 0xfc, 0xed, 0x00,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x5f, 0xfd, 0x50, 0x02, 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x76, 0x18,
+ 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0xcf, 0x98, 0x00, 0x00, 0xc3, 0x04, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xf0, 0x93, 0x96, 0xff, 0xf4,
+ 0xf7, 0x82, 0x76, 0x4c, 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4,
+ 0x8f, 0x96, 0xff, 0xf0, 0xfe, 0x82, 0x00, 0x1f, 0xcf, 0x78, 0xec, 0x00, 0xcf, 0xfc, 0xec, 0x00,
+ 0x7f, 0xfd, 0x00, 0x17, 0x7f, 0x79, 0x00, 0x12, 0xcf, 0xfc, 0xf5, 0x00, 0x5f, 0xfd, 0x60, 0x00,
+ 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x76, 0x80, 0xe0, 0x00, 0x73, 0xcc, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0xcf, 0x98, 0x00, 0x00, 0x44, 0x21, 0x00, 0x00,
+ 0xc3, 0x04, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xec, 0x94, 0x16, 0xff, 0xf4, 0x93, 0x96, 0xff, 0xf0,
+ 0xf7, 0x82, 0x76, 0xbc, 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf0,
+ 0x8f, 0x96, 0xff, 0xec, 0xff, 0x02, 0x00, 0x1f, 0xce, 0xf4, 0xf4, 0x00, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x8f, 0x16, 0xff, 0xf4, 0x7f, 0xfd, 0x00, 0x17, 0x7e, 0xf5, 0x00, 0x12, 0xcf, 0xfc, 0xed, 0x00,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x5f, 0xfd, 0x00, 0x02, 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x76, 0xf8,
+ 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c,
+ 0xcf, 0x98, 0x00, 0x00, 0x44, 0x21, 0x00, 0x00, 0xc3, 0x04, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xec,
+ 0x94, 0x16, 0xff, 0xf4, 0x93, 0x96, 0xff, 0xf0, 0xf7, 0x82, 0x77, 0x34, 0xe0, 0x00, 0x73, 0x40,
+ 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf0, 0x8f, 0x96, 0xff, 0xec, 0xff, 0x02, 0x00, 0x1f,
+ 0xce, 0xf4, 0xf4, 0x00, 0xcf, 0xfc, 0xf4, 0x00, 0x8f, 0x16, 0xff, 0xf4, 0x7f, 0xfd, 0x00, 0x17,
+ 0x7e, 0xf5, 0x00, 0x12, 0xcf, 0xfc, 0xed, 0x00, 0xcf, 0xfc, 0xf5, 0x00, 0x5f, 0xfd, 0x10, 0x02,
+ 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x77, 0x70, 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08, 0xcf, 0x98, 0x00, 0x00, 0xc3, 0x04, 0x00, 0x00,
+ 0x9f, 0x96, 0xff, 0xf0, 0x93, 0x96, 0xff, 0xf4, 0xf7, 0x82, 0x77, 0xa4, 0xe0, 0x00, 0x73, 0x40,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4, 0x8f, 0x96, 0xff, 0xf0, 0xfe, 0x82, 0x00, 0x1f,
+ 0xcf, 0x78, 0xec, 0x00, 0xcf, 0xfc, 0xec, 0x00, 0x7f, 0xfd, 0x00, 0x17, 0x7f, 0x79, 0x00, 0x12,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x5f, 0xfd, 0x30, 0x00, 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x77, 0xd8,
+ 0xe0, 0x00, 0x73, 0xcc, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0xcf, 0x98, 0x00, 0x00, 0xc3, 0x04, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xf0, 0x93, 0x96, 0xff, 0xf4,
+ 0xf7, 0x82, 0x78, 0x0c, 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4,
+ 0x8f, 0x96, 0xff, 0xf0, 0xfe, 0x82, 0x00, 0x1f, 0xcf, 0x78, 0xec, 0x00, 0xcf, 0xfc, 0xec, 0x00,
+ 0x7f, 0xfd, 0x00, 0x17, 0x7f, 0x79, 0x00, 0x12, 0xcf, 0xfc, 0xf5, 0x00, 0x5f, 0xfd, 0x20, 0x00,
+ 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x78, 0x40, 0xe0, 0x00, 0x73, 0xcc, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xff, 0x88, 0xb2, 0xb8,
+ 0x93, 0x16, 0xff, 0xf4, 0xf3, 0x82, 0x00, 0x01, 0xf4, 0x02, 0x00, 0x09, 0x20, 0x7e, 0x00, 0x03,
+ 0xe6, 0x00, 0x78, 0xd4, 0xf3, 0x02, 0x00, 0x00, 0xf7, 0x82, 0x78, 0x84, 0xe0, 0x00, 0x76, 0x8c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x78, 0x98,
+ 0xe0, 0x00, 0x77, 0x7c, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0x78, 0xcd, 0x5f, 0xa0, 0x00, 0x01, 0xff, 0x82, 0xff, 0xfe, 0xc4, 0x20, 0xfc, 0x00,
+ 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x78, 0xc4, 0xe0, 0x00, 0x77, 0x04,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x78, 0xd4, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x78, 0xb0,
+ 0x44, 0x7d, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x24, 0x18, 0x7f, 0xf9, 0xf3, 0x02, 0x00, 0x00,
+ 0xf3, 0x82, 0x00, 0x01, 0x44, 0x21, 0x00, 0x00, 0xf7, 0x82, 0x79, 0x04, 0xe0, 0x00, 0x76, 0x8c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x79, 0x18,
+ 0xe0, 0x00, 0x77, 0x7c, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x08, 0xbb, 0x48,
+ 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xc0, 0x7a, 0x32, 0x00, 0xe6, 0x00, 0x79, 0x95,
+ 0xf4, 0x02, 0x80, 0x00, 0xf7, 0x82, 0x79, 0x50, 0xe0, 0x00, 0x76, 0x8c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x79, 0x64, 0xe0, 0x00, 0x77, 0x7c,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x0c, 0xc4, 0x20, 0xfc, 0x00, 0x20, 0x22, 0x00, 0x04,
+ 0xe6, 0x00, 0x79, 0x8d, 0xf4, 0x09, 0xbc, 0x60, 0xff, 0x88, 0xbc, 0x60, 0x20, 0x7e, 0x00, 0x08,
+ 0xe6, 0x78, 0x00, 0x03, 0xe0, 0x00, 0x79, 0x94, 0xff, 0x09, 0xbb, 0x48, 0xe0, 0x00, 0x79, 0x78,
+ 0xf0, 0x09, 0xbc, 0x60, 0xc4, 0x78, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0x93, 0x16, 0xff, 0xf4, 0x93, 0x96, 0xff, 0xf0, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01,
+ 0xf4, 0x02, 0xc2, 0x00, 0xf7, 0x82, 0x79, 0xd0, 0xe0, 0x00, 0x76, 0x8c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x79, 0xe4, 0xe0, 0x00, 0x77, 0x7c,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x01, 0xc3, 0x20, 0x00, 0x00, 0xc3, 0xfc, 0x00, 0x00,
+ 0xc3, 0x1a, 0xfc, 0x00, 0xf4, 0x02, 0x80, 0x00, 0xe6, 0x00, 0x7a, 0x4c, 0xcf, 0x84, 0x00, 0x00,
+ 0xf7, 0x82, 0x7a, 0x0c, 0xe0, 0x00, 0x76, 0x8c, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf0,
+ 0xf3, 0x02, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x03, 0x7f, 0xf9, 0x00, 0x08, 0x8f, 0x16, 0xff, 0xf4,
+ 0xf3, 0x82, 0x00, 0x01, 0xc0, 0x7a, 0x32, 0x00, 0xe6, 0x00, 0x7a, 0x34, 0x0f, 0xfc, 0x00, 0x02,
+ 0x44, 0x7d, 0x00, 0x00, 0xf7, 0x82, 0x7a, 0x40, 0xe0, 0x00, 0x77, 0x04, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x82, 0x00, 0x01, 0xff, 0x89, 0xbb, 0x48, 0xff, 0x82, 0x00, 0x00, 0xc4, 0x7c, 0x00, 0x00,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x07, 0x08,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x83, 0x5b, 0xe8, 0xf3, 0x02, 0x00, 0x02,
+ 0xf0, 0x89, 0xb8, 0x5c, 0x4f, 0xfc, 0xff, 0xfe, 0xff, 0x83, 0x6b, 0xe8, 0xf7, 0x82, 0x7a, 0x98,
+ 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x76, 0xff, 0xcc, 0x8f, 0xfa, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0xfc, 0x4f, 0xfd, 0xf3, 0xff, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0xfa, 0x00, 0x00,
+ 0xf7, 0x82, 0x7a, 0xbc, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00,
+ 0xf7, 0x82, 0x7a, 0xcc, 0xe0, 0x00, 0x78, 0x50, 0x97, 0x93, 0xff, 0xfc, 0xf0, 0x03, 0x2a, 0x12,
+ 0xf0, 0x03, 0x2a, 0x28, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x76, 0xff, 0xcc, 0x8f, 0xfa, 0x00, 0x00,
+ 0xf3, 0x09, 0xb8, 0x5c, 0x5f, 0xfd, 0x0c, 0x00, 0x9f, 0xfa, 0x00, 0x00, 0xf3, 0x76, 0xff, 0xfc,
+ 0xf7, 0x82, 0x7b, 0x0c, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xe8,
+ 0xf3, 0x02, 0x00, 0x01, 0xcf, 0xfc, 0x35, 0x00, 0xff, 0x83, 0x6b, 0xe8, 0xf7, 0x82, 0x7b, 0x28,
+ 0xe0, 0x00, 0x78, 0x50, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x08,
+ 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x07, 0x08, 0x62, 0x6f, 0x6f, 0x74, 0x5f, 0x72, 0x65, 0x62,
+ 0x6f, 0x6f, 0x74, 0x28, 0x25, 0x75, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0x22, 0x10, 0x00, 0x08, 0xff, 0x02, 0x7b, 0x48,
+ 0x9f, 0x12, 0x00, 0x00, 0x93, 0x12, 0x00, 0x04, 0x93, 0x16, 0xff, 0xf4, 0xf7, 0x82, 0x7b, 0x88,
+ 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4, 0xff, 0x02, 0x00, 0x3f,
+ 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x17, 0xf7, 0x82, 0x7b, 0xa4, 0xc1, 0x7c, 0x7d, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xe1, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8f, 0x82, 0xff, 0xd0, 0xf3, 0x09, 0xe2, 0x20, 0xf3, 0x02, 0x00, 0x01, 0xff, 0x89, 0xf9, 0x80,
+ 0xf7, 0x82, 0x7b, 0xdc, 0xe0, 0x00, 0x7b, 0x5c, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0xb2, 0xc8, 0xfd, 0x8a, 0xbc, 0xb0, 0x20, 0x1a, 0x00, 0x00, 0x7f, 0x7d, 0x00, 0x02,
+ 0xb3, 0x7a, 0xd8, 0x02, 0x0f, 0xfc, 0x00, 0x01, 0x7e, 0x7d, 0x00, 0x02, 0x8e, 0x82, 0xff, 0xc8,
+ 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x02, 0x00, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0xbe, 0xf2, 0xd8, 0x02,
+ 0xe6, 0x00, 0x7c, 0x30, 0xff, 0x89, 0xb2, 0xc8, 0xe0, 0x00, 0x7c, 0x28, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x8f, 0x02, 0xff, 0xd0, 0x8f, 0x82, 0xff, 0xd0, 0xcf, 0xfc, 0xf2, 0x00,
+ 0xc0, 0x7e, 0x32, 0x00, 0xe4, 0x00, 0x7c, 0x48, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0xbb, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x7c, 0x9d, 0xc4, 0x18, 0x00, 0x00,
+ 0x20, 0x1a, 0x00, 0x87, 0xe2, 0x00, 0x7c, 0x99, 0x04, 0x18, 0x00, 0x18, 0x20, 0x1a, 0x00, 0xa7,
+ 0xe2, 0x00, 0x7c, 0x9d, 0x00, 0x00, 0x00, 0x01, 0xc4, 0x18, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x1d, 0xed, 0xa0, 0x04, 0x03, 0xff, 0x02,
+ 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0x02, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x02, 0x00, 0x00, 0x07, 0x06, 0x04, 0x00, 0x0f, 0x0e, 0x0c, 0x08, 0x1f, 0x1e, 0x1c, 0x18,
+ 0x3f, 0x3e, 0x3c, 0x38, 0x7f, 0x7e, 0x7c, 0x78, 0xff, 0xfe, 0xfc, 0xf8, 0x0f, 0xff, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xe1, 0xc0, 0x55, 0x29, 0x80, 0x00,
+ 0x5f, 0xfc, 0x00, 0x02, 0xff, 0x89, 0xe1, 0xc0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x8d, 0x82, 0xff, 0x70,
+ 0xfe, 0x82, 0x00, 0x00, 0xfe, 0x0a, 0xf9, 0x00, 0x7f, 0x75, 0x00, 0x02, 0xaf, 0xfa, 0xe0, 0x02,
+ 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x76, 0x00, 0x02, 0xcf, 0xfc, 0xdd, 0x00, 0xe2, 0x00, 0x7d, 0x29,
+ 0xbf, 0xfa, 0xe0, 0x02, 0x8f, 0x02, 0xff, 0x78, 0xff, 0x88, 0xf9, 0x00, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x7d, 0x69, 0xfe, 0x8a, 0xf9, 0x00, 0xff, 0x88, 0xe1, 0xc0, 0x55, 0x29, 0x80, 0x00,
+ 0x5f, 0xfc, 0x04, 0x00, 0xff, 0x89, 0xe1, 0xc0, 0x73, 0x19, 0x00, 0x02, 0xa4, 0x1a, 0xe8, 0x02,
+ 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x00, 0x7d, 0x81, 0x00, 0x00, 0x00, 0x01, 0xb0, 0x1a, 0xe8, 0x02,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x8f, 0x82, 0xff, 0x70, 0xff, 0x02, 0x00, 0x00, 0xfe, 0x8a, 0xf9, 0x00,
+ 0x9f, 0x82, 0xfe, 0x88, 0x7f, 0xf9, 0x00, 0x02, 0x0f, 0x78, 0x00, 0x01, 0x20, 0x7a, 0x00, 0x02,
+ 0xee, 0x00, 0x7d, 0xa5, 0xb0, 0x7e, 0xe8, 0x02, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf3, 0x82, 0x00, 0x00,
+ 0xf3, 0x0a, 0xb8, 0x24, 0xf7, 0x82, 0x7d, 0xe0, 0xe0, 0x00, 0x2b, 0x98, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x02, 0xf7, 0x82, 0x7d, 0xf0, 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x0a, 0xb8, 0x23, 0xf3, 0x82, 0x00, 0x02, 0xf7, 0x82, 0x7e, 0x04, 0xe0, 0x00, 0x2b, 0x98,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8a, 0x62, 0x5a, 0x9f, 0x82, 0xff, 0xc0,
+ 0x8f, 0x02, 0xff, 0xd0, 0xff, 0xf6, 0xe9, 0xe8, 0x9f, 0x7e, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0x01, 0xc0, 0x8d, 0x0f, 0x78, 0x5d, 0x02, 0xfe, 0xf6, 0xff, 0x38, 0x9f, 0x76, 0x00, 0x00,
+ 0xff, 0xf6, 0xff, 0x34, 0x9f, 0x7e, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x30, 0x9f, 0x76, 0x00, 0x00,
+ 0xfe, 0xf6, 0xff, 0x2c, 0x9f, 0x76, 0x00, 0x00, 0x0f, 0x81, 0xc0, 0x9d, 0x0f, 0xfc, 0x5d, 0x00,
+ 0xff, 0x76, 0xff, 0x58, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x54, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x50, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x4c, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x48, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x44, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x40, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x3c, 0x9f, 0xf6, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0x5c, 0xf7, 0x82, 0x7e, 0xc0, 0xe0, 0x00, 0x2d, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x07, 0xd0, 0xf7, 0x82, 0x7e, 0xd0, 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0x0f, 0x01, 0xc0, 0x0d, 0x0f, 0x78, 0x7d, 0x02, 0xff, 0xf6, 0xff, 0x38, 0x9f, 0x7e, 0x00, 0x00,
+ 0xfe, 0xf6, 0xff, 0x34, 0x9f, 0x76, 0x00, 0x00, 0xff, 0xf6, 0xff, 0x30, 0x9f, 0x7e, 0x00, 0x00,
+ 0xfe, 0xf6, 0xff, 0x2c, 0x9f, 0x76, 0x00, 0x00, 0x0f, 0x81, 0xc0, 0x1d, 0x0f, 0xfc, 0x7d, 0x00,
+ 0xff, 0x76, 0xff, 0x58, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x54, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x50, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x4c, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x48, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x44, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x40, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x3c, 0x9f, 0xf6, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0x5c, 0xf7, 0x82, 0x7f, 0x50, 0xe0, 0x00, 0x2d, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x07, 0xd0, 0xf7, 0x82, 0x7f, 0x60, 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0x0f, 0x01, 0xc0, 0x00, 0x0f, 0x78, 0x40, 0x02, 0xff, 0xf6, 0xff, 0x38, 0x9f, 0x7e, 0x00, 0x00,
+ 0xfe, 0xf6, 0xff, 0x34, 0x9f, 0x76, 0x00, 0x00, 0xff, 0xf6, 0xff, 0x30, 0x9f, 0x7e, 0x00, 0x00,
+ 0xfe, 0xf6, 0xff, 0x2c, 0x9f, 0x76, 0x00, 0x00, 0x0f, 0x81, 0xc0, 0x10, 0x0f, 0xfc, 0x40, 0x00,
+ 0xff, 0x76, 0xff, 0x58, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x54, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x50, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x4c, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x48, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x44, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x40, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x3c, 0xf3, 0x76, 0xff, 0x5c,
+ 0x9f, 0xf6, 0x00, 0x00, 0xf7, 0x82, 0x7f, 0xe0, 0xe0, 0x00, 0x2d, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x07, 0xd0, 0xf7, 0x82, 0x7f, 0xf0, 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x50, 0x43, 0x49, 0x45,
+ 0x20, 0x69, 0x73, 0x20, 0x75, 0x70, 0x0a, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x0c, 0xf7, 0x82, 0x80, 0x20, 0xe0, 0x01, 0x18, 0x10, 0x97, 0x93, 0xff, 0xfc,
+ 0xfd, 0x76, 0xff, 0xe8, 0xfd, 0xf6, 0xff, 0xec, 0x8f, 0xea, 0x00, 0x00, 0x8f, 0x6e, 0x00, 0x00,
+ 0xfe, 0x88, 0xb2, 0xf8, 0x4f, 0xfd, 0xff, 0x01, 0x4f, 0x78, 0x00, 0x00, 0x9f, 0x6e, 0x00, 0x00,
+ 0x5f, 0xfd, 0x00, 0x40, 0x9f, 0xea, 0x00, 0x00, 0xfe, 0x02, 0x00, 0x00, 0x0e, 0xf4, 0x00, 0x01,
+ 0xfe, 0x89, 0xb2, 0xf8, 0xfe, 0x09, 0xe1, 0x80, 0xfe, 0x09, 0xe1, 0xc0, 0xf3, 0x76, 0xff, 0xfc,
+ 0x45, 0x29, 0x7f, 0xff, 0xf7, 0x82, 0x80, 0x70, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x03, 0x5b, 0xe8, 0xff, 0x88, 0xb2, 0xf8, 0xfe, 0x02, 0x00, 0x01, 0xcf, 0x78, 0xe4, 0x00,
+ 0xcf, 0xfc, 0xe0, 0x00, 0x5f, 0x78, 0x00, 0x04, 0xff, 0x89, 0xb2, 0xf8, 0xff, 0x03, 0x6b, 0xe8,
+ 0xf7, 0x82, 0x80, 0x9c, 0xe0, 0x00, 0x7d, 0x8c, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8,
+ 0xff, 0x02, 0x00, 0x80, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x81, 0x19, 0x0e, 0x81, 0x3f, 0xff,
+ 0x0e, 0xf4, 0x33, 0x33, 0x9e, 0x96, 0xff, 0xf0, 0xf7, 0x82, 0x80, 0xc4, 0xe0, 0x00, 0x7e, 0x10,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x02, 0x00, 0x80, 0x9f, 0x02, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xff, 0xd0, 0x8e, 0x96, 0xff, 0xf0, 0xfe, 0x02, 0x00, 0x1f, 0x7f, 0xfc, 0xff, 0xef,
+ 0xff, 0x03, 0x5b, 0xd8, 0xcf, 0xfc, 0xe4, 0x00, 0xcf, 0x80, 0xfa, 0x00, 0xcf, 0xf4, 0xff, 0xc0,
+ 0xfe, 0x02, 0x00, 0x01, 0xce, 0xfc, 0xe4, 0x00, 0x4f, 0x78, 0xff, 0xfe, 0xcf, 0x78, 0xed, 0x00,
+ 0xff, 0x03, 0x6b, 0xd8, 0x8f, 0x82, 0xff, 0xf8, 0xfe, 0x82, 0x00, 0x80, 0xc0, 0x7e, 0xec, 0x00,
+ 0xe6, 0x00, 0x80, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x02, 0x00, 0x50, 0xf7, 0x82, 0x81, 0x28,
+ 0xe0, 0x00, 0x21, 0x54, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x02, 0x18, 0x00, 0xff, 0x03, 0x2a, 0x52,
+ 0xff, 0x88, 0xb2, 0xf8, 0xfe, 0x83, 0x5b, 0xe8, 0xff, 0x02, 0x00, 0x01, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xce, 0xf4, 0xf4, 0x00, 0xff, 0x89, 0xb2, 0xf8, 0x5e, 0xf4, 0x00, 0x06, 0xff, 0x82, 0x00, 0x04,
+ 0xfe, 0x83, 0x6b, 0xe8, 0xff, 0x89, 0xe1, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x0a, 0xb3, 0x78, 0x0e, 0x81, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0x0e, 0xf4, 0x01, 0x80,
+ 0x9e, 0x82, 0xfe, 0x58, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0a, 0xb3, 0x78,
+ 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x01, 0x80, 0x9f, 0x82, 0xfe, 0x58,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xe0, 0x8f, 0x02, 0xfe, 0xf8,
+ 0x8e, 0x82, 0xff, 0x10, 0xcf, 0xfc, 0xf4, 0x00, 0xcf, 0xfc, 0xec, 0x00, 0x9f, 0x96, 0xff, 0xf4,
+ 0xf7, 0x82, 0x81, 0xdc, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8,
+ 0xfe, 0x02, 0x00, 0x80, 0xc0, 0x7e, 0xe4, 0x00, 0xe6, 0x00, 0x81, 0xfd, 0x00, 0x00, 0x00, 0x01,
+ 0xf2, 0x82, 0x04, 0x00, 0xe0, 0x00, 0x80, 0x10, 0x22, 0x14, 0x00, 0x08, 0x8f, 0x82, 0xff, 0xf8,
+ 0xfe, 0x82, 0x01, 0x00, 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x81, 0xd1, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x02, 0xff, 0xd0, 0x0e, 0x81, 0xff, 0xf0, 0xff, 0x82, 0x00, 0x1f, 0x7f, 0x78, 0xff, 0xf0,
+ 0xfe, 0x03, 0x5b, 0xd8, 0xcf, 0xf8, 0xfc, 0x00, 0x0e, 0xf4, 0xff, 0xf0, 0xcf, 0x00, 0xfa, 0x00,
+ 0xcf, 0x74, 0xf7, 0x80, 0xff, 0x82, 0x00, 0x01, 0xce, 0xf8, 0xfc, 0x00, 0x4e, 0x70, 0xff, 0xfe,
+ 0xce, 0x70, 0xed, 0x00, 0xfe, 0x03, 0x6b, 0xd8, 0x8f, 0x96, 0xff, 0xf4, 0xf0, 0x03, 0x2a, 0x60,
+ 0x70, 0x7e, 0x00, 0x01, 0xea, 0x00, 0x81, 0xa0, 0xff, 0x0a, 0xb3, 0x78, 0xff, 0x88, 0xb2, 0xf8,
+ 0xfe, 0x02, 0x00, 0x0c, 0xfe, 0x09, 0xe1, 0x80, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x89, 0xb2, 0xf8,
+ 0xfe, 0x8a, 0xb4, 0xf8, 0x0f, 0x01, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0x0f, 0x78, 0x01, 0x80,
+ 0x9f, 0x02, 0xfe, 0x58, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x02, 0xfe, 0xe0,
+ 0x8e, 0x82, 0xfe, 0xf8, 0x8e, 0x02, 0xff, 0x10, 0xcf, 0x78, 0xed, 0x00, 0x8f, 0x82, 0xff, 0xf8,
+ 0xcf, 0x78, 0xe5, 0x00, 0x7f, 0xfd, 0x00, 0x16, 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x82, 0xbc, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8,
+ 0xfe, 0x02, 0x00, 0x80, 0xc0, 0x7e, 0xe4, 0x00, 0xe6, 0x00, 0x82, 0xdd, 0x00, 0x00, 0x00, 0x01,
+ 0xf2, 0x82, 0x04, 0x00, 0xe0, 0x00, 0x80, 0x10, 0x22, 0x14, 0x00, 0x08, 0x8f, 0x82, 0xff, 0xf8,
+ 0xff, 0x02, 0x01, 0x00, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x82, 0xb1, 0x00, 0x00, 0x00, 0x01,
+ 0x8e, 0x96, 0xff, 0xf4, 0xf0, 0x03, 0x2a, 0x60, 0x20, 0x76, 0x00, 0x00, 0xec, 0x00, 0x82, 0x74,
+ 0xfe, 0x8a, 0xb4, 0xf8, 0x0f, 0x81, 0x80, 0x00, 0x0f, 0xfc, 0x00, 0x43, 0x9f, 0x82, 0xff, 0x90,
+ 0xff, 0x88, 0xb2, 0xf8, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x89, 0xb2, 0xf8, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xff, 0xf8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x83, 0x80, 0x0f, 0x81, 0x80, 0x60,
+ 0xf7, 0x82, 0x83, 0x4c, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8,
+ 0xfe, 0x02, 0x00, 0x80, 0xc0, 0x7e, 0xe4, 0x00, 0xe6, 0x00, 0x83, 0x6d, 0x00, 0x00, 0x00, 0x01,
+ 0xf2, 0x82, 0x04, 0x00, 0xe0, 0x00, 0x80, 0x10, 0x22, 0x14, 0x00, 0x08, 0x8f, 0x82, 0xff, 0xf8,
+ 0xfe, 0x82, 0x01, 0x00, 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x83, 0x41, 0x0f, 0x81, 0x80, 0x60,
+ 0xf0, 0x03, 0x2a, 0x60, 0xff, 0x02, 0x00, 0x08, 0x0f, 0xfc, 0x02, 0x00, 0xff, 0x09, 0xe1, 0x80,
+ 0x9f, 0x82, 0xff, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x01, 0xa0, 0x01, 0x9e, 0x02, 0xff, 0x88,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0xf6, 0xff, 0xec, 0x8f, 0x7e, 0x00, 0x00, 0xf3, 0x76, 0xff, 0xfc,
+ 0x5f, 0x78, 0x00, 0xff, 0x4f, 0x78, 0x00, 0xff, 0x9f, 0x7e, 0x00, 0x00, 0xf7, 0x82, 0x83, 0xe8,
+ 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x0e, 0x81, 0x20, 0x03, 0x0e, 0xf4, 0x00, 0x01,
+ 0x9e, 0x82, 0xff, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x90, 0x00, 0x0f, 0x78, 0x00, 0x43,
+ 0x9f, 0x02, 0xff, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xff, 0x82, 0x00, 0x20, 0xff, 0x83, 0x2b, 0x22,
+ 0xff, 0x88, 0xb2, 0xe8, 0x0e, 0x01, 0x00, 0x3f, 0xf0, 0x03, 0x2b, 0x0a, 0x0e, 0x70, 0xfc, 0x04,
+ 0x20, 0x7e, 0x00, 0x00, 0x9e, 0x02, 0xff, 0x78, 0xe6, 0x00, 0x85, 0xa5, 0xf3, 0x02, 0x00, 0x02,
+ 0xf3, 0x02, 0x00, 0x01, 0xf7, 0x82, 0x84, 0x60, 0xe0, 0x00, 0x90, 0x20, 0x97, 0x93, 0xff, 0xfc,
+ 0xf0, 0x09, 0xb2, 0xe8, 0xf3, 0x02, 0x00, 0x00, 0xf7, 0x82, 0x84, 0x74, 0xe0, 0x00, 0x96, 0xc8,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00, 0xf7, 0x82, 0x84, 0x84, 0xe0, 0x01, 0x01, 0x74,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x03, 0x1b, 0x9a, 0xff, 0x8a, 0xb8, 0x08, 0xfe, 0x82, 0x0f, 0xff,
+ 0x20, 0x7a, 0x0f, 0xff, 0xe6, 0x00, 0x85, 0x1d, 0xfe, 0xff, 0x28, 0x02, 0xff, 0x0a, 0xb8, 0x08,
+ 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x14, 0x9f, 0x82, 0xfe, 0x58,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x84, 0xc4, 0xe0, 0x00, 0x7e, 0x10,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8, 0xfe, 0x02, 0x00, 0x80, 0xc0, 0x7e, 0xe4, 0x00,
+ 0xe6, 0x00, 0x84, 0xe5, 0x00, 0x00, 0x00, 0x01, 0xf2, 0x82, 0x04, 0x00, 0xe0, 0x00, 0x80, 0x10,
+ 0x22, 0x14, 0x00, 0x08, 0x8f, 0x82, 0xff, 0xf8, 0xfe, 0x82, 0x01, 0x00, 0xc0, 0x7e, 0xec, 0x00,
+ 0xe6, 0x00, 0x84, 0xb9, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60, 0xf3, 0x02, 0x07, 0xd0,
+ 0xf7, 0x82, 0x85, 0x0c, 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x1b, 0x9a,
+ 0x20, 0x7e, 0x0f, 0xff, 0xe6, 0x00, 0x84, 0xa0, 0xff, 0x0a, 0xb8, 0x08, 0x0f, 0x01, 0x90, 0x00,
+ 0x0f, 0x78, 0x40, 0x00, 0x9f, 0x02, 0xff, 0x80, 0xf3, 0x02, 0x00, 0x4c, 0xf7, 0x82, 0x85, 0x38,
+ 0xe0, 0x00, 0x21, 0x54, 0x97, 0x93, 0xff, 0xfc, 0x22, 0x10, 0x00, 0x04, 0xff, 0x82, 0x7f, 0xfc,
+ 0x9f, 0x92, 0x00, 0x00, 0xff, 0x88, 0xb2, 0xf8, 0x0f, 0xfd, 0x00, 0x01, 0x4f, 0xfc, 0x00, 0x00,
+ 0xff, 0x89, 0xb2, 0xf8, 0xf7, 0x82, 0x85, 0x60, 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc,
+ 0xfe, 0x02, 0x3d, 0x09, 0x9e, 0x02, 0xff, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x02, 0x10, 0x00, 0x04,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0x85, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x85, 0xb0, 0xe0, 0x00, 0x90, 0x20, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0x84, 0x68, 0xf3, 0x02, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x50, 0x43, 0x49, 0x45, 0x20, 0x69, 0x73, 0x20, 0x64, 0x6f, 0x77, 0x6e,
+ 0x21, 0x21, 0x0a, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04,
+ 0x22, 0x10, 0x00, 0x04, 0xff, 0x82, 0x85, 0xc4, 0x9f, 0x92, 0x00, 0x00, 0xf7, 0x82, 0x85, 0xf8,
+ 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0x02, 0x10, 0x00, 0x04, 0xf7, 0x82, 0x86, 0x08,
+ 0xe0, 0x00, 0x80, 0x08, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x30, 0x00,
+ 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x31, 0x00, 0x4c, 0x31, 0x00, 0x4c,
+ 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x33, 0x00, 0x4c, 0x32, 0x33, 0x5f, 0x52,
+ 0x65, 0x61, 0x64, 0x79, 0x00, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x8f, 0x9a, 0x00, 0x04,
+ 0xff, 0x03, 0x1a, 0x42, 0x7f, 0xfd, 0x00, 0x01, 0x4e, 0x7b, 0x00, 0x00, 0xe6, 0x00, 0x86, 0xed,
+ 0x7e, 0xfc, 0xff, 0xe7, 0xff, 0x82, 0x00, 0x38, 0xff, 0x02, 0x00, 0x5f, 0xcd, 0x74, 0xfc, 0x00,
+ 0xcd, 0xf4, 0xf4, 0x00, 0xff, 0x1b, 0x18, 0x00, 0xff, 0x82, 0x07, 0xff, 0xcf, 0xf8, 0xfc, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0x0f, 0xfc, 0x00, 0x0f, 0x4f, 0xfc, 0xff, 0xf0, 0x7f, 0x78, 0xff, 0xf5,
+ 0x20, 0x7a, 0x00, 0x02, 0xe6, 0x00, 0x87, 0x11, 0xce, 0x98, 0xf8, 0x00, 0xff, 0x88, 0xb8, 0x3c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x86, 0xcc, 0x20, 0x7a, 0x00, 0x11, 0xe6, 0x00, 0x86, 0xf5,
+ 0x20, 0x7a, 0x00, 0x06, 0xe6, 0x00, 0x86, 0xf9, 0x20, 0x6e, 0x00, 0x40, 0xff, 0xfa, 0x7f, 0xff,
+ 0xc0, 0x76, 0xfa, 0x00, 0xe2, 0x00, 0x86, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x2e, 0xf4, 0x80, 0x00,
+ 0x2e, 0x72, 0x00, 0x01, 0xe6, 0x00, 0x86, 0x84, 0xc3, 0x74, 0x00, 0x00, 0xe0, 0x00, 0x87, 0x34,
+ 0xf4, 0x02, 0x00, 0x00, 0x20, 0x6e, 0x00, 0x40, 0xe6, 0x00, 0x86, 0xcd, 0x20, 0x6a, 0x00, 0x30,
+ 0xe6, 0x00, 0x86, 0xcd, 0xff, 0x82, 0x00, 0x01, 0xe0, 0x00, 0x86, 0xcc, 0xff, 0x89, 0xb8, 0x3c,
+ 0xff, 0x9b, 0x58, 0x02, 0x20, 0x7e, 0x00, 0x24, 0xe6, 0x00, 0x87, 0x31, 0x03, 0x01, 0xe1, 0x00,
+ 0x03, 0x18, 0x04, 0xa5, 0xf7, 0x82, 0x87, 0x30, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc,
+ 0xf4, 0x02, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x76, 0xff, 0xe8, 0x8f, 0xfa, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0xfc, 0x0f, 0x01, 0xff, 0xfe, 0x0f, 0x78, 0x01, 0xff, 0x5f, 0xfd, 0x00, 0x02,
+ 0xcf, 0xfc, 0xf4, 0x00, 0x5f, 0xfc, 0x8a, 0x00, 0x5f, 0xfd, 0x00, 0x04, 0xff, 0x76, 0xff, 0xe8,
+ 0x9f, 0xfa, 0x00, 0x00, 0xf7, 0x82, 0x87, 0x80, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x0a, 0xf7, 0x82, 0x87, 0x90, 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x76, 0xff, 0xbc, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x87, 0xa4, 0xe0, 0x00, 0x28, 0x78,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0xf6, 0xff, 0xa8, 0x8e, 0xfe, 0x00, 0x00, 0xfe, 0x76, 0xff, 0xac,
+ 0x8f, 0x72, 0x00, 0x00, 0x7e, 0xf5, 0x00, 0x1b, 0x7e, 0xf4, 0xff, 0xe8, 0x7f, 0x78, 0xff, 0xe3,
+ 0xcf, 0x78, 0xe8, 0x00, 0xff, 0x09, 0xb8, 0x34, 0xff, 0x76, 0xff, 0xe8, 0x8f, 0xfa, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0xfc, 0x4f, 0xfd, 0xff, 0x07, 0x5f, 0xfd, 0x00, 0xa0, 0x9f, 0xfa, 0x00, 0x00,
+ 0xf7, 0x82, 0x87, 0xec, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20,
+ 0x25, 0x73, 0x0a, 0x00, 0x54, 0x69, 0x6d, 0x65, 0x64, 0x2d, 0x6f, 0x75, 0x74, 0x20, 0x77, 0x68,
+ 0x65, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x25, 0x73,
+ 0x0a, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x14,
+ 0xff, 0x0a, 0xb6, 0x78, 0x93, 0x16, 0xff, 0xf4, 0x93, 0x96, 0xff, 0xf0, 0x20, 0x1a, 0x00, 0x02,
+ 0xe6, 0x00, 0x88, 0x51, 0x9f, 0x16, 0xff, 0xec, 0xff, 0x8a, 0xb6, 0xf8, 0x9f, 0x96, 0xff, 0xec,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x08, 0xf9, 0x18, 0xfe, 0x8e, 0x0d, 0x40, 0xcf, 0xfc, 0xf2, 0x00,
+ 0xc0, 0x7e, 0xea, 0x00, 0xe2, 0x00, 0x89, 0xe4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb8, 0x2c,
+ 0x20, 0x7e, 0x00, 0x02, 0xe6, 0x00, 0x89, 0x79, 0x00, 0x00, 0x00, 0x01, 0xe2, 0x00, 0x88, 0xfc,
+ 0x20, 0x7e, 0x00, 0x03, 0x20, 0x7e, 0x00, 0x01, 0xe6, 0x00, 0x88, 0xad, 0xff, 0x82, 0x00, 0x02,
+ 0x03, 0x01, 0xe1, 0x00, 0x03, 0x18, 0x05, 0x3d, 0xf7, 0x82, 0x88, 0xa4, 0xe0, 0x00, 0x7b, 0xb8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x8a, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xec,
+ 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0x01, 0x10, 0x00, 0x0f, 0x78, 0x00, 0x80, 0x9f, 0x02, 0xfe, 0x58,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x2f, 0xfe, 0x00, 0x01, 0xea, 0x00, 0x88, 0xac,
+ 0xff, 0x02, 0x00, 0x03, 0x8f, 0x96, 0xff, 0xf4, 0xff, 0x09, 0xb8, 0x30, 0x20, 0x7e, 0x00, 0x02,
+ 0xff, 0x82, 0x00, 0x02, 0xe6, 0x00, 0x8a, 0x2c, 0xff, 0x89, 0xb8, 0x2c, 0x0f, 0x01, 0x20, 0x00,
+ 0x9f, 0x02, 0xff, 0x88, 0xe0, 0x00, 0x8a, 0x2c, 0x00, 0x00, 0x00, 0x01, 0xe6, 0x00, 0x88, 0x94,
+ 0x03, 0x01, 0xe1, 0x00, 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x17, 0xea, 0x00, 0x89, 0x6c,
+ 0x00, 0x00, 0x00, 0x01, 0xfe, 0x88, 0xb8, 0x30, 0xf0, 0x03, 0x2a, 0x60, 0x2e, 0xf4, 0x00, 0x01,
+ 0xfe, 0x89, 0xb8, 0x30, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0x8a, 0x2c, 0x22, 0x10, 0x00, 0x08,
+ 0x8f, 0x96, 0xff, 0xf4, 0xfe, 0x89, 0xb8, 0x2c, 0x7f, 0x7d, 0x00, 0x02, 0xff, 0x8a, 0xb8, 0x40,
+ 0xaf, 0x7a, 0xf8, 0x02, 0x8f, 0x96, 0xff, 0xf4, 0x9f, 0x12, 0x00, 0x04, 0xff, 0x02, 0x87, 0xf8,
+ 0x9f, 0x12, 0x00, 0x00, 0xff, 0x89, 0xb8, 0x28, 0xf7, 0x82, 0x89, 0x64, 0xe0, 0x02, 0x99, 0xf4,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x8a, 0x2c, 0x02, 0x10, 0x00, 0x08, 0xfe, 0x88, 0xb8, 0x30,
+ 0xe0, 0x00, 0x89, 0x28, 0x20, 0x76, 0x00, 0x00, 0x83, 0x16, 0xff, 0xf0, 0xf7, 0x82, 0x89, 0x88,
+ 0xe0, 0x00, 0x86, 0x54, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x89, 0xcc,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x17, 0xea, 0x00, 0x8a, 0x2c,
+ 0x00, 0x00, 0x00, 0x01, 0xf4, 0x03, 0x2a, 0x60, 0x8f, 0x16, 0xff, 0xec, 0x0f, 0x81, 0x10, 0x00,
+ 0x0f, 0xfc, 0x00, 0x80, 0x9f, 0x02, 0xfe, 0x58, 0x9f, 0x82, 0xfe, 0x58, 0x94, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x8a, 0x2c, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x89, 0xd8,
+ 0xe0, 0x00, 0x87, 0x40, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x03, 0xe0, 0x00, 0x8a, 0x2c,
+ 0xff, 0x89, 0xb8, 0x2c, 0x8f, 0x96, 0xff, 0xf4, 0x22, 0x10, 0x00, 0x08, 0x7f, 0x7d, 0x00, 0x02,
+ 0xff, 0x8a, 0xb8, 0x40, 0xaf, 0x7a, 0xf8, 0x02, 0x9f, 0x12, 0x00, 0x04, 0xff, 0x02, 0x88, 0x04,
+ 0x9f, 0x12, 0x00, 0x00, 0xf7, 0x82, 0x8a, 0x10, 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc,
+ 0x02, 0x10, 0x00, 0x08, 0xf3, 0x02, 0x00, 0x05, 0xf7, 0x82, 0x8a, 0x24, 0xe0, 0x00, 0x7b, 0x5c,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x88, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x42, 0x61, 0x63, 0x6b, 0x20, 0x74, 0x6f, 0x20,
+ 0x4c, 0x30, 0x2c, 0x20, 0x50, 0x43, 0x49, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x56, 0x5f, 0x43, 0x4f,
+ 0x55, 0x4e, 0x54, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x42, 0x61, 0x63, 0x6b, 0x20, 0x74, 0x6f, 0x20,
+ 0x4c, 0x44, 0x6e, 0x2c, 0x20, 0x50, 0x43, 0x49, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x56, 0x5f, 0x43,
+ 0x4f, 0x55, 0x4e, 0x54, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10, 0xff, 0x88, 0xb8, 0x28, 0x20, 0x7e, 0x00, 0x05,
+ 0xe2, 0x00, 0x8c, 0xf0, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x02, 0x8a, 0xa8, 0xae, 0xfe, 0xf0, 0x02,
+ 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x8a, 0xc0, 0x00, 0x00, 0x8a, 0xdc,
+ 0x00, 0x00, 0x8a, 0xf8, 0x00, 0x00, 0x8b, 0xe8, 0x00, 0x00, 0x8b, 0xf4, 0x00, 0x00, 0x8c, 0xe4,
+ 0x03, 0x01, 0xe1, 0x00, 0x03, 0x18, 0x05, 0x51, 0xf7, 0x82, 0x8a, 0xd4, 0xe0, 0x00, 0x7b, 0xb8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x8c, 0xf0, 0x00, 0x00, 0x00, 0x01, 0xc3, 0x98, 0x00, 0x00,
+ 0xf3, 0x02, 0x00, 0x02, 0xf7, 0x82, 0x8a, 0xf0, 0xe0, 0x00, 0x88, 0x24, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0x8c, 0xf0, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb8, 0x3c, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0x8b, 0x4c, 0xfe, 0xf6, 0xff, 0xe8, 0xf3, 0x76, 0xff, 0xbc, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x82, 0x8b, 0x1c, 0xe0, 0x00, 0x28, 0x78, 0x97, 0x93, 0xff, 0xfc, 0xff, 0xf6, 0xff, 0xa8,
+ 0x8f, 0x7e, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0xac, 0x8f, 0xf6, 0x00, 0x00, 0x7f, 0x79, 0x00, 0x1b,
+ 0x7f, 0x78, 0xff, 0xe8, 0xfe, 0x88, 0xb8, 0x34, 0x7f, 0xfc, 0xff, 0xe3, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x8c, 0xf1, 0xfe, 0xf6, 0xff, 0xe8, 0x8f, 0xf6, 0x00, 0x00,
+ 0x0f, 0x01, 0xff, 0xfe, 0x0f, 0x78, 0x01, 0xff, 0x5f, 0xfd, 0x00, 0x02, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x5f, 0xfc, 0x08, 0x00, 0x4f, 0xfd, 0xff, 0x03, 0x5f, 0xfd, 0x00, 0x40, 0x9f, 0xf6, 0x00, 0x00,
+ 0x9e, 0x96, 0xff, 0xf4, 0x9f, 0x16, 0xff, 0xf0, 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x82, 0x8b, 0x88,
+ 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf4, 0x8f, 0x16, 0xff, 0xf0,
+ 0x8f, 0xf6, 0x00, 0x00, 0x4f, 0xfd, 0xff, 0xfd, 0xcf, 0xfc, 0xf4, 0x00, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x88, 0xe1, 0xc0, 0xf0, 0x09, 0xb8, 0x28, 0x4f, 0xfc, 0xf7, 0xff, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0x8b, 0xbc, 0xff, 0x89, 0xe1, 0xc0, 0x45, 0x29, 0x7f, 0xff, 0x22, 0x10, 0x00, 0x08,
+ 0xff, 0x82, 0x8a, 0x38, 0x9f, 0x92, 0x00, 0x00, 0xff, 0x83, 0x1a, 0x42, 0x4f, 0xfd, 0x00, 0x00,
+ 0x9f, 0x92, 0x00, 0x04, 0xf7, 0x82, 0x8b, 0xe0, 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0x8c, 0xf0, 0x02, 0x10, 0x00, 0x08, 0xc3, 0x98, 0x00, 0x00, 0xe0, 0x00, 0x8a, 0xe4,
+ 0xf3, 0x02, 0x00, 0x04, 0xf3, 0x76, 0xff, 0xbc, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x8c, 0x08,
+ 0xe0, 0x00, 0x28, 0x78, 0x97, 0x93, 0xff, 0xfc, 0xff, 0xf6, 0xff, 0xa8, 0x8f, 0x7e, 0x00, 0x00,
+ 0xfe, 0xf6, 0xff, 0xac, 0x8f, 0xf6, 0x00, 0x00, 0x7f, 0x79, 0x00, 0x1b, 0x7f, 0x78, 0xff, 0xe8,
+ 0x7f, 0xfc, 0xff, 0xe3, 0xcf, 0xfc, 0xf0, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x8c, 0xf1,
+ 0xfe, 0xf6, 0xff, 0xe8, 0x8f, 0xf6, 0x00, 0x00, 0x0f, 0x01, 0xff, 0xfe, 0x0f, 0x78, 0x01, 0xff,
+ 0x5f, 0xfd, 0x00, 0x02, 0xcf, 0xfc, 0xf4, 0x00, 0x4f, 0xfd, 0xff, 0x03, 0x5f, 0xfd, 0x00, 0x40,
+ 0x9f, 0xf6, 0x00, 0x00, 0x9e, 0x96, 0xff, 0xf4, 0x9f, 0x16, 0xff, 0xf0, 0xf3, 0x76, 0xff, 0xfc,
+ 0xf7, 0x82, 0x8c, 0x6c, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf4,
+ 0x8f, 0x16, 0xff, 0xf0, 0x8f, 0xf6, 0x00, 0x00, 0x4f, 0xfd, 0xff, 0xfd, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x9f, 0xf6, 0x00, 0x00, 0xff, 0x82, 0x00, 0x05, 0xff, 0x89, 0xb8, 0x28, 0xff, 0x88, 0xe1, 0xc0,
+ 0x4f, 0xfc, 0xf7, 0xff, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x8c, 0xa4, 0xff, 0x89, 0xe1, 0xc0,
+ 0x45, 0x29, 0x7f, 0xff, 0x22, 0x10, 0x00, 0x08, 0xff, 0x82, 0x8a, 0x58, 0x9f, 0x92, 0x00, 0x00,
+ 0xff, 0x83, 0x1a, 0x42, 0x4f, 0xfd, 0x00, 0x00, 0x9f, 0x92, 0x00, 0x04, 0xf7, 0x82, 0x8c, 0xc8,
+ 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x18,
+ 0xea, 0x00, 0x8c, 0xf1, 0x02, 0x10, 0x00, 0x08, 0x03, 0x01, 0xe1, 0x00, 0xe0, 0x00, 0x8a, 0xc8,
+ 0x03, 0x18, 0x05, 0x8f, 0x03, 0x01, 0xe1, 0x00, 0xe0, 0x00, 0x8a, 0xc8, 0x03, 0x18, 0x05, 0x95,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0e, 0x81, 0x02, 0x00, 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x00, 0x8d, 0x45,
+ 0xc4, 0x1c, 0x00, 0x00, 0x8f, 0x82, 0xff, 0xf8, 0x93, 0x02, 0xfe, 0x68, 0x93, 0x82, 0xfe, 0x68,
+ 0x93, 0x02, 0xfe, 0x68, 0xcf, 0xfc, 0xec, 0x00, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x02, 0xff, 0xf8, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x8d, 0x44, 0xc4, 0x78, 0xec, 0x00,
+ 0x9e, 0x82, 0xff, 0xf8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0xf3, 0x82, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0xbc, 0xf7, 0x82, 0x8d, 0x70, 0xe0, 0x00, 0x28, 0x78, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0xf6, 0xff, 0x80, 0x8f, 0xfe, 0x00, 0x00, 0xfd, 0xf6, 0xff, 0xdc, 0xfe, 0x76, 0xff, 0xd8,
+ 0x7f, 0xfd, 0x00, 0x04, 0x9f, 0x96, 0xff, 0xec, 0x8f, 0x6e, 0x00, 0x00, 0x8e, 0xf2, 0x00, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe6, 0x4f, 0x79, 0x3f, 0xff, 0x9f, 0x96, 0xff, 0xf0, 0x4f, 0xfc, 0xff, 0xfe,
+ 0x7e, 0x7c, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x1e, 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x6e, 0x00, 0x00,
+ 0x4e, 0xf4, 0xff, 0xf0, 0xce, 0xf4, 0xe5, 0x00, 0xfd, 0xf6, 0xff, 0xd8, 0x9e, 0xee, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x82, 0x8d, 0xd0, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x26, 0x57, 0x78, 0xf3, 0xf6, 0xfe, 0x00, 0xc3, 0x9c, 0x32, 0x00, 0xf7, 0x82, 0x8d, 0xe8,
+ 0xe0, 0x00, 0x8c, 0xfc, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x76, 0xff, 0x00, 0xf3, 0x8a, 0x01, 0x00,
+ 0x94, 0x16, 0xff, 0xf4, 0xf7, 0x82, 0x8e, 0x00, 0xe0, 0x00, 0x8c, 0xfc, 0x97, 0x93, 0xff, 0xfc,
+ 0xfe, 0x76, 0xff, 0xdc, 0x8f, 0xf2, 0x00, 0x00, 0x8d, 0x96, 0xff, 0xf0, 0xfe, 0xf6, 0xff, 0xd8,
+ 0x8f, 0x76, 0x00, 0x00, 0x7e, 0x6d, 0x00, 0x1e, 0x8d, 0x96, 0xff, 0xec, 0x4f, 0xfd, 0x3f, 0xff,
+ 0xcf, 0xfc, 0xe5, 0x00, 0x7e, 0xec, 0xff, 0xe4, 0x4f, 0x78, 0xff, 0xf0, 0xcf, 0x78, 0xed, 0x00,
+ 0xfe, 0x76, 0xff, 0xdc, 0x9f, 0xf2, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0xd8, 0x9f, 0x76, 0x00, 0x00,
+ 0x8f, 0x16, 0xff, 0xf4, 0xf3, 0x76, 0xff, 0xfc, 0xcf, 0x78, 0x45, 0x00, 0x9f, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x8e, 0x5c, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x84, 0x16, 0xff, 0xf4,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x6f, 0x6e, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x6f, 0x66, 0x66, 0x2c, 0x20, 0x75, 0x6e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x69,
+ 0x6e, 0x67, 0x20, 0x73, 0x74, 0x75, 0x63, 0x6b, 0x20, 0x50, 0x43, 0x49, 0x45, 0x5f, 0x44, 0x4c,
+ 0x4c, 0x5f, 0x42, 0x55, 0x53, 0x59, 0x0a, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x08, 0x90, 0x82, 0xfe, 0x88, 0xf7, 0x82, 0x00, 0x06, 0xf7, 0x83, 0x6a, 0x7a,
+ 0xf7, 0x82, 0x8e, 0xbc, 0xe0, 0x00, 0x7d, 0xc4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xe8,
+ 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x00, 0x8f, 0x18, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xf8,
+ 0x70, 0x7e, 0x00, 0x0e, 0xea, 0x00, 0x8f, 0x24, 0xff, 0x82, 0x8e, 0x6c, 0x22, 0x10, 0x00, 0x04,
+ 0x9f, 0x92, 0x00, 0x00, 0xf7, 0x82, 0x8e, 0xf0, 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc,
+ 0x02, 0x10, 0x00, 0x04, 0xf3, 0x02, 0x00, 0x03, 0xf7, 0x82, 0x8f, 0x04, 0xe0, 0x00, 0x2e, 0xc0,
+ 0x97, 0x93, 0xff, 0xfc, 0x74, 0x21, 0x00, 0x02, 0x04, 0x21, 0x90, 0x00, 0x94, 0x02, 0xff, 0x80,
+ 0xe0, 0x00, 0x8f, 0x28, 0xfe, 0x76, 0xff, 0xdc, 0xf7, 0x82, 0x8f, 0x24, 0xe0, 0x00, 0x7e, 0x38,
+ 0x97, 0x93, 0xff, 0xfc, 0xfe, 0x76, 0xff, 0xdc, 0x8f, 0xf2, 0x00, 0x00, 0xfd, 0x76, 0xff, 0xe8,
+ 0xfd, 0xf6, 0xff, 0xec, 0x4f, 0xfd, 0xc0, 0x3f, 0x5f, 0xfd, 0x01, 0x00, 0x9f, 0xf2, 0x00, 0x00,
+ 0x8f, 0x6a, 0x00, 0x00, 0x8f, 0xee, 0x00, 0x00, 0xfc, 0xf6, 0xff, 0xe4, 0x5f, 0x78, 0x00, 0x02,
+ 0x5f, 0xfd, 0x01, 0x00, 0x4f, 0x79, 0xff, 0x07, 0x9f, 0xee, 0x00, 0x00, 0x5f, 0x79, 0x00, 0x40,
+ 0x9f, 0x6a, 0x00, 0x00, 0x8f, 0xe6, 0x00, 0x00, 0x0e, 0x81, 0xc0, 0x00, 0x0e, 0xf4, 0x00, 0x03,
+ 0xcf, 0xfc, 0xec, 0x00, 0x5f, 0xfc, 0x00, 0x20, 0x9f, 0xe6, 0x00, 0x00, 0x9e, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x8f, 0x8c, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x0f, 0x81, 0x20, 0x00,
+ 0x9f, 0x82, 0xff, 0xf8, 0x8e, 0x16, 0xff, 0xf4, 0xfe, 0xf6, 0xff, 0xd8, 0xf3, 0x76, 0xff, 0xfc,
+ 0x8f, 0x72, 0x00, 0x00, 0x5f, 0x79, 0xc0, 0x00, 0x9f, 0x72, 0x00, 0x00, 0x8f, 0xf6, 0x00, 0x00,
+ 0x5f, 0xfc, 0x00, 0x0f, 0x9f, 0xf6, 0x00, 0x00, 0xf7, 0x82, 0x8f, 0xc4, 0xe0, 0x00, 0x25, 0xb4,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf3, 0x09, 0xe1, 0xa8, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x43, 0x61, 0x70, 0x73, 0x20, 0x64, 0x69, 0x66,
+ 0x66, 0x65, 0x72, 0x73, 0x20, 0x61, 0x74, 0x20, 0x30, 0x78, 0x25, 0x78, 0x28, 0x6f, 0x6c, 0x64,
+ 0x3d, 0x30, 0x78, 0x25, 0x78, 0x29, 0x3a, 0x20, 0x6e, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x3d, 0x25,
+ 0x64, 0x2c, 0x20, 0x6f, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x2c, 0xfe, 0x82, 0x00, 0x80,
+ 0x93, 0x16, 0xff, 0xf4, 0x20, 0x1a, 0x00, 0x02, 0xe6, 0x00, 0x94, 0x6d, 0x9e, 0x96, 0xff, 0xf0,
+ 0x20, 0x1a, 0x00, 0x02, 0xe2, 0x00, 0x91, 0x60, 0x20, 0x1a, 0x00, 0x01, 0xe6, 0x00, 0x91, 0x05,
+ 0x03, 0x01, 0xe1, 0x00, 0x03, 0x18, 0x06, 0xae, 0xf7, 0x82, 0x90, 0x64, 0xe0, 0x00, 0x7b, 0xb8,
+ 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x90, 0x70, 0xe0, 0x00, 0x0a, 0xa0, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x06, 0x38, 0x80, 0xf7, 0x82, 0x90, 0x80, 0xe0, 0x00, 0x8f, 0xd0, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xa6, 0xc0, 0x8e, 0x96, 0xff, 0xf4, 0x8f, 0x16, 0xff, 0xf0, 0xfd, 0x82, 0x00, 0x00,
+ 0x5f, 0xfc, 0x00, 0x40, 0xfe, 0x89, 0xb2, 0xe0, 0xc0, 0x6e, 0xf2, 0x00, 0xe4, 0x00, 0x94, 0xd1,
+ 0xff, 0x89, 0xa6, 0xc0, 0xff, 0x0a, 0xa2, 0x68, 0x8f, 0xfa, 0x00, 0x0c, 0xf3, 0x02, 0x00, 0x00,
+ 0x74, 0xed, 0x00, 0x02, 0x0d, 0xec, 0x00, 0x01, 0xc0, 0x7e, 0x32, 0x00, 0xe6, 0x00, 0x90, 0xdc,
+ 0xc3, 0x98, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xf0, 0xc0, 0x6e, 0xfa, 0x00, 0xe4, 0x00, 0x90, 0xa8,
+ 0x0f, 0x78, 0x00, 0x10, 0xe0, 0x00, 0x94, 0xd4, 0xf0, 0x09, 0xb2, 0xe0, 0x84, 0x7a, 0x00, 0x08,
+ 0x9d, 0x96, 0xff, 0xe4, 0x9f, 0x16, 0xff, 0xe0, 0xf7, 0x82, 0x90, 0xf4, 0xc1, 0x7c, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xe0, 0x8d, 0x96, 0xff, 0xe4, 0xe0, 0x00, 0x90, 0xc4,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb2, 0xec, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x89, 0xb2, 0xec,
+ 0xf7, 0x82, 0x91, 0x1c, 0xe0, 0x00, 0x0a, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x8a, 0xa3, 0xdf,
+ 0x27, 0x80, 0x00, 0x78, 0xf7, 0xff, 0x68, 0x03, 0xff, 0x88, 0xa3, 0xe0, 0xfe, 0x82, 0x00, 0x08,
+ 0xff, 0x0a, 0xa3, 0x20, 0x4f, 0xfd, 0xff, 0xf0, 0xfe, 0xfb, 0x28, 0x00, 0x5f, 0xfd, 0x00, 0x01,
+ 0xff, 0x89, 0xa3, 0xe0, 0xff, 0x0a, 0xa4, 0xef, 0xf0, 0x7b, 0x68, 0x03, 0xff, 0x8a, 0xa2, 0x70,
+ 0xfe, 0xff, 0x28, 0x00, 0x8f, 0x96, 0xff, 0xf4, 0xe0, 0x00, 0x90, 0x64, 0xff, 0x89, 0xbb, 0x50,
+ 0x8f, 0x16, 0xff, 0xf4, 0x20, 0x7a, 0x00, 0x03, 0xe6, 0x00, 0x90, 0x54, 0x03, 0x01, 0xe1, 0x00,
+ 0xff, 0x88, 0xb2, 0xf4, 0xff, 0x02, 0x00, 0x08, 0xff, 0x09, 0xe1, 0x80, 0x0f, 0xfc, 0x00, 0x01,
+ 0xff, 0x89, 0xb2, 0xf4, 0xff, 0x82, 0x00, 0x01, 0xf0, 0x09, 0xb8, 0x24, 0xf0, 0x09, 0xb8, 0x28,
+ 0xff, 0x89, 0xb2, 0xd8, 0xfe, 0xf6, 0xed, 0xa0, 0x8f, 0x76, 0x00, 0x08, 0xfe, 0x76, 0xff, 0xf0,
+ 0xf3, 0x76, 0xff, 0xfc, 0xff, 0x09, 0xb2, 0xdc, 0x8f, 0xf2, 0x00, 0x00, 0x0e, 0x81, 0xe0, 0x00,
+ 0x0e, 0xf4, 0x1f, 0xff, 0x5f, 0xfc, 0x10, 0x00, 0x7f, 0x79, 0x00, 0x0d, 0xcf, 0xfc, 0xec, 0x00,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x9f, 0xf2, 0x00, 0x00, 0xf7, 0x82, 0x91, 0xd4, 0xe0, 0x00, 0x25, 0xb4,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x76, 0xed, 0xa0, 0x8f, 0xfa, 0x00, 0x0c, 0x20, 0x7e, 0x00, 0x80,
+ 0xe4, 0x00, 0x91, 0xed, 0x00, 0x00, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xf0, 0xfd, 0x82, 0x00, 0x00,
+ 0xfa, 0x0a, 0xa2, 0x68, 0xff, 0x0a, 0xa2, 0x70, 0xff, 0xf6, 0xed, 0xb0, 0x20, 0x6e, 0x00, 0x0d,
+ 0xe6, 0x00, 0x92, 0x11, 0x0d, 0xec, 0x00, 0x01, 0x8e, 0xfe, 0x00, 0x00, 0x9e, 0xfa, 0x00, 0x00,
+ 0x20, 0x6e, 0x00, 0x0f, 0x0f, 0xfc, 0x00, 0x04, 0xe2, 0x00, 0x91, 0xfd, 0x0f, 0x78, 0x00, 0x10,
+ 0xfe, 0xf6, 0xed, 0xa0, 0xff, 0x88, 0xa3, 0x40, 0xfc, 0xf7, 0x58, 0x47, 0xff, 0x02, 0x00, 0x40,
+ 0x7f, 0xfd, 0x00, 0x18, 0x7d, 0x7c, 0xff, 0xe8, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x00, 0x93, 0x81,
+ 0x9f, 0x16, 0xff, 0xec, 0x20, 0x6a, 0x00, 0x00, 0xe6, 0x00, 0x93, 0x81, 0x7f, 0x64, 0xff, 0xfe,
+ 0x8f, 0x96, 0xff, 0xf0, 0xc0, 0x7a, 0xfa, 0x00, 0xe4, 0x00, 0x93, 0x81, 0x7d, 0xe8, 0xff, 0xfe,
+ 0xf9, 0x82, 0x00, 0xff, 0xc8, 0xf4, 0x00, 0x00, 0xf9, 0x02, 0x00, 0xfc, 0xf8, 0x02, 0x01, 0x00,
+ 0x7f, 0x79, 0x00, 0x02, 0x7f, 0xed, 0x00, 0x04, 0xcf, 0xfc, 0xa0, 0x00, 0xcf, 0x78, 0x88, 0x00,
+ 0x8e, 0xfe, 0x00, 0x08, 0x8e, 0x7a, 0x00, 0x10, 0x7f, 0xf4, 0xff, 0xf8, 0x7f, 0x70, 0xff, 0xf8,
+ 0xce, 0xf4, 0x9c, 0x00, 0xce, 0x70, 0x9c, 0x00, 0xca, 0xfc, 0x94, 0x00, 0xc0, 0x76, 0xe2, 0x00,
+ 0xe6, 0x00, 0x94, 0x34, 0xcb, 0x78, 0x94, 0x00, 0x20, 0x76, 0x00, 0x09, 0xe6, 0x00, 0x93, 0xf5,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x00, 0x92, 0xc0, 0xcb, 0xd4, 0xd2, 0x00, 0xcb, 0xc0, 0xd2, 0x00,
+ 0x20, 0x5a, 0x00, 0x00, 0xe6, 0x00, 0x92, 0xd0, 0xcc, 0x58, 0xca, 0x00, 0xcc, 0x40, 0xca, 0x00,
+ 0x7f, 0xe4, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x02, 0x7e, 0x6d, 0x00, 0x04, 0xcf, 0xfc, 0x88, 0x00,
+ 0xce, 0x70, 0xa0, 0x00, 0x8f, 0x7e, 0x00, 0x10, 0xfe, 0xf3, 0x18, 0x0a, 0xfd, 0x82, 0x00, 0x04,
+ 0x4f, 0x78, 0x00, 0x00, 0xce, 0xf4, 0xf0, 0x00, 0xc0, 0x6e, 0xba, 0x00, 0xe4, 0x00, 0x93, 0x51,
+ 0x9e, 0xf2, 0x00, 0x08, 0xc0, 0x6e, 0xc2, 0x00, 0xe4, 0x00, 0x93, 0x51, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0xf6, 0xed, 0xa0, 0xcf, 0x64, 0xd8, 0x00, 0x4f, 0x78, 0xff, 0xfc, 0xcf, 0xe8, 0xd8, 0x00,
+ 0xcf, 0x78, 0xe8, 0x00, 0x7f, 0xfc, 0xff, 0xfe, 0x8f, 0x7a, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x04,
+ 0xcf, 0xfc, 0xa0, 0x00, 0x0d, 0xec, 0x00, 0x04, 0xc0, 0x6e, 0xba, 0x00, 0xe4, 0x00, 0x93, 0x51,
+ 0x9f, 0x7e, 0x00, 0x08, 0xc0, 0x6e, 0xc2, 0x00, 0xe4, 0x00, 0x93, 0x14, 0x00, 0x00, 0x00, 0x01,
+ 0x9d, 0x16, 0xff, 0xec, 0x20, 0x5a, 0x00, 0x00, 0xcd, 0x54, 0x00, 0x00, 0xe6, 0x00, 0x93, 0x81,
+ 0xcc, 0xd8, 0x00, 0x00, 0x20, 0x56, 0x00, 0x00, 0xe6, 0x00, 0x93, 0x81, 0x7f, 0x58, 0xff, 0xfe,
+ 0x8f, 0x96, 0xff, 0xf0, 0xc0, 0x7a, 0xfa, 0x00, 0xe4, 0x00, 0x92, 0x70, 0x7d, 0xe8, 0xff, 0xfe,
+ 0x8e, 0x96, 0xff, 0xec, 0xfe, 0x76, 0xed, 0xa0, 0xfd, 0x82, 0x00, 0x40, 0x7f, 0xf4, 0xff, 0xfe,
+ 0x7f, 0xfd, 0x00, 0x04, 0xcf, 0xfc, 0xa0, 0x00, 0x8f, 0x7e, 0x00, 0x08, 0x4f, 0x78, 0x00, 0xff,
+ 0x9f, 0x7e, 0x00, 0x08, 0x8e, 0xf2, 0x00, 0x0c, 0xc0, 0x6e, 0xea, 0x00, 0xe4, 0x00, 0x93, 0xd5,
+ 0x0f, 0x50, 0x04, 0x08, 0xfe, 0xf6, 0xee, 0xb0, 0x8f, 0xf5, 0x00, 0x04, 0x0d, 0xec, 0x00, 0x01,
+ 0x9f, 0xfa, 0x00, 0x00, 0x8f, 0xf2, 0x00, 0x0c, 0xc0, 0x6e, 0xfa, 0x00, 0xe4, 0x00, 0x93, 0xb8,
+ 0x0f, 0x78, 0x00, 0x10, 0xf3, 0x0a, 0xb2, 0xa8, 0xf3, 0x82, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x10,
+ 0xf7, 0x82, 0x93, 0xec, 0xe0, 0x02, 0x9c, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x90, 0x64,
+ 0x00, 0x00, 0x00, 0x01, 0x20, 0x66, 0x00, 0x88, 0xe6, 0x00, 0x93, 0x50, 0x20, 0x6a, 0x00, 0xa0,
+ 0xe6, 0x00, 0x93, 0x50, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa3, 0xe0, 0x7f, 0xfd, 0x00, 0x10,
+ 0x7f, 0xfc, 0xff, 0xe8, 0x20, 0x7e, 0x00, 0xa0, 0xe6, 0x00, 0x93, 0x50, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8a, 0xa3, 0xdf, 0xfc, 0xff, 0x68, 0x03, 0xfe, 0x82, 0x00, 0x01, 0xe0, 0x00, 0x93, 0x50,
+ 0xfe, 0x89, 0xbb, 0x50, 0x22, 0x10, 0x00, 0x14, 0x9e, 0x92, 0x00, 0x0c, 0xfe, 0x82, 0x8f, 0xe8,
+ 0x9d, 0x12, 0x00, 0x04, 0x9c, 0x92, 0x00, 0x08, 0x9e, 0x12, 0x00, 0x10, 0x9e, 0x92, 0x00, 0x00,
+ 0x9a, 0x16, 0xff, 0xe8, 0xf7, 0x82, 0x94, 0x60, 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc,
+ 0x8a, 0x16, 0xff, 0xe8, 0xe0, 0x00, 0x93, 0x80, 0x02, 0x10, 0x00, 0x14, 0xff, 0x88, 0xb2, 0xf0,
+ 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x89, 0xb2, 0xf0, 0xf7, 0x82, 0x94, 0x84, 0xe0, 0x00, 0x0d, 0x18,
+ 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x94, 0x90, 0xe0, 0x00, 0x0a, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0xfe, 0xf6, 0xff, 0xf0, 0xf0, 0x09, 0xb8, 0x24, 0xf0, 0x09, 0xb8, 0x28, 0xf0, 0x09, 0xb2, 0xd8,
+ 0xf0, 0x09, 0xb2, 0xdc, 0x8f, 0x76, 0x00, 0x00, 0x0f, 0x81, 0xe0, 0x00, 0x0f, 0xfc, 0x0f, 0xff,
+ 0xcf, 0x78, 0xfc, 0x00, 0x9f, 0x76, 0x00, 0x00, 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x82, 0x94, 0xc8,
+ 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x90, 0x64, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x09, 0xb2, 0xe0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x76, 0xff, 0xcc, 0xff, 0x9b, 0x58, 0x00,
+ 0x8e, 0xea, 0x00, 0x00, 0x0c, 0x81, 0xff, 0xf0, 0x0c, 0xe4, 0x0f, 0xff, 0x7f, 0xfd, 0x00, 0x0c,
+ 0xce, 0xf4, 0xcc, 0x00, 0xce, 0xf4, 0xfd, 0x00, 0x9e, 0xea, 0x00, 0x00, 0xff, 0x9b, 0x58, 0x01,
+ 0x4e, 0xf4, 0xf0, 0x0f, 0xfd, 0xf6, 0xff, 0xd0, 0x7f, 0xfd, 0x00, 0x04, 0xce, 0xf4, 0xfd, 0x00,
+ 0x9e, 0xea, 0x00, 0x00, 0xff, 0x9b, 0x58, 0x02, 0x8f, 0x6e, 0x00, 0x00, 0x4e, 0xf4, 0xff, 0xf0,
+ 0x7f, 0xfd, 0x00, 0x1c, 0x4f, 0x79, 0x0f, 0xff, 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x6e, 0x00, 0x00,
+ 0xff, 0x9b, 0x58, 0x02, 0xce, 0x18, 0x00, 0x00, 0x4f, 0x79, 0xf0, 0x0f, 0x7f, 0xfc, 0xff, 0xfc,
+ 0xce, 0xf4, 0xfd, 0x00, 0x9e, 0xea, 0x00, 0x00, 0xff, 0xf3, 0x58, 0x03, 0xf3, 0x76, 0xff, 0xfc,
+ 0x7f, 0xfd, 0x00, 0x14, 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x6e, 0x00, 0x00, 0xff, 0xf3, 0x58, 0x04,
+ 0xcf, 0x78, 0xcc, 0x00, 0x7f, 0xfd, 0x00, 0x0c, 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x6e, 0x00, 0x00,
+ 0xff, 0xf3, 0x58, 0x05, 0x4f, 0x78, 0xf0, 0x0f, 0x7f, 0xfd, 0x00, 0x04, 0xcf, 0x78, 0xfd, 0x00,
+ 0x9f, 0x6e, 0x00, 0x00, 0xf7, 0x82, 0x95, 0xa0, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xe6, 0xd8, 0xc0, 0x7e, 0x5a, 0x00, 0xe6, 0x00, 0x96, 0x64,
+ 0xfd, 0x82, 0x00, 0x00, 0xfd, 0x08, 0xb3, 0x68, 0x20, 0x6a, 0x01, 0x00, 0xe2, 0x00, 0x95, 0xdd,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x01, 0x00, 0xfd, 0x09, 0xb3, 0x68, 0x2f, 0xe8, 0x00, 0x01,
+ 0x7e, 0xfc, 0xff, 0xfe, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0x95, 0xfd, 0xcf, 0xf4, 0x00, 0x00,
+ 0x7f, 0xfe, 0xff, 0xff, 0xe6, 0x00, 0x95, 0xf0, 0x0d, 0xec, 0x00, 0x01, 0x0f, 0xec, 0x00, 0x02,
+ 0xff, 0x89, 0xb3, 0x6c, 0xff, 0x02, 0x00, 0x00, 0xfe, 0x0a, 0xe2, 0xd0, 0xcf, 0xf8, 0xe8, 0x00,
+ 0xcc, 0x80, 0xda, 0x00, 0xcc, 0xfc, 0xcf, 0x80, 0xbc, 0xf2, 0xf0, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0x20, 0x7a, 0x04, 0x00, 0xe2, 0x00, 0x96, 0x11, 0xcf, 0xf8, 0xe8, 0x00, 0x7f, 0xe8, 0xff, 0xfe,
+ 0x5f, 0xfd, 0xa0, 0x00, 0x9f, 0x82, 0xff, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xe1, 0xc0,
+ 0x4f, 0xfc, 0xff, 0xdf, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x96, 0x64, 0xff, 0x89, 0xe1, 0xc0,
+ 0x45, 0x29, 0x7f, 0xff, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xe6, 0xd8, 0xc0, 0x7e, 0x5a, 0x00,
+ 0xe6, 0x00, 0x96, 0xbc, 0xff, 0x8a, 0xb2, 0xde, 0xff, 0xff, 0x18, 0x00, 0xfe, 0x8a, 0xc0, 0xd0,
+ 0xff, 0x02, 0x00, 0x7f, 0xff, 0xf7, 0x28, 0x00, 0x2f, 0x7a, 0x00, 0x01, 0xea, 0x00, 0x96, 0x94,
+ 0x0e, 0xf4, 0x00, 0x40, 0xff, 0x88, 0xe1, 0xc0, 0x4f, 0xfc, 0xff, 0xef, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0x96, 0xbc, 0xff, 0x89, 0xe1, 0xc0, 0x45, 0x29, 0x7f, 0xff, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x04, 0xcc, 0x98, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0xfe, 0x0a, 0xc0, 0xc0,
+ 0xfd, 0x8a, 0xb2, 0xde, 0xfd, 0x0a, 0xc1, 0x00, 0x20, 0x7a, 0x00, 0x7f, 0x7f, 0xf9, 0x00, 0x06,
+ 0xe6, 0x00, 0x98, 0x09, 0xfe, 0x8a, 0xc0, 0xc0, 0xce, 0xfc, 0xd0, 0x00, 0xcf, 0xfc, 0xe0, 0x00,
+ 0x9e, 0xfe, 0x00, 0x2c, 0xfe, 0xef, 0x18, 0x00, 0x0f, 0x78, 0x00, 0x01, 0x20, 0x7a, 0x00, 0x7f,
+ 0xee, 0x00, 0x96, 0xed, 0xfe, 0xff, 0x28, 0x10, 0xff, 0x83, 0x1a, 0x60, 0xff, 0x02, 0x00, 0x7f,
+ 0x20, 0x66, 0x00, 0x00, 0xcf, 0xfc, 0xf4, 0x00, 0x7e, 0xfd, 0x00, 0x06, 0xcf, 0x74, 0xe0, 0x00,
+ 0xff, 0x09, 0xe6, 0xd8, 0xe6, 0x00, 0x97, 0xfd, 0xc5, 0xf8, 0x00, 0x00, 0xff, 0xf6, 0xed, 0xa0,
+ 0xfd, 0xff, 0x18, 0x02, 0xbd, 0xf6, 0xe0, 0x00, 0x8f, 0xfe, 0x00, 0x00, 0x9f, 0xfa, 0x00, 0x08,
+ 0xff, 0x83, 0x1b, 0x9a, 0x0e, 0x81, 0x00, 0x3f, 0xff, 0x02, 0x0f, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0xfe, 0x89, 0xe0, 0xd8, 0xff, 0x89, 0xf9, 0x20, 0xff, 0x02, 0x00, 0x00, 0xfe, 0x8a, 0xb2, 0xfc,
+ 0x7f, 0xf9, 0x00, 0x02, 0x0f, 0x78, 0x00, 0x01, 0x20, 0x7a, 0x00, 0x03, 0xee, 0x00, 0x97, 0x71,
+ 0xb0, 0x7e, 0xe8, 0x02, 0xff, 0x08, 0xb2, 0xcc, 0x9c, 0x96, 0xff, 0xf4, 0xf0, 0x09, 0xe2, 0xb0,
+ 0xf0, 0x09, 0xe1, 0xa0, 0xff, 0x09, 0xb3, 0x68, 0xf7, 0x82, 0x97, 0xa4, 0xe0, 0x00, 0x95, 0xac,
+ 0x97, 0x93, 0xff, 0xfc, 0x8c, 0x96, 0xff, 0xf4, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x00, 0x98, 0x11,
+ 0xf0, 0x09, 0xbc, 0xa8, 0xff, 0x02, 0x00, 0x00, 0xfd, 0x82, 0x00, 0x01, 0xfe, 0x76, 0xfd, 0xb0,
+ 0x8f, 0xf1, 0x00, 0x04, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x97, 0xf1, 0xce, 0xec, 0xf7, 0xc0,
+ 0xff, 0x88, 0xbc, 0xa8, 0xcf, 0xfc, 0xed, 0x00, 0x0f, 0x78, 0x00, 0x01, 0x20, 0x7a, 0x00, 0x0f,
+ 0xee, 0x00, 0x97, 0xc1, 0xff, 0x89, 0xbc, 0xa8, 0xe0, 0x00, 0x98, 0x10, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xbc, 0xa8, 0xe0, 0x00, 0x97, 0xdc, 0x0f, 0x78, 0x00, 0x01, 0xfc, 0xfb, 0x28, 0x00,
+ 0xe0, 0x00, 0x97, 0x50, 0x9c, 0xfa, 0x00, 0x08, 0xe0, 0x00, 0x96, 0xfc, 0xff, 0x82, 0x1f, 0xc0,
+ 0xf3, 0x08, 0xbc, 0xa8, 0x53, 0x18, 0x80, 0x00, 0xf7, 0x82, 0x98, 0x24, 0xe0, 0x01, 0xac, 0xc0,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x9b, 0x18, 0x0a, 0xcf, 0x9c, 0xfa, 0x00, 0x70, 0x7e, 0x00, 0x14,
+ 0xea, 0x00, 0x9a, 0x95, 0xfa, 0x82, 0x00, 0x02, 0xfb, 0x02, 0x00, 0x01, 0xfa, 0x02, 0x00, 0x10,
+ 0xff, 0x9b, 0x58, 0x0c, 0x8e, 0x1a, 0x00, 0x30, 0x70, 0x7e, 0x00, 0x1a, 0xea, 0x00, 0x98, 0x79,
+ 0xfc, 0x02, 0x00, 0x14, 0xfc, 0x02, 0x00, 0x10, 0xf0, 0x1b, 0x68, 0x09, 0xff, 0x82, 0x00, 0x40,
+ 0xf0, 0x03, 0x2a, 0x60, 0xcd, 0xf2, 0xfc, 0x00, 0xe6, 0x00, 0x98, 0xd9, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x9a, 0x00, 0x24, 0xfe, 0x9b, 0x18, 0x0a, 0xfe, 0xff, 0x28, 0x02, 0x8f, 0x1a, 0x00, 0x24,
+ 0x9f, 0x02, 0xfe, 0x58, 0x8f, 0x9a, 0x00, 0x28, 0x5f, 0xfd, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x83, 0x1a, 0x00, 0x2c, 0xff, 0x9b, 0x18, 0x0a,
+ 0xcf, 0x9c, 0xfa, 0x00, 0x70, 0x7e, 0x00, 0x14, 0xea, 0x00, 0x98, 0x60, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0x9a, 0x94, 0x00, 0x00, 0x00, 0x01, 0x77, 0xf0, 0x00, 0x1e, 0x70, 0x3e, 0xff, 0xe2,
+ 0xe6, 0x00, 0x99, 0x54, 0xff, 0x82, 0x03, 0xff, 0xff, 0x1b, 0x18, 0x02, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0x99, 0x3d, 0x0f, 0x98, 0x00, 0x08, 0xff, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0xff, 0xff, 0x18, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0x01, 0x10, 0x00, 0x0f, 0x78, 0x00, 0x10, 0x9f, 0x02, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x83, 0x2a, 0x60, 0x0f, 0x98, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5f, 0x61, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9d, 0x82, 0xfe, 0x80, 0xe0, 0x00, 0x98, 0xb4,
+ 0x00, 0x00, 0x00, 0x01, 0x8c, 0x9a, 0x00, 0x0c, 0x8b, 0x9a, 0x00, 0x10, 0xcd, 0x66, 0xfc, 0x00,
+ 0xe6, 0x00, 0x99, 0x6c, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x04, 0x00, 0xff, 0x9b, 0x18, 0x0a,
+ 0xfe, 0x88, 0xb3, 0x6c, 0xff, 0x02, 0x0f, 0xff, 0xcf, 0x9c, 0xfa, 0x00, 0x0f, 0xfc, 0x00, 0x01,
+ 0xcf, 0xfc, 0xf4, 0x00, 0xce, 0xfc, 0xef, 0xc0, 0x7f, 0x74, 0xff, 0xfe, 0xc0, 0x6a, 0xf2, 0x00,
+ 0xe2, 0x00, 0x99, 0xad, 0xc0, 0x72, 0xac, 0x00, 0x4f, 0xe4, 0xfc, 0x00, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x5f, 0x5c, 0x00, 0xf0, 0x9f, 0x9a, 0x00, 0x0c, 0x9f, 0x1a, 0x00, 0x10, 0xe6, 0x00, 0x99, 0xb9,
+ 0xcf, 0x6c, 0x00, 0x00, 0xff, 0x1b, 0x18, 0x22, 0xc0, 0x72, 0xb4, 0x00, 0xe6, 0x00, 0x99, 0xcd,
+ 0xc0, 0x6e, 0xea, 0x00, 0x8d, 0x9a, 0x00, 0x28, 0xc0, 0x6e, 0xea, 0x00, 0xe4, 0x00, 0x9a, 0x80,
+ 0xcf, 0xf8, 0xd8, 0x00, 0xcd, 0xf4, 0x00, 0x00, 0x4e, 0x70, 0xff, 0xfd, 0xc0, 0x72, 0xac, 0x00,
+ 0xe6, 0x00, 0x9a, 0x05, 0x0f, 0x98, 0x00, 0x08, 0xff, 0x9b, 0x18, 0x20, 0x5f, 0xfd, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9f, 0x02, 0xfe, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x0f, 0x98, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0xcf, 0xf2, 0xb4, 0x00, 0xe6, 0x00, 0x9a, 0x18,
+ 0xcf, 0x60, 0x00, 0x00, 0x5f, 0x61, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x90, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x9a, 0x55, 0xc0, 0x72, 0xa4, 0x00,
+ 0x8f, 0x9a, 0x00, 0x24, 0x9f, 0x82, 0xfe, 0x58, 0xe6, 0x00, 0x9a, 0x44, 0xcf, 0xec, 0x00, 0x00,
+ 0x5f, 0xed, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xc0, 0x72, 0xa4, 0x00, 0xe6, 0x00, 0x9a, 0x75, 0x0f, 0x98, 0x00, 0x37, 0x0e, 0x81, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0xf4, 0x00, 0x01, 0x9e, 0x82, 0xfe, 0x58, 0x90, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x9c, 0x9a, 0x00, 0x0c, 0xe0, 0x00, 0x98, 0xb8, 0x9b, 0x9a, 0x00, 0x10,
+ 0xc0, 0x7e, 0xea, 0x00, 0xe2, 0x00, 0x99, 0xe1, 0xc0, 0x72, 0xac, 0x00, 0xe0, 0x00, 0x99, 0xe0,
+ 0xcf, 0x74, 0xda, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xe1, 0xc0, 0xff, 0x02, 0x00, 0x81,
+ 0xce, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x9a, 0xd1, 0x4e, 0xfc, 0xfe, 0xff, 0x20, 0x76, 0x00, 0x00,
+ 0xe6, 0x00, 0x9b, 0x84, 0xfe, 0x89, 0xe1, 0xc0, 0xe0, 0x00, 0x9b, 0x84, 0x45, 0x29, 0x7f, 0xff,
+ 0xff, 0x88, 0xe6, 0xd8, 0xc0, 0x2e, 0xfa, 0x00, 0xe6, 0x00, 0x9b, 0x85, 0x0f, 0x01, 0x80, 0x00,
+ 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xff, 0x02, 0x00, 0x40, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02,
+ 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58,
+ 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x08, 0xe6, 0xd8, 0xfe, 0x03, 0x2a, 0x60,
+ 0x20, 0x1a, 0x00, 0x00, 0xff, 0xfb, 0x18, 0x00, 0x5f, 0xfd, 0x10, 0x00, 0x9f, 0x82, 0xff, 0x90,
+ 0xe6, 0x00, 0x9b, 0x75, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb3, 0x38, 0x0f, 0xfc, 0x00, 0x01,
+ 0xff, 0x89, 0xb3, 0x38, 0xf3, 0x09, 0xb3, 0x74, 0xff, 0x7b, 0x18, 0x00, 0xff, 0x88, 0xe1, 0xc0,
+ 0x55, 0x29, 0x80, 0x00, 0xff, 0x09, 0xb3, 0x70, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x02, 0x00, 0x28,
+ 0xff, 0x89, 0xe1, 0xc0, 0x9f, 0x02, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x9b, 0x84,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb3, 0x34, 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x00, 0x9b, 0x44,
+ 0xff, 0x89, 0xb3, 0x34, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x03, 0x1a, 0x60, 0xff, 0x82, 0x00, 0x7f,
+ 0xfe, 0x88, 0xe6, 0xd8, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x8a, 0xc0, 0xc0, 0x7f, 0x79, 0x00, 0x06,
+ 0xcf, 0xf4, 0xfa, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x00, 0x9c, 0x01, 0xf3, 0x02, 0x00, 0x06,
+ 0xff, 0xf7, 0x18, 0x00, 0x5f, 0xfd, 0x10, 0x00, 0x9f, 0x82, 0xff, 0x90, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0x9b, 0xcc, 0x00, 0x00, 0x00, 0x01,
+ 0xf7, 0x82, 0x9c, 0x0c, 0xe0, 0x00, 0x2e, 0xc0, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x08, 0xe1, 0xc0,
+ 0xff, 0x82, 0x0f, 0xff, 0xc4, 0x20, 0xfc, 0x00, 0x4f, 0x78, 0xff, 0xfe, 0xf4, 0x09, 0xe6, 0xe0,
+ 0xf0, 0x09, 0xf9, 0x10, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0x9c, 0x34, 0xff, 0x09, 0xe1, 0xc0,
+ 0x45, 0x29, 0x7f, 0xff, 0x5f, 0xf8, 0x00, 0x80, 0xf3, 0x02, 0x00, 0x01, 0xff, 0x89, 0xe1, 0xc0,
+ 0xc3, 0x98, 0x00, 0x00, 0x55, 0x29, 0x80, 0x00, 0xf7, 0x82, 0x9c, 0x54, 0xe0, 0x00, 0x7d, 0x14,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x9b, 0xcc, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x08, 0xff, 0x03, 0x1a, 0x60, 0xff, 0x82, 0x00, 0x7f, 0xfe, 0x8a, 0xc0, 0xc0,
+ 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x88, 0xe6, 0xd8, 0x7f, 0x79, 0x00, 0x06, 0xcf, 0xfc, 0xea, 0x00,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x00, 0x9c, 0xd1, 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0x9c, 0x9c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xe6, 0xe0, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x00, 0x9e, 0x69, 0xf3, 0x02, 0x00, 0x01,
+ 0xff, 0x88, 0xe1, 0xc0, 0x70, 0x7e, 0x00, 0x17, 0xea, 0x00, 0x9d, 0x24, 0xff, 0x06, 0x86, 0xa0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0x9c, 0xf0,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xf9, 0x10, 0x95, 0x96, 0xff, 0xf4, 0x0f, 0xfc, 0x00, 0x01,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x9e, 0x51, 0xff, 0x89, 0xf9, 0x10, 0x8f, 0x16, 0xff, 0xf4,
+ 0xf3, 0x88, 0xe6, 0xe0, 0xff, 0xfb, 0x18, 0x0a, 0xcf, 0x9c, 0xfa, 0x00, 0x70, 0x7e, 0x00, 0x14,
+ 0xea, 0x00, 0x9d, 0xd4, 0xff, 0x8a, 0xc0, 0xc0, 0x2e, 0xac, 0x00, 0x40, 0xc0, 0x2e, 0xfa, 0x00,
+ 0xe6, 0x00, 0x9d, 0xc9, 0x9e, 0x96, 0xff, 0xf4, 0x83, 0x16, 0xff, 0xf4, 0xf7, 0x82, 0x9d, 0x78,
+ 0xe0, 0x00, 0x98, 0x3c, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xe1, 0xc0, 0x55, 0x29, 0x80, 0x00,
+ 0x5f, 0xfc, 0x01, 0x00, 0xff, 0x89, 0xe1, 0xc0, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x00, 0x9d, 0x94, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0a, 0xe0, 0x80, 0xe0, 0x00, 0x9d, 0x68,
+ 0x9f, 0x16, 0xff, 0xf4, 0xff, 0x88, 0xf9, 0x10, 0x77, 0xfc, 0x00, 0x1e, 0x70, 0x3e, 0xff, 0xe2,
+ 0xe6, 0x00, 0x9d, 0x68, 0xff, 0xf6, 0xff, 0xe8, 0x8f, 0x7e, 0x00, 0x00, 0xf3, 0x76, 0xff, 0xfc,
+ 0x5f, 0x79, 0x10, 0x00, 0x9f, 0x7e, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xf0, 0xf7, 0x82, 0x9e, 0x08,
+ 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf0, 0x8e, 0x82, 0xff, 0xc8,
+ 0x8f, 0x7e, 0x00, 0x00, 0x4f, 0x79, 0xef, 0xff, 0x9f, 0x7e, 0x00, 0x00, 0x8f, 0x82, 0xff, 0xc8,
+ 0xcf, 0xfc, 0xea, 0x00, 0x20, 0x7e, 0x03, 0xe7, 0xe2, 0x00, 0x9e, 0x1d, 0xf3, 0x02, 0x00, 0x00,
+ 0xf3, 0x82, 0x00, 0x28, 0xc4, 0x18, 0x00, 0x00, 0xf7, 0x82, 0x9e, 0x44, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x88, 0xe6, 0xe0, 0xe0, 0x00, 0x9d, 0x68, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x02, 0x00, 0x04, 0xf7, 0x82, 0x9e, 0x60, 0xe0, 0x00, 0x7b, 0x5c, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0x9d, 0x3c, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x00, 0xf7, 0x82, 0x9e, 0x78,
+ 0xe0, 0x00, 0x7d, 0x14, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x06, 0xc0, 0x22, 0xfc, 0x00,
+ 0xe6, 0x00, 0x9c, 0xe1, 0xc3, 0x2c, 0x00, 0x00, 0xff, 0x88, 0xe6, 0xd8, 0xf3, 0xff, 0x18, 0x0a,
+ 0x23, 0x9c, 0x00, 0x01, 0xf7, 0x82, 0x9e, 0xa0, 0xe0, 0x00, 0x98, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xe1, 0xc0, 0x4f, 0xfc, 0xfe, 0x7f, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x9d, 0x88,
+ 0xff, 0x89, 0xe1, 0xc0, 0xe0, 0x00, 0x9d, 0x88, 0x45, 0x29, 0x7f, 0xff, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0xe6, 0xd8, 0xc0, 0x7e, 0x5a, 0x00, 0xe6, 0x00, 0x9e, 0xf5, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xe1, 0xc0, 0x55, 0x29, 0x80, 0x00, 0x5f, 0xfc, 0x10, 0x00, 0xe0, 0x00, 0xa1, 0xc0,
+ 0xff, 0x89, 0xe1, 0xc0, 0xff, 0x88, 0xa3, 0x80, 0x7f, 0xfd, 0x00, 0x0f, 0x7b, 0x7e, 0xff, 0xe1,
+ 0xe6, 0x00, 0x9f, 0xb5, 0xff, 0x8a, 0xb2, 0xe6, 0xfc, 0x88, 0xa3, 0xa0, 0xfd, 0x7f, 0x18, 0x00,
+ 0x20, 0x66, 0x00, 0x00, 0xfe, 0x88, 0xa3, 0xb0, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0x70, 0x00, 0x02,
+ 0xff, 0x8a, 0xbc, 0x70, 0x7f, 0x79, 0x00, 0x0d, 0xff, 0x7f, 0x28, 0x10, 0xff, 0x0a, 0xb2, 0xde,
+ 0xff, 0x7b, 0x18, 0x00, 0x7d, 0x69, 0x00, 0x0f, 0x5d, 0x68, 0x00, 0x01, 0xff, 0x7f, 0x28, 0x14,
+ 0xff, 0x02, 0x40, 0x00, 0xff, 0x7f, 0x28, 0x0c, 0xff, 0x02, 0x00, 0x0f, 0xfd, 0x7f, 0x28, 0x12,
+ 0xff, 0x7f, 0x28, 0x16, 0x7e, 0xf5, 0x00, 0x10, 0xff, 0x08, 0xa3, 0x90, 0x7e, 0xf4, 0xff, 0xf0,
+ 0xfd, 0x82, 0xff, 0x00, 0xcd, 0xf4, 0xdc, 0x00, 0x7e, 0x71, 0x00, 0x02, 0xcf, 0xf0, 0xf8, 0x00,
+ 0x7d, 0xed, 0x00, 0x08, 0x7e, 0xf5, 0x00, 0x18, 0xfc, 0x89, 0xbc, 0x88, 0xce, 0xf4, 0xdd, 0x00,
+ 0x4f, 0x78, 0xff, 0xfc, 0x0e, 0x70, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x1c, 0x9f, 0x7e, 0x00, 0x18,
+ 0xfe, 0x09, 0xbc, 0x70, 0xf0, 0x09, 0xbc, 0x74, 0xff, 0x88, 0xe1, 0xc0, 0x4f, 0xfc, 0xef, 0xff,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa1, 0xc0, 0xff, 0x89, 0xe1, 0xc0, 0xe0, 0x00, 0xa1, 0xc0,
+ 0x45, 0x29, 0x7f, 0xff, 0xff, 0x88, 0xa5, 0xb0, 0x7e, 0x7e, 0xff, 0xe1, 0xe6, 0x00, 0xa1, 0x59,
+ 0xfc, 0x82, 0xff, 0x00, 0xfe, 0x88, 0xaa, 0xac, 0xfd, 0x88, 0xaa, 0xa8, 0x7f, 0x74, 0xff, 0xf8,
+ 0xcf, 0x78, 0xcc, 0x00, 0x7e, 0x74, 0xff, 0xe8, 0xcf, 0xf4, 0xcc, 0x00, 0xce, 0x70, 0xf5, 0x00,
+ 0x7f, 0xfd, 0x00, 0x08, 0xce, 0x70, 0xfd, 0x00, 0xff, 0x8a, 0xb2, 0xe6, 0xfd, 0x7f, 0x18, 0x00,
+ 0x7e, 0xf5, 0x00, 0x18, 0xcb, 0xf2, 0xed, 0x00, 0xff, 0x8a, 0xb2, 0xde, 0xfc, 0x7f, 0x18, 0x00,
+ 0x7f, 0x6c, 0xff, 0xf8, 0xcf, 0x78, 0xcc, 0x00, 0x7e, 0xec, 0xff, 0xe8, 0xcf, 0xec, 0xcc, 0x00,
+ 0xfa, 0x88, 0xaa, 0xb0, 0xe6, 0x70, 0x00, 0x02, 0xce, 0xf4, 0xf5, 0x00, 0x7f, 0xfd, 0x00, 0x08,
+ 0x5f, 0x70, 0x00, 0x02, 0xce, 0xf4, 0xfd, 0x00, 0xff, 0x8a, 0xbc, 0x70, 0x7f, 0x79, 0x00, 0x0d,
+ 0xff, 0x7f, 0x28, 0x10, 0xff, 0x02, 0x40, 0x00, 0xff, 0x7f, 0x28, 0x0c, 0x7d, 0x69, 0x00, 0x0f,
+ 0x5d, 0x68, 0x00, 0x01, 0xff, 0x02, 0x00, 0x0f, 0x7e, 0x71, 0x00, 0x02, 0xfd, 0x7f, 0x28, 0x12,
+ 0xfc, 0x7f, 0x28, 0x14, 0xff, 0x7f, 0x28, 0x16, 0xcf, 0xf0, 0xf8, 0x00, 0x7d, 0xed, 0x00, 0x18,
+ 0xfb, 0x89, 0xbc, 0x88, 0xce, 0xf4, 0xdd, 0x00, 0x0e, 0x70, 0x00, 0x14, 0xca, 0x58, 0x00, 0x00,
+ 0x9a, 0xfe, 0x00, 0x1c, 0x9e, 0xfe, 0x00, 0x18, 0xfe, 0x09, 0xbc, 0x70, 0xfb, 0x09, 0xbc, 0x74,
+ 0xc8, 0x68, 0x00, 0x00, 0xf8, 0x8a, 0xe6, 0xf0, 0xf9, 0x0a, 0xaa, 0xa8, 0xf9, 0x82, 0x00, 0xff,
+ 0x7f, 0xd1, 0x00, 0x04, 0xcf, 0x7c, 0x90, 0x00, 0x8e, 0x7a, 0x00, 0x04, 0xad, 0x7e, 0x90, 0x02,
+ 0x8a, 0xfa, 0x00, 0x08, 0x7e, 0xf0, 0xff, 0xf8, 0x7f, 0xf0, 0xff, 0xe8, 0xce, 0xf4, 0xcc, 0x00,
+ 0xcf, 0x70, 0xcc, 0x00, 0xcf, 0xfc, 0x9c, 0x00, 0xcf, 0xfc, 0xed, 0x00, 0x7f, 0x79, 0x00, 0x08,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x7e, 0x71, 0x00, 0x18, 0xcb, 0xfe, 0xe5, 0x00, 0x7e, 0xe8, 0xff, 0xe8,
+ 0x7f, 0xe8, 0xff, 0xf8, 0xcf, 0xfc, 0xcc, 0x00, 0xcf, 0x68, 0xcc, 0x00, 0xce, 0xf4, 0x9c, 0x00,
+ 0xe6, 0x70, 0x00, 0x02, 0xce, 0xf4, 0xfd, 0x00, 0x7f, 0x79, 0x00, 0x08, 0x7d, 0xf1, 0x00, 0x02,
+ 0xce, 0xf4, 0xf5, 0x00, 0x0f, 0x6c, 0x00, 0x14, 0xbf, 0x5a, 0x88, 0x02, 0xcf, 0xd8, 0x88, 0x00,
+ 0xff, 0x02, 0x40, 0x00, 0xff, 0x7f, 0x28, 0x0c, 0x5e, 0x70, 0x00, 0x02, 0x7d, 0x69, 0x00, 0x18,
+ 0x7e, 0x71, 0x00, 0x0d, 0xff, 0x02, 0x00, 0x0f, 0xfe, 0x7f, 0x28, 0x10, 0x9b, 0xfe, 0x00, 0x18,
+ 0xf8, 0x7f, 0x28, 0x12, 0xfc, 0x7f, 0x28, 0x14, 0xff, 0x7f, 0x28, 0x16, 0xcd, 0xec, 0xf8, 0x00,
+ 0xce, 0xf4, 0xd5, 0x00, 0x0a, 0x50, 0x00, 0x01, 0x9a, 0xee, 0x00, 0x1c, 0x9e, 0xee, 0x00, 0x18,
+ 0x90, 0x7e, 0x00, 0x04, 0x20, 0x52, 0x00, 0x7f, 0xee, 0x00, 0xa0, 0x91, 0x0b, 0x58, 0x00, 0x24,
+ 0xe0, 0x00, 0x9f, 0x98, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa2, 0x80, 0x70, 0x7e, 0x00, 0x15,
+ 0xea, 0x00, 0xa1, 0xb9, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xfe, 0x8a, 0xbc, 0x70,
+ 0xfe, 0x09, 0xbc, 0x8c, 0xff, 0x0a, 0xb2, 0xde, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0x7b, 0x18, 0x00,
+ 0xff, 0xf7, 0x28, 0x12, 0xff, 0x82, 0x00, 0x20, 0xff, 0x77, 0x28, 0x14, 0xff, 0xf7, 0x28, 0x16,
+ 0xff, 0x02, 0x40, 0x00, 0xff, 0x82, 0x34, 0x00, 0xff, 0x77, 0x28, 0x0c, 0xff, 0xf7, 0x28, 0x10,
+ 0xff, 0x02, 0x00, 0x14, 0xff, 0x82, 0x00, 0x01, 0xfe, 0x09, 0xbc, 0x88, 0xff, 0x09, 0xbc, 0x70,
+ 0xe0, 0x00, 0x9f, 0x98, 0xff, 0x89, 0xbc, 0x74, 0xe0, 0x00, 0x9f, 0x98, 0xfe, 0x09, 0xbc, 0x70,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x8f, 0xae, 0x00, 0x38, 0xff, 0x0a, 0xb2, 0xfc, 0x7f, 0xfd, 0x00, 0x02,
+ 0xb0, 0x7e, 0xf0, 0x02, 0x85, 0xae, 0x00, 0x2c, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa1, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8f, 0x82, 0xff, 0xf8, 0x85, 0xae, 0x00, 0x2c, 0x70, 0x7e, 0x00, 0x12, 0xea, 0x00, 0xa2, 0xcd,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xe1, 0xc0, 0x55, 0x29, 0x80, 0x00, 0x5f, 0xfc, 0x20, 0x00,
+ 0xff, 0x89, 0xe1, 0xc0, 0x70, 0x7e, 0x00, 0x14, 0xea, 0x00, 0xa2, 0x94, 0x0f, 0x81, 0x20, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa2, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x9f, 0x82, 0xff, 0x88, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa2, 0x98, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xe1, 0xc0,
+ 0xe0, 0x00, 0xa2, 0x54, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x85, 0xae, 0x00, 0x2c,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa2, 0xf0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x8d, 0x96, 0x00, 0x08, 0xff, 0x82, 0x00, 0x7f,
+ 0x8e, 0x96, 0x00, 0x00, 0xfe, 0x08, 0xe6, 0xd8, 0xc3, 0x18, 0xfc, 0x00, 0xff, 0x02, 0x0f, 0xff,
+ 0xc4, 0xa4, 0xf4, 0x00, 0x73, 0x9d, 0x00, 0x08, 0x7f, 0xed, 0x00, 0x0d, 0xcf, 0xfc, 0x4d, 0x00,
+ 0xc3, 0x9c, 0x30, 0x00, 0x9e, 0xf2, 0x00, 0x0c, 0xff, 0xf3, 0x28, 0x12, 0x93, 0xf2, 0x00, 0x14,
+ 0xff, 0x0a, 0xb2, 0xde, 0xff, 0x7b, 0x18, 0x00, 0xff, 0x82, 0x03, 0xff, 0xce, 0xf4, 0xfc, 0x00,
+ 0xff, 0x73, 0x28, 0x10, 0x8f, 0x96, 0x00, 0x04, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa3, 0xb9,
+ 0x7c, 0xf5, 0x00, 0x02, 0x20, 0x6e, 0x00, 0x00, 0xe6, 0x00, 0xa3, 0xb8, 0x44, 0x20, 0xff, 0xfc,
+ 0x94, 0x02, 0xfe, 0x68, 0x9c, 0x82, 0xfe, 0x68, 0xff, 0x0a, 0xe1, 0x00, 0x9f, 0x02, 0xfe, 0x68,
+ 0x9d, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x78, 0x00, 0x02,
+ 0xfd, 0xf3, 0x18, 0x0a, 0x8d, 0x72, 0x00, 0x2c, 0x9f, 0x72, 0x00, 0x30, 0x0f, 0xf0, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xa3, 0xe8, 0xff, 0x82, 0x00, 0x10,
+ 0x0f, 0x81, 0x10, 0x00, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0x30,
+ 0x9f, 0xf2, 0x00, 0x04, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xa4, 0x19, 0xfd, 0x09, 0xe6, 0xd8,
+ 0xff, 0x0a, 0xe1, 0x00, 0x9f, 0x72, 0x00, 0x24, 0x9c, 0xf2, 0x00, 0x28, 0x9f, 0x02, 0xfe, 0x58,
+ 0x5f, 0xe5, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x0d, 0xec, 0x00, 0x01, 0x4d, 0xec, 0x0f, 0xff,
+ 0xfd, 0xeb, 0x28, 0x00, 0x9d, 0xea, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x73, 0x28, 0x02, 0x9e, 0x82, 0xff, 0x18, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c,
+ 0x8f, 0x16, 0x00, 0x04, 0x22, 0x10, 0x00, 0x0c, 0xcf, 0x98, 0x00, 0x00, 0x9f, 0x12, 0x00, 0x08,
+ 0x8f, 0x16, 0x00, 0x00, 0x94, 0x92, 0x00, 0x04, 0xc3, 0x1c, 0x00, 0x00, 0xc4, 0xa0, 0x00, 0x00,
+ 0x9f, 0x12, 0x00, 0x00, 0xc3, 0xfc, 0x00, 0x00, 0xc4, 0x18, 0x00, 0x00, 0xf7, 0x82, 0xa4, 0x88,
+ 0xe0, 0x00, 0xa3, 0x30, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xe2, 0xb0,
+ 0x2f, 0xfc, 0x00, 0x01, 0xff, 0x89, 0xe2, 0xb0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa4, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0xe2, 0xb0, 0x85, 0xae, 0x00, 0x2c, 0x2f, 0xfc, 0x00, 0x01, 0xff, 0x89, 0xe2, 0xb0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa5, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xfe, 0x88, 0xbc, 0xa8,
+ 0xff, 0x02, 0x00, 0x00, 0xfe, 0x06, 0x00, 0x00, 0xcf, 0xf0, 0xf7, 0xc0, 0xc0, 0x76, 0xfc, 0x00,
+ 0xe6, 0x00, 0xa5, 0x7c, 0xcf, 0x84, 0xfe, 0x00, 0x0f, 0x78, 0x00, 0x01, 0x20, 0x7a, 0x00, 0x0f,
+ 0xee, 0x00, 0xa5, 0x5d, 0xcf, 0xf0, 0xf7, 0xc0, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0xf4, 0xfc, 0x00,
+ 0x40, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa5, 0xa4, 0xff, 0x89, 0xbc, 0xa8, 0xff, 0x88, 0xe1, 0xc0,
+ 0x4f, 0xfc, 0xff, 0xbf, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa5, 0xa4, 0xff, 0x89, 0xe1, 0xc0,
+ 0x45, 0x29, 0x7f, 0xff, 0xf3, 0x02, 0x00, 0x00, 0xc4, 0x18, 0x00, 0x00, 0x9f, 0x16, 0xff, 0xf4,
+ 0xf3, 0x82, 0x00, 0x0e, 0xf7, 0x82, 0xa5, 0xc0, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x16, 0xff, 0xf4, 0xc3, 0x78, 0x00, 0x00, 0xf7, 0x82, 0xa5, 0xd4, 0xe0, 0x01, 0xae, 0xd4,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10, 0x93, 0x16, 0xff, 0xf4,
+ 0xf3, 0x02, 0x00, 0x02, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0xa6, 0x04, 0xe0, 0x00, 0x7d, 0x14,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4, 0xff, 0x83, 0x1a, 0x42, 0x73, 0x79, 0x00, 0x1c,
+ 0x53, 0x19, 0x08, 0x00, 0x4f, 0xfd, 0x00, 0x00, 0x93, 0x16, 0xff, 0xe8, 0x9f, 0x96, 0xff, 0xf0,
+ 0xf7, 0x82, 0xa6, 0x2c, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x0f, 0x81, 0x40, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x16, 0xff, 0xe8, 0x9f, 0x02, 0xfe, 0x58, 0x8f, 0x02, 0xff, 0xc8,
+ 0x8f, 0x96, 0xff, 0xf0, 0x9f, 0x96, 0xff, 0xec, 0x8f, 0x82, 0xff, 0xc8, 0xcf, 0xfc, 0xf2, 0x00,
+ 0x20, 0x7e, 0x03, 0xe7, 0xe2, 0x00, 0xa6, 0x49, 0xf3, 0x02, 0x00, 0x02, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x82, 0xa6, 0x6c, 0xe0, 0x00, 0x7d, 0x14, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x1a, 0x42,
+ 0x8f, 0x16, 0xff, 0xec, 0x4f, 0xfd, 0x00, 0x00, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0xa6, 0x20,
+ 0x9f, 0x96, 0xff, 0xf0, 0xff, 0x82, 0x00, 0x40, 0xc0, 0x22, 0xfc, 0x00, 0xe6, 0x00, 0xa6, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x28, 0xfe, 0x88, 0xbc, 0xa8,
+ 0xfe, 0x02, 0x00, 0x00, 0xfd, 0x82, 0x00, 0x01, 0xcf, 0xec, 0xe7, 0xc0, 0xc0, 0x76, 0xfc, 0x00,
+ 0xe6, 0x78, 0x00, 0x03, 0x2f, 0x94, 0x00, 0x18, 0xbf, 0x7e, 0xe0, 0x04, 0x0e, 0x70, 0x00, 0x01,
+ 0x20, 0x72, 0x00, 0x0f, 0xe2, 0x00, 0xa6, 0xbd, 0xcf, 0xec, 0xe7, 0xc0, 0xfe, 0x08, 0xe6, 0xd8,
+ 0xc0, 0x2e, 0xe2, 0x00, 0xe6, 0x00, 0xa7, 0x19, 0xcf, 0x2c, 0x00, 0x00, 0xff, 0xfb, 0x58, 0x0c,
+ 0x4e, 0xfc, 0xff, 0xdf, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xa7, 0x08, 0x2d, 0x94, 0x00, 0x18,
+ 0xff, 0xfb, 0x58, 0x12, 0xbe, 0xee, 0xf8, 0x04, 0x8f, 0x7a, 0x00, 0x2c, 0xc0, 0x7a, 0xe2, 0x00,
+ 0xe6, 0x00, 0xa6, 0xec, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x17, 0x6b, 0xf7, 0x23, 0x14, 0x00, 0x18,
+ 0x23, 0x94, 0x00, 0x28, 0xf7, 0x82, 0xa7, 0x30, 0xe0, 0x01, 0xad, 0x34, 0x97, 0x93, 0xff, 0xfc,
+ 0xfe, 0x02, 0x00, 0x00, 0xfd, 0x8a, 0xf9, 0x30, 0x2f, 0x14, 0x00, 0x18, 0xaf, 0xfa, 0xe0, 0x05,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa7, 0xcd, 0x2f, 0x14, 0x00, 0x28, 0xaf, 0xfa, 0xe0, 0x05,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa7, 0x69, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xd0,
+ 0xe0, 0x00, 0xa7, 0xcc, 0x9f, 0xee, 0x00, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0x8f, 0x6e, 0x00, 0x00,
+ 0xfe, 0x88, 0xe1, 0xa8, 0xcf, 0xfc, 0xf2, 0x00, 0xc0, 0x7e, 0xea, 0x00, 0xe2, 0x00, 0xa7, 0xcd,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xa7, 0xcd, 0xc3, 0x70, 0x00, 0x00, 0x9d, 0x96, 0xff, 0xd4,
+ 0x9e, 0x16, 0xff, 0xd0, 0xf7, 0x82, 0xa7, 0xa0, 0xe0, 0x00, 0xa5, 0xe0, 0x97, 0x93, 0xff, 0xfc,
+ 0x8e, 0x16, 0xff, 0xd0, 0xfe, 0x88, 0xbc, 0xa8, 0xff, 0x08, 0xe1, 0xc0, 0xff, 0x86, 0x00, 0x01,
+ 0xcf, 0xfc, 0xe7, 0xc0, 0x8d, 0x96, 0xff, 0xd4, 0xce, 0xf4, 0xfd, 0x00, 0x5f, 0x78, 0x00, 0x40,
+ 0x55, 0x29, 0x80, 0x00, 0xff, 0x09, 0xe1, 0xc0, 0xfe, 0x89, 0xbc, 0xa8, 0x0e, 0x70, 0x00, 0x01,
+ 0x20, 0x72, 0x00, 0x0f, 0xe2, 0x00, 0xa7, 0x39, 0x0d, 0xec, 0x00, 0x04, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8f, 0x9a, 0x00, 0x00, 0x55, 0x29, 0x80, 0x00, 0xff, 0x89, 0xe0, 0xe8, 0x8f, 0x9a, 0x00, 0x04,
+ 0xff, 0x89, 0xfb, 0x90, 0x8f, 0x9a, 0x00, 0x08, 0xff, 0x89, 0xe2, 0xb8, 0x8f, 0x9a, 0x00, 0x0c,
+ 0xff, 0x89, 0xe1, 0xb8, 0x8f, 0x9a, 0x00, 0x10, 0xff, 0x89, 0xe1, 0xb0, 0x8f, 0x9a, 0x00, 0x14,
+ 0xff, 0x89, 0xf9, 0x70, 0xff, 0x88, 0xe1, 0xc0, 0x83, 0x1a, 0x00, 0x18, 0x5f, 0xfc, 0x00, 0x08,
+ 0xf3, 0x09, 0xe0, 0xe0, 0xff, 0x89, 0xe1, 0xc0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04,
+ 0xfd, 0x82, 0x00, 0x00, 0xcf, 0x84, 0x56, 0x00, 0x70, 0x7e, 0x00, 0x01, 0xce, 0x18, 0x00, 0x00,
+ 0xea, 0x00, 0xa8, 0xb8, 0xcd, 0x6c, 0x00, 0x00, 0x4f, 0x9d, 0x00, 0x00, 0x73, 0xfc, 0xff, 0xfa,
+ 0x20, 0x1e, 0x00, 0x07, 0xe2, 0x00, 0xa8, 0xb8, 0x7f, 0x9d, 0x00, 0x02, 0xff, 0x02, 0xa8, 0x8c,
+ 0xae, 0xfe, 0xf0, 0x02, 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xa8, 0xac,
+ 0x00, 0x00, 0xa8, 0xec, 0x00, 0x00, 0xa9, 0x40, 0x00, 0x00, 0xa9, 0x70, 0x00, 0x00, 0xa9, 0xac,
+ 0x00, 0x00, 0xa9, 0xc4, 0x00, 0x00, 0xa8, 0xb8, 0x00, 0x00, 0xaa, 0x0c, 0xf7, 0x82, 0xa8, 0xb8,
+ 0xe0, 0x00, 0xa7, 0xe8, 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa8, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x1a, 0x00, 0x00,
+ 0xff, 0x09, 0xc0, 0xb0, 0x8f, 0x9a, 0x00, 0x04, 0xff, 0x89, 0xf8, 0xf0, 0x8f, 0x1a, 0x00, 0x08,
+ 0xff, 0x09, 0xf9, 0x28, 0x8f, 0x9a, 0x00, 0x0c, 0xff, 0x89, 0xe1, 0xc8, 0x8f, 0x1a, 0x00, 0x10,
+ 0x20, 0x7f, 0x00, 0x20, 0xff, 0x09, 0xe0, 0xe8, 0x8f, 0x1a, 0x00, 0x14, 0xff, 0x09, 0xfb, 0x90,
+ 0x8e, 0x1a, 0x00, 0x18, 0xe2, 0x00, 0xa8, 0xb8, 0xfe, 0x09, 0xe2, 0xb8, 0xff, 0x88, 0xe1, 0xc0,
+ 0x55, 0x29, 0x80, 0x00, 0x5f, 0xfc, 0x00, 0x02, 0xe0, 0x00, 0xa8, 0xb8, 0xff, 0x89, 0xe1, 0xc0,
+ 0xf0, 0x09, 0xe1, 0xc8, 0x8f, 0x9a, 0x00, 0x00, 0xff, 0x26, 0x57, 0x78, 0x55, 0x29, 0x80, 0x00,
+ 0xff, 0x89, 0xe0, 0xe8, 0xff, 0x88, 0xe1, 0xc0, 0x8e, 0x1a, 0x00, 0x04, 0x5f, 0xfc, 0x00, 0x02,
+ 0xfe, 0x09, 0xfb, 0x90, 0xff, 0x89, 0xe1, 0xc0, 0xe0, 0x00, 0xa8, 0xb8, 0xff, 0x09, 0xe2, 0xb8,
+ 0xf0, 0x09, 0xe1, 0xc8, 0x8f, 0x9a, 0x00, 0x00, 0x55, 0x29, 0x80, 0x00, 0xff, 0x89, 0xe0, 0xe8,
+ 0x8f, 0x1a, 0x00, 0x04, 0xff, 0x88, 0xe1, 0xc0, 0xff, 0x09, 0xfb, 0x90, 0x8d, 0x1a, 0x00, 0x08,
+ 0x5f, 0xfc, 0x00, 0x02, 0xff, 0x89, 0xe1, 0xc0, 0xf7, 0x82, 0xa9, 0xa4, 0xc1, 0x68, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xa8, 0xb8, 0xf4, 0x09, 0xe2, 0xb8, 0x83, 0x1a, 0x00, 0x00,
+ 0xf7, 0x82, 0xa9, 0xbc, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xa8, 0xb8,
+ 0x00, 0x00, 0x00, 0x01, 0x83, 0x9a, 0x00, 0x04, 0x83, 0x1a, 0x00, 0x00, 0x9e, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0xa9, 0xdc, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x16, 0xff, 0xf4,
+ 0xf4, 0x09, 0xe2, 0xb8, 0x8f, 0xf2, 0x00, 0x08, 0xff, 0x89, 0xe0, 0xe8, 0x8f, 0x72, 0x00, 0x0c,
+ 0xff, 0x09, 0xfb, 0x90, 0x8f, 0xf2, 0x00, 0x10, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa8, 0xb9,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xa9, 0x2c, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x09, 0xe1, 0xc8,
+ 0x8f, 0x9a, 0x00, 0x00, 0x20, 0x6e, 0x00, 0x00, 0x55, 0x29, 0x80, 0x00, 0xff, 0x89, 0xe0, 0xe8,
+ 0x8f, 0x1a, 0x00, 0x04, 0xff, 0x09, 0xfb, 0x90, 0x8f, 0x9a, 0x00, 0x08, 0xff, 0x89, 0xe2, 0xb8,
+ 0x8f, 0x1a, 0x00, 0x0c, 0xff, 0x09, 0xbc, 0xa0, 0x8f, 0x9a, 0x00, 0x10, 0xff, 0x89, 0xe0, 0xf0,
+ 0xff, 0x88, 0xe1, 0xc0, 0x8e, 0x1a, 0x00, 0x14, 0x5f, 0xfc, 0x00, 0x02, 0xfe, 0x09, 0xe1, 0xa0,
+ 0xe6, 0x00, 0xa8, 0xb9, 0xff, 0x89, 0xe1, 0xc0, 0xe0, 0x00, 0xa9, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x7e, 0x21, 0x00, 0x02, 0xcf, 0x9c, 0xe0, 0x00, 0x2f, 0xfc, 0x00, 0x01,
+ 0xff, 0x02, 0x00, 0x3c, 0xcf, 0x1c, 0xf4, 0x00, 0xcf, 0x9c, 0xfe, 0x00, 0xfe, 0x8a, 0xe1, 0xe0,
+ 0x40, 0x7e, 0xff, 0xc0, 0xe6, 0x00, 0xaa, 0xd1, 0xce, 0xf8, 0xe8, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xaa, 0x9c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0xfa, 0x80, 0x00, 0xcf, 0x7c, 0x32, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xee, 0x00, 0xac, 0x01,
+ 0xcf, 0xf0, 0xf2, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xee, 0x00, 0xab, 0xed, 0x00, 0x00, 0x00, 0x01,
+ 0x93, 0x02, 0xfe, 0x68, 0x9f, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xfe, 0x7a, 0x00, 0x00, 0x9e, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68,
+ 0xcf, 0xf4, 0xf0, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8a, 0xe0, 0xc8, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xab, 0xb9, 0xff, 0x82, 0x00, 0x01,
+ 0xff, 0x02, 0x00, 0x3c, 0xcf, 0xfc, 0x47, 0xc0, 0xcf, 0x1c, 0xf4, 0x00, 0xfe, 0x88, 0xe0, 0xc8,
+ 0x2f, 0xfc, 0x00, 0x01, 0x7f, 0x78, 0xff, 0xfe, 0xcf, 0xfc, 0xf7, 0xc0, 0xce, 0xf4, 0xfd, 0x00,
+ 0x20, 0x76, 0xff, 0xff, 0xe6, 0x00, 0xab, 0x95, 0x4f, 0x9d, 0x00, 0xff, 0xfe, 0x89, 0xe0, 0xc8,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xab, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0xfc, 0xff, 0xee, 0xf0, 0x09, 0xe0, 0xc8, 0x7f, 0xfd, 0x00, 0x02,
+ 0x8f, 0x7e, 0x05, 0x08, 0x43, 0x9c, 0xff, 0xc0, 0xf3, 0x0a, 0xe1, 0xe0, 0xf7, 0x82, 0xab, 0xb8,
+ 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xab, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68,
+ 0x9e, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0xe0, 0x00, 0xab, 0x18, 0x00, 0x00, 0x00, 0x01,
+ 0x2f, 0x98, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0xe0, 0x00, 0xab, 0xf0, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xe1, 0xc0, 0x85, 0xae, 0x00, 0x2c, 0x4f, 0xfc, 0xff, 0xf9,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xac, 0x40, 0xff, 0x89, 0xe1, 0xc0, 0x45, 0x29, 0x7f, 0xff,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xac, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xe1, 0xc0, 0x85, 0xae, 0x00, 0x2c,
+ 0x4f, 0xfc, 0xff, 0xfb, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xac, 0xa4, 0xff, 0x89, 0xe1, 0xc0,
+ 0x45, 0x29, 0x7f, 0xff, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x00, 0xac, 0xa4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xe1, 0xc0,
+ 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x00, 0xad, 0x30, 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xac, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x88, 0xe1, 0xc8, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xae, 0xa5, 0xfc, 0x82, 0x00, 0x04,
+ 0xfb, 0x88, 0xf8, 0xf0, 0xff, 0x82, 0x00, 0x7f, 0xff, 0x02, 0x00, 0x80, 0xcf, 0xdc, 0xfc, 0x00,
+ 0xfc, 0x08, 0xc0, 0xb0, 0xcc, 0xf8, 0xfa, 0x00, 0xc0, 0x76, 0xca, 0x00, 0xe4, 0x00, 0xad, 0x69,
+ 0x00, 0x00, 0x00, 0x01, 0xcc, 0xf4, 0x00, 0x00, 0xff, 0x88, 0xf9, 0x28, 0xfb, 0x0a, 0xe2, 0x30,
+ 0xfa, 0x82, 0xac, 0x80, 0x9f, 0x82, 0xfe, 0x68, 0x9c, 0x82, 0xfe, 0x68, 0x9b, 0x02, 0xfe, 0x68,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xce, 0xf4, 0xca, 0x00, 0xcf, 0x5c, 0xc8, 0x00,
+ 0xcf, 0xfc, 0xc8, 0x00, 0xff, 0x89, 0xf9, 0x28, 0xff, 0x09, 0xf8, 0xf0, 0xfe, 0x89, 0xe1, 0xc8,
+ 0x7f, 0xe4, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x70, 0x00, 0x02, 0x20, 0x62, 0x00, 0x00,
+ 0xfe, 0x88, 0xe6, 0xd8, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xff, 0x82, 0x7c, 0xcc, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xce, 0x70, 0xf8, 0x00, 0xff, 0x88, 0xb2, 0xe4, 0x7f, 0x64, 0xff, 0xfe, 0xfd, 0x73, 0x58, 0x20,
+ 0x4f, 0x78, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xf5, 0x00, 0xff, 0xf7, 0x28, 0x0e,
+ 0x7d, 0xed, 0x00, 0x02, 0xcf, 0xf4, 0xd8, 0x00, 0xfd, 0x77, 0x28, 0x12, 0x9c, 0x76, 0x00, 0x14,
+ 0x9b, 0xfe, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10, 0xff, 0x86, 0x00, 0x01, 0x9f, 0xf6, 0x00, 0x30,
+ 0xff, 0x77, 0x18, 0x0a, 0x8e, 0x76, 0x00, 0x2c, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x9d, 0x82, 0xfe, 0x58, 0x0f, 0xd4, 0x00, 0x08, 0x9f, 0xf6, 0x00, 0x04, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x9b, 0x76, 0x00, 0x24, 0x9c, 0xf6, 0x00, 0x28, 0x9b, 0x02, 0xfe, 0x58, 0x5f, 0xe5, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0f, 0x78, 0x00, 0x01, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x77, 0x28, 0x02,
+ 0xff, 0x88, 0xe1, 0xc0, 0x55, 0x29, 0x80, 0x00, 0x5f, 0xfc, 0x00, 0x04, 0xff, 0x89, 0xe1, 0xc0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xae, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0x08, 0xe0, 0xe8, 0xfb, 0x88, 0xfb, 0x90, 0xfb, 0x0a, 0xe2, 0xb8,
+ 0xe0, 0x00, 0xad, 0xa0, 0xfa, 0x82, 0xac, 0x1c, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x93, 0x02, 0xfe, 0x68,
+ 0x93, 0x82, 0xfe, 0x68, 0x94, 0x02, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xc1, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xae, 0xe8, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x48, 0x61, 0x6e, 0x64,
+ 0x6f, 0x66, 0x66, 0x3a, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69,
+ 0x6c, 0x69, 0x74, 0x79, 0x0a, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x14, 0xff, 0x88, 0xe6, 0xd8, 0xfe, 0x82, 0x00, 0x00, 0x9e, 0x96, 0xff, 0xec,
+ 0xc0, 0x2e, 0xfa, 0x00, 0xe6, 0x00, 0xaf, 0x71, 0x9e, 0x96, 0xff, 0xf0, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xaf, 0x3c, 0x00, 0x00, 0x00, 0x01,
+ 0xf7, 0x82, 0xaf, 0x7c, 0xe0, 0x01, 0xae, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xe2, 0xb0,
+ 0xc0, 0x22, 0xfd, 0x00, 0xe6, 0x00, 0xaf, 0x3c, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x88, 0xf9, 0x70,
+ 0x20, 0x76, 0x00, 0x3c, 0xe2, 0x00, 0xb2, 0xa4, 0xff, 0x02, 0x00, 0x00, 0xff, 0x88, 0xe1, 0xb8,
+ 0xcf, 0x7c, 0xea, 0x00, 0x8f, 0x7a, 0x00, 0x3c, 0xcf, 0xfc, 0xf0, 0x00, 0xcf, 0xfc, 0xea, 0x00,
+ 0x9f, 0x96, 0xff, 0xf4, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xaf, 0xf9, 0xff, 0x82, 0x00, 0x03,
+ 0x8e, 0x96, 0xff, 0xf4, 0x8f, 0xf6, 0x00, 0x00, 0x20, 0x7e, 0x00, 0xa4, 0xe2, 0x00, 0xaf, 0xf9,
+ 0xff, 0x82, 0x00, 0x03, 0xff, 0xf7, 0x18, 0xa4, 0x9f, 0x96, 0xff, 0xf0, 0xfe, 0xf7, 0x18, 0xa6,
+ 0xff, 0x8a, 0xb8, 0x88, 0xff, 0xff, 0x58, 0x9a, 0x9e, 0x96, 0xff, 0xec, 0x8e, 0x96, 0xff, 0xf4,
+ 0xff, 0xf7, 0x68, 0x9a, 0xff, 0x82, 0x00, 0x03, 0x9f, 0x96, 0xff, 0xe8, 0xff, 0x88, 0xbb, 0x50,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xb0, 0x11, 0xfe, 0x82, 0x00, 0x02, 0x9e, 0x96, 0xff, 0xe8,
+ 0xff, 0x88, 0xa4, 0xf0, 0x7f, 0xfd, 0x00, 0x10, 0x7f, 0xfc, 0xff, 0xe8, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0xb0, 0x34, 0x20, 0x7a, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xe8, 0x4f, 0xfc, 0xff, 0xfd,
+ 0x9f, 0x96, 0xff, 0xe8, 0xe6, 0x00, 0xb0, 0x65, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xf0,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xb0, 0x64, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xec,
+ 0x8e, 0x96, 0xff, 0xe8, 0xcf, 0x84, 0xf6, 0x00, 0xc0, 0x76, 0xfc, 0x00, 0xe6, 0x00, 0xb0, 0xe9,
+ 0x00, 0x00, 0x00, 0x01, 0x22, 0x10, 0x00, 0x04, 0xff, 0x02, 0xae, 0xfc, 0x9f, 0x12, 0x00, 0x00,
+ 0xf7, 0x82, 0xb0, 0x7c, 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x08, 0xe2, 0xb8,
+ 0xff, 0x88, 0xe1, 0xc0, 0xf0, 0x09, 0xe1, 0xc8, 0xcf, 0x04, 0xf6, 0x00, 0x4f, 0xfc, 0xff, 0xf7,
+ 0xff, 0x09, 0xe2, 0xb8, 0x20, 0x7e, 0x00, 0x00, 0xff, 0x89, 0xe1, 0xc0, 0xe6, 0x00, 0xb0, 0xa8,
+ 0x02, 0x10, 0x00, 0x04, 0x45, 0x29, 0x7f, 0xff, 0xf7, 0x82, 0xb0, 0xb4, 0xe0, 0x00, 0x7c, 0xf0,
+ 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x00, 0xb0, 0xb4, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb0, 0xf4, 0xe0, 0x00, 0xb6, 0xe4,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x82, 0x7f, 0xff, 0xc4, 0x20, 0xfc, 0x00, 0xff, 0xf6, 0xed, 0xa0,
+ 0x94, 0x7e, 0x00, 0x04, 0xff, 0x88, 0xb2, 0xd8, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xb2, 0x8d,
+ 0x03, 0x01, 0xe1, 0x00, 0xff, 0x02, 0x00, 0x80, 0xfe, 0xf6, 0xed, 0xa0, 0x9f, 0x76, 0x00, 0x0c,
+ 0xff, 0x88, 0xb2, 0xdc, 0xcd, 0xf8, 0x00, 0x00, 0xfe, 0x02, 0x00, 0x00, 0x9f, 0xf6, 0x00, 0x08,
+ 0xfe, 0xf6, 0xed, 0xb0, 0xff, 0x0a, 0xa2, 0x70, 0x8f, 0xfa, 0x00, 0x00, 0x0e, 0x70, 0x00, 0x01,
+ 0xc0, 0x72, 0xda, 0x00, 0x9f, 0xf5, 0x00, 0x04, 0xe4, 0x00, 0xb1, 0x38, 0x0f, 0x78, 0x00, 0x10,
+ 0xff, 0x88, 0xbb, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xb1, 0x8d, 0xff, 0xf6, 0xed, 0xa0,
+ 0xff, 0x8a, 0xa2, 0x68, 0x0f, 0x7c, 0x02, 0x88, 0xfe, 0x02, 0x00, 0x00, 0xfe, 0xf6, 0xee, 0x38,
+ 0x8f, 0xfa, 0x00, 0x00, 0x0e, 0x70, 0x00, 0x01, 0x20, 0x72, 0x00, 0x07, 0x9f, 0xf5, 0x00, 0x04,
+ 0xe2, 0x00, 0xb1, 0x71, 0x0f, 0x78, 0x00, 0x10, 0xff, 0xf6, 0xed, 0xa0, 0xfe, 0x82, 0x00, 0x01,
+ 0x9e, 0xfe, 0x10, 0x5c, 0xff, 0x08, 0xe0, 0xe8, 0xfe, 0x02, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x01,
+ 0x9f, 0x7e, 0x10, 0x50, 0xfe, 0x88, 0xfb, 0x90, 0xfd, 0xf6, 0xfd, 0xb0, 0x9e, 0xfe, 0x10, 0x54,
+ 0xff, 0x08, 0xe2, 0xb8, 0x9f, 0x7e, 0x10, 0x58, 0xff, 0x08, 0xe6, 0xd8, 0xfe, 0xfb, 0x18, 0x00,
+ 0x9e, 0xfe, 0x00, 0x00, 0xff, 0x08, 0xbc, 0xa8, 0xcf, 0xe8, 0xe7, 0xc0, 0x0e, 0x70, 0x00, 0x01,
+ 0xc0, 0x7a, 0xfc, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x20, 0x72, 0x00, 0x0f, 0xe2, 0x00, 0xb1, 0xc5,
+ 0x9e, 0xed, 0x00, 0x04, 0x8f, 0x96, 0xff, 0xe8, 0x70, 0x7e, 0x00, 0x1e, 0xea, 0x00, 0xb2, 0x08,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xf4, 0x8f, 0xf6, 0x00, 0xa8, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0xb2, 0x64, 0xf3, 0x8a, 0xaa, 0xa8, 0xfe, 0x76, 0xff, 0xcc, 0x8f, 0xf2, 0x00, 0x00,
+ 0xfd, 0xf6, 0xff, 0xe4, 0x0e, 0x81, 0xc0, 0x00, 0x5f, 0xfd, 0x0c, 0x00, 0x9f, 0xf2, 0x00, 0x00,
+ 0x8f, 0x6e, 0x00, 0x00, 0x0e, 0xf4, 0x00, 0x03, 0xf3, 0x76, 0xff, 0xfc, 0xcf, 0x78, 0xec, 0x00,
+ 0x9f, 0x6e, 0x00, 0x00, 0xf7, 0x82, 0xb2, 0x40, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x16, 0xff, 0xec, 0x70, 0x7a, 0x00, 0x1d, 0xea, 0x00, 0xb2, 0xad, 0xf3, 0x02, 0x00, 0x01,
+ 0xf7, 0x82, 0xb2, 0x5c, 0xe0, 0x00, 0x78, 0x50, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xb2, 0xac,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x08, 0xe1, 0xb8, 0xf4, 0x02, 0x08, 0x00, 0xc3, 0x18, 0xf8, 0x00,
+ 0xff, 0x88, 0xf9, 0x70, 0xc3, 0x18, 0xfa, 0x00, 0xf7, 0x82, 0xb2, 0x84, 0xe0, 0x02, 0x9d, 0x48,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xb2, 0x08, 0x00, 0x00, 0x00, 0x01, 0x03, 0x18, 0x0b, 0x73,
+ 0xf7, 0x82, 0xb2, 0x9c, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xb1, 0x18,
+ 0xff, 0x02, 0x00, 0x80, 0xe0, 0x00, 0xaf, 0xb4, 0x9f, 0x16, 0xff, 0xf4, 0xf7, 0x82, 0xb2, 0xb8,
+ 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x08, 0xe1, 0xb8, 0xf3, 0x88, 0xe1, 0xb0,
+ 0xf4, 0x08, 0xf9, 0x70, 0xf4, 0x88, 0xe0, 0xe0, 0xf7, 0x82, 0xb2, 0xd4, 0xe0, 0x00, 0xae, 0xc4,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xfe, 0x82, 0x00, 0x00,
+ 0x7f, 0x75, 0x00, 0x02, 0xfe, 0x0a, 0xb2, 0xfc, 0xaf, 0xfa, 0xe0, 0x02, 0xc3, 0xf4, 0x00, 0x00,
+ 0x20, 0x7e, 0x00, 0x02, 0xe6, 0x00, 0xb3, 0x35, 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x76, 0x00, 0x03,
+ 0xee, 0x00, 0xb2, 0xf1, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xe1, 0xc0, 0x4f, 0xfc, 0xfd, 0xff,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xb3, 0x5c, 0xff, 0x89, 0xe1, 0xc0, 0xe0, 0x00, 0xb3, 0x5c,
+ 0x45, 0x29, 0x7f, 0xff, 0xff, 0x8a, 0xe1, 0x90, 0xa3, 0x7a, 0xf8, 0x02, 0xb0, 0x7a, 0xe0, 0x02,
+ 0x9e, 0x96, 0xff, 0xf4, 0xf7, 0x82, 0xb3, 0x50, 0xe0, 0x00, 0xb9, 0x40, 0x97, 0x93, 0xff, 0xfc,
+ 0x8e, 0x96, 0xff, 0xf4, 0xe0, 0x00, 0xb3, 0x10, 0x20, 0x76, 0x00, 0x03, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0xb8, 0x38, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xb4, 0x45, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x08, 0xe6, 0xd8, 0xc0, 0x2e, 0xe2, 0x00, 0xe6, 0x00, 0xb4, 0x94, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x83, 0x1a, 0x60, 0xfe, 0x82, 0x00, 0x7f, 0xff, 0x0a, 0xc0, 0xc0, 0xcf, 0xfc, 0xec, 0x00,
+ 0xcf, 0x70, 0xf2, 0x00, 0x7f, 0xfd, 0x00, 0x06, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0xb4, 0x94,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x13, 0xea, 0x00, 0xb4, 0x94,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x12, 0xea, 0x00, 0xb4, 0x94,
+ 0xf3, 0x02, 0x00, 0x01, 0xf7, 0x82, 0xb3, 0xe0, 0xe0, 0x00, 0x2e, 0xc0, 0x97, 0x93, 0xff, 0xfc,
+ 0x8e, 0x02, 0xfe, 0xe0, 0x0f, 0x01, 0x00, 0xff, 0x7f, 0xa0, 0xff, 0xf4, 0xcf, 0x70, 0xf4, 0x00,
+ 0x7f, 0x78, 0xff, 0xf0, 0xcf, 0x78, 0xfa, 0x00, 0xfe, 0x82, 0x00, 0xff, 0x70, 0x72, 0x00, 0x07,
+ 0xea, 0x00, 0xb4, 0x15, 0xcf, 0x78, 0xec, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xb4, 0x95,
+ 0x00, 0x00, 0x00, 0x01, 0xfe, 0x82, 0x3f, 0xff, 0x7f, 0x21, 0x00, 0x02, 0xcf, 0xf0, 0xec, 0x00,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x70, 0x72, 0x00, 0x11, 0xea, 0x00, 0xb4, 0x41, 0xc4, 0x7c, 0xec, 0x00,
+ 0xff, 0x88, 0xb2, 0xd0, 0xc0, 0x22, 0xfa, 0x00, 0xe4, 0x00, 0xb4, 0x94, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x09, 0xb8, 0x38, 0xf7, 0x82, 0xb4, 0x50, 0xe0, 0x00, 0xb6, 0xe4, 0x97, 0x93, 0xff, 0xfc,
+ 0xc3, 0x20, 0x00, 0x00, 0xf7, 0x82, 0xb4, 0x60, 0xe0, 0x00, 0x8a, 0x7c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xb4, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x12,
+ 0xea, 0x00, 0xb4, 0xd0, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xe1, 0xc0, 0x4f, 0xfc, 0xdf, 0xff,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xb4, 0xd0, 0xff, 0x89, 0xe1, 0xc0, 0x45, 0x29, 0x7f, 0xff,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xff, 0x88, 0xe1, 0xc0, 0x70, 0x7e, 0x00, 0x15,
+ 0xea, 0x00, 0xb6, 0xc1, 0x93, 0x16, 0xff, 0xf4, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x00, 0xb6, 0xa9,
+ 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x18, 0xea, 0x00, 0xb6, 0x85, 0x00, 0x00, 0x00, 0x01,
+ 0x70, 0x7e, 0x00, 0x12, 0xea, 0x00, 0xb6, 0x6d, 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x1b,
+ 0xea, 0x00, 0xb6, 0x55, 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x1a, 0xea, 0x00, 0xb6, 0x3d,
+ 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x13, 0xea, 0x00, 0xb6, 0x25, 0x00, 0x00, 0x00, 0x01,
+ 0x70, 0x7e, 0x00, 0x14, 0xea, 0x00, 0xb6, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x1e,
+ 0xea, 0x00, 0xb5, 0xf5, 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x16, 0xea, 0x00, 0xb5, 0xdd,
+ 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x19, 0xea, 0x00, 0xb5, 0xc5, 0x00, 0x00, 0x00, 0x01,
+ 0x20, 0x7e, 0x00, 0x08, 0xe6, 0x00, 0xb5, 0xb1, 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xb5, 0x7c, 0x00, 0x00, 0x00, 0x01,
+ 0xf7, 0x82, 0xb5, 0xbc, 0xe0, 0x00, 0xaf, 0x18, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xb5, 0x7c,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb5, 0xd0, 0xe0, 0x00, 0xa5, 0x40, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xe1, 0xc0, 0xe0, 0x00, 0xb5, 0x74, 0x20, 0x7e, 0x00, 0x08, 0xf7, 0x82, 0xb5, 0xe8,
+ 0xe0, 0x00, 0xb2, 0xe0, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xe1, 0xc0, 0xe0, 0x00, 0xb5, 0x64,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0x00, 0xe0, 0x00, 0xac, 0xe4, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xe1, 0xc0, 0xe0, 0x00, 0xb5, 0x58, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0x18,
+ 0xe0, 0x00, 0xb3, 0x68, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xe1, 0xc0, 0xe0, 0x00, 0xb5, 0x4c,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0x30, 0xe0, 0x00, 0x9e, 0xc8, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xe1, 0xc0, 0xe0, 0x00, 0xb5, 0x40, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0x48,
+ 0xe0, 0x00, 0x95, 0xac, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xe1, 0xc0, 0xe0, 0x00, 0xb5, 0x34,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0x60, 0xe0, 0x00, 0x96, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xe1, 0xc0, 0xe0, 0x00, 0xb5, 0x28, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0x78,
+ 0xe0, 0x00, 0xb4, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xe1, 0xc0, 0xe0, 0x00, 0xb5, 0x1c,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xf4, 0xf3, 0x02, 0x0f, 0xff, 0xc3, 0x7c, 0x34, 0x00,
+ 0xf7, 0x82, 0xb6, 0x9c, 0xe0, 0x00, 0x9c, 0x68, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xe1, 0xc0,
+ 0xe0, 0x00, 0xb5, 0x10, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0xb4, 0xe0, 0x00, 0x9b, 0x90,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xe1, 0xc0, 0xe0, 0x00, 0xb5, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0xf7, 0x82, 0xb6, 0xcc, 0xe0, 0x01, 0x01, 0xac, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xe1, 0xc0,
+ 0xe0, 0x00, 0xb4, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x24, 0x0c, 0x00, 0x60,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x01, 0x98, 0x00, 0x60, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c,
+ 0x94, 0x16, 0xff, 0xec, 0x93, 0x16, 0xff, 0xf4, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xb8, 0x21,
+ 0x93, 0x96, 0xff, 0xf0, 0x0f, 0x9d, 0xff, 0xe2, 0x20, 0x7e, 0xff, 0xff, 0xe2, 0x00, 0xb8, 0x08,
+ 0x03, 0x01, 0xe1, 0x00, 0xff, 0x88, 0xb2, 0xcc, 0x8e, 0x96, 0xff, 0xec, 0xc0, 0x76, 0xfa, 0x00,
+ 0xe4, 0x00, 0xb7, 0xf1, 0x03, 0x01, 0xe1, 0x00, 0x8f, 0x16, 0xff, 0xf0, 0xff, 0xfa, 0x7f, 0xff,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe2, 0x00, 0xb7, 0x75, 0x00, 0x00, 0x00, 0x01, 0x2f, 0x78, 0x80, 0x00,
+ 0x9f, 0x16, 0xff, 0xf0, 0x8e, 0x96, 0xff, 0xf0, 0x8f, 0x16, 0xff, 0xec, 0xff, 0xfa, 0x80, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe2, 0x00, 0xb7, 0x9d, 0xff, 0x02, 0x00, 0x00,
+ 0x8e, 0x96, 0xff, 0xec, 0x9f, 0x96, 0xff, 0xec, 0xcf, 0x74, 0xfa, 0x00, 0x8f, 0x96, 0xff, 0xf0,
+ 0x9f, 0x82, 0xfe, 0x68, 0x8e, 0x96, 0xff, 0xec, 0x9e, 0x82, 0xfe, 0x68, 0x8f, 0x96, 0xff, 0xf4,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0xb8, 0x21, 0xfe, 0xfa, 0x00, 0x00, 0x9e, 0x82, 0xfe, 0x68, 0x9f, 0x02, 0xfe, 0x68,
+ 0x8f, 0x16, 0xff, 0xf4, 0x8e, 0x96, 0xff, 0xec, 0xcf, 0xf8, 0xe8, 0x00, 0x9f, 0x82, 0xfe, 0x68,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xb8, 0x20, 0x00, 0x00, 0x00, 0x01,
+ 0x03, 0x18, 0x0c, 0x58, 0xf7, 0x82, 0xb8, 0x00, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xb7, 0x58, 0x00, 0x00, 0x00, 0x01, 0x03, 0x18, 0x0c, 0x57, 0xf7, 0x82, 0xb8, 0x18,
+ 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xb7, 0x44, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xa2, 0x80, 0xff, 0x08, 0xa2, 0xb0, 0xfb, 0xf6, 0xff, 0xf4,
+ 0xfc, 0xf6, 0xff, 0xf8, 0x8e, 0xde, 0x00, 0x00, 0x8e, 0x66, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x1e,
+ 0xfd, 0x88, 0xa2, 0xc0, 0x7f, 0x78, 0xff, 0xe8, 0x7f, 0xfc, 0xff, 0xe1, 0xfc, 0x76, 0xff, 0xf0,
+ 0x7f, 0x79, 0x00, 0x04, 0x7f, 0xfd, 0x00, 0x0b, 0x4e, 0xf4, 0xf0, 0x00, 0x4e, 0x70, 0xf7, 0xff,
+ 0x8d, 0x62, 0x00, 0x00, 0xce, 0xf4, 0xf5, 0x00, 0xce, 0x70, 0xfd, 0x00, 0x7f, 0xec, 0xff, 0xec,
+ 0xff, 0x02, 0x0f, 0xff, 0xce, 0xf4, 0xf4, 0x00, 0x7d, 0xed, 0x00, 0x0c, 0xce, 0x70, 0xf4, 0x00,
+ 0x9e, 0x66, 0x00, 0x00, 0xce, 0xf4, 0xdd, 0x00, 0x4d, 0x68, 0xf0, 0x00, 0xcd, 0x68, 0xfd, 0x00,
+ 0x9e, 0xde, 0x00, 0x00, 0x9d, 0x62, 0x00, 0x00, 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x82, 0xb8, 0xb8,
+ 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xa2, 0x80, 0x7f, 0xfd, 0x00, 0x1e,
+ 0x7f, 0xfe, 0xff, 0xe1, 0xe6, 0x00, 0xb8, 0xe9, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x81, 0x01, 0x00,
+ 0xff, 0x89, 0xfb, 0x98, 0xff, 0xc2, 0x00, 0x00, 0xff, 0x89, 0xe0, 0xd0, 0x0f, 0x81, 0x00, 0x20,
+ 0xe0, 0x00, 0xb8, 0xf4, 0xff, 0x89, 0xe0, 0xc0, 0xff, 0x89, 0xe0, 0xc0, 0xff, 0x89, 0xfb, 0x98,
+ 0xff, 0x89, 0xe0, 0xd0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xa2, 0x80, 0x70, 0x7e, 0x00, 0x1e,
+ 0xea, 0x00, 0xb9, 0x30, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa3, 0x30, 0x70, 0x7e, 0x00, 0x1f,
+ 0xea, 0x00, 0xb9, 0x30, 0xff, 0xa2, 0x00, 0x00, 0xe0, 0x00, 0xb9, 0x34, 0xff, 0x89, 0xe1, 0x88,
+ 0xf0, 0x09, 0xe1, 0x88, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x7d, 0x9d, 0x00, 0x02, 0xfc, 0x0a, 0xb2, 0xfc,
+ 0xaf, 0xee, 0xc0, 0x02, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xba, 0x20, 0xfe, 0x02, 0x08, 0x81,
+ 0xff, 0x08, 0xe1, 0xc0, 0xfe, 0x88, 0xe6, 0xd8, 0xff, 0x8a, 0xb3, 0x0c, 0xab, 0xee, 0xf8, 0x02,
+ 0xcd, 0x7a, 0xe4, 0x00, 0x7b, 0x19, 0x00, 0x18, 0x5c, 0xf8, 0x02, 0x00, 0xe6, 0x00, 0xb9, 0xa1,
+ 0x0e, 0x74, 0x00, 0x08, 0xff, 0x8a, 0xe1, 0x90, 0xfe, 0x02, 0x00, 0x02, 0xb3, 0x6e, 0xf8, 0x02,
+ 0xbe, 0x6e, 0xc0, 0x02, 0xfc, 0x89, 0xe1, 0xc0, 0xe0, 0x00, 0xba, 0x20, 0x55, 0x29, 0x80, 0x00,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xd8, 0xfd, 0x00, 0x9f, 0xf6, 0x00, 0x0c,
+ 0xff, 0x08, 0xb2, 0xdc, 0xff, 0x73, 0x28, 0x08, 0xfd, 0x77, 0x68, 0x12, 0xfb, 0xf3, 0x68, 0x0b,
+ 0x9d, 0x72, 0x00, 0x0c, 0xfd, 0x73, 0x28, 0x14, 0x93, 0xf6, 0x00, 0x38, 0xf7, 0x82, 0x00, 0x40,
+ 0xf7, 0xf7, 0x68, 0x08, 0x9d, 0x76, 0x00, 0x30, 0xff, 0xf7, 0x18, 0x0a, 0x8f, 0x76, 0x00, 0x2c,
+ 0x9e, 0x02, 0xfe, 0x58, 0x0e, 0x01, 0x10, 0x00, 0x0e, 0x70, 0x00, 0x14, 0x9e, 0x02, 0xfe, 0x58,
+ 0xfe, 0x02, 0xa1, 0xd4, 0x9e, 0x76, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x09, 0xe6, 0xd8,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0xfb, 0x28, 0x00, 0x9f, 0xfa, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0xfd, 0x77, 0x28, 0x02, 0xfe, 0x02, 0x00, 0x01, 0xbe, 0x6e, 0xc0, 0x02,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x8c, 0x9a, 0x00, 0x04, 0xfd, 0x1b, 0x18, 0x00, 0xff, 0x82, 0x07, 0xff,
+ 0x7e, 0xe5, 0x00, 0x16, 0x70, 0x66, 0x00, 0x02, 0x0e, 0xf5, 0xff, 0xc0, 0xea, 0x6c, 0x00, 0x02,
+ 0x7e, 0xf4, 0xff, 0xea, 0x7e, 0x65, 0x00, 0x01, 0xff, 0x02, 0x00, 0x05, 0xcd, 0x68, 0xfc, 0x00,
+ 0xcf, 0x78, 0xda, 0x00, 0x7e, 0x72, 0xff, 0xe1, 0xe6, 0x00, 0xba, 0x75, 0x0e, 0xf4, 0x00, 0x01,
+ 0xcf, 0x78, 0xe8, 0x00, 0x70, 0x66, 0x00, 0x10, 0xea, 0x00, 0xba, 0x85, 0x0f, 0xf8, 0x00, 0x02,
+ 0x0f, 0xf8, 0x00, 0x01, 0xc0, 0x6a, 0xfa, 0x00, 0xe6, 0x00, 0xba, 0x99, 0xf4, 0x02, 0x00, 0x00,
+ 0xe0, 0x00, 0xba, 0xdc, 0xf4, 0x02, 0x00, 0x01, 0xc0, 0x72, 0x42, 0x00, 0xe6, 0x00, 0xba, 0xb5,
+ 0x7f, 0xe5, 0x00, 0x01, 0xff, 0x88, 0xb2, 0xd0, 0xc0, 0x76, 0xfa, 0x00, 0xe2, 0x00, 0xba, 0x90,
+ 0x7f, 0xe5, 0x00, 0x01, 0x7f, 0xfc, 0xff, 0xe7, 0xff, 0x0a, 0xb7, 0x78, 0xae, 0xfa, 0xf8, 0x05,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xba, 0x91, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xe1, 0x80,
+ 0x70, 0x7e, 0x00, 0x1c, 0xea, 0x00, 0xba, 0x90, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfe, 0x88, 0xa6, 0xd0, 0xff, 0x82, 0x00, 0x1f, 0xcf, 0x9c, 0xfc, 0x00, 0x4e, 0xf4, 0xff, 0xe0,
+ 0xce, 0xf4, 0xfd, 0x00, 0xff, 0x02, 0x00, 0x01, 0xcf, 0x78, 0x3f, 0xc0, 0xff, 0xf6, 0x90, 0x00,
+ 0xc0, 0x7a, 0xfc, 0x00, 0xe6, 0x00, 0xbb, 0x55, 0xfe, 0x89, 0xa6, 0xd0, 0x20, 0x1a, 0x00, 0x00,
+ 0xe6, 0x00, 0xbb, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x9a, 0x00, 0x04, 0xff, 0x89, 0xa6, 0xe0,
+ 0x8f, 0x9a, 0x00, 0x08, 0xff, 0x89, 0xa6, 0xf0, 0x8f, 0x9a, 0x00, 0x0c, 0xff, 0x89, 0xa7, 0x00,
+ 0x83, 0x1a, 0x00, 0x10, 0xe0, 0x00, 0xbb, 0x54, 0xf3, 0x09, 0xa7, 0x10, 0xe0, 0x00, 0xbb, 0x28,
+ 0xf3, 0x0a, 0xbb, 0x58, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xff, 0x88, 0xa4, 0x00,
+ 0x20, 0x1e, 0x00, 0x14, 0xe6, 0x78, 0x00, 0x03, 0x5f, 0xfd, 0x00, 0x01, 0x9f, 0x16, 0xff, 0xf4,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xbc, 0x58, 0xff, 0x89, 0xa4, 0x00, 0x20, 0x1e, 0x00, 0x1f,
+ 0xe2, 0x70, 0x00, 0x03, 0x20, 0x72, 0x00, 0x00, 0xe6, 0x00, 0xbb, 0xa5, 0x2f, 0x9c, 0x00, 0x20,
+ 0xff, 0x82, 0x00, 0x0d, 0xff, 0x08, 0xa6, 0xb0, 0xfd, 0x82, 0x00, 0x01, 0xfe, 0x88, 0xa6, 0xc0,
+ 0xcf, 0xec, 0xff, 0xc0, 0xcf, 0x78, 0xfd, 0x00, 0xc0, 0x76, 0xfc, 0x00, 0xe6, 0x00, 0xbc, 0x64,
+ 0xff, 0x09, 0xa6, 0xb0, 0x20, 0x72, 0x00, 0x00, 0xe6, 0x00, 0xbb, 0xf5, 0xce, 0xec, 0x3f, 0xc0,
+ 0xff, 0x08, 0xa6, 0x80, 0xcf, 0xf8, 0xed, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xbb, 0xf4,
+ 0xff, 0x89, 0xa6, 0x80, 0xff, 0x88, 0xa6, 0x90, 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0xbc, 0x45,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xf4, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xbc, 0x39,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa4, 0x00, 0x70, 0x7e, 0x00, 0x1c, 0xea, 0x00, 0xbc, 0x64,
+ 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x00, 0xbc, 0x64, 0xf3, 0x02, 0x00, 0x30,
+ 0xf3, 0x82, 0x00, 0x00, 0xf7, 0x82, 0xbc, 0x30, 0xe0, 0x00, 0xb9, 0x40, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xbc, 0x64, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa4, 0x00, 0xe0, 0x00, 0xbc, 0x14,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xbc, 0x50, 0xe0, 0x00, 0xba, 0xe8, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xbb, 0xf4, 0x00, 0x00, 0x00, 0x01, 0x5f, 0xfd, 0x00, 0x08, 0xe0, 0x00, 0xbb, 0x8c,
+ 0xff, 0x89, 0xa4, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0x20, 0x1e, 0x00, 0x14,
+ 0xe6, 0x7c, 0x00, 0x03, 0xff, 0x08, 0xa6, 0xa0, 0xfe, 0x82, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xf4,
+ 0xcf, 0xf4, 0x3f, 0xc0, 0xcf, 0x7a, 0xfc, 0x00, 0xe6, 0x00, 0xbd, 0xed, 0x9f, 0x16, 0xff, 0xec,
+ 0xff, 0x88, 0xa4, 0x00, 0xff, 0x02, 0x00, 0x02, 0x9f, 0x16, 0xff, 0xf0, 0x5f, 0xfd, 0x00, 0x04,
+ 0xff, 0x89, 0xa4, 0x00, 0x8f, 0x96, 0xff, 0xf4, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xbc, 0xd1,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa4, 0x00, 0x5f, 0xfd, 0x00, 0x08, 0xff, 0x89, 0xa4, 0x00,
+ 0xff, 0x88, 0xa6, 0x80, 0xff, 0x02, 0x00, 0x01, 0xfe, 0x88, 0xa6, 0x90, 0x20, 0x7e, 0x00, 0x00,
+ 0xcf, 0x78, 0x3f, 0xc0, 0xe6, 0x70, 0x00, 0x03, 0xcf, 0xfc, 0xf5, 0x00, 0xc0, 0x76, 0xf4, 0x00,
+ 0xe6, 0x00, 0xbd, 0xfc, 0xff, 0x89, 0xa6, 0x80, 0x20, 0x72, 0x00, 0x00, 0xe6, 0x00, 0xbd, 0xd8,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xf4, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xbd, 0xcd,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa4, 0x00, 0x70, 0x7e, 0x00, 0x1c, 0xea, 0x00, 0xbd, 0xcd,
+ 0x00, 0x00, 0x00, 0x01, 0xfe, 0x08, 0xa2, 0x80, 0x70, 0x72, 0x00, 0x17, 0xea, 0x00, 0xbd, 0xfc,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xec, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xbd, 0xa9,
+ 0x00, 0x00, 0x00, 0x01, 0x70, 0x72, 0x00, 0x17, 0xea, 0x00, 0xbd, 0x61, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xa4, 0x00, 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x00, 0xbd, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x16, 0xff, 0xf0, 0x7f, 0xf9, 0x00, 0x02, 0xff, 0x0a, 0xb2, 0xfc, 0xae, 0xfe, 0xf0, 0x02,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xbd, 0x8c, 0x00, 0x00, 0x00, 0x01, 0x70, 0x72, 0x00, 0x17,
+ 0xea, 0x00, 0xbd, 0x8c, 0x5f, 0xf1, 0x40, 0x00, 0xff, 0x89, 0xa2, 0x80, 0x83, 0x96, 0xff, 0xf0,
+ 0xf3, 0x02, 0x00, 0x30, 0xf7, 0x82, 0xbd, 0xa0, 0xe0, 0x00, 0xb9, 0x40, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xbd, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x70, 0x72, 0x00, 0x17, 0xea, 0x00, 0xbd, 0x61,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa4, 0x00, 0x70, 0x7e, 0x00, 0x1e, 0xea, 0x00, 0xbd, 0xfc,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xbd, 0x60, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x08, 0xa2, 0x80,
+ 0xe0, 0x00, 0xbd, 0x34, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xbd, 0xe4, 0xe0, 0x00, 0xba, 0xe8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xbd, 0x04, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa4, 0x00,
+ 0x9e, 0x96, 0xff, 0xf0, 0xe0, 0x00, 0xbc, 0xb0, 0x5f, 0xfd, 0x00, 0x02, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x82, 0x00, 0x01, 0xcf, 0x1c, 0x00, 0x00, 0xce, 0xfc, 0x3f, 0xc0, 0x20, 0x1e, 0x00, 0x1f,
+ 0xe2, 0x00, 0xbe, 0x5c, 0xce, 0x18, 0x00, 0x00, 0xff, 0x88, 0xa6, 0xa0, 0xc0, 0x7e, 0xec, 0x00,
+ 0xe6, 0x00, 0xbe, 0x40, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xbe, 0x5c, 0x00, 0x00, 0x00, 0x01,
+ 0xc3, 0x70, 0x00, 0x00, 0xc3, 0xf8, 0x00, 0x00, 0xf7, 0x82, 0xbe, 0x54, 0xe0, 0x00, 0xbc, 0x70,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xbe, 0x68, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xbe, 0x68,
+ 0xe0, 0x00, 0xbb, 0x60, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x14,
+ 0x0f, 0x01, 0x80, 0x00, 0x9f, 0x02, 0xff, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x02, 0x00, 0x02,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0xbe, 0xb0, 0xe0, 0x00, 0x7d, 0x14, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x83, 0x1a, 0x42, 0x8f, 0x02, 0xff, 0xd0, 0x4f, 0xfd, 0x00, 0x00, 0x9f, 0x16, 0xff, 0xe8,
+ 0x9f, 0x96, 0xff, 0xec, 0x8f, 0x82, 0xff, 0xd0, 0x8f, 0x16, 0xff, 0xec, 0xf3, 0x02, 0x00, 0x07,
+ 0x9f, 0x96, 0xff, 0xe4, 0x9f, 0x16, 0xff, 0xf0, 0xf7, 0x82, 0xbe, 0xe4, 0xe0, 0x00, 0x2e, 0xc0,
+ 0x97, 0x93, 0xff, 0xfc, 0x94, 0x16, 0xff, 0xf4, 0x8f, 0x82, 0xff, 0xd0, 0x8f, 0x16, 0xff, 0xe4,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x20, 0x7e, 0x00, 0x01, 0xe2, 0x00, 0xbe, 0xe9, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x83, 0x1a, 0x42, 0xf3, 0x02, 0x00, 0x02, 0xf3, 0x82, 0x00, 0x01, 0x4f, 0xfd, 0x00, 0x00,
+ 0x9f, 0x96, 0xff, 0xec, 0xf7, 0x82, 0xbf, 0x20, 0xe0, 0x00, 0x7d, 0x14, 0x97, 0x93, 0xff, 0xfc,
+ 0x70, 0x22, 0x00, 0x19, 0xea, 0x00, 0xbf, 0xb1, 0x0f, 0x81, 0x80, 0x00, 0x8f, 0x96, 0xff, 0xf0,
+ 0x8f, 0x16, 0xff, 0xec, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0xbf, 0x61, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xff, 0xd0, 0x8f, 0x16, 0xff, 0xe8, 0xcf, 0xfc, 0xf2, 0x00, 0x20, 0x7e, 0x00, 0x0c,
+ 0xe2, 0x00, 0xbe, 0xc5, 0x0f, 0x81, 0x80, 0x00, 0xe0, 0x00, 0xbf, 0xb4, 0x0f, 0xfc, 0x00, 0x43,
+ 0x70, 0x22, 0x00, 0x18, 0xea, 0x00, 0xbf, 0x41, 0xff, 0x0a, 0x00, 0x00, 0x8f, 0x82, 0xff, 0xf8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0xbf, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xf4,
+ 0x5f, 0xf9, 0x10, 0x00, 0x9f, 0x82, 0xff, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0a, 0x00, 0x00,
+ 0x8f, 0x82, 0xff, 0xf8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0xbf, 0xa0, 0x0f, 0x81, 0x80, 0x00,
+ 0x0f, 0xfc, 0x00, 0x43, 0x9f, 0x82, 0xff, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf3, 0x76, 0xff, 0xbc, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0xbf, 0xf4, 0xe0, 0x00, 0x28, 0x78,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xb8, 0x5c, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xc0, 0x40,
+ 0xff, 0xf6, 0xff, 0xb4, 0x8e, 0xfe, 0x00, 0x00, 0xff, 0x76, 0xff, 0xb8, 0x8e, 0x7a, 0x00, 0x00,
+ 0x7f, 0xf5, 0x00, 0x1a, 0x7f, 0xfc, 0xff, 0xf0, 0x7e, 0x70, 0xff, 0xea, 0xce, 0x70, 0xf8, 0x00,
+ 0xff, 0x08, 0xb3, 0x24, 0xff, 0x88, 0xb3, 0x28, 0x7e, 0xf5, 0x00, 0x0a, 0x7e, 0xf4, 0xff, 0xf0,
+ 0xcf, 0x78, 0xe8, 0x00, 0xcf, 0xfc, 0xe0, 0x00, 0xff, 0x09, 0xb3, 0x24, 0xff, 0x89, 0xb3, 0x28,
+ 0xff, 0x83, 0x5b, 0xe8, 0xff, 0x02, 0x00, 0x06, 0x7f, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xe8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0xc1, 0x89, 0xfe, 0xf6, 0xff, 0xa8, 0x8f, 0x76, 0x00, 0x00,
+ 0x7f, 0xf9, 0x00, 0x1a, 0x7e, 0xfe, 0xff, 0xe1, 0xe6, 0x00, 0xc1, 0x54, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xb3, 0x3c, 0x7f, 0x79, 0x00, 0x12, 0x7f, 0x78, 0xff, 0xe8, 0xcf, 0xfc, 0xf0, 0x00,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xc1, 0x34, 0xff, 0x89, 0xb3, 0x3c, 0xff, 0xf6, 0xff, 0xac,
+ 0x8f, 0x7e, 0x00, 0x00, 0x70, 0x7a, 0x00, 0x03, 0xea, 0x00, 0xc0, 0xd4, 0xfe, 0xf6, 0xff, 0xa8,
+ 0x8f, 0xf6, 0x00, 0x00, 0x7f, 0x78, 0xff, 0xe3, 0x7f, 0xfd, 0x00, 0x1b, 0x7f, 0xfc, 0xff, 0xe8,
+ 0xcf, 0x78, 0xf8, 0x00, 0x20, 0x7a, 0x00, 0x03, 0xe6, 0x00, 0xc1, 0x25, 0x00, 0x00, 0x00, 0x01,
+ 0xe2, 0x00, 0xc0, 0xf4, 0x20, 0x7a, 0x00, 0x0f, 0x20, 0x7a, 0x00, 0x01, 0xe6, 0x00, 0xc0, 0xe5,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa4, 0x20, 0x4f, 0xfd, 0xfc, 0x0f, 0xe0, 0x00, 0xc1, 0x88,
+ 0xff, 0x89, 0xa4, 0x20, 0xff, 0x88, 0xa4, 0x20, 0x4f, 0xfd, 0xfc, 0x0f, 0xe0, 0x00, 0xc0, 0xdc,
+ 0x5f, 0xfd, 0x00, 0x10, 0xe6, 0x00, 0xc1, 0x15, 0x20, 0x7a, 0x00, 0xff, 0xe6, 0x00, 0xc0, 0xd4,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa4, 0x20, 0x4f, 0xfd, 0xfc, 0x0f, 0xe0, 0x00, 0xc0, 0xdc,
+ 0x5f, 0xfd, 0x00, 0x80, 0xff, 0x88, 0xa4, 0x20, 0x4f, 0xfd, 0xfc, 0x0f, 0xe0, 0x00, 0xc0, 0xdc,
+ 0x5f, 0xfd, 0x00, 0x40, 0xff, 0x88, 0xa4, 0x20, 0x4f, 0xfd, 0xfc, 0x0f, 0xe0, 0x00, 0xc0, 0xdc,
+ 0x5f, 0xfd, 0x00, 0x20, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x20, 0xc4, 0x18, 0x00, 0x00,
+ 0xf7, 0x82, 0xc1, 0x4c, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xc0, 0x90,
+ 0xff, 0xf6, 0xff, 0xac, 0xff, 0x88, 0xb3, 0x2c, 0xff, 0x0a, 0xb8, 0x88, 0xf7, 0x82, 0x00, 0x01,
+ 0xf7, 0xfb, 0x68, 0x9a, 0xcf, 0xfc, 0xe8, 0x00, 0xff, 0x89, 0xb3, 0x2c, 0xf7, 0x82, 0xc1, 0x78,
+ 0xe0, 0x00, 0xbe, 0x74, 0x97, 0x93, 0xff, 0xfc, 0xff, 0xf6, 0xff, 0xa8, 0x8f, 0x7e, 0x00, 0x00,
+ 0xe0, 0x00, 0xc0, 0x70, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10,
+ 0x8d, 0x1a, 0x00, 0x04, 0xff, 0x08, 0xb2, 0xe4, 0x0e, 0x81, 0x00, 0x70, 0x7f, 0xe9, 0x00, 0x03,
+ 0x7f, 0xfc, 0xff, 0xe5, 0x20, 0x7e, 0x00, 0x01, 0xce, 0xe8, 0xec, 0x00, 0x7f, 0x79, 0x00, 0x0f,
+ 0xff, 0x82, 0x30, 0x00, 0xcf, 0xe8, 0xfc, 0x00, 0xce, 0xf4, 0xf5, 0x00, 0xce, 0xf4, 0xfd, 0x00,
+ 0xe2, 0x24, 0x00, 0x03, 0x7f, 0xe9, 0x00, 0x16, 0xcc, 0x98, 0x00, 0x00, 0x93, 0x96, 0xff, 0xf4,
+ 0x7f, 0xfc, 0xff, 0xea, 0x20, 0x26, 0x00, 0x00, 0xe6, 0x00, 0xc3, 0x0d, 0x5c, 0x75, 0x0a, 0x00,
+ 0xfe, 0x67, 0x58, 0x0b, 0xff, 0x02, 0x38, 0x60, 0x83, 0x1a, 0x00, 0x08, 0xad, 0xfa, 0xe0, 0x05,
+ 0x2f, 0xfc, 0x00, 0x01, 0x7e, 0x99, 0x00, 0x1c, 0x7f, 0xfd, 0x00, 0x16, 0x7e, 0xf4, 0xff, 0xe4,
+ 0xff, 0x02, 0x39, 0x60, 0x7f, 0xfc, 0xff, 0xec, 0xa3, 0xfa, 0xe8, 0x05, 0xcf, 0xfc, 0xda, 0x00,
+ 0x70, 0x6a, 0x00, 0x02, 0xea, 0x00, 0xc3, 0x00, 0x04, 0x7c, 0x00, 0x04, 0x8f, 0xe6, 0x00, 0x10,
+ 0x4f, 0xfc, 0xff, 0xfc, 0xc3, 0xfc, 0x38, 0x00, 0x8f, 0x96, 0xff, 0xf4, 0x22, 0x10, 0x00, 0x08,
+ 0x9c, 0x12, 0x00, 0x00, 0x9f, 0x92, 0x00, 0x04, 0x9c, 0x96, 0xff, 0xf0, 0x73, 0x18, 0xff, 0xf8,
+ 0xf7, 0x82, 0xc2, 0x5c, 0xe0, 0x00, 0xa4, 0x44, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4,
+ 0x8c, 0x96, 0xff, 0xf0, 0x20, 0x7e, 0x00, 0x04, 0xe6, 0x00, 0xc2, 0xc9, 0x02, 0x10, 0x00, 0x08,
+ 0x8f, 0x96, 0xff, 0xf4, 0x20, 0x7e, 0x00, 0x01, 0xe6, 0x00, 0xc2, 0x99, 0x03, 0x01, 0xe1, 0x00,
+ 0x03, 0x18, 0x0e, 0xc5, 0xf7, 0x82, 0xc2, 0x90, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xc3, 0x1c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb8, 0x58, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0xc3, 0x1c, 0xc3, 0x64, 0x00, 0x00, 0x84, 0x16, 0xff, 0xf4, 0xf3, 0x82, 0x00, 0x14,
+ 0xf7, 0x82, 0xc2, 0xbc, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4,
+ 0xe0, 0x00, 0xc3, 0x1c, 0xff, 0x89, 0xb8, 0x58, 0xff, 0x88, 0xa2, 0x80, 0xff, 0x08, 0xb8, 0x58,
+ 0x5f, 0xfd, 0x08, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xc3, 0x1c, 0xff, 0x89, 0xa2, 0x80,
+ 0xc3, 0x64, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x0f, 0xf4, 0x02, 0x00, 0x01, 0xf7, 0x82, 0xc2, 0xf8,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xc2, 0xc0, 0xff, 0x82, 0x00, 0x01,
+ 0x8f, 0xe6, 0x00, 0x0c, 0xe0, 0x00, 0xc2, 0x34, 0x4f, 0xfc, 0xff, 0xfc, 0x83, 0x1a, 0x00, 0x08,
+ 0xf4, 0x02, 0x00, 0x04, 0xe0, 0x00, 0xc2, 0x38, 0xc3, 0xa4, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x08, 0xa3, 0x30, 0xfc, 0x82, 0x00, 0x00, 0xfe, 0x88, 0xe1, 0x88, 0x7f, 0x78, 0xff, 0xed,
+ 0x7f, 0x79, 0x00, 0x13, 0xcf, 0xf8, 0x00, 0x00, 0xcf, 0x64, 0x00, 0x00, 0xcd, 0x9e, 0xfa, 0x00,
+ 0xcd, 0x18, 0xf3, 0x00, 0xce, 0x64, 0x00, 0x00, 0xc0, 0x6e, 0xea, 0x00, 0xc0, 0x6a, 0xe3, 0x00,
+ 0xe4, 0x20, 0x00, 0x02, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x08, 0xa2, 0xb0, 0xff, 0x88, 0xa2, 0xc0,
+ 0xfc, 0x82, 0x00, 0x00, 0x7e, 0x70, 0xff, 0xe8, 0x7e, 0x71, 0x00, 0x18, 0xcf, 0x7c, 0x00, 0x00,
+ 0xce, 0xf0, 0x00, 0x00, 0xcf, 0xe4, 0x00, 0x00, 0xce, 0x64, 0x00, 0x00, 0xcd, 0xfe, 0xe8, 0x00,
+ 0xcd, 0x78, 0xe1, 0x00, 0xff, 0x88, 0xfb, 0x98, 0xce, 0x9e, 0xda, 0x00, 0xce, 0x18, 0xd3, 0x00,
+ 0xcf, 0x64, 0x00, 0x00, 0xc0, 0x76, 0xfa, 0x00, 0xc0, 0x72, 0xf3, 0x00, 0xe4, 0x20, 0x00, 0x02,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfe, 0x08, 0xa2, 0xd0, 0xff, 0x88, 0xa2, 0xe0, 0xfc, 0x82, 0x00, 0x00,
+ 0x7e, 0x70, 0xff, 0xec, 0x7e, 0x71, 0x00, 0x14, 0xcf, 0x7c, 0x00, 0x00, 0xce, 0xf0, 0x00, 0x00,
+ 0xcf, 0xe4, 0x00, 0x00, 0xce, 0x64, 0x00, 0x00, 0xcd, 0xfe, 0xe8, 0x00, 0xcd, 0x78, 0xe1, 0x00,
+ 0xff, 0x88, 0xe0, 0xd0, 0xce, 0x9e, 0xda, 0x00, 0xce, 0x18, 0xd3, 0x00, 0xcf, 0x64, 0x00, 0x00,
+ 0xc0, 0x76, 0xfa, 0x00, 0xc0, 0x72, 0xf3, 0x00, 0xe4, 0x20, 0x00, 0x02, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfe, 0x08, 0xa2, 0xb0, 0xff, 0x88, 0xa2, 0xc0, 0xfc, 0x82, 0x00, 0x00, 0x7e, 0x70, 0xff, 0xe8,
+ 0x7e, 0x71, 0x00, 0x18, 0xcf, 0x7c, 0x00, 0x00, 0xce, 0xf0, 0x00, 0x00, 0xcf, 0xe4, 0x00, 0x00,
+ 0xce, 0x64, 0x00, 0x00, 0xcd, 0xfe, 0xe8, 0x00, 0xcd, 0x78, 0xe1, 0x00, 0xff, 0x88, 0xe0, 0xc0,
+ 0xce, 0x9e, 0xda, 0x00, 0xce, 0x18, 0xd3, 0x00, 0xcf, 0x64, 0x00, 0x00, 0xc0, 0x76, 0xfa, 0x00,
+ 0xc0, 0x72, 0xf3, 0x00, 0xe4, 0x20, 0x00, 0x02, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xb2, 0xdc,
+ 0xcf, 0x18, 0x00, 0x00, 0x0e, 0x81, 0xe0, 0x00, 0x7e, 0x19, 0x00, 0x0d, 0xfd, 0xf6, 0xff, 0xf0,
+ 0x0e, 0xf4, 0x1f, 0xff, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x00, 0xc4, 0xf1, 0xf3, 0x76, 0xff, 0xfc,
+ 0xff, 0x82, 0x00, 0x01, 0xff, 0x89, 0xb2, 0xd8, 0xff, 0x09, 0xb2, 0xdc, 0x8f, 0xee, 0x00, 0x00,
+ 0x5f, 0xfc, 0x10, 0x00, 0xcf, 0xfc, 0xec, 0x00, 0xcf, 0xfc, 0xe5, 0x00, 0x9f, 0xee, 0x00, 0x00,
+ 0xf7, 0x82, 0xc4, 0xdc, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xe1, 0xc0,
+ 0x55, 0x29, 0x80, 0x00, 0x5f, 0xfc, 0x00, 0x10, 0xe0, 0x00, 0xc5, 0x00, 0xff, 0x89, 0xe1, 0xc0,
+ 0xff, 0x88, 0xb2, 0xd8, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xc4, 0xb5, 0xff, 0x82, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xb3, 0x68, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x00, 0xc5, 0x39,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xe1, 0xc0, 0xf3, 0x09, 0xb3, 0x68, 0x55, 0x29, 0x80, 0x00,
+ 0x5f, 0xfc, 0x00, 0x20, 0xff, 0x89, 0xe1, 0xc0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x65, 0x78, 0x74, 0x20,
+ 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x61, 0x74, 0x20, 0x25, 0x70, 0x0a, 0x00, 0x52, 0x65, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x54, 0x75, 0x72, 0x6e, 0x2d, 0x6f, 0x66, 0x66, 0x20, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x00, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x20, 0x20, 0x44, 0x33, 0x5f, 0x68, 0x6f, 0x74, 0x2d, 0x3e, 0x44, 0x30, 0x0a, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x80, 0x8f, 0x9a, 0x00, 0x04,
+ 0xcd, 0x18, 0x00, 0x00, 0x7f, 0x7d, 0x00, 0x16, 0x7e, 0xfd, 0x00, 0x11, 0x7f, 0xfd, 0x00, 0x01,
+ 0x0f, 0x79, 0xff, 0xc0, 0x7b, 0x7e, 0xff, 0xe1, 0x7f, 0x78, 0xff, 0xea, 0x0f, 0x78, 0x00, 0x01,
+ 0x7e, 0xf4, 0xff, 0xe1, 0x7f, 0xfc, 0xff, 0xe7, 0x9f, 0x16, 0xff, 0xd8, 0x9e, 0x96, 0xff, 0xd0,
+ 0x9b, 0x16, 0xff, 0xd4, 0xe6, 0x00, 0xf5, 0x29, 0x9f, 0x96, 0xff, 0xdc, 0x9f, 0x16, 0xff, 0xcc,
+ 0xff, 0xfa, 0x7f, 0xf0, 0xc0, 0x6a, 0xfa, 0x00, 0xe6, 0x00, 0xf5, 0x09, 0x9d, 0x16, 0xff, 0xc8,
+ 0xf0, 0x09, 0xb8, 0x58, 0x8f, 0xea, 0x00, 0x04, 0x70, 0x7e, 0x00, 0x10, 0xea, 0x00, 0xc6, 0x3c,
+ 0xc3, 0x68, 0x00, 0x00, 0xff, 0xeb, 0x18, 0x00, 0xff, 0x02, 0x07, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0xcf, 0xfc, 0xd0, 0x00, 0x8f, 0x7e, 0xff, 0xf8, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0xc6, 0x3d, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0xd0, 0x70, 0x7e, 0x00, 0x17,
+ 0xea, 0x00, 0xf4, 0xe5, 0xf4, 0x02, 0x00, 0x00, 0xc3, 0x68, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x82, 0xc6, 0x4c, 0xe0, 0x00, 0xba, 0x2c, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xf0, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xdc,
+ 0x20, 0x7e, 0x00, 0x77, 0xe2, 0x00, 0xec, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x02, 0xc6, 0x7c,
+ 0xae, 0xfe, 0xf0, 0x02, 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc8, 0x5c,
+ 0x00, 0x00, 0xf1, 0x5c, 0x00, 0x00, 0xf1, 0x5c, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xf1, 0x68,
+ 0x00, 0x00, 0xf1, 0x68, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xf4, 0xd8, 0x00, 0x00, 0xf4, 0xd8, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xc8, 0x5c,
+ 0x00, 0x00, 0xf1, 0x5c, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0xb4,
+ 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0xec, 0xb4,
+ 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xc8, 0x5c,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xf1, 0x5c, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xf1, 0x68,
+ 0x00, 0x00, 0xf1, 0x68, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xf4, 0xd8, 0x00, 0x00, 0xf4, 0xd8, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xc8, 0x5c,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0xbc,
+ 0x00, 0x00, 0xec, 0xbc, 0x00, 0x00, 0xec, 0xbc, 0x00, 0x00, 0xec, 0xbc, 0x00, 0x00, 0xec, 0xbc,
+ 0x00, 0x00, 0xec, 0xbc, 0x00, 0x00, 0xec, 0xbc, 0x00, 0x00, 0xec, 0xbc, 0x8b, 0x6a, 0x00, 0x08,
+ 0x9b, 0x16, 0xff, 0x98, 0x8c, 0xea, 0x00, 0x04, 0x7f, 0xd9, 0x00, 0x18, 0x7c, 0x7c, 0xff, 0xe4,
+ 0x7f, 0x59, 0x00, 0x1c, 0x7e, 0xe5, 0x00, 0x02, 0x7f, 0xfc, 0xff, 0xe8, 0x74, 0x78, 0xff, 0xe4,
+ 0x7e, 0xf6, 0xff, 0xe1, 0xe6, 0x00, 0xec, 0x91, 0x9f, 0x96, 0xff, 0xbc, 0x8e, 0xea, 0x00, 0x0c,
+ 0x8d, 0xea, 0x00, 0x10, 0xce, 0x74, 0x00, 0x00, 0x4d, 0xec, 0xff, 0xfc, 0xfe, 0x82, 0x00, 0x00,
+ 0xcf, 0xec, 0x00, 0x00, 0xcf, 0x74, 0x00, 0x00, 0xcb, 0xf6, 0xf8, 0x00, 0xcb, 0x70, 0xf1, 0x00,
+ 0x9d, 0x96, 0xff, 0xc4, 0xce, 0x5c, 0x00, 0x00, 0xcd, 0xd8, 0x00, 0x00, 0x8b, 0x96, 0xff, 0xc8,
+ 0x0b, 0xdc, 0x00, 0x14, 0x9b, 0x96, 0xff, 0xc0, 0xff, 0x82, 0x7c, 0xbc, 0xff, 0x02, 0x7c, 0xac,
+ 0x8b, 0x16, 0xff, 0xd8, 0xaf, 0xfe, 0x40, 0x05, 0xaf, 0x7a, 0xc0, 0x05, 0x20, 0x5a, 0x00, 0x01,
+ 0xe2, 0x00, 0xc8, 0xf9, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xec, 0x01, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x00, 0xec, 0x01, 0x00, 0x00, 0x00, 0x01, 0x8b, 0x96, 0xff, 0xd8, 0x20, 0x5e, 0x00, 0x01,
+ 0xe6, 0x00, 0xec, 0x7d, 0x20, 0x7e, 0x00, 0xff, 0xe6, 0x00, 0xec, 0x4d, 0x00, 0x00, 0x00, 0x01,
+ 0x20, 0x7a, 0x00, 0xff, 0xe6, 0x00, 0xeb, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xbc,
+ 0xff, 0x82, 0x38, 0x60, 0xc3, 0xf0, 0x00, 0x00, 0xc3, 0x6c, 0x00, 0x00, 0xae, 0xfe, 0xf0, 0x05,
+ 0x8f, 0x96, 0xff, 0xd8, 0xff, 0x02, 0x39, 0x60, 0xaf, 0x7a, 0x40, 0x05, 0x7f, 0xfd, 0x00, 0x02,
+ 0xce, 0xfc, 0xea, 0x00, 0x9c, 0x96, 0xff, 0x90, 0x9d, 0x16, 0xff, 0x8c, 0x9d, 0x96, 0xff, 0x88,
+ 0x9e, 0x16, 0xff, 0x84, 0x9f, 0x16, 0xff, 0xb0, 0x9f, 0x96, 0xff, 0xac, 0x9e, 0x96, 0xff, 0xb4,
+ 0xf7, 0x82, 0xc9, 0x6c, 0xe0, 0x00, 0xc3, 0x70, 0x97, 0x93, 0xff, 0xfc, 0x8b, 0x16, 0xff, 0xc4,
+ 0x8b, 0x96, 0xff, 0xb0, 0x8c, 0x96, 0xff, 0x90, 0x4c, 0x59, 0x00, 0x1f, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8d, 0x96, 0xff, 0x88, 0x8e, 0x16, 0xff, 0x84, 0xcb, 0xe0, 0xb8, 0x00, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xe9, 0x99, 0x9b, 0x96, 0xff, 0xb8, 0x8e, 0x96, 0xff, 0xd4, 0x20, 0x76, 0x00, 0x00,
+ 0xe6, 0x00, 0xca, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x8b, 0x16, 0xff, 0xd8, 0x20, 0x5a, 0x00, 0x20,
+ 0xe2, 0x00, 0xca, 0xc8, 0xc3, 0x68, 0x00, 0x00, 0x9c, 0x96, 0xff, 0x90, 0x9d, 0x16, 0xff, 0x8c,
+ 0xc3, 0xf0, 0x00, 0x00, 0xc3, 0x6c, 0x00, 0x00, 0xf7, 0x82, 0xc9, 0xd4, 0xe0, 0x00, 0xc4, 0x28,
+ 0x97, 0x93, 0xff, 0xfc, 0x8c, 0x96, 0xff, 0x90, 0x8d, 0x16, 0xff, 0x8c, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xca, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb3, 0x4c, 0x0f, 0xfc, 0x00, 0x01,
+ 0xff, 0x89, 0xb3, 0x4c, 0x8c, 0xea, 0x00, 0x04, 0x8b, 0xea, 0x00, 0x08, 0x9b, 0x96, 0xff, 0x98,
+ 0xff, 0x88, 0xb2, 0xe4, 0x0e, 0x81, 0x00, 0x70, 0xce, 0xe4, 0xec, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xce, 0xf4, 0xfd, 0x00, 0xff, 0x02, 0x30, 0x00, 0xcf, 0x64, 0xf4, 0x00, 0x7f, 0xe5, 0x00, 0x16,
+ 0xce, 0xf4, 0xf5, 0x00, 0x7f, 0xfc, 0xff, 0xea, 0xce, 0xf4, 0xfd, 0x00, 0x8f, 0x16, 0xff, 0x98,
+ 0x8f, 0x96, 0xff, 0xd4, 0x83, 0x96, 0xff, 0xb8, 0x84, 0x16, 0xff, 0xb4, 0x22, 0x10, 0x00, 0x08,
+ 0x5e, 0xf5, 0x4a, 0x00, 0x9e, 0x92, 0x00, 0x00, 0x9f, 0x92, 0x00, 0x04, 0x9d, 0x16, 0xff, 0x8c,
+ 0x73, 0x78, 0xff, 0xf8, 0xf4, 0x82, 0x00, 0x01, 0xf7, 0x82, 0xca, 0x64, 0xe0, 0x00, 0xa4, 0x44,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x02, 0x10, 0x00, 0x08, 0x8c, 0xea, 0x00, 0x04,
+ 0xff, 0x02, 0x00, 0x00, 0x9f, 0x16, 0xff, 0xcc, 0x70, 0x66, 0x00, 0x11, 0xea, 0x00, 0xca, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xcc, 0x20, 0x7e, 0x00, 0x00, 0xff, 0x88, 0xb8, 0x58,
+ 0xe6, 0x20, 0x00, 0x03, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xca, 0xad, 0xc3, 0x68, 0x00, 0x00,
+ 0x84, 0x16, 0xff, 0xcc, 0xe0, 0x00, 0xf5, 0x34, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x0c,
+ 0xf7, 0x82, 0xca, 0xbc, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xfb, 0x02, 0x00, 0x01,
+ 0xe0, 0x00, 0xca, 0xa0, 0xfb, 0x09, 0xb8, 0x58, 0xf3, 0x82, 0x00, 0x04, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x82, 0xca, 0xdc, 0xe0, 0x00, 0xc1, 0x94, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0xe0, 0x00, 0xca, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xd0, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0xcb, 0x31, 0x00, 0x00, 0x00, 0x01, 0xf4, 0x08, 0xb8, 0x58, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xca, 0x78, 0xc3, 0x68, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x14, 0xf7, 0x82, 0xcb, 0x18,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xff, 0x82, 0x00, 0x01,
+ 0xff, 0x89, 0xb8, 0x58, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x8b, 0x16, 0xff, 0xd8, 0x20, 0x5a, 0x00, 0x01, 0xe6, 0x00, 0xe9, 0x81, 0x00, 0x00, 0x00, 0x01,
+ 0x9c, 0x16, 0xff, 0x94, 0x9c, 0x96, 0xff, 0x90, 0x9d, 0x16, 0xff, 0x8c, 0xc3, 0xf0, 0x00, 0x00,
+ 0xc3, 0x6c, 0x00, 0x00, 0xf7, 0x82, 0xcb, 0x60, 0xe0, 0x00, 0xc4, 0x28, 0x97, 0x93, 0xff, 0xfc,
+ 0x8c, 0x16, 0xff, 0x94, 0x8c, 0x96, 0xff, 0x90, 0x8d, 0x16, 0xff, 0x8c, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xe9, 0x15, 0xff, 0x02, 0xc5, 0x44, 0x8e, 0x96, 0xff, 0xd8, 0x20, 0x76, 0x00, 0x02,
+ 0xe2, 0x00, 0xe8, 0xe0, 0xff, 0xfa, 0x7f, 0xff, 0x8f, 0x16, 0xff, 0xc0, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe2, 0x00, 0xcb, 0x9d, 0x2f, 0x78, 0x80, 0x00, 0x9f, 0x16, 0xff, 0xc0, 0x8f, 0x96, 0xff, 0xc0,
+ 0x8b, 0x16, 0xff, 0xbc, 0x8d, 0xfe, 0x00, 0x04, 0x83, 0xfe, 0x00, 0x00, 0x20, 0x5a, 0x00, 0xff,
+ 0xe2, 0x00, 0xca, 0x78, 0x7f, 0xd9, 0x00, 0x02, 0xff, 0x02, 0xcb, 0xc8, 0xae, 0xfe, 0xf0, 0x02,
+ 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xca, 0x78, 0x00, 0x00, 0xcf, 0xdc,
+ 0x00, 0x00, 0xcf, 0xf0, 0x00, 0x00, 0xd0, 0x04, 0x00, 0x00, 0xd0, 0x18, 0x00, 0x00, 0xd0, 0x2c,
+ 0x00, 0x00, 0xd0, 0x48, 0x00, 0x00, 0xd0, 0x64, 0x00, 0x00, 0xd0, 0x80, 0x00, 0x00, 0xd0, 0x90,
+ 0x00, 0x00, 0xd0, 0xa8, 0x00, 0x00, 0xd0, 0xc0, 0x00, 0x00, 0xd0, 0xc8, 0x00, 0x00, 0xd0, 0xd8,
+ 0x00, 0x00, 0xd0, 0xe0, 0x00, 0x00, 0xd0, 0xe8, 0x00, 0x00, 0xd0, 0xf8, 0x00, 0x00, 0xd1, 0x0c,
+ 0x00, 0x00, 0xd1, 0x28, 0x00, 0x00, 0xd1, 0x44, 0x00, 0x00, 0xd1, 0x60, 0x00, 0x00, 0xd1, 0x7c,
+ 0x00, 0x00, 0xd1, 0xa0, 0x00, 0x00, 0xd1, 0xc4, 0x00, 0x00, 0xd1, 0xe8, 0x00, 0x00, 0xd2, 0x00,
+ 0x00, 0x00, 0xd2, 0x20, 0x00, 0x00, 0xd2, 0x40, 0x00, 0x00, 0xd2, 0x48, 0x00, 0x00, 0xd2, 0x60,
+ 0x00, 0x00, 0xd2, 0x68, 0x00, 0x00, 0xd2, 0x70, 0x00, 0x00, 0xd2, 0x78, 0x00, 0x00, 0xd2, 0x8c,
+ 0x00, 0x00, 0xd2, 0xa8, 0x00, 0x00, 0xd2, 0xc4, 0x00, 0x00, 0xd2, 0xe0, 0x00, 0x00, 0xd2, 0xfc,
+ 0x00, 0x00, 0xd3, 0x20, 0x00, 0x00, 0xd3, 0x44, 0x00, 0x00, 0xd3, 0x68, 0x00, 0x00, 0xd3, 0x80,
+ 0x00, 0x00, 0xd3, 0xa0, 0x00, 0x00, 0xd3, 0xc0, 0x00, 0x00, 0xd3, 0xc8, 0x00, 0x00, 0xd3, 0xe0,
+ 0x00, 0x00, 0xd3, 0xe8, 0x00, 0x00, 0xd3, 0xf0, 0x00, 0x00, 0xd3, 0xf8, 0x00, 0x00, 0xd4, 0x0c,
+ 0x00, 0x00, 0xd4, 0x28, 0x00, 0x00, 0xd4, 0x44, 0x00, 0x00, 0xd4, 0x60, 0x00, 0x00, 0xd4, 0x7c,
+ 0x00, 0x00, 0xd4, 0xa0, 0x00, 0x00, 0xd4, 0xc4, 0x00, 0x00, 0xd4, 0xe8, 0x00, 0x00, 0xd5, 0x00,
+ 0x00, 0x00, 0xd5, 0x20, 0x00, 0x00, 0xd5, 0x40, 0x00, 0x00, 0xd5, 0x48, 0x00, 0x00, 0xd5, 0x60,
+ 0x00, 0x00, 0xd5, 0x68, 0x00, 0x00, 0xd5, 0x70, 0x00, 0x00, 0xd5, 0x78, 0x00, 0x00, 0xd5, 0x8c,
+ 0x00, 0x00, 0xd5, 0xa8, 0x00, 0x00, 0xd5, 0xc4, 0x00, 0x00, 0xd5, 0xe0, 0x00, 0x00, 0xd5, 0xfc,
+ 0x00, 0x00, 0xd6, 0x20, 0x00, 0x00, 0xd6, 0x44, 0x00, 0x00, 0xd6, 0x68, 0x00, 0x00, 0xd6, 0x80,
+ 0x00, 0x00, 0xd6, 0xa0, 0x00, 0x00, 0xd6, 0xc0, 0x00, 0x00, 0xd6, 0xc8, 0x00, 0x00, 0xd6, 0xe0,
+ 0x00, 0x00, 0xd6, 0xe8, 0x00, 0x00, 0xd6, 0xf0, 0x00, 0x00, 0xd6, 0xf8, 0x00, 0x00, 0xd7, 0x14,
+ 0x00, 0x00, 0xd7, 0x38, 0x00, 0x00, 0xd7, 0x5c, 0x00, 0x00, 0xd7, 0x80, 0x00, 0x00, 0xd7, 0xa4,
+ 0x00, 0x00, 0xd7, 0xd0, 0x00, 0x00, 0xd7, 0xfc, 0x00, 0x00, 0xd8, 0x28, 0x00, 0x00, 0xd8, 0x48,
+ 0x00, 0x00, 0xd8, 0x70, 0x00, 0x00, 0xd8, 0x98, 0x00, 0x00, 0xd8, 0xa0, 0x00, 0x00, 0xd8, 0xc0,
+ 0x00, 0x00, 0xd8, 0xc8, 0x00, 0x00, 0xd8, 0xd0, 0x00, 0x00, 0xd8, 0xd8, 0x00, 0x00, 0xd8, 0xf4,
+ 0x00, 0x00, 0xd9, 0x18, 0x00, 0x00, 0xd9, 0x3c, 0x00, 0x00, 0xd9, 0x60, 0x00, 0x00, 0xd9, 0x84,
+ 0x00, 0x00, 0xd9, 0xb0, 0x00, 0x00, 0xd9, 0xdc, 0x00, 0x00, 0xda, 0x08, 0x00, 0x00, 0xda, 0x28,
+ 0x00, 0x00, 0xda, 0x50, 0x00, 0x00, 0xda, 0x78, 0x00, 0x00, 0xda, 0x80, 0x00, 0x00, 0xda, 0xa0,
+ 0x00, 0x00, 0xda, 0xa8, 0x00, 0x00, 0xda, 0xb0, 0x00, 0x00, 0xda, 0xb8, 0x00, 0x00, 0xda, 0xd4,
+ 0x00, 0x00, 0xda, 0xf8, 0x00, 0x00, 0xdb, 0x1c, 0x00, 0x00, 0xdb, 0x40, 0x00, 0x00, 0xdb, 0x64,
+ 0x00, 0x00, 0xdb, 0x90, 0x00, 0x00, 0xdb, 0xbc, 0x00, 0x00, 0xdb, 0xe8, 0x00, 0x00, 0xdc, 0x08,
+ 0x00, 0x00, 0xdc, 0x30, 0x00, 0x00, 0xdc, 0x58, 0x00, 0x00, 0xdc, 0x60, 0x00, 0x00, 0xdc, 0x80,
+ 0x00, 0x00, 0xdc, 0x88, 0x00, 0x00, 0xdc, 0x90, 0x00, 0x00, 0xdc, 0x98, 0x00, 0x00, 0xdc, 0xa8,
+ 0x00, 0x00, 0xdc, 0xc0, 0x00, 0x00, 0xdc, 0xd8, 0x00, 0x00, 0xdc, 0xf0, 0x00, 0x00, 0xdd, 0x08,
+ 0x00, 0x00, 0xdd, 0x28, 0x00, 0x00, 0xdd, 0x48, 0x00, 0x00, 0xdd, 0x68, 0x00, 0x00, 0xdd, 0x7c,
+ 0x00, 0x00, 0xdd, 0x98, 0x00, 0x00, 0xdd, 0xb4, 0x00, 0x00, 0xdd, 0xbc, 0x00, 0x00, 0xdd, 0xd0,
+ 0x00, 0x00, 0xdd, 0xd8, 0x00, 0x00, 0xdd, 0xe0, 0x00, 0x00, 0xdd, 0xe8, 0x00, 0x00, 0xde, 0x00,
+ 0x00, 0x00, 0xde, 0x20, 0x00, 0x00, 0xde, 0x40, 0x00, 0x00, 0xde, 0x60, 0x00, 0x00, 0xde, 0x80,
+ 0x00, 0x00, 0xde, 0xa8, 0x00, 0x00, 0xde, 0xd0, 0x00, 0x00, 0xde, 0xf8, 0x00, 0x00, 0xdf, 0x14,
+ 0x00, 0x00, 0xdf, 0x38, 0x00, 0x00, 0xdf, 0x5c, 0x00, 0x00, 0xdf, 0x64, 0x00, 0x00, 0xdf, 0x80,
+ 0x00, 0x00, 0xdf, 0x88, 0x00, 0x00, 0xdf, 0x90, 0x00, 0x00, 0xdf, 0x98, 0x00, 0x00, 0xdf, 0xb0,
+ 0x00, 0x00, 0xdf, 0xd0, 0x00, 0x00, 0xdf, 0xf0, 0x00, 0x00, 0xe0, 0x10, 0x00, 0x00, 0xe0, 0x30,
+ 0x00, 0x00, 0xe0, 0x58, 0x00, 0x00, 0xe0, 0x80, 0x00, 0x00, 0xe0, 0xa8, 0x00, 0x00, 0xe0, 0xc4,
+ 0x00, 0x00, 0xe0, 0xe8, 0x00, 0x00, 0xe1, 0x0c, 0x00, 0x00, 0xe1, 0x14, 0x00, 0x00, 0xe1, 0x30,
+ 0x00, 0x00, 0xe1, 0x38, 0x00, 0x00, 0xe1, 0x40, 0x00, 0x00, 0xe1, 0x48, 0x00, 0x00, 0xe1, 0x60,
+ 0x00, 0x00, 0xe1, 0x80, 0x00, 0x00, 0xe1, 0xa0, 0x00, 0x00, 0xe1, 0xc0, 0x00, 0x00, 0xe1, 0xe0,
+ 0x00, 0x00, 0xe2, 0x08, 0x00, 0x00, 0xe2, 0x30, 0x00, 0x00, 0xe2, 0x58, 0x00, 0x00, 0xe2, 0x74,
+ 0x00, 0x00, 0xe2, 0x98, 0x00, 0x00, 0xe2, 0xbc, 0x00, 0x00, 0xe2, 0xc4, 0x00, 0x00, 0xe2, 0xe0,
+ 0x00, 0x00, 0xe2, 0xe8, 0x00, 0x00, 0xe2, 0xf0, 0x00, 0x00, 0xe2, 0xf8, 0x00, 0x00, 0xe3, 0x08,
+ 0x00, 0x00, 0xe3, 0x20, 0x00, 0x00, 0xe3, 0x38, 0x00, 0x00, 0xe3, 0x50, 0x00, 0x00, 0xe3, 0x68,
+ 0x00, 0x00, 0xe3, 0x88, 0x00, 0x00, 0xe3, 0xa8, 0x00, 0x00, 0xe3, 0xc8, 0x00, 0x00, 0xe3, 0xdc,
+ 0x00, 0x00, 0xe3, 0xf8, 0x00, 0x00, 0xe4, 0x14, 0x00, 0x00, 0xe4, 0x1c, 0x00, 0x00, 0xe4, 0x30,
+ 0x00, 0x00, 0xe4, 0x38, 0x00, 0x00, 0xe4, 0x40, 0x00, 0x00, 0xe4, 0x48, 0x00, 0x00, 0xe4, 0x60,
+ 0x00, 0x00, 0xe4, 0x80, 0x00, 0x00, 0xe4, 0xa0, 0x00, 0x00, 0xe4, 0xc0, 0x00, 0x00, 0xe4, 0xe0,
+ 0x00, 0x00, 0xe5, 0x08, 0x00, 0x00, 0xe5, 0x30, 0x00, 0x00, 0xe5, 0x58, 0x00, 0x00, 0xe5, 0x74,
+ 0x00, 0x00, 0xe5, 0x98, 0x00, 0x00, 0xe5, 0xbc, 0x00, 0x00, 0xe5, 0xc4, 0x00, 0x00, 0xe5, 0xe0,
+ 0x00, 0x00, 0xe5, 0xe8, 0x00, 0x00, 0xe5, 0xf0, 0x00, 0x00, 0xe5, 0xf8, 0x00, 0x00, 0xe6, 0x10,
+ 0x00, 0x00, 0xe6, 0x30, 0x00, 0x00, 0xe6, 0x50, 0x00, 0x00, 0xe6, 0x70, 0x00, 0x00, 0xe6, 0x90,
+ 0x00, 0x00, 0xe6, 0xb8, 0x00, 0x00, 0xe6, 0xe0, 0x00, 0x00, 0xe7, 0x08, 0x00, 0x00, 0xe7, 0x24,
+ 0x00, 0x00, 0xe7, 0x48, 0x00, 0x00, 0xe7, 0x6c, 0x00, 0x00, 0xe7, 0x74, 0x00, 0x00, 0xe7, 0x90,
+ 0x00, 0x00, 0xe7, 0x98, 0x00, 0x00, 0xe7, 0xa0, 0x00, 0x00, 0xcf, 0xcc, 0x00, 0x00, 0xe7, 0xa8,
+ 0x00, 0x00, 0xe7, 0xc0, 0x00, 0x00, 0xe7, 0xd8, 0x00, 0x00, 0xe7, 0xf0, 0x00, 0x00, 0xe8, 0x08,
+ 0x00, 0x00, 0xe8, 0x28, 0x00, 0x00, 0xe8, 0x48, 0x00, 0x00, 0xe8, 0x68, 0x00, 0x00, 0xe8, 0x7c,
+ 0x00, 0x00, 0xe8, 0x98, 0x00, 0x00, 0xe8, 0xb4, 0x00, 0x00, 0xe8, 0xbc, 0x00, 0x00, 0xe8, 0xd0,
+ 0x00, 0x00, 0xe8, 0xd8, 0x00, 0x00, 0xcf, 0xc8, 0x93, 0xe2, 0x00, 0x00, 0x9d, 0xe2, 0x00, 0x04,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x02,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x1c, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x00, 0xff, 0x63, 0x68, 0x02, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x01, 0xff, 0x63, 0x68, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0xff, 0xe3, 0x28, 0x00,
+ 0xff, 0x63, 0x68, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x01,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd0, 0x04, 0xf3, 0xe3, 0x68, 0x03, 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xcf, 0xdc, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xcf, 0xf0, 0xf3, 0xe3, 0x28, 0x02, 0x93, 0xe2, 0x00, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8,
+ 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x02,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04, 0xfe, 0xe3, 0x68, 0x02,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x63, 0x68, 0x04, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x00,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x01,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd1, 0x44, 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd1, 0x0c, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xd1, 0x28, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xd0, 0xf8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0,
+ 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x02,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05, 0xfe, 0xe3, 0x68, 0x02,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x63, 0x68, 0x05, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x00,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x01,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd2, 0xc4, 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd2, 0x8c, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xd2, 0xa8, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xd2, 0x78, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0,
+ 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x02,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04, 0xfe, 0xe3, 0x68, 0x02,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x63, 0x28, 0x04, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x00,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x01,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd4, 0x44, 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd4, 0x0c, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xd4, 0x28, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xd3, 0xf8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x06, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06,
+ 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06, 0xff, 0x63, 0x68, 0x02,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x6c, 0xff, 0xf8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x06, 0xfe, 0xe3, 0x68, 0x02,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x06,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x63, 0x68, 0x06, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06, 0xff, 0x63, 0x68, 0x00,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06, 0xff, 0x63, 0x68, 0x01,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd5, 0xc4, 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd5, 0x8c, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xd5, 0xa8, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xd5, 0x78, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0xec, 0xff, 0xf8,
+ 0xff, 0x63, 0x68, 0x04, 0xff, 0xe3, 0x68, 0x00, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04, 0xff, 0xe3, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04, 0xff, 0xe3, 0x28, 0x00,
+ 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf8, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xff, 0xe3, 0x68, 0x02, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7e, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xe8, 0x7f, 0x1c, 0xff, 0xf8,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x68, 0x00,
+ 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7e, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xec, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7e, 0x1c, 0xff, 0xf0,
+ 0x7f, 0xec, 0xff, 0xe8, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x04,
+ 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x28, 0x00, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x04, 0xf3, 0xe3, 0x68, 0x03, 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xe8,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04, 0xff, 0xe3, 0x68, 0x00, 0xfe, 0xe3, 0x68, 0x06,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xff, 0xe3, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xd7, 0x5c, 0xf3, 0xe3, 0x68, 0x03,
+ 0x7f, 0xec, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x04, 0xf3, 0xe3, 0x28, 0x02,
+ 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd7, 0x14, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xd7, 0x38, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xd6, 0xf8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8,
+ 0xff, 0x63, 0x68, 0x05, 0xff, 0xe3, 0x68, 0x00, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05, 0xff, 0xe3, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05, 0xff, 0xe3, 0x28, 0x00,
+ 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xff, 0xe3, 0x68, 0x02, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7e, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x68, 0x00,
+ 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7e, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xec, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7e, 0x1c, 0xff, 0xf0,
+ 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x05,
+ 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x28, 0x00, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x05, 0xf3, 0xe3, 0x68, 0x03, 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05, 0xff, 0xe3, 0x68, 0x00, 0xfe, 0xe3, 0x68, 0x06,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xff, 0xe3, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xd9, 0x3c, 0xf3, 0xe3, 0x68, 0x03,
+ 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x05, 0xf3, 0xe3, 0x28, 0x02,
+ 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd8, 0xf4, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xd9, 0x18, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xd8, 0xd8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8,
+ 0xff, 0x63, 0x28, 0x04, 0xff, 0xe3, 0x68, 0x00, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04, 0xff, 0xe3, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04, 0xff, 0xe3, 0x28, 0x00,
+ 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04,
+ 0xff, 0xe3, 0x68, 0x02, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7e, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x68, 0x00,
+ 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7e, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xec, 0xff, 0xf8,
+ 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7e, 0x1c, 0xff, 0xf0,
+ 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x28, 0x04,
+ 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x28, 0x00, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x28, 0x04, 0xf3, 0xe3, 0x68, 0x03, 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04, 0xff, 0xe3, 0x68, 0x00, 0xfe, 0xe3, 0x68, 0x06,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04,
+ 0xff, 0xe3, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xdb, 0x1c, 0xf3, 0xe3, 0x68, 0x03,
+ 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8, 0xff, 0xe3, 0x28, 0x04, 0xf3, 0xe3, 0x28, 0x02,
+ 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xda, 0xd4, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xda, 0xf8, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xda, 0xb8, 0x93, 0xe2, 0x00, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0xfd, 0xe3, 0x68, 0x07,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0xfd, 0xe3, 0x68, 0x07, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xfd, 0xe3, 0x68, 0x07,
+ 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf8, 0xfd, 0xe3, 0x68, 0x07, 0xff, 0xe3, 0x68, 0x02, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfd, 0xe3, 0x68, 0x07, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfd, 0xe3, 0x68, 0x07, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfd, 0xe3, 0x68, 0x07, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xe3, 0x68, 0x07, 0xf3, 0xe3, 0x68, 0x03,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0xfd, 0xe3, 0x68, 0x07, 0xff, 0xe3, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xfd, 0xe3, 0x68, 0x07,
+ 0xff, 0xe3, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xdc, 0xd8, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xdc, 0xa8, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xdc, 0xc0, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xdc, 0x98, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x00,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x01,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x28, 0x00,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x02,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xff, 0x63, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8,
+ 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xde, 0x40,
+ 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xf3, 0xe3, 0x28, 0x02,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xde, 0x00, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xde, 0x20, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xdd, 0xe8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x00,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x01,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x28, 0x00,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x02,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xff, 0x63, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0,
+ 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xdf, 0xf0,
+ 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xf3, 0xe3, 0x28, 0x02,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xdf, 0xb0, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xdf, 0xd0, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xdf, 0x98, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x00,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x01,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x28, 0x00,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x02,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0xff, 0x63, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0,
+ 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xe1, 0xa0,
+ 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xf3, 0xe3, 0x28, 0x02,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xe1, 0x60, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xe1, 0x80, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xe1, 0x48, 0x93, 0xe2, 0x00, 0x00, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0xfd, 0xe3, 0x28, 0x06,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0xfd, 0xe3, 0x28, 0x06, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xfd, 0xe3, 0x28, 0x06,
+ 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf8, 0xfd, 0xe3, 0x28, 0x06, 0xff, 0xe3, 0x68, 0x02, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfd, 0xe3, 0x28, 0x06, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfd, 0xe3, 0x28, 0x06, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfd, 0xe3, 0x28, 0x06, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xe3, 0x28, 0x06, 0xf3, 0xe3, 0x68, 0x03,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0xfd, 0xe3, 0x28, 0x06, 0xff, 0xe3, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xfd, 0xe3, 0x28, 0x06,
+ 0xff, 0xe3, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xe3, 0x38, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xe3, 0x08, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xe3, 0x20, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xe2, 0xf8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x00,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x01,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x28, 0x00,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x02,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x00, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xff, 0x63, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8,
+ 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xe4, 0xa0,
+ 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xf3, 0xe3, 0x28, 0x02,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xe4, 0x60, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xe4, 0x80, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xe4, 0x48, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x00,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x01,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x28, 0x00,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x02,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x00, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xff, 0x63, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0,
+ 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xe6, 0x50,
+ 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xf3, 0xe3, 0x28, 0x02,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xe6, 0x10, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xe6, 0x30, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xe5, 0xf8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0x9c, 0xff, 0xe8, 0x9d, 0xe2, 0x00, 0x04,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x9d, 0xe2, 0x00, 0x04, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x9d, 0xe2, 0x00, 0x04,
+ 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf8, 0x9d, 0xe2, 0x00, 0x04, 0xff, 0xe3, 0x68, 0x02, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0x9c, 0xff, 0xf8,
+ 0x9d, 0xe2, 0x00, 0x04, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0x9d, 0xe2, 0x00, 0x04, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0x9d, 0xe2, 0x00, 0x04, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x9d, 0xe2, 0x00, 0x04, 0xf3, 0xe3, 0x68, 0x03,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x9d, 0xe2, 0x00, 0x04, 0xff, 0xe3, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x9d, 0xe2, 0x00, 0x04,
+ 0xff, 0xe3, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xe7, 0xd8, 0xf3, 0xe3, 0x68, 0x03, 0x9d, 0xe2, 0x00, 0x04,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xe7, 0xa8, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xe7, 0xc0, 0xf3, 0xe3, 0x28, 0x02,
+ 0x8b, 0x96, 0xff, 0xc0, 0x8e, 0x96, 0xff, 0xb0, 0x83, 0x16, 0xff, 0xb8, 0x84, 0x16, 0xff, 0xb4,
+ 0x9d, 0x16, 0xff, 0x8c, 0xc3, 0xdc, 0xe8, 0x00, 0xf7, 0x82, 0xe9, 0x04, 0xe0, 0x00, 0xb7, 0x14,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x22, 0x10, 0x00, 0x08, 0x9c, 0x12, 0x00, 0x04, 0x9f, 0x12, 0x00, 0x00,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xe9, 0x30, 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xb8, 0x58, 0x8d, 0x16, 0xff, 0x8c, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xe9, 0x51,
+ 0x02, 0x10, 0x00, 0x08, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x84, 0x16, 0xff, 0xd0, 0xc3, 0x68, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x0f, 0xf7, 0x82, 0xe9, 0x68,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xff, 0x82, 0x00, 0x01,
+ 0xff, 0x89, 0xb8, 0x58, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x8b, 0x96, 0xff, 0xbc, 0x20, 0x5e, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x79, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xcb, 0x44, 0x9c, 0x16, 0xff, 0x94, 0xc3, 0xf0, 0x00, 0x00, 0xc3, 0x6c, 0x00, 0x00,
+ 0x9c, 0x96, 0xff, 0x90, 0x9d, 0x16, 0xff, 0x8c, 0x9d, 0x96, 0xff, 0x88, 0x9e, 0x16, 0xff, 0x84,
+ 0xf7, 0x82, 0xe9, 0xbc, 0xe0, 0x00, 0xc3, 0x28, 0x97, 0x93, 0xff, 0xfc, 0x8c, 0x96, 0xff, 0x90,
+ 0x8d, 0x16, 0xff, 0x8c, 0x8d, 0x96, 0xff, 0x88, 0x8e, 0x16, 0xff, 0x84, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xea, 0xdd, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xe1, 0x88, 0x8b, 0x16, 0xff, 0xd4,
+ 0x8b, 0x96, 0xff, 0xc4, 0x2f, 0xfc, 0x00, 0x01, 0x20, 0x5a, 0x00, 0x00, 0xe6, 0x00, 0xea, 0xa4,
+ 0xc3, 0xdc, 0xfc, 0x00, 0x8f, 0x16, 0xff, 0xd8, 0x20, 0x7a, 0x00, 0x20, 0xe2, 0x00, 0xca, 0xc8,
+ 0xc3, 0x68, 0x00, 0x00, 0x84, 0x16, 0xff, 0xac, 0xf3, 0x0a, 0xbb, 0x70, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x82, 0xea, 0x1c, 0xe0, 0x00, 0x1d, 0x28, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0xff, 0x88, 0xb2, 0xe4, 0x0e, 0x81, 0x00, 0x70, 0x8f, 0x6a, 0x00, 0x04, 0xfe, 0x02, 0x30, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xce, 0x78, 0xe4, 0x00, 0xce, 0xf8, 0xec, 0x00, 0xce, 0xf4, 0xfd, 0x00,
+ 0x7f, 0x79, 0x00, 0x16, 0x83, 0xea, 0x00, 0x08, 0xce, 0xf4, 0xe5, 0x00, 0x7f, 0x78, 0xff, 0xea,
+ 0xce, 0xf4, 0xf5, 0x00, 0x22, 0x10, 0x00, 0x0c, 0x8f, 0x96, 0xff, 0xb0, 0x5e, 0xf5, 0x4a, 0x00,
+ 0x8b, 0x16, 0xff, 0xc4, 0x8b, 0x96, 0xff, 0xd4, 0x9e, 0x92, 0x00, 0x00, 0x84, 0x96, 0xff, 0xb4,
+ 0xfe, 0x82, 0x00, 0x01, 0xf4, 0x0a, 0xbb, 0x70, 0x9b, 0x92, 0x00, 0x08, 0x9e, 0x92, 0x00, 0x04,
+ 0xc4, 0x7c, 0x40, 0x00, 0x73, 0x9c, 0xff, 0xf8, 0xc3, 0x58, 0xf8, 0x00, 0xf7, 0x82, 0xea, 0x98,
+ 0xe0, 0x00, 0xa3, 0x30, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xca, 0x6c,
+ 0x02, 0x10, 0x00, 0x0c, 0xf4, 0x08, 0xb8, 0x58, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x78,
+ 0xc3, 0x68, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x0f, 0xf7, 0x82, 0xea, 0xc4, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xfe, 0x82, 0x00, 0x01, 0xfe, 0x89, 0xb8, 0x58,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xc3, 0xf0, 0x00, 0x00,
+ 0xc3, 0x6c, 0x00, 0x00, 0x9c, 0x96, 0xff, 0x90, 0x9d, 0x16, 0xff, 0x8c, 0x9e, 0x16, 0xff, 0x84,
+ 0x9d, 0x96, 0xff, 0x88, 0xf7, 0x82, 0xeb, 0x00, 0xe0, 0x00, 0xc3, 0xcc, 0x97, 0x93, 0xff, 0xfc,
+ 0x8c, 0x96, 0xff, 0x90, 0x8d, 0x16, 0xff, 0x8c, 0x8e, 0x16, 0xff, 0x84, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xeb, 0x85, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xd4, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0xeb, 0x38, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xd8, 0x20, 0x7e, 0x00, 0x20,
+ 0xe2, 0x00, 0xeb, 0x7c, 0xc3, 0x68, 0x00, 0x00, 0x8b, 0x16, 0xff, 0xd8, 0x8b, 0x96, 0xff, 0xbc,
+ 0x83, 0x96, 0xff, 0xd4, 0x84, 0x16, 0xff, 0xc0, 0x22, 0x10, 0x00, 0x08, 0x9b, 0x12, 0x00, 0x00,
+ 0x9b, 0x92, 0x00, 0x04, 0xc3, 0x68, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c, 0xc4, 0xf0, 0x00, 0x00,
+ 0xf7, 0x82, 0xeb, 0x6c, 0xe0, 0x00, 0x39, 0xf0, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x02, 0x10, 0x00, 0x08, 0xe0, 0x00, 0xca, 0xd0,
+ 0xf3, 0x82, 0x00, 0x04, 0x8e, 0x96, 0xff, 0xd4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xeb, 0xcd,
+ 0xc3, 0x68, 0x00, 0x00, 0xf4, 0x08, 0xb8, 0x58, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x78,
+ 0xf3, 0x82, 0x00, 0x14, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xeb, 0xb4, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xff, 0x02, 0x00, 0x01, 0xff, 0x09, 0xb8, 0x58,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0xeb, 0xe0, 0xe0, 0x00, 0xc1, 0x94, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x8b, 0x16, 0xff, 0xd8, 0x20, 0x5a, 0x00, 0x02, 0xe6, 0x00, 0xec, 0x35, 0x00, 0x00, 0x00, 0x01,
+ 0xf4, 0x08, 0xb8, 0x58, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xec, 0x19, 0xc3, 0x68, 0x00, 0x00,
+ 0xe0, 0x00, 0xf5, 0x34, 0xf4, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x12, 0xf7, 0x82, 0xec, 0x28,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xfe, 0x82, 0x00, 0x01, 0xe0, 0x00, 0xec, 0x10,
+ 0xfe, 0x89, 0xb8, 0x58, 0x8b, 0x96, 0xff, 0xc4, 0x70, 0x5e, 0x00, 0x1d, 0xea, 0x00, 0xec, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xc9, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xd8,
+ 0x20, 0x76, 0x00, 0x01, 0xe6, 0x00, 0xc9, 0x11, 0x20, 0x76, 0x00, 0x02, 0xe6, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xc4, 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x00, 0xec, 0x01,
+ 0x20, 0x7a, 0x00, 0xff, 0xe0, 0x00, 0xc9, 0x14, 0x00, 0x00, 0x00, 0x01, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x00, 0xec, 0x00, 0x20, 0x7e, 0x00, 0xff, 0xe0, 0x00, 0xc9, 0x08, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0xea, 0x00, 0x0c, 0x8f, 0x16, 0xff, 0xc8, 0xcd, 0xf4, 0x00, 0x00, 0x4f, 0xfc, 0xff, 0xfc,
+ 0x0f, 0x78, 0x00, 0x10, 0x9f, 0x16, 0xff, 0xc0, 0x9f, 0x96, 0xff, 0xc4, 0xe0, 0x00, 0xc8, 0xc8,
+ 0xce, 0x7c, 0x00, 0x00, 0xff, 0x86, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xcc, 0x8c, 0xea, 0x00, 0x04,
+ 0xff, 0x6b, 0x58, 0x0b, 0x77, 0xe4, 0x00, 0x09, 0x70, 0x3e, 0xff, 0xe3, 0xe6, 0x00, 0xed, 0x3d,
+ 0xff, 0x82, 0x00, 0xf8, 0xcf, 0xf8, 0xfc, 0x00, 0x20, 0x7e, 0x00, 0x20, 0xe6, 0x00, 0xf1, 0x45,
+ 0x20, 0x7a, 0x00, 0x14, 0xe6, 0x00, 0xf1, 0x45, 0x20, 0x7a, 0x00, 0x18, 0xe6, 0x00, 0xf1, 0x2d,
+ 0x20, 0x7a, 0x00, 0x19, 0xe6, 0x00, 0xf1, 0x15, 0x20, 0x7a, 0x00, 0x1b, 0xe6, 0x00, 0xf0, 0xfd,
+ 0xff, 0x82, 0x00, 0xfe, 0xcf, 0xf8, 0xfc, 0x00, 0x20, 0x7e, 0x00, 0x30, 0xe6, 0x00, 0xf0, 0xe5,
+ 0x20, 0x7a, 0x00, 0x33, 0xe6, 0x00, 0xf0, 0xe5, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xed, 0x34,
+ 0x20, 0x7a, 0x00, 0x50, 0x8b, 0x96, 0xff, 0xdc, 0x20, 0x5e, 0x00, 0x33, 0xe6, 0x00, 0xf0, 0xb9,
+ 0x20, 0x7a, 0x00, 0x50, 0xe6, 0x00, 0xf0, 0xa9, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xd0,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xed, 0x61, 0xff, 0x82, 0x00, 0x78, 0x8b, 0x16, 0xff, 0xdc,
+ 0xcf, 0xd8, 0xfc, 0x00, 0x20, 0x7e, 0x00, 0x70, 0xe6, 0x00, 0xf0, 0x65, 0xff, 0x82, 0x00, 0xfe,
+ 0x20, 0x7a, 0x00, 0x7f, 0xe6, 0x00, 0xef, 0xd5, 0x00, 0x00, 0x00, 0x01, 0x8b, 0x96, 0xff, 0xdc,
+ 0x20, 0x5e, 0x00, 0x33, 0xe6, 0x00, 0xee, 0xa9, 0x20, 0x7a, 0x00, 0x19, 0x8f, 0x96, 0xff, 0xdc,
+ 0x20, 0x7e, 0x00, 0x34, 0xe6, 0x00, 0xee, 0x2d, 0x20, 0x7a, 0x00, 0x41, 0x8e, 0x96, 0xff, 0xdc,
+ 0x20, 0x76, 0x00, 0x74, 0xe6, 0x00, 0xed, 0xe1, 0x20, 0x7a, 0x00, 0x50, 0x8b, 0x16, 0xff, 0xd4,
+ 0xff, 0x88, 0xb8, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x78, 0x64, 0x58, 0x00, 0x01,
+ 0xc3, 0x68, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c, 0xf3, 0x82, 0x00, 0x14, 0xf7, 0x82, 0xed, 0xc8,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xfb, 0x82, 0x00, 0x01,
+ 0xfb, 0x89, 0xb8, 0x58, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe6, 0x00, 0xca, 0x79, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xd4, 0xff, 0x88, 0xb8, 0x58,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x78, 0x64, 0x78, 0x00, 0x01, 0xc3, 0x68, 0x00, 0x00,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf3, 0x82, 0x00, 0x14, 0xf7, 0x82, 0xee, 0x14, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xff, 0x82, 0x00, 0x01, 0xff, 0x89, 0xb8, 0x58,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe6, 0x00, 0xca, 0x79,
+ 0x20, 0x7a, 0x00, 0x43, 0xe6, 0x00, 0xca, 0x79, 0x20, 0x7a, 0x00, 0x40, 0xe6, 0x00, 0xca, 0x79,
+ 0x20, 0x7a, 0x00, 0x45, 0xe6, 0x00, 0xca, 0x79, 0x20, 0x7a, 0x00, 0x47, 0xe6, 0x00, 0xca, 0x79,
+ 0x20, 0x7a, 0x00, 0x44, 0xe6, 0x00, 0xca, 0x79, 0x20, 0x7a, 0x00, 0x48, 0xe6, 0x00, 0xca, 0x79,
+ 0x00, 0x00, 0x00, 0x01, 0x8b, 0x16, 0xff, 0xd4, 0xff, 0x88, 0xb8, 0x58, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0xca, 0x78, 0x64, 0x58, 0x00, 0x01, 0xc3, 0x68, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf3, 0x82, 0x00, 0x14, 0xf7, 0x82, 0xee, 0x90, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0xfb, 0x82, 0x00, 0x01, 0xfb, 0x89, 0xb8, 0x58, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe6, 0x00, 0xee, 0xfd, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0xca, 0x79, 0x00, 0x00, 0x00, 0x01, 0x8b, 0x96, 0xff, 0xd4, 0xff, 0x88, 0xb8, 0x58,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x78, 0x64, 0x5c, 0x00, 0x01, 0xc3, 0x68, 0x00, 0x00,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf3, 0x82, 0x00, 0x14, 0xf7, 0x82, 0xee, 0xe4, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xfe, 0x82, 0x00, 0x01, 0xfe, 0x89, 0xb8, 0x58,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb3, 0x08,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xef, 0xb4, 0x03, 0x01, 0xe1, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf3, 0x02, 0x00, 0x35, 0xf3, 0x82, 0x00, 0x03, 0xf7, 0x82, 0xef, 0x24, 0xe0, 0x00, 0xb9, 0x40,
+ 0x97, 0x93, 0xff, 0xfc, 0x22, 0x10, 0x00, 0x04, 0xfe, 0x82, 0xc5, 0x5d, 0x9e, 0x92, 0x00, 0x00,
+ 0xf7, 0x82, 0xef, 0x3c, 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0x0f, 0x01, 0x40, 0x00,
+ 0x0f, 0x78, 0x00, 0x15, 0x9f, 0x02, 0xff, 0x90, 0xff, 0x88, 0xb8, 0x28, 0x8d, 0x16, 0xff, 0x8c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xef, 0x94, 0x02, 0x10, 0x00, 0x04, 0xff, 0x82, 0x00, 0x03,
+ 0xff, 0x89, 0xb8, 0x28, 0xff, 0x88, 0xe1, 0xc0, 0x8f, 0x02, 0xff, 0xd0, 0xfb, 0x02, 0x00, 0x01,
+ 0x5f, 0xfc, 0x08, 0x00, 0xff, 0x09, 0xf9, 0x18, 0xff, 0x89, 0xe1, 0xc0, 0xfb, 0x09, 0xb8, 0x2c,
+ 0xfb, 0x09, 0xb8, 0x38, 0xf0, 0x09, 0xb8, 0x3c, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x55, 0x29, 0x80, 0x00, 0x03, 0x01, 0xe1, 0x00, 0x03, 0x18, 0x04, 0x75, 0xf7, 0x82, 0xef, 0xa8,
+ 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xef, 0x60,
+ 0xff, 0x82, 0x00, 0x03, 0x9d, 0x16, 0xff, 0x8c, 0x03, 0x18, 0x11, 0x98, 0xf7, 0x82, 0xef, 0xc8,
+ 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xef, 0x10,
+ 0x9d, 0x16, 0xff, 0x8c, 0x8e, 0x96, 0xff, 0xdc, 0x20, 0x76, 0x00, 0x34, 0xe2, 0x00, 0xf0, 0x38,
+ 0x20, 0x76, 0x00, 0x32, 0xe4, 0x00, 0xca, 0x79, 0x20, 0x76, 0x00, 0x30, 0xe6, 0x00, 0xca, 0x79,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xd4, 0x64, 0x7c, 0x00, 0x01, 0xff, 0x88, 0xb8, 0x58,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x78, 0xc3, 0x68, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf3, 0x82, 0x00, 0x14, 0xf7, 0x82, 0xf0, 0x20, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0xfb, 0x02, 0x00, 0x01, 0xfb, 0x09, 0xb8, 0x58, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xdc, 0x20, 0x7a, 0x00, 0x70,
+ 0xe6, 0x00, 0xca, 0x79, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0xef, 0xf4, 0x2f, 0xf8, 0x00, 0x72,
+ 0x20, 0x7e, 0x00, 0x02, 0xe2, 0x00, 0xca, 0x79, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xef, 0xf4,
+ 0x00, 0x00, 0x00, 0x01, 0xcf, 0xf8, 0xfc, 0x00, 0x20, 0x7e, 0x00, 0x7f, 0xe6, 0x00, 0xed, 0x65,
+ 0x20, 0x7a, 0x00, 0x7f, 0xf4, 0x08, 0xb8, 0x58, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x74,
+ 0xff, 0x02, 0x00, 0x00, 0xc3, 0x68, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x14, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x82, 0xf0, 0x9c, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xfb, 0x82, 0x00, 0x01,
+ 0xe0, 0x00, 0xca, 0xdc, 0xfb, 0x89, 0xb8, 0x58, 0x8e, 0x96, 0xff, 0xdc, 0x20, 0x76, 0x00, 0x74,
+ 0xe6, 0x00, 0xed, 0x3c, 0x00, 0x00, 0x00, 0x01, 0xf4, 0x08, 0xb8, 0x58, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xec, 0x10, 0xc3, 0x68, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x12, 0xf7, 0x82, 0xf0, 0xd8,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x02, 0x00, 0x01, 0xe0, 0x00, 0xec, 0x10,
+ 0xff, 0x09, 0xb8, 0x58, 0x8b, 0x16, 0xff, 0xdc, 0x20, 0x5a, 0x00, 0x30, 0xe6, 0x00, 0xed, 0x1c,
+ 0x20, 0x7a, 0x00, 0x00, 0xe0, 0x00, 0xf0, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xdc,
+ 0x20, 0x7e, 0x00, 0x35, 0xe6, 0x00, 0xed, 0x04, 0xff, 0x82, 0x00, 0xfe, 0xe0, 0x00, 0xf0, 0xb8,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xdc, 0x20, 0x76, 0x00, 0x33, 0xe6, 0x00, 0xec, 0xfc,
+ 0x20, 0x7a, 0x00, 0x1b, 0xe0, 0x00, 0xf0, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x8b, 0x96, 0xff, 0xdc,
+ 0x20, 0x5e, 0x00, 0x30, 0xe6, 0x00, 0xec, 0xf4, 0x20, 0x7a, 0x00, 0x19, 0xe0, 0x00, 0xf0, 0xb8,
+ 0x00, 0x00, 0x00, 0x01, 0x8b, 0x16, 0xff, 0xdc, 0x20, 0x5a, 0x00, 0x34, 0xe6, 0x00, 0xec, 0xec,
+ 0x20, 0x7a, 0x00, 0x18, 0xe0, 0x00, 0xf0, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xc3, 0x68, 0x00, 0x00,
+ 0xe0, 0x00, 0xca, 0xcc, 0xf3, 0x82, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xdc, 0xfb, 0x02, 0x00, 0x01,
+ 0xfb, 0x82, 0x00, 0x00, 0xc0, 0x7e, 0xb4, 0x00, 0xe6, 0x00, 0xf1, 0x94, 0x9b, 0x96, 0xff, 0xa4,
+ 0x83, 0x6a, 0x00, 0x0c, 0x77, 0x98, 0x00, 0x0d, 0x70, 0x3e, 0xff, 0xe3, 0xe6, 0x00, 0xf1, 0xa1,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xe0, 0x00, 0xca, 0xcc, 0xc3, 0x68, 0x00, 0x00,
+ 0x8e, 0x96, 0xff, 0xd4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xf3, 0xe9, 0xff, 0x82, 0x0f, 0xfc,
+ 0xff, 0x08, 0xb8, 0x24, 0xcd, 0xfc, 0x34, 0x00, 0xc3, 0x6c, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0x9f, 0x16, 0xff, 0xa0, 0xf7, 0x82, 0xf1, 0xd0, 0xe0, 0x00, 0x7c, 0x68, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x96, 0xff, 0xd0, 0x8d, 0x16, 0xff, 0x8c, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xf1, 0xf1,
+ 0xcd, 0xa0, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xe0, 0x00, 0xca, 0xd0, 0xc3, 0x68, 0x00, 0x00,
+ 0x83, 0xea, 0x00, 0x10, 0xf4, 0x6b, 0x58, 0x0b, 0xc3, 0x6c, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0x9d, 0x96, 0xff, 0x88, 0xf7, 0x82, 0xf2, 0x10, 0xe0, 0x00, 0x08, 0x84, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0xff, 0x88, 0xb2, 0xe4, 0x0f, 0x01, 0x00, 0x70, 0x8e, 0x6a, 0x00, 0x04,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xfe, 0x82, 0x30, 0x00, 0xcf, 0x70, 0xf4, 0x00, 0xcf, 0x78, 0xfd, 0x00,
+ 0xce, 0x70, 0xec, 0x00, 0x8d, 0x96, 0xff, 0x88, 0xcf, 0x78, 0xe5, 0x00, 0x5f, 0x79, 0x0a, 0x00,
+ 0x20, 0x6e, 0x00, 0x58, 0xe6, 0x00, 0xf3, 0xcd, 0x9f, 0x16, 0xff, 0xa8, 0x8f, 0x16, 0xff, 0xdc,
+ 0x20, 0x7a, 0x00, 0x44, 0xe6, 0x00, 0xf3, 0xad, 0x00, 0x00, 0x00, 0x01, 0x83, 0x6a, 0x00, 0x08,
+ 0x8f, 0x96, 0xff, 0xa8, 0x22, 0x10, 0x00, 0x08, 0xf3, 0x82, 0x00, 0x00, 0x9f, 0x92, 0x00, 0x00,
+ 0x93, 0x92, 0x00, 0x04, 0x9d, 0x16, 0xff, 0x8c, 0x73, 0x18, 0xff, 0xf8, 0xf4, 0x02, 0x00, 0x04,
+ 0xc4, 0x9c, 0x00, 0x00, 0xf7, 0x82, 0xf2, 0x90, 0xe0, 0x00, 0xa4, 0x44, 0x97, 0x93, 0xff, 0xfc,
+ 0x8b, 0x16, 0xff, 0xa4, 0x8d, 0x16, 0xff, 0x8c, 0x20, 0x5a, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x6d,
+ 0x02, 0x10, 0x00, 0x08, 0xff, 0x88, 0xb8, 0x24, 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x00, 0xf3, 0x3d,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xf3, 0x20, 0x03, 0x01, 0xe1, 0x00, 0xff, 0x88, 0xb8, 0x28,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xf3, 0x04, 0x03, 0x18, 0x11, 0x06, 0x22, 0x10, 0x00, 0x04,
+ 0xff, 0x02, 0xc5, 0x78, 0x9f, 0x12, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xf2, 0xe8,
+ 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0x02, 0x10, 0x00, 0x04, 0xf3, 0x02, 0x00, 0x02,
+ 0xf7, 0x82, 0xf2, 0xfc, 0xe0, 0x00, 0x90, 0x20, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xca, 0xdc,
+ 0x00, 0x00, 0x00, 0x01, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xf3, 0x14, 0xe0, 0x00, 0x7b, 0xb8,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xf2, 0xd0, 0x22, 0x10, 0x00, 0x04,
+ 0x03, 0x18, 0x11, 0x11, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xf3, 0x34, 0xe0, 0x00, 0x7b, 0xb8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xca, 0xdc, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb8, 0x28,
+ 0x0b, 0x81, 0x40, 0x00, 0x0b, 0xdc, 0x00, 0x15, 0x9b, 0x82, 0xff, 0x90, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0xf3, 0x8c, 0x03, 0x01, 0xe1, 0x00, 0xff, 0x88, 0xe1, 0xc0, 0x8f, 0x02, 0xff, 0xd0,
+ 0xfe, 0x82, 0x00, 0x01, 0x5f, 0xfc, 0x08, 0x00, 0xfe, 0x89, 0xb8, 0x28, 0xff, 0x09, 0xf9, 0x18,
+ 0xff, 0x89, 0xe1, 0xc0, 0xfe, 0x89, 0xb8, 0x2c, 0xfe, 0x89, 0xb8, 0x38, 0xf0, 0x09, 0xb8, 0x3c,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x70, 0x55, 0x29, 0x80, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0x03, 0x18, 0x04, 0x75, 0xf7, 0x82, 0xf3, 0xa0, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xf3, 0x58, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x6b, 0x18, 0x0c,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xf3, 0xc0, 0xe0, 0x00, 0xc4, 0x84, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xf2, 0x5c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb8, 0x24,
+ 0x8b, 0x16, 0xff, 0xa0, 0xc0, 0x7e, 0xb2, 0x00, 0xe6, 0x00, 0xf2, 0x4d, 0xfb, 0x82, 0x00, 0x01,
+ 0xe0, 0x00, 0xf2, 0x4c, 0x9b, 0x96, 0xff, 0xa4, 0xcf, 0xfc, 0x34, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0x9f, 0x96, 0xff, 0x9c, 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0xf4, 0x04, 0xe0, 0x00, 0x7c, 0x68,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x20, 0x22, 0x00, 0x64, 0xe6, 0x00, 0xf4, 0xa5,
+ 0x94, 0x16, 0xff, 0x9c, 0x8e, 0x96, 0xff, 0x9c, 0x20, 0x76, 0x00, 0x6c, 0xe6, 0x00, 0xf4, 0x89,
+ 0x20, 0x76, 0x00, 0x64, 0xe6, 0x00, 0xf4, 0x89, 0x20, 0x76, 0x01, 0x10, 0xe6, 0x00, 0xf4, 0x89,
+ 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0x9c, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xf4, 0x48,
+ 0xe0, 0x00, 0x08, 0x28, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xf4, 0x09, 0xe1, 0x00,
+ 0xff, 0x88, 0xb2, 0xe4, 0x8e, 0x6a, 0x00, 0x04, 0x0f, 0x01, 0x00, 0x70, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0x70, 0xf4, 0x00, 0xcf, 0x78, 0xfd, 0x00, 0xfe, 0x82, 0x30, 0x00, 0xce, 0x70, 0xec, 0x00,
+ 0x0f, 0x81, 0x4a, 0x00, 0xcf, 0x78, 0xe5, 0x00, 0x0f, 0xfc, 0x00, 0x01, 0xcf, 0x78, 0xfd, 0x00,
+ 0xe0, 0x00, 0xf2, 0x4c, 0x9f, 0x16, 0xff, 0xa8, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xf4, 0x98,
+ 0xe0, 0x00, 0xbf, 0xd8, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xf4, 0x34,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xf4, 0xb0, 0xe0, 0x01, 0xae, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xe2, 0xb0, 0x0f, 0x01, 0x00, 0x20, 0xc4, 0x20, 0xfd, 0x00, 0xff, 0x88, 0xa4, 0x00,
+ 0x74, 0x21, 0x00, 0x15, 0xc4, 0x20, 0xf4, 0x00, 0x4f, 0xfd, 0xff, 0xdf, 0xcf, 0xfc, 0x45, 0x00,
+ 0xe0, 0x00, 0xf4, 0x98, 0xff, 0x89, 0xa4, 0x00, 0x03, 0x01, 0xe1, 0x00, 0xe0, 0x00, 0xf3, 0x24,
+ 0x03, 0x18, 0x11, 0xeb, 0x9d, 0x16, 0xff, 0x8c, 0xf3, 0x82, 0x00, 0x13, 0xf7, 0x82, 0xf4, 0xf8,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xfe, 0x82, 0x00, 0x01,
+ 0xe0, 0x00, 0xc6, 0x38, 0xfe, 0x89, 0xb8, 0x58, 0xc3, 0xe8, 0x00, 0x00, 0x23, 0x14, 0x00, 0x20,
+ 0xf4, 0x02, 0x00, 0x14, 0xf7, 0x82, 0xf5, 0x20, 0xe0, 0x00, 0xb7, 0x14, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xc5, 0xf0, 0x2d, 0x14, 0x00, 0x20, 0x8b, 0x96, 0xff, 0xd4, 0xe0, 0x00, 0xc5, 0xe0,
+ 0x9b, 0x96, 0xff, 0xcc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x34, 0xff, 0xfa, 0x7f, 0xf0,
+ 0xfe, 0x82, 0x00, 0x00, 0x93, 0x16, 0xff, 0xdc, 0xc0, 0x1a, 0xfa, 0x00, 0x9e, 0x96, 0xff, 0xd4,
+ 0xe6, 0x00, 0xf8, 0xad, 0xcd, 0x98, 0x00, 0x00, 0xff, 0x6f, 0x18, 0x00, 0xff, 0x82, 0x07, 0xff,
+ 0xcf, 0xf8, 0xfc, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0x0f, 0xfc, 0x00, 0x0f, 0x7e, 0x78, 0xff, 0xf5,
+ 0x4f, 0xfc, 0xff, 0xf0, 0x20, 0x72, 0x00, 0x13, 0xe2, 0x00, 0xf8, 0x90, 0x9f, 0x96, 0xff, 0xd8,
+ 0x7f, 0xf1, 0x00, 0x02, 0xff, 0x02, 0xf5, 0xa4, 0xae, 0xfe, 0xf0, 0x02, 0xc1, 0x74, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xf5, 0xf4, 0x00, 0x00, 0xf5, 0xf4, 0x00, 0x00, 0xf6, 0x08,
+ 0x00, 0x00, 0xf6, 0x6c, 0x00, 0x00, 0xf6, 0x6c, 0x00, 0x00, 0xf6, 0x6c, 0x00, 0x00, 0xf6, 0xfc,
+ 0x00, 0x00, 0xf6, 0x6c, 0x00, 0x00, 0xf6, 0x78, 0x00, 0x00, 0xf6, 0x78, 0x00, 0x00, 0xf6, 0x78,
+ 0x00, 0x00, 0xf6, 0x78, 0x00, 0x00, 0xf6, 0x78, 0x00, 0x00, 0xf6, 0x78, 0x00, 0x00, 0xf6, 0x78,
+ 0x00, 0x00, 0xf6, 0x78, 0x00, 0x00, 0xf7, 0x14, 0x00, 0x00, 0xf6, 0xfc, 0x00, 0x00, 0xf7, 0x20,
+ 0x00, 0x00, 0xf7, 0x2c, 0x03, 0x01, 0xe1, 0x00, 0x03, 0x18, 0x12, 0x2b, 0xf7, 0x82, 0xf6, 0x08,
+ 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xdc, 0x8e, 0x96, 0xff, 0xd8,
+ 0xcf, 0xf8, 0xe8, 0x00, 0x4f, 0xfc, 0x7f, 0xff, 0x01, 0xfc, 0x00, 0x60, 0xff, 0x02, 0x00, 0x00,
+ 0x0f, 0xfc, 0x18, 0x00, 0xff, 0x83, 0x2a, 0x52, 0xc0, 0x7a, 0xf2, 0x00, 0xe6, 0x00, 0xf6, 0x39,
+ 0x00, 0x00, 0x00, 0x01, 0x9f, 0x02, 0xff, 0x88, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xf6, 0x38, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0xe1, 0x00,
+ 0xe0, 0x00, 0xf5, 0xfc, 0x03, 0x18, 0x12, 0x3b, 0x8f, 0xee, 0x00, 0x04, 0x70, 0x72, 0x00, 0x1d,
+ 0x7f, 0xfd, 0x00, 0x16, 0x0f, 0xfd, 0xff, 0xc0, 0x7f, 0xfc, 0xff, 0xea, 0x0f, 0xfc, 0x00, 0x01,
+ 0x9f, 0x96, 0xff, 0xd0, 0xea, 0x00, 0xf6, 0xfd, 0x74, 0x7d, 0x00, 0x02, 0x70, 0x72, 0x00, 0x1f,
+ 0xea, 0x00, 0xf6, 0xec, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xdc, 0x8f, 0xee, 0x00, 0x10,
+ 0x03, 0xf8, 0x00, 0x14, 0x4f, 0xfc, 0xff, 0xfc, 0x43, 0x7d, 0x00, 0x1f, 0xf7, 0x82, 0xf6, 0xc8,
+ 0xe0, 0x00, 0xb7, 0x14, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xd0, 0x9f, 0x16, 0xff, 0xd4,
+ 0x8e, 0x96, 0xff, 0xd4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xf6, 0x09, 0x00, 0x00, 0x00, 0x01,
+ 0x9e, 0x82, 0xff, 0x88, 0xe0, 0x00, 0xf6, 0x08, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xdc,
+ 0x8f, 0xee, 0x00, 0x0c, 0xe0, 0x00, 0xf6, 0xb4, 0x03, 0xf4, 0x00, 0x10, 0x83, 0x16, 0xff, 0xdc,
+ 0xf7, 0x82, 0xf7, 0x0c, 0xe0, 0x00, 0xc5, 0x90, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xf6, 0xd0,
+ 0x94, 0x16, 0xff, 0xd4, 0x03, 0x01, 0xe1, 0x00, 0xe0, 0x00, 0xf5, 0xfc, 0x03, 0x18, 0x12, 0x6d,
+ 0x03, 0x01, 0xe1, 0x00, 0xe0, 0x00, 0xf5, 0xfc, 0x03, 0x18, 0x12, 0xb9, 0x8e, 0x96, 0xff, 0xdc,
+ 0x0f, 0xf4, 0x00, 0x10, 0x4f, 0xfc, 0x7f, 0xff, 0x01, 0xfc, 0x00, 0x60, 0xff, 0x02, 0x00, 0x00,
+ 0x0f, 0xfc, 0x18, 0x00, 0xff, 0x83, 0x2a, 0x52, 0xc0, 0x7a, 0xf2, 0x00, 0xe6, 0x00, 0xf7, 0x59,
+ 0x00, 0x00, 0x00, 0x01, 0x9f, 0x02, 0xff, 0x88, 0x8f, 0x6e, 0x00, 0x00, 0x0f, 0x81, 0x00, 0x70,
+ 0xcf, 0xf8, 0xfc, 0x00, 0x7f, 0xfc, 0xff, 0xec, 0x9f, 0x16, 0xff, 0xcc, 0x70, 0x7a, 0x00, 0x08,
+ 0xea, 0x00, 0xf8, 0x59, 0x9f, 0x96, 0xff, 0xc8, 0x8f, 0x96, 0xff, 0xc8, 0x20, 0x7e, 0x00, 0x04,
+ 0xe6, 0x00, 0xf8, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xc8, 0x20, 0x76, 0x00, 0x00,
+ 0xe6, 0x00, 0xf8, 0x19, 0x0f, 0x81, 0x03, 0x00, 0xff, 0x88, 0xa2, 0x80, 0x5f, 0xfd, 0x20, 0x00,
+ 0xff, 0x89, 0xa2, 0x80, 0xff, 0xef, 0x18, 0x00, 0xf3, 0x82, 0x00, 0x0f, 0xcf, 0xfc, 0x3c, 0x00,
+ 0xc0, 0x7e, 0x3a, 0x00, 0xe6, 0x00, 0xf8, 0x09, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xdc,
+ 0xf3, 0x7f, 0x18, 0x00, 0xc3, 0x18, 0x3c, 0x00, 0xf7, 0x82, 0xf7, 0xd4, 0xe0, 0x01, 0xae, 0x70,
+ 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x00, 0xf7, 0xd4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xe2, 0xb0, 0x2f, 0xfc, 0x00, 0x01,
+ 0xe0, 0x00, 0xf7, 0xd4, 0xff, 0x89, 0xe2, 0xb0, 0x8f, 0x16, 0xff, 0xcc, 0xc0, 0x7a, 0xfc, 0x00,
+ 0xe6, 0x00, 0xf7, 0xa5, 0xc3, 0x6c, 0x00, 0x00, 0x84, 0x16, 0xff, 0xc8, 0x9d, 0x96, 0xff, 0xc4,
+ 0xf3, 0x82, 0x00, 0x12, 0xf7, 0x82, 0xf8, 0x40, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x96, 0xff, 0xc4, 0xe0, 0x00, 0xf7, 0xa4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa2, 0x80,
+ 0xe0, 0x00, 0xf7, 0xa0, 0x5f, 0xfd, 0x10, 0x00, 0xc3, 0x6c, 0x00, 0x00, 0x9d, 0x96, 0xff, 0xc4,
+ 0xf3, 0x82, 0x00, 0x0c, 0xf4, 0x02, 0x00, 0x01, 0xf7, 0x82, 0xf8, 0x74, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xa2, 0x80, 0x8d, 0x96, 0xff, 0xc4, 0x70, 0x7e, 0x00, 0x19,
+ 0xea, 0x00, 0xf7, 0x78, 0x5f, 0xfd, 0x01, 0x00, 0xe0, 0x00, 0xf7, 0x78, 0xff, 0x89, 0xa2, 0x80,
+ 0x03, 0x01, 0xe1, 0x00, 0x03, 0x18, 0x12, 0xbf, 0xf7, 0x82, 0xf8, 0xa4, 0xe0, 0x00, 0x7b, 0xb8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xf6, 0xd0, 0x00, 0x00, 0x00, 0x01, 0xc3, 0xec, 0x00, 0x00,
+ 0x23, 0x14, 0x00, 0x20, 0xf4, 0x02, 0x00, 0x14, 0xf7, 0x82, 0xf8, 0xc4, 0xe0, 0x00, 0xb7, 0x14,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xf5, 0x68, 0x2d, 0x94, 0x00, 0x20, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x70, 0x0e, 0x00, 0x10, 0xeb, 0x08, 0x00, 0x53, 0x8f, 0x8f, 0xff, 0xa0, 0x90, 0x02, 0xfe, 0x42,
+ 0x83, 0x8e, 0x00, 0x0c, 0x01, 0x8c, 0x00, 0xc0, 0x7e, 0xfc, 0xff, 0xf0, 0x20, 0x76, 0x60, 0x15,
+ 0xe6, 0x00, 0xf9, 0x45, 0x0f, 0x0c, 0x17, 0x50, 0x43, 0x74, 0x07, 0xff, 0x7e, 0x18, 0x00, 0x02,
+ 0x8d, 0xf2, 0x07, 0x08, 0x21, 0xf8, 0x17, 0xa0, 0xff, 0x03, 0x2a, 0x52, 0x4d, 0x74, 0xf8, 0x00,
+ 0x20, 0x6a, 0x90, 0x00, 0xe7, 0x6c, 0x00, 0x03, 0x43, 0xfd, 0x00, 0x00, 0x23, 0x0c, 0x00, 0x70,
+ 0xe0, 0x00, 0xfb, 0x50, 0xc3, 0xfc, 0x00, 0x00, 0xc3, 0x0c, 0x00, 0x00, 0xe0, 0x00, 0xfb, 0x50,
+ 0x90, 0x02, 0xfe, 0x42, 0x7c, 0x9c, 0x00, 0x08, 0x7c, 0xe4, 0xff, 0xe8, 0x8c, 0x66, 0x05, 0x08,
+ 0xfb, 0x82, 0x00, 0x10, 0x9b, 0x82, 0xff, 0x88, 0x0b, 0x0c, 0x17, 0xa0, 0xfb, 0x03, 0x2a, 0x52,
+ 0xc1, 0x60, 0x00, 0x00, 0x23, 0x0c, 0x00, 0xb0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x70, 0x0e, 0x00, 0x10,
+ 0xeb, 0x08, 0x00, 0x53, 0x8f, 0x8f, 0xff, 0xa0, 0x90, 0x02, 0xfe, 0x42, 0x83, 0x8e, 0x00, 0x0c,
+ 0x01, 0x8c, 0x00, 0xc0, 0x7e, 0xfc, 0xff, 0xf0, 0x20, 0x76, 0x70, 0x16, 0xe6, 0x00, 0xf9, 0xe1,
+ 0x0f, 0x0c, 0x17, 0x50, 0x43, 0x74, 0x07, 0xff, 0x7e, 0x18, 0x00, 0x02, 0x8d, 0xf2, 0x07, 0x08,
+ 0x21, 0xf8, 0x17, 0xa0, 0xff, 0x03, 0x2a, 0x52, 0x4d, 0x74, 0xf8, 0x00, 0x20, 0x6a, 0x90, 0x00,
+ 0xe7, 0x6c, 0x00, 0x03, 0x43, 0xfd, 0x00, 0x00, 0x23, 0x0c, 0x00, 0x70, 0xe0, 0x00, 0xfc, 0xa4,
+ 0xc3, 0xfc, 0x00, 0x00, 0xc3, 0x0c, 0x00, 0x00, 0xe0, 0x00, 0xfc, 0xa4, 0x90, 0x02, 0xfe, 0x42,
+ 0x7c, 0x9c, 0x00, 0x08, 0x7c, 0xe4, 0xff, 0xe8, 0x8c, 0x66, 0x05, 0x08, 0xfb, 0x82, 0x00, 0x10,
+ 0x9b, 0x82, 0xff, 0x88, 0x0b, 0x0c, 0x17, 0xa0, 0xfb, 0x03, 0x2a, 0x52, 0xc1, 0x60, 0x00, 0x00,
+ 0x23, 0x0c, 0x00, 0xb0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x70, 0x0e, 0x00, 0x10, 0xeb, 0x08, 0x00, 0x53,
+ 0x8f, 0x8f, 0xff, 0xa0, 0x90, 0x02, 0xfe, 0x42, 0x83, 0x8e, 0x00, 0x10, 0x01, 0x8c, 0x00, 0xc0,
+ 0x7e, 0xfc, 0xff, 0xf0, 0x20, 0x76, 0x68, 0x16, 0xe6, 0x00, 0xfa, 0x7d, 0x0f, 0x0c, 0x17, 0x50,
+ 0x43, 0x74, 0x07, 0xff, 0x7e, 0x18, 0x00, 0x02, 0x8d, 0xf2, 0x07, 0x08, 0x21, 0xf8, 0x17, 0xa0,
+ 0xff, 0x03, 0x2a, 0x52, 0x4d, 0x74, 0xf8, 0x00, 0x20, 0x6a, 0x90, 0x00, 0xe7, 0x6c, 0x00, 0x03,
+ 0x43, 0xfd, 0x00, 0x00, 0x23, 0x0c, 0x00, 0x70, 0xe0, 0x00, 0xfd, 0xf8, 0xc3, 0xfc, 0x00, 0x00,
+ 0xc3, 0x0c, 0x00, 0x00, 0xe0, 0x00, 0xfd, 0xf8, 0x90, 0x02, 0xfe, 0x42, 0x7c, 0x9c, 0x00, 0x08,
+ 0x7c, 0xe4, 0xff, 0xe8, 0x8c, 0x66, 0x05, 0x08, 0xfb, 0x82, 0x00, 0x10, 0x9b, 0x82, 0xff, 0x88,
+ 0x0b, 0x0c, 0x17, 0xa0, 0xfb, 0x03, 0x2a, 0x52, 0xc1, 0x60, 0x00, 0x00, 0x23, 0x0c, 0x00, 0xac,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x70, 0x0e, 0x00, 0x10, 0xeb, 0x08, 0x00, 0x53, 0x8f, 0x8f, 0xff, 0xa0,
+ 0x90, 0x02, 0xfe, 0x42, 0x83, 0x8e, 0x00, 0x10, 0x01, 0x8c, 0x00, 0xc0, 0x7e, 0xfc, 0xff, 0xf0,
+ 0x20, 0x76, 0x78, 0x17, 0xe6, 0x00, 0xfb, 0x19, 0x0f, 0x0c, 0x17, 0x50, 0x43, 0x74, 0x07, 0xff,
+ 0x7e, 0x18, 0x00, 0x02, 0x8d, 0xf2, 0x07, 0x08, 0x21, 0xf8, 0x17, 0xa0, 0xff, 0x03, 0x2a, 0x52,
+ 0x4d, 0x74, 0xf8, 0x00, 0x20, 0x6a, 0x90, 0x00, 0xe7, 0x6c, 0x00, 0x03, 0x43, 0xfd, 0x00, 0x00,
+ 0x23, 0x0c, 0x00, 0x70, 0xe0, 0x00, 0xff, 0x4c, 0xc3, 0xfc, 0x00, 0x00, 0xc3, 0x0c, 0x00, 0x00,
+ 0xe0, 0x00, 0xff, 0x4c, 0x90, 0x02, 0xfe, 0x42, 0x7c, 0x9c, 0x00, 0x08, 0x7c, 0xe4, 0xff, 0xe8,
+ 0x8c, 0x66, 0x05, 0x08, 0xfb, 0x82, 0x00, 0x10, 0x9b, 0x82, 0xff, 0x88, 0x0b, 0x0c, 0x17, 0xa0,
+ 0xfb, 0x03, 0x2a, 0x52, 0xc1, 0x60, 0x00, 0x00, 0x23, 0x0c, 0x00, 0xac, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x7e, 0x9c, 0xff, 0xe5, 0xce, 0x1c, 0x00, 0x00, 0x20, 0x76, 0x00, 0x0c, 0xcd, 0x98, 0x00, 0x00,
+ 0xe6, 0x00, 0xfc, 0x31, 0x7d, 0x1c, 0xff, 0xf0, 0x20, 0x76, 0x00, 0x12, 0xe6, 0x00, 0xfb, 0xe5,
+ 0x7f, 0x9c, 0xff, 0xe3, 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x00, 0xfb, 0x95, 0xfd, 0x8a, 0xb8, 0x88,
+ 0xf7, 0x82, 0xfb, 0x8c, 0xe0, 0x00, 0xf5, 0x40, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xfc, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x6f, 0x58, 0x9a, 0x2e, 0xf4, 0x00, 0x0c, 0x7f, 0xf4, 0xff, 0xff,
+ 0xfe, 0x03, 0x1a, 0xa8, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x82, 0xff, 0xfc,
+ 0xce, 0x70, 0xfc, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x8a, 0xb8, 0x60, 0xaf, 0xf6, 0xf8, 0x02,
+ 0xff, 0x6f, 0x68, 0x9a, 0xff, 0x0a, 0xb8, 0x70, 0x9f, 0xf2, 0x04, 0x00, 0xaf, 0xf6, 0xf0, 0x02,
+ 0xf7, 0x82, 0xfb, 0xdc, 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xfc, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x98, 0x00, 0x10, 0x4f, 0xfc, 0x7f, 0xff, 0x01, 0xfc, 0x00, 0x60,
+ 0xff, 0x02, 0x00, 0x00, 0x0f, 0xfc, 0x18, 0x00, 0xff, 0x83, 0x2a, 0x52, 0xc0, 0x7a, 0xf2, 0x00,
+ 0xe6, 0x00, 0xfc, 0x11, 0x43, 0x68, 0x00, 0x0f, 0x9f, 0x02, 0xff, 0x88, 0x43, 0x68, 0x00, 0x0f,
+ 0x7f, 0x99, 0x00, 0x02, 0x8f, 0x7e, 0x07, 0x08, 0x43, 0xf1, 0x00, 0x00, 0xf7, 0x82, 0xfc, 0x28,
+ 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xfc, 0x90, 0x00, 0x00, 0x00, 0x01,
+ 0x4f, 0xe8, 0x07, 0xff, 0x0f, 0x7c, 0x00, 0x03, 0x7f, 0x78, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x04,
+ 0xcf, 0x18, 0xf0, 0x00, 0x24, 0x7c, 0x00, 0x05, 0x4f, 0x78, 0x7f, 0xff, 0x01, 0xf8, 0x00, 0x60,
+ 0x0f, 0x78, 0x18, 0x00, 0xff, 0x03, 0x2a, 0x52, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xfc, 0x6d,
+ 0x03, 0x6c, 0x00, 0x0c, 0x94, 0x02, 0xff, 0x88, 0x03, 0x6c, 0x00, 0x0c, 0x43, 0x18, 0x7f, 0xff,
+ 0x83, 0x99, 0x00, 0x04, 0x4f, 0x9d, 0x00, 0xff, 0x7f, 0xfc, 0xff, 0xee, 0x7f, 0xfd, 0x00, 0x02,
+ 0x8f, 0x7e, 0x06, 0x08, 0xf7, 0x82, 0xfc, 0x90, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x7e, 0x9c, 0xff, 0xe5, 0xce, 0x1c, 0x00, 0x00, 0x20, 0x76, 0x00, 0x0e,
+ 0xcd, 0x98, 0x00, 0x00, 0xe6, 0x00, 0xfd, 0x85, 0x7d, 0x1c, 0xff, 0xf0, 0x20, 0x76, 0x00, 0x12,
+ 0xe6, 0x00, 0xfd, 0x39, 0x7f, 0x9c, 0xff, 0xe3, 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x00, 0xfc, 0xe9,
+ 0xfd, 0x8a, 0xb8, 0x88, 0xf7, 0x82, 0xfc, 0xe0, 0xe0, 0x00, 0xf5, 0x40, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xfd, 0xe4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x6f, 0x58, 0x9a, 0x2e, 0xf4, 0x00, 0x0c,
+ 0x7f, 0xf4, 0xff, 0xff, 0xfe, 0x03, 0x1a, 0xa8, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x82, 0xff, 0xfc, 0xce, 0x70, 0xfc, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x8a, 0xb8, 0x60,
+ 0xaf, 0xf6, 0xf8, 0x02, 0xff, 0x6f, 0x68, 0x9a, 0xff, 0x0a, 0xb8, 0x70, 0x9f, 0xf2, 0x04, 0x00,
+ 0xaf, 0xf6, 0xf0, 0x02, 0xf7, 0x82, 0xfd, 0x30, 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xfd, 0xe4, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x98, 0x00, 0x10, 0x4f, 0xfc, 0x7f, 0xff,
+ 0x01, 0xfc, 0x00, 0x60, 0xff, 0x02, 0x00, 0x00, 0x0f, 0xfc, 0x18, 0x00, 0xff, 0x83, 0x2a, 0x52,
+ 0xc0, 0x7a, 0xf2, 0x00, 0xe6, 0x00, 0xfd, 0x65, 0x43, 0x68, 0x00, 0x0f, 0x9f, 0x02, 0xff, 0x88,
+ 0x43, 0x68, 0x00, 0x0f, 0x7f, 0x99, 0x00, 0x02, 0x8f, 0x7e, 0x07, 0x08, 0x43, 0xf1, 0x00, 0x00,
+ 0xf7, 0x82, 0xfd, 0x7c, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xfd, 0xe4,
+ 0x00, 0x00, 0x00, 0x01, 0x4f, 0xe8, 0x07, 0xff, 0x0f, 0x7c, 0x00, 0x03, 0x7f, 0x78, 0xff, 0xfe,
+ 0x7f, 0x79, 0x00, 0x04, 0xcf, 0x18, 0xf0, 0x00, 0x24, 0x7c, 0x00, 0x06, 0x4f, 0x78, 0x7f, 0xff,
+ 0x01, 0xf8, 0x00, 0x60, 0x0f, 0x78, 0x18, 0x00, 0xff, 0x03, 0x2a, 0x52, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xfd, 0xc1, 0x03, 0x6c, 0x00, 0x0c, 0x94, 0x02, 0xff, 0x88, 0x03, 0x6c, 0x00, 0x0c,
+ 0x43, 0x18, 0x7f, 0xff, 0x83, 0x99, 0x00, 0x04, 0x4f, 0x9d, 0x00, 0xff, 0x7f, 0xfc, 0xff, 0xee,
+ 0x7f, 0xfd, 0x00, 0x02, 0x8f, 0x7e, 0x06, 0x08, 0xf7, 0x82, 0xfd, 0xe4, 0xc1, 0x78, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x7e, 0x9c, 0xff, 0xe5, 0xce, 0x1c, 0x00, 0x00,
+ 0x20, 0x76, 0x00, 0x0d, 0xcd, 0x98, 0x00, 0x00, 0xe6, 0x00, 0xfe, 0xd9, 0x7d, 0x1c, 0xff, 0xf0,
+ 0x20, 0x76, 0x00, 0x12, 0xe6, 0x00, 0xfe, 0x8d, 0x7f, 0x9c, 0xff, 0xe3, 0x20, 0x7e, 0x00, 0x03,
+ 0xe6, 0x00, 0xfe, 0x3d, 0xfd, 0x8a, 0xb8, 0x88, 0xf7, 0x82, 0xfe, 0x34, 0xe0, 0x00, 0xf5, 0x40,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xff, 0x38, 0x00, 0x00, 0x00, 0x01, 0xff, 0x6f, 0x58, 0x9a,
+ 0x2e, 0xf4, 0x00, 0x0c, 0x7f, 0xf4, 0xff, 0xff, 0xfe, 0x03, 0x1a, 0xa8, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x82, 0xff, 0xfc, 0xce, 0x70, 0xfc, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xff, 0x8a, 0xb8, 0x60, 0xaf, 0xf6, 0xf8, 0x02, 0xff, 0x6f, 0x68, 0x9a, 0xff, 0x0a, 0xb8, 0x70,
+ 0x9f, 0xf2, 0x04, 0x00, 0xaf, 0xf6, 0xf0, 0x02, 0xf7, 0x82, 0xfe, 0x84, 0xc1, 0x7c, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xff, 0x38, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x98, 0x00, 0x10,
+ 0x4f, 0xfc, 0x7f, 0xff, 0x01, 0xfc, 0x00, 0x60, 0xff, 0x02, 0x00, 0x00, 0x0f, 0xfc, 0x18, 0x00,
+ 0xff, 0x83, 0x2a, 0x52, 0xc0, 0x7a, 0xf2, 0x00, 0xe6, 0x00, 0xfe, 0xb9, 0x43, 0x68, 0x00, 0x0f,
+ 0x9f, 0x02, 0xff, 0x88, 0x43, 0x68, 0x00, 0x0f, 0x7f, 0x99, 0x00, 0x02, 0x8f, 0x7e, 0x07, 0x08,
+ 0x43, 0xf1, 0x00, 0x00, 0xf7, 0x82, 0xfe, 0xd0, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xff, 0x38, 0x00, 0x00, 0x00, 0x01, 0x4f, 0xe8, 0x07, 0xff, 0x0f, 0x7c, 0x00, 0x03,
+ 0x7f, 0x78, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x04, 0xcf, 0x18, 0xf0, 0x00, 0x24, 0x7c, 0x00, 0x06,
+ 0x4f, 0x78, 0x7f, 0xff, 0x01, 0xf8, 0x00, 0x60, 0x0f, 0x78, 0x18, 0x00, 0xff, 0x03, 0x2a, 0x52,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xff, 0x15, 0x03, 0x6c, 0x00, 0x10, 0x94, 0x02, 0xff, 0x88,
+ 0x03, 0x6c, 0x00, 0x10, 0x43, 0x18, 0x7f, 0xff, 0x83, 0x99, 0x00, 0x04, 0x4f, 0x9d, 0x00, 0xff,
+ 0x7f, 0xfc, 0xff, 0xee, 0x7f, 0xfd, 0x00, 0x02, 0x8f, 0x7e, 0x06, 0x08, 0xf7, 0x82, 0xff, 0x38,
+ 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x7e, 0x9c, 0xff, 0xe5,
+ 0xce, 0x1c, 0x00, 0x00, 0x20, 0x76, 0x00, 0x0f, 0xcd, 0x98, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x2d,
+ 0x7d, 0x1c, 0xff, 0xf0, 0x20, 0x76, 0x00, 0x12, 0xe6, 0x00, 0xff, 0xe1, 0x7f, 0x9c, 0xff, 0xe3,
+ 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x00, 0xff, 0x91, 0xfd, 0x8a, 0xb8, 0x88, 0xf7, 0x82, 0xff, 0x88,
+ 0xe0, 0x00, 0xf5, 0x40, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x6f, 0x58, 0x9a, 0x2e, 0xf4, 0x00, 0x0c, 0x7f, 0xf4, 0xff, 0xff, 0xfe, 0x03, 0x1a, 0xa8,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x82, 0xff, 0xfc, 0xce, 0x70, 0xfc, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x8a, 0xb8, 0x60, 0xaf, 0xf6, 0xf8, 0x02, 0xff, 0x6f, 0x68, 0x9a,
+ 0xff, 0x0a, 0xb8, 0x70, 0x9f, 0xf2, 0x04, 0x00, 0xaf, 0xf6, 0xf0, 0x02, 0xf7, 0x82, 0xff, 0xd8,
+ 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0x0f, 0x98, 0x00, 0x10, 0x4f, 0xfc, 0x7f, 0xff, 0x01, 0xfc, 0x00, 0x60, 0xff, 0x02, 0x00, 0x00,
+ 0x0f, 0xfc, 0x18, 0x00, 0xff, 0x83, 0x2a, 0x52, 0xc0, 0x7a, 0xf2, 0x00, 0xe6, 0x01, 0x00, 0x0d,
+ 0x43, 0x68, 0x00, 0x0f, 0x9f, 0x02, 0xff, 0x88, 0x43, 0x68, 0x00, 0x0f, 0x7f, 0x99, 0x00, 0x02,
+ 0x8f, 0x7e, 0x07, 0x08, 0x43, 0xf1, 0x00, 0x00, 0xf7, 0x86, 0x00, 0x24, 0xc1, 0x78, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x01, 0x4f, 0xe8, 0x07, 0xff,
+ 0x0f, 0x7c, 0x00, 0x03, 0x7f, 0x78, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x04, 0xcf, 0x18, 0xf0, 0x00,
+ 0x24, 0x7c, 0x00, 0x07, 0x4f, 0x78, 0x7f, 0xff, 0x01, 0xf8, 0x00, 0x60, 0x0f, 0x78, 0x18, 0x00,
+ 0xff, 0x03, 0x2a, 0x52, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x69, 0x03, 0x6c, 0x00, 0x10,
+ 0x94, 0x02, 0xff, 0x88, 0x03, 0x6c, 0x00, 0x10, 0x43, 0x18, 0x7f, 0xff, 0x83, 0x99, 0x00, 0x04,
+ 0x4f, 0x9d, 0x00, 0xff, 0x7f, 0xfc, 0xff, 0xee, 0x7f, 0xfd, 0x00, 0x02, 0x8f, 0x7e, 0x06, 0x08,
+ 0xf7, 0x86, 0x00, 0x8c, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x00, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x00, 0x7f, 0xf9, 0x00, 0x02, 0xfe, 0x86, 0x00, 0xe8, 0x9e, 0xfe, 0x06, 0x08,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x86, 0x00, 0xa0, 0x20, 0x7a, 0x00, 0x3f, 0xe2, 0x01, 0x01, 0x35,
+ 0x9e, 0xfe, 0x05, 0x08, 0xff, 0x82, 0xa8, 0x4c, 0xfe, 0x82, 0xaa, 0x74, 0xff, 0x81, 0x06, 0x04,
+ 0xfe, 0x81, 0x07, 0x04, 0xf0, 0x09, 0xe0, 0xc8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x20, 0x1a, 0x00, 0x00,
+ 0xe6, 0x01, 0x01, 0x95, 0x03, 0x19, 0x00, 0x1e, 0xff, 0xf6, 0xed, 0xa0, 0x83, 0x7e, 0x00, 0x04,
+ 0x03, 0x19, 0x00, 0x1e, 0xf7, 0x86, 0x01, 0xa0, 0xe0, 0x00, 0xb6, 0xfc, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x86, 0x01, 0xcc, 0xe0, 0x00, 0x7d, 0x14, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x02, 0x10, 0x00,
+ 0xc0, 0x22, 0xf4, 0x00, 0xe6, 0x01, 0x03, 0xe4, 0x94, 0x16, 0xff, 0xf4, 0x8f, 0x96, 0xff, 0xf4,
+ 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x01, 0x02, 0x08, 0x00, 0x00, 0x00, 0x01, 0xff, 0x83, 0x1b, 0x9a,
+ 0xff, 0x02, 0x10, 0x00, 0x4f, 0xfd, 0x00, 0x00, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x01, 0x03, 0xd0,
+ 0xf3, 0x02, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xf4, 0x70, 0x7e, 0x00, 0x0a, 0xea, 0x01, 0x03, 0xbd,
+ 0xf3, 0x02, 0x00, 0x02, 0x8f, 0x16, 0xff, 0xf4, 0x70, 0x7a, 0x00, 0x0b, 0xea, 0x01, 0x03, 0xa9,
+ 0xf3, 0x02, 0x00, 0x03, 0x8f, 0x96, 0xff, 0xf4, 0x70, 0x7e, 0x00, 0x0c, 0xea, 0x01, 0x03, 0x8d,
+ 0xf3, 0x02, 0x00, 0x00, 0x8f, 0x16, 0xff, 0xf4, 0x70, 0x7a, 0x00, 0x0d, 0xea, 0x01, 0x03, 0x71,
+ 0xf3, 0x02, 0x00, 0x00, 0x8f, 0x16, 0xff, 0xf4, 0xff, 0x8e, 0x80, 0x00, 0xc0, 0x7a, 0xfc, 0x00,
+ 0xe6, 0x01, 0x03, 0x54, 0xf3, 0x02, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xf4, 0x70, 0x7e, 0x00, 0x11,
+ 0xea, 0x01, 0x03, 0x39, 0xf3, 0x02, 0x00, 0x00, 0x8f, 0x16, 0xff, 0xf4, 0x70, 0x7a, 0x00, 0x12,
+ 0xea, 0x01, 0x03, 0x1d, 0xf3, 0x02, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xf4, 0x70, 0x7e, 0x00, 0x14,
+ 0xea, 0x01, 0x03, 0x01, 0xf3, 0x02, 0x00, 0x00, 0x8f, 0x16, 0xff, 0xf4, 0x70, 0x7a, 0x00, 0x15,
+ 0xea, 0x01, 0x02, 0xe5, 0xf3, 0x02, 0x00, 0x00, 0xff, 0x88, 0xe1, 0xc0, 0x4f, 0xfc, 0xfb, 0xff,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x02, 0xb0, 0xff, 0x89, 0xe1, 0xc0, 0x45, 0x29, 0x7f, 0xff,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x02, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x27, 0xf4, 0x02, 0x00, 0x01, 0xf7, 0x86, 0x02, 0xf8,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x04, 0xf4, 0x02, 0x00, 0x01, 0xf7, 0x86, 0x03, 0x14, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x88, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x13,
+ 0xc4, 0x18, 0x00, 0x00, 0xf7, 0x86, 0x03, 0x30, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x01, 0x02, 0x78, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x12, 0xc4, 0x18, 0x00, 0x00,
+ 0xf7, 0x86, 0x03, 0x4c, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x68,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x10, 0xf4, 0x02, 0x00, 0x01, 0xf7, 0x86, 0x03, 0x68,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x58, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x0c, 0xc4, 0x18, 0x00, 0x00, 0xf7, 0x86, 0x03, 0x84, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x44, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x11,
+ 0xc4, 0x18, 0x00, 0x00, 0xf7, 0x86, 0x03, 0xa0, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x03, 0xb4, 0xe0, 0x00, 0x7b, 0x5c,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x24, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x03, 0xc8,
+ 0xe0, 0x00, 0x7b, 0x5c, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x14, 0x00, 0x00, 0x00, 0x01,
+ 0xf7, 0x86, 0x03, 0xdc, 0xe0, 0x00, 0x9a, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x04,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x26, 0xc4, 0x18, 0x00, 0x00,
+ 0xf7, 0x86, 0x03, 0xfc, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xb3, 0x30,
+ 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x01, 0x01, 0xdc, 0xff, 0x89, 0xb3, 0x30, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x04, 0xf7, 0x86, 0x04, 0x30, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xb3, 0x1c, 0xf3, 0x82, 0x00, 0x01, 0xf3, 0x02, 0x00, 0x02, 0xcd, 0xfc, 0x38, 0x00,
+ 0xfd, 0x89, 0xb3, 0x1c, 0xf7, 0x86, 0x04, 0x50, 0xe0, 0x00, 0x7d, 0x14, 0x97, 0x93, 0xff, 0xfc,
+ 0xfd, 0x88, 0xb3, 0x1c, 0xff, 0x02, 0x3d, 0x09, 0x9f, 0x02, 0xff, 0xa8, 0xfe, 0x88, 0xe1, 0xd0,
+ 0xff, 0x02, 0x00, 0x1f, 0x7f, 0xec, 0xff, 0xfe, 0xcf, 0xfc, 0xf4, 0x00, 0xcf, 0x00, 0xfa, 0x00,
+ 0xcf, 0x74, 0xf7, 0x80, 0xfe, 0x03, 0x5b, 0xd8, 0xce, 0xf8, 0x00, 0x00, 0xff, 0x02, 0x00, 0x0e,
+ 0xff, 0x82, 0x00, 0x01, 0xce, 0x70, 0xf4, 0x00, 0xce, 0xf4, 0xfc, 0x00, 0xce, 0x70, 0xed, 0x00,
+ 0xfe, 0x03, 0x6b, 0xd8, 0x77, 0xec, 0x00, 0x1c, 0x70, 0x3e, 0xff, 0xe4, 0xe6, 0x01, 0x06, 0x09,
+ 0x00, 0x00, 0x00, 0x01, 0x70, 0x22, 0x00, 0x13, 0xea, 0x01, 0x06, 0x09, 0xff, 0x82, 0x00, 0xc0,
+ 0xc0, 0x22, 0xfc, 0x00, 0xe6, 0x01, 0x04, 0xe0, 0xff, 0x82, 0x00, 0x0f, 0x9d, 0x96, 0xff, 0xf4,
+ 0xf7, 0x86, 0x04, 0xcc, 0xe0, 0x00, 0xb6, 0xe4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xf9, 0x78,
+ 0x8d, 0x96, 0xff, 0xf4, 0xc0, 0x7e, 0x42, 0x00, 0xe6, 0x01, 0x05, 0xed, 0xff, 0x82, 0x00, 0x0f,
+ 0xcf, 0xec, 0xfc, 0x00, 0x20, 0x7e, 0x00, 0x08, 0xe6, 0x01, 0x05, 0x61, 0xff, 0x8a, 0xb8, 0x88,
+ 0xf5, 0x09, 0xbc, 0x98, 0xf5, 0x89, 0xe2, 0xc0, 0xf7, 0x86, 0x05, 0x04, 0xe0, 0x00, 0xb6, 0xe4,
+ 0x97, 0x93, 0xff, 0xfc, 0xf4, 0x09, 0xf9, 0x78, 0xf7, 0x86, 0x05, 0x14, 0xe0, 0x02, 0x81, 0x84,
+ 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x86, 0x05, 0x20, 0xe0, 0x00, 0xa6, 0xa0, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x82, 0x3d, 0x09, 0x9f, 0x82, 0xff, 0xa8, 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x05, 0x2c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0xff, 0x58, 0x99, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x04, 0xf0, 0x00, 0x00, 0x00, 0x01,
+ 0x9f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x05, 0x84, 0xe0, 0x00, 0x34, 0xa0,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x28, 0xf7, 0x86, 0x05, 0x94, 0xe0, 0x00, 0x7c, 0x3c,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xd8, 0x5f, 0xfc, 0x00, 0x02, 0xff, 0x83, 0x6b, 0xd8,
+ 0xf7, 0x86, 0x05, 0xac, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x0f, 0x81, 0x01, 0x00,
+ 0x9f, 0x82, 0xff, 0xf8, 0xf3, 0x02, 0x00, 0x14, 0xf7, 0x86, 0x05, 0xc4, 0xe0, 0x00, 0x7c, 0x3c,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8, 0x0f, 0x01, 0x01, 0x00, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x01, 0x05, 0xa0, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x05, 0xe4, 0xe0, 0x00, 0x21, 0x68,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x04, 0xf4, 0xf5, 0x09, 0xbc, 0x98, 0xf7, 0x86, 0x05, 0xf8,
+ 0xe0, 0x01, 0xae, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xe2, 0xb0, 0xc0, 0x22, 0xfd, 0x00,
+ 0xe6, 0x01, 0x06, 0x1d, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x06, 0x14, 0xe0, 0x00, 0xbf, 0xd8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x04, 0xf4, 0xf5, 0x09, 0xbc, 0x98, 0xfd, 0x88, 0xb3, 0x1c,
+ 0xe0, 0x01, 0x04, 0xe0, 0xff, 0x82, 0x00, 0x0f, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c,
+ 0x8f, 0x2e, 0x00, 0x30, 0xff, 0x88, 0xe6, 0xd8, 0x9f, 0x16, 0xff, 0xec, 0x9f, 0x96, 0xff, 0xf4,
+ 0xff, 0x88, 0xf9, 0x20, 0xff, 0x02, 0x0f, 0xff, 0xc3, 0x18, 0xf4, 0x00, 0xc0, 0x7e, 0x32, 0x00,
+ 0xe6, 0x01, 0x06, 0xd9, 0x93, 0x16, 0xff, 0xf0, 0x8f, 0x16, 0xff, 0xec, 0x8f, 0x96, 0xff, 0xf4,
+ 0x4f, 0x78, 0xfc, 0xff, 0x9f, 0x16, 0xff, 0xec, 0x8f, 0x16, 0xff, 0xf0, 0xc0, 0x2e, 0xfa, 0x00,
+ 0xe6, 0x7c, 0x00, 0x02, 0xff, 0x09, 0xf9, 0x20, 0x8f, 0x16, 0xff, 0xec, 0x7f, 0xfd, 0x00, 0x08,
+ 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x2e, 0x00, 0x30, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x06, 0xa4, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xec, 0x70, 0x7e, 0x00, 0x17,
+ 0xea, 0x01, 0x06, 0x68, 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x16, 0xea, 0x01, 0x07, 0x24,
+ 0xf3, 0x02, 0x00, 0x06, 0xf3, 0x02, 0x00, 0x00, 0xf7, 0x86, 0x07, 0x04, 0xe0, 0x00, 0x9a, 0xa0,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x2c, 0xf4, 0x02, 0x00, 0x01,
+ 0xf7, 0x86, 0x07, 0x1c, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x06, 0x68,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x07, 0x30, 0xe0, 0x00, 0x2e, 0xc0, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x96, 0xff, 0xf0, 0xff, 0x02, 0x0f, 0xff, 0xc4, 0x20, 0xf4, 0x00, 0xc0, 0x22, 0xfa, 0x00,
+ 0xe6, 0x01, 0x07, 0x8d, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0xae, 0x00, 0x30, 0x5f, 0xfc, 0x02, 0x00,
+ 0x9f, 0xae, 0x00, 0x30, 0x9f, 0x02, 0xff, 0xb0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x07, 0x58, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb3, 0x48,
+ 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x01, 0x06, 0x68, 0xff, 0x89, 0xb3, 0x48, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x42, 0x6f, 0x6f, 0x74, 0x20, 0x64, 0x69, 0x73,
+ 0x70, 0x61, 0x74, 0x63, 0x68, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x25, 0x64, 0x0a, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0xff, 0x86, 0x07, 0xa8, 0x9f, 0x92, 0x00, 0x00, 0xff, 0x83, 0x1a, 0xa8, 0x4f, 0xfd, 0x00, 0x00,
+ 0x9f, 0x92, 0x00, 0x04, 0xf7, 0x86, 0x07, 0xf0, 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc,
+ 0x02, 0x10, 0x00, 0x08, 0xe0, 0x01, 0x07, 0xf4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x08, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x90, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x00, 0x5f, 0xf8, 0x00, 0x40,
+ 0x9f, 0x82, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xf9, 0x00, 0x02, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x86, 0x07, 0xc8, 0x20, 0x7a, 0x00, 0x40, 0xe2, 0x01, 0x08, 0x6d, 0x9e, 0xfe, 0x04, 0x00,
+ 0xff, 0x82, 0x00, 0x80, 0x9f, 0x82, 0xfe, 0xb0, 0xff, 0x02, 0x00, 0x00, 0x9f, 0x02, 0xfe, 0xb8,
+ 0x9f, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8, 0x9f, 0x02, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0xc2, 0x00, 0x00, 0x9e, 0x82, 0xfe, 0xb0, 0x9f, 0x02, 0xfe, 0xb8, 0x9f, 0x02, 0xfe, 0xc0,
+ 0x9f, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x01, 0xff, 0x82, 0x85, 0xdc, 0x9f, 0x02, 0xfe, 0xd0,
+ 0xff, 0x81, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x92, 0x00, 0x00, 0x9e, 0x82, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0x90, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x02,
+ 0xff, 0x86, 0x04, 0x20, 0x9f, 0x02, 0xfe, 0xd0, 0xff, 0x81, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0x0e, 0x81, 0x00, 0x20, 0x9e, 0x82, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x90, 0x02, 0xfe, 0xc0,
+ 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x03, 0xff, 0x86, 0x01, 0xb4, 0x9f, 0x02, 0xfe, 0xd0,
+ 0xff, 0x81, 0x04, 0x08, 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x0e, 0x81, 0x80, 0x00, 0x9e, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x04,
+ 0xff, 0x86, 0x06, 0x3c, 0x9f, 0x02, 0xfe, 0xd0, 0xff, 0x81, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x82, 0x02, 0x00, 0x9e, 0x82, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x90, 0x02, 0xfe, 0xc0,
+ 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x05, 0xff, 0x82, 0xb4, 0xe4, 0x9f, 0x02, 0xfe, 0xd0,
+ 0xff, 0x81, 0x04, 0x10, 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x90, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x06, 0xfe, 0x82, 0xf8, 0xe0,
+ 0x9f, 0x02, 0xfe, 0xd0, 0xfe, 0x81, 0x04, 0x14, 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0x08, 0x10,
+ 0xff, 0x81, 0x04, 0x18, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf7, 0x86, 0x09, 0xc4, 0xe0, 0x01, 0x08, 0x50,
+ 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x86, 0x09, 0xd0, 0xe0, 0x01, 0x01, 0x28, 0x97, 0x93, 0xff, 0xfc,
+ 0x0f, 0x81, 0xe0, 0x00, 0xc5, 0x28, 0xfc, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0xf6, 0xed, 0xa0,
+ 0x8f, 0x7e, 0x10, 0x5c, 0x03, 0x01, 0xe1, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x0a, 0x10,
+ 0x03, 0x18, 0x16, 0x02, 0xf7, 0x86, 0x0a, 0x10, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x03, 0xf7, 0x86, 0x0a, 0x20, 0xe0, 0x00, 0x90, 0x20, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x01, 0xf7, 0x86, 0x0a, 0x30, 0xe0, 0x00, 0x96, 0xc8, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x01, 0xf7, 0x86, 0x0a, 0x40, 0xe0, 0x01, 0x01, 0x74, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x01, 0x0a, 0x91, 0xcf, 0x98, 0x00, 0x00,
+ 0xf0, 0x7f, 0x64, 0x01, 0x23, 0x9e, 0x00, 0x01, 0xe6, 0x01, 0x0a, 0x91, 0xcf, 0x7c, 0x32, 0x00,
+ 0x20, 0x7a, 0x00, 0xff, 0xee, 0x01, 0x0a, 0x61, 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68,
+ 0x93, 0x82, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfe, 0xd2, 0x00, 0x00, 0x8f, 0x76, 0x00, 0x00, 0x0f, 0x81, 0x6c, 0x6f,
+ 0x0f, 0xfc, 0x61, 0x65, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x0b, 0x2c, 0xff, 0xd2, 0x00, 0x00,
+ 0x83, 0xf6, 0x00, 0x04, 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x01, 0x0b, 0x2d, 0xcf, 0x1c, 0xe8, 0x00,
+ 0xff, 0xf6, 0xfe, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe2, 0x01, 0x0b, 0x28, 0x5e, 0x1d, 0x80, 0x00,
+ 0x8f, 0x76, 0x00, 0x08, 0x90, 0x76, 0x00, 0x00, 0xff, 0xd2, 0x00, 0x0c, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x82, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0x88, 0xf4, 0x02, 0x00, 0x00, 0xf3, 0x52, 0x00, 0x0c, 0xcf, 0x84, 0xfe, 0x00,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x0b, 0x28, 0xc4, 0xa0, 0x00, 0x00, 0xf7, 0x86, 0x0b, 0x28,
+ 0xe0, 0x00, 0xae, 0xc4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0xd2, 0x00, 0x00, 0x90, 0x7e, 0x00, 0x08,
+ 0x90, 0x7e, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x52, 0x53, 0x3d, 0x25, 0x78, 0x68, 0x2c, 0x25, 0x63, 0x2c, 0x25, 0x73, 0x0a, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x18, 0xf3, 0x0a, 0xba, 0x40,
+ 0xf3, 0xa6, 0x57, 0x7f, 0xc3, 0x9c, 0x32, 0x00, 0xf7, 0x86, 0x0b, 0x74, 0xe0, 0x01, 0x0a, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xfe, 0x8a, 0xb8, 0x88, 0xff, 0xf7, 0x58, 0x98, 0x20, 0x7e, 0x00, 0x01,
+ 0xe6, 0x01, 0x0b, 0xad, 0xff, 0x82, 0x00, 0x40, 0xfe, 0x82, 0x00, 0x04, 0xc0, 0x7e, 0xec, 0x00,
+ 0xe6, 0x01, 0x0b, 0x9c, 0xff, 0x02, 0x00, 0x00, 0xff, 0x08, 0xb8, 0x80, 0x9f, 0x7d, 0x00, 0x04,
+ 0x20, 0x7e, 0x01, 0xff, 0xee, 0x01, 0x0b, 0x91, 0xc0, 0x7e, 0xec, 0x00, 0xf7, 0x86, 0x0b, 0xb8,
+ 0xe0, 0x00, 0x34, 0x30, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xe8, 0xff, 0x02, 0x00, 0x04,
+ 0xfe, 0x82, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xe8, 0xcf, 0xfe, 0xf4, 0x00,
+ 0x9e, 0x96, 0xff, 0xf4, 0xe6, 0x01, 0x0e, 0x3d, 0x9f, 0x96, 0xff, 0xf0, 0x22, 0x10, 0x00, 0x10,
+ 0xfe, 0x86, 0x0b, 0x40, 0x9e, 0x92, 0x00, 0x00, 0x8f, 0x82, 0xff, 0xf0, 0x8e, 0x96, 0xff, 0xf4,
+ 0xff, 0x0a, 0xb3, 0x20, 0xff, 0x09, 0xb9, 0x24, 0x9f, 0x92, 0x00, 0x04, 0x20, 0x76, 0x00, 0x00,
+ 0xcf, 0x90, 0x00, 0x00, 0xe6, 0x01, 0x0c, 0x10, 0xff, 0x02, 0x00, 0x43, 0xff, 0x02, 0x00, 0x57,
+ 0x9f, 0x7e, 0x00, 0x08, 0xff, 0x0a, 0xb8, 0x8c, 0x9f, 0x7e, 0x00, 0x0c, 0xf7, 0x86, 0x0c, 0x28,
+ 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xe8, 0x70, 0x7e, 0x00, 0x1d,
+ 0xea, 0x01, 0x0c, 0x49, 0x02, 0x10, 0x00, 0x10, 0x8f, 0x96, 0xff, 0xf4, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x0e, 0x29, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x0c, 0x54, 0xe0, 0x00, 0x8e, 0x98,
+ 0x97, 0x93, 0xff, 0xfc, 0x05, 0x01, 0x40, 0x00, 0xf7, 0x86, 0x0c, 0x64, 0xe0, 0x01, 0x08, 0x50,
+ 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x86, 0x0c, 0x70, 0xe0, 0x01, 0x01, 0x28, 0x97, 0x93, 0xff, 0xfc,
+ 0xf7, 0x86, 0x0c, 0x7c, 0xe0, 0x00, 0x0a, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x86, 0x0c, 0x88,
+ 0xe0, 0x02, 0x83, 0x0c, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x86, 0x0c, 0x94, 0xe0, 0x00, 0x20, 0x24,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xe8, 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x01, 0x0c, 0xdd,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xf4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x01, 0x0c, 0xb8,
+ 0xf3, 0x02, 0x00, 0x43, 0xf3, 0x02, 0x00, 0x57, 0xf7, 0x86, 0x0c, 0xc4, 0xe0, 0x00, 0x21, 0x54,
+ 0x97, 0x93, 0xff, 0xfc, 0x83, 0x02, 0xff, 0xf0, 0x73, 0x18, 0xff, 0xe6, 0x03, 0x18, 0x00, 0x30,
+ 0xf7, 0x86, 0x0c, 0xdc, 0xe0, 0x00, 0x21, 0x54, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xe8,
+ 0xff, 0x02, 0x03, 0x0f, 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x01, 0x0e, 0x14, 0xff, 0x09, 0xe1, 0xd0,
+ 0xf0, 0x09, 0xb2, 0xe8, 0xf7, 0x86, 0x0d, 0x00, 0xe0, 0x01, 0x09, 0xe4, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x76, 0xed, 0xa0, 0x8c, 0xfa, 0x10, 0x54, 0xcf, 0x84, 0x00, 0x00, 0xc0, 0x66, 0xfa, 0x00,
+ 0xe6, 0x01, 0x0d, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x8d, 0x7a, 0x10, 0x50, 0xff, 0x88, 0xe1, 0xc0,
+ 0xfe, 0x88, 0xe6, 0xd8, 0x20, 0x6a, 0x00, 0x00, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xfc, 0x00, 0x06,
+ 0x5f, 0x70, 0x00, 0x02, 0xff, 0x89, 0xe1, 0xc0, 0x7f, 0x79, 0x00, 0x0d, 0xff, 0x77, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0xff, 0x02, 0x7c, 0xcc,
+ 0xfd, 0xfb, 0x58, 0x20, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x0e,
+ 0x7e, 0x71, 0x00, 0x02, 0xcf, 0xf4, 0xe0, 0x00, 0xfd, 0xf7, 0x28, 0x12, 0x9d, 0x76, 0x00, 0x14,
+ 0x9c, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0x55, 0x29, 0x80, 0x00, 0xff, 0x86, 0x00, 0x01,
+ 0x9f, 0xf6, 0x00, 0x30, 0xff, 0x77, 0x18, 0x0a, 0x8d, 0xf6, 0x00, 0x2c, 0x0f, 0xf4, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x82, 0xac, 0x24, 0x9f, 0xf6, 0x00, 0x04,
+ 0xfd, 0x89, 0xe6, 0xd8, 0xff, 0x82, 0x00, 0x04, 0x9f, 0xf6, 0x00, 0x28, 0xff, 0xf6, 0xfd, 0xf8,
+ 0x9f, 0xf6, 0x00, 0x24, 0x9f, 0x82, 0xfe, 0x58, 0x0f, 0x81, 0x10, 0x00, 0x0f, 0xfc, 0x00, 0x04,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0f, 0x78, 0x00, 0x01, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00,
+ 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xf0, 0x77, 0x28, 0x02,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x0d, 0xe0,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x0e, 0x20, 0xe0, 0x00, 0x80, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x01, 0x0d, 0xe0, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x0e, 0x34, 0xe0, 0x01, 0x0a, 0x9c,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x0c, 0x48, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x0e, 0x48,
+ 0xe0, 0x00, 0x8d, 0x50, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf0, 0xff, 0x0a, 0xb8, 0x88,
+ 0x94, 0x16, 0xff, 0xf4, 0xe0, 0x01, 0x0b, 0xdc, 0xff, 0xfb, 0x68, 0x99, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf2, 0x0a, 0xfb, 0x90, 0xf2, 0x82, 0x00, 0x00, 0xf7, 0x86, 0x0e, 0x88, 0xe0, 0x01, 0x0e, 0xec,
+ 0x97, 0x93, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x0e, 0x88, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x62, 0x63, 0x6f, 0x64,
+ 0x65, 0x5f, 0x6a, 0x6d, 0x70, 0x20, 0x52, 0x54, 0x43, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20,
+ 0x69, 0x74, 0x65, 0x72, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x52, 0x45, 0x42, 0x4f, 0x4f, 0x54, 0x5f,
+ 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x54, 0x72, 0x79,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x6a, 0x6d, 0x70, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20,
+ 0x74, 0x6f, 0x20, 0x7a, 0x65, 0x72, 0x6f, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x14, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x02, 0x00, 0x00,
+ 0x9f, 0x96, 0xff, 0xf4, 0x8f, 0x82, 0xff, 0xd0, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x01, 0x0f, 0x24,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x0f, 0x15,
+ 0x0f, 0x78, 0x00, 0x01, 0x22, 0x10, 0x00, 0x10, 0xff, 0x86, 0x0e, 0x9c, 0x9f, 0x92, 0x00, 0x00,
+ 0x8f, 0x96, 0xff, 0xf4, 0x9f, 0x12, 0x00, 0x08, 0x9f, 0x92, 0x00, 0x04, 0x8f, 0x82, 0xff, 0xf0,
+ 0x9f, 0x92, 0x00, 0x0c, 0xf7, 0x86, 0x0f, 0x50, 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x96, 0xff, 0xf4, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x0f, 0x74, 0x02, 0x10, 0x00, 0x10,
+ 0xff, 0x83, 0x5b, 0xe8, 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x0f, 0x89,
+ 0xff, 0x1a, 0x1a, 0x7f, 0xf3, 0x02, 0x00, 0x04, 0xf7, 0x86, 0x0f, 0x84, 0xe0, 0x00, 0x7b, 0x5c,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x1a, 0x1a, 0x7f, 0x8f, 0x82, 0xff, 0xd0, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xe2, 0x01, 0x0f, 0x89, 0xff, 0x86, 0x0e, 0xcd, 0x22, 0x10, 0x00, 0x04, 0x9f, 0x92, 0x00, 0x00,
+ 0xf7, 0x86, 0x0f, 0xac, 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x07, 0x08,
+ 0x00, 0x00, 0x07, 0x48, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x76, 0xff, 0xd8,
+ 0x8f, 0xf2, 0x00, 0x00, 0x0f, 0x01, 0xff, 0xfc, 0x0f, 0x78, 0x03, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0xfe, 0x86, 0xd4, 0x00, 0xcf, 0xfc, 0xed, 0x00, 0x4f, 0xfd, 0xfc, 0x03, 0x5f, 0xfd, 0x02, 0x00,
+ 0x4f, 0xfd, 0x03, 0xff, 0x5f, 0xfd, 0x04, 0x00, 0x9f, 0xf2, 0x00, 0x00, 0xff, 0x76, 0xff, 0xd4,
+ 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0x76, 0xff, 0xd0, 0xfd, 0x76, 0xff, 0xcc, 0x5f, 0xfc, 0x00, 0x88,
+ 0x4f, 0xfc, 0x7e, 0x88, 0x4f, 0xfd, 0xff, 0xfc, 0x5f, 0xfd, 0x00, 0x06, 0x4f, 0xfd, 0xff, 0xe7,
+ 0x5f, 0xfd, 0x00, 0x10, 0x4f, 0xfd, 0xe7, 0xff, 0x5f, 0xfd, 0x10, 0x00, 0x9f, 0xfa, 0x00, 0x00,
+ 0x8e, 0xf2, 0x00, 0x00, 0xfd, 0xf6, 0xff, 0xc8, 0xf3, 0x76, 0xff, 0xfc, 0x5e, 0xf4, 0x00, 0x08,
+ 0x9e, 0xf2, 0x00, 0x00, 0x8f, 0x6a, 0x00, 0x00, 0x4f, 0x79, 0xef, 0xdf, 0x5f, 0x79, 0xe0, 0x00,
+ 0x9f, 0x6a, 0x00, 0x00, 0x8f, 0xee, 0x00, 0x00, 0x0f, 0x01, 0xff, 0xfe, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x5f, 0xfc, 0x00, 0x7e, 0x4f, 0xfd, 0xff, 0xc9, 0x5f, 0xfd, 0x07, 0x20, 0x9f, 0xee, 0x00, 0x00,
+ 0xf7, 0x86, 0x10, 0x8c, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfe, 0x82, 0x00, 0x00, 0x73, 0x19, 0x00, 0x02, 0xce, 0x74, 0x00, 0x00, 0xfd, 0x9e, 0x46, 0xe0,
+ 0x7f, 0x75, 0x00, 0x02, 0x7f, 0xf0, 0xff, 0xf8, 0x0e, 0xf4, 0x00, 0x01, 0xbf, 0xfa, 0xd8, 0x02,
+ 0x20, 0x76, 0x04, 0x00, 0xe2, 0x01, 0x10, 0xb1, 0xce, 0x70, 0x30, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x86, 0xc6, 0xe0, 0xff, 0x8d, 0x7c, 0x44, 0xff, 0x86, 0xc9, 0x74, 0xff, 0x8d, 0x7c, 0xc4,
+ 0xff, 0x88, 0xb9, 0x44, 0x20, 0x7e, 0x00, 0x01, 0xff, 0x86, 0xcc, 0x08, 0xff, 0x8d, 0x7d, 0x44,
+ 0xff, 0x86, 0xce, 0x9c, 0xff, 0x8d, 0x7d, 0xc4, 0xff, 0x86, 0xd1, 0x30, 0xff, 0x8d, 0x7e, 0x44,
+ 0xff, 0x86, 0xd3, 0xc4, 0xff, 0x8d, 0x7e, 0xc4, 0xff, 0x86, 0xaf, 0xb8, 0xff, 0x8d, 0x7c, 0x40,
+ 0xff, 0x86, 0xb0, 0xb0, 0xff, 0x8d, 0x7c, 0xc0, 0xff, 0x86, 0xb1, 0xa8, 0xff, 0x8d, 0x7d, 0x40,
+ 0xff, 0x86, 0xb2, 0xa0, 0xff, 0x8d, 0x7d, 0xc0, 0xff, 0x86, 0xb3, 0x98, 0xff, 0x8d, 0x7e, 0x40,
+ 0xff, 0x86, 0xb4, 0x90, 0xe6, 0x01, 0x11, 0x7c, 0xff, 0x8d, 0x7e, 0xc0, 0xff, 0x86, 0xd6, 0x58,
+ 0xff, 0x8d, 0x7c, 0x44, 0xff, 0x86, 0xd9, 0x10, 0xff, 0x8d, 0x7c, 0xc4, 0xff, 0x86, 0xdb, 0xc8,
+ 0xff, 0x8d, 0x7d, 0x44, 0xff, 0x86, 0xde, 0x80, 0xff, 0x8d, 0x7d, 0xc4, 0xff, 0x86, 0xe1, 0x38,
+ 0xff, 0x8d, 0x7e, 0x44, 0xff, 0x86, 0xe3, 0xf0, 0xff, 0x8d, 0x7e, 0xc4, 0xff, 0x86, 0xb5, 0x88,
+ 0xff, 0x8d, 0x7c, 0x48, 0xff, 0x86, 0xb6, 0xf8, 0xff, 0x8d, 0x7c, 0xc8, 0xff, 0x86, 0xb8, 0x68,
+ 0xff, 0x8d, 0x7d, 0x48, 0xff, 0x86, 0xb9, 0xd8, 0xff, 0x8d, 0x7d, 0xc8, 0xff, 0x86, 0xbb, 0x48,
+ 0xff, 0x8d, 0x7e, 0x48, 0xff, 0x86, 0xbc, 0xb8, 0xff, 0x8d, 0x7e, 0xc8, 0xff, 0x86, 0xbe, 0x28,
+ 0xff, 0x8d, 0x7c, 0x4c, 0xff, 0x86, 0xbf, 0x9c, 0xff, 0x8d, 0x7c, 0xcc, 0xff, 0x86, 0xc1, 0x10,
+ 0xff, 0x8d, 0x7d, 0x4c, 0xff, 0x86, 0xc2, 0x84, 0xff, 0x8d, 0x7d, 0xcc, 0xff, 0x86, 0xc3, 0xf8,
+ 0xff, 0x8d, 0x7e, 0x4c, 0xff, 0x86, 0xc5, 0x6c, 0xff, 0x8d, 0x7e, 0xcc, 0xff, 0x86, 0xe6, 0xa8,
+ 0xff, 0x8d, 0x7c, 0x50, 0xff, 0x86, 0xe8, 0x50, 0xff, 0x8d, 0x7c, 0xd0, 0xff, 0x86, 0xe9, 0xf8,
+ 0xff, 0x8d, 0x7d, 0x50, 0xff, 0x86, 0xeb, 0xa0, 0xff, 0x8d, 0x7d, 0xd0, 0xff, 0x86, 0xed, 0x48,
+ 0xff, 0x8d, 0x7e, 0x50, 0xff, 0x86, 0xee, 0xf0, 0xff, 0x8d, 0x7e, 0xd0, 0xff, 0x86, 0xf0, 0x98,
+ 0xff, 0x8d, 0x7c, 0x54, 0xff, 0x86, 0xf2, 0x44, 0xff, 0x8d, 0x7c, 0xd4, 0xff, 0x86, 0xf3, 0xf0,
+ 0xff, 0x8d, 0x7d, 0x54, 0xff, 0x86, 0xf5, 0x9c, 0xff, 0x8d, 0x7d, 0xd4, 0xff, 0x86, 0xf7, 0x48,
+ 0xff, 0x8d, 0x7e, 0x54, 0xff, 0x86, 0xf8, 0xf4, 0xff, 0x8d, 0x7e, 0xd4, 0xff, 0x86, 0xfa, 0xa0,
+ 0xff, 0x8d, 0x7c, 0x58, 0xff, 0x86, 0xfd, 0x00, 0xff, 0x8d, 0x7c, 0xd8, 0xff, 0x86, 0xff, 0x60,
+ 0xff, 0x8d, 0x7d, 0x58, 0xff, 0x8a, 0x01, 0xc0, 0xff, 0x8d, 0x7d, 0xd8, 0xff, 0x8a, 0x04, 0x20,
+ 0xff, 0x8d, 0x7e, 0x58, 0xff, 0x8a, 0x06, 0x80, 0xff, 0x8d, 0x7e, 0xd8, 0xff, 0x8a, 0x08, 0xe0,
+ 0xff, 0x8d, 0x7c, 0x5c, 0xff, 0x8a, 0x0b, 0x44, 0xff, 0x8d, 0x7c, 0xdc, 0xff, 0x8a, 0x0d, 0xa8,
+ 0xff, 0x8d, 0x7d, 0x5c, 0xff, 0x8a, 0x10, 0x0c, 0xff, 0x8d, 0x7d, 0xdc, 0xff, 0x8a, 0x12, 0x70,
+ 0xff, 0x8d, 0x7e, 0x5c, 0xff, 0x8a, 0x14, 0xd4, 0xff, 0x8d, 0x7e, 0xdc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8a, 0x17, 0x50, 0xff, 0x81, 0x06, 0x00, 0xff, 0x8a, 0x1e, 0xd8, 0xff, 0x81, 0x07, 0x00,
+ 0xff, 0x8a, 0x20, 0x88, 0xff, 0x81, 0x05, 0x28, 0xff, 0x8a, 0x23, 0xe8, 0xff, 0x81, 0x06, 0x28,
+ 0xff, 0x8a, 0x21, 0x60, 0xff, 0x81, 0x05, 0x2c, 0xff, 0x8a, 0x23, 0xe8, 0xff, 0x81, 0x06, 0x2c,
+ 0xff, 0x8a, 0x22, 0x38, 0xff, 0x81, 0x05, 0x30, 0xff, 0x8a, 0x23, 0xe8, 0xff, 0x81, 0x06, 0x30,
+ 0xff, 0x8a, 0x23, 0x10, 0xff, 0x81, 0x05, 0x34, 0xff, 0x8a, 0x23, 0xe8, 0xff, 0x81, 0x06, 0x34,
+ 0xff, 0x8a, 0x25, 0x98, 0xff, 0x81, 0x05, 0x38, 0xff, 0x8a, 0x26, 0x70, 0xff, 0x81, 0x06, 0x38,
+ 0xff, 0x8a, 0x26, 0x04, 0xff, 0x81, 0x05, 0x3c, 0xff, 0x8a, 0x26, 0x70, 0xff, 0x81, 0x06, 0x3c,
+ 0xff, 0x8a, 0x28, 0x20, 0xff, 0x81, 0x06, 0xfc, 0xf0, 0x1d, 0x46, 0x38, 0xf0, 0x0d, 0x4b, 0xc8,
+ 0xf0, 0x0d, 0x7f, 0xe8, 0xfe, 0x82, 0x00, 0x00, 0xfd, 0x8e, 0x7c, 0x40, 0xfe, 0x0e, 0x7c, 0xc0,
+ 0x20, 0x76, 0x00, 0x06, 0x7f, 0xf5, 0x00, 0x07, 0xe6, 0x01, 0x14, 0x49, 0xff, 0x02, 0x00, 0x00,
+ 0xcf, 0x7c, 0xe0, 0x00, 0xcf, 0xfc, 0xd8, 0x00, 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x76, 0x00, 0x06,
+ 0xe2, 0x01, 0x13, 0x45, 0x9f, 0x7e, 0x00, 0x38, 0xff, 0x82, 0x00, 0x02, 0xff, 0x8d, 0x7c, 0x7c,
+ 0xff, 0x82, 0x05, 0xf2, 0xff, 0x8d, 0x7c, 0xfc, 0xff, 0x82, 0x0b, 0xe2, 0xff, 0x8d, 0x7d, 0x7c,
+ 0xff, 0x82, 0x11, 0xd2, 0xff, 0x8d, 0x7d, 0xfc, 0xff, 0x82, 0x36, 0x8a, 0xff, 0x8d, 0x7e, 0x7c,
+ 0xff, 0x82, 0x5b, 0x42, 0xff, 0x8d, 0x7e, 0xfc, 0xf7, 0x86, 0x13, 0xa4, 0xe0, 0x01, 0x10, 0xd8,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0xa6, 0x57, 0x78, 0x0f, 0xfc, 0x7f, 0xff, 0x4f, 0xfc, 0x80, 0x00,
+ 0xff, 0x99, 0x86, 0x20, 0x0f, 0xfc, 0x60, 0x00, 0xff, 0x8d, 0x80, 0x78, 0x0f, 0xfc, 0x20, 0x00,
+ 0xff, 0x9d, 0x46, 0x78, 0xff, 0x0e, 0x4c, 0x30, 0xfe, 0x82, 0x00, 0x00, 0xff, 0x82, 0x00, 0x06,
+ 0xff, 0xfb, 0x24, 0x02, 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x76, 0x0b, 0xff, 0xe2, 0x01, 0x13, 0xd1,
+ 0x0f, 0xfc, 0x00, 0x10, 0xff, 0x0e, 0x64, 0x30, 0xfe, 0x82, 0x00, 0x00, 0xff, 0x82, 0x00, 0x06,
+ 0xff, 0xfb, 0x24, 0x02, 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x76, 0x0b, 0xff, 0xe2, 0x01, 0x13, 0xf1,
+ 0x0f, 0xfc, 0x00, 0x10, 0xff, 0x1a, 0x86, 0x30, 0xfe, 0x82, 0x00, 0x00, 0xff, 0x82, 0x08, 0x00,
+ 0xff, 0xfb, 0x24, 0x02, 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x76, 0x5b, 0xff, 0xe2, 0x01, 0x14, 0x11,
+ 0x0f, 0xfc, 0x00, 0x02, 0xff, 0x1e, 0x3e, 0x30, 0xfe, 0x82, 0x00, 0x00, 0xcf, 0xf4, 0xe8, 0x00,
+ 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x76, 0x03, 0xff, 0xe2, 0x01, 0x14, 0x2d, 0xff, 0xfb, 0x24, 0x02,
+ 0xe0, 0x01, 0x14, 0x50, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x13, 0x54, 0xff, 0x82, 0x03, 0x00,
+ 0xf3, 0x08, 0xb9, 0x34, 0xf7, 0x86, 0x14, 0x60, 0xe0, 0x01, 0x10, 0x98, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xb3, 0x2c, 0xff, 0x89, 0xbc, 0x08, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0xfe, 0x0c, 0x84, 0xc8, 0x8d, 0x82, 0xff, 0xd0, 0xf4, 0x02, 0x00, 0x01, 0x0f, 0xf0, 0x00, 0x02,
+ 0x20, 0x7e, 0x24, 0xb8, 0xe2, 0x01, 0x15, 0xc8, 0x9d, 0x96, 0xff, 0xf4, 0xff, 0x0c, 0x85, 0xf0,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe2, 0x01, 0x14, 0xe9, 0xfc, 0x8a, 0xb9, 0x68, 0x20, 0x7a, 0x0f, 0xff,
+ 0xe2, 0x01, 0x15, 0xc9, 0x7f, 0xf8, 0xff, 0xf5, 0xc0, 0x7e, 0x42, 0x00, 0xe6, 0x01, 0x14, 0xe9,
+ 0xfc, 0x8a, 0xb9, 0xa4, 0x20, 0x7e, 0x00, 0x02, 0xe6, 0x01, 0x14, 0xe9, 0xfc, 0x8a, 0xb9, 0x90,
+ 0x20, 0x7e, 0x00, 0x04, 0xe6, 0x01, 0x14, 0xe9, 0xfc, 0x8a, 0xb9, 0x7c, 0x20, 0x7e, 0x00, 0x08,
+ 0xe6, 0x01, 0x15, 0xc8, 0xfc, 0x8a, 0xb9, 0x68, 0xfe, 0x82, 0x00, 0x00, 0x7f, 0xf5, 0x00, 0x02,
+ 0x0e, 0xf4, 0x00, 0x01, 0xfd, 0x86, 0x3d, 0x4c, 0xff, 0x0e, 0x86, 0x00, 0x20, 0x76, 0x00, 0x3f,
+ 0xe2, 0x01, 0x14, 0xed, 0xbd, 0xfe, 0xf0, 0x02, 0x0e, 0xf0, 0x00, 0x05, 0x20, 0x76, 0xbf, 0xff,
+ 0xe2, 0x01, 0x15, 0x34, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xf5, 0x00, 0x02, 0x0e, 0xf4, 0x00, 0x01,
+ 0xff, 0x06, 0x3d, 0x4c, 0xfe, 0x0e, 0x86, 0x00, 0x20, 0x76, 0xbf, 0xff, 0xe2, 0x01, 0x15, 0x19,
+ 0xbf, 0x7e, 0xe0, 0x02, 0x9c, 0x96, 0xff, 0xf0, 0xf7, 0x86, 0x15, 0x44, 0xe0, 0x00, 0x7e, 0x10,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x8c, 0x84, 0xc8, 0x8c, 0x96, 0xff, 0xf0, 0xfe, 0x82, 0x00, 0x40,
+ 0x0f, 0xfc, 0x00, 0x04, 0xc0, 0x76, 0xfa, 0x00, 0xe2, 0x01, 0x15, 0xa4, 0xcd, 0xfc, 0x00, 0x00,
+ 0xfd, 0x0c, 0x4b, 0xb8, 0x2f, 0x74, 0x00, 0x04, 0x0f, 0xf8, 0x08, 0x01, 0x7e, 0x75, 0x00, 0x02,
+ 0x7f, 0xfc, 0xff, 0xf5, 0xc0, 0x7a, 0xd2, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0x0e, 0xf4, 0x00, 0x01,
+ 0xe2, 0x01, 0x15, 0x8d, 0xff, 0x0a, 0xb9, 0x54, 0xcf, 0x64, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00,
+ 0x8f, 0xfe, 0xff, 0xfc, 0xff, 0x0e, 0x86, 0x00, 0xc0, 0x76, 0xda, 0x00, 0xe2, 0x01, 0x15, 0x65,
+ 0xbf, 0xf2, 0xf0, 0x02, 0xf7, 0x86, 0x15, 0xb0, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x82, 0xff, 0xd0, 0x8d, 0x96, 0xff, 0xf4, 0xf4, 0x02, 0x00, 0x00, 0xcf, 0xfc, 0xda, 0x00,
+ 0x5f, 0xfd, 0xfd, 0x00, 0x9f, 0x82, 0xfe, 0x88, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x6d, 0x63, 0x70, 0x5f, 0x7a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x75, 0x70,
+ 0x3a, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x0a,
+ 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0xf7, 0x86, 0x16, 0x0c, 0xe0, 0x01, 0x14, 0x74, 0x97, 0x93, 0xff, 0xfc, 0xc9, 0xa0, 0x00, 0x00,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x01, 0x17, 0xdc, 0xf4, 0x02, 0x00, 0x01, 0x99, 0x96, 0xff, 0xf4,
+ 0xf3, 0x02, 0x00, 0x02, 0xf7, 0x86, 0x16, 0x30, 0xe0, 0x00, 0x7a, 0xe0, 0x97, 0x93, 0xff, 0xfc,
+ 0xfe, 0x98, 0x86, 0x18, 0xff, 0x9c, 0x46, 0x78, 0x89, 0x96, 0xff, 0xf4, 0x7f, 0x75, 0x00, 0x01,
+ 0xcf, 0xfc, 0xf0, 0x00, 0xcf, 0x00, 0xf2, 0x00, 0x0f, 0xfc, 0x0f, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0xce, 0xfc, 0xe8, 0x00, 0xff, 0x76, 0xc9, 0xe7, 0xc0, 0x76, 0xf2, 0x00, 0xff, 0x8d, 0x80, 0x70,
+ 0xff, 0x8d, 0x7f, 0xd8, 0xff, 0x9d, 0x46, 0xc0, 0xf9, 0x8d, 0x4c, 0x28, 0xe2, 0x01, 0x17, 0xc0,
+ 0xf9, 0x8d, 0x7f, 0xc8, 0xff, 0x8a, 0xb2, 0xe6, 0xfd, 0x7f, 0x18, 0x00, 0xfd, 0x8c, 0x7f, 0xe0,
+ 0xfe, 0x0c, 0x84, 0xd8, 0xff, 0x8a, 0xb2, 0xde, 0xfb, 0xff, 0x18, 0x00, 0xcd, 0xec, 0xd8, 0x00,
+ 0xfa, 0x88, 0xb9, 0x40, 0xff, 0x88, 0xb9, 0x3c, 0x9d, 0x82, 0xff, 0xb8, 0xfd, 0x82, 0x40, 0x00,
+ 0xce, 0x70, 0xf8, 0x00, 0xff, 0xa6, 0x57, 0x50, 0xfd, 0xff, 0x28, 0x04, 0xfd, 0x82, 0x00, 0x08,
+ 0xfd, 0xff, 0x28, 0x0e, 0xff, 0x0e, 0x85, 0x90, 0xfb, 0x0c, 0x80, 0x68, 0xfd, 0x82, 0x40, 0x00,
+ 0x7d, 0x69, 0x00, 0x0f, 0xfd, 0xfb, 0x28, 0x00, 0x7e, 0xd4, 0xff, 0xfe, 0x5a, 0x68, 0x00, 0x01,
+ 0xfd, 0x82, 0x00, 0xff, 0x20, 0x5a, 0x00, 0x00, 0xcd, 0x68, 0xed, 0x00, 0xfd, 0xfb, 0x28, 0x0a,
+ 0xfe, 0x8e, 0x80, 0x00, 0xe6, 0x48, 0x00, 0x02, 0xfd, 0x82, 0x40, 0x00, 0xfd, 0xf7, 0x28, 0x00,
+ 0x5c, 0x48, 0x00, 0x02, 0x7c, 0x61, 0x00, 0x0d, 0xfd, 0x82, 0x00, 0x0f, 0x7c, 0xc9, 0x00, 0x02,
+ 0xfd, 0xf7, 0x28, 0x0a, 0xfc, 0x7f, 0x28, 0x08, 0xfa, 0x7f, 0x28, 0x0a, 0xfb, 0xff, 0x28, 0x0c,
+ 0xcf, 0xe4, 0xf8, 0x00, 0xfb, 0x25, 0x57, 0x60, 0x2d, 0xf0, 0x00, 0x04, 0x99, 0xfe, 0x00, 0x14,
+ 0x9d, 0xfe, 0x00, 0x10, 0xff, 0x9c, 0x46, 0x60, 0xfd, 0x7b, 0x28, 0x06, 0xfc, 0x7b, 0x28, 0x04,
+ 0xfb, 0xfb, 0x28, 0x08, 0xfc, 0x77, 0x28, 0x04, 0xfa, 0x77, 0x28, 0x06, 0xfb, 0xf7, 0x28, 0x08,
+ 0xcf, 0x64, 0xf0, 0x00, 0xca, 0xf0, 0xaa, 0x00, 0xce, 0xe4, 0xe8, 0x00, 0x20, 0x7e, 0x00, 0x00,
+ 0xfb, 0x0d, 0x85, 0x9c, 0xfb, 0x0d, 0x80, 0x0c, 0x0c, 0xe4, 0x00, 0x14, 0x2e, 0x70, 0x00, 0x28,
+ 0xff, 0x82, 0x00, 0x01, 0x9a, 0xfa, 0x00, 0x0c, 0x9e, 0x76, 0x00, 0x0c, 0xfc, 0xa5, 0x57, 0x50,
+ 0xff, 0x8d, 0x85, 0x80, 0xe6, 0x01, 0x17, 0xa5, 0x45, 0x29, 0xff, 0xef, 0xfd, 0x86, 0x1c, 0xec,
+ 0x20, 0x4a, 0x00, 0x00, 0xfd, 0x81, 0x04, 0x18, 0xe6, 0x01, 0x17, 0x94, 0xff, 0x86, 0x28, 0xf4,
+ 0xff, 0x86, 0x25, 0x5c, 0xff, 0x81, 0x04, 0x1c, 0xff, 0x81, 0x04, 0x20, 0xe0, 0x01, 0x17, 0xdc,
+ 0xf4, 0x02, 0x00, 0x00, 0xff, 0x86, 0x1b, 0xa8, 0xff, 0x81, 0x04, 0x18, 0x20, 0x4a, 0x00, 0x00,
+ 0xe6, 0x01, 0x17, 0x94, 0xff, 0x86, 0x21, 0xc8, 0xe0, 0x01, 0x17, 0x94, 0xff, 0x86, 0x1e, 0x38,
+ 0x22, 0x10, 0x00, 0x04, 0xfd, 0x86, 0x15, 0xd4, 0x9d, 0x92, 0x00, 0x00, 0xf7, 0x86, 0x17, 0xd8,
+ 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0xc4, 0x04, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf7, 0x86, 0x17, 0xfc, 0xe0, 0x00, 0x7a, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xff, 0xfe, 0x00, 0x06,
+ 0xff, 0x8d, 0x7c, 0x30, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xfe, 0x02, 0x00, 0x00,
+ 0xff, 0x8e, 0x7c, 0x60, 0x90, 0xfe, 0x00, 0x00, 0x0e, 0x70, 0x00, 0x01, 0x20, 0x72, 0x00, 0x06,
+ 0xe2, 0x01, 0x18, 0x25, 0x0f, 0xfc, 0x00, 0x80, 0xfe, 0x02, 0x00, 0x00, 0xff, 0x8c, 0x80, 0x78,
+ 0x7e, 0xf1, 0x00, 0x03, 0x0e, 0x70, 0x00, 0x01, 0xb0, 0xf6, 0xf8, 0x02, 0xff, 0x8c, 0x80, 0x78,
+ 0x20, 0x72, 0x01, 0xff, 0xcf, 0xf4, 0xf8, 0x00, 0x90, 0xfe, 0x00, 0x04, 0xff, 0x1c, 0x46, 0x78,
+ 0xb0, 0xf6, 0xf0, 0x02, 0xff, 0x9c, 0x46, 0x78, 0xce, 0xf4, 0xf8, 0x00, 0xe2, 0x01, 0x18, 0x3d,
+ 0x90, 0xf6, 0x00, 0x04, 0xfe, 0x02, 0x00, 0x00, 0xff, 0x98, 0x86, 0x20, 0x7f, 0x71, 0x00, 0x04,
+ 0x0e, 0x70, 0x00, 0x01, 0xb0, 0x7e, 0xf0, 0x02, 0xcf, 0xfc, 0xf0, 0x00, 0x90, 0x7e, 0x00, 0x0c,
+ 0x90, 0x7e, 0x00, 0x04, 0x20, 0x72, 0x03, 0xff, 0xe2, 0x01, 0x18, 0x79, 0x90, 0x7e, 0x00, 0x08,
+ 0xff, 0x98, 0x86, 0x20, 0xff, 0x0c, 0x80, 0x78, 0xfe, 0x9c, 0x46, 0x78, 0xff, 0x8d, 0x7f, 0xf0,
+ 0xff, 0x0d, 0x80, 0x60, 0xfe, 0x8d, 0x7f, 0xf8, 0xff, 0x9d, 0x46, 0x30, 0xff, 0x1d, 0x46, 0xd0,
+ 0xfe, 0x99, 0x86, 0x08, 0xf7, 0x86, 0x18, 0xd0, 0xe0, 0x01, 0x17, 0xe8, 0x97, 0x93, 0xff, 0xfc,
+ 0x0f, 0x81, 0xe0, 0x00, 0xce, 0xa8, 0xfc, 0x00, 0xfe, 0x08, 0xa2, 0x80, 0xff, 0x42, 0xfc, 0x00,
+ 0xc5, 0x74, 0xf5, 0x00, 0xfe, 0x82, 0x00, 0x03, 0xf0, 0x09, 0xb9, 0x44, 0xf0, 0x0d, 0x84, 0xc8,
+ 0xf0, 0x0d, 0x85, 0x80, 0xfe, 0x8d, 0x85, 0x08, 0xfe, 0x8d, 0x85, 0x0c, 0x70, 0x72, 0x00, 0x0c,
+ 0xea, 0x01, 0x19, 0x94, 0xfd, 0x82, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8, 0x4f, 0xf1, 0xff, 0xf7,
+ 0xff, 0x89, 0xa2, 0x80, 0xff, 0x82, 0x34, 0x00, 0xf7, 0x82, 0x00, 0x40, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0xf7, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0x24, 0xff, 0xf7, 0x28, 0x12, 0x9d, 0xf6, 0x00, 0x14,
+ 0x9d, 0xf6, 0x00, 0x18, 0x9d, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x9d, 0xf6, 0x00, 0x30,
+ 0xff, 0x77, 0x18, 0x0a, 0x8e, 0x76, 0x00, 0x2c, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x0f, 0x81, 0x10, 0x00, 0x0f, 0xfc, 0x00, 0x14, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0xec,
+ 0x9f, 0xf6, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0xfd, 0xf7, 0x28, 0x02, 0xff, 0x76, 0xff, 0xd0, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0x82, 0x00, 0x01,
+ 0xf3, 0x76, 0xff, 0xfc, 0xfe, 0x8d, 0x80, 0x58, 0x5f, 0xfc, 0x00, 0x08, 0x9f, 0xfa, 0x00, 0x00,
+ 0x9d, 0x96, 0xff, 0xf4, 0xf7, 0x86, 0x19, 0xc0, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x96, 0xff, 0xf4, 0xfd, 0x89, 0xb9, 0x50, 0xfd, 0x89, 0xb9, 0x4c, 0xf7, 0x86, 0x19, 0xd8,
+ 0xe0, 0x01, 0x2c, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0e, 0x4b, 0xe0,
+ 0xfe, 0x8a, 0x31, 0xc4, 0xf7, 0x82, 0x00, 0x01, 0xf7, 0xfb, 0x68, 0x3f, 0x8d, 0x96, 0xff, 0xf4,
+ 0xff, 0x9d, 0x46, 0x40, 0xff, 0x82, 0x00, 0x03, 0xfd, 0xfb, 0x68, 0x3c, 0xfd, 0xfb, 0x68, 0x3d,
+ 0xfd, 0xfb, 0x68, 0x3e, 0xfd, 0x8d, 0x85, 0x00, 0xfd, 0x8d, 0x7f, 0xd0, 0xfd, 0x8d, 0x85, 0x60,
+ 0xfd, 0x8d, 0x4b, 0xe4, 0xfd, 0x8d, 0x4b, 0xe8, 0xfd, 0x8d, 0x4b, 0xec, 0xfd, 0x8d, 0x4b, 0xf0,
+ 0xfd, 0x8d, 0x4b, 0xf4, 0xfd, 0x8d, 0x4b, 0xf8, 0xff, 0x8d, 0x4b, 0xfc, 0xfd, 0x8d, 0x4c, 0x00,
+ 0xfd, 0x8d, 0x4c, 0x04, 0xfd, 0x8d, 0x4c, 0x08, 0xfd, 0x8d, 0x4c, 0x0c, 0xfd, 0x8d, 0x4c, 0x10,
+ 0xfd, 0x8d, 0x4c, 0x14, 0xfd, 0x99, 0x86, 0x10, 0xfe, 0x81, 0x04, 0x18, 0xfe, 0x81, 0x04, 0x20,
+ 0xfe, 0x81, 0x04, 0x1c, 0xf7, 0x86, 0x1a, 0x60, 0xe0, 0x00, 0xbf, 0xd8, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0xf6, 0xff, 0x70, 0x8e, 0xfe, 0x00, 0x00, 0xff, 0x76, 0xff, 0x74, 0x8d, 0xfa, 0x00, 0x00,
+ 0x7e, 0x75, 0x00, 0x1c, 0xff, 0xf6, 0xff, 0x78, 0x8c, 0xfe, 0x00, 0x00, 0x7e, 0x70, 0xff, 0xe8,
+ 0x7f, 0x6c, 0xff, 0xe4, 0xcf, 0x78, 0xe0, 0x00, 0x7e, 0xf5, 0x00, 0x14, 0x7e, 0x6d, 0x00, 0x04,
+ 0x7e, 0xf4, 0xff, 0xe8, 0x7d, 0x6d, 0x00, 0x1c, 0x7f, 0xed, 0x00, 0x14, 0x7e, 0xf5, 0x00, 0x18,
+ 0x7f, 0x79, 0x00, 0x10, 0x7e, 0x70, 0xff, 0xe8, 0xce, 0xf4, 0xf0, 0x00, 0x7e, 0x71, 0x00, 0x08,
+ 0x7f, 0xfc, 0xff, 0xe8, 0x7c, 0xe4, 0xff, 0xe4, 0x7d, 0x68, 0xff, 0xe8, 0x7d, 0xed, 0x00, 0x0c,
+ 0xce, 0xf4, 0xe0, 0x00, 0xcc, 0xe4, 0xd0, 0x00, 0x7d, 0xec, 0xff, 0xe8, 0x7f, 0xfd, 0x00, 0x08,
+ 0xce, 0xf4, 0xd8, 0x00, 0xcf, 0xfc, 0xc8, 0x00, 0xfe, 0x8d, 0x85, 0xe8, 0xff, 0xa5, 0x57, 0x70,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xe0, 0xd8, 0x85, 0xae, 0x00, 0x2c, 0x4f, 0x05, 0xdf, 0xff,
+ 0x0f, 0xfd, 0x00, 0x04, 0xcf, 0x7c, 0xf5, 0x00, 0xff, 0x89, 0xe0, 0xd8, 0xc5, 0x28, 0xf4, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x1b, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x85, 0xae, 0x00, 0x2c, 0x45, 0x29, 0xff, 0xfb,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x1b, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x98, 0x86, 0x18, 0xfc, 0x1c, 0x46, 0xc0,
+ 0xfc, 0x82, 0x00, 0x80, 0x2e, 0xf4, 0x00, 0x01, 0xce, 0xe0, 0xec, 0x00, 0x4f, 0xf4, 0x00, 0x7f,
+ 0xcc, 0xe4, 0xfa, 0x00, 0x7f, 0x64, 0xff, 0xfd, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x7c, 0x00, 0x02,
+ 0xff, 0x02, 0x7c, 0xcc, 0xcf, 0xfc, 0xf0, 0x00, 0xfd, 0x7f, 0x58, 0x20, 0xfb, 0x8c, 0x7f, 0xd8,
+ 0xfe, 0x0c, 0x84, 0xa0, 0xff, 0x08, 0xe6, 0xd8, 0xfd, 0x82, 0x40, 0x00, 0x7b, 0x64, 0xff, 0xfe,
+ 0xfd, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0xce, 0x70, 0xe8, 0x00, 0x0d, 0x81, 0x00, 0xa1, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xb5, 0x00,
+ 0x4b, 0xdc, 0xff, 0x80, 0xff, 0xfb, 0x28, 0x0e, 0xfd, 0x7b, 0x28, 0x12, 0x9e, 0x7a, 0x00, 0x14,
+ 0x0d, 0xec, 0x00, 0x09, 0xfe, 0x08, 0xe0, 0xd8, 0xfe, 0xfb, 0x18, 0x0a, 0x8d, 0x7a, 0x00, 0x2c,
+ 0x9d, 0xfa, 0x00, 0x30, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x00, 0x10,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5f, 0xe5, 0x10, 0x00, 0xfd, 0x86, 0x1a, 0xf4, 0x9d, 0xfa, 0x00, 0x04,
+ 0xfd, 0x09, 0xe6, 0xd8, 0x9c, 0xfa, 0x00, 0x28, 0x9c, 0x7a, 0x00, 0x24, 0x9c, 0x02, 0xfe, 0x58,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0xf4, 0x00, 0x01, 0x4e, 0xf4, 0x0f, 0xff, 0xfe, 0xeb, 0x28, 0x00,
+ 0x9e, 0xea, 0x00, 0x08, 0x0e, 0x71, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x28, 0xfe, 0x09, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x8c, 0x4c, 0x28, 0x4e, 0x71, 0x20, 0x00,
+ 0xc5, 0x28, 0xe5, 0x00, 0xcf, 0xfc, 0xb0, 0x00, 0xff, 0x8d, 0x4c, 0x28, 0xfb, 0x9d, 0x46, 0xc0,
+ 0x45, 0x29, 0xff, 0xfd, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x1c, 0xa4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x98, 0x86, 0x18,
+ 0xfc, 0x1c, 0x46, 0xc0, 0xfc, 0x82, 0x00, 0x80, 0x2e, 0xf4, 0x00, 0x01, 0xce, 0xe0, 0xec, 0x00,
+ 0x4f, 0xf4, 0x00, 0x7f, 0xcc, 0xe4, 0xfa, 0x00, 0x7f, 0x64, 0xff, 0xfd, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x7c, 0x00, 0x02, 0xff, 0x02, 0x7c, 0xcc, 0xcf, 0xfc, 0xf0, 0x00, 0xfd, 0x7f, 0x58, 0x20,
+ 0xfb, 0x8c, 0x7f, 0xd8, 0xfe, 0x0c, 0x84, 0xa0, 0xfb, 0x1c, 0x46, 0x60, 0xff, 0x08, 0xe6, 0xd8,
+ 0xfd, 0x82, 0x60, 0x00, 0x7a, 0xe4, 0xff, 0xfe, 0xfd, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0xce, 0x70, 0xe8, 0x00, 0x0d, 0x81, 0x00, 0x61,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xad, 0x00, 0x4b, 0xdc, 0xff, 0x80, 0xff, 0xfb, 0x28, 0x0e,
+ 0xfd, 0x7b, 0x28, 0x12, 0x9b, 0x7a, 0x00, 0x14, 0x9e, 0x7a, 0x00, 0x18, 0x0d, 0xec, 0x00, 0x09,
+ 0xfe, 0x08, 0xe0, 0xd8, 0xfe, 0xfb, 0x18, 0x0a, 0x8d, 0x7a, 0x00, 0x2c, 0x9d, 0xfa, 0x00, 0x30,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x00, 0x14, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5f, 0xe5, 0x10, 0x00, 0xfd, 0x86, 0x1a, 0xf4, 0x9d, 0xfa, 0x00, 0x04, 0xfd, 0x09, 0xe6, 0xd8,
+ 0x9c, 0xfa, 0x00, 0x28, 0x9c, 0x7a, 0x00, 0x24, 0x9c, 0x02, 0xfe, 0x58, 0x9f, 0x82, 0xfe, 0x58,
+ 0x0e, 0xf4, 0x00, 0x01, 0x4e, 0xf4, 0x0f, 0xff, 0xfe, 0xeb, 0x28, 0x00, 0x9e, 0xea, 0x00, 0x08,
+ 0x0e, 0x71, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x28, 0xfe, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x8c, 0x4c, 0x28, 0x4e, 0x71, 0x20, 0x00, 0xc5, 0x28, 0xe5, 0x00,
+ 0xcf, 0xfc, 0xa8, 0x00, 0xff, 0x8d, 0x4c, 0x28, 0xfb, 0x9d, 0x46, 0xc0, 0x45, 0x29, 0xff, 0xfd,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x1d, 0xf0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x08, 0xb9, 0x40, 0xff, 0x8e, 0x4c, 0x20,
+ 0xfe, 0x8c, 0x85, 0x08, 0xcf, 0xfc, 0xd2, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8c, 0x85, 0x0c,
+ 0xff, 0x08, 0xa2, 0x80, 0xfe, 0x0c, 0x7f, 0xe0, 0xce, 0xf4, 0xfc, 0x00, 0x7f, 0xa8, 0xff, 0xf9,
+ 0xce, 0xf4, 0xfc, 0x00, 0x7f, 0x79, 0x00, 0x0c, 0x9d, 0x02, 0xfe, 0x68, 0x7f, 0x78, 0xff, 0xe1,
+ 0xff, 0x8e, 0x85, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x2f, 0x78, 0x00, 0x01, 0xce, 0x70, 0xe0, 0x00,
+ 0x9e, 0x02, 0xff, 0xb8, 0xce, 0xf6, 0xf4, 0x00, 0xe6, 0x01, 0x21, 0x15, 0xfb, 0x02, 0x00, 0x00,
+ 0xff, 0x8e, 0x85, 0xdf, 0xfe, 0xff, 0x68, 0x00, 0xff, 0x0e, 0x4b, 0xe0, 0x5e, 0x29, 0x00, 0x04,
+ 0xfb, 0x7b, 0x68, 0x3e, 0x70, 0x76, 0x00, 0x1f, 0x90, 0x82, 0xfe, 0x80, 0xfb, 0x0d, 0x85, 0x0c,
+ 0xea, 0x01, 0x1e, 0xc4, 0x45, 0x70, 0xfe, 0xff, 0x45, 0x70, 0xfe, 0x7f, 0xfe, 0x02, 0x00, 0x02,
+ 0xfe, 0x0d, 0x85, 0x08, 0xff, 0x98, 0x86, 0x18, 0xfc, 0x1c, 0x46, 0xc0, 0xfb, 0x8c, 0x7f, 0xd8,
+ 0x2f, 0xfc, 0x00, 0x01, 0xcd, 0xde, 0xc2, 0x00, 0xe6, 0x01, 0x1f, 0xad, 0xce, 0xe0, 0xfc, 0x00,
+ 0x7f, 0x6c, 0xff, 0xfd, 0x20, 0x7a, 0x00, 0x00, 0xfe, 0x0c, 0x84, 0xa0, 0xe6, 0x7c, 0x00, 0x02,
+ 0xff, 0x02, 0x7c, 0xcc, 0xcf, 0xfc, 0xf0, 0x00, 0xfd, 0x7f, 0x58, 0x20, 0xff, 0x08, 0xe6, 0xd8,
+ 0xce, 0x70, 0xe8, 0x00, 0xfe, 0x82, 0x40, 0x00, 0xfe, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7c, 0xec, 0xff, 0xfe, 0x0e, 0x81, 0x00, 0xa1,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xcd, 0x00, 0x0e, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x0e,
+ 0xfd, 0x7b, 0x28, 0x12, 0x9e, 0x7a, 0x00, 0x14, 0x9e, 0xfa, 0x00, 0x30, 0xfe, 0x7b, 0x18, 0x0a,
+ 0x8e, 0xfa, 0x00, 0x2c, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x00, 0x10,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5f, 0xed, 0x10, 0x00, 0xfd, 0x02, 0xa2, 0xec, 0x9d, 0x7a, 0x00, 0x04,
+ 0xfe, 0x89, 0xe6, 0xd8, 0x9d, 0xfa, 0x00, 0x28, 0x9c, 0x7a, 0x00, 0x24, 0x9c, 0x02, 0xfe, 0x58,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0x70, 0x00, 0x01, 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x77, 0x28, 0x00,
+ 0x9e, 0x76, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xfb, 0x7b, 0x28, 0x02,
+ 0xff, 0x8c, 0x4c, 0x28, 0xfb, 0x9d, 0x46, 0xc0, 0xcf, 0xfc, 0xc8, 0x00, 0xff, 0x8d, 0x4c, 0x28,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x08, 0xb9, 0x40, 0xfd, 0x88, 0xe6, 0xd8,
+ 0xff, 0x02, 0x00, 0x40, 0x0e, 0xe8, 0x00, 0x10, 0x9f, 0x6e, 0x00, 0x30, 0xff, 0x0e, 0x85, 0x90,
+ 0xff, 0xef, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x9f, 0x6e, 0x00, 0x24, 0x9e, 0xee, 0x00, 0x28,
+ 0xff, 0xfb, 0x28, 0x02, 0x9f, 0x02, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xfd, 0x06, 0x1b, 0x58, 0x9d, 0x6e, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0xf3, 0x28, 0x00, 0x9f, 0xf2, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28,
+ 0x9e, 0x02, 0xff, 0xb0, 0xf0, 0x6f, 0x28, 0x02, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xfc, 0x88, 0xbc, 0x70, 0xfd, 0x08, 0xe6, 0xd8, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x01, 0x20, 0x69,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x08, 0xa5, 0xb0, 0x20, 0x7a, 0x00, 0x00, 0xec, 0x01, 0x20, 0x9c,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xaa, 0xb4, 0x70, 0x7e, 0x00, 0x07, 0xea, 0x01, 0x20, 0x51,
+ 0xff, 0x8a, 0xb2, 0xa8, 0x70, 0x7a, 0x00, 0x01, 0xea, 0x01, 0x20, 0x9c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x7f, 0x58, 0x00, 0xfe, 0x82, 0xa2, 0xe4, 0xfe, 0x89, 0xe6, 0xf8, 0x2e, 0x80, 0x00, 0x80,
+ 0xcf, 0x78, 0xed, 0x00, 0xff, 0x7f, 0x68, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x20, 0x68, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x88, 0xbc, 0x74,
+ 0xff, 0x02, 0x00, 0x40, 0xfe, 0x8a, 0xbc, 0x7c, 0x9f, 0x6a, 0x00, 0x30, 0xff, 0x6b, 0x18, 0x0a,
+ 0x8e, 0x6a, 0x00, 0x2c, 0x9e, 0xea, 0x00, 0x24, 0x9c, 0xea, 0x00, 0x28, 0xff, 0x77, 0x28, 0x02,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xe5, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0xec,
+ 0x9f, 0xea, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0,
+ 0xf0, 0x6b, 0x28, 0x02, 0xff, 0x88, 0xa2, 0x80, 0x7d, 0xed, 0x00, 0x13, 0xff, 0x22, 0x00, 0x00,
+ 0xcd, 0xec, 0xf4, 0x00, 0x4f, 0xfd, 0xff, 0xf7, 0xcf, 0xfc, 0xdd, 0x00, 0xe0, 0x01, 0x20, 0x68,
+ 0xff, 0x89, 0xa2, 0x80, 0xfe, 0x8c, 0x4b, 0xf8, 0x55, 0x29, 0x00, 0x04, 0xfd, 0x88, 0xe6, 0xd8,
+ 0xfe, 0x8d, 0x80, 0x10, 0xff, 0x8e, 0x80, 0x00, 0xff, 0x02, 0x00, 0x40, 0x9f, 0x6e, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0xee, 0x00, 0x2c, 0xfd, 0x02, 0x00, 0x14, 0x9f, 0xee, 0x00, 0x24,
+ 0x9d, 0x6e, 0x00, 0x28, 0xff, 0x7f, 0x28, 0x02, 0x0e, 0x01, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x0e, 0x70, 0x00, 0x14, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x1b, 0x58, 0x9f, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x77, 0x28, 0x00,
+ 0x9f, 0x76, 0x00, 0x08, 0xfd, 0x02, 0x00, 0x28, 0x9d, 0x02, 0xff, 0xb0, 0xf0, 0x6f, 0x28, 0x02,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x21, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x08, 0xb9, 0x40, 0xff, 0x8e, 0x4c, 0x20,
+ 0xfe, 0x8c, 0x85, 0x08, 0xcf, 0xfc, 0xd2, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8c, 0x85, 0x0c,
+ 0xff, 0x08, 0xa2, 0x80, 0xfe, 0x0c, 0x7f, 0xe0, 0xce, 0xf4, 0xfc, 0x00, 0x7f, 0xa8, 0xff, 0xf9,
+ 0xce, 0xf4, 0xfc, 0x00, 0x7f, 0x79, 0x00, 0x0c, 0x9d, 0x02, 0xfe, 0x68, 0x7f, 0x78, 0xff, 0xe1,
+ 0xff, 0x8e, 0x85, 0xa4, 0x9f, 0x82, 0xfe, 0x68, 0x2f, 0x78, 0x00, 0x01, 0xce, 0x70, 0xe0, 0x00,
+ 0x9e, 0x02, 0xff, 0xb8, 0xce, 0xf6, 0xf4, 0x00, 0xe6, 0x01, 0x24, 0xa9, 0xfb, 0x02, 0x00, 0x00,
+ 0xff, 0x82, 0x00, 0x01, 0xc0, 0x76, 0xfc, 0x00, 0xff, 0x0e, 0x85, 0xe3, 0xfe, 0xfb, 0x68, 0x00,
+ 0xff, 0x8e, 0x4b, 0xe0, 0x5e, 0x29, 0x00, 0x04, 0xfb, 0x7f, 0x68, 0x3e, 0x90, 0x82, 0xfe, 0x80,
+ 0xfb, 0x0d, 0x85, 0x0c, 0xe6, 0x01, 0x22, 0x59, 0x45, 0x70, 0xfe, 0xff, 0x45, 0x70, 0xfe, 0x7f,
+ 0xfe, 0x02, 0x00, 0x02, 0xfe, 0x0d, 0x85, 0x08, 0xff, 0x98, 0x86, 0x18, 0xfc, 0x1c, 0x46, 0xc0,
+ 0xfb, 0x8c, 0x7f, 0xd8, 0x2f, 0xfc, 0x00, 0x01, 0xcd, 0xde, 0xc2, 0x00, 0xe6, 0x01, 0x23, 0x41,
+ 0xce, 0xe0, 0xfc, 0x00, 0x7f, 0x6c, 0xff, 0xfd, 0x20, 0x7a, 0x00, 0x00, 0xfe, 0x0c, 0x84, 0xa0,
+ 0xe6, 0x7c, 0x00, 0x02, 0xff, 0x02, 0x7c, 0xcc, 0xcf, 0xfc, 0xf0, 0x00, 0xfd, 0x7f, 0x58, 0x20,
+ 0xff, 0x08, 0xe6, 0xd8, 0xce, 0x70, 0xe8, 0x00, 0xfe, 0x82, 0x40, 0x00, 0xfe, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7c, 0xec, 0xff, 0xfe,
+ 0x0e, 0x81, 0x00, 0xa1, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xcd, 0x00, 0x0e, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x0e, 0xfd, 0x7b, 0x28, 0x12, 0x9e, 0x7a, 0x00, 0x14, 0x9e, 0xfa, 0x00, 0x30,
+ 0xfe, 0x7b, 0x18, 0x0a, 0x8e, 0xfa, 0x00, 0x2c, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x5f, 0xed, 0x10, 0x00, 0xfd, 0x02, 0xa2, 0xec,
+ 0x9d, 0x7a, 0x00, 0x04, 0xfe, 0x89, 0xe6, 0xd8, 0x9d, 0xfa, 0x00, 0x28, 0x9c, 0x7a, 0x00, 0x24,
+ 0x9c, 0x02, 0xfe, 0x58, 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0x70, 0x00, 0x01, 0x4e, 0x70, 0x0f, 0xff,
+ 0xfe, 0x77, 0x28, 0x00, 0x9e, 0x76, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0,
+ 0xfb, 0x7b, 0x28, 0x02, 0xff, 0x8c, 0x4c, 0x28, 0xfb, 0x9d, 0x46, 0xc0, 0xcf, 0xfc, 0xc8, 0x00,
+ 0xff, 0x8d, 0x4c, 0x28, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x08, 0xb9, 0x40,
+ 0xfd, 0x88, 0xe6, 0xd8, 0xff, 0x82, 0x00, 0x40, 0x0f, 0x68, 0x00, 0x14, 0x9f, 0xee, 0x00, 0x30,
+ 0xfe, 0x8e, 0x85, 0x90, 0xff, 0xef, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x9e, 0xee, 0x00, 0x24,
+ 0x9f, 0x6e, 0x00, 0x28, 0xff, 0xf7, 0x28, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0x79, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0xfd, 0x06, 0x1b, 0x58, 0x9d, 0x6e, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01,
+ 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0xf3, 0x28, 0x00, 0x9f, 0xf2, 0x00, 0x08,
+ 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xf0, 0x6f, 0x28, 0x02, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0x88, 0xbc, 0x70, 0xfd, 0x08, 0xe6, 0xd8, 0x20, 0x66, 0x00, 0x00,
+ 0xe6, 0x01, 0x23, 0xfd, 0x00, 0x00, 0x00, 0x01, 0xff, 0x08, 0xa5, 0xb0, 0x20, 0x7a, 0x00, 0x00,
+ 0xec, 0x01, 0x24, 0x30, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xaa, 0xb4, 0x70, 0x7e, 0x00, 0x07,
+ 0xea, 0x01, 0x23, 0xe5, 0xff, 0x8a, 0xb2, 0xa8, 0x70, 0x7a, 0x00, 0x01, 0xea, 0x01, 0x24, 0x30,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x7f, 0x58, 0x00, 0xfe, 0x82, 0xa2, 0xe4, 0xfe, 0x89, 0xe6, 0xf8,
+ 0x2e, 0x80, 0x00, 0x80, 0xcf, 0x78, 0xed, 0x00, 0xff, 0x7f, 0x68, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x23, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x88, 0xbc, 0x74, 0xff, 0x02, 0x00, 0x40, 0xfe, 0x8a, 0xbc, 0x7c, 0x9f, 0x6a, 0x00, 0x30,
+ 0xff, 0x6b, 0x18, 0x0a, 0x8e, 0x6a, 0x00, 0x2c, 0x9e, 0xea, 0x00, 0x24, 0x9c, 0xea, 0x00, 0x28,
+ 0xff, 0x77, 0x28, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xe5, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0xa2, 0xec, 0x9f, 0xea, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28,
+ 0x9e, 0x02, 0xff, 0xb0, 0xf0, 0x6b, 0x28, 0x02, 0xff, 0x88, 0xa2, 0x80, 0x7d, 0xed, 0x00, 0x13,
+ 0xff, 0x22, 0x00, 0x00, 0xcd, 0xec, 0xf4, 0x00, 0x4f, 0xfd, 0xff, 0xf7, 0xcf, 0xfc, 0xdd, 0x00,
+ 0xe0, 0x01, 0x23, 0xfc, 0xff, 0x89, 0xa2, 0x80, 0xfe, 0x8c, 0x4b, 0xf8, 0x55, 0x29, 0x00, 0x04,
+ 0xfd, 0x88, 0xe6, 0xd8, 0xfe, 0x8d, 0x80, 0x14, 0xff, 0x8e, 0x80, 0x00, 0xff, 0x02, 0x00, 0x40,
+ 0x9f, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0xee, 0x00, 0x2c, 0xfd, 0x02, 0x00, 0x18,
+ 0x9f, 0xee, 0x00, 0x24, 0x9d, 0x6e, 0x00, 0x28, 0xff, 0x7f, 0x28, 0x02, 0x0e, 0x01, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0x70, 0x00, 0x18, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x1b, 0x58,
+ 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x77, 0x28, 0x00, 0x9f, 0x76, 0x00, 0x08, 0xfd, 0x02, 0x00, 0x28, 0x9d, 0x02, 0xff, 0xb0,
+ 0xf0, 0x6f, 0x28, 0x02, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x25, 0x14, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x08, 0xb9, 0x40,
+ 0xff, 0x8e, 0x4c, 0x20, 0xfe, 0x8c, 0x85, 0x08, 0xcf, 0xfc, 0xd2, 0x00, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8c, 0x85, 0x0c, 0xff, 0x08, 0xa2, 0x80, 0xfe, 0x0c, 0x7f, 0xe0, 0xce, 0xf4, 0xfc, 0x00,
+ 0x7f, 0xa8, 0xff, 0xf9, 0xce, 0xf4, 0xfc, 0x00, 0x7f, 0x79, 0x00, 0x0c, 0x9d, 0x02, 0xfe, 0x68,
+ 0x7f, 0x78, 0xff, 0xe1, 0xff, 0x8e, 0x85, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x2f, 0x78, 0x00, 0x01,
+ 0xce, 0x70, 0xe0, 0x00, 0x9e, 0x02, 0xff, 0xb8, 0xce, 0xf6, 0xf4, 0x00, 0xe6, 0x01, 0x28, 0x41,
+ 0xfa, 0x82, 0x00, 0x00, 0xff, 0x8e, 0x85, 0xdf, 0xfe, 0xff, 0x68, 0x00, 0xff, 0x0e, 0x4b, 0xe0,
+ 0x5e, 0x29, 0x00, 0x04, 0xfa, 0xfb, 0x68, 0x3e, 0x70, 0x76, 0x00, 0x1f, 0x90, 0x82, 0xfe, 0x80,
+ 0xfa, 0x8d, 0x85, 0x0c, 0xea, 0x01, 0x25, 0xe8, 0x45, 0x70, 0xfe, 0xff, 0x45, 0x70, 0xfe, 0x7f,
+ 0xfe, 0x02, 0x00, 0x02, 0xfe, 0x0d, 0x85, 0x08, 0xff, 0x98, 0x86, 0x18, 0xfb, 0x9c, 0x46, 0xc0,
+ 0xfb, 0x0c, 0x7f, 0xd8, 0x2f, 0xfc, 0x00, 0x01, 0xcd, 0xda, 0xba, 0x00, 0xe6, 0x01, 0x26, 0xd9,
+ 0xce, 0x5c, 0xfc, 0x00, 0x7f, 0x6c, 0xff, 0xfd, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x7c, 0x00, 0x02,
+ 0xff, 0x02, 0x7c, 0xcc, 0xcf, 0xfc, 0xf0, 0x00, 0xfd, 0x7f, 0x58, 0x20, 0xfe, 0x8c, 0x84, 0xa0,
+ 0xfc, 0x9c, 0x46, 0x60, 0xff, 0x08, 0xe6, 0xd8, 0xff, 0x82, 0x60, 0x00, 0xce, 0xf4, 0xe0, 0x00,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0xfb, 0x28, 0x0c, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7c, 0x6c, 0xff, 0xfe, 0x0e, 0x01, 0x00, 0x61, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xc5, 0x00,
+ 0x0e, 0x70, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x0e, 0xfd, 0x7b, 0x28, 0x12, 0x9c, 0xfa, 0x00, 0x14,
+ 0x9e, 0xfa, 0x00, 0x18, 0x9e, 0x7a, 0x00, 0x30, 0xfe, 0xfb, 0x18, 0x0a, 0x8e, 0x7a, 0x00, 0x2c,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0xfd, 0x02, 0x00, 0x14, 0x9d, 0x02, 0xfe, 0x58,
+ 0x5f, 0xed, 0x10, 0x00, 0xfd, 0x02, 0xa2, 0xec, 0x9d, 0x7a, 0x00, 0x04, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x9d, 0xfa, 0x00, 0x28, 0x9b, 0xfa, 0x00, 0x24, 0x9b, 0x82, 0xfe, 0x58, 0x9f, 0x82, 0xfe, 0x58,
+ 0x0e, 0xf4, 0x00, 0x01, 0x4e, 0xf4, 0x0f, 0xff, 0xfe, 0xf3, 0x28, 0x00, 0x9e, 0xf2, 0x00, 0x08,
+ 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xfa, 0xfb, 0x28, 0x02, 0xff, 0x8c, 0x4c, 0x28,
+ 0xfb, 0x1d, 0x46, 0xc0, 0xcf, 0xfc, 0xc0, 0x00, 0xff, 0x8d, 0x4c, 0x28, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x08, 0xb9, 0x40, 0xfd, 0x88, 0xe6, 0xd8, 0xff, 0x02, 0x00, 0x40,
+ 0x0e, 0xe8, 0x00, 0x10, 0x9f, 0x6e, 0x00, 0x30, 0xff, 0x0e, 0x85, 0x90, 0xff, 0xef, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x9f, 0x6e, 0x00, 0x24, 0x9e, 0xee, 0x00, 0x28, 0xff, 0xfb, 0x28, 0x02,
+ 0x9f, 0x02, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xfd, 0x06, 0x1b, 0x58,
+ 0x9d, 0x6e, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0xf3, 0x28, 0x00, 0x9f, 0xf2, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0,
+ 0xf0, 0x6f, 0x28, 0x02, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x88, 0xbc, 0x70,
+ 0xfd, 0x08, 0xe6, 0xd8, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x01, 0x27, 0x95, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x08, 0xa5, 0xb0, 0x20, 0x7a, 0x00, 0x00, 0xec, 0x01, 0x27, 0xc8, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xaa, 0xb4, 0x70, 0x7e, 0x00, 0x07, 0xea, 0x01, 0x27, 0x7d, 0xff, 0x8a, 0xb2, 0xa8,
+ 0x70, 0x7a, 0x00, 0x01, 0xea, 0x01, 0x27, 0xc8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x7f, 0x58, 0x00,
+ 0xfe, 0x82, 0xa2, 0xe4, 0xfe, 0x89, 0xe6, 0xf8, 0x2e, 0x80, 0x00, 0x80, 0xcf, 0x78, 0xed, 0x00,
+ 0xff, 0x7f, 0x68, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x27, 0x94, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x88, 0xbc, 0x74, 0xff, 0x02, 0x00, 0x40,
+ 0xfe, 0x8a, 0xbc, 0x7c, 0x9f, 0x6a, 0x00, 0x30, 0xff, 0x6b, 0x18, 0x0a, 0x8e, 0x6a, 0x00, 0x2c,
+ 0x9e, 0xea, 0x00, 0x24, 0x9c, 0xea, 0x00, 0x28, 0xff, 0x77, 0x28, 0x02, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0xe5, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0xec, 0x9f, 0xea, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xf0, 0x6b, 0x28, 0x02,
+ 0xff, 0x88, 0xa2, 0x80, 0x7d, 0xed, 0x00, 0x13, 0xff, 0x22, 0x00, 0x00, 0xcd, 0xec, 0xf4, 0x00,
+ 0x4f, 0xfd, 0xff, 0xf7, 0xcf, 0xfc, 0xdd, 0x00, 0xe0, 0x01, 0x27, 0x94, 0xff, 0x89, 0xa2, 0x80,
+ 0xfe, 0x8c, 0x4b, 0xf8, 0x55, 0x29, 0x00, 0x04, 0xfd, 0x88, 0xe6, 0xd8, 0xfe, 0x8d, 0x80, 0x10,
+ 0xff, 0x8e, 0x80, 0x00, 0xff, 0x02, 0x00, 0x40, 0x9f, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0xee, 0x00, 0x2c, 0xfd, 0x02, 0x00, 0x14, 0x9f, 0xee, 0x00, 0x24, 0x9d, 0x6e, 0x00, 0x28,
+ 0xff, 0x7f, 0x28, 0x02, 0x0e, 0x01, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0x70, 0x00, 0x14,
+ 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x1b, 0x58, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x77, 0x28, 0x00, 0x9f, 0x76, 0x00, 0x08,
+ 0xfd, 0x02, 0x00, 0x28, 0x9d, 0x02, 0xff, 0xb0, 0xf0, 0x6f, 0x28, 0x02, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x28, 0xac, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0x08, 0xb9, 0x40, 0xff, 0x8e, 0x4c, 0x20, 0xfe, 0x8c, 0x85, 0x08,
+ 0xcf, 0xfc, 0xd2, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8c, 0x85, 0x0c, 0xff, 0x08, 0xa2, 0x80,
+ 0xfe, 0x0c, 0x7f, 0xe0, 0xce, 0xf4, 0xfc, 0x00, 0x7f, 0xa8, 0xff, 0xf9, 0xce, 0xf4, 0xfc, 0x00,
+ 0x7f, 0x79, 0x00, 0x0c, 0x9d, 0x02, 0xfe, 0x68, 0x7f, 0x78, 0xff, 0xe1, 0xff, 0x8e, 0x85, 0xa4,
+ 0x9f, 0x82, 0xfe, 0x68, 0x2f, 0x78, 0x00, 0x01, 0xce, 0x70, 0xe0, 0x00, 0x9e, 0x02, 0xff, 0xb8,
+ 0xce, 0xf6, 0xf4, 0x00, 0xe6, 0x01, 0x2b, 0xdd, 0xfa, 0x82, 0x00, 0x00, 0xff, 0x82, 0x00, 0x01,
+ 0xc0, 0x76, 0xfc, 0x00, 0xff, 0x0e, 0x85, 0xe3, 0xfe, 0xfb, 0x68, 0x00, 0xff, 0x8e, 0x4b, 0xe0,
+ 0x5e, 0x29, 0x00, 0x04, 0xfa, 0xff, 0x68, 0x3e, 0x90, 0x82, 0xfe, 0x80, 0xfa, 0x8d, 0x85, 0x0c,
+ 0xe6, 0x01, 0x29, 0x85, 0x45, 0x70, 0xfe, 0xff, 0x45, 0x70, 0xfe, 0x7f, 0xfe, 0x02, 0x00, 0x02,
+ 0xfe, 0x0d, 0x85, 0x08, 0xff, 0x98, 0x86, 0x18, 0xfb, 0x9c, 0x46, 0xc0, 0xfb, 0x0c, 0x7f, 0xd8,
+ 0x2f, 0xfc, 0x00, 0x01, 0xcd, 0xda, 0xba, 0x00, 0xe6, 0x01, 0x2a, 0x75, 0xce, 0x5c, 0xfc, 0x00,
+ 0x7f, 0x6c, 0xff, 0xfd, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x7c, 0x00, 0x02, 0xff, 0x02, 0x7c, 0xcc,
+ 0xcf, 0xfc, 0xf0, 0x00, 0xfd, 0x7f, 0x58, 0x20, 0xfe, 0x8c, 0x84, 0xa0, 0xfc, 0x9c, 0x46, 0x60,
+ 0xff, 0x08, 0xe6, 0xd8, 0xff, 0x82, 0x60, 0x00, 0xce, 0xf4, 0xe0, 0x00, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0xfb, 0x28, 0x0c, 0xff, 0x88, 0xb2, 0xe4, 0x7c, 0x6c, 0xff, 0xfe,
+ 0x0e, 0x01, 0x00, 0x61, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xc5, 0x00, 0x0e, 0x70, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x0e, 0xfd, 0x7b, 0x28, 0x12, 0x9c, 0xfa, 0x00, 0x14, 0x9e, 0xfa, 0x00, 0x18,
+ 0x9e, 0x7a, 0x00, 0x30, 0xfe, 0xfb, 0x18, 0x0a, 0x8e, 0x7a, 0x00, 0x2c, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfd, 0x02, 0x00, 0x14, 0x9d, 0x02, 0xfe, 0x58, 0x5f, 0xed, 0x10, 0x00,
+ 0xfd, 0x02, 0xa2, 0xec, 0x9d, 0x7a, 0x00, 0x04, 0xfe, 0x09, 0xe6, 0xd8, 0x9d, 0xfa, 0x00, 0x28,
+ 0x9b, 0xfa, 0x00, 0x24, 0x9b, 0x82, 0xfe, 0x58, 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0xf4, 0x00, 0x01,
+ 0x4e, 0xf4, 0x0f, 0xff, 0xfe, 0xf3, 0x28, 0x00, 0x9e, 0xf2, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28,
+ 0x9e, 0x02, 0xff, 0xb0, 0xfa, 0xfb, 0x28, 0x02, 0xff, 0x8c, 0x4c, 0x28, 0xfb, 0x1d, 0x46, 0xc0,
+ 0xcf, 0xfc, 0xc0, 0x00, 0xff, 0x8d, 0x4c, 0x28, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x08, 0xb9, 0x40, 0xfd, 0x88, 0xe6, 0xd8, 0xff, 0x82, 0x00, 0x40, 0x0f, 0x68, 0x00, 0x14,
+ 0x9f, 0xee, 0x00, 0x30, 0xfe, 0x8e, 0x85, 0x90, 0xff, 0xef, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x9e, 0xee, 0x00, 0x24, 0x9f, 0x6e, 0x00, 0x28, 0xff, 0xf7, 0x28, 0x02, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0x79, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xfd, 0x06, 0x1b, 0x58, 0x9d, 0x6e, 0x00, 0x04,
+ 0x0f, 0xfc, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0xf3, 0x28, 0x00,
+ 0x9f, 0xf2, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xf0, 0x6f, 0x28, 0x02,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x88, 0xbc, 0x70, 0xfd, 0x08, 0xe6, 0xd8,
+ 0x20, 0x66, 0x00, 0x00, 0xe6, 0x01, 0x2b, 0x31, 0x00, 0x00, 0x00, 0x01, 0xff, 0x08, 0xa5, 0xb0,
+ 0x20, 0x7a, 0x00, 0x00, 0xec, 0x01, 0x2b, 0x64, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xaa, 0xb4,
+ 0x70, 0x7e, 0x00, 0x07, 0xea, 0x01, 0x2b, 0x19, 0xff, 0x8a, 0xb2, 0xa8, 0x70, 0x7a, 0x00, 0x01,
+ 0xea, 0x01, 0x2b, 0x64, 0x00, 0x00, 0x00, 0x01, 0xff, 0x7f, 0x58, 0x00, 0xfe, 0x82, 0xa2, 0xe4,
+ 0xfe, 0x89, 0xe6, 0xf8, 0x2e, 0x80, 0x00, 0x80, 0xcf, 0x78, 0xed, 0x00, 0xff, 0x7f, 0x68, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x2b, 0x30,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x88, 0xbc, 0x74, 0xff, 0x02, 0x00, 0x40, 0xfe, 0x8a, 0xbc, 0x7c,
+ 0x9f, 0x6a, 0x00, 0x30, 0xff, 0x6b, 0x18, 0x0a, 0x8e, 0x6a, 0x00, 0x2c, 0x9e, 0xea, 0x00, 0x24,
+ 0x9c, 0xea, 0x00, 0x28, 0xff, 0x77, 0x28, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xe5, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0xec, 0x9f, 0xea, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xf0, 0x6b, 0x28, 0x02, 0xff, 0x88, 0xa2, 0x80,
+ 0x7d, 0xed, 0x00, 0x13, 0xff, 0x22, 0x00, 0x00, 0xcd, 0xec, 0xf4, 0x00, 0x4f, 0xfd, 0xff, 0xf7,
+ 0xcf, 0xfc, 0xdd, 0x00, 0xe0, 0x01, 0x2b, 0x30, 0xff, 0x89, 0xa2, 0x80, 0xfe, 0x8c, 0x4b, 0xf8,
+ 0x55, 0x29, 0x00, 0x04, 0xfd, 0x88, 0xe6, 0xd8, 0xfe, 0x8d, 0x80, 0x14, 0xff, 0x8e, 0x80, 0x00,
+ 0xff, 0x02, 0x00, 0x40, 0x9f, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0xee, 0x00, 0x2c,
+ 0xfd, 0x02, 0x00, 0x18, 0x9f, 0xee, 0x00, 0x24, 0x9d, 0x6e, 0x00, 0x28, 0xff, 0x7f, 0x28, 0x02,
+ 0x0e, 0x01, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0x70, 0x00, 0x18, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x1b, 0x58, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x89, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x77, 0x28, 0x00, 0x9f, 0x76, 0x00, 0x08, 0xfd, 0x02, 0x00, 0x28,
+ 0x9d, 0x02, 0xff, 0xb0, 0xf0, 0x6f, 0x28, 0x02, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x2c, 0x48, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x20, 0x1e, 0x00, 0x80, 0xe2, 0x01, 0x2c, 0xa1, 0xcf, 0x9c, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x80,
+ 0xcf, 0xfc, 0x3a, 0x00, 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x01, 0x2c, 0xc9, 0xcf, 0x18, 0x38, 0x00,
+ 0xfe, 0x8a, 0xb9, 0xb8, 0x9e, 0x82, 0xfe, 0x68, 0x93, 0x82, 0xfe, 0x68, 0x93, 0x02, 0xfe, 0x68,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x2c, 0xe9,
+ 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68, 0x9f, 0x02, 0xfe, 0x68,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xb9, 0x4c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x2d, 0x24, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x50,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x2d, 0x24, 0xff, 0x82, 0x00, 0x01, 0xe0, 0x01, 0x2d, 0x28,
+ 0xff, 0x89, 0xb9, 0x48, 0xf0, 0x09, 0xb9, 0x48, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0x0e, 0x81, 0xff, 0xff, 0x9e, 0x96, 0xff, 0xf4, 0xf3, 0x1e, 0x56, 0xf0, 0xf3, 0x8a, 0x00, 0x00,
+ 0x90, 0x96, 0xff, 0xf0, 0xf7, 0x86, 0x2d, 0x60, 0xe0, 0x01, 0x2c, 0x88, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x0a, 0xfb, 0xb0, 0xf3, 0x82, 0x50, 0x00, 0xf7, 0x86, 0x2d, 0x74, 0xe0, 0x01, 0x2c, 0x88,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x02, 0x00, 0x00, 0xfe, 0x82, 0x03, 0xff, 0xfe, 0x0a, 0xfb, 0xb0,
+ 0xff, 0x8e, 0x4b, 0x9c, 0x9f, 0x7e, 0x00, 0x08, 0xcf, 0x7c, 0x00, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xea, 0x01, 0x2d, 0x84, 0x2f, 0xfc, 0x00, 0x14, 0x8e, 0x96, 0xff, 0xf4, 0x8f, 0x96, 0xff, 0xf0,
+ 0xff, 0x17, 0x1b, 0xf4, 0x9e, 0xf2, 0x00, 0x04, 0xce, 0x84, 0x00, 0x00, 0x9e, 0x82, 0xfe, 0x88,
+ 0x9f, 0x82, 0xfe, 0xa0, 0x8e, 0xf2, 0x00, 0x08, 0xff, 0x03, 0x2a, 0x98, 0xff, 0x02, 0x04, 0x00,
+ 0xfe, 0x9d, 0x46, 0xc8, 0xff, 0x0d, 0x85, 0x10, 0x9f, 0xf2, 0x00, 0x00, 0x90, 0x72, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xfe, 0x1d, 0x46, 0x68,
+ 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x56, 0xf0, 0xbe, 0x7e, 0xf0, 0x02,
+ 0xff, 0x82, 0x03, 0xff, 0x9e, 0x72, 0x00, 0x10, 0x9e, 0x72, 0x00, 0x0c, 0xff, 0x8d, 0x85, 0x10,
+ 0xf7, 0x86, 0x2e, 0x0c, 0xe0, 0x01, 0x2c, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x08, 0x8f, 0x9a, 0x00, 0x00, 0xff, 0x1b, 0x18, 0x04, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x82, 0xfe, 0xa0, 0xff, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x02, 0xfe, 0x88,
+ 0xfd, 0x1b, 0x18, 0x04, 0xff, 0x82, 0x7f, 0xff, 0xcf, 0x78, 0xfc, 0x00, 0x0f, 0x81, 0xff, 0xff,
+ 0x9f, 0x96, 0xff, 0xf4, 0x7f, 0x79, 0x00, 0x02, 0xfe, 0x9e, 0x56, 0xf0, 0x83, 0x1a, 0x00, 0x00,
+ 0xae, 0x7a, 0xe8, 0x02, 0xcf, 0x84, 0x00, 0x00, 0xfd, 0x97, 0x1b, 0xf4, 0xc0, 0x7e, 0x32, 0x00,
+ 0x9f, 0x96, 0xff, 0xf0, 0xcf, 0x78, 0xe8, 0x00, 0xe6, 0x01, 0x2f, 0x09, 0x4f, 0xe9, 0x00, 0x00,
+ 0x20, 0x72, 0x00, 0x00, 0xe6, 0x01, 0x2f, 0x15, 0xf4, 0x02, 0x00, 0x01, 0x4d, 0xe9, 0x00, 0x00,
+ 0x8f, 0xf2, 0x00, 0x00, 0xfe, 0xf3, 0x18, 0x04, 0xc0, 0x7e, 0x32, 0x00, 0xe6, 0x01, 0x2e, 0xc1,
+ 0xc0, 0x76, 0xda, 0x00, 0x0f, 0x70, 0x00, 0x08, 0x8e, 0x72, 0x00, 0x08, 0x20, 0x72, 0x00, 0x00,
+ 0xe6, 0x01, 0x2e, 0x90, 0xf4, 0x02, 0x00, 0x01, 0xe0, 0x01, 0x2f, 0x14, 0x00, 0x00, 0x00, 0x01,
+ 0xe6, 0x01, 0x2e, 0xa4, 0xf4, 0x02, 0x00, 0x00, 0x8f, 0xf2, 0x00, 0x08, 0x9f, 0xfa, 0x00, 0x00,
+ 0xff, 0x9c, 0x46, 0xc8, 0x9f, 0xf2, 0x00, 0x08, 0xff, 0x8c, 0x85, 0x10, 0xfe, 0x1d, 0x46, 0xc8,
+ 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x85, 0x10, 0x8f, 0x72, 0x00, 0x10, 0x8f, 0xf2, 0x00, 0x0c,
+ 0x9f, 0xfa, 0x00, 0x0c, 0x8f, 0xf2, 0x00, 0x0c, 0x9f, 0x7e, 0x00, 0x10, 0x94, 0x72, 0x00, 0x10,
+ 0xe0, 0x01, 0x2f, 0x14, 0x94, 0x72, 0x00, 0x0c, 0xc0, 0x6e, 0xfa, 0x00, 0xe6, 0x01, 0x2e, 0x80,
+ 0xf4, 0x02, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xff, 0x0c, 0x85, 0x10,
+ 0xff, 0x82, 0x04, 0x00, 0xcf, 0xfc, 0xf2, 0x00, 0x20, 0x7e, 0x01, 0xd1, 0xe2, 0x01, 0x2f, 0xb4,
+ 0x0f, 0x01, 0xff, 0xff, 0xff, 0x9c, 0x46, 0x68, 0x83, 0x7e, 0x00, 0x0c, 0x90, 0xfe, 0x00, 0x00,
+ 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x2f, 0x8d, 0x9f, 0x7e, 0x00, 0x04, 0x9f, 0x96, 0xff, 0xf4,
+ 0xf7, 0x86, 0x2f, 0x6c, 0xe0, 0x01, 0x2e, 0x18, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x01, 0x2f, 0xc4, 0xf4, 0x02, 0x00, 0x01, 0x83, 0x7e, 0x00, 0x0c,
+ 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x2f, 0x5c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x85, 0x10,
+ 0x20, 0x7e, 0x03, 0xff, 0xe6, 0x01, 0x2f, 0xad, 0x03, 0x01, 0xe1, 0x00, 0x03, 0x18, 0x07, 0x7d,
+ 0xf7, 0x86, 0x2f, 0xac, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x2f, 0xc4,
+ 0xf4, 0x02, 0x00, 0x00, 0xf7, 0x86, 0x2f, 0xc0, 0xe0, 0x01, 0x2d, 0x34, 0x97, 0x93, 0xff, 0xfc,
+ 0xf4, 0x02, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0x8f, 0x9a, 0x00, 0x00,
+ 0xff, 0x1b, 0x18, 0x04, 0xcd, 0x18, 0x00, 0x00, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x82, 0xfe, 0xa0,
+ 0xff, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff,
+ 0xfe, 0x1e, 0x56, 0xf0, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0x9f, 0x96, 0xff, 0xf4,
+ 0xaf, 0x7e, 0xe0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x30, 0x4d, 0x00, 0x00, 0x00, 0x01,
+ 0x8e, 0x1a, 0x00, 0x00, 0xfd, 0x9b, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04,
+ 0xc0, 0x7e, 0xe2, 0x00, 0xe6, 0x01, 0x31, 0x05, 0xc0, 0x76, 0xda, 0x00, 0x8f, 0x7a, 0x00, 0x08,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x30, 0x28, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x85, 0x10,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x31, 0x15, 0xf4, 0x02, 0x00, 0x01, 0xfe, 0x9c, 0x46, 0xc8,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x01, 0x30, 0xd9, 0x03, 0x01, 0xe1, 0x00, 0x8f, 0xf6, 0x00, 0x08,
+ 0x8e, 0x16, 0xff, 0xf4, 0xc4, 0x78, 0x00, 0x00, 0xff, 0x9d, 0x46, 0xc8, 0xff, 0x9e, 0x56, 0xf0,
+ 0xae, 0x72, 0xf8, 0x02, 0x9e, 0x76, 0x00, 0x08, 0x8e, 0x16, 0xff, 0xf4, 0xbe, 0xf2, 0xf8, 0x02,
+ 0x8f, 0xea, 0x00, 0x00, 0x9f, 0xf6, 0x00, 0x00, 0x8d, 0x6a, 0x00, 0x04, 0x9d, 0x76, 0x00, 0x04,
+ 0xff, 0x8c, 0x85, 0x10, 0xff, 0x1c, 0x46, 0x68, 0x2f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x85, 0x10,
+ 0x8f, 0x7a, 0x00, 0x0c, 0x9f, 0x76, 0x00, 0x0c, 0xff, 0x9c, 0x46, 0x68, 0x8f, 0x7e, 0x00, 0x0c,
+ 0x9e, 0xfa, 0x00, 0x10, 0xff, 0x9c, 0x46, 0x68, 0x9e, 0xfe, 0x00, 0x0c, 0xfe, 0x1c, 0x46, 0x68,
+ 0xe0, 0x01, 0x31, 0x14, 0x9e, 0x76, 0x00, 0x10, 0x9d, 0x16, 0xff, 0xf0, 0x9f, 0x16, 0xff, 0xec,
+ 0x03, 0x18, 0x07, 0x91, 0xf7, 0x86, 0x30, 0xf0, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc,
+ 0xfe, 0x9c, 0x46, 0xc8, 0x8f, 0x16, 0xff, 0xec, 0x8d, 0x16, 0xff, 0xf0, 0xe0, 0x01, 0x30, 0x6c,
+ 0x00, 0x00, 0x00, 0x01, 0xe6, 0x01, 0x30, 0x3c, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x30, 0x4d,
+ 0xf4, 0x02, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x8d, 0xae, 0x00, 0x1c, 0x8d, 0x2e, 0x00, 0x38,
+ 0xfe, 0x08, 0xe0, 0xd8, 0xff, 0x03, 0x1b, 0xa0, 0x85, 0xae, 0x00, 0x2c, 0x4e, 0xec, 0x00, 0x00,
+ 0xce, 0x70, 0xe8, 0x00, 0x4f, 0x85, 0xdf, 0xff, 0xcf, 0xf0, 0xfd, 0x00, 0xfe, 0x09, 0xe0, 0xd8,
+ 0xce, 0xa8, 0xfc, 0x00, 0xfd, 0x83, 0x2a, 0x12, 0x4f, 0x79, 0x00, 0x00, 0xfe, 0x0c, 0x7f, 0xd8,
+ 0x7f, 0xf8, 0x00, 0x10, 0xcf, 0x7e, 0xf0, 0x00, 0x7f, 0x78, 0xff, 0xf0, 0xcf, 0x00, 0xf1, 0x00,
+ 0xfd, 0x73, 0x28, 0x02, 0xff, 0x73, 0x28, 0x00, 0x0e, 0x70, 0x00, 0x04, 0x7f, 0xf1, 0x00, 0x19,
+ 0x20, 0x7e, 0x00, 0x00, 0xfe, 0x0d, 0x7f, 0xd8, 0xe6, 0x01, 0x31, 0xc5, 0x55, 0x74, 0x00, 0x80,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x31, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x98, 0x86, 0x18, 0x55, 0x29, 0x00, 0x02, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0xf0, 0xfc, 0x00, 0xff, 0x8d, 0x7f, 0xd8, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x31, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8d, 0xae, 0x00, 0x1c, 0xfe, 0x88, 0xe0, 0xd8, 0xfe, 0x03, 0x1b, 0xa0, 0x85, 0xae, 0x00, 0x2c,
+ 0x4f, 0xec, 0x00, 0x00, 0xce, 0xf4, 0xf8, 0x00, 0x4f, 0x05, 0xdf, 0xff, 0x4e, 0x71, 0x00, 0x00,
+ 0xcf, 0x74, 0xf5, 0x00, 0xfe, 0x89, 0xe0, 0xd8, 0xfd, 0x83, 0x2a, 0x12, 0xfe, 0x0d, 0x84, 0xf0,
+ 0xc5, 0x28, 0xf4, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x32, 0x54, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x8d, 0xae, 0x00, 0x1c,
+ 0xff, 0x08, 0xe0, 0xd8, 0xfe, 0x83, 0x1b, 0xa0, 0xfe, 0x0c, 0x84, 0xf0, 0x4f, 0xec, 0x00, 0x00,
+ 0x85, 0xae, 0x00, 0x2c, 0xcf, 0x78, 0xf8, 0x00, 0x4e, 0xf5, 0x00, 0x00, 0x4f, 0x85, 0xdf, 0xff,
+ 0xce, 0x70, 0xe8, 0x00, 0xcf, 0xf8, 0xfd, 0x00, 0xff, 0x09, 0xe0, 0xd8, 0xfd, 0x83, 0x2a, 0x12,
+ 0xfe, 0x0d, 0x84, 0xf0, 0xc5, 0x28, 0xfc, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x32, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8d, 0x2e, 0x00, 0x1c, 0x8c, 0xae, 0x00, 0x38, 0xfe, 0x08, 0xe0, 0xd8, 0xfd, 0x83, 0x1b, 0xa0,
+ 0x85, 0xae, 0x00, 0x2c, 0x4f, 0x68, 0x00, 0x00, 0xff, 0x8c, 0x84, 0xf0, 0xce, 0x70, 0xf0, 0x00,
+ 0x4e, 0x85, 0xdf, 0xff, 0xce, 0xf0, 0xed, 0x00, 0x4d, 0xed, 0x00, 0x00, 0xfe, 0x09, 0xe0, 0xd8,
+ 0xcf, 0x28, 0xec, 0x00, 0xfd, 0x03, 0x2a, 0x12, 0xcf, 0xfc, 0xd8, 0x00, 0xfe, 0x0c, 0x7f, 0xd8,
+ 0x7e, 0xfc, 0x00, 0x10, 0xcf, 0xf6, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00,
+ 0xff, 0xf3, 0x28, 0x00, 0xfc, 0xf3, 0x28, 0x02, 0x0e, 0x70, 0x00, 0x04, 0x7f, 0xf1, 0x00, 0x19,
+ 0x20, 0x7e, 0x00, 0x00, 0xfe, 0x0d, 0x7f, 0xd8, 0xe6, 0x01, 0x33, 0xc5, 0x55, 0x78, 0x00, 0x80,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x33, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x98, 0x86, 0x18, 0x55, 0x29, 0x00, 0x02, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0xf0, 0xfc, 0x00, 0xff, 0x8d, 0x7f, 0xd8, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x33, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8d, 0x2e, 0x00, 0x1c, 0x8c, 0xae, 0x00, 0x38, 0xfe, 0x08, 0xe0, 0xd8, 0xfd, 0x83, 0x1b, 0xa0,
+ 0x85, 0xae, 0x00, 0x2c, 0x4f, 0x68, 0x00, 0x00, 0xff, 0x8c, 0x84, 0xf0, 0xce, 0x70, 0xf0, 0x00,
+ 0x4e, 0x85, 0xdf, 0xff, 0xce, 0xf0, 0xed, 0x00, 0x4d, 0xed, 0x00, 0x00, 0xfe, 0x09, 0xe0, 0xd8,
+ 0xcf, 0x28, 0xec, 0x00, 0xfd, 0x03, 0x2a, 0x12, 0xcf, 0xfc, 0xd8, 0x00, 0xfe, 0x0c, 0x7f, 0xd8,
+ 0x7e, 0xfc, 0x00, 0x10, 0xcf, 0xf6, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00,
+ 0xff, 0xf3, 0x28, 0x00, 0xfc, 0xf3, 0x28, 0x02, 0x0e, 0x70, 0x00, 0x04, 0x7f, 0xf1, 0x00, 0x19,
+ 0x20, 0x7e, 0x00, 0x00, 0xfe, 0x0d, 0x7f, 0xd8, 0xe6, 0x01, 0x34, 0xc5, 0x55, 0x78, 0x00, 0x80,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x34, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x98, 0x86, 0x18, 0x55, 0x29, 0x00, 0x02, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0xf0, 0xfc, 0x00, 0xff, 0x8d, 0x7f, 0xd8, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x34, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8d, 0x2e, 0x00, 0x1c, 0x8c, 0xae, 0x00, 0x38, 0xfe, 0x08, 0xe0, 0xd8, 0xfd, 0x83, 0x1b, 0xa0,
+ 0x85, 0xae, 0x00, 0x2c, 0x4f, 0x68, 0x00, 0x00, 0xff, 0x8c, 0x84, 0xf0, 0xce, 0x70, 0xf0, 0x00,
+ 0x4e, 0x85, 0xdf, 0xff, 0xce, 0xf0, 0xed, 0x00, 0x4d, 0xed, 0x00, 0x00, 0xfe, 0x09, 0xe0, 0xd8,
+ 0xcf, 0x28, 0xec, 0x00, 0xfd, 0x03, 0x2a, 0x12, 0xcf, 0xfc, 0xd8, 0x00, 0xfe, 0x0c, 0x7f, 0xd8,
+ 0x7e, 0xfc, 0x00, 0x10, 0xcf, 0xf6, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00,
+ 0xff, 0xf3, 0x28, 0x00, 0xfc, 0xf3, 0x28, 0x02, 0x0e, 0x70, 0x00, 0x04, 0x7f, 0xf1, 0x00, 0x19,
+ 0x20, 0x7e, 0x00, 0x00, 0xfe, 0x0d, 0x7f, 0xd8, 0xe6, 0x01, 0x35, 0xc5, 0x55, 0x78, 0x00, 0x80,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x35, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x98, 0x86, 0x18, 0x55, 0x29, 0x00, 0x02, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0xf0, 0xfc, 0x00, 0xff, 0x8d, 0x7f, 0xd8, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x35, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x43, 0x19, 0xfe, 0xff, 0xfe, 0x82, 0x00, 0x00, 0xff, 0x0e, 0x7c, 0x40, 0x8f, 0xfa, 0x00, 0x00,
+ 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0xbd, 0x0e, 0xf4, 0x00, 0x01, 0x8f, 0xfa, 0x00, 0x04,
+ 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0xbd, 0x00, 0x00, 0x00, 0x01, 0x8f, 0xfa, 0x00, 0x08,
+ 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0xbd, 0x00, 0x00, 0x00, 0x01, 0x8f, 0xfa, 0x00, 0x0c,
+ 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0xbd, 0x00, 0x00, 0x00, 0x01, 0x8f, 0xfa, 0x00, 0x10,
+ 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0xbd, 0x00, 0x00, 0x00, 0x01, 0x8f, 0xfa, 0x00, 0x14,
+ 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0xbd, 0x00, 0x00, 0x00, 0x01, 0x8f, 0xfa, 0x00, 0x18,
+ 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0xbd, 0x00, 0x00, 0x00, 0x01, 0x8f, 0xfa, 0x00, 0x1c,
+ 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0xbd, 0x20, 0x76, 0x00, 0x05, 0xee, 0x01, 0x36, 0x2d,
+ 0x0f, 0x78, 0x00, 0x80, 0xe0, 0x01, 0x36, 0xc8, 0x00, 0x00, 0x00, 0x01, 0x8f, 0xfa, 0x00, 0x24,
+ 0x5f, 0xfd, 0x20, 0x00, 0x9f, 0xfa, 0x00, 0x24, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x8f, 0x82, 0xff, 0xf8,
+ 0x70, 0x7e, 0x00, 0x1b, 0xea, 0x01, 0x37, 0x34, 0x00, 0x00, 0x00, 0x01, 0xff, 0x83, 0x1a, 0x28,
+ 0xff, 0x7a, 0x80, 0x00, 0xfe, 0x8c, 0x4c, 0x04, 0x4e, 0x7d, 0x00, 0x00, 0xcf, 0x70, 0xf0, 0x00,
+ 0xff, 0xfb, 0x18, 0x06, 0x0f, 0xfc, 0x00, 0x17, 0x4f, 0xfc, 0xff, 0xf0, 0xce, 0x70, 0xf8, 0x00,
+ 0x20, 0x72, 0xbf, 0xff, 0xe2, 0x01, 0x37, 0x21, 0x0e, 0xf4, 0x00, 0x01, 0x2e, 0x70, 0xc0, 0x00,
+ 0xfe, 0x03, 0x2a, 0x28, 0xff, 0x82, 0x00, 0x01, 0xfe, 0x8d, 0x4c, 0x04, 0xf0, 0x03, 0x2a, 0x1a,
+ 0xff, 0x99, 0x86, 0x10, 0x8e, 0x02, 0xfe, 0x08, 0x8e, 0x82, 0xfe, 0x20, 0x7d, 0xf0, 0xff, 0xf0,
+ 0x4c, 0xf1, 0x00, 0x00, 0x4f, 0xf5, 0x00, 0x00, 0xcf, 0xec, 0xf8, 0x00, 0x7f, 0x74, 0xff, 0xf0,
+ 0xc0, 0x72, 0xed, 0x00, 0xe6, 0x01, 0x37, 0x89, 0xcd, 0x7c, 0xf0, 0x00, 0xff, 0x8c, 0x4c, 0x04,
+ 0xfe, 0x8c, 0x4c, 0x00, 0xff, 0x0c, 0x4b, 0xe4, 0xcf, 0xfc, 0xd0, 0x00, 0xff, 0x8d, 0x4c, 0x04,
+ 0xce, 0xf4, 0xc8, 0x00, 0xcf, 0x78, 0xd8, 0x00, 0xff, 0x82, 0x00, 0x01, 0xfe, 0x8d, 0x4c, 0x00,
+ 0xff, 0x0d, 0x4b, 0xe4, 0xff, 0x99, 0x86, 0x10, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x7c, 0x74,
+ 0xf0, 0x03, 0x2a, 0x3a, 0x55, 0x28, 0x04, 0x00, 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x37, 0xac, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x7c, 0xf4, 0xf0, 0x03, 0x2a, 0x3a, 0x55, 0x28, 0x08, 0x00,
+ 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x38, 0x04, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x7d, 0x74,
+ 0xf0, 0x03, 0x2a, 0x3a, 0x55, 0x28, 0x10, 0x00, 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x38, 0x5c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x7d, 0xf4, 0xf0, 0x03, 0x2a, 0x3a, 0x55, 0x28, 0x20, 0x00,
+ 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x38, 0xb4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x7e, 0x74,
+ 0xf0, 0x03, 0x2a, 0x3a, 0x55, 0x28, 0x40, 0x00, 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x39, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x7e, 0xf4, 0xf0, 0x03, 0x2a, 0x3a, 0x55, 0x28, 0x80, 0x00,
+ 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x39, 0x64, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x7c, 0x74,
+ 0x55, 0x28, 0x04, 0x00, 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x39, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8c, 0x7c, 0xf4, 0x55, 0x28, 0x08, 0x00, 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x3a, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x7d, 0x74, 0x55, 0x28, 0x10, 0x00, 0xff, 0x81, 0x04, 0x14,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x3a, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x7d, 0xf4, 0x55, 0x28, 0x20, 0x00,
+ 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x3a, 0xb4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x7e, 0x74,
+ 0x55, 0x28, 0x40, 0x00, 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x3b, 0x08, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8c, 0x7e, 0xf4, 0x55, 0x28, 0x80, 0x00, 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x3b, 0x5c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0xff, 0x8c, 0x7c, 0x30, 0xff, 0x0e, 0x86, 0x00,
+ 0xfe, 0x8e, 0x4c, 0x30, 0xfe, 0x0e, 0x7c, 0x32, 0x83, 0xfe, 0x40, 0x00, 0x43, 0x7d, 0x00, 0x00,
+ 0x0f, 0x98, 0x00, 0x11, 0x40, 0x1e, 0x00, 0x00, 0xe6, 0x01, 0x3b, 0xf0, 0x7d, 0x9c, 0x00, 0x02,
+ 0x90, 0x02, 0xfe, 0x02, 0xad, 0x7a, 0xd8, 0x02, 0xcf, 0xfc, 0x38, 0x00, 0x7f, 0xfc, 0xff, 0xfd,
+ 0xa4, 0x76, 0xf8, 0x01, 0x23, 0x9c, 0x00, 0x02, 0xc1, 0x68, 0x00, 0x00, 0xf4, 0x73, 0x28, 0x00,
+ 0xff, 0x8c, 0x7c, 0x30, 0xff, 0x0e, 0x4c, 0x30, 0x8e, 0x7e, 0x40, 0x00, 0x4f, 0xfd, 0x00, 0x00,
+ 0x9f, 0x96, 0xff, 0xf4, 0xc3, 0x7c, 0x00, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0xcf, 0x98, 0xf8, 0x00,
+ 0x0f, 0xfc, 0x00, 0x11, 0x7f, 0xfc, 0xff, 0xfc, 0xf0, 0x03, 0x2a, 0x02, 0xcf, 0xfc, 0xf8, 0x00,
+ 0xaf, 0xfe, 0xf0, 0x01, 0x40, 0x72, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xf0, 0x8f, 0x16, 0xff, 0xf0,
+ 0xff, 0x8e, 0x7c, 0x32, 0xff, 0x7f, 0x28, 0x00, 0x84, 0x16, 0xff, 0xf0, 0xe6, 0x01, 0x3c, 0x59,
+ 0x03, 0xf0, 0x00, 0x02, 0x9e, 0x16, 0xff, 0xec, 0xf7, 0x86, 0x3c, 0x54, 0xe0, 0x01, 0x3d, 0x44,
+ 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x16, 0xff, 0xec, 0x7f, 0xf1, 0x00, 0x02, 0xff, 0x0e, 0x86, 0x00,
+ 0x83, 0x16, 0xff, 0xf4, 0x84, 0x16, 0xff, 0xf0, 0xae, 0xfe, 0xf0, 0x02, 0x2e, 0x70, 0x00, 0x02,
+ 0xc3, 0xf0, 0x00, 0x00, 0xf7, 0x86, 0x3c, 0x80, 0xc1, 0x74, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xfd, 0x8c, 0x84, 0xb4, 0xff, 0x0e, 0x86, 0x00,
+ 0xff, 0x8c, 0x7f, 0xd8, 0x7e, 0xed, 0x00, 0x02, 0xce, 0xf4, 0xf0, 0x00, 0xff, 0x1c, 0x46, 0xc0,
+ 0x8e, 0xf6, 0x00, 0x08, 0x45, 0x29, 0xff, 0xf7, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0x7d, 0xff, 0xfe,
+ 0xff, 0x8c, 0x4c, 0x28, 0xff, 0x0c, 0x7f, 0xc8, 0xcf, 0xfc, 0xe0, 0x00, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xe6, 0x01, 0x3d, 0x1c, 0x9e, 0x96, 0xff, 0xf4, 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x1a,
+ 0xea, 0x01, 0x3d, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x82, 0xff, 0xd0, 0xff, 0x0c, 0x4b, 0xc0,
+ 0xff, 0x8e, 0x0d, 0x40, 0xce, 0xf4, 0xf2, 0x00, 0xc0, 0x76, 0xfa, 0x00, 0xe2, 0x01, 0x3d, 0x1d,
+ 0xc3, 0xec, 0x00, 0x00, 0xf3, 0x0c, 0x84, 0xb0, 0xf4, 0x0c, 0x84, 0xb8, 0xf7, 0x86, 0x3d, 0x18,
+ 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc, 0xfd, 0x8c, 0x84, 0xb4, 0xf3, 0x0c, 0x84, 0xb0,
+ 0xf4, 0x0c, 0x84, 0xb8, 0x8f, 0x96, 0xff, 0xf4, 0xc3, 0xec, 0x00, 0x00, 0xf7, 0x86, 0x3d, 0x38,
+ 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x83, 0x1a, 0x12,
+ 0x4f, 0x18, 0xff, 0xf0, 0x4f, 0xfd, 0x00, 0x00, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x01, 0x3e, 0x9d,
+ 0x23, 0x9c, 0x00, 0x02, 0xff, 0x8c, 0x84, 0xa8, 0xf4, 0x7f, 0x28, 0x1e, 0x20, 0x1e, 0x00, 0x00,
+ 0xe6, 0x01, 0x3d, 0xc4, 0xcf, 0x84, 0x00, 0x00, 0xff, 0x8c, 0x4b, 0xf4, 0x0f, 0xfc, 0x00, 0x01,
+ 0xff, 0x8d, 0x4b, 0xf4, 0xff, 0x82, 0x00, 0x01, 0xff, 0x99, 0x86, 0x10, 0x55, 0x28, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x3d, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0xc0, 0x1e, 0xfa, 0x00, 0xe6, 0x01, 0x3e, 0x85, 0x20, 0x1e, 0x00, 0x3b,
+ 0xe2, 0x01, 0x3d, 0xe8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x4c, 0x08, 0x0f, 0xfc, 0x00, 0x01,
+ 0xe0, 0x01, 0x3d, 0x84, 0xff, 0x8d, 0x4c, 0x08, 0xff, 0x8c, 0x4b, 0xb8, 0xc0, 0x1e, 0xfa, 0x00,
+ 0xe2, 0x01, 0x3e, 0x08, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x4c, 0x10, 0x0f, 0xfc, 0x00, 0x01,
+ 0xe0, 0x01, 0x3d, 0x84, 0xff, 0x8d, 0x4c, 0x10, 0xff, 0x8c, 0x84, 0xc8, 0xc0, 0x1e, 0xfa, 0x00,
+ 0xe2, 0x01, 0x3e, 0x28, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x4c, 0x14, 0x0f, 0xfc, 0x00, 0x01,
+ 0xe0, 0x01, 0x3d, 0x84, 0xff, 0x8d, 0x4c, 0x14, 0x70, 0x1e, 0x00, 0x01, 0xea, 0x01, 0x3e, 0x50,
+ 0x20, 0x1e, 0x00, 0x00, 0xff, 0x0c, 0x4b, 0xf0, 0xff, 0x8c, 0x4c, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf0, 0xe0, 0x01, 0x3d, 0x84, 0xff, 0x8d, 0x4c, 0x04,
+ 0xec, 0x01, 0x3e, 0x69, 0xf3, 0x7e, 0x40, 0x00, 0xff, 0x8c, 0x4c, 0x0c, 0x0f, 0xfc, 0x00, 0x01,
+ 0xe0, 0x01, 0x3d, 0x84, 0xff, 0x8d, 0x4c, 0x0c, 0xc3, 0x78, 0x30, 0x00, 0x43, 0x9d, 0x00, 0x00,
+ 0xf7, 0x86, 0x3e, 0x7c, 0xe0, 0x02, 0x83, 0x64, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x3d, 0x88,
+ 0xff, 0x82, 0x00, 0x01, 0xff, 0x0c, 0x4b, 0xe8, 0xff, 0x8c, 0x4c, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x01, 0x3e, 0x48, 0xff, 0x0d, 0x4b, 0xe8, 0xf4, 0x03, 0x2a, 0x12,
+ 0xe0, 0x01, 0x3d, 0x70, 0x20, 0x1e, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfb, 0x9c, 0x46, 0x58,
+ 0xfc, 0x8c, 0x85, 0x70, 0xfe, 0x24, 0x56, 0xf0, 0x2d, 0x5c, 0x1f, 0xfd, 0x7f, 0xe8, 0xff, 0xfd,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02,
+ 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc, 0xab, 0x7e, 0xe8, 0x05,
+ 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x7c, 0x30, 0xfe, 0x88, 0xe6, 0xd8, 0xfa, 0x9c, 0x46, 0x48,
+ 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7d, 0x68, 0xff, 0xfe,
+ 0x4f, 0x68, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xf5, 0x00, 0xff, 0xf7, 0x28, 0x0e,
+ 0x7d, 0xed, 0x00, 0x02, 0xfb, 0x77, 0x28, 0x12, 0xcf, 0xf4, 0xd8, 0x00, 0x9c, 0xf6, 0x00, 0x14,
+ 0x0e, 0x70, 0x20, 0x00, 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00,
+ 0xfd, 0xf7, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0x5c, 0x20, 0x00, 0xff, 0x8a, 0xe2, 0xd0,
+ 0xaf, 0x7e, 0xd0, 0x05, 0xfc, 0x88, 0xe0, 0xd8, 0xfe, 0x77, 0x18, 0x0a, 0xff, 0x9a, 0x00, 0x0e,
+ 0x8d, 0x76, 0x00, 0x2c, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x9b, 0x02, 0xfe, 0x58, 0xfa, 0xf7, 0x28, 0x20, 0xfc, 0x77, 0x28, 0x1e, 0xfb, 0x77, 0x28, 0x22,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0x33, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00, 0xfd, 0x09, 0xe6, 0xd8,
+ 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c, 0xfe, 0x6b, 0x28, 0x00,
+ 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10, 0x9e, 0x6a, 0x00, 0x08,
+ 0xcc, 0xe4, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfc, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0x2b, 0xdc, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02, 0x9b, 0xf6, 0x00, 0x38, 0xff, 0x0c, 0x85, 0x00,
+ 0x4c, 0xe5, 0x20, 0x00, 0xc5, 0x28, 0xcd, 0x00, 0xcf, 0x78, 0xb2, 0x00, 0x7f, 0xf9, 0xff, 0xe1,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8, 0xff, 0x0d, 0x85, 0x00,
+ 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x40, 0x14, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48,
+ 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x18, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x3e, 0xbc, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x41, 0x84, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48,
+ 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x10, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x40, 0x5c, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x42, 0xf4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48,
+ 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x08, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x41, 0xcc, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x44, 0x64, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02,
+ 0xcc, 0x98, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x85, 0xe8, 0xfe, 0xa4, 0x57, 0x70,
+ 0xfe, 0x67, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x46, 0xec, 0xcd, 0x1c, 0x00, 0x00,
+ 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x46, 0xec, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xd0,
+ 0x8d, 0xfa, 0x00, 0x04, 0x8e, 0x7a, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x08, 0x70, 0x6e, 0x00, 0x1f,
+ 0xea, 0x01, 0x46, 0x61, 0x4f, 0xfc, 0xef, 0xff, 0xff, 0x9d, 0x46, 0xd0, 0x90, 0xfa, 0x00, 0x04,
+ 0xff, 0x9a, 0x86, 0x30, 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x72, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8,
+ 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x1d, 0x46, 0x58, 0xfe, 0x0d, 0x85, 0x70,
+ 0xfd, 0xa5, 0x56, 0xf0, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10,
+ 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00, 0x9d, 0xfa, 0x00, 0x14,
+ 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xe2, 0xd0,
+ 0xff, 0x82, 0x02, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20,
+ 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x20, 0x9f, 0xf6, 0x00, 0x04,
+ 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0x0e, 0x70, 0x00, 0x01,
+ 0xfe, 0x77, 0x28, 0x1c, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00,
+ 0x7e, 0x71, 0x00, 0x10, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfd, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x77, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00,
+ 0x4d, 0xed, 0x20, 0x00, 0xcc, 0x60, 0xdd, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x43, 0x3c, 0xfb, 0x9d, 0x46, 0x48,
+ 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x46, 0x2c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x80, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x47, 0x99, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x1c, 0x46, 0xc0, 0xff, 0x8c, 0x7f, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe,
+ 0xff, 0x0c, 0x4c, 0x28, 0xff, 0x8c, 0x7f, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x46, 0xa9, 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8,
+ 0xff, 0x8d, 0x4b, 0xc0, 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x84, 0xb0, 0xfd, 0x0d, 0x84, 0xb4,
+ 0xf4, 0x0d, 0x84, 0xb8, 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x46, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48,
+ 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x47, 0x84, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x44, 0xdd,
+ 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x56, 0xf0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x47, 0x65, 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04,
+ 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x47, 0x6d,
+ 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x47, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x47, 0x98, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x47, 0x54,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x44, 0xdc, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x47, 0x98,
+ 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xb9, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x44, 0xdc,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x47, 0xa4, 0xe0, 0x01, 0x3d, 0x44,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfb, 0x9c, 0x46, 0x58, 0xfc, 0x8c, 0x85, 0x70,
+ 0xfe, 0x24, 0x56, 0xf0, 0x2d, 0x5c, 0x17, 0xfd, 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc, 0xab, 0x7e, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00,
+ 0xfc, 0x0c, 0x7c, 0x30, 0xfe, 0x88, 0xe6, 0xd8, 0xfa, 0x9c, 0x46, 0x48, 0xe6, 0x6c, 0x00, 0x02,
+ 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7d, 0x68, 0xff, 0xfe, 0x4f, 0x68, 0x03, 0xff,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xf5, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02,
+ 0xfb, 0x77, 0x28, 0x12, 0xcf, 0xf4, 0xd8, 0x00, 0x9c, 0xf6, 0x00, 0x14, 0x0e, 0x70, 0x18, 0x00,
+ 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xf7, 0x68, 0x09,
+ 0x45, 0x29, 0xff, 0xfe, 0x2b, 0x5c, 0x18, 0x00, 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xd0, 0x05,
+ 0xfc, 0x88, 0xe0, 0xd8, 0xfe, 0x77, 0x18, 0x0a, 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x76, 0x00, 0x2c,
+ 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58,
+ 0xfa, 0xf7, 0x28, 0x20, 0xfc, 0x77, 0x28, 0x1e, 0xfb, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x33, 0x20,
+ 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00, 0xfd, 0x09, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff,
+ 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c, 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01,
+ 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10, 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xf2, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfc, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0x2b, 0xdc, 0x00, 0x02,
+ 0xf0, 0x77, 0x28, 0x02, 0x9b, 0xf6, 0x00, 0x38, 0xff, 0x0c, 0x85, 0x00, 0x4c, 0xe5, 0x20, 0x00,
+ 0xc5, 0x28, 0xcd, 0x00, 0xcf, 0x78, 0xb2, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8, 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x49, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x70,
+ 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x56, 0xf0,
+ 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x10, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00,
+ 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09,
+ 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xe0, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x9c,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0xf4, 0x0f, 0xff,
+ 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c, 0x2f, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02,
+ 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00, 0x2f, 0x78, 0x08, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x47, 0xb8,
+ 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34, 0x55, 0x74, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x4a, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x70,
+ 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x56, 0xf0,
+ 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x08, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00,
+ 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09,
+ 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xe0, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x9c,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0xf4, 0x0f, 0xff,
+ 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c, 0x2f, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02,
+ 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00, 0x2f, 0x78, 0x08, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x49, 0x58,
+ 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34, 0x55, 0x74, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x4b, 0xf0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00,
+ 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x85, 0xe8, 0xfe, 0xa4, 0x57, 0x70, 0xfe, 0x67, 0x18, 0x04,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x4e, 0x78, 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00,
+ 0xe6, 0x01, 0x4e, 0x78, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xd0, 0x8d, 0xfa, 0x00, 0x04,
+ 0x8e, 0x7a, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x08, 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x4d, 0xed,
+ 0x4f, 0xfc, 0xef, 0xff, 0xff, 0x9d, 0x46, 0xd0, 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x86, 0x30,
+ 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x72, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8, 0xe6, 0x78, 0x00, 0x02,
+ 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x1d, 0x46, 0x58, 0xfe, 0x0d, 0x85, 0x70, 0xfd, 0xa5, 0x56, 0xf0,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f,
+ 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12,
+ 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10,
+ 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00,
+ 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22,
+ 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00,
+ 0xfc, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c,
+ 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7e, 0x71, 0x00, 0x10,
+ 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x89, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x77, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0xed, 0x20, 0x00,
+ 0xcc, 0x60, 0xdd, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x4a, 0xc8, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00,
+ 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x4d, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x4f, 0x25, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0,
+ 0xff, 0x8c, 0x7f, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28,
+ 0xff, 0x8c, 0x7f, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x4e, 0x35,
+ 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0,
+ 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x84, 0xb0, 0xfd, 0x0d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8,
+ 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x4e, 0x44, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07,
+ 0xea, 0x01, 0x4f, 0x10, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x4c, 0x69, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02,
+ 0xff, 0x1e, 0x56, 0xf0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x4e, 0xf1,
+ 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00,
+ 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x4e, 0xf9, 0xc0, 0x76, 0xe2, 0x00,
+ 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x4e, 0xcc, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0x4f, 0x24, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x4e, 0xe0, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x4c, 0x68, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x4f, 0x24, 0xf3, 0x82, 0x00, 0x02,
+ 0xff, 0x88, 0xb9, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x4c, 0x68, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x4f, 0x30, 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfb, 0x9c, 0x46, 0x58, 0xfc, 0x8c, 0x85, 0x70, 0xfe, 0x24, 0x56, 0xf0,
+ 0x2d, 0x5c, 0x0f, 0xfd, 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x4f, 0xe8, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xff, 0x82, 0x7c, 0xcc, 0xab, 0x7e, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x7c, 0x30,
+ 0xfe, 0x88, 0xe6, 0xd8, 0xfa, 0x9c, 0x46, 0x48, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7d, 0x68, 0xff, 0xfe, 0x4f, 0x68, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xfb, 0x77, 0x28, 0x12,
+ 0xcf, 0xf4, 0xd8, 0x00, 0x9c, 0xf6, 0x00, 0x14, 0x0e, 0x70, 0x10, 0x00, 0x9e, 0x7e, 0x00, 0x14,
+ 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xf7, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe,
+ 0x2b, 0x5c, 0x10, 0x00, 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xd0, 0x05, 0xfc, 0x88, 0xe0, 0xd8,
+ 0xfe, 0x77, 0x18, 0x0a, 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x76, 0x00, 0x2c, 0x9f, 0xf6, 0x00, 0x30,
+ 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0xfa, 0xf7, 0x28, 0x20,
+ 0xfc, 0x77, 0x28, 0x1e, 0xfb, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x33, 0x20, 0x9f, 0xf6, 0x00, 0x04,
+ 0xce, 0x70, 0xf0, 0x00, 0xfd, 0x09, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01,
+ 0xff, 0x77, 0x28, 0x1c, 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00,
+ 0x7f, 0x79, 0x00, 0x10, 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfc, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0x2b, 0xdc, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02,
+ 0x9b, 0xf6, 0x00, 0x38, 0xff, 0x0c, 0x85, 0x00, 0x4c, 0xe5, 0x20, 0x00, 0xc5, 0x28, 0xcd, 0x00,
+ 0xcf, 0x78, 0xb2, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xfe, 0x8d, 0x84, 0xa8, 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x50, 0x9c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30,
+ 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8,
+ 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02,
+ 0x0e, 0xf4, 0x08, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14,
+ 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0,
+ 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20,
+ 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01,
+ 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00,
+ 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00,
+ 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x4f, 0x44, 0xfb, 0x9d, 0x46, 0x48,
+ 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34, 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x52, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02,
+ 0xff, 0x8c, 0x85, 0xe8, 0xfe, 0xa4, 0x57, 0x70, 0xfe, 0x67, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x54, 0x94, 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x54, 0x94,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xd0, 0x8d, 0xfa, 0x00, 0x04, 0x8e, 0x7a, 0x00, 0x00,
+ 0x0f, 0xf8, 0x00, 0x08, 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x54, 0x09, 0x4f, 0xfc, 0xef, 0xff,
+ 0xff, 0x9d, 0x46, 0xd0, 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x86, 0x30, 0xab, 0x9a, 0xf8, 0x01,
+ 0x20, 0x72, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02,
+ 0xfd, 0x1d, 0x46, 0x58, 0xfe, 0x0d, 0x85, 0x70, 0xfd, 0xa5, 0x56, 0xf0, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00,
+ 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14,
+ 0xcf, 0x74, 0xf0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09,
+ 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xae, 0x7a, 0xf8, 0x05,
+ 0xfd, 0x88, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a,
+ 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0xff, 0x67, 0x28, 0x00,
+ 0x2f, 0xf8, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7e, 0x71, 0x00, 0x10, 0x9f, 0x66, 0x00, 0x08,
+ 0xcd, 0xec, 0xe2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x77, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0xed, 0x20, 0x00, 0xcc, 0x60, 0xdd, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x50, 0xe4, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x53, 0xd4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x55, 0x41, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0, 0xff, 0x8c, 0x7f, 0xd8,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28, 0xff, 0x8c, 0x7f, 0xc8,
+ 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x54, 0x51, 0xff, 0xa2, 0x02, 0x00,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0, 0xff, 0xa2, 0x02, 0x00,
+ 0xf3, 0x0d, 0x84, 0xb0, 0xfd, 0x0d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8, 0xc5, 0x28, 0xfd, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x54, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x55, 0x2c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x52, 0x85, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88,
+ 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x56, 0xf0,
+ 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x55, 0x0d, 0x00, 0x00, 0x00, 0x01,
+ 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04,
+ 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x55, 0x15, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x54, 0xe8, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x55, 0x40,
+ 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x54, 0xfc, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x52, 0x84,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x55, 0x40, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xb9, 0x50,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x52, 0x84, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x86, 0x55, 0x4c, 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfb, 0x9c, 0x46, 0x58, 0xfc, 0x8c, 0x85, 0x70, 0xfe, 0x24, 0x56, 0xf0, 0x2d, 0x5c, 0x07, 0xfd,
+ 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03,
+ 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc,
+ 0xab, 0x7e, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x7c, 0x30, 0xfe, 0x88, 0xe6, 0xd8,
+ 0xfa, 0x9c, 0x46, 0x48, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7d, 0x68, 0xff, 0xfe, 0x4f, 0x68, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xff, 0xf7, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xfb, 0x77, 0x28, 0x12, 0xcf, 0xf4, 0xd8, 0x00,
+ 0x9c, 0xf6, 0x00, 0x14, 0x0e, 0x70, 0x08, 0x00, 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10,
+ 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xf7, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0x5c, 0x08, 0x00,
+ 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xd0, 0x05, 0xfc, 0x88, 0xe0, 0xd8, 0xfe, 0x77, 0x18, 0x0a,
+ 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x76, 0x00, 0x2c, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0xfa, 0xf7, 0x28, 0x20, 0xfc, 0x77, 0x28, 0x1e,
+ 0xfb, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00,
+ 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x33, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00,
+ 0xfd, 0x09, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c,
+ 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10,
+ 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfc, 0x89, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0x2b, 0xdc, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02, 0x9b, 0xf6, 0x00, 0x38,
+ 0xff, 0x0c, 0x85, 0x00, 0x4c, 0xe5, 0x20, 0x00, 0xc5, 0x28, 0xcd, 0x00, 0xcf, 0x78, 0xb2, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8,
+ 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x56, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x85, 0xe8,
+ 0xfe, 0xa4, 0x57, 0x70, 0xfe, 0x67, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x59, 0x40,
+ 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x59, 0x40, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x1c, 0x46, 0xd0, 0x8d, 0xfa, 0x00, 0x04, 0x8e, 0x7a, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x08,
+ 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x58, 0xb5, 0x4f, 0xfc, 0xef, 0xff, 0xff, 0x9d, 0x46, 0xd0,
+ 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x86, 0x30, 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x72, 0x00, 0x00,
+ 0xfe, 0x88, 0xe6, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x1d, 0x46, 0x58,
+ 0xfe, 0x0d, 0x85, 0x70, 0xfd, 0xa5, 0x56, 0xf0, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7f, 0x79, 0x00, 0x02,
+ 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xf7, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01,
+ 0xff, 0x0a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xe0, 0xd8,
+ 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30,
+ 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x20,
+ 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01,
+ 0xff, 0xf7, 0x28, 0x00, 0x7e, 0x71, 0x00, 0x10, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x77, 0x28, 0x02,
+ 0xff, 0x0c, 0x85, 0x00, 0x4d, 0xed, 0x20, 0x00, 0xcc, 0x60, 0xdd, 0x00, 0x2f, 0x78, 0x08, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x55, 0x60,
+ 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x58, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x59, 0xed,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0, 0xff, 0x8c, 0x7f, 0xd8, 0xcf, 0xfc, 0xf2, 0x00,
+ 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28, 0xff, 0x8c, 0x7f, 0xc8, 0xcf, 0x78, 0xe8, 0x00,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x58, 0xfd, 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0,
+ 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0, 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x84, 0xb0,
+ 0xfd, 0x0d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8, 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x59, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x59, 0xd8, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x57, 0x31, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0,
+ 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff,
+ 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x56, 0xf0, 0xaf, 0x7e, 0xf0, 0x02,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x59, 0xb9, 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02,
+ 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00,
+ 0xe6, 0x01, 0x59, 0xc1, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x59, 0x94, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x59, 0xec, 0xf3, 0x82, 0x00, 0x02,
+ 0xe6, 0x01, 0x59, 0xa8, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x57, 0x30, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0x59, 0xec, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xb9, 0x50, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x57, 0x30, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x59, 0xf8,
+ 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02,
+ 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x85, 0xe8, 0xfe, 0xa4, 0x57, 0x70,
+ 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x5c, 0x58, 0xcc, 0x1c, 0x00, 0x00,
+ 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x5c, 0x58, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x1c, 0x46, 0xd0,
+ 0x8b, 0xf2, 0x00, 0x04, 0x8c, 0xf2, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x08, 0x70, 0x5e, 0x00, 0x1f,
+ 0xea, 0x01, 0x5b, 0xcd, 0x4d, 0x7c, 0xef, 0xff, 0x0d, 0xe0, 0x00, 0x03, 0x7f, 0xec, 0xff, 0xfd,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xec, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02,
+ 0xfd, 0x1d, 0x46, 0xd0, 0xce, 0xf8, 0xfd, 0x00, 0x90, 0xf2, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x02,
+ 0xff, 0x82, 0x7c, 0xcc, 0xad, 0x7e, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x78, 0x00, 0x02,
+ 0xfe, 0x88, 0xe6, 0xd8, 0x5f, 0xf8, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7d, 0xec, 0xff, 0xfe,
+ 0x4e, 0x6c, 0x03, 0xff, 0xfd, 0x77, 0x28, 0x12, 0x7f, 0x79, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xe5, 0x00, 0x0d, 0x78, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x0e, 0x9c, 0xf6, 0x00, 0x14,
+ 0xcf, 0x74, 0xf0, 0x00, 0x9b, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09,
+ 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xd8, 0x05, 0xfc, 0x88, 0xe0, 0xd8, 0xfe, 0x77, 0x18, 0x0a,
+ 0xff, 0xba, 0x00, 0x0e, 0x8d, 0xf6, 0x00, 0x2c, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9c, 0x02, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xf4, 0x77, 0x28, 0x1e,
+ 0xfc, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x31, 0x28, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00,
+ 0xfd, 0x89, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c,
+ 0xfe, 0x6f, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10,
+ 0x9e, 0x6e, 0x00, 0x08, 0xcc, 0xe4, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfc, 0x89, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0x23, 0xe0, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02, 0x93, 0xf6, 0x00, 0x38,
+ 0xff, 0x0c, 0x85, 0x00, 0x4c, 0xe5, 0x20, 0x00, 0xc5, 0x28, 0xcd, 0x00, 0xcf, 0x78, 0xc2, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8,
+ 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x5b, 0x98, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x5d, 0x05, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0,
+ 0xff, 0x8c, 0x7f, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28,
+ 0xff, 0x8c, 0x7f, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x5c, 0x15,
+ 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0,
+ 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x84, 0xb0, 0xfc, 0x0d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8,
+ 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x5c, 0x24, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07,
+ 0xea, 0x01, 0x5c, 0xf0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x5a, 0x3d, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02,
+ 0xff, 0x1e, 0x56, 0xf0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x5c, 0xd1,
+ 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00,
+ 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x5c, 0xd9, 0xc0, 0x76, 0xe2, 0x00,
+ 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x5c, 0xac, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0x5d, 0x04, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x5c, 0xc0, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x5d, 0x04, 0xf3, 0x82, 0x00, 0x02,
+ 0xff, 0x88, 0xb9, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x5d, 0x10, 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfb, 0x9c, 0x46, 0x58, 0xfc, 0x8c, 0x85, 0x70, 0xfe, 0x24, 0x56, 0xf0,
+ 0x2d, 0x5c, 0x1f, 0xfd, 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x4f, 0xe8, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xff, 0x82, 0x7c, 0xcc, 0xab, 0x7e, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x7c, 0x30,
+ 0xfe, 0x88, 0xe6, 0xd8, 0xfa, 0x9c, 0x46, 0x48, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7d, 0x68, 0xff, 0xfe, 0x4f, 0x68, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xfb, 0x77, 0x28, 0x12,
+ 0xcf, 0xf4, 0xd8, 0x00, 0x9c, 0xf6, 0x00, 0x14, 0x0e, 0x70, 0x20, 0x00, 0x9e, 0x7e, 0x00, 0x14,
+ 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xf7, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe,
+ 0x2b, 0x5c, 0x20, 0x00, 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xd0, 0x05, 0xfc, 0x88, 0xe0, 0xd8,
+ 0xfe, 0x77, 0x18, 0x0a, 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x76, 0x00, 0x2c, 0x9f, 0xf6, 0x00, 0x30,
+ 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0xfa, 0xf7, 0x28, 0x20,
+ 0xfc, 0x77, 0x28, 0x1e, 0xfb, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x33, 0x20, 0x9f, 0xf6, 0x00, 0x04,
+ 0xce, 0x70, 0xf0, 0x00, 0xfd, 0x09, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01,
+ 0xff, 0x77, 0x28, 0x1c, 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00,
+ 0x7f, 0x79, 0x00, 0x10, 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfc, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0x2b, 0xdc, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02,
+ 0x9b, 0xf6, 0x00, 0x38, 0xff, 0x0c, 0x85, 0x00, 0x4c, 0xe5, 0x20, 0x00, 0xc5, 0x28, 0xcd, 0x00,
+ 0xcf, 0x78, 0xb2, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xfe, 0x8d, 0x84, 0xa8, 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x5e, 0x7c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30,
+ 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8,
+ 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02,
+ 0x0e, 0xf4, 0x18, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14,
+ 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0,
+ 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20,
+ 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01,
+ 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00,
+ 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00,
+ 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x5d, 0x24, 0xfb, 0x9d, 0x46, 0x48,
+ 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34, 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x5f, 0xec, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30,
+ 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8,
+ 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02,
+ 0x0e, 0xf4, 0x10, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14,
+ 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0,
+ 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20,
+ 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01,
+ 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00,
+ 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00,
+ 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x5e, 0xc4, 0xfb, 0x9d, 0x46, 0x48,
+ 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34, 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x61, 0x5c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30,
+ 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8,
+ 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02,
+ 0x0e, 0xf4, 0x08, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14,
+ 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0,
+ 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20,
+ 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01,
+ 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00,
+ 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00,
+ 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x60, 0x34, 0xfb, 0x9d, 0x46, 0x48,
+ 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34, 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x62, 0xcc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02,
+ 0xff, 0x8c, 0x85, 0xe8, 0xfe, 0xa4, 0x57, 0x70, 0xfe, 0x67, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x65, 0x6c, 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x65, 0x6c,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x18, 0x86, 0x08, 0x8d, 0xfa, 0x00, 0x04, 0x8e, 0x7a, 0x00, 0x00,
+ 0x0f, 0xf8, 0x00, 0x08, 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x64, 0xe1, 0x4e, 0xfc, 0xef, 0xff,
+ 0xff, 0x8c, 0x7f, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x63, 0x79, 0x7f, 0xfd, 0x00, 0x03,
+ 0xcf, 0xf8, 0xf8, 0x00, 0x4e, 0xfc, 0xef, 0xff, 0xfe, 0x99, 0x86, 0x08, 0x90, 0xfa, 0x00, 0x04,
+ 0xff, 0x9a, 0x86, 0x30, 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x72, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8,
+ 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x1d, 0x46, 0x58, 0xfe, 0x0d, 0x85, 0x70,
+ 0xfd, 0xa5, 0x56, 0xf0, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10,
+ 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00, 0x9d, 0xfa, 0x00, 0x14,
+ 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xe2, 0xd0,
+ 0xff, 0x82, 0x02, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20,
+ 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x20, 0x9f, 0xf6, 0x00, 0x04,
+ 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0x0e, 0x70, 0x00, 0x01,
+ 0xfe, 0x77, 0x28, 0x1c, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00,
+ 0x7e, 0x71, 0x00, 0x10, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfd, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x77, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00,
+ 0x4d, 0xed, 0x20, 0x00, 0xcc, 0x60, 0xdd, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x61, 0xa4, 0xfb, 0x9d, 0x46, 0x48,
+ 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x64, 0xac, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x80, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x66, 0x19, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x1c, 0x46, 0xc0, 0xff, 0x8c, 0x7f, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe,
+ 0xff, 0x0c, 0x4c, 0x28, 0xff, 0x8c, 0x7f, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x65, 0x29, 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8,
+ 0xff, 0x8d, 0x4b, 0xc0, 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x84, 0xb0, 0xfd, 0x0d, 0x84, 0xb4,
+ 0xf4, 0x0d, 0x84, 0xb8, 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x65, 0x38, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48,
+ 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x66, 0x04, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x63, 0x45,
+ 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x56, 0xf0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x65, 0xe5, 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04,
+ 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x65, 0xed,
+ 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x65, 0xc0,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x66, 0x18, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x65, 0xd4,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x63, 0x44, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x66, 0x18,
+ 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xb9, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x63, 0x44,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x66, 0x24, 0xe0, 0x01, 0x3d, 0x44,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfb, 0x9c, 0x46, 0x58, 0xfc, 0x8c, 0x85, 0x70,
+ 0xfe, 0x24, 0x56, 0xf0, 0x2d, 0x5c, 0x17, 0xfd, 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc, 0xab, 0x7e, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00,
+ 0xfc, 0x0c, 0x7c, 0x30, 0xfe, 0x88, 0xe6, 0xd8, 0xfa, 0x9c, 0x46, 0x48, 0xe6, 0x6c, 0x00, 0x02,
+ 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7d, 0x68, 0xff, 0xfe, 0x4f, 0x68, 0x03, 0xff,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xf5, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02,
+ 0xfb, 0x77, 0x28, 0x12, 0xcf, 0xf4, 0xd8, 0x00, 0x9c, 0xf6, 0x00, 0x14, 0x0e, 0x70, 0x18, 0x00,
+ 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xf7, 0x68, 0x09,
+ 0x45, 0x29, 0xff, 0xfe, 0x2b, 0x5c, 0x18, 0x00, 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xd0, 0x05,
+ 0xfc, 0x88, 0xe0, 0xd8, 0xfe, 0x77, 0x18, 0x0a, 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x76, 0x00, 0x2c,
+ 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58,
+ 0xfa, 0xf7, 0x28, 0x20, 0xfc, 0x77, 0x28, 0x1e, 0xfb, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x33, 0x20,
+ 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00, 0xfd, 0x09, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff,
+ 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c, 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01,
+ 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10, 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xf2, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfc, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0x2b, 0xdc, 0x00, 0x02,
+ 0xf0, 0x77, 0x28, 0x02, 0x9b, 0xf6, 0x00, 0x38, 0xff, 0x0c, 0x85, 0x00, 0x4c, 0xe5, 0x20, 0x00,
+ 0xc5, 0x28, 0xcd, 0x00, 0xcf, 0x78, 0xb2, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8, 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x67, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x70,
+ 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x56, 0xf0,
+ 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x10, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00,
+ 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09,
+ 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xe0, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x9c,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0xf4, 0x0f, 0xff,
+ 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c, 0x2f, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02,
+ 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00, 0x2f, 0x78, 0x08, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x66, 0x38,
+ 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34, 0x55, 0x74, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x69, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x70,
+ 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x56, 0xf0,
+ 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x08, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00,
+ 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09,
+ 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xe0, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x9c,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0xf4, 0x0f, 0xff,
+ 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c, 0x2f, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02,
+ 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00, 0x2f, 0x78, 0x08, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x67, 0xd8,
+ 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34, 0x55, 0x74, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x6a, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00,
+ 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x85, 0xe8, 0xfe, 0xa4, 0x57, 0x70, 0xfe, 0x67, 0x18, 0x04,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x6d, 0x10, 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00,
+ 0xe6, 0x01, 0x6d, 0x10, 0x00, 0x00, 0x00, 0x01, 0xff, 0x18, 0x86, 0x08, 0x8d, 0xfa, 0x00, 0x04,
+ 0x8e, 0x7a, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x08, 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x6c, 0x85,
+ 0x4e, 0xfc, 0xef, 0xff, 0xff, 0x8c, 0x7f, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x6b, 0x1d,
+ 0x7f, 0xfd, 0x00, 0x03, 0xcf, 0xf8, 0xf8, 0x00, 0x4e, 0xfc, 0xef, 0xff, 0xfe, 0x99, 0x86, 0x08,
+ 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x86, 0x30, 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x72, 0x00, 0x00,
+ 0xfe, 0x88, 0xe6, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x1d, 0x46, 0x58,
+ 0xfe, 0x0d, 0x85, 0x70, 0xfd, 0xa5, 0x56, 0xf0, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7f, 0x79, 0x00, 0x02,
+ 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xf7, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01,
+ 0xff, 0x0a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xe0, 0xd8,
+ 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30,
+ 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x20,
+ 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01,
+ 0xff, 0xf7, 0x28, 0x00, 0x7e, 0x71, 0x00, 0x10, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x77, 0x28, 0x02,
+ 0xff, 0x0c, 0x85, 0x00, 0x4d, 0xed, 0x20, 0x00, 0xcc, 0x60, 0xdd, 0x00, 0x2f, 0x78, 0x08, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x69, 0x48,
+ 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x6c, 0x50,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x6d, 0xbd,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0, 0xff, 0x8c, 0x7f, 0xd8, 0xcf, 0xfc, 0xf2, 0x00,
+ 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28, 0xff, 0x8c, 0x7f, 0xc8, 0xcf, 0x78, 0xe8, 0x00,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x6c, 0xcd, 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0,
+ 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0, 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x84, 0xb0,
+ 0xfd, 0x0d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8, 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x6c, 0xdc, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x6d, 0xa8, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x6a, 0xe9, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0,
+ 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff,
+ 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x56, 0xf0, 0xaf, 0x7e, 0xf0, 0x02,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x6d, 0x89, 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02,
+ 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00,
+ 0xe6, 0x01, 0x6d, 0x91, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x6d, 0x64, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x6d, 0xbc, 0xf3, 0x82, 0x00, 0x02,
+ 0xe6, 0x01, 0x6d, 0x78, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x6a, 0xe8, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0x6d, 0xbc, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xb9, 0x50, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x6a, 0xe8, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x6d, 0xc8,
+ 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfb, 0x9c, 0x46, 0x58,
+ 0xfc, 0x8c, 0x85, 0x70, 0xfe, 0x24, 0x56, 0xf0, 0x2d, 0x5c, 0x0f, 0xfd, 0x7f, 0xe8, 0xff, 0xfd,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02,
+ 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc, 0xab, 0x7e, 0xe8, 0x05,
+ 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x7c, 0x30, 0xfe, 0x88, 0xe6, 0xd8, 0xfa, 0x9c, 0x46, 0x48,
+ 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7d, 0x68, 0xff, 0xfe,
+ 0x4f, 0x68, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xf5, 0x00, 0xff, 0xf7, 0x28, 0x0e,
+ 0x7d, 0xed, 0x00, 0x02, 0xfb, 0x77, 0x28, 0x12, 0xcf, 0xf4, 0xd8, 0x00, 0x9c, 0xf6, 0x00, 0x14,
+ 0x0e, 0x70, 0x10, 0x00, 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00,
+ 0xfd, 0xf7, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0x5c, 0x10, 0x00, 0xff, 0x8a, 0xe2, 0xd0,
+ 0xaf, 0x7e, 0xd0, 0x05, 0xfc, 0x88, 0xe0, 0xd8, 0xfe, 0x77, 0x18, 0x0a, 0xff, 0x9a, 0x00, 0x0e,
+ 0x8d, 0x76, 0x00, 0x2c, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x9b, 0x02, 0xfe, 0x58, 0xfa, 0xf7, 0x28, 0x20, 0xfc, 0x77, 0x28, 0x1e, 0xfb, 0x77, 0x28, 0x22,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0x33, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00, 0xfd, 0x09, 0xe6, 0xd8,
+ 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c, 0xfe, 0x6b, 0x28, 0x00,
+ 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10, 0x9e, 0x6a, 0x00, 0x08,
+ 0xcc, 0xe4, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfc, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0x2b, 0xdc, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02, 0x9b, 0xf6, 0x00, 0x38, 0xff, 0x0c, 0x85, 0x00,
+ 0x4c, 0xe5, 0x20, 0x00, 0xc5, 0x28, 0xcd, 0x00, 0xcf, 0x78, 0xb2, 0x00, 0x7f, 0xf9, 0xff, 0xe1,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8, 0xff, 0x0d, 0x85, 0x00,
+ 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x6f, 0x34, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48,
+ 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x08, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x6d, 0xdc, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x70, 0xa4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02,
+ 0xcc, 0x98, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x85, 0xe8, 0xfe, 0xa4, 0x57, 0x70,
+ 0xfe, 0x67, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x73, 0x44, 0xcd, 0x1c, 0x00, 0x00,
+ 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x73, 0x44, 0x00, 0x00, 0x00, 0x01, 0xff, 0x18, 0x86, 0x08,
+ 0x8d, 0xfa, 0x00, 0x04, 0x8e, 0x7a, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x08, 0x70, 0x6e, 0x00, 0x1f,
+ 0xea, 0x01, 0x72, 0xb9, 0x4e, 0xfc, 0xef, 0xff, 0xff, 0x8c, 0x7f, 0xd0, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x71, 0x51, 0x7f, 0xfd, 0x00, 0x03, 0xcf, 0xf8, 0xf8, 0x00, 0x4e, 0xfc, 0xef, 0xff,
+ 0xfe, 0x99, 0x86, 0x08, 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x86, 0x30, 0xab, 0x9a, 0xf8, 0x01,
+ 0x20, 0x72, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02,
+ 0xfd, 0x1d, 0x46, 0x58, 0xfe, 0x0d, 0x85, 0x70, 0xfd, 0xa5, 0x56, 0xf0, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00,
+ 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14,
+ 0xcf, 0x74, 0xf0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09,
+ 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xae, 0x7a, 0xf8, 0x05,
+ 0xfd, 0x88, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a,
+ 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0xff, 0x67, 0x28, 0x00,
+ 0x2f, 0xf8, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7e, 0x71, 0x00, 0x10, 0x9f, 0x66, 0x00, 0x08,
+ 0xcd, 0xec, 0xe2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x77, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0xed, 0x20, 0x00, 0xcc, 0x60, 0xdd, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x6f, 0x7c, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x72, 0x84, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x73, 0xf1, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0, 0xff, 0x8c, 0x7f, 0xd8,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28, 0xff, 0x8c, 0x7f, 0xc8,
+ 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x73, 0x01, 0xff, 0xa2, 0x02, 0x00,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0, 0xff, 0xa2, 0x02, 0x00,
+ 0xf3, 0x0d, 0x84, 0xb0, 0xfd, 0x0d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8, 0xc5, 0x28, 0xfd, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x73, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x73, 0xdc,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x71, 0x1d, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88,
+ 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x56, 0xf0,
+ 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x73, 0xbd, 0x00, 0x00, 0x00, 0x01,
+ 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04,
+ 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x73, 0xc5, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x73, 0x98, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x73, 0xf0,
+ 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x73, 0xac, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x71, 0x1c,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x73, 0xf0, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xb9, 0x50,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x71, 0x1c, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x86, 0x73, 0xfc, 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfb, 0x9c, 0x46, 0x58, 0xfc, 0x8c, 0x85, 0x70, 0xfe, 0x24, 0x56, 0xf0, 0x2d, 0x5c, 0x07, 0xfd,
+ 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03,
+ 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc,
+ 0xab, 0x7e, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x7c, 0x30, 0xfe, 0x88, 0xe6, 0xd8,
+ 0xfa, 0x9c, 0x46, 0x48, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7d, 0x68, 0xff, 0xfe, 0x4f, 0x68, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xff, 0xf7, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xfb, 0x77, 0x28, 0x12, 0xcf, 0xf4, 0xd8, 0x00,
+ 0x9c, 0xf6, 0x00, 0x14, 0x0e, 0x70, 0x08, 0x00, 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10,
+ 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xf7, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0x5c, 0x08, 0x00,
+ 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xd0, 0x05, 0xfc, 0x88, 0xe0, 0xd8, 0xfe, 0x77, 0x18, 0x0a,
+ 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x76, 0x00, 0x2c, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0xfa, 0xf7, 0x28, 0x20, 0xfc, 0x77, 0x28, 0x1e,
+ 0xfb, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00,
+ 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x33, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00,
+ 0xfd, 0x09, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c,
+ 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10,
+ 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfc, 0x89, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0x2b, 0xdc, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02, 0x9b, 0xf6, 0x00, 0x38,
+ 0xff, 0x0c, 0x85, 0x00, 0x4c, 0xe5, 0x20, 0x00, 0xc5, 0x28, 0xcd, 0x00, 0xcf, 0x78, 0xb2, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8,
+ 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x75, 0x68, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x85, 0xe8,
+ 0xfe, 0xa4, 0x57, 0x70, 0xfe, 0x67, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x78, 0x08,
+ 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x78, 0x08, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x18, 0x86, 0x08, 0x8d, 0xfa, 0x00, 0x04, 0x8e, 0x7a, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x08,
+ 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x77, 0x7d, 0x4e, 0xfc, 0xef, 0xff, 0xff, 0x8c, 0x7f, 0xd0,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x76, 0x15, 0x7f, 0xfd, 0x00, 0x03, 0xcf, 0xf8, 0xf8, 0x00,
+ 0x4e, 0xfc, 0xef, 0xff, 0xfe, 0x99, 0x86, 0x08, 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x86, 0x30,
+ 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x72, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8, 0xe6, 0x78, 0x00, 0x02,
+ 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x1d, 0x46, 0x58, 0xfe, 0x0d, 0x85, 0x70, 0xfd, 0xa5, 0x56, 0xf0,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f,
+ 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12,
+ 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10,
+ 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00,
+ 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22,
+ 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00,
+ 0xfc, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c,
+ 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7e, 0x71, 0x00, 0x10,
+ 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x89, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x77, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0xed, 0x20, 0x00,
+ 0xcc, 0x60, 0xdd, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x74, 0x10, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00,
+ 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x77, 0x48, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x78, 0xb5, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0,
+ 0xff, 0x8c, 0x7f, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28,
+ 0xff, 0x8c, 0x7f, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x77, 0xc5,
+ 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0,
+ 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x84, 0xb0, 0xfd, 0x0d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8,
+ 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x77, 0xd4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07,
+ 0xea, 0x01, 0x78, 0xa0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x75, 0xe1, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02,
+ 0xff, 0x1e, 0x56, 0xf0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x78, 0x81,
+ 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00,
+ 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x78, 0x89, 0xc0, 0x76, 0xe2, 0x00,
+ 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x78, 0x5c, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0x78, 0xb4, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x78, 0x70, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x75, 0xe0, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x78, 0xb4, 0xf3, 0x82, 0x00, 0x02,
+ 0xff, 0x88, 0xb9, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x75, 0xe0, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x78, 0xc0, 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02,
+ 0xff, 0x8c, 0x85, 0xe8, 0xfe, 0xa4, 0x57, 0x70, 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x7b, 0x38, 0xcc, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x7b, 0x38,
+ 0x00, 0x00, 0x00, 0x01, 0xfe, 0x18, 0x86, 0x08, 0x8b, 0xf2, 0x00, 0x04, 0x8c, 0xf2, 0x00, 0x00,
+ 0x0f, 0xf0, 0x00, 0x08, 0x70, 0x5e, 0x00, 0x1f, 0xea, 0x01, 0x7a, 0xad, 0x4d, 0x7c, 0xef, 0xff,
+ 0xff, 0x8c, 0x7f, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x79, 0x3d, 0x0d, 0xe0, 0x00, 0x03,
+ 0x7f, 0xfd, 0x00, 0x03, 0xcf, 0xf0, 0xf8, 0x00, 0x4d, 0x7c, 0xef, 0xff, 0x7f, 0xec, 0xff, 0xfd,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xec, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02,
+ 0xfd, 0x19, 0x86, 0x08, 0xce, 0xf8, 0xfd, 0x00, 0x90, 0xf2, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x02,
+ 0xff, 0x82, 0x7c, 0xcc, 0xad, 0x7e, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x78, 0x00, 0x02,
+ 0xfe, 0x88, 0xe6, 0xd8, 0x5f, 0xf8, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7d, 0xec, 0xff, 0xfe,
+ 0x4e, 0x6c, 0x03, 0xff, 0xfd, 0x77, 0x28, 0x12, 0x7f, 0x79, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xe5, 0x00, 0x0d, 0x78, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x0e, 0x9c, 0xf6, 0x00, 0x14,
+ 0xcf, 0x74, 0xf0, 0x00, 0x9b, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09,
+ 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xd8, 0x05, 0xfc, 0x88, 0xe0, 0xd8, 0xfe, 0x77, 0x18, 0x0a,
+ 0xff, 0xba, 0x00, 0x0e, 0x8d, 0xf6, 0x00, 0x2c, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9c, 0x02, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xf4, 0x77, 0x28, 0x1e,
+ 0xfc, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x31, 0x28, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00,
+ 0xfd, 0x89, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c,
+ 0xfe, 0x6f, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10,
+ 0x9e, 0x6e, 0x00, 0x08, 0xcc, 0xe4, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfc, 0x89, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0x23, 0xe0, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02, 0x93, 0xf6, 0x00, 0x38,
+ 0xff, 0x0c, 0x85, 0x00, 0x4c, 0xe5, 0x20, 0x00, 0xc5, 0x28, 0xcd, 0x00, 0xcf, 0x78, 0xc2, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8,
+ 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x7a, 0x78, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x7b, 0xe5, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0,
+ 0xff, 0x8c, 0x7f, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28,
+ 0xff, 0x8c, 0x7f, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x7a, 0xf5,
+ 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0,
+ 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x84, 0xb0, 0xfc, 0x0d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8,
+ 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x7b, 0x04, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07,
+ 0xea, 0x01, 0x7b, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x79, 0x05, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02,
+ 0xff, 0x1e, 0x56, 0xf0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x7b, 0xb1,
+ 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00,
+ 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x7b, 0xb9, 0xc0, 0x76, 0xe2, 0x00,
+ 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x7b, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0x7b, 0xe4, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x7b, 0xa0, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x79, 0x04, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x7b, 0xe4, 0xf3, 0x82, 0x00, 0x02,
+ 0xff, 0x88, 0xb9, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x79, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x7b, 0xf0, 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfb, 0x9c, 0x46, 0x58, 0xfd, 0x0c, 0x85, 0x74, 0xfc, 0x0c, 0x7c, 0x30,
+ 0x2e, 0x5c, 0x1f, 0xfd, 0x7f, 0xf0, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x4f, 0xf0, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xff, 0x82, 0x7c, 0xcc, 0xac, 0xfe, 0xe8, 0x05, 0x20, 0x6a, 0x00, 0x00, 0xfb, 0x24, 0x56, 0xf4,
+ 0xfe, 0x88, 0xe6, 0xd8, 0xfa, 0x9c, 0x46, 0x48, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x70, 0xff, 0xfe, 0x4f, 0x70, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xcf, 0xf4, 0xd8, 0x00,
+ 0xfc, 0xf7, 0x28, 0x12, 0x9d, 0x76, 0x00, 0x14, 0x9b, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10,
+ 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xf7, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0x5c, 0x20, 0x00,
+ 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xe0, 0x05, 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c,
+ 0xff, 0x9a, 0x00, 0x0e, 0xfe, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0xfa, 0xf7, 0x28, 0x20, 0xfc, 0x77, 0x28, 0x1e,
+ 0xfb, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00,
+ 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x34, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00,
+ 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c,
+ 0xfe, 0x67, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10,
+ 0x9e, 0x66, 0x00, 0x08, 0xcd, 0x68, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0x2b, 0xdc, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02, 0x9b, 0xf6, 0x00, 0x38,
+ 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xc5, 0x28, 0xd5, 0x00, 0xcf, 0x78, 0xb2, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8,
+ 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x7d, 0x58, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02,
+ 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x18, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14,
+ 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00,
+ 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22,
+ 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00,
+ 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00,
+ 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00,
+ 0xfd, 0xfb, 0x28, 0x1c, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10,
+ 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00,
+ 0xce, 0xa8, 0xd5, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x7c, 0x04, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00,
+ 0xff, 0x81, 0x04, 0x34, 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x7e, 0xc8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02,
+ 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x10, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14,
+ 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00,
+ 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22,
+ 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00,
+ 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00,
+ 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00,
+ 0xfd, 0xfb, 0x28, 0x1c, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10,
+ 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00,
+ 0xce, 0xa8, 0xd5, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x7d, 0xa0, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00,
+ 0xff, 0x81, 0x04, 0x34, 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x80, 0x38, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02,
+ 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x08, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14,
+ 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00,
+ 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22,
+ 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00,
+ 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00,
+ 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00,
+ 0xfd, 0xfb, 0x28, 0x1c, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10,
+ 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00,
+ 0xce, 0xa8, 0xd5, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x7f, 0x10, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00,
+ 0xff, 0x81, 0x04, 0x34, 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x81, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0xfe, 0x40, 0x02, 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x85, 0xe8,
+ 0xfe, 0xa4, 0x57, 0x70, 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x84, 0x68,
+ 0xcc, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x84, 0x68, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x98, 0x86, 0x08, 0x0f, 0xf4, 0x00, 0x08, 0x4e, 0x7c, 0xef, 0xff, 0x8c, 0xf6, 0x00, 0x04,
+ 0x8d, 0x72, 0x00, 0x04, 0x8d, 0xf6, 0x00, 0x00, 0x8b, 0x72, 0x00, 0x00, 0x0f, 0x70, 0x00, 0x08,
+ 0xcf, 0xe4, 0xd5, 0x00, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x01, 0x83, 0xdd, 0x4f, 0x78, 0xef, 0xff,
+ 0xff, 0x8c, 0x7f, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x82, 0x69, 0x7f, 0xfd, 0x00, 0x03,
+ 0xcf, 0xf4, 0xf8, 0x00, 0x4f, 0x7c, 0xef, 0xff, 0xff, 0x19, 0x86, 0x08, 0x90, 0xf6, 0x00, 0x04,
+ 0xfd, 0x8d, 0x85, 0x70, 0xfc, 0xa5, 0x56, 0xf0, 0x90, 0xf2, 0x00, 0x04, 0xff, 0x9a, 0x86, 0x30,
+ 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8, 0xe6, 0x78, 0x00, 0x02,
+ 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x25, 0x56, 0xf4, 0xfc, 0x1d, 0x46, 0x58, 0xfb, 0x0d, 0x85, 0x74,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f,
+ 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12,
+ 0x9d, 0xf6, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00, 0x9c, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10,
+ 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00,
+ 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22,
+ 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00,
+ 0xfc, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c,
+ 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7e, 0x71, 0x00, 0x10,
+ 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x89, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x77, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0xed, 0x20, 0x00,
+ 0xcc, 0x60, 0xdd, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x80, 0x80, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00,
+ 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x83, 0xa8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x85, 0x15, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0,
+ 0xff, 0x8c, 0x7f, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28,
+ 0xff, 0x8c, 0x7f, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x84, 0x25,
+ 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0,
+ 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x84, 0xb0, 0xfc, 0x0d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8,
+ 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x84, 0x34, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07,
+ 0xea, 0x01, 0x85, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x82, 0x21, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02,
+ 0xff, 0x1e, 0x56, 0xf0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x84, 0xe1,
+ 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00,
+ 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x84, 0xe9, 0xc0, 0x76, 0xe2, 0x00,
+ 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x84, 0xbc, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0x85, 0x14, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x84, 0xd0, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x82, 0x20, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x85, 0x14, 0xf3, 0x82, 0x00, 0x02,
+ 0xff, 0x88, 0xb9, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x82, 0x20, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x85, 0x20, 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfb, 0x9c, 0x46, 0x58, 0xfd, 0x0c, 0x85, 0x78, 0xfc, 0x0c, 0x7c, 0x30,
+ 0x2e, 0x5c, 0x1f, 0xfd, 0x7f, 0xf0, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x4f, 0xf0, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xff, 0x82, 0x7c, 0xcc, 0xac, 0xfe, 0xe8, 0x05, 0x20, 0x6a, 0x00, 0x00, 0xfb, 0x24, 0x56, 0xf8,
+ 0xfe, 0x88, 0xe6, 0xd8, 0xfa, 0x9c, 0x46, 0x48, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x70, 0xff, 0xfe, 0x4f, 0x70, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xcf, 0xf4, 0xd8, 0x00,
+ 0xfc, 0xf7, 0x28, 0x12, 0x9d, 0x76, 0x00, 0x14, 0x9b, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10,
+ 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xf7, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0x5c, 0x20, 0x00,
+ 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xe0, 0x05, 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c,
+ 0xff, 0x9a, 0x00, 0x0e, 0xfe, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0xfa, 0xf7, 0x28, 0x20, 0xfc, 0x77, 0x28, 0x1e,
+ 0xfb, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00,
+ 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x35, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00,
+ 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c,
+ 0xfe, 0x67, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10,
+ 0x9e, 0x66, 0x00, 0x08, 0xcd, 0x68, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0x2b, 0xdc, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02, 0x9b, 0xf6, 0x00, 0x38,
+ 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xc5, 0x28, 0xd5, 0x00, 0xcf, 0x78, 0xb2, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8,
+ 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x86, 0x88, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x74, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x56, 0xf4, 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02,
+ 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x08, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14,
+ 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00,
+ 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22,
+ 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00,
+ 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00,
+ 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00,
+ 0xfd, 0xfb, 0x28, 0x1c, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10,
+ 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00,
+ 0xce, 0xa8, 0xd5, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x85, 0x34, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00,
+ 0xff, 0x81, 0x04, 0x34, 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x87, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x74, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xff, 0x08, 0xe6, 0xd8, 0xfd, 0x24, 0x56, 0xf4, 0xe6, 0x70, 0x00, 0x02,
+ 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0xce, 0xf8, 0xe0, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0x9d, 0xfa, 0x00, 0x14, 0xff, 0xfb, 0x28, 0x12, 0x9d, 0x76, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x86, 0xd0, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x89, 0x64, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48,
+ 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x08, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x88, 0x40, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x8a, 0xd4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02,
+ 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x85, 0xe8, 0xfe, 0xa4, 0x57, 0x70,
+ 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x8d, 0xb4, 0xcb, 0x1c, 0x00, 0x00,
+ 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x8d, 0xb4, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x98, 0x86, 0x08,
+ 0x0f, 0xf4, 0x00, 0x08, 0x4e, 0x7c, 0xef, 0xff, 0x0f, 0x70, 0x00, 0x08, 0x4d, 0xf8, 0xef, 0xff,
+ 0x8c, 0x76, 0x00, 0x04, 0x8b, 0xf2, 0x00, 0x04, 0x8a, 0x6e, 0x00, 0x04, 0x8c, 0xf6, 0x00, 0x00,
+ 0xcf, 0xe0, 0xbd, 0x00, 0x8d, 0x72, 0x00, 0x00, 0x8a, 0xee, 0x00, 0x00, 0x0f, 0x6c, 0x00, 0x08,
+ 0xcf, 0xfc, 0xa5, 0x00, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x01, 0x8d, 0x29, 0x4f, 0x78, 0xef, 0xff,
+ 0xff, 0x8c, 0x7f, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x8b, 0xa9, 0x7f, 0xfd, 0x00, 0x03,
+ 0xcf, 0xf4, 0xf8, 0x00, 0x4f, 0x7c, 0xef, 0xff, 0xff, 0x19, 0x86, 0x08, 0x90, 0xf6, 0x00, 0x04,
+ 0xfc, 0x25, 0x56, 0xf0, 0xfc, 0x8d, 0x85, 0x70, 0x90, 0xf2, 0x00, 0x04, 0xfd, 0x0d, 0x85, 0x74,
+ 0xfb, 0xa5, 0x56, 0xf4, 0x90, 0xee, 0x00, 0x04, 0xff, 0x9a, 0x86, 0x30, 0xab, 0x9a, 0xf8, 0x01,
+ 0x20, 0x66, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02,
+ 0xfa, 0x8d, 0x85, 0x78, 0xfa, 0x25, 0x56, 0xf8, 0xfb, 0x1d, 0x46, 0x58, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00,
+ 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9c, 0xf6, 0x00, 0x14,
+ 0xcf, 0x74, 0xf0, 0x00, 0x9c, 0x7a, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09,
+ 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xae, 0x7a, 0xf8, 0x05,
+ 0xfd, 0x88, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a,
+ 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0xff, 0x67, 0x28, 0x00,
+ 0x2f, 0xf8, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7e, 0x71, 0x00, 0x10, 0x9f, 0x66, 0x00, 0x08,
+ 0xcd, 0xec, 0xe2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x77, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0xed, 0x20, 0x00, 0xcc, 0x60, 0xdd, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x89, 0xac, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x8c, 0xf4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x8e, 0x61, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0, 0xff, 0x8c, 0x7f, 0xd8,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28, 0xff, 0x8c, 0x7f, 0xc8,
+ 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x8d, 0x71, 0xff, 0xa2, 0x02, 0x00,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0, 0xff, 0xa2, 0x02, 0x00,
+ 0xf3, 0x0d, 0x84, 0xb0, 0xfb, 0x0d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8, 0xc5, 0x28, 0xfd, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x8d, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x8e, 0x4c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x8b, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88,
+ 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x56, 0xf0,
+ 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x8e, 0x2d, 0x00, 0x00, 0x00, 0x01,
+ 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04,
+ 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x8e, 0x35, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x8e, 0x08, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x8e, 0x60,
+ 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x8e, 0x1c, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x8b, 0x4c,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x8e, 0x60, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xb9, 0x50,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x8b, 0x4c, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x86, 0x8e, 0x6c, 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfb, 0x9c, 0x46, 0x58, 0xfc, 0x8c, 0x85, 0x74, 0xfe, 0x24, 0x56, 0xf4, 0x2d, 0x5c, 0x17, 0xfd,
+ 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03,
+ 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc,
+ 0xab, 0x7e, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x7c, 0x30, 0xfe, 0x88, 0xe6, 0xd8,
+ 0xfa, 0x9c, 0x46, 0x48, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7d, 0x68, 0xff, 0xfe, 0x4f, 0x68, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xff, 0xf7, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xfb, 0x77, 0x28, 0x12, 0xcf, 0xf4, 0xd8, 0x00,
+ 0x9c, 0xf6, 0x00, 0x14, 0x0e, 0x70, 0x08, 0x00, 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10,
+ 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xf7, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0x5c, 0x18, 0x00,
+ 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xd0, 0x05, 0xfc, 0x88, 0xe0, 0xd8, 0xfe, 0x77, 0x18, 0x0a,
+ 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x76, 0x00, 0x2c, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0xfa, 0xf7, 0x28, 0x20, 0xfc, 0x77, 0x28, 0x1e,
+ 0xfb, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00,
+ 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x34, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00,
+ 0xfd, 0x09, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c,
+ 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10,
+ 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfc, 0x89, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0x2b, 0xdc, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02, 0x9b, 0xf6, 0x00, 0x38,
+ 0xff, 0x0c, 0x85, 0x00, 0x4c, 0xe5, 0x20, 0x00, 0xc5, 0x28, 0xcd, 0x00, 0xcf, 0x78, 0xb2, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8,
+ 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x8f, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x74, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xff, 0x08, 0xe6, 0xd8, 0xfd, 0x24, 0x56, 0xf4, 0xe6, 0x70, 0x00, 0x02,
+ 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0xce, 0xf8, 0xe0, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0x9d, 0xfa, 0x00, 0x14, 0xff, 0xfb, 0x28, 0x12, 0x9d, 0x76, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x8e, 0x80, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x91, 0x44, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48,
+ 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x08, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x90, 0x20, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x92, 0xb4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02,
+ 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x85, 0xe8, 0xfe, 0xa4, 0x57, 0x70,
+ 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x95, 0x74, 0xcc, 0x1c, 0x00, 0x00,
+ 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x95, 0x74, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x98, 0x86, 0x08,
+ 0x0f, 0xf4, 0x00, 0x08, 0x4e, 0x7c, 0xef, 0xff, 0x8c, 0xf6, 0x00, 0x04, 0x8d, 0x72, 0x00, 0x04,
+ 0x8d, 0xf6, 0x00, 0x00, 0x8b, 0x72, 0x00, 0x00, 0x0f, 0x70, 0x00, 0x08, 0xcf, 0xe4, 0xd5, 0x00,
+ 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x01, 0x94, 0xe9, 0x4f, 0x78, 0xef, 0xff, 0xff, 0x8c, 0x7f, 0xd0,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x93, 0x75, 0x7f, 0xfd, 0x00, 0x03, 0xcf, 0xf4, 0xf8, 0x00,
+ 0x4f, 0x7c, 0xef, 0xff, 0xff, 0x19, 0x86, 0x08, 0x90, 0xf6, 0x00, 0x04, 0xfd, 0x8d, 0x85, 0x70,
+ 0xfc, 0xa5, 0x56, 0xf0, 0x90, 0xf2, 0x00, 0x04, 0xff, 0x9a, 0x86, 0x30, 0xab, 0x9a, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02,
+ 0xfd, 0x25, 0x56, 0xf4, 0xfc, 0x1d, 0x46, 0x58, 0xfb, 0x0d, 0x85, 0x74, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00,
+ 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9d, 0xf6, 0x00, 0x14,
+ 0xcf, 0x74, 0xf0, 0x00, 0x9c, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09,
+ 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xae, 0x7a, 0xf8, 0x05,
+ 0xfd, 0x88, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a,
+ 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0xff, 0x67, 0x28, 0x00,
+ 0x2f, 0xf8, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7e, 0x71, 0x00, 0x10, 0x9f, 0x66, 0x00, 0x08,
+ 0xcd, 0xec, 0xe2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x77, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0xed, 0x20, 0x00, 0xcc, 0x60, 0xdd, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x91, 0x8c, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x94, 0xb4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x96, 0x21, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0, 0xff, 0x8c, 0x7f, 0xd8,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28, 0xff, 0x8c, 0x7f, 0xc8,
+ 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x95, 0x31, 0xff, 0xa2, 0x02, 0x00,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0, 0xff, 0xa2, 0x02, 0x00,
+ 0xf3, 0x0d, 0x84, 0xb0, 0xfc, 0x0d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8, 0xc5, 0x28, 0xfd, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x95, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x96, 0x0c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x93, 0x2d, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88,
+ 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x56, 0xf0,
+ 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x95, 0xed, 0x00, 0x00, 0x00, 0x01,
+ 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04,
+ 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x95, 0xf5, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x95, 0xc8, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x96, 0x20,
+ 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x95, 0xdc, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x93, 0x2c,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x96, 0x20, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xb9, 0x50,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x93, 0x2c, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x86, 0x96, 0x2c, 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfb, 0x9c, 0x46, 0x58, 0xfd, 0x0c, 0x85, 0x74, 0xfc, 0x0c, 0x7c, 0x30, 0x2e, 0x5c, 0x0f, 0xfd,
+ 0x7f, 0xf0, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xf0, 0x00, 0x03,
+ 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc,
+ 0xac, 0xfe, 0xe8, 0x05, 0x20, 0x6a, 0x00, 0x00, 0xfb, 0x24, 0x56, 0xf4, 0xfe, 0x88, 0xe6, 0xd8,
+ 0xfa, 0x9c, 0x46, 0x48, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7e, 0x70, 0xff, 0xfe, 0x4f, 0x70, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xff, 0xf7, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xcf, 0xf4, 0xd8, 0x00, 0xfc, 0xf7, 0x28, 0x12,
+ 0x9d, 0x76, 0x00, 0x14, 0x9b, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00,
+ 0xfd, 0xf7, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0x5c, 0x10, 0x00, 0xff, 0x8a, 0xe2, 0xd0,
+ 0xaf, 0x7e, 0xe0, 0x05, 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0x9a, 0x00, 0x0e,
+ 0xfe, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x9b, 0x02, 0xfe, 0x58, 0xfa, 0xf7, 0x28, 0x20, 0xfc, 0x77, 0x28, 0x1e, 0xfb, 0x77, 0x28, 0x22,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0x34, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c, 0xfe, 0x67, 0x28, 0x00,
+ 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10, 0x9e, 0x66, 0x00, 0x08,
+ 0xcd, 0x68, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0x2b, 0xdc, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02, 0x9b, 0xf6, 0x00, 0x38, 0xff, 0x0c, 0x85, 0x00,
+ 0x4d, 0x69, 0x20, 0x00, 0xc5, 0x28, 0xd5, 0x00, 0xcf, 0x78, 0xb2, 0x00, 0x7f, 0xf9, 0xff, 0xe1,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8, 0xff, 0x0d, 0x85, 0x00,
+ 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x97, 0x94, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x46, 0x48,
+ 0xfd, 0x8c, 0x85, 0x70, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x56, 0xf0, 0xff, 0x08, 0xe6, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x08, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x96, 0x40, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x99, 0x04, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02,
+ 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x85, 0xe8, 0xfe, 0xa4, 0x57, 0x70,
+ 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x9b, 0xc4, 0xcc, 0x1c, 0x00, 0x00,
+ 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x9b, 0xc4, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x98, 0x86, 0x08,
+ 0x0f, 0xf4, 0x00, 0x08, 0x4e, 0x7c, 0xef, 0xff, 0x8c, 0xf6, 0x00, 0x04, 0x8d, 0x72, 0x00, 0x04,
+ 0x8d, 0xf6, 0x00, 0x00, 0x8b, 0x72, 0x00, 0x00, 0x0f, 0x70, 0x00, 0x08, 0xcf, 0xe4, 0xd5, 0x00,
+ 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x01, 0x9b, 0x39, 0x4f, 0x78, 0xef, 0xff, 0xff, 0x8c, 0x7f, 0xd0,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x99, 0xc5, 0x7f, 0xfd, 0x00, 0x03, 0xcf, 0xf4, 0xf8, 0x00,
+ 0x4f, 0x7c, 0xef, 0xff, 0xff, 0x19, 0x86, 0x08, 0x90, 0xf6, 0x00, 0x04, 0xfd, 0x8d, 0x85, 0x70,
+ 0xfc, 0xa5, 0x56, 0xf0, 0x90, 0xf2, 0x00, 0x04, 0xff, 0x9a, 0x86, 0x30, 0xab, 0x9a, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02,
+ 0xfd, 0x25, 0x56, 0xf4, 0xfc, 0x1d, 0x46, 0x58, 0xfb, 0x0d, 0x85, 0x74, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00,
+ 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9d, 0xf6, 0x00, 0x14,
+ 0xcf, 0x74, 0xf0, 0x00, 0x9c, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09,
+ 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xae, 0x7a, 0xf8, 0x05,
+ 0xfd, 0x88, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a,
+ 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0xff, 0x67, 0x28, 0x00,
+ 0x2f, 0xf8, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7e, 0x71, 0x00, 0x10, 0x9f, 0x66, 0x00, 0x08,
+ 0xcd, 0xec, 0xe2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x77, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0xed, 0x20, 0x00, 0xcc, 0x60, 0xdd, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0x97, 0xdc, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x9b, 0x04, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x9c, 0x71, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0, 0xff, 0x8c, 0x7f, 0xd8,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28, 0xff, 0x8c, 0x7f, 0xc8,
+ 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x9b, 0x81, 0xff, 0xa2, 0x02, 0x00,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0, 0xff, 0xa2, 0x02, 0x00,
+ 0xf3, 0x0d, 0x84, 0xb0, 0xfc, 0x0d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8, 0xc5, 0x28, 0xfd, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x9b, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x9c, 0x5c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x99, 0x7d, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88,
+ 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x56, 0xf0,
+ 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x9c, 0x3d, 0x00, 0x00, 0x00, 0x01,
+ 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04,
+ 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x9c, 0x45, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x9c, 0x70,
+ 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x9c, 0x2c, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x99, 0x7c,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x9c, 0x70, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xb9, 0x50,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x99, 0x7c, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x86, 0x9c, 0x7c, 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfb, 0x9c, 0x46, 0x58, 0xfc, 0x8c, 0x85, 0x70, 0xfe, 0x24, 0x56, 0xf0, 0x2d, 0x5c, 0x07, 0xfd,
+ 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03,
+ 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc,
+ 0xab, 0x7e, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x7c, 0x30, 0xfe, 0x88, 0xe6, 0xd8,
+ 0xfa, 0x9c, 0x46, 0x48, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7d, 0x68, 0xff, 0xfe, 0x4f, 0x68, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xff, 0xf7, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xfb, 0x77, 0x28, 0x12, 0xcf, 0xf4, 0xd8, 0x00,
+ 0x9c, 0xf6, 0x00, 0x14, 0x0e, 0x70, 0x08, 0x00, 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10,
+ 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xf7, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0x5c, 0x08, 0x00,
+ 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xd0, 0x05, 0xfc, 0x88, 0xe0, 0xd8, 0xfe, 0x77, 0x18, 0x0a,
+ 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x76, 0x00, 0x2c, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0xfa, 0xf7, 0x28, 0x20, 0xfc, 0x77, 0x28, 0x1e,
+ 0xfb, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00,
+ 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x33, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00,
+ 0xfd, 0x09, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c,
+ 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10,
+ 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfc, 0x89, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0x2b, 0xdc, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02, 0x9b, 0xf6, 0x00, 0x38,
+ 0xff, 0x0c, 0x85, 0x00, 0x4c, 0xe5, 0x20, 0x00, 0xc5, 0x28, 0xcd, 0x00, 0xcf, 0x78, 0xb2, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8,
+ 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x9d, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x85, 0xe8,
+ 0xfe, 0xa4, 0x57, 0x70, 0xfe, 0x67, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0xa0, 0x88,
+ 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0xa0, 0x88, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x18, 0x86, 0x08, 0x8d, 0xfa, 0x00, 0x04, 0x8e, 0x7a, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x08,
+ 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x9f, 0xfd, 0x4e, 0xfc, 0xef, 0xff, 0xff, 0x8c, 0x7f, 0xd0,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x9e, 0x95, 0x7f, 0xfd, 0x00, 0x03, 0xcf, 0xf8, 0xf8, 0x00,
+ 0x4e, 0xfc, 0xef, 0xff, 0xfe, 0x99, 0x86, 0x08, 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x86, 0x30,
+ 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x72, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8, 0xe6, 0x78, 0x00, 0x02,
+ 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x1d, 0x46, 0x58, 0xfe, 0x0d, 0x85, 0x70, 0xfd, 0xa5, 0x56, 0xf0,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f,
+ 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12,
+ 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10,
+ 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00,
+ 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22,
+ 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00,
+ 0xfc, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c,
+ 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7e, 0x71, 0x00, 0x10,
+ 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x89, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x77, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0xed, 0x20, 0x00,
+ 0xcc, 0x60, 0xdd, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0x9c, 0x90, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00,
+ 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x9f, 0xc8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xa1, 0x35, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0,
+ 0xff, 0x8c, 0x7f, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28,
+ 0xff, 0x8c, 0x7f, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0xa0, 0x45,
+ 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0,
+ 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x84, 0xb0, 0xfd, 0x0d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8,
+ 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xa0, 0x54, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07,
+ 0xea, 0x01, 0xa1, 0x20, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x9e, 0x61, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02,
+ 0xff, 0x1e, 0x56, 0xf0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0xa1, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00,
+ 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0xa1, 0x09, 0xc0, 0x76, 0xe2, 0x00,
+ 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0xa0, 0xdc, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0xa1, 0x34, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0xa0, 0xf0, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x9e, 0x60, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xa1, 0x34, 0xf3, 0x82, 0x00, 0x02,
+ 0xff, 0x88, 0xb9, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x9e, 0x60, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0xa1, 0x40, 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfb, 0x9c, 0x46, 0x58, 0xfd, 0x0c, 0x85, 0x78, 0xfc, 0x0c, 0x7c, 0x30,
+ 0x2e, 0x5c, 0x0f, 0xfd, 0x7f, 0xf0, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x4f, 0xf0, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xff, 0x82, 0x7c, 0xcc, 0xac, 0xfe, 0xe8, 0x05, 0x20, 0x6a, 0x00, 0x00, 0xfb, 0x24, 0x56, 0xf8,
+ 0xfe, 0x88, 0xe6, 0xd8, 0xfa, 0x9c, 0x46, 0x48, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x70, 0xff, 0xfe, 0x4f, 0x70, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xcf, 0xf4, 0xd8, 0x00,
+ 0xfc, 0xf7, 0x28, 0x12, 0x9d, 0x76, 0x00, 0x14, 0x9b, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10,
+ 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xf7, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0x5c, 0x10, 0x00,
+ 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xe0, 0x05, 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c,
+ 0xff, 0x9a, 0x00, 0x0e, 0xfe, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0xfa, 0xf7, 0x28, 0x20, 0xfc, 0x77, 0x28, 0x1e,
+ 0xfb, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00,
+ 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x35, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00,
+ 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c,
+ 0xfe, 0x67, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7f, 0x79, 0x00, 0x10,
+ 0x9e, 0x66, 0x00, 0x08, 0xcd, 0x68, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0x2b, 0xdc, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02, 0x9b, 0xf6, 0x00, 0x38,
+ 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xc5, 0x28, 0xd5, 0x00, 0xcf, 0x78, 0xb2, 0x00,
+ 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xfe, 0x8d, 0x84, 0xa8,
+ 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xa2, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x46, 0x48, 0xfd, 0x8c, 0x85, 0x74, 0xff, 0x9a, 0x86, 0x30, 0xab, 0xe2, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xff, 0x08, 0xe6, 0xd8, 0xfd, 0x24, 0x56, 0xf4, 0xe6, 0x70, 0x00, 0x02,
+ 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x71, 0x00, 0x02, 0xce, 0xf8, 0xe0, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0x9d, 0xfa, 0x00, 0x14, 0xff, 0xfb, 0x28, 0x12, 0x9d, 0x76, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xe0, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x9c, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfe, 0xe7, 0x28, 0x00, 0xfd, 0xfb, 0x28, 0x1c,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xce, 0xa8, 0xd5, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0xa1, 0x54, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x74, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xa4, 0x14, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02,
+ 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x85, 0xe8, 0xfe, 0xa4, 0x57, 0x70,
+ 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0xa6, 0xec, 0xcb, 0x1c, 0x00, 0x00,
+ 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0xa6, 0xec, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x98, 0x86, 0x08,
+ 0x0f, 0xf4, 0x00, 0x08, 0x4e, 0x7c, 0xef, 0xff, 0x0f, 0x70, 0x00, 0x08, 0x4d, 0xf8, 0xef, 0xff,
+ 0x8a, 0x76, 0x00, 0x04, 0x8c, 0xf2, 0x00, 0x04, 0x8c, 0x6e, 0x00, 0x04, 0x8a, 0xf6, 0x00, 0x00,
+ 0xcf, 0xd0, 0xcd, 0x00, 0x8d, 0x72, 0x00, 0x00, 0x89, 0xee, 0x00, 0x00, 0x0f, 0x6c, 0x00, 0x08,
+ 0xcf, 0xfc, 0xc5, 0x00, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x01, 0xa6, 0x61, 0x4f, 0x78, 0xef, 0xff,
+ 0xff, 0x8c, 0x7f, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xa4, 0xe9, 0x7f, 0xfd, 0x00, 0x03,
+ 0xcf, 0xf4, 0xf8, 0x00, 0x4f, 0x7c, 0xef, 0xff, 0xff, 0x19, 0x86, 0x08, 0x90, 0xf6, 0x00, 0x04,
+ 0x90, 0xf2, 0x00, 0x04, 0xfd, 0x0d, 0x85, 0x74, 0xfc, 0xa5, 0x56, 0xf4, 0x90, 0xee, 0x00, 0x04,
+ 0xff, 0x9a, 0x86, 0x30, 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x56, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8,
+ 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02, 0xfc, 0x25, 0x56, 0xf8, 0xf9, 0x8d, 0x85, 0x78,
+ 0xfb, 0x1d, 0x46, 0x58, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10,
+ 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xf7, 0x28, 0x12, 0x9a, 0xf6, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00, 0x9a, 0x7a, 0x00, 0x14,
+ 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xe2, 0xd0,
+ 0xff, 0x82, 0x02, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20,
+ 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x20, 0x9f, 0xf6, 0x00, 0x04,
+ 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0x0e, 0x70, 0x00, 0x01,
+ 0xfe, 0x77, 0x28, 0x1c, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00,
+ 0x7e, 0x71, 0x00, 0x10, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfd, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x77, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00,
+ 0x4d, 0xed, 0x20, 0x00, 0xcc, 0x60, 0xdd, 0x00, 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x86, 0xa2, 0xf0, 0xfb, 0x9d, 0x46, 0x48,
+ 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xa6, 0x2c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x80, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xa7, 0x99, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x1c, 0x46, 0xc0, 0xff, 0x8c, 0x7f, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe,
+ 0xff, 0x0c, 0x4c, 0x28, 0xff, 0x8c, 0x7f, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0xa6, 0xa9, 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8,
+ 0xff, 0x8d, 0x4b, 0xc0, 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x84, 0xb0, 0xfb, 0x0d, 0x84, 0xb4,
+ 0xf4, 0x0d, 0x84, 0xb8, 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xa6, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48,
+ 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0xa7, 0x84, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xa4, 0x8d,
+ 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x56, 0xf0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0xa7, 0x65, 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04,
+ 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0xa7, 0x6d,
+ 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0xa7, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xa7, 0x98, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0xa7, 0x54,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0xa4, 0x8c, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xa7, 0x98,
+ 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xb9, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xa4, 0x8c,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0xa7, 0xa4, 0xe0, 0x01, 0x3d, 0x44,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfb, 0x9c, 0x46, 0x58, 0xfd, 0x0c, 0x85, 0x74,
+ 0xfc, 0x0c, 0x7c, 0x30, 0x2e, 0x5c, 0x07, 0xfd, 0x7f, 0xf0, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xf0, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc, 0xac, 0xfe, 0xe8, 0x05, 0x20, 0x6a, 0x00, 0x00,
+ 0xfb, 0x24, 0x56, 0xf4, 0xfe, 0x88, 0xe6, 0xd8, 0xfa, 0x9c, 0x46, 0x48, 0xe6, 0x6c, 0x00, 0x02,
+ 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7e, 0x70, 0xff, 0xfe, 0x4f, 0x70, 0x03, 0xff,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xf5, 0x00, 0xff, 0xf7, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02,
+ 0xcf, 0xf4, 0xd8, 0x00, 0xfc, 0xf7, 0x28, 0x12, 0x9d, 0x76, 0x00, 0x14, 0x9b, 0x7e, 0x00, 0x14,
+ 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xf7, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe,
+ 0x2b, 0x5c, 0x08, 0x00, 0xff, 0x8a, 0xe2, 0xd0, 0xaf, 0x7e, 0xe0, 0x05, 0xfd, 0x08, 0xe0, 0xd8,
+ 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0x9a, 0x00, 0x0e, 0xfe, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30,
+ 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0xfa, 0xf7, 0x28, 0x20,
+ 0xfc, 0x77, 0x28, 0x1e, 0xfb, 0x77, 0x28, 0x22, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x34, 0x20, 0x9f, 0xf6, 0x00, 0x04,
+ 0xce, 0x70, 0xf0, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0x70, 0x0f, 0xff, 0x0f, 0x78, 0x00, 0x01,
+ 0xff, 0x77, 0x28, 0x1c, 0xfe, 0x67, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00,
+ 0x7f, 0x79, 0x00, 0x10, 0x9e, 0x66, 0x00, 0x08, 0xcd, 0x68, 0xf2, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0x2b, 0xdc, 0x00, 0x02, 0xf0, 0x77, 0x28, 0x02,
+ 0x9b, 0xf6, 0x00, 0x38, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0x69, 0x20, 0x00, 0xc5, 0x28, 0xd5, 0x00,
+ 0xcf, 0x78, 0xb2, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xfe, 0x8d, 0x84, 0xa8, 0xff, 0x0d, 0x85, 0x00, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xa9, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02,
+ 0xff, 0x8c, 0x85, 0xe8, 0xfe, 0xa4, 0x57, 0x70, 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0xab, 0xc4, 0xcc, 0x9c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0xab, 0xc4,
+ 0x00, 0x00, 0x00, 0x01, 0xfe, 0x98, 0x86, 0x08, 0x0f, 0xf4, 0x00, 0x08, 0x4e, 0x7c, 0xef, 0xff,
+ 0x8b, 0x76, 0x00, 0x04, 0x8d, 0xf2, 0x00, 0x04, 0x8c, 0x76, 0x00, 0x00, 0x8d, 0x72, 0x00, 0x00,
+ 0x0f, 0x70, 0x00, 0x08, 0xcf, 0xd8, 0xdd, 0x00, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x01, 0xab, 0x39,
+ 0x4f, 0x78, 0xef, 0xff, 0xff, 0x8c, 0x7f, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xa9, 0xcd,
+ 0x7f, 0xfd, 0x00, 0x03, 0xcf, 0xf4, 0xf8, 0x00, 0x4f, 0x7c, 0xef, 0xff, 0xff, 0x19, 0x86, 0x08,
+ 0x90, 0xf6, 0x00, 0x04, 0x90, 0xf2, 0x00, 0x04, 0xff, 0x9a, 0x86, 0x30, 0xab, 0x9a, 0xf8, 0x01,
+ 0x20, 0x62, 0x00, 0x00, 0xfe, 0x88, 0xe6, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02,
+ 0xfd, 0x0d, 0x85, 0x74, 0xfd, 0xa5, 0x56, 0xf4, 0xfc, 0x9d, 0x46, 0x58, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4,
+ 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x02, 0x00,
+ 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0x9c, 0x76, 0x00, 0x14, 0xff, 0xf7, 0x28, 0x12,
+ 0xcf, 0x74, 0xf0, 0x00, 0x9b, 0x7a, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09,
+ 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xe2, 0xd0, 0xff, 0x82, 0x02, 0x00, 0xae, 0x7a, 0xf8, 0x05,
+ 0xfd, 0x88, 0xe0, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a,
+ 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x20, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0xff, 0x67, 0x28, 0x00,
+ 0x2f, 0xf8, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x00, 0x7e, 0x71, 0x00, 0x10, 0x9f, 0x66, 0x00, 0x08,
+ 0xcd, 0xec, 0xe2, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x89, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x77, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0x4d, 0xed, 0x20, 0x00, 0xcc, 0x60, 0xdd, 0x00,
+ 0x2f, 0x78, 0x08, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x86, 0xa7, 0xb8, 0xfb, 0x9d, 0x46, 0x48, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xab, 0x04, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x80, 0x58, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0xac, 0x71, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0, 0xff, 0x8c, 0x7f, 0xd8,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28, 0xff, 0x8c, 0x7f, 0xc8,
+ 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0xab, 0x81, 0xff, 0xa2, 0x02, 0x00,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x7f, 0xc8, 0xff, 0x8d, 0x4b, 0xc0, 0xff, 0xa2, 0x02, 0x00,
+ 0xf3, 0x0d, 0x84, 0xb0, 0xfc, 0x8d, 0x84, 0xb4, 0xf4, 0x0d, 0x84, 0xb8, 0xc5, 0x28, 0xfd, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xab, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x48, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0xac, 0x5c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xa9, 0x85, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88,
+ 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x56, 0xf0,
+ 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0xac, 0x3d, 0x00, 0x00, 0x00, 0x01,
+ 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04,
+ 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0xac, 0x45, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0xac, 0x18, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xac, 0x70,
+ 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0xac, 0x2c, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0xa9, 0x84,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xac, 0x70, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xb9, 0x50,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xa9, 0x84, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x86, 0xac, 0x7c, 0xe0, 0x01, 0x3d, 0x44, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8c, 0x4c, 0x18, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x7f, 0xfd, 0x00, 0x19,
+ 0x9f, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x82, 0x00, 0x11, 0x9f, 0x82, 0xfe, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf0, 0x0d, 0x4c, 0x18, 0xfe, 0x82, 0x00, 0x00,
+ 0xfe, 0x02, 0x00, 0x01, 0xcf, 0xf0, 0xef, 0xc0, 0xc0, 0x1a, 0xfc, 0x00, 0xe6, 0x01, 0xac, 0xfc,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x4c, 0x18, 0x0f, 0xfc, 0x07, 0x48, 0xfe, 0xff, 0x68, 0x00,
+ 0xff, 0x0c, 0x4c, 0x18, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4c, 0x18, 0x0e, 0xf4, 0x00, 0x01,
+ 0x20, 0x76, 0x00, 0x0e, 0xee, 0x01, 0xad, 0x1c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x4c, 0x18,
+ 0x20, 0x7e, 0x00, 0x0e, 0xe2, 0x01, 0xac, 0xd9, 0xcf, 0xf0, 0xef, 0xc0, 0xf7, 0x86, 0xad, 0x28,
+ 0xe0, 0x01, 0xac, 0x88, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x0c, 0x4c, 0x18,
+ 0x4f, 0xa9, 0x1e, 0x00, 0x7d, 0xfc, 0xff, 0xe7, 0xc0, 0x6e, 0xf2, 0x00, 0xe4, 0x01, 0xad, 0x71,
+ 0x0f, 0xec, 0x07, 0x48, 0xff, 0x7f, 0x58, 0x00, 0x0d, 0xec, 0x00, 0x01, 0xb0, 0x1a, 0xf0, 0x04,
+ 0xff, 0x8c, 0x4c, 0x18, 0xc0, 0x6e, 0xfa, 0x00, 0xe4, 0x01, 0xad, 0x54, 0x0f, 0xec, 0x07, 0x48,
+ 0xfd, 0x82, 0x00, 0x00, 0x7e, 0x6d, 0x00, 0x02, 0x8e, 0xf2, 0x07, 0x08, 0xaf, 0x1a, 0xd8, 0x05,
+ 0x7f, 0xf4, 0xff, 0xe8, 0x6f, 0xfc, 0x00, 0x01, 0xcf, 0x78, 0xfc, 0x00, 0xbf, 0x1e, 0xd8, 0x04,
+ 0xaf, 0x9a, 0xd8, 0x05, 0x7f, 0xfd, 0x00, 0x18, 0xce, 0xf4, 0xfd, 0x00, 0x0d, 0xec, 0x00, 0x01,
+ 0x20, 0x6e, 0x00, 0x0e, 0xe2, 0x01, 0xad, 0x75, 0x9e, 0xf2, 0x07, 0x08, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x85, 0xae, 0x00, 0x2c, 0x05, 0x29, 0xff, 0xe0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xad, 0xc8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0x81, 0x1e, 0x00, 0xc0, 0x2a, 0xfc, 0x00, 0xe6, 0x20, 0x00, 0x02, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xae, 0x30,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08, 0x93, 0x16, 0xff, 0xf4,
+ 0x7f, 0x99, 0x00, 0x02, 0x8f, 0xfe, 0x07, 0x08, 0xc3, 0x7c, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xf0,
+ 0xf7, 0x86, 0xae, 0x9c, 0xe0, 0x01, 0x36, 0x18, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0x8f, 0x16, 0xff, 0xf0, 0xf3, 0x82, 0x00, 0x00, 0xf7, 0x86, 0xae, 0xb4, 0xc1, 0x78, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x72, 0x64, 0x6d, 0x61, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x25, 0x64, 0x0a,
+ 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10,
+ 0x22, 0x10, 0x00, 0x08, 0xff, 0x06, 0xae, 0xc0, 0x93, 0x12, 0x00, 0x04, 0x9f, 0x12, 0x00, 0x00,
+ 0x93, 0x16, 0xff, 0xf4, 0xf7, 0x86, 0xaf, 0x00, 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x16, 0xff, 0xf4, 0x02, 0x10, 0x00, 0x08, 0x7f, 0xf9, 0x00, 0x02, 0x8f, 0x7e, 0x07, 0x08,
+ 0x9f, 0x16, 0xff, 0xf0, 0xff, 0x06, 0xae, 0x30, 0x9f, 0x7e, 0x07, 0x08, 0x83, 0x16, 0xff, 0xf0,
+ 0xf7, 0x86, 0xaf, 0x2c, 0xe0, 0x01, 0x36, 0x18, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x0c, 0x4c, 0x18,
+ 0x4f, 0xa9, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x2e, 0xf8, 0x00, 0x01, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xe6, 0x01, 0xaf, 0x51, 0x0f, 0x78, 0x07, 0x47, 0xff, 0x7b, 0x58, 0x00, 0x9f, 0x16, 0xff, 0xf4,
+ 0xfe, 0x8d, 0x4c, 0x18, 0xf7, 0x86, 0xaf, 0x60, 0xe0, 0x01, 0xac, 0x88, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x8e, 0x4b, 0xe0, 0xf7, 0x82, 0x00, 0x01, 0xf7, 0xff, 0x68, 0x3e, 0xff, 0x8c, 0x4c, 0x18,
+ 0x55, 0x28, 0x01, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xaf, 0x8c, 0xf3, 0x02, 0x00, 0x3f,
+ 0xf7, 0x86, 0xaf, 0x8c, 0xe0, 0x00, 0x7b, 0x5c, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0x8f, 0x96, 0xff, 0xf0, 0xf3, 0x82, 0x00, 0x00, 0xf7, 0x86, 0xaf, 0xa4, 0xc1, 0x7c, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7c, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0xf3, 0x7f, 0x68, 0x00, 0x2f, 0x7a, 0x00, 0x01, 0xe6, 0x01, 0xb0, 0x5c, 0xfe, 0x8e, 0x7c, 0x40,
+ 0xfe, 0x8c, 0x7c, 0x78, 0xff, 0x8c, 0x7c, 0x64, 0xff, 0x0c, 0x4b, 0xf8, 0x8e, 0x76, 0x00, 0x20,
+ 0x5f, 0xfd, 0x10, 0x00, 0x8d, 0xf6, 0x00, 0x30, 0xf0, 0x8d, 0x7c, 0x60, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x00, 0x02, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x82, 0xfe, 0x30, 0x0f, 0x78, 0x00, 0x01,
+ 0xff, 0x0d, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xec, 0x00, 0x00, 0x4e, 0x73, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9e, 0x76, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb0, 0x28, 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0xaf, 0xe0,
+ 0x9f, 0x76, 0x00, 0x20, 0x9f, 0xf6, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb0, 0x68, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7c, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0x2f, 0x7a, 0x00, 0x01,
+ 0xe6, 0x01, 0xb1, 0x54, 0xfe, 0x8e, 0x7c, 0xc0, 0xfe, 0x8c, 0x7c, 0xf8, 0xff, 0x8c, 0x7c, 0xe4,
+ 0xff, 0x0c, 0x4b, 0xf8, 0x8e, 0x76, 0x00, 0x20, 0x5f, 0xfd, 0x10, 0x00, 0x8d, 0xf6, 0x00, 0x30,
+ 0xf0, 0x8d, 0x7c, 0xe0, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x05, 0xf2, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x82, 0xfe, 0x30, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00,
+ 0xc7, 0xec, 0x00, 0x00, 0x4e, 0x73, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9e, 0x76, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb1, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0xb0, 0xd8, 0x9f, 0x76, 0x00, 0x20, 0x9f, 0xf6, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb1, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7d, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0xf3, 0x7f, 0x68, 0x00, 0x2f, 0x7a, 0x00, 0x01, 0xe6, 0x01, 0xb2, 0x4c, 0xfe, 0x8e, 0x7d, 0x40,
+ 0xfe, 0x8c, 0x7d, 0x78, 0xff, 0x8c, 0x7d, 0x64, 0xff, 0x0c, 0x4b, 0xf8, 0x8e, 0x76, 0x00, 0x20,
+ 0x5f, 0xfd, 0x10, 0x00, 0x8d, 0xf6, 0x00, 0x30, 0xf0, 0x8d, 0x7d, 0x60, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x0b, 0xe2, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x82, 0xfe, 0x30, 0x0f, 0x78, 0x00, 0x01,
+ 0xff, 0x0d, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xec, 0x00, 0x00, 0x4e, 0x73, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9e, 0x76, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb2, 0x18, 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0xb1, 0xd0,
+ 0x9f, 0x76, 0x00, 0x20, 0x9f, 0xf6, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb2, 0x58, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7d, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0x2f, 0x7a, 0x00, 0x01,
+ 0xe6, 0x01, 0xb3, 0x44, 0xfe, 0x8e, 0x7d, 0xc0, 0xfe, 0x8c, 0x7d, 0xf8, 0xff, 0x8c, 0x7d, 0xe4,
+ 0xff, 0x0c, 0x4b, 0xf8, 0x8e, 0x76, 0x00, 0x20, 0x5f, 0xfd, 0x10, 0x00, 0x8d, 0xf6, 0x00, 0x30,
+ 0xf0, 0x8d, 0x7d, 0xe0, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x11, 0xd2, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x82, 0xfe, 0x30, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00,
+ 0xc7, 0xec, 0x00, 0x00, 0x4e, 0x73, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9e, 0x76, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb3, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0xb2, 0xc8, 0x9f, 0x76, 0x00, 0x20, 0x9f, 0xf6, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb3, 0x50,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7e, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0xf3, 0x7f, 0x68, 0x00, 0x2f, 0x7a, 0x00, 0x01, 0xe6, 0x01, 0xb4, 0x3c, 0xfe, 0x8e, 0x7e, 0x40,
+ 0xfe, 0x8c, 0x7e, 0x78, 0xff, 0x8c, 0x7e, 0x64, 0xff, 0x0c, 0x4b, 0xf8, 0x8e, 0x76, 0x00, 0x20,
+ 0x5f, 0xfd, 0x10, 0x00, 0x8d, 0xf6, 0x00, 0x30, 0xf0, 0x8d, 0x7e, 0x60, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x36, 0x8a, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x82, 0xfe, 0x30, 0x0f, 0x78, 0x00, 0x01,
+ 0xff, 0x0d, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xec, 0x00, 0x00, 0x4e, 0x73, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9e, 0x76, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb4, 0x08, 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0xb3, 0xc0,
+ 0x9f, 0x76, 0x00, 0x20, 0x9f, 0xf6, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb4, 0x48, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7e, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0x2f, 0x7a, 0x00, 0x01,
+ 0xe6, 0x01, 0xb5, 0x34, 0xfe, 0x8e, 0x7e, 0xc0, 0xfe, 0x8c, 0x7e, 0xf8, 0xff, 0x8c, 0x7e, 0xe4,
+ 0xff, 0x0c, 0x4b, 0xf8, 0x8e, 0x76, 0x00, 0x20, 0x5f, 0xfd, 0x10, 0x00, 0x8d, 0xf6, 0x00, 0x30,
+ 0xf0, 0x8d, 0x7e, 0xe0, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x5b, 0x42, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x82, 0xfe, 0x30, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00,
+ 0xc7, 0xec, 0x00, 0x00, 0x4e, 0x73, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9e, 0x76, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb5, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0xb4, 0xb8, 0x9f, 0x76, 0x00, 0x20, 0x9f, 0xf6, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb5, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7c, 0x68, 0xfe, 0x8c, 0x7c, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xb6, 0xa4, 0xff, 0x0d, 0x7c, 0x68, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x7c, 0x6c,
+ 0x0b, 0xdc, 0x00, 0x02, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x7c, 0x68, 0xfc, 0x8c, 0x7c, 0x78,
+ 0xfd, 0x0c, 0x7c, 0x64, 0xfa, 0x8c, 0x4b, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xb6, 0x8d,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x7c, 0x40,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x80, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x4b, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb6, 0x58, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x7c, 0x80,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xb6, 0x14,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xb5, 0xb8, 0xff, 0x8d, 0x7c, 0x70, 0xfe, 0x8d, 0x7c, 0x60,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb6, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7c, 0xe8, 0xfe, 0x8c, 0x7c, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xb8, 0x14, 0xff, 0x0d, 0x7c, 0xe8, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x7c, 0xec,
+ 0x0b, 0xdc, 0x05, 0xf2, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x7c, 0xe8, 0xfc, 0x8c, 0x7c, 0xf8,
+ 0xfd, 0x0c, 0x7c, 0xe4, 0xfa, 0x8c, 0x4b, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xb7, 0xfd,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x7c, 0xc0,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x80, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x4b, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb7, 0xc8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x7d, 0x00,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xb7, 0x84,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xb7, 0x28, 0xff, 0x8d, 0x7c, 0xf0, 0xfe, 0x8d, 0x7c, 0xe0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb8, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7d, 0x68, 0xfe, 0x8c, 0x7d, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xb9, 0x84, 0xff, 0x0d, 0x7d, 0x68, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x7d, 0x6c,
+ 0x0b, 0xdc, 0x0b, 0xe2, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x7d, 0x68, 0xfc, 0x8c, 0x7d, 0x78,
+ 0xfd, 0x0c, 0x7d, 0x64, 0xfa, 0x8c, 0x4b, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xb9, 0x6d,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x7d, 0x40,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x80, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x4b, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb9, 0x38, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x7d, 0x80,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xb8, 0xf4,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xb8, 0x98, 0xff, 0x8d, 0x7d, 0x70, 0xfe, 0x8d, 0x7d, 0x60,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb9, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7d, 0xe8, 0xfe, 0x8c, 0x7d, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xba, 0xf4, 0xff, 0x0d, 0x7d, 0xe8, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x7d, 0xec,
+ 0x0b, 0xdc, 0x11, 0xd2, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x7d, 0xe8, 0xfc, 0x8c, 0x7d, 0xf8,
+ 0xfd, 0x0c, 0x7d, 0xe4, 0xfa, 0x8c, 0x4b, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xba, 0xdd,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x7d, 0xc0,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x80, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x4b, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xba, 0xa8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x7e, 0x00,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xba, 0x64,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xba, 0x08, 0xff, 0x8d, 0x7d, 0xf0, 0xfe, 0x8d, 0x7d, 0xe0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xbb, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7e, 0x68, 0xfe, 0x8c, 0x7e, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xbc, 0x64, 0xff, 0x0d, 0x7e, 0x68, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x7e, 0x6c,
+ 0x0b, 0xdc, 0x36, 0x8a, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x7e, 0x68, 0xfc, 0x8c, 0x7e, 0x78,
+ 0xfd, 0x0c, 0x7e, 0x64, 0xfa, 0x8c, 0x4b, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xbc, 0x4d,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x7e, 0x40,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x80, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x4b, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xbc, 0x18, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x7e, 0x80,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xbb, 0xd4,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xbb, 0x78, 0xff, 0x8d, 0x7e, 0x70, 0xfe, 0x8d, 0x7e, 0x60,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xbc, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7e, 0xe8, 0xfe, 0x8c, 0x7e, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xbd, 0xd4, 0xff, 0x0d, 0x7e, 0xe8, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x7e, 0xec,
+ 0x0b, 0xdc, 0x5b, 0x42, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x7e, 0xe8, 0xfc, 0x8c, 0x7e, 0xf8,
+ 0xfd, 0x0c, 0x7e, 0xe4, 0xfa, 0x8c, 0x4b, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xbd, 0xbd,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x7e, 0xc0,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x80, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x4b, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xbd, 0x88, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x7f, 0x00,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xbd, 0x44,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xbc, 0xe8, 0xff, 0x8d, 0x7e, 0xf0, 0xfe, 0x8d, 0x7e, 0xe0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xbd, 0xe0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7c, 0x68, 0xfe, 0x8c, 0x7c, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xbf, 0x48, 0xff, 0x0d, 0x7c, 0x68, 0x0b, 0x81, 0x80, 0x01,
+ 0xfc, 0x0c, 0x7c, 0x6c, 0x0b, 0xdc, 0x00, 0x02, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x7c, 0x68,
+ 0xfc, 0x8c, 0x7c, 0x78, 0xfd, 0x0c, 0x7c, 0x64, 0xfa, 0x8c, 0x4b, 0xf8, 0x8b, 0x66, 0x00, 0x20,
+ 0x7f, 0xf0, 0x00, 0x10, 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00,
+ 0x0d, 0xe0, 0x00, 0x02, 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff,
+ 0xe6, 0x01, 0xbf, 0x31, 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80,
+ 0xff, 0x8e, 0x7c, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30,
+ 0xff, 0x8e, 0x80, 0xa2, 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x4b, 0xf8,
+ 0x9f, 0x82, 0xfe, 0x30, 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00,
+ 0x4b, 0x5b, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xbe, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x7c, 0x80, 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02,
+ 0xe0, 0x01, 0xbe, 0xb8, 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xbe, 0x5c, 0xff, 0x8d, 0x7c, 0x70,
+ 0xfe, 0x8d, 0x7c, 0x60, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xbf, 0x54, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00,
+ 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7c, 0xe8, 0xfe, 0x8c, 0x7c, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xf3, 0x7f, 0x68, 0x00,
+ 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xc0, 0xbc, 0xff, 0x0d, 0x7c, 0xe8,
+ 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x7c, 0xec, 0x0b, 0xdc, 0x05, 0xf2, 0x9b, 0x82, 0xfe, 0x68,
+ 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68,
+ 0xfe, 0x0c, 0x7c, 0xe8, 0xfc, 0x8c, 0x7c, 0xf8, 0xfd, 0x0c, 0x7c, 0xe4, 0xfa, 0x8c, 0x4b, 0xf8,
+ 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10, 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02, 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00,
+ 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xc0, 0xa5, 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30,
+ 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x7c, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30,
+ 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x80, 0xa2, 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00,
+ 0xff, 0x0d, 0x4b, 0xf8, 0x9f, 0x82, 0xfe, 0x30, 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc0, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x7d, 0x00, 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10,
+ 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xc0, 0x2c, 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xbf, 0xd0,
+ 0xff, 0x8d, 0x7c, 0xf0, 0xfe, 0x8d, 0x7c, 0xe0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc0, 0xc8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7d, 0x68, 0xfe, 0x8c, 0x7d, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08,
+ 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xc2, 0x30,
+ 0xff, 0x0d, 0x7d, 0x68, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x7d, 0x6c, 0x0b, 0xdc, 0x0b, 0xe2,
+ 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0,
+ 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x7d, 0x68, 0xfc, 0x8c, 0x7d, 0x78, 0xfd, 0x0c, 0x7d, 0x64,
+ 0xfa, 0x8c, 0x4b, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10, 0xce, 0x7e, 0xe0, 0x00,
+ 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02, 0xcd, 0x68, 0xda, 0x00,
+ 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xc2, 0x19, 0x5d, 0xed, 0x10, 0x00,
+ 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x7d, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x80, 0xa2, 0x0f, 0x54, 0x00, 0x01,
+ 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x4b, 0xf8, 0x9f, 0x82, 0xfe, 0x30, 0x9d, 0x82, 0xfe, 0x30,
+ 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03,
+ 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xc1, 0xe4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x7d, 0x80, 0xcf, 0xe0, 0xfa, 0x00,
+ 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xc1, 0xa0, 0xce, 0x70, 0xf2, 0x00,
+ 0xff, 0x86, 0xc1, 0x44, 0xff, 0x8d, 0x7d, 0x70, 0xfe, 0x8d, 0x7d, 0x60, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc2, 0x3c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7d, 0xe8,
+ 0xfe, 0x8c, 0x7d, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0x73, 0x9d, 0x00, 0x08, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xc3, 0xa4, 0xff, 0x0d, 0x7d, 0xe8, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x7d, 0xec,
+ 0x0b, 0xdc, 0x11, 0xd2, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x7d, 0xe8, 0xfc, 0x8c, 0x7d, 0xf8,
+ 0xfd, 0x0c, 0x7d, 0xe4, 0xfa, 0x8c, 0x4b, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xc3, 0x8d,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x7d, 0xc0,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x80, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x4b, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc3, 0x58, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x7e, 0x00,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xc3, 0x14,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xc2, 0xb8, 0xff, 0x8d, 0x7d, 0xf0, 0xfe, 0x8d, 0x7d, 0xe0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc3, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7e, 0x68, 0xfe, 0x8c, 0x7e, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xc5, 0x18, 0xff, 0x0d, 0x7e, 0x68, 0x0b, 0x81, 0x80, 0x01,
+ 0xfc, 0x0c, 0x7e, 0x6c, 0x0b, 0xdc, 0x36, 0x8a, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x7e, 0x68,
+ 0xfc, 0x8c, 0x7e, 0x78, 0xfd, 0x0c, 0x7e, 0x64, 0xfa, 0x8c, 0x4b, 0xf8, 0x8b, 0x66, 0x00, 0x20,
+ 0x7f, 0xf0, 0x00, 0x10, 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00,
+ 0x0d, 0xe0, 0x00, 0x02, 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff,
+ 0xe6, 0x01, 0xc5, 0x01, 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80,
+ 0xff, 0x8e, 0x7e, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30,
+ 0xff, 0x8e, 0x80, 0xa2, 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x4b, 0xf8,
+ 0x9f, 0x82, 0xfe, 0x30, 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00,
+ 0x4b, 0x5b, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc4, 0xcc, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x7e, 0x80, 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02,
+ 0xe0, 0x01, 0xc4, 0x88, 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xc4, 0x2c, 0xff, 0x8d, 0x7e, 0x70,
+ 0xfe, 0x8d, 0x7e, 0x60, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xc5, 0x24, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00,
+ 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7e, 0xe8, 0xfe, 0x8c, 0x7e, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xf3, 0x7f, 0x68, 0x00,
+ 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xc6, 0x8c, 0xff, 0x0d, 0x7e, 0xe8,
+ 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x7e, 0xec, 0x0b, 0xdc, 0x5b, 0x42, 0x9b, 0x82, 0xfe, 0x68,
+ 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68,
+ 0xfe, 0x0c, 0x7e, 0xe8, 0xfc, 0x8c, 0x7e, 0xf8, 0xfd, 0x0c, 0x7e, 0xe4, 0xfa, 0x8c, 0x4b, 0xf8,
+ 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10, 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02, 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00,
+ 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xc6, 0x75, 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30,
+ 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x7e, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30,
+ 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x80, 0xa2, 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00,
+ 0xff, 0x0d, 0x4b, 0xf8, 0x9f, 0x82, 0xfe, 0x30, 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc6, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x7f, 0x00, 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10,
+ 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xc5, 0xfc, 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xc5, 0xa0,
+ 0xff, 0x8d, 0x7e, 0xf0, 0xfe, 0x8d, 0x7e, 0xe0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc6, 0x98, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7c, 0x68, 0xfe, 0x8c, 0x7c, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7c, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xc9, 0x20,
+ 0xff, 0x0e, 0x7c, 0x40, 0xfb, 0x0c, 0x7c, 0x64, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x00, 0x02,
+ 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd8, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xae,
+ 0xff, 0x7f, 0x18, 0x00, 0xfa, 0x8c, 0x7c, 0x6c, 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x7c, 0x00, 0x02,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xc8, 0x75, 0xff, 0xa5, 0x57, 0x00, 0xfb, 0x8c, 0x7c, 0x80,
+ 0xfe, 0x8e, 0x80, 0xb4, 0xff, 0x77, 0x18, 0x00, 0xcf, 0xd4, 0xb0, 0x00, 0xce, 0x58, 0xba, 0x00,
+ 0xfd, 0x0e, 0x80, 0xa2, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0xf7, 0x28, 0x00, 0xcc, 0xf0, 0xd0, 0x00,
+ 0xfd, 0xe7, 0x18, 0x0c, 0xcf, 0x78, 0xb2, 0x00, 0x0c, 0x78, 0x00, 0x36, 0x4f, 0xec, 0xff, 0xf6,
+ 0xff, 0xe7, 0x28, 0x0c, 0xfb, 0x0d, 0x84, 0xf8, 0xfd, 0x8d, 0x80, 0x88, 0xfa, 0x8d, 0x85, 0x88,
+ 0xfc, 0x8d, 0x84, 0xe8, 0xad, 0xf2, 0xd0, 0x02, 0x6c, 0x60, 0xff, 0xff, 0x8e, 0xe6, 0x00, 0x08,
+ 0x8e, 0x66, 0x00, 0x04, 0x8f, 0x66, 0x00, 0x0c, 0x8f, 0xe6, 0x00, 0x10, 0xcc, 0x60, 0xa8, 0x00,
+ 0xcc, 0x6e, 0xc0, 0x00, 0xcc, 0x72, 0xc1, 0x00, 0xcc, 0x76, 0xc1, 0x00, 0xcc, 0x7a, 0xc1, 0x00,
+ 0xcc, 0x7e, 0xc1, 0x00, 0xcc, 0x00, 0xc1, 0x00, 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00,
+ 0xee, 0x01, 0xc8, 0x09, 0x0c, 0xe4, 0x00, 0x14, 0xff, 0xe7, 0x18, 0x00, 0xff, 0x67, 0x18, 0x02,
+ 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0x60, 0xf8, 0x00,
+ 0xee, 0x01, 0xc7, 0xe8, 0x0c, 0xe4, 0x00, 0x04, 0x7f, 0xe0, 0x00, 0x10, 0xcc, 0x7e, 0xc0, 0x00,
+ 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00, 0xfc, 0x09, 0xfb, 0xa0, 0xff, 0x0c, 0x7c, 0x78,
+ 0xff, 0x8e, 0x7c, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc8, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x8e, 0x80, 0xb2, 0xff, 0x6f, 0x18, 0x00, 0xfd, 0x0e, 0x80, 0xba,
+ 0xfe, 0xeb, 0x18, 0x00, 0xfc, 0x8e, 0x80, 0xb0, 0xfe, 0x67, 0x58, 0x00, 0x4f, 0xd9, 0xdf, 0xff,
+ 0xcf, 0xfc, 0xa8, 0x00, 0xcf, 0x04, 0xf6, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0xce, 0x84, 0xee, 0x00,
+ 0x4f, 0x79, 0x00, 0x00, 0xff, 0xef, 0x28, 0x00, 0x4c, 0x75, 0x00, 0x00, 0xcf, 0x78, 0xf8, 0x00,
+ 0x4e, 0x70, 0x00, 0x0f, 0x7e, 0x71, 0x00, 0x02, 0xfa, 0x8d, 0x85, 0x88, 0xcf, 0xe0, 0xf0, 0x00,
+ 0x7d, 0xfc, 0x00, 0x10, 0xcc, 0x6e, 0xf8, 0x00, 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00,
+ 0xce, 0x84, 0xc6, 0x00, 0xfe, 0xeb, 0x28, 0x00, 0xcc, 0xf0, 0xc8, 0x00, 0xfd, 0xe7, 0x18, 0x0c,
+ 0xfc, 0x0c, 0x7c, 0x68, 0x4e, 0xec, 0x00, 0x09, 0x6e, 0xf4, 0xff, 0xff, 0xfb, 0x0d, 0x84, 0xf8,
+ 0xfc, 0x8d, 0x84, 0xe8, 0xfd, 0x8d, 0x80, 0x88, 0xcf, 0x78, 0xe8, 0x00, 0x4f, 0xec, 0xff, 0xf6,
+ 0xff, 0xe7, 0x28, 0x0c, 0xcf, 0x60, 0xf0, 0x00, 0x7f, 0xf8, 0x00, 0x10, 0xcf, 0x7e, 0xf0, 0x00,
+ 0x7f, 0x78, 0xff, 0xf0, 0xcf, 0x00, 0xf1, 0x00, 0xe0, 0x01, 0xc8, 0x1c, 0xff, 0x09, 0xfb, 0xa0,
+ 0xff, 0x86, 0xc7, 0x14, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc9, 0x2c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7c, 0xe8,
+ 0xfe, 0x8c, 0x7c, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7c, 0xe8, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xcb, 0xb4, 0xff, 0x0e, 0x7c, 0xc0, 0xfb, 0x0c, 0x7c, 0xe4, 0x0f, 0x81, 0x80, 0x01,
+ 0x0f, 0xfc, 0x05, 0xf2, 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd8, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8e, 0x80, 0xae, 0xff, 0x7f, 0x18, 0x00, 0xfa, 0x8c, 0x7c, 0xec, 0x20, 0x7a, 0x08, 0x00,
+ 0xe6, 0x7c, 0x00, 0x02, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xcb, 0x09, 0xff, 0xa5, 0x57, 0x00,
+ 0xfb, 0x8c, 0x7d, 0x00, 0xfe, 0x8e, 0x80, 0xb4, 0xff, 0x77, 0x18, 0x00, 0xcf, 0xd4, 0xb0, 0x00,
+ 0xce, 0x58, 0xba, 0x00, 0xfd, 0x0e, 0x80, 0xa2, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0xf7, 0x28, 0x00,
+ 0xcc, 0xf0, 0xd0, 0x00, 0xfd, 0xe7, 0x18, 0x0c, 0xcf, 0x78, 0xb2, 0x00, 0x0c, 0x78, 0x00, 0x36,
+ 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c, 0xfb, 0x0d, 0x84, 0xf8, 0xfd, 0x8d, 0x80, 0x88,
+ 0xfa, 0x8d, 0x85, 0x88, 0xfc, 0x8d, 0x84, 0xe8, 0xad, 0xf2, 0xd0, 0x02, 0x6c, 0x60, 0xff, 0xff,
+ 0x8e, 0xe6, 0x00, 0x08, 0x8e, 0x66, 0x00, 0x04, 0x8f, 0x66, 0x00, 0x0c, 0x8f, 0xe6, 0x00, 0x10,
+ 0xcc, 0x60, 0xa8, 0x00, 0xcc, 0x6e, 0xc0, 0x00, 0xcc, 0x72, 0xc1, 0x00, 0xcc, 0x76, 0xc1, 0x00,
+ 0xcc, 0x7a, 0xc1, 0x00, 0xcc, 0x7e, 0xc1, 0x00, 0xcc, 0x00, 0xc1, 0x00, 0x2b, 0xdc, 0x00, 0x14,
+ 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xca, 0x9d, 0x0c, 0xe4, 0x00, 0x14, 0xff, 0xe7, 0x18, 0x00,
+ 0xff, 0x67, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xcc, 0x60, 0xf8, 0x00, 0xee, 0x01, 0xca, 0x7c, 0x0c, 0xe4, 0x00, 0x04, 0x7f, 0xe0, 0x00, 0x10,
+ 0xcc, 0x7e, 0xc0, 0x00, 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00, 0xfc, 0x09, 0xfb, 0xa0,
+ 0xff, 0x0c, 0x7c, 0xf8, 0xff, 0x8e, 0x7c, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30,
+ 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03,
+ 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xca, 0xd4, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x8e, 0x80, 0xb2, 0xff, 0x6f, 0x18, 0x00,
+ 0xfd, 0x0e, 0x80, 0xba, 0xfe, 0xeb, 0x18, 0x00, 0xfc, 0x8e, 0x80, 0xb0, 0xfe, 0x67, 0x58, 0x00,
+ 0x4f, 0xd9, 0xdf, 0xff, 0xcf, 0xfc, 0xa8, 0x00, 0xcf, 0x04, 0xf6, 0x00, 0x2f, 0xfc, 0x00, 0x0e,
+ 0xce, 0x84, 0xee, 0x00, 0x4f, 0x79, 0x00, 0x00, 0xff, 0xef, 0x28, 0x00, 0x4c, 0x75, 0x00, 0x00,
+ 0xcf, 0x78, 0xf8, 0x00, 0x4e, 0x70, 0x00, 0x0f, 0x7e, 0x71, 0x00, 0x02, 0xfa, 0x8d, 0x85, 0x88,
+ 0xcf, 0xe0, 0xf0, 0x00, 0x7d, 0xfc, 0x00, 0x10, 0xcc, 0x6e, 0xf8, 0x00, 0x7c, 0x60, 0xff, 0xf0,
+ 0xcc, 0x00, 0xc1, 0x00, 0xce, 0x84, 0xc6, 0x00, 0xfe, 0xeb, 0x28, 0x00, 0xcc, 0xf0, 0xc8, 0x00,
+ 0xfd, 0xe7, 0x18, 0x0c, 0xfc, 0x0c, 0x7c, 0xe8, 0x4e, 0xec, 0x00, 0x09, 0x6e, 0xf4, 0xff, 0xff,
+ 0xfb, 0x0d, 0x84, 0xf8, 0xfc, 0x8d, 0x84, 0xe8, 0xfd, 0x8d, 0x80, 0x88, 0xcf, 0x78, 0xe8, 0x00,
+ 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c, 0xcf, 0x60, 0xf0, 0x00, 0x7f, 0xf8, 0x00, 0x10,
+ 0xcf, 0x7e, 0xf0, 0x00, 0x7f, 0x78, 0xff, 0xf0, 0xcf, 0x00, 0xf1, 0x00, 0xe0, 0x01, 0xca, 0xb0,
+ 0xff, 0x09, 0xfb, 0xa0, 0xff, 0x86, 0xc9, 0xa8, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xcb, 0xc0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7d, 0x68, 0xfe, 0x8c, 0x7d, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7d, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xce, 0x48, 0xff, 0x0e, 0x7d, 0x40, 0xfb, 0x0c, 0x7d, 0x64,
+ 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x0b, 0xe2, 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd8, 0x00, 0x09,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xae, 0xff, 0x7f, 0x18, 0x00, 0xfa, 0x8c, 0x7d, 0x6c,
+ 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x7c, 0x00, 0x02, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xcd, 0x9d,
+ 0xff, 0xa5, 0x57, 0x00, 0xfb, 0x8c, 0x7d, 0x80, 0xfe, 0x8e, 0x80, 0xb4, 0xff, 0x77, 0x18, 0x00,
+ 0xcf, 0xd4, 0xb0, 0x00, 0xce, 0x58, 0xba, 0x00, 0xfd, 0x0e, 0x80, 0xa2, 0x2f, 0xfc, 0x00, 0x36,
+ 0xff, 0xf7, 0x28, 0x00, 0xcc, 0xf0, 0xd0, 0x00, 0xfd, 0xe7, 0x18, 0x0c, 0xcf, 0x78, 0xb2, 0x00,
+ 0x0c, 0x78, 0x00, 0x36, 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c, 0xfb, 0x0d, 0x84, 0xf8,
+ 0xfd, 0x8d, 0x80, 0x88, 0xfa, 0x8d, 0x85, 0x88, 0xfc, 0x8d, 0x84, 0xe8, 0xad, 0xf2, 0xd0, 0x02,
+ 0x6c, 0x60, 0xff, 0xff, 0x8e, 0xe6, 0x00, 0x08, 0x8e, 0x66, 0x00, 0x04, 0x8f, 0x66, 0x00, 0x0c,
+ 0x8f, 0xe6, 0x00, 0x10, 0xcc, 0x60, 0xa8, 0x00, 0xcc, 0x6e, 0xc0, 0x00, 0xcc, 0x72, 0xc1, 0x00,
+ 0xcc, 0x76, 0xc1, 0x00, 0xcc, 0x7a, 0xc1, 0x00, 0xcc, 0x7e, 0xc1, 0x00, 0xcc, 0x00, 0xc1, 0x00,
+ 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xcd, 0x31, 0x0c, 0xe4, 0x00, 0x14,
+ 0xff, 0xe7, 0x18, 0x00, 0xff, 0x67, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00,
+ 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0x60, 0xf8, 0x00, 0xee, 0x01, 0xcd, 0x10, 0x0c, 0xe4, 0x00, 0x04,
+ 0x7f, 0xe0, 0x00, 0x10, 0xcc, 0x7e, 0xc0, 0x00, 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00,
+ 0xfc, 0x09, 0xfb, 0xa0, 0xff, 0x0c, 0x7d, 0x78, 0xff, 0x8e, 0x7d, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xcd, 0x68, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x8e, 0x80, 0xb2,
+ 0xff, 0x6f, 0x18, 0x00, 0xfd, 0x0e, 0x80, 0xba, 0xfe, 0xeb, 0x18, 0x00, 0xfc, 0x8e, 0x80, 0xb0,
+ 0xfe, 0x67, 0x58, 0x00, 0x4f, 0xd9, 0xdf, 0xff, 0xcf, 0xfc, 0xa8, 0x00, 0xcf, 0x04, 0xf6, 0x00,
+ 0x2f, 0xfc, 0x00, 0x0e, 0xce, 0x84, 0xee, 0x00, 0x4f, 0x79, 0x00, 0x00, 0xff, 0xef, 0x28, 0x00,
+ 0x4c, 0x75, 0x00, 0x00, 0xcf, 0x78, 0xf8, 0x00, 0x4e, 0x70, 0x00, 0x0f, 0x7e, 0x71, 0x00, 0x02,
+ 0xfa, 0x8d, 0x85, 0x88, 0xcf, 0xe0, 0xf0, 0x00, 0x7d, 0xfc, 0x00, 0x10, 0xcc, 0x6e, 0xf8, 0x00,
+ 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00, 0xce, 0x84, 0xc6, 0x00, 0xfe, 0xeb, 0x28, 0x00,
+ 0xcc, 0xf0, 0xc8, 0x00, 0xfd, 0xe7, 0x18, 0x0c, 0xfc, 0x0c, 0x7d, 0x68, 0x4e, 0xec, 0x00, 0x09,
+ 0x6e, 0xf4, 0xff, 0xff, 0xfb, 0x0d, 0x84, 0xf8, 0xfc, 0x8d, 0x84, 0xe8, 0xfd, 0x8d, 0x80, 0x88,
+ 0xcf, 0x78, 0xe8, 0x00, 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c, 0xcf, 0x60, 0xf0, 0x00,
+ 0x7f, 0xf8, 0x00, 0x10, 0xcf, 0x7e, 0xf0, 0x00, 0x7f, 0x78, 0xff, 0xf0, 0xcf, 0x00, 0xf1, 0x00,
+ 0xe0, 0x01, 0xcd, 0x44, 0xff, 0x09, 0xfb, 0xa0, 0xff, 0x86, 0xcc, 0x3c, 0x9e, 0xfa, 0x00, 0x20,
+ 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xce, 0x54, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00,
+ 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7d, 0xe8, 0xfe, 0x8c, 0x7d, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00,
+ 0xff, 0x0d, 0x7d, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xd0, 0xdc, 0xff, 0x0e, 0x7d, 0xc0,
+ 0xfb, 0x0c, 0x7d, 0xe4, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x11, 0xd2, 0x9f, 0x82, 0xfe, 0x68,
+ 0x0f, 0xd8, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xae, 0xff, 0x7f, 0x18, 0x00,
+ 0xfa, 0x8c, 0x7d, 0xec, 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x7c, 0x00, 0x02, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0xd0, 0x31, 0xff, 0xa5, 0x57, 0x00, 0xfb, 0x8c, 0x7e, 0x00, 0xfe, 0x8e, 0x80, 0xb4,
+ 0xff, 0x77, 0x18, 0x00, 0xcf, 0xd4, 0xb0, 0x00, 0xce, 0x58, 0xba, 0x00, 0xfd, 0x0e, 0x80, 0xa2,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0xf7, 0x28, 0x00, 0xcc, 0xf0, 0xd0, 0x00, 0xfd, 0xe7, 0x18, 0x0c,
+ 0xcf, 0x78, 0xb2, 0x00, 0x0c, 0x78, 0x00, 0x36, 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c,
+ 0xfb, 0x0d, 0x84, 0xf8, 0xfd, 0x8d, 0x80, 0x88, 0xfa, 0x8d, 0x85, 0x88, 0xfc, 0x8d, 0x84, 0xe8,
+ 0xad, 0xf2, 0xd0, 0x02, 0x6c, 0x60, 0xff, 0xff, 0x8e, 0xe6, 0x00, 0x08, 0x8e, 0x66, 0x00, 0x04,
+ 0x8f, 0x66, 0x00, 0x0c, 0x8f, 0xe6, 0x00, 0x10, 0xcc, 0x60, 0xa8, 0x00, 0xcc, 0x6e, 0xc0, 0x00,
+ 0xcc, 0x72, 0xc1, 0x00, 0xcc, 0x76, 0xc1, 0x00, 0xcc, 0x7a, 0xc1, 0x00, 0xcc, 0x7e, 0xc1, 0x00,
+ 0xcc, 0x00, 0xc1, 0x00, 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xcf, 0xc5,
+ 0x0c, 0xe4, 0x00, 0x14, 0xff, 0xe7, 0x18, 0x00, 0xff, 0x67, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04,
+ 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0x60, 0xf8, 0x00, 0xee, 0x01, 0xcf, 0xa4,
+ 0x0c, 0xe4, 0x00, 0x04, 0x7f, 0xe0, 0x00, 0x10, 0xcc, 0x7e, 0xc0, 0x00, 0x7c, 0x60, 0xff, 0xf0,
+ 0xcc, 0x00, 0xc1, 0x00, 0xfc, 0x09, 0xfb, 0xa0, 0xff, 0x0c, 0x7d, 0xf8, 0xff, 0x8e, 0x7d, 0xc0,
+ 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00,
+ 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xcf, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x8e, 0x80, 0xb2, 0xff, 0x6f, 0x18, 0x00, 0xfd, 0x0e, 0x80, 0xba, 0xfe, 0xeb, 0x18, 0x00,
+ 0xfc, 0x8e, 0x80, 0xb0, 0xfe, 0x67, 0x58, 0x00, 0x4f, 0xd9, 0xdf, 0xff, 0xcf, 0xfc, 0xa8, 0x00,
+ 0xcf, 0x04, 0xf6, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0xce, 0x84, 0xee, 0x00, 0x4f, 0x79, 0x00, 0x00,
+ 0xff, 0xef, 0x28, 0x00, 0x4c, 0x75, 0x00, 0x00, 0xcf, 0x78, 0xf8, 0x00, 0x4e, 0x70, 0x00, 0x0f,
+ 0x7e, 0x71, 0x00, 0x02, 0xfa, 0x8d, 0x85, 0x88, 0xcf, 0xe0, 0xf0, 0x00, 0x7d, 0xfc, 0x00, 0x10,
+ 0xcc, 0x6e, 0xf8, 0x00, 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00, 0xce, 0x84, 0xc6, 0x00,
+ 0xfe, 0xeb, 0x28, 0x00, 0xcc, 0xf0, 0xc8, 0x00, 0xfd, 0xe7, 0x18, 0x0c, 0xfc, 0x0c, 0x7d, 0xe8,
+ 0x4e, 0xec, 0x00, 0x09, 0x6e, 0xf4, 0xff, 0xff, 0xfb, 0x0d, 0x84, 0xf8, 0xfc, 0x8d, 0x84, 0xe8,
+ 0xfd, 0x8d, 0x80, 0x88, 0xcf, 0x78, 0xe8, 0x00, 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c,
+ 0xcf, 0x60, 0xf0, 0x00, 0x7f, 0xf8, 0x00, 0x10, 0xcf, 0x7e, 0xf0, 0x00, 0x7f, 0x78, 0xff, 0xf0,
+ 0xcf, 0x00, 0xf1, 0x00, 0xe0, 0x01, 0xcf, 0xd8, 0xff, 0x09, 0xfb, 0xa0, 0xff, 0x86, 0xce, 0xd0,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd0, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7e, 0x68, 0xfe, 0x8c, 0x7e, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7e, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xd3, 0x70,
+ 0xff, 0x0e, 0x7e, 0x40, 0xfb, 0x0c, 0x7e, 0x64, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x36, 0x8a,
+ 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd8, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xae,
+ 0xff, 0x7f, 0x18, 0x00, 0xfa, 0x8c, 0x7e, 0x6c, 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x7c, 0x00, 0x02,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xd2, 0xc5, 0xff, 0xa5, 0x57, 0x00, 0xfb, 0x8c, 0x7e, 0x80,
+ 0xfe, 0x8e, 0x80, 0xb4, 0xff, 0x77, 0x18, 0x00, 0xcf, 0xd4, 0xb0, 0x00, 0xce, 0x58, 0xba, 0x00,
+ 0xfd, 0x0e, 0x80, 0xa2, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0xf7, 0x28, 0x00, 0xcc, 0xf0, 0xd0, 0x00,
+ 0xfd, 0xe7, 0x18, 0x0c, 0xcf, 0x78, 0xb2, 0x00, 0x0c, 0x78, 0x00, 0x36, 0x4f, 0xec, 0xff, 0xf6,
+ 0xff, 0xe7, 0x28, 0x0c, 0xfb, 0x0d, 0x84, 0xf8, 0xfd, 0x8d, 0x80, 0x88, 0xfa, 0x8d, 0x85, 0x88,
+ 0xfc, 0x8d, 0x84, 0xe8, 0xad, 0xf2, 0xd0, 0x02, 0x6c, 0x60, 0xff, 0xff, 0x8e, 0xe6, 0x00, 0x08,
+ 0x8e, 0x66, 0x00, 0x04, 0x8f, 0x66, 0x00, 0x0c, 0x8f, 0xe6, 0x00, 0x10, 0xcc, 0x60, 0xa8, 0x00,
+ 0xcc, 0x6e, 0xc0, 0x00, 0xcc, 0x72, 0xc1, 0x00, 0xcc, 0x76, 0xc1, 0x00, 0xcc, 0x7a, 0xc1, 0x00,
+ 0xcc, 0x7e, 0xc1, 0x00, 0xcc, 0x00, 0xc1, 0x00, 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00,
+ 0xee, 0x01, 0xd2, 0x59, 0x0c, 0xe4, 0x00, 0x14, 0xff, 0xe7, 0x18, 0x00, 0xff, 0x67, 0x18, 0x02,
+ 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0x60, 0xf8, 0x00,
+ 0xee, 0x01, 0xd2, 0x38, 0x0c, 0xe4, 0x00, 0x04, 0x7f, 0xe0, 0x00, 0x10, 0xcc, 0x7e, 0xc0, 0x00,
+ 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00, 0xfc, 0x09, 0xfb, 0xa0, 0xff, 0x0c, 0x7e, 0x78,
+ 0xff, 0x8e, 0x7e, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd2, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x8e, 0x80, 0xb2, 0xff, 0x6f, 0x18, 0x00, 0xfd, 0x0e, 0x80, 0xba,
+ 0xfe, 0xeb, 0x18, 0x00, 0xfc, 0x8e, 0x80, 0xb0, 0xfe, 0x67, 0x58, 0x00, 0x4f, 0xd9, 0xdf, 0xff,
+ 0xcf, 0xfc, 0xa8, 0x00, 0xcf, 0x04, 0xf6, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0xce, 0x84, 0xee, 0x00,
+ 0x4f, 0x79, 0x00, 0x00, 0xff, 0xef, 0x28, 0x00, 0x4c, 0x75, 0x00, 0x00, 0xcf, 0x78, 0xf8, 0x00,
+ 0x4e, 0x70, 0x00, 0x0f, 0x7e, 0x71, 0x00, 0x02, 0xfa, 0x8d, 0x85, 0x88, 0xcf, 0xe0, 0xf0, 0x00,
+ 0x7d, 0xfc, 0x00, 0x10, 0xcc, 0x6e, 0xf8, 0x00, 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00,
+ 0xce, 0x84, 0xc6, 0x00, 0xfe, 0xeb, 0x28, 0x00, 0xcc, 0xf0, 0xc8, 0x00, 0xfd, 0xe7, 0x18, 0x0c,
+ 0xfc, 0x0c, 0x7e, 0x68, 0x4e, 0xec, 0x00, 0x09, 0x6e, 0xf4, 0xff, 0xff, 0xfb, 0x0d, 0x84, 0xf8,
+ 0xfc, 0x8d, 0x84, 0xe8, 0xfd, 0x8d, 0x80, 0x88, 0xcf, 0x78, 0xe8, 0x00, 0x4f, 0xec, 0xff, 0xf6,
+ 0xff, 0xe7, 0x28, 0x0c, 0xcf, 0x60, 0xf0, 0x00, 0x7f, 0xf8, 0x00, 0x10, 0xcf, 0x7e, 0xf0, 0x00,
+ 0x7f, 0x78, 0xff, 0xf0, 0xcf, 0x00, 0xf1, 0x00, 0xe0, 0x01, 0xd2, 0x6c, 0xff, 0x09, 0xfb, 0xa0,
+ 0xff, 0x86, 0xd1, 0x64, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd3, 0x7c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7e, 0xe8,
+ 0xfe, 0x8c, 0x7e, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7e, 0xe8, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xd6, 0x04, 0xff, 0x0e, 0x7e, 0xc0, 0xfb, 0x0c, 0x7e, 0xe4, 0x0f, 0x81, 0x80, 0x01,
+ 0x0f, 0xfc, 0x5b, 0x42, 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd8, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8e, 0x80, 0xae, 0xff, 0x7f, 0x18, 0x00, 0xfa, 0x8c, 0x7e, 0xec, 0x20, 0x7a, 0x08, 0x00,
+ 0xe6, 0x7c, 0x00, 0x02, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xd5, 0x59, 0xff, 0xa5, 0x57, 0x00,
+ 0xfb, 0x8c, 0x7f, 0x00, 0xfe, 0x8e, 0x80, 0xb4, 0xff, 0x77, 0x18, 0x00, 0xcf, 0xd4, 0xb0, 0x00,
+ 0xce, 0x58, 0xba, 0x00, 0xfd, 0x0e, 0x80, 0xa2, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0xf7, 0x28, 0x00,
+ 0xcc, 0xf0, 0xd0, 0x00, 0xfd, 0xe7, 0x18, 0x0c, 0xcf, 0x78, 0xb2, 0x00, 0x0c, 0x78, 0x00, 0x36,
+ 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c, 0xfb, 0x0d, 0x84, 0xf8, 0xfd, 0x8d, 0x80, 0x88,
+ 0xfa, 0x8d, 0x85, 0x88, 0xfc, 0x8d, 0x84, 0xe8, 0xad, 0xf2, 0xd0, 0x02, 0x6c, 0x60, 0xff, 0xff,
+ 0x8e, 0xe6, 0x00, 0x08, 0x8e, 0x66, 0x00, 0x04, 0x8f, 0x66, 0x00, 0x0c, 0x8f, 0xe6, 0x00, 0x10,
+ 0xcc, 0x60, 0xa8, 0x00, 0xcc, 0x6e, 0xc0, 0x00, 0xcc, 0x72, 0xc1, 0x00, 0xcc, 0x76, 0xc1, 0x00,
+ 0xcc, 0x7a, 0xc1, 0x00, 0xcc, 0x7e, 0xc1, 0x00, 0xcc, 0x00, 0xc1, 0x00, 0x2b, 0xdc, 0x00, 0x14,
+ 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xd4, 0xed, 0x0c, 0xe4, 0x00, 0x14, 0xff, 0xe7, 0x18, 0x00,
+ 0xff, 0x67, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xcc, 0x60, 0xf8, 0x00, 0xee, 0x01, 0xd4, 0xcc, 0x0c, 0xe4, 0x00, 0x04, 0x7f, 0xe0, 0x00, 0x10,
+ 0xcc, 0x7e, 0xc0, 0x00, 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00, 0xfc, 0x09, 0xfb, 0xa0,
+ 0xff, 0x0c, 0x7e, 0xf8, 0xff, 0x8e, 0x7e, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30,
+ 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03,
+ 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xd5, 0x24, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x8e, 0x80, 0xb2, 0xff, 0x6f, 0x18, 0x00,
+ 0xfd, 0x0e, 0x80, 0xba, 0xfe, 0xeb, 0x18, 0x00, 0xfc, 0x8e, 0x80, 0xb0, 0xfe, 0x67, 0x58, 0x00,
+ 0x4f, 0xd9, 0xdf, 0xff, 0xcf, 0xfc, 0xa8, 0x00, 0xcf, 0x04, 0xf6, 0x00, 0x2f, 0xfc, 0x00, 0x0e,
+ 0xce, 0x84, 0xee, 0x00, 0x4f, 0x79, 0x00, 0x00, 0xff, 0xef, 0x28, 0x00, 0x4c, 0x75, 0x00, 0x00,
+ 0xcf, 0x78, 0xf8, 0x00, 0x4e, 0x70, 0x00, 0x0f, 0x7e, 0x71, 0x00, 0x02, 0xfa, 0x8d, 0x85, 0x88,
+ 0xcf, 0xe0, 0xf0, 0x00, 0x7d, 0xfc, 0x00, 0x10, 0xcc, 0x6e, 0xf8, 0x00, 0x7c, 0x60, 0xff, 0xf0,
+ 0xcc, 0x00, 0xc1, 0x00, 0xce, 0x84, 0xc6, 0x00, 0xfe, 0xeb, 0x28, 0x00, 0xcc, 0xf0, 0xc8, 0x00,
+ 0xfd, 0xe7, 0x18, 0x0c, 0xfc, 0x0c, 0x7e, 0xe8, 0x4e, 0xec, 0x00, 0x09, 0x6e, 0xf4, 0xff, 0xff,
+ 0xfb, 0x0d, 0x84, 0xf8, 0xfc, 0x8d, 0x84, 0xe8, 0xfd, 0x8d, 0x80, 0x88, 0xcf, 0x78, 0xe8, 0x00,
+ 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c, 0xcf, 0x60, 0xf0, 0x00, 0x7f, 0xf8, 0x00, 0x10,
+ 0xcf, 0x7e, 0xf0, 0x00, 0x7f, 0x78, 0xff, 0xf0, 0xcf, 0x00, 0xf1, 0x00, 0xe0, 0x01, 0xd5, 0x00,
+ 0xff, 0x09, 0xfb, 0xa0, 0xff, 0x86, 0xd3, 0xf8, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd6, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7c, 0x68, 0xfe, 0x8c, 0x7c, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7c, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xd8, 0xbc, 0xff, 0x0e, 0x7c, 0x40, 0xfa, 0x8c, 0x7c, 0x64,
+ 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x00, 0x02, 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd4, 0x00, 0x09,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xae, 0xff, 0x7f, 0x18, 0x00, 0xfb, 0x0c, 0x7c, 0x6c,
+ 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x60, 0x00, 0x02, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xd7, 0xdd,
+ 0xfc, 0x25, 0x57, 0x00, 0xfb, 0x8c, 0x7c, 0x80, 0xcf, 0x58, 0xa8, 0x00, 0xfd, 0x0e, 0x80, 0xa2,
+ 0xce, 0xd4, 0xba, 0x00, 0x2f, 0x78, 0x00, 0x36, 0xff, 0x8e, 0x80, 0xb4, 0xff, 0x7f, 0x28, 0x00,
+ 0xcc, 0x74, 0xd0, 0x00, 0xff, 0x63, 0x18, 0x0c, 0xcc, 0xdc, 0xb0, 0x00, 0x4f, 0xf8, 0xff, 0xf6,
+ 0xff, 0xe3, 0x28, 0x0c, 0xfa, 0x8d, 0x84, 0xf8, 0xff, 0x0d, 0x80, 0x88, 0xfb, 0x0d, 0x85, 0x88,
+ 0xfc, 0x0d, 0x84, 0xe8, 0xad, 0xf6, 0xd0, 0x02, 0x8e, 0x62, 0x00, 0x04, 0x8f, 0x62, 0x00, 0x0c,
+ 0x8e, 0xe2, 0x00, 0x08, 0x8f, 0xe2, 0x00, 0x10, 0xcc, 0xee, 0xc8, 0x00, 0xcc, 0xf2, 0xc9, 0x00,
+ 0xcc, 0xf6, 0xc9, 0x00, 0xcc, 0xfa, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00,
+ 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xd7, 0x71, 0x0c, 0x60, 0x00, 0x14,
+ 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00,
+ 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00, 0xee, 0x01, 0xd7, 0x50, 0x0c, 0x60, 0x00, 0x04,
+ 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00,
+ 0xfc, 0x89, 0xfb, 0xa0, 0xff, 0x0c, 0x7c, 0x78, 0xff, 0x8e, 0x7c, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd7, 0xa8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xb0,
+ 0xfe, 0xff, 0x58, 0x00, 0x4f, 0x55, 0xdf, 0xff, 0xcf, 0x78, 0xb0, 0x00, 0x2f, 0x78, 0x00, 0x0e,
+ 0xff, 0x8e, 0x80, 0xb2, 0xff, 0x7f, 0x28, 0x00, 0x4e, 0xf4, 0x00, 0x0f, 0xfc, 0x8c, 0x80, 0xb0,
+ 0xfd, 0x0c, 0x80, 0xb4, 0xfd, 0x8c, 0x80, 0xb8, 0xfe, 0x0c, 0x80, 0xbc, 0xff, 0x8c, 0x80, 0xc0,
+ 0x7e, 0xf5, 0x00, 0x02, 0xfb, 0x0d, 0x85, 0x88, 0xcb, 0xf8, 0xea, 0x00, 0xcc, 0xe6, 0xc0, 0x00,
+ 0xcc, 0xea, 0xc9, 0x00, 0xcc, 0xee, 0xc9, 0x00, 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00,
+ 0xcc, 0x80, 0xc9, 0x00, 0x2e, 0xf6, 0x00, 0x14, 0xe6, 0x01, 0xd8, 0x5d, 0xfc, 0x0e, 0x80, 0xc4,
+ 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02, 0x2e, 0xf6, 0x00, 0x04, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xcc, 0xe4, 0xf8, 0x00, 0xe6, 0x01, 0xd8, 0x40, 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10,
+ 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00, 0xff, 0x8e, 0x80, 0xba,
+ 0xcf, 0x04, 0xce, 0x00, 0xff, 0x7f, 0x28, 0x00, 0xff, 0x63, 0x18, 0x0c, 0xfc, 0x8c, 0x7c, 0x68,
+ 0x4f, 0xf8, 0x00, 0x09, 0xff, 0x0d, 0x80, 0x88, 0x6f, 0xfc, 0xff, 0xff, 0xfa, 0x8d, 0x84, 0xf8,
+ 0xfc, 0x0d, 0x84, 0xe8, 0xcb, 0xdc, 0xf8, 0x00, 0x4f, 0x78, 0xff, 0xf6, 0xff, 0x63, 0x28, 0x0c,
+ 0xcf, 0xe4, 0xb8, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xe0, 0x01, 0xd7, 0x84, 0xff, 0x89, 0xfb, 0xa0, 0xff, 0x86, 0xd6, 0x8c,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd8, 0xc8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7c, 0xe8, 0xfe, 0x8c, 0x7c, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7c, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xdb, 0x74,
+ 0xff, 0x0e, 0x7c, 0xc0, 0xfa, 0x8c, 0x7c, 0xe4, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x05, 0xf2,
+ 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd4, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xae,
+ 0xff, 0x7f, 0x18, 0x00, 0xfb, 0x0c, 0x7c, 0xec, 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x60, 0x00, 0x02,
+ 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xda, 0x95, 0xfc, 0x25, 0x57, 0x00, 0xfb, 0x8c, 0x7d, 0x00,
+ 0xcf, 0x58, 0xa8, 0x00, 0xfd, 0x0e, 0x80, 0xa2, 0xce, 0xd4, 0xba, 0x00, 0x2f, 0x78, 0x00, 0x36,
+ 0xff, 0x8e, 0x80, 0xb4, 0xff, 0x7f, 0x28, 0x00, 0xcc, 0x74, 0xd0, 0x00, 0xff, 0x63, 0x18, 0x0c,
+ 0xcc, 0xdc, 0xb0, 0x00, 0x4f, 0xf8, 0xff, 0xf6, 0xff, 0xe3, 0x28, 0x0c, 0xfa, 0x8d, 0x84, 0xf8,
+ 0xff, 0x0d, 0x80, 0x88, 0xfb, 0x0d, 0x85, 0x88, 0xfc, 0x0d, 0x84, 0xe8, 0xad, 0xf6, 0xd0, 0x02,
+ 0x8e, 0x62, 0x00, 0x04, 0x8f, 0x62, 0x00, 0x0c, 0x8e, 0xe2, 0x00, 0x08, 0x8f, 0xe2, 0x00, 0x10,
+ 0xcc, 0xee, 0xc8, 0x00, 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xf6, 0xc9, 0x00, 0xcc, 0xfa, 0xc9, 0x00,
+ 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00, 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00,
+ 0xee, 0x01, 0xda, 0x29, 0x0c, 0x60, 0x00, 0x14, 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02,
+ 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00,
+ 0xee, 0x01, 0xda, 0x08, 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00,
+ 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00, 0xfc, 0x89, 0xfb, 0xa0, 0xff, 0x0c, 0x7c, 0xf8,
+ 0xff, 0x8e, 0x7c, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xda, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xb0, 0xfe, 0xff, 0x58, 0x00, 0x4f, 0x55, 0xdf, 0xff,
+ 0xcf, 0x78, 0xb0, 0x00, 0x2f, 0x78, 0x00, 0x0e, 0xff, 0x8e, 0x80, 0xb2, 0xff, 0x7f, 0x28, 0x00,
+ 0x4e, 0xf4, 0x00, 0x0f, 0xfc, 0x8c, 0x80, 0xb0, 0xfd, 0x0c, 0x80, 0xb4, 0xfd, 0x8c, 0x80, 0xb8,
+ 0xfe, 0x0c, 0x80, 0xbc, 0xff, 0x8c, 0x80, 0xc0, 0x7e, 0xf5, 0x00, 0x02, 0xfb, 0x0d, 0x85, 0x88,
+ 0xcb, 0xf8, 0xea, 0x00, 0xcc, 0xe6, 0xc0, 0x00, 0xcc, 0xea, 0xc9, 0x00, 0xcc, 0xee, 0xc9, 0x00,
+ 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00, 0x2e, 0xf6, 0x00, 0x14,
+ 0xe6, 0x01, 0xdb, 0x15, 0xfc, 0x0e, 0x80, 0xc4, 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02,
+ 0x2e, 0xf6, 0x00, 0x04, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00, 0xe6, 0x01, 0xda, 0xf8,
+ 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0,
+ 0xcc, 0x80, 0xc9, 0x00, 0xff, 0x8e, 0x80, 0xba, 0xcf, 0x04, 0xce, 0x00, 0xff, 0x7f, 0x28, 0x00,
+ 0xff, 0x63, 0x18, 0x0c, 0xfc, 0x8c, 0x7c, 0xe8, 0x4f, 0xf8, 0x00, 0x09, 0xff, 0x0d, 0x80, 0x88,
+ 0x6f, 0xfc, 0xff, 0xff, 0xfa, 0x8d, 0x84, 0xf8, 0xfc, 0x0d, 0x84, 0xe8, 0xcb, 0xdc, 0xf8, 0x00,
+ 0x4f, 0x78, 0xff, 0xf6, 0xff, 0x63, 0x28, 0x0c, 0xcf, 0xe4, 0xb8, 0x00, 0x7f, 0x7c, 0x00, 0x10,
+ 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xe0, 0x01, 0xda, 0x3c,
+ 0xff, 0x89, 0xfb, 0xa0, 0xff, 0x86, 0xd9, 0x44, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xdb, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7d, 0x68, 0xfe, 0x8c, 0x7d, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7d, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xde, 0x2c, 0xff, 0x0e, 0x7d, 0x40, 0xfa, 0x8c, 0x7d, 0x64,
+ 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x0b, 0xe2, 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd4, 0x00, 0x09,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xae, 0xff, 0x7f, 0x18, 0x00, 0xfb, 0x0c, 0x7d, 0x6c,
+ 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x60, 0x00, 0x02, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xdd, 0x4d,
+ 0xfc, 0x25, 0x57, 0x00, 0xfb, 0x8c, 0x7d, 0x80, 0xcf, 0x58, 0xa8, 0x00, 0xfd, 0x0e, 0x80, 0xa2,
+ 0xce, 0xd4, 0xba, 0x00, 0x2f, 0x78, 0x00, 0x36, 0xff, 0x8e, 0x80, 0xb4, 0xff, 0x7f, 0x28, 0x00,
+ 0xcc, 0x74, 0xd0, 0x00, 0xff, 0x63, 0x18, 0x0c, 0xcc, 0xdc, 0xb0, 0x00, 0x4f, 0xf8, 0xff, 0xf6,
+ 0xff, 0xe3, 0x28, 0x0c, 0xfa, 0x8d, 0x84, 0xf8, 0xff, 0x0d, 0x80, 0x88, 0xfb, 0x0d, 0x85, 0x88,
+ 0xfc, 0x0d, 0x84, 0xe8, 0xad, 0xf6, 0xd0, 0x02, 0x8e, 0x62, 0x00, 0x04, 0x8f, 0x62, 0x00, 0x0c,
+ 0x8e, 0xe2, 0x00, 0x08, 0x8f, 0xe2, 0x00, 0x10, 0xcc, 0xee, 0xc8, 0x00, 0xcc, 0xf2, 0xc9, 0x00,
+ 0xcc, 0xf6, 0xc9, 0x00, 0xcc, 0xfa, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00,
+ 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xdc, 0xe1, 0x0c, 0x60, 0x00, 0x14,
+ 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00,
+ 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00, 0xee, 0x01, 0xdc, 0xc0, 0x0c, 0x60, 0x00, 0x04,
+ 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00,
+ 0xfc, 0x89, 0xfb, 0xa0, 0xff, 0x0c, 0x7d, 0x78, 0xff, 0x8e, 0x7d, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xb0,
+ 0xfe, 0xff, 0x58, 0x00, 0x4f, 0x55, 0xdf, 0xff, 0xcf, 0x78, 0xb0, 0x00, 0x2f, 0x78, 0x00, 0x0e,
+ 0xff, 0x8e, 0x80, 0xb2, 0xff, 0x7f, 0x28, 0x00, 0x4e, 0xf4, 0x00, 0x0f, 0xfc, 0x8c, 0x80, 0xb0,
+ 0xfd, 0x0c, 0x80, 0xb4, 0xfd, 0x8c, 0x80, 0xb8, 0xfe, 0x0c, 0x80, 0xbc, 0xff, 0x8c, 0x80, 0xc0,
+ 0x7e, 0xf5, 0x00, 0x02, 0xfb, 0x0d, 0x85, 0x88, 0xcb, 0xf8, 0xea, 0x00, 0xcc, 0xe6, 0xc0, 0x00,
+ 0xcc, 0xea, 0xc9, 0x00, 0xcc, 0xee, 0xc9, 0x00, 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00,
+ 0xcc, 0x80, 0xc9, 0x00, 0x2e, 0xf6, 0x00, 0x14, 0xe6, 0x01, 0xdd, 0xcd, 0xfc, 0x0e, 0x80, 0xc4,
+ 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02, 0x2e, 0xf6, 0x00, 0x04, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xcc, 0xe4, 0xf8, 0x00, 0xe6, 0x01, 0xdd, 0xb0, 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10,
+ 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00, 0xff, 0x8e, 0x80, 0xba,
+ 0xcf, 0x04, 0xce, 0x00, 0xff, 0x7f, 0x28, 0x00, 0xff, 0x63, 0x18, 0x0c, 0xfc, 0x8c, 0x7d, 0x68,
+ 0x4f, 0xf8, 0x00, 0x09, 0xff, 0x0d, 0x80, 0x88, 0x6f, 0xfc, 0xff, 0xff, 0xfa, 0x8d, 0x84, 0xf8,
+ 0xfc, 0x0d, 0x84, 0xe8, 0xcb, 0xdc, 0xf8, 0x00, 0x4f, 0x78, 0xff, 0xf6, 0xff, 0x63, 0x28, 0x0c,
+ 0xcf, 0xe4, 0xb8, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xe0, 0x01, 0xdc, 0xf4, 0xff, 0x89, 0xfb, 0xa0, 0xff, 0x86, 0xdb, 0xfc,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xde, 0x38, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7d, 0xe8, 0xfe, 0x8c, 0x7d, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7d, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xe0, 0xe4,
+ 0xff, 0x0e, 0x7d, 0xc0, 0xfa, 0x8c, 0x7d, 0xe4, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x11, 0xd2,
+ 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd4, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xae,
+ 0xff, 0x7f, 0x18, 0x00, 0xfb, 0x0c, 0x7d, 0xec, 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x60, 0x00, 0x02,
+ 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xe0, 0x05, 0xfc, 0x25, 0x57, 0x00, 0xfb, 0x8c, 0x7e, 0x00,
+ 0xcf, 0x58, 0xa8, 0x00, 0xfd, 0x0e, 0x80, 0xa2, 0xce, 0xd4, 0xba, 0x00, 0x2f, 0x78, 0x00, 0x36,
+ 0xff, 0x8e, 0x80, 0xb4, 0xff, 0x7f, 0x28, 0x00, 0xcc, 0x74, 0xd0, 0x00, 0xff, 0x63, 0x18, 0x0c,
+ 0xcc, 0xdc, 0xb0, 0x00, 0x4f, 0xf8, 0xff, 0xf6, 0xff, 0xe3, 0x28, 0x0c, 0xfa, 0x8d, 0x84, 0xf8,
+ 0xff, 0x0d, 0x80, 0x88, 0xfb, 0x0d, 0x85, 0x88, 0xfc, 0x0d, 0x84, 0xe8, 0xad, 0xf6, 0xd0, 0x02,
+ 0x8e, 0x62, 0x00, 0x04, 0x8f, 0x62, 0x00, 0x0c, 0x8e, 0xe2, 0x00, 0x08, 0x8f, 0xe2, 0x00, 0x10,
+ 0xcc, 0xee, 0xc8, 0x00, 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xf6, 0xc9, 0x00, 0xcc, 0xfa, 0xc9, 0x00,
+ 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00, 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00,
+ 0xee, 0x01, 0xdf, 0x99, 0x0c, 0x60, 0x00, 0x14, 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02,
+ 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00,
+ 0xee, 0x01, 0xdf, 0x78, 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00,
+ 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00, 0xfc, 0x89, 0xfb, 0xa0, 0xff, 0x0c, 0x7d, 0xf8,
+ 0xff, 0x8e, 0x7d, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xdf, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xb0, 0xfe, 0xff, 0x58, 0x00, 0x4f, 0x55, 0xdf, 0xff,
+ 0xcf, 0x78, 0xb0, 0x00, 0x2f, 0x78, 0x00, 0x0e, 0xff, 0x8e, 0x80, 0xb2, 0xff, 0x7f, 0x28, 0x00,
+ 0x4e, 0xf4, 0x00, 0x0f, 0xfc, 0x8c, 0x80, 0xb0, 0xfd, 0x0c, 0x80, 0xb4, 0xfd, 0x8c, 0x80, 0xb8,
+ 0xfe, 0x0c, 0x80, 0xbc, 0xff, 0x8c, 0x80, 0xc0, 0x7e, 0xf5, 0x00, 0x02, 0xfb, 0x0d, 0x85, 0x88,
+ 0xcb, 0xf8, 0xea, 0x00, 0xcc, 0xe6, 0xc0, 0x00, 0xcc, 0xea, 0xc9, 0x00, 0xcc, 0xee, 0xc9, 0x00,
+ 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00, 0x2e, 0xf6, 0x00, 0x14,
+ 0xe6, 0x01, 0xe0, 0x85, 0xfc, 0x0e, 0x80, 0xc4, 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02,
+ 0x2e, 0xf6, 0x00, 0x04, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00, 0xe6, 0x01, 0xe0, 0x68,
+ 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0,
+ 0xcc, 0x80, 0xc9, 0x00, 0xff, 0x8e, 0x80, 0xba, 0xcf, 0x04, 0xce, 0x00, 0xff, 0x7f, 0x28, 0x00,
+ 0xff, 0x63, 0x18, 0x0c, 0xfc, 0x8c, 0x7d, 0xe8, 0x4f, 0xf8, 0x00, 0x09, 0xff, 0x0d, 0x80, 0x88,
+ 0x6f, 0xfc, 0xff, 0xff, 0xfa, 0x8d, 0x84, 0xf8, 0xfc, 0x0d, 0x84, 0xe8, 0xcb, 0xdc, 0xf8, 0x00,
+ 0x4f, 0x78, 0xff, 0xf6, 0xff, 0x63, 0x28, 0x0c, 0xcf, 0xe4, 0xb8, 0x00, 0x7f, 0x7c, 0x00, 0x10,
+ 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xe0, 0x01, 0xdf, 0xac,
+ 0xff, 0x89, 0xfb, 0xa0, 0xff, 0x86, 0xde, 0xb4, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe0, 0xf0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7e, 0x68, 0xfe, 0x8c, 0x7e, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7e, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xe3, 0x9c, 0xff, 0x0e, 0x7e, 0x40, 0xfa, 0x8c, 0x7e, 0x64,
+ 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x36, 0x8a, 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd4, 0x00, 0x09,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xae, 0xff, 0x7f, 0x18, 0x00, 0xfb, 0x0c, 0x7e, 0x6c,
+ 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x60, 0x00, 0x02, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xe2, 0xbd,
+ 0xfc, 0x25, 0x57, 0x00, 0xfb, 0x8c, 0x7e, 0x80, 0xcf, 0x58, 0xa8, 0x00, 0xfd, 0x0e, 0x80, 0xa2,
+ 0xce, 0xd4, 0xba, 0x00, 0x2f, 0x78, 0x00, 0x36, 0xff, 0x8e, 0x80, 0xb4, 0xff, 0x7f, 0x28, 0x00,
+ 0xcc, 0x74, 0xd0, 0x00, 0xff, 0x63, 0x18, 0x0c, 0xcc, 0xdc, 0xb0, 0x00, 0x4f, 0xf8, 0xff, 0xf6,
+ 0xff, 0xe3, 0x28, 0x0c, 0xfa, 0x8d, 0x84, 0xf8, 0xff, 0x0d, 0x80, 0x88, 0xfb, 0x0d, 0x85, 0x88,
+ 0xfc, 0x0d, 0x84, 0xe8, 0xad, 0xf6, 0xd0, 0x02, 0x8e, 0x62, 0x00, 0x04, 0x8f, 0x62, 0x00, 0x0c,
+ 0x8e, 0xe2, 0x00, 0x08, 0x8f, 0xe2, 0x00, 0x10, 0xcc, 0xee, 0xc8, 0x00, 0xcc, 0xf2, 0xc9, 0x00,
+ 0xcc, 0xf6, 0xc9, 0x00, 0xcc, 0xfa, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00,
+ 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xe2, 0x51, 0x0c, 0x60, 0x00, 0x14,
+ 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00,
+ 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00, 0xee, 0x01, 0xe2, 0x30, 0x0c, 0x60, 0x00, 0x04,
+ 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00,
+ 0xfc, 0x89, 0xfb, 0xa0, 0xff, 0x0c, 0x7e, 0x78, 0xff, 0x8e, 0x7e, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe2, 0x88, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xb0,
+ 0xfe, 0xff, 0x58, 0x00, 0x4f, 0x55, 0xdf, 0xff, 0xcf, 0x78, 0xb0, 0x00, 0x2f, 0x78, 0x00, 0x0e,
+ 0xff, 0x8e, 0x80, 0xb2, 0xff, 0x7f, 0x28, 0x00, 0x4e, 0xf4, 0x00, 0x0f, 0xfc, 0x8c, 0x80, 0xb0,
+ 0xfd, 0x0c, 0x80, 0xb4, 0xfd, 0x8c, 0x80, 0xb8, 0xfe, 0x0c, 0x80, 0xbc, 0xff, 0x8c, 0x80, 0xc0,
+ 0x7e, 0xf5, 0x00, 0x02, 0xfb, 0x0d, 0x85, 0x88, 0xcb, 0xf8, 0xea, 0x00, 0xcc, 0xe6, 0xc0, 0x00,
+ 0xcc, 0xea, 0xc9, 0x00, 0xcc, 0xee, 0xc9, 0x00, 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00,
+ 0xcc, 0x80, 0xc9, 0x00, 0x2e, 0xf6, 0x00, 0x14, 0xe6, 0x01, 0xe3, 0x3d, 0xfc, 0x0e, 0x80, 0xc4,
+ 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02, 0x2e, 0xf6, 0x00, 0x04, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xcc, 0xe4, 0xf8, 0x00, 0xe6, 0x01, 0xe3, 0x20, 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10,
+ 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00, 0xff, 0x8e, 0x80, 0xba,
+ 0xcf, 0x04, 0xce, 0x00, 0xff, 0x7f, 0x28, 0x00, 0xff, 0x63, 0x18, 0x0c, 0xfc, 0x8c, 0x7e, 0x68,
+ 0x4f, 0xf8, 0x00, 0x09, 0xff, 0x0d, 0x80, 0x88, 0x6f, 0xfc, 0xff, 0xff, 0xfa, 0x8d, 0x84, 0xf8,
+ 0xfc, 0x0d, 0x84, 0xe8, 0xcb, 0xdc, 0xf8, 0x00, 0x4f, 0x78, 0xff, 0xf6, 0xff, 0x63, 0x28, 0x0c,
+ 0xcf, 0xe4, 0xb8, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xe0, 0x01, 0xe2, 0x64, 0xff, 0x89, 0xfb, 0xa0, 0xff, 0x86, 0xe1, 0x6c,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe3, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7e, 0xe8, 0xfe, 0x8c, 0x7e, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7e, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xe6, 0x54,
+ 0xff, 0x0e, 0x7e, 0xc0, 0xfa, 0x8c, 0x7e, 0xe4, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x5b, 0x42,
+ 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd4, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x80, 0xa0,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xae,
+ 0xff, 0x7f, 0x18, 0x00, 0xfb, 0x0c, 0x7e, 0xec, 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x60, 0x00, 0x02,
+ 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xe5, 0x75, 0xfc, 0x25, 0x57, 0x00, 0xfb, 0x8c, 0x7f, 0x00,
+ 0xcf, 0x58, 0xa8, 0x00, 0xfd, 0x0e, 0x80, 0xa2, 0xce, 0xd4, 0xba, 0x00, 0x2f, 0x78, 0x00, 0x36,
+ 0xff, 0x8e, 0x80, 0xb4, 0xff, 0x7f, 0x28, 0x00, 0xcc, 0x74, 0xd0, 0x00, 0xff, 0x63, 0x18, 0x0c,
+ 0xcc, 0xdc, 0xb0, 0x00, 0x4f, 0xf8, 0xff, 0xf6, 0xff, 0xe3, 0x28, 0x0c, 0xfa, 0x8d, 0x84, 0xf8,
+ 0xff, 0x0d, 0x80, 0x88, 0xfb, 0x0d, 0x85, 0x88, 0xfc, 0x0d, 0x84, 0xe8, 0xad, 0xf6, 0xd0, 0x02,
+ 0x8e, 0x62, 0x00, 0x04, 0x8f, 0x62, 0x00, 0x0c, 0x8e, 0xe2, 0x00, 0x08, 0x8f, 0xe2, 0x00, 0x10,
+ 0xcc, 0xee, 0xc8, 0x00, 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xf6, 0xc9, 0x00, 0xcc, 0xfa, 0xc9, 0x00,
+ 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00, 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00,
+ 0xee, 0x01, 0xe5, 0x09, 0x0c, 0x60, 0x00, 0x14, 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02,
+ 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00,
+ 0xee, 0x01, 0xe4, 0xe8, 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00,
+ 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00, 0xfc, 0x89, 0xfb, 0xa0, 0xff, 0x0c, 0x7e, 0xf8,
+ 0xff, 0x8e, 0x7e, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe5, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x80, 0xb0, 0xfe, 0xff, 0x58, 0x00, 0x4f, 0x55, 0xdf, 0xff,
+ 0xcf, 0x78, 0xb0, 0x00, 0x2f, 0x78, 0x00, 0x0e, 0xff, 0x8e, 0x80, 0xb2, 0xff, 0x7f, 0x28, 0x00,
+ 0x4e, 0xf4, 0x00, 0x0f, 0xfc, 0x8c, 0x80, 0xb0, 0xfd, 0x0c, 0x80, 0xb4, 0xfd, 0x8c, 0x80, 0xb8,
+ 0xfe, 0x0c, 0x80, 0xbc, 0xff, 0x8c, 0x80, 0xc0, 0x7e, 0xf5, 0x00, 0x02, 0xfb, 0x0d, 0x85, 0x88,
+ 0xcb, 0xf8, 0xea, 0x00, 0xcc, 0xe6, 0xc0, 0x00, 0xcc, 0xea, 0xc9, 0x00, 0xcc, 0xee, 0xc9, 0x00,
+ 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00, 0x2e, 0xf6, 0x00, 0x14,
+ 0xe6, 0x01, 0xe5, 0xf5, 0xfc, 0x0e, 0x80, 0xc4, 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02,
+ 0x2e, 0xf6, 0x00, 0x04, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00, 0xe6, 0x01, 0xe5, 0xd8,
+ 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0,
+ 0xcc, 0x80, 0xc9, 0x00, 0xff, 0x8e, 0x80, 0xba, 0xcf, 0x04, 0xce, 0x00, 0xff, 0x7f, 0x28, 0x00,
+ 0xff, 0x63, 0x18, 0x0c, 0xfc, 0x8c, 0x7e, 0xe8, 0x4f, 0xf8, 0x00, 0x09, 0xff, 0x0d, 0x80, 0x88,
+ 0x6f, 0xfc, 0xff, 0xff, 0xfa, 0x8d, 0x84, 0xf8, 0xfc, 0x0d, 0x84, 0xe8, 0xcb, 0xdc, 0xf8, 0x00,
+ 0x4f, 0x78, 0xff, 0xf6, 0xff, 0x63, 0x28, 0x0c, 0xcf, 0xe4, 0xb8, 0x00, 0x7f, 0x7c, 0x00, 0x10,
+ 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xe0, 0x01, 0xe5, 0x1c,
+ 0xff, 0x89, 0xfb, 0xa0, 0xff, 0x86, 0xe4, 0x24, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe6, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7c, 0x68, 0xfe, 0x8c, 0x7c, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7c, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xe7, 0xfc, 0xff, 0x0e, 0x7c, 0x40, 0xfe, 0x0c, 0x7c, 0x64,
+ 0xfc, 0x24, 0x57, 0x00, 0xfe, 0x8c, 0x84, 0xf8, 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x84, 0xe8,
+ 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00,
+ 0xff, 0x8c, 0x7c, 0x68, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x00, 0x02, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xfb, 0xa0, 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x80, 0xa2,
+ 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10,
+ 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03,
+ 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xfb, 0xa0, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x01, 0xe7, 0x9c, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x80, 0xba, 0xfc, 0xf3, 0x18, 0x00,
+ 0xfe, 0x8c, 0x80, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0,
+ 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xe7, 0xf5,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x80, 0xb4, 0xff, 0x0c, 0x7c, 0x78,
+ 0xff, 0x8e, 0x7c, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe7, 0xc0,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xe7, 0x94, 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xe6, 0xdc,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe8, 0x08, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7c, 0xe8, 0xfe, 0x8c, 0x7c, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7c, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xe9, 0xa4,
+ 0xff, 0x0e, 0x7c, 0xc0, 0xfe, 0x0c, 0x7c, 0xe4, 0xfc, 0x24, 0x57, 0x00, 0xfe, 0x8c, 0x84, 0xf8,
+ 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x84, 0xe8, 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff,
+ 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x7c, 0xe8, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x05, 0xf2, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xfb, 0xa0,
+ 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x80, 0xa2, 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00,
+ 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30,
+ 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00,
+ 0xfc, 0x89, 0xfb, 0xa0, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xe9, 0x44, 0x9f, 0x6e, 0x00, 0x04,
+ 0xfe, 0x0e, 0x80, 0xba, 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x80, 0xb4, 0x0e, 0xf7, 0x00, 0x01,
+ 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00,
+ 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xe9, 0x9d, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00,
+ 0xfe, 0x8d, 0x80, 0xb4, 0xff, 0x0c, 0x7c, 0xf8, 0xff, 0x8e, 0x7c, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe9, 0x68, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xe9, 0x3c,
+ 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xe8, 0x84, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe9, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7d, 0x68, 0xfe, 0x8c, 0x7d, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7d, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xeb, 0x4c, 0xff, 0x0e, 0x7d, 0x40, 0xfe, 0x0c, 0x7d, 0x64,
+ 0xfc, 0x24, 0x57, 0x00, 0xfe, 0x8c, 0x84, 0xf8, 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x84, 0xe8,
+ 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00,
+ 0xff, 0x8c, 0x7d, 0x68, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x0b, 0xe2, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xfb, 0xa0, 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x80, 0xa2,
+ 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10,
+ 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03,
+ 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xfb, 0xa0, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x01, 0xea, 0xec, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x80, 0xba, 0xfc, 0xf3, 0x18, 0x00,
+ 0xfe, 0x8c, 0x80, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0,
+ 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xeb, 0x45,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x80, 0xb4, 0xff, 0x0c, 0x7d, 0x78,
+ 0xff, 0x8e, 0x7d, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xeb, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xea, 0xe4, 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xea, 0x2c,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xeb, 0x58, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7d, 0xe8, 0xfe, 0x8c, 0x7d, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7d, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xec, 0xf4,
+ 0xff, 0x0e, 0x7d, 0xc0, 0xfe, 0x0c, 0x7d, 0xe4, 0xfc, 0x24, 0x57, 0x00, 0xfe, 0x8c, 0x84, 0xf8,
+ 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x84, 0xe8, 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff,
+ 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x7d, 0xe8, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x11, 0xd2, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xfb, 0xa0,
+ 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x80, 0xa2, 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00,
+ 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30,
+ 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00,
+ 0xfc, 0x89, 0xfb, 0xa0, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xec, 0x94, 0x9f, 0x6e, 0x00, 0x04,
+ 0xfe, 0x0e, 0x80, 0xba, 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x80, 0xb4, 0x0e, 0xf7, 0x00, 0x01,
+ 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00,
+ 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xec, 0xed, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00,
+ 0xfe, 0x8d, 0x80, 0xb4, 0xff, 0x0c, 0x7d, 0xf8, 0xff, 0x8e, 0x7d, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xec, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xec, 0x8c,
+ 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xeb, 0xd4, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xed, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7e, 0x68, 0xfe, 0x8c, 0x7e, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7e, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xee, 0x9c, 0xff, 0x0e, 0x7e, 0x40, 0xfe, 0x0c, 0x7e, 0x64,
+ 0xfc, 0x24, 0x57, 0x00, 0xfe, 0x8c, 0x84, 0xf8, 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x84, 0xe8,
+ 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00,
+ 0xff, 0x8c, 0x7e, 0x68, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x36, 0x8a, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xfb, 0xa0, 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x80, 0xa2,
+ 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10,
+ 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03,
+ 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xfb, 0xa0, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x01, 0xee, 0x3c, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x80, 0xba, 0xfc, 0xf3, 0x18, 0x00,
+ 0xfe, 0x8c, 0x80, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0,
+ 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xee, 0x95,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x80, 0xb4, 0xff, 0x0c, 0x7e, 0x78,
+ 0xff, 0x8e, 0x7e, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xee, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xee, 0x34, 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xed, 0x7c,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xee, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7e, 0xe8, 0xfe, 0x8c, 0x7e, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7e, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xf0, 0x44,
+ 0xff, 0x0e, 0x7e, 0xc0, 0xfe, 0x0c, 0x7e, 0xe4, 0xfc, 0x24, 0x57, 0x00, 0xfe, 0x8c, 0x84, 0xf8,
+ 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x84, 0xe8, 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff,
+ 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x7e, 0xe8, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x5b, 0x42, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xfb, 0xa0,
+ 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x80, 0xa2, 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00,
+ 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30,
+ 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00,
+ 0xfc, 0x89, 0xfb, 0xa0, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xef, 0xe4, 0x9f, 0x6e, 0x00, 0x04,
+ 0xfe, 0x0e, 0x80, 0xba, 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x80, 0xb4, 0x0e, 0xf7, 0x00, 0x01,
+ 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00,
+ 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xf0, 0x3d, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00,
+ 0xfe, 0x8d, 0x80, 0xb4, 0xff, 0x0c, 0x7e, 0xf8, 0xff, 0x8e, 0x7e, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf0, 0x08, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xef, 0xdc,
+ 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xef, 0x24, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf0, 0x50,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7c, 0x68, 0xfe, 0x8c, 0x7c, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00,
+ 0xff, 0x0d, 0x7c, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xf1, 0xf0, 0xff, 0x0e, 0x7c, 0x40,
+ 0xfe, 0x0c, 0x7c, 0x64, 0xfc, 0x24, 0x57, 0x00, 0xfe, 0x8c, 0x84, 0xf8, 0x0f, 0x01, 0x20, 0x00,
+ 0xfd, 0x8c, 0x84, 0xe8, 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00,
+ 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x7c, 0x68, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x00, 0x02,
+ 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xfb, 0xa0, 0x8f, 0x6e, 0x00, 0x04,
+ 0xfd, 0x0e, 0x80, 0xa2, 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00,
+ 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00,
+ 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00,
+ 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xfb, 0xa0,
+ 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xf1, 0x90, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x80, 0xba,
+ 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x80, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe,
+ 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff,
+ 0xe6, 0x01, 0xf1, 0xe9, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x80, 0xb4,
+ 0xff, 0x0c, 0x7c, 0x78, 0xff, 0x8e, 0x7c, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30,
+ 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03,
+ 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xf1, 0xb4, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xf1, 0x88, 0xcc, 0xe0, 0x00, 0x00,
+ 0xff, 0x86, 0xf0, 0xd0, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf1, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7c, 0xe8,
+ 0xfe, 0x8c, 0x7c, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7c, 0xe8,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xf3, 0x9c, 0xff, 0x0e, 0x7c, 0xc0, 0xfe, 0x0c, 0x7c, 0xe4,
+ 0xfc, 0x24, 0x57, 0x00, 0xfe, 0x8c, 0x84, 0xf8, 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x84, 0xe8,
+ 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00,
+ 0xff, 0x8c, 0x7c, 0xe8, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x05, 0xf2, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xfb, 0xa0, 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x80, 0xa2,
+ 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10,
+ 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03,
+ 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xfb, 0xa0, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x01, 0xf3, 0x3c, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x80, 0xba, 0xfc, 0xf3, 0x18, 0x00,
+ 0xfe, 0x8c, 0x80, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0,
+ 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xf3, 0x95,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x80, 0xb4, 0xff, 0x0c, 0x7c, 0xf8,
+ 0xff, 0x8e, 0x7c, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf3, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xf3, 0x34, 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xf2, 0x7c,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf3, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7d, 0x68, 0xfe, 0x8c, 0x7d, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08,
+ 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7d, 0x68, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xf5, 0x48, 0xff, 0x0e, 0x7d, 0x40, 0xfe, 0x0c, 0x7d, 0x64, 0xfc, 0x24, 0x57, 0x00,
+ 0xfe, 0x8c, 0x84, 0xf8, 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x84, 0xe8, 0xcf, 0x74, 0xf4, 0x00,
+ 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x7d, 0x68,
+ 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x0b, 0xe2, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30,
+ 0xfc, 0x88, 0xfb, 0xa0, 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x80, 0xa2, 0x9d, 0x02, 0xfe, 0x30,
+ 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10,
+ 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00,
+ 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xfb, 0xa0, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xf4, 0xe8,
+ 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x80, 0xba, 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x80, 0xb4,
+ 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00,
+ 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xf5, 0x41, 0x00, 0x00, 0x00, 0x01,
+ 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x80, 0xb4, 0xff, 0x0c, 0x7d, 0x78, 0xff, 0x8e, 0x7d, 0x40,
+ 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00,
+ 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf5, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0xf4, 0xe0, 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xf4, 0x28, 0x9e, 0xfa, 0x00, 0x20,
+ 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xf5, 0x54, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00,
+ 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7d, 0xe8, 0xfe, 0x8c, 0x7d, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7d, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xf6, 0xf4,
+ 0xff, 0x0e, 0x7d, 0xc0, 0xfe, 0x0c, 0x7d, 0xe4, 0xfc, 0x24, 0x57, 0x00, 0xfe, 0x8c, 0x84, 0xf8,
+ 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x84, 0xe8, 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff,
+ 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x7d, 0xe8, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x11, 0xd2, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xfb, 0xa0,
+ 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x80, 0xa2, 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00,
+ 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30,
+ 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00,
+ 0xfc, 0x89, 0xfb, 0xa0, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xf6, 0x94, 0x9f, 0x6e, 0x00, 0x04,
+ 0xfe, 0x0e, 0x80, 0xba, 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x80, 0xb4, 0x0e, 0xf7, 0x00, 0x01,
+ 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00,
+ 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xf6, 0xed, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00,
+ 0xfe, 0x8d, 0x80, 0xb4, 0xff, 0x0c, 0x7d, 0xf8, 0xff, 0x8e, 0x7d, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf6, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xf6, 0x8c,
+ 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xf5, 0xd4, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf7, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7e, 0x68, 0xfe, 0x8c, 0x7e, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00,
+ 0xff, 0x0d, 0x7e, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xf8, 0xa0, 0xff, 0x0e, 0x7e, 0x40,
+ 0xfe, 0x0c, 0x7e, 0x64, 0xfc, 0x24, 0x57, 0x00, 0xfe, 0x8c, 0x84, 0xf8, 0x0f, 0x01, 0x20, 0x00,
+ 0xfd, 0x8c, 0x84, 0xe8, 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00,
+ 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x7e, 0x68, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x36, 0x8a,
+ 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xfb, 0xa0, 0x8f, 0x6e, 0x00, 0x04,
+ 0xfd, 0x0e, 0x80, 0xa2, 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00,
+ 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00,
+ 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00,
+ 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xfb, 0xa0,
+ 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xf8, 0x40, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x80, 0xba,
+ 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x80, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe,
+ 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff,
+ 0xe6, 0x01, 0xf8, 0x99, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x80, 0xb4,
+ 0xff, 0x0c, 0x7e, 0x78, 0xff, 0x8e, 0x7e, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30,
+ 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03,
+ 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xf8, 0x64, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xf8, 0x38, 0xcc, 0xe0, 0x00, 0x00,
+ 0xff, 0x86, 0xf7, 0x80, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf8, 0xac, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7e, 0xe8,
+ 0xfe, 0x8c, 0x7e, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7e, 0xe8,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xfa, 0x4c, 0xff, 0x0e, 0x7e, 0xc0, 0xfe, 0x0c, 0x7e, 0xe4,
+ 0xfc, 0x24, 0x57, 0x00, 0xfe, 0x8c, 0x84, 0xf8, 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x84, 0xe8,
+ 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00,
+ 0xff, 0x8c, 0x7e, 0xe8, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x5b, 0x42, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xfb, 0xa0, 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x80, 0xa2,
+ 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10,
+ 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03,
+ 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xfb, 0xa0, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x01, 0xf9, 0xec, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x80, 0xba, 0xfc, 0xf3, 0x18, 0x00,
+ 0xfe, 0x8c, 0x80, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0,
+ 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xfa, 0x45,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x80, 0xb4, 0xff, 0x0c, 0x7e, 0xf8,
+ 0xff, 0x8e, 0x7e, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xfa, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xf9, 0xe4, 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xf9, 0x2c,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xfa, 0x58, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7c, 0x68, 0xfe, 0x8c, 0x7c, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7c, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xfc, 0xac,
+ 0xff, 0x0e, 0x7c, 0x40, 0xfe, 0x8c, 0x7c, 0x64, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x00, 0x02,
+ 0xfa, 0xa4, 0x57, 0x00, 0xfd, 0x8c, 0x84, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x84, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x7c, 0x68,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x01, 0xfc, 0x45, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xfb, 0xa0, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x85, 0x88, 0xfc, 0x8c, 0x80, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x01, 0xfb, 0xed, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x80, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x7c, 0x78, 0xff, 0x8e, 0x7c, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xfb, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x80, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x80, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x01, 0xfc, 0x3d,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xfb, 0x60, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x01, 0xfc, 0x34,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x00, 0x02, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x81, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x81, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x01, 0xfb, 0x10, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x86, 0xfa, 0xd4,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xfc, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7c, 0xe8, 0xfe, 0x8c, 0x7c, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7c, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xff, 0x0c,
+ 0xff, 0x0e, 0x7c, 0xc0, 0xfe, 0x8c, 0x7c, 0xe4, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x05, 0xf2,
+ 0xfa, 0xa4, 0x57, 0x00, 0xfd, 0x8c, 0x84, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x84, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x7c, 0xe8,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x01, 0xfe, 0xa5, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xfb, 0xa0, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x85, 0x88, 0xfc, 0x8c, 0x80, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x01, 0xfe, 0x4d, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x80, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x7c, 0xf8, 0xff, 0x8e, 0x7c, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xfe, 0x18, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x80, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x80, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x01, 0xfe, 0x9d,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xfd, 0xc0, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x01, 0xfe, 0x94,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x05, 0xf2, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x81, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x81, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x01, 0xfd, 0x70, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x86, 0xfd, 0x34,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xff, 0x18, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7d, 0x68, 0xfe, 0x8c, 0x7d, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7d, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x01, 0x6c,
+ 0xff, 0x0e, 0x7d, 0x40, 0xfe, 0x8c, 0x7d, 0x64, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x0b, 0xe2,
+ 0xfa, 0xa4, 0x57, 0x00, 0xfd, 0x8c, 0x84, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x84, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x7d, 0x68,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x02, 0x01, 0x05, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xfb, 0xa0, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x85, 0x88, 0xfc, 0x8c, 0x80, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x00, 0xad, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x80, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x7d, 0x78, 0xff, 0x8e, 0x7d, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x00, 0x78, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x80, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x80, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x02, 0x00, 0xfd,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x00, 0x20, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x02, 0x00, 0xf4,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x0b, 0xe2, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x81, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x81, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x01, 0xff, 0xd0, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x86, 0xff, 0x94,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x01, 0x78, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7d, 0xe8, 0xfe, 0x8c, 0x7d, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7d, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x03, 0xcc,
+ 0xff, 0x0e, 0x7d, 0xc0, 0xfe, 0x8c, 0x7d, 0xe4, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x11, 0xd2,
+ 0xfa, 0xa4, 0x57, 0x00, 0xfd, 0x8c, 0x84, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x84, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x7d, 0xe8,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x02, 0x03, 0x65, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xfb, 0xa0, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x85, 0x88, 0xfc, 0x8c, 0x80, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x03, 0x0d, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x80, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x7d, 0xf8, 0xff, 0x8e, 0x7d, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x02, 0xd8, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x80, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x80, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x02, 0x03, 0x5d,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x02, 0x80, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x02, 0x03, 0x54,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x11, 0xd2, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x81, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x81, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x02, 0x30, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x8a, 0x01, 0xf4,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x03, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7e, 0x68, 0xfe, 0x8c, 0x7e, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7e, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x06, 0x2c,
+ 0xff, 0x0e, 0x7e, 0x40, 0xfe, 0x8c, 0x7e, 0x64, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x36, 0x8a,
+ 0xfa, 0xa4, 0x57, 0x00, 0xfd, 0x8c, 0x84, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x84, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x7e, 0x68,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x02, 0x05, 0xc5, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xfb, 0xa0, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x85, 0x88, 0xfc, 0x8c, 0x80, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x05, 0x6d, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x80, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x7e, 0x78, 0xff, 0x8e, 0x7e, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x05, 0x38, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x80, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x80, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x02, 0x05, 0xbd,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x04, 0xe0, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x02, 0x05, 0xb4,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x36, 0x8a, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x81, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x81, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x04, 0x90, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x8a, 0x04, 0x54,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x06, 0x38, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7e, 0xe8, 0xfe, 0x8c, 0x7e, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7e, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x08, 0x8c,
+ 0xff, 0x0e, 0x7e, 0xc0, 0xfe, 0x8c, 0x7e, 0xe4, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x5b, 0x42,
+ 0xfa, 0xa4, 0x57, 0x00, 0xfd, 0x8c, 0x84, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x84, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x7e, 0xe8,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x02, 0x08, 0x25, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xfb, 0xa0, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x85, 0x88, 0xfc, 0x8c, 0x80, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x07, 0xcd, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x80, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x7e, 0xf8, 0xff, 0x8e, 0x7e, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x07, 0x98, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x80, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x80, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x02, 0x08, 0x1d,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x07, 0x40, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x02, 0x08, 0x14,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x5b, 0x42, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x81, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x81, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x06, 0xf0, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x8a, 0x06, 0xb4,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x08, 0x98, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7c, 0x68, 0xfe, 0x8c, 0x7c, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08,
+ 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7c, 0x68, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x02, 0x0a, 0xf0, 0xff, 0x0e, 0x7c, 0x40, 0xfe, 0x8c, 0x7c, 0x64, 0x0f, 0x01, 0x80, 0x01,
+ 0x0f, 0x78, 0x00, 0x02, 0xfa, 0xa4, 0x57, 0x00, 0xfd, 0x8c, 0x84, 0xf8, 0x0f, 0x81, 0x20, 0x00,
+ 0xfb, 0x8c, 0x84, 0xe8, 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00,
+ 0xf9, 0x8c, 0x7c, 0x68, 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x02, 0x0a, 0x89,
+ 0x5b, 0x6d, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xfb, 0xa0,
+ 0xff, 0x0e, 0x80, 0xa2, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x85, 0x88, 0xfc, 0x8c, 0x80, 0x88,
+ 0x4e, 0xf5, 0xdf, 0xff, 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00,
+ 0x4f, 0xe4, 0x00, 0x09, 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x0a, 0x31, 0xcd, 0x68, 0xf8, 0x00,
+ 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x80, 0xb4, 0xff, 0xfb, 0x28, 0x00,
+ 0xfc, 0xdf, 0x28, 0x0c, 0xff, 0x0c, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01,
+ 0xff, 0x0d, 0x4b, 0xf8, 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10,
+ 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xdf, 0x28, 0x10, 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x7c, 0x78, 0xff, 0x8e, 0x7c, 0x40,
+ 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00,
+ 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x09, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0xfa, 0x0e, 0x80, 0xba, 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e,
+ 0x6e, 0xf4, 0xff, 0xff, 0xff, 0x0e, 0x80, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00,
+ 0xfc, 0xdf, 0x28, 0x0c, 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00,
+ 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff,
+ 0xe6, 0x02, 0x0a, 0x81, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x09, 0xa4, 0xfe, 0x53, 0x28, 0x00,
+ 0xe0, 0x02, 0x0a, 0x78, 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x00, 0x02,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00,
+ 0xff, 0x0e, 0x81, 0x00, 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x81, 0x02, 0x9f, 0x02, 0xfe, 0x68,
+ 0xff, 0x0e, 0x80, 0xa2, 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00,
+ 0xcf, 0x78, 0xfa, 0x00, 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x09, 0x54, 0xcb, 0x58, 0xe8, 0x00,
+ 0xff, 0x8a, 0x09, 0x18, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x0a, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7c, 0xe8,
+ 0xfe, 0x8c, 0x7c, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7c, 0xe8,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x0d, 0x54, 0xff, 0x0e, 0x7c, 0xc0, 0xfe, 0x8c, 0x7c, 0xe4,
+ 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x05, 0xf2, 0xfa, 0xa4, 0x57, 0x00, 0xfd, 0x8c, 0x84, 0xf8,
+ 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x84, 0xe8, 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff,
+ 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x7c, 0xe8, 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b,
+ 0xe2, 0x02, 0x0c, 0xed, 0x5b, 0x6d, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30,
+ 0xfd, 0x08, 0xfb, 0xa0, 0xff, 0x0e, 0x80, 0xa2, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x85, 0x88,
+ 0xfc, 0x8c, 0x80, 0x88, 0x4e, 0xf5, 0xdf, 0xff, 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00,
+ 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09, 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x0c, 0x95,
+ 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x80, 0xb4,
+ 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c, 0xff, 0x0c, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00,
+ 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf8, 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00,
+ 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00,
+ 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10, 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x7c, 0xf8,
+ 0xff, 0x8e, 0x7c, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x0c, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x80, 0xba, 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff, 0xff, 0x0e, 0x80, 0xb2, 0xff, 0xfb, 0x28, 0x00,
+ 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c, 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10,
+ 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00,
+ 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x02, 0x0c, 0xe5, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x0c, 0x08,
+ 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x02, 0x0c, 0xdc, 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01,
+ 0x0f, 0xfc, 0x05, 0xf2, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68,
+ 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x81, 0x00, 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68,
+ 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x81, 0x02,
+ 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x80, 0xa2, 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00,
+ 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01,
+ 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00, 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x0b, 0xb8,
+ 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x8a, 0x0b, 0x7c, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x0d, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x7d, 0x68, 0xfe, 0x8c, 0x7d, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00,
+ 0xff, 0x0d, 0x7d, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x0f, 0xb8, 0xff, 0x0e, 0x7d, 0x40,
+ 0xfe, 0x8c, 0x7d, 0x64, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x0b, 0xe2, 0xfa, 0xa4, 0x57, 0x00,
+ 0xfd, 0x8c, 0x84, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x84, 0xe8, 0xcf, 0xec, 0xfc, 0x00,
+ 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x7d, 0x68, 0xcf, 0xec, 0xe0, 0x00,
+ 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x02, 0x0f, 0x51, 0x5b, 0x6d, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x30,
+ 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xfb, 0xa0, 0xff, 0x0e, 0x80, 0xa2, 0x9f, 0x02, 0xfe, 0x30,
+ 0xfc, 0x0c, 0x85, 0x88, 0xfc, 0x8c, 0x80, 0x88, 0x4e, 0xf5, 0xdf, 0xff, 0x6f, 0xe0, 0xff, 0xff,
+ 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09, 0x20, 0x56, 0x00, 0x00,
+ 0xe6, 0x02, 0x0e, 0xf9, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x36,
+ 0xff, 0x0e, 0x80, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c, 0xff, 0x0c, 0x4b, 0xf8,
+ 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf8, 0xcf, 0xea, 0x98, 0x00,
+ 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10, 0x9b, 0x02, 0xfe, 0x30,
+ 0xff, 0x0c, 0x7d, 0x78, 0xff, 0x8e, 0x7d, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30,
+ 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03,
+ 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x0e, 0xc4, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x80, 0xba, 0xfe, 0x53, 0x18, 0x00,
+ 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff, 0xff, 0x0e, 0x80, 0xb2,
+ 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c, 0xce, 0x70, 0xc0, 0x00,
+ 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00,
+ 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x02, 0x0f, 0x49, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x02, 0x0e, 0x6c, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x02, 0x0f, 0x40, 0xce, 0x54, 0x00, 0x00,
+ 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x0b, 0xe2, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x08,
+ 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x81, 0x00, 0xcf, 0xfc, 0xea, 0x00,
+ 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x0e, 0x81, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x80, 0xa2, 0x9e, 0x82, 0xfe, 0x68,
+ 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00, 0xce, 0x7c, 0x00, 0x00,
+ 0xe0, 0x02, 0x0e, 0x1c, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x8a, 0x0d, 0xe0, 0x9e, 0xfa, 0x00, 0x20,
+ 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x0f, 0xc4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00,
+ 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7d, 0xe8, 0xfe, 0x8c, 0x7d, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7d, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x12, 0x1c,
+ 0xff, 0x0e, 0x7d, 0xc0, 0xfe, 0x8c, 0x7d, 0xe4, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x11, 0xd2,
+ 0xfa, 0xa4, 0x57, 0x00, 0xfd, 0x8c, 0x84, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x84, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x7d, 0xe8,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x02, 0x11, 0xb5, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xfb, 0xa0, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x85, 0x88, 0xfc, 0x8c, 0x80, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x11, 0x5d, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x80, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x7d, 0xf8, 0xff, 0x8e, 0x7d, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x11, 0x28, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x80, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x80, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x02, 0x11, 0xad,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x10, 0xd0, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x02, 0x11, 0xa4,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x11, 0xd2, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x81, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x81, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x80, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x10, 0x80, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x8a, 0x10, 0x44,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x12, 0x28, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7e, 0x68, 0xfe, 0x8c, 0x7e, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08,
+ 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7e, 0x68, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x02, 0x14, 0x80, 0xff, 0x0e, 0x7e, 0x40, 0xfe, 0x8c, 0x7e, 0x64, 0x0f, 0x01, 0x80, 0x01,
+ 0x0f, 0x78, 0x36, 0x8a, 0xfa, 0xa4, 0x57, 0x00, 0xfd, 0x8c, 0x84, 0xf8, 0x0f, 0x81, 0x20, 0x00,
+ 0xfb, 0x8c, 0x84, 0xe8, 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00,
+ 0xf9, 0x8c, 0x7e, 0x68, 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x02, 0x14, 0x19,
+ 0x5b, 0x6d, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xfb, 0xa0,
+ 0xff, 0x0e, 0x80, 0xa2, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x85, 0x88, 0xfc, 0x8c, 0x80, 0x88,
+ 0x4e, 0xf5, 0xdf, 0xff, 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00,
+ 0x4f, 0xe4, 0x00, 0x09, 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x13, 0xc1, 0xcd, 0x68, 0xf8, 0x00,
+ 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x80, 0xb4, 0xff, 0xfb, 0x28, 0x00,
+ 0xfc, 0xdf, 0x28, 0x0c, 0xff, 0x0c, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01,
+ 0xff, 0x0d, 0x4b, 0xf8, 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10,
+ 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xdf, 0x28, 0x10, 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x7e, 0x78, 0xff, 0x8e, 0x7e, 0x40,
+ 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00,
+ 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x13, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0xfa, 0x0e, 0x80, 0xba, 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e,
+ 0x6e, 0xf4, 0xff, 0xff, 0xff, 0x0e, 0x80, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00,
+ 0xfc, 0xdf, 0x28, 0x0c, 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00,
+ 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff,
+ 0xe6, 0x02, 0x14, 0x11, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x13, 0x34, 0xfe, 0x53, 0x28, 0x00,
+ 0xe0, 0x02, 0x14, 0x08, 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x36, 0x8a,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00,
+ 0xff, 0x0e, 0x81, 0x00, 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x81, 0x02, 0x9f, 0x02, 0xfe, 0x68,
+ 0xff, 0x0e, 0x80, 0xa2, 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00,
+ 0xcf, 0x78, 0xfa, 0x00, 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x12, 0xe4, 0xcb, 0x58, 0xe8, 0x00,
+ 0xff, 0x8a, 0x12, 0xa8, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x14, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x7e, 0xe8,
+ 0xfe, 0x8c, 0x7e, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x7e, 0xe8,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x16, 0xe4, 0xff, 0x0e, 0x7e, 0xc0, 0xfe, 0x8c, 0x7e, 0xe4,
+ 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x5b, 0x42, 0xfa, 0xa4, 0x57, 0x00, 0xfd, 0x8c, 0x84, 0xf8,
+ 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x84, 0xe8, 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff,
+ 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x7e, 0xe8, 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b,
+ 0xe2, 0x02, 0x16, 0x7d, 0x5b, 0x6d, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30,
+ 0xfd, 0x08, 0xfb, 0xa0, 0xff, 0x0e, 0x80, 0xa2, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x85, 0x88,
+ 0xfc, 0x8c, 0x80, 0x88, 0x4e, 0xf5, 0xdf, 0xff, 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00,
+ 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09, 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x16, 0x25,
+ 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x80, 0xb4,
+ 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c, 0xff, 0x0c, 0x4b, 0xf8, 0x55, 0x28, 0x01, 0x00,
+ 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x4b, 0xf8, 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00,
+ 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00,
+ 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10, 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x7e, 0xf8,
+ 0xff, 0x8e, 0x7e, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x15, 0xf0,
+ 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x80, 0xba, 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff, 0xff, 0x0e, 0x80, 0xb2, 0xff, 0xfb, 0x28, 0x00,
+ 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c, 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10,
+ 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00,
+ 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x02, 0x16, 0x75, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x15, 0x98,
+ 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x02, 0x16, 0x6c, 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01,
+ 0x0f, 0xfc, 0x5b, 0x42, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68,
+ 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x81, 0x00, 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68,
+ 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x81, 0x02,
+ 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x80, 0xa2, 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00,
+ 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01,
+ 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00, 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x15, 0x48,
+ 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x8a, 0x15, 0x0c, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x16, 0xf0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x44, 0x4d, 0x41, 0x2d, 0x54, 0x45, 0x53,
+ 0x54, 0x3f, 0x3f, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x1c, 0xff, 0x8c, 0x85, 0x80, 0x20, 0x7e, 0x00, 0x04, 0xe6, 0x02, 0x1e, 0x89,
+ 0xce, 0x18, 0x00, 0x00, 0x8d, 0x72, 0x00, 0x00, 0x8f, 0xf2, 0x00, 0x10, 0x8a, 0x72, 0x00, 0x04,
+ 0x89, 0xf2, 0x00, 0x08, 0x8d, 0xf2, 0x00, 0x0c, 0x20, 0x6a, 0x00, 0x31, 0xff, 0x89, 0xc0, 0xb0,
+ 0x8e, 0xf2, 0x00, 0x14, 0xff, 0x8e, 0x4b, 0xb0, 0xfe, 0x89, 0xf8, 0xf0, 0xff, 0x89, 0xf9, 0x28,
+ 0xf0, 0x09, 0xe1, 0xc8, 0x8e, 0xf2, 0x00, 0x10, 0xfe, 0x89, 0xe0, 0xe8, 0x8f, 0xf2, 0x00, 0x14,
+ 0x0f, 0xfc, 0x00, 0x04, 0xff, 0x89, 0xfb, 0x90, 0xe2, 0x02, 0x1c, 0xcc, 0xf0, 0x09, 0xe2, 0xb8,
+ 0x7f, 0xe9, 0x00, 0x02, 0xff, 0x0a, 0x17, 0xc4, 0xae, 0xfe, 0xf0, 0x02, 0xc1, 0x74, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x18, 0xa0, 0x00, 0x02, 0x18, 0x8c, 0x00, 0x02, 0x19, 0x10,
+ 0x00, 0x02, 0x19, 0x20, 0x00, 0x02, 0x19, 0x2c, 0x00, 0x02, 0x19, 0x54, 0x00, 0x02, 0x19, 0x5c,
+ 0x00, 0x02, 0x19, 0x70, 0x00, 0x02, 0x19, 0x7c, 0x00, 0x02, 0x19, 0x88, 0x00, 0x02, 0x19, 0x90,
+ 0x00, 0x02, 0x19, 0x98, 0x00, 0x02, 0x19, 0xa0, 0x00, 0x02, 0x19, 0xa8, 0x00, 0x02, 0x19, 0xb0,
+ 0x00, 0x02, 0x19, 0xd0, 0x00, 0x02, 0x19, 0xe0, 0x00, 0x02, 0x19, 0xf8, 0x00, 0x02, 0x18, 0xa0,
+ 0x00, 0x02, 0x1a, 0x04, 0x00, 0x02, 0x1a, 0x30, 0x00, 0x02, 0x1a, 0x68, 0x00, 0x02, 0x1a, 0x80,
+ 0x00, 0x02, 0x1b, 0x20, 0x00, 0x02, 0x1b, 0x40, 0x00, 0x02, 0x1b, 0xd8, 0x00, 0x02, 0x1b, 0x58,
+ 0x00, 0x02, 0x1b, 0x74, 0x00, 0x02, 0x1b, 0x7c, 0x00, 0x02, 0x1b, 0xa0, 0x00, 0x02, 0x1b, 0xc4,
+ 0x00, 0x02, 0x1a, 0x08, 0x00, 0x02, 0x1b, 0xd8, 0x00, 0x02, 0x1c, 0x80, 0x00, 0x02, 0x1c, 0xac,
+ 0x00, 0x02, 0x1c, 0xcc, 0x00, 0x02, 0x1c, 0xcc, 0x00, 0x02, 0x1c, 0xcc, 0x00, 0x02, 0x1c, 0xcc,
+ 0x00, 0x02, 0x1c, 0xcc, 0x00, 0x02, 0x1c, 0xcc, 0x00, 0x02, 0x1c, 0xcc, 0x00, 0x02, 0x1c, 0xcc,
+ 0x00, 0x02, 0x1c, 0xcc, 0x00, 0x02, 0x1c, 0xe4, 0x00, 0x02, 0x1c, 0xec, 0x00, 0x02, 0x1d, 0x10,
+ 0x00, 0x02, 0x1d, 0x60, 0x00, 0x02, 0x1d, 0xb8, 0x00, 0x02, 0x1e, 0x24, 0x0f, 0x81, 0x1f, 0xe0,
+ 0xc0, 0x2a, 0xfc, 0x00, 0xe6, 0x02, 0x18, 0xfd, 0xff, 0x82, 0x00, 0x03, 0xff, 0x89, 0xe2, 0xb8,
+ 0x70, 0x2a, 0x00, 0x01, 0xea, 0x02, 0x18, 0xc9, 0xcf, 0x84, 0x00, 0x00, 0xff, 0x08, 0xf8, 0xf0,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x02, 0x18, 0xc9, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x8a, 0x18, 0xc8,
+ 0xe0, 0x00, 0x7c, 0xf0, 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x18, 0xc8, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x8a, 0x19, 0x08,
+ 0xe0, 0x01, 0x18, 0x10, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x18, 0xa0, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x0d, 0x4b, 0xb0, 0xfe, 0x82, 0x00, 0x04, 0xe0, 0x02, 0x18, 0xa0, 0xfe, 0x89, 0xe1, 0xc8,
+ 0xfa, 0x0d, 0x84, 0xa0, 0xe0, 0x02, 0x18, 0xa0, 0xf9, 0x9d, 0x46, 0x60, 0xff, 0x8c, 0x84, 0xc8,
+ 0x0f, 0xfc, 0x00, 0x02, 0xc0, 0x7e, 0xa2, 0x00, 0xe2, 0x02, 0x18, 0xa1, 0xfa, 0x0d, 0x85, 0xf0,
+ 0x20, 0x52, 0x0f, 0xff, 0xe2, 0x02, 0x18, 0xa0, 0xff, 0x82, 0x00, 0x02, 0xe0, 0x02, 0x18, 0x9c,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x18, 0xa0, 0xfa, 0x0d, 0x4b, 0xb8, 0xfe, 0x98, 0x86, 0x20,
+ 0xff, 0x82, 0x00, 0x04, 0xfe, 0x8d, 0x4b, 0xb0, 0xe0, 0x02, 0x18, 0xa0, 0xff, 0x89, 0xe1, 0xc8,
+ 0xfe, 0x8c, 0x80, 0x78, 0xe0, 0x02, 0x19, 0x64, 0xff, 0x82, 0x00, 0x04, 0xfe, 0x9c, 0x46, 0x78,
+ 0xe0, 0x02, 0x19, 0x64, 0xff, 0x82, 0x00, 0x04, 0xe0, 0x02, 0x19, 0x60, 0xfe, 0x8e, 0x85, 0x08,
+ 0xe0, 0x02, 0x19, 0x60, 0x0e, 0x81, 0x00, 0xf4, 0xe0, 0x02, 0x19, 0x60, 0xfe, 0x82, 0x40, 0x00,
+ 0xe0, 0x02, 0x19, 0x60, 0xfe, 0x82, 0x10, 0x00, 0xe0, 0x02, 0x18, 0xa0, 0xfa, 0x19, 0x86, 0x18,
+ 0xf7, 0x8a, 0x19, 0xbc, 0xe0, 0x01, 0x15, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x02, 0x18, 0xa1, 0xfe, 0x82, 0x00, 0x02, 0xe0, 0x02, 0x18, 0xa0, 0xfe, 0x89, 0xe2, 0xb8,
+ 0xff, 0x82, 0x00, 0x02, 0xff, 0x8d, 0x85, 0x80, 0xe0, 0x02, 0x18, 0xa0, 0x55, 0x29, 0x00, 0x10,
+ 0x0f, 0xd0, 0x00, 0x02, 0x20, 0x7e, 0x24, 0xb8, 0xe2, 0x02, 0x18, 0xa1, 0xfa, 0x0d, 0x84, 0xc8,
+ 0xe0, 0x02, 0x19, 0xc8, 0xfe, 0x82, 0x00, 0x02, 0xff, 0x8e, 0x7f, 0xe0, 0xe0, 0x02, 0x19, 0x14,
+ 0xff, 0x8d, 0x4b, 0xb0, 0xfd, 0x82, 0x00, 0x28, 0x20, 0x6e, 0x00, 0x40, 0xe2, 0x02, 0x1a, 0x29,
+ 0xfd, 0x89, 0xb9, 0x3c, 0xff, 0x82, 0x00, 0x40, 0xff, 0x89, 0xb9, 0x40, 0xfa, 0x0d, 0x84, 0xd8,
+ 0xe0, 0x02, 0x18, 0xa0, 0xf9, 0x8d, 0x80, 0x68, 0xe0, 0x02, 0x1a, 0x1c, 0xfd, 0x89, 0xb9, 0x40,
+ 0xff, 0x88, 0xb9, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x18, 0xa0, 0xff, 0x82, 0x00, 0x01,
+ 0xff, 0x89, 0xb9, 0x50, 0xf7, 0x8a, 0x1a, 0x50, 0xe0, 0x01, 0x2c, 0xf4, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x8a, 0x1a, 0x60, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x02, 0x18, 0xa0, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb9, 0x50, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x18, 0xa1, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x1a, 0x44, 0xf0, 0x09, 0xb9, 0x50,
+ 0xfb, 0x76, 0xff, 0xd0, 0x8f, 0xda, 0x00, 0x00, 0xfd, 0x82, 0x00, 0xff, 0xfa, 0xf6, 0xff, 0xcc,
+ 0x7c, 0x50, 0xff, 0xf8, 0x8e, 0x56, 0x00, 0x00, 0xcc, 0x60, 0xdc, 0x00, 0x7f, 0x61, 0x00, 0x1c,
+ 0x0b, 0x81, 0xff, 0xf0, 0x4f, 0xfd, 0x00, 0x0f, 0x0b, 0xdc, 0x0f, 0xff, 0xcd, 0x50, 0xdc, 0x00,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x7c, 0xd0, 0xff, 0xe8, 0xce, 0x70, 0xbc, 0x00, 0x7c, 0xe5, 0x00, 0x0c,
+ 0x7d, 0x69, 0x00, 0x14, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xcc, 0xff, 0xf8, 0xcf, 0x78, 0xdc, 0x00,
+ 0xce, 0xf4, 0xdc, 0x00, 0xce, 0x70, 0xcd, 0x00, 0xcf, 0xfc, 0xd5, 0x00, 0xcf, 0xfc, 0xbc, 0x00,
+ 0x7f, 0x79, 0x00, 0x04, 0x4e, 0x70, 0xf0, 0x00, 0x7e, 0xf5, 0x00, 0x0c, 0xce, 0x70, 0xf5, 0x00,
+ 0xcf, 0xfc, 0xed, 0x00, 0x7c, 0x60, 0xff, 0xfc, 0xcd, 0xcc, 0xdc, 0x00, 0xce, 0x70, 0xc5, 0x00,
+ 0x4f, 0xfc, 0xf0, 0x0f, 0x7d, 0xed, 0x00, 0x04, 0x9e, 0x56, 0x00, 0x00, 0xcf, 0xfc, 0xdd, 0x00,
+ 0x9f, 0xda, 0x00, 0x00, 0xfa, 0x0d, 0x85, 0xe8, 0xe0, 0x02, 0x1a, 0x50, 0xf9, 0xa5, 0x57, 0x70,
+ 0xff, 0x76, 0xff, 0xd0, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0x82, 0x00, 0x01, 0xf3, 0x76, 0xff, 0xfc,
+ 0xfe, 0x8d, 0x80, 0x58, 0x5f, 0xfc, 0x00, 0x08, 0xe0, 0x02, 0x1a, 0x54, 0x9f, 0xfa, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0xd0, 0x8f, 0xfa, 0x00, 0x00, 0xf3, 0x76, 0xff, 0xfc, 0xf0, 0x0d, 0x80, 0x58,
+ 0xe0, 0x02, 0x1b, 0x38, 0x4f, 0xfc, 0xff, 0xf7, 0xfe, 0x82, 0x00, 0x01, 0xfe, 0x89, 0xb9, 0x4c,
+ 0xf7, 0x8a, 0x1b, 0x6c, 0xe0, 0x01, 0x2c, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x18, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x1b, 0x60, 0xf0, 0x09, 0xb9, 0x4c, 0x03, 0x70, 0x00, 0x04,
+ 0xf7, 0x8a, 0x1b, 0x8c, 0xe0, 0x01, 0x2f, 0xd0, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x02, 0x18, 0x9c, 0xff, 0x82, 0x00, 0x06, 0xe0, 0x02, 0x18, 0xa0, 0x00, 0x00, 0x00, 0x01,
+ 0x03, 0x70, 0x00, 0x04, 0xf7, 0x8a, 0x1b, 0xb0, 0xe0, 0x01, 0x2e, 0x18, 0x97, 0x93, 0xff, 0xfc,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x19, 0xc8, 0xfe, 0x82, 0x00, 0x06, 0xe0, 0x02, 0x18, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x8a, 0x1b, 0xd0, 0xe0, 0x01, 0x2f, 0x20, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x02, 0x1b, 0x90, 0x20, 0x22, 0x00, 0x00, 0xff, 0x8c, 0x85, 0x80, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x19, 0xc8, 0xfe, 0x82, 0x00, 0x03, 0xff, 0x88, 0xb3, 0x30, 0xfd, 0x0d, 0x84, 0xd0,
+ 0xff, 0x02, 0xff, 0xf8, 0xff, 0x8d, 0x4b, 0xd0, 0xff, 0xf3, 0x18, 0x0c, 0x4e, 0xfc, 0xff, 0xf8,
+ 0xfe, 0x8d, 0x7f, 0xc0, 0x8f, 0xf2, 0x00, 0x0c, 0xcf, 0xfc, 0xf4, 0x00, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x1c, 0x69, 0xff, 0x8d, 0x4b, 0xd8, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x1c, 0x51,
+ 0xfe, 0x82, 0x00, 0x06, 0xfe, 0x9d, 0x46, 0x50, 0x8e, 0xf2, 0x00, 0x10, 0x4f, 0xd0, 0xff, 0xf8,
+ 0xfe, 0x8d, 0x4c, 0x20, 0x8e, 0x72, 0x00, 0x14, 0xff, 0x8d, 0x84, 0xc0, 0xff, 0x82, 0x00, 0x04,
+ 0xfe, 0x0d, 0x80, 0x80, 0xf9, 0x99, 0x86, 0x00, 0xe0, 0x02, 0x18, 0xc8, 0xff, 0x8d, 0x85, 0x80,
+ 0xff, 0x8c, 0x4b, 0xd8, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x1c, 0x69, 0xff, 0x82, 0x00, 0x05,
+ 0xe0, 0x02, 0x1c, 0x28, 0xff, 0x9d, 0x46, 0x50, 0xff, 0x8c, 0x7f, 0xc0, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x18, 0x9d, 0xff, 0x82, 0x00, 0x02, 0xe0, 0x02, 0x1c, 0x24, 0xfe, 0x82, 0x00, 0x04,
+ 0xff, 0x88, 0xb3, 0x34, 0x20, 0x7e, 0x00, 0x05, 0xe2, 0x02, 0x1c, 0xa0, 0xff, 0x02, 0x00, 0x00,
+ 0xff, 0x88, 0xb3, 0x30, 0x20, 0x7e, 0x01, 0x2c, 0xe2, 0x02, 0x1c, 0xa5, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x02, 0x00, 0x01, 0xe0, 0x02, 0x19, 0x14, 0xff, 0x0d, 0x4b, 0xb0, 0x20, 0x52, 0x00, 0x00,
+ 0xe6, 0x02, 0x1c, 0xc5, 0x2f, 0xd0, 0x00, 0x01, 0xc0, 0x52, 0xfc, 0x00, 0xe6, 0x02, 0x18, 0x9c,
+ 0xff, 0x82, 0x00, 0x02, 0xe0, 0x02, 0x18, 0xa0, 0xfa, 0x0d, 0x7f, 0xd0, 0xff, 0x82, 0x00, 0x01,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x18, 0xc9, 0xff, 0x89, 0xe2, 0xb8, 0xe0, 0x02, 0x18, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x19, 0x60, 0xfe, 0x82, 0x03, 0xfe, 0x20, 0x52, 0x00, 0x01,
+ 0xe2, 0x02, 0x19, 0xc8, 0xfe, 0x82, 0x00, 0x02, 0xfa, 0x09, 0xb9, 0x44, 0xf7, 0x8a, 0x1d, 0x08,
+ 0xe0, 0x01, 0x10, 0xd8, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x18, 0xa0, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xb2, 0xb8, 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x02, 0x1d, 0x29, 0xc3, 0xd0, 0x00, 0x00,
+ 0xe0, 0x02, 0x18, 0x9c, 0xff, 0x82, 0x00, 0x0b, 0x9a, 0x16, 0xff, 0xe8, 0x44, 0x4d, 0x00, 0x00,
+ 0xf3, 0x02, 0x00, 0x00, 0xf7, 0x8a, 0x1d, 0x40, 0xe0, 0x00, 0x76, 0x8c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8a, 0x16, 0xff, 0xe8, 0xf3, 0x02, 0x00, 0x00, 0xc3, 0xd0, 0x00, 0x00, 0xf7, 0x8a, 0x1d, 0x58,
+ 0xe0, 0x00, 0x77, 0x7c, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x19, 0x14, 0xf4, 0x0d, 0x4b, 0xb0,
+ 0xff, 0x88, 0xb2, 0xb8, 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x02, 0x18, 0x9c, 0xff, 0x82, 0x00, 0x0b,
+ 0x44, 0x4d, 0x00, 0x00, 0xc3, 0xd0, 0x00, 0x00, 0x9a, 0x16, 0xff, 0xe8, 0x9d, 0x96, 0xff, 0xe4,
+ 0xf3, 0x02, 0x00, 0x00, 0xf7, 0x8a, 0x1d, 0x90, 0xe0, 0x00, 0x76, 0x8c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x96, 0xff, 0xe4, 0x8a, 0x16, 0xff, 0xe8, 0xf3, 0x02, 0x00, 0x00, 0x44, 0x6d, 0x00, 0x00,
+ 0xc3, 0xd0, 0x00, 0x00, 0xf7, 0x8a, 0x1d, 0xb0, 0xe0, 0x00, 0x77, 0x04, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x02, 0x18, 0xa0, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xb2, 0xb8, 0xfe, 0x82, 0x00, 0x0b,
+ 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x02, 0x19, 0xc8, 0x9f, 0x96, 0xff, 0xf0, 0x99, 0x96, 0xff, 0xec,
+ 0x9a, 0x16, 0xff, 0xe8, 0xf7, 0x8a, 0x1d, 0xe0, 0xe0, 0x00, 0x79, 0x24, 0x97, 0x93, 0xff, 0xfc,
+ 0x89, 0x96, 0xff, 0xec, 0x8a, 0x16, 0xff, 0xe8, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x1e, 0x01,
+ 0xc3, 0x50, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xf0, 0xe0, 0x02, 0x18, 0xa0, 0xff, 0x89, 0xe2, 0xb8,
+ 0xc3, 0xcc, 0x00, 0x00, 0xf7, 0x8a, 0x1e, 0x10, 0xe0, 0x00, 0x79, 0xa4, 0x97, 0x93, 0xff, 0xfc,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x18, 0xa1, 0xfe, 0x82, 0x00, 0x0d, 0xe0, 0x02, 0x18, 0xa0,
+ 0xfe, 0x89, 0xe2, 0xb8, 0xfe, 0x88, 0xb2, 0xb8, 0x20, 0x76, 0x00, 0x03, 0xe6, 0x02, 0x1d, 0x20,
+ 0x9e, 0x96, 0xff, 0xf4, 0x9a, 0x16, 0xff, 0xe8, 0xf7, 0x8a, 0x1e, 0x44, 0xe0, 0x00, 0x79, 0x24,
+ 0x97, 0x93, 0xff, 0xfc, 0x8a, 0x16, 0xff, 0xe8, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x1e, 0x61,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xf4, 0xe0, 0x02, 0x18, 0xa0, 0xfe, 0x89, 0xe2, 0xb8,
+ 0xff, 0x88, 0xbc, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x18, 0x9c, 0xff, 0x82, 0x00, 0x0c,
+ 0xc3, 0x50, 0x00, 0x00, 0xf7, 0x8a, 0x1e, 0x80, 0xe0, 0x00, 0x78, 0xe0, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x02, 0x19, 0x14, 0xf4, 0x0d, 0x4b, 0xb0, 0x22, 0x10, 0x00, 0x04, 0xfe, 0x8a, 0x17, 0x30,
+ 0x9e, 0x92, 0x00, 0x00, 0x93, 0x16, 0xff, 0xe0, 0xf7, 0x8a, 0x1e, 0xa4, 0xe0, 0x02, 0x99, 0xf4,
+ 0x97, 0x93, 0xff, 0xfc, 0x02, 0x10, 0x00, 0x04, 0xf3, 0x02, 0x00, 0x3e, 0xf7, 0x8a, 0x1e, 0xb8,
+ 0xe0, 0x00, 0x7b, 0x5c, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x16, 0xff, 0xe0, 0xe0, 0x02, 0x17, 0x64,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x7e, 0x21, 0x00, 0x02, 0xcf, 0x9c, 0xe0, 0x00,
+ 0x2f, 0xfc, 0x00, 0x01, 0xff, 0x02, 0x00, 0x3c, 0xcf, 0x1c, 0xf4, 0x00, 0xcf, 0x9c, 0xfe, 0x00,
+ 0xfe, 0x9e, 0x46, 0x80, 0x40, 0x7e, 0xff, 0xc0, 0xe6, 0x02, 0x1f, 0x35, 0xce, 0xf8, 0xe8, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x1f, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0xfa, 0x80, 0x00, 0xcf, 0x7c, 0x32, 0x00, 0x20, 0x7a, 0x00, 0x00,
+ 0xee, 0x02, 0x20, 0x65, 0xcf, 0xf0, 0xf2, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xee, 0x02, 0x20, 0x51,
+ 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68, 0x9f, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x7a, 0x00, 0x00, 0x9e, 0x02, 0xfe, 0x68,
+ 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xf4, 0xf0, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x9e, 0x46, 0x38, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x20, 0x1d,
+ 0xff, 0x82, 0x00, 0x01, 0xff, 0x02, 0x00, 0x3c, 0xcf, 0xfc, 0x47, 0xc0, 0xcf, 0x1c, 0xf4, 0x00,
+ 0xfe, 0x9c, 0x46, 0x38, 0x2f, 0xfc, 0x00, 0x01, 0x7f, 0x78, 0xff, 0xfe, 0xcf, 0xfc, 0xf7, 0xc0,
+ 0xce, 0xf4, 0xfd, 0x00, 0x20, 0x76, 0xff, 0xff, 0xe6, 0x02, 0x1f, 0xf9, 0x4f, 0x9d, 0x00, 0xff,
+ 0xfe, 0x9d, 0x46, 0x38, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x1f, 0xc4, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xfc, 0xff, 0xee, 0xf0, 0x1d, 0x46, 0x38,
+ 0x7f, 0xfd, 0x00, 0x02, 0x8f, 0x7e, 0x05, 0x08, 0x43, 0x9c, 0xff, 0xc0, 0xf3, 0x1e, 0x46, 0x80,
+ 0xf7, 0x8a, 0x20, 0x1c, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x01,
+ 0x93, 0x02, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0xe0, 0x02, 0x1f, 0x7c,
+ 0x00, 0x00, 0x00, 0x01, 0x2f, 0x98, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0xe0, 0x02, 0x20, 0x54,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x7f, 0xf0, 0x93, 0x02, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x40, 0x9f, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xfc, 0xf0, 0x00,
+ 0x70, 0x7e, 0x00, 0x11, 0xea, 0x02, 0x20, 0xe9, 0x4f, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80,
+ 0xff, 0x8d, 0x7f, 0xf0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x20, 0xb4, 0x00, 0x00, 0x00, 0x01, 0xce, 0xfc, 0xf2, 0x00, 0x4f, 0xfc, 0xbf, 0xff,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x21, 0x11, 0x4e, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x9f, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68,
+ 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x7f, 0xf0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x21, 0x18, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8c, 0x7f, 0xf0, 0x93, 0x02, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x10, 0x9f, 0x02, 0xfe, 0x68,
+ 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xfc, 0xf0, 0x00, 0x70, 0x7e, 0x00, 0x11, 0xea, 0x02, 0x21, 0xc1,
+ 0x4f, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x7f, 0xf0, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x21, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0xce, 0xfc, 0xf2, 0x00, 0x4f, 0xfc, 0xbf, 0xff, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x21, 0xe9,
+ 0x4e, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x9f, 0x02, 0xfe, 0x68,
+ 0x9e, 0x82, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x7f, 0xf0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x21, 0xf0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x7f, 0xf0, 0x93, 0x02, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x20, 0x9f, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xfc, 0xf0, 0x00,
+ 0x70, 0x7e, 0x00, 0x11, 0xea, 0x02, 0x22, 0x99, 0x4f, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80,
+ 0xff, 0x8d, 0x7f, 0xf0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x22, 0x64, 0x00, 0x00, 0x00, 0x01, 0xce, 0xfc, 0xf2, 0x00, 0x4f, 0xfc, 0xbf, 0xff,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x22, 0xc1, 0x4e, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x9f, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68,
+ 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x7f, 0xf0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x22, 0xc8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8c, 0x7f, 0xf0, 0x93, 0x02, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x30, 0x9f, 0x02, 0xfe, 0x68,
+ 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xfc, 0xf0, 0x00, 0x70, 0x7e, 0x00, 0x11, 0xea, 0x02, 0x23, 0x71,
+ 0x4f, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x7f, 0xf0, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x23, 0x3c, 0x00, 0x00, 0x00, 0x01,
+ 0xce, 0xfc, 0xf2, 0x00, 0x4f, 0xfc, 0xbf, 0xff, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x23, 0x99,
+ 0x4e, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x9f, 0x02, 0xfe, 0x68,
+ 0x9e, 0x82, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x7f, 0xf0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x23, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x7e, 0x21, 0x00, 0x02, 0xcf, 0x9c, 0xe0, 0x00,
+ 0x2f, 0xfc, 0x00, 0x01, 0xff, 0x02, 0x00, 0x3c, 0xcf, 0x1c, 0xf4, 0x00, 0xcf, 0x9c, 0xfe, 0x00,
+ 0xfe, 0x8e, 0x85, 0x20, 0x40, 0x7e, 0xff, 0xc0, 0xe6, 0x02, 0x24, 0x45, 0xce, 0xf8, 0xe8, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x24, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0xfa, 0x80, 0x00, 0xcf, 0x7c, 0x32, 0x00, 0x20, 0x7a, 0x00, 0x00,
+ 0xee, 0x02, 0x25, 0x75, 0xcf, 0xf0, 0xf2, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xee, 0x02, 0x25, 0x61,
+ 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68, 0x9f, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x7a, 0x00, 0x00, 0x9e, 0x02, 0xfe, 0x68,
+ 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xf4, 0xf0, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x4b, 0xc8, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x25, 0x2d,
+ 0xff, 0x82, 0x00, 0x01, 0xff, 0x02, 0x00, 0x3c, 0xcf, 0xfc, 0x47, 0xc0, 0xcf, 0x1c, 0xf4, 0x00,
+ 0xfe, 0x8c, 0x4b, 0xc8, 0x2f, 0xfc, 0x00, 0x01, 0x7f, 0x78, 0xff, 0xfe, 0xcf, 0xfc, 0xf7, 0xc0,
+ 0xce, 0xf4, 0xfd, 0x00, 0x20, 0x76, 0xff, 0xff, 0xe6, 0x02, 0x25, 0x09, 0x4f, 0x9d, 0x00, 0xff,
+ 0xfe, 0x8d, 0x4b, 0xc8, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x24, 0xd4, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xfc, 0xff, 0xee, 0xf0, 0x0d, 0x4b, 0xc8,
+ 0x7f, 0xfd, 0x00, 0x02, 0x8f, 0x7e, 0x05, 0x08, 0x43, 0x9c, 0xff, 0xc0, 0xf3, 0x0e, 0x85, 0x20,
+ 0xf7, 0x8a, 0x25, 0x2c, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x25, 0x2c, 0x00, 0x00, 0x00, 0x01,
+ 0x93, 0x02, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0xe0, 0x02, 0x24, 0x8c,
+ 0x00, 0x00, 0x00, 0x01, 0x2f, 0x98, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0xe0, 0x02, 0x25, 0x64,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x80, 0x60, 0x93, 0x02, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x40, 0x9f, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xfc, 0xf0, 0x00,
+ 0x4f, 0xfc, 0xef, 0xff, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x80, 0x60, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x25, 0xbc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x7f, 0xf8, 0x93, 0x02, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x40,
+ 0x9f, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xfc, 0xf0, 0x00, 0x4f, 0xfc, 0xef, 0xff,
+ 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x7f, 0xf8, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x26, 0x28, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x7e, 0x21, 0x00, 0x02, 0xcf, 0x9c, 0xe0, 0x00, 0x2f, 0xfc, 0x00, 0x01, 0xff, 0x02, 0x00, 0x3c,
+ 0xcf, 0x1c, 0xf4, 0x00, 0xcf, 0x9c, 0xfe, 0x00, 0xfe, 0xa6, 0x57, 0x10, 0x40, 0x7e, 0xff, 0xc0,
+ 0xe6, 0x02, 0x26, 0xcd, 0xce, 0xf8, 0xe8, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x26, 0x98, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfa, 0x80, 0x00,
+ 0xcf, 0x7c, 0x32, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xee, 0x02, 0x27, 0xfd, 0xcf, 0xf0, 0xf2, 0x00,
+ 0x20, 0x7e, 0x00, 0x00, 0xee, 0x02, 0x27, 0xe9, 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68,
+ 0x9f, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x7a, 0x00, 0x00, 0x9e, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xf4, 0xf0, 0x00,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x7f, 0xe8,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x27, 0xb5, 0xff, 0x82, 0x00, 0x01, 0xff, 0x02, 0x00, 0x3c,
+ 0xcf, 0xfc, 0x47, 0xc0, 0xcf, 0x1c, 0xf4, 0x00, 0xfe, 0x8c, 0x7f, 0xe8, 0x2f, 0xfc, 0x00, 0x01,
+ 0x7f, 0x78, 0xff, 0xfe, 0xcf, 0xfc, 0xf7, 0xc0, 0xce, 0xf4, 0xfd, 0x00, 0x20, 0x76, 0xff, 0xff,
+ 0xe6, 0x02, 0x27, 0x91, 0x4f, 0x9d, 0x00, 0xff, 0xfe, 0x8d, 0x7f, 0xe8, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x27, 0x5c, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0xfc, 0xff, 0xee, 0xf0, 0x0d, 0x7f, 0xe8, 0x7f, 0xfd, 0x00, 0x02, 0x8f, 0x7e, 0x05, 0x08,
+ 0x43, 0x9c, 0xff, 0xc0, 0xf3, 0x26, 0x57, 0x10, 0xf7, 0x8a, 0x27, 0xb4, 0xc1, 0x78, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x27, 0xb4, 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68,
+ 0x9e, 0x82, 0xfe, 0x68, 0xe0, 0x02, 0x27, 0x14, 0x00, 0x00, 0x00, 0x01, 0x2f, 0x98, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x68, 0xe0, 0x02, 0x27, 0xec, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0xa2, 0x80, 0x70, 0x7e, 0x00, 0x0c, 0xea, 0x02, 0x28, 0xbc, 0xfd, 0x02, 0x00, 0x00,
+ 0xfe, 0x88, 0xe6, 0xd8, 0x4f, 0xfd, 0xff, 0xf7, 0xff, 0x89, 0xa2, 0x80, 0xfd, 0x82, 0x34, 0x00,
+ 0xf7, 0x82, 0x00, 0x40, 0xf7, 0xf7, 0x68, 0x08, 0xfd, 0xf7, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6,
+ 0xff, 0xfb, 0x18, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0x24,
+ 0xff, 0xf7, 0x28, 0x12, 0x9d, 0x76, 0x00, 0x14, 0x9d, 0x76, 0x00, 0x18, 0x9d, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x9d, 0x76, 0x00, 0x30, 0xff, 0x77, 0x18, 0x0a, 0x8e, 0x76, 0x00, 0x2c,
+ 0x0d, 0x81, 0x10, 0x00, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x0d, 0xec, 0x00, 0x14,
+ 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0xec, 0x9f, 0xf6, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xfd, 0x82, 0x00, 0x28, 0x9d, 0x82, 0xff, 0xb0, 0xfd, 0x77, 0x28, 0x02, 0xff, 0x08, 0xe6, 0xd8,
+ 0xfe, 0xa4, 0x57, 0x50, 0xfd, 0x82, 0x00, 0x40, 0xfe, 0x26, 0x57, 0x54, 0x9d, 0xfa, 0x00, 0x30,
+ 0xff, 0xfb, 0x18, 0x0a, 0x8d, 0xfa, 0x00, 0x2c, 0x9e, 0x7a, 0x00, 0x24, 0x9e, 0xfa, 0x00, 0x28,
+ 0xff, 0xf3, 0x28, 0x02, 0x9e, 0x02, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xfe, 0x82, 0xa2, 0xec, 0x9e, 0xfa, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xfd, 0x89, 0xe6, 0xd8,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0xef, 0x28, 0x00, 0x9f, 0xee, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0xfd, 0x7b, 0x28, 0x02, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x29, 0x18, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0x4f, 0x7d, 0x1e, 0x00, 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0x78, 0x07, 0x48,
+ 0xc5, 0x7c, 0x00, 0x00, 0xf3, 0x7b, 0x68, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x29, 0x78, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8f, 0xae, 0x00, 0x1c, 0xff, 0x08, 0xe0, 0xd8, 0x4e, 0x85, 0xdf, 0xff, 0x4f, 0xfc, 0x00, 0x00,
+ 0x85, 0xae, 0x00, 0x2c, 0xcf, 0x78, 0xf8, 0x00, 0xce, 0xf8, 0xed, 0x00, 0xff, 0x09, 0xe0, 0xd8,
+ 0xc5, 0x28, 0xec, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x29, 0xe4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfb, 0x9c, 0x46, 0x50,
+ 0x8b, 0x02, 0xff, 0xd0, 0xff, 0x8c, 0x84, 0xe0, 0xfa, 0x9c, 0x46, 0x70, 0x20, 0x5e, 0x00, 0x08,
+ 0xe2, 0x02, 0x30, 0x84, 0xcb, 0x58, 0xfa, 0x00, 0x7f, 0xdd, 0x00, 0x02, 0xff, 0x0a, 0x2a, 0x5c,
+ 0xae, 0xfe, 0xf0, 0x02, 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x2a, 0x80,
+ 0x00, 0x02, 0x2c, 0x28, 0x00, 0x02, 0x2d, 0x50, 0x00, 0x02, 0x2e, 0xdc, 0x00, 0x02, 0x30, 0x84,
+ 0x00, 0x02, 0x30, 0x84, 0x00, 0x02, 0x30, 0x84, 0x00, 0x02, 0x30, 0x84, 0x00, 0x02, 0x30, 0x0c,
+ 0x4f, 0xa9, 0x1e, 0x00, 0x7e, 0xfc, 0xff, 0xe7, 0xff, 0x8c, 0x4c, 0x18, 0x8e, 0x02, 0xff, 0xf8,
+ 0x4f, 0x29, 0x01, 0xe0, 0xc0, 0x76, 0xfa, 0x00, 0xe6, 0x02, 0x2c, 0x21, 0x7f, 0x78, 0xff, 0xeb,
+ 0x20, 0x7a, 0x00, 0x0f, 0xe6, 0x02, 0x2c, 0x21, 0x00, 0x00, 0x00, 0x01, 0x70, 0x72, 0x00, 0x13,
+ 0xea, 0x02, 0x2c, 0x20, 0x0f, 0xf4, 0x07, 0x48, 0xfc, 0x0c, 0x85, 0x00, 0xfc, 0xff, 0x58, 0x00,
+ 0xfa, 0x18, 0x86, 0x00, 0xf9, 0x8c, 0x84, 0xc0, 0xfb, 0x8c, 0x7f, 0xc0, 0x20, 0x62, 0x00, 0x00,
+ 0xee, 0x02, 0x2b, 0x15, 0x0f, 0x01, 0x80, 0x00, 0xff, 0x88, 0xe6, 0xd8, 0xff, 0xff, 0x18, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x9c, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x03, 0x2a, 0x60, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x7f, 0xe5, 0x00, 0x1c,
+ 0xcf, 0xdc, 0xfd, 0x00, 0x0f, 0x01, 0x80, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x52, 0xd2, 0x00, 0xe6, 0x70, 0x00, 0x02, 0x7f, 0xf1, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xfe, 0xfb, 0x18, 0x00, 0x4f, 0xdc, 0x0f, 0xf8,
+ 0x7f, 0xfc, 0xff, 0xfe, 0x7e, 0xf5, 0x00, 0x0f, 0xce, 0xf4, 0xfd, 0x00, 0x7e, 0x71, 0x00, 0x02,
+ 0xcf, 0xec, 0xe0, 0x00, 0xfe, 0xef, 0x28, 0x0e, 0x9a, 0x6e, 0x00, 0x14, 0xfc, 0xef, 0x68, 0x12,
+ 0xf0, 0xef, 0x68, 0x13, 0x99, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0xee, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x77, 0x28, 0x00,
+ 0x9f, 0x76, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfc, 0x6f, 0x28, 0x02,
+ 0x9d, 0x02, 0xff, 0x00, 0x7f, 0xe5, 0x00, 0x02, 0xff, 0x0a, 0x29, 0x58, 0x9f, 0x7e, 0x07, 0x08,
+ 0xff, 0x8c, 0x7f, 0xc0, 0xff, 0x1e, 0x46, 0xe0, 0xfe, 0x82, 0x00, 0x01, 0x4f, 0xfc, 0xff, 0xfc,
+ 0xaf, 0xfe, 0xf0, 0x02, 0x05, 0x29, 0x02, 0x20, 0xff, 0x8d, 0x85, 0x00, 0xca, 0xd4, 0xe8, 0x00,
+ 0xff, 0x82, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x30, 0x85, 0xfa, 0x9d, 0x46, 0x70,
+ 0x20, 0x56, 0xff, 0xef, 0xe2, 0x02, 0x2c, 0x18, 0xff, 0x02, 0x00, 0x08, 0x20, 0x5a, 0x27, 0x10,
+ 0xe2, 0x02, 0x30, 0x85, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x30, 0x84, 0xff, 0x1d, 0x46, 0x50,
+ 0xe0, 0x02, 0x2b, 0xec, 0xfe, 0x82, 0x00, 0x00, 0x0f, 0x81, 0x20, 0x00, 0xcb, 0xaa, 0xfc, 0x00,
+ 0xe6, 0x02, 0x2d, 0x48, 0xff, 0x82, 0x00, 0x00, 0xfd, 0x98, 0x86, 0x00, 0xfc, 0x0c, 0x4b, 0xd8,
+ 0xff, 0x08, 0xe6, 0xd8, 0xc0, 0x6e, 0xfa, 0x00, 0xfd, 0x0c, 0x84, 0xc0, 0xe6, 0x70, 0x00, 0x02,
+ 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7c, 0xe0, 0xff, 0xfe, 0x4e, 0xe4, 0x03, 0xff,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xfb, 0x28, 0x12, 0x7e, 0x71, 0x00, 0x02, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14,
+ 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xff, 0x8a, 0xe2, 0xd0, 0xad, 0xfe, 0xc8, 0x05,
+ 0xfd, 0x08, 0xe0, 0xd8, 0xfe, 0xfb, 0x18, 0x0a, 0xff, 0xa6, 0x00, 0x0e, 0x8c, 0xfa, 0x00, 0x2c,
+ 0x9f, 0xfa, 0x00, 0x30, 0x0f, 0x81, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9c, 0x02, 0xfe, 0x58,
+ 0xfc, 0x7b, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x20, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x8a, 0x29, 0xc0,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8, 0x4e, 0xf4, 0x0f, 0xff,
+ 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xfb, 0xfb, 0x28, 0x02,
+ 0xff, 0x0c, 0x85, 0x00, 0xfe, 0x8c, 0x4b, 0xd8, 0x4d, 0x69, 0x20, 0x00, 0xc5, 0x28, 0xd5, 0x00,
+ 0xcf, 0x78, 0xea, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x0d, 0x85, 0x00, 0xff, 0x82, 0x00, 0x01, 0xe0, 0x02, 0x2b, 0xf0, 0xca, 0xd4, 0xf8, 0x00,
+ 0x4f, 0xa9, 0x1e, 0x00, 0x7e, 0xfc, 0xff, 0xe7, 0xff, 0x8c, 0x4c, 0x18, 0x8e, 0x02, 0xff, 0xf8,
+ 0x4f, 0x29, 0x01, 0xe0, 0xc0, 0x76, 0xfa, 0x00, 0xe6, 0x02, 0x2e, 0xd5, 0x7f, 0x78, 0xff, 0xeb,
+ 0x20, 0x7a, 0x00, 0x0f, 0xe6, 0x02, 0x2e, 0xd5, 0x00, 0x00, 0x00, 0x01, 0x70, 0x72, 0x00, 0x13,
+ 0xea, 0x02, 0x2e, 0xd4, 0x00, 0x00, 0x00, 0x01, 0x0f, 0xf4, 0x07, 0x48, 0xfc, 0x0c, 0x85, 0x00,
+ 0xfc, 0xff, 0x58, 0x00, 0xf9, 0x98, 0x86, 0x00, 0xf9, 0x0c, 0x84, 0xc0, 0xfa, 0x0c, 0x7f, 0xc0,
+ 0x20, 0x62, 0x00, 0x00, 0xee, 0x02, 0x2d, 0xe9, 0x0f, 0x01, 0x80, 0x00, 0xff, 0x88, 0xe6, 0xd8,
+ 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9c, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8,
+ 0x7f, 0xe5, 0x00, 0x1c, 0xcf, 0xd0, 0xfd, 0x00, 0x0f, 0x01, 0x80, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x4e, 0xd2, 0x00, 0xe6, 0x70, 0x00, 0x02,
+ 0x7f, 0xf1, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xfe, 0xfb, 0x18, 0x00,
+ 0x4f, 0xd0, 0x0f, 0xf8, 0x7f, 0xfc, 0xff, 0xfe, 0x7e, 0xf5, 0x00, 0x0f, 0xce, 0xf4, 0xfd, 0x00,
+ 0x7e, 0x71, 0x00, 0x02, 0xcf, 0xec, 0xe0, 0x00, 0xfe, 0xef, 0x28, 0x0e, 0x99, 0xee, 0x00, 0x14,
+ 0xfc, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x99, 0x7e, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0x9d, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0xee, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0,
+ 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x89, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x77, 0x28, 0x00, 0x9f, 0x76, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfc, 0x6f, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00, 0x7f, 0xe5, 0x00, 0x02, 0xff, 0x0a, 0x29, 0x58,
+ 0x9f, 0x7e, 0x07, 0x08, 0xff, 0x8c, 0x7f, 0xc0, 0xff, 0x1e, 0x46, 0xe0, 0xfe, 0x82, 0x00, 0x01,
+ 0x4f, 0xfc, 0xff, 0xfc, 0xaf, 0xfe, 0xf0, 0x02, 0x05, 0x29, 0x02, 0x20, 0xff, 0x8d, 0x85, 0x00,
+ 0xcb, 0xdc, 0xe8, 0x00, 0xff, 0x82, 0x00, 0x03, 0xfb, 0x9d, 0x46, 0x50, 0xe0, 0x02, 0x2b, 0xf4,
+ 0xcf, 0xfc, 0xba, 0x00, 0xe0, 0x02, 0x2e, 0xc0, 0xfe, 0x82, 0x00, 0x00, 0x0f, 0x81, 0x20, 0x00,
+ 0xca, 0x2a, 0xfc, 0x00, 0xe6, 0x02, 0x2f, 0xfc, 0xff, 0x82, 0x00, 0x00, 0xfd, 0x98, 0x86, 0x00,
+ 0xfc, 0x0c, 0x4b, 0xd8, 0xff, 0x08, 0xe6, 0xd8, 0xc0, 0x6e, 0xfa, 0x00, 0xfd, 0x0c, 0x84, 0xc0,
+ 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0xb2, 0xe4, 0x7c, 0xe0, 0xff, 0xfe,
+ 0x4e, 0xe4, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0x7e, 0x71, 0x00, 0x02, 0xcf, 0xf8, 0xe0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xff, 0x8a, 0xe2, 0xd0,
+ 0xad, 0xfe, 0xc8, 0x05, 0xfd, 0x08, 0xe0, 0xd8, 0xfe, 0xfb, 0x18, 0x0a, 0xff, 0xa6, 0x00, 0x0e,
+ 0x8c, 0xfa, 0x00, 0x2c, 0x9f, 0xfa, 0x00, 0x30, 0x0f, 0x81, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x9c, 0x02, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x22, 0xfa, 0x7b, 0x28, 0x20, 0xfa, 0x7b, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x8a, 0x29, 0xc0, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xe6, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xe0, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xfa, 0x7b, 0x28, 0x02, 0xff, 0x0c, 0x85, 0x00, 0xfe, 0x8c, 0x4b, 0xd8, 0x4d, 0x69, 0x20, 0x00,
+ 0xc5, 0x28, 0xd5, 0x00, 0xcf, 0x78, 0xea, 0x00, 0x7f, 0xf9, 0xff, 0xe1, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x0d, 0x85, 0x00, 0xff, 0x82, 0x00, 0x01, 0xcb, 0xdc, 0xfa, 0x00,
+ 0xfb, 0x9d, 0x46, 0x50, 0xe0, 0x02, 0x2b, 0xf4, 0xca, 0xd4, 0xf8, 0x00, 0xff, 0x88, 0xe0, 0xd8,
+ 0x20, 0x7f, 0x00, 0x3f, 0xe6, 0x02, 0x30, 0x84, 0x0f, 0x81, 0x1e, 0x00, 0xcd, 0xaa, 0xfc, 0x00,
+ 0xe6, 0x02, 0x30, 0x84, 0x20, 0x5a, 0xff, 0xfe, 0xe2, 0x02, 0x30, 0x35, 0x00, 0x00, 0x00, 0x01,
+ 0xfb, 0x02, 0xff, 0xff, 0xfe, 0x0c, 0x80, 0x80, 0x7f, 0xd5, 0x00, 0x10, 0xfe, 0x8c, 0x4c, 0x20,
+ 0xcf, 0xfc, 0xb5, 0x00, 0x0f, 0x70, 0x00, 0x04, 0xff, 0x8d, 0x4b, 0xb0, 0xff, 0x09, 0xfb, 0x90,
+ 0xff, 0x0e, 0x4b, 0xb0, 0xff, 0x82, 0x00, 0x04, 0xfe, 0x89, 0xe0, 0xe8, 0xfd, 0x89, 0xe2, 0xb8,
+ 0xfd, 0x9d, 0x46, 0x50, 0xfd, 0x8d, 0x85, 0x80, 0xfe, 0x89, 0xc0, 0xb0, 0xfe, 0x09, 0xf8, 0xf0,
+ 0xff, 0x09, 0xf9, 0x28, 0xff, 0x89, 0xe1, 0xc8, 0xf7, 0x8a, 0x30, 0x84, 0xe0, 0x00, 0x7c, 0xf0,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x0c, 0x85, 0x80, 0x20, 0x7a, 0x00, 0x04,
+ 0xe6, 0x02, 0x31, 0x81, 0x20, 0x7a, 0x00, 0x02, 0xe6, 0x02, 0x31, 0x1d, 0x20, 0x7a, 0x00, 0x03,
+ 0xe6, 0x02, 0x30, 0xed, 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x30, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x85, 0x0c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x30, 0xb9, 0x00, 0x00, 0x00, 0x01, 0x70, 0x2a, 0x00, 0x0d,
+ 0xea, 0x02, 0x30, 0xb9, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x8a, 0x31, 0x14, 0xe0, 0x01, 0x18, 0x10,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x30, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xe0, 0xd8,
+ 0x20, 0x7f, 0x00, 0x3f, 0xe6, 0x02, 0x30, 0xb0, 0x20, 0x7a, 0x00, 0x03, 0x0f, 0x81, 0x1e, 0x04,
+ 0xc0, 0x2a, 0xfc, 0x00, 0xe6, 0x02, 0x30, 0xb0, 0x20, 0x7a, 0x00, 0x03, 0xff, 0x8c, 0x85, 0x0c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x30, 0xb1, 0x20, 0x7a, 0x00, 0x03, 0xff, 0x00, 0x04, 0x1c,
+ 0xff, 0x8e, 0x4b, 0xe0, 0x55, 0x28, 0x01, 0x00, 0xf7, 0x82, 0x00, 0x01, 0xf7, 0xff, 0x68, 0x3e,
+ 0xf7, 0x82, 0x00, 0x01, 0xf7, 0xff, 0x68, 0x3d, 0xff, 0x82, 0x00, 0x03, 0xff, 0x8d, 0x85, 0x80,
+ 0xc1, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x30, 0xb8, 0x00, 0x00, 0x00, 0x01,
+ 0xf7, 0x8a, 0x31, 0x8c, 0xe0, 0x02, 0x2a, 0x24, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x30, 0xb8,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xe0, 0x02, 0x31, 0xa8, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x31, 0xc4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x45, 0x28, 0xfd, 0xff,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x32, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x1c, 0x46, 0x30, 0x4f, 0xa8, 0xfd, 0xc0,
+ 0xfe, 0xfb, 0x58, 0x0f, 0xc5, 0x7c, 0xed, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x32, 0x68, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x4f, 0x29, 0x1e, 0x00, 0xfd, 0x9c, 0x46, 0x30, 0xfd, 0x0c, 0x80, 0x90, 0x7f, 0x78, 0xff, 0xe7,
+ 0xff, 0x82, 0x00, 0x0c, 0x0f, 0x78, 0x07, 0x48, 0xce, 0x28, 0xfc, 0x00, 0xfb, 0x7b, 0x58, 0x00,
+ 0xa9, 0xea, 0xe0, 0x02, 0x0e, 0xec, 0x00, 0x10, 0x4e, 0xf4, 0xbf, 0xff, 0x8f, 0xea, 0x00, 0x24,
+ 0xff, 0x77, 0x58, 0x0f, 0x8c, 0xea, 0x00, 0x3c, 0xfc, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x04,
+ 0xfa, 0x82, 0x00, 0x00, 0xfa, 0xef, 0x68, 0x0f, 0xcc, 0xe4, 0xf8, 0x00, 0xfe, 0x9d, 0x46, 0x30,
+ 0xcf, 0xfc, 0xc0, 0x00, 0x9f, 0xea, 0x00, 0x24, 0xfb, 0x8c, 0x85, 0x00, 0x4f, 0xa8, 0xfd, 0xc0,
+ 0xfe, 0xef, 0x58, 0x0e, 0x8a, 0x6e, 0x00, 0x00, 0xcf, 0xfc, 0xf5, 0x00, 0xc0, 0x5e, 0xaa, 0x00,
+ 0xee, 0x02, 0x33, 0x69, 0x05, 0x7d, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00,
+ 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xfa, 0x83, 0x2a, 0x60, 0x4d, 0x70, 0xff, 0xf8, 0xce, 0x70, 0xd2, 0x00,
+ 0x7f, 0xf5, 0x00, 0x10, 0x7f, 0x71, 0x00, 0x0d, 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xc5, 0x00,
+ 0xfd, 0x88, 0xe6, 0xd8, 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x5e, 0xe5, 0x80, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x20, 0x52, 0x00, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6,
+ 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8,
+ 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x9a, 0x6e, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12,
+ 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9a, 0xee, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfb, 0xef, 0x28, 0x02,
+ 0x9a, 0x82, 0xff, 0x00, 0x7f, 0xd9, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0,
+ 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x34, 0x48, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x4e, 0xa9, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c, 0xff, 0x1c, 0x46, 0x30, 0xcd, 0xa8, 0xfc, 0x00,
+ 0x7e, 0xf4, 0xff, 0xe7, 0xfd, 0x0e, 0x7c, 0x40, 0x0f, 0xf4, 0x07, 0x48, 0xfa, 0xff, 0x58, 0x00,
+ 0xa9, 0x6a, 0xd8, 0x02, 0x0e, 0x78, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0x73, 0x58, 0x0f,
+ 0xff, 0xfb, 0x58, 0x0d, 0xfd, 0x8c, 0x80, 0x90, 0xfc, 0xfb, 0x18, 0x08, 0xfb, 0xfb, 0x18, 0x0a,
+ 0x8b, 0x7a, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x10, 0xf0, 0x7b, 0x68, 0x0f, 0xcf, 0xfc, 0xed, 0x00,
+ 0xfe, 0x1d, 0x46, 0x30, 0xfe, 0x86, 0x37, 0x9c, 0x9d, 0x6e, 0x00, 0x38, 0x9e, 0xee, 0x00, 0x34,
+ 0xff, 0x8d, 0x7c, 0x60, 0xfc, 0x8d, 0x7c, 0x6c, 0xfb, 0x8d, 0x7c, 0x64, 0xfe, 0xfb, 0x58, 0x0e,
+ 0xfa, 0x0c, 0x85, 0x00, 0x4f, 0xa8, 0xf9, 0xc0, 0xfe, 0x8d, 0x7c, 0x80, 0xfe, 0x8e, 0x7f, 0x40,
+ 0xfd, 0x0d, 0x80, 0x90, 0xf0, 0x0d, 0x7c, 0x68, 0xfe, 0x8d, 0x7c, 0x78, 0xfe, 0xfb, 0x58, 0x0e,
+ 0x89, 0xfa, 0x00, 0x00, 0xcf, 0xfc, 0xc5, 0x00, 0x20, 0x52, 0x00, 0x00, 0xee, 0x02, 0x35, 0x75,
+ 0x05, 0x7d, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x9a, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x58, 0xff, 0xf8, 0xce, 0x58, 0xd2, 0x00, 0x7f, 0xf5, 0x00, 0x10,
+ 0x7f, 0x71, 0x00, 0x0d, 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xbd, 0x00, 0xfc, 0x82, 0x00, 0x00,
+ 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x55, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x00, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x4e, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x5c, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x99, 0xee, 0x00, 0x14,
+ 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xfe, 0x86, 0xad, 0xc0,
+ 0x9e, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfa, 0x6f, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02, 0x99, 0x7e, 0x07, 0x08,
+ 0xff, 0x1e, 0x46, 0xe0, 0xab, 0xde, 0xf0, 0x02, 0xfb, 0x8d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x36, 0x5c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x4e, 0xa9, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c, 0xff, 0x1c, 0x46, 0x30,
+ 0xcd, 0xa8, 0xfc, 0x00, 0x7e, 0xf4, 0xff, 0xe7, 0xfd, 0x0e, 0x7c, 0xc0, 0x0f, 0xf4, 0x07, 0x48,
+ 0xfa, 0xff, 0x58, 0x00, 0xa9, 0x6a, 0xd8, 0x02, 0x0e, 0x78, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff,
+ 0xfc, 0x73, 0x58, 0x0f, 0xff, 0xfb, 0x58, 0x0d, 0xfd, 0x8c, 0x80, 0x90, 0xfc, 0xfb, 0x18, 0x08,
+ 0xfb, 0xfb, 0x18, 0x0a, 0x8b, 0x7a, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x10, 0xf0, 0x7b, 0x68, 0x0f,
+ 0xcf, 0xfc, 0xed, 0x00, 0xfe, 0x1d, 0x46, 0x30, 0xfe, 0x86, 0x37, 0xf4, 0x9d, 0x6e, 0x00, 0x38,
+ 0x9e, 0xee, 0x00, 0x34, 0xff, 0x8d, 0x7c, 0xe0, 0xfc, 0x8d, 0x7c, 0xec, 0xfb, 0x8d, 0x7c, 0xe4,
+ 0xfe, 0xfb, 0x58, 0x0e, 0xfa, 0x0c, 0x85, 0x00, 0x4f, 0xa8, 0xf5, 0xc0, 0xfe, 0x8d, 0x7d, 0x00,
+ 0xfe, 0x8e, 0x7f, 0x40, 0xfd, 0x0d, 0x80, 0x90, 0xf0, 0x0d, 0x7c, 0xe8, 0xfe, 0x8d, 0x7c, 0xf8,
+ 0xfe, 0xfb, 0x58, 0x0e, 0x89, 0xfa, 0x00, 0x00, 0xcf, 0xfc, 0xc5, 0x00, 0x20, 0x52, 0x00, 0x00,
+ 0xee, 0x02, 0x37, 0x89, 0x05, 0x7d, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00,
+ 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9a, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x58, 0xff, 0xf8, 0xce, 0x58, 0xd2, 0x00,
+ 0x7f, 0xf5, 0x00, 0x10, 0x7f, 0x71, 0x00, 0x0d, 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xbd, 0x00,
+ 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x55, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x05, 0xf2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x4e, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x5c, 0xe0, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0x99, 0xee, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xfe, 0x86, 0xad, 0xc0, 0x9e, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28,
+ 0x9f, 0x02, 0xff, 0xb0, 0xfa, 0x6f, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02,
+ 0x99, 0x7e, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xab, 0xde, 0xf0, 0x02, 0xfb, 0x8d, 0x85, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x38, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x4e, 0xa9, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c,
+ 0xff, 0x1c, 0x46, 0x30, 0xcd, 0xa8, 0xfc, 0x00, 0x7e, 0xf4, 0xff, 0xe7, 0xfd, 0x0e, 0x7d, 0x40,
+ 0x0f, 0xf4, 0x07, 0x48, 0xfa, 0xff, 0x58, 0x00, 0xa9, 0x6a, 0xd8, 0x02, 0x0e, 0x78, 0x00, 0x10,
+ 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0x73, 0x58, 0x0f, 0xff, 0xfb, 0x58, 0x0d, 0xfd, 0x8c, 0x80, 0x90,
+ 0xfc, 0xfb, 0x18, 0x08, 0xfb, 0xfb, 0x18, 0x0a, 0x8b, 0x7a, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x10,
+ 0xf0, 0x7b, 0x68, 0x0f, 0xcf, 0xfc, 0xed, 0x00, 0xfe, 0x1d, 0x46, 0x30, 0xfe, 0x86, 0x38, 0x4c,
+ 0x9d, 0x6e, 0x00, 0x38, 0x9e, 0xee, 0x00, 0x34, 0xff, 0x8d, 0x7d, 0x60, 0xfc, 0x8d, 0x7d, 0x6c,
+ 0xfb, 0x8d, 0x7d, 0x64, 0xfe, 0xfb, 0x58, 0x0e, 0xfa, 0x0c, 0x85, 0x00, 0x4f, 0xa8, 0xed, 0xc0,
+ 0xfe, 0x8d, 0x7d, 0x80, 0xfe, 0x8e, 0x7f, 0x40, 0xfd, 0x0d, 0x80, 0x90, 0xf0, 0x0d, 0x7d, 0x68,
+ 0xfe, 0x8d, 0x7d, 0x78, 0xfe, 0xfb, 0x58, 0x0e, 0x89, 0xfa, 0x00, 0x00, 0xcf, 0xfc, 0xc5, 0x00,
+ 0x20, 0x52, 0x00, 0x00, 0xee, 0x02, 0x39, 0x9d, 0x05, 0x7d, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8,
+ 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9a, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02,
+ 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58,
+ 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x58, 0xff, 0xf8,
+ 0xce, 0x58, 0xd2, 0x00, 0x7f, 0xf5, 0x00, 0x10, 0x7f, 0x71, 0x00, 0x0d, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xcf, 0xfc, 0xbd, 0x00, 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0x55, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x0b, 0xe2, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x4e, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00,
+ 0xce, 0x5c, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xec, 0xe8, 0x00, 0x99, 0xee, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13,
+ 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xfe, 0x86, 0xad, 0xc0, 0x9e, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfa, 0x6f, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00,
+ 0x7f, 0xd5, 0x00, 0x02, 0x99, 0x7e, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xab, 0xde, 0xf0, 0x02,
+ 0xfb, 0x8d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x3a, 0x84, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x4e, 0xa9, 0x1e, 0x00,
+ 0xff, 0x82, 0x00, 0x0c, 0xff, 0x1c, 0x46, 0x30, 0xcd, 0xa8, 0xfc, 0x00, 0x7e, 0xf4, 0xff, 0xe7,
+ 0xfd, 0x0e, 0x7d, 0xc0, 0x0f, 0xf4, 0x07, 0x48, 0xfa, 0xff, 0x58, 0x00, 0xa9, 0x6a, 0xd8, 0x02,
+ 0x0e, 0x78, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0x73, 0x58, 0x0f, 0xff, 0xfb, 0x58, 0x0d,
+ 0xfd, 0x8c, 0x80, 0x90, 0xfc, 0xfb, 0x18, 0x08, 0xfb, 0xfb, 0x18, 0x0a, 0x8b, 0x7a, 0x00, 0x04,
+ 0x7e, 0xf5, 0x00, 0x10, 0xf0, 0x7b, 0x68, 0x0f, 0xcf, 0xfc, 0xed, 0x00, 0xfe, 0x1d, 0x46, 0x30,
+ 0xfe, 0x86, 0x38, 0xa4, 0x9d, 0x6e, 0x00, 0x38, 0x9e, 0xee, 0x00, 0x34, 0xff, 0x8d, 0x7d, 0xe0,
+ 0xfc, 0x8d, 0x7d, 0xec, 0xfb, 0x8d, 0x7d, 0xe4, 0xfe, 0xfb, 0x58, 0x0e, 0xfa, 0x0c, 0x85, 0x00,
+ 0x4f, 0xa8, 0xdd, 0xc0, 0xfe, 0x8d, 0x7e, 0x00, 0xfe, 0x8e, 0x7f, 0x40, 0xfd, 0x0d, 0x80, 0x90,
+ 0xf0, 0x0d, 0x7d, 0xe8, 0xfe, 0x8d, 0x7d, 0xf8, 0xfe, 0xfb, 0x58, 0x0e, 0x89, 0xfa, 0x00, 0x00,
+ 0xcf, 0xfc, 0xc5, 0x00, 0x20, 0x52, 0x00, 0x00, 0xee, 0x02, 0x3b, 0xb1, 0x05, 0x7d, 0x02, 0x20,
+ 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x9a, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8,
+ 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10,
+ 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60,
+ 0x4d, 0x58, 0xff, 0xf8, 0xce, 0x58, 0xd2, 0x00, 0x7f, 0xf5, 0x00, 0x10, 0x7f, 0x71, 0x00, 0x0d,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xbd, 0x00, 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x55, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x11, 0xd2,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x4e, 0xca, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6,
+ 0xff, 0xfb, 0x18, 0x00, 0xce, 0x5c, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8,
+ 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x99, 0xee, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12,
+ 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xfe, 0x86, 0xad, 0xc0, 0x9e, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfa, 0x6f, 0x28, 0x02,
+ 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02, 0x99, 0x7e, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0,
+ 0xab, 0xde, 0xf0, 0x02, 0xfb, 0x8d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x3c, 0x98, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x4e, 0xa9, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c, 0xff, 0x1c, 0x46, 0x30, 0xcd, 0xa8, 0xfc, 0x00,
+ 0x7e, 0xf4, 0xff, 0xe7, 0xfd, 0x0e, 0x7e, 0x40, 0x0f, 0xf4, 0x07, 0x48, 0xfa, 0xff, 0x58, 0x00,
+ 0xa9, 0x6a, 0xd8, 0x02, 0x0e, 0x78, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0x73, 0x58, 0x0f,
+ 0xff, 0xfb, 0x58, 0x0d, 0xfd, 0x8c, 0x80, 0x90, 0xfc, 0xfb, 0x18, 0x08, 0xfb, 0xfb, 0x18, 0x0a,
+ 0x8b, 0x7a, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x10, 0xf0, 0x7b, 0x68, 0x0f, 0xcf, 0xfc, 0xed, 0x00,
+ 0xfe, 0x1d, 0x46, 0x30, 0xfe, 0x86, 0x38, 0xfc, 0x9d, 0x6e, 0x00, 0x38, 0x9e, 0xee, 0x00, 0x34,
+ 0xff, 0x8d, 0x7e, 0x60, 0xfc, 0x8d, 0x7e, 0x6c, 0xfb, 0x8d, 0x7e, 0x64, 0xfe, 0xfb, 0x58, 0x0e,
+ 0xfa, 0x0c, 0x85, 0x00, 0x4f, 0xa8, 0xbd, 0xc0, 0xfe, 0x8d, 0x7e, 0x80, 0xfe, 0x8e, 0x7f, 0x40,
+ 0xfd, 0x0d, 0x80, 0x90, 0xf0, 0x0d, 0x7e, 0x68, 0xfe, 0x8d, 0x7e, 0x78, 0xfe, 0xfb, 0x58, 0x0e,
+ 0x89, 0xfa, 0x00, 0x00, 0xcf, 0xfc, 0xc5, 0x00, 0x20, 0x52, 0x00, 0x00, 0xee, 0x02, 0x3d, 0xc5,
+ 0x05, 0x7d, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x9a, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x58, 0xff, 0xf8, 0xce, 0x58, 0xd2, 0x00, 0x7f, 0xf5, 0x00, 0x10,
+ 0x7f, 0x71, 0x00, 0x0d, 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xbd, 0x00, 0xfc, 0x82, 0x00, 0x00,
+ 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x55, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x36, 0x8a, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x4e, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x5c, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x99, 0xee, 0x00, 0x14,
+ 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xfe, 0x86, 0xad, 0xc0,
+ 0x9e, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfa, 0x6f, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02, 0x99, 0x7e, 0x07, 0x08,
+ 0xff, 0x1e, 0x46, 0xe0, 0xab, 0xde, 0xf0, 0x02, 0xfb, 0x8d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x3e, 0xac, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x4e, 0xa9, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c, 0xff, 0x1c, 0x46, 0x30,
+ 0xcd, 0xa8, 0xfc, 0x00, 0x7e, 0xf4, 0xff, 0xe7, 0xfd, 0x0e, 0x7e, 0xc0, 0x0f, 0xf4, 0x07, 0x48,
+ 0xfa, 0xff, 0x58, 0x00, 0xa9, 0x6a, 0xd8, 0x02, 0x0e, 0x78, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff,
+ 0xfc, 0x73, 0x58, 0x0f, 0xff, 0xfb, 0x58, 0x0d, 0xfd, 0x8c, 0x80, 0x90, 0xfc, 0xfb, 0x18, 0x08,
+ 0xfb, 0xfb, 0x18, 0x0a, 0x8b, 0x7a, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x10, 0xf0, 0x7b, 0x68, 0x0f,
+ 0xcf, 0xfc, 0xed, 0x00, 0xfe, 0x1d, 0x46, 0x30, 0xfe, 0x86, 0x39, 0x54, 0x9d, 0x6e, 0x00, 0x38,
+ 0x9e, 0xee, 0x00, 0x34, 0xff, 0x8d, 0x7e, 0xe0, 0xfc, 0x8d, 0x7e, 0xec, 0xfb, 0x8d, 0x7e, 0xe4,
+ 0xfe, 0xfb, 0x58, 0x0e, 0xfa, 0x0c, 0x85, 0x00, 0x4f, 0xa8, 0x7d, 0xc0, 0xfe, 0x8d, 0x7f, 0x00,
+ 0xfe, 0x8e, 0x7f, 0x40, 0xfd, 0x0d, 0x80, 0x90, 0xf0, 0x0d, 0x7e, 0xe8, 0xfe, 0x8d, 0x7e, 0xf8,
+ 0xfe, 0xfb, 0x58, 0x0e, 0x89, 0xfa, 0x00, 0x00, 0xcf, 0xfc, 0xc5, 0x00, 0x20, 0x52, 0x00, 0x00,
+ 0xee, 0x02, 0x3f, 0xd9, 0x05, 0x7d, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00,
+ 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9a, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x58, 0xff, 0xf8, 0xce, 0x58, 0xd2, 0x00,
+ 0x7f, 0xf5, 0x00, 0x10, 0x7f, 0x71, 0x00, 0x0d, 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xbd, 0x00,
+ 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x55, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x5b, 0x42, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x4e, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x5c, 0xe0, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0x99, 0xee, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xfe, 0x86, 0xad, 0xc0, 0x9e, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28,
+ 0x9f, 0x02, 0xff, 0xb0, 0xfa, 0x6f, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02,
+ 0x99, 0x7e, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xab, 0xde, 0xf0, 0x02, 0xfb, 0x8d, 0x85, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x40, 0xc0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x4e, 0xa9, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c,
+ 0xcd, 0xa8, 0xfc, 0x00, 0x7e, 0xf4, 0xff, 0xe7, 0xff, 0x1c, 0x46, 0x30, 0x0f, 0xf4, 0x07, 0x48,
+ 0xfb, 0x7f, 0x58, 0x00, 0xfd, 0x0e, 0x7c, 0x40, 0xa9, 0xea, 0xd8, 0x02, 0x0e, 0x78, 0x00, 0x10,
+ 0xff, 0xfb, 0x58, 0x0d, 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0xf3, 0x58, 0x0f, 0xfd, 0xfb, 0x18, 0x08,
+ 0xfc, 0x7b, 0x18, 0x0a, 0x8b, 0xfa, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x10, 0xcf, 0xfc, 0xed, 0x00,
+ 0xf0, 0x7b, 0x68, 0x0f, 0xfe, 0x86, 0x37, 0x9c, 0xff, 0x8d, 0x7c, 0x60, 0xfe, 0x1d, 0x46, 0x30,
+ 0xfd, 0x8d, 0x7c, 0x6c, 0xfc, 0x0d, 0x7c, 0x64, 0xfe, 0x81, 0x04, 0x14, 0xfe, 0xfb, 0x58, 0x0e,
+ 0xfa, 0x8c, 0x85, 0x00, 0x4f, 0xa8, 0xf9, 0xc0, 0xfe, 0x8d, 0x7c, 0x80, 0xfe, 0x8e, 0x7f, 0x40,
+ 0xfd, 0x0d, 0x80, 0x90, 0xf0, 0x0d, 0x7c, 0x68, 0xfe, 0x8d, 0x7c, 0x78, 0xfe, 0xfb, 0x58, 0x0e,
+ 0x8a, 0x7a, 0x00, 0x00, 0xcf, 0xfc, 0xcd, 0x00, 0x20, 0x56, 0x00, 0x00, 0xee, 0x02, 0x41, 0xe5,
+ 0x05, 0x7d, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x9a, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x5c, 0xff, 0xf8, 0xce, 0x5c, 0xd2, 0x00, 0x7f, 0xf5, 0x00, 0x10,
+ 0x7f, 0x71, 0x00, 0x0d, 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00,
+ 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x00, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x52, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x9a, 0x6e, 0x00, 0x14,
+ 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xfe, 0x86, 0xad, 0xc0,
+ 0x9e, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfa, 0xef, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd9, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08,
+ 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x42, 0xcc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x4e, 0xa9, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c, 0xcd, 0xa8, 0xfc, 0x00,
+ 0x7e, 0xf4, 0xff, 0xe7, 0xff, 0x1c, 0x46, 0x30, 0x0f, 0xf4, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00,
+ 0xfd, 0x0e, 0x7d, 0xc0, 0xa9, 0xea, 0xd8, 0x02, 0x0e, 0x78, 0x00, 0x10, 0xff, 0xfb, 0x58, 0x0d,
+ 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0xf3, 0x58, 0x0f, 0xfd, 0xfb, 0x18, 0x08, 0xfc, 0x7b, 0x18, 0x0a,
+ 0x8b, 0xfa, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x10, 0xcf, 0xfc, 0xed, 0x00, 0xf0, 0x7b, 0x68, 0x0f,
+ 0xfe, 0x86, 0x38, 0xa4, 0xff, 0x8d, 0x7d, 0xe0, 0xfe, 0x1d, 0x46, 0x30, 0xfd, 0x8d, 0x7d, 0xec,
+ 0xfc, 0x0d, 0x7d, 0xe4, 0xfe, 0x81, 0x04, 0x14, 0xfe, 0xfb, 0x58, 0x0e, 0xfa, 0x8c, 0x85, 0x00,
+ 0x4f, 0xa8, 0xdd, 0xc0, 0xfe, 0x8d, 0x7e, 0x00, 0xfe, 0x8e, 0x7f, 0x40, 0xfd, 0x0d, 0x80, 0x90,
+ 0xf0, 0x0d, 0x7d, 0xe8, 0xfe, 0x8d, 0x7d, 0xf8, 0xfe, 0xfb, 0x58, 0x0e, 0x8a, 0x7a, 0x00, 0x00,
+ 0xcf, 0xfc, 0xcd, 0x00, 0x20, 0x56, 0x00, 0x00, 0xee, 0x02, 0x43, 0xf1, 0x05, 0x7d, 0x02, 0x20,
+ 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x9a, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8,
+ 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10,
+ 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60,
+ 0x4d, 0x5c, 0xff, 0xf8, 0xce, 0x5c, 0xd2, 0x00, 0x7f, 0xf5, 0x00, 0x10, 0x7f, 0x71, 0x00, 0x0d,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x11, 0xd2,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x52, 0xca, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6,
+ 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8,
+ 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x9a, 0x6e, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12,
+ 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xfe, 0x86, 0xad, 0xc0, 0x9e, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfa, 0xef, 0x28, 0x02,
+ 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd9, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0,
+ 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x44, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfe, 0x1c, 0x46, 0x30, 0xfd, 0x8c, 0x80, 0x90, 0x4f, 0xa9, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0e, 0xf0, 0x00, 0x10, 0x4e, 0xf4, 0xbf, 0xff, 0x0f, 0xfc, 0x07, 0x48, 0x8f, 0x6e, 0x00, 0x24,
+ 0xfd, 0x77, 0x58, 0x0f, 0xfa, 0xff, 0x58, 0x00, 0x8c, 0xee, 0x00, 0x3c, 0x89, 0x6e, 0x00, 0x04,
+ 0xfc, 0x73, 0x18, 0x0a, 0x8b, 0x72, 0x00, 0x04, 0xfa, 0x02, 0x00, 0x00, 0xfa, 0x73, 0x68, 0x0f,
+ 0xcc, 0xe4, 0xf0, 0x00, 0xfe, 0x9d, 0x46, 0x30, 0xcf, 0x78, 0xc0, 0x00, 0x9f, 0x6e, 0x00, 0x24,
+ 0xfb, 0x8c, 0x85, 0x00, 0x4f, 0xa8, 0xfd, 0xc0, 0xfe, 0xf3, 0x58, 0x0e, 0x89, 0xf2, 0x00, 0x00,
+ 0xcf, 0xfc, 0xd5, 0x00, 0xc0, 0x5e, 0xa2, 0x00, 0xee, 0x02, 0x45, 0xd1, 0x05, 0x7d, 0x02, 0x20,
+ 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x9b, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8,
+ 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10,
+ 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x03, 0x2a, 0x60,
+ 0x4d, 0x58, 0xff, 0xf8, 0xce, 0x58, 0xd2, 0x00, 0x7f, 0xf5, 0x00, 0x10, 0x7f, 0x71, 0x00, 0x0d,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xc5, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x7f, 0x55, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x5e, 0xe5, 0x80, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x20, 0x4e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0xf0, 0xef, 0x68, 0x13, 0x99, 0xee, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12, 0x9d, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9a, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28,
+ 0x9f, 0x02, 0xff, 0xb0, 0xfb, 0xef, 0x28, 0x02, 0x9a, 0x02, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02,
+ 0x99, 0x7e, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x46, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x1c, 0x46, 0x30, 0x4e, 0xa9, 0x1e, 0x00,
+ 0x7e, 0xf4, 0xff, 0xe7, 0x0f, 0xf4, 0x07, 0x48, 0xfb, 0xff, 0x58, 0x00, 0x0e, 0x78, 0x00, 0x10,
+ 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0xf3, 0x58, 0x0f, 0xfd, 0x8c, 0x80, 0x90, 0xf9, 0x8c, 0x7c, 0x44,
+ 0xff, 0xfb, 0x58, 0x0d, 0xfd, 0x7b, 0x18, 0x08, 0xfc, 0x7b, 0x18, 0x0a, 0x8a, 0xfa, 0x00, 0x04,
+ 0xf0, 0x7b, 0x68, 0x0f, 0x7e, 0xf5, 0x00, 0x10, 0xfe, 0x1d, 0x46, 0x30, 0xcf, 0xfc, 0xed, 0x00,
+ 0xfe, 0x0e, 0x7c, 0x40, 0xfe, 0x86, 0x39, 0xac, 0x9e, 0x6e, 0x00, 0x38, 0x9e, 0xee, 0x00, 0x34,
+ 0xff, 0x8d, 0x7c, 0x60, 0xfd, 0x0d, 0x7c, 0x6c, 0xfc, 0x0d, 0x7c, 0x64, 0xfe, 0xfb, 0x58, 0x0e,
+ 0xfb, 0x0c, 0x85, 0x00, 0x4f, 0xa8, 0xf9, 0xc0, 0xfe, 0x8d, 0x7c, 0x80, 0xfe, 0x8e, 0x7f, 0x40,
+ 0xfe, 0x0d, 0x80, 0x90, 0xf0, 0x0d, 0x7c, 0x68, 0xfe, 0x8d, 0x7c, 0x78, 0xfe, 0xfb, 0x58, 0x0e,
+ 0x8a, 0x7a, 0x00, 0x00, 0xcf, 0xfc, 0xcd, 0x00, 0x20, 0x5a, 0x00, 0x00, 0xee, 0x02, 0x47, 0xd5,
+ 0x05, 0x7d, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x54, 0xff, 0xf8, 0xce, 0x54, 0xd2, 0x00, 0x7f, 0xf5, 0x00, 0x10,
+ 0x7f, 0x71, 0x00, 0x0d, 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00,
+ 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x00, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x52, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xf0, 0xef, 0x68, 0x13,
+ 0x9a, 0x6e, 0x00, 0x14, 0xfb, 0xef, 0x68, 0x12, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xfe, 0x86, 0xad, 0xc0,
+ 0x9e, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfb, 0x6f, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xdd, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08,
+ 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x48, 0xbc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x1c, 0x46, 0x30, 0x4e, 0xa9, 0x1e, 0x00, 0x7e, 0xf4, 0xff, 0xe7,
+ 0x0f, 0xf4, 0x07, 0x48, 0xfb, 0xff, 0x58, 0x00, 0x0e, 0x78, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff,
+ 0xfc, 0xf3, 0x58, 0x0f, 0xfd, 0x8c, 0x80, 0x90, 0xf9, 0x8c, 0x7c, 0xc4, 0xff, 0xfb, 0x58, 0x0d,
+ 0xfd, 0x7b, 0x18, 0x08, 0xfc, 0x7b, 0x18, 0x0a, 0x8a, 0xfa, 0x00, 0x04, 0xf0, 0x7b, 0x68, 0x0f,
+ 0x7e, 0xf5, 0x00, 0x10, 0xfe, 0x1d, 0x46, 0x30, 0xcf, 0xfc, 0xed, 0x00, 0xfe, 0x0e, 0x7c, 0xc0,
+ 0xfe, 0x86, 0x3a, 0x00, 0x9e, 0x6e, 0x00, 0x38, 0x9e, 0xee, 0x00, 0x34, 0xff, 0x8d, 0x7c, 0xe0,
+ 0xfd, 0x0d, 0x7c, 0xec, 0xfc, 0x0d, 0x7c, 0xe4, 0xfe, 0xfb, 0x58, 0x0e, 0xfb, 0x0c, 0x85, 0x00,
+ 0x4f, 0xa8, 0xf5, 0xc0, 0xfe, 0x8d, 0x7d, 0x00, 0xfe, 0x8e, 0x7f, 0x40, 0xfe, 0x0d, 0x80, 0x90,
+ 0xf0, 0x0d, 0x7c, 0xe8, 0xfe, 0x8d, 0x7c, 0xf8, 0xfe, 0xfb, 0x58, 0x0e, 0x8a, 0x7a, 0x00, 0x00,
+ 0xcf, 0xfc, 0xcd, 0x00, 0x20, 0x5a, 0x00, 0x00, 0xee, 0x02, 0x49, 0xe1, 0x05, 0x7d, 0x02, 0x20,
+ 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x9b, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8,
+ 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10,
+ 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60,
+ 0x4d, 0x54, 0xff, 0xf8, 0xce, 0x54, 0xd2, 0x00, 0x7f, 0xf5, 0x00, 0x10, 0x7f, 0x71, 0x00, 0x0d,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x05, 0xf2,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x52, 0xca, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6,
+ 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8,
+ 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xf0, 0xef, 0x68, 0x13, 0x9a, 0x6e, 0x00, 0x14,
+ 0xfb, 0xef, 0x68, 0x12, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xfe, 0x86, 0xad, 0xc0, 0x9e, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfb, 0x6f, 0x28, 0x02,
+ 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xdd, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0,
+ 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x4a, 0xc8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x1c, 0x46, 0x30, 0x4e, 0xa9, 0x1e, 0x00, 0x7e, 0xf4, 0xff, 0xe7, 0x0f, 0xf4, 0x07, 0x48,
+ 0xfb, 0xff, 0x58, 0x00, 0x0e, 0x78, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0xf3, 0x58, 0x0f,
+ 0xfd, 0x8c, 0x80, 0x90, 0xf9, 0x8c, 0x7d, 0x44, 0xff, 0xfb, 0x58, 0x0d, 0xfd, 0x7b, 0x18, 0x08,
+ 0xfc, 0x7b, 0x18, 0x0a, 0x8a, 0xfa, 0x00, 0x04, 0xf0, 0x7b, 0x68, 0x0f, 0x7e, 0xf5, 0x00, 0x10,
+ 0xfe, 0x1d, 0x46, 0x30, 0xcf, 0xfc, 0xed, 0x00, 0xfe, 0x0e, 0x7d, 0x40, 0xfe, 0x86, 0x3a, 0x54,
+ 0x9e, 0x6e, 0x00, 0x38, 0x9e, 0xee, 0x00, 0x34, 0xff, 0x8d, 0x7d, 0x60, 0xfd, 0x0d, 0x7d, 0x6c,
+ 0xfc, 0x0d, 0x7d, 0x64, 0xfe, 0xfb, 0x58, 0x0e, 0xfb, 0x0c, 0x85, 0x00, 0x4f, 0xa8, 0xed, 0xc0,
+ 0xfe, 0x8d, 0x7d, 0x80, 0xfe, 0x8e, 0x7f, 0x40, 0xfe, 0x0d, 0x80, 0x90, 0xf0, 0x0d, 0x7d, 0x68,
+ 0xfe, 0x8d, 0x7d, 0x78, 0xfe, 0xfb, 0x58, 0x0e, 0x8a, 0x7a, 0x00, 0x00, 0xcf, 0xfc, 0xcd, 0x00,
+ 0x20, 0x5a, 0x00, 0x00, 0xee, 0x02, 0x4b, 0xed, 0x05, 0x7d, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8,
+ 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02,
+ 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58,
+ 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x54, 0xff, 0xf8,
+ 0xce, 0x54, 0xd2, 0x00, 0x7f, 0xf5, 0x00, 0x10, 0x7f, 0x71, 0x00, 0x0d, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x0b, 0xe2, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x52, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00,
+ 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xec, 0xe8, 0x00, 0xf0, 0xef, 0x68, 0x13, 0x9a, 0x6e, 0x00, 0x14, 0xfb, 0xef, 0x68, 0x12,
+ 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xfe, 0x86, 0xad, 0xc0, 0x9e, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfb, 0x6f, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00,
+ 0x7f, 0xdd, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02,
+ 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x4c, 0xd4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x1c, 0x46, 0x30,
+ 0x4e, 0xa9, 0x1e, 0x00, 0x7e, 0xf4, 0xff, 0xe7, 0x0f, 0xf4, 0x07, 0x48, 0xfb, 0xff, 0x58, 0x00,
+ 0x0e, 0x78, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0xf3, 0x58, 0x0f, 0xfd, 0x8c, 0x80, 0x90,
+ 0xf9, 0x8c, 0x7d, 0xc4, 0xff, 0xfb, 0x58, 0x0d, 0xfd, 0x7b, 0x18, 0x08, 0xfc, 0x7b, 0x18, 0x0a,
+ 0x8a, 0xfa, 0x00, 0x04, 0xf0, 0x7b, 0x68, 0x0f, 0x7e, 0xf5, 0x00, 0x10, 0xfe, 0x1d, 0x46, 0x30,
+ 0xcf, 0xfc, 0xed, 0x00, 0xfe, 0x0e, 0x7d, 0xc0, 0xfe, 0x86, 0x3a, 0xa8, 0x9e, 0x6e, 0x00, 0x38,
+ 0x9e, 0xee, 0x00, 0x34, 0xff, 0x8d, 0x7d, 0xe0, 0xfd, 0x0d, 0x7d, 0xec, 0xfc, 0x0d, 0x7d, 0xe4,
+ 0xfe, 0xfb, 0x58, 0x0e, 0xfb, 0x0c, 0x85, 0x00, 0x4f, 0xa8, 0xdd, 0xc0, 0xfe, 0x8d, 0x7e, 0x00,
+ 0xfe, 0x8e, 0x7f, 0x40, 0xfe, 0x0d, 0x80, 0x90, 0xf0, 0x0d, 0x7d, 0xe8, 0xfe, 0x8d, 0x7d, 0xf8,
+ 0xfe, 0xfb, 0x58, 0x0e, 0x8a, 0x7a, 0x00, 0x00, 0xcf, 0xfc, 0xcd, 0x00, 0x20, 0x5a, 0x00, 0x00,
+ 0xee, 0x02, 0x4d, 0xf9, 0x05, 0x7d, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00,
+ 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x54, 0xff, 0xf8, 0xce, 0x54, 0xd2, 0x00,
+ 0x7f, 0xf5, 0x00, 0x10, 0x7f, 0x71, 0x00, 0x0d, 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xc5, 0x00,
+ 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x11, 0xd2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x52, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0xf0, 0xef, 0x68, 0x13, 0x9a, 0x6e, 0x00, 0x14, 0xfb, 0xef, 0x68, 0x12, 0x9d, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xfe, 0x86, 0xad, 0xc0, 0x9e, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28,
+ 0x9f, 0x02, 0xff, 0xb0, 0xfb, 0x6f, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xdd, 0x00, 0x02,
+ 0x99, 0xfe, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x4e, 0xe0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x1c, 0x46, 0x30, 0x4e, 0xa9, 0x1e, 0x00,
+ 0x7e, 0xf4, 0xff, 0xe7, 0x0f, 0xf4, 0x07, 0x48, 0xfb, 0xff, 0x58, 0x00, 0x0e, 0x78, 0x00, 0x10,
+ 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0xf3, 0x58, 0x0f, 0xfd, 0x8c, 0x80, 0x90, 0xf9, 0x8c, 0x7e, 0x44,
+ 0xff, 0xfb, 0x58, 0x0d, 0xfd, 0x7b, 0x18, 0x08, 0xfc, 0x7b, 0x18, 0x0a, 0x8a, 0xfa, 0x00, 0x04,
+ 0xf0, 0x7b, 0x68, 0x0f, 0x7e, 0xf5, 0x00, 0x10, 0xfe, 0x1d, 0x46, 0x30, 0xcf, 0xfc, 0xed, 0x00,
+ 0xfe, 0x0e, 0x7e, 0x40, 0xfe, 0x86, 0x3a, 0xfc, 0x9e, 0x6e, 0x00, 0x38, 0x9e, 0xee, 0x00, 0x34,
+ 0xff, 0x8d, 0x7e, 0x60, 0xfd, 0x0d, 0x7e, 0x6c, 0xfc, 0x0d, 0x7e, 0x64, 0xfe, 0xfb, 0x58, 0x0e,
+ 0xfb, 0x0c, 0x85, 0x00, 0x4f, 0xa8, 0xbd, 0xc0, 0xfe, 0x8d, 0x7e, 0x80, 0xfe, 0x8e, 0x7f, 0x40,
+ 0xfe, 0x0d, 0x80, 0x90, 0xf0, 0x0d, 0x7e, 0x68, 0xfe, 0x8d, 0x7e, 0x78, 0xfe, 0xfb, 0x58, 0x0e,
+ 0x8a, 0x7a, 0x00, 0x00, 0xcf, 0xfc, 0xcd, 0x00, 0x20, 0x5a, 0x00, 0x00, 0xee, 0x02, 0x50, 0x05,
+ 0x05, 0x7d, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x54, 0xff, 0xf8, 0xce, 0x54, 0xd2, 0x00, 0x7f, 0xf5, 0x00, 0x10,
+ 0x7f, 0x71, 0x00, 0x0d, 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00,
+ 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x36, 0x8a, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x52, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xf0, 0xef, 0x68, 0x13,
+ 0x9a, 0x6e, 0x00, 0x14, 0xfb, 0xef, 0x68, 0x12, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xfe, 0x86, 0xad, 0xc0,
+ 0x9e, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfb, 0x6f, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xdd, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08,
+ 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x50, 0xec, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x1c, 0x46, 0x30, 0x4e, 0xa9, 0x1e, 0x00, 0x7e, 0xf4, 0xff, 0xe7,
+ 0x0f, 0xf4, 0x07, 0x48, 0xfb, 0xff, 0x58, 0x00, 0x0e, 0x78, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff,
+ 0xfc, 0xf3, 0x58, 0x0f, 0xfd, 0x8c, 0x80, 0x90, 0xf9, 0x8c, 0x7e, 0xc4, 0xff, 0xfb, 0x58, 0x0d,
+ 0xfd, 0x7b, 0x18, 0x08, 0xfc, 0x7b, 0x18, 0x0a, 0x8a, 0xfa, 0x00, 0x04, 0xf0, 0x7b, 0x68, 0x0f,
+ 0x7e, 0xf5, 0x00, 0x10, 0xfe, 0x1d, 0x46, 0x30, 0xcf, 0xfc, 0xed, 0x00, 0xfe, 0x0e, 0x7e, 0xc0,
+ 0xfe, 0x86, 0x3b, 0x50, 0x9e, 0x6e, 0x00, 0x38, 0x9e, 0xee, 0x00, 0x34, 0xff, 0x8d, 0x7e, 0xe0,
+ 0xfd, 0x0d, 0x7e, 0xec, 0xfc, 0x0d, 0x7e, 0xe4, 0xfe, 0xfb, 0x58, 0x0e, 0xfb, 0x0c, 0x85, 0x00,
+ 0x4f, 0xa8, 0x7d, 0xc0, 0xfe, 0x8d, 0x7f, 0x00, 0xfe, 0x8e, 0x7f, 0x40, 0xfe, 0x0d, 0x80, 0x90,
+ 0xf0, 0x0d, 0x7e, 0xe8, 0xfe, 0x8d, 0x7e, 0xf8, 0xfe, 0xfb, 0x58, 0x0e, 0x8a, 0x7a, 0x00, 0x00,
+ 0xcf, 0xfc, 0xcd, 0x00, 0x20, 0x5a, 0x00, 0x00, 0xee, 0x02, 0x52, 0x11, 0x05, 0x7d, 0x02, 0x20,
+ 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x9b, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8,
+ 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10,
+ 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60,
+ 0x4d, 0x54, 0xff, 0xf8, 0xce, 0x54, 0xd2, 0x00, 0x7f, 0xf5, 0x00, 0x10, 0x7f, 0x71, 0x00, 0x0d,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x5b, 0x42,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x52, 0xca, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6,
+ 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8,
+ 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xf0, 0xef, 0x68, 0x13, 0x9a, 0x6e, 0x00, 0x14,
+ 0xfb, 0xef, 0x68, 0x12, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xfe, 0x86, 0xad, 0xc0, 0x9e, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfb, 0x6f, 0x28, 0x02,
+ 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xdd, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0,
+ 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x52, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x4e, 0xa9, 0x1e, 0x00, 0x7e, 0xf4, 0xff, 0xe7, 0xff, 0x1c, 0x46, 0x30, 0x0f, 0xf4, 0x07, 0x48,
+ 0xfb, 0xff, 0x58, 0x00, 0x0e, 0x78, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xff, 0xfb, 0x58, 0x0d,
+ 0xfd, 0x73, 0x58, 0x0f, 0xfa, 0x0c, 0x7c, 0x44, 0xfd, 0xfb, 0x18, 0x08, 0xfc, 0x7b, 0x18, 0x0a,
+ 0x8c, 0xfa, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x10, 0xcf, 0xfc, 0xed, 0x00, 0xf0, 0x7b, 0x68, 0x0f,
+ 0xfe, 0x86, 0x39, 0xac, 0xff, 0x8d, 0x7c, 0x60, 0xfe, 0x1d, 0x46, 0x30, 0xfd, 0x8d, 0x7c, 0x6c,
+ 0xfc, 0x0d, 0x7c, 0x64, 0xfe, 0x81, 0x04, 0x14, 0xfe, 0xfb, 0x58, 0x0e, 0xfb, 0x0c, 0x85, 0x00,
+ 0x4f, 0xa8, 0xf9, 0xc0, 0xfe, 0x8d, 0x7c, 0x80, 0xfe, 0x8e, 0x7f, 0x40, 0xfe, 0x8d, 0x7c, 0x78,
+ 0xfe, 0x8e, 0x7c, 0x40, 0xf0, 0x0d, 0x7c, 0x68, 0xfe, 0x8d, 0x80, 0x90, 0xfe, 0xfb, 0x58, 0x0e,
+ 0x8a, 0xfa, 0x00, 0x00, 0xcf, 0xfc, 0xd5, 0x00, 0x20, 0x5a, 0x00, 0x00, 0xee, 0x02, 0x54, 0x15,
+ 0x05, 0x7d, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x64, 0xff, 0xf8, 0xce, 0x64, 0xd2, 0x00, 0x7f, 0xf5, 0x00, 0x10,
+ 0x7f, 0x71, 0x00, 0x0d, 0xcf, 0xfc, 0xf5, 0x00, 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00,
+ 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x00, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x56, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xf0, 0xef, 0x68, 0x13,
+ 0x9a, 0xee, 0x00, 0x14, 0xfb, 0xef, 0x68, 0x12, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xfe, 0x86, 0xad, 0xc0,
+ 0x9e, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfb, 0x6f, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xdd, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08,
+ 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x54, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0x0c, 0x80, 0x90, 0x4f, 0x29, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c,
+ 0xfd, 0x9c, 0x46, 0x30, 0xce, 0xa8, 0xfc, 0x00, 0x7f, 0x78, 0xff, 0xe7, 0xce, 0xe8, 0xe8, 0x00,
+ 0x0f, 0x78, 0x07, 0x48, 0x89, 0xf6, 0x00, 0x10, 0xfb, 0x7b, 0x58, 0x00, 0x0e, 0x6c, 0x00, 0x10,
+ 0x4e, 0x70, 0xbf, 0xff, 0x8f, 0xea, 0x00, 0x24, 0xff, 0x73, 0x58, 0x0f, 0x8e, 0xea, 0x00, 0x3c,
+ 0xfc, 0xef, 0x18, 0x0a, 0x8b, 0xee, 0x00, 0x04, 0xfa, 0x82, 0x00, 0x00, 0xfa, 0xef, 0x68, 0x0f,
+ 0xce, 0xf4, 0xf8, 0x00, 0xfe, 0x1d, 0x46, 0x30, 0xcf, 0xfc, 0xc8, 0x00, 0x9f, 0xea, 0x00, 0x24,
+ 0xfc, 0x0c, 0x85, 0x00, 0x4f, 0xa8, 0xfd, 0xc0, 0x8a, 0x6e, 0x00, 0x00, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xc0, 0x62, 0xaa, 0x00, 0xee, 0x02, 0x55, 0xfd, 0x05, 0x7d, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8,
+ 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9c, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02,
+ 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58,
+ 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x83, 0x2a, 0x60, 0x4d, 0x5c, 0xff, 0xf8,
+ 0xce, 0x5c, 0xd2, 0x00, 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xcd, 0x00, 0xfd, 0x88, 0xe6, 0xd8,
+ 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x5e, 0xf5, 0x80, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x20, 0x52, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00,
+ 0xce, 0x64, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xec, 0xe8, 0x00, 0x9a, 0x6e, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13,
+ 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9a, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfc, 0x6f, 0x28, 0x02, 0x9a, 0x82, 0xff, 0x00,
+ 0x7f, 0xd9, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xac, 0xe6, 0xf0, 0x02,
+ 0xfc, 0x8d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x56, 0xd4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x82, 0x00, 0x0c,
+ 0xfd, 0x9c, 0x46, 0x30, 0xcf, 0x28, 0xfc, 0x00, 0xfd, 0x0e, 0x7c, 0x40, 0x4e, 0xa9, 0x1e, 0x00,
+ 0x7e, 0xf4, 0xff, 0xe7, 0xcf, 0x78, 0xd0, 0x00, 0x89, 0xfa, 0x00, 0x10, 0x0f, 0xf4, 0x07, 0x48,
+ 0xfb, 0x7f, 0x58, 0x00, 0x0e, 0x6c, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0xf3, 0x58, 0x0f,
+ 0xff, 0x0c, 0x80, 0x90, 0xff, 0xef, 0x58, 0x0d, 0xfc, 0x6f, 0x18, 0x0a, 0x8b, 0xee, 0x00, 0x04,
+ 0xf0, 0x6f, 0x68, 0x0f, 0x7e, 0xf5, 0x00, 0x10, 0xfe, 0x1d, 0x46, 0x30, 0xfe, 0x06, 0x37, 0x9c,
+ 0x9d, 0x7a, 0x00, 0x38, 0x9e, 0x7a, 0x00, 0x34, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0x0e, 0x7f, 0x40,
+ 0xff, 0x8d, 0x7c, 0x60, 0xfd, 0x0d, 0x80, 0x90, 0xfc, 0x0d, 0x7c, 0x64, 0xf0, 0x0d, 0x7c, 0x68,
+ 0xff, 0x0d, 0x7c, 0x78, 0xfa, 0x8c, 0x85, 0x00, 0x4f, 0xa8, 0xf9, 0xc0, 0x8a, 0x6e, 0x00, 0x00,
+ 0xcf, 0xfc, 0xcd, 0x00, 0x05, 0x7d, 0x02, 0x20, 0x20, 0x56, 0x00, 0x00, 0xee, 0x02, 0x57, 0xf5,
+ 0xfc, 0x82, 0x00, 0x00, 0xff, 0x88, 0xe6, 0xd8, 0x0e, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00,
+ 0x9e, 0x02, 0xfe, 0x58, 0x9a, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0x01, 0x10, 0x00,
+ 0x0f, 0x78, 0x00, 0x10, 0x9f, 0x02, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xfc, 0x83, 0x2a, 0x60, 0x4d, 0x5c, 0xff, 0xf8, 0xce, 0x5c, 0xd2, 0x00, 0x7f, 0xf1, 0x00, 0x0d,
+ 0xcf, 0xfc, 0xc5, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x59, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x00, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x20, 0x52, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0x9a, 0x6e, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28,
+ 0x9e, 0x02, 0xff, 0xb0, 0xfa, 0xef, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd9, 0x00, 0x02,
+ 0x99, 0xfe, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x58, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x82, 0x00, 0x0c, 0xfd, 0x9c, 0x46, 0x30,
+ 0xcf, 0x28, 0xfc, 0x00, 0xfd, 0x0e, 0x7c, 0xc0, 0x4e, 0xa9, 0x1e, 0x00, 0x7e, 0xf4, 0xff, 0xe7,
+ 0xcf, 0x78, 0xd0, 0x00, 0x89, 0xfa, 0x00, 0x10, 0x0f, 0xf4, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00,
+ 0x0e, 0x6c, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0xf3, 0x58, 0x0f, 0xff, 0x0c, 0x80, 0x90,
+ 0xff, 0xef, 0x58, 0x0d, 0xfc, 0x6f, 0x18, 0x0a, 0x8b, 0xee, 0x00, 0x04, 0xf0, 0x6f, 0x68, 0x0f,
+ 0x7e, 0xf5, 0x00, 0x10, 0xfe, 0x1d, 0x46, 0x30, 0xfe, 0x06, 0x37, 0xf4, 0x9d, 0x7a, 0x00, 0x38,
+ 0x9e, 0x7a, 0x00, 0x34, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0x0e, 0x7f, 0x40, 0xff, 0x8d, 0x7c, 0xe0,
+ 0xfd, 0x0d, 0x80, 0x90, 0xfc, 0x0d, 0x7c, 0xe4, 0xf0, 0x0d, 0x7c, 0xe8, 0xff, 0x0d, 0x7c, 0xf8,
+ 0xfa, 0x8c, 0x85, 0x00, 0x4f, 0xa8, 0xf5, 0xc0, 0x8a, 0x6e, 0x00, 0x00, 0xcf, 0xfc, 0xcd, 0x00,
+ 0x05, 0x7d, 0x02, 0x20, 0x20, 0x56, 0x00, 0x00, 0xee, 0x02, 0x59, 0xf1, 0xfc, 0x82, 0x00, 0x00,
+ 0xff, 0x88, 0xe6, 0xd8, 0x0e, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0x9a, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8,
+ 0xff, 0xfb, 0x28, 0x02, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0x01, 0x10, 0x00, 0x0f, 0x78, 0x00, 0x10,
+ 0x9f, 0x02, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x83, 0x2a, 0x60,
+ 0x4d, 0x5c, 0xff, 0xf8, 0xce, 0x5c, 0xd2, 0x00, 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xc5, 0x00,
+ 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x05, 0xf2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x20, 0x52, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x9a, 0x6e, 0x00, 0x14,
+ 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0,
+ 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0,
+ 0xfa, 0xef, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd9, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08,
+ 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x5a, 0xcc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x82, 0x00, 0x0c, 0xfd, 0x9c, 0x46, 0x30, 0xcf, 0x28, 0xfc, 0x00,
+ 0xfd, 0x0e, 0x7d, 0x40, 0x4e, 0xa9, 0x1e, 0x00, 0x7e, 0xf4, 0xff, 0xe7, 0xcf, 0x78, 0xd0, 0x00,
+ 0x89, 0xfa, 0x00, 0x10, 0x0f, 0xf4, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00, 0x0e, 0x6c, 0x00, 0x10,
+ 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0xf3, 0x58, 0x0f, 0xff, 0x0c, 0x80, 0x90, 0xff, 0xef, 0x58, 0x0d,
+ 0xfc, 0x6f, 0x18, 0x0a, 0x8b, 0xee, 0x00, 0x04, 0xf0, 0x6f, 0x68, 0x0f, 0x7e, 0xf5, 0x00, 0x10,
+ 0xfe, 0x1d, 0x46, 0x30, 0xfe, 0x06, 0x38, 0x4c, 0x9d, 0x7a, 0x00, 0x38, 0x9e, 0x7a, 0x00, 0x34,
+ 0xcf, 0xfc, 0xed, 0x00, 0xff, 0x0e, 0x7f, 0x40, 0xff, 0x8d, 0x7d, 0x60, 0xfd, 0x0d, 0x80, 0x90,
+ 0xfc, 0x0d, 0x7d, 0x64, 0xf0, 0x0d, 0x7d, 0x68, 0xff, 0x0d, 0x7d, 0x78, 0xfa, 0x8c, 0x85, 0x00,
+ 0x4f, 0xa8, 0xed, 0xc0, 0x8a, 0x6e, 0x00, 0x00, 0xcf, 0xfc, 0xcd, 0x00, 0x05, 0x7d, 0x02, 0x20,
+ 0x20, 0x56, 0x00, 0x00, 0xee, 0x02, 0x5b, 0xed, 0xfc, 0x82, 0x00, 0x00, 0xff, 0x88, 0xe6, 0xd8,
+ 0x0e, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0x9a, 0x82, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02,
+ 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0x01, 0x10, 0x00, 0x0f, 0x78, 0x00, 0x10, 0x9f, 0x02, 0xfe, 0x58,
+ 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x83, 0x2a, 0x60, 0x4d, 0x5c, 0xff, 0xf8,
+ 0xce, 0x5c, 0xd2, 0x00, 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xc5, 0x00, 0xfd, 0x88, 0xe6, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x0b, 0xe2,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x20, 0x52, 0x00, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6,
+ 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8,
+ 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x9a, 0x6e, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12,
+ 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xfa, 0xef, 0x28, 0x02,
+ 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd9, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0,
+ 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x5c, 0xc8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x82, 0x00, 0x0c, 0xfd, 0x9c, 0x46, 0x30, 0xcf, 0x28, 0xfc, 0x00, 0xfd, 0x0e, 0x7d, 0xc0,
+ 0x4e, 0xa9, 0x1e, 0x00, 0x7e, 0xf4, 0xff, 0xe7, 0xcf, 0x78, 0xd0, 0x00, 0x89, 0xfa, 0x00, 0x10,
+ 0x0f, 0xf4, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00, 0x0e, 0x6c, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff,
+ 0xfc, 0xf3, 0x58, 0x0f, 0xff, 0x0c, 0x80, 0x90, 0xff, 0xef, 0x58, 0x0d, 0xfc, 0x6f, 0x18, 0x0a,
+ 0x8b, 0xee, 0x00, 0x04, 0xf0, 0x6f, 0x68, 0x0f, 0x7e, 0xf5, 0x00, 0x10, 0xfe, 0x1d, 0x46, 0x30,
+ 0xfe, 0x06, 0x38, 0xa4, 0x9d, 0x7a, 0x00, 0x38, 0x9e, 0x7a, 0x00, 0x34, 0xcf, 0xfc, 0xed, 0x00,
+ 0xff, 0x0e, 0x7f, 0x40, 0xff, 0x8d, 0x7d, 0xe0, 0xfd, 0x0d, 0x80, 0x90, 0xfc, 0x0d, 0x7d, 0xe4,
+ 0xf0, 0x0d, 0x7d, 0xe8, 0xff, 0x0d, 0x7d, 0xf8, 0xfa, 0x8c, 0x85, 0x00, 0x4f, 0xa8, 0xdd, 0xc0,
+ 0x8a, 0x6e, 0x00, 0x00, 0xcf, 0xfc, 0xcd, 0x00, 0x05, 0x7d, 0x02, 0x20, 0x20, 0x56, 0x00, 0x00,
+ 0xee, 0x02, 0x5d, 0xe9, 0xfc, 0x82, 0x00, 0x00, 0xff, 0x88, 0xe6, 0xd8, 0x0e, 0x01, 0x80, 0x00,
+ 0xff, 0xff, 0x18, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0x9a, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0x01, 0x10, 0x00, 0x0f, 0x78, 0x00, 0x10, 0x9f, 0x02, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0x83, 0x2a, 0x60, 0x4d, 0x5c, 0xff, 0xf8, 0xce, 0x5c, 0xd2, 0x00,
+ 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xc5, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x11, 0xd2, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x20, 0x52, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00,
+ 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xec, 0xe8, 0x00, 0x9a, 0x6e, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13,
+ 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xfa, 0xef, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00,
+ 0x7f, 0xd9, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02,
+ 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x5e, 0xc4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x82, 0x00, 0x0c,
+ 0xfd, 0x9c, 0x46, 0x30, 0xcf, 0x28, 0xfc, 0x00, 0xfd, 0x0e, 0x7e, 0x40, 0x4e, 0xa9, 0x1e, 0x00,
+ 0x7e, 0xf4, 0xff, 0xe7, 0xcf, 0x78, 0xd0, 0x00, 0x89, 0xfa, 0x00, 0x10, 0x0f, 0xf4, 0x07, 0x48,
+ 0xfb, 0x7f, 0x58, 0x00, 0x0e, 0x6c, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0xf3, 0x58, 0x0f,
+ 0xff, 0x0c, 0x80, 0x90, 0xff, 0xef, 0x58, 0x0d, 0xfc, 0x6f, 0x18, 0x0a, 0x8b, 0xee, 0x00, 0x04,
+ 0xf0, 0x6f, 0x68, 0x0f, 0x7e, 0xf5, 0x00, 0x10, 0xfe, 0x1d, 0x46, 0x30, 0xfe, 0x06, 0x38, 0xfc,
+ 0x9d, 0x7a, 0x00, 0x38, 0x9e, 0x7a, 0x00, 0x34, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0x0e, 0x7f, 0x40,
+ 0xff, 0x8d, 0x7e, 0x60, 0xfd, 0x0d, 0x80, 0x90, 0xfc, 0x0d, 0x7e, 0x64, 0xf0, 0x0d, 0x7e, 0x68,
+ 0xff, 0x0d, 0x7e, 0x78, 0xfa, 0x8c, 0x85, 0x00, 0x4f, 0xa8, 0xbd, 0xc0, 0x8a, 0x6e, 0x00, 0x00,
+ 0xcf, 0xfc, 0xcd, 0x00, 0x05, 0x7d, 0x02, 0x20, 0x20, 0x56, 0x00, 0x00, 0xee, 0x02, 0x5f, 0xe5,
+ 0xfc, 0x82, 0x00, 0x00, 0xff, 0x88, 0xe6, 0xd8, 0x0e, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00,
+ 0x9e, 0x02, 0xfe, 0x58, 0x9a, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0x01, 0x10, 0x00,
+ 0x0f, 0x78, 0x00, 0x10, 0x9f, 0x02, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xfc, 0x83, 0x2a, 0x60, 0x4d, 0x5c, 0xff, 0xf8, 0xce, 0x5c, 0xd2, 0x00, 0x7f, 0xf1, 0x00, 0x0d,
+ 0xcf, 0xfc, 0xc5, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x59, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x36, 0x8a, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x20, 0x52, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0x9a, 0x6e, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28,
+ 0x9e, 0x02, 0xff, 0xb0, 0xfa, 0xef, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd9, 0x00, 0x02,
+ 0x99, 0xfe, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x60, 0xc0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x82, 0x00, 0x0c, 0xfd, 0x9c, 0x46, 0x30,
+ 0xcf, 0x28, 0xfc, 0x00, 0xfd, 0x0e, 0x7e, 0xc0, 0x4e, 0xa9, 0x1e, 0x00, 0x7e, 0xf4, 0xff, 0xe7,
+ 0xcf, 0x78, 0xd0, 0x00, 0x89, 0xfa, 0x00, 0x10, 0x0f, 0xf4, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00,
+ 0x0e, 0x6c, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfc, 0xf3, 0x58, 0x0f, 0xff, 0x0c, 0x80, 0x90,
+ 0xff, 0xef, 0x58, 0x0d, 0xfc, 0x6f, 0x18, 0x0a, 0x8b, 0xee, 0x00, 0x04, 0xf0, 0x6f, 0x68, 0x0f,
+ 0x7e, 0xf5, 0x00, 0x10, 0xfe, 0x1d, 0x46, 0x30, 0xfe, 0x06, 0x39, 0x54, 0x9d, 0x7a, 0x00, 0x38,
+ 0x9e, 0x7a, 0x00, 0x34, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0x0e, 0x7f, 0x40, 0xff, 0x8d, 0x7e, 0xe0,
+ 0xfd, 0x0d, 0x80, 0x90, 0xfc, 0x0d, 0x7e, 0xe4, 0xf0, 0x0d, 0x7e, 0xe8, 0xff, 0x0d, 0x7e, 0xf8,
+ 0xfa, 0x8c, 0x85, 0x00, 0x4f, 0xa8, 0x7d, 0xc0, 0x8a, 0x6e, 0x00, 0x00, 0xcf, 0xfc, 0xcd, 0x00,
+ 0x05, 0x7d, 0x02, 0x20, 0x20, 0x56, 0x00, 0x00, 0xee, 0x02, 0x61, 0xe1, 0xfc, 0x82, 0x00, 0x00,
+ 0xff, 0x88, 0xe6, 0xd8, 0x0e, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0x9a, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8,
+ 0xff, 0xfb, 0x28, 0x02, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0x01, 0x10, 0x00, 0x0f, 0x78, 0x00, 0x10,
+ 0x9f, 0x02, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x83, 0x2a, 0x60,
+ 0x4d, 0x5c, 0xff, 0xf8, 0xce, 0x5c, 0xd2, 0x00, 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xc5, 0x00,
+ 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x5b, 0x42, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x20, 0x52, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x9a, 0x6e, 0x00, 0x14,
+ 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0,
+ 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0,
+ 0xfa, 0xef, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd9, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08,
+ 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x62, 0xbc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x4e, 0xa9, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c, 0xfd, 0x9c, 0x46, 0x30,
+ 0xcf, 0x28, 0xfc, 0x00, 0x7e, 0xf4, 0xff, 0xe7, 0x0f, 0xf4, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00,
+ 0xfd, 0x0e, 0x7c, 0x40, 0x0e, 0x6c, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xcf, 0x78, 0xd0, 0x00,
+ 0xfc, 0xf3, 0x58, 0x0f, 0x89, 0xfa, 0x00, 0x10, 0xff, 0xef, 0x58, 0x0d, 0xfc, 0x6f, 0x18, 0x0a,
+ 0x8b, 0xee, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x10, 0xf0, 0x6f, 0x68, 0x0f, 0xcf, 0xfc, 0xed, 0x00,
+ 0xff, 0x8d, 0x7c, 0x60, 0xff, 0x8e, 0x7f, 0x40, 0xff, 0x06, 0x37, 0x9c, 0xff, 0x8d, 0x7c, 0x78,
+ 0xfe, 0x1d, 0x46, 0x30, 0xfd, 0x0d, 0x80, 0x90, 0xfc, 0x0d, 0x7c, 0x64, 0xff, 0x01, 0x04, 0x14,
+ 0xf0, 0x0d, 0x7c, 0x68, 0xfa, 0x8c, 0x85, 0x00, 0x4f, 0xa8, 0xf9, 0xc0, 0x8a, 0x6e, 0x00, 0x00,
+ 0xcf, 0xfc, 0xcd, 0x00, 0x05, 0x7d, 0x02, 0x20, 0x20, 0x56, 0x00, 0x00, 0xee, 0x02, 0x63, 0xd5,
+ 0xfc, 0x82, 0x00, 0x00, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x9a, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xfc, 0x83, 0x2a, 0x60, 0x4d, 0x5c, 0xff, 0xf8, 0xce, 0x5c, 0xd2, 0x00, 0x7f, 0xf1, 0x00, 0x0d,
+ 0xcf, 0xfc, 0xc5, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x59, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x00, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x20, 0x52, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0x9a, 0x6e, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28,
+ 0x9f, 0x02, 0xff, 0xb0, 0xfa, 0xef, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd9, 0x00, 0x02,
+ 0x99, 0xfe, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x64, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x4e, 0xa9, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c,
+ 0xfd, 0x9c, 0x46, 0x30, 0xcf, 0x28, 0xfc, 0x00, 0x7e, 0xf4, 0xff, 0xe7, 0x0f, 0xf4, 0x07, 0x48,
+ 0xfb, 0x7f, 0x58, 0x00, 0xfd, 0x0e, 0x7d, 0xc0, 0x0e, 0x6c, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff,
+ 0xcf, 0x78, 0xd0, 0x00, 0xfc, 0xf3, 0x58, 0x0f, 0x89, 0xfa, 0x00, 0x10, 0xff, 0xef, 0x58, 0x0d,
+ 0xfc, 0x6f, 0x18, 0x0a, 0x8b, 0xee, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x10, 0xf0, 0x6f, 0x68, 0x0f,
+ 0xcf, 0xfc, 0xed, 0x00, 0xff, 0x8d, 0x7d, 0xe0, 0xff, 0x8e, 0x7f, 0x40, 0xff, 0x06, 0x38, 0xa4,
+ 0xff, 0x8d, 0x7d, 0xf8, 0xfe, 0x1d, 0x46, 0x30, 0xfd, 0x0d, 0x80, 0x90, 0xfc, 0x0d, 0x7d, 0xe4,
+ 0xff, 0x01, 0x04, 0x14, 0xf0, 0x0d, 0x7d, 0xe8, 0xfa, 0x8c, 0x85, 0x00, 0x4f, 0xa8, 0xdd, 0xc0,
+ 0x8a, 0x6e, 0x00, 0x00, 0xcf, 0xfc, 0xcd, 0x00, 0x05, 0x7d, 0x02, 0x20, 0x20, 0x56, 0x00, 0x00,
+ 0xee, 0x02, 0x65, 0xc9, 0xfc, 0x82, 0x00, 0x00, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00,
+ 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9a, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0x83, 0x2a, 0x60, 0x4d, 0x5c, 0xff, 0xf8, 0xce, 0x5c, 0xd2, 0x00,
+ 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xc5, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x11, 0xd2, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x20, 0x52, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00,
+ 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xec, 0xe8, 0x00, 0x9a, 0x6e, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13,
+ 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfa, 0xef, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00,
+ 0x7f, 0xd9, 0x00, 0x02, 0x99, 0xfe, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02,
+ 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x66, 0xa4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x0c, 0x80, 0x90,
+ 0xfd, 0x9c, 0x46, 0x30, 0x4e, 0xa9, 0x1e, 0x00, 0x8f, 0x6a, 0x00, 0x24, 0x8b, 0x6a, 0x00, 0x3c,
+ 0xfc, 0x6f, 0x18, 0x0a, 0xfc, 0xef, 0x18, 0x08, 0xff, 0x82, 0x00, 0x04, 0x7e, 0xf4, 0xff, 0xe7,
+ 0xce, 0x28, 0xfc, 0x00, 0x0e, 0xf4, 0x07, 0x48, 0xcb, 0x58, 0xf0, 0x00, 0xfa, 0xf7, 0x58, 0x00,
+ 0x8b, 0xee, 0x00, 0x04, 0xcf, 0x78, 0xc0, 0x00, 0xce, 0x68, 0xe0, 0x00, 0xcf, 0x78, 0xca, 0x00,
+ 0x89, 0x72, 0x00, 0x10, 0xcc, 0x60, 0xf2, 0x00, 0x4e, 0xa8, 0xff, 0xfb, 0xcf, 0xdc, 0xc0, 0x00,
+ 0x9f, 0xee, 0x00, 0x04, 0xc0, 0x7a, 0xca, 0x00, 0xff, 0x6f, 0x28, 0x0a, 0x5e, 0xf4, 0x00, 0x02,
+ 0xee, 0x02, 0x67, 0x5c, 0xfa, 0x02, 0x00, 0x00, 0x2e, 0xf4, 0x00, 0x10, 0x9c, 0xea, 0x00, 0x24,
+ 0xfc, 0x8c, 0x85, 0x00, 0x89, 0xee, 0x00, 0x00, 0xc5, 0x74, 0x00, 0x00, 0x20, 0x66, 0x00, 0x00,
+ 0xee, 0x02, 0x67, 0xb9, 0x05, 0x75, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00,
+ 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9c, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xfa, 0x03, 0x2a, 0x60, 0x4d, 0x5c, 0xff, 0xf8, 0xce, 0x5c, 0xd2, 0x00,
+ 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xc5, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x7f, 0x55, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x5e, 0xd9, 0x80, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x20, 0x4e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0x99, 0xee, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9a, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28,
+ 0x9f, 0x02, 0xff, 0xb0, 0xfc, 0xef, 0x28, 0x02, 0x9a, 0x02, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02,
+ 0x99, 0x7e, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x68, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x9c, 0x46, 0x30, 0xff, 0x82, 0x00, 0x04,
+ 0xcf, 0x28, 0xfc, 0x00, 0xfb, 0x8e, 0x7c, 0x40, 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xb8, 0x00,
+ 0xfc, 0x6f, 0x18, 0x0a, 0x8a, 0x7a, 0x00, 0x10, 0xfd, 0x6f, 0x18, 0x08, 0x7b, 0x74, 0xff, 0xe7,
+ 0x0f, 0xd8, 0x07, 0x48, 0xfa, 0xff, 0x58, 0x00, 0x8e, 0x6e, 0x00, 0x04, 0xcf, 0x60, 0xd2, 0x00,
+ 0xfc, 0x8c, 0x80, 0x90, 0xcc, 0x60, 0xf2, 0x00, 0x4e, 0xa8, 0xfb, 0xfb, 0xcf, 0xf0, 0xc0, 0x00,
+ 0x9f, 0xee, 0x00, 0x04, 0xc0, 0x7a, 0xd2, 0x00, 0xff, 0x6f, 0x28, 0x0a, 0xee, 0x02, 0x69, 0x38,
+ 0x5e, 0xf4, 0x00, 0x02, 0x2e, 0xf4, 0x00, 0x10, 0x7f, 0xd9, 0x00, 0x10, 0x5f, 0xfc, 0x00, 0x01,
+ 0xff, 0x06, 0x37, 0x9c, 0x9b, 0xe6, 0x00, 0x38, 0x9f, 0x66, 0x00, 0x34, 0xff, 0x8d, 0x7c, 0x60,
+ 0xfb, 0x8d, 0x80, 0x90, 0xff, 0x8e, 0x7f, 0x40, 0xfd, 0x0d, 0x7c, 0x64, 0xf0, 0x0d, 0x7c, 0x68,
+ 0xff, 0x8d, 0x7c, 0x78, 0xfb, 0x8c, 0x85, 0x00, 0x8b, 0x6e, 0x00, 0x00, 0xc5, 0x74, 0x00, 0x00,
+ 0x20, 0x5e, 0x00, 0x00, 0xee, 0x02, 0x69, 0xbd, 0x05, 0x75, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8,
+ 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02,
+ 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58,
+ 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x70, 0xff, 0xf8,
+ 0xce, 0x70, 0xd2, 0x00, 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00,
+ 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x55, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x00, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x5a, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x9b, 0x6e, 0x00, 0x14,
+ 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0,
+ 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfb, 0xef, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08,
+ 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x6a, 0x9c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0x9c, 0x46, 0x30, 0xff, 0x82, 0x00, 0x04, 0xcf, 0x28, 0xfc, 0x00,
+ 0xfb, 0x8e, 0x7c, 0xc0, 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xb8, 0x00, 0xfc, 0x6f, 0x18, 0x0a,
+ 0x8a, 0x7a, 0x00, 0x10, 0xfd, 0x6f, 0x18, 0x08, 0x7b, 0x74, 0xff, 0xe7, 0x0f, 0xd8, 0x07, 0x48,
+ 0xfa, 0xff, 0x58, 0x00, 0x8e, 0x6e, 0x00, 0x04, 0xcf, 0x60, 0xd2, 0x00, 0xfc, 0x8c, 0x80, 0x90,
+ 0xcc, 0x60, 0xf2, 0x00, 0x4e, 0xa8, 0xf7, 0xfb, 0xcf, 0xf0, 0xc0, 0x00, 0x9f, 0xee, 0x00, 0x04,
+ 0xc0, 0x7a, 0xd2, 0x00, 0xff, 0x6f, 0x28, 0x0a, 0xee, 0x02, 0x6b, 0x44, 0x5e, 0xf4, 0x00, 0x02,
+ 0x2e, 0xf4, 0x00, 0x10, 0x7f, 0xd9, 0x00, 0x10, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x06, 0x37, 0xf4,
+ 0x9b, 0xe6, 0x00, 0x38, 0x9f, 0x66, 0x00, 0x34, 0xff, 0x8d, 0x7c, 0xe0, 0xfb, 0x8d, 0x80, 0x90,
+ 0xff, 0x8e, 0x7f, 0x40, 0xfd, 0x0d, 0x7c, 0xe4, 0xf0, 0x0d, 0x7c, 0xe8, 0xff, 0x8d, 0x7c, 0xf8,
+ 0xfb, 0x8c, 0x85, 0x00, 0x8b, 0x6e, 0x00, 0x00, 0xc5, 0x74, 0x00, 0x00, 0x20, 0x5e, 0x00, 0x00,
+ 0xee, 0x02, 0x6b, 0xc9, 0x05, 0x75, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00,
+ 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x70, 0xff, 0xf8, 0xce, 0x70, 0xd2, 0x00,
+ 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x55, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x05, 0xf2,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5a, 0xca, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6,
+ 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8,
+ 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x9b, 0x6e, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12,
+ 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfb, 0xef, 0x28, 0x02,
+ 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0,
+ 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x6c, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0x9c, 0x46, 0x30, 0xff, 0x82, 0x00, 0x04, 0xcf, 0x28, 0xfc, 0x00, 0xfb, 0x8e, 0x7d, 0x40,
+ 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xb8, 0x00, 0xfc, 0x6f, 0x18, 0x0a, 0x8a, 0x7a, 0x00, 0x10,
+ 0xfd, 0x6f, 0x18, 0x08, 0x7b, 0x74, 0xff, 0xe7, 0x0f, 0xd8, 0x07, 0x48, 0xfa, 0xff, 0x58, 0x00,
+ 0x8e, 0x6e, 0x00, 0x04, 0xcf, 0x60, 0xd2, 0x00, 0xfc, 0x8c, 0x80, 0x90, 0xcc, 0x60, 0xf2, 0x00,
+ 0x4e, 0xa8, 0xef, 0xfb, 0xcf, 0xf0, 0xc0, 0x00, 0x9f, 0xee, 0x00, 0x04, 0xc0, 0x7a, 0xd2, 0x00,
+ 0xff, 0x6f, 0x28, 0x0a, 0xee, 0x02, 0x6d, 0x50, 0x5e, 0xf4, 0x00, 0x02, 0x2e, 0xf4, 0x00, 0x10,
+ 0x7f, 0xd9, 0x00, 0x10, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x06, 0x38, 0x4c, 0x9b, 0xe6, 0x00, 0x38,
+ 0x9f, 0x66, 0x00, 0x34, 0xff, 0x8d, 0x7d, 0x60, 0xfb, 0x8d, 0x80, 0x90, 0xff, 0x8e, 0x7f, 0x40,
+ 0xfd, 0x0d, 0x7d, 0x64, 0xf0, 0x0d, 0x7d, 0x68, 0xff, 0x8d, 0x7d, 0x78, 0xfb, 0x8c, 0x85, 0x00,
+ 0x8b, 0x6e, 0x00, 0x00, 0xc5, 0x74, 0x00, 0x00, 0x20, 0x5e, 0x00, 0x00, 0xee, 0x02, 0x6d, 0xd5,
+ 0x05, 0x75, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x70, 0xff, 0xf8, 0xce, 0x70, 0xd2, 0x00, 0x7f, 0xf1, 0x00, 0x0d,
+ 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0x55, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x0b, 0xe2, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5a, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00,
+ 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xec, 0xe8, 0x00, 0x9b, 0x6e, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13,
+ 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfb, 0xef, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00,
+ 0x7f, 0xd5, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02,
+ 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x6e, 0xb4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x9c, 0x46, 0x30,
+ 0xff, 0x82, 0x00, 0x04, 0xcf, 0x28, 0xfc, 0x00, 0xfb, 0x8e, 0x7d, 0xc0, 0x4e, 0xa9, 0x1e, 0x00,
+ 0xcf, 0x78, 0xb8, 0x00, 0xfc, 0x6f, 0x18, 0x0a, 0x8a, 0x7a, 0x00, 0x10, 0xfd, 0x6f, 0x18, 0x08,
+ 0x7b, 0x74, 0xff, 0xe7, 0x0f, 0xd8, 0x07, 0x48, 0xfa, 0xff, 0x58, 0x00, 0x8e, 0x6e, 0x00, 0x04,
+ 0xcf, 0x60, 0xd2, 0x00, 0xfc, 0x8c, 0x80, 0x90, 0xcc, 0x60, 0xf2, 0x00, 0x4e, 0xa8, 0xdf, 0xfb,
+ 0xcf, 0xf0, 0xc0, 0x00, 0x9f, 0xee, 0x00, 0x04, 0xc0, 0x7a, 0xd2, 0x00, 0xff, 0x6f, 0x28, 0x0a,
+ 0xee, 0x02, 0x6f, 0x5c, 0x5e, 0xf4, 0x00, 0x02, 0x2e, 0xf4, 0x00, 0x10, 0x7f, 0xd9, 0x00, 0x10,
+ 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x06, 0x38, 0xa4, 0x9b, 0xe6, 0x00, 0x38, 0x9f, 0x66, 0x00, 0x34,
+ 0xff, 0x8d, 0x7d, 0xe0, 0xfb, 0x8d, 0x80, 0x90, 0xff, 0x8e, 0x7f, 0x40, 0xfd, 0x0d, 0x7d, 0xe4,
+ 0xf0, 0x0d, 0x7d, 0xe8, 0xff, 0x8d, 0x7d, 0xf8, 0xfb, 0x8c, 0x85, 0x00, 0x8b, 0x6e, 0x00, 0x00,
+ 0xc5, 0x74, 0x00, 0x00, 0x20, 0x5e, 0x00, 0x00, 0xee, 0x02, 0x6f, 0xe1, 0x05, 0x75, 0x02, 0x20,
+ 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x9b, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8,
+ 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10,
+ 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60,
+ 0x4d, 0x70, 0xff, 0xf8, 0xce, 0x70, 0xd2, 0x00, 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xc5, 0x00,
+ 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x55, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x11, 0xd2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5a, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0x9b, 0x6e, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28,
+ 0x9f, 0x02, 0xff, 0xb0, 0xfb, 0xef, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02,
+ 0x9a, 0x7e, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x70, 0xc0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x9c, 0x46, 0x30, 0xff, 0x82, 0x00, 0x04,
+ 0xcf, 0x28, 0xfc, 0x00, 0xfb, 0x8e, 0x7e, 0x40, 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xb8, 0x00,
+ 0xfc, 0x6f, 0x18, 0x0a, 0x8a, 0x7a, 0x00, 0x10, 0xfd, 0x6f, 0x18, 0x08, 0x7b, 0x74, 0xff, 0xe7,
+ 0x0f, 0xd8, 0x07, 0x48, 0xfa, 0xff, 0x58, 0x00, 0x8e, 0x6e, 0x00, 0x04, 0xcf, 0x60, 0xd2, 0x00,
+ 0xfc, 0x8c, 0x80, 0x90, 0xcc, 0x60, 0xf2, 0x00, 0x4e, 0xa8, 0xbf, 0xfb, 0xcf, 0xf0, 0xc0, 0x00,
+ 0x9f, 0xee, 0x00, 0x04, 0xc0, 0x7a, 0xd2, 0x00, 0xff, 0x6f, 0x28, 0x0a, 0xee, 0x02, 0x71, 0x68,
+ 0x5e, 0xf4, 0x00, 0x02, 0x2e, 0xf4, 0x00, 0x10, 0x7f, 0xd9, 0x00, 0x10, 0x5f, 0xfc, 0x00, 0x01,
+ 0xff, 0x06, 0x38, 0xfc, 0x9b, 0xe6, 0x00, 0x38, 0x9f, 0x66, 0x00, 0x34, 0xff, 0x8d, 0x7e, 0x60,
+ 0xfb, 0x8d, 0x80, 0x90, 0xff, 0x8e, 0x7f, 0x40, 0xfd, 0x0d, 0x7e, 0x64, 0xf0, 0x0d, 0x7e, 0x68,
+ 0xff, 0x8d, 0x7e, 0x78, 0xfb, 0x8c, 0x85, 0x00, 0x8b, 0x6e, 0x00, 0x00, 0xc5, 0x74, 0x00, 0x00,
+ 0x20, 0x5e, 0x00, 0x00, 0xee, 0x02, 0x71, 0xed, 0x05, 0x75, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8,
+ 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02,
+ 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58,
+ 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x70, 0xff, 0xf8,
+ 0xce, 0x70, 0xd2, 0x00, 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00,
+ 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x55, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x36, 0x8a, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x5a, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x9b, 0x6e, 0x00, 0x14,
+ 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0,
+ 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfb, 0xef, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08,
+ 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x72, 0xcc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0x9c, 0x46, 0x30, 0xff, 0x82, 0x00, 0x04, 0xcf, 0x28, 0xfc, 0x00,
+ 0xfb, 0x8e, 0x7e, 0xc0, 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xb8, 0x00, 0xfc, 0x6f, 0x18, 0x0a,
+ 0x8a, 0x7a, 0x00, 0x10, 0xfd, 0x6f, 0x18, 0x08, 0x7b, 0x74, 0xff, 0xe7, 0x0f, 0xd8, 0x07, 0x48,
+ 0xfa, 0xff, 0x58, 0x00, 0x8e, 0x6e, 0x00, 0x04, 0xcf, 0x60, 0xd2, 0x00, 0xfc, 0x8c, 0x80, 0x90,
+ 0xcc, 0x60, 0xf2, 0x00, 0x4e, 0xa8, 0x7f, 0xfb, 0xcf, 0xf0, 0xc0, 0x00, 0x9f, 0xee, 0x00, 0x04,
+ 0xc0, 0x7a, 0xd2, 0x00, 0xff, 0x6f, 0x28, 0x0a, 0xee, 0x02, 0x73, 0x74, 0x5e, 0xf4, 0x00, 0x02,
+ 0x2e, 0xf4, 0x00, 0x10, 0x7f, 0xd9, 0x00, 0x10, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x06, 0x39, 0x54,
+ 0x9b, 0xe6, 0x00, 0x38, 0x9f, 0x66, 0x00, 0x34, 0xff, 0x8d, 0x7e, 0xe0, 0xfb, 0x8d, 0x80, 0x90,
+ 0xff, 0x8e, 0x7f, 0x40, 0xfd, 0x0d, 0x7e, 0xe4, 0xf0, 0x0d, 0x7e, 0xe8, 0xff, 0x8d, 0x7e, 0xf8,
+ 0xfb, 0x8c, 0x85, 0x00, 0x8b, 0x6e, 0x00, 0x00, 0xc5, 0x74, 0x00, 0x00, 0x20, 0x5e, 0x00, 0x00,
+ 0xee, 0x02, 0x73, 0xf9, 0x05, 0x75, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00,
+ 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x70, 0xff, 0xf8, 0xce, 0x70, 0xd2, 0x00,
+ 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x55, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x5b, 0x42,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5a, 0xca, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6,
+ 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8,
+ 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x9b, 0x6e, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12,
+ 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfb, 0xef, 0x28, 0x02,
+ 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0,
+ 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x74, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0x9c, 0x46, 0x30, 0xff, 0x82, 0x00, 0x04, 0xcf, 0x28, 0xfc, 0x00, 0xfb, 0x0e, 0x7c, 0x40,
+ 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xb0, 0x00, 0xfc, 0x6f, 0x18, 0x0a, 0x8a, 0x7a, 0x00, 0x10,
+ 0xfd, 0x6f, 0x18, 0x08, 0x7c, 0xf4, 0xff, 0xe7, 0x0f, 0xe4, 0x07, 0x48, 0xfb, 0xff, 0x58, 0x00,
+ 0x8e, 0x6e, 0x00, 0x04, 0xcf, 0x60, 0xd2, 0x00, 0xcc, 0x60, 0xf2, 0x00, 0x4e, 0xa8, 0xfb, 0xfb,
+ 0xcf, 0xf0, 0xc0, 0x00, 0x9f, 0xee, 0x00, 0x04, 0xc0, 0x7a, 0xd2, 0x00, 0xff, 0x6f, 0x28, 0x0a,
+ 0xee, 0x02, 0x75, 0x7c, 0x5e, 0xf4, 0x00, 0x02, 0x2e, 0xf4, 0x00, 0x10, 0x7f, 0xe5, 0x00, 0x10,
+ 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x7c, 0x60, 0xfb, 0x0d, 0x80, 0x90, 0xff, 0x06, 0x37, 0x9c,
+ 0xff, 0x8e, 0x7f, 0x40, 0xfd, 0x0d, 0x7c, 0x64, 0xff, 0x01, 0x04, 0x14, 0xf0, 0x0d, 0x7c, 0x68,
+ 0xff, 0x8d, 0x7c, 0x78, 0xfb, 0x0c, 0x85, 0x00, 0x8a, 0xee, 0x00, 0x00, 0xc5, 0x74, 0x00, 0x00,
+ 0x20, 0x5a, 0x00, 0x00, 0xee, 0x02, 0x75, 0xfd, 0x05, 0x75, 0x02, 0x20, 0xff, 0x88, 0xe6, 0xd8,
+ 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9b, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8, 0xff, 0xfb, 0x28, 0x02,
+ 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58,
+ 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60, 0x4d, 0x70, 0xff, 0xf8,
+ 0xce, 0x70, 0xd2, 0x00, 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xc5, 0x00, 0xfc, 0x82, 0x00, 0x00,
+ 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x00, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x56, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0x9a, 0xee, 0x00, 0x14,
+ 0xfb, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xad, 0xc0,
+ 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfb, 0x6f, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xdd, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08,
+ 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0x9c, 0x46, 0x30, 0xff, 0x82, 0x00, 0x04, 0xcf, 0x28, 0xfc, 0x00,
+ 0xfb, 0x0e, 0x7d, 0xc0, 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xb0, 0x00, 0xfc, 0x6f, 0x18, 0x0a,
+ 0x8a, 0x7a, 0x00, 0x10, 0xfd, 0x6f, 0x18, 0x08, 0x7c, 0xf4, 0xff, 0xe7, 0x0f, 0xe4, 0x07, 0x48,
+ 0xfb, 0xff, 0x58, 0x00, 0x8e, 0x6e, 0x00, 0x04, 0xcf, 0x60, 0xd2, 0x00, 0xcc, 0x60, 0xf2, 0x00,
+ 0x4e, 0xa8, 0xdf, 0xfb, 0xcf, 0xf0, 0xc0, 0x00, 0x9f, 0xee, 0x00, 0x04, 0xc0, 0x7a, 0xd2, 0x00,
+ 0xff, 0x6f, 0x28, 0x0a, 0xee, 0x02, 0x77, 0x80, 0x5e, 0xf4, 0x00, 0x02, 0x2e, 0xf4, 0x00, 0x10,
+ 0x7f, 0xe5, 0x00, 0x10, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x7d, 0xe0, 0xfb, 0x0d, 0x80, 0x90,
+ 0xff, 0x06, 0x38, 0xa4, 0xff, 0x8e, 0x7f, 0x40, 0xfd, 0x0d, 0x7d, 0xe4, 0xff, 0x01, 0x04, 0x14,
+ 0xf0, 0x0d, 0x7d, 0xe8, 0xff, 0x8d, 0x7d, 0xf8, 0xfb, 0x0c, 0x85, 0x00, 0x8a, 0xee, 0x00, 0x00,
+ 0xc5, 0x74, 0x00, 0x00, 0x20, 0x5a, 0x00, 0x00, 0xee, 0x02, 0x78, 0x01, 0x05, 0x75, 0x02, 0x20,
+ 0xff, 0x88, 0xe6, 0xd8, 0x0f, 0x01, 0x80, 0x00, 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0x9b, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xb7, 0xf8,
+ 0xff, 0xfb, 0x28, 0x02, 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10,
+ 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60,
+ 0x4d, 0x70, 0xff, 0xf8, 0xce, 0x70, 0xd2, 0x00, 0x7f, 0xf1, 0x00, 0x0d, 0xcf, 0xfc, 0xc5, 0x00,
+ 0xfc, 0x82, 0x00, 0x00, 0xfd, 0x88, 0xe6, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x11, 0xd2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x56, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x0a, 0xb2, 0xe6, 0xff, 0xfb, 0x18, 0x00, 0xce, 0x60, 0xe0, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xe5, 0x00, 0xff, 0xef, 0x28, 0x0e, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0x9a, 0xee, 0x00, 0x14, 0xfb, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9d, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xad, 0xc0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xe6, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28,
+ 0x9f, 0x02, 0xff, 0xb0, 0xfb, 0x6f, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7f, 0xdd, 0x00, 0x02,
+ 0x9a, 0x7e, 0x07, 0x08, 0xff, 0x1e, 0x46, 0xe0, 0xac, 0x62, 0xf0, 0x02, 0xfc, 0x0d, 0x85, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x78, 0xe0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x02, 0x00, 0x02, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0x90, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x05,
+ 0x9d, 0x02, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x8a, 0x00, 0x00, 0x9d, 0x82, 0xfe, 0xc0, 0x0f, 0x01, 0x60, 0x00, 0x9f, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x06, 0x9d, 0x02, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x81, 0x00, 0x40,
+ 0x9f, 0x82, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x00, 0x80, 0x9d, 0x02, 0xfe, 0xc0,
+ 0x0d, 0x81, 0x40, 0x06, 0x9d, 0x82, 0xfe, 0xc8, 0xff, 0x8a, 0x31, 0xc4, 0xfd, 0x02, 0x00, 0x07,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x81, 0x04, 0x18, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x00, 0x40,
+ 0x9f, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x01, 0x00, 0x9d, 0x02, 0xfe, 0xc0,
+ 0x9d, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x08, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x81, 0x04, 0x1c,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x02, 0x00, 0x9f, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x90, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x09, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xff, 0x81, 0x04, 0x20, 0xfe, 0x82, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0x0d, 0x01, 0x40, 0x00, 0x9d, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x0a, 0xfd, 0x82, 0xf8, 0xe0, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x81, 0x04, 0x24,
+ 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xff, 0x42, 0x00, 0x00,
+ 0x9f, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x0b, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xff, 0x81, 0x04, 0x28, 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x22, 0x00, 0x00, 0x0d, 0x81, 0x20, 0x00, 0x9d, 0x02, 0xfe, 0xc0, 0x0d, 0xec, 0x02, 0x00,
+ 0x9d, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x0c, 0xff, 0x0a, 0x30, 0x98, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xff, 0x01, 0x04, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x06, 0x00, 0x00, 0x9d, 0x02, 0xfe, 0xc0, 0x9d, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x0d,
+ 0xff, 0x06, 0x3c, 0x94, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0x30, 0xfe, 0x02, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x00, 0x04, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x90, 0x02, 0xfe, 0xc0, 0x9d, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x0e, 0x9d, 0x02, 0xfe, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x04, 0x9f, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x90, 0x02, 0xfe, 0xc0, 0xfd, 0x02, 0x02, 0x00, 0x9d, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x0f,
+ 0xfd, 0x86, 0x3b, 0xa4, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x81, 0x04, 0x38, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x90, 0x02, 0xfe, 0xc0, 0xff, 0x02, 0x00, 0x31,
+ 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x10, 0xff, 0x81, 0x04, 0x3c, 0x9d, 0x02, 0xfe, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x4c, 0x18, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x7f, 0xfd, 0x00, 0x19, 0x9f, 0x82, 0xfe, 0xc0, 0xcf, 0x68, 0x00, 0x00, 0x90, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x11, 0xff, 0x8a, 0x32, 0x58, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x81, 0x04, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x0d, 0x01, 0x01, 0xe0,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x8a, 0x32, 0x0c, 0xfd, 0x02, 0x00, 0x12,
+ 0xff, 0x81, 0x04, 0x44, 0x9d, 0x02, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x82, 0x10, 0x00,
+ 0x9d, 0x82, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x82, 0xfc, 0x13, 0x9d, 0x82, 0xfe, 0xc0,
+ 0xcd, 0xe8, 0x00, 0x00, 0x9e, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x13, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xff, 0x81, 0x04, 0x48, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x04, 0x13, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x82, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x14, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x41, 0x08, 0xfd, 0x01, 0x04, 0x4c,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x02, 0x08, 0x13, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x15,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x34, 0x90, 0xfd, 0x01, 0x04, 0x50, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x10, 0x13,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x16, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xfd, 0x0a, 0x36, 0xa4, 0xfd, 0x01, 0x04, 0x54, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0xfc, 0x12, 0x9d, 0x02, 0xfe, 0xc0,
+ 0x9e, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x17, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x38, 0xb8,
+ 0xfd, 0x01, 0x04, 0x58, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x20, 0x12, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x82, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x18, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x43, 0x14, 0xfd, 0x01, 0x04, 0x5c,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x02, 0x40, 0x12, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x19,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x3a, 0xcc, 0xfd, 0x01, 0x04, 0x60, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x80, 0x12,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x1a, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xfd, 0x0a, 0x3c, 0xe0, 0xfd, 0x01, 0x04, 0x64, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x9f, 0x02, 0xfe, 0xc0, 0xfd, 0x02, 0x00, 0x22,
+ 0x9d, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x1b, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x3e, 0xf4,
+ 0xfd, 0x01, 0x04, 0x68, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0xfc, 0x03, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x1c, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x32, 0xb0, 0xfd, 0x01, 0x04, 0x6c,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x02, 0x04, 0x03, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x1d,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x53, 0x40, 0xfd, 0x01, 0x04, 0x70, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x08, 0x03,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x1e, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xfd, 0x0a, 0x46, 0xf8, 0xfd, 0x01, 0x04, 0x74, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x10, 0x03, 0x9d, 0x02, 0xfe, 0xc0,
+ 0x9e, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x1f, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x49, 0x04,
+ 0xfd, 0x01, 0x04, 0x78, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x20, 0x03, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x0a, 0x4b, 0x10, 0xfd, 0x01, 0x04, 0x7c, 0x9e, 0x82, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x40, 0x03,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x21, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xfd, 0x0a, 0x4d, 0x1c, 0xfd, 0x01, 0x04, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x80, 0x03, 0x9d, 0x02, 0xfe, 0xc0,
+ 0x9e, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x22, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x4f, 0x28,
+ 0xfd, 0x01, 0x04, 0x84, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x00, 0x01, 0x9d, 0x02, 0xfe, 0xc0, 0xfd, 0x02, 0x00, 0x32,
+ 0x9d, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x23, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x51, 0x34,
+ 0xfd, 0x01, 0x04, 0x88, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0xfc, 0x23, 0x9d, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x24, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x45, 0x20, 0xfd, 0x01, 0x04, 0x8c,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x02, 0x04, 0x23, 0x9d, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x25,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x63, 0x04, 0xfd, 0x01, 0x04, 0x90, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x08, 0x23,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x26, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xfd, 0x0a, 0x57, 0x1c, 0xfd, 0x01, 0x04, 0x94, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x10, 0x23, 0x9d, 0x02, 0xfe, 0xc0,
+ 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x27, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x59, 0x18,
+ 0xfd, 0x01, 0x04, 0x98, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0xfc, 0x22, 0x9d, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x28, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x5b, 0x14, 0xfd, 0x01, 0x04, 0x9c,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x02, 0x20, 0x22, 0x9d, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x29,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x64, 0xf8, 0xfd, 0x01, 0x04, 0xa0, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x40, 0x22,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x2a, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xfd, 0x0a, 0x5d, 0x10, 0xfd, 0x01, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x80, 0x22, 0x9d, 0x02, 0xfe, 0xc0,
+ 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x2b, 0xff, 0x0a, 0x5f, 0x0c, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xff, 0x01, 0x04, 0xa8, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0x9e, 0x82, 0xfe, 0xc0, 0x9d, 0x82, 0xfe, 0xc8, 0xfd, 0x82, 0x00, 0x2c,
+ 0xff, 0x0a, 0x61, 0x08, 0x9d, 0x82, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0xac, 0x00, 0x00, 0x00, 0x01,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x82, 0xfc, 0x33, 0x9d, 0x82, 0xfe, 0xc0,
+ 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x2d, 0xff, 0x0a, 0x55, 0x44, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xff, 0x01, 0x04, 0xb0, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x82, 0x04, 0x33, 0x9d, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x2e, 0xff, 0x0a, 0x75, 0x20, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0xb4,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x82, 0x08, 0x33, 0x9d, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x2f,
+ 0xff, 0x0a, 0x68, 0xd8, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0xb8, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x82, 0x10, 0x33,
+ 0x9d, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x0a, 0x6a, 0xe4, 0xff, 0x01, 0x04, 0xbc,
+ 0x9e, 0x02, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x82, 0xfc, 0x32, 0x9d, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x31,
+ 0xff, 0x0a, 0x6c, 0xf0, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0xc0, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x82, 0x20, 0x32,
+ 0x9d, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x32, 0xff, 0x0a, 0x77, 0x24,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0xc4, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x82, 0x40, 0x32, 0x9d, 0x82, 0xfe, 0xc0,
+ 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x33, 0xff, 0x0a, 0x6e, 0xfc, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xff, 0x01, 0x04, 0xc8, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x82, 0x80, 0x32, 0x9d, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x34, 0xff, 0x0a, 0x71, 0x08, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0xcc,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x9e, 0x02, 0xfe, 0xc0, 0xfd, 0x82, 0x00, 0x02, 0x9d, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x35,
+ 0xff, 0x0a, 0x73, 0x14, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0xd0, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x90, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x36, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x66, 0xec, 0xfd, 0x01, 0x04, 0xd4,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x81, 0x04, 0xd8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x70, 0x2a, 0x00, 0x0b,
+ 0xea, 0x02, 0x81, 0xd4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x85, 0x80, 0x20, 0x7e, 0x00, 0x04,
+ 0xe6, 0x02, 0x83, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x9c, 0x46, 0x50, 0x4f, 0xf4, 0xff, 0xfc,
+ 0x20, 0x7e, 0x00, 0x04, 0xe6, 0x02, 0x83, 0x00, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x02, 0xff, 0xd0,
+ 0x2f, 0xf4, 0x00, 0x04, 0xff, 0x9d, 0x46, 0x50, 0xff, 0x0d, 0x84, 0xe0, 0xe0, 0x02, 0x83, 0x00,
+ 0xf0, 0x1d, 0x46, 0x70, 0xf7, 0x8a, 0x81, 0xe0, 0xe0, 0x01, 0x36, 0xd4, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x82, 0xff, 0xf8, 0xfe, 0x82, 0x00, 0x01, 0xfd, 0x8e, 0x4b, 0xe0, 0xcf, 0xfe, 0xec, 0x00,
+ 0x9f, 0x82, 0xff, 0xf8, 0x8f, 0x02, 0xff, 0xf8, 0xe6, 0x70, 0x00, 0x03, 0x20, 0x72, 0x00, 0x00,
+ 0x7f, 0x78, 0xff, 0xfa, 0xcf, 0x78, 0xec, 0x00, 0xe6, 0x02, 0x82, 0x25, 0xff, 0x6f, 0x68, 0x3c,
+ 0xff, 0x8c, 0x85, 0x60, 0x20, 0x7e, 0x00, 0x64, 0xe2, 0x02, 0x82, 0x25, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x02, 0x00, 0x02, 0xff, 0x8c, 0x4b, 0xfc, 0xc0, 0x72, 0xfa, 0x00, 0xe6, 0x02, 0x82, 0x55,
+ 0xf0, 0x0d, 0x85, 0x60, 0xff, 0x83, 0x5b, 0xe8, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x02, 0x82, 0x54,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x00, 0x01, 0xf7, 0xef, 0x68, 0x3e, 0xfe, 0x0d, 0x4b, 0xfc,
+ 0x55, 0x28, 0x01, 0x00, 0xff, 0x98, 0x86, 0x10, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x82, 0x91,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x1c, 0x46, 0x40, 0xfe, 0xfa, 0x84, 0x80,
+ 0xcf, 0xfc, 0xf2, 0x00, 0xc0, 0x7e, 0xea, 0x00, 0xe2, 0x02, 0x82, 0x91, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xff, 0xd0, 0xf0, 0x19, 0x86, 0x10, 0x55, 0x28, 0x01, 0x00, 0xff, 0x9d, 0x46, 0x40,
+ 0xfe, 0x88, 0xb3, 0x2c, 0xff, 0x88, 0xbc, 0x08, 0xc0, 0x7e, 0xea, 0x00, 0xe6, 0x02, 0x83, 0x01,
+ 0xff, 0x1e, 0x07, 0xff, 0xfe, 0x08, 0xb3, 0x1c, 0xff, 0x88, 0xbb, 0xf8, 0xcf, 0xf0, 0xfa, 0x00,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe2, 0x02, 0x82, 0xd0, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x08, 0xb9, 0x34,
+ 0xff, 0x88, 0xb9, 0x38, 0xc0, 0x1a, 0xfa, 0x00, 0xe4, 0x02, 0x82, 0xdc, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x89, 0xbc, 0x08, 0xe0, 0x02, 0x83, 0x00, 0xfe, 0x09, 0xbb, 0xf8, 0x03, 0x18, 0x00, 0x04,
+ 0xf3, 0x09, 0xb9, 0x34, 0xf7, 0x8a, 0x82, 0xf0, 0xe0, 0x01, 0x10, 0x98, 0x97, 0x93, 0xff, 0xfc,
+ 0xfe, 0x88, 0xb3, 0x2c, 0xfe, 0x08, 0xb3, 0x1c, 0xe0, 0x02, 0x82, 0xd4, 0xfe, 0x89, 0xbc, 0x08,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x82, 0x00, 0x0f, 0xff, 0x8d, 0x4c, 0x18, 0xf7, 0x8a, 0x83, 0x28,
+ 0xe0, 0x02, 0x79, 0x20, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x8a, 0x83, 0x34, 0xe0, 0x01, 0x0f, 0xd4,
+ 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x8a, 0x83, 0x40, 0xe0, 0x01, 0x12, 0xa8, 0x97, 0x93, 0xff, 0xfc,
+ 0xf7, 0x8a, 0x83, 0x4c, 0xe0, 0x01, 0x2d, 0x34, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x8a, 0x83, 0x58,
+ 0xe0, 0x01, 0x18, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x0c, 0x4b, 0xec,
+ 0xff, 0x8c, 0x4c, 0x04, 0xfe, 0x9b, 0x58, 0x08, 0x0f, 0x78, 0x00, 0x01, 0x0f, 0xfc, 0x00, 0x01,
+ 0xff, 0x0d, 0x4b, 0xec, 0x20, 0x1e, 0x00, 0x01, 0xe6, 0x02, 0x83, 0xf0, 0xff, 0x8d, 0x4c, 0x04,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x83, 0xb5, 0x20, 0x76, 0x00, 0x0f, 0xe6, 0x02, 0x83, 0xb5,
+ 0x20, 0x76, 0x00, 0xf0, 0xe6, 0x02, 0x83, 0xb5, 0x20, 0x76, 0x00, 0xff, 0xe6, 0x02, 0x83, 0xf0,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x46, 0xc0, 0xff, 0x8c, 0x7f, 0xd8, 0xcf, 0xfc, 0xf2, 0x00,
+ 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x4c, 0x28, 0xff, 0x88, 0xbc, 0x00, 0xcf, 0x78, 0xe8, 0x00,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x02, 0x83, 0xe1, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x0d, 0x85, 0x60,
+ 0xff, 0x8c, 0x85, 0x60, 0xff, 0x09, 0xbc, 0x00, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x85, 0x60,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
+ 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
+ 0x77, 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x9b, 0x44, 0x01, 0xf4, 0x02, 0x00, 0x00, 0xc0, 0x7e, 0x42, 0x00, 0xe6, 0x02, 0x84, 0x55,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x9b, 0x44, 0x01, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x84, 0x44,
+ 0x04, 0x20, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x02, 0x00, 0x19, 0xcf, 0x9c, 0xf7, 0xc0,
+ 0xc0, 0x1a, 0xfa, 0x00, 0xe4, 0x02, 0x84, 0x8c, 0x00, 0x00, 0x00, 0x01, 0xc3, 0x18, 0xfa, 0x00,
+ 0xc0, 0x1a, 0xfa, 0x00, 0xe4, 0x02, 0x84, 0x7d, 0x00, 0x00, 0x00, 0x01, 0x2f, 0x7a, 0x00, 0x01,
+ 0xea, 0x02, 0x84, 0x6c, 0xc4, 0x18, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xcf, 0x18, 0x00, 0x00,
+ 0xf3, 0x02, 0x00, 0x00, 0xfe, 0x02, 0x00, 0x19, 0xfd, 0x82, 0x00, 0x01, 0xcf, 0x9c, 0xe7, 0xc0,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe4, 0x02, 0x84, 0xe0, 0x00, 0x00, 0x00, 0x01, 0xce, 0xec, 0xe7, 0xc0,
+ 0xcf, 0x78, 0xfa, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe4, 0x02, 0x84, 0xd1, 0xc3, 0x18, 0xe8, 0x00,
+ 0x2e, 0x72, 0x00, 0x01, 0xea, 0x02, 0x84, 0xbc, 0xc4, 0x18, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x14, 0x93, 0x16, 0xff, 0xf4, 0x93, 0x16, 0xff, 0xe8, 0x94, 0x16, 0xff, 0xf0,
+ 0x94, 0x96, 0xff, 0xec, 0xcf, 0x9c, 0x00, 0x00, 0xf0, 0x1b, 0x68, 0x00, 0x83, 0x96, 0xff, 0xf0,
+ 0xc3, 0x7c, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xe4, 0xf7, 0x8a, 0x85, 0x34, 0xe0, 0x02, 0x84, 0x60,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x0a, 0x84, 0x00, 0x8e, 0x96, 0xff, 0xe8, 0xa4, 0x7a, 0x40, 0x05,
+ 0xf4, 0x77, 0x6c, 0x01, 0x8f, 0x96, 0xff, 0xe4, 0x83, 0x96, 0xff, 0xf0, 0x9e, 0x96, 0xff, 0xe8,
+ 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x8a, 0x85, 0x60, 0xe0, 0x02, 0x84, 0xa4, 0x97, 0x93, 0xff, 0xfc,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x85, 0x1c, 0xcf, 0xa0, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xec,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x85, 0x91, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xe8,
+ 0x8f, 0x16, 0xff, 0xf4, 0xcf, 0xf4, 0xf2, 0x00, 0x8e, 0x96, 0xff, 0xec, 0x9f, 0xf6, 0x00, 0x00,
+ 0x84, 0x16, 0xff, 0xe8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x28, 0x66, 0x6d, 0x74, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x0a, 0x00, 0x28, 0x6e, 0x75, 0x6c,
+ 0x6c, 0x29, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x74,
+ 0xfe, 0x82, 0x00, 0x00, 0x93, 0x96, 0xff, 0xc4, 0x94, 0x16, 0xff, 0xc0, 0x93, 0x16, 0xff, 0xc8,
+ 0xcd, 0x24, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x00, 0x9e, 0x96, 0xff, 0x90, 0xe6, 0x02, 0x85, 0xe9,
+ 0x94, 0x16, 0xff, 0xbc, 0x9e, 0x96, 0xff, 0xbc, 0x8f, 0x16, 0xff, 0xc8, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x02, 0x97, 0x15, 0xff, 0x8a, 0x85, 0xa0, 0x8e, 0x96, 0xff, 0xc8, 0xff, 0x02, 0x00, 0x20,
+ 0xff, 0x82, 0x00, 0x00, 0xf3, 0x77, 0x54, 0x01, 0x9f, 0x16, 0xff, 0x94, 0x9e, 0x96, 0xff, 0xc8,
+ 0x20, 0x1a, 0x00, 0x25, 0xe6, 0x02, 0x86, 0x71, 0x9f, 0x96, 0xff, 0xa4, 0x20, 0x1a, 0x00, 0x00,
+ 0xe6, 0x02, 0x97, 0x1d, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xc4, 0x20, 0x76, 0x00, 0x00,
+ 0xe6, 0x02, 0x97, 0x05, 0x00, 0x00, 0x00, 0x01, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x8a, 0x86, 0x4c, 0xc1, 0x74, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8f, 0x96, 0xff, 0xc8, 0x8e, 0x96, 0xff, 0x90, 0xf3, 0x7f, 0x54, 0x01, 0x0e, 0xf4, 0x00, 0x01,
+ 0x9f, 0x96, 0xff, 0xc8, 0x20, 0x1a, 0x00, 0x25, 0xe6, 0x02, 0x86, 0x1c, 0x9e, 0x96, 0xff, 0x90,
+ 0x8f, 0x16, 0xff, 0xc8, 0xfc, 0x82, 0x00, 0x00, 0xcb, 0x64, 0x00, 0x00, 0xfe, 0xfb, 0x58, 0x00,
+ 0x2d, 0xf8, 0x00, 0x01, 0xcb, 0xe4, 0x00, 0x00, 0x9c, 0x96, 0xff, 0xa0, 0x9c, 0x96, 0xff, 0x9c,
+ 0x9c, 0x96, 0xff, 0x98, 0xca, 0x64, 0x00, 0x00, 0xc9, 0x64, 0x00, 0x00, 0xc8, 0xe4, 0x00, 0x00,
+ 0xcc, 0x64, 0x00, 0x00, 0xca, 0xe4, 0x00, 0x00, 0xc9, 0xe4, 0x00, 0x00, 0x7f, 0xf5, 0x00, 0x18,
+ 0x8e, 0x96, 0xff, 0xc8, 0x73, 0x7c, 0xff, 0xe8, 0x2f, 0x98, 0x00, 0x23, 0x0e, 0xf4, 0x00, 0x01,
+ 0x20, 0x7e, 0x00, 0x57, 0xe2, 0x02, 0x96, 0x6c, 0x9e, 0x96, 0xff, 0xc8, 0x7f, 0xfd, 0x00, 0x02,
+ 0xff, 0x0a, 0x86, 0xe0, 0xae, 0xfe, 0xf0, 0x02, 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x02, 0x88, 0x54, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x88, 0x68, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x88, 0xb0,
+ 0x00, 0x02, 0x88, 0xd0, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x89, 0x18, 0x00, 0x02, 0x88, 0x40,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x89, 0x2c, 0x00, 0x02, 0x89, 0x38, 0x00, 0x02, 0x89, 0x38,
+ 0x00, 0x02, 0x89, 0x38, 0x00, 0x02, 0x89, 0x38, 0x00, 0x02, 0x89, 0x38, 0x00, 0x02, 0x89, 0x38,
+ 0x00, 0x02, 0x89, 0x38, 0x00, 0x02, 0x89, 0x38, 0x00, 0x02, 0x89, 0x38, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x89, 0xa4, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0xe0, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x8b, 0x5c,
+ 0x00, 0x02, 0x8d, 0xb4, 0x00, 0x02, 0x8d, 0xec, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x8d, 0xc4, 0x00, 0x02, 0x8d, 0xec, 0x00, 0x02, 0x92, 0x90,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x92, 0x9c, 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x92, 0xc8,
+ 0x00, 0x02, 0x93, 0x68, 0x00, 0x02, 0x93, 0xe0, 0x00, 0x02, 0x94, 0x04, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x94, 0x10, 0x00, 0x02, 0x96, 0x58, 0x00, 0x02, 0x96, 0x64, 0x00, 0x02, 0x96, 0x6c,
+ 0x00, 0x02, 0x96, 0x6c, 0x00, 0x02, 0x96, 0xe0, 0x00, 0x02, 0x96, 0xec, 0x00, 0x02, 0x96, 0xf8,
+ 0x8f, 0x16, 0xff, 0xc8, 0xfb, 0x82, 0x00, 0x01, 0xfe, 0xfb, 0x58, 0x00, 0xe0, 0x02, 0x86, 0xb0,
+ 0x7f, 0xf5, 0x00, 0x18, 0x8f, 0x96, 0xff, 0xc8, 0xff, 0x02, 0x00, 0x01, 0xfe, 0xff, 0x58, 0x00,
+ 0xe0, 0x02, 0x86, 0xac, 0x9f, 0x16, 0xff, 0x9c, 0x8e, 0x96, 0xff, 0xc4, 0x20, 0x76, 0x00, 0x00,
+ 0xe6, 0x02, 0x88, 0xa1, 0x00, 0x00, 0x00, 0x01, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x8a, 0x88, 0x8c, 0xc1, 0x74, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8f, 0x96, 0xff, 0x90, 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x02, 0x85, 0xf8, 0x9f, 0x96, 0xff, 0x90,
+ 0x8f, 0x16, 0xff, 0xbc, 0xf3, 0x7b, 0x64, 0x01, 0xe0, 0x02, 0x88, 0x90, 0x9f, 0x16, 0xff, 0xbc,
+ 0x20, 0x5e, 0x00, 0x00, 0xe6, 0x02, 0x89, 0x04, 0x00, 0x00, 0x00, 0x01, 0x8f, 0xea, 0x00, 0x00,
+ 0x0d, 0x68, 0x00, 0x04, 0x20, 0x7e, 0x00, 0x00, 0xec, 0x02, 0x88, 0xe1, 0x9f, 0x96, 0xff, 0xa4,
+ 0x8f, 0x96, 0xff, 0xc8, 0xfe, 0xff, 0x58, 0x00, 0xe0, 0x02, 0x86, 0xb0, 0x7f, 0xf5, 0x00, 0x18,
+ 0x8f, 0x16, 0xff, 0xc8, 0x8f, 0x96, 0xff, 0xa0, 0xfe, 0xfb, 0x58, 0x00, 0x6f, 0xfc, 0x00, 0x01,
+ 0x8f, 0x16, 0xff, 0xa4, 0x9f, 0x96, 0xff, 0xa0, 0xcf, 0x00, 0xf2, 0x00, 0xe0, 0x02, 0x86, 0xac,
+ 0x9f, 0x16, 0xff, 0xa4, 0x8f, 0x96, 0xff, 0xc8, 0x8a, 0x6a, 0x00, 0x00, 0xfe, 0xff, 0x58, 0x00,
+ 0xe0, 0x02, 0x86, 0xac, 0x0d, 0x68, 0x00, 0x04, 0x8f, 0x16, 0xff, 0xc8, 0xff, 0x82, 0x00, 0x01,
+ 0xfe, 0xfb, 0x58, 0x00, 0xe0, 0x02, 0x86, 0xac, 0x9f, 0x96, 0xff, 0xa0, 0x20, 0x5e, 0x00, 0x00,
+ 0xe6, 0x02, 0x89, 0x95, 0xff, 0x82, 0x00, 0x30, 0xfe, 0x02, 0x00, 0x00, 0x7f, 0xf1, 0x00, 0x03,
+ 0xcf, 0xfc, 0xe0, 0x00, 0x8e, 0x96, 0xff, 0xc8, 0xcf, 0xfc, 0xe0, 0x00, 0xcf, 0xfc, 0x30, 0x00,
+ 0xf3, 0x77, 0x48, 0x00, 0xfe, 0xf7, 0x58, 0x00, 0x2f, 0x18, 0x00, 0x30, 0x20, 0x7a, 0x00, 0x09,
+ 0xe2, 0x02, 0x89, 0x78, 0x2e, 0x7c, 0x00, 0x30, 0x8f, 0x16, 0xff, 0xc8, 0x0f, 0x78, 0x00, 0x01,
+ 0xe0, 0x02, 0x89, 0x3c, 0x9f, 0x16, 0xff, 0xc8, 0x20, 0x5e, 0x00, 0x00, 0xe6, 0x02, 0x89, 0x8d,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x86, 0xac, 0xca, 0x70, 0x00, 0x00, 0xe0, 0x02, 0x86, 0xac,
+ 0x9e, 0x16, 0xff, 0xa4, 0x8f, 0x16, 0xff, 0xc8, 0xfe, 0xfb, 0x58, 0x00, 0xe0, 0x02, 0x86, 0xac,
+ 0x9f, 0x96, 0xff, 0x94, 0xcf, 0x68, 0x00, 0x00, 0x8f, 0x7a, 0x00, 0x00, 0x0d, 0x68, 0x00, 0x04,
+ 0x8e, 0x96, 0xff, 0xa4, 0x9f, 0x16, 0xff, 0xb0, 0x8f, 0xea, 0x00, 0x00, 0x20, 0x76, 0x00, 0x00,
+ 0x9f, 0x96, 0xff, 0xb8, 0xe6, 0x02, 0x89, 0xd4, 0x0d, 0x68, 0x00, 0x04, 0xff, 0x02, 0x00, 0x10,
+ 0x9f, 0x16, 0xff, 0xa4, 0x8f, 0x96, 0xff, 0xa4, 0x2f, 0xfc, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xa4,
+ 0x8e, 0x96, 0xff, 0xa4, 0xcf, 0x84, 0x00, 0x00, 0xc0, 0x76, 0xfa, 0x00, 0xe6, 0x02, 0x85, 0xf9,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xb0, 0x8e, 0x96, 0xff, 0xc4, 0xff, 0xfb, 0x58, 0x00,
+ 0x20, 0x76, 0x00, 0x00, 0x7f, 0xfc, 0xff, 0xfc, 0xff, 0x0a, 0x84, 0x00, 0xa3, 0x7a, 0xf8, 0x04,
+ 0xe6, 0x02, 0x8b, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x8a, 0x8a, 0x2c, 0xc1, 0x74, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8e, 0x96, 0xff, 0xb0, 0x8f, 0x16, 0xff, 0xc4, 0xff, 0xf7, 0x58, 0x00, 0x20, 0x7a, 0x00, 0x00,
+ 0xff, 0x02, 0x00, 0x0f, 0xcf, 0xfc, 0xf4, 0x00, 0x8f, 0x16, 0xff, 0x90, 0xfe, 0x8a, 0x84, 0x00,
+ 0xa3, 0x76, 0xf8, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xe6, 0x02, 0x8b, 0x3d, 0x9f, 0x16, 0xff, 0x90,
+ 0x83, 0x96, 0xff, 0xc0, 0x8f, 0x96, 0xff, 0xc4, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x8a, 0x78,
+ 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x96, 0xff, 0x90,
+ 0x8e, 0x96, 0xff, 0xb0, 0x8f, 0x16, 0xff, 0xa4, 0x0f, 0xfc, 0x00, 0x01, 0x0e, 0xf4, 0x00, 0x01,
+ 0x20, 0x7a, 0x00, 0x00, 0x9f, 0x96, 0xff, 0x90, 0xe6, 0x02, 0x8b, 0x0d, 0x9e, 0x96, 0xff, 0xb0,
+ 0x8f, 0x16, 0xff, 0xb8, 0x8e, 0x96, 0xff, 0xb8, 0xff, 0xfb, 0x48, 0x00, 0xff, 0x7b, 0x58, 0x00,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8b, 0x0d, 0x9e, 0x96, 0xff, 0xb4, 0x7f, 0xf9, 0x00, 0x18,
+ 0x8f, 0x16, 0xff, 0xc4, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x8b, 0x2d, 0x73, 0x7d, 0xff, 0xe8,
+ 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x8a, 0xe4, 0xc1, 0x78, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8e, 0x96, 0xff, 0xb4, 0x8f, 0x96, 0xff, 0x90,
+ 0xff, 0x77, 0x5c, 0x01, 0x0f, 0xfc, 0x00, 0x01, 0x9f, 0x96, 0xff, 0x90, 0x7f, 0xf9, 0x00, 0x18,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8a, 0xc0, 0x9e, 0x96, 0xff, 0xb4, 0x8e, 0x96, 0xff, 0xa4,
+ 0xcf, 0x84, 0x00, 0x00, 0x2e, 0xf4, 0x00, 0x01, 0xc0, 0x76, 0xfa, 0x00, 0xe6, 0x02, 0x89, 0xf4,
+ 0x9e, 0x96, 0xff, 0xa4, 0xe0, 0x02, 0x85, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xbc,
+ 0xf3, 0x7f, 0x64, 0x01, 0xe0, 0x02, 0x8a, 0xe8, 0x9f, 0x96, 0xff, 0xbc, 0x8e, 0x96, 0xff, 0xbc,
+ 0xf3, 0x77, 0x64, 0x01, 0xe0, 0x02, 0x8a, 0x7c, 0x9e, 0x96, 0xff, 0xbc, 0x8f, 0x96, 0xff, 0xbc,
+ 0xf3, 0x7f, 0x64, 0x01, 0xe0, 0x02, 0x8a, 0x30, 0x9f, 0x96, 0xff, 0xbc, 0xcf, 0xe8, 0x00, 0x00,
+ 0x8f, 0x6b, 0x00, 0x04, 0x8f, 0xfe, 0x00, 0x00, 0x23, 0x14, 0x00, 0x30, 0xf4, 0x82, 0x00, 0x00,
+ 0x9f, 0x96, 0xff, 0xac, 0xf4, 0x7b, 0x44, 0x01, 0xc3, 0xfc, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0x9f, 0x16, 0xff, 0xb8, 0xf7, 0x8a, 0x8b, 0x90, 0xe0, 0x02, 0x84, 0xf8, 0x97, 0x93, 0xff, 0xfc,
+ 0x94, 0x16, 0xff, 0xb4, 0xff, 0xa3, 0x58, 0x00, 0x8d, 0x16, 0xff, 0x8c, 0x7f, 0xfd, 0x00, 0x18,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8c, 0x01, 0x0d, 0x68, 0x00, 0x04, 0x8e, 0x96, 0xff, 0xb4,
+ 0x73, 0x7d, 0xff, 0xe8, 0x8f, 0x96, 0xff, 0xc4, 0x2e, 0xf4, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x8d, 0xa5, 0x9e, 0x96, 0xff, 0xb4, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x8a, 0x8b, 0xdc, 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8e, 0x96, 0xff, 0xb4, 0x8f, 0x16, 0xff, 0x90, 0xff, 0xf7, 0x58, 0x00, 0x0f, 0x78, 0x00, 0x01,
+ 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8b, 0xac, 0x9f, 0x16, 0xff, 0x90,
+ 0x8f, 0x96, 0xff, 0xac, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x85, 0xf9, 0x00, 0x00, 0x00, 0x01,
+ 0x8e, 0x96, 0xff, 0xb8, 0x90, 0x16, 0xff, 0xcc, 0xff, 0xf7, 0x58, 0x00, 0x7f, 0xfd, 0x00, 0x18,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8d, 0x15, 0x00, 0x00, 0x00, 0x01, 0x7e, 0x7d, 0xff, 0xe8,
+ 0x2f, 0x70, 0x00, 0x01, 0xff, 0x82, 0x00, 0x01, 0xcf, 0xfc, 0xf7, 0xc0, 0x8f, 0x16, 0xff, 0xac,
+ 0xc0, 0x7a, 0xfc, 0x00, 0x8f, 0x96, 0xff, 0xb8, 0x0f, 0xfc, 0x00, 0x01, 0xe6, 0x02, 0x8d, 0x69,
+ 0x9f, 0x96, 0xff, 0xb8, 0x8f, 0x96, 0xff, 0xcc, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8c, 0x68,
+ 0xf3, 0x02, 0x00, 0x2c, 0xf3, 0x02, 0x00, 0x3c, 0x8e, 0x96, 0xff, 0xc4, 0x20, 0x76, 0x00, 0x00,
+ 0xe6, 0x02, 0x8d, 0x59, 0x00, 0x00, 0x00, 0x01, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x8a, 0x8c, 0x8c, 0xc1, 0x74, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8f, 0x96, 0xff, 0xb8, 0x8e, 0x96, 0xff, 0x90, 0xfe, 0x7f, 0x48, 0x00, 0x0e, 0xf4, 0x00, 0x01,
+ 0x20, 0x72, 0x00, 0x20, 0xee, 0x02, 0x8c, 0xf5, 0x9e, 0x96, 0xff, 0x90, 0x8f, 0x16, 0xff, 0xc4,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x8d, 0x49, 0xc3, 0x70, 0x00, 0x00, 0x83, 0x96, 0xff, 0xc0,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x8c, 0xd0, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0x8e, 0x96, 0xff, 0xb8, 0x8f, 0x16, 0xff, 0x90, 0xfe, 0x77, 0x4c, 0x01,
+ 0x0f, 0x78, 0x00, 0x01, 0x9e, 0x96, 0xff, 0xb8, 0x20, 0x72, 0x00, 0x20, 0xee, 0x02, 0x8c, 0xac,
+ 0x9f, 0x16, 0xff, 0x90, 0x8e, 0x96, 0xff, 0xb8, 0xff, 0x82, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xcc,
+ 0xff, 0x77, 0x58, 0x00, 0x7f, 0xf9, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8c, 0x2c,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xcc, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x85, 0xf9,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xc4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x88, 0x78,
+ 0xf3, 0x02, 0x00, 0x3e, 0x8f, 0x16, 0xff, 0xbc, 0xf7, 0x82, 0x00, 0x3e, 0xf7, 0xfb, 0x64, 0x01,
+ 0xe0, 0x02, 0x88, 0x90, 0x9f, 0x16, 0xff, 0xbc, 0x8f, 0x96, 0xff, 0xbc, 0xfe, 0x7f, 0x64, 0x01,
+ 0xe0, 0x02, 0x8c, 0xd4, 0x9f, 0x96, 0xff, 0xbc, 0x8f, 0x16, 0xff, 0xbc, 0xf3, 0x7b, 0x64, 0x01,
+ 0xe0, 0x02, 0x8c, 0x90, 0x9f, 0x16, 0xff, 0xbc, 0x8f, 0x16, 0xff, 0xb8, 0xff, 0xfb, 0x48, 0x00,
+ 0xff, 0x7b, 0x58, 0x00, 0x20, 0x7e, 0x00, 0x20, 0xee, 0x02, 0x8d, 0x09, 0x7f, 0xf9, 0x00, 0x18,
+ 0x8f, 0x96, 0xff, 0xb8, 0xff, 0x7f, 0x5c, 0x01, 0x9f, 0x96, 0xff, 0xb8, 0x7f, 0xf9, 0x00, 0x18,
+ 0x20, 0x7f, 0x20, 0x00, 0xee, 0x02, 0x8d, 0x80, 0x20, 0x7e, 0x00, 0x00, 0xe0, 0x02, 0x8d, 0x0c,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xbc, 0xf3, 0x7b, 0x64, 0x01, 0xe0, 0x02, 0x8b, 0xe0,
+ 0x9f, 0x16, 0xff, 0xbc, 0x83, 0x6a, 0x00, 0x00, 0x8e, 0x96, 0xff, 0xc4, 0xe0, 0x02, 0x88, 0x6c,
+ 0x0d, 0x68, 0x00, 0x04, 0x20, 0x46, 0x00, 0x00, 0xe6, 0x02, 0x8d, 0xe1, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x96, 0xff, 0xc8, 0xf8, 0x82, 0x00, 0x00, 0xe0, 0x02, 0x88, 0xd4, 0xf9, 0x02, 0x00, 0x01,
+ 0x8f, 0x16, 0xff, 0xc8, 0xe0, 0x02, 0x88, 0x48, 0xf8, 0x82, 0x00, 0x01, 0xff, 0x02, 0x00, 0x0a,
+ 0x9f, 0x16, 0xff, 0xa8, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x02, 0x92, 0x40, 0xff, 0x02, 0x00, 0x01,
+ 0x20, 0x5a, 0x00, 0x00, 0xe6, 0x02, 0x92, 0x29, 0x20, 0x56, 0x00, 0x00, 0x8f, 0xea, 0x00, 0x04,
+ 0x0d, 0x68, 0x00, 0x08, 0x9f, 0x96, 0xff, 0xac, 0x8f, 0x96, 0xff, 0xac, 0x20, 0x7e, 0x00, 0x00,
+ 0xec, 0x02, 0x92, 0x19, 0xfe, 0x82, 0x00, 0x01, 0x83, 0x96, 0xff, 0xac, 0x84, 0x16, 0xff, 0xa8,
+ 0x9d, 0x16, 0xff, 0x8c, 0x23, 0x14, 0x00, 0x30, 0x24, 0x94, 0x00, 0x34, 0xf7, 0x8a, 0x8e, 0x48,
+ 0xe0, 0x02, 0x84, 0xf8, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0x9c, 0x8d, 0x16, 0xff, 0x8c,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x8e, 0x8d, 0x94, 0x16, 0xff, 0xb8, 0x8f, 0x96, 0xff, 0xac,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8e, 0x8d, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xa8,
+ 0x20, 0x76, 0x00, 0x08, 0xe6, 0x02, 0x92, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xa8,
+ 0x20, 0x7a, 0x00, 0x10, 0xe6, 0x02, 0x91, 0xfd, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0x98,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8e, 0xa9, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xcc,
+ 0x0f, 0xfc, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xcc, 0x8e, 0x96, 0xff, 0xa0, 0x20, 0x76, 0x00, 0x00,
+ 0xe6, 0x02, 0x8f, 0x40, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xa4, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x02, 0x8f, 0x41, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xcc, 0xcf, 0x78, 0xfa, 0x00,
+ 0x20, 0x7a, 0x00, 0x00, 0xee, 0x02, 0x8f, 0x41, 0x9f, 0x16, 0xff, 0xa4, 0x2f, 0x78, 0x00, 0x01,
+ 0xcf, 0x84, 0x00, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x02, 0x8f, 0x41, 0x9f, 0x16, 0xff, 0xa4,
+ 0x8f, 0x96, 0xff, 0xc4, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x91, 0xe9, 0x00, 0x00, 0x00, 0x01,
+ 0x83, 0x16, 0xff, 0x94, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x8f, 0x18,
+ 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x96, 0xff, 0xa4,
+ 0x8f, 0x16, 0xff, 0x90, 0xce, 0x84, 0x00, 0x00, 0x2f, 0xfc, 0x00, 0x01, 0x0f, 0x78, 0x00, 0x01,
+ 0x9f, 0x96, 0xff, 0xa4, 0xc0, 0x7e, 0xea, 0x00, 0xe6, 0x02, 0x8e, 0xf0, 0x9f, 0x16, 0xff, 0x90,
+ 0x8f, 0x96, 0xff, 0x98, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8f, 0x85, 0x00, 0x00, 0x00, 0x01,
+ 0x8e, 0x96, 0xff, 0xc4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x91, 0xd5, 0xf3, 0x02, 0x00, 0x2d,
+ 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x8f, 0x74, 0xc1, 0x74, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x96, 0xff, 0x90, 0x0f, 0xfc, 0x00, 0x01,
+ 0x9f, 0x96, 0xff, 0x90, 0x8e, 0x96, 0xff, 0x9c, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x8f, 0xc5,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xac, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x8f, 0xc5,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xa8, 0x20, 0x7e, 0x00, 0x08, 0xe6, 0x02, 0x91, 0x89,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xa8, 0x20, 0x76, 0x00, 0x10, 0xe6, 0x02, 0x90, 0xf5,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xb8, 0xff, 0xfb, 0x58, 0x00, 0x7f, 0xfd, 0x00, 0x18,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x90, 0x31, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xb8,
+ 0x73, 0x7d, 0xff, 0xe8, 0x8f, 0x96, 0xff, 0xc4, 0x2e, 0xf4, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x90, 0xe5, 0x9e, 0x96, 0xff, 0xb8, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x8a, 0x90, 0x0c, 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8e, 0x96, 0xff, 0xb8, 0x8f, 0x16, 0xff, 0x90, 0xff, 0xf7, 0x58, 0x00, 0x0f, 0x78, 0x00, 0x01,
+ 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8f, 0xdc, 0x9f, 0x16, 0xff, 0x90,
+ 0x8f, 0x96, 0xff, 0xa0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x85, 0xf9, 0x00, 0x00, 0x00, 0x01,
+ 0x8e, 0x96, 0xff, 0xa4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x85, 0xf9, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x96, 0xff, 0xcc, 0xce, 0xf4, 0xfa, 0x00, 0x20, 0x76, 0x00, 0x00, 0xee, 0x02, 0x85, 0xf9,
+ 0x9e, 0x96, 0xff, 0xa4, 0x2e, 0xf4, 0x00, 0x01, 0xcf, 0x84, 0x00, 0x00, 0xc0, 0x76, 0xfa, 0x00,
+ 0xe6, 0x02, 0x85, 0xf9, 0x9e, 0x96, 0xff, 0xa4, 0x8f, 0x16, 0xff, 0xc4, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x02, 0x90, 0xd1, 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0x94, 0x83, 0x96, 0xff, 0xc0,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x90, 0xa0, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x16, 0xff, 0xa4, 0x8e, 0x96, 0xff, 0x90, 0xcf, 0x84, 0x00, 0x00,
+ 0x2f, 0x78, 0x00, 0x01, 0x0e, 0xf4, 0x00, 0x01, 0x9f, 0x16, 0xff, 0xa4, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x02, 0x90, 0x78, 0x9e, 0x96, 0xff, 0x90, 0xe0, 0x02, 0x85, 0xf8, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x96, 0xff, 0xbc, 0x8e, 0x96, 0xff, 0x94, 0xfe, 0xff, 0x64, 0x01, 0xe0, 0x02, 0x90, 0xa4,
+ 0x9f, 0x96, 0xff, 0xbc, 0x8f, 0x16, 0xff, 0xbc, 0xf3, 0x7b, 0x64, 0x01, 0xe0, 0x02, 0x90, 0x10,
+ 0x9f, 0x16, 0xff, 0xbc, 0x8f, 0x16, 0xff, 0xc4, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x91, 0x75,
+ 0xf3, 0x02, 0x00, 0x30, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x91, 0x18,
+ 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x16, 0xff, 0x90,
+ 0x8e, 0x96, 0xff, 0xc4, 0x0f, 0x78, 0x00, 0x01, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x91, 0x61,
+ 0x9f, 0x16, 0xff, 0x90, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf3, 0x02, 0x00, 0x78,
+ 0xf7, 0x8a, 0x91, 0x4c, 0xc1, 0x74, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8e, 0x96, 0xff, 0x90, 0x0e, 0xf4, 0x00, 0x01, 0xe0, 0x02, 0x8f, 0xc4, 0x9e, 0x96, 0xff, 0x90,
+ 0x8f, 0x96, 0xff, 0xbc, 0xf7, 0x82, 0x00, 0x78, 0xf7, 0xff, 0x64, 0x01, 0xe0, 0x02, 0x91, 0x50,
+ 0x9f, 0x96, 0xff, 0xbc, 0x8f, 0x96, 0xff, 0xbc, 0xf7, 0x82, 0x00, 0x30, 0xf7, 0xff, 0x64, 0x01,
+ 0xe0, 0x02, 0x91, 0x1c, 0x9f, 0x96, 0xff, 0xbc, 0x8e, 0x96, 0xff, 0xc4, 0x20, 0x76, 0x00, 0x00,
+ 0xe6, 0x02, 0x91, 0xc1, 0xf3, 0x02, 0x00, 0x30, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x8a, 0x91, 0xac, 0xc1, 0x74, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8f, 0x96, 0xff, 0x90, 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x02, 0x8f, 0xc4, 0x9f, 0x96, 0xff, 0x90,
+ 0x8f, 0x16, 0xff, 0xbc, 0xf7, 0x82, 0x00, 0x30, 0xf7, 0xfb, 0x64, 0x01, 0xe0, 0x02, 0x91, 0xb0,
+ 0x9f, 0x16, 0xff, 0xbc, 0x8f, 0x16, 0xff, 0xbc, 0xf7, 0x82, 0x00, 0x2d, 0xf7, 0xfb, 0x64, 0x01,
+ 0xe0, 0x02, 0x8f, 0x78, 0x9f, 0x16, 0xff, 0xbc, 0x8e, 0x96, 0xff, 0xbc, 0x8f, 0x16, 0xff, 0x94,
+ 0xff, 0x77, 0x64, 0x01, 0xe0, 0x02, 0x8f, 0x1c, 0x9e, 0x96, 0xff, 0xbc, 0x8f, 0x96, 0xff, 0xcc,
+ 0x0f, 0xfc, 0x00, 0x02, 0xe0, 0x02, 0x8e, 0x8c, 0x9f, 0x96, 0xff, 0xcc, 0x8f, 0x96, 0xff, 0xcc,
+ 0xe0, 0x02, 0x92, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xcf, 0x80, 0xfa, 0x00, 0x9e, 0x96, 0xff, 0x98,
+ 0xe0, 0x02, 0x8e, 0x28, 0x9f, 0x96, 0xff, 0xac, 0xe6, 0x02, 0x92, 0x40, 0x20, 0x66, 0x00, 0x00,
+ 0xe6, 0x02, 0x92, 0x40, 0x20, 0x4e, 0x00, 0x00, 0xe6, 0x02, 0x92, 0x51, 0x20, 0x46, 0x00, 0x00,
+ 0x8f, 0xea, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xac, 0xe0, 0x02, 0x8e, 0x18, 0x0d, 0x68, 0x00, 0x04,
+ 0xe6, 0x02, 0x92, 0x65, 0x20, 0x4a, 0x00, 0x00, 0xff, 0xeb, 0x08, 0x02, 0xe0, 0x02, 0x92, 0x48,
+ 0x9f, 0x96, 0xff, 0xac, 0xe6, 0x02, 0x92, 0x79, 0x20, 0x7a, 0x00, 0x00, 0xff, 0xeb, 0x48, 0x03,
+ 0xe0, 0x02, 0x92, 0x48, 0x9f, 0x96, 0xff, 0xac, 0x8f, 0xea, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xac,
+ 0xe6, 0x02, 0x8e, 0x29, 0x0d, 0x68, 0x00, 0x04, 0xe0, 0x02, 0x8e, 0x18, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x96, 0xff, 0xc8, 0xe0, 0x02, 0x88, 0xd4, 0xfc, 0x02, 0x00, 0x01, 0x20, 0x66, 0x00, 0x00,
+ 0xe6, 0x02, 0x92, 0xbd, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xc8, 0xfc, 0x82, 0x00, 0x00,
+ 0xfe, 0xfb, 0x58, 0x00, 0xe0, 0x02, 0x86, 0xac, 0xfb, 0x02, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xc8,
+ 0xe0, 0x02, 0x88, 0xd4, 0xfc, 0x82, 0x00, 0x01, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x02, 0x93, 0x08,
+ 0x20, 0x5a, 0x00, 0x00, 0xe6, 0x02, 0x92, 0xf9, 0x20, 0x66, 0x00, 0x00, 0x8f, 0x16, 0xff, 0x90,
+ 0x8e, 0x6a, 0x00, 0x00, 0x7e, 0xf9, 0xff, 0xe1, 0x9f, 0x72, 0x00, 0x04, 0x9e, 0xf2, 0x00, 0x00,
+ 0xe0, 0x02, 0x85, 0xf8, 0x0d, 0x68, 0x00, 0x04, 0xe6, 0x02, 0x93, 0x54, 0x20, 0x4e, 0x00, 0x00,
+ 0xe6, 0x02, 0x93, 0x1d, 0x20, 0x46, 0x00, 0x00, 0x8f, 0x6a, 0x00, 0x00, 0x8e, 0x96, 0xff, 0x90,
+ 0x0d, 0x68, 0x00, 0x04, 0xe0, 0x02, 0x85, 0xf8, 0x9e, 0xfa, 0x00, 0x00, 0xe6, 0x02, 0x93, 0x39,
+ 0x20, 0x4a, 0x00, 0x00, 0x8f, 0x6a, 0x00, 0x00, 0x8f, 0x96, 0xff, 0x90, 0x0d, 0x68, 0x00, 0x04,
+ 0xe0, 0x02, 0x85, 0xf8, 0xff, 0xfb, 0x28, 0x00, 0xe6, 0x02, 0x93, 0x55, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x6a, 0x00, 0x00, 0x8e, 0x96, 0xff, 0x90, 0x0d, 0x68, 0x00, 0x04, 0xe0, 0x02, 0x85, 0xf8,
+ 0xfe, 0xfb, 0x68, 0x00, 0x8f, 0x6a, 0x00, 0x00, 0x8f, 0x96, 0xff, 0x90, 0x0d, 0x68, 0x00, 0x04,
+ 0xe0, 0x02, 0x85, 0xf8, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0x82, 0x00, 0x08, 0x9e, 0x96, 0xff, 0xa8,
+ 0x20, 0x62, 0x00, 0x00, 0xe6, 0x02, 0x93, 0xd4, 0x20, 0x5a, 0x00, 0x00, 0xe6, 0x02, 0x93, 0x91,
+ 0x20, 0x56, 0x00, 0x00, 0x8f, 0xea, 0x00, 0x04, 0xe0, 0x02, 0x92, 0x20, 0x0d, 0x68, 0x00, 0x08,
+ 0xe6, 0x02, 0x93, 0xd4, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x02, 0x93, 0xd4, 0x20, 0x4e, 0x00, 0x00,
+ 0xe6, 0x02, 0x93, 0xd4, 0x20, 0x46, 0x00, 0x00, 0xe6, 0x02, 0x93, 0xc1, 0x20, 0x4a, 0x00, 0x00,
+ 0xff, 0xeb, 0x18, 0x02, 0x9f, 0x96, 0xff, 0xac, 0xe0, 0x02, 0x8e, 0x28, 0x0d, 0x68, 0x00, 0x04,
+ 0xe6, 0x02, 0x93, 0xd5, 0x00, 0x00, 0x00, 0x01, 0xff, 0xeb, 0x58, 0x03, 0xe0, 0x02, 0x93, 0xb8,
+ 0x9f, 0x96, 0xff, 0xac, 0x8f, 0xea, 0x00, 0x00, 0xe0, 0x02, 0x93, 0xb8, 0x9f, 0x96, 0xff, 0xac,
+ 0x8f, 0xea, 0x00, 0x00, 0x8f, 0x16, 0xff, 0xa4, 0xfe, 0x82, 0x00, 0x10, 0x9f, 0x96, 0xff, 0xac,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x7c, 0x00, 0x03, 0x9f, 0x96, 0xff, 0x9c, 0xe0, 0x02, 0x93, 0xb8,
+ 0x9e, 0x96, 0xff, 0xa8, 0x8f, 0x16, 0xff, 0xc8, 0xe0, 0x02, 0x92, 0xb0, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0xea, 0x00, 0x00, 0x0d, 0x68, 0x00, 0x04, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x96, 0x4d,
+ 0x9f, 0x96, 0xff, 0xb8, 0x20, 0x5e, 0x00, 0x00, 0xe6, 0x02, 0x96, 0x2d, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x02, 0x00, 0x00, 0xc0, 0x72, 0xa2, 0x00, 0xec, 0x02, 0x94, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x8e, 0x96, 0xff, 0xb8, 0xff, 0xf7, 0x48, 0x00, 0xc0, 0x7e, 0xe2, 0x00, 0xe6, 0x02, 0x94, 0x79,
+ 0x00, 0x00, 0x00, 0x01, 0x0e, 0x70, 0x00, 0x01, 0xc0, 0x72, 0xa2, 0x00, 0xec, 0x02, 0x94, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xb8, 0xaf, 0xfa, 0xe0, 0x04, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x94, 0x54, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xa4, 0x8f, 0x96, 0xff, 0xa0,
+ 0xce, 0xf4, 0xe2, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x95, 0x04, 0x9e, 0x96, 0xff, 0xa4,
+ 0x20, 0x76, 0x00, 0x00, 0xee, 0x02, 0x95, 0x05, 0xcf, 0x84, 0x00, 0x00, 0x2e, 0xf4, 0x00, 0x01,
+ 0xc0, 0x76, 0xfa, 0x00, 0xe6, 0x02, 0x95, 0x05, 0x9e, 0x96, 0xff, 0xa4, 0x8f, 0x16, 0xff, 0xc4,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x96, 0x19, 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0x94,
+ 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0x9e, 0x16, 0xff, 0x84, 0xf7, 0x8a, 0x94, 0xd8,
+ 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8e, 0x16, 0xff, 0x84,
+ 0x8f, 0x16, 0xff, 0xa4, 0x8e, 0x96, 0xff, 0x90, 0xcf, 0x84, 0x00, 0x00, 0x2f, 0x78, 0x00, 0x01,
+ 0x0e, 0xf4, 0x00, 0x01, 0x9f, 0x16, 0xff, 0xa4, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x02, 0x94, 0xac,
+ 0x9e, 0x96, 0xff, 0x90, 0x2e, 0x70, 0x00, 0x01, 0xcf, 0x84, 0x00, 0x00, 0xc0, 0x72, 0xfa, 0x00,
+ 0xe6, 0x02, 0x95, 0x6d, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xb8, 0x8f, 0x96, 0xff, 0xc4,
+ 0xf3, 0x7b, 0x44, 0x01, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x96, 0x09, 0x9f, 0x16, 0xff, 0xb8,
+ 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0x9e, 0x16, 0xff, 0x84, 0xf7, 0x8a, 0x95, 0x48,
+ 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8e, 0x16, 0xff, 0x84,
+ 0x8f, 0x96, 0xff, 0x90, 0x2e, 0x70, 0x00, 0x01, 0xcf, 0x04, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x01,
+ 0xc0, 0x72, 0xf2, 0x00, 0xe6, 0x02, 0x95, 0x18, 0x9f, 0x96, 0xff, 0x90, 0x8e, 0x96, 0xff, 0xa0,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x85, 0xf9, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xa4,
+ 0x20, 0x7a, 0x00, 0x00, 0xee, 0x02, 0x85, 0xf9, 0x2f, 0x78, 0x00, 0x01, 0xcf, 0x84, 0x00, 0x00,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x02, 0x85, 0xf9, 0x9f, 0x16, 0xff, 0xa4, 0x8f, 0x96, 0xff, 0xc4,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x95, 0xf5, 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0x94,
+ 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x95, 0xc4, 0xc1, 0x7c, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x96, 0xff, 0xa4, 0x8f, 0x16, 0xff, 0x90,
+ 0xce, 0x84, 0x00, 0x00, 0x2f, 0xfc, 0x00, 0x01, 0x0f, 0x78, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xa4,
+ 0xc0, 0x7e, 0xea, 0x00, 0xe6, 0x02, 0x95, 0x9c, 0x9f, 0x16, 0xff, 0x90, 0xe0, 0x02, 0x85, 0xf8,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xbc, 0x8f, 0x16, 0xff, 0x94, 0xff, 0x77, 0x64, 0x01,
+ 0xe0, 0x02, 0x95, 0xc8, 0x9e, 0x96, 0xff, 0xbc, 0x8e, 0x96, 0xff, 0xbc, 0xf3, 0x77, 0x64, 0x01,
+ 0xe0, 0x02, 0x95, 0x50, 0x9e, 0x96, 0xff, 0xbc, 0x8f, 0x96, 0xff, 0xbc, 0x8e, 0x96, 0xff, 0x94,
+ 0xfe, 0xff, 0x64, 0x01, 0xe0, 0x02, 0x94, 0xe0, 0x9f, 0x96, 0xff, 0xbc, 0x83, 0x16, 0xff, 0xb8,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x96, 0x40, 0xe0, 0x02, 0x84, 0x28, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x02, 0x94, 0x78, 0xce, 0x20, 0x00, 0x00, 0xff, 0x8a, 0x85, 0xac,
+ 0xe0, 0x02, 0x94, 0x24, 0x9f, 0x96, 0xff, 0xb8, 0x8f, 0x96, 0xff, 0xc8, 0xe0, 0x02, 0x88, 0xd4,
+ 0xfa, 0x82, 0x00, 0x01, 0xe0, 0x02, 0x93, 0x6c, 0xfe, 0x82, 0x00, 0x0a, 0x8f, 0x16, 0xff, 0xc8,
+ 0xc0, 0x6e, 0xf2, 0x00, 0xe4, 0x02, 0x85, 0xf9, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xc4,
+ 0xf3, 0x6f, 0x44, 0x01, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x96, 0xd1, 0x00, 0x00, 0x00, 0x01,
+ 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0x9d, 0x96, 0xff, 0x88, 0xf7, 0x8a, 0x96, 0xa8,
+ 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8d, 0x96, 0xff, 0x88,
+ 0x8f, 0x96, 0xff, 0x90, 0x8f, 0x16, 0xff, 0xc8, 0x0f, 0xfc, 0x00, 0x01, 0xc0, 0x6e, 0xf2, 0x00,
+ 0xe4, 0x02, 0x96, 0x7c, 0x9f, 0x96, 0xff, 0x90, 0xe0, 0x02, 0x85, 0xf8, 0x00, 0x00, 0x00, 0x01,
+ 0x8e, 0x96, 0xff, 0xbc, 0xf3, 0x77, 0x64, 0x01, 0xe0, 0x02, 0x96, 0xb0, 0x9e, 0x96, 0xff, 0xbc,
+ 0xff, 0x02, 0x00, 0x10, 0xe0, 0x02, 0x93, 0x70, 0x9f, 0x16, 0xff, 0xa8, 0xff, 0x82, 0x00, 0x10,
+ 0xe0, 0x02, 0x8d, 0xf4, 0x9f, 0x96, 0xff, 0xa8, 0x8f, 0x16, 0xff, 0xc8, 0xe0, 0x02, 0x88, 0x48,
+ 0xf9, 0x82, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xbc, 0xf3, 0x7b, 0x64, 0x01, 0xe0, 0x02, 0x86, 0x50,
+ 0x9f, 0x16, 0xff, 0xbc, 0xe0, 0x02, 0x85, 0xf8, 0x9f, 0x96, 0xff, 0xc8, 0x84, 0x16, 0xff, 0x90,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x4d, 0x43, 0x50, 0x20,
+ 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x32, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69,
+ 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x4d, 0x43, 0x50, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74,
+ 0x66, 0x3a, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x63, 0x2d, 0x72,
+ 0x65, 0x73, 0x65, 0x74, 0x20, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x25, 0x64, 0x2e, 0x25,
+ 0x30, 0x36, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0xe8, 0xfe, 0xf6, 0xe9, 0xe8, 0x8f, 0xf6, 0x00, 0x08, 0x0f, 0x01, 0x70, 0x72,
+ 0x0f, 0x78, 0x69, 0x6e, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x02, 0x98, 0x19, 0x2f, 0x94, 0x00, 0x70,
+ 0x22, 0x10, 0x00, 0x0c, 0x9f, 0x92, 0x00, 0x00, 0xff, 0x8a, 0x97, 0x2c, 0x9f, 0x92, 0x00, 0x04,
+ 0x8f, 0xf6, 0x00, 0x08, 0x9e, 0x96, 0xff, 0x24, 0x9f, 0x92, 0x00, 0x08, 0x9f, 0x16, 0xff, 0x20,
+ 0xf7, 0x8a, 0x97, 0xdc, 0xe0, 0x02, 0x9b, 0x44, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0x24,
+ 0x8f, 0x16, 0xff, 0x20, 0xff, 0xf6, 0xc9, 0xe8, 0x23, 0x14, 0x00, 0x70, 0x9f, 0x76, 0x00, 0x08,
+ 0x9f, 0xf6, 0x00, 0x14, 0x90, 0x76, 0x00, 0x04, 0x90, 0x76, 0x00, 0x0c, 0x90, 0x76, 0x00, 0x10,
+ 0x02, 0x10, 0x00, 0x0c, 0xf7, 0x8a, 0x98, 0x10, 0xe0, 0x02, 0x99, 0x1c, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x02, 0x98, 0xa0, 0xf0, 0x09, 0xba, 0x38, 0xff, 0x88, 0xba, 0x38, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x98, 0x9d, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x02, 0xff, 0xd0, 0x4f, 0x85, 0x00, 0x4f,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe2, 0x02, 0x98, 0x9c, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x76, 0x00, 0x00,
+ 0x8f, 0x82, 0xff, 0xd0, 0xc0, 0x7a, 0xfa, 0x00, 0xe2, 0x02, 0x98, 0x9d, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0xf6, 0x00, 0x04, 0x22, 0x10, 0x00, 0x10, 0xcf, 0xfc, 0xf0, 0x00, 0x9f, 0xf6, 0x00, 0x04,
+ 0x7f, 0xfc, 0xff, 0xff, 0x4f, 0x7d, 0x00, 0x0f, 0x7f, 0xfc, 0xff, 0xec, 0x9f, 0x92, 0x00, 0x08,
+ 0x2f, 0x94, 0x00, 0xd8, 0x9f, 0x92, 0x00, 0x00, 0xff, 0x8a, 0x97, 0x57, 0x9f, 0x12, 0x00, 0x0c,
+ 0x9f, 0x92, 0x00, 0x04, 0xf7, 0x8a, 0x98, 0x90, 0xe0, 0x02, 0x9b, 0x44, 0x97, 0x93, 0xff, 0xfc,
+ 0x23, 0x14, 0x00, 0xd8, 0xe0, 0x02, 0x98, 0x04, 0x02, 0x10, 0x00, 0x10, 0xf0, 0x09, 0xba, 0x38,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x02, 0x98, 0xd9, 0xfe, 0x76, 0xe9, 0xe8,
+ 0x8f, 0x1e, 0x00, 0x00, 0xf3, 0x7b, 0x68, 0x00, 0x8f, 0x9e, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x01,
+ 0xe0, 0x02, 0x99, 0x10, 0x9f, 0x9e, 0x00, 0x00, 0x8e, 0xf2, 0x00, 0x0c, 0x8d, 0x72, 0x00, 0x14,
+ 0xff, 0x82, 0x1f, 0xff, 0xcd, 0xf4, 0xfc, 0x00, 0xcf, 0x68, 0xd8, 0x00, 0x0f, 0x79, 0xff, 0xf0,
+ 0xff, 0xb6, 0xe9, 0xe8, 0xc0, 0x7a, 0xfa, 0x00, 0xe2, 0x02, 0x99, 0x04, 0x0e, 0xf4, 0x00, 0x01,
+ 0xb3, 0x6a, 0xd8, 0x04, 0x8f, 0x82, 0xff, 0xd0, 0x9e, 0xf2, 0x00, 0x0c, 0x9f, 0xf2, 0x00, 0x00,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0x93, 0x16, 0xff, 0xf4, 0xff, 0x9b, 0x58, 0x00,
+ 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x99, 0x6d, 0x00, 0x00, 0x00, 0x01,
+ 0x73, 0x7d, 0xff, 0xe8, 0xf3, 0x82, 0x00, 0x00, 0xf7, 0x8a, 0x99, 0x54, 0xe0, 0x02, 0x98, 0xac,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4, 0xff, 0xfb, 0x5c, 0x01, 0x7f, 0xfd, 0x00, 0x18,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x99, 0x40, 0x9f, 0x16, 0xff, 0xf4, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x08, 0x93, 0x16, 0xff, 0xf4, 0xff, 0x9b, 0x58, 0x00, 0xff, 0x02, 0x00, 0x00,
+ 0x7f, 0xfd, 0x00, 0x18, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x02, 0x99, 0xd9, 0x9f, 0x16, 0xff, 0xf0,
+ 0x73, 0x7d, 0xff, 0xe8, 0xf3, 0x82, 0x00, 0x00, 0xf7, 0x8a, 0x99, 0xb4, 0xe0, 0x02, 0x98, 0xac,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4, 0xff, 0xfb, 0x5c, 0x01, 0x9f, 0x16, 0xff, 0xf4,
+ 0x8f, 0x16, 0xff, 0xf0, 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00, 0x0f, 0x78, 0x00, 0x01,
+ 0xe6, 0x02, 0x99, 0xa0, 0x9f, 0x16, 0xff, 0xf0, 0x84, 0x16, 0xff, 0xf0, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x25, 0x64, 0x2e, 0x25, 0x30, 0x36, 0x64, 0x3a,
+ 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x3c,
+ 0x92, 0x96, 0xff, 0xd0, 0xce, 0x94, 0x00, 0x00, 0x8f, 0x02, 0xff, 0xd0, 0x8f, 0xf5, 0x00, 0x04,
+ 0x9e, 0x96, 0xff, 0xd0, 0x2e, 0x94, 0x00, 0x28, 0x9f, 0x96, 0x00, 0x00, 0x9e, 0x96, 0xff, 0xd4,
+ 0x9f, 0x16, 0xff, 0xcc, 0xf7, 0x8a, 0x9a, 0x30, 0xe0, 0x02, 0x97, 0x88, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0xf6, 0xe9, 0xe8, 0x8e, 0xfe, 0x00, 0x04, 0x8f, 0x16, 0xff, 0xcc, 0x22, 0x10, 0x00, 0x10,
+ 0xcf, 0x78, 0xe8, 0x00, 0x7f, 0xf8, 0xff, 0xff, 0x7f, 0x78, 0xff, 0xeb, 0x4f, 0xfd, 0x00, 0x0f,
+ 0x9f, 0x12, 0x00, 0x08, 0x9f, 0x92, 0x00, 0x0c, 0x2f, 0x14, 0x00, 0x28, 0xff, 0x8a, 0x99, 0xe8,
+ 0x9f, 0x12, 0x00, 0x00, 0x9f, 0x92, 0x00, 0x04, 0xf7, 0x8a, 0x9a, 0x74, 0xe0, 0x02, 0x9b, 0x44,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xd4, 0x2e, 0x94, 0x00, 0x28, 0x2f, 0x94, 0x00, 0x0a,
+ 0xb0, 0x76, 0x40, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe4, 0x02, 0x9a, 0xe9, 0x02, 0x10, 0x00, 0x10,
+ 0xff, 0x97, 0x4b, 0xd8, 0xff, 0x17, 0x5b, 0xd8, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x9a, 0xe9,
+ 0xcf, 0xf8, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x18, 0x73, 0x7d, 0xff, 0xe8, 0xf3, 0x82, 0x00, 0x00,
+ 0xf7, 0x8a, 0x9a, 0xbc, 0xe0, 0x02, 0x98, 0xac, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xd4,
+ 0x2f, 0x14, 0x00, 0x0a, 0x0e, 0xf4, 0x00, 0x01, 0xc0, 0x76, 0xf2, 0x00, 0xe4, 0x02, 0x9a, 0xe9,
+ 0x9e, 0x96, 0xff, 0xd4, 0xff, 0xf7, 0x58, 0x00, 0x7f, 0x7d, 0x00, 0x18, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x02, 0x9a, 0xa8, 0x7f, 0xfd, 0x00, 0x18, 0x83, 0x16, 0x00, 0x00, 0x84, 0x96, 0xff, 0xd0,
+ 0xf3, 0x8a, 0x98, 0xac, 0xf4, 0x02, 0x00, 0x00, 0xf7, 0x8a, 0x9b, 0x04, 0xe0, 0x02, 0x85, 0xb4,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04,
+ 0x22, 0x10, 0x00, 0x04, 0xff, 0x8a, 0x9b, 0x10, 0x9f, 0x92, 0x00, 0x00, 0xf7, 0x8a, 0x9b, 0x38,
+ 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x83, 0x16, 0x00, 0x04,
+ 0x04, 0x94, 0x00, 0x08, 0xf3, 0x8a, 0x98, 0xac, 0xc4, 0x14, 0x00, 0x00, 0xf7, 0x8a, 0x9b, 0x68,
+ 0xe0, 0x02, 0x85, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04,
+ 0x93, 0x16, 0xff, 0xf4, 0xc4, 0xa0, 0x00, 0x00, 0xc3, 0x1c, 0x00, 0x00, 0xf3, 0x8a, 0x98, 0xac,
+ 0x24, 0x14, 0x00, 0x0c, 0xf7, 0x8a, 0x9b, 0xa0, 0xe0, 0x02, 0x85, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x25, 0x63, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0xff, 0x8a, 0x9b, 0xac, 0x93, 0x12, 0x00, 0x04, 0x9f, 0x92, 0x00, 0x00, 0xf7, 0x8a, 0x9b, 0xd8,
+ 0xe0, 0x02, 0x99, 0xf4, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf7, 0x8a, 0x9b, 0xfc, 0xe0, 0x02, 0x9e, 0xd0, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x24, 0x20, 0x00, 0x01, 0xcf, 0x04, 0x00, 0x00, 0xc0, 0x22, 0xf2, 0x00, 0xe6, 0x02, 0x9c, 0x35,
+ 0xcf, 0x98, 0x00, 0x00, 0x24, 0x20, 0x00, 0x01, 0xc0, 0x22, 0xf2, 0x00, 0xe6, 0x02, 0x9c, 0x24,
+ 0xf3, 0xff, 0x64, 0x01, 0xc4, 0x18, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x9c, 0xfd, 0xce, 0x20, 0x00, 0x00, 0x24, 0x22, 0x00, 0x01,
+ 0xe6, 0x02, 0x9c, 0xf1, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x1b, 0x48, 0x00, 0xff, 0x1b, 0x58, 0x00,
+ 0x20, 0x72, 0x00, 0x00, 0xe6, 0x02, 0x9c, 0xe5, 0x00, 0x00, 0x00, 0x01, 0xff, 0x9f, 0x48, 0x00,
+ 0xfe, 0x9f, 0x58, 0x00, 0xc0, 0x72, 0xfa, 0x00, 0xe6, 0x02, 0x9c, 0xa5, 0x7f, 0x79, 0x00, 0x18,
+ 0x7e, 0xf5, 0x00, 0x18, 0x7e, 0x79, 0xff, 0xe8, 0x7f, 0xf5, 0xff, 0xe8, 0xe0, 0x02, 0x9c, 0xfc,
+ 0xce, 0x70, 0xfa, 0x00, 0x03, 0x18, 0x00, 0x01, 0x24, 0x22, 0x00, 0x01, 0xe6, 0x02, 0x9c, 0xf1,
+ 0x03, 0x9c, 0x00, 0x01, 0xfe, 0x1b, 0x48, 0x00, 0xff, 0x1b, 0x58, 0x00, 0x20, 0x72, 0x00, 0x00,
+ 0xe6, 0x02, 0x9c, 0xe5, 0x00, 0x00, 0x00, 0x01, 0xff, 0x9f, 0x48, 0x00, 0xfe, 0x9f, 0x58, 0x00,
+ 0xc0, 0x72, 0xfa, 0x00, 0xe6, 0x02, 0x9c, 0xa5, 0x7f, 0x79, 0x00, 0x18, 0xe0, 0x02, 0x9c, 0x94,
+ 0x7e, 0xf5, 0x00, 0x18, 0xfe, 0x9f, 0x58, 0x00, 0xe0, 0x02, 0x9c, 0x90, 0x7f, 0x79, 0x00, 0x18,
+ 0xff, 0x1b, 0x58, 0x00, 0xe0, 0x02, 0x9c, 0xe4, 0x00, 0x00, 0x00, 0x01, 0xc4, 0x70, 0x00, 0x00,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x9b, 0x44, 0x01, 0xf4, 0x02, 0x00, 0x00,
+ 0xc0, 0x7e, 0x42, 0x00, 0xe6, 0x02, 0x9d, 0x3d, 0x00, 0x00, 0x00, 0x01, 0xff, 0x9b, 0x44, 0x01,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x9d, 0x2c, 0x04, 0x20, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x24, 0x20, 0x00, 0x01, 0xcf, 0x04, 0x00, 0x00, 0xc0, 0x22, 0xf2, 0x00, 0xe6, 0x02, 0x9d, 0x79,
+ 0xcf, 0x98, 0x00, 0x00, 0xfe, 0x9f, 0x54, 0x01, 0x24, 0x20, 0x00, 0x01, 0xc0, 0x22, 0xf2, 0x00,
+ 0xe6, 0x02, 0x9d, 0x64, 0xfe, 0xff, 0x64, 0x01, 0xc4, 0x18, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x10, 0xff, 0x1b, 0x58, 0x00, 0xcc, 0x98, 0x00, 0x00, 0x2f, 0xf8, 0x00, 0x30,
+ 0x93, 0x96, 0xff, 0xf4, 0x7f, 0xfd, 0x00, 0x18, 0x94, 0x16, 0xff, 0xf0, 0x20, 0x7f, 0x09, 0x00,
+ 0xe2, 0x02, 0x9e, 0x7c, 0xf3, 0x82, 0x00, 0x00, 0x7f, 0xf9, 0x00, 0x18, 0x7f, 0x7d, 0xff, 0xe8,
+ 0x2d, 0x78, 0x00, 0x30, 0x8f, 0x96, 0xff, 0xf0, 0xc0, 0x6a, 0xfa, 0x00, 0xec, 0x02, 0x9e, 0x64,
+ 0x0c, 0xe4, 0x00, 0x01, 0x83, 0x16, 0xff, 0xf0, 0x9c, 0x96, 0xff, 0xec, 0x9d, 0x16, 0xff, 0xe8,
+ 0xf7, 0x8a, 0x9d, 0xec, 0xe0, 0x02, 0xa1, 0xac, 0x97, 0x93, 0xff, 0xfc, 0x8c, 0x96, 0xff, 0xec,
+ 0x8d, 0x16, 0xff, 0xe8, 0xfd, 0xe7, 0x58, 0x00, 0xc3, 0xa0, 0xd0, 0x00, 0x7e, 0x6d, 0x00, 0x18,
+ 0x2f, 0xec, 0x00, 0x30, 0x2f, 0x6c, 0x00, 0x61, 0x7f, 0xfd, 0x00, 0x18, 0x7e, 0xf1, 0xff, 0xe8,
+ 0x7f, 0x79, 0x00, 0x18, 0x20, 0x7f, 0x09, 0x00, 0xe2, 0x02, 0x9e, 0x55, 0x2d, 0x74, 0x00, 0x30,
+ 0x7f, 0xed, 0x00, 0x18, 0x20, 0x7b, 0x19, 0x00, 0x2e, 0xec, 0x00, 0x41, 0x7f, 0x7d, 0xff, 0xe8,
+ 0x7e, 0xf5, 0x00, 0x18, 0xe2, 0x02, 0x9e, 0x55, 0x2d, 0x78, 0x00, 0x57, 0x7f, 0xed, 0x00, 0x18,
+ 0x20, 0x77, 0x19, 0x00, 0xfd, 0x02, 0x00, 0x7f, 0xe2, 0x02, 0x9e, 0x54, 0x7e, 0x7d, 0xff, 0xe8,
+ 0x2d, 0x70, 0x00, 0x37, 0x8f, 0x96, 0xff, 0xf0, 0xc0, 0x6a, 0xfa, 0x00, 0xec, 0x02, 0x9d, 0xd5,
+ 0x0c, 0xe4, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xf4, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x9e, 0xc1,
+ 0x2c, 0xe4, 0x00, 0x01, 0xe0, 0x02, 0x9e, 0xc0, 0x9c, 0xfe, 0x00, 0x00, 0x2f, 0xf8, 0x00, 0x61,
+ 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7f, 0x19, 0x00, 0xe2, 0x02, 0x9e, 0xa0, 0x2f, 0xf8, 0x00, 0x41,
+ 0x7f, 0xf9, 0x00, 0x18, 0x7f, 0x7d, 0xff, 0xe8, 0xe0, 0x02, 0x9d, 0xc4, 0x2d, 0x78, 0x00, 0x57,
+ 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7f, 0x19, 0x00, 0xe2, 0x02, 0x9d, 0xc4, 0xfd, 0x02, 0x00, 0x7f,
+ 0x7f, 0xf9, 0x00, 0x18, 0x7f, 0x7d, 0xff, 0xe8, 0xe0, 0x02, 0x9d, 0xc4, 0x2d, 0x78, 0x00, 0x37,
+ 0xc4, 0x1c, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10, 0xff, 0x02, 0x00, 0x00,
+ 0x94, 0x16, 0xff, 0xec, 0x93, 0x16, 0xff, 0xf4, 0x93, 0x96, 0xff, 0xf0, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x02, 0x9f, 0x19, 0x9f, 0x16, 0xff, 0xe8, 0x2f, 0xa0, 0x00, 0x02, 0x20, 0x7e, 0x00, 0x22,
+ 0xe2, 0x02, 0x9f, 0x19, 0x00, 0x00, 0x00, 0x01, 0x93, 0x1e, 0x00, 0x00, 0x84, 0x16, 0xff, 0xe8,
+ 0xe0, 0x02, 0xa1, 0x64, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xf4, 0xf3, 0x7b, 0x48, 0x00,
+ 0xf7, 0x8a, 0x9f, 0x2c, 0xe0, 0x02, 0xa2, 0x18, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x02, 0x9f, 0x49, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xf4, 0x0f, 0xfc, 0x00, 0x01,
+ 0xe0, 0x02, 0x9f, 0x18, 0x9f, 0x96, 0xff, 0xf4, 0x8f, 0x16, 0xff, 0xf4, 0xff, 0xfb, 0x48, 0x00,
+ 0x20, 0x7e, 0x00, 0x2b, 0xe6, 0x02, 0xa1, 0x5d, 0x0f, 0x78, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x2d,
+ 0xe6, 0x02, 0xa1, 0x51, 0xff, 0x82, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xec, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0xa1, 0x1d, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x02, 0xa1, 0x1d, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x16, 0xff, 0xec, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x9f, 0xb8, 0x20, 0x7a, 0x00, 0x20,
+ 0x8f, 0x16, 0xff, 0xf4, 0xff, 0xfb, 0x48, 0x00, 0xff, 0x02, 0x00, 0x08, 0x20, 0x7e, 0x00, 0x30,
+ 0xe6, 0x02, 0x9f, 0xc1, 0x9f, 0x16, 0xff, 0xec, 0xff, 0x82, 0x00, 0x0a, 0x9f, 0x96, 0xff, 0xec,
+ 0x8f, 0x16, 0xff, 0xec, 0x20, 0x7a, 0x00, 0x20, 0xe2, 0x02, 0xa0, 0xec, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x16, 0xff, 0xec, 0x7f, 0xf9, 0x00, 0x02, 0xff, 0x0a, 0x9f, 0xd8, 0xae, 0xfe, 0xf0, 0x02,
+ 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec,
+ 0x00, 0x02, 0xa0, 0x5c, 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0x74, 0x00, 0x02, 0xa0, 0xec,
+ 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0x8c, 0x00, 0x02, 0xa0, 0xec,
+ 0x00, 0x02, 0xa0, 0xa4, 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec,
+ 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xbc, 0x00, 0x02, 0xa0, 0xec,
+ 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec,
+ 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec,
+ 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec,
+ 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xec, 0x00, 0x02, 0xa0, 0xd4, 0x83, 0x16, 0xff, 0xf4,
+ 0x83, 0x96, 0xff, 0xf0, 0xf4, 0x02, 0x00, 0x02, 0xf7, 0x8a, 0xa0, 0x74, 0xe0, 0x02, 0x9d, 0x88,
+ 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4, 0x83, 0x96, 0xff, 0xf0, 0xf4, 0x02, 0x00, 0x04,
+ 0xf7, 0x8a, 0xa0, 0x8c, 0xe0, 0x02, 0x9d, 0x88, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0x83, 0x96, 0xff, 0xf0, 0xf4, 0x02, 0x00, 0x08, 0xf7, 0x8a, 0xa0, 0xa4, 0xe0, 0x02, 0x9d, 0x88,
+ 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4, 0x83, 0x96, 0xff, 0xf0, 0xf4, 0x02, 0x00, 0x0a,
+ 0xf7, 0x8a, 0xa0, 0xbc, 0xe0, 0x02, 0x9d, 0x88, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0x83, 0x96, 0xff, 0xf0, 0xf4, 0x02, 0x00, 0x10, 0xf7, 0x8a, 0xa0, 0xd4, 0xe0, 0x02, 0x9d, 0x88,
+ 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4, 0x83, 0x96, 0xff, 0xf0, 0xf4, 0x02, 0x00, 0x20,
+ 0xf7, 0x8a, 0xa0, 0xec, 0xe0, 0x02, 0x9d, 0x88, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0x83, 0x96, 0xff, 0xf0, 0x84, 0x16, 0xff, 0xec, 0xf7, 0x8a, 0xa1, 0x04, 0xe0, 0x02, 0x9d, 0x88,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xe8, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0xa1, 0x65,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0xa1, 0x64, 0xc4, 0x00, 0x42, 0x00, 0x8f, 0x16, 0xff, 0xf4,
+ 0xff, 0xfb, 0x48, 0x00, 0x20, 0x7e, 0x00, 0x30, 0xe6, 0x02, 0x9f, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0xfb, 0x48, 0x01, 0x20, 0x7e, 0x00, 0x78, 0xe6, 0x02, 0x9f, 0x80, 0x0f, 0x78, 0x00, 0x02,
+ 0xff, 0x82, 0x00, 0x10, 0x9f, 0x96, 0xff, 0xec, 0xe0, 0x02, 0x9f, 0x80, 0x9f, 0x16, 0xff, 0xf4,
+ 0x8f, 0x16, 0xff, 0xf4, 0x9f, 0x96, 0xff, 0xe8, 0xcf, 0x78, 0xf8, 0x00, 0xe0, 0x02, 0x9f, 0x68,
+ 0x9f, 0x16, 0xff, 0xf4, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf4, 0x02, 0x00, 0x00, 0xff, 0x82, 0x00, 0x01,
+ 0xc0, 0x1a, 0xfc, 0x00, 0xe6, 0x02, 0xa1, 0x91, 0x73, 0x18, 0xff, 0xff, 0xc4, 0x20, 0x38, 0x00,
+ 0x73, 0x9d, 0x00, 0x01, 0xc0, 0x1a, 0x3d, 0x00, 0xe6, 0x02, 0xa1, 0x84, 0xc0, 0x1a, 0xfc, 0x00,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x20, 0x1a, 0x00, 0x00, 0xec, 0x02, 0xa1, 0xf5, 0x20, 0x1e, 0x00, 0x00,
+ 0xec, 0x02, 0xa1, 0xdd, 0xcf, 0x80, 0x3a, 0x00, 0xf7, 0x8a, 0xa1, 0xd4, 0xe0, 0x02, 0xa1, 0x70,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0xa2, 0x08, 0x00, 0x00, 0x00, 0x01, 0xc3, 0xfc, 0x00, 0x00,
+ 0xf7, 0x8a, 0xa1, 0xec, 0xe0, 0x02, 0xa1, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0xa2, 0x08,
+ 0xc4, 0x00, 0x42, 0x00, 0xc3, 0x00, 0x32, 0x00, 0xec, 0x02, 0xa1, 0xe0, 0xce, 0x80, 0x3a, 0x00,
+ 0xe0, 0x02, 0xa1, 0xc8, 0xc3, 0xf4, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x20, 0x1a, 0x00, 0x20, 0xe6, 0x02, 0xa2, 0x59, 0xf4, 0x02, 0x00, 0x00, 0x20, 0x1a, 0x00, 0x0c,
+ 0xe6, 0x02, 0xa2, 0x59, 0x20, 0x1a, 0x00, 0x0a, 0xe6, 0x02, 0xa2, 0x59, 0x20, 0x1a, 0x00, 0x0d,
+ 0xe6, 0x02, 0xa2, 0x59, 0x20, 0x1a, 0x00, 0x09, 0xe6, 0x02, 0xa2, 0x59, 0x20, 0x1a, 0x00, 0x0b,
+ 0xe6, 0x02, 0xa2, 0x5c, 0x00, 0x00, 0x00, 0x01, 0xf4, 0x02, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x09, 0x14, 0xc1, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x46,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x11, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x09, 0x14, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00,
+ 0x00, 0x80, 0x54, 0x05, 0x00, 0x00, 0x13, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x5c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x03,
+ 0x64, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0xa0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x78, 0xff,
+ 0x00, 0x00, 0x28, 0x10, 0x00, 0x00, 0x13, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0xf4, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1c, 0xd0, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xa8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x7f, 0x00, 0x11, 0x00, 0x00, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0f, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0f, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1a, 0x81, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x31,
+ 0x00, 0x06, 0x20, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0xc1, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0xc1,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40,
+ 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x18, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08,
+ 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x14, 0xc1, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x86, 0x14, 0x00, 0x00, 0x86, 0x20, 0x00, 0x00, 0x86, 0x2c, 0x00, 0x00, 0x86, 0x2f,
+ 0x00, 0x00, 0x86, 0x3b, 0x00, 0x00, 0x86, 0x45, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0xf8, 0xe0, 0x00, 0x00, 0xfa, 0x18, 0x00, 0x00, 0xf9, 0x7c, 0x00, 0x00, 0xfa, 0xb4,
+ 0x00, 0x00, 0xfb, 0x48, 0x00, 0x00, 0xfd, 0xf0, 0x00, 0x00, 0xfc, 0x9c, 0x00, 0x00, 0xff, 0x44,
+ 0xe0, 0x01, 0x0e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x45, 0x54, 0x48, 0x20,
+ 0x31, 0x2e, 0x34, 0x2e, 0x32, 0x36, 0x20, 0x2d, 0x50, 0x2d, 0x20, 0x32, 0x30, 0x30, 0x37, 0x2f,
+ 0x31, 0x30, 0x2f, 0x33, 0x30, 0x20, 0x32, 0x33, 0x3a, 0x35, 0x39, 0x3a, 0x35, 0x37, 0x20, 0x6d,
+ 0x79, 0x72, 0x69, 0x31, 0x30, 0x67, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1d, 0xfe, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x00, 0x02, 0xaa, 0xa8, 0x00, 0x00, 0x01, 0xa0, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x28,
+ 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x5a, 0x0c, 0x00, 0x01, 0x57, 0x00, 0x00, 0x01, 0x52, 0x54,
+ 0x00, 0x01, 0x4c, 0x38, 0x00, 0x01, 0x44, 0xac, 0x00, 0x01, 0x78, 0xd4, 0x00, 0x01, 0x75, 0xb0,
+ 0x00, 0x01, 0x70, 0xec, 0x00, 0x01, 0x6a, 0xb8, 0x00, 0x01, 0x63, 0x14, 0x00, 0x01, 0x78, 0xd4,
+ 0x00, 0x01, 0x75, 0xb0, 0x00, 0x01, 0x70, 0xec, 0x00, 0x01, 0x6a, 0xb8, 0x00, 0x01, 0x81, 0xf0,
+ 0x00, 0x01, 0x78, 0xd4, 0x00, 0x01, 0x9e, 0x30, 0x00, 0x01, 0x99, 0x4c, 0x00, 0x01, 0x92, 0xfc,
+ 0x00, 0x01, 0x8b, 0x1c, 0x00, 0x01, 0x78, 0xd4, 0x00, 0x01, 0xa9, 0x54, 0x00, 0x01, 0xa4, 0x5c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+};
diff --git a/sys/src/9/pc/etherm10g4k.i b/sys/src/9/pc/etherm10g4k.i
new file mode 100755
index 000000000..b755e8105
--- /dev/null
+++ b/sys/src/9/pc/etherm10g4k.i
@@ -0,0 +1,10871 @@
+static char fw4k[] ={
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xa5, 0xa0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf2, 0x02, 0x04, 0x00, 0xc2, 0x90, 0x00, 0x00, 0xf7, 0x82, 0x08, 0x18, 0xe0, 0x01, 0x0b, 0x50,
+ 0x97, 0x93, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x08, 0x18, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x73, 0x18, 0xff, 0xfe, 0x7f, 0x19, 0x00, 0x04, 0xff, 0x8a, 0x8f, 0x80, 0xfe, 0x82, 0xff, 0x00,
+ 0xcf, 0x78, 0xf8, 0x00, 0x20, 0x1a, 0x00, 0x7f, 0xe2, 0x00, 0x08, 0x78, 0xf4, 0x02, 0x00, 0x00,
+ 0x8e, 0x7a, 0x00, 0x08, 0x7f, 0x70, 0xff, 0xf8, 0xcf, 0x78, 0xec, 0x00, 0xce, 0xf0, 0xec, 0x00,
+ 0x7f, 0xf0, 0xff, 0xe8, 0xcf, 0xfc, 0xf5, 0x00, 0x7e, 0xf5, 0x00, 0x08, 0xcf, 0xfc, 0xed, 0x00,
+ 0x7e, 0x71, 0x00, 0x18, 0xc4, 0x7c, 0xe5, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x02, 0xff, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf8, 0xcf, 0x78, 0xe4, 0x00, 0xce, 0x9c, 0xe4, 0x00, 0x7f, 0x9c, 0xff, 0xe8,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x7e, 0xf5, 0x00, 0x08, 0xcf, 0xfc, 0xed, 0x00, 0x7f, 0x1d, 0x00, 0x18,
+ 0xcd, 0xfc, 0xf5, 0x00, 0xff, 0x82, 0x00, 0x0f, 0x74, 0x98, 0xff, 0xfe, 0xc4, 0x20, 0xfc, 0x00,
+ 0xfc, 0x0a, 0x8f, 0x80, 0x7c, 0xa5, 0x00, 0x04, 0x7f, 0x21, 0x00, 0x02, 0xcd, 0x64, 0xc0, 0x00,
+ 0x20, 0x26, 0x00, 0x7f, 0xe2, 0x00, 0x09, 0x40, 0xf4, 0x02, 0x00, 0x00, 0x84, 0x6a, 0x00, 0x08,
+ 0xa3, 0x66, 0xc0, 0x02, 0xff, 0x8a, 0x97, 0x80, 0xae, 0xfa, 0xf8, 0x02, 0x83, 0xea, 0x00, 0x04,
+ 0xc3, 0x18, 0x44, 0x00, 0xc3, 0x18, 0xdc, 0x00, 0xcf, 0x98, 0x3d, 0x00, 0xcf, 0xf4, 0xfc, 0x00,
+ 0x8e, 0x6a, 0x00, 0x0c, 0xc3, 0xf4, 0x3c, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xc4, 0x20, 0xfc, 0x00,
+ 0xcf, 0x6c, 0x3c, 0x00, 0xc4, 0x20, 0xf5, 0x00, 0xc3, 0x18, 0xec, 0x00, 0x20, 0x72, 0x00, 0x00,
+ 0xe6, 0x00, 0x09, 0x30, 0x94, 0x6a, 0x00, 0x08, 0xe0, 0x00, 0x09, 0x40, 0xf4, 0x02, 0x00, 0x01,
+ 0xf7, 0x82, 0x09, 0x3c, 0xc1, 0x70, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xf4, 0x02, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10, 0x93, 0x16, 0xff, 0xec, 0xff, 0x02, 0x00, 0x00,
+ 0x83, 0x16, 0xff, 0xec, 0x9f, 0x16, 0xff, 0xe8, 0x23, 0x94, 0x00, 0x14, 0xf4, 0x02, 0x00, 0x10,
+ 0xf7, 0x82, 0x09, 0x7c, 0xe0, 0x02, 0x89, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xe8,
+ 0x2f, 0x94, 0x00, 0x10, 0xb4, 0x7e, 0xf0, 0x04, 0x8f, 0x96, 0xff, 0xec, 0x0f, 0x78, 0x00, 0x01,
+ 0x20, 0x7a, 0x00, 0x05, 0x0f, 0xfc, 0x00, 0x01, 0xe2, 0x00, 0x09, 0x61, 0x9f, 0x96, 0xff, 0xec,
+ 0x23, 0x14, 0x00, 0x10, 0xf7, 0x82, 0x09, 0xb0, 0xe0, 0x00, 0x94, 0xe0, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x17, 0x5b, 0xf1, 0xfe, 0x17, 0x5b, 0xf0, 0xfe, 0x97, 0x5b, 0xf2, 0xff, 0x97, 0x5b, 0xf3,
+ 0xfd, 0x97, 0x5b, 0xf4, 0x7f, 0x79, 0x00, 0x08, 0xfd, 0x17, 0x5b, 0xf5, 0xce, 0x70, 0xf5, 0x00,
+ 0x7e, 0xf5, 0x00, 0x10, 0xce, 0x70, 0xed, 0x00, 0x7f, 0xfd, 0x00, 0x08, 0x7d, 0xed, 0x00, 0x10,
+ 0x5e, 0x71, 0xff, 0x00, 0xcf, 0xfc, 0xdd, 0x00, 0x7d, 0x69, 0x00, 0x18, 0xfe, 0x09, 0x96, 0x38,
+ 0xcf, 0xfc, 0xd5, 0x00, 0x5e, 0x7c, 0x00, 0xff, 0xfe, 0x09, 0x96, 0x48, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf3, 0x0a, 0x97, 0xc0, 0xf3, 0x82, 0x00, 0x00, 0xf4, 0x02, 0x08, 0x00, 0xf7, 0x82, 0x0a, 0x28,
+ 0xe0, 0x02, 0x89, 0x20, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x0a, 0x9f, 0xc0, 0xf3, 0x82, 0x00, 0x00,
+ 0xf4, 0x02, 0x00, 0x10, 0xf7, 0x82, 0x0a, 0x40, 0xe0, 0x02, 0x89, 0x20, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x0a, 0x97, 0xcc, 0xff, 0x82, 0x00, 0x7f, 0x0e, 0x81, 0x01, 0x00, 0x9e, 0xfa, 0x00, 0x00,
+ 0x2f, 0xfe, 0x00, 0x01, 0xea, 0x00, 0x0a, 0x4c, 0x0f, 0x78, 0x00, 0x10, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x52, 0x45, 0x56, 0x3d, 0x00, 0x4d, 0x41, 0x43,
+ 0x3d, 0x00, 0x50, 0x57, 0x52, 0x3d, 0x00, 0x50, 0x43, 0x3d, 0x31, 0x30, 0x47, 0x2d, 0x50, 0x43,
+ 0x49, 0x45, 0x2d, 0x38, 0x41, 0x00, 0x2d, 0x43, 0x00, 0x4c, 0x2d, 0x43, 0x00, 0x2d, 0x49, 0x00,
+ 0x2d, 0x51, 0x00, 0x4c, 0x2d, 0x51, 0x00, 0x2d, 0x52, 0x00, 0x4c, 0x2d, 0x52, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0xff, 0x76, 0xfe, 0x00,
+ 0x9f, 0x16, 0xff, 0xf4, 0xff, 0xfb, 0x48, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x0d, 0x0d,
+ 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0xf4, 0xf3, 0x82, 0x0a, 0x68, 0xf4, 0x02, 0x00, 0x04,
+ 0xf7, 0x82, 0x0a, 0xdc, 0xe0, 0x02, 0x89, 0x60, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0x0b, 0x3c, 0xc3, 0xa0, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xf4, 0xf4, 0x02, 0x00, 0x10,
+ 0x03, 0x7c, 0x00, 0x04, 0xf7, 0x82, 0x0b, 0x00, 0xe0, 0x02, 0x89, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x0a, 0x8f, 0xa8, 0xf4, 0x7b, 0x68, 0x03, 0x83, 0x16, 0xff, 0xf4, 0xf7, 0x82, 0x0b, 0x18,
+ 0xe0, 0x02, 0x8a, 0x28, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4, 0xc4, 0x7c, 0x40, 0x00,
+ 0xff, 0xa3, 0x48, 0x01, 0x04, 0x20, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x0a, 0xc4,
+ 0x94, 0x16, 0xff, 0xf4, 0xe0, 0x00, 0x0d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0xf4,
+ 0xf3, 0x82, 0x0a, 0x6d, 0xf4, 0x02, 0x00, 0x04, 0xf7, 0x82, 0x0b, 0x54, 0xe0, 0x02, 0x89, 0x60,
+ 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0b, 0x7c, 0xf3, 0x82, 0x0a, 0x72,
+ 0x8f, 0x96, 0xff, 0xf4, 0x03, 0x7c, 0x00, 0x04, 0xf7, 0x82, 0x0b, 0x74, 0xe0, 0x00, 0x09, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0xf4,
+ 0xf4, 0x02, 0x00, 0x04, 0xf7, 0x82, 0x0b, 0x90, 0xe0, 0x02, 0x89, 0x60, 0x97, 0x93, 0xff, 0xfc,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0b, 0xbc, 0xc3, 0xa0, 0x00, 0x00, 0x8f, 0x16, 0xff, 0xf4,
+ 0xf4, 0x02, 0x00, 0x0a, 0x03, 0x78, 0x00, 0x04, 0xf7, 0x82, 0x0b, 0xb4, 0xe0, 0x02, 0x89, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x0b, 0x08, 0xf4, 0x09, 0xa9, 0x10, 0x83, 0x16, 0xff, 0xf4,
+ 0xf3, 0x82, 0x0a, 0x77, 0xf4, 0x02, 0x00, 0x0e, 0xf7, 0x82, 0x0b, 0xd4, 0xe0, 0x02, 0x89, 0x60,
+ 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0b, 0x08, 0x94, 0x16, 0xff, 0xf0,
+ 0x8f, 0x96, 0xff, 0xf4, 0xf3, 0x82, 0x0a, 0x86, 0xf4, 0x02, 0x00, 0x02, 0x0f, 0xfc, 0x00, 0x0e,
+ 0x9f, 0x96, 0xff, 0xec, 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x0c, 0x04, 0xe0, 0x02, 0x89, 0x60,
+ 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0c, 0x1c, 0xf3, 0x82, 0x0a, 0x89,
+ 0xff, 0x02, 0x00, 0x01, 0xe0, 0x00, 0x0b, 0x08, 0xff, 0x09, 0x9f, 0xd0, 0x83, 0x16, 0xff, 0xec,
+ 0xf4, 0x02, 0x00, 0x03, 0xf7, 0x82, 0x0c, 0x30, 0xe0, 0x02, 0x89, 0x60, 0x97, 0x93, 0xff, 0xfc,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0c, 0x15, 0xff, 0x02, 0x00, 0x01, 0x83, 0x16, 0xff, 0xec,
+ 0xf3, 0x82, 0x0a, 0x8d, 0xf4, 0x02, 0x00, 0x02, 0xf7, 0x82, 0x0c, 0x54, 0xe0, 0x02, 0x89, 0x60,
+ 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0c, 0x68, 0xff, 0x82, 0x00, 0x04,
+ 0xe0, 0x00, 0x0b, 0x08, 0xff, 0x89, 0x9f, 0xd0, 0x83, 0x16, 0xff, 0xec, 0xf3, 0x82, 0x0a, 0x90,
+ 0xf4, 0x02, 0x00, 0x02, 0xf7, 0x82, 0x0c, 0x80, 0xe0, 0x02, 0x89, 0x60, 0x97, 0x93, 0xff, 0xfc,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0c, 0x94, 0xf3, 0x82, 0x0a, 0x93, 0xe0, 0x00, 0x0c, 0x14,
+ 0xff, 0x02, 0x00, 0x02, 0x83, 0x16, 0xff, 0xec, 0xf4, 0x02, 0x00, 0x03, 0xf7, 0x82, 0x0c, 0xa8,
+ 0xe0, 0x02, 0x89, 0x60, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0c, 0x15,
+ 0xff, 0x02, 0x00, 0x02, 0x83, 0x16, 0xff, 0xec, 0xf3, 0x82, 0x0a, 0x97, 0xf4, 0x02, 0x00, 0x02,
+ 0xf7, 0x82, 0x0c, 0xcc, 0xe0, 0x02, 0x89, 0x60, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0x0c, 0xe0, 0xf3, 0x82, 0x0a, 0x9a, 0xe0, 0x00, 0x0c, 0x60, 0xff, 0x82, 0x00, 0x03,
+ 0x83, 0x16, 0xff, 0xec, 0xf4, 0x02, 0x00, 0x03, 0xf7, 0x82, 0x0c, 0xf4, 0xe0, 0x02, 0x89, 0x60,
+ 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x0c, 0x61, 0xff, 0x82, 0x00, 0x03,
+ 0x8f, 0x16, 0xff, 0xf0, 0xe0, 0x00, 0x0b, 0x08, 0xff, 0x09, 0x9f, 0xd0, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfb, 0x02, 0x14, 0xc1, 0xff, 0x8a, 0x8f, 0x8a, 0xfb, 0x7f, 0x28, 0x00, 0xff, 0x88, 0x8f, 0x98,
+ 0x2d, 0x00, 0x00, 0x02, 0x2c, 0x80, 0x00, 0x09, 0xcf, 0xfc, 0xd4, 0x00, 0x4f, 0xfc, 0xff, 0xfd,
+ 0x4f, 0xfc, 0xff, 0xfb, 0x29, 0x00, 0x00, 0x11, 0xcf, 0xfc, 0xcc, 0x00, 0x27, 0x00, 0x00, 0x21,
+ 0xcf, 0xfc, 0x94, 0x00, 0xcf, 0xfc, 0x74, 0x00, 0x4f, 0xfc, 0xff, 0xbf, 0x23, 0x00, 0x01, 0x01,
+ 0x4f, 0xfc, 0xff, 0x7f, 0x29, 0x80, 0x02, 0x01, 0xcf, 0xfc, 0x34, 0x00, 0xcf, 0xfc, 0x9c, 0x00,
+ 0x24, 0x00, 0x04, 0x01, 0x46, 0x85, 0xff, 0xf7, 0xcf, 0xfc, 0x44, 0x00, 0xcf, 0xfc, 0x6c, 0x00,
+ 0x5f, 0xfd, 0x00, 0x10, 0x4c, 0x05, 0xff, 0x7f, 0x4f, 0xfd, 0xff, 0xdf, 0x46, 0x05, 0xfe, 0xff,
+ 0xcf, 0xfc, 0xc4, 0x00, 0xcf, 0xfc, 0x64, 0x00, 0x4f, 0xfd, 0xf9, 0xff, 0x4f, 0xfd, 0xf7, 0xff,
+ 0x4f, 0xfd, 0xef, 0xff, 0x4f, 0xfd, 0xdf, 0xff, 0x4f, 0xfd, 0xbf, 0xff, 0x4f, 0xfd, 0x7f, 0xff,
+ 0xff, 0x89, 0x8f, 0x98, 0xfb, 0x82, 0x00, 0x00, 0xff, 0x8a, 0x8f, 0xa8, 0xfb, 0xff, 0x68, 0x03,
+ 0xff, 0x88, 0x8f, 0xa8, 0xf3, 0x82, 0x00, 0xff, 0xff, 0x0a, 0x8f, 0xb8, 0xcf, 0xfc, 0x3c, 0x00,
+ 0x5f, 0xfd, 0x02, 0x00, 0xff, 0x89, 0x8f, 0xa8, 0xfb, 0xfb, 0x68, 0x03, 0xff, 0x8a, 0x8f, 0xb7,
+ 0xfb, 0xff, 0x68, 0x03, 0xff, 0x0a, 0x8f, 0xb6, 0xfb, 0xfb, 0x68, 0x03, 0xff, 0x88, 0x8f, 0xc8,
+ 0xff, 0x08, 0x8f, 0xb8, 0x2d, 0x80, 0x00, 0x07, 0xcf, 0xfc, 0xd4, 0x00, 0xfe, 0x02, 0x00, 0x04,
+ 0xcf, 0xfc, 0xdc, 0x00, 0xcf, 0xfc, 0xe5, 0x00, 0x4f, 0x79, 0xf0, 0xff, 0xcf, 0xfc, 0xcc, 0x00,
+ 0x0e, 0x81, 0xff, 0x00, 0x4f, 0x79, 0xbf, 0xff, 0x0e, 0xf4, 0x00, 0x0f, 0x4f, 0x79, 0x7f, 0xff,
+ 0x5f, 0xfc, 0x00, 0x08, 0xff, 0x09, 0x8f, 0xb8, 0xcf, 0xfc, 0xec, 0x00, 0xff, 0x89, 0x8f, 0xc8,
+ 0xff, 0x0a, 0x8f, 0xc5, 0xfb, 0xfb, 0x68, 0x03, 0xff, 0x88, 0x8f, 0xe8, 0x0e, 0x81, 0xff, 0xf0,
+ 0x0e, 0xf4, 0x00, 0x0f, 0xcf, 0xfc, 0xd4, 0x00, 0xcf, 0xfc, 0xdc, 0x00, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xcf, 0xfc, 0xcc, 0x00, 0xcf, 0xfc, 0xec, 0x00, 0x4f, 0xfd, 0x00, 0x0f, 0xff, 0x89, 0x8f, 0xe8,
+ 0xfb, 0x89, 0x8f, 0xd8, 0xfb, 0x89, 0x8f, 0xf8, 0xfb, 0x89, 0x90, 0x28, 0xff, 0x0a, 0x90, 0x3a,
+ 0xfb, 0x7b, 0x28, 0x00, 0xff, 0x88, 0x90, 0x48, 0xff, 0x0a, 0x90, 0x58, 0xf8, 0x82, 0x00, 0x01,
+ 0xcf, 0xfc, 0xd4, 0x00, 0x4f, 0xfd, 0x00, 0x07, 0xff, 0x89, 0x90, 0x48, 0xf7, 0x82, 0x00, 0x44,
+ 0xf7, 0xfb, 0x68, 0x03, 0xff, 0x8a, 0x90, 0x78, 0xfb, 0xff, 0x68, 0x03, 0xff, 0x8a, 0x90, 0x77,
+ 0xf8, 0xff, 0x68, 0x03, 0xff, 0x0a, 0x90, 0x76, 0xfb, 0xfb, 0x68, 0x03, 0xff, 0x8a, 0x90, 0x75,
+ 0xfb, 0xff, 0x68, 0x03, 0xf4, 0x82, 0x00, 0x05, 0xff, 0x8a, 0x90, 0x98, 0xf4, 0xff, 0x68, 0x03,
+ 0xff, 0x0a, 0x90, 0x97, 0xf7, 0x82, 0x00, 0x54, 0xf7, 0xfb, 0x68, 0x03, 0xff, 0x88, 0x90, 0x98,
+ 0xff, 0x08, 0x90, 0xa8, 0xfe, 0x82, 0x00, 0x03, 0x4f, 0xfd, 0xff, 0x80, 0xcf, 0xfc, 0xc4, 0x00,
+ 0x5f, 0xfd, 0x00, 0x80, 0xcf, 0x78, 0xec, 0x00, 0xcf, 0xfc, 0x64, 0x00, 0xff, 0x89, 0x90, 0x98,
+ 0xff, 0x09, 0x90, 0xa8, 0xfb, 0x89, 0x90, 0xb8, 0xff, 0x8a, 0x90, 0xca, 0xfb, 0xff, 0x28, 0x00,
+ 0xff, 0x0a, 0x90, 0xd8, 0xf8, 0xfb, 0x68, 0x03, 0xff, 0x8a, 0x90, 0xd7, 0xf7, 0x82, 0x00, 0x5c,
+ 0xf7, 0xff, 0x68, 0x03, 0xff, 0x08, 0x90, 0xd8, 0xff, 0x88, 0x90, 0xe8, 0xfa, 0x02, 0x20, 0x00,
+ 0x4f, 0x79, 0xff, 0xf8, 0x4f, 0xfc, 0x81, 0xfc, 0x5f, 0x79, 0x00, 0x02, 0xcf, 0xfc, 0xa5, 0x00,
+ 0x28, 0x00, 0x80, 0x01, 0xcf, 0x78, 0x6c, 0x00, 0xcf, 0xfc, 0x84, 0x00, 0x4f, 0x79, 0xff, 0xdf,
+ 0x4f, 0x79, 0x00, 0x12, 0x4f, 0xfd, 0xff, 0xbf, 0xff, 0x09, 0x90, 0xd8, 0xcf, 0xfc, 0xc4, 0x00,
+ 0xff, 0x89, 0x90, 0xe8, 0xff, 0x0a, 0x90, 0xe5, 0xf7, 0x82, 0x00, 0x64, 0xf7, 0xfb, 0x68, 0x03,
+ 0xfa, 0x82, 0x00, 0x10, 0xff, 0x0a, 0x90, 0xf8, 0xfa, 0xfb, 0x68, 0x03, 0xff, 0x88, 0x91, 0x18,
+ 0xfe, 0x88, 0x91, 0x38, 0xfe, 0x08, 0x91, 0x28, 0xcf, 0xfc, 0xd4, 0x00, 0x4f, 0xfc, 0xff, 0xfd,
+ 0x4f, 0xfc, 0xff, 0xfb, 0xcf, 0xfc, 0xcc, 0x00, 0xcf, 0xfc, 0x94, 0x00, 0xcf, 0xfc, 0xad, 0x00,
+ 0x4f, 0xfc, 0xff, 0x10, 0xcf, 0xfc, 0x34, 0x00, 0xcf, 0xfc, 0x9c, 0x00, 0xfd, 0x88, 0x91, 0x08,
+ 0x2b, 0x00, 0x00, 0x10, 0x4e, 0xf4, 0xff, 0xfc, 0xcf, 0xfc, 0x44, 0x00, 0x2f, 0x00, 0x70, 0x01,
+ 0xce, 0xf4, 0xcc, 0x00, 0x5f, 0xfc, 0x08, 0x00, 0xce, 0x70, 0xb4, 0x00, 0x29, 0x80, 0x00, 0x08,
+ 0xcf, 0xfc, 0xf4, 0x00, 0xce, 0xf4, 0x94, 0x00, 0xce, 0x70, 0x8d, 0x00, 0xcf, 0xfc, 0xa5, 0x00,
+ 0xce, 0xf4, 0x74, 0x00, 0xcd, 0xec, 0x9c, 0x00, 0x4e, 0x70, 0xf4, 0x81, 0xfd, 0x08, 0x91, 0x88,
+ 0xcd, 0xec, 0x4d, 0x00, 0x4e, 0xf4, 0xff, 0xbf, 0x4f, 0xfd, 0xff, 0xfe, 0x5e, 0x70, 0x04, 0x80,
+ 0x4a, 0x05, 0xff, 0xf0, 0xce, 0x70, 0xf4, 0x00, 0x4e, 0xf4, 0xff, 0x7f, 0xcd, 0xec, 0x74, 0x00,
+ 0x4f, 0xfd, 0xff, 0xfd, 0xfc, 0x88, 0x90, 0xf8, 0xfc, 0x08, 0x91, 0x98, 0x4d, 0xec, 0x80, 0x05,
+ 0xce, 0xf4, 0xa4, 0x00, 0x4f, 0xfd, 0xff, 0xfb, 0x0f, 0x01, 0xff, 0xfc, 0x0f, 0x78, 0x7f, 0xff,
+ 0xcd, 0xec, 0x84, 0x00, 0x5e, 0xf5, 0x00, 0x01, 0xcd, 0x68, 0xb4, 0x00, 0xcf, 0xfc, 0x6c, 0x00,
+ 0x5e, 0x70, 0x70, 0x00, 0xce, 0x70, 0xf4, 0x00, 0x4e, 0xf5, 0xfc, 0x0f, 0x5d, 0xec, 0x80, 0x00,
+ 0x5d, 0x68, 0x00, 0x0e, 0x4f, 0xfd, 0xff, 0xef, 0x4f, 0xfd, 0xff, 0xdf, 0xff, 0x0e, 0x80, 0x00,
+ 0xcc, 0xe4, 0x64, 0x00, 0x4d, 0xed, 0xfc, 0x03, 0x4e, 0xf5, 0xfb, 0xff, 0xcc, 0x60, 0x94, 0x00,
+ 0xcd, 0x68, 0x94, 0x00, 0xff, 0x89, 0x91, 0x18, 0xce, 0x70, 0xf5, 0x00, 0x4d, 0xed, 0xf3, 0xff,
+ 0x4e, 0xf5, 0xf7, 0xff, 0xcd, 0x68, 0xad, 0x00, 0xcc, 0x60, 0xb4, 0x00, 0x4c, 0xe5, 0xc0, 0x0f,
+ 0xfd, 0x89, 0x91, 0x08, 0xfe, 0x09, 0x91, 0x28, 0xfe, 0x89, 0x91, 0x38, 0xfc, 0x89, 0x90, 0xf8,
+ 0xfd, 0x09, 0x91, 0x88, 0xfc, 0x09, 0x91, 0x98, 0xff, 0x8a, 0x92, 0x08, 0xf7, 0x82, 0x00, 0x09,
+ 0xf7, 0xff, 0x68, 0x03, 0xff, 0x0a, 0x92, 0x06, 0xf7, 0x82, 0x00, 0x1c, 0xf7, 0xfb, 0x68, 0x03,
+ 0xff, 0x08, 0x92, 0x18, 0xff, 0x88, 0x92, 0x38, 0xfb, 0x89, 0x92, 0x28, 0xcf, 0x78, 0x3c, 0x00,
+ 0xff, 0x09, 0x92, 0x18, 0xcf, 0xfc, 0x3c, 0x00, 0xff, 0x89, 0x92, 0x38, 0xff, 0x0a, 0x92, 0x38,
+ 0xfb, 0xfb, 0x68, 0x03, 0xff, 0x8a, 0x92, 0x48, 0xfb, 0xff, 0x68, 0x03, 0xfb, 0x89, 0x92, 0x58,
+ 0xfb, 0x89, 0x92, 0x68, 0xff, 0x8a, 0x92, 0xc8, 0xf7, 0x82, 0x00, 0x11, 0xf7, 0xff, 0x68, 0x03,
+ 0xff, 0x0a, 0x92, 0xc7, 0xfb, 0xfb, 0x68, 0x03, 0xfe, 0x08, 0x92, 0xc8, 0xfe, 0x88, 0x92, 0xd8,
+ 0xff, 0x08, 0x92, 0xe8, 0xff, 0x82, 0x00, 0x02, 0x4e, 0x71, 0xf8, 0x00, 0xce, 0xf4, 0x9c, 0x00,
+ 0xcf, 0x78, 0x9c, 0x00, 0xcf, 0x78, 0xfd, 0x00, 0xce, 0xf4, 0xfd, 0x00, 0xfd, 0x82, 0x00, 0x07,
+ 0x5e, 0x71, 0x00, 0x7f, 0xff, 0xbe, 0x90, 0x00, 0x4e, 0x71, 0xbf, 0xff, 0xcf, 0x78, 0xdc, 0x00,
+ 0xce, 0xf4, 0xdc, 0x00, 0xcf, 0x78, 0xfd, 0x00, 0x4e, 0x71, 0x7f, 0xff, 0x5e, 0xf5, 0x00, 0x0f,
+ 0xfe, 0x09, 0x92, 0xc8, 0xfe, 0x89, 0x92, 0xd8, 0xff, 0x09, 0x92, 0xe8, 0xff, 0x8a, 0x93, 0x8a,
+ 0xf8, 0xff, 0x28, 0x00, 0xff, 0x88, 0x93, 0x88, 0xff, 0x08, 0x93, 0xe8, 0xfe, 0x06, 0x00, 0x00,
+ 0xcf, 0xfc, 0xa4, 0x00, 0xfe, 0xbe, 0xff, 0xff, 0xcf, 0xfc, 0xe5, 0x00, 0xcf, 0xfc, 0xec, 0x00,
+ 0x5f, 0xfd, 0x1a, 0x80, 0x5f, 0x78, 0x00, 0xa0, 0xff, 0x89, 0x93, 0x88, 0xff, 0x09, 0x93, 0xe8,
+ 0xff, 0x8a, 0x96, 0x2a, 0xff, 0x02, 0x00, 0x03, 0xff, 0x7f, 0x28, 0x00, 0xff, 0x88, 0x96, 0x28,
+ 0xfb, 0x89, 0x96, 0x48, 0xfb, 0x89, 0x96, 0x38, 0xcf, 0xfc, 0xa4, 0x00, 0xcf, 0xfc, 0xe5, 0x00,
+ 0xcf, 0xfc, 0xec, 0x00, 0xff, 0x89, 0x96, 0x28, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x08,
+ 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x07, 0x08, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf7, 0x82, 0x11, 0xdc, 0xe0, 0x00, 0xb8, 0x2c, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x11, 0xe8,
+ 0xe0, 0x00, 0xb9, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x11, 0xf4, 0xe0, 0x00, 0x9e, 0xc8,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0x8f, 0x98, 0x70, 0x7e, 0x00, 0x15, 0xea, 0x00, 0x12, 0xa8,
+ 0xfd, 0x82, 0x00, 0x00, 0x70, 0x7e, 0x00, 0x0c, 0xea, 0x00, 0x12, 0xac, 0x4f, 0x29, 0xbf, 0xff,
+ 0xfe, 0x88, 0xd3, 0xd8, 0x4f, 0xfd, 0xff, 0xf7, 0xff, 0x89, 0x8f, 0x98, 0xff, 0x82, 0x34, 0x00,
+ 0xf7, 0x82, 0x00, 0x40, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0xf7, 0x28, 0x0c, 0xff, 0x0a, 0x9f, 0xfe,
+ 0xff, 0xfb, 0x18, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0x24,
+ 0xff, 0xf7, 0x28, 0x12, 0x9d, 0xf6, 0x00, 0x14, 0x9d, 0xf6, 0x00, 0x18, 0x9d, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x9d, 0xf6, 0x00, 0x30, 0xff, 0x77, 0x18, 0x0a, 0x8e, 0x76, 0x00, 0x2c,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x0f, 0x81, 0x10, 0x00, 0x0f, 0xfc, 0x00, 0x14,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0xec, 0x9f, 0xf6, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0xfd, 0xf7, 0x28, 0x02, 0xff, 0x88, 0x8f, 0x98,
+ 0x4f, 0xfd, 0xff, 0xf7, 0xff, 0x89, 0x8f, 0x98, 0x4f, 0x29, 0xbf, 0xff, 0x70, 0x7e, 0x00, 0x1d,
+ 0xea, 0x00, 0x12, 0xbc, 0x55, 0x79, 0x40, 0x00, 0xc5, 0x78, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf7, 0x82, 0x12, 0xdc, 0xe0, 0x00, 0xb8, 0x2c, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf7, 0x82, 0x12, 0xfc, 0xe0, 0x00, 0xb9, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf7, 0x82, 0x13, 0x1c, 0xe0, 0x00, 0x9e, 0xc8, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x04, 0xff, 0x88, 0x91, 0x18, 0xfd, 0x76, 0xff, 0xf0, 0x8f, 0x6a, 0x00, 0x00,
+ 0x7f, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xe3, 0xfd, 0x82, 0x00, 0x80, 0x7e, 0xfd, 0x00, 0x1d,
+ 0x4f, 0x79, 0x1f, 0xff, 0xcf, 0xec, 0xff, 0xc0, 0xcf, 0x78, 0xed, 0x00, 0x9f, 0x6a, 0x00, 0x00,
+ 0x7e, 0x7c, 0xff, 0xfe, 0xff, 0x89, 0x9f, 0xe4, 0xf3, 0x76, 0xff, 0xfc, 0x9d, 0x96, 0xff, 0xf4,
+ 0xfe, 0x09, 0x9f, 0xe8, 0xf7, 0x82, 0x13, 0x80, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0x91, 0x18, 0x8d, 0x96, 0xff, 0xf4, 0xf3, 0x08, 0x9f, 0xe4, 0x7f, 0xfd, 0x00, 0x11,
+ 0x7f, 0xfc, 0xff, 0xe3, 0xcd, 0xec, 0xff, 0xc0, 0xfd, 0x89, 0x9f, 0xec, 0xf7, 0x82, 0x13, 0xa8,
+ 0xe0, 0x00, 0xc5, 0x0c, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x91, 0x98,
+ 0xf3, 0x02, 0x00, 0x00, 0x7f, 0x7d, 0x00, 0x1c, 0x70, 0x7e, 0x00, 0x1b, 0xea, 0x00, 0x14, 0x1d,
+ 0x7f, 0x78, 0xff, 0xe6, 0xff, 0x82, 0x13, 0xb4, 0xa3, 0x7a, 0xf8, 0x02, 0xf7, 0x82, 0x14, 0x28,
+ 0xe0, 0x00, 0x8f, 0xd0, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x91, 0x38,
+ 0xfe, 0xf6, 0xff, 0xe8, 0x8f, 0x76, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xe1,
+ 0x4f, 0x79, 0xfe, 0xff, 0x7f, 0xfd, 0x00, 0x18, 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x76, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x82, 0x14, 0x70, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xff, 0x88, 0x9f, 0xf8, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0x14, 0xd0, 0xff, 0x82, 0xff, 0x00, 0xc0, 0x1e, 0xfc, 0x00, 0xe6, 0x00, 0x14, 0xd1,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x92, 0x28, 0xf3, 0x08, 0x92, 0x18, 0x7f, 0xfd, 0x00, 0x08,
+ 0x9f, 0x96, 0xff, 0xf4, 0x73, 0x18, 0xff, 0xf8, 0xf7, 0x82, 0x14, 0xc4, 0xe0, 0x00, 0x1c, 0x58,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4, 0xcf, 0xfc, 0x45, 0x00, 0xff, 0x89, 0x92, 0x28,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x14, 0xff, 0x88, 0x9f, 0xf8, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0x17, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x92, 0x38, 0xff, 0x08, 0xa9, 0x54,
+ 0x7e, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xf8, 0x7e, 0xf4, 0xff, 0xe8, 0x9f, 0x96, 0xff, 0xf4,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe4, 0x00, 0x17, 0xc0, 0x9e, 0x96, 0xff, 0xf0, 0xff, 0x88, 0xa9, 0x48,
+ 0x8e, 0x96, 0xff, 0xf4, 0xc0, 0x76, 0xfa, 0x00, 0xe4, 0x00, 0x17, 0xc1, 0xff, 0x82, 0x00, 0xff,
+ 0xc0, 0x1e, 0xfc, 0x00, 0xe6, 0x00, 0x17, 0xc1, 0xf3, 0x02, 0x00, 0x17, 0x8f, 0x16, 0xff, 0xf0,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x7c, 0x00, 0x03, 0x9f, 0x96, 0xff, 0xec, 0xf7, 0x82, 0x15, 0x58,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x82, 0x00, 0xaa, 0xf3, 0x02, 0x55, 0x55,
+ 0xf7, 0x82, 0x15, 0x6c, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15,
+ 0xf7, 0x82, 0x15, 0x7c, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17,
+ 0xf7, 0x82, 0x15, 0x8c, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x82, 0x00, 0x55,
+ 0xf3, 0x02, 0x2a, 0xaa, 0xf7, 0x82, 0x15, 0xa0, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x15, 0xb0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x15, 0xc0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8e, 0x96, 0xff, 0xec, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0x17, 0x81, 0xf3, 0x82, 0x00, 0xa0,
+ 0xf3, 0x82, 0x00, 0x80, 0xf3, 0x02, 0x55, 0x55, 0xf7, 0x82, 0x15, 0xe4, 0xe0, 0x00, 0x32, 0x70,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x15, 0xf4, 0xe0, 0x00, 0x31, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x16, 0x04, 0xe0, 0x00, 0x31, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x82, 0x00, 0xaa, 0xf3, 0x02, 0x55, 0x55, 0xf7, 0x82, 0x16, 0x18,
+ 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x16, 0x28,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x16, 0x38,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x82, 0x00, 0x55, 0xf3, 0x02, 0x2a, 0xaa,
+ 0xf7, 0x82, 0x16, 0x4c, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15,
+ 0xf7, 0x82, 0x16, 0x5c, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17,
+ 0xf7, 0x82, 0x16, 0x6c, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0xf3, 0x82, 0x00, 0x30, 0xf7, 0x82, 0x16, 0x80, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x16, 0x90, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x16, 0xa0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x13, 0xf7, 0x82, 0x16, 0xb0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x96, 0xff, 0xf4, 0xfe, 0x82, 0x00, 0xff, 0xf3, 0x82, 0x00, 0x00, 0x7f, 0x7d, 0x00, 0x08,
+ 0xff, 0x88, 0x92, 0x18, 0xcf, 0xfc, 0xec, 0x00, 0xcf, 0xfc, 0xf5, 0x00, 0x73, 0x7c, 0xff, 0xf8,
+ 0xff, 0x89, 0x92, 0x18, 0xf7, 0x82, 0x16, 0xe0, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0x92, 0x28, 0xf3, 0x08, 0x92, 0x18, 0xf3, 0x82, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x08,
+ 0x9f, 0x96, 0xff, 0xe8, 0x73, 0x18, 0xff, 0xf8, 0xf7, 0x82, 0x17, 0x04, 0xe0, 0x00, 0x32, 0x70,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x02, 0x00, 0xff, 0xc4, 0x20, 0xf4, 0x00, 0x8e, 0x96, 0xff, 0xe8,
+ 0x8f, 0x16, 0xff, 0xec, 0xcf, 0xf4, 0x45, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0x17, 0x48,
+ 0xff, 0x89, 0x92, 0x28, 0x8f, 0x96, 0xff, 0xf4, 0xfe, 0x82, 0x00, 0xff, 0x0f, 0x7c, 0x00, 0x01,
+ 0xff, 0x88, 0x92, 0x38, 0x7f, 0x79, 0x00, 0x08, 0xcf, 0xfc, 0xec, 0x00, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xe0, 0x00, 0x17, 0xc0, 0xff, 0x89, 0x92, 0x38, 0xf3, 0x08, 0x92, 0x18, 0x7f, 0xfd, 0x00, 0x08,
+ 0x9f, 0x96, 0xff, 0xe4, 0xf3, 0x82, 0x00, 0x00, 0x73, 0x18, 0xff, 0xf8, 0xf7, 0x82, 0x17, 0x68,
+ 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xe4, 0xff, 0x82, 0x00, 0xff,
+ 0xc4, 0x20, 0xfc, 0x00, 0xcf, 0xf4, 0x45, 0x00, 0xe0, 0x00, 0x17, 0xc0, 0xff, 0x89, 0x92, 0x28,
+ 0xf3, 0x02, 0x55, 0x55, 0xf7, 0x82, 0x17, 0x90, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x17, 0xa0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x17, 0xb0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0x83, 0x16, 0xff, 0xf4, 0x83, 0x96, 0xff, 0xf0, 0xe0, 0x00, 0x16, 0x74, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x08, 0x90, 0xe8, 0x7f, 0xf9, 0x00, 0x1e, 0x7f, 0xfe, 0xff, 0xe2,
+ 0xe6, 0x00, 0x18, 0x45, 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x00, 0x18, 0x45, 0xfe, 0x82, 0x00, 0x03,
+ 0x4f, 0xf8, 0xff, 0xfc, 0xff, 0x08, 0xa5, 0x3c, 0xcf, 0x78, 0xec, 0x00, 0xcf, 0x7c, 0xf5, 0x00,
+ 0xff, 0x09, 0x90, 0xe8, 0x7f, 0xf9, 0x00, 0x13, 0x7f, 0xfe, 0xff, 0xe4, 0xe6, 0x00, 0x18, 0x35,
+ 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x00, 0x18, 0x35, 0x20, 0x7e, 0x00, 0x04, 0xe6, 0x00, 0x18, 0x35,
+ 0x20, 0x7e, 0x00, 0x07, 0xe6, 0x00, 0x18, 0x35, 0xff, 0x8a, 0x90, 0xe5, 0xe0, 0x00, 0x18, 0x4c,
+ 0xf0, 0x7f, 0x68, 0x03, 0xff, 0x08, 0xa9, 0x10, 0xff, 0x8a, 0x90, 0xe5, 0xe0, 0x00, 0x18, 0x4c,
+ 0xff, 0x7f, 0x68, 0x03, 0xe0, 0x00, 0x18, 0x04, 0xff, 0x89, 0xa5, 0x3c, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf7, 0x82, 0x18, 0x6c, 0xe0, 0x00, 0x9e, 0xc8, 0x97, 0x93, 0xff, 0xfc, 0xfe, 0x88, 0x93, 0xe8,
+ 0xfd, 0xf6, 0xff, 0xec, 0x8f, 0x6e, 0x00, 0x00, 0x7f, 0xf5, 0x00, 0x17, 0xfe, 0x02, 0x00, 0x1f,
+ 0xcd, 0x00, 0xe2, 0x00, 0xcd, 0x7c, 0xd7, 0x80, 0x7f, 0xe9, 0x00, 0x13, 0x4f, 0x79, 0xff, 0xf7,
+ 0xcf, 0x78, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x19, 0xcf, 0x80, 0xe2, 0x00, 0xcf, 0xf4, 0xff, 0x80,
+ 0x9f, 0x6e, 0x00, 0x00, 0xff, 0x89, 0x9f, 0xfc, 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x82, 0x18, 0xb8,
+ 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x92, 0x68,
+ 0x20, 0x7e, 0x00, 0x02, 0xe6, 0x00, 0x19, 0x25, 0xf3, 0x82, 0x00, 0x00, 0xe2, 0x00, 0x19, 0x10,
+ 0x20, 0x7e, 0x00, 0x03, 0x20, 0x7e, 0x00, 0x01, 0xe6, 0x00, 0x19, 0x01, 0xff, 0xf6, 0xff, 0x5c,
+ 0xff, 0x82, 0x00, 0x00, 0xff, 0x89, 0x92, 0x58, 0xe0, 0x00, 0x19, 0x3c, 0xff, 0x89, 0x92, 0x68,
+ 0xff, 0x89, 0x92, 0x68, 0xff, 0x82, 0x00, 0x60, 0xe0, 0x00, 0x19, 0x3c, 0xff, 0x89, 0x92, 0x58,
+ 0xe6, 0x00, 0x18, 0xf0, 0xff, 0xf6, 0xfe, 0x00, 0xff, 0x89, 0x92, 0x68, 0xe0, 0x00, 0x19, 0x08,
+ 0xff, 0x82, 0x01, 0x00, 0xf3, 0x76, 0xff, 0xbc, 0xf7, 0x82, 0x19, 0x34, 0xe0, 0x00, 0x28, 0x78,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x19, 0x00, 0xff, 0xf6, 0xff, 0x5c, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0x92, 0x58, 0xff, 0x02, 0x00, 0x00, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x19, 0x9d,
+ 0x20, 0x7e, 0x01, 0x00, 0xe2, 0x00, 0x19, 0x71, 0x00, 0x00, 0x00, 0x01, 0xff, 0x82, 0x01, 0x00,
+ 0x9f, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x88, 0x92, 0x68, 0x9e, 0x82, 0xfe, 0x68,
+ 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x8a, 0xa7, 0x50, 0x9e, 0x82, 0xfe, 0x68, 0x9f, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x89, 0x92, 0x58, 0xfe, 0x89, 0x92, 0x68, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x82, 0x00, 0xff, 0xc0, 0x1e, 0xfc, 0x00, 0xe6, 0x00, 0x1a, 0x49, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0x92, 0x48, 0xfe, 0x08, 0x92, 0x68, 0x7f, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xe8,
+ 0x20, 0x7e, 0x00, 0x09, 0xe2, 0x00, 0x1a, 0x48, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x02, 0x19, 0xec,
+ 0xae, 0xfe, 0xf0, 0x02, 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x48,
+ 0x00, 0x00, 0x1a, 0x48, 0x00, 0x00, 0x1a, 0x48, 0x00, 0x00, 0x1a, 0x48, 0x00, 0x00, 0x1a, 0x48,
+ 0x00, 0x00, 0x1a, 0x14, 0x00, 0x00, 0x1a, 0x24, 0x00, 0x00, 0x1a, 0x30, 0x00, 0x00, 0x1a, 0x48,
+ 0x00, 0x00, 0x1a, 0x3c, 0xff, 0x88, 0x92, 0x58, 0xff, 0xf3, 0x64, 0x01, 0xe0, 0x00, 0x1a, 0x48,
+ 0xfe, 0x09, 0x92, 0x68, 0xff, 0x88, 0x92, 0x58, 0xe0, 0x00, 0x1a, 0x1c, 0xff, 0xf3, 0x24, 0x02,
+ 0xff, 0x88, 0x92, 0x58, 0xe0, 0x00, 0x1a, 0x1c, 0x9f, 0xf1, 0x00, 0x04, 0xf7, 0x82, 0x1a, 0x48,
+ 0xe0, 0x00, 0x19, 0x48, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x82, 0x00, 0xff,
+ 0xc0, 0x1e, 0xfc, 0x00, 0xe6, 0x00, 0x1b, 0x05, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x92, 0x48,
+ 0xfe, 0x08, 0x92, 0x58, 0x7f, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xe8, 0x20, 0x7e, 0x00, 0x08,
+ 0xe2, 0x00, 0x1b, 0x04, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x02, 0x1a, 0x98, 0xae, 0xfe, 0xf0, 0x02,
+ 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x04, 0x00, 0x00, 0x1a, 0xd0,
+ 0x00, 0x00, 0x1a, 0xe8, 0x00, 0x00, 0x1a, 0xf8, 0x00, 0x00, 0x1b, 0x04, 0x00, 0x00, 0x1b, 0x04,
+ 0x00, 0x00, 0x1b, 0x04, 0x00, 0x00, 0x1b, 0x04, 0x00, 0x00, 0x1a, 0xbc, 0xf7, 0x82, 0x1a, 0xc8,
+ 0xe0, 0x00, 0x18, 0xc4, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x08, 0x92, 0x68, 0x7f, 0xf1, 0x00, 0x08, 0xfe, 0xfb, 0x58, 0x00, 0xcf, 0xfc, 0xed, 0x00,
+ 0xe0, 0x00, 0x1b, 0x04, 0xff, 0x89, 0x92, 0x58, 0xff, 0x08, 0x92, 0x68, 0xfe, 0xfb, 0x18, 0x00,
+ 0xe0, 0x00, 0x1a, 0xdc, 0x7f, 0xf1, 0x00, 0x10, 0xff, 0x88, 0x92, 0x68, 0x8f, 0xfe, 0x00, 0x00,
+ 0xff, 0x89, 0x92, 0x58, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf7, 0x82, 0x1b, 0x24, 0xe0, 0x00, 0x9e, 0xc8,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x08, 0x92, 0xc8, 0x20, 0x7a, 0x00, 0x00, 0xec, 0x00, 0x1c, 0x30,
+ 0x7f, 0xf9, 0x00, 0x01, 0xff, 0x88, 0xa8, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x1c, 0x31,
+ 0x7f, 0xf9, 0x00, 0x01, 0x7f, 0xfe, 0xff, 0xe1, 0xe6, 0x00, 0x1c, 0x2c, 0xcd, 0x7c, 0x00, 0x00,
+ 0xfa, 0x8a, 0x9f, 0xc0, 0xfb, 0x02, 0x00, 0x07, 0xfa, 0x02, 0x00, 0x40, 0xfc, 0x8a, 0xd3, 0xfc,
+ 0xfc, 0x0a, 0x97, 0xcc, 0xcf, 0xe8, 0xb4, 0x00, 0xce, 0xfc, 0xb2, 0x00, 0x20, 0x6a, 0x00, 0x00,
+ 0xec, 0x00, 0x1c, 0x25, 0xcf, 0x68, 0x00, 0x00, 0x7f, 0x79, 0xff, 0xfd, 0xaf, 0xfa, 0xa8, 0x04,
+ 0xcf, 0xfc, 0xef, 0xc0, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x00, 0x1c, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0x8b, 0xe2, 0x00, 0x00, 0x20, 0x5e, 0x00, 0x00, 0xe6, 0x00, 0x1c, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x08, 0xd3, 0xd8, 0x8e, 0x66, 0xff, 0xfc, 0x8e, 0xe6, 0xff, 0xf4, 0xff, 0xfb, 0x18, 0x0a,
+ 0x8d, 0xfa, 0x00, 0x2c, 0x9a, 0x7a, 0x00, 0x30, 0x9c, 0xfa, 0x00, 0x24, 0x9e, 0xfa, 0x00, 0x28,
+ 0xff, 0xe7, 0x28, 0x02, 0x9c, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0x0e, 0x70, 0x00, 0x08, 0x9e, 0x7a, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0xef, 0x28, 0x00, 0x9f, 0xee, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0xfb, 0xfb, 0x28, 0x02, 0xff, 0x88, 0xa0, 0x5c, 0x0f, 0xfc, 0x00, 0x01,
+ 0xff, 0x89, 0xa0, 0x5c, 0x0d, 0x68, 0x00, 0x01, 0x0c, 0x60, 0x00, 0x10, 0x20, 0x6a, 0x00, 0x7f,
+ 0xee, 0x00, 0x1b, 0x65, 0x0c, 0xe4, 0x00, 0x24, 0xff, 0x08, 0x92, 0xc8, 0xe0, 0x00, 0x1c, 0x30,
+ 0x7f, 0xf9, 0x00, 0x01, 0xe0, 0x00, 0x1b, 0x78, 0x0f, 0x68, 0x00, 0x07, 0x7f, 0xf9, 0x00, 0x01,
+ 0x7f, 0xfc, 0xff, 0xe1, 0xff, 0x89, 0xa8, 0x50, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x08,
+ 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x07, 0x08, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x04, 0x93, 0x16, 0xff, 0xf4, 0xf3, 0x02, 0x00, 0x13, 0xf7, 0x82, 0x1c, 0x78,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4, 0xf3, 0x82, 0x00, 0x00,
+ 0xf7, 0x82, 0x1c, 0x8c, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0x74, 0x21, 0x00, 0x18,
+ 0x74, 0x20, 0xff, 0xe8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10, 0x93, 0x16, 0xff, 0xf4,
+ 0x93, 0x96, 0xff, 0xf0, 0x94, 0x16, 0xff, 0xec, 0xc3, 0x1c, 0x00, 0x00, 0xf7, 0x82, 0x1c, 0xc8,
+ 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xec, 0xff, 0x82, 0x00, 0x00,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe4, 0x00, 0x1d, 0x1d, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xf0,
+ 0x9f, 0x96, 0xff, 0xe8, 0x0f, 0x78, 0x00, 0x01, 0x9f, 0x16, 0xff, 0xf0, 0xc3, 0x78, 0x00, 0x00,
+ 0xf7, 0x82, 0x1c, 0xfc, 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xe8,
+ 0x8f, 0x16, 0xff, 0xf4, 0xb4, 0x7a, 0xf8, 0x04, 0x8f, 0x16, 0xff, 0xec, 0x0f, 0xfc, 0x00, 0x01,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe4, 0x00, 0x1c, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x0c, 0xff, 0x88, 0xa9, 0x38, 0xce, 0x9c, 0x00, 0x00, 0xce, 0x20, 0x00, 0x00,
+ 0xcd, 0x9c, 0x40, 0x00, 0xc0, 0x1e, 0xfa, 0x00, 0x93, 0x16, 0xff, 0xf4, 0xe2, 0x00, 0x1d, 0x64,
+ 0xff, 0x02, 0x00, 0x00, 0xc0, 0x6e, 0xfa, 0x00, 0xe2, 0x00, 0x1d, 0x64, 0xcf, 0x7c, 0x3a, 0x00,
+ 0xcf, 0x20, 0x00, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0x1d, 0x9c, 0xc4, 0x78, 0x00, 0x00,
+ 0x8f, 0x96, 0xff, 0xf4, 0xc4, 0x70, 0xf2, 0x00, 0xf3, 0x82, 0x00, 0xff, 0xc0, 0x72, 0xf2, 0x00,
+ 0xe6, 0x00, 0x1d, 0xc9, 0xc3, 0x7c, 0xf0, 0x00, 0xf7, 0x82, 0x1d, 0x94, 0xe0, 0x02, 0x89, 0x20,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x1d, 0xc8, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x88, 0xa9, 0x30,
+ 0x9e, 0x16, 0xff, 0xf0, 0x9f, 0x16, 0xff, 0xec, 0xc3, 0xf4, 0x38, 0x00, 0xf7, 0x82, 0x1d, 0xb8,
+ 0xe0, 0x00, 0x1c, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xec, 0x8e, 0x16, 0xff, 0xf0,
+ 0xe0, 0x00, 0x1d, 0x70, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10,
+ 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1d, 0xf0, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x82, 0x00, 0xaa, 0xf3, 0x02, 0x05, 0x55, 0xf7, 0x82, 0x1e, 0x04, 0xe0, 0x00, 0x32, 0x70,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x1e, 0x14, 0xe0, 0x00, 0x31, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1e, 0x24, 0xe0, 0x00, 0x31, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x82, 0x00, 0x55, 0xf3, 0x02, 0x02, 0xaa, 0xf7, 0x82, 0x1e, 0x38,
+ 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x1e, 0x48,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1e, 0x58,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x82, 0x00, 0x90, 0xf3, 0x02, 0x05, 0x55,
+ 0xf7, 0x82, 0x1e, 0x6c, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15,
+ 0xf7, 0x82, 0x1e, 0x7c, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17,
+ 0xf7, 0x82, 0x1e, 0x8c, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00,
+ 0xf7, 0x82, 0x1e, 0x9c, 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x01,
+ 0xf7, 0x82, 0x1e, 0xac, 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x02,
+ 0x94, 0x16, 0xff, 0xf0, 0xf7, 0x82, 0x1e, 0xc0, 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc,
+ 0xfe, 0x82, 0x00, 0x00, 0x9e, 0x96, 0xff, 0xf4, 0x94, 0x16, 0xff, 0xec, 0xf3, 0x02, 0x00, 0x17,
+ 0xf7, 0x82, 0x1e, 0xdc, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0xf3, 0x82, 0x00, 0xf0, 0xf7, 0x82, 0x1e, 0xf0, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x1f, 0x00, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1f, 0x10, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x16, 0xff, 0xf0, 0x20, 0x7a, 0x00, 0xc2, 0xe6, 0x00, 0x1f, 0xe8, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x96, 0xff, 0xec, 0x20, 0x7e, 0x00, 0x4f, 0xe6, 0x00, 0x1f, 0xe8, 0xf3, 0x82, 0x00, 0x98,
+ 0xf3, 0x02, 0x00, 0xaa, 0xf7, 0x82, 0x1f, 0x40, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x1f, 0x50, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1f, 0x60, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x10, 0xf7, 0x82, 0x1f, 0x70, 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x10, 0x03, 0x18, 0x00, 0x01, 0x93, 0x16, 0xff, 0xe8, 0xf7, 0x82, 0x1f, 0x88,
+ 0xe0, 0x00, 0x1c, 0x58, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf4, 0x83, 0x16, 0xff, 0xe8,
+ 0x7f, 0xf5, 0x00, 0x08, 0xcf, 0xfc, 0x40, 0x00, 0x20, 0x1a, 0x00, 0x12, 0xe2, 0x00, 0x1f, 0x75,
+ 0x9f, 0x96, 0xff, 0xf4, 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1f, 0xb4, 0xe0, 0x00, 0x31, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0xf0, 0xf7, 0x82, 0x1f, 0xc8,
+ 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x15, 0xf7, 0x82, 0x1f, 0xd8,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x17, 0xf7, 0x82, 0x1f, 0xe8,
+ 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4, 0x0f, 0x81, 0x00, 0x51,
+ 0x0f, 0xfc, 0x52, 0x59, 0xc0, 0x7a, 0xfa, 0x00, 0x8f, 0x96, 0xff, 0xf0, 0x8e, 0x96, 0xff, 0xec,
+ 0x7f, 0x7d, 0x00, 0x18, 0x7f, 0xf5, 0x00, 0x10, 0xcf, 0x78, 0xf8, 0x00, 0xe6, 0x74, 0x00, 0x03,
+ 0xcf, 0x78, 0xe8, 0x00, 0xff, 0x09, 0xa0, 0x58, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10,
+ 0xf3, 0x0a, 0xa9, 0x40, 0xf3, 0x82, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x20, 0xf7, 0x82, 0x20, 0x48,
+ 0xe0, 0x00, 0x1c, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x20, 0x54, 0xe0, 0x00, 0x1d, 0xd4,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x8a, 0xa5, 0xa0, 0xff, 0x7f, 0x58, 0x98, 0x20, 0x7a, 0x00, 0x01,
+ 0xe6, 0x00, 0x21, 0x3d, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa9, 0x54, 0x9f, 0x96, 0xff, 0xe8,
+ 0x83, 0x96, 0xff, 0xe8, 0x23, 0x14, 0x00, 0x0c, 0xf4, 0x02, 0x00, 0x04, 0xf7, 0x82, 0x20, 0x88,
+ 0xe0, 0x00, 0x1c, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4, 0x20, 0x7a, 0x3f, 0xff,
+ 0xe2, 0x00, 0x21, 0x49, 0x23, 0x14, 0x00, 0x10, 0x8e, 0x96, 0xff, 0xe8, 0xff, 0x88, 0xa9, 0x48,
+ 0xc3, 0xf4, 0xf0, 0x00, 0xcf, 0xfc, 0xea, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe2, 0x00, 0x21, 0x48,
+ 0xf4, 0x02, 0x00, 0x04, 0xf7, 0x82, 0x20, 0xc0, 0xe0, 0x00, 0x1c, 0xa0, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x16, 0xff, 0xf0, 0x8f, 0x96, 0xff, 0xf4, 0x8e, 0x96, 0xff, 0xe8, 0xf4, 0x02, 0x00, 0x04,
+ 0x2f, 0xfc, 0x00, 0x04, 0xc3, 0xf4, 0xf0, 0x00, 0x23, 0x14, 0x00, 0x14, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x00, 0x21, 0x49, 0xc3, 0x9c, 0x40, 0x00, 0xf7, 0x82, 0x20, 0xf4, 0xe0, 0x00, 0x1c, 0xa0,
+ 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf0, 0x8f, 0x96, 0xff, 0xf4, 0x0f, 0x74, 0x00, 0x04,
+ 0x2e, 0x7c, 0x00, 0x04, 0xc0, 0x7a, 0xe2, 0x00, 0xe2, 0x00, 0x21, 0x48, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x96, 0xff, 0xe8, 0x8d, 0x96, 0xff, 0xec, 0xcf, 0x7c, 0xe8, 0x00, 0xcf, 0xf4, 0xd8, 0x00,
+ 0x0f, 0xfc, 0x00, 0x04, 0xc0, 0x7e, 0xe2, 0x00, 0xe6, 0x00, 0x21, 0x48, 0x03, 0xf8, 0x00, 0x08,
+ 0xf3, 0x89, 0xa9, 0x30, 0xe0, 0x00, 0x21, 0x48, 0xfd, 0x89, 0xa9, 0x38, 0xfe, 0x88, 0xa9, 0x50,
+ 0xe0, 0x00, 0x20, 0x70, 0x9e, 0x96, 0xff, 0xe8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xcf, 0xfe, 0xf4, 0x00, 0xe6, 0x00, 0x21, 0x74,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x89, 0x9f, 0xd8, 0xff, 0x82, 0xbf, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xf7, 0x82, 0x21, 0xb0, 0xe0, 0x00, 0x21, 0x68, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0x9f, 0xd8, 0x20, 0x7e, 0x00, 0xfa, 0xe6, 0x00, 0x22, 0x49, 0x20, 0x7e, 0x00, 0xfb,
+ 0xe6, 0x00, 0x22, 0x2d, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x21, 0xc8, 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x21, 0xe0, 0x0f, 0x81, 0x00, 0xfa,
+ 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x21, 0xfc, 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0x14,
+ 0xff, 0x82, 0x00, 0xfa, 0xe0, 0x00, 0x22, 0x48, 0xff, 0x89, 0x9f, 0xd8, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0x2c, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x21, 0xc8, 0xff, 0x02, 0x00, 0x0f, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x9f, 0xd8,
+ 0x73, 0x19, 0x00, 0x18, 0x20, 0x7e, 0x00, 0xf9, 0xe6, 0x00, 0x22, 0xe1, 0x73, 0x18, 0xff, 0xe8,
+ 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x23, 0x35, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0x7c, 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0x94,
+ 0x0f, 0x81, 0x00, 0xf9, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0xb0, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x02, 0x03, 0x52, 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0xcc, 0xff, 0x82, 0x00, 0xf9, 0xff, 0x89, 0x9f, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x22, 0xe4,
+ 0x7f, 0x99, 0x00, 0x10, 0xff, 0x02, 0x00, 0x52, 0x9f, 0x02, 0xfe, 0xd8, 0x53, 0x7c, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x23, 0x04,
+ 0x0f, 0x98, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x23, 0x1c, 0xff, 0x82, 0x07, 0x53, 0xe0, 0x00, 0x23, 0x54,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x23, 0x34,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x0e, 0x54, 0x9f, 0x02, 0xfe, 0xd8, 0xe0, 0x00, 0x22, 0x7c,
+ 0xff, 0x02, 0x00, 0x0f, 0x9f, 0x82, 0xfe, 0xd8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04,
+ 0x93, 0x16, 0xff, 0xf4, 0x73, 0x18, 0xff, 0xe8, 0xf7, 0x82, 0x23, 0x84, 0xe0, 0x00, 0x22, 0x54,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4, 0x73, 0x7c, 0xff, 0xf0, 0x73, 0x19, 0x00, 0x18,
+ 0x73, 0x18, 0xff, 0xe8, 0xf7, 0x82, 0x23, 0xa0, 0xe0, 0x00, 0x22, 0x54, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x96, 0xff, 0xf4, 0x73, 0x7c, 0xff, 0xf8, 0x73, 0x19, 0x00, 0x18, 0x73, 0x18, 0xff, 0xe8,
+ 0xf7, 0x82, 0x23, 0xbc, 0xe0, 0x00, 0x22, 0x54, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4,
+ 0x73, 0x7d, 0x00, 0x18, 0x73, 0x18, 0xff, 0xe8, 0xf7, 0x82, 0x23, 0xd4, 0xe0, 0x00, 0x22, 0x54,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x9f, 0xd8, 0x73, 0x19, 0x00, 0x18,
+ 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x24, 0x79, 0x73, 0x18, 0xff, 0xe8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0x00, 0xff, 0x82, 0x01, 0x53,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x24, 0x18, 0x0f, 0x81, 0x00, 0xfb, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0x34,
+ 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0x4c, 0xff, 0x92, 0x00, 0x53, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0x64,
+ 0xff, 0x82, 0x00, 0xfb, 0xff, 0x89, 0x9f, 0xd8, 0x7f, 0x99, 0x00, 0x10, 0x53, 0x7c, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0x84,
+ 0x0f, 0x98, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x9f, 0xd8,
+ 0x73, 0x19, 0x00, 0x18, 0x20, 0x7e, 0x00, 0xfd, 0xe6, 0x00, 0x25, 0x2d, 0x73, 0x18, 0xff, 0xe8,
+ 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x25, 0x79, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0xcc, 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x24, 0xe4,
+ 0x0f, 0x81, 0x00, 0xfd, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x25, 0x00, 0xff, 0x82, 0x03, 0x52,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x25, 0x18, 0xff, 0x82, 0x00, 0xfd, 0xff, 0x89, 0x9f, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x25, 0x30, 0xff, 0x82, 0x00, 0x52,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x25, 0x48, 0xff, 0x82, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x25, 0x60, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xe0, 0x00, 0x25, 0x94, 0x7f, 0xfd, 0x00, 0x18, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x25, 0x78, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8, 0xe0, 0x00, 0x24, 0xcc,
+ 0xff, 0x02, 0x00, 0x0f, 0x7f, 0xfc, 0xff, 0xe8, 0xc0, 0x7e, 0x32, 0x00, 0xff, 0x82, 0x03, 0x52,
+ 0xe6, 0x20, 0x00, 0x02, 0x9f, 0x82, 0xfe, 0xd8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x9f, 0xd8,
+ 0x20, 0x7e, 0x00, 0xef, 0xe6, 0x00, 0x26, 0x39, 0xfe, 0x02, 0x01, 0xa4, 0x20, 0x7e, 0x00, 0xfb,
+ 0xe6, 0x00, 0x26, 0xe9, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x25, 0xd8, 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x25, 0xf0, 0x0f, 0x81, 0x00, 0xef,
+ 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x26, 0x0c, 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x26, 0x24,
+ 0xff, 0x82, 0x00, 0xef, 0xff, 0x89, 0x9f, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x26, 0x3c, 0xff, 0x82, 0x00, 0x52, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xfe, 0x82, 0x00, 0x0f, 0xff, 0x9b, 0x5f, 0xff, 0x2e, 0x70, 0x00, 0x08, 0x7f, 0xfd, 0x00, 0x10,
+ 0x0f, 0x7c, 0x00, 0x08, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x26, 0x64,
+ 0x0f, 0xf8, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0x20, 0x72, 0x00, 0x08, 0xee, 0x00, 0x26, 0x54,
+ 0xff, 0x02, 0x00, 0x01, 0xff, 0x9b, 0x5b, 0xff, 0x0e, 0xf0, 0x00, 0x07, 0x7f, 0xfd, 0x00, 0x10,
+ 0xcf, 0x78, 0xef, 0xc0, 0xcf, 0xfc, 0xe0, 0x00, 0xc3, 0x7c, 0xf0, 0x00, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x26, 0xa0, 0x0f, 0x98, 0x00, 0x50,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x26, 0xb8, 0xff, 0x82, 0x03, 0x92, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x26, 0xd0, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0x27, 0x04, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x26, 0xe8, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8, 0xe0, 0x00, 0x25, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0x9f, 0xd8, 0x20, 0x7e, 0x00, 0xef, 0xe6, 0x00, 0x27, 0xd9, 0x20, 0x7e, 0x00, 0xfb,
+ 0xe6, 0x00, 0x27, 0xbd, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x27, 0x58, 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x27, 0x70, 0x0f, 0x81, 0x00, 0xef,
+ 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x27, 0x8c, 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x27, 0xa4,
+ 0xff, 0x82, 0x00, 0xef, 0xe0, 0x00, 0x27, 0xd8, 0xff, 0x89, 0x9f, 0xd8, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x27, 0xbc, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x27, 0x58, 0xff, 0x02, 0x00, 0x0f, 0xff, 0x82, 0x06, 0x13, 0x9f, 0x82, 0xfe, 0xd8,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x82, 0x00, 0x01, 0x9f, 0x9a, 0x00, 0x00, 0xff, 0x82, 0x01, 0x21, 0x9f, 0x82, 0xfe, 0xd8,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x90, 0x1a, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfe, 0x02, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x01, 0xe6, 0x00, 0x28, 0x9d, 0xfe, 0x82, 0x00, 0xd8,
+ 0x20, 0x1e, 0x00, 0x02, 0xe6, 0x00, 0x2a, 0x45, 0xfe, 0x82, 0x02, 0x7c, 0xff, 0x88, 0x9f, 0xd8,
+ 0x20, 0x7e, 0x00, 0xdf, 0xe6, 0x00, 0x29, 0x19, 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x2a, 0x25,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x28, 0xb4,
+ 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x28, 0xcc, 0x0f, 0x81, 0x00, 0xdf, 0x0f, 0xfc, 0x80, 0x58,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x28, 0xe8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x03, 0x52, 0x9f, 0x02, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x29, 0x04,
+ 0xff, 0x82, 0x00, 0xdf, 0xff, 0x89, 0x9f, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x29, 0x1c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x83,
+ 0x9f, 0x02, 0xfe, 0xd8, 0x20, 0x72, 0x00, 0x00, 0xe6, 0x00, 0x29, 0x8d, 0xff, 0x02, 0x00, 0x0f,
+ 0x20, 0x72, 0x00, 0x08, 0xee, 0x00, 0x29, 0x75, 0x00, 0x00, 0x00, 0x01, 0x2e, 0x70, 0x00, 0x08,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x29, 0x50, 0xff, 0x82, 0x00, 0x58,
+ 0x9f, 0x82, 0xfe, 0xd8, 0x20, 0x72, 0x00, 0x08, 0xee, 0x00, 0x29, 0x4c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x29, 0x74,
+ 0x0f, 0xf0, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x29, 0x8c, 0x00, 0x00, 0x00, 0x01, 0x2e, 0xf4, 0x00, 0x08,
+ 0xfe, 0x02, 0x00, 0x58, 0x9e, 0x02, 0xfe, 0xd8, 0x20, 0x76, 0x00, 0x00, 0xee, 0x00, 0x29, 0xe1,
+ 0xff, 0x02, 0x00, 0x0f, 0x2e, 0xf4, 0x00, 0x08, 0x23, 0x18, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x29, 0xbc, 0xfe, 0x02, 0x00, 0x58, 0x9e, 0x02, 0xfe, 0xd8,
+ 0x7f, 0xfc, 0xff, 0xf0, 0x20, 0x76, 0x00, 0x00, 0xee, 0x00, 0x29, 0xb4, 0xff, 0x9b, 0x68, 0x00,
+ 0x23, 0x18, 0x00, 0x01, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x29, 0xe8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x07, 0x53, 0x9f, 0x02, 0xfe, 0xd8,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x00, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2a, 0x0c, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x2a, 0x50,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2a, 0x24,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x0e, 0x54, 0x9f, 0x02, 0xfe, 0xd8, 0xe0, 0x00, 0x28, 0xb4,
+ 0xff, 0x02, 0x00, 0x0f, 0xfe, 0x82, 0x01, 0xa4, 0xe0, 0x00, 0x28, 0x9c, 0xfe, 0x02, 0x00, 0xd8,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x9f, 0xd8,
+ 0x20, 0x7e, 0x00, 0xdf, 0xe6, 0x00, 0x2b, 0x25, 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x2b, 0x09,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2a, 0xa4,
+ 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2a, 0xbc, 0x0f, 0x81, 0x00, 0xdf, 0x0f, 0xfc, 0x80, 0x58,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2a, 0xd8, 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2a, 0xf0, 0xff, 0x82, 0x00, 0xdf,
+ 0xe0, 0x00, 0x2b, 0x24, 0xff, 0x89, 0x9f, 0xd8, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2b, 0x08, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8, 0xe0, 0x00, 0x2a, 0xa4,
+ 0xff, 0x02, 0x00, 0x0f, 0xff, 0x82, 0x00, 0x11, 0x9f, 0x82, 0xfe, 0xd8, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x82, 0x07, 0x13, 0x9f, 0x82, 0xfe, 0xd8, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x82, 0x00, 0x01, 0x9f, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x00, 0x2b, 0xb0, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x38,
+ 0xff, 0x88, 0x9f, 0xd8, 0xce, 0x18, 0x00, 0x00, 0x20, 0x7e, 0x00, 0x7f, 0xe6, 0x00, 0x2c, 0x31,
+ 0xc3, 0x1c, 0x00, 0x00, 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x2c, 0xed, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2b, 0xd0, 0xff, 0x82, 0x01, 0x53,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2b, 0xe8, 0x0f, 0x81, 0x00, 0x7f, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0x04,
+ 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0x1c, 0xff, 0x82, 0x00, 0x7f, 0xff, 0x89, 0x9f, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0x34,
+ 0xff, 0x82, 0x00, 0x52, 0x20, 0x1e, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0xd8, 0xee, 0x00, 0x2c, 0x85,
+ 0xfe, 0x82, 0x00, 0x0f, 0xff, 0xf3, 0x5f, 0xff, 0x23, 0x18, 0x00, 0x08, 0x7f, 0xfd, 0x00, 0x10,
+ 0x0f, 0x7c, 0x00, 0x08, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x2c, 0x64,
+ 0x0f, 0xf8, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0x20, 0x1a, 0x00, 0x08, 0xee, 0x00, 0x2c, 0x54,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0xf3, 0x5b, 0xff, 0x0e, 0x98, 0x00, 0x07, 0xff, 0x02, 0x00, 0x01,
+ 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xef, 0xc0, 0xcf, 0xfc, 0x30, 0x00, 0xc3, 0x7c, 0xf0, 0x00,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0xa4,
+ 0x0f, 0x98, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0xbc, 0xff, 0x82, 0x03, 0x92, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0xd4,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x2d, 0x08, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2c, 0xec, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x2b, 0xd0, 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x9f, 0xd8, 0x20, 0x7e, 0x00, 0x8f, 0xe6, 0x00, 0x2d, 0xc1,
+ 0xfe, 0x02, 0x01, 0x80, 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x2e, 0x71, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2d, 0x60, 0xff, 0x82, 0x01, 0x53,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2d, 0x78, 0x0f, 0x81, 0x00, 0x8f, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2d, 0x94,
+ 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2d, 0xac, 0xff, 0x82, 0x00, 0x8f, 0xff, 0x89, 0x9f, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2d, 0xc4,
+ 0xff, 0x82, 0x00, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xfe, 0x82, 0x00, 0x0f, 0xff, 0x9b, 0x5f, 0xff,
+ 0x2e, 0x70, 0x00, 0x08, 0x7f, 0xfd, 0x00, 0x10, 0x0f, 0x7c, 0x00, 0x08, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x2d, 0xec, 0x0f, 0xf8, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8,
+ 0x20, 0x72, 0x00, 0x08, 0xee, 0x00, 0x2d, 0xdc, 0xff, 0x02, 0x00, 0x01, 0xff, 0x9b, 0x5b, 0xff,
+ 0x0e, 0xf0, 0x00, 0x07, 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xef, 0xc0, 0xcf, 0xfc, 0xe0, 0x00,
+ 0xc3, 0x7c, 0xf0, 0x00, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2e, 0x28, 0x0f, 0x98, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2e, 0x40, 0xff, 0x82, 0x03, 0x92,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2e, 0x58, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x2e, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2e, 0x70, 0xff, 0x82, 0x0e, 0x54,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xe0, 0x00, 0x2d, 0x60, 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x88, 0x9f, 0xd8, 0x20, 0x76, 0x00, 0x9f,
+ 0xe6, 0x00, 0x2f, 0x49, 0x20, 0x76, 0x00, 0xfb, 0xe6, 0x00, 0x30, 0xf9, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2e, 0xe0, 0xff, 0x82, 0x01, 0x53,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2e, 0xf8, 0x0f, 0x81, 0x00, 0x9f, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2f, 0x14,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x03, 0x52, 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2f, 0x30, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x82, 0x00, 0x9f, 0xfe, 0x89, 0x9f, 0xd8, 0x7f, 0x99, 0x00, 0x12, 0x53, 0x7c, 0xe0, 0x08,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2f, 0x54,
+ 0x0f, 0x98, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0x20, 0x76, 0x00, 0xaf, 0xe6, 0x00, 0x2f, 0xe5,
+ 0x20, 0x76, 0x00, 0xfb, 0xe6, 0x00, 0x30, 0xdd, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x01, 0x53,
+ 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2f, 0x98, 0x0f, 0x81, 0x00, 0xaf, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2f, 0xb4,
+ 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x2f, 0xcc, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0xaf,
+ 0xff, 0x09, 0x9f, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x2f, 0xe8, 0xff, 0x82, 0x00, 0x53, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x02, 0x00, 0x58, 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x82, 0x00, 0x0f, 0x8f, 0x02, 0xfe, 0xd8,
+ 0xc0, 0x7a, 0xfc, 0x00, 0xe6, 0x00, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x81, 0x00, 0xff,
+ 0xcf, 0xf8, 0xfc, 0x00, 0xff, 0x02, 0x00, 0x58, 0x74, 0x7c, 0xff, 0xf0, 0x9f, 0x02, 0xfe, 0xd8,
+ 0xff, 0x82, 0x00, 0x0f, 0x8f, 0x02, 0xfe, 0xd8, 0xc0, 0x7a, 0xfc, 0x00, 0xe6, 0x00, 0x30, 0x44,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x81, 0x00, 0xff, 0xcf, 0xf8, 0xfc, 0x00, 0x7f, 0xfc, 0xff, 0xf8,
+ 0xff, 0x02, 0x00, 0x58, 0xc4, 0x20, 0xfd, 0x00, 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x82, 0x00, 0x0f,
+ 0x8f, 0x02, 0xfe, 0xd8, 0xc0, 0x7a, 0xfc, 0x00, 0xe6, 0x00, 0x30, 0x70, 0x00, 0x00, 0x00, 0x01,
+ 0x0f, 0x81, 0x00, 0xff, 0xcf, 0xf8, 0xfc, 0x00, 0xff, 0x02, 0x00, 0x58, 0xc4, 0x20, 0xfd, 0x00,
+ 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x82, 0x00, 0x0f, 0x8f, 0x02, 0xfe, 0xd8, 0xc0, 0x7a, 0xfc, 0x00,
+ 0xe6, 0x00, 0x30, 0x98, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x81, 0x00, 0xff, 0xcf, 0xf8, 0xfc, 0x00,
+ 0xff, 0x02, 0x07, 0x53, 0x7f, 0xfd, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0xd8, 0xc4, 0x20, 0xfd, 0x00,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x30, 0xc4,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x31, 0x18, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x30, 0xdc, 0xff, 0x82, 0x0e, 0x54, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x2f, 0x7c, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x30, 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x0e, 0x54, 0x9f, 0x02, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x2e, 0xe0, 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x9f, 0xd8, 0x20, 0x7e, 0x00, 0xbf, 0xe6, 0x00, 0x31, 0xcd,
+ 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x32, 0x21, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x31, 0x6c, 0xff, 0x82, 0x01, 0x53, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x31, 0x84,
+ 0x0f, 0x81, 0x00, 0xbf, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x31, 0xa0, 0xff, 0x82, 0x03, 0x52,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x31, 0xb8, 0xff, 0x82, 0x00, 0xbf, 0xff, 0x89, 0x9f, 0xd8, 0x7f, 0x99, 0x00, 0x12,
+ 0x53, 0x7c, 0x40, 0x07, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x31, 0xd8, 0x0f, 0x98, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x31, 0xf0, 0xff, 0x82, 0x03, 0x52,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x32, 0x08, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x32, 0x3c, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x32, 0x20, 0xff, 0x82, 0x0e, 0x54,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xe0, 0x00, 0x31, 0x6c, 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x9f, 0xd8, 0x20, 0x7e, 0x00, 0xcf,
+ 0xe6, 0x00, 0x32, 0xf5, 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x33, 0xd9, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x32, 0x90, 0xff, 0x82, 0x01, 0x53,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x32, 0xa8, 0x0f, 0x81, 0x00, 0xcf, 0x0f, 0xfc, 0x80, 0x58, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x32, 0xc4,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x03, 0x52, 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x32, 0xe0, 0xff, 0x82, 0x00, 0xcf,
+ 0xff, 0x89, 0x9f, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x32, 0xf8, 0x7f, 0x9d, 0x00, 0x10, 0xff, 0x02, 0x00, 0x53, 0x9f, 0x02, 0xfe, 0xd8,
+ 0x53, 0xfc, 0x00, 0x08, 0xfe, 0x82, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xec, 0x00,
+ 0xe6, 0x00, 0x33, 0x18, 0xff, 0x82, 0x00, 0xff, 0x0f, 0x1c, 0x00, 0x50, 0xcf, 0x98, 0xfc, 0x00,
+ 0x7f, 0xfd, 0x00, 0x10, 0x9f, 0x02, 0xfe, 0xd8, 0x5f, 0x7c, 0x00, 0x08, 0xff, 0x82, 0x00, 0x0f,
+ 0x84, 0x02, 0xfe, 0xd8, 0xc0, 0x22, 0xfc, 0x00, 0xe6, 0x00, 0x33, 0x40, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x82, 0xff, 0x00, 0x0f, 0x78, 0x00, 0x50, 0xcf, 0x98, 0xfc, 0x00, 0x7f, 0xfd, 0x00, 0x08,
+ 0x9f, 0x02, 0xfe, 0xd8, 0x5f, 0x7c, 0x00, 0x08, 0xfe, 0x82, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x33, 0x6c, 0x0f, 0x81, 0x00, 0xff, 0x0f, 0x78, 0x00, 0x50,
+ 0xcf, 0x98, 0xfc, 0x00, 0x9f, 0x02, 0xfe, 0xd8, 0x53, 0x7c, 0x80, 0x08, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x33, 0x90, 0x0f, 0x98, 0x00, 0x50,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x33, 0xa8, 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x33, 0xc0, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0x33, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x33, 0xd8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x0e, 0x54, 0x9f, 0x02, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x32, 0x90, 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x74, 0x20, 0xff, 0xf0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x83, 0x5b, 0xd8, 0x70, 0x7e, 0x00, 0x1e,
+ 0xea, 0x00, 0x34, 0x95, 0x00, 0x00, 0x00, 0x01, 0xff, 0x83, 0x5b, 0xd8, 0x0e, 0x81, 0x01, 0x00,
+ 0x5f, 0xfc, 0x00, 0x02, 0xff, 0x83, 0x6b, 0xd8, 0x0f, 0x81, 0x01, 0x00, 0x9f, 0x82, 0xff, 0xf8,
+ 0x8f, 0x02, 0xff, 0xd0, 0x8f, 0x82, 0xff, 0xd0, 0xcf, 0xfc, 0xf2, 0x00, 0x20, 0x7e, 0x00, 0x13,
+ 0xe2, 0x00, 0x34, 0x65, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xf8, 0xc0, 0x7e, 0xec, 0x00,
+ 0xe6, 0x00, 0x34, 0x5c, 0x0f, 0x81, 0x01, 0x00, 0xf7, 0x82, 0x34, 0x94, 0xe0, 0x00, 0x21, 0x68,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x83, 0x5b, 0xd8, 0x4f, 0xfc, 0xff, 0xfd,
+ 0xff, 0x83, 0x6b, 0xd8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0x93, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x34, 0xdc, 0xe0, 0x00, 0x34, 0x30, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x34, 0xec, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x34, 0xf8,
+ 0xe0, 0x00, 0x34, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0x93, 0x16, 0xff, 0xf4, 0x93, 0x96, 0xff, 0xf0, 0xf7, 0x82, 0x35, 0x24, 0xe0, 0x00, 0x34, 0x30,
+ 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4, 0x83, 0x96, 0xff, 0xf0, 0xf7, 0x82, 0x35, 0x38,
+ 0xe0, 0x00, 0x28, 0x78, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x35, 0x44, 0xe0, 0x00, 0x34, 0xa0,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0x93, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x35, 0x6c, 0xe0, 0x00, 0x34, 0x30, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x35, 0x7c, 0xe0, 0x00, 0x2d, 0x3c, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x35, 0x88,
+ 0xe0, 0x00, 0x34, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x02, 0x00, 0x0f,
+ 0x84, 0x02, 0xfe, 0xd8, 0xc0, 0x22, 0xf4, 0x00, 0xe6, 0x00, 0x35, 0xa0, 0x0f, 0x98, 0x00, 0x50,
+ 0x9f, 0x82, 0xfe, 0xd8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x9f, 0xd8, 0xc0, 0x7e, 0x32, 0x00,
+ 0xe6, 0x00, 0x36, 0x91, 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x36, 0x71, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x35, 0xe0, 0x7f, 0x99, 0x00, 0x10,
+ 0xff, 0x02, 0x01, 0x53, 0x9f, 0x02, 0xfe, 0xd8, 0x5e, 0xfc, 0x80, 0x08, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x36, 0x00, 0x0f, 0xf4, 0x00, 0x50,
+ 0x9f, 0x82, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x36, 0x18, 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0x20, 0x1a, 0x00, 0xfb,
+ 0xe6, 0x00, 0x36, 0x51, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x36, 0x38, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x36, 0x90, 0xf3, 0x09, 0x9f, 0xd8,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x36, 0x50, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x12, 0x00, 0x53, 0x9f, 0x02, 0xfe, 0xd8, 0xe0, 0x00, 0x36, 0x38, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x36, 0x70, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x02, 0x0e, 0x54, 0x9f, 0x02, 0xfe, 0xd8, 0xe0, 0x00, 0x35, 0xe0, 0xff, 0x02, 0x00, 0x0f,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x9f, 0xd8, 0xc0, 0x7e, 0x32, 0x00, 0xe6, 0x00, 0x37, 0x29,
+ 0x20, 0x7e, 0x00, 0xfb, 0xe6, 0x00, 0x38, 0x09, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x36, 0xbc, 0x7f, 0x99, 0x00, 0x10, 0xff, 0x02, 0x01, 0x53,
+ 0x9f, 0x02, 0xfe, 0xd8, 0x5e, 0xfc, 0x80, 0x08, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x36, 0xdc, 0x0f, 0xf4, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x36, 0xf4,
+ 0xff, 0x82, 0x03, 0x52, 0x9f, 0x82, 0xfe, 0xd8, 0x20, 0x1a, 0x00, 0xfb, 0xe6, 0x00, 0x37, 0xe9,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x37, 0x14,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x09, 0x9f, 0xd8, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x37, 0x2c, 0xff, 0x82, 0x00, 0x52, 0x9f, 0x82, 0xfe, 0xd8,
+ 0x20, 0x22, 0x00, 0x08, 0xee, 0x00, 0x37, 0x7d, 0xfe, 0x82, 0x00, 0x0f, 0xff, 0x9f, 0x5f, 0xff,
+ 0x24, 0x20, 0x00, 0x08, 0x7f, 0xfd, 0x00, 0x10, 0x0f, 0x7c, 0x00, 0x08, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x37, 0x5c, 0x0f, 0xf8, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8,
+ 0x20, 0x22, 0x00, 0x08, 0xee, 0x00, 0x37, 0x4c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x9f, 0x5b, 0xff,
+ 0x0e, 0xa0, 0x00, 0x07, 0xff, 0x02, 0x00, 0x01, 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xef, 0xc0,
+ 0xcf, 0xfc, 0x40, 0x00, 0xc3, 0xfc, 0xf0, 0x00, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x37, 0x9c, 0x0f, 0x9c, 0x00, 0x50, 0x9f, 0x82, 0xfe, 0xd8,
+ 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x37, 0xb4,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x03, 0x92, 0x9f, 0x02, 0xfe, 0xd8, 0xff, 0x02, 0x00, 0x0f,
+ 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x37, 0xd0, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0x38, 0x28, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x37, 0xe8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x12, 0x00, 0x53, 0x9f, 0x02, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x37, 0x14, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0x82, 0xfe, 0xd8, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x38, 0x08, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x0e, 0x54, 0x9f, 0x02, 0xfe, 0xd8,
+ 0xe0, 0x00, 0x36, 0xbc, 0xff, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x03, 0x03, 0x02, 0x03, 0x01, 0x02, 0x01, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x07, 0x03, 0x04, 0x03, 0x05, 0x03, 0x04, 0x03, 0x06, 0x03, 0x04, 0x03, 0x05, 0x03, 0x04, 0x03,
+ 0x07, 0x02, 0x03, 0x02, 0x04, 0x02, 0x03, 0x02, 0x05, 0x02, 0x03, 0x02, 0x04, 0x02, 0x03, 0x02,
+ 0x06, 0x02, 0x03, 0x02, 0x04, 0x02, 0x03, 0x02, 0x05, 0x02, 0x03, 0x02, 0x04, 0x02, 0x03, 0x02,
+ 0x07, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01,
+ 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01,
+ 0x06, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01,
+ 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x04, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01,
+ 0x07, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x06, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x07, 0x08,
+ 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x61, 0x63,
+ 0x63, 0x65, 0x73, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x42, 0x41, 0x52, 0x32, 0x3a, 0x20, 0x30, 0x78,
+ 0x25, 0x78, 0x2c, 0x20, 0x6c, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x4d, 0x77, 0x72, 0x20, 0x74, 0x6f,
+ 0x20, 0x4d, 0x53, 0x49, 0x58, 0x20, 0x50, 0x42, 0x41, 0x3a, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2c,
+ 0x20, 0x6c, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x72,
+ 0x65, 0x61, 0x64, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x42, 0x41,
+ 0x52, 0x32, 0x3a, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x6c, 0x3d, 0x25, 0x64, 0x0a, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x40, 0x88, 0x96, 0x00, 0x00,
+ 0x8d, 0x16, 0x00, 0x04, 0x93, 0x16, 0xff, 0xe4, 0xcd, 0xa0, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x00,
+ 0xe6, 0x00, 0x54, 0xf5, 0xcc, 0xa4, 0x00, 0x00, 0xff, 0xfa, 0x7f, 0xff, 0xc0, 0x22, 0xfa, 0x00,
+ 0xe2, 0x00, 0x3a, 0x2d, 0x00, 0x00, 0x00, 0x01, 0x2d, 0xa0, 0x80, 0x00, 0x70, 0x66, 0x00, 0x0c,
+ 0xea, 0x00, 0x3a, 0x49, 0xff, 0xbe, 0xf0, 0x00, 0x20, 0x46, 0x00, 0x02, 0xe2, 0x00, 0x73, 0x31,
+ 0xc4, 0x44, 0x00, 0x00, 0xff, 0xbe, 0xf0, 0x00, 0xcf, 0xe4, 0xfc, 0x00, 0x20, 0x7f, 0x00, 0x08,
+ 0xe6, 0x00, 0x54, 0xa1, 0x20, 0x46, 0x00, 0x01, 0xff, 0x3e, 0xfe, 0x00, 0xcf, 0xe4, 0xf4, 0x00,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x3d, 0x55, 0x20, 0x46, 0x00, 0x01, 0xff, 0xbe, 0x80, 0x00,
+ 0xcf, 0xe4, 0xfc, 0x00, 0x20, 0x7f, 0x00, 0x0f, 0xe6, 0x00, 0x3a, 0xf1, 0xff, 0xbe, 0xff, 0x00,
+ 0xcf, 0xe4, 0xfc, 0x00, 0xff, 0x3e, 0x90, 0x00, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x3a, 0xc1,
+ 0xff, 0x02, 0x39, 0x80, 0x22, 0x10, 0x00, 0x0c, 0x98, 0x92, 0x00, 0x08, 0x98, 0x96, 0xff, 0xdc,
+ 0x9c, 0x92, 0x00, 0x04, 0x9f, 0x12, 0x00, 0x00, 0xf7, 0x82, 0x3a, 0xb4, 0xe0, 0x02, 0x87, 0x0c,
+ 0x97, 0x93, 0xff, 0xfc, 0x88, 0x96, 0xff, 0xdc, 0xe0, 0x00, 0x73, 0x30, 0xc4, 0x44, 0x00, 0x00,
+ 0x22, 0x10, 0x00, 0x0c, 0xfe, 0x02, 0x39, 0xaa, 0x98, 0x92, 0x00, 0x08, 0x9c, 0x92, 0x00, 0x04,
+ 0x9e, 0x12, 0x00, 0x00, 0x98, 0x96, 0xff, 0xdc, 0xf7, 0x82, 0x3a, 0xe4, 0xe0, 0x02, 0x87, 0x0c,
+ 0x97, 0x93, 0xff, 0xfc, 0x88, 0x96, 0xff, 0xdc, 0xe0, 0x00, 0x3a, 0xb8, 0x02, 0x10, 0x00, 0x0c,
+ 0x4e, 0xe5, 0x00, 0x0f, 0x0f, 0xf5, 0xff, 0xf1, 0x7a, 0x7c, 0xff, 0xfc, 0xff, 0x0a, 0x97, 0xc0,
+ 0x79, 0x51, 0x00, 0x04, 0xcf, 0xc8, 0xf0, 0x00, 0x8d, 0x7e, 0x00, 0x0c, 0xce, 0xf4, 0xf0, 0x00,
+ 0x2e, 0x44, 0x00, 0x01, 0xcf, 0x84, 0x00, 0x00, 0xc8, 0x78, 0x00, 0x00, 0xc0, 0x72, 0xfa, 0x00,
+ 0xe6, 0x00, 0x3b, 0x41, 0x03, 0x75, 0xff, 0xf1, 0x4d, 0xec, 0x7f, 0xff, 0x8f, 0x6d, 0x00, 0x04,
+ 0x2e, 0x70, 0x00, 0x01, 0xc0, 0x72, 0xfa, 0x00, 0xe6, 0x00, 0x3b, 0x28, 0x9f, 0x19, 0x00, 0x04,
+ 0x0f, 0x01, 0x01, 0x00, 0xc0, 0x6a, 0xf4, 0x00, 0xe6, 0x00, 0x3c, 0x69, 0x7c, 0x51, 0xff, 0xfd,
+ 0xc9, 0xc8, 0x80, 0x00, 0x8f, 0xce, 0x00, 0x0c, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x3c, 0x6c,
+ 0xfb, 0x8a, 0x9f, 0xc0, 0xff, 0x8a, 0x9f, 0xfe, 0x8e, 0xce, 0x00, 0x04, 0xfa, 0xff, 0x18, 0x00,
+ 0xff, 0x02, 0xff, 0x00, 0xab, 0xca, 0x80, 0x02, 0x7f, 0xf4, 0xff, 0xf8, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x7c, 0x74, 0xff, 0xe8, 0xcc, 0x60, 0xfd, 0x00, 0xff, 0x8a, 0x9f, 0xf6, 0xf6, 0xff, 0x18, 0x00,
+ 0xce, 0x74, 0xf4, 0x00, 0x7d, 0xdc, 0xff, 0xf8, 0x87, 0x4e, 0x00, 0x08, 0x20, 0x76, 0x00, 0x00,
+ 0xcd, 0xec, 0xf4, 0x00, 0x7e, 0x71, 0x00, 0x08, 0x7d, 0x51, 0x00, 0x03, 0xe6, 0x58, 0x00, 0x02,
+ 0xcd, 0x68, 0xa0, 0x00, 0xcf, 0x5c, 0xf4, 0x00, 0x7c, 0xdc, 0xff, 0xe8, 0xcc, 0x60, 0xe5, 0x00,
+ 0xce, 0x68, 0xb0, 0x00, 0x5f, 0xd8, 0x00, 0x02, 0xcc, 0xe4, 0xdd, 0x00, 0x7f, 0x79, 0x00, 0x08,
+ 0xfd, 0x8a, 0xd3, 0xf0, 0x7e, 0xf5, 0x00, 0x18, 0x7d, 0x69, 0x00, 0x02, 0xcc, 0xe4, 0xf5, 0x00,
+ 0x79, 0xfd, 0x00, 0x0d, 0x7a, 0xd5, 0x00, 0x0f, 0xcf, 0xe8, 0xd8, 0x00, 0xcc, 0x60, 0xed, 0x00,
+ 0x5a, 0xd4, 0x00, 0x01, 0x7e, 0x71, 0x00, 0x02, 0x7b, 0xdd, 0x00, 0x18, 0x7b, 0x59, 0x00, 0x02,
+ 0xff, 0x02, 0x40, 0x00, 0x9c, 0x7e, 0x00, 0x18, 0xff, 0x7f, 0x28, 0x0c, 0xf9, 0xff, 0x28, 0x10,
+ 0xfa, 0xff, 0x28, 0x12, 0xf6, 0xff, 0x28, 0x14, 0xce, 0x70, 0xd8, 0x00, 0xcc, 0xe4, 0xbd, 0x00,
+ 0x0e, 0xd8, 0x00, 0x14, 0xbe, 0xea, 0xd8, 0x02, 0x97, 0x72, 0x00, 0x1c, 0x20, 0x52, 0x00, 0x00,
+ 0xe6, 0x00, 0x3c, 0x64, 0x9c, 0xf2, 0x00, 0x18, 0xff, 0x8a, 0xa9, 0x70, 0xfe, 0x02, 0x40, 0x00,
+ 0xf9, 0xff, 0x28, 0x10, 0xfa, 0xff, 0x28, 0x12, 0xf6, 0xff, 0x28, 0x14, 0xfc, 0x09, 0xa9, 0x88,
+ 0xcf, 0x58, 0xf8, 0x00, 0xfe, 0x7f, 0x28, 0x0c, 0x97, 0x7a, 0x00, 0x1c, 0x9c, 0xfa, 0x00, 0x18,
+ 0xfe, 0x89, 0xa9, 0x70, 0x7c, 0x51, 0xff, 0xfd, 0xfb, 0x8a, 0x9f, 0xc0, 0xfe, 0x82, 0x00, 0x07,
+ 0xaf, 0x62, 0xb8, 0x04, 0xcf, 0xd0, 0xec, 0x00, 0xcd, 0xf4, 0xfa, 0x00, 0xce, 0x00, 0xda, 0x00,
+ 0xcf, 0x78, 0xe7, 0xc0, 0xab, 0x62, 0xb8, 0x05, 0xfe, 0x02, 0x00, 0x01, 0xc0, 0x7a, 0xe4, 0x00,
+ 0xe6, 0x00, 0x73, 0x31, 0xc4, 0x44, 0x00, 0x00, 0xcf, 0xc8, 0x80, 0x00, 0x8f, 0x7e, 0x00, 0x0c,
+ 0x70, 0x7a, 0x00, 0x07, 0xea, 0x00, 0x73, 0x31, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x92, 0xc8,
+ 0xcf, 0xfc, 0xe7, 0xc0, 0x7a, 0xfe, 0xff, 0xe1, 0xe6, 0x00, 0x73, 0x30, 0x7e, 0xd1, 0x00, 0x03,
+ 0xce, 0xf4, 0xa0, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xfd, 0x0a, 0xd3, 0xf0, 0xcf, 0xf4, 0xd0, 0x00,
+ 0xcf, 0x70, 0xdf, 0xc0, 0xfe, 0x08, 0xd3, 0xd8, 0x8c, 0xfe, 0x00, 0x08, 0xad, 0xf6, 0xd0, 0x02,
+ 0xcf, 0x04, 0xf6, 0x00, 0xcf, 0x58, 0xf4, 0x00, 0xbf, 0x62, 0xb8, 0x04, 0xff, 0x8a, 0xd3, 0xfc,
+ 0xff, 0x02, 0x00, 0x40, 0xce, 0xf4, 0xf8, 0x00, 0x9f, 0x72, 0x00, 0x30, 0xff, 0xf3, 0x18, 0x0a,
+ 0x8f, 0x72, 0x00, 0x2c, 0x9e, 0xf2, 0x00, 0x24, 0x9d, 0xf2, 0x00, 0x28, 0xff, 0xf7, 0x28, 0x02,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0x0c, 0xe4, 0x00, 0x08,
+ 0x9c, 0xf2, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x09, 0xd3, 0xd8, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0xfb, 0x28, 0x00, 0x9f, 0xfa, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0xfa, 0xf3, 0x28, 0x02, 0xff, 0x88, 0xa0, 0x5c, 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x89, 0xa0, 0x5c, 0xe2, 0x00, 0x3a, 0x70, 0xff, 0xbe, 0x80, 0x00, 0x8c, 0x6e, 0x00, 0x04,
+ 0x83, 0xee, 0x00, 0x00, 0x2f, 0x80, 0x02, 0x00, 0x20, 0x6a, 0x00, 0xff, 0xe2, 0x00, 0x3a, 0xb8,
+ 0xc3, 0x64, 0xfd, 0x00, 0x7f, 0xe9, 0x00, 0x02, 0xff, 0x02, 0x3d, 0x88, 0xae, 0xfe, 0xf0, 0x02,
+ 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x3a, 0xb8, 0x00, 0x00, 0x41, 0x94,
+ 0x00, 0x00, 0x41, 0xa0, 0x00, 0x00, 0x41, 0xac, 0x00, 0x00, 0x41, 0xb8, 0x00, 0x00, 0x41, 0xc4,
+ 0x00, 0x00, 0x41, 0xd8, 0x00, 0x00, 0x41, 0xec, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x42, 0x08,
+ 0x00, 0x00, 0x42, 0x18, 0x00, 0x00, 0x42, 0x28, 0x00, 0x00, 0x42, 0x30, 0x00, 0x00, 0x42, 0x38,
+ 0x00, 0x00, 0x42, 0x40, 0x00, 0x00, 0x42, 0x48, 0x00, 0x00, 0x42, 0x50, 0x00, 0x00, 0x42, 0x5c,
+ 0x00, 0x00, 0x42, 0x70, 0x00, 0x00, 0x42, 0x84, 0x00, 0x00, 0x42, 0x98, 0x00, 0x00, 0x42, 0xac,
+ 0x00, 0x00, 0x42, 0xc8, 0x00, 0x00, 0x42, 0xe4, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x43, 0x10,
+ 0x00, 0x00, 0x43, 0x28, 0x00, 0x00, 0x43, 0x40, 0x00, 0x00, 0x43, 0x48, 0x00, 0x00, 0x43, 0x58,
+ 0x00, 0x00, 0x43, 0x60, 0x00, 0x00, 0x43, 0x68, 0x00, 0x00, 0x43, 0x70, 0x00, 0x00, 0x43, 0x7c,
+ 0x00, 0x00, 0x43, 0x90, 0x00, 0x00, 0x43, 0xa4, 0x00, 0x00, 0x43, 0xb8, 0x00, 0x00, 0x43, 0xcc,
+ 0x00, 0x00, 0x43, 0xe8, 0x00, 0x00, 0x44, 0x04, 0x00, 0x00, 0x44, 0x20, 0x00, 0x00, 0x44, 0x30,
+ 0x00, 0x00, 0x44, 0x48, 0x00, 0x00, 0x44, 0x60, 0x00, 0x00, 0x44, 0x68, 0x00, 0x00, 0x44, 0x78,
+ 0x00, 0x00, 0x44, 0x80, 0x00, 0x00, 0x44, 0x88, 0x00, 0x00, 0x44, 0x90, 0x00, 0x00, 0x44, 0x9c,
+ 0x00, 0x00, 0x44, 0xb0, 0x00, 0x00, 0x44, 0xc4, 0x00, 0x00, 0x44, 0xd8, 0x00, 0x00, 0x44, 0xec,
+ 0x00, 0x00, 0x45, 0x08, 0x00, 0x00, 0x45, 0x24, 0x00, 0x00, 0x45, 0x40, 0x00, 0x00, 0x45, 0x50,
+ 0x00, 0x00, 0x45, 0x68, 0x00, 0x00, 0x45, 0x80, 0x00, 0x00, 0x45, 0x88, 0x00, 0x00, 0x45, 0x98,
+ 0x00, 0x00, 0x45, 0xa0, 0x00, 0x00, 0x45, 0xa8, 0x00, 0x00, 0x45, 0xb0, 0x00, 0x00, 0x45, 0xbc,
+ 0x00, 0x00, 0x45, 0xd0, 0x00, 0x00, 0x45, 0xe4, 0x00, 0x00, 0x45, 0xf8, 0x00, 0x00, 0x46, 0x0c,
+ 0x00, 0x00, 0x46, 0x28, 0x00, 0x00, 0x46, 0x44, 0x00, 0x00, 0x46, 0x60, 0x00, 0x00, 0x46, 0x70,
+ 0x00, 0x00, 0x46, 0x88, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x00, 0x46, 0xa8, 0x00, 0x00, 0x46, 0xb8,
+ 0x00, 0x00, 0x46, 0xc0, 0x00, 0x00, 0x46, 0xc8, 0x00, 0x00, 0x46, 0xd0, 0x00, 0x00, 0x46, 0xe4,
+ 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x47, 0x1c, 0x00, 0x00, 0x47, 0x38, 0x00, 0x00, 0x47, 0x54,
+ 0x00, 0x00, 0x47, 0x78, 0x00, 0x00, 0x47, 0x9c, 0x00, 0x00, 0x47, 0xc0, 0x00, 0x00, 0x47, 0xd8,
+ 0x00, 0x00, 0x47, 0xf8, 0x00, 0x00, 0x48, 0x18, 0x00, 0x00, 0x48, 0x20, 0x00, 0x00, 0x48, 0x38,
+ 0x00, 0x00, 0x48, 0x40, 0x00, 0x00, 0x48, 0x48, 0x00, 0x00, 0x48, 0x50, 0x00, 0x00, 0x48, 0x64,
+ 0x00, 0x00, 0x48, 0x80, 0x00, 0x00, 0x48, 0x9c, 0x00, 0x00, 0x48, 0xb8, 0x00, 0x00, 0x48, 0xd4,
+ 0x00, 0x00, 0x48, 0xf8, 0x00, 0x00, 0x49, 0x1c, 0x00, 0x00, 0x49, 0x40, 0x00, 0x00, 0x49, 0x58,
+ 0x00, 0x00, 0x49, 0x78, 0x00, 0x00, 0x49, 0x98, 0x00, 0x00, 0x49, 0xa0, 0x00, 0x00, 0x49, 0xb8,
+ 0x00, 0x00, 0x49, 0xc0, 0x00, 0x00, 0x49, 0xc8, 0x00, 0x00, 0x49, 0xd0, 0x00, 0x00, 0x49, 0xe4,
+ 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x4a, 0x1c, 0x00, 0x00, 0x4a, 0x38, 0x00, 0x00, 0x4a, 0x54,
+ 0x00, 0x00, 0x4a, 0x78, 0x00, 0x00, 0x4a, 0x9c, 0x00, 0x00, 0x4a, 0xc0, 0x00, 0x00, 0x4a, 0xd8,
+ 0x00, 0x00, 0x4a, 0xf8, 0x00, 0x00, 0x4b, 0x18, 0x00, 0x00, 0x4b, 0x20, 0x00, 0x00, 0x4b, 0x38,
+ 0x00, 0x00, 0x4b, 0x40, 0x00, 0x00, 0x4b, 0x48, 0x00, 0x00, 0x4b, 0x50, 0x00, 0x00, 0x4b, 0x58,
+ 0x00, 0x00, 0x4b, 0x68, 0x00, 0x00, 0x4b, 0x78, 0x00, 0x00, 0x4b, 0x88, 0x00, 0x00, 0x4b, 0x98,
+ 0x00, 0x00, 0x4b, 0xb0, 0x00, 0x00, 0x4b, 0xc8, 0x00, 0x00, 0x4b, 0xe0, 0x00, 0x00, 0x4b, 0xec,
+ 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4c, 0x14, 0x00, 0x00, 0x4c, 0x1c, 0x00, 0x00, 0x4c, 0x28,
+ 0x00, 0x00, 0x4c, 0x30, 0x00, 0x00, 0x4c, 0x38, 0x00, 0x00, 0x4c, 0x40, 0x00, 0x00, 0x4c, 0x50,
+ 0x00, 0x00, 0x4c, 0x68, 0x00, 0x00, 0x4c, 0x80, 0x00, 0x00, 0x4c, 0x98, 0x00, 0x00, 0x4c, 0xb0,
+ 0x00, 0x00, 0x4c, 0xd0, 0x00, 0x00, 0x4c, 0xf0, 0x00, 0x00, 0x4d, 0x10, 0x00, 0x00, 0x4d, 0x24,
+ 0x00, 0x00, 0x4d, 0x40, 0x00, 0x00, 0x4d, 0x5c, 0x00, 0x00, 0x4d, 0x64, 0x00, 0x00, 0x4d, 0x78,
+ 0x00, 0x00, 0x4d, 0x80, 0x00, 0x00, 0x4d, 0x88, 0x00, 0x00, 0x4d, 0x90, 0x00, 0x00, 0x4d, 0xa0,
+ 0x00, 0x00, 0x4d, 0xb8, 0x00, 0x00, 0x4d, 0xd0, 0x00, 0x00, 0x4d, 0xe8, 0x00, 0x00, 0x4e, 0x00,
+ 0x00, 0x00, 0x4e, 0x20, 0x00, 0x00, 0x4e, 0x40, 0x00, 0x00, 0x4e, 0x60, 0x00, 0x00, 0x4e, 0x74,
+ 0x00, 0x00, 0x4e, 0x90, 0x00, 0x00, 0x4e, 0xac, 0x00, 0x00, 0x4e, 0xb4, 0x00, 0x00, 0x4e, 0xc8,
+ 0x00, 0x00, 0x4e, 0xd0, 0x00, 0x00, 0x4e, 0xd8, 0x00, 0x00, 0x4e, 0xe0, 0x00, 0x00, 0x4e, 0xf0,
+ 0x00, 0x00, 0x4f, 0x08, 0x00, 0x00, 0x4f, 0x20, 0x00, 0x00, 0x4f, 0x38, 0x00, 0x00, 0x4f, 0x50,
+ 0x00, 0x00, 0x4f, 0x70, 0x00, 0x00, 0x4f, 0x90, 0x00, 0x00, 0x4f, 0xb0, 0x00, 0x00, 0x4f, 0xc4,
+ 0x00, 0x00, 0x4f, 0xe0, 0x00, 0x00, 0x4f, 0xfc, 0x00, 0x00, 0x50, 0x04, 0x00, 0x00, 0x50, 0x18,
+ 0x00, 0x00, 0x50, 0x20, 0x00, 0x00, 0x50, 0x28, 0x00, 0x00, 0x50, 0x30, 0x00, 0x00, 0x50, 0x38,
+ 0x00, 0x00, 0x50, 0x48, 0x00, 0x00, 0x50, 0x58, 0x00, 0x00, 0x50, 0x68, 0x00, 0x00, 0x50, 0x78,
+ 0x00, 0x00, 0x50, 0x90, 0x00, 0x00, 0x50, 0xa8, 0x00, 0x00, 0x50, 0xc0, 0x00, 0x00, 0x50, 0xcc,
+ 0x00, 0x00, 0x50, 0xe0, 0x00, 0x00, 0x50, 0xf4, 0x00, 0x00, 0x50, 0xfc, 0x00, 0x00, 0x51, 0x08,
+ 0x00, 0x00, 0x51, 0x10, 0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x51, 0x20, 0x00, 0x00, 0x51, 0x30,
+ 0x00, 0x00, 0x51, 0x48, 0x00, 0x00, 0x51, 0x60, 0x00, 0x00, 0x51, 0x78, 0x00, 0x00, 0x51, 0x90,
+ 0x00, 0x00, 0x51, 0xb0, 0x00, 0x00, 0x51, 0xd0, 0x00, 0x00, 0x51, 0xf0, 0x00, 0x00, 0x52, 0x04,
+ 0x00, 0x00, 0x52, 0x20, 0x00, 0x00, 0x52, 0x3c, 0x00, 0x00, 0x52, 0x44, 0x00, 0x00, 0x52, 0x58,
+ 0x00, 0x00, 0x52, 0x60, 0x00, 0x00, 0x52, 0x68, 0x00, 0x00, 0x52, 0x70, 0x00, 0x00, 0x52, 0x80,
+ 0x00, 0x00, 0x52, 0x98, 0x00, 0x00, 0x52, 0xb0, 0x00, 0x00, 0x52, 0xc8, 0x00, 0x00, 0x52, 0xe0,
+ 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x53, 0x20, 0x00, 0x00, 0x53, 0x40, 0x00, 0x00, 0x53, 0x54,
+ 0x00, 0x00, 0x53, 0x70, 0x00, 0x00, 0x53, 0x8c, 0x00, 0x00, 0x53, 0x94, 0x00, 0x00, 0x53, 0xa8,
+ 0x00, 0x00, 0x53, 0xb0, 0x00, 0x00, 0x53, 0xb8, 0x00, 0x00, 0x41, 0x8c, 0x00, 0x00, 0x53, 0xc0,
+ 0x00, 0x00, 0x53, 0xd0, 0x00, 0x00, 0x53, 0xe0, 0x00, 0x00, 0x53, 0xf0, 0x00, 0x00, 0x54, 0x00,
+ 0x00, 0x00, 0x54, 0x18, 0x00, 0x00, 0x54, 0x30, 0x00, 0x00, 0x54, 0x48, 0x00, 0x00, 0x54, 0x54,
+ 0x00, 0x00, 0x54, 0x68, 0x00, 0x00, 0x54, 0x7c, 0x00, 0x00, 0x54, 0x84, 0x00, 0x00, 0x54, 0x90,
+ 0x00, 0x00, 0x54, 0x98, 0x00, 0x00, 0x41, 0x88, 0x93, 0x9a, 0x00, 0x00, 0xe0, 0x00, 0x3a, 0xb8,
+ 0x9c, 0x1a, 0x00, 0x04, 0x7f, 0x9c, 0xff, 0xe8, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00,
+ 0x7f, 0x9c, 0xff, 0xf0, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00, 0x7f, 0x9c, 0xff, 0xf8, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x9b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x1c, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8,
+ 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x1c, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x01,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x41, 0xac, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x41, 0x94, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x41, 0xa0, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x04, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xe8,
+ 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04, 0xfe, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x1b, 0x68, 0x04, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8,
+ 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x42, 0x84, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x42, 0x5c, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x42, 0x70, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x42, 0x50, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x05, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05, 0xfe, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x1b, 0x68, 0x05, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x43, 0xa4, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x43, 0x7c, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x43, 0x90, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x43, 0x70, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x04, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x28, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04, 0xfe, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x1b, 0x28, 0x04, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x44, 0xc4, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x44, 0x9c, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x44, 0xb0, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x44, 0x90, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf8, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x06, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x06, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x06, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xf8,
+ 0xff, 0x9b, 0x68, 0x06, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x02, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x60, 0xff, 0xf8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x06, 0xfe, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x06, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x1b, 0x68, 0x06, 0xfe, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x06, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x06, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf8,
+ 0xff, 0x9b, 0x68, 0x06, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x45, 0xe4, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x45, 0xbc, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x45, 0xd0, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x45, 0xb0, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0xe0, 0xff, 0xf8,
+ 0xff, 0x1b, 0x68, 0x04, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04, 0xff, 0x9b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xf8, 0x7f, 0x60, 0xff, 0xe8,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xe8, 0x7f, 0x1c, 0xff, 0xf8,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x02, 0xfe, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x02,
+ 0xfe, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xf0,
+ 0x7f, 0xe0, 0xff, 0xe8, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x04,
+ 0xff, 0x1b, 0x68, 0x02, 0xfe, 0x1b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06,
+ 0x7f, 0xe0, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x04, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xe8,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04, 0xff, 0x9b, 0x68, 0x00, 0xfe, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04, 0xff, 0x9b, 0x68, 0x01, 0xfe, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x47, 0x1c, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0xe0, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x04, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x06, 0xe0, 0x00, 0x46, 0xe4, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x47, 0x00, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x46, 0xd0, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0xe0, 0xff, 0xf8,
+ 0xff, 0x1b, 0x68, 0x05, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05, 0xff, 0x9b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xf8, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x02, 0xfe, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x02,
+ 0xfe, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xf0,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x05,
+ 0xff, 0x1b, 0x68, 0x02, 0xfe, 0x1b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x05, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05, 0xff, 0x9b, 0x68, 0x00, 0xfe, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05, 0xff, 0x9b, 0x68, 0x01, 0xfe, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x48, 0x9c, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x68, 0x05, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x06, 0xe0, 0x00, 0x48, 0x64, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x48, 0x80, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x48, 0x50, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x04, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xff, 0x1b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0xe0, 0xff, 0xf8,
+ 0xff, 0x1b, 0x28, 0x04, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04,
+ 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04, 0xff, 0x9b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xf8, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x02, 0xfe, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x02,
+ 0xfe, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06, 0x7e, 0x1c, 0xff, 0xf0,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x04,
+ 0xff, 0x1b, 0x68, 0x02, 0xfe, 0x1b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfe, 0x9b, 0x68, 0x06,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x04, 0xf3, 0x9b, 0x68, 0x03,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04, 0xff, 0x9b, 0x68, 0x00, 0xfe, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0,
+ 0x7e, 0xe0, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04, 0xff, 0x9b, 0x68, 0x01, 0xfe, 0x9b, 0x68, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x4a, 0x1c, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0xe0, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf8, 0xff, 0x9b, 0x28, 0x04, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x06, 0xe0, 0x00, 0x49, 0xe4, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x4a, 0x00, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x49, 0xd0, 0x93, 0x9a, 0x00, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x9c, 0xff, 0xe8, 0xfc, 0x1b, 0x68, 0x07,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00, 0x7f, 0x9c, 0xff, 0xf0, 0xfc, 0x1b, 0x68, 0x07,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xfc, 0x1b, 0x68, 0x07,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00, 0x7f, 0x9c, 0xff, 0xf8, 0xfc, 0x1b, 0x68, 0x07,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x02, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfc, 0x1b, 0x68, 0x07, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8, 0xfc, 0x1b, 0x68, 0x07, 0xff, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfc, 0x1b, 0x68, 0x07, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00,
+ 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xe8,
+ 0xfc, 0x1b, 0x68, 0x07, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0x9c, 0xff, 0xf0, 0xfc, 0x1b, 0x68, 0x07, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x4b, 0x78, 0xf3, 0x9b, 0x68, 0x03, 0xfc, 0x1b, 0x68, 0x07,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x4b, 0x58, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x4b, 0x68, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x4b, 0x50, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8,
+ 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xe8,
+ 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04,
+ 0xff, 0x1b, 0x68, 0x00, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x01,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x4c, 0x80,
+ 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x4c, 0x50, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x4c, 0x68, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x4c, 0x40, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05,
+ 0xff, 0x1b, 0x68, 0x00, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x01,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x4d, 0xd0,
+ 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x4d, 0xa0, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x4d, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x4d, 0x90, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x28, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfc, 0x1b, 0x68, 0x07, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04,
+ 0xff, 0x1b, 0x68, 0x00, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xff, 0x1b, 0x68, 0x01,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x4f, 0x20,
+ 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x28, 0x04, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x68, 0x07, 0xe0, 0x00, 0x4e, 0xf0, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x4f, 0x08, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x4e, 0xe0, 0x93, 0x9a, 0x00, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x9c, 0xff, 0xe8, 0xfc, 0x1b, 0x28, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00, 0x7f, 0x9c, 0xff, 0xf0, 0xfc, 0x1b, 0x28, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xfc, 0x1b, 0x28, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00, 0x7f, 0x9c, 0xff, 0xf8, 0xfc, 0x1b, 0x28, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x02, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfc, 0x1b, 0x28, 0x06, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8, 0xfc, 0x1b, 0x28, 0x06, 0xff, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfc, 0x1b, 0x28, 0x06, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00,
+ 0xfc, 0x1b, 0x28, 0x06, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xe8,
+ 0xfc, 0x1b, 0x28, 0x06, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03,
+ 0x7f, 0x9c, 0xff, 0xf0, 0xfc, 0x1b, 0x28, 0x06, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x50, 0x58, 0xf3, 0x9b, 0x68, 0x03, 0xfc, 0x1b, 0x28, 0x06,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x50, 0x38, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x50, 0x48, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x50, 0x30, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8,
+ 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xe8,
+ 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x04,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04,
+ 0xff, 0x1b, 0x68, 0x00, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xff, 0x1b, 0x68, 0x01,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0xe0, 0x00, 0x51, 0x60,
+ 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xe8, 0xff, 0x9b, 0x68, 0x04, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0xe0, 0x00, 0x51, 0x30, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x51, 0x48, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x51, 0x20, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x28, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xe0, 0xff, 0xf0,
+ 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x60, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x1b, 0x68, 0x05,
+ 0xfe, 0x9b, 0x68, 0x02, 0xff, 0x9b, 0x28, 0x00, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xfc, 0x1b, 0x28, 0x06, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05,
+ 0xff, 0x1b, 0x68, 0x00, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xff, 0x1b, 0x68, 0x01,
+ 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0xe0, 0x00, 0x52, 0xb0,
+ 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0x9b, 0x68, 0x05, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xfc, 0x1b, 0x28, 0x06, 0xe0, 0x00, 0x52, 0x80, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x52, 0x98, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x52, 0x70, 0x93, 0x9a, 0x00, 0x00,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x9c, 0x1a, 0x00, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x00,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x9c, 0x1a, 0x00, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x9c, 0x1a, 0x00, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x28, 0x00,
+ 0x7f, 0x9c, 0xff, 0xf8, 0x9c, 0x1a, 0x00, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x9b, 0x68, 0x02,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0x9c, 0xff, 0xf8, 0x9c, 0x1a, 0x00, 0x04, 0xff, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x00, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0x9c, 0x1a, 0x00, 0x04, 0xff, 0x9b, 0x68, 0x02, 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x68, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8, 0x9c, 0x1a, 0x00, 0x04, 0xff, 0x9b, 0x68, 0x02,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xff, 0x1b, 0x28, 0x00, 0x9c, 0x1a, 0x00, 0x04, 0xe0, 0x00, 0x3a, 0xb8,
+ 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xe8, 0x9c, 0x1a, 0x00, 0x04, 0xff, 0x9b, 0x68, 0x00,
+ 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0x7f, 0x9c, 0xff, 0xf0, 0x9c, 0x1a, 0x00, 0x04,
+ 0xff, 0x9b, 0x68, 0x01, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x68, 0x03, 0xe0, 0x00, 0x53, 0xe0,
+ 0xf3, 0x9b, 0x68, 0x03, 0x9c, 0x1a, 0x00, 0x04, 0xe0, 0x00, 0x3a, 0xb8, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe0, 0x00, 0x53, 0xc0, 0xf3, 0x9b, 0x28, 0x02, 0xe0, 0x00, 0x53, 0xd0, 0xf3, 0x9b, 0x28, 0x02,
+ 0xe2, 0x00, 0x3a, 0x5c, 0xff, 0x3e, 0xfe, 0x00, 0xf3, 0x02, 0x0f, 0xff, 0xc3, 0x64, 0x34, 0x00,
+ 0x98, 0x96, 0xff, 0xdc, 0x9d, 0x16, 0xff, 0xc8, 0x9d, 0x96, 0xff, 0xc4, 0xf7, 0x82, 0x54, 0xc8,
+ 0xe0, 0x00, 0x7c, 0x68, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x96, 0xff, 0xc4, 0x8d, 0x16, 0xff, 0xc8,
+ 0xc3, 0x20, 0x00, 0x00, 0x83, 0xee, 0x00, 0x00, 0xc4, 0x68, 0x00, 0x00, 0xf7, 0x82, 0x54, 0xe8,
+ 0xe0, 0x00, 0x08, 0x84, 0x97, 0x93, 0xff, 0xfc, 0x88, 0x96, 0xff, 0xdc, 0xe0, 0x00, 0x73, 0x30,
+ 0xc4, 0x44, 0x00, 0x00, 0xff, 0x82, 0x38, 0x60, 0xfe, 0x82, 0x00, 0x0f, 0xae, 0x7e, 0xd0, 0x05,
+ 0xff, 0x02, 0x39, 0x60, 0xce, 0xe8, 0xec, 0x00, 0xac, 0x7a, 0xe8, 0x05, 0x7f, 0xc5, 0x00, 0x02,
+ 0xcf, 0xfc, 0xe2, 0x00, 0x2f, 0x14, 0x00, 0x18, 0x93, 0x96, 0xff, 0xf0, 0x9f, 0x96, 0xff, 0xe0,
+ 0x93, 0x96, 0xff, 0xe8, 0x93, 0x96, 0xff, 0xec, 0x70, 0x7a, 0x00, 0x1d, 0xea, 0x00, 0x55, 0x39,
+ 0x2b, 0x94, 0x00, 0x14, 0xcb, 0xf8, 0x00, 0x00, 0x70, 0x66, 0x00, 0x0c, 0xea, 0x00, 0x55, 0x51,
+ 0xff, 0xbe, 0xf0, 0x00, 0x20, 0x46, 0x00, 0x02, 0xe2, 0x00, 0x72, 0xfd, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xcf, 0xe4, 0xfc, 0x00, 0x20, 0x7f, 0x00, 0x08, 0xe6, 0x00, 0x72, 0xa9, 0x20, 0x46, 0x00, 0x01,
+ 0xff, 0x3e, 0xfe, 0x00, 0xcf, 0xe4, 0xf4, 0x00, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x58, 0x4d,
+ 0x20, 0x46, 0x00, 0x01, 0xff, 0xbe, 0xff, 0xfc, 0xcf, 0xe4, 0xfc, 0x00, 0xff, 0x3e, 0xfd, 0xf8,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x58, 0x35, 0x20, 0x46, 0x00, 0x01, 0xff, 0xbe, 0xff, 0xfc,
+ 0xcf, 0xe4, 0xfc, 0x00, 0xff, 0x3e, 0xfd, 0xf0, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x57, 0x6d,
+ 0x20, 0x46, 0x00, 0x01, 0xff, 0xbe, 0x80, 0x00, 0xce, 0xe4, 0xfc, 0x00, 0x20, 0x77, 0x00, 0x0f,
+ 0xe6, 0x00, 0x57, 0x51, 0xff, 0xbe, 0xff, 0x00, 0xce, 0x64, 0xfc, 0x00, 0xff, 0x3e, 0x90, 0x00,
+ 0xc0, 0x72, 0xf2, 0x00, 0xe6, 0x00, 0x57, 0x35, 0xff, 0xa2, 0x80, 0x00, 0xc0, 0x76, 0xfa, 0x00,
+ 0xe6, 0x00, 0x56, 0xf1, 0x20, 0x46, 0x00, 0x02, 0xff, 0xbe, 0x00, 0x00, 0xcf, 0xe4, 0xfc, 0x00,
+ 0x20, 0x7f, 0x00, 0x09, 0xe6, 0x00, 0x56, 0xb1, 0x20, 0x46, 0x00, 0x02, 0x90, 0xde, 0x00, 0x04,
+ 0x90, 0xde, 0x00, 0x00, 0x22, 0x10, 0x00, 0x0c, 0xfe, 0x02, 0x39, 0xc7, 0x9c, 0x92, 0x00, 0x04,
+ 0x98, 0x92, 0x00, 0x08, 0x9e, 0x12, 0x00, 0x00, 0x9b, 0x96, 0xff, 0xd4, 0x9c, 0x16, 0xff, 0xd0,
+ 0x9c, 0x96, 0xff, 0xcc, 0xf7, 0x82, 0x56, 0x20, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8c, 0x16, 0xff, 0xd0, 0x8c, 0x96, 0xff, 0xcc, 0x8b, 0x96, 0xff, 0xd4, 0x02, 0x10, 0x00, 0x0c,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xca, 0xdc, 0xc0, 0x00, 0x8f, 0x16, 0xff, 0xe4, 0xff, 0x88, 0x9f, 0xfc,
+ 0xfe, 0x02, 0x30, 0x00, 0x8e, 0xfa, 0x00, 0x04, 0x7f, 0xfd, 0x00, 0x0f, 0x84, 0x96, 0xff, 0xe0,
+ 0x0f, 0x01, 0x00, 0x70, 0xcf, 0x74, 0xf4, 0x00, 0xcf, 0x78, 0xfd, 0x00, 0x8f, 0x96, 0xff, 0xe4,
+ 0xce, 0x74, 0xe4, 0x00, 0x7e, 0xf5, 0x00, 0x16, 0x83, 0xfe, 0x00, 0x08, 0xcf, 0x78, 0xe5, 0x00,
+ 0x7e, 0xf4, 0xff, 0xea, 0xcf, 0x78, 0xed, 0x00, 0x22, 0x10, 0x00, 0x0c, 0x5f, 0x79, 0x4a, 0x00,
+ 0xfe, 0x02, 0x00, 0x01, 0xc4, 0x54, 0x00, 0x00, 0x73, 0x9c, 0xff, 0xf8, 0x9f, 0x12, 0x00, 0x00,
+ 0x9e, 0x12, 0x00, 0x04, 0x90, 0x12, 0x00, 0x08, 0xc3, 0x6c, 0x00, 0x00, 0xf7, 0x82, 0x56, 0xa8,
+ 0xe0, 0x00, 0xa3, 0x30, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x73, 0x30, 0xf4, 0x02, 0x00, 0x00,
+ 0xe2, 0x00, 0x55, 0xec, 0xff, 0x82, 0xff, 0xf8, 0xcf, 0xe4, 0xfc, 0x00, 0x0f, 0xfd, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x82, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x68, 0x9b, 0x82, 0xfe, 0x68,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x82, 0x00, 0x04, 0xcf, 0xe4, 0xfc, 0x00,
+ 0xcf, 0xdc, 0xf8, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xca, 0xfc, 0xc0, 0x00,
+ 0xe2, 0x00, 0x55, 0xdc, 0xff, 0xbe, 0x00, 0x00, 0xff, 0x82, 0x7f, 0xf8, 0xcf, 0xe4, 0xfc, 0x00,
+ 0x0f, 0xfd, 0x80, 0x01, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68,
+ 0x9b, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x82, 0x00, 0x04,
+ 0xcf, 0xe4, 0xfc, 0x00, 0xcf, 0xdc, 0xf8, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xca, 0xfc, 0xc0, 0x00, 0xff, 0x0a, 0x9f, 0xc0, 0xca, 0xe0, 0xf0, 0x00, 0x4f, 0xe5, 0x00, 0x0f,
+ 0xcf, 0xd4, 0xf8, 0x00, 0xca, 0xfc, 0xe2, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xff, 0x0a, 0x97, 0xc0, 0xca, 0xe0, 0xf0, 0x00, 0x4f, 0xe5, 0x00, 0x0f, 0xcf, 0xd4, 0xf8, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0x0a, 0xfd, 0xff, 0xf1, 0xe2, 0x00, 0x55, 0xa8,
+ 0xff, 0xbe, 0x80, 0x00, 0xff, 0x88, 0x8f, 0x98, 0xfd, 0x82, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x0c,
+ 0x7f, 0xfc, 0xff, 0xe1, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x00, 0x58, 0x29, 0x9f, 0xde, 0x00, 0x00,
+ 0xff, 0x88, 0x8f, 0x98, 0x70, 0x7e, 0x00, 0x0c, 0xea, 0x00, 0x58, 0x28, 0x4f, 0xfd, 0xff, 0xf7,
+ 0xfe, 0x88, 0xd3, 0xd8, 0xff, 0x89, 0x8f, 0x98, 0xff, 0x82, 0x34, 0x00, 0xf7, 0x82, 0x00, 0x40,
+ 0xf7, 0xf7, 0x68, 0x08, 0xff, 0xf7, 0x28, 0x0c, 0xff, 0x0a, 0x9f, 0xfe, 0xff, 0xfb, 0x18, 0x00,
+ 0xfe, 0x02, 0x00, 0x24, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xfe, 0x77, 0x28, 0x12,
+ 0x9d, 0xf6, 0x00, 0x14, 0x9d, 0xf6, 0x00, 0x18, 0x9d, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0x9d, 0xf6, 0x00, 0x30, 0xff, 0x77, 0x18, 0x0a, 0x8e, 0x76, 0x00, 0x2c, 0x0f, 0xf4, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0f, 0x81, 0x10, 0x00, 0x0f, 0xfc, 0x00, 0x14, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0xa2, 0xec, 0x9f, 0xf6, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28,
+ 0x9e, 0x02, 0xff, 0xb0, 0xfd, 0xf7, 0x28, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xca, 0xdc, 0xc0, 0x00, 0xe2, 0x00, 0x55, 0x90, 0xff, 0xbe, 0xff, 0xfc, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x95, 0x5e, 0x00, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xca, 0xdc, 0xc0, 0x00, 0xe2, 0x00, 0x55, 0x78,
+ 0xff, 0xbe, 0xff, 0xfc, 0x2f, 0x80, 0x02, 0x00, 0xcf, 0x64, 0xfd, 0x00, 0xab, 0x66, 0xfd, 0x02,
+ 0x8a, 0x7a, 0x00, 0x04, 0x20, 0x6a, 0x00, 0xff, 0xca, 0xdc, 0xc0, 0x00, 0xe2, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xe9, 0x00, 0x02, 0xff, 0x02, 0x58, 0x88, 0xae, 0xfe, 0xf0, 0x02,
+ 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x5c, 0x98, 0x00, 0x00, 0x5c, 0xa0,
+ 0x00, 0x00, 0x5c, 0xb0, 0x00, 0x00, 0x5c, 0xc0, 0x00, 0x00, 0x5c, 0xd0, 0x00, 0x00, 0x5c, 0xe0,
+ 0x00, 0x00, 0x5c, 0xf8, 0x00, 0x00, 0x5d, 0x10, 0x00, 0x00, 0x5d, 0x28, 0x00, 0x00, 0x5d, 0x34,
+ 0x00, 0x00, 0x5d, 0x48, 0x00, 0x00, 0x5d, 0x5c, 0x00, 0x00, 0x5d, 0x64, 0x00, 0x00, 0x5d, 0x70,
+ 0x00, 0x00, 0x5d, 0x78, 0x00, 0x00, 0x5d, 0x80, 0x00, 0x00, 0x5d, 0x8c, 0x00, 0x00, 0x5d, 0x9c,
+ 0x00, 0x00, 0x5d, 0xb4, 0x00, 0x00, 0x5d, 0xcc, 0x00, 0x00, 0x5d, 0xe4, 0x00, 0x00, 0x5d, 0xfc,
+ 0x00, 0x00, 0x5e, 0x1c, 0x00, 0x00, 0x5e, 0x3c, 0x00, 0x00, 0x5e, 0x5c, 0x00, 0x00, 0x5e, 0x70,
+ 0x00, 0x00, 0x5e, 0x8c, 0x00, 0x00, 0x5e, 0xa8, 0x00, 0x00, 0x5e, 0xb0, 0x00, 0x00, 0x5e, 0xc4,
+ 0x00, 0x00, 0x5e, 0xcc, 0x00, 0x00, 0x5e, 0xd4, 0x00, 0x00, 0x5e, 0xdc, 0x00, 0x00, 0x5e, 0xec,
+ 0x00, 0x00, 0x5f, 0x04, 0x00, 0x00, 0x5f, 0x1c, 0x00, 0x00, 0x5f, 0x34, 0x00, 0x00, 0x5f, 0x4c,
+ 0x00, 0x00, 0x5f, 0x6c, 0x00, 0x00, 0x5f, 0x8c, 0x00, 0x00, 0x5f, 0xac, 0x00, 0x00, 0x5f, 0xc0,
+ 0x00, 0x00, 0x5f, 0xdc, 0x00, 0x00, 0x5f, 0xf8, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x14,
+ 0x00, 0x00, 0x60, 0x1c, 0x00, 0x00, 0x60, 0x24, 0x00, 0x00, 0x60, 0x2c, 0x00, 0x00, 0x60, 0x3c,
+ 0x00, 0x00, 0x60, 0x54, 0x00, 0x00, 0x60, 0x6c, 0x00, 0x00, 0x60, 0x84, 0x00, 0x00, 0x60, 0x9c,
+ 0x00, 0x00, 0x60, 0xbc, 0x00, 0x00, 0x60, 0xdc, 0x00, 0x00, 0x60, 0xfc, 0x00, 0x00, 0x61, 0x10,
+ 0x00, 0x00, 0x61, 0x2c, 0x00, 0x00, 0x61, 0x48, 0x00, 0x00, 0x61, 0x50, 0x00, 0x00, 0x61, 0x64,
+ 0x00, 0x00, 0x61, 0x6c, 0x00, 0x00, 0x61, 0x74, 0x00, 0x00, 0x61, 0x7c, 0x00, 0x00, 0x61, 0x8c,
+ 0x00, 0x00, 0x61, 0xa4, 0x00, 0x00, 0x61, 0xbc, 0x00, 0x00, 0x61, 0xd4, 0x00, 0x00, 0x61, 0xec,
+ 0x00, 0x00, 0x62, 0x0c, 0x00, 0x00, 0x62, 0x2c, 0x00, 0x00, 0x62, 0x4c, 0x00, 0x00, 0x62, 0x60,
+ 0x00, 0x00, 0x62, 0x7c, 0x00, 0x00, 0x62, 0x98, 0x00, 0x00, 0x62, 0xa0, 0x00, 0x00, 0x62, 0xb4,
+ 0x00, 0x00, 0x62, 0xbc, 0x00, 0x00, 0x62, 0xc4, 0x00, 0x00, 0x62, 0xcc, 0x00, 0x00, 0x62, 0xe4,
+ 0x00, 0x00, 0x63, 0x04, 0x00, 0x00, 0x63, 0x24, 0x00, 0x00, 0x63, 0x44, 0x00, 0x00, 0x63, 0x64,
+ 0x00, 0x00, 0x63, 0x8c, 0x00, 0x00, 0x63, 0xb4, 0x00, 0x00, 0x63, 0xdc, 0x00, 0x00, 0x63, 0xf8,
+ 0x00, 0x00, 0x64, 0x1c, 0x00, 0x00, 0x64, 0x40, 0x00, 0x00, 0x64, 0x48, 0x00, 0x00, 0x64, 0x64,
+ 0x00, 0x00, 0x64, 0x6c, 0x00, 0x00, 0x64, 0x74, 0x00, 0x00, 0x64, 0x7c, 0x00, 0x00, 0x64, 0x94,
+ 0x00, 0x00, 0x64, 0xb4, 0x00, 0x00, 0x64, 0xd4, 0x00, 0x00, 0x64, 0xf4, 0x00, 0x00, 0x65, 0x14,
+ 0x00, 0x00, 0x65, 0x3c, 0x00, 0x00, 0x65, 0x64, 0x00, 0x00, 0x65, 0x8c, 0x00, 0x00, 0x65, 0xa8,
+ 0x00, 0x00, 0x65, 0xcc, 0x00, 0x00, 0x65, 0xf0, 0x00, 0x00, 0x65, 0xf8, 0x00, 0x00, 0x66, 0x14,
+ 0x00, 0x00, 0x66, 0x1c, 0x00, 0x00, 0x66, 0x24, 0x00, 0x00, 0x66, 0x2c, 0x00, 0x00, 0x66, 0x44,
+ 0x00, 0x00, 0x66, 0x64, 0x00, 0x00, 0x66, 0x84, 0x00, 0x00, 0x66, 0xa4, 0x00, 0x00, 0x66, 0xc4,
+ 0x00, 0x00, 0x66, 0xec, 0x00, 0x00, 0x67, 0x14, 0x00, 0x00, 0x67, 0x3c, 0x00, 0x00, 0x67, 0x58,
+ 0x00, 0x00, 0x67, 0x7c, 0x00, 0x00, 0x67, 0xa0, 0x00, 0x00, 0x67, 0xa8, 0x00, 0x00, 0x67, 0xc4,
+ 0x00, 0x00, 0x67, 0xcc, 0x00, 0x00, 0x67, 0xd4, 0x00, 0x00, 0x67, 0xdc, 0x00, 0x00, 0x67, 0xe8,
+ 0x00, 0x00, 0x67, 0xfc, 0x00, 0x00, 0x68, 0x10, 0x00, 0x00, 0x68, 0x24, 0x00, 0x00, 0x68, 0x38,
+ 0x00, 0x00, 0x68, 0x54, 0x00, 0x00, 0x68, 0x70, 0x00, 0x00, 0x68, 0x8c, 0x00, 0x00, 0x68, 0x9c,
+ 0x00, 0x00, 0x68, 0xb4, 0x00, 0x00, 0x68, 0xcc, 0x00, 0x00, 0x68, 0xd4, 0x00, 0x00, 0x68, 0xe4,
+ 0x00, 0x00, 0x68, 0xec, 0x00, 0x00, 0x68, 0xf4, 0x00, 0x00, 0x68, 0xfc, 0x00, 0x00, 0x69, 0x10,
+ 0x00, 0x00, 0x69, 0x2c, 0x00, 0x00, 0x69, 0x48, 0x00, 0x00, 0x69, 0x64, 0x00, 0x00, 0x69, 0x80,
+ 0x00, 0x00, 0x69, 0xa4, 0x00, 0x00, 0x69, 0xc8, 0x00, 0x00, 0x69, 0xec, 0x00, 0x00, 0x6a, 0x04,
+ 0x00, 0x00, 0x6a, 0x24, 0x00, 0x00, 0x6a, 0x44, 0x00, 0x00, 0x6a, 0x4c, 0x00, 0x00, 0x6a, 0x64,
+ 0x00, 0x00, 0x6a, 0x6c, 0x00, 0x00, 0x6a, 0x74, 0x00, 0x00, 0x6a, 0x7c, 0x00, 0x00, 0x6a, 0x90,
+ 0x00, 0x00, 0x6a, 0xac, 0x00, 0x00, 0x6a, 0xc8, 0x00, 0x00, 0x6a, 0xe4, 0x00, 0x00, 0x6b, 0x00,
+ 0x00, 0x00, 0x6b, 0x24, 0x00, 0x00, 0x6b, 0x48, 0x00, 0x00, 0x6b, 0x6c, 0x00, 0x00, 0x6b, 0x84,
+ 0x00, 0x00, 0x6b, 0xa4, 0x00, 0x00, 0x6b, 0xc4, 0x00, 0x00, 0x6b, 0xcc, 0x00, 0x00, 0x6b, 0xe4,
+ 0x00, 0x00, 0x6b, 0xec, 0x00, 0x00, 0x6b, 0xf4, 0x00, 0x00, 0x6b, 0xfc, 0x00, 0x00, 0x6c, 0x10,
+ 0x00, 0x00, 0x6c, 0x2c, 0x00, 0x00, 0x6c, 0x48, 0x00, 0x00, 0x6c, 0x64, 0x00, 0x00, 0x6c, 0x80,
+ 0x00, 0x00, 0x6c, 0xa4, 0x00, 0x00, 0x6c, 0xc8, 0x00, 0x00, 0x6c, 0xec, 0x00, 0x00, 0x6d, 0x04,
+ 0x00, 0x00, 0x6d, 0x24, 0x00, 0x00, 0x6d, 0x44, 0x00, 0x00, 0x6d, 0x4c, 0x00, 0x00, 0x6d, 0x64,
+ 0x00, 0x00, 0x6d, 0x6c, 0x00, 0x00, 0x6d, 0x74, 0x00, 0x00, 0x6d, 0x7c, 0x00, 0x00, 0x6d, 0x88,
+ 0x00, 0x00, 0x6d, 0x9c, 0x00, 0x00, 0x6d, 0xb0, 0x00, 0x00, 0x6d, 0xc4, 0x00, 0x00, 0x6d, 0xd8,
+ 0x00, 0x00, 0x6d, 0xf4, 0x00, 0x00, 0x6e, 0x10, 0x00, 0x00, 0x6e, 0x2c, 0x00, 0x00, 0x6e, 0x3c,
+ 0x00, 0x00, 0x6e, 0x54, 0x00, 0x00, 0x6e, 0x6c, 0x00, 0x00, 0x6e, 0x74, 0x00, 0x00, 0x6e, 0x84,
+ 0x00, 0x00, 0x6e, 0x8c, 0x00, 0x00, 0x6e, 0x94, 0x00, 0x00, 0x6e, 0x9c, 0x00, 0x00, 0x6e, 0xb0,
+ 0x00, 0x00, 0x6e, 0xcc, 0x00, 0x00, 0x6e, 0xe8, 0x00, 0x00, 0x6f, 0x04, 0x00, 0x00, 0x6f, 0x20,
+ 0x00, 0x00, 0x6f, 0x44, 0x00, 0x00, 0x6f, 0x68, 0x00, 0x00, 0x6f, 0x8c, 0x00, 0x00, 0x6f, 0xa4,
+ 0x00, 0x00, 0x6f, 0xc4, 0x00, 0x00, 0x6f, 0xe4, 0x00, 0x00, 0x6f, 0xec, 0x00, 0x00, 0x70, 0x04,
+ 0x00, 0x00, 0x70, 0x0c, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x00, 0x70, 0x30,
+ 0x00, 0x00, 0x70, 0x4c, 0x00, 0x00, 0x70, 0x68, 0x00, 0x00, 0x70, 0x84, 0x00, 0x00, 0x70, 0xa0,
+ 0x00, 0x00, 0x70, 0xc4, 0x00, 0x00, 0x70, 0xe8, 0x00, 0x00, 0x71, 0x0c, 0x00, 0x00, 0x71, 0x24,
+ 0x00, 0x00, 0x71, 0x44, 0x00, 0x00, 0x71, 0x64, 0x00, 0x00, 0x71, 0x6c, 0x00, 0x00, 0x71, 0x84,
+ 0x00, 0x00, 0x71, 0x8c, 0x00, 0x00, 0x71, 0x94, 0x00, 0x00, 0x5c, 0x8c, 0x00, 0x00, 0x71, 0x9c,
+ 0x00, 0x00, 0x71, 0xb0, 0x00, 0x00, 0x71, 0xc4, 0x00, 0x00, 0x71, 0xd8, 0x00, 0x00, 0x71, 0xec,
+ 0x00, 0x00, 0x72, 0x08, 0x00, 0x00, 0x72, 0x24, 0x00, 0x00, 0x72, 0x40, 0x00, 0x00, 0x72, 0x50,
+ 0x00, 0x00, 0x72, 0x68, 0x00, 0x00, 0x72, 0x80, 0x00, 0x00, 0x72, 0x88, 0x00, 0x00, 0x72, 0x98,
+ 0x00, 0x00, 0x72, 0xa0, 0x00, 0x00, 0x5c, 0x88, 0x9b, 0x5e, 0x00, 0x00, 0x9a, 0x5e, 0x00, 0x04,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x58, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x00, 0xff, 0x5f, 0x68, 0x02,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8,
+ 0xff, 0xdf, 0x68, 0x01, 0xff, 0x5f, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8, 0xff, 0xdf, 0x28, 0x00, 0xff, 0x5f, 0x68, 0x02,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x01,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x5c, 0xc0,
+ 0xfb, 0x5f, 0x68, 0x03, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x5c, 0xa0, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x5c, 0xb0, 0xfb, 0x5f, 0x28, 0x02,
+ 0x9b, 0x5e, 0x00, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8,
+ 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x5d, 0xcc, 0xfb, 0x5f, 0x68, 0x03,
+ 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x5d, 0x9c, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x5d, 0xb4,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x5d, 0x8c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x5f, 0x1c, 0xfb, 0x5f, 0x68, 0x03,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x5e, 0xec, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x5f, 0x04,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x5e, 0xdc, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x28, 0x04, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04,
+ 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x28, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x60, 0x6c, 0xfb, 0x5f, 0x68, 0x03,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x60, 0x3c, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x60, 0x54,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x60, 0x2c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf8,
+ 0xff, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8,
+ 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06, 0xff, 0x5f, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06,
+ 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06, 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06,
+ 0xff, 0x5f, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0x7f, 0x50, 0xff, 0xf8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x06, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x06, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x06, 0xfe, 0xdf, 0x68, 0x02,
+ 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xf8,
+ 0xff, 0xdf, 0x68, 0x06, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x61, 0xbc, 0xfb, 0x5f, 0x68, 0x03,
+ 0x7f, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x06, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x61, 0x8c, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x61, 0xa4,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x61, 0x7c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xe8,
+ 0x7f, 0x50, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x04, 0xff, 0xdf, 0x68, 0x00, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x04, 0xff, 0xdf, 0x68, 0x01, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x04, 0xff, 0xdf, 0x28, 0x00, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf8, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x04, 0xff, 0xdf, 0x68, 0x02, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xe8, 0x7f, 0x58, 0xff, 0xf8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x68, 0x00,
+ 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xe8, 0x7f, 0x58, 0xff, 0xf8, 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x68, 0x01, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xe8, 0x7f, 0x58, 0xff, 0xf8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x28, 0x00,
+ 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xe8,
+ 0x7f, 0x50, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xff, 0x5f, 0x68, 0x06,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xe8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xff, 0xdf, 0x68, 0x00, 0xfe, 0xdf, 0x68, 0x06,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xff, 0xdf, 0x68, 0x01,
+ 0xfe, 0xdf, 0x68, 0x06, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03,
+ 0xe0, 0x00, 0x63, 0x24, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf8,
+ 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xff, 0x5f, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x62, 0xe4, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x63, 0x04,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x62, 0xcc, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x05, 0xff, 0xdf, 0x68, 0x00, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x05, 0xff, 0xdf, 0x68, 0x01, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x05, 0xff, 0xdf, 0x28, 0x00, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x05, 0xff, 0xdf, 0x68, 0x02, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x68, 0x00,
+ 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8, 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x68, 0x01, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x28, 0x00,
+ 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf8, 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x68, 0x03, 0xff, 0x5f, 0x68, 0x06,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xff, 0xdf, 0x68, 0x00, 0xfe, 0xdf, 0x68, 0x06,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xff, 0xdf, 0x68, 0x01,
+ 0xfe, 0xdf, 0x68, 0x06, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03,
+ 0xe0, 0x00, 0x64, 0xd4, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf8,
+ 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x28, 0x02, 0xff, 0x5f, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x64, 0x94, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x64, 0xb4,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x64, 0x7c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf8, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x28, 0x04, 0xff, 0xdf, 0x68, 0x00, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x28, 0x04, 0xff, 0xdf, 0x68, 0x01, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x28, 0x04, 0xff, 0xdf, 0x28, 0x00, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8,
+ 0xff, 0x5f, 0x28, 0x04, 0xff, 0xdf, 0x68, 0x02, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x68, 0x00,
+ 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8, 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x28, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x68, 0x01, 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7e, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x58, 0xff, 0xf8,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x02, 0xfe, 0x5f, 0x28, 0x00,
+ 0xfe, 0xdf, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf8, 0xff, 0xdf, 0x28, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xff, 0x5f, 0x68, 0x06,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0,
+ 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04, 0xff, 0xdf, 0x68, 0x00, 0xfe, 0xdf, 0x68, 0x06,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0,
+ 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd0, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04, 0xff, 0xdf, 0x68, 0x01,
+ 0xfe, 0xdf, 0x68, 0x06, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03,
+ 0xe0, 0x00, 0x66, 0x84, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf8,
+ 0xff, 0xdf, 0x28, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xff, 0x5f, 0x68, 0x06, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x66, 0x44, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x66, 0x64,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x66, 0x2c, 0x9b, 0x5e, 0x00, 0x00, 0xfa, 0x5f, 0x68, 0x07,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0xfa, 0x5f, 0x68, 0x07,
+ 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf0, 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf8, 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x68, 0x02,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd8, 0xff, 0xf8,
+ 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd8, 0xff, 0xf8, 0xfa, 0x5f, 0x68, 0x07,
+ 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd8, 0xff, 0xf8, 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x68, 0x02,
+ 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0xfa, 0x5f, 0x68, 0x07,
+ 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0, 0xfa, 0x5f, 0x68, 0x07, 0xff, 0xdf, 0x68, 0x01,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x68, 0x10,
+ 0xfb, 0x5f, 0x68, 0x03, 0xfa, 0x5f, 0x68, 0x07, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x67, 0xe8, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x67, 0xfc,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x67, 0xdc, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x28, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04,
+ 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xe8,
+ 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x28, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0xe0, 0x00, 0x69, 0x48, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0xe0, 0x00, 0x69, 0x10, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x69, 0x2c,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x68, 0xfc, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x28, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05,
+ 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0,
+ 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x28, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x68, 0x03, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0xe0, 0x00, 0x6a, 0xc8, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x28, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0xe0, 0x00, 0x6a, 0x90, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6a, 0xac,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6a, 0x7c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x28, 0x04, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x28, 0x04, 0xff, 0x5f, 0x28, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04,
+ 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8,
+ 0xff, 0x5f, 0x28, 0x04, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0,
+ 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x28, 0x04, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x28, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x28, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04,
+ 0xff, 0x5f, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x28, 0x04,
+ 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0xe0, 0x00, 0x6c, 0x48, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x28, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x68, 0x07, 0xe0, 0x00, 0x6c, 0x10, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6c, 0x2c,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6b, 0xfc, 0x9b, 0x5e, 0x00, 0x00, 0xfa, 0x5f, 0x28, 0x06,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8, 0xfa, 0x5f, 0x28, 0x06,
+ 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0,
+ 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf0, 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf8, 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x68, 0x02,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd8, 0xff, 0xf8,
+ 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd8, 0xff, 0xf8, 0xfa, 0x5f, 0x28, 0x06,
+ 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd8, 0xff, 0xf8, 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x68, 0x02,
+ 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0xfa, 0x5f, 0x28, 0x06,
+ 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0, 0xfa, 0x5f, 0x28, 0x06, 0xff, 0xdf, 0x68, 0x01,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x6d, 0xb0,
+ 0xfb, 0x5f, 0x68, 0x03, 0xfa, 0x5f, 0x28, 0x06, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x6d, 0x88, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6d, 0x9c,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6d, 0x7c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xff, 0x5f, 0x28, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04,
+ 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xe8, 0x7e, 0xd8, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xe8,
+ 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x04, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x28, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xe8, 0xff, 0xdf, 0x68, 0x04,
+ 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0xe0, 0x00, 0x6e, 0xe8, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xe8,
+ 0xff, 0xdf, 0x68, 0x04, 0xfb, 0x5f, 0x28, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0xe0, 0x00, 0x6e, 0xb0, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6e, 0xcc,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x6e, 0x9c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06,
+ 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf0,
+ 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xff, 0x5f, 0x28, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05,
+ 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xd8, 0xff, 0xf8,
+ 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0xd8, 0xff, 0xf0, 0x7f, 0x50, 0xff, 0xf0,
+ 0x7e, 0xd8, 0xff, 0xf8, 0xff, 0x5f, 0x68, 0x05, 0xfe, 0xdf, 0x68, 0x02, 0xff, 0xdf, 0x28, 0x00,
+ 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x68, 0x03, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xe8, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd0, 0xff, 0xf0, 0xff, 0xdf, 0x68, 0x05,
+ 0xff, 0x5f, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0xe0, 0x00, 0x70, 0x68, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd0, 0xff, 0xf0,
+ 0xff, 0xdf, 0x68, 0x05, 0xfb, 0x5f, 0x28, 0x02, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38,
+ 0xfa, 0x5f, 0x28, 0x06, 0xe0, 0x00, 0x70, 0x30, 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x70, 0x4c,
+ 0xfb, 0x5f, 0x28, 0x02, 0xe0, 0x00, 0x70, 0x1c, 0x9b, 0x5e, 0x00, 0x00, 0x7f, 0xd8, 0xff, 0xe8,
+ 0x9a, 0x5e, 0x00, 0x04, 0xff, 0xdf, 0x68, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xf0, 0x9a, 0x5e, 0x00, 0x04, 0xff, 0xdf, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf0, 0x9a, 0x5e, 0x00, 0x04, 0xff, 0xdf, 0x28, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0xd8, 0xff, 0xf8, 0x9a, 0x5e, 0x00, 0x04,
+ 0xff, 0xdf, 0x68, 0x02, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xe8,
+ 0x7f, 0xd8, 0xff, 0xf8, 0x9a, 0x5e, 0x00, 0x04, 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x68, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd8, 0xff, 0xf8,
+ 0x9a, 0x5e, 0x00, 0x04, 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x68, 0x01, 0xe0, 0x00, 0x56, 0x38,
+ 0xcd, 0xe4, 0xc0, 0x00, 0x7f, 0x58, 0xff, 0xf0, 0x7f, 0xd8, 0xff, 0xf8, 0x9a, 0x5e, 0x00, 0x04,
+ 0xff, 0xdf, 0x68, 0x02, 0xff, 0x5f, 0x28, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x9a, 0x5e, 0x00, 0x04, 0xfb, 0x5f, 0x68, 0x03, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00,
+ 0x7f, 0xd8, 0xff, 0xe8, 0x9a, 0x5e, 0x00, 0x04, 0xff, 0xdf, 0x68, 0x00, 0xcd, 0xe4, 0xc0, 0x00,
+ 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03, 0x7f, 0xd8, 0xff, 0xf0, 0x9a, 0x5e, 0x00, 0x04,
+ 0xff, 0xdf, 0x68, 0x01, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xfb, 0x5f, 0x68, 0x03,
+ 0xe0, 0x00, 0x71, 0xc4, 0xfb, 0x5f, 0x68, 0x03, 0x9a, 0x5e, 0x00, 0x04, 0xfb, 0x5f, 0x28, 0x02,
+ 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0xe0, 0x00, 0x71, 0x9c, 0xfb, 0x5f, 0x28, 0x02,
+ 0xe0, 0x00, 0x71, 0xb0, 0xfb, 0x5f, 0x28, 0x02, 0xe2, 0x00, 0x55, 0x64, 0xff, 0x3e, 0xfe, 0x00,
+ 0xf3, 0x02, 0x0f, 0xff, 0xc3, 0x64, 0x34, 0x00, 0x9b, 0x96, 0xff, 0xd4, 0x9c, 0x16, 0xff, 0xd0,
+ 0x9c, 0x96, 0xff, 0xcc, 0xf7, 0x82, 0x72, 0xd0, 0xe0, 0x00, 0x7c, 0x68, 0x97, 0x93, 0xff, 0xfc,
+ 0xc3, 0x20, 0x00, 0x00, 0xf7, 0x82, 0x72, 0xe0, 0xe0, 0x00, 0x08, 0x28, 0x97, 0x93, 0xff, 0xfc,
+ 0x8b, 0x96, 0xff, 0xd4, 0x94, 0x5e, 0x00, 0x00, 0x8c, 0x16, 0xff, 0xd0, 0x8c, 0x96, 0xff, 0xcc,
+ 0xca, 0xdc, 0xc0, 0x00, 0xe0, 0x00, 0x56, 0x38, 0xcd, 0xe4, 0xc0, 0x00, 0x84, 0x16, 0xff, 0xe0,
+ 0xca, 0xdc, 0xc0, 0x00, 0x43, 0xed, 0x00, 0x07, 0xc3, 0x54, 0x00, 0x00, 0x9a, 0x96, 0xff, 0xd8,
+ 0x9d, 0x96, 0xff, 0xc4, 0xf7, 0x82, 0x73, 0x20, 0xe0, 0x00, 0x1c, 0xa0, 0x97, 0x93, 0xff, 0xfc,
+ 0x8a, 0x96, 0xff, 0xd8, 0x8d, 0x96, 0xff, 0xc4, 0xe0, 0x00, 0x56, 0x38, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x82, 0x00, 0x1f, 0xfd, 0x02, 0x00, 0x01,
+ 0xcf, 0x80, 0xda, 0x00, 0xcf, 0x98, 0xff, 0x80, 0xce, 0xfc, 0xd4, 0x00, 0x5e, 0x74, 0x00, 0x02,
+ 0xfe, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8, 0x2f, 0x7c, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xc8,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x73, 0x6d, 0x5f, 0xf4, 0x00, 0x06, 0xff, 0x83, 0x6b, 0xe1,
+ 0x8f, 0x02, 0xff, 0xc8, 0x0f, 0x78, 0x00, 0x09, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xea, 0x00, 0x73, 0x89, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8,
+ 0x0f, 0x7c, 0x00, 0x02, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x73, 0xa5,
+ 0x00, 0x00, 0x00, 0x01, 0x2d, 0xee, 0x00, 0x01, 0xea, 0x00, 0x73, 0x50, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0x82, 0x00, 0x1f, 0xfd, 0x02, 0x00, 0x01, 0xcf, 0x80, 0xda, 0x00,
+ 0xcf, 0x98, 0xff, 0x80, 0xce, 0xfc, 0xd4, 0x00, 0x5e, 0x74, 0x00, 0x02, 0xfe, 0x03, 0x6b, 0xe1,
+ 0x8f, 0x82, 0xff, 0xc8, 0x2f, 0x7c, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xea, 0x00, 0x73, 0xf9, 0x5f, 0xf4, 0x00, 0x06, 0xff, 0x83, 0x6b, 0xe1, 0x8f, 0x02, 0xff, 0xc8,
+ 0x0f, 0x78, 0x00, 0x09, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0x15,
+ 0x00, 0x00, 0x00, 0x01, 0xfe, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8, 0x0f, 0x7c, 0x00, 0x02,
+ 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0x31, 0x00, 0x00, 0x00, 0x01,
+ 0x2d, 0xec, 0x00, 0x01, 0x20, 0x6e, 0x00, 0x11, 0xee, 0x00, 0x73, 0xdc, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8, 0x2f, 0x7c, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xc8,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0x5d, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x00, 0x04,
+ 0xf7, 0x83, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8, 0x0f, 0x7c, 0x00, 0x09, 0x8f, 0x82, 0xff, 0xc8,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0x7d, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x6b, 0xe1,
+ 0x8f, 0x82, 0xff, 0xc8, 0x0f, 0x7c, 0x00, 0x02, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xea, 0x00, 0x74, 0x99, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8,
+ 0x2f, 0x7c, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0xb5,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x00, 0x04, 0xf7, 0x83, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8,
+ 0x0f, 0x7c, 0x00, 0x09, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0xd5,
+ 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8, 0x0f, 0x7c, 0x00, 0x02,
+ 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xf2, 0x00, 0xea, 0x00, 0x74, 0xf1, 0xf4, 0x02, 0x00, 0x00,
+ 0xfd, 0x82, 0x00, 0x0f, 0xfe, 0x02, 0x00, 0x01, 0xf0, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8,
+ 0x2e, 0xfc, 0x00, 0x05, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xea, 0x00, 0xea, 0x00, 0x75, 0x15,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x83, 0x5b, 0xe1, 0x7f, 0x21, 0x00, 0x01, 0x7f, 0xfd, 0x00, 0x18,
+ 0x7f, 0xfc, 0xff, 0xe8, 0x8e, 0x82, 0xff, 0xc8, 0xcf, 0xfc, 0xe4, 0x00, 0xcf, 0x78, 0xfd, 0x00,
+ 0x44, 0x79, 0x00, 0x00, 0x2e, 0xf4, 0x00, 0x05, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xea, 0x00,
+ 0xea, 0x00, 0x75, 0x49, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x00, 0x04, 0xf7, 0x83, 0x6b, 0xe1,
+ 0x8f, 0x82, 0xff, 0xc8, 0x0e, 0xfc, 0x00, 0x09, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xea, 0x00,
+ 0xea, 0x00, 0x75, 0x69, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x6b, 0xe1, 0x8f, 0x82, 0xff, 0xc8,
+ 0x0e, 0xfc, 0x00, 0x02, 0x8f, 0x82, 0xff, 0xc8, 0xc0, 0x7e, 0xea, 0x00, 0xea, 0x00, 0x75, 0x85,
+ 0x00, 0x00, 0x00, 0x01, 0x2d, 0xee, 0x00, 0x01, 0xea, 0x00, 0x75, 0x08, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0xcf, 0x98, 0x00, 0x00, 0x44, 0x21, 0x00, 0x00,
+ 0xc3, 0x04, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xec, 0x94, 0x16, 0xff, 0xf4, 0x93, 0x96, 0xff, 0xf0,
+ 0xf7, 0x82, 0x75, 0xdc, 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf0,
+ 0x8f, 0x96, 0xff, 0xec, 0xff, 0x02, 0x00, 0x1f, 0xce, 0xf4, 0xf4, 0x00, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x8f, 0x16, 0xff, 0xf4, 0x7f, 0xfd, 0x00, 0x17, 0x7e, 0xf5, 0x00, 0x12, 0xcf, 0xfc, 0xed, 0x00,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x5f, 0xfd, 0x50, 0x02, 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x76, 0x18,
+ 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0xcf, 0x98, 0x00, 0x00, 0xc3, 0x04, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xf0, 0x93, 0x96, 0xff, 0xf4,
+ 0xf7, 0x82, 0x76, 0x4c, 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4,
+ 0x8f, 0x96, 0xff, 0xf0, 0xfe, 0x82, 0x00, 0x1f, 0xcf, 0x78, 0xec, 0x00, 0xcf, 0xfc, 0xec, 0x00,
+ 0x7f, 0xfd, 0x00, 0x17, 0x7f, 0x79, 0x00, 0x12, 0xcf, 0xfc, 0xf5, 0x00, 0x5f, 0xfd, 0x60, 0x00,
+ 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x76, 0x80, 0xe0, 0x00, 0x73, 0xcc, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0xcf, 0x98, 0x00, 0x00, 0x44, 0x21, 0x00, 0x00,
+ 0xc3, 0x04, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xec, 0x94, 0x16, 0xff, 0xf4, 0x93, 0x96, 0xff, 0xf0,
+ 0xf7, 0x82, 0x76, 0xbc, 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf0,
+ 0x8f, 0x96, 0xff, 0xec, 0xff, 0x02, 0x00, 0x1f, 0xce, 0xf4, 0xf4, 0x00, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x8f, 0x16, 0xff, 0xf4, 0x7f, 0xfd, 0x00, 0x17, 0x7e, 0xf5, 0x00, 0x12, 0xcf, 0xfc, 0xed, 0x00,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x5f, 0xfd, 0x00, 0x02, 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x76, 0xf8,
+ 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c,
+ 0xcf, 0x98, 0x00, 0x00, 0x44, 0x21, 0x00, 0x00, 0xc3, 0x04, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xec,
+ 0x94, 0x16, 0xff, 0xf4, 0x93, 0x96, 0xff, 0xf0, 0xf7, 0x82, 0x77, 0x34, 0xe0, 0x00, 0x73, 0x40,
+ 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf0, 0x8f, 0x96, 0xff, 0xec, 0xff, 0x02, 0x00, 0x1f,
+ 0xce, 0xf4, 0xf4, 0x00, 0xcf, 0xfc, 0xf4, 0x00, 0x8f, 0x16, 0xff, 0xf4, 0x7f, 0xfd, 0x00, 0x17,
+ 0x7e, 0xf5, 0x00, 0x12, 0xcf, 0xfc, 0xed, 0x00, 0xcf, 0xfc, 0xf5, 0x00, 0x5f, 0xfd, 0x10, 0x02,
+ 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x77, 0x70, 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08, 0xcf, 0x98, 0x00, 0x00, 0xc3, 0x04, 0x00, 0x00,
+ 0x9f, 0x96, 0xff, 0xf0, 0x93, 0x96, 0xff, 0xf4, 0xf7, 0x82, 0x77, 0xa4, 0xe0, 0x00, 0x73, 0x40,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4, 0x8f, 0x96, 0xff, 0xf0, 0xfe, 0x82, 0x00, 0x1f,
+ 0xcf, 0x78, 0xec, 0x00, 0xcf, 0xfc, 0xec, 0x00, 0x7f, 0xfd, 0x00, 0x17, 0x7f, 0x79, 0x00, 0x12,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x5f, 0xfd, 0x30, 0x00, 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x77, 0xd8,
+ 0xe0, 0x00, 0x73, 0xcc, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0xcf, 0x98, 0x00, 0x00, 0xc3, 0x04, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xf0, 0x93, 0x96, 0xff, 0xf4,
+ 0xf7, 0x82, 0x78, 0x0c, 0xe0, 0x00, 0x73, 0x40, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4,
+ 0x8f, 0x96, 0xff, 0xf0, 0xfe, 0x82, 0x00, 0x1f, 0xcf, 0x78, 0xec, 0x00, 0xcf, 0xfc, 0xec, 0x00,
+ 0x7f, 0xfd, 0x00, 0x17, 0x7f, 0x79, 0x00, 0x12, 0xcf, 0xfc, 0xf5, 0x00, 0x5f, 0xfd, 0x20, 0x00,
+ 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0x78, 0x40, 0xe0, 0x00, 0x73, 0xcc, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xff, 0x88, 0x9f, 0xd0,
+ 0x93, 0x16, 0xff, 0xf4, 0xf3, 0x82, 0x00, 0x01, 0xf4, 0x02, 0x00, 0x09, 0x20, 0x7e, 0x00, 0x03,
+ 0xe6, 0x00, 0x78, 0xd4, 0xf3, 0x02, 0x00, 0x00, 0xf7, 0x82, 0x78, 0x84, 0xe0, 0x00, 0x76, 0x8c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x78, 0x98,
+ 0xe0, 0x00, 0x77, 0x7c, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0x78, 0xcd, 0x5f, 0xa0, 0x00, 0x01, 0xff, 0x82, 0xff, 0xfe, 0xc4, 0x20, 0xfc, 0x00,
+ 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x78, 0xc4, 0xe0, 0x00, 0x77, 0x04,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x78, 0xd4, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x78, 0xb0,
+ 0x44, 0x7d, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x24, 0x18, 0x7f, 0xf9, 0xf3, 0x02, 0x00, 0x00,
+ 0xf3, 0x82, 0x00, 0x01, 0x44, 0x21, 0x00, 0x00, 0xf7, 0x82, 0x79, 0x04, 0xe0, 0x00, 0x76, 0x8c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x79, 0x18,
+ 0xe0, 0x00, 0x77, 0x7c, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x08, 0xa8, 0x58,
+ 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xc0, 0x7a, 0x32, 0x00, 0xe6, 0x00, 0x79, 0x95,
+ 0xf4, 0x02, 0x80, 0x00, 0xf7, 0x82, 0x79, 0x50, 0xe0, 0x00, 0x76, 0x8c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x79, 0x64, 0xe0, 0x00, 0x77, 0x7c,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x0c, 0xc4, 0x20, 0xfc, 0x00, 0x20, 0x22, 0x00, 0x04,
+ 0xe6, 0x00, 0x79, 0x8d, 0xf4, 0x09, 0xa9, 0x60, 0xff, 0x88, 0xa9, 0x60, 0x20, 0x7e, 0x00, 0x08,
+ 0xe6, 0x78, 0x00, 0x03, 0xe0, 0x00, 0x79, 0x94, 0xff, 0x09, 0xa8, 0x58, 0xe0, 0x00, 0x79, 0x78,
+ 0xf0, 0x09, 0xa9, 0x60, 0xc4, 0x78, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0x93, 0x16, 0xff, 0xf4, 0x93, 0x96, 0xff, 0xf0, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01,
+ 0xf4, 0x02, 0xc2, 0x00, 0xf7, 0x82, 0x79, 0xd0, 0xe0, 0x00, 0x76, 0x8c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x79, 0xe4, 0xe0, 0x00, 0x77, 0x7c,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x01, 0xc3, 0x20, 0x00, 0x00, 0xc3, 0xfc, 0x00, 0x00,
+ 0xc3, 0x1a, 0xfc, 0x00, 0xf4, 0x02, 0x80, 0x00, 0xe6, 0x00, 0x7a, 0x4c, 0xcf, 0x84, 0x00, 0x00,
+ 0xf7, 0x82, 0x7a, 0x0c, 0xe0, 0x00, 0x76, 0x8c, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf0,
+ 0xf3, 0x02, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x03, 0x7f, 0xf9, 0x00, 0x08, 0x8f, 0x16, 0xff, 0xf4,
+ 0xf3, 0x82, 0x00, 0x01, 0xc0, 0x7a, 0x32, 0x00, 0xe6, 0x00, 0x7a, 0x34, 0x0f, 0xfc, 0x00, 0x02,
+ 0x44, 0x7d, 0x00, 0x00, 0xf7, 0x82, 0x7a, 0x40, 0xe0, 0x00, 0x77, 0x04, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x82, 0x00, 0x01, 0xff, 0x89, 0xa8, 0x58, 0xff, 0x82, 0x00, 0x00, 0xc4, 0x7c, 0x00, 0x00,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x07, 0x08,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x83, 0x5b, 0xe8, 0xf3, 0x02, 0x00, 0x02,
+ 0xf0, 0x89, 0xa5, 0x74, 0x4f, 0xfc, 0xff, 0xfe, 0xff, 0x83, 0x6b, 0xe8, 0xf7, 0x82, 0x7a, 0x98,
+ 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x76, 0xff, 0xcc, 0x8f, 0xfa, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0xfc, 0x4f, 0xfd, 0xf3, 0xff, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0xfa, 0x00, 0x00,
+ 0xf7, 0x82, 0x7a, 0xbc, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00,
+ 0xf7, 0x82, 0x7a, 0xcc, 0xe0, 0x00, 0x78, 0x50, 0x97, 0x93, 0xff, 0xfc, 0xf0, 0x03, 0x2a, 0x12,
+ 0xf0, 0x03, 0x2a, 0x28, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x76, 0xff, 0xcc, 0x8f, 0xfa, 0x00, 0x00,
+ 0xf3, 0x09, 0xa5, 0x74, 0x5f, 0xfd, 0x0c, 0x00, 0x9f, 0xfa, 0x00, 0x00, 0xf3, 0x76, 0xff, 0xfc,
+ 0xf7, 0x82, 0x7b, 0x0c, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xe8,
+ 0xf3, 0x02, 0x00, 0x01, 0xcf, 0xfc, 0x35, 0x00, 0xff, 0x83, 0x6b, 0xe8, 0xf7, 0x82, 0x7b, 0x28,
+ 0xe0, 0x00, 0x78, 0x50, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x08,
+ 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x07, 0x08, 0x62, 0x6f, 0x6f, 0x74, 0x5f, 0x72, 0x65, 0x62,
+ 0x6f, 0x6f, 0x74, 0x28, 0x25, 0x75, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0x22, 0x10, 0x00, 0x08, 0xff, 0x02, 0x7b, 0x48,
+ 0x9f, 0x12, 0x00, 0x00, 0x93, 0x12, 0x00, 0x04, 0x93, 0x16, 0xff, 0xf4, 0xf7, 0x82, 0x7b, 0x88,
+ 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4, 0xff, 0x02, 0x00, 0x3f,
+ 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x17, 0xf7, 0x82, 0x7b, 0xa4, 0xc1, 0x7c, 0x7d, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xe1, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8f, 0x82, 0xff, 0xd0, 0xf3, 0x09, 0xcf, 0x20, 0xf3, 0x02, 0x00, 0x01, 0xff, 0x89, 0xe6, 0x80,
+ 0xf7, 0x82, 0x7b, 0xdc, 0xe0, 0x00, 0x7b, 0x5c, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0x9f, 0xe0, 0xfd, 0x8a, 0xa9, 0xb0, 0x20, 0x1a, 0x00, 0x00, 0x7f, 0x7d, 0x00, 0x02,
+ 0xb3, 0x7a, 0xd8, 0x02, 0x0f, 0xfc, 0x00, 0x01, 0x7e, 0x7d, 0x00, 0x02, 0x8e, 0x82, 0xff, 0xc8,
+ 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x02, 0x00, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0xbe, 0xf2, 0xd8, 0x02,
+ 0xe6, 0x00, 0x7c, 0x30, 0xff, 0x89, 0x9f, 0xe0, 0xe0, 0x00, 0x7c, 0x28, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x8f, 0x02, 0xff, 0xd0, 0x8f, 0x82, 0xff, 0xd0, 0xcf, 0xfc, 0xf2, 0x00,
+ 0xc0, 0x7e, 0x32, 0x00, 0xe4, 0x00, 0x7c, 0x48, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0xa8, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x7c, 0x9d, 0xc4, 0x18, 0x00, 0x00,
+ 0x20, 0x1a, 0x00, 0x87, 0xe2, 0x00, 0x7c, 0x99, 0x04, 0x18, 0x00, 0x18, 0x20, 0x1a, 0x00, 0xa7,
+ 0xe2, 0x00, 0x7c, 0x9d, 0x00, 0x00, 0x00, 0x01, 0xc4, 0x18, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x1d, 0xed, 0xa0, 0x04, 0x03, 0xff, 0x02,
+ 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0x02, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x02, 0x00, 0x00, 0x07, 0x06, 0x04, 0x00, 0x0f, 0x0e, 0x0c, 0x08, 0x1f, 0x1e, 0x1c, 0x18,
+ 0x3f, 0x3e, 0x3c, 0x38, 0x7f, 0x7e, 0x7c, 0x78, 0xff, 0xfe, 0xfc, 0xf8, 0x0f, 0xff, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xce, 0xc0, 0x55, 0x29, 0x80, 0x00,
+ 0x5f, 0xfc, 0x00, 0x02, 0xff, 0x89, 0xce, 0xc0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x8d, 0x82, 0xff, 0x70,
+ 0xfe, 0x82, 0x00, 0x00, 0xfe, 0x0a, 0xe6, 0x00, 0x7f, 0x75, 0x00, 0x02, 0xaf, 0xfa, 0xe0, 0x02,
+ 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x76, 0x00, 0x02, 0xcf, 0xfc, 0xdd, 0x00, 0xe2, 0x00, 0x7d, 0x29,
+ 0xbf, 0xfa, 0xe0, 0x02, 0x8f, 0x02, 0xff, 0x78, 0xff, 0x88, 0xe6, 0x00, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x00, 0x7d, 0x69, 0xfe, 0x8a, 0xe6, 0x00, 0xff, 0x88, 0xce, 0xc0, 0x55, 0x29, 0x80, 0x00,
+ 0x5f, 0xfc, 0x04, 0x00, 0xff, 0x89, 0xce, 0xc0, 0x73, 0x19, 0x00, 0x02, 0xa4, 0x1a, 0xe8, 0x02,
+ 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x00, 0x7d, 0x81, 0x00, 0x00, 0x00, 0x01, 0xb0, 0x1a, 0xe8, 0x02,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x8f, 0x82, 0xff, 0x70, 0xff, 0x02, 0x00, 0x00, 0xfe, 0x8a, 0xe6, 0x00,
+ 0x9f, 0x82, 0xfe, 0x88, 0x7f, 0xf9, 0x00, 0x02, 0x0f, 0x78, 0x00, 0x01, 0x20, 0x7a, 0x00, 0x02,
+ 0xee, 0x00, 0x7d, 0xa5, 0xb0, 0x7e, 0xe8, 0x02, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf3, 0x82, 0x00, 0x00,
+ 0xf3, 0x0a, 0xa5, 0x3c, 0xf7, 0x82, 0x7d, 0xe0, 0xe0, 0x00, 0x2b, 0x98, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x02, 0xf7, 0x82, 0x7d, 0xf0, 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x0a, 0xa5, 0x3b, 0xf3, 0x82, 0x00, 0x02, 0xf7, 0x82, 0x7e, 0x04, 0xe0, 0x00, 0x2b, 0x98,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8a, 0x62, 0x5a, 0x9f, 0x82, 0xff, 0xc0,
+ 0x8f, 0x02, 0xff, 0xd0, 0xff, 0xf6, 0xe9, 0xe8, 0x9f, 0x7e, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0x01, 0xc0, 0x8d, 0x0f, 0x78, 0x5d, 0x02, 0xfe, 0xf6, 0xff, 0x38, 0x9f, 0x76, 0x00, 0x00,
+ 0xff, 0xf6, 0xff, 0x34, 0x9f, 0x7e, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x30, 0x9f, 0x76, 0x00, 0x00,
+ 0xfe, 0xf6, 0xff, 0x2c, 0x9f, 0x76, 0x00, 0x00, 0x0f, 0x81, 0xc0, 0x9d, 0x0f, 0xfc, 0x5d, 0x00,
+ 0xff, 0x76, 0xff, 0x58, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x54, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x50, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x4c, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x48, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x44, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x40, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x3c, 0x9f, 0xf6, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0x5c, 0xf7, 0x82, 0x7e, 0xc0, 0xe0, 0x00, 0x2d, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x07, 0xd0, 0xf7, 0x82, 0x7e, 0xd0, 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0x0f, 0x01, 0xc0, 0x0d, 0x0f, 0x78, 0x7d, 0x02, 0xff, 0xf6, 0xff, 0x38, 0x9f, 0x7e, 0x00, 0x00,
+ 0xfe, 0xf6, 0xff, 0x34, 0x9f, 0x76, 0x00, 0x00, 0xff, 0xf6, 0xff, 0x30, 0x9f, 0x7e, 0x00, 0x00,
+ 0xfe, 0xf6, 0xff, 0x2c, 0x9f, 0x76, 0x00, 0x00, 0x0f, 0x81, 0xc0, 0x1d, 0x0f, 0xfc, 0x7d, 0x00,
+ 0xff, 0x76, 0xff, 0x58, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x54, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x50, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x4c, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x48, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x44, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x40, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x3c, 0x9f, 0xf6, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0x5c, 0xf7, 0x82, 0x7f, 0x50, 0xe0, 0x00, 0x2d, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x07, 0xd0, 0xf7, 0x82, 0x7f, 0x60, 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0x0f, 0x01, 0xc0, 0x00, 0x0f, 0x78, 0x40, 0x02, 0xff, 0xf6, 0xff, 0x38, 0x9f, 0x7e, 0x00, 0x00,
+ 0xfe, 0xf6, 0xff, 0x34, 0x9f, 0x76, 0x00, 0x00, 0xff, 0xf6, 0xff, 0x30, 0x9f, 0x7e, 0x00, 0x00,
+ 0xfe, 0xf6, 0xff, 0x2c, 0x9f, 0x76, 0x00, 0x00, 0x0f, 0x81, 0xc0, 0x10, 0x0f, 0xfc, 0x40, 0x00,
+ 0xff, 0x76, 0xff, 0x58, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x54, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x50, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x4c, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x48, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x44, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0x40, 0x9f, 0xfa, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0x3c, 0xf3, 0x76, 0xff, 0x5c,
+ 0x9f, 0xf6, 0x00, 0x00, 0xf7, 0x82, 0x7f, 0xe0, 0xe0, 0x00, 0x2d, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x07, 0xd0, 0xf7, 0x82, 0x7f, 0xf0, 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x50, 0x43, 0x49, 0x45,
+ 0x20, 0x69, 0x73, 0x20, 0x75, 0x70, 0x0a, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x0c, 0xf7, 0x82, 0x80, 0x20, 0xe0, 0x01, 0x17, 0xc8, 0x97, 0x93, 0xff, 0xfc,
+ 0xfd, 0x76, 0xff, 0xe8, 0xfd, 0xf6, 0xff, 0xec, 0x8f, 0xea, 0x00, 0x00, 0x8f, 0x6e, 0x00, 0x00,
+ 0xfe, 0x88, 0xa0, 0x10, 0x4f, 0xfd, 0xff, 0x01, 0x4f, 0x78, 0x00, 0x00, 0x9f, 0x6e, 0x00, 0x00,
+ 0x5f, 0xfd, 0x00, 0x40, 0x9f, 0xea, 0x00, 0x00, 0xfe, 0x02, 0x00, 0x00, 0x0e, 0xf4, 0x00, 0x01,
+ 0xfe, 0x89, 0xa0, 0x10, 0xfe, 0x09, 0xce, 0x80, 0xfe, 0x09, 0xce, 0xc0, 0xf3, 0x76, 0xff, 0xfc,
+ 0x45, 0x29, 0x7f, 0xff, 0xf7, 0x82, 0x80, 0x70, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x03, 0x5b, 0xe8, 0xff, 0x88, 0xa0, 0x10, 0xfe, 0x02, 0x00, 0x01, 0xcf, 0x78, 0xe4, 0x00,
+ 0xcf, 0xfc, 0xe0, 0x00, 0x5f, 0x78, 0x00, 0x04, 0xff, 0x89, 0xa0, 0x10, 0xff, 0x03, 0x6b, 0xe8,
+ 0xf7, 0x82, 0x80, 0x9c, 0xe0, 0x00, 0x7d, 0x8c, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8,
+ 0xff, 0x02, 0x00, 0x80, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x81, 0x19, 0x0e, 0x81, 0x3f, 0xff,
+ 0x0e, 0xf4, 0x33, 0x33, 0x9e, 0x96, 0xff, 0xf0, 0xf7, 0x82, 0x80, 0xc4, 0xe0, 0x00, 0x7e, 0x10,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x02, 0x00, 0x80, 0x9f, 0x02, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xff, 0xd0, 0x8e, 0x96, 0xff, 0xf0, 0xfe, 0x02, 0x00, 0x1f, 0x7f, 0xfc, 0xff, 0xef,
+ 0xff, 0x03, 0x5b, 0xd8, 0xcf, 0xfc, 0xe4, 0x00, 0xcf, 0x80, 0xfa, 0x00, 0xcf, 0xf4, 0xff, 0xc0,
+ 0xfe, 0x02, 0x00, 0x01, 0xce, 0xfc, 0xe4, 0x00, 0x4f, 0x78, 0xff, 0xfe, 0xcf, 0x78, 0xed, 0x00,
+ 0xff, 0x03, 0x6b, 0xd8, 0x8f, 0x82, 0xff, 0xf8, 0xfe, 0x82, 0x00, 0x80, 0xc0, 0x7e, 0xec, 0x00,
+ 0xe6, 0x00, 0x80, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x02, 0x00, 0x50, 0xf7, 0x82, 0x81, 0x28,
+ 0xe0, 0x00, 0x21, 0x54, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x02, 0x18, 0x00, 0xff, 0x03, 0x2a, 0x52,
+ 0xff, 0x88, 0xa0, 0x10, 0xfe, 0x83, 0x5b, 0xe8, 0xff, 0x02, 0x00, 0x01, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xce, 0xf4, 0xf4, 0x00, 0xff, 0x89, 0xa0, 0x10, 0x5e, 0xf4, 0x00, 0x06, 0xff, 0x82, 0x00, 0x04,
+ 0xfe, 0x83, 0x6b, 0xe8, 0xff, 0x89, 0xce, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x0a, 0xa0, 0x90, 0x0e, 0x81, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0x0e, 0xf4, 0x01, 0x80,
+ 0x9e, 0x82, 0xfe, 0x58, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0a, 0xa0, 0x90,
+ 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x01, 0x80, 0x9f, 0x82, 0xfe, 0x58,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0xe0, 0x8f, 0x02, 0xfe, 0xf8,
+ 0x8e, 0x82, 0xff, 0x10, 0xcf, 0xfc, 0xf4, 0x00, 0xcf, 0xfc, 0xec, 0x00, 0x9f, 0x96, 0xff, 0xf4,
+ 0xf7, 0x82, 0x81, 0xdc, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8,
+ 0xfe, 0x02, 0x00, 0x80, 0xc0, 0x7e, 0xe4, 0x00, 0xe6, 0x00, 0x81, 0xfd, 0x00, 0x00, 0x00, 0x01,
+ 0xf2, 0x82, 0x04, 0x00, 0xe0, 0x00, 0x80, 0x10, 0x22, 0x14, 0x00, 0x08, 0x8f, 0x82, 0xff, 0xf8,
+ 0xfe, 0x82, 0x01, 0x00, 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x81, 0xd1, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x02, 0xff, 0xd0, 0x0e, 0x81, 0xff, 0xf0, 0xff, 0x82, 0x00, 0x1f, 0x7f, 0x78, 0xff, 0xf0,
+ 0xfe, 0x03, 0x5b, 0xd8, 0xcf, 0xf8, 0xfc, 0x00, 0x0e, 0xf4, 0xff, 0xf0, 0xcf, 0x00, 0xfa, 0x00,
+ 0xcf, 0x74, 0xf7, 0x80, 0xff, 0x82, 0x00, 0x01, 0xce, 0xf8, 0xfc, 0x00, 0x4e, 0x70, 0xff, 0xfe,
+ 0xce, 0x70, 0xed, 0x00, 0xfe, 0x03, 0x6b, 0xd8, 0x8f, 0x96, 0xff, 0xf4, 0xf0, 0x03, 0x2a, 0x60,
+ 0x70, 0x7e, 0x00, 0x01, 0xea, 0x00, 0x81, 0xa0, 0xff, 0x0a, 0xa0, 0x90, 0xff, 0x88, 0xa0, 0x10,
+ 0xfe, 0x02, 0x00, 0x0c, 0xfe, 0x09, 0xce, 0x80, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x89, 0xa0, 0x10,
+ 0xfe, 0x8a, 0xa2, 0x10, 0x0f, 0x01, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0x0f, 0x78, 0x01, 0x80,
+ 0x9f, 0x02, 0xfe, 0x58, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x02, 0xfe, 0xe0,
+ 0x8e, 0x82, 0xfe, 0xf8, 0x8e, 0x02, 0xff, 0x10, 0xcf, 0x78, 0xed, 0x00, 0x8f, 0x82, 0xff, 0xf8,
+ 0xcf, 0x78, 0xe5, 0x00, 0x7f, 0xfd, 0x00, 0x16, 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x82, 0xbc, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8,
+ 0xfe, 0x02, 0x00, 0x80, 0xc0, 0x7e, 0xe4, 0x00, 0xe6, 0x00, 0x82, 0xdd, 0x00, 0x00, 0x00, 0x01,
+ 0xf2, 0x82, 0x04, 0x00, 0xe0, 0x00, 0x80, 0x10, 0x22, 0x14, 0x00, 0x08, 0x8f, 0x82, 0xff, 0xf8,
+ 0xff, 0x02, 0x01, 0x00, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x82, 0xb1, 0x00, 0x00, 0x00, 0x01,
+ 0x8e, 0x96, 0xff, 0xf4, 0xf0, 0x03, 0x2a, 0x60, 0x20, 0x76, 0x00, 0x00, 0xec, 0x00, 0x82, 0x74,
+ 0xfe, 0x8a, 0xa2, 0x10, 0x0f, 0x81, 0x80, 0x00, 0x0f, 0xfc, 0x00, 0x43, 0x9f, 0x82, 0xff, 0x90,
+ 0xff, 0x88, 0xa0, 0x10, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x89, 0xa0, 0x10, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xff, 0xf8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x83, 0x80, 0x0f, 0x81, 0x80, 0x60,
+ 0xf7, 0x82, 0x83, 0x4c, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8,
+ 0xfe, 0x02, 0x00, 0x80, 0xc0, 0x7e, 0xe4, 0x00, 0xe6, 0x00, 0x83, 0x6d, 0x00, 0x00, 0x00, 0x01,
+ 0xf2, 0x82, 0x04, 0x00, 0xe0, 0x00, 0x80, 0x10, 0x22, 0x14, 0x00, 0x08, 0x8f, 0x82, 0xff, 0xf8,
+ 0xfe, 0x82, 0x01, 0x00, 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x83, 0x41, 0x0f, 0x81, 0x80, 0x60,
+ 0xf0, 0x03, 0x2a, 0x60, 0xff, 0x02, 0x00, 0x08, 0x0f, 0xfc, 0x02, 0x00, 0xff, 0x09, 0xce, 0x80,
+ 0x9f, 0x82, 0xff, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x01, 0xa0, 0x01, 0x9e, 0x02, 0xff, 0x88,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0xf6, 0xff, 0xec, 0x8f, 0x7e, 0x00, 0x00, 0xf3, 0x76, 0xff, 0xfc,
+ 0x5f, 0x78, 0x00, 0xff, 0x4f, 0x78, 0x00, 0xff, 0x9f, 0x7e, 0x00, 0x00, 0xf7, 0x82, 0x83, 0xe8,
+ 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x0e, 0x81, 0x20, 0x03, 0x0e, 0xf4, 0x00, 0x01,
+ 0x9e, 0x82, 0xff, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x90, 0x00, 0x0f, 0x78, 0x00, 0x43,
+ 0x9f, 0x02, 0xff, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xff, 0x82, 0x00, 0x20, 0xff, 0x83, 0x2b, 0x22,
+ 0xff, 0x88, 0xa0, 0x00, 0x0e, 0x01, 0x00, 0x3f, 0xf0, 0x03, 0x2b, 0x0a, 0x0e, 0x70, 0xfc, 0x04,
+ 0x20, 0x7e, 0x00, 0x00, 0x9e, 0x02, 0xff, 0x78, 0xe6, 0x00, 0x85, 0xa5, 0xf3, 0x02, 0x00, 0x02,
+ 0xf3, 0x02, 0x00, 0x01, 0xf7, 0x82, 0x84, 0x60, 0xe0, 0x00, 0x90, 0x20, 0x97, 0x93, 0xff, 0xfc,
+ 0xf0, 0x09, 0xa0, 0x00, 0xf3, 0x02, 0x00, 0x00, 0xf7, 0x82, 0x84, 0x74, 0xe0, 0x00, 0x96, 0xc8,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00, 0xf7, 0x82, 0x84, 0x84, 0xe0, 0x01, 0x01, 0x74,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x03, 0x1b, 0x9a, 0xff, 0x8a, 0xa5, 0x20, 0xfe, 0x82, 0x0f, 0xff,
+ 0x20, 0x7a, 0x0f, 0xff, 0xe6, 0x00, 0x85, 0x1d, 0xfe, 0xff, 0x28, 0x02, 0xff, 0x0a, 0xa5, 0x20,
+ 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x14, 0x9f, 0x82, 0xfe, 0x58,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x84, 0xc4, 0xe0, 0x00, 0x7e, 0x10,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8, 0xfe, 0x02, 0x00, 0x80, 0xc0, 0x7e, 0xe4, 0x00,
+ 0xe6, 0x00, 0x84, 0xe5, 0x00, 0x00, 0x00, 0x01, 0xf2, 0x82, 0x04, 0x00, 0xe0, 0x00, 0x80, 0x10,
+ 0x22, 0x14, 0x00, 0x08, 0x8f, 0x82, 0xff, 0xf8, 0xfe, 0x82, 0x01, 0x00, 0xc0, 0x7e, 0xec, 0x00,
+ 0xe6, 0x00, 0x84, 0xb9, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x2a, 0x60, 0xf3, 0x02, 0x07, 0xd0,
+ 0xf7, 0x82, 0x85, 0x0c, 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x1b, 0x9a,
+ 0x20, 0x7e, 0x0f, 0xff, 0xe6, 0x00, 0x84, 0xa0, 0xff, 0x0a, 0xa5, 0x20, 0x0f, 0x01, 0x90, 0x00,
+ 0x0f, 0x78, 0x40, 0x00, 0x9f, 0x02, 0xff, 0x80, 0xf3, 0x02, 0x00, 0x4c, 0xf7, 0x82, 0x85, 0x38,
+ 0xe0, 0x00, 0x21, 0x54, 0x97, 0x93, 0xff, 0xfc, 0x22, 0x10, 0x00, 0x04, 0xff, 0x82, 0x7f, 0xfc,
+ 0x9f, 0x92, 0x00, 0x00, 0xff, 0x88, 0xa0, 0x10, 0x0f, 0xfd, 0x00, 0x01, 0x4f, 0xfc, 0x00, 0x00,
+ 0xff, 0x89, 0xa0, 0x10, 0xf7, 0x82, 0x85, 0x60, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc,
+ 0xfe, 0x02, 0x3d, 0x09, 0x9e, 0x02, 0xff, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x02, 0x10, 0x00, 0x04,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0x85, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x85, 0xb0, 0xe0, 0x00, 0x90, 0x20, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0x84, 0x68, 0xf3, 0x02, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x50, 0x43, 0x49, 0x45, 0x20, 0x69, 0x73, 0x20, 0x64, 0x6f, 0x77, 0x6e,
+ 0x21, 0x21, 0x0a, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04,
+ 0x22, 0x10, 0x00, 0x04, 0xff, 0x82, 0x85, 0xc4, 0x9f, 0x92, 0x00, 0x00, 0xf7, 0x82, 0x85, 0xf8,
+ 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc, 0x02, 0x10, 0x00, 0x04, 0xf7, 0x82, 0x86, 0x08,
+ 0xe0, 0x00, 0x80, 0x08, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x30, 0x00,
+ 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x31, 0x00, 0x4c, 0x31, 0x00, 0x4c,
+ 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x33, 0x00, 0x4c, 0x32, 0x33, 0x5f, 0x52,
+ 0x65, 0x61, 0x64, 0x79, 0x00, 0x4c, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x35,
+ 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x8f, 0x9a, 0x00, 0x04,
+ 0xff, 0x03, 0x1a, 0x42, 0x7f, 0xfd, 0x00, 0x01, 0x4e, 0x7b, 0x00, 0x00, 0xe6, 0x00, 0x86, 0xed,
+ 0x7e, 0xfc, 0xff, 0xe7, 0xff, 0x82, 0x00, 0x38, 0xff, 0x02, 0x00, 0x5f, 0xcd, 0x74, 0xfc, 0x00,
+ 0xcd, 0xf4, 0xf4, 0x00, 0xff, 0x1b, 0x18, 0x00, 0xff, 0x82, 0x07, 0xff, 0xcf, 0xf8, 0xfc, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0x0f, 0xfc, 0x00, 0x0f, 0x4f, 0xfc, 0xff, 0xf0, 0x7f, 0x78, 0xff, 0xf5,
+ 0x20, 0x7a, 0x00, 0x02, 0xe6, 0x00, 0x87, 0x11, 0xce, 0x98, 0xf8, 0x00, 0xff, 0x88, 0xa5, 0x54,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x86, 0xcc, 0x20, 0x7a, 0x00, 0x11, 0xe6, 0x00, 0x86, 0xf5,
+ 0x20, 0x7a, 0x00, 0x06, 0xe6, 0x00, 0x86, 0xf9, 0x20, 0x6e, 0x00, 0x40, 0xff, 0xfa, 0x7f, 0xff,
+ 0xc0, 0x76, 0xfa, 0x00, 0xe2, 0x00, 0x86, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x2e, 0xf4, 0x80, 0x00,
+ 0x2e, 0x72, 0x00, 0x01, 0xe6, 0x00, 0x86, 0x84, 0xc3, 0x74, 0x00, 0x00, 0xe0, 0x00, 0x87, 0x34,
+ 0xf4, 0x02, 0x00, 0x00, 0x20, 0x6e, 0x00, 0x40, 0xe6, 0x00, 0x86, 0xcd, 0x20, 0x6a, 0x00, 0x30,
+ 0xe6, 0x00, 0x86, 0xcd, 0xff, 0x82, 0x00, 0x01, 0xe0, 0x00, 0x86, 0xcc, 0xff, 0x89, 0xa5, 0x54,
+ 0xff, 0x9b, 0x58, 0x02, 0x20, 0x7e, 0x00, 0x24, 0xe6, 0x00, 0x87, 0x31, 0x03, 0x01, 0xe1, 0x00,
+ 0x03, 0x18, 0x04, 0xa5, 0xf7, 0x82, 0x87, 0x30, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc,
+ 0xf4, 0x02, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x76, 0xff, 0xe8, 0x8f, 0xfa, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0xfc, 0x0f, 0x01, 0xff, 0xfe, 0x0f, 0x78, 0x01, 0xff, 0x5f, 0xfd, 0x00, 0x02,
+ 0xcf, 0xfc, 0xf4, 0x00, 0x5f, 0xfc, 0x8a, 0x00, 0x5f, 0xfd, 0x00, 0x04, 0xff, 0x76, 0xff, 0xe8,
+ 0x9f, 0xfa, 0x00, 0x00, 0xf7, 0x82, 0x87, 0x80, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x0a, 0xf7, 0x82, 0x87, 0x90, 0xe0, 0x00, 0x7c, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x76, 0xff, 0xbc, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x87, 0xa4, 0xe0, 0x00, 0x28, 0x78,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0xf6, 0xff, 0xa8, 0x8e, 0xfe, 0x00, 0x00, 0xfe, 0x76, 0xff, 0xac,
+ 0x8f, 0x72, 0x00, 0x00, 0x7e, 0xf5, 0x00, 0x1b, 0x7e, 0xf4, 0xff, 0xe8, 0x7f, 0x78, 0xff, 0xe3,
+ 0xcf, 0x78, 0xe8, 0x00, 0xff, 0x09, 0xa5, 0x4c, 0xff, 0x76, 0xff, 0xe8, 0x8f, 0xfa, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0xfc, 0x4f, 0xfd, 0xff, 0x07, 0x5f, 0xfd, 0x00, 0xa0, 0x9f, 0xfa, 0x00, 0x00,
+ 0xf7, 0x82, 0x87, 0xec, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20,
+ 0x25, 0x73, 0x0a, 0x00, 0x54, 0x69, 0x6d, 0x65, 0x64, 0x2d, 0x6f, 0x75, 0x74, 0x20, 0x77, 0x68,
+ 0x65, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x25, 0x73,
+ 0x0a, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x14,
+ 0xff, 0x0a, 0xa3, 0x90, 0x93, 0x16, 0xff, 0xf4, 0x93, 0x96, 0xff, 0xf0, 0x20, 0x1a, 0x00, 0x02,
+ 0xe6, 0x00, 0x88, 0x51, 0x9f, 0x16, 0xff, 0xec, 0xff, 0x8a, 0xa4, 0x10, 0x9f, 0x96, 0xff, 0xec,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x08, 0xe6, 0x18, 0xfe, 0x8e, 0x0d, 0x40, 0xcf, 0xfc, 0xf2, 0x00,
+ 0xc0, 0x7e, 0xea, 0x00, 0xe2, 0x00, 0x89, 0xe4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa5, 0x44,
+ 0x20, 0x7e, 0x00, 0x02, 0xe6, 0x00, 0x89, 0x79, 0x00, 0x00, 0x00, 0x01, 0xe2, 0x00, 0x88, 0xfc,
+ 0x20, 0x7e, 0x00, 0x03, 0x20, 0x7e, 0x00, 0x01, 0xe6, 0x00, 0x88, 0xad, 0xff, 0x82, 0x00, 0x02,
+ 0x03, 0x01, 0xe1, 0x00, 0x03, 0x18, 0x05, 0x3d, 0xf7, 0x82, 0x88, 0xa4, 0xe0, 0x00, 0x7b, 0xb8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x8a, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xec,
+ 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0x01, 0x10, 0x00, 0x0f, 0x78, 0x00, 0x80, 0x9f, 0x02, 0xfe, 0x58,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x2f, 0xfe, 0x00, 0x01, 0xea, 0x00, 0x88, 0xac,
+ 0xff, 0x02, 0x00, 0x03, 0x8f, 0x96, 0xff, 0xf4, 0xff, 0x09, 0xa5, 0x48, 0x20, 0x7e, 0x00, 0x02,
+ 0xff, 0x82, 0x00, 0x02, 0xe6, 0x00, 0x8a, 0x2c, 0xff, 0x89, 0xa5, 0x44, 0x0f, 0x01, 0x20, 0x00,
+ 0x9f, 0x02, 0xff, 0x88, 0xe0, 0x00, 0x8a, 0x2c, 0x00, 0x00, 0x00, 0x01, 0xe6, 0x00, 0x88, 0x94,
+ 0x03, 0x01, 0xe1, 0x00, 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x17, 0xea, 0x00, 0x89, 0x6c,
+ 0x00, 0x00, 0x00, 0x01, 0xfe, 0x88, 0xa5, 0x48, 0xf0, 0x03, 0x2a, 0x60, 0x2e, 0xf4, 0x00, 0x01,
+ 0xfe, 0x89, 0xa5, 0x48, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0x8a, 0x2c, 0x22, 0x10, 0x00, 0x08,
+ 0x8f, 0x96, 0xff, 0xf4, 0xfe, 0x89, 0xa5, 0x44, 0x7f, 0x7d, 0x00, 0x02, 0xff, 0x8a, 0xa5, 0x58,
+ 0xaf, 0x7a, 0xf8, 0x02, 0x8f, 0x96, 0xff, 0xf4, 0x9f, 0x12, 0x00, 0x04, 0xff, 0x02, 0x87, 0xf8,
+ 0x9f, 0x12, 0x00, 0x00, 0xff, 0x89, 0xa5, 0x40, 0xf7, 0x82, 0x89, 0x64, 0xe0, 0x02, 0x87, 0x0c,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x8a, 0x2c, 0x02, 0x10, 0x00, 0x08, 0xfe, 0x88, 0xa5, 0x48,
+ 0xe0, 0x00, 0x89, 0x28, 0x20, 0x76, 0x00, 0x00, 0x83, 0x16, 0xff, 0xf0, 0xf7, 0x82, 0x89, 0x88,
+ 0xe0, 0x00, 0x86, 0x54, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0x89, 0xcc,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x17, 0xea, 0x00, 0x8a, 0x2c,
+ 0x00, 0x00, 0x00, 0x01, 0xf4, 0x03, 0x2a, 0x60, 0x8f, 0x16, 0xff, 0xec, 0x0f, 0x81, 0x10, 0x00,
+ 0x0f, 0xfc, 0x00, 0x80, 0x9f, 0x02, 0xfe, 0x58, 0x9f, 0x82, 0xfe, 0x58, 0x94, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x8a, 0x2c, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x89, 0xd8,
+ 0xe0, 0x00, 0x87, 0x40, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x03, 0xe0, 0x00, 0x8a, 0x2c,
+ 0xff, 0x89, 0xa5, 0x44, 0x8f, 0x96, 0xff, 0xf4, 0x22, 0x10, 0x00, 0x08, 0x7f, 0x7d, 0x00, 0x02,
+ 0xff, 0x8a, 0xa5, 0x58, 0xaf, 0x7a, 0xf8, 0x02, 0x9f, 0x12, 0x00, 0x04, 0xff, 0x02, 0x88, 0x04,
+ 0x9f, 0x12, 0x00, 0x00, 0xf7, 0x82, 0x8a, 0x10, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc,
+ 0x02, 0x10, 0x00, 0x08, 0xf3, 0x02, 0x00, 0x05, 0xf7, 0x82, 0x8a, 0x24, 0xe0, 0x00, 0x7b, 0x5c,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x88, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x42, 0x61, 0x63, 0x6b, 0x20, 0x74, 0x6f, 0x20,
+ 0x4c, 0x30, 0x2c, 0x20, 0x50, 0x43, 0x49, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x56, 0x5f, 0x43, 0x4f,
+ 0x55, 0x4e, 0x54, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x42, 0x61, 0x63, 0x6b, 0x20, 0x74, 0x6f, 0x20,
+ 0x4c, 0x44, 0x6e, 0x2c, 0x20, 0x50, 0x43, 0x49, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x56, 0x5f, 0x43,
+ 0x4f, 0x55, 0x4e, 0x54, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10, 0xff, 0x88, 0xa5, 0x40, 0x20, 0x7e, 0x00, 0x05,
+ 0xe2, 0x00, 0x8c, 0xf0, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x02, 0x8a, 0xa8, 0xae, 0xfe, 0xf0, 0x02,
+ 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x8a, 0xc0, 0x00, 0x00, 0x8a, 0xdc,
+ 0x00, 0x00, 0x8a, 0xf8, 0x00, 0x00, 0x8b, 0xe8, 0x00, 0x00, 0x8b, 0xf4, 0x00, 0x00, 0x8c, 0xe4,
+ 0x03, 0x01, 0xe1, 0x00, 0x03, 0x18, 0x05, 0x51, 0xf7, 0x82, 0x8a, 0xd4, 0xe0, 0x00, 0x7b, 0xb8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x8c, 0xf0, 0x00, 0x00, 0x00, 0x01, 0xc3, 0x98, 0x00, 0x00,
+ 0xf3, 0x02, 0x00, 0x02, 0xf7, 0x82, 0x8a, 0xf0, 0xe0, 0x00, 0x88, 0x24, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0x8c, 0xf0, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa5, 0x54, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0x8b, 0x4c, 0xfe, 0xf6, 0xff, 0xe8, 0xf3, 0x76, 0xff, 0xbc, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x82, 0x8b, 0x1c, 0xe0, 0x00, 0x28, 0x78, 0x97, 0x93, 0xff, 0xfc, 0xff, 0xf6, 0xff, 0xa8,
+ 0x8f, 0x7e, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0xac, 0x8f, 0xf6, 0x00, 0x00, 0x7f, 0x79, 0x00, 0x1b,
+ 0x7f, 0x78, 0xff, 0xe8, 0xfe, 0x88, 0xa5, 0x4c, 0x7f, 0xfc, 0xff, 0xe3, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0x8c, 0xf1, 0xfe, 0xf6, 0xff, 0xe8, 0x8f, 0xf6, 0x00, 0x00,
+ 0x0f, 0x01, 0xff, 0xfe, 0x0f, 0x78, 0x01, 0xff, 0x5f, 0xfd, 0x00, 0x02, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x5f, 0xfc, 0x08, 0x00, 0x4f, 0xfd, 0xff, 0x03, 0x5f, 0xfd, 0x00, 0x40, 0x9f, 0xf6, 0x00, 0x00,
+ 0x9e, 0x96, 0xff, 0xf4, 0x9f, 0x16, 0xff, 0xf0, 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x82, 0x8b, 0x88,
+ 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf4, 0x8f, 0x16, 0xff, 0xf0,
+ 0x8f, 0xf6, 0x00, 0x00, 0x4f, 0xfd, 0xff, 0xfd, 0xcf, 0xfc, 0xf4, 0x00, 0x9f, 0xf6, 0x00, 0x00,
+ 0xff, 0x88, 0xce, 0xc0, 0xf0, 0x09, 0xa5, 0x40, 0x4f, 0xfc, 0xf7, 0xff, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0x8b, 0xbc, 0xff, 0x89, 0xce, 0xc0, 0x45, 0x29, 0x7f, 0xff, 0x22, 0x10, 0x00, 0x08,
+ 0xff, 0x82, 0x8a, 0x38, 0x9f, 0x92, 0x00, 0x00, 0xff, 0x83, 0x1a, 0x42, 0x4f, 0xfd, 0x00, 0x00,
+ 0x9f, 0x92, 0x00, 0x04, 0xf7, 0x82, 0x8b, 0xe0, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0x8c, 0xf0, 0x02, 0x10, 0x00, 0x08, 0xc3, 0x98, 0x00, 0x00, 0xe0, 0x00, 0x8a, 0xe4,
+ 0xf3, 0x02, 0x00, 0x04, 0xf3, 0x76, 0xff, 0xbc, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0x8c, 0x08,
+ 0xe0, 0x00, 0x28, 0x78, 0x97, 0x93, 0xff, 0xfc, 0xff, 0xf6, 0xff, 0xa8, 0x8f, 0x7e, 0x00, 0x00,
+ 0xfe, 0xf6, 0xff, 0xac, 0x8f, 0xf6, 0x00, 0x00, 0x7f, 0x79, 0x00, 0x1b, 0x7f, 0x78, 0xff, 0xe8,
+ 0x7f, 0xfc, 0xff, 0xe3, 0xcf, 0xfc, 0xf0, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x8c, 0xf1,
+ 0xfe, 0xf6, 0xff, 0xe8, 0x8f, 0xf6, 0x00, 0x00, 0x0f, 0x01, 0xff, 0xfe, 0x0f, 0x78, 0x01, 0xff,
+ 0x5f, 0xfd, 0x00, 0x02, 0xcf, 0xfc, 0xf4, 0x00, 0x4f, 0xfd, 0xff, 0x03, 0x5f, 0xfd, 0x00, 0x40,
+ 0x9f, 0xf6, 0x00, 0x00, 0x9e, 0x96, 0xff, 0xf4, 0x9f, 0x16, 0xff, 0xf0, 0xf3, 0x76, 0xff, 0xfc,
+ 0xf7, 0x82, 0x8c, 0x6c, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xf4,
+ 0x8f, 0x16, 0xff, 0xf0, 0x8f, 0xf6, 0x00, 0x00, 0x4f, 0xfd, 0xff, 0xfd, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x9f, 0xf6, 0x00, 0x00, 0xff, 0x82, 0x00, 0x05, 0xff, 0x89, 0xa5, 0x40, 0xff, 0x88, 0xce, 0xc0,
+ 0x4f, 0xfc, 0xf7, 0xff, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x8c, 0xa4, 0xff, 0x89, 0xce, 0xc0,
+ 0x45, 0x29, 0x7f, 0xff, 0x22, 0x10, 0x00, 0x08, 0xff, 0x82, 0x8a, 0x58, 0x9f, 0x92, 0x00, 0x00,
+ 0xff, 0x83, 0x1a, 0x42, 0x4f, 0xfd, 0x00, 0x00, 0x9f, 0x92, 0x00, 0x04, 0xf7, 0x82, 0x8c, 0xc8,
+ 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x18,
+ 0xea, 0x00, 0x8c, 0xf1, 0x02, 0x10, 0x00, 0x08, 0x03, 0x01, 0xe1, 0x00, 0xe0, 0x00, 0x8a, 0xc8,
+ 0x03, 0x18, 0x05, 0x8f, 0x03, 0x01, 0xe1, 0x00, 0xe0, 0x00, 0x8a, 0xc8, 0x03, 0x18, 0x05, 0x95,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0e, 0x81, 0x02, 0x00, 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x00, 0x8d, 0x45,
+ 0xc4, 0x1c, 0x00, 0x00, 0x8f, 0x82, 0xff, 0xf8, 0x93, 0x02, 0xfe, 0x68, 0x93, 0x82, 0xfe, 0x68,
+ 0x93, 0x02, 0xfe, 0x68, 0xcf, 0xfc, 0xec, 0x00, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x02, 0xff, 0xf8, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x8d, 0x44, 0xc4, 0x78, 0xec, 0x00,
+ 0x9e, 0x82, 0xff, 0xf8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0xf3, 0x82, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0xbc, 0xf7, 0x82, 0x8d, 0x70, 0xe0, 0x00, 0x28, 0x78, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0xf6, 0xff, 0x80, 0x8f, 0xfe, 0x00, 0x00, 0xfd, 0xf6, 0xff, 0xdc, 0xfe, 0x76, 0xff, 0xd8,
+ 0x7f, 0xfd, 0x00, 0x04, 0x9f, 0x96, 0xff, 0xec, 0x8f, 0x6e, 0x00, 0x00, 0x8e, 0xf2, 0x00, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe6, 0x4f, 0x79, 0x3f, 0xff, 0x9f, 0x96, 0xff, 0xf0, 0x4f, 0xfc, 0xff, 0xfe,
+ 0x7e, 0x7c, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x1e, 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x6e, 0x00, 0x00,
+ 0x4e, 0xf4, 0xff, 0xf0, 0xce, 0xf4, 0xe5, 0x00, 0xfd, 0xf6, 0xff, 0xd8, 0x9e, 0xee, 0x00, 0x00,
+ 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x82, 0x8d, 0xd0, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x26, 0x34, 0x58, 0xf3, 0xf6, 0xfe, 0x00, 0xc3, 0x9c, 0x32, 0x00, 0xf7, 0x82, 0x8d, 0xe8,
+ 0xe0, 0x00, 0x8c, 0xfc, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x76, 0xff, 0x00, 0xf3, 0x8a, 0x01, 0x00,
+ 0x94, 0x16, 0xff, 0xf4, 0xf7, 0x82, 0x8e, 0x00, 0xe0, 0x00, 0x8c, 0xfc, 0x97, 0x93, 0xff, 0xfc,
+ 0xfe, 0x76, 0xff, 0xdc, 0x8f, 0xf2, 0x00, 0x00, 0x8d, 0x96, 0xff, 0xf0, 0xfe, 0xf6, 0xff, 0xd8,
+ 0x8f, 0x76, 0x00, 0x00, 0x7e, 0x6d, 0x00, 0x1e, 0x8d, 0x96, 0xff, 0xec, 0x4f, 0xfd, 0x3f, 0xff,
+ 0xcf, 0xfc, 0xe5, 0x00, 0x7e, 0xec, 0xff, 0xe4, 0x4f, 0x78, 0xff, 0xf0, 0xcf, 0x78, 0xed, 0x00,
+ 0xfe, 0x76, 0xff, 0xdc, 0x9f, 0xf2, 0x00, 0x00, 0xfe, 0xf6, 0xff, 0xd8, 0x9f, 0x76, 0x00, 0x00,
+ 0x8f, 0x16, 0xff, 0xf4, 0xf3, 0x76, 0xff, 0xfc, 0xcf, 0x78, 0x45, 0x00, 0x9f, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x8e, 0x5c, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x84, 0x16, 0xff, 0xf4,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x6f, 0x6e, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x6f, 0x66, 0x66, 0x2c, 0x20, 0x75, 0x6e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x69,
+ 0x6e, 0x67, 0x20, 0x73, 0x74, 0x75, 0x63, 0x6b, 0x20, 0x50, 0x43, 0x49, 0x45, 0x5f, 0x44, 0x4c,
+ 0x4c, 0x5f, 0x42, 0x55, 0x53, 0x59, 0x0a, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x08, 0x90, 0x82, 0xfe, 0x88, 0xf7, 0x82, 0x00, 0x06, 0xf7, 0x83, 0x6a, 0x7a,
+ 0xf7, 0x82, 0x8e, 0xbc, 0xe0, 0x00, 0x7d, 0xc4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xe8,
+ 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x00, 0x8f, 0x18, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xf8,
+ 0x70, 0x7e, 0x00, 0x0e, 0xea, 0x00, 0x8f, 0x24, 0xff, 0x82, 0x8e, 0x6c, 0x22, 0x10, 0x00, 0x04,
+ 0x9f, 0x92, 0x00, 0x00, 0xf7, 0x82, 0x8e, 0xf0, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc,
+ 0x02, 0x10, 0x00, 0x04, 0xf3, 0x02, 0x00, 0x03, 0xf7, 0x82, 0x8f, 0x04, 0xe0, 0x00, 0x2e, 0xc0,
+ 0x97, 0x93, 0xff, 0xfc, 0x74, 0x21, 0x00, 0x02, 0x04, 0x21, 0x90, 0x00, 0x94, 0x02, 0xff, 0x80,
+ 0xe0, 0x00, 0x8f, 0x28, 0xfe, 0x76, 0xff, 0xdc, 0xf7, 0x82, 0x8f, 0x24, 0xe0, 0x00, 0x7e, 0x38,
+ 0x97, 0x93, 0xff, 0xfc, 0xfe, 0x76, 0xff, 0xdc, 0x8f, 0xf2, 0x00, 0x00, 0xfd, 0x76, 0xff, 0xe8,
+ 0xfd, 0xf6, 0xff, 0xec, 0x4f, 0xfd, 0xc0, 0x3f, 0x5f, 0xfd, 0x01, 0x00, 0x9f, 0xf2, 0x00, 0x00,
+ 0x8f, 0x6a, 0x00, 0x00, 0x8f, 0xee, 0x00, 0x00, 0xfc, 0xf6, 0xff, 0xe4, 0x5f, 0x78, 0x00, 0x02,
+ 0x5f, 0xfd, 0x01, 0x00, 0x4f, 0x79, 0xff, 0x07, 0x9f, 0xee, 0x00, 0x00, 0x5f, 0x79, 0x00, 0x40,
+ 0x9f, 0x6a, 0x00, 0x00, 0x8f, 0xe6, 0x00, 0x00, 0x0e, 0x81, 0xc0, 0x00, 0x0e, 0xf4, 0x00, 0x03,
+ 0xcf, 0xfc, 0xec, 0x00, 0x5f, 0xfc, 0x00, 0x20, 0x9f, 0xe6, 0x00, 0x00, 0x9e, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0x8f, 0x8c, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x0f, 0x81, 0x20, 0x00,
+ 0x9f, 0x82, 0xff, 0xf8, 0x8e, 0x16, 0xff, 0xf4, 0xfe, 0xf6, 0xff, 0xd8, 0xf3, 0x76, 0xff, 0xfc,
+ 0x8f, 0x72, 0x00, 0x00, 0x5f, 0x79, 0xc0, 0x00, 0x9f, 0x72, 0x00, 0x00, 0x8f, 0xf6, 0x00, 0x00,
+ 0x5f, 0xfc, 0x00, 0x0f, 0x9f, 0xf6, 0x00, 0x00, 0xf7, 0x82, 0x8f, 0xc4, 0xe0, 0x00, 0x25, 0xb4,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf3, 0x09, 0xce, 0xa8, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x43, 0x61, 0x70, 0x73, 0x20, 0x64, 0x69, 0x66,
+ 0x66, 0x65, 0x72, 0x73, 0x20, 0x61, 0x74, 0x20, 0x30, 0x78, 0x25, 0x78, 0x28, 0x6f, 0x6c, 0x64,
+ 0x3d, 0x30, 0x78, 0x25, 0x78, 0x29, 0x3a, 0x20, 0x6e, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x3d, 0x25,
+ 0x64, 0x2c, 0x20, 0x6f, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x2c, 0xfe, 0x82, 0x00, 0x80,
+ 0x93, 0x16, 0xff, 0xf4, 0x20, 0x1a, 0x00, 0x02, 0xe6, 0x00, 0x94, 0x6d, 0x9e, 0x96, 0xff, 0xf0,
+ 0x20, 0x1a, 0x00, 0x02, 0xe2, 0x00, 0x91, 0x60, 0x20, 0x1a, 0x00, 0x01, 0xe6, 0x00, 0x91, 0x05,
+ 0x03, 0x01, 0xe1, 0x00, 0x03, 0x18, 0x06, 0xae, 0xf7, 0x82, 0x90, 0x64, 0xe0, 0x00, 0x7b, 0xb8,
+ 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x90, 0x70, 0xe0, 0x00, 0x0a, 0xa0, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x06, 0x38, 0x80, 0xf7, 0x82, 0x90, 0x80, 0xe0, 0x00, 0x8f, 0xd0, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0x93, 0xd8, 0x8e, 0x96, 0xff, 0xf4, 0x8f, 0x16, 0xff, 0xf0, 0xfd, 0x82, 0x00, 0x00,
+ 0x5f, 0xfc, 0x00, 0x40, 0xfe, 0x89, 0x9f, 0xf8, 0xc0, 0x6e, 0xf2, 0x00, 0xe4, 0x00, 0x94, 0xd1,
+ 0xff, 0x89, 0x93, 0xd8, 0xff, 0x0a, 0x8f, 0x80, 0x8f, 0xfa, 0x00, 0x0c, 0xf3, 0x02, 0x00, 0x00,
+ 0x74, 0xed, 0x00, 0x02, 0x0d, 0xec, 0x00, 0x01, 0xc0, 0x7e, 0x32, 0x00, 0xe6, 0x00, 0x90, 0xdc,
+ 0xc3, 0x98, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xf0, 0xc0, 0x6e, 0xfa, 0x00, 0xe4, 0x00, 0x90, 0xa8,
+ 0x0f, 0x78, 0x00, 0x10, 0xe0, 0x00, 0x94, 0xd4, 0xf0, 0x09, 0x9f, 0xf8, 0x84, 0x7a, 0x00, 0x08,
+ 0x9d, 0x96, 0xff, 0xe4, 0x9f, 0x16, 0xff, 0xe0, 0xf7, 0x82, 0x90, 0xf4, 0xc1, 0x7c, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xe0, 0x8d, 0x96, 0xff, 0xe4, 0xe0, 0x00, 0x90, 0xc4,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa0, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x89, 0xa0, 0x04,
+ 0xf7, 0x82, 0x91, 0x1c, 0xe0, 0x00, 0x0a, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x8a, 0x90, 0xf7,
+ 0x27, 0x80, 0x00, 0x78, 0xf7, 0xff, 0x68, 0x03, 0xff, 0x88, 0x90, 0xf8, 0xfe, 0x82, 0x00, 0x08,
+ 0xff, 0x0a, 0x90, 0x38, 0x4f, 0xfd, 0xff, 0xf0, 0xfe, 0xfb, 0x28, 0x00, 0x5f, 0xfd, 0x00, 0x01,
+ 0xff, 0x89, 0x90, 0xf8, 0xff, 0x0a, 0x92, 0x07, 0xf0, 0x7b, 0x68, 0x03, 0xff, 0x8a, 0x8f, 0x88,
+ 0xfe, 0xff, 0x28, 0x00, 0x8f, 0x96, 0xff, 0xf4, 0xe0, 0x00, 0x90, 0x64, 0xff, 0x89, 0xa8, 0x60,
+ 0x8f, 0x16, 0xff, 0xf4, 0x20, 0x7a, 0x00, 0x03, 0xe6, 0x00, 0x90, 0x54, 0x03, 0x01, 0xe1, 0x00,
+ 0xff, 0x88, 0xa0, 0x0c, 0xff, 0x02, 0x00, 0x08, 0xff, 0x09, 0xce, 0x80, 0x0f, 0xfc, 0x00, 0x01,
+ 0xff, 0x89, 0xa0, 0x0c, 0xff, 0x82, 0x00, 0x01, 0xf0, 0x09, 0xa5, 0x3c, 0xf0, 0x09, 0xa5, 0x40,
+ 0xff, 0x89, 0x9f, 0xf0, 0xfe, 0xf6, 0xed, 0xa0, 0x8f, 0x76, 0x00, 0x08, 0xfe, 0x76, 0xff, 0xf0,
+ 0xf3, 0x76, 0xff, 0xfc, 0xff, 0x09, 0x9f, 0xf4, 0x8f, 0xf2, 0x00, 0x00, 0x0e, 0x81, 0xe0, 0x00,
+ 0x0e, 0xf4, 0x1f, 0xff, 0x5f, 0xfc, 0x10, 0x00, 0x7f, 0x79, 0x00, 0x0d, 0xcf, 0xfc, 0xec, 0x00,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x9f, 0xf2, 0x00, 0x00, 0xf7, 0x82, 0x91, 0xd4, 0xe0, 0x00, 0x25, 0xb4,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x76, 0xed, 0xa0, 0x8f, 0xfa, 0x00, 0x0c, 0x20, 0x7e, 0x00, 0x80,
+ 0xe4, 0x00, 0x91, 0xed, 0x00, 0x00, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xf0, 0xfd, 0x82, 0x00, 0x00,
+ 0xfa, 0x0a, 0x8f, 0x80, 0xff, 0x0a, 0x8f, 0x88, 0xff, 0xf6, 0xed, 0xb0, 0x20, 0x6e, 0x00, 0x0d,
+ 0xe6, 0x00, 0x92, 0x11, 0x0d, 0xec, 0x00, 0x01, 0x8e, 0xfe, 0x00, 0x00, 0x9e, 0xfa, 0x00, 0x00,
+ 0x20, 0x6e, 0x00, 0x0f, 0x0f, 0xfc, 0x00, 0x04, 0xe2, 0x00, 0x91, 0xfd, 0x0f, 0x78, 0x00, 0x10,
+ 0xfe, 0xf6, 0xed, 0xa0, 0xff, 0x88, 0x90, 0x58, 0xfc, 0xf7, 0x58, 0x47, 0xff, 0x02, 0x00, 0x40,
+ 0x7f, 0xfd, 0x00, 0x18, 0x7d, 0x7c, 0xff, 0xe8, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x00, 0x93, 0x81,
+ 0x9f, 0x16, 0xff, 0xec, 0x20, 0x6a, 0x00, 0x00, 0xe6, 0x00, 0x93, 0x81, 0x7f, 0x64, 0xff, 0xfe,
+ 0x8f, 0x96, 0xff, 0xf0, 0xc0, 0x7a, 0xfa, 0x00, 0xe4, 0x00, 0x93, 0x81, 0x7d, 0xe8, 0xff, 0xfe,
+ 0xf9, 0x82, 0x00, 0xff, 0xc8, 0xf4, 0x00, 0x00, 0xf9, 0x02, 0x00, 0xfc, 0xf8, 0x02, 0x01, 0x00,
+ 0x7f, 0x79, 0x00, 0x02, 0x7f, 0xed, 0x00, 0x04, 0xcf, 0xfc, 0xa0, 0x00, 0xcf, 0x78, 0x88, 0x00,
+ 0x8e, 0xfe, 0x00, 0x08, 0x8e, 0x7a, 0x00, 0x10, 0x7f, 0xf4, 0xff, 0xf8, 0x7f, 0x70, 0xff, 0xf8,
+ 0xce, 0xf4, 0x9c, 0x00, 0xce, 0x70, 0x9c, 0x00, 0xca, 0xfc, 0x94, 0x00, 0xc0, 0x76, 0xe2, 0x00,
+ 0xe6, 0x00, 0x94, 0x34, 0xcb, 0x78, 0x94, 0x00, 0x20, 0x76, 0x00, 0x09, 0xe6, 0x00, 0x93, 0xf5,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x00, 0x92, 0xc0, 0xcb, 0xd4, 0xd2, 0x00, 0xcb, 0xc0, 0xd2, 0x00,
+ 0x20, 0x5a, 0x00, 0x00, 0xe6, 0x00, 0x92, 0xd0, 0xcc, 0x58, 0xca, 0x00, 0xcc, 0x40, 0xca, 0x00,
+ 0x7f, 0xe4, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x02, 0x7e, 0x6d, 0x00, 0x04, 0xcf, 0xfc, 0x88, 0x00,
+ 0xce, 0x70, 0xa0, 0x00, 0x8f, 0x7e, 0x00, 0x10, 0xfe, 0xf3, 0x18, 0x0a, 0xfd, 0x82, 0x00, 0x04,
+ 0x4f, 0x78, 0x00, 0x00, 0xce, 0xf4, 0xf0, 0x00, 0xc0, 0x6e, 0xba, 0x00, 0xe4, 0x00, 0x93, 0x51,
+ 0x9e, 0xf2, 0x00, 0x08, 0xc0, 0x6e, 0xc2, 0x00, 0xe4, 0x00, 0x93, 0x51, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0xf6, 0xed, 0xa0, 0xcf, 0x64, 0xd8, 0x00, 0x4f, 0x78, 0xff, 0xfc, 0xcf, 0xe8, 0xd8, 0x00,
+ 0xcf, 0x78, 0xe8, 0x00, 0x7f, 0xfc, 0xff, 0xfe, 0x8f, 0x7a, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x04,
+ 0xcf, 0xfc, 0xa0, 0x00, 0x0d, 0xec, 0x00, 0x04, 0xc0, 0x6e, 0xba, 0x00, 0xe4, 0x00, 0x93, 0x51,
+ 0x9f, 0x7e, 0x00, 0x08, 0xc0, 0x6e, 0xc2, 0x00, 0xe4, 0x00, 0x93, 0x14, 0x00, 0x00, 0x00, 0x01,
+ 0x9d, 0x16, 0xff, 0xec, 0x20, 0x5a, 0x00, 0x00, 0xcd, 0x54, 0x00, 0x00, 0xe6, 0x00, 0x93, 0x81,
+ 0xcc, 0xd8, 0x00, 0x00, 0x20, 0x56, 0x00, 0x00, 0xe6, 0x00, 0x93, 0x81, 0x7f, 0x58, 0xff, 0xfe,
+ 0x8f, 0x96, 0xff, 0xf0, 0xc0, 0x7a, 0xfa, 0x00, 0xe4, 0x00, 0x92, 0x70, 0x7d, 0xe8, 0xff, 0xfe,
+ 0x8e, 0x96, 0xff, 0xec, 0xfe, 0x76, 0xed, 0xa0, 0xfd, 0x82, 0x00, 0x40, 0x7f, 0xf4, 0xff, 0xfe,
+ 0x7f, 0xfd, 0x00, 0x04, 0xcf, 0xfc, 0xa0, 0x00, 0x8f, 0x7e, 0x00, 0x08, 0x4f, 0x78, 0x00, 0xff,
+ 0x9f, 0x7e, 0x00, 0x08, 0x8e, 0xf2, 0x00, 0x0c, 0xc0, 0x6e, 0xea, 0x00, 0xe4, 0x00, 0x93, 0xd5,
+ 0x0f, 0x50, 0x04, 0x08, 0xfe, 0xf6, 0xee, 0xb0, 0x8f, 0xf5, 0x00, 0x04, 0x0d, 0xec, 0x00, 0x01,
+ 0x9f, 0xfa, 0x00, 0x00, 0x8f, 0xf2, 0x00, 0x0c, 0xc0, 0x6e, 0xfa, 0x00, 0xe4, 0x00, 0x93, 0xb8,
+ 0x0f, 0x78, 0x00, 0x10, 0xf3, 0x0a, 0x9f, 0xc0, 0xf3, 0x82, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x10,
+ 0xf7, 0x82, 0x93, 0xec, 0xe0, 0x02, 0x89, 0x20, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x90, 0x64,
+ 0x00, 0x00, 0x00, 0x01, 0x20, 0x66, 0x00, 0x88, 0xe6, 0x00, 0x93, 0x50, 0x20, 0x6a, 0x00, 0xa0,
+ 0xe6, 0x00, 0x93, 0x50, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x90, 0xf8, 0x7f, 0xfd, 0x00, 0x10,
+ 0x7f, 0xfc, 0xff, 0xe8, 0x20, 0x7e, 0x00, 0xa0, 0xe6, 0x00, 0x93, 0x50, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8a, 0x90, 0xf7, 0xfc, 0xff, 0x68, 0x03, 0xfe, 0x82, 0x00, 0x01, 0xe0, 0x00, 0x93, 0x50,
+ 0xfe, 0x89, 0xa8, 0x60, 0x22, 0x10, 0x00, 0x14, 0x9e, 0x92, 0x00, 0x0c, 0xfe, 0x82, 0x8f, 0xe8,
+ 0x9d, 0x12, 0x00, 0x04, 0x9c, 0x92, 0x00, 0x08, 0x9e, 0x12, 0x00, 0x10, 0x9e, 0x92, 0x00, 0x00,
+ 0x9a, 0x16, 0xff, 0xe8, 0xf7, 0x82, 0x94, 0x60, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8a, 0x16, 0xff, 0xe8, 0xe0, 0x00, 0x93, 0x80, 0x02, 0x10, 0x00, 0x14, 0xff, 0x88, 0xa0, 0x08,
+ 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x89, 0xa0, 0x08, 0xf7, 0x82, 0x94, 0x84, 0xe0, 0x00, 0x0d, 0x18,
+ 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x82, 0x94, 0x90, 0xe0, 0x00, 0x0a, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0xfe, 0xf6, 0xff, 0xf0, 0xf0, 0x09, 0xa5, 0x3c, 0xf0, 0x09, 0xa5, 0x40, 0xf0, 0x09, 0x9f, 0xf0,
+ 0xf0, 0x09, 0x9f, 0xf4, 0x8f, 0x76, 0x00, 0x00, 0x0f, 0x81, 0xe0, 0x00, 0x0f, 0xfc, 0x0f, 0xff,
+ 0xcf, 0x78, 0xfc, 0x00, 0x9f, 0x76, 0x00, 0x00, 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x82, 0x94, 0xc8,
+ 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x90, 0x64, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x09, 0x9f, 0xf8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x76, 0xff, 0xcc, 0xff, 0x9b, 0x58, 0x00,
+ 0x8e, 0xea, 0x00, 0x00, 0x0c, 0x81, 0xff, 0xf0, 0x0c, 0xe4, 0x0f, 0xff, 0x7f, 0xfd, 0x00, 0x0c,
+ 0xce, 0xf4, 0xcc, 0x00, 0xce, 0xf4, 0xfd, 0x00, 0x9e, 0xea, 0x00, 0x00, 0xff, 0x9b, 0x58, 0x01,
+ 0x4e, 0xf4, 0xf0, 0x0f, 0xfd, 0xf6, 0xff, 0xd0, 0x7f, 0xfd, 0x00, 0x04, 0xce, 0xf4, 0xfd, 0x00,
+ 0x9e, 0xea, 0x00, 0x00, 0xff, 0x9b, 0x58, 0x02, 0x8f, 0x6e, 0x00, 0x00, 0x4e, 0xf4, 0xff, 0xf0,
+ 0x7f, 0xfd, 0x00, 0x1c, 0x4f, 0x79, 0x0f, 0xff, 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x6e, 0x00, 0x00,
+ 0xff, 0x9b, 0x58, 0x02, 0xce, 0x18, 0x00, 0x00, 0x4f, 0x79, 0xf0, 0x0f, 0x7f, 0xfc, 0xff, 0xfc,
+ 0xce, 0xf4, 0xfd, 0x00, 0x9e, 0xea, 0x00, 0x00, 0xff, 0xf3, 0x58, 0x03, 0xf3, 0x76, 0xff, 0xfc,
+ 0x7f, 0xfd, 0x00, 0x14, 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x6e, 0x00, 0x00, 0xff, 0xf3, 0x58, 0x04,
+ 0xcf, 0x78, 0xcc, 0x00, 0x7f, 0xfd, 0x00, 0x0c, 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x6e, 0x00, 0x00,
+ 0xff, 0xf3, 0x58, 0x05, 0x4f, 0x78, 0xf0, 0x0f, 0x7f, 0xfd, 0x00, 0x04, 0xcf, 0x78, 0xfd, 0x00,
+ 0x9f, 0x6e, 0x00, 0x00, 0xf7, 0x82, 0x95, 0xa0, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xd3, 0xd8, 0xc0, 0x7e, 0x5a, 0x00, 0xe6, 0x00, 0x96, 0x64,
+ 0xfd, 0x82, 0x00, 0x00, 0xfd, 0x08, 0xa0, 0x80, 0x20, 0x6a, 0x01, 0x00, 0xe2, 0x00, 0x95, 0xdd,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x01, 0x00, 0xfd, 0x09, 0xa0, 0x80, 0x2f, 0xe8, 0x00, 0x01,
+ 0x7e, 0xfc, 0xff, 0xfe, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0x95, 0xfd, 0xcf, 0xf4, 0x00, 0x00,
+ 0x7f, 0xfe, 0xff, 0xff, 0xe6, 0x00, 0x95, 0xf0, 0x0d, 0xec, 0x00, 0x01, 0x0f, 0xec, 0x00, 0x02,
+ 0xff, 0x89, 0xa0, 0x84, 0xff, 0x02, 0x00, 0x00, 0xfe, 0x0a, 0xcf, 0xd0, 0xcf, 0xf8, 0xe8, 0x00,
+ 0xcc, 0x80, 0xda, 0x00, 0xcc, 0xfc, 0xcf, 0x80, 0xbc, 0xf2, 0xf0, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0x20, 0x7a, 0x04, 0x00, 0xe2, 0x00, 0x96, 0x11, 0xcf, 0xf8, 0xe8, 0x00, 0x7f, 0xe8, 0xff, 0xfe,
+ 0x5f, 0xfd, 0xa0, 0x00, 0x9f, 0x82, 0xff, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xce, 0xc0,
+ 0x4f, 0xfc, 0xff, 0xdf, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x96, 0x64, 0xff, 0x89, 0xce, 0xc0,
+ 0x45, 0x29, 0x7f, 0xff, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xd3, 0xd8, 0xc0, 0x7e, 0x5a, 0x00,
+ 0xe6, 0x00, 0x96, 0xbc, 0xff, 0x8a, 0x9f, 0xf6, 0xff, 0xff, 0x18, 0x00, 0xfe, 0x8a, 0xad, 0xd0,
+ 0xff, 0x02, 0x00, 0x7f, 0xff, 0xf7, 0x28, 0x00, 0x2f, 0x7a, 0x00, 0x01, 0xea, 0x00, 0x96, 0x94,
+ 0x0e, 0xf4, 0x00, 0x40, 0xff, 0x88, 0xce, 0xc0, 0x4f, 0xfc, 0xff, 0xef, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0x96, 0xbc, 0xff, 0x89, 0xce, 0xc0, 0x45, 0x29, 0x7f, 0xff, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x04, 0xcc, 0x98, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0xfe, 0x0a, 0xad, 0xc0,
+ 0xfd, 0x8a, 0x9f, 0xf6, 0xfd, 0x0a, 0xae, 0x00, 0x20, 0x7a, 0x00, 0x7f, 0x7f, 0xf9, 0x00, 0x06,
+ 0xe6, 0x00, 0x98, 0x09, 0xfe, 0x8a, 0xad, 0xc0, 0xce, 0xfc, 0xd0, 0x00, 0xcf, 0xfc, 0xe0, 0x00,
+ 0x9e, 0xfe, 0x00, 0x2c, 0xfe, 0xef, 0x18, 0x00, 0x0f, 0x78, 0x00, 0x01, 0x20, 0x7a, 0x00, 0x7f,
+ 0xee, 0x00, 0x96, 0xed, 0xfe, 0xff, 0x28, 0x10, 0xff, 0x83, 0x1a, 0x60, 0xff, 0x02, 0x00, 0x7f,
+ 0x20, 0x66, 0x00, 0x00, 0xcf, 0xfc, 0xf4, 0x00, 0x7e, 0xfd, 0x00, 0x06, 0xcf, 0x74, 0xe0, 0x00,
+ 0xff, 0x09, 0xd3, 0xd8, 0xe6, 0x00, 0x97, 0xfd, 0xc5, 0xf8, 0x00, 0x00, 0xff, 0xf6, 0xed, 0xa0,
+ 0xfd, 0xff, 0x18, 0x02, 0xbd, 0xf6, 0xe0, 0x00, 0x8f, 0xfe, 0x00, 0x00, 0x9f, 0xfa, 0x00, 0x08,
+ 0xff, 0x83, 0x1b, 0x9a, 0x0e, 0x81, 0x00, 0x3f, 0xff, 0x02, 0x0f, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0xfe, 0x89, 0xcd, 0xd8, 0xff, 0x89, 0xe6, 0x20, 0xff, 0x02, 0x00, 0x00, 0xfe, 0x8a, 0xa0, 0x14,
+ 0x7f, 0xf9, 0x00, 0x02, 0x0f, 0x78, 0x00, 0x01, 0x20, 0x7a, 0x00, 0x03, 0xee, 0x00, 0x97, 0x71,
+ 0xb0, 0x7e, 0xe8, 0x02, 0xff, 0x08, 0x9f, 0xe4, 0x9c, 0x96, 0xff, 0xf4, 0xf0, 0x09, 0xcf, 0xb0,
+ 0xf0, 0x09, 0xce, 0xa0, 0xff, 0x09, 0xa0, 0x80, 0xf7, 0x82, 0x97, 0xa4, 0xe0, 0x00, 0x95, 0xac,
+ 0x97, 0x93, 0xff, 0xfc, 0x8c, 0x96, 0xff, 0xf4, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x00, 0x98, 0x11,
+ 0xf0, 0x09, 0xa9, 0xa8, 0xff, 0x02, 0x00, 0x00, 0xfd, 0x82, 0x00, 0x01, 0xfe, 0x76, 0xfd, 0xb0,
+ 0x8f, 0xf1, 0x00, 0x04, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x97, 0xf1, 0xce, 0xec, 0xf7, 0xc0,
+ 0xff, 0x88, 0xa9, 0xa8, 0xcf, 0xfc, 0xed, 0x00, 0x0f, 0x78, 0x00, 0x01, 0x20, 0x7a, 0x00, 0x0f,
+ 0xee, 0x00, 0x97, 0xc1, 0xff, 0x89, 0xa9, 0xa8, 0xe0, 0x00, 0x98, 0x10, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xa9, 0xa8, 0xe0, 0x00, 0x97, 0xdc, 0x0f, 0x78, 0x00, 0x01, 0xfc, 0xfb, 0x28, 0x00,
+ 0xe0, 0x00, 0x97, 0x50, 0x9c, 0xfa, 0x00, 0x08, 0xe0, 0x00, 0x96, 0xfc, 0xff, 0x82, 0x1f, 0xc0,
+ 0xf3, 0x08, 0xa9, 0xa8, 0x53, 0x18, 0x80, 0x00, 0xf7, 0x82, 0x98, 0x24, 0xe0, 0x01, 0xa6, 0xd0,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x9b, 0x18, 0x0a, 0xcf, 0x9c, 0xfa, 0x00, 0x70, 0x7e, 0x00, 0x14,
+ 0xea, 0x00, 0x9a, 0x95, 0xfa, 0x82, 0x00, 0x02, 0xfb, 0x02, 0x00, 0x01, 0xfa, 0x02, 0x00, 0x10,
+ 0xff, 0x9b, 0x58, 0x0c, 0x8e, 0x1a, 0x00, 0x30, 0x70, 0x7e, 0x00, 0x1a, 0xea, 0x00, 0x98, 0x79,
+ 0xfc, 0x02, 0x00, 0x14, 0xfc, 0x02, 0x00, 0x10, 0xf0, 0x1b, 0x68, 0x09, 0xff, 0x82, 0x00, 0x40,
+ 0xf0, 0x03, 0x2a, 0x60, 0xcd, 0xf2, 0xfc, 0x00, 0xe6, 0x00, 0x98, 0xd9, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x9a, 0x00, 0x24, 0xfe, 0x9b, 0x18, 0x0a, 0xfe, 0xff, 0x28, 0x02, 0x8f, 0x1a, 0x00, 0x24,
+ 0x9f, 0x02, 0xfe, 0x58, 0x8f, 0x9a, 0x00, 0x28, 0x5f, 0xfd, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x83, 0x1a, 0x00, 0x2c, 0xff, 0x9b, 0x18, 0x0a,
+ 0xcf, 0x9c, 0xfa, 0x00, 0x70, 0x7e, 0x00, 0x14, 0xea, 0x00, 0x98, 0x60, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0x9a, 0x94, 0x00, 0x00, 0x00, 0x01, 0x77, 0xf0, 0x00, 0x1e, 0x70, 0x3e, 0xff, 0xe2,
+ 0xe6, 0x00, 0x99, 0x54, 0xff, 0x82, 0x03, 0xff, 0xff, 0x1b, 0x18, 0x02, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0x99, 0x3d, 0x0f, 0x98, 0x00, 0x08, 0xff, 0x88, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0xff, 0xff, 0x18, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x01,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xa5, 0x10, 0xff, 0xfb, 0x28, 0x02, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0x01, 0x10, 0x00, 0x0f, 0x78, 0x00, 0x10, 0x9f, 0x02, 0xfe, 0x58, 0x8f, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x83, 0x2a, 0x60, 0x0f, 0x98, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5f, 0x61, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x9d, 0x82, 0xfe, 0x80, 0xe0, 0x00, 0x98, 0xb4,
+ 0x00, 0x00, 0x00, 0x01, 0x8c, 0x9a, 0x00, 0x0c, 0x8b, 0x9a, 0x00, 0x10, 0xcd, 0x66, 0xfc, 0x00,
+ 0xe6, 0x00, 0x99, 0x6c, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x04, 0x00, 0xff, 0x9b, 0x18, 0x0a,
+ 0xfe, 0x88, 0xa0, 0x84, 0xff, 0x02, 0x0f, 0xff, 0xcf, 0x9c, 0xfa, 0x00, 0x0f, 0xfc, 0x00, 0x01,
+ 0xcf, 0xfc, 0xf4, 0x00, 0xce, 0xfc, 0xef, 0xc0, 0x7f, 0x74, 0xff, 0xfe, 0xc0, 0x6a, 0xf2, 0x00,
+ 0xe2, 0x00, 0x99, 0xad, 0xc0, 0x72, 0xac, 0x00, 0x4f, 0xe4, 0xfc, 0x00, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x5f, 0x5c, 0x00, 0xf0, 0x9f, 0x9a, 0x00, 0x0c, 0x9f, 0x1a, 0x00, 0x10, 0xe6, 0x00, 0x99, 0xb9,
+ 0xcf, 0x6c, 0x00, 0x00, 0xff, 0x1b, 0x18, 0x22, 0xc0, 0x72, 0xb4, 0x00, 0xe6, 0x00, 0x99, 0xcd,
+ 0xc0, 0x6e, 0xea, 0x00, 0x8d, 0x9a, 0x00, 0x28, 0xc0, 0x6e, 0xea, 0x00, 0xe4, 0x00, 0x9a, 0x80,
+ 0xcf, 0xf8, 0xd8, 0x00, 0xcd, 0xf4, 0x00, 0x00, 0x4e, 0x70, 0xff, 0xfd, 0xc0, 0x72, 0xac, 0x00,
+ 0xe6, 0x00, 0x9a, 0x05, 0x0f, 0x98, 0x00, 0x08, 0xff, 0x9b, 0x18, 0x20, 0x5f, 0xfd, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9f, 0x02, 0xfe, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x0f, 0x98, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0xcf, 0xf2, 0xb4, 0x00, 0xe6, 0x00, 0x9a, 0x18,
+ 0xcf, 0x60, 0x00, 0x00, 0x5f, 0x61, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x90, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x9a, 0x55, 0xc0, 0x72, 0xa4, 0x00,
+ 0x8f, 0x9a, 0x00, 0x24, 0x9f, 0x82, 0xfe, 0x58, 0xe6, 0x00, 0x9a, 0x44, 0xcf, 0xec, 0x00, 0x00,
+ 0x5f, 0xed, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xc0, 0x72, 0xa4, 0x00, 0xe6, 0x00, 0x9a, 0x75, 0x0f, 0x98, 0x00, 0x37, 0x0e, 0x81, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0xf4, 0x00, 0x01, 0x9e, 0x82, 0xfe, 0x58, 0x90, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x9c, 0x9a, 0x00, 0x0c, 0xe0, 0x00, 0x98, 0xb8, 0x9b, 0x9a, 0x00, 0x10,
+ 0xc0, 0x7e, 0xea, 0x00, 0xe2, 0x00, 0x99, 0xe1, 0xc0, 0x72, 0xac, 0x00, 0xe0, 0x00, 0x99, 0xe0,
+ 0xcf, 0x74, 0xda, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xce, 0xc0, 0xff, 0x02, 0x00, 0x81,
+ 0xce, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0x9a, 0xd1, 0x4e, 0xfc, 0xfe, 0xff, 0x20, 0x76, 0x00, 0x00,
+ 0xe6, 0x00, 0x9b, 0x84, 0xfe, 0x89, 0xce, 0xc0, 0xe0, 0x00, 0x9b, 0x84, 0x45, 0x29, 0x7f, 0xff,
+ 0xff, 0x88, 0xd3, 0xd8, 0xc0, 0x2e, 0xfa, 0x00, 0xe6, 0x00, 0x9b, 0x85, 0x0f, 0x01, 0x80, 0x00,
+ 0xff, 0xff, 0x18, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xff, 0x02, 0x00, 0x40, 0x9f, 0x02, 0xfe, 0x58,
+ 0x0f, 0xfc, 0x00, 0x01, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0x0a, 0xa5, 0x10, 0xff, 0xfb, 0x28, 0x02,
+ 0x0f, 0x81, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58,
+ 0x8f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x08, 0xd3, 0xd8, 0xfe, 0x03, 0x2a, 0x60,
+ 0x20, 0x1a, 0x00, 0x00, 0xff, 0xfb, 0x18, 0x00, 0x5f, 0xfd, 0x10, 0x00, 0x9f, 0x82, 0xff, 0x90,
+ 0xe6, 0x00, 0x9b, 0x75, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa0, 0x50, 0x0f, 0xfc, 0x00, 0x01,
+ 0xff, 0x89, 0xa0, 0x50, 0xf3, 0x09, 0xa0, 0x8c, 0xff, 0x7b, 0x18, 0x00, 0xff, 0x88, 0xce, 0xc0,
+ 0x55, 0x29, 0x80, 0x00, 0xff, 0x09, 0xa0, 0x88, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x02, 0x00, 0x28,
+ 0xff, 0x89, 0xce, 0xc0, 0x9f, 0x02, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x9b, 0x84,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa0, 0x4c, 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x00, 0x9b, 0x44,
+ 0xff, 0x89, 0xa0, 0x4c, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x03, 0x1a, 0x60, 0xff, 0x82, 0x00, 0x7f,
+ 0xfe, 0x88, 0xd3, 0xd8, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x8a, 0xad, 0xc0, 0x7f, 0x79, 0x00, 0x06,
+ 0xcf, 0xf4, 0xfa, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x00, 0x9c, 0x01, 0xf3, 0x02, 0x00, 0x06,
+ 0xff, 0xf7, 0x18, 0x00, 0x5f, 0xfd, 0x10, 0x00, 0x9f, 0x82, 0xff, 0x90, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0x9b, 0xcc, 0x00, 0x00, 0x00, 0x01,
+ 0xf7, 0x82, 0x9c, 0x0c, 0xe0, 0x00, 0x2e, 0xc0, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x08, 0xce, 0xc0,
+ 0xff, 0x82, 0x0f, 0xff, 0xc4, 0x20, 0xfc, 0x00, 0x4f, 0x78, 0xff, 0xfe, 0xf4, 0x09, 0xd3, 0xe0,
+ 0xf0, 0x09, 0xe6, 0x10, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0x9c, 0x34, 0xff, 0x09, 0xce, 0xc0,
+ 0x45, 0x29, 0x7f, 0xff, 0x5f, 0xf8, 0x00, 0x80, 0xf3, 0x02, 0x00, 0x01, 0xff, 0x89, 0xce, 0xc0,
+ 0xc3, 0x98, 0x00, 0x00, 0x55, 0x29, 0x80, 0x00, 0xf7, 0x82, 0x9c, 0x54, 0xe0, 0x00, 0x7d, 0x14,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x9b, 0xcc, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x08, 0xff, 0x03, 0x1a, 0x60, 0xff, 0x82, 0x00, 0x7f, 0xfe, 0x8a, 0xad, 0xc0,
+ 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x88, 0xd3, 0xd8, 0x7f, 0x79, 0x00, 0x06, 0xcf, 0xfc, 0xea, 0x00,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x00, 0x9c, 0xd1, 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0x9c, 0x9c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xd3, 0xe0, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x00, 0x9e, 0x69, 0xf3, 0x02, 0x00, 0x01,
+ 0xff, 0x88, 0xce, 0xc0, 0x70, 0x7e, 0x00, 0x17, 0xea, 0x00, 0x9d, 0x24, 0xff, 0x06, 0x86, 0xa0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0x9c, 0xf0,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xe6, 0x10, 0x95, 0x96, 0xff, 0xf4, 0x0f, 0xfc, 0x00, 0x01,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0x9e, 0x51, 0xff, 0x89, 0xe6, 0x10, 0x8f, 0x16, 0xff, 0xf4,
+ 0xf3, 0x88, 0xd3, 0xe0, 0xff, 0xfb, 0x18, 0x0a, 0xcf, 0x9c, 0xfa, 0x00, 0x70, 0x7e, 0x00, 0x14,
+ 0xea, 0x00, 0x9d, 0xd4, 0xff, 0x8a, 0xad, 0xc0, 0x2e, 0xac, 0x00, 0x40, 0xc0, 0x2e, 0xfa, 0x00,
+ 0xe6, 0x00, 0x9d, 0xc9, 0x9e, 0x96, 0xff, 0xf4, 0x83, 0x16, 0xff, 0xf4, 0xf7, 0x82, 0x9d, 0x78,
+ 0xe0, 0x00, 0x98, 0x3c, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xce, 0xc0, 0x55, 0x29, 0x80, 0x00,
+ 0x5f, 0xfc, 0x01, 0x00, 0xff, 0x89, 0xce, 0xc0, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x00, 0x9d, 0x94, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0a, 0xcd, 0x80, 0xe0, 0x00, 0x9d, 0x68,
+ 0x9f, 0x16, 0xff, 0xf4, 0xff, 0x88, 0xe6, 0x10, 0x77, 0xfc, 0x00, 0x1e, 0x70, 0x3e, 0xff, 0xe2,
+ 0xe6, 0x00, 0x9d, 0x68, 0xff, 0xf6, 0xff, 0xe8, 0x8f, 0x7e, 0x00, 0x00, 0xf3, 0x76, 0xff, 0xfc,
+ 0x5f, 0x79, 0x10, 0x00, 0x9f, 0x7e, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xf0, 0xf7, 0x82, 0x9e, 0x08,
+ 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf0, 0x8e, 0x82, 0xff, 0xc8,
+ 0x8f, 0x7e, 0x00, 0x00, 0x4f, 0x79, 0xef, 0xff, 0x9f, 0x7e, 0x00, 0x00, 0x8f, 0x82, 0xff, 0xc8,
+ 0xcf, 0xfc, 0xea, 0x00, 0x20, 0x7e, 0x03, 0xe7, 0xe2, 0x00, 0x9e, 0x1d, 0xf3, 0x02, 0x00, 0x00,
+ 0xf3, 0x82, 0x00, 0x28, 0xc4, 0x18, 0x00, 0x00, 0xf7, 0x82, 0x9e, 0x44, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x88, 0xd3, 0xe0, 0xe0, 0x00, 0x9d, 0x68, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x02, 0x00, 0x04, 0xf7, 0x82, 0x9e, 0x60, 0xe0, 0x00, 0x7b, 0x5c, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0x9d, 0x3c, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x00, 0xf7, 0x82, 0x9e, 0x78,
+ 0xe0, 0x00, 0x7d, 0x14, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x06, 0xc0, 0x22, 0xfc, 0x00,
+ 0xe6, 0x00, 0x9c, 0xe1, 0xc3, 0x2c, 0x00, 0x00, 0xff, 0x88, 0xd3, 0xd8, 0xf3, 0xff, 0x18, 0x0a,
+ 0x23, 0x9c, 0x00, 0x01, 0xf7, 0x82, 0x9e, 0xa0, 0xe0, 0x00, 0x98, 0x3c, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xce, 0xc0, 0x4f, 0xfc, 0xfe, 0x7f, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0x9d, 0x88,
+ 0xff, 0x89, 0xce, 0xc0, 0xe0, 0x00, 0x9d, 0x88, 0x45, 0x29, 0x7f, 0xff, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0xd3, 0xd8, 0xc0, 0x7e, 0x5a, 0x00, 0xe6, 0x00, 0x9e, 0xf5, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xce, 0xc0, 0x55, 0x29, 0x80, 0x00, 0x5f, 0xfc, 0x10, 0x00, 0xe0, 0x00, 0xa1, 0xc0,
+ 0xff, 0x89, 0xce, 0xc0, 0xff, 0x88, 0x90, 0x98, 0x7f, 0xfd, 0x00, 0x0f, 0x7b, 0x7e, 0xff, 0xe1,
+ 0xe6, 0x00, 0x9f, 0xb5, 0xff, 0x8a, 0x9f, 0xfe, 0xfc, 0x88, 0x90, 0xb8, 0xfd, 0x7f, 0x18, 0x00,
+ 0x20, 0x66, 0x00, 0x00, 0xfe, 0x88, 0x90, 0xc8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0x70, 0x00, 0x02,
+ 0xff, 0x8a, 0xa9, 0x70, 0x7f, 0x79, 0x00, 0x0d, 0xff, 0x7f, 0x28, 0x10, 0xff, 0x0a, 0x9f, 0xf6,
+ 0xff, 0x7b, 0x18, 0x00, 0x7d, 0x69, 0x00, 0x0f, 0x5d, 0x68, 0x00, 0x01, 0xff, 0x7f, 0x28, 0x14,
+ 0xff, 0x02, 0x40, 0x00, 0xff, 0x7f, 0x28, 0x0c, 0xff, 0x02, 0x00, 0x0f, 0xfd, 0x7f, 0x28, 0x12,
+ 0xff, 0x7f, 0x28, 0x16, 0x7e, 0xf5, 0x00, 0x10, 0xff, 0x08, 0x90, 0xa8, 0x7e, 0xf4, 0xff, 0xf0,
+ 0xfd, 0x82, 0xff, 0x00, 0xcd, 0xf4, 0xdc, 0x00, 0x7e, 0x71, 0x00, 0x02, 0xcf, 0xf0, 0xf8, 0x00,
+ 0x7d, 0xed, 0x00, 0x08, 0x7e, 0xf5, 0x00, 0x18, 0xfc, 0x89, 0xa9, 0x88, 0xce, 0xf4, 0xdd, 0x00,
+ 0x4f, 0x78, 0xff, 0xfc, 0x0e, 0x70, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x1c, 0x9f, 0x7e, 0x00, 0x18,
+ 0xfe, 0x09, 0xa9, 0x70, 0xf0, 0x09, 0xa9, 0x74, 0xff, 0x88, 0xce, 0xc0, 0x4f, 0xfc, 0xef, 0xff,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa1, 0xc0, 0xff, 0x89, 0xce, 0xc0, 0xe0, 0x00, 0xa1, 0xc0,
+ 0x45, 0x29, 0x7f, 0xff, 0xff, 0x88, 0x92, 0xc8, 0x7e, 0x7e, 0xff, 0xe1, 0xe6, 0x00, 0xa1, 0x59,
+ 0xfc, 0x82, 0xff, 0x00, 0xfe, 0x88, 0x97, 0xc4, 0xfd, 0x88, 0x97, 0xc0, 0x7f, 0x74, 0xff, 0xf8,
+ 0xcf, 0x78, 0xcc, 0x00, 0x7e, 0x74, 0xff, 0xe8, 0xcf, 0xf4, 0xcc, 0x00, 0xce, 0x70, 0xf5, 0x00,
+ 0x7f, 0xfd, 0x00, 0x08, 0xce, 0x70, 0xfd, 0x00, 0xff, 0x8a, 0x9f, 0xfe, 0xfd, 0x7f, 0x18, 0x00,
+ 0x7e, 0xf5, 0x00, 0x18, 0xcb, 0xf2, 0xed, 0x00, 0xff, 0x8a, 0x9f, 0xf6, 0xfc, 0x7f, 0x18, 0x00,
+ 0x7f, 0x6c, 0xff, 0xf8, 0xcf, 0x78, 0xcc, 0x00, 0x7e, 0xec, 0xff, 0xe8, 0xcf, 0xec, 0xcc, 0x00,
+ 0xfa, 0x88, 0x97, 0xc8, 0xe6, 0x70, 0x00, 0x02, 0xce, 0xf4, 0xf5, 0x00, 0x7f, 0xfd, 0x00, 0x08,
+ 0x5f, 0x70, 0x00, 0x02, 0xce, 0xf4, 0xfd, 0x00, 0xff, 0x8a, 0xa9, 0x70, 0x7f, 0x79, 0x00, 0x0d,
+ 0xff, 0x7f, 0x28, 0x10, 0xff, 0x02, 0x40, 0x00, 0xff, 0x7f, 0x28, 0x0c, 0x7d, 0x69, 0x00, 0x0f,
+ 0x5d, 0x68, 0x00, 0x01, 0xff, 0x02, 0x00, 0x0f, 0x7e, 0x71, 0x00, 0x02, 0xfd, 0x7f, 0x28, 0x12,
+ 0xfc, 0x7f, 0x28, 0x14, 0xff, 0x7f, 0x28, 0x16, 0xcf, 0xf0, 0xf8, 0x00, 0x7d, 0xed, 0x00, 0x18,
+ 0xfb, 0x89, 0xa9, 0x88, 0xce, 0xf4, 0xdd, 0x00, 0x0e, 0x70, 0x00, 0x14, 0xca, 0x58, 0x00, 0x00,
+ 0x9a, 0xfe, 0x00, 0x1c, 0x9e, 0xfe, 0x00, 0x18, 0xfe, 0x09, 0xa9, 0x70, 0xfb, 0x09, 0xa9, 0x74,
+ 0xc8, 0x68, 0x00, 0x00, 0xf8, 0x8a, 0xd3, 0xf0, 0xf9, 0x0a, 0x97, 0xc0, 0xf9, 0x82, 0x00, 0xff,
+ 0x7f, 0xd1, 0x00, 0x04, 0xcf, 0x7c, 0x90, 0x00, 0x8e, 0x7a, 0x00, 0x04, 0xad, 0x7e, 0x90, 0x02,
+ 0x8a, 0xfa, 0x00, 0x08, 0x7e, 0xf0, 0xff, 0xf8, 0x7f, 0xf0, 0xff, 0xe8, 0xce, 0xf4, 0xcc, 0x00,
+ 0xcf, 0x70, 0xcc, 0x00, 0xcf, 0xfc, 0x9c, 0x00, 0xcf, 0xfc, 0xed, 0x00, 0x7f, 0x79, 0x00, 0x08,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x7e, 0x71, 0x00, 0x18, 0xcb, 0xfe, 0xe5, 0x00, 0x7e, 0xe8, 0xff, 0xe8,
+ 0x7f, 0xe8, 0xff, 0xf8, 0xcf, 0xfc, 0xcc, 0x00, 0xcf, 0x68, 0xcc, 0x00, 0xce, 0xf4, 0x9c, 0x00,
+ 0xe6, 0x70, 0x00, 0x02, 0xce, 0xf4, 0xfd, 0x00, 0x7f, 0x79, 0x00, 0x08, 0x7d, 0xf1, 0x00, 0x02,
+ 0xce, 0xf4, 0xf5, 0x00, 0x0f, 0x6c, 0x00, 0x14, 0xbf, 0x5a, 0x88, 0x02, 0xcf, 0xd8, 0x88, 0x00,
+ 0xff, 0x02, 0x40, 0x00, 0xff, 0x7f, 0x28, 0x0c, 0x5e, 0x70, 0x00, 0x02, 0x7d, 0x69, 0x00, 0x18,
+ 0x7e, 0x71, 0x00, 0x0d, 0xff, 0x02, 0x00, 0x0f, 0xfe, 0x7f, 0x28, 0x10, 0x9b, 0xfe, 0x00, 0x18,
+ 0xf8, 0x7f, 0x28, 0x12, 0xfc, 0x7f, 0x28, 0x14, 0xff, 0x7f, 0x28, 0x16, 0xcd, 0xec, 0xf8, 0x00,
+ 0xce, 0xf4, 0xd5, 0x00, 0x0a, 0x50, 0x00, 0x01, 0x9a, 0xee, 0x00, 0x1c, 0x9e, 0xee, 0x00, 0x18,
+ 0x90, 0x7e, 0x00, 0x04, 0x20, 0x52, 0x00, 0x7f, 0xee, 0x00, 0xa0, 0x91, 0x0b, 0x58, 0x00, 0x24,
+ 0xe0, 0x00, 0x9f, 0x98, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x8f, 0x98, 0x70, 0x7e, 0x00, 0x15,
+ 0xea, 0x00, 0xa1, 0xb9, 0xff, 0x0a, 0x9f, 0xfe, 0xff, 0xfb, 0x18, 0x00, 0xfe, 0x8a, 0xa9, 0x70,
+ 0xfe, 0x09, 0xa9, 0x8c, 0xff, 0x0a, 0x9f, 0xf6, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0x7b, 0x18, 0x00,
+ 0xff, 0xf7, 0x28, 0x12, 0xff, 0x82, 0x00, 0x20, 0xff, 0x77, 0x28, 0x14, 0xff, 0xf7, 0x28, 0x16,
+ 0xff, 0x02, 0x40, 0x00, 0xff, 0x82, 0x34, 0x00, 0xff, 0x77, 0x28, 0x0c, 0xff, 0xf7, 0x28, 0x10,
+ 0xff, 0x02, 0x00, 0x14, 0xff, 0x82, 0x00, 0x01, 0xfe, 0x09, 0xa9, 0x88, 0xff, 0x09, 0xa9, 0x70,
+ 0xe0, 0x00, 0x9f, 0x98, 0xff, 0x89, 0xa9, 0x74, 0xe0, 0x00, 0x9f, 0x98, 0xfe, 0x09, 0xa9, 0x70,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x8f, 0xae, 0x00, 0x38, 0xff, 0x0a, 0xa0, 0x14, 0x7f, 0xfd, 0x00, 0x02,
+ 0xb0, 0x7e, 0xf0, 0x02, 0x85, 0xae, 0x00, 0x2c, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa1, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8f, 0x82, 0xff, 0xf8, 0x85, 0xae, 0x00, 0x2c, 0x70, 0x7e, 0x00, 0x12, 0xea, 0x00, 0xa2, 0xcd,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xce, 0xc0, 0x55, 0x29, 0x80, 0x00, 0x5f, 0xfc, 0x20, 0x00,
+ 0xff, 0x89, 0xce, 0xc0, 0x70, 0x7e, 0x00, 0x14, 0xea, 0x00, 0xa2, 0x94, 0x0f, 0x81, 0x20, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa2, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x9f, 0x82, 0xff, 0x88, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa2, 0x98, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xce, 0xc0,
+ 0xe0, 0x00, 0xa2, 0x54, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x85, 0xae, 0x00, 0x2c,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa2, 0xf0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x8d, 0x96, 0x00, 0x08, 0xff, 0x82, 0x00, 0x7f,
+ 0x8e, 0x96, 0x00, 0x00, 0xfe, 0x08, 0xd3, 0xd8, 0xc3, 0x18, 0xfc, 0x00, 0xff, 0x02, 0x0f, 0xff,
+ 0xc4, 0xa4, 0xf4, 0x00, 0x73, 0x9d, 0x00, 0x08, 0x7f, 0xed, 0x00, 0x0d, 0xcf, 0xfc, 0x4d, 0x00,
+ 0xc3, 0x9c, 0x30, 0x00, 0x9e, 0xf2, 0x00, 0x0c, 0xff, 0xf3, 0x28, 0x12, 0x93, 0xf2, 0x00, 0x14,
+ 0xff, 0x0a, 0x9f, 0xf6, 0xff, 0x7b, 0x18, 0x00, 0xff, 0x82, 0x03, 0xff, 0xce, 0xf4, 0xfc, 0x00,
+ 0xff, 0x73, 0x28, 0x10, 0x8f, 0x96, 0x00, 0x04, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa3, 0xb9,
+ 0x7c, 0xf5, 0x00, 0x02, 0x20, 0x6e, 0x00, 0x00, 0xe6, 0x00, 0xa3, 0xb8, 0x44, 0x20, 0xff, 0xfc,
+ 0x94, 0x02, 0xfe, 0x68, 0x9c, 0x82, 0xfe, 0x68, 0xff, 0x0a, 0xce, 0x00, 0x9f, 0x02, 0xfe, 0x68,
+ 0x9d, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x78, 0x00, 0x02,
+ 0xfd, 0xf3, 0x18, 0x0a, 0x8d, 0x72, 0x00, 0x2c, 0x9f, 0x72, 0x00, 0x30, 0x0f, 0xf0, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xa3, 0xe8, 0xff, 0x82, 0x00, 0x10,
+ 0x0f, 0x81, 0x10, 0x00, 0x0f, 0xfc, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0x30,
+ 0x9f, 0xf2, 0x00, 0x04, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xa4, 0x19, 0xfd, 0x09, 0xd3, 0xd8,
+ 0xff, 0x0a, 0xce, 0x00, 0x9f, 0x72, 0x00, 0x24, 0x9c, 0xf2, 0x00, 0x28, 0x9f, 0x02, 0xfe, 0x58,
+ 0x5f, 0xe5, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x0d, 0xec, 0x00, 0x01, 0x4d, 0xec, 0x0f, 0xff,
+ 0xfd, 0xeb, 0x28, 0x00, 0x9d, 0xea, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x73, 0x28, 0x02, 0x9e, 0x82, 0xff, 0x18, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c,
+ 0x8f, 0x16, 0x00, 0x04, 0x22, 0x10, 0x00, 0x0c, 0xcf, 0x98, 0x00, 0x00, 0x9f, 0x12, 0x00, 0x08,
+ 0x8f, 0x16, 0x00, 0x00, 0x94, 0x92, 0x00, 0x04, 0xc3, 0x1c, 0x00, 0x00, 0xc4, 0xa0, 0x00, 0x00,
+ 0x9f, 0x12, 0x00, 0x00, 0xc3, 0xfc, 0x00, 0x00, 0xc4, 0x18, 0x00, 0x00, 0xf7, 0x82, 0xa4, 0x88,
+ 0xe0, 0x00, 0xa3, 0x30, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xcf, 0xb0,
+ 0x2f, 0xfc, 0x00, 0x01, 0xff, 0x89, 0xcf, 0xb0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa4, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0xcf, 0xb0, 0x85, 0xae, 0x00, 0x2c, 0x2f, 0xfc, 0x00, 0x01, 0xff, 0x89, 0xcf, 0xb0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa5, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xfe, 0x88, 0xa9, 0xa8,
+ 0xff, 0x02, 0x00, 0x00, 0xfe, 0x06, 0x00, 0x00, 0xcf, 0xf0, 0xf7, 0xc0, 0xc0, 0x76, 0xfc, 0x00,
+ 0xe6, 0x00, 0xa5, 0x7c, 0xcf, 0x84, 0xfe, 0x00, 0x0f, 0x78, 0x00, 0x01, 0x20, 0x7a, 0x00, 0x0f,
+ 0xee, 0x00, 0xa5, 0x5d, 0xcf, 0xf0, 0xf7, 0xc0, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0xf4, 0xfc, 0x00,
+ 0x40, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa5, 0xa4, 0xff, 0x89, 0xa9, 0xa8, 0xff, 0x88, 0xce, 0xc0,
+ 0x4f, 0xfc, 0xff, 0xbf, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa5, 0xa4, 0xff, 0x89, 0xce, 0xc0,
+ 0x45, 0x29, 0x7f, 0xff, 0xf3, 0x02, 0x00, 0x00, 0xc4, 0x18, 0x00, 0x00, 0x9f, 0x16, 0xff, 0xf4,
+ 0xf3, 0x82, 0x00, 0x0e, 0xf7, 0x82, 0xa5, 0xc0, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x16, 0xff, 0xf4, 0xc3, 0x78, 0x00, 0x00, 0xf7, 0x82, 0xa5, 0xd4, 0xe0, 0x01, 0xa8, 0xe4,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10, 0x93, 0x16, 0xff, 0xf4,
+ 0xf3, 0x02, 0x00, 0x02, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0xa6, 0x04, 0xe0, 0x00, 0x7d, 0x14,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4, 0xff, 0x83, 0x1a, 0x42, 0x73, 0x79, 0x00, 0x1c,
+ 0x53, 0x19, 0x08, 0x00, 0x4f, 0xfd, 0x00, 0x00, 0x93, 0x16, 0xff, 0xe8, 0x9f, 0x96, 0xff, 0xf0,
+ 0xf7, 0x82, 0xa6, 0x2c, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x0f, 0x81, 0x40, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x8f, 0x16, 0xff, 0xe8, 0x9f, 0x02, 0xfe, 0x58, 0x8f, 0x02, 0xff, 0xc8,
+ 0x8f, 0x96, 0xff, 0xf0, 0x9f, 0x96, 0xff, 0xec, 0x8f, 0x82, 0xff, 0xc8, 0xcf, 0xfc, 0xf2, 0x00,
+ 0x20, 0x7e, 0x03, 0xe7, 0xe2, 0x00, 0xa6, 0x49, 0xf3, 0x02, 0x00, 0x02, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x82, 0xa6, 0x6c, 0xe0, 0x00, 0x7d, 0x14, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x1a, 0x42,
+ 0x8f, 0x16, 0xff, 0xec, 0x4f, 0xfd, 0x00, 0x00, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0xa6, 0x20,
+ 0x9f, 0x96, 0xff, 0xf0, 0xff, 0x82, 0x00, 0x40, 0xc0, 0x22, 0xfc, 0x00, 0xe6, 0x00, 0xa6, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x28, 0xfe, 0x88, 0xa9, 0xa8,
+ 0xfe, 0x02, 0x00, 0x00, 0xfd, 0x82, 0x00, 0x01, 0xcf, 0xec, 0xe7, 0xc0, 0xc0, 0x76, 0xfc, 0x00,
+ 0xe6, 0x78, 0x00, 0x03, 0x2f, 0x94, 0x00, 0x18, 0xbf, 0x7e, 0xe0, 0x04, 0x0e, 0x70, 0x00, 0x01,
+ 0x20, 0x72, 0x00, 0x0f, 0xe2, 0x00, 0xa6, 0xbd, 0xcf, 0xec, 0xe7, 0xc0, 0xfe, 0x08, 0xd3, 0xd8,
+ 0xc0, 0x2e, 0xe2, 0x00, 0xe6, 0x00, 0xa7, 0x19, 0xcf, 0x2c, 0x00, 0x00, 0xff, 0xfb, 0x58, 0x0c,
+ 0x4e, 0xfc, 0xff, 0xdf, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xa7, 0x08, 0x2d, 0x94, 0x00, 0x18,
+ 0xff, 0xfb, 0x58, 0x12, 0xbe, 0xee, 0xf8, 0x04, 0x8f, 0x7a, 0x00, 0x2c, 0xc0, 0x7a, 0xe2, 0x00,
+ 0xe6, 0x00, 0xa6, 0xec, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x17, 0x6b, 0xf7, 0x23, 0x14, 0x00, 0x18,
+ 0x23, 0x94, 0x00, 0x28, 0xf7, 0x82, 0xa7, 0x30, 0xe0, 0x01, 0xa7, 0x44, 0x97, 0x93, 0xff, 0xfc,
+ 0xfe, 0x02, 0x00, 0x00, 0xfd, 0x8a, 0xe6, 0x30, 0x2f, 0x14, 0x00, 0x18, 0xaf, 0xfa, 0xe0, 0x05,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa7, 0xcd, 0x2f, 0x14, 0x00, 0x28, 0xaf, 0xfa, 0xe0, 0x05,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa7, 0x69, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xd0,
+ 0xe0, 0x00, 0xa7, 0xcc, 0x9f, 0xee, 0x00, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0x8f, 0x6e, 0x00, 0x00,
+ 0xfe, 0x88, 0xce, 0xa8, 0xcf, 0xfc, 0xf2, 0x00, 0xc0, 0x7e, 0xea, 0x00, 0xe2, 0x00, 0xa7, 0xcd,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xa7, 0xcd, 0xc3, 0x70, 0x00, 0x00, 0x9d, 0x96, 0xff, 0xd4,
+ 0x9e, 0x16, 0xff, 0xd0, 0xf7, 0x82, 0xa7, 0xa0, 0xe0, 0x00, 0xa5, 0xe0, 0x97, 0x93, 0xff, 0xfc,
+ 0x8e, 0x16, 0xff, 0xd0, 0xfe, 0x88, 0xa9, 0xa8, 0xff, 0x08, 0xce, 0xc0, 0xff, 0x86, 0x00, 0x01,
+ 0xcf, 0xfc, 0xe7, 0xc0, 0x8d, 0x96, 0xff, 0xd4, 0xce, 0xf4, 0xfd, 0x00, 0x5f, 0x78, 0x00, 0x40,
+ 0x55, 0x29, 0x80, 0x00, 0xff, 0x09, 0xce, 0xc0, 0xfe, 0x89, 0xa9, 0xa8, 0x0e, 0x70, 0x00, 0x01,
+ 0x20, 0x72, 0x00, 0x0f, 0xe2, 0x00, 0xa7, 0x39, 0x0d, 0xec, 0x00, 0x04, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8f, 0x9a, 0x00, 0x00, 0x55, 0x29, 0x80, 0x00, 0xff, 0x89, 0xcd, 0xe8, 0x8f, 0x9a, 0x00, 0x04,
+ 0xff, 0x89, 0xe8, 0x90, 0x8f, 0x9a, 0x00, 0x08, 0xff, 0x89, 0xcf, 0xb8, 0x8f, 0x9a, 0x00, 0x0c,
+ 0xff, 0x89, 0xce, 0xb8, 0x8f, 0x9a, 0x00, 0x10, 0xff, 0x89, 0xce, 0xb0, 0x8f, 0x9a, 0x00, 0x14,
+ 0xff, 0x89, 0xe6, 0x70, 0xff, 0x88, 0xce, 0xc0, 0x83, 0x1a, 0x00, 0x18, 0x5f, 0xfc, 0x00, 0x08,
+ 0xf3, 0x09, 0xcd, 0xe0, 0xff, 0x89, 0xce, 0xc0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04,
+ 0xfd, 0x82, 0x00, 0x00, 0xcf, 0x84, 0x56, 0x00, 0x70, 0x7e, 0x00, 0x01, 0xce, 0x18, 0x00, 0x00,
+ 0xea, 0x00, 0xa8, 0xb8, 0xcd, 0x6c, 0x00, 0x00, 0x4f, 0x9d, 0x00, 0x00, 0x73, 0xfc, 0xff, 0xfa,
+ 0x20, 0x1e, 0x00, 0x07, 0xe2, 0x00, 0xa8, 0xb8, 0x7f, 0x9d, 0x00, 0x02, 0xff, 0x02, 0xa8, 0x8c,
+ 0xae, 0xfe, 0xf0, 0x02, 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xa8, 0xac,
+ 0x00, 0x00, 0xa8, 0xec, 0x00, 0x00, 0xa9, 0x40, 0x00, 0x00, 0xa9, 0x70, 0x00, 0x00, 0xa9, 0xac,
+ 0x00, 0x00, 0xa9, 0xc4, 0x00, 0x00, 0xa8, 0xb8, 0x00, 0x00, 0xaa, 0x0c, 0xf7, 0x82, 0xa8, 0xb8,
+ 0xe0, 0x00, 0xa7, 0xe8, 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xa8, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x1a, 0x00, 0x00,
+ 0xff, 0x09, 0xad, 0xb0, 0x8f, 0x9a, 0x00, 0x04, 0xff, 0x89, 0xe5, 0xf0, 0x8f, 0x1a, 0x00, 0x08,
+ 0xff, 0x09, 0xe6, 0x28, 0x8f, 0x9a, 0x00, 0x0c, 0xff, 0x89, 0xce, 0xc8, 0x8f, 0x1a, 0x00, 0x10,
+ 0x20, 0x7f, 0x00, 0x20, 0xff, 0x09, 0xcd, 0xe8, 0x8f, 0x1a, 0x00, 0x14, 0xff, 0x09, 0xe8, 0x90,
+ 0x8e, 0x1a, 0x00, 0x18, 0xe2, 0x00, 0xa8, 0xb8, 0xfe, 0x09, 0xcf, 0xb8, 0xff, 0x88, 0xce, 0xc0,
+ 0x55, 0x29, 0x80, 0x00, 0x5f, 0xfc, 0x00, 0x02, 0xe0, 0x00, 0xa8, 0xb8, 0xff, 0x89, 0xce, 0xc0,
+ 0xf0, 0x09, 0xce, 0xc8, 0x8f, 0x9a, 0x00, 0x00, 0xff, 0x26, 0x34, 0x58, 0x55, 0x29, 0x80, 0x00,
+ 0xff, 0x89, 0xcd, 0xe8, 0xff, 0x88, 0xce, 0xc0, 0x8e, 0x1a, 0x00, 0x04, 0x5f, 0xfc, 0x00, 0x02,
+ 0xfe, 0x09, 0xe8, 0x90, 0xff, 0x89, 0xce, 0xc0, 0xe0, 0x00, 0xa8, 0xb8, 0xff, 0x09, 0xcf, 0xb8,
+ 0xf0, 0x09, 0xce, 0xc8, 0x8f, 0x9a, 0x00, 0x00, 0x55, 0x29, 0x80, 0x00, 0xff, 0x89, 0xcd, 0xe8,
+ 0x8f, 0x1a, 0x00, 0x04, 0xff, 0x88, 0xce, 0xc0, 0xff, 0x09, 0xe8, 0x90, 0x8d, 0x1a, 0x00, 0x08,
+ 0x5f, 0xfc, 0x00, 0x02, 0xff, 0x89, 0xce, 0xc0, 0xf7, 0x82, 0xa9, 0xa4, 0xc1, 0x68, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xa8, 0xb8, 0xf4, 0x09, 0xcf, 0xb8, 0x83, 0x1a, 0x00, 0x00,
+ 0xf7, 0x82, 0xa9, 0xbc, 0xe0, 0x00, 0x31, 0x4c, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xa8, 0xb8,
+ 0x00, 0x00, 0x00, 0x01, 0x83, 0x9a, 0x00, 0x04, 0x83, 0x1a, 0x00, 0x00, 0x9e, 0x16, 0xff, 0xf4,
+ 0xf7, 0x82, 0xa9, 0xdc, 0xe0, 0x00, 0x32, 0x70, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x16, 0xff, 0xf4,
+ 0xf4, 0x09, 0xcf, 0xb8, 0x8f, 0xf2, 0x00, 0x08, 0xff, 0x89, 0xcd, 0xe8, 0x8f, 0x72, 0x00, 0x0c,
+ 0xff, 0x09, 0xe8, 0x90, 0x8f, 0xf2, 0x00, 0x10, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xa8, 0xb9,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xa9, 0x2c, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x09, 0xce, 0xc8,
+ 0x8f, 0x9a, 0x00, 0x00, 0x20, 0x6e, 0x00, 0x00, 0x55, 0x29, 0x80, 0x00, 0xff, 0x89, 0xcd, 0xe8,
+ 0x8f, 0x1a, 0x00, 0x04, 0xff, 0x09, 0xe8, 0x90, 0x8f, 0x9a, 0x00, 0x08, 0xff, 0x89, 0xcf, 0xb8,
+ 0x8f, 0x1a, 0x00, 0x0c, 0xff, 0x09, 0xa9, 0xa0, 0x8f, 0x9a, 0x00, 0x10, 0xff, 0x89, 0xcd, 0xf0,
+ 0xff, 0x88, 0xce, 0xc0, 0x8e, 0x1a, 0x00, 0x14, 0x5f, 0xfc, 0x00, 0x02, 0xfe, 0x09, 0xce, 0xa0,
+ 0xe6, 0x00, 0xa8, 0xb9, 0xff, 0x89, 0xce, 0xc0, 0xe0, 0x00, 0xa9, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x7e, 0x21, 0x00, 0x02, 0xcf, 0x9c, 0xe0, 0x00, 0x2f, 0xfc, 0x00, 0x01,
+ 0xff, 0x02, 0x00, 0x3c, 0xcf, 0x1c, 0xf4, 0x00, 0xcf, 0x9c, 0xfe, 0x00, 0xfe, 0x8a, 0xce, 0xe0,
+ 0x40, 0x7e, 0xff, 0xc0, 0xe6, 0x00, 0xaa, 0xd1, 0xce, 0xf8, 0xe8, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xaa, 0x9c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0xfa, 0x80, 0x00, 0xcf, 0x7c, 0x32, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xee, 0x00, 0xac, 0x01,
+ 0xcf, 0xf0, 0xf2, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xee, 0x00, 0xab, 0xed, 0x00, 0x00, 0x00, 0x01,
+ 0x93, 0x02, 0xfe, 0x68, 0x9f, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xfe, 0x7a, 0x00, 0x00, 0x9e, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68,
+ 0xcf, 0xf4, 0xf0, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8a, 0xcd, 0xc8, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xab, 0xb9, 0xff, 0x82, 0x00, 0x01,
+ 0xff, 0x02, 0x00, 0x3c, 0xcf, 0xfc, 0x47, 0xc0, 0xcf, 0x1c, 0xf4, 0x00, 0xfe, 0x88, 0xcd, 0xc8,
+ 0x2f, 0xfc, 0x00, 0x01, 0x7f, 0x78, 0xff, 0xfe, 0xcf, 0xfc, 0xf7, 0xc0, 0xce, 0xf4, 0xfd, 0x00,
+ 0x20, 0x76, 0xff, 0xff, 0xe6, 0x00, 0xab, 0x95, 0x4f, 0x9d, 0x00, 0xff, 0xfe, 0x89, 0xcd, 0xc8,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xab, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0xfc, 0xff, 0xee, 0xf0, 0x09, 0xcd, 0xc8, 0x7f, 0xfd, 0x00, 0x02,
+ 0x8f, 0x7e, 0x05, 0x08, 0x43, 0x9c, 0xff, 0xc0, 0xf3, 0x0a, 0xce, 0xe0, 0xf7, 0x82, 0xab, 0xb8,
+ 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xab, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68,
+ 0x9e, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0xe0, 0x00, 0xab, 0x18, 0x00, 0x00, 0x00, 0x01,
+ 0x2f, 0x98, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0xe0, 0x00, 0xab, 0xf0, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xce, 0xc0, 0x85, 0xae, 0x00, 0x2c, 0x4f, 0xfc, 0xff, 0xf9,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xac, 0x40, 0xff, 0x89, 0xce, 0xc0, 0x45, 0x29, 0x7f, 0xff,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xac, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xce, 0xc0, 0x85, 0xae, 0x00, 0x2c,
+ 0x4f, 0xfc, 0xff, 0xfb, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xac, 0xa4, 0xff, 0x89, 0xce, 0xc0,
+ 0x45, 0x29, 0x7f, 0xff, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x00, 0xac, 0xa4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xce, 0xc0,
+ 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x00, 0xad, 0x30, 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xac, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x88, 0xce, 0xc8, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xae, 0xa5, 0xfc, 0x82, 0x00, 0x04,
+ 0xfb, 0x88, 0xe5, 0xf0, 0xff, 0x82, 0x00, 0x7f, 0xff, 0x02, 0x00, 0x80, 0xcf, 0xdc, 0xfc, 0x00,
+ 0xfc, 0x08, 0xad, 0xb0, 0xcc, 0xf8, 0xfa, 0x00, 0xc0, 0x76, 0xca, 0x00, 0xe4, 0x00, 0xad, 0x69,
+ 0x00, 0x00, 0x00, 0x01, 0xcc, 0xf4, 0x00, 0x00, 0xff, 0x88, 0xe6, 0x28, 0xfb, 0x0a, 0xcf, 0x30,
+ 0xfa, 0x82, 0xac, 0x80, 0x9f, 0x82, 0xfe, 0x68, 0x9c, 0x82, 0xfe, 0x68, 0x9b, 0x02, 0xfe, 0x68,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xce, 0xf4, 0xca, 0x00, 0xcf, 0x5c, 0xc8, 0x00,
+ 0xcf, 0xfc, 0xc8, 0x00, 0xff, 0x89, 0xe6, 0x28, 0xff, 0x09, 0xe5, 0xf0, 0xfe, 0x89, 0xce, 0xc8,
+ 0x7f, 0xe4, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x70, 0x00, 0x02, 0x20, 0x62, 0x00, 0x00,
+ 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xff, 0x82, 0x7c, 0xcc, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xce, 0x70, 0xf8, 0x00, 0xff, 0x88, 0x9f, 0xfc, 0x7f, 0x64, 0xff, 0xfe, 0xfd, 0x73, 0x58, 0x20,
+ 0x4f, 0x78, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xf5, 0x00, 0xff, 0xf7, 0x28, 0x0e,
+ 0x7d, 0xed, 0x00, 0x02, 0xcf, 0xf4, 0xd8, 0x00, 0xfd, 0x77, 0x28, 0x12, 0x9c, 0x76, 0x00, 0x14,
+ 0x9b, 0xfe, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10, 0xff, 0x86, 0x00, 0x01, 0x9f, 0xf6, 0x00, 0x30,
+ 0xff, 0x77, 0x18, 0x0a, 0x8e, 0x76, 0x00, 0x2c, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x9d, 0x82, 0xfe, 0x58, 0x0f, 0xd4, 0x00, 0x08, 0x9f, 0xf6, 0x00, 0x04, 0xfe, 0x09, 0xd3, 0xd8,
+ 0x9b, 0x76, 0x00, 0x24, 0x9c, 0xf6, 0x00, 0x28, 0x9b, 0x02, 0xfe, 0x58, 0x5f, 0xe5, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0f, 0x78, 0x00, 0x01, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x77, 0x28, 0x02,
+ 0xff, 0x88, 0xce, 0xc0, 0x55, 0x29, 0x80, 0x00, 0x5f, 0xfc, 0x00, 0x04, 0xff, 0x89, 0xce, 0xc0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xae, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0x08, 0xcd, 0xe8, 0xfb, 0x88, 0xe8, 0x90, 0xfb, 0x0a, 0xcf, 0xb8,
+ 0xe0, 0x00, 0xad, 0xa0, 0xfa, 0x82, 0xac, 0x1c, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x93, 0x02, 0xfe, 0x68,
+ 0x93, 0x82, 0xfe, 0x68, 0x94, 0x02, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xc1, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xae, 0xe8, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x48, 0x61, 0x6e, 0x64,
+ 0x6f, 0x66, 0x66, 0x3a, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69,
+ 0x6c, 0x69, 0x74, 0x79, 0x0a, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x14, 0xff, 0x88, 0xd3, 0xd8, 0xfe, 0x82, 0x00, 0x00, 0x9e, 0x96, 0xff, 0xec,
+ 0xc0, 0x2e, 0xfa, 0x00, 0xe6, 0x00, 0xaf, 0x71, 0x9e, 0x96, 0xff, 0xf0, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xaf, 0x3c, 0x00, 0x00, 0x00, 0x01,
+ 0xf7, 0x82, 0xaf, 0x7c, 0xe0, 0x01, 0xa8, 0x18, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xcf, 0xb0,
+ 0xc0, 0x22, 0xfd, 0x00, 0xe6, 0x00, 0xaf, 0x3c, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x88, 0xe6, 0x70,
+ 0x20, 0x76, 0x00, 0x3c, 0xe2, 0x00, 0xb2, 0xa4, 0xff, 0x02, 0x00, 0x00, 0xff, 0x88, 0xce, 0xb8,
+ 0xcf, 0x7c, 0xea, 0x00, 0x8f, 0x7a, 0x00, 0x3c, 0xcf, 0xfc, 0xf0, 0x00, 0xcf, 0xfc, 0xea, 0x00,
+ 0x9f, 0x96, 0xff, 0xf4, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xaf, 0xf9, 0xff, 0x82, 0x00, 0x03,
+ 0x8e, 0x96, 0xff, 0xf4, 0x8f, 0xf6, 0x00, 0x00, 0x20, 0x7e, 0x00, 0xa4, 0xe2, 0x00, 0xaf, 0xf9,
+ 0xff, 0x82, 0x00, 0x03, 0xff, 0xf7, 0x18, 0xa4, 0x9f, 0x96, 0xff, 0xf0, 0xfe, 0xf7, 0x18, 0xa6,
+ 0xff, 0x8a, 0xa5, 0xa0, 0xff, 0xff, 0x58, 0x9a, 0x9e, 0x96, 0xff, 0xec, 0x8e, 0x96, 0xff, 0xf4,
+ 0xff, 0xf7, 0x68, 0x9a, 0xff, 0x82, 0x00, 0x03, 0x9f, 0x96, 0xff, 0xe8, 0xff, 0x88, 0xa8, 0x60,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xb0, 0x11, 0xfe, 0x82, 0x00, 0x02, 0x9e, 0x96, 0xff, 0xe8,
+ 0xff, 0x88, 0x92, 0x08, 0x7f, 0xfd, 0x00, 0x10, 0x7f, 0xfc, 0xff, 0xe8, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0xb0, 0x34, 0x20, 0x7a, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xe8, 0x4f, 0xfc, 0xff, 0xfd,
+ 0x9f, 0x96, 0xff, 0xe8, 0xe6, 0x00, 0xb0, 0x65, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xf0,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xb0, 0x64, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xec,
+ 0x8e, 0x96, 0xff, 0xe8, 0xcf, 0x84, 0xf6, 0x00, 0xc0, 0x76, 0xfc, 0x00, 0xe6, 0x00, 0xb0, 0xe9,
+ 0x00, 0x00, 0x00, 0x01, 0x22, 0x10, 0x00, 0x04, 0xff, 0x02, 0xae, 0xfc, 0x9f, 0x12, 0x00, 0x00,
+ 0xf7, 0x82, 0xb0, 0x7c, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x08, 0xcf, 0xb8,
+ 0xff, 0x88, 0xce, 0xc0, 0xf0, 0x09, 0xce, 0xc8, 0xcf, 0x04, 0xf6, 0x00, 0x4f, 0xfc, 0xff, 0xf7,
+ 0xff, 0x09, 0xcf, 0xb8, 0x20, 0x7e, 0x00, 0x00, 0xff, 0x89, 0xce, 0xc0, 0xe6, 0x00, 0xb0, 0xa8,
+ 0x02, 0x10, 0x00, 0x04, 0x45, 0x29, 0x7f, 0xff, 0xf7, 0x82, 0xb0, 0xb4, 0xe0, 0x00, 0x7c, 0xf0,
+ 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x00, 0xb0, 0xb4, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb0, 0xf4, 0xe0, 0x00, 0xb6, 0xe4,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x82, 0x7f, 0xff, 0xc4, 0x20, 0xfc, 0x00, 0xff, 0xf6, 0xed, 0xa0,
+ 0x94, 0x7e, 0x00, 0x04, 0xff, 0x88, 0x9f, 0xf0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xb2, 0x8d,
+ 0x03, 0x01, 0xe1, 0x00, 0xff, 0x02, 0x00, 0x80, 0xfe, 0xf6, 0xed, 0xa0, 0x9f, 0x76, 0x00, 0x0c,
+ 0xff, 0x88, 0x9f, 0xf4, 0xcd, 0xf8, 0x00, 0x00, 0xfe, 0x02, 0x00, 0x00, 0x9f, 0xf6, 0x00, 0x08,
+ 0xfe, 0xf6, 0xed, 0xb0, 0xff, 0x0a, 0x8f, 0x88, 0x8f, 0xfa, 0x00, 0x00, 0x0e, 0x70, 0x00, 0x01,
+ 0xc0, 0x72, 0xda, 0x00, 0x9f, 0xf5, 0x00, 0x04, 0xe4, 0x00, 0xb1, 0x38, 0x0f, 0x78, 0x00, 0x10,
+ 0xff, 0x88, 0xa8, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xb1, 0x8d, 0xff, 0xf6, 0xed, 0xa0,
+ 0xff, 0x8a, 0x8f, 0x80, 0x0f, 0x7c, 0x02, 0x88, 0xfe, 0x02, 0x00, 0x00, 0xfe, 0xf6, 0xee, 0x38,
+ 0x8f, 0xfa, 0x00, 0x00, 0x0e, 0x70, 0x00, 0x01, 0x20, 0x72, 0x00, 0x07, 0x9f, 0xf5, 0x00, 0x04,
+ 0xe2, 0x00, 0xb1, 0x71, 0x0f, 0x78, 0x00, 0x10, 0xff, 0xf6, 0xed, 0xa0, 0xfe, 0x82, 0x00, 0x01,
+ 0x9e, 0xfe, 0x10, 0x5c, 0xff, 0x08, 0xcd, 0xe8, 0xfe, 0x02, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x01,
+ 0x9f, 0x7e, 0x10, 0x50, 0xfe, 0x88, 0xe8, 0x90, 0xfd, 0xf6, 0xfd, 0xb0, 0x9e, 0xfe, 0x10, 0x54,
+ 0xff, 0x08, 0xcf, 0xb8, 0x9f, 0x7e, 0x10, 0x58, 0xff, 0x08, 0xd3, 0xd8, 0xfe, 0xfb, 0x18, 0x00,
+ 0x9e, 0xfe, 0x00, 0x00, 0xff, 0x08, 0xa9, 0xa8, 0xcf, 0xe8, 0xe7, 0xc0, 0x0e, 0x70, 0x00, 0x01,
+ 0xc0, 0x7a, 0xfc, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x20, 0x72, 0x00, 0x0f, 0xe2, 0x00, 0xb1, 0xc5,
+ 0x9e, 0xed, 0x00, 0x04, 0x8f, 0x96, 0xff, 0xe8, 0x70, 0x7e, 0x00, 0x1e, 0xea, 0x00, 0xb2, 0x08,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xf4, 0x8f, 0xf6, 0x00, 0xa8, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0xb2, 0x64, 0xf3, 0x8a, 0x97, 0xc0, 0xfe, 0x76, 0xff, 0xcc, 0x8f, 0xf2, 0x00, 0x00,
+ 0xfd, 0xf6, 0xff, 0xe4, 0x0e, 0x81, 0xc0, 0x00, 0x5f, 0xfd, 0x0c, 0x00, 0x9f, 0xf2, 0x00, 0x00,
+ 0x8f, 0x6e, 0x00, 0x00, 0x0e, 0xf4, 0x00, 0x03, 0xf3, 0x76, 0xff, 0xfc, 0xcf, 0x78, 0xec, 0x00,
+ 0x9f, 0x6e, 0x00, 0x00, 0xf7, 0x82, 0xb2, 0x40, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x16, 0xff, 0xec, 0x70, 0x7a, 0x00, 0x1d, 0xea, 0x00, 0xb2, 0xad, 0xf3, 0x02, 0x00, 0x01,
+ 0xf7, 0x82, 0xb2, 0x5c, 0xe0, 0x00, 0x78, 0x50, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xb2, 0xac,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x08, 0xce, 0xb8, 0xf4, 0x02, 0x08, 0x00, 0xc3, 0x18, 0xf8, 0x00,
+ 0xff, 0x88, 0xe6, 0x70, 0xc3, 0x18, 0xfa, 0x00, 0xf7, 0x82, 0xb2, 0x84, 0xe0, 0x02, 0x8a, 0x60,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xb2, 0x08, 0x00, 0x00, 0x00, 0x01, 0x03, 0x18, 0x0b, 0x73,
+ 0xf7, 0x82, 0xb2, 0x9c, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xb1, 0x18,
+ 0xff, 0x02, 0x00, 0x80, 0xe0, 0x00, 0xaf, 0xb4, 0x9f, 0x16, 0xff, 0xf4, 0xf7, 0x82, 0xb2, 0xb8,
+ 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x08, 0xce, 0xb8, 0xf3, 0x88, 0xce, 0xb0,
+ 0xf4, 0x08, 0xe6, 0x70, 0xf4, 0x88, 0xcd, 0xe0, 0xf7, 0x82, 0xb2, 0xd4, 0xe0, 0x00, 0xae, 0xc4,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xfe, 0x82, 0x00, 0x00,
+ 0x7f, 0x75, 0x00, 0x02, 0xfe, 0x0a, 0xa0, 0x14, 0xaf, 0xfa, 0xe0, 0x02, 0xc3, 0xf4, 0x00, 0x00,
+ 0x20, 0x7e, 0x00, 0x02, 0xe6, 0x00, 0xb3, 0x35, 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x76, 0x00, 0x03,
+ 0xee, 0x00, 0xb2, 0xf1, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xce, 0xc0, 0x4f, 0xfc, 0xfd, 0xff,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xb3, 0x5c, 0xff, 0x89, 0xce, 0xc0, 0xe0, 0x00, 0xb3, 0x5c,
+ 0x45, 0x29, 0x7f, 0xff, 0xff, 0x8a, 0xce, 0x90, 0xa3, 0x7a, 0xf8, 0x02, 0xb0, 0x7a, 0xe0, 0x02,
+ 0x9e, 0x96, 0xff, 0xf4, 0xf7, 0x82, 0xb3, 0x50, 0xe0, 0x00, 0xb9, 0x40, 0x97, 0x93, 0xff, 0xfc,
+ 0x8e, 0x96, 0xff, 0xf4, 0xe0, 0x00, 0xb3, 0x10, 0x20, 0x76, 0x00, 0x03, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0xa5, 0x50, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xb4, 0x45, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x08, 0xd3, 0xd8, 0xc0, 0x2e, 0xe2, 0x00, 0xe6, 0x00, 0xb4, 0x94, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x83, 0x1a, 0x60, 0xfe, 0x82, 0x00, 0x7f, 0xff, 0x0a, 0xad, 0xc0, 0xcf, 0xfc, 0xec, 0x00,
+ 0xcf, 0x70, 0xf2, 0x00, 0x7f, 0xfd, 0x00, 0x06, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0xb4, 0x94,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x13, 0xea, 0x00, 0xb4, 0x94,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x12, 0xea, 0x00, 0xb4, 0x94,
+ 0xf3, 0x02, 0x00, 0x01, 0xf7, 0x82, 0xb3, 0xe0, 0xe0, 0x00, 0x2e, 0xc0, 0x97, 0x93, 0xff, 0xfc,
+ 0x8e, 0x02, 0xfe, 0xe0, 0x0f, 0x01, 0x00, 0xff, 0x7f, 0xa0, 0xff, 0xf4, 0xcf, 0x70, 0xf4, 0x00,
+ 0x7f, 0x78, 0xff, 0xf0, 0xcf, 0x78, 0xfa, 0x00, 0xfe, 0x82, 0x00, 0xff, 0x70, 0x72, 0x00, 0x07,
+ 0xea, 0x00, 0xb4, 0x15, 0xcf, 0x78, 0xec, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xb4, 0x95,
+ 0x00, 0x00, 0x00, 0x01, 0xfe, 0x82, 0x3f, 0xff, 0x7f, 0x21, 0x00, 0x02, 0xcf, 0xf0, 0xec, 0x00,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x70, 0x72, 0x00, 0x11, 0xea, 0x00, 0xb4, 0x41, 0xc4, 0x7c, 0xec, 0x00,
+ 0xff, 0x88, 0x9f, 0xe8, 0xc0, 0x22, 0xfa, 0x00, 0xe4, 0x00, 0xb4, 0x94, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x09, 0xa5, 0x50, 0xf7, 0x82, 0xb4, 0x50, 0xe0, 0x00, 0xb6, 0xe4, 0x97, 0x93, 0xff, 0xfc,
+ 0xc3, 0x20, 0x00, 0x00, 0xf7, 0x82, 0xb4, 0x60, 0xe0, 0x00, 0x8a, 0x7c, 0x97, 0x93, 0xff, 0xfc,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xb4, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x12,
+ 0xea, 0x00, 0xb4, 0xd0, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xce, 0xc0, 0x4f, 0xfc, 0xdf, 0xff,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xb4, 0xd0, 0xff, 0x89, 0xce, 0xc0, 0x45, 0x29, 0x7f, 0xff,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xff, 0x88, 0xce, 0xc0, 0x70, 0x7e, 0x00, 0x15,
+ 0xea, 0x00, 0xb6, 0xc1, 0x93, 0x16, 0xff, 0xf4, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x00, 0xb6, 0xa9,
+ 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x18, 0xea, 0x00, 0xb6, 0x85, 0x00, 0x00, 0x00, 0x01,
+ 0x70, 0x7e, 0x00, 0x12, 0xea, 0x00, 0xb6, 0x6d, 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x1b,
+ 0xea, 0x00, 0xb6, 0x55, 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x1a, 0xea, 0x00, 0xb6, 0x3d,
+ 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x13, 0xea, 0x00, 0xb6, 0x25, 0x00, 0x00, 0x00, 0x01,
+ 0x70, 0x7e, 0x00, 0x14, 0xea, 0x00, 0xb6, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x1e,
+ 0xea, 0x00, 0xb5, 0xf5, 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x16, 0xea, 0x00, 0xb5, 0xdd,
+ 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x19, 0xea, 0x00, 0xb5, 0xc5, 0x00, 0x00, 0x00, 0x01,
+ 0x20, 0x7e, 0x00, 0x08, 0xe6, 0x00, 0xb5, 0xb1, 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xb5, 0x7c, 0x00, 0x00, 0x00, 0x01,
+ 0xf7, 0x82, 0xb5, 0xbc, 0xe0, 0x00, 0xaf, 0x18, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xb5, 0x7c,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb5, 0xd0, 0xe0, 0x00, 0xa5, 0x40, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xce, 0xc0, 0xe0, 0x00, 0xb5, 0x74, 0x20, 0x7e, 0x00, 0x08, 0xf7, 0x82, 0xb5, 0xe8,
+ 0xe0, 0x00, 0xb2, 0xe0, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xce, 0xc0, 0xe0, 0x00, 0xb5, 0x64,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0x00, 0xe0, 0x00, 0xac, 0xe4, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xce, 0xc0, 0xe0, 0x00, 0xb5, 0x58, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0x18,
+ 0xe0, 0x00, 0xb3, 0x68, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xce, 0xc0, 0xe0, 0x00, 0xb5, 0x4c,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0x30, 0xe0, 0x00, 0x9e, 0xc8, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xce, 0xc0, 0xe0, 0x00, 0xb5, 0x40, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0x48,
+ 0xe0, 0x00, 0x95, 0xac, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xce, 0xc0, 0xe0, 0x00, 0xb5, 0x34,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0x60, 0xe0, 0x00, 0x96, 0x70, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xce, 0xc0, 0xe0, 0x00, 0xb5, 0x28, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0x78,
+ 0xe0, 0x00, 0xb4, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xce, 0xc0, 0xe0, 0x00, 0xb5, 0x1c,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xf4, 0xf3, 0x02, 0x0f, 0xff, 0xc3, 0x7c, 0x34, 0x00,
+ 0xf7, 0x82, 0xb6, 0x9c, 0xe0, 0x00, 0x9c, 0x68, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xce, 0xc0,
+ 0xe0, 0x00, 0xb5, 0x10, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xb6, 0xb4, 0xe0, 0x00, 0x9b, 0x90,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xce, 0xc0, 0xe0, 0x00, 0xb5, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0xf7, 0x82, 0xb6, 0xcc, 0xe0, 0x01, 0x01, 0xac, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xce, 0xc0,
+ 0xe0, 0x00, 0xb4, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x24, 0x0c, 0x00, 0x60,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x01, 0x98, 0x00, 0x60, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c,
+ 0x94, 0x16, 0xff, 0xec, 0x93, 0x16, 0xff, 0xf4, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xb8, 0x21,
+ 0x93, 0x96, 0xff, 0xf0, 0x0f, 0x9d, 0xff, 0xe2, 0x20, 0x7e, 0xff, 0xff, 0xe2, 0x00, 0xb8, 0x08,
+ 0x03, 0x01, 0xe1, 0x00, 0xff, 0x88, 0x9f, 0xe4, 0x8e, 0x96, 0xff, 0xec, 0xc0, 0x76, 0xfa, 0x00,
+ 0xe4, 0x00, 0xb7, 0xf1, 0x03, 0x01, 0xe1, 0x00, 0x8f, 0x16, 0xff, 0xf0, 0xff, 0xfa, 0x7f, 0xff,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe2, 0x00, 0xb7, 0x75, 0x00, 0x00, 0x00, 0x01, 0x2f, 0x78, 0x80, 0x00,
+ 0x9f, 0x16, 0xff, 0xf0, 0x8e, 0x96, 0xff, 0xf0, 0x8f, 0x16, 0xff, 0xec, 0xff, 0xfa, 0x80, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe2, 0x00, 0xb7, 0x9d, 0xff, 0x02, 0x00, 0x00,
+ 0x8e, 0x96, 0xff, 0xec, 0x9f, 0x96, 0xff, 0xec, 0xcf, 0x74, 0xfa, 0x00, 0x8f, 0x96, 0xff, 0xf0,
+ 0x9f, 0x82, 0xfe, 0x68, 0x8e, 0x96, 0xff, 0xec, 0x9e, 0x82, 0xfe, 0x68, 0x8f, 0x96, 0xff, 0xf4,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0xb8, 0x21, 0xfe, 0xfa, 0x00, 0x00, 0x9e, 0x82, 0xfe, 0x68, 0x9f, 0x02, 0xfe, 0x68,
+ 0x8f, 0x16, 0xff, 0xf4, 0x8e, 0x96, 0xff, 0xec, 0xcf, 0xf8, 0xe8, 0x00, 0x9f, 0x82, 0xfe, 0x68,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xb8, 0x20, 0x00, 0x00, 0x00, 0x01,
+ 0x03, 0x18, 0x0c, 0x58, 0xf7, 0x82, 0xb8, 0x00, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xb7, 0x58, 0x00, 0x00, 0x00, 0x01, 0x03, 0x18, 0x0c, 0x57, 0xf7, 0x82, 0xb8, 0x18,
+ 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xb7, 0x44, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x8f, 0x98, 0xff, 0x08, 0x8f, 0xc8, 0xfb, 0xf6, 0xff, 0xf4,
+ 0xfc, 0xf6, 0xff, 0xf8, 0x8e, 0xde, 0x00, 0x00, 0x8e, 0x66, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x1e,
+ 0xfd, 0x88, 0x8f, 0xd8, 0x7f, 0x78, 0xff, 0xe8, 0x7f, 0xfc, 0xff, 0xe1, 0xfc, 0x76, 0xff, 0xf0,
+ 0x7f, 0x79, 0x00, 0x04, 0x7f, 0xfd, 0x00, 0x0b, 0x4e, 0xf4, 0xf0, 0x00, 0x4e, 0x70, 0xf7, 0xff,
+ 0x8d, 0x62, 0x00, 0x00, 0xce, 0xf4, 0xf5, 0x00, 0xce, 0x70, 0xfd, 0x00, 0x7f, 0xec, 0xff, 0xec,
+ 0xff, 0x02, 0x0f, 0xff, 0xce, 0xf4, 0xf4, 0x00, 0x7d, 0xed, 0x00, 0x0c, 0xce, 0x70, 0xf4, 0x00,
+ 0x9e, 0x66, 0x00, 0x00, 0xce, 0xf4, 0xdd, 0x00, 0x4d, 0x68, 0xf0, 0x00, 0xcd, 0x68, 0xfd, 0x00,
+ 0x9e, 0xde, 0x00, 0x00, 0x9d, 0x62, 0x00, 0x00, 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x82, 0xb8, 0xb8,
+ 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0x8f, 0x98, 0x7f, 0xfd, 0x00, 0x1e,
+ 0x7f, 0xfe, 0xff, 0xe1, 0xe6, 0x00, 0xb8, 0xe9, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x81, 0x01, 0x00,
+ 0xff, 0x89, 0xe8, 0x98, 0xff, 0xc2, 0x00, 0x00, 0xff, 0x89, 0xcd, 0xd0, 0x0f, 0x81, 0x00, 0x20,
+ 0xe0, 0x00, 0xb8, 0xf4, 0xff, 0x89, 0xcd, 0xc0, 0xff, 0x89, 0xcd, 0xc0, 0xff, 0x89, 0xe8, 0x98,
+ 0xff, 0x89, 0xcd, 0xd0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x8f, 0x98, 0x70, 0x7e, 0x00, 0x1e,
+ 0xea, 0x00, 0xb9, 0x30, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x90, 0x48, 0x70, 0x7e, 0x00, 0x1f,
+ 0xea, 0x00, 0xb9, 0x30, 0xff, 0xa2, 0x00, 0x00, 0xe0, 0x00, 0xb9, 0x34, 0xff, 0x89, 0xce, 0x88,
+ 0xf0, 0x09, 0xce, 0x88, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x7d, 0x9d, 0x00, 0x02, 0xfc, 0x0a, 0xa0, 0x14,
+ 0xaf, 0xee, 0xc0, 0x02, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xba, 0x20, 0xfe, 0x02, 0x08, 0x81,
+ 0xff, 0x08, 0xce, 0xc0, 0xfe, 0x88, 0xd3, 0xd8, 0xff, 0x8a, 0xa0, 0x24, 0xab, 0xee, 0xf8, 0x02,
+ 0xcd, 0x7a, 0xe4, 0x00, 0x7b, 0x19, 0x00, 0x18, 0x5c, 0xf8, 0x02, 0x00, 0xe6, 0x00, 0xb9, 0xa1,
+ 0x0e, 0x74, 0x00, 0x08, 0xff, 0x8a, 0xce, 0x90, 0xfe, 0x02, 0x00, 0x02, 0xb3, 0x6e, 0xf8, 0x02,
+ 0xbe, 0x6e, 0xc0, 0x02, 0xfc, 0x89, 0xce, 0xc0, 0xe0, 0x00, 0xba, 0x20, 0x55, 0x29, 0x80, 0x00,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xd8, 0xfd, 0x00, 0x9f, 0xf6, 0x00, 0x0c,
+ 0xff, 0x08, 0x9f, 0xf4, 0xff, 0x73, 0x28, 0x08, 0xfd, 0x77, 0x68, 0x12, 0xfb, 0xf3, 0x68, 0x0b,
+ 0x9d, 0x72, 0x00, 0x0c, 0xfd, 0x73, 0x28, 0x14, 0x93, 0xf6, 0x00, 0x38, 0xf7, 0x82, 0x00, 0x40,
+ 0xf7, 0xf7, 0x68, 0x08, 0x9d, 0x76, 0x00, 0x30, 0xff, 0xf7, 0x18, 0x0a, 0x8f, 0x76, 0x00, 0x2c,
+ 0x9e, 0x02, 0xfe, 0x58, 0x0e, 0x01, 0x10, 0x00, 0x0e, 0x70, 0x00, 0x14, 0x9e, 0x02, 0xfe, 0x58,
+ 0xfe, 0x02, 0xa1, 0xd4, 0x9e, 0x76, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x09, 0xd3, 0xd8,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0xfb, 0x28, 0x00, 0x9f, 0xfa, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0xfd, 0x77, 0x28, 0x02, 0xfe, 0x02, 0x00, 0x01, 0xbe, 0x6e, 0xc0, 0x02,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x8c, 0x9a, 0x00, 0x04, 0xfd, 0x1b, 0x18, 0x00, 0xff, 0x82, 0x07, 0xff,
+ 0x7e, 0xe5, 0x00, 0x16, 0x70, 0x66, 0x00, 0x02, 0x0e, 0xf5, 0xff, 0xc0, 0xea, 0x6c, 0x00, 0x02,
+ 0x7e, 0xf4, 0xff, 0xea, 0x7e, 0x65, 0x00, 0x01, 0xff, 0x02, 0x00, 0x05, 0xcd, 0x68, 0xfc, 0x00,
+ 0xcf, 0x78, 0xda, 0x00, 0x7e, 0x72, 0xff, 0xe1, 0xe6, 0x00, 0xba, 0x75, 0x0e, 0xf4, 0x00, 0x01,
+ 0xcf, 0x78, 0xe8, 0x00, 0x70, 0x66, 0x00, 0x10, 0xea, 0x00, 0xba, 0x85, 0x0f, 0xf8, 0x00, 0x02,
+ 0x0f, 0xf8, 0x00, 0x01, 0xc0, 0x6a, 0xfa, 0x00, 0xe6, 0x00, 0xba, 0x99, 0xf4, 0x02, 0x00, 0x00,
+ 0xe0, 0x00, 0xba, 0xdc, 0xf4, 0x02, 0x00, 0x01, 0xc0, 0x72, 0x42, 0x00, 0xe6, 0x00, 0xba, 0xb5,
+ 0x7f, 0xe5, 0x00, 0x01, 0xff, 0x88, 0x9f, 0xe8, 0xc0, 0x76, 0xfa, 0x00, 0xe2, 0x00, 0xba, 0x90,
+ 0x7f, 0xe5, 0x00, 0x01, 0x7f, 0xfc, 0xff, 0xe7, 0xff, 0x0a, 0xa4, 0x90, 0xae, 0xfa, 0xf8, 0x05,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xba, 0x91, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xce, 0x80,
+ 0x70, 0x7e, 0x00, 0x1c, 0xea, 0x00, 0xba, 0x90, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfe, 0x88, 0x93, 0xe8, 0xff, 0x82, 0x00, 0x1f, 0xcf, 0x9c, 0xfc, 0x00, 0x4e, 0xf4, 0xff, 0xe0,
+ 0xce, 0xf4, 0xfd, 0x00, 0xff, 0x02, 0x00, 0x01, 0xcf, 0x78, 0x3f, 0xc0, 0xff, 0xf6, 0x90, 0x00,
+ 0xc0, 0x7a, 0xfc, 0x00, 0xe6, 0x00, 0xbb, 0x55, 0xfe, 0x89, 0x93, 0xe8, 0x20, 0x1a, 0x00, 0x00,
+ 0xe6, 0x00, 0xbb, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x9a, 0x00, 0x04, 0xff, 0x89, 0x93, 0xf8,
+ 0x8f, 0x9a, 0x00, 0x08, 0xff, 0x89, 0x94, 0x08, 0x8f, 0x9a, 0x00, 0x0c, 0xff, 0x89, 0x94, 0x18,
+ 0x83, 0x1a, 0x00, 0x10, 0xe0, 0x00, 0xbb, 0x54, 0xf3, 0x09, 0x94, 0x28, 0xe0, 0x00, 0xbb, 0x28,
+ 0xf3, 0x0a, 0xa8, 0x68, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xff, 0x88, 0x91, 0x18,
+ 0x20, 0x1e, 0x00, 0x14, 0xe6, 0x78, 0x00, 0x03, 0x5f, 0xfd, 0x00, 0x01, 0x9f, 0x16, 0xff, 0xf4,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xbc, 0x58, 0xff, 0x89, 0x91, 0x18, 0x20, 0x1e, 0x00, 0x1f,
+ 0xe2, 0x70, 0x00, 0x03, 0x20, 0x72, 0x00, 0x00, 0xe6, 0x00, 0xbb, 0xa5, 0x2f, 0x9c, 0x00, 0x20,
+ 0xff, 0x82, 0x00, 0x0d, 0xff, 0x08, 0x93, 0xc8, 0xfd, 0x82, 0x00, 0x01, 0xfe, 0x88, 0x93, 0xd8,
+ 0xcf, 0xec, 0xff, 0xc0, 0xcf, 0x78, 0xfd, 0x00, 0xc0, 0x76, 0xfc, 0x00, 0xe6, 0x00, 0xbc, 0x64,
+ 0xff, 0x09, 0x93, 0xc8, 0x20, 0x72, 0x00, 0x00, 0xe6, 0x00, 0xbb, 0xf5, 0xce, 0xec, 0x3f, 0xc0,
+ 0xff, 0x08, 0x93, 0x98, 0xcf, 0xf8, 0xed, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xbb, 0xf4,
+ 0xff, 0x89, 0x93, 0x98, 0xff, 0x88, 0x93, 0xa8, 0xc0, 0x7e, 0xec, 0x00, 0xe6, 0x00, 0xbc, 0x45,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xf4, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xbc, 0x39,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x91, 0x18, 0x70, 0x7e, 0x00, 0x1c, 0xea, 0x00, 0xbc, 0x64,
+ 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x00, 0xbc, 0x64, 0xf3, 0x02, 0x00, 0x30,
+ 0xf3, 0x82, 0x00, 0x00, 0xf7, 0x82, 0xbc, 0x30, 0xe0, 0x00, 0xb9, 0x40, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xbc, 0x64, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x91, 0x18, 0xe0, 0x00, 0xbc, 0x14,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xbc, 0x50, 0xe0, 0x00, 0xba, 0xe8, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xbb, 0xf4, 0x00, 0x00, 0x00, 0x01, 0x5f, 0xfd, 0x00, 0x08, 0xe0, 0x00, 0xbb, 0x8c,
+ 0xff, 0x89, 0x91, 0x18, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0x20, 0x1e, 0x00, 0x14,
+ 0xe6, 0x7c, 0x00, 0x03, 0xff, 0x08, 0x93, 0xb8, 0xfe, 0x82, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xf4,
+ 0xcf, 0xf4, 0x3f, 0xc0, 0xcf, 0x7a, 0xfc, 0x00, 0xe6, 0x00, 0xbd, 0xed, 0x9f, 0x16, 0xff, 0xec,
+ 0xff, 0x88, 0x91, 0x18, 0xff, 0x02, 0x00, 0x02, 0x9f, 0x16, 0xff, 0xf0, 0x5f, 0xfd, 0x00, 0x04,
+ 0xff, 0x89, 0x91, 0x18, 0x8f, 0x96, 0xff, 0xf4, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xbc, 0xd1,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x91, 0x18, 0x5f, 0xfd, 0x00, 0x08, 0xff, 0x89, 0x91, 0x18,
+ 0xff, 0x88, 0x93, 0x98, 0xff, 0x02, 0x00, 0x01, 0xfe, 0x88, 0x93, 0xa8, 0x20, 0x7e, 0x00, 0x00,
+ 0xcf, 0x78, 0x3f, 0xc0, 0xe6, 0x70, 0x00, 0x03, 0xcf, 0xfc, 0xf5, 0x00, 0xc0, 0x76, 0xf4, 0x00,
+ 0xe6, 0x00, 0xbd, 0xfc, 0xff, 0x89, 0x93, 0x98, 0x20, 0x72, 0x00, 0x00, 0xe6, 0x00, 0xbd, 0xd8,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xf4, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xbd, 0xcd,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x91, 0x18, 0x70, 0x7e, 0x00, 0x1c, 0xea, 0x00, 0xbd, 0xcd,
+ 0x00, 0x00, 0x00, 0x01, 0xfe, 0x08, 0x8f, 0x98, 0x70, 0x72, 0x00, 0x17, 0xea, 0x00, 0xbd, 0xfc,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xec, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xbd, 0xa9,
+ 0x00, 0x00, 0x00, 0x01, 0x70, 0x72, 0x00, 0x17, 0xea, 0x00, 0xbd, 0x61, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0x91, 0x18, 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x00, 0xbd, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x16, 0xff, 0xf0, 0x7f, 0xf9, 0x00, 0x02, 0xff, 0x0a, 0xa0, 0x14, 0xae, 0xfe, 0xf0, 0x02,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xbd, 0x8c, 0x00, 0x00, 0x00, 0x01, 0x70, 0x72, 0x00, 0x17,
+ 0xea, 0x00, 0xbd, 0x8c, 0x5f, 0xf1, 0x40, 0x00, 0xff, 0x89, 0x8f, 0x98, 0x83, 0x96, 0xff, 0xf0,
+ 0xf3, 0x02, 0x00, 0x30, 0xf7, 0x82, 0xbd, 0xa0, 0xe0, 0x00, 0xb9, 0x40, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xbd, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x70, 0x72, 0x00, 0x17, 0xea, 0x00, 0xbd, 0x61,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x91, 0x18, 0x70, 0x7e, 0x00, 0x1e, 0xea, 0x00, 0xbd, 0xfc,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xbd, 0x60, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x08, 0x8f, 0x98,
+ 0xe0, 0x00, 0xbd, 0x34, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xbd, 0xe4, 0xe0, 0x00, 0xba, 0xe8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xbd, 0x04, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x91, 0x18,
+ 0x9e, 0x96, 0xff, 0xf0, 0xe0, 0x00, 0xbc, 0xb0, 0x5f, 0xfd, 0x00, 0x02, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x82, 0x00, 0x01, 0xcf, 0x1c, 0x00, 0x00, 0xce, 0xfc, 0x3f, 0xc0, 0x20, 0x1e, 0x00, 0x1f,
+ 0xe2, 0x00, 0xbe, 0x5c, 0xce, 0x18, 0x00, 0x00, 0xff, 0x88, 0x93, 0xb8, 0xc0, 0x7e, 0xec, 0x00,
+ 0xe6, 0x00, 0xbe, 0x40, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xbe, 0x5c, 0x00, 0x00, 0x00, 0x01,
+ 0xc3, 0x70, 0x00, 0x00, 0xc3, 0xf8, 0x00, 0x00, 0xf7, 0x82, 0xbe, 0x54, 0xe0, 0x00, 0xbc, 0x70,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xbe, 0x68, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xbe, 0x68,
+ 0xe0, 0x00, 0xbb, 0x60, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x14,
+ 0x0f, 0x01, 0x80, 0x00, 0x9f, 0x02, 0xff, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x02, 0x00, 0x02,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0xbe, 0xb0, 0xe0, 0x00, 0x7d, 0x14, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x83, 0x1a, 0x42, 0x8f, 0x02, 0xff, 0xd0, 0x4f, 0xfd, 0x00, 0x00, 0x9f, 0x16, 0xff, 0xe8,
+ 0x9f, 0x96, 0xff, 0xec, 0x8f, 0x82, 0xff, 0xd0, 0x8f, 0x16, 0xff, 0xec, 0xf3, 0x02, 0x00, 0x07,
+ 0x9f, 0x96, 0xff, 0xe4, 0x9f, 0x16, 0xff, 0xf0, 0xf7, 0x82, 0xbe, 0xe4, 0xe0, 0x00, 0x2e, 0xc0,
+ 0x97, 0x93, 0xff, 0xfc, 0x94, 0x16, 0xff, 0xf4, 0x8f, 0x82, 0xff, 0xd0, 0x8f, 0x16, 0xff, 0xe4,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x20, 0x7e, 0x00, 0x01, 0xe2, 0x00, 0xbe, 0xe9, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x83, 0x1a, 0x42, 0xf3, 0x02, 0x00, 0x02, 0xf3, 0x82, 0x00, 0x01, 0x4f, 0xfd, 0x00, 0x00,
+ 0x9f, 0x96, 0xff, 0xec, 0xf7, 0x82, 0xbf, 0x20, 0xe0, 0x00, 0x7d, 0x14, 0x97, 0x93, 0xff, 0xfc,
+ 0x70, 0x22, 0x00, 0x19, 0xea, 0x00, 0xbf, 0xb1, 0x0f, 0x81, 0x80, 0x00, 0x8f, 0x96, 0xff, 0xf0,
+ 0x8f, 0x16, 0xff, 0xec, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x00, 0xbf, 0x61, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xff, 0xd0, 0x8f, 0x16, 0xff, 0xe8, 0xcf, 0xfc, 0xf2, 0x00, 0x20, 0x7e, 0x00, 0x0c,
+ 0xe2, 0x00, 0xbe, 0xc5, 0x0f, 0x81, 0x80, 0x00, 0xe0, 0x00, 0xbf, 0xb4, 0x0f, 0xfc, 0x00, 0x43,
+ 0x70, 0x22, 0x00, 0x18, 0xea, 0x00, 0xbf, 0x41, 0xff, 0x0a, 0x00, 0x00, 0x8f, 0x82, 0xff, 0xf8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0xbf, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xf4,
+ 0x5f, 0xf9, 0x10, 0x00, 0x9f, 0x82, 0xff, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0a, 0x00, 0x00,
+ 0x8f, 0x82, 0xff, 0xf8, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0xbf, 0xa0, 0x0f, 0x81, 0x80, 0x00,
+ 0x0f, 0xfc, 0x00, 0x43, 0x9f, 0x82, 0xff, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf3, 0x76, 0xff, 0xbc, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0xbf, 0xf4, 0xe0, 0x00, 0x28, 0x78,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xa5, 0x74, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xc0, 0x40,
+ 0xff, 0xf6, 0xff, 0xb4, 0x8e, 0xfe, 0x00, 0x00, 0xff, 0x76, 0xff, 0xb8, 0x8e, 0x7a, 0x00, 0x00,
+ 0x7f, 0xf5, 0x00, 0x1a, 0x7f, 0xfc, 0xff, 0xf0, 0x7e, 0x70, 0xff, 0xea, 0xce, 0x70, 0xf8, 0x00,
+ 0xff, 0x08, 0xa0, 0x3c, 0xff, 0x88, 0xa0, 0x40, 0x7e, 0xf5, 0x00, 0x0a, 0x7e, 0xf4, 0xff, 0xf0,
+ 0xcf, 0x78, 0xe8, 0x00, 0xcf, 0xfc, 0xe0, 0x00, 0xff, 0x09, 0xa0, 0x3c, 0xff, 0x89, 0xa0, 0x40,
+ 0xff, 0x83, 0x5b, 0xe8, 0xff, 0x02, 0x00, 0x06, 0x7f, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xe8,
+ 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x00, 0xc1, 0x89, 0xfe, 0xf6, 0xff, 0xa8, 0x8f, 0x76, 0x00, 0x00,
+ 0x7f, 0xf9, 0x00, 0x1a, 0x7e, 0xfe, 0xff, 0xe1, 0xe6, 0x00, 0xc1, 0x54, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xa0, 0x54, 0x7f, 0x79, 0x00, 0x12, 0x7f, 0x78, 0xff, 0xe8, 0xcf, 0xfc, 0xf0, 0x00,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xc1, 0x34, 0xff, 0x89, 0xa0, 0x54, 0xff, 0xf6, 0xff, 0xac,
+ 0x8f, 0x7e, 0x00, 0x00, 0x70, 0x7a, 0x00, 0x03, 0xea, 0x00, 0xc0, 0xd4, 0xfe, 0xf6, 0xff, 0xa8,
+ 0x8f, 0xf6, 0x00, 0x00, 0x7f, 0x78, 0xff, 0xe3, 0x7f, 0xfd, 0x00, 0x1b, 0x7f, 0xfc, 0xff, 0xe8,
+ 0xcf, 0x78, 0xf8, 0x00, 0x20, 0x7a, 0x00, 0x03, 0xe6, 0x00, 0xc1, 0x25, 0x00, 0x00, 0x00, 0x01,
+ 0xe2, 0x00, 0xc0, 0xf4, 0x20, 0x7a, 0x00, 0x0f, 0x20, 0x7a, 0x00, 0x01, 0xe6, 0x00, 0xc0, 0xe5,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x91, 0x38, 0x4f, 0xfd, 0xfc, 0x0f, 0xe0, 0x00, 0xc1, 0x88,
+ 0xff, 0x89, 0x91, 0x38, 0xff, 0x88, 0x91, 0x38, 0x4f, 0xfd, 0xfc, 0x0f, 0xe0, 0x00, 0xc0, 0xdc,
+ 0x5f, 0xfd, 0x00, 0x10, 0xe6, 0x00, 0xc1, 0x15, 0x20, 0x7a, 0x00, 0xff, 0xe6, 0x00, 0xc0, 0xd4,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x91, 0x38, 0x4f, 0xfd, 0xfc, 0x0f, 0xe0, 0x00, 0xc0, 0xdc,
+ 0x5f, 0xfd, 0x00, 0x80, 0xff, 0x88, 0x91, 0x38, 0x4f, 0xfd, 0xfc, 0x0f, 0xe0, 0x00, 0xc0, 0xdc,
+ 0x5f, 0xfd, 0x00, 0x40, 0xff, 0x88, 0x91, 0x38, 0x4f, 0xfd, 0xfc, 0x0f, 0xe0, 0x00, 0xc0, 0xdc,
+ 0x5f, 0xfd, 0x00, 0x20, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x20, 0xc4, 0x18, 0x00, 0x00,
+ 0xf7, 0x82, 0xc1, 0x4c, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xc0, 0x90,
+ 0xff, 0xf6, 0xff, 0xac, 0xff, 0x88, 0xa0, 0x44, 0xff, 0x0a, 0xa5, 0xa0, 0xf7, 0x82, 0x00, 0x01,
+ 0xf7, 0xfb, 0x68, 0x9a, 0xcf, 0xfc, 0xe8, 0x00, 0xff, 0x89, 0xa0, 0x44, 0xf7, 0x82, 0xc1, 0x78,
+ 0xe0, 0x00, 0xbe, 0x74, 0x97, 0x93, 0xff, 0xfc, 0xff, 0xf6, 0xff, 0xa8, 0x8f, 0x7e, 0x00, 0x00,
+ 0xe0, 0x00, 0xc0, 0x70, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10,
+ 0x8d, 0x1a, 0x00, 0x04, 0xff, 0x08, 0x9f, 0xfc, 0x0e, 0x81, 0x00, 0x70, 0x7f, 0xe9, 0x00, 0x03,
+ 0x7f, 0xfc, 0xff, 0xe5, 0x20, 0x7e, 0x00, 0x01, 0xce, 0xe8, 0xec, 0x00, 0x7f, 0x79, 0x00, 0x0f,
+ 0xff, 0x82, 0x30, 0x00, 0xcf, 0xe8, 0xfc, 0x00, 0xce, 0xf4, 0xf5, 0x00, 0xce, 0xf4, 0xfd, 0x00,
+ 0xe2, 0x24, 0x00, 0x03, 0x7f, 0xe9, 0x00, 0x16, 0xcc, 0x98, 0x00, 0x00, 0x93, 0x96, 0xff, 0xf4,
+ 0x7f, 0xfc, 0xff, 0xea, 0x20, 0x26, 0x00, 0x00, 0xe6, 0x00, 0xc3, 0x0d, 0x5c, 0x75, 0x0a, 0x00,
+ 0xfe, 0x67, 0x58, 0x0b, 0xff, 0x02, 0x38, 0x60, 0x83, 0x1a, 0x00, 0x08, 0xad, 0xfa, 0xe0, 0x05,
+ 0x2f, 0xfc, 0x00, 0x01, 0x7e, 0x99, 0x00, 0x1c, 0x7f, 0xfd, 0x00, 0x16, 0x7e, 0xf4, 0xff, 0xe4,
+ 0xff, 0x02, 0x39, 0x60, 0x7f, 0xfc, 0xff, 0xec, 0xa3, 0xfa, 0xe8, 0x05, 0xcf, 0xfc, 0xda, 0x00,
+ 0x70, 0x6a, 0x00, 0x02, 0xea, 0x00, 0xc3, 0x00, 0x04, 0x7c, 0x00, 0x04, 0x8f, 0xe6, 0x00, 0x10,
+ 0x4f, 0xfc, 0xff, 0xfc, 0xc3, 0xfc, 0x38, 0x00, 0x8f, 0x96, 0xff, 0xf4, 0x22, 0x10, 0x00, 0x08,
+ 0x9c, 0x12, 0x00, 0x00, 0x9f, 0x92, 0x00, 0x04, 0x9c, 0x96, 0xff, 0xf0, 0x73, 0x18, 0xff, 0xf8,
+ 0xf7, 0x82, 0xc2, 0x5c, 0xe0, 0x00, 0xa4, 0x44, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4,
+ 0x8c, 0x96, 0xff, 0xf0, 0x20, 0x7e, 0x00, 0x04, 0xe6, 0x00, 0xc2, 0xc9, 0x02, 0x10, 0x00, 0x08,
+ 0x8f, 0x96, 0xff, 0xf4, 0x20, 0x7e, 0x00, 0x01, 0xe6, 0x00, 0xc2, 0x99, 0x03, 0x01, 0xe1, 0x00,
+ 0x03, 0x18, 0x0e, 0xc5, 0xf7, 0x82, 0xc2, 0x90, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xc3, 0x1c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa5, 0x70, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0xc3, 0x1c, 0xc3, 0x64, 0x00, 0x00, 0x84, 0x16, 0xff, 0xf4, 0xf3, 0x82, 0x00, 0x14,
+ 0xf7, 0x82, 0xc2, 0xbc, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf4,
+ 0xe0, 0x00, 0xc3, 0x1c, 0xff, 0x89, 0xa5, 0x70, 0xff, 0x88, 0x8f, 0x98, 0xff, 0x08, 0xa5, 0x70,
+ 0x5f, 0xfd, 0x08, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xc3, 0x1c, 0xff, 0x89, 0x8f, 0x98,
+ 0xc3, 0x64, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x0f, 0xf4, 0x02, 0x00, 0x01, 0xf7, 0x82, 0xc2, 0xf8,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xc2, 0xc0, 0xff, 0x82, 0x00, 0x01,
+ 0x8f, 0xe6, 0x00, 0x0c, 0xe0, 0x00, 0xc2, 0x34, 0x4f, 0xfc, 0xff, 0xfc, 0x83, 0x1a, 0x00, 0x08,
+ 0xf4, 0x02, 0x00, 0x04, 0xe0, 0x00, 0xc2, 0x38, 0xc3, 0xa4, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x08, 0x90, 0x48, 0xfc, 0x82, 0x00, 0x00, 0xfe, 0x88, 0xce, 0x88, 0x7f, 0x78, 0xff, 0xed,
+ 0x7f, 0x79, 0x00, 0x13, 0xcf, 0xf8, 0x00, 0x00, 0xcf, 0x64, 0x00, 0x00, 0xcd, 0x9e, 0xfa, 0x00,
+ 0xcd, 0x18, 0xf3, 0x00, 0xce, 0x64, 0x00, 0x00, 0xc0, 0x6e, 0xea, 0x00, 0xc0, 0x6a, 0xe3, 0x00,
+ 0xe4, 0x20, 0x00, 0x02, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x08, 0x8f, 0xc8, 0xff, 0x88, 0x8f, 0xd8,
+ 0xfc, 0x82, 0x00, 0x00, 0x7e, 0x70, 0xff, 0xe8, 0x7e, 0x71, 0x00, 0x18, 0xcf, 0x7c, 0x00, 0x00,
+ 0xce, 0xf0, 0x00, 0x00, 0xcf, 0xe4, 0x00, 0x00, 0xce, 0x64, 0x00, 0x00, 0xcd, 0xfe, 0xe8, 0x00,
+ 0xcd, 0x78, 0xe1, 0x00, 0xff, 0x88, 0xe8, 0x98, 0xce, 0x9e, 0xda, 0x00, 0xce, 0x18, 0xd3, 0x00,
+ 0xcf, 0x64, 0x00, 0x00, 0xc0, 0x76, 0xfa, 0x00, 0xc0, 0x72, 0xf3, 0x00, 0xe4, 0x20, 0x00, 0x02,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfe, 0x08, 0x8f, 0xe8, 0xff, 0x88, 0x8f, 0xf8, 0xfc, 0x82, 0x00, 0x00,
+ 0x7e, 0x70, 0xff, 0xec, 0x7e, 0x71, 0x00, 0x14, 0xcf, 0x7c, 0x00, 0x00, 0xce, 0xf0, 0x00, 0x00,
+ 0xcf, 0xe4, 0x00, 0x00, 0xce, 0x64, 0x00, 0x00, 0xcd, 0xfe, 0xe8, 0x00, 0xcd, 0x78, 0xe1, 0x00,
+ 0xff, 0x88, 0xcd, 0xd0, 0xce, 0x9e, 0xda, 0x00, 0xce, 0x18, 0xd3, 0x00, 0xcf, 0x64, 0x00, 0x00,
+ 0xc0, 0x76, 0xfa, 0x00, 0xc0, 0x72, 0xf3, 0x00, 0xe4, 0x20, 0x00, 0x02, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfe, 0x08, 0x8f, 0xc8, 0xff, 0x88, 0x8f, 0xd8, 0xfc, 0x82, 0x00, 0x00, 0x7e, 0x70, 0xff, 0xe8,
+ 0x7e, 0x71, 0x00, 0x18, 0xcf, 0x7c, 0x00, 0x00, 0xce, 0xf0, 0x00, 0x00, 0xcf, 0xe4, 0x00, 0x00,
+ 0xce, 0x64, 0x00, 0x00, 0xcd, 0xfe, 0xe8, 0x00, 0xcd, 0x78, 0xe1, 0x00, 0xff, 0x88, 0xcd, 0xc0,
+ 0xce, 0x9e, 0xda, 0x00, 0xce, 0x18, 0xd3, 0x00, 0xcf, 0x64, 0x00, 0x00, 0xc0, 0x76, 0xfa, 0x00,
+ 0xc0, 0x72, 0xf3, 0x00, 0xe4, 0x20, 0x00, 0x02, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0x9f, 0xf4,
+ 0xcf, 0x18, 0x00, 0x00, 0x0e, 0x81, 0xe0, 0x00, 0x7e, 0x19, 0x00, 0x0d, 0xfd, 0xf6, 0xff, 0xf0,
+ 0x0e, 0xf4, 0x1f, 0xff, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x00, 0xc4, 0xf1, 0xf3, 0x76, 0xff, 0xfc,
+ 0xff, 0x82, 0x00, 0x01, 0xff, 0x89, 0x9f, 0xf0, 0xff, 0x09, 0x9f, 0xf4, 0x8f, 0xee, 0x00, 0x00,
+ 0x5f, 0xfc, 0x10, 0x00, 0xcf, 0xfc, 0xec, 0x00, 0xcf, 0xfc, 0xe5, 0x00, 0x9f, 0xee, 0x00, 0x00,
+ 0xf7, 0x82, 0xc4, 0xdc, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xce, 0xc0,
+ 0x55, 0x29, 0x80, 0x00, 0x5f, 0xfc, 0x00, 0x10, 0xe0, 0x00, 0xc5, 0x00, 0xff, 0x89, 0xce, 0xc0,
+ 0xff, 0x88, 0x9f, 0xf0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xc4, 0xb5, 0xff, 0x82, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xa0, 0x80, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x00, 0xc5, 0x39,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xce, 0xc0, 0xf3, 0x09, 0xa0, 0x80, 0x55, 0x29, 0x80, 0x00,
+ 0x5f, 0xfc, 0x00, 0x20, 0xff, 0x89, 0xce, 0xc0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x65, 0x78, 0x74, 0x20,
+ 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x61, 0x74, 0x20, 0x25, 0x70, 0x0a, 0x00, 0x52, 0x65, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x54, 0x75, 0x72, 0x6e, 0x2d, 0x6f, 0x66, 0x66, 0x20, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x00, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x20, 0x20, 0x44, 0x33, 0x5f, 0x68, 0x6f, 0x74, 0x2d, 0x3e, 0x44, 0x30, 0x0a, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x80, 0x8f, 0x9a, 0x00, 0x04,
+ 0xcd, 0x18, 0x00, 0x00, 0x7f, 0x7d, 0x00, 0x16, 0x7e, 0xfd, 0x00, 0x11, 0x7f, 0xfd, 0x00, 0x01,
+ 0x0f, 0x79, 0xff, 0xc0, 0x7b, 0x7e, 0xff, 0xe1, 0x7f, 0x78, 0xff, 0xea, 0x0f, 0x78, 0x00, 0x01,
+ 0x7e, 0xf4, 0xff, 0xe1, 0x7f, 0xfc, 0xff, 0xe7, 0x9f, 0x16, 0xff, 0xd8, 0x9e, 0x96, 0xff, 0xd0,
+ 0x9b, 0x16, 0xff, 0xd4, 0xe6, 0x00, 0xf5, 0x29, 0x9f, 0x96, 0xff, 0xdc, 0x9f, 0x16, 0xff, 0xcc,
+ 0xff, 0xfa, 0x7f, 0xf0, 0xc0, 0x6a, 0xfa, 0x00, 0xe6, 0x00, 0xf5, 0x09, 0x9d, 0x16, 0xff, 0xc8,
+ 0xf0, 0x09, 0xa5, 0x70, 0x8f, 0xea, 0x00, 0x04, 0x70, 0x7e, 0x00, 0x10, 0xea, 0x00, 0xc6, 0x3c,
+ 0xc3, 0x68, 0x00, 0x00, 0xff, 0xeb, 0x18, 0x00, 0xff, 0x02, 0x07, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0xcf, 0xfc, 0xd0, 0x00, 0x8f, 0x7e, 0xff, 0xf8, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0xc6, 0x3d, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x93, 0xe8, 0x70, 0x7e, 0x00, 0x17,
+ 0xea, 0x00, 0xf4, 0xe5, 0xf4, 0x02, 0x00, 0x00, 0xc3, 0x68, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x82, 0xc6, 0x4c, 0xe0, 0x00, 0xba, 0x2c, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xf0, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xdc,
+ 0x20, 0x7e, 0x00, 0x77, 0xe2, 0x00, 0xec, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x02, 0xc6, 0x7c,
+ 0xae, 0xfe, 0xf0, 0x02, 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc8, 0x5c,
+ 0x00, 0x00, 0xf1, 0x5c, 0x00, 0x00, 0xf1, 0x5c, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xf1, 0x68,
+ 0x00, 0x00, 0xf1, 0x68, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xf4, 0xd8, 0x00, 0x00, 0xf4, 0xd8, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xc8, 0x5c,
+ 0x00, 0x00, 0xf1, 0x5c, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0xb4,
+ 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0xec, 0xb4,
+ 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xc8, 0x5c,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xf1, 0x5c, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xf1, 0x68,
+ 0x00, 0x00, 0xf1, 0x68, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xf4, 0xd8, 0x00, 0x00, 0xf4, 0xd8, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xc8, 0x5c,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xec, 0xbc,
+ 0x00, 0x00, 0xec, 0xbc, 0x00, 0x00, 0xec, 0xbc, 0x00, 0x00, 0xec, 0xbc, 0x00, 0x00, 0xec, 0xbc,
+ 0x00, 0x00, 0xec, 0xbc, 0x00, 0x00, 0xec, 0xbc, 0x00, 0x00, 0xec, 0xbc, 0x8b, 0x6a, 0x00, 0x08,
+ 0x9b, 0x16, 0xff, 0x98, 0x8c, 0xea, 0x00, 0x04, 0x7f, 0xd9, 0x00, 0x18, 0x7c, 0x7c, 0xff, 0xe4,
+ 0x7f, 0x59, 0x00, 0x1c, 0x7e, 0xe5, 0x00, 0x02, 0x7f, 0xfc, 0xff, 0xe8, 0x74, 0x78, 0xff, 0xe4,
+ 0x7e, 0xf6, 0xff, 0xe1, 0xe6, 0x00, 0xec, 0x91, 0x9f, 0x96, 0xff, 0xbc, 0x8e, 0xea, 0x00, 0x0c,
+ 0x8d, 0xea, 0x00, 0x10, 0xce, 0x74, 0x00, 0x00, 0x4d, 0xec, 0xff, 0xfc, 0xfe, 0x82, 0x00, 0x00,
+ 0xcf, 0xec, 0x00, 0x00, 0xcf, 0x74, 0x00, 0x00, 0xcb, 0xf6, 0xf8, 0x00, 0xcb, 0x70, 0xf1, 0x00,
+ 0x9d, 0x96, 0xff, 0xc4, 0xce, 0x5c, 0x00, 0x00, 0xcd, 0xd8, 0x00, 0x00, 0x8b, 0x96, 0xff, 0xc8,
+ 0x0b, 0xdc, 0x00, 0x14, 0x9b, 0x96, 0xff, 0xc0, 0xff, 0x82, 0x7c, 0xbc, 0xff, 0x02, 0x7c, 0xac,
+ 0x8b, 0x16, 0xff, 0xd8, 0xaf, 0xfe, 0x40, 0x05, 0xaf, 0x7a, 0xc0, 0x05, 0x20, 0x5a, 0x00, 0x01,
+ 0xe2, 0x00, 0xc8, 0xf9, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xec, 0x01, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x00, 0xec, 0x01, 0x00, 0x00, 0x00, 0x01, 0x8b, 0x96, 0xff, 0xd8, 0x20, 0x5e, 0x00, 0x01,
+ 0xe6, 0x00, 0xec, 0x7d, 0x20, 0x7e, 0x00, 0xff, 0xe6, 0x00, 0xec, 0x4d, 0x00, 0x00, 0x00, 0x01,
+ 0x20, 0x7a, 0x00, 0xff, 0xe6, 0x00, 0xeb, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xbc,
+ 0xff, 0x82, 0x38, 0x60, 0xc3, 0xf0, 0x00, 0x00, 0xc3, 0x6c, 0x00, 0x00, 0xae, 0xfe, 0xf0, 0x05,
+ 0x8f, 0x96, 0xff, 0xd8, 0xff, 0x02, 0x39, 0x60, 0xaf, 0x7a, 0x40, 0x05, 0x7f, 0xfd, 0x00, 0x02,
+ 0xce, 0xfc, 0xea, 0x00, 0x9c, 0x96, 0xff, 0x90, 0x9d, 0x16, 0xff, 0x8c, 0x9d, 0x96, 0xff, 0x88,
+ 0x9e, 0x16, 0xff, 0x84, 0x9f, 0x16, 0xff, 0xb0, 0x9f, 0x96, 0xff, 0xac, 0x9e, 0x96, 0xff, 0xb4,
+ 0xf7, 0x82, 0xc9, 0x6c, 0xe0, 0x00, 0xc3, 0x70, 0x97, 0x93, 0xff, 0xfc, 0x8b, 0x16, 0xff, 0xc4,
+ 0x8b, 0x96, 0xff, 0xb0, 0x8c, 0x96, 0xff, 0x90, 0x4c, 0x59, 0x00, 0x1f, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8d, 0x96, 0xff, 0x88, 0x8e, 0x16, 0xff, 0x84, 0xcb, 0xe0, 0xb8, 0x00, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xe9, 0x99, 0x9b, 0x96, 0xff, 0xb8, 0x8e, 0x96, 0xff, 0xd4, 0x20, 0x76, 0x00, 0x00,
+ 0xe6, 0x00, 0xca, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x8b, 0x16, 0xff, 0xd8, 0x20, 0x5a, 0x00, 0x20,
+ 0xe2, 0x00, 0xca, 0xc8, 0xc3, 0x68, 0x00, 0x00, 0x9c, 0x96, 0xff, 0x90, 0x9d, 0x16, 0xff, 0x8c,
+ 0xc3, 0xf0, 0x00, 0x00, 0xc3, 0x6c, 0x00, 0x00, 0xf7, 0x82, 0xc9, 0xd4, 0xe0, 0x00, 0xc4, 0x28,
+ 0x97, 0x93, 0xff, 0xfc, 0x8c, 0x96, 0xff, 0x90, 0x8d, 0x16, 0xff, 0x8c, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xca, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa0, 0x64, 0x0f, 0xfc, 0x00, 0x01,
+ 0xff, 0x89, 0xa0, 0x64, 0x8c, 0xea, 0x00, 0x04, 0x8b, 0xea, 0x00, 0x08, 0x9b, 0x96, 0xff, 0x98,
+ 0xff, 0x88, 0x9f, 0xfc, 0x0e, 0x81, 0x00, 0x70, 0xce, 0xe4, 0xec, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xce, 0xf4, 0xfd, 0x00, 0xff, 0x02, 0x30, 0x00, 0xcf, 0x64, 0xf4, 0x00, 0x7f, 0xe5, 0x00, 0x16,
+ 0xce, 0xf4, 0xf5, 0x00, 0x7f, 0xfc, 0xff, 0xea, 0xce, 0xf4, 0xfd, 0x00, 0x8f, 0x16, 0xff, 0x98,
+ 0x8f, 0x96, 0xff, 0xd4, 0x83, 0x96, 0xff, 0xb8, 0x84, 0x16, 0xff, 0xb4, 0x22, 0x10, 0x00, 0x08,
+ 0x5e, 0xf5, 0x4a, 0x00, 0x9e, 0x92, 0x00, 0x00, 0x9f, 0x92, 0x00, 0x04, 0x9d, 0x16, 0xff, 0x8c,
+ 0x73, 0x78, 0xff, 0xf8, 0xf4, 0x82, 0x00, 0x01, 0xf7, 0x82, 0xca, 0x64, 0xe0, 0x00, 0xa4, 0x44,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x02, 0x10, 0x00, 0x08, 0x8c, 0xea, 0x00, 0x04,
+ 0xff, 0x02, 0x00, 0x00, 0x9f, 0x16, 0xff, 0xcc, 0x70, 0x66, 0x00, 0x11, 0xea, 0x00, 0xca, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xcc, 0x20, 0x7e, 0x00, 0x00, 0xff, 0x88, 0xa5, 0x70,
+ 0xe6, 0x20, 0x00, 0x03, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xca, 0xad, 0xc3, 0x68, 0x00, 0x00,
+ 0x84, 0x16, 0xff, 0xcc, 0xe0, 0x00, 0xf5, 0x34, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x0c,
+ 0xf7, 0x82, 0xca, 0xbc, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xfb, 0x02, 0x00, 0x01,
+ 0xe0, 0x00, 0xca, 0xa0, 0xfb, 0x09, 0xa5, 0x70, 0xf3, 0x82, 0x00, 0x04, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x82, 0xca, 0xdc, 0xe0, 0x00, 0xc1, 0x94, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0xe0, 0x00, 0xca, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xd0, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0xcb, 0x31, 0x00, 0x00, 0x00, 0x01, 0xf4, 0x08, 0xa5, 0x70, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xca, 0x78, 0xc3, 0x68, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x14, 0xf7, 0x82, 0xcb, 0x18,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xff, 0x82, 0x00, 0x01,
+ 0xff, 0x89, 0xa5, 0x70, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x8b, 0x16, 0xff, 0xd8, 0x20, 0x5a, 0x00, 0x01, 0xe6, 0x00, 0xe9, 0x81, 0x00, 0x00, 0x00, 0x01,
+ 0x9c, 0x16, 0xff, 0x94, 0x9c, 0x96, 0xff, 0x90, 0x9d, 0x16, 0xff, 0x8c, 0xc3, 0xf0, 0x00, 0x00,
+ 0xc3, 0x6c, 0x00, 0x00, 0xf7, 0x82, 0xcb, 0x60, 0xe0, 0x00, 0xc4, 0x28, 0x97, 0x93, 0xff, 0xfc,
+ 0x8c, 0x16, 0xff, 0x94, 0x8c, 0x96, 0xff, 0x90, 0x8d, 0x16, 0xff, 0x8c, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xe9, 0x15, 0xff, 0x02, 0xc5, 0x44, 0x8e, 0x96, 0xff, 0xd8, 0x20, 0x76, 0x00, 0x02,
+ 0xe2, 0x00, 0xe8, 0xe0, 0xff, 0xfa, 0x7f, 0xff, 0x8f, 0x16, 0xff, 0xc0, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe2, 0x00, 0xcb, 0x9d, 0x2f, 0x78, 0x80, 0x00, 0x9f, 0x16, 0xff, 0xc0, 0x8f, 0x96, 0xff, 0xc0,
+ 0x8b, 0x16, 0xff, 0xbc, 0x8d, 0xfe, 0x00, 0x04, 0x83, 0xfe, 0x00, 0x00, 0x20, 0x5a, 0x00, 0xff,
+ 0xe2, 0x00, 0xca, 0x78, 0x7f, 0xd9, 0x00, 0x02, 0xff, 0x02, 0xcb, 0xc8, 0xae, 0xfe, 0xf0, 0x02,
+ 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xca, 0x78, 0x00, 0x00, 0xcf, 0xdc,
+ 0x00, 0x00, 0xcf, 0xf0, 0x00, 0x00, 0xd0, 0x04, 0x00, 0x00, 0xd0, 0x18, 0x00, 0x00, 0xd0, 0x2c,
+ 0x00, 0x00, 0xd0, 0x48, 0x00, 0x00, 0xd0, 0x64, 0x00, 0x00, 0xd0, 0x80, 0x00, 0x00, 0xd0, 0x90,
+ 0x00, 0x00, 0xd0, 0xa8, 0x00, 0x00, 0xd0, 0xc0, 0x00, 0x00, 0xd0, 0xc8, 0x00, 0x00, 0xd0, 0xd8,
+ 0x00, 0x00, 0xd0, 0xe0, 0x00, 0x00, 0xd0, 0xe8, 0x00, 0x00, 0xd0, 0xf8, 0x00, 0x00, 0xd1, 0x0c,
+ 0x00, 0x00, 0xd1, 0x28, 0x00, 0x00, 0xd1, 0x44, 0x00, 0x00, 0xd1, 0x60, 0x00, 0x00, 0xd1, 0x7c,
+ 0x00, 0x00, 0xd1, 0xa0, 0x00, 0x00, 0xd1, 0xc4, 0x00, 0x00, 0xd1, 0xe8, 0x00, 0x00, 0xd2, 0x00,
+ 0x00, 0x00, 0xd2, 0x20, 0x00, 0x00, 0xd2, 0x40, 0x00, 0x00, 0xd2, 0x48, 0x00, 0x00, 0xd2, 0x60,
+ 0x00, 0x00, 0xd2, 0x68, 0x00, 0x00, 0xd2, 0x70, 0x00, 0x00, 0xd2, 0x78, 0x00, 0x00, 0xd2, 0x8c,
+ 0x00, 0x00, 0xd2, 0xa8, 0x00, 0x00, 0xd2, 0xc4, 0x00, 0x00, 0xd2, 0xe0, 0x00, 0x00, 0xd2, 0xfc,
+ 0x00, 0x00, 0xd3, 0x20, 0x00, 0x00, 0xd3, 0x44, 0x00, 0x00, 0xd3, 0x68, 0x00, 0x00, 0xd3, 0x80,
+ 0x00, 0x00, 0xd3, 0xa0, 0x00, 0x00, 0xd3, 0xc0, 0x00, 0x00, 0xd3, 0xc8, 0x00, 0x00, 0xd3, 0xe0,
+ 0x00, 0x00, 0xd3, 0xe8, 0x00, 0x00, 0xd3, 0xf0, 0x00, 0x00, 0xd3, 0xf8, 0x00, 0x00, 0xd4, 0x0c,
+ 0x00, 0x00, 0xd4, 0x28, 0x00, 0x00, 0xd4, 0x44, 0x00, 0x00, 0xd4, 0x60, 0x00, 0x00, 0xd4, 0x7c,
+ 0x00, 0x00, 0xd4, 0xa0, 0x00, 0x00, 0xd4, 0xc4, 0x00, 0x00, 0xd4, 0xe8, 0x00, 0x00, 0xd5, 0x00,
+ 0x00, 0x00, 0xd5, 0x20, 0x00, 0x00, 0xd5, 0x40, 0x00, 0x00, 0xd5, 0x48, 0x00, 0x00, 0xd5, 0x60,
+ 0x00, 0x00, 0xd5, 0x68, 0x00, 0x00, 0xd5, 0x70, 0x00, 0x00, 0xd5, 0x78, 0x00, 0x00, 0xd5, 0x8c,
+ 0x00, 0x00, 0xd5, 0xa8, 0x00, 0x00, 0xd5, 0xc4, 0x00, 0x00, 0xd5, 0xe0, 0x00, 0x00, 0xd5, 0xfc,
+ 0x00, 0x00, 0xd6, 0x20, 0x00, 0x00, 0xd6, 0x44, 0x00, 0x00, 0xd6, 0x68, 0x00, 0x00, 0xd6, 0x80,
+ 0x00, 0x00, 0xd6, 0xa0, 0x00, 0x00, 0xd6, 0xc0, 0x00, 0x00, 0xd6, 0xc8, 0x00, 0x00, 0xd6, 0xe0,
+ 0x00, 0x00, 0xd6, 0xe8, 0x00, 0x00, 0xd6, 0xf0, 0x00, 0x00, 0xd6, 0xf8, 0x00, 0x00, 0xd7, 0x14,
+ 0x00, 0x00, 0xd7, 0x38, 0x00, 0x00, 0xd7, 0x5c, 0x00, 0x00, 0xd7, 0x80, 0x00, 0x00, 0xd7, 0xa4,
+ 0x00, 0x00, 0xd7, 0xd0, 0x00, 0x00, 0xd7, 0xfc, 0x00, 0x00, 0xd8, 0x28, 0x00, 0x00, 0xd8, 0x48,
+ 0x00, 0x00, 0xd8, 0x70, 0x00, 0x00, 0xd8, 0x98, 0x00, 0x00, 0xd8, 0xa0, 0x00, 0x00, 0xd8, 0xc0,
+ 0x00, 0x00, 0xd8, 0xc8, 0x00, 0x00, 0xd8, 0xd0, 0x00, 0x00, 0xd8, 0xd8, 0x00, 0x00, 0xd8, 0xf4,
+ 0x00, 0x00, 0xd9, 0x18, 0x00, 0x00, 0xd9, 0x3c, 0x00, 0x00, 0xd9, 0x60, 0x00, 0x00, 0xd9, 0x84,
+ 0x00, 0x00, 0xd9, 0xb0, 0x00, 0x00, 0xd9, 0xdc, 0x00, 0x00, 0xda, 0x08, 0x00, 0x00, 0xda, 0x28,
+ 0x00, 0x00, 0xda, 0x50, 0x00, 0x00, 0xda, 0x78, 0x00, 0x00, 0xda, 0x80, 0x00, 0x00, 0xda, 0xa0,
+ 0x00, 0x00, 0xda, 0xa8, 0x00, 0x00, 0xda, 0xb0, 0x00, 0x00, 0xda, 0xb8, 0x00, 0x00, 0xda, 0xd4,
+ 0x00, 0x00, 0xda, 0xf8, 0x00, 0x00, 0xdb, 0x1c, 0x00, 0x00, 0xdb, 0x40, 0x00, 0x00, 0xdb, 0x64,
+ 0x00, 0x00, 0xdb, 0x90, 0x00, 0x00, 0xdb, 0xbc, 0x00, 0x00, 0xdb, 0xe8, 0x00, 0x00, 0xdc, 0x08,
+ 0x00, 0x00, 0xdc, 0x30, 0x00, 0x00, 0xdc, 0x58, 0x00, 0x00, 0xdc, 0x60, 0x00, 0x00, 0xdc, 0x80,
+ 0x00, 0x00, 0xdc, 0x88, 0x00, 0x00, 0xdc, 0x90, 0x00, 0x00, 0xdc, 0x98, 0x00, 0x00, 0xdc, 0xa8,
+ 0x00, 0x00, 0xdc, 0xc0, 0x00, 0x00, 0xdc, 0xd8, 0x00, 0x00, 0xdc, 0xf0, 0x00, 0x00, 0xdd, 0x08,
+ 0x00, 0x00, 0xdd, 0x28, 0x00, 0x00, 0xdd, 0x48, 0x00, 0x00, 0xdd, 0x68, 0x00, 0x00, 0xdd, 0x7c,
+ 0x00, 0x00, 0xdd, 0x98, 0x00, 0x00, 0xdd, 0xb4, 0x00, 0x00, 0xdd, 0xbc, 0x00, 0x00, 0xdd, 0xd0,
+ 0x00, 0x00, 0xdd, 0xd8, 0x00, 0x00, 0xdd, 0xe0, 0x00, 0x00, 0xdd, 0xe8, 0x00, 0x00, 0xde, 0x00,
+ 0x00, 0x00, 0xde, 0x20, 0x00, 0x00, 0xde, 0x40, 0x00, 0x00, 0xde, 0x60, 0x00, 0x00, 0xde, 0x80,
+ 0x00, 0x00, 0xde, 0xa8, 0x00, 0x00, 0xde, 0xd0, 0x00, 0x00, 0xde, 0xf8, 0x00, 0x00, 0xdf, 0x14,
+ 0x00, 0x00, 0xdf, 0x38, 0x00, 0x00, 0xdf, 0x5c, 0x00, 0x00, 0xdf, 0x64, 0x00, 0x00, 0xdf, 0x80,
+ 0x00, 0x00, 0xdf, 0x88, 0x00, 0x00, 0xdf, 0x90, 0x00, 0x00, 0xdf, 0x98, 0x00, 0x00, 0xdf, 0xb0,
+ 0x00, 0x00, 0xdf, 0xd0, 0x00, 0x00, 0xdf, 0xf0, 0x00, 0x00, 0xe0, 0x10, 0x00, 0x00, 0xe0, 0x30,
+ 0x00, 0x00, 0xe0, 0x58, 0x00, 0x00, 0xe0, 0x80, 0x00, 0x00, 0xe0, 0xa8, 0x00, 0x00, 0xe0, 0xc4,
+ 0x00, 0x00, 0xe0, 0xe8, 0x00, 0x00, 0xe1, 0x0c, 0x00, 0x00, 0xe1, 0x14, 0x00, 0x00, 0xe1, 0x30,
+ 0x00, 0x00, 0xe1, 0x38, 0x00, 0x00, 0xe1, 0x40, 0x00, 0x00, 0xe1, 0x48, 0x00, 0x00, 0xe1, 0x60,
+ 0x00, 0x00, 0xe1, 0x80, 0x00, 0x00, 0xe1, 0xa0, 0x00, 0x00, 0xe1, 0xc0, 0x00, 0x00, 0xe1, 0xe0,
+ 0x00, 0x00, 0xe2, 0x08, 0x00, 0x00, 0xe2, 0x30, 0x00, 0x00, 0xe2, 0x58, 0x00, 0x00, 0xe2, 0x74,
+ 0x00, 0x00, 0xe2, 0x98, 0x00, 0x00, 0xe2, 0xbc, 0x00, 0x00, 0xe2, 0xc4, 0x00, 0x00, 0xe2, 0xe0,
+ 0x00, 0x00, 0xe2, 0xe8, 0x00, 0x00, 0xe2, 0xf0, 0x00, 0x00, 0xe2, 0xf8, 0x00, 0x00, 0xe3, 0x08,
+ 0x00, 0x00, 0xe3, 0x20, 0x00, 0x00, 0xe3, 0x38, 0x00, 0x00, 0xe3, 0x50, 0x00, 0x00, 0xe3, 0x68,
+ 0x00, 0x00, 0xe3, 0x88, 0x00, 0x00, 0xe3, 0xa8, 0x00, 0x00, 0xe3, 0xc8, 0x00, 0x00, 0xe3, 0xdc,
+ 0x00, 0x00, 0xe3, 0xf8, 0x00, 0x00, 0xe4, 0x14, 0x00, 0x00, 0xe4, 0x1c, 0x00, 0x00, 0xe4, 0x30,
+ 0x00, 0x00, 0xe4, 0x38, 0x00, 0x00, 0xe4, 0x40, 0x00, 0x00, 0xe4, 0x48, 0x00, 0x00, 0xe4, 0x60,
+ 0x00, 0x00, 0xe4, 0x80, 0x00, 0x00, 0xe4, 0xa0, 0x00, 0x00, 0xe4, 0xc0, 0x00, 0x00, 0xe4, 0xe0,
+ 0x00, 0x00, 0xe5, 0x08, 0x00, 0x00, 0xe5, 0x30, 0x00, 0x00, 0xe5, 0x58, 0x00, 0x00, 0xe5, 0x74,
+ 0x00, 0x00, 0xe5, 0x98, 0x00, 0x00, 0xe5, 0xbc, 0x00, 0x00, 0xe5, 0xc4, 0x00, 0x00, 0xe5, 0xe0,
+ 0x00, 0x00, 0xe5, 0xe8, 0x00, 0x00, 0xe5, 0xf0, 0x00, 0x00, 0xe5, 0xf8, 0x00, 0x00, 0xe6, 0x10,
+ 0x00, 0x00, 0xe6, 0x30, 0x00, 0x00, 0xe6, 0x50, 0x00, 0x00, 0xe6, 0x70, 0x00, 0x00, 0xe6, 0x90,
+ 0x00, 0x00, 0xe6, 0xb8, 0x00, 0x00, 0xe6, 0xe0, 0x00, 0x00, 0xe7, 0x08, 0x00, 0x00, 0xe7, 0x24,
+ 0x00, 0x00, 0xe7, 0x48, 0x00, 0x00, 0xe7, 0x6c, 0x00, 0x00, 0xe7, 0x74, 0x00, 0x00, 0xe7, 0x90,
+ 0x00, 0x00, 0xe7, 0x98, 0x00, 0x00, 0xe7, 0xa0, 0x00, 0x00, 0xcf, 0xcc, 0x00, 0x00, 0xe7, 0xa8,
+ 0x00, 0x00, 0xe7, 0xc0, 0x00, 0x00, 0xe7, 0xd8, 0x00, 0x00, 0xe7, 0xf0, 0x00, 0x00, 0xe8, 0x08,
+ 0x00, 0x00, 0xe8, 0x28, 0x00, 0x00, 0xe8, 0x48, 0x00, 0x00, 0xe8, 0x68, 0x00, 0x00, 0xe8, 0x7c,
+ 0x00, 0x00, 0xe8, 0x98, 0x00, 0x00, 0xe8, 0xb4, 0x00, 0x00, 0xe8, 0xbc, 0x00, 0x00, 0xe8, 0xd0,
+ 0x00, 0x00, 0xe8, 0xd8, 0x00, 0x00, 0xcf, 0xc8, 0x93, 0xe2, 0x00, 0x00, 0x9d, 0xe2, 0x00, 0x04,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x02,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x1c, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x00, 0xff, 0x63, 0x68, 0x02, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x01, 0xff, 0x63, 0x68, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0xff, 0xe3, 0x28, 0x00,
+ 0xff, 0x63, 0x68, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x01,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd0, 0x04, 0xf3, 0xe3, 0x68, 0x03, 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xcf, 0xdc, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xcf, 0xf0, 0xf3, 0xe3, 0x28, 0x02, 0x93, 0xe2, 0x00, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8,
+ 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x02,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04, 0xfe, 0xe3, 0x68, 0x02,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x63, 0x68, 0x04, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x00,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x01,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd1, 0x44, 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd1, 0x0c, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xd1, 0x28, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xd0, 0xf8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0,
+ 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x02,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05, 0xfe, 0xe3, 0x68, 0x02,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x63, 0x68, 0x05, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x00,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x01,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd2, 0xc4, 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd2, 0x8c, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xd2, 0xa8, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xd2, 0x78, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0,
+ 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x02,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04, 0xfe, 0xe3, 0x68, 0x02,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x63, 0x28, 0x04, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x00,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x01,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd4, 0x44, 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd4, 0x0c, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xd4, 0x28, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xd3, 0xf8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8,
+ 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x06, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06,
+ 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06, 0xff, 0x63, 0x68, 0x02,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x7f, 0x6c, 0xff, 0xf8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x06, 0xfe, 0xe3, 0x68, 0x02,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x06,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8, 0x7e, 0x9c, 0xff, 0xf8,
+ 0xff, 0x63, 0x68, 0x06, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06, 0xff, 0x63, 0x68, 0x00,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06, 0xff, 0x63, 0x68, 0x01,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd5, 0xc4, 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x06,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd5, 0x8c, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xd5, 0xa8, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xd5, 0x78, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0xec, 0xff, 0xf8,
+ 0xff, 0x63, 0x68, 0x04, 0xff, 0xe3, 0x68, 0x00, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04, 0xff, 0xe3, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04, 0xff, 0xe3, 0x28, 0x00,
+ 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf8, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xff, 0xe3, 0x68, 0x02, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7e, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xe8, 0x7f, 0x1c, 0xff, 0xf8,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x68, 0x00,
+ 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7e, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xec, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7e, 0x1c, 0xff, 0xf0,
+ 0x7f, 0xec, 0xff, 0xe8, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x04,
+ 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x28, 0x00, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x04, 0xf3, 0xe3, 0x68, 0x03, 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xe8,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04, 0xff, 0xe3, 0x68, 0x00, 0xfe, 0xe3, 0x68, 0x06,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xff, 0xe3, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xd7, 0x5c, 0xf3, 0xe3, 0x68, 0x03,
+ 0x7f, 0xec, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x04, 0xf3, 0xe3, 0x28, 0x02,
+ 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd7, 0x14, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xd7, 0x38, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xd6, 0xf8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8,
+ 0xff, 0x63, 0x68, 0x05, 0xff, 0xe3, 0x68, 0x00, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05, 0xff, 0xe3, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05, 0xff, 0xe3, 0x28, 0x00,
+ 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xff, 0xe3, 0x68, 0x02, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7e, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x68, 0x00,
+ 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7e, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xec, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7e, 0x1c, 0xff, 0xf0,
+ 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x05,
+ 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x28, 0x00, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x68, 0x05, 0xf3, 0xe3, 0x68, 0x03, 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05, 0xff, 0xe3, 0x68, 0x00, 0xfe, 0xe3, 0x68, 0x06,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xff, 0xe3, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xd9, 0x3c, 0xf3, 0xe3, 0x68, 0x03,
+ 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8, 0xff, 0xe3, 0x68, 0x05, 0xf3, 0xe3, 0x28, 0x02,
+ 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xd8, 0xf4, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xd9, 0x18, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xd8, 0xd8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8,
+ 0xff, 0x63, 0x28, 0x04, 0xff, 0xe3, 0x68, 0x00, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04, 0xff, 0xe3, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0,
+ 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04, 0xff, 0xe3, 0x28, 0x00,
+ 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04,
+ 0xff, 0xe3, 0x68, 0x02, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7e, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x68, 0x00,
+ 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7e, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xec, 0xff, 0xf8,
+ 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7e, 0x1c, 0xff, 0xf0,
+ 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x1c, 0xff, 0xf8, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0xe3, 0x28, 0x04,
+ 0xff, 0x63, 0x68, 0x02, 0xfe, 0x63, 0x28, 0x00, 0xfe, 0xe3, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8,
+ 0xff, 0xe3, 0x28, 0x04, 0xf3, 0xe3, 0x68, 0x03, 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04, 0xff, 0xe3, 0x68, 0x00, 0xfe, 0xe3, 0x68, 0x06,
+ 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0xec, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04,
+ 0xff, 0xe3, 0x68, 0x01, 0xfe, 0xe3, 0x68, 0x06, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xdb, 0x1c, 0xf3, 0xe3, 0x68, 0x03,
+ 0x7f, 0xec, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf8, 0xff, 0xe3, 0x28, 0x04, 0xf3, 0xe3, 0x28, 0x02,
+ 0xff, 0x63, 0x68, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xda, 0xd4, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xda, 0xf8, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xda, 0xb8, 0x93, 0xe2, 0x00, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0xfd, 0xe3, 0x68, 0x07,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0xfd, 0xe3, 0x68, 0x07, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xfd, 0xe3, 0x68, 0x07,
+ 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf8, 0xfd, 0xe3, 0x68, 0x07, 0xff, 0xe3, 0x68, 0x02, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfd, 0xe3, 0x68, 0x07, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfd, 0xe3, 0x68, 0x07, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfd, 0xe3, 0x68, 0x07, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xe3, 0x68, 0x07, 0xf3, 0xe3, 0x68, 0x03,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0xfd, 0xe3, 0x68, 0x07, 0xff, 0xe3, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xfd, 0xe3, 0x68, 0x07,
+ 0xff, 0xe3, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xdc, 0xd8, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xdc, 0xa8, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xdc, 0xc0, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xdc, 0x98, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x00,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x01,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x28, 0x00,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x02,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xff, 0x63, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8,
+ 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xde, 0x40,
+ 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xf3, 0xe3, 0x28, 0x02,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xde, 0x00, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xde, 0x20, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xdd, 0xe8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x00,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x01,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x28, 0x00,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x02,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xff, 0x63, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0,
+ 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xdf, 0xf0,
+ 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xf3, 0xe3, 0x28, 0x02,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xdf, 0xb0, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xdf, 0xd0, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xdf, 0x98, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x00,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x01,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x28, 0x00,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x02,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x28, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04,
+ 0xff, 0x63, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0,
+ 0xff, 0xe3, 0x28, 0x04, 0xff, 0x63, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x68, 0x07,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xe1, 0xa0,
+ 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x28, 0x04, 0xf3, 0xe3, 0x28, 0x02,
+ 0xfd, 0xe3, 0x68, 0x07, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xe1, 0x60, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xe1, 0x80, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xe1, 0x48, 0x93, 0xe2, 0x00, 0x00, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8, 0xfd, 0xe3, 0x28, 0x06,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0xfd, 0xe3, 0x28, 0x06, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xfd, 0xe3, 0x28, 0x06,
+ 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf8, 0xfd, 0xe3, 0x28, 0x06, 0xff, 0xe3, 0x68, 0x02, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfd, 0xe3, 0x28, 0x06, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfd, 0xe3, 0x28, 0x06, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0xfd, 0xe3, 0x28, 0x06, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xe3, 0x28, 0x06, 0xf3, 0xe3, 0x68, 0x03,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0xfd, 0xe3, 0x28, 0x06, 0xff, 0xe3, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0xfd, 0xe3, 0x28, 0x06,
+ 0xff, 0xe3, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xe3, 0x38, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xe3, 0x08, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xe3, 0x20, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xe2, 0xf8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x00,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x01,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x28, 0x00,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x02,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x00, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xe8, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x04,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04,
+ 0xff, 0x63, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xe8,
+ 0xff, 0xe3, 0x68, 0x04, 0xff, 0x63, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xe4, 0xa0,
+ 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xe8, 0xff, 0xe3, 0x68, 0x04, 0xf3, 0xe3, 0x28, 0x02,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xe4, 0x60, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xe4, 0x80, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xe4, 0x48, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x00,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x01,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x28, 0x00,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x1c, 0xff, 0xf8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x02,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x00, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0,
+ 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05, 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x68, 0x01,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x7f, 0x6c, 0xff, 0xf0, 0x7e, 0x9c, 0xff, 0xf8, 0xff, 0x63, 0x68, 0x05,
+ 0xfe, 0xe3, 0x68, 0x02, 0xff, 0xe3, 0x28, 0x00, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05,
+ 0xff, 0x63, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0xec, 0xff, 0xf0,
+ 0xff, 0xe3, 0x68, 0x05, 0xff, 0x63, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0xfd, 0xe3, 0x28, 0x06,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xe6, 0x50,
+ 0xf3, 0xe3, 0x68, 0x03, 0x7f, 0xec, 0xff, 0xf0, 0xff, 0xe3, 0x68, 0x05, 0xf3, 0xe3, 0x28, 0x02,
+ 0xfd, 0xe3, 0x28, 0x06, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xe6, 0x10, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xe6, 0x30, 0xf3, 0xe3, 0x28, 0x02,
+ 0xe0, 0x00, 0xe5, 0xf8, 0x93, 0xe2, 0x00, 0x00, 0x7f, 0x9c, 0xff, 0xe8, 0x9d, 0xe2, 0x00, 0x04,
+ 0xff, 0xe3, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf0, 0x9d, 0xe2, 0x00, 0x04, 0xff, 0xe3, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x9d, 0xe2, 0x00, 0x04,
+ 0xff, 0xe3, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0x9c, 0xff, 0xf8, 0x9d, 0xe2, 0x00, 0x04, 0xff, 0xe3, 0x68, 0x02, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xe8, 0x7f, 0x9c, 0xff, 0xf8,
+ 0x9d, 0xe2, 0x00, 0x04, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x68, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0x9d, 0xe2, 0x00, 0x04, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x68, 0x01, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1c, 0xff, 0xf0, 0x7f, 0x9c, 0xff, 0xf8,
+ 0x9d, 0xe2, 0x00, 0x04, 0xff, 0xe3, 0x68, 0x02, 0xff, 0x63, 0x28, 0x00, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x9d, 0xe2, 0x00, 0x04, 0xf3, 0xe3, 0x68, 0x03,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xe8,
+ 0x9d, 0xe2, 0x00, 0x04, 0xff, 0xe3, 0x68, 0x00, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x9c, 0xff, 0xf0, 0x9d, 0xe2, 0x00, 0x04,
+ 0xff, 0xe3, 0x68, 0x01, 0xf3, 0xe3, 0x68, 0x03, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xe7, 0xd8, 0xf3, 0xe3, 0x68, 0x03, 0x9d, 0xe2, 0x00, 0x04,
+ 0xf3, 0xe3, 0x28, 0x02, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xe7, 0xa8, 0xf3, 0xe3, 0x28, 0x02, 0xe0, 0x00, 0xe7, 0xc0, 0xf3, 0xe3, 0x28, 0x02,
+ 0x8b, 0x96, 0xff, 0xc0, 0x8e, 0x96, 0xff, 0xb0, 0x83, 0x16, 0xff, 0xb8, 0x84, 0x16, 0xff, 0xb4,
+ 0x9d, 0x16, 0xff, 0x8c, 0xc3, 0xdc, 0xe8, 0x00, 0xf7, 0x82, 0xe9, 0x04, 0xe0, 0x00, 0xb7, 0x14,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0x22, 0x10, 0x00, 0x08, 0x9c, 0x12, 0x00, 0x04, 0x9f, 0x12, 0x00, 0x00,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xe9, 0x30, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xa5, 0x70, 0x8d, 0x16, 0xff, 0x8c, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xe9, 0x51,
+ 0x02, 0x10, 0x00, 0x08, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x84, 0x16, 0xff, 0xd0, 0xc3, 0x68, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x0f, 0xf7, 0x82, 0xe9, 0x68,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xff, 0x82, 0x00, 0x01,
+ 0xff, 0x89, 0xa5, 0x70, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x8b, 0x96, 0xff, 0xbc, 0x20, 0x5e, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x79, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x00, 0xcb, 0x44, 0x9c, 0x16, 0xff, 0x94, 0xc3, 0xf0, 0x00, 0x00, 0xc3, 0x6c, 0x00, 0x00,
+ 0x9c, 0x96, 0xff, 0x90, 0x9d, 0x16, 0xff, 0x8c, 0x9d, 0x96, 0xff, 0x88, 0x9e, 0x16, 0xff, 0x84,
+ 0xf7, 0x82, 0xe9, 0xbc, 0xe0, 0x00, 0xc3, 0x28, 0x97, 0x93, 0xff, 0xfc, 0x8c, 0x96, 0xff, 0x90,
+ 0x8d, 0x16, 0xff, 0x8c, 0x8d, 0x96, 0xff, 0x88, 0x8e, 0x16, 0xff, 0x84, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xea, 0xdd, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xce, 0x88, 0x8b, 0x16, 0xff, 0xd4,
+ 0x8b, 0x96, 0xff, 0xc4, 0x2f, 0xfc, 0x00, 0x01, 0x20, 0x5a, 0x00, 0x00, 0xe6, 0x00, 0xea, 0xa4,
+ 0xc3, 0xdc, 0xfc, 0x00, 0x8f, 0x16, 0xff, 0xd8, 0x20, 0x7a, 0x00, 0x20, 0xe2, 0x00, 0xca, 0xc8,
+ 0xc3, 0x68, 0x00, 0x00, 0x84, 0x16, 0xff, 0xac, 0xf3, 0x0a, 0xa8, 0x80, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x82, 0xea, 0x1c, 0xe0, 0x00, 0x1d, 0x28, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0xff, 0x88, 0x9f, 0xfc, 0x0e, 0x81, 0x00, 0x70, 0x8f, 0x6a, 0x00, 0x04, 0xfe, 0x02, 0x30, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xce, 0x78, 0xe4, 0x00, 0xce, 0xf8, 0xec, 0x00, 0xce, 0xf4, 0xfd, 0x00,
+ 0x7f, 0x79, 0x00, 0x16, 0x83, 0xea, 0x00, 0x08, 0xce, 0xf4, 0xe5, 0x00, 0x7f, 0x78, 0xff, 0xea,
+ 0xce, 0xf4, 0xf5, 0x00, 0x22, 0x10, 0x00, 0x0c, 0x8f, 0x96, 0xff, 0xb0, 0x5e, 0xf5, 0x4a, 0x00,
+ 0x8b, 0x16, 0xff, 0xc4, 0x8b, 0x96, 0xff, 0xd4, 0x9e, 0x92, 0x00, 0x00, 0x84, 0x96, 0xff, 0xb4,
+ 0xfe, 0x82, 0x00, 0x01, 0xf4, 0x0a, 0xa8, 0x80, 0x9b, 0x92, 0x00, 0x08, 0x9e, 0x92, 0x00, 0x04,
+ 0xc4, 0x7c, 0x40, 0x00, 0x73, 0x9c, 0xff, 0xf8, 0xc3, 0x58, 0xf8, 0x00, 0xf7, 0x82, 0xea, 0x98,
+ 0xe0, 0x00, 0xa3, 0x30, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xca, 0x6c,
+ 0x02, 0x10, 0x00, 0x0c, 0xf4, 0x08, 0xa5, 0x70, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x78,
+ 0xc3, 0x68, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x0f, 0xf7, 0x82, 0xea, 0xc4, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xfe, 0x82, 0x00, 0x01, 0xfe, 0x89, 0xa5, 0x70,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xc3, 0xf0, 0x00, 0x00,
+ 0xc3, 0x6c, 0x00, 0x00, 0x9c, 0x96, 0xff, 0x90, 0x9d, 0x16, 0xff, 0x8c, 0x9e, 0x16, 0xff, 0x84,
+ 0x9d, 0x96, 0xff, 0x88, 0xf7, 0x82, 0xeb, 0x00, 0xe0, 0x00, 0xc3, 0xcc, 0x97, 0x93, 0xff, 0xfc,
+ 0x8c, 0x96, 0xff, 0x90, 0x8d, 0x16, 0xff, 0x8c, 0x8e, 0x16, 0xff, 0x84, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xeb, 0x85, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xd4, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0xeb, 0x38, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xd8, 0x20, 0x7e, 0x00, 0x20,
+ 0xe2, 0x00, 0xeb, 0x7c, 0xc3, 0x68, 0x00, 0x00, 0x8b, 0x16, 0xff, 0xd8, 0x8b, 0x96, 0xff, 0xbc,
+ 0x83, 0x96, 0xff, 0xd4, 0x84, 0x16, 0xff, 0xc0, 0x22, 0x10, 0x00, 0x08, 0x9b, 0x12, 0x00, 0x00,
+ 0x9b, 0x92, 0x00, 0x04, 0xc3, 0x68, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c, 0xc4, 0xf0, 0x00, 0x00,
+ 0xf7, 0x82, 0xeb, 0x6c, 0xe0, 0x00, 0x39, 0xf0, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x02, 0x10, 0x00, 0x08, 0xe0, 0x00, 0xca, 0xd0,
+ 0xf3, 0x82, 0x00, 0x04, 0x8e, 0x96, 0xff, 0xd4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xeb, 0xcd,
+ 0xc3, 0x68, 0x00, 0x00, 0xf4, 0x08, 0xa5, 0x70, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x78,
+ 0xf3, 0x82, 0x00, 0x14, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xeb, 0xb4, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xff, 0x02, 0x00, 0x01, 0xff, 0x09, 0xa5, 0x70,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x82, 0xeb, 0xe0, 0xe0, 0x00, 0xc1, 0x94, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0x8b, 0x16, 0xff, 0xd8, 0x20, 0x5a, 0x00, 0x02, 0xe6, 0x00, 0xec, 0x35, 0x00, 0x00, 0x00, 0x01,
+ 0xf4, 0x08, 0xa5, 0x70, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xec, 0x19, 0xc3, 0x68, 0x00, 0x00,
+ 0xe0, 0x00, 0xf5, 0x34, 0xf4, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x12, 0xf7, 0x82, 0xec, 0x28,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xfe, 0x82, 0x00, 0x01, 0xe0, 0x00, 0xec, 0x10,
+ 0xfe, 0x89, 0xa5, 0x70, 0x8b, 0x96, 0xff, 0xc4, 0x70, 0x5e, 0x00, 0x1d, 0xea, 0x00, 0xec, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xc9, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xd8,
+ 0x20, 0x76, 0x00, 0x01, 0xe6, 0x00, 0xc9, 0x11, 0x20, 0x76, 0x00, 0x02, 0xe6, 0x00, 0xec, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xc4, 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x00, 0xec, 0x01,
+ 0x20, 0x7a, 0x00, 0xff, 0xe0, 0x00, 0xc9, 0x14, 0x00, 0x00, 0x00, 0x01, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x00, 0xec, 0x00, 0x20, 0x7e, 0x00, 0xff, 0xe0, 0x00, 0xc9, 0x08, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0xea, 0x00, 0x0c, 0x8f, 0x16, 0xff, 0xc8, 0xcd, 0xf4, 0x00, 0x00, 0x4f, 0xfc, 0xff, 0xfc,
+ 0x0f, 0x78, 0x00, 0x10, 0x9f, 0x16, 0xff, 0xc0, 0x9f, 0x96, 0xff, 0xc4, 0xe0, 0x00, 0xc8, 0xc8,
+ 0xce, 0x7c, 0x00, 0x00, 0xff, 0x86, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xcc, 0x8c, 0xea, 0x00, 0x04,
+ 0xff, 0x6b, 0x58, 0x0b, 0x77, 0xe4, 0x00, 0x09, 0x70, 0x3e, 0xff, 0xe3, 0xe6, 0x00, 0xed, 0x3d,
+ 0xff, 0x82, 0x00, 0xf8, 0xcf, 0xf8, 0xfc, 0x00, 0x20, 0x7e, 0x00, 0x20, 0xe6, 0x00, 0xf1, 0x45,
+ 0x20, 0x7a, 0x00, 0x14, 0xe6, 0x00, 0xf1, 0x45, 0x20, 0x7a, 0x00, 0x18, 0xe6, 0x00, 0xf1, 0x2d,
+ 0x20, 0x7a, 0x00, 0x19, 0xe6, 0x00, 0xf1, 0x15, 0x20, 0x7a, 0x00, 0x1b, 0xe6, 0x00, 0xf0, 0xfd,
+ 0xff, 0x82, 0x00, 0xfe, 0xcf, 0xf8, 0xfc, 0x00, 0x20, 0x7e, 0x00, 0x30, 0xe6, 0x00, 0xf0, 0xe5,
+ 0x20, 0x7a, 0x00, 0x33, 0xe6, 0x00, 0xf0, 0xe5, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x00, 0xed, 0x34,
+ 0x20, 0x7a, 0x00, 0x50, 0x8b, 0x96, 0xff, 0xdc, 0x20, 0x5e, 0x00, 0x33, 0xe6, 0x00, 0xf0, 0xb9,
+ 0x20, 0x7a, 0x00, 0x50, 0xe6, 0x00, 0xf0, 0xa9, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xd0,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xed, 0x61, 0xff, 0x82, 0x00, 0x78, 0x8b, 0x16, 0xff, 0xdc,
+ 0xcf, 0xd8, 0xfc, 0x00, 0x20, 0x7e, 0x00, 0x70, 0xe6, 0x00, 0xf0, 0x65, 0xff, 0x82, 0x00, 0xfe,
+ 0x20, 0x7a, 0x00, 0x7f, 0xe6, 0x00, 0xef, 0xd5, 0x00, 0x00, 0x00, 0x01, 0x8b, 0x96, 0xff, 0xdc,
+ 0x20, 0x5e, 0x00, 0x33, 0xe6, 0x00, 0xee, 0xa9, 0x20, 0x7a, 0x00, 0x19, 0x8f, 0x96, 0xff, 0xdc,
+ 0x20, 0x7e, 0x00, 0x34, 0xe6, 0x00, 0xee, 0x2d, 0x20, 0x7a, 0x00, 0x41, 0x8e, 0x96, 0xff, 0xdc,
+ 0x20, 0x76, 0x00, 0x74, 0xe6, 0x00, 0xed, 0xe1, 0x20, 0x7a, 0x00, 0x50, 0x8b, 0x16, 0xff, 0xd4,
+ 0xff, 0x88, 0xa5, 0x70, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x78, 0x64, 0x58, 0x00, 0x01,
+ 0xc3, 0x68, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c, 0xf3, 0x82, 0x00, 0x14, 0xf7, 0x82, 0xed, 0xc8,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xfb, 0x82, 0x00, 0x01,
+ 0xfb, 0x89, 0xa5, 0x70, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xe6, 0x00, 0xca, 0x79, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xd4, 0xff, 0x88, 0xa5, 0x70,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x78, 0x64, 0x78, 0x00, 0x01, 0xc3, 0x68, 0x00, 0x00,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf3, 0x82, 0x00, 0x14, 0xf7, 0x82, 0xee, 0x14, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xff, 0x82, 0x00, 0x01, 0xff, 0x89, 0xa5, 0x70,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe6, 0x00, 0xca, 0x79,
+ 0x20, 0x7a, 0x00, 0x43, 0xe6, 0x00, 0xca, 0x79, 0x20, 0x7a, 0x00, 0x40, 0xe6, 0x00, 0xca, 0x79,
+ 0x20, 0x7a, 0x00, 0x45, 0xe6, 0x00, 0xca, 0x79, 0x20, 0x7a, 0x00, 0x47, 0xe6, 0x00, 0xca, 0x79,
+ 0x20, 0x7a, 0x00, 0x44, 0xe6, 0x00, 0xca, 0x79, 0x20, 0x7a, 0x00, 0x48, 0xe6, 0x00, 0xca, 0x79,
+ 0x00, 0x00, 0x00, 0x01, 0x8b, 0x16, 0xff, 0xd4, 0xff, 0x88, 0xa5, 0x70, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0xca, 0x78, 0x64, 0x58, 0x00, 0x01, 0xc3, 0x68, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf3, 0x82, 0x00, 0x14, 0xf7, 0x82, 0xee, 0x90, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0xfb, 0x82, 0x00, 0x01, 0xfb, 0x89, 0xa5, 0x70, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe6, 0x00, 0xee, 0xfd, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x00, 0xca, 0x79, 0x00, 0x00, 0x00, 0x01, 0x8b, 0x96, 0xff, 0xd4, 0xff, 0x88, 0xa5, 0x70,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x78, 0x64, 0x5c, 0x00, 0x01, 0xc3, 0x68, 0x00, 0x00,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf3, 0x82, 0x00, 0x14, 0xf7, 0x82, 0xee, 0xe4, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xfe, 0x82, 0x00, 0x01, 0xfe, 0x89, 0xa5, 0x70,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa0, 0x20,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xef, 0xb4, 0x03, 0x01, 0xe1, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf3, 0x02, 0x00, 0x35, 0xf3, 0x82, 0x00, 0x03, 0xf7, 0x82, 0xef, 0x24, 0xe0, 0x00, 0xb9, 0x40,
+ 0x97, 0x93, 0xff, 0xfc, 0x22, 0x10, 0x00, 0x04, 0xfe, 0x82, 0xc5, 0x5d, 0x9e, 0x92, 0x00, 0x00,
+ 0xf7, 0x82, 0xef, 0x3c, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc, 0x0f, 0x01, 0x40, 0x00,
+ 0x0f, 0x78, 0x00, 0x15, 0x9f, 0x02, 0xff, 0x90, 0xff, 0x88, 0xa5, 0x40, 0x8d, 0x16, 0xff, 0x8c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xef, 0x94, 0x02, 0x10, 0x00, 0x04, 0xff, 0x82, 0x00, 0x03,
+ 0xff, 0x89, 0xa5, 0x40, 0xff, 0x88, 0xce, 0xc0, 0x8f, 0x02, 0xff, 0xd0, 0xfb, 0x02, 0x00, 0x01,
+ 0x5f, 0xfc, 0x08, 0x00, 0xff, 0x09, 0xe6, 0x18, 0xff, 0x89, 0xce, 0xc0, 0xfb, 0x09, 0xa5, 0x44,
+ 0xfb, 0x09, 0xa5, 0x50, 0xf0, 0x09, 0xa5, 0x54, 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x78,
+ 0x55, 0x29, 0x80, 0x00, 0x03, 0x01, 0xe1, 0x00, 0x03, 0x18, 0x04, 0x75, 0xf7, 0x82, 0xef, 0xa8,
+ 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xef, 0x60,
+ 0xff, 0x82, 0x00, 0x03, 0x9d, 0x16, 0xff, 0x8c, 0x03, 0x18, 0x11, 0x98, 0xf7, 0x82, 0xef, 0xc8,
+ 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xef, 0x10,
+ 0x9d, 0x16, 0xff, 0x8c, 0x8e, 0x96, 0xff, 0xdc, 0x20, 0x76, 0x00, 0x34, 0xe2, 0x00, 0xf0, 0x38,
+ 0x20, 0x76, 0x00, 0x32, 0xe4, 0x00, 0xca, 0x79, 0x20, 0x76, 0x00, 0x30, 0xe6, 0x00, 0xca, 0x79,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xd4, 0x64, 0x7c, 0x00, 0x01, 0xff, 0x88, 0xa5, 0x70,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x78, 0xc3, 0x68, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf3, 0x82, 0x00, 0x14, 0xf7, 0x82, 0xf0, 0x20, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0xfb, 0x02, 0x00, 0x01, 0xfb, 0x09, 0xa5, 0x70, 0x8c, 0xea, 0x00, 0x04,
+ 0xe0, 0x00, 0xca, 0x78, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xdc, 0x20, 0x7a, 0x00, 0x70,
+ 0xe6, 0x00, 0xca, 0x79, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0xef, 0xf4, 0x2f, 0xf8, 0x00, 0x72,
+ 0x20, 0x7e, 0x00, 0x02, 0xe2, 0x00, 0xca, 0x79, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xef, 0xf4,
+ 0x00, 0x00, 0x00, 0x01, 0xcf, 0xf8, 0xfc, 0x00, 0x20, 0x7e, 0x00, 0x7f, 0xe6, 0x00, 0xed, 0x65,
+ 0x20, 0x7a, 0x00, 0x7f, 0xf4, 0x08, 0xa5, 0x70, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x74,
+ 0xff, 0x02, 0x00, 0x00, 0xc3, 0x68, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x14, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x82, 0xf0, 0x9c, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xfb, 0x82, 0x00, 0x01,
+ 0xe0, 0x00, 0xca, 0xdc, 0xfb, 0x89, 0xa5, 0x70, 0x8e, 0x96, 0xff, 0xdc, 0x20, 0x76, 0x00, 0x74,
+ 0xe6, 0x00, 0xed, 0x3c, 0x00, 0x00, 0x00, 0x01, 0xf4, 0x08, 0xa5, 0x70, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xec, 0x10, 0xc3, 0x68, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x12, 0xf7, 0x82, 0xf0, 0xd8,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x02, 0x00, 0x01, 0xe0, 0x00, 0xec, 0x10,
+ 0xff, 0x09, 0xa5, 0x70, 0x8b, 0x16, 0xff, 0xdc, 0x20, 0x5a, 0x00, 0x30, 0xe6, 0x00, 0xed, 0x1c,
+ 0x20, 0x7a, 0x00, 0x00, 0xe0, 0x00, 0xf0, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xdc,
+ 0x20, 0x7e, 0x00, 0x35, 0xe6, 0x00, 0xed, 0x04, 0xff, 0x82, 0x00, 0xfe, 0xe0, 0x00, 0xf0, 0xb8,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xdc, 0x20, 0x76, 0x00, 0x33, 0xe6, 0x00, 0xec, 0xfc,
+ 0x20, 0x7a, 0x00, 0x1b, 0xe0, 0x00, 0xf0, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x8b, 0x96, 0xff, 0xdc,
+ 0x20, 0x5e, 0x00, 0x30, 0xe6, 0x00, 0xec, 0xf4, 0x20, 0x7a, 0x00, 0x19, 0xe0, 0x00, 0xf0, 0xb8,
+ 0x00, 0x00, 0x00, 0x01, 0x8b, 0x16, 0xff, 0xdc, 0x20, 0x5a, 0x00, 0x34, 0xe6, 0x00, 0xec, 0xec,
+ 0x20, 0x7a, 0x00, 0x18, 0xe0, 0x00, 0xf0, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xc3, 0x68, 0x00, 0x00,
+ 0xe0, 0x00, 0xca, 0xcc, 0xf3, 0x82, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xdc, 0xfb, 0x02, 0x00, 0x01,
+ 0xfb, 0x82, 0x00, 0x00, 0xc0, 0x7e, 0xb4, 0x00, 0xe6, 0x00, 0xf1, 0x94, 0x9b, 0x96, 0xff, 0xa4,
+ 0x83, 0x6a, 0x00, 0x0c, 0x77, 0x98, 0x00, 0x0d, 0x70, 0x3e, 0xff, 0xe3, 0xe6, 0x00, 0xf1, 0xa1,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xe0, 0x00, 0xca, 0xcc, 0xc3, 0x68, 0x00, 0x00,
+ 0x8e, 0x96, 0xff, 0xd4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xf3, 0xe9, 0xff, 0x82, 0x0f, 0xfc,
+ 0xff, 0x08, 0xa5, 0x3c, 0xcd, 0xfc, 0x34, 0x00, 0xc3, 0x6c, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0x9f, 0x16, 0xff, 0xa0, 0xf7, 0x82, 0xf1, 0xd0, 0xe0, 0x00, 0x7c, 0x68, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x96, 0xff, 0xd0, 0x8d, 0x16, 0xff, 0x8c, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xf1, 0xf1,
+ 0xcd, 0xa0, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01, 0xe0, 0x00, 0xca, 0xd0, 0xc3, 0x68, 0x00, 0x00,
+ 0x83, 0xea, 0x00, 0x10, 0xf4, 0x6b, 0x58, 0x0b, 0xc3, 0x6c, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0x9d, 0x96, 0xff, 0x88, 0xf7, 0x82, 0xf2, 0x10, 0xe0, 0x00, 0x08, 0x84, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0xff, 0x88, 0x9f, 0xfc, 0x0f, 0x01, 0x00, 0x70, 0x8e, 0x6a, 0x00, 0x04,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xfe, 0x82, 0x30, 0x00, 0xcf, 0x70, 0xf4, 0x00, 0xcf, 0x78, 0xfd, 0x00,
+ 0xce, 0x70, 0xec, 0x00, 0x8d, 0x96, 0xff, 0x88, 0xcf, 0x78, 0xe5, 0x00, 0x5f, 0x79, 0x0a, 0x00,
+ 0x20, 0x6e, 0x00, 0x58, 0xe6, 0x00, 0xf3, 0xcd, 0x9f, 0x16, 0xff, 0xa8, 0x8f, 0x16, 0xff, 0xdc,
+ 0x20, 0x7a, 0x00, 0x44, 0xe6, 0x00, 0xf3, 0xad, 0x00, 0x00, 0x00, 0x01, 0x83, 0x6a, 0x00, 0x08,
+ 0x8f, 0x96, 0xff, 0xa8, 0x22, 0x10, 0x00, 0x08, 0xf3, 0x82, 0x00, 0x00, 0x9f, 0x92, 0x00, 0x00,
+ 0x93, 0x92, 0x00, 0x04, 0x9d, 0x16, 0xff, 0x8c, 0x73, 0x18, 0xff, 0xf8, 0xf4, 0x02, 0x00, 0x04,
+ 0xc4, 0x9c, 0x00, 0x00, 0xf7, 0x82, 0xf2, 0x90, 0xe0, 0x00, 0xa4, 0x44, 0x97, 0x93, 0xff, 0xfc,
+ 0x8b, 0x16, 0xff, 0xa4, 0x8d, 0x16, 0xff, 0x8c, 0x20, 0x5a, 0x00, 0x00, 0xe6, 0x00, 0xca, 0x6d,
+ 0x02, 0x10, 0x00, 0x08, 0xff, 0x88, 0xa5, 0x3c, 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x00, 0xf3, 0x3d,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xf3, 0x20, 0x03, 0x01, 0xe1, 0x00, 0xff, 0x88, 0xa5, 0x40,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x00, 0xf3, 0x04, 0x03, 0x18, 0x11, 0x06, 0x22, 0x10, 0x00, 0x04,
+ 0xff, 0x02, 0xc5, 0x78, 0x9f, 0x12, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xf2, 0xe8,
+ 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc, 0x02, 0x10, 0x00, 0x04, 0xf3, 0x02, 0x00, 0x02,
+ 0xf7, 0x82, 0xf2, 0xfc, 0xe0, 0x00, 0x90, 0x20, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xca, 0xdc,
+ 0x00, 0x00, 0x00, 0x01, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xf3, 0x14, 0xe0, 0x00, 0x7b, 0xb8,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xf2, 0xd0, 0x22, 0x10, 0x00, 0x04,
+ 0x03, 0x18, 0x11, 0x11, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xf3, 0x34, 0xe0, 0x00, 0x7b, 0xb8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xca, 0xdc, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa5, 0x40,
+ 0x0b, 0x81, 0x40, 0x00, 0x0b, 0xdc, 0x00, 0x15, 0x9b, 0x82, 0xff, 0x90, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x00, 0xf3, 0x8c, 0x03, 0x01, 0xe1, 0x00, 0xff, 0x88, 0xce, 0xc0, 0x8f, 0x02, 0xff, 0xd0,
+ 0xfe, 0x82, 0x00, 0x01, 0x5f, 0xfc, 0x08, 0x00, 0xfe, 0x89, 0xa5, 0x40, 0xff, 0x09, 0xe6, 0x18,
+ 0xff, 0x89, 0xce, 0xc0, 0xfe, 0x89, 0xa5, 0x44, 0xfe, 0x89, 0xa5, 0x50, 0xf0, 0x09, 0xa5, 0x54,
+ 0x8c, 0xea, 0x00, 0x04, 0xe0, 0x00, 0xca, 0x70, 0x55, 0x29, 0x80, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0x03, 0x18, 0x04, 0x75, 0xf7, 0x82, 0xf3, 0xa0, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xf3, 0x58, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x6b, 0x18, 0x0c,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xf3, 0xc0, 0xe0, 0x00, 0xc4, 0x84, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xf2, 0x5c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa5, 0x3c,
+ 0x8b, 0x16, 0xff, 0xa0, 0xc0, 0x7e, 0xb2, 0x00, 0xe6, 0x00, 0xf2, 0x4d, 0xfb, 0x82, 0x00, 0x01,
+ 0xe0, 0x00, 0xf2, 0x4c, 0x9b, 0x96, 0xff, 0xa4, 0xcf, 0xfc, 0x34, 0x00, 0x9d, 0x16, 0xff, 0x8c,
+ 0x9f, 0x96, 0xff, 0x9c, 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x82, 0xf4, 0x04, 0xe0, 0x00, 0x7c, 0x68,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x20, 0x22, 0x00, 0x64, 0xe6, 0x00, 0xf4, 0xa5,
+ 0x94, 0x16, 0xff, 0x9c, 0x8e, 0x96, 0xff, 0x9c, 0x20, 0x76, 0x00, 0x6c, 0xe6, 0x00, 0xf4, 0x89,
+ 0x20, 0x76, 0x00, 0x64, 0xe6, 0x00, 0xf4, 0x89, 0x20, 0x76, 0x01, 0x10, 0xe6, 0x00, 0xf4, 0x89,
+ 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0x9c, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xf4, 0x48,
+ 0xe0, 0x00, 0x08, 0x28, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xf4, 0x09, 0xce, 0x00,
+ 0xff, 0x88, 0x9f, 0xfc, 0x8e, 0x6a, 0x00, 0x04, 0x0f, 0x01, 0x00, 0x70, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0x70, 0xf4, 0x00, 0xcf, 0x78, 0xfd, 0x00, 0xfe, 0x82, 0x30, 0x00, 0xce, 0x70, 0xec, 0x00,
+ 0x0f, 0x81, 0x4a, 0x00, 0xcf, 0x78, 0xe5, 0x00, 0x0f, 0xfc, 0x00, 0x01, 0xcf, 0x78, 0xfd, 0x00,
+ 0xe0, 0x00, 0xf2, 0x4c, 0x9f, 0x16, 0xff, 0xa8, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x82, 0xf4, 0x98,
+ 0xe0, 0x00, 0xbf, 0xd8, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x00, 0xf4, 0x34,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0xf4, 0xb0, 0xe0, 0x01, 0xa8, 0x18, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xcf, 0xb0, 0x0f, 0x01, 0x00, 0x20, 0xc4, 0x20, 0xfd, 0x00, 0xff, 0x88, 0x91, 0x18,
+ 0x74, 0x21, 0x00, 0x15, 0xc4, 0x20, 0xf4, 0x00, 0x4f, 0xfd, 0xff, 0xdf, 0xcf, 0xfc, 0x45, 0x00,
+ 0xe0, 0x00, 0xf4, 0x98, 0xff, 0x89, 0x91, 0x18, 0x03, 0x01, 0xe1, 0x00, 0xe0, 0x00, 0xf3, 0x24,
+ 0x03, 0x18, 0x11, 0xeb, 0x9d, 0x16, 0xff, 0x8c, 0xf3, 0x82, 0x00, 0x13, 0xf7, 0x82, 0xf4, 0xf8,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xfe, 0x82, 0x00, 0x01,
+ 0xe0, 0x00, 0xc6, 0x38, 0xfe, 0x89, 0xa5, 0x70, 0xc3, 0xe8, 0x00, 0x00, 0x23, 0x14, 0x00, 0x20,
+ 0xf4, 0x02, 0x00, 0x14, 0xf7, 0x82, 0xf5, 0x20, 0xe0, 0x00, 0xb7, 0x14, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xc5, 0xf0, 0x2d, 0x14, 0x00, 0x20, 0x8b, 0x96, 0xff, 0xd4, 0xe0, 0x00, 0xc5, 0xe0,
+ 0x9b, 0x96, 0xff, 0xcc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x34, 0xff, 0xfa, 0x7f, 0xf0,
+ 0xfe, 0x82, 0x00, 0x00, 0x93, 0x16, 0xff, 0xdc, 0xc0, 0x1a, 0xfa, 0x00, 0x9e, 0x96, 0xff, 0xd4,
+ 0xe6, 0x00, 0xf8, 0xad, 0xcd, 0x98, 0x00, 0x00, 0xff, 0x6f, 0x18, 0x00, 0xff, 0x82, 0x07, 0xff,
+ 0xcf, 0xf8, 0xfc, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0x0f, 0xfc, 0x00, 0x0f, 0x7e, 0x78, 0xff, 0xf5,
+ 0x4f, 0xfc, 0xff, 0xf0, 0x20, 0x72, 0x00, 0x13, 0xe2, 0x00, 0xf8, 0x90, 0x9f, 0x96, 0xff, 0xd8,
+ 0x7f, 0xf1, 0x00, 0x02, 0xff, 0x02, 0xf5, 0xa4, 0xae, 0xfe, 0xf0, 0x02, 0xc1, 0x74, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xf5, 0xf4, 0x00, 0x00, 0xf5, 0xf4, 0x00, 0x00, 0xf6, 0x08,
+ 0x00, 0x00, 0xf6, 0x6c, 0x00, 0x00, 0xf6, 0x6c, 0x00, 0x00, 0xf6, 0x6c, 0x00, 0x00, 0xf6, 0xfc,
+ 0x00, 0x00, 0xf6, 0x6c, 0x00, 0x00, 0xf6, 0x78, 0x00, 0x00, 0xf6, 0x78, 0x00, 0x00, 0xf6, 0x78,
+ 0x00, 0x00, 0xf6, 0x78, 0x00, 0x00, 0xf6, 0x78, 0x00, 0x00, 0xf6, 0x78, 0x00, 0x00, 0xf6, 0x78,
+ 0x00, 0x00, 0xf6, 0x78, 0x00, 0x00, 0xf7, 0x14, 0x00, 0x00, 0xf6, 0xfc, 0x00, 0x00, 0xf7, 0x20,
+ 0x00, 0x00, 0xf7, 0x2c, 0x03, 0x01, 0xe1, 0x00, 0x03, 0x18, 0x12, 0x2b, 0xf7, 0x82, 0xf6, 0x08,
+ 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xdc, 0x8e, 0x96, 0xff, 0xd8,
+ 0xcf, 0xf8, 0xe8, 0x00, 0x4f, 0xfc, 0x7f, 0xff, 0x01, 0xfc, 0x00, 0x60, 0xff, 0x02, 0x00, 0x00,
+ 0x0f, 0xfc, 0x18, 0x00, 0xff, 0x83, 0x2a, 0x52, 0xc0, 0x7a, 0xf2, 0x00, 0xe6, 0x00, 0xf6, 0x39,
+ 0x00, 0x00, 0x00, 0x01, 0x9f, 0x02, 0xff, 0x88, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x00, 0xf6, 0x38, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0xe1, 0x00,
+ 0xe0, 0x00, 0xf5, 0xfc, 0x03, 0x18, 0x12, 0x3b, 0x8f, 0xee, 0x00, 0x04, 0x70, 0x72, 0x00, 0x1d,
+ 0x7f, 0xfd, 0x00, 0x16, 0x0f, 0xfd, 0xff, 0xc0, 0x7f, 0xfc, 0xff, 0xea, 0x0f, 0xfc, 0x00, 0x01,
+ 0x9f, 0x96, 0xff, 0xd0, 0xea, 0x00, 0xf6, 0xfd, 0x74, 0x7d, 0x00, 0x02, 0x70, 0x72, 0x00, 0x1f,
+ 0xea, 0x00, 0xf6, 0xec, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xdc, 0x8f, 0xee, 0x00, 0x10,
+ 0x03, 0xf8, 0x00, 0x14, 0x4f, 0xfc, 0xff, 0xfc, 0x43, 0x7d, 0x00, 0x1f, 0xf7, 0x82, 0xf6, 0xc8,
+ 0xe0, 0x00, 0xb7, 0x14, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xd0, 0x9f, 0x16, 0xff, 0xd4,
+ 0x8e, 0x96, 0xff, 0xd4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x00, 0xf6, 0x09, 0x00, 0x00, 0x00, 0x01,
+ 0x9e, 0x82, 0xff, 0x88, 0xe0, 0x00, 0xf6, 0x08, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xdc,
+ 0x8f, 0xee, 0x00, 0x0c, 0xe0, 0x00, 0xf6, 0xb4, 0x03, 0xf4, 0x00, 0x10, 0x83, 0x16, 0xff, 0xdc,
+ 0xf7, 0x82, 0xf7, 0x0c, 0xe0, 0x00, 0xc5, 0x90, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xf6, 0xd0,
+ 0x94, 0x16, 0xff, 0xd4, 0x03, 0x01, 0xe1, 0x00, 0xe0, 0x00, 0xf5, 0xfc, 0x03, 0x18, 0x12, 0x6d,
+ 0x03, 0x01, 0xe1, 0x00, 0xe0, 0x00, 0xf5, 0xfc, 0x03, 0x18, 0x12, 0xb9, 0x8e, 0x96, 0xff, 0xdc,
+ 0x0f, 0xf4, 0x00, 0x10, 0x4f, 0xfc, 0x7f, 0xff, 0x01, 0xfc, 0x00, 0x60, 0xff, 0x02, 0x00, 0x00,
+ 0x0f, 0xfc, 0x18, 0x00, 0xff, 0x83, 0x2a, 0x52, 0xc0, 0x7a, 0xf2, 0x00, 0xe6, 0x00, 0xf7, 0x59,
+ 0x00, 0x00, 0x00, 0x01, 0x9f, 0x02, 0xff, 0x88, 0x8f, 0x6e, 0x00, 0x00, 0x0f, 0x81, 0x00, 0x70,
+ 0xcf, 0xf8, 0xfc, 0x00, 0x7f, 0xfc, 0xff, 0xec, 0x9f, 0x16, 0xff, 0xcc, 0x70, 0x7a, 0x00, 0x08,
+ 0xea, 0x00, 0xf8, 0x59, 0x9f, 0x96, 0xff, 0xc8, 0x8f, 0x96, 0xff, 0xc8, 0x20, 0x7e, 0x00, 0x04,
+ 0xe6, 0x00, 0xf8, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xc8, 0x20, 0x76, 0x00, 0x00,
+ 0xe6, 0x00, 0xf8, 0x19, 0x0f, 0x81, 0x03, 0x00, 0xff, 0x88, 0x8f, 0x98, 0x5f, 0xfd, 0x20, 0x00,
+ 0xff, 0x89, 0x8f, 0x98, 0xff, 0xef, 0x18, 0x00, 0xf3, 0x82, 0x00, 0x0f, 0xcf, 0xfc, 0x3c, 0x00,
+ 0xc0, 0x7e, 0x3a, 0x00, 0xe6, 0x00, 0xf8, 0x09, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xdc,
+ 0xf3, 0x7f, 0x18, 0x00, 0xc3, 0x18, 0x3c, 0x00, 0xf7, 0x82, 0xf7, 0xd4, 0xe0, 0x01, 0xa8, 0x80,
+ 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x00, 0xf7, 0xd4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xcf, 0xb0, 0x2f, 0xfc, 0x00, 0x01,
+ 0xe0, 0x00, 0xf7, 0xd4, 0xff, 0x89, 0xcf, 0xb0, 0x8f, 0x16, 0xff, 0xcc, 0xc0, 0x7a, 0xfc, 0x00,
+ 0xe6, 0x00, 0xf7, 0xa5, 0xc3, 0x6c, 0x00, 0x00, 0x84, 0x16, 0xff, 0xc8, 0x9d, 0x96, 0xff, 0xc4,
+ 0xf3, 0x82, 0x00, 0x12, 0xf7, 0x82, 0xf8, 0x40, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x96, 0xff, 0xc4, 0xe0, 0x00, 0xf7, 0xa4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x8f, 0x98,
+ 0xe0, 0x00, 0xf7, 0xa0, 0x5f, 0xfd, 0x10, 0x00, 0xc3, 0x6c, 0x00, 0x00, 0x9d, 0x96, 0xff, 0xc4,
+ 0xf3, 0x82, 0x00, 0x0c, 0xf4, 0x02, 0x00, 0x01, 0xf7, 0x82, 0xf8, 0x74, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0x8f, 0x98, 0x8d, 0x96, 0xff, 0xc4, 0x70, 0x7e, 0x00, 0x19,
+ 0xea, 0x00, 0xf7, 0x78, 0x5f, 0xfd, 0x01, 0x00, 0xe0, 0x00, 0xf7, 0x78, 0xff, 0x89, 0x8f, 0x98,
+ 0x03, 0x01, 0xe1, 0x00, 0x03, 0x18, 0x12, 0xbf, 0xf7, 0x82, 0xf8, 0xa4, 0xe0, 0x00, 0x7b, 0xb8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xf6, 0xd0, 0x00, 0x00, 0x00, 0x01, 0xc3, 0xec, 0x00, 0x00,
+ 0x23, 0x14, 0x00, 0x20, 0xf4, 0x02, 0x00, 0x14, 0xf7, 0x82, 0xf8, 0xc4, 0xe0, 0x00, 0xb7, 0x14,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xf5, 0x68, 0x2d, 0x94, 0x00, 0x20, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x70, 0x0e, 0x00, 0x10, 0xeb, 0x08, 0x00, 0x53, 0x8f, 0x8f, 0xff, 0xa0, 0x90, 0x02, 0xfe, 0x42,
+ 0x83, 0x8e, 0x00, 0x0c, 0x01, 0x8c, 0x00, 0xc0, 0x7e, 0xfc, 0xff, 0xf0, 0x20, 0x76, 0x60, 0x15,
+ 0xe6, 0x00, 0xf9, 0x45, 0x0f, 0x0c, 0x17, 0x50, 0x43, 0x74, 0x07, 0xff, 0x7e, 0x18, 0x00, 0x02,
+ 0x8d, 0xf2, 0x07, 0x08, 0x21, 0xf8, 0x17, 0xa0, 0xff, 0x03, 0x2a, 0x52, 0x4d, 0x74, 0xf8, 0x00,
+ 0x20, 0x6a, 0x90, 0x00, 0xe7, 0x6c, 0x00, 0x03, 0x43, 0xfd, 0x00, 0x00, 0x23, 0x0c, 0x00, 0x70,
+ 0xe0, 0x00, 0xfb, 0x50, 0xc3, 0xfc, 0x00, 0x00, 0xc3, 0x0c, 0x00, 0x00, 0xe0, 0x00, 0xfb, 0x50,
+ 0x90, 0x02, 0xfe, 0x42, 0x7c, 0x9c, 0x00, 0x08, 0x7c, 0xe4, 0xff, 0xe8, 0x8c, 0x66, 0x05, 0x08,
+ 0xfb, 0x82, 0x00, 0x10, 0x9b, 0x82, 0xff, 0x88, 0x0b, 0x0c, 0x17, 0xa0, 0xfb, 0x03, 0x2a, 0x52,
+ 0xc1, 0x60, 0x00, 0x00, 0x23, 0x0c, 0x00, 0xb0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x70, 0x0e, 0x00, 0x10,
+ 0xeb, 0x08, 0x00, 0x53, 0x8f, 0x8f, 0xff, 0xa0, 0x90, 0x02, 0xfe, 0x42, 0x83, 0x8e, 0x00, 0x0c,
+ 0x01, 0x8c, 0x00, 0xc0, 0x7e, 0xfc, 0xff, 0xf0, 0x20, 0x76, 0x70, 0x16, 0xe6, 0x00, 0xf9, 0xe1,
+ 0x0f, 0x0c, 0x17, 0x50, 0x43, 0x74, 0x07, 0xff, 0x7e, 0x18, 0x00, 0x02, 0x8d, 0xf2, 0x07, 0x08,
+ 0x21, 0xf8, 0x17, 0xa0, 0xff, 0x03, 0x2a, 0x52, 0x4d, 0x74, 0xf8, 0x00, 0x20, 0x6a, 0x90, 0x00,
+ 0xe7, 0x6c, 0x00, 0x03, 0x43, 0xfd, 0x00, 0x00, 0x23, 0x0c, 0x00, 0x70, 0xe0, 0x00, 0xfc, 0xa4,
+ 0xc3, 0xfc, 0x00, 0x00, 0xc3, 0x0c, 0x00, 0x00, 0xe0, 0x00, 0xfc, 0xa4, 0x90, 0x02, 0xfe, 0x42,
+ 0x7c, 0x9c, 0x00, 0x08, 0x7c, 0xe4, 0xff, 0xe8, 0x8c, 0x66, 0x05, 0x08, 0xfb, 0x82, 0x00, 0x10,
+ 0x9b, 0x82, 0xff, 0x88, 0x0b, 0x0c, 0x17, 0xa0, 0xfb, 0x03, 0x2a, 0x52, 0xc1, 0x60, 0x00, 0x00,
+ 0x23, 0x0c, 0x00, 0xb0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x70, 0x0e, 0x00, 0x10, 0xeb, 0x08, 0x00, 0x53,
+ 0x8f, 0x8f, 0xff, 0xa0, 0x90, 0x02, 0xfe, 0x42, 0x83, 0x8e, 0x00, 0x10, 0x01, 0x8c, 0x00, 0xc0,
+ 0x7e, 0xfc, 0xff, 0xf0, 0x20, 0x76, 0x68, 0x16, 0xe6, 0x00, 0xfa, 0x7d, 0x0f, 0x0c, 0x17, 0x50,
+ 0x43, 0x74, 0x07, 0xff, 0x7e, 0x18, 0x00, 0x02, 0x8d, 0xf2, 0x07, 0x08, 0x21, 0xf8, 0x17, 0xa0,
+ 0xff, 0x03, 0x2a, 0x52, 0x4d, 0x74, 0xf8, 0x00, 0x20, 0x6a, 0x90, 0x00, 0xe7, 0x6c, 0x00, 0x03,
+ 0x43, 0xfd, 0x00, 0x00, 0x23, 0x0c, 0x00, 0x70, 0xe0, 0x00, 0xfd, 0xf8, 0xc3, 0xfc, 0x00, 0x00,
+ 0xc3, 0x0c, 0x00, 0x00, 0xe0, 0x00, 0xfd, 0xf8, 0x90, 0x02, 0xfe, 0x42, 0x7c, 0x9c, 0x00, 0x08,
+ 0x7c, 0xe4, 0xff, 0xe8, 0x8c, 0x66, 0x05, 0x08, 0xfb, 0x82, 0x00, 0x10, 0x9b, 0x82, 0xff, 0x88,
+ 0x0b, 0x0c, 0x17, 0xa0, 0xfb, 0x03, 0x2a, 0x52, 0xc1, 0x60, 0x00, 0x00, 0x23, 0x0c, 0x00, 0xac,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x70, 0x0e, 0x00, 0x10, 0xeb, 0x08, 0x00, 0x53, 0x8f, 0x8f, 0xff, 0xa0,
+ 0x90, 0x02, 0xfe, 0x42, 0x83, 0x8e, 0x00, 0x10, 0x01, 0x8c, 0x00, 0xc0, 0x7e, 0xfc, 0xff, 0xf0,
+ 0x20, 0x76, 0x78, 0x17, 0xe6, 0x00, 0xfb, 0x19, 0x0f, 0x0c, 0x17, 0x50, 0x43, 0x74, 0x07, 0xff,
+ 0x7e, 0x18, 0x00, 0x02, 0x8d, 0xf2, 0x07, 0x08, 0x21, 0xf8, 0x17, 0xa0, 0xff, 0x03, 0x2a, 0x52,
+ 0x4d, 0x74, 0xf8, 0x00, 0x20, 0x6a, 0x90, 0x00, 0xe7, 0x6c, 0x00, 0x03, 0x43, 0xfd, 0x00, 0x00,
+ 0x23, 0x0c, 0x00, 0x70, 0xe0, 0x00, 0xff, 0x4c, 0xc3, 0xfc, 0x00, 0x00, 0xc3, 0x0c, 0x00, 0x00,
+ 0xe0, 0x00, 0xff, 0x4c, 0x90, 0x02, 0xfe, 0x42, 0x7c, 0x9c, 0x00, 0x08, 0x7c, 0xe4, 0xff, 0xe8,
+ 0x8c, 0x66, 0x05, 0x08, 0xfb, 0x82, 0x00, 0x10, 0x9b, 0x82, 0xff, 0x88, 0x0b, 0x0c, 0x17, 0xa0,
+ 0xfb, 0x03, 0x2a, 0x52, 0xc1, 0x60, 0x00, 0x00, 0x23, 0x0c, 0x00, 0xac, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x7e, 0x9c, 0xff, 0xe5, 0xce, 0x1c, 0x00, 0x00, 0x20, 0x76, 0x00, 0x0c, 0xcd, 0x98, 0x00, 0x00,
+ 0xe6, 0x00, 0xfc, 0x31, 0x7d, 0x1c, 0xff, 0xf0, 0x20, 0x76, 0x00, 0x12, 0xe6, 0x00, 0xfb, 0xe5,
+ 0x7f, 0x9c, 0xff, 0xe3, 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x00, 0xfb, 0x95, 0xfd, 0x8a, 0xa5, 0xa0,
+ 0xf7, 0x82, 0xfb, 0x8c, 0xe0, 0x00, 0xf5, 0x40, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xfc, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x6f, 0x58, 0x9a, 0x2e, 0xf4, 0x00, 0x0c, 0x7f, 0xf4, 0xff, 0xff,
+ 0xfe, 0x03, 0x1a, 0xa8, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x82, 0xff, 0xfc,
+ 0xce, 0x70, 0xfc, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x8a, 0xa5, 0x78, 0xaf, 0xf6, 0xf8, 0x02,
+ 0xff, 0x6f, 0x68, 0x9a, 0xff, 0x0a, 0xa5, 0x88, 0x9f, 0xf2, 0x04, 0x00, 0xaf, 0xf6, 0xf0, 0x02,
+ 0xf7, 0x82, 0xfb, 0xdc, 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xfc, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x98, 0x00, 0x10, 0x4f, 0xfc, 0x7f, 0xff, 0x01, 0xfc, 0x00, 0x60,
+ 0xff, 0x02, 0x00, 0x00, 0x0f, 0xfc, 0x18, 0x00, 0xff, 0x83, 0x2a, 0x52, 0xc0, 0x7a, 0xf2, 0x00,
+ 0xe6, 0x00, 0xfc, 0x11, 0x43, 0x68, 0x00, 0x0f, 0x9f, 0x02, 0xff, 0x88, 0x43, 0x68, 0x00, 0x0f,
+ 0x7f, 0x99, 0x00, 0x02, 0x8f, 0x7e, 0x07, 0x08, 0x43, 0xf1, 0x00, 0x00, 0xf7, 0x82, 0xfc, 0x28,
+ 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xfc, 0x90, 0x00, 0x00, 0x00, 0x01,
+ 0x4f, 0xe8, 0x07, 0xff, 0x0f, 0x7c, 0x00, 0x03, 0x7f, 0x78, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x04,
+ 0xcf, 0x18, 0xf0, 0x00, 0x24, 0x7c, 0x00, 0x05, 0x4f, 0x78, 0x7f, 0xff, 0x01, 0xf8, 0x00, 0x60,
+ 0x0f, 0x78, 0x18, 0x00, 0xff, 0x03, 0x2a, 0x52, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xfc, 0x6d,
+ 0x03, 0x6c, 0x00, 0x0c, 0x94, 0x02, 0xff, 0x88, 0x03, 0x6c, 0x00, 0x0c, 0x43, 0x18, 0x7f, 0xff,
+ 0x83, 0x99, 0x00, 0x04, 0x4f, 0x9d, 0x00, 0xff, 0x7f, 0xfc, 0xff, 0xee, 0x7f, 0xfd, 0x00, 0x02,
+ 0x8f, 0x7e, 0x06, 0x08, 0xf7, 0x82, 0xfc, 0x90, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x7e, 0x9c, 0xff, 0xe5, 0xce, 0x1c, 0x00, 0x00, 0x20, 0x76, 0x00, 0x0e,
+ 0xcd, 0x98, 0x00, 0x00, 0xe6, 0x00, 0xfd, 0x85, 0x7d, 0x1c, 0xff, 0xf0, 0x20, 0x76, 0x00, 0x12,
+ 0xe6, 0x00, 0xfd, 0x39, 0x7f, 0x9c, 0xff, 0xe3, 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x00, 0xfc, 0xe9,
+ 0xfd, 0x8a, 0xa5, 0xa0, 0xf7, 0x82, 0xfc, 0xe0, 0xe0, 0x00, 0xf5, 0x40, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xfd, 0xe4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x6f, 0x58, 0x9a, 0x2e, 0xf4, 0x00, 0x0c,
+ 0x7f, 0xf4, 0xff, 0xff, 0xfe, 0x03, 0x1a, 0xa8, 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00,
+ 0xff, 0x82, 0xff, 0xfc, 0xce, 0x70, 0xfc, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x8a, 0xa5, 0x78,
+ 0xaf, 0xf6, 0xf8, 0x02, 0xff, 0x6f, 0x68, 0x9a, 0xff, 0x0a, 0xa5, 0x88, 0x9f, 0xf2, 0x04, 0x00,
+ 0xaf, 0xf6, 0xf0, 0x02, 0xf7, 0x82, 0xfd, 0x30, 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xfd, 0xe4, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x98, 0x00, 0x10, 0x4f, 0xfc, 0x7f, 0xff,
+ 0x01, 0xfc, 0x00, 0x60, 0xff, 0x02, 0x00, 0x00, 0x0f, 0xfc, 0x18, 0x00, 0xff, 0x83, 0x2a, 0x52,
+ 0xc0, 0x7a, 0xf2, 0x00, 0xe6, 0x00, 0xfd, 0x65, 0x43, 0x68, 0x00, 0x0f, 0x9f, 0x02, 0xff, 0x88,
+ 0x43, 0x68, 0x00, 0x0f, 0x7f, 0x99, 0x00, 0x02, 0x8f, 0x7e, 0x07, 0x08, 0x43, 0xf1, 0x00, 0x00,
+ 0xf7, 0x82, 0xfd, 0x7c, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xfd, 0xe4,
+ 0x00, 0x00, 0x00, 0x01, 0x4f, 0xe8, 0x07, 0xff, 0x0f, 0x7c, 0x00, 0x03, 0x7f, 0x78, 0xff, 0xfe,
+ 0x7f, 0x79, 0x00, 0x04, 0xcf, 0x18, 0xf0, 0x00, 0x24, 0x7c, 0x00, 0x06, 0x4f, 0x78, 0x7f, 0xff,
+ 0x01, 0xf8, 0x00, 0x60, 0x0f, 0x78, 0x18, 0x00, 0xff, 0x03, 0x2a, 0x52, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x00, 0xfd, 0xc1, 0x03, 0x6c, 0x00, 0x0c, 0x94, 0x02, 0xff, 0x88, 0x03, 0x6c, 0x00, 0x0c,
+ 0x43, 0x18, 0x7f, 0xff, 0x83, 0x99, 0x00, 0x04, 0x4f, 0x9d, 0x00, 0xff, 0x7f, 0xfc, 0xff, 0xee,
+ 0x7f, 0xfd, 0x00, 0x02, 0x8f, 0x7e, 0x06, 0x08, 0xf7, 0x82, 0xfd, 0xe4, 0xc1, 0x78, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x7e, 0x9c, 0xff, 0xe5, 0xce, 0x1c, 0x00, 0x00,
+ 0x20, 0x76, 0x00, 0x0d, 0xcd, 0x98, 0x00, 0x00, 0xe6, 0x00, 0xfe, 0xd9, 0x7d, 0x1c, 0xff, 0xf0,
+ 0x20, 0x76, 0x00, 0x12, 0xe6, 0x00, 0xfe, 0x8d, 0x7f, 0x9c, 0xff, 0xe3, 0x20, 0x7e, 0x00, 0x03,
+ 0xe6, 0x00, 0xfe, 0x3d, 0xfd, 0x8a, 0xa5, 0xa0, 0xf7, 0x82, 0xfe, 0x34, 0xe0, 0x00, 0xf5, 0x40,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xff, 0x38, 0x00, 0x00, 0x00, 0x01, 0xff, 0x6f, 0x58, 0x9a,
+ 0x2e, 0xf4, 0x00, 0x0c, 0x7f, 0xf4, 0xff, 0xff, 0xfe, 0x03, 0x1a, 0xa8, 0xcf, 0x84, 0xfe, 0x00,
+ 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x82, 0xff, 0xfc, 0xce, 0x70, 0xfc, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xff, 0x8a, 0xa5, 0x78, 0xaf, 0xf6, 0xf8, 0x02, 0xff, 0x6f, 0x68, 0x9a, 0xff, 0x0a, 0xa5, 0x88,
+ 0x9f, 0xf2, 0x04, 0x00, 0xaf, 0xf6, 0xf0, 0x02, 0xf7, 0x82, 0xfe, 0x84, 0xc1, 0x7c, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0xff, 0x38, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x98, 0x00, 0x10,
+ 0x4f, 0xfc, 0x7f, 0xff, 0x01, 0xfc, 0x00, 0x60, 0xff, 0x02, 0x00, 0x00, 0x0f, 0xfc, 0x18, 0x00,
+ 0xff, 0x83, 0x2a, 0x52, 0xc0, 0x7a, 0xf2, 0x00, 0xe6, 0x00, 0xfe, 0xb9, 0x43, 0x68, 0x00, 0x0f,
+ 0x9f, 0x02, 0xff, 0x88, 0x43, 0x68, 0x00, 0x0f, 0x7f, 0x99, 0x00, 0x02, 0x8f, 0x7e, 0x07, 0x08,
+ 0x43, 0xf1, 0x00, 0x00, 0xf7, 0x82, 0xfe, 0xd0, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x00, 0xff, 0x38, 0x00, 0x00, 0x00, 0x01, 0x4f, 0xe8, 0x07, 0xff, 0x0f, 0x7c, 0x00, 0x03,
+ 0x7f, 0x78, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x04, 0xcf, 0x18, 0xf0, 0x00, 0x24, 0x7c, 0x00, 0x06,
+ 0x4f, 0x78, 0x7f, 0xff, 0x01, 0xf8, 0x00, 0x60, 0x0f, 0x78, 0x18, 0x00, 0xff, 0x03, 0x2a, 0x52,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x00, 0xff, 0x15, 0x03, 0x6c, 0x00, 0x10, 0x94, 0x02, 0xff, 0x88,
+ 0x03, 0x6c, 0x00, 0x10, 0x43, 0x18, 0x7f, 0xff, 0x83, 0x99, 0x00, 0x04, 0x4f, 0x9d, 0x00, 0xff,
+ 0x7f, 0xfc, 0xff, 0xee, 0x7f, 0xfd, 0x00, 0x02, 0x8f, 0x7e, 0x06, 0x08, 0xf7, 0x82, 0xff, 0x38,
+ 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x7e, 0x9c, 0xff, 0xe5,
+ 0xce, 0x1c, 0x00, 0x00, 0x20, 0x76, 0x00, 0x0f, 0xcd, 0x98, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x2d,
+ 0x7d, 0x1c, 0xff, 0xf0, 0x20, 0x76, 0x00, 0x12, 0xe6, 0x00, 0xff, 0xe1, 0x7f, 0x9c, 0xff, 0xe3,
+ 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x00, 0xff, 0x91, 0xfd, 0x8a, 0xa5, 0xa0, 0xf7, 0x82, 0xff, 0x88,
+ 0xe0, 0x00, 0xf5, 0x40, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x6f, 0x58, 0x9a, 0x2e, 0xf4, 0x00, 0x0c, 0x7f, 0xf4, 0xff, 0xff, 0xfe, 0x03, 0x1a, 0xa8,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0x78, 0xfc, 0x00, 0xff, 0x82, 0xff, 0xfc, 0xce, 0x70, 0xfc, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x8a, 0xa5, 0x78, 0xaf, 0xf6, 0xf8, 0x02, 0xff, 0x6f, 0x68, 0x9a,
+ 0xff, 0x0a, 0xa5, 0x88, 0x9f, 0xf2, 0x04, 0x00, 0xaf, 0xf6, 0xf0, 0x02, 0xf7, 0x82, 0xff, 0xd8,
+ 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0x0f, 0x98, 0x00, 0x10, 0x4f, 0xfc, 0x7f, 0xff, 0x01, 0xfc, 0x00, 0x60, 0xff, 0x02, 0x00, 0x00,
+ 0x0f, 0xfc, 0x18, 0x00, 0xff, 0x83, 0x2a, 0x52, 0xc0, 0x7a, 0xf2, 0x00, 0xe6, 0x01, 0x00, 0x0d,
+ 0x43, 0x68, 0x00, 0x0f, 0x9f, 0x02, 0xff, 0x88, 0x43, 0x68, 0x00, 0x0f, 0x7f, 0x99, 0x00, 0x02,
+ 0x8f, 0x7e, 0x07, 0x08, 0x43, 0xf1, 0x00, 0x00, 0xf7, 0x86, 0x00, 0x24, 0xc1, 0x78, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x01, 0x4f, 0xe8, 0x07, 0xff,
+ 0x0f, 0x7c, 0x00, 0x03, 0x7f, 0x78, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x04, 0xcf, 0x18, 0xf0, 0x00,
+ 0x24, 0x7c, 0x00, 0x07, 0x4f, 0x78, 0x7f, 0xff, 0x01, 0xf8, 0x00, 0x60, 0x0f, 0x78, 0x18, 0x00,
+ 0xff, 0x03, 0x2a, 0x52, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x69, 0x03, 0x6c, 0x00, 0x10,
+ 0x94, 0x02, 0xff, 0x88, 0x03, 0x6c, 0x00, 0x10, 0x43, 0x18, 0x7f, 0xff, 0x83, 0x99, 0x00, 0x04,
+ 0x4f, 0x9d, 0x00, 0xff, 0x7f, 0xfc, 0xff, 0xee, 0x7f, 0xfd, 0x00, 0x02, 0x8f, 0x7e, 0x06, 0x08,
+ 0xf7, 0x86, 0x00, 0x8c, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x00, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x00, 0x7f, 0xf9, 0x00, 0x02, 0xfe, 0x86, 0x00, 0xe8, 0x9e, 0xfe, 0x06, 0x08,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x86, 0x00, 0xa0, 0x20, 0x7a, 0x00, 0x3f, 0xe2, 0x01, 0x01, 0x35,
+ 0x9e, 0xfe, 0x05, 0x08, 0xff, 0x82, 0xa8, 0x4c, 0xfe, 0x82, 0xaa, 0x74, 0xff, 0x81, 0x06, 0x04,
+ 0xfe, 0x81, 0x07, 0x04, 0xf0, 0x09, 0xcd, 0xc8, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x20, 0x1a, 0x00, 0x00,
+ 0xe6, 0x01, 0x01, 0x95, 0x03, 0x19, 0x00, 0x1e, 0xff, 0xf6, 0xed, 0xa0, 0x83, 0x7e, 0x00, 0x04,
+ 0x03, 0x19, 0x00, 0x1e, 0xf7, 0x86, 0x01, 0xa0, 0xe0, 0x00, 0xb6, 0xfc, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x86, 0x01, 0xcc, 0xe0, 0x00, 0x7d, 0x14, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x02, 0x10, 0x00,
+ 0xc0, 0x22, 0xf4, 0x00, 0xe6, 0x01, 0x03, 0xe4, 0x94, 0x16, 0xff, 0xf4, 0x8f, 0x96, 0xff, 0xf4,
+ 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x01, 0x02, 0x08, 0x00, 0x00, 0x00, 0x01, 0xff, 0x83, 0x1b, 0x9a,
+ 0xff, 0x02, 0x10, 0x00, 0x4f, 0xfd, 0x00, 0x00, 0xc0, 0x7e, 0xf4, 0x00, 0xe6, 0x01, 0x03, 0xd0,
+ 0xf3, 0x02, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xf4, 0x70, 0x7e, 0x00, 0x0a, 0xea, 0x01, 0x03, 0xbd,
+ 0xf3, 0x02, 0x00, 0x02, 0x8f, 0x16, 0xff, 0xf4, 0x70, 0x7a, 0x00, 0x0b, 0xea, 0x01, 0x03, 0xa9,
+ 0xf3, 0x02, 0x00, 0x03, 0x8f, 0x96, 0xff, 0xf4, 0x70, 0x7e, 0x00, 0x0c, 0xea, 0x01, 0x03, 0x8d,
+ 0xf3, 0x02, 0x00, 0x00, 0x8f, 0x16, 0xff, 0xf4, 0x70, 0x7a, 0x00, 0x0d, 0xea, 0x01, 0x03, 0x71,
+ 0xf3, 0x02, 0x00, 0x00, 0x8f, 0x16, 0xff, 0xf4, 0xff, 0x8e, 0x80, 0x00, 0xc0, 0x7a, 0xfc, 0x00,
+ 0xe6, 0x01, 0x03, 0x54, 0xf3, 0x02, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xf4, 0x70, 0x7e, 0x00, 0x11,
+ 0xea, 0x01, 0x03, 0x39, 0xf3, 0x02, 0x00, 0x00, 0x8f, 0x16, 0xff, 0xf4, 0x70, 0x7a, 0x00, 0x12,
+ 0xea, 0x01, 0x03, 0x1d, 0xf3, 0x02, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xf4, 0x70, 0x7e, 0x00, 0x14,
+ 0xea, 0x01, 0x03, 0x01, 0xf3, 0x02, 0x00, 0x00, 0x8f, 0x16, 0xff, 0xf4, 0x70, 0x7a, 0x00, 0x15,
+ 0xea, 0x01, 0x02, 0xe5, 0xf3, 0x02, 0x00, 0x00, 0xff, 0x88, 0xce, 0xc0, 0x4f, 0xfc, 0xfb, 0xff,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x02, 0xb0, 0xff, 0x89, 0xce, 0xc0, 0x45, 0x29, 0x7f, 0xff,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x02, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x27, 0xf4, 0x02, 0x00, 0x01, 0xf7, 0x86, 0x02, 0xf8,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x04, 0xf4, 0x02, 0x00, 0x01, 0xf7, 0x86, 0x03, 0x14, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x88, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x13,
+ 0xc4, 0x18, 0x00, 0x00, 0xf7, 0x86, 0x03, 0x30, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x01, 0x02, 0x78, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x12, 0xc4, 0x18, 0x00, 0x00,
+ 0xf7, 0x86, 0x03, 0x4c, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x68,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x10, 0xf4, 0x02, 0x00, 0x01, 0xf7, 0x86, 0x03, 0x68,
+ 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x58, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x0c, 0xc4, 0x18, 0x00, 0x00, 0xf7, 0x86, 0x03, 0x84, 0xe0, 0x00, 0xbe, 0x08,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x44, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x11,
+ 0xc4, 0x18, 0x00, 0x00, 0xf7, 0x86, 0x03, 0xa0, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x03, 0xb4, 0xe0, 0x00, 0x7b, 0x5c,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x24, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x03, 0xc8,
+ 0xe0, 0x00, 0x7b, 0x5c, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x14, 0x00, 0x00, 0x00, 0x01,
+ 0xf7, 0x86, 0x03, 0xdc, 0xe0, 0x00, 0x9a, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x02, 0x04,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x26, 0xc4, 0x18, 0x00, 0x00,
+ 0xf7, 0x86, 0x03, 0xfc, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xa0, 0x48,
+ 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x01, 0x01, 0xdc, 0xff, 0x89, 0xa0, 0x48, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x04, 0xf7, 0x86, 0x04, 0x30, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x88, 0xa0, 0x34, 0xf3, 0x82, 0x00, 0x01, 0xf3, 0x02, 0x00, 0x02, 0xcd, 0xfc, 0x38, 0x00,
+ 0xfd, 0x89, 0xa0, 0x34, 0xf7, 0x86, 0x04, 0x50, 0xe0, 0x00, 0x7d, 0x14, 0x97, 0x93, 0xff, 0xfc,
+ 0xfd, 0x88, 0xa0, 0x34, 0xff, 0x02, 0x3d, 0x09, 0x9f, 0x02, 0xff, 0xa8, 0xfe, 0x88, 0xce, 0xd0,
+ 0xff, 0x02, 0x00, 0x1f, 0x7f, 0xec, 0xff, 0xfe, 0xcf, 0xfc, 0xf4, 0x00, 0xcf, 0x00, 0xfa, 0x00,
+ 0xcf, 0x74, 0xf7, 0x80, 0xfe, 0x03, 0x5b, 0xd8, 0xce, 0xf8, 0x00, 0x00, 0xff, 0x02, 0x00, 0x0e,
+ 0xff, 0x82, 0x00, 0x01, 0xce, 0x70, 0xf4, 0x00, 0xce, 0xf4, 0xfc, 0x00, 0xce, 0x70, 0xed, 0x00,
+ 0xfe, 0x03, 0x6b, 0xd8, 0x77, 0xec, 0x00, 0x1c, 0x70, 0x3e, 0xff, 0xe4, 0xe6, 0x01, 0x06, 0x09,
+ 0x00, 0x00, 0x00, 0x01, 0x70, 0x22, 0x00, 0x13, 0xea, 0x01, 0x06, 0x09, 0xff, 0x82, 0x00, 0xc0,
+ 0xc0, 0x22, 0xfc, 0x00, 0xe6, 0x01, 0x04, 0xe0, 0xff, 0x82, 0x00, 0x0f, 0x9d, 0x96, 0xff, 0xf4,
+ 0xf7, 0x86, 0x04, 0xcc, 0xe0, 0x00, 0xb6, 0xe4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xe6, 0x78,
+ 0x8d, 0x96, 0xff, 0xf4, 0xc0, 0x7e, 0x42, 0x00, 0xe6, 0x01, 0x05, 0xed, 0xff, 0x82, 0x00, 0x0f,
+ 0xcf, 0xec, 0xfc, 0x00, 0x20, 0x7e, 0x00, 0x08, 0xe6, 0x01, 0x05, 0x61, 0xff, 0x8a, 0xa5, 0xa0,
+ 0xf5, 0x09, 0xa9, 0x98, 0xf5, 0x89, 0xcf, 0xc0, 0xf7, 0x86, 0x05, 0x04, 0xe0, 0x00, 0xb6, 0xe4,
+ 0x97, 0x93, 0xff, 0xfc, 0xf4, 0x09, 0xe6, 0x78, 0xf7, 0x86, 0x05, 0x14, 0xe0, 0x02, 0x6f, 0x0c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x86, 0x05, 0x20, 0xe0, 0x00, 0xa6, 0xa0, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x82, 0x3d, 0x09, 0x9f, 0x82, 0xff, 0xa8, 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x05, 0x2c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0xff, 0x58, 0x99, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x04, 0xf0, 0x00, 0x00, 0x00, 0x01,
+ 0x9f, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x05, 0x84, 0xe0, 0x00, 0x34, 0xa0,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x28, 0xf7, 0x86, 0x05, 0x94, 0xe0, 0x00, 0x7c, 0x3c,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xd8, 0x5f, 0xfc, 0x00, 0x02, 0xff, 0x83, 0x6b, 0xd8,
+ 0xf7, 0x86, 0x05, 0xac, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x0f, 0x81, 0x01, 0x00,
+ 0x9f, 0x82, 0xff, 0xf8, 0xf3, 0x02, 0x00, 0x14, 0xf7, 0x86, 0x05, 0xc4, 0xe0, 0x00, 0x7c, 0x3c,
+ 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8, 0x0f, 0x01, 0x01, 0x00, 0xc0, 0x7e, 0xf4, 0x00,
+ 0xe6, 0x01, 0x05, 0xa0, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x05, 0xe4, 0xe0, 0x00, 0x21, 0x68,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x04, 0xf4, 0xf5, 0x09, 0xa9, 0x98, 0xf7, 0x86, 0x05, 0xf8,
+ 0xe0, 0x01, 0xa8, 0x18, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x88, 0xcf, 0xb0, 0xc0, 0x22, 0xfd, 0x00,
+ 0xe6, 0x01, 0x06, 0x1d, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x06, 0x14, 0xe0, 0x00, 0xbf, 0xd8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x04, 0xf4, 0xf5, 0x09, 0xa9, 0x98, 0xfd, 0x88, 0xa0, 0x34,
+ 0xe0, 0x01, 0x04, 0xe0, 0xff, 0x82, 0x00, 0x0f, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c,
+ 0x8f, 0x2e, 0x00, 0x30, 0xff, 0x88, 0xd3, 0xd8, 0x9f, 0x16, 0xff, 0xec, 0x9f, 0x96, 0xff, 0xf4,
+ 0xff, 0x88, 0xe6, 0x20, 0xff, 0x02, 0x0f, 0xff, 0xc3, 0x18, 0xf4, 0x00, 0xc0, 0x7e, 0x32, 0x00,
+ 0xe6, 0x01, 0x06, 0xd9, 0x93, 0x16, 0xff, 0xf0, 0x8f, 0x16, 0xff, 0xec, 0x8f, 0x96, 0xff, 0xf4,
+ 0x4f, 0x78, 0xfc, 0xff, 0x9f, 0x16, 0xff, 0xec, 0x8f, 0x16, 0xff, 0xf0, 0xc0, 0x2e, 0xfa, 0x00,
+ 0xe6, 0x7c, 0x00, 0x02, 0xff, 0x09, 0xe6, 0x20, 0x8f, 0x16, 0xff, 0xec, 0x7f, 0xfd, 0x00, 0x08,
+ 0xcf, 0x78, 0xfd, 0x00, 0x9f, 0x2e, 0x00, 0x30, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x06, 0xa4, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xec, 0x70, 0x7e, 0x00, 0x17,
+ 0xea, 0x01, 0x06, 0x68, 0x00, 0x00, 0x00, 0x01, 0x70, 0x7e, 0x00, 0x16, 0xea, 0x01, 0x07, 0x24,
+ 0xf3, 0x02, 0x00, 0x06, 0xf3, 0x02, 0x00, 0x00, 0xf7, 0x86, 0x07, 0x04, 0xe0, 0x00, 0x9a, 0xa0,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x02, 0x00, 0x00, 0xf3, 0x82, 0x00, 0x2c, 0xf4, 0x02, 0x00, 0x01,
+ 0xf7, 0x86, 0x07, 0x1c, 0xe0, 0x00, 0xbe, 0x08, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x06, 0x68,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x07, 0x30, 0xe0, 0x00, 0x2e, 0xc0, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x96, 0xff, 0xf0, 0xff, 0x02, 0x0f, 0xff, 0xc4, 0x20, 0xf4, 0x00, 0xc0, 0x22, 0xfa, 0x00,
+ 0xe6, 0x01, 0x07, 0x8d, 0xff, 0x02, 0x00, 0x0f, 0x8f, 0xae, 0x00, 0x30, 0x5f, 0xfc, 0x02, 0x00,
+ 0x9f, 0xae, 0x00, 0x30, 0x9f, 0x02, 0xff, 0xb0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x07, 0x58, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa0, 0x60,
+ 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x01, 0x06, 0x68, 0xff, 0x89, 0xa0, 0x60, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x42, 0x6f, 0x6f, 0x74, 0x20, 0x64, 0x69, 0x73,
+ 0x70, 0x61, 0x74, 0x63, 0x68, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x25, 0x64, 0x0a, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08,
+ 0xff, 0x86, 0x07, 0xa8, 0x9f, 0x92, 0x00, 0x00, 0xff, 0x83, 0x1a, 0xa8, 0x4f, 0xfd, 0x00, 0x00,
+ 0x9f, 0x92, 0x00, 0x04, 0xf7, 0x86, 0x07, 0xf0, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc,
+ 0x02, 0x10, 0x00, 0x08, 0xe0, 0x01, 0x07, 0xf4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x08, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x90, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x00, 0x5f, 0xf8, 0x00, 0x40,
+ 0x9f, 0x82, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xf9, 0x00, 0x02, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x86, 0x07, 0xc8, 0x20, 0x7a, 0x00, 0x40, 0xe2, 0x01, 0x08, 0x6d, 0x9e, 0xfe, 0x04, 0x00,
+ 0xff, 0x82, 0x00, 0x80, 0x9f, 0x82, 0xfe, 0xb0, 0xff, 0x02, 0x00, 0x00, 0x9f, 0x02, 0xfe, 0xb8,
+ 0x9f, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8, 0x9f, 0x02, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0xc2, 0x00, 0x00, 0x9e, 0x82, 0xfe, 0xb0, 0x9f, 0x02, 0xfe, 0xb8, 0x9f, 0x02, 0xfe, 0xc0,
+ 0x9f, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x01, 0xff, 0x82, 0x85, 0xdc, 0x9f, 0x02, 0xfe, 0xd0,
+ 0xff, 0x81, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x92, 0x00, 0x00, 0x9e, 0x82, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0x90, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x02,
+ 0xff, 0x86, 0x04, 0x20, 0x9f, 0x02, 0xfe, 0xd0, 0xff, 0x81, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0x0e, 0x81, 0x00, 0x20, 0x9e, 0x82, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x90, 0x02, 0xfe, 0xc0,
+ 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x03, 0xff, 0x86, 0x01, 0xb4, 0x9f, 0x02, 0xfe, 0xd0,
+ 0xff, 0x81, 0x04, 0x08, 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x0e, 0x81, 0x80, 0x00, 0x9e, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x04,
+ 0xff, 0x86, 0x06, 0x3c, 0x9f, 0x02, 0xfe, 0xd0, 0xff, 0x81, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x82, 0x02, 0x00, 0x9e, 0x82, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x90, 0x02, 0xfe, 0xc0,
+ 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x05, 0xff, 0x82, 0xb4, 0xe4, 0x9f, 0x02, 0xfe, 0xd0,
+ 0xff, 0x81, 0x04, 0x10, 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x90, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x02, 0x00, 0x06, 0xfe, 0x82, 0xf8, 0xe0,
+ 0x9f, 0x02, 0xfe, 0xd0, 0xfe, 0x81, 0x04, 0x14, 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0x08, 0x10,
+ 0xff, 0x81, 0x04, 0x18, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf7, 0x86, 0x09, 0xc4, 0xe0, 0x01, 0x08, 0x50,
+ 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x86, 0x09, 0xd0, 0xe0, 0x01, 0x01, 0x28, 0x97, 0x93, 0xff, 0xfc,
+ 0x0f, 0x81, 0xe0, 0x00, 0xc5, 0x28, 0xfc, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0xf6, 0xed, 0xa0,
+ 0x8f, 0x7e, 0x10, 0x5c, 0x03, 0x01, 0xe1, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x0a, 0x10,
+ 0x03, 0x18, 0x16, 0x02, 0xf7, 0x86, 0x0a, 0x10, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x03, 0xf7, 0x86, 0x0a, 0x20, 0xe0, 0x00, 0x90, 0x20, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x01, 0xf7, 0x86, 0x0a, 0x30, 0xe0, 0x00, 0x96, 0xc8, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x02, 0x00, 0x01, 0xf7, 0x86, 0x0a, 0x40, 0xe0, 0x01, 0x01, 0x74, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x01, 0x0a, 0x91, 0xcf, 0x98, 0x00, 0x00,
+ 0xf0, 0x7f, 0x64, 0x01, 0x23, 0x9e, 0x00, 0x01, 0xe6, 0x01, 0x0a, 0x91, 0xcf, 0x7c, 0x32, 0x00,
+ 0x20, 0x7a, 0x00, 0xff, 0xee, 0x01, 0x0a, 0x61, 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68,
+ 0x93, 0x82, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfe, 0xd2, 0x00, 0x00, 0x8f, 0x76, 0x00, 0x00, 0x0f, 0x81, 0x6c, 0x6f,
+ 0x0f, 0xfc, 0x61, 0x65, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x0b, 0x2c, 0xff, 0xd2, 0x00, 0x00,
+ 0x83, 0xf6, 0x00, 0x04, 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x01, 0x0b, 0x2d, 0xcf, 0x1c, 0xe8, 0x00,
+ 0xff, 0xf6, 0xfe, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe2, 0x01, 0x0b, 0x28, 0x5e, 0x1d, 0x80, 0x00,
+ 0x8f, 0x76, 0x00, 0x08, 0x90, 0x76, 0x00, 0x00, 0xff, 0xd2, 0x00, 0x0c, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x82, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0x88, 0xf4, 0x02, 0x00, 0x00, 0xf3, 0x52, 0x00, 0x0c, 0xcf, 0x84, 0xfe, 0x00,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x0b, 0x28, 0xc4, 0xa0, 0x00, 0x00, 0xf7, 0x86, 0x0b, 0x28,
+ 0xe0, 0x00, 0xae, 0xc4, 0x97, 0x93, 0xff, 0xfc, 0xff, 0xd2, 0x00, 0x00, 0x90, 0x7e, 0x00, 0x08,
+ 0x90, 0x7e, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x52, 0x53, 0x3d, 0x25, 0x78, 0x68, 0x2c, 0x25, 0x63, 0x2c, 0x25, 0x73, 0x0a, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x18, 0xf3, 0x0a, 0xa7, 0x50,
+ 0xf3, 0xa6, 0x34, 0x5f, 0xc3, 0x9c, 0x32, 0x00, 0xf7, 0x86, 0x0b, 0x74, 0xe0, 0x01, 0x0a, 0x4c,
+ 0x97, 0x93, 0xff, 0xfc, 0xfe, 0x8a, 0xa5, 0xa0, 0xff, 0xf7, 0x58, 0x98, 0x20, 0x7e, 0x00, 0x01,
+ 0xe6, 0x01, 0x0b, 0xad, 0xff, 0x82, 0x00, 0x40, 0xfe, 0x82, 0x00, 0x04, 0xc0, 0x7e, 0xec, 0x00,
+ 0xe6, 0x01, 0x0b, 0x9c, 0xff, 0x02, 0x00, 0x00, 0xff, 0x08, 0xa5, 0x98, 0x9f, 0x7d, 0x00, 0x04,
+ 0x20, 0x7e, 0x01, 0xff, 0xee, 0x01, 0x0b, 0x91, 0xc0, 0x7e, 0xec, 0x00, 0xf7, 0x86, 0x0b, 0xb8,
+ 0xe0, 0x00, 0x34, 0x30, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xe8, 0xff, 0x02, 0x00, 0x04,
+ 0xfe, 0x82, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x18, 0x7f, 0xfc, 0xff, 0xe8, 0xcf, 0xfe, 0xf4, 0x00,
+ 0x9e, 0x96, 0xff, 0xf4, 0xe6, 0x01, 0x0e, 0x3d, 0x9f, 0x96, 0xff, 0xf0, 0x22, 0x10, 0x00, 0x10,
+ 0xfe, 0x86, 0x0b, 0x40, 0x9e, 0x92, 0x00, 0x00, 0x8f, 0x82, 0xff, 0xf0, 0x8e, 0x96, 0xff, 0xf4,
+ 0xff, 0x0a, 0xa0, 0x38, 0xff, 0x09, 0xa6, 0x3c, 0x9f, 0x92, 0x00, 0x04, 0x20, 0x76, 0x00, 0x00,
+ 0xcf, 0x90, 0x00, 0x00, 0xe6, 0x01, 0x0c, 0x10, 0xff, 0x02, 0x00, 0x43, 0xff, 0x02, 0x00, 0x57,
+ 0x9f, 0x7e, 0x00, 0x08, 0xff, 0x0a, 0xa5, 0xa4, 0x9f, 0x7e, 0x00, 0x0c, 0xf7, 0x86, 0x0c, 0x28,
+ 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xe8, 0x70, 0x7e, 0x00, 0x1d,
+ 0xea, 0x01, 0x0c, 0x49, 0x02, 0x10, 0x00, 0x10, 0x8f, 0x96, 0xff, 0xf4, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x0e, 0x29, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x0c, 0x54, 0xe0, 0x00, 0x8e, 0x98,
+ 0x97, 0x93, 0xff, 0xfc, 0x05, 0x01, 0x40, 0x00, 0xf7, 0x86, 0x0c, 0x64, 0xe0, 0x01, 0x08, 0x50,
+ 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x86, 0x0c, 0x70, 0xe0, 0x01, 0x01, 0x28, 0x97, 0x93, 0xff, 0xfc,
+ 0xf7, 0x86, 0x0c, 0x7c, 0xe0, 0x00, 0x0a, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x86, 0x0c, 0x88,
+ 0xe0, 0x02, 0x70, 0x24, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x86, 0x0c, 0x94, 0xe0, 0x00, 0x20, 0x24,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xe8, 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x01, 0x0c, 0xdd,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xf4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x01, 0x0c, 0xb8,
+ 0xf3, 0x02, 0x00, 0x43, 0xf3, 0x02, 0x00, 0x57, 0xf7, 0x86, 0x0c, 0xc4, 0xe0, 0x00, 0x21, 0x54,
+ 0x97, 0x93, 0xff, 0xfc, 0x83, 0x02, 0xff, 0xf0, 0x73, 0x18, 0xff, 0xe6, 0x03, 0x18, 0x00, 0x30,
+ 0xf7, 0x86, 0x0c, 0xdc, 0xe0, 0x00, 0x21, 0x54, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x83, 0x5b, 0xe8,
+ 0xff, 0x02, 0x03, 0x0f, 0x70, 0x7e, 0x00, 0x1d, 0xea, 0x01, 0x0e, 0x14, 0xff, 0x09, 0xce, 0xd0,
+ 0xf0, 0x09, 0xa0, 0x00, 0xf7, 0x86, 0x0d, 0x00, 0xe0, 0x01, 0x09, 0xe4, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x76, 0xed, 0xa0, 0x8c, 0xfa, 0x10, 0x54, 0xcf, 0x84, 0x00, 0x00, 0xc0, 0x66, 0xfa, 0x00,
+ 0xe6, 0x01, 0x0d, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x8d, 0x7a, 0x10, 0x50, 0xff, 0x88, 0xce, 0xc0,
+ 0xfe, 0x88, 0xd3, 0xd8, 0x20, 0x6a, 0x00, 0x00, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xfc, 0x00, 0x06,
+ 0x5f, 0x70, 0x00, 0x02, 0xff, 0x89, 0xce, 0xc0, 0x7f, 0x79, 0x00, 0x0d, 0xff, 0x77, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0xff, 0x02, 0x7c, 0xcc,
+ 0xfd, 0xfb, 0x58, 0x20, 0x7f, 0xfd, 0x00, 0x0f, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0xf7, 0x28, 0x0e,
+ 0x7e, 0x71, 0x00, 0x02, 0xcf, 0xf4, 0xe0, 0x00, 0xfd, 0xf7, 0x28, 0x12, 0x9d, 0x76, 0x00, 0x14,
+ 0x9c, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0x55, 0x29, 0x80, 0x00, 0xff, 0x86, 0x00, 0x01,
+ 0x9f, 0xf6, 0x00, 0x30, 0xff, 0x77, 0x18, 0x0a, 0x8d, 0xf6, 0x00, 0x2c, 0x0f, 0xf4, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x82, 0xac, 0x24, 0x9f, 0xf6, 0x00, 0x04,
+ 0xfd, 0x89, 0xd3, 0xd8, 0xff, 0x82, 0x00, 0x04, 0x9f, 0xf6, 0x00, 0x28, 0xff, 0xf6, 0xfd, 0xf8,
+ 0x9f, 0xf6, 0x00, 0x24, 0x9f, 0x82, 0xfe, 0x58, 0x0f, 0x81, 0x10, 0x00, 0x0f, 0xfc, 0x00, 0x04,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0f, 0x78, 0x00, 0x01, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00,
+ 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xf0, 0x77, 0x28, 0x02,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x0d, 0xe0,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x0e, 0x20, 0xe0, 0x00, 0x80, 0x08, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x01, 0x0d, 0xe0, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x0e, 0x34, 0xe0, 0x01, 0x0a, 0x9c,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x01, 0x0c, 0x48, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x86, 0x0e, 0x48,
+ 0xe0, 0x00, 0x8d, 0x50, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xf0, 0xff, 0x0a, 0xa5, 0xa0,
+ 0x94, 0x16, 0xff, 0xf4, 0xe0, 0x01, 0x0b, 0xdc, 0xff, 0xfb, 0x68, 0x99, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf2, 0x0a, 0xe8, 0x90, 0xf2, 0x82, 0x00, 0x00, 0xf7, 0x86, 0x0e, 0x88, 0xe0, 0x01, 0x0e, 0xec,
+ 0x97, 0x93, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x0e, 0x88, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x62, 0x63, 0x6f, 0x64,
+ 0x65, 0x5f, 0x6a, 0x6d, 0x70, 0x20, 0x52, 0x54, 0x43, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20,
+ 0x69, 0x74, 0x65, 0x72, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x52, 0x45, 0x42, 0x4f, 0x4f, 0x54, 0x5f,
+ 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x54, 0x72, 0x79,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x6a, 0x6d, 0x70, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20,
+ 0x74, 0x6f, 0x20, 0x7a, 0x65, 0x72, 0x6f, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x14, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x02, 0x00, 0x00,
+ 0x9f, 0x96, 0xff, 0xf4, 0x8f, 0x82, 0xff, 0xd0, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x01, 0x0f, 0x24,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x0f, 0x15,
+ 0x0f, 0x78, 0x00, 0x01, 0x22, 0x10, 0x00, 0x10, 0xff, 0x86, 0x0e, 0x9c, 0x9f, 0x92, 0x00, 0x00,
+ 0x8f, 0x96, 0xff, 0xf4, 0x9f, 0x12, 0x00, 0x08, 0x9f, 0x92, 0x00, 0x04, 0x8f, 0x82, 0xff, 0xf0,
+ 0x9f, 0x92, 0x00, 0x0c, 0xf7, 0x86, 0x0f, 0x50, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x96, 0xff, 0xf4, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x0f, 0x74, 0x02, 0x10, 0x00, 0x10,
+ 0xff, 0x83, 0x5b, 0xe8, 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x0f, 0x89,
+ 0xff, 0x1a, 0x1a, 0x7f, 0xf3, 0x02, 0x00, 0x04, 0xf7, 0x86, 0x0f, 0x84, 0xe0, 0x00, 0x7b, 0x5c,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0x1a, 0x1a, 0x7f, 0x8f, 0x82, 0xff, 0xd0, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xe2, 0x01, 0x0f, 0x89, 0xff, 0x86, 0x0e, 0xcd, 0x22, 0x10, 0x00, 0x04, 0x9f, 0x92, 0x00, 0x00,
+ 0xf7, 0x86, 0x0f, 0xac, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x07, 0x08,
+ 0x00, 0x00, 0x07, 0x48, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x76, 0xff, 0xd8,
+ 0x8f, 0xf2, 0x00, 0x00, 0x0f, 0x01, 0xff, 0xfc, 0x0f, 0x78, 0x03, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0xfe, 0x86, 0xd4, 0x00, 0xcf, 0xfc, 0xed, 0x00, 0x4f, 0xfd, 0xfc, 0x03, 0x5f, 0xfd, 0x02, 0x00,
+ 0x4f, 0xfd, 0x03, 0xff, 0x5f, 0xfd, 0x04, 0x00, 0x9f, 0xf2, 0x00, 0x00, 0xff, 0x76, 0xff, 0xd4,
+ 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0x76, 0xff, 0xd0, 0xfd, 0x76, 0xff, 0xcc, 0x5f, 0xfc, 0x00, 0x88,
+ 0x4f, 0xfc, 0x7e, 0x88, 0x4f, 0xfd, 0xff, 0xfc, 0x5f, 0xfd, 0x00, 0x06, 0x4f, 0xfd, 0xff, 0xe7,
+ 0x5f, 0xfd, 0x00, 0x10, 0x4f, 0xfd, 0xe7, 0xff, 0x5f, 0xfd, 0x10, 0x00, 0x9f, 0xfa, 0x00, 0x00,
+ 0x8e, 0xf2, 0x00, 0x00, 0xfd, 0xf6, 0xff, 0xc8, 0xf3, 0x76, 0xff, 0xfc, 0x5e, 0xf4, 0x00, 0x08,
+ 0x9e, 0xf2, 0x00, 0x00, 0x8f, 0x6a, 0x00, 0x00, 0x4f, 0x79, 0xef, 0xdf, 0x5f, 0x79, 0xe0, 0x00,
+ 0x9f, 0x6a, 0x00, 0x00, 0x8f, 0xee, 0x00, 0x00, 0x0f, 0x01, 0xff, 0xfe, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x5f, 0xfc, 0x00, 0x7e, 0x4f, 0xfd, 0xff, 0xc9, 0x5f, 0xfd, 0x07, 0x20, 0x9f, 0xee, 0x00, 0x00,
+ 0xf7, 0x86, 0x10, 0x8c, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x86, 0xc0, 0xf0, 0xff, 0x8d, 0x69, 0x44, 0xff, 0x86, 0xc3, 0x84,
+ 0xff, 0x8d, 0x69, 0xc4, 0xff, 0x88, 0xa6, 0x54, 0x20, 0x7e, 0x00, 0x01, 0xff, 0x86, 0xc6, 0x18,
+ 0xff, 0x8d, 0x6a, 0x44, 0xff, 0x86, 0xc8, 0xac, 0xff, 0x8d, 0x6a, 0xc4, 0xff, 0x86, 0xcb, 0x40,
+ 0xff, 0x8d, 0x6b, 0x44, 0xff, 0x86, 0xcd, 0xd4, 0xff, 0x8d, 0x6b, 0xc4, 0xff, 0x86, 0xa9, 0xc8,
+ 0xff, 0x8d, 0x69, 0x40, 0xff, 0x86, 0xaa, 0xc0, 0xff, 0x8d, 0x69, 0xc0, 0xff, 0x86, 0xab, 0xb8,
+ 0xff, 0x8d, 0x6a, 0x40, 0xff, 0x86, 0xac, 0xb0, 0xff, 0x8d, 0x6a, 0xc0, 0xff, 0x86, 0xad, 0xa8,
+ 0xff, 0x8d, 0x6b, 0x40, 0xff, 0x86, 0xae, 0xa0, 0xe6, 0x01, 0x11, 0x50, 0xff, 0x8d, 0x6b, 0xc0,
+ 0xff, 0x86, 0xd0, 0x68, 0xff, 0x8d, 0x69, 0x44, 0xff, 0x86, 0xd3, 0x20, 0xff, 0x8d, 0x69, 0xc4,
+ 0xff, 0x86, 0xd5, 0xd8, 0xff, 0x8d, 0x6a, 0x44, 0xff, 0x86, 0xd8, 0x90, 0xff, 0x8d, 0x6a, 0xc4,
+ 0xff, 0x86, 0xdb, 0x48, 0xff, 0x8d, 0x6b, 0x44, 0xff, 0x86, 0xde, 0x00, 0xff, 0x8d, 0x6b, 0xc4,
+ 0xff, 0x86, 0xaf, 0x98, 0xff, 0x8d, 0x69, 0x48, 0xff, 0x86, 0xb1, 0x08, 0xff, 0x8d, 0x69, 0xc8,
+ 0xff, 0x86, 0xb2, 0x78, 0xff, 0x8d, 0x6a, 0x48, 0xff, 0x86, 0xb3, 0xe8, 0xff, 0x8d, 0x6a, 0xc8,
+ 0xff, 0x86, 0xb5, 0x58, 0xff, 0x8d, 0x6b, 0x48, 0xff, 0x86, 0xb6, 0xc8, 0xff, 0x8d, 0x6b, 0xc8,
+ 0xff, 0x86, 0xb8, 0x38, 0xff, 0x8d, 0x69, 0x4c, 0xff, 0x86, 0xb9, 0xac, 0xff, 0x8d, 0x69, 0xcc,
+ 0xff, 0x86, 0xbb, 0x20, 0xff, 0x8d, 0x6a, 0x4c, 0xff, 0x86, 0xbc, 0x94, 0xff, 0x8d, 0x6a, 0xcc,
+ 0xff, 0x86, 0xbe, 0x08, 0xff, 0x8d, 0x6b, 0x4c, 0xff, 0x86, 0xbf, 0x7c, 0xff, 0x8d, 0x6b, 0xcc,
+ 0xff, 0x86, 0xe0, 0xb8, 0xff, 0x8d, 0x69, 0x50, 0xff, 0x86, 0xe2, 0x60, 0xff, 0x8d, 0x69, 0xd0,
+ 0xff, 0x86, 0xe4, 0x08, 0xff, 0x8d, 0x6a, 0x50, 0xff, 0x86, 0xe5, 0xb0, 0xff, 0x8d, 0x6a, 0xd0,
+ 0xff, 0x86, 0xe7, 0x58, 0xff, 0x8d, 0x6b, 0x50, 0xff, 0x86, 0xe9, 0x00, 0xff, 0x8d, 0x6b, 0xd0,
+ 0xff, 0x86, 0xea, 0xa8, 0xff, 0x8d, 0x69, 0x54, 0xff, 0x86, 0xec, 0x54, 0xff, 0x8d, 0x69, 0xd4,
+ 0xff, 0x86, 0xee, 0x00, 0xff, 0x8d, 0x6a, 0x54, 0xff, 0x86, 0xef, 0xac, 0xff, 0x8d, 0x6a, 0xd4,
+ 0xff, 0x86, 0xf1, 0x58, 0xff, 0x8d, 0x6b, 0x54, 0xff, 0x86, 0xf3, 0x04, 0xff, 0x8d, 0x6b, 0xd4,
+ 0xff, 0x86, 0xf4, 0xb0, 0xff, 0x8d, 0x69, 0x58, 0xff, 0x86, 0xf7, 0x10, 0xff, 0x8d, 0x69, 0xd8,
+ 0xff, 0x86, 0xf9, 0x70, 0xff, 0x8d, 0x6a, 0x58, 0xff, 0x86, 0xfb, 0xd0, 0xff, 0x8d, 0x6a, 0xd8,
+ 0xff, 0x86, 0xfe, 0x30, 0xff, 0x8d, 0x6b, 0x58, 0xff, 0x8a, 0x00, 0x90, 0xff, 0x8d, 0x6b, 0xd8,
+ 0xff, 0x8a, 0x02, 0xf0, 0xff, 0x8d, 0x69, 0x5c, 0xff, 0x8a, 0x05, 0x54, 0xff, 0x8d, 0x69, 0xdc,
+ 0xff, 0x8a, 0x07, 0xb8, 0xff, 0x8d, 0x6a, 0x5c, 0xff, 0x8a, 0x0a, 0x1c, 0xff, 0x8d, 0x6a, 0xdc,
+ 0xff, 0x8a, 0x0c, 0x80, 0xff, 0x8d, 0x6b, 0x5c, 0xff, 0x8a, 0x0e, 0xe4, 0xff, 0x8d, 0x6b, 0xdc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x8a, 0x11, 0x60, 0xff, 0x81, 0x06, 0x00, 0xff, 0x8a, 0x18, 0xe8,
+ 0xff, 0x81, 0x07, 0x00, 0xff, 0x8a, 0x1a, 0x98, 0xff, 0x81, 0x05, 0x28, 0xff, 0x8a, 0x1d, 0xf8,
+ 0xff, 0x81, 0x06, 0x28, 0xff, 0x8a, 0x1b, 0x70, 0xff, 0x81, 0x05, 0x2c, 0xff, 0x8a, 0x1d, 0xf8,
+ 0xff, 0x81, 0x06, 0x2c, 0xff, 0x8a, 0x1c, 0x48, 0xff, 0x81, 0x05, 0x30, 0xff, 0x8a, 0x1d, 0xf8,
+ 0xff, 0x81, 0x06, 0x30, 0xff, 0x8a, 0x1d, 0x20, 0xff, 0x81, 0x05, 0x34, 0xff, 0x8a, 0x1d, 0xf8,
+ 0xff, 0x81, 0x06, 0x34, 0xff, 0x8a, 0x1f, 0xa8, 0xff, 0x81, 0x05, 0x38, 0xff, 0x8a, 0x20, 0x80,
+ 0xff, 0x81, 0x06, 0x38, 0xff, 0x8a, 0x20, 0x14, 0xff, 0x81, 0x05, 0x3c, 0xff, 0x8a, 0x20, 0x80,
+ 0xff, 0x81, 0x06, 0x3c, 0xff, 0x8a, 0x22, 0x30, 0xff, 0x81, 0x06, 0xfc, 0xf0, 0x1d, 0x33, 0x28,
+ 0xf0, 0x0d, 0x38, 0xc8, 0xf0, 0x0d, 0x6c, 0xe8, 0xfe, 0x82, 0x00, 0x00, 0xfd, 0x8e, 0x69, 0x40,
+ 0xfe, 0x0e, 0x69, 0xc0, 0x20, 0x76, 0x00, 0x06, 0x7f, 0xf5, 0x00, 0x07, 0xe6, 0x01, 0x14, 0x05,
+ 0xff, 0x02, 0x00, 0x00, 0xcf, 0x7c, 0xe0, 0x00, 0xcf, 0xfc, 0xd8, 0x00, 0x0e, 0xf4, 0x00, 0x01,
+ 0x20, 0x76, 0x00, 0x06, 0xe2, 0x01, 0x13, 0x19, 0x9f, 0x7e, 0x00, 0x38, 0xff, 0x82, 0x00, 0x02,
+ 0xff, 0x8d, 0x69, 0x7c, 0xff, 0x82, 0x05, 0xf2, 0xff, 0x8d, 0x69, 0xfc, 0xff, 0x82, 0x0b, 0xe2,
+ 0xff, 0x8d, 0x6a, 0x7c, 0xff, 0x82, 0x11, 0xd2, 0xff, 0x8d, 0x6a, 0xfc, 0xff, 0x82, 0x36, 0x8a,
+ 0xff, 0x8d, 0x6b, 0x7c, 0xff, 0x82, 0x5b, 0x42, 0xff, 0x8d, 0x6b, 0xfc, 0xf7, 0x86, 0x13, 0x78,
+ 0xe0, 0x01, 0x10, 0xac, 0x97, 0x93, 0xff, 0xfc, 0xff, 0xa6, 0x34, 0x58, 0x0f, 0xfc, 0x7f, 0xff,
+ 0x4f, 0xfc, 0x80, 0x00, 0xff, 0x99, 0x73, 0x10, 0x0f, 0xfc, 0x60, 0x00, 0xff, 0x8d, 0x6d, 0x78,
+ 0x0f, 0xfc, 0x20, 0x00, 0xff, 0x9d, 0x33, 0x68, 0xff, 0x0e, 0x39, 0x30, 0xfe, 0x82, 0x00, 0x00,
+ 0xff, 0x82, 0x00, 0x06, 0xff, 0xfb, 0x24, 0x02, 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x76, 0x0b, 0xff,
+ 0xe2, 0x01, 0x13, 0xa5, 0x0f, 0xfc, 0x00, 0x10, 0xff, 0x0e, 0x51, 0x30, 0xfe, 0x82, 0x00, 0x00,
+ 0xff, 0x82, 0x00, 0x06, 0xff, 0xfb, 0x24, 0x02, 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x76, 0x0b, 0xff,
+ 0xe2, 0x01, 0x13, 0xc5, 0x0f, 0xfc, 0x00, 0x10, 0xff, 0x1a, 0x73, 0x20, 0xfe, 0x82, 0x00, 0x00,
+ 0xff, 0x82, 0x10, 0x00, 0xff, 0xfb, 0x24, 0x02, 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x76, 0x57, 0xff,
+ 0xe2, 0x01, 0x13, 0xe5, 0x0f, 0xfc, 0x00, 0x02, 0xff, 0x1e, 0x23, 0x20, 0xe0, 0x01, 0x14, 0x0c,
+ 0xfe, 0x82, 0x00, 0x00, 0xe0, 0x01, 0x13, 0x28, 0xff, 0x82, 0x03, 0x00, 0xcf, 0xf4, 0xe8, 0x00,
+ 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x76, 0x07, 0xff, 0xe2, 0x01, 0x14, 0x0d, 0xff, 0xfb, 0x24, 0x02,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08, 0xfe, 0x0c, 0x71, 0xc8, 0x8d, 0x82, 0xff, 0xd0,
+ 0xf4, 0x02, 0x00, 0x01, 0x0f, 0xf0, 0x00, 0x02, 0x20, 0x7e, 0x24, 0xb8, 0xe2, 0x01, 0x15, 0x80,
+ 0x9d, 0x96, 0xff, 0xf4, 0xff, 0x0c, 0x72, 0xe0, 0xc0, 0x7e, 0xf2, 0x00, 0xe2, 0x01, 0x14, 0xa1,
+ 0xfc, 0x8a, 0xa6, 0x78, 0x20, 0x7a, 0x0f, 0xff, 0xe2, 0x01, 0x15, 0x81, 0x7f, 0xf8, 0xff, 0xf4,
+ 0xc0, 0x7e, 0x42, 0x00, 0xe6, 0x01, 0x14, 0xa1, 0xfc, 0x8a, 0xa6, 0xb4, 0x20, 0x7e, 0x00, 0x02,
+ 0xe6, 0x01, 0x14, 0xa1, 0xfc, 0x8a, 0xa6, 0xa0, 0x20, 0x7e, 0x00, 0x04, 0xe6, 0x01, 0x14, 0xa1,
+ 0xfc, 0x8a, 0xa6, 0x8c, 0x20, 0x7e, 0x00, 0x08, 0xe6, 0x01, 0x15, 0x80, 0xfc, 0x8a, 0xa6, 0x78,
+ 0xfe, 0x82, 0x00, 0x00, 0x7f, 0xf5, 0x00, 0x02, 0x0e, 0xf4, 0x00, 0x01, 0xfd, 0x86, 0x3d, 0x00,
+ 0xff, 0x0e, 0x72, 0xf0, 0x20, 0x76, 0x00, 0x3f, 0xe2, 0x01, 0x14, 0xa5, 0xbd, 0xfe, 0xf0, 0x02,
+ 0x0e, 0xf0, 0x00, 0x05, 0x20, 0x76, 0xbf, 0xff, 0xe2, 0x01, 0x14, 0xec, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0xf5, 0x00, 0x02, 0x0e, 0xf4, 0x00, 0x01, 0xff, 0x06, 0x3d, 0x00, 0xfe, 0x0e, 0x72, 0xf0,
+ 0x20, 0x76, 0xbf, 0xff, 0xe2, 0x01, 0x14, 0xd1, 0xbf, 0x7e, 0xe0, 0x02, 0x9c, 0x96, 0xff, 0xf0,
+ 0xf7, 0x86, 0x14, 0xfc, 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x8c, 0x71, 0xc8,
+ 0x8c, 0x96, 0xff, 0xf0, 0xfe, 0x82, 0x00, 0x40, 0x0f, 0xfc, 0x00, 0x04, 0xc0, 0x76, 0xfa, 0x00,
+ 0xe2, 0x01, 0x15, 0x5c, 0xcd, 0xfc, 0x00, 0x00, 0xfd, 0x0c, 0x38, 0xb8, 0x2f, 0x74, 0x00, 0x04,
+ 0x0f, 0xf8, 0x10, 0x01, 0x7e, 0x75, 0x00, 0x02, 0x7f, 0xfc, 0xff, 0xf4, 0xc0, 0x7a, 0xd2, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0x0e, 0xf4, 0x00, 0x01, 0xe2, 0x01, 0x15, 0x45, 0xff, 0x0a, 0xa6, 0x64,
+ 0xcf, 0x64, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00, 0x8f, 0xfe, 0xff, 0xfc, 0xff, 0x0e, 0x72, 0xf0,
+ 0xc0, 0x76, 0xda, 0x00, 0xe2, 0x01, 0x15, 0x1d, 0xbf, 0xf2, 0xf0, 0x02, 0xf7, 0x86, 0x15, 0x68,
+ 0xe0, 0x00, 0x7e, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xd0, 0x8d, 0x96, 0xff, 0xf4,
+ 0xf4, 0x02, 0x00, 0x00, 0xcf, 0xfc, 0xda, 0x00, 0x5f, 0xfd, 0xfd, 0x00, 0x9f, 0x82, 0xfe, 0x88,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x6d, 0x63, 0x70, 0x5f,
+ 0x7a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x75, 0x70, 0x3a, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08, 0xf7, 0x86, 0x15, 0xc4, 0xe0, 0x01, 0x14, 0x2c,
+ 0x97, 0x93, 0xff, 0xfc, 0xc9, 0xa0, 0x00, 0x00, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x01, 0x17, 0x94,
+ 0xf4, 0x02, 0x00, 0x01, 0x99, 0x96, 0xff, 0xf4, 0xf3, 0x02, 0x00, 0x02, 0xf7, 0x86, 0x15, 0xe8,
+ 0xe0, 0x00, 0x7a, 0xe0, 0x97, 0x93, 0xff, 0xfc, 0xfe, 0x98, 0x73, 0x08, 0xff, 0x9c, 0x33, 0x68,
+ 0x89, 0x96, 0xff, 0xf4, 0x7f, 0x75, 0x00, 0x01, 0xcf, 0xfc, 0xf0, 0x00, 0xcf, 0x00, 0xf2, 0x00,
+ 0x0f, 0xfc, 0x0f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0xce, 0xfc, 0xe8, 0x00, 0xff, 0x76, 0xc9, 0xe7,
+ 0xc0, 0x76, 0xf2, 0x00, 0xff, 0x8d, 0x6d, 0x70, 0xff, 0x8d, 0x6c, 0xd8, 0xff, 0x9d, 0x33, 0xb0,
+ 0xf9, 0x8d, 0x39, 0x28, 0xe2, 0x01, 0x17, 0x78, 0xf9, 0x8d, 0x6c, 0xc8, 0xff, 0x8a, 0x9f, 0xfe,
+ 0xfd, 0x7f, 0x18, 0x00, 0xfd, 0x8c, 0x6c, 0xe0, 0xfe, 0x0c, 0x71, 0xd8, 0xff, 0x8a, 0x9f, 0xf6,
+ 0xfb, 0xff, 0x18, 0x00, 0xcd, 0xec, 0xd8, 0x00, 0xfa, 0x88, 0xa6, 0x50, 0xff, 0x88, 0xa6, 0x4c,
+ 0x9d, 0x82, 0xff, 0xb8, 0xfd, 0x82, 0x40, 0x00, 0xce, 0x70, 0xf8, 0x00, 0xff, 0xa6, 0x34, 0x30,
+ 0xfd, 0xff, 0x28, 0x04, 0xfd, 0x82, 0x00, 0x08, 0xfd, 0xff, 0x28, 0x0e, 0xff, 0x0e, 0x72, 0x80,
+ 0xfb, 0x0c, 0x6d, 0x68, 0xfd, 0x82, 0x40, 0x00, 0x7d, 0x69, 0x00, 0x0f, 0xfd, 0xfb, 0x28, 0x00,
+ 0x7e, 0xd4, 0xff, 0xfe, 0x5a, 0x68, 0x00, 0x01, 0xfd, 0x82, 0x00, 0xff, 0x20, 0x5a, 0x00, 0x00,
+ 0xcd, 0x68, 0xed, 0x00, 0xfd, 0xfb, 0x28, 0x0a, 0xfe, 0x8e, 0x6d, 0x00, 0xe6, 0x48, 0x00, 0x02,
+ 0xfd, 0x82, 0x40, 0x00, 0xfd, 0xf7, 0x28, 0x00, 0x5c, 0x48, 0x00, 0x02, 0x7c, 0x61, 0x00, 0x0d,
+ 0xfd, 0x82, 0x00, 0x0f, 0x7c, 0xc9, 0x00, 0x02, 0xfd, 0xf7, 0x28, 0x0a, 0xfc, 0x7f, 0x28, 0x08,
+ 0xfa, 0x7f, 0x28, 0x0a, 0xfb, 0xff, 0x28, 0x0c, 0xcf, 0xe4, 0xf8, 0x00, 0xfb, 0x25, 0x34, 0x40,
+ 0x2d, 0xf0, 0x00, 0x04, 0x99, 0xfe, 0x00, 0x14, 0x9d, 0xfe, 0x00, 0x10, 0xff, 0x9c, 0x33, 0x50,
+ 0xfd, 0x7b, 0x28, 0x06, 0xfc, 0x7b, 0x28, 0x04, 0xfb, 0xfb, 0x28, 0x08, 0xfc, 0x77, 0x28, 0x04,
+ 0xfa, 0x77, 0x28, 0x06, 0xfb, 0xf7, 0x28, 0x08, 0xcf, 0x64, 0xf0, 0x00, 0xca, 0xf0, 0xaa, 0x00,
+ 0xce, 0xe4, 0xe8, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xfb, 0x0d, 0x72, 0x8c, 0xfb, 0x0d, 0x6d, 0x0c,
+ 0x0c, 0xe4, 0x00, 0x14, 0x2e, 0x70, 0x00, 0x28, 0xff, 0x82, 0x00, 0x01, 0x9a, 0xfa, 0x00, 0x0c,
+ 0x9e, 0x76, 0x00, 0x0c, 0xfc, 0xa5, 0x34, 0x30, 0xff, 0x8d, 0x72, 0x70, 0xe6, 0x01, 0x17, 0x5d,
+ 0x45, 0x29, 0xff, 0xef, 0xfd, 0x86, 0x1c, 0xa0, 0x20, 0x4a, 0x00, 0x00, 0xfd, 0x81, 0x04, 0x18,
+ 0xe6, 0x01, 0x17, 0x4c, 0xff, 0x86, 0x28, 0xa8, 0xff, 0x86, 0x25, 0x10, 0xff, 0x81, 0x04, 0x1c,
+ 0xff, 0x81, 0x04, 0x20, 0xe0, 0x01, 0x17, 0x94, 0xf4, 0x02, 0x00, 0x00, 0xff, 0x86, 0x1b, 0x5c,
+ 0xff, 0x81, 0x04, 0x18, 0x20, 0x4a, 0x00, 0x00, 0xe6, 0x01, 0x17, 0x4c, 0xff, 0x86, 0x21, 0x7c,
+ 0xe0, 0x01, 0x17, 0x4c, 0xff, 0x86, 0x1d, 0xec, 0x22, 0x10, 0x00, 0x04, 0xfd, 0x86, 0x15, 0x8c,
+ 0x9d, 0x92, 0x00, 0x00, 0xf7, 0x86, 0x17, 0x90, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc,
+ 0xc4, 0x04, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf7, 0x86, 0x17, 0xb4, 0xe0, 0x00, 0x7a, 0x70,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0xfe, 0x00, 0x06, 0xff, 0x8d, 0x69, 0x30, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x04, 0xfe, 0x02, 0x00, 0x00, 0xff, 0x8e, 0x69, 0x60, 0x90, 0xfe, 0x00, 0x00,
+ 0x0e, 0x70, 0x00, 0x01, 0x20, 0x72, 0x00, 0x06, 0xe2, 0x01, 0x17, 0xdd, 0x0f, 0xfc, 0x00, 0x80,
+ 0xfe, 0x02, 0x00, 0x00, 0xff, 0x8c, 0x6d, 0x78, 0x7e, 0xf1, 0x00, 0x03, 0x0e, 0x70, 0x00, 0x01,
+ 0xb0, 0xf6, 0xf8, 0x02, 0xff, 0x8c, 0x6d, 0x78, 0x20, 0x72, 0x01, 0xff, 0xcf, 0xf4, 0xf8, 0x00,
+ 0x90, 0xfe, 0x00, 0x04, 0xff, 0x1c, 0x33, 0x68, 0xb0, 0xf6, 0xf0, 0x02, 0xff, 0x9c, 0x33, 0x68,
+ 0xce, 0xf4, 0xf8, 0x00, 0xe2, 0x01, 0x17, 0xf5, 0x90, 0xf6, 0x00, 0x04, 0xfe, 0x02, 0x00, 0x00,
+ 0xff, 0x98, 0x73, 0x10, 0x7f, 0x71, 0x00, 0x04, 0x0e, 0x70, 0x00, 0x01, 0xb0, 0x7e, 0xf0, 0x02,
+ 0xcf, 0xfc, 0xf0, 0x00, 0x90, 0x7e, 0x00, 0x0c, 0x90, 0x7e, 0x00, 0x04, 0x20, 0x72, 0x03, 0xff,
+ 0xe2, 0x01, 0x18, 0x31, 0x90, 0x7e, 0x00, 0x08, 0xff, 0x98, 0x73, 0x10, 0xff, 0x0c, 0x6d, 0x78,
+ 0xfe, 0x9c, 0x33, 0x68, 0xff, 0x8d, 0x6c, 0xf0, 0xff, 0x0d, 0x6d, 0x60, 0xfe, 0x8d, 0x6c, 0xf8,
+ 0xff, 0x9d, 0x33, 0x20, 0xff, 0x1d, 0x33, 0xc0, 0xfe, 0x99, 0x72, 0xf8, 0xf7, 0x86, 0x18, 0x88,
+ 0xe0, 0x01, 0x17, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0x0f, 0x81, 0xe0, 0x00, 0xce, 0xa8, 0xfc, 0x00,
+ 0xfe, 0x08, 0x8f, 0x98, 0xff, 0x42, 0xfc, 0x00, 0xc5, 0x74, 0xf5, 0x00, 0xfe, 0x82, 0x00, 0x03,
+ 0xf0, 0x09, 0xa6, 0x54, 0xf0, 0x0d, 0x71, 0xc8, 0xf0, 0x0d, 0x72, 0x70, 0xfe, 0x8d, 0x72, 0x00,
+ 0xfe, 0x8d, 0x72, 0x04, 0x70, 0x72, 0x00, 0x0c, 0xea, 0x01, 0x19, 0x4c, 0xfd, 0x82, 0x00, 0x00,
+ 0xfe, 0x88, 0xd3, 0xd8, 0x4f, 0xf1, 0xff, 0xf7, 0xff, 0x89, 0x8f, 0x98, 0xff, 0x82, 0x34, 0x00,
+ 0xf7, 0x82, 0x00, 0x40, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0xf7, 0x28, 0x0c, 0xff, 0x0a, 0x9f, 0xfe,
+ 0xff, 0xfb, 0x18, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0x24,
+ 0xff, 0xf7, 0x28, 0x12, 0x9d, 0xf6, 0x00, 0x14, 0x9d, 0xf6, 0x00, 0x18, 0x9d, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x9d, 0xf6, 0x00, 0x30, 0xff, 0x77, 0x18, 0x0a, 0x8e, 0x76, 0x00, 0x2c,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x0f, 0x81, 0x10, 0x00, 0x0f, 0xfc, 0x00, 0x14,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0xec, 0x9f, 0xf6, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0xfd, 0xf7, 0x28, 0x02, 0xff, 0x76, 0xff, 0xd0,
+ 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0x82, 0x00, 0x01, 0xf3, 0x76, 0xff, 0xfc, 0xfe, 0x8d, 0x6d, 0x58,
+ 0x5f, 0xfc, 0x00, 0x08, 0x9f, 0xfa, 0x00, 0x00, 0x9d, 0x96, 0xff, 0xf4, 0xf7, 0x86, 0x19, 0x78,
+ 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x96, 0xff, 0xf4, 0xfd, 0x89, 0xa6, 0x60,
+ 0xfd, 0x89, 0xa6, 0x5c, 0xf7, 0x86, 0x19, 0x90, 0xe0, 0x01, 0x2c, 0xa8, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0e, 0x38, 0xe0, 0xfe, 0x8a, 0x2b, 0x54, 0xf7, 0x82, 0x00, 0x01,
+ 0xf7, 0xfb, 0x68, 0x3f, 0x8d, 0x96, 0xff, 0xf4, 0xff, 0x9d, 0x33, 0x30, 0xff, 0x82, 0x00, 0x03,
+ 0xfd, 0xfb, 0x68, 0x3c, 0xfd, 0xfb, 0x68, 0x3d, 0xfd, 0xfb, 0x68, 0x3e, 0xfd, 0x99, 0x73, 0x00,
+ 0xfd, 0x8d, 0x6c, 0xd0, 0xfd, 0x8d, 0x72, 0x50, 0xfd, 0x8d, 0x38, 0xe4, 0xfd, 0x8d, 0x38, 0xe8,
+ 0xfd, 0x8d, 0x38, 0xec, 0xfd, 0x8d, 0x38, 0xf0, 0xfd, 0x8d, 0x38, 0xf4, 0xfd, 0x8d, 0x38, 0xf8,
+ 0xff, 0x8d, 0x38, 0xfc, 0xfd, 0x8d, 0x39, 0x00, 0xfd, 0x8d, 0x39, 0x04, 0xfd, 0x8d, 0x39, 0x08,
+ 0xfd, 0x8d, 0x39, 0x0c, 0xfd, 0x8d, 0x39, 0x10, 0xfd, 0x8d, 0x39, 0x14, 0xfe, 0x81, 0x04, 0x18,
+ 0xfe, 0x81, 0x04, 0x20, 0xfe, 0x81, 0x04, 0x1c, 0xf7, 0x86, 0x1a, 0x14, 0xe0, 0x00, 0xbf, 0xd8,
+ 0x97, 0x93, 0xff, 0xfc, 0xff, 0xf6, 0xff, 0x70, 0x8e, 0xfe, 0x00, 0x00, 0xff, 0x76, 0xff, 0x74,
+ 0x8d, 0xfa, 0x00, 0x00, 0x7e, 0x75, 0x00, 0x1c, 0xff, 0xf6, 0xff, 0x78, 0x8c, 0xfe, 0x00, 0x00,
+ 0x7e, 0x70, 0xff, 0xe8, 0x7f, 0x6c, 0xff, 0xe4, 0xcf, 0x78, 0xe0, 0x00, 0x7e, 0xf5, 0x00, 0x14,
+ 0x7e, 0x6d, 0x00, 0x04, 0x7e, 0xf4, 0xff, 0xe8, 0x7d, 0x6d, 0x00, 0x1c, 0x7f, 0xed, 0x00, 0x14,
+ 0x7e, 0xf5, 0x00, 0x18, 0x7f, 0x79, 0x00, 0x10, 0x7e, 0x70, 0xff, 0xe8, 0xce, 0xf4, 0xf0, 0x00,
+ 0x7e, 0x71, 0x00, 0x08, 0x7f, 0xfc, 0xff, 0xe8, 0x7c, 0xe4, 0xff, 0xe4, 0x7d, 0x68, 0xff, 0xe8,
+ 0x7d, 0xed, 0x00, 0x0c, 0xce, 0xf4, 0xe0, 0x00, 0xcc, 0xe4, 0xd0, 0x00, 0x7d, 0xec, 0xff, 0xe8,
+ 0x7f, 0xfd, 0x00, 0x08, 0xce, 0xf4, 0xd8, 0x00, 0xcf, 0xfc, 0xc8, 0x00, 0xfe, 0x8d, 0x72, 0xd8,
+ 0xff, 0xa5, 0x34, 0x50, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x88, 0xcd, 0xd8, 0x85, 0xae, 0x00, 0x2c,
+ 0x4f, 0x05, 0xdf, 0xff, 0x0f, 0xfd, 0x00, 0x04, 0xcf, 0x7c, 0xf5, 0x00, 0xff, 0x89, 0xcd, 0xd8,
+ 0xc5, 0x28, 0xf4, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x1a, 0xc4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x85, 0xae, 0x00, 0x2c,
+ 0x45, 0x29, 0xff, 0xfb, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x1b, 0x14, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x98, 0x73, 0x08,
+ 0xfc, 0x1c, 0x33, 0xb0, 0xfc, 0x82, 0x00, 0x80, 0x2e, 0xf4, 0x00, 0x01, 0xce, 0xe0, 0xec, 0x00,
+ 0x4f, 0xf4, 0x00, 0x7f, 0xcc, 0xe4, 0xfa, 0x00, 0x7f, 0x64, 0xff, 0xfd, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x7c, 0x00, 0x02, 0xff, 0x02, 0x7c, 0xcc, 0xcf, 0xfc, 0xf0, 0x00, 0xfd, 0x7f, 0x58, 0x20,
+ 0xfb, 0x8c, 0x6c, 0xd8, 0xfe, 0x0c, 0x71, 0xa0, 0xff, 0x08, 0xd3, 0xd8, 0xfd, 0x82, 0x40, 0x00,
+ 0x7b, 0x64, 0xff, 0xfe, 0xfd, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0xce, 0x70, 0xe8, 0x00, 0x0d, 0x81, 0x00, 0xa1, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xb5, 0x00, 0x4b, 0xdc, 0xff, 0x80, 0xff, 0xfb, 0x28, 0x0e, 0xfd, 0x7b, 0x28, 0x12,
+ 0x9e, 0x7a, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x09, 0xfe, 0x08, 0xcd, 0xd8, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x8d, 0x7a, 0x00, 0x2c, 0x9d, 0xfa, 0x00, 0x30, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x5f, 0xe5, 0x10, 0x00, 0xfd, 0x86, 0x1a, 0xa8,
+ 0x9d, 0xfa, 0x00, 0x04, 0xfd, 0x09, 0xd3, 0xd8, 0x9c, 0xfa, 0x00, 0x28, 0x9c, 0x7a, 0x00, 0x24,
+ 0x9c, 0x02, 0xfe, 0x58, 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0xf4, 0x00, 0x01, 0x4e, 0xf4, 0x0f, 0xff,
+ 0xfe, 0xeb, 0x28, 0x00, 0x9e, 0xea, 0x00, 0x08, 0x0e, 0x71, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x28,
+ 0xfe, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x8c, 0x39, 0x28,
+ 0x4e, 0x71, 0x20, 0x00, 0xc5, 0x28, 0xe5, 0x00, 0xcf, 0xfc, 0xb0, 0x00, 0xff, 0x8d, 0x39, 0x28,
+ 0xfb, 0x9d, 0x33, 0xb0, 0x45, 0x29, 0xff, 0xfd, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x1c, 0x58, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfe, 0x98, 0x73, 0x08, 0xfc, 0x1c, 0x33, 0xb0, 0xfc, 0x82, 0x00, 0x80, 0x2e, 0xf4, 0x00, 0x01,
+ 0xce, 0xe0, 0xec, 0x00, 0x4f, 0xf4, 0x00, 0x7f, 0xcc, 0xe4, 0xfa, 0x00, 0x7f, 0x64, 0xff, 0xfd,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x7c, 0x00, 0x02, 0xff, 0x02, 0x7c, 0xcc, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xfd, 0x7f, 0x58, 0x20, 0xfb, 0x8c, 0x6c, 0xd8, 0xfe, 0x0c, 0x71, 0xa0, 0xfb, 0x1c, 0x33, 0x50,
+ 0xff, 0x08, 0xd3, 0xd8, 0xfd, 0x82, 0x60, 0x00, 0x7a, 0xe4, 0xff, 0xfe, 0xfd, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0xce, 0x70, 0xe8, 0x00,
+ 0x0d, 0x81, 0x00, 0x61, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xad, 0x00, 0x4b, 0xdc, 0xff, 0x80,
+ 0xff, 0xfb, 0x28, 0x0e, 0xfd, 0x7b, 0x28, 0x12, 0x9b, 0x7a, 0x00, 0x14, 0x9e, 0x7a, 0x00, 0x18,
+ 0x0d, 0xec, 0x00, 0x09, 0xfe, 0x08, 0xcd, 0xd8, 0xfe, 0xfb, 0x18, 0x0a, 0x8d, 0x7a, 0x00, 0x2c,
+ 0x9d, 0xfa, 0x00, 0x30, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x00, 0x14,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5f, 0xe5, 0x10, 0x00, 0xfd, 0x86, 0x1a, 0xa8, 0x9d, 0xfa, 0x00, 0x04,
+ 0xfd, 0x09, 0xd3, 0xd8, 0x9c, 0xfa, 0x00, 0x28, 0x9c, 0x7a, 0x00, 0x24, 0x9c, 0x02, 0xfe, 0x58,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0xf4, 0x00, 0x01, 0x4e, 0xf4, 0x0f, 0xff, 0xfe, 0xeb, 0x28, 0x00,
+ 0x9e, 0xea, 0x00, 0x08, 0x0e, 0x71, 0xff, 0xfc, 0xff, 0x82, 0x00, 0x28, 0xfe, 0x09, 0xcd, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0xff, 0x8c, 0x39, 0x28, 0x4e, 0x71, 0x20, 0x00,
+ 0xc5, 0x28, 0xe5, 0x00, 0xcf, 0xfc, 0xa8, 0x00, 0xff, 0x8d, 0x39, 0x28, 0xfb, 0x9d, 0x33, 0xb0,
+ 0x45, 0x29, 0xff, 0xfd, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x1d, 0xa4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x08, 0xa6, 0x50,
+ 0xff, 0x8e, 0x39, 0x20, 0xfe, 0x8c, 0x72, 0x00, 0xcf, 0xfc, 0xd2, 0x00, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8c, 0x72, 0x04, 0xff, 0x08, 0x8f, 0x98, 0xfe, 0x0c, 0x6c, 0xe0, 0xce, 0xf4, 0xfc, 0x00,
+ 0x7f, 0xa8, 0xff, 0xf9, 0xce, 0xf4, 0xfc, 0x00, 0x7f, 0x79, 0x00, 0x0c, 0x9d, 0x02, 0xfe, 0x68,
+ 0x7f, 0x78, 0xff, 0xe1, 0xff, 0x8e, 0x72, 0x90, 0x9f, 0x82, 0xfe, 0x68, 0x2f, 0x78, 0x00, 0x01,
+ 0xce, 0x70, 0xe0, 0x00, 0x9e, 0x02, 0xff, 0xb8, 0xce, 0xf6, 0xf4, 0x00, 0xe6, 0x01, 0x20, 0xc9,
+ 0xfb, 0x02, 0x00, 0x00, 0xff, 0x8e, 0x72, 0xcf, 0xfe, 0xff, 0x68, 0x00, 0xff, 0x0e, 0x38, 0xe0,
+ 0x5e, 0x29, 0x00, 0x04, 0xfb, 0x7b, 0x68, 0x3e, 0x70, 0x76, 0x00, 0x1f, 0x90, 0x82, 0xfe, 0x80,
+ 0xfb, 0x0d, 0x72, 0x04, 0xea, 0x01, 0x1e, 0x78, 0x45, 0x70, 0xfe, 0xff, 0x45, 0x70, 0xfe, 0x7f,
+ 0xfe, 0x02, 0x00, 0x02, 0xfe, 0x0d, 0x72, 0x00, 0xff, 0x98, 0x73, 0x08, 0xfc, 0x1c, 0x33, 0xb0,
+ 0xfb, 0x8c, 0x6c, 0xd8, 0x2f, 0xfc, 0x00, 0x01, 0xcd, 0xde, 0xc2, 0x00, 0xe6, 0x01, 0x1f, 0x61,
+ 0xce, 0xe0, 0xfc, 0x00, 0x7f, 0x6c, 0xff, 0xfd, 0x20, 0x7a, 0x00, 0x00, 0xfe, 0x0c, 0x71, 0xa0,
+ 0xe6, 0x7c, 0x00, 0x02, 0xff, 0x02, 0x7c, 0xcc, 0xcf, 0xfc, 0xf0, 0x00, 0xfd, 0x7f, 0x58, 0x20,
+ 0xff, 0x08, 0xd3, 0xd8, 0xce, 0x70, 0xe8, 0x00, 0xfe, 0x82, 0x40, 0x00, 0xfe, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7c, 0xec, 0xff, 0xfe,
+ 0x0e, 0x81, 0x00, 0xa1, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xcd, 0x00, 0x0e, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x0e, 0xfd, 0x7b, 0x28, 0x12, 0x9e, 0x7a, 0x00, 0x14, 0x9e, 0xfa, 0x00, 0x30,
+ 0xfe, 0x7b, 0x18, 0x0a, 0x8e, 0xfa, 0x00, 0x2c, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x5f, 0xed, 0x10, 0x00, 0xfd, 0x02, 0xa2, 0xec,
+ 0x9d, 0x7a, 0x00, 0x04, 0xfe, 0x89, 0xd3, 0xd8, 0x9d, 0xfa, 0x00, 0x28, 0x9c, 0x7a, 0x00, 0x24,
+ 0x9c, 0x02, 0xfe, 0x58, 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0x70, 0x00, 0x01, 0x4e, 0x70, 0x0f, 0xff,
+ 0xfe, 0x77, 0x28, 0x00, 0x9e, 0x76, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0,
+ 0xfb, 0x7b, 0x28, 0x02, 0xff, 0x8c, 0x39, 0x28, 0xfb, 0x9d, 0x33, 0xb0, 0xcf, 0xfc, 0xc8, 0x00,
+ 0xff, 0x8d, 0x39, 0x28, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x08, 0xa6, 0x50,
+ 0xfd, 0x88, 0xd3, 0xd8, 0xff, 0x02, 0x00, 0x40, 0x0e, 0xe8, 0x00, 0x10, 0x9f, 0x6e, 0x00, 0x30,
+ 0xff, 0x0e, 0x72, 0x80, 0xff, 0xef, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x9f, 0x6e, 0x00, 0x24,
+ 0x9e, 0xee, 0x00, 0x28, 0xff, 0xfb, 0x28, 0x02, 0x9f, 0x02, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xfd, 0x06, 0x1b, 0x0c, 0x9d, 0x6e, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01,
+ 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0xf3, 0x28, 0x00, 0x9f, 0xf2, 0x00, 0x08,
+ 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xf0, 0x6f, 0x28, 0x02, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0x88, 0xa9, 0x70, 0xfd, 0x08, 0xd3, 0xd8, 0x20, 0x66, 0x00, 0x00,
+ 0xe6, 0x01, 0x20, 0x1d, 0x00, 0x00, 0x00, 0x01, 0xff, 0x08, 0x92, 0xc8, 0x20, 0x7a, 0x00, 0x00,
+ 0xec, 0x01, 0x20, 0x50, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x97, 0xcc, 0x70, 0x7e, 0x00, 0x07,
+ 0xea, 0x01, 0x20, 0x05, 0xff, 0x8a, 0x9f, 0xc0, 0x70, 0x7a, 0x00, 0x01, 0xea, 0x01, 0x20, 0x50,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x7f, 0x58, 0x00, 0xfe, 0x82, 0xa2, 0xe4, 0xfe, 0x89, 0xd3, 0xf8,
+ 0x2e, 0x80, 0x00, 0x80, 0xcf, 0x78, 0xed, 0x00, 0xff, 0x7f, 0x68, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x88, 0xa9, 0x74, 0xff, 0x02, 0x00, 0x40, 0xfe, 0x8a, 0xa9, 0x7c, 0x9f, 0x6a, 0x00, 0x30,
+ 0xff, 0x6b, 0x18, 0x0a, 0x8e, 0x6a, 0x00, 0x2c, 0x9e, 0xea, 0x00, 0x24, 0x9c, 0xea, 0x00, 0x28,
+ 0xff, 0x77, 0x28, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xe5, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0xa2, 0xec, 0x9f, 0xea, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28,
+ 0x9e, 0x02, 0xff, 0xb0, 0xf0, 0x6b, 0x28, 0x02, 0xff, 0x88, 0x8f, 0x98, 0x7d, 0xed, 0x00, 0x13,
+ 0xff, 0x22, 0x00, 0x00, 0xcd, 0xec, 0xf4, 0x00, 0x4f, 0xfd, 0xff, 0xf7, 0xcf, 0xfc, 0xdd, 0x00,
+ 0xe0, 0x01, 0x20, 0x1c, 0xff, 0x89, 0x8f, 0x98, 0xfe, 0x8c, 0x38, 0xf8, 0x55, 0x29, 0x00, 0x04,
+ 0xfd, 0x88, 0xd3, 0xd8, 0xfe, 0x8d, 0x6d, 0x10, 0xff, 0x8e, 0x6d, 0x00, 0xff, 0x02, 0x00, 0x40,
+ 0x9f, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0xee, 0x00, 0x2c, 0xfd, 0x02, 0x00, 0x14,
+ 0x9f, 0xee, 0x00, 0x24, 0x9d, 0x6e, 0x00, 0x28, 0xff, 0x7f, 0x28, 0x02, 0x0e, 0x01, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0x70, 0x00, 0x14, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x1b, 0x0c,
+ 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x77, 0x28, 0x00, 0x9f, 0x76, 0x00, 0x08, 0xfd, 0x02, 0x00, 0x28, 0x9d, 0x02, 0xff, 0xb0,
+ 0xf0, 0x6f, 0x28, 0x02, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x21, 0x34, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x08, 0xa6, 0x50,
+ 0xff, 0x8e, 0x39, 0x20, 0xfe, 0x8c, 0x72, 0x00, 0xcf, 0xfc, 0xd2, 0x00, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8c, 0x72, 0x04, 0xff, 0x08, 0x8f, 0x98, 0xfe, 0x0c, 0x6c, 0xe0, 0xce, 0xf4, 0xfc, 0x00,
+ 0x7f, 0xa8, 0xff, 0xf9, 0xce, 0xf4, 0xfc, 0x00, 0x7f, 0x79, 0x00, 0x0c, 0x9d, 0x02, 0xfe, 0x68,
+ 0x7f, 0x78, 0xff, 0xe1, 0xff, 0x8e, 0x72, 0x94, 0x9f, 0x82, 0xfe, 0x68, 0x2f, 0x78, 0x00, 0x01,
+ 0xce, 0x70, 0xe0, 0x00, 0x9e, 0x02, 0xff, 0xb8, 0xce, 0xf6, 0xf4, 0x00, 0xe6, 0x01, 0x24, 0x5d,
+ 0xfb, 0x02, 0x00, 0x00, 0xff, 0x82, 0x00, 0x01, 0xc0, 0x76, 0xfc, 0x00, 0xff, 0x0e, 0x72, 0xd3,
+ 0xfe, 0xfb, 0x68, 0x00, 0xff, 0x8e, 0x38, 0xe0, 0x5e, 0x29, 0x00, 0x04, 0xfb, 0x7f, 0x68, 0x3e,
+ 0x90, 0x82, 0xfe, 0x80, 0xfb, 0x0d, 0x72, 0x04, 0xe6, 0x01, 0x22, 0x0d, 0x45, 0x70, 0xfe, 0xff,
+ 0x45, 0x70, 0xfe, 0x7f, 0xfe, 0x02, 0x00, 0x02, 0xfe, 0x0d, 0x72, 0x00, 0xff, 0x98, 0x73, 0x08,
+ 0xfc, 0x1c, 0x33, 0xb0, 0xfb, 0x8c, 0x6c, 0xd8, 0x2f, 0xfc, 0x00, 0x01, 0xcd, 0xde, 0xc2, 0x00,
+ 0xe6, 0x01, 0x22, 0xf5, 0xce, 0xe0, 0xfc, 0x00, 0x7f, 0x6c, 0xff, 0xfd, 0x20, 0x7a, 0x00, 0x00,
+ 0xfe, 0x0c, 0x71, 0xa0, 0xe6, 0x7c, 0x00, 0x02, 0xff, 0x02, 0x7c, 0xcc, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xfd, 0x7f, 0x58, 0x20, 0xff, 0x08, 0xd3, 0xd8, 0xce, 0x70, 0xe8, 0x00, 0xfe, 0x82, 0x40, 0x00,
+ 0xfe, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7c, 0xec, 0xff, 0xfe, 0x0e, 0x81, 0x00, 0xa1, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xcd, 0x00,
+ 0x0e, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x0e, 0xfd, 0x7b, 0x28, 0x12, 0x9e, 0x7a, 0x00, 0x14,
+ 0x9e, 0xfa, 0x00, 0x30, 0xfe, 0x7b, 0x18, 0x0a, 0x8e, 0xfa, 0x00, 0x2c, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x00, 0x10, 0x9f, 0x82, 0xfe, 0x58, 0x5f, 0xed, 0x10, 0x00,
+ 0xfd, 0x02, 0xa2, 0xec, 0x9d, 0x7a, 0x00, 0x04, 0xfe, 0x89, 0xd3, 0xd8, 0x9d, 0xfa, 0x00, 0x28,
+ 0x9c, 0x7a, 0x00, 0x24, 0x9c, 0x02, 0xfe, 0x58, 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0x70, 0x00, 0x01,
+ 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x77, 0x28, 0x00, 0x9e, 0x76, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28,
+ 0x9e, 0x02, 0xff, 0xb0, 0xfb, 0x7b, 0x28, 0x02, 0xff, 0x8c, 0x39, 0x28, 0xfb, 0x9d, 0x33, 0xb0,
+ 0xcf, 0xfc, 0xc8, 0x00, 0xff, 0x8d, 0x39, 0x28, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x08, 0xa6, 0x50, 0xfd, 0x88, 0xd3, 0xd8, 0xff, 0x82, 0x00, 0x40, 0x0f, 0x68, 0x00, 0x14,
+ 0x9f, 0xee, 0x00, 0x30, 0xfe, 0x8e, 0x72, 0x80, 0xff, 0xef, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x9e, 0xee, 0x00, 0x24, 0x9f, 0x6e, 0x00, 0x28, 0xff, 0xf7, 0x28, 0x02, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0x79, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xfd, 0x06, 0x1b, 0x0c, 0x9d, 0x6e, 0x00, 0x04,
+ 0x0f, 0xfc, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0xf3, 0x28, 0x00,
+ 0x9f, 0xf2, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xf0, 0x6f, 0x28, 0x02,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x88, 0xa9, 0x70, 0xfd, 0x08, 0xd3, 0xd8,
+ 0x20, 0x66, 0x00, 0x00, 0xe6, 0x01, 0x23, 0xb1, 0x00, 0x00, 0x00, 0x01, 0xff, 0x08, 0x92, 0xc8,
+ 0x20, 0x7a, 0x00, 0x00, 0xec, 0x01, 0x23, 0xe4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x97, 0xcc,
+ 0x70, 0x7e, 0x00, 0x07, 0xea, 0x01, 0x23, 0x99, 0xff, 0x8a, 0x9f, 0xc0, 0x70, 0x7a, 0x00, 0x01,
+ 0xea, 0x01, 0x23, 0xe4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x7f, 0x58, 0x00, 0xfe, 0x82, 0xa2, 0xe4,
+ 0xfe, 0x89, 0xd3, 0xf8, 0x2e, 0x80, 0x00, 0x80, 0xcf, 0x78, 0xed, 0x00, 0xff, 0x7f, 0x68, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x23, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x88, 0xa9, 0x74, 0xff, 0x02, 0x00, 0x40, 0xfe, 0x8a, 0xa9, 0x7c,
+ 0x9f, 0x6a, 0x00, 0x30, 0xff, 0x6b, 0x18, 0x0a, 0x8e, 0x6a, 0x00, 0x2c, 0x9e, 0xea, 0x00, 0x24,
+ 0x9c, 0xea, 0x00, 0x28, 0xff, 0x77, 0x28, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xe5, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0xec, 0x9f, 0xea, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xf0, 0x6b, 0x28, 0x02, 0xff, 0x88, 0x8f, 0x98,
+ 0x7d, 0xed, 0x00, 0x13, 0xff, 0x22, 0x00, 0x00, 0xcd, 0xec, 0xf4, 0x00, 0x4f, 0xfd, 0xff, 0xf7,
+ 0xcf, 0xfc, 0xdd, 0x00, 0xe0, 0x01, 0x23, 0xb0, 0xff, 0x89, 0x8f, 0x98, 0xfe, 0x8c, 0x38, 0xf8,
+ 0x55, 0x29, 0x00, 0x04, 0xfd, 0x88, 0xd3, 0xd8, 0xfe, 0x8d, 0x6d, 0x14, 0xff, 0x8e, 0x6d, 0x00,
+ 0xff, 0x02, 0x00, 0x40, 0x9f, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0xee, 0x00, 0x2c,
+ 0xfd, 0x02, 0x00, 0x18, 0x9f, 0xee, 0x00, 0x24, 0x9d, 0x6e, 0x00, 0x28, 0xff, 0x7f, 0x28, 0x02,
+ 0x0e, 0x01, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0x70, 0x00, 0x18, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x1b, 0x0c, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x89, 0xd3, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x77, 0x28, 0x00, 0x9f, 0x76, 0x00, 0x08, 0xfd, 0x02, 0x00, 0x28,
+ 0x9d, 0x02, 0xff, 0xb0, 0xf0, 0x6f, 0x28, 0x02, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x24, 0xc8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0x08, 0xa6, 0x50, 0xff, 0x8e, 0x39, 0x20, 0xfe, 0x8c, 0x72, 0x00, 0xcf, 0xfc, 0xd2, 0x00,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8c, 0x72, 0x04, 0xff, 0x08, 0x8f, 0x98, 0xfe, 0x0c, 0x6c, 0xe0,
+ 0xce, 0xf4, 0xfc, 0x00, 0x7f, 0xa8, 0xff, 0xf9, 0xce, 0xf4, 0xfc, 0x00, 0x7f, 0x79, 0x00, 0x0c,
+ 0x9d, 0x02, 0xfe, 0x68, 0x7f, 0x78, 0xff, 0xe1, 0xff, 0x8e, 0x72, 0x90, 0x9f, 0x82, 0xfe, 0x68,
+ 0x2f, 0x78, 0x00, 0x01, 0xce, 0x70, 0xe0, 0x00, 0x9e, 0x02, 0xff, 0xb8, 0xce, 0xf6, 0xf4, 0x00,
+ 0xe6, 0x01, 0x27, 0xf5, 0xfa, 0x82, 0x00, 0x00, 0xff, 0x8e, 0x72, 0xcf, 0xfe, 0xff, 0x68, 0x00,
+ 0xff, 0x0e, 0x38, 0xe0, 0x5e, 0x29, 0x00, 0x04, 0xfa, 0xfb, 0x68, 0x3e, 0x70, 0x76, 0x00, 0x1f,
+ 0x90, 0x82, 0xfe, 0x80, 0xfa, 0x8d, 0x72, 0x04, 0xea, 0x01, 0x25, 0x9c, 0x45, 0x70, 0xfe, 0xff,
+ 0x45, 0x70, 0xfe, 0x7f, 0xfe, 0x02, 0x00, 0x02, 0xfe, 0x0d, 0x72, 0x00, 0xff, 0x98, 0x73, 0x08,
+ 0xfb, 0x9c, 0x33, 0xb0, 0xfb, 0x0c, 0x6c, 0xd8, 0x2f, 0xfc, 0x00, 0x01, 0xcd, 0xda, 0xba, 0x00,
+ 0xe6, 0x01, 0x26, 0x8d, 0xce, 0x5c, 0xfc, 0x00, 0x7f, 0x6c, 0xff, 0xfd, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x7c, 0x00, 0x02, 0xff, 0x02, 0x7c, 0xcc, 0xcf, 0xfc, 0xf0, 0x00, 0xfd, 0x7f, 0x58, 0x20,
+ 0xfe, 0x8c, 0x71, 0xa0, 0xfc, 0x9c, 0x33, 0x50, 0xff, 0x08, 0xd3, 0xd8, 0xff, 0x82, 0x60, 0x00,
+ 0xce, 0xf4, 0xe0, 0x00, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0xfb, 0x28, 0x0c,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7c, 0x6c, 0xff, 0xfe, 0x0e, 0x01, 0x00, 0x61, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xc5, 0x00, 0x0e, 0x70, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x0e, 0xfd, 0x7b, 0x28, 0x12,
+ 0x9c, 0xfa, 0x00, 0x14, 0x9e, 0xfa, 0x00, 0x18, 0x9e, 0x7a, 0x00, 0x30, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x8e, 0x7a, 0x00, 0x2c, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0xfd, 0x02, 0x00, 0x14,
+ 0x9d, 0x02, 0xfe, 0x58, 0x5f, 0xed, 0x10, 0x00, 0xfd, 0x02, 0xa2, 0xec, 0x9d, 0x7a, 0x00, 0x04,
+ 0xfe, 0x09, 0xd3, 0xd8, 0x9d, 0xfa, 0x00, 0x28, 0x9b, 0xfa, 0x00, 0x24, 0x9b, 0x82, 0xfe, 0x58,
+ 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0xf4, 0x00, 0x01, 0x4e, 0xf4, 0x0f, 0xff, 0xfe, 0xf3, 0x28, 0x00,
+ 0x9e, 0xf2, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xfa, 0xfb, 0x28, 0x02,
+ 0xff, 0x8c, 0x39, 0x28, 0xfb, 0x1d, 0x33, 0xb0, 0xcf, 0xfc, 0xc0, 0x00, 0xff, 0x8d, 0x39, 0x28,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x08, 0xa6, 0x50, 0xfd, 0x88, 0xd3, 0xd8,
+ 0xff, 0x02, 0x00, 0x40, 0x0e, 0xe8, 0x00, 0x10, 0x9f, 0x6e, 0x00, 0x30, 0xff, 0x0e, 0x72, 0x80,
+ 0xff, 0xef, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x9f, 0x6e, 0x00, 0x24, 0x9e, 0xee, 0x00, 0x28,
+ 0xff, 0xfb, 0x28, 0x02, 0x9f, 0x02, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xfd, 0x06, 0x1b, 0x0c, 0x9d, 0x6e, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0xf3, 0x28, 0x00, 0x9f, 0xf2, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28,
+ 0x9e, 0x02, 0xff, 0xb0, 0xf0, 0x6f, 0x28, 0x02, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xfc, 0x88, 0xa9, 0x70, 0xfd, 0x08, 0xd3, 0xd8, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x01, 0x27, 0x49,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x08, 0x92, 0xc8, 0x20, 0x7a, 0x00, 0x00, 0xec, 0x01, 0x27, 0x7c,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x97, 0xcc, 0x70, 0x7e, 0x00, 0x07, 0xea, 0x01, 0x27, 0x31,
+ 0xff, 0x8a, 0x9f, 0xc0, 0x70, 0x7a, 0x00, 0x01, 0xea, 0x01, 0x27, 0x7c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x7f, 0x58, 0x00, 0xfe, 0x82, 0xa2, 0xe4, 0xfe, 0x89, 0xd3, 0xf8, 0x2e, 0x80, 0x00, 0x80,
+ 0xcf, 0x78, 0xed, 0x00, 0xff, 0x7f, 0x68, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x27, 0x48, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x88, 0xa9, 0x74,
+ 0xff, 0x02, 0x00, 0x40, 0xfe, 0x8a, 0xa9, 0x7c, 0x9f, 0x6a, 0x00, 0x30, 0xff, 0x6b, 0x18, 0x0a,
+ 0x8e, 0x6a, 0x00, 0x2c, 0x9e, 0xea, 0x00, 0x24, 0x9c, 0xea, 0x00, 0x28, 0xff, 0x77, 0x28, 0x02,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xe5, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0xec,
+ 0x9f, 0xea, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0,
+ 0xf0, 0x6b, 0x28, 0x02, 0xff, 0x88, 0x8f, 0x98, 0x7d, 0xed, 0x00, 0x13, 0xff, 0x22, 0x00, 0x00,
+ 0xcd, 0xec, 0xf4, 0x00, 0x4f, 0xfd, 0xff, 0xf7, 0xcf, 0xfc, 0xdd, 0x00, 0xe0, 0x01, 0x27, 0x48,
+ 0xff, 0x89, 0x8f, 0x98, 0xfe, 0x8c, 0x38, 0xf8, 0x55, 0x29, 0x00, 0x04, 0xfd, 0x88, 0xd3, 0xd8,
+ 0xfe, 0x8d, 0x6d, 0x10, 0xff, 0x8e, 0x6d, 0x00, 0xff, 0x02, 0x00, 0x40, 0x9f, 0x6e, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0xee, 0x00, 0x2c, 0xfd, 0x02, 0x00, 0x14, 0x9f, 0xee, 0x00, 0x24,
+ 0x9d, 0x6e, 0x00, 0x28, 0xff, 0x7f, 0x28, 0x02, 0x0e, 0x01, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x0e, 0x70, 0x00, 0x14, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x1b, 0x0c, 0x9f, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x77, 0x28, 0x00,
+ 0x9f, 0x76, 0x00, 0x08, 0xfd, 0x02, 0x00, 0x28, 0x9d, 0x02, 0xff, 0xb0, 0xf0, 0x6f, 0x28, 0x02,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x28, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x08, 0xa6, 0x50, 0xff, 0x8e, 0x39, 0x20,
+ 0xfe, 0x8c, 0x72, 0x00, 0xcf, 0xfc, 0xd2, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8c, 0x72, 0x04,
+ 0xff, 0x08, 0x8f, 0x98, 0xfe, 0x0c, 0x6c, 0xe0, 0xce, 0xf4, 0xfc, 0x00, 0x7f, 0xa8, 0xff, 0xf9,
+ 0xce, 0xf4, 0xfc, 0x00, 0x7f, 0x79, 0x00, 0x0c, 0x9d, 0x02, 0xfe, 0x68, 0x7f, 0x78, 0xff, 0xe1,
+ 0xff, 0x8e, 0x72, 0x94, 0x9f, 0x82, 0xfe, 0x68, 0x2f, 0x78, 0x00, 0x01, 0xce, 0x70, 0xe0, 0x00,
+ 0x9e, 0x02, 0xff, 0xb8, 0xce, 0xf6, 0xf4, 0x00, 0xe6, 0x01, 0x2b, 0x91, 0xfa, 0x82, 0x00, 0x00,
+ 0xff, 0x82, 0x00, 0x01, 0xc0, 0x76, 0xfc, 0x00, 0xff, 0x0e, 0x72, 0xd3, 0xfe, 0xfb, 0x68, 0x00,
+ 0xff, 0x8e, 0x38, 0xe0, 0x5e, 0x29, 0x00, 0x04, 0xfa, 0xff, 0x68, 0x3e, 0x90, 0x82, 0xfe, 0x80,
+ 0xfa, 0x8d, 0x72, 0x04, 0xe6, 0x01, 0x29, 0x39, 0x45, 0x70, 0xfe, 0xff, 0x45, 0x70, 0xfe, 0x7f,
+ 0xfe, 0x02, 0x00, 0x02, 0xfe, 0x0d, 0x72, 0x00, 0xff, 0x98, 0x73, 0x08, 0xfb, 0x9c, 0x33, 0xb0,
+ 0xfb, 0x0c, 0x6c, 0xd8, 0x2f, 0xfc, 0x00, 0x01, 0xcd, 0xda, 0xba, 0x00, 0xe6, 0x01, 0x2a, 0x29,
+ 0xce, 0x5c, 0xfc, 0x00, 0x7f, 0x6c, 0xff, 0xfd, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x7c, 0x00, 0x02,
+ 0xff, 0x02, 0x7c, 0xcc, 0xcf, 0xfc, 0xf0, 0x00, 0xfd, 0x7f, 0x58, 0x20, 0xfe, 0x8c, 0x71, 0xa0,
+ 0xfc, 0x9c, 0x33, 0x50, 0xff, 0x08, 0xd3, 0xd8, 0xff, 0x82, 0x60, 0x00, 0xce, 0xf4, 0xe0, 0x00,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0xfb, 0x28, 0x0c, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7c, 0x6c, 0xff, 0xfe, 0x0e, 0x01, 0x00, 0x61, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xc5, 0x00,
+ 0x0e, 0x70, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x0e, 0xfd, 0x7b, 0x28, 0x12, 0x9c, 0xfa, 0x00, 0x14,
+ 0x9e, 0xfa, 0x00, 0x18, 0x9e, 0x7a, 0x00, 0x30, 0xfe, 0xfb, 0x18, 0x0a, 0x8e, 0x7a, 0x00, 0x2c,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0xfd, 0x02, 0x00, 0x14, 0x9d, 0x02, 0xfe, 0x58,
+ 0x5f, 0xed, 0x10, 0x00, 0xfd, 0x02, 0xa2, 0xec, 0x9d, 0x7a, 0x00, 0x04, 0xfe, 0x09, 0xd3, 0xd8,
+ 0x9d, 0xfa, 0x00, 0x28, 0x9b, 0xfa, 0x00, 0x24, 0x9b, 0x82, 0xfe, 0x58, 0x9f, 0x82, 0xfe, 0x58,
+ 0x0e, 0xf4, 0x00, 0x01, 0x4e, 0xf4, 0x0f, 0xff, 0xfe, 0xf3, 0x28, 0x00, 0x9e, 0xf2, 0x00, 0x08,
+ 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xfa, 0xfb, 0x28, 0x02, 0xff, 0x8c, 0x39, 0x28,
+ 0xfb, 0x1d, 0x33, 0xb0, 0xcf, 0xfc, 0xc0, 0x00, 0xff, 0x8d, 0x39, 0x28, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x08, 0xa6, 0x50, 0xfd, 0x88, 0xd3, 0xd8, 0xff, 0x82, 0x00, 0x40,
+ 0x0f, 0x68, 0x00, 0x14, 0x9f, 0xee, 0x00, 0x30, 0xfe, 0x8e, 0x72, 0x80, 0xff, 0xef, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x9e, 0xee, 0x00, 0x24, 0x9f, 0x6e, 0x00, 0x28, 0xff, 0xf7, 0x28, 0x02,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0x79, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xfd, 0x06, 0x1b, 0x0c,
+ 0x9d, 0x6e, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0xfc, 0x0f, 0xff,
+ 0xff, 0xf3, 0x28, 0x00, 0x9f, 0xf2, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0,
+ 0xf0, 0x6f, 0x28, 0x02, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x88, 0xa9, 0x70,
+ 0xfd, 0x08, 0xd3, 0xd8, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x01, 0x2a, 0xe5, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x08, 0x92, 0xc8, 0x20, 0x7a, 0x00, 0x00, 0xec, 0x01, 0x2b, 0x18, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0x97, 0xcc, 0x70, 0x7e, 0x00, 0x07, 0xea, 0x01, 0x2a, 0xcd, 0xff, 0x8a, 0x9f, 0xc0,
+ 0x70, 0x7a, 0x00, 0x01, 0xea, 0x01, 0x2b, 0x18, 0x00, 0x00, 0x00, 0x01, 0xff, 0x7f, 0x58, 0x00,
+ 0xfe, 0x82, 0xa2, 0xe4, 0xfe, 0x89, 0xd3, 0xf8, 0x2e, 0x80, 0x00, 0x80, 0xcf, 0x78, 0xed, 0x00,
+ 0xff, 0x7f, 0x68, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x2a, 0xe4, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x88, 0xa9, 0x74, 0xff, 0x02, 0x00, 0x40,
+ 0xfe, 0x8a, 0xa9, 0x7c, 0x9f, 0x6a, 0x00, 0x30, 0xff, 0x6b, 0x18, 0x0a, 0x8e, 0x6a, 0x00, 0x2c,
+ 0x9e, 0xea, 0x00, 0x24, 0x9c, 0xea, 0x00, 0x28, 0xff, 0x77, 0x28, 0x02, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0xe5, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0xec, 0x9f, 0xea, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xfe, 0x02, 0x00, 0x28, 0x9e, 0x02, 0xff, 0xb0, 0xf0, 0x6b, 0x28, 0x02,
+ 0xff, 0x88, 0x8f, 0x98, 0x7d, 0xed, 0x00, 0x13, 0xff, 0x22, 0x00, 0x00, 0xcd, 0xec, 0xf4, 0x00,
+ 0x4f, 0xfd, 0xff, 0xf7, 0xcf, 0xfc, 0xdd, 0x00, 0xe0, 0x01, 0x2a, 0xe4, 0xff, 0x89, 0x8f, 0x98,
+ 0xfe, 0x8c, 0x38, 0xf8, 0x55, 0x29, 0x00, 0x04, 0xfd, 0x88, 0xd3, 0xd8, 0xfe, 0x8d, 0x6d, 0x14,
+ 0xff, 0x8e, 0x6d, 0x00, 0xff, 0x02, 0x00, 0x40, 0x9f, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0xee, 0x00, 0x2c, 0xfd, 0x02, 0x00, 0x18, 0x9f, 0xee, 0x00, 0x24, 0x9d, 0x6e, 0x00, 0x28,
+ 0xff, 0x7f, 0x28, 0x02, 0x0e, 0x01, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x0e, 0x70, 0x00, 0x18,
+ 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x1b, 0x0c, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x77, 0x28, 0x00, 0x9f, 0x76, 0x00, 0x08,
+ 0xfd, 0x02, 0x00, 0x28, 0x9d, 0x02, 0xff, 0xb0, 0xf0, 0x6f, 0x28, 0x02, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x2b, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x20, 0x1e, 0x00, 0x80, 0xe2, 0x01, 0x2c, 0x55, 0xcf, 0x9c, 0x00, 0x00,
+ 0xf3, 0x82, 0x00, 0x80, 0xcf, 0xfc, 0x3a, 0x00, 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x01, 0x2c, 0x7d,
+ 0xcf, 0x18, 0x38, 0x00, 0xfe, 0x8a, 0xa6, 0xc8, 0x9e, 0x82, 0xfe, 0x68, 0x93, 0x82, 0xfe, 0x68,
+ 0x93, 0x02, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x2c, 0x9d, 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68,
+ 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0xa6, 0x5c, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x2c, 0xd8, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x2c, 0xd8, 0xff, 0x82, 0x00, 0x01,
+ 0xe0, 0x01, 0x2c, 0xdc, 0xff, 0x89, 0xa6, 0x58, 0xf0, 0x09, 0xa6, 0x58, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x08, 0x0e, 0x81, 0xff, 0xff, 0x9e, 0x96, 0xff, 0xf4, 0xf3, 0x1e, 0x33, 0xd0,
+ 0xf3, 0x8a, 0x00, 0x00, 0x90, 0x96, 0xff, 0xf0, 0xf7, 0x86, 0x2d, 0x14, 0xe0, 0x01, 0x2c, 0x3c,
+ 0x97, 0x93, 0xff, 0xfc, 0xf3, 0x0a, 0xe8, 0xb0, 0xf3, 0x82, 0x50, 0x00, 0xf7, 0x86, 0x2d, 0x28,
+ 0xe0, 0x01, 0x2c, 0x3c, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x02, 0x00, 0x00, 0xfe, 0x82, 0x03, 0xff,
+ 0xfe, 0x0a, 0xe8, 0xb0, 0xff, 0x8e, 0x38, 0x9c, 0x9f, 0x7e, 0x00, 0x08, 0xcf, 0x7c, 0x00, 0x00,
+ 0x2e, 0xf6, 0x00, 0x01, 0xea, 0x01, 0x2d, 0x38, 0x2f, 0xfc, 0x00, 0x14, 0x8e, 0x96, 0xff, 0xf4,
+ 0x8f, 0x96, 0xff, 0xf0, 0xff, 0x17, 0x1b, 0xf4, 0x9e, 0xf2, 0x00, 0x04, 0xce, 0x84, 0x00, 0x00,
+ 0x9e, 0x82, 0xfe, 0x88, 0x9f, 0x82, 0xfe, 0xa0, 0x8e, 0xf2, 0x00, 0x08, 0xff, 0x03, 0x2a, 0x98,
+ 0xff, 0x02, 0x04, 0x00, 0xfe, 0x9d, 0x33, 0xb8, 0xff, 0x0d, 0x72, 0x08, 0x9f, 0xf2, 0x00, 0x00,
+ 0x90, 0x72, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff,
+ 0xfe, 0x1d, 0x33, 0x58, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0,
+ 0xbe, 0x7e, 0xf0, 0x02, 0xff, 0x82, 0x03, 0xff, 0x9e, 0x72, 0x00, 0x10, 0x9e, 0x72, 0x00, 0x0c,
+ 0xff, 0x8d, 0x72, 0x08, 0xf7, 0x86, 0x2d, 0xc0, 0xe0, 0x01, 0x2c, 0xa8, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08, 0x8f, 0x9a, 0x00, 0x00, 0xff, 0x1b, 0x18, 0x04,
+ 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x82, 0xfe, 0xa0, 0xff, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x02, 0xfe, 0x88, 0xfd, 0x1b, 0x18, 0x04, 0xff, 0x82, 0x7f, 0xff, 0xcf, 0x78, 0xfc, 0x00,
+ 0x0f, 0x81, 0xff, 0xff, 0x9f, 0x96, 0xff, 0xf4, 0x7f, 0x79, 0x00, 0x02, 0xfe, 0x9e, 0x33, 0xd0,
+ 0x83, 0x1a, 0x00, 0x00, 0xae, 0x7a, 0xe8, 0x02, 0xcf, 0x84, 0x00, 0x00, 0xfd, 0x97, 0x1b, 0xf4,
+ 0xc0, 0x7e, 0x32, 0x00, 0x9f, 0x96, 0xff, 0xf0, 0xcf, 0x78, 0xe8, 0x00, 0xe6, 0x01, 0x2e, 0xbd,
+ 0x4f, 0xe9, 0x00, 0x00, 0x20, 0x72, 0x00, 0x00, 0xe6, 0x01, 0x2e, 0xc9, 0xf4, 0x02, 0x00, 0x01,
+ 0x4d, 0xe9, 0x00, 0x00, 0x8f, 0xf2, 0x00, 0x00, 0xfe, 0xf3, 0x18, 0x04, 0xc0, 0x7e, 0x32, 0x00,
+ 0xe6, 0x01, 0x2e, 0x75, 0xc0, 0x76, 0xda, 0x00, 0x0f, 0x70, 0x00, 0x08, 0x8e, 0x72, 0x00, 0x08,
+ 0x20, 0x72, 0x00, 0x00, 0xe6, 0x01, 0x2e, 0x44, 0xf4, 0x02, 0x00, 0x01, 0xe0, 0x01, 0x2e, 0xc8,
+ 0x00, 0x00, 0x00, 0x01, 0xe6, 0x01, 0x2e, 0x58, 0xf4, 0x02, 0x00, 0x00, 0x8f, 0xf2, 0x00, 0x08,
+ 0x9f, 0xfa, 0x00, 0x00, 0xff, 0x9c, 0x33, 0xb8, 0x9f, 0xf2, 0x00, 0x08, 0xff, 0x8c, 0x72, 0x08,
+ 0xfe, 0x1d, 0x33, 0xb8, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x72, 0x08, 0x8f, 0x72, 0x00, 0x10,
+ 0x8f, 0xf2, 0x00, 0x0c, 0x9f, 0xfa, 0x00, 0x0c, 0x8f, 0xf2, 0x00, 0x0c, 0x9f, 0x7e, 0x00, 0x10,
+ 0x94, 0x72, 0x00, 0x10, 0xe0, 0x01, 0x2e, 0xc8, 0x94, 0x72, 0x00, 0x0c, 0xc0, 0x6e, 0xfa, 0x00,
+ 0xe6, 0x01, 0x2e, 0x34, 0xf4, 0x02, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04,
+ 0xff, 0x0c, 0x72, 0x08, 0xff, 0x82, 0x04, 0x00, 0xcf, 0xfc, 0xf2, 0x00, 0x20, 0x7e, 0x01, 0xd1,
+ 0xe2, 0x01, 0x2f, 0x68, 0x0f, 0x01, 0xff, 0xff, 0xff, 0x9c, 0x33, 0x58, 0x83, 0x7e, 0x00, 0x0c,
+ 0x90, 0xfe, 0x00, 0x00, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x2f, 0x41, 0x9f, 0x7e, 0x00, 0x04,
+ 0x9f, 0x96, 0xff, 0xf4, 0xf7, 0x86, 0x2f, 0x20, 0xe0, 0x01, 0x2d, 0xcc, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x96, 0xff, 0xf4, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x01, 0x2f, 0x78, 0xf4, 0x02, 0x00, 0x01,
+ 0x83, 0x7e, 0x00, 0x0c, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x2f, 0x10, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x72, 0x08, 0x20, 0x7e, 0x03, 0xff, 0xe6, 0x01, 0x2f, 0x61, 0x03, 0x01, 0xe1, 0x00,
+ 0x03, 0x18, 0x07, 0x7c, 0xf7, 0x86, 0x2f, 0x60, 0xe0, 0x00, 0x7b, 0xb8, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x01, 0x2f, 0x78, 0xf4, 0x02, 0x00, 0x00, 0xf7, 0x86, 0x2f, 0x74, 0xe0, 0x01, 0x2c, 0xe8,
+ 0x97, 0x93, 0xff, 0xfc, 0xf4, 0x02, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c,
+ 0x8f, 0x9a, 0x00, 0x00, 0xff, 0x1b, 0x18, 0x04, 0xcd, 0x18, 0x00, 0x00, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x82, 0xfe, 0xa0, 0xff, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88,
+ 0xff, 0x02, 0x7f, 0xff, 0xfe, 0x1e, 0x33, 0xd0, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02,
+ 0x9f, 0x96, 0xff, 0xf4, 0xaf, 0x7e, 0xe0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x30, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x1a, 0x00, 0x00, 0xfd, 0x9b, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00,
+ 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xe2, 0x00, 0xe6, 0x01, 0x30, 0xb9, 0xc0, 0x76, 0xda, 0x00,
+ 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x2f, 0xdc, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x72, 0x08, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x30, 0xc9, 0xf4, 0x02, 0x00, 0x01,
+ 0xfe, 0x9c, 0x33, 0xb8, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x01, 0x30, 0x8d, 0x03, 0x01, 0xe1, 0x00,
+ 0x8f, 0xf6, 0x00, 0x08, 0x8e, 0x16, 0xff, 0xf4, 0xc4, 0x78, 0x00, 0x00, 0xff, 0x9d, 0x33, 0xb8,
+ 0xff, 0x9e, 0x33, 0xd0, 0xae, 0x72, 0xf8, 0x02, 0x9e, 0x76, 0x00, 0x08, 0x8e, 0x16, 0xff, 0xf4,
+ 0xbe, 0xf2, 0xf8, 0x02, 0x8f, 0xea, 0x00, 0x00, 0x9f, 0xf6, 0x00, 0x00, 0x8d, 0x6a, 0x00, 0x04,
+ 0x9d, 0x76, 0x00, 0x04, 0xff, 0x8c, 0x72, 0x08, 0xff, 0x1c, 0x33, 0x58, 0x2f, 0xfc, 0x00, 0x01,
+ 0xff, 0x8d, 0x72, 0x08, 0x8f, 0x7a, 0x00, 0x0c, 0x9f, 0x76, 0x00, 0x0c, 0xff, 0x9c, 0x33, 0x58,
+ 0x8f, 0x7e, 0x00, 0x0c, 0x9e, 0xfa, 0x00, 0x10, 0xff, 0x9c, 0x33, 0x58, 0x9e, 0xfe, 0x00, 0x0c,
+ 0xfe, 0x1c, 0x33, 0x58, 0xe0, 0x01, 0x30, 0xc8, 0x9e, 0x76, 0x00, 0x10, 0x9d, 0x16, 0xff, 0xf0,
+ 0x9f, 0x16, 0xff, 0xec, 0x03, 0x18, 0x07, 0x90, 0xf7, 0x86, 0x30, 0xa4, 0xe0, 0x00, 0x7b, 0xb8,
+ 0x97, 0x93, 0xff, 0xfc, 0xfe, 0x9c, 0x33, 0xb8, 0x8f, 0x16, 0xff, 0xec, 0x8d, 0x16, 0xff, 0xf0,
+ 0xe0, 0x01, 0x30, 0x20, 0x00, 0x00, 0x00, 0x01, 0xe6, 0x01, 0x2f, 0xf0, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x30, 0x01, 0xf4, 0x02, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x8d, 0xae, 0x00, 0x1c,
+ 0x8d, 0x2e, 0x00, 0x38, 0xfe, 0x08, 0xcd, 0xd8, 0xff, 0x03, 0x1b, 0xa0, 0x85, 0xae, 0x00, 0x2c,
+ 0x4e, 0xec, 0x00, 0x00, 0xce, 0x70, 0xe8, 0x00, 0x4f, 0x85, 0xdf, 0xff, 0xcf, 0xf0, 0xfd, 0x00,
+ 0xfe, 0x09, 0xcd, 0xd8, 0xce, 0xa8, 0xfc, 0x00, 0xfd, 0x83, 0x2a, 0x12, 0x4f, 0x79, 0x00, 0x00,
+ 0xfe, 0x0c, 0x6c, 0xd8, 0x7f, 0xf8, 0x00, 0x10, 0xcf, 0x7e, 0xf0, 0x00, 0x7f, 0x78, 0xff, 0xf0,
+ 0xcf, 0x00, 0xf1, 0x00, 0xfd, 0x73, 0x28, 0x02, 0xff, 0x73, 0x28, 0x00, 0x0e, 0x70, 0x00, 0x04,
+ 0x7f, 0xf1, 0x00, 0x19, 0x20, 0x7e, 0x00, 0x00, 0xfe, 0x0d, 0x6c, 0xd8, 0xe6, 0x01, 0x31, 0x79,
+ 0x55, 0x74, 0x00, 0x80, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x31, 0x44, 0x00, 0x00, 0x00, 0x01, 0xff, 0x98, 0x73, 0x08, 0x55, 0x29, 0x00, 0x02,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0xf0, 0xfc, 0x00, 0xff, 0x8d, 0x6c, 0xd8, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x31, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x8d, 0xae, 0x00, 0x1c, 0xfe, 0x88, 0xcd, 0xd8, 0xfe, 0x03, 0x1b, 0xa0,
+ 0x85, 0xae, 0x00, 0x2c, 0x4f, 0xec, 0x00, 0x00, 0xce, 0xf4, 0xf8, 0x00, 0x4f, 0x05, 0xdf, 0xff,
+ 0x4e, 0x71, 0x00, 0x00, 0xcf, 0x74, 0xf5, 0x00, 0xfe, 0x89, 0xcd, 0xd8, 0xfd, 0x83, 0x2a, 0x12,
+ 0xfe, 0x0d, 0x71, 0xf0, 0xc5, 0x28, 0xf4, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x32, 0x08, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8d, 0xae, 0x00, 0x1c, 0xff, 0x08, 0xcd, 0xd8, 0xfe, 0x83, 0x1b, 0xa0, 0xfe, 0x0c, 0x71, 0xf0,
+ 0x4f, 0xec, 0x00, 0x00, 0x85, 0xae, 0x00, 0x2c, 0xcf, 0x78, 0xf8, 0x00, 0x4e, 0xf5, 0x00, 0x00,
+ 0x4f, 0x85, 0xdf, 0xff, 0xce, 0x70, 0xe8, 0x00, 0xcf, 0xf8, 0xfd, 0x00, 0xff, 0x09, 0xcd, 0xd8,
+ 0xfd, 0x83, 0x2a, 0x12, 0xfe, 0x0d, 0x71, 0xf0, 0xc5, 0x28, 0xfc, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x32, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x8d, 0x2e, 0x00, 0x1c, 0x8c, 0xae, 0x00, 0x38, 0xfe, 0x08, 0xcd, 0xd8,
+ 0xfd, 0x83, 0x1b, 0xa0, 0x85, 0xae, 0x00, 0x2c, 0x4f, 0x68, 0x00, 0x00, 0xff, 0x8c, 0x71, 0xf0,
+ 0xce, 0x70, 0xf0, 0x00, 0x4e, 0x85, 0xdf, 0xff, 0xce, 0xf0, 0xed, 0x00, 0x4d, 0xed, 0x00, 0x00,
+ 0xfe, 0x09, 0xcd, 0xd8, 0xcf, 0x28, 0xec, 0x00, 0xfd, 0x03, 0x2a, 0x12, 0xcf, 0xfc, 0xd8, 0x00,
+ 0xfe, 0x0c, 0x6c, 0xd8, 0x7e, 0xfc, 0x00, 0x10, 0xcf, 0xf6, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xff, 0xf3, 0x28, 0x00, 0xfc, 0xf3, 0x28, 0x02, 0x0e, 0x70, 0x00, 0x04,
+ 0x7f, 0xf1, 0x00, 0x19, 0x20, 0x7e, 0x00, 0x00, 0xfe, 0x0d, 0x6c, 0xd8, 0xe6, 0x01, 0x33, 0x79,
+ 0x55, 0x78, 0x00, 0x80, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x33, 0x44, 0x00, 0x00, 0x00, 0x01, 0xff, 0x98, 0x73, 0x08, 0x55, 0x29, 0x00, 0x02,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0xf0, 0xfc, 0x00, 0xff, 0x8d, 0x6c, 0xd8, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x33, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x8d, 0x2e, 0x00, 0x1c, 0x8c, 0xae, 0x00, 0x38, 0xfe, 0x08, 0xcd, 0xd8,
+ 0xfd, 0x83, 0x1b, 0xa0, 0x85, 0xae, 0x00, 0x2c, 0x4f, 0x68, 0x00, 0x00, 0xff, 0x8c, 0x71, 0xf0,
+ 0xce, 0x70, 0xf0, 0x00, 0x4e, 0x85, 0xdf, 0xff, 0xce, 0xf0, 0xed, 0x00, 0x4d, 0xed, 0x00, 0x00,
+ 0xfe, 0x09, 0xcd, 0xd8, 0xcf, 0x28, 0xec, 0x00, 0xfd, 0x03, 0x2a, 0x12, 0xcf, 0xfc, 0xd8, 0x00,
+ 0xfe, 0x0c, 0x6c, 0xd8, 0x7e, 0xfc, 0x00, 0x10, 0xcf, 0xf6, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xff, 0xf3, 0x28, 0x00, 0xfc, 0xf3, 0x28, 0x02, 0x0e, 0x70, 0x00, 0x04,
+ 0x7f, 0xf1, 0x00, 0x19, 0x20, 0x7e, 0x00, 0x00, 0xfe, 0x0d, 0x6c, 0xd8, 0xe6, 0x01, 0x34, 0x79,
+ 0x55, 0x78, 0x00, 0x80, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x34, 0x44, 0x00, 0x00, 0x00, 0x01, 0xff, 0x98, 0x73, 0x08, 0x55, 0x29, 0x00, 0x02,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0xf0, 0xfc, 0x00, 0xff, 0x8d, 0x6c, 0xd8, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x34, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x8d, 0x2e, 0x00, 0x1c, 0x8c, 0xae, 0x00, 0x38, 0xfe, 0x08, 0xcd, 0xd8,
+ 0xfd, 0x83, 0x1b, 0xa0, 0x85, 0xae, 0x00, 0x2c, 0x4f, 0x68, 0x00, 0x00, 0xff, 0x8c, 0x71, 0xf0,
+ 0xce, 0x70, 0xf0, 0x00, 0x4e, 0x85, 0xdf, 0xff, 0xce, 0xf0, 0xed, 0x00, 0x4d, 0xed, 0x00, 0x00,
+ 0xfe, 0x09, 0xcd, 0xd8, 0xcf, 0x28, 0xec, 0x00, 0xfd, 0x03, 0x2a, 0x12, 0xcf, 0xfc, 0xd8, 0x00,
+ 0xfe, 0x0c, 0x6c, 0xd8, 0x7e, 0xfc, 0x00, 0x10, 0xcf, 0xf6, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xff, 0xf3, 0x28, 0x00, 0xfc, 0xf3, 0x28, 0x02, 0x0e, 0x70, 0x00, 0x04,
+ 0x7f, 0xf1, 0x00, 0x19, 0x20, 0x7e, 0x00, 0x00, 0xfe, 0x0d, 0x6c, 0xd8, 0xe6, 0x01, 0x35, 0x79,
+ 0x55, 0x78, 0x00, 0x80, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x35, 0x44, 0x00, 0x00, 0x00, 0x01, 0xff, 0x98, 0x73, 0x08, 0x55, 0x29, 0x00, 0x02,
+ 0xcf, 0x84, 0xfe, 0x00, 0xcf, 0xf0, 0xfc, 0x00, 0xff, 0x8d, 0x6c, 0xd8, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x35, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x43, 0x19, 0xfe, 0xff, 0xfe, 0x82, 0x00, 0x00, 0xff, 0x0e, 0x69, 0x40,
+ 0x8f, 0xfa, 0x00, 0x00, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0x71, 0x0e, 0xf4, 0x00, 0x01,
+ 0x8f, 0xfa, 0x00, 0x04, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0x71, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0xfa, 0x00, 0x08, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0x71, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0xfa, 0x00, 0x0c, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0x71, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0xfa, 0x00, 0x10, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0x71, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0xfa, 0x00, 0x14, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0x71, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0xfa, 0x00, 0x18, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0x71, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0xfa, 0x00, 0x1c, 0xc0, 0x1a, 0xfa, 0x00, 0xe6, 0x01, 0x36, 0x71, 0x20, 0x76, 0x00, 0x05,
+ 0xee, 0x01, 0x35, 0xe1, 0x0f, 0x78, 0x00, 0x80, 0xe0, 0x01, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0xfa, 0x00, 0x24, 0x5f, 0xfd, 0x20, 0x00, 0x9f, 0xfa, 0x00, 0x24, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8f, 0x82, 0xff, 0xf8, 0x70, 0x7e, 0x00, 0x1b, 0xea, 0x01, 0x36, 0xe8, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x83, 0x1a, 0x28, 0xff, 0x7a, 0x80, 0x00, 0xfe, 0x8c, 0x39, 0x04, 0x4e, 0x7d, 0x00, 0x00,
+ 0xcf, 0x70, 0xf0, 0x00, 0xff, 0xfb, 0x18, 0x06, 0x0f, 0xfc, 0x00, 0x17, 0x4f, 0xfc, 0xff, 0xf0,
+ 0xce, 0x70, 0xf8, 0x00, 0x20, 0x72, 0xbf, 0xff, 0xe2, 0x01, 0x36, 0xd5, 0x0e, 0xf4, 0x00, 0x01,
+ 0x2e, 0x70, 0xc0, 0x00, 0xfe, 0x03, 0x2a, 0x28, 0xff, 0x82, 0x00, 0x01, 0xfe, 0x8d, 0x39, 0x04,
+ 0xf0, 0x03, 0x2a, 0x1a, 0xff, 0x99, 0x73, 0x00, 0x8e, 0x02, 0xfe, 0x08, 0x8e, 0x82, 0xfe, 0x20,
+ 0x7d, 0xf0, 0xff, 0xf0, 0x4c, 0xf1, 0x00, 0x00, 0x4f, 0xf5, 0x00, 0x00, 0xcf, 0xec, 0xf8, 0x00,
+ 0x7f, 0x74, 0xff, 0xf0, 0xc0, 0x72, 0xed, 0x00, 0xe6, 0x01, 0x37, 0x3d, 0xcd, 0x7c, 0xf0, 0x00,
+ 0xff, 0x8c, 0x39, 0x04, 0xfe, 0x8c, 0x39, 0x00, 0xff, 0x0c, 0x38, 0xe4, 0xcf, 0xfc, 0xd0, 0x00,
+ 0xff, 0x8d, 0x39, 0x04, 0xce, 0xf4, 0xc8, 0x00, 0xcf, 0x78, 0xd8, 0x00, 0xff, 0x82, 0x00, 0x01,
+ 0xfe, 0x8d, 0x39, 0x00, 0xff, 0x0d, 0x38, 0xe4, 0xff, 0x99, 0x73, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8c, 0x69, 0x74, 0xf0, 0x03, 0x2a, 0x3a, 0x55, 0x28, 0x04, 0x00, 0xff, 0x81, 0x04, 0x14,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x37, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x69, 0xf4, 0xf0, 0x03, 0x2a, 0x3a,
+ 0x55, 0x28, 0x08, 0x00, 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x37, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8c, 0x6a, 0x74, 0xf0, 0x03, 0x2a, 0x3a, 0x55, 0x28, 0x10, 0x00, 0xff, 0x81, 0x04, 0x14,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x38, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x6a, 0xf4, 0xf0, 0x03, 0x2a, 0x3a,
+ 0x55, 0x28, 0x20, 0x00, 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x38, 0x68, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8c, 0x6b, 0x74, 0xf0, 0x03, 0x2a, 0x3a, 0x55, 0x28, 0x40, 0x00, 0xff, 0x81, 0x04, 0x14,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x38, 0xc0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x6b, 0xf4, 0xf0, 0x03, 0x2a, 0x3a,
+ 0x55, 0x28, 0x80, 0x00, 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x39, 0x18, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8c, 0x69, 0x74, 0x55, 0x28, 0x04, 0x00, 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x39, 0x6c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x69, 0xf4, 0x55, 0x28, 0x08, 0x00, 0xff, 0x81, 0x04, 0x14,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x39, 0xc0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x6a, 0x74, 0x55, 0x28, 0x10, 0x00,
+ 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x3a, 0x14, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x6a, 0xf4,
+ 0x55, 0x28, 0x20, 0x00, 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x3a, 0x68, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8c, 0x6b, 0x74, 0x55, 0x28, 0x40, 0x00, 0xff, 0x81, 0x04, 0x14, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x3a, 0xbc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x6b, 0xf4, 0x55, 0x28, 0x80, 0x00, 0xff, 0x81, 0x04, 0x14,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x3b, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x0c, 0xff, 0x8c, 0x69, 0x30,
+ 0xff, 0x0e, 0x72, 0xf0, 0xfe, 0x8e, 0x39, 0x30, 0xfe, 0x0e, 0x69, 0x32, 0x83, 0xfe, 0x40, 0x00,
+ 0x43, 0x7d, 0x00, 0x00, 0x0f, 0x98, 0x00, 0x11, 0x40, 0x1e, 0x00, 0x00, 0xe6, 0x01, 0x3b, 0xa4,
+ 0x7d, 0x9c, 0x00, 0x02, 0x90, 0x02, 0xfe, 0x02, 0xad, 0x7a, 0xd8, 0x02, 0xcf, 0xfc, 0x38, 0x00,
+ 0x7f, 0xfc, 0xff, 0xfd, 0xa4, 0x76, 0xf8, 0x01, 0x23, 0x9c, 0x00, 0x02, 0xc1, 0x68, 0x00, 0x00,
+ 0xf4, 0x73, 0x28, 0x00, 0xff, 0x8c, 0x69, 0x30, 0xff, 0x0e, 0x39, 0x30, 0x8e, 0x7e, 0x40, 0x00,
+ 0x4f, 0xfd, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xf4, 0xc3, 0x7c, 0x00, 0x00, 0x4f, 0xf1, 0x00, 0x00,
+ 0xcf, 0x98, 0xf8, 0x00, 0x0f, 0xfc, 0x00, 0x11, 0x7f, 0xfc, 0xff, 0xfc, 0xf0, 0x03, 0x2a, 0x02,
+ 0xcf, 0xfc, 0xf8, 0x00, 0xaf, 0xfe, 0xf0, 0x01, 0x40, 0x72, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xf0,
+ 0x8f, 0x16, 0xff, 0xf0, 0xff, 0x8e, 0x69, 0x32, 0xff, 0x7f, 0x28, 0x00, 0x84, 0x16, 0xff, 0xf0,
+ 0xe6, 0x01, 0x3c, 0x0d, 0x03, 0xf0, 0x00, 0x02, 0x9e, 0x16, 0xff, 0xec, 0xf7, 0x86, 0x3c, 0x08,
+ 0xe0, 0x01, 0x3c, 0xf8, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x16, 0xff, 0xec, 0x7f, 0xf1, 0x00, 0x02,
+ 0xff, 0x0e, 0x72, 0xf0, 0x83, 0x16, 0xff, 0xf4, 0x84, 0x16, 0xff, 0xf0, 0xae, 0xfe, 0xf0, 0x02,
+ 0x2e, 0x70, 0x00, 0x02, 0xc3, 0xf0, 0x00, 0x00, 0xf7, 0x86, 0x3c, 0x34, 0xc1, 0x74, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0xfd, 0x8c, 0x71, 0xb4,
+ 0xff, 0x0e, 0x72, 0xf0, 0xff, 0x8c, 0x6c, 0xd8, 0x7e, 0xed, 0x00, 0x02, 0xce, 0xf4, 0xf0, 0x00,
+ 0xff, 0x1c, 0x33, 0xb0, 0x8e, 0xf6, 0x00, 0x08, 0x45, 0x29, 0xff, 0xf7, 0xcf, 0xfc, 0xf2, 0x00,
+ 0x7e, 0x7d, 0xff, 0xfe, 0xff, 0x8c, 0x39, 0x28, 0xff, 0x0c, 0x6c, 0xc8, 0xcf, 0xfc, 0xe0, 0x00,
+ 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x01, 0x3c, 0xd0, 0x9e, 0x96, 0xff, 0xf4, 0x8f, 0x82, 0xff, 0xf8,
+ 0x70, 0x7e, 0x00, 0x1a, 0xea, 0x01, 0x3c, 0xd0, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x82, 0xff, 0xd0,
+ 0xff, 0x0c, 0x38, 0xc0, 0xff, 0x8e, 0x0d, 0x40, 0xce, 0xf4, 0xf2, 0x00, 0xc0, 0x76, 0xfa, 0x00,
+ 0xe2, 0x01, 0x3c, 0xd1, 0xc3, 0xec, 0x00, 0x00, 0xf3, 0x0c, 0x71, 0xb0, 0xf4, 0x0c, 0x71, 0xb8,
+ 0xf7, 0x86, 0x3c, 0xcc, 0xe0, 0x01, 0x3c, 0xf8, 0x97, 0x93, 0xff, 0xfc, 0xfd, 0x8c, 0x71, 0xb4,
+ 0xf3, 0x0c, 0x71, 0xb0, 0xf4, 0x0c, 0x71, 0xb8, 0x8f, 0x96, 0xff, 0xf4, 0xc3, 0xec, 0x00, 0x00,
+ 0xf7, 0x86, 0x3c, 0xec, 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x83, 0x1a, 0x12, 0x4f, 0x18, 0xff, 0xf0, 0x4f, 0xfd, 0x00, 0x00, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xe6, 0x01, 0x3e, 0x51, 0x23, 0x9c, 0x00, 0x02, 0xff, 0x8c, 0x71, 0xa8, 0xf4, 0x7f, 0x28, 0x1e,
+ 0x20, 0x1e, 0x00, 0x00, 0xe6, 0x01, 0x3d, 0x78, 0xcf, 0x84, 0x00, 0x00, 0xff, 0x8c, 0x38, 0xf4,
+ 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x38, 0xf4, 0xff, 0x82, 0x00, 0x01, 0xff, 0x99, 0x73, 0x00,
+ 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x3d, 0x44, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x1e, 0xfa, 0x00, 0xe6, 0x01, 0x3e, 0x39,
+ 0x20, 0x1e, 0x00, 0x3b, 0xe2, 0x01, 0x3d, 0x9c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x39, 0x08,
+ 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x01, 0x3d, 0x38, 0xff, 0x8d, 0x39, 0x08, 0xff, 0x8c, 0x38, 0xb8,
+ 0xc0, 0x1e, 0xfa, 0x00, 0xe2, 0x01, 0x3d, 0xbc, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x39, 0x10,
+ 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x01, 0x3d, 0x38, 0xff, 0x8d, 0x39, 0x10, 0xff, 0x8c, 0x71, 0xc8,
+ 0xc0, 0x1e, 0xfa, 0x00, 0xe2, 0x01, 0x3d, 0xdc, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x39, 0x14,
+ 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x01, 0x3d, 0x38, 0xff, 0x8d, 0x39, 0x14, 0x70, 0x1e, 0x00, 0x01,
+ 0xea, 0x01, 0x3e, 0x04, 0x20, 0x1e, 0x00, 0x00, 0xff, 0x0c, 0x38, 0xf0, 0xff, 0x8c, 0x39, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf0, 0xe0, 0x01, 0x3d, 0x38,
+ 0xff, 0x8d, 0x39, 0x04, 0xec, 0x01, 0x3e, 0x1d, 0xf3, 0x7e, 0x40, 0x00, 0xff, 0x8c, 0x39, 0x0c,
+ 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x01, 0x3d, 0x38, 0xff, 0x8d, 0x39, 0x0c, 0xc3, 0x78, 0x30, 0x00,
+ 0x43, 0x9d, 0x00, 0x00, 0xf7, 0x86, 0x3e, 0x30, 0xe0, 0x02, 0x70, 0x7c, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x01, 0x3d, 0x3c, 0xff, 0x82, 0x00, 0x01, 0xff, 0x0c, 0x38, 0xe8, 0xff, 0x8c, 0x39, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x01, 0x3d, 0xfc, 0xff, 0x0d, 0x38, 0xe8,
+ 0xf4, 0x03, 0x2a, 0x12, 0xe0, 0x01, 0x3d, 0x24, 0x20, 0x1e, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfb, 0x1c, 0x33, 0x48, 0xfc, 0x8c, 0x72, 0x60, 0xfe, 0x24, 0x33, 0xd0, 0x2d, 0x58, 0x3f, 0xfd,
+ 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03,
+ 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc,
+ 0xab, 0xfe, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x69, 0x30, 0xff, 0x08, 0xd3, 0xd8,
+ 0xfa, 0x9c, 0x33, 0x38, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7d, 0x68, 0xff, 0xfe, 0x4e, 0xe8, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xed, 0x00,
+ 0xff, 0xfb, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xfb, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xd8, 0x00,
+ 0x9c, 0xfa, 0x00, 0x14, 0x0e, 0x70, 0x40, 0x00, 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10,
+ 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xfb, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0xd8, 0x40, 0x00,
+ 0xff, 0x8a, 0xcf, 0xd0, 0xae, 0xfe, 0xd0, 0x05, 0xfc, 0x88, 0xcd, 0xd8, 0xfe, 0x7b, 0x18, 0x0a,
+ 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x7a, 0x00, 0x2c, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0xfa, 0xfb, 0x28, 0x20, 0xfb, 0xfb, 0x28, 0x22,
+ 0xfc, 0x7b, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00,
+ 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x32, 0xd4, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0x70, 0xe8, 0x00,
+ 0xfd, 0x09, 0xd3, 0xd8, 0x0e, 0xf4, 0x00, 0x01, 0xfe, 0xfb, 0x28, 0x1c, 0x4e, 0x70, 0x0f, 0xff,
+ 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0x7e, 0xf5, 0x00, 0x10, 0xff, 0xfb, 0x28, 0x00,
+ 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xea, 0x00, 0xfc, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0x4c, 0xe5, 0x20, 0x00, 0x2b, 0x58, 0x00, 0x02, 0xf0, 0x7b, 0x28, 0x02,
+ 0x9b, 0x7a, 0x00, 0x38, 0xc5, 0x28, 0xcd, 0x00, 0xff, 0x0d, 0x71, 0xa8, 0x55, 0x28, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x3f, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38, 0xfd, 0x8c, 0x72, 0x60,
+ 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x33, 0xd0,
+ 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x30, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xfb, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14,
+ 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0,
+ 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20,
+ 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01,
+ 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00,
+ 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00,
+ 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x3e, 0x70, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34,
+ 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x41, 0x04, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38,
+ 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x20, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09,
+ 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff,
+ 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02,
+ 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x3f, 0xf8, 0xfb, 0x9d, 0x33, 0x38,
+ 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x42, 0x58, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x33, 0x38, 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02,
+ 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x10, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x41, 0x4c,
+ 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x43, 0xac, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02,
+ 0xff, 0x8c, 0x72, 0xd8, 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x67, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x46, 0x18, 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x46, 0x18,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xc0, 0x8d, 0xfa, 0x00, 0x04, 0x8e, 0x7a, 0x00, 0x00,
+ 0x0f, 0xf8, 0x00, 0x08, 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x45, 0x8d, 0x4f, 0xfc, 0xef, 0xff,
+ 0xff, 0x9d, 0x33, 0xc0, 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x73, 0x20, 0xab, 0x9a, 0xf8, 0x01,
+ 0x20, 0x72, 0x00, 0x00, 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02,
+ 0xfd, 0x1d, 0x33, 0x48, 0xfe, 0x0d, 0x72, 0x60, 0xfd, 0xa5, 0x33, 0xd0, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01,
+ 0xff, 0x0a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xcd, 0xd8,
+ 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30,
+ 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x31, 0xd4,
+ 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0x70, 0x00, 0x01,
+ 0xfe, 0x77, 0x28, 0x1c, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01,
+ 0x7e, 0x71, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x00, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00,
+ 0xfd, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0xed, 0x20, 0x00,
+ 0xf0, 0x77, 0x28, 0x02, 0xcc, 0x60, 0xdd, 0x00, 0xff, 0x86, 0x42, 0xa0, 0xfb, 0x9d, 0x33, 0x38,
+ 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x45, 0x58, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6d, 0x58,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x46, 0xc5, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xb0,
+ 0xff, 0x8c, 0x6c, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x39, 0x28,
+ 0xff, 0x8c, 0x6c, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x45, 0xd5,
+ 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8, 0xff, 0x8d, 0x38, 0xc0,
+ 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x71, 0xb0, 0xfd, 0x0d, 0x71, 0xb4, 0xf4, 0x0d, 0x71, 0xb8,
+ 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x45, 0xe4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58, 0x70, 0x7a, 0x00, 0x07,
+ 0xea, 0x01, 0x46, 0xb0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x44, 0x25, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02,
+ 0xff, 0x1e, 0x33, 0xd0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x46, 0x91,
+ 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00,
+ 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x46, 0x99, 0xc0, 0x76, 0xe2, 0x00,
+ 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x46, 0x6c, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0x46, 0xc4, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x46, 0x80, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x44, 0x24, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x46, 0xc4, 0xf3, 0x82, 0x00, 0x02,
+ 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x44, 0x24, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x46, 0xd0, 0xe0, 0x01, 0x3c, 0xf8, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfb, 0x1c, 0x33, 0x48, 0xfc, 0x8c, 0x72, 0x60, 0xfe, 0x24, 0x33, 0xd0,
+ 0x2d, 0x58, 0x2f, 0xfd, 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x4f, 0xe8, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xff, 0x82, 0x7c, 0xcc, 0xab, 0xfe, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x69, 0x30,
+ 0xff, 0x08, 0xd3, 0xd8, 0xfa, 0x9c, 0x33, 0x38, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7d, 0x68, 0xff, 0xfe, 0x4e, 0xe8, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xfb, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xd8, 0x00, 0x9c, 0xfa, 0x00, 0x14, 0x0e, 0x70, 0x30, 0x00, 0x9e, 0x7e, 0x00, 0x14,
+ 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xfb, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe,
+ 0x2b, 0xd8, 0x30, 0x00, 0xff, 0x8a, 0xcf, 0xd0, 0xae, 0xfe, 0xd0, 0x05, 0xfc, 0x88, 0xcd, 0xd8,
+ 0xfe, 0x7b, 0x18, 0x0a, 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x7a, 0x00, 0x2c, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0xfa, 0xfb, 0x28, 0x20,
+ 0xfb, 0xfb, 0x28, 0x22, 0xfc, 0x7b, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x32, 0xd4, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0x70, 0xe8, 0x00, 0xfd, 0x09, 0xd3, 0xd8, 0x0e, 0xf4, 0x00, 0x01, 0xfe, 0xfb, 0x28, 0x1c,
+ 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0x7e, 0xf5, 0x00, 0x10,
+ 0xff, 0xfb, 0x28, 0x00, 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xea, 0x00, 0xfc, 0x89, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4c, 0xe5, 0x20, 0x00, 0x2b, 0x58, 0x00, 0x02,
+ 0xf0, 0x7b, 0x28, 0x02, 0x9b, 0x7a, 0x00, 0x38, 0xc5, 0x28, 0xcd, 0x00, 0xff, 0x0d, 0x71, 0xa8,
+ 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x48, 0x24, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38,
+ 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x20, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09,
+ 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff,
+ 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02,
+ 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x46, 0xe4, 0xfb, 0x9d, 0x33, 0x38,
+ 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x49, 0x78, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x33, 0x38, 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02,
+ 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x10, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x48, 0x6c,
+ 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x4a, 0xcc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02,
+ 0xff, 0x8c, 0x72, 0xd8, 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x67, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x4d, 0x38, 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x4d, 0x38,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xc0, 0x8d, 0xfa, 0x00, 0x04, 0x8e, 0x7a, 0x00, 0x00,
+ 0x0f, 0xf8, 0x00, 0x08, 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x4c, 0xad, 0x4f, 0xfc, 0xef, 0xff,
+ 0xff, 0x9d, 0x33, 0xc0, 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x73, 0x20, 0xab, 0x9a, 0xf8, 0x01,
+ 0x20, 0x72, 0x00, 0x00, 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02,
+ 0xfd, 0x1d, 0x33, 0x48, 0xfe, 0x0d, 0x72, 0x60, 0xfd, 0xa5, 0x33, 0xd0, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01,
+ 0xff, 0x0a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xcd, 0xd8,
+ 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30,
+ 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x31, 0xd4,
+ 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0x70, 0x00, 0x01,
+ 0xfe, 0x77, 0x28, 0x1c, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01,
+ 0x7e, 0x71, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x00, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00,
+ 0xfd, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0xed, 0x20, 0x00,
+ 0xf0, 0x77, 0x28, 0x02, 0xcc, 0x60, 0xdd, 0x00, 0xff, 0x86, 0x49, 0xc0, 0xfb, 0x9d, 0x33, 0x38,
+ 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x4c, 0x78, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6d, 0x58,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x4d, 0xe5, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xb0,
+ 0xff, 0x8c, 0x6c, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x39, 0x28,
+ 0xff, 0x8c, 0x6c, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x4c, 0xf5,
+ 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8, 0xff, 0x8d, 0x38, 0xc0,
+ 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x71, 0xb0, 0xfd, 0x0d, 0x71, 0xb4, 0xf4, 0x0d, 0x71, 0xb8,
+ 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x4d, 0x04, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58, 0x70, 0x7a, 0x00, 0x07,
+ 0xea, 0x01, 0x4d, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x4b, 0x45, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02,
+ 0xff, 0x1e, 0x33, 0xd0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x4d, 0xb1,
+ 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00,
+ 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x4d, 0xb9, 0xc0, 0x76, 0xe2, 0x00,
+ 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x4d, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0x4d, 0xe4, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x4d, 0xa0, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x4b, 0x44, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x4d, 0xe4, 0xf3, 0x82, 0x00, 0x02,
+ 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x4b, 0x44, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x4d, 0xf0, 0xe0, 0x01, 0x3c, 0xf8, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfb, 0x1c, 0x33, 0x48, 0xfc, 0x8c, 0x72, 0x60, 0xfe, 0x24, 0x33, 0xd0,
+ 0x2d, 0x58, 0x1f, 0xfd, 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x4f, 0xe8, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xff, 0x82, 0x7c, 0xcc, 0xab, 0xfe, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x69, 0x30,
+ 0xff, 0x08, 0xd3, 0xd8, 0xfa, 0x9c, 0x33, 0x38, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7d, 0x68, 0xff, 0xfe, 0x4e, 0xe8, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xfb, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xd8, 0x00, 0x9c, 0xfa, 0x00, 0x14, 0x0e, 0x70, 0x20, 0x00, 0x9e, 0x7e, 0x00, 0x14,
+ 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xfb, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe,
+ 0x2b, 0xd8, 0x20, 0x00, 0xff, 0x8a, 0xcf, 0xd0, 0xae, 0xfe, 0xd0, 0x05, 0xfc, 0x88, 0xcd, 0xd8,
+ 0xfe, 0x7b, 0x18, 0x0a, 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x7a, 0x00, 0x2c, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0xfa, 0xfb, 0x28, 0x20,
+ 0xfb, 0xfb, 0x28, 0x22, 0xfc, 0x7b, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x32, 0xd4, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0x70, 0xe8, 0x00, 0xfd, 0x09, 0xd3, 0xd8, 0x0e, 0xf4, 0x00, 0x01, 0xfe, 0xfb, 0x28, 0x1c,
+ 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0x7e, 0xf5, 0x00, 0x10,
+ 0xff, 0xfb, 0x28, 0x00, 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xea, 0x00, 0xfc, 0x89, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4c, 0xe5, 0x20, 0x00, 0x2b, 0x58, 0x00, 0x02,
+ 0xf0, 0x7b, 0x28, 0x02, 0x9b, 0x7a, 0x00, 0x38, 0xc5, 0x28, 0xcd, 0x00, 0xff, 0x0d, 0x71, 0xa8,
+ 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x4f, 0x44, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38,
+ 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x10, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09,
+ 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff,
+ 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02,
+ 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x4e, 0x04, 0xfb, 0x9d, 0x33, 0x38,
+ 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x50, 0x98, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8,
+ 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x67, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x53, 0x04,
+ 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x53, 0x04, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x1c, 0x33, 0xc0, 0x8d, 0xfa, 0x00, 0x04, 0x8e, 0x7a, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x08,
+ 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x52, 0x79, 0x4f, 0xfc, 0xef, 0xff, 0xff, 0x9d, 0x33, 0xc0,
+ 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x73, 0x20, 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x72, 0x00, 0x00,
+ 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x1d, 0x33, 0x48,
+ 0xfe, 0x0d, 0x72, 0x60, 0xfd, 0xa5, 0x33, 0xd0, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7f, 0x79, 0x00, 0x02,
+ 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00, 0x9d, 0xfa, 0x00, 0x14,
+ 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xcf, 0xd0,
+ 0xff, 0x82, 0x04, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xcd, 0xd8, 0x8c, 0xf6, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20,
+ 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x31, 0xd4, 0x9f, 0xf6, 0x00, 0x04,
+ 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0x7e, 0x71, 0x00, 0x10,
+ 0xff, 0xf7, 0x28, 0x00, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xfd, 0x89, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0xed, 0x20, 0x00, 0xf0, 0x77, 0x28, 0x02,
+ 0xcc, 0x60, 0xdd, 0x00, 0xff, 0x86, 0x4f, 0x8c, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x52, 0x44, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6d, 0x58, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x53, 0xb1, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xb0, 0xff, 0x8c, 0x6c, 0xd8,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x39, 0x28, 0xff, 0x8c, 0x6c, 0xc8,
+ 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x52, 0xc1, 0xff, 0xa2, 0x02, 0x00,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8, 0xff, 0x8d, 0x38, 0xc0, 0xff, 0xa2, 0x02, 0x00,
+ 0xf3, 0x0d, 0x71, 0xb0, 0xfd, 0x0d, 0x71, 0xb4, 0xf4, 0x0d, 0x71, 0xb8, 0xc5, 0x28, 0xfd, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x52, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x53, 0x9c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x51, 0x11, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88,
+ 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0,
+ 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x53, 0x7d, 0x00, 0x00, 0x00, 0x01,
+ 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04,
+ 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x53, 0x85, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x53, 0x58, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x53, 0xb0,
+ 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x53, 0x6c, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x51, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x53, 0xb0, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xa6, 0x60,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x51, 0x10, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x86, 0x53, 0xbc, 0xe0, 0x01, 0x3c, 0xf8, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfb, 0x1c, 0x33, 0x48, 0xfc, 0x8c, 0x72, 0x60, 0xfe, 0x24, 0x33, 0xd0, 0x2d, 0x58, 0x0f, 0xfd,
+ 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03,
+ 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc,
+ 0xab, 0xfe, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x69, 0x30, 0xff, 0x08, 0xd3, 0xd8,
+ 0xfa, 0x9c, 0x33, 0x38, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7d, 0x68, 0xff, 0xfe, 0x4e, 0xe8, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xed, 0x00,
+ 0xff, 0xfb, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xfb, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xd8, 0x00,
+ 0x9c, 0xfa, 0x00, 0x14, 0x0e, 0x70, 0x10, 0x00, 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10,
+ 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xfb, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0xd8, 0x10, 0x00,
+ 0xff, 0x8a, 0xcf, 0xd0, 0xae, 0xfe, 0xd0, 0x05, 0xfc, 0x88, 0xcd, 0xd8, 0xfe, 0x7b, 0x18, 0x0a,
+ 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x7a, 0x00, 0x2c, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0xfa, 0xfb, 0x28, 0x20, 0xfb, 0xfb, 0x28, 0x22,
+ 0xfc, 0x7b, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00,
+ 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x32, 0xd4, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0x70, 0xe8, 0x00,
+ 0xfd, 0x09, 0xd3, 0xd8, 0x0e, 0xf4, 0x00, 0x01, 0xfe, 0xfb, 0x28, 0x1c, 0x4e, 0x70, 0x0f, 0xff,
+ 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0x7e, 0xf5, 0x00, 0x10, 0xff, 0xfb, 0x28, 0x00,
+ 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xea, 0x00, 0xfc, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0x4c, 0xe5, 0x20, 0x00, 0x2b, 0x58, 0x00, 0x02, 0xf0, 0x7b, 0x28, 0x02,
+ 0x9b, 0x7a, 0x00, 0x38, 0xc5, 0x28, 0xcd, 0x00, 0xff, 0x0d, 0x71, 0xa8, 0x55, 0x28, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x55, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00,
+ 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8, 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x67, 0x18, 0x04,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x57, 0x7c, 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00,
+ 0xe6, 0x01, 0x57, 0x7c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xc0, 0x8d, 0xfa, 0x00, 0x04,
+ 0x8e, 0x7a, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x08, 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x56, 0xf1,
+ 0x4f, 0xfc, 0xef, 0xff, 0xff, 0x9d, 0x33, 0xc0, 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x73, 0x20,
+ 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x72, 0x00, 0x00, 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x78, 0x00, 0x02,
+ 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x1d, 0x33, 0x48, 0xfe, 0x0d, 0x72, 0x60, 0xfd, 0xa5, 0x33, 0xd0,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14,
+ 0xcf, 0x74, 0xf0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09,
+ 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xae, 0x7a, 0xf8, 0x05,
+ 0xfd, 0x88, 0xcd, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a,
+ 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x31, 0xd4, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xd3, 0xd8,
+ 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x67, 0x28, 0x00,
+ 0x2f, 0xf8, 0x00, 0x01, 0x7e, 0x71, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x00, 0x9f, 0x66, 0x00, 0x08,
+ 0xcd, 0xec, 0xe2, 0x00, 0xfd, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0x4d, 0xed, 0x20, 0x00, 0xf0, 0x77, 0x28, 0x02, 0xcc, 0x60, 0xdd, 0x00, 0xff, 0x86, 0x53, 0xd0,
+ 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x56, 0xbc, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x6d, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x58, 0x29, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x1c, 0x33, 0xb0, 0xff, 0x8c, 0x6c, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe,
+ 0xff, 0x0c, 0x39, 0x28, 0xff, 0x8c, 0x6c, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x57, 0x39, 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8,
+ 0xff, 0x8d, 0x38, 0xc0, 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x71, 0xb0, 0xfd, 0x0d, 0x71, 0xb4,
+ 0xf4, 0x0d, 0x71, 0xb8, 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x57, 0x48, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58,
+ 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x58, 0x14, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x55, 0x89,
+ 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x57, 0xf5, 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04,
+ 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x57, 0xfd,
+ 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x57, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x58, 0x28, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x57, 0xe4,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x55, 0x88, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x58, 0x28,
+ 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x55, 0x88,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x58, 0x34, 0xe0, 0x01, 0x3c, 0xf8,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcd, 0x18, 0xd8, 0x00,
+ 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8, 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x6b, 0x18, 0x04,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x5a, 0x7c, 0xcc, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00,
+ 0xe6, 0x01, 0x5a, 0x7c, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x1c, 0x33, 0xc0, 0x8b, 0xf2, 0x00, 0x04,
+ 0x8c, 0xf2, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x08, 0x70, 0x5e, 0x00, 0x1f, 0xea, 0x01, 0x59, 0xf1,
+ 0x4d, 0x7c, 0xef, 0xff, 0x0d, 0xe0, 0x00, 0x03, 0x7f, 0xec, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xec, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xfd, 0x1d, 0x33, 0xc0,
+ 0xce, 0xf8, 0xfd, 0x00, 0x90, 0xf2, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc,
+ 0xad, 0x7e, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x78, 0x00, 0x02, 0xfe, 0x88, 0xd3, 0xd8,
+ 0x5f, 0xf8, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7d, 0xec, 0xff, 0xfe, 0x4e, 0x6c, 0x03, 0xff,
+ 0xfd, 0x77, 0x28, 0x12, 0x7f, 0x79, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00,
+ 0x0d, 0x78, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x0e, 0x9c, 0xf6, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00,
+ 0x9b, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0xff, 0x8a, 0xcf, 0xd0,
+ 0xaf, 0x7e, 0xd8, 0x05, 0xfc, 0x88, 0xcd, 0xd8, 0xfe, 0x77, 0x18, 0x0a, 0xff, 0xba, 0x00, 0x0e,
+ 0x8d, 0xf6, 0x00, 0x2c, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x9c, 0x02, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xf4, 0x77, 0x28, 0x1e, 0xfc, 0x77, 0x28, 0x22,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x30, 0xdc, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00, 0xfd, 0x89, 0xd3, 0xd8,
+ 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c, 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x6f, 0x28, 0x00,
+ 0x2f, 0xf0, 0x00, 0x01, 0x7f, 0x79, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x00, 0x9e, 0x6e, 0x00, 0x08,
+ 0xcc, 0xe4, 0xf2, 0x00, 0xfc, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0x23, 0xe0, 0x00, 0x02, 0x4c, 0xe5, 0x20, 0x00, 0xf0, 0x77, 0x28, 0x02, 0x93, 0xf6, 0x00, 0x38,
+ 0xc5, 0x28, 0xcd, 0x00, 0xfe, 0x8d, 0x71, 0xa8, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x59, 0xbc, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x6d, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x5b, 0x29, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x1c, 0x33, 0xb0, 0xff, 0x8c, 0x6c, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe,
+ 0xff, 0x0c, 0x39, 0x28, 0xff, 0x8c, 0x6c, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x5a, 0x39, 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8,
+ 0xff, 0x8d, 0x38, 0xc0, 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x71, 0xb0, 0xfc, 0x0d, 0x71, 0xb4,
+ 0xf4, 0x0d, 0x71, 0xb8, 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x5a, 0x48, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58,
+ 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x5b, 0x14, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x58, 0x79,
+ 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x5a, 0xf5, 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04,
+ 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x5a, 0xfd,
+ 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x5a, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x5b, 0x28, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x5a, 0xe4,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x58, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x5b, 0x28,
+ 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x58, 0x78,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x5b, 0x34, 0xe0, 0x01, 0x3c, 0xf8,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfb, 0x1c, 0x33, 0x48, 0xfc, 0x8c, 0x72, 0x60,
+ 0xfe, 0x24, 0x33, 0xd0, 0x2d, 0x58, 0x3f, 0xfd, 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc, 0xab, 0xfe, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00,
+ 0xfc, 0x0c, 0x69, 0x30, 0xff, 0x08, 0xd3, 0xd8, 0xfa, 0x9c, 0x33, 0x38, 0xe6, 0x6c, 0x00, 0x02,
+ 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7d, 0x68, 0xff, 0xfe, 0x4e, 0xe8, 0x03, 0xff,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02,
+ 0xfb, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xd8, 0x00, 0x9c, 0xfa, 0x00, 0x14, 0x0e, 0x70, 0x40, 0x00,
+ 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xfb, 0x68, 0x09,
+ 0x45, 0x29, 0xff, 0xfe, 0x2b, 0xd8, 0x40, 0x00, 0xff, 0x8a, 0xcf, 0xd0, 0xae, 0xfe, 0xd0, 0x05,
+ 0xfc, 0x88, 0xcd, 0xd8, 0xfe, 0x7b, 0x18, 0x0a, 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x7a, 0x00, 0x2c,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58,
+ 0xfa, 0xfb, 0x28, 0x20, 0xfb, 0xfb, 0x28, 0x22, 0xfc, 0x7b, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x32, 0xd4,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0x70, 0xe8, 0x00, 0xfd, 0x09, 0xd3, 0xd8, 0x0e, 0xf4, 0x00, 0x01,
+ 0xfe, 0xfb, 0x28, 0x1c, 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01,
+ 0x7e, 0xf5, 0x00, 0x10, 0xff, 0xfb, 0x28, 0x00, 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xea, 0x00,
+ 0xfc, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4c, 0xe5, 0x20, 0x00,
+ 0x2b, 0x58, 0x00, 0x02, 0xf0, 0x7b, 0x28, 0x02, 0x9b, 0x7a, 0x00, 0x38, 0xc5, 0x28, 0xcd, 0x00,
+ 0xff, 0x0d, 0x71, 0xa8, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x5c, 0x88, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x33, 0x38, 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02,
+ 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x30, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x5b, 0x48,
+ 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x5d, 0xdc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38, 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20,
+ 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8,
+ 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02,
+ 0x0e, 0xf4, 0x20, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14,
+ 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00,
+ 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22,
+ 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00,
+ 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00,
+ 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c,
+ 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10,
+ 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00,
+ 0xff, 0x06, 0x5c, 0xd0, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x5f, 0x30,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38, 0xfd, 0x8c, 0x72, 0x60,
+ 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x33, 0xd0,
+ 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x10, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xfb, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14,
+ 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0,
+ 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20,
+ 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01,
+ 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00,
+ 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00,
+ 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x5e, 0x24, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34,
+ 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x60, 0x84, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02,
+ 0xcc, 0x98, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8, 0xfe, 0xa4, 0x34, 0x50,
+ 0xfe, 0x67, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x63, 0x08, 0xcd, 0x1c, 0x00, 0x00,
+ 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x63, 0x08, 0x00, 0x00, 0x00, 0x01, 0xff, 0x18, 0x72, 0xf8,
+ 0x8d, 0xfa, 0x00, 0x04, 0x8e, 0x7a, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x08, 0x70, 0x6e, 0x00, 0x1f,
+ 0xea, 0x01, 0x62, 0x7d, 0x4e, 0xfc, 0xef, 0xff, 0xff, 0x8c, 0x6c, 0xd0, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x61, 0x31, 0x7f, 0xfd, 0x00, 0x03, 0xcf, 0xf8, 0xf8, 0x00, 0x4e, 0xfc, 0xef, 0xff,
+ 0xfe, 0x99, 0x72, 0xf8, 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x73, 0x20, 0xab, 0x9a, 0xf8, 0x01,
+ 0x20, 0x72, 0x00, 0x00, 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02,
+ 0xfd, 0x1d, 0x33, 0x48, 0xfe, 0x0d, 0x72, 0x60, 0xfd, 0xa5, 0x33, 0xd0, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01,
+ 0xff, 0x0a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xcd, 0xd8,
+ 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30,
+ 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x31, 0xd4,
+ 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0x70, 0x00, 0x01,
+ 0xfe, 0x77, 0x28, 0x1c, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01,
+ 0x7e, 0x71, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x00, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00,
+ 0xfd, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0xed, 0x20, 0x00,
+ 0xf0, 0x77, 0x28, 0x02, 0xcc, 0x60, 0xdd, 0x00, 0xff, 0x86, 0x5f, 0x78, 0xfb, 0x9d, 0x33, 0x38,
+ 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x62, 0x48, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6d, 0x58,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x63, 0xb5, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xb0,
+ 0xff, 0x8c, 0x6c, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x39, 0x28,
+ 0xff, 0x8c, 0x6c, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x62, 0xc5,
+ 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8, 0xff, 0x8d, 0x38, 0xc0,
+ 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x71, 0xb0, 0xfd, 0x0d, 0x71, 0xb4, 0xf4, 0x0d, 0x71, 0xb8,
+ 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x62, 0xd4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58, 0x70, 0x7a, 0x00, 0x07,
+ 0xea, 0x01, 0x63, 0xa0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x60, 0xfd, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02,
+ 0xff, 0x1e, 0x33, 0xd0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x63, 0x81,
+ 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00,
+ 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x63, 0x89, 0xc0, 0x76, 0xe2, 0x00,
+ 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x63, 0x5c, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0x63, 0xb4, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x63, 0x70, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x60, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x63, 0xb4, 0xf3, 0x82, 0x00, 0x02,
+ 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x60, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x63, 0xc0, 0xe0, 0x01, 0x3c, 0xf8, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfb, 0x1c, 0x33, 0x48, 0xfc, 0x8c, 0x72, 0x60, 0xfe, 0x24, 0x33, 0xd0,
+ 0x2d, 0x58, 0x2f, 0xfd, 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x4f, 0xe8, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xff, 0x82, 0x7c, 0xcc, 0xab, 0xfe, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x69, 0x30,
+ 0xff, 0x08, 0xd3, 0xd8, 0xfa, 0x9c, 0x33, 0x38, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7d, 0x68, 0xff, 0xfe, 0x4e, 0xe8, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xfb, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xd8, 0x00, 0x9c, 0xfa, 0x00, 0x14, 0x0e, 0x70, 0x30, 0x00, 0x9e, 0x7e, 0x00, 0x14,
+ 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xfb, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe,
+ 0x2b, 0xd8, 0x30, 0x00, 0xff, 0x8a, 0xcf, 0xd0, 0xae, 0xfe, 0xd0, 0x05, 0xfc, 0x88, 0xcd, 0xd8,
+ 0xfe, 0x7b, 0x18, 0x0a, 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x7a, 0x00, 0x2c, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0xfa, 0xfb, 0x28, 0x20,
+ 0xfb, 0xfb, 0x28, 0x22, 0xfc, 0x7b, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x32, 0xd4, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0x70, 0xe8, 0x00, 0xfd, 0x09, 0xd3, 0xd8, 0x0e, 0xf4, 0x00, 0x01, 0xfe, 0xfb, 0x28, 0x1c,
+ 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0x7e, 0xf5, 0x00, 0x10,
+ 0xff, 0xfb, 0x28, 0x00, 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xea, 0x00, 0xfc, 0x89, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4c, 0xe5, 0x20, 0x00, 0x2b, 0x58, 0x00, 0x02,
+ 0xf0, 0x7b, 0x28, 0x02, 0x9b, 0x7a, 0x00, 0x38, 0xc5, 0x28, 0xcd, 0x00, 0xff, 0x0d, 0x71, 0xa8,
+ 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x65, 0x14, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38,
+ 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x20, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09,
+ 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff,
+ 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02,
+ 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x63, 0xd4, 0xfb, 0x9d, 0x33, 0x38,
+ 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x66, 0x68, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x33, 0x38, 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02,
+ 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x10, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x65, 0x5c,
+ 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x67, 0xbc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02,
+ 0xff, 0x8c, 0x72, 0xd8, 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x67, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x6a, 0x40, 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x6a, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x18, 0x72, 0xf8, 0x8d, 0xfa, 0x00, 0x04, 0x8e, 0x7a, 0x00, 0x00,
+ 0x0f, 0xf8, 0x00, 0x08, 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x69, 0xb5, 0x4e, 0xfc, 0xef, 0xff,
+ 0xff, 0x8c, 0x6c, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x68, 0x69, 0x7f, 0xfd, 0x00, 0x03,
+ 0xcf, 0xf8, 0xf8, 0x00, 0x4e, 0xfc, 0xef, 0xff, 0xfe, 0x99, 0x72, 0xf8, 0x90, 0xfa, 0x00, 0x04,
+ 0xff, 0x9a, 0x73, 0x20, 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x72, 0x00, 0x00, 0xfe, 0x88, 0xd3, 0xd8,
+ 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x1d, 0x33, 0x48, 0xfe, 0x0d, 0x72, 0x60,
+ 0xfd, 0xa5, 0x33, 0xd0, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12,
+ 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10,
+ 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00,
+ 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xcd, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22,
+ 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x31, 0xd4, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00,
+ 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0x7e, 0x71, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x00,
+ 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xfd, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0xed, 0x20, 0x00, 0xf0, 0x77, 0x28, 0x02, 0xcc, 0x60, 0xdd, 0x00,
+ 0xff, 0x86, 0x66, 0xb0, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x69, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6d, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x6a, 0xed,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xb0, 0xff, 0x8c, 0x6c, 0xd8, 0xcf, 0xfc, 0xf2, 0x00,
+ 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x39, 0x28, 0xff, 0x8c, 0x6c, 0xc8, 0xcf, 0x78, 0xe8, 0x00,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x69, 0xfd, 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0,
+ 0xff, 0x0d, 0x6c, 0xc8, 0xff, 0x8d, 0x38, 0xc0, 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x71, 0xb0,
+ 0xfd, 0x0d, 0x71, 0xb4, 0xf4, 0x0d, 0x71, 0xb8, 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x6a, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xa6, 0x58, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x6a, 0xd8, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x68, 0x35, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0,
+ 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff,
+ 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0, 0xaf, 0x7e, 0xf0, 0x02,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x6a, 0xb9, 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02,
+ 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00,
+ 0xe6, 0x01, 0x6a, 0xc1, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x6a, 0x94, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x6a, 0xec, 0xf3, 0x82, 0x00, 0x02,
+ 0xe6, 0x01, 0x6a, 0xa8, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x68, 0x34, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0x6a, 0xec, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x68, 0x34, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x6a, 0xf8,
+ 0xe0, 0x01, 0x3c, 0xf8, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfb, 0x1c, 0x33, 0x48,
+ 0xfc, 0x8c, 0x72, 0x60, 0xfe, 0x24, 0x33, 0xd0, 0x2d, 0x58, 0x1f, 0xfd, 0x7f, 0xe8, 0xff, 0xfd,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02,
+ 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc, 0xab, 0xfe, 0xe8, 0x05,
+ 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x69, 0x30, 0xff, 0x08, 0xd3, 0xd8, 0xfa, 0x9c, 0x33, 0x38,
+ 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7d, 0x68, 0xff, 0xfe,
+ 0x4e, 0xe8, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e,
+ 0x7d, 0xed, 0x00, 0x02, 0xfb, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xd8, 0x00, 0x9c, 0xfa, 0x00, 0x14,
+ 0x0e, 0x70, 0x20, 0x00, 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00,
+ 0xfd, 0xfb, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0xd8, 0x20, 0x00, 0xff, 0x8a, 0xcf, 0xd0,
+ 0xae, 0xfe, 0xd0, 0x05, 0xfc, 0x88, 0xcd, 0xd8, 0xfe, 0x7b, 0x18, 0x0a, 0xff, 0x9a, 0x00, 0x0e,
+ 0x8d, 0x7a, 0x00, 0x2c, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x9b, 0x82, 0xfe, 0x58, 0xfa, 0xfb, 0x28, 0x20, 0xfb, 0xfb, 0x28, 0x22, 0xfc, 0x7b, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0xd4, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0x70, 0xe8, 0x00, 0xfd, 0x09, 0xd3, 0xd8,
+ 0x0e, 0xf4, 0x00, 0x01, 0xfe, 0xfb, 0x28, 0x1c, 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x6b, 0x28, 0x00,
+ 0x2f, 0xf0, 0x00, 0x01, 0x7e, 0xf5, 0x00, 0x10, 0xff, 0xfb, 0x28, 0x00, 0x9e, 0x6a, 0x00, 0x08,
+ 0xcc, 0xe4, 0xea, 0x00, 0xfc, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0x4c, 0xe5, 0x20, 0x00, 0x2b, 0x58, 0x00, 0x02, 0xf0, 0x7b, 0x28, 0x02, 0x9b, 0x7a, 0x00, 0x38,
+ 0xc5, 0x28, 0xcd, 0x00, 0xff, 0x0d, 0x71, 0xa8, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x6c, 0x4c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38, 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20,
+ 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8,
+ 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02,
+ 0x0e, 0xf4, 0x10, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14,
+ 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00,
+ 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22,
+ 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00,
+ 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00,
+ 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c,
+ 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10,
+ 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00,
+ 0xff, 0x06, 0x6b, 0x0c, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x6d, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00,
+ 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8, 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x67, 0x18, 0x04,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x70, 0x24, 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00,
+ 0xe6, 0x01, 0x70, 0x24, 0x00, 0x00, 0x00, 0x01, 0xff, 0x18, 0x72, 0xf8, 0x8d, 0xfa, 0x00, 0x04,
+ 0x8e, 0x7a, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x08, 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x6f, 0x99,
+ 0x4e, 0xfc, 0xef, 0xff, 0xff, 0x8c, 0x6c, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x6e, 0x4d,
+ 0x7f, 0xfd, 0x00, 0x03, 0xcf, 0xf8, 0xf8, 0x00, 0x4e, 0xfc, 0xef, 0xff, 0xfe, 0x99, 0x72, 0xf8,
+ 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x73, 0x20, 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x72, 0x00, 0x00,
+ 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x1d, 0x33, 0x48,
+ 0xfe, 0x0d, 0x72, 0x60, 0xfd, 0xa5, 0x33, 0xd0, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7f, 0x79, 0x00, 0x02,
+ 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00, 0x9d, 0xfa, 0x00, 0x14,
+ 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xcf, 0xd0,
+ 0xff, 0x82, 0x04, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xcd, 0xd8, 0x8c, 0xf6, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20,
+ 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x31, 0xd4, 0x9f, 0xf6, 0x00, 0x04,
+ 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0x7e, 0x71, 0x00, 0x10,
+ 0xff, 0xf7, 0x28, 0x00, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xfd, 0x89, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0xed, 0x20, 0x00, 0xf0, 0x77, 0x28, 0x02,
+ 0xcc, 0x60, 0xdd, 0x00, 0xff, 0x86, 0x6c, 0x94, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x6f, 0x64, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6d, 0x58, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x70, 0xd1, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xb0, 0xff, 0x8c, 0x6c, 0xd8,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x39, 0x28, 0xff, 0x8c, 0x6c, 0xc8,
+ 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x6f, 0xe1, 0xff, 0xa2, 0x02, 0x00,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8, 0xff, 0x8d, 0x38, 0xc0, 0xff, 0xa2, 0x02, 0x00,
+ 0xf3, 0x0d, 0x71, 0xb0, 0xfd, 0x0d, 0x71, 0xb4, 0xf4, 0x0d, 0x71, 0xb8, 0xc5, 0x28, 0xfd, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x6f, 0xf0,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x70, 0xbc,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x6e, 0x19, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88,
+ 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0,
+ 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x70, 0x9d, 0x00, 0x00, 0x00, 0x01,
+ 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04,
+ 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x70, 0xa5, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x70, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x70, 0xd0,
+ 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x70, 0x8c, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x6e, 0x18,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x70, 0xd0, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xa6, 0x60,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x6e, 0x18, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x86, 0x70, 0xdc, 0xe0, 0x01, 0x3c, 0xf8, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfb, 0x1c, 0x33, 0x48, 0xfc, 0x8c, 0x72, 0x60, 0xfe, 0x24, 0x33, 0xd0, 0x2d, 0x58, 0x0f, 0xfd,
+ 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03,
+ 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc,
+ 0xab, 0xfe, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x69, 0x30, 0xff, 0x08, 0xd3, 0xd8,
+ 0xfa, 0x9c, 0x33, 0x38, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7d, 0x68, 0xff, 0xfe, 0x4e, 0xe8, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xed, 0x00,
+ 0xff, 0xfb, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xfb, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xd8, 0x00,
+ 0x9c, 0xfa, 0x00, 0x14, 0x0e, 0x70, 0x10, 0x00, 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10,
+ 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xfb, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0xd8, 0x10, 0x00,
+ 0xff, 0x8a, 0xcf, 0xd0, 0xae, 0xfe, 0xd0, 0x05, 0xfc, 0x88, 0xcd, 0xd8, 0xfe, 0x7b, 0x18, 0x0a,
+ 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x7a, 0x00, 0x2c, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0xfa, 0xfb, 0x28, 0x20, 0xfb, 0xfb, 0x28, 0x22,
+ 0xfc, 0x7b, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00,
+ 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x32, 0xd4, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0x70, 0xe8, 0x00,
+ 0xfd, 0x09, 0xd3, 0xd8, 0x0e, 0xf4, 0x00, 0x01, 0xfe, 0xfb, 0x28, 0x1c, 0x4e, 0x70, 0x0f, 0xff,
+ 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0x7e, 0xf5, 0x00, 0x10, 0xff, 0xfb, 0x28, 0x00,
+ 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xea, 0x00, 0xfc, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0x4c, 0xe5, 0x20, 0x00, 0x2b, 0x58, 0x00, 0x02, 0xf0, 0x7b, 0x28, 0x02,
+ 0x9b, 0x7a, 0x00, 0x38, 0xc5, 0x28, 0xcd, 0x00, 0xff, 0x0d, 0x71, 0xa8, 0x55, 0x28, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x72, 0x30,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00,
+ 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8, 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x67, 0x18, 0x04,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x74, 0xb4, 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00,
+ 0xe6, 0x01, 0x74, 0xb4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x18, 0x72, 0xf8, 0x8d, 0xfa, 0x00, 0x04,
+ 0x8e, 0x7a, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x08, 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x74, 0x29,
+ 0x4e, 0xfc, 0xef, 0xff, 0xff, 0x8c, 0x6c, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x72, 0xdd,
+ 0x7f, 0xfd, 0x00, 0x03, 0xcf, 0xf8, 0xf8, 0x00, 0x4e, 0xfc, 0xef, 0xff, 0xfe, 0x99, 0x72, 0xf8,
+ 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x73, 0x20, 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x72, 0x00, 0x00,
+ 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x1d, 0x33, 0x48,
+ 0xfe, 0x0d, 0x72, 0x60, 0xfd, 0xa5, 0x33, 0xd0, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7f, 0x79, 0x00, 0x02,
+ 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00, 0x9d, 0xfa, 0x00, 0x14,
+ 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xcf, 0xd0,
+ 0xff, 0x82, 0x04, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xcd, 0xd8, 0x8c, 0xf6, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20,
+ 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x31, 0xd4, 0x9f, 0xf6, 0x00, 0x04,
+ 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0x7e, 0x71, 0x00, 0x10,
+ 0xff, 0xf7, 0x28, 0x00, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xfd, 0x89, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0xed, 0x20, 0x00, 0xf0, 0x77, 0x28, 0x02,
+ 0xcc, 0x60, 0xdd, 0x00, 0xff, 0x86, 0x70, 0xf0, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x73, 0xf4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6d, 0x58, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x75, 0x61, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xb0, 0xff, 0x8c, 0x6c, 0xd8,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x39, 0x28, 0xff, 0x8c, 0x6c, 0xc8,
+ 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x74, 0x71, 0xff, 0xa2, 0x02, 0x00,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8, 0xff, 0x8d, 0x38, 0xc0, 0xff, 0xa2, 0x02, 0x00,
+ 0xf3, 0x0d, 0x71, 0xb0, 0xfd, 0x0d, 0x71, 0xb4, 0xf4, 0x0d, 0x71, 0xb8, 0xc5, 0x28, 0xfd, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x74, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x75, 0x4c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x72, 0xa9, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88,
+ 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0,
+ 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x75, 0x2d, 0x00, 0x00, 0x00, 0x01,
+ 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04,
+ 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x75, 0x35, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x75, 0x08, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x75, 0x60,
+ 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x75, 0x1c, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x72, 0xa8,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x75, 0x60, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xa6, 0x60,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x72, 0xa8, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x86, 0x75, 0x6c, 0xe0, 0x01, 0x3c, 0xf8, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0xfe, 0x40, 0x02, 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8,
+ 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x77, 0xcc,
+ 0xcc, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x77, 0xcc, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x18, 0x72, 0xf8, 0x8b, 0xf2, 0x00, 0x04, 0x8c, 0xf2, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x08,
+ 0x70, 0x5e, 0x00, 0x1f, 0xea, 0x01, 0x77, 0x41, 0x4d, 0x7c, 0xef, 0xff, 0xff, 0x8c, 0x6c, 0xd0,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x75, 0xe9, 0x0d, 0xe0, 0x00, 0x03, 0x7f, 0xfd, 0x00, 0x03,
+ 0xcf, 0xf0, 0xf8, 0x00, 0x4d, 0x7c, 0xef, 0xff, 0x7f, 0xec, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xec, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xfd, 0x19, 0x72, 0xf8,
+ 0xce, 0xf8, 0xfd, 0x00, 0x90, 0xf2, 0x00, 0x04, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc,
+ 0xad, 0x7e, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x78, 0x00, 0x02, 0xfe, 0x88, 0xd3, 0xd8,
+ 0x5f, 0xf8, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7d, 0xec, 0xff, 0xfe, 0x4e, 0x6c, 0x03, 0xff,
+ 0xfd, 0x77, 0x28, 0x12, 0x7f, 0x79, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xe5, 0x00,
+ 0x0d, 0x78, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x0e, 0x9c, 0xf6, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00,
+ 0x9b, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0xff, 0x8a, 0xcf, 0xd0,
+ 0xaf, 0x7e, 0xd8, 0x05, 0xfc, 0x88, 0xcd, 0xd8, 0xfe, 0x77, 0x18, 0x0a, 0xff, 0xba, 0x00, 0x0e,
+ 0x8d, 0xf6, 0x00, 0x2c, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x9c, 0x02, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xf4, 0x77, 0x28, 0x1e, 0xfc, 0x77, 0x28, 0x22,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x30, 0xdc, 0x9f, 0xf6, 0x00, 0x04, 0xce, 0x70, 0xf0, 0x00, 0xfd, 0x89, 0xd3, 0xd8,
+ 0x0f, 0x78, 0x00, 0x01, 0xff, 0x77, 0x28, 0x1c, 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x6f, 0x28, 0x00,
+ 0x2f, 0xf0, 0x00, 0x01, 0x7f, 0x79, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x00, 0x9e, 0x6e, 0x00, 0x08,
+ 0xcc, 0xe4, 0xf2, 0x00, 0xfc, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0x23, 0xe0, 0x00, 0x02, 0x4c, 0xe5, 0x20, 0x00, 0xf0, 0x77, 0x28, 0x02, 0x93, 0xf6, 0x00, 0x38,
+ 0xc5, 0x28, 0xcd, 0x00, 0xfe, 0x8d, 0x71, 0xa8, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x77, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x6d, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x78, 0x79, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x1c, 0x33, 0xb0, 0xff, 0x8c, 0x6c, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe,
+ 0xff, 0x0c, 0x39, 0x28, 0xff, 0x8c, 0x6c, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x77, 0x89, 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8,
+ 0xff, 0x8d, 0x38, 0xc0, 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x71, 0xb0, 0xfc, 0x0d, 0x71, 0xb4,
+ 0xf4, 0x0d, 0x71, 0xb8, 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x77, 0x98, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58,
+ 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x78, 0x64, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x75, 0xb1,
+ 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x78, 0x45, 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04,
+ 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x78, 0x4d,
+ 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x78, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x78, 0x78, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x78, 0x34,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x75, 0xb0, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x78, 0x78,
+ 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x75, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x78, 0x84, 0xe0, 0x01, 0x3c, 0xf8,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfb, 0x1c, 0x33, 0x48, 0xfd, 0x0c, 0x72, 0x64,
+ 0xfc, 0x0c, 0x69, 0x30, 0x2e, 0x58, 0x3f, 0xfd, 0x7f, 0xf0, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xf0, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc, 0xac, 0xfe, 0xe8, 0x05, 0x20, 0x6a, 0x00, 0x00,
+ 0xff, 0x08, 0xd3, 0xd8, 0xfb, 0xa4, 0x33, 0xd4, 0xfa, 0x9c, 0x33, 0x38, 0xe6, 0x6c, 0x00, 0x02,
+ 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x70, 0xff, 0xfe, 0x4e, 0xf0, 0x03, 0xff,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02,
+ 0xcf, 0xf8, 0xd8, 0x00, 0xfc, 0xfb, 0x28, 0x12, 0x9d, 0x7a, 0x00, 0x14, 0x9b, 0xfe, 0x00, 0x14,
+ 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xfb, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe,
+ 0x2b, 0xd8, 0x40, 0x00, 0xff, 0x8a, 0xcf, 0xd0, 0xae, 0xfe, 0xe0, 0x05, 0xfd, 0x08, 0xcd, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0x9a, 0x00, 0x0e, 0xfe, 0x7b, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0xfa, 0xfb, 0x28, 0x20,
+ 0xfb, 0xfb, 0x28, 0x22, 0xfc, 0x7b, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x33, 0xd4, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0x70, 0xe8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0xf4, 0x00, 0x01, 0xfe, 0xfb, 0x28, 0x1c,
+ 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x67, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0x7e, 0xf5, 0x00, 0x10,
+ 0xff, 0xfb, 0x28, 0x00, 0x9e, 0x66, 0x00, 0x08, 0xcd, 0x68, 0xea, 0x00, 0xfd, 0x09, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0x69, 0x20, 0x00, 0x2b, 0x58, 0x00, 0x02,
+ 0xf0, 0x7b, 0x28, 0x02, 0x9b, 0x7a, 0x00, 0x38, 0xc5, 0x28, 0xd5, 0x00, 0xff, 0x0d, 0x71, 0xa8,
+ 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x79, 0xd4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38,
+ 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x30, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09,
+ 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff,
+ 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02,
+ 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x78, 0x98, 0xfb, 0x9d, 0x33, 0x38,
+ 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x7b, 0x28, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x33, 0x38, 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01,
+ 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02,
+ 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x20, 0x00,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10,
+ 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05,
+ 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8,
+ 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00,
+ 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08,
+ 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0,
+ 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x7a, 0x1c,
+ 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38, 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20,
+ 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8,
+ 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02,
+ 0x0e, 0xf4, 0x10, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14,
+ 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00,
+ 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22,
+ 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00,
+ 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00,
+ 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c,
+ 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10,
+ 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00,
+ 0xff, 0x06, 0x7b, 0x70, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x7d, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02, 0xcd, 0x18, 0xd8, 0x00,
+ 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8, 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x6b, 0x18, 0x04,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x80, 0x74, 0xcc, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00,
+ 0xe6, 0x01, 0x80, 0x74, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x98, 0x72, 0xf8, 0x0f, 0xf4, 0x00, 0x08,
+ 0x4e, 0x7c, 0xef, 0xff, 0x8c, 0xf6, 0x00, 0x04, 0x8d, 0x72, 0x00, 0x04, 0x8d, 0xf6, 0x00, 0x00,
+ 0x8b, 0x72, 0x00, 0x00, 0x0f, 0x70, 0x00, 0x08, 0xcf, 0xe4, 0xd5, 0x00, 0x70, 0x7e, 0x00, 0x1f,
+ 0xea, 0x01, 0x7f, 0xe9, 0x4f, 0x78, 0xef, 0xff, 0xff, 0x8c, 0x6c, 0xd0, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x7e, 0x91, 0x7f, 0xfd, 0x00, 0x03, 0xcf, 0xf4, 0xf8, 0x00, 0x4f, 0x7c, 0xef, 0xff,
+ 0xff, 0x19, 0x72, 0xf8, 0x90, 0xf6, 0x00, 0x04, 0xfd, 0x8d, 0x72, 0x60, 0xfc, 0xa5, 0x33, 0xd0,
+ 0x90, 0xf2, 0x00, 0x04, 0xff, 0x9a, 0x73, 0x20, 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x25, 0x33, 0xd4,
+ 0xfc, 0x1d, 0x33, 0x48, 0xfb, 0x0d, 0x72, 0x64, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7f, 0x79, 0x00, 0x02,
+ 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xf7, 0x28, 0x12, 0x9d, 0xf6, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00, 0x9c, 0xfa, 0x00, 0x14,
+ 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xcf, 0xd0,
+ 0xff, 0x82, 0x04, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xcd, 0xd8, 0x8c, 0xf6, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20,
+ 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x31, 0xd4, 0x9f, 0xf6, 0x00, 0x04,
+ 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0x7e, 0x71, 0x00, 0x10,
+ 0xff, 0xf7, 0x28, 0x00, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xfd, 0x89, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0xed, 0x20, 0x00, 0xf0, 0x77, 0x28, 0x02,
+ 0xcc, 0x60, 0xdd, 0x00, 0xff, 0x86, 0x7c, 0xc4, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x7f, 0xb4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6d, 0x58, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x81, 0x21, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xb0, 0xff, 0x8c, 0x6c, 0xd8,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x39, 0x28, 0xff, 0x8c, 0x6c, 0xc8,
+ 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x80, 0x31, 0xff, 0xa2, 0x02, 0x00,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8, 0xff, 0x8d, 0x38, 0xc0, 0xff, 0xa2, 0x02, 0x00,
+ 0xf3, 0x0d, 0x71, 0xb0, 0xfc, 0x0d, 0x71, 0xb4, 0xf4, 0x0d, 0x71, 0xb8, 0xc5, 0x28, 0xfd, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x80, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x81, 0x0c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x7e, 0x49, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88,
+ 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0,
+ 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x80, 0xed, 0x00, 0x00, 0x00, 0x01,
+ 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04,
+ 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x80, 0xf5, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x80, 0xc8, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x81, 0x20,
+ 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x80, 0xdc, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x7e, 0x48,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x81, 0x20, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xa6, 0x60,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x7e, 0x48, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x86, 0x81, 0x2c, 0xe0, 0x01, 0x3c, 0xf8, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfb, 0x1c, 0x33, 0x48, 0xfd, 0x0c, 0x72, 0x68, 0xfc, 0x0c, 0x69, 0x30, 0x2e, 0x58, 0x3f, 0xfd,
+ 0x7f, 0xf0, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xf0, 0x00, 0x03,
+ 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc,
+ 0xac, 0xfe, 0xe8, 0x05, 0x20, 0x6a, 0x00, 0x00, 0xff, 0x08, 0xd3, 0xd8, 0xfb, 0xa4, 0x33, 0xd8,
+ 0xfa, 0x9c, 0x33, 0x38, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7e, 0x70, 0xff, 0xfe, 0x4e, 0xf0, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xed, 0x00,
+ 0xff, 0xfb, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xcf, 0xf8, 0xd8, 0x00, 0xfc, 0xfb, 0x28, 0x12,
+ 0x9d, 0x7a, 0x00, 0x14, 0x9b, 0xfe, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00,
+ 0xfd, 0xfb, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe, 0x2b, 0xd8, 0x40, 0x00, 0xff, 0x8a, 0xcf, 0xd0,
+ 0xae, 0xfe, 0xe0, 0x05, 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0x9a, 0x00, 0x0e,
+ 0xfe, 0x7b, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0x9b, 0x82, 0xfe, 0x58, 0xfa, 0xfb, 0x28, 0x20, 0xfb, 0xfb, 0x28, 0x22, 0xfc, 0x7b, 0x28, 0x1e,
+ 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0x34, 0xd4, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0x89, 0xd3, 0xd8,
+ 0x0e, 0xf4, 0x00, 0x01, 0xfe, 0xfb, 0x28, 0x1c, 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x67, 0x28, 0x00,
+ 0x2f, 0xf0, 0x00, 0x01, 0x7e, 0xf5, 0x00, 0x10, 0xff, 0xfb, 0x28, 0x00, 0x9e, 0x66, 0x00, 0x08,
+ 0xcd, 0x68, 0xea, 0x00, 0xfd, 0x09, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0x4d, 0x69, 0x20, 0x00, 0x2b, 0x58, 0x00, 0x02, 0xf0, 0x7b, 0x28, 0x02, 0x9b, 0x7a, 0x00, 0x38,
+ 0xc5, 0x28, 0xd5, 0x00, 0xff, 0x0d, 0x71, 0xa8, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38, 0xfd, 0x8c, 0x72, 0x64, 0xff, 0x9a, 0x73, 0x20,
+ 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x33, 0xd4, 0xff, 0x08, 0xd3, 0xd8,
+ 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02,
+ 0x0e, 0xf4, 0x10, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14,
+ 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00,
+ 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22,
+ 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00,
+ 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00,
+ 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c,
+ 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10,
+ 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00,
+ 0xff, 0x06, 0x81, 0x40, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x83, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38, 0xfd, 0x8c, 0x72, 0x64,
+ 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xff, 0x08, 0xd3, 0xd8,
+ 0xfd, 0x24, 0x33, 0xd4, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7e, 0x71, 0x00, 0x02, 0xce, 0xf8, 0xe0, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xfb, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0x9d, 0xfa, 0x00, 0x14, 0xff, 0xfb, 0x28, 0x12, 0x9d, 0x76, 0x00, 0x14,
+ 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00,
+ 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22,
+ 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00,
+ 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00,
+ 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c,
+ 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10,
+ 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8,
+ 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00,
+ 0xff, 0x06, 0x82, 0xc4, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x85, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38, 0xfd, 0x8c, 0x72, 0x60,
+ 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0xa4, 0x33, 0xd0,
+ 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x10, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xfb, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14,
+ 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0,
+ 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20,
+ 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01,
+ 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00,
+ 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00,
+ 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x84, 0x18, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34,
+ 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x86, 0x74, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02,
+ 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8, 0xfe, 0xa4, 0x34, 0x50,
+ 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x89, 0x38, 0xcb, 0x1c, 0x00, 0x00,
+ 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x89, 0x38, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x98, 0x72, 0xf8,
+ 0x0f, 0xf4, 0x00, 0x08, 0x4e, 0x7c, 0xef, 0xff, 0x0f, 0x70, 0x00, 0x08, 0x4d, 0xf8, 0xef, 0xff,
+ 0x8c, 0x76, 0x00, 0x04, 0x8b, 0xf2, 0x00, 0x04, 0x8a, 0x6e, 0x00, 0x04, 0x8c, 0xf6, 0x00, 0x00,
+ 0xcf, 0xe0, 0xbd, 0x00, 0x8d, 0x72, 0x00, 0x00, 0x8a, 0xee, 0x00, 0x00, 0x0f, 0x6c, 0x00, 0x08,
+ 0xcf, 0xfc, 0xa5, 0x00, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x01, 0x88, 0xad, 0x4f, 0x78, 0xef, 0xff,
+ 0xff, 0x8c, 0x6c, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x87, 0x49, 0x7f, 0xfd, 0x00, 0x03,
+ 0xcf, 0xf4, 0xf8, 0x00, 0x4f, 0x7c, 0xef, 0xff, 0xff, 0x19, 0x72, 0xf8, 0x90, 0xf6, 0x00, 0x04,
+ 0xfc, 0x25, 0x33, 0xd0, 0xfc, 0x8d, 0x72, 0x60, 0x90, 0xf2, 0x00, 0x04, 0xfd, 0x0d, 0x72, 0x64,
+ 0xfb, 0xa5, 0x33, 0xd4, 0x90, 0xee, 0x00, 0x04, 0xff, 0x9a, 0x73, 0x20, 0xab, 0x9a, 0xf8, 0x01,
+ 0x20, 0x66, 0x00, 0x00, 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02,
+ 0xfa, 0x8d, 0x72, 0x68, 0xfa, 0x25, 0x33, 0xd8, 0xfb, 0x1d, 0x33, 0x48, 0x7f, 0xfd, 0x00, 0x0d,
+ 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc,
+ 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e,
+ 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9c, 0xf6, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00,
+ 0x9c, 0x7a, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01,
+ 0xff, 0x0a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xcd, 0xd8,
+ 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30,
+ 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x31, 0xd4,
+ 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0x70, 0x00, 0x01,
+ 0xfe, 0x77, 0x28, 0x1c, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01,
+ 0x7e, 0x71, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x00, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00,
+ 0xfd, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0xed, 0x20, 0x00,
+ 0xf0, 0x77, 0x28, 0x02, 0xcc, 0x60, 0xdd, 0x00, 0xff, 0x86, 0x85, 0x68, 0xfb, 0x9d, 0x33, 0x38,
+ 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x88, 0x78, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6d, 0x58,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x89, 0xe5, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xb0,
+ 0xff, 0x8c, 0x6c, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x39, 0x28,
+ 0xff, 0x8c, 0x6c, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x88, 0xf5,
+ 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8, 0xff, 0x8d, 0x38, 0xc0,
+ 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x71, 0xb0, 0xfb, 0x0d, 0x71, 0xb4, 0xf4, 0x0d, 0x71, 0xb8,
+ 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x89, 0x04, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58, 0x70, 0x7a, 0x00, 0x07,
+ 0xea, 0x01, 0x89, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x86, 0xed, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02,
+ 0xff, 0x1e, 0x33, 0xd0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x89, 0xb1,
+ 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00,
+ 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x89, 0xb9, 0xc0, 0x76, 0xe2, 0x00,
+ 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x89, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0x89, 0xe4, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x89, 0xa0, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x86, 0xec, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x89, 0xe4, 0xf3, 0x82, 0x00, 0x02,
+ 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x86, 0xec, 0x00, 0x00, 0x00, 0x01,
+ 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x89, 0xf0, 0xe0, 0x01, 0x3c, 0xf8, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfb, 0x1c, 0x33, 0x48, 0xfc, 0x8c, 0x72, 0x64, 0xfe, 0x24, 0x33, 0xd4,
+ 0x2d, 0x58, 0x2f, 0xfd, 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x4f, 0xe8, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xff, 0x82, 0x7c, 0xcc, 0xab, 0xfe, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00, 0xfc, 0x0c, 0x69, 0x30,
+ 0xff, 0x08, 0xd3, 0xd8, 0xfa, 0x9c, 0x33, 0x38, 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7d, 0x68, 0xff, 0xfe, 0x4e, 0xe8, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02, 0xfb, 0xfb, 0x28, 0x12,
+ 0xcf, 0xf8, 0xd8, 0x00, 0x9c, 0xfa, 0x00, 0x14, 0x0e, 0x70, 0x10, 0x00, 0x9e, 0x7e, 0x00, 0x14,
+ 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xfb, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe,
+ 0x2b, 0xd8, 0x30, 0x00, 0xff, 0x8a, 0xcf, 0xd0, 0xae, 0xfe, 0xd0, 0x05, 0xfc, 0x88, 0xcd, 0xd8,
+ 0xfe, 0x7b, 0x18, 0x0a, 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x7a, 0x00, 0x2c, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0xfa, 0xfb, 0x28, 0x20,
+ 0xfb, 0xfb, 0x28, 0x22, 0xfc, 0x7b, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x33, 0xd4, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0x70, 0xe8, 0x00, 0xfd, 0x09, 0xd3, 0xd8, 0x0e, 0xf4, 0x00, 0x01, 0xfe, 0xfb, 0x28, 0x1c,
+ 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0x7e, 0xf5, 0x00, 0x10,
+ 0xff, 0xfb, 0x28, 0x00, 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xea, 0x00, 0xfc, 0x89, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4c, 0xe5, 0x20, 0x00, 0x2b, 0x58, 0x00, 0x02,
+ 0xf0, 0x7b, 0x28, 0x02, 0x9b, 0x7a, 0x00, 0x38, 0xc5, 0x28, 0xcd, 0x00, 0xff, 0x0d, 0x71, 0xa8,
+ 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x8b, 0x44, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38,
+ 0xfd, 0x8c, 0x72, 0x64, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xff, 0x08, 0xd3, 0xd8, 0xfd, 0x24, 0x33, 0xd4, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0xce, 0xf8, 0xe0, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0x9d, 0xfa, 0x00, 0x14, 0xff, 0xfb, 0x28, 0x12,
+ 0x9d, 0x76, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0,
+ 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20,
+ 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01,
+ 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00,
+ 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00,
+ 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x8a, 0x04, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34,
+ 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x8c, 0x94, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38,
+ 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x10, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09,
+ 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff,
+ 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02,
+ 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x8b, 0x8c, 0xfb, 0x9d, 0x33, 0x38,
+ 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x8d, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0xfe, 0x40, 0x02, 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8,
+ 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x90, 0x8c,
+ 0xcc, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x90, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x98, 0x72, 0xf8, 0x0f, 0xf4, 0x00, 0x08, 0x4e, 0x7c, 0xef, 0xff, 0x8c, 0xf6, 0x00, 0x04,
+ 0x8d, 0x72, 0x00, 0x04, 0x8d, 0xf6, 0x00, 0x00, 0x8b, 0x72, 0x00, 0x00, 0x0f, 0x70, 0x00, 0x08,
+ 0xcf, 0xe4, 0xd5, 0x00, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x01, 0x90, 0x01, 0x4f, 0x78, 0xef, 0xff,
+ 0xff, 0x8c, 0x6c, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x8e, 0xa9, 0x7f, 0xfd, 0x00, 0x03,
+ 0xcf, 0xf4, 0xf8, 0x00, 0x4f, 0x7c, 0xef, 0xff, 0xff, 0x19, 0x72, 0xf8, 0x90, 0xf6, 0x00, 0x04,
+ 0xfd, 0x8d, 0x72, 0x60, 0xfc, 0xa5, 0x33, 0xd0, 0x90, 0xf2, 0x00, 0x04, 0xff, 0x9a, 0x73, 0x20,
+ 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x78, 0x00, 0x02,
+ 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x25, 0x33, 0xd4, 0xfc, 0x1d, 0x33, 0x48, 0xfb, 0x0d, 0x72, 0x64,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9d, 0xf6, 0x00, 0x14,
+ 0xcf, 0x74, 0xf0, 0x00, 0x9c, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09,
+ 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xae, 0x7a, 0xf8, 0x05,
+ 0xfd, 0x88, 0xcd, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a,
+ 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x31, 0xd4, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xd3, 0xd8,
+ 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x67, 0x28, 0x00,
+ 0x2f, 0xf8, 0x00, 0x01, 0x7e, 0x71, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x00, 0x9f, 0x66, 0x00, 0x08,
+ 0xcd, 0xec, 0xe2, 0x00, 0xfd, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0x4d, 0xed, 0x20, 0x00, 0xf0, 0x77, 0x28, 0x02, 0xcc, 0x60, 0xdd, 0x00, 0xff, 0x86, 0x8c, 0xdc,
+ 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x8f, 0xcc, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x6d, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x91, 0x39, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x1c, 0x33, 0xb0, 0xff, 0x8c, 0x6c, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe,
+ 0xff, 0x0c, 0x39, 0x28, 0xff, 0x8c, 0x6c, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x90, 0x49, 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8,
+ 0xff, 0x8d, 0x38, 0xc0, 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x71, 0xb0, 0xfc, 0x0d, 0x71, 0xb4,
+ 0xf4, 0x0d, 0x71, 0xb8, 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x90, 0x58, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58,
+ 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x91, 0x24, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x8e, 0x61,
+ 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x91, 0x05, 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04,
+ 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x91, 0x0d,
+ 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x90, 0xe0,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x91, 0x38, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x90, 0xf4,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x8e, 0x60, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x91, 0x38,
+ 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x8e, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x91, 0x44, 0xe0, 0x01, 0x3c, 0xf8,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfb, 0x1c, 0x33, 0x48, 0xfd, 0x0c, 0x72, 0x64,
+ 0xfc, 0x0c, 0x69, 0x30, 0x2e, 0x58, 0x1f, 0xfd, 0x7f, 0xf0, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xf0, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc, 0xac, 0xfe, 0xe8, 0x05, 0x20, 0x6a, 0x00, 0x00,
+ 0xff, 0x08, 0xd3, 0xd8, 0xfb, 0xa4, 0x33, 0xd4, 0xfa, 0x9c, 0x33, 0x38, 0xe6, 0x6c, 0x00, 0x02,
+ 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x70, 0xff, 0xfe, 0x4e, 0xf0, 0x03, 0xff,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02,
+ 0xcf, 0xf8, 0xd8, 0x00, 0xfc, 0xfb, 0x28, 0x12, 0x9d, 0x7a, 0x00, 0x14, 0x9b, 0xfe, 0x00, 0x14,
+ 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xfb, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe,
+ 0x2b, 0xd8, 0x20, 0x00, 0xff, 0x8a, 0xcf, 0xd0, 0xae, 0xfe, 0xe0, 0x05, 0xfd, 0x08, 0xcd, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0x9a, 0x00, 0x0e, 0xfe, 0x7b, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0xfa, 0xfb, 0x28, 0x20,
+ 0xfb, 0xfb, 0x28, 0x22, 0xfc, 0x7b, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x33, 0xd4, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0x70, 0xe8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0xf4, 0x00, 0x01, 0xfe, 0xfb, 0x28, 0x1c,
+ 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x67, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0x7e, 0xf5, 0x00, 0x10,
+ 0xff, 0xfb, 0x28, 0x00, 0x9e, 0x66, 0x00, 0x08, 0xcd, 0x68, 0xea, 0x00, 0xfd, 0x09, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0x69, 0x20, 0x00, 0x2b, 0x58, 0x00, 0x02,
+ 0xf0, 0x7b, 0x28, 0x02, 0x9b, 0x7a, 0x00, 0x38, 0xc5, 0x28, 0xd5, 0x00, 0xff, 0x0d, 0x71, 0xa8,
+ 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x92, 0x94, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38,
+ 0xfd, 0x8c, 0x72, 0x60, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xfe, 0xa4, 0x33, 0xd0, 0xff, 0x08, 0xd3, 0xd8, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0x0e, 0xf4, 0x10, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xe0, 0x00,
+ 0x9d, 0xfa, 0x00, 0x14, 0x9e, 0xfe, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09,
+ 0xfe, 0x8a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xe1, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xfc, 0x7b, 0x28, 0x20, 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff,
+ 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01,
+ 0xff, 0xfb, 0x28, 0x00, 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00,
+ 0xff, 0x82, 0x00, 0x28, 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02,
+ 0x4d, 0x69, 0x20, 0x00, 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x91, 0x58, 0xfb, 0x9d, 0x33, 0x38,
+ 0xff, 0x01, 0x04, 0x34, 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x93, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0xfe, 0x40, 0x02, 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8,
+ 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x96, 0x8c,
+ 0xcc, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x96, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x98, 0x72, 0xf8, 0x0f, 0xf4, 0x00, 0x08, 0x4e, 0x7c, 0xef, 0xff, 0x8c, 0xf6, 0x00, 0x04,
+ 0x8d, 0x72, 0x00, 0x04, 0x8d, 0xf6, 0x00, 0x00, 0x8b, 0x72, 0x00, 0x00, 0x0f, 0x70, 0x00, 0x08,
+ 0xcf, 0xe4, 0xd5, 0x00, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x01, 0x96, 0x01, 0x4f, 0x78, 0xef, 0xff,
+ 0xff, 0x8c, 0x6c, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x94, 0xa9, 0x7f, 0xfd, 0x00, 0x03,
+ 0xcf, 0xf4, 0xf8, 0x00, 0x4f, 0x7c, 0xef, 0xff, 0xff, 0x19, 0x72, 0xf8, 0x90, 0xf6, 0x00, 0x04,
+ 0xfd, 0x8d, 0x72, 0x60, 0xfc, 0xa5, 0x33, 0xd0, 0x90, 0xf2, 0x00, 0x04, 0xff, 0x9a, 0x73, 0x20,
+ 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00, 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x78, 0x00, 0x02,
+ 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x25, 0x33, 0xd4, 0xfc, 0x1d, 0x33, 0x48, 0xfb, 0x0d, 0x72, 0x64,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9d, 0xf6, 0x00, 0x14,
+ 0xcf, 0x74, 0xf0, 0x00, 0x9c, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09,
+ 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xae, 0x7a, 0xf8, 0x05,
+ 0xfd, 0x88, 0xcd, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a,
+ 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x31, 0xd4, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xd3, 0xd8,
+ 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x67, 0x28, 0x00,
+ 0x2f, 0xf8, 0x00, 0x01, 0x7e, 0x71, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x00, 0x9f, 0x66, 0x00, 0x08,
+ 0xcd, 0xec, 0xe2, 0x00, 0xfd, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0x4d, 0xed, 0x20, 0x00, 0xf0, 0x77, 0x28, 0x02, 0xcc, 0x60, 0xdd, 0x00, 0xff, 0x86, 0x92, 0xdc,
+ 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x95, 0xcc, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x6d, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x97, 0x39, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x1c, 0x33, 0xb0, 0xff, 0x8c, 0x6c, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe,
+ 0xff, 0x0c, 0x39, 0x28, 0xff, 0x8c, 0x6c, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x96, 0x49, 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8,
+ 0xff, 0x8d, 0x38, 0xc0, 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x71, 0xb0, 0xfc, 0x0d, 0x71, 0xb4,
+ 0xf4, 0x0d, 0x71, 0xb8, 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x96, 0x58, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58,
+ 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x97, 0x24, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x94, 0x61,
+ 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x97, 0x05, 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04,
+ 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x97, 0x0d,
+ 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x96, 0xe0,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x97, 0x38, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x96, 0xf4,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x94, 0x60, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x97, 0x38,
+ 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x94, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x97, 0x44, 0xe0, 0x01, 0x3c, 0xf8,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfb, 0x1c, 0x33, 0x48, 0xfc, 0x8c, 0x72, 0x60,
+ 0xfe, 0x24, 0x33, 0xd0, 0x2d, 0x58, 0x0f, 0xfd, 0x7f, 0xe8, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xe8, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc, 0xab, 0xfe, 0xe8, 0x05, 0x20, 0x66, 0x00, 0x00,
+ 0xfc, 0x0c, 0x69, 0x30, 0xff, 0x08, 0xd3, 0xd8, 0xfa, 0x9c, 0x33, 0x38, 0xe6, 0x6c, 0x00, 0x02,
+ 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7d, 0x68, 0xff, 0xfe, 0x4e, 0xe8, 0x03, 0xff,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02,
+ 0xfb, 0xfb, 0x28, 0x12, 0xcf, 0xf8, 0xd8, 0x00, 0x9c, 0xfa, 0x00, 0x14, 0x0e, 0x70, 0x10, 0x00,
+ 0x9e, 0x7e, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xfb, 0x68, 0x09,
+ 0x45, 0x29, 0xff, 0xfe, 0x2b, 0xd8, 0x10, 0x00, 0xff, 0x8a, 0xcf, 0xd0, 0xae, 0xfe, 0xd0, 0x05,
+ 0xfc, 0x88, 0xcd, 0xd8, 0xfe, 0x7b, 0x18, 0x0a, 0xff, 0x9a, 0x00, 0x0e, 0x8d, 0x7a, 0x00, 0x2c,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58,
+ 0xfa, 0xfb, 0x28, 0x20, 0xfb, 0xfb, 0x28, 0x22, 0xfc, 0x7b, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x32, 0xd4,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0x70, 0xe8, 0x00, 0xfd, 0x09, 0xd3, 0xd8, 0x0e, 0xf4, 0x00, 0x01,
+ 0xfe, 0xfb, 0x28, 0x1c, 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x6b, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01,
+ 0x7e, 0xf5, 0x00, 0x10, 0xff, 0xfb, 0x28, 0x00, 0x9e, 0x6a, 0x00, 0x08, 0xcc, 0xe4, 0xea, 0x00,
+ 0xfc, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4c, 0xe5, 0x20, 0x00,
+ 0x2b, 0x58, 0x00, 0x02, 0xf0, 0x7b, 0x28, 0x02, 0x9b, 0x7a, 0x00, 0x38, 0xc5, 0x28, 0xcd, 0x00,
+ 0xff, 0x0d, 0x71, 0xa8, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x98, 0x98, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0xfe, 0x40, 0x02, 0xcc, 0x98, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8,
+ 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x67, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0x9b, 0x1c,
+ 0xcd, 0x1c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0x9b, 0x1c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x18, 0x72, 0xf8, 0x8d, 0xfa, 0x00, 0x04, 0x8e, 0x7a, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x08,
+ 0x70, 0x6e, 0x00, 0x1f, 0xea, 0x01, 0x9a, 0x91, 0x4e, 0xfc, 0xef, 0xff, 0xff, 0x8c, 0x6c, 0xd0,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x99, 0x45, 0x7f, 0xfd, 0x00, 0x03, 0xcf, 0xf8, 0xf8, 0x00,
+ 0x4e, 0xfc, 0xef, 0xff, 0xfe, 0x99, 0x72, 0xf8, 0x90, 0xfa, 0x00, 0x04, 0xff, 0x9a, 0x73, 0x20,
+ 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x72, 0x00, 0x00, 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x78, 0x00, 0x02,
+ 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x1d, 0x33, 0x48, 0xfe, 0x0d, 0x72, 0x60, 0xfd, 0xa5, 0x33, 0xd0,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12, 0x9e, 0x76, 0x00, 0x14,
+ 0xcf, 0x74, 0xf0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09,
+ 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00, 0xae, 0x7a, 0xf8, 0x05,
+ 0xfd, 0x88, 0xcd, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a,
+ 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e,
+ 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58,
+ 0xff, 0x86, 0x31, 0xd4, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xd3, 0xd8,
+ 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x67, 0x28, 0x00,
+ 0x2f, 0xf8, 0x00, 0x01, 0x7e, 0x71, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x00, 0x9f, 0x66, 0x00, 0x08,
+ 0xcd, 0xec, 0xe2, 0x00, 0xfd, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0x4d, 0xed, 0x20, 0x00, 0xf0, 0x77, 0x28, 0x02, 0xcc, 0x60, 0xdd, 0x00, 0xff, 0x86, 0x97, 0x58,
+ 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x9a, 0x5c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x6d, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x9b, 0xc9, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x1c, 0x33, 0xb0, 0xff, 0x8c, 0x6c, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe,
+ 0xff, 0x0c, 0x39, 0x28, 0xff, 0x8c, 0x6c, 0xc8, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x01, 0x9a, 0xd9, 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8,
+ 0xff, 0x8d, 0x38, 0xc0, 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x71, 0xb0, 0xfd, 0x0d, 0x71, 0xb4,
+ 0xf4, 0x0d, 0x71, 0xb8, 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0x9a, 0xe8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58,
+ 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0x9b, 0xb4, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x99, 0x11,
+ 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0, 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0x9b, 0x95, 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x67, 0x18, 0x04,
+ 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0x9b, 0x9d,
+ 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x9b, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x9b, 0xc8, 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0x9b, 0x84,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x99, 0x10, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0x9b, 0xc8,
+ 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x99, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0x9b, 0xd4, 0xe0, 0x01, 0x3c, 0xf8,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfb, 0x1c, 0x33, 0x48, 0xfd, 0x0c, 0x72, 0x68,
+ 0xfc, 0x0c, 0x69, 0x30, 0x2e, 0x58, 0x1f, 0xfd, 0x7f, 0xf0, 0xff, 0xfd, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xf0, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02, 0xce, 0xf8, 0xfd, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc, 0xac, 0xfe, 0xe8, 0x05, 0x20, 0x6a, 0x00, 0x00,
+ 0xff, 0x08, 0xd3, 0xd8, 0xfb, 0xa4, 0x33, 0xd8, 0xfa, 0x9c, 0x33, 0x38, 0xe6, 0x6c, 0x00, 0x02,
+ 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x70, 0xff, 0xfe, 0x4e, 0xf0, 0x03, 0xff,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0x7d, 0xed, 0x00, 0x02,
+ 0xcf, 0xf8, 0xd8, 0x00, 0xfc, 0xfb, 0x28, 0x12, 0x9d, 0x7a, 0x00, 0x14, 0x9b, 0xfe, 0x00, 0x14,
+ 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xfb, 0x68, 0x09, 0x45, 0x29, 0xff, 0xfe,
+ 0x2b, 0xd8, 0x20, 0x00, 0xff, 0x8a, 0xcf, 0xd0, 0xae, 0xfe, 0xe0, 0x05, 0xfd, 0x08, 0xcd, 0xd8,
+ 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0x9a, 0x00, 0x0e, 0xfe, 0x7b, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30,
+ 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58, 0xfa, 0xfb, 0x28, 0x20,
+ 0xfb, 0xfb, 0x28, 0x22, 0xfc, 0x7b, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x34, 0xd4, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0x70, 0xe8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0xf4, 0x00, 0x01, 0xfe, 0xfb, 0x28, 0x1c,
+ 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x67, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01, 0x7e, 0xf5, 0x00, 0x10,
+ 0xff, 0xfb, 0x28, 0x00, 0x9e, 0x66, 0x00, 0x08, 0xcd, 0x68, 0xea, 0x00, 0xfd, 0x09, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0x69, 0x20, 0x00, 0x2b, 0x58, 0x00, 0x02,
+ 0xf0, 0x7b, 0x28, 0x02, 0x9b, 0x7a, 0x00, 0x38, 0xc5, 0x28, 0xd5, 0x00, 0xff, 0x0d, 0x71, 0xa8,
+ 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x9d, 0x24, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x38,
+ 0xfd, 0x8c, 0x72, 0x64, 0xff, 0x9a, 0x73, 0x20, 0xab, 0xe2, 0xf8, 0x01, 0x20, 0x6e, 0x00, 0x00,
+ 0xff, 0x08, 0xd3, 0xd8, 0xfd, 0x24, 0x33, 0xd4, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x71, 0x00, 0x02, 0xce, 0xf8, 0xe0, 0x00, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0x9d, 0xfa, 0x00, 0x14, 0xff, 0xfb, 0x28, 0x12,
+ 0x9d, 0x76, 0x00, 0x14, 0x0e, 0x70, 0x00, 0x10, 0xfe, 0x7b, 0x68, 0x09, 0xfe, 0x8a, 0xcf, 0xd0,
+ 0xff, 0x82, 0x04, 0x00, 0xad, 0xf6, 0xf8, 0x05, 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xfe, 0xfb, 0x18, 0x0a, 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xe1, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x20,
+ 0xff, 0xfb, 0x28, 0x22, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x32, 0x50, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x4e, 0xf4, 0x0f, 0xff, 0x0d, 0xec, 0x00, 0x01,
+ 0xfd, 0xfb, 0x28, 0x1c, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01, 0xff, 0xfb, 0x28, 0x00,
+ 0x7d, 0xed, 0x00, 0x10, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xff, 0x82, 0x00, 0x28,
+ 0xfd, 0x09, 0xcd, 0xd8, 0x9f, 0x82, 0xff, 0xb0, 0xf0, 0x7b, 0x28, 0x02, 0x4d, 0x69, 0x20, 0x00,
+ 0xcf, 0xa8, 0xd5, 0x00, 0xff, 0x06, 0x9b, 0xe8, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x01, 0x04, 0x34,
+ 0x55, 0x7c, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0x9e, 0x74, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0xfe, 0x40, 0x02,
+ 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8, 0xfe, 0xa4, 0x34, 0x50,
+ 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0xa1, 0x30, 0xcb, 0x1c, 0x00, 0x00,
+ 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0xa1, 0x30, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x98, 0x72, 0xf8,
+ 0x0f, 0xf4, 0x00, 0x08, 0x4e, 0x7c, 0xef, 0xff, 0x0f, 0x70, 0x00, 0x08, 0x4d, 0xf8, 0xef, 0xff,
+ 0x8a, 0x76, 0x00, 0x04, 0x8c, 0xf2, 0x00, 0x04, 0x8c, 0x6e, 0x00, 0x04, 0x8a, 0xf6, 0x00, 0x00,
+ 0xcf, 0xd0, 0xcd, 0x00, 0x8d, 0x72, 0x00, 0x00, 0x89, 0xee, 0x00, 0x00, 0x0f, 0x6c, 0x00, 0x08,
+ 0xcf, 0xfc, 0xc5, 0x00, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x01, 0xa0, 0xa5, 0x4f, 0x78, 0xef, 0xff,
+ 0xff, 0x8c, 0x6c, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0x9f, 0x49, 0x7f, 0xfd, 0x00, 0x03,
+ 0xcf, 0xf4, 0xf8, 0x00, 0x4f, 0x7c, 0xef, 0xff, 0xff, 0x19, 0x72, 0xf8, 0x90, 0xf6, 0x00, 0x04,
+ 0x90, 0xf2, 0x00, 0x04, 0xfd, 0x0d, 0x72, 0x64, 0xfc, 0xa5, 0x33, 0xd4, 0x90, 0xee, 0x00, 0x04,
+ 0xff, 0x9a, 0x73, 0x20, 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x56, 0x00, 0x00, 0xfe, 0x88, 0xd3, 0xd8,
+ 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02, 0xfc, 0x25, 0x33, 0xd8, 0xf9, 0x8d, 0x72, 0x68,
+ 0xfb, 0x1d, 0x33, 0x48, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50,
+ 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7f, 0x79, 0x00, 0x02, 0x0d, 0x78, 0x00, 0x10,
+ 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xf7, 0x28, 0x12,
+ 0x9a, 0xf6, 0x00, 0x14, 0xcf, 0x74, 0xf0, 0x00, 0x9a, 0x7a, 0x00, 0x14, 0x0f, 0xe8, 0x00, 0x10,
+ 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xcf, 0xd0, 0xff, 0x82, 0x04, 0x00,
+ 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xcd, 0xd8, 0x8c, 0xf6, 0x00, 0x2c, 0xff, 0xb6, 0x00, 0x0e,
+ 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20, 0xff, 0xf7, 0x28, 0x22,
+ 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0x69, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x31, 0xd4, 0x9f, 0xf6, 0x00, 0x04, 0xcf, 0x78, 0xe0, 0x00,
+ 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0x7e, 0x71, 0x00, 0x10, 0xff, 0xf7, 0x28, 0x00,
+ 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xfd, 0x89, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0xed, 0x20, 0x00, 0xf0, 0x77, 0x28, 0x02, 0xcc, 0x60, 0xdd, 0x00,
+ 0xff, 0x86, 0x9d, 0x6c, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x81, 0x04, 0x34, 0x55, 0x60, 0x02, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xa0, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6d, 0x58, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xa1, 0xdd,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xb0, 0xff, 0x8c, 0x6c, 0xd8, 0xcf, 0xfc, 0xf2, 0x00,
+ 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x39, 0x28, 0xff, 0x8c, 0x6c, 0xc8, 0xcf, 0x78, 0xe8, 0x00,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0xa0, 0xed, 0xff, 0xa2, 0x02, 0x00, 0x8f, 0x82, 0xff, 0xd0,
+ 0xff, 0x0d, 0x6c, 0xc8, 0xff, 0x8d, 0x38, 0xc0, 0xff, 0xa2, 0x02, 0x00, 0xf3, 0x0d, 0x71, 0xb0,
+ 0xfb, 0x0d, 0x71, 0xb4, 0xf4, 0x0d, 0x71, 0xb8, 0xc5, 0x28, 0xfd, 0x00, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xa0, 0xfc, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0xa6, 0x58, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0xa1, 0xc8, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x9e, 0xed, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88, 0x9f, 0x02, 0xfe, 0xa0,
+ 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88, 0xff, 0x02, 0x7f, 0xff,
+ 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0, 0xaf, 0x7e, 0xf0, 0x02,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0xa1, 0xa9, 0x00, 0x00, 0x00, 0x01, 0xad, 0x9a, 0xd8, 0x02,
+ 0xfe, 0x6b, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04, 0xc0, 0x7e, 0xda, 0x00,
+ 0xe6, 0x01, 0xa1, 0xb1, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x01, 0xa1, 0x84, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xa1, 0xdc, 0xf3, 0x82, 0x00, 0x02,
+ 0xe6, 0x01, 0xa1, 0x98, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0x9e, 0xec, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0xa1, 0xdc, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0x9e, 0xec, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01, 0xf7, 0x86, 0xa1, 0xe8,
+ 0xe0, 0x01, 0x3c, 0xf8, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfb, 0x1c, 0x33, 0x48,
+ 0xfd, 0x0c, 0x72, 0x64, 0xfc, 0x0c, 0x69, 0x30, 0x2e, 0x58, 0x0f, 0xfd, 0x7f, 0xf0, 0xff, 0xfd,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x4f, 0xf0, 0x00, 0x03, 0x7f, 0x75, 0x00, 0x02,
+ 0xce, 0xf8, 0xfd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xff, 0x82, 0x7c, 0xcc, 0xac, 0xfe, 0xe8, 0x05,
+ 0x20, 0x6a, 0x00, 0x00, 0xff, 0x08, 0xd3, 0xd8, 0xfb, 0xa4, 0x33, 0xd4, 0xfa, 0x9c, 0x33, 0x38,
+ 0xe6, 0x6c, 0x00, 0x02, 0x5f, 0xec, 0x00, 0x02, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7e, 0x70, 0xff, 0xfe,
+ 0x4e, 0xf0, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e,
+ 0x7d, 0xed, 0x00, 0x02, 0xcf, 0xf8, 0xd8, 0x00, 0xfc, 0xfb, 0x28, 0x12, 0x9d, 0x7a, 0x00, 0x14,
+ 0x9b, 0xfe, 0x00, 0x14, 0x0d, 0xec, 0x00, 0x10, 0x4c, 0x61, 0x00, 0x00, 0xfd, 0xfb, 0x68, 0x09,
+ 0x45, 0x29, 0xff, 0xfe, 0x2b, 0xd8, 0x10, 0x00, 0xff, 0x8a, 0xcf, 0xd0, 0xae, 0xfe, 0xe0, 0x05,
+ 0xfd, 0x08, 0xcd, 0xd8, 0x8c, 0xfa, 0x00, 0x2c, 0xff, 0x9a, 0x00, 0x0e, 0xfe, 0x7b, 0x18, 0x0a,
+ 0x9f, 0xfa, 0x00, 0x30, 0x5f, 0xd5, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9b, 0x82, 0xfe, 0x58,
+ 0xfa, 0xfb, 0x28, 0x20, 0xfb, 0xfb, 0x28, 0x22, 0xfc, 0x7b, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5d, 0xed, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x86, 0x33, 0xd4,
+ 0x9f, 0xfa, 0x00, 0x04, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0xf4, 0x00, 0x01,
+ 0xfe, 0xfb, 0x28, 0x1c, 0x4e, 0x70, 0x0f, 0xff, 0xfe, 0x67, 0x28, 0x00, 0x2f, 0xf0, 0x00, 0x01,
+ 0x7e, 0xf5, 0x00, 0x10, 0xff, 0xfb, 0x28, 0x00, 0x9e, 0x66, 0x00, 0x08, 0xcd, 0x68, 0xea, 0x00,
+ 0xfd, 0x09, 0xcd, 0xd8, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0x69, 0x20, 0x00,
+ 0x2b, 0x58, 0x00, 0x02, 0xf0, 0x7b, 0x28, 0x02, 0x9b, 0x7a, 0x00, 0x38, 0xc5, 0x28, 0xd5, 0x00,
+ 0xff, 0x0d, 0x71, 0xa8, 0x55, 0x28, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xa3, 0x38, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0xfe, 0x40, 0x02, 0xcd, 0x18, 0xd8, 0x00, 0xaf, 0x1a, 0xd8, 0x02, 0xff, 0x8c, 0x72, 0xd8,
+ 0xfe, 0xa4, 0x34, 0x50, 0xfe, 0x6b, 0x18, 0x04, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0xa5, 0xd4,
+ 0xcc, 0x9c, 0x00, 0x00, 0xc0, 0x72, 0xea, 0x00, 0xe6, 0x01, 0xa5, 0xd4, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x98, 0x72, 0xf8, 0x0f, 0xf4, 0x00, 0x08, 0x4e, 0x7c, 0xef, 0xff, 0x8b, 0x76, 0x00, 0x04,
+ 0x8d, 0xf2, 0x00, 0x04, 0x8c, 0x76, 0x00, 0x00, 0x8d, 0x72, 0x00, 0x00, 0x0f, 0x70, 0x00, 0x08,
+ 0xcf, 0xd8, 0xdd, 0x00, 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x01, 0xa5, 0x49, 0x4f, 0x78, 0xef, 0xff,
+ 0xff, 0x8c, 0x6c, 0xd0, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xa3, 0xf9, 0x7f, 0xfd, 0x00, 0x03,
+ 0xcf, 0xf4, 0xf8, 0x00, 0x4f, 0x7c, 0xef, 0xff, 0xff, 0x19, 0x72, 0xf8, 0x90, 0xf6, 0x00, 0x04,
+ 0x90, 0xf2, 0x00, 0x04, 0xff, 0x9a, 0x73, 0x20, 0xab, 0x9a, 0xf8, 0x01, 0x20, 0x62, 0x00, 0x00,
+ 0xfe, 0x88, 0xd3, 0xd8, 0xe6, 0x78, 0x00, 0x02, 0x5f, 0xf8, 0x00, 0x02, 0xfd, 0x0d, 0x72, 0x64,
+ 0xfd, 0xa5, 0x33, 0xd4, 0xfc, 0x9d, 0x33, 0x48, 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xf7, 0x28, 0x0c,
+ 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xf7, 0x68, 0x08, 0xff, 0x88, 0x9f, 0xfc, 0x7f, 0x79, 0x00, 0x02,
+ 0x0d, 0x78, 0x00, 0x10, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff,
+ 0x9c, 0x76, 0x00, 0x14, 0xff, 0xf7, 0x28, 0x12, 0xcf, 0x74, 0xf0, 0x00, 0x9b, 0x7a, 0x00, 0x14,
+ 0x0f, 0xe8, 0x00, 0x10, 0xff, 0xf7, 0x68, 0x09, 0x5c, 0x29, 0x00, 0x01, 0xff, 0x0a, 0xcf, 0xd0,
+ 0xff, 0x82, 0x04, 0x00, 0xae, 0x7a, 0xf8, 0x05, 0xfd, 0x88, 0xcd, 0xd8, 0x8c, 0xf6, 0x00, 0x2c,
+ 0xff, 0xb6, 0x00, 0x0e, 0xff, 0x77, 0x18, 0x0a, 0x9f, 0xf6, 0x00, 0x30, 0x5f, 0x99, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xff, 0x82, 0x10, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xf3, 0x77, 0x28, 0x20,
+ 0xff, 0xf7, 0x28, 0x22, 0xfb, 0xf7, 0x28, 0x1e, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5d, 0x69, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0x58, 0xff, 0x86, 0x31, 0xd4, 0x9f, 0xf6, 0x00, 0x04,
+ 0xcf, 0x78, 0xe0, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0e, 0x70, 0x00, 0x01, 0xfe, 0x77, 0x28, 0x1c,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x67, 0x28, 0x00, 0x2f, 0xf8, 0x00, 0x01, 0x7e, 0x71, 0x00, 0x10,
+ 0xff, 0xf7, 0x28, 0x00, 0x9f, 0x66, 0x00, 0x08, 0xcd, 0xec, 0xe2, 0x00, 0xfd, 0x89, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0xed, 0x20, 0x00, 0xf0, 0x77, 0x28, 0x02,
+ 0xcc, 0x60, 0xdd, 0x00, 0xff, 0x86, 0xa1, 0xfc, 0xfb, 0x9d, 0x33, 0x38, 0xff, 0x81, 0x04, 0x34,
+ 0x55, 0x60, 0x02, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xa5, 0x14, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6d, 0x58, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0xa6, 0x81, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xb0, 0xff, 0x8c, 0x6c, 0xd8,
+ 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x39, 0x28, 0xff, 0x8c, 0x6c, 0xc8,
+ 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x01, 0xa5, 0x91, 0xff, 0xa2, 0x02, 0x00,
+ 0x8f, 0x82, 0xff, 0xd0, 0xff, 0x0d, 0x6c, 0xc8, 0xff, 0x8d, 0x38, 0xc0, 0xff, 0xa2, 0x02, 0x00,
+ 0xf3, 0x0d, 0x71, 0xb0, 0xfc, 0x8d, 0x71, 0xb4, 0xf4, 0x0d, 0x71, 0xb8, 0xc5, 0x28, 0xfd, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xa5, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x58, 0x70, 0x7a, 0x00, 0x07, 0xea, 0x01, 0xa6, 0x6c,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xa3, 0xb1, 0x00, 0x00, 0x00, 0x01, 0x90, 0x82, 0xfe, 0x88,
+ 0x9f, 0x02, 0xfe, 0xa0, 0xfe, 0x03, 0x2a, 0x98, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xfe, 0x88,
+ 0xff, 0x02, 0x7f, 0xff, 0xcf, 0xfc, 0xf4, 0x00, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x1e, 0x33, 0xd0,
+ 0xaf, 0x7e, 0xf0, 0x02, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0xa6, 0x4d, 0x00, 0x00, 0x00, 0x01,
+ 0xad, 0x9a, 0xd8, 0x02, 0xfe, 0x6b, 0x18, 0x04, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0xfb, 0x18, 0x04,
+ 0xc0, 0x7e, 0xda, 0x00, 0xe6, 0x01, 0xa6, 0x55, 0xc0, 0x76, 0xe2, 0x00, 0x8f, 0x7a, 0x00, 0x08,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0xa6, 0x28, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xa6, 0x80,
+ 0xf3, 0x82, 0x00, 0x02, 0xe6, 0x01, 0xa6, 0x3c, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x01, 0xa3, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xa6, 0x80, 0xf3, 0x82, 0x00, 0x02, 0xff, 0x88, 0xa6, 0x60,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xa3, 0xb0, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x82, 0x00, 0x01,
+ 0xf7, 0x86, 0xa6, 0x8c, 0xe0, 0x01, 0x3c, 0xf8, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8c, 0x39, 0x18, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x7f, 0xfd, 0x00, 0x19,
+ 0x9f, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xff, 0x82, 0x00, 0x11, 0x9f, 0x82, 0xfe, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf0, 0x0d, 0x39, 0x18, 0xfe, 0x82, 0x00, 0x00,
+ 0xfe, 0x02, 0x00, 0x01, 0xcf, 0xf0, 0xef, 0xc0, 0xc0, 0x1a, 0xfc, 0x00, 0xe6, 0x01, 0xa7, 0x0c,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x39, 0x18, 0x0f, 0xfc, 0x07, 0x48, 0xfe, 0xff, 0x68, 0x00,
+ 0xff, 0x0c, 0x39, 0x18, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x39, 0x18, 0x0e, 0xf4, 0x00, 0x01,
+ 0x20, 0x76, 0x00, 0x0e, 0xee, 0x01, 0xa7, 0x2c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x39, 0x18,
+ 0x20, 0x7e, 0x00, 0x0e, 0xe2, 0x01, 0xa6, 0xe9, 0xcf, 0xf0, 0xef, 0xc0, 0xf7, 0x86, 0xa7, 0x38,
+ 0xe0, 0x01, 0xa6, 0x98, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x0c, 0x39, 0x18,
+ 0x4f, 0xa9, 0x1e, 0x00, 0x7d, 0xfc, 0xff, 0xe7, 0xc0, 0x6e, 0xf2, 0x00, 0xe4, 0x01, 0xa7, 0x81,
+ 0x0f, 0xec, 0x07, 0x48, 0xff, 0x7f, 0x58, 0x00, 0x0d, 0xec, 0x00, 0x01, 0xb0, 0x1a, 0xf0, 0x04,
+ 0xff, 0x8c, 0x39, 0x18, 0xc0, 0x6e, 0xfa, 0x00, 0xe4, 0x01, 0xa7, 0x64, 0x0f, 0xec, 0x07, 0x48,
+ 0xfd, 0x82, 0x00, 0x00, 0x7e, 0x6d, 0x00, 0x02, 0x8e, 0xf2, 0x07, 0x08, 0xaf, 0x1a, 0xd8, 0x05,
+ 0x7f, 0xf4, 0xff, 0xe8, 0x6f, 0xfc, 0x00, 0x01, 0xcf, 0x78, 0xfc, 0x00, 0xbf, 0x1e, 0xd8, 0x04,
+ 0xaf, 0x9a, 0xd8, 0x05, 0x7f, 0xfd, 0x00, 0x18, 0xce, 0xf4, 0xfd, 0x00, 0x0d, 0xec, 0x00, 0x01,
+ 0x20, 0x6e, 0x00, 0x0e, 0xe2, 0x01, 0xa7, 0x85, 0x9e, 0xf2, 0x07, 0x08, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x85, 0xae, 0x00, 0x2c, 0x05, 0x29, 0xff, 0xe0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xa7, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0x81, 0x1e, 0x00, 0xc0, 0x2a, 0xfc, 0x00, 0xe6, 0x20, 0x00, 0x02, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xa8, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08, 0x93, 0x16, 0xff, 0xf4,
+ 0x7f, 0x99, 0x00, 0x02, 0x8f, 0xfe, 0x07, 0x08, 0xc3, 0x7c, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xf0,
+ 0xf7, 0x86, 0xa8, 0xac, 0xe0, 0x01, 0x35, 0xcc, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0x8f, 0x16, 0xff, 0xf0, 0xf3, 0x82, 0x00, 0x00, 0xf7, 0x86, 0xa8, 0xc4, 0xc1, 0x78, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x72, 0x64, 0x6d, 0x61, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x25, 0x64, 0x0a,
+ 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10,
+ 0x22, 0x10, 0x00, 0x08, 0xff, 0x06, 0xa8, 0xd0, 0x93, 0x12, 0x00, 0x04, 0x9f, 0x12, 0x00, 0x00,
+ 0x93, 0x16, 0xff, 0xf4, 0xf7, 0x86, 0xa9, 0x10, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x16, 0xff, 0xf4, 0x02, 0x10, 0x00, 0x08, 0x7f, 0xf9, 0x00, 0x02, 0x8f, 0x7e, 0x07, 0x08,
+ 0x9f, 0x16, 0xff, 0xf0, 0xff, 0x06, 0xa8, 0x40, 0x9f, 0x7e, 0x07, 0x08, 0x83, 0x16, 0xff, 0xf0,
+ 0xf7, 0x86, 0xa9, 0x3c, 0xe0, 0x01, 0x35, 0xcc, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x0c, 0x39, 0x18,
+ 0x4f, 0xa9, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x2e, 0xf8, 0x00, 0x01, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xe6, 0x01, 0xa9, 0x61, 0x0f, 0x78, 0x07, 0x47, 0xff, 0x7b, 0x58, 0x00, 0x9f, 0x16, 0xff, 0xf4,
+ 0xfe, 0x8d, 0x39, 0x18, 0xf7, 0x86, 0xa9, 0x70, 0xe0, 0x01, 0xa6, 0x98, 0x97, 0x93, 0xff, 0xfc,
+ 0xff, 0x8e, 0x38, 0xe0, 0xf7, 0x82, 0x00, 0x01, 0xf7, 0xff, 0x68, 0x3e, 0xff, 0x8c, 0x39, 0x18,
+ 0x55, 0x28, 0x01, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xa9, 0x9c, 0xf3, 0x02, 0x00, 0x3f,
+ 0xf7, 0x86, 0xa9, 0x9c, 0xe0, 0x00, 0x7b, 0x5c, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0x8f, 0x96, 0xff, 0xf0, 0xf3, 0x82, 0x00, 0x00, 0xf7, 0x86, 0xa9, 0xb4, 0xc1, 0x7c, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x69, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0xf3, 0x7f, 0x68, 0x00, 0x2f, 0x7a, 0x00, 0x01, 0xe6, 0x01, 0xaa, 0x6c, 0xfe, 0x8e, 0x69, 0x40,
+ 0xfe, 0x8c, 0x69, 0x78, 0xff, 0x8c, 0x69, 0x64, 0xff, 0x0c, 0x38, 0xf8, 0x8e, 0x76, 0x00, 0x20,
+ 0x5f, 0xfd, 0x10, 0x00, 0x8d, 0xf6, 0x00, 0x30, 0xf0, 0x8d, 0x69, 0x60, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x00, 0x02, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x82, 0xfe, 0x30, 0x0f, 0x78, 0x00, 0x01,
+ 0xff, 0x0d, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xec, 0x00, 0x00, 0x4e, 0x73, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9e, 0x76, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xaa, 0x38, 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0xa9, 0xf0,
+ 0x9f, 0x76, 0x00, 0x20, 0x9f, 0xf6, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xaa, 0x78, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x69, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0x2f, 0x7a, 0x00, 0x01,
+ 0xe6, 0x01, 0xab, 0x64, 0xfe, 0x8e, 0x69, 0xc0, 0xfe, 0x8c, 0x69, 0xf8, 0xff, 0x8c, 0x69, 0xe4,
+ 0xff, 0x0c, 0x38, 0xf8, 0x8e, 0x76, 0x00, 0x20, 0x5f, 0xfd, 0x10, 0x00, 0x8d, 0xf6, 0x00, 0x30,
+ 0xf0, 0x8d, 0x69, 0xe0, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x05, 0xf2, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x82, 0xfe, 0x30, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00,
+ 0xc7, 0xec, 0x00, 0x00, 0x4e, 0x73, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9e, 0x76, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xab, 0x30,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0xaa, 0xe8, 0x9f, 0x76, 0x00, 0x20, 0x9f, 0xf6, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xab, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6a, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0xf3, 0x7f, 0x68, 0x00, 0x2f, 0x7a, 0x00, 0x01, 0xe6, 0x01, 0xac, 0x5c, 0xfe, 0x8e, 0x6a, 0x40,
+ 0xfe, 0x8c, 0x6a, 0x78, 0xff, 0x8c, 0x6a, 0x64, 0xff, 0x0c, 0x38, 0xf8, 0x8e, 0x76, 0x00, 0x20,
+ 0x5f, 0xfd, 0x10, 0x00, 0x8d, 0xf6, 0x00, 0x30, 0xf0, 0x8d, 0x6a, 0x60, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x0b, 0xe2, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x82, 0xfe, 0x30, 0x0f, 0x78, 0x00, 0x01,
+ 0xff, 0x0d, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xec, 0x00, 0x00, 0x4e, 0x73, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9e, 0x76, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xac, 0x28, 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0xab, 0xe0,
+ 0x9f, 0x76, 0x00, 0x20, 0x9f, 0xf6, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xac, 0x68, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6a, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0x2f, 0x7a, 0x00, 0x01,
+ 0xe6, 0x01, 0xad, 0x54, 0xfe, 0x8e, 0x6a, 0xc0, 0xfe, 0x8c, 0x6a, 0xf8, 0xff, 0x8c, 0x6a, 0xe4,
+ 0xff, 0x0c, 0x38, 0xf8, 0x8e, 0x76, 0x00, 0x20, 0x5f, 0xfd, 0x10, 0x00, 0x8d, 0xf6, 0x00, 0x30,
+ 0xf0, 0x8d, 0x6a, 0xe0, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x11, 0xd2, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x82, 0xfe, 0x30, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00,
+ 0xc7, 0xec, 0x00, 0x00, 0x4e, 0x73, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9e, 0x76, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xad, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0xac, 0xd8, 0x9f, 0x76, 0x00, 0x20, 0x9f, 0xf6, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xad, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6b, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0xf3, 0x7f, 0x68, 0x00, 0x2f, 0x7a, 0x00, 0x01, 0xe6, 0x01, 0xae, 0x4c, 0xfe, 0x8e, 0x6b, 0x40,
+ 0xfe, 0x8c, 0x6b, 0x78, 0xff, 0x8c, 0x6b, 0x64, 0xff, 0x0c, 0x38, 0xf8, 0x8e, 0x76, 0x00, 0x20,
+ 0x5f, 0xfd, 0x10, 0x00, 0x8d, 0xf6, 0x00, 0x30, 0xf0, 0x8d, 0x6b, 0x60, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x36, 0x8a, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x82, 0xfe, 0x30, 0x0f, 0x78, 0x00, 0x01,
+ 0xff, 0x0d, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xec, 0x00, 0x00, 0x4e, 0x73, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9e, 0x76, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xae, 0x18, 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0xad, 0xd0,
+ 0x9f, 0x76, 0x00, 0x20, 0x9f, 0xf6, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xae, 0x58, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6b, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0x2f, 0x7a, 0x00, 0x01,
+ 0xe6, 0x01, 0xaf, 0x44, 0xfe, 0x8e, 0x6b, 0xc0, 0xfe, 0x8c, 0x6b, 0xf8, 0xff, 0x8c, 0x6b, 0xe4,
+ 0xff, 0x0c, 0x38, 0xf8, 0x8e, 0x76, 0x00, 0x20, 0x5f, 0xfd, 0x10, 0x00, 0x8d, 0xf6, 0x00, 0x30,
+ 0xf0, 0x8d, 0x6b, 0xe0, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x5b, 0x42, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x82, 0xfe, 0x30, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00,
+ 0xc7, 0xec, 0x00, 0x00, 0x4e, 0x73, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9e, 0x76, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xaf, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x86, 0xae, 0xc8, 0x9f, 0x76, 0x00, 0x20, 0x9f, 0xf6, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xaf, 0x50,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x69, 0x68, 0xfe, 0x8c, 0x69, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xb0, 0xb4, 0xff, 0x0d, 0x69, 0x68, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x69, 0x6c,
+ 0x0b, 0xdc, 0x00, 0x02, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x69, 0x68, 0xfc, 0x8c, 0x69, 0x78,
+ 0xfd, 0x0c, 0x69, 0x64, 0xfa, 0x8c, 0x38, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xb0, 0x9d,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x69, 0x40,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x6d, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x38, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb0, 0x68, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x69, 0x80,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xb0, 0x24,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xaf, 0xc8, 0xff, 0x8d, 0x69, 0x70, 0xfe, 0x8d, 0x69, 0x60,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb0, 0xc0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x69, 0xe8, 0xfe, 0x8c, 0x69, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xb2, 0x24, 0xff, 0x0d, 0x69, 0xe8, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x69, 0xec,
+ 0x0b, 0xdc, 0x05, 0xf2, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x69, 0xe8, 0xfc, 0x8c, 0x69, 0xf8,
+ 0xfd, 0x0c, 0x69, 0xe4, 0xfa, 0x8c, 0x38, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xb2, 0x0d,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x69, 0xc0,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x6d, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x38, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb1, 0xd8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6a, 0x00,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xb1, 0x94,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xb1, 0x38, 0xff, 0x8d, 0x69, 0xf0, 0xfe, 0x8d, 0x69, 0xe0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb2, 0x30,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6a, 0x68, 0xfe, 0x8c, 0x6a, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xb3, 0x94, 0xff, 0x0d, 0x6a, 0x68, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x6a, 0x6c,
+ 0x0b, 0xdc, 0x0b, 0xe2, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x6a, 0x68, 0xfc, 0x8c, 0x6a, 0x78,
+ 0xfd, 0x0c, 0x6a, 0x64, 0xfa, 0x8c, 0x38, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xb3, 0x7d,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x6a, 0x40,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x6d, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x38, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb3, 0x48, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6a, 0x80,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xb3, 0x04,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xb2, 0xa8, 0xff, 0x8d, 0x6a, 0x70, 0xfe, 0x8d, 0x6a, 0x60,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb3, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6a, 0xe8, 0xfe, 0x8c, 0x6a, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xb5, 0x04, 0xff, 0x0d, 0x6a, 0xe8, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x6a, 0xec,
+ 0x0b, 0xdc, 0x11, 0xd2, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x6a, 0xe8, 0xfc, 0x8c, 0x6a, 0xf8,
+ 0xfd, 0x0c, 0x6a, 0xe4, 0xfa, 0x8c, 0x38, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xb4, 0xed,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x6a, 0xc0,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x6d, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x38, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb4, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6b, 0x00,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xb4, 0x74,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xb4, 0x18, 0xff, 0x8d, 0x6a, 0xf0, 0xfe, 0x8d, 0x6a, 0xe0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb5, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6b, 0x68, 0xfe, 0x8c, 0x6b, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xb6, 0x74, 0xff, 0x0d, 0x6b, 0x68, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x6b, 0x6c,
+ 0x0b, 0xdc, 0x36, 0x8a, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x6b, 0x68, 0xfc, 0x8c, 0x6b, 0x78,
+ 0xfd, 0x0c, 0x6b, 0x64, 0xfa, 0x8c, 0x38, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xb6, 0x5d,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x6b, 0x40,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x6d, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x38, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb6, 0x28, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6b, 0x80,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xb5, 0xe4,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xb5, 0x88, 0xff, 0x8d, 0x6b, 0x70, 0xfe, 0x8d, 0x6b, 0x60,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb6, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6b, 0xe8, 0xfe, 0x8c, 0x6b, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xb7, 0xe4, 0xff, 0x0d, 0x6b, 0xe8, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x6b, 0xec,
+ 0x0b, 0xdc, 0x5b, 0x42, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x6b, 0xe8, 0xfc, 0x8c, 0x6b, 0xf8,
+ 0xfd, 0x0c, 0x6b, 0xe4, 0xfa, 0x8c, 0x38, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xb7, 0xcd,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x6b, 0xc0,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x6d, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x38, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb7, 0x98, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6c, 0x00,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xb7, 0x54,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xb6, 0xf8, 0xff, 0x8d, 0x6b, 0xf0, 0xfe, 0x8d, 0x6b, 0xe0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb7, 0xf0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x69, 0x68, 0xfe, 0x8c, 0x69, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xb9, 0x58, 0xff, 0x0d, 0x69, 0x68, 0x0b, 0x81, 0x80, 0x01,
+ 0xfc, 0x0c, 0x69, 0x6c, 0x0b, 0xdc, 0x00, 0x02, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x69, 0x68,
+ 0xfc, 0x8c, 0x69, 0x78, 0xfd, 0x0c, 0x69, 0x64, 0xfa, 0x8c, 0x38, 0xf8, 0x8b, 0x66, 0x00, 0x20,
+ 0x7f, 0xf0, 0x00, 0x10, 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00,
+ 0x0d, 0xe0, 0x00, 0x02, 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff,
+ 0xe6, 0x01, 0xb9, 0x41, 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80,
+ 0xff, 0x8e, 0x69, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30,
+ 0xff, 0x8e, 0x6d, 0xa2, 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x38, 0xf8,
+ 0x9f, 0x82, 0xfe, 0x30, 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00,
+ 0x4b, 0x5b, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xb9, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x69, 0x80, 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02,
+ 0xe0, 0x01, 0xb8, 0xc8, 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xb8, 0x6c, 0xff, 0x8d, 0x69, 0x70,
+ 0xfe, 0x8d, 0x69, 0x60, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xb9, 0x64, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00,
+ 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x69, 0xe8, 0xfe, 0x8c, 0x69, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xf3, 0x7f, 0x68, 0x00,
+ 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xba, 0xcc, 0xff, 0x0d, 0x69, 0xe8,
+ 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x69, 0xec, 0x0b, 0xdc, 0x05, 0xf2, 0x9b, 0x82, 0xfe, 0x68,
+ 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68,
+ 0xfe, 0x0c, 0x69, 0xe8, 0xfc, 0x8c, 0x69, 0xf8, 0xfd, 0x0c, 0x69, 0xe4, 0xfa, 0x8c, 0x38, 0xf8,
+ 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10, 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02, 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00,
+ 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xba, 0xb5, 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30,
+ 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x69, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30,
+ 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x6d, 0xa2, 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00,
+ 0xff, 0x0d, 0x38, 0xf8, 0x9f, 0x82, 0xfe, 0x30, 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xba, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6a, 0x00, 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10,
+ 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xba, 0x3c, 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xb9, 0xe0,
+ 0xff, 0x8d, 0x69, 0xf0, 0xfe, 0x8d, 0x69, 0xe0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xba, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6a, 0x68, 0xfe, 0x8c, 0x6a, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08,
+ 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xbc, 0x40,
+ 0xff, 0x0d, 0x6a, 0x68, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x6a, 0x6c, 0x0b, 0xdc, 0x0b, 0xe2,
+ 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0,
+ 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x6a, 0x68, 0xfc, 0x8c, 0x6a, 0x78, 0xfd, 0x0c, 0x6a, 0x64,
+ 0xfa, 0x8c, 0x38, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10, 0xce, 0x7e, 0xe0, 0x00,
+ 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02, 0xcd, 0x68, 0xda, 0x00,
+ 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xbc, 0x29, 0x5d, 0xed, 0x10, 0x00,
+ 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x6a, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x6d, 0xa2, 0x0f, 0x54, 0x00, 0x01,
+ 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x38, 0xf8, 0x9f, 0x82, 0xfe, 0x30, 0x9d, 0x82, 0xfe, 0x30,
+ 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03,
+ 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xbb, 0xf4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6a, 0x80, 0xcf, 0xe0, 0xfa, 0x00,
+ 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xbb, 0xb0, 0xce, 0x70, 0xf2, 0x00,
+ 0xff, 0x86, 0xbb, 0x54, 0xff, 0x8d, 0x6a, 0x70, 0xfe, 0x8d, 0x6a, 0x60, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xbc, 0x4c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6a, 0xe8,
+ 0xfe, 0x8c, 0x6a, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0x73, 0x9d, 0x00, 0x08, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xbd, 0xb4, 0xff, 0x0d, 0x6a, 0xe8, 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x6a, 0xec,
+ 0x0b, 0xdc, 0x11, 0xd2, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x6a, 0xe8, 0xfc, 0x8c, 0x6a, 0xf8,
+ 0xfd, 0x0c, 0x6a, 0xe4, 0xfa, 0x8c, 0x38, 0xf8, 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10,
+ 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02,
+ 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xbd, 0x9d,
+ 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x6a, 0xc0,
+ 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x6d, 0xa2,
+ 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x38, 0xf8, 0x9f, 0x82, 0xfe, 0x30,
+ 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xbd, 0x68, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6b, 0x00,
+ 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xbd, 0x24,
+ 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xbc, 0xc8, 0xff, 0x8d, 0x6a, 0xf0, 0xfe, 0x8d, 0x6a, 0xe0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xbd, 0xc0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6b, 0x68, 0xfe, 0x8c, 0x6b, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xf3, 0x7f, 0x68, 0x00, 0xcf, 0x78, 0x38, 0x00,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xbf, 0x28, 0xff, 0x0d, 0x6b, 0x68, 0x0b, 0x81, 0x80, 0x01,
+ 0xfc, 0x0c, 0x6b, 0x6c, 0x0b, 0xdc, 0x36, 0x8a, 0x9b, 0x82, 0xfe, 0x68, 0x0f, 0xe0, 0x00, 0x09,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0xfe, 0x0c, 0x6b, 0x68,
+ 0xfc, 0x8c, 0x6b, 0x78, 0xfd, 0x0c, 0x6b, 0x64, 0xfa, 0x8c, 0x38, 0xf8, 0x8b, 0x66, 0x00, 0x20,
+ 0x7f, 0xf0, 0x00, 0x10, 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00,
+ 0x0d, 0xe0, 0x00, 0x02, 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00, 0x6e, 0x72, 0xff, 0xff,
+ 0xe6, 0x01, 0xbf, 0x11, 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30, 0x90, 0x82, 0xfe, 0x80,
+ 0xff, 0x8e, 0x6b, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30, 0x9d, 0x02, 0xfe, 0x30,
+ 0xff, 0x8e, 0x6d, 0xa2, 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00, 0xff, 0x0d, 0x38, 0xf8,
+ 0x9f, 0x82, 0xfe, 0x30, 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00, 0xc7, 0xf4, 0x00, 0x00,
+ 0x4b, 0x5b, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xbe, 0xdc, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x6b, 0x80, 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10, 0xe6, 0x78, 0x00, 0x02,
+ 0xe0, 0x01, 0xbe, 0x98, 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xbe, 0x3c, 0xff, 0x8d, 0x6b, 0x70,
+ 0xfe, 0x8d, 0x6b, 0x60, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xbf, 0x34, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00,
+ 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6b, 0xe8, 0xfe, 0x8c, 0x6b, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xf3, 0x7f, 0x68, 0x00,
+ 0xcf, 0x78, 0x38, 0x00, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xc0, 0x9c, 0xff, 0x0d, 0x6b, 0xe8,
+ 0x0b, 0x81, 0x80, 0x01, 0xfc, 0x0c, 0x6b, 0xec, 0x0b, 0xdc, 0x5b, 0x42, 0x9b, 0x82, 0xfe, 0x68,
+ 0x0f, 0xe0, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68,
+ 0xfe, 0x0c, 0x6b, 0xe8, 0xfc, 0x8c, 0x6b, 0xf8, 0xfd, 0x0c, 0x6b, 0xe4, 0xfa, 0x8c, 0x38, 0xf8,
+ 0x8b, 0x66, 0x00, 0x20, 0x7f, 0xf0, 0x00, 0x10, 0xce, 0x7e, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x0d, 0xe0, 0x00, 0x02, 0xcd, 0x68, 0xda, 0x00, 0xcb, 0xec, 0xb8, 0x00,
+ 0x6e, 0x72, 0xff, 0xff, 0xe6, 0x01, 0xc0, 0x85, 0x5d, 0xed, 0x10, 0x00, 0x8e, 0xe6, 0x00, 0x30,
+ 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8e, 0x6b, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x9b, 0x82, 0xfe, 0x30,
+ 0x9d, 0x02, 0xfe, 0x30, 0xff, 0x8e, 0x6d, 0xa2, 0x0f, 0x54, 0x00, 0x01, 0xbe, 0x62, 0xf8, 0x00,
+ 0xff, 0x0d, 0x38, 0xf8, 0x9f, 0x82, 0xfe, 0x30, 0x9d, 0x82, 0xfe, 0x30, 0x55, 0x28, 0x01, 0x00,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4b, 0x5b, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9b, 0x66, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc0, 0x50,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x6c, 0x00, 0xcf, 0xe0, 0xfa, 0x00, 0x20, 0x7e, 0x00, 0x10,
+ 0xe6, 0x78, 0x00, 0x02, 0xe0, 0x01, 0xc0, 0x0c, 0xce, 0x70, 0xf2, 0x00, 0xff, 0x86, 0xbf, 0xb0,
+ 0xff, 0x8d, 0x6b, 0xf0, 0xfe, 0x8d, 0x6b, 0xe0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc0, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x69, 0x68, 0xfe, 0x8c, 0x69, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x69, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xc3, 0x30,
+ 0xff, 0x0e, 0x69, 0x40, 0xfb, 0x0c, 0x69, 0x64, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x00, 0x02,
+ 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd8, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xae,
+ 0xff, 0x7f, 0x18, 0x00, 0xfa, 0x8c, 0x69, 0x6c, 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x7c, 0x00, 0x02,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xc2, 0x85, 0xff, 0xa5, 0x33, 0xe0, 0xfb, 0x8c, 0x69, 0x80,
+ 0xfe, 0x8e, 0x6d, 0xb4, 0xff, 0x77, 0x18, 0x00, 0xcf, 0xd4, 0xb0, 0x00, 0xce, 0x58, 0xba, 0x00,
+ 0xfd, 0x0e, 0x6d, 0xa2, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0xf7, 0x28, 0x00, 0xcc, 0xf0, 0xd0, 0x00,
+ 0xfd, 0xe7, 0x18, 0x0c, 0xcf, 0x78, 0xb2, 0x00, 0x0c, 0x78, 0x00, 0x36, 0x4f, 0xec, 0xff, 0xf6,
+ 0xff, 0xe7, 0x28, 0x0c, 0xfb, 0x0d, 0x71, 0xf8, 0xfd, 0x8d, 0x6d, 0x88, 0xfa, 0x8d, 0x72, 0x78,
+ 0xfc, 0x8d, 0x71, 0xe8, 0xad, 0xf2, 0xd0, 0x02, 0x6c, 0x60, 0xff, 0xff, 0x8e, 0xe6, 0x00, 0x08,
+ 0x8e, 0x66, 0x00, 0x04, 0x8f, 0x66, 0x00, 0x0c, 0x8f, 0xe6, 0x00, 0x10, 0xcc, 0x60, 0xa8, 0x00,
+ 0xcc, 0x6e, 0xc0, 0x00, 0xcc, 0x72, 0xc1, 0x00, 0xcc, 0x76, 0xc1, 0x00, 0xcc, 0x7a, 0xc1, 0x00,
+ 0xcc, 0x7e, 0xc1, 0x00, 0xcc, 0x00, 0xc1, 0x00, 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00,
+ 0xee, 0x01, 0xc2, 0x19, 0x0c, 0xe4, 0x00, 0x14, 0xff, 0xe7, 0x18, 0x00, 0xff, 0x67, 0x18, 0x02,
+ 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0x60, 0xf8, 0x00,
+ 0xee, 0x01, 0xc1, 0xf8, 0x0c, 0xe4, 0x00, 0x04, 0x7f, 0xe0, 0x00, 0x10, 0xcc, 0x7e, 0xc0, 0x00,
+ 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00, 0xfc, 0x09, 0xe8, 0xa0, 0xff, 0x0c, 0x69, 0x78,
+ 0xff, 0x8e, 0x69, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc2, 0x50,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x8e, 0x6d, 0xb2, 0xff, 0x6f, 0x18, 0x00, 0xfd, 0x0e, 0x6d, 0xba,
+ 0xfe, 0xeb, 0x18, 0x00, 0xfc, 0x8e, 0x6d, 0xb0, 0xfe, 0x67, 0x58, 0x00, 0x4f, 0xd9, 0xdf, 0xff,
+ 0xcf, 0xfc, 0xa8, 0x00, 0xcf, 0x04, 0xf6, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0xce, 0x84, 0xee, 0x00,
+ 0x4f, 0x79, 0x00, 0x00, 0xff, 0xef, 0x28, 0x00, 0x4c, 0x75, 0x00, 0x00, 0xcf, 0x78, 0xf8, 0x00,
+ 0x4e, 0x70, 0x00, 0x0f, 0x7e, 0x71, 0x00, 0x02, 0xfa, 0x8d, 0x72, 0x78, 0xcf, 0xe0, 0xf0, 0x00,
+ 0x7d, 0xfc, 0x00, 0x10, 0xcc, 0x6e, 0xf8, 0x00, 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00,
+ 0xce, 0x84, 0xc6, 0x00, 0xfe, 0xeb, 0x28, 0x00, 0xcc, 0xf0, 0xc8, 0x00, 0xfd, 0xe7, 0x18, 0x0c,
+ 0xfc, 0x0c, 0x69, 0x68, 0x4e, 0xec, 0x00, 0x09, 0x6e, 0xf4, 0xff, 0xff, 0xfb, 0x0d, 0x71, 0xf8,
+ 0xfc, 0x8d, 0x71, 0xe8, 0xfd, 0x8d, 0x6d, 0x88, 0xcf, 0x78, 0xe8, 0x00, 0x4f, 0xec, 0xff, 0xf6,
+ 0xff, 0xe7, 0x28, 0x0c, 0xcf, 0x60, 0xf0, 0x00, 0x7f, 0xf8, 0x00, 0x10, 0xcf, 0x7e, 0xf0, 0x00,
+ 0x7f, 0x78, 0xff, 0xf0, 0xcf, 0x00, 0xf1, 0x00, 0xe0, 0x01, 0xc2, 0x2c, 0xff, 0x09, 0xe8, 0xa0,
+ 0xff, 0x86, 0xc1, 0x24, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc3, 0x3c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x69, 0xe8,
+ 0xfe, 0x8c, 0x69, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x69, 0xe8, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xc5, 0xc4, 0xff, 0x0e, 0x69, 0xc0, 0xfb, 0x0c, 0x69, 0xe4, 0x0f, 0x81, 0x80, 0x01,
+ 0x0f, 0xfc, 0x05, 0xf2, 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd8, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8e, 0x6d, 0xae, 0xff, 0x7f, 0x18, 0x00, 0xfa, 0x8c, 0x69, 0xec, 0x20, 0x7a, 0x08, 0x00,
+ 0xe6, 0x7c, 0x00, 0x02, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xc5, 0x19, 0xff, 0xa5, 0x33, 0xe0,
+ 0xfb, 0x8c, 0x6a, 0x00, 0xfe, 0x8e, 0x6d, 0xb4, 0xff, 0x77, 0x18, 0x00, 0xcf, 0xd4, 0xb0, 0x00,
+ 0xce, 0x58, 0xba, 0x00, 0xfd, 0x0e, 0x6d, 0xa2, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0xf7, 0x28, 0x00,
+ 0xcc, 0xf0, 0xd0, 0x00, 0xfd, 0xe7, 0x18, 0x0c, 0xcf, 0x78, 0xb2, 0x00, 0x0c, 0x78, 0x00, 0x36,
+ 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c, 0xfb, 0x0d, 0x71, 0xf8, 0xfd, 0x8d, 0x6d, 0x88,
+ 0xfa, 0x8d, 0x72, 0x78, 0xfc, 0x8d, 0x71, 0xe8, 0xad, 0xf2, 0xd0, 0x02, 0x6c, 0x60, 0xff, 0xff,
+ 0x8e, 0xe6, 0x00, 0x08, 0x8e, 0x66, 0x00, 0x04, 0x8f, 0x66, 0x00, 0x0c, 0x8f, 0xe6, 0x00, 0x10,
+ 0xcc, 0x60, 0xa8, 0x00, 0xcc, 0x6e, 0xc0, 0x00, 0xcc, 0x72, 0xc1, 0x00, 0xcc, 0x76, 0xc1, 0x00,
+ 0xcc, 0x7a, 0xc1, 0x00, 0xcc, 0x7e, 0xc1, 0x00, 0xcc, 0x00, 0xc1, 0x00, 0x2b, 0xdc, 0x00, 0x14,
+ 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xc4, 0xad, 0x0c, 0xe4, 0x00, 0x14, 0xff, 0xe7, 0x18, 0x00,
+ 0xff, 0x67, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xcc, 0x60, 0xf8, 0x00, 0xee, 0x01, 0xc4, 0x8c, 0x0c, 0xe4, 0x00, 0x04, 0x7f, 0xe0, 0x00, 0x10,
+ 0xcc, 0x7e, 0xc0, 0x00, 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00, 0xfc, 0x09, 0xe8, 0xa0,
+ 0xff, 0x0c, 0x69, 0xf8, 0xff, 0x8e, 0x69, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30,
+ 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03,
+ 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xc4, 0xe4, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x8e, 0x6d, 0xb2, 0xff, 0x6f, 0x18, 0x00,
+ 0xfd, 0x0e, 0x6d, 0xba, 0xfe, 0xeb, 0x18, 0x00, 0xfc, 0x8e, 0x6d, 0xb0, 0xfe, 0x67, 0x58, 0x00,
+ 0x4f, 0xd9, 0xdf, 0xff, 0xcf, 0xfc, 0xa8, 0x00, 0xcf, 0x04, 0xf6, 0x00, 0x2f, 0xfc, 0x00, 0x0e,
+ 0xce, 0x84, 0xee, 0x00, 0x4f, 0x79, 0x00, 0x00, 0xff, 0xef, 0x28, 0x00, 0x4c, 0x75, 0x00, 0x00,
+ 0xcf, 0x78, 0xf8, 0x00, 0x4e, 0x70, 0x00, 0x0f, 0x7e, 0x71, 0x00, 0x02, 0xfa, 0x8d, 0x72, 0x78,
+ 0xcf, 0xe0, 0xf0, 0x00, 0x7d, 0xfc, 0x00, 0x10, 0xcc, 0x6e, 0xf8, 0x00, 0x7c, 0x60, 0xff, 0xf0,
+ 0xcc, 0x00, 0xc1, 0x00, 0xce, 0x84, 0xc6, 0x00, 0xfe, 0xeb, 0x28, 0x00, 0xcc, 0xf0, 0xc8, 0x00,
+ 0xfd, 0xe7, 0x18, 0x0c, 0xfc, 0x0c, 0x69, 0xe8, 0x4e, 0xec, 0x00, 0x09, 0x6e, 0xf4, 0xff, 0xff,
+ 0xfb, 0x0d, 0x71, 0xf8, 0xfc, 0x8d, 0x71, 0xe8, 0xfd, 0x8d, 0x6d, 0x88, 0xcf, 0x78, 0xe8, 0x00,
+ 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c, 0xcf, 0x60, 0xf0, 0x00, 0x7f, 0xf8, 0x00, 0x10,
+ 0xcf, 0x7e, 0xf0, 0x00, 0x7f, 0x78, 0xff, 0xf0, 0xcf, 0x00, 0xf1, 0x00, 0xe0, 0x01, 0xc4, 0xc0,
+ 0xff, 0x09, 0xe8, 0xa0, 0xff, 0x86, 0xc3, 0xb8, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc5, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6a, 0x68, 0xfe, 0x8c, 0x6a, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6a, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xc8, 0x58, 0xff, 0x0e, 0x6a, 0x40, 0xfb, 0x0c, 0x6a, 0x64,
+ 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x0b, 0xe2, 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd8, 0x00, 0x09,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xae, 0xff, 0x7f, 0x18, 0x00, 0xfa, 0x8c, 0x6a, 0x6c,
+ 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x7c, 0x00, 0x02, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xc7, 0xad,
+ 0xff, 0xa5, 0x33, 0xe0, 0xfb, 0x8c, 0x6a, 0x80, 0xfe, 0x8e, 0x6d, 0xb4, 0xff, 0x77, 0x18, 0x00,
+ 0xcf, 0xd4, 0xb0, 0x00, 0xce, 0x58, 0xba, 0x00, 0xfd, 0x0e, 0x6d, 0xa2, 0x2f, 0xfc, 0x00, 0x36,
+ 0xff, 0xf7, 0x28, 0x00, 0xcc, 0xf0, 0xd0, 0x00, 0xfd, 0xe7, 0x18, 0x0c, 0xcf, 0x78, 0xb2, 0x00,
+ 0x0c, 0x78, 0x00, 0x36, 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c, 0xfb, 0x0d, 0x71, 0xf8,
+ 0xfd, 0x8d, 0x6d, 0x88, 0xfa, 0x8d, 0x72, 0x78, 0xfc, 0x8d, 0x71, 0xe8, 0xad, 0xf2, 0xd0, 0x02,
+ 0x6c, 0x60, 0xff, 0xff, 0x8e, 0xe6, 0x00, 0x08, 0x8e, 0x66, 0x00, 0x04, 0x8f, 0x66, 0x00, 0x0c,
+ 0x8f, 0xe6, 0x00, 0x10, 0xcc, 0x60, 0xa8, 0x00, 0xcc, 0x6e, 0xc0, 0x00, 0xcc, 0x72, 0xc1, 0x00,
+ 0xcc, 0x76, 0xc1, 0x00, 0xcc, 0x7a, 0xc1, 0x00, 0xcc, 0x7e, 0xc1, 0x00, 0xcc, 0x00, 0xc1, 0x00,
+ 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xc7, 0x41, 0x0c, 0xe4, 0x00, 0x14,
+ 0xff, 0xe7, 0x18, 0x00, 0xff, 0x67, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00,
+ 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0x60, 0xf8, 0x00, 0xee, 0x01, 0xc7, 0x20, 0x0c, 0xe4, 0x00, 0x04,
+ 0x7f, 0xe0, 0x00, 0x10, 0xcc, 0x7e, 0xc0, 0x00, 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00,
+ 0xfc, 0x09, 0xe8, 0xa0, 0xff, 0x0c, 0x6a, 0x78, 0xff, 0x8e, 0x6a, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xc7, 0x78, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x8e, 0x6d, 0xb2,
+ 0xff, 0x6f, 0x18, 0x00, 0xfd, 0x0e, 0x6d, 0xba, 0xfe, 0xeb, 0x18, 0x00, 0xfc, 0x8e, 0x6d, 0xb0,
+ 0xfe, 0x67, 0x58, 0x00, 0x4f, 0xd9, 0xdf, 0xff, 0xcf, 0xfc, 0xa8, 0x00, 0xcf, 0x04, 0xf6, 0x00,
+ 0x2f, 0xfc, 0x00, 0x0e, 0xce, 0x84, 0xee, 0x00, 0x4f, 0x79, 0x00, 0x00, 0xff, 0xef, 0x28, 0x00,
+ 0x4c, 0x75, 0x00, 0x00, 0xcf, 0x78, 0xf8, 0x00, 0x4e, 0x70, 0x00, 0x0f, 0x7e, 0x71, 0x00, 0x02,
+ 0xfa, 0x8d, 0x72, 0x78, 0xcf, 0xe0, 0xf0, 0x00, 0x7d, 0xfc, 0x00, 0x10, 0xcc, 0x6e, 0xf8, 0x00,
+ 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00, 0xce, 0x84, 0xc6, 0x00, 0xfe, 0xeb, 0x28, 0x00,
+ 0xcc, 0xf0, 0xc8, 0x00, 0xfd, 0xe7, 0x18, 0x0c, 0xfc, 0x0c, 0x6a, 0x68, 0x4e, 0xec, 0x00, 0x09,
+ 0x6e, 0xf4, 0xff, 0xff, 0xfb, 0x0d, 0x71, 0xf8, 0xfc, 0x8d, 0x71, 0xe8, 0xfd, 0x8d, 0x6d, 0x88,
+ 0xcf, 0x78, 0xe8, 0x00, 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c, 0xcf, 0x60, 0xf0, 0x00,
+ 0x7f, 0xf8, 0x00, 0x10, 0xcf, 0x7e, 0xf0, 0x00, 0x7f, 0x78, 0xff, 0xf0, 0xcf, 0x00, 0xf1, 0x00,
+ 0xe0, 0x01, 0xc7, 0x54, 0xff, 0x09, 0xe8, 0xa0, 0xff, 0x86, 0xc6, 0x4c, 0x9e, 0xfa, 0x00, 0x20,
+ 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xc8, 0x64, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00,
+ 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6a, 0xe8, 0xfe, 0x8c, 0x6a, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00,
+ 0xff, 0x0d, 0x6a, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xca, 0xec, 0xff, 0x0e, 0x6a, 0xc0,
+ 0xfb, 0x0c, 0x6a, 0xe4, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x11, 0xd2, 0x9f, 0x82, 0xfe, 0x68,
+ 0x0f, 0xd8, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xae, 0xff, 0x7f, 0x18, 0x00,
+ 0xfa, 0x8c, 0x6a, 0xec, 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x7c, 0x00, 0x02, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x01, 0xca, 0x41, 0xff, 0xa5, 0x33, 0xe0, 0xfb, 0x8c, 0x6b, 0x00, 0xfe, 0x8e, 0x6d, 0xb4,
+ 0xff, 0x77, 0x18, 0x00, 0xcf, 0xd4, 0xb0, 0x00, 0xce, 0x58, 0xba, 0x00, 0xfd, 0x0e, 0x6d, 0xa2,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0xf7, 0x28, 0x00, 0xcc, 0xf0, 0xd0, 0x00, 0xfd, 0xe7, 0x18, 0x0c,
+ 0xcf, 0x78, 0xb2, 0x00, 0x0c, 0x78, 0x00, 0x36, 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c,
+ 0xfb, 0x0d, 0x71, 0xf8, 0xfd, 0x8d, 0x6d, 0x88, 0xfa, 0x8d, 0x72, 0x78, 0xfc, 0x8d, 0x71, 0xe8,
+ 0xad, 0xf2, 0xd0, 0x02, 0x6c, 0x60, 0xff, 0xff, 0x8e, 0xe6, 0x00, 0x08, 0x8e, 0x66, 0x00, 0x04,
+ 0x8f, 0x66, 0x00, 0x0c, 0x8f, 0xe6, 0x00, 0x10, 0xcc, 0x60, 0xa8, 0x00, 0xcc, 0x6e, 0xc0, 0x00,
+ 0xcc, 0x72, 0xc1, 0x00, 0xcc, 0x76, 0xc1, 0x00, 0xcc, 0x7a, 0xc1, 0x00, 0xcc, 0x7e, 0xc1, 0x00,
+ 0xcc, 0x00, 0xc1, 0x00, 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xc9, 0xd5,
+ 0x0c, 0xe4, 0x00, 0x14, 0xff, 0xe7, 0x18, 0x00, 0xff, 0x67, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04,
+ 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0x60, 0xf8, 0x00, 0xee, 0x01, 0xc9, 0xb4,
+ 0x0c, 0xe4, 0x00, 0x04, 0x7f, 0xe0, 0x00, 0x10, 0xcc, 0x7e, 0xc0, 0x00, 0x7c, 0x60, 0xff, 0xf0,
+ 0xcc, 0x00, 0xc1, 0x00, 0xfc, 0x09, 0xe8, 0xa0, 0xff, 0x0c, 0x6a, 0xf8, 0xff, 0x8e, 0x6a, 0xc0,
+ 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00,
+ 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xca, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x8e, 0x6d, 0xb2, 0xff, 0x6f, 0x18, 0x00, 0xfd, 0x0e, 0x6d, 0xba, 0xfe, 0xeb, 0x18, 0x00,
+ 0xfc, 0x8e, 0x6d, 0xb0, 0xfe, 0x67, 0x58, 0x00, 0x4f, 0xd9, 0xdf, 0xff, 0xcf, 0xfc, 0xa8, 0x00,
+ 0xcf, 0x04, 0xf6, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0xce, 0x84, 0xee, 0x00, 0x4f, 0x79, 0x00, 0x00,
+ 0xff, 0xef, 0x28, 0x00, 0x4c, 0x75, 0x00, 0x00, 0xcf, 0x78, 0xf8, 0x00, 0x4e, 0x70, 0x00, 0x0f,
+ 0x7e, 0x71, 0x00, 0x02, 0xfa, 0x8d, 0x72, 0x78, 0xcf, 0xe0, 0xf0, 0x00, 0x7d, 0xfc, 0x00, 0x10,
+ 0xcc, 0x6e, 0xf8, 0x00, 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00, 0xce, 0x84, 0xc6, 0x00,
+ 0xfe, 0xeb, 0x28, 0x00, 0xcc, 0xf0, 0xc8, 0x00, 0xfd, 0xe7, 0x18, 0x0c, 0xfc, 0x0c, 0x6a, 0xe8,
+ 0x4e, 0xec, 0x00, 0x09, 0x6e, 0xf4, 0xff, 0xff, 0xfb, 0x0d, 0x71, 0xf8, 0xfc, 0x8d, 0x71, 0xe8,
+ 0xfd, 0x8d, 0x6d, 0x88, 0xcf, 0x78, 0xe8, 0x00, 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c,
+ 0xcf, 0x60, 0xf0, 0x00, 0x7f, 0xf8, 0x00, 0x10, 0xcf, 0x7e, 0xf0, 0x00, 0x7f, 0x78, 0xff, 0xf0,
+ 0xcf, 0x00, 0xf1, 0x00, 0xe0, 0x01, 0xc9, 0xe8, 0xff, 0x09, 0xe8, 0xa0, 0xff, 0x86, 0xc8, 0xe0,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xca, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6b, 0x68, 0xfe, 0x8c, 0x6b, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6b, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xcd, 0x80,
+ 0xff, 0x0e, 0x6b, 0x40, 0xfb, 0x0c, 0x6b, 0x64, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x36, 0x8a,
+ 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd8, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xae,
+ 0xff, 0x7f, 0x18, 0x00, 0xfa, 0x8c, 0x6b, 0x6c, 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x7c, 0x00, 0x02,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xcc, 0xd5, 0xff, 0xa5, 0x33, 0xe0, 0xfb, 0x8c, 0x6b, 0x80,
+ 0xfe, 0x8e, 0x6d, 0xb4, 0xff, 0x77, 0x18, 0x00, 0xcf, 0xd4, 0xb0, 0x00, 0xce, 0x58, 0xba, 0x00,
+ 0xfd, 0x0e, 0x6d, 0xa2, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0xf7, 0x28, 0x00, 0xcc, 0xf0, 0xd0, 0x00,
+ 0xfd, 0xe7, 0x18, 0x0c, 0xcf, 0x78, 0xb2, 0x00, 0x0c, 0x78, 0x00, 0x36, 0x4f, 0xec, 0xff, 0xf6,
+ 0xff, 0xe7, 0x28, 0x0c, 0xfb, 0x0d, 0x71, 0xf8, 0xfd, 0x8d, 0x6d, 0x88, 0xfa, 0x8d, 0x72, 0x78,
+ 0xfc, 0x8d, 0x71, 0xe8, 0xad, 0xf2, 0xd0, 0x02, 0x6c, 0x60, 0xff, 0xff, 0x8e, 0xe6, 0x00, 0x08,
+ 0x8e, 0x66, 0x00, 0x04, 0x8f, 0x66, 0x00, 0x0c, 0x8f, 0xe6, 0x00, 0x10, 0xcc, 0x60, 0xa8, 0x00,
+ 0xcc, 0x6e, 0xc0, 0x00, 0xcc, 0x72, 0xc1, 0x00, 0xcc, 0x76, 0xc1, 0x00, 0xcc, 0x7a, 0xc1, 0x00,
+ 0xcc, 0x7e, 0xc1, 0x00, 0xcc, 0x00, 0xc1, 0x00, 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00,
+ 0xee, 0x01, 0xcc, 0x69, 0x0c, 0xe4, 0x00, 0x14, 0xff, 0xe7, 0x18, 0x00, 0xff, 0x67, 0x18, 0x02,
+ 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0x60, 0xf8, 0x00,
+ 0xee, 0x01, 0xcc, 0x48, 0x0c, 0xe4, 0x00, 0x04, 0x7f, 0xe0, 0x00, 0x10, 0xcc, 0x7e, 0xc0, 0x00,
+ 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00, 0xfc, 0x09, 0xe8, 0xa0, 0xff, 0x0c, 0x6b, 0x78,
+ 0xff, 0x8e, 0x6b, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xcc, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x8e, 0x6d, 0xb2, 0xff, 0x6f, 0x18, 0x00, 0xfd, 0x0e, 0x6d, 0xba,
+ 0xfe, 0xeb, 0x18, 0x00, 0xfc, 0x8e, 0x6d, 0xb0, 0xfe, 0x67, 0x58, 0x00, 0x4f, 0xd9, 0xdf, 0xff,
+ 0xcf, 0xfc, 0xa8, 0x00, 0xcf, 0x04, 0xf6, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0xce, 0x84, 0xee, 0x00,
+ 0x4f, 0x79, 0x00, 0x00, 0xff, 0xef, 0x28, 0x00, 0x4c, 0x75, 0x00, 0x00, 0xcf, 0x78, 0xf8, 0x00,
+ 0x4e, 0x70, 0x00, 0x0f, 0x7e, 0x71, 0x00, 0x02, 0xfa, 0x8d, 0x72, 0x78, 0xcf, 0xe0, 0xf0, 0x00,
+ 0x7d, 0xfc, 0x00, 0x10, 0xcc, 0x6e, 0xf8, 0x00, 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00,
+ 0xce, 0x84, 0xc6, 0x00, 0xfe, 0xeb, 0x28, 0x00, 0xcc, 0xf0, 0xc8, 0x00, 0xfd, 0xe7, 0x18, 0x0c,
+ 0xfc, 0x0c, 0x6b, 0x68, 0x4e, 0xec, 0x00, 0x09, 0x6e, 0xf4, 0xff, 0xff, 0xfb, 0x0d, 0x71, 0xf8,
+ 0xfc, 0x8d, 0x71, 0xe8, 0xfd, 0x8d, 0x6d, 0x88, 0xcf, 0x78, 0xe8, 0x00, 0x4f, 0xec, 0xff, 0xf6,
+ 0xff, 0xe7, 0x28, 0x0c, 0xcf, 0x60, 0xf0, 0x00, 0x7f, 0xf8, 0x00, 0x10, 0xcf, 0x7e, 0xf0, 0x00,
+ 0x7f, 0x78, 0xff, 0xf0, 0xcf, 0x00, 0xf1, 0x00, 0xe0, 0x01, 0xcc, 0x7c, 0xff, 0x09, 0xe8, 0xa0,
+ 0xff, 0x86, 0xcb, 0x74, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xcd, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6b, 0xe8,
+ 0xfe, 0x8c, 0x6b, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6b, 0xe8, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xd0, 0x14, 0xff, 0x0e, 0x6b, 0xc0, 0xfb, 0x0c, 0x6b, 0xe4, 0x0f, 0x81, 0x80, 0x01,
+ 0x0f, 0xfc, 0x5b, 0x42, 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd8, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8e, 0x6d, 0xae, 0xff, 0x7f, 0x18, 0x00, 0xfa, 0x8c, 0x6b, 0xec, 0x20, 0x7a, 0x08, 0x00,
+ 0xe6, 0x7c, 0x00, 0x02, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x01, 0xcf, 0x69, 0xff, 0xa5, 0x33, 0xe0,
+ 0xfb, 0x8c, 0x6c, 0x00, 0xfe, 0x8e, 0x6d, 0xb4, 0xff, 0x77, 0x18, 0x00, 0xcf, 0xd4, 0xb0, 0x00,
+ 0xce, 0x58, 0xba, 0x00, 0xfd, 0x0e, 0x6d, 0xa2, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0xf7, 0x28, 0x00,
+ 0xcc, 0xf0, 0xd0, 0x00, 0xfd, 0xe7, 0x18, 0x0c, 0xcf, 0x78, 0xb2, 0x00, 0x0c, 0x78, 0x00, 0x36,
+ 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c, 0xfb, 0x0d, 0x71, 0xf8, 0xfd, 0x8d, 0x6d, 0x88,
+ 0xfa, 0x8d, 0x72, 0x78, 0xfc, 0x8d, 0x71, 0xe8, 0xad, 0xf2, 0xd0, 0x02, 0x6c, 0x60, 0xff, 0xff,
+ 0x8e, 0xe6, 0x00, 0x08, 0x8e, 0x66, 0x00, 0x04, 0x8f, 0x66, 0x00, 0x0c, 0x8f, 0xe6, 0x00, 0x10,
+ 0xcc, 0x60, 0xa8, 0x00, 0xcc, 0x6e, 0xc0, 0x00, 0xcc, 0x72, 0xc1, 0x00, 0xcc, 0x76, 0xc1, 0x00,
+ 0xcc, 0x7a, 0xc1, 0x00, 0xcc, 0x7e, 0xc1, 0x00, 0xcc, 0x00, 0xc1, 0x00, 0x2b, 0xdc, 0x00, 0x14,
+ 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xce, 0xfd, 0x0c, 0xe4, 0x00, 0x14, 0xff, 0xe7, 0x18, 0x00,
+ 0xff, 0x67, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xcc, 0x60, 0xf8, 0x00, 0xee, 0x01, 0xce, 0xdc, 0x0c, 0xe4, 0x00, 0x04, 0x7f, 0xe0, 0x00, 0x10,
+ 0xcc, 0x7e, 0xc0, 0x00, 0x7c, 0x60, 0xff, 0xf0, 0xcc, 0x00, 0xc1, 0x00, 0xfc, 0x09, 0xe8, 0xa0,
+ 0xff, 0x0c, 0x6b, 0xf8, 0xff, 0x8e, 0x6b, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30,
+ 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03,
+ 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xcf, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x8e, 0x6d, 0xb2, 0xff, 0x6f, 0x18, 0x00,
+ 0xfd, 0x0e, 0x6d, 0xba, 0xfe, 0xeb, 0x18, 0x00, 0xfc, 0x8e, 0x6d, 0xb0, 0xfe, 0x67, 0x58, 0x00,
+ 0x4f, 0xd9, 0xdf, 0xff, 0xcf, 0xfc, 0xa8, 0x00, 0xcf, 0x04, 0xf6, 0x00, 0x2f, 0xfc, 0x00, 0x0e,
+ 0xce, 0x84, 0xee, 0x00, 0x4f, 0x79, 0x00, 0x00, 0xff, 0xef, 0x28, 0x00, 0x4c, 0x75, 0x00, 0x00,
+ 0xcf, 0x78, 0xf8, 0x00, 0x4e, 0x70, 0x00, 0x0f, 0x7e, 0x71, 0x00, 0x02, 0xfa, 0x8d, 0x72, 0x78,
+ 0xcf, 0xe0, 0xf0, 0x00, 0x7d, 0xfc, 0x00, 0x10, 0xcc, 0x6e, 0xf8, 0x00, 0x7c, 0x60, 0xff, 0xf0,
+ 0xcc, 0x00, 0xc1, 0x00, 0xce, 0x84, 0xc6, 0x00, 0xfe, 0xeb, 0x28, 0x00, 0xcc, 0xf0, 0xc8, 0x00,
+ 0xfd, 0xe7, 0x18, 0x0c, 0xfc, 0x0c, 0x6b, 0xe8, 0x4e, 0xec, 0x00, 0x09, 0x6e, 0xf4, 0xff, 0xff,
+ 0xfb, 0x0d, 0x71, 0xf8, 0xfc, 0x8d, 0x71, 0xe8, 0xfd, 0x8d, 0x6d, 0x88, 0xcf, 0x78, 0xe8, 0x00,
+ 0x4f, 0xec, 0xff, 0xf6, 0xff, 0xe7, 0x28, 0x0c, 0xcf, 0x60, 0xf0, 0x00, 0x7f, 0xf8, 0x00, 0x10,
+ 0xcf, 0x7e, 0xf0, 0x00, 0x7f, 0x78, 0xff, 0xf0, 0xcf, 0x00, 0xf1, 0x00, 0xe0, 0x01, 0xcf, 0x10,
+ 0xff, 0x09, 0xe8, 0xa0, 0xff, 0x86, 0xce, 0x08, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd0, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x69, 0x68, 0xfe, 0x8c, 0x69, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x69, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xd2, 0xcc, 0xff, 0x0e, 0x69, 0x40, 0xfa, 0x8c, 0x69, 0x64,
+ 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x00, 0x02, 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd4, 0x00, 0x09,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xae, 0xff, 0x7f, 0x18, 0x00, 0xfb, 0x0c, 0x69, 0x6c,
+ 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x60, 0x00, 0x02, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xd1, 0xed,
+ 0xfc, 0x25, 0x33, 0xe0, 0xfb, 0x8c, 0x69, 0x80, 0xcf, 0x58, 0xa8, 0x00, 0xfd, 0x0e, 0x6d, 0xa2,
+ 0xce, 0xd4, 0xba, 0x00, 0x2f, 0x78, 0x00, 0x36, 0xff, 0x8e, 0x6d, 0xb4, 0xff, 0x7f, 0x28, 0x00,
+ 0xcc, 0x74, 0xd0, 0x00, 0xff, 0x63, 0x18, 0x0c, 0xcc, 0xdc, 0xb0, 0x00, 0x4f, 0xf8, 0xff, 0xf6,
+ 0xff, 0xe3, 0x28, 0x0c, 0xfa, 0x8d, 0x71, 0xf8, 0xff, 0x0d, 0x6d, 0x88, 0xfb, 0x0d, 0x72, 0x78,
+ 0xfc, 0x0d, 0x71, 0xe8, 0xad, 0xf6, 0xd0, 0x02, 0x8e, 0x62, 0x00, 0x04, 0x8f, 0x62, 0x00, 0x0c,
+ 0x8e, 0xe2, 0x00, 0x08, 0x8f, 0xe2, 0x00, 0x10, 0xcc, 0xee, 0xc8, 0x00, 0xcc, 0xf2, 0xc9, 0x00,
+ 0xcc, 0xf6, 0xc9, 0x00, 0xcc, 0xfa, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00,
+ 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xd1, 0x81, 0x0c, 0x60, 0x00, 0x14,
+ 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00,
+ 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00, 0xee, 0x01, 0xd1, 0x60, 0x0c, 0x60, 0x00, 0x04,
+ 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00,
+ 0xfc, 0x89, 0xe8, 0xa0, 0xff, 0x0c, 0x69, 0x78, 0xff, 0x8e, 0x69, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd1, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xb0,
+ 0xfe, 0xff, 0x58, 0x00, 0x4f, 0x55, 0xdf, 0xff, 0xcf, 0x78, 0xb0, 0x00, 0x2f, 0x78, 0x00, 0x0e,
+ 0xff, 0x8e, 0x6d, 0xb2, 0xff, 0x7f, 0x28, 0x00, 0x4e, 0xf4, 0x00, 0x0f, 0xfc, 0x8c, 0x6d, 0xb0,
+ 0xfd, 0x0c, 0x6d, 0xb4, 0xfd, 0x8c, 0x6d, 0xb8, 0xfe, 0x0c, 0x6d, 0xbc, 0xff, 0x8c, 0x6d, 0xc0,
+ 0x7e, 0xf5, 0x00, 0x02, 0xfb, 0x0d, 0x72, 0x78, 0xcb, 0xf8, 0xea, 0x00, 0xcc, 0xe6, 0xc0, 0x00,
+ 0xcc, 0xea, 0xc9, 0x00, 0xcc, 0xee, 0xc9, 0x00, 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00,
+ 0xcc, 0x80, 0xc9, 0x00, 0x2e, 0xf6, 0x00, 0x14, 0xe6, 0x01, 0xd2, 0x6d, 0xfc, 0x0e, 0x6d, 0xc4,
+ 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02, 0x2e, 0xf6, 0x00, 0x04, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xcc, 0xe4, 0xf8, 0x00, 0xe6, 0x01, 0xd2, 0x50, 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10,
+ 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00, 0xff, 0x8e, 0x6d, 0xba,
+ 0xcf, 0x04, 0xce, 0x00, 0xff, 0x7f, 0x28, 0x00, 0xff, 0x63, 0x18, 0x0c, 0xfc, 0x8c, 0x69, 0x68,
+ 0x4f, 0xf8, 0x00, 0x09, 0xff, 0x0d, 0x6d, 0x88, 0x6f, 0xfc, 0xff, 0xff, 0xfa, 0x8d, 0x71, 0xf8,
+ 0xfc, 0x0d, 0x71, 0xe8, 0xcb, 0xdc, 0xf8, 0x00, 0x4f, 0x78, 0xff, 0xf6, 0xff, 0x63, 0x28, 0x0c,
+ 0xcf, 0xe4, 0xb8, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xe0, 0x01, 0xd1, 0x94, 0xff, 0x89, 0xe8, 0xa0, 0xff, 0x86, 0xd0, 0x9c,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd2, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x69, 0xe8, 0xfe, 0x8c, 0x69, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x69, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xd5, 0x84,
+ 0xff, 0x0e, 0x69, 0xc0, 0xfa, 0x8c, 0x69, 0xe4, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x05, 0xf2,
+ 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd4, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xae,
+ 0xff, 0x7f, 0x18, 0x00, 0xfb, 0x0c, 0x69, 0xec, 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x60, 0x00, 0x02,
+ 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xd4, 0xa5, 0xfc, 0x25, 0x33, 0xe0, 0xfb, 0x8c, 0x6a, 0x00,
+ 0xcf, 0x58, 0xa8, 0x00, 0xfd, 0x0e, 0x6d, 0xa2, 0xce, 0xd4, 0xba, 0x00, 0x2f, 0x78, 0x00, 0x36,
+ 0xff, 0x8e, 0x6d, 0xb4, 0xff, 0x7f, 0x28, 0x00, 0xcc, 0x74, 0xd0, 0x00, 0xff, 0x63, 0x18, 0x0c,
+ 0xcc, 0xdc, 0xb0, 0x00, 0x4f, 0xf8, 0xff, 0xf6, 0xff, 0xe3, 0x28, 0x0c, 0xfa, 0x8d, 0x71, 0xf8,
+ 0xff, 0x0d, 0x6d, 0x88, 0xfb, 0x0d, 0x72, 0x78, 0xfc, 0x0d, 0x71, 0xe8, 0xad, 0xf6, 0xd0, 0x02,
+ 0x8e, 0x62, 0x00, 0x04, 0x8f, 0x62, 0x00, 0x0c, 0x8e, 0xe2, 0x00, 0x08, 0x8f, 0xe2, 0x00, 0x10,
+ 0xcc, 0xee, 0xc8, 0x00, 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xf6, 0xc9, 0x00, 0xcc, 0xfa, 0xc9, 0x00,
+ 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00, 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00,
+ 0xee, 0x01, 0xd4, 0x39, 0x0c, 0x60, 0x00, 0x14, 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02,
+ 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00,
+ 0xee, 0x01, 0xd4, 0x18, 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00,
+ 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00, 0xfc, 0x89, 0xe8, 0xa0, 0xff, 0x0c, 0x69, 0xf8,
+ 0xff, 0x8e, 0x69, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd4, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xb0, 0xfe, 0xff, 0x58, 0x00, 0x4f, 0x55, 0xdf, 0xff,
+ 0xcf, 0x78, 0xb0, 0x00, 0x2f, 0x78, 0x00, 0x0e, 0xff, 0x8e, 0x6d, 0xb2, 0xff, 0x7f, 0x28, 0x00,
+ 0x4e, 0xf4, 0x00, 0x0f, 0xfc, 0x8c, 0x6d, 0xb0, 0xfd, 0x0c, 0x6d, 0xb4, 0xfd, 0x8c, 0x6d, 0xb8,
+ 0xfe, 0x0c, 0x6d, 0xbc, 0xff, 0x8c, 0x6d, 0xc0, 0x7e, 0xf5, 0x00, 0x02, 0xfb, 0x0d, 0x72, 0x78,
+ 0xcb, 0xf8, 0xea, 0x00, 0xcc, 0xe6, 0xc0, 0x00, 0xcc, 0xea, 0xc9, 0x00, 0xcc, 0xee, 0xc9, 0x00,
+ 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00, 0x2e, 0xf6, 0x00, 0x14,
+ 0xe6, 0x01, 0xd5, 0x25, 0xfc, 0x0e, 0x6d, 0xc4, 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02,
+ 0x2e, 0xf6, 0x00, 0x04, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00, 0xe6, 0x01, 0xd5, 0x08,
+ 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0,
+ 0xcc, 0x80, 0xc9, 0x00, 0xff, 0x8e, 0x6d, 0xba, 0xcf, 0x04, 0xce, 0x00, 0xff, 0x7f, 0x28, 0x00,
+ 0xff, 0x63, 0x18, 0x0c, 0xfc, 0x8c, 0x69, 0xe8, 0x4f, 0xf8, 0x00, 0x09, 0xff, 0x0d, 0x6d, 0x88,
+ 0x6f, 0xfc, 0xff, 0xff, 0xfa, 0x8d, 0x71, 0xf8, 0xfc, 0x0d, 0x71, 0xe8, 0xcb, 0xdc, 0xf8, 0x00,
+ 0x4f, 0x78, 0xff, 0xf6, 0xff, 0x63, 0x28, 0x0c, 0xcf, 0xe4, 0xb8, 0x00, 0x7f, 0x7c, 0x00, 0x10,
+ 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xe0, 0x01, 0xd4, 0x4c,
+ 0xff, 0x89, 0xe8, 0xa0, 0xff, 0x86, 0xd3, 0x54, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd5, 0x90,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6a, 0x68, 0xfe, 0x8c, 0x6a, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6a, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xd8, 0x3c, 0xff, 0x0e, 0x6a, 0x40, 0xfa, 0x8c, 0x6a, 0x64,
+ 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x0b, 0xe2, 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd4, 0x00, 0x09,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xae, 0xff, 0x7f, 0x18, 0x00, 0xfb, 0x0c, 0x6a, 0x6c,
+ 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x60, 0x00, 0x02, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xd7, 0x5d,
+ 0xfc, 0x25, 0x33, 0xe0, 0xfb, 0x8c, 0x6a, 0x80, 0xcf, 0x58, 0xa8, 0x00, 0xfd, 0x0e, 0x6d, 0xa2,
+ 0xce, 0xd4, 0xba, 0x00, 0x2f, 0x78, 0x00, 0x36, 0xff, 0x8e, 0x6d, 0xb4, 0xff, 0x7f, 0x28, 0x00,
+ 0xcc, 0x74, 0xd0, 0x00, 0xff, 0x63, 0x18, 0x0c, 0xcc, 0xdc, 0xb0, 0x00, 0x4f, 0xf8, 0xff, 0xf6,
+ 0xff, 0xe3, 0x28, 0x0c, 0xfa, 0x8d, 0x71, 0xf8, 0xff, 0x0d, 0x6d, 0x88, 0xfb, 0x0d, 0x72, 0x78,
+ 0xfc, 0x0d, 0x71, 0xe8, 0xad, 0xf6, 0xd0, 0x02, 0x8e, 0x62, 0x00, 0x04, 0x8f, 0x62, 0x00, 0x0c,
+ 0x8e, 0xe2, 0x00, 0x08, 0x8f, 0xe2, 0x00, 0x10, 0xcc, 0xee, 0xc8, 0x00, 0xcc, 0xf2, 0xc9, 0x00,
+ 0xcc, 0xf6, 0xc9, 0x00, 0xcc, 0xfa, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00,
+ 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xd6, 0xf1, 0x0c, 0x60, 0x00, 0x14,
+ 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00,
+ 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00, 0xee, 0x01, 0xd6, 0xd0, 0x0c, 0x60, 0x00, 0x04,
+ 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00,
+ 0xfc, 0x89, 0xe8, 0xa0, 0xff, 0x0c, 0x6a, 0x78, 0xff, 0x8e, 0x6a, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd7, 0x28, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xb0,
+ 0xfe, 0xff, 0x58, 0x00, 0x4f, 0x55, 0xdf, 0xff, 0xcf, 0x78, 0xb0, 0x00, 0x2f, 0x78, 0x00, 0x0e,
+ 0xff, 0x8e, 0x6d, 0xb2, 0xff, 0x7f, 0x28, 0x00, 0x4e, 0xf4, 0x00, 0x0f, 0xfc, 0x8c, 0x6d, 0xb0,
+ 0xfd, 0x0c, 0x6d, 0xb4, 0xfd, 0x8c, 0x6d, 0xb8, 0xfe, 0x0c, 0x6d, 0xbc, 0xff, 0x8c, 0x6d, 0xc0,
+ 0x7e, 0xf5, 0x00, 0x02, 0xfb, 0x0d, 0x72, 0x78, 0xcb, 0xf8, 0xea, 0x00, 0xcc, 0xe6, 0xc0, 0x00,
+ 0xcc, 0xea, 0xc9, 0x00, 0xcc, 0xee, 0xc9, 0x00, 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00,
+ 0xcc, 0x80, 0xc9, 0x00, 0x2e, 0xf6, 0x00, 0x14, 0xe6, 0x01, 0xd7, 0xdd, 0xfc, 0x0e, 0x6d, 0xc4,
+ 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02, 0x2e, 0xf6, 0x00, 0x04, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xcc, 0xe4, 0xf8, 0x00, 0xe6, 0x01, 0xd7, 0xc0, 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10,
+ 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00, 0xff, 0x8e, 0x6d, 0xba,
+ 0xcf, 0x04, 0xce, 0x00, 0xff, 0x7f, 0x28, 0x00, 0xff, 0x63, 0x18, 0x0c, 0xfc, 0x8c, 0x6a, 0x68,
+ 0x4f, 0xf8, 0x00, 0x09, 0xff, 0x0d, 0x6d, 0x88, 0x6f, 0xfc, 0xff, 0xff, 0xfa, 0x8d, 0x71, 0xf8,
+ 0xfc, 0x0d, 0x71, 0xe8, 0xcb, 0xdc, 0xf8, 0x00, 0x4f, 0x78, 0xff, 0xf6, 0xff, 0x63, 0x28, 0x0c,
+ 0xcf, 0xe4, 0xb8, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xe0, 0x01, 0xd7, 0x04, 0xff, 0x89, 0xe8, 0xa0, 0xff, 0x86, 0xd6, 0x0c,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd8, 0x48, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6a, 0xe8, 0xfe, 0x8c, 0x6a, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6a, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xda, 0xf4,
+ 0xff, 0x0e, 0x6a, 0xc0, 0xfa, 0x8c, 0x6a, 0xe4, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x11, 0xd2,
+ 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd4, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xae,
+ 0xff, 0x7f, 0x18, 0x00, 0xfb, 0x0c, 0x6a, 0xec, 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x60, 0x00, 0x02,
+ 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xda, 0x15, 0xfc, 0x25, 0x33, 0xe0, 0xfb, 0x8c, 0x6b, 0x00,
+ 0xcf, 0x58, 0xa8, 0x00, 0xfd, 0x0e, 0x6d, 0xa2, 0xce, 0xd4, 0xba, 0x00, 0x2f, 0x78, 0x00, 0x36,
+ 0xff, 0x8e, 0x6d, 0xb4, 0xff, 0x7f, 0x28, 0x00, 0xcc, 0x74, 0xd0, 0x00, 0xff, 0x63, 0x18, 0x0c,
+ 0xcc, 0xdc, 0xb0, 0x00, 0x4f, 0xf8, 0xff, 0xf6, 0xff, 0xe3, 0x28, 0x0c, 0xfa, 0x8d, 0x71, 0xf8,
+ 0xff, 0x0d, 0x6d, 0x88, 0xfb, 0x0d, 0x72, 0x78, 0xfc, 0x0d, 0x71, 0xe8, 0xad, 0xf6, 0xd0, 0x02,
+ 0x8e, 0x62, 0x00, 0x04, 0x8f, 0x62, 0x00, 0x0c, 0x8e, 0xe2, 0x00, 0x08, 0x8f, 0xe2, 0x00, 0x10,
+ 0xcc, 0xee, 0xc8, 0x00, 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xf6, 0xc9, 0x00, 0xcc, 0xfa, 0xc9, 0x00,
+ 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00, 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00,
+ 0xee, 0x01, 0xd9, 0xa9, 0x0c, 0x60, 0x00, 0x14, 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02,
+ 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00,
+ 0xee, 0x01, 0xd9, 0x88, 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00,
+ 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00, 0xfc, 0x89, 0xe8, 0xa0, 0xff, 0x0c, 0x6a, 0xf8,
+ 0xff, 0x8e, 0x6a, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xd9, 0xe0,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xb0, 0xfe, 0xff, 0x58, 0x00, 0x4f, 0x55, 0xdf, 0xff,
+ 0xcf, 0x78, 0xb0, 0x00, 0x2f, 0x78, 0x00, 0x0e, 0xff, 0x8e, 0x6d, 0xb2, 0xff, 0x7f, 0x28, 0x00,
+ 0x4e, 0xf4, 0x00, 0x0f, 0xfc, 0x8c, 0x6d, 0xb0, 0xfd, 0x0c, 0x6d, 0xb4, 0xfd, 0x8c, 0x6d, 0xb8,
+ 0xfe, 0x0c, 0x6d, 0xbc, 0xff, 0x8c, 0x6d, 0xc0, 0x7e, 0xf5, 0x00, 0x02, 0xfb, 0x0d, 0x72, 0x78,
+ 0xcb, 0xf8, 0xea, 0x00, 0xcc, 0xe6, 0xc0, 0x00, 0xcc, 0xea, 0xc9, 0x00, 0xcc, 0xee, 0xc9, 0x00,
+ 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00, 0x2e, 0xf6, 0x00, 0x14,
+ 0xe6, 0x01, 0xda, 0x95, 0xfc, 0x0e, 0x6d, 0xc4, 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02,
+ 0x2e, 0xf6, 0x00, 0x04, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00, 0xe6, 0x01, 0xda, 0x78,
+ 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0,
+ 0xcc, 0x80, 0xc9, 0x00, 0xff, 0x8e, 0x6d, 0xba, 0xcf, 0x04, 0xce, 0x00, 0xff, 0x7f, 0x28, 0x00,
+ 0xff, 0x63, 0x18, 0x0c, 0xfc, 0x8c, 0x6a, 0xe8, 0x4f, 0xf8, 0x00, 0x09, 0xff, 0x0d, 0x6d, 0x88,
+ 0x6f, 0xfc, 0xff, 0xff, 0xfa, 0x8d, 0x71, 0xf8, 0xfc, 0x0d, 0x71, 0xe8, 0xcb, 0xdc, 0xf8, 0x00,
+ 0x4f, 0x78, 0xff, 0xf6, 0xff, 0x63, 0x28, 0x0c, 0xcf, 0xe4, 0xb8, 0x00, 0x7f, 0x7c, 0x00, 0x10,
+ 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xe0, 0x01, 0xd9, 0xbc,
+ 0xff, 0x89, 0xe8, 0xa0, 0xff, 0x86, 0xd8, 0xc4, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xdb, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6b, 0x68, 0xfe, 0x8c, 0x6b, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6b, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xdd, 0xac, 0xff, 0x0e, 0x6b, 0x40, 0xfa, 0x8c, 0x6b, 0x64,
+ 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x36, 0x8a, 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd4, 0x00, 0x09,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xae, 0xff, 0x7f, 0x18, 0x00, 0xfb, 0x0c, 0x6b, 0x6c,
+ 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x60, 0x00, 0x02, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xdc, 0xcd,
+ 0xfc, 0x25, 0x33, 0xe0, 0xfb, 0x8c, 0x6b, 0x80, 0xcf, 0x58, 0xa8, 0x00, 0xfd, 0x0e, 0x6d, 0xa2,
+ 0xce, 0xd4, 0xba, 0x00, 0x2f, 0x78, 0x00, 0x36, 0xff, 0x8e, 0x6d, 0xb4, 0xff, 0x7f, 0x28, 0x00,
+ 0xcc, 0x74, 0xd0, 0x00, 0xff, 0x63, 0x18, 0x0c, 0xcc, 0xdc, 0xb0, 0x00, 0x4f, 0xf8, 0xff, 0xf6,
+ 0xff, 0xe3, 0x28, 0x0c, 0xfa, 0x8d, 0x71, 0xf8, 0xff, 0x0d, 0x6d, 0x88, 0xfb, 0x0d, 0x72, 0x78,
+ 0xfc, 0x0d, 0x71, 0xe8, 0xad, 0xf6, 0xd0, 0x02, 0x8e, 0x62, 0x00, 0x04, 0x8f, 0x62, 0x00, 0x0c,
+ 0x8e, 0xe2, 0x00, 0x08, 0x8f, 0xe2, 0x00, 0x10, 0xcc, 0xee, 0xc8, 0x00, 0xcc, 0xf2, 0xc9, 0x00,
+ 0xcc, 0xf6, 0xc9, 0x00, 0xcc, 0xfa, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00,
+ 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00, 0xee, 0x01, 0xdc, 0x61, 0x0c, 0x60, 0x00, 0x14,
+ 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02, 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00,
+ 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00, 0xee, 0x01, 0xdc, 0x40, 0x0c, 0x60, 0x00, 0x04,
+ 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00,
+ 0xfc, 0x89, 0xe8, 0xa0, 0xff, 0x0c, 0x6b, 0x78, 0xff, 0x8e, 0x6b, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xdc, 0x98, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xb0,
+ 0xfe, 0xff, 0x58, 0x00, 0x4f, 0x55, 0xdf, 0xff, 0xcf, 0x78, 0xb0, 0x00, 0x2f, 0x78, 0x00, 0x0e,
+ 0xff, 0x8e, 0x6d, 0xb2, 0xff, 0x7f, 0x28, 0x00, 0x4e, 0xf4, 0x00, 0x0f, 0xfc, 0x8c, 0x6d, 0xb0,
+ 0xfd, 0x0c, 0x6d, 0xb4, 0xfd, 0x8c, 0x6d, 0xb8, 0xfe, 0x0c, 0x6d, 0xbc, 0xff, 0x8c, 0x6d, 0xc0,
+ 0x7e, 0xf5, 0x00, 0x02, 0xfb, 0x0d, 0x72, 0x78, 0xcb, 0xf8, 0xea, 0x00, 0xcc, 0xe6, 0xc0, 0x00,
+ 0xcc, 0xea, 0xc9, 0x00, 0xcc, 0xee, 0xc9, 0x00, 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00,
+ 0xcc, 0x80, 0xc9, 0x00, 0x2e, 0xf6, 0x00, 0x14, 0xe6, 0x01, 0xdd, 0x4d, 0xfc, 0x0e, 0x6d, 0xc4,
+ 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02, 0x2e, 0xf6, 0x00, 0x04, 0xcf, 0xfc, 0xf0, 0x00,
+ 0xcc, 0xe4, 0xf8, 0x00, 0xe6, 0x01, 0xdd, 0x30, 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10,
+ 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00, 0xff, 0x8e, 0x6d, 0xba,
+ 0xcf, 0x04, 0xce, 0x00, 0xff, 0x7f, 0x28, 0x00, 0xff, 0x63, 0x18, 0x0c, 0xfc, 0x8c, 0x6b, 0x68,
+ 0x4f, 0xf8, 0x00, 0x09, 0xff, 0x0d, 0x6d, 0x88, 0x6f, 0xfc, 0xff, 0xff, 0xfa, 0x8d, 0x71, 0xf8,
+ 0xfc, 0x0d, 0x71, 0xe8, 0xcb, 0xdc, 0xf8, 0x00, 0x4f, 0x78, 0xff, 0xf6, 0xff, 0x63, 0x28, 0x0c,
+ 0xcf, 0xe4, 0xb8, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xe0, 0x01, 0xdc, 0x74, 0xff, 0x89, 0xe8, 0xa0, 0xff, 0x86, 0xdb, 0x7c,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xdd, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6b, 0xe8, 0xfe, 0x8c, 0x6b, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6b, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xe0, 0x64,
+ 0xff, 0x0e, 0x6b, 0xc0, 0xfa, 0x8c, 0x6b, 0xe4, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x5b, 0x42,
+ 0x9f, 0x82, 0xfe, 0x68, 0x0f, 0xd4, 0x00, 0x09, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x8e, 0x6d, 0xa0,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xae,
+ 0xff, 0x7f, 0x18, 0x00, 0xfb, 0x0c, 0x6b, 0xec, 0x20, 0x7a, 0x08, 0x00, 0xe6, 0x60, 0x00, 0x02,
+ 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xdf, 0x85, 0xfc, 0x25, 0x33, 0xe0, 0xfb, 0x8c, 0x6c, 0x00,
+ 0xcf, 0x58, 0xa8, 0x00, 0xfd, 0x0e, 0x6d, 0xa2, 0xce, 0xd4, 0xba, 0x00, 0x2f, 0x78, 0x00, 0x36,
+ 0xff, 0x8e, 0x6d, 0xb4, 0xff, 0x7f, 0x28, 0x00, 0xcc, 0x74, 0xd0, 0x00, 0xff, 0x63, 0x18, 0x0c,
+ 0xcc, 0xdc, 0xb0, 0x00, 0x4f, 0xf8, 0xff, 0xf6, 0xff, 0xe3, 0x28, 0x0c, 0xfa, 0x8d, 0x71, 0xf8,
+ 0xff, 0x0d, 0x6d, 0x88, 0xfb, 0x0d, 0x72, 0x78, 0xfc, 0x0d, 0x71, 0xe8, 0xad, 0xf6, 0xd0, 0x02,
+ 0x8e, 0x62, 0x00, 0x04, 0x8f, 0x62, 0x00, 0x0c, 0x8e, 0xe2, 0x00, 0x08, 0x8f, 0xe2, 0x00, 0x10,
+ 0xcc, 0xee, 0xc8, 0x00, 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xf6, 0xc9, 0x00, 0xcc, 0xfa, 0xc9, 0x00,
+ 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00, 0x2b, 0xdc, 0x00, 0x14, 0x20, 0x5e, 0x00, 0x00,
+ 0xee, 0x01, 0xdf, 0x19, 0x0c, 0x60, 0x00, 0x14, 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02,
+ 0x2b, 0xdc, 0x00, 0x04, 0x20, 0x5e, 0x00, 0x00, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00,
+ 0xee, 0x01, 0xde, 0xf8, 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00,
+ 0x7c, 0xe4, 0xff, 0xf0, 0xcc, 0x80, 0xc9, 0x00, 0xfc, 0x89, 0xe8, 0xa0, 0xff, 0x0c, 0x6b, 0xf8,
+ 0xff, 0x8e, 0x6b, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xdf, 0x50,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6d, 0xb0, 0xfe, 0xff, 0x58, 0x00, 0x4f, 0x55, 0xdf, 0xff,
+ 0xcf, 0x78, 0xb0, 0x00, 0x2f, 0x78, 0x00, 0x0e, 0xff, 0x8e, 0x6d, 0xb2, 0xff, 0x7f, 0x28, 0x00,
+ 0x4e, 0xf4, 0x00, 0x0f, 0xfc, 0x8c, 0x6d, 0xb0, 0xfd, 0x0c, 0x6d, 0xb4, 0xfd, 0x8c, 0x6d, 0xb8,
+ 0xfe, 0x0c, 0x6d, 0xbc, 0xff, 0x8c, 0x6d, 0xc0, 0x7e, 0xf5, 0x00, 0x02, 0xfb, 0x0d, 0x72, 0x78,
+ 0xcb, 0xf8, 0xea, 0x00, 0xcc, 0xe6, 0xc0, 0x00, 0xcc, 0xea, 0xc9, 0x00, 0xcc, 0xee, 0xc9, 0x00,
+ 0xcc, 0xf2, 0xc9, 0x00, 0xcc, 0xfe, 0xc9, 0x00, 0xcc, 0x80, 0xc9, 0x00, 0x2e, 0xf6, 0x00, 0x14,
+ 0xe6, 0x01, 0xe0, 0x05, 0xfc, 0x0e, 0x6d, 0xc4, 0xff, 0xe3, 0x18, 0x00, 0xff, 0x63, 0x18, 0x02,
+ 0x2e, 0xf6, 0x00, 0x04, 0xcf, 0xfc, 0xf0, 0x00, 0xcc, 0xe4, 0xf8, 0x00, 0xe6, 0x01, 0xdf, 0xe8,
+ 0x0c, 0x60, 0x00, 0x04, 0x7f, 0xe4, 0x00, 0x10, 0xcc, 0xfe, 0xc8, 0x00, 0x7c, 0xe4, 0xff, 0xf0,
+ 0xcc, 0x80, 0xc9, 0x00, 0xff, 0x8e, 0x6d, 0xba, 0xcf, 0x04, 0xce, 0x00, 0xff, 0x7f, 0x28, 0x00,
+ 0xff, 0x63, 0x18, 0x0c, 0xfc, 0x8c, 0x6b, 0xe8, 0x4f, 0xf8, 0x00, 0x09, 0xff, 0x0d, 0x6d, 0x88,
+ 0x6f, 0xfc, 0xff, 0xff, 0xfa, 0x8d, 0x71, 0xf8, 0xfc, 0x0d, 0x71, 0xe8, 0xcb, 0xdc, 0xf8, 0x00,
+ 0x4f, 0x78, 0xff, 0xf6, 0xff, 0x63, 0x28, 0x0c, 0xcf, 0xe4, 0xb8, 0x00, 0x7f, 0x7c, 0x00, 0x10,
+ 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xe0, 0x01, 0xdf, 0x2c,
+ 0xff, 0x89, 0xe8, 0xa0, 0xff, 0x86, 0xde, 0x34, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe0, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x69, 0x68, 0xfe, 0x8c, 0x69, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x69, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xe2, 0x0c, 0xff, 0x0e, 0x69, 0x40, 0xfe, 0x0c, 0x69, 0x64,
+ 0xfc, 0x24, 0x33, 0xe0, 0xfe, 0x8c, 0x71, 0xf8, 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x71, 0xe8,
+ 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00,
+ 0xff, 0x8c, 0x69, 0x68, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x00, 0x02, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xe8, 0xa0, 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x6d, 0xa2,
+ 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10,
+ 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03,
+ 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xe8, 0xa0, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x01, 0xe1, 0xac, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x6d, 0xba, 0xfc, 0xf3, 0x18, 0x00,
+ 0xfe, 0x8c, 0x6d, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0,
+ 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xe2, 0x05,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x6d, 0xb4, 0xff, 0x0c, 0x69, 0x78,
+ 0xff, 0x8e, 0x69, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe1, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xe1, 0xa4, 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xe0, 0xec,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe2, 0x18, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x69, 0xe8, 0xfe, 0x8c, 0x69, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x69, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xe3, 0xb4,
+ 0xff, 0x0e, 0x69, 0xc0, 0xfe, 0x0c, 0x69, 0xe4, 0xfc, 0x24, 0x33, 0xe0, 0xfe, 0x8c, 0x71, 0xf8,
+ 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x71, 0xe8, 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff,
+ 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x69, 0xe8, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x05, 0xf2, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xe8, 0xa0,
+ 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x6d, 0xa2, 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00,
+ 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30,
+ 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00,
+ 0xfc, 0x89, 0xe8, 0xa0, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xe3, 0x54, 0x9f, 0x6e, 0x00, 0x04,
+ 0xfe, 0x0e, 0x6d, 0xba, 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x6d, 0xb4, 0x0e, 0xf7, 0x00, 0x01,
+ 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00,
+ 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xe3, 0xad, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00,
+ 0xfe, 0x8d, 0x6d, 0xb4, 0xff, 0x0c, 0x69, 0xf8, 0xff, 0x8e, 0x69, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe3, 0x78, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xe3, 0x4c,
+ 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xe2, 0x94, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe3, 0xc0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6a, 0x68, 0xfe, 0x8c, 0x6a, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6a, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xe5, 0x5c, 0xff, 0x0e, 0x6a, 0x40, 0xfe, 0x0c, 0x6a, 0x64,
+ 0xfc, 0x24, 0x33, 0xe0, 0xfe, 0x8c, 0x71, 0xf8, 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x71, 0xe8,
+ 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00,
+ 0xff, 0x8c, 0x6a, 0x68, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x0b, 0xe2, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xe8, 0xa0, 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x6d, 0xa2,
+ 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10,
+ 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03,
+ 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xe8, 0xa0, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x01, 0xe4, 0xfc, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x6d, 0xba, 0xfc, 0xf3, 0x18, 0x00,
+ 0xfe, 0x8c, 0x6d, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0,
+ 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xe5, 0x55,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x6d, 0xb4, 0xff, 0x0c, 0x6a, 0x78,
+ 0xff, 0x8e, 0x6a, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe5, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xe4, 0xf4, 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xe4, 0x3c,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe5, 0x68, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6a, 0xe8, 0xfe, 0x8c, 0x6a, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6a, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xe7, 0x04,
+ 0xff, 0x0e, 0x6a, 0xc0, 0xfe, 0x0c, 0x6a, 0xe4, 0xfc, 0x24, 0x33, 0xe0, 0xfe, 0x8c, 0x71, 0xf8,
+ 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x71, 0xe8, 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff,
+ 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x6a, 0xe8, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x11, 0xd2, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xe8, 0xa0,
+ 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x6d, 0xa2, 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00,
+ 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30,
+ 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00,
+ 0xfc, 0x89, 0xe8, 0xa0, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xe6, 0xa4, 0x9f, 0x6e, 0x00, 0x04,
+ 0xfe, 0x0e, 0x6d, 0xba, 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x6d, 0xb4, 0x0e, 0xf7, 0x00, 0x01,
+ 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00,
+ 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xe6, 0xfd, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00,
+ 0xfe, 0x8d, 0x6d, 0xb4, 0xff, 0x0c, 0x6a, 0xf8, 0xff, 0x8e, 0x6a, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe6, 0xc8, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xe6, 0x9c,
+ 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xe5, 0xe4, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe7, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6b, 0x68, 0xfe, 0x8c, 0x6b, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6b, 0x68,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xe8, 0xac, 0xff, 0x0e, 0x6b, 0x40, 0xfe, 0x0c, 0x6b, 0x64,
+ 0xfc, 0x24, 0x33, 0xe0, 0xfe, 0x8c, 0x71, 0xf8, 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x71, 0xe8,
+ 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00,
+ 0xff, 0x8c, 0x6b, 0x68, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x36, 0x8a, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xe8, 0xa0, 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x6d, 0xa2,
+ 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10,
+ 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03,
+ 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xe8, 0xa0, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x01, 0xe8, 0x4c, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x6d, 0xba, 0xfc, 0xf3, 0x18, 0x00,
+ 0xfe, 0x8c, 0x6d, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0,
+ 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xe8, 0xa5,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x6d, 0xb4, 0xff, 0x0c, 0x6b, 0x78,
+ 0xff, 0x8e, 0x6b, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe8, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xe8, 0x44, 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xe7, 0x8c,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xe8, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6b, 0xe8, 0xfe, 0x8c, 0x6b, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6b, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xea, 0x54,
+ 0xff, 0x0e, 0x6b, 0xc0, 0xfe, 0x0c, 0x6b, 0xe4, 0xfc, 0x24, 0x33, 0xe0, 0xfe, 0x8c, 0x71, 0xf8,
+ 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x71, 0xe8, 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff,
+ 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x6b, 0xe8, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x5b, 0x42, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xe8, 0xa0,
+ 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x6d, 0xa2, 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00,
+ 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30,
+ 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00,
+ 0xfc, 0x89, 0xe8, 0xa0, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xe9, 0xf4, 0x9f, 0x6e, 0x00, 0x04,
+ 0xfe, 0x0e, 0x6d, 0xba, 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x6d, 0xb4, 0x0e, 0xf7, 0x00, 0x01,
+ 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00,
+ 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xea, 0x4d, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00,
+ 0xfe, 0x8d, 0x6d, 0xb4, 0xff, 0x0c, 0x6b, 0xf8, 0xff, 0x8e, 0x6b, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xea, 0x18, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xe9, 0xec,
+ 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xe9, 0x34, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xea, 0x60,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x69, 0x68, 0xfe, 0x8c, 0x69, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00,
+ 0xff, 0x0d, 0x69, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xec, 0x00, 0xff, 0x0e, 0x69, 0x40,
+ 0xfe, 0x0c, 0x69, 0x64, 0xfc, 0x24, 0x33, 0xe0, 0xfe, 0x8c, 0x71, 0xf8, 0x0f, 0x01, 0x20, 0x00,
+ 0xfd, 0x8c, 0x71, 0xe8, 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00,
+ 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x69, 0x68, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x00, 0x02,
+ 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xe8, 0xa0, 0x8f, 0x6e, 0x00, 0x04,
+ 0xfd, 0x0e, 0x6d, 0xa2, 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00,
+ 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00,
+ 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00,
+ 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xe8, 0xa0,
+ 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xeb, 0xa0, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x6d, 0xba,
+ 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x6d, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe,
+ 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff,
+ 0xe6, 0x01, 0xeb, 0xf9, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x6d, 0xb4,
+ 0xff, 0x0c, 0x69, 0x78, 0xff, 0x8e, 0x69, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30,
+ 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03,
+ 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xeb, 0xc4, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xeb, 0x98, 0xcc, 0xe0, 0x00, 0x00,
+ 0xff, 0x86, 0xea, 0xe0, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xec, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x69, 0xe8,
+ 0xfe, 0x8c, 0x69, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x69, 0xe8,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xed, 0xac, 0xff, 0x0e, 0x69, 0xc0, 0xfe, 0x0c, 0x69, 0xe4,
+ 0xfc, 0x24, 0x33, 0xe0, 0xfe, 0x8c, 0x71, 0xf8, 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x71, 0xe8,
+ 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00,
+ 0xff, 0x8c, 0x69, 0xe8, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x05, 0xf2, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xe8, 0xa0, 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x6d, 0xa2,
+ 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10,
+ 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03,
+ 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xe8, 0xa0, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x01, 0xed, 0x4c, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x6d, 0xba, 0xfc, 0xf3, 0x18, 0x00,
+ 0xfe, 0x8c, 0x6d, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0,
+ 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xed, 0xa5,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x6d, 0xb4, 0xff, 0x0c, 0x69, 0xf8,
+ 0xff, 0x8e, 0x69, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xed, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xed, 0x44, 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xec, 0x8c,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xed, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6a, 0x68, 0xfe, 0x8c, 0x6a, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08,
+ 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6a, 0x68, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x01, 0xef, 0x58, 0xff, 0x0e, 0x6a, 0x40, 0xfe, 0x0c, 0x6a, 0x64, 0xfc, 0x24, 0x33, 0xe0,
+ 0xfe, 0x8c, 0x71, 0xf8, 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x71, 0xe8, 0xcf, 0x74, 0xf4, 0x00,
+ 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x6a, 0x68,
+ 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x0b, 0xe2, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30,
+ 0xfc, 0x88, 0xe8, 0xa0, 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x6d, 0xa2, 0x9d, 0x02, 0xfe, 0x30,
+ 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10,
+ 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00,
+ 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xe8, 0xa0, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xee, 0xf8,
+ 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x6d, 0xba, 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x6d, 0xb4,
+ 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00,
+ 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xef, 0x51, 0x00, 0x00, 0x00, 0x01,
+ 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x6d, 0xb4, 0xff, 0x0c, 0x6a, 0x78, 0xff, 0x8e, 0x6a, 0x40,
+ 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00,
+ 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xef, 0x1c, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x01, 0xee, 0xf0, 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xee, 0x38, 0x9e, 0xfa, 0x00, 0x20,
+ 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xef, 0x64, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00,
+ 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6a, 0xe8, 0xfe, 0x8c, 0x6a, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6a, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xf1, 0x04,
+ 0xff, 0x0e, 0x6a, 0xc0, 0xfe, 0x0c, 0x6a, 0xe4, 0xfc, 0x24, 0x33, 0xe0, 0xfe, 0x8c, 0x71, 0xf8,
+ 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x71, 0xe8, 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff,
+ 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x6a, 0xe8, 0x0d, 0x01, 0x80, 0x01,
+ 0x0d, 0x68, 0x11, 0xd2, 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xe8, 0xa0,
+ 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x6d, 0xa2, 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00,
+ 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30,
+ 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00,
+ 0xfc, 0x89, 0xe8, 0xa0, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xf0, 0xa4, 0x9f, 0x6e, 0x00, 0x04,
+ 0xfe, 0x0e, 0x6d, 0xba, 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x6d, 0xb4, 0x0e, 0xf7, 0x00, 0x01,
+ 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00,
+ 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xf0, 0xfd, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00,
+ 0xfe, 0x8d, 0x6d, 0xb4, 0xff, 0x0c, 0x6a, 0xf8, 0xff, 0x8e, 0x6a, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf0, 0xc8, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xf0, 0x9c,
+ 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xef, 0xe4, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf1, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6b, 0x68, 0xfe, 0x8c, 0x6b, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00,
+ 0xff, 0x0d, 0x6b, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xf2, 0xb0, 0xff, 0x0e, 0x6b, 0x40,
+ 0xfe, 0x0c, 0x6b, 0x64, 0xfc, 0x24, 0x33, 0xe0, 0xfe, 0x8c, 0x71, 0xf8, 0x0f, 0x01, 0x20, 0x00,
+ 0xfd, 0x8c, 0x71, 0xe8, 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00,
+ 0x5e, 0xf5, 0x10, 0x00, 0xff, 0x8c, 0x6b, 0x68, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x36, 0x8a,
+ 0x9d, 0x02, 0xfe, 0x30, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xe8, 0xa0, 0x8f, 0x6e, 0x00, 0x04,
+ 0xfd, 0x0e, 0x6d, 0xa2, 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00,
+ 0x7d, 0x7c, 0x00, 0x10, 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00,
+ 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00,
+ 0xe4, 0x3c, 0x00, 0x03, 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xe8, 0xa0,
+ 0x20, 0x62, 0x00, 0x00, 0xe6, 0x01, 0xf2, 0x50, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x6d, 0xba,
+ 0xfc, 0xf3, 0x18, 0x00, 0xfe, 0x8c, 0x6d, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe,
+ 0x7f, 0xe4, 0xff, 0xf0, 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff,
+ 0xe6, 0x01, 0xf2, 0xa9, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x6d, 0xb4,
+ 0xff, 0x0c, 0x6b, 0x78, 0xff, 0x8e, 0x6b, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30,
+ 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03,
+ 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x01, 0xf2, 0x74, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xf2, 0x48, 0xcc, 0xe0, 0x00, 0x00,
+ 0xff, 0x86, 0xf1, 0x90, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf2, 0xbc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6b, 0xe8,
+ 0xfe, 0x8c, 0x6b, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6b, 0xe8,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xf4, 0x5c, 0xff, 0x0e, 0x6b, 0xc0, 0xfe, 0x0c, 0x6b, 0xe4,
+ 0xfc, 0x24, 0x33, 0xe0, 0xfe, 0x8c, 0x71, 0xf8, 0x0f, 0x01, 0x20, 0x00, 0xfd, 0x8c, 0x71, 0xe8,
+ 0xcf, 0x74, 0xf4, 0x00, 0x4e, 0xf5, 0xdf, 0xff, 0xcf, 0x70, 0xf5, 0x00, 0x5e, 0xf5, 0x10, 0x00,
+ 0xff, 0x8c, 0x6b, 0xe8, 0x0d, 0x01, 0x80, 0x01, 0x0d, 0x68, 0x5b, 0x42, 0x9d, 0x02, 0xfe, 0x30,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x88, 0xe8, 0xa0, 0x8f, 0x6e, 0x00, 0x04, 0xfd, 0x0e, 0x6d, 0xa2,
+ 0x9d, 0x02, 0xfe, 0x30, 0xcf, 0xe6, 0xf8, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7d, 0x7c, 0x00, 0x10,
+ 0xcf, 0xea, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xef, 0x28, 0x10, 0x9e, 0x82, 0xfe, 0x30, 0xcf, 0x7a, 0xe0, 0x00, 0xe4, 0x3c, 0x00, 0x03,
+ 0xcc, 0xe4, 0xe0, 0x00, 0xcc, 0xe4, 0x7a, 0x00, 0xfc, 0x89, 0xe8, 0xa0, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x01, 0xf3, 0xfc, 0x9f, 0x6e, 0x00, 0x04, 0xfe, 0x0e, 0x6d, 0xba, 0xfc, 0xf3, 0x18, 0x00,
+ 0xfe, 0x8c, 0x6d, 0xb4, 0x0e, 0xf7, 0x00, 0x01, 0x1c, 0xe4, 0xff, 0xfe, 0x7f, 0xe4, 0xff, 0xf0,
+ 0xcc, 0xe4, 0xf8, 0x00, 0x4f, 0x65, 0x00, 0x00, 0x20, 0x7a, 0xff, 0xff, 0xe6, 0x01, 0xf4, 0x55,
+ 0x00, 0x00, 0x00, 0x01, 0xfc, 0xf3, 0x28, 0x00, 0xfe, 0x8d, 0x6d, 0xb4, 0xff, 0x0c, 0x6b, 0xf8,
+ 0xff, 0x8e, 0x6b, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf4, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xf3, 0xf4, 0xcc, 0xe0, 0x00, 0x00, 0xff, 0x86, 0xf3, 0x3c,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf4, 0x68, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x69, 0x68, 0xfe, 0x8c, 0x69, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x69, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xf6, 0xbc,
+ 0xff, 0x0e, 0x69, 0x40, 0xfe, 0x8c, 0x69, 0x64, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x00, 0x02,
+ 0xfa, 0xa4, 0x33, 0xe0, 0xfd, 0x8c, 0x71, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x71, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x69, 0x68,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x01, 0xf6, 0x55, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xe8, 0xa0, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x72, 0x78, 0xfc, 0x8c, 0x6d, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x01, 0xf5, 0xfd, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x6d, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x69, 0x78, 0xff, 0x8e, 0x69, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x6d, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x6d, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x01, 0xf6, 0x4d,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xf5, 0x70, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x01, 0xf6, 0x44,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x00, 0x02, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x6e, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x6e, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x01, 0xf5, 0x20, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x86, 0xf4, 0xe4,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf6, 0xc8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x69, 0xe8, 0xfe, 0x8c, 0x69, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x69, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xf9, 0x1c,
+ 0xff, 0x0e, 0x69, 0xc0, 0xfe, 0x8c, 0x69, 0xe4, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x05, 0xf2,
+ 0xfa, 0xa4, 0x33, 0xe0, 0xfd, 0x8c, 0x71, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x71, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x69, 0xe8,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x01, 0xf8, 0xb5, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xe8, 0xa0, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x72, 0x78, 0xfc, 0x8c, 0x6d, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x01, 0xf8, 0x5d, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x6d, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x69, 0xf8, 0xff, 0x8e, 0x69, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf8, 0x28, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x6d, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x6d, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x01, 0xf8, 0xad,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xf7, 0xd0, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x01, 0xf8, 0xa4,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x05, 0xf2, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x6e, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x6e, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x01, 0xf7, 0x80, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x86, 0xf7, 0x44,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xf9, 0x28, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6a, 0x68, 0xfe, 0x8c, 0x6a, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6a, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xfb, 0x7c,
+ 0xff, 0x0e, 0x6a, 0x40, 0xfe, 0x8c, 0x6a, 0x64, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x0b, 0xe2,
+ 0xfa, 0xa4, 0x33, 0xe0, 0xfd, 0x8c, 0x71, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x71, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x6a, 0x68,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x01, 0xfb, 0x15, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xe8, 0xa0, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x72, 0x78, 0xfc, 0x8c, 0x6d, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x01, 0xfa, 0xbd, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x6d, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x6a, 0x78, 0xff, 0x8e, 0x6a, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xfa, 0x88, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x6d, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x6d, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x01, 0xfb, 0x0d,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xfa, 0x30, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x01, 0xfb, 0x04,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x0b, 0xe2, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x6e, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x6e, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x01, 0xf9, 0xe0, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x86, 0xf9, 0xa4,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xfb, 0x88, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6a, 0xe8, 0xfe, 0x8c, 0x6a, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6a, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x01, 0xfd, 0xdc,
+ 0xff, 0x0e, 0x6a, 0xc0, 0xfe, 0x8c, 0x6a, 0xe4, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x11, 0xd2,
+ 0xfa, 0xa4, 0x33, 0xe0, 0xfd, 0x8c, 0x71, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x71, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x6a, 0xe8,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x01, 0xfd, 0x75, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xe8, 0xa0, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x72, 0x78, 0xfc, 0x8c, 0x6d, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x01, 0xfd, 0x1d, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x6d, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x6a, 0xf8, 0xff, 0x8e, 0x6a, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xfc, 0xe8, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x6d, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x6d, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x01, 0xfd, 0x6d,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xfc, 0x90, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x01, 0xfd, 0x64,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x11, 0xd2, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x6e, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x6e, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x01, 0xfc, 0x40, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x86, 0xfc, 0x04,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xfd, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6b, 0x68, 0xfe, 0x8c, 0x6b, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6b, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x00, 0x3c,
+ 0xff, 0x0e, 0x6b, 0x40, 0xfe, 0x8c, 0x6b, 0x64, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x36, 0x8a,
+ 0xfa, 0xa4, 0x33, 0xe0, 0xfd, 0x8c, 0x71, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x71, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x6b, 0x68,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x01, 0xff, 0xd5, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xe8, 0xa0, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x72, 0x78, 0xfc, 0x8c, 0x6d, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x01, 0xff, 0x7d, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x6d, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x6b, 0x78, 0xff, 0x8e, 0x6b, 0x40, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x01, 0xff, 0x48, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x6d, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x6d, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x01, 0xff, 0xcd,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xfe, 0xf0, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x01, 0xff, 0xc4,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x36, 0x8a, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x6e, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x6e, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x01, 0xfe, 0xa0, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x86, 0xfe, 0x64,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6b, 0xe8, 0xfe, 0x8c, 0x6b, 0xe0,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6b, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x02, 0x9c,
+ 0xff, 0x0e, 0x6b, 0xc0, 0xfe, 0x8c, 0x6b, 0xe4, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x5b, 0x42,
+ 0xfa, 0xa4, 0x33, 0xe0, 0xfd, 0x8c, 0x71, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x71, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x6b, 0xe8,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x02, 0x02, 0x35, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xe8, 0xa0, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x72, 0x78, 0xfc, 0x8c, 0x6d, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x01, 0xdd, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x6d, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x6b, 0xf8, 0xff, 0x8e, 0x6b, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x01, 0xa8, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x6d, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x6d, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x02, 0x02, 0x2d,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x01, 0x50, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x02, 0x02, 0x24,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x5b, 0x42, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x6e, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x6e, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x01, 0x00, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x8a, 0x00, 0xc4,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x02, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x69, 0x68, 0xfe, 0x8c, 0x69, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08,
+ 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x69, 0x68, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x02, 0x05, 0x00, 0xff, 0x0e, 0x69, 0x40, 0xfe, 0x8c, 0x69, 0x64, 0x0f, 0x01, 0x80, 0x01,
+ 0x0f, 0x78, 0x00, 0x02, 0xfa, 0xa4, 0x33, 0xe0, 0xfd, 0x8c, 0x71, 0xf8, 0x0f, 0x81, 0x20, 0x00,
+ 0xfb, 0x8c, 0x71, 0xe8, 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00,
+ 0xf9, 0x8c, 0x69, 0x68, 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x02, 0x04, 0x99,
+ 0x5b, 0x6d, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xe8, 0xa0,
+ 0xff, 0x0e, 0x6d, 0xa2, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x72, 0x78, 0xfc, 0x8c, 0x6d, 0x88,
+ 0x4e, 0xf5, 0xdf, 0xff, 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00,
+ 0x4f, 0xe4, 0x00, 0x09, 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x04, 0x41, 0xcd, 0x68, 0xf8, 0x00,
+ 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x6d, 0xb4, 0xff, 0xfb, 0x28, 0x00,
+ 0xfc, 0xdf, 0x28, 0x0c, 0xff, 0x0c, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01,
+ 0xff, 0x0d, 0x38, 0xf8, 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10,
+ 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xdf, 0x28, 0x10, 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x69, 0x78, 0xff, 0x8e, 0x69, 0x40,
+ 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00,
+ 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0xfa, 0x0e, 0x6d, 0xba, 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e,
+ 0x6e, 0xf4, 0xff, 0xff, 0xff, 0x0e, 0x6d, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00,
+ 0xfc, 0xdf, 0x28, 0x0c, 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00,
+ 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff,
+ 0xe6, 0x02, 0x04, 0x91, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x03, 0xb4, 0xfe, 0x53, 0x28, 0x00,
+ 0xe0, 0x02, 0x04, 0x88, 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x00, 0x02,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00,
+ 0xff, 0x0e, 0x6e, 0x00, 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x6e, 0x02, 0x9f, 0x02, 0xfe, 0x68,
+ 0xff, 0x0e, 0x6d, 0xa2, 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00,
+ 0xcf, 0x78, 0xfa, 0x00, 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x03, 0x64, 0xcb, 0x58, 0xe8, 0x00,
+ 0xff, 0x8a, 0x03, 0x28, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x05, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x69, 0xe8,
+ 0xfe, 0x8c, 0x69, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x69, 0xe8,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x07, 0x64, 0xff, 0x0e, 0x69, 0xc0, 0xfe, 0x8c, 0x69, 0xe4,
+ 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x05, 0xf2, 0xfa, 0xa4, 0x33, 0xe0, 0xfd, 0x8c, 0x71, 0xf8,
+ 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x71, 0xe8, 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff,
+ 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x69, 0xe8, 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b,
+ 0xe2, 0x02, 0x06, 0xfd, 0x5b, 0x6d, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30,
+ 0xfd, 0x08, 0xe8, 0xa0, 0xff, 0x0e, 0x6d, 0xa2, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x72, 0x78,
+ 0xfc, 0x8c, 0x6d, 0x88, 0x4e, 0xf5, 0xdf, 0xff, 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00,
+ 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09, 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x06, 0xa5,
+ 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x6d, 0xb4,
+ 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c, 0xff, 0x0c, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00,
+ 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf8, 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00,
+ 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00,
+ 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10, 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x69, 0xf8,
+ 0xff, 0x8e, 0x69, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x06, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x6d, 0xba, 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff, 0xff, 0x0e, 0x6d, 0xb2, 0xff, 0xfb, 0x28, 0x00,
+ 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c, 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10,
+ 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00,
+ 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x02, 0x06, 0xf5, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x06, 0x18,
+ 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x02, 0x06, 0xec, 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01,
+ 0x0f, 0xfc, 0x05, 0xf2, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68,
+ 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x6e, 0x00, 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68,
+ 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x6e, 0x02,
+ 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x6d, 0xa2, 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00,
+ 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01,
+ 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00, 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x05, 0xc8,
+ 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x8a, 0x05, 0x8c, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x07, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00,
+ 0xff, 0x0c, 0x6a, 0x68, 0xfe, 0x8c, 0x6a, 0x60, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7,
+ 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00,
+ 0xff, 0x0d, 0x6a, 0x68, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x09, 0xc8, 0xff, 0x0e, 0x6a, 0x40,
+ 0xfe, 0x8c, 0x6a, 0x64, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x0b, 0xe2, 0xfa, 0xa4, 0x33, 0xe0,
+ 0xfd, 0x8c, 0x71, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x71, 0xe8, 0xcf, 0xec, 0xfc, 0x00,
+ 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x6a, 0x68, 0xcf, 0xec, 0xe0, 0x00,
+ 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x02, 0x09, 0x61, 0x5b, 0x6d, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x30,
+ 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xe8, 0xa0, 0xff, 0x0e, 0x6d, 0xa2, 0x9f, 0x02, 0xfe, 0x30,
+ 0xfc, 0x0c, 0x72, 0x78, 0xfc, 0x8c, 0x6d, 0x88, 0x4e, 0xf5, 0xdf, 0xff, 0x6f, 0xe0, 0xff, 0xff,
+ 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09, 0x20, 0x56, 0x00, 0x00,
+ 0xe6, 0x02, 0x09, 0x09, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x36,
+ 0xff, 0x0e, 0x6d, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c, 0xff, 0x0c, 0x38, 0xf8,
+ 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf8, 0xcf, 0xea, 0x98, 0x00,
+ 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0,
+ 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10, 0x9b, 0x02, 0xfe, 0x30,
+ 0xff, 0x0c, 0x6a, 0x78, 0xff, 0x8e, 0x6a, 0x40, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30,
+ 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03,
+ 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x08, 0xd4, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x6d, 0xba, 0xfe, 0x53, 0x18, 0x00,
+ 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff, 0xff, 0x0e, 0x6d, 0xb2,
+ 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c, 0xce, 0x70, 0xc0, 0x00,
+ 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00,
+ 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x02, 0x09, 0x59, 0x00, 0x00, 0x00, 0x01,
+ 0xe0, 0x02, 0x08, 0x7c, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x02, 0x09, 0x50, 0xce, 0x54, 0x00, 0x00,
+ 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x0b, 0xe2, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x08,
+ 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x6e, 0x00, 0xcf, 0xfc, 0xea, 0x00,
+ 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x0e, 0x6e, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x6d, 0xa2, 0x9e, 0x82, 0xfe, 0x68,
+ 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00, 0xce, 0x7c, 0x00, 0x00,
+ 0xe0, 0x02, 0x08, 0x2c, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x8a, 0x07, 0xf0, 0x9e, 0xfa, 0x00, 0x20,
+ 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x09, 0xd4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00,
+ 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6a, 0xe8, 0xfe, 0x8c, 0x6a, 0xe0, 0x4f, 0xfd, 0x1e, 0x00,
+ 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00,
+ 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6a, 0xe8, 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x0c, 0x2c,
+ 0xff, 0x0e, 0x6a, 0xc0, 0xfe, 0x8c, 0x6a, 0xe4, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x11, 0xd2,
+ 0xfa, 0xa4, 0x33, 0xe0, 0xfd, 0x8c, 0x71, 0xf8, 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x71, 0xe8,
+ 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x6a, 0xe8,
+ 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x02, 0x0b, 0xc5, 0x5b, 0x6d, 0x10, 0x00,
+ 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xe8, 0xa0, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x72, 0x78, 0xfc, 0x8c, 0x6d, 0x88, 0x4e, 0xf5, 0xdf, 0xff,
+ 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09,
+ 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x0b, 0x6d, 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x6d, 0xb4, 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xff, 0x0c, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf8,
+ 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00,
+ 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10,
+ 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x6a, 0xf8, 0xff, 0x8e, 0x6a, 0xc0, 0x90, 0xfe, 0x00, 0x20,
+ 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00,
+ 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x0b, 0x38, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x6d, 0xba,
+ 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff,
+ 0xff, 0x0e, 0x6d, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c,
+ 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0,
+ 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x02, 0x0b, 0xbd,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x0a, 0xe0, 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x02, 0x0b, 0xb4,
+ 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x11, 0xd2, 0x9f, 0x82, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x6e, 0x00,
+ 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x6e, 0x02, 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x6d, 0xa2,
+ 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00,
+ 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x0a, 0x90, 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x8a, 0x0a, 0x54,
+ 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6b, 0x68, 0xfe, 0x8c, 0x6b, 0x60,
+ 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48, 0x73, 0x9d, 0x00, 0x08,
+ 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6b, 0x68, 0x2e, 0xf6, 0x00, 0x01,
+ 0xe6, 0x02, 0x0e, 0x90, 0xff, 0x0e, 0x6b, 0x40, 0xfe, 0x8c, 0x6b, 0x64, 0x0f, 0x01, 0x80, 0x01,
+ 0x0f, 0x78, 0x36, 0x8a, 0xfa, 0xa4, 0x33, 0xe0, 0xfd, 0x8c, 0x71, 0xf8, 0x0f, 0x81, 0x20, 0x00,
+ 0xfb, 0x8c, 0x71, 0xe8, 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff, 0xce, 0x74, 0xfd, 0x00,
+ 0xf9, 0x8c, 0x6b, 0x68, 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b, 0xe2, 0x02, 0x0e, 0x29,
+ 0x5b, 0x6d, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30, 0xfd, 0x08, 0xe8, 0xa0,
+ 0xff, 0x0e, 0x6d, 0xa2, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x72, 0x78, 0xfc, 0x8c, 0x6d, 0x88,
+ 0x4e, 0xf5, 0xdf, 0xff, 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00, 0xcd, 0x68, 0xe8, 0x00,
+ 0x4f, 0xe4, 0x00, 0x09, 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x0d, 0xd1, 0xcd, 0x68, 0xf8, 0x00,
+ 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x6d, 0xb4, 0xff, 0xfb, 0x28, 0x00,
+ 0xfc, 0xdf, 0x28, 0x0c, 0xff, 0x0c, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00, 0x0f, 0x78, 0x00, 0x01,
+ 0xff, 0x0d, 0x38, 0xf8, 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00, 0x7f, 0x7c, 0x00, 0x10,
+ 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00, 0xcf, 0x84, 0xfe, 0x00,
+ 0xff, 0xdf, 0x28, 0x10, 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x6b, 0x78, 0xff, 0x8e, 0x6b, 0x40,
+ 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20, 0xc7, 0xf4, 0x00, 0x00,
+ 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x0d, 0x9c, 0x00, 0x00, 0x00, 0x01,
+ 0xfa, 0x0e, 0x6d, 0xba, 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x0e,
+ 0x6e, 0xf4, 0xff, 0xff, 0xff, 0x0e, 0x6d, 0xb2, 0xff, 0xfb, 0x28, 0x00, 0xce, 0x70, 0xe8, 0x00,
+ 0xfc, 0xdf, 0x28, 0x0c, 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10, 0xce, 0x7a, 0xe0, 0x00,
+ 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00, 0x20, 0x7e, 0xff, 0xff,
+ 0xe6, 0x02, 0x0e, 0x21, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x0d, 0x44, 0xfe, 0x53, 0x28, 0x00,
+ 0xe0, 0x02, 0x0e, 0x18, 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01, 0x0f, 0xfc, 0x36, 0x8a,
+ 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68, 0xcf, 0x80, 0xda, 0x00,
+ 0xff, 0x0e, 0x6e, 0x00, 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68, 0x0f, 0xfc, 0x00, 0x3c,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x6e, 0x02, 0x9f, 0x02, 0xfe, 0x68,
+ 0xff, 0x0e, 0x6d, 0xa2, 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00, 0x9f, 0x02, 0xfe, 0x68,
+ 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x80, 0x00,
+ 0xcf, 0x78, 0xfa, 0x00, 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x0c, 0xf4, 0xcb, 0x58, 0xe8, 0x00,
+ 0xff, 0x8a, 0x0c, 0xb8, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x0e, 0x9c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x0f, 0xa9, 0xfe, 0x00, 0xc5, 0x7c, 0x00, 0x00, 0xff, 0x0c, 0x6b, 0xe8,
+ 0xfe, 0x8c, 0x6b, 0xe0, 0x4f, 0xfd, 0x1e, 0x00, 0x7f, 0xfc, 0xff, 0xe7, 0x0f, 0xfc, 0x07, 0x48,
+ 0x73, 0x9d, 0x00, 0x08, 0xcf, 0x78, 0x38, 0x00, 0xf3, 0x7f, 0x68, 0x00, 0xff, 0x0d, 0x6b, 0xe8,
+ 0x2e, 0xf6, 0x00, 0x01, 0xe6, 0x02, 0x10, 0xf4, 0xff, 0x0e, 0x6b, 0xc0, 0xfe, 0x8c, 0x6b, 0xe4,
+ 0x0f, 0x01, 0x80, 0x01, 0x0f, 0x78, 0x5b, 0x42, 0xfa, 0xa4, 0x33, 0xe0, 0xfd, 0x8c, 0x71, 0xf8,
+ 0x0f, 0x81, 0x20, 0x00, 0xfb, 0x8c, 0x71, 0xe8, 0xcf, 0xec, 0xfc, 0x00, 0x4d, 0xed, 0xdf, 0xff,
+ 0xce, 0x74, 0xfd, 0x00, 0xf9, 0x8c, 0x6b, 0xe8, 0xcf, 0xec, 0xe0, 0x00, 0x20, 0x7e, 0x00, 0x3b,
+ 0xe2, 0x02, 0x10, 0x8d, 0x5b, 0x6d, 0x10, 0x00, 0x9f, 0x02, 0xfe, 0x30, 0x9e, 0x02, 0xfe, 0x30,
+ 0xfd, 0x08, 0xe8, 0xa0, 0xff, 0x0e, 0x6d, 0xa2, 0x9f, 0x02, 0xfe, 0x30, 0xfc, 0x0c, 0x72, 0x78,
+ 0xfc, 0x8c, 0x6d, 0x88, 0x4e, 0xf5, 0xdf, 0xff, 0x6f, 0xe0, 0xff, 0xff, 0xcd, 0x68, 0xf8, 0x00,
+ 0xcd, 0x68, 0xe8, 0x00, 0x4f, 0xe4, 0x00, 0x09, 0x20, 0x56, 0x00, 0x00, 0xe6, 0x02, 0x10, 0x35,
+ 0xcd, 0x68, 0xf8, 0x00, 0xcf, 0xec, 0xe8, 0x00, 0x2f, 0xfc, 0x00, 0x36, 0xff, 0x0e, 0x6d, 0xb4,
+ 0xff, 0xfb, 0x28, 0x00, 0xfc, 0xdf, 0x28, 0x0c, 0xff, 0x0c, 0x38, 0xf8, 0x55, 0x28, 0x01, 0x00,
+ 0x0f, 0x78, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xf8, 0xcf, 0xea, 0x98, 0x00, 0xcf, 0x80, 0xf9, 0x00,
+ 0x7f, 0x7c, 0x00, 0x10, 0xcf, 0xfa, 0xf8, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xcf, 0x80, 0xf9, 0x00,
+ 0xcf, 0x84, 0xfe, 0x00, 0xff, 0xdf, 0x28, 0x10, 0x9b, 0x02, 0xfe, 0x30, 0xff, 0x0c, 0x6b, 0xf8,
+ 0xff, 0x8e, 0x6b, 0xc0, 0x90, 0xfe, 0x00, 0x20, 0x8e, 0xfa, 0x00, 0x30, 0x8f, 0xfa, 0x00, 0x20,
+ 0xc7, 0xf4, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0xe7, 0x3c, 0x00, 0x03, 0x9f, 0xfa, 0x00, 0x20,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xfa, 0x0e, 0x6d, 0xba, 0xfe, 0x53, 0x18, 0x00, 0xcf, 0xec, 0xe8, 0x00,
+ 0x2f, 0xfc, 0x00, 0x0e, 0x6e, 0xf4, 0xff, 0xff, 0xff, 0x0e, 0x6d, 0xb2, 0xff, 0xfb, 0x28, 0x00,
+ 0xce, 0x70, 0xe8, 0x00, 0xfc, 0xdf, 0x28, 0x0c, 0xce, 0x70, 0xc0, 0x00, 0x7f, 0x70, 0x00, 0x10,
+ 0xce, 0x7a, 0xe0, 0x00, 0x7e, 0x70, 0xff, 0xf0, 0xce, 0x00, 0xe1, 0x00, 0x4f, 0xf1, 0x00, 0x00,
+ 0x20, 0x7e, 0xff, 0xff, 0xe6, 0x02, 0x10, 0x85, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x0f, 0xa8,
+ 0xfe, 0x53, 0x28, 0x00, 0xe0, 0x02, 0x10, 0x7c, 0xce, 0x54, 0x00, 0x00, 0x0f, 0x81, 0x80, 0x01,
+ 0x0f, 0xfc, 0x5b, 0x42, 0x9f, 0x82, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x08, 0x9f, 0x02, 0xfe, 0x68,
+ 0xcf, 0x80, 0xda, 0x00, 0xff, 0x0e, 0x6e, 0x00, 0xcf, 0xfc, 0xea, 0x00, 0x9f, 0x02, 0xfe, 0x68,
+ 0x0f, 0xfc, 0x00, 0x3c, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0e, 0x6e, 0x02,
+ 0x9f, 0x02, 0xfe, 0x68, 0xff, 0x0e, 0x6d, 0xa2, 0x9e, 0x82, 0xfe, 0x68, 0xcf, 0x6c, 0xf0, 0x00,
+ 0x9f, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x80, 0x01,
+ 0x0f, 0x78, 0x80, 0x00, 0xcf, 0x78, 0xfa, 0x00, 0xce, 0x7c, 0x00, 0x00, 0xe0, 0x02, 0x0f, 0x58,
+ 0xcb, 0x58, 0xe8, 0x00, 0xff, 0x8a, 0x0f, 0x1c, 0x9e, 0xfa, 0x00, 0x20, 0x9f, 0xfa, 0x00, 0x30,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x44, 0x4d, 0x41, 0x2d, 0x54, 0x45, 0x53,
+ 0x54, 0x3f, 0x3f, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x1c, 0xff, 0x8c, 0x72, 0x70, 0x20, 0x7e, 0x00, 0x04, 0xe6, 0x02, 0x18, 0x99,
+ 0xce, 0x18, 0x00, 0x00, 0x8d, 0x72, 0x00, 0x00, 0x8f, 0xf2, 0x00, 0x10, 0x8a, 0x72, 0x00, 0x04,
+ 0x89, 0xf2, 0x00, 0x08, 0x8d, 0xf2, 0x00, 0x0c, 0x20, 0x6a, 0x00, 0x31, 0xff, 0x89, 0xad, 0xb0,
+ 0x8e, 0xf2, 0x00, 0x14, 0xff, 0x8e, 0x38, 0xb0, 0xfe, 0x89, 0xe5, 0xf0, 0xff, 0x89, 0xe6, 0x28,
+ 0xf0, 0x09, 0xce, 0xc8, 0x8e, 0xf2, 0x00, 0x10, 0xfe, 0x89, 0xcd, 0xe8, 0x8f, 0xf2, 0x00, 0x14,
+ 0x0f, 0xfc, 0x00, 0x04, 0xff, 0x89, 0xe8, 0x90, 0xe2, 0x02, 0x16, 0xdc, 0xf0, 0x09, 0xcf, 0xb8,
+ 0x7f, 0xe9, 0x00, 0x02, 0xff, 0x0a, 0x11, 0xd4, 0xae, 0xfe, 0xf0, 0x02, 0xc1, 0x74, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x12, 0xb0, 0x00, 0x02, 0x12, 0x9c, 0x00, 0x02, 0x13, 0x20,
+ 0x00, 0x02, 0x13, 0x30, 0x00, 0x02, 0x13, 0x3c, 0x00, 0x02, 0x13, 0x64, 0x00, 0x02, 0x13, 0x6c,
+ 0x00, 0x02, 0x13, 0x80, 0x00, 0x02, 0x13, 0x8c, 0x00, 0x02, 0x13, 0x98, 0x00, 0x02, 0x13, 0xa0,
+ 0x00, 0x02, 0x13, 0xa8, 0x00, 0x02, 0x13, 0xb0, 0x00, 0x02, 0x13, 0xb8, 0x00, 0x02, 0x13, 0xc0,
+ 0x00, 0x02, 0x13, 0xe0, 0x00, 0x02, 0x13, 0xf0, 0x00, 0x02, 0x14, 0x08, 0x00, 0x02, 0x12, 0xb0,
+ 0x00, 0x02, 0x14, 0x14, 0x00, 0x02, 0x14, 0x40, 0x00, 0x02, 0x14, 0x78, 0x00, 0x02, 0x14, 0x90,
+ 0x00, 0x02, 0x15, 0x30, 0x00, 0x02, 0x15, 0x50, 0x00, 0x02, 0x15, 0xe8, 0x00, 0x02, 0x15, 0x68,
+ 0x00, 0x02, 0x15, 0x84, 0x00, 0x02, 0x15, 0x8c, 0x00, 0x02, 0x15, 0xb0, 0x00, 0x02, 0x15, 0xd4,
+ 0x00, 0x02, 0x14, 0x18, 0x00, 0x02, 0x15, 0xe8, 0x00, 0x02, 0x16, 0x90, 0x00, 0x02, 0x16, 0xbc,
+ 0x00, 0x02, 0x16, 0xdc, 0x00, 0x02, 0x16, 0xdc, 0x00, 0x02, 0x16, 0xdc, 0x00, 0x02, 0x16, 0xdc,
+ 0x00, 0x02, 0x16, 0xdc, 0x00, 0x02, 0x16, 0xdc, 0x00, 0x02, 0x16, 0xdc, 0x00, 0x02, 0x16, 0xdc,
+ 0x00, 0x02, 0x16, 0xdc, 0x00, 0x02, 0x16, 0xf4, 0x00, 0x02, 0x16, 0xfc, 0x00, 0x02, 0x17, 0x20,
+ 0x00, 0x02, 0x17, 0x70, 0x00, 0x02, 0x17, 0xc8, 0x00, 0x02, 0x18, 0x34, 0x0f, 0x81, 0x1f, 0xe0,
+ 0xc0, 0x2a, 0xfc, 0x00, 0xe6, 0x02, 0x13, 0x0d, 0xff, 0x82, 0x00, 0x03, 0xff, 0x89, 0xcf, 0xb8,
+ 0x70, 0x2a, 0x00, 0x01, 0xea, 0x02, 0x12, 0xd9, 0xcf, 0x84, 0x00, 0x00, 0xff, 0x08, 0xe5, 0xf0,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x02, 0x12, 0xd9, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x8a, 0x12, 0xd8,
+ 0xe0, 0x00, 0x7c, 0xf0, 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x12, 0xd8, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x8a, 0x13, 0x18,
+ 0xe0, 0x01, 0x17, 0xc8, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x12, 0xb0, 0x00, 0x00, 0x00, 0x01,
+ 0xf0, 0x0d, 0x38, 0xb0, 0xfe, 0x82, 0x00, 0x04, 0xe0, 0x02, 0x12, 0xb0, 0xfe, 0x89, 0xce, 0xc8,
+ 0xfa, 0x0d, 0x71, 0xa0, 0xe0, 0x02, 0x12, 0xb0, 0xf9, 0x9d, 0x33, 0x50, 0xff, 0x8c, 0x71, 0xc8,
+ 0x0f, 0xfc, 0x00, 0x02, 0xc0, 0x7e, 0xa2, 0x00, 0xe2, 0x02, 0x12, 0xb1, 0xfa, 0x0d, 0x72, 0xe0,
+ 0x20, 0x52, 0x0f, 0xff, 0xe2, 0x02, 0x12, 0xb0, 0xff, 0x82, 0x00, 0x02, 0xe0, 0x02, 0x12, 0xac,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x12, 0xb0, 0xfa, 0x0d, 0x38, 0xb8, 0xfe, 0x98, 0x73, 0x10,
+ 0xff, 0x82, 0x00, 0x04, 0xfe, 0x8d, 0x38, 0xb0, 0xe0, 0x02, 0x12, 0xb0, 0xff, 0x89, 0xce, 0xc8,
+ 0xfe, 0x8c, 0x6d, 0x78, 0xe0, 0x02, 0x13, 0x74, 0xff, 0x82, 0x00, 0x04, 0xfe, 0x9c, 0x33, 0x68,
+ 0xe0, 0x02, 0x13, 0x74, 0xff, 0x82, 0x00, 0x04, 0xe0, 0x02, 0x13, 0x70, 0xfe, 0x8e, 0x72, 0x00,
+ 0xe0, 0x02, 0x13, 0x70, 0x0e, 0x81, 0x00, 0xf4, 0xe0, 0x02, 0x13, 0x70, 0xfe, 0x82, 0x40, 0x00,
+ 0xe0, 0x02, 0x13, 0x70, 0xfe, 0x82, 0x10, 0x00, 0xe0, 0x02, 0x12, 0xb0, 0xfa, 0x19, 0x73, 0x08,
+ 0xf7, 0x8a, 0x13, 0xcc, 0xe0, 0x01, 0x15, 0xac, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x02, 0x12, 0xb1, 0xfe, 0x82, 0x00, 0x02, 0xe0, 0x02, 0x12, 0xb0, 0xfe, 0x89, 0xcf, 0xb8,
+ 0xff, 0x82, 0x00, 0x02, 0xff, 0x8d, 0x72, 0x70, 0xe0, 0x02, 0x12, 0xb0, 0x55, 0x29, 0x00, 0x10,
+ 0x0f, 0xd0, 0x00, 0x02, 0x20, 0x7e, 0x24, 0xb8, 0xe2, 0x02, 0x12, 0xb1, 0xfa, 0x0d, 0x71, 0xc8,
+ 0xe0, 0x02, 0x13, 0xd8, 0xfe, 0x82, 0x00, 0x02, 0xff, 0x8e, 0x6c, 0xe0, 0xe0, 0x02, 0x13, 0x24,
+ 0xff, 0x8d, 0x38, 0xb0, 0xfd, 0x82, 0x00, 0x28, 0x20, 0x6e, 0x00, 0x40, 0xe2, 0x02, 0x14, 0x39,
+ 0xfd, 0x89, 0xa6, 0x4c, 0xff, 0x82, 0x00, 0x40, 0xff, 0x89, 0xa6, 0x50, 0xfa, 0x0d, 0x71, 0xd8,
+ 0xe0, 0x02, 0x12, 0xb0, 0xf9, 0x8d, 0x6d, 0x68, 0xe0, 0x02, 0x14, 0x2c, 0xfd, 0x89, 0xa6, 0x50,
+ 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x12, 0xb0, 0xff, 0x82, 0x00, 0x01,
+ 0xff, 0x89, 0xa6, 0x60, 0xf7, 0x8a, 0x14, 0x60, 0xe0, 0x01, 0x2c, 0xa8, 0x97, 0x93, 0xff, 0xfc,
+ 0xf3, 0x76, 0xff, 0xfc, 0xf7, 0x8a, 0x14, 0x70, 0xe0, 0x00, 0x25, 0xb4, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x02, 0x12, 0xb0, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa6, 0x60, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x12, 0xb1, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x14, 0x54, 0xf0, 0x09, 0xa6, 0x60,
+ 0xfb, 0x76, 0xff, 0xd0, 0x8f, 0xda, 0x00, 0x00, 0xfd, 0x82, 0x00, 0xff, 0xfa, 0xf6, 0xff, 0xcc,
+ 0x7c, 0x50, 0xff, 0xf8, 0x8e, 0x56, 0x00, 0x00, 0xcc, 0x60, 0xdc, 0x00, 0x7f, 0x61, 0x00, 0x1c,
+ 0x0b, 0x81, 0xff, 0xf0, 0x4f, 0xfd, 0x00, 0x0f, 0x0b, 0xdc, 0x0f, 0xff, 0xcd, 0x50, 0xdc, 0x00,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x7c, 0xd0, 0xff, 0xe8, 0xce, 0x70, 0xbc, 0x00, 0x7c, 0xe5, 0x00, 0x0c,
+ 0x7d, 0x69, 0x00, 0x14, 0x7f, 0x50, 0xff, 0xf0, 0x7e, 0xcc, 0xff, 0xf8, 0xcf, 0x78, 0xdc, 0x00,
+ 0xce, 0xf4, 0xdc, 0x00, 0xce, 0x70, 0xcd, 0x00, 0xcf, 0xfc, 0xd5, 0x00, 0xcf, 0xfc, 0xbc, 0x00,
+ 0x7f, 0x79, 0x00, 0x04, 0x4e, 0x70, 0xf0, 0x00, 0x7e, 0xf5, 0x00, 0x0c, 0xce, 0x70, 0xf5, 0x00,
+ 0xcf, 0xfc, 0xed, 0x00, 0x7c, 0x60, 0xff, 0xfc, 0xcd, 0xcc, 0xdc, 0x00, 0xce, 0x70, 0xc5, 0x00,
+ 0x4f, 0xfc, 0xf0, 0x0f, 0x7d, 0xed, 0x00, 0x04, 0x9e, 0x56, 0x00, 0x00, 0xcf, 0xfc, 0xdd, 0x00,
+ 0x9f, 0xda, 0x00, 0x00, 0xfa, 0x0d, 0x72, 0xd8, 0xe0, 0x02, 0x14, 0x60, 0xf9, 0xa5, 0x34, 0x50,
+ 0xff, 0x76, 0xff, 0xd0, 0x8f, 0xfa, 0x00, 0x00, 0xfe, 0x82, 0x00, 0x01, 0xf3, 0x76, 0xff, 0xfc,
+ 0xfe, 0x8d, 0x6d, 0x58, 0x5f, 0xfc, 0x00, 0x08, 0xe0, 0x02, 0x14, 0x64, 0x9f, 0xfa, 0x00, 0x00,
+ 0xff, 0x76, 0xff, 0xd0, 0x8f, 0xfa, 0x00, 0x00, 0xf3, 0x76, 0xff, 0xfc, 0xf0, 0x0d, 0x6d, 0x58,
+ 0xe0, 0x02, 0x15, 0x48, 0x4f, 0xfc, 0xff, 0xf7, 0xfe, 0x82, 0x00, 0x01, 0xfe, 0x89, 0xa6, 0x5c,
+ 0xf7, 0x8a, 0x15, 0x7c, 0xe0, 0x01, 0x2c, 0xa8, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x12, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x15, 0x70, 0xf0, 0x09, 0xa6, 0x5c, 0x03, 0x70, 0x00, 0x04,
+ 0xf7, 0x8a, 0x15, 0x9c, 0xe0, 0x01, 0x2f, 0x84, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00,
+ 0xe6, 0x02, 0x12, 0xac, 0xff, 0x82, 0x00, 0x06, 0xe0, 0x02, 0x12, 0xb0, 0x00, 0x00, 0x00, 0x01,
+ 0x03, 0x70, 0x00, 0x04, 0xf7, 0x8a, 0x15, 0xc0, 0xe0, 0x01, 0x2d, 0xcc, 0x97, 0x93, 0xff, 0xfc,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x13, 0xd8, 0xfe, 0x82, 0x00, 0x06, 0xe0, 0x02, 0x12, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0xf7, 0x8a, 0x15, 0xe0, 0xe0, 0x01, 0x2e, 0xd4, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x02, 0x15, 0xa0, 0x20, 0x22, 0x00, 0x00, 0xff, 0x8c, 0x72, 0x70, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x13, 0xd8, 0xfe, 0x82, 0x00, 0x03, 0xff, 0x88, 0xa0, 0x48, 0xfd, 0x0d, 0x71, 0xd0,
+ 0xff, 0x02, 0xff, 0xf8, 0xff, 0x8d, 0x38, 0xd0, 0xff, 0xf3, 0x18, 0x0c, 0x4e, 0xfc, 0xff, 0xf8,
+ 0xfe, 0x8d, 0x6c, 0xc0, 0x8f, 0xf2, 0x00, 0x0c, 0xcf, 0xfc, 0xf4, 0x00, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x16, 0x79, 0xff, 0x8d, 0x38, 0xd8, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x16, 0x61,
+ 0xfe, 0x82, 0x00, 0x06, 0xfe, 0x9d, 0x33, 0x40, 0x8e, 0xf2, 0x00, 0x10, 0x4f, 0xd0, 0xff, 0xf8,
+ 0xfe, 0x8d, 0x39, 0x20, 0x8e, 0x72, 0x00, 0x14, 0xff, 0x8d, 0x71, 0xc0, 0xff, 0x82, 0x00, 0x04,
+ 0xfe, 0x0d, 0x6d, 0x80, 0xf9, 0x99, 0x72, 0xf0, 0xe0, 0x02, 0x12, 0xd8, 0xff, 0x8d, 0x72, 0x70,
+ 0xff, 0x8c, 0x38, 0xd8, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x16, 0x79, 0xff, 0x82, 0x00, 0x05,
+ 0xe0, 0x02, 0x16, 0x38, 0xff, 0x9d, 0x33, 0x40, 0xff, 0x8c, 0x6c, 0xc0, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x12, 0xad, 0xff, 0x82, 0x00, 0x02, 0xe0, 0x02, 0x16, 0x34, 0xfe, 0x82, 0x00, 0x04,
+ 0xff, 0x88, 0xa0, 0x4c, 0x20, 0x7e, 0x00, 0x05, 0xe2, 0x02, 0x16, 0xb0, 0xff, 0x02, 0x00, 0x00,
+ 0xff, 0x88, 0xa0, 0x48, 0x20, 0x7e, 0x01, 0x2c, 0xe2, 0x02, 0x16, 0xb5, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x02, 0x00, 0x01, 0xe0, 0x02, 0x13, 0x24, 0xff, 0x0d, 0x38, 0xb0, 0x20, 0x52, 0x00, 0x00,
+ 0xe6, 0x02, 0x16, 0xd5, 0x2f, 0xd0, 0x00, 0x01, 0xc0, 0x52, 0xfc, 0x00, 0xe6, 0x02, 0x12, 0xac,
+ 0xff, 0x82, 0x00, 0x02, 0xe0, 0x02, 0x12, 0xb0, 0xfa, 0x0d, 0x6c, 0xd0, 0xff, 0x82, 0x00, 0x01,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x12, 0xd9, 0xff, 0x89, 0xcf, 0xb8, 0xe0, 0x02, 0x12, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x13, 0x70, 0xfe, 0x82, 0x03, 0xfe, 0x20, 0x52, 0x00, 0x01,
+ 0xe2, 0x02, 0x13, 0xd8, 0xfe, 0x82, 0x00, 0x02, 0xfa, 0x09, 0xa6, 0x54, 0xf7, 0x8a, 0x17, 0x18,
+ 0xe0, 0x01, 0x10, 0xac, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x12, 0xb0, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x88, 0x9f, 0xd0, 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x02, 0x17, 0x39, 0xc3, 0xd0, 0x00, 0x00,
+ 0xe0, 0x02, 0x12, 0xac, 0xff, 0x82, 0x00, 0x0b, 0x9a, 0x16, 0xff, 0xe8, 0x44, 0x4d, 0x00, 0x00,
+ 0xf3, 0x02, 0x00, 0x00, 0xf7, 0x8a, 0x17, 0x50, 0xe0, 0x00, 0x76, 0x8c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8a, 0x16, 0xff, 0xe8, 0xf3, 0x02, 0x00, 0x00, 0xc3, 0xd0, 0x00, 0x00, 0xf7, 0x8a, 0x17, 0x68,
+ 0xe0, 0x00, 0x77, 0x7c, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x13, 0x24, 0xf4, 0x0d, 0x38, 0xb0,
+ 0xff, 0x88, 0x9f, 0xd0, 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x02, 0x12, 0xac, 0xff, 0x82, 0x00, 0x0b,
+ 0x44, 0x4d, 0x00, 0x00, 0xc3, 0xd0, 0x00, 0x00, 0x9a, 0x16, 0xff, 0xe8, 0x9d, 0x96, 0xff, 0xe4,
+ 0xf3, 0x02, 0x00, 0x00, 0xf7, 0x8a, 0x17, 0xa0, 0xe0, 0x00, 0x76, 0x8c, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x96, 0xff, 0xe4, 0x8a, 0x16, 0xff, 0xe8, 0xf3, 0x02, 0x00, 0x00, 0x44, 0x6d, 0x00, 0x00,
+ 0xc3, 0xd0, 0x00, 0x00, 0xf7, 0x8a, 0x17, 0xc0, 0xe0, 0x00, 0x77, 0x04, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x02, 0x12, 0xb0, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0x9f, 0xd0, 0xfe, 0x82, 0x00, 0x0b,
+ 0x20, 0x7e, 0x00, 0x03, 0xe6, 0x02, 0x13, 0xd8, 0x9f, 0x96, 0xff, 0xf0, 0x99, 0x96, 0xff, 0xec,
+ 0x9a, 0x16, 0xff, 0xe8, 0xf7, 0x8a, 0x17, 0xf0, 0xe0, 0x00, 0x79, 0x24, 0x97, 0x93, 0xff, 0xfc,
+ 0x89, 0x96, 0xff, 0xec, 0x8a, 0x16, 0xff, 0xe8, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x18, 0x11,
+ 0xc3, 0x50, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xf0, 0xe0, 0x02, 0x12, 0xb0, 0xff, 0x89, 0xcf, 0xb8,
+ 0xc3, 0xcc, 0x00, 0x00, 0xf7, 0x8a, 0x18, 0x20, 0xe0, 0x00, 0x79, 0xa4, 0x97, 0x93, 0xff, 0xfc,
+ 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x12, 0xb1, 0xfe, 0x82, 0x00, 0x0d, 0xe0, 0x02, 0x12, 0xb0,
+ 0xfe, 0x89, 0xcf, 0xb8, 0xfe, 0x88, 0x9f, 0xd0, 0x20, 0x76, 0x00, 0x03, 0xe6, 0x02, 0x17, 0x30,
+ 0x9e, 0x96, 0xff, 0xf4, 0x9a, 0x16, 0xff, 0xe8, 0xf7, 0x8a, 0x18, 0x54, 0xe0, 0x00, 0x79, 0x24,
+ 0x97, 0x93, 0xff, 0xfc, 0x8a, 0x16, 0xff, 0xe8, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x18, 0x71,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xf4, 0xe0, 0x02, 0x12, 0xb0, 0xfe, 0x89, 0xcf, 0xb8,
+ 0xff, 0x88, 0xa9, 0x60, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x12, 0xac, 0xff, 0x82, 0x00, 0x0c,
+ 0xc3, 0x50, 0x00, 0x00, 0xf7, 0x8a, 0x18, 0x90, 0xe0, 0x00, 0x78, 0xe0, 0x97, 0x93, 0xff, 0xfc,
+ 0xe0, 0x02, 0x13, 0x24, 0xf4, 0x0d, 0x38, 0xb0, 0x22, 0x10, 0x00, 0x04, 0xfe, 0x8a, 0x11, 0x40,
+ 0x9e, 0x92, 0x00, 0x00, 0x93, 0x16, 0xff, 0xe0, 0xf7, 0x8a, 0x18, 0xb4, 0xe0, 0x02, 0x87, 0x0c,
+ 0x97, 0x93, 0xff, 0xfc, 0x02, 0x10, 0x00, 0x04, 0xf3, 0x02, 0x00, 0x3e, 0xf7, 0x8a, 0x18, 0xc8,
+ 0xe0, 0x00, 0x7b, 0x5c, 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x16, 0xff, 0xe0, 0xe0, 0x02, 0x11, 0x74,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x7e, 0x21, 0x00, 0x02, 0xcf, 0x9c, 0xe0, 0x00,
+ 0x2f, 0xfc, 0x00, 0x01, 0xff, 0x02, 0x00, 0x3c, 0xcf, 0x1c, 0xf4, 0x00, 0xcf, 0x9c, 0xfe, 0x00,
+ 0xfe, 0x9e, 0x33, 0x70, 0x40, 0x7e, 0xff, 0xc0, 0xe6, 0x02, 0x19, 0x45, 0xce, 0xf8, 0xe8, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x19, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0xfa, 0x80, 0x00, 0xcf, 0x7c, 0x32, 0x00, 0x20, 0x7a, 0x00, 0x00,
+ 0xee, 0x02, 0x1a, 0x75, 0xcf, 0xf0, 0xf2, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xee, 0x02, 0x1a, 0x61,
+ 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68, 0x9f, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x7a, 0x00, 0x00, 0x9e, 0x02, 0xfe, 0x68,
+ 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xf4, 0xf0, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x9e, 0x33, 0x28, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x1a, 0x2d,
+ 0xff, 0x82, 0x00, 0x01, 0xff, 0x02, 0x00, 0x3c, 0xcf, 0xfc, 0x47, 0xc0, 0xcf, 0x1c, 0xf4, 0x00,
+ 0xfe, 0x9c, 0x33, 0x28, 0x2f, 0xfc, 0x00, 0x01, 0x7f, 0x78, 0xff, 0xfe, 0xcf, 0xfc, 0xf7, 0xc0,
+ 0xce, 0xf4, 0xfd, 0x00, 0x20, 0x76, 0xff, 0xff, 0xe6, 0x02, 0x1a, 0x09, 0x4f, 0x9d, 0x00, 0xff,
+ 0xfe, 0x9d, 0x33, 0x28, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x19, 0xd4, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xfc, 0xff, 0xee, 0xf0, 0x1d, 0x33, 0x28,
+ 0x7f, 0xfd, 0x00, 0x02, 0x8f, 0x7e, 0x05, 0x08, 0x43, 0x9c, 0xff, 0xc0, 0xf3, 0x1e, 0x33, 0x70,
+ 0xf7, 0x8a, 0x1a, 0x2c, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x1a, 0x2c, 0x00, 0x00, 0x00, 0x01,
+ 0x93, 0x02, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0xe0, 0x02, 0x19, 0x8c,
+ 0x00, 0x00, 0x00, 0x01, 0x2f, 0x98, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0xe0, 0x02, 0x1a, 0x64,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x6c, 0xf0, 0x93, 0x02, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x40, 0x9f, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xfc, 0xf0, 0x00,
+ 0x70, 0x7e, 0x00, 0x11, 0xea, 0x02, 0x1a, 0xf9, 0x4f, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80,
+ 0xff, 0x8d, 0x6c, 0xf0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x1a, 0xc4, 0x00, 0x00, 0x00, 0x01, 0xce, 0xfc, 0xf2, 0x00, 0x4f, 0xfc, 0xbf, 0xff,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x1b, 0x21, 0x4e, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x9f, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68,
+ 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x6c, 0xf0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x1b, 0x28, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8c, 0x6c, 0xf0, 0x93, 0x02, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x10, 0x9f, 0x02, 0xfe, 0x68,
+ 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xfc, 0xf0, 0x00, 0x70, 0x7e, 0x00, 0x11, 0xea, 0x02, 0x1b, 0xd1,
+ 0x4f, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x6c, 0xf0, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x1b, 0x9c, 0x00, 0x00, 0x00, 0x01,
+ 0xce, 0xfc, 0xf2, 0x00, 0x4f, 0xfc, 0xbf, 0xff, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x1b, 0xf9,
+ 0x4e, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x9f, 0x02, 0xfe, 0x68,
+ 0x9e, 0x82, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x6c, 0xf0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x1c, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x6c, 0xf0, 0x93, 0x02, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x20, 0x9f, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xfc, 0xf0, 0x00,
+ 0x70, 0x7e, 0x00, 0x11, 0xea, 0x02, 0x1c, 0xa9, 0x4f, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80,
+ 0xff, 0x8d, 0x6c, 0xf0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x1c, 0x74, 0x00, 0x00, 0x00, 0x01, 0xce, 0xfc, 0xf2, 0x00, 0x4f, 0xfc, 0xbf, 0xff,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x1c, 0xd1, 0x4e, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x9f, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68,
+ 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x6c, 0xf0, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x1c, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x8c, 0x6c, 0xf0, 0x93, 0x02, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x30, 0x9f, 0x02, 0xfe, 0x68,
+ 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xfc, 0xf0, 0x00, 0x70, 0x7e, 0x00, 0x11, 0xea, 0x02, 0x1d, 0x81,
+ 0x4f, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x6c, 0xf0, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x1d, 0x4c, 0x00, 0x00, 0x00, 0x01,
+ 0xce, 0xfc, 0xf2, 0x00, 0x4f, 0xfc, 0xbf, 0xff, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x1d, 0xa9,
+ 0x4e, 0x7c, 0xc0, 0x00, 0x90, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0x9f, 0x02, 0xfe, 0x68,
+ 0x9e, 0x82, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x6c, 0xf0,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x1d, 0xb0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x7e, 0x21, 0x00, 0x02, 0xcf, 0x9c, 0xe0, 0x00,
+ 0x2f, 0xfc, 0x00, 0x01, 0xff, 0x02, 0x00, 0x3c, 0xcf, 0x1c, 0xf4, 0x00, 0xcf, 0x9c, 0xfe, 0x00,
+ 0xfe, 0x8e, 0x72, 0x10, 0x40, 0x7e, 0xff, 0xc0, 0xe6, 0x02, 0x1e, 0x55, 0xce, 0xf8, 0xe8, 0x00,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x1e, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0xfa, 0x80, 0x00, 0xcf, 0x7c, 0x32, 0x00, 0x20, 0x7a, 0x00, 0x00,
+ 0xee, 0x02, 0x1f, 0x85, 0xcf, 0xf0, 0xf2, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xee, 0x02, 0x1f, 0x71,
+ 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68, 0x9f, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68,
+ 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x7a, 0x00, 0x00, 0x9e, 0x02, 0xfe, 0x68,
+ 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xf4, 0xf0, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x38, 0xc8, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x1f, 0x3d,
+ 0xff, 0x82, 0x00, 0x01, 0xff, 0x02, 0x00, 0x3c, 0xcf, 0xfc, 0x47, 0xc0, 0xcf, 0x1c, 0xf4, 0x00,
+ 0xfe, 0x8c, 0x38, 0xc8, 0x2f, 0xfc, 0x00, 0x01, 0x7f, 0x78, 0xff, 0xfe, 0xcf, 0xfc, 0xf7, 0xc0,
+ 0xce, 0xf4, 0xfd, 0x00, 0x20, 0x76, 0xff, 0xff, 0xe6, 0x02, 0x1f, 0x19, 0x4f, 0x9d, 0x00, 0xff,
+ 0xfe, 0x8d, 0x38, 0xc8, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x1e, 0xe4, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xfc, 0xff, 0xee, 0xf0, 0x0d, 0x38, 0xc8,
+ 0x7f, 0xfd, 0x00, 0x02, 0x8f, 0x7e, 0x05, 0x08, 0x43, 0x9c, 0xff, 0xc0, 0xf3, 0x0e, 0x72, 0x10,
+ 0xf7, 0x8a, 0x1f, 0x3c, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x1f, 0x3c, 0x00, 0x00, 0x00, 0x01,
+ 0x93, 0x02, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0xe0, 0x02, 0x1e, 0x9c,
+ 0x00, 0x00, 0x00, 0x01, 0x2f, 0x98, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x68, 0xe0, 0x02, 0x1f, 0x74,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x6d, 0x60, 0x93, 0x02, 0xfe, 0x68,
+ 0xff, 0x02, 0x00, 0x40, 0x9f, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xfc, 0xf0, 0x00,
+ 0x4f, 0xfc, 0xef, 0xff, 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x6d, 0x60, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x1f, 0xcc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x8c, 0x6c, 0xf8, 0x93, 0x02, 0xfe, 0x68, 0xff, 0x02, 0x00, 0x40,
+ 0x9f, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xfc, 0xf0, 0x00, 0x4f, 0xfc, 0xef, 0xff,
+ 0x90, 0x82, 0xfe, 0x80, 0xff, 0x8d, 0x6c, 0xf8, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x20, 0x38, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x7e, 0x21, 0x00, 0x02, 0xcf, 0x9c, 0xe0, 0x00, 0x2f, 0xfc, 0x00, 0x01, 0xff, 0x02, 0x00, 0x3c,
+ 0xcf, 0x1c, 0xf4, 0x00, 0xcf, 0x9c, 0xfe, 0x00, 0xfe, 0xa6, 0x33, 0xf0, 0x40, 0x7e, 0xff, 0xc0,
+ 0xe6, 0x02, 0x20, 0xdd, 0xce, 0xf8, 0xe8, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x20, 0xa8, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfa, 0x80, 0x00,
+ 0xcf, 0x7c, 0x32, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xee, 0x02, 0x22, 0x0d, 0xcf, 0xf0, 0xf2, 0x00,
+ 0x20, 0x7e, 0x00, 0x00, 0xee, 0x02, 0x21, 0xf9, 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68,
+ 0x9f, 0x02, 0xfe, 0x68, 0x9e, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x7a, 0x00, 0x00, 0x9e, 0x02, 0xfe, 0x68, 0x9f, 0x82, 0xfe, 0x68, 0xcf, 0xf4, 0xf0, 0x00,
+ 0x9f, 0x82, 0xfe, 0x68, 0x90, 0x02, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8e, 0x6c, 0xe8,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x21, 0xc5, 0xff, 0x82, 0x00, 0x01, 0xff, 0x02, 0x00, 0x3c,
+ 0xcf, 0xfc, 0x47, 0xc0, 0xcf, 0x1c, 0xf4, 0x00, 0xfe, 0x8c, 0x6c, 0xe8, 0x2f, 0xfc, 0x00, 0x01,
+ 0x7f, 0x78, 0xff, 0xfe, 0xcf, 0xfc, 0xf7, 0xc0, 0xce, 0xf4, 0xfd, 0x00, 0x20, 0x76, 0xff, 0xff,
+ 0xe6, 0x02, 0x21, 0xa1, 0x4f, 0x9d, 0x00, 0xff, 0xfe, 0x8d, 0x6c, 0xe8, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x21, 0x6c, 0x00, 0x00, 0x00, 0x01,
+ 0x7f, 0xfc, 0xff, 0xee, 0xf0, 0x0d, 0x6c, 0xe8, 0x7f, 0xfd, 0x00, 0x02, 0x8f, 0x7e, 0x05, 0x08,
+ 0x43, 0x9c, 0xff, 0xc0, 0xf3, 0x26, 0x33, 0xf0, 0xf7, 0x8a, 0x21, 0xc4, 0xc1, 0x78, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x01, 0x93, 0x02, 0xfe, 0x68, 0x9e, 0x02, 0xfe, 0x68,
+ 0x9e, 0x82, 0xfe, 0x68, 0xe0, 0x02, 0x21, 0x24, 0x00, 0x00, 0x00, 0x01, 0x2f, 0x98, 0x80, 0x00,
+ 0x9f, 0x82, 0xfe, 0x68, 0xe0, 0x02, 0x21, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x88, 0x8f, 0x98, 0x70, 0x7e, 0x00, 0x0c, 0xea, 0x02, 0x22, 0xcc, 0xfd, 0x02, 0x00, 0x00,
+ 0xfe, 0x88, 0xd3, 0xd8, 0x4f, 0xfd, 0xff, 0xf7, 0xff, 0x89, 0x8f, 0x98, 0xfd, 0x82, 0x34, 0x00,
+ 0xf7, 0x82, 0x00, 0x40, 0xf7, 0xf7, 0x68, 0x08, 0xfd, 0xf7, 0x28, 0x0c, 0xff, 0x0a, 0x9f, 0xfe,
+ 0xff, 0xfb, 0x18, 0x00, 0x7f, 0xfd, 0x00, 0x0f, 0xff, 0xf7, 0x28, 0x0e, 0xff, 0x82, 0x00, 0x24,
+ 0xff, 0xf7, 0x28, 0x12, 0x9d, 0x76, 0x00, 0x14, 0x9d, 0x76, 0x00, 0x18, 0x9d, 0x02, 0xfe, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x9d, 0x76, 0x00, 0x30, 0xff, 0x77, 0x18, 0x0a, 0x8e, 0x76, 0x00, 0x2c,
+ 0x0d, 0x81, 0x10, 0x00, 0x0f, 0xf4, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x0d, 0xec, 0x00, 0x14,
+ 0x9d, 0x82, 0xfe, 0x58, 0xff, 0x82, 0xa2, 0xec, 0x9f, 0xf6, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xfd, 0x82, 0x00, 0x28, 0x9d, 0x82, 0xff, 0xb0, 0xfd, 0x77, 0x28, 0x02, 0xff, 0x08, 0xd3, 0xd8,
+ 0xfe, 0xa4, 0x34, 0x30, 0xfd, 0x82, 0x00, 0x40, 0xfe, 0x26, 0x34, 0x34, 0x9d, 0xfa, 0x00, 0x30,
+ 0xff, 0xfb, 0x18, 0x0a, 0x8d, 0xfa, 0x00, 0x2c, 0x9e, 0x7a, 0x00, 0x24, 0x9e, 0xfa, 0x00, 0x28,
+ 0xff, 0xf3, 0x28, 0x02, 0x9e, 0x02, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xfe, 0x82, 0xa2, 0xec, 0x9e, 0xfa, 0x00, 0x04, 0x0f, 0xfc, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8,
+ 0x4f, 0xfc, 0x0f, 0xff, 0xff, 0xef, 0x28, 0x00, 0x9f, 0xee, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0xfd, 0x7b, 0x28, 0x02, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x23, 0x28, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x0f, 0xa9, 0xfe, 0x00, 0x4f, 0x7d, 0x1e, 0x00, 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0x78, 0x07, 0x48,
+ 0xc5, 0x7c, 0x00, 0x00, 0xf3, 0x7b, 0x68, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x23, 0x88, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x8f, 0xae, 0x00, 0x1c, 0xff, 0x08, 0xcd, 0xd8, 0x4e, 0x85, 0xdf, 0xff, 0x4f, 0xfc, 0x00, 0x00,
+ 0x85, 0xae, 0x00, 0x2c, 0xcf, 0x78, 0xf8, 0x00, 0xce, 0xf8, 0xed, 0x00, 0xff, 0x09, 0xcd, 0xd8,
+ 0xc5, 0x28, 0xec, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x23, 0xf4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x8a, 0x82, 0xff, 0xd0,
+ 0xff, 0x8c, 0x71, 0xd0, 0xff, 0x0c, 0x71, 0xe0, 0xfb, 0x1c, 0x33, 0x40, 0xfa, 0x1c, 0x33, 0x60,
+ 0x20, 0x7e, 0x00, 0x20, 0xe6, 0x02, 0x29, 0xed, 0xca, 0xd4, 0xf2, 0x00, 0x20, 0x5a, 0x00, 0x08,
+ 0xe2, 0x02, 0x2a, 0x14, 0x7f, 0xd9, 0x00, 0x02, 0xff, 0x0a, 0x24, 0x78, 0xae, 0xfe, 0xf0, 0x02,
+ 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x24, 0x9c, 0x00, 0x02, 0x25, 0xe4,
+ 0x00, 0x02, 0x26, 0xec, 0x00, 0x02, 0x28, 0x14, 0x00, 0x02, 0x2a, 0x14, 0x00, 0x02, 0x2a, 0x14,
+ 0x00, 0x02, 0x2a, 0x14, 0x00, 0x02, 0x2a, 0x14, 0x00, 0x02, 0x29, 0x28, 0x4f, 0xa9, 0x1e, 0x00,
+ 0x7e, 0xfc, 0xff, 0xe7, 0xff, 0x8c, 0x39, 0x18, 0x8e, 0x02, 0xff, 0xf8, 0x4f, 0x29, 0x01, 0xe0,
+ 0xc0, 0x76, 0xfa, 0x00, 0xe6, 0x02, 0x25, 0xdd, 0x7f, 0x78, 0xff, 0xeb, 0x20, 0x7a, 0x00, 0x0f,
+ 0xe6, 0x02, 0x25, 0xa9, 0xff, 0x82, 0x00, 0x00, 0x70, 0x72, 0x00, 0x13, 0xea, 0x02, 0x25, 0xa8,
+ 0xfc, 0x82, 0x00, 0x00, 0x0f, 0xf4, 0x07, 0x48, 0xfd, 0x7f, 0x58, 0x00, 0xfc, 0x18, 0x72, 0xf0,
+ 0xfb, 0x8c, 0x71, 0xc0, 0xfd, 0x8c, 0x6c, 0xc0, 0xfe, 0x08, 0xd3, 0xd8, 0x7f, 0xe9, 0x00, 0x1c,
+ 0xcf, 0xec, 0xfd, 0x00, 0x0f, 0x01, 0x80, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x62, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x0a, 0x9f, 0xfe, 0xff, 0xfb, 0x18, 0x00, 0x4d, 0xec, 0x0f, 0xf8,
+ 0x7d, 0xec, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xdd, 0x00, 0xff, 0xf3, 0x28, 0x0e,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xf0, 0xe8, 0x00, 0x9c, 0x72, 0x00, 0x14, 0xfd, 0x73, 0x68, 0x12,
+ 0xf0, 0xf3, 0x68, 0x13, 0x9b, 0xfe, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xf2, 0x00, 0x30,
+ 0xff, 0x73, 0x18, 0x0a, 0x8d, 0xf2, 0x00, 0x2c, 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00,
+ 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfc, 0xf3, 0x28, 0x02,
+ 0xff, 0x8a, 0x23, 0x68, 0x9c, 0x82, 0xff, 0x00, 0x7d, 0x69, 0x00, 0x02, 0x9f, 0xea, 0x07, 0x08,
+ 0xff, 0x82, 0x00, 0x01, 0x05, 0x29, 0x02, 0x20, 0xca, 0x50, 0xf8, 0x00, 0xff, 0x82, 0x00, 0x01,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x2a, 0x15, 0xfa, 0x1d, 0x33, 0x60, 0x20, 0x52, 0xff, 0xef,
+ 0xe2, 0x02, 0x25, 0xd4, 0xff, 0x82, 0x00, 0x08, 0x20, 0x56, 0x27, 0x10, 0xe2, 0x02, 0x2a, 0x15,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x2a, 0x14, 0xff, 0x9d, 0x33, 0x40, 0xe0, 0x02, 0x25, 0xa8,
+ 0xff, 0x82, 0x00, 0x00, 0x0f, 0x81, 0x20, 0x00, 0xcb, 0xaa, 0xfc, 0x00, 0xe6, 0x02, 0x25, 0xa8,
+ 0xff, 0x82, 0x00, 0x00, 0xfd, 0x98, 0x72, 0xf0, 0xfc, 0x0c, 0x38, 0xd8, 0xff, 0x08, 0xd3, 0xd8,
+ 0xc0, 0x6e, 0xfa, 0x00, 0xfd, 0x0c, 0x71, 0xc0, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7c, 0xe0, 0xff, 0xfe, 0x4e, 0xe4, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0x7e, 0x71, 0x00, 0x02, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9d, 0x7e, 0x00, 0x14,
+ 0x0e, 0x70, 0x00, 0x10, 0xff, 0x8a, 0xcf, 0xd0, 0xad, 0xfe, 0xc8, 0x05, 0xfd, 0x08, 0xcd, 0xd8,
+ 0xfe, 0xfb, 0x18, 0x0a, 0xff, 0xa6, 0x00, 0x0e, 0x8c, 0xfa, 0x00, 0x2c, 0x9f, 0xfa, 0x00, 0x30,
+ 0x0f, 0x81, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9c, 0x02, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x22,
+ 0xfb, 0xfb, 0x28, 0x20, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x8a, 0x23, 0xd0, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c,
+ 0x4e, 0xf4, 0x0f, 0xff, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01, 0x7d, 0xed, 0x00, 0x10,
+ 0xff, 0xfb, 0x28, 0x00, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xfd, 0x09, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0x69, 0x20, 0x00, 0xfb, 0xfb, 0x28, 0x02,
+ 0xc5, 0x28, 0xd5, 0x00, 0xe0, 0x02, 0x25, 0xa8, 0xff, 0x82, 0x00, 0x01, 0x4f, 0xa9, 0x1e, 0x00,
+ 0x7e, 0xfc, 0xff, 0xe7, 0xff, 0x8c, 0x39, 0x18, 0x8e, 0x02, 0xff, 0xf8, 0x4f, 0x29, 0x01, 0xe0,
+ 0xc0, 0x76, 0xfa, 0x00, 0xe6, 0x02, 0x28, 0x0d, 0x7f, 0x78, 0xff, 0xeb, 0x20, 0x7a, 0x00, 0x0f,
+ 0xe6, 0x02, 0x28, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x70, 0x72, 0x00, 0x13, 0xea, 0x02, 0x28, 0x0c,
+ 0xfc, 0x82, 0x00, 0x00, 0x0f, 0xf4, 0x07, 0x48, 0xfd, 0x7f, 0x58, 0x00, 0xfc, 0x18, 0x72, 0xf0,
+ 0xfb, 0x8c, 0x71, 0xc0, 0xfd, 0x8c, 0x6c, 0xc0, 0xfe, 0x08, 0xd3, 0xd8, 0x7f, 0xe9, 0x00, 0x1c,
+ 0xcf, 0xec, 0xfd, 0x00, 0x0f, 0x01, 0x80, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x62, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x0a, 0x9f, 0xfe, 0xff, 0xfb, 0x18, 0x00, 0x4d, 0xec, 0x0f, 0xf8,
+ 0x7d, 0xec, 0xff, 0xfe, 0x7f, 0xfd, 0x00, 0x0f, 0xcf, 0xfc, 0xdd, 0x00, 0xff, 0xf3, 0x28, 0x0e,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xf0, 0xe8, 0x00, 0x9c, 0x72, 0x00, 0x14, 0xfd, 0x73, 0x68, 0x12,
+ 0xf0, 0xf3, 0x68, 0x13, 0x9b, 0xfe, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xf2, 0x00, 0x30,
+ 0xff, 0x73, 0x18, 0x0a, 0x8d, 0xf2, 0x00, 0x2c, 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00,
+ 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfc, 0xf3, 0x28, 0x02,
+ 0xff, 0x8a, 0x23, 0x68, 0x9c, 0x82, 0xff, 0x00, 0x7d, 0x69, 0x00, 0x02, 0x9f, 0xea, 0x07, 0x08,
+ 0xff, 0x82, 0x00, 0x01, 0x05, 0x29, 0x02, 0x20, 0xcb, 0x58, 0xf8, 0x00, 0xff, 0x82, 0x00, 0x03,
+ 0xfb, 0x1d, 0x33, 0x40, 0xe0, 0x02, 0x25, 0xb0, 0xcf, 0xfc, 0xb2, 0x00, 0xe0, 0x02, 0x27, 0xf8,
+ 0xff, 0x82, 0x00, 0x00, 0x0f, 0x81, 0x20, 0x00, 0xcb, 0xaa, 0xfc, 0x00, 0xe6, 0x02, 0x29, 0x18,
+ 0xff, 0x82, 0x00, 0x00, 0xfd, 0x98, 0x72, 0xf0, 0xfc, 0x0c, 0x38, 0xd8, 0xff, 0x08, 0xd3, 0xd8,
+ 0xc0, 0x6e, 0xfa, 0x00, 0xfd, 0x0c, 0x71, 0xc0, 0xe6, 0x70, 0x00, 0x02, 0x5f, 0xf0, 0x00, 0x02,
+ 0x7f, 0xfd, 0x00, 0x0d, 0xff, 0xfb, 0x28, 0x0c, 0xf7, 0x82, 0x00, 0x50, 0xf7, 0xfb, 0x68, 0x08,
+ 0xff, 0x88, 0x9f, 0xfc, 0x7c, 0xe0, 0xff, 0xfe, 0x4e, 0xe4, 0x03, 0xff, 0x7f, 0xfd, 0x00, 0x0f,
+ 0xcf, 0xfc, 0xed, 0x00, 0xff, 0xfb, 0x28, 0x0e, 0xff, 0x82, 0x00, 0xff, 0xff, 0xfb, 0x28, 0x12,
+ 0x7e, 0x71, 0x00, 0x02, 0xcf, 0xf8, 0xe0, 0x00, 0x9d, 0xfa, 0x00, 0x14, 0x9d, 0x7e, 0x00, 0x14,
+ 0x0e, 0x70, 0x00, 0x10, 0xff, 0x8a, 0xcf, 0xd0, 0xad, 0xfe, 0xc8, 0x05, 0xfd, 0x08, 0xcd, 0xd8,
+ 0xfe, 0xfb, 0x18, 0x0a, 0xff, 0xa6, 0x00, 0x0e, 0x8c, 0xfa, 0x00, 0x2c, 0x9f, 0xfa, 0x00, 0x30,
+ 0x0f, 0x81, 0x80, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x9c, 0x02, 0xfe, 0x58, 0xfc, 0x7b, 0x28, 0x22,
+ 0xfb, 0xfb, 0x28, 0x20, 0xfb, 0xfb, 0x28, 0x1e, 0x0f, 0xf8, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0x71, 0x10, 0x00, 0x9e, 0x02, 0xfe, 0x58, 0xff, 0x8a, 0x23, 0xd0, 0x9f, 0xfa, 0x00, 0x04,
+ 0xce, 0xf4, 0xd8, 0x00, 0xfc, 0x89, 0xd3, 0xd8, 0x0d, 0xec, 0x00, 0x01, 0xfd, 0xfb, 0x28, 0x1c,
+ 0x4e, 0xf4, 0x0f, 0xff, 0xfe, 0xe7, 0x28, 0x00, 0x2f, 0xf4, 0x00, 0x01, 0x7d, 0xed, 0x00, 0x10,
+ 0xff, 0xfb, 0x28, 0x00, 0x9e, 0xe6, 0x00, 0x08, 0xcd, 0x68, 0xda, 0x00, 0xfd, 0x09, 0xcd, 0xd8,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0x4d, 0x69, 0x20, 0x00, 0xfb, 0xfb, 0x28, 0x02,
+ 0xc5, 0x28, 0xd5, 0x00, 0xff, 0x82, 0x00, 0x01, 0xcb, 0x58, 0xfa, 0x00, 0xfb, 0x1d, 0x33, 0x40,
+ 0xe0, 0x02, 0x25, 0xb0, 0xca, 0x50, 0xf8, 0x00, 0xff, 0x88, 0xcd, 0xd8, 0x20, 0x7f, 0x00, 0x3f,
+ 0xe6, 0x02, 0x2a, 0x14, 0x0f, 0x81, 0x1e, 0x00, 0xcd, 0xaa, 0xfc, 0x00, 0xe6, 0x02, 0x2a, 0x14,
+ 0x20, 0x56, 0xff, 0xfe, 0xe2, 0x02, 0x29, 0x51, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x82, 0xff, 0xff,
+ 0xfe, 0x0c, 0x6d, 0x80, 0x7f, 0xd1, 0x00, 0x10, 0xfe, 0x8c, 0x39, 0x20, 0xcf, 0xfc, 0xad, 0x00,
+ 0x0f, 0x70, 0x00, 0x04, 0xff, 0x8d, 0x38, 0xb0, 0xff, 0x09, 0xe8, 0x90, 0xff, 0x82, 0x00, 0x04,
+ 0xff, 0x0e, 0x38, 0xb0, 0xff, 0x89, 0xce, 0xc8, 0xfd, 0x8d, 0x72, 0x70, 0xfe, 0x89, 0xcd, 0xe8,
+ 0xfd, 0x9d, 0x33, 0x40, 0xfe, 0x89, 0xad, 0xb0, 0xfe, 0x09, 0xe5, 0xf0, 0xff, 0x09, 0xe6, 0x28,
+ 0xf7, 0x8a, 0x29, 0x9c, 0xe0, 0x00, 0xbf, 0xd8, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x8c, 0x71, 0xd0,
+ 0x20, 0x7e, 0x00, 0x20, 0xe6, 0x02, 0x29, 0xc5, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x09, 0xcf, 0xb8,
+ 0xf7, 0x8a, 0x29, 0xbc, 0xe0, 0x00, 0x7c, 0xf0, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x2a, 0x14,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa0, 0x4c, 0x20, 0x7e, 0x00, 0x05, 0xe2, 0x02, 0x29, 0xe4,
+ 0xff, 0x02, 0x00, 0x0a, 0xff, 0x88, 0xa0, 0x48, 0x20, 0x7e, 0x01, 0x2c, 0xe2, 0x02, 0x29, 0xad,
+ 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x29, 0xb0, 0xff, 0x09, 0xcf, 0xb8, 0xff, 0x88, 0xa0, 0x4c,
+ 0x20, 0x7e, 0x00, 0x05, 0xe2, 0x02, 0x2a, 0x0c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xa0, 0x48,
+ 0x20, 0x7e, 0x01, 0x2c, 0xe2, 0x02, 0x24, 0x61, 0x20, 0x5a, 0x00, 0x08, 0xe0, 0x02, 0x24, 0x5c,
+ 0xfb, 0x02, 0x00, 0x08, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x0c, 0x72, 0x70, 0x20, 0x7a, 0x00, 0x04,
+ 0xe6, 0x02, 0x2b, 0x11, 0x20, 0x7a, 0x00, 0x02, 0xe6, 0x02, 0x2a, 0xad, 0x20, 0x7a, 0x00, 0x03,
+ 0xe6, 0x02, 0x2a, 0x7d, 0x00, 0x00, 0x00, 0x01, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x2a, 0x48, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x72, 0x04,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x2a, 0x49, 0x00, 0x00, 0x00, 0x01, 0x70, 0x2a, 0x00, 0x0d,
+ 0xea, 0x02, 0x2a, 0x49, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x8a, 0x2a, 0xa4, 0xe0, 0x01, 0x17, 0xc8,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x2a, 0x48, 0x00, 0x00, 0x00, 0x01, 0xff, 0x88, 0xcd, 0xd8,
+ 0x20, 0x7f, 0x00, 0x3f, 0xe6, 0x02, 0x2a, 0x40, 0x20, 0x7a, 0x00, 0x03, 0x0f, 0x81, 0x1e, 0x04,
+ 0xc0, 0x2a, 0xfc, 0x00, 0xe6, 0x02, 0x2a, 0x40, 0x20, 0x7a, 0x00, 0x03, 0xff, 0x8c, 0x72, 0x04,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x2a, 0x41, 0x20, 0x7a, 0x00, 0x03, 0xff, 0x00, 0x04, 0x1c,
+ 0xff, 0x8e, 0x38, 0xe0, 0x55, 0x28, 0x01, 0x00, 0xf7, 0x82, 0x00, 0x01, 0xf7, 0xff, 0x68, 0x3e,
+ 0xf7, 0x82, 0x00, 0x01, 0xf7, 0xff, 0x68, 0x3d, 0xff, 0x82, 0x00, 0x03, 0xff, 0x8d, 0x72, 0x70,
+ 0xc1, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x2a, 0x48, 0x00, 0x00, 0x00, 0x01,
+ 0xf7, 0x8a, 0x2b, 0x1c, 0xe0, 0x02, 0x24, 0x34, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x2a, 0x48,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xe0, 0x02, 0x2b, 0x38, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x2b, 0x54, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x45, 0x28, 0xfd, 0xff,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x2b, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x1c, 0x33, 0x20, 0x4f, 0xa8, 0xfd, 0xc0,
+ 0xfe, 0xfb, 0x58, 0x0f, 0xc5, 0x7c, 0xed, 0x00, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x2b, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0x0c, 0x6d, 0x90, 0xfc, 0x9c, 0x33, 0x20, 0xff, 0x82, 0x00, 0x0c, 0xce, 0xa8, 0xfc, 0x00,
+ 0xa9, 0xea, 0xe8, 0x02, 0x4f, 0x29, 0x1e, 0x00, 0x0d, 0xe4, 0x00, 0x10, 0x7f, 0x78, 0xff, 0xe7,
+ 0x4d, 0xec, 0xbf, 0xff, 0x0f, 0x78, 0x07, 0x48, 0x8e, 0xea, 0x00, 0x24, 0xfa, 0xef, 0x58, 0x0f,
+ 0xfb, 0x7b, 0x58, 0x00, 0x8c, 0x6a, 0x00, 0x3c, 0xfe, 0x67, 0x18, 0x0a, 0x8b, 0xe6, 0x00, 0x04,
+ 0xfa, 0x02, 0x00, 0x00, 0xfa, 0x67, 0x68, 0x0f, 0xcc, 0x60, 0xe8, 0x00, 0xfd, 0x9d, 0x33, 0x20,
+ 0xce, 0xf4, 0xe0, 0x00, 0x9e, 0xea, 0x00, 0x24, 0xff, 0xe7, 0x58, 0x0e, 0x49, 0x5c, 0xff, 0xf8,
+ 0xcb, 0xdc, 0x92, 0x00, 0x4f, 0x28, 0xfd, 0xc0, 0x7e, 0xdd, 0x00, 0x0d, 0x7f, 0xfd, 0x00, 0x10,
+ 0xcf, 0x78, 0xad, 0x00, 0xcf, 0xfc, 0xed, 0x00, 0x05, 0x79, 0x02, 0x20, 0xcf, 0xfc, 0xe5, 0x00,
+ 0x8d, 0x66, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8, 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x5c, 0x61, 0x80, 0x00, 0x9c, 0x02, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x6a, 0xa2, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xce, 0x70, 0xb8, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e, 0x9d, 0x6e, 0x00, 0x14,
+ 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x99, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9a, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0,
+ 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0xfa, 0x6f, 0x28, 0x02, 0x9a, 0x02, 0xff, 0x00, 0x7b, 0x59, 0x00, 0x02, 0x99, 0xda, 0x07, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x2d, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x4f, 0x29, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c,
+ 0xfe, 0x9c, 0x33, 0x20, 0xcd, 0xa8, 0xfc, 0x00, 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0xf8, 0x07, 0x48,
+ 0xfb, 0x7f, 0x58, 0x00, 0xfd, 0x0e, 0x69, 0x40, 0xaa, 0x6a, 0xd8, 0x02, 0x0e, 0x74, 0x00, 0x10,
+ 0x4e, 0x70, 0xbf, 0xff, 0xfa, 0xf3, 0x58, 0x0f, 0xff, 0xf7, 0x58, 0x0d, 0xfb, 0x8c, 0x6d, 0x90,
+ 0x8c, 0xf6, 0x00, 0x04, 0xfd, 0xf7, 0x18, 0x0a, 0xfc, 0x77, 0x18, 0x08, 0x7f, 0x79, 0x00, 0x10,
+ 0xf0, 0x77, 0x68, 0x0f, 0xcf, 0xfc, 0xf5, 0x00, 0xfe, 0x1d, 0x33, 0x20, 0xff, 0x06, 0x37, 0x50,
+ 0x9d, 0x5e, 0x00, 0x38, 0x9f, 0x5e, 0x00, 0x34, 0xfc, 0x0d, 0x69, 0x6c, 0xff, 0x8d, 0x69, 0x60,
+ 0xfd, 0x8d, 0x69, 0x64, 0xff, 0xf7, 0x58, 0x0e, 0x4c, 0x64, 0xff, 0xf8, 0xcc, 0xe4, 0xc2, 0x00,
+ 0xff, 0x8d, 0x69, 0x80, 0xff, 0x8e, 0x6c, 0x40, 0xfd, 0x0d, 0x6d, 0x90, 0xf0, 0x0d, 0x69, 0x68,
+ 0xff, 0x8d, 0x69, 0x78, 0xff, 0xf7, 0x58, 0x0e, 0x7e, 0x65, 0x00, 0x0d, 0x4f, 0x28, 0xf9, 0xc0,
+ 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xad, 0x00, 0xcf, 0xfc, 0xe5, 0x00, 0x05, 0x79, 0x02, 0x20,
+ 0xcf, 0xfc, 0xdd, 0x00, 0x8b, 0xf6, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfe, 0x08, 0xd3, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x00, 0x02,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5e, 0xd2, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe,
+ 0xff, 0x7f, 0x18, 0x00, 0xcd, 0xec, 0xc8, 0x00, 0x0d, 0xec, 0x00, 0x07, 0x4d, 0xec, 0x0f, 0xf8,
+ 0x7d, 0xec, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xdd, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xf0, 0xe8, 0x00, 0xff, 0x73, 0x28, 0x0e, 0x9b, 0xf2, 0x00, 0x14, 0xfb, 0x73, 0x68, 0x12,
+ 0xf0, 0xf3, 0x68, 0x13, 0x9c, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x72, 0x00, 0x30,
+ 0xff, 0x73, 0x18, 0x0a, 0x8d, 0xf2, 0x00, 0x2c, 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00,
+ 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x73, 0x28, 0x02,
+ 0x9d, 0x02, 0xff, 0x00, 0x7b, 0x59, 0x00, 0x02, 0x9a, 0x5a, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x2f, 0x3c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x4f, 0x29, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c, 0xfe, 0x9c, 0x33, 0x20,
+ 0xcd, 0xa8, 0xfc, 0x00, 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0xf8, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00,
+ 0xfd, 0x0e, 0x69, 0xc0, 0xaa, 0x6a, 0xd8, 0x02, 0x0e, 0x74, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff,
+ 0xfa, 0xf3, 0x58, 0x0f, 0xff, 0xf7, 0x58, 0x0d, 0xfb, 0x8c, 0x6d, 0x90, 0x8c, 0xf6, 0x00, 0x04,
+ 0xfd, 0xf7, 0x18, 0x0a, 0xfc, 0x77, 0x18, 0x08, 0x7f, 0x79, 0x00, 0x10, 0xf0, 0x77, 0x68, 0x0f,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xfe, 0x1d, 0x33, 0x20, 0xff, 0x06, 0x37, 0xa8, 0x9d, 0x5e, 0x00, 0x38,
+ 0x9f, 0x5e, 0x00, 0x34, 0xfc, 0x0d, 0x69, 0xec, 0xff, 0x8d, 0x69, 0xe0, 0xfd, 0x8d, 0x69, 0xe4,
+ 0xff, 0xf7, 0x58, 0x0e, 0x4c, 0x64, 0xff, 0xf8, 0xcc, 0xe4, 0xc2, 0x00, 0xff, 0x8d, 0x6a, 0x00,
+ 0xff, 0x8e, 0x6c, 0x40, 0xfd, 0x0d, 0x6d, 0x90, 0xf0, 0x0d, 0x69, 0xe8, 0xff, 0x8d, 0x69, 0xf8,
+ 0xff, 0xf7, 0x58, 0x0e, 0x7e, 0x65, 0x00, 0x0d, 0x4f, 0x28, 0xf5, 0xc0, 0x7f, 0xfd, 0x00, 0x10,
+ 0xcf, 0x78, 0xad, 0x00, 0xcf, 0xfc, 0xe5, 0x00, 0x05, 0x79, 0x02, 0x20, 0xcf, 0xfc, 0xdd, 0x00,
+ 0x8b, 0xf6, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfe, 0x08, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x05, 0xf2, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5e, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00,
+ 0xcd, 0xec, 0xc8, 0x00, 0x0d, 0xec, 0x00, 0x07, 0x4d, 0xec, 0x0f, 0xf8, 0x7d, 0xec, 0xff, 0xfe,
+ 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xdd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xf0, 0xe8, 0x00,
+ 0xff, 0x73, 0x28, 0x0e, 0x9b, 0xf2, 0x00, 0x14, 0xfb, 0x73, 0x68, 0x12, 0xf0, 0xf3, 0x68, 0x13,
+ 0x9c, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x72, 0x00, 0x30, 0xff, 0x73, 0x18, 0x0a,
+ 0x8d, 0xf2, 0x00, 0x2c, 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfd, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00, 0x9f, 0x6e, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x73, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00,
+ 0x7b, 0x59, 0x00, 0x02, 0x9a, 0x5a, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x30, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x4f, 0x29, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c, 0xfe, 0x9c, 0x33, 0x20, 0xcd, 0xa8, 0xfc, 0x00,
+ 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0xf8, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00, 0xfd, 0x0e, 0x6a, 0x40,
+ 0xaa, 0x6a, 0xd8, 0x02, 0x0e, 0x74, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfa, 0xf3, 0x58, 0x0f,
+ 0xff, 0xf7, 0x58, 0x0d, 0xfb, 0x8c, 0x6d, 0x90, 0x8c, 0xf6, 0x00, 0x04, 0xfd, 0xf7, 0x18, 0x0a,
+ 0xfc, 0x77, 0x18, 0x08, 0x7f, 0x79, 0x00, 0x10, 0xf0, 0x77, 0x68, 0x0f, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xfe, 0x1d, 0x33, 0x20, 0xff, 0x06, 0x38, 0x00, 0x9d, 0x5e, 0x00, 0x38, 0x9f, 0x5e, 0x00, 0x34,
+ 0xfc, 0x0d, 0x6a, 0x6c, 0xff, 0x8d, 0x6a, 0x60, 0xfd, 0x8d, 0x6a, 0x64, 0xff, 0xf7, 0x58, 0x0e,
+ 0x4c, 0x64, 0xff, 0xf8, 0xcc, 0xe4, 0xc2, 0x00, 0xff, 0x8d, 0x6a, 0x80, 0xff, 0x8e, 0x6c, 0x40,
+ 0xfd, 0x0d, 0x6d, 0x90, 0xf0, 0x0d, 0x6a, 0x68, 0xff, 0x8d, 0x6a, 0x78, 0xff, 0xf7, 0x58, 0x0e,
+ 0x7e, 0x65, 0x00, 0x0d, 0x4f, 0x28, 0xed, 0xc0, 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xad, 0x00,
+ 0xcf, 0xfc, 0xe5, 0x00, 0x05, 0x79, 0x02, 0x20, 0xcf, 0xfc, 0xdd, 0x00, 0x8b, 0xf6, 0x00, 0x00,
+ 0xfd, 0x02, 0x00, 0x00, 0xfe, 0x08, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x59, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x0b, 0xe2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5e, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xcd, 0xec, 0xc8, 0x00,
+ 0x0d, 0xec, 0x00, 0x07, 0x4d, 0xec, 0x0f, 0xf8, 0x7d, 0xec, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f,
+ 0xcf, 0x78, 0xdd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xf0, 0xe8, 0x00, 0xff, 0x73, 0x28, 0x0e,
+ 0x9b, 0xf2, 0x00, 0x14, 0xfb, 0x73, 0x68, 0x12, 0xf0, 0xf3, 0x68, 0x13, 0x9c, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x72, 0x00, 0x30, 0xff, 0x73, 0x18, 0x0a, 0x8d, 0xf2, 0x00, 0x2c,
+ 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00, 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28,
+ 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x73, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00, 0x7b, 0x59, 0x00, 0x02,
+ 0x9a, 0x5a, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x32, 0xb4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x4f, 0x29, 0x1e, 0x00,
+ 0xff, 0x82, 0x00, 0x0c, 0xfe, 0x9c, 0x33, 0x20, 0xcd, 0xa8, 0xfc, 0x00, 0x7f, 0x78, 0xff, 0xe7,
+ 0x0f, 0xf8, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00, 0xfd, 0x0e, 0x6a, 0xc0, 0xaa, 0x6a, 0xd8, 0x02,
+ 0x0e, 0x74, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfa, 0xf3, 0x58, 0x0f, 0xff, 0xf7, 0x58, 0x0d,
+ 0xfb, 0x8c, 0x6d, 0x90, 0x8c, 0xf6, 0x00, 0x04, 0xfd, 0xf7, 0x18, 0x0a, 0xfc, 0x77, 0x18, 0x08,
+ 0x7f, 0x79, 0x00, 0x10, 0xf0, 0x77, 0x68, 0x0f, 0xcf, 0xfc, 0xf5, 0x00, 0xfe, 0x1d, 0x33, 0x20,
+ 0xff, 0x06, 0x38, 0x58, 0x9d, 0x5e, 0x00, 0x38, 0x9f, 0x5e, 0x00, 0x34, 0xfc, 0x0d, 0x6a, 0xec,
+ 0xff, 0x8d, 0x6a, 0xe0, 0xfd, 0x8d, 0x6a, 0xe4, 0xff, 0xf7, 0x58, 0x0e, 0x4c, 0x64, 0xff, 0xf8,
+ 0xcc, 0xe4, 0xc2, 0x00, 0xff, 0x8d, 0x6b, 0x00, 0xff, 0x8e, 0x6c, 0x40, 0xfd, 0x0d, 0x6d, 0x90,
+ 0xf0, 0x0d, 0x6a, 0xe8, 0xff, 0x8d, 0x6a, 0xf8, 0xff, 0xf7, 0x58, 0x0e, 0x7e, 0x65, 0x00, 0x0d,
+ 0x4f, 0x28, 0xdd, 0xc0, 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xad, 0x00, 0xcf, 0xfc, 0xe5, 0x00,
+ 0x05, 0x79, 0x02, 0x20, 0xcf, 0xfc, 0xdd, 0x00, 0x8b, 0xf6, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x00,
+ 0xfe, 0x08, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x11, 0xd2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x5e, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xf3, 0x28, 0x0c,
+ 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xcd, 0xec, 0xc8, 0x00, 0x0d, 0xec, 0x00, 0x07,
+ 0x4d, 0xec, 0x0f, 0xf8, 0x7d, 0xec, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xdd, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xf0, 0xe8, 0x00, 0xff, 0x73, 0x28, 0x0e, 0x9b, 0xf2, 0x00, 0x14,
+ 0xfb, 0x73, 0x68, 0x12, 0xf0, 0xf3, 0x68, 0x13, 0x9c, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9d, 0x72, 0x00, 0x30, 0xff, 0x73, 0x18, 0x0a, 0x8d, 0xf2, 0x00, 0x2c, 0x0f, 0xf0, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0,
+ 0x9f, 0xf2, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x6f, 0x28, 0x00, 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfd, 0x73, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00, 0x7b, 0x59, 0x00, 0x02, 0x9a, 0x5a, 0x07, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x34, 0x70,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x4f, 0x29, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c,
+ 0xfe, 0x9c, 0x33, 0x20, 0xcd, 0xa8, 0xfc, 0x00, 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0xf8, 0x07, 0x48,
+ 0xfb, 0x7f, 0x58, 0x00, 0xfd, 0x0e, 0x6b, 0x40, 0xaa, 0x6a, 0xd8, 0x02, 0x0e, 0x74, 0x00, 0x10,
+ 0x4e, 0x70, 0xbf, 0xff, 0xfa, 0xf3, 0x58, 0x0f, 0xff, 0xf7, 0x58, 0x0d, 0xfb, 0x8c, 0x6d, 0x90,
+ 0x8c, 0xf6, 0x00, 0x04, 0xfd, 0xf7, 0x18, 0x0a, 0xfc, 0x77, 0x18, 0x08, 0x7f, 0x79, 0x00, 0x10,
+ 0xf0, 0x77, 0x68, 0x0f, 0xcf, 0xfc, 0xf5, 0x00, 0xfe, 0x1d, 0x33, 0x20, 0xff, 0x06, 0x38, 0xb0,
+ 0x9d, 0x5e, 0x00, 0x38, 0x9f, 0x5e, 0x00, 0x34, 0xfc, 0x0d, 0x6b, 0x6c, 0xff, 0x8d, 0x6b, 0x60,
+ 0xfd, 0x8d, 0x6b, 0x64, 0xff, 0xf7, 0x58, 0x0e, 0x4c, 0x64, 0xff, 0xf8, 0xcc, 0xe4, 0xc2, 0x00,
+ 0xff, 0x8d, 0x6b, 0x80, 0xff, 0x8e, 0x6c, 0x40, 0xfd, 0x0d, 0x6d, 0x90, 0xf0, 0x0d, 0x6b, 0x68,
+ 0xff, 0x8d, 0x6b, 0x78, 0xff, 0xf7, 0x58, 0x0e, 0x7e, 0x65, 0x00, 0x0d, 0x4f, 0x28, 0xbd, 0xc0,
+ 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xad, 0x00, 0xcf, 0xfc, 0xe5, 0x00, 0x05, 0x79, 0x02, 0x20,
+ 0xcf, 0xfc, 0xdd, 0x00, 0x8b, 0xf6, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfe, 0x08, 0xd3, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x36, 0x8a,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5e, 0xd2, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe,
+ 0xff, 0x7f, 0x18, 0x00, 0xcd, 0xec, 0xc8, 0x00, 0x0d, 0xec, 0x00, 0x07, 0x4d, 0xec, 0x0f, 0xf8,
+ 0x7d, 0xec, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xdd, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xf0, 0xe8, 0x00, 0xff, 0x73, 0x28, 0x0e, 0x9b, 0xf2, 0x00, 0x14, 0xfb, 0x73, 0x68, 0x12,
+ 0xf0, 0xf3, 0x68, 0x13, 0x9c, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x72, 0x00, 0x30,
+ 0xff, 0x73, 0x18, 0x0a, 0x8d, 0xf2, 0x00, 0x2c, 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00,
+ 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x73, 0x28, 0x02,
+ 0x9d, 0x02, 0xff, 0x00, 0x7b, 0x59, 0x00, 0x02, 0x9a, 0x5a, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x36, 0x2c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x4f, 0x29, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c, 0xfe, 0x9c, 0x33, 0x20,
+ 0xcd, 0xa8, 0xfc, 0x00, 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0xf8, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00,
+ 0xfd, 0x0e, 0x6b, 0xc0, 0xaa, 0x6a, 0xd8, 0x02, 0x0e, 0x74, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff,
+ 0xfa, 0xf3, 0x58, 0x0f, 0xff, 0xf7, 0x58, 0x0d, 0xfb, 0x8c, 0x6d, 0x90, 0x8c, 0xf6, 0x00, 0x04,
+ 0xfd, 0xf7, 0x18, 0x0a, 0xfc, 0x77, 0x18, 0x08, 0x7f, 0x79, 0x00, 0x10, 0xf0, 0x77, 0x68, 0x0f,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xfe, 0x1d, 0x33, 0x20, 0xff, 0x06, 0x39, 0x08, 0x9d, 0x5e, 0x00, 0x38,
+ 0x9f, 0x5e, 0x00, 0x34, 0xfc, 0x0d, 0x6b, 0xec, 0xff, 0x8d, 0x6b, 0xe0, 0xfd, 0x8d, 0x6b, 0xe4,
+ 0xff, 0xf7, 0x58, 0x0e, 0x4c, 0x64, 0xff, 0xf8, 0xcc, 0xe4, 0xc2, 0x00, 0xff, 0x8d, 0x6c, 0x00,
+ 0xff, 0x8e, 0x6c, 0x40, 0xfd, 0x0d, 0x6d, 0x90, 0xf0, 0x0d, 0x6b, 0xe8, 0xff, 0x8d, 0x6b, 0xf8,
+ 0xff, 0xf7, 0x58, 0x0e, 0x7e, 0x65, 0x00, 0x0d, 0x4f, 0x28, 0x7d, 0xc0, 0x7f, 0xfd, 0x00, 0x10,
+ 0xcf, 0x78, 0xad, 0x00, 0xcf, 0xfc, 0xe5, 0x00, 0x05, 0x79, 0x02, 0x20, 0xcf, 0xfc, 0xdd, 0x00,
+ 0x8b, 0xf6, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfe, 0x08, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0x59, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x5b, 0x42, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5e, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00,
+ 0xcd, 0xec, 0xc8, 0x00, 0x0d, 0xec, 0x00, 0x07, 0x4d, 0xec, 0x0f, 0xf8, 0x7d, 0xec, 0xff, 0xfe,
+ 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xdd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xf0, 0xe8, 0x00,
+ 0xff, 0x73, 0x28, 0x0e, 0x9b, 0xf2, 0x00, 0x14, 0xfb, 0x73, 0x68, 0x12, 0xf0, 0xf3, 0x68, 0x13,
+ 0x9c, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x72, 0x00, 0x30, 0xff, 0x73, 0x18, 0x0a,
+ 0x8d, 0xf2, 0x00, 0x2c, 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfd, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00, 0x9f, 0x6e, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x73, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00,
+ 0x7b, 0x59, 0x00, 0x02, 0x9a, 0x5a, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x37, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x4f, 0x29, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c, 0xfe, 0x9c, 0x33, 0x20, 0xcd, 0xa8, 0xfc, 0x00,
+ 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0xf8, 0x07, 0x48, 0xfb, 0xff, 0x58, 0x00, 0xfc, 0x0e, 0x69, 0x40,
+ 0xaa, 0x62, 0xd8, 0x02, 0x0e, 0x74, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfb, 0x73, 0x58, 0x0f,
+ 0xff, 0xf7, 0x58, 0x0d, 0x8c, 0xf6, 0x00, 0x04, 0xfd, 0xf7, 0x18, 0x0a, 0xfd, 0x77, 0x18, 0x08,
+ 0x7f, 0x79, 0x00, 0x10, 0xf0, 0x77, 0x68, 0x0f, 0xcf, 0xfc, 0xf5, 0x00, 0xff, 0x8d, 0x69, 0x60,
+ 0xff, 0x86, 0x37, 0x50, 0xfe, 0x1d, 0x33, 0x20, 0xfd, 0x0d, 0x69, 0x6c, 0xfd, 0x8d, 0x69, 0x64,
+ 0xff, 0x81, 0x04, 0x14, 0xff, 0xf7, 0x58, 0x0e, 0x4a, 0xe4, 0xff, 0xf8, 0xcc, 0xe4, 0xaa, 0x00,
+ 0xff, 0x8d, 0x69, 0x80, 0xff, 0x8e, 0x6c, 0x40, 0xfc, 0x0d, 0x6d, 0x90, 0xf0, 0x0d, 0x69, 0x68,
+ 0xff, 0x8d, 0x69, 0x78, 0xff, 0xf7, 0x58, 0x0e, 0x7e, 0x65, 0x00, 0x0d, 0x4f, 0x28, 0xf9, 0xc0,
+ 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xb5, 0x00, 0xcf, 0xfc, 0xe5, 0x00, 0x05, 0x79, 0x02, 0x20,
+ 0xcf, 0xfc, 0xdd, 0x00, 0x8c, 0x76, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfe, 0x08, 0xd3, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x00, 0x02,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x62, 0xd2, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe,
+ 0xff, 0x7f, 0x18, 0x00, 0xcd, 0xec, 0xc8, 0x00, 0x0d, 0xec, 0x00, 0x07, 0x4d, 0xec, 0x0f, 0xf8,
+ 0x7d, 0xec, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xdd, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xf0, 0xe8, 0x00, 0xff, 0x73, 0x28, 0x0e, 0x9c, 0x72, 0x00, 0x14, 0xfb, 0xf3, 0x68, 0x12,
+ 0xf0, 0xf3, 0x68, 0x13, 0x9a, 0xfe, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x72, 0x00, 0x30,
+ 0xff, 0x73, 0x18, 0x0a, 0x8d, 0xf2, 0x00, 0x2c, 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00,
+ 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0xfd, 0x73, 0x28, 0x02,
+ 0x9d, 0x02, 0xff, 0x00, 0x7b, 0xdd, 0x00, 0x02, 0x9a, 0x5e, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x39, 0x9c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x4f, 0x29, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c, 0xfe, 0x9c, 0x33, 0x20,
+ 0xcd, 0xa8, 0xfc, 0x00, 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0xf8, 0x07, 0x48, 0xfb, 0xff, 0x58, 0x00,
+ 0xfc, 0x0e, 0x6a, 0xc0, 0xaa, 0x62, 0xd8, 0x02, 0x0e, 0x74, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff,
+ 0xfb, 0x73, 0x58, 0x0f, 0xff, 0xf7, 0x58, 0x0d, 0x8c, 0xf6, 0x00, 0x04, 0xfd, 0xf7, 0x18, 0x0a,
+ 0xfd, 0x77, 0x18, 0x08, 0x7f, 0x79, 0x00, 0x10, 0xf0, 0x77, 0x68, 0x0f, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xff, 0x8d, 0x6a, 0xe0, 0xff, 0x86, 0x38, 0x58, 0xfe, 0x1d, 0x33, 0x20, 0xfd, 0x0d, 0x6a, 0xec,
+ 0xfd, 0x8d, 0x6a, 0xe4, 0xff, 0x81, 0x04, 0x14, 0xff, 0xf7, 0x58, 0x0e, 0x4a, 0xe4, 0xff, 0xf8,
+ 0xcc, 0xe4, 0xaa, 0x00, 0xff, 0x8d, 0x6b, 0x00, 0xff, 0x8e, 0x6c, 0x40, 0xfc, 0x0d, 0x6d, 0x90,
+ 0xf0, 0x0d, 0x6a, 0xe8, 0xff, 0x8d, 0x6a, 0xf8, 0xff, 0xf7, 0x58, 0x0e, 0x7e, 0x65, 0x00, 0x0d,
+ 0x4f, 0x28, 0xdd, 0xc0, 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xb5, 0x00, 0xcf, 0xfc, 0xe5, 0x00,
+ 0x05, 0x79, 0x02, 0x20, 0xcf, 0xfc, 0xdd, 0x00, 0x8c, 0x76, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x00,
+ 0xfe, 0x08, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x11, 0xd2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x62, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xf3, 0x28, 0x0c,
+ 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xcd, 0xec, 0xc8, 0x00, 0x0d, 0xec, 0x00, 0x07,
+ 0x4d, 0xec, 0x0f, 0xf8, 0x7d, 0xec, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xdd, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xf0, 0xe8, 0x00, 0xff, 0x73, 0x28, 0x0e, 0x9c, 0x72, 0x00, 0x14,
+ 0xfb, 0xf3, 0x68, 0x12, 0xf0, 0xf3, 0x68, 0x13, 0x9a, 0xfe, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9d, 0x72, 0x00, 0x30, 0xff, 0x73, 0x18, 0x0a, 0x8d, 0xf2, 0x00, 0x2c, 0x0f, 0xf0, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0,
+ 0x9f, 0xf2, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x6f, 0x28, 0x00, 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0xfd, 0x73, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00, 0x7b, 0xdd, 0x00, 0x02, 0x9a, 0x5e, 0x07, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x3b, 0x50,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfd, 0x1c, 0x33, 0x20, 0xfd, 0x8c, 0x6d, 0x90,
+ 0x4f, 0xa9, 0x1e, 0x00, 0x0e, 0xe8, 0x00, 0x10, 0x7f, 0xfc, 0xff, 0xe7, 0x4e, 0xf4, 0xbf, 0xff,
+ 0x0f, 0xfc, 0x07, 0x48, 0x8f, 0x6e, 0x00, 0x24, 0xfb, 0x77, 0x58, 0x0f, 0xfb, 0xff, 0x58, 0x00,
+ 0x8c, 0xee, 0x00, 0x3c, 0x8a, 0x6e, 0x00, 0x04, 0xfe, 0x6b, 0x18, 0x0a, 0x8c, 0x6a, 0x00, 0x04,
+ 0xfa, 0x82, 0x00, 0x00, 0xfa, 0xeb, 0x68, 0x0f, 0xcc, 0xe4, 0xf0, 0x00, 0xfe, 0x9d, 0x33, 0x20,
+ 0xcf, 0x78, 0xe0, 0x00, 0x9f, 0x6e, 0x00, 0x24, 0xff, 0xeb, 0x58, 0x0e, 0x49, 0xe0, 0xff, 0xf8,
+ 0xcc, 0x60, 0x9a, 0x00, 0x4f, 0x28, 0xfd, 0xc0, 0x7e, 0xe1, 0x00, 0x0d, 0x7f, 0xfd, 0x00, 0x10,
+ 0xcf, 0x78, 0xb5, 0x00, 0xcf, 0xfc, 0xed, 0x00, 0x05, 0x79, 0x02, 0x20, 0xcf, 0xfc, 0xe5, 0x00,
+ 0x8b, 0x6a, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8, 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x5c, 0xe5, 0x80, 0x00, 0x9c, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x5a, 0xaa, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xce, 0x70, 0xc0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e, 0xf0, 0xef, 0x68, 0x13,
+ 0x9b, 0x6e, 0x00, 0x14, 0xfb, 0xef, 0x68, 0x12, 0x99, 0xfe, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9a, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0,
+ 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0,
+ 0xfa, 0xef, 0x28, 0x02, 0x9a, 0x82, 0xff, 0x00, 0x7b, 0xdd, 0x00, 0x02, 0x9a, 0x5e, 0x07, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x3c, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x9c, 0x33, 0x20, 0x4f, 0x29, 0x1e, 0x00,
+ 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0xf8, 0x07, 0x48, 0xfb, 0xff, 0x58, 0x00, 0x0e, 0x74, 0x00, 0x10,
+ 0x4e, 0x70, 0xbf, 0xff, 0xfb, 0x73, 0x58, 0x0f, 0xfc, 0x8c, 0x6d, 0x90, 0xfa, 0x8c, 0x69, 0x44,
+ 0x8d, 0x76, 0x00, 0x04, 0xfd, 0xf7, 0x18, 0x0a, 0xff, 0xf7, 0x58, 0x0d, 0xfc, 0x77, 0x18, 0x08,
+ 0xf0, 0x77, 0x68, 0x0f, 0x7f, 0x79, 0x00, 0x10, 0xfe, 0x1d, 0x33, 0x20, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xfe, 0x0e, 0x69, 0x40, 0xff, 0x06, 0x39, 0x60, 0x9e, 0x66, 0x00, 0x38, 0x9f, 0x66, 0x00, 0x34,
+ 0xfc, 0x0d, 0x69, 0x6c, 0xff, 0x8d, 0x69, 0x60, 0xfd, 0x8d, 0x69, 0x64, 0xff, 0xf7, 0x58, 0x0e,
+ 0x4c, 0x68, 0xff, 0xf8, 0xcd, 0x68, 0xc2, 0x00, 0xff, 0x8d, 0x69, 0x80, 0xff, 0x8e, 0x6c, 0x40,
+ 0xfe, 0x0d, 0x6d, 0x90, 0xf0, 0x0d, 0x69, 0x68, 0xff, 0x8d, 0x69, 0x78, 0xff, 0xf7, 0x58, 0x0e,
+ 0x7e, 0x69, 0x00, 0x0d, 0x4f, 0x28, 0xf9, 0xc0, 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xb5, 0x00,
+ 0xcf, 0xfc, 0xe5, 0x00, 0x05, 0x79, 0x02, 0x20, 0xcf, 0xfc, 0xdd, 0x00, 0x8b, 0x76, 0x00, 0x00,
+ 0xfc, 0x82, 0x00, 0x00, 0xfe, 0x08, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x00, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5a, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xcd, 0xec, 0xd0, 0x00,
+ 0x0d, 0xec, 0x00, 0x07, 0x4d, 0xec, 0x0f, 0xf8, 0x7d, 0xec, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f,
+ 0xcf, 0x78, 0xdd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xf0, 0xe8, 0x00, 0xff, 0x73, 0x28, 0x0e,
+ 0xf0, 0xf3, 0x68, 0x13, 0x9b, 0x72, 0x00, 0x14, 0xfb, 0xf3, 0x68, 0x12, 0x9c, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xf2, 0x00, 0x30, 0xff, 0x73, 0x18, 0x0a, 0x8d, 0xf2, 0x00, 0x2c,
+ 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00, 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28,
+ 0x9f, 0x02, 0xff, 0xb0, 0xfc, 0xf3, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7b, 0xdd, 0x00, 0x02,
+ 0x9a, 0xde, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x3e, 0x84, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x9c, 0x33, 0x20,
+ 0x4f, 0x29, 0x1e, 0x00, 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0xf8, 0x07, 0x48, 0xfb, 0xff, 0x58, 0x00,
+ 0x0e, 0x74, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfb, 0x73, 0x58, 0x0f, 0xfc, 0x8c, 0x6d, 0x90,
+ 0xfa, 0x8c, 0x69, 0xc4, 0x8d, 0x76, 0x00, 0x04, 0xfd, 0xf7, 0x18, 0x0a, 0xff, 0xf7, 0x58, 0x0d,
+ 0xfc, 0x77, 0x18, 0x08, 0xf0, 0x77, 0x68, 0x0f, 0x7f, 0x79, 0x00, 0x10, 0xfe, 0x1d, 0x33, 0x20,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xfe, 0x0e, 0x69, 0xc0, 0xff, 0x06, 0x39, 0xb4, 0x9e, 0x66, 0x00, 0x38,
+ 0x9f, 0x66, 0x00, 0x34, 0xfc, 0x0d, 0x69, 0xec, 0xff, 0x8d, 0x69, 0xe0, 0xfd, 0x8d, 0x69, 0xe4,
+ 0xff, 0xf7, 0x58, 0x0e, 0x4c, 0x68, 0xff, 0xf8, 0xcd, 0x68, 0xc2, 0x00, 0xff, 0x8d, 0x6a, 0x00,
+ 0xff, 0x8e, 0x6c, 0x40, 0xfe, 0x0d, 0x6d, 0x90, 0xf0, 0x0d, 0x69, 0xe8, 0xff, 0x8d, 0x69, 0xf8,
+ 0xff, 0xf7, 0x58, 0x0e, 0x7e, 0x69, 0x00, 0x0d, 0x4f, 0x28, 0xf5, 0xc0, 0x7f, 0xfd, 0x00, 0x10,
+ 0xcf, 0x78, 0xb5, 0x00, 0xcf, 0xfc, 0xe5, 0x00, 0x05, 0x79, 0x02, 0x20, 0xcf, 0xfc, 0xdd, 0x00,
+ 0x8b, 0x76, 0x00, 0x00, 0xfc, 0x82, 0x00, 0x00, 0xfe, 0x08, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x05, 0xf2, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5a, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00,
+ 0xcd, 0xec, 0xd0, 0x00, 0x0d, 0xec, 0x00, 0x07, 0x4d, 0xec, 0x0f, 0xf8, 0x7d, 0xec, 0xff, 0xfe,
+ 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xdd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xf0, 0xe8, 0x00,
+ 0xff, 0x73, 0x28, 0x0e, 0xf0, 0xf3, 0x68, 0x13, 0x9b, 0x72, 0x00, 0x14, 0xfb, 0xf3, 0x68, 0x12,
+ 0x9c, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xf2, 0x00, 0x30, 0xff, 0x73, 0x18, 0x0a,
+ 0x8d, 0xf2, 0x00, 0x2c, 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfd, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00, 0x9f, 0x6e, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfc, 0xf3, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00,
+ 0x7b, 0xdd, 0x00, 0x02, 0x9a, 0xde, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x40, 0x38, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfe, 0x9c, 0x33, 0x20, 0x4f, 0x29, 0x1e, 0x00, 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0xf8, 0x07, 0x48,
+ 0xfb, 0xff, 0x58, 0x00, 0x0e, 0x74, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfb, 0x73, 0x58, 0x0f,
+ 0xfc, 0x8c, 0x6d, 0x90, 0xfa, 0x8c, 0x6a, 0x44, 0x8d, 0x76, 0x00, 0x04, 0xfd, 0xf7, 0x18, 0x0a,
+ 0xff, 0xf7, 0x58, 0x0d, 0xfc, 0x77, 0x18, 0x08, 0xf0, 0x77, 0x68, 0x0f, 0x7f, 0x79, 0x00, 0x10,
+ 0xfe, 0x1d, 0x33, 0x20, 0xcf, 0xfc, 0xf5, 0x00, 0xfe, 0x0e, 0x6a, 0x40, 0xff, 0x06, 0x3a, 0x08,
+ 0x9e, 0x66, 0x00, 0x38, 0x9f, 0x66, 0x00, 0x34, 0xfc, 0x0d, 0x6a, 0x6c, 0xff, 0x8d, 0x6a, 0x60,
+ 0xfd, 0x8d, 0x6a, 0x64, 0xff, 0xf7, 0x58, 0x0e, 0x4c, 0x68, 0xff, 0xf8, 0xcd, 0x68, 0xc2, 0x00,
+ 0xff, 0x8d, 0x6a, 0x80, 0xff, 0x8e, 0x6c, 0x40, 0xfe, 0x0d, 0x6d, 0x90, 0xf0, 0x0d, 0x6a, 0x68,
+ 0xff, 0x8d, 0x6a, 0x78, 0xff, 0xf7, 0x58, 0x0e, 0x7e, 0x69, 0x00, 0x0d, 0x4f, 0x28, 0xed, 0xc0,
+ 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xb5, 0x00, 0xcf, 0xfc, 0xe5, 0x00, 0x05, 0x79, 0x02, 0x20,
+ 0xcf, 0xfc, 0xdd, 0x00, 0x8b, 0x76, 0x00, 0x00, 0xfc, 0x82, 0x00, 0x00, 0xfe, 0x08, 0xd3, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x0b, 0xe2,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5a, 0xca, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe,
+ 0xff, 0x7f, 0x18, 0x00, 0xcd, 0xec, 0xd0, 0x00, 0x0d, 0xec, 0x00, 0x07, 0x4d, 0xec, 0x0f, 0xf8,
+ 0x7d, 0xec, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xdd, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xf0, 0xe8, 0x00, 0xff, 0x73, 0x28, 0x0e, 0xf0, 0xf3, 0x68, 0x13, 0x9b, 0x72, 0x00, 0x14,
+ 0xfb, 0xf3, 0x68, 0x12, 0x9c, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xf2, 0x00, 0x30,
+ 0xff, 0x73, 0x18, 0x0a, 0x8d, 0xf2, 0x00, 0x2c, 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00,
+ 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfc, 0xf3, 0x28, 0x02,
+ 0x9c, 0x82, 0xff, 0x00, 0x7b, 0xdd, 0x00, 0x02, 0x9a, 0xde, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x41, 0xec, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfe, 0x9c, 0x33, 0x20, 0x4f, 0x29, 0x1e, 0x00, 0x7f, 0x78, 0xff, 0xe7,
+ 0x0f, 0xf8, 0x07, 0x48, 0xfb, 0xff, 0x58, 0x00, 0x0e, 0x74, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff,
+ 0xfb, 0x73, 0x58, 0x0f, 0xfc, 0x8c, 0x6d, 0x90, 0xfa, 0x8c, 0x6a, 0xc4, 0x8d, 0x76, 0x00, 0x04,
+ 0xfd, 0xf7, 0x18, 0x0a, 0xff, 0xf7, 0x58, 0x0d, 0xfc, 0x77, 0x18, 0x08, 0xf0, 0x77, 0x68, 0x0f,
+ 0x7f, 0x79, 0x00, 0x10, 0xfe, 0x1d, 0x33, 0x20, 0xcf, 0xfc, 0xf5, 0x00, 0xfe, 0x0e, 0x6a, 0xc0,
+ 0xff, 0x06, 0x3a, 0x5c, 0x9e, 0x66, 0x00, 0x38, 0x9f, 0x66, 0x00, 0x34, 0xfc, 0x0d, 0x6a, 0xec,
+ 0xff, 0x8d, 0x6a, 0xe0, 0xfd, 0x8d, 0x6a, 0xe4, 0xff, 0xf7, 0x58, 0x0e, 0x4c, 0x68, 0xff, 0xf8,
+ 0xcd, 0x68, 0xc2, 0x00, 0xff, 0x8d, 0x6b, 0x00, 0xff, 0x8e, 0x6c, 0x40, 0xfe, 0x0d, 0x6d, 0x90,
+ 0xf0, 0x0d, 0x6a, 0xe8, 0xff, 0x8d, 0x6a, 0xf8, 0xff, 0xf7, 0x58, 0x0e, 0x7e, 0x69, 0x00, 0x0d,
+ 0x4f, 0x28, 0xdd, 0xc0, 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xb5, 0x00, 0xcf, 0xfc, 0xe5, 0x00,
+ 0x05, 0x79, 0x02, 0x20, 0xcf, 0xfc, 0xdd, 0x00, 0x8b, 0x76, 0x00, 0x00, 0xfc, 0x82, 0x00, 0x00,
+ 0xfe, 0x08, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00,
+ 0x0e, 0xf4, 0x11, 0xd2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58,
+ 0xc0, 0x5a, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xf3, 0x28, 0x0c,
+ 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xcd, 0xec, 0xd0, 0x00, 0x0d, 0xec, 0x00, 0x07,
+ 0x4d, 0xec, 0x0f, 0xf8, 0x7d, 0xec, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xdd, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xf0, 0xe8, 0x00, 0xff, 0x73, 0x28, 0x0e, 0xf0, 0xf3, 0x68, 0x13,
+ 0x9b, 0x72, 0x00, 0x14, 0xfb, 0xf3, 0x68, 0x12, 0x9c, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9c, 0xf2, 0x00, 0x30, 0xff, 0x73, 0x18, 0x0a, 0x8d, 0xf2, 0x00, 0x2c, 0x0f, 0xf0, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0,
+ 0x9f, 0xf2, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x6f, 0x28, 0x00, 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfc, 0xf3, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7b, 0xdd, 0x00, 0x02, 0x9a, 0xde, 0x07, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x43, 0xa0,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x9c, 0x33, 0x20, 0x4f, 0x29, 0x1e, 0x00,
+ 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0xf8, 0x07, 0x48, 0xfb, 0xff, 0x58, 0x00, 0x0e, 0x74, 0x00, 0x10,
+ 0x4e, 0x70, 0xbf, 0xff, 0xfb, 0x73, 0x58, 0x0f, 0xfc, 0x8c, 0x6d, 0x90, 0xfa, 0x8c, 0x6b, 0x44,
+ 0x8d, 0x76, 0x00, 0x04, 0xfd, 0xf7, 0x18, 0x0a, 0xff, 0xf7, 0x58, 0x0d, 0xfc, 0x77, 0x18, 0x08,
+ 0xf0, 0x77, 0x68, 0x0f, 0x7f, 0x79, 0x00, 0x10, 0xfe, 0x1d, 0x33, 0x20, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xfe, 0x0e, 0x6b, 0x40, 0xff, 0x06, 0x3a, 0xb0, 0x9e, 0x66, 0x00, 0x38, 0x9f, 0x66, 0x00, 0x34,
+ 0xfc, 0x0d, 0x6b, 0x6c, 0xff, 0x8d, 0x6b, 0x60, 0xfd, 0x8d, 0x6b, 0x64, 0xff, 0xf7, 0x58, 0x0e,
+ 0x4c, 0x68, 0xff, 0xf8, 0xcd, 0x68, 0xc2, 0x00, 0xff, 0x8d, 0x6b, 0x80, 0xff, 0x8e, 0x6c, 0x40,
+ 0xfe, 0x0d, 0x6d, 0x90, 0xf0, 0x0d, 0x6b, 0x68, 0xff, 0x8d, 0x6b, 0x78, 0xff, 0xf7, 0x58, 0x0e,
+ 0x7e, 0x69, 0x00, 0x0d, 0x4f, 0x28, 0xbd, 0xc0, 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xb5, 0x00,
+ 0xcf, 0xfc, 0xe5, 0x00, 0x05, 0x79, 0x02, 0x20, 0xcf, 0xfc, 0xdd, 0x00, 0x8b, 0x76, 0x00, 0x00,
+ 0xfc, 0x82, 0x00, 0x00, 0xfe, 0x08, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x5d, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x36, 0x8a, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5a, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xcd, 0xec, 0xd0, 0x00,
+ 0x0d, 0xec, 0x00, 0x07, 0x4d, 0xec, 0x0f, 0xf8, 0x7d, 0xec, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f,
+ 0xcf, 0x78, 0xdd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xf0, 0xe8, 0x00, 0xff, 0x73, 0x28, 0x0e,
+ 0xf0, 0xf3, 0x68, 0x13, 0x9b, 0x72, 0x00, 0x14, 0xfb, 0xf3, 0x68, 0x12, 0x9c, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xf2, 0x00, 0x30, 0xff, 0x73, 0x18, 0x0a, 0x8d, 0xf2, 0x00, 0x2c,
+ 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00, 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28,
+ 0x9f, 0x02, 0xff, 0xb0, 0xfc, 0xf3, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00, 0x7b, 0xdd, 0x00, 0x02,
+ 0x9a, 0xde, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x45, 0x54, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfe, 0x9c, 0x33, 0x20,
+ 0x4f, 0x29, 0x1e, 0x00, 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0xf8, 0x07, 0x48, 0xfb, 0xff, 0x58, 0x00,
+ 0x0e, 0x74, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfb, 0x73, 0x58, 0x0f, 0xfc, 0x8c, 0x6d, 0x90,
+ 0xfa, 0x8c, 0x6b, 0xc4, 0x8d, 0x76, 0x00, 0x04, 0xfd, 0xf7, 0x18, 0x0a, 0xff, 0xf7, 0x58, 0x0d,
+ 0xfc, 0x77, 0x18, 0x08, 0xf0, 0x77, 0x68, 0x0f, 0x7f, 0x79, 0x00, 0x10, 0xfe, 0x1d, 0x33, 0x20,
+ 0xcf, 0xfc, 0xf5, 0x00, 0xfe, 0x0e, 0x6b, 0xc0, 0xff, 0x06, 0x3b, 0x04, 0x9e, 0x66, 0x00, 0x38,
+ 0x9f, 0x66, 0x00, 0x34, 0xfc, 0x0d, 0x6b, 0xec, 0xff, 0x8d, 0x6b, 0xe0, 0xfd, 0x8d, 0x6b, 0xe4,
+ 0xff, 0xf7, 0x58, 0x0e, 0x4c, 0x68, 0xff, 0xf8, 0xcd, 0x68, 0xc2, 0x00, 0xff, 0x8d, 0x6c, 0x00,
+ 0xff, 0x8e, 0x6c, 0x40, 0xfe, 0x0d, 0x6d, 0x90, 0xf0, 0x0d, 0x6b, 0xe8, 0xff, 0x8d, 0x6b, 0xf8,
+ 0xff, 0xf7, 0x58, 0x0e, 0x7e, 0x69, 0x00, 0x0d, 0x4f, 0x28, 0x7d, 0xc0, 0x7f, 0xfd, 0x00, 0x10,
+ 0xcf, 0x78, 0xb5, 0x00, 0xcf, 0xfc, 0xe5, 0x00, 0x05, 0x79, 0x02, 0x20, 0xcf, 0xfc, 0xdd, 0x00,
+ 0x8b, 0x76, 0x00, 0x00, 0xfc, 0x82, 0x00, 0x00, 0xfe, 0x08, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0x5d, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x5b, 0x42, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5a, 0xca, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00,
+ 0xcd, 0xec, 0xd0, 0x00, 0x0d, 0xec, 0x00, 0x07, 0x4d, 0xec, 0x0f, 0xf8, 0x7d, 0xec, 0xff, 0xfe,
+ 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xdd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xf0, 0xe8, 0x00,
+ 0xff, 0x73, 0x28, 0x0e, 0xf0, 0xf3, 0x68, 0x13, 0x9b, 0x72, 0x00, 0x14, 0xfb, 0xf3, 0x68, 0x12,
+ 0x9c, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9c, 0xf2, 0x00, 0x30, 0xff, 0x73, 0x18, 0x0a,
+ 0x8d, 0xf2, 0x00, 0x2c, 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfd, 0x89, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00, 0x9f, 0x6e, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfc, 0xf3, 0x28, 0x02, 0x9c, 0x82, 0xff, 0x00,
+ 0x7b, 0xdd, 0x00, 0x02, 0x9a, 0xde, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x47, 0x08, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x4f, 0x29, 0x1e, 0x00, 0xfe, 0x9c, 0x33, 0x20, 0x7f, 0x78, 0xff, 0xe7, 0x0f, 0xf8, 0x07, 0x48,
+ 0xfc, 0x7f, 0x58, 0x00, 0x0e, 0x74, 0x00, 0x10, 0x4e, 0x70, 0xbf, 0xff, 0xfb, 0xf3, 0x58, 0x0f,
+ 0xff, 0xf7, 0x58, 0x0d, 0xfa, 0x8c, 0x69, 0x44, 0x8c, 0xf6, 0x00, 0x04, 0xfd, 0xf7, 0x18, 0x0a,
+ 0xfd, 0x77, 0x18, 0x08, 0x7f, 0x79, 0x00, 0x10, 0xf0, 0x77, 0x68, 0x0f, 0xcf, 0xfc, 0xf5, 0x00,
+ 0xff, 0x8d, 0x69, 0x60, 0xff, 0x86, 0x39, 0x60, 0xfe, 0x1d, 0x33, 0x20, 0xfd, 0x0d, 0x69, 0x6c,
+ 0xfd, 0x8d, 0x69, 0x64, 0xff, 0x81, 0x04, 0x14, 0xff, 0xf7, 0x58, 0x0e, 0x4b, 0x64, 0xff, 0xf8,
+ 0xcc, 0xe4, 0xb2, 0x00, 0xff, 0x8d, 0x69, 0x80, 0xff, 0x8e, 0x6c, 0x40, 0xff, 0x8d, 0x69, 0x78,
+ 0xff, 0x8e, 0x69, 0x40, 0xf0, 0x0d, 0x69, 0x68, 0xff, 0x8d, 0x6d, 0x90, 0xff, 0xf7, 0x58, 0x0e,
+ 0x7e, 0x65, 0x00, 0x0d, 0x4f, 0x28, 0xf9, 0xc0, 0x7f, 0xfd, 0x00, 0x10, 0xcf, 0x78, 0xbd, 0x00,
+ 0xcf, 0xfc, 0xe5, 0x00, 0x05, 0x79, 0x02, 0x20, 0xcf, 0xfc, 0xdd, 0x00, 0x8b, 0xf6, 0x00, 0x00,
+ 0xfd, 0x02, 0x00, 0x00, 0xfe, 0x08, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0x61, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x0e, 0xf4, 0x00, 0x02, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x5e, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xf3, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xcd, 0xec, 0xc8, 0x00,
+ 0x0d, 0xec, 0x00, 0x07, 0x4d, 0xec, 0x0f, 0xf8, 0x7d, 0xec, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f,
+ 0xcf, 0x78, 0xdd, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xf0, 0xe8, 0x00, 0xff, 0x73, 0x28, 0x0e,
+ 0xf0, 0xf3, 0x68, 0x13, 0x9b, 0xf2, 0x00, 0x14, 0xfc, 0x73, 0x68, 0x12, 0x9b, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x72, 0x00, 0x30, 0xff, 0x73, 0x18, 0x0a, 0x8d, 0xf2, 0x00, 0x2c,
+ 0x0f, 0xf0, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xf2, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfd, 0x89, 0xd3, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x6f, 0x28, 0x00, 0x9f, 0x6e, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0xfd, 0x73, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00, 0x7c, 0x61, 0x00, 0x02,
+ 0x9a, 0xe2, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x48, 0xb4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x8c, 0x6d, 0x90,
+ 0xff, 0x82, 0x00, 0x0c, 0xfd, 0x1c, 0x33, 0x20, 0xce, 0xa8, 0xfc, 0x00, 0xce, 0xe4, 0xe8, 0x00,
+ 0x8a, 0x76, 0x00, 0x10, 0x4f, 0x29, 0x1e, 0x00, 0x0d, 0xe8, 0x00, 0x10, 0x7f, 0x78, 0xff, 0xe7,
+ 0x4d, 0xec, 0xbf, 0xff, 0x0f, 0x78, 0x07, 0x48, 0x8f, 0xe6, 0x00, 0x24, 0xfb, 0x6f, 0x58, 0x0f,
+ 0xfb, 0xfb, 0x58, 0x00, 0x8e, 0xe6, 0x00, 0x3c, 0x8c, 0x6a, 0x00, 0x04, 0xfe, 0x6b, 0x18, 0x0a,
+ 0xfa, 0x82, 0x00, 0x00, 0xfa, 0xeb, 0x68, 0x0f, 0xce, 0xf4, 0xf8, 0x00, 0xfd, 0x9d, 0x33, 0x20,
+ 0xcf, 0xfc, 0xe0, 0x00, 0x49, 0xe0, 0xff, 0xf8, 0x9f, 0xe6, 0x00, 0x24, 0x4f, 0x28, 0xfd, 0xc0,
+ 0xcc, 0x60, 0x9a, 0x00, 0xcf, 0x78, 0xb5, 0x00, 0x7f, 0xe1, 0x00, 0x0d, 0x05, 0x79, 0x02, 0x20,
+ 0x8c, 0xea, 0x00, 0x00, 0xcf, 0xfc, 0xe5, 0x00, 0xfd, 0x88, 0xd3, 0xd8, 0x7f, 0x5d, 0x00, 0x1c,
+ 0xcf, 0xfc, 0xf5, 0x00, 0x5e, 0xf5, 0x80, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0xfd, 0x08, 0x00,
+ 0x9f, 0x82, 0xfe, 0x58, 0xc0, 0x66, 0xaa, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xce, 0x70, 0xc0, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f,
+ 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e,
+ 0x9c, 0xee, 0x00, 0x14, 0xfb, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x99, 0xfe, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9a, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0xfa, 0xef, 0x28, 0x02, 0x9a, 0x82, 0xff, 0x00, 0x7b, 0xdd, 0x00, 0x02,
+ 0x9a, 0x5e, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x4a, 0x34, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x82, 0x00, 0x0c,
+ 0xfd, 0x1c, 0x33, 0x20, 0xfc, 0x8e, 0x69, 0x40, 0xcf, 0x28, 0xfc, 0x00, 0xcf, 0x78, 0xc8, 0x00,
+ 0x89, 0xfa, 0x00, 0x10, 0x4d, 0xa9, 0x1e, 0x00, 0x7d, 0xec, 0xff, 0xe7, 0x0e, 0xe8, 0x00, 0x10,
+ 0x4e, 0xf4, 0xbf, 0xff, 0x0f, 0xec, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00, 0xfa, 0xf7, 0x58, 0x0f,
+ 0xff, 0x6b, 0x58, 0x0d, 0xfc, 0x0c, 0x6d, 0x90, 0x8b, 0xea, 0x00, 0x04, 0xfe, 0x6b, 0x18, 0x0a,
+ 0x7d, 0xed, 0x00, 0x10, 0xf0, 0x6b, 0x68, 0x0f, 0xcf, 0x78, 0xdd, 0x00, 0xfe, 0x9d, 0x33, 0x20,
+ 0xff, 0x0d, 0x69, 0x60, 0xff, 0x86, 0x37, 0x50, 0x9f, 0xe2, 0x00, 0x34, 0x9c, 0xe2, 0x00, 0x38,
+ 0xff, 0x0e, 0x6c, 0x40, 0xff, 0x0d, 0x69, 0x78, 0xfc, 0x8d, 0x6d, 0x90, 0xfe, 0x0d, 0x69, 0x64,
+ 0xf0, 0x0d, 0x69, 0x68, 0x4a, 0x5c, 0xff, 0xf8, 0x8c, 0xea, 0x00, 0x00, 0x4f, 0xa8, 0xf9, 0xc0,
+ 0xcb, 0xdc, 0xa2, 0x00, 0xcf, 0xfc, 0xad, 0x00, 0x7f, 0x5d, 0x00, 0x0d, 0x05, 0x7d, 0x02, 0x20,
+ 0xcf, 0x78, 0xe5, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0xd9, 0x00, 0x1c, 0xcf, 0x78, 0xfd, 0x00, 0x0e, 0xf4, 0x00, 0x02, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0x79, 0x08, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xc0, 0x66, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00,
+ 0xce, 0x70, 0xb8, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe,
+ 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0xff, 0x6f, 0x28, 0x0e, 0x9c, 0xee, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13,
+ 0x9a, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x6f, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00,
+ 0x7b, 0x59, 0x00, 0x02, 0x99, 0xda, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x4b, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x82, 0x00, 0x0c, 0xfd, 0x1c, 0x33, 0x20, 0xfc, 0x8e, 0x69, 0xc0, 0xcf, 0x28, 0xfc, 0x00,
+ 0xcf, 0x78, 0xc8, 0x00, 0x89, 0xfa, 0x00, 0x10, 0x4d, 0xa9, 0x1e, 0x00, 0x7d, 0xec, 0xff, 0xe7,
+ 0x0e, 0xe8, 0x00, 0x10, 0x4e, 0xf4, 0xbf, 0xff, 0x0f, 0xec, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00,
+ 0xfa, 0xf7, 0x58, 0x0f, 0xff, 0x6b, 0x58, 0x0d, 0xfc, 0x0c, 0x6d, 0x90, 0x8b, 0xea, 0x00, 0x04,
+ 0xfe, 0x6b, 0x18, 0x0a, 0x7d, 0xed, 0x00, 0x10, 0xf0, 0x6b, 0x68, 0x0f, 0xcf, 0x78, 0xdd, 0x00,
+ 0xfe, 0x9d, 0x33, 0x20, 0xff, 0x0d, 0x69, 0xe0, 0xff, 0x86, 0x37, 0xa8, 0x9f, 0xe2, 0x00, 0x34,
+ 0x9c, 0xe2, 0x00, 0x38, 0xff, 0x0e, 0x6c, 0x40, 0xff, 0x0d, 0x69, 0xf8, 0xfc, 0x8d, 0x6d, 0x90,
+ 0xfe, 0x0d, 0x69, 0xe4, 0xf0, 0x0d, 0x69, 0xe8, 0x4a, 0x5c, 0xff, 0xf8, 0x8c, 0xea, 0x00, 0x00,
+ 0x4f, 0xa8, 0xf5, 0xc0, 0xcb, 0xdc, 0xa2, 0x00, 0xcf, 0xfc, 0xad, 0x00, 0x7f, 0x5d, 0x00, 0x0d,
+ 0x05, 0x7d, 0x02, 0x20, 0xcf, 0x78, 0xe5, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0xd9, 0x00, 0x1c, 0xcf, 0x78, 0xfd, 0x00, 0x0e, 0xf4, 0x05, 0xf2,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0x79, 0x08, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xc0, 0x66, 0xd2, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe,
+ 0xff, 0x7f, 0x18, 0x00, 0xce, 0x70, 0xb8, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8,
+ 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e, 0x9c, 0xee, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12,
+ 0xf0, 0xef, 0x68, 0x13, 0x9a, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x6f, 0x28, 0x02,
+ 0x9d, 0x02, 0xff, 0x00, 0x7b, 0x59, 0x00, 0x02, 0x99, 0xda, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x4d, 0x7c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x82, 0x00, 0x0c, 0xfd, 0x1c, 0x33, 0x20, 0xfc, 0x8e, 0x6a, 0x40,
+ 0xcf, 0x28, 0xfc, 0x00, 0xcf, 0x78, 0xc8, 0x00, 0x89, 0xfa, 0x00, 0x10, 0x4d, 0xa9, 0x1e, 0x00,
+ 0x7d, 0xec, 0xff, 0xe7, 0x0e, 0xe8, 0x00, 0x10, 0x4e, 0xf4, 0xbf, 0xff, 0x0f, 0xec, 0x07, 0x48,
+ 0xfb, 0x7f, 0x58, 0x00, 0xfa, 0xf7, 0x58, 0x0f, 0xff, 0x6b, 0x58, 0x0d, 0xfc, 0x0c, 0x6d, 0x90,
+ 0x8b, 0xea, 0x00, 0x04, 0xfe, 0x6b, 0x18, 0x0a, 0x7d, 0xed, 0x00, 0x10, 0xf0, 0x6b, 0x68, 0x0f,
+ 0xcf, 0x78, 0xdd, 0x00, 0xfe, 0x9d, 0x33, 0x20, 0xff, 0x0d, 0x6a, 0x60, 0xff, 0x86, 0x38, 0x00,
+ 0x9f, 0xe2, 0x00, 0x34, 0x9c, 0xe2, 0x00, 0x38, 0xff, 0x0e, 0x6c, 0x40, 0xff, 0x0d, 0x6a, 0x78,
+ 0xfc, 0x8d, 0x6d, 0x90, 0xfe, 0x0d, 0x6a, 0x64, 0xf0, 0x0d, 0x6a, 0x68, 0x4a, 0x5c, 0xff, 0xf8,
+ 0x8c, 0xea, 0x00, 0x00, 0x4f, 0xa8, 0xed, 0xc0, 0xcb, 0xdc, 0xa2, 0x00, 0xcf, 0xfc, 0xad, 0x00,
+ 0x7f, 0x5d, 0x00, 0x0d, 0x05, 0x7d, 0x02, 0x20, 0xcf, 0x78, 0xe5, 0x00, 0xfd, 0x02, 0x00, 0x00,
+ 0xfd, 0x88, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0xd9, 0x00, 0x1c, 0xcf, 0x78, 0xfd, 0x00,
+ 0x0e, 0xf4, 0x0b, 0xe2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0x79, 0x08, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0xc0, 0x66, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xce, 0x70, 0xb8, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e, 0x9c, 0xee, 0x00, 0x14,
+ 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9a, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9d, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0,
+ 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfd, 0x6f, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00, 0x7b, 0x59, 0x00, 0x02, 0x99, 0xda, 0x07, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x4f, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x82, 0x00, 0x0c, 0xfd, 0x1c, 0x33, 0x20,
+ 0xfc, 0x8e, 0x6a, 0xc0, 0xcf, 0x28, 0xfc, 0x00, 0xcf, 0x78, 0xc8, 0x00, 0x89, 0xfa, 0x00, 0x10,
+ 0x4d, 0xa9, 0x1e, 0x00, 0x7d, 0xec, 0xff, 0xe7, 0x0e, 0xe8, 0x00, 0x10, 0x4e, 0xf4, 0xbf, 0xff,
+ 0x0f, 0xec, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00, 0xfa, 0xf7, 0x58, 0x0f, 0xff, 0x6b, 0x58, 0x0d,
+ 0xfc, 0x0c, 0x6d, 0x90, 0x8b, 0xea, 0x00, 0x04, 0xfe, 0x6b, 0x18, 0x0a, 0x7d, 0xed, 0x00, 0x10,
+ 0xf0, 0x6b, 0x68, 0x0f, 0xcf, 0x78, 0xdd, 0x00, 0xfe, 0x9d, 0x33, 0x20, 0xff, 0x0d, 0x6a, 0xe0,
+ 0xff, 0x86, 0x38, 0x58, 0x9f, 0xe2, 0x00, 0x34, 0x9c, 0xe2, 0x00, 0x38, 0xff, 0x0e, 0x6c, 0x40,
+ 0xff, 0x0d, 0x6a, 0xf8, 0xfc, 0x8d, 0x6d, 0x90, 0xfe, 0x0d, 0x6a, 0xe4, 0xf0, 0x0d, 0x6a, 0xe8,
+ 0x4a, 0x5c, 0xff, 0xf8, 0x8c, 0xea, 0x00, 0x00, 0x4f, 0xa8, 0xdd, 0xc0, 0xcb, 0xdc, 0xa2, 0x00,
+ 0xcf, 0xfc, 0xad, 0x00, 0x7f, 0x5d, 0x00, 0x0d, 0x05, 0x7d, 0x02, 0x20, 0xcf, 0x78, 0xe5, 0x00,
+ 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0xd9, 0x00, 0x1c,
+ 0xcf, 0x78, 0xfd, 0x00, 0x0e, 0xf4, 0x11, 0xd2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0x79, 0x08, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0xc0, 0x66, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xce, 0x70, 0xb8, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f,
+ 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e,
+ 0x9c, 0xee, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9a, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28,
+ 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x6f, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00, 0x7b, 0x59, 0x00, 0x02,
+ 0x99, 0xda, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x50, 0xc4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x82, 0x00, 0x0c,
+ 0xfd, 0x1c, 0x33, 0x20, 0xfc, 0x8e, 0x6b, 0x40, 0xcf, 0x28, 0xfc, 0x00, 0xcf, 0x78, 0xc8, 0x00,
+ 0x89, 0xfa, 0x00, 0x10, 0x4d, 0xa9, 0x1e, 0x00, 0x7d, 0xec, 0xff, 0xe7, 0x0e, 0xe8, 0x00, 0x10,
+ 0x4e, 0xf4, 0xbf, 0xff, 0x0f, 0xec, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00, 0xfa, 0xf7, 0x58, 0x0f,
+ 0xff, 0x6b, 0x58, 0x0d, 0xfc, 0x0c, 0x6d, 0x90, 0x8b, 0xea, 0x00, 0x04, 0xfe, 0x6b, 0x18, 0x0a,
+ 0x7d, 0xed, 0x00, 0x10, 0xf0, 0x6b, 0x68, 0x0f, 0xcf, 0x78, 0xdd, 0x00, 0xfe, 0x9d, 0x33, 0x20,
+ 0xff, 0x0d, 0x6b, 0x60, 0xff, 0x86, 0x38, 0xb0, 0x9f, 0xe2, 0x00, 0x34, 0x9c, 0xe2, 0x00, 0x38,
+ 0xff, 0x0e, 0x6c, 0x40, 0xff, 0x0d, 0x6b, 0x78, 0xfc, 0x8d, 0x6d, 0x90, 0xfe, 0x0d, 0x6b, 0x64,
+ 0xf0, 0x0d, 0x6b, 0x68, 0x4a, 0x5c, 0xff, 0xf8, 0x8c, 0xea, 0x00, 0x00, 0x4f, 0xa8, 0xbd, 0xc0,
+ 0xcb, 0xdc, 0xa2, 0x00, 0xcf, 0xfc, 0xad, 0x00, 0x7f, 0x5d, 0x00, 0x0d, 0x05, 0x7d, 0x02, 0x20,
+ 0xcf, 0x78, 0xe5, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0xd9, 0x00, 0x1c, 0xcf, 0x78, 0xfd, 0x00, 0x0e, 0xf4, 0x36, 0x8a, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0x79, 0x08, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xc0, 0x66, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00,
+ 0xce, 0x70, 0xb8, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe,
+ 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0xff, 0x6f, 0x28, 0x0e, 0x9c, 0xee, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13,
+ 0x9a, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x6f, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00,
+ 0x7b, 0x59, 0x00, 0x02, 0x99, 0xda, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x52, 0x68, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x82, 0x00, 0x0c, 0xfd, 0x1c, 0x33, 0x20, 0xfc, 0x8e, 0x6b, 0xc0, 0xcf, 0x28, 0xfc, 0x00,
+ 0xcf, 0x78, 0xc8, 0x00, 0x89, 0xfa, 0x00, 0x10, 0x4d, 0xa9, 0x1e, 0x00, 0x7d, 0xec, 0xff, 0xe7,
+ 0x0e, 0xe8, 0x00, 0x10, 0x4e, 0xf4, 0xbf, 0xff, 0x0f, 0xec, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00,
+ 0xfa, 0xf7, 0x58, 0x0f, 0xff, 0x6b, 0x58, 0x0d, 0xfc, 0x0c, 0x6d, 0x90, 0x8b, 0xea, 0x00, 0x04,
+ 0xfe, 0x6b, 0x18, 0x0a, 0x7d, 0xed, 0x00, 0x10, 0xf0, 0x6b, 0x68, 0x0f, 0xcf, 0x78, 0xdd, 0x00,
+ 0xfe, 0x9d, 0x33, 0x20, 0xff, 0x0d, 0x6b, 0xe0, 0xff, 0x86, 0x39, 0x08, 0x9f, 0xe2, 0x00, 0x34,
+ 0x9c, 0xe2, 0x00, 0x38, 0xff, 0x0e, 0x6c, 0x40, 0xff, 0x0d, 0x6b, 0xf8, 0xfc, 0x8d, 0x6d, 0x90,
+ 0xfe, 0x0d, 0x6b, 0xe4, 0xf0, 0x0d, 0x6b, 0xe8, 0x4a, 0x5c, 0xff, 0xf8, 0x8c, 0xea, 0x00, 0x00,
+ 0x4f, 0xa8, 0x7d, 0xc0, 0xcb, 0xdc, 0xa2, 0x00, 0xcf, 0xfc, 0xad, 0x00, 0x7f, 0x5d, 0x00, 0x0d,
+ 0x05, 0x7d, 0x02, 0x20, 0xcf, 0x78, 0xe5, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0xd9, 0x00, 0x1c, 0xcf, 0x78, 0xfd, 0x00, 0x0e, 0xf4, 0x5b, 0x42,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0x79, 0x08, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xc0, 0x66, 0xd2, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe,
+ 0xff, 0x7f, 0x18, 0x00, 0xce, 0x70, 0xb8, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8,
+ 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e, 0x9c, 0xee, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12,
+ 0xf0, 0xef, 0x68, 0x13, 0x9a, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x6f, 0x28, 0x02,
+ 0x9d, 0x02, 0xff, 0x00, 0x7b, 0x59, 0x00, 0x02, 0x99, 0xda, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x54, 0x0c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x4e, 0xa9, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c, 0xfd, 0x1c, 0x33, 0x20,
+ 0xcf, 0x28, 0xfc, 0x00, 0x7e, 0xf4, 0xff, 0xe7, 0x0f, 0xf4, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00,
+ 0xfb, 0x8e, 0x69, 0x40, 0x0d, 0xe8, 0x00, 0x10, 0x4d, 0xec, 0xbf, 0xff, 0xcf, 0x78, 0xb8, 0x00,
+ 0xfc, 0x6f, 0x58, 0x0f, 0x8a, 0xfa, 0x00, 0x10, 0xff, 0xeb, 0x58, 0x0d, 0x8c, 0xea, 0x00, 0x04,
+ 0xfe, 0x6b, 0x18, 0x0a, 0x7e, 0xf5, 0x00, 0x10, 0xf0, 0x6b, 0x68, 0x0f, 0xcf, 0xfc, 0xed, 0x00,
+ 0xff, 0x8d, 0x69, 0x60, 0xff, 0x86, 0x37, 0x50, 0xff, 0x81, 0x04, 0x14, 0x4e, 0xa8, 0xf9, 0xc0,
+ 0xff, 0x8e, 0x6c, 0x40, 0xfd, 0x9d, 0x33, 0x20, 0xce, 0xf4, 0xc5, 0x00, 0xfb, 0x8d, 0x6d, 0x90,
+ 0xfe, 0x0d, 0x69, 0x64, 0xf0, 0x0d, 0x69, 0x68, 0xff, 0x8d, 0x69, 0x78, 0x4a, 0x64, 0xff, 0xf8,
+ 0x8c, 0x6a, 0x00, 0x00, 0xcc, 0xe4, 0xa2, 0x00, 0x7f, 0x65, 0x00, 0x0d, 0x05, 0x75, 0x02, 0x20,
+ 0xcf, 0x78, 0xe5, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0xd9, 0x00, 0x1c, 0xcf, 0x78, 0xfd, 0x00, 0x0e, 0xf4, 0x00, 0x02, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0x79, 0x08, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xc0, 0x62, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00,
+ 0xce, 0x70, 0xc8, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe,
+ 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0xff, 0x6f, 0x28, 0x0e, 0x9c, 0x6e, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13,
+ 0x9a, 0x7e, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0xfd, 0x6f, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00,
+ 0x7b, 0x59, 0x00, 0x02, 0x9a, 0xda, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x55, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x4e, 0xa9, 0x1e, 0x00, 0xff, 0x82, 0x00, 0x0c, 0xfd, 0x1c, 0x33, 0x20, 0xcf, 0x28, 0xfc, 0x00,
+ 0x7e, 0xf4, 0xff, 0xe7, 0x0f, 0xf4, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00, 0xfb, 0x8e, 0x6a, 0xc0,
+ 0x0d, 0xe8, 0x00, 0x10, 0x4d, 0xec, 0xbf, 0xff, 0xcf, 0x78, 0xb8, 0x00, 0xfc, 0x6f, 0x58, 0x0f,
+ 0x8a, 0xfa, 0x00, 0x10, 0xff, 0xeb, 0x58, 0x0d, 0x8c, 0xea, 0x00, 0x04, 0xfe, 0x6b, 0x18, 0x0a,
+ 0x7e, 0xf5, 0x00, 0x10, 0xf0, 0x6b, 0x68, 0x0f, 0xcf, 0xfc, 0xed, 0x00, 0xff, 0x8d, 0x6a, 0xe0,
+ 0xff, 0x86, 0x38, 0x58, 0xff, 0x81, 0x04, 0x14, 0x4e, 0xa8, 0xdd, 0xc0, 0xff, 0x8e, 0x6c, 0x40,
+ 0xfd, 0x9d, 0x33, 0x20, 0xce, 0xf4, 0xc5, 0x00, 0xfb, 0x8d, 0x6d, 0x90, 0xfe, 0x0d, 0x6a, 0xe4,
+ 0xf0, 0x0d, 0x6a, 0xe8, 0xff, 0x8d, 0x6a, 0xf8, 0x4a, 0x64, 0xff, 0xf8, 0x8c, 0x6a, 0x00, 0x00,
+ 0xcc, 0xe4, 0xa2, 0x00, 0x7f, 0x65, 0x00, 0x0d, 0x05, 0x75, 0x02, 0x20, 0xcf, 0x78, 0xe5, 0x00,
+ 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0xd9, 0x00, 0x1c,
+ 0xcf, 0x78, 0xfd, 0x00, 0x0e, 0xf4, 0x11, 0xd2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0x79, 0x08, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0xc0, 0x62, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xce, 0x70, 0xc8, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f,
+ 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e,
+ 0x9c, 0x6e, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9a, 0x7e, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28,
+ 0x9f, 0x82, 0xff, 0xb0, 0xfd, 0x6f, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00, 0x7b, 0x59, 0x00, 0x02,
+ 0x9a, 0xda, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x57, 0x44, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x0c, 0x6d, 0x90,
+ 0xfd, 0x1c, 0x33, 0x20, 0x4e, 0xa9, 0x1e, 0x00, 0x8f, 0x62, 0x00, 0x24, 0x8a, 0xe2, 0x00, 0x3c,
+ 0xfb, 0x6b, 0x18, 0x0a, 0xfb, 0xeb, 0x18, 0x08, 0xff, 0x82, 0x00, 0x04, 0x7e, 0xf4, 0xff, 0xe7,
+ 0xce, 0x28, 0xfc, 0x00, 0x0e, 0xf4, 0x07, 0x48, 0xca, 0xd4, 0xf0, 0x00, 0xfa, 0x77, 0x58, 0x00,
+ 0x8d, 0xea, 0x00, 0x04, 0xcf, 0x78, 0xb0, 0x00, 0xce, 0x60, 0xe0, 0x00, 0xcf, 0x78, 0xba, 0x00,
+ 0x89, 0x72, 0x00, 0x10, 0xcb, 0x58, 0xf2, 0x00, 0x4e, 0xa8, 0xff, 0xfb, 0xcf, 0xec, 0xb0, 0x00,
+ 0x9f, 0xea, 0x00, 0x04, 0xc0, 0x7a, 0xba, 0x00, 0xff, 0x6b, 0x28, 0x0a, 0x5e, 0xf4, 0x00, 0x02,
+ 0xee, 0x02, 0x57, 0xfc, 0xf9, 0x82, 0x00, 0x00, 0x2e, 0xf4, 0x00, 0x10, 0x4c, 0xec, 0xff, 0xf8,
+ 0xce, 0x6c, 0xca, 0x00, 0x9b, 0xe2, 0x00, 0x24, 0xc5, 0x74, 0x00, 0x00, 0x7f, 0xf1, 0x00, 0x0d,
+ 0x05, 0x75, 0x02, 0x20, 0x8d, 0x6a, 0x00, 0x00, 0xcf, 0xfc, 0xb5, 0x00, 0xfd, 0x88, 0xd3, 0xd8,
+ 0x7f, 0x51, 0x00, 0x1c, 0xcf, 0xfc, 0xf5, 0x00, 0x5e, 0xd5, 0x80, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0xfd, 0x08, 0x00, 0x9f, 0x82, 0xfe, 0x58, 0x20, 0x6a, 0x00, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00,
+ 0xce, 0x58, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe,
+ 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0xff, 0x6f, 0x28, 0x0e, 0x9d, 0x6e, 0x00, 0x14, 0xfa, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13,
+ 0x9c, 0xfe, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x99, 0xee, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0xf9, 0xef, 0x28, 0x02, 0x99, 0x82, 0xff, 0x00,
+ 0x7f, 0xd1, 0x00, 0x02, 0x99, 0x7e, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x58, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x33, 0x20, 0xff, 0x82, 0x00, 0x04, 0xcf, 0x28, 0xfc, 0x00, 0xfb, 0x0e, 0x69, 0x40,
+ 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xb0, 0x00, 0xfb, 0xe3, 0x18, 0x0a, 0x8a, 0x7a, 0x00, 0x10,
+ 0xfd, 0xe3, 0x18, 0x08, 0x7c, 0xf4, 0xff, 0xe7, 0x0f, 0xe4, 0x07, 0x48, 0xfa, 0xff, 0x58, 0x00,
+ 0x8e, 0x62, 0x00, 0x04, 0xcf, 0x5c, 0xda, 0x00, 0xfd, 0x0c, 0x6d, 0x90, 0xcb, 0xdc, 0xf2, 0x00,
+ 0x4e, 0xa8, 0xfb, 0xfb, 0xcf, 0xf0, 0xb8, 0x00, 0x9f, 0xe2, 0x00, 0x04, 0xc0, 0x7a, 0xda, 0x00,
+ 0xff, 0x63, 0x28, 0x0a, 0xee, 0x02, 0x59, 0x80, 0x5e, 0xf4, 0x00, 0x02, 0x2e, 0xf4, 0x00, 0x10,
+ 0x7f, 0xe5, 0x00, 0x10, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x69, 0x60, 0x4c, 0xf0, 0xff, 0xf8,
+ 0xff, 0x06, 0x37, 0x50, 0x9f, 0x6a, 0x00, 0x34, 0x9b, 0x6a, 0x00, 0x38, 0xce, 0x70, 0xca, 0x00,
+ 0xff, 0x8e, 0x6c, 0x40, 0xfd, 0x8d, 0x69, 0x64, 0xfb, 0x0d, 0x6d, 0x90, 0xc5, 0x74, 0x00, 0x00,
+ 0xf0, 0x0d, 0x69, 0x68, 0xff, 0x8d, 0x69, 0x78, 0x7f, 0x71, 0x00, 0x0d, 0x05, 0x75, 0x02, 0x20,
+ 0x8c, 0x62, 0x00, 0x00, 0xcf, 0x78, 0xbd, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0xd5, 0x00, 0x1c, 0xcf, 0x78, 0xfd, 0x00, 0x0e, 0xf4, 0x00, 0x02,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0x79, 0x08, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xc0, 0x62, 0xd2, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe,
+ 0xff, 0x7f, 0x18, 0x00, 0xce, 0x5c, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8,
+ 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e, 0x9c, 0x6e, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12,
+ 0xf0, 0xef, 0x68, 0x13, 0x9c, 0xfe, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x6f, 0x28, 0x02,
+ 0x9d, 0x02, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x5a, 0x8c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x20, 0xff, 0x82, 0x00, 0x04, 0xcf, 0x28, 0xfc, 0x00,
+ 0xfb, 0x0e, 0x69, 0xc0, 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xb0, 0x00, 0xfb, 0xe3, 0x18, 0x0a,
+ 0x8a, 0x7a, 0x00, 0x10, 0xfd, 0xe3, 0x18, 0x08, 0x7c, 0xf4, 0xff, 0xe7, 0x0f, 0xe4, 0x07, 0x48,
+ 0xfa, 0xff, 0x58, 0x00, 0x8e, 0x62, 0x00, 0x04, 0xcf, 0x5c, 0xda, 0x00, 0xfd, 0x0c, 0x6d, 0x90,
+ 0xcb, 0xdc, 0xf2, 0x00, 0x4e, 0xa8, 0xf7, 0xfb, 0xcf, 0xf0, 0xb8, 0x00, 0x9f, 0xe2, 0x00, 0x04,
+ 0xc0, 0x7a, 0xda, 0x00, 0xff, 0x63, 0x28, 0x0a, 0xee, 0x02, 0x5b, 0x34, 0x5e, 0xf4, 0x00, 0x02,
+ 0x2e, 0xf4, 0x00, 0x10, 0x7f, 0xe5, 0x00, 0x10, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x69, 0xe0,
+ 0x4c, 0xf0, 0xff, 0xf8, 0xff, 0x06, 0x37, 0xa8, 0x9f, 0x6a, 0x00, 0x34, 0x9b, 0x6a, 0x00, 0x38,
+ 0xce, 0x70, 0xca, 0x00, 0xff, 0x8e, 0x6c, 0x40, 0xfd, 0x8d, 0x69, 0xe4, 0xfb, 0x0d, 0x6d, 0x90,
+ 0xc5, 0x74, 0x00, 0x00, 0xf0, 0x0d, 0x69, 0xe8, 0xff, 0x8d, 0x69, 0xf8, 0x7f, 0x71, 0x00, 0x0d,
+ 0x05, 0x75, 0x02, 0x20, 0x8c, 0x62, 0x00, 0x00, 0xcf, 0x78, 0xbd, 0x00, 0xfd, 0x02, 0x00, 0x00,
+ 0xfd, 0x88, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0xd5, 0x00, 0x1c, 0xcf, 0x78, 0xfd, 0x00,
+ 0x0e, 0xf4, 0x05, 0xf2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0x79, 0x08, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0xc0, 0x62, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xce, 0x5c, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e, 0x9c, 0x6e, 0x00, 0x14,
+ 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9c, 0xfe, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9d, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0,
+ 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfd, 0x6f, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x5c, 0x40,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x20, 0xff, 0x82, 0x00, 0x04,
+ 0xcf, 0x28, 0xfc, 0x00, 0xfb, 0x0e, 0x6a, 0x40, 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xb0, 0x00,
+ 0xfb, 0xe3, 0x18, 0x0a, 0x8a, 0x7a, 0x00, 0x10, 0xfd, 0xe3, 0x18, 0x08, 0x7c, 0xf4, 0xff, 0xe7,
+ 0x0f, 0xe4, 0x07, 0x48, 0xfa, 0xff, 0x58, 0x00, 0x8e, 0x62, 0x00, 0x04, 0xcf, 0x5c, 0xda, 0x00,
+ 0xfd, 0x0c, 0x6d, 0x90, 0xcb, 0xdc, 0xf2, 0x00, 0x4e, 0xa8, 0xef, 0xfb, 0xcf, 0xf0, 0xb8, 0x00,
+ 0x9f, 0xe2, 0x00, 0x04, 0xc0, 0x7a, 0xda, 0x00, 0xff, 0x63, 0x28, 0x0a, 0xee, 0x02, 0x5c, 0xe8,
+ 0x5e, 0xf4, 0x00, 0x02, 0x2e, 0xf4, 0x00, 0x10, 0x7f, 0xe5, 0x00, 0x10, 0x5f, 0xfc, 0x00, 0x01,
+ 0xff, 0x8d, 0x6a, 0x60, 0x4c, 0xf0, 0xff, 0xf8, 0xff, 0x06, 0x38, 0x00, 0x9f, 0x6a, 0x00, 0x34,
+ 0x9b, 0x6a, 0x00, 0x38, 0xce, 0x70, 0xca, 0x00, 0xff, 0x8e, 0x6c, 0x40, 0xfd, 0x8d, 0x6a, 0x64,
+ 0xfb, 0x0d, 0x6d, 0x90, 0xc5, 0x74, 0x00, 0x00, 0xf0, 0x0d, 0x6a, 0x68, 0xff, 0x8d, 0x6a, 0x78,
+ 0x7f, 0x71, 0x00, 0x0d, 0x05, 0x75, 0x02, 0x20, 0x8c, 0x62, 0x00, 0x00, 0xcf, 0x78, 0xbd, 0x00,
+ 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0xd5, 0x00, 0x1c,
+ 0xcf, 0x78, 0xfd, 0x00, 0x0e, 0xf4, 0x0b, 0xe2, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0x79, 0x08, 0x00,
+ 0x9f, 0x02, 0xfe, 0x58, 0xc0, 0x62, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d,
+ 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xce, 0x5c, 0xe0, 0x00,
+ 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f,
+ 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e,
+ 0x9c, 0x6e, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9c, 0xfe, 0x00, 0x14,
+ 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c,
+ 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58,
+ 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8,
+ 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28,
+ 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x6f, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02,
+ 0x9a, 0x7e, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8,
+ 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00,
+ 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08,
+ 0xe0, 0x02, 0x5d, 0xf4, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x20,
+ 0xff, 0x82, 0x00, 0x04, 0xcf, 0x28, 0xfc, 0x00, 0xfb, 0x0e, 0x6a, 0xc0, 0x4e, 0xa9, 0x1e, 0x00,
+ 0xcf, 0x78, 0xb0, 0x00, 0xfb, 0xe3, 0x18, 0x0a, 0x8a, 0x7a, 0x00, 0x10, 0xfd, 0xe3, 0x18, 0x08,
+ 0x7c, 0xf4, 0xff, 0xe7, 0x0f, 0xe4, 0x07, 0x48, 0xfa, 0xff, 0x58, 0x00, 0x8e, 0x62, 0x00, 0x04,
+ 0xcf, 0x5c, 0xda, 0x00, 0xfd, 0x0c, 0x6d, 0x90, 0xcb, 0xdc, 0xf2, 0x00, 0x4e, 0xa8, 0xdf, 0xfb,
+ 0xcf, 0xf0, 0xb8, 0x00, 0x9f, 0xe2, 0x00, 0x04, 0xc0, 0x7a, 0xda, 0x00, 0xff, 0x63, 0x28, 0x0a,
+ 0xee, 0x02, 0x5e, 0x9c, 0x5e, 0xf4, 0x00, 0x02, 0x2e, 0xf4, 0x00, 0x10, 0x7f, 0xe5, 0x00, 0x10,
+ 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x6a, 0xe0, 0x4c, 0xf0, 0xff, 0xf8, 0xff, 0x06, 0x38, 0x58,
+ 0x9f, 0x6a, 0x00, 0x34, 0x9b, 0x6a, 0x00, 0x38, 0xce, 0x70, 0xca, 0x00, 0xff, 0x8e, 0x6c, 0x40,
+ 0xfd, 0x8d, 0x6a, 0xe4, 0xfb, 0x0d, 0x6d, 0x90, 0xc5, 0x74, 0x00, 0x00, 0xf0, 0x0d, 0x6a, 0xe8,
+ 0xff, 0x8d, 0x6a, 0xf8, 0x7f, 0x71, 0x00, 0x0d, 0x05, 0x75, 0x02, 0x20, 0x8c, 0x62, 0x00, 0x00,
+ 0xcf, 0x78, 0xbd, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0xd5, 0x00, 0x1c, 0xcf, 0x78, 0xfd, 0x00, 0x0e, 0xf4, 0x11, 0xd2, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0x79, 0x08, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xc0, 0x62, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00,
+ 0xce, 0x5c, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe,
+ 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0xff, 0x6f, 0x28, 0x0e, 0x9c, 0x6e, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13,
+ 0x9c, 0xfe, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x6f, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00,
+ 0x7f, 0xd5, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x5f, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfc, 0x1c, 0x33, 0x20, 0xff, 0x82, 0x00, 0x04, 0xcf, 0x28, 0xfc, 0x00, 0xfb, 0x0e, 0x6b, 0x40,
+ 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xb0, 0x00, 0xfb, 0xe3, 0x18, 0x0a, 0x8a, 0x7a, 0x00, 0x10,
+ 0xfd, 0xe3, 0x18, 0x08, 0x7c, 0xf4, 0xff, 0xe7, 0x0f, 0xe4, 0x07, 0x48, 0xfa, 0xff, 0x58, 0x00,
+ 0x8e, 0x62, 0x00, 0x04, 0xcf, 0x5c, 0xda, 0x00, 0xfd, 0x0c, 0x6d, 0x90, 0xcb, 0xdc, 0xf2, 0x00,
+ 0x4e, 0xa8, 0xbf, 0xfb, 0xcf, 0xf0, 0xb8, 0x00, 0x9f, 0xe2, 0x00, 0x04, 0xc0, 0x7a, 0xda, 0x00,
+ 0xff, 0x63, 0x28, 0x0a, 0xee, 0x02, 0x60, 0x50, 0x5e, 0xf4, 0x00, 0x02, 0x2e, 0xf4, 0x00, 0x10,
+ 0x7f, 0xe5, 0x00, 0x10, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x6b, 0x60, 0x4c, 0xf0, 0xff, 0xf8,
+ 0xff, 0x06, 0x38, 0xb0, 0x9f, 0x6a, 0x00, 0x34, 0x9b, 0x6a, 0x00, 0x38, 0xce, 0x70, 0xca, 0x00,
+ 0xff, 0x8e, 0x6c, 0x40, 0xfd, 0x8d, 0x6b, 0x64, 0xfb, 0x0d, 0x6d, 0x90, 0xc5, 0x74, 0x00, 0x00,
+ 0xf0, 0x0d, 0x6b, 0x68, 0xff, 0x8d, 0x6b, 0x78, 0x7f, 0x71, 0x00, 0x0d, 0x05, 0x75, 0x02, 0x20,
+ 0x8c, 0x62, 0x00, 0x00, 0xcf, 0x78, 0xbd, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0xd5, 0x00, 0x1c, 0xcf, 0x78, 0xfd, 0x00, 0x0e, 0xf4, 0x36, 0x8a,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0x79, 0x08, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xc0, 0x62, 0xd2, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe,
+ 0xff, 0x7f, 0x18, 0x00, 0xce, 0x5c, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8,
+ 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e, 0x9c, 0x6e, 0x00, 0x14, 0xfa, 0xef, 0x68, 0x12,
+ 0xf0, 0xef, 0x68, 0x13, 0x9c, 0xfe, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0, 0xfd, 0x6f, 0x28, 0x02,
+ 0x9d, 0x02, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x61, 0x5c, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x20, 0xff, 0x82, 0x00, 0x04, 0xcf, 0x28, 0xfc, 0x00,
+ 0xfb, 0x0e, 0x6b, 0xc0, 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xb0, 0x00, 0xfb, 0xe3, 0x18, 0x0a,
+ 0x8a, 0x7a, 0x00, 0x10, 0xfd, 0xe3, 0x18, 0x08, 0x7c, 0xf4, 0xff, 0xe7, 0x0f, 0xe4, 0x07, 0x48,
+ 0xfa, 0xff, 0x58, 0x00, 0x8e, 0x62, 0x00, 0x04, 0xcf, 0x5c, 0xda, 0x00, 0xfd, 0x0c, 0x6d, 0x90,
+ 0xcb, 0xdc, 0xf2, 0x00, 0x4e, 0xa8, 0x7f, 0xfb, 0xcf, 0xf0, 0xb8, 0x00, 0x9f, 0xe2, 0x00, 0x04,
+ 0xc0, 0x7a, 0xda, 0x00, 0xff, 0x63, 0x28, 0x0a, 0xee, 0x02, 0x62, 0x04, 0x5e, 0xf4, 0x00, 0x02,
+ 0x2e, 0xf4, 0x00, 0x10, 0x7f, 0xe5, 0x00, 0x10, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x6b, 0xe0,
+ 0x4c, 0xf0, 0xff, 0xf8, 0xff, 0x06, 0x39, 0x08, 0x9f, 0x6a, 0x00, 0x34, 0x9b, 0x6a, 0x00, 0x38,
+ 0xce, 0x70, 0xca, 0x00, 0xff, 0x8e, 0x6c, 0x40, 0xfd, 0x8d, 0x6b, 0xe4, 0xfb, 0x0d, 0x6d, 0x90,
+ 0xc5, 0x74, 0x00, 0x00, 0xf0, 0x0d, 0x6b, 0xe8, 0xff, 0x8d, 0x6b, 0xf8, 0x7f, 0x71, 0x00, 0x0d,
+ 0x05, 0x75, 0x02, 0x20, 0x8c, 0x62, 0x00, 0x00, 0xcf, 0x78, 0xbd, 0x00, 0xfd, 0x02, 0x00, 0x00,
+ 0xfd, 0x88, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00, 0x7f, 0xd5, 0x00, 0x1c, 0xcf, 0x78, 0xfd, 0x00,
+ 0x0e, 0xf4, 0x5b, 0x42, 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0x79, 0x08, 0x00, 0x9f, 0x02, 0xfe, 0x58,
+ 0xc0, 0x62, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c,
+ 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00, 0xce, 0x5c, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07,
+ 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00,
+ 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e, 0x9c, 0x6e, 0x00, 0x14,
+ 0xfa, 0xef, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13, 0x9c, 0xfe, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10,
+ 0x9d, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08,
+ 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0,
+ 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff,
+ 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08, 0xff, 0x02, 0x00, 0x28, 0x9f, 0x02, 0xff, 0xb0,
+ 0xfd, 0x6f, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00, 0x7f, 0xd5, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08,
+ 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00,
+ 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14,
+ 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x63, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x20, 0xff, 0x82, 0x00, 0x04,
+ 0xcf, 0x28, 0xfc, 0x00, 0xfa, 0x8e, 0x69, 0x40, 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xa8, 0x00,
+ 0xfb, 0xe3, 0x18, 0x0a, 0x8a, 0x7a, 0x00, 0x10, 0xfd, 0xe3, 0x18, 0x08, 0x7d, 0x74, 0xff, 0xe7,
+ 0x0f, 0xe8, 0x07, 0x48, 0xfb, 0x7f, 0x58, 0x00, 0x8e, 0x62, 0x00, 0x04, 0xcf, 0x5c, 0xda, 0x00,
+ 0xcb, 0xdc, 0xf2, 0x00, 0x4e, 0xa8, 0xfb, 0xfb, 0xcf, 0xf0, 0xb8, 0x00, 0x9f, 0xe2, 0x00, 0x04,
+ 0xc0, 0x7a, 0xda, 0x00, 0xff, 0x63, 0x28, 0x0a, 0xee, 0x02, 0x63, 0xb4, 0x5e, 0xf4, 0x00, 0x02,
+ 0x2e, 0xf4, 0x00, 0x10, 0x7f, 0xe9, 0x00, 0x10, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x69, 0x60,
+ 0xff, 0x86, 0x37, 0x50, 0xff, 0x81, 0x04, 0x14, 0x4c, 0xf0, 0xff, 0xf8, 0xce, 0x70, 0xca, 0x00,
+ 0xff, 0x8e, 0x6c, 0x40, 0xfd, 0x8d, 0x69, 0x64, 0xfa, 0x8d, 0x6d, 0x90, 0xc5, 0x74, 0x00, 0x00,
+ 0xf0, 0x0d, 0x69, 0x68, 0xff, 0x8d, 0x69, 0x78, 0x7f, 0x71, 0x00, 0x0d, 0x05, 0x75, 0x02, 0x20,
+ 0x8c, 0x62, 0x00, 0x00, 0xcf, 0x78, 0xbd, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8,
+ 0x0e, 0x81, 0x80, 0x00, 0x7f, 0xd9, 0x00, 0x1c, 0xcf, 0x78, 0xfd, 0x00, 0x0e, 0xf4, 0x00, 0x02,
+ 0x9e, 0x82, 0xfe, 0x58, 0x5f, 0x79, 0x08, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xc0, 0x62, 0xd2, 0x00,
+ 0xe6, 0x74, 0x00, 0x02, 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe,
+ 0xff, 0x7f, 0x18, 0x00, 0xce, 0x5c, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8,
+ 0x7e, 0x70, 0xff, 0xfe, 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02,
+ 0xcf, 0xec, 0xe8, 0x00, 0xff, 0x6f, 0x28, 0x0e, 0x9c, 0x6e, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12,
+ 0xf0, 0xef, 0x68, 0x13, 0x9c, 0xfe, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30,
+ 0xff, 0x6f, 0x18, 0x0a, 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58,
+ 0x5e, 0xf5, 0x10, 0x00, 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04,
+ 0x0f, 0x78, 0x00, 0x01, 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00,
+ 0x9f, 0x72, 0x00, 0x08, 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0xfd, 0x6f, 0x28, 0x02,
+ 0x9d, 0x02, 0xff, 0x00, 0x7f, 0xd9, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00,
+ 0xf3, 0x03, 0x1b, 0x9a, 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8,
+ 0x87, 0x2e, 0x00, 0x04, 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00,
+ 0xeb, 0x38, 0x00, 0x02, 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x64, 0xbc, 0x00, 0x00, 0x00, 0x01,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xfc, 0x1c, 0x33, 0x20, 0xff, 0x82, 0x00, 0x04, 0xcf, 0x28, 0xfc, 0x00,
+ 0xfa, 0x8e, 0x6a, 0xc0, 0x4e, 0xa9, 0x1e, 0x00, 0xcf, 0x78, 0xa8, 0x00, 0xfb, 0xe3, 0x18, 0x0a,
+ 0x8a, 0x7a, 0x00, 0x10, 0xfd, 0xe3, 0x18, 0x08, 0x7d, 0x74, 0xff, 0xe7, 0x0f, 0xe8, 0x07, 0x48,
+ 0xfb, 0x7f, 0x58, 0x00, 0x8e, 0x62, 0x00, 0x04, 0xcf, 0x5c, 0xda, 0x00, 0xcb, 0xdc, 0xf2, 0x00,
+ 0x4e, 0xa8, 0xdf, 0xfb, 0xcf, 0xf0, 0xb8, 0x00, 0x9f, 0xe2, 0x00, 0x04, 0xc0, 0x7a, 0xda, 0x00,
+ 0xff, 0x63, 0x28, 0x0a, 0xee, 0x02, 0x65, 0x60, 0x5e, 0xf4, 0x00, 0x02, 0x2e, 0xf4, 0x00, 0x10,
+ 0x7f, 0xe9, 0x00, 0x10, 0x5f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x6a, 0xe0, 0xff, 0x86, 0x38, 0x58,
+ 0xff, 0x81, 0x04, 0x14, 0x4c, 0xf0, 0xff, 0xf8, 0xce, 0x70, 0xca, 0x00, 0xff, 0x8e, 0x6c, 0x40,
+ 0xfd, 0x8d, 0x6a, 0xe4, 0xfa, 0x8d, 0x6d, 0x90, 0xc5, 0x74, 0x00, 0x00, 0xf0, 0x0d, 0x6a, 0xe8,
+ 0xff, 0x8d, 0x6a, 0xf8, 0x7f, 0x71, 0x00, 0x0d, 0x05, 0x75, 0x02, 0x20, 0x8c, 0x62, 0x00, 0x00,
+ 0xcf, 0x78, 0xbd, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x88, 0xd3, 0xd8, 0x0e, 0x81, 0x80, 0x00,
+ 0x7f, 0xd9, 0x00, 0x1c, 0xcf, 0x78, 0xfd, 0x00, 0x0e, 0xf4, 0x11, 0xd2, 0x9e, 0x82, 0xfe, 0x58,
+ 0x5f, 0x79, 0x08, 0x00, 0x9f, 0x02, 0xfe, 0x58, 0xc0, 0x62, 0xd2, 0x00, 0xe6, 0x74, 0x00, 0x02,
+ 0x7f, 0xf5, 0x00, 0x0d, 0xff, 0xef, 0x28, 0x0c, 0xff, 0x8a, 0x9f, 0xfe, 0xff, 0x7f, 0x18, 0x00,
+ 0xce, 0x5c, 0xe0, 0x00, 0x0e, 0x70, 0x00, 0x07, 0x4e, 0x70, 0x0f, 0xf8, 0x7e, 0x70, 0xff, 0xfe,
+ 0x7f, 0x79, 0x00, 0x0f, 0xcf, 0x78, 0xe5, 0x00, 0x7e, 0xf5, 0x00, 0x02, 0xcf, 0xec, 0xe8, 0x00,
+ 0xff, 0x6f, 0x28, 0x0e, 0x9c, 0x6e, 0x00, 0x14, 0xfb, 0x6f, 0x68, 0x12, 0xf0, 0xef, 0x68, 0x13,
+ 0x9c, 0xfe, 0x00, 0x14, 0x0e, 0xf4, 0x00, 0x10, 0x9d, 0x6e, 0x00, 0x30, 0xff, 0x6f, 0x18, 0x0a,
+ 0x8e, 0x6e, 0x00, 0x2c, 0x0f, 0xec, 0x00, 0x08, 0x9f, 0x82, 0xfe, 0x58, 0x5e, 0xf5, 0x10, 0x00,
+ 0x9e, 0x82, 0xfe, 0x58, 0xff, 0x86, 0xa7, 0xd0, 0x9f, 0xee, 0x00, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xfe, 0x09, 0xd3, 0xd8, 0x4f, 0x78, 0x0f, 0xff, 0xff, 0x73, 0x28, 0x00, 0x9f, 0x72, 0x00, 0x08,
+ 0xff, 0x82, 0x00, 0x28, 0x9f, 0x82, 0xff, 0xb0, 0xfd, 0x6f, 0x28, 0x02, 0x9d, 0x02, 0xff, 0x00,
+ 0x7f, 0xd9, 0x00, 0x02, 0x9a, 0x7e, 0x07, 0x08, 0xf6, 0x2f, 0x18, 0x00, 0xf3, 0x03, 0x1b, 0x9a,
+ 0x95, 0x02, 0xfe, 0xa8, 0xf2, 0x82, 0x04, 0x00, 0xf6, 0x83, 0x1a, 0xa8, 0x87, 0x2e, 0x00, 0x04,
+ 0xc6, 0x18, 0x62, 0x00, 0x70, 0x32, 0x00, 0x14, 0x81, 0x36, 0x04, 0x00, 0xeb, 0x38, 0x00, 0x02,
+ 0x22, 0x14, 0x00, 0x08, 0xe0, 0x02, 0x66, 0x68, 0x00, 0x00, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xfd, 0x02, 0x00, 0x02, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x90, 0x02, 0xfe, 0xc0,
+ 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x05, 0x9d, 0x02, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x8a, 0x00, 0x00, 0x9d, 0x82, 0xfe, 0xc0,
+ 0x0f, 0x01, 0x60, 0x00, 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x06, 0x9d, 0x02, 0xfe, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x81, 0x00, 0x40, 0x9f, 0x82, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x02, 0x00, 0x80, 0x9d, 0x02, 0xfe, 0xc0, 0x0d, 0x81, 0x40, 0x06, 0x9d, 0x82, 0xfe, 0xc8,
+ 0xff, 0x8a, 0x2b, 0x54, 0xfd, 0x02, 0x00, 0x07, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x81, 0x04, 0x18,
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x00, 0x40, 0x9f, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x02, 0x01, 0x00, 0x9d, 0x02, 0xfe, 0xc0, 0x9d, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x08,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x81, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x02, 0x00,
+ 0x9f, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x90, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x09, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x81, 0x04, 0x20, 0xfe, 0x82, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x0d, 0x01, 0x40, 0x00,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x0a, 0xfd, 0x82, 0xf8, 0xe0,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x81, 0x04, 0x24, 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xff, 0x42, 0x00, 0x00, 0x9f, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x0b, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x81, 0x04, 0x28, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x22, 0x00, 0x00, 0x0d, 0x81, 0x20, 0x00,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x0d, 0xec, 0x02, 0x00, 0x9d, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x0c,
+ 0xff, 0x0a, 0x2a, 0x28, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0x2c, 0x00, 0x00, 0x00, 0x01,
+ 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x06, 0x00, 0x00, 0x9d, 0x02, 0xfe, 0xc0,
+ 0x9d, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x0d, 0xff, 0x06, 0x3c, 0x48, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xff, 0x01, 0x04, 0x30, 0xfe, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x00, 0x04,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x90, 0x02, 0xfe, 0xc0, 0x9d, 0x82, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x0e, 0x9d, 0x02, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x04,
+ 0x9f, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x90, 0x02, 0xfe, 0xc0, 0xfd, 0x02, 0x02, 0x00,
+ 0x9d, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x0f, 0xfd, 0x86, 0x3b, 0x58, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xfd, 0x81, 0x04, 0x38, 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x90, 0x02, 0xfe, 0xc0, 0xff, 0x02, 0x00, 0x31, 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x10,
+ 0xff, 0x81, 0x04, 0x3c, 0x9d, 0x02, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8c, 0x39, 0x18,
+ 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x7f, 0xfd, 0x00, 0x19, 0x9f, 0x82, 0xfe, 0xc0,
+ 0xcf, 0x68, 0x00, 0x00, 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x11, 0xff, 0x8a, 0x2b, 0xe8,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x81, 0x04, 0x40, 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0x0d, 0x01, 0x01, 0xe0, 0x9d, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8,
+ 0xff, 0x8a, 0x2b, 0x9c, 0xfd, 0x02, 0x00, 0x12, 0xff, 0x81, 0x04, 0x44, 0x9d, 0x02, 0xfe, 0xd0,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x82, 0x10, 0x00, 0x9d, 0x82, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x82, 0xfc, 0x13, 0x9d, 0x82, 0xfe, 0xc0, 0xcd, 0xe8, 0x00, 0x00, 0x9e, 0x82, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x13, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x81, 0x04, 0x48, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x04, 0x13,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x14, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xfd, 0x0a, 0x38, 0x30, 0xfd, 0x01, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x08, 0x13, 0x9d, 0x02, 0xfe, 0xc0,
+ 0x9e, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x15, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x2d, 0xc8,
+ 0xfd, 0x01, 0x04, 0x50, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x10, 0x13, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x82, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x16, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x2f, 0x84, 0xfd, 0x01, 0x04, 0x54,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x02, 0xfc, 0x12, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x17,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x31, 0x40, 0xfd, 0x01, 0x04, 0x58, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x20, 0x12,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x18, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xfd, 0x0a, 0x39, 0xe4, 0xfd, 0x01, 0x04, 0x5c, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x40, 0x12, 0x9d, 0x02, 0xfe, 0xc0,
+ 0x9e, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x19, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x32, 0xfc,
+ 0xfd, 0x01, 0x04, 0x60, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x80, 0x12, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x82, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x1a, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x34, 0xb8, 0xfd, 0x01, 0x04, 0x64,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x9f, 0x02, 0xfe, 0xc0, 0xfd, 0x02, 0x00, 0x22, 0x9d, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x1b,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x36, 0x74, 0xfd, 0x01, 0x04, 0x68, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0xfc, 0x03,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x1c, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xfd, 0x0a, 0x2c, 0x40, 0xfd, 0x01, 0x04, 0x6c, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x04, 0x03, 0x9d, 0x02, 0xfe, 0xc0,
+ 0x9e, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x1d, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x47, 0x50,
+ 0xfd, 0x01, 0x04, 0x70, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x08, 0x03, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x1e, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x3d, 0x18, 0xfd, 0x01, 0x04, 0x74,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x02, 0x10, 0x03, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x1f,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x3e, 0xcc, 0xfd, 0x01, 0x04, 0x78, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x20, 0x03,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x02, 0xfe, 0xc8, 0xfd, 0x0a, 0x40, 0x80, 0xfd, 0x01, 0x04, 0x7c,
+ 0x9e, 0x82, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x40, 0x03, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x21, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x42, 0x34, 0xfd, 0x01, 0x04, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x02, 0x80, 0x03, 0x9d, 0x02, 0xfe, 0xc0, 0x9e, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x22,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x43, 0xe8, 0xfd, 0x01, 0x04, 0x84, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x00, 0x01,
+ 0x9d, 0x02, 0xfe, 0xc0, 0xfd, 0x02, 0x00, 0x32, 0x9d, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x23,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x45, 0x9c, 0xfd, 0x01, 0x04, 0x88, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0xfc, 0x23,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x24, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xfd, 0x0a, 0x3b, 0x98, 0xfd, 0x01, 0x04, 0x8c, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x04, 0x23, 0x9d, 0x02, 0xfe, 0xc0,
+ 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x25, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x54, 0x54,
+ 0xfd, 0x01, 0x04, 0x90, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x08, 0x23, 0x9d, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x26, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x4a, 0x7c, 0xfd, 0x01, 0x04, 0x94,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x02, 0x10, 0x23, 0x9d, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x27,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x4c, 0x20, 0xfd, 0x01, 0x04, 0x98, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0xfc, 0x22,
+ 0x9d, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x28, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xfd, 0x0a, 0x4d, 0xc4, 0xfd, 0x01, 0x04, 0x9c, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x20, 0x22, 0x9d, 0x02, 0xfe, 0xc0,
+ 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x29, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x55, 0xf0,
+ 0xfd, 0x01, 0x04, 0xa0, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x02, 0x40, 0x22, 0x9d, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x2a, 0x9d, 0x02, 0xfe, 0xd0, 0xfd, 0x0a, 0x4f, 0x68, 0xfd, 0x01, 0x04, 0xa4,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x02, 0x80, 0x22, 0x9d, 0x02, 0xfe, 0xc0, 0x9f, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x2b,
+ 0xff, 0x0a, 0x51, 0x0c, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0xa8, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x9e, 0x82, 0xfe, 0xc0,
+ 0x9d, 0x82, 0xfe, 0xc8, 0xfd, 0x82, 0x00, 0x2c, 0xff, 0x0a, 0x52, 0xb0, 0x9d, 0x82, 0xfe, 0xd0,
+ 0xff, 0x01, 0x04, 0xac, 0x00, 0x00, 0x00, 0x01, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x82, 0xfc, 0x33, 0x9d, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x2d,
+ 0xff, 0x0a, 0x48, 0xfc, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0xb0, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x82, 0x04, 0x33,
+ 0x9d, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x2e, 0xff, 0x0a, 0x63, 0x58,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0xb4, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x82, 0x08, 0x33, 0x9d, 0x82, 0xfe, 0xc0,
+ 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x2f, 0xff, 0x0a, 0x59, 0x20, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xff, 0x01, 0x04, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x82, 0x10, 0x33, 0x9d, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8,
+ 0xff, 0x0a, 0x5a, 0xd4, 0xff, 0x01, 0x04, 0xbc, 0x9e, 0x02, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x01,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x82, 0xfc, 0x32, 0x9d, 0x82, 0xfe, 0xc0,
+ 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x31, 0xff, 0x0a, 0x5c, 0x88, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xff, 0x01, 0x04, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0,
+ 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x82, 0x20, 0x32, 0x9d, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8,
+ 0xfd, 0x02, 0x00, 0x32, 0xff, 0x0a, 0x65, 0x04, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0xc4,
+ 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0xfd, 0x82, 0x40, 0x32, 0x9d, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x33,
+ 0xff, 0x0a, 0x5e, 0x3c, 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0xc8, 0x00, 0x00, 0x00, 0x01,
+ 0xfd, 0x02, 0x10, 0x00, 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0xfd, 0x82, 0x80, 0x32,
+ 0x9d, 0x82, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x34, 0xff, 0x0a, 0x5f, 0xf0,
+ 0x9d, 0x02, 0xfe, 0xd0, 0xff, 0x01, 0x04, 0xcc, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x02, 0x10, 0x00,
+ 0x9d, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8, 0x9e, 0x02, 0xfe, 0xc0, 0xfd, 0x82, 0x00, 0x02,
+ 0x9d, 0x82, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x35, 0xff, 0x0a, 0x61, 0xa4, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xff, 0x01, 0x04, 0xd0, 0x00, 0x00, 0x00, 0x01, 0x90, 0x02, 0xfe, 0xb0, 0x90, 0x02, 0xfe, 0xb8,
+ 0x90, 0x02, 0xfe, 0xc0, 0x90, 0x02, 0xfe, 0xc8, 0xfd, 0x02, 0x00, 0x36, 0x9d, 0x02, 0xfe, 0xd0,
+ 0xfd, 0x0a, 0x57, 0x8c, 0xfd, 0x01, 0x04, 0xd4, 0x00, 0x00, 0x00, 0x01, 0xff, 0x81, 0x04, 0xd8,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x70, 0x2a, 0x00, 0x0b, 0xea, 0x02, 0x6f, 0x5c, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x8c, 0x72, 0x70, 0x20, 0x7e, 0x00, 0x04, 0xe6, 0x02, 0x70, 0x18, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x9c, 0x33, 0x40, 0x4f, 0xf4, 0xff, 0xfc, 0x20, 0x7e, 0x00, 0x04, 0xe6, 0x02, 0x70, 0x18,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x02, 0xff, 0xd0, 0x2f, 0xf4, 0x00, 0x04, 0xff, 0x9d, 0x33, 0x40,
+ 0xff, 0x0d, 0x71, 0xe0, 0xe0, 0x02, 0x70, 0x18, 0xf0, 0x1d, 0x33, 0x60, 0xf7, 0x8a, 0x6f, 0x68,
+ 0xe0, 0x01, 0x36, 0x88, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x82, 0xff, 0xf8, 0xfe, 0x82, 0x00, 0x01,
+ 0xfd, 0x8e, 0x38, 0xe0, 0xcf, 0xfe, 0xec, 0x00, 0x9f, 0x82, 0xff, 0xf8, 0x8f, 0x02, 0xff, 0xf8,
+ 0xe6, 0x70, 0x00, 0x03, 0x20, 0x72, 0x00, 0x00, 0x7f, 0x78, 0xff, 0xfa, 0xcf, 0x78, 0xec, 0x00,
+ 0xe6, 0x02, 0x6f, 0xad, 0xff, 0x6f, 0x68, 0x3c, 0xff, 0x8c, 0x72, 0x50, 0x20, 0x7e, 0x00, 0x64,
+ 0xe2, 0x02, 0x6f, 0xad, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x02, 0x00, 0x02, 0xff, 0x8c, 0x38, 0xfc,
+ 0xc0, 0x72, 0xfa, 0x00, 0xe6, 0x02, 0x6f, 0xdd, 0xf0, 0x0d, 0x72, 0x50, 0xff, 0x83, 0x5b, 0xe8,
+ 0x70, 0x7e, 0x00, 0x1f, 0xea, 0x02, 0x6f, 0xdc, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x82, 0x00, 0x01,
+ 0xf7, 0xef, 0x68, 0x3e, 0xfe, 0x0d, 0x38, 0xfc, 0x55, 0x28, 0x01, 0x00, 0xff, 0x98, 0x73, 0x00,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x70, 0x19, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xd0,
+ 0xff, 0x1c, 0x33, 0x30, 0xfe, 0xfa, 0x84, 0x80, 0xcf, 0xfc, 0xf2, 0x00, 0xc0, 0x7e, 0xea, 0x00,
+ 0xe2, 0x02, 0x70, 0x19, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x82, 0xff, 0xd0, 0xf0, 0x19, 0x73, 0x00,
+ 0x55, 0x28, 0x01, 0x00, 0xff, 0x9d, 0x33, 0x30, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x82, 0x00, 0x0f,
+ 0xff, 0x8d, 0x39, 0x18, 0xf7, 0x8a, 0x70, 0x40, 0xe0, 0x02, 0x66, 0xa8, 0x97, 0x93, 0xff, 0xfc,
+ 0xf7, 0x8a, 0x70, 0x4c, 0xe0, 0x01, 0x0f, 0xd4, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x8a, 0x70, 0x58,
+ 0xe0, 0x01, 0x12, 0x7c, 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x8a, 0x70, 0x64, 0xe0, 0x01, 0x2c, 0xe8,
+ 0x97, 0x93, 0xff, 0xfc, 0xf7, 0x8a, 0x70, 0x70, 0xe0, 0x01, 0x17, 0xc8, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xff, 0x0c, 0x38, 0xec, 0xff, 0x8c, 0x39, 0x04, 0xfe, 0x9b, 0x58, 0x08,
+ 0x0f, 0x78, 0x00, 0x01, 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x0d, 0x38, 0xec, 0x20, 0x1e, 0x00, 0x01,
+ 0xe6, 0x02, 0x71, 0x08, 0xff, 0x8d, 0x39, 0x04, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x70, 0xcd,
+ 0x20, 0x76, 0x00, 0x0f, 0xe6, 0x02, 0x70, 0xcd, 0x20, 0x76, 0x00, 0xf0, 0xe6, 0x02, 0x70, 0xcd,
+ 0x20, 0x76, 0x00, 0xff, 0xe6, 0x02, 0x71, 0x08, 0x00, 0x00, 0x00, 0x01, 0xff, 0x1c, 0x33, 0xb0,
+ 0xff, 0x8c, 0x6c, 0xd8, 0xcf, 0xfc, 0xf2, 0x00, 0x7e, 0xfd, 0xff, 0xfe, 0xff, 0x0c, 0x39, 0x28,
+ 0xff, 0x88, 0xa9, 0x08, 0xcf, 0x78, 0xe8, 0x00, 0xc0, 0x7e, 0xf2, 0x00, 0xe6, 0x02, 0x70, 0xf9,
+ 0x00, 0x00, 0x00, 0x01, 0xf0, 0x0d, 0x72, 0x50, 0xff, 0x8c, 0x72, 0x50, 0xff, 0x09, 0xa9, 0x08,
+ 0x0f, 0xfc, 0x00, 0x01, 0xff, 0x8d, 0x72, 0x50, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
+ 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xff, 0x9b, 0x44, 0x01, 0xf4, 0x02, 0x00, 0x00,
+ 0xc0, 0x7e, 0x42, 0x00, 0xe6, 0x02, 0x71, 0x6d, 0x00, 0x00, 0x00, 0x01, 0xff, 0x9b, 0x44, 0x01,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x71, 0x5c, 0x04, 0x20, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x02, 0x00, 0x19, 0xcf, 0x9c, 0xf7, 0xc0, 0xc0, 0x1a, 0xfa, 0x00, 0xe4, 0x02, 0x71, 0xa4,
+ 0x00, 0x00, 0x00, 0x01, 0xc3, 0x18, 0xfa, 0x00, 0xc0, 0x1a, 0xfa, 0x00, 0xe4, 0x02, 0x71, 0x95,
+ 0x00, 0x00, 0x00, 0x01, 0x2f, 0x7a, 0x00, 0x01, 0xea, 0x02, 0x71, 0x84, 0xc4, 0x18, 0x00, 0x00,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0xcf, 0x18, 0x00, 0x00, 0xf3, 0x02, 0x00, 0x00, 0xfe, 0x02, 0x00, 0x19,
+ 0xfd, 0x82, 0x00, 0x01, 0xcf, 0x9c, 0xe7, 0xc0, 0xc0, 0x7a, 0xfa, 0x00, 0xe4, 0x02, 0x71, 0xf8,
+ 0x00, 0x00, 0x00, 0x01, 0xce, 0xec, 0xe7, 0xc0, 0xcf, 0x78, 0xfa, 0x00, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe4, 0x02, 0x71, 0xe9, 0xc3, 0x18, 0xe8, 0x00, 0x2e, 0x72, 0x00, 0x01, 0xea, 0x02, 0x71, 0xd4,
+ 0xc4, 0x18, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x14, 0x93, 0x16, 0xff, 0xf4,
+ 0x93, 0x16, 0xff, 0xe8, 0x94, 0x16, 0xff, 0xf0, 0x94, 0x96, 0xff, 0xec, 0xcf, 0x9c, 0x00, 0x00,
+ 0xf0, 0x1b, 0x68, 0x00, 0x83, 0x96, 0xff, 0xf0, 0xc3, 0x7c, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xe4,
+ 0xf7, 0x8a, 0x72, 0x4c, 0xe0, 0x02, 0x71, 0x78, 0x97, 0x93, 0xff, 0xfc, 0xff, 0x0a, 0x71, 0x18,
+ 0x8e, 0x96, 0xff, 0xe8, 0xa4, 0x7a, 0x40, 0x05, 0xf4, 0x77, 0x6c, 0x01, 0x8f, 0x96, 0xff, 0xe4,
+ 0x83, 0x96, 0xff, 0xf0, 0x9e, 0x96, 0xff, 0xe8, 0xc3, 0x7c, 0x00, 0x00, 0xf7, 0x8a, 0x72, 0x78,
+ 0xe0, 0x02, 0x71, 0xbc, 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x72, 0x34,
+ 0xcf, 0xa0, 0x00, 0x00, 0x8f, 0x96, 0xff, 0xec, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x72, 0xa9,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xe8, 0x8f, 0x16, 0xff, 0xf4, 0xcf, 0xf4, 0xf2, 0x00,
+ 0x8e, 0x96, 0xff, 0xec, 0x9f, 0xf6, 0x00, 0x00, 0x84, 0x16, 0xff, 0xe8, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x28, 0x66, 0x6d, 0x74, 0x20, 0x6e, 0x75, 0x6c,
+ 0x6c, 0x29, 0x0a, 0x00, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x74, 0xfe, 0x82, 0x00, 0x00, 0x93, 0x96, 0xff, 0xc4,
+ 0x94, 0x16, 0xff, 0xc0, 0x93, 0x16, 0xff, 0xc8, 0xcd, 0x24, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x00,
+ 0x9e, 0x96, 0xff, 0x90, 0xe6, 0x02, 0x73, 0x01, 0x94, 0x16, 0xff, 0xbc, 0x9e, 0x96, 0xff, 0xbc,
+ 0x8f, 0x16, 0xff, 0xc8, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x84, 0x2d, 0xff, 0x8a, 0x72, 0xb8,
+ 0x8e, 0x96, 0xff, 0xc8, 0xff, 0x02, 0x00, 0x20, 0xff, 0x82, 0x00, 0x00, 0xf3, 0x77, 0x54, 0x01,
+ 0x9f, 0x16, 0xff, 0x94, 0x9e, 0x96, 0xff, 0xc8, 0x20, 0x1a, 0x00, 0x25, 0xe6, 0x02, 0x73, 0x89,
+ 0x9f, 0x96, 0xff, 0xa4, 0x20, 0x1a, 0x00, 0x00, 0xe6, 0x02, 0x84, 0x35, 0x00, 0x00, 0x00, 0x01,
+ 0x8e, 0x96, 0xff, 0xc4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x84, 0x1d, 0x00, 0x00, 0x00, 0x01,
+ 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x73, 0x64, 0xc1, 0x74, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x96, 0xff, 0xc8, 0x8e, 0x96, 0xff, 0x90,
+ 0xf3, 0x7f, 0x54, 0x01, 0x0e, 0xf4, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xc8, 0x20, 0x1a, 0x00, 0x25,
+ 0xe6, 0x02, 0x73, 0x34, 0x9e, 0x96, 0xff, 0x90, 0x8f, 0x16, 0xff, 0xc8, 0xfc, 0x82, 0x00, 0x00,
+ 0xcb, 0x64, 0x00, 0x00, 0xfe, 0xfb, 0x58, 0x00, 0x2d, 0xf8, 0x00, 0x01, 0xcb, 0xe4, 0x00, 0x00,
+ 0x9c, 0x96, 0xff, 0xa0, 0x9c, 0x96, 0xff, 0x9c, 0x9c, 0x96, 0xff, 0x98, 0xca, 0x64, 0x00, 0x00,
+ 0xc9, 0x64, 0x00, 0x00, 0xc8, 0xe4, 0x00, 0x00, 0xcc, 0x64, 0x00, 0x00, 0xca, 0xe4, 0x00, 0x00,
+ 0xc9, 0xe4, 0x00, 0x00, 0x7f, 0xf5, 0x00, 0x18, 0x8e, 0x96, 0xff, 0xc8, 0x73, 0x7c, 0xff, 0xe8,
+ 0x2f, 0x98, 0x00, 0x23, 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x57, 0xe2, 0x02, 0x83, 0x84,
+ 0x9e, 0x96, 0xff, 0xc8, 0x7f, 0xfd, 0x00, 0x02, 0xff, 0x0a, 0x73, 0xf8, 0xae, 0xfe, 0xf0, 0x02,
+ 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x75, 0x6c, 0x00, 0x02, 0x83, 0x84,
+ 0x00, 0x02, 0x75, 0x80, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84,
+ 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x75, 0xc8, 0x00, 0x02, 0x75, 0xe8, 0x00, 0x02, 0x83, 0x84,
+ 0x00, 0x02, 0x76, 0x30, 0x00, 0x02, 0x75, 0x58, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x76, 0x44,
+ 0x00, 0x02, 0x76, 0x50, 0x00, 0x02, 0x76, 0x50, 0x00, 0x02, 0x76, 0x50, 0x00, 0x02, 0x76, 0x50,
+ 0x00, 0x02, 0x76, 0x50, 0x00, 0x02, 0x76, 0x50, 0x00, 0x02, 0x76, 0x50, 0x00, 0x02, 0x76, 0x50,
+ 0x00, 0x02, 0x76, 0x50, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84,
+ 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84,
+ 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x76, 0xbc,
+ 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84,
+ 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84,
+ 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84,
+ 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84,
+ 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0xf8,
+ 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84,
+ 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84,
+ 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x78, 0x74, 0x00, 0x02, 0x7a, 0xcc, 0x00, 0x02, 0x7b, 0x04,
+ 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x7a, 0xdc,
+ 0x00, 0x02, 0x7b, 0x04, 0x00, 0x02, 0x7f, 0xa8, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x7f, 0xb4,
+ 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x7f, 0xe0, 0x00, 0x02, 0x80, 0x80, 0x00, 0x02, 0x80, 0xf8,
+ 0x00, 0x02, 0x81, 0x1c, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x81, 0x28, 0x00, 0x02, 0x83, 0x70,
+ 0x00, 0x02, 0x83, 0x7c, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0x84, 0x00, 0x02, 0x83, 0xf8,
+ 0x00, 0x02, 0x84, 0x04, 0x00, 0x02, 0x84, 0x10, 0x8f, 0x16, 0xff, 0xc8, 0xfb, 0x82, 0x00, 0x01,
+ 0xfe, 0xfb, 0x58, 0x00, 0xe0, 0x02, 0x73, 0xc8, 0x7f, 0xf5, 0x00, 0x18, 0x8f, 0x96, 0xff, 0xc8,
+ 0xff, 0x02, 0x00, 0x01, 0xfe, 0xff, 0x58, 0x00, 0xe0, 0x02, 0x73, 0xc4, 0x9f, 0x16, 0xff, 0x9c,
+ 0x8e, 0x96, 0xff, 0xc4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x75, 0xb9, 0x00, 0x00, 0x00, 0x01,
+ 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x75, 0xa4, 0xc1, 0x74, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x96, 0xff, 0x90, 0x0f, 0xfc, 0x00, 0x01,
+ 0xe0, 0x02, 0x73, 0x10, 0x9f, 0x96, 0xff, 0x90, 0x8f, 0x16, 0xff, 0xbc, 0xf3, 0x7b, 0x64, 0x01,
+ 0xe0, 0x02, 0x75, 0xa8, 0x9f, 0x16, 0xff, 0xbc, 0x20, 0x5e, 0x00, 0x00, 0xe6, 0x02, 0x76, 0x1c,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0xea, 0x00, 0x00, 0x0d, 0x68, 0x00, 0x04, 0x20, 0x7e, 0x00, 0x00,
+ 0xec, 0x02, 0x75, 0xf9, 0x9f, 0x96, 0xff, 0xa4, 0x8f, 0x96, 0xff, 0xc8, 0xfe, 0xff, 0x58, 0x00,
+ 0xe0, 0x02, 0x73, 0xc8, 0x7f, 0xf5, 0x00, 0x18, 0x8f, 0x16, 0xff, 0xc8, 0x8f, 0x96, 0xff, 0xa0,
+ 0xfe, 0xfb, 0x58, 0x00, 0x6f, 0xfc, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xa4, 0x9f, 0x96, 0xff, 0xa0,
+ 0xcf, 0x00, 0xf2, 0x00, 0xe0, 0x02, 0x73, 0xc4, 0x9f, 0x16, 0xff, 0xa4, 0x8f, 0x96, 0xff, 0xc8,
+ 0x8a, 0x6a, 0x00, 0x00, 0xfe, 0xff, 0x58, 0x00, 0xe0, 0x02, 0x73, 0xc4, 0x0d, 0x68, 0x00, 0x04,
+ 0x8f, 0x16, 0xff, 0xc8, 0xff, 0x82, 0x00, 0x01, 0xfe, 0xfb, 0x58, 0x00, 0xe0, 0x02, 0x73, 0xc4,
+ 0x9f, 0x96, 0xff, 0xa0, 0x20, 0x5e, 0x00, 0x00, 0xe6, 0x02, 0x76, 0xad, 0xff, 0x82, 0x00, 0x30,
+ 0xfe, 0x02, 0x00, 0x00, 0x7f, 0xf1, 0x00, 0x03, 0xcf, 0xfc, 0xe0, 0x00, 0x8e, 0x96, 0xff, 0xc8,
+ 0xcf, 0xfc, 0xe0, 0x00, 0xcf, 0xfc, 0x30, 0x00, 0xf3, 0x77, 0x48, 0x00, 0xfe, 0xf7, 0x58, 0x00,
+ 0x2f, 0x18, 0x00, 0x30, 0x20, 0x7a, 0x00, 0x09, 0xe2, 0x02, 0x76, 0x90, 0x2e, 0x7c, 0x00, 0x30,
+ 0x8f, 0x16, 0xff, 0xc8, 0x0f, 0x78, 0x00, 0x01, 0xe0, 0x02, 0x76, 0x54, 0x9f, 0x16, 0xff, 0xc8,
+ 0x20, 0x5e, 0x00, 0x00, 0xe6, 0x02, 0x76, 0xa5, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x73, 0xc4,
+ 0xca, 0x70, 0x00, 0x00, 0xe0, 0x02, 0x73, 0xc4, 0x9e, 0x16, 0xff, 0xa4, 0x8f, 0x16, 0xff, 0xc8,
+ 0xfe, 0xfb, 0x58, 0x00, 0xe0, 0x02, 0x73, 0xc4, 0x9f, 0x96, 0xff, 0x94, 0xcf, 0x68, 0x00, 0x00,
+ 0x8f, 0x7a, 0x00, 0x00, 0x0d, 0x68, 0x00, 0x04, 0x8e, 0x96, 0xff, 0xa4, 0x9f, 0x16, 0xff, 0xb0,
+ 0x8f, 0xea, 0x00, 0x00, 0x20, 0x76, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xb8, 0xe6, 0x02, 0x76, 0xec,
+ 0x0d, 0x68, 0x00, 0x04, 0xff, 0x02, 0x00, 0x10, 0x9f, 0x16, 0xff, 0xa4, 0x8f, 0x96, 0xff, 0xa4,
+ 0x2f, 0xfc, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xa4, 0x8e, 0x96, 0xff, 0xa4, 0xcf, 0x84, 0x00, 0x00,
+ 0xc0, 0x76, 0xfa, 0x00, 0xe6, 0x02, 0x73, 0x11, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xb0,
+ 0x8e, 0x96, 0xff, 0xc4, 0xff, 0xfb, 0x58, 0x00, 0x20, 0x76, 0x00, 0x00, 0x7f, 0xfc, 0xff, 0xfc,
+ 0xff, 0x0a, 0x71, 0x18, 0xa3, 0x7a, 0xf8, 0x04, 0xe6, 0x02, 0x78, 0x65, 0x00, 0x00, 0x00, 0x01,
+ 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x77, 0x44, 0xc1, 0x74, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8e, 0x96, 0xff, 0xb0, 0x8f, 0x16, 0xff, 0xc4,
+ 0xff, 0xf7, 0x58, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xff, 0x02, 0x00, 0x0f, 0xcf, 0xfc, 0xf4, 0x00,
+ 0x8f, 0x16, 0xff, 0x90, 0xfe, 0x8a, 0x71, 0x18, 0xa3, 0x76, 0xf8, 0x04, 0x0f, 0x78, 0x00, 0x01,
+ 0xe6, 0x02, 0x78, 0x55, 0x9f, 0x16, 0xff, 0x90, 0x83, 0x96, 0xff, 0xc0, 0x8f, 0x96, 0xff, 0xc4,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x77, 0x90, 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x96, 0xff, 0x90, 0x8e, 0x96, 0xff, 0xb0, 0x8f, 0x16, 0xff, 0xa4,
+ 0x0f, 0xfc, 0x00, 0x01, 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x7a, 0x00, 0x00, 0x9f, 0x96, 0xff, 0x90,
+ 0xe6, 0x02, 0x78, 0x25, 0x9e, 0x96, 0xff, 0xb0, 0x8f, 0x16, 0xff, 0xb8, 0x8e, 0x96, 0xff, 0xb8,
+ 0xff, 0xfb, 0x48, 0x00, 0xff, 0x7b, 0x58, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x78, 0x25,
+ 0x9e, 0x96, 0xff, 0xb4, 0x7f, 0xf9, 0x00, 0x18, 0x8f, 0x16, 0xff, 0xc4, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x02, 0x78, 0x45, 0x73, 0x7d, 0xff, 0xe8, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x8a, 0x77, 0xfc, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8e, 0x96, 0xff, 0xb4, 0x8f, 0x96, 0xff, 0x90, 0xff, 0x77, 0x5c, 0x01, 0x0f, 0xfc, 0x00, 0x01,
+ 0x9f, 0x96, 0xff, 0x90, 0x7f, 0xf9, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x77, 0xd8,
+ 0x9e, 0x96, 0xff, 0xb4, 0x8e, 0x96, 0xff, 0xa4, 0xcf, 0x84, 0x00, 0x00, 0x2e, 0xf4, 0x00, 0x01,
+ 0xc0, 0x76, 0xfa, 0x00, 0xe6, 0x02, 0x77, 0x0c, 0x9e, 0x96, 0xff, 0xa4, 0xe0, 0x02, 0x73, 0x10,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xbc, 0xf3, 0x7f, 0x64, 0x01, 0xe0, 0x02, 0x78, 0x00,
+ 0x9f, 0x96, 0xff, 0xbc, 0x8e, 0x96, 0xff, 0xbc, 0xf3, 0x77, 0x64, 0x01, 0xe0, 0x02, 0x77, 0x94,
+ 0x9e, 0x96, 0xff, 0xbc, 0x8f, 0x96, 0xff, 0xbc, 0xf3, 0x7f, 0x64, 0x01, 0xe0, 0x02, 0x77, 0x48,
+ 0x9f, 0x96, 0xff, 0xbc, 0xcf, 0xe8, 0x00, 0x00, 0x8f, 0x6b, 0x00, 0x04, 0x8f, 0xfe, 0x00, 0x00,
+ 0x23, 0x14, 0x00, 0x30, 0xf4, 0x82, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xac, 0xf4, 0x7b, 0x44, 0x01,
+ 0xc3, 0xfc, 0x00, 0x00, 0x9d, 0x16, 0xff, 0x8c, 0x9f, 0x16, 0xff, 0xb8, 0xf7, 0x8a, 0x78, 0xa8,
+ 0xe0, 0x02, 0x72, 0x10, 0x97, 0x93, 0xff, 0xfc, 0x94, 0x16, 0xff, 0xb4, 0xff, 0xa3, 0x58, 0x00,
+ 0x8d, 0x16, 0xff, 0x8c, 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x79, 0x19,
+ 0x0d, 0x68, 0x00, 0x04, 0x8e, 0x96, 0xff, 0xb4, 0x73, 0x7d, 0xff, 0xe8, 0x8f, 0x96, 0xff, 0xc4,
+ 0x2e, 0xf4, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x7a, 0xbd, 0x9e, 0x96, 0xff, 0xb4,
+ 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x78, 0xf4, 0xc1, 0x7c, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8e, 0x96, 0xff, 0xb4, 0x8f, 0x16, 0xff, 0x90,
+ 0xff, 0xf7, 0x58, 0x00, 0x0f, 0x78, 0x00, 0x01, 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x78, 0xc4, 0x9f, 0x16, 0xff, 0x90, 0x8f, 0x96, 0xff, 0xac, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x73, 0x11, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xb8, 0x90, 0x16, 0xff, 0xcc,
+ 0xff, 0xf7, 0x58, 0x00, 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x7a, 0x2d,
+ 0x00, 0x00, 0x00, 0x01, 0x7e, 0x7d, 0xff, 0xe8, 0x2f, 0x70, 0x00, 0x01, 0xff, 0x82, 0x00, 0x01,
+ 0xcf, 0xfc, 0xf7, 0xc0, 0x8f, 0x16, 0xff, 0xac, 0xc0, 0x7a, 0xfc, 0x00, 0x8f, 0x96, 0xff, 0xb8,
+ 0x0f, 0xfc, 0x00, 0x01, 0xe6, 0x02, 0x7a, 0x81, 0x9f, 0x96, 0xff, 0xb8, 0x8f, 0x96, 0xff, 0xcc,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x79, 0x80, 0xf3, 0x02, 0x00, 0x2c, 0xf3, 0x02, 0x00, 0x3c,
+ 0x8e, 0x96, 0xff, 0xc4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x7a, 0x71, 0x00, 0x00, 0x00, 0x01,
+ 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x79, 0xa4, 0xc1, 0x74, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x96, 0xff, 0xb8, 0x8e, 0x96, 0xff, 0x90,
+ 0xfe, 0x7f, 0x48, 0x00, 0x0e, 0xf4, 0x00, 0x01, 0x20, 0x72, 0x00, 0x20, 0xee, 0x02, 0x7a, 0x0d,
+ 0x9e, 0x96, 0xff, 0x90, 0x8f, 0x16, 0xff, 0xc4, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x7a, 0x61,
+ 0xc3, 0x70, 0x00, 0x00, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x79, 0xe8,
+ 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8e, 0x96, 0xff, 0xb8,
+ 0x8f, 0x16, 0xff, 0x90, 0xfe, 0x77, 0x4c, 0x01, 0x0f, 0x78, 0x00, 0x01, 0x9e, 0x96, 0xff, 0xb8,
+ 0x20, 0x72, 0x00, 0x20, 0xee, 0x02, 0x79, 0xc4, 0x9f, 0x16, 0xff, 0x90, 0x8e, 0x96, 0xff, 0xb8,
+ 0xff, 0x82, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xcc, 0xff, 0x77, 0x58, 0x00, 0x7f, 0xf9, 0x00, 0x18,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x79, 0x44, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xcc,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x73, 0x11, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xc4,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x75, 0x90, 0xf3, 0x02, 0x00, 0x3e, 0x8f, 0x16, 0xff, 0xbc,
+ 0xf7, 0x82, 0x00, 0x3e, 0xf7, 0xfb, 0x64, 0x01, 0xe0, 0x02, 0x75, 0xa8, 0x9f, 0x16, 0xff, 0xbc,
+ 0x8f, 0x96, 0xff, 0xbc, 0xfe, 0x7f, 0x64, 0x01, 0xe0, 0x02, 0x79, 0xec, 0x9f, 0x96, 0xff, 0xbc,
+ 0x8f, 0x16, 0xff, 0xbc, 0xf3, 0x7b, 0x64, 0x01, 0xe0, 0x02, 0x79, 0xa8, 0x9f, 0x16, 0xff, 0xbc,
+ 0x8f, 0x16, 0xff, 0xb8, 0xff, 0xfb, 0x48, 0x00, 0xff, 0x7b, 0x58, 0x00, 0x20, 0x7e, 0x00, 0x20,
+ 0xee, 0x02, 0x7a, 0x21, 0x7f, 0xf9, 0x00, 0x18, 0x8f, 0x96, 0xff, 0xb8, 0xff, 0x7f, 0x5c, 0x01,
+ 0x9f, 0x96, 0xff, 0xb8, 0x7f, 0xf9, 0x00, 0x18, 0x20, 0x7f, 0x20, 0x00, 0xee, 0x02, 0x7a, 0x98,
+ 0x20, 0x7e, 0x00, 0x00, 0xe0, 0x02, 0x7a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xbc,
+ 0xf3, 0x7b, 0x64, 0x01, 0xe0, 0x02, 0x78, 0xf8, 0x9f, 0x16, 0xff, 0xbc, 0x83, 0x6a, 0x00, 0x00,
+ 0x8e, 0x96, 0xff, 0xc4, 0xe0, 0x02, 0x75, 0x84, 0x0d, 0x68, 0x00, 0x04, 0x20, 0x46, 0x00, 0x00,
+ 0xe6, 0x02, 0x7a, 0xf9, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xc8, 0xf8, 0x82, 0x00, 0x00,
+ 0xe0, 0x02, 0x75, 0xec, 0xf9, 0x02, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xc8, 0xe0, 0x02, 0x75, 0x60,
+ 0xf8, 0x82, 0x00, 0x01, 0xff, 0x02, 0x00, 0x0a, 0x9f, 0x16, 0xff, 0xa8, 0x20, 0x62, 0x00, 0x00,
+ 0xe6, 0x02, 0x7f, 0x58, 0xff, 0x02, 0x00, 0x01, 0x20, 0x5a, 0x00, 0x00, 0xe6, 0x02, 0x7f, 0x41,
+ 0x20, 0x56, 0x00, 0x00, 0x8f, 0xea, 0x00, 0x04, 0x0d, 0x68, 0x00, 0x08, 0x9f, 0x96, 0xff, 0xac,
+ 0x8f, 0x96, 0xff, 0xac, 0x20, 0x7e, 0x00, 0x00, 0xec, 0x02, 0x7f, 0x31, 0xfe, 0x82, 0x00, 0x01,
+ 0x83, 0x96, 0xff, 0xac, 0x84, 0x16, 0xff, 0xa8, 0x9d, 0x16, 0xff, 0x8c, 0x23, 0x14, 0x00, 0x30,
+ 0x24, 0x94, 0x00, 0x34, 0xf7, 0x8a, 0x7b, 0x60, 0xe0, 0x02, 0x72, 0x10, 0x97, 0x93, 0xff, 0xfc,
+ 0x8f, 0x16, 0xff, 0x9c, 0x8d, 0x16, 0xff, 0x8c, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x7b, 0xa5,
+ 0x94, 0x16, 0xff, 0xb8, 0x8f, 0x96, 0xff, 0xac, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x7b, 0xa5,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xa8, 0x20, 0x76, 0x00, 0x08, 0xe6, 0x02, 0x7f, 0x25,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xa8, 0x20, 0x7a, 0x00, 0x10, 0xe6, 0x02, 0x7f, 0x15,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0x98, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x7b, 0xc1,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xcc, 0x0f, 0xfc, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xcc,
+ 0x8e, 0x96, 0xff, 0xa0, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x7c, 0x58, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x16, 0xff, 0xa4, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x7c, 0x59, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x96, 0xff, 0xcc, 0xcf, 0x78, 0xfa, 0x00, 0x20, 0x7a, 0x00, 0x00, 0xee, 0x02, 0x7c, 0x59,
+ 0x9f, 0x16, 0xff, 0xa4, 0x2f, 0x78, 0x00, 0x01, 0xcf, 0x84, 0x00, 0x00, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe6, 0x02, 0x7c, 0x59, 0x9f, 0x16, 0xff, 0xa4, 0x8f, 0x96, 0xff, 0xc4, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x7f, 0x01, 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0x94, 0x83, 0x96, 0xff, 0xc0,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x7c, 0x30, 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x96, 0xff, 0xa4, 0x8f, 0x16, 0xff, 0x90, 0xce, 0x84, 0x00, 0x00,
+ 0x2f, 0xfc, 0x00, 0x01, 0x0f, 0x78, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xa4, 0xc0, 0x7e, 0xea, 0x00,
+ 0xe6, 0x02, 0x7c, 0x08, 0x9f, 0x16, 0xff, 0x90, 0x8f, 0x96, 0xff, 0x98, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x7c, 0x9d, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xc4, 0x20, 0x76, 0x00, 0x00,
+ 0xe6, 0x02, 0x7e, 0xed, 0xf3, 0x02, 0x00, 0x2d, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x8a, 0x7c, 0x8c, 0xc1, 0x74, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8f, 0x96, 0xff, 0x90, 0x0f, 0xfc, 0x00, 0x01, 0x9f, 0x96, 0xff, 0x90, 0x8e, 0x96, 0xff, 0x9c,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x7c, 0xdd, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xac,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x7c, 0xdd, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xa8,
+ 0x20, 0x7e, 0x00, 0x08, 0xe6, 0x02, 0x7e, 0xa1, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xa8,
+ 0x20, 0x76, 0x00, 0x10, 0xe6, 0x02, 0x7e, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xb8,
+ 0xff, 0xfb, 0x58, 0x00, 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x7d, 0x49,
+ 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xb8, 0x73, 0x7d, 0xff, 0xe8, 0x8f, 0x96, 0xff, 0xc4,
+ 0x2e, 0xf4, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x7d, 0xfd, 0x9e, 0x96, 0xff, 0xb8,
+ 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x7d, 0x24, 0xc1, 0x7c, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8e, 0x96, 0xff, 0xb8, 0x8f, 0x16, 0xff, 0x90,
+ 0xff, 0xf7, 0x58, 0x00, 0x0f, 0x78, 0x00, 0x01, 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x7c, 0xf4, 0x9f, 0x16, 0xff, 0x90, 0x8f, 0x96, 0xff, 0xa0, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x73, 0x11, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xa4, 0x20, 0x76, 0x00, 0x00,
+ 0xe6, 0x02, 0x73, 0x11, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xcc, 0xce, 0xf4, 0xfa, 0x00,
+ 0x20, 0x76, 0x00, 0x00, 0xee, 0x02, 0x73, 0x11, 0x9e, 0x96, 0xff, 0xa4, 0x2e, 0xf4, 0x00, 0x01,
+ 0xcf, 0x84, 0x00, 0x00, 0xc0, 0x76, 0xfa, 0x00, 0xe6, 0x02, 0x73, 0x11, 0x9e, 0x96, 0xff, 0xa4,
+ 0x8f, 0x16, 0xff, 0xc4, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x7d, 0xe9, 0x00, 0x00, 0x00, 0x01,
+ 0x83, 0x16, 0xff, 0x94, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x7d, 0xb8,
+ 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x16, 0xff, 0xa4,
+ 0x8e, 0x96, 0xff, 0x90, 0xcf, 0x84, 0x00, 0x00, 0x2f, 0x78, 0x00, 0x01, 0x0e, 0xf4, 0x00, 0x01,
+ 0x9f, 0x16, 0xff, 0xa4, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x02, 0x7d, 0x90, 0x9e, 0x96, 0xff, 0x90,
+ 0xe0, 0x02, 0x73, 0x10, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xbc, 0x8e, 0x96, 0xff, 0x94,
+ 0xfe, 0xff, 0x64, 0x01, 0xe0, 0x02, 0x7d, 0xbc, 0x9f, 0x96, 0xff, 0xbc, 0x8f, 0x16, 0xff, 0xbc,
+ 0xf3, 0x7b, 0x64, 0x01, 0xe0, 0x02, 0x7d, 0x28, 0x9f, 0x16, 0xff, 0xbc, 0x8f, 0x16, 0xff, 0xc4,
+ 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x7e, 0x8d, 0xf3, 0x02, 0x00, 0x30, 0x83, 0x96, 0xff, 0xc0,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x7e, 0x30, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x16, 0xff, 0x90, 0x8e, 0x96, 0xff, 0xc4, 0x0f, 0x78, 0x00, 0x01,
+ 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x7e, 0x79, 0x9f, 0x16, 0xff, 0x90, 0x83, 0x96, 0xff, 0xc0,
+ 0x9d, 0x16, 0xff, 0x8c, 0xf3, 0x02, 0x00, 0x78, 0xf7, 0x8a, 0x7e, 0x64, 0xc1, 0x74, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8e, 0x96, 0xff, 0x90, 0x0e, 0xf4, 0x00, 0x01,
+ 0xe0, 0x02, 0x7c, 0xdc, 0x9e, 0x96, 0xff, 0x90, 0x8f, 0x96, 0xff, 0xbc, 0xf7, 0x82, 0x00, 0x78,
+ 0xf7, 0xff, 0x64, 0x01, 0xe0, 0x02, 0x7e, 0x68, 0x9f, 0x96, 0xff, 0xbc, 0x8f, 0x96, 0xff, 0xbc,
+ 0xf7, 0x82, 0x00, 0x30, 0xf7, 0xff, 0x64, 0x01, 0xe0, 0x02, 0x7e, 0x34, 0x9f, 0x96, 0xff, 0xbc,
+ 0x8e, 0x96, 0xff, 0xc4, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x7e, 0xd9, 0xf3, 0x02, 0x00, 0x30,
+ 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x7e, 0xc4, 0xc1, 0x74, 0x00, 0x00,
+ 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0x8f, 0x96, 0xff, 0x90, 0x0f, 0xfc, 0x00, 0x01,
+ 0xe0, 0x02, 0x7c, 0xdc, 0x9f, 0x96, 0xff, 0x90, 0x8f, 0x16, 0xff, 0xbc, 0xf7, 0x82, 0x00, 0x30,
+ 0xf7, 0xfb, 0x64, 0x01, 0xe0, 0x02, 0x7e, 0xc8, 0x9f, 0x16, 0xff, 0xbc, 0x8f, 0x16, 0xff, 0xbc,
+ 0xf7, 0x82, 0x00, 0x2d, 0xf7, 0xfb, 0x64, 0x01, 0xe0, 0x02, 0x7c, 0x90, 0x9f, 0x16, 0xff, 0xbc,
+ 0x8e, 0x96, 0xff, 0xbc, 0x8f, 0x16, 0xff, 0x94, 0xff, 0x77, 0x64, 0x01, 0xe0, 0x02, 0x7c, 0x34,
+ 0x9e, 0x96, 0xff, 0xbc, 0x8f, 0x96, 0xff, 0xcc, 0x0f, 0xfc, 0x00, 0x02, 0xe0, 0x02, 0x7b, 0xa4,
+ 0x9f, 0x96, 0xff, 0xcc, 0x8f, 0x96, 0xff, 0xcc, 0xe0, 0x02, 0x7f, 0x1c, 0x0f, 0xfc, 0x00, 0x01,
+ 0xcf, 0x80, 0xfa, 0x00, 0x9e, 0x96, 0xff, 0x98, 0xe0, 0x02, 0x7b, 0x40, 0x9f, 0x96, 0xff, 0xac,
+ 0xe6, 0x02, 0x7f, 0x58, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x02, 0x7f, 0x58, 0x20, 0x4e, 0x00, 0x00,
+ 0xe6, 0x02, 0x7f, 0x69, 0x20, 0x46, 0x00, 0x00, 0x8f, 0xea, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xac,
+ 0xe0, 0x02, 0x7b, 0x30, 0x0d, 0x68, 0x00, 0x04, 0xe6, 0x02, 0x7f, 0x7d, 0x20, 0x4a, 0x00, 0x00,
+ 0xff, 0xeb, 0x08, 0x02, 0xe0, 0x02, 0x7f, 0x60, 0x9f, 0x96, 0xff, 0xac, 0xe6, 0x02, 0x7f, 0x91,
+ 0x20, 0x7a, 0x00, 0x00, 0xff, 0xeb, 0x48, 0x03, 0xe0, 0x02, 0x7f, 0x60, 0x9f, 0x96, 0xff, 0xac,
+ 0x8f, 0xea, 0x00, 0x00, 0x9f, 0x96, 0xff, 0xac, 0xe6, 0x02, 0x7b, 0x41, 0x0d, 0x68, 0x00, 0x04,
+ 0xe0, 0x02, 0x7b, 0x30, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xc8, 0xe0, 0x02, 0x75, 0xec,
+ 0xfc, 0x02, 0x00, 0x01, 0x20, 0x66, 0x00, 0x00, 0xe6, 0x02, 0x7f, 0xd5, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x16, 0xff, 0xc8, 0xfc, 0x82, 0x00, 0x00, 0xfe, 0xfb, 0x58, 0x00, 0xe0, 0x02, 0x73, 0xc4,
+ 0xfb, 0x02, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xc8, 0xe0, 0x02, 0x75, 0xec, 0xfc, 0x82, 0x00, 0x01,
+ 0x20, 0x62, 0x00, 0x00, 0xe6, 0x02, 0x80, 0x20, 0x20, 0x5a, 0x00, 0x00, 0xe6, 0x02, 0x80, 0x11,
+ 0x20, 0x66, 0x00, 0x00, 0x8f, 0x16, 0xff, 0x90, 0x8e, 0x6a, 0x00, 0x00, 0x7e, 0xf9, 0xff, 0xe1,
+ 0x9f, 0x72, 0x00, 0x04, 0x9e, 0xf2, 0x00, 0x00, 0xe0, 0x02, 0x73, 0x10, 0x0d, 0x68, 0x00, 0x04,
+ 0xe6, 0x02, 0x80, 0x6c, 0x20, 0x4e, 0x00, 0x00, 0xe6, 0x02, 0x80, 0x35, 0x20, 0x46, 0x00, 0x00,
+ 0x8f, 0x6a, 0x00, 0x00, 0x8e, 0x96, 0xff, 0x90, 0x0d, 0x68, 0x00, 0x04, 0xe0, 0x02, 0x73, 0x10,
+ 0x9e, 0xfa, 0x00, 0x00, 0xe6, 0x02, 0x80, 0x51, 0x20, 0x4a, 0x00, 0x00, 0x8f, 0x6a, 0x00, 0x00,
+ 0x8f, 0x96, 0xff, 0x90, 0x0d, 0x68, 0x00, 0x04, 0xe0, 0x02, 0x73, 0x10, 0xff, 0xfb, 0x28, 0x00,
+ 0xe6, 0x02, 0x80, 0x6d, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x6a, 0x00, 0x00, 0x8e, 0x96, 0xff, 0x90,
+ 0x0d, 0x68, 0x00, 0x04, 0xe0, 0x02, 0x73, 0x10, 0xfe, 0xfb, 0x68, 0x00, 0x8f, 0x6a, 0x00, 0x00,
+ 0x8f, 0x96, 0xff, 0x90, 0x0d, 0x68, 0x00, 0x04, 0xe0, 0x02, 0x73, 0x10, 0x9f, 0xfa, 0x00, 0x00,
+ 0xfe, 0x82, 0x00, 0x08, 0x9e, 0x96, 0xff, 0xa8, 0x20, 0x62, 0x00, 0x00, 0xe6, 0x02, 0x80, 0xec,
+ 0x20, 0x5a, 0x00, 0x00, 0xe6, 0x02, 0x80, 0xa9, 0x20, 0x56, 0x00, 0x00, 0x8f, 0xea, 0x00, 0x04,
+ 0xe0, 0x02, 0x7f, 0x38, 0x0d, 0x68, 0x00, 0x08, 0xe6, 0x02, 0x80, 0xec, 0x20, 0x66, 0x00, 0x00,
+ 0xe6, 0x02, 0x80, 0xec, 0x20, 0x4e, 0x00, 0x00, 0xe6, 0x02, 0x80, 0xec, 0x20, 0x46, 0x00, 0x00,
+ 0xe6, 0x02, 0x80, 0xd9, 0x20, 0x4a, 0x00, 0x00, 0xff, 0xeb, 0x18, 0x02, 0x9f, 0x96, 0xff, 0xac,
+ 0xe0, 0x02, 0x7b, 0x40, 0x0d, 0x68, 0x00, 0x04, 0xe6, 0x02, 0x80, 0xed, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0xeb, 0x58, 0x03, 0xe0, 0x02, 0x80, 0xd0, 0x9f, 0x96, 0xff, 0xac, 0x8f, 0xea, 0x00, 0x00,
+ 0xe0, 0x02, 0x80, 0xd0, 0x9f, 0x96, 0xff, 0xac, 0x8f, 0xea, 0x00, 0x00, 0x8f, 0x16, 0xff, 0xa4,
+ 0xfe, 0x82, 0x00, 0x10, 0x9f, 0x96, 0xff, 0xac, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x7c, 0x00, 0x03,
+ 0x9f, 0x96, 0xff, 0x9c, 0xe0, 0x02, 0x80, 0xd0, 0x9e, 0x96, 0xff, 0xa8, 0x8f, 0x16, 0xff, 0xc8,
+ 0xe0, 0x02, 0x7f, 0xc8, 0x00, 0x00, 0x00, 0x01, 0x8f, 0xea, 0x00, 0x00, 0x0d, 0x68, 0x00, 0x04,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x83, 0x65, 0x9f, 0x96, 0xff, 0xb8, 0x20, 0x5e, 0x00, 0x00,
+ 0xe6, 0x02, 0x83, 0x45, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x02, 0x00, 0x00, 0xc0, 0x72, 0xa2, 0x00,
+ 0xec, 0x02, 0x81, 0x90, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xb8, 0xff, 0xf7, 0x48, 0x00,
+ 0xc0, 0x7e, 0xe2, 0x00, 0xe6, 0x02, 0x81, 0x91, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x70, 0x00, 0x01,
+ 0xc0, 0x72, 0xa2, 0x00, 0xec, 0x02, 0x81, 0x90, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xb8,
+ 0xaf, 0xfa, 0xe0, 0x04, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x01,
+ 0x8e, 0x96, 0xff, 0xa4, 0x8f, 0x96, 0xff, 0xa0, 0xce, 0xf4, 0xe2, 0x00, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x82, 0x1c, 0x9e, 0x96, 0xff, 0xa4, 0x20, 0x76, 0x00, 0x00, 0xee, 0x02, 0x82, 0x1d,
+ 0xcf, 0x84, 0x00, 0x00, 0x2e, 0xf4, 0x00, 0x01, 0xc0, 0x76, 0xfa, 0x00, 0xe6, 0x02, 0x82, 0x1d,
+ 0x9e, 0x96, 0xff, 0xa4, 0x8f, 0x16, 0xff, 0xc4, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x83, 0x31,
+ 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0x94, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c,
+ 0x9e, 0x16, 0xff, 0x84, 0xf7, 0x8a, 0x81, 0xf0, 0xc1, 0x78, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0x8e, 0x16, 0xff, 0x84, 0x8f, 0x16, 0xff, 0xa4, 0x8e, 0x96, 0xff, 0x90,
+ 0xcf, 0x84, 0x00, 0x00, 0x2f, 0x78, 0x00, 0x01, 0x0e, 0xf4, 0x00, 0x01, 0x9f, 0x16, 0xff, 0xa4,
+ 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x02, 0x81, 0xc4, 0x9e, 0x96, 0xff, 0x90, 0x2e, 0x70, 0x00, 0x01,
+ 0xcf, 0x84, 0x00, 0x00, 0xc0, 0x72, 0xfa, 0x00, 0xe6, 0x02, 0x82, 0x85, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x16, 0xff, 0xb8, 0x8f, 0x96, 0xff, 0xc4, 0xf3, 0x7b, 0x44, 0x01, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x83, 0x21, 0x9f, 0x16, 0xff, 0xb8, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c,
+ 0x9e, 0x16, 0xff, 0x84, 0xf7, 0x8a, 0x82, 0x60, 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0x8e, 0x16, 0xff, 0x84, 0x8f, 0x96, 0xff, 0x90, 0x2e, 0x70, 0x00, 0x01,
+ 0xcf, 0x04, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x01, 0xc0, 0x72, 0xf2, 0x00, 0xe6, 0x02, 0x82, 0x30,
+ 0x9f, 0x96, 0xff, 0x90, 0x8e, 0x96, 0xff, 0xa0, 0x20, 0x76, 0x00, 0x00, 0xe6, 0x02, 0x73, 0x11,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xa4, 0x20, 0x7a, 0x00, 0x00, 0xee, 0x02, 0x73, 0x11,
+ 0x2f, 0x78, 0x00, 0x01, 0xcf, 0x84, 0x00, 0x00, 0xc0, 0x7a, 0xfa, 0x00, 0xe6, 0x02, 0x73, 0x11,
+ 0x9f, 0x16, 0xff, 0xa4, 0x8f, 0x96, 0xff, 0xc4, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x83, 0x0d,
+ 0x00, 0x00, 0x00, 0x01, 0x83, 0x16, 0xff, 0x94, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c,
+ 0xf7, 0x8a, 0x82, 0xdc, 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c,
+ 0x8f, 0x96, 0xff, 0xa4, 0x8f, 0x16, 0xff, 0x90, 0xce, 0x84, 0x00, 0x00, 0x2f, 0xfc, 0x00, 0x01,
+ 0x0f, 0x78, 0x00, 0x01, 0x9f, 0x96, 0xff, 0xa4, 0xc0, 0x7e, 0xea, 0x00, 0xe6, 0x02, 0x82, 0xb4,
+ 0x9f, 0x16, 0xff, 0x90, 0xe0, 0x02, 0x73, 0x10, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xbc,
+ 0x8f, 0x16, 0xff, 0x94, 0xff, 0x77, 0x64, 0x01, 0xe0, 0x02, 0x82, 0xe0, 0x9e, 0x96, 0xff, 0xbc,
+ 0x8e, 0x96, 0xff, 0xbc, 0xf3, 0x77, 0x64, 0x01, 0xe0, 0x02, 0x82, 0x68, 0x9e, 0x96, 0xff, 0xbc,
+ 0x8f, 0x96, 0xff, 0xbc, 0x8e, 0x96, 0xff, 0x94, 0xfe, 0xff, 0x64, 0x01, 0xe0, 0x02, 0x81, 0xf8,
+ 0x9f, 0x96, 0xff, 0xbc, 0x83, 0x16, 0xff, 0xb8, 0x9d, 0x16, 0xff, 0x8c, 0xf7, 0x8a, 0x83, 0x58,
+ 0xe0, 0x02, 0x71, 0x40, 0x97, 0x93, 0xff, 0xfc, 0x8d, 0x16, 0xff, 0x8c, 0xe0, 0x02, 0x81, 0x90,
+ 0xce, 0x20, 0x00, 0x00, 0xff, 0x8a, 0x72, 0xc4, 0xe0, 0x02, 0x81, 0x3c, 0x9f, 0x96, 0xff, 0xb8,
+ 0x8f, 0x96, 0xff, 0xc8, 0xe0, 0x02, 0x75, 0xec, 0xfa, 0x82, 0x00, 0x01, 0xe0, 0x02, 0x80, 0x84,
+ 0xfe, 0x82, 0x00, 0x0a, 0x8f, 0x16, 0xff, 0xc8, 0xc0, 0x6e, 0xf2, 0x00, 0xe4, 0x02, 0x73, 0x11,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xc4, 0xf3, 0x6f, 0x44, 0x01, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x83, 0xe9, 0x00, 0x00, 0x00, 0x01, 0x83, 0x96, 0xff, 0xc0, 0x9d, 0x16, 0xff, 0x8c,
+ 0x9d, 0x96, 0xff, 0x88, 0xf7, 0x8a, 0x83, 0xc0, 0xc1, 0x7c, 0x00, 0x00, 0x97, 0x93, 0xff, 0xfc,
+ 0x8d, 0x16, 0xff, 0x8c, 0x8d, 0x96, 0xff, 0x88, 0x8f, 0x96, 0xff, 0x90, 0x8f, 0x16, 0xff, 0xc8,
+ 0x0f, 0xfc, 0x00, 0x01, 0xc0, 0x6e, 0xf2, 0x00, 0xe4, 0x02, 0x83, 0x94, 0x9f, 0x96, 0xff, 0x90,
+ 0xe0, 0x02, 0x73, 0x10, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x96, 0xff, 0xbc, 0xf3, 0x77, 0x64, 0x01,
+ 0xe0, 0x02, 0x83, 0xc8, 0x9e, 0x96, 0xff, 0xbc, 0xff, 0x02, 0x00, 0x10, 0xe0, 0x02, 0x80, 0x88,
+ 0x9f, 0x16, 0xff, 0xa8, 0xff, 0x82, 0x00, 0x10, 0xe0, 0x02, 0x7b, 0x0c, 0x9f, 0x96, 0xff, 0xa8,
+ 0x8f, 0x16, 0xff, 0xc8, 0xe0, 0x02, 0x75, 0x60, 0xf9, 0x82, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xbc,
+ 0xf3, 0x7b, 0x64, 0x01, 0xe0, 0x02, 0x73, 0x68, 0x9f, 0x16, 0xff, 0xbc, 0xe0, 0x02, 0x73, 0x10,
+ 0x9f, 0x96, 0xff, 0xc8, 0x84, 0x16, 0xff, 0x90, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x4d, 0x43, 0x50, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x32, 0x20,
+ 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x6d,
+ 0x61, 0x67, 0x69, 0x63, 0x20, 0x77, 0x61, 0x73, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x4d,
+ 0x43, 0x50, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x3a, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d,
+ 0x65, 0x64, 0x20, 0x6e, 0x69, 0x63, 0x2d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x61, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x20, 0x25, 0x64, 0x2e, 0x25, 0x30, 0x36, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0xe8, 0xfe, 0xf6, 0xe9, 0xe8,
+ 0x8f, 0xf6, 0x00, 0x08, 0x0f, 0x01, 0x70, 0x72, 0x0f, 0x78, 0x69, 0x6e, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xe6, 0x02, 0x85, 0x31, 0x2f, 0x94, 0x00, 0x70, 0x22, 0x10, 0x00, 0x0c, 0x9f, 0x92, 0x00, 0x00,
+ 0xff, 0x8a, 0x84, 0x44, 0x9f, 0x92, 0x00, 0x04, 0x8f, 0xf6, 0x00, 0x08, 0x9e, 0x96, 0xff, 0x24,
+ 0x9f, 0x92, 0x00, 0x08, 0x9f, 0x16, 0xff, 0x20, 0xf7, 0x8a, 0x84, 0xf4, 0xe0, 0x02, 0x88, 0x5c,
+ 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0x24, 0x8f, 0x16, 0xff, 0x20, 0xff, 0xf6, 0xc9, 0xe8,
+ 0x23, 0x14, 0x00, 0x70, 0x9f, 0x76, 0x00, 0x08, 0x9f, 0xf6, 0x00, 0x14, 0x90, 0x76, 0x00, 0x04,
+ 0x90, 0x76, 0x00, 0x0c, 0x90, 0x76, 0x00, 0x10, 0x02, 0x10, 0x00, 0x0c, 0xf7, 0x8a, 0x85, 0x28,
+ 0xe0, 0x02, 0x86, 0x34, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x85, 0xb8, 0xf0, 0x09, 0xa7, 0x48,
+ 0xff, 0x88, 0xa7, 0x48, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x85, 0xb5, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x02, 0xff, 0xd0, 0x4f, 0x85, 0x00, 0x4f, 0xc0, 0x7a, 0xfa, 0x00, 0xe2, 0x02, 0x85, 0xb4,
+ 0x00, 0x00, 0x00, 0x01, 0x8f, 0x76, 0x00, 0x00, 0x8f, 0x82, 0xff, 0xd0, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe2, 0x02, 0x85, 0xb5, 0x00, 0x00, 0x00, 0x01, 0x8f, 0xf6, 0x00, 0x04, 0x22, 0x10, 0x00, 0x10,
+ 0xcf, 0xfc, 0xf0, 0x00, 0x9f, 0xf6, 0x00, 0x04, 0x7f, 0xfc, 0xff, 0xff, 0x4f, 0x7d, 0x00, 0x0f,
+ 0x7f, 0xfc, 0xff, 0xec, 0x9f, 0x92, 0x00, 0x08, 0x2f, 0x94, 0x00, 0xd8, 0x9f, 0x92, 0x00, 0x00,
+ 0xff, 0x8a, 0x84, 0x6f, 0x9f, 0x12, 0x00, 0x0c, 0x9f, 0x92, 0x00, 0x04, 0xf7, 0x8a, 0x85, 0xa8,
+ 0xe0, 0x02, 0x88, 0x5c, 0x97, 0x93, 0xff, 0xfc, 0x23, 0x14, 0x00, 0xd8, 0xe0, 0x02, 0x85, 0x1c,
+ 0x02, 0x10, 0x00, 0x10, 0xf0, 0x09, 0xa7, 0x48, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x20, 0x1e, 0x00, 0x00,
+ 0xe6, 0x02, 0x85, 0xf1, 0xfe, 0x76, 0xe9, 0xe8, 0x8f, 0x1e, 0x00, 0x00, 0xf3, 0x7b, 0x68, 0x00,
+ 0x8f, 0x9e, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x02, 0x86, 0x28, 0x9f, 0x9e, 0x00, 0x00,
+ 0x8e, 0xf2, 0x00, 0x0c, 0x8d, 0x72, 0x00, 0x14, 0xff, 0x82, 0x1f, 0xff, 0xcd, 0xf4, 0xfc, 0x00,
+ 0xcf, 0x68, 0xd8, 0x00, 0x0f, 0x79, 0xff, 0xf0, 0xff, 0xb6, 0xe9, 0xe8, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe2, 0x02, 0x86, 0x1c, 0x0e, 0xf4, 0x00, 0x01, 0xb3, 0x6a, 0xd8, 0x04, 0x8f, 0x82, 0xff, 0xd0,
+ 0x9e, 0xf2, 0x00, 0x0c, 0x9f, 0xf2, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04,
+ 0x93, 0x16, 0xff, 0xf4, 0xff, 0x9b, 0x58, 0x00, 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00,
+ 0xe6, 0x02, 0x86, 0x85, 0x00, 0x00, 0x00, 0x01, 0x73, 0x7d, 0xff, 0xe8, 0xf3, 0x82, 0x00, 0x00,
+ 0xf7, 0x8a, 0x86, 0x6c, 0xe0, 0x02, 0x85, 0xc4, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4,
+ 0xff, 0xfb, 0x5c, 0x01, 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x86, 0x58,
+ 0x9f, 0x16, 0xff, 0xf4, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08, 0x93, 0x16, 0xff, 0xf4,
+ 0xff, 0x9b, 0x58, 0x00, 0xff, 0x02, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x18, 0xc0, 0x7e, 0xf2, 0x00,
+ 0xe6, 0x02, 0x86, 0xf1, 0x9f, 0x16, 0xff, 0xf0, 0x73, 0x7d, 0xff, 0xe8, 0xf3, 0x82, 0x00, 0x00,
+ 0xf7, 0x8a, 0x86, 0xcc, 0xe0, 0x02, 0x85, 0xc4, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xf4,
+ 0xff, 0xfb, 0x5c, 0x01, 0x9f, 0x16, 0xff, 0xf4, 0x8f, 0x16, 0xff, 0xf0, 0x7f, 0xfd, 0x00, 0x18,
+ 0x20, 0x7e, 0x00, 0x00, 0x0f, 0x78, 0x00, 0x01, 0xe6, 0x02, 0x86, 0xb8, 0x9f, 0x16, 0xff, 0xf0,
+ 0x84, 0x16, 0xff, 0xf0, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x25, 0x64, 0x2e, 0x25, 0x30, 0x36, 0x64, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x3c, 0x92, 0x96, 0xff, 0xd0, 0xce, 0x94, 0x00, 0x00,
+ 0x8f, 0x02, 0xff, 0xd0, 0x8f, 0xf5, 0x00, 0x04, 0x9e, 0x96, 0xff, 0xd0, 0x2e, 0x94, 0x00, 0x28,
+ 0x9f, 0x96, 0x00, 0x00, 0x9e, 0x96, 0xff, 0xd4, 0x9f, 0x16, 0xff, 0xcc, 0xf7, 0x8a, 0x87, 0x48,
+ 0xe0, 0x02, 0x84, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0xff, 0xf6, 0xe9, 0xe8, 0x8e, 0xfe, 0x00, 0x04,
+ 0x8f, 0x16, 0xff, 0xcc, 0x22, 0x10, 0x00, 0x10, 0xcf, 0x78, 0xe8, 0x00, 0x7f, 0xf8, 0xff, 0xff,
+ 0x7f, 0x78, 0xff, 0xeb, 0x4f, 0xfd, 0x00, 0x0f, 0x9f, 0x12, 0x00, 0x08, 0x9f, 0x92, 0x00, 0x0c,
+ 0x2f, 0x14, 0x00, 0x28, 0xff, 0x8a, 0x87, 0x00, 0x9f, 0x12, 0x00, 0x00, 0x9f, 0x92, 0x00, 0x04,
+ 0xf7, 0x8a, 0x87, 0x8c, 0xe0, 0x02, 0x88, 0x5c, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x16, 0xff, 0xd4,
+ 0x2e, 0x94, 0x00, 0x28, 0x2f, 0x94, 0x00, 0x0a, 0xb0, 0x76, 0x40, 0x04, 0xc0, 0x7a, 0xfa, 0x00,
+ 0xe4, 0x02, 0x88, 0x01, 0x02, 0x10, 0x00, 0x10, 0xff, 0x97, 0x4b, 0xd8, 0xff, 0x17, 0x5b, 0xd8,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x88, 0x01, 0xcf, 0xf8, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x18,
+ 0x73, 0x7d, 0xff, 0xe8, 0xf3, 0x82, 0x00, 0x00, 0xf7, 0x8a, 0x87, 0xd4, 0xe0, 0x02, 0x85, 0xc4,
+ 0x97, 0x93, 0xff, 0xfc, 0x8e, 0x96, 0xff, 0xd4, 0x2f, 0x14, 0x00, 0x0a, 0x0e, 0xf4, 0x00, 0x01,
+ 0xc0, 0x76, 0xf2, 0x00, 0xe4, 0x02, 0x88, 0x01, 0x9e, 0x96, 0xff, 0xd4, 0xff, 0xf7, 0x58, 0x00,
+ 0x7f, 0x7d, 0x00, 0x18, 0x20, 0x7a, 0x00, 0x00, 0xe6, 0x02, 0x87, 0xc0, 0x7f, 0xfd, 0x00, 0x18,
+ 0x83, 0x16, 0x00, 0x00, 0x84, 0x96, 0xff, 0xd0, 0xf3, 0x8a, 0x85, 0xc4, 0xf4, 0x02, 0x00, 0x00,
+ 0xf7, 0x8a, 0x88, 0x1c, 0xe0, 0x02, 0x72, 0xcc, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0x22, 0x10, 0x00, 0x04, 0xff, 0x8a, 0x88, 0x28,
+ 0x9f, 0x92, 0x00, 0x00, 0xf7, 0x8a, 0x88, 0x50, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x83, 0x16, 0x00, 0x04, 0x04, 0x94, 0x00, 0x08, 0xf3, 0x8a, 0x85, 0xc4,
+ 0xc4, 0x14, 0x00, 0x00, 0xf7, 0x8a, 0x88, 0x80, 0xe0, 0x02, 0x72, 0xcc, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc,
+ 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x04, 0x93, 0x16, 0xff, 0xf4, 0xc4, 0xa0, 0x00, 0x00,
+ 0xc3, 0x1c, 0x00, 0x00, 0xf3, 0x8a, 0x85, 0xc4, 0x24, 0x14, 0x00, 0x0c, 0xf7, 0x8a, 0x88, 0xb8,
+ 0xe0, 0x02, 0x72, 0xcc, 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x25, 0x63, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x08, 0x22, 0x10, 0x00, 0x08, 0xff, 0x8a, 0x88, 0xc4, 0x93, 0x12, 0x00, 0x04,
+ 0x9f, 0x92, 0x00, 0x00, 0xf7, 0x8a, 0x88, 0xf0, 0xe0, 0x02, 0x87, 0x0c, 0x97, 0x93, 0xff, 0xfc,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0xf7, 0x8a, 0x89, 0x14, 0xe0, 0x02, 0x8b, 0xe8,
+ 0x97, 0x93, 0xff, 0xfc, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x24, 0x20, 0x00, 0x01, 0xcf, 0x04, 0x00, 0x00,
+ 0xc0, 0x22, 0xf2, 0x00, 0xe6, 0x02, 0x89, 0x4d, 0xcf, 0x98, 0x00, 0x00, 0x24, 0x20, 0x00, 0x01,
+ 0xc0, 0x22, 0xf2, 0x00, 0xe6, 0x02, 0x89, 0x3c, 0xf3, 0xff, 0x64, 0x01, 0xc4, 0x18, 0x00, 0x00,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x8a, 0x15,
+ 0xce, 0x20, 0x00, 0x00, 0x24, 0x22, 0x00, 0x01, 0xe6, 0x02, 0x8a, 0x09, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x1b, 0x48, 0x00, 0xff, 0x1b, 0x58, 0x00, 0x20, 0x72, 0x00, 0x00, 0xe6, 0x02, 0x89, 0xfd,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x9f, 0x48, 0x00, 0xfe, 0x9f, 0x58, 0x00, 0xc0, 0x72, 0xfa, 0x00,
+ 0xe6, 0x02, 0x89, 0xbd, 0x7f, 0x79, 0x00, 0x18, 0x7e, 0xf5, 0x00, 0x18, 0x7e, 0x79, 0xff, 0xe8,
+ 0x7f, 0xf5, 0xff, 0xe8, 0xe0, 0x02, 0x8a, 0x14, 0xce, 0x70, 0xfa, 0x00, 0x03, 0x18, 0x00, 0x01,
+ 0x24, 0x22, 0x00, 0x01, 0xe6, 0x02, 0x8a, 0x09, 0x03, 0x9c, 0x00, 0x01, 0xfe, 0x1b, 0x48, 0x00,
+ 0xff, 0x1b, 0x58, 0x00, 0x20, 0x72, 0x00, 0x00, 0xe6, 0x02, 0x89, 0xfd, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0x9f, 0x48, 0x00, 0xfe, 0x9f, 0x58, 0x00, 0xc0, 0x72, 0xfa, 0x00, 0xe6, 0x02, 0x89, 0xbd,
+ 0x7f, 0x79, 0x00, 0x18, 0xe0, 0x02, 0x89, 0xac, 0x7e, 0xf5, 0x00, 0x18, 0xfe, 0x9f, 0x58, 0x00,
+ 0xe0, 0x02, 0x89, 0xa8, 0x7f, 0x79, 0x00, 0x18, 0xff, 0x1b, 0x58, 0x00, 0xe0, 0x02, 0x89, 0xfc,
+ 0x00, 0x00, 0x00, 0x01, 0xc4, 0x70, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xff, 0x9b, 0x44, 0x01, 0xf4, 0x02, 0x00, 0x00, 0xc0, 0x7e, 0x42, 0x00, 0xe6, 0x02, 0x8a, 0x55,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x9b, 0x44, 0x01, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8a, 0x44,
+ 0x04, 0x20, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x24, 0x20, 0x00, 0x01, 0xcf, 0x04, 0x00, 0x00,
+ 0xc0, 0x22, 0xf2, 0x00, 0xe6, 0x02, 0x8a, 0x91, 0xcf, 0x98, 0x00, 0x00, 0xfe, 0x9f, 0x54, 0x01,
+ 0x24, 0x20, 0x00, 0x01, 0xc0, 0x22, 0xf2, 0x00, 0xe6, 0x02, 0x8a, 0x7c, 0xfe, 0xff, 0x64, 0x01,
+ 0xc4, 0x18, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x22, 0x10, 0x00, 0x10, 0xff, 0x1b, 0x58, 0x00,
+ 0xcc, 0x98, 0x00, 0x00, 0x2f, 0xf8, 0x00, 0x30, 0x93, 0x96, 0xff, 0xf4, 0x7f, 0xfd, 0x00, 0x18,
+ 0x94, 0x16, 0xff, 0xf0, 0x20, 0x7f, 0x09, 0x00, 0xe2, 0x02, 0x8b, 0x94, 0xf3, 0x82, 0x00, 0x00,
+ 0x7f, 0xf9, 0x00, 0x18, 0x7f, 0x7d, 0xff, 0xe8, 0x2d, 0x78, 0x00, 0x30, 0x8f, 0x96, 0xff, 0xf0,
+ 0xc0, 0x6a, 0xfa, 0x00, 0xec, 0x02, 0x8b, 0x7c, 0x0c, 0xe4, 0x00, 0x01, 0x83, 0x16, 0xff, 0xf0,
+ 0x9c, 0x96, 0xff, 0xec, 0x9d, 0x16, 0xff, 0xe8, 0xf7, 0x8a, 0x8b, 0x04, 0xe0, 0x02, 0x8e, 0xc4,
+ 0x97, 0x93, 0xff, 0xfc, 0x8c, 0x96, 0xff, 0xec, 0x8d, 0x16, 0xff, 0xe8, 0xfd, 0xe7, 0x58, 0x00,
+ 0xc3, 0xa0, 0xd0, 0x00, 0x7e, 0x6d, 0x00, 0x18, 0x2f, 0xec, 0x00, 0x30, 0x2f, 0x6c, 0x00, 0x61,
+ 0x7f, 0xfd, 0x00, 0x18, 0x7e, 0xf1, 0xff, 0xe8, 0x7f, 0x79, 0x00, 0x18, 0x20, 0x7f, 0x09, 0x00,
+ 0xe2, 0x02, 0x8b, 0x6d, 0x2d, 0x74, 0x00, 0x30, 0x7f, 0xed, 0x00, 0x18, 0x20, 0x7b, 0x19, 0x00,
+ 0x2e, 0xec, 0x00, 0x41, 0x7f, 0x7d, 0xff, 0xe8, 0x7e, 0xf5, 0x00, 0x18, 0xe2, 0x02, 0x8b, 0x6d,
+ 0x2d, 0x78, 0x00, 0x57, 0x7f, 0xed, 0x00, 0x18, 0x20, 0x77, 0x19, 0x00, 0xfd, 0x02, 0x00, 0x7f,
+ 0xe2, 0x02, 0x8b, 0x6c, 0x7e, 0x7d, 0xff, 0xe8, 0x2d, 0x70, 0x00, 0x37, 0x8f, 0x96, 0xff, 0xf0,
+ 0xc0, 0x6a, 0xfa, 0x00, 0xec, 0x02, 0x8a, 0xed, 0x0c, 0xe4, 0x00, 0x01, 0x8f, 0x96, 0xff, 0xf4,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8b, 0xd9, 0x2c, 0xe4, 0x00, 0x01, 0xe0, 0x02, 0x8b, 0xd8,
+ 0x9c, 0xfe, 0x00, 0x00, 0x2f, 0xf8, 0x00, 0x61, 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7f, 0x19, 0x00,
+ 0xe2, 0x02, 0x8b, 0xb8, 0x2f, 0xf8, 0x00, 0x41, 0x7f, 0xf9, 0x00, 0x18, 0x7f, 0x7d, 0xff, 0xe8,
+ 0xe0, 0x02, 0x8a, 0xdc, 0x2d, 0x78, 0x00, 0x57, 0x7f, 0xfd, 0x00, 0x18, 0x20, 0x7f, 0x19, 0x00,
+ 0xe2, 0x02, 0x8a, 0xdc, 0xfd, 0x02, 0x00, 0x7f, 0x7f, 0xf9, 0x00, 0x18, 0x7f, 0x7d, 0xff, 0xe8,
+ 0xe0, 0x02, 0x8a, 0xdc, 0x2d, 0x78, 0x00, 0x37, 0xc4, 0x1c, 0x00, 0x00, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0x22, 0x10, 0x00, 0x10, 0xff, 0x02, 0x00, 0x00, 0x94, 0x16, 0xff, 0xec, 0x93, 0x16, 0xff, 0xf4,
+ 0x93, 0x96, 0xff, 0xf0, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x8c, 0x31, 0x9f, 0x16, 0xff, 0xe8,
+ 0x2f, 0xa0, 0x00, 0x02, 0x20, 0x7e, 0x00, 0x22, 0xe2, 0x02, 0x8c, 0x31, 0x00, 0x00, 0x00, 0x01,
+ 0x93, 0x1e, 0x00, 0x00, 0x84, 0x16, 0xff, 0xe8, 0xe0, 0x02, 0x8e, 0x7c, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x16, 0xff, 0xf4, 0xf3, 0x7b, 0x48, 0x00, 0xf7, 0x8a, 0x8c, 0x44, 0xe0, 0x02, 0x8f, 0x30,
+ 0x97, 0x93, 0xff, 0xfc, 0x20, 0x22, 0x00, 0x00, 0xe6, 0x02, 0x8c, 0x61, 0x00, 0x00, 0x00, 0x01,
+ 0x8f, 0x96, 0xff, 0xf4, 0x0f, 0xfc, 0x00, 0x01, 0xe0, 0x02, 0x8c, 0x30, 0x9f, 0x96, 0xff, 0xf4,
+ 0x8f, 0x16, 0xff, 0xf4, 0xff, 0xfb, 0x48, 0x00, 0x20, 0x7e, 0x00, 0x2b, 0xe6, 0x02, 0x8e, 0x75,
+ 0x0f, 0x78, 0x00, 0x01, 0x20, 0x7e, 0x00, 0x2d, 0xe6, 0x02, 0x8e, 0x69, 0xff, 0x82, 0x00, 0x01,
+ 0x8f, 0x96, 0xff, 0xec, 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8e, 0x35, 0x20, 0x7e, 0x00, 0x10,
+ 0xe6, 0x02, 0x8e, 0x35, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xec, 0x20, 0x7a, 0x00, 0x00,
+ 0xe6, 0x02, 0x8c, 0xd0, 0x20, 0x7a, 0x00, 0x20, 0x8f, 0x16, 0xff, 0xf4, 0xff, 0xfb, 0x48, 0x00,
+ 0xff, 0x02, 0x00, 0x08, 0x20, 0x7e, 0x00, 0x30, 0xe6, 0x02, 0x8c, 0xd9, 0x9f, 0x16, 0xff, 0xec,
+ 0xff, 0x82, 0x00, 0x0a, 0x9f, 0x96, 0xff, 0xec, 0x8f, 0x16, 0xff, 0xec, 0x20, 0x7a, 0x00, 0x20,
+ 0xe2, 0x02, 0x8e, 0x04, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x16, 0xff, 0xec, 0x7f, 0xf9, 0x00, 0x02,
+ 0xff, 0x0a, 0x8c, 0xf0, 0xae, 0xfe, 0xf0, 0x02, 0xc1, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8d, 0x74, 0x00, 0x02, 0x8e, 0x04,
+ 0x00, 0x02, 0x8d, 0x8c, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04,
+ 0x00, 0x02, 0x8d, 0xa4, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8d, 0xbc, 0x00, 0x02, 0x8e, 0x04,
+ 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04,
+ 0x00, 0x02, 0x8d, 0xd4, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04,
+ 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04,
+ 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04,
+ 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04, 0x00, 0x02, 0x8e, 0x04,
+ 0x00, 0x02, 0x8d, 0xec, 0x83, 0x16, 0xff, 0xf4, 0x83, 0x96, 0xff, 0xf0, 0xf4, 0x02, 0x00, 0x02,
+ 0xf7, 0x8a, 0x8d, 0x8c, 0xe0, 0x02, 0x8a, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0x83, 0x96, 0xff, 0xf0, 0xf4, 0x02, 0x00, 0x04, 0xf7, 0x8a, 0x8d, 0xa4, 0xe0, 0x02, 0x8a, 0xa0,
+ 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4, 0x83, 0x96, 0xff, 0xf0, 0xf4, 0x02, 0x00, 0x08,
+ 0xf7, 0x8a, 0x8d, 0xbc, 0xe0, 0x02, 0x8a, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0x83, 0x96, 0xff, 0xf0, 0xf4, 0x02, 0x00, 0x0a, 0xf7, 0x8a, 0x8d, 0xd4, 0xe0, 0x02, 0x8a, 0xa0,
+ 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4, 0x83, 0x96, 0xff, 0xf0, 0xf4, 0x02, 0x00, 0x10,
+ 0xf7, 0x8a, 0x8d, 0xec, 0xe0, 0x02, 0x8a, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4,
+ 0x83, 0x96, 0xff, 0xf0, 0xf4, 0x02, 0x00, 0x20, 0xf7, 0x8a, 0x8e, 0x04, 0xe0, 0x02, 0x8a, 0xa0,
+ 0x97, 0x93, 0xff, 0xfc, 0x83, 0x16, 0xff, 0xf4, 0x83, 0x96, 0xff, 0xf0, 0x84, 0x16, 0xff, 0xec,
+ 0xf7, 0x8a, 0x8e, 0x1c, 0xe0, 0x02, 0x8a, 0xa0, 0x97, 0x93, 0xff, 0xfc, 0x8f, 0x96, 0xff, 0xe8,
+ 0x20, 0x7e, 0x00, 0x00, 0xe6, 0x02, 0x8e, 0x7d, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x02, 0x8e, 0x7c,
+ 0xc4, 0x00, 0x42, 0x00, 0x8f, 0x16, 0xff, 0xf4, 0xff, 0xfb, 0x48, 0x00, 0x20, 0x7e, 0x00, 0x30,
+ 0xe6, 0x02, 0x8c, 0x98, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfb, 0x48, 0x01, 0x20, 0x7e, 0x00, 0x78,
+ 0xe6, 0x02, 0x8c, 0x98, 0x0f, 0x78, 0x00, 0x02, 0xff, 0x82, 0x00, 0x10, 0x9f, 0x96, 0xff, 0xec,
+ 0xe0, 0x02, 0x8c, 0x98, 0x9f, 0x16, 0xff, 0xf4, 0x8f, 0x16, 0xff, 0xf4, 0x9f, 0x96, 0xff, 0xe8,
+ 0xcf, 0x78, 0xf8, 0x00, 0xe0, 0x02, 0x8c, 0x80, 0x9f, 0x16, 0xff, 0xf4, 0x81, 0x16, 0xff, 0xfc,
+ 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08,
+ 0xf4, 0x02, 0x00, 0x00, 0xff, 0x82, 0x00, 0x01, 0xc0, 0x1a, 0xfc, 0x00, 0xe6, 0x02, 0x8e, 0xa9,
+ 0x73, 0x18, 0xff, 0xff, 0xc4, 0x20, 0x38, 0x00, 0x73, 0x9d, 0x00, 0x01, 0xc0, 0x1a, 0x3d, 0x00,
+ 0xe6, 0x02, 0x8e, 0x9c, 0xc0, 0x1a, 0xfc, 0x00, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00,
+ 0x82, 0x96, 0xff, 0xf8, 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x20, 0x1a, 0x00, 0x00,
+ 0xec, 0x02, 0x8f, 0x0d, 0x20, 0x1e, 0x00, 0x00, 0xec, 0x02, 0x8e, 0xf5, 0xcf, 0x80, 0x3a, 0x00,
+ 0xf7, 0x8a, 0x8e, 0xec, 0xe0, 0x02, 0x8e, 0x88, 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x8f, 0x20,
+ 0x00, 0x00, 0x00, 0x01, 0xc3, 0xfc, 0x00, 0x00, 0xf7, 0x8a, 0x8f, 0x04, 0xe0, 0x02, 0x8e, 0x88,
+ 0x97, 0x93, 0xff, 0xfc, 0xe0, 0x02, 0x8f, 0x20, 0xc4, 0x00, 0x42, 0x00, 0xc3, 0x00, 0x32, 0x00,
+ 0xec, 0x02, 0x8e, 0xf8, 0xce, 0x80, 0x3a, 0x00, 0xe0, 0x02, 0x8e, 0xe0, 0xc3, 0xf4, 0x00, 0x00,
+ 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x92, 0x93, 0xff, 0xfc, 0x02, 0x90, 0x00, 0x08, 0x20, 0x1a, 0x00, 0x20, 0xe6, 0x02, 0x8f, 0x71,
+ 0xf4, 0x02, 0x00, 0x00, 0x20, 0x1a, 0x00, 0x0c, 0xe6, 0x02, 0x8f, 0x71, 0x20, 0x1a, 0x00, 0x0a,
+ 0xe6, 0x02, 0x8f, 0x71, 0x20, 0x1a, 0x00, 0x0d, 0xe6, 0x02, 0x8f, 0x71, 0x20, 0x1a, 0x00, 0x09,
+ 0xe6, 0x02, 0x8f, 0x71, 0x20, 0x1a, 0x00, 0x0b, 0xe6, 0x02, 0x8f, 0x74, 0x00, 0x00, 0x00, 0x01,
+ 0xf4, 0x02, 0x00, 0x01, 0x81, 0x16, 0xff, 0xfc, 0x02, 0x14, 0x00, 0x00, 0x82, 0x96, 0xff, 0xf8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x14, 0xc1, 0x00, 0x00, 0x00, 0x00,
+ 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x46, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x11, 0xc8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x12, 0xc8,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xc8,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x14, 0xc1, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xe8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x80, 0x54, 0x05, 0x00, 0x00, 0x13, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5c, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x03, 0x64, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0xcc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x78, 0xff, 0x00, 0x00, 0x28, 0x10, 0x00, 0x00, 0x13, 0x28,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf4, 0x81, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x34,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xf4,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xd0, 0x09, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x7c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xdc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xa8,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x54,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x11, 0x00, 0x00, 0x1b, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x81, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1f, 0xf0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x31, 0x00, 0x06, 0x20, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x31, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0xc1, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x18, 0x58,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x33,
+ 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
+ 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0x50, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x18, 0x00, 0x80, 0x00, 0x00,
+ 0x80, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x14, 0xc1,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x14, 0x00, 0x00, 0x86, 0x20,
+ 0x00, 0x00, 0x86, 0x2c, 0x00, 0x00, 0x86, 0x2f, 0x00, 0x00, 0x86, 0x3b, 0x00, 0x00, 0x86, 0x45,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf8, 0xe0, 0x00, 0x00, 0xfa, 0x18,
+ 0x00, 0x00, 0xf9, 0x7c, 0x00, 0x00, 0xfa, 0xb4, 0x00, 0x00, 0xfb, 0x48, 0x00, 0x00, 0xfd, 0xf0,
+ 0x00, 0x00, 0xfc, 0x9c, 0x00, 0x00, 0xff, 0x44, 0xe0, 0x01, 0x0e, 0x70, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xac, 0x45, 0x54, 0x48, 0x20, 0x31, 0x2e, 0x34, 0x2e, 0x32, 0x36, 0x20, 0x2d,
+ 0x2d, 0x20, 0x32, 0x30, 0x30, 0x37, 0x2f, 0x31, 0x30, 0x2f, 0x33, 0x30, 0x20, 0x32, 0x33, 0x3a,
+ 0x35, 0x39, 0x3a, 0x35, 0x37, 0x20, 0x6d, 0x79, 0x72, 0x69, 0x31, 0x30, 0x67, 0x65, 0x20, 0x66,
+ 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x1d, 0xfe, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x97, 0xc0, 0x00, 0x00, 0x00, 0x28,
+ 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x58, 0x48, 0x00, 0x01, 0x55, 0x58, 0x00, 0x01, 0x50, 0xe0,
+ 0x00, 0x01, 0x4b, 0x14, 0x00, 0x01, 0x43, 0xf4, 0x00, 0x01, 0x75, 0x80, 0x00, 0x01, 0x72, 0x78,
+ 0x00, 0x01, 0x6d, 0xe8, 0x00, 0x01, 0x68, 0x04, 0x00, 0x01, 0x60, 0xcc, 0x00, 0x01, 0x75, 0x80,
+ 0x00, 0x01, 0x72, 0x78, 0x00, 0x01, 0x6d, 0xe8, 0x00, 0x01, 0x68, 0x04, 0x00, 0x01, 0x7e, 0x18,
+ 0x00, 0x01, 0x75, 0x80, 0x00, 0x01, 0x98, 0xe0, 0x00, 0x01, 0x94, 0x30, 0x00, 0x01, 0x8e, 0x30,
+ 0x00, 0x01, 0x86, 0xbc, 0x00, 0x01, 0x75, 0x80, 0x00, 0x01, 0xa3, 0x80, 0x00, 0x01, 0x9e, 0xbc,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+};
diff --git a/sys/src/9/pc/ethermii.c b/sys/src/9/pc/ethermii.c
new file mode 100755
index 000000000..90b219b3f
--- /dev/null
+++ b/sys/src/9/pc/ethermii.c
@@ -0,0 +1,235 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+int
+mii(Mii* mii, int mask)
+{
+ MiiPhy *miiphy;
+ int bit, oui, phyno, r, rmask;
+
+ /*
+ * Probe through mii for PHYs in mask;
+ * return the mask of those found in the current probe.
+ * If the PHY has not already been probed, update
+ * the Mii information.
+ */
+ rmask = 0;
+ for(phyno = 0; phyno < NMiiPhy; phyno++){
+ bit = 1<<phyno;
+ if(!(mask & bit))
+ continue;
+ if(mii->mask & bit){
+ rmask |= bit;
+ continue;
+ }
+ if(mii->mir(mii, phyno, Bmsr) == -1)
+ continue;
+ r = mii->mir(mii, phyno, Phyidr1);
+ oui = (r & 0x3FFF)<<6;
+ r = mii->mir(mii, phyno, Phyidr2);
+ oui |= r>>10;
+ if(oui == 0xFFFFF || oui == 0)
+ continue;
+
+ if((miiphy = malloc(sizeof(MiiPhy))) == nil)
+ continue;
+
+ miiphy->mii = mii;
+ miiphy->oui = oui;
+ miiphy->phyno = phyno;
+
+ miiphy->anar = ~0;
+ miiphy->fc = ~0;
+ miiphy->mscr = ~0;
+
+ mii->phy[phyno] = miiphy;
+ if(mii->curphy == nil)
+ mii->curphy = miiphy;
+ mii->mask |= bit;
+ mii->nphy++;
+
+ rmask |= bit;
+ }
+ return rmask;
+}
+
+int
+miimir(Mii* mii, int r)
+{
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ return mii->mir(mii, mii->curphy->phyno, r);
+}
+
+int
+miimiw(Mii* mii, int r, int data)
+{
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ return mii->miw(mii, mii->curphy->phyno, r, data);
+}
+
+int
+miireset(Mii* mii)
+{
+ int bmcr;
+
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
+ bmcr |= BmcrR;
+ mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
+ microdelay(1);
+
+ return 0;
+}
+
+int
+miiane(Mii* mii, int a, int p, int e)
+{
+ int anar, bmsr, mscr, r, phyno;
+
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ phyno = mii->curphy->phyno;
+
+ bmsr = mii->mir(mii, phyno, Bmsr);
+ if(!(bmsr & BmsrAna))
+ return -1;
+
+ if(a != ~0)
+ anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
+ else if(mii->curphy->anar != ~0)
+ anar = mii->curphy->anar;
+ else{
+ anar = mii->mir(mii, phyno, Anar);
+ anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
+ if(bmsr & Bmsr10THD)
+ anar |= Ana10HD;
+ if(bmsr & Bmsr10TFD)
+ anar |= Ana10FD;
+ if(bmsr & Bmsr100TXHD)
+ anar |= AnaTXHD;
+ if(bmsr & Bmsr100TXFD)
+ anar |= AnaTXFD;
+ }
+ mii->curphy->anar = anar;
+
+ if(p != ~0)
+ anar |= (AnaAP|AnaP) & p;
+ else if(mii->curphy->fc != ~0)
+ anar |= mii->curphy->fc;
+ mii->curphy->fc = (AnaAP|AnaP) & anar;
+
+ if(bmsr & BmsrEs){
+ mscr = mii->mir(mii, phyno, Mscr);
+ mscr &= ~(Mscr1000TFD|Mscr1000THD);
+ if(e != ~0)
+ mscr |= (Mscr1000TFD|Mscr1000THD) & e;
+ else if(mii->curphy->mscr != ~0)
+ mscr = mii->curphy->mscr;
+ else{
+ r = mii->mir(mii, phyno, Esr);
+ if(r & Esr1000THD)
+ mscr |= Mscr1000THD;
+ if(r & Esr1000TFD)
+ mscr |= Mscr1000TFD;
+ }
+ mii->curphy->mscr = mscr;
+ mii->miw(mii, phyno, Mscr, mscr);
+ }
+ mii->miw(mii, phyno, Anar, anar);
+
+ r = mii->mir(mii, phyno, Bmcr);
+ if(!(r & BmcrR)){
+ r |= BmcrAne|BmcrRan;
+ mii->miw(mii, phyno, Bmcr, r);
+ }
+
+ return 0;
+}
+
+int
+miistatus(Mii* mii)
+{
+ MiiPhy *phy;
+ int anlpar, bmsr, p, r, phyno;
+
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ phy = mii->curphy;
+ phyno = phy->phyno;
+
+ /*
+ * Check Auto-Negotiation is complete and link is up.
+ * (Read status twice as the Ls bit is sticky).
+ */
+ bmsr = mii->mir(mii, phyno, Bmsr);
+ if(!(bmsr & (BmsrAnc|BmsrAna))) {
+ // print("miistatus: auto-neg incomplete\n");
+ return -1;
+ }
+
+ bmsr = mii->mir(mii, phyno, Bmsr);
+ if(!(bmsr & BmsrLs)){
+ // print("miistatus: link down\n");
+ phy->link = 0;
+ return -1;
+ }
+
+ phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
+ if(phy->mscr){
+ r = mii->mir(mii, phyno, Mssr);
+ if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
+ phy->speed = 1000;
+ phy->fd = 1;
+ }
+ else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
+ phy->speed = 1000;
+ }
+
+ anlpar = mii->mir(mii, phyno, Anlpar);
+ if(phy->speed == 0){
+ r = phy->anar & anlpar;
+ if(r & AnaTXFD){
+ phy->speed = 100;
+ phy->fd = 1;
+ }
+ else if(r & AnaTXHD)
+ phy->speed = 100;
+ else if(r & Ana10FD){
+ phy->speed = 10;
+ phy->fd = 1;
+ }
+ else if(r & Ana10HD)
+ phy->speed = 10;
+ }
+ if(phy->speed == 0) {
+ // print("miistatus: phy speed 0\n");
+ return -1;
+ }
+
+ if(phy->fd){
+ p = phy->fc;
+ r = anlpar & (AnaAP|AnaP);
+ if(p == AnaAP && r == (AnaAP|AnaP))
+ phy->tfc = 1;
+ else if(p == (AnaAP|AnaP) && r == AnaAP)
+ phy->rfc = 1;
+ else if((p & AnaP) && (r & AnaP))
+ phy->rfc = phy->tfc = 1;
+ }
+
+ phy->link = 1;
+
+ return 0;
+}
diff --git a/sys/src/9/pc/ethermii.h b/sys/src/9/pc/ethermii.h
new file mode 100755
index 000000000..02a45ee5f
--- /dev/null
+++ b/sys/src/9/pc/ethermii.h
@@ -0,0 +1,116 @@
+typedef struct Mii Mii;
+typedef struct MiiPhy MiiPhy;
+
+enum { /* registers */
+ Bmcr = 0x00, /* Basic Mode Control */
+ Bmsr = 0x01, /* Basic Mode Status */
+ Phyidr1 = 0x02, /* PHY Identifier #1 */
+ Phyidr2 = 0x03, /* PHY Identifier #2 */
+ Anar = 0x04, /* Auto-Negotiation Advertisement */
+ Anlpar = 0x05, /* AN Link Partner Ability */
+ Aner = 0x06, /* AN Expansion */
+ Annptr = 0x07, /* AN Next Page TX */
+ Annprr = 0x08, /* AN Next Page RX */
+ Mscr = 0x09, /* MASTER-SLAVE Control */
+ Mssr = 0x0A, /* MASTER-SLAVE Status */
+ Esr = 0x0F, /* Extended Status */
+
+ NMiiPhyr = 32,
+ NMiiPhy = 32,
+};
+
+enum { /* Bmcr */
+ BmcrSs1 = 0x0040, /* Speed Select[1] */
+ BmcrCte = 0x0080, /* Collision Test Enable */
+ BmcrDm = 0x0100, /* Duplex Mode */
+ BmcrRan = 0x0200, /* Restart Auto-Negotiation */
+ BmcrI = 0x0400, /* Isolate */
+ BmcrPd = 0x0800, /* Power Down */
+ BmcrAne = 0x1000, /* Auto-Negotiation Enable */
+ BmcrSs0 = 0x2000, /* Speed Select[0] */
+ BmcrLe = 0x4000, /* Loopback Enable */
+ BmcrR = 0x8000, /* Reset */
+};
+
+enum { /* Bmsr */
+ BmsrEc = 0x0001, /* Extended Capability */
+ BmsrJd = 0x0002, /* Jabber Detect */
+ BmsrLs = 0x0004, /* Link Status */
+ BmsrAna = 0x0008, /* Auto-Negotiation Ability */
+ BmsrRf = 0x0010, /* Remote Fault */
+ BmsrAnc = 0x0020, /* Auto-Negotiation Complete */
+ BmsrPs = 0x0040, /* Preamble Suppression Capable */
+ BmsrEs = 0x0100, /* Extended Status */
+ Bmsr100T2HD = 0x0200, /* 100BASE-T2 HD Capable */
+ Bmsr100T2FD = 0x0400, /* 100BASE-T2 FD Capable */
+ Bmsr10THD = 0x0800, /* 10BASE-T HD Capable */
+ Bmsr10TFD = 0x1000, /* 10BASE-T FD Capable */
+ Bmsr100TXHD = 0x2000, /* 100BASE-TX HD Capable */
+ Bmsr100TXFD = 0x4000, /* 100BASE-TX FD Capable */
+ Bmsr100T4 = 0x8000, /* 100BASE-T4 Capable */
+};
+
+enum { /* Anar/Anlpar */
+ Ana10HD = 0x0020, /* Advertise 10BASE-T */
+ Ana10FD = 0x0040, /* Advertise 10BASE-T FD */
+ AnaTXHD = 0x0080, /* Advertise 100BASE-TX */
+ AnaTXFD = 0x0100, /* Advertise 100BASE-TX FD */
+ AnaT4 = 0x0200, /* Advertise 100BASE-T4 */
+ AnaP = 0x0400, /* Pause */
+ AnaAP = 0x0800, /* Asymmetrical Pause */
+ AnaRf = 0x2000, /* Remote Fault */
+ AnaAck = 0x4000, /* Acknowledge */
+ AnaNp = 0x8000, /* Next Page Indication */
+};
+
+enum { /* Mscr */
+ Mscr1000THD = 0x0100, /* Advertise 1000BASE-T HD */
+ Mscr1000TFD = 0x0200, /* Advertise 1000BASE-T FD */
+};
+
+enum { /* Mssr */
+ Mssr1000THD = 0x0400, /* Link Partner 1000BASE-T HD able */
+ Mssr1000TFD = 0x0800, /* Link Partner 1000BASE-T FD able */
+};
+
+enum { /* Esr */
+ Esr1000THD = 0x1000, /* 1000BASE-T HD Capable */
+ Esr1000TFD = 0x2000, /* 1000BASE-T FD Capable */
+ Esr1000XHD = 0x4000, /* 1000BASE-X HD Capable */
+ Esr1000XFD = 0x8000, /* 1000BASE-X FD Capable */
+};
+
+typedef struct Mii {
+ Lock;
+ int nphy;
+ int mask;
+ MiiPhy* phy[NMiiPhy];
+ MiiPhy* curphy;
+
+ void* ctlr;
+ int (*mir)(Mii*, int, int);
+ int (*miw)(Mii*, int, int, int);
+} Mii;
+
+typedef struct MiiPhy {
+ Mii* mii;
+ int oui;
+ int phyno;
+
+ int anar;
+ int fc;
+ int mscr;
+
+ int link;
+ int speed;
+ int fd;
+ int rfc;
+ int tfc;
+};
+
+extern int mii(Mii*, int);
+extern int miiane(Mii*, int, int, int);
+extern int miimir(Mii*, int);
+extern int miimiw(Mii*, int, int);
+extern int miireset(Mii*);
+extern int miistatus(Mii*);
diff --git a/sys/src/9/pc/ethersink.c b/sys/src/9/pc/ethersink.c
new file mode 100755
index 000000000..dd701804f
--- /dev/null
+++ b/sys/src/9/pc/ethersink.c
@@ -0,0 +1,65 @@
+/*
+ * An ethernet /dev/null.
+ * Useful as a bridging target with ethernet-based VPN.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+#include "etherif.h"
+
+static long
+ctl(Ether *ether, void *buf, long n)
+{
+ uchar ea[Eaddrlen];
+ Cmdbuf *cb;
+
+ cb = parsecmd(buf, n);
+ if(cb->nf >= 2
+ && strcmp(cb->f[0], "ea")==0
+ && parseether(ea, cb->f[1]) == 0){
+ free(cb);
+ memmove(ether->ea, ea, Eaddrlen);
+ memmove(ether->addr, ether->ea, Eaddrlen);
+ return 0;
+ }
+ free(cb);
+ error(Ebadctl);
+ return -1; /* not reached */
+}
+
+static void
+nop(Ether*)
+{
+}
+
+static int
+reset(Ether* ether)
+{
+ uchar ea[Eaddrlen];
+
+ if(ether->type==nil)
+ return -1;
+ memset(ea, 0, sizeof ea);
+ ether->mbps = 1000;
+ ether->attach = nop;
+ ether->transmit = nop;
+ ether->irq = -1;
+ ether->interrupt = nil;
+ ether->ifstat = nil;
+ ether->ctl = ctl;
+ ether->promiscuous = nil;
+ ether->multicast = nil;
+ ether->arg = ether;
+ return 0;
+}
+
+void
+ethersinklink(void)
+{
+ addethercard("sink", reset);
+}
diff --git a/sys/src/9/pc/ethersmc.c b/sys/src/9/pc/ethersmc.c
new file mode 100755
index 000000000..65ebffcac
--- /dev/null
+++ b/sys/src/9/pc/ethersmc.c
@@ -0,0 +1,781 @@
+/*
+ * SMC EtherEZ (SMC91cXX chip) PCMCIA card support.
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+#include "etherif.h"
+
+enum {
+ IoSize = 0x10, /* port pool size */
+ TxTimeout = 150,
+};
+
+enum { /* PCMCIA related */
+ TupleFunce = 0x22,
+ TfNodeId = 0x04,
+};
+
+enum { /* bank 0 registers */
+ Tcr = 0x0000, /* transmit control */
+ Eph = 0x0002, /* ethernet protocol handler */
+ Rcr = 0x0004, /* receiver control */
+ Counter = 0x0006, /* statistics counter */
+ MemInfo = 0x0008,
+ MemCfg = 0x000A,
+};
+
+enum { /* bank 1 registers */
+ Config = 0x0000,
+ BaseAddr = 0x0002,
+ Addr0 = 0x0004, /* ethernet address */
+ Addr1 = 0x0006,
+ Addr2 = 0x0008,
+ General = 0x000A,
+ Control = 0x000C,
+};
+
+enum { /* bank 2 registers */
+ MmuCmd = 0x0000,
+ PktNo = 0x0002,
+ AllocRes = 0x0003,
+ FifoPorts = 0x0004,
+ Pointer = 0x0006,
+ Data1 = 0x0008,
+ Interrupt = 0x000C,
+ IntrMask = 0x000D,
+};
+
+enum { /* bank 3 registers */
+ Mcast0 = 0x0000,
+ Mcast2 = 0x0002,
+ Mcast4 = 0x0004,
+ Mcast6 = 0x0006,
+ Revision = 0x000A,
+};
+
+enum {
+ BankSelect = 0x000E /* bank select register */
+};
+
+enum {
+ BsrMask = 0xFF00, /* mask for chip identification */
+ BsrId = 0x3300,
+};
+
+
+enum { /* Tcr values */
+ TcrClear = 0x0000,
+ TcrEnable = 0x0001, /* enable transmit */
+ TcrLoop = 0x0002, /* enable internal analogue loopback */
+ TcrForceCol = 0x0004, /* force collision on next tx */
+ TcrPadEn = 0x0080, /* pad short packets to 64 bytes */
+ TcrNoCrc = 0x0100, /* do not append CRC */
+ TcrMonCns = 0x0400, /* monitor carrier status */
+ TcrFduplx = 0x0800,
+ TcrStpSqet = 0x1000,
+ TcrEphLoop = 0x2000,
+ TcrNormal = TcrEnable,
+};
+
+enum { /* Eph values */
+ EphTxOk = 0x0001,
+ Eph1Col = 0x0002, /* single collision */
+ EphMCol = 0x0004, /* multiple collisions */
+ EphTxMcast = 0x0008, /* multicast transmit */
+ Eph16Col = 0x0010, /* 16 collisions, tx disabled */
+ EphSqet = 0x0020, /* SQE test failed, tx disabled */
+ EphTxBcast = 0x0040, /* broadcast tx */
+ EphDefr = 0x0080, /* deffered tx */
+ EphLatCol = 0x0200, /* late collision, tx disabled */
+ EphLostCarr = 0x0400, /* lost carrier, tx disabled */
+ EphExcDefr = 0x0800, /* excessive defferals */
+ EphCntRol = 0x1000, /* ECR counter(s) rolled over */
+ EphRxOvrn = 0x2000, /* receiver overrun, packets dropped */
+ EphLinkOk = 0x4000,
+ EphTxUnrn = 0x8000, /* tx underrun */
+};
+
+enum { /* Rcr values */
+ RcrClear = 0x0000,
+ RcrPromisc = 0x0002,
+ RcrAllMcast = 0x0004,
+ RcrEnable = 0x0100,
+ RcrStripCrc = 0x0200,
+ RcrSoftReset = 0x8000,
+ RcrNormal = RcrStripCrc | RcrEnable,
+};
+
+enum { /* Counter value masks */
+ CntColMask = 0x000F, /* collisions */
+ CntMColMask = 0x00F0, /* multiple collisions */
+ CntDtxMask = 0x0F00, /* deferred transmits */
+ CntExDtxMask = 0xF000, /* excessively deferred transmits */
+
+ CntColShr = 1,
+ CntMColShr = 4,
+ CntDtxShr = 8,
+};
+
+enum { /* MemInfo value masks */
+ MirTotalMask = 0x00FF,
+ MirFreeMask = 0xFF00,
+};
+
+enum { /* Config values */
+ CfgIrqSel0 = 0x0002,
+ CfgIrqSel1 = 0x0004,
+ CfgDisLink = 0x0040, /* disable 10BaseT link test */
+ Cfg16Bit = 0x0080,
+ CfgAuiSelect = 0x0100,
+ CfgSetSqlch = 0x0200,
+ CfgFullStep = 0x0400,
+ CfgNoWait = 0x1000,
+ CfgMiiSelect = 0x8000,
+};
+
+enum { /* Control values */
+ CtlStore = 0x0001, /* store to EEPROM */
+ CtlReload = 0x0002, /* reload EEPROM into registers */
+ CtlEeSelect = 0x0004, /* select registers for reload/store */
+ CtlTeEnable = 0x0020, /* tx error detection via eph irq */
+ CtlCrEnable = 0x0040, /* counter rollover via eph irq */
+ CtlLeEnable = 0x0080, /* link error detection via eph irq*/
+ CtlAutoRls = 0x0800, /* auto release mode */
+ CtlPowerDn = 0x2000,
+};
+
+enum { /* MmuCmd values */
+ McBusy = 0x0001,
+ McAlloc = 0x0020, /* | with number of 256 byte packets - 1 */
+ McReset = 0x0040,
+ McRelease = 0x0080, /* dequeue (but not free) current rx packet */
+ McFreePkt = 0x00A0, /* dequeue and free current rx packet */
+ McEnqueue = 0x00C0, /* enqueue the packet for tx */
+ McTxReset = 0x00E0, /* reset transmit queues */
+};
+
+enum { /* AllocRes values */
+ ArFailed = 0x80,
+};
+
+enum { /* FifoPorts values */
+ FpTxEmpty = 0x0080,
+ FpRxEmpty = 0x8000,
+ FpTxMask = 0x007F,
+ FpRxMask = 0x7F00,
+};
+
+enum { /* Pointer values */
+ PtrRead = 0x2000,
+ PtrAutoInc = 0x4000,
+ PtrRcv = 0x8000,
+};
+
+enum { /* Interrupt values */
+ IntRcv = 0x0001,
+ IntTxError = 0x0002,
+ IntTxEmpty = 0x0004,
+ IntAlloc = 0x0008,
+ IntRxOvrn = 0x0010,
+ IntEph = 0x0020,
+};
+
+enum { /* transmit status bits */
+ TsSuccess = 0x0001,
+ Ts16Col = 0x00A0,
+ TsLatCol = 0x0200,
+ TsLostCar = 0x0400,
+};
+
+enum { /* receive status bits */
+ RsMcast = 0x0001,
+ RsTooShort = 0x0400,
+ RsTooLong = 0x0800,
+ RsOddFrame = 0x1000,
+ RsBadCrc = 0x2000,
+ RsAlgnErr = 0x8000,
+ RsError = RsAlgnErr | RsBadCrc | RsTooLong | RsTooShort,
+};
+
+enum {
+ RxLenMask = 0x07FF, /* significant rx len bits */
+ HdrSize = 6, /* packet header length */
+ PageSize = 256, /* page length */
+};
+
+typedef struct Smc91xx Smc91xx;
+struct Smc91xx {
+ Lock;
+ ushort rev;
+ int attached;
+ Block *txbp;
+ ulong txtime;
+
+ ulong rovrn;
+ ulong lcar;
+ ulong col;
+ ulong scol;
+ ulong mcol;
+ ulong lcol;
+ ulong dfr;
+};
+
+#define SELECT_BANK(x) outs(port + BankSelect, x)
+
+static int
+readnodeid(int slot, Ether* ether)
+{
+ uchar data[Eaddrlen + 1];
+ int len;
+
+ len = sizeof(data);
+ if (pcmcistuple(slot, TupleFunce, TfNodeId, data, len) != len)
+ return -1;
+
+ if (data[0] != Eaddrlen)
+ return -1;
+
+ memmove(ether->ea, &data[1], Eaddrlen);
+ return 0;
+}
+
+static void
+chipreset(Ether* ether)
+{
+ int port;
+ int i;
+
+ port = ether->port;
+
+ /* reset the chip */
+ SELECT_BANK(0);
+ outs(port + Rcr, RcrSoftReset);
+ delay(1);
+ outs(port + Rcr, RcrClear);
+ outs(port + Tcr, TcrClear);
+ SELECT_BANK(1);
+ outs(port + Control, CtlAutoRls | CtlTeEnable |
+ CtlCrEnable);
+
+ for(i = 0; i < 6; i++) {
+ outb(port + Addr0 + i, ether->ea[i]);
+ }
+
+ SELECT_BANK(2);
+ outs(port + MmuCmd, McReset);
+}
+
+static void
+chipenable(Ether* ether)
+{
+ int port;
+
+ port = ether->port;
+ SELECT_BANK(0);
+ outs(port + Tcr, TcrNormal);
+ outs(port + Rcr, RcrNormal);
+ SELECT_BANK(2);
+ outb(port + IntrMask, IntEph | IntRxOvrn | IntRcv);
+}
+
+static void
+attach(Ether *ether)
+{
+ Smc91xx* ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(ctlr);
+
+ if (ctlr->attached) {
+ iunlock(ctlr);
+ return;
+ }
+
+ chipenable(ether);
+ ctlr->attached = 1;
+ iunlock(ctlr);
+}
+
+static void
+txstart(Ether* ether)
+{
+ int port;
+ Smc91xx* ctlr;
+ Block* bp;
+ int len, npages;
+ int pno;
+
+ /* assumes ctlr is locked and bank 2 is selected */
+ /* leaves bank 2 selected on return */
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ if (ctlr->txbp) {
+ bp = ctlr->txbp;
+ ctlr->txbp = 0;
+ } else {
+ bp = qget(ether->oq);
+ if (bp == 0)
+ return;
+
+ len = BLEN(bp);
+ npages = (len + HdrSize) / PageSize;
+ outs(port + MmuCmd, McAlloc | npages);
+ }
+
+ pno = inb(port + AllocRes);
+ if (pno & ArFailed) {
+ outb(port + IntrMask, inb(port + IntrMask) | IntAlloc);
+ ctlr->txbp = bp;
+ ctlr->txtime = MACHP(0)->ticks;
+ return;
+ }
+
+ outb(port + PktNo, pno);
+ outs(port + Pointer, PtrAutoInc);
+
+ len = BLEN(bp);
+ outs(port + Data1, 0);
+ outb(port + Data1, (len + HdrSize) & 0xFF);
+ outb(port + Data1, (len + HdrSize) >> 8);
+ outss(port + Data1, bp->rp, len / 2);
+ if ((len & 1) == 0) {
+ outs(port + Data1, 0);
+ } else {
+ outb(port + Data1, bp->rp[len - 1]);
+ outb(port + Data1, 0x20); /* no info what 0x20 means */
+ }
+
+ outb(port + IntrMask, inb(port + IntrMask) |
+ IntTxError | IntTxEmpty);
+
+ outs(port + MmuCmd, McEnqueue);
+ freeb(bp);
+}
+
+static void
+receive(Ether* ether)
+{
+ int port;
+ Block* bp;
+ int pktno, status, len;
+
+ /* assumes ctlr is locked and bank 2 is selected */
+ /* leaves bank 2 selected on return */
+ port = ether->port;
+
+ pktno = ins(port + FifoPorts);
+ if (pktno & FpRxEmpty) {
+ return;
+ }
+
+ outs(port + Pointer, PtrRead | PtrRcv | PtrAutoInc);
+ status = ins(port + Data1);
+ len = ins(port + Data1) & RxLenMask - HdrSize;
+
+ if (status & RsOddFrame)
+ len++;
+
+ if ((status & RsError) || (bp = iallocb(len)) == 0) {
+
+ if (status & RsAlgnErr)
+ ether->frames++;
+ if (status & (RsTooShort | RsTooLong))
+ ether->buffs++;
+ if (status & RsBadCrc)
+ ether->crcs++;
+
+ outs(port + MmuCmd, McRelease);
+ return;
+ }
+
+ /* packet length is padded to word */
+ inss(port + Data1, bp->rp, len / 2);
+ bp->wp = bp->rp + (len & ~1);
+
+ if (len & 1) {
+ *bp->wp = inb(port + Data1);
+ bp->wp++;
+ }
+
+ etheriq(ether, bp, 1);
+ ether->inpackets++;
+ outs(port + MmuCmd, McRelease);
+}
+
+static void
+txerror(Ether* ether)
+{
+ int port;
+ Smc91xx* ctlr;
+ int save_pkt;
+ int pktno, status;
+
+ /* assumes ctlr is locked and bank 2 is selected */
+ /* leaves bank 2 selected on return */
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ save_pkt = inb(port + PktNo);
+
+ pktno = ins(port + FifoPorts) & FpTxMask;
+ outb(port + PktNo, pktno);
+ outs(port + Pointer, PtrAutoInc | PtrRead);
+ status = ins(port + Data1);
+
+ if (status & TsLostCar)
+ ctlr->lcar++;
+
+ if (status & TsLatCol)
+ ctlr->lcol++;
+
+ if (status & Ts16Col)
+ ctlr->scol++;
+
+ ether->oerrs++;
+
+ SELECT_BANK(0);
+ outs(port + Tcr, ins(port + Tcr) | TcrEnable);
+
+ SELECT_BANK(2);
+ outs(port + MmuCmd, McFreePkt);
+
+ outb(port + PktNo, save_pkt);
+}
+
+static void
+eph_irq(Ether* ether)
+{
+ int port;
+ Smc91xx* ctlr;
+ ushort status;
+ int n;
+
+ /* assumes ctlr is locked and bank 2 is selected */
+ /* leaves bank 2 selected on return */
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ SELECT_BANK(0);
+ status = ins(port + Eph);
+
+ if (status & EphCntRol) {
+ /* read the counter register even if we don't need it */
+ /* otherwise we will keep getting this interrupt */
+ n = ins(port + Counter);
+ ctlr->col += (n & CntColMask) >> CntColShr;
+ ctlr->mcol += (n & CntMColMask) >> CntMColShr;
+ ctlr->dfr += (n & CntDtxMask) >> CntDtxShr;
+ }
+
+ /* if there was a transmit error, Tcr is disabled */
+ outs(port + Tcr, ins(port + Tcr) | TcrEnable);
+
+ /* clear a link error interrupt */
+ SELECT_BANK(1);
+ outs(port + Control, CtlAutoRls);
+ outs(port + Control, CtlAutoRls | CtlTeEnable | CtlCrEnable);
+
+ SELECT_BANK(2);
+}
+
+static void
+transmit(Ether* ether)
+{
+ Smc91xx* ctlr;
+ int port, n;
+
+ ctlr = ether->ctlr;
+ port = ether->port;
+ ilock(ctlr);
+
+ if (ctlr->txbp) {
+ n = TK2MS(MACHP(0)->ticks - ctlr->txtime);
+ if (n > TxTimeout) {
+ chipreset(ether);
+ chipenable(ether);
+ freeb(ctlr->txbp);
+ ctlr->txbp = 0;
+ }
+ iunlock(ctlr);
+ return;
+ }
+
+ SELECT_BANK(2);
+ txstart(ether);
+ iunlock(ctlr);
+}
+
+static void
+interrupt(Ureg*, void *arg)
+{
+ int port;
+ Smc91xx* ctlr;
+ Ether* ether;
+ int save_bank;
+ int save_pointer;
+ int mask, status;
+
+ ether = arg;
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ ilock(ctlr);
+ save_bank = ins(port + BankSelect);
+ SELECT_BANK(2);
+ save_pointer = ins(port + Pointer);
+
+ mask = inb(port + IntrMask);
+ outb(port + IntrMask, 0);
+
+ while ((status = inb(port + Interrupt) & mask) != 0) {
+ if (status & IntRcv) {
+ receive(ether);
+ }
+
+ if (status & IntTxError) {
+ txerror(ether);
+ }
+
+ if (status & IntTxEmpty) {
+ outb(port + Interrupt, IntTxEmpty);
+ outb(port + IntrMask, mask & ~IntTxEmpty);
+ txstart(ether);
+ mask = inb(port + IntrMask);
+ }
+
+ if (status & IntAlloc) {
+ outb(port + IntrMask, mask & ~IntAlloc);
+ txstart(ether);;
+ mask = inb(port + IntrMask);
+ }
+
+ if (status & IntRxOvrn) {
+ ctlr->rovrn++;
+ ether->misses++;
+ outb(port + Interrupt,IntRxOvrn);
+ }
+
+ if (status & IntEph)
+ eph_irq(ether);
+ }
+
+ outb(port + IntrMask, mask);
+ outs(port + Pointer, save_pointer);
+ outs(port + BankSelect, save_bank);
+ iunlock(ctlr);
+}
+
+static void
+promiscuous(void* arg, int on)
+{
+ int port;
+ Smc91xx *ctlr;
+ Ether* ether;
+ ushort x;
+
+ ether = arg;
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ ilock(ctlr);
+ SELECT_BANK(0);
+ x = ins(port + Rcr);
+ if (on)
+ x |= RcrPromisc;
+ else
+ x &= ~RcrPromisc;
+
+ outs(port + Rcr, x);
+ iunlock(ctlr);
+}
+
+static void
+multicast(void* arg, uchar *addr, int on)
+{
+ int port;
+ Smc91xx*ctlr;
+ Ether *ether;
+ ushort x;
+
+ USED(addr, on);
+
+ ether = arg;
+ port = ether->port;
+ ctlr = ether->ctlr;
+ ilock(ctlr);
+
+ SELECT_BANK(0);
+ x = ins(port + Rcr);
+
+ if (ether->nmaddr)
+ x |= RcrAllMcast;
+ else
+ x &= ~RcrAllMcast;
+
+ outs(port + Rcr, x);
+ iunlock(ctlr);
+}
+
+static long
+ifstat(Ether* ether, void* a, long n, ulong offset)
+{
+ static char *chiprev[] = {
+ [3] "92",
+ [5] "95",
+ [7] "100",
+ [8] "100-FD",
+ [9] "110",
+ };
+
+ Smc91xx* ctlr;
+ char* p;
+ int r, len;
+ char* s;
+
+ if (n == 0)
+ return 0;
+
+ ctlr = ether->ctlr;
+ p = malloc(READSTR);
+
+ s = 0;
+ if (ctlr->rev > 0) {
+ r = ctlr->rev >> 4;
+ if (r < nelem(chiprev))
+ s = chiprev[r];
+
+ if (r == 4) {
+ if ((ctlr->rev & 0x0F) >= 6)
+ s = "96";
+ else
+ s = "94";
+ }
+ }
+
+ len = snprint(p, READSTR, "rev: 91c%s\n", (s) ? s : "???");
+ len += snprint(p + len, READSTR - len, "rxovrn: %uld\n", ctlr->rovrn);
+ len += snprint(p + len, READSTR - len, "lcar: %uld\n", ctlr->lcar);
+ len += snprint(p + len, READSTR - len, "col: %uld\n", ctlr->col);
+ len += snprint(p + len, READSTR - len, "16col: %uld\n", ctlr->scol);
+ len += snprint(p + len, READSTR - len, "mcol: %uld\n", ctlr->mcol);
+ len += snprint(p + len, READSTR - len, "lcol: %uld\n", ctlr->lcol);
+ len += snprint(p + len, READSTR - len, "dfr: %uld\n", ctlr->dfr);
+ USED(len);
+
+ n = readstr(offset, a, n, p);
+ free(p);
+
+ return n;
+}
+
+static int
+reset(Ether* ether)
+{
+ int port;
+ int i, x;
+ char* type;
+ Smc91xx* ctlr;
+ int slot;
+ uchar ea[Eaddrlen];
+
+ if (ether->irq == 0)
+ ether->irq = 9;
+
+ if (ether->port == 0)
+ ether->port = 0x100;
+
+ type = "8020";
+ for(i = 0; i < ether->nopt; i++) {
+ if (cistrncmp(ether->opt[i], "id=", 3))
+ continue;
+ type = &ether->opt[i][3];
+ break;
+ }
+
+ if ((slot = pcmspecial(type, ether)) < 0)
+ return -1;
+
+ if (ioalloc(ether->port, IoSize, 0, "smc91cXX") < 0) {
+ pcmspecialclose(slot);
+ return -1;
+ }
+
+ ether->ctlr = malloc(sizeof(Smc91xx));
+ ctlr = ether->ctlr;
+ if (ctlr == 0) {
+ iofree(ether->port);
+ pcmspecialclose(slot);
+ return -1;
+ }
+
+ ilock(ctlr);
+ ctlr->rev = 0;
+ ctlr->txbp = nil;
+ ctlr->attached = 0;
+ ctlr->rovrn = 0;
+ ctlr->lcar = 0;
+ ctlr->col = 0;
+ ctlr->scol = 0;
+ ctlr->mcol = 0;
+ ctlr->lcol = 0;
+ ctlr->dfr = 0;
+
+ port = ether->port;
+
+ SELECT_BANK(1);
+ if ((ins(port + BankSelect) & BsrMask) != BsrId) {
+ outs(port + Control, 0); /* try powering up the chip */
+ delay(55);
+ }
+
+ outs(port + Config, ins(port + Config) | Cfg16Bit);
+ x = ins(port + BaseAddr);
+
+ if (((ins(port + BankSelect) & BsrMask) != BsrId) ||
+ ((x >> 8) == (x & 0xFF))) {
+ iunlock(ctlr);
+ iofree(port);
+ pcmspecialclose(slot);
+ return -1;
+ }
+
+ SELECT_BANK(3);
+ ctlr->rev = ins(port + Revision) & 0xFF;
+
+ memset(ea, 0, Eaddrlen);
+ if (memcmp(ea, ether->ea, Eaddrlen) == 0) {
+ if (readnodeid(slot, ether) < 0) {
+ print("Smc91cXX: cannot find ethernet address\n");
+ iunlock(ctlr);
+ iofree(port);
+ pcmspecialclose(slot);
+ return -1;
+ }
+ }
+
+ chipreset(ether);
+
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->ifstat = ifstat;
+ ether->promiscuous = promiscuous;
+ ether->multicast = multicast;
+ ether->arg = ether;
+ iunlock(ctlr);
+ return 0;
+}
+
+void
+ethersmclink(void)
+{
+ addethercard("smc91cXX", reset);
+}
diff --git a/sys/src/9/pc/ethervgbe.c b/sys/src/9/pc/ethervgbe.c
new file mode 100755
index 000000000..3f31800e6
--- /dev/null
+++ b/sys/src/9/pc/ethervgbe.c
@@ -0,0 +1,1160 @@
+/*
+ * VIA Velocity gigabit ethernet.
+ * Register info has been stolen from FreeBSD driver.
+ *
+ * Has been tested on:
+ * - VIA8237 (ABIT AV8): 100Mpbs Full duplex only.
+ * It works enough to run replica/pull, vncv, ...
+ *
+ * To do:
+ * - 64/48 bits
+ * - autonegotiation
+ * - thresholds
+ * - dynamic ring sizing ??
+ * - link status change
+ * - shutdown
+ * - promiscuous
+ * - report error
+ * - Rx/Tx Csum
+ * - Jumbo frames
+ *
+ * Philippe Anel, xigh@free.fr
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+#define DEBUG
+
+enum
+{
+ DumpIntr = (1<<0),
+ DumpRx = (1<<1),
+ DumpTx = (1<<2),
+};
+
+#define htole16(x) (x)
+#define htole32(x) (x)
+#define le32toh(x) (x)
+
+enum
+{
+ Timeout = 50000,
+ RxCount = 256,
+ TxCount = 256,
+ RxSize = 2048,
+
+ EthAddr = 0x00,
+
+ /* Command registers. */
+ Cr0S = 0x08, /* Global command 0 (Set) */
+ Cr0C = 0x0c, /* Global command 0 (Clear) */
+ Cr0_Start = 0x01, /* - start MAC */
+ Cr0_Stop = 0x02, /* - stop MAC */
+ Cr0_EnableRx = 0x04, /* - turn on Rx engine */
+ Cr0_EnableTx = 0x08, /* - turn on Tx engine */
+
+ Cr1S = 0x09, /* Global command 1 (Set) */
+ Cr1C = 0x0d, /* Global command 1 (Clear) */
+ Cr1_NoPool = 0x08, /* - disable Rx/Tx desc pool */
+ Cr1_reset = 0x80, /* - software reset */
+
+ Cr2S = 0x0a, /* Global command 2 (Set) */
+ Cr2_XonEnable = 0x80, /* - 802.3x XON/XOFF flow control */
+
+ Cr3S = 0x0b, /* Global command 3 (Set) */
+ Cr3C = 0x0f, /* Global command 3 (Set) */
+ Cr3_IntMask = 0x02, /* - Mask all interrupts */
+
+ /* Eeprom registers. */
+ Eecsr = 0x93, /* EEPROM control/status */
+ Eecsr_Autold = 0x20, /* - trigger reload from EEPROM */
+
+ /* Mii registers. */
+ MiiStatus = 0x6D, /* MII port status */
+ MiiStatus_idle = 0x80, /* - idle */
+
+ MiiCmd = 0x70, /* MII command */
+ MiiCmd_write = 0x20, /* - write */
+ MiiCmd_read = 0x40, /* - read */
+ MiiCmd_auto = 0x80, /* - enable autopolling */
+
+ MiiAddr = 0x71, /* MII address */
+ MiiData = 0x72, /* MII data */
+
+ /* 64 bits related registers. */
+ TxDescHi = 0x18,
+ DataBufHi = 0x1d,
+
+ /* Rx engine registers. */
+ RxDescLo = 0x38, /* Rx descriptor base address (lo 32 bits) */
+ RxCsrS = 0x32, /* Rx descriptor queue control/status (Set) */
+ RxCsrC = 0x36, /* Rx descriptor queue control/status (Clear) */
+ RxCsr_RunQueue = 0x01, /* - enable queue */
+ RxCsr_Active = 0x02, /* - queue active indicator */
+ RxCsr_Wakeup = 0x04, /* - wake up queue */
+ RxCsr_Dead = 0x08, /* - queue dead indicator */
+ RxNum = 0x50, /* Size of Rx desc ring */
+ RxDscIdx = 0x3c, /* Current Rx descriptor index */
+ RxResCnt = 0x5e, /* Rx descriptor residue count */
+ RxHostErr = 0x23, /* Rx host error status */
+ RxTimer = 0x3e, /* Rx queue timer pend */
+ RxControl = 0x06, /* MAC Rx control */
+ RxControl_BadFrame = 0x01, /* - accept CRC error frames */
+ RxControl_Runt = 0x02, /* - accept runts */
+ RxControl_MultiCast = 0x04, /* - accept multicasts */
+ RxControl_BroadCast = 0x08, /* - accept broadcasts */
+ RxControl_Promisc = 0x10, /* - promisc mode */
+ RxControl_Giant = 0x20, /* - accept VLAN tagged frames */
+ RxControl_UniCast = 0x40, /* - use perfect filtering */
+ RxControl_SymbolErr = 0x80, /* - accept symbol err packet */
+ RxConfig = 0x7e, /* MAC Rx config */
+ RxConfig_VlanFilter = 0x01, /* - filter VLAN ID mismatches */
+ RxConfig_VlanOpt0 = (0<<1), /* - TX: no tag insert, RX: all, no extr */
+ RxConfig_VlanOpt1 = (1<<1), /* - TX: no tag insert, RX: tagged pkts, no extr */
+ RxConfig_VlanOpt2 = (2<<1), /* - TX: tag insert, RX: all, extract tags */
+ RxConfig_VlanOpt3 = (3<<1), /* - TX: tag insert, RX: tagged pkts, with extr */
+ RxConfig_FifoLowWat = 0x08, /* - RX FIFO low watermark (7QW/15QW) */
+ RxConfig_FifoTh128 = (0<<4), /* - RX FIFO threshold 128 bytes */
+ RxConfig_FifoTh512 = (1<<4), /* - RX FIFO threshold 512 bytes */
+ RxConfig_FifoTh1024 = (2<<4), /* - RX FIFO threshold 1024 bytes */
+ RxConfig_FifoThFwd = (3<<4), /* - RX FIFO threshold ??? */
+ RxConfig_ArbPrio = 0x80, /* - arbitration priority */
+
+ /* Tx engine registers. */
+ TxDescLo = 0x40, /* Tx descriptor base address (lo 32 bits) */
+ TxCsrS = 0x30, /* Tx descriptor queue control/status (Set) */
+ TxCsrC = 0x38, /* Tx descriptor queue control/status (Clear) */
+ TxCsr_RunQueue = 0x01, /* - enable queue */
+ TxCsr_Active = 0x02, /* - queue active indicator */
+ TxCsr_Wakeup = 0x04, /* - wake up queue */
+ TxCsr_Dead = 0x08, /* - queue dead indicator */
+ TxNum = 0x52, /* Size of Tx desc ring */
+ TxDscIdx = 0x54, /* Current Tx descriptor index */
+ TxHostErr = 0x22, /* Tx host error status */
+ TxTimer = 0x3f, /* Tx queue timer pend */
+ TxControl = 0x07, /* MAC Rx control */
+ TxControl_LC_Off = (0<<0), /* - loopback control off */
+ TxControl_LC_Mac = (1<<0), /* - loopback control MAC internal */
+ TxControl_LC_Ext = (2<<0), /* - loopback control external */
+ TxControl_Coll16 = (0<<2), /* - one set of 16 retries */
+ TxControl_Coll32 = (1<<2), /* - two sets of 16 retries */
+ TxControl_Coll48 = (2<<2), /* - three sets of 16 retries */
+ TxControl_CollInf = (3<<2), /* - retry forever */
+
+ TxConfig = 0x7f, /* MAC Tx config */
+ TxConfig_SnapOpt = 0x01, /* - 1 == insert VLAN tag at 13th byte, */
+ /* 0 == insert VLAN tag after SNAP header (21st byte) */
+ TxConfig_NonBlk = 0x02, /* - priority TX/non-blocking mode */
+ TxConfig_Blk64 = (0<<3), /* - non-blocking threshold 64 packets */
+ TxConfig_Blk32 = (1<<3), /* - non-blocking threshold 32 packets */
+ TxConfig_Blk128 = (2<<3), /* - non-blocking threshold 128 packets */
+ TxConfig_Blk8 = (3<<3), /* - non-blocking threshold 8 packets */
+ TxConfig_ArbPrio = 0x80, /* - arbitration priority */
+
+ /* Timer registers. */
+ Timer0 = 0x74, /* single-shot timer */
+ Timer1 = 0x76, /* periodic timer */
+
+ /* Chip config registers. */
+ ChipCfgA = 0x78, /* chip config A */
+ ChipCfgB = 0x79, /* chip config B */
+ ChipCfgC = 0x7a, /* chip config C */
+ ChipCfgD = 0x7b, /* chip config D */
+
+ /* DMA config registers. */
+ DmaCfg0 = 0x7C, /* DMA config 0 */
+ DmaCfg1 = 0x7D, /* DMA config 1 */
+
+ /* Interrupt registers. */
+ IntCtl = 0x20, /* Interrupt control */
+ Imr = 0x28, /* Interrupt mask */
+ Isr = 0x24, /* Interrupt status */
+ Isr_RxHiPrio = (1<<0), /* - hi prio Rx int */
+ Isr_TxHiPrio = (1<<1), /* - hi prio Tx int */
+ Isr_RxComplete = (1<<2), /* - Rx queue completed */
+ Isr_TxComplete = (1<<3), /* - One of Tx queues completed */
+
+ Isr_TxComplete0 = (1<<4), /* - Tx queue 0 completed */
+ Isr_TxComplete1 = (1<<5), /* - Tx queue 1 completed */
+ Isr_TxComplete2 = (1<<6), /* - Tx queue 2 completed */
+ Isr_TxComplete3 = (1<<7), /* - Tx queue 3 completed */
+
+ Isr_Reserved8 = (1<<8), /* - reserved */
+ Isr_Reserver9 = (1<<9), /* - reserved */
+ Isr_RxCountOvflow = (1<<10), /* - Rx packet count overflow */
+ Isr_RxPause = (1<<11), /* - pause frame Rx */
+
+ Isr_RxFifoOvflow = (1<<12), /* - RX FIFO overflow */
+ Isr_RxNoDesc = (1<<13), /* - ran out of Rx descriptors */
+ Isr_RxNoDescWar = (1<<14), /* - running out of Rx descriptors */
+ Isr_LinkStatus = (1<<15), /* - link status change */
+
+ Isr_Timer0 = (1<<16), /* - one shot timer expired */
+ Isr_Timer1 = (1<<17), /* - periodic timer expired */
+ Isr_Power = (1<<18), /* - wake up power event */
+ Isr_PhyIntr = (1<<19), /* - PHY interrupt */
+
+ Isr_Stopped = (1<<20), /* - software shutdown complete */
+ Isr_MibOvflow = (1<<21), /* - MIB counter overflow warning */
+ Isr_SoftIntr = (1<<22), /* - software interrupt */
+ Isr_HoldOffReload = (1<<23), /* - reload hold timer */
+
+ Isr_RxDmaStall = (1<<24), /* - Rx DMA stall */
+ Isr_TxDmaStall = (1<<25), /* - Tx DMA stall */
+ Isr_Reserved26 = (1<<26), /* - reserved */
+ Isr_Reserved27 = (1<<27), /* - reserved */
+
+ Isr_Source0 = (1<<28), /* - interrupt source indication */
+ Isr_Source1 = (1<<29), /* - interrupt source indication */
+ Isr_Source2 = (1<<30), /* - interrupt source indication */
+ Isr_Source3 = (1<<31), /* - interrupt source indication */
+
+ Isr_Mask = Isr_TxComplete0|Isr_RxComplete|Isr_Stopped|
+ Isr_RxFifoOvflow|Isr_PhyIntr|Isr_LinkStatus|
+ Isr_RxNoDesc|Isr_RxDmaStall|Isr_TxDmaStall
+};
+
+typedef struct Frag Frag;
+struct Frag
+{
+ ulong addr_lo;
+ ushort addr_hi;
+ ushort length;
+};
+
+typedef struct RxDesc RxDesc;
+struct RxDesc
+{
+ ulong status;
+ ulong control;
+ Frag;
+};
+
+typedef struct TxDesc TxDesc;
+struct TxDesc
+{
+ ulong status;
+ ulong control;
+ Frag frags[7];
+};
+
+enum
+{
+ RxDesc_Status_VidMiss = (1<<0), /* VLAN tag filter miss */
+ RxDesc_Status_CrcErr = (1<<1), /* bad CRC error */
+ RxDesc_Status_FrAlErr = (1<<3), /* frame alignment error */
+ RxDesc_Status_CsumErr = (1<<3), /* bad TCP/IP checksum */
+ RxDesc_Status_RxLenErr = (1<<4), /* Rx length error */
+ RxDesc_Status_SymErr = (1<<5), /* PCS symbol error */
+ RxDesc_Status_SnTag = (1<<6), /* RX'ed tagged SNAP pkt */
+ RxDesc_Status_DeTag = (1<<7), /* VLAN tag extracted */
+
+ RxDesc_Status_OneFrag = (0<<8), /* only one fragment */
+ RxDesc_Status_FirstFrag = (1<<8), /* first frag in frame */
+ RxDesc_Status_LastFrag = (2<<8), /* last frag in frame */
+ RxDesc_Status_MidFrag = (3<<8), /* intermediate frag */
+
+ RxDesc_Status_Vtag = (1<<10), /* VLAN tag indicator */
+ RxDesc_Status_UniCast = (1<<11), /* unicast frame */
+ RxDesc_Status_BroadCast = (1<<12), /* broadcast frame */
+ RxDesc_Status_MultiCast = (1<<13), /* multicast frame */
+ RxDesc_Status_Perfect = (1<<14), /* perfect filter hit */
+ RxDesc_Status_Goodframe = (1<<15), /* frame is good. */
+
+ RxDesc_Status_SizShift = 16, /* received frame len shift */
+ RxDesc_Status_SizMask = 0x3FFF, /* received frame len mask */
+
+ RxDesc_Status_Shutdown = (1<<30), /* shutdown during RX */
+ RxDesc_Status_Own = (1<<31), /* own bit */
+
+ /* ... */
+ TxDesc_Status_Own = (1<<31), /* own bit */
+
+ /* ... */
+ TxDesc_Control_Intr = (1<<23), /* Tx intr request */
+ TxDesc_Control_Normal = (3<<24), /* normal frame */
+};
+
+typedef struct Stats Stats;
+struct Stats
+{
+ ulong rx;
+ ulong tx;
+ ulong txe;
+ ulong intr;
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr
+{
+ Ctlr* link;
+ Pcidev* pdev;
+ int port;
+
+ int inited;
+ Lock init_lock;
+
+ ulong debugflags;
+ ulong debugcount;
+
+ Mii* mii;
+ int active;
+ uchar ea[6];
+
+ RxDesc* rx_ring;
+ Block* rx_blocks[RxCount];
+
+ Lock tx_lock;
+ TxDesc* tx_ring;
+ Block* tx_blocks[TxCount];
+ ulong tx_count;
+
+ Stats stats;
+};
+
+static Ctlr* vgbehead;
+static Ctlr* vgbetail;
+
+#define riob(c, r) inb(c->port + r)
+#define riow(c, r) ins(c->port + r)
+#define riol(c, r) inl(c->port + r)
+#define wiob(c, r, d) outb(c->port + r, d)
+#define wiow(c, r, d) outs(c->port + r, d)
+#define wiol(c, r, d) outl(c->port + r, d)
+
+#define siob(c, r, b) wiob(c, r, riob(c, r) | b)
+#define siow(c, r, b) wiow(c, r, riob(c, r) | b)
+#define siol(c, r, b) wiol(c, r, riob(c, r) | b)
+#define ciob(c, r, b) wiob(c, r, riob(c, r) & ~b)
+#define ciow(c, r, b) wiow(c, r, riob(c, r) & ~b)
+#define ciol(c, r, b) wiol(c, r, riob(c, r) & ~b)
+
+static int
+vgbemiiw(Mii* mii, int phy, int addr, int data)
+{
+ Ctlr* ctlr;
+ int i;
+
+ if(phy != 1)
+ return -1;
+
+ ctlr = mii->ctlr;
+
+ wiob(ctlr, MiiAddr, addr);
+ wiow(ctlr, MiiData, (ushort) data);
+ wiob(ctlr, MiiCmd, MiiCmd_write);
+
+ for(i = 0; i < Timeout; i++)
+ if((riob(ctlr, MiiCmd) & MiiCmd_write) == 0)
+ break;
+
+ if(i >= Timeout){
+ print("vgbe: miiw timeout\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+vgbemiir(Mii* mii, int phy, int addr)
+{
+ Ctlr* ctlr;
+ int i;
+
+ if(phy != 1)
+ return -1;
+
+ ctlr = mii->ctlr;
+
+ wiob(ctlr, MiiAddr, addr);
+ wiob(ctlr, MiiCmd, MiiCmd_read);
+
+ for(i = 0; i < Timeout; i++)
+ if((riob(ctlr, MiiCmd) & MiiCmd_read) == 0)
+ break;
+
+ if(i >= Timeout){
+ print("vgbe: miir timeout\n");
+ return -1;
+ }
+
+ return riow(ctlr, MiiData);
+}
+
+static long
+vgbeifstat(Ether* edev, void* a, long n, ulong offset)
+{
+ char* p;
+ Ctlr* ctlr;
+ int l;
+
+ ctlr = edev->ctlr;
+
+ p = malloc(READSTR);
+ l = 0;
+ l += snprint(p+l, READSTR-l, "tx: %uld\n", ctlr->stats.tx);
+ l += snprint(p+l, READSTR-l, "tx [errs]: %uld\n", ctlr->stats.txe);
+ l += snprint(p+l, READSTR-l, "rx: %uld\n", ctlr->stats.rx);
+ l += snprint(p+l, READSTR-l, "intr: %uld\n", ctlr->stats.intr);
+ snprint(p+l, READSTR-l, "\n");
+
+ n = readstr(offset, a, n, p);
+ free(p);
+
+ return n;
+}
+
+static char* vgbeisr_info[] = {
+ "hi prio Rx int",
+ "hi prio Tx int",
+ "Rx queue completed",
+ "One of Tx queues completed",
+ "Tx queue 0 completed",
+ "Tx queue 1 completed",
+ "Tx queue 2 completed",
+ "Tx queue 3 completed",
+ "reserved",
+ "reserved",
+ "Rx packet count overflow",
+ "pause frame Rx'ed",
+ "RX FIFO overflow",
+ "ran out of Rx descriptors",
+ "running out of Rx descriptors",
+ "link status change",
+ "one shot timer expired",
+ "periodic timer expired",
+ "wake up power event",
+ "PHY interrupt",
+ "software shutdown complete",
+ "MIB counter overflow warning",
+ "software interrupt",
+ "reload hold timer",
+ "Rx DMA stall",
+ "Tx DMA stall",
+ "reserved",
+ "reserved",
+ "interrupt source indication 0",
+ "interrupt source indication 1",
+ "interrupt source indication 2",
+ "interrupt source indication 3",
+};
+
+static void
+vgbedumpisr(ulong isr)
+{
+ int i;
+
+ for(i = 0; i < 32; i++){
+ ulong mask;
+
+ mask = 1<<i;
+ if(isr & mask)
+ print("vgbe: irq: - %02d : %c %s\n", i,
+ Isr_Mask & mask ? '*' : '-', vgbeisr_info[i]);
+ }
+}
+
+static void
+noop(Block *)
+{
+}
+
+static int
+vgbenewrx(Ctlr* ctlr, int i)
+{
+ Block* block;
+ RxDesc* desc;
+
+ /*
+ * allocate a receive Block. we're maintaining
+ * a private pool of Blocks, so we don't want freeb
+ * to actually free them, thus we set block->free.
+ */
+ block = allocb(RxSize);
+ block->free = noop;
+
+ /* Remember that block. */
+ ctlr->rx_blocks[i] = block;
+
+ /* Initialize Rx descriptor. (TODO: 48/64 bits support ?) */
+ desc = &ctlr->rx_ring[i];
+ desc->status = htole32(RxDesc_Status_Own);
+ desc->control = htole32(0);
+
+ desc->addr_lo = htole32((ulong)PCIWADDR(block->rp));
+ desc->addr_hi = htole16(0);
+ desc->length = htole16(RxSize | 0x8000);
+
+ return 0;
+}
+
+static void
+vgberxeof(Ether* edev)
+{
+ Ctlr* ctlr;
+ int i;
+ Block* block;
+ ulong length, status;
+ RxDesc* desc;
+
+ ctlr = edev->ctlr;
+
+ if(ctlr->debugflags & DumpRx)
+ print("vgbe: rx_eof\n");
+
+ for(i = 0; i < RxCount; i++){
+ /* Remember that block. */
+ desc = &ctlr->rx_ring[i];
+
+ status = le32toh(desc->status);
+
+ if(status & RxDesc_Status_Own)
+ continue;
+
+ if(status & RxDesc_Status_Goodframe){
+ length = status >> RxDesc_Status_SizShift;
+ length &= RxDesc_Status_SizMask;
+
+ if(ctlr->debugflags & DumpRx)
+ print("vgbe: Rx-desc[%03d] status=%#08ulx ctl=%#08ulx len=%uld bytes\n",
+ i, status, desc->control, length);
+
+ block = ctlr->rx_blocks[i];
+ block->wp = block->rp + length;
+
+ ctlr->stats.rx++;
+ etheriq(edev, block, 1);
+ }
+ else
+ print("vgbe: Rx-desc[%#02x] *BAD FRAME* status=%#08ulx ctl=%#08ulx\n",
+ i, status, desc->control);
+
+ /* reset packet ... */
+ desc->status = htole32(RxDesc_Status_Own);
+ desc->control = htole32(0);
+ }
+
+ if(ctlr->debugflags & DumpRx)
+ print("vgbe: rx_eof: done\n");
+
+ wiow(ctlr, RxResCnt, RxCount);
+ wiob(ctlr, RxCsrS, RxCsr_Wakeup);
+}
+
+static void
+vgbetxeof(Ether* edev)
+{
+ Ctlr* ctlr;
+ int i, count;
+ Block* block;
+ ulong status;
+
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->tx_lock);
+
+ if(ctlr->debugflags & DumpTx)
+ print("vgbe: tx_eof\n");
+
+ for(count = 0, i = 0; i < TxCount; i++){
+ block = ctlr->tx_blocks[i];
+ if(block == nil)
+ continue;
+
+ status = le32toh(ctlr->tx_ring[i].status);
+ if(status & TxDesc_Status_Own)
+ continue;
+
+ /* Todo add info if it failed */
+ ctlr->stats.tx++;
+
+ if(ctlr->debugflags & DumpTx)
+ print("vgbe: Block[%03d]:%#p has been sent\n", i, block);
+
+ count++;
+ ctlr->tx_blocks[i] = nil;
+ freeb(block);
+
+ if(ctlr->debugflags & DumpTx)
+ print("vgbe: Block[%03d]:%#p has been freed\n", i, block);
+ }
+ ctlr->tx_count -= count;
+
+ if(ctlr->debugflags & DumpTx)
+ print("vgbe: tx_eof: done [count=%d]\n", count);
+
+ iunlock(&ctlr->tx_lock);
+
+ if(ctlr->tx_count)
+ wiob(ctlr, TxCsrS, TxCsr_Wakeup);
+}
+
+static void
+vgbeinterrupt(Ureg *, void* arg)
+{
+ Ether* edev;
+ Ctlr* ctlr;
+ ulong status;
+
+ edev = (Ether *) arg;
+ if(edev == nil)
+ return;
+
+ ctlr = edev->ctlr;
+ if(ctlr == nil)
+ return;
+
+ /* Mask interrupts. */
+ wiol(ctlr, Imr, 0);
+
+ status = riol(ctlr, Isr);
+ if(status == 0xffff)
+ goto end;
+
+ /* acknowledge */
+ if(status)
+ wiol(ctlr, Isr, status);
+
+ if((status & Isr_Mask) == 0)
+ goto end;
+
+ ctlr->stats.intr++;
+
+ if(ctlr->debugflags & DumpIntr)
+ if(ctlr->debugcount){
+ print("vgbe: irq: status = %#08ulx\n", status);
+ vgbedumpisr(status);
+ ctlr->debugcount--;
+ }
+
+ if(status & Isr_RxComplete)
+ vgberxeof(edev);
+
+ if(status & Isr_TxComplete0)
+ vgbetxeof(edev);
+
+ if(status & Isr_Stopped)
+ print("vgbe: irq: software shutdown complete\n");
+
+ if(status & Isr_RxFifoOvflow)
+ print("vgbe: irq: RX FIFO overflow\n");
+
+ if(status & Isr_PhyIntr)
+ print("vgbe: irq: PHY interrupt\n");
+
+ if(status & Isr_LinkStatus)
+ print("vgbe: irq: link status change\n");
+
+ if(status & Isr_RxNoDesc)
+ print("vgbe: irq: ran out of Rx descriptors\n");
+
+ if(status & Isr_RxDmaStall){
+ print("vgbe: irq: Rx DMA stall\n");
+ wiol(ctlr, Cr3C, Cr3_IntMask);
+ return;
+ }
+
+ if(status & Isr_TxDmaStall){
+ print("vgbe: irq: Tx DMA stall\n");
+ wiol(ctlr, Cr3C, Cr3_IntMask);
+ return;
+ }
+
+end:
+ /* Unmask interrupts. */
+ wiol(ctlr, Imr, ~0);
+}
+
+static void
+vgbetransmit(Ether* edev)
+{
+ Block* block;
+ Ctlr* ctlr;
+ int i, index, start, count;
+ TxDesc* desc;
+ ulong status, length;
+
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->tx_lock);
+
+ start = riow(ctlr, TxDscIdx);
+
+ if(ctlr->debugflags & DumpTx)
+ print("vgbe: transmit (start=%d)\n", start);
+
+ /* find empty slot */
+ for(count = 0, i = 0; i < TxCount; i++){
+ index = (i + start) % TxCount;
+
+ if(ctlr->tx_blocks[index])
+ continue;
+
+ desc = &ctlr->tx_ring[index];
+
+ status = le32toh(desc->status);
+ if(status & TxDesc_Status_Own)
+ continue;
+
+ block = qget(edev->oq);
+ if(block == nil)
+ break;
+
+ count++;
+
+ length = BLEN(block);
+
+ if(ctlr->debugflags & DumpTx)
+ print("vgbe: Tx-Desc[%03d] Block:%#p, addr=%#08ulx, len:%ld\n", index, block,
+ PCIWADDR(block->rp), length);
+
+ ctlr->tx_blocks[index] = block;
+
+ /* Initialize Tx descriptor. */
+ desc->status = htole32((length<<16)|TxDesc_Status_Own);
+ desc->control = htole32(TxDesc_Control_Intr|TxDesc_Control_Normal|((1+1)<<28));
+
+ desc->frags[0].addr_lo = htole32((ulong) PCIWADDR(block->rp));
+ desc->frags[0].addr_hi = htole16(0);
+ desc->frags[0].length = htole16(length);
+ }
+ ctlr->tx_count += count;
+
+ if(ctlr->debugflags & DumpTx)
+ print("vgbe: transmit: done [count=%d]\n", count);
+
+ iunlock(&ctlr->tx_lock);
+
+ if(ctlr->tx_count)
+ wiob(ctlr, TxCsrS, TxCsr_Wakeup);
+
+ if(count == 0)
+ print("vgbe: transmit: no Tx entry available\n");
+}
+
+static void
+vgbeattach(Ether* edev)
+{
+ Ctlr* ctlr;
+ RxDesc* rxdesc;
+ TxDesc* txdesc;
+ int i;
+
+ ctlr = edev->ctlr;
+
+ lock(&ctlr->init_lock);
+ if(ctlr->inited){
+ unlock(&ctlr->init_lock);
+ return;
+ }
+
+// print("vgbe: attach\n");
+
+ /* Allocate Rx ring. (TODO: Alignment ?) */
+ rxdesc = mallocalign(RxCount* sizeof(RxDesc), 256, 0, 0);
+ if(rxdesc == nil){
+ print("vgbe: unable to alloc Rx ring\n");
+ unlock(&ctlr->init_lock);
+ return;
+ }
+ ctlr->rx_ring = rxdesc;
+
+ /* Allocate Rx blocks, initialize Rx ring. */
+ for(i = 0; i < RxCount; i++)
+ vgbenewrx(ctlr, i);
+
+ /* Init Rx MAC. */
+ wiob(ctlr, RxControl,
+ RxControl_MultiCast|RxControl_BroadCast|RxControl_UniCast);
+ wiob(ctlr, RxConfig, RxConfig_VlanOpt0);
+
+ /* Load Rx ring. */
+ wiol(ctlr, RxDescLo, (ulong) PCIWADDR(rxdesc));
+ wiow(ctlr, RxNum, RxCount - 1);
+ wiow(ctlr, RxDscIdx, 0);
+ wiow(ctlr, RxResCnt, RxCount);
+
+ /* Allocate Tx ring. */
+ txdesc = mallocalign(TxCount* sizeof(TxDesc), 256, 0, 0);
+ if(txdesc == nil){
+ print("vgbe: unable to alloc Tx ring\n");
+ unlock(&ctlr->init_lock);
+ return;
+ }
+ ctlr->tx_ring = txdesc;
+
+ /* Init DMAs */
+ wiob(ctlr, DmaCfg0, 4);
+
+ /* Init Tx MAC. */
+ wiob(ctlr, TxControl, 0);
+ wiob(ctlr, TxConfig, TxConfig_NonBlk|TxConfig_ArbPrio);
+
+ /* Load Tx ring. */
+ wiol(ctlr, TxDescLo, (ulong) PCIWADDR(txdesc));
+ wiow(ctlr, TxNum, TxCount - 1);
+ wiow(ctlr, TxDscIdx, 0);
+
+ /* Enable Xon/Xoff */
+ wiob(ctlr, Cr2S, 0xb|Cr2_XonEnable);
+
+ /* Enable Rx queue */
+ wiob(ctlr, RxCsrS, RxCsr_RunQueue);
+
+ /* Enable Tx queue */
+ wiob(ctlr, TxCsrS, TxCsr_RunQueue);
+
+ /* Done */
+ ctlr->inited = 1;
+ unlock(&ctlr->init_lock);
+
+ /* Enable interrupts */
+ wiol(ctlr, Isr, 0xffffffff);
+ wiob(ctlr, Cr3S, Cr3_IntMask);
+
+ /* Wake up Rx queue */
+ wiob(ctlr, RxCsrS, RxCsr_Wakeup);
+}
+
+static void
+vgbereset(Ctlr* ctlr)
+{
+// MiiPhy* phy;
+ int timeo, i;
+
+// print("vgbe: reset\n");
+
+ /* Soft reset the controller. */
+ wiob(ctlr, Cr1S, Cr1_reset);
+
+ for(timeo = 0; timeo < Timeout; timeo++)
+ if((riob(ctlr, Cr1S) & Cr1_reset) == 0)
+ break;
+
+ if(timeo >= Timeout){
+ print("vgbe: softreset timeout\n");
+ return;
+ }
+
+ /* Reload eeprom. */
+ siob(ctlr, Eecsr, Eecsr_Autold);
+
+ for(timeo = 0; timeo < Timeout; timeo++)
+ if((riob(ctlr, Eecsr) & Eecsr_Autold) == 0)
+ break;
+
+ if(timeo >= Timeout){
+ print("vgbe: eeprom reload timeout\n");
+ return;
+ }
+
+ /* Load the MAC address. */
+ for(i = 0; i < Eaddrlen; i++)
+ ctlr->ea[i] = riob(ctlr, EthAddr+i);
+
+ /* Initialize interrupts. */
+ wiol(ctlr, Isr, 0xffffffff);
+ wiol(ctlr, Imr, 0xffffffff);
+
+ /* Disable interrupts. */
+ wiol(ctlr, Cr3C, Cr3_IntMask);
+
+ /* 32 bits addresses only. (TODO: 64 bits ?) */
+ wiol(ctlr, TxDescHi, 0);
+ wiow(ctlr, DataBufHi, 0);
+
+ /* Enable MAC (turning off Rx/Tx engines for the moment). */
+ wiob(ctlr, Cr0C, Cr0_Stop|Cr0_EnableRx|Cr0_EnableTx);
+ wiob(ctlr, Cr0S, Cr0_Start);
+
+ /* Initialize Rx engine. */
+ wiow(ctlr, RxCsrC, RxCsr_RunQueue);
+
+ /* Initialize Tx engine. */
+ wiow(ctlr, TxCsrC, TxCsr_RunQueue);
+
+ /* Enable Rx/Tx engines. */
+ wiob(ctlr, Cr0S, Cr0_EnableRx|Cr0_EnableTx);
+
+ /* Initialize link management. */
+ ctlr->mii = malloc(sizeof(Mii));
+ if(ctlr->mii == nil){
+ print("vgbe: unable to alloc Mii\n");
+ return;
+ }
+
+ ctlr->mii->mir = vgbemiir;
+ ctlr->mii->miw = vgbemiiw;
+ ctlr->mii->ctlr = ctlr;
+
+ if(mii(ctlr->mii, 1<<1) == 0){
+ print("vgbe: no phy found\n");
+ return;
+ }
+
+// phy = ctlr->mii->curphy;
+// print("vgbe: phy:oui %#x\n", phy->oui);
+}
+
+static void
+vgbepci(void)
+{
+ Pcidev* pdev;
+
+// print("vgbe: pci\n");
+
+ pdev = nil;
+ while(pdev = pcimatch(pdev, 0, 0)){
+ Ctlr* ctlr;
+ int port, size;
+
+ if(pdev->ccrb != 0x02 || pdev->ccru != 0)
+ continue;
+
+ switch((pdev->did<<16) | pdev->vid){
+ default:
+ continue;
+
+ case (0x3119<<16)|0x1106: /* VIA Velocity (VT6122) */
+ break;
+ }
+
+ if((pdev->pcr & 1) == 0){
+ print("vgbe: io not enabled [pcr=%#lux]\n", (ulong)pdev->pcr);
+ continue;
+ }
+
+ pcisetbme(pdev);
+ pcisetpms(pdev, 0);
+
+ port = pdev->mem[0].bar;
+ size = pdev->mem[0].size;
+
+ if((port & 1) == 0){
+ print("vgbe: bar[0]=%#x is not io\n", port);
+ continue;
+ }
+
+ if(port > 0xff00){
+ print("vgbe: invalid port %#ux\n", port);
+ continue;
+ }
+
+ port &= 0xfffe;
+
+ if(size != 256){
+ print("vgbe: invalid io size: %d\n", size);
+ continue;
+ }
+
+ if(ioalloc(port, size, 0, "vge") < 0){
+ print("vgbe: port %#ux already in use\n", port);
+ continue;
+ }
+
+ ctlr = malloc(sizeof(Ctlr));
+ if(ctlr == nil){
+ print("vgbe: unable to alloc Ctlr\n");
+ iofree(port);
+ continue;
+ }
+
+ ctlr->pdev = pdev;
+ ctlr->port = port;
+ ctlr->inited = 0;
+
+ if(vgbehead != nil)
+ vgbetail->link = ctlr;
+ else
+ vgbehead = ctlr;
+ vgbetail = ctlr;
+ }
+}
+
+static long
+vgbectl(Ether* edev, void* buf, long n)
+{
+ Cmdbuf* cb;
+ Ctlr* ctlr;
+ ulong index;
+ char* rptr;
+ RxDesc* rd;
+ TxDesc* td;
+ uchar* p;
+
+ ctlr = edev->ctlr;
+
+ cb = parsecmd(buf, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+
+ if(cistrcmp(cb->f[0], "reset") == 0){
+ vgbereset(ctlr);
+ wiob(ctlr, Cr3S, Cr3_IntMask);
+ wiob(ctlr, RxCsrS, RxCsr_RunQueue);
+ wiob(ctlr, RxCsrS, RxCsr_Wakeup);
+ }
+ else if(cistrcmp(cb->f[0], "dumpintr") == 0){
+ if(cb->nf < 2)
+ error(Ecmdargs);
+
+ if(cistrcmp(cb->f[1], "on") == 0){
+ ctlr->debugflags |= DumpIntr;
+ ctlr->debugcount = ~0;
+ }
+ else if(cistrcmp(cb->f[1], "off") == 0)
+ ctlr->debugflags &= ~DumpIntr;
+ else{
+ ulong count;
+ char* rptr;
+
+ count = strtoul(cb->f[1], &rptr, 0);
+ if(rptr == cb->f[1])
+ error("invalid control request");
+
+ ctlr->debugflags |= DumpIntr;
+ ctlr->debugcount = count;
+
+ print("vgbe: debugcount set to %uld\n", count);
+ }
+ }
+ else if(cistrcmp(cb->f[0], "dumprx") == 0){
+ if(cb->nf < 2)
+ error(Ecmdargs);
+
+ if(cistrcmp(cb->f[1], "on") == 0)
+ ctlr->debugflags |= DumpRx;
+ else if(cistrcmp(cb->f[1], "off") == 0)
+ ctlr->debugflags &= ~DumpRx;
+ else{
+ index = strtoul(cb->f[1], &rptr, 0);
+ if((rptr == cb->f[1]) || (index >= RxCount))
+ error("invalid control request");
+
+ rd = &ctlr->rx_ring[index];
+ print("vgbe: DumpRx[%03uld] status=%#08ulx ctl=%#08ulx len=%#04ux bytes\n",
+ index, rd->status, rd->control, rd->length);
+ }
+ }
+ else if(cistrcmp(cb->f[0], "dumptx") == 0){
+ if(cb->nf < 2)
+ error(Ecmdargs);
+
+ if(cistrcmp(cb->f[1], "on") == 0)
+ ctlr->debugflags |= DumpTx;
+ else if(cistrcmp(cb->f[1], "off") == 0)
+ ctlr->debugflags &= ~DumpTx;
+ else{
+ index = strtoul(cb->f[1], &rptr, 0);
+ if((rptr == cb->f[1]) || (index >= TxCount))
+ error("invalid control request");
+
+ td = &ctlr->tx_ring[index];
+ print("vgbe: DumpTx[%03uld] status=%#08ulx ctl=%#08ulx len=%#04ux bytes",
+ index, td->status, td->control, td->frags[0].length);
+
+ p = (uchar*)td;
+ for(index = 0; index < sizeof(TxDesc); index++){
+ if((index % 16) == 0)
+ print("\nvgbe: ");
+ else
+ print(" ");
+ print("%#02x", p[index]);
+ }
+ }
+ }
+ else if(cistrcmp(cb->f[0], "dumpall") == 0){
+ if(cb->nf < 2)
+ error(Ecmdargs);
+
+ if(cistrcmp(cb->f[1], "on") == 0){
+ ctlr->debugflags = ~0;
+ ctlr->debugcount = ~0;
+ }
+ else if(cistrcmp(cb->f[1], "off") == 0)
+ ctlr->debugflags = 0;
+ else error("invalid control request");
+ }
+ else
+ error(Ebadctl);
+
+ free(cb);
+ poperror();
+
+ return n;
+}
+
+static void
+vgbepromiscuous(void* arg, int on)
+{
+ USED(arg, on);
+}
+
+/* multicast already on, don't need to do anything */
+static void
+vgbemulticast(void*, uchar*, int)
+{
+}
+
+static int
+vgbepnp(Ether* edev)
+{
+ Ctlr* ctlr;
+
+// print("vgbe: pnp\n");
+
+ if(vgbehead == nil)
+ vgbepci();
+
+ for(ctlr = vgbehead; ctlr != nil; ctlr = ctlr->link){
+ if(ctlr->active)
+ continue;
+
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+
+ if(ctlr == nil)
+ return -1;
+
+ vgbereset(ctlr);
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pdev->intl;
+ edev->tbdf = ctlr->pdev->tbdf;
+ edev->mbps = 1000;
+ memmove(edev->ea, ctlr->ea, Eaddrlen);
+ edev->attach = vgbeattach;
+ edev->transmit = vgbetransmit;
+ edev->interrupt = vgbeinterrupt;
+ edev->ifstat = vgbeifstat;
+// edev->promiscuous = vgbepromiscuous;
+ edev->multicast = vgbemulticast;
+// edev->shutdown = vgbeshutdown;
+ edev->ctl = vgbectl;
+
+ edev->arg = edev;
+ return 0;
+}
+
+void
+ethervgbelink(void)
+{
+ addethercard("vgbe", vgbepnp);
+}
diff --git a/sys/src/9/pc/ethervt6102.c b/sys/src/9/pc/ethervt6102.c
new file mode 100755
index 000000000..575824b59
--- /dev/null
+++ b/sys/src/9/pc/ethervt6102.c
@@ -0,0 +1,1050 @@
+/*
+ * VIA VT6102 Fast Ethernet Controller (Rhine II).
+ * To do:
+ * cache-line size alignments - done
+ * reduce tx interrupts
+ * use 2 descriptors on tx for alignment - done
+ * reorganise initialisation/shutdown/reset
+ * adjust Tx FIFO threshold on underflow - untested
+ * why does the link status never cause an interrupt?
+ * use the lproc as a periodic timer for stalls, etc.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+enum {
+ Par0 = 0x00, /* Ethernet Address */
+ Rcr = 0x06, /* Receive Configuration */
+ Tcr = 0x07, /* Transmit Configuration */
+ Cr = 0x08, /* Control */
+ Isr = 0x0C, /* Interrupt Status */
+ Imr = 0x0E, /* Interrupt Mask */
+ Mcfilt0 = 0x10, /* Multicast Filter 0 */
+ Mcfilt1 = 0x14, /* Multicast Filter 1 */
+ Rxdaddr = 0x18, /* Current Rx Descriptor Address */
+ Txdaddr = 0x1C, /* Current Tx Descriptor Address */
+ Phyadr = 0x6C, /* Phy Address */
+ Miisr = 0x6D, /* MII Status */
+ Bcr0 = 0x6E, /* Bus Control */
+ Bcr1 = 0x6F,
+ Miicr = 0x70, /* MII Control */
+ Miiadr = 0x71, /* MII Address */
+ Miidata = 0x72, /* MII Data */
+ Eecsr = 0x74, /* EEPROM Control and Status */
+ Stickhw = 0x83, /* Sticky Hardware Control */
+ Wolcrclr = 0xA4,
+ Wolcgclr = 0xA7,
+ Pwrcsrclr = 0xAC,
+};
+
+enum { /* Rcr */
+ Sep = 0x01, /* Accept Error Packets */
+ Ar = 0x02, /* Accept Small Packets */
+ Am = 0x04, /* Accept Multicast */
+ Ab = 0x08, /* Accept Broadcast */
+ Prom = 0x10, /* Accept Physical Address Packets */
+ RrftMASK = 0xE0, /* Receive FIFO Threshold */
+ RrftSHIFT = 5,
+ Rrft64 = 0<<RrftSHIFT,
+ Rrft32 = 1<<RrftSHIFT,
+ Rrft128 = 2<<RrftSHIFT,
+ Rrft256 = 3<<RrftSHIFT,
+ Rrft512 = 4<<RrftSHIFT,
+ Rrft768 = 5<<RrftSHIFT,
+ Rrft1024 = 6<<RrftSHIFT,
+ RrftSAF = 7<<RrftSHIFT,
+};
+
+enum { /* Tcr */
+ Lb0 = 0x02, /* Loopback Mode */
+ Lb1 = 0x04,
+ Ofset = 0x08, /* Back-off Priority Selection */
+ RtsfMASK = 0xE0, /* Transmit FIFO Threshold */
+ RtsfSHIFT = 5,
+ Rtsf128 = 0<<RtsfSHIFT,
+ Rtsf256 = 1<<RtsfSHIFT,
+ Rtsf512 = 2<<RtsfSHIFT,
+ Rtsf1024 = 3<<RtsfSHIFT,
+ RtsfSAF = 7<<RtsfSHIFT,
+};
+
+enum { /* Cr */
+ Init = 0x0001, /* INIT Process Begin */
+ Strt = 0x0002, /* Start NIC */
+ Stop = 0x0004, /* Stop NIC */
+ Rxon = 0x0008, /* Turn on Receive Process */
+ Txon = 0x0010, /* Turn on Transmit Process */
+ Tdmd = 0x0020, /* Transmit Poll Demand */
+ Rdmd = 0x0040, /* Receive Poll Demand */
+ Eren = 0x0100, /* Early Receive Enable */
+ Fdx = 0x0400, /* Set MAC to Full Duplex Mode */
+ Dpoll = 0x0800, /* Disable Td/Rd Auto Polling */
+ Tdmd1 = 0x2000, /* Transmit Poll Demand 1 */
+ Rdmd1 = 0x4000, /* Receive Poll Demand 1 */
+ Sfrst = 0x8000, /* Software Reset */
+};
+
+enum { /* Isr/Imr */
+ Prx = 0x0001, /* Received Packet Successfully */
+ Ptx = 0x0002, /* Transmitted Packet Successfully */
+ Rxe = 0x0004, /* Receive Error */
+ Txe = 0x0008, /* Transmit Error */
+ Tu = 0x0010, /* Transmit Buffer Underflow */
+ Ru = 0x0020, /* Receive Buffer Link Error */
+ Be = 0x0040, /* PCI Bus Error */
+ Cnt = 0x0080, /* Counter Overflow */
+ Eri = 0x0100, /* Early Receive Interrupt */
+ Udfi = 0x0200, /* Tx FIFO Underflow */
+ Ovfi = 0x0400, /* Receive FIFO Overflow */
+ Pktrace = 0x0800, /* Hmmm... */
+ Norbf = 0x1000, /* No Receive Buffers */
+ Abti = 0x2000, /* Transmission Abort */
+ Srci = 0x4000, /* Port State Change */
+ Geni = 0x8000, /* General Purpose Interrupt */
+};
+
+enum { /* Phyadr */
+ PhyadMASK = 0x1F, /* PHY Address */
+ PhyadSHIFT = 0,
+ Mfdc = 0x20, /* Accelerate MDC Speed */
+ Mpo0 = 0x40, /* MII Polling Timer Interval */
+ Mpo1 = 0x80,
+};
+
+enum { /* Bcr0 */
+ DmaMASK = 0x07, /* DMA Length */
+ DmaSHIFT = 0,
+ Dma32 = 0<<DmaSHIFT,
+ Dma64 = 1<<DmaSHIFT,
+ Dma128 = 2<<DmaSHIFT,
+ Dma256 = 3<<DmaSHIFT,
+ Dma512 = 4<<DmaSHIFT,
+ Dma1024 = 5<<DmaSHIFT,
+ DmaSAF = 7<<DmaSHIFT,
+ CrftMASK = 0x38, /* Rx FIFO Threshold */
+ CrftSHIFT = 3,
+ Crft64 = 1<<CrftSHIFT,
+ Crft128 = 2<<CrftSHIFT,
+ Crft256 = 3<<CrftSHIFT,
+ Crft512 = 4<<CrftSHIFT,
+ Crft1024 = 5<<CrftSHIFT,
+ CrftSAF = 7<<CrftSHIFT,
+ Extled = 0x40, /* Extra LED Support Control */
+ Med2 = 0x80, /* Medium Select Control */
+};
+
+enum { /* Bcr1 */
+ PotMASK = 0x07, /* Polling Timer Interval */
+ PotSHIFT = 0,
+ CtftMASK = 0x38, /* Tx FIFO Threshold */
+ CtftSHIFT = 3,
+ Ctft64 = 1<<CtftSHIFT,
+ Ctft128 = 2<<CtftSHIFT,
+ Ctft256 = 3<<CtftSHIFT,
+ Ctft512 = 4<<CtftSHIFT,
+ Ctft1024 = 5<<CtftSHIFT,
+ CtftSAF = 7<<CtftSHIFT,
+};
+
+enum { /* Miicr */
+ Mdc = 0x01, /* Clock */
+ Mdi = 0x02, /* Data In */
+ Mdo = 0x04, /* Data Out */
+ Mout = 0x08, /* Output Enable */
+ Mdpm = 0x10, /* Direct Program Mode Enable */
+ Wcmd = 0x20, /* Write Enable */
+ Rcmd = 0x40, /* Read Enable */
+ Mauto = 0x80, /* Auto Polling Enable */
+};
+
+enum { /* Miiadr */
+ MadMASK = 0x1F, /* MII Port Address */
+ MadSHIFT = 0,
+ Mdone = 0x20, /* Accelerate MDC Speed */
+ Msrcen = 0x40, /* MII Polling Timer Interval */
+ Midle = 0x80,
+};
+
+enum { /* Eecsr */
+ Edo = 0x01, /* Data Out */
+ Edi = 0x02, /* Data In */
+ Eck = 0x04, /* Clock */
+ Ecs = 0x08, /* Chip Select */
+ Dpm = 0x10, /* Direct Program Mode Enable */
+ Autold = 0x20, /* Dynamic Reload */
+ Embp = 0x40, /* Embedded Program Enable */
+ Eepr = 0x80, /* Programmed */
+};
+
+/*
+ * Ring descriptor. The space allocated for each
+ * of these will be rounded up to a cache-line boundary.
+ * The first 4 elements are known to the hardware.
+ */
+typedef struct Ds Ds;
+typedef struct Ds {
+ uint status;
+ uint control;
+ uint addr;
+ uint branch;
+
+ Block* bp;
+ void* bounce;
+ Ds* next;
+ Ds* prev;
+} Ds;
+
+enum { /* Rx Ds status */
+ Rerr = 0x00000001, /* Receiver Error */
+ Crc = 0x00000002, /* CRC Error */
+ Fae = 0x00000004, /* Frame Alignment Error */
+ Fov = 0x00000008, /* FIFO Overflow */
+ Long = 0x00000010, /* A Long Packet */
+ Runt = 0x00000020, /* A Runt Packet */
+ Rxserr = 0x00000040, /* System Error */
+ Buff = 0x00000080, /* Buffer Underflow Error */
+ Rxedp = 0x00000100, /* End of Packet Buffer */
+ Rxstp = 0x00000200, /* Packet Start */
+ Chn = 0x00000400, /* Chain Buffer */
+ Phy = 0x00000800, /* Physical Address Packet */
+ Bar = 0x00001000, /* Broadcast Packet */
+ Mar = 0x00002000, /* Multicast Packet */
+ Rxok = 0x00008000, /* Packet Received Successfully */
+ LengthMASK = 0x07FF0000, /* Received Packet Length */
+ LengthSHIFT = 16,
+
+ Own = 0x80000000, /* Descriptor Owned by NIC */
+};
+
+enum { /* Tx Ds status */
+ NcrMASK = 0x0000000F, /* Collision Retry Count */
+ NcrSHIFT = 0,
+ Cols = 0x00000010, /* Experienced Collisions */
+ Cdh = 0x00000080, /* CD Heartbeat */
+ Abt = 0x00000100, /* Aborted after Excessive Collisions */
+ Owc = 0x00000200, /* Out of Window Collision Seen */
+ Crs = 0x00000400, /* Carrier Sense Lost */
+ Udf = 0x00000800, /* FIFO Underflow */
+ Tbuff = 0x00001000, /* Invalid Td */
+ Txserr = 0x00002000, /* System Error */
+ Terr = 0x00008000, /* Excessive Collisions */
+};
+
+enum { /* Tx Ds control */
+ TbsMASK = 0x000007FF, /* Tx Buffer Size */
+ TbsSHIFT = 0,
+ Chain = 0x00008000, /* Chain Buffer */
+ Crcdisable = 0x00010000, /* Disable CRC generation */
+ Stp = 0x00200000, /* Start of Packet */
+ Edp = 0x00400000, /* End of Packet */
+ Ic = 0x00800000, /* Assert Interrupt Immediately */
+};
+
+enum {
+ Nrd = 64,
+ Ntd = 64,
+ Rdbsz = ROUNDUP(ETHERMAXTU+4, 4),
+
+ Nrxstats = 8,
+ Ntxstats = 9,
+
+ Txcopy = 128,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id;
+ uchar par[Eaddrlen];
+
+ QLock alock; /* attach */
+ void* alloc; /* receive/transmit descriptors */
+ int cls; /* alignment */
+ int nrd;
+ int ntd;
+
+ Ds* rd;
+ Ds* rdh;
+
+ Lock tlock;
+ Ds* td;
+ Ds* tdh;
+ Ds* tdt;
+ int tdused;
+
+ Lock clock; /* */
+ int cr;
+ int imr;
+ int tft; /* Tx threshold */
+
+ Mii* mii;
+ Rendez lrendez;
+ int lwakeup;
+
+ uint rxstats[Nrxstats]; /* statistics */
+ uint txstats[Ntxstats];
+ uint intr;
+ uint lintr;
+ uint lsleep;
+ uint rintr;
+ uint tintr;
+ uint taligned;
+ uint tsplit;
+ uint tcopied;
+ uint txdw;
+} Ctlr;
+
+static Ctlr* vt6102ctlrhead;
+static Ctlr* vt6102ctlrtail;
+
+#define csr8r(c, r) (inb((c)->port+(r)))
+#define csr16r(c, r) (ins((c)->port+(r)))
+#define csr32r(c, r) (inl((c)->port+(r)))
+#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
+#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
+#define csr32w(c, r, w) (outl((c)->port+(r), (ulong)(w)))
+
+static char* rxstats[Nrxstats] = {
+ "Receiver Error",
+ "CRC Error",
+ "Frame Alignment Error",
+ "FIFO Overflow",
+ "Long Packet",
+ "Runt Packet",
+ "System Error",
+ "Buffer Underflow Error",
+};
+static char* txstats[Ntxstats] = {
+ "Aborted after Excessive Collisions",
+ "Out of Window Collision Seen",
+ "Carrier Sense Lost",
+ "FIFO Underflow",
+ "Invalid Td",
+ "System Error",
+ nil,
+ "Excessive Collisions",
+};
+
+static long
+vt6102ifstat(Ether* edev, void* a, long n, ulong offset)
+{
+ char *p;
+ Ctlr *ctlr;
+ int i, l, r;
+
+ ctlr = edev->ctlr;
+
+ p = malloc(READSTR);
+ l = 0;
+ for(i = 0; i < Nrxstats; i++){
+ l += snprint(p+l, READSTR-l, "%s: %ud\n",
+ rxstats[i], ctlr->rxstats[i]);
+ }
+ for(i = 0; i < Ntxstats; i++){
+ if(txstats[i] == nil)
+ continue;
+ l += snprint(p+l, READSTR-l, "%s: %ud\n",
+ txstats[i], ctlr->txstats[i]);
+ }
+ l += snprint(p+l, READSTR-l, "cls: %ud\n", ctlr->cls);
+ l += snprint(p+l, READSTR-l, "intr: %ud\n", ctlr->intr);
+ l += snprint(p+l, READSTR-l, "lintr: %ud\n", ctlr->lintr);
+ l += snprint(p+l, READSTR-l, "lsleep: %ud\n", ctlr->lsleep);
+ l += snprint(p+l, READSTR-l, "rintr: %ud\n", ctlr->rintr);
+ l += snprint(p+l, READSTR-l, "tintr: %ud\n", ctlr->tintr);
+ l += snprint(p+l, READSTR-l, "taligned: %ud\n", ctlr->taligned);
+ l += snprint(p+l, READSTR-l, "tsplit: %ud\n", ctlr->tsplit);
+ l += snprint(p+l, READSTR-l, "tcopied: %ud\n", ctlr->tcopied);
+ l += snprint(p+l, READSTR-l, "txdw: %ud\n", ctlr->txdw);
+ l += snprint(p+l, READSTR-l, "tft: %ud\n", ctlr->tft);
+
+ if(ctlr->mii != nil && ctlr->mii->curphy != nil){
+ l += snprint(p+l, READSTR, "phy: ");
+ for(i = 0; i < NMiiPhyr; i++){
+ 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);
+ }
+ snprint(p+l, READSTR-l, "\n");
+ }
+ snprint(p+l, READSTR-l, "\n");
+
+ n = readstr(offset, a, n, p);
+ free(p);
+
+ return n;
+}
+
+static void
+vt6102promiscuous(void* arg, int on)
+{
+ int rcr;
+ Ctlr *ctlr;
+ Ether *edev;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+ rcr = csr8r(ctlr, Rcr);
+ if(on)
+ rcr |= Prom;
+ else
+ rcr &= ~Prom;
+ csr8w(ctlr, Rcr, rcr);
+}
+
+static void
+vt6102multicast(void* arg, uchar* addr, int on)
+{
+ /*
+ * For now Am is set in Rcr.
+ * Will need to interlock with promiscuous
+ * when this gets filled in.
+ */
+ USED(arg, addr, on);
+}
+
+static int
+vt6102wakeup(void* v)
+{
+ return *((int*)v) != 0;
+}
+
+static void
+vt6102imr(Ctlr* ctlr, int imr)
+{
+ ilock(&ctlr->clock);
+ ctlr->imr |= imr;
+ csr16w(ctlr, Imr, ctlr->imr);
+ iunlock(&ctlr->clock);
+}
+
+static void
+vt6102lproc(void* arg)
+{
+ Ctlr *ctlr;
+ Ether *edev;
+ MiiPhy *phy;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+ for(;;){
+ if(ctlr->mii == nil || ctlr->mii->curphy == nil)
+ break;
+ if(miistatus(ctlr->mii) < 0)
+ goto enable;
+
+ phy = ctlr->mii->curphy;
+ ilock(&ctlr->clock);
+ if(phy->fd)
+ ctlr->cr |= Fdx;
+ else
+ ctlr->cr &= ~Fdx;
+ csr16w(ctlr, Cr, ctlr->cr);
+ iunlock(&ctlr->clock);
+enable:
+ ctlr->lwakeup = 0;
+ vt6102imr(ctlr, Srci);
+
+ ctlr->lsleep++;
+ sleep(&ctlr->lrendez, vt6102wakeup, &ctlr->lwakeup);
+
+ }
+ pexit("vt6102lproc: done", 1);
+}
+
+static void
+vt6102attach(Ether* edev)
+{
+ int i;
+ Ctlr *ctlr;
+ Ds *ds, *prev;
+ uchar *alloc, *bounce;
+ char name[KNAMELEN];
+
+ ctlr = edev->ctlr;
+ qlock(&ctlr->alock);
+ if(ctlr->alloc != nil){
+ qunlock(&ctlr->alock);
+ return;
+ }
+
+ /*
+ * Descriptor and bounce-buffer space.
+ * Must all be aligned on a 4-byte boundary,
+ * but try to align on cache-lines.
+ */
+ ctlr->nrd = Nrd;
+ ctlr->ntd = Ntd;
+ alloc = malloc((ctlr->nrd+ctlr->ntd)*ctlr->cls + ctlr->ntd*Txcopy + ctlr->cls-1);
+ if(alloc == nil){
+ qunlock(&ctlr->alock);
+ return;
+ }
+ ctlr->alloc = alloc;
+ alloc = (uchar*)ROUNDUP((ulong)alloc, ctlr->cls);
+
+ ctlr->rd = (Ds*)alloc;
+
+ if(waserror()){
+ ds = ctlr->rd;
+ for(i = 0; i < ctlr->nrd; i++){
+ if(ds->bp != nil){
+ freeb(ds->bp);
+ ds->bp = nil;
+ }
+ if((ds = ds->next) == nil)
+ break;
+ }
+ free(ctlr->alloc);
+ ctlr->alloc = nil;
+ qunlock(&ctlr->alock);
+ nexterror();
+ }
+
+ prev = ctlr->rd + ctlr->nrd-1;
+ for(i = 0; i < ctlr->nrd; i++){
+ ds = (Ds*)alloc;
+ alloc += ctlr->cls;
+
+ ds->control = Rdbsz;
+ ds->branch = PCIWADDR(alloc);
+
+ ds->bp = iallocb(Rdbsz+3);
+ if(ds->bp == nil)
+ error("vt6102: can't allocate receive ring\n");
+ ds->bp->rp = (uchar*)ROUNDUP((ulong)ds->bp->rp, 4);
+ ds->addr = PCIWADDR(ds->bp->rp);
+
+ ds->next = (Ds*)alloc;
+ ds->prev = prev;
+ prev = ds;
+
+ ds->status = Own;
+ }
+ prev->branch = 0;
+ prev->next = ctlr->rd;
+ prev->status = 0;
+ ctlr->rdh = ctlr->rd;
+
+ ctlr->td = (Ds*)alloc;
+ prev = ctlr->td + ctlr->ntd-1;
+ bounce = alloc + ctlr->ntd*ctlr->cls;
+ for(i = 0; i < ctlr->ntd; i++){
+ ds = (Ds*)alloc;
+ alloc += ctlr->cls;
+
+ ds->bounce = bounce;
+ bounce += Txcopy;
+ ds->next = (Ds*)alloc;
+ ds->prev = prev;
+ prev = ds;
+ }
+ prev->next = ctlr->td;
+ ctlr->tdh = ctlr->tdt = ctlr->td;
+ ctlr->tdused = 0;
+
+ ctlr->cr = Dpoll|Rdmd|Txon|Rxon|Strt;
+ /*Srci|Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx*/
+ ctlr->imr = Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx;
+
+ ilock(&ctlr->clock);
+ csr32w(ctlr, Rxdaddr, PCIWADDR(ctlr->rd));
+ csr32w(ctlr, Txdaddr, PCIWADDR(ctlr->td));
+ csr16w(ctlr, Isr, ~0);
+ csr16w(ctlr, Imr, ctlr->imr);
+ csr16w(ctlr, Cr, ctlr->cr);
+ iunlock(&ctlr->clock);
+
+ snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno);
+ kproc(name, vt6102lproc, edev);
+
+ qunlock(&ctlr->alock);
+ poperror();
+}
+
+static void
+vt6102transmit(Ether* edev)
+{
+ Block *bp;
+ Ctlr *ctlr;
+ Ds *ds, *next;
+ int control, i, o, prefix, size, tdused, timeo;
+
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->tlock);
+
+ /*
+ * Free any completed packets
+ */
+ ds = ctlr->tdh;
+ for(tdused = ctlr->tdused; tdused > 0; tdused--){
+ /*
+ * For some errors the chip will turn the Tx engine
+ * off. Wait for that to happen.
+ * Could reset and re-init the chip here if it doesn't
+ * play fair.
+ * To do: adjust Tx FIFO threshold on underflow.
+ */
+ if(ds->status & (Abt|Tbuff|Udf)){
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!(csr16r(ctlr, Cr) & Txon))
+ break;
+ microdelay(1);
+ }
+ ds->status = Own;
+ csr32w(ctlr, Txdaddr, PCIWADDR(ds));
+ }
+
+ if(ds->status & Own)
+ break;
+ ds->addr = 0;
+ ds->branch = 0;
+
+ if(ds->bp != nil){
+ freeb(ds->bp);
+ ds->bp = nil;
+ }
+ for(i = 0; i < Ntxstats-1; i++){
+ if(ds->status & (1<<i))
+ ctlr->txstats[i]++;
+ }
+ ctlr->txstats[i] += (ds->status & NcrMASK)>>NcrSHIFT;
+
+ ds = ds->next;
+ }
+ ctlr->tdh = ds;
+
+ /*
+ * Try to fill the ring back up.
+ */
+ ds = ctlr->tdt;
+ while(tdused < ctlr->ntd-2){
+ if((bp = qget(edev->oq)) == nil)
+ break;
+ tdused++;
+
+ size = BLEN(bp);
+ prefix = 0;
+
+ if(o = (((int)bp->rp) & 0x03)){
+ prefix = Txcopy-o;
+ if(prefix > size)
+ prefix = size;
+ memmove(ds->bounce, bp->rp, prefix);
+ ds->addr = PCIWADDR(ds->bounce);
+ bp->rp += prefix;
+ size -= prefix;
+ }
+
+ next = ds->next;
+ ds->branch = PCIWADDR(ds->next);
+
+ if(size){
+ if(prefix){
+ next->bp = bp;
+ next->addr = PCIWADDR(bp->rp);
+ next->branch = PCIWADDR(next->next);
+ next->control = Edp|Chain|((size<<TbsSHIFT) & TbsMASK);
+
+ control = Stp|Chain|((prefix<<TbsSHIFT) & TbsMASK);
+
+ next = next->next;
+ tdused++;
+ ctlr->tsplit++;
+ }
+ else{
+ ds->bp = bp;
+ ds->addr = PCIWADDR(bp->rp);
+ control = Edp|Stp|((size<<TbsSHIFT) & TbsMASK);
+ ctlr->taligned++;
+ }
+ }
+ else{
+ freeb(bp);
+ control = Edp|Stp|((prefix<<TbsSHIFT) & TbsMASK);
+ ctlr->tcopied++;
+ }
+
+ ds->control = control;
+ if(tdused >= ctlr->ntd-2){
+ ds->control |= Ic;
+ ctlr->txdw++;
+ }
+ coherence();
+ ds->status = Own;
+
+ ds = next;
+ }
+ ctlr->tdt = ds;
+ ctlr->tdused = tdused;
+ if(ctlr->tdused)
+ csr16w(ctlr, Cr, Tdmd|ctlr->cr);
+
+ iunlock(&ctlr->tlock);
+}
+
+static void
+vt6102receive(Ether* edev)
+{
+ Ds *ds;
+ Block *bp;
+ Ctlr *ctlr;
+ int i, len;
+
+ ctlr = edev->ctlr;
+
+ ds = ctlr->rdh;
+ while(!(ds->status & Own) && ds->status != 0){
+ if(ds->status & Rerr){
+ for(i = 0; i < Nrxstats; i++){
+ if(ds->status & (1<<i))
+ ctlr->rxstats[i]++;
+ }
+ }
+ else if(bp = iallocb(Rdbsz+3)){
+ len = ((ds->status & LengthMASK)>>LengthSHIFT)-4;
+ ds->bp->wp = ds->bp->rp+len;
+ etheriq(edev, ds->bp, 1);
+ bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4);
+ ds->addr = PCIWADDR(bp->rp);
+ ds->bp = bp;
+ }
+ ds->control = Rdbsz;
+ ds->branch = 0;
+ ds->status = 0;
+
+ ds->prev->branch = PCIWADDR(ds);
+ coherence();
+ ds->prev->status = Own;
+
+ ds = ds->next;
+ }
+ ctlr->rdh = ds;
+
+ csr16w(ctlr, Cr, ctlr->cr);
+}
+
+static void
+vt6102interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Ether *edev;
+ int imr, isr, r, timeo;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->clock);
+ csr16w(ctlr, Imr, 0);
+ imr = ctlr->imr;
+ ctlr->intr++;
+ for(;;){
+ if((isr = csr16r(ctlr, Isr)) != 0)
+ csr16w(ctlr, Isr, isr);
+ if((isr & ctlr->imr) == 0)
+ break;
+
+ if(isr & Srci){
+ imr &= ~Srci;
+ ctlr->lwakeup = isr & Srci;
+ wakeup(&ctlr->lrendez);
+ isr &= ~Srci;
+ ctlr->lintr++;
+ }
+ if(isr & (Norbf|Pktrace|Ovfi|Ru|Rxe|Prx)){
+ vt6102receive(edev);
+ isr &= ~(Norbf|Pktrace|Ovfi|Ru|Rxe|Prx);
+ ctlr->rintr++;
+ }
+ if(isr & (Abti|Udfi|Tu|Txe|Ptx)){
+ if(isr & (Abti|Udfi|Tu)){
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!(csr16r(ctlr, Cr) & Txon))
+ break;
+ microdelay(1);
+ }
+
+ if((isr & Udfi) && ctlr->tft < CtftSAF){
+ ctlr->tft += 1<<CtftSHIFT;
+ r = csr8r(ctlr, Bcr1) & ~CtftMASK;
+ csr8w(ctlr, Bcr1, r|ctlr->tft);
+ }
+ }
+ vt6102transmit(edev);
+ isr &= ~(Abti|Udfi|Tu|Txe|Ptx);
+ ctlr->tintr++;
+ }
+ if(isr)
+ panic("vt6102: isr %4.4uX\n", isr);
+ }
+ ctlr->imr = imr;
+ csr16w(ctlr, Imr, ctlr->imr);
+ iunlock(&ctlr->clock);
+}
+
+static int
+vt6102miimicmd(Mii* mii, int pa, int ra, int cmd, int data)
+{
+ Ctlr *ctlr;
+ int r, timeo;
+
+ ctlr = mii->ctlr;
+
+ csr8w(ctlr, Miicr, 0);
+ r = csr8r(ctlr, Phyadr);
+ csr8w(ctlr, Phyadr, (r & ~PhyadMASK)|pa);
+ csr8w(ctlr, Phyadr, pa);
+ csr8w(ctlr, Miiadr, ra);
+ if(cmd == Wcmd)
+ csr16w(ctlr, Miidata, data);
+ csr8w(ctlr, Miicr, cmd);
+
+ for(timeo = 0; timeo < 10000; timeo++){
+ if(!(csr8r(ctlr, Miicr) & cmd))
+ break;
+ microdelay(1);
+ }
+ if(timeo >= 10000)
+ return -1;
+
+ if(cmd == Wcmd)
+ return 0;
+ return csr16r(ctlr, Miidata);
+}
+
+static int
+vt6102miimir(Mii* mii, int pa, int ra)
+{
+ return vt6102miimicmd(mii, pa, ra, Rcmd, 0);
+}
+
+static int
+vt6102miimiw(Mii* mii, int pa, int ra, int data)
+{
+ return vt6102miimicmd(mii, pa, ra, Wcmd, data);
+}
+
+static int
+vt6102detach(Ctlr* ctlr)
+{
+ int revid, timeo;
+
+ /*
+ * Reset power management registers.
+ */
+ revid = pcicfgr8(ctlr->pcidev, PciRID);
+ if(revid >= 0x40){
+ /* Set power state D0. */
+ csr8w(ctlr, Stickhw, csr8r(ctlr, Stickhw) & 0xFC);
+
+ /* Disable force PME-enable. */
+ csr8w(ctlr, Wolcgclr, 0x80);
+
+ /* Clear WOL config and status bits. */
+ csr8w(ctlr, Wolcrclr, 0xFF);
+ csr8w(ctlr, Pwrcsrclr, 0xFF);
+ }
+
+ /*
+ * Soft reset the controller.
+ */
+ csr16w(ctlr, Cr, Stop);
+ csr16w(ctlr, Cr, Stop|Sfrst);
+ for(timeo = 0; timeo < 10000; timeo++){
+ if(!(csr16r(ctlr, Cr) & Sfrst))
+ break;
+ microdelay(1);
+ }
+ if(timeo >= 1000)
+ return -1;
+
+ return 0;
+}
+
+static int
+vt6102reset(Ctlr* ctlr)
+{
+ MiiPhy *phy;
+ int i, r, timeo;
+
+ if(vt6102detach(ctlr) < 0)
+ return -1;
+
+ /*
+ * Load the MAC address into the PAR[01]
+ * registers.
+ */
+ r = csr8r(ctlr, Eecsr);
+ csr8w(ctlr, Eecsr, Autold|r);
+ for(timeo = 0; timeo < 100; timeo++){
+ if(!(csr8r(ctlr, Cr) & Autold))
+ break;
+ microdelay(1);
+ }
+ if(timeo >= 100)
+ return -1;
+
+ for(i = 0; i < Eaddrlen; i++)
+ ctlr->par[i] = csr8r(ctlr, Par0+i);
+
+ /*
+ * Configure DMA and Rx/Tx thresholds.
+ * If the Rx/Tx threshold bits in Bcr[01] are 0 then
+ * the thresholds are determined by Rcr/Tcr.
+ */
+ r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK);
+ csr8w(ctlr, Bcr0, r|Crft64|Dma64);
+ r = csr8r(ctlr, Bcr1) & ~CtftMASK;
+ csr8w(ctlr, Bcr1, r|ctlr->tft);
+
+ r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep);
+ csr8w(ctlr, Rcr, r|Ab|Am);
+ csr32w(ctlr, Mcfilt0, ~0UL); /* accept all multicast */
+ csr32w(ctlr, Mcfilt1, ~0UL);
+
+ r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0);
+ csr8w(ctlr, Tcr, r);
+
+ /*
+ * Link management.
+ */
+ if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+ return -1;
+ ctlr->mii->mir = vt6102miimir;
+ ctlr->mii->miw = vt6102miimiw;
+ ctlr->mii->ctlr = ctlr;
+
+ if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
+ free(ctlr->mii);
+ ctlr->mii = nil;
+ return -1;
+ }
+ // print("oui %X phyno %d\n", phy->oui, phy->phyno);
+ USED(phy);
+
+ //miiane(ctlr->mii, ~0, ~0, ~0);
+
+ return 0;
+}
+
+static void
+vt6102pci(void)
+{
+ Pcidev *p;
+ Ctlr *ctlr;
+ int cls, port;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
+ continue;
+
+ switch((p->did<<16)|p->vid){
+ default:
+ continue;
+ case (0x3065<<16)|0x1106: /* Rhine II */
+ case (0x3106<<16)|0x1106: /* Rhine III */
+ break;
+ }
+
+ port = p->mem[0].bar & ~0x01;
+ if(ioalloc(port, p->mem[0].size, 0, "vt6102") < 0){
+ print("vt6102: port 0x%uX in use\n", port);
+ continue;
+ }
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = port;
+ ctlr->pcidev = p;
+ ctlr->id = (p->did<<16)|p->vid;
+ if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF)
+ cls = 0x10;
+ ctlr->cls = cls*4;
+ if(ctlr->cls < sizeof(Ds)){
+ print("vt6102: cls %d < sizeof(Ds)\n", ctlr->cls);
+ iofree(port);
+ free(ctlr);
+ continue;
+ }
+ ctlr->tft = Ctft64;
+
+ if(vt6102reset(ctlr)){
+ iofree(port);
+ free(ctlr);
+ continue;
+ }
+ pcisetbme(p);
+
+ if(vt6102ctlrhead != nil)
+ vt6102ctlrtail->next = ctlr;
+ else
+ vt6102ctlrhead = ctlr;
+ vt6102ctlrtail = ctlr;
+ }
+}
+
+static int
+vt6102pnp(Ether* edev)
+{
+ Ctlr *ctlr;
+
+ if(vt6102ctlrhead == nil)
+ vt6102pci();
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = vt6102ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+ edev->mbps = 100;
+ memmove(edev->ea, ctlr->par, Eaddrlen);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ edev->attach = vt6102attach;
+ edev->transmit = vt6102transmit;
+ edev->interrupt = vt6102interrupt;
+ edev->ifstat = vt6102ifstat;
+ edev->ctl = nil;
+
+ edev->arg = edev;
+ edev->promiscuous = vt6102promiscuous;
+ edev->multicast = vt6102multicast;
+
+ return 0;
+}
+
+void
+ethervt6102link(void)
+{
+ addethercard("vt6102", vt6102pnp);
+ addethercard("rhine", vt6102pnp);
+}
diff --git a/sys/src/9/pc/ethervt6105m.c b/sys/src/9/pc/ethervt6105m.c
new file mode 100755
index 000000000..06d02c0f2
--- /dev/null
+++ b/sys/src/9/pc/ethervt6105m.c
@@ -0,0 +1,1220 @@
+/*
+ * VIA VT6105M Fast Ethernet Controller (Rhine III).
+ * To do:
+ * cache-line size alignments - done
+ * reduce tx interrupts - done
+ * reorganise initialisation/shutdown/reset
+ * adjust Tx FIFO threshold on underflow - untested
+ * why does the link status never cause an interrupt?
+ * use the lproc as a periodic timer for stalls, etc.
+ * checksum offload - done
+ * take non-HW stuff out of descriptor for 64-bit
+ * cleanliness
+ * why does the receive buffer alloc have a +3?
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+enum {
+ Par0 = 0x00, /* Ethernet Address */
+ Rcr = 0x06, /* Receive Configuration */
+ Tcr = 0x07, /* Transmit Configuration */
+ Cr = 0x08, /* Control */
+ Tqw = 0x0A, /* Transmit Queue Wake */
+ Isr = 0x0C, /* Interrupt Status */
+ Imr = 0x0E, /* Interrupt Mask */
+ Mcfilt0 = 0x10, /* Multicast Filter 0 */
+ Mcfilt1 = 0x14, /* Multicast Filter 1 */
+ Rxdaddr = 0x18, /* Current Rd Address */
+ Txdaddr = 0x1C, /* Current Td Address */
+ Phyadr = 0x6C, /* Phy Address */
+ Miisr = 0x6D, /* MII Status */
+ Bcr0 = 0x6E, /* Bus Control */
+ Bcr1 = 0x6F,
+ Miicr = 0x70, /* MII Control */
+ Miiadr = 0x71, /* MII Address */
+ Miidata = 0x72, /* MII Data */
+ Eecsr = 0x74, /* EEPROM Control and Status */
+ CfgA = 0x78, /* Chip Configuration A */
+ CfgB = 0x79,
+ CfgC = 0x7A,
+ CfgD = 0x7B,
+ Cr0 = 0x80, /* Miscellaneous Control */
+ Cr1 = 0x81,
+ Pmcc = 0x82, /* Power Mgmt Capability Control */
+ Stickhw = 0x83, /* Sticky Hardware Control */
+ Misr = 0x84, /* MII Interrupt Control */
+ Mimr = 0x85, /* MII Interrupt Mask */
+ Wolcrclr = 0xA4,
+ Wolcgclr = 0xA7,
+ Pwrcsrclr = 0xAC,
+};
+
+enum { /* Rcr */
+ Sep = 0x01, /* Accept Error Packets */
+ Ar = 0x02, /* Accept Small Packets */
+ Am = 0x04, /* Accept Multicast */
+ Ab = 0x08, /* Accept Broadcast */
+ Prom = 0x10, /* Accept Physical Address Packets */
+ RrftMASK = 0xE0, /* Receive FIFO Threshold */
+ RrftSHIFT = 5,
+ Rrft64 = 0<<RrftSHIFT,
+ Rrft32 = 1<<RrftSHIFT,
+ Rrft128 = 2<<RrftSHIFT,
+ Rrft256 = 3<<RrftSHIFT,
+ Rrft512 = 4<<RrftSHIFT,
+ Rrft768 = 5<<RrftSHIFT,
+ Rrft1024 = 6<<RrftSHIFT,
+ RrftSAF = 7<<RrftSHIFT,
+};
+
+enum { /* Tcr */
+ Lb0 = 0x02, /* Loopback Mode */
+ Lb1 = 0x04,
+ Ofset = 0x08, /* Select Back-off Priority */
+ RtsfMASK = 0xE0, /* Transmit FIFO Threshold */
+ RtsfSHIFT = 5,
+ Rtsf128 = 0<<RtsfSHIFT,
+ Rtsf256 = 1<<RtsfSHIFT,
+ Rtsf512 = 2<<RtsfSHIFT,
+ Rtsf1024 = 3<<RtsfSHIFT,
+ RtsfSAF = 7<<RtsfSHIFT,
+};
+
+enum { /* Cr */
+ Init = 0x0001, /* INIT Process Begin */
+ Strt = 0x0002, /* Start NIC */
+ Stop = 0x0004, /* Stop NIC */
+ Rxon = 0x0008, /* Turn on Receive Process */
+ Txon = 0x0010, /* Turn on Transmit Process */
+ Tdmd = 0x0020, /* Transmit Poll Demand */
+ Rdmd = 0x0040, /* Receive Poll Demand */
+ Eren = 0x0100, /* Early Receive Enable */
+ Fdx = 0x0400, /* Set MAC to Full Duplex */
+ Dpoll = 0x0800, /* Disable Td/Rd Auto Polling */
+ Tdmd1 = 0x2000, /* Transmit Poll Demand 1 */
+ Rdmd1 = 0x4000, /* Receive Poll Demand 1 */
+ Sfrst = 0x8000, /* Software Reset */
+};
+
+enum { /* Isr/Imr */
+ Prx = 0x0001, /* Packet Received OK */
+ Ptx = 0x0002, /* Packet Transmitted OK */
+ Rxe = 0x0004, /* Receive Error */
+ Txe = 0x0008, /* Transmit Error */
+ Tu = 0x0010, /* Transmit Buffer Underflow */
+ Ru = 0x0020, /* Receive Buffer Link Error */
+ Be = 0x0040, /* PCI Bus Error */
+ Cnt = 0x0080, /* Counter Overflow */
+ Eri = 0x0100, /* Early Receive Interrupt */
+ Udfi = 0x0200, /* Tx FIFO Underflow */
+ Ovfi = 0x0400, /* Receive FIFO Overflow */
+ Pktrace = 0x0800, /* Hmmm... */
+ Norbf = 0x1000, /* No Receive Buffers */
+ Abti = 0x2000, /* Transmission Abort */
+ Srci = 0x4000, /* Port State Change */
+ Geni = 0x8000, /* General Purpose Interrupt */
+};
+
+enum { /* Phyadr */
+ PhyadMASK = 0x1F, /* PHY Address */
+ PhyadSHIFT = 0,
+ Mfdc = 0x20, /* Accelerate MDC Speed */
+ Mpo0 = 0x40, /* MII Polling Timer Interval */
+ Mpo1 = 0x80,
+};
+
+enum { /* Bcr0 */
+ DmaMASK = 0x07, /* DMA Length */
+ DmaSHIFT = 0,
+ Dma32 = 0<<DmaSHIFT,
+ Dma64 = 1<<DmaSHIFT,
+ Dma128 = 2<<DmaSHIFT,
+ Dma256 = 3<<DmaSHIFT,
+ Dma512 = 4<<DmaSHIFT,
+ Dma1024 = 5<<DmaSHIFT,
+ DmaSAF = 7<<DmaSHIFT,
+ CrftMASK = 0x38, /* Rx FIFO Threshold */
+ CrftSHIFT = 3,
+ Crft64 = 1<<CrftSHIFT,
+ Crft128 = 2<<CrftSHIFT,
+ Crft256 = 3<<CrftSHIFT,
+ Crft512 = 4<<CrftSHIFT,
+ Crft1024 = 5<<CrftSHIFT,
+ CrftSAF = 7<<CrftSHIFT,
+ Extled = 0x40, /* Extra LED Support Control */
+ Med2 = 0x80, /* Medium Select Control */
+};
+
+enum { /* Bcr1 */
+ PotMASK = 0x07, /* Polling Timer Interval */
+ PotSHIFT = 0,
+ CtftMASK = 0x38, /* Tx FIFO Threshold */
+ CtftSHIFT = 3,
+ Ctft64 = 1<<CtftSHIFT,
+ Ctft128 = 2<<CtftSHIFT,
+ Ctft256 = 3<<CtftSHIFT,
+ Ctft512 = 4<<CtftSHIFT,
+ Ctft1024 = 5<<CtftSHIFT,
+ CtftSAF = 7<<CtftSHIFT,
+};
+
+enum { /* Miicr */
+ Mdc = 0x01, /* Clock */
+ Mdi = 0x02, /* Data In */
+ Mdo = 0x04, /* Data Out */
+ Mout = 0x08, /* Output Enable */
+ Mdpm = 0x10, /* Direct Program Mode Enable */
+ Wcmd = 0x20, /* Write Enable */
+ Rcmd = 0x40, /* Read Enable */
+ Mauto = 0x80, /* Auto Polling Enable */
+};
+
+enum { /* Miiadr */
+ MadMASK = 0x1F, /* MII Port Address */
+ MadSHIFT = 0,
+ Mdone = 0x20, /* Accelerate MDC Speed */
+ Msrcen = 0x40, /* MII Polling Timer Interval */
+ Midle = 0x80,
+};
+
+enum { /* Eecsr */
+ Edo = 0x01, /* Data Out */
+ Edi = 0x02, /* Data In */
+ Eck = 0x04, /* Clock */
+ Ecs = 0x08, /* Chip Select */
+ Dpm = 0x10, /* Direct Program Mode Enable */
+ Autold = 0x20, /* Dynamic Reload */
+ Embp = 0x40, /* Embedded Program Enable */
+ Eepr = 0x80, /* Programmed */
+};
+
+/*
+ * Ring descriptor. The space allocated for each
+ * of these will be rounded up to a cache-line boundary.
+ * The first 4 elements are known to the hardware.
+ */
+typedef struct Ds Ds;
+typedef struct Ds {
+ u32int status;
+ u32int control;
+ u32int addr;
+ u32int branch;
+
+ Block* bp;
+ Ds* next;
+ Ds* prev;
+} Ds;
+
+enum { /* Rx Ds status */
+ Rerr = 0x00000001, /* Buff|Rxserr|Fov|Fae|Crc */
+ Crc = 0x00000002, /* CRC Error */
+ Fae = 0x00000004, /* Frame Alignment Error */
+ Fov = 0x00000008, /* FIFO Overflow */
+ Long = 0x00000010, /* A Long Packet */
+ Runt = 0x00000020, /* A Runt Packet */
+ Rxserr = 0x00000040, /* System Error */
+ Buff = 0x00000080, /* Buffer Underflow Error */
+ Rxedp = 0x00000100, /* End of Packet Buffer */
+ Rxstp = 0x00000200, /* Packet Start */
+ Chn = 0x00000400, /* Chain Buffer */
+ Phy = 0x00000800, /* Physical Address Packet */
+ Bar = 0x00001000, /* Broadcast Packet */
+ Mar = 0x00002000, /* Multicast Packet */
+ Rxok = 0x00008000, /* Packet Received OK */
+ LengthMASK = 0x07FF0000, /* Received Packet Length */
+ LengthSHIFT = 16,
+
+ Own = 0x80000000, /* Descriptor Owned by NIC */
+};
+
+enum { /* Rx Ds control */
+ RbsizeMASK = 0x000007FF, /* Receive Buffer Size */
+ RbsizeSHIFT = 0,
+ Tag = 0x00010000, /* Receive a Tagged Packet */
+ Udpkt = 0x00020000, /* Receive a UDP Packet */
+ Tcpkt = 0x00040000, /* Receive a TCP Packet */
+ Ipkt = 0x00080000, /* Receive an IP Packet */
+ Tuok = 0x00100000, /* TCP/UDP Checksum OK */
+ Ipok = 0x00200000, /* IP Checksum OK */
+ Snaptag = 0x00400000, /* Snap Packet + 802.1q Tag */
+ Rxlerr = 0x00800000, /* Receive Length Check Error */
+ IpktMASK = 0xff000000, /* Interesting Packet */
+ IpktSHIFT = 24,
+};
+
+enum { /* Tx Ds status */
+ NcrMASK = 0x0000000F, /* Collision Retry Count */
+ NcrSHIFT = 0,
+ Cols = 0x00000010, /* Experienced Collisions */
+ Cdh = 0x00000080, /* CD Heartbeat */
+ Abt = 0x00000100, /* Aborted after Excessive Collisions */
+ Owc = 0x00000200, /* Out of Window Collision */
+ Crs = 0x00000400, /* Carrier Sense Lost */
+ Udf = 0x00000800, /* FIFO Underflow */
+ Tbuff = 0x00001000, /* Invalid Td */
+ Txserr = 0x00002000, /* System Error */
+ Terr = 0x00008000, /* Excessive Collisions */
+};
+
+enum { /* Tx Ds control */
+ TbsMASK = 0x000007FF, /* Tx Buffer Size */
+ TbsSHIFT = 0,
+ Chain = 0x00008000, /* Chain Buffer */
+ Crcdisable = 0x00010000, /* Disable CRC generation */
+ Stp = 0x00200000, /* Start of Packet */
+ Edp = 0x00400000, /* End of Packet */
+ Ic = 0x00800000, /* Interrupt Control */
+};
+
+enum { /* Tx Ds branch */
+ Tdctl = 0x00000001, /* No Interrupt Generated */
+};
+
+enum {
+ Nrd = 196,
+ Ntd = 128,
+ Crcsz = 4,
+ Bslop = 48,
+ Rdbsz = ETHERMAXTU+Crcsz+Bslop,
+
+ Nrxstats = 8,
+ Ntxstats = 9,
+
+ Txcopy = 128,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id;
+ uchar par[Eaddrlen];
+
+ QLock alock; /* attach */
+ void* alloc; /* descriptors, etc. */
+ int cls; /* alignment */
+ int nrd;
+ int ntd;
+
+ Ds* rd;
+ Ds* rdh;
+
+ Lock tlock;
+ Ds* td;
+ Ds* tdh;
+ Ds* tdt;
+ int tdused;
+
+ Lock clock; /* */
+ int cr;
+ int imr;
+ int tft; /* Tx threshold */
+
+ Mii* mii;
+ Rendez lrendez;
+ int lwakeup;
+
+ uint rxstats[Nrxstats]; /* statistics */
+ uint txstats[Ntxstats];
+ ulong totalt;
+ uint intr;
+ uint lintr;
+ uint lsleep;
+ uint rintr;
+ uint tintr;
+ uint txdw;
+ int tdumax;
+
+ uint abt;
+ uint tbuff;
+ uint udf;
+
+ uint abti;
+ uint udfi;
+ uint tu;
+
+ uint tuok;
+ uint ipok;
+} Ctlr;
+
+static Ctlr* vt6105Mctlrhead;
+static Ctlr* vt6105Mctlrtail;
+
+#define csr8r(c, r) (inb((c)->port+(r)))
+#define csr16r(c, r) (ins((c)->port+(r)))
+#define csr32r(c, r) (inl((c)->port+(r)))
+#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
+#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
+#define csr32w(c, r, w) (outl((c)->port+(r), (ulong)(w)))
+
+static Lock vt6105Mrblock; /* receive Block freelist */
+static Block* vt6105Mrbpool;
+static uint vt6105Mrbpoolsz;
+
+typedef struct Regs Regs;
+typedef struct Regs {
+ char* name;
+ int offset;
+ int size;
+} Regs;
+
+static Regs regs[] = {
+// "Par0", Par0, 1,
+// "Par1", Par0+1, 1,
+// "Par2", Par0+2, 1,
+// "Par3", Par0+3, 1,
+// "Par4", Par0+4, 1,
+// "Par5", Par0+5, 1,
+ "Rcr", Rcr, 1,
+ "Tcr", Tcr, 1,
+ "Cr0", Cr, 1,
+ "Cr1", Cr+1, 1,
+ "Isr0", Isr, 1,
+ "Isr1", Isr+1, 1,
+ "Imr0", Imr, 1,
+ "Imr1", Imr+1, 1,
+// "Mcfilt0", Mcfilt0,4,
+// "Mcfilt1", Mcfilt1,4,
+// "Rxdaddr", Rxdaddr,4,
+// "Txdaddr", Txdaddr,4,
+ "Phyadr", Phyadr, 1,
+ "Miisr", Miisr, 1,
+ "Bcr0", Bcr0, 1,
+ "Bcr1", Bcr1, 1,
+ "Miicr", Miicr, 1,
+ "Miiadr", Miiadr, 1,
+// "Miidata", Miidata,2,
+ "Eecsr", Eecsr, 1,
+ "CfgA", CfgA, 1,
+ "CfgB", CfgB, 1,
+ "CfgC", CfgC, 1,
+ "CfgD", CfgD, 1,
+ "Cr0", Cr0, 1,
+ "Cr1", Cr1, 1,
+ "Pmcc", Pmcc, 1,
+ "Stickhw", Stickhw,1,
+ "Misr", Misr, 1,
+ "Mimr", Mimr, 1,
+ nil,
+};
+
+static char* rxstats[Nrxstats] = {
+ "Receiver Error",
+ "CRC Error",
+ "Frame Alignment Error",
+ "FIFO Overflow",
+ "Long Packet",
+ "Runt Packet",
+ "System Error",
+ "Buffer Underflow Error",
+};
+static char* txstats[Ntxstats] = {
+ "Aborted after Excessive Collisions",
+ "Out of Window Collision Seen",
+ "Carrier Sense Lost",
+ "FIFO Underflow",
+ "Invalid Td",
+ "System Error",
+ nil,
+ "Excessive Collisions",
+};
+
+static long
+vt6105Mifstat(Ether* edev, void* a, long n, ulong offset)
+{
+ int i, r;
+ Ctlr *ctlr;
+ char *alloc, *e, *p;
+
+ ctlr = edev->ctlr;
+
+ alloc = malloc(READSTR);
+ p = alloc;
+ e = p + READSTR;
+ for(i = 0; i < Nrxstats; i++){
+ p = seprint(p, e, "%s: %ud\n", rxstats[i], ctlr->rxstats[i]);
+ }
+ for(i = 0; i < Ntxstats; i++){
+ if(txstats[i] == nil)
+ continue;
+ p = seprint(p, e, "%s: %ud\n", txstats[i], ctlr->txstats[i]);
+ }
+ p = seprint(p, e, "cls: %ud\n", ctlr->cls);
+ p = seprint(p, e, "intr: %ud\n", ctlr->intr);
+ p = seprint(p, e, "lintr: %ud\n", ctlr->lintr);
+ p = seprint(p, e, "lsleep: %ud\n", ctlr->lsleep);
+ p = seprint(p, e, "rintr: %ud\n", ctlr->rintr);
+ p = seprint(p, e, "tintr: %ud\n", ctlr->tintr);
+ p = seprint(p, e, "txdw: %ud\n", ctlr->txdw);
+ p = seprint(p, e, "tdumax: %ud\n", ctlr->tdumax);
+ p = seprint(p, e, "tft: %ud\n", ctlr->tft);
+
+ p = seprint(p, e, "abt: %ud\n", ctlr->abt);
+ p = seprint(p, e, "tbuff: %ud\n", ctlr->tbuff);
+ p = seprint(p, e, "udf: %ud\n", ctlr->udf);
+ p = seprint(p, e, "abti: %ud\n", ctlr->abti);
+ p = seprint(p, e, "udfi: %ud\n", ctlr->udfi);
+ p = seprint(p, e, "tu: %ud\n", ctlr->tu);
+
+ p = seprint(p, e, "tuok: %ud\n", ctlr->tuok);
+ p = seprint(p, e, "ipok: %ud\n", ctlr->ipok);
+
+ p = seprint(p, e, "rbpoolsz: %ud\n", vt6105Mrbpoolsz);
+ p = seprint(p, e, "totalt: %uld\n", ctlr->totalt);
+
+ for(i = 0; regs[i].name != nil; i++){
+ p = seprint(p, e, "%s: %2.2x\n",
+ regs[i].name, csr8r(ctlr, regs[i].offset));
+ }
+
+ if(ctlr->mii != nil && ctlr->mii->curphy != nil){
+ p = seprint(p, e, "phy: ");
+ for(i = 0; i < NMiiPhyr; i++){
+ if(i && ((i & 0x07) == 0))
+ p = seprint(p, e, "\n ");
+ r = miimir(ctlr->mii, i);
+ p = seprint(p, e, " %4.4uX", r);
+ }
+ seprint(p, e, "\n");
+ }
+
+ n = readstr(offset, a, n, alloc);
+ free(alloc);
+
+ return n;
+}
+
+static void
+vt6105Mpromiscuous(void* arg, int on)
+{
+ int rcr;
+ Ctlr *ctlr;
+ Ether *edev;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+ rcr = csr8r(ctlr, Rcr);
+ if(on)
+ rcr |= Prom;
+ else
+ rcr &= ~Prom;
+ csr8w(ctlr, Rcr, rcr);
+}
+
+static void
+vt6105Mmulticast(void* arg, uchar* addr, int on)
+{
+ /*
+ * For now Am is set in Rcr.
+ * Will need to interlock with promiscuous
+ * when this gets filled in.
+ */
+ USED(arg, addr, on);
+}
+
+static int
+vt6105Mwakeup(void* v)
+{
+ return *((int*)v) != 0;
+}
+
+static void
+vt6105Mimr(Ctlr* ctlr, int imr)
+{
+ ilock(&ctlr->clock);
+ ctlr->imr |= imr;
+ csr16w(ctlr, Imr, ctlr->imr);
+ iunlock(&ctlr->clock);
+}
+
+static void
+vt6105Mlproc(void* arg)
+{
+ Ctlr *ctlr;
+ Ether *edev;
+ MiiPhy *phy;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+ for(;;){
+ if(ctlr->mii == nil || ctlr->mii->curphy == nil)
+ break;
+ if(miistatus(ctlr->mii) < 0)
+ goto enable;
+
+ phy = ctlr->mii->curphy;
+ ilock(&ctlr->clock);
+ csr16w(ctlr, Cr, ctlr->cr & ~(Txon|Rxon));
+ if(phy->fd)
+ ctlr->cr |= Fdx;
+ else
+ ctlr->cr &= ~Fdx;
+ csr16w(ctlr, Cr, ctlr->cr);
+ iunlock(&ctlr->clock);
+enable:
+ ctlr->lwakeup = 0;
+ vt6105Mimr(ctlr, Srci);
+
+ ctlr->lsleep++;
+ sleep(&ctlr->lrendez, vt6105Mwakeup, &ctlr->lwakeup);
+
+ }
+ pexit("vt6105Mlproc: done", 1);
+}
+
+static void
+vt6105Mrbfree(Block* bp)
+{
+ bp->rp = bp->lim - (Rdbsz+3);
+ bp->wp = bp->rp;
+ bp->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
+
+ ilock(&vt6105Mrblock);
+ bp->next = vt6105Mrbpool;
+ vt6105Mrbpool = bp;
+ iunlock(&vt6105Mrblock);
+}
+
+static Block*
+vt6105Mrballoc(void)
+{
+ Block *bp;
+
+ ilock(&vt6105Mrblock);
+ if((bp = vt6105Mrbpool) != nil){
+ vt6105Mrbpool = bp->next;
+ bp->next = nil;
+ _xinc(&bp->ref); /* prevent bp from being freed */
+ }
+ iunlock(&vt6105Mrblock);
+
+ if(bp == nil && (bp = iallocb(Rdbsz+3)) != nil){
+ bp->free = vt6105Mrbfree;
+ vt6105Mrbpoolsz++;
+ }
+ return bp;
+}
+
+static void
+vt6105Mattach(Ether* edev)
+{
+ Ctlr *ctlr;
+// MiiPhy *phy;
+ uchar *alloc;
+ Ds *ds, *prev;
+ int dsz, i, timeo;
+ char name[KNAMELEN];
+
+ ctlr = edev->ctlr;
+ qlock(&ctlr->alock);
+ if(ctlr->alloc != nil){
+ qunlock(&ctlr->alock);
+ return;
+ }
+
+ /*
+ * Descriptor space.
+ * Receive descriptors should all be aligned on a 4-byte boundary,
+ * but try to do cache-line alignment.
+ */
+ ctlr->nrd = Nrd;
+ ctlr->ntd = Ntd;
+ dsz = ROUNDUP(sizeof(Ds), ctlr->cls);
+ alloc = mallocalign((ctlr->nrd+ctlr->ntd)*dsz, dsz, 0, 0);
+ if(alloc == nil){
+ qunlock(&ctlr->alock);
+ return;
+ }
+ ctlr->alloc = alloc;
+
+ ctlr->rd = (Ds*)alloc;
+
+ if(waserror()){
+ ds = ctlr->rd;
+ for(i = 0; i < ctlr->nrd; i++){
+ if(ds->bp != nil){
+ freeb(ds->bp);
+ ds->bp = nil;
+ }
+ if((ds = ds->next) == nil)
+ break;
+ }
+ free(ctlr->alloc);
+ ctlr->alloc = nil;
+ qunlock(&ctlr->alock);
+ nexterror();
+ }
+
+ prev = (Ds*)(alloc + (ctlr->nrd-1)*dsz);
+ for(i = 0; i < ctlr->nrd; i++){
+ ds = (Ds*)alloc;
+ alloc += dsz;
+
+ ds->control = Ipkt|Tcpkt|Udpkt|Rdbsz;
+ ds->branch = PCIWADDR(alloc);
+
+ ds->bp = vt6105Mrballoc();
+ if(ds->bp == nil)
+ error("vt6105M: can't allocate receive ring\n");
+ ds->bp->rp = (uchar*)ROUNDUP((ulong)ds->bp->rp, 4);
+ ds->addr = PCIWADDR(ds->bp->rp);
+
+ ds->next = (Ds*)alloc;
+ ds->prev = prev;
+ prev = ds;
+
+ ds->status = Own;
+ }
+ prev->branch = 0;
+ prev->next = ctlr->rd;
+ prev->status = 0;
+ ctlr->rdh = ctlr->rd;
+
+ ctlr->td = (Ds*)alloc;
+ prev = (Ds*)(alloc + (ctlr->ntd-1)*dsz);
+ for(i = 0; i < ctlr->ntd; i++){
+ ds = (Ds*)alloc;
+ alloc += dsz;
+
+ ds->next = (Ds*)alloc;
+ ds->prev = prev;
+ prev = ds;
+ }
+ prev->next = ctlr->td;
+ ctlr->tdh = ctlr->tdt = ctlr->td;
+ ctlr->tdused = 0;
+
+ ctlr->cr = Dpoll|Rdmd/*|Txon|Rxon*/|Strt;
+ /*Srci|Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx*/
+ ctlr->imr = Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx;
+
+ ilock(&ctlr->clock);
+ csr32w(ctlr, Rxdaddr, PCIWADDR(ctlr->rd));
+ csr32w(ctlr, Txdaddr, PCIWADDR(ctlr->td));
+ csr16w(ctlr, Isr, ~0);
+ csr16w(ctlr, Imr, ctlr->imr);
+ csr16w(ctlr, Cr, ctlr->cr);
+ iunlock(&ctlr->clock);
+
+ /*
+ * Wait for link to be ready.
+ */
+ for(timeo = 0; timeo < 350; timeo++){
+ if(miistatus(ctlr->mii) == 0)
+ break;
+ tsleep(&up->sleep, return0, 0, 10);
+ }
+// phy = ctlr->mii->curphy;
+// print("%s: speed %d fd %d link %d rfc %d tfc %d\n",
+// edev->name, phy->speed, phy->fd, phy->link, phy->rfc, phy->tfc);
+
+ ilock(&ctlr->clock);
+ ctlr->cr |= Txon|Rxon;
+ csr16w(ctlr, Cr, ctlr->cr);
+ iunlock(&ctlr->clock);
+
+ snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno);
+ kproc(name, vt6105Mlproc, edev);
+
+ qunlock(&ctlr->alock);
+ poperror();
+}
+
+static void
+vt6105Mtransmit(Ether* edev)
+{
+ Block *bp;
+ Ctlr *ctlr;
+ Ds *ds, *next;
+ int control, i, size, tdused, timeo;
+ long t;
+
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->tlock);
+ t = lcycles();
+
+ /*
+ * Free any completed packets
+ */
+ ds = ctlr->tdh;
+ for(tdused = ctlr->tdused; tdused > 0; tdused--){
+ /*
+ * For some errors the chip will turn the Tx engine
+ * off. Wait for that to happen.
+ * Could reset and re-init the chip here if it doesn't
+ * play fair.
+ * To do: adjust Tx FIFO threshold on underflow.
+ */
+ if(ds->status & (Abt|Tbuff|Udf)){
+ if(ds->status & Abt)
+ ctlr->abt++;
+ if(ds->status & Tbuff)
+ ctlr->tbuff++;
+ if(ds->status & Udf)
+ ctlr->udf++;
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!(csr16r(ctlr, Cr) & Txon))
+ break;
+ microdelay(1);
+ }
+ ds->status = Own;
+ csr32w(ctlr, Txdaddr, PCIWADDR(ds));
+ }
+
+ if(ds->status & Own)
+ break;
+ ds->addr = 0;
+ ds->branch = 0;
+
+ if(ds->bp != nil){
+ freeb(ds->bp);
+ ds->bp = nil;
+ }
+ for(i = 0; i < Ntxstats-1; i++){
+ if(ds->status & (1<<i))
+ ctlr->txstats[i]++;
+ }
+ ctlr->txstats[i] += (ds->status & NcrMASK)>>NcrSHIFT;
+
+ ds = ds->next;
+ }
+ ctlr->tdh = ds;
+
+ /*
+ * Try to fill the ring back up.
+ */
+ ds = ctlr->tdt;
+ while(tdused < ctlr->ntd-2){
+ if((bp = qget(edev->oq)) == nil)
+ break;
+ tdused++;
+
+ size = BLEN(bp);
+
+ next = ds->next;
+ ds->branch = PCIWADDR(ds->next)|Tdctl;
+
+ ds->bp = bp;
+ ds->addr = PCIWADDR(bp->rp);
+ control = Edp|Stp|((size<<TbsSHIFT) & TbsMASK);
+
+ ds->control = control;
+ if(tdused >= ctlr->ntd-2){
+ ctlr->txdw++;
+ ds->branch &= ~Tdctl;
+ }
+ coherence();
+ ds->status = Own;
+
+ ds = next;
+ }
+ ctlr->tdt = ds;
+ ctlr->tdused = tdused;
+ if(ctlr->tdused){
+ csr16w(ctlr, Cr, Tdmd|ctlr->cr);
+ if(tdused > ctlr->tdumax)
+ ctlr->tdumax = tdused;
+ }
+
+ ctlr->totalt += lcycles() - t;
+ iunlock(&ctlr->tlock);
+}
+
+static void
+vt6105Mreceive(Ether* edev)
+{
+ Ds *ds;
+ Block *bp;
+ Ctlr *ctlr;
+ int i, len;
+
+ ctlr = edev->ctlr;
+
+ ds = ctlr->rdh;
+ while(!(ds->status & Own) && ds->status != 0){
+ /*
+ * Can Long packets be received OK?
+ * What happens to the Rxok bit?
+ */
+ if(ds->status & Rerr){
+ for(i = 0; i < Nrxstats; i++){
+ if(ds->status & (1<<i))
+ ctlr->rxstats[i]++;
+ }
+ }
+ else if(bp = vt6105Mrballoc()){
+ if(ds->control & Tuok){
+ ds->bp->flag |= Btcpck|Budpck;
+ ctlr->tuok++;
+ }
+ if(ds->control & Ipok){
+ ds->bp->flag |= Bipck;
+ ctlr->ipok++;
+ }
+ len = ((ds->status & LengthMASK)>>LengthSHIFT)-4;
+ ds->bp->wp = ds->bp->rp+len;
+ etheriq(edev, ds->bp, 1);
+ bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4);
+ ds->addr = PCIWADDR(bp->rp);
+ ds->bp = bp;
+ }
+ ds->control = Ipkt|Tcpkt|Udpkt|Rdbsz;
+ ds->branch = 0;
+ ds->status = 0;
+
+ ds->prev->branch = PCIWADDR(ds);
+ coherence();
+ ds->prev->status = Own;
+
+ ds = ds->next;
+ }
+ ctlr->rdh = ds;
+
+ csr16w(ctlr, Cr, ctlr->cr);
+}
+
+static void
+vt6105Minterrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Ether *edev;
+ int imr, isr, r, timeo;
+ long t;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->clock);
+ t = lcycles();
+
+ csr16w(ctlr, Imr, 0);
+ imr = ctlr->imr;
+ ctlr->intr++;
+ for(;;){
+ if((isr = csr16r(ctlr, Isr)) != 0)
+ csr16w(ctlr, Isr, isr);
+ if((isr & ctlr->imr) == 0)
+ break;
+
+ if(isr & Srci){
+ imr &= ~Srci;
+ ctlr->lwakeup = isr & Srci;
+ wakeup(&ctlr->lrendez);
+ isr &= ~Srci;
+ ctlr->lintr++;
+ }
+ if(isr & (Norbf|Pktrace|Ovfi|Ru|Rxe|Prx)){
+ vt6105Mreceive(edev);
+ isr &= ~(Norbf|Pktrace|Ovfi|Ru|Rxe|Prx);
+ ctlr->rintr++;
+ }
+ if(isr & (Abti|Udfi|Tu|Txe|Ptx)){
+ if(isr & (Abti|Udfi|Tu)){
+ if(isr & Abti)
+ ctlr->abti++;
+ if(isr & Udfi)
+ ctlr->udfi++;
+ if(isr & Tu)
+ ctlr->tu++;
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!(csr16r(ctlr, Cr) & Txon))
+ break;
+ microdelay(1);
+ }
+
+ if((isr & Udfi) && ctlr->tft < CtftSAF){
+ ctlr->tft += 1<<CtftSHIFT;
+ r = csr8r(ctlr, Bcr1) & ~CtftMASK;
+ csr8w(ctlr, Bcr1, r|ctlr->tft);
+ }
+ }
+
+
+ ctlr->totalt += lcycles() - t;
+ vt6105Mtransmit(edev);
+ t = lcycles();
+ isr &= ~(Abti|Udfi|Tu|Txe|Ptx);
+ ctlr->tintr++;
+ }
+ if(isr)
+ panic("vt6105M: isr %4.4uX\n", isr);
+ }
+ ctlr->imr = imr;
+ csr16w(ctlr, Imr, ctlr->imr);
+
+ ctlr->totalt += lcycles() - t;
+ iunlock(&ctlr->clock);
+}
+
+static int
+vt6105Mmiimicmd(Mii* mii, int pa, int ra, int cmd, int data)
+{
+ Ctlr *ctlr;
+ int r, timeo;
+
+ ctlr = mii->ctlr;
+
+ csr8w(ctlr, Miicr, 0);
+ r = csr8r(ctlr, Phyadr);
+ csr8w(ctlr, Phyadr, (r & ~PhyadMASK)|pa);
+ csr8w(ctlr, Phyadr, pa);
+ csr8w(ctlr, Miiadr, ra);
+ if(cmd == Wcmd)
+ csr16w(ctlr, Miidata, data);
+ csr8w(ctlr, Miicr, cmd);
+
+ for(timeo = 0; timeo < 10000; timeo++){
+ if(!(csr8r(ctlr, Miicr) & cmd))
+ break;
+ microdelay(1);
+ }
+ if(timeo >= 10000)
+ return -1;
+
+ if(cmd == Wcmd)
+ return 0;
+ return csr16r(ctlr, Miidata);
+}
+
+static int
+vt6105Mmiimir(Mii* mii, int pa, int ra)
+{
+ return vt6105Mmiimicmd(mii, pa, ra, Rcmd, 0);
+}
+
+static int
+vt6105Mmiimiw(Mii* mii, int pa, int ra, int data)
+{
+ return vt6105Mmiimicmd(mii, pa, ra, Wcmd, data);
+}
+
+static int
+vt6105Mdetach(Ctlr* ctlr)
+{
+ int revid, timeo;
+
+ /*
+ * Reset power management registers.
+ */
+ revid = pcicfgr8(ctlr->pcidev, PciRID);
+ if(revid >= 0x40){
+ /* Set power state D0. */
+ csr8w(ctlr, Stickhw, csr8r(ctlr, Stickhw) & 0xFC);
+
+ /* Disable force PME-enable. */
+ csr8w(ctlr, Wolcgclr, 0x80);
+
+ /* Clear WOL config and status bits. */
+ csr8w(ctlr, Wolcrclr, 0xFF);
+ csr8w(ctlr, Pwrcsrclr, 0xFF);
+ }
+
+ /*
+ * Soft reset the controller.
+ */
+ csr16w(ctlr, Cr, Stop);
+ csr16w(ctlr, Cr, Stop|Sfrst);
+ for(timeo = 0; timeo < 10000; timeo++){
+ if(!(csr16r(ctlr, Cr) & Sfrst))
+ break;
+ microdelay(1);
+ }
+ if(timeo >= 1000)
+ return -1;
+
+ return 0;
+}
+
+static int
+vt6105Mreset(Ctlr* ctlr)
+{
+ MiiPhy *phy;
+ int i, r, timeo;
+
+ if(vt6105Mdetach(ctlr) < 0)
+ return -1;
+
+ /*
+ * Load the MAC address into the PAR[01]
+ * registers.
+ */
+ r = csr8r(ctlr, Eecsr);
+ csr8w(ctlr, Eecsr, Autold|r);
+ for(timeo = 0; timeo < 100; timeo++){
+ if(!(csr8r(ctlr, Cr) & Autold))
+ break;
+ microdelay(1);
+ }
+ if(timeo >= 100)
+ return -1;
+
+ for(i = 0; i < Eaddrlen; i++)
+ ctlr->par[i] = csr8r(ctlr, Par0+i);
+
+ /*
+ * Configure DMA and Rx/Tx thresholds.
+ * If the Rx/Tx threshold bits in Bcr[01] are 0 then
+ * the thresholds are determined by Rcr/Tcr.
+ */
+ r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK);
+ csr8w(ctlr, Bcr0, r|Crft128|DmaSAF);
+ r = csr8r(ctlr, Bcr1) & ~CtftMASK;
+ csr8w(ctlr, Bcr1, r|ctlr->tft);
+
+ r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep);
+ csr8w(ctlr, Rcr, r|Ab|Am);
+ csr32w(ctlr, Mcfilt0, ~0UL); /* accept all multicast */
+ csr32w(ctlr, Mcfilt1, ~0UL);
+
+ r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0);
+ csr8w(ctlr, Tcr, r);
+
+ /*
+ * Link management.
+ */
+ if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+ return -1;
+ ctlr->mii->mir = vt6105Mmiimir;
+ ctlr->mii->miw = vt6105Mmiimiw;
+ ctlr->mii->ctlr = ctlr;
+
+ if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
+ free(ctlr->mii);
+ ctlr->mii = nil;
+ return -1;
+ }
+// print("oui %X phyno %d\n", phy->oui, phy->phyno);
+ USED(phy);
+
+ if(miistatus(ctlr->mii) < 0){
+// miireset(ctlr->mii);
+ miiane(ctlr->mii, ~0, ~0, ~0);
+ }
+
+ return 0;
+}
+
+static void
+vt6105Mpci(void)
+{
+ Pcidev *p;
+ Ctlr *ctlr;
+ int cls, port;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
+ continue;
+
+ switch((p->did<<16)|p->vid){
+ default:
+ continue;
+ case (0x3053<<16)|0x1106: /* Rhine III-M vt6105M */
+ break;
+ }
+
+ port = p->mem[0].bar & ~0x01;
+ if(ioalloc(port, p->mem[0].size, 0, "vt6105M") < 0){
+ print("vt6105M: port 0x%uX in use\n", port);
+ continue;
+ }
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = port;
+ ctlr->pcidev = p;
+ ctlr->id = (p->did<<16)|p->vid;
+ if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF)
+ cls = 0x10;
+ ctlr->cls = cls*4;
+ if(ctlr->cls < sizeof(Ds)){
+ print("vt6105M: cls %d < sizeof(Ds)\n", ctlr->cls);
+ iofree(port);
+ free(ctlr);
+ continue;
+ }
+ ctlr->tft = CtftSAF;
+
+ if(vt6105Mreset(ctlr)){
+ iofree(port);
+ free(ctlr);
+ continue;
+ }
+ pcisetbme(p);
+
+ if(vt6105Mctlrhead != nil)
+ vt6105Mctlrtail->next = ctlr;
+ else
+ vt6105Mctlrhead = ctlr;
+ vt6105Mctlrtail = ctlr;
+ }
+}
+
+static int
+vt6105Mpnp(Ether* edev)
+{
+ Ctlr *ctlr;
+
+ if(vt6105Mctlrhead == nil)
+ vt6105Mpci();
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = vt6105Mctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+ /*
+ * Set to 1000Mb/s to fool the bsz calculation. We need
+ * something better, though.
+ */
+ edev->mbps = 1000;
+ memmove(edev->ea, ctlr->par, Eaddrlen);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ edev->attach = vt6105Mattach;
+ edev->transmit = vt6105Mtransmit;
+ edev->interrupt = vt6105Minterrupt;
+ edev->ifstat = vt6105Mifstat;
+ edev->ctl = nil;
+
+ edev->arg = edev;
+ edev->promiscuous = vt6105Mpromiscuous;
+ edev->multicast = vt6105Mmulticast;
+
+ edev->maxmtu = ETHERMAXTU+Bslop;
+
+ return 0;
+}
+
+void
+ethervt6105mlink(void)
+{
+ addethercard("vt6105M", vt6105Mpnp);
+}
diff --git a/sys/src/9/pc/etherwavelan.c b/sys/src/9/pc/etherwavelan.c
new file mode 100755
index 000000000..e76905b52
--- /dev/null
+++ b/sys/src/9/pc/etherwavelan.c
@@ -0,0 +1,197 @@
+/* Pci/pcmcia code for wavelan.c */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+#include "etherif.h"
+
+#include "wavelan.h"
+
+static int
+wavelanpcmciareset(Ether *ether)
+{
+ int i;
+ char *p;
+ Ctlr *ctlr;
+
+ if((ctlr = malloc(sizeof(Ctlr))) == nil)
+ return -1;
+
+ ilock(ctlr);
+ ctlr->ctlrno = ether->ctlrno;
+
+ if (ether->port==0)
+ ether->port=WDfltIOB;
+ ctlr->iob = ether->port;
+
+ if (ether->irq==0)
+ ether->irq=WDfltIRQ;
+
+ if (ioalloc(ether->port,WIOLen,0,"wavelan")<0){
+ // print("#l%d: port 0x%lx in use\n",
+ // ether->ctlrno, ether->port);
+ goto abort1;
+ }
+
+ /*
+ * If id= is specified, card must match. Otherwise try generic.
+ */
+ ctlr->slot = -1;
+ for(i=0; i<ether->nopt; i++){
+ if(cistrncmp(ether->opt[i], "id=", 3) == 0){
+ if((ctlr->slot = pcmspecial(&ether->opt[i][3], ether)) < 0)
+ goto abort;
+ break;
+ }
+ }
+ if(ctlr->slot == -1){
+ for (i=0; wavenames[i]; i++)
+ if((ctlr->slot = pcmspecial(wavenames[i], ether))>=0)
+ break;
+ if(!wavenames[i]){
+ DEBUG("no wavelan found\n");
+ goto abort;
+ }
+ }
+
+ // DEBUG("#l%d: port=0x%lx irq=%ld\n",
+ // ether->ctlrno, ether->port, ether->irq);
+
+ if(wavelanreset(ether, ctlr) < 0){
+ abort:
+ iofree(ether->port);
+ abort1:
+ iunlock(ctlr);
+ free(ctlr);
+ ether->ctlr = nil;
+ return -1;
+ }
+
+ for(i = 0; i < ether->nopt; i++){
+ if(p = strchr(ether->opt[i], '='))
+ *p = ' ';
+ w_option(ctlr, ether->opt[i], strlen(ether->opt[i]));
+ }
+
+ iunlock(ctlr);
+ return 0;
+}
+
+static struct {
+ int vid;
+ int did;
+} wavelanpci[] = {
+ 0x1260, 0x3873, /* Intersil Prism2.5 */
+ 0x1737, 0x0019, /* Linksys WPC-11 untested */
+};
+
+static Ctlr *ctlrhead, *ctlrtail;
+
+static void
+wavelanpciscan(void)
+{
+ int i;
+ void *mem;
+ Pcidev *p;
+ Ctlr *ctlr;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ for(i=0; i<nelem(wavelanpci); i++)
+ if(p->vid == wavelanpci[i].vid && p->did == wavelanpci[i].did)
+ break;
+ if(i==nelem(wavelanpci))
+ continue;
+
+ /*
+ * On the Prism, bar[0] is the memory-mapped register address (4KB),
+ */
+ if(p->mem[0].size != 4096){
+ print("wavelanpci: %.4ux %.4ux: unlikely mmio size\n", p->vid, p->did);
+ continue;
+ }
+
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->pcidev = p;
+ 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 = mem;
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ pcisetbme(p);
+ }
+}
+
+static int
+wavelanpcireset(Ether *ether)
+{
+ int i;
+ char *p;
+ Ctlr *ctlr;
+
+ if(ctlrhead == nil)
+ wavelanpciscan();
+
+ /*
+ * Allow plan9.ini to set vid, did?
+ */
+ for(ctlr=ctlrhead; ctlr!=nil; ctlr=ctlr->next)
+ if(ctlr->active == 0)
+ break;
+ if(ctlr == nil)
+ return -1;
+
+ ctlr->active = 1;
+ ilock(ctlr);
+ ether->irq = ctlr->pcidev->intl;
+ ether->tbdf = ctlr->pcidev->tbdf;
+
+ /*
+ * Really hard reset.
+ */
+ csr_outs(ctlr, WR_PciCor, 0x0080);
+ delay(250);
+ csr_outs(ctlr, WR_PciCor, 0x0000);
+ delay(500);
+ for(i=0; i<2*10; i++){
+ if(!(csr_ins(ctlr, WR_Cmd)&WCmdBusy))
+ break;
+ delay(100);
+ }
+ if(i >= 2*10)
+ print("wavelan pci %.4ux %.4ux: reset timeout %.4ux\n",
+ ctlr->pcidev->vid, ctlr->pcidev->did, csr_ins(ctlr, WR_Cmd));
+
+ if(wavelanreset(ether, ctlr) < 0){
+ iunlock(ctlr);
+ ether->ctlr = nil;
+ return -1;
+ }
+
+ for(i = 0; i < ether->nopt; i++){
+ if(p = strchr(ether->opt[i], '='))
+ *p = ' ';
+ w_option(ctlr, ether->opt[i], strlen(ether->opt[i]));
+ }
+ iunlock(ctlr);
+ return 0;
+}
+
+void
+etherwavelanlink(void)
+{
+ addethercard("wavelan", wavelanpcmciareset);
+ addethercard("wavelanpci", wavelanpcireset);
+}
diff --git a/sys/src/9/pc/floppy.h b/sys/src/9/pc/floppy.h
new file mode 100755
index 000000000..f84c9eae7
--- /dev/null
+++ b/sys/src/9/pc/floppy.h
@@ -0,0 +1,183 @@
+typedef struct FController FController;
+typedef struct FDrive FDrive;
+typedef struct FType FType;
+
+static void floppyintr(Ureg*);
+static int floppyon(FDrive*);
+static void floppyoff(FDrive*);
+static void floppysetdef(FDrive*);
+
+/*
+ * a floppy drive
+ */
+struct FDrive
+{
+ FType *t; /* floppy type */
+ int dt; /* drive type */
+ int dev;
+
+ ulong lasttouched; /* time last touched */
+ int cyl; /* current arm position */
+ int confused; /* needs to be recalibrated */
+ int vers;
+ int maxtries; /* max read attempts before Eio */
+
+ int tcyl; /* target cylinder */
+ int thead; /* target head */
+ int tsec; /* target sector */
+ long len; /* size of xfer */
+
+ uchar *cache; /* track cache */
+ int ccyl;
+ int chead;
+};
+
+/*
+ * controller for 4 floppys
+ */
+struct FController
+{
+ QLock; /* exclusive access to the contoller */
+
+ int ndrive;
+ FDrive *d; /* the floppy drives */
+ FDrive *selected;
+ int rate; /* current rate selected */
+ uchar cmd[14]; /* command */
+ int ncmd; /* # command bytes */
+ uchar stat[14]; /* command status */
+ int nstat; /* # status bytes */
+ int confused; /* controler needs to be reset */
+ Rendez r; /* wait here for command termination */
+ int motor; /* bit mask of spinning disks */
+};
+
+/*
+ * floppy types (all MFM encoding)
+ */
+struct FType
+{
+ char *name;
+ int dt; /* compatible drive type */
+ int bytes; /* bytes/sector */
+ int sectors; /* sectors/track */
+ int heads; /* number of heads */
+ int steps; /* steps per cylinder */
+ int tracks; /* tracks/disk */
+ int gpl; /* intersector gap length for read/write */
+ int fgpl; /* intersector gap length for format */
+ int rate; /* rate code */
+
+ /*
+ * these depend on previous entries and are set filled in
+ * by floppyinit
+ */
+ int bcode; /* coded version of bytes for the controller */
+ long cap; /* drive capacity in bytes */
+ long tsize; /* track size in bytes */
+};
+/* bits in the registers */
+enum
+{
+ /* status registers a & b */
+ Psra= 0x3f0,
+ Psrb= 0x3f1,
+
+ /* digital output register */
+ Pdor= 0x3f2,
+ Fintena= 0x8, /* enable floppy interrupt */
+ Fena= 0x4, /* 0 == reset controller */
+
+ /* main status register */
+ Pmsr= 0x3f4,
+ Fready= 0x80, /* ready to be touched */
+ Ffrom= 0x40, /* data from controller */
+ Ffloppybusy= 0x10, /* operation not over */
+
+ /* data register */
+ Pfdata= 0x3f5,
+ Frecal= 0x07, /* recalibrate cmd */
+ Fseek= 0x0f, /* seek cmd */
+ Fsense= 0x08, /* sense cmd */
+ Fread= 0x66, /* read cmd */
+ Freadid= 0x4a, /* read track id */
+ Fspec= 0x03, /* set hold times */
+ Fwrite= 0x45, /* write cmd */
+ Fformat= 0x4d, /* format cmd */
+ Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */
+ Fdumpreg= 0x0e, /* dump internal registers */
+
+ /* digital input register */
+ Pdir= 0x3F7, /* disk changed port (read only) */
+ Pdsr= 0x3F7, /* data rate select port (write only) */
+ Fchange= 0x80, /* disk has changed */
+
+ /* status 0 byte */
+ Drivemask= 3<<0,
+ Seekend= 1<<5,
+ Codemask= (3<<6)|(3<<3),
+ Cmdexec= 1<<6,
+
+ /* status 1 byte */
+ Overrun= 0x10,
+};
+
+
+static void
+pcfloppyintr(Ureg *ur, void *a)
+{
+ USED(a);
+
+ floppyintr(ur);
+}
+
+void
+floppysetup0(FController *fl)
+{
+ fl->ndrive = 0;
+ if(ioalloc(Psra, 6, 0, "floppy") < 0)
+ return;
+ if(ioalloc(Pdir, 1, 0, "floppy") < 0){
+ iofree(Psra);
+ return;
+ }
+ fl->ndrive = 2;
+}
+
+void
+floppysetup1(FController *fl)
+{
+ uchar equip;
+
+ /*
+ * read nvram for types of floppies 0 & 1
+ */
+ equip = nvramread(0x10);
+ if(fl->ndrive > 0){
+ fl->d[0].dt = (equip >> 4) & 0xf;
+ floppysetdef(&fl->d[0]);
+ }
+ if(fl->ndrive > 1){
+ fl->d[1].dt = equip & 0xf;
+ floppysetdef(&fl->d[1]);
+ }
+ intrenable(IrqFLOPPY, pcfloppyintr, fl, BUSUNKNOWN, "floppy");
+}
+
+/*
+ * eject disk ( unknown on safari )
+ */
+void
+floppyeject(FDrive *dp)
+{
+ floppyon(dp);
+ dp->vers++;
+ floppyoff(dp);
+}
+
+int
+floppyexec(char *a, long b, int c)
+{
+ USED(a, b, c);
+ return b;
+}
diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h
new file mode 100755
index 000000000..bce829162
--- /dev/null
+++ b/sys/src/9/pc/fns.h
@@ -0,0 +1,184 @@
+#include "../port/portfns.h"
+
+void aamloop(int);
+Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong));
+void archinit(void);
+int bios32call(BIOS32ci*, u16int[3]);
+int bios32ci(BIOS32si*, BIOS32ci*);
+void bios32close(BIOS32si*);
+BIOS32si* bios32open(char*);
+void bootargs(void*);
+ulong cankaddr(ulong);
+void clockintr(Ureg*, void*);
+int (*cmpswap)(long*, long, long);
+int cmpswap486(long*, long, long);
+void (*coherence)(void);
+void cpuid(int, ulong regs[]);
+int cpuidentify(void);
+void cpuidprint(void);
+void (*cycles)(uvlong*);
+void delay(int);
+int dmacount(int);
+int dmadone(int);
+void dmaend(int);
+int dmainit(int, int);
+long dmasetup(int, void*, long, int);
+#define evenaddr(x) /* x86 doesn't care */
+void fpclear(void);
+void fpenv(FPsave*);
+void fpinit(void);
+void fpoff(void);
+void fprestore(FPsave*);
+void fpsave(FPsave*);
+ulong fpstatus(void);
+ulong getcr0(void);
+ulong getcr2(void);
+ulong getcr3(void);
+ulong getcr4(void);
+char* getconf(char*);
+void guesscpuhz(int);
+void halt(void);
+int i8042auxcmd(int);
+int i8042auxcmds(uchar*, int);
+void i8042auxenable(void (*)(int, int));
+void i8042reset(void);
+void i8250console(void);
+void* i8250alloc(int, int, int);
+void i8250mouse(char*, int (*)(Queue*, int), int);
+void i8250setmouseputc(char*, int (*)(Queue*, int));
+void i8253enable(void);
+void i8253init(void);
+void i8253link(void);
+uvlong i8253read(uvlong*);
+void i8253timerset(uvlong);
+int i8259disable(int);
+int i8259enable(Vctl*);
+void i8259init(void);
+int i8259isr(int);
+void i8259on(void);
+void i8259off(void);
+int i8259vecno(int);
+void idle(void);
+void idlehands(void);
+int inb(int);
+void insb(int, void*, int);
+ushort ins(int);
+void inss(int, void*, int);
+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);
+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()
+void lgdt(ushort[3]);
+void lidt(ushort[3]);
+void links(void);
+void ltr(ulong);
+void mach0init(void);
+void mathinit(void);
+void mb386(void);
+void mb586(void);
+void meminit(void);
+void memorysummary(void);
+void mfence(void);
+#define mmuflushtlb(pdb) putcr3(pdb)
+void mmuinit(void);
+ulong* mmuwalk(ulong*, ulong, int, int);
+int mtrr(uvlong, uvlong, char *);
+void mtrrclock(void);
+int mtrrprint(char *, long);
+uchar nvramread(int);
+void nvramwrite(int, uchar);
+void outb(int, int);
+void outsb(int, void*, int);
+void outs(int, ushort);
+void outss(int, void*, int);
+void outl(int, ulong);
+void outsl(int, void*, int);
+ulong paddr(void*);
+ulong pcibarsize(Pcidev*, int);
+void pcibussize(Pcidev*, ulong*, ulong*);
+int pcicfgr8(Pcidev*, int);
+int pcicfgr16(Pcidev*, int);
+int pcicfgr32(Pcidev*, int);
+void pcicfgw8(Pcidev*, int, int);
+void pcicfgw16(Pcidev*, int, int);
+void pcicfgw32(Pcidev*, int, int);
+void pciclrbme(Pcidev*);
+void pciclrioe(Pcidev*);
+void pciclrmwi(Pcidev*);
+int pcigetpms(Pcidev*);
+void pcihinv(Pcidev*);
+uchar pciipin(Pcidev*, uchar);
+Pcidev* pcimatch(Pcidev*, int, int);
+Pcidev* pcimatchtbdf(int);
+void pcireset(void);
+int pciscan(int, Pcidev**);
+void pcisetbme(Pcidev*);
+void pcisetioe(Pcidev*);
+void pcisetmwi(Pcidev*);
+int pcisetpms(Pcidev*, int);
+void pcmcisread(PCMslot*);
+int pcmcistuple(int, int, int, void*, int);
+PCMmap* pcmmap(int, ulong, int, int);
+int pcmspecial(char*, ISAConf*);
+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 putcr0(ulong);
+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 syscallfmt(int syscallno, ulong pc, va_list list);
+void sysretfmt(int syscallno, va_list list, long ret, uvlong start, uvlong stop);
+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 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 wbinvd(void);
+void wrmsr(int, vlong);
+int xchgw(ushort*, int);
+
+#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
+#define KADDR(a) kaddr(a)
+#define PADDR(a) paddr((void*)(a))
+
+#define dcflush(a, b)
diff --git a/sys/src/9/pc/hcwAMC.h b/sys/src/9/pc/hcwAMC.h
new file mode 100755
index 000000000..ef42f1012
--- /dev/null
+++ b/sys/src/9/pc/hcwAMC.h
@@ -0,0 +1,2027 @@
+static uchar hcwAMC[] = {
+ 0xFF,0xFF,0x62,0x7F,0x16,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,
+ 0x00,0x02,0x01,0x00,0x41,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x02,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFA,0x00,0x00,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDA,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,
+ 0x40,0x00,0x40,0x02,0x00,0x02,0x40,0x02,0x00,0x02,0x00,0x02,0x40,0x00,0x00,0x02,
+ 0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x00,0x00,0x0A,0x51,
+ 0x02,0x50,0x02,0x40,0x0A,0x51,0x02,0x50,0x02,0x40,0x0A,0x41,0x0A,0x41,0x02,0x40,
+ 0x02,0x00,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x40,0x00,0x00,0x02,0x40,0x02,0x40,
+ 0x00,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x80,0x91,0x00,0x00,0x12,0x50,0x82,
+ 0x40,0x02,0x40,0x82,0x50,0x02,0x44,0x02,0x40,0x06,0x40,0x06,0x40,0x02,0x42,0x02,
+ 0x42,0x02,0x40,0x42,0x60,0x02,0x40,0x02,0x40,0x02,0x68,0x02,0x40,0x02,0x40,0x02,
+ 0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x80,0xF5,0x00,0x00,0x02,0x40,0x00,0x40,
+ 0x00,0x00,0x02,0x40,0x00,0x40,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x40,0x00,0x40,
+ 0x02,0x00,0x02,0x40,0x02,0x00,0x02,0x00,0x02,0x40,0x00,0x00,0x02,0x00,0x02,0x00,
+ 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB8,0x00,0x00,0x02,0x40,0x02,0x40,0x02,
+ 0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,
+ 0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x40,0x02,
+ 0x40,0x02,0x40,0x02,0x40,0x00,0x00,0xBE,0x00,0x00,0x14,0x00,0x02,0x20,0x02,0x40,
+ 0x44,0x00,0x02,0x10,0x02,0x40,0x00,0x44,0x00,0x44,0x0A,0x54,0x02,0x50,0x8A,0x40,
+ 0x0A,0x44,0x06,0x42,0x0A,0x44,0x0A,0x48,0x02,0x40,0x46,0x40,0x00,0x40,0x0A,0x44,
+ 0x02,0x40,0x02,0x40,0x00,0x80,0xB1,0x80,0x60,0x09,0x51,0x27,0x40,0x01,0x00,0x80,
+ 0x40,0x02,0x52,0x09,0x42,0x02,0x62,0x24,0x60,0x01,0x00,0x00,0x40,0x04,0x62,0x4B,
+ 0x40,0x1B,0x40,0x01,0x51,0x08,0x00,0x00,0x48,0x87,0x40,0x00,0x40,0x00,0x00,0x20,
+ 0x50,0x08,0x51,0x03,0xC0,0xC3,0x00,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x02,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x01,0x00,0x8D,0x00,0x00,0x03,0x00,0x01,0x40,0x01,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x40,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x40,0x01,0x00,0x03,0x00,0x03,
+ 0x40,0x00,0x00,0x03,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x99,0x0A,0x41,0x21,0x40,0x13,0x50,0x25,0x00,0x00,0x60,0x25,0x40,
+ 0x12,0x50,0x24,0x40,0x23,0x40,0x14,0x00,0x00,0x40,0x01,0x41,0x23,0x60,0x03,0x52,
+ 0x08,0x42,0x43,0x00,0x00,0x50,0x41,0x50,0x2B,0x40,0x00,0x00,0x00,0x40,0x80,0x40,
+ 0x09,0x01,0xA6,0x2A,0x20,0x20,0x20,0x07,0x40,0x00,0x00,0x40,0x60,0x88,0x00,0x05,
+ 0x54,0x00,0x21,0x83,0x00,0x0B,0x00,0x00,0x52,0x22,0x10,0x23,0x10,0x42,0x40,0x40,
+ 0x00,0x07,0x00,0x20,0x50,0x02,0x12,0x03,0x28,0x00,0x00,0x00,0x00,0x03,0x42,0x02,
+ 0x40,0x8C,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x03,0x00,
+ 0x03,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x40,
+ 0xC8,0x02,0x40,0x00,0x40,0x03,0x40,0x03,0x80,0x00,0x40,0x01,0xC0,0x01,0x40,0x01,
+ 0x40,0x01,0x40,0x03,0x80,0x00,0x00,0x02,0x40,0x01,0x40,0x03,0x40,0x00,0x40,0x00,
+ 0x00,0x00,0xC0,0x00,0x40,0x00,0x80,0x03,0x00,0x00,0x40,0x00,0x40,0x02,0x00,0xCC,
+ 0x00,0x02,0x04,0x01,0x02,0x02,0x07,0x42,0x00,0x00,0x02,0x51,0x20,0x00,0x08,0x04,
+ 0x8B,0xD0,0x00,0x42,0x00,0x00,0x26,0x00,0x47,0x00,0x07,0x11,0x0B,0x21,0x02,0xC1,
+ 0x00,0x40,0x24,0x00,0x84,0x40,0x00,0x00,0x00,0xC0,0x00,0x10,0x24,0x00,0xCD,0x00,
+ 0x64,0x09,0x68,0x41,0x40,0x03,0x48,0x02,0x64,0x00,0x52,0x07,0x68,0x08,0x62,0x86,
+ 0x40,0x03,0x00,0x00,0x40,0x20,0x50,0x0A,0x51,0x08,0x00,0x00,0x48,0x03,0x00,0x00,
+ 0x48,0x07,0x51,0x0A,0x40,0x00,0x00,0x10,0x50,0x08,0x64,0x06,0x40,0xBF,0x00,0x00,
+ 0x01,0x00,0x03,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xBC,0x00,0x00,0x03,
+ 0x00,0x01,0x00,0x02,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,
+ 0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x01,
+ 0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0xBF,0x02,0x40,0x01,0x44,
+ 0x25,0x50,0x84,0x50,0x28,0x40,0x14,0x40,0x01,0x44,0x00,0x41,0x02,0x51,0x18,0x00,
+ 0x00,0x40,0x05,0x42,0x80,0x40,0x00,0x02,0x00,0x60,0x84,0x00,0x00,0x60,0x41,0x40,
+ 0x42,0x40,0x00,0x00,0x00,0x40,0x20,0x40,0x43,0x80,0x95,0x22,0x20,0x00,0x21,0x40,
+ 0x00,0x00,0x00,0x03,0x44,0x88,0x00,0x03,0x00,0x03,0x21,0x05,0x00,0x02,0x00,0x00,
+ 0x52,0x02,0x00,0x21,0x10,0x01,0x00,0x00,0x40,0x02,0x00,0x20,0x50,0x02,0x00,0x09,
+ 0x08,0x00,0x00,0x40,0x00,0x88,0x40,0x0B,0xC0,0xB7,0x00,0x00,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x01,0x00,0x00,0x40,0x03,0x00,0x02,0x00,0x01,0x00,0x00,0x00,
+ 0x01,0x40,0x02,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x40,0x02,0x00,
+ 0x03,0x00,0x00,0x00,0x02,0x40,0x02,0x40,0xE8,0x02,0xC0,0x00,0x40,0x01,0x40,0x02,
+ 0x40,0x03,0x40,0x01,0x40,0x03,0x40,0x00,0xC0,0x01,0x40,0x02,0x00,0x00,0x80,0x02,
+ 0x40,0x01,0x40,0x01,0x80,0x00,0x40,0x02,0x00,0x00,0x40,0x00,0xC0,0x00,0x00,0x03,
+ 0x00,0x00,0x40,0x00,0xC0,0x03,0x80,0xD3,0x02,0x40,0x04,0x01,0x88,0x20,0x05,0x01,
+ 0x07,0x12,0x03,0x14,0x08,0x08,0x00,0x40,0x22,0x00,0x05,0xC2,0x00,0x40,0x16,0xC0,
+ 0x46,0x00,0x84,0x40,0x00,0x00,0x15,0x00,0x00,0x00,0x14,0x40,0x00,0x12,0x00,0x00,
+ 0x00,0x20,0x80,0x50,0x02,0x02,0xE4,0x40,0x40,0x03,0x62,0x07,0x64,0x07,0x48,0x02,
+ 0x40,0x82,0x40,0x01,0x58,0x00,0x48,0x03,0x52,0x06,0x00,0x00,0x40,0x08,0x62,0x18,
+ 0x50,0x2B,0x60,0x03,0x48,0x0B,0x40,0x01,0x68,0x07,0x40,0x03,0x40,0x00,0x00,0x00,
+ 0x44,0x01,0x44,0x01,0xC0,0xFE,0x00,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x02,0x00,
+ 0x02,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x03,0x00,0xBD,0x00,0x00,0x02,0x40,0x02,0x40,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x01,0x00,0x00,0x40,0x01,0x00,0x03,0x00,0x01,
+ 0x40,0x00,0x40,0x00,0x00,0x00,0x40,0x01,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x03,
+ 0x00,0x01,0x00,0xFC,0x0A,0x61,0x44,0x40,0x10,0x40,0x10,0x50,0x08,0x42,0x08,0x58,
+ 0x14,0x40,0x88,0x60,0x19,0x40,0x01,0x04,0x00,0x40,0x41,0x40,0x23,0x40,0x11,0x40,
+ 0x09,0x61,0x20,0x40,0x04,0x42,0x41,0x40,0x0A,0x44,0x00,0x00,0x00,0x60,0x87,0x60,
+ 0x14,0x00,0xB8,0x2A,0x20,0x00,0x58,0x00,0x61,0x0A,0x00,0x03,0x40,0x04,0x00,0x05,
+ 0x22,0x01,0x00,0x00,0x40,0x06,0x00,0x00,0x52,0x06,0x00,0x00,0x14,0x12,0x40,0x06,
+ 0x40,0x06,0x00,0x28,0x50,0x06,0x00,0x05,0x18,0x00,0x00,0x10,0x10,0x8A,0x00,0x00,
+ 0x40,0xA4,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x40,
+ 0xF9,0x02,0x40,0x02,0x40,0x03,0xC0,0x02,0x40,0x03,0xC0,0x01,0xC0,0x03,0x40,0x00,
+ 0xC0,0x01,0x80,0x02,0x00,0x00,0x00,0x02,0x40,0x00,0x40,0x02,0xC0,0x02,0x40,0x02,
+ 0x40,0x02,0x40,0x00,0x40,0x03,0x00,0x03,0x00,0x00,0x40,0x03,0x40,0x03,0x80,0xF0,
+ 0x40,0x00,0x05,0x01,0x19,0x40,0x13,0x00,0x07,0x42,0x02,0x44,0x23,0x00,0x24,0x40,
+ 0x86,0x40,0x11,0xC0,0x00,0x00,0x12,0x00,0x00,0x00,0x06,0x51,0x10,0x00,0x11,0x00,
+ 0x01,0x04,0x10,0x00,0x03,0xC4,0x00,0x00,0x00,0x00,0x83,0x10,0x0B,0x84,0xEF,0x00,
+ 0x62,0x05,0x61,0x27,0x40,0x09,0x48,0x0A,0x62,0x81,0x40,0x0B,0x62,0x20,0x40,0x0B,
+ 0x40,0x04,0x00,0x00,0x40,0x00,0x62,0x42,0x40,0x21,0x50,0x03,0x48,0x0B,0x00,0x08,
+ 0x58,0x07,0x51,0x05,0x40,0x00,0x41,0x03,0x41,0x07,0x44,0x0B,0x80,0xB0,0x00,0x00,
+ 0x01,0x00,0x03,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x9F,0x00,0x00,0x00,
+ 0x00,0x03,0x40,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x40,0x01,0x40,0x00,0x40,0x01,
+ 0x00,0x00,0x40,0x01,0x00,0x02,0x00,0x01,0x40,0x00,0x40,0x00,0x40,0x03,0x40,0x01,
+ 0x40,0x01,0x00,0x03,0x00,0x03,0x00,0x00,0x40,0x03,0x00,0xDC,0x0A,0x41,0x40,0x40,
+ 0x03,0x52,0x11,0x50,0x00,0x41,0x25,0x50,0x80,0x40,0x0B,0x54,0x10,0x40,0x01,0x02,
+ 0x00,0x40,0x09,0x42,0x44,0x60,0x29,0x40,0x09,0x61,0x00,0x41,0x13,0x40,0x41,0x40,
+ 0x83,0x40,0x00,0x60,0x00,0x60,0x03,0x52,0x10,0xC0,0xD5,0x22,0x20,0x20,0x20,0x03,
+ 0x40,0x08,0x00,0x03,0x00,0x00,0x00,0x02,0x54,0x08,0x54,0x06,0x52,0x0A,0x00,0x00,
+ 0x52,0x8A,0x00,0x2B,0x10,0x10,0x40,0x0A,0x40,0x0A,0x40,0x23,0x50,0x2A,0x40,0x03,
+ 0x08,0x80,0x00,0x43,0x00,0x87,0x40,0x00,0xC0,0xDB,0x02,0x00,0x02,0x00,0x03,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x00,0x00,
+ 0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x01,0x40,0x01,0x00,
+ 0x03,0x40,0x00,0x40,0x00,0x40,0x02,0x00,0xA8,0x02,0x40,0x02,0x40,0x03,0xC0,0x03,
+ 0xC0,0x03,0xC0,0x03,0x40,0x02,0x40,0x00,0x40,0x02,0x00,0x02,0x80,0x00,0x00,0x02,
+ 0x40,0x00,0xC0,0x00,0x40,0x02,0x40,0x02,0xC0,0x00,0x40,0x00,0x40,0x03,0x00,0x03,
+ 0x40,0x03,0xC0,0x03,0x40,0x03,0xC0,0xFA,0x08,0xC2,0x07,0x01,0x89,0x40,0x03,0x44,
+ 0x07,0x42,0x4B,0x00,0x05,0x08,0x40,0x00,0x13,0xC0,0x12,0x40,0x00,0x00,0x12,0xE0,
+ 0x21,0x40,0x17,0x10,0x10,0x00,0x11,0x40,0x00,0x00,0x10,0xD0,0x08,0xE1,0x00,0x10,
+ 0x00,0x60,0x11,0x10,0x26,0xC0,0xA2,0x40,0x60,0x21,0x60,0x07,0x42,0x89,0x60,0x03,
+ 0x44,0x03,0x52,0x23,0x40,0x02,0x62,0x04,0x40,0x08,0x00,0x00,0x40,0x04,0x62,0x2B,
+ 0x40,0x80,0x50,0x03,0x48,0x03,0x64,0x43,0x60,0x02,0x54,0x09,0x40,0x01,0x61,0x09,
+ 0x44,0x03,0x61,0x00,0x00,0xBE,0x00,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x03,0x00,
+ 0x03,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,
+ 0x01,0x00,0x03,0x00,0x9D,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x40,0x01,
+ 0x00,0x02,0x40,0x02,0x00,0x01,0x40,0x01,0x00,0x00,0x40,0x01,0x00,0x02,0x00,0x00,
+ 0x40,0x00,0x40,0x00,0x40,0x03,0x40,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x03,
+ 0x00,0x00,0x00,0xAD,0x02,0x40,0x28,0x40,0x03,0x52,0x10,0x40,0x04,0x62,0x19,0x40,
+ 0x8B,0x50,0x18,0x40,0x20,0x40,0x21,0x00,0x00,0x40,0x41,0x40,0x23,0x50,0x84,0x40,
+ 0x09,0x61,0x08,0x41,0x1B,0x40,0x00,0x40,0x10,0x40,0x00,0x40,0x40,0x60,0x24,0x40,
+ 0x87,0x40,0xCD,0x22,0x20,0x00,0x21,0x43,0x00,0x00,0x00,0x03,0x40,0x80,0x00,0x07,
+ 0x54,0x00,0x21,0x00,0x52,0x02,0x00,0x00,0x52,0x22,0x10,0x43,0x00,0x12,0x40,0x02,
+ 0x40,0x02,0x54,0x20,0x50,0x22,0x00,0x00,0x04,0x42,0x00,0x45,0x00,0x88,0x00,0x07,
+ 0xC0,0xBD,0x00,0x00,0x02,0x00,0x03,0x00,0x02,0x40,0x03,0x00,0x00,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x03,0x40,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x02,0x00,0x01,0x00,0x03,0x00,0x02,0x40,0x01,0x00,0x03,0x00,0x03,0x00,
+ 0xFA,0x02,0x40,0x02,0xC0,0x02,0x40,0x02,0x40,0x03,0x40,0x01,0xC0,0x03,0x40,0x01,
+ 0x40,0x00,0x00,0x02,0x80,0x00,0x00,0x02,0x40,0x03,0x40,0x00,0x40,0x02,0x40,0x02,
+ 0xC0,0x01,0x00,0x02,0x40,0x03,0x80,0x02,0x40,0x00,0x40,0x00,0x40,0x03,0x40,0xAF,
+ 0x02,0x00,0x07,0x41,0x8B,0x20,0x07,0xC1,0x03,0x00,0x86,0x50,0x21,0xC0,0x08,0x04,
+ 0x88,0x00,0x1A,0x40,0x00,0x00,0x1A,0x00,0x47,0x20,0x04,0x11,0x18,0x00,0x19,0x40,
+ 0x86,0xC0,0x19,0x10,0x0B,0x64,0x8A,0x20,0x40,0x20,0x23,0x10,0x41,0xC0,0xB3,0x00,
+ 0x00,0x20,0x60,0x04,0x48,0x25,0x60,0x07,0x48,0x0B,0x48,0x40,0x40,0x0A,0x00,0x00,
+ 0x40,0x08,0x00,0x00,0x40,0x00,0x62,0x27,0x50,0x18,0x40,0x01,0x68,0x00,0x48,0x03,
+ 0x40,0x00,0x51,0x02,0x48,0x23,0x40,0x01,0x44,0x88,0x60,0x00,0xC0,0x8D,0x00,0x00,
+ 0x00,0x00,0x02,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x02,0x00,0x02,0x00,0x03,0x00,0x03,0x00,0x9C,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x03,0x00,0x03,0x40,0x02,0x40,0x03,0x40,0x02,0x00,0x00,0x40,0x03,
+ 0x00,0x00,0x40,0x03,0x00,0x01,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x01,0x00,0x01,
+ 0x40,0x02,0x40,0x02,0x00,0x00,0x00,0x03,0x40,0x00,0x00,0xCC,0x02,0x00,0x00,0x40,
+ 0x00,0x52,0x01,0x44,0x03,0x51,0x12,0x50,0x03,0x60,0x00,0x01,0x00,0x40,0x80,0x00,
+ 0x00,0x40,0x48,0x40,0x01,0x42,0x00,0x52,0x48,0x40,0x08,0x54,0x85,0x40,0x01,0x40,
+ 0x07,0x51,0x16,0x50,0x08,0x62,0x23,0x40,0x8B,0xC0,0x9D,0x02,0x00,0x00,0x21,0x00,
+ 0x68,0x84,0x00,0x00,0x40,0x00,0x40,0x00,0x54,0x00,0x00,0x00,0x48,0x00,0x00,0x00,
+ 0x48,0x20,0x10,0x03,0x00,0x03,0x48,0x00,0x48,0x03,0x52,0x08,0x00,0x22,0x40,0x2B,
+ 0x50,0x04,0x02,0x25,0x10,0x83,0x40,0x07,0xD4,0xA0,0x00,0x00,0x00,0x40,0x00,0x00,
+ 0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x03,0x00,0x01,0x00,0x03,0x00,0x03,0x40,0x02,0x40,0x00,0x00,0x01,0x40,0x02,0x00,
+ 0x00,0x40,0x01,0x00,0x03,0x40,0x03,0x40,0xD9,0x02,0x00,0x00,0x40,0x00,0x40,0x00,
+ 0x40,0x03,0x40,0x02,0x00,0x03,0xC0,0x01,0x80,0x00,0x00,0x02,0x00,0x00,0x00,0x02,
+ 0x40,0x03,0xC0,0x00,0x40,0x00,0x40,0x03,0x40,0x00,0x00,0x01,0x40,0x03,0x40,0x00,
+ 0x40,0x00,0x40,0x00,0x40,0x03,0xC0,0xCE,0x02,0xC0,0x00,0x00,0x8A,0x00,0x00,0x11,
+ 0x03,0x00,0x85,0x00,0x03,0x40,0x08,0x44,0x00,0x10,0x06,0x01,0x00,0x10,0x06,0x01,
+ 0x45,0x40,0x00,0x10,0x0B,0x21,0x0B,0x02,0x43,0x00,0x26,0xD0,0x80,0x00,0x41,0x10,
+ 0x00,0x04,0x03,0x10,0x41,0x40,0x83,0x80,0x50,0x07,0x40,0x48,0x50,0x01,0x48,0x02,
+ 0x64,0x00,0x40,0x80,0x40,0x06,0x44,0x03,0x40,0x00,0x00,0x00,0x40,0x00,0x58,0x23,
+ 0x40,0x03,0x62,0x03,0x48,0x05,0x40,0x02,0x40,0x00,0x48,0x03,0x58,0x07,0x41,0x49,
+ 0x40,0x08,0x48,0x03,0x00,0xAB,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x02,0x00,
+ 0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0x03,0x00,0x01,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x02,0x00,
+ 0x03,0x00,0x03,0x00,0x9E,0x00,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x40,0x03,0x40,0x02,0x00,0x02,0x40,0x03,0x00,0x00,0x40,0x03,0x40,0x02,0x00,0x03,
+ 0x40,0x00,0x00,0x03,0x00,0x03,0x00,0x01,0x00,0x02,0x40,0x02,0x00,0x00,0x00,0x01,
+ 0x00,0x02,0x00,0xFC,0x02,0x40,0x80,0x40,0x02,0x44,0x24,0x50,0x04,0x41,0x48,0x40,
+ 0x00,0x60,0x80,0x60,0x16,0x40,0x44,0x00,0x00,0x40,0x08,0x44,0x27,0x50,0x0B,0x42,
+ 0x09,0x51,0x23,0x40,0x87,0x40,0x01,0x50,0x0B,0x44,0x12,0x50,0x00,0x61,0x83,0x50,
+ 0x0B,0x44,0xE5,0x22,0x20,0x00,0x00,0x49,0x00,0x00,0x00,0x03,0x52,0x08,0x58,0x00,
+ 0x54,0x00,0x28,0x00,0x58,0x00,0x00,0x00,0x58,0x20,0x40,0x04,0x24,0x13,0x40,0x02,
+ 0x08,0x00,0x00,0x03,0x00,0x2A,0x00,0x20,0x50,0x84,0x10,0x25,0x10,0x8B,0x00,0x04,
+ 0xC0,0x86,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x03,0x00,0x01,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x40,0x02,0x40,0x01,0x00,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x01,0x00,0x02,0x00,0x00,0x40,0x01,0x00,0x03,0x00,0x02,0x00,
+ 0x8D,0x02,0x40,0x02,0x40,0x00,0x40,0x02,0xC0,0x03,0x40,0x01,0x00,0x03,0xC0,0x01,
+ 0x40,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x40,0x00,0x40,0x02,0x40,0x02,0x40,0x00,
+ 0xC0,0x01,0x00,0x01,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x03,0x40,0x00,0xC0,0xC1,
+ 0x02,0x00,0x05,0xC1,0x80,0x20,0x07,0x41,0x07,0xC2,0x03,0x04,0x00,0x40,0x08,0x04,
+ 0x89,0x00,0x06,0xC1,0x00,0x00,0x06,0x11,0x03,0x01,0x25,0x10,0x04,0x21,0x45,0x40,
+ 0x46,0x00,0x12,0x10,0x8B,0x00,0x41,0x00,0x80,0x00,0x20,0x10,0x03,0xC2,0xEB,0x20,
+ 0x40,0x23,0x60,0x08,0x68,0x03,0x48,0x06,0x68,0x00,0x40,0x00,0x68,0x00,0x62,0x01,
+ 0x40,0x00,0x00,0x00,0x40,0x84,0x50,0x00,0x44,0x03,0x68,0x05,0x40,0x02,0x52,0x04,
+ 0x40,0x00,0x68,0x03,0x68,0x03,0x64,0x05,0x54,0x4B,0x40,0x07,0x40,0xDD,0x00,0x00,
+ 0x01,0x00,0x01,0x00,0x03,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x02,0x00,0x02,0x00,0x03,0x00,0x03,0x00,0x9C,0x00,0x00,0x02,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x40,0x03,0x40,0x01,0x00,0x01,0x40,0x03,
+ 0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x03,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x01,
+ 0x40,0x02,0x40,0x02,0x00,0x00,0x00,0x03,0x40,0x00,0x00,0xEB,0x02,0x50,0x08,0x44,
+ 0x00,0x41,0x0B,0x52,0x00,0x48,0x0A,0x42,0x00,0x40,0x0B,0x44,0x07,0x41,0x84,0x00,
+ 0x00,0x40,0x00,0x44,0x07,0x61,0x27,0x40,0x03,0x41,0x04,0x42,0x02,0x44,0x01,0x40,
+ 0x0B,0x44,0x26,0x40,0x00,0x41,0x23,0x60,0x43,0x40,0x8B,0x22,0x20,0x00,0x21,0x27,
+ 0x40,0x00,0x00,0x03,0x64,0x08,0x68,0x00,0x54,0x00,0x21,0x07,0x68,0x00,0x00,0x00,
+ 0x68,0x20,0x00,0x23,0x00,0x11,0x40,0x00,0x00,0x04,0x54,0x03,0x00,0x26,0x40,0x20,
+ 0x50,0x04,0x22,0x01,0x04,0x8B,0x40,0x03,0xC2,0x82,0x00,0x00,0x00,0x40,0x03,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x40,0x00,0x40,0x03,0x00,0x01,0x40,0x02,0x00,
+ 0x00,0x40,0x01,0x40,0x01,0x40,0x03,0x40,0xCE,0x02,0x40,0x02,0xC0,0x03,0x40,0x00,
+ 0xC0,0x03,0x40,0x02,0x00,0x03,0x40,0x00,0xC0,0x03,0x00,0x02,0x80,0x00,0x00,0x02,
+ 0x40,0x03,0x40,0x01,0x40,0x00,0x40,0x01,0x40,0x03,0x00,0x01,0xC0,0x00,0x40,0x00,
+ 0x40,0x00,0x40,0x03,0x40,0x03,0x40,0xF3,0x02,0xC0,0x05,0x41,0x03,0xD2,0x03,0x40,
+ 0x07,0x02,0x00,0x04,0x00,0x00,0x44,0x40,0x23,0x00,0x06,0x41,0x00,0x00,0x06,0x11,
+ 0x19,0x10,0x87,0x10,0x09,0xC1,0x42,0xC0,0x87,0x00,0x12,0x50,0x47,0x00,0x41,0x00,
+ 0x08,0xE4,0x80,0xD0,0x03,0xD0,0xD2,0x02,0x00,0x20,0x60,0x07,0x68,0x09,0x41,0x0B,
+ 0x48,0x0A,0x40,0x40,0x40,0x02,0x62,0x04,0x40,0x08,0x00,0x00,0x40,0x84,0x40,0x08,
+ 0x40,0x0A,0x51,0x23,0x40,0x00,0x68,0x02,0x40,0x00,0x51,0x0A,0x48,0x2B,0x50,0x01,
+ 0x44,0x03,0x68,0x01,0x00,0xC9,0x00,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x03,0x00,
+ 0x03,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x8C,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x40,0x02,0x40,0x02,
+ 0x40,0x03,0x40,0x02,0x00,0x03,0x40,0x03,0x00,0x00,0x40,0x03,0x00,0x03,0x00,0x00,
+ 0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x40,0x02,0x00,0x00,0x00,0x03,
+ 0x00,0x03,0x00,0x98,0x02,0x00,0x00,0x40,0x03,0x42,0x41,0x50,0x22,0x60,0x82,0x40,
+ 0x03,0x50,0x88,0x40,0x23,0x40,0x00,0x04,0x00,0x40,0x23,0x60,0x23,0x40,0x00,0x42,
+ 0x09,0x51,0x88,0x40,0x86,0x40,0x01,0x40,0x03,0x64,0x12,0x40,0x49,0x60,0x07,0x42,
+ 0x47,0x40,0xC8,0x02,0x00,0x00,0x21,0x48,0x00,0x00,0x40,0x49,0x60,0x08,0x40,0x03,
+ 0x54,0x00,0x21,0x02,0x48,0x00,0x00,0x00,0x40,0x22,0x10,0x03,0x00,0x10,0x40,0x0A,
+ 0x12,0x01,0x14,0x00,0x00,0x22,0x00,0x27,0x50,0x04,0x02,0x21,0x10,0x80,0x00,0x08,
+ 0x40,0xB4,0x02,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0xBE,0x02,0x80,0x00,0xC0,0x00,0xC0,0x00,0x40,0x00,0x40,0x02,0x80,0x00,0x40,0x01,
+ 0x40,0x01,0x00,0x02,0x80,0x00,0x00,0x01,0x40,0x00,0x40,0x01,0x40,0x02,0x40,0x01,
+ 0xC0,0x01,0x00,0x01,0x40,0x03,0x40,0x00,0x40,0x00,0x40,0x02,0x40,0x00,0x40,0x82,
+ 0x02,0x40,0x00,0x40,0x20,0x60,0x04,0x01,0x00,0x04,0x00,0x41,0x00,0x00,0x08,0x04,
+ 0x8B,0x20,0x06,0x41,0x00,0x00,0x06,0x01,0x44,0x00,0x86,0xD0,0x00,0x04,0x27,0x40,
+ 0x46,0x00,0x16,0x10,0x00,0x01,0x41,0x20,0x06,0x02,0x17,0xD0,0x21,0x40,0x9F,0x00,
+ 0x00,0x00,0x00,0x00,0x44,0x03,0x48,0x0A,0x48,0x27,0x50,0x07,0x44,0x00,0x62,0x08,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x41,0x40,0x09,0x44,0x05,0x44,0x07,0x00,0x00,
+ 0x44,0x04,0x44,0x03,0x44,0x03,0x00,0x00,0x68,0x0A,0x42,0x09,0x00,0x9E,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0xBE,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x40,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x03,0x40,0x00,0x40,0x00,0x00,0x00,0x40,0x03,
+ 0x40,0x00,0x40,0x02,0x00,0x00,0x40,0x02,0x40,0x00,0x00,0xFA,0x02,0x00,0x00,0x00,
+ 0x00,0x60,0x24,0x50,0x00,0x68,0x03,0x42,0x43,0x60,0x0B,0x44,0x00,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x60,0x4B,0x60,0x03,0x62,0x03,0x62,0x83,0x00,0x00,0x60,0x43,0x60,
+ 0x17,0x60,0x1A,0x00,0x00,0x40,0x00,0x54,0x00,0xC1,0x8E,0x02,0x00,0x00,0x00,0x00,
+ 0x61,0x04,0x00,0x03,0x28,0x00,0x00,0x03,0x54,0x00,0x21,0x25,0x00,0x00,0x00,0x20,
+ 0x00,0x28,0x40,0x20,0x10,0x13,0x40,0x00,0x48,0x00,0x00,0x20,0x50,0x20,0x40,0x20,
+ 0x50,0x04,0x00,0x00,0x44,0x00,0x44,0x00,0x40,0xE8,0x00,0x40,0x00,0x40,0x00,0x40,
+ 0x00,0x40,0x03,0x40,0x00,0x00,0x03,0x40,0x01,0x40,0x00,0x40,0x00,0x40,0x00,0x00,
+ 0x00,0x40,0x00,0x40,0x03,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,
+ 0x00,0x40,0x00,0x40,0x02,0x40,0x03,0x00,0xAC,0x02,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x80,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x80,0x00,
+ 0x80,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xEB,0x02,0x00,0x00,0xC0,0x00,0x00,0x00,0x44,
+ 0x07,0x02,0x03,0x00,0x08,0x04,0x08,0x02,0x20,0x50,0x48,0xC0,0x00,0x50,0x00,0x52,
+ 0x09,0x02,0x07,0x11,0x09,0x21,0x03,0x00,0x00,0x00,0x03,0x10,0x03,0x40,0x41,0x00,
+ 0x00,0x20,0x28,0x20,0x0B,0x41,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x84,0x00,0x00,0x00,0x00,0xE1,0x84,0x00,0x00,0xE1,0x84,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x20,0xD9,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
+ 0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x00,
+ 0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x02,0x42,0x00,0x02,0x00,0x00,0x02,0x82,
+ 0x00,0x02,0x00,0x20,0x90,0x00,0x80,0x02,0x00,0x00,0x02,0x00,0x02,0x20,0x00,0x10,
+ 0x00,0x00,0x10,0x00,0x01,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x04,0x24,0x00,0x00,
+ 0x00,0x20,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x80,0x10,0x00,0x00,0x20,0x40,0x00,
+ 0x20,0x00,0x80,0xAF,0x00,0x00,0x00,0x00,0x08,0x80,0x00,0x40,0x20,0x00,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x80,
+ 0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x10,
+ 0x00,0xA0,0xDC,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x02,0x00,0x04,0x00,0x00,0x00,
+ 0x42,0x84,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x22,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x40,0x00,0x01,0x00,0x01,0x80,
+ 0x00,0x89,0x08,0x84,0x00,0x10,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x80,
+ 0x00,0x00,0x20,0x00,0x20,0x10,0x40,0x40,0x20,0x01,0x00,0x00,0x10,0x00,0x00,0x00,
+ 0xA6,0x00,0x00,0x22,0x00,0x00,0x20,0x02,0x00,0x00,0x40,0x00,0x02,0x02,0x00,0x40,
+ 0x10,0x02,0x00,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,
+ 0x82,0x00,0x00,0x40,0x00,0x20,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xA9,
+ 0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x80,0x00,0x80,0x00,0x50,
+ 0x00,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x82,0x00,
+ 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x20,0x00,0xB1,0x00,
+ 0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x04,0x20,0x04,0x00,0x00,0x22,0x00,0x40,0x80,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x80,0xC3,0x00,0x00,
+ 0x00,0x00,0x04,0x00,0x00,0x04,0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x02,0x00,0x00,0x80,0xB0,0x00,0x00,0x00,
+ 0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x20,0x10,0xCD,0x00,0x10,0x00,
+ 0x01,0x00,0x00,0x00,0x10,0x42,0x01,0x00,0x80,0x00,0x40,0x00,0x01,0x00,0x00,0x48,
+ 0x00,0x00,0x00,0x0A,0x00,0x00,0x20,0x00,0x08,0x00,0x00,0x00,0x85,0x16,0x00,0x00,
+ 0x00,0x02,0x00,0x00,0x00,0x00,0x08,0x82,0x00,0x00,0x80,0xE4,0x00,0x10,0x00,0x00,
+ 0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x80,0x00,0x00,0x00,0x02,0x00,0x00,
+ 0x00,0x00,0x80,0x11,0x40,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x42,0x00,0x08,0x00,0x00,0xE7,0x00,0x10,0x04,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x10,0x08,0x20,0x00,0x00,0x00,0x00,0x00,0x08,0x02,0x40,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x08,0x48,0x00,0x00,0x04,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x28,0x00,0x04,0x00,0x00,0x00,0xA0,0xB0,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x40,0x08,0x00,0x60,0x04,0x10,0x00,0x00,0x00,0x00,0x10,
+ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,
+ 0x08,0x00,0x00,0x00,0x10,0x04,0x80,0x01,0xEE,0x20,0x00,0x80,0x81,0x42,0x00,0x00,
+ 0x00,0x00,0x08,0x00,0x00,0x00,0x84,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x12,
+ 0x00,0x00,0x00,0x10,0x81,0x00,0x00,0x00,0x80,0x00,0x08,0x00,0x00,0x04,0x00,0x00,
+ 0x00,0x00,0x20,0x40,0x00,0x00,0x00,0xF7,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x10,0x00,0x00,0x04,0x80,0x10,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x01,0x08,0x00,
+ 0x00,0x40,0x00,0x00,0x00,0x01,0x00,0x20,0x10,0x00,0x08,0x00,0x20,0x08,0x00,0x00,
+ 0x00,0x00,0x80,0x00,0x00,0x00,0x94,0x00,0x00,0x00,0x00,0x04,0x00,0x80,0x01,0x04,
+ 0x00,0x00,0x00,0x40,0x20,0x80,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x40,0x00,0x00,
+ 0x20,0x00,0x08,0x02,0x48,0xD0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x21,
+ 0x00,0x00,0x20,0x00,0xC4,0x00,0x00,0x00,0x00,0x04,0x10,0x00,0x80,0x10,0x02,0x00,
+ 0x00,0x00,0x00,0x20,0x00,0x00,0x10,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,
+ 0x20,0x01,0x00,0x80,0x8D,0x02,0x00,0x20,0x00,0x10,0x42,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x48,0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x00,0x08,0x00,0x00,
+ 0x00,0x08,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x08,0x30,0x00,0x00,0x80,0x02,0x08,
+ 0x00,0x00,0x80,0x98,0x00,0x00,0x48,0x00,0x30,0x00,0x40,0x00,0x00,0x00,0x00,0x00,
+ 0x04,0x00,0x00,0x00,0x80,0x00,0x20,0x00,0x00,0x00,0x04,0x01,0x00,0x20,0x88,0x00,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x20,0x80,0xB9,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x20,0x08,
+ 0x00,0x00,0x08,0x00,0x02,0x00,0x20,0x00,0x10,0x40,0x08,0x20,0x02,0x00,0x30,0x00,
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x00,0x02,0x04,0x01,0x00,0x00,0x00,
+ 0x00,0xEE,0xA0,0x00,0x00,0x00,0x00,0x04,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
+ 0x08,0x20,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,
+ 0x20,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x82,
+ 0x8C,0x00,0x00,0x00,0xA0,0x42,0x00,0x40,0x00,0x00,0x04,0x40,0x00,0x00,0x00,0x04,
+ 0x00,0xC0,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x40,0x08,0x02,0x00,0x28,0x00,
+ 0x80,0x00,0x00,0x00,0x10,0x80,0x80,0x00,0x00,0x08,0x00,0x00,0x40,0x00,0x80,0x9F,
+ 0x14,0x00,0x20,0x08,0x00,0xC0,0x00,0x40,0x00,0x40,0x08,0x02,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x20,0x00,0x08,0x10,0x00,0x08,0x00,0x08,0x00,0x00,0x08,0x40,
+ 0x00,0x80,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xF5,0x00,
+ 0x00,0x00,0x04,0x00,0x00,0x2A,0x06,0x00,0x10,0x00,0x00,0x08,0x20,0x02,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x44,0x00,0x02,0x02,0x00,0x00,0x00,0x20,0x00,0x00,0x04,0x80,0xAF,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xD0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x88,0x00,0x00,0x08,0x00,0x80,0x01,0x80,0x80,0x00,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x20,0x40,0x20,0x40,0x00,0x10,0x00,0x02,0x00,0x00,0xF1,0x80,0x10,0x80,
+ 0x00,0x00,0x00,0x20,0x80,0x00,0x00,0x02,0x20,0x10,0x00,0x20,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x18,
+ 0x00,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x80,0xA4,0x40,0x04,0x00,0x00,
+ 0x00,0x80,0x00,0x00,0x00,0x20,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x80,
+ 0x00,0x00,0x14,0x01,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x60,0x00,0x00,0x00,0x00,
+ 0x00,0x20,0x00,0x00,0x00,0x02,0x00,0xA0,0x00,0x20,0xD1,0x80,0x00,0x40,0x00,0x00,
+ 0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x40,0x10,0x00,0x00,0x00,0x40,0x00,0x40,0x00,
+ 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x10,0x00,
+ 0x00,0x00,0x00,0x04,0x00,0x04,0x40,0x00,0x80,0xCF,0x00,0x80,0x10,0xC0,0x00,0x00,
+ 0x04,0x08,0x00,0x00,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x89,0x00,0x00,0x80,0x10,0x10,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x10,0x00,0x00,0x00,0x00,0x40,0x80,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x02,
+ 0x00,0x00,0x44,0x80,0x04,0x00,0x00,0x00,0x00,0x08,0x52,0x00,0x08,0x0A,0x10,0x00,
+ 0x48,0x02,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x20,0x40,0x00,0x00,0x00,0x00,0x00,
+ 0x04,0x00,0x00,0x00,0x00,0x00,0x80,0xD1,0x00,0x02,0x00,0x02,0x08,0x02,0x00,0x00,
+ 0x00,0x12,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x40,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x80,0x40,0x00,
+ 0x10,0x40,0x00,0x00,0x00,0xC0,0x9B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0xDE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xDE,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x40,0xDC,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xC0,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x8F,0x02,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xA3,
+ 0x02,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x20,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xB9,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x42,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xAB,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x0A,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,
+ 0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x06,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x04,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xBA,0x02,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xFA,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xBA,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x43,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xC0,0xCD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x04,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0x9A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xDE,0x0A,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xC0,0x92,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x40,0x50,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0xE6,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xAF,0x02,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xAB,
+ 0x00,0x01,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x03,0x01,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xB0,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0x40,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x9A,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDE,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,
+ 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x9B,0x02,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x08,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC4,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xCB,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xAB,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x60,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x03,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xC9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x9E,0x0A,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x40,0xB1,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xC0,0x8C,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xAF,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xBA,
+ 0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xAD,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x40,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA9,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,
+ 0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xA8,0x02,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x9E,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xBA,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x43,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x40,0xDD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x08,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xDE,0x0A,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xC0,0xB1,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0xBA,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xBE,0x02,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0x00,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x90,
+ 0x04,0x01,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,
+ 0x00,0x00,0x00,0x20,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xAF,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xDA,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xFA,0x02,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xDA,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0x00,0xC0,0xF2,0x02,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x40,0x00,0xC0,0xF2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x03,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0x40,0x09,0x40,0xDA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x01,0x00,0x8F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x01,0x00,0x8F,0x0A,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,
+ 0x21,0x00,0xB6,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,
+ 0x40,0xB5,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,
+ 0xEB,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0xBE,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x10,0x43,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x02,0xE6,0x02,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x44,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x03,0x00,0xC9,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x9E,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xED,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,
+ 0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x03,0x40,0xF9,0x02,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x08,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xBA,0x02,0x40,0x00,0x40,0x00,0x40,
+ 0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,
+ 0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,
+ 0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x02,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x20,0x00,0x01,0x00,0x00,
+ 0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xC0,0xA6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x20,0xBC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x20,0xBA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0xD8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x9E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,
+ 0x00,0xD8,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x23,0xC0,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0xB0,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x00,0x08,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x97,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,
+ 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x80,0x9A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xBD,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0x97,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x02,0x80,0xB4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x9E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x9E,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0x92,0x84,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x20,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
+ 0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9F,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0xDC,0x08,
+ 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x40,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xB4,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x08,0x00,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCA,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x10,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAF,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0xC0,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF2,0x00,0x40,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xB8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x04,0x00,0x10,0x00,0x80,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0x00,0x00,0x00,0x42,0x41,0x60,0x8B,0x40,0x03,
+ 0x42,0x03,0x58,0x01,0x42,0x83,0x50,0x06,0x58,0x07,0x00,0x00,0x68,0x0B,0x00,0x00,
+ 0x42,0x03,0x00,0x00,0x48,0x03,0x00,0x00,0x68,0x03,0x42,0x03,0x61,0x03,0x00,0x00,
+ 0x48,0x03,0x00,0x00,0x40,0xA2,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,
+ 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x8E,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x40,0x00,
+ 0x40,0x01,0x40,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x40,0x02,0x00,0x00,0x40,0x02,0x40,0x00,0x40,0x00,0x00,0x00,0x40,0x02,
+ 0x00,0x00,0x00,0xFF,0x02,0x00,0x00,0x60,0x47,0x40,0x03,0x52,0x1B,0x60,0x24,0x40,
+ 0x0B,0x62,0x24,0x40,0x00,0x42,0x03,0x02,0x00,0x40,0x10,0x00,0x00,0x60,0x24,0x00,
+ 0x00,0x60,0x26,0x00,0x00,0x40,0x26,0x60,0x24,0x40,0x24,0x00,0x00,0x50,0x26,0x00,
+ 0x00,0x00,0xB0,0x02,0x00,0x00,0x02,0x04,0x18,0x02,0x02,0x0B,0x40,0x82,0x50,0x00,
+ 0x40,0x02,0x22,0x00,0x04,0x0B,0x00,0x00,0x08,0x00,0x00,0x00,0x40,0x06,0x00,0x00,
+ 0x40,0x00,0x00,0x00,0x40,0x00,0x40,0x02,0x40,0x02,0x00,0x00,0x40,0x00,0x00,0x00,
+ 0xC0,0xB5,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x01,0x00,
+ 0x01,0x40,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x40,
+ 0x8D,0x02,0x00,0x00,0x40,0x00,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x40,0x02,
+ 0x40,0x00,0x40,0x03,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x02,0x00,0x00,0x40,0x02,
+ 0x00,0x00,0x40,0x02,0x40,0x02,0x40,0x02,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0xCA,
+ 0x02,0x00,0x00,0x10,0x81,0x00,0x1B,0x10,0x83,0x00,0x05,0x02,0x25,0x00,0x05,0x08,
+ 0x04,0x24,0x83,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x04,0x00,0x00,0x05,0x02,
+ 0x00,0x00,0x05,0x02,0x29,0x00,0x15,0x00,0x00,0x00,0x05,0x02,0x00,0x80,0xD7,0x02,
+ 0x40,0x0B,0x44,0x20,0x60,0x83,0x40,0x28,0x20,0x03,0x00,0x00,0x42,0x03,0x42,0x00,
+ 0x00,0x00,0x62,0x23,0x40,0x00,0x00,0x00,0x44,0x03,0x00,0x00,0x42,0x03,0x00,0x00,
+ 0x42,0x03,0x42,0x03,0x12,0x21,0x20,0x03,0x61,0x03,0x00,0x00,0x80,0xA9,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0xAD,0x00,0x40,0x00,
+ 0x00,0x02,0x00,0x03,0x00,0x00,0x40,0x01,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,
+ 0x40,0x00,0x40,0x01,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0xBF,0x02,0x40,0x40,0x60,
+ 0x8B,0x40,0x0B,0x54,0x80,0x40,0x14,0x00,0x00,0x60,0x14,0x50,0x84,0x00,0x00,0x40,
+ 0x8B,0x50,0x06,0x02,0x00,0x60,0x25,0x00,0x00,0x60,0x14,0x00,0x00,0x60,0x14,0x60,
+ 0x14,0x40,0x15,0x40,0x14,0x40,0x14,0x00,0x00,0x40,0xC9,0x02,0x40,0x00,0x02,0x02,
+ 0x02,0x07,0x02,0x80,0x60,0x04,0x00,0x00,0x40,0x06,0x00,0x00,0x00,0x80,0x10,0x4B,
+ 0x10,0x00,0x00,0x20,0x00,0x02,0x00,0x00,0x40,0x0A,0x00,0x00,0x40,0x0A,0x40,0x02,
+ 0x40,0x00,0x44,0x00,0x40,0x02,0x00,0x00,0xC0,0x94,0x02,0x00,0x00,0x00,0x00,0x00,
+ 0x03,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,
+ 0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0xFC,0x02,0x40,0x03,0x40,0x00,0x40,0x00,
+ 0x40,0x03,0x40,0x03,0x00,0x00,0x40,0x02,0x40,0x03,0x00,0x00,0x40,0x03,0x40,0x00,
+ 0x00,0x00,0x40,0x03,0x00,0x00,0x40,0x02,0x00,0x00,0x40,0x02,0x40,0x02,0x40,0x03,
+ 0x40,0x01,0x40,0x02,0x00,0x00,0x40,0xC8,0x46,0xC0,0x03,0x20,0x18,0x20,0x82,0x10,
+ 0x00,0x00,0x23,0x00,0x00,0x00,0x41,0x00,0x03,0x00,0x00,0x00,0x13,0x00,0x24,0x00,
+ 0x00,0x10,0x09,0x04,0x00,0x00,0x81,0x00,0x00,0x00,0x11,0x00,0x05,0x08,0x07,0x24,
+ 0x0B,0x01,0x19,0x00,0x00,0xC0,0xB0,0x02,0x00,0x80,0x00,0x05,0x62,0x0A,0x40,0x24,
+ 0x20,0x07,0x48,0x01,0x42,0x07,0x42,0x02,0x58,0x07,0x00,0x00,0x54,0x05,0x00,0x00,
+ 0x42,0x07,0x00,0x00,0x58,0x07,0x00,0x00,0x21,0x05,0x42,0x07,0x61,0x27,0x10,0x0B,
+ 0x58,0x07,0x00,0x00,0xC0,0xA0,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,
+ 0x03,0x00,0x00,0x00,0x9C,0x00,0x00,0x00,0x40,0x00,0x00,0x02,0x00,0x01,0x40,0x01,
+ 0x40,0x01,0x40,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x40,0x02,0x00,0x00,0x40,0x01,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x02,
+ 0x00,0x00,0x00,0xCE,0x02,0x00,0x00,0x50,0x10,0x40,0x03,0x41,0x01,0x44,0x10,0x50,
+ 0x0B,0x62,0x10,0x50,0x04,0x48,0x01,0x02,0x00,0x40,0x00,0x01,0x00,0x60,0x10,0x00,
+ 0x00,0x40,0x12,0x00,0x00,0x40,0x10,0x60,0x10,0x40,0x10,0x40,0x43,0x40,0x12,0x00,
+ 0x00,0x00,0xA3,0x02,0x00,0x00,0x42,0x09,0x04,0x0B,0x00,0x8A,0x60,0x80,0x50,0x04,
+ 0x40,0x0A,0x00,0x00,0x04,0x0B,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x02,0x00,0x00,
+ 0x40,0x00,0x00,0x00,0x41,0x00,0x40,0x02,0x40,0x02,0x61,0x00,0x40,0x00,0x00,0x00,
+ 0xC0,0xD2,0x02,0x00,0x00,0x00,0x00,0x40,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
+ 0x01,0x40,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x40,
+ 0xBA,0x02,0x00,0x00,0x40,0x03,0x40,0x01,0x40,0x00,0x40,0x03,0x40,0x00,0x40,0x02,
+ 0x40,0x00,0x40,0x03,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x02,0x00,0x00,0x40,0x02,
+ 0x00,0x00,0x40,0x03,0x40,0x02,0x40,0x02,0x40,0x00,0x40,0x02,0x00,0x00,0x00,0x9F,
+ 0x06,0x04,0x00,0x10,0x11,0x20,0x42,0x00,0x20,0x00,0x0B,0x02,0x11,0x00,0x41,0x00,
+ 0x04,0x24,0x83,0x00,0x00,0x10,0x0B,0x02,0x00,0x00,0x05,0x02,0x00,0x00,0x05,0x02,
+ 0x00,0x10,0x0B,0x01,0x45,0x00,0x19,0x00,0x03,0x00,0x05,0x02,0x00,0x00,0x90,0x02,
+ 0x00,0x80,0x40,0x00,0x58,0x83,0x40,0x08,0x48,0x0B,0x68,0x0B,0x42,0x8B,0x60,0x09,
+ 0x64,0x8B,0x50,0x44,0x50,0x00,0x00,0x00,0x12,0x0B,0x00,0x00,0x21,0x09,0x00,0x40,
+ 0x00,0x0B,0x61,0x03,0x61,0x0B,0x04,0x0B,0x12,0x0B,0x00,0x00,0x80,0xD7,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0x03,0x00,0x01,0x00,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x8C,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x03,0x00,0x00,0x40,0x02,0x40,0x00,0x40,0x00,0x00,0x01,0x00,0x03,
+ 0x00,0x02,0x40,0x02,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x40,0x00,
+ 0x00,0x03,0x40,0x00,0x40,0x02,0x40,0x00,0x00,0x00,0x00,0xDB,0x00,0x00,0x00,0x50,
+ 0x24,0x40,0x1B,0x50,0x80,0x50,0x12,0x40,0x12,0x60,0x10,0x40,0x01,0x41,0x83,0x40,
+ 0x02,0x44,0x05,0x02,0x00,0x40,0x10,0x00,0x00,0x40,0x10,0x00,0x00,0x50,0x10,0x40,
+ 0x8B,0x40,0x10,0x60,0x10,0x40,0x10,0x00,0x00,0x40,0xE3,0x02,0x00,0x00,0x02,0x01,
+ 0x00,0x03,0x02,0x00,0x40,0x84,0x50,0x00,0x40,0x02,0x00,0x22,0x10,0x06,0x22,0x40,
+ 0x60,0x0A,0x00,0x00,0x41,0x00,0x00,0x20,0x60,0x00,0x00,0x00,0x41,0x00,0x28,0x02,
+ 0x44,0x20,0x40,0x24,0x60,0x00,0x00,0x00,0x40,0xFE,0x02,0x00,0x00,0x00,0x01,0x00,
+ 0x03,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x02,0x00,
+ 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x40,0x03,0x40,0x00,
+ 0x40,0x00,0x40,0x02,0x40,0x00,0x40,0x02,0x40,0x03,0x40,0x03,0x40,0x00,0x40,0x00,
+ 0x00,0x00,0x40,0x01,0x00,0x00,0x40,0x03,0x00,0x00,0x40,0x03,0x40,0x02,0x40,0x00,
+ 0x40,0x03,0x40,0x03,0x80,0x00,0xC0,0xB3,0x00,0x00,0x00,0x10,0x1B,0x00,0x00,0xD0,
+ 0x00,0x00,0x01,0xC1,0x0B,0x02,0x45,0x00,0x87,0x00,0x03,0x02,0x08,0x04,0x10,0x00,
+ 0x00,0x10,0x0B,0x01,0x00,0x00,0x0B,0x01,0x00,0x10,0x09,0x01,0x27,0x20,0x03,0x10,
+ 0x01,0x02,0x09,0x41,0x00,0xC0,0xBB,0x02,0x48,0x00,0x04,0x00,0x41,0x0B,0x40,0x46,
+ 0x00,0x05,0x48,0x03,0x42,0x03,0x62,0x06,0x44,0x88,0x50,0x00,0x41,0x03,0x00,0x80,
+ 0x00,0x03,0x00,0x00,0x44,0x03,0x00,0x00,0x48,0x03,0x58,0x09,0x02,0x01,0x61,0x83,
+ 0x20,0x03,0x00,0x00,0x80,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x02,0x00,
+ 0x03,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,
+ 0x03,0x00,0x00,0x00,0xAC,0x00,0x40,0x00,0x40,0x01,0x40,0x02,0x00,0x00,0x40,0x03,
+ 0x40,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x01,0x00,0x03,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0x03,0x00,0x00,0x40,0x02,0x00,0x01,0x40,0x01,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0xD9,0x00,0x50,0x17,0x60,0x88,0x60,0x02,0x44,0x00,0x64,0x23,0x60,
+ 0x1A,0x60,0x18,0x40,0x00,0x62,0x10,0x40,0x88,0x50,0x00,0x00,0x00,0x50,0x18,0x00,
+ 0x00,0x60,0x25,0x00,0x00,0x60,0x1A,0x40,0x10,0x50,0x18,0x40,0x84,0x40,0x18,0x00,
+ 0x00,0x40,0x87,0x22,0x50,0x02,0x42,0x41,0x60,0x01,0x00,0x08,0x41,0x84,0x50,0x00,
+ 0x40,0x82,0x10,0x80,0x40,0x02,0x22,0x08,0x02,0x00,0x00,0x00,0x41,0x00,0x00,0x20,
+ 0x00,0x06,0x00,0x00,0x40,0x00,0x14,0x04,0x41,0x00,0x00,0x26,0x60,0x00,0x00,0x00,
+ 0x40,0xB0,0x02,0x00,0x01,0x00,0x03,0x40,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x40,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x40,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
+ 0xF9,0x00,0x40,0x00,0x40,0x00,0x40,0x03,0x40,0x01,0x40,0x00,0x40,0x00,0x40,0x02,
+ 0x40,0x00,0x40,0x02,0x40,0x00,0x40,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x40,0x03,
+ 0x00,0x00,0x40,0x02,0x40,0x00,0x40,0x03,0x40,0x02,0x40,0x03,0x00,0x00,0x40,0xDB,
+ 0x00,0x00,0x18,0x20,0x18,0x00,0x46,0x00,0x22,0x10,0x81,0x00,0x0B,0x02,0x05,0x04,
+ 0x04,0x24,0x19,0x00,0x10,0x10,0x00,0x00,0x00,0x10,0x0B,0x01,0x00,0x10,0x01,0x01,
+ 0x00,0x00,0x05,0x02,0x01,0xD2,0x07,0x04,0x41,0x00,0x09,0x01,0x00,0xC0,0xA8,0x40,
+ 0x60,0x08,0x08,0x43,0x60,0x81,0x40,0x03,0x08,0x87,0x40,0x01,0x58,0x03,0x42,0x03,
+ 0x44,0x04,0x00,0x00,0x48,0x03,0x00,0x00,0x08,0x07,0x00,0x00,0x44,0x03,0x00,0x00,
+ 0x44,0x03,0x42,0x03,0x00,0x00,0x08,0x07,0x08,0x07,0x48,0x07,0x00,0x9A,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0x9E,0x00,0x00,0x00,
+ 0x40,0x03,0x00,0x01,0x00,0x03,0x40,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
+ 0x40,0x00,0x00,0x00,0x40,0x03,0x40,0x01,0x40,0x03,0x00,0xAE,0x02,0x40,0x80,0x50,
+ 0x89,0x40,0x25,0x50,0x1B,0x50,0x83,0x60,0x02,0x40,0x17,0x50,0x84,0x60,0x00,0x02,
+ 0x00,0x50,0x07,0x02,0x00,0x50,0x22,0x00,0x00,0x50,0x15,0x00,0x00,0x60,0x25,0x60,
+ 0x88,0x00,0x00,0x50,0x02,0x52,0x23,0x50,0x80,0x40,0xD2,0x22,0x10,0x01,0x48,0x46,
+ 0x00,0x02,0x02,0x1B,0x50,0x00,0x00,0x47,0x00,0x01,0x00,0x00,0x00,0x0A,0x00,0x20,
+ 0x60,0x03,0x00,0x00,0x41,0x00,0x00,0x20,0x00,0x07,0x00,0x00,0x04,0x04,0x40,0x0A,
+ 0x00,0x00,0x44,0x20,0x60,0x00,0x52,0x08,0xC0,0xF5,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x01,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x00,0x40,0x01,0x00,0x00,0x40,
+ 0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x40,0x03,0x00,0x01,0x00,
+ 0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0xA8,0x02,0x40,0x01,0x40,0x00,0x40,0x03,
+ 0x40,0x03,0xC0,0x00,0x00,0x03,0x40,0x01,0x40,0x00,0x40,0x00,0x00,0x00,0x40,0x03,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x03,0x00,0x00,0x40,0x01,0x40,0x02,0x00,0x00,
+ 0x40,0x00,0x40,0x00,0x40,0x01,0xC0,0x8E,0x02,0x00,0x08,0xE1,0x00,0x14,0x47,0x10,
+ 0x83,0x40,0x09,0x01,0x13,0x20,0x0B,0x04,0x00,0x00,0x80,0x00,0x00,0xC0,0x03,0x00,
+ 0x00,0x10,0x28,0x00,0x00,0x10,0x13,0x00,0x00,0x10,0x03,0x08,0x21,0x00,0x00,0x20,
+ 0x08,0x01,0x08,0x01,0x00,0x44,0xDF,0x02,0x00,0x0B,0x00,0x40,0x60,0x87,0x40,0x08,
+ 0x01,0x03,0x40,0x01,0x58,0x87,0x50,0x07,0x64,0x03,0x00,0x20,0x50,0x05,0x00,0x00,
+ 0x68,0x07,0x00,0x00,0x18,0x07,0x00,0x00,0x64,0x03,0x61,0x03,0x44,0x27,0x50,0x0B,
+ 0x18,0x03,0x44,0x0B,0x40,0xA8,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x02,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x03,0x00,
+ 0x03,0x00,0x03,0x00,0x9F,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,
+ 0x00,0x03,0x40,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,
+ 0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x40,0x01,
+ 0x40,0x00,0x00,0xA8,0x00,0x40,0x40,0x00,0x00,0x40,0x00,0x54,0x83,0x50,0x04,0x42,
+ 0x03,0x40,0x20,0x40,0x03,0x42,0x00,0x00,0x00,0x40,0x43,0x00,0x00,0x40,0x11,0x00,
+ 0x00,0x40,0x43,0x00,0x00,0x40,0x17,0x40,0x15,0x50,0x13,0x40,0x43,0x40,0x8B,0x50,
+ 0x03,0xC8,0x92,0x02,0x40,0x00,0x00,0x00,0x00,0x03,0x02,0x80,0x60,0x88,0x00,0x03,
+ 0x42,0x00,0x22,0x23,0x10,0x00,0x00,0x20,0x20,0x03,0x00,0x20,0x00,0x02,0x00,0x20,
+ 0x60,0x00,0x00,0x00,0x04,0x07,0x28,0x27,0x20,0x0A,0x21,0x20,0x60,0x00,0x52,0x0A,
+ 0xC8,0xC8,0x02,0x00,0x00,0x00,0x00,0x40,0x03,0x40,0x00,0x00,0x00,0x00,0x02,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x40,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x40,
+ 0xCF,0x00,0x40,0x03,0x00,0x00,0x40,0x03,0x40,0x00,0x40,0x03,0x00,0x03,0x40,0x03,
+ 0xC0,0x02,0x40,0x00,0x00,0x00,0x40,0x03,0x00,0x00,0x40,0x03,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x40,0x03,0x40,0x03,0x40,0x02,0x40,0x00,0x40,0x00,0x40,0x02,0xC0,0x98,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x10,0x00,0x00,0x03,0x21,0x25,0x20,0x00,0x40,
+ 0x07,0x04,0x00,0x00,0x00,0x00,0x05,0x02,0x00,0x10,0x09,0x04,0x00,0x00,0x08,0x01,
+ 0x00,0x10,0x01,0x08,0x13,0x00,0x43,0x00,0x03,0xC0,0x08,0x01,0x03,0x64,0xB2,0x00,
+ 0x00,0x0B,0x42,0x43,0x60,0x00,0x40,0x04,0x28,0x09,0x40,0x01,0x44,0x87,0x50,0x07,
+ 0x44,0x08,0x00,0x00,0x68,0x03,0x00,0x00,0x68,0x07,0x00,0x40,0x00,0x0B,0x00,0x00,
+ 0x28,0x03,0x44,0x06,0x44,0x2B,0x50,0x0A,0x44,0x03,0x68,0x07,0x80,0xD8,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x03,0x00,0xAE,0x00,0x40,0x00,
+ 0x00,0x03,0x00,0x03,0x00,0x02,0x40,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x03,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x01,
+ 0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x40,0x03,0x00,0x89,0x02,0x40,0x40,0x60,
+ 0x46,0x40,0x07,0x42,0x02,0x44,0x03,0x41,0x03,0x50,0x13,0x40,0x03,0x62,0x00,0x02,
+ 0x00,0x40,0x07,0x02,0x00,0x40,0x00,0x01,0x00,0x50,0x80,0x00,0x00,0x40,0x07,0x61,
+ 0x43,0x50,0x11,0x40,0x42,0x60,0x25,0x40,0x81,0xC0,0xD4,0x02,0x40,0x00,0x02,0x05,
+ 0x00,0x01,0x00,0x29,0x60,0x84,0x00,0x4B,0x00,0x0A,0x22,0x83,0x00,0x00,0x00,0x80,
+ 0x50,0x03,0x00,0x00,0x48,0x00,0x00,0x20,0x60,0x00,0x00,0x00,0x41,0x80,0x50,0x23,
+ 0x20,0x03,0x21,0x24,0x00,0x46,0x40,0x0A,0xC0,0x99,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x02,0x00,0x00,0x00,0x02,0x40,0x00,0x00,0x03,0x40,0x02,0x00,0x00,0x40,
+ 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x40,0x03,0x00,
+ 0x03,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0xAD,0x02,0x40,0x03,0x40,0x03,0x40,0x00,
+ 0x40,0x00,0x40,0x00,0x00,0x03,0x40,0x02,0x40,0x03,0x40,0x01,0x00,0x00,0x40,0x03,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x03,0x00,0x00,0xC0,0x00,0x40,0x03,0x40,0x03,
+ 0x40,0x00,0x40,0x03,0x40,0x03,0xC0,0xFC,0x02,0x00,0x03,0x10,0x80,0x00,0x84,0x00,
+ 0x20,0x00,0x81,0x20,0x11,0x20,0x13,0x00,0x05,0x24,0x1A,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x10,0x00,0x00,0x00,0x00,0x09,0x01,0x00,0x50,0x08,0x01,0x04,0x02,0x27,0x00,
+ 0x12,0x10,0x01,0x21,0x00,0xC4,0xE3,0x02,0x00,0x0B,0x68,0x40,0x60,0x83,0x40,0x03,
+ 0x08,0x07,0x40,0x01,0x44,0x03,0x01,0x03,0x58,0x05,0x00,0x20,0x50,0x05,0x00,0x00,
+ 0x08,0x03,0x00,0x00,0x08,0x03,0x00,0x00,0x08,0x07,0x42,0x07,0x08,0x07,0x00,0x00,
+ 0x44,0x03,0x44,0x03,0xC0,0xF0,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x00,
+ 0x03,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x01,0x00,0x02,0x00,0x9D,0x00,0x40,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x40,0x02,
+ 0x00,0x01,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x40,0x03,
+ 0x00,0x00,0x40,0x01,0x00,0x00,0x40,0x01,0x00,0x03,0x40,0x01,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0xCD,0x00,0x40,0x40,0x40,0x8B,0x40,0x07,0x51,0x1B,0x60,0x83,0x40,
+ 0x01,0x50,0x19,0x50,0x05,0x41,0x03,0x02,0x00,0x40,0x43,0x00,0x00,0x60,0x06,0x01,
+ 0x00,0x60,0x07,0x01,0x00,0x60,0x43,0x60,0x40,0x60,0x83,0x00,0x00,0x50,0x15,0x50,
+ 0x06,0xC8,0xA0,0x02,0x40,0x00,0x02,0x02,0x18,0x02,0x02,0x1B,0x50,0x80,0x00,0x40,
+ 0x00,0x03,0x40,0x84,0x00,0x0B,0x00,0x80,0x10,0x03,0x00,0x00,0x41,0x00,0x00,0x20,
+ 0x60,0x00,0x00,0x00,0x41,0x00,0x28,0x01,0x41,0x00,0x00,0x20,0x00,0x47,0x40,0x08,
+ 0x68,0xD7,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x40,
+ 0xC8,0x00,0x40,0x03,0x40,0x00,0x40,0x02,0x40,0x01,0x40,0x00,0x00,0x00,0x40,0x03,
+ 0x40,0x01,0x40,0x03,0x00,0x00,0x40,0x03,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x40,0x00,0x40,0x03,0x40,0x00,0x00,0x00,0x40,0x03,0x40,0x00,0x40,0x99,
+ 0x00,0x00,0x03,0x10,0x18,0x00,0x1B,0x10,0x83,0x00,0x29,0x20,0x1A,0x20,0x27,0x00,
+ 0x12,0x20,0x80,0x00,0x00,0x00,0x05,0x02,0x00,0x10,0x08,0x01,0x00,0x00,0x08,0x01,
+ 0x00,0x10,0x08,0x01,0x87,0x10,0x04,0x04,0x00,0x10,0x13,0x20,0x03,0x44,0x84,0x02,
+ 0x40,0x06,0x42,0x01,0x51,0x03,0x68,0x0B,0x44,0x07,0x01,0x00,0x48,0x0B,0x04,0x01,
+ 0x42,0x03,0x00,0x00,0x42,0x07,0x00,0x00,0x44,0x07,0x00,0x00,0x44,0x03,0x00,0x00,
+ 0x44,0x03,0x68,0x00,0x04,0x01,0x61,0x03,0x44,0x23,0x40,0x0B,0x40,0x98,0x00,0x00,
+ 0x02,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x01,0x00,
+ 0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0xAD,0x00,0x00,0x00,
+ 0x00,0x03,0x00,0x01,0x00,0x03,0x40,0x01,0x00,0x00,0x00,0x01,0x40,0x03,0x40,0x00,
+ 0x00,0x00,0x00,0x03,0x00,0x00,0x40,0x01,0x00,0x00,0x40,0x01,0x00,0x00,0x40,0x01,
+ 0x00,0x00,0x40,0x03,0x00,0x00,0x40,0x01,0x00,0x03,0x00,0xFE,0x00,0x40,0x00,0x51,
+ 0x47,0x40,0x14,0x40,0x81,0x60,0x01,0x21,0x00,0x50,0x00,0x62,0x1B,0x50,0x88,0x00,
+ 0x00,0x60,0x12,0x00,0x00,0x60,0x01,0x01,0x00,0x60,0x05,0x02,0x00,0x60,0x05,0x42,
+ 0x00,0x60,0x8B,0x40,0x04,0x62,0x05,0x52,0x03,0x08,0xA6,0x00,0x00,0x00,0x01,0x85,
+ 0x00,0x88,0x00,0x03,0x41,0x02,0x00,0x00,0x28,0x08,0x41,0x04,0x40,0x00,0x00,0x00,
+ 0x22,0x01,0x00,0x00,0x42,0x02,0x00,0x00,0x42,0x0A,0x00,0x00,0x42,0x06,0x00,0x03,
+ 0x41,0x00,0x02,0x12,0x40,0x0A,0x00,0x00,0x00,0xF2,0x00,0x40,0x00,0x40,0x02,0x40,
+ 0x01,0x40,0x03,0x40,0x01,0x40,0x00,0x40,0x01,0x40,0x00,0x40,0x00,0x40,0x00,0x40,
+ 0x02,0x40,0x00,0x40,0x01,0x40,0x00,0x40,0x01,0x40,0x00,0x40,0x01,0x40,0x03,0x40,
+ 0x00,0x40,0x01,0x40,0x01,0x40,0x00,0x00,0xCC,0x00,0x00,0x01,0x00,0x03,0x00,0x00,
+ 0x00,0x03,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x02,
+ 0x00,0x02,0x00,0x00,0x00,0x03,0x00,0xA5,0x00,0x00,0x4A,0x20,0x83,0x20,0x21,0x10,
+ 0x0B,0x22,0x18,0x40,0x00,0x00,0x01,0x24,0x81,0x00,0x03,0x00,0x00,0x00,0x4B,0xC0,
+ 0x00,0xD0,0x84,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x10,0xC0,0x03,0x20,0x05,0x14,
+ 0x09,0x12,0x10,0x00,0x03,0x80,0x84,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,
+ 0x01,0x00,0x00,0x00,0x20,0xAE,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x00,0x00,0x30,
+ 0x00,0x01,0x00,0x70,0x00,0x40,0x02,0x01,0x00,0x80,0x00,0x30,0x00,0x00,0x00,0x30,
+ 0x00,0x40,0x00,0x30,0x00,0x00,0x00,0xB0,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x30,
+ 0x00,0x02,0x00,0x20,0x83,0x00,0x20,0x04,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,
+ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x20,0x00,0x00,0x10,0x00,0x00,0x00,
+ 0x00,0x00,0x80,0xD7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x02,0x00,0x04,0x00,
+ 0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x04,0x00,
+ 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x44,0x00,0x02,0x00,0x00,0x00,
+ 0x00,0x80,0x83,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0xDA,0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,
+ 0xA5,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x02,0x00,0x00,0x40,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x80,0xB0,
+ 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x10,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x80,0x9F,0x00,
+ 0x20,0x44,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x97,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x08,0x00,0x00,
+ 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD3,0x00,0x00,0x00,
+ 0x04,0x00,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x24,0x00,0x40,0x80,0x00,0x08,0x48,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x10,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0xB9,0x00,0x01,0x00,0x00,
+ 0x40,0x00,0x04,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x10,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x86,0x00,0x00,0x00,0x00,0xA0,
+ 0x01,0x00,0x50,0x02,0x00,0x00,0x00,0x04,0x00,0x80,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x02,
+ 0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x80,0xDA,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x02,0x00,0x10,0x00,0x10,0x00,0x00,0x00,
+ 0x00,0x00,0x08,0x00,0x40,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x20,
+ 0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x80,0xE1,0x20,0x10,0x00,0x00,0x20,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x08,0x02,0x20,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0x80,0xAE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x00,0x00,0x80,0xA3,0x02,0x00,0x00,0x12,0x00,0x00,0x14,0x00,0x00,
+ 0x20,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x00,0x0C,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
+ 0x00,0x00,0x10,0x00,0x80,0xD3,0x10,0x00,0x08,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
+ 0x20,0x20,0x00,0x00,0x00,0x00,0x20,0x00,0x80,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x20,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x80,0x8B,0x00,0x10,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x05,0x00,
+ 0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x10,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x08,
+ 0x00,0x00,0xA0,0x91,0x00,0x00,0x40,0x08,0x00,0x00,0x00,0x44,0x40,0x0C,0x82,0x09,
+ 0x00,0x04,0x00,0x08,0x10,0x20,0x00,0x00,0x08,0x00,0x00,0x04,0x00,0x24,0x20,0x01,
+ 0x00,0x24,0x00,0x04,0x00,0x24,0x00,0x04,0x00,0x09,0x00,0x20,0x44,0x01,0x00,0x14,
+ 0x00,0x00,0xE3,0x10,0x00,0x80,0x00,0x48,0x04,0x02,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,0x20,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x01,0x00,
+ 0x00,0xBF,0x10,0x00,0x00,0x24,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x20,0x00,0x04,0x04,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x50,0x00,0x00,0x00,
+ 0xF4,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x20,0x00,0x20,0x00,
+ 0x01,0x00,0x20,0x00,0x01,0x20,0xA0,0x80,0x00,0x00,0x20,0x00,0x01,0x00,0x00,0xB7,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0xAE,0x00,
+ 0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x00,0x08,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x80,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x40,
+ 0x00,0x40,0x00,0x00,0x20,0x90,0x60,0x08,0x00,0x08,0x20,0x00,0x10,0x00,0x42,0x00,
+ 0x00,0x40,0x40,0x80,0x20,0x00,0x00,0x20,0x00,0x00,0x00,0x08,0x04,0x00,0x40,0x08,
+ 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x80,0xDF,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x86,0x04,0x10,0x00,0x00,0x00,
+ 0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD3,0x00,0x00,0x00,0x00,0x00,0x04,
+ 0x00,0x20,0x00,0x82,0x00,0x02,0x02,0x20,0x10,0x21,0x40,0x00,0x00,0x00,0x00,0x08,
+ 0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x02,0x02,
+ 0x00,0x00,0x00,0x1A,0x00,0x00,0x00,0x80,0xA2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,
+ 0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x02,0x80,0x00,0x00,0x00,0x00,0x00,0x02,0x00,
+ 0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x52,0x00,0x80,0xC6,0x02,0x24,0x2B,0x40,0x20,0x60,0x09,0x61,0x05,
+ 0x44,0x03,0x00,0x00,0x64,0x4B,0x60,0x00,0x52,0x03,0x52,0x00,0x00,0x00,0x00,0x00,
+ 0x64,0x03,0x40,0x18,0x50,0x00,0x44,0x11,0x40,0x23,0x50,0x01,0x62,0x01,0x40,0x8B,
+ 0x50,0x00,0x42,0x03,0x40,0xBE,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,
+ 0x03,0x00,0x03,0x00,0xBE,0x00,0x40,0x03,0x00,0x02,0x40,0x01,0x40,0x01,0x40,0x03,
+ 0x00,0x00,0x00,0x03,0x00,0x01,0x40,0x03,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
+ 0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x01,0x00,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0xED,0x00,0x40,0x13,0x50,0x08,0x41,0x03,0x42,0x03,0x54,0x03,0x00,
+ 0x00,0x40,0x03,0x41,0x2B,0x40,0x47,0x40,0x18,0x00,0x00,0x00,0x00,0x40,0x4B,0x40,
+ 0x01,0x42,0x89,0x60,0x1B,0x50,0x44,0x40,0x48,0x40,0x04,0x44,0x21,0x40,0x14,0x60,
+ 0x18,0x80,0x9C,0x00,0x40,0x00,0x02,0x41,0x60,0x80,0x50,0x00,0x40,0x00,0x00,0x00,
+ 0x02,0x44,0x10,0x01,0x64,0x00,0x40,0x04,0x00,0x00,0x00,0x40,0x00,0x07,0x00,0x06,
+ 0x01,0x04,0x24,0x03,0x08,0x00,0x52,0x83,0x60,0x03,0x00,0x02,0x14,0x04,0x00,0x03,
+ 0x08,0xBA,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x40,0x01,0x40,
+ 0x00,0x00,0x03,0x40,0x03,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x03,0x00,
+ 0x9A,0x00,0xC0,0x03,0x40,0x02,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x40,0x03,
+ 0xC0,0x03,0x40,0x02,0x40,0x01,0x00,0x00,0x00,0x00,0x40,0x03,0x40,0x00,0x40,0x00,
+ 0x40,0x02,0x40,0x00,0x40,0x02,0x40,0x00,0x40,0x03,0x40,0x03,0x40,0x03,0x00,0x93,
+ 0x00,0x40,0x03,0x10,0x85,0x00,0x25,0xC0,0x25,0x00,0x00,0x00,0x00,0x20,0x81,0x40,
+ 0x08,0x02,0x25,0x00,0x02,0xC2,0x00,0x00,0x00,0x20,0x03,0x02,0x40,0x20,0x10,0x00,
+ 0x15,0x10,0x03,0x00,0x25,0x00,0x25,0x00,0x07,0x02,0x02,0xC2,0x03,0x10,0x91,0x02,
+ 0x68,0x00,0x42,0x23,0x50,0x09,0x58,0x05,0x48,0x08,0x00,0x40,0x60,0x03,0x41,0x23,
+ 0x60,0x07,0x48,0x04,0x00,0x00,0x00,0x00,0x64,0x10,0x40,0x48,0x60,0x08,0x52,0x13,
+ 0x50,0x03,0x61,0x03,0x62,0x43,0x40,0x03,0x40,0x03,0x44,0x03,0x80,0xF8,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0x01,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0xAC,0x00,0x40,0x02,
+ 0x00,0x01,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x01,
+ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x03,0x00,0x03,
+ 0x40,0x00,0x40,0x00,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0xCE,0x02,0x40,0x26,0x50,
+ 0x85,0x40,0x03,0x42,0x03,0x54,0x80,0x00,0x00,0x40,0x0B,0x61,0x2B,0x40,0x11,0x50,
+ 0x03,0x02,0x00,0x00,0x00,0x40,0x4A,0x50,0x10,0x40,0x00,0x44,0x17,0x40,0x2B,0x40,
+ 0x14,0x40,0x14,0x50,0x44,0x40,0x09,0x54,0x28,0x40,0xC7,0x02,0x40,0x08,0x11,0x42,
+ 0x60,0x80,0x50,0x00,0x21,0x00,0x00,0x20,0x10,0x49,0x10,0x01,0x00,0x00,0x52,0x00,
+ 0x00,0x00,0x00,0x40,0x00,0x04,0x01,0x00,0x11,0x89,0x60,0x10,0x00,0x07,0x40,0x41,
+ 0x60,0x46,0x00,0x04,0x00,0x06,0x04,0x00,0xC0,0xB4,0x02,0x40,0x00,0x00,0x01,0x00,
+ 0x01,0x00,0x01,0x40,0x01,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x02,0x00,
+ 0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0xDF,0x02,0x40,0x00,0x40,0x02,0x40,0x00,
+ 0x40,0x00,0x40,0x01,0x80,0x00,0x40,0x00,0x40,0x03,0xC0,0x01,0x40,0x00,0x80,0x00,
+ 0x00,0x00,0x40,0x02,0x40,0x01,0x40,0x00,0x40,0x01,0x40,0x03,0x40,0x01,0x40,0x02,
+ 0x40,0x00,0xC0,0x03,0x40,0x01,0xC0,0xC4,0x06,0x04,0x10,0x00,0x0B,0x01,0x15,0x00,
+ 0x15,0x00,0x07,0x42,0x00,0x00,0x02,0x04,0x0B,0x42,0x06,0x02,0x00,0x40,0x00,0x00,
+ 0x00,0x20,0x00,0xE2,0x04,0x01,0x40,0x00,0x86,0xD0,0x03,0x04,0x0A,0x01,0x43,0x20,
+ 0x01,0x44,0x83,0x20,0x26,0x40,0xBA,0x00,0x40,0x04,0x42,0x00,0x64,0x89,0x40,0x10,
+ 0x40,0x04,0x00,0x00,0x44,0x03,0x44,0x17,0x50,0x03,0x62,0x00,0x22,0x40,0x40,0x07,
+ 0x64,0x03,0x40,0x08,0x64,0x29,0x60,0x04,0x48,0x0B,0x42,0x03,0x62,0x07,0x44,0x00,
+ 0x58,0x84,0x40,0x09,0xC0,0xF7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x02,0x00,
+ 0x00,0x00,0x03,0x00,0xAC,0x00,0x00,0x02,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x01,0x40,0x00,0x40,0x03,0x00,0x03,0x00,0x03,
+ 0x00,0x02,0x40,0x01,0x40,0x00,0x40,0x02,0x00,0x03,0x40,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x01,0x00,0xC9,0x02,0x40,0x02,0x52,0x84,0x40,0x03,0x62,0x16,0x60,0x00,0x01,
+ 0x00,0x60,0x87,0x60,0x10,0x40,0x25,0x40,0x00,0x40,0x07,0x51,0x03,0x42,0x4B,0x40,
+ 0x22,0x40,0x80,0x40,0x01,0x51,0x02,0x51,0x14,0x40,0x10,0x60,0x26,0x40,0x02,0x54,
+ 0x03,0x48,0x91,0x02,0x00,0x09,0x00,0x43,0x60,0x04,0x04,0x20,0x00,0x00,0x00,0x00,
+ 0x02,0x2A,0x40,0x02,0x04,0x08,0x52,0x06,0x40,0x05,0x00,0x43,0x00,0x05,0x00,0x89,
+ 0x50,0x24,0x40,0x06,0x40,0x03,0x01,0x40,0x60,0x06,0x08,0x49,0x10,0x01,0x51,0x04,
+ 0xC1,0x95,0x00,0x00,0x02,0x00,0x03,0x00,0x01,0x40,0x02,0x40,0x00,0x00,0x00,0x40,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x03,0x00,0x02,0x00,
+ 0x01,0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x40,
+ 0xCA,0x02,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x01,0x00,0x00,0x40,0x02,
+ 0x40,0x02,0x40,0x00,0x00,0x01,0x40,0x00,0x40,0x00,0x40,0x03,0x40,0x00,0x40,0x03,
+ 0x40,0x00,0x40,0x03,0x40,0x02,0x40,0x02,0x40,0x01,0x40,0x01,0xC0,0x03,0xC0,0xE6,
+ 0x02,0xC0,0x40,0x00,0x00,0x00,0x11,0x10,0x24,0x20,0x08,0x04,0x00,0x20,0x03,0xD4,
+ 0x18,0x10,0x02,0x04,0x10,0x00,0x10,0x00,0x00,0x20,0x03,0x02,0x00,0x01,0x11,0x10,
+ 0x10,0x00,0x07,0x22,0x18,0x00,0x23,0x20,0x40,0x00,0x28,0x40,0x11,0x50,0x91,0x02,
+ 0x64,0x03,0x68,0x43,0x40,0x09,0x41,0x84,0x60,0x00,0x00,0x00,0x42,0x09,0x64,0x43,
+ 0x40,0x0B,0x40,0x00,0x44,0x4B,0x40,0x04,0x00,0x00,0x44,0x07,0x68,0x43,0x40,0x03,
+ 0x62,0x06,0x61,0x09,0x44,0x43,0x40,0x03,0x58,0x04,0x68,0x01,0x80,0xB7,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,
+ 0x02,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x8D,0x00,0x40,0x03,
+ 0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x02,0x40,0x03,
+ 0x00,0x01,0x40,0x03,0x00,0x00,0x00,0x00,0x40,0x03,0x40,0x03,0x40,0x03,0x00,0x03,
+ 0x40,0x01,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0xFA,0x02,0x40,0x07,0x42,
+ 0x24,0x60,0x03,0x62,0x80,0x40,0x04,0x01,0x00,0x60,0x01,0x41,0x26,0x50,0x10,0x40,
+ 0x01,0x50,0x01,0x52,0x00,0x02,0x00,0x60,0x03,0x42,0x84,0x60,0x0B,0x44,0x43,0x40,
+ 0x01,0x54,0x14,0x50,0x07,0x42,0x02,0x44,0x2B,0xC0,0x84,0x0A,0x40,0x00,0x11,0x46,
+ 0x60,0x88,0x20,0x42,0x00,0x04,0x00,0x00,0x00,0x04,0x40,0x00,0x68,0x04,0x00,0x42,
+ 0x60,0x0A,0x00,0x04,0x00,0x00,0x68,0x00,0x64,0x41,0x60,0x02,0x08,0x00,0x40,0x2B,
+ 0x00,0x40,0x00,0x4A,0x10,0x05,0x04,0x00,0xC0,0x82,0x02,0x00,0x00,0x40,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x40,0x03,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x03,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0xBF,0x02,0xC0,0x03,0x40,0x02,0xC0,0x00,
+ 0xC0,0x00,0x40,0x00,0x00,0x00,0x40,0x03,0x40,0x02,0x40,0x03,0x80,0x01,0x40,0x00,
+ 0x40,0x02,0x00,0x00,0xC0,0x00,0x40,0x03,0x40,0x02,0x40,0x00,0x40,0x00,0x40,0x02,
+ 0x40,0x03,0x40,0x01,0x40,0x02,0x40,0xBE,0x02,0x42,0x03,0xC0,0x13,0x40,0x11,0x40,
+ 0x48,0x10,0x80,0x00,0x00,0x00,0x83,0xC0,0x45,0x00,0x01,0x44,0x06,0x04,0x00,0x04,
+ 0x01,0xC4,0x00,0x40,0x47,0x00,0x0B,0x04,0x4B,0xD0,0x26,0x00,0x10,0x20,0x25,0xE0,
+ 0x23,0x00,0x80,0x20,0x25,0x40,0xFB,0x00,0x42,0x03,0x40,0x06,0x44,0x80,0x40,0x00,
+ 0x52,0x00,0x00,0x00,0x68,0x08,0x44,0x03,0x48,0x03,0x40,0x20,0x50,0x09,0x68,0x02,
+ 0x42,0x43,0x50,0x01,0x40,0x23,0x40,0x08,0x64,0x23,0x50,0x01,0x48,0x45,0x40,0x03,
+ 0x48,0x01,0x61,0x01,0x40,0xA2,0x00,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x00,
+ 0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x03,0x00,
+ 0x03,0x00,0x01,0x00,0xBD,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0x02,0x40,0x00,0x40,0x00,0x00,0x01,0x40,0x01,0x00,0x00,0x40,0x02,
+ 0x00,0x01,0x00,0x02,0x40,0x00,0x00,0x03,0x40,0x00,0x00,0x00,0x00,0x03,0x40,0x00,
+ 0x00,0x00,0x00,0xAF,0x02,0x50,0x18,0x40,0x00,0x62,0x24,0x60,0x14,0x40,0x88,0x00,
+ 0x00,0x40,0x02,0x62,0x18,0x50,0x19,0x40,0x01,0x40,0x03,0x42,0x04,0x51,0x1A,0x40,
+ 0x47,0x40,0x06,0x51,0x00,0x41,0x48,0x40,0x04,0x61,0x10,0x50,0x05,0x52,0x1A,0x40,
+ 0x88,0x40,0xF2,0x02,0x64,0x0A,0x00,0x00,0x18,0x05,0x04,0x20,0x40,0x03,0x00,0x00,
+ 0x00,0x20,0x40,0x06,0x58,0x04,0x00,0x42,0x60,0x00,0x00,0x08,0x58,0x04,0x28,0x0B,
+ 0x00,0x05,0x40,0x80,0x00,0x03,0x52,0x03,0x00,0x43,0x00,0x0B,0x54,0x05,0x00,0x88,
+ 0x40,0xF5,0x00,0x00,0x03,0x00,0x00,0x40,0x00,0x40,0x02,0x00,0x01,0x00,0x00,0x40,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x01,0x40,0x00,0x00,0x02,0x00,0x01,0x40,
+ 0x02,0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x02,0x40,0x00,0x40,
+ 0xC9,0x02,0x40,0x02,0x40,0x01,0x40,0x00,0x40,0x00,0x40,0x02,0x00,0x00,0x40,0x00,
+ 0x40,0x02,0x40,0x00,0x00,0x01,0x40,0x00,0x40,0x00,0xC0,0x02,0x40,0x00,0x40,0x03,
+ 0x40,0x03,0x40,0x03,0x40,0x02,0x40,0x03,0xC0,0x03,0x40,0x03,0x40,0x00,0x40,0xC6,
+ 0x02,0xC0,0x03,0x02,0x2A,0x00,0x10,0x10,0x24,0x10,0x19,0x00,0x00,0x00,0x24,0x10,
+ 0x13,0xC0,0x03,0x01,0x26,0xC0,0x19,0x00,0x00,0x42,0x03,0x08,0x11,0xC0,0x03,0xC2,
+ 0x03,0x10,0x87,0x00,0x19,0x00,0x27,0x60,0x23,0x00,0x13,0x00,0x80,0x60,0x85,0x02,
+ 0x42,0x01,0x68,0x04,0x44,0x80,0x60,0x04,0x44,0x01,0x00,0x20,0x40,0x02,0x40,0x06,
+ 0x40,0x02,0x40,0x00,0x00,0x00,0x42,0x48,0x40,0x03,0x64,0x11,0x50,0x20,0x50,0x27,
+ 0x40,0x00,0x48,0x03,0x40,0x03,0x44,0x04,0x62,0x24,0x60,0x07,0x00,0xFE,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x00,
+ 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xBE,0x00,0x40,0x01,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x40,0x01,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x40,0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xAC,0x00,0x50,0x89,0x40,
+ 0x00,0x52,0x14,0x40,0x80,0x50,0x1B,0x00,0x00,0x50,0x17,0x40,0x10,0x40,0x14,0x40,
+ 0x01,0x00,0x00,0x60,0x20,0x60,0x4B,0x40,0x08,0x41,0x88,0x40,0x10,0x50,0x28,0x50,
+ 0x06,0x42,0x0A,0x62,0x03,0x42,0x00,0x44,0x01,0xC4,0xBC,0x02,0x64,0x00,0x00,0x00,
+ 0x08,0x01,0x01,0x02,0x14,0x03,0x00,0x00,0x02,0x03,0x00,0x00,0x00,0x08,0x00,0x02,
+ 0x00,0x10,0x00,0x01,0x24,0x05,0x68,0x08,0x01,0x04,0x00,0x49,0x20,0x29,0x60,0x04,
+ 0x00,0x01,0x28,0x07,0x00,0x00,0x00,0x04,0xC0,0x82,0x02,0x00,0x03,0x40,0x00,0x00,
+ 0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x40,0x00,0x40,0x02,0x00,0x02,0x00,0x01,0x40,
+ 0x02,0x00,0x02,0x40,0x00,0x00,0x00,0x00,0xAE,0x00,0x40,0x03,0x40,0x01,0xC0,0x00,
+ 0x40,0x00,0x40,0x03,0x00,0x00,0x40,0x00,0x40,0x01,0x40,0x01,0x00,0x01,0x00,0x00,
+ 0x40,0x00,0x40,0x03,0xC0,0x03,0x40,0x00,0x40,0x03,0x40,0x03,0x40,0x02,0x40,0x03,
+ 0x40,0x00,0x40,0x03,0x40,0x01,0xC0,0x91,0x00,0x00,0x87,0x00,0x2A,0x60,0x08,0x22,
+ 0x48,0x00,0x05,0xC2,0x00,0x20,0x0B,0x04,0x8A,0x00,0x42,0x00,0x16,0x00,0x00,0x10,
+ 0x28,0x00,0x03,0x42,0x01,0x21,0x10,0x00,0x13,0x00,0x82,0x00,0x01,0x04,0x27,0x00,
+ 0x20,0x00,0x03,0x00,0x02,0x42,0xEA,0x00,0x24,0x23,0x40,0x00,0x58,0x8B,0x40,0x00,
+ 0x40,0x02,0x00,0x00,0x48,0x06,0x40,0x43,0x50,0x04,0x40,0x01,0x00,0x00,0x48,0x02,
+ 0x42,0x08,0x64,0x41,0x60,0x08,0x42,0x08,0x48,0x0B,0x48,0x8B,0x40,0x00,0x44,0x80,
+ 0x40,0x00,0x44,0x08,0xC0,0xB7,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x02,0x00,
+ 0x00,0x00,0x00,0x00,0x8C,0x00,0x40,0x03,0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x01,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x03,0x00,0xCB,0x02,0x40,0x07,0x52,0x08,0x41,0x01,0x62,0x14,0x40,0x87,0x00,
+ 0x00,0x50,0x10,0x40,0x2A,0x40,0x02,0x41,0x00,0x00,0x00,0x50,0x04,0x61,0x00,0x42,
+ 0x28,0x40,0x00,0x54,0x12,0x50,0x00,0x54,0x10,0x50,0x1A,0x60,0x1A,0x50,0x08,0x68,
+ 0x03,0xC2,0xE4,0x02,0x40,0x00,0x11,0x41,0x60,0x0A,0x04,0x02,0x00,0x03,0x00,0x00,
+ 0x00,0x08,0x00,0x81,0x00,0x09,0x04,0x06,0x00,0x00,0x00,0x00,0x00,0x05,0x68,0x00,
+ 0x11,0x09,0x01,0x03,0x40,0x02,0x01,0x00,0x12,0x03,0x08,0x09,0x00,0x08,0x00,0x00,
+ 0x40,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x03,0x00,0x00,0x40,
+ 0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x40,0x00,0x40,0x02,0x00,0x01,0x00,
+ 0x00,0x00,0x03,0x00,0x01,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,
+ 0xA8,0x02,0xC0,0x03,0xC0,0x00,0x40,0x00,0x40,0x00,0x40,0x01,0x00,0x00,0x40,0x00,
+ 0xC0,0x03,0x40,0x01,0x00,0x02,0x80,0x00,0x40,0x00,0x40,0x00,0x40,0x03,0x40,0x00,
+ 0x40,0x03,0x40,0x02,0x40,0x02,0x40,0x00,0xC0,0x01,0xC0,0x02,0x40,0x00,0xC0,0x8A,
+ 0x02,0x40,0x03,0x40,0x84,0x00,0x40,0xD0,0x24,0x00,0x06,0x02,0x00,0x00,0x20,0x40,
+ 0x0B,0x22,0x42,0x20,0x22,0x40,0x00,0x00,0x08,0x04,0x20,0x00,0x05,0x01,0x40,0x10,
+ 0x1B,0x00,0x09,0x24,0x18,0x00,0x24,0x60,0x02,0x42,0x81,0x00,0x00,0x40,0xCC,0x02,
+ 0x40,0x24,0x40,0x00,0x42,0x09,0x41,0x04,0x44,0x01,0x00,0x00,0x61,0x00,0x62,0x00,
+ 0x52,0x03,0x44,0x04,0x00,0x40,0x60,0x44,0x40,0x80,0x40,0x00,0x61,0x00,0x41,0x17,
+ 0x50,0x03,0x62,0x0B,0x40,0x02,0x44,0x4B,0x60,0x42,0x40,0x00,0x00,0xD9,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x03,0x00,
+ 0x03,0x00,0x03,0x00,0x02,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0x9C,0x00,0x40,0x02,
+ 0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,
+ 0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0xE9,0x00,0x40,0x02,0x52,
+ 0x08,0x61,0x03,0x62,0x80,0x50,0x18,0x00,0x00,0x40,0x88,0x40,0x07,0x42,0x07,0x61,
+ 0x20,0x00,0x00,0x40,0x01,0x51,0x18,0x50,0x08,0x44,0x18,0x50,0x13,0x40,0x28,0x40,
+ 0x40,0x40,0x0B,0x64,0x23,0x40,0x87,0x50,0x08,0x42,0x87,0x02,0x40,0x09,0x02,0x43,
+ 0x60,0x80,0x20,0x02,0x14,0x00,0x00,0x00,0x01,0x01,0x01,0x0B,0x01,0x00,0x00,0x03,
+ 0x00,0x00,0x04,0x82,0x20,0x40,0x00,0x05,0x02,0x00,0x08,0x11,0x00,0x02,0x00,0x03,
+ 0x00,0x03,0x00,0x01,0x00,0x0B,0x01,0x04,0x40,0xB6,0x02,0x00,0x02,0x40,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x40,0x00,0x40,0x03,0x40,0x00,0x40,0x03,0x00,
+ 0x00,0x40,0x01,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x01,0x40,0x03,0x40,
+ 0x03,0x40,0x02,0x40,0x03,0x40,0x00,0x00,0xD9,0x00,0x40,0x00,0x40,0x03,0x40,0x00,
+ 0x40,0x00,0xC0,0x00,0x00,0x00,0x40,0x00,0x40,0x03,0x40,0x01,0x40,0x00,0x00,0x00,
+ 0xC0,0x00,0x40,0x00,0x40,0x00,0xC0,0x00,0x40,0x02,0x40,0x03,0x40,0x03,0x40,0x01,
+ 0xC0,0x00,0x40,0x00,0x40,0x00,0x40,0xCA,0x00,0xC0,0x40,0xD0,0x00,0x00,0x09,0x02,
+ 0x48,0x40,0x09,0xC2,0x00,0xE0,0x48,0x20,0x03,0xE4,0x08,0x01,0x00,0x00,0x00,0x50,
+ 0x84,0x00,0x04,0x21,0x80,0x50,0x04,0x22,0x19,0xE0,0x0B,0x01,0x03,0x00,0x26,0x40,
+ 0x04,0x02,0x40,0xE0,0x80,0x40,0x92,0x00,0x48,0x27,0x40,0x0B,0x48,0x0B,0x00,0x00,
+ 0x41,0x03,0x00,0x80,0x60,0x20,0x40,0x00,0x40,0x03,0x44,0x80,0x40,0x23,0x50,0x81,
+ 0x50,0x08,0x44,0x40,0x50,0x03,0x44,0x03,0x48,0x82,0x40,0x13,0x40,0x01,0x44,0x40,
+ 0x60,0x42,0x60,0x04,0x80,0xCD,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x01,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0xBF,0x00,0x40,0x00,0x00,0x03,0x40,0x03,0x00,0x00,0x00,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x40,0x03,0x00,0x01,0x00,0x00,
+ 0x00,0x03,0x00,0x01,0x00,0x03,0x40,0x02,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0x02,
+ 0x00,0x00,0x00,0xEA,0x02,0x60,0x81,0x50,0x43,0x60,0x01,0x02,0x00,0x50,0x25,0x00,
+ 0x00,0x40,0x04,0x52,0x00,0x40,0x15,0x50,0x14,0x50,0x03,0x40,0x09,0x41,0x20,0x60,
+ 0x47,0x40,0x49,0x60,0x00,0x50,0x8A,0x50,0x19,0x50,0x05,0x62,0x16,0x40,0x0A,0x41,
+ 0x10,0xC0,0xA2,0x02,0x64,0x02,0x00,0x4B,0x60,0x02,0x00,0x20,0x00,0x0B,0x00,0x00,
+ 0x04,0x45,0x10,0x00,0x00,0x8A,0x00,0x01,0x40,0x00,0x00,0x04,0x14,0x01,0x00,0x00,
+ 0x00,0x04,0x24,0x00,0x40,0x00,0x22,0x20,0x00,0x03,0x00,0x03,0x00,0x03,0x12,0x09,
+ 0xC0,0x85,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,
+ 0xBD,0x02,0xC0,0x00,0x40,0x01,0x40,0x00,0x00,0x00,0xC0,0x02,0x00,0x00,0x40,0x00,
+ 0x40,0x00,0x40,0x03,0x40,0x00,0x40,0x00,0x40,0x02,0x40,0x00,0x40,0x00,0x40,0x01,
+ 0x40,0x00,0x40,0x03,0x40,0x01,0x40,0x03,0x40,0x03,0x40,0x00,0x40,0x00,0x40,0xD6,
+ 0x02,0x40,0x48,0x00,0x02,0xC4,0x88,0x00,0x00,0x50,0x43,0x00,0x00,0x10,0x00,0xC1,
+ 0x03,0xC0,0x43,0x10,0x04,0x04,0x00,0x00,0x41,0xC0,0x08,0xC8,0x00,0xC0,0x02,0x02,
+ 0x00,0x00,0x87,0x00,0x27,0x20,0x25,0x00,0x07,0xC1,0x44,0x00,0x00,0xC1,0x9B,0x02,
+ 0x40,0x01,0x00,0x00,0x44,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x21,0x40,0x00,
+ 0x44,0x07,0x58,0x14,0x10,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x68,0x00,0x44,0x08,
+ 0x44,0x15,0x60,0x00,0x44,0x0B,0x44,0x08,0x44,0x0B,0x40,0x03,0x80,0xDD,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x02,0x00,
+ 0x03,0x00,0x01,0x00,0x03,0x00,0x02,0x00,0x03,0x00,0x03,0x00,0x9D,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,
+ 0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x40,0x00,0x40,0x03,0x40,0x03,
+ 0x00,0x00,0x40,0x02,0x40,0x00,0x40,0x01,0x00,0x01,0x00,0xAB,0x02,0x40,0x04,0x01,
+ 0x00,0x60,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x40,0x44,0x50,0x14,0x60,0x03,0x44,
+ 0x03,0x42,0x07,0x01,0x00,0x00,0x00,0x40,0x26,0x40,0x03,0x60,0x03,0x64,0x83,0x40,
+ 0x14,0x60,0x03,0x64,0x12,0x60,0x03,0x44,0x05,0xC2,0x95,0x02,0x00,0x04,0x00,0x40,
+ 0x60,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x68,0x00,0x52,0x00,
+ 0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x64,0x20,0x40,0x04,0x48,0x02,0x01,0x00,
+ 0x64,0x08,0x48,0x05,0x48,0x09,0x00,0x02,0xC0,0xE9,0x02,0x40,0x00,0x40,0x00,0x40,
+ 0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x01,0x40,0x01,0x40,0x00,0x40,
+ 0x00,0x40,0x00,0x40,0x00,0x40,0x02,0x40,0x00,0x40,0x00,0x40,0x03,0x40,0x03,0x40,
+ 0x02,0x40,0x00,0x40,0x00,0x40,0x01,0x00,0xED,0x02,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x00,0x02,0x00,0x00,
+ 0x00,0x01,0x80,0x01,0x80,0x03,0x40,0xE8,0x06,0x08,0x41,0x00,0x00,0xC0,0x00,0x04,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x01,0x03,0x04,0x0B,0x02,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x10,0x10,0x50,0x19,0x20,0x1B,0x00,0x23,0xE0,
+ 0x02,0x52,0x12,0x40,0x1B,0xC0,0xD0,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x20,0xAD,0x00,0x02,0x00,0x00,0x00,0x82,0x00,0x02,0x00,0x02,
+ 0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x30,0x00,0x02,0x00,0x00,0x00,0x02,
+ 0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
+ 0x00,0x02,0x00,0x20,0xA6,0x00,0x00,0x80,0x00,0x00,0x00,0x40,0x00,0x00,0x90,0x00,
+ 0x00,0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x02,0x00,0x00,0x00,0x10,0x00,0x80,0x00,0x40,0x00,0x00,0x20,0x04,0x00,
+ 0x02,0x00,0x80,0xAE,0x00,0x10,0x10,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x20,0x90,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,
+ 0x00,0x00,0x20,0x00,0x00,0x60,0x02,0x04,0x08,0x00,0x00,0x80,0x00,0x00,0x08,0x00,
+ 0x10,0x80,0x8E,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x80,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x02,0x00,0x20,0x00,0x00,0x00,0x00,0x80,
+ 0x12,0x00,0x02,0x04,0x20,0x00,0x00,0x80,0x00,0x80,0x00,0x00,0x02,0x04,0x00,0x00,
+ 0x80,0xF5,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x10,0x00,0x00,0x00,0x84,
+ 0x00,0x00,0x00,0x00,0x30,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x40,
+ 0x87,0x00,0x00,0x00,0x00,0x00,0x80,0x20,0x60,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x04,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x20,0x80,0xB8,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x80,
+ 0x00,0x04,0x04,0x02,0x00,0x08,0x00,0x10,0x00,0x00,0x08,0x00,0x04,0x80,0xAD,0x00,
+ 0x00,0x00,0x00,0x00,0x0A,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x04,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x40,
+ 0x80,0x00,0x00,0x00,0x40,0x84,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0xE1,0x00,0x00,
+ 0x20,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,
+ 0x80,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x08,0x00,0x40,0x00,0x00,0x00,
+ 0x04,0x00,0x40,0x00,0x00,0x80,0x00,0x00,0x00,0x0C,0x00,0x80,0xD4,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x10,0x00,0x40,0x08,0x00,0x00,
+ 0x20,0x06,0x00,0x00,0x80,0x00,0x10,0x00,0x00,0x20,0x20,0x88,0x00,0x00,0x00,0x00,
+ 0x00,0x10,0x00,0x00,0x00,0x00,0x08,0x80,0x26,0x00,0x80,0x81,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x08,
+ 0x00,0x08,0x00,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x08,
+ 0x00,0x82,0x40,0x00,0x20,0x40,0x00,0x40,0x00,0x04,0xD1,0x00,0x00,0x00,0x00,0x00,
+ 0x20,0x84,0x00,0x00,0x00,0xA0,0x00,0x00,0x18,0x20,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x04,0x00,0xA6,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x10,0x40,0x00,
+ 0x04,0x00,0x60,0x00,0x00,0x40,0x00,0x80,0x00,0x83,0x00,0x00,0x00,0x00,0x12,0x00,
+ 0x00,0x00,0x00,0x08,0x80,0x04,0x00,0x00,0x00,0x00,0x50,0x00,0x20,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x10,0x00,0x84,0x00,0x00,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xF0,0x04,0x10,0x00,0x04,0x00,0x08,0x02,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x18,0x02,0x80,0x00,0x80,0xE1,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x08,
+ 0x00,0x00,0x10,0x08,0x00,0x02,0x40,0x00,0x04,0x00,0x00,0x00,0x02,0x04,0x00,0x00,
+ 0x00,0x00,0x04,0x08,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,
+ 0x80,0x00,0x20,0x08,0x80,0x80,0xC0,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,
+ 0x01,0x00,0x00,0x00,0x00,0x08,0x20,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x08,
+ 0x00,0x00,0x00,0x04,0x00,0x10,0x08,0x00,0x00,0x00,0x02,0x00,0x30,0x00,0x00,0x00,
+ 0x00,0x48,0x00,0x40,0x80,0xE7,0x00,0x00,0x80,0x01,0x12,0x00,0x00,0x00,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x24,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x40,0x20,0x00,0x80,0x00,0x02,0x00,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0xEB,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x04,0x00,0x10,0x40,
+ 0x00,0x80,0x00,0x08,0x02,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
+ 0x10,0x40,0x00,0x0C,0x01,0x08,0x00,0x00,0x01,0x80,0x00,0x10,0x08,0x02,0x00,0x00,
+ 0x02,0x00,0x00,0xA3,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x08,0x10,0x00,0x00,
+ 0x80,0x00,0x00,0x02,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x02,0x00,
+ 0x00,0x00,0x80,0x08,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x20,0x00,0x00,0x00,0x40,
+ 0x0C,0x88,0xA6,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x20,
+ 0x10,0x00,0x24,0x00,0x20,0x00,0x02,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,
+ 0x00,0x00,0x01,0x00,0x10,0x82,0x20,0x00,0x08,0x08,0x01,0x00,0x08,0x00,0x04,0x00,
+ 0x90,0xF9,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x10,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x10,0x20,0x40,0x04,0x00,0x00,0x00,
+ 0x02,0x24,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x81,
+ 0xCB,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x81,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x20,0x80,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x80,0x90,0x02,
+ 0x42,0x20,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0xA6,
+ 0x00,0xC0,0x24,0x20,0x00,0x00,0x00,0x00,0x08,0x41,0x04,0x00,0x20,0x00,0x02,0x00,
+ 0x00,0x20,0x04,0x40,0x00,0x00,0x00,0x00,0x00,0x80,0x12,0x40,0x02,0x40,0x04,0x10,
+ 0x08,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x80,0x10,0x00,0x00,0x08,0x00,0xF1,0x10,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x04,0x10,0x40,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x20,0x20,0x08,
+ 0x00,0x00,0x10,0x00,0x40,0x10,0x00,0x00,0x12,0x00,0x00,0x00,0x80,0x9B,0x00,0x10,
+ 0x00,0x00,0x00,0x40,0x00,0x28,0x00,0x02,0x00,0x20,0x00,0x20,0x40,0x00,0x20,0x08,
+ 0x00,0x00,0x00,0x80,0x00,0x00,0x80,0x06,0x00,0x0C,0x10,0x01,0x00,0x40,0x00,0x08,
+ 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x82,0x90,0x00,0x00,0x24,
+ 0x08,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x20,0x00,0x00,
+ 0x04,0x00,0x00,0x02,0x00,0x10,0x00,0x08,0x00,0x80,0x00,0x40,0x00,0x08,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x80,0x08,0x90,0xD4,0x00,0x81,0x00,0x14,
+ 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x40,0x00,0x90,0x00,0x00,0x04,0x00,0x00,0x00,0x10,0x02,0x80,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xEE,0x00,0x20,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x50,0x00,0x00,0x08,0x00,0x04,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x02,0x00,0x00,0x50,0x04,0x20,0x00,0x08,0x40,
+ 0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0xAD,0x00,0x00,0x00,0x00,0x10,0x02,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x02,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x02,0x40,0x01,0x00,0x10,0x08,0x00,
+ 0x02,0x08,0x80,0x00,0x10,0x00,0x00,0x80,0x86,0x00,0x40,0x00,0x00,0x20,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x00,0x00,0x00,0x10,0x00,0x60,0x10,
+ 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x20,0x00,
+ 0x00,0x02,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x08,0x08,0x00,0x00,0x00,0x40,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x60,0x00,0x00,0x04,0x00,
+ 0x00,0x00,0x04,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x4A,0x00,0x00,0x50,0x10,0x00,
+ 0x00,0x80,0x00,0x00,0x00,0x00,0xA9,0x02,0x41,0x83,0x00,0x01,0x54,0x03,0x42,0x04,
+ 0x41,0x4A,0x50,0x04,0x48,0x03,0x58,0x03,0x44,0x05,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x40,0x02,0x41,0x8B,0x60,0x00,0x40,0x00,
+ 0x00,0x00,0x40,0x0A,0x00,0xB1,0x00,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x02,0x00,0x8C,0x00,0x40,0x01,0x40,0x01,0x00,0x03,0x00,0x00,0x40,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x03,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x40,0x00,0x40,0x02,0x00,0x00,
+ 0x00,0x00,0x00,0xDC,0x00,0x60,0x25,0x50,0x25,0x40,0x29,0x50,0x10,0x60,0x03,0x44,
+ 0x40,0x50,0x8B,0x40,0x0B,0x64,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x50,0x00,0x00,0x00,0x40,0x88,0x50,0x13,0x40,0x25,0x40,0x8A,0x00,0x00,0x40,
+ 0x00,0x41,0xA0,0x02,0x40,0x00,0x40,0x44,0x00,0x87,0x20,0x06,0x40,0x03,0x04,0x00,
+ 0x04,0x40,0x20,0x00,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x18,0x00,0x00,0x00,0x00,0x04,0x08,0x02,0x42,0x08,0x42,0x02,0x00,0x00,0x00,0x00,
+ 0x40,0xEE,0x02,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x40,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0xEB,0x00,0x40,0x01,0x40,0x03,0x40,0x02,0x40,0x02,0x40,0x03,0x40,0x00,0x40,0x00,
+ 0x40,0x00,0x40,0x00,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0xC0,0x01,0x40,0x03,0x40,0x03,0x00,0x02,0x00,0x00,0x40,0x01,0xC0,0x94,
+ 0x00,0x00,0x8A,0x00,0x03,0x14,0x03,0x02,0x20,0x00,0x07,0x14,0x05,0xD1,0x03,0x00,
+ 0x03,0x00,0x25,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x40,0x12,0x10,0x1B,0x20,0x13,0x10,0x26,0x00,0x00,0x00,0x0A,0x44,0x82,0x02,
+ 0x40,0x81,0x00,0x01,0x61,0x49,0x60,0x23,0x60,0x03,0x00,0x00,0x44,0x09,0x62,0x01,
+ 0x42,0x05,0x00,0x00,0x68,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x00,0x00,0x00,
+ 0x40,0x06,0x58,0x43,0x40,0x01,0x40,0x04,0x00,0x00,0x62,0x00,0x00,0x9B,0x00,0x00,
+ 0x01,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xBC,0x00,0x00,0x02,
+ 0x40,0x01,0x40,0x01,0x40,0x01,0x00,0x02,0x00,0x00,0x00,0x01,0x40,0x00,0x40,0x01,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x03,0x40,0x00,0x40,0x02,0x00,0x00,0x40,0x00,0x00,0x89,0x2A,0x40,0x02,0x50,
+ 0x15,0x40,0x10,0x40,0x15,0x40,0x24,0x00,0x00,0x50,0x81,0x40,0x16,0x60,0x10,0x00,
+ 0x00,0x40,0x01,0x04,0x00,0x00,0x00,0x00,0x00,0x50,0x18,0x00,0x00,0x40,0x80,0x40,
+ 0x03,0x60,0x16,0x40,0x42,0x00,0x00,0x40,0x15,0xC0,0xEF,0x0A,0x00,0x01,0x40,0x00,
+ 0x48,0x00,0x40,0x04,0x01,0x09,0x00,0x00,0x00,0x00,0x64,0x04,0x64,0x03,0x00,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x28,0x00,
+ 0x52,0x04,0x42,0x02,0x00,0x00,0x61,0x08,0xC0,0xF1,0x02,0x00,0x02,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0xAF,0x02,0x00,0x02,0x40,0x03,0x40,0x03,
+ 0x40,0x01,0xC0,0x03,0x00,0x00,0xC0,0x03,0x40,0x02,0x40,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x03,0x00,0x00,0x40,0x01,0x40,0x00,0x40,0x02,
+ 0x00,0x02,0x00,0x00,0x40,0x03,0x40,0xA6,0x00,0x04,0x45,0x00,0x47,0xD0,0x15,0xC0,
+ 0x02,0x62,0x03,0x01,0x00,0x40,0x87,0x00,0x01,0x01,0x15,0x00,0x00,0x20,0x48,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x12,0x00,0x03,0x00,0x01,0x11,
+ 0x16,0x00,0x00,0x00,0x03,0xC2,0xB9,0x00,0x40,0x80,0x00,0x05,0x61,0x07,0x48,0x01,
+ 0x58,0x01,0x40,0x00,0x44,0x05,0x51,0x83,0x50,0x01,0x00,0x00,0x51,0x0B,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x58,0x00,0x00,0x40,0x60,0x03,0x44,0x82,0x60,0x04,0x40,0x00,
+ 0x00,0x00,0x40,0x02,0x00,0xB7,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x02,0x00,0xBF,0x00,0x00,0x01,0x40,0x01,0x40,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x02,0x00,0x01,0x40,0x00,0x00,0x03,0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x03,0x00,0x00,0x40,0x03,0x40,0x01,0x40,0x00,0x40,0x02,0x00,0x00,
+ 0x00,0x00,0x00,0xA9,0x02,0x40,0x01,0x50,0x11,0x40,0x13,0x60,0x44,0x40,0x18,0x40,
+ 0x06,0x51,0x01,0x41,0x24,0x40,0x2B,0x00,0x00,0x40,0x03,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x40,0x0B,0x02,0x00,0x40,0x03,0x50,0x89,0x40,0x11,0x40,0x4A,0x00,0x00,0x40,
+ 0x28,0xC0,0xD2,0x02,0x00,0x06,0x40,0x00,0x44,0x2A,0x20,0x00,0x00,0x08,0x00,0x05,
+ 0x00,0x08,0x40,0x06,0x00,0x0B,0x00,0x00,0x52,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x03,0x00,0x00,0x40,0x00,0x40,0x06,0x42,0x00,0x42,0x06,0x00,0x00,0x00,0x00,
+ 0xC0,0xD6,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x02,0x00,
+ 0x00,0x00,0x01,0x40,0x03,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0xFF,0x02,0x00,0x01,0x40,0x03,0x40,0x02,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x03,
+ 0x40,0x02,0x40,0x03,0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x03,
+ 0x00,0x00,0x40,0x00,0x00,0x02,0x40,0x03,0x00,0x02,0x00,0x00,0x40,0x01,0x40,0xBE,
+ 0x02,0x00,0x02,0x01,0x0B,0x24,0x83,0x00,0x08,0x04,0x20,0x00,0x40,0x00,0x03,0x04,
+ 0x11,0xC0,0x83,0xC0,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x11,0x20,0x17,0x10,0x12,0x00,0x00,0x00,0x0A,0xC4,0x82,0x00,
+ 0x40,0x80,0x00,0x89,0x60,0x41,0x40,0x08,0x40,0x84,0x40,0x08,0x52,0x0A,0x44,0x0A,
+ 0x58,0x03,0x00,0x00,0x44,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x0B,0x00,0x00,
+ 0x40,0x06,0x40,0x28,0x50,0x09,0x40,0x00,0x00,0x20,0x50,0x00,0x80,0xAA,0x00,0x00,
+ 0x00,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x00,0x00,0x02,
+ 0x40,0x01,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x00,0x40,0x02,0x40,0x00,0x00,0x02,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,
+ 0x40,0x02,0x40,0x00,0x40,0x02,0x00,0x00,0x00,0x03,0x00,0xFC,0x02,0x40,0x02,0x50,
+ 0x11,0x40,0x29,0x60,0x03,0x42,0x41,0x60,0x00,0x44,0x10,0x60,0x11,0x40,0x27,0x00,
+ 0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x03,0x02,0x00,0x40,0x00,0x44,
+ 0x02,0x48,0x12,0x40,0x0A,0x01,0x00,0x40,0x0B,0x44,0x97,0x02,0x00,0x01,0x40,0x00,
+ 0x14,0x08,0x00,0x00,0x00,0x22,0x00,0x01,0x51,0x00,0x42,0x48,0x10,0x03,0x00,0x00,
+ 0x11,0x09,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x04,0x44,0x0A,
+ 0x52,0x04,0x42,0x0A,0x00,0x00,0x00,0x00,0x40,0xC0,0x00,0x00,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
+ 0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x9C,0x02,0x00,0x02,0x40,0x03,0x40,0x03,
+ 0x40,0x00,0x40,0x00,0xC0,0x00,0x40,0x03,0x40,0x01,0x40,0x03,0x00,0x00,0x40,0x01,
+ 0x00,0x00,0x80,0x00,0x00,0x00,0x40,0x00,0x80,0x00,0xC0,0x01,0x00,0x02,0x40,0x02,
+ 0x00,0x02,0x00,0x00,0x40,0x00,0xC0,0xA5,0x02,0x00,0x05,0x02,0x07,0x01,0x40,0x00,
+ 0x00,0x00,0x24,0x50,0x28,0x00,0x04,0x22,0x02,0xC1,0x17,0x00,0x00,0x00,0x03,0x04,
+ 0x00,0x40,0x00,0x00,0x00,0x10,0x03,0x40,0x00,0x40,0x12,0xD0,0x12,0x00,0x01,0x11,
+ 0x12,0x00,0x00,0x00,0x00,0xC0,0xF0,0x00,0x40,0x80,0x00,0x01,0x48,0x85,0x20,0x01,
+ 0x41,0x0A,0x42,0x05,0x62,0x03,0x42,0x01,0x40,0x04,0x00,0x00,0x68,0x03,0x00,0x00,
+ 0x00,0x00,0x00,0x40,0x60,0x03,0x00,0x00,0x00,0x00,0x40,0x04,0x48,0x00,0x40,0x04,
+ 0x00,0x00,0x51,0x0B,0x00,0xDF,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
+ 0x02,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x9C,0x00,0x00,0x02,0x40,0x01,0x40,0x01,0x40,0x00,0x40,0x03,
+ 0x40,0x03,0x40,0x00,0x40,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x40,0x02,0x00,0x03,0x40,0x02,0x00,0x00,
+ 0x00,0x03,0x00,0x9C,0x02,0x40,0x02,0x50,0x19,0x60,0x03,0x41,0x24,0x60,0x03,0x52,
+ 0x83,0x40,0x14,0x50,0x1A,0x40,0x02,0x04,0x00,0x40,0x4B,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x40,0x1A,0x00,0x00,0x00,0x00,0x40,0x02,0x52,0x0B,0x44,0x02,0x02,0x00,0x40,
+ 0x01,0xC2,0xDF,0x02,0x00,0x01,0x40,0x00,0x48,0x00,0x42,0x03,0x40,0x43,0x40,0x07,
+ 0x40,0x02,0x64,0x04,0x00,0x09,0x00,0x00,0x08,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x51,0x04,0x00,0x00,0x00,0x00,0x44,0x02,0x00,0x00,0x42,0x02,0x00,0x00,0x01,0x0A,
+ 0x40,0x8B,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x40,0x03,0x40,0x03,0x00,
+ 0x01,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x40,0x03,0x00,
+ 0x8B,0x02,0x00,0x02,0x40,0x03,0xC0,0x00,0x40,0x02,0x40,0x03,0x40,0x03,0x40,0x02,
+ 0x40,0x02,0x40,0x00,0x80,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x02,0x40,0x00,0x00,0x02,0x00,0x00,0x40,0x02,0xC0,0xE9,
+ 0x02,0xC0,0x09,0x08,0x87,0x50,0x19,0x10,0x19,0x00,0x07,0x14,0x03,0xC1,0x19,0x00,
+ 0x01,0x01,0x20,0x40,0x00,0x20,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x04,
+ 0x00,0xC0,0x00,0x10,0x1A,0x00,0x00,0x10,0x1A,0x00,0x00,0x20,0x41,0x40,0xA6,0x02,
+ 0x40,0x10,0x40,0x83,0x60,0x04,0x44,0x49,0x40,0x03,0x51,0x03,0x48,0x42,0x40,0x0B,
+ 0x40,0x02,0x00,0x00,0x40,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x06,0x00,0x00,
+ 0x40,0x0A,0x40,0x00,0x48,0x05,0x40,0x00,0x00,0x00,0x41,0x01,0x00,0xAA,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,
+ 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xAF,0x00,0x00,0x02,
+ 0x40,0x02,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x00,0x40,0x00,0x00,0x01,0x00,0x00,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x40,0x01,0x40,0x00,0x00,0x00,0x00,0x03,0x00,0xB9,0x2A,0x40,0x02,0x50,
+ 0x8B,0x40,0x00,0x52,0x41,0x50,0x1B,0x40,0x18,0x50,0x07,0x61,0x11,0x40,0x24,0x00,
+ 0x00,0x40,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x03,0x04,0x00,0x40,0x00,0x42,
+ 0x0B,0x51,0x81,0x40,0x0B,0x02,0x00,0x60,0x87,0x40,0x84,0x0A,0x00,0x09,0x41,0x2B,
+ 0x10,0x0A,0x00,0x00,0x00,0x20,0x20,0x07,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x04,0x48,0x00,
+ 0x52,0x04,0x48,0x00,0x00,0x00,0x00,0x0B,0x40,0xE6,0x02,0x00,0x02,0x40,0x03,0x40,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,
+ 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0xBD,0x02,0x00,0x02,0x40,0x03,0x40,0x00,
+ 0x40,0x03,0x40,0x03,0x40,0x03,0x40,0x00,0x40,0x01,0x40,0x01,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0xC0,0x01,0x80,0x02,0x40,0x01,
+ 0x00,0x02,0x00,0x00,0x40,0x03,0xC0,0x97,0x00,0x02,0x81,0x20,0x43,0xC0,0x80,0x00,
+ 0x0B,0x01,0x03,0x00,0x83,0x00,0x06,0x02,0x0A,0x04,0x16,0x00,0x00,0x00,0x00,0x04,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x02,0x00,0x40,0x12,0x50,0x0A,0x04,0x00,0x11,
+ 0x0A,0x04,0x00,0x00,0x43,0xC0,0xAC,0x00,0x40,0x00,0x48,0x0B,0x42,0x20,0x50,0x40,
+ 0x40,0x05,0x51,0x04,0x44,0x09,0x58,0x4A,0x40,0x00,0x00,0x00,0x48,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x61,0x08,0x00,0x00,0x40,0x06,0x40,0x04,0x40,0x0A,0x40,0x00,
+ 0x00,0x00,0x00,0x02,0x00,0xCB,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x01,0x00,
+ 0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x02,0x00,0xAC,0x00,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x40,0x03,
+ 0x40,0x00,0x00,0x01,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
+ 0x40,0x01,0x00,0xAA,0x02,0x40,0x02,0x50,0x03,0x61,0x86,0x40,0x09,0x52,0x03,0x44,
+ 0x80,0x50,0x11,0x40,0x03,0x51,0x2A,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x40,0x00,0x04,0x00,0x40,0x40,0x40,0x43,0x40,0x10,0x40,0x87,0x00,0x00,0x40,
+ 0x01,0xC0,0x8E,0x02,0x00,0x09,0x01,0x45,0x00,0x0B,0x01,0x02,0x41,0x27,0x60,0x07,
+ 0x00,0x04,0x68,0x04,0x01,0x08,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,
+ 0x20,0x01,0x00,0x00,0x00,0x04,0x58,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x40,0x0A,
+ 0xC0,0x99,0x00,0x00,0x02,0x00,0x03,0x00,0x00,0x40,0x01,0x40,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x40,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,
+ 0xC8,0x02,0x00,0x02,0x40,0x00,0x40,0x03,0x40,0x02,0x40,0x03,0x40,0x01,0x40,0x03,
+ 0x40,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x40,0x01,0x00,0x02,0x40,0x01,0x00,0x02,0x00,0x00,0x00,0x01,0x40,0xCD,
+ 0x02,0x00,0x41,0x20,0x20,0x10,0x00,0x24,0x45,0x20,0x03,0x01,0x02,0xC1,0x23,0x00,
+ 0x42,0x20,0x80,0x00,0x00,0xD0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x01,
+ 0x00,0xC0,0x12,0x00,0x0A,0x04,0x0A,0x04,0x0A,0x04,0x00,0x00,0x02,0xC8,0xDA,0x02,
+ 0x40,0x40,0x40,0x03,0x00,0x20,0x60,0x00,0x58,0x2B,0x40,0x0B,0x58,0x0B,0x68,0x01,
+ 0x40,0x00,0x00,0x40,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x00,0x00,
+ 0x40,0x06,0x40,0x20,0x20,0x03,0x40,0x04,0x00,0x00,0x00,0x00,0x00,0xA4,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBE,0x00,0x00,0x02,
+ 0x40,0x02,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x03,0x40,0x03,0x40,0x01,0x00,0x02,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x40,0x03,0x40,0x00,0x00,0x00,0x40,0x03,0x00,0xBD,0x2A,0x40,0x02,0x50,
+ 0x8B,0x00,0x00,0x40,0x08,0x44,0x03,0x51,0x83,0x40,0x00,0x41,0x85,0x40,0x86,0x00,
+ 0x00,0x40,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x04,0x02,0x00,0x40,0x20,0x40,
+ 0x2B,0x40,0x07,0x41,0x03,0x01,0x00,0x40,0x00,0x40,0xBF,0x06,0x00,0x05,0x41,0x0B,
+ 0x00,0x40,0x00,0x28,0x20,0x0B,0x00,0x03,0x68,0x00,0x64,0x04,0x00,0x09,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x05,0x00,0x00,0x00,0x04,0x68,0x00,
+ 0x61,0x0B,0x68,0x00,0x00,0x00,0x68,0x00,0xC0,0x8B,0x02,0x00,0x02,0x40,0x03,0x00,
+ 0x00,0x40,0x00,0x00,0x01,0x40,0x03,0x00,0x03,0x00,0x00,0x40,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x40,
+ 0x03,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0xCE,0x02,0x00,0x02,0x40,0x03,0x80,0x00,
+ 0x40,0x00,0x40,0x00,0xC0,0x01,0x40,0x00,0x40,0x01,0x40,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x01,0x00,0x02,0x40,0x03,
+ 0x00,0x02,0x00,0x00,0x00,0x03,0x40,0xE9,0x80,0xC0,0x01,0x28,0x43,0x40,0x00,0x20,
+ 0x00,0x02,0x00,0x48,0x2A,0x00,0x00,0x00,0x00,0x01,0x20,0xC0,0x00,0x20,0x44,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x12,0x00,0x0A,0x04,0x43,0x00,
+ 0x0A,0x04,0x00,0x00,0x00,0xC0,0xBB,0x02,0x40,0x02,0x68,0x0B,0x54,0x01,0x41,0x00,
+ 0x44,0x05,0x44,0x82,0x40,0x07,0x48,0x07,0x58,0x00,0x00,0x20,0x60,0x09,0x00,0x00,
+ 0x00,0x00,0x00,0x80,0x40,0x08,0x00,0x00,0x40,0x02,0x40,0x04,0x42,0x03,0x40,0x0B,
+ 0x00,0x00,0x00,0x00,0x40,0xA0,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,
+ 0x03,0x00,0x02,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x8F,0x00,0x00,0x02,0x00,0x03,0x00,0x01,0x00,0x00,0x40,0x01,
+ 0x00,0x03,0x40,0x01,0x40,0x03,0x00,0x01,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x03,0x40,0x00,0x00,0x00,
+ 0x40,0x03,0x00,0x99,0x2A,0x40,0x00,0x40,0x03,0x41,0x28,0x60,0x04,0x68,0x41,0x50,
+ 0x07,0x61,0x81,0x50,0x00,0x42,0x25,0x00,0x00,0x40,0x43,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x60,0x20,0x00,0x00,0x40,0x04,0x42,0x03,0x54,0x04,0x41,0x20,0x00,0x00,0x40,
+ 0x03,0xC0,0x8D,0x02,0x02,0x05,0x01,0x45,0x00,0x2B,0x10,0x40,0x40,0x00,0x00,0x07,
+ 0x40,0x08,0x48,0x00,0x00,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x00,0x00,0x00,0x40,
+ 0x10,0x01,0x00,0x00,0x00,0x04,0x48,0x00,0x28,0x05,0x40,0x02,0x00,0x00,0x40,0x03,
+ 0xD8,0x8F,0x02,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x03,0x40,
+ 0xCA,0x02,0x00,0x01,0x40,0x00,0x40,0x00,0xC0,0x00,0xC0,0x03,0x40,0x03,0x40,0x01,
+ 0xC0,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x40,0x01,0x00,0x02,0x40,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0xC0,0xD6,
+ 0x08,0x22,0x81,0x20,0x20,0x10,0x01,0x41,0x04,0x52,0x04,0x04,0x43,0x00,0x02,0x61,
+ 0x00,0x00,0x14,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x08,0x04,
+ 0x00,0x00,0x12,0x20,0x0A,0xC4,0x23,0x00,0x0A,0x04,0x00,0x00,0x00,0xC0,0xD9,0x00,
+ 0x00,0x00,0x04,0x03,0x48,0x03,0x44,0x03,0x41,0x47,0x40,0x04,0x44,0x07,0x44,0x01,
+ 0x48,0x06,0x00,0x00,0x64,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x02,0x00,0x00,
+ 0x40,0x1A,0x60,0x08,0x44,0x0A,0x44,0x08,0x00,0x00,0x40,0x0B,0x80,0x96,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xAC,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x03,0x40,0x02,0x00,0x00,0x00,0x03,0x40,0x02,0x40,0x01,0x00,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xE9,0x02,0x00,0x00,0x60,
+ 0x0B,0x52,0x27,0x60,0x8A,0x60,0x80,0x50,0x03,0x61,0x12,0x60,0x09,0x52,0x03,0x04,
+ 0x00,0x40,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x1A,0x00,0x00,0x40,0x00,0x41,
+ 0x80,0x60,0x03,0x51,0x00,0x01,0x00,0x40,0x01,0xC2,0x9D,0x02,0x00,0x80,0x40,0x20,
+ 0x10,0x00,0x40,0x04,0x00,0x00,0x00,0x00,0x40,0x08,0x64,0x04,0x08,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x08,0x00,0x00,0x00,0x04,0x22,0x08,
+ 0x48,0x04,0x22,0x04,0x00,0x00,0x00,0x0A,0xC0,0xFB,0x00,0x40,0x00,0x40,0x00,0x40,
+ 0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x02,0x40,0x00,0x40,
+ 0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,
+ 0x00,0x00,0x00,0x40,0x00,0x00,0x01,0x00,0xEB,0x02,0x00,0x00,0x00,0x00,0x00,0x03,
+ 0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x00,
+ 0x00,0x03,0x00,0x00,0x00,0x03,0x40,0xEA,0x02,0x00,0x00,0x10,0x03,0x00,0x00,0x00,
+ 0x01,0xC2,0x00,0x00,0x00,0xC0,0x01,0x01,0x00,0x21,0x86,0xC0,0x00,0x20,0x44,0x00,
+ 0x00,0xC0,0x00,0x00,0x00,0x20,0x00,0x01,0x00,0x00,0x12,0x00,0x03,0xD1,0x42,0x00,
+ 0x03,0x04,0x00,0x00,0x43,0x40,0xEF,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x30,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x80,0x30,0x00,0xC1,0x80,
+ 0x00,0x00,0x04,0x00,0xA0,0xD9,0x00,0x02,0x00,0xB0,0x00,0xC2,0x00,0x02,0x00,0x30,
+ 0x02,0x30,0x00,0x02,0x00,0x02,0x00,0x82,0x00,0x40,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,
+ 0x00,0x02,0x00,0xA0,0xFB,0x00,0x20,0x04,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x20,0x20,0x00,0x40,0x00,0x80,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x01,0x00,0x00,0x00,0x40,0x02,
+ 0x00,0x00,0x80,0x85,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,
+ 0x00,0x00,0x00,0x04,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x04,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x04,0x20,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0xB0,0x00,0x00,0x00,0x02,0x44,0x03,0x00,0x21,0x00,0x00,0x00,0x22,0x80,
+ 0x00,0x00,0x00,0x00,0x02,0x04,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,
+ 0x80,0x8D,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x10,0x00,0x01,0x28,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xF4,0x00,0x00,0x00,0x06,0x02,0x00,0x00,0x00,0x02,0x04,0x42,0x00,0x00,0x02,0x00,
+ 0x60,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0xBE,
+ 0x00,0x00,0x40,0x80,0x00,0x00,0x00,0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,
+ 0x00,0x10,0x00,0x04,0x0A,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x20,
+ 0x00,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x02,0x00,
+ 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFC,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x20,0x00,0x04,0x00,0x00,
+ 0x40,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x02,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x80,0xC1,0x00,0x08,0x80,
+ 0x10,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x80,0x0C,
+ 0x00,0x00,0x50,0x00,0x20,0x02,0x00,0x00,0x00,0x00,0x10,0xE0,0x00,0x02,0x00,0x00,
+ 0x00,0x00,0x40,0x40,0x00,0x00,0x08,0x00,0x00,0x40,0x20,0x00,0x00,0x10,0xC0,0x02,
+ 0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0x08,0x40,0x00,0x00,0x00,0x00,0x02,0x00,0x80,0x8B,0x00,0x00,0x00,0x08,0x40,
+ 0x40,0x80,0x10,0x00,0x08,0x00,0x33,0x84,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x01,0x00,
+ 0x02,0x00,0x08,0x04,0x00,0x00,0x00,0x00,0x80,0xC7,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x40,0x10,0x00,0x00,0x00,0x01,0x00,0x04,0x80,0x00,0x00,0x00,0x00,0x00,0x12,0x04,
+ 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF5,0x00,0x00,0x00,0x00,0x84,0x00,0x00,
+ 0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x01,0x00,0x04,0x00,0x00,0x02,0x10,0x00,
+ 0x00,0x00,0x00,0x02,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x80,
+ 0x00,0x02,0x02,0x00,0x00,0x00,0x80,0xB3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x18,0x00,0x02,0x00,0x00,0x04,0x08,0x44,0x00,0x41,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x00,0x00,0x00,0xE9,0x04,0x00,0x00,0x02,0x00,0x08,0x00,0x04,0x00,
+ 0x01,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xBE,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,
+ 0x00,0x00,0x00,0x00,0x34,0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x82,0xD9,0x00,0x08,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x80,
+ 0x08,0x40,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x02,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,
+ 0x00,0x00,0x10,0xCE,0x40,0x00,0x80,0x00,0x40,0x01,0x04,0x01,0x00,0x00,0x00,0x40,
+ 0x00,0x08,0x00,0x00,0x20,0x0C,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x90,0x40,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x01,
+ 0x00,0x80,0xDE,0x00,0x20,0x00,0x00,0x00,0x00,0x80,0x00,0x04,0x00,0x00,0x10,0x20,
+ 0x01,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x08,0x00,0x00,0x04,0x00,
+ 0x80,0x8C,0x00,0x00,0x08,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x04,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xC6,0x80,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x80,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0xAF,
+ 0x00,0x80,0x20,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x40,
+ 0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x42,
+ 0x00,0x80,0x00,0x00,0x50,0x10,0x00,0x02,0x08,0x00,0x00,0x00,0x00,0x00,0xF1,0x1C,
+ 0x00,0x00,0x10,0x28,0x00,0x00,0x80,0x00,0x00,0x04,0x10,0x00,0x10,0x00,0x00,0x08,
+ 0x30,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE8,0x00,0x00,
+ 0x00,0x00,0x00,0x88,0x00,0x08,0x00,0x50,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,
+ 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x04,0x80,0x82,0x00,0x08,0x30,
+ 0x00,0x80,0x00,0x02,0x00,0x10,0x10,0x0A,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x02,0x00,
+ 0x80,0x80,0x01,0x00,0x00,0x08,0x20,0x00,0x00,0x00,0x00,0xA6,0x80,0x84,0x00,0x00,
+ 0x00,0x00,0x08,0x00,0x00,0x04,0x04,0x10,0x00,0x80,0x80,0x02,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDE,0x40,0x00,0x00,0x00,0x02,
+ 0x08,0x08,0x02,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x08,0x00,0x00,0x00,0x00,0x00,
+ 0x10,0x00,0x00,0x40,0x00,0x00,0x02,0x00,0x00,0xC4,0x00,0x40,0x00,0x00,0x16,0x00,
+ 0x80,0x00,0x48,0x80,0x08,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x28,0x00,0x20,
+ 0x06,0x90,0x00,0x20,0x00,0x01,0x00,0x80,0xD2,0x00,0x00,0x40,0x00,0x00,0x00,0x04,
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x20,0x02,0x00,0x04,0x61,0x20,0x00,0x00,0x00,0x04,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x80,0x00,
+ 0x01,0x00,0x04,0x00,0x40,0x20,0x80,0xF0,0x08,0x00,0x00,0x00,0x00,0x20,0x10,0x80,
+ 0x00,0x00,0x02,0x40,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x40,0x10,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x08,0x00,0x00,0x8A,0x00,0x00,0x40,0x50,0x01,0x68,0x83,0x40,0x43,
+ 0x50,0x01,0x48,0x24,0x60,0x01,0x41,0x03,0x41,0x25,0x60,0x41,0x50,0x09,0x68,0x40,
+ 0x50,0x03,0x00,0x00,0x00,0x00,0x00,0x20,0x60,0x03,0x44,0x07,0x62,0x28,0x50,0x02,
+ 0x42,0x22,0x40,0x0B,0x00,0xC3,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x03,0x00,
+ 0x01,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x02,0x00,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0xBD,0x00,0x00,0x00,0x40,0x01,0x00,0x03,0x40,0x01,0x40,0x01,
+ 0x00,0x03,0x40,0x01,0x00,0x01,0x40,0x03,0x40,0x01,0x40,0x01,0x40,0x00,0x40,0x01,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x02,
+ 0x00,0x03,0x00,0xC8,0x02,0x00,0x00,0x40,0x25,0x40,0x15,0x60,0x25,0x40,0x25,0x50,
+ 0x03,0x44,0x25,0x50,0x19,0x60,0x10,0x40,0x25,0x40,0x01,0x41,0x26,0x40,0x8B,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x40,0x4B,0x60,0x03,0x48,0x03,0x42,0x06,0x68,0x16,0x50,
+ 0x03,0x42,0x9F,0x02,0x00,0x00,0x40,0x80,0x00,0x0A,0x40,0x00,0x40,0x80,0x00,0x03,
+ 0x40,0x00,0x00,0x28,0x60,0x00,0x40,0x00,0x44,0x80,0x40,0x00,0x44,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x40,0x20,0x83,0x10,0x03,0x14,0x0B,0x18,0x08,0x08,0x19,0x20,0x03,
+ 0xC0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x40,0x02,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x03,0x00,
+ 0x9A,0x02,0x00,0x00,0xC0,0x03,0x40,0x03,0x40,0x01,0x40,0x03,0x40,0x03,0x40,0x03,
+ 0x40,0x01,0x40,0x02,0xC0,0x03,0x40,0x03,0x40,0x03,0x40,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x03,0x40,0x02,0x40,0x03,0x40,0x00,0x40,0x00,0x40,0x03,0x40,0xD2,
+ 0x02,0x00,0x00,0x40,0x0B,0x14,0x81,0xC0,0x0A,0x02,0x0B,0x24,0x06,0xC4,0x87,0x00,
+ 0x02,0xC8,0x25,0x40,0x0B,0x11,0x27,0x10,0x87,0x10,0x24,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x29,0x00,0x8B,0x00,0x00,0x04,0x02,0x24,0x00,0x04,0x49,0x40,0xBE,0x22,
+ 0x60,0x41,0x50,0x41,0x60,0x83,0x60,0x45,0x50,0x01,0x64,0x2B,0x60,0x01,0x42,0x21,
+ 0x60,0x23,0x60,0x01,0x48,0x86,0x40,0x04,0x68,0x04,0x42,0x03,0x00,0x00,0x00,0x00,
+ 0x44,0x83,0x60,0x80,0x60,0x08,0x68,0x22,0x60,0x48,0x60,0x00,0x80,0xE5,0x00,0x00,
+ 0x01,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,
+ 0x03,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x03,0x00,0xAD,0x00,0x40,0x01,
+ 0x40,0x01,0x40,0x01,0x00,0x01,0x40,0x01,0x00,0x03,0x40,0x01,0x40,0x01,0x00,0x03,
+ 0x40,0x01,0x00,0x02,0x40,0x00,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x40,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0xC9,0x46,0x40,0x15,0x40,
+ 0x15,0x40,0x15,0x40,0x11,0x40,0x15,0x40,0x11,0x40,0x15,0x50,0x15,0x40,0x0B,0x44,
+ 0x15,0x50,0x02,0x54,0x10,0x40,0x00,0x64,0x14,0x00,0x00,0x00,0x00,0x50,0x14,0x40,
+ 0x85,0x40,0x00,0x42,0x06,0x48,0x82,0x40,0x26,0x40,0xC0,0x02,0x40,0x00,0x40,0x00,
+ 0x40,0x00,0x00,0x04,0x40,0x28,0x10,0x07,0x40,0x00,0x40,0x00,0x00,0x00,0x40,0x00,
+ 0x08,0x89,0x60,0x00,0x08,0x89,0x40,0x09,0x00,0x00,0x00,0x00,0x42,0x46,0x10,0x87,
+ 0x40,0x85,0x20,0x08,0x22,0x04,0x14,0x07,0x40,0xD3,0x02,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x01,0x40,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,
+ 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0xDE,0x02,0x40,0x03,0x40,0x03,0x40,0x01,
+ 0x40,0x03,0x40,0x03,0x40,0x03,0xC0,0x03,0x40,0x03,0x40,0x03,0x40,0x03,0x40,0x00,
+ 0x40,0x03,0x40,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x40,0x02,0x40,0x00,0xC0,0x00,
+ 0x40,0x01,0x40,0x02,0x40,0x03,0x40,0xCE,0x08,0x01,0x8B,0x00,0x87,0xC0,0x2A,0x00,
+ 0x23,0xC0,0x03,0x01,0x43,0x40,0x0B,0x01,0x0B,0x01,0x03,0x00,0x87,0xE0,0x02,0x04,
+ 0x19,0x10,0x00,0x14,0x13,0x00,0x00,0x00,0x00,0x20,0x03,0x01,0x00,0x61,0x80,0x00,
+ 0x00,0x04,0x00,0x04,0x20,0x40,0xA4,0x40,0x50,0x45,0x50,0x45,0x60,0x07,0x44,0x47,
+ 0x50,0x25,0x50,0x2B,0x60,0x05,0x42,0x05,0x48,0x02,0x44,0x45,0x40,0x43,0x60,0x41,
+ 0x50,0x00,0x68,0x00,0x48,0x07,0x00,0x00,0x44,0x07,0x44,0x84,0x60,0x84,0x40,0x87,
+ 0x60,0x10,0x60,0x08,0x80,0x8C,0x00,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x03,0x00,
+ 0x01,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x03,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x01,0x00,0xAC,0x00,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,
+ 0x00,0x03,0x40,0x01,0x40,0x01,0x00,0x02,0x00,0x03,0x40,0x03,0x00,0x01,0x00,0x03,
+ 0x40,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x40,0x02,0x00,0x00,
+ 0x00,0x00,0x00,0xDF,0x02,0x40,0x11,0x40,0x11,0x40,0x11,0x60,0x11,0x40,0x11,0x40,
+ 0x13,0x40,0x11,0x50,0x11,0x50,0x1A,0x60,0x80,0x50,0x03,0x40,0x87,0x40,0x27,0x40,
+ 0x87,0x60,0x03,0x02,0x00,0x50,0x10,0x60,0x00,0x48,0x10,0x50,0x12,0x40,0x84,0x40,
+ 0x03,0x42,0x88,0x02,0x40,0x00,0x40,0x04,0x40,0x08,0x40,0x08,0x40,0x00,0x00,0x02,
+ 0x40,0x00,0x40,0x04,0x04,0x09,0x28,0x00,0x40,0x40,0x00,0x01,0x00,0x80,0x40,0x86,
+ 0x20,0x00,0x00,0x00,0x42,0x8A,0x10,0x00,0x62,0x04,0x48,0x00,0x00,0x03,0x14,0x0B,
+ 0xC0,0xE8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x00,0x00,
+ 0x9F,0x02,0x40,0x03,0x40,0x03,0x40,0x01,0x40,0x01,0x40,0x03,0x40,0x03,0x40,0x03,
+ 0x40,0x03,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x03,0x40,0x02,0x40,0x00,
+ 0x00,0x00,0x40,0x02,0x40,0x00,0x40,0x00,0x40,0x02,0x40,0x00,0x40,0x03,0x40,0xCA,
+ 0x02,0xC0,0x8B,0x00,0x23,0x00,0x42,0xC0,0x02,0xC2,0x07,0x02,0x0B,0xC4,0x4B,0x00,
+ 0x03,0x24,0x22,0xC0,0x04,0x02,0x00,0x20,0x28,0x00,0x03,0x10,0x11,0x00,0x03,0x00,
+ 0x00,0x20,0x03,0x04,0x88,0x00,0x00,0x14,0x27,0x00,0x00,0x00,0x00,0xC1,0xED,0x40,
+ 0x50,0x49,0x50,0x09,0x44,0x83,0x40,0x43,0x50,0x09,0x54,0x28,0x60,0x09,0x42,0x49,
+ 0x40,0x27,0x60,0x09,0x61,0x06,0x48,0x0B,0x42,0x0B,0x42,0x02,0x42,0x05,0x00,0x00,
+ 0x58,0x88,0x60,0x03,0x40,0x03,0x48,0x0B,0x62,0x0B,0x48,0x0A,0xC0,0xC8,0x00,0x00,
+ 0x01,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,
+ 0x03,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0xAE,0x00,0x40,0x01,
+ 0x40,0x01,0x00,0x02,0x40,0x00,0x40,0x01,0x40,0x02,0x40,0x01,0x40,0x01,0x40,0x01,
+ 0x40,0x01,0x00,0x02,0x40,0x03,0x00,0x02,0x00,0x02,0x40,0x01,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x03,0x00,0x02,0x00,0xDB,0x02,0x40,0x11,0x40,
+ 0x11,0x60,0x0A,0x51,0x14,0x40,0x11,0x40,0x12,0x40,0x11,0x50,0x11,0x50,0x83,0x40,
+ 0x11,0x40,0x02,0x54,0x20,0x60,0x02,0x62,0x84,0x50,0x83,0x00,0x00,0x40,0x10,0x40,
+ 0x08,0x42,0x15,0x60,0x10,0x40,0x83,0x50,0x02,0x42,0x92,0x02,0x40,0x08,0x40,0x04,
+ 0x00,0x04,0x40,0x0A,0x40,0x08,0x40,0x04,0x40,0x08,0x40,0x00,0x48,0x08,0x40,0x04,
+ 0x18,0x89,0x40,0x2A,0x00,0x04,0x04,0x88,0x50,0x08,0x00,0x00,0x68,0x00,0x00,0x02,
+ 0x00,0x06,0x48,0x01,0x00,0x16,0x20,0x09,0x68,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x02,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x03,0x40,0x01,0x00,
+ 0x01,0x00,0x00,0x00,0x01,0x00,0x02,0x40,0xCD,0x02,0x40,0x03,0x40,0x03,0x40,0x02,
+ 0x40,0x02,0x40,0x03,0x80,0x01,0x40,0x03,0x40,0x03,0x40,0x00,0x40,0x03,0x40,0x01,
+ 0x40,0x02,0x40,0x02,0x40,0x00,0x40,0x00,0x80,0x00,0x40,0x03,0x40,0x02,0x40,0x03,
+ 0x40,0x01,0x40,0x03,0x40,0x01,0xC0,0xEF,0x02,0x00,0x03,0x04,0x03,0xC4,0x81,0x00,
+ 0x11,0xC0,0x43,0x40,0x12,0xC0,0x03,0x04,0x0B,0x22,0x10,0x00,0x23,0xC0,0x02,0x14,
+ 0x11,0x10,0x83,0x20,0x02,0x04,0x11,0x40,0x00,0x00,0x03,0x00,0x85,0x00,0x13,0x10,
+ 0x88,0x00,0x03,0x04,0x00,0x44,0xC8,0x40,0x50,0x41,0x50,0x01,0x61,0x0B,0x68,0x41,
+ 0x50,0x01,0x40,0x80,0x40,0x03,0x68,0x83,0x40,0x28,0x60,0x01,0x44,0x48,0x60,0x02,
+ 0x42,0x86,0x40,0x00,0x61,0x07,0x00,0x80,0x40,0x02,0x44,0x14,0x40,0x12,0x50,0x85,
+ 0x40,0x40,0x60,0x00,0x00,0xA1,0x00,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x03,0x00,
+ 0x01,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,
+ 0x02,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x03,0x00,
+ 0x03,0x00,0x03,0x00,0xBD,0x00,0x40,0x01,0x40,0x01,0x40,0x00,0x40,0x00,0x40,0x01,
+ 0x40,0x03,0x00,0x03,0x40,0x01,0x40,0x00,0x40,0x01,0x00,0x00,0x00,0x02,0x00,0x03,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0xEB,0x02,0x40,0x19,0x40,0x19,0x40,0x10,0x40,0x1A,0x40,0x19,0x40,
+ 0x18,0x60,0x16,0x40,0x19,0x50,0x10,0x40,0x19,0x60,0x00,0x44,0x87,0x60,0x80,0x60,
+ 0x03,0x40,0x10,0x00,0x00,0x60,0x18,0x60,0x00,0x58,0x47,0x40,0x00,0x52,0x18,0x40,
+ 0x27,0x40,0x8D,0x02,0x40,0x00,0x40,0x00,0x40,0x42,0x40,0x08,0x40,0x24,0x60,0x04,
+ 0x21,0x00,0x40,0x48,0x40,0x00,0x40,0x00,0x00,0x43,0x00,0x27,0x00,0x87,0x20,0x00,
+ 0x40,0x02,0x00,0x00,0x68,0x80,0x10,0x22,0x00,0x23,0x20,0x04,0x48,0x04,0x14,0x06,
+ 0x40,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x00,
+ 0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
+ 0xBD,0x02,0x40,0x03,0x40,0x03,0x40,0x02,0x40,0x02,0x40,0x03,0x00,0x01,0x40,0x02,
+ 0xC0,0x01,0xC0,0x01,0xC0,0x03,0xC0,0x00,0x40,0x00,0x40,0x01,0x40,0x00,0x40,0x02,
+ 0x00,0x00,0x40,0x03,0x40,0x00,0x40,0x00,0x40,0x03,0x40,0x03,0x40,0x03,0xC0,0xED,
+ 0x02,0x00,0x4B,0x00,0x2B,0xC0,0x19,0x10,0x01,0x04,0x03,0x02,0x10,0xC0,0x2B,0x40,
+ 0x42,0x50,0x18,0x40,0x2B,0x40,0x00,0x20,0x00,0x11,0x02,0x01,0x00,0x00,0x19,0x00,
+ 0x00,0x00,0x24,0x00,0x88,0x20,0x08,0x02,0x00,0x14,0x02,0x04,0x20,0x40,0xA3,0x00,
+ 0x48,0x2B,0x40,0x03,0x00,0x00,0x48,0x01,0x48,0x03,0x40,0x04,0x48,0x0B,0x62,0x27,
+ 0x60,0x20,0x60,0x09,0x40,0x45,0x60,0x47,0x50,0x03,0x00,0x00,0x00,0x00,0x00,0x40,
+ 0x50,0x8B,0x40,0x8B,0x40,0x08,0x41,0x20,0x60,0x2B,0x40,0x03,0x80,0xD8,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x00,
+ 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0xBC,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x00,0x40,0x03,0x40,0x00,0x40,0x03,0x00,0x02,
+ 0x40,0x01,0x00,0x03,0x00,0x03,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x40,0x03,0x00,0x00,0x40,0x03,0x00,0x03,0x00,0x03,0x00,0x8B,0x02,0x50,0x23,0x50,
+ 0x07,0x01,0x00,0x50,0x25,0x50,0x0B,0x41,0x00,0x52,0x43,0x40,0x00,0x41,0x0A,0x44,
+ 0x01,0x41,0x23,0x40,0x00,0x41,0x1A,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x11,0x50,
+ 0x13,0x60,0x00,0x52,0x89,0x40,0x11,0x50,0x4B,0x40,0xCB,0x42,0x50,0x00,0x21,0x0B,
+ 0x00,0x40,0x40,0x48,0x50,0x00,0x48,0x24,0x60,0x00,0x48,0x00,0x00,0x06,0x40,0x04,
+ 0x00,0x0B,0x14,0x07,0x48,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x40,0x04,
+ 0x00,0x04,0x48,0x82,0x20,0x4A,0x20,0x05,0x40,0xA1,0x00,0x00,0x00,0x40,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x00,0x00,
+ 0x03,0x40,0x03,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x40,0x01,0x00,0x03,0x00,0xB8,0x02,0x40,0x00,0x40,0x03,0x00,0x00,
+ 0x40,0x01,0x40,0x00,0x00,0x01,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x03,0x40,0x02,
+ 0x40,0x03,0x40,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x01,0x40,0x01,
+ 0x40,0x00,0x40,0x03,0x40,0x03,0x40,0x98,0x02,0xC0,0x03,0x00,0x81,0x00,0x00,0x10,
+ 0x00,0xC4,0x03,0x10,0x10,0xC0,0x03,0x10,0x00,0xC0,0x00,0xC2,0x03,0x02,0x41,0x00,
+ 0x83,0x10,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x82,0x00,0x82,0x00,0x82,0x10,
+ 0x18,0xC0,0x03,0x04,0x23,0xC0,0xE0,0x82,0x50,0x25,0x40,0x03,0x00,0x00,0x48,0x07,
+ 0x58,0x03,0x40,0x04,0x54,0x83,0x60,0x85,0x40,0x01,0x58,0x07,0x40,0x47,0x60,0x0B,
+ 0x54,0x04,0x42,0x80,0x40,0x05,0x00,0x20,0x60,0x86,0x60,0x10,0x40,0x22,0x50,0x03,
+ 0x48,0x09,0x58,0x05,0x40,0xEF,0x00,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x03,0x00,
+ 0x03,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x9D,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x40,0x03,0x40,0x02,
+ 0x40,0x03,0x00,0x01,0x40,0x00,0x40,0x01,0x40,0x00,0x00,0x01,0x00,0x03,0x00,0x00,
+ 0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,
+ 0x40,0x01,0x00,0xED,0x46,0x40,0x00,0x52,0x24,0x00,0x00,0x60,0x00,0x41,0x0A,0x44,
+ 0x80,0x40,0x27,0x40,0x00,0x58,0x14,0x40,0x03,0x44,0x21,0x40,0x23,0x40,0x00,0x64,
+ 0x85,0x50,0x20,0x00,0x00,0x40,0x13,0x40,0x0B,0x52,0x47,0x40,0x04,0x68,0x13,0x40,
+ 0x01,0xC2,0xE4,0x06,0x04,0x03,0x21,0x02,0x00,0x00,0x58,0x00,0x40,0x00,0x58,0x04,
+ 0x21,0x03,0x52,0x00,0x58,0x24,0x60,0x00,0x00,0x0A,0x14,0x04,0x00,0x43,0x00,0x42,
+ 0x20,0x08,0x00,0x40,0x20,0x47,0x10,0x21,0x00,0x03,0x01,0x05,0x28,0x0B,0x44,0x00,
+ 0x48,0xF6,0x02,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,
+ 0x00,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x40,0x03,0x40,0x00,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x40,
+ 0x9A,0x02,0x40,0x03,0x40,0x02,0x00,0x00,0x40,0x00,0x40,0x02,0x00,0x01,0x40,0x03,
+ 0x40,0x02,0x40,0x01,0x40,0x00,0x40,0x03,0x40,0x02,0x40,0x00,0xC0,0x00,0x40,0x00,
+ 0x00,0x00,0x40,0x03,0x40,0x01,0x40,0x02,0x40,0x01,0x40,0x02,0x40,0x01,0xC0,0xDA,
+ 0x40,0x20,0x07,0x04,0x07,0xC2,0x00,0x00,0x00,0x00,0x29,0x00,0x10,0xC0,0x2A,0xC0,
+ 0x29,0x00,0x13,0x00,0x03,0x00,0x43,0x00,0x83,0x00,0x00,0x60,0x1A,0x00,0x11,0x00,
+ 0x00,0x00,0x42,0x00,0x84,0x20,0x28,0x10,0x23,0x00,0x01,0x14,0x18,0xE0,0xB4,0x82,
+ 0x40,0x23,0x40,0x03,0x68,0x07,0x68,0x23,0x40,0x03,0x40,0x04,0x52,0x07,0x44,0x49,
+ 0x40,0x2A,0x40,0x03,0x48,0x46,0x40,0x0B,0x54,0x08,0x42,0x03,0x44,0x07,0x00,0x00,
+ 0x64,0x84,0x50,0x04,0x58,0x00,0x48,0x81,0x60,0x0B,0x62,0x07,0x40,0x99,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x01,0x00,
+ 0x02,0x00,0x03,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x9F,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x02,0x40,0x02,0x00,0x00,0x40,0x03,0x00,0x02,0x00,0x01,0x00,0x02,
+ 0x00,0x00,0x00,0x02,0x00,0x03,0x40,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x00,0x00,0x03,0x00,0x00,0x40,0x00,0x00,0xAD,0x46,0x50,0x1B,0x50,
+ 0x17,0x40,0x02,0x41,0x8A,0x50,0x17,0x40,0x00,0x41,0x13,0x60,0x01,0x51,0x10,0x50,
+ 0x17,0x60,0x02,0x64,0x20,0x40,0x10,0x60,0x85,0x60,0x23,0x00,0x00,0x40,0x82,0x40,
+ 0x00,0x48,0x1A,0x50,0x0B,0x44,0x00,0x42,0x00,0x48,0xAF,0x0A,0x21,0x07,0x21,0x07,
+ 0x40,0x00,0x40,0x80,0x10,0x0B,0x68,0x04,0x21,0x03,0x00,0x04,0x08,0x09,0x21,0x0B,
+ 0x18,0x09,0x14,0x01,0x40,0x85,0x20,0x2A,0x00,0x09,0x00,0x20,0x00,0x08,0x04,0x82,
+ 0x60,0x24,0x20,0x07,0x00,0x03,0x44,0x06,0x44,0xEA,0x02,0x40,0x01,0x40,0x01,0x00,
+ 0x00,0x00,0x00,0x40,0x01,0x00,0x02,0x40,0x00,0x40,0x00,0x00,0x02,0x40,0x01,0x00,
+ 0x02,0x40,0x03,0x40,0x02,0x40,0x03,0x00,0x03,0x00,0x00,0x40,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x03,0x40,0x03,0x00,0x00,0x40,0xAE,0x02,0x40,0x03,0x40,0x03,0x40,0x02,
+ 0x40,0x02,0x40,0x03,0x00,0x01,0xC0,0x03,0x40,0x02,0xC0,0x00,0xC0,0x03,0x40,0x00,
+ 0x40,0x03,0x40,0x03,0x40,0x02,0x40,0x03,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x02,
+ 0x40,0x01,0x40,0x03,0x40,0x02,0x40,0xD5,0x00,0xC4,0x11,0x00,0x11,0x00,0x29,0xC0,
+ 0x09,0xC2,0x11,0x00,0x10,0x40,0x29,0x00,0x41,0x60,0x22,0x40,0x11,0xC0,0x02,0x04,
+ 0x87,0xC0,0x03,0x04,0x03,0x14,0x13,0x00,0x00,0x10,0x40,0x20,0x88,0x00,0x80,0x00,
+ 0x03,0x02,0x03,0x10,0x00,0xE2,0xA8,0x00,0x48,0x2B,0x40,0x0B,0x48,0x83,0x60,0x09,
+ 0x48,0x03,0x40,0x00,0x48,0x0B,0x40,0x0A,0x44,0x03,0x58,0x03,0x40,0x03,0x54,0x43,
+ 0x50,0x03,0x42,0x01,0x48,0x07,0x00,0x40,0x60,0x02,0x44,0x07,0x00,0x00,0x68,0x06,
+ 0x62,0x08,0x48,0x07,0xC0,0xE7,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x01,0x00,
+ 0x03,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,
+ 0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x02,0x00,
+ 0x00,0x00,0x03,0x00,0x9E,0x00,0x00,0x01,0x00,0x03,0x40,0x02,0x00,0x01,0x00,0x03,
+ 0x40,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x03,0x00,0x03,
+ 0x00,0x01,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,
+ 0x40,0x03,0x00,0xFB,0x02,0x50,0x13,0x50,0x10,0x60,0x0A,0x41,0x01,0x51,0x25,0x40,
+ 0x8B,0x50,0x12,0x40,0x00,0x62,0x18,0x40,0x19,0x40,0x4A,0x40,0x2B,0x40,0x27,0x60,
+ 0x87,0x60,0x03,0x01,0x00,0x40,0x48,0x60,0x01,0x08,0x00,0x40,0x02,0x48,0x80,0x60,
+ 0x11,0xC0,0xFE,0x82,0x00,0x06,0x21,0x02,0x40,0x00,0x00,0x80,0x10,0x00,0x40,0x05,
+ 0x21,0x00,0x00,0x00,0x00,0x03,0x21,0x00,0x00,0x01,0x00,0x05,0x08,0x46,0x00,0x0B,
+ 0x58,0x00,0x00,0x00,0x00,0x80,0x10,0x03,0x00,0x00,0x00,0x08,0x00,0x04,0x44,0x06,
+ 0x58,0xAA,0x00,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x02,0x00,
+ 0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0x02,0x00,0x03,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x40,
+ 0xC8,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x03,0x40,0x01,0x00,0x00,0xC0,0x02,
+ 0xC0,0x01,0xC0,0x03,0x40,0x01,0x40,0x03,0x40,0x00,0x40,0x03,0x40,0x03,0x40,0x00,
+ 0x00,0x00,0x40,0x00,0x40,0x03,0x00,0x00,0x40,0x01,0xC0,0x02,0x40,0x00,0x40,0xA4,
+ 0x02,0x10,0x03,0xC1,0x1B,0x00,0x29,0xC0,0x0B,0x04,0x07,0x08,0x10,0x40,0x2B,0x40,
+ 0x2A,0x40,0x03,0xC0,0x8B,0x00,0x2B,0x00,0x80,0x10,0x03,0xE4,0x03,0x04,0x03,0x00,
+ 0x00,0x00,0x28,0x00,0x8B,0x00,0x00,0x00,0x02,0x44,0x01,0x14,0x00,0x42,0xF6,0x82,
+ 0x60,0x09,0x48,0x05,0x44,0x2A,0x60,0x05,0x40,0x23,0x50,0x03,0x58,0x81,0x60,0x81,
+ 0x40,0x2B,0x40,0x4B,0x60,0x03,0x00,0x00,0x44,0x03,0x42,0x80,0x50,0x07,0x00,0x00,
+ 0x48,0x0B,0x40,0x03,0x44,0x0B,0x44,0x83,0x40,0x83,0x60,0x01,0x40,0xED,0x00,0x00,
+ 0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x01,0x00,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x03,0x00,0x03,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x9C,0x00,0x00,0x00,
+ 0x00,0x01,0x40,0x03,0x00,0x01,0x40,0x00,0x00,0x03,0x00,0x03,0x40,0x01,0x40,0x03,
+ 0x00,0x00,0x40,0x03,0x00,0x00,0x40,0x02,0x00,0x03,0x40,0x03,0x00,0x00,0x40,0x03,
+ 0x40,0x01,0x40,0x03,0x40,0x03,0x40,0x00,0x40,0x00,0x00,0xBD,0x46,0x40,0x00,0x51,
+ 0x80,0x60,0x03,0x42,0x80,0x40,0x04,0x41,0x0B,0x44,0x04,0x42,0x08,0x52,0x13,0x50,
+ 0x03,0x41,0x03,0x00,0x00,0x60,0x0A,0x62,0x85,0x40,0x80,0x00,0x00,0x50,0x00,0x48,
+ 0x05,0x62,0x00,0x61,0x89,0x50,0x24,0x40,0x04,0x84,0xC2,0x02,0x28,0x00,0x28,0x00,
+ 0x42,0x48,0x20,0x04,0x40,0x00,0x04,0x06,0x28,0x00,0x44,0x44,0x40,0x03,0x21,0x03,
+ 0x40,0x00,0x00,0x00,0x40,0x40,0x00,0x02,0x44,0x0A,0x00,0x00,0x44,0x00,0x40,0x06,
+ 0x51,0x00,0x48,0x00,0x44,0x05,0x42,0x00,0x40,0x9D,0x02,0x40,0x01,0x40,0x01,0x40,
+ 0x00,0x40,0x00,0x40,0x00,0x00,0x01,0x40,0x03,0x40,0x01,0x40,0x01,0x40,0x01,0x40,
+ 0x00,0x40,0x00,0x40,0x00,0x40,0x03,0x40,0x01,0x40,0x00,0x40,0x03,0x40,0x01,0x40,
+ 0x00,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x8D,0x02,0x80,0x00,0x00,0x00,0x80,0x00,
+ 0x00,0x00,0x80,0x03,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x00,
+ 0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x01,
+ 0x00,0x01,0x00,0x00,0x00,0x02,0x00,0xBD,0x08,0x42,0x85,0x00,0x44,0x50,0x02,0x04,
+ 0x41,0x40,0x03,0x20,0x43,0x00,0x18,0x20,0x03,0xD8,0x1B,0xC0,0x25,0x00,0x00,0x00,
+ 0x00,0x00,0x15,0x20,0x19,0xE0,0x00,0x01,0x00,0x20,0x00,0x00,0x83,0x00,0x08,0x14,
+ 0x16,0xE0,0x03,0x14,0x1B,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x20,0xA5,0x00,0x02,0x02,0x02,0x00,0x42,0x00,0x82,0x02,0x82,
+ 0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x42,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
+ 0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x82,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
+ 0x00,0x02,0x00,0xA0,0xB4,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0x10,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0x08,0x04,0x00,0x00,0x00,0x00,0x02,0x00,
+ 0x42,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x10,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0xB9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x01,
+ 0x00,0x80,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xBD,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,
+ 0x00,0x00,0x21,0x40,0x21,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x20,
+ 0x01,0x00,0x00,0x00,0x02,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xC0,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x10,0x00,0x01,0x00,0x10,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xCC,0x00,0x00,0x20,0x40,0x00,0x00,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,
+ 0x40,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x40,0x00,0x40,0x00,0xC4,0x00,0x40,0x00,
+ 0x00,0x00,0x10,0x08,0x00,0x40,0x40,0x00,0x10,0x00,0x40,0x00,0x50,0x00,0xC0,0x93,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x10,
+ 0x08,0x10,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
+ 0x00,0x00,0x08,0x00,0x00,0x04,0x00,0x00,0x00,0x40,0x0C,0x00,0x00,0x80,0xC2,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x00,0x0A,0x80,0x03,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x40,0x00,0x00,0x00,0x00,
+ 0x00,0xC0,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x04,0x00,0x40,0x00,0xE7,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x40,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xD6,0x00,0x02,0x00,
+ 0x00,0x40,0x04,0x04,0x10,0x10,0x00,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x08,0x00,0x00,0xA4,0x40,0x00,0x00,0x80,0xD3,0x80,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x02,0x00,0x00,
+ 0x04,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x00,0x00,0x00,0x00,0x00,
+ 0x03,0x40,0x00,0x00,0x12,0x00,0x00,0x20,0x40,0x00,0x00,0x00,0x12,0x00,0x00,0x00,
+ 0x00,0x80,0x00,0x80,0x20,0x80,0x00,0x80,0x02,0x00,0x00,0x00,0x00,0x80,0x10,0x00,
+ 0x00,0x82,0x00,0x80,0x00,0x04,0x00,0x00,0x80,0xF8,0x02,0x00,0x80,0x00,0x00,0x00,
+ 0x08,0x00,0x00,0x10,0x08,0x00,0x02,0x04,0x00,0x10,0x04,0x00,0x02,0x00,0x00,0x04,
+ 0x10,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAE,0x02,0x00,0x00,0x00,0x00,0x00,0xA0,
+ 0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x24,0x10,0x00,0x00,0x02,0x02,0x08,
+ 0x01,0x00,0x80,0x00,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x20,0x00,0x00,0x08,0xF2,0x80,0x00,0x08,0x00,0x82,0x00,0x00,0x20,
+ 0x1A,0x20,0x00,0x41,0x80,0x00,0x18,0x04,0x04,0x00,0x08,0x00,0x82,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xB6,0x84,0x00,0x00,0x04,0x80,0x00,0x00,0x00,0x20,
+ 0x00,0x00,0x70,0x84,0x04,0x00,0x09,0x00,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x00,
+ 0x10,0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x08,0x00,0x00,0x00,
+ 0x04,0x00,0x00,0x00,0x00,0x99,0x0C,0x00,0x08,0x00,0x00,0x08,0x08,0x00,0x08,0x00,
+ 0x04,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x40,0x00,0x00,0x20,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x88,0x00,0x00,0x00,0x02,0x00,0x04,0x02,0x00,0x80,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0x05,0x00,0x20,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x11,0x02,0x00,0x02,0x00,0x04,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x06,0x01,0xF3,0x04,0x20,0x00,0x00,0x08,0x00,0x24,0x00,0x00,0x00,0x80,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x40,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x20,0x00,0x40,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xD2,0x10,0x42,0x10,0x02,0x20,0x00,0x90,0x00,0x80,0x01,0x10,0x10,0x10,
+ 0x02,0x00,0x00,0x10,0x00,0x00,0x06,0x10,0x00,0x30,0x00,0x00,0x00,0x10,0x00,0x00,
+ 0x00,0x00,0x02,0x00,0x11,0x00,0x04,0x00,0x00,0x10,0x20,0x00,0x01,0x00,0x00,0x00,
+ 0x90,0x85,0x00,0x04,0x00,0x00,0x00,0x40,0x00,0x02,0x00,0x14,0x22,0x11,0x04,0x04,
+ 0x80,0x00,0x40,0x00,0x80,0x00,0x00,0x40,0x40,0x00,0x00,0x04,0x40,0x00,0x00,0x00,
+ 0x80,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x40,0x00,0x42,0x00,0x80,0x00,0x00,0x00,
+ 0xB1,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x00,0x00,0x00,
+ 0x00,0x04,0x00,0x80,0x00,0x20,0x00,0x04,0x40,0x00,0x00,0x20,0x00,0x00,0x80,0xDB,
+ 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x08,0x00,0x80,0x04,0x00,
+ 0x00,0x80,0x20,0x00,0x20,0x08,0x08,0x00,0x04,0x00,0x00,0x20,0x00,0x20,0x00,0x08,
+ 0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,
+ 0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x04,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x02,0x20,0x10,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,
+ 0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x0C,0x00,0x80,0x20,0x00,0x80,0xF1,0x00,0x00,
+ 0x00,0x00,0x00,0x40,0x00,0x01,0x00,0x08,0x80,0x00,0x00,0x00,0x00,0x80,0x02,0x10,
+ 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x00,0x00,0x84,
+ 0x00,0x00,0x20,0x00,0x00,0x08,0x00,0x02,0x00,0x00,0x00,0x24,0x00,0x00,0x04,0x02,
+ 0x00,0x80,0x00,0x08,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x08,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0x00,0x04,0x00,0x00,
+ 0x00,0x00,0x00,0x81,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x08,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x40,0x00,0x04,0x01,0x00,
+ 0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x50,0x00,0x00,0x00,
+ 0x10,0x04,0x00,0x40,0x00,0x10,0x00,0x08,0x10,0x00,0x00,0x00,0x54,0x08,0x00,0x00,
+ 0x02,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0x80,0x00,0x20,0x00,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0x20,0x00,0x08,0x00,0x80,0x00,0x00,0x80,0x00,0x20,0x00,0x01,
+ 0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x08,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x02,0x10,0x00,0x80,0x95,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x06,0x00,0x00,0xA0,0x20,0x80,0x00,0x00,0x02,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x44,0x00,0x00,0xCD,0x00,0x00,0x02,0x80,0x00,0x00,0x02,0x00,
+ 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x40,0x00,0x02,0x00,0x00,0x00,0x20,0x00,0x20,
+ 0x08,0x00,0x00,0x10,0x00,0x80,0xE3,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x40,0x00,0x00,0x40,0x40,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x02,0x00,0x00,0x00,0x98,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x40,0x00,0x00,0xFC,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,
+ 0x00,0x02,0x00,0x00,0x00,0x02,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x02,0x00,0x00,
+ 0x00,0x02,0x40,0x00,0x40,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
+ 0x40,0x00,0x00,0xF8,0x00,0x00,0x46,0x40,0x02,0x40,0x46,0x40,0x06,0x44,0x46,0x40,
+ 0x46,0x40,0x02,0x40,0x46,0x60,0x02,0x40,0x02,0x60,0x02,0x40,0x02,0x40,0x02,0x40,
+ 0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x00,
+ 0x00,0x00,0x9A,0x00,0x00,0x0A,0x40,0x02,0x40,0x0A,0x40,0x0A,0x40,0x0A,0x40,0x02,
+ 0x40,0x02,0x40,0x02,0x62,0x02,0x40,0x02,0x42,0x02,0x40,0x02,0x40,0x02,0x40,0x02,
+ 0x42,0x42,0x60,0x02,0x40,0x06,0x40,0x0A,0x40,0x06,0x40,0x02,0x40,0x02,0x40,0x00,
+ 0x00,0x90,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,
+ 0x00,0x00,0x02,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x40,
+ 0x00,0x40,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x40,0x00,0x00,
+ 0xF8,0x00,0x00,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,
+ 0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,
+ 0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x00,0x00,0x00,0xFE,
+ 0x00,0x00,0x80,0x40,0x02,0x40,0x00,0x41,0x10,0x40,0x80,0x40,0x48,0x40,0x02,0x40,
+ 0x84,0x00,0x02,0x40,0x02,0x10,0x02,0x40,0x06,0x41,0x02,0x40,0x46,0x60,0x02,0x40,
+ 0x0A,0x41,0x02,0x44,0x02,0x42,0x42,0x40,0x2A,0x40,0x00,0x00,0x00,0x00,0x92,0xFF,
+ 0xFF,
+};
diff --git a/sys/src/9/pc/i8253.c b/sys/src/9/pc/i8253.c
new file mode 100755
index 000000000..0e22c0a6e
--- /dev/null
+++ b/sys/src/9/pc/i8253.c
@@ -0,0 +1,316 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ * 8253 timer
+ */
+enum
+{
+ T0cntr= 0x40, /* counter ports */
+ T1cntr= 0x41, /* ... */
+ T2cntr= 0x42, /* ... */
+ Tmode= 0x43, /* mode port (control word register) */
+ T2ctl= 0x61, /* counter 2 control port */
+
+ /* commands */
+ Latch0= 0x00, /* latch counter 0's value */
+ Load0l= 0x10, /* load counter 0's lsb */
+ Load0m= 0x20, /* load counter 0's msb */
+ Load0= 0x30, /* load counter 0 with 2 bytes */
+
+ Latch1= 0x40, /* latch counter 1's value */
+ Load1l= 0x50, /* load counter 1's lsb */
+ Load1m= 0x60, /* load counter 1's msb */
+ Load1= 0x70, /* load counter 1 with 2 bytes */
+
+ Latch2= 0x80, /* latch counter 2's value */
+ Load2l= 0x90, /* load counter 2's lsb */
+ Load2m= 0xa0, /* load counter 2's msb */
+ Load2= 0xb0, /* load counter 2 with 2 bytes */
+
+ /* 8254 read-back command: everything > pc-at has an 8254 */
+ Rdback= 0xc0, /* readback counters & status */
+ Rdnstat=0x10, /* don't read status */
+ Rdncnt= 0x20, /* don't read counter value */
+ Rd0cntr=0x02, /* read back for which counter */
+ Rd1cntr=0x04,
+ Rd2cntr=0x08,
+
+ /* modes */
+ ModeMsk=0xe,
+ Square= 0x6, /* periodic square wave */
+ Trigger=0x0, /* interrupt on terminal count */
+ Sstrobe=0x8, /* software triggered strobe */
+
+ /* T2ctl bits */
+ T2gate= (1<<0), /* enable T2 counting */
+ T2spkr= (1<<1), /* connect T2 out to speaker */
+ T2out= (1<<5), /* output of T2 */
+
+ Freq= 1193182, /* Real clock frequency */
+ Tickshift=8, /* extra accuracy */
+ MaxPeriod=Freq/HZ,
+ MinPeriod=Freq/(100*HZ),
+};
+
+typedef struct I8253 I8253;
+struct I8253
+{
+ Lock;
+ ulong period; /* current clock period */
+ int enabled;
+ uvlong hz;
+
+ ushort last; /* last value of clock 1 */
+ uvlong ticks; /* cumulative ticks of counter 1 */
+
+ ulong periodset;
+};
+I8253 i8253;
+
+void
+i8253init(void)
+{
+ int loops, x;
+
+ ioalloc(T0cntr, 4, 0, "i8253");
+ ioalloc(T2ctl, 1, 0, "i8253.cntr2ctl");
+
+ i8253.period = Freq/HZ;
+
+ /*
+ * enable a 1/HZ interrupt for providing scheduling interrupts
+ */
+ outb(Tmode, Load0|Square);
+ outb(T0cntr, (Freq/HZ)); /* low byte */
+ outb(T0cntr, (Freq/HZ)>>8); /* high byte */
+
+ /*
+ * enable a longer period counter to use as a clock
+ */
+ outb(Tmode, Load2|Square);
+ outb(T2cntr, 0); /* low byte */
+ outb(T2cntr, 0); /* high byte */
+ x = inb(T2ctl);
+ x |= T2gate;
+ outb(T2ctl, x);
+
+ /*
+ * Introduce a little delay to make sure the count is
+ * latched and the timer is counting down; with a fast
+ * enough processor this may not be the case.
+ * The i8254 (which this probably is) has a read-back
+ * command which can be used to make sure the counting
+ * register has been written into the counting element.
+ */
+ x = (Freq/HZ);
+ for(loops = 0; loops < 100000 && x >= (Freq/HZ); loops++){
+ outb(Tmode, Latch0);
+ x = inb(T0cntr);
+ x |= inb(T0cntr)<<8;
+ }
+}
+
+void
+guesscpuhz(int aalcycles)
+{
+ int loops, incr, x, y;
+ uvlong a, b, cpufreq;
+
+ /* find biggest loop that doesn't wrap */
+ incr = 16000000/(aalcycles*HZ*2);
+ x = 2000;
+ for(loops = incr; loops < 64*1024; loops += incr) {
+
+ /*
+ * measure time for the loop
+ *
+ * MOVL loops,CX
+ * aaml1: AAM
+ * LOOP aaml1
+ *
+ * the time for the loop should be independent of external
+ * cache and memory system since it fits in the execution
+ * prefetch buffer.
+ *
+ */
+ outb(Tmode, Latch0);
+ cycles(&a);
+ x = inb(T0cntr);
+ x |= inb(T0cntr)<<8;
+ aamloop(loops);
+ outb(Tmode, Latch0);
+ cycles(&b);
+ y = inb(T0cntr);
+ y |= inb(T0cntr)<<8;
+ x -= y;
+
+ if(x < 0)
+ x += Freq/HZ;
+
+ if(x > Freq/(3*HZ))
+ break;
+ }
+
+ /*
+ * figure out clock frequency and a loop multiplier for delay().
+ * n.b. counter goes up by 2*Freq
+ */
+ if(x == 0)
+ x = 1; /* avoid division by zero on vmware 7 */
+ cpufreq = (vlong)loops*((aalcycles*2*Freq)/x);
+ m->loopconst = (cpufreq/1000)/aalcycles; /* AAM+LOOP's for 1 ms */
+
+ if(m->havetsc){
+ /* counter goes up by 2*Freq */
+ b = (b-a)<<1;
+ b *= Freq;
+ b /= x;
+
+ /*
+ * round to the nearest megahz
+ */
+ m->cpumhz = (b+500000)/1000000L;
+ m->cpuhz = b;
+ m->cyclefreq = b;
+ } else {
+ /*
+ * add in possible 0.5% error and convert to MHz
+ */
+ m->cpumhz = (cpufreq + cpufreq/200)/1000000;
+ m->cpuhz = cpufreq;
+ }
+
+ i8253.hz = Freq<<Tickshift;
+}
+
+void
+i8253timerset(uvlong next)
+{
+ long period;
+ ulong want;
+ ulong now;
+
+ period = MaxPeriod;
+ if(next != 0){
+ want = next>>Tickshift;
+ now = i8253.ticks; /* assuming whomever called us just did fastticks() */
+
+ period = want - now;
+ if(period < MinPeriod)
+ period = MinPeriod;
+ else if(period > MaxPeriod)
+ period = MaxPeriod;
+ }
+
+ /* hysteresis */
+ if(i8253.period != period){
+ ilock(&i8253);
+ /* load new value */
+ outb(Tmode, Load0|Square);
+ outb(T0cntr, period); /* low byte */
+ outb(T0cntr, period >> 8); /* high byte */
+
+ /* remember period */
+ i8253.period = period;
+ i8253.periodset++;
+ iunlock(&i8253);
+ }
+}
+
+static void
+i8253clock(Ureg* ureg, void*)
+{
+ timerintr(ureg, 0);
+}
+
+void
+i8253enable(void)
+{
+ i8253.enabled = 1;
+ i8253.period = Freq/HZ;
+ intrenable(IrqCLOCK, i8253clock, 0, BUSUNKNOWN, "clock");
+}
+
+void
+i8253link(void)
+{
+}
+
+/*
+ * return the total ticks of counter 2. We shift by
+ * 8 to give timesync more wriggle room for interpretation
+ * of the frequency
+ */
+uvlong
+i8253read(uvlong *hz)
+{
+ ushort y, x;
+ uvlong ticks;
+
+ if(hz)
+ *hz = i8253.hz;
+
+ ilock(&i8253);
+ outb(Tmode, Latch2);
+ y = inb(T2cntr);
+ y |= inb(T2cntr)<<8;
+
+ if(y < i8253.last)
+ x = i8253.last - y;
+ else {
+ x = i8253.last + (0x10000 - y);
+ if (x > 3*MaxPeriod) {
+ outb(Tmode, Load2|Square);
+ outb(T2cntr, 0); /* low byte */
+ outb(T2cntr, 0); /* high byte */
+ y = 0xFFFF;
+ x = i8253.period;
+ }
+ }
+ i8253.last = y;
+ i8253.ticks += x>>1;
+ ticks = i8253.ticks;
+ iunlock(&i8253);
+
+ return ticks<<Tickshift;
+}
+
+void
+delay(int millisecs)
+{
+ millisecs *= m->loopconst;
+ if(millisecs <= 0)
+ millisecs = 1;
+ aamloop(millisecs);
+}
+
+void
+microdelay(int microsecs)
+{
+ microsecs *= m->loopconst;
+ microsecs /= 1000;
+ if(microsecs <= 0)
+ microsecs = 1;
+ aamloop(microsecs);
+}
+
+/*
+ * performance measurement ticks. must be low overhead.
+ * doesn't have to count over a second.
+ */
+ulong
+perfticks(void)
+{
+ uvlong x;
+
+ if(m->havetsc)
+ cycles(&x);
+ else
+ x = 0;
+ return x;
+}
diff --git a/sys/src/9/pc/i8259.c b/sys/src/9/pc/i8259.c
new file mode 100755
index 000000000..cfe1a5a42
--- /dev/null
+++ b/sys/src/9/pc/i8259.c
@@ -0,0 +1,214 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ * 8259 interrupt controllers
+ */
+enum
+{
+ Int0ctl= 0x20, /* control port (ICW1, OCW2, OCW3) */
+ Int0aux= 0x21, /* everything else (ICW2, ICW3, ICW4, OCW1) */
+ Int1ctl= 0xA0, /* control port */
+ Int1aux= 0xA1, /* everything else (ICW2, ICW3, ICW4, OCW1) */
+
+ Icw1= 0x10, /* select bit in ctl register */
+ Ocw2= 0x00,
+ Ocw3= 0x08,
+
+ EOI= 0x20, /* non-specific end of interrupt */
+
+ Elcr1= 0x4D0, /* Edge/Level Triggered Register */
+ Elcr2= 0x4D1,
+};
+
+static Lock i8259lock;
+static int i8259mask = 0xFFFF; /* disabled interrupts */
+int i8259elcr; /* mask of level-triggered interrupts */
+
+void
+i8259init(void)
+{
+ int x;
+
+ ioalloc(Int0ctl, 2, 0, "i8259.0");
+ ioalloc(Int1ctl, 2, 0, "i8259.1");
+ ilock(&i8259lock);
+
+ /*
+ * Set up the first 8259 interrupt processor.
+ * Make 8259 interrupts start at CPU vector VectorPIC.
+ * Set the 8259 as master with edge triggered
+ * input with fully nested interrupts.
+ */
+ outb(Int0ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered,
+ ICW4 will be sent */
+ outb(Int0aux, VectorPIC); /* ICW2 - interrupt vector offset */
+ outb(Int0aux, 0x04); /* ICW3 - have slave on level 2 */
+ outb(Int0aux, 0x01); /* ICW4 - 8086 mode, not buffered */
+
+ /*
+ * Set up the second 8259 interrupt processor.
+ * Make 8259 interrupts start at CPU vector VectorPIC+8.
+ * Set the 8259 as slave with edge triggered
+ * input with fully nested interrupts.
+ */
+ outb(Int1ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered,
+ ICW4 will be sent */
+ outb(Int1aux, VectorPIC+8); /* ICW2 - interrupt vector offset */
+ outb(Int1aux, 0x02); /* ICW3 - I am a slave on level 2 */
+ outb(Int1aux, 0x01); /* ICW4 - 8086 mode, not buffered */
+ outb(Int1aux, (i8259mask>>8) & 0xFF);
+
+ /*
+ * pass #2 8259 interrupts to #1
+ */
+ i8259mask &= ~0x04;
+ outb(Int0aux, i8259mask & 0xFF);
+
+ /*
+ * Set Ocw3 to return the ISR when ctl read.
+ * After initialisation status read is set to IRR.
+ * Read IRR first to possibly deassert an outstanding
+ * interrupt.
+ */
+ inb(Int0ctl);
+ outb(Int0ctl, Ocw3|0x03);
+ inb(Int1ctl);
+ outb(Int1ctl, Ocw3|0x03);
+
+ /*
+ * Check for Edge/Level register.
+ * This check may not work for all chipsets.
+ * First try a non-intrusive test - the bits for
+ * IRQs 13, 8, 2, 1 and 0 must be edge (0). If
+ * that's OK try a R/W test.
+ */
+ x = (inb(Elcr2)<<8)|inb(Elcr1);
+ if(!(x & 0x2107)){
+ outb(Elcr1, 0);
+ if(inb(Elcr1) == 0){
+ outb(Elcr1, 0x20);
+ if(inb(Elcr1) == 0x20)
+ i8259elcr = x;
+ outb(Elcr1, x & 0xFF);
+ print("ELCR: %4.4uX\n", i8259elcr);
+ }
+ }
+ iunlock(&i8259lock);
+}
+
+int
+i8259isr(int vno)
+{
+ int irq, isr;
+
+ if(vno < VectorPIC || vno > VectorPIC+MaxIrqPIC)
+ return 0;
+ irq = vno-VectorPIC;
+
+ /*
+ * tell the 8259 that we're done with the
+ * highest level interrupt (interrupts are still
+ * off at this point)
+ */
+ ilock(&i8259lock);
+ isr = inb(Int0ctl);
+ outb(Int0ctl, EOI);
+ if(irq >= 8){
+ isr |= inb(Int1ctl)<<8;
+ outb(Int1ctl, EOI);
+ }
+ iunlock(&i8259lock);
+
+ return isr & (1<<irq);
+}
+
+int
+i8259enable(Vctl* v)
+{
+ int irq, irqbit;
+
+ /*
+ * Given an IRQ, enable the corresponding interrupt in the i8259
+ * and return the vector to be used. The i8259 is set to use a fixed
+ * range of vectors starting at VectorPIC.
+ */
+ irq = v->irq;
+ if(irq < 0 || irq > MaxIrqPIC){
+ print("i8259enable: irq %d out of range\n", irq);
+ return -1;
+ }
+ irqbit = 1<<irq;
+
+ ilock(&i8259lock);
+ if(!(i8259mask & irqbit) && !(i8259elcr & irqbit)){
+ print("i8259enable: irq %d shared but not level\n", irq);
+ iunlock(&i8259lock);
+ return -1;
+ }
+ i8259mask &= ~irqbit;
+ if(irq < 8)
+ outb(Int0aux, i8259mask & 0xFF);
+ else
+ outb(Int1aux, (i8259mask>>8) & 0xFF);
+
+ if(i8259elcr & irqbit)
+ v->eoi = i8259isr;
+ else
+ v->isr = i8259isr;
+ iunlock(&i8259lock);
+
+ return VectorPIC+irq;
+}
+
+int
+i8259vecno(int irq)
+{
+ return VectorPIC+irq;
+}
+
+int
+i8259disable(int irq)
+{
+ int irqbit;
+
+ /*
+ * Given an IRQ, disable the corresponding interrupt
+ * in the 8259.
+ */
+ if(irq < 0 || irq > MaxIrqPIC){
+ print("i8259disable: irq %d out of range\n", irq);
+ return -1;
+ }
+ irqbit = 1<<irq;
+
+ ilock(&i8259lock);
+ if(!(i8259mask & irqbit)){
+ i8259mask |= irqbit;
+ if(irq < 8)
+ outb(Int0aux, i8259mask & 0xFF);
+ else
+ outb(Int1aux, (i8259mask>>8) & 0xFF);
+ }
+ 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);
+}
+
diff --git a/sys/src/9/pc/init9.c b/sys/src/9/pc/init9.c
new file mode 100755
index 000000000..9ba7e7a97
--- /dev/null
+++ b/sys/src/9/pc/init9.c
@@ -0,0 +1,7 @@
+extern void startboot(char*, char**);
+
+void
+_main(char *argv0)
+{
+ startboot(argv0, &argv0);
+}
diff --git a/sys/src/9/pc/initcode.s b/sys/src/9/pc/initcode.s
new file mode 100755
index 000000000..55018f9ee
--- /dev/null
+++ b/sys/src/9/pc/initcode.s
@@ -0,0 +1,23 @@
+#include "/sys/src/libc/9syscall/sys.h"
+
+TEXT main(SB),$0
+
+ /*
+ * exec("/boot", bootv)
+ */
+ LEAL 4(SP),AX
+ PUSHL AX
+ LEAL boot(SB),AX
+ PUSHL AX
+ PUSHL $0
+ MOVL $EXEC,AX
+ INT $64
+
+ /*
+ * should never get here
+ */
+here:
+ JMP here
+
+GLOBL boot+0(SB),$6
+DATA boot+0(SB)/5,$"/boot"
diff --git a/sys/src/9/pc/io.h b/sys/src/9/pc/io.h
new file mode 100755
index 000000000..ba2399b7a
--- /dev/null
+++ b/sys/src/9/pc/io.h
@@ -0,0 +1,380 @@
+#define X86STEPPING(x) ((x) & 0x0F)
+/* incorporates extended-model and -family bits */
+#define X86MODEL(x) ((((x)>>4) & 0x0F) | (((x)>>16) & 0x0F)<<4)
+#define X86FAMILY(x) ((((x)>>8) & 0x0F) | (((x)>>20) & 0xFF)<<4)
+
+enum {
+ VectorNMI = 2, /* non-maskable interrupt */
+ VectorBPT = 3, /* breakpoint */
+ VectorUD = 6, /* invalid opcode exception */
+ VectorCNA = 7, /* coprocessor not available */
+ Vector2F = 8, /* double fault */
+ VectorCSO = 9, /* coprocessor segment overrun */
+ VectorPF = 14, /* page fault */
+ Vector15 = 15, /* reserved */
+ VectorCERR = 16, /* coprocessor error */
+
+ VectorPIC = 32, /* external i8259 interrupts */
+ IrqCLOCK = 0,
+ IrqKBD = 1,
+ IrqUART1 = 3,
+ IrqUART0 = 4,
+ IrqPCMCIA = 5,
+ IrqFLOPPY = 6,
+ IrqLPT = 7,
+ IrqIRQ7 = 7,
+ IrqAUX = 12, /* PS/2 port */
+ IrqIRQ13 = 13, /* coprocessor on 386 */
+ IrqATA0 = 14,
+ IrqATA1 = 15,
+ MaxIrqPIC = 15,
+
+ VectorLAPIC = VectorPIC+16, /* local APIC interrupts */
+ IrqLINT0 = 16, /* LINT[01] must be offsets 0 and 1 */
+ IrqLINT1 = 17,
+ IrqTIMER = 18,
+ IrqERROR = 19,
+ IrqPCINT = 20,
+ IrqSPURIOUS = 31, /* must have bits [3-0] == 0x0F */
+ MaxIrqLAPIC = 31,
+
+ VectorSYSCALL = 64,
+
+ VectorAPIC = 65, /* external APIC interrupts */
+ MaxVectorAPIC = 255,
+};
+
+typedef struct Vctl {
+ Vctl* next; /* handlers on this vector */
+
+ char name[KNAMELEN]; /* of driver */
+ int isintr; /* interrupt or fault/trap */
+ int irq;
+ int tbdf;
+ int (*isr)(int); /* get isr bit for this irq */
+ int (*eoi)(int); /* eoi */
+
+ void (*f)(Ureg*, void*); /* handler to call */
+ void* a; /* argument to call it with */
+} Vctl;
+
+enum {
+ BusCBUS = 0, /* Corollary CBUS */
+ BusCBUSII, /* Corollary CBUS II */
+ BusEISA, /* Extended ISA */
+ BusFUTURE, /* IEEE Futurebus */
+ BusINTERN, /* Internal bus */
+ BusISA, /* Industry Standard Architecture */
+ BusMBI, /* Multibus I */
+ BusMBII, /* Multibus II */
+ BusMCA, /* Micro Channel Architecture */
+ BusMPI, /* MPI */
+ BusMPSA, /* MPSA */
+ BusNUBUS, /* Apple Macintosh NuBus */
+ BusPCI, /* Peripheral Component Interconnect */
+ BusPCMCIA, /* PC Memory Card International Association */
+ BusTC, /* DEC TurboChannel */
+ BusVL, /* VESA Local bus */
+ BusVME, /* VMEbus */
+ BusXPRESS, /* Express System Bus */
+};
+
+#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
+#define BUSFNO(tbdf) (((tbdf)>>8)&0x07)
+#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F)
+#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF)
+#define BUSTYPE(tbdf) ((tbdf)>>24)
+#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00)
+#define BUSUNKNOWN (-1)
+
+enum {
+ MaxEISA = 16,
+ CfgEISA = 0xC80,
+};
+
+/*
+ * PCI support code.
+ */
+enum { /* type 0 & type 1 pre-defined header */
+ PciVID = 0x00, /* vendor ID */
+ PciDID = 0x02, /* device ID */
+ PciPCR = 0x04, /* command */
+ PciPSR = 0x06, /* status */
+ PciRID = 0x08, /* revision ID */
+ PciCCRp = 0x09, /* programming interface class code */
+ PciCCRu = 0x0A, /* sub-class code */
+ PciCCRb = 0x0B, /* base class code */
+ PciCLS = 0x0C, /* cache line size */
+ PciLTR = 0x0D, /* latency timer */
+ PciHDT = 0x0E, /* header type */
+ PciBST = 0x0F, /* BIST */
+
+ PciBAR0 = 0x10, /* base address */
+ PciBAR1 = 0x14,
+
+ PciINTL = 0x3C, /* interrupt line */
+ PciINTP = 0x3D, /* interrupt pin */
+};
+
+/* ccrb (base class code) values; controller types */
+enum {
+ Pcibcpci1 = 0, /* pci 1.0; no class codes defined */
+ Pcibcstore = 1, /* mass storage */
+ Pcibcnet = 2, /* network */
+ Pcibcdisp = 3, /* display */
+ Pcibcmmedia = 4, /* multimedia */
+ Pcibcmem = 5, /* memory */
+ Pcibcbridge = 6, /* bridge */
+ Pcibccomm = 7, /* simple comms (e.g., serial) */
+ Pcibcbasesys = 8, /* base system */
+ Pcibcinput = 9, /* input */
+ Pcibcdock = 0xa, /* docking stations */
+ Pcibcproc = 0xb, /* processors */
+ Pcibcserial = 0xc, /* serial bus (e.g., USB) */
+ Pcibcwireless = 0xd, /* wireless */
+ Pcibcintell = 0xe, /* intelligent i/o */
+ Pcibcsatcom = 0xf, /* satellite comms */
+ Pcibccrypto = 0x10, /* encryption/decryption */
+ Pcibcdacq = 0x11, /* data acquisition & signal proc. */
+};
+
+/* ccru (sub-class code) values; common cases only */
+enum {
+ /* mass storage */
+ Pciscscsi = 0, /* SCSI */
+ Pciscide = 1, /* IDE (ATA) */
+
+ /* network */
+ Pciscether = 0, /* Ethernet */
+
+ /* display */
+ Pciscvga = 0, /* VGA */
+ Pciscxga = 1, /* XGA */
+ Pcisc3d = 2, /* 3D */
+
+ /* bridges */
+ Pcischostpci = 0, /* host/pci */
+ Pciscpcicpci = 1, /* pci/pci */
+
+ /* simple comms */
+ Pciscserial = 0, /* 16450, etc. */
+ Pciscmultiser = 1, /* multiport serial */
+
+ /* serial bus */
+ Pciscusb = 3, /* USB */
+};
+
+enum { /* type 0 pre-defined header */
+ PciCIS = 0x28, /* cardbus CIS pointer */
+ PciSVID = 0x2C, /* subsystem vendor ID */
+ PciSID = 0x2E, /* cardbus CIS pointer */
+ PciEBAR0 = 0x30, /* expansion ROM base address */
+ PciMGNT = 0x3E, /* burst period length */
+ PciMLT = 0x3F, /* maximum latency between bursts */
+};
+
+enum { /* type 1 pre-defined header */
+ PciPBN = 0x18, /* primary bus number */
+ PciSBN = 0x19, /* secondary bus number */
+ PciUBN = 0x1A, /* subordinate bus number */
+ PciSLTR = 0x1B, /* secondary latency timer */
+ PciIBR = 0x1C, /* I/O base */
+ PciILR = 0x1D, /* I/O limit */
+ PciSPSR = 0x1E, /* secondary status */
+ PciMBR = 0x20, /* memory base */
+ PciMLR = 0x22, /* memory limit */
+ PciPMBR = 0x24, /* prefetchable memory base */
+ PciPMLR = 0x26, /* prefetchable memory limit */
+ PciPUBR = 0x28, /* prefetchable base upper 32 bits */
+ PciPULR = 0x2C, /* prefetchable limit upper 32 bits */
+ PciIUBR = 0x30, /* I/O base upper 16 bits */
+ PciIULR = 0x32, /* I/O limit upper 16 bits */
+ PciEBAR1 = 0x28, /* expansion ROM base address */
+ PciBCR = 0x3E, /* bridge control register */
+};
+
+enum { /* type 2 pre-defined header */
+ PciCBExCA = 0x10,
+ PciCBSPSR = 0x16,
+ PciCBPBN = 0x18, /* primary bus number */
+ PciCBSBN = 0x19, /* secondary bus number */
+ PciCBUBN = 0x1A, /* subordinate bus number */
+ PciCBSLTR = 0x1B, /* secondary latency timer */
+ PciCBMBR0 = 0x1C,
+ PciCBMLR0 = 0x20,
+ PciCBMBR1 = 0x24,
+ PciCBMLR1 = 0x28,
+ PciCBIBR0 = 0x2C, /* I/O base */
+ PciCBILR0 = 0x30, /* I/O limit */
+ PciCBIBR1 = 0x34, /* I/O base */
+ PciCBILR1 = 0x38, /* I/O limit */
+ PciCBSVID = 0x40, /* subsystem vendor ID */
+ PciCBSID = 0x42, /* subsystem ID */
+ PciCBLMBAR = 0x44, /* legacy mode base address */
+};
+
+typedef struct Pcisiz Pcisiz;
+struct Pcisiz
+{
+ Pcidev* dev;
+ int siz;
+ int bar;
+};
+
+typedef struct Pcidev Pcidev;
+struct Pcidev
+{
+ int tbdf; /* type+bus+device+function */
+ ushort vid; /* vendor ID */
+ ushort did; /* device ID */
+
+ ushort pcr;
+
+ uchar rid;
+ uchar ccrp;
+ uchar ccru;
+ uchar ccrb;
+ uchar cls;
+ uchar ltr;
+
+ struct {
+ ulong bar; /* base address */
+ int size;
+ } mem[6];
+
+ struct {
+ ulong bar;
+ int size;
+ } rom;
+ uchar intl; /* interrupt line */
+
+ Pcidev* list;
+ Pcidev* link; /* next device on this bno */
+
+ Pcidev* bridge; /* down a bus */
+ struct {
+ ulong bar;
+ int size;
+ } ioa, mema;
+
+ int pmrb; /* power management register block */
+};
+
+enum {
+ /* vendor ids */
+ Vintel = 0x8086,
+ Vmyricom= 0x14c1,
+};
+
+#define PCIWINDOW 0
+#define PCIWADDR(va) (PADDR(va)+PCIWINDOW)
+#define ISAWINDOW 0
+#define ISAWADDR(va) (PADDR(va)+ISAWINDOW)
+
+/* SMBus transactions */
+enum
+{
+ SMBquick, /* sends address only */
+
+ /* write */
+ SMBsend, /* sends address and cmd */
+ SMBbytewrite, /* sends address and cmd and 1 byte */
+ SMBwordwrite, /* sends address and cmd and 2 bytes */
+
+ /* read */
+ SMBrecv, /* sends address, recvs 1 byte */
+ SMBbyteread, /* sends address and cmd, recv's byte */
+ SMBwordread, /* sends address and cmd, recv's 2 bytes */
+};
+
+typedef struct SMBus SMBus;
+struct SMBus {
+ QLock; /* mutex */
+ Rendez r; /* rendezvous point for completion interrupts */
+ void *arg; /* implementation dependent */
+ ulong base; /* port or memory base of smbus */
+ int busy;
+ void (*transact)(SMBus*, int, int, int, uchar*);
+};
+
+/*
+ * PCMCIA support code.
+ */
+
+typedef struct PCMslot PCMslot;
+typedef struct PCMconftab PCMconftab;
+
+/*
+ * Map between ISA memory space and PCMCIA card memory space.
+ */
+struct PCMmap {
+ ulong ca; /* card address */
+ ulong cea; /* card end address */
+ ulong isa; /* ISA address */
+ int len; /* length of the ISA area */
+ int attr; /* attribute memory */
+ int ref;
+};
+
+/* configuration table entry */
+struct PCMconftab
+{
+ int index;
+ ushort irqs; /* legal irqs */
+ uchar irqtype;
+ uchar bit16; /* true for 16 bit access */
+ struct {
+ ulong start;
+ ulong len;
+ } io[16];
+ int nio;
+ uchar vpp1;
+ uchar vpp2;
+ uchar memwait;
+ ulong maxwait;
+ ulong readywait;
+ ulong otherwait;
+};
+
+/* a card slot */
+struct PCMslot
+{
+ Lock;
+ int ref;
+
+ void *cp; /* controller for this slot */
+ long memlen; /* memory length */
+ uchar base; /* index register base */
+ uchar slotno; /* slot number */
+
+ /* status */
+ uchar special; /* in use for a special device */
+ uchar already; /* already inited */
+ uchar occupied;
+ uchar battery;
+ uchar wrprot;
+ uchar powered;
+ uchar configed;
+ uchar enabled;
+ uchar busy;
+
+ /* cis info */
+ ulong msec; /* time of last slotinfo call */
+ char verstr[512]; /* version string */
+ int ncfg; /* number of configurations */
+ struct {
+ ushort cpresent; /* config registers present */
+ ulong caddr; /* relative address of config registers */
+ } cfg[8];
+ int nctab; /* number of config table entries */
+ PCMconftab ctab[8];
+ PCMconftab *def; /* default conftab */
+
+ /* memory maps */
+ Lock mlock; /* lock down the maps */
+ int time;
+ PCMmap mmap[4]; /* maps, last is always for the kernel */
+};
+
+#pragma varargck type "T" int
+#pragma varargck type "T" uint
diff --git a/sys/src/9/pc/kbd.c b/sys/src/9/pc/kbd.c
new file mode 100755
index 000000000..69ee3162d
--- /dev/null
+++ b/sys/src/9/pc/kbd.c
@@ -0,0 +1,715 @@
+/*
+ * keyboard input
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+enum {
+ Data= 0x60, /* data port */
+
+ Status= 0x64, /* status port */
+ Inready= 0x01, /* input character ready */
+ Outbusy= 0x02, /* output busy */
+ Sysflag= 0x04, /* system flag */
+ Cmddata= 0x08, /* cmd==0, data==1 */
+ Inhibit= 0x10, /* keyboard/mouse inhibited */
+ Minready= 0x20, /* mouse character ready */
+ Rtimeout= 0x40, /* general timeout */
+ Parity= 0x80,
+
+ Cmd= 0x64, /* command port (write only) */
+
+ Spec= 0xF800, /* Unicode private space */
+ PF= Spec|0x20, /* num pad function key */
+ View= Spec|0x00, /* view (shift window up) */
+ KF= 0xF000, /* function key (begin Unicode private space) */
+ Shift= Spec|0x60,
+ Break= Spec|0x61,
+ Ctrl= Spec|0x62,
+ Latin= Spec|0x63,
+ Caps= Spec|0x64,
+ Num= Spec|0x65,
+ Middle= Spec|0x66,
+ Altgr= Spec|0x67,
+ Kmouse= Spec|0x100,
+ No= 0x00, /* peter */
+
+ Home= KF|13,
+ Up= KF|14,
+ Pgup= KF|15,
+ Print= KF|16,
+ Left= KF|17,
+ Right= KF|18,
+ End= KF|24,
+ Down= View,
+ Pgdown= KF|19,
+ Ins= KF|20,
+ Del= 0x7F,
+ Scroll= KF|21,
+
+ Nscan= 128,
+
+ Int= 0, /* kbscans indices */
+ Ext,
+ Nscans,
+};
+
+/*
+ * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard.
+ * A 'standard' keyboard doesn't produce anything above 0x58.
+ */
+Rune kbtab[Nscan] =
+{
+[0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
+[0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
+[0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
+[0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
+[0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+[0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
+[0x30] 'b', 'n', 'm', ',', '.', '/', Shift, '*',
+[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',
+[0x48] '8', '9', '-', '4', '5', '6', '+', '1',
+[0x50] '2', '3', '0', '.', No, No, No, KF|11,
+[0x58] KF|12, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, View, No, Up, No, No, No, No,
+};
+
+Rune kbtabshift[Nscan] =
+{
+[0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
+[0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
+[0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
+[0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
+[0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
+[0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
+[0x30] 'B', 'N', 'M', '<', '>', '?', Shift, '*',
+[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',
+[0x48] '8', '9', '-', '4', '5', '6', '+', '1',
+[0x50] '2', '3', '0', '.', No, No, No, KF|11,
+[0x58] KF|12, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, Up, No, Up, No, No, No, No,
+};
+
+Rune kbtabesc1[Nscan] =
+{
+[0x00] No, No, No, No, No, No, No, No,
+[0x08] No, No, No, No, No, No, No, No,
+[0x10] No, No, No, No, No, No, No, No,
+[0x18] No, No, No, No, '\n', Ctrl, No, No,
+[0x20] No, No, No, No, No, No, No, No,
+[0x28] No, No, Shift, No, No, No, No, No,
+[0x30] No, No, No, No, No, '/', No, Print,
+[0x38] Altgr, No, No, No, No, No, No, No,
+[0x40] No, No, No, No, No, No, Break, Home,
+[0x48] Up, Pgup, No, Left, No, Right, No, End,
+[0x50] Down, Pgdown, Ins, Del, No, No, No, No,
+[0x58] No, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, Up, No, No, No, No, No, No,
+};
+
+Rune kbtabaltgr[Nscan] =
+{
+[0x00] No, No, No, No, No, No, No, No,
+[0x08] No, No, No, No, No, No, No, No,
+[0x10] No, No, No, No, No, No, No, No,
+[0x18] No, No, No, No, '\n', Ctrl, No, No,
+[0x20] No, No, No, No, No, No, No, No,
+[0x28] No, No, Shift, No, No, No, No, No,
+[0x30] No, No, No, No, No, '/', No, Print,
+[0x38] Altgr, No, No, No, No, No, No, No,
+[0x40] No, No, No, No, No, No, Break, Home,
+[0x48] Up, Pgup, No, Left, No, Right, No, End,
+[0x50] Down, Pgdown, Ins, Del, No, No, No, No,
+[0x58] No, No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, Up, No, No, No, No, No, No,
+};
+
+Rune kbtabctrl[Nscan] =
+{
+[0x00] No, '', '', '', '', '', '', '',
+[0x08] '', '', '', '', ' ', '', '\b', '\t',
+[0x10] '', '', '', '', '', '', '', '\t',
+[0x18] '', '', '', '', '\n', Ctrl, '', '',
+[0x20] '', '', '', '\b', '\n', ' ', ' ', '',
+[0x28] '', No, Shift, '', '', '', '', '',
+[0x30] '', '', ' ', ' ', '', '', Shift, '\n',
+[0x38] Latin, No, Ctrl, '', '', '', '', '',
+[0x40] '', '', ' ', ' ', '', '', '', '',
+[0x48] '', '', ' ', '', '', '', ' ', '',
+[0x50] '', '', '', '', No, No, No, '',
+[0x58] ' ', No, No, No, No, No, No, No,
+[0x60] No, No, No, No, No, No, No, No,
+[0x68] No, No, No, No, No, No, No, No,
+[0x70] No, No, No, No, No, No, No, No,
+[0x78] No, '', No, '\b', No, No, No, No,
+};
+
+enum
+{
+ /* controller command byte */
+ Cscs1= (1<<6), /* scan code set 1 */
+ Cauxdis= (1<<5), /* mouse disable */
+ Ckbddis= (1<<4), /* kbd disable */
+ Csf= (1<<2), /* system flag */
+ Cauxint= (1<<1), /* mouse interrupt enable */
+ Ckbdint= (1<<0), /* kbd interrupt enable */
+};
+
+int mouseshifted;
+void (*kbdmouse)(int);
+
+static Lock i8042lock;
+static uchar ccc;
+static void (*auxputc)(int, int);
+static int nokbd = 1; /* flag: no PS/2 keyboard */
+
+/*
+ * wait for output no longer busy
+ */
+static int
+outready(void)
+{
+ int tries;
+
+ for(tries = 0; (inb(Status) & Outbusy); tries++){
+ if(tries > 500)
+ return -1;
+ delay(2);
+ }
+ return 0;
+}
+
+/*
+ * wait for input
+ */
+static int
+inready(void)
+{
+ int tries;
+
+ for(tries = 0; !(inb(Status) & Inready); tries++){
+ if(tries > 500)
+ return -1;
+ delay(2);
+ }
+ return 0;
+}
+
+/*
+ * ask 8042 to reset the machine
+ */
+void
+i8042reset(void)
+{
+ int i, x;
+
+ if(nokbd)
+ return;
+
+ *((ushort*)KADDR(0x472)) = 0x1234; /* BIOS warm-boot flag */
+
+ /*
+ * newer reset the machine command
+ */
+ outready();
+ outb(Cmd, 0xFE);
+ outready();
+
+ /*
+ * Pulse it by hand (old somewhat reliable)
+ */
+ x = 0xDF;
+ for(i = 0; i < 5; i++){
+ x ^= 1;
+ outready();
+ outb(Cmd, 0xD1);
+ outready();
+ outb(Data, x); /* toggle reset */
+ delay(100);
+ }
+}
+
+int
+i8042auxcmd(int cmd)
+{
+ unsigned int c;
+ int tries;
+ static int badkbd;
+
+ if(badkbd)
+ return -1;
+ c = 0;
+ tries = 0;
+
+ ilock(&i8042lock);
+ do{
+ if(tries++ > 2)
+ break;
+ if(outready() < 0)
+ break;
+ outb(Cmd, 0xD4);
+ if(outready() < 0)
+ break;
+ outb(Data, cmd);
+ if(outready() < 0)
+ break;
+ if(inready() < 0)
+ break;
+ c = inb(Data);
+ } while(c == 0xFE || c == 0);
+ iunlock(&i8042lock);
+
+ if(c != 0xFA){
+ print("i8042: %2.2ux returned to the %2.2ux command\n", c, cmd);
+ badkbd = 1; /* don't keep trying; there might not be one */
+ return -1;
+ }
+ return 0;
+}
+
+int
+i8042auxcmds(uchar *cmd, int ncmd)
+{
+ int i;
+
+ ilock(&i8042lock);
+ for(i=0; i<ncmd; i++){
+ if(outready() < 0)
+ break;
+ outb(Cmd, 0xD4);
+ if(outready() < 0)
+ break;
+ outb(Data, cmd[i]);
+ }
+ iunlock(&i8042lock);
+ return i;
+}
+
+typedef struct Kbscan Kbscan;
+struct Kbscan {
+ int esc1;
+ int esc2;
+ int alt;
+ int altgr;
+ int caps;
+ int ctl;
+ int num;
+ int shift;
+ int collecting;
+ int nk;
+ Rune kc[5];
+ int buttons;
+};
+
+Kbscan kbscans[Nscans]; /* kernel and external scan code state */
+
+static int kdebug;
+
+/*
+ * set keyboard's leds for lock states (scroll, numeric, caps).
+ *
+ * at least one keyboard (from Qtronics) also sets its numeric-lock
+ * behaviour to match the led state, though it has no numeric keypad,
+ * and some BIOSes bring the system up with numeric-lock set and no
+ * setting to change that. this combination steals the keys for these
+ * characters and makes it impossible to generate them: uiolkjm&*().
+ * thus we'd like to be able to force the numeric-lock led (and behaviour) off.
+ */
+static void
+setleds(Kbscan *kbscan)
+{
+ int leds;
+
+ if(nokbd || kbscan != &kbscans[Int])
+ return;
+ leds = 0;
+ if(kbscan->num)
+ leds |= 1<<1;
+ if(0 && kbscan->caps) /* we don't implement caps lock */
+ leds |= 1<<2;
+ ilock(&i8042lock);
+ outready();
+ outb(Data, 0xed); /* `reset keyboard lock states' */
+ outready();
+ outb(Data, leds);
+ outready();
+ iunlock(&i8042lock);
+}
+
+/*
+ * Scan code processing
+ */
+void
+kbdputsc(int c, int external)
+{
+ int i, keyup;
+ Kbscan *kbscan;
+
+ if(external)
+ kbscan = &kbscans[Ext];
+ else
+ kbscan = &kbscans[Int];
+
+ if(kdebug)
+ print("sc %x ms %d\n", c, mouseshifted);
+ /*
+ * e0's is the first of a 2 character sequence, e1 the first
+ * of a 3 character sequence (on the safari)
+ */
+ if(c == 0xe0){
+ kbscan->esc1 = 1;
+ return;
+ } else if(c == 0xe1){
+ kbscan->esc2 = 2;
+ return;
+ }
+
+ keyup = c & 0x80;
+ c &= 0x7f;
+ if(c > sizeof kbtab){
+ c |= keyup;
+ if(c != 0xFF) /* these come fairly often: CAPSLOCK U Y */
+ print("unknown key %ux\n", c);
+ return;
+ }
+
+ if(kbscan->esc1){
+ c = kbtabesc1[c];
+ kbscan->esc1 = 0;
+ } else if(kbscan->esc2){
+ kbscan->esc2--;
+ return;
+ } else if(kbscan->shift)
+ c = kbtabshift[c];
+ else if(kbscan->altgr)
+ c = kbtabaltgr[c];
+ else if(kbscan->ctl)
+ c = kbtabctrl[c];
+ else
+ c = kbtab[c];
+
+ if(kbscan->caps && c<='z' && c>='a')
+ c += 'A' - 'a';
+
+ /*
+ * keyup only important for shifts
+ */
+ if(keyup){
+ switch(c){
+ case Latin:
+ kbscan->alt = 0;
+ break;
+ case Shift:
+ kbscan->shift = 0;
+ mouseshifted = 0;
+ if(kdebug)
+ print("shiftclr\n");
+ break;
+ case Ctrl:
+ kbscan->ctl = 0;
+ break;
+ case Altgr:
+ kbscan->altgr = 0;
+ break;
+ case Kmouse|1:
+ case Kmouse|2:
+ case Kmouse|3:
+ case Kmouse|4:
+ case Kmouse|5:
+ kbscan->buttons &= ~(1<<(c-Kmouse-1));
+ if(kbdmouse)
+ kbdmouse(kbscan->buttons);
+ break;
+ }
+ return;
+ }
+
+ /*
+ * normal character
+ */
+ if(!(c & (Spec|KF))){
+ if(kbscan->ctl)
+ if(kbscan->alt && c == Del)
+ exit(0);
+ if(!kbscan->collecting){
+ kbdputc(kbdq, c);
+ return;
+ }
+ kbscan->kc[kbscan->nk++] = c;
+ c = latin1(kbscan->kc, kbscan->nk);
+ if(c < -1) /* need more keystrokes */
+ return;
+ if(c != -1) /* valid sequence */
+ kbdputc(kbdq, c);
+ else /* dump characters */
+ for(i=0; i<kbscan->nk; i++)
+ kbdputc(kbdq, kbscan->kc[i]);
+ kbscan->nk = 0;
+ kbscan->collecting = 0;
+ return;
+ } else {
+ switch(c){
+ case Caps:
+ kbscan->caps ^= 1;
+ return;
+ case Num:
+ kbscan->num ^= 1;
+ if(!external)
+ setleds(kbscan);
+ return;
+ case Shift:
+ kbscan->shift = 1;
+ if(kdebug)
+ print("shift\n");
+ mouseshifted = 1;
+ return;
+ case Latin:
+ kbscan->alt = 1;
+ /*
+ * VMware and Qemu use Ctl-Alt as the key combination
+ * to make the VM give up keyboard and mouse focus.
+ * This has the unfortunate side effect that when you
+ * come back into focus, Plan 9 thinks you want to type
+ * a compose sequence (you just typed alt).
+ *
+ * As a clumsy hack around this, we look for ctl-alt
+ * and don't treat it as the start of a compose sequence.
+ */
+ if(!kbscan->ctl){
+ kbscan->collecting = 1;
+ kbscan->nk = 0;
+ }
+ return;
+ case Ctrl:
+ kbscan->ctl = 1;
+ return;
+ case Altgr:
+ kbscan->altgr = 1;
+ return;
+ case Kmouse|1:
+ case Kmouse|2:
+ case Kmouse|3:
+ case Kmouse|4:
+ case Kmouse|5:
+ kbscan->buttons |= 1<<(c-Kmouse-1);
+ if(kbdmouse)
+ kbdmouse(kbscan->buttons);
+ return;
+ case KF|11:
+ print("kbd debug on, F12 turns it off\n");
+ kdebug = 1;
+ break;
+ case KF|12:
+ kdebug = 0;
+ break;
+ }
+ }
+ kbdputc(kbdq, c);
+}
+
+/*
+ * keyboard interrupt
+ */
+static void
+i8042intr(Ureg*, void*)
+{
+ int s, c;
+
+ /*
+ * get status
+ */
+ ilock(&i8042lock);
+ s = inb(Status);
+ if(!(s&Inready)){
+ iunlock(&i8042lock);
+ return;
+ }
+
+ /*
+ * get the character
+ */
+ c = inb(Data);
+ iunlock(&i8042lock);
+
+ /*
+ * if it's the aux port...
+ */
+ if(s & Minready){
+ if(auxputc != nil)
+ auxputc(c, kbscans[Int].shift);
+ return;
+ }
+
+ kbdputsc(c, Int);
+}
+
+void
+i8042auxenable(void (*putc)(int, int))
+{
+ char *err = "i8042: aux init failed\n";
+
+ /* enable kbd/aux xfers and interrupts */
+ ccc &= ~Cauxdis;
+ ccc |= Cauxint;
+
+ ilock(&i8042lock);
+ if(outready() < 0)
+ print(err);
+ outb(Cmd, 0x60); /* write control register */
+ if(outready() < 0)
+ print(err);
+ outb(Data, ccc);
+ if(outready() < 0)
+ print(err);
+ outb(Cmd, 0xA8); /* auxiliary device enable */
+ if(outready() < 0){
+ iunlock(&i8042lock);
+ return;
+ }
+ auxputc = putc;
+ intrenable(IrqAUX, i8042intr, 0, BUSUNKNOWN, "kbdaux");
+ iunlock(&i8042lock);
+}
+
+static char *initfailed = "i8042: kbdinit failed\n";
+
+static int
+outbyte(int port, int c)
+{
+ outb(port, c);
+ if(outready() < 0) {
+ print(initfailed);
+ return -1;
+ }
+ return 0;
+}
+
+void
+kbdinit(void)
+{
+ int c, try;
+
+ /* wait for a quiescent controller */
+ try = 1000;
+ while(try-- > 0 && (c = inb(Status)) & (Outbusy | Inready)) {
+ if(c & Inready)
+ inb(Data);
+ delay(1);
+ }
+ if (try <= 0) {
+ print(initfailed);
+ return;
+ }
+
+ /* get current controller command byte */
+ outb(Cmd, 0x20);
+ if(inready() < 0){
+ print("i8042: kbdinit can't read ccc\n");
+ ccc = 0;
+ } else
+ ccc = inb(Data);
+
+ /* enable kbd xfers and interrupts */
+ ccc &= ~Ckbddis;
+ ccc |= Csf | Ckbdint | Cscs1;
+ if(outready() < 0) {
+ print(initfailed);
+ return;
+ }
+
+ nokbd = 0;
+
+ /* disable mouse */
+ if (outbyte(Cmd, 0x60) < 0 || outbyte(Data, ccc) < 0)
+ print("i8042: kbdinit mouse disable failed\n");
+}
+
+void
+kbdenable(void)
+{
+ kbdq = qopen(4*1024, 0, 0, 0);
+ if(kbdq == nil)
+ panic("kbdinit");
+ qnoblock(kbdq, 1);
+
+ ioalloc(Data, 1, 0, "kbd");
+ ioalloc(Cmd, 1, 0, "kbd");
+
+ intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "kbd");
+
+ kbscans[Int].num = 0;
+ setleds(&kbscans[Int]);
+}
+
+void
+kbdputmap(ushort m, ushort scanc, Rune r)
+{
+ if(scanc >= Nscan)
+ error(Ebadarg);
+ switch(m) {
+ default:
+ error(Ebadarg);
+ case 0:
+ kbtab[scanc] = r;
+ break;
+ case 1:
+ kbtabshift[scanc] = r;
+ break;
+ case 2:
+ kbtabesc1[scanc] = r;
+ break;
+ case 3:
+ kbtabaltgr[scanc] = r;
+ break;
+ case 4:
+ kbtabctrl[scanc] = r;
+ break;
+ }
+}
+
+int
+kbdgetmap(uint offset, int *t, int *sc, Rune *r)
+{
+ if ((int)offset < 0)
+ error(Ebadarg);
+ *t = offset/Nscan;
+ *sc = offset%Nscan;
+ switch(*t) {
+ default:
+ return 0;
+ case 0:
+ *r = kbtab[*sc];
+ return 1;
+ case 1:
+ *r = kbtabshift[*sc];
+ return 1;
+ case 2:
+ *r = kbtabesc1[*sc];
+ return 1;
+ case 3:
+ *r = kbtabaltgr[*sc];
+ return 1;
+ case 4:
+ *r = kbtabctrl[*sc];
+ return 1;
+ }
+}
diff --git a/sys/src/9/pc/l.s b/sys/src/9/pc/l.s
new file mode 100755
index 000000000..7d971a9ad
--- /dev/null
+++ b/sys/src/9/pc/l.s
@@ -0,0 +1,1294 @@
+#include "mem.h"
+#include "/sys/src/boot/pc/x16.h"
+#undef DELAY
+
+#define PADDR(a) ((a) & ~KZERO)
+#define KADDR(a) (KZERO|(a))
+
+/*
+ * Some machine instructions not handled by 8[al].
+ */
+#define OP16 BYTE $0x66
+#define DELAY BYTE $0xEB; BYTE $0x00 /* JMP .+2 */
+#define CPUID BYTE $0x0F; BYTE $0xA2 /* CPUID, argument in AX */
+#define WRMSR BYTE $0x0F; BYTE $0x30 /* WRMSR, argument in AX/DX (lo/hi) */
+#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) */
+#define WBINVD BYTE $0x0F; BYTE $0x09
+
+/*
+ * Macros for calculating offsets within the page directory base
+ * and page tables. Note that these are assembler-specific hence
+ * the '<<2'.
+ */
+#define PDO(a) (((((a))>>22) & 0x03FF)<<2)
+#define PTO(a) (((((a))>>12) & 0x03FF)<<2)
+
+/*
+ * For backwards compatiblity with 9load - should go away when 9load is changed
+ * 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 _startKADDR(SB), $0
+ MOVL $_startPADDR(SB), AX
+ ANDL $~KZERO, AX
+ JMP* AX
+
+/*
+ * Must be 4-byte aligned.
+ */
+TEXT _multibootheader(SB), $0
+ LONG $0x1BADB002 /* magic */
+ LONG $0x00010003 /* flags */
+ LONG $-(0x1BADB002 + 0x00010003) /* checksum */
+ LONG $_multibootheader-KZERO(SB) /* header_addr */
+ LONG $_startKADDR-KZERO(SB) /* load_addr */
+ LONG $edata-KZERO(SB) /* load_end_addr */
+ LONG $end-KZERO(SB) /* bss_end_addr */
+ LONG $_startKADDR-KZERO(SB) /* entry_addr */
+ LONG $0 /* mode_type */
+ LONG $0 /* width */
+ LONG $0 /* height */
+ LONG $0 /* depth */
+
+/*
+ * In protected mode with paging turned off and segment registers setup
+ * to linear map all memory. 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. Six pages are needed for
+ * the basic set:
+ * a page directory;
+ * page tables for mapping the first 8MB of physical memory to KZERO;
+ * a page for the GDT;
+ * virtual and physical pages for mapping the Mach structure.
+ * The remaining PTEs will be allocated later when memory is sized.
+ * An identity mmu map is also needed for the switch to virtual mode.
+ * This identity mapping is removed once the MMU is going and the JMP has
+ * been made to virtual memory.
+ */
+TEXT _startPADDR(SB), $0
+ CLI /* make sure interrupts are off */
+
+ /* set up the gdt so we have sane plan 9 style gdts. */
+ MOVL $tgdtptr(SB), AX
+ ANDL $~KZERO, AX
+ MOVL (AX), GDTR
+ MOVW $1, AX
+ MOVW AX, MSW
+
+ /* clear prefetch queue (weird code to avoid optimizations) */
+ DELAY
+
+ /* set segs to something sane (avoid traps later) */
+ MOVW $(1<<3), AX
+ MOVW AX, DS
+ MOVW AX, SS
+ MOVW AX, ES
+ MOVW AX, FS
+ MOVW AX, GS
+
+/* JMP $(2<<3):$mode32bit(SB) /**/
+ BYTE $0xEA
+ LONG $mode32bit-KZERO(SB)
+ WORD $(2<<3)
+
+/*
+ * gdt to get us to 32-bit/segmented/unpaged mode
+ */
+TEXT tgdt(SB), $0
+
+ /* null descriptor */
+ LONG $0
+ LONG $0
+
+ /* data segment descriptor for 4 gigabytes (PL 0) */
+ LONG $(0xFFFF)
+ LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
+
+ /* exec segment descriptor for 4 gigabytes (PL 0) */
+ LONG $(0xFFFF)
+ LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
+
+/*
+ * pointer to initial gdt
+ * Note the -KZERO which puts the physical address in the gdtptr.
+ * 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. */
+
+ MOVL $PADDR(CPU0PDB), DI /* clear 4 pages for the tables etc. */
+ XORL AX, AX
+ MOVL $(4*BY2PG), CX
+ SHRL $2, CX
+
+ CLD
+ REP; STOSL
+
+ MOVL $PADDR(CPU0PDB), AX
+ ADDL $PDO(KZERO), AX /* page directory offset for KZERO */
+ MOVL $PADDR(CPU0PTE), (AX) /* PTE's for KZERO */
+ MOVL $(PTEWRITE|PTEVALID), BX /* page permissions */
+ ORL BX, (AX)
+
+ ADDL $4, AX
+ MOVL $PADDR(CPU0PTE1), (AX) /* PTE's for KZERO+4MB */
+ MOVL $(PTEWRITE|PTEVALID), BX /* page permissions */
+ ORL BX, (AX)
+
+ MOVL $PADDR(CPU0PTE), AX /* first page of page table */
+ MOVL $1024, CX /* 1024 pages in 4MB */
+_setpte:
+ MOVL BX, (AX)
+ ADDL $(1<<PGSHIFT), BX
+ ADDL $4, AX
+ LOOP _setpte
+
+ MOVL $PADDR(CPU0PTE1), AX /* second page of page table */
+ MOVL $1024, CX /* 1024 pages in 4MB */
+_setpte1:
+ MOVL BX, (AX)
+ ADDL $(1<<PGSHIFT), BX
+ ADDL $4, AX
+ LOOP _setpte1
+
+ MOVL $PADDR(CPU0PTE), AX
+ ADDL $PTO(MACHADDR), AX /* page table entry offset for MACHADDR */
+ MOVL $PADDR(CPU0MACH), (AX) /* PTE for Mach */
+ MOVL $(PTEWRITE|PTEVALID), BX /* page permissions */
+ ORL BX, (AX)
+
+/*
+ * Now ready to use the new map. Make sure the processor options are what is wanted.
+ * It is necessary on some processors to immediately follow mode switching with a JMP instruction
+ * to clear the prefetch queues.
+ */
+ MOVL $PADDR(CPU0PDB), CX /* load address of page directory */
+ MOVL (PDO(KZERO))(CX), DX /* double-map KZERO at 0 */
+ MOVL DX, (PDO(0))(CX)
+ MOVL CX, CR3
+ DELAY /* JMP .+2 */
+
+ MOVL CR0, DX
+ ORL $0x80010000, DX /* PG|WP */
+ ANDL $~0x6000000A, DX /* ~(CD|NW|TS|MP) */
+
+ MOVL $_startpg(SB), AX /* this is a virtual address */
+ MOVL DX, CR0 /* turn on paging */
+ JMP* AX /* jump to the virtual nirvana */
+
+/*
+ * Basic machine environment set, can clear BSS and create a stack.
+ * The stack starts at the top of the page containing the Mach structure.
+ * The x86 architecture forces the use of the same virtual address for
+ * each processor's Mach structure, so the global Mach pointer 'm' can
+ * be initialised here.
+ */
+TEXT _startpg(SB), $0
+ MOVL $0, (PDO(0))(CX) /* undo double-map of KZERO at 0 */
+ MOVL CX, CR3 /* load and flush the mmu */
+
+_clearbss:
+ MOVL $edata(SB), DI
+ XORL AX, AX
+ MOVL $end(SB), CX
+ SUBL DI, CX /* end-edata bytes */
+ SHRL $2, CX /* end-edata doublewords */
+
+ CLD
+ REP; STOSL /* clear BSS */
+
+ MOVL $MACHADDR, SP
+ MOVL SP, m(SB) /* initialise global Mach pointer */
+ MOVL $0, 0(SP) /* initialise m->machno */
+
+
+ ADDL $(MACHSIZE-4), SP /* initialise stack */
+
+/*
+ * Need to do one final thing to ensure a clean machine environment,
+ * clear the EFLAGS register, which can only be done once there is a stack.
+ */
+ MOVL $0, AX
+ PUSHL AX
+ POPFL
+
+ CALL main(SB)
+
+/*
+ * Park a processor. Should never fall through a return from main to here,
+ * should only be called by application processors when shutting down.
+ */
+TEXT idle(SB), $0
+_idle:
+ STI
+ 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 $0x80010000, AX /* PG|WP */
+ 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
+
+/*
+ * BIOS32.
+ */
+TEXT bios32call(SB), $0
+ MOVL ci+0(FP), BP
+ MOVL 0(BP), AX
+ MOVL 4(BP), BX
+ MOVL 8(BP), CX
+ MOVL 12(BP), DX
+ MOVL 16(BP), SI
+ MOVL 20(BP), DI
+ PUSHL BP
+
+ MOVL 12(SP), BP /* ptr */
+ BYTE $0xFF; BYTE $0x5D; BYTE $0x00 /* CALL FAR 0(BP) */
+
+ POPL BP
+ MOVL DI, 20(BP)
+ MOVL SI, 16(BP)
+ MOVL DX, 12(BP)
+ MOVL CX, 8(BP)
+ MOVL BX, 4(BP)
+ MOVL AX, 0(BP)
+
+ XORL AX, AX
+ JCC _bios32xxret
+ INCL AX
+
+_bios32xxret:
+ RET
+
+/*
+ * Port I/O.
+ * in[bsl] input a byte|short|long
+ * ins[bsl] input a string of bytes|shorts|longs
+ * out[bsl] output a byte|short|long
+ * outs[bsl] output a string of bytes|shorts|longs
+ */
+TEXT inb(SB), $0
+ MOVL port+0(FP), DX
+ XORL AX, AX
+ INB
+ RET
+
+TEXT insb(SB), $0
+ MOVL port+0(FP), DX
+ MOVL address+4(FP), DI
+ MOVL count+8(FP), CX
+ CLD
+ REP; INSB
+ RET
+
+TEXT ins(SB), $0
+ MOVL port+0(FP), DX
+ XORL AX, AX
+ OP16; INL
+ RET
+
+TEXT inss(SB), $0
+ MOVL port+0(FP), DX
+ MOVL address+4(FP), DI
+ MOVL count+8(FP), CX
+ CLD
+ REP; OP16; INSL
+ RET
+
+TEXT inl(SB), $0
+ MOVL port+0(FP), DX
+ INL
+ RET
+
+TEXT insl(SB), $0
+ MOVL port+0(FP), DX
+ MOVL address+4(FP), DI
+ MOVL count+8(FP), CX
+ CLD
+ REP; INSL
+ RET
+
+TEXT outb(SB), $0
+ MOVL port+0(FP), DX
+ MOVL byte+4(FP), AX
+ OUTB
+ RET
+
+TEXT outsb(SB), $0
+ MOVL port+0(FP), DX
+ MOVL address+4(FP), SI
+ MOVL count+8(FP), CX
+ CLD
+ REP; OUTSB
+ RET
+
+TEXT outs(SB), $0
+ MOVL port+0(FP), DX
+ MOVL short+4(FP), AX
+ OP16; OUTL
+ RET
+
+TEXT outss(SB), $0
+ MOVL port+0(FP), DX
+ MOVL address+4(FP), SI
+ MOVL count+8(FP), CX
+ CLD
+ REP; OP16; OUTSL
+ RET
+
+TEXT outl(SB), $0
+ MOVL port+0(FP), DX
+ MOVL long+4(FP), AX
+ OUTL
+ RET
+
+TEXT outsl(SB), $0
+ MOVL port+0(FP), DX
+ MOVL address+4(FP), SI
+ MOVL count+8(FP), CX
+ CLD
+ REP; OUTSL
+ RET
+
+/*
+ * Read/write various system registers.
+ * CR4 and the 'model specific registers' should only be read/written
+ * after it has been determined the processor supports them
+ */
+TEXT lgdt(SB), $0 /* GDTR - global descriptor table */
+ MOVL gdtptr+0(FP), AX
+ MOVL (AX), GDTR
+ RET
+
+TEXT lidt(SB), $0 /* IDTR - interrupt descriptor table */
+ MOVL idtptr+0(FP), AX
+ MOVL (AX), IDTR
+ RET
+
+TEXT ltr(SB), $0 /* TR - task register */
+ MOVL tptr+0(FP), AX
+ MOVW AX, TASK
+ RET
+
+TEXT getcr0(SB), $0 /* CR0 - processor control */
+ MOVL CR0, AX
+ RET
+
+TEXT getcr2(SB), $0 /* CR2 - page fault linear address */
+ MOVL CR2, AX
+ RET
+
+TEXT getcr3(SB), $0 /* CR3 - page directory base */
+ MOVL CR3, AX
+ RET
+
+TEXT putcr0(SB), $0
+ MOVL cr0+0(FP), AX
+ MOVL AX, CR0
+ RET
+
+TEXT putcr3(SB), $0
+ MOVL cr3+0(FP), AX
+ MOVL AX, CR3
+ RET
+
+TEXT getcr4(SB), $0 /* CR4 - extensions */
+ MOVL CR4, AX
+ RET
+
+TEXT putcr4(SB), $0
+ MOVL cr4+0(FP), AX
+ MOVL AX, CR4
+ RET
+
+TEXT invlpg(SB), $0
+ /* 486+ only */
+ MOVL va+0(FP), CX
+ INVLPG
+ RET
+
+TEXT wbinvd(SB), $0
+ WBINVD
+ RET
+
+TEXT _cycles(SB), $0 /* time stamp counter */
+ RDTSC
+ MOVL vlong+0(FP), CX /* &vlong */
+ MOVL AX, 0(CX) /* lo */
+ MOVL DX, 4(CX) /* hi */
+ RET
+
+/*
+ * stub for:
+ * time stamp counter; low-order 32 bits of 64-bit cycle counter
+ * Runs at fasthz/4 cycles per second (m->clkin>>3)
+ */
+TEXT lcycles(SB),1,$0
+ RDTSC
+ RET
+
+TEXT rdmsr(SB), $0 /* model-specific register */
+ MOVL index+0(FP), CX
+ RDMSR
+ MOVL vlong+4(FP), CX /* &vlong */
+ MOVL AX, 0(CX) /* lo */
+ MOVL DX, 4(CX) /* hi */
+ RET
+
+TEXT wrmsr(SB), $0
+ MOVL index+0(FP), CX
+ MOVL lo+4(FP), AX
+ MOVL hi+8(FP), DX
+ WRMSR
+ RET
+
+/*
+ * Try to determine the CPU type which requires fiddling with EFLAGS.
+ * If the Id bit can be toggled then the CPUID instruction can be used
+ * to determine CPU identity and features. First have to check if it's
+ * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
+ * toggled then it's an older 486 of some kind.
+ *
+ * cpuid(fun, regs[4]);
+ */
+TEXT cpuid(SB), $0
+ MOVL $0x240000, AX
+ PUSHL AX
+ POPFL /* set Id|Ac */
+ PUSHFL
+ POPL BX /* retrieve value */
+ MOVL $0, AX
+ PUSHL AX
+ POPFL /* clear Id|Ac, EFLAGS initialised */
+ PUSHFL
+ POPL AX /* retrieve value */
+ XORL BX, AX
+ TESTL $0x040000, AX /* Ac */
+ JZ _cpu386 /* can't set this bit on 386 */
+ TESTL $0x200000, AX /* Id */
+ JZ _cpu486 /* can't toggle this bit on some 486 */
+ MOVL fn+0(FP), AX
+ CPUID
+ JMP _cpuid
+_cpu486:
+ MOVL $0x400, AX
+ JMP _maybezapax
+_cpu386:
+ MOVL $0x300, AX
+_maybezapax:
+ CMPL fn+0(FP), $1
+ JE _zaprest
+ XORL AX, AX
+_zaprest:
+ XORL BX, BX
+ XORL CX, CX
+ XORL DX, DX
+_cpuid:
+ MOVL regs+4(FP), BP
+ MOVL AX, 0(BP)
+ MOVL BX, 4(BP)
+ MOVL CX, 8(BP)
+ MOVL DX, 12(BP)
+ RET
+
+/*
+ * Basic timing loop to determine CPU frequency.
+ */
+TEXT aamloop(SB), $0
+ MOVL count+0(FP), CX
+_aamloop:
+ AAM
+ LOOP _aamloop
+ RET
+
+/*
+ * Floating point.
+ * Note: the encodings for the FCLEX, FINIT, FSAVE, FSTCW, FSENV and FSTSW
+ * instructions do NOT have the WAIT prefix byte (i.e. they act like their
+ * 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 */ ;\
+ MOVL AX, CR0
+
+#define FPON ;\
+ MOVL CR0, AX ;\
+ ANDL $~0xC, AX /* EM=0, TS=0 */ ;\
+ MOVL AX, CR0
+
+TEXT fpoff(SB), $0 /* disable */
+ FPOFF(l1)
+ RET
+
+TEXT fpinit(SB), $0 /* enable and init */
+ FPON
+ FINIT
+ WAIT
+ /* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */
+ /* note that low 6 bits are masks, not enables, on this chip */
+ PUSHW $0x0232
+ FLDCW 0(SP)
+ POPW AX
+ WAIT
+ RET
+
+TEXT fpsave(SB), $0 /* save state and disable */
+ MOVL p+0(FP), AX
+ FSAVE 0(AX) /* no WAIT */
+ FPOFF(l2)
+ RET
+
+TEXT fprestore(SB), $0 /* enable and restore state */
+ FPON
+ MOVL p+0(FP), AX
+ FRSTOR 0(AX)
+ WAIT
+ RET
+
+TEXT fpstatus(SB), $0 /* get floating point status */
+ FSTSW AX
+ RET
+
+TEXT fpenv(SB), $0 /* save state without waiting */
+ MOVL p+0(FP), AX
+ FSTENV 0(AX)
+ RET
+
+TEXT fpclear(SB), $0 /* clear pending exceptions */
+ FPON
+ FCLEX /* no WAIT */
+ FPOFF(l3)
+ RET
+
+/*
+ */
+TEXT splhi(SB), $0
+shi:
+ PUSHFL
+ POPL AX
+ TESTL $0x200, AX
+ JZ alreadyhi
+ MOVL $(MACHADDR+0x04), CX /* save PC in m->splpc */
+ MOVL (SP), BX
+ MOVL BX, (CX)
+alreadyhi:
+ CLI
+ RET
+
+TEXT spllo(SB), $0
+slo:
+ PUSHFL
+ POPL AX
+ TESTL $0x200, AX
+ JNZ alreadylo
+ MOVL $(MACHADDR+0x04), CX /* clear m->splpc */
+ MOVL $0, (CX)
+alreadylo:
+ STI
+ RET
+
+TEXT splx(SB), $0
+ MOVL s+0(FP), AX
+ TESTL $0x200, AX
+ JNZ slo
+ JMP shi
+
+TEXT spldone(SB), $0
+ RET
+
+TEXT islo(SB), $0
+ PUSHFL
+ POPL AX
+ ANDL $0x200, AX /* interrupt enable flag */
+ RET
+
+/*
+ * Test-And-Set
+ */
+TEXT tas(SB), $0
+ MOVL $0xDEADDEAD, AX
+ MOVL lock+0(FP), BX
+ XCHGL AX, (BX) /* lock->key */
+ RET
+
+TEXT _xinc(SB), $0 /* void _xinc(long*); */
+ MOVL l+0(FP), AX
+ LOCK; INCL 0(AX)
+ RET
+
+TEXT _xdec(SB), $0 /* long _xdec(long*); */
+ MOVL l+0(FP), BX
+ XORL AX, AX
+ LOCK; DECL 0(BX)
+ JLT _xdeclt
+ JGT _xdecgt
+ RET
+_xdecgt:
+ INCL AX
+ RET
+_xdeclt:
+ DECL AX
+ RET
+
+TEXT mb386(SB), $0
+ POPL AX /* return PC */
+ PUSHFL
+ PUSHL CS
+ PUSHL AX
+ IRETL
+
+TEXT mb586(SB), $0
+ XORL AX, AX
+ CPUID
+ RET
+
+TEXT sfence(SB), $0
+ BYTE $0x0f
+ BYTE $0xae
+ BYTE $0xf8
+ RET
+
+TEXT lfence(SB), $0
+ BYTE $0x0f
+ BYTE $0xae
+ BYTE $0xe8
+ RET
+
+TEXT mfence(SB), $0
+ BYTE $0x0f
+ BYTE $0xae
+ BYTE $0xf0
+ RET
+
+TEXT xchgw(SB), $0
+ MOVL v+4(FP), AX
+ MOVL p+0(FP), BX
+ XCHGW AX, (BX)
+ RET
+
+TEXT cmpswap486(SB), $0
+ MOVL addr+0(FP), BX
+ MOVL old+4(FP), AX
+ MOVL new+8(FP), CX
+ LOCK
+ BYTE $0x0F; BYTE $0xB1; BYTE $0x0B /* CMPXCHGL CX, (BX) */
+ JNZ didnt
+ MOVL $1, AX
+ RET
+didnt:
+ XORL AX,AX
+ RET
+
+TEXT mul64fract(SB), $0
+/*
+ * Multiply two 64-bit number s and keep the middle 64 bits from the 128-bit result
+ * See ../port/tod.c for motivation.
+ */
+ MOVL r+0(FP), CX
+ XORL BX, BX /* BX = 0 */
+
+ MOVL a+8(FP), AX
+ MULL b+16(FP) /* a1*b1 */
+ MOVL AX, 4(CX) /* r2 = lo(a1*b1) */
+
+ MOVL a+8(FP), AX
+ MULL b+12(FP) /* a1*b0 */
+ MOVL AX, 0(CX) /* r1 = lo(a1*b0) */
+ ADDL DX, 4(CX) /* r2 += hi(a1*b0) */
+
+ MOVL a+4(FP), AX
+ MULL b+16(FP) /* a0*b1 */
+ ADDL AX, 0(CX) /* r1 += lo(a0*b1) */
+ ADCL DX, 4(CX) /* r2 += hi(a0*b1) + carry */
+
+ MOVL a+4(FP), AX
+ MULL b+12(FP) /* a0*b0 */
+ ADDL DX, 0(CX) /* r1 += hi(a0*b0) */
+ ADCL BX, 4(CX) /* r2 += carry */
+ RET
+
+/*
+ * label consists of a stack pointer and a PC
+ */
+TEXT gotolabel(SB), $0
+ MOVL label+0(FP), AX
+ MOVL 0(AX), SP /* restore sp */
+ MOVL 4(AX), AX /* put return pc on the stack */
+ MOVL AX, 0(SP)
+ MOVL $1, AX /* return 1 */
+ RET
+
+TEXT setlabel(SB), $0
+ MOVL label+0(FP), AX
+ MOVL SP, 0(AX) /* store sp */
+ MOVL 0(SP), BX /* store return pc */
+ MOVL BX, 4(AX)
+ MOVL $0, AX /* return 0 */
+ RET
+
+/*
+ * Attempt at power saving. -rsc
+ */
+TEXT halt(SB), $0
+ CLI
+ CMPL nrdy(SB), $0
+ JEQ _nothingready
+ STI
+ RET
+
+_nothingready:
+ STI
+ HLT
+ RET
+
+/*
+ * Interrupt/exception handling.
+ * Each entry in the vector table calls either _strayintr or _strayintrx depending
+ * on whether an error code has been automatically pushed onto the stack
+ * (_strayintrx) or not, in which case a dummy entry must be pushed before retrieving
+ * the trap type from the vector table entry and placing it on the stack as part
+ * of the Ureg structure.
+ * The size of each entry in the vector table (6 bytes) is known in trapinit().
+ */
+TEXT _strayintr(SB), $0
+ PUSHL AX /* save AX */
+ MOVL 4(SP), AX /* return PC from vectortable(SB) */
+ JMP intrcommon
+
+TEXT _strayintrx(SB), $0
+ XCHGL AX, (SP) /* swap AX with vectortable CALL PC */
+intrcommon:
+ PUSHL DS /* save DS */
+ PUSHL $(KDSEL)
+ POPL DS /* fix up DS */
+ MOVBLZX (AX), AX /* trap type -> AX */
+ XCHGL AX, 4(SP) /* exchange trap type with saved AX */
+
+ PUSHL ES /* save ES */
+ PUSHL $(KDSEL)
+ POPL ES /* fix up ES */
+
+ PUSHL FS /* save the rest of the Ureg struct */
+ PUSHL GS
+ PUSHAL
+
+ PUSHL SP /* Ureg* argument to trap */
+ CALL trap(SB)
+
+TEXT forkret(SB), $0
+ POPL AX
+ POPAL
+ POPL GS
+ POPL FS
+ POPL ES
+ POPL DS
+ ADDL $8, SP /* pop error code and trap type */
+ IRETL
+
+TEXT vectortable(SB), $0
+ CALL _strayintr(SB); BYTE $0x00 /* divide error */
+ CALL _strayintr(SB); BYTE $0x01 /* debug exception */
+ CALL _strayintr(SB); BYTE $0x02 /* NMI interrupt */
+ CALL _strayintr(SB); BYTE $0x03 /* breakpoint */
+ CALL _strayintr(SB); BYTE $0x04 /* overflow */
+ CALL _strayintr(SB); BYTE $0x05 /* bound */
+ CALL _strayintr(SB); BYTE $0x06 /* invalid opcode */
+ CALL _strayintr(SB); BYTE $0x07 /* no coprocessor available */
+ CALL _strayintrx(SB); BYTE $0x08 /* double fault */
+ CALL _strayintr(SB); BYTE $0x09 /* coprocessor segment overflow */
+ CALL _strayintrx(SB); BYTE $0x0A /* invalid TSS */
+ CALL _strayintrx(SB); BYTE $0x0B /* segment not available */
+ CALL _strayintrx(SB); BYTE $0x0C /* stack exception */
+ CALL _strayintrx(SB); BYTE $0x0D /* general protection error */
+ CALL _strayintrx(SB); BYTE $0x0E /* page fault */
+ CALL _strayintr(SB); BYTE $0x0F /* */
+ CALL _strayintr(SB); BYTE $0x10 /* coprocessor error */
+ CALL _strayintrx(SB); BYTE $0x11 /* alignment check */
+ CALL _strayintr(SB); BYTE $0x12 /* machine check */
+ CALL _strayintr(SB); BYTE $0x13
+ CALL _strayintr(SB); BYTE $0x14
+ CALL _strayintr(SB); BYTE $0x15
+ CALL _strayintr(SB); BYTE $0x16
+ CALL _strayintr(SB); BYTE $0x17
+ CALL _strayintr(SB); BYTE $0x18
+ CALL _strayintr(SB); BYTE $0x19
+ CALL _strayintr(SB); BYTE $0x1A
+ CALL _strayintr(SB); BYTE $0x1B
+ CALL _strayintr(SB); BYTE $0x1C
+ CALL _strayintr(SB); BYTE $0x1D
+ CALL _strayintr(SB); BYTE $0x1E
+ CALL _strayintr(SB); BYTE $0x1F
+ CALL _strayintr(SB); BYTE $0x20 /* VectorLAPIC */
+ CALL _strayintr(SB); BYTE $0x21
+ CALL _strayintr(SB); BYTE $0x22
+ CALL _strayintr(SB); BYTE $0x23
+ CALL _strayintr(SB); BYTE $0x24
+ CALL _strayintr(SB); BYTE $0x25
+ CALL _strayintr(SB); BYTE $0x26
+ CALL _strayintr(SB); BYTE $0x27
+ CALL _strayintr(SB); BYTE $0x28
+ CALL _strayintr(SB); BYTE $0x29
+ CALL _strayintr(SB); BYTE $0x2A
+ CALL _strayintr(SB); BYTE $0x2B
+ CALL _strayintr(SB); BYTE $0x2C
+ CALL _strayintr(SB); BYTE $0x2D
+ CALL _strayintr(SB); BYTE $0x2E
+ CALL _strayintr(SB); BYTE $0x2F
+ CALL _strayintr(SB); BYTE $0x30
+ CALL _strayintr(SB); BYTE $0x31
+ CALL _strayintr(SB); BYTE $0x32
+ CALL _strayintr(SB); BYTE $0x33
+ CALL _strayintr(SB); BYTE $0x34
+ CALL _strayintr(SB); BYTE $0x35
+ CALL _strayintr(SB); BYTE $0x36
+ CALL _strayintr(SB); BYTE $0x37
+ CALL _strayintr(SB); BYTE $0x38
+ CALL _strayintr(SB); BYTE $0x39
+ CALL _strayintr(SB); BYTE $0x3A
+ CALL _strayintr(SB); BYTE $0x3B
+ CALL _strayintr(SB); BYTE $0x3C
+ CALL _strayintr(SB); BYTE $0x3D
+ CALL _strayintr(SB); BYTE $0x3E
+ CALL _strayintr(SB); BYTE $0x3F
+ CALL _syscallintr(SB); BYTE $0x40 /* VectorSYSCALL */
+ CALL _strayintr(SB); BYTE $0x41
+ CALL _strayintr(SB); BYTE $0x42
+ CALL _strayintr(SB); BYTE $0x43
+ CALL _strayintr(SB); BYTE $0x44
+ CALL _strayintr(SB); BYTE $0x45
+ CALL _strayintr(SB); BYTE $0x46
+ CALL _strayintr(SB); BYTE $0x47
+ CALL _strayintr(SB); BYTE $0x48
+ CALL _strayintr(SB); BYTE $0x49
+ CALL _strayintr(SB); BYTE $0x4A
+ CALL _strayintr(SB); BYTE $0x4B
+ CALL _strayintr(SB); BYTE $0x4C
+ CALL _strayintr(SB); BYTE $0x4D
+ CALL _strayintr(SB); BYTE $0x4E
+ CALL _strayintr(SB); BYTE $0x4F
+ CALL _strayintr(SB); BYTE $0x50
+ CALL _strayintr(SB); BYTE $0x51
+ CALL _strayintr(SB); BYTE $0x52
+ CALL _strayintr(SB); BYTE $0x53
+ CALL _strayintr(SB); BYTE $0x54
+ CALL _strayintr(SB); BYTE $0x55
+ CALL _strayintr(SB); BYTE $0x56
+ CALL _strayintr(SB); BYTE $0x57
+ CALL _strayintr(SB); BYTE $0x58
+ CALL _strayintr(SB); BYTE $0x59
+ CALL _strayintr(SB); BYTE $0x5A
+ CALL _strayintr(SB); BYTE $0x5B
+ CALL _strayintr(SB); BYTE $0x5C
+ CALL _strayintr(SB); BYTE $0x5D
+ CALL _strayintr(SB); BYTE $0x5E
+ CALL _strayintr(SB); BYTE $0x5F
+ CALL _strayintr(SB); BYTE $0x60
+ CALL _strayintr(SB); BYTE $0x61
+ CALL _strayintr(SB); BYTE $0x62
+ CALL _strayintr(SB); BYTE $0x63
+ CALL _strayintr(SB); BYTE $0x64
+ CALL _strayintr(SB); BYTE $0x65
+ CALL _strayintr(SB); BYTE $0x66
+ CALL _strayintr(SB); BYTE $0x67
+ CALL _strayintr(SB); BYTE $0x68
+ CALL _strayintr(SB); BYTE $0x69
+ CALL _strayintr(SB); BYTE $0x6A
+ CALL _strayintr(SB); BYTE $0x6B
+ CALL _strayintr(SB); BYTE $0x6C
+ CALL _strayintr(SB); BYTE $0x6D
+ CALL _strayintr(SB); BYTE $0x6E
+ CALL _strayintr(SB); BYTE $0x6F
+ CALL _strayintr(SB); BYTE $0x70
+ CALL _strayintr(SB); BYTE $0x71
+ CALL _strayintr(SB); BYTE $0x72
+ CALL _strayintr(SB); BYTE $0x73
+ CALL _strayintr(SB); BYTE $0x74
+ CALL _strayintr(SB); BYTE $0x75
+ CALL _strayintr(SB); BYTE $0x76
+ CALL _strayintr(SB); BYTE $0x77
+ CALL _strayintr(SB); BYTE $0x78
+ CALL _strayintr(SB); BYTE $0x79
+ CALL _strayintr(SB); BYTE $0x7A
+ CALL _strayintr(SB); BYTE $0x7B
+ CALL _strayintr(SB); BYTE $0x7C
+ CALL _strayintr(SB); BYTE $0x7D
+ CALL _strayintr(SB); BYTE $0x7E
+ CALL _strayintr(SB); BYTE $0x7F
+ CALL _strayintr(SB); BYTE $0x80 /* Vector[A]PIC */
+ CALL _strayintr(SB); BYTE $0x81
+ CALL _strayintr(SB); BYTE $0x82
+ CALL _strayintr(SB); BYTE $0x83
+ CALL _strayintr(SB); BYTE $0x84
+ CALL _strayintr(SB); BYTE $0x85
+ CALL _strayintr(SB); BYTE $0x86
+ CALL _strayintr(SB); BYTE $0x87
+ CALL _strayintr(SB); BYTE $0x88
+ CALL _strayintr(SB); BYTE $0x89
+ CALL _strayintr(SB); BYTE $0x8A
+ CALL _strayintr(SB); BYTE $0x8B
+ CALL _strayintr(SB); BYTE $0x8C
+ CALL _strayintr(SB); BYTE $0x8D
+ CALL _strayintr(SB); BYTE $0x8E
+ CALL _strayintr(SB); BYTE $0x8F
+ CALL _strayintr(SB); BYTE $0x90
+ CALL _strayintr(SB); BYTE $0x91
+ CALL _strayintr(SB); BYTE $0x92
+ CALL _strayintr(SB); BYTE $0x93
+ CALL _strayintr(SB); BYTE $0x94
+ CALL _strayintr(SB); BYTE $0x95
+ CALL _strayintr(SB); BYTE $0x96
+ CALL _strayintr(SB); BYTE $0x97
+ CALL _strayintr(SB); BYTE $0x98
+ CALL _strayintr(SB); BYTE $0x99
+ CALL _strayintr(SB); BYTE $0x9A
+ CALL _strayintr(SB); BYTE $0x9B
+ CALL _strayintr(SB); BYTE $0x9C
+ CALL _strayintr(SB); BYTE $0x9D
+ CALL _strayintr(SB); BYTE $0x9E
+ CALL _strayintr(SB); BYTE $0x9F
+ CALL _strayintr(SB); BYTE $0xA0
+ CALL _strayintr(SB); BYTE $0xA1
+ CALL _strayintr(SB); BYTE $0xA2
+ CALL _strayintr(SB); BYTE $0xA3
+ CALL _strayintr(SB); BYTE $0xA4
+ CALL _strayintr(SB); BYTE $0xA5
+ CALL _strayintr(SB); BYTE $0xA6
+ CALL _strayintr(SB); BYTE $0xA7
+ CALL _strayintr(SB); BYTE $0xA8
+ CALL _strayintr(SB); BYTE $0xA9
+ CALL _strayintr(SB); BYTE $0xAA
+ CALL _strayintr(SB); BYTE $0xAB
+ CALL _strayintr(SB); BYTE $0xAC
+ CALL _strayintr(SB); BYTE $0xAD
+ CALL _strayintr(SB); BYTE $0xAE
+ CALL _strayintr(SB); BYTE $0xAF
+ CALL _strayintr(SB); BYTE $0xB0
+ CALL _strayintr(SB); BYTE $0xB1
+ CALL _strayintr(SB); BYTE $0xB2
+ CALL _strayintr(SB); BYTE $0xB3
+ CALL _strayintr(SB); BYTE $0xB4
+ CALL _strayintr(SB); BYTE $0xB5
+ CALL _strayintr(SB); BYTE $0xB6
+ CALL _strayintr(SB); BYTE $0xB7
+ CALL _strayintr(SB); BYTE $0xB8
+ CALL _strayintr(SB); BYTE $0xB9
+ CALL _strayintr(SB); BYTE $0xBA
+ CALL _strayintr(SB); BYTE $0xBB
+ CALL _strayintr(SB); BYTE $0xBC
+ CALL _strayintr(SB); BYTE $0xBD
+ CALL _strayintr(SB); BYTE $0xBE
+ CALL _strayintr(SB); BYTE $0xBF
+ CALL _strayintr(SB); BYTE $0xC0
+ CALL _strayintr(SB); BYTE $0xC1
+ CALL _strayintr(SB); BYTE $0xC2
+ CALL _strayintr(SB); BYTE $0xC3
+ CALL _strayintr(SB); BYTE $0xC4
+ CALL _strayintr(SB); BYTE $0xC5
+ CALL _strayintr(SB); BYTE $0xC6
+ CALL _strayintr(SB); BYTE $0xC7
+ CALL _strayintr(SB); BYTE $0xC8
+ CALL _strayintr(SB); BYTE $0xC9
+ CALL _strayintr(SB); BYTE $0xCA
+ CALL _strayintr(SB); BYTE $0xCB
+ CALL _strayintr(SB); BYTE $0xCC
+ CALL _strayintr(SB); BYTE $0xCD
+ CALL _strayintr(SB); BYTE $0xCE
+ CALL _strayintr(SB); BYTE $0xCF
+ CALL _strayintr(SB); BYTE $0xD0
+ CALL _strayintr(SB); BYTE $0xD1
+ CALL _strayintr(SB); BYTE $0xD2
+ CALL _strayintr(SB); BYTE $0xD3
+ CALL _strayintr(SB); BYTE $0xD4
+ CALL _strayintr(SB); BYTE $0xD5
+ CALL _strayintr(SB); BYTE $0xD6
+ CALL _strayintr(SB); BYTE $0xD7
+ CALL _strayintr(SB); BYTE $0xD8
+ CALL _strayintr(SB); BYTE $0xD9
+ CALL _strayintr(SB); BYTE $0xDA
+ CALL _strayintr(SB); BYTE $0xDB
+ CALL _strayintr(SB); BYTE $0xDC
+ CALL _strayintr(SB); BYTE $0xDD
+ CALL _strayintr(SB); BYTE $0xDE
+ CALL _strayintr(SB); BYTE $0xDF
+ CALL _strayintr(SB); BYTE $0xE0
+ CALL _strayintr(SB); BYTE $0xE1
+ CALL _strayintr(SB); BYTE $0xE2
+ CALL _strayintr(SB); BYTE $0xE3
+ CALL _strayintr(SB); BYTE $0xE4
+ CALL _strayintr(SB); BYTE $0xE5
+ CALL _strayintr(SB); BYTE $0xE6
+ CALL _strayintr(SB); BYTE $0xE7
+ CALL _strayintr(SB); BYTE $0xE8
+ CALL _strayintr(SB); BYTE $0xE9
+ CALL _strayintr(SB); BYTE $0xEA
+ CALL _strayintr(SB); BYTE $0xEB
+ CALL _strayintr(SB); BYTE $0xEC
+ CALL _strayintr(SB); BYTE $0xED
+ CALL _strayintr(SB); BYTE $0xEE
+ CALL _strayintr(SB); BYTE $0xEF
+ CALL _strayintr(SB); BYTE $0xF0
+ CALL _strayintr(SB); BYTE $0xF1
+ CALL _strayintr(SB); BYTE $0xF2
+ CALL _strayintr(SB); BYTE $0xF3
+ CALL _strayintr(SB); BYTE $0xF4
+ CALL _strayintr(SB); BYTE $0xF5
+ CALL _strayintr(SB); BYTE $0xF6
+ CALL _strayintr(SB); BYTE $0xF7
+ CALL _strayintr(SB); BYTE $0xF8
+ CALL _strayintr(SB); BYTE $0xF9
+ CALL _strayintr(SB); BYTE $0xFA
+ CALL _strayintr(SB); BYTE $0xFB
+ CALL _strayintr(SB); BYTE $0xFC
+ CALL _strayintr(SB); BYTE $0xFD
+ CALL _strayintr(SB); BYTE $0xFE
+ CALL _strayintr(SB); BYTE $0xFF
diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c
new file mode 100755
index 000000000..f1e1fa20d
--- /dev/null
+++ b/sys/src/9/pc/main.c
@@ -0,0 +1,842 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "init.h"
+#include "pool.h"
+#include "reboot.h"
+
+Mach *m;
+
+/*
+ * Where configuration info is left for the loaded programme.
+ * This will turn into a structure as more is done by the boot loader
+ * (e.g. why parse the .ini file twice?).
+ * There are 3584 bytes available at CONFADDR.
+ */
+#define BOOTLINE ((char*)CONFADDR)
+#define BOOTLINELEN 64
+#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
+#define BOOTARGSLEN (4096-0x200-BOOTLINELEN)
+#define MAXCONF 64
+
+char bootdisk[KNAMELEN];
+Conf conf;
+char *confname[MAXCONF];
+char *confval[MAXCONF];
+int nconf;
+uchar *sp; /* user stack of init proc */
+int delaylink;
+
+static void
+options(void)
+{
+ long i, n;
+ char *cp, *line[MAXCONF], *p, *q;
+
+ /*
+ * parse configuration args from dos file plan9.ini
+ */
+ cp = BOOTARGS; /* where b.com leaves its config */
+ cp[BOOTARGSLEN-1] = 0;
+
+ /*
+ * Strip out '\r', change '\t' -> ' '.
+ */
+ p = cp;
+ for(q = cp; *q; q++){
+ if(*q == '\r')
+ continue;
+ if(*q == '\t')
+ *q = ' ';
+ *p++ = *q;
+ }
+ *p = 0;
+
+ n = getfields(cp, line, MAXCONF, 1, "\n");
+ for(i = 0; i < n; i++){
+ if(*line[i] == '#')
+ continue;
+ cp = strchr(line[i], '=');
+ if(cp == nil)
+ continue;
+ *cp++ = '\0';
+ confname[nconf] = line[i];
+ confval[nconf] = cp;
+ nconf++;
+ }
+}
+
+extern void mmuinit0(void);
+extern void (*i8237alloc)(void);
+
+void
+main(void)
+{
+ mach0init();
+ options();
+ ioinit();
+ i8250console();
+ quotefmtinstall();
+ screeninit();
+
+ print("\nPlan 9\n");
+
+ trapinit0();
+ mmuinit0();
+
+ kbdinit();
+ i8253init();
+ cpuidentify();
+ meminit();
+ confinit();
+ archinit();
+ xinit();
+ if(i8237alloc != nil)
+ i8237alloc();
+ trapinit();
+ printinit();
+ cpuidprint();
+ mmuinit();
+ if(arch->intrinit) /* launches other processors on an mp */
+ arch->intrinit();
+ timersinit();
+ mathinit();
+ kbdenable();
+ if(arch->clockenable)
+ arch->clockenable();
+ procinit0();
+ initseg();
+ if(delaylink){
+ bootlinks();
+ pcimatch(0, 0, 0);
+ }else
+ links();
+ conf.monitor = 1;
+ chandevreset();
+ pageinit();
+ i8253link();
+ swapinit();
+ userinit();
+ active.thunderbirdsarego = 1;
+ schedinit();
+}
+
+void
+mach0init(void)
+{
+ conf.nmach = 1;
+ MACHP(0) = (Mach*)CPU0MACH;
+ m->pdb = (ulong*)CPU0PDB;
+ m->gdt = (Segdesc*)CPU0GDT;
+
+ machinit();
+
+ active.machs = 1;
+ active.exiting = 0;
+}
+
+void
+machinit(void)
+{
+ int machno;
+ ulong *pdb;
+ Segdesc *gdt;
+
+ machno = m->machno;
+ pdb = m->pdb;
+ gdt = m->gdt;
+ memset(m, 0, sizeof(Mach));
+ m->machno = machno;
+ m->pdb = pdb;
+ m->gdt = gdt;
+ m->perf.period = 1;
+
+ /*
+ * For polled uart output at boot, need
+ * a default delay constant. 100000 should
+ * be enough for a while. Cpuidentify will
+ * calculate the real value later.
+ */
+ m->loopconst = 100000;
+}
+
+void
+init0(void)
+{
+ int i;
+ char buf[2*KNAMELEN];
+
+ up->nerrlab = 0;
+
+ spllo();
+
+ /*
+ * These are o.k. because rootinit is null.
+ * Then early kproc's will have a root and dot.
+ */
+ up->slash = namec("#/", Atodir, 0, 0);
+ pathclose(up->slash->path);
+ up->slash->path = newpath("/");
+ up->dot = cclone(up->slash);
+
+ chandevinit();
+
+ if(!waserror()){
+ snprint(buf, sizeof(buf), "%s %s", arch->id, conffile);
+ ksetenv("terminal", buf, 0);
+ ksetenv("cputype", "386", 0);
+ if(cpuserver)
+ ksetenv("service", "cpu", 0);
+ else
+ ksetenv("service", "terminal", 0);
+ for(i = 0; i < nconf; i++){
+ if(confname[i][0] != '*')
+ ksetenv(confname[i], confval[i], 0);
+ ksetenv(confname[i], confval[i], 1);
+ }
+ poperror();
+ }
+ kproc("alarm", alarmkproc, 0);
+ touser(sp);
+}
+
+void
+userinit(void)
+{
+ void *v;
+ Proc *p;
+ Segment *s;
+ Page *pg;
+
+ p = newproc();
+ p->pgrp = newpgrp();
+ p->egrp = smalloc(sizeof(Egrp));
+ p->egrp->ref = 1;
+ p->fgrp = dupfgrp(nil);
+ p->rgrp = newrgrp();
+ p->procmode = 0640;
+
+ kstrdup(&eve, "");
+ kstrdup(&p->text, "*init*");
+ kstrdup(&p->user, eve);
+
+ p->fpstate = FPinit;
+ fpoff();
+
+ /*
+ * Kernel Stack
+ *
+ * N.B. make sure there's enough space for syscall to check
+ * for valid args and
+ * 4 bytes for gotolabel's return PC
+ */
+ p->sched.pc = (ulong)init0;
+ p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
+
+ /*
+ * 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(0, 0, USTKTOP-BY2PG);
+ v = tmpmap(pg);
+ memset(v, 0, BY2PG);
+ segpage(s, pg);
+ bootargs(v);
+ tmpunmap(v);
+
+ /*
+ * Text
+ */
+ s = newseg(SG_TEXT, UTZERO, 1);
+ s->flushme++;
+ p->seg[TSEG] = s;
+ pg = newpage(0, 0, UTZERO);
+ memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
+ segpage(s, pg);
+ v = tmpmap(pg);
+ memset(v, 0, BY2PG);
+ memmove(v, initcode, sizeof initcode);
+ tmpunmap(v);
+
+ ready(p);
+}
+
+uchar *
+pusharg(char *p)
+{
+ int n;
+
+ n = strlen(p)+1;
+ sp -= n;
+ memmove(sp, p, n);
+ return sp;
+}
+
+void
+bootargs(void *base)
+{
+ int i, ac;
+ uchar *av[32];
+ uchar **lsp;
+ char *cp = BOOTLINE;
+ char buf[64];
+
+ sp = (uchar*)base + BY2PG - MAXSYSARG*BY2WD;
+
+ ac = 0;
+ av[ac++] = pusharg("/386/9dos");
+
+ /* when boot is changed to only use rc, this code can go away */
+ cp[BOOTLINELEN-1] = 0;
+ buf[0] = 0;
+ if(strncmp(cp, "fd", 2) == 0){
+ sprint(buf, "local!#f/fd%lddisk", strtol(cp+2, 0, 0));
+ av[ac++] = pusharg(buf);
+ } else if(strncmp(cp, "sd", 2) == 0){
+ sprint(buf, "local!#S/sd%c%c/fs", *(cp+2), *(cp+3));
+ av[ac++] = pusharg(buf);
+ } else if(strncmp(cp, "ether", 5) == 0)
+ av[ac++] = pusharg("-n");
+
+ /* 4 byte word align stack */
+ sp = (uchar*)((ulong)sp & ~3);
+
+ /* build argc, argv on stack */
+ sp -= (ac+1)*sizeof(sp);
+ lsp = (uchar**)sp;
+ for(i = 0; i < ac; i++)
+ *lsp++ = av[i] + ((USTKTOP - BY2PG) - (ulong)base);
+ *lsp = 0;
+ sp += (USTKTOP - BY2PG) - (ulong)base - sizeof(ulong);
+}
+
+char*
+getconf(char *name)
+{
+ int i;
+
+ for(i = 0; i < nconf; i++)
+ if(cistrcmp(confname[i], name) == 0)
+ return confval[i];
+ return 0;
+}
+
+static void
+writeconf(void)
+{
+ char *p, *q;
+ int n;
+
+ p = getconfenv();
+
+ if(waserror()) {
+ free(p);
+ nexterror();
+ }
+
+ /* convert to name=value\n format */
+ for(q=p; *q; q++) {
+ q += strlen(q);
+ *q = '=';
+ q += strlen(q);
+ *q = '\n';
+ }
+ n = q - p + 1;
+ if(n >= BOOTARGSLEN)
+ error("kernel configuration too large");
+ memset(BOOTLINE, 0, BOOTLINELEN);
+ memmove(BOOTARGS, p, n);
+ poperror();
+ free(p);
+}
+
+void
+confinit(void)
+{
+ char *p;
+ int i, userpcnt;
+ ulong kpages;
+
+ if(p = getconf("*kernelpercent"))
+ userpcnt = 100 - strtol(p, 0, 0);
+ else
+ userpcnt = 0;
+
+ 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)
+ conf.nproc *= 3;
+ if(conf.nproc > 2000)
+ conf.nproc = 2000;
+ conf.nimage = 200;
+ conf.nswap = conf.nproc*80;
+ conf.nswppo = 4096;
+
+ if(cpuserver) {
+ if(userpcnt < 10)
+ userpcnt = 70;
+ kpages = conf.npage - (conf.npage*userpcnt)/100;
+
+ /*
+ * Hack for the big boys. Only good while physmem < 4GB.
+ * Give the kernel fixed max + enough to allocate the
+ * page pool.
+ * This is an overestimate as conf.upages < conf.npages.
+ * The patch of nimage is a band-aid, scanning the whole
+ * page list in imagereclaim just takes too long.
+ */
+ if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){
+ kpages = (64*MB + conf.npage*sizeof(Page))/BY2PG;
+ conf.nimage = 2000;
+ kpages += (conf.nproc*KSTACK)/BY2PG;
+ }
+ } else {
+ if(userpcnt < 10) {
+ if(conf.npage*BY2PG < 16*MB)
+ userpcnt = 40;
+ else
+ userpcnt = 60;
+ }
+ kpages = conf.npage - (conf.npage*userpcnt)/100;
+
+ /*
+ * Make sure terminals with low memory get at least
+ * 4MB on the first Image chunk allocation.
+ */
+ 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;
+
+ /*
+ * Guess how much is taken by the large permanent
+ * datastructures. Mntcache and Mntrpc are not accounted for
+ * (probably ~300KB).
+ */
+ kpages *= BY2PG;
+ kpages -= conf.upages*sizeof(Page)
+ + conf.nproc*sizeof(Proc)
+ + conf.nimage*sizeof(Image)
+ + conf.nswap
+ + conf.nswppo*sizeof(Page);
+ mainmem->maxsize = kpages;
+ if(!cpuserver){
+ /*
+ * give terminals lots of image memory, too; the dynamic
+ * allocation will balance the load properly, hopefully.
+ * be careful with 32-bit overflow.
+ */
+ imagmem->maxsize = kpages;
+ }
+}
+
+static char* mathmsg[] =
+{
+ nil, /* handled below */
+ "denormalized operand",
+ "division by zero",
+ "numeric overflow",
+ "numeric underflow",
+ "precision loss",
+};
+
+static void
+mathnote(void)
+{
+ int i;
+ ulong status;
+ char *msg, note[ERRMAX];
+
+ status = up->fpsave.status;
+
+ /*
+ * Some attention should probably be paid here to the
+ * exception masks and error summary.
+ */
+ msg = "unknown exception";
+ for(i = 1; i <= 5; i++){
+ if(!((1<<i) & status))
+ continue;
+ msg = mathmsg[i];
+ break;
+ }
+ if(status & 0x01){
+ if(status & 0x40){
+ if(status & 0x200)
+ msg = "stack overflow";
+ else
+ msg = "stack underflow";
+ }else
+ msg = "invalid operation";
+ }
+ snprint(note, sizeof note, "sys: fp: %s fppc=0x%lux status=0x%lux",
+ msg, up->fpsave.pc, status);
+ postnote(up, 1, note, NDebug);
+}
+
+/*
+ * math coprocessor error
+ */
+static void
+matherror(Ureg *ur, void*)
+{
+ /*
+ * a write cycle to port 0xF0 clears the interrupt latch attached
+ * to the error# line from the 387
+ */
+ if(!(m->cpuiddx & 0x01))
+ outb(0xF0, 0xFF);
+
+ /*
+ * save floating point state to check out error
+ */
+ fpenv(&up->fpsave);
+ mathnote();
+
+ if((ur->pc & 0xf0000000) == KZERO)
+ panic("fp: status %ux fppc=0x%lux pc=0x%lux",
+ up->fpsave.status, up->fpsave.pc, ur->pc);
+}
+
+/*
+ * math coprocessor emulation fault
+ */
+static void
+mathemu(Ureg *ureg, void*)
+{
+ if(up->fpstate & FPillegal){
+ /* someone did floating point in a note handler */
+ postnote(up, 1, "sys: floating point in note handler", NDebug);
+ return;
+ }
+ switch(up->fpstate){
+ case FPinit:
+ fpinit();
+ up->fpstate = FPactive;
+ break;
+ case FPinactive:
+ /*
+ * Before restoring the state, check for any pending
+ * exceptions, there's no way to restore the state without
+ * generating an unmasked exception.
+ * More attention should probably be paid here to the
+ * exception masks and error summary.
+ */
+ if((up->fpsave.status & ~up->fpsave.control) & 0x07F){
+ mathnote();
+ break;
+ }
+ fprestore(&up->fpsave);
+ up->fpstate = FPactive;
+ break;
+ case FPactive:
+ panic("math emu pid %ld %s pc 0x%lux",
+ up->pid, up->text, ureg->pc);
+ break;
+ }
+}
+
+/*
+ * math coprocessor segment overrun
+ */
+static void
+mathover(Ureg*, void*)
+{
+ pexit("math overrun", 0);
+}
+
+void
+mathinit(void)
+{
+ trapenable(VectorCERR, matherror, 0, "matherror");
+ if(X86FAMILY(m->cpuidax) == 3)
+ intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror");
+ trapenable(VectorCNA, mathemu, 0, "mathemu");
+ trapenable(VectorCSO, mathover, 0, "mathover");
+}
+
+/*
+ * set up floating point for a new process
+ */
+void
+procsetup(Proc*p)
+{
+ p->fpstate = FPinit;
+ fpoff();
+}
+
+void
+procrestore(Proc *p)
+{
+ uvlong t;
+
+ if(p->kp)
+ return;
+ cycles(&t);
+ p->pcycles -= t;
+}
+
+/*
+ * Save the mach dependent part of the process state.
+ */
+void
+procsave(Proc *p)
+{
+ uvlong t;
+
+ cycles(&t);
+ p->pcycles += t;
+ if(p->fpstate == FPactive){
+ if(p->state == Moribund)
+ fpclear();
+ else{
+ /*
+ * Fpsave() stores without handling pending
+ * unmasked exeptions. Postnote() can't be called
+ * here as sleep() already has up->rlock, so
+ * the handling of pending exceptions is delayed
+ * until the process runs again and generates an
+ * emulation fault to activate the FPU.
+ */
+ fpsave(&p->fpsave);
+ }
+ p->fpstate = FPinactive;
+ }
+
+ /*
+ * While this processor is in the scheduler, the process could run
+ * on another processor and exit, returning the page tables to
+ * the free list where they could be reallocated and overwritten.
+ * When this processor eventually has to get an entry from the
+ * trashed page tables it will crash.
+ *
+ * If there's only one processor, this can't happen.
+ * You might think it would be a win not to do this in that case,
+ * especially on VMware, but it turns out not to matter.
+ */
+ mmuflushtlb(PADDR(m->pdb));
+}
+
+static void
+shutdown(int ispanic)
+{
+ int ms, once;
+
+ lock(&active);
+ if(ispanic)
+ active.ispanic = ispanic;
+ else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
+ active.ispanic = 0;
+ once = active.machs & (1<<m->machno);
+ /*
+ * setting exiting will make hzclock() on each processor call exit(0),
+ * which calls shutdown(0) and arch->reset(), which on mp systems is
+ * mpshutdown, from which there is no return: the processor is idled
+ * or initiates a reboot. clearing our bit in machs avoids calling
+ * exit(0) from hzclock() on this processor.
+ */
+ active.machs &= ~(1<<m->machno);
+ active.exiting = 1;
+ unlock(&active);
+
+ if(once)
+ iprint("cpu%d: exiting\n", m->machno);
+
+ /* wait for any other processors to shutdown */
+ spllo();
+ for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
+ delay(TK2MS(2));
+ if(active.machs == 0 && consactive() == 0)
+ break;
+ }
+
+ if(active.ispanic){
+ if(!cpuserver)
+ for(;;)
+ halt();
+ if(getconf("*debug"))
+ delay(5*60*1000);
+ else
+ delay(10000);
+ }else
+ delay(1000);
+}
+
+void
+reboot(void *entry, void *code, ulong size)
+{
+ void (*f)(ulong, ulong, ulong);
+ ulong *pdb;
+
+ writeconf();
+
+ /*
+ * the boot processor is cpu0. execute this function on it
+ * so that the new kernel has the same cpu0. this only matters
+ * because the hardware has a notion of which processor was the
+ * boot processor and we look at it at start up.
+ */
+ if (m->machno != 0) {
+ procwired(up, 0);
+ sched();
+ }
+
+ shutdown(0);
+
+ /*
+ * should be the only processor running now
+ */
+ if (m->machno != 0)
+ print("on cpu%d (not 0)!\n", m->machno);
+ if (active.machs)
+ print("still have active ap processors!\n");
+
+ print("shutting down...\n");
+ delay(200);
+
+ splhi();
+
+ /* turn off buffered serial console */
+ serialoq = nil;
+
+ /* shutdown devices */
+ chandevshutdown();
+ arch->introff();
+
+ /*
+ * Modify the machine page table to directly map the low 4MB of memory
+ * This allows the reboot code to turn off the page mapping
+ */
+ pdb = m->pdb;
+ pdb[PDX(0)] = pdb[PDX(KZERO)];
+ mmuflushtlb(PADDR(pdb));
+
+ /* setup reboot trampoline function */
+ f = (void*)REBOOTADDR;
+ memmove(f, rebootcode, sizeof(rebootcode));
+
+ print("rebooting...\n");
+
+ /* off we go - never to return */
+ coherence();
+ (*f)(PADDR(entry), PADDR(code), size);
+}
+
+
+void
+exit(int ispanic)
+{
+ shutdown(ispanic);
+ arch->reset();
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ char cc[32], *p;
+ int i;
+
+ snprint(cc, sizeof cc, "%s%d", class, ctlrno);
+ p = getconf(cc);
+ if(p == nil)
+ return 0;
+
+ isa->type = "";
+ isa->nopt = tokenize(p, isa->opt, NISAOPT);
+ for(i = 0; i < isa->nopt; i++){
+ p = isa->opt[i];
+ if(cistrncmp(p, "type=", 5) == 0)
+ isa->type = p + 5;
+ else if(cistrncmp(p, "port=", 5) == 0)
+ isa->port = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "irq=", 4) == 0)
+ isa->irq = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "dma=", 4) == 0)
+ isa->dma = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "mem=", 4) == 0)
+ isa->mem = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "size=", 5) == 0)
+ isa->size = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "freq=", 5) == 0)
+ isa->freq = strtoul(p+5, &p, 0);
+ }
+ return 1;
+}
+
+int
+cistrcmp(char *a, char *b)
+{
+ int ac, bc;
+
+ for(;;){
+ ac = *a++;
+ bc = *b++;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+ return 0;
+}
+
+int
+cistrncmp(char *a, char *b, int n)
+{
+ unsigned ac, bc;
+
+ while(n > 0){
+ ac = *a++;
+ bc = *b++;
+ n--;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * put the processor in the halt state if we've no processes to run.
+ * an interrupt will get us going again.
+ */
+void
+idlehands(void)
+{
+ if(conf.nmach == 1)
+ halt();
+}
diff --git a/sys/src/9/pc/mem.h b/sys/src/9/pc/mem.h
new file mode 100755
index 000000000..184e86c72
--- /dev/null
+++ b/sys/src/9/pc/mem.h
@@ -0,0 +1,164 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+
+#define MIN(a, b) ((a) < (b)? (a): (b))
+#define MAX(a, b) ((a) > (b)? (a): (b))
+
+/*
+ * Sizes
+ */
+#define BI2BY 8 /* bits per byte */
+#define BI2WD 32 /* bits per word */
+#define BY2WD 4 /* bytes per word */
+#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)
+#define BLOCKALIGN 8
+
+/*
+ * In 32-bit mode, the MAXMACH limit is 32 without
+ * changing the way active.machs is defined and used
+ * (unfortunately, it is also used in the port code).
+ */
+#define MAXMACH 32 /* max # cpus system can run */
+#define KSTACK 4096 /* Size of kernel stack */
+
+/*
+ * Time
+ */
+#define HZ (100) /* clock frequency */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+
+/*
+ * Address spaces
+ */
+#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 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 /* pages in new stack; limits exec args */
+
+/*
+ * 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 (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
+#define CPU0PTE1 (KZERO+0x17000) /* bootstrap processor PTE's for 4MB-8MB */
+#define CPU0END (CPU0PTE1+BY2PG)
+/*
+ * N.B. ramscan knows that CPU0END is the end of reserved data
+ * N.B. _startPADDR knows that CPU0PDB is the first reserved page
+ * and that there are 6 of them.
+ */
+
+/*
+ * known x86 segments (in GDT) and their selectors
+ */
+#define NULLSEG 0 /* null segment */
+#define KDSEG 1 /* kernel data/stack */
+#define KESEG 2 /* kernel executable */
+#define UDSEG 3 /* user data/stack */
+#define UESEG 4 /* user executable */
+#define TSSSEG 5 /* task segment */
+#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 */
+
+#define SELGDT (0<<2) /* selector is in gdt */
+#define SELLDT (1<<2) /* selector is in ldt */
+
+#define SELECTOR(i, t, p) (((i)<<3) | (t) | (p))
+
+#define NULLSEL SELECTOR(NULLSEG, SELGDT, 0)
+#define KDSEL SELECTOR(KDSEG, SELGDT, 0)
+#define KESEL SELECTOR(KESEG, SELGDT, 0)
+#define UESEL SELECTOR(UESEG, SELGDT, 3)
+#define UDSEL SELECTOR(UDSEG, SELGDT, 3)
+#define TSSSEL SELECTOR(TSSSEG, SELGDT, 0)
+#define APMCSEL SELECTOR(APMCSEG, SELGDT, 0)
+#define APMCSEL16 SELECTOR(APMCSEG16, SELGDT, 0)
+#define APMDSEL SELECTOR(APMDSEG, SELGDT, 0)
+/* #define APM40SEL SELECTOR(APM40SEG, SELGDT, 0) */
+
+/*
+ * fields in segment descriptors
+ */
+#define SEGDATA (0x10<<8) /* data/stack segment */
+#define SEGEXEC (0x18<<8) /* executable segment */
+#define SEGTSS (0x9<<8) /* TSS segment */
+#define SEGCG (0x0C<<8) /* call gate */
+#define SEGIG (0x0E<<8) /* interrupt gate */
+#define SEGTG (0x0F<<8) /* trap gate */
+#define SEGTYPE (0x1F<<8)
+
+#define SEGP (1<<15) /* segment present */
+#define SEGPL(x) ((x)<<13) /* priority level */
+#define SEGB (1<<22) /* granularity 1==4k (for expand-down) */
+#define SEGG (1<<23) /* granularity 1==4k (for other) */
+#define SEGE (1<<10) /* expand down */
+#define SEGW (1<<9) /* writable (for data/stack) */
+#define SEGR (1<<9) /* readable (for code) */
+#define SEGD (1<<22) /* default 1==32bit (for code) */
+
+/*
+ * virtual MMU
+ */
+#define PTEMAPMEM (1024*1024)
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 1984
+#define SSEGMAPSIZE 16
+#define PPN(x) ((x)&~(BY2PG-1))
+
+/*
+ * physical MMU
+ */
+#define PTEVALID (1<<0)
+#define PTEWT (1<<3)
+#define PTEUNCACHED (1<<4)
+#define PTEWRITE (1<<1)
+#define PTERONLY (0<<1)
+#define PTEKERNEL (0<<2)
+#define PTEUSER (1<<2)
+#define PTESIZE (1<<7)
+#define PTEGLOBAL (1<<8)
+
+/*
+ * Macros for calculating offsets within the page directory base
+ * and page tables.
+ */
+#define PDX(va) ((((ulong)(va))>>22) & 0x03FF)
+#define PTX(va) ((((ulong)(va))>>12) & 0x03FF)
+
+#define getpgcolor(a) 0
+
diff --git a/sys/src/9/pc/memory.c b/sys/src/9/pc/memory.c
new file mode 100755
index 000000000..edf52623e
--- /dev/null
+++ b/sys/src/9/pc/memory.c
@@ -0,0 +1,899 @@
+/*
+ * Size memory and create the kernel page-tables on the fly while doing so.
+ * Called from main(), this code should only be run by the bootstrap processor.
+ *
+ * MemMin is what the bootstrap code in l.s has already mapped;
+ * MemMax is the limit of physical memory to scan.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+#define MEMDEBUG 0
+
+enum {
+ MemUPA = 0, /* unbacked physical address */
+ MemRAM = 1, /* physical memory */
+ MemUMB = 2, /* upper memory block (<16MB) */
+ MemReserved = 3,
+ NMemType = 4,
+
+ KB = 1024,
+
+ MemMin = 8*MB,
+ MemMax = (3*1024+768)*MB,
+};
+
+typedef struct Map Map;
+struct Map {
+ ulong size;
+ ulong addr;
+};
+
+typedef struct RMap RMap;
+struct RMap {
+ char* name;
+ Map* map;
+ Map* mapend;
+
+ Lock;
+};
+
+/*
+ * Memory allocation tracking.
+ */
+static Map mapupa[16];
+static RMap rmapupa = {
+ "unallocated unbacked physical memory",
+ mapupa,
+ &mapupa[nelem(mapupa)-1],
+};
+
+static Map xmapupa[16];
+static RMap xrmapupa = {
+ "unbacked physical memory",
+ xmapupa,
+ &xmapupa[nelem(xmapupa)-1],
+};
+
+static Map mapram[16];
+static RMap rmapram = {
+ "physical memory",
+ mapram,
+ &mapram[nelem(mapram)-1],
+};
+
+static Map mapumb[64];
+static RMap rmapumb = {
+ "upper memory block",
+ mapumb,
+ &mapumb[nelem(mapumb)-1],
+};
+
+static Map mapumbrw[16];
+static RMap rmapumbrw = {
+ "UMB device memory",
+ mapumbrw,
+ &mapumbrw[nelem(mapumbrw)-1],
+};
+
+void
+mapprint(RMap *rmap)
+{
+ Map *mp;
+
+ print("%s\n", rmap->name);
+ for(mp = rmap->map; mp->size; mp++)
+ print("\t%8.8luX %8.8luX (%lud)\n", mp->addr, mp->addr+mp->size, mp->size);
+}
+
+
+void
+memdebug(void)
+{
+ ulong maxpa, maxpa1, maxpa2;
+
+ maxpa = (nvramread(0x18)<<8)|nvramread(0x17);
+ maxpa1 = (nvramread(0x31)<<8)|nvramread(0x30);
+ maxpa2 = (nvramread(0x16)<<8)|nvramread(0x15);
+ print("maxpa = %luX -> %luX, maxpa1 = %luX maxpa2 = %luX\n",
+ maxpa, MB+maxpa*KB, maxpa1, maxpa2);
+
+ mapprint(&rmapram);
+ mapprint(&rmapumb);
+ mapprint(&rmapumbrw);
+ mapprint(&rmapupa);
+}
+
+void
+mapfree(RMap* rmap, ulong addr, ulong size)
+{
+ Map *mp;
+ ulong t;
+
+ if(size <= 0)
+ return;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
+ ;
+
+ if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
+ (mp-1)->size += size;
+ if(addr+size == mp->addr){
+ (mp-1)->size += mp->size;
+ while(mp->size){
+ mp++;
+ (mp-1)->addr = mp->addr;
+ (mp-1)->size = mp->size;
+ }
+ }
+ }
+ else{
+ if(addr+size == mp->addr && mp->size){
+ mp->addr -= size;
+ mp->size += size;
+ }
+ else do{
+ if(mp >= rmap->mapend){
+ print("mapfree: %s: losing 0x%luX, %ld\n",
+ rmap->name, addr, size);
+ break;
+ }
+ t = mp->addr;
+ mp->addr = addr;
+ addr = t;
+ t = mp->size;
+ mp->size = size;
+ mp++;
+ }while(size = t);
+ }
+ unlock(rmap);
+}
+
+ulong
+mapalloc(RMap* rmap, ulong addr, int size, int align)
+{
+ Map *mp;
+ ulong maddr, oaddr;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->size; mp++){
+ maddr = mp->addr;
+
+ if(addr){
+ /*
+ * A specific address range has been given:
+ * if the current map entry is greater then
+ * the address is not in the map;
+ * if the current map entry does not overlap
+ * the beginning of the requested range then
+ * continue on to the next map entry;
+ * if the current map entry does not entirely
+ * contain the requested range then the range
+ * is not in the map.
+ */
+ if(maddr > addr)
+ break;
+ if(mp->size < addr - maddr) /* maddr+mp->size < addr, but no overflow */
+ continue;
+ if(addr - maddr > mp->size - size) /* addr+size > maddr+mp->size, but no overflow */
+ break;
+ maddr = addr;
+ }
+
+ if(align > 0)
+ maddr = ((maddr+align-1)/align)*align;
+ if(mp->addr+mp->size-maddr < size)
+ continue;
+
+ oaddr = mp->addr;
+ mp->addr = maddr+size;
+ mp->size -= maddr-oaddr+size;
+ if(mp->size == 0){
+ do{
+ mp++;
+ (mp-1)->addr = mp->addr;
+ }while((mp-1)->size = mp->size);
+ }
+
+ unlock(rmap);
+ if(oaddr != maddr)
+ mapfree(rmap, oaddr, maddr-oaddr);
+
+ return maddr;
+ }
+ unlock(rmap);
+
+ 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
+umbexclude(void)
+{
+ int size;
+ ulong addr;
+ char *op, *p, *rptr;
+
+ if((p = getconf("umbexclude")) == nil)
+ return;
+
+ while(p && *p != '\0' && *p != '\n'){
+ op = p;
+ addr = strtoul(p, &rptr, 0);
+ if(rptr == nil || rptr == p || *rptr != '-'){
+ print("umbexclude: invalid argument <%s>\n", op);
+ break;
+ }
+ p = rptr+1;
+
+ size = strtoul(p, &rptr, 0) - addr + 1;
+ if(size <= 0){
+ print("umbexclude: bad range <%s>\n", op);
+ break;
+ }
+ if(rptr != nil && *rptr == ',')
+ *rptr++ = '\0';
+ p = rptr;
+
+ mapalloc(&rmapumb, addr, size, 0);
+ }
+}
+
+static void
+umbscan(void)
+{
+ uchar *p;
+
+ /*
+ * Scan the Upper Memory Blocks (0xA0000->0xF0000) for pieces
+ * which aren't used; they can be used later for devices which
+ * want to allocate some virtual address space.
+ * Check for two things:
+ * 1) device BIOS ROM. This should start with a two-byte header
+ * of 0x55 0xAA, followed by a byte giving the size of the ROM
+ * in 512-byte chunks. These ROM's must start on a 2KB boundary.
+ * 2) device memory. This is read-write.
+ * There are some assumptions: there's VGA memory at 0xA0000 and
+ * the VGA BIOS ROM is at 0xC0000. Also, if there's no ROM signature
+ * at 0xE0000 then the whole 64KB up to 0xF0000 is theoretically up
+ * for grabs; check anyway.
+ */
+ p = KADDR(0xD0000);
+ while(p < (uchar*)KADDR(0xE0000)){
+ /*
+ * Test for 0x55 0xAA before poking obtrusively,
+ * some machines (e.g. Thinkpad X20) seem to map
+ * something dynamic here (cardbus?) causing weird
+ * problems if it is changed.
+ */
+ if(p[0] == 0x55 && p[1] == 0xAA){
+ p += p[2]*512;
+ continue;
+ }
+
+ p[0] = 0xCC;
+ p[2*KB-1] = 0xCC;
+ if(p[0] != 0xCC || p[2*KB-1] != 0xCC){
+ p[0] = 0x55;
+ p[1] = 0xAA;
+ p[2] = 4;
+ if(p[0] == 0x55 && p[1] == 0xAA){
+ p += p[2]*512;
+ continue;
+ }
+ if(p[0] == 0xFF && p[1] == 0xFF)
+ mapfree(&rmapumb, PADDR(p), 2*KB);
+ }
+ else
+ mapfree(&rmapumbrw, PADDR(p), 2*KB);
+ p += 2*KB;
+ }
+
+ p = KADDR(0xE0000);
+ if(p[0] != 0x55 || p[1] != 0xAA){
+ p[0] = 0xCC;
+ p[64*KB-1] = 0xCC;
+ if(p[0] != 0xCC && p[64*KB-1] != 0xCC)
+ mapfree(&rmapumb, PADDR(p), 64*KB);
+ }
+
+ umbexclude();
+}
+
+static void
+lowraminit(void)
+{
+ ulong n, pa, x;
+ uchar *bda;
+
+ /*
+ * Initialise the memory bank information for conventional memory
+ * (i.e. less than 640KB). The base is the first location after the
+ * bootstrap processor MMU information and the limit is obtained from
+ * the BIOS data area.
+ */
+ x = PADDR(CPU0END);
+ bda = (uchar*)KADDR(0x400);
+ n = ((bda[0x14]<<8)|bda[0x13])*KB-x;
+ mapfree(&rmapram, x, n);
+ memset(KADDR(x), 0, n); /* keep us honest */
+
+ x = PADDR(PGROUND((ulong)end));
+ pa = MemMin;
+ if(x > pa)
+ panic("kernel too big");
+ 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 MemMin 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 = MemMin;
+
+ /*
+ * Check if the extended memory size can be obtained from the CMOS.
+ * If it's 0 then it's either not known or >= 64MB. Always check
+ * at least 24MB in case there's a memory gap (up to 8MB) below 16MB;
+ * in this case the memory from the gap is remapped to the top of
+ * memory.
+ * The value in CMOS is supposed to be the number of KB above 1MB.
+ */
+ if(maxmem == 0){
+ x = (nvramread(0x18)<<8)|nvramread(0x17);
+ if(x == 0 || x >= (63*KB))
+ maxpa = MemMax;
+ else
+ maxpa = MB+x*KB;
+ if(maxpa < 24*MB)
+ maxpa = 24*MB;
+ }else
+ maxpa = maxmem;
+ maxkpa = (u32int)-KZERO; /* 2^32 - KZERO */
+
+ /*
+ * March up memory from MemMin to maxpa 1MB at a time,
+ * mapping the first page and checking the page can
+ * be written and read correctly. The page tables are created here
+ * on the fly, allocating from low memory as necessary.
+ */
+ k0 = (ulong*)KADDR(0);
+ kzero = *k0;
+ 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
+ * MemMin->MemMin+4MB while we are scanning.
+ */
+ vbase = MemMin;
+ 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. Map in a fixed range (the second 4M)
+ * because high physical addresses cannot be passed to KADDR.
+ */
+ va = (void*)(vbase + pa%(4*MB));
+ table = &m->pdb[PDX(va)];
+ if(pa%(4*MB) == 0){
+ if(map == 0 && (map = mapalloc(&rmapram, 0, BY2PG, BY2PG)) == 0)
+ break;
+ memset(KADDR(map), 0, BY2PG);
+ *table = map|PTEWRITE|PTEVALID;
+ memset(nvalid, 0, sizeof(nvalid));
+ }
+ table = KADDR(PPN(*table));
+ pte = &table[PTX(va)];
+
+ *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 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
+ * chunk is marked uncached and added to the UMB pool if <16MB
+ * or is marked invalid and added to the UPA pool.
+ */
+ *va = x;
+ *k0 = ~x;
+ if(*va == x){
+ nvalid[MemRAM] += MB/BY2PG;
+ mapfree(&rmapram, pa, MB);
+
+ do{
+ *pte++ = pa|PTEWRITE|PTEVALID;
+ pa += BY2PG;
+ }while(pa % MB);
+ mmuflushtlb(PADDR(m->pdb));
+ /* memset(va, 0, MB); so damn slow to memset all of memory */
+ }
+ else if(pa < 16*MB){
+ nvalid[MemUMB] += MB/BY2PG;
+ mapfree(&rmapumb, pa, MB);
+
+ do{
+ *pte++ = pa|PTEWRITE|PTEUNCACHED|PTEVALID;
+ pa += BY2PG;
+ }while(pa % MB);
+ }
+ else{
+ nvalid[MemUPA] += MB/BY2PG;
+ mapfree(&rmapupa, pa, MB);
+
+ *pte = 0;
+ pa += MB;
+ }
+ /*
+ * Done with this 4MB chunk, review the options:
+ * 1) not physical memory and >=16MB - invalidate the PDB entry;
+ * 2) physical memory - use the 4MB page extension if possible;
+ * 3) not physical memory and <16MB - use the 4MB page extension
+ * if possible;
+ * 4) mixed or no 4MB page extension - commit the already
+ * initialised space for the page table.
+ */
+ 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{
+ *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) && pa <= maxkpa){
+ m->pdb[PDX(KADDR(pa))] = map|PTEWRITE|PTEVALID;
+ map = 0;
+ }
+ if(map)
+ mapfree(&rmapram, map, BY2PG);
+
+ 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 MemMin to make below simpler.
+ */
+ if(base < MemMin && len > MemMin-base){
+ n = MemMin - base;
+ map(base, n, type);
+ map(MemMin, len-n, type);
+ }
+
+ /*
+ * Let lowraminit and umbscan hash out the low MemMin.
+ */
+ if(base < MemMin)
+ 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 CPU0END is reserved for the kernel
+ * and already mapped.
+ */
+ if(base < PADDR(CPU0END)){
+ n = PADDR(CPU0END) - base;
+ if(len <= n)
+ return;
+ map(PADDR(CPU0END), 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|PTEVALID;
+ break;
+ case MemUMB:
+ mapfree(&rmapumb, base, len);
+ flags = PTEWRITE|PTEUNCACHED|PTEVALID;
+ break;
+ case MemUPA:
+ mapfree(&rmapupa, base, len);
+ flags = 0;
+ break;
+ default:
+ case MemReserved:
+ flags = 0;
+ break;
+ }
+
+ /*
+ * bottom MemMin is already mapped - just twiddle flags.
+ * (not currently used - see above)
+ */
+ if(base < MemMin){
+ 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.
+ */
+ if(flags){
+ 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, len;
+ uvlong last;
+ 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);
+
+ if(getconf("*noe820print") == nil){
+ 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);
+ }
+ if(last < (1LL<<32))
+ map(last, (u32int)-last, MemUPA);
+ return 0;
+}
+
+void
+meminit(void)
+{
+ int i;
+ Map *mp;
+ Confmem *cm;
+ ulong pa, *pte;
+ ulong maxmem, lost;
+ char *p;
+
+ if(p = getconf("*maxmem"))
+ maxmem = strtoul(p, 0, 0);
+ else
+ maxmem = 0;
+
+ /*
+ * Set special attributes for memory between 640KB and 1MB:
+ * VGA memory is writethrough;
+ * BIOS ROM's/UMB's are uncached;
+ * then scan for useful memory.
+ */
+ for(pa = 0xA0000; pa < 0xC0000; pa += BY2PG){
+ pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 2, 0);
+ *pte |= PTEWT;
+ }
+ for(pa = 0xC0000; pa < 0x100000; pa += BY2PG){
+ pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 2, 0);
+ *pte |= PTEUNCACHED;
+ }
+ mmuflushtlb(PADDR(m->pdb));
+
+ umbscan();
+ lowraminit();
+ if(e820scan() < 0)
+ ramscan(maxmem);
+
+ /*
+ * Set the conf entries describing banks of allocatable memory.
+ */
+ 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(MEMDEBUG)
+ memdebug();
+}
+
+/*
+ * Allocate memory from the upper memory blocks.
+ */
+ulong
+umbmalloc(ulong addr, int size, int align)
+{
+ ulong a;
+
+ if(a = mapalloc(&rmapumb, addr, size, align))
+ return (ulong)KADDR(a);
+
+ return 0;
+}
+
+void
+umbfree(ulong addr, int size)
+{
+ mapfree(&rmapumb, PADDR(addr), size);
+}
+
+ulong
+umbrwmalloc(ulong addr, int size, int align)
+{
+ ulong a;
+ uchar *p;
+
+ if(a = mapalloc(&rmapumbrw, addr, size, align))
+ return(ulong)KADDR(a);
+
+ /*
+ * Perhaps the memory wasn't visible before
+ * the interface is initialised, so try again.
+ */
+ if((a = umbmalloc(addr, size, align)) == 0)
+ return 0;
+ p = (uchar*)a;
+ p[0] = 0xCC;
+ p[size-1] = 0xCC;
+ if(p[0] == 0xCC && p[size-1] == 0xCC)
+ return a;
+ umbfree(a, size);
+
+ return 0;
+}
+
+void
+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
+upaalloc(int size, int align)
+{
+ ulong a;
+
+ a = mapalloc(&rmapupa, 0, size, align);
+ if(a == 0){
+ print("out of physical address space allocating %d\n", size);
+ mapprint(&rmapupa);
+ }
+ return a;
+}
+
+void
+upafree(ulong pa, int 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();
+}
+
diff --git a/sys/src/9/pc/mkfile b/sys/src/9/pc/mkfile
new file mode 100755
index 000000000..955623d35
--- /dev/null
+++ b/sys/src/9/pc/mkfile
@@ -0,0 +1,192 @@
+CONF=pc
+CONFLIST=pc pccpu pcf pcdisk # pccpuf pcauth
+CRAPLIST=pccd pcflop
+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=\
+ alarm.$O\
+ alloc.$O\
+ allocb.$O\
+ auth.$O\
+ cache.$O\
+ chan.$O\
+ dev.$O\
+ edf.$O\
+ fault.$O\
+ latin1.$O\
+ page.$O\
+ parse.$O\
+ pgrp.$O\
+ portclock.$O\
+ print.$O\
+ proc.$O\
+ qio.$O\
+ qlock.$O\
+ rdb.$O\
+ rebootcmd.$O\
+ segment.$O\
+ swap.$O\
+ sysfile.$O\
+ sysproc.$O\
+ taslock.$O\
+ tod.$O\
+ xalloc.$O\
+
+OBJ=\
+ l.$O\
+ plan9l.$O\
+ cga.$O\
+ i8253.$O\
+ i8259.$O\
+ kbd.$O\
+ main.$O\
+ memory.$O\
+ mmu.$O\
+ random.$O\
+ syscallfmt.$O\
+ trap.$O\
+ $CONF.root.$O\
+ $CONF.rootc.$O\
+ $DEVS\
+ $PORT\
+
+LIB=\
+ /$objtype/lib/libmemlayer.a\
+ /$objtype/lib/libmemdraw.a\
+ /$objtype/lib/libdraw.a\
+ /$objtype/lib/libip.a\
+ /$objtype/lib/libc.a\
+ /$objtype/lib/libsec.a\
+ /$objtype/lib/libmp.a\
+
+ETHER=`{echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
+VGA=`{echo devvga.c screen.c vga*.c | sed 's/\.c/.'$O'/g'}
+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 -T$KTZERO -l $OBJ $CONF.$O $LIB
+ size $target
+
+# don't strip the gzipped kernels -- too frustrating when that's all you have!
+$p%.gz:D: $p%
+ gzip -9 <$p$stem >$p$stem.gz
+
+
+# pcflop and pccd need all the space they can get
+9pcflop.gz:D: 9pcflop
+ strip -o /fd/1 9pcflop | gzip -9 >9pcflop.gz
+
+9pccd.gz:D: 9pccd
+ strip -o /fd/1 9pccd | gzip -9 >9pccd.gz
+
+
+install:V: $p$CONF $p$CONF.gz
+ cp $p$CONF $p$CONF.gz /$objtype/
+ for(i in $EXTRACOPIES)
+ import $i / /n/$i && cp $p$CONF $p$CONF.gz /n/$i/$objtype/
+
+<../boot/bootmkfile
+<../port/portmkfile
+<|../port/mkbootrules $CONF
+
+$ETHER: etherif.h ../port/netif.h
+ether8003.$O ether8390.$O: ether8390.h
+$VGA mouse.$O: screen.h /sys/include/memdraw.h
+devfloppy.$O: floppy.h
+archmp.$O mp.$O: apbootstrap.h
+apic.$O archmp.$O mp.$O: mp.h
+$SDEV: ../port/sd.h
+sd53c8xx.$O: sd53c8xx.i
+sdiahci.$O: ahci.h
+devaoe.$O sdaoe.$O: ../port/aoe.h
+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 usbehci.$O: ../port/usb.h
+trap.$O: /sys/include/tos.h
+uartaxp.$O: uartaxp.i
+etherm10g.$O: etherm10g2k.i etherm10g4k.i
+
+init.h:D: ../port/initcode.c init9.c
+ $CC ../port/initcode.c
+ $CC init9.c
+ $LD -l -R1 -s -o init.out init9.$O initcode.$O /386/lib/libc.a
+ {echo 'uchar initcode[]={'
+ xd -1x <init.out |
+ sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+ echo '};'} > init.h
+
+reboot.h:D: rebootcode.s
+ $AS rebootcode.s
+ $LD -l -s -T0x11000 -R4 -o reboot.out rebootcode.$O
+ {echo 'uchar rebootcode[]={'
+ xd -1x reboot.out |
+ sed -e '1,2d' -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+ echo '};'} > reboot.h
+
+apbootstrap.h: apbootstrap.s mem.h
+ $AS $prereq
+ $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
+
+sd53c8xx.i: sd53c8xx.n
+ aux/na $prereq > $target
+
+uartaxp.i: a100p.cp
+ {echo 'static uchar uartaxpcp[] = {'
+ xd -1x $prereq |
+ sed -e 's/^[0-9a-f]+ //' -e '/^$/d' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+ echo '};'
+ } > $target
+
+acid:V:
+ 8c -a -w -I. i8253.c>acid
+
+%.checkether:VQ:
+ for (i in ether*.c){
+ x=`{echo $i | sed 's/\.c//'}
+ if(! ~ $x ether8390 && ! grep -s '^ '^$x^'([ ]|$)' $stem)
+ echo $x not included in $stem
+ }
+ exit 0
+
+%.checkvga:VQ:
+ for (i in vga*.c){
+ x=`{echo $i | sed 's/\.c//'}
+ if(! ~ $x vga vgax vgasavage && ! grep -s '^ '^$x^'([ ]|$)' $stem)
+ echo $x not included in $stem
+ }
+ exit 0
+
+checkdist:VQ:
+ for(i in pcdisk pcflop)
+ for(j in checkvga checkether)
+ mk $i.$j
+
+%.clean:V:
+ 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
diff --git a/sys/src/9/pc/mmu.c b/sys/src/9/pc/mmu.c
new file mode 100755
index 000000000..06b195fca
--- /dev/null
+++ b/sys/src/9/pc/mmu.c
@@ -0,0 +1,1063 @@
+/*
+ * 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"
+#include "dat.h"
+#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 }
+
+Segdesc gdt[NGDT] =
+{
+[NULLSEG] { 0, 0}, /* null descriptor */
+[KDSEG] DATASEGM(0), /* kernel data/stack */
+[KESEG] EXECSEGM(0), /* kernel code */
+[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 int didmmuinit;
+static void taskswitch(ulong, ulong);
+static void memglobal(void);
+
+#define vpt ((ulong*)VPT)
+#define VPTX(va) (((ulong)(va))>>12)
+#define vpd (vpt+VPTX(VPT))
+
+void
+mmuinit0(void)
+{
+ memmove(m->gdt, gdt, sizeof gdt);
+}
+
+void
+mmuinit(void)
+{
+ ulong x, *p;
+ ushort ptr[3];
+
+ didmmuinit = 1;
+
+ if(0) print("vpt=%#.8ux vpd=%#p kmap=%#.8ux\n",
+ VPT, 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;
+
+ /*
+ * We used to keep the GDT in the Mach structure, but it
+ * turns out that that slows down access to the rest of the
+ * page. Since the Mach structure is accessed quite often,
+ * it pays off anywhere from a factor of 1.25 to 2 on real
+ * hardware to separate them (the AMDs are more sensitive
+ * 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);
+ m->gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP;
+
+ ptr[0] = sizeof(gdt)-1;
+ x = (ulong)m->gdt;
+ ptr[1] = x & 0xFFFF;
+ ptr[2] = (x>>16) & 0xFFFF;
+ lgdt(ptr);
+
+ ptr[0] = sizeof(Segdesc)*256-1;
+ x = IDTADDR;
+ ptr[1] = x & 0xFFFF;
+ ptr[2] = (x>>16) & 0xFFFF;
+ lidt(ptr);
+
+ /* make kernel text unwritable */
+ for(x = KTZERO; x < (ulong)etext; x += BY2PG){
+ p = mmuwalk(m->pdb, x, 2, 0);
+ if(p == nil)
+ panic("mmuinit");
+ *p &= ~PTEWRITE;
+ }
+
+ taskswitch(PADDR(m->pdb), (ulong)m + BY2PG);
+ 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)
+{
+ int s;
+
+ s = splhi();
+ up->newtlb = 1;
+ mmuswitch(up);
+ splx(s);
+}
+
+/*
+ * Flush a single page mapping from the tlb.
+ */
+void
+flushpg(ulong va)
+{
+ if(X86FAMILY(m->cpuidax) >= 4)
+ invlpg(va);
+ else
+ putcr3(getcr3());
+}
+
+/*
+ * 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();
+ m->pdballoc++;
+ 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");
+ m->pdbfree++;
+ if(m->pdbcnt >= 10){
+ p->next = proc->mmufree;
+ proc->mmufree = p;
+ }else{
+ p->next = m->pdbpool;
+ m->pdbpool = p;
+ m->pdbcnt++;
+ }
+}
+
+/*
+ * 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 == 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;
+ putcr3(pdb);
+}
+
+void
+mmuswitch(Proc* proc)
+{
+ ulong *pdb;
+
+ if(proc->newtlb){
+ mmuptefree(proc);
+ proc->newtlb = 0;
+ }
+
+ if(proc->mmupdb){
+ pdb = tmpmap(proc->mmupdb);
+ pdb[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)];
+ tmpunmap(pdb);
+ taskswitch(proc->mmupdb->pa, (ulong)(proc->kstack+KSTACK));
+ }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 schedinit() with palloc locked.
+ */
+void
+mmurelease(Proc* proc)
+{
+ Page *page, *next;
+ ulong *pdb;
+
+ if(islo())
+ panic("mmurelease: islo");
+ taskswitch(PADDR(m->pdb), (ulong)m + BY2PG);
+ if(proc->kmaptable){
+ if(proc->mmupdb == nil)
+ panic("mmurelease: no mmupdb");
+ if(--proc->kmaptable->ref)
+ panic("mmurelease: kmap ref %d", proc->kmaptable->ref);
+ if(proc->nkmap)
+ panic("mmurelease: nkmap %d", proc->nkmap);
+ /*
+ * remove kmaptable from pdb before putting pdb up for reuse.
+ */
+ pdb = tmpmap(proc->mmupdb);
+ if(PPN(pdb[PDX(KMAP)]) != proc->kmaptable->pa)
+ panic("mmurelease: bad kmap pde %#.8lux kmap %#.8lux",
+ pdb[PDX(KMAP)], proc->kmaptable->pa);
+ pdb[PDX(KMAP)] = 0;
+ tmpunmap(pdb);
+ /*
+ * move kmaptable to free list.
+ */
+ pagechainhead(proc->kmaptable);
+ proc->kmaptable = 0;
+ }
+ if(proc->mmupdb){
+ mmuptefree(proc);
+ mmupdbfree(proc, proc->mmupdb);
+ proc->mmupdb = 0;
+ }
+ for(page = proc->mmufree; page; page = next){
+ next = page->next;
+ if(--page->ref)
+ panic("mmurelease: page->ref %d", page->ref);
+ pagechainhead(page);
+ }
+ if(proc->mmufree && palloc.r.p)
+ wakeup(&palloc.r);
+ proc->mmufree = 0;
+}
+
+/*
+ * Allocate and install pdb for the current process.
+ */
+static void
+upallocpdb(void)
+{
+ int s;
+ ulong *pdb;
+ Page *page;
+
+ if(up->mmupdb != nil)
+ return;
+ page = mmupdballoc();
+ s = splhi();
+ if(up->mmupdb != nil){
+ /*
+ * Perhaps we got an interrupt while
+ * mmupdballoc was sleeping and that
+ * interrupt allocated an mmupdb?
+ * Seems unlikely.
+ */
+ mmupdbfree(up, page);
+ splx(s);
+ return;
+ }
+ pdb = tmpmap(page);
+ pdb[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)];
+ tmpunmap(pdb);
+ up->mmupdb = page;
+ putcr3(up->mmupdb->pa);
+ splx(s);
+}
+
+/*
+ * Update the mmu in response to a user fault. pa may have PTEWRITE set.
+ */
+void
+putmmu(ulong va, ulong pa, Page*)
+{
+ int old, s;
+ Page *page;
+
+ if(up->mmupdb == nil)
+ upallocpdb();
+
+ /*
+ * We should be able to get through this with interrupts
+ * turned on (if we get interrupted we'll just pick up
+ * where we left off) but we get many faults accessing
+ * vpt[] near the end of this function, and they always happen
+ * after the process has been switched out and then
+ * switched back, usually many times in a row (perhaps
+ * it cannot switch back successfully for some reason).
+ *
+ * In any event, I'm tired of searching for this bug.
+ * Turn off interrupts during putmmu even though
+ * we shouldn't need to. - rsc
+ */
+
+ s = splhi();
+ if(!(vpd[PDX(va)]&PTEVALID)){
+ if(up->mmufree == 0){
+ spllo();
+ page = newpage(0, 0, 0);
+ splhi();
+ }
+ else{
+ page = up->mmufree;
+ up->mmufree = page->next;
+ }
+ 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);
+ if(getcr3() != up->mmupdb->pa)
+ print("bad cr3 %#.8lux %#.8lux\n", getcr3(), 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=%#08lux pa=%#08lux pte=%#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 *table;
+ void *map;
+
+ table = &pdb[PDX(va)];
+ if(!(*table & PTEVALID) && create == 0)
+ return 0;
+
+ switch(level){
+
+ default:
+ return 0;
+
+ case 1:
+ return table;
+
+ case 2:
+ if(*table & PTESIZE)
+ panic("mmuwalk2: va %luX entry %luX", va, *table);
+ if(!(*table & 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)];
+ }
+}
+
+/*
+ * 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.
+ */
+
+static Lock vmaplock;
+
+static int findhole(ulong *a, int n, int count);
+static ulong vmapalloc(ulong size);
+static void pdbunmap(ulong*, ulong, int);
+
+/*
+ * 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=%#p\n", getcallerpc(&pa));
+ return nil;
+ }
+ ilock(&vmaplock);
+ if((va = vmapalloc(size)) == 0
+ || pdbmap(MACHP(0)->pdb, pa|PTEUNCACHED|PTEWRITE, va, size) < 0){
+ iunlock(&vmaplock);
+ return 0;
+ }
+ 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);
+}
+
+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;
+}
+
+/*
+ * 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 0;
+ }
+ 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;
+}
+
+/*
+ * 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",
+ va, size, getcallerpc(&v));
+
+ 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.
+ * It is possible for vunmap to be called with up == nil,
+ * e.g. from the reset/init driver routines during system
+ * boot. In that case it suffices to flush the MACH(0) TLB
+ * and return.
+ */
+ if(!active.thunderbirdsarego){
+ putcr3(PADDR(MACHP(0)->pdb));
+ return;
+ }
+ 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)
+ ;
+ }
+}
+
+/*
+ * Add kernel mappings for pa -> va for a section of size bytes.
+ */
+int
+pdbmap(ulong *pdb, ulong pa, ulong va, int size)
+{
+ int pse;
+ ulong pgsz, *pte, *table;
+ ulong flag, off;
+
+ flag = pa&0xFFF;
+ pa &= ~0xFFF;
+
+ if((MACHP(0)->cpuiddx & 0x08) && (getcr4() & 0x10))
+ pse = 1;
+ else
+ pse = 0;
+
+ for(off=0; off<size; off+=pgsz){
+ table = &pdb[PDX(va+off)];
+ if((*table&PTEVALID) && (*table&PTESIZE))
+ panic("vmap: va=%#.8lux pa=%#.8lux pde=%#.8lux",
+ va+off, pa+off, *table);
+
+ /*
+ * Check if it can be mapped using a 4MB page:
+ * va, pa aligned and size >= 4MB and processor can do it.
+ */
+ if(pse && (pa+off)%(4*MB) == 0 && (va+off)%(4*MB) == 0 && (size-off) >= 4*MB){
+ *table = (pa+off)|flag|PTESIZE|PTEVALID;
+ pgsz = 4*MB;
+ }else{
+ pte = mmuwalk(pdb, va+off, 2, 1);
+ if(*pte&PTEVALID)
+ panic("vmap: va=%#.8lux pa=%#.8lux pte=%#.8lux",
+ va+off, pa+off, *pte);
+ *pte = (pa+off)|flag|PTEVALID;
+ pgsz = BY2PG;
+ }
+ }
+ 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;
+
+ if(up == nil)
+ panic("kmap: up=0 pc=%#.8lux", getcallerpc(&page));
+ if(up->mmupdb == nil)
+ upallocpdb();
+ if(up->nkmap < 0)
+ panic("kmap %lud %s: nkmap=%d", up->pid, up->text, up->nkmap);
+
+ /*
+ * Splhi shouldn't be necessary here, but paranoia reigns.
+ * See comment in putmmu above.
+ */
+ s = splhi();
+ up->nkmap++;
+ if(!(vpd[PDX(KMAP)]&PTEVALID)){
+ /* allocate page directory */
+ if(KMAPSIZE > BY2XPG)
+ panic("bad kmapsize");
+ if(up->kmaptable != nil)
+ panic("kmaptable");
+ spllo();
+ up->kmaptable = newpage(0, 0, 0);
+ splhi();
+ vpd[PDX(KMAP)] = up->kmaptable->pa|PTEWRITE|PTEVALID;
+ flushpg((ulong)kpt);
+ memset(kpt, 0, BY2PG);
+ kpt[0] = page->pa|PTEWRITE|PTEVALID;
+ up->lastkmap = 0;
+ splx(s);
+ return (KMap*)KMAP;
+ }
+ if(up->kmaptable == nil)
+ panic("no kmaptable");
+ 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;
+ splx(s);
+ 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=%#p", va, getcallerpc(&k));
+ if(!(vpt[VPTX(va)]&PTEVALID))
+ panic("kunmap: not mapped %#.8lux pc=%#p", va, getcallerpc(&k));
+ up->nkmap--;
+ if(up->nkmap < 0)
+ panic("kunmap %lud %s: nkmap=%d", up->pid, up->text, up->nkmap);
+ 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);
+
+ /*
+ * PDX(TMPADDR) == PDX(MACHADDR), so this
+ * entry is private to the processor and shared
+ * between up->mmupdb (if any) and m->pdb.
+ */
+ entry = &vpt[VPTX(TMPADDR)];
+ if(!(*entry&PTEVALID)){
+ for(i=KZERO; i<=CPU0MACH; i+=BY2PG)
+ print("%#p: *%#p=%#p (vpt=%#p index=%#p)\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;
+}
+
+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 pc=%#p", va, getcallerpc(&v));
+ return va-KZERO;
+}
+
+/*
+ * More debugging.
+ */
+void
+countpagerefs(ulong *ref, int print)
+{
+ int i, n;
+ Mach *mm;
+ Page *pg;
+ Proc *p;
+
+ n = 0;
+ for(i=0; i<conf.nproc; i++){
+ p = proctab(i);
+ if(p->mmupdb){
+ if(print){
+ if(ref[pagenumber(p->mmupdb)])
+ iprint("page %#.8lux is proc %d (pid %lud) pdb\n",
+ p->mmupdb->pa, i, p->pid);
+ continue;
+ }
+ if(ref[pagenumber(p->mmupdb)]++ == 0)
+ n++;
+ else
+ iprint("page %#.8lux is proc %d (pid %lud) pdb but has other refs!\n",
+ p->mmupdb->pa, i, p->pid);
+ }
+ if(p->kmaptable){
+ if(print){
+ if(ref[pagenumber(p->kmaptable)])
+ iprint("page %#.8lux is proc %d (pid %lud) kmaptable\n",
+ p->kmaptable->pa, i, p->pid);
+ continue;
+ }
+ if(ref[pagenumber(p->kmaptable)]++ == 0)
+ n++;
+ else
+ iprint("page %#.8lux is proc %d (pid %lud) kmaptable but has other refs!\n",
+ p->kmaptable->pa, i, p->pid);
+ }
+ for(pg=p->mmuused; pg; pg=pg->next){
+ if(print){
+ if(ref[pagenumber(pg)])
+ iprint("page %#.8lux is on proc %d (pid %lud) mmuused\n",
+ pg->pa, i, p->pid);
+ continue;
+ }
+ if(ref[pagenumber(pg)]++ == 0)
+ n++;
+ else
+ iprint("page %#.8lux is on proc %d (pid %lud) mmuused but has other refs!\n",
+ pg->pa, i, p->pid);
+ }
+ for(pg=p->mmufree; pg; pg=pg->next){
+ if(print){
+ if(ref[pagenumber(pg)])
+ iprint("page %#.8lux is on proc %d (pid %lud) mmufree\n",
+ pg->pa, i, p->pid);
+ continue;
+ }
+ if(ref[pagenumber(pg)]++ == 0)
+ n++;
+ else
+ iprint("page %#.8lux is on proc %d (pid %lud) mmufree but has other refs!\n",
+ pg->pa, i, p->pid);
+ }
+ }
+ if(!print)
+ iprint("%d pages in proc mmu\n", n);
+ n = 0;
+ for(i=0; i<conf.nmach; i++){
+ mm = MACHP(i);
+ for(pg=mm->pdbpool; pg; pg=pg->next){
+ if(print){
+ if(ref[pagenumber(pg)])
+ iprint("page %#.8lux is in cpu%d pdbpool\n",
+ pg->pa, i);
+ continue;
+ }
+ if(ref[pagenumber(pg)]++ == 0)
+ n++;
+ else
+ iprint("page %#.8lux is in cpu%d pdbpool but has other refs!\n",
+ pg->pa, i);
+ }
+ }
+ if(!print){
+ iprint("%d pages in mach pdbpools\n", n);
+ for(i=0; i<conf.nmach; i++)
+ iprint("cpu%d: %d pdballoc, %d pdbfree\n",
+ i, MACHP(i)->pdballoc, MACHP(i)->pdbfree);
+ }
+}
+
+void
+checkfault(ulong, ulong)
+{
+}
+
+/*
+ * Return the number of bytes that can be accessed via KADDR(pa).
+ * If pa is not a valid argument to KADDR, return 0.
+ */
+ulong
+cankaddr(ulong pa)
+{
+ if(pa >= -KZERO)
+ return 0;
+ return -KZERO - pa;
+}
+
diff --git a/sys/src/9/pc/mouse.c b/sys/src/9/pc/mouse.c
new file mode 100755
index 000000000..282e3595f
--- /dev/null
+++ b/sys/src/9/pc/mouse.c
@@ -0,0 +1,343 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+/*
+ * mouse types
+ */
+enum
+{
+ Mouseother= 0,
+ Mouseserial= 1,
+ MousePS2= 2,
+};
+
+extern int mouseshifted;
+
+static QLock mousectlqlock;
+static int mousetype;
+static int intellimouse;
+static int packetsize;
+static int resolution;
+static int accelerated;
+static int mousehwaccel;
+static char mouseport[5];
+
+enum
+{
+ CMaccelerated,
+ CMhwaccel,
+ CMintellimouse,
+ CMlinear,
+ CMps2,
+ CMps2intellimouse,
+ CMres,
+ CMreset,
+ CMserial,
+};
+
+static Cmdtab mousectlmsg[] =
+{
+ CMaccelerated, "accelerated", 0,
+ CMhwaccel, "hwaccel", 2,
+ CMintellimouse, "intellimouse", 1,
+ CMlinear, "linear", 1,
+ CMps2, "ps2", 1,
+ CMps2intellimouse, "ps2intellimouse", 1,
+ CMres, "res", 0,
+ CMreset, "reset", 1,
+ CMserial, "serial", 0,
+};
+
+/*
+ * ps/2 mouse message is three bytes
+ *
+ * byte 0 - 0 0 SDY SDX 1 M R L
+ * byte 1 - DX
+ * byte 2 - DY
+ *
+ * shift & right button is the same as middle button
+ *
+ * Intellimouse and AccuPoint with extra buttons deliver
+ * byte 3 - 00 or 01 or FF according to extra button state.
+ * extra buttons are mapped in this code to buttons 4 and 5.
+ * AccuPoint generates repeated events for these buttons;
+* it and Intellimouse generate 'down' events only, so
+ * user-level code is required to generate button 'up' events
+ * if they are needed by the application.
+ * Also on laptops with AccuPoint AND external mouse, the
+ * controller may deliver 3 or 4 bytes according to the type
+ * of the external mouse; code must adapt.
+ *
+ * On the NEC Versa series (and perhaps others?) we seem to
+ * lose a byte from the packet every once in a while, which
+ * means we lose where we are in the instruction stream.
+ * To resynchronize, if we get a byte more than two seconds
+ * after the previous byte, we assume it's the first in a packet.
+ */
+static void
+ps2mouseputc(int c, int shift)
+{
+ static short msg[4];
+ static int nb;
+ static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 3, 2, 3, 6, 7 };
+ static ulong lasttick;
+ ulong m;
+ int buttons, dx, dy;
+
+ /*
+ * non-ps2 keyboards might not set shift
+ * but still set mouseshifted.
+ */
+ shift |= mouseshifted;
+ /*
+ * Resynchronize in stream with timing; see comment above.
+ */
+ m = MACHP(0)->ticks;
+ if(TK2SEC(m - lasttick) > 2)
+ nb = 0;
+ lasttick = m;
+
+ /*
+ * check byte 0 for consistency
+ */
+ if(nb==0 && (c&0xc8)!=0x08)
+ if(intellimouse && (c==0x00 || c==0x01 || c==0xFF)){
+ /* last byte of 4-byte packet */
+ packetsize = 4;
+ return;
+ }
+
+ msg[nb] = c;
+ if(++nb == packetsize){
+ nb = 0;
+ if(msg[0] & 0x10)
+ msg[1] |= 0xFF00;
+ if(msg[0] & 0x20)
+ msg[2] |= 0xFF00;
+
+ buttons = b[(msg[0]&7) | (shift ? 8 : 0)];
+ if(intellimouse && packetsize==4){
+ if((msg[3]&0xc8) == 0x08){
+ /* first byte of 3-byte packet */
+ packetsize = 3;
+ msg[0] = msg[3];
+ nb = 1;
+ /* fall through to emit previous packet */
+ }else{
+ /* The AccuPoint on the Toshiba 34[48]0CT
+ * encodes extra buttons as 4 and 5. They repeat
+ * and don't release, however, so user-level
+ * timing code is required. Furthermore,
+ * intellimice with 3buttons + scroll give a
+ * two's complement number in the lower 4 bits
+ * (bit 4 is sign extension) that describes
+ * the amount the scroll wheel has moved during
+ * the last sample. Here we use only the sign to
+ * decide whether the wheel is moving up or down
+ * and generate a single button 4 or 5 click
+ * accordingly.
+ */
+ if((msg[3] >> 3) & 1)
+ buttons |= 1<<3;
+ else if(msg[3] & 0x7)
+ buttons |= 1<<4;
+ }
+ }
+ dx = msg[1];
+ dy = -msg[2];
+ mousetrack(dx, dy, buttons, TK2MS(MACHP(0)->ticks));
+ }
+ return;
+}
+
+/*
+ * set up a ps2 mouse
+ */
+static void
+ps2mouse(void)
+{
+ if(mousetype == MousePS2)
+ return;
+
+ i8042auxenable(ps2mouseputc);
+ /* make mouse streaming, enabled */
+ i8042auxcmd(0xEA);
+ i8042auxcmd(0xF4);
+
+ mousetype = MousePS2;
+ packetsize = 3;
+ mousehwaccel = 1;
+}
+
+/*
+ * The PS/2 Trackpoint multiplexor on the IBM Thinkpad T23 ignores
+ * acceleration commands. It is supposed to pass them on
+ * to the attached device, but my Logitech mouse is simply
+ * not behaving any differently. For such devices, we allow
+ * the user to use "hwaccel off" to tell us to back off to
+ * software acceleration even if we're using the PS/2 port.
+ * (Serial mice are always software accelerated.)
+ * For more information on the Thinkpad multiplexor, see
+ * http://wwwcssrv.almaden.ibm.com/trackpoint/
+ */
+static void
+setaccelerated(int x)
+{
+ accelerated = x;
+ if(mousehwaccel){
+ switch(mousetype){
+ case MousePS2:
+ i8042auxcmd(0xE7);
+ return;
+ }
+ }
+ mouseaccelerate(x);
+}
+
+static void
+setlinear(void)
+{
+ accelerated = 0;
+ if(mousehwaccel){
+ switch(mousetype){
+ case MousePS2:
+ i8042auxcmd(0xE6);
+ return;
+ }
+ }
+ mouseaccelerate(0);
+}
+
+static void
+setres(int n)
+{
+ resolution = n;
+ switch(mousetype){
+ case MousePS2:
+ i8042auxcmd(0xE8);
+ i8042auxcmd(n);
+ break;
+ }
+}
+
+static void
+setintellimouse(void)
+{
+ intellimouse = 1;
+ packetsize = 4;
+ switch(mousetype){
+ case MousePS2:
+ i8042auxcmd(0xF3); /* set sample */
+ i8042auxcmd(0xC8);
+ i8042auxcmd(0xF3); /* set sample */
+ i8042auxcmd(0x64);
+ i8042auxcmd(0xF3); /* set sample */
+ i8042auxcmd(0x50);
+ break;
+ case Mouseserial:
+ i8250setmouseputc(mouseport, m5mouseputc);
+ break;
+ }
+}
+
+static void
+resetmouse(void)
+{
+ packetsize = 3;
+ switch(mousetype){
+ case MousePS2:
+ i8042auxcmd(0xF6);
+ i8042auxcmd(0xEA); /* streaming */
+ i8042auxcmd(0xE8); /* set resolution */
+ i8042auxcmd(3);
+ i8042auxcmd(0xF4); /* enabled */
+ break;
+ }
+}
+
+void
+mousectl(Cmdbuf *cb)
+{
+ Cmdtab *ct;
+
+ qlock(&mousectlqlock);
+ if(waserror()){
+ qunlock(&mousectlqlock);
+ nexterror();
+ }
+
+ ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg));
+ switch(ct->index){
+ case CMaccelerated:
+ setaccelerated(cb->nf == 1 ? 1 : atoi(cb->f[1]));
+ break;
+ case CMintellimouse:
+ setintellimouse();
+ break;
+ case CMlinear:
+ setlinear();
+ break;
+ case CMps2:
+ intellimouse = 0;
+ ps2mouse();
+ break;
+ case CMps2intellimouse:
+ ps2mouse();
+ setintellimouse();
+ break;
+ case CMres:
+ if(cb->nf >= 2)
+ setres(atoi(cb->f[1]));
+ else
+ setres(1);
+ break;
+ case CMreset:
+ resetmouse();
+ if(accelerated)
+ setaccelerated(accelerated);
+ if(resolution)
+ setres(resolution);
+ if(intellimouse)
+ setintellimouse();
+ break;
+ case CMserial:
+ if(mousetype == Mouseserial)
+ error(Emouseset);
+
+ if(cb->nf > 2){
+ if(strcmp(cb->f[2], "M") == 0)
+ i8250mouse(cb->f[1], m3mouseputc, 0);
+ else if(strcmp(cb->f[2], "MI") == 0)
+ i8250mouse(cb->f[1], m5mouseputc, 0);
+ else
+ i8250mouse(cb->f[1], mouseputc, cb->nf == 1);
+ } else
+ i8250mouse(cb->f[1], mouseputc, cb->nf == 1);
+
+ mousetype = Mouseserial;
+ strncpy(mouseport, cb->f[1], sizeof(mouseport)-1);
+ packetsize = 3;
+ break;
+ case CMhwaccel:
+ if(strcmp(cb->f[1], "on")==0)
+ mousehwaccel = 1;
+ else if(strcmp(cb->f[1], "off")==0)
+ mousehwaccel = 0;
+ else
+ cmderror(cb, "bad mouse control message");
+ }
+
+ qunlock(&mousectlqlock);
+ poperror();
+}
diff --git a/sys/src/9/pc/mp.c b/sys/src/9/pc/mp.c
new file mode 100755
index 000000000..0fb65b2db
--- /dev/null
+++ b/sys/src/9/pc/mp.c
@@ -0,0 +1,898 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+#include "mp.h"
+#include "apbootstrap.h"
+
+static PCMP* mppcmp;
+static Bus* mpbus;
+static Bus* mpbuslast;
+static int mpisabus = -1;
+static int mpeisabus = -1;
+extern int i8259elcr; /* mask of level-triggered interrupts */
+static Apic mpapic[MaxAPICNO+1];
+static int machno2apicno[MaxAPICNO+1]; /* inverse map: machno -> APIC ID */
+static Ref mpvnoref; /* unique vector assignment */
+static int mpmachno = 1;
+static Lock mpphysidlock;
+static int mpphysid;
+
+static char* buses[] = {
+ "CBUSI ",
+ "CBUSII",
+ "EISA ",
+ "FUTURE",
+ "INTERN",
+ "ISA ",
+ "MBI ",
+ "MBII ",
+ "MCA ",
+ "MPI ",
+ "MPSA ",
+ "NUBUS ",
+ "PCI ",
+ "PCMCIA",
+ "TC ",
+ "VL ",
+ "VME ",
+ "XPRESS",
+ 0,
+};
+
+static Apic*
+mkprocessor(PCMPprocessor* p)
+{
+ int apicno;
+ Apic *apic;
+
+ apicno = p->apicno;
+ if(!(p->flags & PcmpEN) || apicno > MaxAPICNO)
+ return 0;
+
+ apic = &mpapic[apicno];
+ apic->type = PcmpPROCESSOR;
+ apic->apicno = apicno;
+ apic->flags = p->flags;
+ apic->lintr[0] = ApicIMASK;
+ apic->lintr[1] = ApicIMASK;
+
+ if(p->flags & PcmpBP){
+ machno2apicno[0] = apicno;
+ apic->machno = 0;
+ }
+ else{
+ machno2apicno[mpmachno] = apicno;
+ apic->machno = mpmachno;
+ mpmachno++;
+ }
+
+ return apic;
+}
+
+static Bus*
+mkbus(PCMPbus* p)
+{
+ Bus *bus;
+ int i;
+
+ for(i = 0; buses[i]; i++){
+ if(strncmp(buses[i], p->string, sizeof(p->string)) == 0)
+ break;
+ }
+ if(buses[i] == 0)
+ return 0;
+
+ bus = xalloc(sizeof(Bus));
+ if(mpbus)
+ mpbuslast->next = bus;
+ else
+ mpbus = bus;
+ mpbuslast = bus;
+
+ bus->type = i;
+ bus->busno = p->busno;
+ if(bus->type == BusEISA){
+ bus->po = PcmpLOW;
+ bus->el = PcmpLEVEL;
+ if(mpeisabus != -1)
+ print("mkbus: more than one EISA bus\n");
+ mpeisabus = bus->busno;
+ }
+ else if(bus->type == BusPCI){
+ bus->po = PcmpLOW;
+ bus->el = PcmpLEVEL;
+ }
+ else if(bus->type == BusISA){
+ bus->po = PcmpHIGH;
+ bus->el = PcmpEDGE;
+ if(mpisabus != -1)
+ print("mkbus: more than one ISA bus\n");
+ mpisabus = bus->busno;
+ }
+ else{
+ bus->po = PcmpHIGH;
+ bus->el = PcmpEDGE;
+ }
+
+ return bus;
+}
+
+static Bus*
+mpgetbus(int busno)
+{
+ Bus *bus;
+
+ for(bus = mpbus; bus; bus = bus->next){
+ if(bus->busno == busno)
+ return bus;
+ }
+ print("mpgetbus: can't find bus %d\n", busno);
+
+ return 0;
+}
+
+static Apic*
+mkioapic(PCMPioapic* p)
+{
+ void *va;
+ int apicno;
+ Apic *apic;
+
+ apicno = p->apicno;
+ if(!(p->flags & PcmpEN) || apicno > MaxAPICNO)
+ return 0;
+
+ /*
+ * Map the I/O APIC.
+ */
+ if((va = vmap(p->addr, 1024)) == nil)
+ return 0;
+
+ apic = &mpapic[apicno];
+ apic->type = PcmpIOAPIC;
+ apic->apicno = apicno;
+ apic->addr = va;
+ apic->paddr = p->addr;
+ apic->flags = p->flags;
+
+ return apic;
+}
+
+static Aintr*
+mkiointr(PCMPintr* p)
+{
+ Bus *bus;
+ Aintr *aintr;
+ PCMPintr* pcmpintr;
+
+ /*
+ * According to the MultiProcessor Specification, a destination
+ * I/O APIC of 0xFF means the signal is routed to all I/O APICs.
+ * It's unclear how that can possibly be correct so treat it as
+ * an error for now.
+ */
+ if(p->apicno == 0xFF)
+ return 0;
+ if((bus = mpgetbus(p->busno)) == 0)
+ return 0;
+
+ aintr = xalloc(sizeof(Aintr));
+ aintr->intr = p;
+
+ if(0)
+ print("iointr: type %d intr type %d flags %#o "
+ "bus %d irq %d apicno %d intin %d\n",
+ p->type, p->intr, p->flags,
+ p->busno, p->irq, p->apicno, p->intin);
+ /*
+ * Hack for Intel SR1520ML motherboard, which BIOS describes
+ * the i82575 dual ethernet controllers incorrectly.
+ */
+ if(memcmp(mppcmp->product, "INTEL X38MLST ", 20) == 0){
+ if(p->busno == 1 && p->intin == 16 && p->irq == 1){
+ pcmpintr = malloc(sizeof(PCMPintr));
+ memmove(pcmpintr, p, sizeof(PCMPintr));
+ print("mkiointr: %20.20s bus %d intin %d irq %d\n",
+ (char*)mppcmp->product,
+ pcmpintr->busno, pcmpintr->intin,
+ pcmpintr->irq);
+ pcmpintr->intin = 17;
+ aintr->intr = pcmpintr;
+ }
+ }
+ aintr->apic = &mpapic[p->apicno];
+ aintr->next = bus->aintr;
+ bus->aintr = aintr;
+
+ return aintr;
+}
+
+static int
+mpintrinit(Bus* bus, PCMPintr* intr, int vno, int /*irq*/)
+{
+ int el, po, v;
+
+ /*
+ * Parse an I/O or Local APIC interrupt table entry and
+ * return the encoded vector.
+ */
+ v = vno;
+
+ po = intr->flags & PcmpPOMASK;
+ el = intr->flags & PcmpELMASK;
+
+ switch(intr->intr){
+
+ default: /* PcmpINT */
+ v |= ApicFIXED; /* no-op */
+ break;
+
+ case PcmpNMI:
+ v |= ApicNMI;
+ po = PcmpHIGH;
+ el = PcmpEDGE;
+ break;
+
+ case PcmpSMI:
+ v |= ApicSMI;
+ break;
+
+ case PcmpExtINT:
+ v |= ApicExtINT;
+ /*
+ * The AMI Goliath doesn't boot successfully with it's LINTR0
+ * entry which decodes to low+level. The PPro manual says ExtINT
+ * should be level, whereas the Pentium is edge. Setting the
+ * Goliath to edge+high seems to cure the problem. Other PPro
+ * MP tables (e.g. ASUS P/I-P65UP5 have a entry which decodes
+ * to edge+high, so who knows.
+ * Perhaps it would be best just to not set an ExtINT entry at
+ * all, it shouldn't be needed for SMP mode.
+ */
+ po = PcmpHIGH;
+ el = PcmpEDGE;
+ break;
+ }
+
+ /*
+ */
+ if(bus->type == BusEISA && !po && !el /*&& !(i8259elcr & (1<<irq))*/){
+ po = PcmpHIGH;
+ el = PcmpEDGE;
+ }
+ if(!po)
+ po = bus->po;
+ if(po == PcmpLOW)
+ v |= ApicLOW;
+ else if(po != PcmpHIGH){
+ print("mpintrinit: bad polarity 0x%uX\n", po);
+ return ApicIMASK;
+ }
+
+ if(!el)
+ el = bus->el;
+ if(el == PcmpLEVEL)
+ v |= ApicLEVEL;
+ else if(el != PcmpEDGE){
+ print("mpintrinit: bad trigger 0x%uX\n", el);
+ return ApicIMASK;
+ }
+
+ return v;
+}
+
+static int
+mklintr(PCMPintr* p)
+{
+ Apic *apic;
+ Bus *bus;
+ int intin, v;
+
+ /*
+ * The offsets of vectors for LINT[01] are known to be
+ * 0 and 1 from the local APIC vector space at VectorLAPIC.
+ */
+ if((bus = mpgetbus(p->busno)) == 0)
+ return 0;
+ intin = p->intin;
+
+ /*
+ * Pentium Pros have problems if LINT[01] are set to ExtINT
+ * so just bag it, SMP mode shouldn't need ExtINT anyway.
+ */
+ if(p->intr == PcmpExtINT || p->intr == PcmpNMI)
+ v = ApicIMASK;
+ else
+ v = mpintrinit(bus, p, VectorLAPIC+intin, p->irq);
+
+ if(p->apicno == 0xFF){
+ for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){
+ if((apic->flags & PcmpEN)
+ && apic->type == PcmpPROCESSOR)
+ apic->lintr[intin] = v;
+ }
+ }
+ else{
+ apic = &mpapic[p->apicno];
+ if((apic->flags & PcmpEN) && apic->type == PcmpPROCESSOR)
+ apic->lintr[intin] = v;
+ }
+
+ return v;
+}
+
+static void
+checkmtrr(void)
+{
+ int i, vcnt;
+ Mach *mach0;
+
+ /*
+ * If there are MTRR registers, snarf them for validation.
+ */
+ if(!(m->cpuiddx & 0x1000))
+ return;
+
+ rdmsr(0x0FE, &m->mtrrcap);
+ rdmsr(0x2FF, &m->mtrrdef);
+ if(m->mtrrcap & 0x0100){
+ rdmsr(0x250, &m->mtrrfix[0]);
+ rdmsr(0x258, &m->mtrrfix[1]);
+ rdmsr(0x259, &m->mtrrfix[2]);
+ for(i = 0; i < 8; i++)
+ rdmsr(0x268+i, &m->mtrrfix[(i+3)]);
+ }
+ vcnt = m->mtrrcap & 0x00FF;
+ if(vcnt > nelem(m->mtrrvar))
+ vcnt = nelem(m->mtrrvar);
+ for(i = 0; i < vcnt; i++)
+ rdmsr(0x200+i, &m->mtrrvar[i]);
+
+ /*
+ * If not the bootstrap processor, compare.
+ */
+ if(m->machno == 0)
+ return;
+
+ mach0 = MACHP(0);
+ if(mach0->mtrrcap != m->mtrrcap)
+ print("mtrrcap%d: %lluX %lluX\n",
+ m->machno, mach0->mtrrcap, m->mtrrcap);
+ if(mach0->mtrrdef != m->mtrrdef)
+ print("mtrrdef%d: %lluX %lluX\n",
+ m->machno, mach0->mtrrdef, m->mtrrdef);
+ for(i = 0; i < 11; i++){
+ if(mach0->mtrrfix[i] != m->mtrrfix[i])
+ print("mtrrfix%d: i%d: %lluX %lluX\n",
+ m->machno, i, mach0->mtrrfix[i], m->mtrrfix[i]);
+ }
+ for(i = 0; i < vcnt; i++){
+ if(mach0->mtrrvar[i] != m->mtrrvar[i])
+ print("mtrrvar%d: i%d: %lluX %lluX\n",
+ m->machno, i, mach0->mtrrvar[i], m->mtrrvar[i]);
+ }
+}
+
+static void
+squidboy(Apic* apic)
+{
+// iprint("Hello Squidboy\n");
+
+ machinit();
+ mmuinit();
+
+ cpuidentify();
+ cpuidprint();
+ checkmtrr();
+
+ apic->online = 1;
+
+ lapicinit(apic);
+ lapiconline();
+ syncclock();
+ timersinit();
+
+ fpoff();
+
+ lock(&active);
+ active.machs |= 1<<m->machno;
+ unlock(&active);
+
+ while(!active.thunderbirdsarego)
+ microdelay(100);
+
+ schedinit();
+}
+
+static void
+mpstartap(Apic* apic)
+{
+ ulong *apbootp, *pdb, *pte;
+ Mach *mach, *mach0;
+ int i, machno;
+ uchar *p;
+
+ mach0 = MACHP(0);
+
+ /*
+ * Initialise the AP page-tables and Mach structure. The page-tables
+ * are the same as for the bootstrap processor with the exception of
+ * the PTE for the Mach structure.
+ * Xspanalloc will panic if an allocation can't be made.
+ */
+ p = xspanalloc(4*BY2PG, BY2PG, 0);
+ pdb = (ulong*)p;
+ memmove(pdb, mach0->pdb, BY2PG);
+ p += BY2PG;
+
+ if((pte = mmuwalk(pdb, MACHADDR, 1, 0)) == nil)
+ return;
+ memmove(p, KADDR(PPN(*pte)), BY2PG);
+ *pte = PADDR(p)|PTEWRITE|PTEVALID;
+ if(mach0->havepge)
+ *pte |= PTEGLOBAL;
+ p += BY2PG;
+
+ mach = (Mach*)p;
+ if((pte = mmuwalk(pdb, MACHADDR, 2, 0)) == nil)
+ return;
+ *pte = PADDR(mach)|PTEWRITE|PTEVALID;
+ if(mach0->havepge)
+ *pte |= PTEGLOBAL;
+ p += BY2PG;
+
+ machno = apic->machno;
+ MACHP(machno) = mach;
+ mach->machno = machno;
+ mach->pdb = pdb;
+ mach->gdt = (Segdesc*)p; /* filled by mmuinit */
+
+ /*
+ * Tell the AP where its kernel vector and pdb are.
+ * The offsets are known in the AP bootstrap code.
+ */
+ apbootp = (ulong*)(APBOOTSTRAP+0x08);
+ *apbootp++ = (ulong)squidboy;
+ *apbootp++ = PADDR(pdb);
+ *apbootp = (ulong)apic;
+
+ /*
+ * Universal Startup Algorithm.
+ */
+ p = KADDR(0x467);
+ *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;
+
+ nvramwrite(0x0F, 0x0A);
+ lapicstartap(apic, PADDR(APBOOTSTRAP));
+ for(i = 0; i < 1000; i++){
+ if(apic->online)
+ break;
+ delay(10);
+ }
+ nvramwrite(0x0F, 0x00);
+}
+
+void
+mpinit(void)
+{
+ int ncpu;
+ char *cp;
+ PCMP *pcmp;
+ uchar *e, *p;
+ Apic *apic, *bpapic;
+ void *va;
+
+ i8259init();
+ syncclock();
+
+ if(_mp_ == 0)
+ return;
+ pcmp = KADDR(_mp_->physaddr);
+
+ /*
+ * Map the local APIC.
+ */
+ if((va = vmap(pcmp->lapicbase, 1024)) == nil)
+ return;
+ mppcmp = pcmp;
+ print("LAPIC: %.8lux %.8lux\n", pcmp->lapicbase, (ulong)va);
+
+ bpapic = nil;
+
+ /*
+ * Run through the table saving information needed for starting
+ * application processors and initialising any I/O APICs. The table
+ * is guaranteed to be in order such that only one pass is necessary.
+ */
+ p = ((uchar*)pcmp)+sizeof(PCMP);
+ e = ((uchar*)pcmp)+pcmp->length;
+ while(p < e) switch(*p){
+
+ default:
+ print("mpinit: unknown PCMP type 0x%uX (e-p 0x%luX)\n",
+ *p, e-p);
+ while(p < e){
+ print("%uX ", *p);
+ p++;
+ }
+ break;
+
+ case PcmpPROCESSOR:
+ if(apic = mkprocessor((PCMPprocessor*)p)){
+ /*
+ * Must take a note of bootstrap processor APIC
+ * now as it will be needed in order to start the
+ * application processors later and there's no
+ * guarantee that the bootstrap processor appears
+ * first in the table before the others.
+ */
+ apic->addr = va;
+ apic->paddr = pcmp->lapicbase;
+ if(apic->flags & PcmpBP)
+ bpapic = apic;
+ }
+ p += sizeof(PCMPprocessor);
+ continue;
+
+ case PcmpBUS:
+ mkbus((PCMPbus*)p);
+ p += sizeof(PCMPbus);
+ continue;
+
+ case PcmpIOAPIC:
+ if(apic = mkioapic((PCMPioapic*)p))
+ ioapicinit(apic, ((PCMPioapic*)p)->apicno);
+ p += sizeof(PCMPioapic);
+ continue;
+
+ case PcmpIOINTR:
+ mkiointr((PCMPintr*)p);
+ p += sizeof(PCMPintr);
+ continue;
+
+ case PcmpLINTR:
+ mklintr((PCMPintr*)p);
+ p += sizeof(PCMPintr);
+ continue;
+ }
+
+ /*
+ * No bootstrap processor, no need to go further.
+ */
+ if(bpapic == 0)
+ return;
+ bpapic->online = 1;
+
+ lapicinit(bpapic);
+
+ /*
+ * These interrupts are local to the processor
+ * and do not appear in the I/O APIC so it is OK
+ * to set them now.
+ */
+ intrenable(IrqTIMER, lapicclock, 0, BUSUNKNOWN, "clock");
+ intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN, "lapicerror");
+ intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN, "lapicspurious");
+ lapiconline();
+
+ checkmtrr();
+
+ /*
+ * Initialise the application processors.
+ */
+ if(cp = getconf("*ncpu")){
+ ncpu = strtol(cp, 0, 0);
+ if(ncpu < 1)
+ ncpu = 1;
+ else if(ncpu > MAXMACH)
+ ncpu = MAXMACH;
+ }
+ else
+ ncpu = MAXMACH;
+ memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap));
+ for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){
+ if(ncpu <= 1)
+ break;
+ if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN
+ && apic->type == PcmpPROCESSOR){
+ mpstartap(apic);
+ conf.nmach++;
+ ncpu--;
+ }
+ }
+
+ /*
+ * we don't really know the number of processors till
+ * here.
+ *
+ * set conf.copymode here if nmach > 1.
+ * Should look for an ExtINT line and enable it.
+ */
+ if(X86FAMILY(m->cpuidax) == 3 || conf.nmach > 1)
+ conf.copymode = 1;
+}
+
+static int
+mpintrcpu(void)
+{
+ int i;
+
+ /*
+ * The bulk of this code was written ~1995, when there was
+ * one architecture and one generation of hardware, the number
+ * of CPUs was up to 4(8) and the choices for interrupt routing
+ * were physical, or flat logical (optionally with lowest
+ * priority interrupt). Logical mode hasn't scaled well with
+ * the increasing number of packages/cores/threads, so the
+ * fall-back is to physical mode, which works across all processor
+ * generations, both AMD and Intel, using the APIC and xAPIC.
+ *
+ * Interrupt routing policy can be set here.
+ * Currently, just assign each interrupt to a different CPU on
+ * a round-robin basis. Some idea of the packages/cores/thread
+ * topology would be useful here, e.g. to not assign interrupts
+ * to more than one thread in a core, or to use a "noise" core.
+ * But, as usual, Intel make that an onerous task.
+ */
+ lock(&mpphysidlock);
+ for(;;){
+ i = mpphysid++;
+ if(mpphysid >= MaxAPICNO+1)
+ mpphysid = 0;
+ if(mpapic[i].online)
+ break;
+ }
+ unlock(&mpphysidlock);
+
+ return mpapic[i].apicno;
+}
+
+static int
+mpintrenablex(Vctl* v, int tbdf)
+{
+ Bus *bus;
+ Aintr *aintr;
+ Apic *apic;
+ Pcidev *pcidev;
+ int bno, dno, hi, irq, lo, n, type, vno;
+
+ /*
+ * Find the bus.
+ */
+ type = BUSTYPE(tbdf);
+ bno = BUSBNO(tbdf);
+ dno = BUSDNO(tbdf);
+ if(type == BusISA)
+ bno = mpisabus;
+ for(bus = mpbus; bus != nil; bus = bus->next){
+ if(bus->type != type)
+ continue;
+ if(bus->busno == bno)
+ break;
+ }
+ if(bus == nil){
+ print("ioapicirq: can't find bus type %d\n", type);
+ return -1;
+ }
+
+ /*
+ * For PCI devices the interrupt pin (INT[ABCD]) and device
+ * number are encoded into the entry irq field, so create something
+ * to match on. The interrupt pin used by the device has to be
+ * obtained from the PCI config space.
+ */
+ if(bus->type == BusPCI){
+ pcidev = pcimatchtbdf(tbdf);
+ if(pcidev != nil && (n = pcicfgr8(pcidev, PciINTP)) != 0)
+ irq = (dno<<2)|(n-1);
+ else
+ irq = -1;
+ //print("pcidev %uX: irq %uX v->irq %uX\n", tbdf, irq, v->irq);
+ }
+ else
+ irq = v->irq;
+
+ /*
+ * Find a matching interrupt entry from the list of interrupts
+ * attached to this bus.
+ */
+ for(aintr = bus->aintr; aintr; aintr = aintr->next){
+ if(aintr->intr->irq != irq)
+ continue;
+ if (0) {
+ PCMPintr* p = aintr->intr;
+
+ print("mpintrenablex: bus %d intin %d irq %d\n",
+ p->busno, p->intin, p->irq);
+ }
+ /*
+ * Check if already enabled. Multifunction devices may share
+ * INT[A-D]# so, if already enabled, check the polarity matches
+ * and the trigger is level.
+ *
+ * Should check the devices differ only in the function number,
+ * but that can wait for the planned enable/disable rewrite.
+ * The RDT read here is safe for now as currently interrupts
+ * are never disabled once enabled.
+ */
+ apic = aintr->apic;
+ ioapicrdtr(apic, aintr->intr->intin, 0, &lo);
+ if(!(lo & ApicIMASK)){
+ vno = lo & 0xFF;
+//print("%s vector %d (!imask)\n", v->name, vno);
+ n = mpintrinit(bus, aintr->intr, vno, v->irq);
+ n |= ApicPHYSICAL; /* no-op */
+ lo &= ~(ApicRemoteIRR|ApicDELIVS);
+ if(n != lo || !(n & ApicLEVEL)){
+ print("mpintrenable: multiple botch irq%d, tbdf %uX, lo %8.8uX, n %8.8uX\n",
+ v->irq, tbdf, lo, n);
+ return -1;
+ }
+
+ v->isr = lapicisr;
+ v->eoi = lapiceoi;
+
+ return vno;
+ }
+
+ /*
+ * With the APIC a unique vector can be assigned to each
+ * request to enable an interrupt. There are two reasons this
+ * is a good idea:
+ * 1) to prevent lost interrupts, no more than 2 interrupts
+ * should be assigned per block of 16 vectors (there is an
+ * in-service entry and a holding entry for each priority
+ * level and there is one priority level per block of 16
+ * interrupts).
+ * 2) each input pin on the IOAPIC will receive a different
+ * vector regardless of whether the devices on that pin use
+ * the same IRQ as devices on another pin.
+ */
+ vno = VectorAPIC + (incref(&mpvnoref)-1)*8;
+//print("%s vector %d (imask)\n", v->name, vno);
+ if(vno > MaxVectorAPIC){
+ print("mpintrenable: vno %d, irq %d, tbdf %uX\n",
+ vno, v->irq, tbdf);
+ return -1;
+ }
+ hi = mpintrcpu()<<24;
+ lo = mpintrinit(bus, aintr->intr, vno, v->irq);
+ //print("lo 0x%uX: busno %d intr %d vno %d irq %d elcr 0x%uX\n",
+ // lo, bus->busno, aintr->intr->irq, vno,
+ // v->irq, i8259elcr);
+ if(lo & ApicIMASK)
+ return -1;
+
+ lo |= ApicPHYSICAL; /* no-op */
+
+ if((apic->flags & PcmpEN) && apic->type == PcmpIOAPIC)
+ ioapicrdtw(apic, aintr->intr->intin, hi, lo);
+ //else
+ // print("lo not enabled 0x%uX %d\n",
+ // apic->flags, apic->type);
+
+ v->isr = lapicisr;
+ v->eoi = lapiceoi;
+
+ return vno;
+ }
+
+ return -1;
+}
+
+int
+mpintrenable(Vctl* v)
+{
+ int irq, tbdf, vno;
+
+ /*
+ * If the bus is known, try it.
+ * BUSUNKNOWN is given both by [E]ISA devices and by
+ * interrupts local to the processor (local APIC, coprocessor
+ * breakpoint and page-fault).
+ */
+ tbdf = v->tbdf;
+ if(tbdf != BUSUNKNOWN && (vno = mpintrenablex(v, tbdf)) != -1)
+ return vno;
+
+ irq = v->irq;
+ if(irq >= IrqLINT0 && irq <= MaxIrqLAPIC){
+ if(irq != IrqSPURIOUS)
+ v->isr = lapiceoi;
+ return VectorPIC+irq;
+ }
+ if(irq < 0 || irq > MaxIrqPIC){
+ print("mpintrenable: irq %d out of range\n", irq);
+ return -1;
+ }
+
+ /*
+ * Either didn't find it or have to try the default buses
+ * (ISA and EISA). This hack is due to either over-zealousness
+ * or laziness on the part of some manufacturers.
+ *
+ * The MP configuration table on some older systems
+ * (e.g. ASUS PCI/E-P54NP4) has an entry for the EISA bus
+ * but none for ISA. It also has the interrupt type and
+ * polarity set to 'default for this bus' which wouldn't
+ * be compatible with ISA.
+ */
+ if(mpeisabus != -1){
+ vno = mpintrenablex(v, MKBUS(BusEISA, 0, 0, 0));
+ if(vno != -1)
+ return vno;
+ }
+ if(mpisabus != -1){
+ vno = mpintrenablex(v, MKBUS(BusISA, 0, 0, 0));
+ if(vno != -1)
+ return vno;
+ }
+ print("mpintrenable: out of choices eisa %d isa %d tbdf %#ux irq %d\n",
+ mpeisabus, mpisabus, v->tbdf, v->irq);
+ return -1;
+}
+
+static Lock mpshutdownlock;
+
+void
+mpshutdown(void)
+{
+ /*
+ * To be done...
+ */
+ if(!canlock(&mpshutdownlock)){
+ /*
+ * If this processor received the CTRL-ALT-DEL from
+ * the keyboard, acknowledge it. Send an INIT to self.
+ */
+#ifdef FIXTHIS
+ if(lapicisr(VectorKBD))
+ lapiceoi(VectorKBD);
+#endif /* FIX THIS */
+ arch->introff();
+ idle();
+ }
+
+ print("apshutdown: active = %#8.8ux\n", active.machs);
+ delay(1000);
+ splhi();
+
+ /*
+ * INIT all excluding self.
+ */
+ lapicicrw(0, 0x000C0000|ApicINIT);
+
+ pcireset();
+ i8042reset();
+
+ /*
+ * Often the BIOS hangs during restart if a conventional 8042
+ * warm-boot sequence is tried. The following is Intel specific and
+ * seems to perform a cold-boot, but at least it comes back.
+ * And sometimes there is no keyboard...
+ *
+ * The reset register (0xcf9) is usually in one of the bridge
+ * chips. The actual location and sequence could be extracted from
+ * ACPI but why bother, this is the end of the line anyway.
+ */
+ print("no kbd; trying bios warm boot...");
+ *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */
+ outb(0xCF9, 0x02);
+ outb(0xCF9, 0x06);
+
+ print("can't reset\n");
+ for(;;)
+ idle();
+}
diff --git a/sys/src/9/pc/mp.h b/sys/src/9/pc/mp.h
new file mode 100755
index 000000000..31fd13e1f
--- /dev/null
+++ b/sys/src/9/pc/mp.h
@@ -0,0 +1,235 @@
+/*
+ * MultiProcessor Specification Version 1.[14].
+ */
+typedef struct { /* floating pointer */
+ uchar signature[4]; /* "_MP_" */
+ long physaddr; /* physical address of MP configuration table */
+ uchar length; /* 1 */
+ uchar specrev; /* [14] */
+ uchar checksum; /* all bytes must add up to 0 */
+ uchar type; /* MP system configuration type */
+ uchar imcrp;
+ uchar reserved[3];
+} _MP_;
+
+typedef struct { /* configuration table header */
+ uchar signature[4]; /* "PCMP" */
+ ushort length; /* total table length */
+ uchar version; /* [14] */
+ uchar checksum; /* all bytes must add up to 0 */
+ uchar product[20]; /* product id */
+ ulong oemtable; /* OEM table pointer */
+ ushort oemlength; /* OEM table length */
+ ushort entry; /* entry count */
+ ulong lapicbase; /* address of local APIC */
+ ushort xlength; /* extended table length */
+ uchar xchecksum; /* extended table checksum */
+ uchar reserved;
+} PCMP;
+
+typedef struct { /* processor table entry */
+ uchar type; /* entry type (0) */
+ uchar apicno; /* local APIC id */
+ uchar version; /* local APIC verison */
+ uchar flags; /* CPU flags */
+ uchar signature[4]; /* CPU signature */
+ ulong feature; /* feature flags from CPUID instruction */
+ uchar reserved[8];
+} PCMPprocessor;
+
+typedef struct { /* bus table entry */
+ uchar type; /* entry type (1) */
+ uchar busno; /* bus id */
+ char string[6]; /* bus type string */
+} PCMPbus;
+
+typedef struct { /* I/O APIC table entry */
+ uchar type; /* entry type (2) */
+ uchar apicno; /* I/O APIC id */
+ uchar version; /* I/O APIC version */
+ uchar flags; /* I/O APIC flags */
+ ulong addr; /* I/O APIC address */
+} PCMPioapic;
+
+typedef struct { /* interrupt table entry */
+ uchar type; /* entry type ([34]) */
+ uchar intr; /* interrupt type */
+ ushort flags; /* interrupt flag */
+ uchar busno; /* source bus id */
+ uchar irq; /* source bus irq */
+ uchar apicno; /* destination APIC id */
+ uchar intin; /* destination APIC [L]INTIN# */
+} PCMPintr;
+
+typedef struct { /* system address space mapping entry */
+ uchar type; /* entry type (128) */
+ uchar length; /* of this entry (20) */
+ uchar busno; /* bus id */
+ uchar addrtype;
+ ulong addrbase[2];
+ ulong addrlength[2];
+} PCMPsasm;
+
+typedef struct { /* bus hierarchy descriptor entry */
+ uchar type; /* entry type (129) */
+ uchar length; /* of this entry (8) */
+ uchar busno; /* bus id */
+ uchar info; /* bus info */
+ uchar parent; /* parent bus */
+ uchar reserved[3];
+} PCMPhierarchy;
+
+typedef struct { /* compatibility bus address space modifier entry */
+ uchar type; /* entry type (130) */
+ uchar length; /* of this entry (8) */
+ uchar busno; /* bus id */
+ uchar modifier; /* address modifier */
+ ulong range; /* predefined range list */
+} PCMPcbasm;
+
+enum { /* table entry types */
+ PcmpPROCESSOR = 0x00, /* one entry per processor */
+ PcmpBUS = 0x01, /* one entry per bus */
+ PcmpIOAPIC = 0x02, /* one entry per I/O APIC */
+ PcmpIOINTR = 0x03, /* one entry per bus interrupt source */
+ PcmpLINTR = 0x04, /* one entry per system interrupt source */
+
+ PcmpSASM = 0x80,
+ PcmpHIERARCHY = 0x81,
+ PcmpCBASM = 0x82,
+
+ /* PCMPprocessor and PCMPioapic flags */
+ PcmpEN = 0x01, /* enabled */
+ PcmpBP = 0x02, /* bootstrap processor */
+
+ /* PCMPiointr and PCMPlintr flags */
+ PcmpPOMASK = 0x03, /* polarity conforms to specifications of bus */
+ PcmpHIGH = 0x01, /* active high */
+ PcmpLOW = 0x03, /* active low */
+ PcmpELMASK = 0x0C, /* trigger mode of APIC input signals */
+ PcmpEDGE = 0x04, /* edge-triggered */
+ PcmpLEVEL = 0x0C, /* level-triggered */
+
+ /* PCMPiointr and PCMPlintr interrupt type */
+ PcmpINT = 0x00, /* vectored interrupt from APIC Rdt */
+ PcmpNMI = 0x01, /* non-maskable interrupt */
+ PcmpSMI = 0x02, /* system management interrupt */
+ PcmpExtINT = 0x03, /* vectored interrupt from external PIC */
+
+ /* PCMPsasm addrtype */
+ PcmpIOADDR = 0x00, /* I/O address */
+ PcmpMADDR = 0x01, /* memory address */
+ PcmpPADDR = 0x02, /* prefetch address */
+
+ /* PCMPhierarchy info */
+ PcmpSD = 0x01, /* subtractive decode bus */
+
+ /* PCMPcbasm modifier */
+ PcmpPR = 0x01, /* predefined range list */
+};
+
+/*
+ * Condensed form of the MP Configuration Table.
+ * This is created during a single pass through the MP Configuration
+ * table.
+ */
+typedef struct Aintr Aintr;
+typedef struct Bus Bus;
+typedef struct Apic Apic;
+
+typedef struct Bus {
+ uchar type;
+ uchar busno;
+ uchar po;
+ uchar el;
+
+ Aintr* aintr; /* interrupts tied to this bus */
+ Bus* next;
+} Bus;
+
+typedef struct Aintr {
+ PCMPintr* intr;
+ Apic* apic;
+ Aintr* next;
+};
+
+typedef struct Apic {
+ int type;
+ int apicno;
+ ulong* addr; /* register base address */
+ ulong paddr;
+ int flags; /* PcmpBP|PcmpEN */
+
+ Lock; /* I/O APIC: register access */
+ int mre; /* I/O APIC: maximum redirection entry */
+
+ int lintr[2]; /* Local APIC */
+ int machno;
+
+ int online;
+} Apic;
+
+enum {
+ MaxAPICNO = 254, /* 255 is physical broadcast */
+};
+
+enum { /* I/O APIC registers */
+ IoapicID = 0x00, /* ID */
+ IoapicVER = 0x01, /* version */
+ IoapicARB = 0x02, /* arbitration ID */
+ IoapicRDT = 0x10, /* redirection table */
+};
+
+/*
+ * Common bits for
+ * I/O APIC Redirection Table Entry;
+ * Local APIC Local Interrupt Vector Table;
+ * Local APIC Inter-Processor Interrupt;
+ * Local APIC Timer Vector Table.
+ */
+enum {
+ ApicFIXED = 0x00000000, /* [10:8] Delivery Mode */
+ ApicLOWEST = 0x00000100, /* Lowest priority */
+ ApicSMI = 0x00000200, /* System Management Interrupt */
+ ApicRR = 0x00000300, /* Remote Read */
+ ApicNMI = 0x00000400,
+ ApicINIT = 0x00000500, /* INIT/RESET */
+ ApicSTARTUP = 0x00000600, /* Startup IPI */
+ ApicExtINT = 0x00000700,
+
+ ApicPHYSICAL = 0x00000000, /* [11] Destination Mode (RW) */
+ ApicLOGICAL = 0x00000800,
+
+ ApicDELIVS = 0x00001000, /* [12] Delivery Status (RO) */
+ ApicHIGH = 0x00000000, /* [13] Interrupt Input Pin Polarity (RW) */
+ ApicLOW = 0x00002000,
+ ApicRemoteIRR = 0x00004000, /* [14] Remote IRR (RO) */
+ ApicEDGE = 0x00000000, /* [15] Trigger Mode (RW) */
+ ApicLEVEL = 0x00008000,
+ ApicIMASK = 0x00010000, /* [16] Interrupt Mask */
+};
+
+extern void ioapicinit(Apic*, int);
+extern void ioapicrdtr(Apic*, int, int*, int*);
+extern void ioapicrdtw(Apic*, int, int, int);
+
+extern void lapicclock(Ureg*, void*);
+extern int lapiceoi(int);
+extern void lapicerror(Ureg*, void*);
+extern void lapicicrw(ulong, ulong);
+extern void lapicinit(Apic*);
+extern void lapicintroff(void);
+extern void lapicintron(void);
+extern int lapicisr(int);
+extern void lapicnmidisable(void);
+extern void lapicnmienable(void);
+extern void lapiconline(void);
+extern void lapicspurious(Ureg*, void*);
+extern void lapicstartap(Apic*, int);
+extern void lapictimerset(uvlong);
+
+extern void mpinit(void);
+extern int mpintrenable(Vctl*);
+extern void mpshutdown(void);
+
+extern _MP_ *_mp_;
diff --git a/sys/src/9/pc/mtrr.c b/sys/src/9/pc/mtrr.c
new file mode 100755
index 000000000..dc8e52baa
--- /dev/null
+++ b/sys/src/9/pc/mtrr.c
@@ -0,0 +1,341 @@
+/*
+ * memory-type region registers.
+ *
+ * due to the possibility of extended addresses (for PAE)
+ * as large as 36 bits coming from the e820 memory map and the like,
+ * we'll use vlongs to hold addresses and lengths, even though we don't
+ * implement PAE in Plan 9.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+enum {
+ /*
+ * MTRR Physical base/mask are indexed by
+ * MTRRPhys{Base|Mask}N = MTRRPhys{Base|Mask}0 + 2*N
+ */
+ MTRRPhysBase0 = 0x200,
+ MTRRPhysMask0 = 0x201,
+ MTRRDefaultType = 0x2FF,
+ MTRRCap = 0xFE,
+ Nmtrr = 8,
+
+ /* cpuid extended function codes */
+ Exthighfunc = 1ul << 31,
+ Extprocsigamd,
+ Extprocname0,
+ Extprocname1,
+ Extprocname2,
+ Exttlbl1,
+ Extl2,
+ Extapm,
+ Extaddrsz,
+
+ Paerange = 1LL << 36,
+};
+
+enum {
+ CR4PageGlobalEnable = 1 << 7,
+ CR0CacheDisable = 1 << 30,
+};
+
+enum {
+ Uncacheable = 0,
+ Writecomb = 1,
+ Unknown1 = 2,
+ Unknown2 = 3,
+ Writethru = 4,
+ Writeprot = 5,
+ Writeback = 6,
+};
+
+enum {
+ Capvcnt = 0xff, /* mask: # of variable-range MTRRs we have */
+ Capwc = 1<<8, /* flag: have write combining? */
+ Capfix = 1<<10, /* flag: have fixed MTRRs? */
+ Deftype = 0xff, /* default MTRR type */
+ Deffixena = 1<<10, /* fixed-range MTRR enable */
+ Defena = 1<<11, /* MTRR enable */
+};
+
+typedef struct Mtrreg Mtrreg;
+typedef struct Mtrrop Mtrrop;
+
+struct Mtrreg {
+ vlong base;
+ vlong mask;
+};
+struct Mtrrop {
+ Mtrreg *reg;
+ int slot;
+};
+
+static char *types[] = {
+[Uncacheable] "uc",
+[Writecomb] "wc",
+[Unknown1] "uk1",
+[Unknown2] "uk2",
+[Writethru] "wt",
+[Writeprot] "wp",
+[Writeback] "wb",
+ nil
+};
+static Mtrrop *postedop;
+static Rendez oprend;
+
+static char *
+type2str(int type)
+{
+ if(type < 0 || type >= nelem(types))
+ return nil;
+ return types[type];
+}
+
+static int
+str2type(char *str)
+{
+ char **p;
+
+ for(p = types; *p != nil; p++)
+ if (strcmp(str, *p) == 0)
+ return p - types;
+ return -1;
+}
+
+static uvlong
+physmask(void)
+{
+ ulong regs[4];
+ static vlong mask = -1;
+
+ if (mask != -1)
+ return mask;
+ cpuid(Exthighfunc, regs);
+ if(regs[0] >= Extaddrsz) { /* ax */
+ cpuid(Extaddrsz, regs);
+ mask = (1LL << (regs[0] & 0xFF)) - 1; /* ax */
+ }
+ mask &= Paerange - 1; /* x86 sanity */
+ return mask;
+}
+
+/* limit physical addresses to 36 bits on the x86 */
+static void
+sanity(Mtrreg *mtrr)
+{
+ mtrr->base &= Paerange - 1;
+ mtrr->mask &= Paerange - 1;
+}
+
+static int
+ispow2(uvlong ul)
+{
+ return (ul & (ul - 1)) == 0;
+}
+
+/* true if mtrr is valid */
+static int
+mtrrdec(Mtrreg *mtrr, uvlong *ptr, uvlong *size, int *type)
+{
+ sanity(mtrr);
+ *ptr = mtrr->base & ~(BY2PG-1);
+ *type = mtrr->base & 0xff;
+ *size = (physmask() ^ (mtrr->mask & ~(BY2PG-1))) + 1;
+ return (mtrr->mask >> 11) & 1;
+}
+
+static void
+mtrrenc(Mtrreg *mtrr, uvlong ptr, uvlong size, int type, int ok)
+{
+ mtrr->base = ptr | (type & 0xff);
+ mtrr->mask = (physmask() & ~(size - 1)) | (ok? 1<<11: 0);
+ sanity(mtrr);
+}
+
+/*
+ * i is the index of the MTRR, and is multiplied by 2 because
+ * mask and base offsets are interleaved.
+ */
+static void
+mtrrget(Mtrreg *mtrr, uint i)
+{
+ if (i >= Nmtrr)
+ error("mtrr index out of range");
+ rdmsr(MTRRPhysBase0 + 2*i, &mtrr->base);
+ rdmsr(MTRRPhysMask0 + 2*i, &mtrr->mask);
+ sanity(mtrr);
+}
+
+static void
+mtrrput(Mtrreg *mtrr, uint i)
+{
+ if (i >= Nmtrr)
+ error("mtrr index out of range");
+ sanity(mtrr);
+ wrmsr(MTRRPhysBase0 + 2*i, mtrr->base);
+ wrmsr(MTRRPhysMask0 + 2*i, mtrr->mask);
+}
+
+static void
+mtrrop(Mtrrop **op)
+{
+ int s;
+ ulong cr0, cr4;
+ vlong def;
+ static long bar1, bar2;
+
+ s = splhi(); /* avoid race with mtrrclock */
+
+ /*
+ * wait for all CPUs to sync here, so that the MTRR setup gets
+ * done at roughly the same time on all processors.
+ */
+ _xinc(&bar1);
+ while(bar1 < conf.nmach)
+ microdelay(10);
+
+ cr4 = getcr4();
+ putcr4(cr4 & ~CR4PageGlobalEnable);
+ cr0 = getcr0();
+ wbinvd();
+ putcr0(cr0 | CR0CacheDisable);
+ wbinvd();
+ rdmsr(MTRRDefaultType, &def);
+ wrmsr(MTRRDefaultType, def & ~(vlong)Defena);
+
+ mtrrput((*op)->reg, (*op)->slot);
+
+ wbinvd();
+ wrmsr(MTRRDefaultType, def);
+ putcr0(cr0);
+ putcr4(cr4);
+
+ /*
+ * wait for all CPUs to sync up again, so that we don't continue
+ * executing while the MTRRs are still being set up.
+ */
+ _xinc(&bar2);
+ while(bar2 < conf.nmach)
+ microdelay(10);
+ *op = nil;
+ _xdec(&bar1);
+ while(bar1 > 0)
+ microdelay(10);
+ _xdec(&bar2);
+ wakeup(&oprend);
+ splx(s);
+}
+
+void
+mtrrclock(void) /* called from clock interrupt */
+{
+ if(postedop != nil)
+ mtrrop(&postedop);
+}
+
+/* if there's an operation still pending, keep sleeping */
+static int
+opavail(void *)
+{
+ return postedop == nil;
+}
+
+int
+mtrr(uvlong base, uvlong size, char *tstr)
+{
+ int i, vcnt, slot, type, mtype, mok;
+ vlong def, cap;
+ uvlong mp, msize;
+ Mtrreg entry, mtrr;
+ Mtrrop op;
+ static int tickreg;
+ static QLock mtrrlk;
+
+ if(!(m->cpuiddx & Mtrr))
+ error("mtrrs not supported");
+ if(base & (BY2PG-1) || size & (BY2PG-1) || size == 0)
+ error("mtrr base or size not 4k aligned or zero size");
+ if(base + size >= Paerange)
+ error("mtrr range exceeds 36 bits");
+ if(!ispow2(size))
+ error("mtrr size not power of 2");
+ if(base & (size - 1))
+ error("mtrr base not naturally aligned");
+
+ if((type = str2type(tstr)) == -1)
+ error("mtrr bad type");
+
+ rdmsr(MTRRCap, &cap);
+ rdmsr(MTRRDefaultType, &def);
+
+ switch(type){
+ default:
+ error("mtrr unknown type");
+ break;
+ case Writecomb:
+ if(!(cap & Capwc))
+ error("mtrr type wc (write combining) unsupported");
+ /* fallthrough */
+ case Uncacheable:
+ case Writethru:
+ case Writeprot:
+ case Writeback:
+ break;
+ }
+
+ qlock(&mtrrlk);
+ slot = -1;
+ vcnt = cap & Capvcnt;
+ for(i = 0; i < vcnt; i++){
+ mtrrget(&mtrr, i);
+ mok = mtrrdec(&mtrr, &mp, &msize, &mtype);
+ /* reuse any entry for addresses above 4GB */
+ if(!mok || mp == base && msize == size || mp >= (1LL<<32)){
+ slot = i;
+ break;
+ }
+ }
+ if(slot == -1)
+ error("no free mtrr slots");
+
+ while(postedop != nil)
+ sleep(&oprend, opavail, 0);
+ mtrrenc(&entry, base, size, type, 1);
+ op.reg = &entry;
+ op.slot = slot;
+ postedop = &op;
+ mtrrop(&postedop);
+ qunlock(&mtrrlk);
+ return 0;
+}
+
+int
+mtrrprint(char *buf, long bufsize)
+{
+ int i, vcnt, type;
+ long n;
+ uvlong base, size;
+ vlong cap, def;
+ Mtrreg mtrr;
+
+ n = 0;
+ if(!(m->cpuiddx & Mtrr))
+ return 0;
+ rdmsr(MTRRCap, &cap);
+ rdmsr(MTRRDefaultType, &def);
+ n += snprint(buf+n, bufsize-n, "cache default %s\n",
+ type2str(def & Deftype));
+ vcnt = cap & Capvcnt;
+ for(i = 0; i < vcnt; i++){
+ mtrrget(&mtrr, i);
+ if (mtrrdec(&mtrr, &base, &size, &type))
+ n += snprint(buf+n, bufsize-n,
+ "cache 0x%llux %llud %s\n",
+ base, size, type2str(type));
+ }
+ return n;
+}
diff --git a/sys/src/9/pc/nv_dma.h b/sys/src/9/pc/nv_dma.h
new file mode 100755
index 000000000..509324c21
--- /dev/null
+++ b/sys/src/9/pc/nv_dma.h
@@ -0,0 +1,179 @@
+
+ /***************************************************************************\
+|* *|
+|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NOTICE TO USER: The source code is copyrighted under U.S. and *|
+|* international laws. Users and possessors of this source code are *|
+|* hereby granted a nonexclusive, royalty-free copyright license to *|
+|* use this code in individual and commercial software. *|
+|* *|
+|* Any use of this source code must include, in the user documenta- *|
+|* tion and internal comments to the code, notices to the end user *|
+|* as follows: *|
+|* *|
+|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
+|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
+|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
+|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
+|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
+|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
+|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
+|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
+|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
+|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
+|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
+|* *|
+|* U.S. Government End Users. This source code is a "commercial *|
+|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
+|* consisting of "commercial computer software" and "commercial *|
+|* computer software documentation," as such terms are used in *|
+|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
+|* ment only as a commercial end item. Consistent with 48 C.F.R. *|
+|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
+|* all U.S. Government End Users acquire the source code with only *|
+|* those rights set forth herein. *|
+|* *|
+ \***************************************************************************/
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_dma.h,v 1.2 2003/07/31 21:41:26 mvojkovi Exp $ */
+
+#define SURFACE_FORMAT 0x00000300
+#define SURFACE_FORMAT_DEPTH8 0x00000001
+#define SURFACE_FORMAT_DEPTH15 0x00000002
+#define SURFACE_FORMAT_DEPTH16 0x00000004
+#define SURFACE_FORMAT_DEPTH24 0x00000006
+#define SURFACE_PITCH 0x00000304
+#define SURFACE_PITCH_SRC 15:0
+#define SURFACE_PITCH_DST 31:16
+#define SURFACE_OFFSET_SRC 0x00000308
+#define SURFACE_OFFSET_DST 0x0000030C
+
+#define ROP_SET 0x00002300
+
+#define PATTERN_FORMAT 0x00004300
+#define PATTERN_FORMAT_DEPTH8 0x00000003
+#define PATTERN_FORMAT_DEPTH16 0x00000001
+#define PATTERN_FORMAT_DEPTH24 0x00000003
+#define PATTERN_COLOR_0 0x00004310
+#define PATTERN_COLOR_1 0x00004314
+#define PATTERN_PATTERN_0 0x00004318
+#define PATTERN_PATTERN_1 0x0000431C
+
+#define CLIP_POINT 0x00006300
+#define CLIP_POINT_X 15:0
+#define CLIP_POINT_Y 31:16
+#define CLIP_SIZE 0x00006304
+#define CLIP_SIZE_WIDTH 15:0
+#define CLIP_SIZE_HEIGHT 31:16
+
+#define LINE_FORMAT 0x00008300
+#define LINE_FORMAT_DEPTH8 0x00000003
+#define LINE_FORMAT_DEPTH16 0x00000001
+#define LINE_FORMAT_DEPTH24 0x00000003
+#define LINE_COLOR 0x00008304
+#define LINE_MAX_LINES 16
+#define LINE_LINES(i) 0x00008400\
+ +(i)*8
+#define LINE_LINES_POINT0_X 15:0
+#define LINE_LINES_POINT0_Y 31:16
+#define LINE_LINES_POINT1_X 47:32
+#define LINE_LINES_POINT1_Y 63:48
+
+#define BLIT_POINT_SRC 0x0000A300
+#define BLIT_POINT_SRC_X 15:0
+#define BLIT_POINT_SRC_Y 31:16
+#define BLIT_POINT_DST 0x0000A304
+#define BLIT_POINT_DST_X 15:0
+#define BLIT_POINT_DST_Y 31:16
+#define BLIT_SIZE 0x0000A308
+#define BLIT_SIZE_WIDTH 15:0
+#define BLIT_SIZE_HEIGHT 31:16
+
+#define RECT_FORMAT 0x0000C300
+#define RECT_FORMAT_DEPTH8 0x00000003
+#define RECT_FORMAT_DEPTH16 0x00000001
+#define RECT_FORMAT_DEPTH24 0x00000003
+#define RECT_SOLID_COLOR 0x0000C3FC
+#define RECT_SOLID_RECTS_MAX_RECTS 32
+#define RECT_SOLID_RECTS(i) 0x0000C400\
+ +(i)*8
+#define RECT_SOLID_RECTS_Y 15:0
+#define RECT_SOLID_RECTS_X 31:16
+#define RECT_SOLID_RECTS_HEIGHT 47:32
+#define RECT_SOLID_RECTS_WIDTH 63:48
+
+#define RECT_EXPAND_ONE_COLOR_CLIP 0x0000C7EC
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_X 15:0
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_Y 31:16
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_X 47:32
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_Y 63:48
+#define RECT_EXPAND_ONE_COLOR_COLOR 0x0000C7F4
+#define RECT_EXPAND_ONE_COLOR_SIZE 0x0000C7F8
+#define RECT_EXPAND_ONE_COLOR_SIZE_WIDTH 15:0
+#define RECT_EXPAND_ONE_COLOR_SIZE_HEIGHT 31:16
+#define RECT_EXPAND_ONE_COLOR_POINT 0x0000C7FC
+#define RECT_EXPAND_ONE_COLOR_POINT_X 15:0
+#define RECT_EXPAND_ONE_COLOR_POINT_Y 31:16
+#define RECT_EXPAND_ONE_COLOR_DATA_MAX_DWORDS 128
+#define RECT_EXPAND_ONE_COLOR_DATA(i) 0x0000C800\
+ +(i)*4
+
+#define RECT_EXPAND_TWO_COLOR_CLIP 0x0000CBE4
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_X 15:0
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_Y 31:16
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_X 47:32
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_Y 63:48
+#define RECT_EXPAND_TWO_COLOR_COLOR_0 0x0000CBEC
+#define RECT_EXPAND_TWO_COLOR_COLOR_1 0x0000CBF0
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN 0x0000CBF4
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN_WIDTH 15:0
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN_HEIGHT 31:16
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT 0x0000CBF8
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_WIDTH 15:0
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_HEIGHT 31:16
+#define RECT_EXPAND_TWO_COLOR_POINT 0x0000CBFC
+#define RECT_EXPAND_TWO_COLOR_POINT_X 15:0
+#define RECT_EXPAND_TWO_COLOR_POINT_Y 31:16
+#define RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS 128
+#define RECT_EXPAND_TWO_COLOR_DATA(i) 0x0000CC00\
+ +(i)*4
+
+#define STRETCH_BLIT_FORMAT 0x0000E300
+#define STRETCH_BLIT_FORMAT_DEPTH8 0x00000004
+#define STRETCH_BLIT_FORMAT_DEPTH16 0x00000007
+#define STRETCH_BLIT_FORMAT_DEPTH24 0x00000004
+#define STRETCH_BLIT_FORMAT_X8R8G8B8 0x00000004
+#define STRETCH_BLIT_FORMAT_YUYV 0x00000005
+#define STRETCH_BLIT_FORMAT_UYVY 0x00000006
+#define STRETCH_BLIT_CLIP_POINT 0x0000E308
+#define STRETCH_BLIT_CLIP_POINT_X 15:0
+#define STRETCH_BLIT_CLIP_POINT_Y 31:16
+#define STRETCH_BLIT_CLIP_SIZE 0x0000E30C
+#define STRETCH_BLIT_CLIP_SIZE_WIDTH 15:0
+#define STRETCH_BLIT_CLIP_SIZE_HEIGHT 31:16
+#define STRETCH_BLIT_DST_POINT 0x0000E310
+#define STRETCH_BLIT_DST_POINT_X 15:0
+#define STRETCH_BLIT_DST_POINT_Y 31:16
+#define STRETCH_BLIT_DST_SIZE 0x0000E314
+#define STRETCH_BLIT_DST_SIZE_WIDTH 15:0
+#define STRETCH_BLIT_DST_SIZE_HEIGHT 31:16
+#define STRETCH_BLIT_DU_DX 0x0000E318
+#define STRETCH_BLIT_DV_DY 0x0000E31C
+#define STRETCH_BLIT_SRC_SIZE 0x0000E400
+#define STRETCH_BLIT_SRC_SIZE_WIDTH 15:0
+#define STRETCH_BLIT_SRC_SIZE_HEIGHT 31:16
+#define STRETCH_BLIT_SRC_FORMAT 0x0000E404
+#define STRETCH_BLIT_SRC_FORMAT_PITCH 15:0
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN 23:16
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER 0x00000001
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER 0x00000002
+#define STRETCH_BLIT_SRC_FORMAT_FILTER 31:24
+#define STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE 0x00000000
+#define STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR 0x00000001
+#define STRETCH_BLIT_SRC_OFFSET 0x0000E408
+#define STRETCH_BLIT_SRC_POINT 0x0000E40C
+#define STRETCH_BLIT_SRC_POINT_U 15:0
+#define STRETCH_BLIT_SRC_POINT_V 31:16
diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc
new file mode 100755
index 000000000..d05e60baa
--- /dev/null
+++ b/sys/src/9/pc/pc
@@ -0,0 +1,132 @@
+dev
+ root
+ cons
+
+ arch
+ pnp pci
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ rtc
+ ssl
+ tls
+ cap
+ kprof
+ fs
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
+
+ draw screen vga vgax
+ mouse mouse
+ vga
+ kbmap
+ kbin
+
+ sd
+ floppy dma
+ lpt
+
+ audio dma
+ pccard
+ i82365 cis
+ uart
+ usb
+
+
+link
+ realmode
+ devpccard
+ devi82365
+ ether2000 ether8390
+ ether2114x pci
+ ether589 etherelnk3
+ ether79c970 pci
+ ether8003 ether8390
+ ether8139 pci
+ ether8169 pci ethermii
+ ether82543gc pci
+ ether82563 pci
+ ether82557 pci
+ ether83815 pci
+ etherdp83820 pci
+ etherec2t ether8390
+ etherelnk3 pci
+ etherga620 pci
+ etherigbe pci ethermii
+ ethervgbe pci ethermii
+ ethervt6102 pci ethermii
+ ethervt6105m pci ethermii
+ ethersink
+ ethersmc devi82365 cis
+ etherwavelan wavelan devi82365 cis pci
+ ethermedium
+# etherm10g
+ ether82598 pci
+ pcmciamodem
+ netdevmedium
+ loopbackmedium
+ usbuhci
+ usbohci
+ usbehci usbehcipc
+
+misc
+ archmp mp apic
+ mtrr
+
+ sdata pci sdscsi
+ sd53c8xx pci sdscsi
+ sdmylex pci sdscsi
+ sdiahci pci sdscsi
+
+ uarti8250
+ uartpci pci
+ uartisa
+
+ vga3dfx +cur
+ vgaark2000pv +cur
+ vgabt485 =cur
+ vgaclgd542x +cur
+ vgaclgd546x +cur
+ vgact65545 +cur
+ vgacyber938x +cur
+ vgaet4000 +cur
+ vgahiqvideo +cur
+ vgai81x +cur
+ vgamach64xx +cur
+ vgamga2164w +cur
+ vgamga4xx +cur
+ vganeomagic +cur
+ vganvidia +cur
+ vgargb524 =cur
+ vgas3 +cur vgasavage
+ vgat2r4 +cur
+ vgatvp3020 =cur
+ vgatvp3026 =cur
+ vgavesa
+ vgavmware +cur
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+ gre
+ ipmux
+ esp
+
+port
+ int cpuserver = 0;
+
+boot
+ tcp
+
+bootdir
+ bootpc.out boot
+ /386/bin/ip/ipconfig
+ /386/bin/auth/factotum
+ /386/bin/usb/usbd
diff --git a/sys/src/9/pc/pcauth b/sys/src/9/pc/pcauth
new file mode 100755
index 000000000..5899273ba
--- /dev/null
+++ b/sys/src/9/pc/pcauth
@@ -0,0 +1,82 @@
+# pcauth - pccpuf specialised for our auth servers
+dev
+ root
+ cons
+ arch
+ pnp pci
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ rtc
+ ssl
+ tls
+ cap
+ kprof
+ fs
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
+
+ draw screen vga vgax
+ mouse mouse
+ vga
+
+ sd
+ floppy dma
+
+ uart
+ usb
+ kbin
+
+link
+ apm apmjump
+ etherdp83820 pci
+ ether82557 pci
+ ethervt6102 pci ethermii
+ ethervt6105m pci ethermii
+ ethermedium
+ netdevmedium
+ loopbackmedium
+ usbuhci
+ usbohci
+ usbehci usbehcipc
+
+misc
+ realmode
+ mtrr
+ sdata pci sdscsi
+
+ uarti8250
+ uartpci
+
+ vgamach64xx +cur
+ vgas3 +cur vgasavage
+
+ip
+ tcp
+ udp
+ rudp
+ ipifc
+ icmp
+ icmp6
+ gre
+ ipmux
+ esp
+
+port
+ int cpuserver = 1;
+
+boot cpu boot #S/sdC0/
+ tcp
+ local
+
+bootdir
+ bootpcauth.out boot
+ /386/bin/ip/ipconfig
+ /386/bin/auth/factotum
+ /386/bin/fossil/fossil
+ /386/bin/venti/venti
+ /386/bin/usb/usbd
diff --git a/sys/src/9/pc/pccd b/sys/src/9/pc/pccd
new file mode 100755
index 000000000..0fbfbb599
--- /dev/null
+++ b/sys/src/9/pc/pccd
@@ -0,0 +1,130 @@
+# pccd - small kernel used to install from cd
+dev
+ root
+ cons
+
+ arch
+ pnp pci
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ rtc
+ ssl
+ tls
+ cap
+ kprof
+ fs
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
+
+ draw screen vga vgax
+ mouse mouse
+ vga
+ kbmap
+ kbin
+
+ sd
+ floppy dma
+ lpt
+
+ audio dma
+ pccard
+ i82365 cis
+ uart
+ usb
+
+link
+ realmode
+ devpccard
+ devi82365
+ apm apmjump
+ ether2000 ether8390
+ ether2114x pci
+ ether589 etherelnk3
+ ether79c970 pci
+ ether8003 ether8390
+ ether8139 pci
+ ether8169 pci ethermii
+ ether82543gc pci
+ ether82563 pci
+ ether82557 pci
+ ether83815 pci
+ etherdp83820 pci
+ etherec2t ether8390
+ etherelnk3 pci
+ etherga620 pci
+ etherigbe pci ethermii
+ ethervgbe pci ethermii
+ ethervt6102 pci ethermii
+ ethervt6105m pci ethermii
+ ethersink
+ ethersmc devi82365 cis
+ etherwavelan wavelan devi82365 cis pci
+ ethermedium
+# etherm10g
+# ether82598 pci
+ pcmciamodem
+ netdevmedium
+ usbuhci
+ usbohci
+ usbehci usbehcipc
+
+misc
+ archmp mp apic
+ mtrr
+
+ sdata pci sdscsi
+ sd53c8xx pci sdscsi
+ sdmylex pci sdscsi
+ sdiahci pci sdscsi
+
+ uarti8250
+ uartpci pci
+ uartisa
+
+ vga3dfx +cur
+ vgaark2000pv +cur
+ vgabt485 =cur
+ vgaclgd542x +cur
+ vgaclgd546x +cur
+ vgact65545 +cur
+ vgacyber938x +cur
+ vgaet4000 +cur
+ vgahiqvideo +cur
+ vgai81x +cur
+ vgamach64xx +cur
+ vgamga2164w +cur
+ vgamga4xx +cur
+ vganeomagic +cur
+ vganvidia +cur
+ vgargb524 =cur
+ vgas3 +cur vgasavage
+ vgat2r4 +cur
+ vgatvp3020 =cur
+ vgatvp3026 =cur
+ vgavesa
+ vgavmware +cur
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+
+port
+ int cpuserver = 0;
+
+boot boot #S/sdD0/data
+ tcp
+ local
+
+bootdir
+ bootpccd.out boot
+ /386/bin/ip/ipconfig ipconfig
+ /386/bin/9660srv kfs
+ /386/bin/usb/usbd
diff --git a/sys/src/9/pc/pccpu b/sys/src/9/pc/pccpu
new file mode 100755
index 000000000..e4a71194d
--- /dev/null
+++ b/sys/src/9/pc/pccpu
@@ -0,0 +1,99 @@
+# pccpu - cpu server kernel
+dev
+ root
+ cons
+ arch
+ pnp pci
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ rtc
+ ssl
+ tls
+ bridge log
+ sdp thwack unthwack
+ cap
+ kprof
+ fs
+ segment
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
+
+ sd
+ floppy dma
+ aoe
+
+ uart
+ usb
+ kbin
+ audio
+
+link
+ realmode
+ ether2000 ether8390
+ ether2114x pci
+ ether79c970 pci
+ ether8003 ether8390
+ ether8139 pci
+ ether8169 pci ethermii
+ ether82543gc pci
+ ether82563 pci
+ ether82557 pci
+ ether83815 pci
+ etherdp83820 pci
+ etherelnk3 pci
+ etherga620 pci
+ etherigbe pci ethermii
+ ethervgbe pci ethermii
+ ethervt6102 pci ethermii
+ ethervt6105m pci ethermii
+# etherm10g pci ethermii
+ ether82598 pci
+ ethersink
+ ethermedium
+ loopbackmedium
+ usbuhci
+ usbohci
+ usbehci usbehcipc
+
+misc
+ archmp mp apic
+ mtrr
+
+ uarti8250
+ uartpci pci
+ uartaxp pci
+
+ sdata pci sdscsi
+ sd53c8xx pci sdscsi
+ sdmv50xx pci sdscsi
+ sdmylex pci sdscsi
+ sdiahci pci sdscsi
+ sdaoe sdscsi
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+ gre
+ ipmux
+ esp
+ rudp
+
+port
+ int cpuserver = 1;
+
+boot cpu
+ tcp
+
+bootdir
+ bootpccpu.out boot
+ /386/bin/ip/ipconfig ipconfig
+ /386/bin/auth/factotum
+ /386/bin/usb/usbd
diff --git a/sys/src/9/pc/pccpuf b/sys/src/9/pc/pccpuf
new file mode 100755
index 000000000..0fb4a0a34
--- /dev/null
+++ b/sys/src/9/pc/pccpuf
@@ -0,0 +1,132 @@
+# pccpuf - pc cpu server with fossil root and maybe venti block store
+dev
+ root
+ cons
+ arch
+ pnp pci
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ rtc
+ ssl
+ tls
+ bridge log
+ sdp thwack unthwack
+ cap
+ kprof
+ fs
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
+
+ draw screen vga vgax
+ mouse mouse
+ vga
+
+ sd
+ floppy dma
+ aoe
+
+ uart
+ usb
+ kbin
+
+link
+ realmode
+ devpccard
+ devi82365
+ ether2000 ether8390
+ ether2114x pci
+ ether589 etherelnk3
+ ether79c970 pci
+ ether8003 ether8390
+ ether8139 pci
+ ether8169 pci ethermii
+ ether82543gc pci
+ ether82563 pci
+ ether82557 pci
+ ether83815 pci
+ etherdp83820 pci
+ etherec2t ether8390
+ etherelnk3 pci
+ etherga620 pci
+ etherigbe pci ethermii
+ ethervgbe pci ethermii
+ ethervt6102 pci ethermii
+ ethervt6105m pci ethermii
+# etherm10g pci
+ ethersink
+ ethersmc devi82365 cis
+ etherwavelan wavelan devi82365 cis pci
+ ethermedium
+ netdevmedium
+ loopbackmedium
+ usbuhci
+ usbohci
+ usbehci usbehcipc
+
+misc
+ archmp mp apic
+ mtrr
+
+ uarti8250
+ uartpci pci
+
+ sdata pci sdscsi
+ sd53c8xx pci sdscsi
+ sdmylex pci sdscsi
+ sdiahci pci sdscsi
+ sdaoe
+
+ vga3dfx +cur
+ vgaark2000pv +cur
+ vgabt485 =cur
+ vgaclgd542x +cur
+ vgaclgd546x +cur
+ vgact65545 +cur
+ vgacyber938x +cur
+ vgaet4000 +cur
+ vgahiqvideo +cur
+ vgai81x +cur
+ vgamach64xx +cur
+ vgamga2164w +cur
+ vgamga4xx +cur
+ vganeomagic +cur
+ vganvidia +cur
+ vgargb524 =cur
+ vgas3 +cur vgasavage
+ vgat2r4 +cur
+ vgatvp3020 =cur
+ vgatvp3026 =cur
+ vgavesa
+ vgavmware +cur
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+ gre
+ ipmux
+ esp
+ rudp
+
+port
+ int cpuserver = 1;
+
+boot cpu boot #S/sdC0/
+ tcp
+ local
+
+bootdir
+ bootpccpuf.out boot
+ /386/bin/ip/ipconfig
+ /386/bin/auth/factotum
+# /386/bin/disk/kfs
+ /386/bin/fossil/fossil
+ /386/bin/venti/venti
+ /386/bin/usb/usbd
diff --git a/sys/src/9/pc/pcdisk b/sys/src/9/pc/pcdisk
new file mode 100755
index 000000000..0b6cfb53b
--- /dev/null
+++ b/sys/src/9/pc/pcdisk
@@ -0,0 +1,134 @@
+# pcdisk - pc terminal with kfs or cfs root
+dev
+ root
+ cons
+ arch
+ pnp pci
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ rtc
+ ssl
+ tls
+ cap
+ kprof
+ fs
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
+
+ draw screen vga vgax
+ mouse mouse
+ vga
+ kbmap
+ kbin
+
+ sd
+ floppy dma
+ lpt
+
+ audio dma
+ pccard
+ i82365 cis
+ uart
+ usb
+ aoe
+
+link
+ realmode
+ devpccard
+ devi82365
+ apm apmjump
+ ether2000 ether8390
+ ether2114x pci
+ ether589 etherelnk3
+ ether79c970 pci
+ ether8003 ether8390
+ ether8139
+ ether8169 pci ethermii
+ ether82543gc pci
+ ether82563 pci
+ ether82557 pci
+ ether83815 pci
+ etherec2t ether8390
+ etherelnk3 pci
+ etherga620 pci
+ etherigbe pci ethermii
+ ethervgbe pci ethermii
+ ethervt6102 pci ethermii
+ ethervt6105m pci ethermii
+ ethersink
+ ethersmc devi82365 cis
+ etherwavelan wavelan devi82365 cis pci
+ ethermedium
+ pcmciamodem
+ netdevmedium
+ loopbackmedium
+ usbuhci
+ usbohci
+ usbehci usbehcipc
+
+misc
+ archmp mp apic
+ mtrr
+
+ sdata pci sdscsi
+ sd53c8xx pci sdscsi
+ sdmylex pci sdscsi
+ sdiahci pci sdscsi
+ sdaoe
+
+ uarti8250
+ uartpci pci
+
+ vga3dfx +cur
+ vgaark2000pv +cur
+ vgabt485 =cur
+ vgaclgd542x +cur
+ vgaclgd546x +cur
+ vgact65545 +cur
+ vgacyber938x +cur
+ vgaet4000 +cur
+ vgahiqvideo +cur
+ vgai81x +cur
+ vgamach64xx +cur
+ vgamga2164w +cur
+ vgamga4xx +cur
+ vganeomagic +cur
+ vganvidia +cur
+ vgargb524 =cur
+ vgas3 +cur vgasavage
+ vgat2r4 +cur
+ vgatvp3020 =cur
+ vgatvp3026 =cur
+ vgavesa
+ vgavmware +cur
+
+ip
+ tcp
+ udp
+ rudp
+ ipifc
+ icmp
+ icmp6
+ gre
+ ipmux
+ esp
+
+port
+ int cpuserver = 0;
+
+boot boot #S/sdC0/
+ tcp
+ local
+
+bootdir
+ bootpcdisk.out boot
+ /386/bin/ip/ipconfig
+ /386/bin/auth/factotum
+ /386/bin/disk/kfs
+ /386/bin/cfs
+ /386/bin/usb/usbd
diff --git a/sys/src/9/pc/pcf b/sys/src/9/pc/pcf
new file mode 100755
index 000000000..0bf8d9c98
--- /dev/null
+++ b/sys/src/9/pc/pcf
@@ -0,0 +1,137 @@
+# pcf - pc terminal with fossil root and maybe venti block store
+dev
+ root
+ cons
+ arch
+ pnp pci
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ rtc
+ ssl
+ tls
+ cap
+ kprof
+ fs
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
+
+ draw screen vga vgax
+ mouse mouse
+ vga
+ kbmap
+ kbin
+
+ sd
+ floppy dma
+ aoe
+ lpt
+
+ audio dma
+ pccard
+ i82365 cis
+ uart
+ usb
+
+link
+ realmode
+ devpccard
+ devi82365
+ apm apmjump
+ ether2000 ether8390
+ ether2114x pci
+ ether589 etherelnk3
+ ether79c970 pci
+ ether8003 ether8390
+ ether8139 pci
+ ether8169 pci ethermii
+# should be obsoleted by igbe
+# ether82543gc pci
+ ether82557 pci
+ ether82563 pci
+ ether83815 pci
+ etherdp83820 pci
+ etherec2t ether8390
+ etherelnk3 pci
+ etherga620 pci
+ etherigbe pci ethermii
+ ethervgbe pci ethermii
+ ethervt6102 pci ethermii
+ ethervt6105m pci ethermii
+ ethersink
+ ethersmc devi82365 cis
+ etherwavelan wavelan devi82365 cis pci
+ ethermedium
+ pcmciamodem
+ netdevmedium
+ loopbackmedium
+ usbuhci
+ usbohci
+ usbehci usbehcipc
+
+misc
+ archmp mp apic
+ mtrr
+
+ sdata pci sdscsi
+ sd53c8xx pci sdscsi
+ sdmylex pci sdscsi
+ sdiahci pci sdscsi
+ sdaoe
+
+ uarti8250
+ uartpci pci
+
+ vga3dfx +cur
+ vgaark2000pv +cur
+ vgabt485 =cur
+ vgaclgd542x +cur
+ vgaclgd546x +cur
+ vgact65545 +cur
+ vgacyber938x +cur
+ vgaet4000 +cur
+ vgahiqvideo +cur
+ vgai81x +cur
+ vgamach64xx +cur
+ vgamga2164w +cur
+ vgamga4xx +cur
+ vganeomagic +cur
+ vganvidia +cur
+ vgaradeon +cur
+ vgargb524 =cur
+ vgas3 +cur vgasavage
+ vgat2r4 +cur
+ vgatvp3020 =cur
+ vgatvp3026 =cur
+ vgavesa
+ vgavmware +cur
+
+ip
+ tcp
+ udp
+ rudp
+ ipifc
+ icmp
+ icmp6
+ gre
+ ipmux
+ esp
+
+port
+ int cpuserver = 0;
+
+boot boot #S/sdC0/
+ tcp
+ local
+
+bootdir
+ bootpcf.out boot
+ /386/bin/ip/ipconfig
+ /386/bin/auth/factotum
+ /386/bin/fossil/fossil
+ /386/bin/venti/venti
+ /386/bin/usb/usbd
diff --git a/sys/src/9/pc/pcflop b/sys/src/9/pc/pcflop
new file mode 100755
index 000000000..4fbd32d7a
--- /dev/null
+++ b/sys/src/9/pc/pcflop
@@ -0,0 +1,99 @@
+# tiny kernel used to install from floppy.
+# has minimal vga drivers, no usb support and only some ether drivers,
+# and in general no frills. probably only useful in quite old systems.
+dev
+ root
+ cons
+
+ arch
+ pnp pci
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ rtc
+# ssl
+# tls
+ cap
+# kprof
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
+
+ draw screen vga vgax
+ mouse mouse
+ vga
+# kbmap
+
+ sd
+ floppy dma
+
+ pccard
+ i82365 cis
+ uart
+
+link
+ realmode
+ devpccard
+ devi82365
+ ether2000 ether8390
+ ether2114x pci
+ ether589 etherelnk3
+ ether79c970 pci
+ ether8003 ether8390
+ ether8139 pci
+ ether8169 pci ethermii
+# ether82563 pci
+ ether82557 pci
+ ether83815 pci
+# etherdp83820 pci
+ etherec2t ether8390
+ etherelnk3 pci
+# has vast firmware
+# etherga620 pci
+ etherigbe pci ethermii
+ ethervgbe pci ethermii
+ ethervt6102 pci ethermii
+# ethervt6105m pci ethermii
+# ethersink
+ ethersmc devi82365 cis
+ etherwavelan wavelan devi82365 cis pci
+ ethermedium
+ pcmciamodem
+ netdevmedium
+ loopbackmedium
+
+misc
+# archmp mp apic
+ mtrr
+
+ sdata pci sdscsi
+ sd53c8xx pci sdscsi
+ sdmylex pci sdscsi
+# sdiahci pci sdscsi
+
+ uarti8250
+# uartpci pci
+
+ vgavesa
+# vgavmware +cur
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+
+port
+ int cpuserver = 0;
+
+boot glenda boot #f/fd0disk
+ local
+
+bootdir
+ bootpcflop.out boot
+ /sys/lib/dist/bin/386/bzfs kfs
+ /sys/lib/dist/pc/root.bz2 bzroot
diff --git a/sys/src/9/pc/pcfs b/sys/src/9/pc/pcfs
new file mode 100755
index 000000000..16b990777
--- /dev/null
+++ b/sys/src/9/pc/pcfs
@@ -0,0 +1,99 @@
+# pcfs - pccpuf variant with venti, fossil, boot script & more compiled in.
+# for use on file servers, including standalone ones
+dev
+ root
+ cons
+ arch
+ pnp pci
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ rtc
+ ssl
+ tls
+ cap
+ fs
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
+
+ sd
+ floppy dma
+ aoe
+
+ uart
+ usb
+ kbin
+
+link
+ ether82557 pci
+ ether82563 pci
+ etherdp83820 pci
+ etherga620 pci
+ etherigbe pci ethermii
+ ethervt6105m
+ ethersink
+ ethermedium
+ netdevmedium
+ loopbackmedium
+ usbuhci
+ usbohci
+ usbehci usbehcipc
+
+misc
+ realmode
+ archmp mp apic
+ mtrr
+
+ uarti8250
+
+ sdaoe
+ sdata pci sdscsi
+ sdiahci pci sdscsi
+ sd53c8xx pci sdscsi
+ sdmylex pci sdscsi
+
+ip
+ tcp
+ udp
+ rudp
+ ipifc
+ icmp
+ icmp6
+ ipmux
+ esp
+
+port
+ int cpuserver = 1;
+
+boot boot #S/sdC0/
+ tcp
+ local
+
+bootdir
+ boot.fs boot
+ /386/bin/rc
+ /rc/lib/rcmain
+ /386/bin/ip/ipconfig
+ /386/bin/auth/factotum
+ /386/bin/venti/venti
+ /386/bin/fossil/fossil
+ /386/bin/auth/aescbc
+ /386/bin/aux/zerotrunc
+ /386/bin/bind
+ /386/bin/cat
+ /386/bin/cp
+ /386/bin/disk/fdisk
+ /386/bin/disk/prep
+ /386/bin/echo
+ /386/bin/ls
+ /386/bin/mount
+ /386/bin/read
+ /386/bin/sed
+ /386/bin/sleep
+ /386/bin/srv
+ /386/bin/test
+ /386/bin/usb/usbd
diff --git a/sys/src/9/pc/pci.c b/sys/src/9/pc/pci.c
new file mode 100755
index 000000000..1443a31dc
--- /dev/null
+++ b/sys/src/9/pc/pci.c
@@ -0,0 +1,1488 @@
+/*
+ * PCI support code.
+ * Needs a massive rewrite.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define DBG if(0) pcilog
+
+struct
+{
+ char output[16384];
+ int ptr;
+}PCICONS;
+
+int
+pcilog(char *fmt, ...)
+{
+ int n;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+
+ memmove(PCICONS.output+PCICONS.ptr, buf, n);
+ PCICONS.ptr += n;
+ return n;
+}
+
+enum
+{ /* configuration mechanism #1 */
+ PciADDR = 0xCF8, /* CONFIG_ADDRESS */
+ PciDATA = 0xCFC, /* CONFIG_DATA */
+
+ /* configuration mechanism #2 */
+ PciCSE = 0xCF8, /* configuration space enable */
+ PciFORWARD = 0xCFA, /* which bus */
+
+ MaxFNO = 7,
+ MaxUBN = 255,
+};
+
+enum
+{ /* command register */
+ IOen = (1<<0),
+ MEMen = (1<<1),
+ MASen = (1<<2),
+ MemWrInv = (1<<4),
+ PErrEn = (1<<6),
+ SErrEn = (1<<8),
+};
+
+static Lock pcicfglock;
+static Lock pcicfginitlock;
+static int pcicfgmode = -1;
+static int pcimaxbno = 7;
+static int pcimaxdno;
+static Pcidev* pciroot;
+static Pcidev* pcilist;
+static Pcidev* pcitail;
+static int nobios, nopcirouting;
+static BIOS32si* pcibiossi;
+
+static int pcicfgrw8raw(int, int, int, int);
+static int pcicfgrw16raw(int, int, int, int);
+static int pcicfgrw32raw(int, int, int, int);
+
+static int (*pcicfgrw8)(int, int, int, int) = pcicfgrw8raw;
+static int (*pcicfgrw16)(int, int, int, int) = pcicfgrw16raw;
+static int (*pcicfgrw32)(int, int, int, int) = pcicfgrw32raw;
+
+static char* bustypes[] = {
+ "CBUSI",
+ "CBUSII",
+ "EISA",
+ "FUTURE",
+ "INTERN",
+ "ISA",
+ "MBI",
+ "MBII",
+ "MCA",
+ "MPI",
+ "MPSA",
+ "NUBUS",
+ "PCI",
+ "PCMCIA",
+ "TC",
+ "VL",
+ "VME",
+ "XPRESS",
+};
+
+static int
+tbdffmt(Fmt* fmt)
+{
+ char *p;
+ int l, r;
+ uint type, tbdf;
+
+ if((p = malloc(READSTR)) == nil)
+ return fmtstrcpy(fmt, "(tbdfconv)");
+
+ switch(fmt->r){
+ case 'T':
+ tbdf = va_arg(fmt->args, int);
+ if(tbdf == BUSUNKNOWN)
+ snprint(p, READSTR, "unknown");
+ else{
+ type = BUSTYPE(tbdf);
+ if(type < nelem(bustypes))
+ l = snprint(p, READSTR, bustypes[type]);
+ else
+ l = snprint(p, READSTR, "%d", type);
+ snprint(p+l, READSTR-l, ".%d.%d.%d",
+ BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
+ }
+ break;
+
+ default:
+ snprint(p, READSTR, "(tbdfconv)");
+ break;
+ }
+ r = fmtstrcpy(fmt, p);
+ free(p);
+
+ return r;
+}
+
+ulong
+pcibarsize(Pcidev *p, int rno)
+{
+ ulong v, size;
+
+ v = pcicfgrw32(p->tbdf, rno, 0, 1);
+ pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
+ size = pcicfgrw32(p->tbdf, rno, 0, 1);
+ if(v & 1)
+ size |= 0xFFFF0000;
+ pcicfgrw32(p->tbdf, rno, v, 0);
+
+ return -(size & ~0x0F);
+}
+
+static int
+pcisizcmp(void *a, void *b)
+{
+ Pcisiz *aa, *bb;
+
+ aa = a;
+ bb = b;
+ return aa->siz - bb->siz;
+}
+
+static ulong
+pcimask(ulong v)
+{
+ ulong m;
+
+ m = BI2BY*sizeof(v);
+ for(m = 1<<(m-1); m != 0; m >>= 1) {
+ if(m & v)
+ break;
+ }
+
+ m--;
+ if((v & m) == 0)
+ return v;
+
+ v |= m;
+ return v+1;
+}
+
+static void
+pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
+{
+ Pcidev *p;
+ int ntb, i, size, rno, hole;
+ ulong v, mema, ioa, sioa, smema, base, limit;
+ Pcisiz *table, *tptr, *mtb, *itb;
+
+ if(!nobios)
+ return;
+
+ ioa = *pioa;
+ mema = *pmema;
+
+ DBG("pcibusmap wr=%d %T mem=%luX io=%luX\n",
+ wrreg, root->tbdf, mema, ioa);
+
+ ntb = 0;
+ for(p = root; p != nil; p = p->link)
+ ntb++;
+
+ ntb *= (PciCIS-PciBAR0)/4;
+ table = malloc(2*ntb*sizeof(Pcisiz));
+ itb = table;
+ mtb = table+ntb;
+
+ /*
+ * Build a table of sizes
+ */
+ for(p = root; p != nil; p = p->link) {
+ if(p->ccrb == 0x06) {
+ if(p->ccru != 0x04 || p->bridge == nil) {
+// DBG("pci: ignored bridge %T\n", p->tbdf);
+ continue;
+ }
+
+ sioa = ioa;
+ smema = mema;
+ pcibusmap(p->bridge, &smema, &sioa, 0);
+
+ hole = pcimask(smema-mema);
+ if(hole < (1<<20))
+ hole = 1<<20;
+ p->mema.size = hole;
+
+ hole = pcimask(sioa-ioa);
+ if(hole < (1<<12))
+ hole = 1<<12;
+
+ p->ioa.size = hole;
+
+ itb->dev = p;
+ itb->bar = -1;
+ itb->siz = p->ioa.size;
+ itb++;
+
+ mtb->dev = p;
+ mtb->bar = -1;
+ mtb->siz = p->mema.size;
+ mtb++;
+ continue;
+ }
+
+ for(i = 0; i <= 5; i++) {
+ rno = PciBAR0 + i*4;
+ v = pcicfgrw32(p->tbdf, rno, 0, 1);
+ size = pcibarsize(p, rno);
+ if(size == 0)
+ continue;
+
+ if(v & 1) {
+ itb->dev = p;
+ itb->bar = i;
+ itb->siz = size;
+ itb++;
+ }
+ else {
+ mtb->dev = p;
+ mtb->bar = i;
+ mtb->siz = size;
+ mtb++;
+ }
+
+ p->mem[i].size = size;
+ }
+ }
+
+ /*
+ * Sort both tables IO smallest first, Memory largest
+ */
+ qsort(table, itb-table, sizeof(Pcisiz), pcisizcmp);
+ tptr = table+ntb;
+ qsort(tptr, mtb-tptr, sizeof(Pcisiz), pcisizcmp);
+
+ /*
+ * Allocate IO address space on this bus
+ */
+ for(tptr = table; tptr < itb; tptr++) {
+ hole = tptr->siz;
+ if(tptr->bar == -1)
+ hole = 1<<12;
+ ioa = (ioa+hole-1) & ~(hole-1);
+
+ p = tptr->dev;
+ if(tptr->bar == -1)
+ p->ioa.bar = ioa;
+ else {
+ p->pcr |= IOen;
+ p->mem[tptr->bar].bar = ioa|1;
+ if(wrreg)
+ pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), ioa|1, 0);
+ }
+
+ ioa += tptr->siz;
+ }
+
+ /*
+ * Allocate Memory address space on this bus
+ */
+ for(tptr = table+ntb; tptr < mtb; tptr++) {
+ hole = tptr->siz;
+ if(tptr->bar == -1)
+ hole = 1<<20;
+ mema = (mema+hole-1) & ~(hole-1);
+
+ p = tptr->dev;
+ if(tptr->bar == -1)
+ p->mema.bar = mema;
+ else {
+ p->pcr |= MEMen;
+ p->mem[tptr->bar].bar = mema;
+ if(wrreg)
+ pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), mema, 0);
+ }
+ mema += tptr->siz;
+ }
+
+ *pmema = mema;
+ *pioa = ioa;
+ free(table);
+
+ if(wrreg == 0)
+ return;
+
+ /*
+ * Finally set all the bridge addresses & registers
+ */
+ for(p = root; p != nil; p = p->link) {
+ if(p->bridge == nil) {
+ pcicfgrw8(p->tbdf, PciLTR, 64, 0);
+
+ p->pcr |= MASen;
+ pcicfgrw16(p->tbdf, PciPCR, p->pcr, 0);
+ continue;
+ }
+
+ base = p->ioa.bar;
+ limit = base+p->ioa.size-1;
+ v = pcicfgrw32(p->tbdf, PciIBR, 0, 1);
+ v = (v&0xFFFF0000)|(limit & 0xF000)|((base & 0xF000)>>8);
+ pcicfgrw32(p->tbdf, PciIBR, v, 0);
+ v = (limit & 0xFFFF0000)|(base>>16);
+ pcicfgrw32(p->tbdf, PciIUBR, v, 0);
+
+ base = p->mema.bar;
+ limit = base+p->mema.size-1;
+ v = (limit & 0xFFF00000)|((base & 0xFFF00000)>>16);
+ pcicfgrw32(p->tbdf, PciMBR, v, 0);
+
+ /*
+ * Disable memory prefetch
+ */
+ pcicfgrw32(p->tbdf, PciPMBR, 0x0000FFFF, 0);
+ pcicfgrw8(p->tbdf, PciLTR, 64, 0);
+
+ /*
+ * Enable the bridge
+ */
+ p->pcr |= IOen|MEMen|MASen;
+ pcicfgrw32(p->tbdf, PciPCR, 0xFFFF0000|p->pcr , 0);
+
+ sioa = p->ioa.bar;
+ smema = p->mema.bar;
+ pcibusmap(p->bridge, &smema, &sioa, 1);
+ }
+}
+
+static int
+pcilscan(int bno, Pcidev** list)
+{
+ Pcidev *p, *head, *tail;
+ int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
+
+ maxubn = bno;
+ head = nil;
+ tail = nil;
+ for(dno = 0; dno <= pcimaxdno; dno++){
+ maxfno = 0;
+ for(fno = 0; fno <= maxfno; fno++){
+ /*
+ * For this possible device, form the
+ * bus+device+function triplet needed to address it
+ * and try to read the vendor and device ID.
+ * If successful, allocate a device struct and
+ * start to fill it in with some useful information
+ * from the device's configuration space.
+ */
+ tbdf = MKBUS(BusPCI, bno, dno, fno);
+ l = pcicfgrw32(tbdf, PciVID, 0, 1);
+ if(l == 0xFFFFFFFF || l == 0)
+ continue;
+ p = malloc(sizeof(*p));
+ p->tbdf = tbdf;
+ p->vid = l;
+ p->did = l>>16;
+
+ if(pcilist != nil)
+ pcitail->list = p;
+ else
+ pcilist = p;
+ pcitail = p;
+
+ p->pcr = pcicfgr16(p, PciPCR);
+ p->rid = pcicfgr8(p, PciRID);
+ p->ccrp = pcicfgr8(p, PciCCRp);
+ p->ccru = pcicfgr8(p, PciCCRu);
+ p->ccrb = pcicfgr8(p, PciCCRb);
+ p->cls = pcicfgr8(p, PciCLS);
+ p->ltr = pcicfgr8(p, PciLTR);
+
+ p->intl = pcicfgr8(p, PciINTL);
+
+ /*
+ * If the device is a multi-function device adjust the
+ * loop count so all possible functions are checked.
+ */
+ hdt = pcicfgr8(p, PciHDT);
+ if(hdt & 0x80)
+ maxfno = MaxFNO;
+
+ /*
+ * If appropriate, read the base address registers
+ * and work out the sizes.
+ */
+ switch(p->ccrb) {
+ case 0x01: /* mass storage controller */
+ case 0x02: /* network controller */
+ case 0x03: /* display controller */
+ case 0x04: /* multimedia device */
+ case 0x07: /* simple comm. controllers */
+ case 0x08: /* base system peripherals */
+ case 0x09: /* input devices */
+ case 0x0A: /* docking stations */
+ case 0x0B: /* processors */
+ case 0x0C: /* serial bus controllers */
+ if((hdt & 0x7F) != 0)
+ break;
+ rno = PciBAR0 - 4;
+ for(i = 0; i < nelem(p->mem); i++) {
+ rno += 4;
+ p->mem[i].bar = pcicfgr32(p, rno);
+ p->mem[i].size = pcibarsize(p, rno);
+ }
+ break;
+
+ case 0x00:
+ case 0x05: /* memory controller */
+ case 0x06: /* bridge device */
+ default:
+ break;
+ }
+
+ if(head != nil)
+ tail->link = p;
+ else
+ head = p;
+ tail = p;
+ }
+ }
+
+ *list = head;
+ for(p = head; p != nil; p = p->link){
+ /*
+ * Find PCI-PCI bridges and recursively descend the tree.
+ */
+ if(p->ccrb != 0x06 || p->ccru != 0x04)
+ continue;
+
+ /*
+ * If the secondary or subordinate bus number is not
+ * initialised try to do what the PCI BIOS should have
+ * done and fill in the numbers as the tree is descended.
+ * On the way down the subordinate bus number is set to
+ * the maximum as it's not known how many buses are behind
+ * this one; the final value is set on the way back up.
+ */
+ sbn = pcicfgr8(p, PciSBN);
+ ubn = pcicfgr8(p, PciUBN);
+
+ if(sbn == 0 || ubn == 0 || nobios) {
+ sbn = maxubn+1;
+ /*
+ * Make sure memory, I/O and master enables are
+ * off, set the primary, secondary and subordinate
+ * bus numbers and clear the secondary status before
+ * attempting to scan the secondary bus.
+ *
+ * Initialisation of the bridge should be done here.
+ */
+ pcicfgw32(p, PciPCR, 0xFFFF0000);
+ l = (MaxUBN<<16)|(sbn<<8)|bno;
+ pcicfgw32(p, PciPBN, l);
+ pcicfgw16(p, PciSPSR, 0xFFFF);
+ maxubn = pcilscan(sbn, &p->bridge);
+ l = (maxubn<<16)|(sbn<<8)|bno;
+
+ pcicfgw32(p, PciPBN, l);
+ }
+ else {
+ if(ubn > maxubn)
+ maxubn = ubn;
+ pcilscan(sbn, &p->bridge);
+ }
+ }
+
+ return maxubn;
+}
+
+int
+pciscan(int bno, Pcidev **list)
+{
+ int ubn;
+
+ lock(&pcicfginitlock);
+ ubn = pcilscan(bno, list);
+ unlock(&pcicfginitlock);
+ return ubn;
+}
+
+static uchar
+pIIxget(Pcidev *router, uchar link)
+{
+ uchar pirq;
+
+ /* link should be 0x60, 0x61, 0x62, 0x63 */
+ pirq = pcicfgr8(router, link);
+ return (pirq < 16)? pirq: 0;
+}
+
+static void
+pIIxset(Pcidev *router, uchar link, uchar irq)
+{
+ pcicfgw8(router, link, irq);
+}
+
+static uchar
+viaget(Pcidev *router, uchar link)
+{
+ uchar pirq;
+
+ /* link should be 1, 2, 3, 5 */
+ pirq = (link < 6)? pcicfgr8(router, 0x55 + (link>>1)): 0;
+
+ return (link & 1)? (pirq >> 4): (pirq & 15);
+}
+
+static void
+viaset(Pcidev *router, uchar link, uchar irq)
+{
+ uchar pirq;
+
+ pirq = pcicfgr8(router, 0x55 + (link >> 1));
+ pirq &= (link & 1)? 0x0f: 0xf0;
+ pirq |= (link & 1)? (irq << 4): (irq & 15);
+ pcicfgw8(router, 0x55 + (link>>1), pirq);
+}
+
+static uchar
+optiget(Pcidev *router, uchar link)
+{
+ uchar pirq = 0;
+
+ /* link should be 0x02, 0x12, 0x22, 0x32 */
+ if ((link & 0xcf) == 0x02)
+ pirq = pcicfgr8(router, 0xb8 + (link >> 5));
+ return (link & 0x10)? (pirq >> 4): (pirq & 15);
+}
+
+static void
+optiset(Pcidev *router, uchar link, uchar irq)
+{
+ uchar pirq;
+
+ pirq = pcicfgr8(router, 0xb8 + (link >> 5));
+ pirq &= (link & 0x10)? 0x0f : 0xf0;
+ pirq |= (link & 0x10)? (irq << 4): (irq & 15);
+ pcicfgw8(router, 0xb8 + (link >> 5), pirq);
+}
+
+static uchar
+aliget(Pcidev *router, uchar link)
+{
+ /* No, you're not dreaming */
+ static const uchar map[] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+ uchar pirq;
+
+ /* link should be 0x01..0x08 */
+ pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
+ return (link & 1)? map[pirq&15]: map[pirq>>4];
+}
+
+static void
+aliset(Pcidev *router, uchar link, uchar irq)
+{
+ /* Inverse of map in aliget */
+ static const uchar map[] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
+ uchar pirq;
+
+ pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
+ pirq &= (link & 1)? 0x0f: 0xf0;
+ pirq |= (link & 1)? (map[irq] << 4): (map[irq] & 15);
+ pcicfgw8(router, 0x48 + ((link-1)>>1), pirq);
+}
+
+static uchar
+cyrixget(Pcidev *router, uchar link)
+{
+ uchar pirq;
+
+ /* link should be 1, 2, 3, 4 */
+ pirq = pcicfgr8(router, 0x5c + ((link-1)>>1));
+ return ((link & 1)? pirq >> 4: pirq & 15);
+}
+
+static void
+cyrixset(Pcidev *router, uchar link, uchar irq)
+{
+ uchar pirq;
+
+ pirq = pcicfgr8(router, 0x5c + (link>>1));
+ pirq &= (link & 1)? 0x0f: 0xf0;
+ pirq |= (link & 1)? (irq << 4): (irq & 15);
+ pcicfgw8(router, 0x5c + (link>>1), pirq);
+}
+
+typedef struct Bridge Bridge;
+struct Bridge
+{
+ ushort vid;
+ ushort did;
+ uchar (*get)(Pcidev *, uchar);
+ void (*set)(Pcidev *, uchar, uchar);
+};
+
+static Bridge southbridges[] = {
+ { 0x8086, 0x122e, pIIxget, pIIxset }, /* Intel 82371FB */
+ { 0x8086, 0x1234, pIIxget, pIIxset }, /* Intel 82371MX */
+ { 0x8086, 0x7000, pIIxget, pIIxset }, /* Intel 82371SB */
+ { 0x8086, 0x7110, pIIxget, pIIxset }, /* Intel 82371AB */
+ { 0x8086, 0x7198, pIIxget, pIIxset }, /* Intel 82443MX (fn 1) */
+ { 0x8086, 0x2410, pIIxget, pIIxset }, /* Intel 82801AA */
+ { 0x8086, 0x2420, pIIxget, pIIxset }, /* Intel 82801AB */
+ { 0x8086, 0x2440, pIIxget, pIIxset }, /* Intel 82801BA */
+ { 0x8086, 0x244c, pIIxget, pIIxset }, /* Intel 82801BAM */
+ { 0x8086, 0x2480, pIIxget, pIIxset }, /* Intel 82801CA */
+ { 0x8086, 0x248c, pIIxget, pIIxset }, /* Intel 82801CAM */
+ { 0x8086, 0x24c0, pIIxget, pIIxset }, /* Intel 82801DBL */
+ { 0x8086, 0x24cc, pIIxget, pIIxset }, /* Intel 82801DBM */
+ { 0x8086, 0x24d0, pIIxget, pIIxset }, /* Intel 82801EB */
+ { 0x8086, 0x25a1, pIIxget, pIIxset }, /* Intel 6300ESB */
+ { 0x8086, 0x2640, pIIxget, pIIxset }, /* Intel 82801FB */
+ { 0x8086, 0x2641, pIIxget, pIIxset }, /* Intel 82801FBM */
+ { 0x8086, 0x27b8, pIIxget, pIIxset }, /* Intel 82801GB */
+ { 0x8086, 0x27b9, pIIxget, pIIxset }, /* Intel 82801GBM */
+ { 0x8086, 0x2916, pIIxget, pIIxset }, /* Intel 82801? */
+ { 0x1106, 0x0586, viaget, viaset }, /* Viatech 82C586 */
+ { 0x1106, 0x0596, viaget, viaset }, /* Viatech 82C596 */
+ { 0x1106, 0x0686, viaget, viaset }, /* Viatech 82C686 */
+ { 0x1106, 0x3227, viaget, viaset }, /* Viatech VT8237 */
+ { 0x1045, 0xc700, optiget, optiset }, /* Opti 82C700 */
+ { 0x10b9, 0x1533, aliget, aliset }, /* Al M1533 */
+ { 0x1039, 0x0008, pIIxget, pIIxset }, /* SI 503 */
+ { 0x1039, 0x0496, pIIxget, pIIxset }, /* SI 496 */
+ { 0x1078, 0x0100, cyrixget, cyrixset }, /* Cyrix 5530 Legacy */
+
+ { 0x1022, 0x746B, nil, nil }, /* AMD 8111 */
+ { 0x10DE, 0x00D1, nil, nil }, /* NVIDIA nForce 3 */
+ { 0x10DE, 0x00E0, nil, nil }, /* NVIDIA nForce 3 250 Series */
+ { 0x10DE, 0x00E1, nil, nil }, /* NVIDIA nForce 3 250 Series */
+ { 0x1166, 0x0200, nil, nil }, /* ServerWorks ServerSet III LE */
+ { 0x1002, 0x4377, nil, nil }, /* ATI Radeon Xpress 200M */
+ { 0x1002, 0x4372, nil, nil }, /* ATI SB400 */
+};
+
+typedef struct Slot Slot;
+struct Slot {
+ uchar bus; /* Pci bus number */
+ uchar dev; /* Pci device number */
+ uchar maps[12]; /* Avoid structs! Link and mask. */
+ uchar slot; /* Add-in/built-in slot */
+ uchar reserved;
+};
+
+typedef struct Router Router;
+struct Router {
+ uchar signature[4]; /* Routing table signature */
+ uchar version[2]; /* Version number */
+ uchar size[2]; /* Total table size */
+ uchar bus; /* Interrupt router bus number */
+ uchar devfn; /* Router's devfunc */
+ uchar pciirqs[2]; /* Exclusive PCI irqs */
+ uchar compat[4]; /* Compatible PCI interrupt router */
+ uchar miniport[4]; /* Miniport data */
+ uchar reserved[11];
+ uchar checksum;
+};
+
+static ushort pciirqs; /* Exclusive PCI irqs */
+static Bridge *southbridge; /* Which southbridge to use. */
+
+static void
+pcirouting(void)
+{
+ Slot *e;
+ Router *r;
+ int size, i, fn, tbdf;
+ Pcidev *sbpci, *pci;
+ uchar *p, pin, irq, link, *map;
+
+ /* Search for PCI interrupt routing table in BIOS */
+ for(p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16)
+ if(p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R')
+ break;
+
+ if(p >= (uchar *)KADDR(0xfffff))
+ return;
+
+ r = (Router *)p;
+
+ // print("PCI interrupt routing table version %d.%d at %.6uX\n",
+ // r->version[0], r->version[1], (ulong)r & 0xfffff);
+
+ tbdf = (BusPCI << 24)|(r->bus << 16)|(r->devfn << 8);
+ sbpci = pcimatchtbdf(tbdf);
+ if(sbpci == nil) {
+ print("pcirouting: Cannot find south bridge %T\n", tbdf);
+ return;
+ }
+
+ for(i = 0; i != nelem(southbridges); i++)
+ if(sbpci->vid == southbridges[i].vid && sbpci->did == southbridges[i].did)
+ break;
+
+ if(i == nelem(southbridges)) {
+ print("pcirouting: ignoring south bridge %T %.4uX/%.4uX\n", tbdf, sbpci->vid, sbpci->did);
+ return;
+ }
+ southbridge = &southbridges[i];
+ if(southbridge->get == nil || southbridge->set == nil)
+ return;
+
+ pciirqs = (r->pciirqs[1] << 8)|r->pciirqs[0];
+
+ size = (r->size[1] << 8)|r->size[0];
+ for(e = (Slot *)&r[1]; (uchar *)e < p + size; e++) {
+ if (0) {
+ print("%.2uX/%.2uX %.2uX: ", e->bus, e->dev, e->slot);
+ for (i = 0; i != 4; i++) {
+ uchar *m = &e->maps[i * 3];
+ print("[%d] %.2uX %.4uX ",
+ i, m[0], (m[2] << 8)|m[1]);
+ }
+ print("\n");
+ }
+ for(fn = 0; fn != 8; fn++) {
+ tbdf = (BusPCI << 24)|(e->bus << 16)|((e->dev | fn) << 8);
+ pci = pcimatchtbdf(tbdf);
+ if(pci == nil)
+ continue;
+ pin = pcicfgr8(pci, PciINTP);
+ if(pin == 0 || pin == 0xff)
+ continue;
+
+ map = &e->maps[(pin - 1) * 3];
+ link = map[0];
+ irq = southbridge->get(sbpci, link);
+ if(irq == 0 || irq == pci->intl)
+ continue;
+ if(pci->intl != 0 && pci->intl != 0xFF) {
+ print("pcirouting: BIOS workaround: %T at pin %d link %d irq %d -> %d\n",
+ tbdf, pin, link, irq, pci->intl);
+ southbridge->set(sbpci, link, pci->intl);
+ continue;
+ }
+ print("pcirouting: %T at pin %d link %d irq %d\n", tbdf, pin, link, irq);
+ pcicfgw8(pci, PciINTL, irq);
+ pci->intl = irq;
+ }
+ }
+}
+
+static void pcireservemem(void);
+
+static int
+pcicfgrw8bios(int tbdf, int rno, int data, int read)
+{
+ BIOS32ci ci;
+
+ if(pcibiossi == nil)
+ return -1;
+
+ memset(&ci, 0, sizeof(BIOS32ci));
+ ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf);
+ ci.edi = rno;
+ if(read){
+ ci.eax = 0xB108;
+ if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
+ return ci.ecx & 0xFF;
+ }
+ else{
+ ci.eax = 0xB10B;
+ ci.ecx = data & 0xFF;
+ if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
+ return 0;
+ }
+
+ return -1;
+}
+
+static int
+pcicfgrw16bios(int tbdf, int rno, int data, int read)
+{
+ BIOS32ci ci;
+
+ if(pcibiossi == nil)
+ return -1;
+
+ memset(&ci, 0, sizeof(BIOS32ci));
+ ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf);
+ ci.edi = rno;
+ if(read){
+ ci.eax = 0xB109;
+ if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
+ return ci.ecx & 0xFFFF;
+ }
+ else{
+ ci.eax = 0xB10C;
+ ci.ecx = data & 0xFFFF;
+ if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
+ return 0;
+ }
+
+ return -1;
+}
+
+static int
+pcicfgrw32bios(int tbdf, int rno, int data, int read)
+{
+ BIOS32ci ci;
+
+ if(pcibiossi == nil)
+ return -1;
+
+ memset(&ci, 0, sizeof(BIOS32ci));
+ ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf);
+ ci.edi = rno;
+ if(read){
+ ci.eax = 0xB10A;
+ if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
+ return ci.ecx;
+ }
+ else{
+ ci.eax = 0xB10D;
+ ci.ecx = data;
+ if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
+ return 0;
+ }
+
+ return -1;
+}
+
+static BIOS32si*
+pcibiosinit(void)
+{
+ BIOS32ci ci;
+ BIOS32si *si;
+
+ if((si = bios32open("$PCI")) == nil)
+ return nil;
+
+ memset(&ci, 0, sizeof(BIOS32ci));
+ ci.eax = 0xB101;
+ if(bios32ci(si, &ci) || ci.edx != ((' '<<24)|('I'<<16)|('C'<<8)|'P')){
+ free(si);
+ return nil;
+ }
+ if(ci.eax & 0x01)
+ pcimaxdno = 31;
+ else
+ pcimaxdno = 15;
+ pcimaxbno = ci.ecx & 0xff;
+
+ return si;
+}
+
+void
+pcibussize(Pcidev *root, ulong *msize, ulong *iosize)
+{
+ *msize = 0;
+ *iosize = 0;
+ pcibusmap(root, msize, iosize, 0);
+}
+
+static void
+pcicfginit(void)
+{
+ char *p;
+ Pcidev **list;
+ ulong mema, ioa;
+ int bno, n, pcibios;
+
+ lock(&pcicfginitlock);
+ if(pcicfgmode != -1)
+ goto out;
+
+ pcibios = 0;
+ if(getconf("*nobios"))
+ nobios = 1;
+ else if(getconf("*pcibios"))
+ pcibios = 1;
+ if(getconf("*nopcirouting"))
+ nopcirouting = 1;
+
+ /*
+ * Try to determine which PCI configuration mode is implemented.
+ * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
+ * a DWORD at 0xCF8 and another at 0xCFC and will pass through
+ * any non-DWORD accesses as normal I/O cycles. There shouldn't be
+ * a device behind these addresses so if Mode1 accesses fail try
+ * for Mode2 (Mode2 is deprecated).
+ */
+ if(!pcibios){
+ /*
+ * Bits [30:24] of PciADDR must be 0,
+ * according to the spec.
+ */
+ n = inl(PciADDR);
+ if(!(n & 0x7F000000)){
+ outl(PciADDR, 0x80000000);
+ outb(PciADDR+3, 0);
+ if(inl(PciADDR) & 0x80000000){
+ pcicfgmode = 1;
+ pcimaxdno = 31;
+ }
+ }
+ outl(PciADDR, n);
+
+ if(pcicfgmode < 0){
+ /*
+ * The 'key' part of PciCSE should be 0.
+ */
+ n = inb(PciCSE);
+ if(!(n & 0xF0)){
+ outb(PciCSE, 0x0E);
+ if(inb(PciCSE) == 0x0E){
+ pcicfgmode = 2;
+ pcimaxdno = 15;
+ }
+ }
+ outb(PciCSE, n);
+ }
+ }
+
+ if(pcicfgmode < 0 || pcibios) {
+ if((pcibiossi = pcibiosinit()) == nil)
+ goto out;
+ pcicfgrw8 = pcicfgrw8bios;
+ pcicfgrw16 = pcicfgrw16bios;
+ pcicfgrw32 = pcicfgrw32bios;
+ pcicfgmode = 3;
+ }
+
+ fmtinstall('T', tbdffmt);
+
+ if(p = getconf("*pcimaxbno")){
+ n = strtoul(p, 0, 0);
+ if(n < pcimaxbno)
+ pcimaxbno = n;
+ }
+ if(p = getconf("*pcimaxdno")){
+ n = strtoul(p, 0, 0);
+ if(n < pcimaxdno)
+ pcimaxdno = n;
+ }
+
+ list = &pciroot;
+ for(bno = 0; bno <= pcimaxbno; bno++) {
+ int sbno = bno;
+ bno = pcilscan(bno, list);
+
+ while(*list)
+ list = &(*list)->link;
+
+ if (sbno == 0) {
+ Pcidev *pci;
+
+ /*
+ * If we have found a PCI-to-Cardbus bridge, make sure
+ * it has no valid mappings anymore.
+ */
+ for(pci = pciroot; pci != nil; pci = pci->link){
+ if (pci->ccrb == 6 && pci->ccru == 7) {
+ ushort bcr;
+
+ /* reset the cardbus */
+ bcr = pcicfgr16(pci, PciBCR);
+ pcicfgw16(pci, PciBCR, 0x40 | bcr);
+ delay(50);
+ }
+ }
+ }
+ }
+
+ if(pciroot == nil)
+ goto out;
+
+ if(nobios) {
+ /*
+ * Work out how big the top bus is
+ */
+ pcibussize(pciroot, &mema, &ioa);
+
+ /*
+ * Align the windows and map it
+ */
+ ioa = 0x1000;
+ mema = 0x90000000;
+
+ pcilog("Mask sizes: mem=%lux io=%lux\n", mema, ioa);
+
+ pcibusmap(pciroot, &mema, &ioa, 1);
+ DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa);
+
+ unlock(&pcicfginitlock);
+ return;
+ }
+
+ if (!nopcirouting)
+ 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
+pcicfgrw8raw(int tbdf, int rno, int data, int read)
+{
+ int o, type, x;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(BUSBNO(tbdf))
+ type = 0x01;
+ else
+ type = 0x00;
+ x = -1;
+ if(BUSDNO(tbdf) > pcimaxdno)
+ return x;
+
+ lock(&pcicfglock);
+ switch(pcicfgmode){
+
+ case 1:
+ o = rno & 0x03;
+ rno &= ~0x03;
+ outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+ if(read)
+ x = inb(PciDATA+o);
+ else
+ outb(PciDATA+o, data);
+ outl(PciADDR, 0);
+ break;
+
+ case 2:
+ outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
+ outb(PciFORWARD, BUSBNO(tbdf));
+ if(read)
+ x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
+ else
+ outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
+ outb(PciCSE, 0);
+ break;
+ }
+ unlock(&pcicfglock);
+
+ return x;
+}
+
+int
+pcicfgr8(Pcidev* pcidev, int rno)
+{
+ return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw8(Pcidev* pcidev, int rno, int data)
+{
+ pcicfgrw8(pcidev->tbdf, rno, data, 0);
+}
+
+static int
+pcicfgrw16raw(int tbdf, int rno, int data, int read)
+{
+ int o, type, x;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(BUSBNO(tbdf))
+ type = 0x01;
+ else
+ type = 0x00;
+ x = -1;
+ if(BUSDNO(tbdf) > pcimaxdno)
+ return x;
+
+ lock(&pcicfglock);
+ switch(pcicfgmode){
+
+ case 1:
+ o = rno & 0x02;
+ rno &= ~0x03;
+ outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+ if(read)
+ x = ins(PciDATA+o);
+ else
+ outs(PciDATA+o, data);
+ outl(PciADDR, 0);
+ break;
+
+ case 2:
+ outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
+ outb(PciFORWARD, BUSBNO(tbdf));
+ if(read)
+ x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
+ else
+ outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
+ outb(PciCSE, 0);
+ break;
+ }
+ unlock(&pcicfglock);
+
+ return x;
+}
+
+int
+pcicfgr16(Pcidev* pcidev, int rno)
+{
+ return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw16(Pcidev* pcidev, int rno, int data)
+{
+ pcicfgrw16(pcidev->tbdf, rno, data, 0);
+}
+
+static int
+pcicfgrw32raw(int tbdf, int rno, int data, int read)
+{
+ int type, x;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(BUSBNO(tbdf))
+ type = 0x01;
+ else
+ type = 0x00;
+ x = -1;
+ if(BUSDNO(tbdf) > pcimaxdno)
+ return x;
+
+ lock(&pcicfglock);
+ switch(pcicfgmode){
+
+ case 1:
+ rno &= ~0x03;
+ outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+ if(read)
+ x = inl(PciDATA);
+ else
+ outl(PciDATA, data);
+ outl(PciADDR, 0);
+ break;
+
+ case 2:
+ outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
+ outb(PciFORWARD, BUSBNO(tbdf));
+ if(read)
+ x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
+ else
+ outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
+ outb(PciCSE, 0);
+ break;
+ }
+ unlock(&pcicfglock);
+
+ return x;
+}
+
+int
+pcicfgr32(Pcidev* pcidev, int rno)
+{
+ return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw32(Pcidev* pcidev, int rno, int data)
+{
+ pcicfgrw32(pcidev->tbdf, rno, data, 0);
+}
+
+Pcidev*
+pcimatch(Pcidev* prev, int vid, int did)
+{
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(prev == nil)
+ prev = pcilist;
+ else
+ prev = prev->list;
+
+ while(prev != nil){
+ if((vid == 0 || prev->vid == vid)
+ && (did == 0 || prev->did == did))
+ break;
+ prev = prev->list;
+ }
+ return prev;
+}
+
+Pcidev*
+pcimatchtbdf(int tbdf)
+{
+ Pcidev *pcidev;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
+ if(pcidev->tbdf == tbdf)
+ break;
+ }
+ return pcidev;
+}
+
+uchar
+pciipin(Pcidev *pci, uchar pin)
+{
+ if (pci == nil)
+ pci = pcilist;
+
+ while (pci) {
+ uchar intl;
+
+ if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)
+ return pci->intl;
+
+ if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)
+ return intl;
+
+ pci = pci->list;
+ }
+ return 0;
+}
+
+static void
+pcilhinv(Pcidev* p)
+{
+ int i;
+ Pcidev *t;
+
+ if(p == nil) {
+ putstrn(PCICONS.output, PCICONS.ptr);
+ p = pciroot;
+ print("bus dev type vid did intl memory\n");
+ }
+ for(t = p; t != nil; t = t->link) {
+ print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d ",
+ BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
+ t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
+
+ for(i = 0; i < nelem(p->mem); i++) {
+ if(t->mem[i].size == 0)
+ continue;
+ print("%d:%.8lux %d ", i,
+ t->mem[i].bar, t->mem[i].size);
+ }
+ if(t->ioa.bar || t->ioa.size)
+ print("ioa:%.8lux %d ", t->ioa.bar, t->ioa.size);
+ if(t->mema.bar || t->mema.size)
+ print("mema:%.8lux %d ", t->mema.bar, t->mema.size);
+ if(t->bridge)
+ print("->%d", BUSBNO(t->bridge->tbdf));
+ print("\n");
+ }
+ while(p != nil) {
+ if(p->bridge != nil)
+ pcilhinv(p->bridge);
+ p = p->link;
+ }
+}
+
+void
+pcihinv(Pcidev* p)
+{
+ if(pcicfgmode == -1)
+ pcicfginit();
+ lock(&pcicfginitlock);
+ pcilhinv(p);
+ unlock(&pcicfginitlock);
+}
+
+void
+pcireset(void)
+{
+ Pcidev *p;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ for(p = pcilist; p != nil; p = p->list) {
+ /* don't mess with the bridges */
+ if(p->ccrb == 0x06)
+ continue;
+ pciclrbme(p);
+ }
+}
+
+void
+pcisetioe(Pcidev* p)
+{
+ p->pcr |= IOen;
+ pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pciclrioe(Pcidev* p)
+{
+ p->pcr &= ~IOen;
+ pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pcisetbme(Pcidev* p)
+{
+ p->pcr |= MASen;
+ pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pciclrbme(Pcidev* p)
+{
+ p->pcr &= ~MASen;
+ pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pcisetmwi(Pcidev* p)
+{
+ p->pcr |= MemWrInv;
+ pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pciclrmwi(Pcidev* p)
+{
+ p->pcr &= ~MemWrInv;
+ pcicfgw16(p, PciPCR, p->pcr);
+}
+
+static int
+pcigetpmrb(Pcidev* p)
+{
+ int ptr;
+
+ if(p->pmrb != 0)
+ return p->pmrb;
+ p->pmrb = -1;
+
+ /*
+ * If there are no extended capabilities implemented,
+ * (bit 4 in the status register) assume there's no standard
+ * power management method.
+ * Find the capabilities pointer based on PCI header type.
+ */
+ if(!(pcicfgr16(p, PciPSR) & 0x0010))
+ return -1;
+ switch(pcicfgr8(p, PciHDT)){
+ default:
+ return -1;
+ case 0: /* all other */
+ case 1: /* PCI to PCI bridge */
+ ptr = 0x34;
+ break;
+ case 2: /* CardBus bridge */
+ ptr = 0x14;
+ break;
+ }
+ ptr = pcicfgr32(p, ptr);
+
+ while(ptr != 0){
+ /*
+ * Check for validity.
+ * Can't be in standard header and must be double
+ * word aligned.
+ */
+ if(ptr < 0x40 || (ptr & ~0xFC))
+ return -1;
+ if(pcicfgr8(p, ptr) == 0x01){
+ p->pmrb = ptr;
+ return ptr;
+ }
+
+ ptr = pcicfgr8(p, ptr+1);
+ }
+
+ return -1;
+}
+
+int
+pcigetpms(Pcidev* p)
+{
+ int pmcsr, ptr;
+
+ if((ptr = pcigetpmrb(p)) == -1)
+ return -1;
+
+ /*
+ * Power Management Register Block:
+ * offset 0: Capability ID
+ * 1: next item pointer
+ * 2: capabilities
+ * 4: control/status
+ * 6: bridge support extensions
+ * 7: data
+ */
+ pmcsr = pcicfgr16(p, ptr+4);
+
+ return pmcsr & 0x0003;
+}
+
+int
+pcisetpms(Pcidev* p, int state)
+{
+ int ostate, pmc, pmcsr, ptr;
+
+ if((ptr = pcigetpmrb(p)) == -1)
+ return -1;
+
+ pmc = pcicfgr16(p, ptr+2);
+ pmcsr = pcicfgr16(p, ptr+4);
+ ostate = pmcsr & 0x0003;
+ pmcsr &= ~0x0003;
+
+ switch(state){
+ default:
+ return -1;
+ case 0:
+ break;
+ case 1:
+ if(!(pmc & 0x0200))
+ return -1;
+ break;
+ case 2:
+ if(!(pmc & 0x0400))
+ return -1;
+ break;
+ case 3:
+ break;
+ }
+ pmcsr |= state;
+ pcicfgw16(p, ptr+4, pmcsr);
+
+ return ostate;
+}
diff --git a/sys/src/9/pc/pcmciamodem.c b/sys/src/9/pc/pcmciamodem.c
new file mode 100755
index 000000000..ebeb1cea4
--- /dev/null
+++ b/sys/src/9/pc/pcmciamodem.c
@@ -0,0 +1,76 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+/*
+ * PCMCIA modem.
+ * By default, this will set it up with the port and irq of
+ * COM2 unless a serialx=type=com line is found in plan9.ini.
+ * The assumption is that a laptop with a pcmcia will have only
+ * one com port.
+ */
+
+enum {
+ Maxcard= 8,
+};
+
+static char* modems[] = {
+ "IBM 33.6 Data/Fax/Voice Modem",
+ "CM-56G", /* Xircom CreditCard Modem 56 - GlobalACCESS */
+ "KeepInTouch",
+ "CEM56",
+ "MONTANA V.34 FAX/MODEM", /* Motorola */
+ "REM10",
+ "GSM/GPRS",
+ "AirCard 555",
+ "Gold Card Global", /* Psion V90 Gold card */
+ "Merlin UMTS Modem", /* Novatel card */
+ 0,
+};
+
+void
+pcmciamodemlink(void)
+{
+ ISAConf isa;
+ int i, j, slot, com2used, usingcom2;
+
+ i = 0;
+ com2used = 0;
+ for(j = 0; modems[j]; j++){
+ memset(&isa, 0, sizeof(isa));
+
+ /* look for a configuration line */
+ for(; i < Maxcard; i++){
+ if(isaconfig("serial", i, &isa))
+ if(cistrcmp(isa.type, "com") == 0)
+ break;
+ memset(&isa, 0, sizeof(isa));
+ }
+
+ usingcom2 = 0;
+ if (isa.irq == 0 && isa.port == 0) {
+ if (com2used == 0) {
+ /* default is COM2 */
+ isa.irq = 3;
+ isa.port = 0x2F8;
+ usingcom2 = 1;
+ } else
+ break;
+ }
+ slot = pcmspecial(modems[j], &isa);
+ if(slot >= 0){
+ if(usingcom2)
+ com2used = 1;
+ if(ioalloc(isa.port, 8, 0, modems[j]) < 0)
+ print("%s port %lux already in use\n",
+ modems[j], isa.port);
+ print("%s in pcmcia slot %d port 0x%lux irq %d\n",
+ modems[j], slot, isa.port, isa.irq);
+ }
+ }
+}
diff --git a/sys/src/9/pc/pcmkfile b/sys/src/9/pc/pcmkfile
new file mode 100755
index 000000000..c8db9416e
--- /dev/null
+++ b/sys/src/9/pc/pcmkfile
@@ -0,0 +1,3 @@
+PCFILES=`{../port/mkfilelist ../pc}
+^($PCFILES)\.$O:R: '../pc/\1.c'
+ $CC $CFLAGS -.I. ../pc/$stem1.c
diff --git a/sys/src/9/pc/piix4smbus.c b/sys/src/9/pc/piix4smbus.c
new file mode 100755
index 000000000..b05bb8f25
--- /dev/null
+++ b/sys/src/9/pc/piix4smbus.c
@@ -0,0 +1,213 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ * SMBus support for the PIIX4
+ */
+enum
+{
+ IntelVendID= 0x8086,
+ Piix4PMID= 0x7113, /* PIIX4 power management function */
+
+ /* SMBus configuration registers (function 3) */
+ SMBbase= 0x90, /* 4 byte base address (bit 0 == 1, bit 3:1 == 0) */
+ SMBconfig= 0xd2,
+ SMBintrselect= (7<<1),
+ SMIenable= (0<<1), /* interrupts sent to SMI# */
+ IRQ9enable= (4<<1), /* interrupts sent to IRQ9 */
+ SMBenable= (1<<0), /* 1 enables */
+
+ /* SMBus IO space registers */
+ Hoststatus= 0x0, /* (writing 1 bits reset the interrupt bits) */
+ Failed= (1<<4), /* transaction terminated by KILL */
+ Bus_error= (1<<3), /* transaction collision */
+ Dev_error= (1<<2), /* device error interrupt */
+ Host_complete= (1<<1), /* host command completion interrupt */
+ Host_busy= (1<<0), /* */
+ Slavestatus= 0x1, /* (writing 1 bits reset) */
+ Alert_sts= (1<<5), /* someone asserted SMBALERT# */
+ Shdw2_sts= (1<<4), /* slave accessed shadow 2 port */
+ Shdw1_sts= (1<<3), /* slave accessed shadow 1 port */
+ Slv_sts= (1<<2), /* slave accessed shadow 1 port */
+ Slv_bsy= (1<<0),
+ Hostcontrol= 0x2,
+ Start= (1<<6), /* start execution */
+ Cmd_prot= (7<<2), /* command protocol mask */
+ Quick= (0<<2), /* address only */
+ Byte= (1<<2), /* address + cmd */
+ ByteData= (2<<2), /* address + cmd + data */
+ WordData= (3<<2), /* address + cmd + data + data */
+ Kill= (1<<1), /* abort in progress command */
+ Ienable= (1<<0), /* enable completion interrupts */
+ Hostcommand= 0x3,
+ Hostaddress= 0x4,
+ AddressMask= (0x7f<<1), /* target address */
+ Read= (1<<0), /* 1 == read, 0 == write */
+ Hostdata0= 0x5,
+ Hostdata1= 0x6,
+ Blockdata= 0x7,
+ Slavecontrol= 0x8,
+ Alert_en= (1<<3), /* enable inter on SMBALERT# */
+ Shdw2_en= (1<<2), /* enable inter on external shadow 2 access */
+ Shdw1_en= (1<<1), /* enable inter on external shadow 1 access */
+ Slv_en= (1<<0), /* enable inter on access of host ctlr slave port */
+ Shadowcommand= 0x9,
+ Slaveevent= 0xa,
+ Slavedata= 0xc,
+};
+
+static struct
+{
+ int rw;
+ int cmd;
+ int len;
+ int proto;
+} proto[] =
+{
+ [SMBquick] { 0, 0, 0, Quick },
+ [SMBsend] { 0, 1, 0, Byte },
+ [SMBbytewrite] { 0, 1, 1, ByteData },
+ [SMBwordwrite] { 0, 1, 2, WordData },
+ [SMBrecv] { Read, 0, 1, Byte },
+ [SMBbyteread] { Read, 1, 1, ByteData },
+ [SMBwordread] { Read, 1, 2, WordData },
+};
+
+static void
+transact(SMBus *s, int type, int addr, int cmd, uchar *data)
+{
+ int tries, status;
+ char err[256];
+
+ if(type < 0 || type > nelem(proto))
+ panic("piix4smbus: illegal transaction type %d", type);
+
+ if(waserror()){
+ qunlock(s);
+ nexterror();
+ }
+ qlock(s);
+
+ /* wait a while for the host interface to be available */
+ for(tries = 0; tries < 1000000; tries++){
+ if((inb(s->base+Hoststatus) & Host_busy) == 0)
+ break;
+ sched();
+ }
+ if(tries >= 1000000){
+ /* try aborting current transaction */
+ outb(s->base+Hostcontrol, Kill);
+ for(tries = 0; tries < 1000000; tries++){
+ if((inb(s->base+Hoststatus) & Host_busy) == 0)
+ break;
+ sched();
+ }
+ if(tries >= 1000000){
+ snprint(err, sizeof(err), "SMBus jammed: %2.2ux", inb(s->base+Hoststatus));
+ error(err);
+ }
+ }
+
+ /* set up for transaction */
+ outb(s->base+Hostaddress, (addr<<1)|proto[type].rw);
+ if(proto[type].cmd)
+ outb(s->base+Hostcommand, cmd);
+ if(proto[type].rw != Read){
+ switch(proto[type].len){
+ case 2:
+ outb(s->base+Hostdata1, data[1]);
+ /* fall through */
+ case 1:
+ outb(s->base+Hostdata0, data[0]);
+ break;
+ }
+ }
+
+
+ /* reset the completion/error bits and start transaction */
+ outb(s->base+Hoststatus, Failed|Bus_error|Dev_error|Host_complete);
+ outb(s->base+Hostcontrol, Start|proto[type].proto);
+
+ /* wait for completion */
+ status = 0;
+ for(tries = 0; tries < 1000000; tries++){
+ status = inb(s->base+Hoststatus);
+ if(status & (Failed|Bus_error|Dev_error|Host_complete))
+ break;
+ sched();
+ }
+ if((status & Host_complete) == 0){
+ snprint(err, sizeof(err), "SMBus request failed: %2.2ux", status);
+ error(err);
+ }
+
+ /* get results */
+ if(proto[type].rw == Read){
+ switch(proto[type].len){
+ case 2:
+ data[1] = inb(s->base+Hostdata1);
+ /* fall through */
+ case 1:
+ data[0] = inb(s->base+Hostdata0);
+ break;
+ }
+ }
+ qunlock(s);
+ poperror();
+}
+
+static SMBus smbusproto =
+{
+ .transact = transact,
+};
+
+/*
+ * return 0 if this is a piix4 with an smbus interface
+ */
+SMBus*
+piix4smbus(void)
+{
+ Pcidev *p;
+ static SMBus *s;
+
+ if(s != nil)
+ return s;
+
+ p = pcimatch(nil, IntelVendID, Piix4PMID);
+ if(p == nil)
+ return nil;
+
+ s = smalloc(sizeof(*s));
+ memmove(s, &smbusproto, sizeof(*s));
+ s->arg = p;
+
+ /* disable the smbus */
+ pcicfgw8(p, SMBconfig, IRQ9enable|0);
+
+ /* see if bios gave us a viable port space */
+ s->base = pcicfgr32(p, SMBbase) & ~1;
+print("SMB base from bios is 0x%lux\n", s->base);
+ if(ioalloc(s->base, 0xd, 0, "piix4smbus") < 0){
+ s->base = ioalloc(-1, 0xd, 2, "piix4smbus");
+ if(s->base < 0){
+ free(s);
+ print("piix4smbus: can't allocate io port\n");
+ return nil;
+ }
+print("SMB base ialloc is 0x%lux\n", s->base);
+ pcicfgw32(p, SMBbase, s->base|1);
+ }
+
+ /* disable SMBus interrupts, abort any transaction in progress */
+ outb(s->base+Hostcontrol, Kill);
+ outb(s->base+Slavecontrol, 0);
+
+ /* enable the smbus */
+ pcicfgw8(p, SMBconfig, IRQ9enable|SMBenable);
+
+ return s;
+}
diff --git a/sys/src/9/pc/plan9l.s b/sys/src/9/pc/plan9l.s
new file mode 100755
index 000000000..e44671ac7
--- /dev/null
+++ b/sys/src/9/pc/plan9l.s
@@ -0,0 +1,52 @@
+#include "mem.h"
+
+/*
+ * This must match io.h.
+ */
+#define VectorSYSCALL 0x40
+
+/*
+ * Used to get to the first process:
+ * set up an interrupt return frame and IRET to user level.
+ */
+TEXT touser(SB), $0
+ PUSHL $(UDSEL) /* old ss */
+ MOVL sp+0(FP), AX /* old sp */
+ PUSHL AX
+ MOVL $0x200, AX /* interrupt enable flag */
+ PUSHL AX /* old flags */
+ PUSHL $(UESEL) /* old cs */
+ PUSHL $(UTZERO+32) /* old pc */
+ MOVL $(UDSEL), AX
+ MOVW AX, DS
+ MOVW AX, ES
+ MOVW AX, GS
+ MOVW AX, FS
+ IRETL
+
+/*
+ * This is merely _strayintr from l.s optimised to vector
+ * to syscall() without going through trap().
+ */
+TEXT _syscallintr(SB), $0
+ PUSHL $VectorSYSCALL /* trap type */
+
+ PUSHL DS
+ PUSHL ES
+ PUSHL FS
+ PUSHL GS
+ PUSHAL
+ MOVL $(KDSEL), AX
+ MOVW AX, DS
+ MOVW AX, ES
+ PUSHL SP
+ CALL syscall(SB)
+
+ POPL AX
+ POPAL
+ POPL GS
+ POPL FS
+ POPL ES
+ POPL DS
+ ADDL $8, SP /* pop error code and trap type */
+ IRETL
diff --git a/sys/src/9/pc/psaux.c b/sys/src/9/pc/psaux.c
new file mode 100755
index 000000000..e0c5d9f61
--- /dev/null
+++ b/sys/src/9/pc/psaux.c
@@ -0,0 +1,57 @@
+/*
+ * Interface to raw PS/2 aux port.
+ * Used by user-level mouse daemon.
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+/*
+ * BUG: we ignore shift here.
+ * we need a more general solution,
+ * one that will also work for serial mice.
+ */
+Queue *psauxq;
+
+static void
+psauxputc(int c, int)
+{
+ uchar uc;
+
+ uc = c;
+ qproduce(psauxq, &uc, 1);
+}
+
+static long
+psauxread(Chan*, void *a, long n, vlong)
+{
+ return qread(psauxq, a, n);
+}
+
+static long
+psauxwrite(Chan*, void *a, long n, vlong)
+{
+ return i8042auxcmds(a, n);
+}
+
+void
+psauxlink(void)
+{
+ psauxq = qopen(1024, 0, 0, 0);
+ if(psauxq == nil)
+ panic("psauxlink");
+ qnoblock(psauxq, 1);
+ i8042auxenable(psauxputc);
+ addarchfile("psaux", DMEXCL|0660, psauxread, psauxwrite);
+}
diff --git a/sys/src/9/pc/ptclbsum386.s b/sys/src/9/pc/ptclbsum386.s
new file mode 100755
index 000000000..ba0a6a4d1
--- /dev/null
+++ b/sys/src/9/pc/ptclbsum386.s
@@ -0,0 +1,126 @@
+TEXT ptclbsum(SB), $0
+ MOVL addr+0(FP), SI
+ MOVL len+4(FP), CX
+
+ XORL AX, AX /* sum */
+
+ TESTL $1, SI /* byte aligned? */
+ MOVL SI, DI
+ JEQ _2align
+
+ DECL CX
+ JLT _return
+
+ MOVB 0x00(SI), AH
+ INCL SI
+
+_2align:
+ TESTL $2, SI /* word aligned? */
+ JEQ _32loop
+
+ CMPL CX, $2 /* less than 2 bytes? */
+ JLT _1dreg
+ SUBL $2, CX
+
+ XORL BX, BX
+ MOVW 0x00(SI), BX
+ ADDL BX, AX
+ ADCL $0, AX
+ LEAL 2(SI), SI
+
+_32loop:
+ CMPL CX, $0x20
+ JLT _8loop
+
+ MOVL CX, BP
+ SHRL $5, BP
+ ANDL $0x1F, CX
+
+_32loopx:
+ MOVL 0x00(SI), BX
+ MOVL 0x1C(SI), DX
+ ADCL BX, AX
+ MOVL 0x04(SI), BX
+ ADCL DX, AX
+ MOVL 0x10(SI), DX
+ ADCL BX, AX
+ MOVL 0x08(SI), BX
+ ADCL DX, AX
+ MOVL 0x14(SI), DX
+ ADCL BX, AX
+ MOVL 0x0C(SI), BX
+ ADCL DX, AX
+ MOVL 0x18(SI), DX
+ ADCL BX, AX
+ LEAL 0x20(SI), SI
+ ADCL DX, AX
+
+ DECL BP
+ JNE _32loopx
+
+ ADCL $0, AX
+
+_8loop:
+ CMPL CX, $0x08
+ JLT _2loop
+
+ MOVL CX, BP
+ SHRL $3, BP
+ ANDL $0x07, CX
+
+_8loopx:
+ MOVL 0x00(SI), BX
+ ADCL BX, AX
+ MOVL 0x04(SI), DX
+ ADCL DX, AX
+
+ LEAL 0x08(SI), SI
+ DECL BP
+ JNE _8loopx
+
+ ADCL $0, AX
+
+_2loop:
+ CMPL CX, $0x02
+ JLT _1dreg
+
+ MOVL CX, BP
+ SHRL $1, BP
+ ANDL $0x01, CX
+
+_2loopx:
+ MOVWLZX 0x00(SI), BX
+ ADCL BX, AX
+
+ LEAL 0x02(SI), SI
+ DECL BP
+ JNE _2loopx
+
+ ADCL $0, AX
+
+_1dreg:
+ TESTL $1, CX /* 1 byte left? */
+ JEQ _fold
+
+ XORL BX, BX
+ MOVB 0x00(SI), BX
+ ADDL BX, AX
+ ADCL $0, AX
+
+_fold:
+ MOVL AX, BX
+ SHRL $16, BX
+ JEQ _swab
+
+ ANDL $0xFFFF, AX
+ ADDL BX, AX
+ JMP _fold
+
+_swab:
+ TESTL $1, addr+0(FP)
+ /*TESTL $1, DI*/
+ JNE _return
+ XCHGB AH, AL
+
+_return:
+ RET
diff --git a/sys/src/9/pc/random.c b/sys/src/9/pc/random.c
new file mode 100755
index 000000000..8e60a2ba0
--- /dev/null
+++ b/sys/src/9/pc/random.c
@@ -0,0 +1,139 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+
+struct Rb
+{
+ QLock;
+ Rendez producer;
+ Rendez consumer;
+ ulong randomcount;
+ uchar buf[1024];
+ uchar *ep;
+ uchar *rp;
+ uchar *wp;
+ uchar next;
+ uchar wakeme;
+ ushort bits;
+ ulong randn;
+} rb;
+
+static int
+rbnotfull(void*)
+{
+ int i;
+
+ i = rb.rp - rb.wp;
+ return i != 1 && i != (1 - sizeof(rb.buf));
+}
+
+static int
+rbnotempty(void*)
+{
+ return rb.wp != rb.rp;
+}
+
+static void
+genrandom(void*)
+{
+ up->basepri = PriNormal;
+ up->priority = up->basepri;
+
+ for(;;){
+ for(;;)
+ if(++rb.randomcount > 100000)
+ break;
+ if(anyhigher())
+ sched();
+ if(!rbnotfull(0))
+ sleep(&rb.producer, rbnotfull, 0);
+ }
+}
+
+/*
+ * produce random bits in a circular buffer
+ */
+static void
+randomclock(void)
+{
+ if(rb.randomcount == 0 || !rbnotfull(0))
+ return;
+
+ rb.bits = (rb.bits<<2) ^ rb.randomcount;
+ rb.randomcount = 0;
+
+ rb.next++;
+ if(rb.next != 8/2)
+ return;
+ rb.next = 0;
+
+ *rb.wp ^= rb.bits;
+ if(rb.wp+1 == rb.ep)
+ rb.wp = rb.buf;
+ else
+ rb.wp = rb.wp+1;
+
+ if(rb.wakeme)
+ wakeup(&rb.consumer);
+}
+
+void
+randominit(void)
+{
+ /* Frequency close but not equal to HZ */
+ addclock0link(randomclock, 13);
+ rb.ep = rb.buf + sizeof(rb.buf);
+ rb.rp = rb.wp = rb.buf;
+ kproc("genrandom", genrandom, 0);
+}
+
+/*
+ * consume random bytes from a circular buffer
+ */
+ulong
+randomread(void *xp, ulong n)
+{
+ uchar *e, *p;
+ ulong x;
+
+ p = xp;
+
+ if(waserror()){
+ qunlock(&rb);
+ nexterror();
+ }
+
+ qlock(&rb);
+ for(e = p + n; p < e; ){
+ if(rb.wp == rb.rp){
+ rb.wakeme = 1;
+ wakeup(&rb.producer);
+ sleep(&rb.consumer, rbnotempty, 0);
+ rb.wakeme = 0;
+ continue;
+ }
+
+ /*
+ * beating clocks will be predictable if
+ * they are synchronized. Use a cheap pseudo-
+ * random number generator to obscure any cycles.
+ */
+ x = rb.randn*1103515245 ^ *rb.rp;
+ *p++ = rb.randn = x;
+
+ if(rb.rp+1 == rb.ep)
+ rb.rp = rb.buf;
+ else
+ rb.rp = rb.rp+1;
+ }
+ qunlock(&rb);
+ poperror();
+
+ wakeup(&rb.producer);
+
+ return n;
+}
diff --git a/sys/src/9/pc/realmode.c b/sys/src/9/pc/realmode.c
new file mode 100755
index 000000000..7e892a240
--- /dev/null
+++ b/sys/src/9/pc/realmode.c
@@ -0,0 +1,140 @@
+#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;
+ ulong cr3;
+ extern void realmode0(void); /* in l.s */
+
+ 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 */
+ cr3 = getcr3();
+ putcr3(PADDR(m->pdb));
+ if (arch)
+ arch->introff();
+ else
+ i8259off();
+ realmode0();
+ if(m->tss){
+ /*
+ * Called from memory.c before initialization of mmu.
+ * Don't turn interrupts on before the kernel is ready!
+ */
+ if (arch)
+ arch->intron();
+ else
+ i8259on();
+ }
+ m->pdb[PDX(0)] = 0; /* remove low mapping */
+ putcr3(cr3);
+ 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 < 0 || n < 0)
+ error("bad offset/count");
+ if(isr){
+ if(off >= MB)
+ return 0;
+ if(off+n >= MB)
+ n = MB - off;
+ memmove(a, KADDR((ulong)off), n);
+ }else{
+ /* realmode buf page ok, allow vga framebuf's access */
+ if(off >= MB || off+n > MB ||
+ (off < LORMBUF || off+n > LORMBUF+BY2PG) &&
+ (off < 0xA0000 || off+n > 0xB0000+0x10000))
+ 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);
+}
+
diff --git a/sys/src/9/pc/rebootcode.s b/sys/src/9/pc/rebootcode.s
new file mode 100755
index 000000000..34ee4ca36
--- /dev/null
+++ b/sys/src/9/pc/rebootcode.s
@@ -0,0 +1,54 @@
+#include "mem.h"
+
+/*
+ * Turn off MMU, then memmory the new kernel to its correct location
+ * in physical memory. Then jumps the to start of the kernel.
+ */
+
+TEXT main(SB),$0
+ MOVL p1+0(FP), DI /* destination */
+ MOVL DI, AX /* entry point */
+ MOVL p2+4(FP), SI /* source */
+ MOVL n+8(FP), CX /* byte count */
+
+/*
+ * disable paging
+ */
+ MOVL CR0, DX
+ ANDL $~0x80000000, DX /* ~(PG) */
+ MOVL DX, CR0
+ MOVL $0, DX
+ MOVL DX, CR3
+
+/*
+ * the source and destination may overlap.
+ * determine whether to copy forward or backwards
+ */
+ CMPL SI, DI
+ JGT _forward
+ MOVL SI, DX
+ ADDL CX, DX
+ CMPL DX, DI
+ JGT _back
+
+_forward:
+ CLD
+ REP; MOVSB
+ JMP _startkernel
+
+_back:
+ ADDL CX, DI
+ ADDL CX, SI
+ SUBL $1, DI
+ SUBL $1, SI
+ STD
+ REP; MOVSB
+ JMP _startkernel
+/*
+ * JMP to kernel entry point. Note the true kernel entry point is
+ * the virtual address KZERO|AX, but this must wait until
+ * the MMU is enabled by the kernel in l.s
+ */
+_startkernel:
+ ORL AX, AX /* NOP: avoid link bug */
+ JMP* AX
diff --git a/sys/src/9/pc/screen.c b/sys/src/9/pc/screen.c
new file mode 100755
index 000000000..d1d4ae729
--- /dev/null
+++ b/sys/src/9/pc/screen.c
@@ -0,0 +1,748 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+#define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19)
+
+Point ZP = {0, 0};
+
+Rectangle physgscreenr;
+
+Memdata gscreendata;
+Memimage *gscreen;
+
+VGAscr vgascreen[1];
+
+Cursor arrow = {
+ { -1, -1 },
+ { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
+ 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
+ 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
+ 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
+ },
+ { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
+ 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
+ 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
+ 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
+ },
+};
+
+int didswcursorinit;
+
+static void *softscreen;
+
+int
+screensize(int x, int y, int z, ulong chan)
+{
+ VGAscr *scr;
+ void *oldsoft;
+
+ lock(&vgascreenlock);
+ if(waserror()){
+ unlock(&vgascreenlock);
+ nexterror();
+ }
+
+ memimageinit();
+ scr = &vgascreen[0];
+ oldsoft = softscreen;
+
+ if(scr->paddr == 0){
+ int width = (x*z)/BI2WD;
+ void *p;
+
+ p = xalloc(width*BY2WD*y);
+ if(p == nil)
+ error("no memory for vga soft screen");
+ gscreendata.bdata = softscreen = p;
+ if(scr->dev && scr->dev->page){
+ scr->vaddr = KADDR(VGAMEM());
+ scr->apsize = 1<<16;
+ }
+ scr->useflush = 1;
+ }
+ else{
+ gscreendata.bdata = scr->vaddr;
+ scr->useflush = scr->dev && scr->dev->flush;
+ }
+
+ scr->gscreen = nil;
+ if(gscreen)
+ freememimage(gscreen);
+ gscreen = allocmemimaged(Rect(0,0,x,y), chan, &gscreendata);
+ if(gscreen == nil)
+ error("no memory for vga memimage");
+ vgaimageinit(chan);
+
+ scr->palettedepth = 6; /* default */
+ scr->gscreendata = &gscreendata;
+ scr->memdefont = getmemdefont();
+ scr->gscreen = gscreen;
+
+ physgscreenr = gscreen->r;
+ unlock(&vgascreenlock);
+ poperror();
+ if(oldsoft)
+ xfree(oldsoft);
+
+ memimagedraw(gscreen, gscreen->r, memblack, ZP, nil, ZP, S);
+ flushmemscreen(gscreen->r);
+
+ if(didswcursorinit)
+ swcursorinit();
+ drawcmap();
+ return 0;
+}
+
+int
+screenaperture(int size, int align)
+{
+ VGAscr *scr;
+
+ scr = &vgascreen[0];
+
+ if(scr->paddr) /* set up during enable */
+ return 0;
+
+ if(size == 0)
+ return 0;
+
+ if(scr->dev && scr->dev->linear){
+ scr->dev->linear(scr, size, align);
+ return 0;
+ }
+
+ /*
+ * 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;
+}
+
+uchar*
+attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
+{
+ VGAscr *scr;
+
+ scr = &vgascreen[0];
+ if(scr->gscreen == nil || scr->gscreendata == nil)
+ return nil;
+
+ *r = scr->gscreen->clipr;
+ *chan = scr->gscreen->chan;
+ *d = scr->gscreen->depth;
+ *width = scr->gscreen->width;
+ *softscreen = scr->useflush;
+
+ return scr->gscreendata->bdata;
+}
+
+/*
+ * It would be fair to say that this doesn't work for >8-bit screens.
+ */
+void
+flushmemscreen(Rectangle r)
+{
+ VGAscr *scr;
+ uchar *sp, *disp, *sdisp, *edisp;
+ int y, len, incs, off, page;
+
+ scr = &vgascreen[0];
+ if(scr->dev && scr->dev->flush){
+ scr->dev->flush(scr, r);
+ return;
+ }
+ if(scr->gscreen == nil || scr->useflush == 0)
+ return;
+ if(scr->dev == nil || scr->dev->page == nil)
+ return;
+
+ if(rectclip(&r, scr->gscreen->r) == 0)
+ return;
+
+ incs = scr->gscreen->width * BY2WD;
+
+ switch(scr->gscreen->depth){
+ default:
+ len = 0;
+ panic("flushmemscreen: depth\n");
+ break;
+ case 8:
+ len = Dx(r);
+ break;
+ }
+ if(len < 1)
+ return;
+
+ off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8;
+ page = off/scr->apsize;
+ off %= scr->apsize;
+ disp = scr->vaddr;
+ sdisp = disp+off;
+ edisp = disp+scr->apsize;
+
+ off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8;
+
+ sp = scr->gscreendata->bdata + off;
+
+ scr->dev->page(scr, page);
+ for(y = r.min.y; y < r.max.y; y++) {
+ if(sdisp + incs < edisp) {
+ memmove(sdisp, sp, len);
+ sp += incs;
+ sdisp += incs;
+ }
+ else {
+ off = edisp - sdisp;
+ page++;
+ if(off <= len){
+ if(off > 0)
+ memmove(sdisp, sp, off);
+ scr->dev->page(scr, page);
+ if(len - off > 0)
+ memmove(disp, sp+off, len - off);
+ }
+ else {
+ memmove(sdisp, sp, len);
+ scr->dev->page(scr, page);
+ }
+ sp += incs;
+ sdisp += incs - scr->apsize;
+ }
+ }
+}
+
+void
+getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
+{
+ VGAscr *scr;
+ ulong x;
+
+ scr = &vgascreen[0];
+ if(scr->gscreen == nil)
+ return;
+
+ switch(scr->gscreen->depth){
+ default:
+ x = 0x0F;
+ break;
+ case 8:
+ x = 0xFF;
+ break;
+ }
+ p &= x;
+
+ lock(&cursor);
+ *pr = scr->colormap[p][0];
+ *pg = scr->colormap[p][1];
+ *pb = scr->colormap[p][2];
+ unlock(&cursor);
+}
+
+int
+setpalette(ulong p, ulong r, ulong g, ulong b)
+{
+ VGAscr *scr;
+ int d;
+
+ scr = &vgascreen[0];
+ d = scr->palettedepth;
+
+ lock(&cursor);
+ scr->colormap[p][0] = r;
+ scr->colormap[p][1] = g;
+ scr->colormap[p][2] = b;
+ vgao(PaddrW, p);
+ vgao(Pdata, r>>(32-d));
+ vgao(Pdata, g>>(32-d));
+ vgao(Pdata, b>>(32-d));
+ unlock(&cursor);
+
+ return ~0;
+}
+
+/*
+ * On some video cards (e.g. Mach64), the palette is used as the
+ * DAC registers for >8-bit modes. We don't want to set them when the user
+ * is trying to set a colormap and the card is in one of these modes.
+ */
+int
+setcolor(ulong p, ulong r, ulong g, ulong b)
+{
+ VGAscr *scr;
+ int x;
+
+ scr = &vgascreen[0];
+ if(scr->gscreen == nil)
+ return 0;
+
+ switch(scr->gscreen->depth){
+ case 1:
+ case 2:
+ case 4:
+ x = 0x0F;
+ break;
+ case 8:
+ x = 0xFF;
+ break;
+ default:
+ return 0;
+ }
+ p &= x;
+
+ return setpalette(p, r, g, b);
+}
+
+int
+cursoron(int dolock)
+{
+ VGAscr *scr;
+ int v;
+
+ scr = &vgascreen[0];
+ if(scr->cur == nil || scr->cur->move == nil)
+ return 0;
+
+ if(dolock)
+ lock(&cursor);
+ v = scr->cur->move(scr, mousexy());
+ if(dolock)
+ unlock(&cursor);
+
+ return v;
+}
+
+void
+cursoroff(int)
+{
+}
+
+void
+setcursor(Cursor* curs)
+{
+ VGAscr *scr;
+
+ scr = &vgascreen[0];
+ if(scr->cur == nil || scr->cur->load == nil)
+ return;
+
+ scr->cur->load(scr, curs);
+}
+
+int hwaccel = 1;
+int hwblank = 0; /* turned on by drivers that are known good */
+int panning = 0;
+
+int
+hwdraw(Memdrawparam *par)
+{
+ VGAscr *scr;
+ Memimage *dst, *src, *mask;
+ int m;
+
+ if(hwaccel == 0)
+ return 0;
+
+ scr = &vgascreen[0];
+ 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){
+ /*
+ * always calling swcursorhide here doesn't cure
+ * leaving cursor tracks nor failing to refresh menus
+ * with the latest libmemdraw/draw.c.
+ */
+ 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;
+
+ if(scr->fill==nil && scr->scroll==nil)
+ return 0;
+
+ /*
+ * If we have an opaque mask and source is one opaque
+ * pixel we can convert to the destination format and just
+ * replicate with memset.
+ */
+ m = Simplesrc|Simplemask|Fullmask;
+ if(scr->fill
+ && (par->state&m)==m
+ && ((par->srgba&0xFF) == 0xFF)
+ && (par->op&S) == S)
+ return scr->fill(scr, par->r, par->sdval);
+
+ /*
+ * If no source alpha, an opaque mask, we can just copy the
+ * source onto the destination. If the channels are the same and
+ * the source is not replicated, memmove suffices.
+ */
+ m = Simplemask|Fullmask;
+ if(scr->scroll
+ && src->data->bdata==dst->data->bdata
+ && !(src->flags&Falpha)
+ && (par->state&m)==m
+ && (par->op&S) == S)
+ return scr->scroll(scr, par->r, par->sr);
+
+ return 0;
+}
+
+void
+blankscreen(int blank)
+{
+ VGAscr *scr;
+
+ scr = &vgascreen[0];
+ if(hwblank){
+ if(scr->blank)
+ scr->blank(scr, blank);
+ else
+ 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).
+ * Some 3dfx cards (e.g., Voodoo3) have mmio
+ * buffers the same size as the frame buffer,
+ * but only the frame buffer is marked as
+ * prefetchable (bar&8). If a card doesn't fit
+ * into these heuristics, its driver will have to
+ * call vgalinearaddr directly.
+ */
+ 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
+ || (p->mem[i].size == p->mem[best].size
+ && (p->mem[i].bar&8)
+ && !(p->mem[best].bar&8)))
+ 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);
+
+ /*
+ * Don't bother trying to map more than 4000x4000x32 = 64MB.
+ * We only have a 256MB window.
+ */
+ if(nsize > 64*MB)
+ nsize = 64*MB;
+ 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;
+ /* let mtrr harmlessly fail on old CPUs, e.g., P54C */
+ if(!waserror()){
+ mtrr(npaddr, nsize, "wc");
+ poperror();
+ }
+}
+
+
+/*
+ * 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);
+ flushmemscreen(swrect);
+}
+
+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);
+ flushmemscreen(swrect);
+ 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, 10);
+ }
+ 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 fails");
+ return;
+ }
+
+ memfillcolor(swmask, DOpaque);
+ memfillcolor(swmask1, DOpaque);
+ memfillcolor(swimg, DBlack);
+ memfillcolor(swimg1, DBlack);
+}
+
+VGAcur swcursor =
+{
+ "soft",
+ swenable,
+ swdisable,
+ swload,
+ swmove,
+};
+
diff --git a/sys/src/9/pc/screen.h b/sys/src/9/pc/screen.h
new file mode 100755
index 000000000..a9d1b66a4
--- /dev/null
+++ b/sys/src/9/pc/screen.h
@@ -0,0 +1,177 @@
+typedef struct Cursor Cursor;
+typedef struct Cursorinfo Cursorinfo;
+struct Cursorinfo {
+ Cursor;
+ Lock;
+};
+
+/* devmouse.c */
+extern void mousetrack(int, int, int, int);
+extern Point mousexy(void);
+
+extern void mouseaccelerate(int);
+extern int m3mouseputc(Queue*, int);
+extern int m5mouseputc(Queue*, int);
+extern int mouseputc(Queue*, int);
+
+extern Cursorinfo cursor;
+extern Cursor arrow;
+
+/*
+ * Generic VGA registers.
+ */
+enum {
+ MiscW = 0x03C2, /* Miscellaneous Output (W) */
+ MiscR = 0x03CC, /* Miscellaneous Output (R) */
+ Status0 = 0x03C2, /* Input status 0 (R) */
+ Status1 = 0x03DA, /* Input Status 1 (R) */
+ FeatureR = 0x03CA, /* Feature Control (R) */
+ FeatureW = 0x03DA, /* Feature Control (W) */
+
+ Seqx = 0x03C4, /* Sequencer Index, Data at Seqx+1 */
+ Crtx = 0x03D4, /* CRT Controller Index, Data at Crtx+1 */
+ Grx = 0x03CE, /* Graphics Controller Index, Data at Grx+1 */
+ Attrx = 0x03C0, /* Attribute Controller Index and Data */
+
+ PaddrW = 0x03C8, /* Palette Address Register, write */
+ Pdata = 0x03C9, /* Palette Data Register */
+ Pixmask = 0x03C6, /* Pixel Mask Register */
+ PaddrR = 0x03C7, /* Palette Address Register, read */
+ Pstatus = 0x03C7, /* DAC Status (RO) */
+
+ Pcolours = 256, /* Palette */
+ Pred = 0,
+ Pgreen = 1,
+ Pblue = 2,
+
+ Pblack = 0x00,
+ Pwhite = 0xFF,
+};
+
+#define VGAMEM() 0xA0000
+#define vgai(port) inb(port)
+#define vgao(port, data) outb(port, data)
+
+extern int vgaxi(long, uchar);
+extern int vgaxo(long, uchar, uchar);
+
+/*
+ */
+typedef struct VGAdev VGAdev;
+typedef struct VGAcur VGAcur;
+typedef struct VGAscr VGAscr;
+
+struct VGAdev {
+ char* name;
+
+ void (*enable)(VGAscr*);
+ void (*disable)(VGAscr*);
+ void (*page)(VGAscr*, int);
+ void (*linear)(VGAscr*, int, int);
+ void (*drawinit)(VGAscr*);
+ int (*fill)(VGAscr*, Rectangle, ulong);
+ void (*ovlctl)(VGAscr*, Chan*, void*, int);
+ int (*ovlwrite)(VGAscr*, void*, int, vlong);
+ void (*flush)(VGAscr*, Rectangle);
+};
+
+struct VGAcur {
+ char* name;
+
+ void (*enable)(VGAscr*);
+ void (*disable)(VGAscr*);
+ void (*load)(VGAscr*, Cursor*);
+ int (*move)(VGAscr*, Point);
+
+ int doespanning;
+};
+
+/*
+ */
+struct VGAscr {
+ Lock devlock;
+ VGAdev* dev;
+ Pcidev* pci;
+
+ VGAcur* cur;
+ ulong storage;
+ Cursor;
+
+ int useflush;
+
+ ulong paddr; /* frame buffer */
+ void* vaddr;
+ int apsize;
+
+ ulong io; /* device specific registers */
+ ulong *mmio;
+
+ ulong colormap[Pcolours][3];
+ int palettedepth;
+
+ Memimage* gscreen;
+ Memdata* gscreendata;
+ Memsubfont* memdefont;
+
+ int (*fill)(VGAscr*, Rectangle, ulong);
+ int (*scroll)(VGAscr*, Rectangle, Rectangle);
+ void (*blank)(VGAscr*, int);
+ ulong id; /* internal identifier for driver use */
+ int isblank;
+ int overlayinit;
+};
+
+extern VGAscr vgascreen[];
+
+enum {
+ Backgnd = 0, /* black */
+};
+
+/* mouse.c */
+extern void mousectl(Cmdbuf*);
+extern void mouseresize(void);
+
+/* screen.c */
+extern int hwaccel; /* use hw acceleration; default on */
+extern int hwblank; /* use hw blanking; default on */
+extern int panning; /* use virtual screen panning; default off */
+extern void addvgaseg(char*, ulong, ulong);
+extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*);
+extern void flushmemscreen(Rectangle);
+extern int cursoron(int);
+extern void cursoroff(int);
+extern void setcursor(Cursor*);
+extern int screensize(int, int, int, ulong);
+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 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;
+
+#define ishwimage(i) (vgascreen[0].gscreendata && (i)->data->bdata == vgascreen[0].gscreendata->bdata)
diff --git a/sys/src/9/pc/sd53c8xx.c b/sys/src/9/pc/sd53c8xx.c
new file mode 100755
index 000000000..7c2b1f2bf
--- /dev/null
+++ b/sys/src/9/pc/sd53c8xx.c
@@ -0,0 +1,2270 @@
+/*
+ * NCR/Symbios/LSI Logic 53c8xx driver for Plan 9
+ * Nigel Roles (nigel@9fs.org)
+ *
+ * 27/5/02 Fixed problems with transfers >= 256 * 512
+ *
+ * 13/3/01 Fixed microcode to support targets > 7
+ *
+ * 01/12/00 Removed previous comments. Fixed a small problem in
+ * mismatch recovery for targets with synchronous offsets of >=16
+ * connected to >=875s. Thanks, Jean.
+ *
+ * Known problems
+ *
+ * Read/write mismatch recovery may fail on 53c1010s. Really need to get a manual.
+ */
+
+#define MAXTARGET 16 /* can be 8 or 16 */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "../port/sd.h"
+extern SDifc sd53c8xxifc;
+
+/**********************************/
+/* Portable configuration macros */
+/**********************************/
+
+//#define BOOTDEBUG
+//#define ASYNC_ONLY
+//#define INTERNAL_SCLK
+//#define ALWAYS_DO_WDTR
+#define WMR_DEBUG
+
+/**********************************/
+/* CPU specific macros */
+/**********************************/
+
+#define PRINTPREFIX "sd53c8xx: "
+
+#ifdef BOOTDEBUG
+
+#define KPRINT oprint
+#define IPRINT intrprint
+#define DEBUG(n) 1
+#define IFLUSH() iflush()
+
+#else
+
+static int idebug = 1;
+#define KPRINT if(0) iprint
+#define IPRINT if(idebug) iprint
+#define DEBUG(n) (0)
+#define IFLUSH()
+
+#endif /* BOOTDEBUG */
+
+/*******************************/
+/* General */
+/*******************************/
+
+#ifndef DMASEG
+#define DMASEG(x) PCIWADDR(x)
+#define legetl(x) (*(ulong*)(x))
+#define lesetl(x,v) (*(ulong*)(x) = (v))
+#define swabl(a,b,c)
+#else
+#endif /*DMASEG */
+#define DMASEG_TO_KADDR(x) KADDR((x)-PCIWINDOW)
+#define KPTR(x) ((x) == 0 ? 0 : DMASEG_TO_KADDR(x))
+
+#define MEGA 1000000L
+#ifdef INTERNAL_SCLK
+#define SCLK (33 * MEGA)
+#else
+#define SCLK (40 * MEGA)
+#endif /* INTERNAL_SCLK */
+#define ULTRA_NOCLOCKDOUBLE_SCLK (80 * MEGA)
+
+#define MAXSYNCSCSIRATE (5 * MEGA)
+#define MAXFASTSYNCSCSIRATE (10 * MEGA)
+#define MAXULTRASYNCSCSIRATE (20 * MEGA)
+#define MAXULTRA2SYNCSCSIRATE (40 * MEGA)
+#define MAXASYNCCORERATE (25 * MEGA)
+#define MAXSYNCCORERATE (25 * MEGA)
+#define MAXFASTSYNCCORERATE (50 * MEGA)
+#define MAXULTRASYNCCORERATE (80 * MEGA)
+#define MAXULTRA2SYNCCORERATE (160 * MEGA)
+
+
+#define X_MSG 1
+#define X_MSG_SDTR 1
+#define X_MSG_WDTR 3
+
+struct na_patch {
+ unsigned lwoff;
+ unsigned char type;
+};
+
+typedef struct Ncr {
+ uchar scntl0; /* 00 */
+ uchar scntl1;
+ uchar scntl2;
+ uchar scntl3;
+
+ uchar scid; /* 04 */
+ uchar sxfer;
+ uchar sdid;
+ uchar gpreg;
+
+ uchar sfbr; /* 08 */
+ uchar socl;
+ uchar ssid;
+ uchar sbcl;
+
+ uchar dstat; /* 0c */
+ uchar sstat0;
+ uchar sstat1;
+ uchar sstat2;
+
+ uchar dsa[4]; /* 10 */
+
+ uchar istat; /* 14 */
+ uchar istatpad[3];
+
+ uchar ctest0; /* 18 */
+ uchar ctest1;
+ uchar ctest2;
+ uchar ctest3;
+
+ uchar temp[4]; /* 1c */
+
+ uchar dfifo; /* 20 */
+ uchar ctest4;
+ uchar ctest5;
+ uchar ctest6;
+
+ uchar dbc[3]; /* 24 */
+ uchar dcmd; /* 27 */
+
+ uchar dnad[4]; /* 28 */
+ uchar dsp[4]; /* 2c */
+ uchar dsps[4]; /* 30 */
+
+ uchar scratcha[4]; /* 34 */
+
+ uchar dmode; /* 38 */
+ uchar dien;
+ uchar dwt;
+ uchar dcntl;
+
+ uchar adder[4]; /* 3c */
+
+ uchar sien0; /* 40 */
+ uchar sien1;
+ uchar sist0;
+ uchar sist1;
+
+ uchar slpar; /* 44 */
+ uchar slparpad0;
+ uchar macntl;
+ uchar gpcntl;
+
+ uchar stime0; /* 48 */
+ uchar stime1;
+ uchar respid;
+ uchar respidpad0;
+
+ uchar stest0; /* 4c */
+ uchar stest1;
+ uchar stest2;
+ uchar stest3;
+
+ uchar sidl; /* 50 */
+ uchar sidlpad[3];
+
+ uchar sodl; /* 54 */
+ uchar sodlpad[3];
+
+ uchar sbdl; /* 58 */
+ uchar sbdlpad[3];
+
+ uchar scratchb[4]; /* 5c */
+} Ncr;
+
+typedef struct Movedata {
+ uchar dbc[4];
+ uchar pa[4];
+} Movedata;
+
+typedef enum NegoState {
+ NeitherDone, WideInit, WideResponse, WideDone,
+ SyncInit, SyncResponse, BothDone
+} NegoState;
+
+typedef enum State {
+ Allocated, Queued, Active, Done
+} State;
+
+typedef struct Dsa Dsa;
+struct Dsa {
+ uchar stateb;
+ uchar result;
+ uchar dmablks;
+ uchar flag; /* setbyte(state,3,...) */
+
+ union {
+ ulong dmancr; /* For block transfer: NCR order (little-endian) */
+ uchar dmaaddr[4];
+ };
+
+ uchar target; /* Target */
+ uchar pad0[3];
+
+ uchar lun; /* Logical Unit Number */
+ uchar pad1[3];
+
+ uchar scntl3;
+ uchar sxfer;
+ uchar pad2[2];
+
+ uchar next[4]; /* chaining for SCRIPT (NCR byte order) */
+ Dsa *freechain; /* chaining for freelist */
+ Rendez;
+ uchar scsi_id_buf[4];
+ Movedata msg_out_buf;
+ Movedata cmd_buf;
+ Movedata data_buf;
+ Movedata status_buf;
+ uchar msg_out[10]; /* enough to include SDTR */
+ uchar status;
+ int p9status;
+ uchar parityerror;
+};
+
+typedef enum Feature {
+ BigFifo = 1, /* 536 byte fifo */
+ BurstOpCodeFetch = 2, /* burst fetch opcodes */
+ Prefetch = 4, /* prefetch 8 longwords */
+ LocalRAM = 8, /* 4K longwords of local RAM */
+ Differential = 16, /* Differential support */
+ Wide = 32, /* Wide capable */
+ Ultra = 64, /* Ultra capable */
+ ClockDouble = 128, /* Has clock doubler */
+ ClockQuad = 256, /* Has clock quadrupler (same as Ultra2) */
+ Ultra2 = 256,
+} Feature;
+
+typedef enum Burst {
+ Burst2 = 0,
+ Burst4 = 1,
+ Burst8 = 2,
+ Burst16 = 3,
+ Burst32 = 4,
+ Burst64 = 5,
+ Burst128 = 6
+} Burst;
+
+typedef struct Variant {
+ ushort did;
+ uchar maxrid; /* maximum allowed revision ID */
+ char *name;
+ Burst burst; /* codings for max burst */
+ uchar maxsyncoff; /* max synchronous offset */
+ uchar registers; /* number of 32 bit registers */
+ unsigned feature;
+} Variant;
+
+static unsigned char cf2[] = { 6, 2, 3, 4, 6, 8, 12, 16 };
+#define NULTRA2SCF (sizeof(cf2)/sizeof(cf2[0]))
+#define NULTRASCF (NULTRA2SCF - 2)
+#define NSCF (NULTRASCF - 1)
+
+typedef struct Controller {
+ Lock;
+ struct {
+ uchar scntl3;
+ uchar stest2;
+ } bios;
+ uchar synctab[NULTRA2SCF - 1][8];/* table of legal tpfs */
+ NegoState s[MAXTARGET];
+ uchar scntl3[MAXTARGET];
+ uchar sxfer[MAXTARGET];
+ uchar cap[MAXTARGET]; /* capabilities byte from Identify */
+ ushort capvalid; /* bit per target for validity of cap[] */
+ ushort wide; /* bit per target set if wide negotiated */
+ ulong sclk; /* clock speed of controller */
+ uchar clockmult; /* set by synctabinit */
+ uchar ccf; /* CCF bits */
+ uchar tpf; /* best tpf value for this controller */
+ uchar feature; /* requested features */
+ int running; /* is the script processor running? */
+ int ssm; /* single step mode */
+ Ncr *n; /* pointer to registers */
+ Variant *v; /* pointer to variant type */
+ ulong *script; /* where the real script is */
+ ulong scriptpa; /* where the real script is */
+ Pcidev* pcidev;
+ SDev* sdev;
+
+ struct {
+ Lock;
+ uchar head[4]; /* head of free list (NCR byte order) */
+ Dsa *freechain;
+ } dsalist;
+
+ QLock q[MAXTARGET]; /* queues for each target */
+} Controller;
+
+#define SYNCOFFMASK(c) (((c)->v->maxsyncoff * 2) - 1)
+#define SSIDMASK(c) (((c)->v->feature & Wide) ? 15 : 7)
+
+/* ISTAT */
+enum { Abrt = 0x80, Srst = 0x40, Sigp = 0x20, Sem = 0x10, Con = 0x08, Intf = 0x04, Sip = 0x02, Dip = 0x01 };
+
+/* DSTAT */
+enum { Dfe = 0x80, Mdpe = 0x40, Bf = 0x20, Abrted = 0x10, Ssi = 0x08, Sir = 0x04, Iid = 0x01 };
+
+/* SSTAT */
+enum { DataOut, DataIn, Cmd, Status, ReservedOut, ReservedIn, MessageOut, MessageIn };
+
+static void setmovedata(Movedata*, ulong, ulong);
+static void advancedata(Movedata*, long);
+static int bios_set_differential(Controller *c);
+
+static char *phase[] = {
+ "data out", "data in", "command", "status",
+ "reserved out", "reserved in", "message out", "message in"
+};
+
+#ifdef BOOTDEBUG
+#define DEBUGSIZE 10240
+char debugbuf[DEBUGSIZE];
+char *debuglast;
+
+static void
+intrprint(char *format, ...)
+{
+ if (debuglast == 0)
+ debuglast = debugbuf;
+ debuglast = vseprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
+}
+
+static void
+iflush()
+{
+ int s;
+ char *endp;
+ s = splhi();
+ if (debuglast == 0)
+ debuglast = debugbuf;
+ if (debuglast == debugbuf) {
+ splx(s);
+ return;
+ }
+ endp = debuglast;
+ splx(s);
+ screenputs(debugbuf, endp - debugbuf);
+ s = splhi();
+ memmove(debugbuf, endp, debuglast - endp);
+ debuglast -= endp - debugbuf;
+ splx(s);
+}
+
+static void
+oprint(char *format, ...)
+{
+ int s;
+
+ iflush();
+ s = splhi();
+ if (debuglast == 0)
+ debuglast = debugbuf;
+ debuglast = vseprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
+ splx(s);
+ iflush();
+}
+#endif
+
+#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);
+ if (d == nil)
+ panic("sd53c8xx dsaallocnew: no memory");
+ 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) {
+ 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;
+ return d;
+}
+
+static void
+dsafree(Controller *c, Dsa *d)
+{
+ ilock(&c->dsalist);
+ d->freechain = c->dsalist.freechain;
+ c->dsalist.freechain = d;
+ lesetl(&d->stateb, A_STATE_FREE);
+ 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 != dsaend; d = KPTR(legetl(d->next))) {
+ if (d->target != 0xff && d->target != target)
+ continue;
+ if (lun != 0xff && d->lun != lun)
+ continue;
+ if (state != 0xff && d->stateb != state)
+ continue;
+ break;
+ }
+ return d;
+}
+
+static void
+dumpncrregs(Controller *c, int intr)
+{
+ int i;
+ Ncr *n = c->n;
+ int depth = c->v->registers / 4;
+
+ if (intr) {
+ IPRINT("sa = %.8lux\n", c->scriptpa);
+ }
+ else {
+ KPRINT("sa = %.8lux\n", c->scriptpa);
+ }
+ for (i = 0; i < depth; i++) {
+ int j;
+ for (j = 0; j < 4; j++) {
+ int k = j * depth + i;
+ uchar *p;
+
+ /* display little-endian to make 32-bit values readable */
+ p = (uchar*)n+k*4;
+ if (intr) {
+ IPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
+ }
+ else {
+ KPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
+ }
+ USED(p);
+ }
+ if (intr) {
+ IPRINT("\n");
+ }
+ else {
+ KPRINT("\n");
+ }
+ }
+}
+
+static int
+chooserate(Controller *c, int tpf, int *scfp, int *xferpp)
+{
+ /* find lowest entry >= tpf */
+ int besttpf = 1000;
+ int bestscfi = 0;
+ int bestxferp = 0;
+ int scf, xferp;
+ int maxscf;
+
+ if (c->v->feature & Ultra2)
+ maxscf = NULTRA2SCF;
+ else if (c->v->feature & Ultra)
+ maxscf = NULTRASCF;
+ else
+ maxscf = NSCF;
+
+ /*
+ * search large clock factors first since this should
+ * result in more reliable transfers
+ */
+ for (scf = maxscf; scf >= 1; scf--) {
+ for (xferp = 0; xferp < 8; xferp++) {
+ unsigned char v = c->synctab[scf - 1][xferp];
+ if (v == 0)
+ continue;
+ if (v >= tpf && v < besttpf) {
+ besttpf = v;
+ bestscfi = scf;
+ bestxferp = xferp;
+ }
+ }
+ }
+ if (besttpf == 1000)
+ return 0;
+ if (scfp)
+ *scfp = bestscfi;
+ if (xferpp)
+ *xferpp = bestxferp;
+ return besttpf;
+}
+
+static void
+synctabinit(Controller *c)
+{
+ int scf;
+ unsigned long scsilimit;
+ int xferp;
+ unsigned long cr, sr;
+ int tpf;
+ int fast;
+ int maxscf;
+
+ if (c->v->feature & Ultra2)
+ maxscf = NULTRA2SCF;
+ else if (c->v->feature & Ultra)
+ maxscf = NULTRASCF;
+ else
+ maxscf = NSCF;
+
+ /*
+ * for chips with no clock doubler, but Ultra capable (e.g. 860, or interestingly the
+ * first spin of the 875), assume 80MHz
+ * otherwise use the internal (33 Mhz) or external (40MHz) default
+ */
+
+ if ((c->v->feature & Ultra) != 0 && (c->v->feature & (ClockDouble | ClockQuad)) == 0)
+ c->sclk = ULTRA_NOCLOCKDOUBLE_SCLK;
+ else
+ c->sclk = SCLK;
+
+ /*
+ * otherwise, if the chip is Ultra capable, but has a slow(ish) clock,
+ * invoke the doubler
+ */
+
+ if (SCLK <= 40000000) {
+ if (c->v->feature & ClockDouble) {
+ c->sclk *= 2;
+ c->clockmult = 1;
+ }
+ else if (c->v->feature & ClockQuad) {
+ c->sclk *= 4;
+ c->clockmult = 1;
+ }
+ else
+ c->clockmult = 0;
+ }
+ else
+ c->clockmult = 0;
+
+ /* derive CCF from sclk */
+ /* woebetide anyone with SCLK < 16.7 or > 80MHz */
+ if (c->sclk <= 25 * MEGA)
+ c->ccf = 1;
+ else if (c->sclk <= 3750000)
+ c->ccf = 2;
+ else if (c->sclk <= 50 * MEGA)
+ c->ccf = 3;
+ else if (c->sclk <= 75 * MEGA)
+ c->ccf = 4;
+ else if ((c->v->feature & ClockDouble) && c->sclk <= 80 * MEGA)
+ c->ccf = 5;
+ else if ((c->v->feature & ClockQuad) && c->sclk <= 120 * MEGA)
+ c->ccf = 6;
+ else if ((c->v->feature & ClockQuad) && c->sclk <= 160 * MEGA)
+ c->ccf = 7;
+
+ for (scf = 1; scf < maxscf; scf++) {
+ /* check for legal core rate */
+ /* round up so we run slower for safety */
+ cr = (c->sclk * 2 + cf2[scf] - 1) / cf2[scf];
+ if (cr <= MAXSYNCCORERATE) {
+ scsilimit = MAXSYNCSCSIRATE;
+ fast = 0;
+ }
+ else if (cr <= MAXFASTSYNCCORERATE) {
+ scsilimit = MAXFASTSYNCSCSIRATE;
+ fast = 1;
+ }
+ else if ((c->v->feature & Ultra) && cr <= MAXULTRASYNCCORERATE) {
+ scsilimit = MAXULTRASYNCSCSIRATE;
+ fast = 2;
+ }
+ else if ((c->v->feature & Ultra2) && cr <= MAXULTRA2SYNCCORERATE) {
+ scsilimit = MAXULTRA2SYNCSCSIRATE;
+ fast = 3;
+ }
+ else
+ continue;
+ for (xferp = 11; xferp >= 4; xferp--) {
+ int ok;
+ int tp;
+ /* calculate scsi rate - round up again */
+ /* start from sclk for accuracy */
+ int totaldivide = xferp * cf2[scf];
+ sr = (c->sclk * 2 + totaldivide - 1) / totaldivide;
+ if (sr > scsilimit)
+ break;
+ /*
+ * now work out transfer period
+ * round down now so that period is pessimistic
+ */
+ tp = (MEGA * 1000) / sr;
+ /*
+ * bounds check it
+ */
+ if (tp < 25 || tp > 255 * 4)
+ continue;
+ /*
+ * spot stupid special case for Ultra or Ultra2
+ * while working out factor
+ */
+ if (tp == 25)
+ tpf = 10;
+ else if (tp == 50)
+ tpf = 12;
+ else if (tp < 52)
+ continue;
+ else
+ tpf = tp / 4;
+ /*
+ * now check tpf looks sensible
+ * given core rate
+ */
+ switch (fast) {
+ case 0:
+ /* scf must be ccf for SCSI 1 */
+ ok = tpf >= 50 && scf == c->ccf;
+ break;
+ case 1:
+ ok = tpf >= 25 && tpf < 50;
+ break;
+ case 2:
+ /*
+ * must use xferp of 4, or 5 at a pinch
+ * for an Ultra transfer
+ */
+ ok = xferp <= 5 && tpf >= 12 && tpf < 25;
+ break;
+ case 3:
+ ok = xferp == 4 && (tpf == 10 || tpf == 11);
+ break;
+ default:
+ ok = 0;
+ }
+ if (!ok)
+ continue;
+ c->synctab[scf - 1][xferp - 4] = tpf;
+ }
+ }
+
+#ifndef NO_ULTRA2
+ if (c->v->feature & Ultra2)
+ tpf = 10;
+ else
+#endif
+ if (c->v->feature & Ultra)
+ tpf = 12;
+ else
+ tpf = 25;
+ for (; tpf < 256; tpf++) {
+ if (chooserate(c, tpf, &scf, &xferp) == tpf) {
+ unsigned tp = tpf == 10 ? 25 : (tpf == 12 ? 50 : tpf * 4);
+ unsigned long khz = (MEGA + tp - 1) / (tp);
+ KPRINT(PRINTPREFIX "tpf=%d scf=%d.%.1d xferp=%d mhz=%ld.%.3ld\n",
+ tpf, cf2[scf] / 2, (cf2[scf] & 1) ? 5 : 0,
+ xferp + 4, khz / 1000, khz % 1000);
+ USED(khz);
+ if (c->tpf == 0)
+ c->tpf = tpf; /* note lowest value for controller */
+ }
+ }
+}
+
+static void
+synctodsa(Dsa *dsa, Controller *c)
+{
+/*
+ KPRINT("synctodsa(dsa=%lux, target=%d, scntl3=%.2lx sxfer=%.2x)\n",
+ dsa, dsa->target, c->scntl3[dsa->target], c->sxfer[dsa->target]);
+*/
+ dsa->scntl3 = c->scntl3[dsa->target];
+ dsa->sxfer = c->sxfer[dsa->target];
+}
+
+static void
+setsync(Dsa *dsa, Controller *c, int target, uchar ultra, uchar scf, uchar xferp, uchar reqack)
+{
+ c->scntl3[target] =
+ (c->scntl3[target] & 0x08) | (((scf << 4) | c->ccf | (ultra << 7)) & ~0x08);
+ c->sxfer[target] = (xferp << 5) | reqack;
+ c->s[target] = BothDone;
+ if (dsa) {
+ synctodsa(dsa, c);
+ c->n->scntl3 = c->scntl3[target];
+ c->n->sxfer = c->sxfer[target];
+ }
+}
+
+static void
+setasync(Dsa *dsa, Controller *c, int target)
+{
+ setsync(dsa, c, target, 0, c->ccf, 0, 0);
+}
+
+static void
+setwide(Dsa *dsa, Controller *c, int target, uchar wide)
+{
+ c->scntl3[target] = wide ? (1 << 3) : 0;
+ setasync(dsa, c, target);
+ c->s[target] = WideDone;
+}
+
+static int
+buildsdtrmsg(uchar *buf, uchar tpf, uchar offset)
+{
+ *buf++ = X_MSG;
+ *buf++ = 3;
+ *buf++ = X_MSG_SDTR;
+ *buf++ = tpf;
+ *buf = offset;
+ return 5;
+}
+
+static int
+buildwdtrmsg(uchar *buf, uchar expo)
+{
+ *buf++ = X_MSG;
+ *buf++ = 2;
+ *buf++ = X_MSG_WDTR;
+ *buf = expo;
+ return 4;
+}
+
+static void
+start(Controller *c, long entry)
+{
+ ulong p;
+
+ if (c->running)
+ panic(PRINTPREFIX "start called while running");
+ 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 */
+}
+
+static void
+ncrcontinue(Controller *c)
+{
+ if (c->running)
+ panic(PRINTPREFIX "ncrcontinue called while running");
+ /* set the start DMA bit to continue execution */
+ c->running = 1;
+ coherence();
+ c->n->dcntl |= 0x4;
+}
+
+static void
+softreset(Controller *c)
+{
+ Ncr *n = c->n;
+
+ n->istat = Srst; /* software reset */
+ n->istat = 0;
+ /* general initialisation */
+ n->scid = (1 << 6) | 7; /* respond to reselect, ID 7 */
+ n->respid = 1 << 7; /* response ID = 7 */
+
+#ifdef INTERNAL_SCLK
+ n->stest1 = 0x80; /* disable external scsi clock */
+#else
+ n->stest1 = 0x00;
+#endif
+
+ n->stime0 = 0xdd; /* about 0.5 second timeout on each device */
+ n->scntl0 |= 0x8; /* Enable parity checking */
+
+ /* continued setup */
+ n->sien0 = 0x8f;
+ n->sien1 = 0x04;
+ n->dien = 0x7d;
+ n->stest3 = 0x80; /* TolerANT enable */
+ c->running = 0;
+
+ if (c->v->feature & BigFifo)
+ n->ctest5 = (1 << 5);
+ n->dmode = c->v->burst << 6; /* set burst length bits */
+ if (c->v->burst & 4)
+ n->ctest5 |= (1 << 2); /* including overflow into ctest5 bit 2 */
+ if (c->v->feature & Prefetch)
+ n->dcntl |= (1 << 5); /* prefetch enable */
+ else if (c->v->feature & BurstOpCodeFetch)
+ n->dmode |= (1 << 1); /* burst opcode fetch */
+ if (c->v->feature & Differential) {
+ /* chip capable */
+ if ((c->feature & Differential) || bios_set_differential(c)) {
+ /* user enabled, or some evidence bios set differential */
+ if (n->sstat2 & (1 << 2))
+ print(PRINTPREFIX "can't go differential; wrong cable\n");
+ else {
+ n->stest2 = (1 << 5);
+ print(PRINTPREFIX "differential mode set\n");
+ }
+ }
+ }
+ if (c->clockmult) {
+ n->stest1 |= (1 << 3); /* power up doubler */
+ delay(2);
+ n->stest3 |= (1 << 5); /* stop clock */
+ n->stest1 |= (1 << 2); /* enable doubler */
+ n->stest3 &= ~(1 << 5); /* start clock */
+ /* pray */
+ }
+}
+
+static void
+msgsm(Dsa *dsa, Controller *c, int msg, int *cont, int *wakeme)
+{
+ uchar histpf, hisreqack;
+ int tpf;
+ int scf, xferp;
+ int len;
+
+ Ncr *n = c->n;
+
+ switch (c->s[dsa->target]) {
+ case SyncInit:
+ switch (msg) {
+ case A_SIR_MSG_SDTR:
+ /* reply to my SDTR */
+ histpf = n->scratcha[2];
+ hisreqack = n->scratcha[3];
+ KPRINT(PRINTPREFIX "%d: SDTN response %d %d\n",
+ dsa->target, histpf, hisreqack);
+
+ if (hisreqack == 0)
+ setasync(dsa, c, dsa->target);
+ else {
+ /* hisreqack should be <= c->v->maxsyncoff */
+ tpf = chooserate(c, histpf, &scf, &xferp);
+ KPRINT(PRINTPREFIX "%d: SDTN: using %d %d\n",
+ dsa->target, tpf, hisreqack);
+ setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
+ }
+ *cont = -2;
+ return;
+ case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
+ /* target ignored ATN for message after IDENTIFY - not SCSI-II */
+ KPRINT(PRINTPREFIX "%d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
+ KPRINT(PRINTPREFIX "%d: SDTN: async\n", dsa->target);
+ setasync(dsa, c, dsa->target);
+ *cont = E_to_decisions;
+ return;
+ case A_SIR_MSG_REJECT:
+ /* rejection of my SDTR */
+ KPRINT(PRINTPREFIX "%d: SDTN: rejected SDTR\n", dsa->target);
+ //async:
+ KPRINT(PRINTPREFIX "%d: SDTN: async\n", dsa->target);
+ setasync(dsa, c, dsa->target);
+ *cont = -2;
+ return;
+ }
+ break;
+ case WideInit:
+ switch (msg) {
+ case A_SIR_MSG_WDTR:
+ /* reply to my WDTR */
+ KPRINT(PRINTPREFIX "%d: WDTN: response %d\n",
+ dsa->target, n->scratcha[2]);
+ setwide(dsa, c, dsa->target, n->scratcha[2]);
+ *cont = -2;
+ return;
+ case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
+ /* target ignored ATN for message after IDENTIFY - not SCSI-II */
+ KPRINT(PRINTPREFIX "%d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
+ setwide(dsa, c, dsa->target, 0);
+ *cont = E_to_decisions;
+ return;
+ case A_SIR_MSG_REJECT:
+ /* rejection of my SDTR */
+ KPRINT(PRINTPREFIX "%d: WDTN: rejected WDTR\n", dsa->target);
+ setwide(dsa, c, dsa->target, 0);
+ *cont = -2;
+ return;
+ }
+ break;
+
+ case NeitherDone:
+ case WideDone:
+ case BothDone:
+ switch (msg) {
+ case A_SIR_MSG_WDTR: {
+ uchar hiswide, mywide;
+ hiswide = n->scratcha[2];
+ mywide = (c->v->feature & Wide) != 0;
+ KPRINT(PRINTPREFIX "%d: WDTN: target init %d\n",
+ dsa->target, hiswide);
+ if (hiswide < mywide)
+ mywide = hiswide;
+ KPRINT(PRINTPREFIX "%d: WDTN: responding %d\n",
+ dsa->target, mywide);
+ setwide(dsa, c, dsa->target, mywide);
+ len = buildwdtrmsg(dsa->msg_out, mywide);
+ setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
+ *cont = E_response;
+ c->s[dsa->target] = WideResponse;
+ return;
+ }
+ case A_SIR_MSG_SDTR:
+#ifdef ASYNC_ONLY
+ *cont = E_reject;
+ return;
+#else
+ /* target decides to renegotiate */
+ histpf = n->scratcha[2];
+ hisreqack = n->scratcha[3];
+ KPRINT(PRINTPREFIX "%d: SDTN: target init %d %d\n",
+ dsa->target, histpf, hisreqack);
+ if (hisreqack == 0) {
+ /* he wants asynchronous */
+ setasync(dsa, c, dsa->target);
+ tpf = 0;
+ }
+ else {
+ /* he wants synchronous */
+ tpf = chooserate(c, histpf, &scf, &xferp);
+ if (hisreqack > c->v->maxsyncoff)
+ hisreqack = c->v->maxsyncoff;
+ KPRINT(PRINTPREFIX "%d: using %d %d\n",
+ dsa->target, tpf, hisreqack);
+ setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
+ }
+ /* build my SDTR message */
+ len = buildsdtrmsg(dsa->msg_out, tpf, hisreqack);
+ setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
+ *cont = E_response;
+ c->s[dsa->target] = SyncResponse;
+ return;
+#endif
+ }
+ break;
+ case WideResponse:
+ switch (msg) {
+ case A_SIR_EV_RESPONSE_OK:
+ c->s[dsa->target] = WideDone;
+ KPRINT(PRINTPREFIX "%d: WDTN: response accepted\n", dsa->target);
+ *cont = -2;
+ return;
+ case A_SIR_MSG_REJECT:
+ setwide(dsa, c, dsa->target, 0);
+ KPRINT(PRINTPREFIX "%d: WDTN: response REJECTed\n", dsa->target);
+ *cont = -2;
+ return;
+ }
+ break;
+ case SyncResponse:
+ switch (msg) {
+ case A_SIR_EV_RESPONSE_OK:
+ c->s[dsa->target] = BothDone;
+ KPRINT(PRINTPREFIX "%d: SDTN: response accepted (%s)\n",
+ dsa->target, phase[n->sstat1 & 7]);
+ *cont = -2;
+ return; /* chf */
+ case A_SIR_MSG_REJECT:
+ setasync(dsa, c, dsa->target);
+ KPRINT(PRINTPREFIX "%d: SDTN: response REJECTed\n", dsa->target);
+ *cont = -2;
+ return;
+ }
+ break;
+ }
+ KPRINT(PRINTPREFIX "%d: msgsm: state %d msg %d\n",
+ dsa->target, c->s[dsa->target], msg);
+ *wakeme = 1;
+ return;
+}
+
+static void
+calcblockdma(Dsa *d, ulong base, ulong count)
+{
+ ulong blocks;
+ if (DEBUG(3))
+ blocks = 0;
+ else {
+ blocks = count / A_BSIZE;
+ if (blocks > 255)
+ blocks = 255;
+ }
+ d->dmablks = blocks;
+ d->dmaaddr[0] = base;
+ d->dmaaddr[1] = base >> 8;
+ d->dmaaddr[2] = base >> 16;
+ d->dmaaddr[3] = base >> 24;
+ setmovedata(&d->data_buf, base + blocks * A_BSIZE, count - blocks * A_BSIZE);
+ d->flag = legetl(d->data_buf.dbc) == 0;
+}
+
+static ulong
+read_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa)
+{
+ ulong dbc;
+ uchar dfifo = n->dfifo;
+ int inchip;
+
+ dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
+ if (n->ctest5 & (1 << 5))
+ inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
+ else
+ inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
+ if (inchip) {
+ IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: DMA FIFO = %d\n",
+ dsa->target, dsa->lun, inchip);
+ }
+ if (n->sxfer & SYNCOFFMASK(c)) {
+ /* SCSI FIFO */
+ uchar fifo = n->sstat1 >> 4;
+ if (c->v->maxsyncoff > 8)
+ fifo |= (n->sstat2 & (1 << 4));
+ if (fifo) {
+ inchip += fifo;
+ IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SCSI FIFO = %d\n",
+ dsa->target, dsa->lun, fifo);
+ }
+ }
+ else {
+ if (n->sstat0 & (1 << 7)) {
+ inchip++;
+ IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL full\n",
+ dsa->target, dsa->lun);
+ }
+ if (n->sstat2 & (1 << 7)) {
+ inchip++;
+ IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL msb full\n",
+ dsa->target, dsa->lun);
+ }
+ }
+ USED(inchip);
+ return dbc;
+}
+
+static ulong
+write_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa)
+{
+ ulong dbc;
+ uchar dfifo = n->dfifo;
+ int inchip;
+
+ dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
+ USED(dsa);
+ if (n->ctest5 & (1 << 5))
+ inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
+ else
+ inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
+#ifdef WMR_DEBUG
+ if (inchip) {
+ IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: DMA FIFO = %d\n",
+ dsa->target, dsa->lun, inchip);
+ }
+#endif
+ if (n->sstat0 & (1 << 5)) {
+ inchip++;
+#ifdef WMR_DEBUG
+ IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun);
+#endif
+ }
+ if (n->sstat2 & (1 << 5)) {
+ inchip++;
+#ifdef WMR_DEBUG
+ IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun);
+#endif
+ }
+ if (n->sxfer & SYNCOFFMASK(c)) {
+ /* synchronous SODR */
+ if (n->sstat0 & (1 << 6)) {
+ inchip++;
+#ifdef WMR_DEBUG
+ IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODR full\n",
+ dsa->target, dsa->lun);
+#endif
+ }
+ if (n->sstat2 & (1 << 6)) {
+ inchip++;
+#ifdef WMR_DEBUG
+ IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODR msb full\n",
+ dsa->target, dsa->lun);
+#endif
+ }
+ }
+ /* clear the dma fifo */
+ n->ctest3 |= (1 << 2);
+ /* wait till done */
+ while ((n->dstat & Dfe) == 0)
+ ;
+ return dbc + inchip;
+}
+
+static void
+sd53c8xxinterrupt(Ureg *ur, void *a)
+{
+ uchar istat, dstat;
+ ushort sist;
+ int wakeme = 0;
+ int cont = -1;
+ Dsa *dsa;
+ ulong dsapa;
+ Controller *c = a;
+ Ncr *n = c->n;
+
+ USED(ur);
+ if (DEBUG(1)) {
+ IPRINT(PRINTPREFIX "int\n");
+ }
+ ilock(c);
+ istat = n->istat;
+ if (istat & Intf) {
+ Dsa *d;
+ int wokesomething = 0;
+ if (DEBUG(1)) {
+ IPRINT(PRINTPREFIX "Intfly\n");
+ }
+ n->istat = Intf;
+ /* search for structures in A_STATE_DONE */
+ 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)) {
+ IPRINT(PRINTPREFIX "waking up dsa %lux\n", (ulong)d);
+ }
+ wakeup(d);
+ wokesomething = 1;
+ }
+ }
+ if (!wokesomething) {
+ IPRINT(PRINTPREFIX "nothing to wake up\n");
+ }
+ }
+
+ if ((istat & (Sip | Dip)) == 0) {
+ if (DEBUG(1)) {
+ IPRINT(PRINTPREFIX "int end %x\n", istat);
+ }
+ iunlock(c);
+ return;
+ }
+
+ sist = (n->sist1<<8)|n->sist0; /* BUG? can two-byte read be inconsistent? */
+ dstat = n->dstat;
+ 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)) {
+ IPRINT("sist = %.4x\n", sist);
+ }
+ if (sist & 0x80) {
+ ulong addr;
+ ulong sa;
+ ulong dbc;
+ ulong tbc;
+ int dmablks;
+ ulong dmaaddr;
+
+ addr = legetl(n->dsp);
+ sa = addr - c->scriptpa;
+ if (DEBUG(1) || DEBUG(2)) {
+ IPRINT(PRINTPREFIX "%d/%d: Phase Mismatch sa=%.8lux\n",
+ dsa->target, dsa->lun, sa);
+ }
+ /*
+ * now recover
+ */
+ if (sa == E_data_in_mismatch) {
+ /*
+ * though this is a failure in the residue, there may have been blocks
+ * as well. if so, dmablks will not have been zeroed, since the state
+ * was not saved by the microcode.
+ */
+ dbc = read_mismatch_recover(c, n, dsa);
+ tbc = legetl(dsa->data_buf.dbc) - dbc;
+ dsa->dmablks = 0;
+ n->scratcha[2] = 0;
+ advancedata(&dsa->data_buf, tbc);
+ if (DEBUG(1) || DEBUG(2)) {
+ IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n",
+ dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
+ }
+ cont = E_data_mismatch_recover;
+ }
+ else if (sa == E_data_in_block_mismatch) {
+ dbc = read_mismatch_recover(c, n, dsa);
+ tbc = A_BSIZE - dbc;
+ /* recover current state from registers */
+ dmablks = n->scratcha[2];
+ dmaaddr = legetl(n->scratchb);
+ /* we have got to dmaaddr + tbc */
+ /* we have dmablks * A_BSIZE - tbc + residue left to do */
+ /* so remaining transfer is */
+ IPRINT("in_block_mismatch: dmaaddr = 0x%lux tbc=%lud dmablks=%d\n",
+ dmaaddr, tbc, dmablks);
+ calcblockdma(dsa, dmaaddr + tbc,
+ dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
+ /* copy changes into scratch registers */
+ IPRINT("recalc: dmablks %d dmaaddr 0x%lx pa 0x%lx dbc %ld\n",
+ dsa->dmablks, legetl(dsa->dmaaddr),
+ legetl(dsa->data_buf.pa), legetl(dsa->data_buf.dbc));
+ n->scratcha[2] = dsa->dmablks;
+ lesetl(n->scratchb, dsa->dmancr);
+ cont = E_data_block_mismatch_recover;
+ }
+ else if (sa == E_data_out_mismatch) {
+ dbc = write_mismatch_recover(c, n, dsa);
+ tbc = legetl(dsa->data_buf.dbc) - dbc;
+ dsa->dmablks = 0;
+ n->scratcha[2] = 0;
+ advancedata(&dsa->data_buf, tbc);
+ if (DEBUG(1) || DEBUG(2)) {
+ IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n",
+ dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
+ }
+ cont = E_data_mismatch_recover;
+ }
+ else if (sa == E_data_out_block_mismatch) {
+ dbc = write_mismatch_recover(c, n, dsa);
+ tbc = legetl(dsa->data_buf.dbc) - dbc;
+ /* recover current state from registers */
+ dmablks = n->scratcha[2];
+ dmaaddr = legetl(n->scratchb);
+ /* we have got to dmaaddr + tbc */
+ /* we have dmablks blocks - tbc + residue left to do */
+ /* so remaining transfer is */
+ IPRINT("out_block_mismatch: dmaaddr = %lux tbc=%lud dmablks=%d\n",
+ dmaaddr, tbc, dmablks);
+ calcblockdma(dsa, dmaaddr + tbc,
+ dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
+ /* copy changes into scratch registers */
+ n->scratcha[2] = dsa->dmablks;
+ lesetl(n->scratchb, dsa->dmancr);
+ cont = E_data_block_mismatch_recover;
+ }
+ else if (sa == E_id_out_mismatch) {
+ /*
+ * target switched phases while attention held during
+ * message out. The possibilities are:
+ * 1. It didn't like the last message. This is indicated
+ * by the new phase being message_in. Use script to recover
+ *
+ * 2. It's not SCSI-II compliant. The new phase will be other
+ * than message_in. We should also indicate that the device
+ * is asynchronous, if it's the SDTR that got ignored
+ *
+ * For now, if the phase switch is not to message_in, and
+ * and it happens after IDENTIFY and before SDTR, we
+ * notify the negotiation state machine.
+ */
+ ulong lim = legetl(dsa->msg_out_buf.dbc);
+ uchar p = n->sstat1 & 7;
+ dbc = write_mismatch_recover(c, n, dsa);
+ tbc = lim - dbc;
+ IPRINT(PRINTPREFIX "%d/%d: msg_out_mismatch: %lud/%lud sent, phase %s\n",
+ dsa->target, dsa->lun, tbc, lim, phase[p]);
+ if (p != MessageIn && tbc == 1) {
+ msgsm(dsa, c, A_SIR_EV_PHASE_SWITCH_AFTER_ID, &cont, &wakeme);
+ }
+ else
+ cont = E_id_out_mismatch_recover;
+ }
+ else if (sa == E_cmd_out_mismatch) {
+ /*
+ * probably the command count is longer than the device wants ...
+ */
+ ulong lim = legetl(dsa->cmd_buf.dbc);
+ uchar p = n->sstat1 & 7;
+ dbc = write_mismatch_recover(c, n, dsa);
+ tbc = lim - dbc;
+ IPRINT(PRINTPREFIX "%d/%d: cmd_out_mismatch: %lud/%lud sent, phase %s\n",
+ dsa->target, dsa->lun, tbc, lim, phase[p]);
+ USED(p, tbc);
+ cont = E_to_decisions;
+ }
+ else {
+ IPRINT(PRINTPREFIX "%d/%d: ma sa=%.8lux wanted=%s got=%s\n",
+ dsa->target, dsa->lun, sa,
+ phase[n->dcmd & 7],
+ phase[n->sstat1 & 7]);
+ dumpncrregs(c, 1);
+ dsa->p9status = SDeio; /* chf */
+ wakeme = 1;
+ }
+ }
+ /*else*/ if (sist & 0x400) {
+ if (DEBUG(0)) {
+ IPRINT(PRINTPREFIX "%d/%d Sto\n", dsa->target, dsa->lun);
+ }
+ dsa->p9status = SDtimeout;
+ dsa->stateb = A_STATE_DONE;
+ coherence();
+ softreset(c);
+ cont = E_issue_check;
+ wakeme = 1;
+ }
+ if (sist & 0x1) {
+ IPRINT(PRINTPREFIX "%d/%d: parity error\n", dsa->target, dsa->lun);
+ dsa->parityerror = 1;
+ }
+ if (sist & 0x4) {
+ IPRINT(PRINTPREFIX "%s%d lun %d: unexpected disconnect\n",
+ c->sdev->name, dsa->target, dsa->lun);
+ dumpncrregs(c, 1);
+ //wakeme = 1;
+ dsa->p9status = SDeio;
+ }
+ }
+ if (istat & Dip) {
+ if (DEBUG(1)) {
+ IPRINT("dstat = %.2x\n", dstat);
+ }
+ /*else*/ if (dstat & Ssi) {
+ ulong w = legetl(n->dsp) - c->scriptpa;
+ IPRINT("[%lux]", w);
+ USED(w);
+ cont = -2; /* restart */
+ }
+ if (dstat & Sir) {
+ switch (legetl(n->dsps)) {
+ case A_SIR_MSG_IO_COMPLETE:
+ dsa->p9status = dsa->status;
+ wakeme = 1;
+ break;
+ case A_SIR_MSG_SDTR:
+ case A_SIR_MSG_WDTR:
+ case A_SIR_MSG_REJECT:
+ case A_SIR_EV_RESPONSE_OK:
+ msgsm(dsa, c, legetl(n->dsps), &cont, &wakeme);
+ break;
+ case A_SIR_MSG_IGNORE_WIDE_RESIDUE:
+ /* back up one in the data transfer */
+ IPRINT(PRINTPREFIX "%d/%d: ignore wide residue %d, WSR = %d\n",
+ dsa->target, dsa->lun, n->scratcha[1], n->scntl2 & 1);
+ if (dsa->flag == 2) {
+ IPRINT(PRINTPREFIX "%d/%d: transfer over; residue ignored\n",
+ dsa->target, dsa->lun);
+ }
+ else {
+ calcblockdma(dsa, legetl(dsa->dmaaddr) - 1,
+ dsa->dmablks * A_BSIZE + legetl(dsa->data_buf.dbc) + 1);
+ }
+ cont = -2;
+ break;
+ case A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT:
+ IPRINT(PRINTPREFIX "%d: not msg_in after reselect (%s)",
+ n->ssid & SSIDMASK(c), phase[n->sstat1 & 7]);
+ dsa = dsafind(c, n->ssid & SSIDMASK(c), -1, A_STATE_DISCONNECTED);
+ 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);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DISC:
+ IPRINT(PRINTPREFIX "%d/%d: disconnect:", dsa->target, dsa->lun);
+ goto dsadump;
+ case A_SIR_NOTIFY_STATUS:
+ IPRINT(PRINTPREFIX "%d/%d: status\n", dsa->target, dsa->lun);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_COMMAND:
+ IPRINT(PRINTPREFIX "%d/%d: commands\n", dsa->target, dsa->lun);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DATA_IN:
+ IPRINT(PRINTPREFIX "%d/%d: data in a %lx b %lx\n",
+ dsa->target, dsa->lun, legetl(n->scratcha), legetl(n->scratchb));
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_BLOCK_DATA_IN:
+ IPRINT(PRINTPREFIX "%d/%d: block data in: a2 %x b %lx\n",
+ dsa->target, dsa->lun, n->scratcha[2], legetl(n->scratchb));
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DATA_OUT:
+ IPRINT(PRINTPREFIX "%d/%d: data out\n", dsa->target, dsa->lun);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DUMP:
+ IPRINT(PRINTPREFIX "%d/%d: dump\n", dsa->target, dsa->lun);
+ dumpncrregs(c, 1);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DUMP2:
+ IPRINT(PRINTPREFIX "%d/%d: dump2:", dsa->target, dsa->lun);
+ IPRINT(" sa %lux", legetl(n->dsp) - c->scriptpa);
+ IPRINT(" dsa %lux", legetl(n->dsa));
+ IPRINT(" sfbr %ux", n->sfbr);
+ IPRINT(" a %lux", legetl(n->scratcha));
+ IPRINT(" b %lux", legetl(n->scratchb));
+ IPRINT(" ssid %ux", n->ssid);
+ IPRINT("\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_WAIT_RESELECT:
+ IPRINT(PRINTPREFIX "wait reselect\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_RESELECT:
+ IPRINT(PRINTPREFIX "reselect: ssid %.2x sfbr %.2x at %ld\n",
+ n->ssid, n->sfbr, TK2MS(m->ticks));
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_ISSUE:
+ 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));
+ IPRINT("\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_ISSUE_CHECK:
+ IPRINT(PRINTPREFIX "issue check\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_SIGP:
+ IPRINT(PRINTPREFIX "responded to SIGP\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DUMP_NEXT_CODE: {
+ 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++) {
+ IPRINT(" %.8lux", dsp[x]);
+ }
+ IPRINT("\n");
+ USED(dsp);
+ cont = -2;
+ break;
+ }
+ case A_SIR_NOTIFY_WSR:
+ IPRINT(PRINTPREFIX "%d/%d: WSR set\n", dsa->target, dsa->lun);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_LOAD_SYNC:
+ IPRINT(PRINTPREFIX "%d/%d: scntl=%.2x sxfer=%.2x\n",
+ dsa->target, dsa->lun, n->scntl3, n->sxfer);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_RESELECTED_ON_SELECT:
+ if (DEBUG(2)) {
+ IPRINT(PRINTPREFIX "%d/%d: reselected during select\n",
+ dsa->target, dsa->lun);
+ }
+ cont = -2;
+ break;
+ case A_error_reselected: /* dsa isn't valid here */
+ iprint(PRINTPREFIX "reselection error\n");
+ dumpncrregs(c, 1);
+ 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;
+ default:
+ IPRINT(PRINTPREFIX "%d/%d: script error %ld\n",
+ dsa->target, dsa->lun, legetl(n->dsps));
+ dumpncrregs(c, 1);
+ wakeme = 1;
+ }
+ }
+ /*else*/ if (dstat & Iid) {
+ 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",
+ target, lun,
+ addr, addr - c->scriptpa, dbc);
+ 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;
+ }
+ /*else*/ if (dstat & Bf) {
+ IPRINT(PRINTPREFIX "%d/%d: Bus Fault\n", dsa->target, dsa->lun);
+ dumpncrregs(c, 1);
+ dsa->p9status = SDeio;
+ wakeme = 1;
+ }
+ }
+ if (cont == -2)
+ ncrcontinue(c);
+ else if (cont >= 0)
+ start(c, cont);
+ if (wakeme){
+ if(dsa->p9status == SDnostatus)
+ dsa->p9status = SDeio;
+ wakeup(dsa);
+ }
+ iunlock(c);
+ if (DEBUG(1)) {
+ IPRINT(PRINTPREFIX "int end 1\n");
+ }
+}
+
+static int
+done(void *arg)
+{
+ return ((Dsa *)arg)->p9status != SDnostatus;
+}
+
+static void
+setmovedata(Movedata *d, ulong pa, ulong bc)
+{
+ d->pa[0] = pa;
+ d->pa[1] = pa>>8;
+ d->pa[2] = pa>>16;
+ d->pa[3] = pa>>24;
+ d->dbc[0] = bc;
+ d->dbc[1] = bc>>8;
+ d->dbc[2] = bc>>16;
+ d->dbc[3] = bc>>24;
+}
+
+static void
+advancedata(Movedata *d, long v)
+{
+ lesetl(d->pa, legetl(d->pa) + v);
+ lesetl(d->dbc, legetl(d->dbc) - v);
+}
+
+static void
+dumpwritedata(uchar *data, int datalen)
+{
+ int i;
+ uchar *bp;
+ if (!DEBUG(0)){
+ USED(data, datalen);
+ return;
+ }
+
+ if (datalen) {
+ KPRINT(PRINTPREFIX "write:");
+ for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++) {
+ KPRINT("%.2ux", *bp);
+ }
+ if (i < datalen) {
+ KPRINT("...");
+ }
+ KPRINT("\n");
+ }
+}
+
+static void
+dumpreaddata(uchar *data, int datalen)
+{
+ int i;
+ uchar *bp;
+ if (!DEBUG(0)){
+ USED(data, datalen);
+ return;
+ }
+
+ if (datalen) {
+ KPRINT(PRINTPREFIX "read:");
+ for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++) {
+ KPRINT("%.2ux", *bp);
+ }
+ if (i < datalen) {
+ KPRINT("...");
+ }
+ KPRINT("\n");
+ }
+}
+
+static void
+busreset(Controller *c)
+{
+ int x, ntarget;
+
+ /* bus reset */
+ c->n->scntl1 |= (1 << 3);
+ delay(500);
+ c->n->scntl1 &= ~(1 << 3);
+ if(!(c->v->feature & Wide))
+ ntarget = 8;
+ else
+ ntarget = MAXTARGET;
+ for (x = 0; x < ntarget; x++) {
+ setwide(0, c, x, 0);
+#ifndef ASYNC_ONLY
+ c->s[x] = NeitherDone;
+#endif
+ }
+ c->capvalid = 0;
+}
+
+static void
+reset(Controller *c)
+{
+ /* should wakeup all pending tasks */
+ softreset(c);
+ busreset(c);
+}
+
+static int
+sd53c8xxrio(SDreq* r)
+{
+ Dsa *d;
+ uchar *bp;
+ Controller *c;
+ uchar target_expo, my_expo;
+ int bc, check, i, status, target;
+
+ if((target = r->unit->subno) == 0x07)
+ return r->status = SDtimeout; /* assign */
+
+ c = r->unit->dev->ctlr;
+
+ check = 0;
+ d = dsaalloc(c, target, r->lun);
+
+ qlock(&c->q[target]); /* obtain access to target */
+docheck:
+ /* load the transfer control stuff */
+ d->scsi_id_buf[0] = 0;
+ d->scsi_id_buf[1] = c->sxfer[target];
+ d->scsi_id_buf[2] = target;
+ d->scsi_id_buf[3] = c->scntl3[target];
+ synctodsa(d, c);
+
+ bc = 0;
+
+ d->msg_out[bc] = 0x80 | r->lun;
+
+#ifndef NO_DISCONNECT
+ d->msg_out[bc] |= (1 << 6);
+#endif
+ bc++;
+
+ /* work out what to do about negotiation */
+ switch (c->s[target]) {
+ default:
+ KPRINT(PRINTPREFIX "%d: strange nego state %d\n", target, c->s[target]);
+ c->s[target] = NeitherDone;
+ /* fall through */
+ case NeitherDone:
+ if ((c->capvalid & (1 << target)) == 0)
+ break;
+ target_expo = (c->cap[target] >> 5) & 3;
+ my_expo = (c->v->feature & Wide) != 0;
+ if (target_expo < my_expo)
+ my_expo = target_expo;
+#ifdef ALWAYS_DO_WDTR
+ bc += buildwdtrmsg(d->msg_out + bc, my_expo);
+ KPRINT(PRINTPREFIX "%d: WDTN: initiating expo %d\n", target, my_expo);
+ c->s[target] = WideInit;
+ break;
+#else
+ if (my_expo) {
+ bc += buildwdtrmsg(d->msg_out + bc, (c->v->feature & Wide) ? 1 : 0);
+ KPRINT(PRINTPREFIX "%d: WDTN: initiating expo %d\n", target, my_expo);
+ c->s[target] = WideInit;
+ break;
+ }
+ KPRINT(PRINTPREFIX "%d: WDTN: narrow\n", target);
+ /* fall through */
+#endif
+ case WideDone:
+ if (c->cap[target] & (1 << 4)) {
+ KPRINT(PRINTPREFIX "%d: SDTN: initiating %d %d\n", target, c->tpf, c->v->maxsyncoff);
+ bc += buildsdtrmsg(d->msg_out + bc, c->tpf, c->v->maxsyncoff);
+ c->s[target] = SyncInit;
+ break;
+ }
+ KPRINT(PRINTPREFIX "%d: SDTN: async only\n", target);
+ c->s[target] = BothDone;
+ break;
+
+ case BothDone:
+ break;
+ }
+
+ setmovedata(&d->msg_out_buf, DMASEG(d->msg_out), bc);
+ setmovedata(&d->cmd_buf, DMASEG(r->cmd), r->clen);
+ calcblockdma(d, r->data ? DMASEG(r->data) : 0, r->dlen);
+
+ if (DEBUG(0)) {
+ KPRINT(PRINTPREFIX "%d/%d: exec: ", target, r->lun);
+ for (bp = r->cmd; bp < &r->cmd[r->clen]; bp++) {
+ KPRINT("%.2ux", *bp);
+ }
+ KPRINT("\n");
+ if (!r->write) {
+ KPRINT(PRINTPREFIX "%d/%d: exec: limit=(%d)%ld\n",
+ target, r->lun, d->dmablks, legetl(d->data_buf.dbc));
+ }
+ else
+ dumpwritedata(r->data, r->dlen);
+ }
+
+ setmovedata(&d->status_buf, DMASEG(&d->status), 1);
+
+ d->p9status = SDnostatus;
+ d->parityerror = 0;
+ coherence();
+ d->stateb = A_STATE_ISSUE; /* start operation */
+ coherence();
+
+ ilock(c);
+ if (c->ssm)
+ c->n->dcntl |= 0x10; /* single step */
+ if (c->running) {
+ c->n->istat = Sigp;
+ }
+ else {
+ start(c, E_issue_check);
+ }
+ iunlock(c);
+
+ while(waserror())
+ ;
+ tsleep(d, done, d, 600 * 1000);
+ poperror();
+
+ if (!done(d)) {
+ KPRINT(PRINTPREFIX "%d/%d: exec: Timed out\n", target, r->lun);
+ dumpncrregs(c, 0);
+ dsafree(c, d);
+ reset(c);
+ qunlock(&c->q[target]);
+ r->status = SDtimeout;
+ return r->status = SDtimeout; /* assign */
+ }
+
+ if((status = d->p9status) == SDeio)
+ c->s[target] = NeitherDone;
+ if (d->parityerror) {
+ status = SDeio;
+ }
+
+ /*
+ * adjust datalen
+ */
+ r->rlen = r->dlen;
+ if (DEBUG(0)) {
+ KPRINT(PRINTPREFIX "%d/%d: exec: before rlen adjust: dmablks %d flag %d dbc %lud\n",
+ target, r->lun, d->dmablks, d->flag, legetl(d->data_buf.dbc));
+ }
+ r->rlen = r->dlen;
+ if (d->flag != 2) {
+ r->rlen -= d->dmablks * A_BSIZE;
+ r->rlen -= legetl(d->data_buf.dbc);
+ }
+ if(!r->write)
+ dumpreaddata(r->data, r->rlen);
+ if (DEBUG(0)) {
+ KPRINT(PRINTPREFIX "%d/%d: exec: p9status=%d status %d rlen %ld\n",
+ target, r->lun, d->p9status, status, r->rlen);
+ }
+ /*
+ * spot the identify
+ */
+ if ((c->capvalid & (1 << target)) == 0
+ && (status == SDok || status == SDcheck)
+ && r->cmd[0] == 0x12 && r->dlen >= 8) {
+ c->capvalid |= 1 << target;
+ bp = r->data;
+ c->cap[target] = bp[7];
+ KPRINT(PRINTPREFIX "%d: capabilities %.2x\n", target, bp[7]);
+ }
+ if(!check && status == SDcheck && !(r->flags & SDnosense)){
+ check = 1;
+ r->write = 0;
+ memset(r->cmd, 0, sizeof(r->cmd));
+ r->cmd[0] = 0x03;
+ r->cmd[1] = r->lun<<5;
+ r->cmd[4] = sizeof(r->sense)-1;
+ r->clen = 6;
+ r->data = r->sense;
+ r->dlen = sizeof(r->sense)-1;
+ /*
+ * Clear out the microcode state
+ * so the Dsa can be re-used.
+ */
+ lesetl(&d->stateb, A_STATE_ALLOCATED);
+ coherence();
+ goto docheck;
+ }
+ qunlock(&c->q[target]);
+ dsafree(c, d);
+
+ if(status == SDok && check){
+ status = SDcheck;
+ r->flags |= SDvalidsense;
+ }
+ if(DEBUG(0))
+ KPRINT(PRINTPREFIX "%d: r flags %8.8uX status %d rlen %ld\n",
+ target, r->flags, status, r->rlen);
+ if(r->flags & SDvalidsense){
+ if(!DEBUG(0))
+ KPRINT(PRINTPREFIX "%d: r flags %8.8uX status %d rlen %ld\n",
+ target, r->flags, status, r->rlen);
+ for(i = 0; i < r->rlen; i++)
+ KPRINT(" %2.2uX", r->sense[i]);
+ KPRINT("\n");
+ }
+ return r->status = status;
+}
+
+static void
+cribbios(Controller *c)
+{
+ c->bios.scntl3 = c->n->scntl3;
+ c->bios.stest2 = c->n->stest2;
+ print(PRINTPREFIX "%s: bios scntl3(%.2x) stest2(%.2x)\n",
+ c->sdev->name, c->bios.scntl3, c->bios.stest2);
+}
+
+static int
+bios_set_differential(Controller *c)
+{
+ /* Concept lifted from FreeBSD - thanks Gerard */
+ /* basically, if clock conversion factors are set, then there is
+ * evidence the bios had a go at the chip, and if so, it would
+ * have set the differential enable bit in stest2
+ */
+ return (c->bios.scntl3 & 7) != 0 && (c->bios.stest2 & 0x20) != 0;
+}
+
+#define NCR_VID 0x1000
+#define NCR_810_DID 0x0001
+#define NCR_820_DID 0x0002 /* don't know enough about this one to support it */
+#define NCR_825_DID 0x0003
+#define NCR_815_DID 0x0004
+#define SYM_810AP_DID 0x0005
+#define SYM_860_DID 0x0006
+#define SYM_896_DID 0x000b
+#define SYM_895_DID 0x000c
+#define SYM_885_DID 0x000d /* ditto */
+#define SYM_875_DID 0x000f /* ditto */
+#define SYM_1010_DID 0x0020
+#define SYM_1011_DID 0x0021
+#define SYM_875J_DID 0x008f
+
+static Variant variant[] = {
+{ NCR_810_DID, 0x0f, "NCR53C810", Burst16, 8, 24, 0 },
+{ NCR_810_DID, 0x1f, "SYM53C810ALV", Burst16, 8, 24, Prefetch },
+{ NCR_810_DID, 0xff, "SYM53C810A", Burst16, 8, 24, Prefetch },
+{ SYM_810AP_DID, 0xff, "SYM53C810AP", Burst16, 8, 24, Prefetch },
+{ NCR_815_DID, 0xff, "NCR53C815", Burst16, 8, 24, BurstOpCodeFetch },
+{ NCR_825_DID, 0x0f, "NCR53C825", Burst16, 8, 24, Wide|BurstOpCodeFetch|Differential },
+{ NCR_825_DID, 0xff, "SYM53C825A", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide },
+{ SYM_860_DID, 0x0f, "SYM53C860", Burst16, 8, 24, Prefetch|Ultra },
+{ SYM_860_DID, 0xff, "SYM53C860LV", Burst16, 8, 24, Prefetch|Ultra },
+{ SYM_875_DID, 0x01, "SYM53C875r1", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra },
+{ SYM_875_DID, 0xff, "SYM53C875", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
+{ SYM_875J_DID, 0xff, "SYM53C875j", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
+{ SYM_885_DID, 0xff, "SYM53C885", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|ClockDouble },
+{ SYM_895_DID, 0xff, "SYM53C895", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+{ SYM_896_DID, 0xff, "SYM53C896", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+{ SYM_1010_DID, 0xff, "SYM53C1010", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+{ SYM_1011_DID, 0xff, "SYM53C1010", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+};
+
+static int
+xfunc(Controller *c, enum na_external x, unsigned long *v)
+{
+ switch (x) {
+ default:
+ print("xfunc: can't find external %d\n", x);
+ return 0;
+ case X_scsi_id_buf:
+ *v = offsetof(Dsa, scsi_id_buf[0]);
+ break;
+ case X_msg_out_buf:
+ *v = offsetof(Dsa, msg_out_buf);
+ break;
+ case X_cmd_buf:
+ *v = offsetof(Dsa, cmd_buf);
+ break;
+ case X_data_buf:
+ *v = offsetof(Dsa, data_buf);
+ break;
+ case X_status_buf:
+ *v = offsetof(Dsa, status_buf);
+ break;
+ case X_dsa_head:
+ *v = DMASEG(&c->dsalist.head[0]);
+ break;
+ case X_ssid_mask:
+ *v = SSIDMASK(c);
+ break;
+ }
+ return 1;
+}
+
+static int
+na_fixup(Controller *c, ulong pa_reg,
+ struct na_patch *patch, int patches,
+ int (*externval)(Controller*, int, ulong*))
+{
+ int p;
+ int v;
+ ulong *script, pa_script;
+ unsigned long lw, lv;
+
+ script = c->script;
+ pa_script = c->scriptpa;
+ for (p = 0; p < patches; p++) {
+ switch (patch[p].type) {
+ case 1:
+ /* script relative */
+ script[patch[p].lwoff] += pa_script;
+ break;
+ case 2:
+ /* register i/o relative */
+ script[patch[p].lwoff] += pa_reg;
+ break;
+ case 3:
+ /* data external */
+ lw = script[patch[p].lwoff];
+ v = (lw >> 8) & 0xff;
+ if (!(*externval)(c, v, &lv))
+ return 0;
+ v = lv & 0xff;
+ script[patch[p].lwoff] = (lw & 0xffff00ffL) | (v << 8);
+ break;
+ case 4:
+ /* 32 bit external */
+ lw = script[patch[p].lwoff];
+ if (!(*externval)(c, lw, &lv))
+ return 0;
+ script[patch[p].lwoff] = lv;
+ break;
+ case 5:
+ /* 24 bit external */
+ lw = script[patch[p].lwoff];
+ if (!(*externval)(c, lw & 0xffffff, &lv))
+ return 0;
+ script[patch[p].lwoff] = (lw & 0xff000000L) | (lv & 0xffffffL);
+ break;
+ }
+ }
+ return 1;
+}
+
+static SDev*
+sd53c8xxpnp(void)
+{
+ char *cp;
+ Pcidev *p;
+ Variant *v;
+ int ba, nctlr;
+ void *scriptma;
+ Controller *ctlr;
+ SDev *sdev, *head, *tail;
+ ulong regpa, *script, scriptpa;
+ void *regva, *scriptva;
+
+ if(cp = getconf("*maxsd53c8xx"))
+ nctlr = strtoul(cp, 0, 0);
+ else
+ nctlr = 32;
+
+ p = nil;
+ head = tail = nil;
+ while((p = pcimatch(p, NCR_VID, 0)) != nil && nctlr > 0){
+ for(v = variant; v < &variant[nelem(variant)]; v++){
+ if(p->did == v->did && p->rid <= v->maxrid)
+ break;
+ }
+ if(v >= &variant[nelem(variant)]) {
+ print("no match\n");
+ continue;
+ }
+ print(PRINTPREFIX "%s rev. 0x%2.2x intr=%d command=%4.4uX\n",
+ v->name, p->rid, p->intl, p->pcr);
+
+ regpa = p->mem[1].bar;
+ ba = 2;
+ if(regpa & 0x04){
+ if(p->mem[2].bar)
+ continue;
+ ba++;
+ }
+ 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){
+ vunmap(regva, p->mem[1].size);
+ continue;
+ }
+ scriptpa &= ~0x0F;
+ scriptva = vmap(scriptpa, p->mem[ba].size);
+ if(scriptva)
+ script = scriptva;
+ }
+ if(scriptpa == 0){
+ /*
+ * Either the map failed, or this chip does not have
+ * local RAM. It will need a copy of the microcode.
+ */
+ scriptma = malloc(sizeof(na_script));
+ if(scriptma == nil){
+ vunmap(regva, p->mem[1].size);
+ continue;
+ }
+ scriptpa = DMASEG(scriptma);
+ script = scriptma;
+ }
+
+ ctlr = malloc(sizeof(Controller));
+ sdev = malloc(sizeof(SDev));
+ if(ctlr == nil || sdev == nil){
+buggery:
+ if(ctlr)
+ free(ctlr);
+ if(sdev)
+ free(sdev);
+ if(scriptma)
+ free(scriptma);
+ else if(scriptva)
+ vunmap(scriptva, p->mem[ba].size);
+ if(regva)
+ vunmap(regva, p->mem[1].size);
+ continue;
+ }
+
+ if(dsaend == nil)
+ dsaend = xalloc(sizeof *dsaend);
+ if(dsaend == nil)
+ panic("sd53c8xxpnp: no memory");
+ 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));
+
+ /*
+ * Because we don't yet have an abstraction for the
+ * addresses as seen from the controller side (and on
+ * the 386 it doesn't matter), the following two lines
+ * are different between the 386 and alpha copies of
+ * this driver.
+ */
+ ctlr->scriptpa = scriptpa;
+ if(!na_fixup(ctlr, regpa, na_patches, NA_PATCHES, xfunc)){
+ print("script fixup failed\n");
+ goto buggery;
+ }
+ swabl(ctlr->script, ctlr->script, sizeof(na_script));
+
+ 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
+ head = sdev;
+ tail = sdev;
+
+ nctlr--;
+ }
+
+ return head;
+}
+
+static int
+sd53c8xxenable(SDev* sdev)
+{
+ Pcidev *pcidev;
+ Controller *ctlr;
+ char name[32];
+
+ ctlr = sdev->ctlr;
+ pcidev = ctlr->pcidev;
+
+ pcisetbme(pcidev);
+
+ 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;
+}
+
+SDifc sd53c8xxifc = {
+ "53c8xx", /* name */
+
+ sd53c8xxpnp, /* pnp */
+ nil, /* legacy */
+ sd53c8xxenable, /* enable */
+ nil, /* disable */
+
+ scsiverify, /* verify */
+ scsionline, /* online */
+ sd53c8xxrio, /* rio */
+ nil, /* rctl */
+ nil, /* wctl */
+
+ scsibio, /* bio */
+ nil, /* probe */
+ nil, /* clear */
+ nil, /* rtopctl */
+ nil, /* wtopctl */
+};
diff --git a/sys/src/9/pc/sd53c8xx.n b/sys/src/9/pc/sd53c8xx.n
new file mode 100755
index 000000000..3f660abaf
--- /dev/null
+++ b/sys/src/9/pc/sd53c8xx.n
@@ -0,0 +1,459 @@
+// NCR 53c8xx driver for Plan 9
+// Nigel Roles (nigel@9fs.org)
+//
+// Microcode
+//
+// 27/5/02 Fixed problems with transfers >= 256 * 512
+//
+// 13/3/01 Fixed microcode to support targets > 7
+//
+
+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
+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
+
+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
+//BSIZE=4096
+
+ // idle:
+ jump wait_for_reselection
+start:
+ call load_sync
+// move 13 to ctest0
+// 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 // why is this here?
+start1:
+// move 14 to ctest0
+ move from msg_out_buf, when msg_out
+id_out_mismatch:
+ jump start1, when msg_out // repeat on parity grounds
+ jump to_decisions, when not cmd
+cmd_phase:
+// int SIR_NOTIFY_COMMAND
+ clear atn
+ move from cmd_buf, when cmd
+cmd_out_mismatch:
+ jump to_decisions, when not data_in
+data_in_phase:
+ move memory 4, state, scratcha
+ move memory 4, dmaaddr, scratchb
+// int SIR_NOTIFY_DATA_IN
+data_in_block_loop:
+ move scratcha2 to sfbr
+ jump data_in_normal, if 0
+// int SIR_NOTIFY_BLOCK_DATA_IN
+ move BSIZE, ptr dmaaddr, when data_in // transfer BSIZE bytes
+data_in_block_mismatch:
+ move scratchb1 + BSIZE / 256 to scratchb1 // add BSIZE to scratchb
+ move scratchb2 + 0 to scratchb2 with carry
+ move scratchb3 + 0 to scratchb3 with carry
+ move scratcha2 + 255 to scratcha2 // sub one from block count
+ move memory 4, scratchb, dmaaddr // save latest dmaddr
+ jump data_in_block_loop, when data_in
+ move memory 4, scratcha, state // save latest state
+ call save_state
+ jump to_decisions
+data_block_mismatch_recover:
+ move memory 4, scratchb, dmaaddr // save latest dmaddr
+data_mismatch_recover:
+ move memory 4, scratcha, state // save latest state
+ jump to_decisions // no need to save
+ // as interrupt routine
+ // did this
+data_in_normal:
+ move scratcha3 to sfbr
+ int error_too_much_data, if not 0
+ move from data_buf, when data_in
+data_in_mismatch:
+ move 2 to scratcha3
+ move memory 4, scratcha, state
+ call save_state
+ jump post_data_to_decisions
+data_out_phase:
+// int SIR_NOTIFY_DATA_OUT
+ move memory 4, state, scratcha
+ move memory 4, dmaaddr, scratchb
+data_out_block_loop:
+ move scratcha2 to sfbr
+ jump data_out_normal, if 0
+ move memory 4, dmaaddr, scratchb
+ move BSIZE, ptr dmaaddr, when data_out // transfer BSIZE bytes
+data_out_block_mismatch:
+ move scratchb1 + BSIZE / 256 to scratchb1 // add BSIZE to scratchb
+ move scratchb2 + 0 to scratchb2 with carry
+ move scratchb3 + 0 to scratchb3 with carry
+ move scratcha2 + 255 to scratcha2 // sub one from block count
+ move memory 4, scratchb, dmaaddr // save latest dmaddr
+ jump data_out_block_loop, when data_out
+ move memory 4, scratcha, state // save latest state
+ jump to_decisions
+data_out_normal:
+ move scratcha3 to sfbr
+ int error_too_little_data, if not 0
+ move from data_buf, when data_out
+data_out_mismatch:
+ move 2 to scratcha3
+ move memory 4, scratcha, state
+ call save_state
+ jump post_data_to_decisions
+status_phase:
+ move from status_buf, when status
+// int SIR_NOTIFY_STATUS
+ int error_unexpected_phase, when not msg_in
+msg_in_phase:
+ move 1, scratcha, when msg_in
+// int SIR_NOTIFY_MSG_IN
+ jump rejected, if MSG_REJECT
+msg_in_not_reject:
+ jump disconnected, if MSG_DISCONNECT
+ jump msg_in_skip, if MSG_SAVE_DATA_POINTER
+ jump msg_in_skip, if MSG_RESTORE_POINTERS
+ jump ignore_wide, if MSG_IGNORE_WIDE_RESIDUE
+ jump extended, if X_MSG
+ int error_not_cmd_complete, if not 0
+ move scntl2&0x7e to scntl2 // take care not to clear WSR
+ clear ack
+ wait disconnect
+ // update state
+ move memory 4, state, scratcha
+ move STATE_DONE to scratcha0
+ move RESULT_OK to scratcha1
+ move memory 4, scratcha, state
+ call save_state
+// int SIR_MSG_IO_COMPLETE
+ intfly 0
+ jump issue_check
+
+rejected:
+ int SIR_MSG_REJECT
+ clear ack
+ jump to_decisions
+msg_in_skip:
+ clear ack
+ jump to_decisions
+
+extended:
+ clear ack
+ int error_unexpected_phase, when not msg_in
+ move 1, scratcha1, when msg_in
+ jump ext_3, if 3
+ jump ext_2, if 2
+ int error_weird_message, if not 1
+ext_1:
+ clear ack
+ int error_unexpected_phase, when not msg_in
+ move 1, scratcha1, when msg_in
+ jump ext_done
+
+ext_3: clear ack
+ int error_unexpected_phase, when not msg_in
+ move 1, scratcha1, when msg_in
+ clear ack
+ int error_unexpected_phase, when not msg_in
+ move 1, scratcha2, when msg_in
+ clear ack
+ int error_unexpected_phase, when not msg_in
+ move 1, scratcha3, when msg_in
+ move scratcha1 to sfbr
+ jump ext_done, if not X_MSG_SDTR
+
+// the target sent SDTR - leave ACK asserted and signal kernel
+// kernel will either restart at reject, or continue
+sdtr: int SIR_MSG_SDTR
+ clear ack
+ jump to_decisions
+
+ext_2: clear ack
+ int error_unexpected_phase, when not msg_in
+ move 1, scratcha1, when msg_in
+ clear ack
+ int error_unexpected_phase, when not msg_in
+ move 1, scratcha2, when msg_in
+ move scratcha1 to sfbr
+ jump ext_done, if not X_MSG_WDTR
+
+wdtr: int SIR_MSG_WDTR
+ clear ack
+ jump to_decisions
+
+ext_done:
+// ought to check message here, but instead reject all
+// NB ATN set
+reject:
+ set atn // get target's ATN
+ clear ack // finish ACK
+ move MSG_REJECT to scratcha // prepare message
+ int error_unexpected_phase, when not msg_out// didn't get ATN
+ clear atn // last byte coming
+ move 1, scratcha, when msg_out // send byte
+ clear ack // finish ACK
+ jump reject, when msg_out // parity error
+ jump to_decisions
+
+ignore_wide:
+ clear ack
+ int error_unexpected_phase, when not msg_in
+ move 1, scratcha1, when msg_in
+ int SIR_MSG_IGNORE_WIDE_RESIDUE
+ clear ack
+ jump to_decisions
+
+// sends a response to a message
+response:
+ set atn
+ clear ack
+ int error_unexpected_phase, when not msg_out
+response_repeat:
+ move from msg_out_buf, when msg_out
+ jump response_repeat, when msg_out // repeat on parity grounds
+// now look for response
+// msg_in could be a REJECT
+// anything other message is something else so signal kernel first
+ jump response_msg_in, when msg_in
+ int SIR_EV_RESPONSE_OK // not a MSG_IN so OK
+ jump to_decisions
+
+response_msg_in:
+ move 1, scratcha, when msg_in
+ jump rejected, if MSG_REJECT // go and generate rej interrupt
+ int SIR_EV_RESPONSE_OK // not a REJECT so OK
+ jump msg_in_not_reject // try others
+
+disconnected:
+// move 5 to ctest0
+ move scntl2&0x7e to scntl2 // don't clear WSR
+ clear ack
+ wait disconnect
+ // UPDATE state to disconnected
+ move memory 4, state, scratcha
+ move STATE_DISCONNECTED to scratcha0
+ move memory 4, scratcha, state
+ call save_state
+wsr_check:
+ move scntl2&0x01 to sfbr
+ int SIR_NOTIFY_WSR, if not 0
+// int SIR_NOTIFY_DISC
+ jump issue_check
+
+reselected_on_select:
+ int SIR_NOTIFY_RESELECTED_ON_SELECT
+ jump reselected
+
+wait_for_reselection:
+// move 11 to ctest0
+// int SIR_NOTIFY_WAIT_RESELECT
+ wait reselect sigp_set
+reselected:
+// move 12 to ctest0
+ clear target
+ int SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT, when not msg_in
+ move 1, scratchb, when msg_in
+ int error_not_identify_after_reselect, if not MSG_IDENTIFY and mask 0x1f
+// int SIR_NOTIFY_RESELECT
+ // now locate the right DSA - note do not clear ACK, so target doesn't start
+ // synchronous transfer until we are ready
+find_dsa:
+// move 6 to ctest0
+ move memory 4, dsa_head, dsa
+find_dsa_loop:
+// move 7 to ctest0
+// 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:
+ jump find_dsa_next, if not 255 // jump if not matched
+ move memory 1, lun, find_dsa_smc2 // forge lun comparison instruction
+ move scratchb0 to sfbr // recover IDENTIFY message
+find_dsa_smc2:
+ jump reload_sync, if 255 and mask ~7 // off we jolly well go
+find_dsa_next:
+ move memory 4, next, dsa // find next
+ jump find_dsa_loop
+
+// 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
+ int SIR_MSG_REJECT
+ jump to_decisions
+
+// Reload synchronous registers after a reconnect. If the transfer is a synchronous read, then
+// as soon as we clear ACK, the target will switch to data_in and start blasting data into the
+// fifo. We need to be executing the 'jump when data_in' instruction before the target stops REQing
+// since it is the REQ which latches the 'when'. The target will do 16 REQs before stopping, so
+// we have 16 bytes (160uS) plus delays to do this after clearing ACK. Once the jump is executing,
+// the target will wait, so as much debugging as you like can happen in data_in_phase, just don't
+// stick any delays between 'clear ack' and 'jump data_in_phase, when data_in'.
+
+reload_sync:
+ call load_sync
+ clear ack
+to_decisions:
+ jump data_in_phase, when data_in
+ jump cmd_phase, if cmd
+ jump data_out_phase, if data_out
+ 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
+ int error_unexpected_phase
+
+//
+// MULTI_TARGET
+//
+// following must mirror top of dsa structure
+// the first section is loaded and saved, the
+// second section loaded only
+dsa_copy:
+state: defw 0 // a0 is state, a1 result, a2 dma block count
+dmaaddr: defw 0 // dma address for block moves
+dsa_save_end:
+targ: defw 0 // lsb is target
+lun: defw 0 // lsb is lun
+sync: defw 0 // lsb is scntl3, sxfer
+next: defw 0
+dsa_load_end:
+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
+load_state_smc0:
+ move memory dsa_load_len, 0, dsa_copy
+// move 20 to ctest0
+ return
+save_state:
+ move memory 4, dsa, save_state_smc0 + 8
+save_state_smc0:
+ move memory dsa_save_len, dsa_copy, 0
+ return
+
+sigp_set:
+// int SIR_NOTIFY_SIGP
+ move ctest2 to sfbr // clear SIGP
+issue_check:
+// int SIR_NOTIFY_ISSUE_CHECK
+// move 1 to ctest0
+ move memory 4, dsa_head, dsa
+issue_check_loop:
+ 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
+ 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
+ return
diff --git a/sys/src/9/pc/sdata.c b/sys/src/9/pc/sdata.c
new file mode 100755
index 000000000..21b289db9
--- /dev/null
+++ b/sys/src/9/pc/sdata.c
@@ -0,0 +1,2304 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+#include "../port/sd.h"
+
+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
+
+extern SDifc sdataifc;
+
+enum {
+ DbgCONFIG = 0x0001, /* detected drive config info */
+ DbgIDENTIFY = 0x0002, /* detected drive identify info */
+ DbgSTATE = 0x0004, /* dump state on panic */
+ DbgPROBE = 0x0008, /* trace device probing */
+ DbgDEBUG = 0x0080, /* the current problem... */
+ DbgINL = 0x0100, /* That Inil20+ message we hate */
+ Dbg48BIT = 0x0200, /* 48-bit LBA */
+ DbgBsy = 0x0400, /* interrupt but Bsy (shared IRQ) */
+};
+#define DEBUG (DbgDEBUG|DbgSTATE)
+
+enum { /* I/O ports */
+ Data = 0,
+ Error = 1, /* (read) */
+ Features = 1, /* (write) */
+ Count = 2, /* sector count<7-0>, sector count<15-8> */
+ Ir = 2, /* interrupt reason (PACKET) */
+ Sector = 3, /* sector number */
+ Lbalo = 3, /* LBA<7-0>, LBA<31-24> */
+ Cyllo = 4, /* cylinder low */
+ Bytelo = 4, /* byte count low (PACKET) */
+ Lbamid = 4, /* LBA<15-8>, LBA<39-32> */
+ Cylhi = 5, /* cylinder high */
+ Bytehi = 5, /* byte count hi (PACKET) */
+ Lbahi = 5, /* LBA<23-16>, LBA<47-40> */
+ Dh = 6, /* Device/Head, LBA<27-24> */
+ Status = 7, /* (read) */
+ Command = 7, /* (write) */
+
+ As = 2, /* Alternate Status (read) */
+ Dc = 2, /* Device Control (write) */
+};
+
+enum { /* Error */
+ Med = 0x01, /* Media error */
+ Ili = 0x01, /* command set specific (PACKET) */
+ Nm = 0x02, /* No Media */
+ Eom = 0x02, /* command set specific (PACKET) */
+ Abrt = 0x04, /* Aborted command */
+ Mcr = 0x08, /* Media Change Request */
+ Idnf = 0x10, /* no user-accessible address */
+ Mc = 0x20, /* Media Change */
+ Unc = 0x40, /* Uncorrectable data error */
+ Wp = 0x40, /* Write Protect */
+ Icrc = 0x80, /* Interface CRC error */
+};
+
+enum { /* Features */
+ Dma = 0x01, /* data transfer via DMA (PACKET) */
+ Ovl = 0x02, /* command overlapped (PACKET) */
+};
+
+enum { /* Interrupt Reason */
+ Cd = 0x01, /* Command/Data */
+ Io = 0x02, /* I/O direction */
+ Rel = 0x04, /* Bus Release */
+};
+
+enum { /* Device/Head */
+ Dev0 = 0xA0, /* Master */
+ Dev1 = 0xB0, /* Slave */
+ Lba = 0x40, /* LBA mode */
+};
+
+enum { /* Status, Alternate Status */
+ Err = 0x01, /* Error */
+ Chk = 0x01, /* Check error (PACKET) */
+ Drq = 0x08, /* Data Request */
+ Dsc = 0x10, /* Device Seek Complete */
+ Serv = 0x10, /* Service */
+ Df = 0x20, /* Device Fault */
+ Dmrd = 0x20, /* DMA ready (PACKET) */
+ Drdy = 0x40, /* Device Ready */
+ Bsy = 0x80, /* Busy */
+};
+
+enum { /* Command */
+ Cnop = 0x00, /* NOP */
+ Cdr = 0x08, /* Device Reset */
+ Crs = 0x20, /* Read Sectors */
+ Crs48 = 0x24, /* Read Sectors Ext */
+ Crd48 = 0x25, /* Read w/ DMA Ext */
+ Crdq48 = 0x26, /* Read w/ DMA Queued Ext */
+ Crsm48 = 0x29, /* Read Multiple Ext */
+ Cws = 0x30, /* Write Sectors */
+ Cws48 = 0x34, /* Write Sectors Ext */
+ Cwd48 = 0x35, /* Write w/ DMA Ext */
+ Cwdq48 = 0x36, /* Write w/ DMA Queued Ext */
+ Cwsm48 = 0x39, /* Write Multiple Ext */
+ Cedd = 0x90, /* Execute Device Diagnostics */
+ Cpkt = 0xA0, /* Packet */
+ Cidpkt = 0xA1, /* Identify Packet Device */
+ Crsm = 0xC4, /* Read Multiple */
+ Cwsm = 0xC5, /* Write Multiple */
+ Csm = 0xC6, /* Set Multiple */
+ Crdq = 0xC7, /* Read DMA queued */
+ Crd = 0xC8, /* Read DMA */
+ Cwd = 0xCA, /* Write DMA */
+ Cwdq = 0xCC, /* Write DMA queued */
+ Cstandby = 0xE2, /* Standby */
+ Cid = 0xEC, /* Identify Device */
+ Csf = 0xEF, /* Set Features */
+};
+
+enum { /* Device Control */
+ Nien = 0x02, /* (not) Interrupt Enable */
+ Srst = 0x04, /* Software Reset */
+ Hob = 0x80, /* High Order Bit [sic] */
+};
+
+enum { /* PCI Configuration Registers */
+ Bmiba = 0x20, /* Bus Master Interface Base Address */
+ Idetim = 0x40, /* IE Timing */
+ Sidetim = 0x44, /* Slave IE Timing */
+ Udmactl = 0x48, /* Ultra DMA/33 Control */
+ Udmatim = 0x4A, /* Ultra DMA/33 Timing */
+};
+
+enum { /* Bus Master IDE I/O Ports */
+ Bmicx = 0, /* Command */
+ Bmisx = 2, /* Status */
+ Bmidtpx = 4, /* Descriptor Table Pointer */
+};
+
+enum { /* Bmicx */
+ Ssbm = 0x01, /* Start/Stop Bus Master */
+ Rwcon = 0x08, /* Read/Write Control */
+};
+
+enum { /* Bmisx */
+ Bmidea = 0x01, /* Bus Master IDE Active */
+ Idedmae = 0x02, /* IDE DMA Error (R/WC) */
+ Ideints = 0x04, /* IDE Interrupt Status (R/WC) */
+ Dma0cap = 0x20, /* Drive 0 DMA Capable */
+ Dma1cap = 0x40, /* Drive 0 DMA Capable */
+};
+enum { /* Physical Region Descriptor */
+ PrdEOT = 0x80000000, /* End of Transfer */
+};
+
+enum { /* offsets into the identify info. */
+ Iconfig = 0, /* general configuration */
+ Ilcyl = 1, /* logical cylinders */
+ Ilhead = 3, /* logical heads */
+ Ilsec = 6, /* logical sectors per logical track */
+ Iserial = 10, /* serial number */
+ Ifirmware = 23, /* firmware revision */
+ Imodel = 27, /* model number */
+ Imaxrwm = 47, /* max. read/write multiple sectors */
+ Icapabilities = 49, /* capabilities */
+ Istandby = 50, /* device specific standby timer */
+ Ipiomode = 51, /* PIO data transfer mode number */
+ Ivalid = 53,
+ Iccyl = 54, /* cylinders if (valid&0x01) */
+ Ichead = 55, /* heads if (valid&0x01) */
+ Icsec = 56, /* sectors if (valid&0x01) */
+ Iccap = 57, /* capacity if (valid&0x01) */
+ Irwm = 59, /* read/write multiple */
+ Ilba = 60, /* LBA size */
+ Imwdma = 63, /* multiword DMA mode */
+ Iapiomode = 64, /* advanced PIO modes supported */
+ Iminmwdma = 65, /* min. multiword DMA cycle time */
+ Irecmwdma = 66, /* rec. multiword DMA cycle time */
+ Iminpio = 67, /* min. PIO cycle w/o flow control */
+ Iminiordy = 68, /* min. PIO cycle with IORDY */
+ Ipcktbr = 71, /* time from PACKET to bus release */
+ Iserbsy = 72, /* time from SERVICE to !Bsy */
+ Iqdepth = 75, /* max. queue depth */
+ Imajor = 80, /* major version number */
+ Iminor = 81, /* minor version number */
+ Icsfs = 82, /* command set/feature supported */
+ Icsfe = 85, /* command set/feature enabled */
+ Iudma = 88, /* ultra DMA mode */
+ Ierase = 89, /* time for security erase */
+ Ieerase = 90, /* time for enhanced security erase */
+ Ipower = 91, /* current advanced power management */
+ Ilba48 = 100, /* 48-bit LBA size (64 bits in 100-103) */
+ Irmsn = 127, /* removable status notification */
+ Isecstat = 128, /* security status */
+ Icfapwr = 160, /* CFA power mode */
+ Imediaserial = 176, /* current media serial number */
+ Icksum = 255, /* checksum */
+};
+
+enum { /* bit masks for config identify info */
+ Mpktsz = 0x0003, /* packet command size */
+ Mincomplete = 0x0004, /* incomplete information */
+ Mdrq = 0x0060, /* DRQ type */
+ Mrmdev = 0x0080, /* device is removable */
+ Mtype = 0x1F00, /* device type */
+ Mproto = 0x8000, /* command protocol */
+};
+
+enum { /* bit masks for capabilities identify info */
+ Mdma = 0x0100, /* DMA supported */
+ Mlba = 0x0200, /* LBA supported */
+ Mnoiordy = 0x0400, /* IORDY may be disabled */
+ Miordy = 0x0800, /* IORDY supported */
+ Msoftrst = 0x1000, /* needs soft reset when Bsy */
+ Mstdby = 0x2000, /* standby supported */
+ Mqueueing = 0x4000, /* queueing overlap supported */
+ Midma = 0x8000, /* interleaved DMA supported */
+};
+
+enum { /* bit masks for supported/enabled features */
+ Msmart = 0x0001,
+ Msecurity = 0x0002,
+ Mrmmedia = 0x0004,
+ Mpwrmgmt = 0x0008,
+ Mpkt = 0x0010,
+ Mwcache = 0x0020,
+ Mlookahead = 0x0040,
+ Mrelirq = 0x0080,
+ Msvcirq = 0x0100,
+ Mreset = 0x0200,
+ Mprotected = 0x0400,
+ Mwbuf = 0x1000,
+ Mrbuf = 0x2000,
+ Mnop = 0x4000,
+ Mmicrocode = 0x0001,
+ Mqueued = 0x0002,
+ Mcfa = 0x0004,
+ Mapm = 0x0008,
+ Mnotify = 0x0010,
+ Mstandby = 0x0020,
+ Mspinup = 0x0040,
+ Mmaxsec = 0x0100,
+ Mautoacoustic = 0x0200,
+ Maddr48 = 0x0400,
+ Mdevconfov = 0x0800,
+ Mflush = 0x1000,
+ Mflush48 = 0x2000,
+ Msmarterror = 0x0001,
+ Msmartselftest = 0x0002,
+ Mmserial = 0x0004,
+ Mmpassthru = 0x0008,
+ Mlogging = 0x0020,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Drive Drive;
+
+typedef struct Prd { /* Physical Region Descriptor */
+ ulong pa; /* Physical Base Address */
+ int count;
+} Prd;
+
+enum {
+ BMspan = 64*1024, /* must be power of 2 <= 64*1024 */
+
+ Nprd = SDmaxio/BMspan+2,
+};
+
+typedef struct Ctlr {
+ int cmdport;
+ int ctlport;
+ 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*);
+ void (*idisable)(Ctlr*);
+ SDev* sdev;
+
+ Drive* drive[2];
+
+ Prd* prdt; /* physical region descriptor table */
+
+ QLock; /* current command */
+ Drive* curdrive;
+ int command; /* last command issued (debugging) */
+ Rendez;
+ int done;
+
+ Lock; /* register access */
+} Ctlr;
+
+typedef struct Drive {
+ Ctlr* ctlr;
+
+ int dev;
+ ushort info[256];
+ int c; /* cylinder */
+ int h; /* head */
+ int s; /* sector */
+ vlong sectors; /* total */
+ int secsize; /* sector size */
+
+ int dma; /* DMA R/W possible */
+ int dmactl;
+ int rwm; /* read/write multiple possible */
+ int rwmctl;
+
+ int pkt; /* PACKET device, length of pktcmd */
+ uchar pktcmd[16];
+ int pktdma; /* this PACKET command using dma */
+
+ uchar sense[18];
+ uchar inquiry[48];
+
+ QLock; /* drive access */
+ int command; /* current command */
+ int write;
+ uchar* data;
+ int dlen;
+ uchar* limit;
+ int count; /* sectors */
+ int block; /* R/W bytes per block */
+ int status;
+ int error;
+ int flags; /* internal flags */
+} Drive;
+
+enum { /* internal flags */
+ Lba48 = 0x1, /* LBA48 mode */
+ Lba48always = 0x2, /* ... */
+};
+enum {
+ Last28 = (1<<28) - 1 - 1, /* all-ones mask is not addressible */
+};
+
+static void
+pc87415ienable(Ctlr* ctlr)
+{
+ Pcidev *p;
+ int x;
+
+ p = ctlr->pcidev;
+ if(p == nil)
+ return;
+
+ x = pcicfgr32(p, 0x40);
+ if(ctlr->cmdport == p->mem[0].bar)
+ x &= ~0x00000100;
+ else
+ x &= ~0x00000200;
+ pcicfgw32(p, 0x40, x);
+}
+
+static void
+atadumpstate(Drive* drive, uchar* cmd, vlong lba, int count)
+{
+ Prd *prd;
+ Pcidev *p;
+ Ctlr *ctlr;
+ int i, bmiba;
+
+ if(!(DEBUG & DbgSTATE)){
+ USED(drive, cmd, lba, count);
+ return;
+ }
+
+ ctlr = drive->ctlr;
+ print("sdata: command %2.2uX\n", ctlr->command);
+ print("data %8.8p limit %8.8p dlen %d status %uX error %uX\n",
+ drive->data, drive->limit, drive->dlen,
+ drive->status, drive->error);
+ if(cmd != nil){
+ print("lba %d -> %lld, count %d -> %d (%d)\n",
+ (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5], lba,
+ (cmd[7]<<8)|cmd[8], count, drive->count);
+ }
+ if(!(inb(ctlr->ctlport+As) & Bsy)){
+ for(i = 1; i < 7; i++)
+ print(" 0x%2.2uX", inb(ctlr->cmdport+i));
+ print(" 0x%2.2uX\n", inb(ctlr->ctlport+As));
+ }
+ if(drive->command == Cwd || drive->command == Crd){
+ bmiba = ctlr->bmiba;
+ prd = ctlr->prdt;
+ print("bmicx %2.2uX bmisx %2.2uX prdt %8.8p\n",
+ inb(bmiba+Bmicx), inb(bmiba+Bmisx), prd);
+ for(;;){
+ print("pa 0x%8.8luX count %8.8uX\n",
+ prd->pa, prd->count);
+ if(prd->count & PrdEOT)
+ break;
+ prd++;
+ }
+ }
+ if(ctlr->pcidev && ctlr->pcidev->vid == 0x8086){
+ p = ctlr->pcidev;
+ print("0x40: %4.4uX 0x42: %4.4uX",
+ pcicfgr16(p, 0x40), pcicfgr16(p, 0x42));
+ print("0x48: %2.2uX\n", pcicfgr8(p, 0x48));
+ print("0x4A: %4.4uX\n", pcicfgr16(p, 0x4A));
+ }
+}
+
+static int
+atadebug(int cmdport, int ctlport, char* fmt, ...)
+{
+ int i, n;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ if(!(DEBUG & DbgPROBE)){
+ USED(cmdport, ctlport, fmt);
+ return 0;
+ }
+
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+
+ if(cmdport){
+ if(buf[n-1] == '\n')
+ n--;
+ n += snprint(buf+n, PRINTSIZE-n, " ataregs 0x%uX:",
+ cmdport);
+ for(i = Features; i < Command; i++)
+ n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",
+ inb(cmdport+i));
+ if(ctlport)
+ n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",
+ inb(ctlport+As));
+ n += snprint(buf+n, PRINTSIZE-n, "\n");
+ }
+ putstrn(buf, n);
+
+ return n;
+}
+
+static int
+ataready(int cmdport, int ctlport, int dev, int reset, int ready, int micro)
+{
+ int as;
+
+ atadebug(cmdport, ctlport, "ataready: dev %uX reset %uX ready %uX",
+ dev, reset, ready);
+
+ for(;;){
+ /*
+ * Wait for the controller to become not busy and
+ * possibly for a status bit to become true (usually
+ * Drdy). Must change to the appropriate device
+ * register set if necessary before testing for ready.
+ * Always run through the loop at least once so it
+ * can be used as a test for !Bsy.
+ */
+ as = inb(ctlport+As);
+ if(as & reset){
+ /* nothing to do */
+ }
+ else if(dev){
+ outb(cmdport+Dh, dev);
+ dev = 0;
+ }
+ else if(ready == 0 || (as & ready)){
+ atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);
+ return as;
+ }
+
+ if(micro-- <= 0){
+ atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);
+ break;
+ }
+ microdelay(1);
+ }
+ atadebug(cmdport, ctlport, "ataready: timeout");
+
+ return -1;
+}
+
+/*
+static int
+atacsf(Drive* drive, vlong csf, int supported)
+{
+ ushort *info;
+ int cmdset, i, x;
+
+ if(supported)
+ info = &drive->info[Icsfs];
+ else
+ info = &drive->info[Icsfe];
+
+ for(i = 0; i < 3; i++){
+ x = (csf>>(16*i)) & 0xFFFF;
+ if(x == 0)
+ continue;
+ cmdset = info[i];
+ if(cmdset == 0 || cmdset == 0xFFFF)
+ return 0;
+ return cmdset & x;
+ }
+
+ return 0;
+}
+*/
+
+static int
+atadone(void* arg)
+{
+ return ((Ctlr*)arg)->done;
+}
+
+static int
+atarwmmode(Drive* drive, int cmdport, int ctlport, int dev)
+{
+ int as, maxrwm, rwm;
+
+ maxrwm = (drive->info[Imaxrwm] & 0xFF);
+ if(maxrwm == 0)
+ return 0;
+
+ /*
+ * Sometimes drives come up with the current count set
+ * to 0; if so, set a suitable value, otherwise believe
+ * the value in Irwm if the 0x100 bit is set.
+ */
+ if(drive->info[Irwm] & 0x100)
+ rwm = (drive->info[Irwm] & 0xFF);
+ else
+ rwm = 0;
+ if(rwm == 0)
+ rwm = maxrwm;
+ if(rwm > 16)
+ rwm = 16;
+ if(ataready(cmdport, ctlport, dev, Bsy|Drq, Drdy, 102*1000) < 0)
+ return 0;
+ outb(cmdport+Count, rwm);
+ outb(cmdport+Command, Csm);
+ microdelay(1);
+ as = ataready(cmdport, ctlport, 0, Bsy, Drdy|Df|Err, 1000);
+ inb(cmdport+Status);
+ if(as < 0 || (as & (Df|Err)))
+ return 0;
+
+ drive->rwm = rwm;
+
+ return rwm;
+}
+
+static int
+atadmamode(Drive* drive)
+{
+ int dma;
+
+ /*
+ * Check if any DMA mode enabled.
+ * Assumes the BIOS has picked and enabled the best.
+ * This is completely passive at the moment, no attempt is
+ * made to ensure the hardware is correctly set up.
+ */
+ dma = drive->info[Imwdma] & 0x0707;
+ drive->dma = (dma>>8) & dma;
+ if(drive->dma == 0 && (drive->info[Ivalid] & 0x04)){
+ dma = drive->info[Iudma] & 0x7F7F;
+ drive->dma = (dma>>8) & dma;
+ if(drive->dma)
+ drive->dma |= 'U'<<16;
+ }
+
+ return dma;
+}
+
+static int
+ataidentify(int cmdport, int ctlport, int dev, int pkt, void* info)
+{
+ int as, command, drdy;
+
+ if(pkt){
+ command = Cidpkt;
+ drdy = 0;
+ }
+ else{
+ command = Cid;
+ drdy = Drdy;
+ }
+ as = ataready(cmdport, ctlport, dev, Bsy|Drq, drdy, 103*1000);
+ if(as < 0)
+ return as;
+ outb(cmdport+Command, command);
+ microdelay(1);
+
+ as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 400*1000);
+ if(as < 0)
+ return -1;
+ if(as & Err)
+ return as;
+
+ memset(info, 0, 512);
+ inss(cmdport+Data, info, 256);
+ inb(cmdport+Status);
+
+ if(DEBUG & DbgIDENTIFY){
+ int i;
+ ushort *sp;
+
+ sp = (ushort*)info;
+ for(i = 0; i < 256; i++){
+ if(i && (i%16) == 0)
+ print("\n");
+ print(" %4.4uX", *sp);
+ sp++;
+ }
+ print("\n");
+ }
+
+ return 0;
+}
+
+static Drive*
+atadrive(int cmdport, int ctlport, int dev)
+{
+ Drive *drive;
+ int as, i, pkt;
+ uchar buf[512], *p;
+ ushort iconfig, *sp;
+
+ atadebug(0, 0, "identify: port 0x%uX dev 0x%2.2uX\n", cmdport, dev);
+ pkt = 1;
+retry:
+ as = ataidentify(cmdport, ctlport, dev, pkt, buf);
+ if(as < 0)
+ return nil;
+ if(as & Err){
+ if(pkt == 0)
+ return nil;
+ pkt = 0;
+ goto retry;
+ }
+
+ if((drive = malloc(sizeof(Drive))) == nil)
+ return nil;
+ drive->dev = dev;
+ memmove(drive->info, buf, sizeof(drive->info));
+ drive->sense[0] = 0x70;
+ drive->sense[7] = sizeof(drive->sense)-7;
+
+ drive->inquiry[2] = 2;
+ drive->inquiry[3] = 2;
+ drive->inquiry[4] = sizeof(drive->inquiry)-4;
+ p = &drive->inquiry[8];
+ sp = &drive->info[Imodel];
+ for(i = 0; i < 20; i++){
+ *p++ = *sp>>8;
+ *p++ = *sp++;
+ }
+
+ drive->secsize = 512;
+
+ /*
+ * Beware the CompactFlash Association feature set.
+ * Now, why this value in Iconfig just walks all over the bit
+ * definitions used in the other parts of the ATA/ATAPI standards
+ * is a mystery and a sign of true stupidity on someone's part.
+ * Anyway, the standard says if this value is 0x848A then it's
+ * CompactFlash and it's NOT a packet device.
+ */
+ iconfig = drive->info[Iconfig];
+ if(iconfig != 0x848A && (iconfig & 0xC000) == 0x8000){
+ if(iconfig & 0x01)
+ drive->pkt = 16;
+ else
+ drive->pkt = 12;
+ }
+ else{
+ if(drive->info[Ivalid] & 0x0001){
+ drive->c = drive->info[Iccyl];
+ drive->h = drive->info[Ichead];
+ drive->s = drive->info[Icsec];
+ }
+ else{
+ drive->c = drive->info[Ilcyl];
+ drive->h = drive->info[Ilhead];
+ drive->s = drive->info[Ilsec];
+ }
+ if(drive->info[Icapabilities] & Mlba){
+ if(drive->info[Icsfs+1] & Maddr48){
+ drive->sectors = drive->info[Ilba48]
+ | (drive->info[Ilba48+1]<<16)
+ | ((vlong)drive->info[Ilba48+2]<<32);
+ drive->flags |= Lba48;
+ }
+ else{
+ drive->sectors = (drive->info[Ilba+1]<<16)
+ |drive->info[Ilba];
+ }
+ drive->dev |= Lba;
+ }
+ else
+ drive->sectors = drive->c*drive->h*drive->s;
+ atarwmmode(drive, cmdport, ctlport, dev);
+ }
+ atadmamode(drive);
+
+ if(DEBUG & DbgCONFIG){
+ print("dev %2.2uX port %uX config %4.4uX capabilities %4.4uX",
+ dev, cmdport, iconfig, drive->info[Icapabilities]);
+ print(" mwdma %4.4uX", drive->info[Imwdma]);
+ if(drive->info[Ivalid] & 0x04)
+ print(" udma %4.4uX", drive->info[Iudma]);
+ print(" dma %8.8uX rwm %ud", drive->dma, drive->rwm);
+ if(drive->flags&Lba48)
+ print("\tLLBA sectors %lld", drive->sectors);
+ print("\n");
+ }
+
+ return drive;
+}
+
+static void
+atasrst(int ctlport)
+{
+ /*
+ * Srst is a big stick and may cause problems if further
+ * commands are tried before the drives become ready again.
+ * Also, there will be problems here if overlapped commands
+ * are ever supported.
+ */
+ microdelay(5);
+ outb(ctlport+Dc, Srst);
+ microdelay(5);
+ outb(ctlport+Dc, 0);
+ microdelay(2*1000);
+}
+
+static SDev*
+ataprobe(int cmdport, int ctlport, int irq)
+{
+ Ctlr* ctlr;
+ 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;
+ }
+ if(ioalloc(ctlport+As, 1, 0, "atactl") < 0){
+ print("ataprobe: Cannot allocate %X\n", ctlport + As);
+ iofree(cmdport);
+ return nil;
+ }
+
+ /*
+ * Try to detect a floating bus.
+ * Bsy should be cleared. If not, see if the cylinder registers
+ * are read/write capable.
+ * If the master fails, try the slave to catch slave-only
+ * configurations.
+ * There's no need to restore the tested registers as they will
+ * be reset on any detected drives by the Cedd command.
+ * All this indicates is that there is at least one drive on the
+ * controller; when the non-existent drive is selected in a
+ * single-drive configuration the registers of the existing drive
+ * are often seen, only command execution fails.
+ */
+ dev = Dev0;
+ if(inb(ctlport+As) & Bsy){
+ outb(cmdport+Dh, dev);
+ microdelay(1);
+trydev1:
+ atadebug(cmdport, ctlport, "ataprobe bsy");
+ outb(cmdport+Cyllo, 0xAA);
+ outb(cmdport+Cylhi, 0x55);
+ outb(cmdport+Sector, 0xFF);
+ rlo = inb(cmdport+Cyllo);
+ rhi = inb(cmdport+Cylhi);
+ if(rlo != 0xAA && (rlo == 0xFF || rhi != 0x55)){
+ if(dev == Dev1){
+release:
+ iofree(cmdport);
+ iofree(ctlport+As);
+ return nil;
+ }
+ dev = Dev1;
+ if(ataready(cmdport, ctlport, dev, Bsy, 0, 20*1000) < 0)
+ goto trydev1;
+ }
+ }
+
+ /*
+ * Disable interrupts on any detected controllers.
+ */
+ outb(ctlport+Dc, Nien);
+tryedd1:
+ if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 105*1000) < 0){
+ /*
+ * There's something there, but it didn't come up clean,
+ * so try hitting it with a big stick. The timing here is
+ * wrong but this is a last-ditch effort and it sometimes
+ * gets some marginal hardware back online.
+ */
+ atasrst(ctlport);
+ if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 106*1000) < 0)
+ goto release;
+ }
+
+ /*
+ * Can only get here if controller is not busy.
+ * If there are drives Bsy will be set within 400nS,
+ * must wait 2mS before testing Status.
+ * Wait for the command to complete (6 seconds max).
+ */
+ outb(cmdport+Command, Cedd);
+ delay(2);
+ if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 6*1000*1000) < 0)
+ goto release;
+
+ /*
+ * If bit 0 of the error register is set then the selected drive
+ * exists. This is enough to detect single-drive configurations.
+ * However, if the master exists there is no way short of executing
+ * a command to determine if a slave is present.
+ * It appears possible to get here testing Dev0 although it doesn't
+ * exist and the EDD won't take, so try again with Dev1.
+ */
+ error = inb(cmdport+Error);
+ atadebug(cmdport, ctlport, "ataprobe: dev %uX", dev);
+ if((error & ~0x80) != 0x01){
+ if(dev == Dev1)
+ goto release;
+ dev = Dev1;
+ goto tryedd1;
+ }
+
+ /*
+ * At least one drive is known to exist, try to
+ * identify it. If that fails, don't bother checking
+ * any further.
+ * If the one drive found is Dev0 and the EDD command
+ * didn't indicate Dev1 doesn't exist, check for it.
+ */
+ if((drive = atadrive(cmdport, ctlport, dev)) == nil)
+ goto release;
+ if((ctlr = malloc(sizeof(Ctlr))) == nil){
+ free(drive);
+ goto release;
+ }
+ memset(ctlr, 0, sizeof(Ctlr));
+ if((sdev = malloc(sizeof(SDev))) == nil){
+ free(ctlr);
+ free(drive);
+ goto release;
+ }
+ memset(sdev, 0, sizeof(SDev));
+ drive->ctlr = ctlr;
+ if(dev == Dev0){
+ ctlr->drive[0] = drive;
+ if(!(error & 0x80)){
+ /*
+ * Always leave Dh pointing to a valid drive,
+ * otherwise a subsequent call to ataready on
+ * this controller may try to test a bogus Status.
+ * Ataprobe is the only place possibly invalid
+ * drives should be selected.
+ */
+ drive = atadrive(cmdport, ctlport, Dev1);
+ if(drive != nil){
+ drive->ctlr = ctlr;
+ ctlr->drive[1] = drive;
+ }
+ else{
+ outb(cmdport+Dh, Dev0);
+ microdelay(1);
+ }
+ }
+ }
+ else
+ ctlr->drive[1] = drive;
+
+ ctlr->cmdport = cmdport;
+ ctlr->ctlport = ctlport;
+ 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;
+ ctlr->sdev = sdev;
+
+ return sdev;
+}
+
+static void
+ataclear(SDev *sdev)
+{
+ Ctlr* ctlr;
+
+ ctlr = sdev->ctlr;
+ iofree(ctlr->cmdport);
+ iofree(ctlr->ctlport + As);
+
+ if (ctlr->drive[0])
+ free(ctlr->drive[0]);
+ if (ctlr->drive[1])
+ free(ctlr->drive[1]);
+ if (sdev->name)
+ free(sdev->name);
+ if (sdev->unitflg)
+ free(sdev->unitflg);
+ if (sdev->unit)
+ free(sdev->unit);
+ free(ctlr);
+ free(sdev);
+}
+
+static char *
+atastat(SDev *sdev, char *p, char *e)
+{
+ Ctlr *ctlr = sdev->ctlr;
+
+ return seprint(p, e, "%s ata port %X ctl %X irq %d\n",
+ sdev->name, ctlr->cmdport, ctlr->ctlport, ctlr->irq);
+}
+
+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)
+{
+ drive->sense[2] = key;
+ drive->sense[12] = asc;
+ drive->sense[13] = 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)
+{
+ Ctlr* ctlr;
+ int cmdport, done;
+
+ ctlr = drive->ctlr;
+ drive->command = Cstandby;
+ qlock(ctlr);
+
+ cmdport = ctlr->cmdport;
+ ilock(ctlr);
+ outb(cmdport+Count, period);
+ outb(cmdport+Dh, drive->dev);
+ ctlr->done = 0;
+ ctlr->curdrive = drive;
+ ctlr->command = Cstandby; /* debugging */
+ outb(cmdport+Command, Cstandby);
+ iunlock(ctlr);
+
+ while(waserror())
+ ;
+ tsleep(ctlr, atadone, ctlr, 60*1000);
+ poperror();
+
+ done = ctlr->done;
+ qunlock(ctlr);
+
+ if(!done || (drive->status & Err))
+ return atasetsense(drive, SDcheck, 4, 8, drive->error);
+ return SDok;
+}
+
+static void
+atanop(Drive* drive, int subcommand)
+{
+ Ctlr* ctlr;
+ int as, cmdport, ctlport, timeo;
+
+ /*
+ * Attempt to abort a command by using NOP.
+ * In response, the drive is supposed to set Abrt
+ * in the Error register, set (Drdy|Err) in Status
+ * and clear Bsy when done. However, some drives
+ * (e.g. ATAPI Zip) just go Bsy then clear Status
+ * when done, hence the timeout loop only on Bsy
+ * and the forced setting of drive->error.
+ */
+ ctlr = drive->ctlr;
+ cmdport = ctlr->cmdport;
+ outb(cmdport+Features, subcommand);
+ outb(cmdport+Dh, drive->dev);
+ ctlr->command = Cnop; /* debugging */
+ outb(cmdport+Command, Cnop);
+
+ microdelay(1);
+ ctlport = ctlr->ctlport;
+ for(timeo = 0; timeo < 1000; timeo++){
+ as = inb(ctlport+As);
+ if(!(as & Bsy))
+ break;
+ microdelay(1);
+ }
+ drive->error |= Abrt;
+}
+
+static void
+ataabort(Drive* drive, int dolock)
+{
+ /*
+ * If NOP is available (packet commands) use it otherwise
+ * must try a software reset.
+ */
+ if(dolock)
+ ilock(drive->ctlr);
+ if(drive->info[Icsfs] & Mnop)
+ atanop(drive, 0);
+ else{
+ atasrst(drive->ctlr->ctlport);
+ drive->error |= Abrt;
+ }
+ if(dolock)
+ iunlock(drive->ctlr);
+}
+
+static int
+atadmasetup(Drive* drive, int len)
+{
+ Prd *prd;
+ ulong pa;
+ Ctlr *ctlr;
+ int bmiba, bmisx, count, i, span;
+
+ ctlr = drive->ctlr;
+ pa = PCIWADDR(drive->data);
+ if(pa & 0x03)
+ return -1;
+
+ /*
+ * 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(i = 0; len && i < Nprd; i++){
+ prd->pa = pa;
+ span = ROUNDUP(pa, ctlr->span);
+ if(span == pa)
+ span += ctlr->span;
+ count = span - pa;
+ if(count >= len){
+ prd->count = PrdEOT|len;
+ break;
+ }
+ prd->count = count;
+ len -= count;
+ pa += count;
+ prd++;
+ }
+ if(i == Nprd)
+ (prd-1)->count |= PrdEOT;
+
+ bmiba = ctlr->bmiba;
+ outl(bmiba+Bmidtpx, PCIWADDR(ctlr->prdt));
+ if(drive->write)
+ outb(ctlr->bmiba+Bmicx, 0);
+ else
+ outb(ctlr->bmiba+Bmicx, Rwcon);
+ bmisx = inb(bmiba+Bmisx);
+ outb(bmiba+Bmisx, bmisx|Ideints|Idedmae);
+
+ return 0;
+}
+
+static void
+atadmastart(Ctlr* ctlr, int write)
+{
+ if(write)
+ outb(ctlr->bmiba+Bmicx, Ssbm);
+ else
+ outb(ctlr->bmiba+Bmicx, Rwcon|Ssbm);
+}
+
+static int
+atadmastop(Ctlr* ctlr)
+{
+ int bmiba;
+
+ bmiba = ctlr->bmiba;
+ outb(bmiba+Bmicx, inb(bmiba+Bmicx) & ~Ssbm);
+
+ return inb(bmiba+Bmisx);
+}
+
+static void
+atadmainterrupt(Drive* drive, int count)
+{
+ Ctlr* ctlr;
+ int bmiba, bmisx;
+
+ ctlr = drive->ctlr;
+ bmiba = ctlr->bmiba;
+ bmisx = inb(bmiba+Bmisx);
+ switch(bmisx & (Ideints|Idedmae|Bmidea)){
+ case Bmidea:
+ /*
+ * Data transfer still in progress, nothing to do
+ * (this should never happen).
+ */
+ return;
+
+ case Ideints:
+ case Ideints|Bmidea:
+ /*
+ * Normal termination, tidy up.
+ */
+ drive->data += count;
+ break;
+
+ default:
+ /*
+ * What's left are error conditions (memory transfer
+ * problem) and the device is not done but the PRD is
+ * exhausted. For both cases must somehow tell the
+ * drive to abort.
+ */
+ ataabort(drive, 0);
+ break;
+ }
+ atadmastop(ctlr);
+ ctlr->done = 1;
+}
+
+static void
+atapktinterrupt(Drive* drive)
+{
+ Ctlr* ctlr;
+ int cmdport, len;
+
+ ctlr = drive->ctlr;
+ cmdport = ctlr->cmdport;
+ switch(inb(cmdport+Ir) & (/*Rel|*/Io|Cd)){
+ case Cd:
+ outss(cmdport+Data, drive->pktcmd, drive->pkt/2);
+ break;
+
+ case 0:
+ len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
+ if(drive->data+len > drive->limit){
+ atanop(drive, 0);
+ break;
+ }
+ outss(cmdport+Data, drive->data, len/2);
+ drive->data += len;
+ break;
+
+ case Io:
+ len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
+ if(drive->data+len > drive->limit){
+ atanop(drive, 0);
+ break;
+ }
+ inss(cmdport+Data, drive->data, len/2);
+ drive->data += len;
+ break;
+
+ case Io|Cd:
+ if(drive->pktdma)
+ atadmainterrupt(drive, drive->dlen);
+ else
+ ctlr->done = 1;
+ break;
+ }
+}
+
+static int
+atapktio(Drive* drive, uchar* cmd, int clen)
+{
+ Ctlr *ctlr;
+ int as, cmdport, ctlport, len, r, timeo;
+
+ if(cmd[0] == 0x5A && (cmd[2] & 0x3F) == 0)
+ return atamodesense(drive, cmd);
+
+ r = SDok;
+
+ drive->command = Cpkt;
+ memmove(drive->pktcmd, cmd, clen);
+ memset(drive->pktcmd+clen, 0, drive->pkt-clen);
+ drive->limit = drive->data+drive->dlen;
+
+ ctlr = drive->ctlr;
+ cmdport = ctlr->cmdport;
+ ctlport = ctlr->ctlport;
+
+ qlock(ctlr);
+
+ as = ataready(cmdport, ctlport, drive->dev, Bsy|Drq, Drdy, 107*1000);
+ /* used to test as&Chk as failure too, but some CD readers use that for media change */
+ if(as < 0){
+ qunlock(ctlr);
+ return -1;
+ }
+
+ ilock(ctlr);
+ if(drive->dlen && drive->dmactl && !atadmasetup(drive, drive->dlen))
+ drive->pktdma = Dma;
+ else
+ drive->pktdma = 0;
+
+ outb(cmdport+Features, drive->pktdma);
+ outb(cmdport+Count, 0);
+ outb(cmdport+Sector, 0);
+ len = 16*drive->secsize;
+ outb(cmdport+Bytelo, len);
+ outb(cmdport+Bytehi, len>>8);
+ outb(cmdport+Dh, drive->dev);
+ ctlr->done = 0;
+ ctlr->curdrive = drive;
+ ctlr->command = Cpkt; /* debugging */
+ if(drive->pktdma)
+ atadmastart(ctlr, drive->write);
+ outb(cmdport+Command, Cpkt);
+
+ if((drive->info[Iconfig] & Mdrq) != 0x0020){
+ microdelay(1);
+ as = ataready(cmdport, ctlport, 0, Bsy, Drq|Chk, 4*1000);
+ if(as < 0 || (as & (Bsy|Chk))){
+ drive->status = as<0 ? 0 : as;
+ ctlr->curdrive = nil;
+ ctlr->done = 1;
+ r = SDtimeout;
+ }else
+ atapktinterrupt(drive);
+ }
+ iunlock(ctlr);
+
+ while(waserror())
+ ;
+ if(!drive->pktdma)
+ sleep(ctlr, atadone, ctlr);
+ else for(timeo = 0; !ctlr->done; timeo++){
+ tsleep(ctlr, atadone, ctlr, 1000);
+ if(ctlr->done)
+ break;
+ ilock(ctlr);
+ atadmainterrupt(drive, 0);
+ if(!drive->error && timeo > 20){
+ ataabort(drive, 0);
+ atadmastop(ctlr);
+ drive->dmactl = 0;
+ drive->error |= Abrt;
+ }
+ if(drive->error){
+ drive->status |= Chk;
+ ctlr->curdrive = nil;
+ }
+ iunlock(ctlr);
+ }
+ poperror();
+
+ qunlock(ctlr);
+
+ if(drive->status & Chk)
+ r = SDcheck;
+
+ return r;
+}
+
+static uchar cmd48[256] = {
+ [Crs] Crs48,
+ [Crd] Crd48,
+ [Crdq] Crdq48,
+ [Crsm] Crsm48,
+ [Cws] Cws48,
+ [Cwd] Cwd48,
+ [Cwdq] Cwdq48,
+ [Cwsm] Cwsm48,
+};
+
+static int
+atageniostart(Drive* drive, uvlong lba)
+{
+ Ctlr *ctlr;
+ uchar cmd;
+ int as, c, cmdport, ctlport, h, len, s, use48;
+
+ use48 = 0;
+ if((drive->flags&Lba48always) || lba > Last28 || drive->count > 256){
+ if(!(drive->flags & Lba48))
+ return -1;
+ use48 = 1;
+ c = h = s = 0;
+ }
+ else if(drive->dev & Lba){
+ c = (lba>>8) & 0xFFFF;
+ h = (lba>>24) & 0x0F;
+ s = lba & 0xFF;
+ }
+ else{
+ c = lba/(drive->s*drive->h);
+ h = ((lba/drive->s) % drive->h);
+ s = (lba % drive->s) + 1;
+ }
+
+ ctlr = drive->ctlr;
+ cmdport = ctlr->cmdport;
+ ctlport = ctlr->ctlport;
+ if(ataready(cmdport, ctlport, drive->dev, Bsy|Drq, Drdy, 101*1000) < 0)
+ return -1;
+
+ ilock(ctlr);
+ if(drive->dmactl && !atadmasetup(drive, drive->count*drive->secsize)){
+ if(drive->write)
+ drive->command = Cwd;
+ else
+ drive->command = Crd;
+ }
+ else if(drive->rwmctl){
+ drive->block = drive->rwm*drive->secsize;
+ if(drive->write)
+ drive->command = Cwsm;
+ else
+ drive->command = Crsm;
+ }
+ else{
+ drive->block = drive->secsize;
+ if(drive->write)
+ drive->command = Cws;
+ else
+ drive->command = Crs;
+ }
+ drive->limit = drive->data + drive->count*drive->secsize;
+ cmd = drive->command;
+ if(use48){
+ outb(cmdport+Count, drive->count>>8);
+ outb(cmdport+Count, drive->count);
+ outb(cmdport+Lbalo, lba>>24);
+ outb(cmdport+Lbalo, lba);
+ outb(cmdport+Lbamid, lba>>32);
+ outb(cmdport+Lbamid, lba>>8);
+ outb(cmdport+Lbahi, lba>>40);
+ outb(cmdport+Lbahi, lba>>16);
+ outb(cmdport+Dh, drive->dev|Lba);
+ cmd = cmd48[cmd];
+
+ if(DEBUG & Dbg48BIT)
+ print("using 48-bit commands\n");
+ }
+ else{
+ outb(cmdport+Count, drive->count);
+ outb(cmdport+Sector, s);
+ outb(cmdport+Cyllo, c);
+ outb(cmdport+Cylhi, c>>8);
+ outb(cmdport+Dh, drive->dev|h);
+ }
+ ctlr->done = 0;
+ ctlr->curdrive = drive;
+ ctlr->command = drive->command; /* debugging */
+ outb(cmdport+Command, cmd);
+
+ switch(drive->command){
+ case Cws:
+ case Cwsm:
+ microdelay(1);
+ /* 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;
+ }
+ len = drive->block;
+ if(drive->data+len > drive->limit)
+ len = drive->limit-drive->data;
+ outss(cmdport+Data, drive->data, len/2);
+ break;
+
+ case Crd:
+ case Cwd:
+ atadmastart(ctlr, drive->write);
+ break;
+ }
+ iunlock(ctlr);
+
+ return 0;
+}
+
+static int
+atagenioretry(Drive* drive)
+{
+ if(drive->dmactl){
+ drive->dmactl = 0;
+ print("atagenioretry: disabling dma\n");
+ }
+ else if(drive->rwmctl)
+ drive->rwmctl = 0;
+ else
+ return atasetsense(drive, SDcheck, 4, 8, drive->error);
+
+ return SDretry;
+}
+
+static int
+atagenio(Drive* drive, uchar* cmd, int clen)
+{
+ uchar *p;
+ Ctlr *ctlr;
+ vlong lba, len;
+ int count, maxio;
+
+ /*
+ * Map SCSI commands into ATA commands for discs.
+ * Fail any command with a LUN except INQUIRY which
+ * will return 'logical unit not supported'.
+ */
+ if((cmd[1]>>5) && cmd[0] != 0x12)
+ return atasetsense(drive, SDcheck, 0x05, 0x25, 0);
+
+ switch(cmd[0]){
+ default:
+ return atasetsense(drive, SDcheck, 0x05, 0x20, 0);
+
+ case 0x00: /* test unit ready */
+ return SDok;
+
+ case 0x03: /* request sense */
+ if(cmd[4] < sizeof(drive->sense))
+ len = cmd[4];
+ else
+ len = sizeof(drive->sense);
+ if(drive->data && drive->dlen >= len){
+ memmove(drive->data, drive->sense, len);
+ drive->data += len;
+ }
+ return SDok;
+
+ case 0x12: /* inquiry */
+ if(cmd[4] < sizeof(drive->inquiry))
+ len = cmd[4];
+ else
+ len = sizeof(drive->inquiry);
+ if(drive->data && drive->dlen >= len){
+ memmove(drive->data, drive->inquiry, len);
+ drive->data += len;
+ }
+ return SDok;
+
+ case 0x1B: /* start/stop unit */
+ /*
+ * NOP for now, can use the power management feature
+ * set later.
+ */
+ return SDok;
+
+ case 0x25: /* read capacity */
+ if((cmd[1] & 0x01) || cmd[2] || cmd[3])
+ return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
+ if(drive->data == nil || drive->dlen < 8)
+ return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
+ /*
+ * Read capacity returns the LBA of the last sector.
+ */
+ len = drive->sectors-1;
+ p = drive->data;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p++ = len;
+ len = drive->secsize;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p = len;
+ drive->data += 8;
+ return SDok;
+
+ case 0x9E: /* long read capacity */
+ if((cmd[1] & 0x01) || cmd[2] || cmd[3])
+ return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
+ if(drive->data == nil || drive->dlen < 8)
+ return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
+ /*
+ * Read capacity returns the LBA of the last sector.
+ */
+ len = drive->sectors-1;
+ p = drive->data;
+ *p++ = len>>56;
+ *p++ = len>>48;
+ *p++ = len>>40;
+ *p++ = len>>32;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p++ = len;
+ len = drive->secsize;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p = len;
+ drive->data += 12;
+ return SDok;
+
+ case 0x28: /* read */
+ case 0x88:
+ case 0x2a: /* write */
+ case 0x8a:
+ break;
+
+ case 0x5A:
+ return atamodesense(drive, cmd);
+ }
+
+ ctlr = drive->ctlr;
+ if(clen == 16){
+ /* ata commands only go to 48-bit lba */
+ if(cmd[2] || cmd[3])
+ return atasetsense(drive, SDcheck, 3, 0xc, 2);
+ lba = (uvlong)cmd[4]<<40 | (uvlong)cmd[5]<<32;
+ lba |= cmd[6]<<24 | cmd[7]<<16 | cmd[8]<<8 | cmd[9];
+ count = cmd[10]<<24 | cmd[11]<<16 | cmd[12]<<8 | cmd[13];
+ }else{
+ lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5];
+ count = cmd[7]<<8 | cmd[8];
+ }
+ if(drive->data == nil)
+ return SDok;
+ 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){
+ if(count > maxio)
+ drive->count = maxio;
+ else
+ drive->count = count;
+ if(atageniostart(drive, lba)){
+ ilock(ctlr);
+ atanop(drive, 0);
+ iunlock(ctlr);
+ qunlock(ctlr);
+ return atagenioretry(drive);
+ }
+
+ while(waserror())
+ ;
+ tsleep(ctlr, atadone, ctlr, 60*1000);
+ poperror();
+ if(!ctlr->done){
+ /*
+ * What should the above timeout be? In
+ * standby and sleep modes it could take as
+ * long as 30 seconds for a drive to respond.
+ * Very hard to get out of this cleanly.
+ */
+ atadumpstate(drive, cmd, lba, count);
+ ataabort(drive, 1);
+ qunlock(ctlr);
+ return atagenioretry(drive);
+ }
+
+ if(drive->status & Err){
+ qunlock(ctlr);
+ return atasetsense(drive, SDcheck, 4, 8, drive->error);
+ }
+ count -= drive->count;
+ lba += drive->count;
+ }
+ qunlock(ctlr);
+
+ return SDok;
+}
+
+static int
+atario(SDreq* r)
+{
+ Ctlr *ctlr;
+ Drive *drive;
+ SDunit *unit;
+ uchar cmd10[10], *cmdp, *p;
+ int clen, reqstatus, status;
+
+ unit = r->unit;
+ if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil){
+ r->status = SDtimeout;
+ return SDtimeout;
+ }
+ drive = ctlr->drive[unit->subno];
+
+ /*
+ * Most SCSI commands can be passed unchanged except for
+ * the padding on the end. The few which require munging
+ * are not used internally. Mode select/sense(6) could be
+ * converted to the 10-byte form but it's not worth the
+ * effort. Read/write(6) are easy.
+ */
+ switch(r->cmd[0]){
+ case 0x08: /* read */
+ case 0x0A: /* write */
+ cmdp = cmd10;
+ memset(cmdp, 0, sizeof(cmd10));
+ cmdp[0] = r->cmd[0]|0x20;
+ cmdp[1] = r->cmd[1] & 0xE0;
+ cmdp[5] = r->cmd[3];
+ cmdp[4] = r->cmd[2];
+ cmdp[3] = r->cmd[1] & 0x0F;
+ cmdp[8] = r->cmd[4];
+ clen = sizeof(cmd10);
+ break;
+
+ default:
+ cmdp = r->cmd;
+ clen = r->clen;
+ break;
+ }
+
+ qlock(drive);
+retry:
+ drive->write = r->write;
+ drive->data = r->data;
+ drive->dlen = r->dlen;
+
+ drive->status = 0;
+ drive->error = 0;
+ if(drive->pkt)
+ status = atapktio(drive, cmdp, clen);
+ else
+ status = atagenio(drive, cmdp, clen);
+ if(status == SDretry){
+ if(DbgDEBUG)
+ print("%s: retry: dma %8.8uX rwm %4.4uX\n",
+ unit->name, drive->dmactl, drive->rwmctl);
+ goto retry;
+ }
+ if(status == SDok){
+ atasetsense(drive, SDok, 0, 0, 0);
+ if(drive->data){
+ p = r->data;
+ r->rlen = drive->data - p;
+ }
+ else
+ r->rlen = 0;
+ }
+ else if(status == SDcheck && !(r->flags & SDnosense)){
+ drive->write = 0;
+ memset(cmd10, 0, sizeof(cmd10));
+ cmd10[0] = 0x03;
+ cmd10[1] = r->lun<<5;
+ cmd10[4] = sizeof(r->sense)-1;
+ drive->data = r->sense;
+ drive->dlen = sizeof(r->sense)-1;
+ drive->status = 0;
+ drive->error = 0;
+ if(drive->pkt)
+ reqstatus = atapktio(drive, cmd10, 6);
+ else
+ reqstatus = atagenio(drive, cmd10, 6);
+ if(reqstatus == SDok){
+ r->flags |= SDvalidsense;
+ atasetsense(drive, SDok, 0, 0, 0);
+ }
+ }
+ qunlock(drive);
+ r->status = status;
+ if(status != SDok)
+ return status;
+
+ /*
+ * Fix up any results.
+ * Many ATAPI CD-ROMs ignore the LUN field completely and
+ * return valid INQUIRY data. Patch the response to indicate
+ * 'logical unit not supported' if the LUN is non-zero.
+ */
+ switch(cmdp[0]){
+ case 0x12: /* inquiry */
+ if((p = r->data) == nil)
+ break;
+ if((cmdp[1]>>5) && (!drive->pkt || (p[0] & 0x1F) == 0x05))
+ p[0] = 0x7F;
+ /*FALLTHROUGH*/
+ default:
+ break;
+ }
+
+ return SDok;
+}
+
+static void
+atainterrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Drive *drive;
+ int cmdport, len, status;
+
+ ctlr = arg;
+
+ ilock(ctlr);
+ if(inb(ctlr->ctlport+As) & Bsy){
+ iunlock(ctlr);
+ if(DEBUG & DbgBsy)
+ print("IBsy+");
+ return;
+ }
+ cmdport = ctlr->cmdport;
+ status = inb(cmdport+Status);
+ if((drive = ctlr->curdrive) == nil){
+ iunlock(ctlr);
+ if((DEBUG & DbgINL) && ctlr->command != Cedd)
+ print("Inil%2.2uX+", ctlr->command);
+ return;
+ }
+
+ if(status & Err)
+ drive->error = inb(cmdport+Error);
+ else switch(drive->command){
+ default:
+ drive->error = Abrt;
+ break;
+
+ case Crs:
+ case Crsm:
+ if(!(status & Drq)){
+ drive->error = Abrt;
+ break;
+ }
+ len = drive->block;
+ if(drive->data+len > drive->limit)
+ len = drive->limit-drive->data;
+ inss(cmdport+Data, drive->data, len/2);
+ drive->data += len;
+ if(drive->data >= drive->limit)
+ ctlr->done = 1;
+ break;
+
+ case Cws:
+ case Cwsm:
+ len = drive->block;
+ if(drive->data+len > drive->limit)
+ len = drive->limit-drive->data;
+ drive->data += len;
+ if(drive->data >= drive->limit){
+ ctlr->done = 1;
+ break;
+ }
+ if(!(status & Drq)){
+ drive->error = Abrt;
+ break;
+ }
+ len = drive->block;
+ if(drive->data+len > drive->limit)
+ len = drive->limit-drive->data;
+ outss(cmdport+Data, drive->data, len/2);
+ break;
+
+ case Cpkt:
+ atapktinterrupt(drive);
+ break;
+
+ case Crd:
+ case Cwd:
+ atadmainterrupt(drive, drive->count*drive->secsize);
+ break;
+
+ case Cstandby:
+ ctlr->done = 1;
+ break;
+ }
+ iunlock(ctlr);
+
+ if(drive->error){
+ status |= Err;
+ ctlr->done = 1;
+ }
+
+ if(ctlr->done){
+ ctlr->curdrive = nil;
+ drive->status = status;
+ wakeup(ctlr);
+ }
+}
+
+static SDev*
+atapnp(void)
+{
+ Ctlr *ctlr;
+ Pcidev *p;
+ 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)){
+ head = tail = sdev;
+ legacy[0] = sdev;
+ }
+ if(sdev = ataprobe(0x170, 0x374, IrqATA1)){
+ if(head != nil)
+ tail->next = sdev;
+ else
+ head = sdev;
+ tail = sdev;
+ legacy[1] = sdev;
+ }
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ /*
+ * Look for devices with the correct class and sub-class
+ * code and known device and vendor ID; add native-mode
+ * channels to the list to be probed, save info for the
+ * compatibility mode channels.
+ * Note that the legacy devices should not be considered
+ * PCI devices by the interrupt controller.
+ * For both native and legacy, save info for busmastering
+ * if capable.
+ * Promise Ultra ATA/66 (PDC20262) appears to
+ * 1) give a sub-class of 'other mass storage controller'
+ * instead of 'IDE controller', regardless of whether it's
+ * the only controller or not;
+ * 2) put 0 in the programming interface byte (probably
+ * as a consequence of 1) above).
+ * Sub-class code 0x04 is 'RAID controller', e.g. VIA VT8237.
+ */
+ if(p->ccrb != 0x01)
+ continue;
+ if(p->ccru != 0x01 && p->ccru != 0x04 && p->ccru != 0x80)
+ continue;
+ pi = p->ccrp;
+ ispc87415 = 0;
+ maxio = 0;
+ span = BMspan;
+
+ switch((p->did<<16)|p->vid){
+ default:
+ continue;
+
+ case (0x0002<<16)|0x100B: /* NS PC87415 */
+ /*
+ * Disable interrupts on both channels until
+ * after they are probed for drives.
+ * This must be called before interrupts are
+ * enabled because the IRQ may be shared.
+ */
+ ispc87415 = 1;
+ pcicfgw32(p, 0x40, 0x00000300);
+ break;
+ case (0x1000<<16)|0x1042: /* PC-Tech RZ1000 */
+ /*
+ * Turn off prefetch. Overkill, but cheap.
+ */
+ r = pcicfgr32(p, 0x40);
+ r &= ~0x2000;
+ pcicfgw32(p, 0x40, r);
+ break;
+ case (0x4D38<<16)|0x105A: /* Promise PDC20262 */
+ case (0x4D30<<16)|0x105A: /* Promise PDC202xx */
+ case (0x4D68<<16)|0x105A: /* Promise PDC20268 */
+ 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: /* SiI 3112 SATA/RAID */
+ maxio = 15;
+ span = 8*1024;
+ /*FALLTHROUGH*/
+ case (0x0680<<16)|0x1095: /* SiI 0680/680A PATA133 ATAPI/RAID */
+ case (0x3114<<16)|0x1095: /* SiI 3114 SATA/RAID */
+ pi = 0x85;
+ break;
+ case (0x0004<<16)|0x1103: /* HighPoint HPT366 */
+ pi = 0x85;
+ /*
+ * Turn off fast interrupt prediction.
+ */
+ if((r = pcicfgr8(p, 0x51)) & 0x80)
+ pcicfgw8(p, 0x51, r & ~0x80);
+ if((r = pcicfgr8(p, 0x55)) & 0x80)
+ pcicfgw8(p, 0x55, r & ~0x80);
+ break;
+ case (0x0640<<16)|0x1095: /* CMD 640B */
+ /*
+ * Bugfix code here...
+ */
+ break;
+ case (0x7441<<16)|0x1022: /* AMD 768 */
+ /*
+ * Set:
+ * 0x41 prefetch, postwrite;
+ * 0x43 FIFO configuration 1/2 and 1/2;
+ * 0x44 status register read retry;
+ * 0x46 DMA read and end of sector flush.
+ */
+ r = pcicfgr8(p, 0x41);
+ pcicfgw8(p, 0x41, r|0xF0);
+ r = pcicfgr8(p, 0x43);
+ pcicfgw8(p, 0x43, (r & 0x90)|0x2A);
+ r = pcicfgr8(p, 0x44);
+ pcicfgw8(p, 0x44, r|0x08);
+ r = pcicfgr8(p, 0x46);
+ pcicfgw8(p, 0x46, (r & 0x0C)|0xF0);
+ /*FALLTHROUGH*/
+ case (0x7401<<16)|0x1022: /* AMD 755 Cobra */
+ case (0x7409<<16)|0x1022: /* AMD 756 Viper */
+ case (0x7410<<16)|0x1022: /* AMD 766 Viper Plus */
+ case (0x7469<<16)|0x1022: /* AMD 3111 */
+ /*
+ * This can probably be lumped in with the 768 above.
+ */
+ /*FALLTHROUGH*/
+ case (0x209A<<16)|0x1022: /* AMD CS5536 */
+ case (0x01BC<<16)|0x10DE: /* nVidia nForce1 */
+ case (0x0065<<16)|0x10DE: /* nVidia nForce2 */
+ case (0x0085<<16)|0x10DE: /* nVidia nForce2 MCP */
+ case (0x00E3<<16)|0x10DE: /* nVidia nForce2 250 SATA */
+ case (0x00D5<<16)|0x10DE: /* nVidia nForce3 */
+ case (0x00E5<<16)|0x10DE: /* nVidia nForce3 Pro */
+ case (0x00EE<<16)|0x10DE: /* nVidia nForce3 250 SATA */
+ case (0x0035<<16)|0x10DE: /* nVidia nForce3 MCP */
+ case (0x0053<<16)|0x10DE: /* nVidia nForce4 */
+ case (0x0054<<16)|0x10DE: /* nVidia nForce4 SATA */
+ case (0x0055<<16)|0x10DE: /* nVidia nForce4 SATA */
+ case (0x0266<<16)|0x10DE: /* nVidia nForce4 430 SATA */
+ case (0x0267<<16)|0x10DE: /* nVidia nForce 55 MCP SATA */
+ case (0x03EC<<16)|0x10DE: /* nVidia nForce 61 MCP SATA */
+ case (0x0448<<16)|0x10DE: /* nVidia nForce 65 MCP SATA */
+ case (0x0560<<16)|0x10DE: /* nVidia nForce 69 MCP SATA */
+ /*
+ * Ditto, although it may have a different base
+ * address for the registers (0x50?).
+ */
+ /*FALLTHROUGH*/
+ case (0x4376<<16)|0x1002: /* ATI SB400 PATA */
+ case (0x4379<<16)|0x1002: /* ATI SB400 SATA */
+ case (0x437a<<16)|0x1002: /* ATI SB400 SATA */
+ break;
+ case (0x0211<<16)|0x1166: /* ServerWorks IB6566 */
+ {
+ Pcidev *sb;
+
+ sb = pcimatch(nil, 0x1166, 0x0200);
+ if(sb == nil)
+ break;
+ r = pcicfgr32(sb, 0x64);
+ r &= ~0x2000;
+ pcicfgw32(sb, 0x64, r);
+ }
+ span = 32*1024;
+ break;
+ case (0x0502<<17)|0x100B: /* NS SC1100/SCx200 */
+ case (0x5229<<16)|0x10B9: /* ALi M1543 */
+ case (0x5288<<16)|0x10B9: /* ALi M5288 SATA */
+ case (0x5513<<16)|0x1039: /* SiS 962 */
+ case (0x0646<<16)|0x1095: /* CMD 646 */
+ case (0x0571<<16)|0x1106: /* VIA 82C686 */
+ case (0x2363<<16)|0x197b: /* JMicron SATA */
+ case (0x1230<<16)|0x8086: /* 82371FB (PIIX) */
+ case (0x7010<<16)|0x8086: /* 82371SB (PIIX3) */
+ case (0x7111<<16)|0x8086: /* 82371[AE]B (PIIX4[E]) */
+ case (0x2411<<16)|0x8086: /* 82801AA (ICH) */
+ case (0x2421<<16)|0x8086: /* 82801AB (ICH0) */
+ case (0x244A<<16)|0x8086: /* 82801BA (ICH2, Mobile) */
+ case (0x244B<<16)|0x8086: /* 82801BA (ICH2, High-End) */
+ case (0x248A<<16)|0x8086: /* 82801CA (ICH3, Mobile) */
+ case (0x248B<<16)|0x8086: /* 82801CA (ICH3, High-End) */
+ case (0x24CA<<16)|0x8086: /* 82801DBM (ICH4, Mobile) */
+ case (0x24CB<<16)|0x8086: /* 82801DB (ICH4, High-End) */
+ case (0x24DB<<16)|0x8086: /* 82801EB (ICH5) */
+ case (0x25A3<<16)|0x8086: /* 6300ESB (E7210) */
+ case (0x266F<<16)|0x8086: /* 82801FB (ICH6) */
+ case (0x27DF<<16)|0x8086: /* 82801G SATA (ICH7) */
+ case (0x27C0<<16)|0x8086: /* 82801GB SATA AHCI (ICH7) */
+// case (0x27C4<<16)|0x8086: /* 82801GBM SATA (ICH7) */
+ case (0x27C5<<16)|0x8086: /* 82801GBM SATA AHCI (ICH7) */
+ case (0x2920<<16)|0x8086: /* 82801(IB)/IR/IH/IO SATA IDE (ICH9) */
+ case (0x3a20<<16)|0x8086: /* 82801JI (ICH10) */
+ case (0x3a26<<16)|0x8086: /* 82801JI (ICH10) */
+ break;
+ }
+
+ for(channel = 0; channel < 2; channel++){
+ if(pi & (1<<(2*channel))){
+ sdev = ataprobe(p->mem[0+2*channel].bar & ~0x01,
+ p->mem[1+2*channel].bar & ~0x01,
+ p->intl);
+ if(sdev == nil)
+ continue;
+
+ ctlr = sdev->ctlr;
+ if(ispc87415) {
+ ctlr->ienable = pc87415ienable;
+ print("pc87415disable: not yet implemented\n");
+ }
+
+ if(head != nil)
+ tail->next = sdev;
+ else
+ head = sdev;
+ tail = sdev;
+ ctlr->tbdf = p->tbdf;
+ }
+ else if((sdev = legacy[channel]) == nil)
+ continue;
+ else
+ 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;
+ }
+ }
+
+if(0){
+ int port;
+ ISAConf isa;
+
+ /*
+ * Hack for PCMCIA drives.
+ * This will be tidied once we figure out how the whole
+ * removeable device thing is going to work.
+ */
+ memset(&isa, 0, sizeof(isa));
+ isa.port = 0x180; /* change this for your machine */
+ isa.irq = 11; /* change this for your machine */
+
+ port = isa.port+0x0C;
+ channel = pcmspecial("MK2001MPL", &isa);
+ if(channel == -1)
+ channel = pcmspecial("SunDisk", &isa);
+ if(channel == -1){
+ isa.irq = 10;
+ channel = pcmspecial("CF", &isa);
+ }
+ if(channel == -1){
+ isa.irq = 10;
+ channel = pcmspecial("OLYMPUS", &isa);
+ }
+ if(channel == -1){
+ port = isa.port+0x204;
+ channel = pcmspecial("ATA/ATAPI", &isa);
+ }
+ if(channel >= 0 && (sdev = ataprobe(isa.port, port, isa.irq)) != nil){
+ if(head != nil)
+ tail->next = sdev;
+ else
+ head = sdev;
+ }
+}
+ return head;
+}
+
+static SDev*
+atalegacy(int port, int irq)
+{
+ return ataprobe(port, port+0x204, irq);
+}
+
+static int
+ataenable(SDev* sdev)
+{
+ Ctlr *ctlr;
+ char name[32];
+
+ ctlr = sdev->ctlr;
+
+ if(ctlr->bmiba){
+#define ALIGN (4 * 1024)
+ if(ctlr->pcidev != nil)
+ pcisetbme(ctlr->pcidev);
+ ctlr->prdt = mallocalign(Nprd*sizeof(Prd), 4, 0, 4*1024);
+ }
+ snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name);
+ intrenable(ctlr->irq, atainterrupt, ctlr, ctlr->tbdf, name);
+ outb(ctlr->ctlport+Dc, 0);
+ if(ctlr->ienable)
+ ctlr->ienable(ctlr);
+
+ return 1;
+}
+
+static int
+atadisable(SDev *sdev)
+{
+ Ctlr *ctlr;
+ char name[32];
+
+ ctlr = sdev->ctlr;
+ outb(ctlr->ctlport+Dc, Nien); /* disable interrupts */
+ if (ctlr->idisable)
+ ctlr->idisable(ctlr);
+ snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name);
+ intrdisable(ctlr->irq, atainterrupt, ctlr, ctlr->tbdf, name);
+ if (ctlr->bmiba) {
+ if (ctlr->pcidev)
+ pciclrbme(ctlr->pcidev);
+ free(ctlr->prdt);
+ }
+ return 0;
+}
+
+static int
+atarctl(SDunit* unit, char* p, int l)
+{
+ int n;
+ Ctlr *ctlr;
+ Drive *drive;
+
+ if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil)
+ return 0;
+ drive = ctlr->drive[unit->subno];
+
+ qlock(drive);
+ n = snprint(p, l, "config %4.4uX capabilities %4.4uX",
+ drive->info[Iconfig], drive->info[Icapabilities]);
+ if(drive->dma)
+ n += snprint(p+n, l-n, " dma %8.8uX dmactl %8.8uX",
+ drive->dma, drive->dmactl);
+ if(drive->rwm)
+ n += snprint(p+n, l-n, " rwm %ud rwmctl %ud",
+ drive->rwm, drive->rwmctl);
+ if(drive->flags&Lba48)
+ n += snprint(p+n, l-n, " lba48always %s",
+ (drive->flags&Lba48always) ? "on" : "off");
+ n += snprint(p+n, l-n, "\n");
+ if(drive->sectors){
+ n += snprint(p+n, l-n, "geometry %lld %d",
+ drive->sectors, drive->secsize);
+ if(drive->pkt == 0)
+ n += snprint(p+n, l-n, " %d %d %d",
+ drive->c, drive->h, drive->s);
+ n += snprint(p+n, l-n, "\n");
+ }
+ qunlock(drive);
+
+ return n;
+}
+
+static int
+atawctl(SDunit* unit, Cmdbuf* cb)
+{
+ int period;
+ Ctlr *ctlr;
+ Drive *drive;
+
+ if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil)
+ return 0;
+ drive = ctlr->drive[unit->subno];
+
+ qlock(drive);
+ if(waserror()){
+ qunlock(drive);
+ nexterror();
+ }
+
+ /*
+ * Dma and rwm control is passive at the moment,
+ * i.e. it is assumed that the hardware is set up
+ * correctly already either by the BIOS or when
+ * the drive was initially identified.
+ */
+ if(strcmp(cb->f[0], "dma") == 0){
+ if(cb->nf != 2 || drive->dma == 0)
+ error(Ebadctl);
+ if(strcmp(cb->f[1], "on") == 0)
+ drive->dmactl = drive->dma;
+ else if(strcmp(cb->f[1], "off") == 0)
+ drive->dmactl = 0;
+ else
+ error(Ebadctl);
+ }
+ else if(strcmp(cb->f[0], "rwm") == 0){
+ if(cb->nf != 2 || drive->rwm == 0)
+ error(Ebadctl);
+ if(strcmp(cb->f[1], "on") == 0)
+ drive->rwmctl = drive->rwm;
+ else if(strcmp(cb->f[1], "off") == 0)
+ drive->rwmctl = 0;
+ else
+ error(Ebadctl);
+ }
+ else if(strcmp(cb->f[0], "standby") == 0){
+ switch(cb->nf){
+ default:
+ error(Ebadctl);
+ case 2:
+ period = strtol(cb->f[1], 0, 0);
+ if(period && (period < 30 || period > 240*5))
+ error(Ebadctl);
+ period /= 5;
+ break;
+ }
+ if(atastandby(drive, period) != SDok)
+ error(Ebadctl);
+ }
+ else if(strcmp(cb->f[0], "lba48always") == 0){
+ if(cb->nf != 2 || !(drive->flags&Lba48))
+ error(Ebadctl);
+ if(strcmp(cb->f[1], "on") == 0)
+ drive->flags |= Lba48always;
+ else if(strcmp(cb->f[1], "off") == 0)
+ drive->flags &= ~Lba48always;
+ else
+ error(Ebadctl);
+ }
+ else
+ error(Ebadctl);
+ qunlock(drive);
+ poperror();
+
+ return 0;
+}
+
+SDifc sdataifc = {
+ "ata", /* name */
+
+ atapnp, /* pnp */
+ atalegacy, /* legacy */
+ ataenable, /* enable */
+ atadisable, /* disable */
+
+ scsiverify, /* verify */
+ scsionline, /* online */
+ atario, /* rio */
+ atarctl, /* rctl */
+ atawctl, /* wctl */
+
+ scsibio, /* bio */
+ ataprobew, /* probe */
+ ataclear, /* clear */
+ atastat, /* rtopctl */
+ nil, /* wtopctl */
+};
diff --git a/sys/src/9/pc/sdiahci.c b/sys/src/9/pc/sdiahci.c
new file mode 100755
index 000000000..73e46fc63
--- /dev/null
+++ b/sys/src/9/pc/sdiahci.c
@@ -0,0 +1,2298 @@
+/*
+ * intel/amd ahci sata controller
+ * copyright © 2007-8 coraid, inc.
+ */
+
+#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"
+#include "ahci.h"
+
+#define dprint(...) if(debug) iprint(__VA_ARGS__); else USED(debug)
+#define idprint(...) if(prid) iprint(__VA_ARGS__); else USED(prid)
+#define aprint(...) if(datapi) iprint(__VA_ARGS__); else USED(datapi)
+#define Tname(c) tname[(c)->type]
+
+enum {
+ NCtlr = 4,
+ NCtlrdrv= 32,
+ NDrive = NCtlr*NCtlrdrv,
+
+ Read = 0,
+ Write,
+};
+
+/* pci space configuration */
+enum {
+ Pmap = 0x90,
+ Ppcs = 0x91,
+ Prev = 0xa8,
+};
+
+enum {
+ Tesb,
+ Tich,
+ Tsb600,
+ Tunk,
+};
+
+#define Intel(x) ((x)->pci->vid == 0x8086)
+
+static char *tname[] = {
+ "63xxesb",
+ "ich",
+ "sb600",
+ "unk",
+};
+
+enum {
+ Dnull,
+ Dmissing,
+ Dnew,
+ Dready,
+ Derror,
+ Dreset,
+ Doffline,
+ Dportreset,
+ Dlast,
+};
+
+static char *diskstates[Dlast] = {
+ "null",
+ "missing",
+ "new",
+ "ready",
+ "error",
+ "reset",
+ "offline",
+ "portreset",
+};
+
+extern SDifc sdiahciifc;
+typedef struct Ctlr Ctlr;
+
+enum {
+ DMautoneg,
+ DMsatai,
+ DMsataii,
+};
+
+static char *modename[] = {
+ "auto",
+ "satai",
+ "sataii",
+};
+
+static char *flagname[] = {
+ "llba",
+ "smart",
+ "power",
+ "nop",
+ "atapi",
+ "atapi16",
+};
+
+typedef struct {
+ Lock;
+
+ Ctlr *ctlr;
+ SDunit *unit;
+ char name[10];
+ Aport *port;
+ Aportm portm;
+ Aportc portc; /* redundant ptr to port and portm */
+
+ uchar mediachange;
+ uchar state;
+ uchar smartrs;
+
+ uvlong sectors;
+ ulong secsize;
+ ulong intick; /* start tick of current transfer */
+ ulong lastseen;
+ int wait;
+ uchar mode; /* DMautoneg, satai or sataii */
+ uchar active;
+
+ char serial[20+1];
+ char firmware[8+1];
+ char model[40+1];
+
+ ushort info[0x200];
+
+ int driveno; /* ctlr*NCtlrdrv + unit */
+ /* controller port # != driveno when not all ports are enabled */
+ int portno;
+} Drive;
+
+struct Ctlr {
+ Lock;
+
+ int type;
+ int enabled;
+ SDev *sdev;
+ Pcidev *pci;
+
+ uchar *mmio;
+ ulong *lmmio;
+ Ahba *hba;
+
+ Drive rawdrive[NCtlrdrv];
+ Drive* drive[NCtlrdrv];
+ int ndrive;
+ int mport;
+};
+
+static Ctlr iactlr[NCtlr];
+static SDev sdevs[NCtlr];
+static int niactlr;
+
+static Drive *iadrive[NDrive];
+static int niadrive;
+
+/* these are fiddled in iawtopctl() */
+static int debug;
+static int prid = 1;
+static int datapi;
+
+static char stab[] = {
+[0] 'i', 'm',
+[8] 't', 'c', 'p', 'e',
+[16] 'N', 'I', 'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X'
+};
+
+static void
+serrstr(ulong r, char *s, char *e)
+{
+ int i;
+
+ e -= 3;
+ for(i = 0; i < nelem(stab) && s < e; i++)
+ if(r & (1<<i) && stab[i]){
+ *s++ = stab[i];
+ if(SerrBad & (1<<i))
+ *s++ = '*';
+ }
+ *s = 0;
+}
+
+static char ntab[] = "0123456789abcdef";
+
+static void
+preg(uchar *reg, int n)
+{
+ int i;
+ char buf[25*3+1], *e;
+
+ e = buf;
+ for(i = 0; i < n; i++){
+ *e++ = ntab[reg[i]>>4];
+ *e++ = ntab[reg[i]&0xf];
+ *e++ = ' ';
+ }
+ *e++ = '\n';
+ *e = 0;
+ dprint(buf);
+}
+
+static void
+dreg(char *s, Aport *p)
+{
+ dprint("ahci: %stask=%lux; cmd=%lux; ci=%lux; is=%lux\n",
+ s, p->task, p->cmd, p->ci, p->isr);
+}
+
+static void
+esleep(int ms)
+{
+ if(waserror())
+ return;
+ tsleep(&up->sleep, return0, 0, ms);
+ poperror();
+}
+
+typedef struct {
+ Aport *p;
+ int i;
+}Asleep;
+
+static int
+ahciclear(void *v)
+{
+ Asleep *s;
+
+ s = v;
+ return (s->p->ci & s->i) == 0;
+}
+
+static void
+aesleep(Aportm *m, Asleep *a, int ms)
+{
+ if(waserror())
+ return;
+ tsleep(m, ahciclear, a, ms);
+ poperror();
+}
+
+static int
+ahciwait(Aportc *c, int ms)
+{
+ Asleep as;
+ Aport *p;
+
+ p = c->p;
+ p->ci = 1;
+ as.p = p;
+ as.i = 1;
+ aesleep(c->m, &as, ms);
+ if((p->task&1) == 0 && p->ci == 0)
+ return 0;
+ dreg("ahciwait timeout ", c->p);
+ return -1;
+}
+
+static int
+nop(Aportc *pc)
+{
+ uchar *c;
+ Actab *t;
+ Alist *l;
+
+ if((pc->m->feat & Dnop) == 0)
+ return -1;
+
+ t = pc->m->ctab;
+ c = t->cfis;
+
+ memset(c, 0, 0x20);
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = 0x00;
+ c[7] = 0xa0; /* obsolete device bits */
+
+ l = pc->m->list;
+ l->flags = Lwrite | 0x5;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ return ahciwait(pc, 3*1000);
+}
+
+static int
+setfeatures(Aportc *pc, uchar f)
+{
+ uchar *c;
+ Actab *t;
+ Alist *l;
+
+ t = pc->m->ctab;
+ c = t->cfis;
+
+ memset(c, 0, 0x20);
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = 0xef;
+ c[3] = f;
+ c[7] = 0xa0; /* obsolete device bits */
+
+ l = pc->m->list;
+ l->flags = Lwrite | 0x5;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ return ahciwait(pc, 3*1000);
+}
+
+static int
+setudmamode(Aportc *pc, uchar f)
+{
+ uchar *c;
+ Actab *t;
+ Alist *l;
+
+ /* hack */
+ if((pc->p->sig >> 16) == 0xeb14)
+ return 0;
+
+ t = pc->m->ctab;
+ c = t->cfis;
+
+ memset(c, 0, 0x20);
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = 0xef;
+ c[3] = 3; /* set transfer mode */
+ c[7] = 0xa0; /* obsolete device bits */
+ c[12] = 0x40 | f; /* sector count */
+
+ l = pc->m->list;
+ l->flags = Lwrite | 0x5;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ return ahciwait(pc, 3*1000);
+}
+
+static void
+asleep(int ms)
+{
+ if(up == nil)
+ delay(ms);
+ else
+ esleep(ms);
+}
+
+static int
+ahciportreset(Aportc *c)
+{
+ ulong *cmd, i;
+ Aport *p;
+
+ p = c->p;
+ cmd = &p->cmd;
+ *cmd &= ~(Afre|Ast);
+ for(i = 0; i < 500; i += 25){
+ if((*cmd&Acr) == 0)
+ break;
+ asleep(25);
+ }
+ p->sctl = 1|(p->sctl&~7);
+ delay(1);
+ p->sctl &= ~7;
+ return 0;
+}
+
+static int
+smart(Aportc *pc, int n)
+{
+ uchar *c;
+ Actab *t;
+ Alist *l;
+
+ if((pc->m->feat&Dsmart) == 0)
+ return -1;
+
+ t = pc->m->ctab;
+ c = t->cfis;
+
+ memset(c, 0, 0x20);
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = 0xb0;
+ c[3] = 0xd8 + n; /* able smart */
+ c[5] = 0x4f;
+ c[6] = 0xc2;
+ c[7] = 0xa0;
+
+ l = pc->m->list;
+ l->flags = Lwrite | 0x5;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ if(ahciwait(pc, 1000) == -1 || pc->p->task & (1|32)){
+ dprint("ahci: smart fail %lux\n", pc->p->task);
+// preg(pc->m->fis.r, 20);
+ return -1;
+ }
+ if(n)
+ return 0;
+ return 1;
+}
+
+static int
+smartrs(Aportc *pc)
+{
+ uchar *c;
+ Actab *t;
+ Alist *l;
+
+ t = pc->m->ctab;
+ c = t->cfis;
+
+ memset(c, 0, 0x20);
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = 0xb0;
+ c[3] = 0xda; /* return smart status */
+ c[5] = 0x4f;
+ c[6] = 0xc2;
+ c[7] = 0xa0;
+
+ l = pc->m->list;
+ l->flags = Lwrite | 0x5;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ c = pc->m->fis.r;
+ if(ahciwait(pc, 1000) == -1 || pc->p->task & (1|32)){
+ dprint("ahci: smart fail %lux\n", pc->p->task);
+ preg(c, 20);
+ return -1;
+ }
+ if(c[5] == 0x4f && c[6] == 0xc2)
+ return 1;
+ return 0;
+}
+
+static int
+ahciflushcache(Aportc *pc)
+{
+ uchar *c, llba;
+ Actab *t;
+ Alist *l;
+ static uchar tab[2] = {0xe7, 0xea};
+
+ llba = pc->m->feat&Dllba? 1: 0;
+ t = pc->m->ctab;
+ c = t->cfis;
+
+ memset(c, 0, 0x20);
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = tab[llba];
+ c[7] = 0xa0;
+
+ l = pc->m->list;
+ l->flags = Lwrite | 0x5;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ if(ahciwait(pc, 60000) == -1 || pc->p->task & (1|32)){
+ dprint("ahciflushcache: fail %lux\n", pc->p->task);
+// preg( pc->m->fis.r, 20);
+ return -1;
+ }
+ return 0;
+}
+
+static ushort
+gbit16(void *a)
+{
+ uchar *i;
+
+ i = a;
+ return i[1]<<8 | i[0];
+}
+
+static ulong
+gbit32(void *a)
+{
+ ulong j;
+ uchar *i;
+
+ i = a;
+ j = i[3] << 24;
+ j |= i[2] << 16;
+ j |= i[1] << 8;
+ j |= i[0];
+ return j;
+}
+
+static uvlong
+gbit64(void *a)
+{
+ uchar *i;
+
+ i = a;
+ return (uvlong)gbit32(i+4) << 32 | gbit32(a);
+}
+
+static int
+ahciidentify0(Aportc *pc, void *id, int atapi)
+{
+ uchar *c;
+ Actab *t;
+ Alist *l;
+ Aprdt *p;
+ static uchar tab[] = { 0xec, 0xa1, };
+
+ t = pc->m->ctab;
+ c = t->cfis;
+
+ memset(c, 0, 0x20);
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = tab[atapi];
+ c[7] = 0xa0; /* obsolete device bits */
+
+ l = pc->m->list;
+ l->flags = 1<<16 | 0x5;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ memset(id, 0, 0x100);
+ p = &t->prdt;
+ p->dba = PCIWADDR(id);
+ p->dbahi = 0;
+ p->count = 1<<31 | (0x200-2) | 1;
+
+ return ahciwait(pc, 3*1000);
+}
+
+static vlong
+ahciidentify(Aportc *pc, ushort *id)
+{
+ int i, sig;
+ vlong s;
+ Aportm *m;
+
+ m = pc->m;
+ m->feat = 0;
+ m->smart = 0;
+ i = 0;
+ sig = pc->p->sig >> 16;
+ if(sig == 0xeb14){
+ m->feat |= Datapi;
+ i = 1;
+ }
+ if(ahciidentify0(pc, id, i) == -1)
+ return -1;
+
+ i = gbit16(id+83) | gbit16(id+86);
+ if(i & (1<<10)){
+ m->feat |= Dllba;
+ s = gbit64(id+100);
+ }else
+ s = gbit32(id+60);
+
+ if(m->feat&Datapi){
+ i = gbit16(id+0);
+ if(i&1)
+ m->feat |= Datapi16;
+ }
+
+ i = gbit16(id+83);
+ if((i>>14) == 1) {
+ if(i & (1<<3))
+ m->feat |= Dpower;
+ i = gbit16(id+82);
+ if(i & 1)
+ m->feat |= Dsmart;
+ if(i & (1<<14))
+ m->feat |= Dnop;
+ }
+ return s;
+}
+
+static int
+ahciquiet(Aport *a)
+{
+ ulong *p, i;
+
+ p = &a->cmd;
+ *p &= ~Ast;
+ for(i = 0; i < 500; i += 50){
+ if((*p & Acr) == 0)
+ goto stop;
+ asleep(50);
+ }
+ return -1;
+stop:
+ if((a->task & (ASdrq|ASbsy)) == 0){
+ *p |= Ast;
+ return 0;
+ }
+
+ *p |= Aclo;
+ for(i = 0; i < 500; i += 50){
+ if((*p & Aclo) == 0)
+ goto stop1;
+ asleep(50);
+ }
+ return -1;
+stop1:
+ /* extra check */
+ dprint("ahci: clo clear %lx\n", a->task);
+ if(a->task & ASbsy)
+ return -1;
+ *p |= Ast;
+ return 0;
+}
+
+static int
+ahcicomreset(Aportc *pc)
+{
+ uchar *c;
+ Actab *t;
+ Alist *l;
+
+ dprint("ahcicomreset\n");
+ dreg("ahci: comreset ", pc->p);
+ if(ahciquiet(pc->p) == -1){
+ dprint("ahciquiet failed\n");
+ return -1;
+ }
+ dreg("comreset ", pc->p);
+
+ t = pc->m->ctab;
+ c = t->cfis;
+
+ memset(c, 0, 0x20);
+ c[0] = 0x27;
+ c[1] = 0x00;
+ c[7] = 0xa0; /* obsolete device bits */
+ c[15] = 1<<2; /* srst */
+
+ l = pc->m->list;
+ l->flags = Lclear | Lreset | 0x5;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ if(ahciwait(pc, 500) == -1){
+ dprint("ahcicomreset: first command failed\n");
+ return -1;
+ }
+ microdelay(250);
+ dreg("comreset ", pc->p);
+
+ memset(c, 0, 0x20);
+ c[0] = 0x27;
+ c[1] = 0x00;
+ c[7] = 0xa0; /* obsolete device bits */
+
+ l = pc->m->list;
+ l->flags = Lwrite | 0x5;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ if(ahciwait(pc, 150) == -1){
+ dprint("ahcicomreset: second command failed\n");
+ return -1;
+ }
+ dreg("comreset ", pc->p);
+ return 0;
+}
+
+static int
+ahciidle(Aport *port)
+{
+ ulong *p, i, r;
+
+ p = &port->cmd;
+ if((*p & Arun) == 0)
+ return 0;
+ *p &= ~Ast;
+ r = 0;
+ for(i = 0; i < 500; i += 25){
+ if((*p & Acr) == 0)
+ goto stop;
+ asleep(25);
+ }
+ r = -1;
+stop:
+ if((*p & Afre) == 0)
+ return r;
+ *p &= ~Afre;
+ for(i = 0; i < 500; i += 25){
+ if((*p & Afre) == 0)
+ return 0;
+ asleep(25);
+ }
+ return -1;
+}
+
+/*
+ * § 6.2.2.1 first part; comreset handled by reset disk.
+ * - remainder is handled by configdisk.
+ * - ahcirecover is a quick recovery from a failed command.
+ */
+static int
+ahciswreset(Aportc *pc)
+{
+ int i;
+
+ i = ahciidle(pc->p);
+ pc->p->cmd |= Afre;
+ if(i == -1)
+ return -1;
+ if(pc->p->task & (ASdrq|ASbsy))
+ return -1;
+ return 0;
+}
+
+static int
+ahcirecover(Aportc *pc)
+{
+ ahciswreset(pc);
+ pc->p->cmd |= Ast;
+ if(setudmamode(pc, 5) == -1)
+ return -1;
+ return 0;
+}
+
+static void*
+malign(int size, int align)
+{
+ void *v;
+
+ v = xspanalloc(size, align, 0);
+ memset(v, 0, size);
+ return v;
+}
+
+static void
+setupfis(Afis *f)
+{
+ f->base = malign(0x100, 0x100);
+ f->d = f->base + 0;
+ f->p = f->base + 0x20;
+ f->r = f->base + 0x40;
+ f->u = f->base + 0x60;
+ f->devicebits = (ulong*)(f->base + 0x58);
+}
+
+static void
+ahciwakeup(Aport *p)
+{
+ ushort s;
+
+ s = p->sstatus;
+ if((s & 0xF00) != 0x600)
+ return;
+ if((s & 7) != 1){ /* not (device, no phy) */
+ iprint("ahci: slumbering drive unwakable %ux\n", s);
+ return;
+ }
+ p->sctl = 3*Aipm | 0*Aspd | Adet;
+ delay(1);
+ p->sctl &= ~7;
+// iprint("ahci: wake %ux -> %ux\n", s, p->sstatus);
+}
+
+static int
+ahciconfigdrive(Ahba *h, Aportc *c, int mode)
+{
+ Aportm *m;
+ Aport *p;
+
+ p = c->p;
+ m = c->m;
+
+ if(m->list == 0){
+ setupfis(&m->fis);
+ m->list = malign(sizeof *m->list, 1024);
+ m->ctab = malign(sizeof *m->ctab, 128);
+ }
+
+ if(p->sstatus & 3 && h->cap & Hsss){
+ /* device connected & staggered spin-up */
+ dprint("ahci: configdrive: spinning up ... [%lux]\n",
+ p->sstatus);
+ p->cmd |= Apod|Asud;
+ asleep(1400);
+ }
+
+ p->serror = SerrAll;
+
+ p->list = PCIWADDR(m->list);
+ p->listhi = 0;
+ p->fis = PCIWADDR(m->fis.base);
+ p->fishi = 0;
+ p->cmd |= Afre|Ast;
+
+ if((p->sstatus & 0xF0F) == 0x601) /* drive coming up in slumbering? */
+ ahciwakeup(p);
+
+ /* disable power managment sequence from book. */
+ p->sctl = (3*Aipm) | (mode*Aspd) | (0*Adet);
+ p->cmd &= ~Aalpe;
+
+ p->ie = IEM;
+
+ return 0;
+}
+
+static int
+ahcienable(Ahba *h)
+{
+ h->ghc |= Hie;
+ return 0;
+}
+
+static int
+ahcidisable(Ahba *h)
+{
+ h->ghc &= ~Hie;
+ return 0;
+}
+
+static int
+countbits(ulong u)
+{
+ int i, n;
+
+ n = 0;
+ for(i = 0; i < 32; i++)
+ if(u & (1<<i))
+ n++;
+ return n;
+}
+
+static int
+ahciconf(Ctlr *ctlr)
+{
+ Ahba *h;
+ ulong u;
+
+ h = ctlr->hba = (Ahba*)ctlr->mmio;
+ u = h->cap;
+
+ if((u&Hsam) == 0)
+ h->ghc |= Hae;
+
+ print("#S/sd%c: ahci %s port %#p: sss %ld ncs %ld coal %ld "
+ "mports %ld led %ld clo %ld ems %ld\n",
+ ctlr->sdev->idno, tname[ctlr->type], h,
+ (u>>27) & 1, (u>>8) & 0x1f, (u>>7) & 1, u & 0x1f, (u>>25) & 1,
+ (u>>24) & 1, (u>>6) & 1);
+ return countbits(h->pi);
+}
+
+static int
+ahcihbareset(Ahba *h)
+{
+ int wait;
+
+ h->ghc |= 1;
+ for(wait = 0; wait < 1000; wait += 100){
+ if(h->ghc == 0)
+ return 0;
+ delay(100);
+ }
+ return -1;
+}
+
+static void
+idmove(char *p, ushort *a, int n)
+{
+ int i;
+ char *op, *e;
+
+ op = p;
+ for(i = 0; i < n/2; i++){
+ *p++ = a[i] >> 8;
+ *p++ = a[i];
+ }
+ *p = 0;
+ while(p > op && *--p == ' ')
+ *p = 0;
+ e = p;
+ for (p = op; *p == ' '; p++)
+ ;
+ memmove(op, p, n - (e - p));
+}
+
+static int
+identify(Drive *d)
+{
+ ushort *id;
+ vlong osectors, s;
+ uchar oserial[21];
+ SDunit *u;
+
+ id = d->info;
+ s = ahciidentify(&d->portc, id);
+ if(s == -1){
+ d->state = Derror;
+ return -1;
+ }
+ osectors = d->sectors;
+ memmove(oserial, d->serial, sizeof d->serial);
+
+ u = d->unit;
+ d->sectors = s;
+ d->secsize = u->secsize;
+ if(d->secsize == 0)
+ d->secsize = 512; /* default */
+ d->smartrs = 0;
+
+ idmove(d->serial, id+10, 20);
+ idmove(d->firmware, id+23, 8);
+ idmove(d->model, id+27, 40);
+
+ memset(u->inquiry, 0, sizeof u->inquiry);
+ u->inquiry[2] = 2;
+ u->inquiry[3] = 2;
+ u->inquiry[4] = sizeof u->inquiry - 4;
+ memmove(u->inquiry+8, d->model, 40);
+
+ if(osectors != s || memcmp(oserial, d->serial, sizeof oserial) != 0){
+ d->mediachange = 1;
+ u->sectors = 0;
+ }
+ return 0;
+}
+
+static void
+clearci(Aport *p)
+{
+ if(p->cmd & Ast) {
+ p->cmd &= ~Ast;
+ p->cmd |= Ast;
+ }
+}
+
+static void
+updatedrive(Drive *d)
+{
+ ulong cause, serr, s0, pr, ewake;
+ char *name;
+ Aport *p;
+ static ulong last;
+
+ pr = 1;
+ ewake = 0;
+ p = d->port;
+ cause = p->isr;
+ serr = p->serror;
+ p->isr = cause;
+ name = "??";
+ if(d->unit && d->unit->name)
+ name = d->unit->name;
+
+ if(p->ci == 0){
+ d->portm.flag |= Fdone;
+ wakeup(&d->portm);
+ pr = 0;
+ }else if(cause & Adps)
+ pr = 0;
+ if(cause & Ifatal){
+ ewake = 1;
+ dprint("ahci: updatedrive: fatal\n");
+ }
+ if(cause & Adhrs){
+ if(p->task & (1<<5|1)){
+ dprint("ahci: Adhrs cause %lux serr %lux task %lux\n",
+ cause, serr, p->task);
+ d->portm.flag |= Ferror;
+ ewake = 1;
+ }
+ pr = 0;
+ }
+ if(p->task & 1 && last != cause)
+ dprint("%s: err ca %lux serr %lux task %lux sstat %lux\n",
+ name, cause, serr, p->task, p->sstatus);
+ if(pr)
+ dprint("%s: upd %lux ta %lux\n", name, cause, p->task);
+
+ if(cause & (Aprcs|Aifs)){
+ s0 = d->state;
+ switch(p->sstatus & 7){
+ case 0: /* no device */
+ d->state = Dmissing;
+ break;
+ case 1: /* device but no phy comm. */
+ if((p->sstatus & 0xF00) == 0x600)
+ d->state = Dnew; /* slumbering */
+ else
+ d->state = Derror;
+ break;
+ case 3: /* device & phy comm. estab. */
+ /* power mgnt crap for surprise removal */
+ p->ie |= Aprcs|Apcs; /* is this required? */
+ d->state = Dreset;
+ break;
+ case 4: /* phy off-line */
+ d->state = Doffline;
+ break;
+ }
+ dprint("%s: %s → %s [Apcrs] %lux\n", name,
+ diskstates[s0], diskstates[d->state], p->sstatus);
+ /* print pulled message here. */
+ if(s0 == Dready && d->state != Dready)
+ idprint("%s: pulled\n", name);
+ if(d->state != Dready)
+ d->portm.flag |= Ferror;
+ ewake = 1;
+ }
+ p->serror = serr;
+ if(ewake){
+ clearci(p);
+ wakeup(&d->portm);
+ }
+ last = cause;
+}
+
+static void
+pstatus(Drive *d, ulong s)
+{
+ /*
+ * bogus code because the first interrupt is currently dropped.
+ * likely my fault. serror may be cleared at the wrong time.
+ */
+ switch(s){
+ case 0: /* no device */
+ d->state = Dmissing;
+ break;
+ case 1: /* device but no phy. comm. */
+ break;
+ case 2: /* should this be missing? need testcase. */
+ dprint("ahci: pstatus 2\n");
+ /* fallthrough */
+ case 3: /* device & phy. comm. */
+ d->wait = 0;
+ d->state = Dnew;
+ break;
+ case 4: /* offline */
+ d->state = Doffline;
+ break;
+ case 6: /* ? not sure this makes sense. TODO */
+ d->state = Dnew;
+ break;
+ }
+}
+
+static int
+configdrive(Drive *d)
+{
+ if(ahciconfigdrive(d->ctlr->hba, &d->portc, d->mode) == -1)
+ return -1;
+ ilock(d);
+ pstatus(d, d->port->sstatus & 7);
+ iunlock(d);
+ return 0;
+}
+
+static void
+resetdisk(Drive *d)
+{
+ uint state, det, stat;
+ Aport *p;
+
+ p = d->port;
+ det = p->sctl & 7;
+ stat = p->sstatus & 7;
+ state = (p->cmd>>28) & 0xf;
+ dprint("ahci: resetdisk: icc %ux det %d sdet %d\n", state, det, stat);
+
+ ilock(d);
+ state = d->state;
+ if(d->state != Dready || d->state != Dnew)
+ d->portm.flag |= Ferror;
+ clearci(p); /* satisfy sleep condition. */
+ wakeup(&d->portm);
+ if(stat != 3){ /* device absent or phy not communicating? */
+ d->state = Dportreset;
+ iunlock(d);
+ return;
+ }
+ d->state = Derror;
+ iunlock(d);
+
+ qlock(&d->portm);
+ if(p->cmd&Ast && ahciswreset(&d->portc) == -1){
+ ilock(d);
+ d->state = Dportreset; /* get a bigger stick. */
+ iunlock(d);
+ } else {
+ ilock(d);
+ d->state = Dmissing;
+ iunlock(d);
+
+ configdrive(d);
+ }
+ dprint("ahci: resetdisk: %s → %s\n",
+ diskstates[state], diskstates[d->state]);
+ qunlock(&d->portm);
+}
+
+static int
+newdrive(Drive *d)
+{
+ char *name;
+ Aportc *c;
+ Aportm *m;
+
+ c = &d->portc;
+ m = &d->portm;
+
+ name = d->unit->name;
+ if(name == 0)
+ name = "??";
+
+ if(d->port->task == 0x80)
+ return -1;
+ qlock(c->m);
+ if(setudmamode(c, 5) == -1){
+ dprint("%s: can't set udma mode\n", name);
+ goto lose;
+ }
+ if(identify(d) == -1){
+ dprint("%s: identify failure\n", name);
+ goto lose;
+ }
+ if(m->feat & Dpower && setfeatures(c, 0x85) == -1){
+ m->feat &= ~Dpower;
+ if(ahcirecover(c) == -1)
+ goto lose;
+ }
+
+ ilock(d);
+ d->state = Dready;
+ iunlock(d);
+
+ qunlock(c->m);
+
+ idprint("%s: %sLBA %,llud sectors: %s %s %s %s\n", d->unit->name,
+ (m->feat & Dllba? "L": ""), d->sectors, d->model, d->firmware,
+ d->serial, d->mediachange? "[mediachange]": "");
+ return 0;
+
+lose:
+ idprint("%s: can't be initialized\n", d->unit->name);
+ ilock(d);
+ d->state = Dnull;
+ iunlock(d);
+ qunlock(c->m);
+ return -1;
+}
+
+enum {
+ Nms = 256,
+ Mphywait = 2*1024/Nms - 1,
+ Midwait = 16*1024/Nms - 1,
+ Mcomrwait = 64*1024/Nms - 1,
+};
+
+static void
+westerndigitalhung(Drive *d)
+{
+ if((d->portm.feat&Datapi) == 0 && d->active &&
+ TK2MS(MACHP(0)->ticks - d->intick) > 5000){
+ dprint("%s: drive hung; resetting [%lux] ci %lx\n",
+ d->unit->name, d->port->task, d->port->ci);
+ d->state = Dreset;
+ }
+}
+
+static ushort olds[NCtlr*NCtlrdrv];
+
+static int
+doportreset(Drive *d)
+{
+ int i;
+
+ i = -1;
+ qlock(&d->portm);
+ if(ahciportreset(&d->portc) == -1)
+ dprint("ahci: doportreset: fails\n");
+ else
+ i = 0;
+ qunlock(&d->portm);
+ dprint("ahci: doportreset: portreset → %s [task %lux]\n",
+ diskstates[d->state], d->port->task);
+ return i;
+}
+
+/* drive must be locked */
+static void
+statechange(Drive *d)
+{
+ switch(d->state){
+ case Dnull:
+ case Doffline:
+ if(d->unit->sectors != 0){
+ d->sectors = 0;
+ d->mediachange = 1;
+ }
+ /* fallthrough */
+ case Dready:
+ d->wait = 0;
+ break;
+ }
+}
+
+static void
+checkdrive(Drive *d, int i)
+{
+ ushort s;
+ char *name;
+
+ if(d == nil) {
+ print("checkdrive: nil d\n");
+ return;
+ }
+ ilock(d);
+ if(d->unit == nil || d->port == nil) {
+ if(0)
+ print("checkdrive: nil d->%s\n",
+ d->unit == nil? "unit": "port");
+ iunlock(d);
+ return;
+ }
+ name = d->unit->name;
+ s = d->port->sstatus;
+ if(s)
+ d->lastseen = MACHP(0)->ticks;
+ if(s != olds[i]){
+ dprint("%s: status: %04ux -> %04ux: %s\n",
+ name, olds[i], s, diskstates[d->state]);
+ olds[i] = s;
+ d->wait = 0;
+ }
+ westerndigitalhung(d);
+ switch(d->state){
+ case Dnull:
+ case Dready:
+ break;
+ case Dmissing:
+ case Dnew:
+ switch(s & 0x107){
+ case 1: /* no device (pm), device but no phy. comm. */
+ ahciwakeup(d->port);
+ /* fall through */
+ case 0: /* no device */
+ break;
+ default:
+ dprint("%s: unknown status %04ux\n", name, s);
+ /* fall through */
+ case 0x100: /* active, no device */
+ if(++d->wait&Mphywait)
+ break;
+reset:
+ if(++d->mode > DMsataii)
+ d->mode = 0;
+ if(d->mode == DMsatai){ /* we tried everything */
+ d->state = Dportreset;
+ goto portreset;
+ }
+ dprint("%s: reset; new mode %s\n", name,
+ modename[d->mode]);
+ iunlock(d);
+ resetdisk(d);
+ ilock(d);
+ break;
+ case 0x103: /* active, device, phy. comm. */
+ if((++d->wait&Midwait) == 0){
+ dprint("%s: slow reset %04ux task=%lux; %d\n",
+ name, s, d->port->task, d->wait);
+ goto reset;
+ }
+ s = (uchar)d->port->task;
+ if(s == 0x7f || ((d->port->sig >> 16) != 0xeb14 &&
+ (s & ~0x17) != (1<<6)))
+ break;
+ iunlock(d);
+ newdrive(d);
+ ilock(d);
+ break;
+ }
+ break;
+ case Doffline:
+ if(d->wait++ & Mcomrwait)
+ break;
+ /* fallthrough */
+ case Derror:
+ case Dreset:
+ dprint("%s: reset [%s]: mode %d; status %04ux\n",
+ name, diskstates[d->state], d->mode, s);
+ iunlock(d);
+ resetdisk(d);
+ ilock(d);
+ break;
+ case Dportreset:
+portreset:
+ if(d->wait++ & 0xff && (s & 0x100) == 0)
+ break;
+ /* device is active */
+ dprint("%s: portreset [%s]: mode %d; status %04ux\n",
+ name, diskstates[d->state], d->mode, s);
+ d->portm.flag |= Ferror;
+ clearci(d->port);
+ wakeup(&d->portm);
+ if((s & 7) == 0){ /* no device */
+ d->state = Dmissing;
+ break;
+ }
+ iunlock(d);
+ doportreset(d);
+ ilock(d);
+ break;
+ }
+ statechange(d);
+ iunlock(d);
+}
+
+static void
+satakproc(void*)
+{
+ int i;
+
+ for(;;){
+ tsleep(&up->sleep, return0, 0, Nms);
+ for(i = 0; i < niadrive; i++)
+ checkdrive(iadrive[i], i);
+ }
+}
+
+static void
+iainterrupt(Ureg*, void *a)
+{
+ int i;
+ ulong cause, m;
+ Ctlr *c;
+ Drive *d;
+
+ c = a;
+ ilock(c);
+ cause = c->hba->isr;
+ for(i = 0; i < c->mport; i++){
+ m = 1 << i;
+ if((cause & m) == 0)
+ continue;
+ d = c->rawdrive + i;
+ ilock(d);
+ if(d->port->isr && c->hba->pi & m)
+ updatedrive(d);
+ c->hba->isr = m;
+ iunlock(d);
+ }
+ iunlock(c);
+}
+
+static int
+iaverify(SDunit *u)
+{
+ Ctlr *c;
+ Drive *d;
+
+ c = u->dev->ctlr;
+ d = c->drive[u->subno];
+ ilock(c);
+ ilock(d);
+ d->unit = u;
+ iunlock(d);
+ iunlock(c);
+ checkdrive(d, d->driveno); /* c->d0 + d->driveno */
+ return 1;
+}
+
+static int
+iaenable(SDev *s)
+{
+ char name[32];
+ Ctlr *c;
+ static int once;
+
+ c = s->ctlr;
+ ilock(c);
+ if(!c->enabled) {
+ if(once == 0) {
+ once = 1;
+ kproc("iasata", satakproc, 0);
+ }
+ if(c->ndrive == 0)
+ panic("iaenable: zero s->ctlr->ndrive");
+ pcisetbme(c->pci);
+ snprint(name, sizeof name, "%s (%s)", s->name, s->ifc->name);
+ intrenable(c->pci->intl, iainterrupt, c, c->pci->tbdf, name);
+ /* supposed to squelch leftover interrupts here. */
+ ahcienable(c->hba);
+ c->enabled = 1;
+ }
+ iunlock(c);
+ return 1;
+}
+
+static int
+iadisable(SDev *s)
+{
+ char name[32];
+ Ctlr *c;
+
+ c = s->ctlr;
+ ilock(c);
+ ahcidisable(c->hba);
+ snprint(name, sizeof name, "%s (%s)", s->name, s->ifc->name);
+ intrdisable(c->pci->intl, iainterrupt, c, c->pci->tbdf, name);
+ c->enabled = 0;
+ iunlock(c);
+ return 1;
+}
+
+static int
+iaonline(SDunit *unit)
+{
+ int r;
+ Ctlr *c;
+ Drive *d;
+
+ c = unit->dev->ctlr;
+ d = c->drive[unit->subno];
+ r = 0;
+
+ if(d->portm.feat & Datapi && d->mediachange){
+ r = scsionline(unit);
+ if(r > 0)
+ d->mediachange = 0;
+ return r;
+ }
+
+ ilock(d);
+ if(d->mediachange){
+ r = 2;
+ d->mediachange = 0;
+ /* devsd resets this after online is called; why? */
+ unit->sectors = d->sectors;
+ unit->secsize = 512; /* default size */
+ } else if(d->state == Dready)
+ r = 1;
+ iunlock(d);
+ return r;
+}
+
+/* returns locked list! */
+static Alist*
+ahcibuild(Drive *d, uchar *cmd, void *data, int n, vlong lba)
+{
+ uchar *c, acmd, dir, llba;
+ Alist *l;
+ Actab *t;
+ Aportm *m;
+ Aprdt *p;
+ static uchar tab[2][2] = { 0xc8, 0x25, 0xca, 0x35, };
+
+ m = &d->portm;
+ dir = *cmd != 0x28;
+ llba = m->feat&Dllba? 1: 0;
+ acmd = tab[dir][llba];
+ qlock(m);
+ l = m->list;
+ t = m->ctab;
+ c = t->cfis;
+
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = acmd;
+ c[3] = 0;
+
+ c[4] = lba; /* sector lba low 7:0 */
+ c[5] = lba >> 8; /* cylinder low lba mid 15:8 */
+ c[6] = lba >> 16; /* cylinder hi lba hi 23:16 */
+ c[7] = 0xa0 | 0x40; /* obsolete device bits + lba */
+ if(llba == 0)
+ c[7] |= (lba>>24) & 7;
+
+ c[8] = lba >> 24; /* sector (exp) lba 31:24 */
+ c[9] = lba >> 32; /* cylinder low (exp) lba 39:32 */
+ c[10] = lba >> 48; /* cylinder hi (exp) lba 48:40 */
+ c[11] = 0; /* features (exp); */
+
+ c[12] = n; /* sector count */
+ c[13] = n >> 8; /* sector count (exp) */
+ c[14] = 0; /* r */
+ c[15] = 0; /* control */
+
+ *(ulong*)(c + 16) = 0;
+
+ l->flags = 1<<16 | Lpref | 0x5; /* Lpref ?? */
+ if(dir == Write)
+ l->flags |= Lwrite;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ p = &t->prdt;
+ p->dba = PCIWADDR(data);
+ p->dbahi = 0;
+ if(d->unit == nil)
+ panic("ahcibuild: nil d->unit");
+ p->count = 1<<31 | (d->unit->secsize*n - 2) | 1;
+
+ return l;
+}
+
+static Alist*
+ahcibuildpkt(Aportm *m, SDreq *r, void *data, int n)
+{
+ int fill, len;
+ uchar *c;
+ Alist *l;
+ Actab *t;
+ Aprdt *p;
+
+ qlock(m);
+ l = m->list;
+ t = m->ctab;
+ c = t->cfis;
+
+ fill = m->feat&Datapi16? 16: 12;
+ if((len = r->clen) > fill)
+ len = fill;
+ memmove(t->atapi, r->cmd, len);
+ memset(t->atapi+len, 0, fill-len);
+
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = 0xa0;
+ if(n != 0)
+ c[3] = 1; /* dma */
+ else
+ c[3] = 0; /* features (exp); */
+
+ c[4] = 0; /* sector lba low 7:0 */
+ c[5] = n; /* cylinder low lba mid 15:8 */
+ c[6] = n >> 8; /* cylinder hi lba hi 23:16 */
+ c[7] = 0xa0; /* obsolete device bits */
+
+ *(ulong*)(c + 8) = 0;
+ *(ulong*)(c + 12) = 0;
+ *(ulong*)(c + 16) = 0;
+
+ l->flags = 1<<16 | Lpref | Latapi | 0x5;
+ if(r->write != 0 && data)
+ l->flags |= Lwrite;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ if(data == 0)
+ return l;
+
+ p = &t->prdt;
+ p->dba = PCIWADDR(data);
+ p->dbahi = 0;
+ p->count = 1<<31 | (n - 2) | 1;
+
+ return l;
+}
+
+static int
+waitready(Drive *d)
+{
+ ulong s, i, δ;
+
+ for(i = 0; i < 15000; i += 250){
+ if(d->state == Dreset || d->state == Dportreset ||
+ d->state == Dnew)
+ return 1;
+ δ = MACHP(0)->ticks - d->lastseen;
+ if(d->state == Dnull || δ > 10*1000)
+ return -1;
+ ilock(d);
+ s = d->port->sstatus;
+ iunlock(d);
+ if((s & 0x700) == 0 && δ > 1500)
+ return -1; /* no detect */
+ if(d->state == Dready && (s & 7) == 3)
+ return 0; /* ready, present & phy. comm. */
+ esleep(250);
+ }
+ print("%s: not responding; offline\n", d->unit->name);
+ ilock(d);
+ d->state = Doffline;
+ iunlock(d);
+ return -1;
+}
+
+static int
+lockready(Drive *d)
+{
+ int i;
+
+ qlock(&d->portm);
+ while ((i = waitready(d)) == 1) {
+ qunlock(&d->portm);
+ esleep(1);
+ qlock(&d->portm);
+ }
+ return i;
+}
+
+static int
+flushcache(Drive *d)
+{
+ int i;
+
+ i = -1;
+ if(lockready(d) == 0)
+ i = ahciflushcache(&d->portc);
+ qunlock(&d->portm);
+ return i;
+}
+
+static int
+iariopkt(SDreq *r, Drive *d)
+{
+ int n, count, try, max, flag, task;
+ char *name;
+ uchar *cmd, *data;
+ Aport *p;
+ Asleep as;
+
+ cmd = r->cmd;
+ name = d->unit->name;
+ p = d->port;
+
+ aprint("ahci: iariopkt: %02ux %02ux %c %d %p\n",
+ cmd[0], cmd[2], "rw"[r->write], r->dlen, r->data);
+ if(cmd[0] == 0x5a && (cmd[2] & 0x3f) == 0x3f)
+ return sdmodesense(r, cmd, d->info, sizeof d->info);
+ r->rlen = 0;
+ count = r->dlen;
+ max = 65536;
+
+ try = 0;
+retry:
+ data = r->data;
+ n = count;
+ if(n > max)
+ n = max;
+ ahcibuildpkt(&d->portm, r, data, n);
+ switch(waitready(d)){
+ case -1:
+ qunlock(&d->portm);
+ return SDeio;
+ case 1:
+ qunlock(&d->portm);
+ esleep(1);
+ goto retry;
+ }
+
+ ilock(d);
+ d->portm.flag = 0;
+ iunlock(d);
+ p->ci = 1;
+
+ as.p = p;
+ as.i = 1;
+ d->intick = MACHP(0)->ticks;
+ d->active++;
+
+ while(waserror())
+ ;
+ sleep(&d->portm, ahciclear, &as);
+ poperror();
+
+ d->active--;
+ ilock(d);
+ flag = d->portm.flag;
+ task = d->port->task;
+ iunlock(d);
+
+ if(task & (Efatal<<8) || task & (ASbsy|ASdrq) && d->state == Dready){
+ d->port->ci = 0;
+ ahcirecover(&d->portc);
+ task = d->port->task;
+ flag &= ~Fdone; /* either an error or do-over */
+ }
+ qunlock(&d->portm);
+ if(flag == 0){
+ if(++try == 10){
+ print("%s: bad disk\n", name);
+ r->status = SDcheck;
+ return SDcheck;
+ }
+ print("%s: retry\n", name);
+ goto retry;
+ }
+ if(flag & Ferror){
+ if((task&Eidnf) == 0)
+ print("%s: i/o error %ux\n", name, task);
+ r->status = SDcheck;
+ return SDcheck;
+ }
+
+ data += n;
+
+ r->rlen = data - (uchar*)r->data;
+ r->status = SDok;
+ return SDok;
+}
+
+static int
+iario(SDreq *r)
+{
+ int i, n, count, try, max, flag, task;
+ vlong lba;
+ char *name;
+ uchar *cmd, *data;
+ Aport *p;
+ Asleep as;
+ Ctlr *c;
+ Drive *d;
+ SDunit *unit;
+
+ unit = r->unit;
+ c = unit->dev->ctlr;
+ d = c->drive[unit->subno];
+ if(d->portm.feat & Datapi)
+ return iariopkt(r, d);
+ cmd = r->cmd;
+ name = d->unit->name;
+ p = d->port;
+
+ if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91){
+ if(flushcache(d) == 0)
+ return sdsetsense(r, SDok, 0, 0, 0);
+ return sdsetsense(r, SDcheck, 3, 0xc, 2);
+ }
+
+ if((i = sdfakescsi(r, d->info, sizeof d->info)) != SDnostatus){
+ r->status = i;
+ return i;
+ }
+
+ if(*cmd != 0x28 && *cmd != 0x2a){
+ print("%s: bad cmd 0x%.2ux\n", name, 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;
+ max = 128;
+
+ try = 0;
+retry:
+ data = r->data;
+ while(count > 0){
+ n = count;
+ if(n > max)
+ n = max;
+ ahcibuild(d, cmd, data, n, lba);
+ switch(waitready(d)){
+ case -1:
+ qunlock(&d->portm);
+ return SDeio;
+ case 1:
+ qunlock(&d->portm);
+ esleep(1);
+ goto retry;
+ }
+ ilock(d);
+ d->portm.flag = 0;
+ iunlock(d);
+ p->ci = 1;
+
+ as.p = p;
+ as.i = 1;
+ d->intick = MACHP(0)->ticks;
+ d->active++;
+
+ while(waserror())
+ ;
+ sleep(&d->portm, ahciclear, &as);
+ poperror();
+
+ d->active--;
+ ilock(d);
+ flag = d->portm.flag;
+ task = d->port->task;
+ iunlock(d);
+
+ if(task & (Efatal<<8) ||
+ task & (ASbsy|ASdrq) && d->state == Dready){
+ d->port->ci = 0;
+ ahcirecover(&d->portc);
+ task = d->port->task;
+ }
+ qunlock(&d->portm);
+ if(flag == 0){
+ if(++try == 10){
+ print("%s: bad disk\n", name);
+ r->status = SDeio;
+ return SDeio;
+ }
+ iprint("%s: retry %lld\n", name, lba);
+ goto retry;
+ }
+ if(flag & Ferror){
+ iprint("%s: i/o error %ux @%,lld\n", name, task, lba);
+ r->status = SDeio;
+ return SDeio;
+ }
+
+ count -= n;
+ lba += n;
+ data += n * unit->secsize;
+ }
+ r->rlen = data - (uchar*)r->data;
+ r->status = SDok;
+ return SDok;
+}
+
+/*
+ * configure drives 0-5 as ahci sata (c.f. errata)
+ */
+static int
+iaahcimode(Pcidev *p)
+{
+ dprint("iaahcimode: %ux %ux %ux\n", pcicfgr8(p, 0x91), pcicfgr8(p, 92),
+ pcicfgr8(p, 93));
+ pcicfgw16(p, 0x92, pcicfgr32(p, 0x92) | 0xf); /* ports 0-3 */
+// pcicfgw8(p, 0x93, pcicfgr32(p, 9x93) | 3); /* ports 4-5 */
+ return 0;
+}
+
+static void
+iasetupahci(Ctlr *c)
+{
+ /* disable cmd block decoding. */
+ pcicfgw16(c->pci, 0x40, pcicfgr16(c->pci, 0x40) & ~(1<<15));
+ pcicfgw16(c->pci, 0x42, pcicfgr16(c->pci, 0x42) & ~(1<<15));
+
+ c->lmmio[0x4/4] |= 1 << 31; /* enable ahci mode (ghc register) */
+ c->lmmio[0xc/4] = (1 << 6) - 1; /* 5 ports. (supposedly ro pi reg.) */
+
+ /* enable ahci mode; from ich9 datasheet */
+ pcicfgw16(c->pci, 0x90, 1<<6 | 1<<5);
+}
+
+static int
+didtype(Pcidev *p)
+{
+ switch(p->vid){
+ case 0x8086:
+ if((p->did & 0xfffc) == 0x2680)
+ return Tesb;
+ /*
+ * 0x27c4 is the intel 82801 in compatibility (not sata) mode.
+ */
+ if ((p->did & 0xfffb) == 0x27c1 || /* 82801g[bh]m ich7 */
+ p->did == 0x2821 || /* 82801h[roh] */
+ (p->did & 0xfffe) == 0x2824 || /* 82801h[b] */
+ (p->did & 0xfeff) == 0x2829 || /* ich8/9m */
+ (p->did & 0xfffe) == 0x2922 || /* ich9 */
+ p->did == 0x3a02 || /* 82801jd/do */
+ (p->did & 0xfefe) == 0x3a22 || /* ich10, pch */
+ (p->did & 0xfff7) == 0x3b28) /* pchm */
+ return Tich;
+ break;
+ case 0x1002:
+ if(p->did == 0x4380)
+ return Tsb600;
+ break;
+ }
+ if(p->ccrb == Pcibcstore && p->ccru == 6 && p->ccrp == 1)
+ return Tunk;
+ return -1;
+}
+
+static SDev*
+iapnp(void)
+{
+ int i, n, nunit, type;
+ ulong io;
+ Ctlr *c;
+ Drive *d;
+ Pcidev *p;
+ SDev *head, *tail, *s;
+ static int done;
+
+ if(done++)
+ return nil;
+
+ memset(olds, 0xff, sizeof olds);
+ p = nil;
+ head = tail = nil;
+loop:
+ while((p = pcimatch(p, 0, 0)) != nil){
+ type = didtype(p);
+ if (type == -1 || p->mem[Abar].bar == 0)
+ continue;
+ if(niactlr == NCtlr){
+ print("ahci: iapnp: %s: too many controllers\n",
+ tname[type]);
+ break;
+ }
+ c = iactlr + niactlr;
+ s = sdevs + niactlr;
+ memset(c, 0, sizeof *c);
+ memset(s, 0, sizeof *s);
+ io = p->mem[Abar].bar & ~0xf;
+ c->mmio = vmap(io, p->mem[Abar].size);
+ if(c->mmio == 0){
+ print("ahci: %s: address 0x%luX in use did=%x\n",
+ Tname(c), io, p->did);
+ continue;
+ }
+ c->lmmio = (ulong*)c->mmio;
+ c->pci = p;
+ c->type = type;
+
+ s->ifc = &sdiahciifc;
+ s->idno = 'E' + niactlr;
+ s->ctlr = c;
+ c->sdev = s;
+
+ if(Intel(c) && p->did != 0x2681)
+ iasetupahci(c);
+ nunit = ahciconf(c);
+// ahcihbareset((Ahba*)c->mmio);
+ if(Intel(c) && iaahcimode(p) == -1)
+ break;
+ if(nunit < 1){
+ vunmap(c->mmio, p->mem[Abar].size);
+ continue;
+ }
+ c->ndrive = s->nunit = nunit;
+ c->mport = c->hba->cap & ((1<<5)-1);
+
+ i = (c->hba->cap >> 21) & 1;
+ print("#S/sd%c: %s: sata-%s with %d ports\n", s->idno,
+ Tname(c), "I\0II" + i*2, nunit);
+
+ /* map the drives -- they don't all need to be enabled. */
+ memset(c->rawdrive, 0, sizeof c->rawdrive);
+ n = 0;
+ for(i = 0; i < NCtlrdrv; i++) {
+ d = c->rawdrive + i;
+ d->portno = i;
+ d->driveno = -1;
+ d->sectors = 0;
+ d->serial[0] = ' ';
+ d->ctlr = c;
+ if((c->hba->pi & (1<<i)) == 0)
+ continue;
+ d->port = (Aport*)(c->mmio + 0x80*i + 0x100);
+ d->portc.p = d->port;
+ d->portc.m = &d->portm;
+ d->driveno = n++;
+ c->drive[d->driveno] = d;
+ iadrive[niadrive + d->driveno] = d;
+ }
+ for(i = 0; i < n; i++)
+ if(ahciidle(c->drive[i]->port) == -1){
+ dprint("ahci: %s: port %d wedged; abort\n",
+ Tname(c), i);
+ goto loop;
+ }
+ for(i = 0; i < n; i++){
+ c->drive[i]->mode = DMsatai;
+ configdrive(c->drive[i]);
+ }
+
+ niadrive += n;
+ niactlr++;
+ if(head)
+ tail->next = s;
+ else
+ head = s;
+ tail = s;
+ }
+ return head;
+}
+
+static char* smarttab[] = {
+ "unset",
+ "error",
+ "threshold exceeded",
+ "normal"
+};
+
+static char *
+pflag(char *s, char *e, uchar f)
+{
+ uchar i;
+
+ for(i = 0; i < 8; i++)
+ if(f & (1 << i))
+ s = seprint(s, e, "%s ", flagname[i]);
+ return seprint(s, e, "\n");
+}
+
+static int
+iarctl(SDunit *u, char *p, int l)
+{
+ char buf[32];
+ char *e, *op;
+ Aport *o;
+ Ctlr *c;
+ Drive *d;
+
+ c = u->dev->ctlr;
+ if(c == nil) {
+print("iarctl: nil u->dev->ctlr\n");
+ return 0;
+ }
+ d = c->drive[u->subno];
+ o = d->port;
+
+ e = p+l;
+ op = p;
+ if(d->state == Dready){
+ p = seprint(p, e, "model\t%s\n", d->model);
+ p = seprint(p, e, "serial\t%s\n", d->serial);
+ p = seprint(p, e, "firm\t%s\n", d->firmware);
+ if(d->smartrs == 0xff)
+ p = seprint(p, e, "smart\tenable error\n");
+ else if(d->smartrs == 0)
+ p = seprint(p, e, "smart\tdisabled\n");
+ else
+ p = seprint(p, e, "smart\t%s\n",
+ smarttab[d->portm.smart]);
+ p = seprint(p, e, "flag\t");
+ p = pflag(p, e, d->portm.feat);
+ }else
+ p = seprint(p, e, "no disk present [%s]\n", diskstates[d->state]);
+ serrstr(o->serror, buf, buf + sizeof buf - 1);
+ p = seprint(p, e, "reg\ttask %lux cmd %lux serr %lux %s ci %lux is %lux; "
+ "sig %lux sstatus %04lux\n", o->task, o->cmd, o->serror, buf,
+ o->ci, o->isr, o->sig, o->sstatus);
+ if(d->unit == nil)
+ panic("iarctl: nil d->unit");
+ p = seprint(p, e, "geometry %llud %lud\n", d->sectors, d->unit->secsize);
+ return p - op;
+}
+
+static void
+runflushcache(Drive *d)
+{
+ long t0;
+
+ t0 = MACHP(0)->ticks;
+ if(flushcache(d) != 0)
+ error(Eio);
+ dprint("ahci: flush in %ld ms\n", MACHP(0)->ticks - t0);
+}
+
+static void
+forcemode(Drive *d, char *mode)
+{
+ int i;
+
+ for(i = 0; i < nelem(modename); i++)
+ if(strcmp(mode, modename[i]) == 0)
+ break;
+ if(i == nelem(modename))
+ i = 0;
+ ilock(d);
+ d->mode = i;
+ iunlock(d);
+}
+
+static void
+runsmartable(Drive *d, int i)
+{
+ if(waserror()){
+ qunlock(&d->portm);
+ d->smartrs = 0;
+ nexterror();
+ }
+ if(lockready(d) == -1)
+ error(Eio);
+ d->smartrs = smart(&d->portc, i);
+ d->portm.smart = 0;
+ qunlock(&d->portm);
+ poperror();
+}
+
+static void
+forcestate(Drive *d, char *state)
+{
+ int i;
+
+ for(i = 0; i < nelem(diskstates); i++)
+ if(strcmp(state, diskstates[i]) == 0)
+ break;
+ if(i == nelem(diskstates))
+ error(Ebadctl);
+ ilock(d);
+ d->state = i;
+ iunlock(d);
+}
+
+
+static int
+iawctl(SDunit *u, Cmdbuf *cmd)
+{
+ char **f;
+ Ctlr *c;
+ Drive *d;
+ uint i;
+
+ c = u->dev->ctlr;
+ d = c->drive[u->subno];
+ f = cmd->f;
+
+ if(strcmp(f[0], "flushcache") == 0)
+ runflushcache(d);
+ else if(strcmp(f[0], "identify") == 0){
+ i = strtoul(f[1]? f[1]: "0", 0, 0);
+ if(i > 0xff)
+ i = 0;
+ dprint("ahci: %04d %ux\n", i, d->info[i]);
+ }else if(strcmp(f[0], "mode") == 0)
+ forcemode(d, f[1]? f[1]: "satai");
+ else if(strcmp(f[0], "nop") == 0){
+ if((d->portm.feat & Dnop) == 0){
+ cmderror(cmd, "no drive support");
+ return -1;
+ }
+ if(waserror()){
+ qunlock(&d->portm);
+ nexterror();
+ }
+ if(lockready(d) == -1)
+ error(Eio);
+ nop(&d->portc);
+ qunlock(&d->portm);
+ poperror();
+ }else if(strcmp(f[0], "reset") == 0)
+ forcestate(d, "reset");
+ else if(strcmp(f[0], "smart") == 0){
+ if(d->smartrs == 0){
+ cmderror(cmd, "smart not enabled");
+ return -1;
+ }
+ if(waserror()){
+ qunlock(&d->portm);
+ d->smartrs = 0;
+ nexterror();
+ }
+ if(lockready(d) == -1)
+ error(Eio);
+ d->portm.smart = 2 + smartrs(&d->portc);
+ qunlock(&d->portm);
+ poperror();
+ }else if(strcmp(f[0], "smartdisable") == 0)
+ runsmartable(d, 1);
+ else if(strcmp(f[0], "smartenable") == 0)
+ runsmartable(d, 0);
+ else if(strcmp(f[0], "state") == 0)
+ forcestate(d, f[1]? f[1]: "null");
+ else{
+ cmderror(cmd, Ebadctl);
+ return -1;
+ }
+ return 0;
+}
+
+static char *
+portr(char *p, char *e, uint x)
+{
+ int i, a;
+
+ p[0] = 0;
+ a = -1;
+ for(i = 0; i < 32; i++){
+ if((x & (1<<i)) == 0){
+ if(a != -1 && i - 1 != a)
+ p = seprint(p, e, "-%d", i - 1);
+ a = -1;
+ continue;
+ }
+ if(a == -1){
+ if(i > 0)
+ p = seprint(p, e, ", ");
+ p = seprint(p, e, "%d", a = i);
+ }
+ }
+ if(a != -1 && i - 1 != a)
+ p = seprint(p, e, "-%d", i - 1);
+ return p;
+}
+
+/* must emit exactly one line per controller (sd(3)) */
+static char*
+iartopctl(SDev *sdev, char *p, char *e)
+{
+ ulong cap;
+ char pr[25];
+ Ahba *hba;
+ Ctlr *ctlr;
+
+#define has(x, str) if(cap & (x)) p = seprint(p, e, "%s ", (str))
+
+ ctlr = sdev->ctlr;
+ hba = ctlr->hba;
+ p = seprint(p, e, "sd%c ahci port %#p: ", sdev->idno, hba);
+ cap = hba->cap;
+ has(Hs64a, "64a");
+ has(Hsalp, "alp");
+ has(Hsam, "am");
+ has(Hsclo, "clo");
+ has(Hcccs, "coal");
+ has(Hems, "ems");
+ has(Hsal, "led");
+ has(Hsmps, "mps");
+ has(Hsncq, "ncq");
+ has(Hssntf, "ntf");
+ has(Hspm, "pm");
+ has(Hpsc, "pslum");
+ has(Hssc, "slum");
+ has(Hsss, "ss");
+ has(Hsxs, "sxs");
+ portr(pr, pr + sizeof pr, hba->pi);
+ return seprint(p, e,
+ "iss %ld ncs %ld np %ld; ghc %lux isr %lux pi %lux %s ver %lux\n",
+ (cap>>20) & 0xf, (cap>>8) & 0x1f, 1 + (cap & 0x1f),
+ hba->ghc, hba->isr, hba->pi, pr, hba->ver);
+#undef has
+}
+
+static int
+iawtopctl(SDev *, Cmdbuf *cmd)
+{
+ int *v;
+ char **f;
+
+ f = cmd->f;
+ v = 0;
+
+ if (f[0] == nil)
+ return 0;
+ if(strcmp(f[0], "debug") == 0)
+ v = &debug;
+ else if(strcmp(f[0], "idprint") == 0)
+ v = &prid;
+ else if(strcmp(f[0], "aprint") == 0)
+ v = &datapi;
+ else
+ cmderror(cmd, Ebadctl);
+
+ switch(cmd->nf){
+ default:
+ cmderror(cmd, Ebadarg);
+ case 1:
+ *v ^= 1;
+ break;
+ case 2:
+ if(f[1])
+ *v = strcmp(f[1], "on") == 0;
+ else
+ *v ^= 1;
+ break;
+ }
+ return 0;
+}
+
+SDifc sdiahciifc = {
+ "iahci",
+
+ iapnp,
+ nil, /* legacy */
+ iaenable,
+ iadisable,
+
+ iaverify,
+ iaonline,
+ iario,
+ iarctl,
+ iawctl,
+
+ scsibio,
+ nil, /* probe */
+ nil, /* clear */
+ iartopctl,
+ iawtopctl,
+};
diff --git a/sys/src/9/pc/sdmv50xx.c b/sys/src/9/pc/sdmv50xx.c
new file mode 100755
index 000000000..e9ba87c47
--- /dev/null
+++ b/sys/src/9/pc/sdmv50xx.c
@@ -0,0 +1,1762 @@
+/*
+ * Marvell 88SX[56]0[48][01] fileserver Serial ATA (SATA) driver
+ *
+ * See MV-S101357-00 Rev B Marvell PCI/PCI-X to 8-Port/4-Port
+ * SATA Host Controller, ATA-5 ANSI NCITS 340-2000.
+ *
+ * This is a heavily-modified version (by Coraid) of a heavily-modified
+ * version (from The Labs) 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){}else iprint
+#define idprint if(!0){}else iprint
+#define ioprint if(!0){}else iprint
+
+enum {
+ NCtlr = 4,
+ NCtlrdrv = 8,
+ NDrive = NCtlr*NCtlrdrv,
+
+ Read = 0,
+ Write,
+
+ Coraiddebug = 0,
+};
+
+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),
+ ATAobs = (1<<1 | 1<<2 | 1<<4),
+ ATAeIEN = (1<<1),
+ ATAsrst = (1<<2),
+ ATAhob = (1<<7),
+ ATAbad = (ATAbusy|ATAdf|ATAdrq|ATAerr),
+
+ 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),
+
+ /* flags for sata 2 version */
+ eSelfDis2 = (1<<7),
+ SerrInt = (1<<5),
+
+ /* EDMA Command Register */
+
+ eEnEDMA = (1<<0),
+ eDsEDMA = (1<<1),
+ eAtaRst = (1<<2),
+
+ /* Interrupt mask for errors we care about */
+ IEM = (eDevDis | eDevCon | eSelfDis),
+ IEM2 = (eDevDis | eDevCon | eSelfDis2),
+
+ /* drive states */
+ Dnull = 0,
+ Dnew,
+ Dready,
+ Derror,
+ Dmissing,
+ Dreset,
+ Dlast,
+
+ /* drive flags */
+ 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 */
+
+ /* phyerrata magic crap */
+ Mpreamp = 0x7e0,
+ Dpreamp = 0x720,
+
+ REV60X1B2 = 0x7,
+ REV60X1C0 = 0x9,
+
+};
+
+static char* diskstates[Dlast] = {
+ "null",
+ "new",
+ "ready",
+ "error",
+ "missing",
+ "reset",
+};
+
+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;
+
+/*
+ * there are 4 drives per chip. thus an 8-port
+ * card has two chips.
+ */
+struct Chip
+{
+ Arb *arb;
+ Edma *edma;
+};
+
+enum {
+ DMautoneg,
+ DMsatai,
+ DMsataii,
+};
+
+struct Drive
+{
+ Lock;
+
+ Ctlr *ctlr;
+ SDunit *unit;
+ char name[10];
+ ulong magic;
+
+ Bridge *bridge;
+ Edma *edma;
+ Chip *chip;
+ int chipx;
+
+ int mediachange;
+ int state;
+ int flag;
+ uvlong sectors;
+ ulong pm2; /* phymode 2 init state */
+ ulong intick; /* check for hung western digital drives. */
+ int wait;
+ int mode; /* DMautoneg, satai or sataii. */
+
+ 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;
+ int driveno; /* ctlr*NCtlrdrv + unit */
+};
+
+struct Ctlr
+{
+ Lock;
+
+ int irq;
+ int tbdf;
+ int rid;
+ ulong magic;
+ int enabled;
+ int type;
+ SDev *sdev;
+ Pcidev *pcidev;
+
+ uchar *mmio;
+ ulong *lmmio;
+ Chip chip[2];
+ int nchip;
+ Drive drive[NCtlrdrv];
+ 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;
+ ulong phymode3;
+ ulong phymode4;
+ uchar fill0[0x14];
+ ulong phymode1;
+ ulong phymode2;
+ char fill1[8];
+ ulong ctrl;
+ char fill2[0x34];
+ ulong phymode;
+ char fill3[0x88];
+}; /* length must be 0x100 */
+
+struct Arb /* memory-mapped per-Chip registers */
+{
+ ulong config; /* satahc configuration register (sata2 only) */
+ 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[0x18];
+ ulong sataconfig; /* sata 2 */
+ char fill[0xac];
+ 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 */
+ uchar fill2[0x1df];
+ Bridge port;
+ char fill3[0x1c00]; /* 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 */
+};
+
+static Drive *mvsatadrive[NDrive];
+static int nmvsatadrive;
+
+/*
+ * 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;
+
+ for(i=0; i<ms && (*p & mask) != v; i++)
+ microdelay(1000);
+ return (*p & mask) == v;
+}
+
+/*
+ * Drive initialization
+ */
+/* unmask in the pci registers err done */
+static void
+unmask(ulong *mmio, int port, int coal)
+{
+ port &= 7;
+ if(coal)
+ coal = 1;
+ if (port < 4)
+ mmio[0x1d64/4] |= (3 << (((port&3)*2)) | (coal<<8));
+ else
+ mmio[0x1d64/4] |= (3 << (((port&3)*2+9)) | (coal<<17));
+}
+
+static void
+mask(ulong *mmio, int port, int coal)
+{
+ port &= 7;
+ if(coal)
+ coal = 1;
+ if (port < 4)
+ mmio[0x1d64/4] &= ~(3 << (((port&3)*2)) | (coal<<8));
+ else
+ mmio[0x1d64/4] &= ~(3 << (((port&3)*2+9)) | (coal<<17));
+}
+
+/* I give up, marvell. You win. */
+static void
+phyerrata(Drive *d)
+{
+ ulong n, m;
+ enum { BadAutoCal = 0xf << 26, };
+
+ if (d->ctlr->type == 1)
+ return;
+ microdelay(200);
+ n = d->bridge->phymode2;
+ while ((n & BadAutoCal) == BadAutoCal) {
+ dprint("%s: badautocal\n", d->unit->name);
+ n &= ~(1<<16);
+ n |= (1<<31);
+ d->bridge->phymode2 = n;
+ microdelay(200);
+ d->bridge->phymode2 &= ~((1<<16) | (1<<31));
+ microdelay(200);
+ n = d->bridge->phymode2;
+ }
+ n &= ~(1<<31);
+ d->bridge->phymode2 = n;
+ microdelay(200);
+
+ /* abra cadabra! (random magic) */
+ m = d->bridge->phymode3;
+ m &= ~0x7f800000;
+ m |= 0x2a800000;
+ d->bridge->phymode3 = m;
+
+ /* fix phy mode 4 */
+ m = d->bridge->phymode3;
+ n = d->bridge->phymode4;
+ n &= ~(1<<1);
+ n |= 1;
+ switch(d->ctlr->rid){
+ case REV60X1B2:
+ default:
+ d->bridge->phymode4 = n;
+ d->bridge->phymode3 = m;
+ break;
+ case REV60X1C0:
+ d->bridge->phymode4 = n;
+ break;
+ }
+
+ /* revert values of pre-emphasis and signal amps to the saved ones */
+ n = d->bridge->phymode2;
+ n &= ~Mpreamp;
+ n |= d->pm2;
+ n &= ~(1<<16);
+ d->bridge->phymode2 = n;
+}
+
+static void
+edmacleanout(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 void
+resetdisk(Drive *d)
+{
+ ulong n;
+
+ d->sectors = 0;
+ d->unit->sectors = 0;
+ if (d->ctlr->type == 2) {
+ /*
+ * without bit 8 we can boot without disks, but
+ * inserted disks will never appear. :-X
+ */
+ n = d->edma->sataconfig;
+ n &= 0xff;
+ n |= 0x9b1100;
+ d->edma->sataconfig = n;
+ n = d->edma->sataconfig; /* flush */
+ USED(n);
+ }
+ d->edma->ctl = eDsEDMA;
+ microdelay(1);
+ d->edma->ctl = eAtaRst;
+ microdelay(25);
+ d->edma->ctl = 0;
+ if (satawait((uchar *)&d->edma->ctl, eEnEDMA, 0, 3*1000) == 0)
+ print("%s: eEnEDMA never cleared on reset\n", d->unit->name);
+ edmacleanout(d);
+ phyerrata(d);
+ d->bridge->sctrl = 0x301 | (d->mode << 4);
+ d->state = Dmissing;
+}
+
+static void
+edmainit(Drive *d)
+{
+ int i;
+
+ if(d->tx != nil)
+ return;
+
+ d->tx = xspanalloc(32*sizeof(Tx), 1024, 0);
+ d->rx = xspanalloc(32*sizeof(Rx), 256, 0);
+ d->prd = xspanalloc(32*sizeof(Prd), 32, 0);
+ for(i = 0; i < 32; i++)
+ d->tx[i].prdpa = PADDR(&d->prd[i]);
+ coherence();
+}
+
+static int
+configdrive(Ctlr *ctlr, Drive *d, SDunit *unit)
+{
+ dprint("%s: configdrive\n", unit->name);
+ if(d->driveno < 0)
+ panic("mv50xx: configdrive: unset driveno\n");
+ d->unit = unit;
+ edmainit(d);
+ d->mode = DMsatai;
+ if(d->ctlr->type == 1){
+ d->edma->iem = IEM;
+ d->bridge = &d->chip->arb->bridge[d->chipx];
+ }else{
+ d->edma->iem = IEM2;
+ d->bridge = &d->chip->edma[d->chipx].port;
+ d->edma->iem = ~(1<<6);
+ d->pm2 = Dpreamp;
+ if(d->ctlr->lmmio[0x180d8/4] & 1)
+ d->pm2 = d->bridge->phymode2 & Mpreamp;
+ }
+ resetdisk(d);
+ unmask(ctlr->lmmio, d->driveno, 0);
+ delay(100);
+ if(d->bridge->status){
+ dprint("%s: configdrive: found drive %lx\n", unit->name, d->bridge->status);
+ return 0;
+ }
+ return -1;
+}
+
+static int
+enabledrive(Drive *d)
+{
+ Edma *edma;
+
+ dprint("%s: enabledrive..", d->unit->name);
+
+ if((d->bridge->status & 0xf) != 3){
+ dprint("%s: not present\n", d->unit->name);
+ d->state = Dmissing;
+ return -1;
+ }
+ edma = d->edma;
+ if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0){
+ dprint("%s: busy timeout\n", d->unit->name);
+ d->state = Dmissing;
+ return -1;
+ }
+ edma->iec = 0;
+ d->chip->arb->ic &= ~(0x101 << d->chipx);
+ edma->config = 0x51f;
+ if (d->ctlr->type == 2)
+ edma->config |= 7<<11;
+ 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 */
+
+ if(d->bridge->status = 0x113){
+ dprint("%s: new\n", d->unit->name);
+ d->state = Dnew;
+ }else
+ print("%s: status not forced (should be okay)\n", d->unit->name);
+ return 0;
+}
+
+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 (edma == nil) {
+ iprint("setudamode(m%d): zero d->edma\m", d->driveno);
+ return 0;
+ }
+ if(satawait(&edma->cmdstat, ~ATAobs, ATAdrdy, 9*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, 5*1000) == 0){
+ iprint("%s: cmdstat 0x%.2ux busy timeout\n", d->unit->name, edma->cmdstat);
+ return 0;
+ }
+ return 1;
+}
+
+static int
+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, ~ATAobs, ATAdrdy, 5*1000) == 0)
+ goto Error;
+
+ edma->altstat = ATAeIEN; /* no interrupts */
+ edma->cmdstat = 0xec;
+ microdelay(1);
+ if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0)
+ goto Error;
+ for(i = 0; i < 256; i++)
+ id[i] = edma->pio;
+ if(edma->cmdstat & ATAbad)
+ 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) == 0) {
+ d->state = Dready;
+ d->mediachange = 1;
+ idprint("%s: LLBA %lld sectors\n", d->unit->name, d->sectors);
+ } else
+ d->state = Derror;
+ if(d->state == Dready)
+ return 0;
+ return -1;
+Error:
+ dprint("error...");
+ d->state = Derror;
+ return -1;
+}
+
+/* p. 163:
+ M recovered error
+ P protocol error
+ N PhyRdy change
+ W CommWake
+ B 8-to-10 encoding error
+ D disparity error
+ C crc error
+ H handshake error
+ S link sequence error
+ T transport state transition error
+ F unrecognized fis type
+ X device changed
+*/
+
+static char stab[] = {
+[1] 'M',
+[10] 'P',
+[16] 'N',
+[18] 'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X'
+};
+static ulong sbad = (7<<20)|(3<<23);
+
+static void
+serrdecode(ulong r, char *s, char *e)
+{
+ int i;
+
+ e -= 3;
+ for(i = 0; i < nelem(stab) && s < e; i++){
+ if((r&(1<<i)) && stab[i]){
+ *s++ = stab[i];
+ if(sbad&(1<<i))
+ *s++ = '*';
+ }
+ }
+ *s = 0;
+}
+
+char *iectab[] = {
+ "ePrtDataErr",
+ "ePrtPRDErr",
+ "eDevErr",
+ "eDevDis",
+ "eDevCon",
+ "SerrInt",
+ "eUnderrun",
+ "eSelfDis2",
+ "eSelfDis",
+ "ePrtCRQBErr",
+ "ePrtCRPBErr",
+ "ePrtIntErr",
+ "eIORdyErr",
+};
+
+static char*
+iecdecode(ulong cause)
+{
+ int i;
+
+ for(i = 0; i < nelem(iectab); i++)
+ if(cause&(1<<i))
+ return iectab[i];
+ return "";
+}
+
+enum{
+ Cerror = ePrtDataErr|ePrtPRDErr|eDevErr|eSelfDis2|ePrtCRPBErr|ePrtIntErr,
+};
+
+static void
+updatedrive(Drive *d)
+{
+ int x;
+ ulong cause;
+ Edma *edma;
+ char buf[32+4+1];
+
+ edma = d->edma;
+ if((edma->ctl&eEnEDMA) == 0){
+ /* FEr SATA#4 40xx */
+ x = d->edma->cmdstat;
+ USED(x);
+ }
+ cause = edma->iec;
+ if(cause == 0)
+ return;
+ dprint("%s: cause %08ulx [%s]\n", d->unit->name, cause, iecdecode(cause));
+ if(cause & eDevCon)
+ d->state = Dnew;
+ if(cause&eDevDis && d->state == Dready)
+ iprint("%s: pulled: st=%08ulx\n", d->unit->name, cause);
+ switch(d->ctlr->type){
+ case 1:
+ if(cause&eSelfDis)
+ d->state = Derror;
+ break;
+ case 2:
+ if(cause&Cerror)
+ d->state = Derror;
+ if(cause&SerrInt){
+ serrdecode(d->bridge->serror, buf, buf+sizeof buf);
+ dprint("%s: serror %08ulx [%s]\n", d->unit->name, (ulong)d->bridge->serror, buf);
+ d->bridge->serror = d->bridge->serror;
+ }
+ }
+ edma->iec = ~cause;
+}
+
+/*
+ * 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 };
+
+ 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
+mvsatarequest(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);
+}
+
+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->intick = MACHP(0)->ticks;
+ 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;
+ mvsatarequest(tx->regs, srb, d->flag&Dext);
+ coherence();
+ edma->txi = advance(edma->txi, 5);
+ d->intick = MACHP(0)->ticks;
+}
+
+enum{
+ Rpidx = 0x1f<<3,
+};
+
+static void
+completesrb(Drive *d)
+{
+ Edma *edma;
+ Rx *rx;
+ Srb *srb;
+
+ edma = d->edma;
+ if((edma->ctl & eEnEDMA) == 0)
+ return;
+
+ while((edma->rxo&Rpidx) != (edma->rxi&Rpidx)){
+ rx = (Rx*)KADDR(edma->rxo);
+ if(srb = d->srb[rx->cid]){
+ d->srb[rx->cid] = nil;
+ d->nsrb--;
+ if(rx->cDevSts & ATAbad)
+ srb->flag |= SFerror;
+ if (rx->cEdmaSts)
+ iprint("cEdmaSts: %02ux\n", rx->cEdmaSts);
+ srb->sta = rx->cDevSts;
+ srb->flag |= SFdone;
+ 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 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 = ctlr->lmmio[0x1d60/4];
+// 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];
+ if(drive->edma == 0)
+ continue; /* not ready yet. */
+ ilock(drive);
+ updatedrive(drive);
+ 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);
+}
+
+enum{
+ Nms = 256,
+ Midwait = 16*1024/Nms-1,
+ Mphywait = 512/Nms-1,
+};
+
+static void
+westerndigitalhung(Drive *d)
+{
+ Edma *e;
+
+ e = d->edma;
+ if(d->srb
+ && TK2MS(MACHP(0)->ticks-d->intick) > 5*1000
+ && (e->rxo&Rpidx) == (e->rxi&Rpidx)){
+ dprint("westerndigital drive hung; resetting\n");
+ d->state = Dreset;
+ }
+}
+
+static void
+checkdrive(Drive *d, int i)
+{
+ static ulong s, olds[NCtlr*NCtlrdrv];
+ char *name;
+
+ ilock(d);
+ name = d->unit->name;
+ s = d->bridge->status;
+ if(s != olds[i]){
+ dprint("%s: status: %08lx -> %08lx: %s\n", name, olds[i], s, diskstates[d->state]);
+ olds[i] = s;
+ }
+ /* westerndigitalhung(d); */
+ switch(d->state){
+ case Dnew:
+ case Dmissing:
+ switch(s){
+ case 0x000:
+ break;
+ default:
+ dprint("%s: unknown state %8lx\n", name, s);
+ case 0x100:
+ if(++d->wait&Mphywait)
+ break;
+ reset: d->mode ^= 1;
+ dprint("%s: reset; new mode %d\n", name, d->mode);
+ resetdisk(d);
+ break;
+ case 0x123:
+ case 0x113:
+ s = d->edma->cmdstat;
+ if(s == 0x7f || (s&~ATAobs) != ATAdrdy){
+ if((++d->wait&Midwait) == 0)
+ goto reset;
+ }else if(identifydrive(d) == -1)
+ goto reset;
+ }
+ break;
+ case Dready:
+ if(s != 0)
+ break;
+ iprint("%s: pulled: st=%08ulx\n", name, s); /* never happens */
+ case Dreset:
+ case Derror:
+ dprint("%s reset: mode %d\n", name, d->mode);
+ resetdisk(d);
+ break;
+ }
+ iunlock(d);
+}
+
+static void
+satakproc(void*)
+{
+ int i;
+
+ while(waserror())
+ ;
+
+ for(;;){
+ tsleep(&up->sleep, return0, 0, Nms);
+ for(i = 0; i < nmvsatadrive; i++)
+ checkdrive(mvsatadrive[i], i);
+ }
+}
+
+/*
+ * Device discovery
+ */
+static SDev*
+mv50pnp(void)
+{
+ int i, nunit;
+ uchar *base;
+ ulong io, n, *mem;
+ Ctlr *ctlr;
+ Pcidev *p;
+ SDev *head, *tail, *sdev;
+ Drive *d;
+ static int ctlrno, done;
+
+ dprint("mv50pnp\n");
+ if(done++)
+ return nil;
+
+ p = nil;
+ head = nil;
+ tail = nil;
+ while((p = pcimatch(p, 0x11ab, 0)) != nil){
+ switch(p->did){
+ case 0x5040:
+ case 0x5041:
+ case 0x5080:
+ case 0x5081:
+ case 0x6041:
+ case 0x6081:
+ break;
+ default:
+ print("mv50pnp: unknown did %ux ignored\n", (ushort)p->did);
+ continue;
+ }
+ if (ctlrno >= NCtlr) {
+ print("mv50pnp: too many controllers\n");
+ break;
+ }
+ nunit = (p->did&0xf0) >> 4;
+ print("Marvell 88SX%ux: %d SATA-%s ports with%s flash\n",
+ (ushort)p->did, nunit,
+ ((p->did&0xf000)==0x6000? "II": "I"),
+ (p->did&1? "": "out"));
+ if((sdev = malloc(sizeof(SDev))) == nil)
+ continue;
+ if((ctlr = malloc(sizeof(Ctlr))) == nil){
+ free(sdev);
+ continue;
+ }
+ memset(sdev, 0, sizeof *sdev);
+ memset(ctlr, 0, sizeof *ctlr);
+
+ io = p->mem[0].bar & ~0x0F;
+ mem = (ulong*)vmap(io, p->mem[0].size);
+ if(mem == 0){
+ print("sdmv50xx: address 0x%luX in use\n", io);
+ free(sdev);
+ free(ctlr);
+ continue;
+ }
+ ctlr->rid = p->rid;
+
+ /* avert thine eyes! (what does this do?) */
+ mem[0x104f0/4] = 0;
+ ctlr->type = (p->did >> 12) & 3;
+ if(ctlr->type == 1){
+ n = mem[0xc00/4];
+ n &= ~(3<<4);
+ mem[0xc00/4] = n;
+ }
+
+ 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->lmmio = mem;
+ ctlr->mmio = (uchar*)mem;
+ ctlr->nchip = (nunit+3)/4;
+ ctlr->ndrive = nunit;
+ ctlr->enabled = 0;
+ 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);
+ }
+ for (i = 0; i < nunit; i++) {
+ d = &ctlr->drive[i];
+ d->sectors = 0;
+ d->ctlr = ctlr;
+ d->driveno = ctlrno*NCtlrdrv + i;
+ d->chipx = i%4;
+ d->chip = &ctlr->chip[i/4];
+ d->edma = &d->chip->edma[d->chipx];
+ mvsatadrive[d->driveno] = d;
+ }
+ nmvsatadrive += nunit;
+ ctlrno++;
+ 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;
+ if (ctlr->enabled)
+ return 1;
+ snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name);
+ intrenable(ctlr->irq, mv50interrupt, ctlr, ctlr->tbdf, name);
+ ctlr->enabled = 1;
+ 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;
+ int i;
+
+ dprint("%s: verify\n", unit->name);
+ ctlr = unit->dev->ctlr;
+ drive = &ctlr->drive[unit->subno];
+ ilock(ctlr);
+ ilock(drive);
+ i = configdrive(ctlr, drive, unit);
+ iunlock(drive);
+ iunlock(ctlr);
+
+ /*
+ * If ctlr->type == 1, then the drives spin up whenever
+ * the controller feels like it; if ctlr->type != 1, then
+ * they spin up as a result of configdrive.
+ *
+ * If there is a drive in the slot, give it 1.5s to spin up
+ * before returning. There is a noticeable drag on the
+ * power supply when spinning up fifteen drives
+ * all at once (like in the Coraid enclosures).
+ */
+ if(ctlr->type != 1 && i == 0){
+ if(!waserror()){
+ tsleep(&up->sleep, return0, 0, 1500);
+ poperror();
+ }
+ }
+ return 1;
+}
+
+/*
+ * Check whether the disk is online.
+ */
+static int
+mv50online(SDunit *unit)
+{
+ Ctlr *ctlr;
+ Drive *d;
+ int r, s0;
+ static int once;
+
+ if(once++ == 0)
+ kproc("mvsata", satakproc, 0);
+
+ ctlr = unit->dev->ctlr;
+ d = &ctlr->drive[unit->subno];
+ r = 0;
+ ilock(d);
+ s0 = d->state;
+ USED(s0);
+ if(d->state == Dnew)
+ identifydrive(d);
+ if(d->mediachange){
+ idprint("%s: online: %s -> %s\n", unit->name, diskstates[s0], diskstates[d->state]);
+ r = 2;
+ unit->sectors = d->sectors;
+ unit->secsize = 512;
+ d->mediachange = 0;
+ } else if(d->state == Dready)
+ r = 1;
+ iunlock(d);
+ return r;
+}
+
+/*
+ * 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 %.8lux\n",
+ prefix? prefix: "", prefix? ": ": "",
+ r[i].name, *(ulong *)((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);
+ drive->state = Dreset;
+ iunlock(drive);
+ return 0;
+ }
+ cmderror(cb, Ebadctl);
+ return -1;
+}
+
+/*
+ * sd(3): ``Reading /dev/sdctl yields information about each controller,
+ * one line per controller.''
+ */
+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);
+ if (Coraiddebug) {
+ /* info for first disk. BUG: this shouldn't be here. */
+ 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
+waitready(Drive *d)
+{
+ ulong s, i;
+
+ for(i = 0; i < 120; i++){
+ ilock(d);
+ s = d->bridge->status;
+ iunlock(d);
+ if(s == 0)
+ return SDeio;
+ if (d->state == Dready)
+ return SDok;
+ if ((i+1)%60 == 0){
+ ilock(d);
+ resetdisk(d);
+ iunlock(d);
+ }
+ if(!waserror()){
+ tsleep(&up->sleep, return0, 0, 1000);
+ poperror();
+ }
+ }
+ print("%s: not responding after 2 minutes\n", d->unit->name);
+ return SDeio;
+}
+
+static int
+mv50rio(SDreq *r)
+{
+ int count, max, n, status, try, flag;
+ 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:
+ iprint("%s: bad cmd 0x%.2ux\n", drive->unit->name, 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;
+
+ try = 0;
+retry:
+ if(waitready(drive) != SDok)
+ return SDeio;
+ /*
+ * 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;
+ if((drive->edma->ctl&eEnEDMA) == 0)
+ goto tryagain;
+ srb = srbrw(cmd[0]==0x28 ? SRBread : SRBwrite, drive, data, n, lba);
+ ilock(drive);
+ startsrb(drive, srb);
+ iunlock(drive);
+
+ /* Don't let user interrupt DMA. */
+ while(waserror())
+ ;
+ sleep(srb, srbdone, srb);
+ poperror();
+
+ flag = srb->flag;
+ freesrb(srb);
+ if(flag == 0){
+tryagain:
+ if(++try == 10){
+ print("%s: bad disk\n", drive->unit->name);
+ return SDeio;
+ }
+ dprint("%s: retry\n", drive->unit->name);
+ if(!waserror()){
+ tsleep(&up->sleep, return0, 0, 1000);
+ poperror();
+ }
+ goto retry;
+ }
+ if(flag & SFerror){
+ print("%s: i/o error\n", drive->unit->name);
+ return SDeio;
+ }
+ 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.
+ */
diff --git a/sys/src/9/pc/sdmylex.c b/sys/src/9/pc/sdmylex.c
new file mode 100755
index 000000000..201cdaa08
--- /dev/null
+++ b/sys/src/9/pc/sdmylex.c
@@ -0,0 +1,1269 @@
+/*
+ * Mylex MultiMaster (Buslogic BT-*) SCSI Host Adapter
+ * in both 24-bit and 32-bit mode.
+ * 24-bit mode works for Adaptec AHA-154xx series too.
+ *
+ * To do:
+ * allocate more Ccb's as needed, up to NMbox-1;
+ * add nmbox and nccb to Ctlr struct for the above;
+ * 64-bit LUN/explicit wide support necessary?
+ *
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+#include "../port/sd.h"
+
+#define K2BPA(va, tbdf) PADDR(va)
+#define BPA2K(pa, tbdf) KADDR(pa)
+
+extern SDifc sdmylexifc;
+
+enum { /* registers */
+ Rcontrol = 0x00, /* WO: control register */
+ Rstatus = 0x00, /* RO: status register */
+ Rcpr = 0x01, /* WO: command/parameter register */
+ Rdatain = 0x01, /* RO: data-in register */
+ Rinterrupt = 0x02, /* RO: interrupt register */
+};
+
+enum { /* Rcontrol */
+ Rsbus = 0x10, /* SCSI Bus Reset */
+ Rint = 0x20, /* Interrupt Reset */
+ Rsoft = 0x40, /* Soft Reset */
+ Rhard = 0x80, /* Hard Reset */
+};
+
+enum { /* Rstatus */
+ Cmdinv = 0x01, /* Command Invalid */
+ Dirrdy = 0x04, /* Data In Register Ready */
+ Cprbsy = 0x08, /* Command/Parameter Register Busy */
+ Hardy = 0x10, /* Host Adapter Ready */
+ Inreq = 0x20, /* Initialisation Required */
+ Dfail = 0x40, /* Diagnostic Failure */
+ Dact = 0x80, /* Diagnostic Active */
+};
+
+enum { /* Rcpr */
+ Cinitialise = 0x01, /* Initialise Mailbox */
+ Cstart = 0x02, /* Start Mailbox Command */
+ Cinquiry = 0x04, /* Adapter Inquiry */
+ Ceombri = 0x05, /* Enable OMBR Interrupt */
+ Cinquire = 0x0B, /* Inquire Configuration */
+ Cextbios = 0x28, /* AHA-1542: extended BIOS info. */
+ Cmbienable = 0x29, /* AHA-1542: Mailbox interface enable */
+ Ciem = 0x81, /* Initialise Extended Mailbox */
+ Ciesi = 0x8D, /* Inquire Extended Setup Information */
+ Cerrm = 0x8F, /* Enable strict round-robin mode */
+ Cwide = 0x96, /* Wide CCB */
+};
+
+enum { /* Rinterrupt */
+ Imbl = 0x01, /* Incoming Mailbox Loaded */
+ Mbor = 0x02, /* Mailbox Out Ready */
+ Cmdc = 0x04, /* Command Complete */
+ Rsts = 0x08, /* SCSI Reset State */
+ Intv = 0x80, /* Interrupt Valid */
+};
+
+typedef struct Mbox24 Mbox24;
+struct Mbox24 {
+ uchar code; /* action/completion code */
+ uchar ccb[3]; /* CCB pointer (MSB, ..., LSB) */
+};
+
+typedef struct Mbox32 Mbox32;
+struct Mbox32 {
+ uchar ccb[4]; /* CCB pointer (LSB, ..., MSB) */
+ uchar btstat; /* BT-7[45]7[SD] status */
+ uchar sdstat; /* SCSI device status */
+ uchar pad;
+ uchar code; /* action/completion code */
+};
+
+enum { /* mailbox commands */
+ Mbfree = 0x00, /* Mailbox not in use */
+
+ Mbostart = 0x01, /* Start a mailbox command */
+ Mboabort = 0x02, /* Abort a mailbox command */
+
+ Mbiok = 0x01, /* CCB completed without error */
+ Mbiabort = 0x02, /* CCB aborted at request of host */
+ Mbinx = 0x03, /* Aborted CCB not found */
+ Mbierror = 0x04, /* CCB completed with error */
+};
+
+typedef struct Ccb24 Ccb24;
+typedef struct Ccb32 Ccb32;
+typedef union Ccb Ccb;
+
+typedef struct Ccb24 {
+ uchar opcode; /* Operation code */
+ uchar datadir; /* Data direction control */
+ uchar cdblen; /* Length of CDB */
+ uchar senselen; /* Length of sense area */
+ uchar datalen[3]; /* Data length (MSB, ..., LSB) */
+ uchar dataptr[3]; /* Data pointer (MSB, ..., LSB) */
+ uchar linkptr[3]; /* Link pointer (MSB, ..., LSB) */
+ uchar linkid; /* command linking identifier */
+ uchar btstat; /* BT-* adapter status */
+ uchar sdstat; /* SCSI device status */
+ uchar reserved[2]; /* */
+ uchar cs[12+0xFF]; /* Command descriptor block + Sense */
+
+ void* data; /* buffer if address > 24-bits */
+
+ Rendez;
+ int done; /* command completed */
+
+ Ccb* ccb; /* link on free list */
+} Ccb24;
+
+
+typedef struct Ccb32 {
+ uchar opcode; /* Operation code */
+ uchar datadir; /* Data direction control */
+ uchar cdblen; /* Length of CDB */
+ uchar senselen; /* Length of sense area */
+ uchar datalen[4]; /* Data length (LSB, ..., MSB) */
+ uchar dataptr[4]; /* Data pointer (LSB, ..., MSB) */
+ uchar reserved[2];
+ uchar btstat; /* BT-* adapter status */
+ uchar sdstat; /* SCSI device status */
+ uchar targetid; /* Target ID */
+ uchar luntag; /* LUN & tag */
+ uchar cdb[12]; /* Command descriptor block */
+ uchar ccbctl; /* CCB control */
+ uchar linkid; /* command linking identifier */
+ uchar linkptr[4]; /* Link pointer (LSB, ..., MSB) */
+ uchar senseptr[4]; /* Sense pointer (LSB, ..., MSB) */
+ uchar sense[0xFF]; /* Sense bytes */
+
+ Rendez;
+ int done; /* command completed */
+
+ Ccb* ccb; /* link on free list */
+} Ccb32;
+
+typedef union Ccb {
+ Ccb24;
+ Ccb32;
+} Ccb;
+
+enum { /* opcode */
+ OInitiator = 0x00, /* initiator CCB */
+ Ordl = 0x03, /* initiator CCB with
+ * residual data length returned
+ */
+};
+
+enum { /* datadir */
+ CCBdatain = 0x08, /* inbound, length is checked */
+ CCBdataout = 0x10, /* outbound, length is checked */
+};
+
+enum { /* btstat */
+ Eok = 0x00, /* normal completion with no errors */
+};
+
+enum { /* luntag */
+ TagEnable = 0x20, /* Tag enable */
+ SQTag = 0x00, /* Simple Queue Tag */
+ HQTag = 0x40, /* Head of Queue Tag */
+ OQTag = 0x80, /* Ordered Queue Tag */
+};
+
+enum { /* CCB control */
+ NoDisc = 0x08, /* No disconnect */
+ NoUnd = 0x10, /* No underrrun error report */
+ NoData = 0x20, /* No data transfer */
+ NoStat = 0x40, /* No CCB status if zero */
+ NoIntr = 0x80, /* No Interrupts */
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ int port; /* I/O port */
+ int id; /* adapter SCSI id */
+ int bus; /* 24 or 32 -bit */
+ int irq;
+ int wide;
+ Pcidev* pcidev;
+ SDev* sdev;
+ int spurious;
+
+ Lock issuelock;
+
+ Lock ccblock;
+ QLock ccbq;
+ Rendez ccbr;
+
+ Lock mboxlock;
+ void* mb; /* mailbox out + mailbox in */
+ int mbox; /* current mailbox out index into mb */
+ int mbix; /* current mailbox in index into mb */
+
+ Lock cachelock;
+ Ccb* ccb; /* list of free Ccb's */
+ Ccb** cache; /* last completed Ccb */
+};
+
+/*
+ * The number of mailboxes should be a multiple of 8 (4 for Mbox32)
+ * to ensure the boundary between the out and in mailboxes doesn't
+ * straddle a cache-line boundary.
+ * The number of Ccb's should be less than the number of mailboxes to
+ * ensure no queueing is necessary on mailbox allocation.
+ */
+enum {
+ NMbox = 8*8, /* number of Mbox's */
+ NCcb = NMbox-1, /* number of Ccb's */
+};
+
+#define PADDR24(a, n) ((PADDR(a)+(n)) <= (1<<24))
+
+static void
+ccbfree(Ctlr* ctlr, Ccb* ccb)
+{
+ lock(&ctlr->ccblock);
+ if(ctlr->bus == 24)
+ ((Ccb24*)ccb)->ccb = ctlr->ccb;
+ else
+ ((Ccb32*)ccb)->ccb = ctlr->ccb;
+ if(ctlr->ccb == nil)
+ wakeup(&ctlr->ccbr);
+ ctlr->ccb = ccb;
+ unlock(&ctlr->ccblock);
+}
+
+static int
+ccbavailable(void* a)
+{
+ return ((Ctlr*)a)->ccb != nil;
+}
+
+static Ccb*
+ccballoc(Ctlr* ctlr)
+{
+ Ccb *ccb;
+
+ for(;;){
+ lock(&ctlr->ccblock);
+ if((ccb = ctlr->ccb) != nil){
+ if(ctlr->bus == 24)
+ ctlr->ccb = ((Ccb24*)ccb)->ccb;
+ else
+ ctlr->ccb = ((Ccb32*)ccb)->ccb;
+ unlock(&ctlr->ccblock);
+ break;
+ }
+
+ unlock(&ctlr->ccblock);
+ qlock(&ctlr->ccbq);
+ if(waserror()){
+ qunlock(&ctlr->ccbq);
+ continue;
+ }
+ sleep(&ctlr->ccbr, ccbavailable, ctlr);
+ qunlock(&ctlr->ccbq);
+ poperror();
+ }
+
+ return ccb;
+}
+
+static int
+done24(void* arg)
+{
+ return ((Ccb24*)arg)->done;
+}
+
+static int
+mylex24rio(SDreq* r)
+{
+ ulong p;
+ Ctlr *ctlr;
+ Ccb24 *ccb;
+ Mbox24 *mb;
+ uchar *data, lun, *sense;
+ int d, n, btstat, sdstat, target;
+
+ ctlr = r->unit->dev->ctlr;
+ target = r->unit->subno;
+ lun = (r->cmd[1]>>5) & 0x07;
+
+ /*
+ * Ctlr->cache holds the last completed Ccb for this target if it
+ * returned 'check condition'.
+ * If this command is a request-sense and there is valid sense data
+ * from the last completed Ccb, return it immediately.
+ */
+ lock(&ctlr->cachelock);
+ if((ccb = ctlr->cache[target]) != nil){
+ ctlr->cache[target] = nil;
+ if(r->cmd[0] == 0x03
+ && ccb->sdstat == SDcheck && lun == ((ccb->cs[1]>>5) & 0x07)){
+ unlock(&ctlr->cachelock);
+ if(r->dlen){
+ sense = &ccb->cs[ccb->cdblen];
+ n = 8+sense[7];
+ if(n > r->dlen)
+ n = r->dlen;
+ memmove(r->data, sense, n);
+ r->rlen = n;
+ }
+ ccbfree(ctlr, (Ccb*)ccb);
+ return SDok;
+ }
+ }
+ unlock(&ctlr->cachelock);
+ if(ccb == nil)
+ ccb = ccballoc(ctlr);
+
+ /*
+ * Check if the transfer is to memory above the 24-bit limit the
+ * controller can address. If it is, try to allocate a temporary
+ * buffer as a staging area.
+ */
+ n = r->dlen;
+ if(n && !PADDR24(r->data, n)){
+ data = mallocz(n, 0);
+ if(data == nil || !PADDR24(data, n)){
+ if(data != nil){
+ free(data);
+ ccb->data = nil;
+ }
+ ccbfree(ctlr, (Ccb*)ccb);
+ return SDmalloc;
+ }
+ if(r->write)
+ memmove(data, r->data, n);
+ ccb->data = r->data;
+ }
+ else
+ data = r->data;
+
+ /*
+ * Fill in the ccb.
+ */
+ ccb->opcode = Ordl;
+
+ ccb->datadir = (target<<5)|lun;
+ if(n == 0)
+ ccb->datadir |= CCBdataout|CCBdatain;
+ else if(!r->write)
+ ccb->datadir |= CCBdatain;
+ else
+ ccb->datadir |= CCBdataout;
+
+ ccb->cdblen = r->clen;
+ ccb->senselen = 0xFF;
+
+ ccb->datalen[0] = n>>16;
+ ccb->datalen[1] = n>>8;
+ ccb->datalen[2] = n;
+ if(data == nil)
+ p = 0;
+ else
+ p = PADDR(data);
+ ccb->dataptr[0] = p>>16;
+ ccb->dataptr[1] = p>>8;
+ ccb->dataptr[2] = p;
+
+ ccb->linkptr[0] = ccb->linkptr[1] = ccb->linkptr[2] = 0;
+ ccb->linkid = 0;
+ ccb->btstat = ccb->sdstat = 0;
+ ccb->reserved[0] = ccb->reserved[1] = 0;
+
+ memmove(ccb->cs, r->cmd, r->clen);
+
+ /*
+ * There's one more mbox than there there is
+ * ccb so there is always one free.
+ */
+ lock(&ctlr->mboxlock);
+ mb = ctlr->mb;
+ mb += ctlr->mbox;
+ p = PADDR(ccb);
+ mb->ccb[0] = p>>16;
+ mb->ccb[1] = p>>8;
+ mb->ccb[2] = p;
+ mb->code = Mbostart;
+ ctlr->mbox++;
+ if(ctlr->mbox >= NMbox)
+ ctlr->mbox = 0;
+
+ /*
+ * This command does not require Hardy
+ * and doesn't generate a Cmdc interrupt.
+ */
+ ccb->done = 0;
+ outb(ctlr->port+Rcpr, Cstart);
+ unlock(&ctlr->mboxlock);
+
+ /*
+ * Wait for the request to complete and return the status.
+ * Since the buffer is not reference counted cannot return
+ * until the DMA is done writing into the buffer so the caller
+ * cannot free the buffer prematurely.
+ */
+ while(waserror())
+ ;
+ sleep(ccb, done24, ccb);
+ poperror();
+
+ /*
+ * Save the status and patch up the number of
+ * bytes actually transferred.
+ * There's a firmware bug on some 956C controllers
+ * which causes the return count from a successful
+ * READ CAPACITY not be updated, so fix it here.
+ */
+ sdstat = ccb->sdstat;
+ btstat = ccb->btstat;
+
+ d = ccb->datalen[0]<<16;
+ d |= ccb->datalen[1]<<8;
+ d |= ccb->datalen[2];
+ if(ccb->cs[0] == 0x25 && sdstat == SDok)
+ d = 0;
+ n -= d;
+ r->rlen = n;
+
+ /*
+ * Tidy things up if a staging area was used for the data,
+ */
+ if(ccb->data != nil){
+ if(sdstat == SDok && btstat == 0 && !r->write)
+ memmove(ccb->data, data, n);
+ free(data);
+ ccb->data = nil;
+ }
+
+ /*
+ * If there was a check-condition, save the
+ * ccb for a possible request-sense command.
+ */
+ if(sdstat == SDcheck){
+ if(r->flags & SDnosense){
+ lock(&ctlr->cachelock);
+ if(ctlr->cache[target])
+ ccbfree(ctlr, ctlr->cache[target]);
+ ctlr->cache[target] = (Ccb*)ccb;
+ unlock(&ctlr->cachelock);
+ return SDcheck;
+ }
+ sense = &ccb->cs[ccb->cdblen];
+ n = 8+sense[7];
+ if(n > sizeof(r->sense)-1)
+ n = sizeof(r->sense)-1;
+ memmove(r->sense, sense, n);
+ r->flags |= SDvalidsense;
+ }
+ ccbfree(ctlr, (Ccb*)ccb);
+
+ if(btstat){
+ if(btstat == 0x11)
+ return SDtimeout;
+ return SDeio;
+ }
+ return sdstat;
+}
+
+static void
+mylex24interrupt(Ureg*, void* arg)
+{
+ ulong pa;
+ Ctlr *ctlr;
+ Ccb24 *ccb;
+ Mbox24 *mb, *mbox;
+ int port, rinterrupt, rstatus;
+
+ ctlr = arg;
+ port = ctlr->port;
+
+ /*
+ * Save and clear the interrupt(s). The only
+ * interrupts expected are Cmdc, which is ignored,
+ * and Imbl which means something completed.
+ * There's one spurious interrupt left over from
+ * initialisation, ignore it.
+ */
+ rinterrupt = inb(port+Rinterrupt);
+ rstatus = inb(port+Rstatus);
+ outb(port+Rcontrol, Rint);
+ if((rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
+ print("%s: interrupt 0x%2.2ux\n",
+ ctlr->sdev->name, rinterrupt);
+ if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
+ print("%s: command invalid\n", ctlr->sdev->name);
+
+ /*
+ * Look for something in the mail.
+ * If there is, save the status, free the mailbox
+ * and wakeup whoever.
+ */
+ mb = ctlr->mb;
+ for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
+ pa = (mbox->ccb[0]<<16)|(mbox->ccb[1]<<8)|mbox->ccb[2];
+ ccb = BPA2K(pa, BUSUNKNOWN);
+ mbox->code = 0;
+ ccb->done = 1;
+ wakeup(ccb);
+
+ ctlr->mbix++;
+ if(ctlr->mbix >= NMbox+NMbox)
+ ctlr->mbix = NMbox;
+ }
+}
+
+static int
+done32(void* arg)
+{
+ return ((Ccb32*)arg)->done;
+}
+
+static int
+mylex32rio(SDreq* r)
+{
+ ulong p;
+ uchar lun;
+ Ctlr *ctlr;
+ Ccb32 *ccb;
+ Mbox32 *mb;
+ int d, n, btstat, sdstat, target;
+
+ ctlr = r->unit->dev->ctlr;
+ target = r->unit->subno;
+ lun = (r->cmd[1]>>5) & 0x07;
+
+ /*
+ * Ctlr->cache holds the last completed Ccb for this target if it
+ * returned 'check condition'.
+ * If this command is a request-sense and there is valid sense data
+ * from the last completed Ccb, return it immediately.
+ */
+ lock(&ctlr->cachelock);
+ if((ccb = ctlr->cache[target]) != nil){
+ ctlr->cache[target] = nil;
+ if(r->cmd[0] == 0x03
+ && ccb->sdstat == SDcheck && lun == (ccb->luntag & 0x07)){
+ unlock(&ctlr->cachelock);
+ if(r->dlen){
+ n = 8+ccb->sense[7];
+ if(n > r->dlen)
+ n = r->dlen;
+ memmove(r->data, ccb->sense, n);
+ r->rlen = n;
+ }
+ ccbfree(ctlr, (Ccb*)ccb);
+ return SDok;
+ }
+ }
+ unlock(&ctlr->cachelock);
+ if(ccb == nil)
+ ccb = ccballoc(ctlr);
+
+ /*
+ * Fill in the ccb.
+ */
+ ccb->opcode = Ordl;
+
+ n = r->dlen;
+ if(n == 0)
+ ccb->datadir = CCBdataout|CCBdatain;
+ else if(!r->write)
+ ccb->datadir = CCBdatain;
+ else
+ ccb->datadir = CCBdataout;
+
+ ccb->cdblen = r->clen;
+
+ ccb->datalen[0] = n;
+ ccb->datalen[1] = n>>8;
+ ccb->datalen[2] = n>>16;
+ ccb->datalen[3] = n>>24;
+ if(r->data == nil)
+ p = 0;
+ else
+ p = PADDR(r->data);
+ ccb->dataptr[0] = p;
+ ccb->dataptr[1] = p>>8;
+ ccb->dataptr[2] = p>>16;
+ ccb->dataptr[3] = p>>24;
+
+ ccb->targetid = target;
+ ccb->luntag = lun;
+ if(r->unit->inquiry[7] & 0x02)
+ if(ctlr->wide)
+ ccb->datadir |= SQTag|TagEnable;
+ else
+ ccb->luntag |= SQTag|TagEnable;
+ memmove(ccb->cdb, r->cmd, r->clen);
+ ccb->btstat = ccb->sdstat = 0;
+ ccb->ccbctl = 0;
+
+ /*
+ * There's one more mbox than there there is
+ * ccb so there is always one free.
+ */
+ lock(&ctlr->mboxlock);
+ mb = ctlr->mb;
+ mb += ctlr->mbox;
+ p = PADDR(ccb);
+ mb->ccb[0] = p;
+ mb->ccb[1] = p>>8;
+ mb->ccb[2] = p>>16;
+ mb->ccb[3] = p>>24;
+ mb->code = Mbostart;
+ ctlr->mbox++;
+ if(ctlr->mbox >= NMbox)
+ ctlr->mbox = 0;
+
+ /*
+ * This command does not require Hardy
+ * and doesn't generate a Cmdc interrupt.
+ */
+ ccb->done = 0;
+ outb(ctlr->port+Rcpr, Cstart);
+ unlock(&ctlr->mboxlock);
+
+ /*
+ * Wait for the request to complete and return the status.
+ * Since the buffer is not reference counted cannot return
+ * until the DMA is done writing into the buffer so the caller
+ * cannot free the buffer prematurely.
+ */
+ while(waserror())
+ ;
+ sleep(ccb, done32, ccb);
+ poperror();
+
+ /*
+ * Save the status and patch up the number of
+ * bytes actually transferred.
+ * There's a firmware bug on some 956C controllers
+ * which causes the return count from a successful
+ * READ CAPACITY not to be updated, so fix it here.
+ */
+ sdstat = ccb->sdstat;
+ btstat = ccb->btstat;
+
+ d = ccb->datalen[0];
+ d |= (ccb->datalen[1]<<8);
+ d |= (ccb->datalen[2]<<16);
+ d |= (ccb->datalen[3]<<24);
+ if(ccb->cdb[0] == 0x25 && sdstat == SDok)
+ d = 0;
+ n -= d;
+ r->rlen = n;
+
+ /*
+ * If there was a check-condition, save the
+ * ccb for a possible request-sense command.
+ */
+ if(sdstat == SDcheck){
+ if(r->flags & SDnosense){
+ lock(&ctlr->cachelock);
+ if(ctlr->cache[target])
+ ccbfree(ctlr, ctlr->cache[target]);
+ ctlr->cache[target] = (Ccb*)ccb;
+ unlock(&ctlr->cachelock);
+ return SDcheck;
+ }
+ n = 8+ccb->sense[7];
+ if(n > sizeof(r->sense)-1)
+ n = sizeof(r->sense)-1;
+ memmove(r->sense, ccb->sense, n);
+ r->flags |= SDvalidsense;
+ }
+ ccbfree(ctlr, (Ccb*)ccb);
+
+ if(btstat){
+ if(btstat == 0x11)
+ return SDtimeout;
+ return SDeio;
+ }
+ return sdstat;
+}
+
+static void
+mylex32interrupt(Ureg*, void* arg)
+{
+ ulong pa;
+ Ctlr *ctlr;
+ Ccb32 *ccb;
+ Mbox32 *mb, *mbox;
+ int port, rinterrupt, rstatus;
+
+ ctlr = arg;
+ port = ctlr->port;
+
+ /*
+ * Save and clear the interrupt(s). The only
+ * interrupts expected are Cmdc, which is ignored,
+ * and Imbl which means something completed.
+ * There's one spurious interrupt left over from
+ * initialisation, ignore it.
+ * In order to share PCI IRQs, just ignore spurious interrupts.
+ */
+ rinterrupt = inb(port+Rinterrupt);
+ rstatus = inb(port+Rstatus);
+ outb(port+Rcontrol, Rint);
+ if(0 && (rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
+ print("%s: interrupt 0x%2.2ux\n",
+ ctlr->sdev->name, rinterrupt);
+ if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
+ print("%s: command invalid\n", ctlr->sdev->name);
+
+ /*
+ * Look for something in the mail.
+ * If there is, free the mailbox and wakeup whoever.
+ */
+ mb = ctlr->mb;
+ for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
+ pa = (mbox->ccb[3]<<24)
+ |(mbox->ccb[2]<<16)
+ |(mbox->ccb[1]<<8)
+ |mbox->ccb[0];
+ if(ctlr->pcidev)
+ ccb = BPA2K(pa, ctlr->pcidev->tbdf);
+ else
+ ccb = BPA2K(pa, BUSUNKNOWN);
+ mbox->code = 0;
+ ccb->done = 1;
+ wakeup(ccb);
+
+ ctlr->mbix++;
+ if(ctlr->mbix >= NMbox+NMbox)
+ ctlr->mbix = NMbox;
+ }
+}
+
+static int
+mylexrio(SDreq* r)
+{
+ int subno;
+ Ctlr *ctlr;
+
+ subno = r->unit->subno;
+ ctlr = r->unit->dev->ctlr;
+ if(subno == ctlr->id || (!ctlr->wide && subno >= 8))
+ r->status = SDtimeout;
+ else if(ctlr->bus == 24)
+ r->status = mylex24rio(r);
+ else
+ r->status = mylex32rio(r);
+ return r->status;
+}
+
+/*
+ * Issue a command to a controller. The command and its length is
+ * contained in cmd and cmdlen. If any data is to be
+ * returned, datalen should be non-zero, and the returned data
+ * will be placed in data.
+ * If Cmdc is set, bail out, the invalid command will be handled
+ * when the interrupt is processed.
+ */
+static void
+issueio(int port, uchar* cmd, int cmdlen, uchar* data, int datalen)
+{
+ int len;
+
+ if(cmd[0] != Cstart && cmd[0] != Ceombri){
+ while(!(inb(port+Rstatus) & Hardy))
+ ;
+ }
+ outb(port+Rcpr, cmd[0]);
+
+ len = 1;
+ while(len < cmdlen){
+ if(!(inb(port+Rstatus) & Cprbsy)){
+ outb(port+Rcpr, cmd[len]);
+ len++;
+ }
+ if(inb(port+Rinterrupt) & Cmdc)
+ return;
+ }
+
+ if(datalen){
+ len = 0;
+ while(len < datalen){
+ if(inb(port+Rstatus) & Dirrdy){
+ data[len] = inb(port+Rdatain);
+ len++;
+ }
+ if(inb(port+Rinterrupt) & Cmdc)
+ return;
+ }
+ }
+}
+
+/*
+ * Issue a command to a controller, wait for it to complete then
+ * try to reset the interrupt. Should only be called at initialisation.
+ */
+static int
+issue(Ctlr* ctlr, uchar* cmd, int cmdlen, uchar* data, int datalen)
+{
+ int port;
+ uchar rinterrupt, rstatus;
+ static Lock mylexissuelock;
+
+ port = ctlr->port;
+
+ ilock(&ctlr->issuelock);
+ issueio(port, cmd, cmdlen, data, datalen);
+
+ while(!((rinterrupt = inb(port+Rinterrupt)) & Cmdc))
+ ;
+
+ rstatus = inb(port+Rstatus);
+ outb(port+Rcontrol, Rint);
+ iunlock(&ctlr->issuelock);
+
+ if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
+ return 0;
+ return 1;
+}
+
+static SDev*
+mylexprobe(int port, int irq)
+{
+ SDev *sdev;
+ Ctlr *ctlr;
+ uchar cmd[6], data[256];
+ int clen, dlen, timeo;
+ static int count;
+
+ if(ioalloc(port, 0x3, 0, "mylex") < 0)
+ return nil;
+ ctlr = nil;
+ sdev = nil;
+ /*
+ * Attempt to hard-reset the board and reset
+ * the SCSI bus. If the board state doesn't settle to
+ * idle with mailbox initialisation required, either
+ * it isn't a compatible board or it's broken.
+ * If the controller has SCAM set this can take a while.
+ */
+ if(getconf("*noscsireset") != nil)
+ outb(port+Rcontrol, Rhard);
+ else
+ outb(port+Rcontrol, Rhard|Rsbus);
+ for(timeo = 0; timeo < 100; timeo++){
+ if(inb(port+Rstatus) == (Inreq|Hardy))
+ break;
+ delay(100);
+ }
+ if(inb(port+Rstatus) != (Inreq|Hardy)){
+buggery:
+ if(ctlr != nil)
+ free(ctlr);
+ if (sdev != nil)
+ free(sdev);
+ iofree(port);
+ return nil;
+ }
+
+ if((ctlr = malloc(sizeof(Ctlr))) == nil)
+ goto buggery;
+ ctlr->port = port;
+ ctlr->irq = irq;
+ ctlr->bus = 24;
+ ctlr->wide = 0;
+
+ /*
+ * Try to determine if this is a 32-bit MultiMaster controller
+ * by attempting to obtain the extended inquiry information;
+ * this command is not implemented on Adaptec 154xx
+ * controllers. If successful, the first byte of the returned
+ * data is the host adapter bus type, 'E' for 32-bit EISA,
+ * PCI and VLB buses.
+ */
+ cmd[0] = Ciesi;
+ cmd[1] = 14;
+ clen = 2;
+ dlen = 256;
+ if(issue(ctlr, cmd, clen, data, dlen)){
+ if(data[0] == 'E')
+ ctlr->bus = 32;
+ ctlr->wide = data[0x0D] & 0x01;
+ /*
+ * devsd doesn't pass us the `spec' argument, so
+ * we'll assume that sd0 goes to the first scsi host
+ * adapter found, etc.
+ */
+ print("#S/sd%d: mylex SCSI: port 0x%ux: %d-bit, ",
+ count++, ctlr->port, ctlr->bus);
+ if (ctlr->wide)
+ print("wide\n");
+ else
+ print("narrow\n");
+ }
+ else{
+ /*
+ * Inconceivable though it may seem, a hard controller reset
+ * is necessary here to clear out the command queue. Every
+ * board seems to lock-up in a different way if you give an
+ * invalid command and then try to clear out the
+ * command/parameter and/or data-in register.
+ * Soft reset doesn't do the job either. Fortunately no
+ * serious initialisation has been done yet so there's nothing
+ * to tidy up.
+ */
+ outb(port+Rcontrol, Rhard);
+ for(timeo = 0; timeo < 100; timeo++){
+ if(inb(port+Rstatus) == (Inreq|Hardy))
+ break;
+ delay(100);
+ }
+ if(inb(port+Rstatus) != (Inreq|Hardy))
+ goto buggery;
+ }
+
+ /*
+ * If the BIOS is enabled on the AHA-1542C/CF and BIOS options for
+ * support of drives > 1Gb, dynamic scanning of the SCSI bus or more
+ * than 2 drives under DOS 5.0 are enabled, the BIOS disables
+ * accepting Cmbinit to protect against running with drivers which
+ * don't support those options. In order to unlock the interface it
+ * is necessary to read a lock-code using Cextbios and write it back
+ * using Cmbienable; the lock-code is non-zero.
+ */
+ cmd[0] = Cinquiry;
+ clen = 1;
+ dlen = 4;
+ if(issue(ctlr, cmd, clen, data, dlen) == 0)
+ goto buggery;
+ if(data[0] >= 0x43){
+ cmd[0] = Cextbios;
+ clen = 1;
+ dlen = 2;
+ if(issue(ctlr, cmd, clen, data, dlen) == 0)
+ goto buggery;
+
+ /*
+ * Lock-code returned in data[1]. If it's non-zero write
+ * it back along with bit 0 of byte 0 cleared to enable
+ * mailbox initialisation.
+ */
+ if(data[1]){
+ cmd[0] = Cmbienable;
+ cmd[1] = 0;
+ cmd[2] = data[1];
+ clen = 3;
+ if(issue(ctlr, cmd, clen, 0, 0) == 0)
+ goto buggery;
+ }
+ }
+
+ /*
+ * Get the id, DMA and IRQ info from the board. This will
+ * cause an interrupt which will hopefully not cause any
+ * trouble because the interrupt number isn't known yet.
+ * This is necessary as the DMA won't be set up if the
+ * board has the BIOS disabled.
+ *
+ * If the IRQ is already known, this must be a 32-bit PCI
+ * or EISA card, in which case the returned DMA and IRQ can
+ * be ignored.
+ */
+ cmd[0] = Cinquire;
+ clen = 1;
+ dlen = 3;
+ if(issue(ctlr, cmd, clen, data, dlen) == 0)
+ goto buggery;
+
+ ctlr->id = data[2] & 0x07;
+ if(ctlr->irq < 0){
+ switch(data[0]){ /* DMA Arbitration Priority */
+ case 0x80: /* Channel 7 */
+ outb(0xD6, 0xC3);
+ outb(0xD4, 0x03);
+ break;
+ case 0x40: /* Channel 6 */
+ outb(0xD6, 0xC2);
+ outb(0xD4, 0x02);
+ break;
+ case 0x20: /* Channel 5 */
+ outb(0xD6, 0xC1);
+ outb(0xD4, 0x01);
+ break;
+ case 0x01: /* Channel 0 */
+ outb(0x0B, 0xC0);
+ outb(0x0A, 0x00);
+ break;
+ default:
+ if(ctlr->bus == 24)
+ goto buggery;
+ break;
+ }
+
+ switch(data[1]){ /* Interrupt Channel */
+ case 0x40:
+ ctlr->irq = 15;
+ break;
+ case 0x20:
+ ctlr->irq = 14;
+ break;
+ case 0x08:
+ ctlr->irq = 12;
+ break;
+ case 0x04:
+ ctlr->irq = 11;
+ break;
+ case 0x02:
+ ctlr->irq = 10;
+ break;
+ case 0x01:
+ ctlr->irq = 9;
+ break;
+ default:
+ goto buggery;
+ }
+ }
+
+ if((sdev = malloc(sizeof(SDev))) == nil)
+ goto buggery;
+ sdev->ifc = &sdmylexifc;
+ sdev->ctlr = ctlr;
+ sdev->idno = '0';
+ ctlr->sdev = sdev;
+ if(!ctlr->wide)
+ sdev->nunit = 8;
+ else
+ sdev->nunit = 16;
+
+ return sdev;
+}
+
+static int mylexport[8] = {
+ 0x330, 0x334, 0x230, 0x234, 0x130, 0x134, 0x000, 0x000,
+};
+
+static SDev*
+mylexpnp(void)
+{
+ Pcidev *p;
+ Ctlr *ctlr;
+ ISAConf isa;
+ int cfg, ctlrno, i, x;
+ SDev *sdev, *head, *tail;
+
+ p = nil;
+ head = tail = nil;
+ while(p = pcimatch(p, 0x104B, 0)){
+ if((sdev = mylexprobe(p->mem[0].bar & ~0x01, p->intl)) == nil)
+ continue;
+
+ ctlr = sdev->ctlr;
+ ctlr->pcidev = p;
+
+ if(head != nil)
+ tail->next = sdev;
+ else
+ head = sdev;
+ tail = sdev;
+ }
+
+ if(strncmp(KADDR(0xFFFD9), "EISA", 4) == 0){
+ for(cfg = 0x1000; cfg < MaxEISA*0x1000; cfg += 0x1000){
+ x = 0;
+ for(i = 0; i < 4; i++)
+ x |= inb(cfg+CfgEISA+i)<<(i*8);
+ if(x != 0x0142B30A && x != 0x0242B30A)
+ continue;
+
+ x = inb(cfg+0xC8C);
+ if((sdev = mylexprobe(mylexport[x & 0x07], -1)) == nil)
+ continue;
+
+ if(head != nil)
+ tail->next = sdev;
+ else
+ head = sdev;
+ tail = sdev;
+ }
+ }
+
+ for(ctlrno = 0; ctlrno < 4; ctlrno++){
+ memset(&isa, 0, sizeof(isa));
+ if(!isaconfig("scsi", ctlrno, &isa))
+ continue;
+ if(strcmp(isa.type, "aha1542"))
+ continue;
+ if((sdev = mylexprobe(isa.port, -1)) == nil)
+ continue;
+
+ if(head != nil)
+ tail->next = sdev;
+ else
+ head = sdev;
+ tail = sdev;
+ }
+
+ return head;
+}
+
+static int
+mylex24enable(Ctlr* ctlr)
+{
+ ulong p;
+ Ccb24 *ccb, *ccbp;
+ uchar cmd[6], *v;
+ int len;
+
+ len = (sizeof(Mbox24)*NMbox*2)+(sizeof(Ccb24)*NCcb);
+ v = xspanalloc(len, 32, 0);
+
+ if(!PADDR24(ctlr, sizeof(Ctlr)) || !PADDR24(v, len))
+ return 0;
+
+ ctlr->mb = v;
+ v += sizeof(Mbox24)*NMbox*2;
+
+ ccb = (Ccb24*)v;
+ for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
+ ccbp->ccb = ctlr->ccb;
+ ctlr->ccb = (Ccb*)ccbp;
+ }
+
+ /*
+ * Initialise the software controller and
+ * set the board scanning the mailboxes.
+ */
+ ctlr->mbix = NMbox;
+
+ cmd[0] = Cinitialise;
+ cmd[1] = NMbox;
+ p = K2BPA(ctlr->mb, BUSUNKNOWN);
+ cmd[2] = p>>16;
+ cmd[3] = p>>8;
+ cmd[4] = p;
+
+ return issue(ctlr, cmd, 5, 0, 0);
+}
+
+static int
+mylex32enable(Ctlr* ctlr)
+{
+ ulong p;
+ Ccb32 *ccb, *ccbp;
+ uchar cmd[6], *v;
+
+ v = xspanalloc((sizeof(Mbox32)*NMbox*2)+(sizeof(Ccb32)*NCcb), 32, 0);
+
+ ctlr->mb = v;
+ v += sizeof(Mbox32)*NMbox*2;
+
+ ccb = (Ccb32*)v;
+ for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
+ /*
+ * Fill in some stuff that doesn't change.
+ */
+ ccbp->senselen = sizeof(ccbp->sense);
+ p = PADDR(ccbp->sense);
+ ccbp->senseptr[0] = p;
+ ccbp->senseptr[1] = p>>8;
+ ccbp->senseptr[2] = p>>16;
+ ccbp->senseptr[3] = p>>24;
+
+ ccbp->ccb = ctlr->ccb;
+ ctlr->ccb = (Ccb*)ccbp;
+ }
+
+ /*
+ * Attempt wide mode setup.
+ */
+ if(ctlr->wide){
+ cmd[0] = Cwide;
+ cmd[1] = 1;
+ if(!issue(ctlr, cmd, 2, 0, 0)) {
+ ctlr->wide = 0;
+ print("mylex32enable: port 0x%ux: scsi wide-mode setup "
+ "failed on wide host adapter", ctlr->port);
+ }
+ }
+
+ /*
+ * Initialise the software controller and
+ * set the board scanning the mailboxes.
+ */
+ ctlr->mbix = NMbox;
+
+ cmd[0] = Ciem;
+ cmd[1] = NMbox;
+ if(ctlr->pcidev)
+ p = K2BPA(ctlr->mb, ctlr->tbdf);
+ else
+ p = K2BPA(ctlr->mb, BUSUNKNOWN);
+ cmd[2] = p;
+ cmd[3] = p>>8;
+ cmd[4] = p>>16;
+ cmd[5] = p>>24;
+
+ return issue(ctlr, cmd, 6, 0, 0);
+}
+
+static int
+mylexenable(SDev* sdev)
+{
+ int tbdf;
+ Ctlr *ctlr;
+ void (*interrupt)(Ureg*, void*);
+ char name[32];
+
+ ctlr = sdev->ctlr;
+ if(ctlr->cache == nil){
+ if((ctlr->cache = malloc(sdev->nunit*sizeof(Ccb*))) == nil)
+ return 0;
+ }
+
+ tbdf = BUSUNKNOWN;
+ if(ctlr->bus == 32){
+ if(ctlr->pcidev){
+ tbdf = ctlr->pcidev->tbdf;
+ pcisetbme(ctlr->pcidev);
+ }
+ if(!mylex32enable(ctlr))
+ return 0;
+ interrupt = mylex32interrupt;
+ }
+ else if(mylex24enable(ctlr))
+ interrupt = mylex24interrupt;
+ else
+ return 0;
+
+ snprint(name, sizeof(name), "sd%c (%s)", sdev->idno, sdev->ifc->name);
+ intrenable(ctlr->irq, interrupt, ctlr, tbdf, name);
+
+ return 1;
+}
+
+SDifc sdmylexifc = {
+ "mylex", /* name */
+
+ mylexpnp, /* pnp */
+ nil, /* legacy */
+ mylexenable, /* enable */
+ nil, /* disable */
+
+ scsiverify, /* verify */
+ scsionline, /* online */
+ mylexrio, /* rio */
+ nil, /* rctl */
+ nil, /* wctl */
+
+ scsibio, /* bio */
+ nil, /* probe */
+ nil, /* clear */
+ nil, /* rtopctl */
+ nil, /* wtopctl */
+};
diff --git a/sys/src/9/pc/trap.c b/sys/src/9/pc/trap.c
new file mode 100755
index 000000000..17ca545c5
--- /dev/null
+++ b/sys/src/9/pc/trap.c
@@ -0,0 +1,1077 @@
+#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"
+#include <trace.h>
+
+static int trapinited;
+
+void noted(Ureg*, ulong);
+
+static void debugbpt(Ureg*, void*);
+static void fault386(Ureg*, void*);
+static void doublefault(Ureg*, void*);
+static void unexpected(Ureg*, void*);
+static void _dumpstack(Ureg*);
+
+static Lock vctllock;
+static Vctl *vctl[256];
+
+enum
+{
+ Ntimevec = 20 /* number of time buckets for each intr */
+};
+ulong intrtimes[256][Ntimevec];
+
+void
+intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
+{
+ int vno;
+ Vctl *v;
+
+ if(f == nil){
+ print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n",
+ irq, tbdf, name);
+ return;
+ }
+
+ v = xalloc(sizeof(Vctl));
+ v->isintr = 1;
+ v->irq = irq;
+ v->tbdf = tbdf;
+ v->f = f;
+ v->a = a;
+ strncpy(v->name, name, KNAMELEN-1);
+ v->name[KNAMELEN-1] = 0;
+
+ ilock(&vctllock);
+ vno = arch->intrenable(v);
+ if(vno == -1){
+ iunlock(&vctllock);
+ print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n",
+ irq, tbdf, v->name);
+ xfree(v);
+ return;
+ }
+ if(vctl[vno]){
+ if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)
+ panic("intrenable: handler: %s %s %#p %#p %#p %#p",
+ vctl[vno]->name, v->name,
+ vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);
+ v->next = vctl[vno];
+ }
+ vctl[vno] = v;
+ iunlock(&vctllock);
+}
+
+int
+intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
+{
+ Vctl **pv, *v;
+ int vno;
+
+ /*
+ * For now, none of this will work with the APIC code,
+ * there is no mapping between irq and vector as the IRQ
+ * is pretty meaningless.
+ */
+ if(arch->intrvecno == nil)
+ return -1;
+ vno = arch->intrvecno(irq);
+ ilock(&vctllock);
+ pv = &vctl[vno];
+ while (*pv &&
+ ((*pv)->irq != irq || (*pv)->tbdf != tbdf || (*pv)->f != f || (*pv)->a != a ||
+ strcmp((*pv)->name, name)))
+ pv = &((*pv)->next);
+ assert(*pv);
+
+ v = *pv;
+ *pv = (*pv)->next; /* Link out the entry */
+
+ if(vctl[vno] == nil && arch->intrdisable != nil)
+ arch->intrdisable(irq);
+ iunlock(&vctllock);
+ xfree(v);
+ return 0;
+}
+
+static long
+irqallocread(Chan*, void *vbuf, long n, vlong offset)
+{
+ char *buf, *p, str[2*(11+1)+KNAMELEN+1+1];
+ int m, vno;
+ long oldn;
+ Vctl *v;
+
+ if(n < 0 || offset < 0)
+ error(Ebadarg);
+
+ oldn = n;
+ buf = vbuf;
+ for(vno=0; vno<nelem(vctl); vno++){
+ for(v=vctl[vno]; v; v=v->next){
+ m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name);
+ if(m <= offset) /* if do not want this, skip entry */
+ offset -= m;
+ else{
+ /* skip offset bytes */
+ m -= offset;
+ p = str+offset;
+ offset = 0;
+
+ /* write at most max(n,m) bytes */
+ if(m > n)
+ m = n;
+ memmove(buf, p, m);
+ n -= m;
+ buf += m;
+
+ if(n == 0)
+ return oldn;
+ }
+ }
+ }
+ return oldn - n;
+}
+
+void
+trapenable(int vno, void (*f)(Ureg*, void*), void* a, char *name)
+{
+ Vctl *v;
+
+ if(vno < 0 || vno >= VectorPIC)
+ panic("trapenable: vno %d", vno);
+ v = xalloc(sizeof(Vctl));
+ v->tbdf = BUSUNKNOWN;
+ v->f = f;
+ v->a = a;
+ strncpy(v->name, name, KNAMELEN);
+ v->name[KNAMELEN-1] = 0;
+
+ ilock(&vctllock);
+ if(vctl[vno])
+ v->next = vctl[vno]->next;
+ vctl[vno] = v;
+ iunlock(&vctllock);
+}
+
+static void
+nmienable(void)
+{
+ int x;
+
+ /*
+ * Hack: should be locked with NVRAM access.
+ */
+ outb(0x70, 0x80); /* NMI latch clear */
+ outb(0x70, 0);
+
+ x = inb(0x61) & 0x07; /* Enable NMI */
+ outb(0x61, 0x08|x);
+ 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
+trapinit0(void)
+{
+ int d1, v;
+ ulong vaddr;
+ Segdesc *idt;
+
+ idt = (Segdesc*)IDTADDR;
+ vaddr = (ulong)vectortable;
+ for(v = 0; v < 256; v++){
+ d1 = (vaddr & 0xFFFF0000)|SEGP;
+ switch(v){
+
+ case VectorBPT:
+ d1 |= SEGPL(3)|SEGIG;
+ break;
+
+ case VectorSYSCALL:
+ d1 |= SEGPL(3)|SEGIG;
+ break;
+
+ default:
+ d1 |= SEGPL(0)|SEGIG;
+ break;
+ }
+ idt[v].d0 = (vaddr & 0xFFFF)|(KESEL<<16);
+ idt[v].d1 = d1;
+ vaddr += 6;
+ }
+}
+
+void
+trapinit(void)
+{
+ /*
+ * Special traps.
+ * Syscall() is called directly without going through trap().
+ */
+ trapenable(VectorBPT, debugbpt, 0, "debugpt");
+ trapenable(VectorPF, fault386, 0, "fault386");
+ trapenable(Vector2F, doublefault, 0, "doublefault");
+ trapenable(Vector15, unexpected, 0, "unexpected");
+ nmienable();
+
+ addarchfile("irqalloc", 0444, irqallocread, nil);
+ trapinited = 1;
+}
+
+static char* excname[32] = {
+ "divide error",
+ "debug exception",
+ "nonmaskable interrupt",
+ "breakpoint",
+ "overflow",
+ "bounds check",
+ "invalid opcode",
+ "coprocessor not available",
+ "double fault",
+ "coprocessor segment overrun",
+ "invalid TSS",
+ "segment not present",
+ "stack exception",
+ "general protection violation",
+ "page fault",
+ "15 (reserved)",
+ "coprocessor error",
+ "alignment check",
+ "machine check",
+ "19 (reserved)",
+ "20 (reserved)",
+ "21 (reserved)",
+ "22 (reserved)",
+ "23 (reserved)",
+ "24 (reserved)",
+ "25 (reserved)",
+ "26 (reserved)",
+ "27 (reserved)",
+ "28 (reserved)",
+ "29 (reserved)",
+ "30 (reserved)",
+ "31 (reserved)",
+};
+
+/*
+ * keep histogram of interrupt service times
+ */
+void
+intrtime(Mach*, int vno)
+{
+ ulong diff;
+ ulong x;
+
+ x = perfticks();
+ diff = x - m->perf.intrts;
+ m->perf.intrts = x;
+
+ m->perf.inintr += diff;
+ if(up == nil && m->perf.inidle > diff)
+ m->perf.inidle -= diff;
+
+ diff /= m->cpumhz*100; /* quantum = 100µsec */
+ if(diff >= Ntimevec)
+ diff = Ntimevec-1;
+ intrtimes[vno][diff]++;
+}
+
+/* go to user space */
+void
+kexit(Ureg*)
+{
+ uvlong t;
+ Tos *tos;
+
+ /* precise time accounting, kernel exit */
+ tos = (Tos*)(USTKTOP-sizeof(Tos));
+ cycles(&t);
+ tos->kcycles += t - up->kentry;
+ tos->pcycles = up->pcycles;
+ tos->pid = up->pid;
+}
+
+/*
+ * All traps come here. It is slower to have all traps call trap()
+ * rather than directly vectoring the handler. However, this avoids a
+ * lot of code duplication and possible bugs. The only exception is
+ * VectorSYSCALL.
+ * Trap is called with interrupts disabled via interrupt-gates.
+ */
+void
+trap(Ureg* ureg)
+{
+ int clockintr, i, vno, user;
+ char buf[ERRMAX];
+ 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){
+ up->dbgreg = ureg;
+ cycles(&up->kentry);
+ }
+
+ clockintr = 0;
+
+ vno = ureg->trap;
+ if(ctl = vctl[vno]){
+ if(ctl->isintr){
+ m->intr++;
+ if(vno >= VectorPIC && vno != VectorSYSCALL)
+ m->lastintr = ctl->irq;
+ }
+
+ if(ctl->isr)
+ ctl->isr(vno);
+ for(v = ctl; v != nil; v = v->next){
+ if(v->f)
+ v->f(ureg, v->a);
+ }
+ if(ctl->eoi)
+ ctl->eoi(vno);
+
+ if(ctl->isintr){
+ intrtime(m, vno);
+
+ if(ctl->irq == IrqCLOCK || ctl->irq == IrqTIMER)
+ clockintr = 1;
+
+ if(up && !clockintr)
+ preempted();
+ }
+ }
+ else if(vno < nelem(excname) && user){
+ spllo();
+ sprint(buf, "sys: trap: %s", excname[vno]);
+ postnote(up, 1, buf, NDebug);
+ }
+ else if(vno >= VectorPIC && vno != VectorSYSCALL){
+ /*
+ * An unknown interrupt.
+ * Check for a default IRQ7. This can happen when
+ * the IRQ input goes away before the acknowledge.
+ * In this case, a 'default IRQ7' is generated, but
+ * the corresponding bit in the ISR isn't set.
+ * In fact, just ignore all such interrupts.
+ */
+
+ /* call all interrupt routines, just in case */
+ for(i = VectorPIC; i <= MaxIrqLAPIC; i++){
+ ctl = vctl[i];
+ if(ctl == nil)
+ continue;
+ if(!ctl->isintr)
+ continue;
+ for(v = ctl; v != nil; v = v->next){
+ if(v->f)
+ v->f(ureg, v->a);
+ }
+ /* should we do this? */
+ if(ctl->eoi)
+ ctl->eoi(i);
+ }
+
+ /* clear the interrupt */
+ i8259isr(vno);
+
+ if(0)print("cpu%d: spurious interrupt %d, last %d\n",
+ m->machno, vno, m->lastintr);
+ if(0)if(conf.nmach > 1){
+ for(i = 0; i < 32; i++){
+ if(!(active.machs & (1<<i)))
+ continue;
+ mach = MACHP(i);
+ if(m->machno == mach->machno)
+ continue;
+ print(" cpu%d: last %d",
+ mach->machno, mach->lastintr);
+ }
+ print("\n");
+ }
+ m->spuriousintr++;
+ if(user)
+ kexit(ureg);
+ return;
+ }
+ else{
+ if(vno == VectorNMI){
+ /*
+ * Don't re-enable, it confuses the crash dumps.
+ nmienable();
+ */
+ iprint("cpu%d: PC %#8.8lux\n", m->machno, ureg->pc);
+ while(m->machno != 0)
+ ;
+ }
+ dumpregs(ureg);
+ if(!user){
+ ureg->sp = (ulong)&ureg->sp;
+ _dumpstack(ureg);
+ }
+ if(vno < nelem(excname))
+ panic("%s", excname[vno]);
+ panic("unknown trap/intr: %d", vno);
+ }
+ splhi();
+
+ /* delaysched set because we held a lock or because our quantum ended */
+ if(up && up->delaysched && clockintr){
+ sched();
+ splhi();
+ }
+
+ if(user){
+ if(up->procctl || up->nnote)
+ notify(ureg);
+ kexit(ureg);
+ }
+}
+
+/*
+ * dump registers
+ */
+void
+dumpregs2(Ureg* ureg)
+{
+ if(up)
+ iprint("cpu%d: registers for %s %lud\n",
+ m->machno, up->text, up->pid);
+ else
+ iprint("cpu%d: registers for kernel\n", m->machno);
+ iprint("FLAGS=%luX TRAP=%luX ECODE=%luX PC=%luX",
+ ureg->flags, ureg->trap, ureg->ecode, ureg->pc);
+ iprint(" SS=%4.4luX USP=%luX\n", ureg->ss & 0xFFFF, ureg->usp);
+ iprint(" AX %8.8luX BX %8.8luX CX %8.8luX DX %8.8luX\n",
+ ureg->ax, ureg->bx, ureg->cx, ureg->dx);
+ iprint(" SI %8.8luX DI %8.8luX BP %8.8luX\n",
+ ureg->si, ureg->di, ureg->bp);
+ iprint(" CS %4.4luX DS %4.4luX ES %4.4luX FS %4.4luX GS %4.4luX\n",
+ ureg->cs & 0xFFFF, ureg->ds & 0xFFFF, ureg->es & 0xFFFF,
+ ureg->fs & 0xFFFF, ureg->gs & 0xFFFF);
+}
+
+void
+dumpregs(Ureg* ureg)
+{
+ vlong mca, mct;
+
+ dumpregs2(ureg);
+
+ /*
+ * Processor control registers.
+ * If machine check exception, time stamp counter, page size extensions
+ * or enhanced virtual 8086 mode extensions are supported, there is a
+ * CR4. If there is a CR4 and machine check extensions, read the machine
+ * check address and machine check type registers if RDMSR supported.
+ */
+ iprint(" CR0 %8.8lux CR2 %8.8lux CR3 %8.8lux",
+ getcr0(), getcr2(), getcr3());
+ if(m->cpuiddx & 0x9A){
+ iprint(" CR4 %8.8lux", getcr4());
+ if((m->cpuiddx & 0xA0) == 0xA0){
+ rdmsr(0x00, &mca);
+ rdmsr(0x01, &mct);
+ iprint("\n MCA %8.8llux MCT %8.8llux", mca, mct);
+ }
+ }
+ iprint("\n ur %#p up %#p\n", ureg, up);
+}
+
+
+/*
+ * Fill in enough of Ureg to get a stack trace, and call a function.
+ * Used by debugging interface rdb.
+ */
+void
+callwithureg(void (*fn)(Ureg*))
+{
+ Ureg ureg;
+ ureg.pc = getcallerpc(&fn);
+ ureg.sp = (ulong)&fn;
+ fn(&ureg);
+}
+
+static void
+_dumpstack(Ureg *ureg)
+{
+ uintptr l, v, i, estack;
+ extern ulong etext;
+ int x;
+ char *s;
+
+ if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){
+ iprint("dumpstack disabled\n");
+ return;
+ }
+ iprint("dumpstack\n");
+
+ x = 0;
+ x += iprint("ktrace /kernel/path %.8lux %.8lux <<EOF\n", ureg->pc, ureg->sp);
+ i = 0;
+ if(up
+ && (uintptr)&l >= (uintptr)up->kstack
+ && (uintptr)&l <= (uintptr)up->kstack+KSTACK)
+ estack = (uintptr)up->kstack+KSTACK;
+ else if((uintptr)&l >= (uintptr)m->stack
+ && (uintptr)&l <= (uintptr)m+MACHSIZE)
+ estack = (uintptr)m+MACHSIZE;
+ else
+ return;
+ x += iprint("estackx %p\n", estack);
+
+ for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
+ v = *(uintptr*)l;
+ if((KTZERO < v && v < (uintptr)&etext) || estack-l < 32){
+ /*
+ * Could Pick off general CALL (((uchar*)v)[-5] == 0xE8)
+ * and CALL indirect through AX
+ * (((uchar*)v)[-2] == 0xFF && ((uchar*)v)[-2] == 0xD0),
+ * but this is too clever and misses faulting address.
+ */
+ x += iprint("%.8p=%.8p ", l, v);
+ i++;
+ }
+ if(i == 4){
+ i = 0;
+ x += iprint("\n");
+ }
+ }
+ if(i)
+ iprint("\n");
+ iprint("EOF\n");
+
+ if(ureg->trap != VectorNMI)
+ return;
+
+ i = 0;
+ for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
+ iprint("%.8p ", *(uintptr*)l);
+ if(++i == 8){
+ i = 0;
+ iprint("\n");
+ }
+ }
+ if(i)
+ iprint("\n");
+}
+
+void
+dumpstack(void)
+{
+ callwithureg(_dumpstack);
+}
+
+static void
+debugbpt(Ureg* ureg, void*)
+{
+ char buf[ERRMAX];
+
+ if(up == 0)
+ panic("kernel bpt");
+ /* restore pc to instruction that caused the trap */
+ ureg->pc--;
+ sprint(buf, "sys: breakpoint");
+ postnote(up, 1, buf, NDebug);
+}
+
+static void
+doublefault(Ureg*, void*)
+{
+ panic("double fault");
+}
+
+static void
+unexpected(Ureg* ureg, void*)
+{
+ print("unexpected trap %lud; ignoring\n", ureg->trap);
+}
+
+extern void checkpages(void);
+extern void checkfault(ulong, ulong);
+static void
+fault386(Ureg* ureg, void*)
+{
+ ulong addr;
+ int read, user, n, insyscall;
+ char buf[ERRMAX];
+
+ addr = getcr2();
+ 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("user fault: up=0 pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr);
+
+ insyscall = up->insyscall;
+ up->insyscall = 1;
+ n = fault(addr, read);
+ if(n < 0){
+ if(!user){
+ dumpregs(ureg);
+ panic("fault: 0x%lux", addr);
+ }
+ checkpages();
+ checkfault(addr, ureg->pc);
+ sprint(buf, "sys: trap: fault %s addr=0x%lux",
+ read ? "read" : "write", addr);
+ postnote(up, 1, buf, NDebug);
+ }
+ up->insyscall = insyscall;
+}
+
+/*
+ * system calls
+ */
+#include "../port/systab.h"
+
+/*
+ * Syscall is called directly from assembler without going through trap().
+ */
+void
+syscall(Ureg* ureg)
+{
+ char *e;
+ ulong sp;
+ long ret;
+ int i, s;
+ ulong scallnr;
+ vlong startns, stopns;
+
+ if((ureg->cs & 0xFFFF) != UESEL)
+ panic("syscall: cs 0x%4.4luX", ureg->cs);
+
+ cycles(&up->kentry);
+
+ m->syscall++;
+ up->insyscall = 1;
+ up->pc = ureg->pc;
+ up->dbgreg = ureg;
+
+ sp = ureg->usp;
+ scallnr = ureg->ax;
+ up->scallnr = scallnr;
+
+ if(up->procctl == Proc_tracesyscall){
+ /*
+ * Redundant validaddr. Do we care?
+ * Tracing syscalls is not exactly a fast path...
+ * Beware, validaddr currently does a pexit rather
+ * than an error if there's a problem; that might
+ * change in the future.
+ */
+ if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)-BY2WD))
+ validaddr(sp, sizeof(Sargs)+BY2WD, 0);
+
+ syscallfmt(scallnr, ureg->pc, (va_list)(sp+BY2WD));
+ up->procctl = Proc_stopme;
+ procctl(up);
+ if(up->syscalltrace)
+ free(up->syscalltrace);
+ up->syscalltrace = nil;
+ startns = todget(nil);
+ }
+
+ if(scallnr == RFORK && up->fpstate == FPactive){
+ fpsave(&up->fpsave);
+ up->fpstate = FPinactive;
+ }
+ spllo();
+
+ up->nerrlab = 0;
+ ret = -1;
+ if(!waserror()){
+ if(scallnr >= nsyscall || systab[scallnr] == 0){
+ pprint("bad sys call number %lud pc %lux\n",
+ scallnr, ureg->pc);
+ postnote(up, 1, "sys: bad sys call", NDebug);
+ error(Ebadarg);
+ }
+
+ if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
+ validaddr(sp, sizeof(Sargs)+BY2WD, 0);
+
+ up->s = *((Sargs*)(sp+BY2WD));
+ up->psstate = sysctab[scallnr];
+
+ ret = systab[scallnr](up->s.args);
+ poperror();
+ }else{
+ /* failure: save the error buffer for errstr */
+ e = up->syserrstr;
+ up->syserrstr = up->errstr;
+ up->errstr = e;
+ if(0 && up->pid == 1)
+ print("syscall %lud error %s\n", scallnr, up->syserrstr);
+ }
+ if(up->nerrlab){
+ print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
+ for(i = 0; i < NERR; i++)
+ print("sp=%lux pc=%lux\n",
+ up->errlab[i].sp, up->errlab[i].pc);
+ panic("error stack");
+ }
+
+ /*
+ * Put return value in frame. On the x86 the syscall is
+ * just another trap and the return value from syscall is
+ * ignored. On other machines the return value is put into
+ * the results register by caller of syscall.
+ */
+ ureg->ax = ret;
+
+ if(up->procctl == Proc_tracesyscall){
+ stopns = todget(nil);
+ up->procctl = Proc_stopme;
+ sysretfmt(scallnr, (va_list)(sp+BY2WD), ret, startns, stopns);
+ s = splhi();
+ procctl(up);
+ splx(s);
+ if(up->syscalltrace)
+ free(up->syscalltrace);
+ up->syscalltrace = nil;
+ }
+
+ up->insyscall = 0;
+ up->psstate = 0;
+
+ if(scallnr == NOTED)
+ noted(ureg, *(ulong*)(sp+BY2WD));
+
+ if(scallnr!=RFORK && (up->procctl || up->nnote)){
+ splhi();
+ notify(ureg);
+ }
+ /* if we delayed sched because we held a lock, sched now */
+ if(up->delaysched)
+ sched();
+ kexit(ureg);
+}
+
+/*
+ * Call user, if necessary, with note.
+ * Pass user the Ureg struct and the note on his stack.
+ */
+int
+notify(Ureg* ureg)
+{
+ int l;
+ ulong s, sp;
+ Note *n;
+
+ if(up->procctl)
+ procctl(up);
+ if(up->nnote == 0)
+ return 0;
+
+ if(up->fpstate == FPactive){
+ fpsave(&up->fpsave);
+ up->fpstate = FPinactive;
+ }
+ up->fpstate |= FPillegal;
+
+ s = spllo();
+ qlock(&up->debug);
+ up->notepending = 0;
+ n = &up->note[0];
+ if(strncmp(n->msg, "sys:", 4) == 0){
+ l = strlen(n->msg);
+ if(l > ERRMAX-15) /* " pc=0x12345678\0" */
+ l = ERRMAX-15;
+ sprint(n->msg+l, " pc=0x%.8lux", ureg->pc);
+ }
+
+ if(n->flag!=NUser && (up->notified || up->notify==0)){
+ if(n->flag == NDebug)
+ pprint("suicide: %s\n", n->msg);
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag!=NDebug);
+ }
+
+ if(up->notified){
+ qunlock(&up->debug);
+ splhi();
+ return 0;
+ }
+
+ if(!up->notify){
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag!=NDebug);
+ }
+ sp = ureg->usp;
+ sp -= 256; /* debugging: preserve context causing problem */
+ sp -= sizeof(Ureg);
+if(0) print("%s %lud: notify %.8lux %.8lux %.8lux %s\n",
+ up->text, up->pid, ureg->pc, ureg->usp, sp, n->msg);
+
+ if(!okaddr((ulong)up->notify, 1, 0)
+ || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)){
+ qunlock(&up->debug);
+ pprint("suicide: bad address in notify\n");
+ pexit("Suicide", 0);
+ }
+
+ memmove((Ureg*)sp, ureg, sizeof(Ureg));
+ *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
+ up->ureg = (void*)sp;
+ sp -= BY2WD+ERRMAX;
+ memmove((char*)sp, up->note[0].msg, ERRMAX);
+ sp -= 3*BY2WD;
+ *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */
+ *(ulong*)(sp+1*BY2WD) = (ulong)up->ureg; /* arg 1 is ureg* */
+ *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
+ ureg->usp = sp;
+ ureg->pc = (ulong)up->notify;
+ up->notified = 1;
+ up->nnote--;
+ memmove(&up->lastnote, &up->note[0], sizeof(Note));
+ memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
+
+ qunlock(&up->debug);
+ splx(s);
+ return 1;
+}
+
+/*
+ * Return user to state before notify()
+ */
+void
+noted(Ureg* ureg, ulong arg0)
+{
+ Ureg *nureg;
+ ulong oureg, sp;
+
+ qlock(&up->debug);
+ if(arg0!=NRSTR && !up->notified) {
+ qunlock(&up->debug);
+ pprint("call to noted() when not notified\n");
+ pexit("Suicide", 0);
+ }
+ up->notified = 0;
+
+ nureg = up->ureg; /* pointer to user returned Ureg struct */
+
+ up->fpstate &= ~FPillegal;
+
+ /* sanity clause */
+ oureg = (ulong)nureg;
+ if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
+ qunlock(&up->debug);
+ pprint("bad ureg in noted or call to noted when not notified\n");
+ pexit("Suicide", 0);
+ }
+
+ /*
+ * Check the segment selectors are all valid, otherwise
+ * a fault will be taken on attempting to return to the
+ * user process.
+ * Take care with the comparisons as different processor
+ * generations push segment descriptors in different ways.
+ */
+ if((nureg->cs & 0xFFFF) != UESEL || (nureg->ss & 0xFFFF) != UDSEL
+ || (nureg->ds & 0xFFFF) != UDSEL || (nureg->es & 0xFFFF) != UDSEL
+ || (nureg->fs & 0xFFFF) != UDSEL || (nureg->gs & 0xFFFF) != UDSEL){
+ qunlock(&up->debug);
+ pprint("bad segment selector in noted\n");
+ pexit("Suicide", 0);
+ }
+
+ /* don't let user change system flags */
+ nureg->flags = (ureg->flags & ~0xCD5) | (nureg->flags & 0xCD5);
+
+ memmove(ureg, nureg, sizeof(Ureg));
+
+ switch(arg0){
+ case NCONT:
+ case NRSTR:
+if(0) print("%s %lud: noted %.8lux %.8lux\n",
+ up->text, up->pid, nureg->pc, nureg->usp);
+ if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->usp, BY2WD, 0)){
+ qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
+ pexit("Suicide", 0);
+ }
+ up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
+ qunlock(&up->debug);
+ break;
+
+ case NSAVE:
+ if(!okaddr(nureg->pc, BY2WD, 0)
+ || !okaddr(nureg->usp, BY2WD, 0)){
+ qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
+ pexit("Suicide", 0);
+ }
+ qunlock(&up->debug);
+ sp = oureg-4*BY2WD-ERRMAX;
+ splhi();
+ ureg->sp = sp;
+ ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
+ ((ulong*)sp)[0] = 0; /* arg 0 is pc */
+ break;
+
+ default:
+ pprint("unknown noted arg 0x%lux\n", arg0);
+ up->lastnote.flag = NDebug;
+ /* fall through */
+
+ case NDFLT:
+ if(up->lastnote.flag == NDebug){
+ qunlock(&up->debug);
+ pprint("suicide: %s\n", up->lastnote.msg);
+ } else
+ qunlock(&up->debug);
+ pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
+ }
+}
+
+long
+execregs(ulong entry, ulong ssize, ulong nargs)
+{
+ ulong *sp;
+ Ureg *ureg;
+
+ up->fpstate = FPinit;
+ fpoff();
+
+ sp = (ulong*)(USTKTOP - ssize);
+ *--sp = nargs;
+
+ ureg = up->dbgreg;
+ ureg->usp = (ulong)sp;
+ ureg->pc = entry;
+ return USTKTOP-sizeof(Tos); /* address of kernel/user shared data */
+}
+
+/*
+ * return the userpc the last exception happened at
+ */
+ulong
+userpc(void)
+{
+ Ureg *ureg;
+
+ ureg = (Ureg*)up->dbgreg;
+ return ureg->pc;
+}
+
+/* This routine must save the values of registers the user is not permitted
+ * to write from devproc and then restore the saved values before returning.
+ */
+void
+setregisters(Ureg* ureg, char* pureg, char* uva, int n)
+{
+ ulong cs, ds, es, flags, fs, gs, ss;
+
+ ss = ureg->ss;
+ flags = ureg->flags;
+ cs = ureg->cs;
+ ds = ureg->ds;
+ es = ureg->es;
+ fs = ureg->fs;
+ gs = ureg->gs;
+ memmove(pureg, uva, n);
+ ureg->gs = gs;
+ ureg->fs = fs;
+ ureg->es = es;
+ ureg->ds = ds;
+ ureg->cs = cs;
+ ureg->flags = (ureg->flags & 0x00FF) | (flags & 0xFF00);
+ ureg->ss = ss;
+}
+
+static void
+linkproc(void)
+{
+ spllo();
+ up->kpfun(up->kparg);
+ pexit("kproc dying", 0);
+}
+
+void
+kprocchild(Proc* p, void (*func)(void*), void* arg)
+{
+ /*
+ * gotolabel() needs a word on the stack in
+ * which to place the return PC used to jump
+ * to linkproc().
+ */
+ p->sched.pc = (ulong)linkproc;
+ p->sched.sp = (ulong)p->kstack+KSTACK-BY2WD;
+
+ p->kpfun = func;
+ p->kparg = arg;
+}
+
+void
+forkchild(Proc *p, Ureg *ureg)
+{
+ Ureg *cureg;
+
+ /*
+ * Add 2*BY2WD to the stack to account for
+ * - the return PC
+ * - trap's argument (ur)
+ */
+ p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Ureg)+2*BY2WD);
+ p->sched.pc = (ulong)forkret;
+
+ cureg = (Ureg*)(p->sched.sp+2*BY2WD);
+ memmove(cureg, ureg, sizeof(Ureg));
+ /* return value of syscall in child */
+ cureg->ax = 0;
+
+ /* Things from bottom of syscall which were never executed */
+ p->psstate = 0;
+ p->insyscall = 0;
+}
+
+/* Give enough context in the ureg to produce a kernel stack for
+ * a sleeping process
+ */
+void
+setkernur(Ureg* ureg, Proc* p)
+{
+ ureg->pc = p->sched.pc;
+ ureg->sp = p->sched.sp+4;
+}
+
+ulong
+dbgpc(Proc *p)
+{
+ Ureg *ureg;
+
+ ureg = p->dbgreg;
+ if(ureg == 0)
+ return 0;
+
+ return ureg->pc;
+}
diff --git a/sys/src/9/pc/uartaxp.c b/sys/src/9/pc/uartaxp.c
new file mode 100755
index 000000000..af928a1e2
--- /dev/null
+++ b/sys/src/9/pc/uartaxp.c
@@ -0,0 +1,951 @@
+/*
+ * Avanstar Xp pci uart driver
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#include "uartaxp.i"
+
+typedef struct Cc Cc;
+typedef struct Ccb Ccb;
+typedef struct Ctlr Ctlr;
+typedef struct Gcb Gcb;
+
+/*
+ * Global Control Block.
+ * Service Request fields must be accessed using XCHG.
+ */
+struct Gcb {
+ u16int gcw; /* Global Command Word */
+ u16int gsw; /* Global Status Word */
+ u16int gsr; /* Global Service Request */
+ u16int abs; /* Available Buffer Space */
+ u16int bt; /* Board Type */
+ u16int cpv; /* Control Program Version */
+ u16int ccbn; /* Ccb count */
+ u16int ccboff; /* Ccb offset */
+ u16int ccbsz; /* Ccb size */
+ u16int gcw2; /* Global Command Word 2 */
+ u16int gsw2; /* Global Status Word 2 */
+ u16int esr; /* Error Service Request */
+ u16int isr; /* Input Service Request */
+ u16int osr; /* Output Service Request */
+ u16int msr; /* Modem Service Request */
+ u16int csr; /* Command Service Request */
+};
+
+/*
+ * Channel Control Block.
+ */
+struct Ccb {
+ u16int br; /* Baud Rate */
+ u16int df; /* Data Format */
+ u16int lp; /* Line Protocol */
+ u16int ibs; /* Input Buffer Size */
+ u16int obs; /* Output Buffer Size */
+ u16int ibtr; /* Ib Trigger Rate */
+ u16int oblw; /* Ob Low Watermark */
+ u8int ixon[2]; /* IXON characters */
+ u16int ibhw; /* Ib High Watermark */
+ u16int iblw; /* Ib Low Watermark */
+ u16int cc; /* Channel Command */
+ u16int cs; /* Channel Status */
+ u16int ibsa; /* Ib Start Addr */
+ u16int ibea; /* Ib Ending Addr */
+ u16int obsa; /* Ob Start Addr */
+ u16int obea; /* Ob Ending Addr */
+ u16int ibwp; /* Ib write pointer (RO) */
+ u16int ibrp; /* Ib read pointer (R/W) */
+ u16int obwp; /* Ob write pointer (R/W) */
+ u16int obrp; /* Ob read pointer (RO) */
+ u16int ces; /* Communication Error Status */
+ u16int bcp; /* Bad Character Pointer */
+ u16int mc; /* Modem Control */
+ u16int ms; /* Modem Status */
+ u16int bs; /* Blocking Status */
+ u16int crf; /* Character Received Flag */
+ u8int ixoff[2]; /* IXOFF characters */
+ u16int cs2; /* Channel Status 2 */
+ u8int sec[2]; /* Strip/Error Characters */
+};
+
+enum { /* br */
+ Br76800 = 0xFF00,
+ Br115200 = 0xFF01,
+};
+
+enum { /* df */
+ Db5 = 0x0000, /* Data Bits - 5 bits/byte */
+ Db6 = 0x0001, /* 6 bits/byte */
+ Db7 = 0x0002, /* 7 bits/byte */
+ Db8 = 0x0003, /* 8 bits/byte */
+ DbMASK = 0x0003,
+ Sb1 = 0x0000, /* 1 Stop Bit */
+ Sb2 = 0x0004, /* 2 Stop Bit */
+ SbMASK = 0x0004,
+ Np = 0x0000, /* No Parity */
+ Op = 0x0008, /* Odd Parity */
+ Ep = 0x0010, /* Even Parity */
+ Mp = 0x0020, /* Mark Parity */
+ Sp = 0x0030, /* Space Parity */
+ PMASK = 0x0038,
+ Cmn = 0x0000, /* Channel Mode Normal */
+ Cme = 0x0040, /* CM Echo */
+ Cmll = 0x0080, /* CM Local Loopback */
+ Cmrl = 0x00C0, /* CM Remote Loopback */
+};
+
+enum { /* lp */
+ Ixon = 0x0001, /* Obey IXON/IXOFF */
+ Ixany = 0x0002, /* Any character retarts Tx */
+ Ixgen = 0x0004, /* Generate IXON/IXOFF */
+ Cts = 0x0008, /* CTS controls Tx */
+ Dtr = 0x0010, /* Rx controls DTR */
+ ½d = 0x0020, /* RTS off during Tx */
+ Rts = 0x0040, /* generate RTS */
+ Emcs = 0x0080, /* Enable Modem Control */
+ Ecs = 0x1000, /* Enable Character Stripping */
+ Eia422 = 0x2000, /* EIA422 */
+};
+
+enum { /* cc */
+ Ccu = 0x0001, /* Configure Channel and UART */
+ Cco = 0x0002, /* Configure Channel Only */
+ Fib = 0x0004, /* Flush Input Buffer */
+ Fob = 0x0008, /* Flush Output Buffer */
+ Er = 0x0010, /* Enable Receiver */
+ Dr = 0x0020, /* Disable Receiver */
+ Et = 0x0040, /* Enable Transmitter */
+ Dt = 0x0080, /* Disable Transmitter */
+};
+
+enum { /* ces */
+ Oe = 0x0001, /* Overrun Error */
+ Pe = 0x0002, /* Parity Error */
+ Fe = 0x0004, /* Framing Error */
+ Br = 0x0008, /* Break Received */
+};
+
+enum { /* mc */
+ Adtr = 0x0001, /* Assert DTR */
+ Arts = 0x0002, /* Assert RTS */
+ Ab = 0x0010, /* Assert BREAK */
+};
+
+enum { /* ms */
+ Scts = 0x0001, /* Status od CTS */
+ Sdsr = 0x0002, /* Status of DSR */
+ Sri = 0x0004, /* Status of RI */
+ Sdcd = 0x0008, /* Status of DCD */
+};
+
+enum { /* bs */
+ Rd = 0x0001, /* Receiver Disabled */
+ Td = 0x0002, /* Transmitter Disabled */
+ Tbxoff = 0x0004, /* Tx Blocked by XOFF */
+ Tbcts = 0x0008, /* Tx Blocked by CTS */
+ Rbxoff = 0x0010, /* Rx Blocked by XOFF */
+ Rbrts = 0x0020, /* Rx Blocked by RTS */
+};
+
+enum { /* Local Configuration */
+ Range = 0x00,
+ Remap = 0x04,
+ Region = 0x18,
+ Mb0 = 0x40, /* Mailbox 0 */
+ Ldb = 0x60, /* PCI to Local Doorbell */
+ Pdb = 0x64, /* Local to PCI Doorbell */
+ Ics = 0x68, /* Interrupt Control/Status */
+ Mcc = 0x6C, /* Misc. Command and Control */
+};
+
+enum { /* Mb0 */
+ Edcc = 1, /* exec. downloaded code cmd */
+ Aic = 0x10, /* adapter init'zed correctly */
+ Cpr = 1ul << 31, /* control program ready */
+};
+
+enum { /* Mcc */
+ Rcr = 1ul << 29, /* reload config. reg.s */
+ Asr = 1ul << 30, /* pci adapter sw reset */
+ Lis = 1ul << 31, /* local init status */
+};
+
+typedef struct Cc Cc;
+typedef struct Ccb Ccb;
+typedef struct Ctlr Ctlr;
+
+/*
+ * Channel Control, one per uart.
+ * Devuart communicates via the PhysUart functions with
+ * a Uart* argument. Uart.regs is filled in by this driver
+ * to point to a Cc, and Cc.ctlr points to the Axp board
+ * controller.
+ */
+struct Cc {
+ int uartno;
+ Ccb* ccb;
+ Ctlr* ctlr;
+
+ Rendez;
+
+ Uart;
+};
+
+typedef struct Ctlr {
+ char* name;
+ Pcidev* pcidev;
+ int ctlrno;
+ Ctlr* next;
+
+ u32int* reg;
+ uchar* mem;
+ Gcb* gcb;
+
+ int im; /* interrupt mask */
+ Cc cc[16];
+} Ctlr;
+
+#define csr32r(c, r) (*((c)->reg+((r)/4)))
+#define csr32w(c, r, v) (*((c)->reg+((r)/4)) = (v))
+
+static Ctlr* axpctlrhead;
+static Ctlr* axpctlrtail;
+
+extern PhysUart axpphysuart;
+
+static int
+axpccdone(void* ccb)
+{
+ return !((Ccb*)ccb)->cc; /* hw sets ccb->cc to zero */
+}
+
+static void
+axpcc(Cc* cc, int cmd)
+{
+ Ccb *ccb;
+ int timeo;
+ u16int cs;
+
+ ccb = cc->ccb;
+ ccb->cc = cmd;
+
+ if(!cc->ctlr->im)
+ for(timeo = 0; timeo < 1000000; timeo++){
+ if(!ccb->cc)
+ break;
+ microdelay(1);
+ }
+ else
+ tsleep(cc, axpccdone, ccb, 1000);
+
+ cs = ccb->cs;
+ if(ccb->cc || cs){
+ print("%s: cmd %#ux didn't terminate: %#ux %#ux\n",
+ cc->name, cmd, ccb->cc, cs);
+ if(cc->ctlr->im)
+ error(Eio);
+ }
+}
+
+static long
+axpstatus(Uart* uart, void* buf, long n, long offset)
+{
+ char *p;
+ Ccb *ccb;
+ u16int bs, fstat, ms;
+
+ ccb = ((Cc*)(uart->regs))->ccb;
+
+ p = malloc(READSTR);
+ bs = ccb->bs;
+ fstat = ccb->df;
+ ms = ccb->ms;
+
+ snprint(p, READSTR,
+ "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
+ "dev(%d) type(%d) framing(%d) overruns(%d) "
+ "berr(%d) serr(%d)%s%s%s%s\n",
+
+ uart->baud,
+ uart->hup_dcd,
+ ms & Sdsr,
+ uart->hup_dsr,
+ (fstat & DbMASK) + 5,
+ 0,
+ (fstat & PMASK) ? ((fstat & Ep) == Ep? 'e': 'o'): 'n',
+ (bs & Rbrts) ? 1 : 0,
+ (fstat & Sb2) ? 2 : 1,
+ 0,
+
+ uart->dev,
+ uart->type,
+ uart->ferr,
+ uart->oerr,
+ uart->berr,
+ uart->serr,
+ (ms & Scts) ? " cts" : "",
+ (ms & Sdsr) ? " dsr" : "",
+ (ms & Sdcd) ? " dcd" : "",
+ (ms & Sri) ? " ring" : ""
+ );
+ n = readstr(offset, buf, n, p);
+ free(p);
+
+ return n;
+}
+
+static void
+axpfifo(Uart*, int)
+{
+}
+
+static void
+axpdtr(Uart* uart, int on)
+{
+ Ccb *ccb;
+ u16int mc;
+
+ ccb = ((Cc*)(uart->regs))->ccb;
+
+ mc = ccb->mc;
+ if(on)
+ mc |= Adtr;
+ else
+ mc &= ~Adtr;
+ ccb->mc = mc;
+}
+
+/*
+ * can be called from uartstageinput() during an input interrupt,
+ * with uart->rlock ilocked or the uart qlocked, sometimes both.
+ */
+static void
+axprts(Uart* uart, int on)
+{
+ Ccb *ccb;
+ u16int mc;
+
+ ccb = ((Cc*)(uart->regs))->ccb;
+
+ mc = ccb->mc;
+ if(on)
+ mc |= Arts;
+ else
+ mc &= ~Arts;
+ ccb->mc = mc;
+}
+
+static void
+axpmodemctl(Uart* uart, int on)
+{
+ Ccb *ccb;
+ u16int lp;
+
+ ccb = ((Cc*)(uart->regs))->ccb;
+
+ ilock(&uart->tlock);
+ lp = ccb->lp;
+ if(on){
+ lp |= Cts|Rts;
+ lp &= ~Emcs;
+ uart->cts = ccb->ms & Scts;
+ }
+ else{
+ lp &= ~(Cts|Rts);
+ lp |= Emcs;
+ uart->cts = 1;
+ }
+ uart->modem = on;
+ iunlock(&uart->tlock);
+
+ ccb->lp = lp;
+ axpcc(uart->regs, Ccu);
+}
+
+static int
+axpparity(Uart* uart, int parity)
+{
+ Ccb *ccb;
+ u16int df;
+
+ switch(parity){
+ default:
+ return -1;
+ case 'e':
+ parity = Ep;
+ break;
+ case 'o':
+ parity = Op;
+ break;
+ case 'n':
+ parity = Np;
+ break;
+ }
+
+ ccb = ((Cc*)(uart->regs))->ccb;
+
+ df = ccb->df & ~PMASK;
+ ccb->df = df|parity;
+ axpcc(uart->regs, Ccu);
+
+ return 0;
+}
+
+static int
+axpstop(Uart* uart, int stop)
+{
+ Ccb *ccb;
+ u16int df;
+
+ switch(stop){
+ default:
+ return -1;
+ case 1:
+ stop = Sb1;
+ break;
+ case 2:
+ stop = Sb2;
+ break;
+ }
+
+ ccb = ((Cc*)(uart->regs))->ccb;
+
+ df = ccb->df & ~SbMASK;
+ ccb->df = df|stop;
+ axpcc(uart->regs, Ccu);
+
+ return 0;
+}
+
+static int
+axpbits(Uart* uart, int bits)
+{
+ Ccb *ccb;
+ u16int df;
+
+ bits -= 5;
+ if(bits < 0 || bits > 3)
+ return -1;
+
+ ccb = ((Cc*)(uart->regs))->ccb;
+
+ df = ccb->df & ~DbMASK;
+ ccb->df = df|bits;
+ axpcc(uart->regs, Ccu);
+
+ return 0;
+}
+
+static int
+axpbaud(Uart* uart, int baud)
+{
+ Ccb *ccb;
+ int i, ibtr;
+
+ /*
+ * Set baud rate (high rates are special - only 16 bits).
+ */
+ if(baud <= 0)
+ return -1;
+ uart->baud = baud;
+
+ ccb = ((Cc*)(uart->regs))->ccb;
+
+ switch(baud){
+ default:
+ ccb->br = baud;
+ break;
+ case 76800:
+ ccb->br = Br76800;
+ break;
+ case 115200:
+ ccb->br = Br115200;
+ break;
+ }
+
+ /*
+ * Set trigger level to about 50 per second.
+ */
+ ibtr = baud/500;
+ i = (ccb->ibea - ccb->ibsa)/2;
+ if(ibtr > i)
+ ibtr = i;
+ ccb->ibtr = ibtr;
+ axpcc(uart->regs, Ccu);
+
+ return 0;
+}
+
+static void
+axpbreak(Uart* uart, int ms)
+{
+ Ccb *ccb;
+ u16int mc;
+
+ /*
+ * Send a break.
+ */
+ if(ms <= 0)
+ ms = 200;
+
+ ccb = ((Cc*)(uart->regs))->ccb;
+
+ mc = ccb->mc;
+ ccb->mc = Ab|mc;
+ tsleep(&up->sleep, return0, 0, ms);
+ ccb->mc = mc & ~Ab;
+}
+
+/* only called from interrupt service */
+static void
+axpmc(Cc* cc)
+{
+ int old;
+ Ccb *ccb;
+ u16int ms;
+
+ ccb = cc->ccb;
+
+ ms = ccb->ms;
+
+ if(ms & Scts){
+ ilock(&cc->tlock);
+ old = cc->cts;
+ cc->cts = ms & Scts;
+ if(old == 0 && cc->cts)
+ cc->ctsbackoff = 2;
+ iunlock(&cc->tlock);
+ }
+ if(ms & Sdsr){
+ old = ms & Sdsr;
+ if(cc->hup_dsr && cc->dsr && !old)
+ cc->dohup = 1;
+ cc->dsr = old;
+ }
+ if(ms & Sdcd){
+ old = ms & Sdcd;
+ if(cc->hup_dcd && cc->dcd && !old)
+ cc->dohup = 1;
+ cc->dcd = old;
+ }
+}
+
+/* called from uartkick() with uart->tlock ilocked */
+static void
+axpkick(Uart* uart)
+{
+ Cc *cc;
+ Ccb *ccb;
+ uchar *ep, *mem, *rp, *wp, *bp;
+
+ if(uart->cts == 0 || uart->blocked)
+ return;
+
+ cc = uart->regs;
+ ccb = cc->ccb;
+
+ mem = (uchar*)cc->ctlr->gcb;
+ bp = mem + ccb->obsa;
+ rp = mem + ccb->obrp;
+ wp = mem + ccb->obwp;
+ ep = mem + ccb->obea;
+ while(wp != rp-1 && (rp != bp || wp != ep)){
+ /*
+ * if we've exhausted the uart's output buffer,
+ * ask for more from the output queue, and quit if there
+ * isn't any.
+ */
+ if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
+ break;
+ *wp++ = *(uart->op++);
+ if(wp > ep)
+ wp = bp;
+ ccb->obwp = wp - mem;
+ }
+}
+
+/* only called from interrupt service */
+static void
+axprecv(Cc* cc)
+{
+ Ccb *ccb;
+ uchar *ep, *mem, *rp, *wp;
+
+ ccb = cc->ccb;
+
+ mem = (uchar*)cc->ctlr->gcb;
+ rp = mem + ccb->ibrp;
+ wp = mem + ccb->ibwp;
+ ep = mem + ccb->ibea;
+
+ while(rp != wp){
+ uartrecv(cc, *rp++); /* ilocks cc->tlock */
+ if(rp > ep)
+ rp = mem + ccb->ibsa;
+ ccb->ibrp = rp - mem;
+ }
+}
+
+static void
+axpinterrupt(Ureg*, void* arg)
+{
+ int work;
+ Cc *cc;
+ Ctlr *ctlr;
+ u32int ics;
+ u16int r, sr;
+
+ work = 0;
+ ctlr = arg;
+ ics = csr32r(ctlr, Ics);
+ if(ics & 0x0810C000)
+ print("%s: unexpected interrupt %#ux\n", ctlr->name, ics);
+ if(!(ics & 0x00002000)) {
+ /* we get a steady stream of these on consoles */
+ // print("%s: non-doorbell interrupt\n", ctlr->name);
+ ctlr->gcb->gcw2 = 0x0001; /* set Gintack */
+ return;
+ }
+
+// while(work to do){
+ cc = ctlr->cc;
+ for(sr = xchgw(&ctlr->gcb->isr, 0); sr != 0; sr >>= 1){
+ if(sr & 0x0001)
+ work++, axprecv(cc);
+ cc++;
+ }
+ cc = ctlr->cc;
+ for(sr = xchgw(&ctlr->gcb->osr, 0); sr != 0; sr >>= 1){
+ if(sr & 0x0001)
+ work++, uartkick(&cc->Uart);
+ cc++;
+ }
+ cc = ctlr->cc;
+ for(sr = xchgw(&ctlr->gcb->csr, 0); sr != 0; sr >>= 1){
+ if(sr & 0x0001)
+ work++, wakeup(cc);
+ cc++;
+ }
+ cc = ctlr->cc;
+ for(sr = xchgw(&ctlr->gcb->msr, 0); sr != 0; sr >>= 1){
+ if(sr & 0x0001)
+ work++, axpmc(cc);
+ cc++;
+ }
+ cc = ctlr->cc;
+ for(sr = xchgw(&ctlr->gcb->esr, 0); sr != 0; sr >>= 1){
+ if(sr & 0x0001){
+ r = cc->ccb->ms;
+ if(r & Oe)
+ cc->oerr++;
+ if(r & Pe)
+ cc->perr++;
+ if(r & Fe)
+ cc->ferr++;
+ if (r & (Oe|Pe|Fe))
+ work++;
+ }
+ cc++;
+ }
+// }
+ /* only meaningful if we don't share the irq */
+ if (0 && !work)
+ print("%s: interrupt with no work\n", ctlr->name);
+ csr32w(ctlr, Pdb, 1); /* clear doorbell interrupt */
+ ctlr->gcb->gcw2 = 0x0001; /* set Gintack */
+}
+
+static void
+axpdisable(Uart* uart)
+{
+ Cc *cc;
+ u16int lp;
+ Ctlr *ctlr;
+
+ /*
+ * Turn off DTR and RTS, disable interrupts.
+ */
+ (*uart->phys->dtr)(uart, 0);
+ (*uart->phys->rts)(uart, 0);
+
+ cc = uart->regs;
+ lp = cc->ccb->lp;
+ cc->ccb->lp = Emcs|lp;
+ axpcc(cc, Dt|Dr|Fob|Fib|Ccu);
+
+ /*
+ * The Uart is qlocked.
+ */
+ ctlr = cc->ctlr;
+ ctlr->im &= ~(1<<cc->uartno);
+ if(ctlr->im == 0)
+ intrdisable(ctlr->pcidev->intl, axpinterrupt, ctlr,
+ ctlr->pcidev->tbdf, ctlr->name);
+}
+
+static void
+axpenable(Uart* uart, int ie)
+{
+ Cc *cc;
+ Ctlr *ctlr;
+ u16int lp;
+
+ cc = uart->regs;
+ ctlr = cc->ctlr;
+
+ /*
+ * Enable interrupts and turn on DTR and RTS.
+ * Be careful if this is called to set up a polled serial line
+ * early on not to try to enable interrupts as interrupt-
+ * -enabling mechanisms might not be set up yet.
+ */
+ if(ie){
+ /*
+ * The Uart is qlocked.
+ */
+ if(ctlr->im == 0){
+ intrenable(ctlr->pcidev->intl, axpinterrupt, ctlr,
+ ctlr->pcidev->tbdf, ctlr->name);
+ csr32w(ctlr, Ics, 0x00031F00);
+ csr32w(ctlr, Pdb, 1);
+ ctlr->gcb->gcw2 = 1;
+ }
+ ctlr->im |= 1<<cc->uartno;
+ }
+
+ (*uart->phys->dtr)(uart, 1);
+ (*uart->phys->rts)(uart, 1);
+
+ /*
+ * Make sure we control RTS, DTR and break.
+ */
+ lp = cc->ccb->lp;
+ cc->ccb->lp = Emcs|lp;
+ cc->ccb->oblw = 64;
+ axpcc(cc, Et|Er|Ccu);
+}
+
+static void*
+axpdealloc(Ctlr* ctlr)
+{
+ int i;
+
+ for(i = 0; i < 16; i++){
+ if(ctlr->cc[i].name != nil)
+ free(ctlr->cc[i].name);
+ }
+ if(ctlr->reg != nil)
+ vunmap(ctlr->reg, ctlr->pcidev->mem[0].size);
+ if(ctlr->mem != nil)
+ vunmap(ctlr->mem, ctlr->pcidev->mem[2].size);
+ if(ctlr->name != nil)
+ free(ctlr->name);
+ free(ctlr);
+
+ return nil;
+}
+
+static Uart*
+axpalloc(int ctlrno, Pcidev* pcidev)
+{
+ Cc *cc;
+ uchar *p;
+ Ctlr *ctlr;
+ void *addr;
+ char name[64];
+ u32int bar, r;
+ int i, n, timeo;
+
+ ctlr = malloc(sizeof(Ctlr));
+ seprint(name, name+sizeof(name), "uartaxp%d", ctlrno);
+ kstrdup(&ctlr->name, name);
+ ctlr->pcidev = pcidev;
+ ctlr->ctlrno = ctlrno;
+
+ /*
+ * Access to runtime registers.
+ */
+ bar = pcidev->mem[0].bar;
+ if((addr = vmap(bar & ~0x0F, pcidev->mem[0].size)) == 0){
+ print("%s: can't map registers at %#ux\n", ctlr->name, bar);
+ return axpdealloc(ctlr);
+ }
+ ctlr->reg = addr;
+ print("%s: port 0x%ux irq %d ", ctlr->name, bar, pcidev->intl);
+
+ /*
+ * Local address space 0.
+ */
+ bar = pcidev->mem[2].bar;
+ if((addr = vmap(bar & ~0x0F, pcidev->mem[2].size)) == 0){
+ print("%s: can't map memory at %#ux\n", ctlr->name, bar);
+ return axpdealloc(ctlr);
+ }
+ ctlr->mem = addr;
+ ctlr->gcb = (Gcb*)(ctlr->mem+0x10000);
+ print("mem 0x%ux size %d: ", bar, pcidev->mem[2].size);
+
+ /*
+ * Toggle the software reset and wait for
+ * the adapter local init status to indicate done.
+ *
+ * The two 'delay(100)'s below are important,
+ * without them the board seems to become confused
+ * (perhaps it needs some 'quiet time' because the
+ * timeout loops are not sufficient in themselves).
+ */
+ r = csr32r(ctlr, Mcc);
+ csr32w(ctlr, Mcc, r|Asr);
+ microdelay(1);
+ csr32w(ctlr, Mcc, r&~Asr);
+ delay(100);
+
+ for(timeo = 0; timeo < 100000; timeo++){
+ if(csr32r(ctlr, Mcc) & Lis)
+ break;
+ microdelay(1);
+ }
+ if(!(csr32r(ctlr, Mcc) & Lis)){
+ print("%s: couldn't reset\n", ctlr->name);
+ return axpdealloc(ctlr);
+ }
+ print("downloading...");
+ /*
+ * Copy the control programme to the card memory.
+ * The card's i960 control structures live at 0xD000.
+ */
+ if(sizeof(uartaxpcp) > 0xD000){
+ print("%s: control programme too big\n", ctlr->name);
+ return axpdealloc(ctlr);
+ }
+ /* TODO: is this right for more than 1 card? devastar does the same */
+ csr32w(ctlr, Remap, 0xA0000001);
+ for(i = 0; i < sizeof(uartaxpcp); i++)
+ ctlr->mem[i] = uartaxpcp[i];
+ /*
+ * Execute downloaded code and wait for it
+ * to signal ready.
+ */
+ csr32w(ctlr, Mb0, Edcc);
+ delay(100);
+ /* the manual says to wait for Cpr for 1 second */
+ for(timeo = 0; timeo < 10000; timeo++){
+ if(csr32r(ctlr, Mb0) & Cpr)
+ break;
+ microdelay(100);
+ }
+ if(!(csr32r(ctlr, Mb0) & Cpr)){
+ print("control programme not ready; Mb0 %#ux\n",
+ csr32r(ctlr, Mb0));
+ print("%s: distribution panel not connected or card not fully seated?\n",
+ ctlr->name);
+
+ return axpdealloc(ctlr);
+ }
+ print("\n");
+
+ n = ctlr->gcb->ccbn;
+ if(ctlr->gcb->bt != 0x12 || n > 16){
+ print("%s: wrong board type %#ux, %d channels\n",
+ ctlr->name, ctlr->gcb->bt, ctlr->gcb->ccbn);
+ return axpdealloc(ctlr);
+ }
+
+ p = ((uchar*)ctlr->gcb) + ctlr->gcb->ccboff;
+ for(i = 0; i < n; i++){
+ cc = &ctlr->cc[i];
+ cc->ccb = (Ccb*)p;
+ p += ctlr->gcb->ccbsz;
+ cc->uartno = i;
+ cc->ctlr = ctlr;
+
+ cc->regs = cc; /* actually Uart->regs */
+ seprint(name, name+sizeof(name), "uartaxp%d%2.2d", ctlrno, i);
+ kstrdup(&cc->name, name);
+ cc->freq = 0;
+ cc->bits = 8;
+ cc->stop = 1;
+ cc->parity = 'n';
+ cc->baud = 9600;
+ cc->phys = &axpphysuart;
+ cc->console = 0;
+ cc->special = 0;
+
+ cc->next = &ctlr->cc[i+1];
+ }
+ ctlr->cc[n-1].next = nil;
+
+ ctlr->next = nil;
+ if(axpctlrhead != nil)
+ axpctlrtail->next = ctlr;
+ else
+ axpctlrhead = ctlr;
+ axpctlrtail = ctlr;
+
+ return ctlr->cc;
+}
+
+static Uart*
+axppnp(void)
+{
+ Pcidev *p;
+ int ctlrno;
+ Uart *head, *tail, *uart;
+
+ /*
+ * Loop through all PCI devices looking for simple serial
+ * controllers (ccrb == 0x07) and configure the ones which
+ * are familiar.
+ */
+ head = tail = nil;
+ ctlrno = 0;
+ for(p = pcimatch(nil, 0, 0); p != nil; p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x07)
+ continue;
+
+ switch((p->did<<16)|p->vid){
+ default:
+ continue;
+ case (0x6001<<16)|0x114F: /* AvanstarXp */
+ if((uart = axpalloc(ctlrno, p)) == nil)
+ continue;
+ break;
+ }
+
+ if(head != nil)
+ tail->next = uart;
+ else
+ head = uart;
+ for(tail = uart; tail->next != nil; tail = tail->next)
+ ;
+ ctlrno++;
+ }
+
+ return head;
+}
+
+PhysUart axpphysuart = {
+ .name = "AvanstarXp",
+ .pnp = axppnp,
+ .enable = axpenable,
+ .disable = axpdisable,
+ .kick = axpkick,
+ .dobreak = axpbreak,
+ .baud = axpbaud,
+ .bits = axpbits,
+ .stop = axpstop,
+ .parity = axpparity,
+ .modemctl = axpmodemctl,
+ .rts = axprts,
+ .dtr = axpdtr,
+ .status = axpstatus,
+ .fifo = axpfifo,
+ .getc = nil,
+ .putc = nil,
+};
diff --git a/sys/src/9/pc/uarti8250.c b/sys/src/9/pc/uarti8250.c
new file mode 100755
index 000000000..a3caf7741
--- /dev/null
+++ b/sys/src/9/pc/uarti8250.c
@@ -0,0 +1,739 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+/*
+ * 8250 UART and compatibles.
+ */
+enum {
+ Uart0 = 0x3F8, /* COM1 */
+ Uart0IRQ = 4,
+ Uart1 = 0x2F8, /* COM2 */
+ Uart1IRQ = 3,
+
+ UartFREQ = 1843200,
+};
+
+enum { /* I/O ports */
+ Rbr = 0, /* Receiver Buffer (RO) */
+ Thr = 0, /* Transmitter Holding (WO) */
+ Ier = 1, /* Interrupt Enable */
+ Iir = 2, /* Interrupt Identification (RO) */
+ Fcr = 2, /* FIFO Control (WO) */
+ Lcr = 3, /* Line Control */
+ Mcr = 4, /* Modem Control */
+ Lsr = 5, /* Line Status */
+ Msr = 6, /* Modem Status */
+ Scr = 7, /* Scratch Pad */
+ Dll = 0, /* Divisor Latch LSB */
+ Dlm = 1, /* Divisor Latch MSB */
+};
+
+enum { /* Ier */
+ Erda = 0x01, /* Enable Received Data Available */
+ Ethre = 0x02, /* Enable Thr Empty */
+ Erls = 0x04, /* Enable Receiver Line Status */
+ Ems = 0x08, /* Enable Modem Status */
+};
+
+enum { /* Iir */
+ Ims = 0x00, /* Ms interrupt */
+ Ip = 0x01, /* Interrupt Pending (not) */
+ Ithre = 0x02, /* Thr Empty */
+ Irda = 0x04, /* Received Data Available */
+ Irls = 0x06, /* Receiver Line Status */
+ Ictoi = 0x0C, /* Character Time-out Indication */
+ IirMASK = 0x3F,
+ Ifena = 0xC0, /* FIFOs enabled */
+};
+
+enum { /* Fcr */
+ FIFOena = 0x01, /* FIFO enable */
+ FIFOrclr = 0x02, /* clear Rx FIFO */
+ FIFOtclr = 0x04, /* clear Tx FIFO */
+ FIFO1 = 0x00, /* Rx FIFO trigger level 1 byte */
+ FIFO4 = 0x40, /* 4 bytes */
+ FIFO8 = 0x80, /* 8 bytes */
+ FIFO14 = 0xC0, /* 14 bytes */
+};
+
+enum { /* Lcr */
+ Wls5 = 0x00, /* Word Length Select 5 bits/byte */
+ Wls6 = 0x01, /* 6 bits/byte */
+ Wls7 = 0x02, /* 7 bits/byte */
+ Wls8 = 0x03, /* 8 bits/byte */
+ WlsMASK = 0x03,
+ Stb = 0x04, /* 2 stop bits */
+ Pen = 0x08, /* Parity Enable */
+ Eps = 0x10, /* Even Parity Select */
+ Stp = 0x20, /* Stick Parity */
+ Brk = 0x40, /* Break */
+ Dlab = 0x80, /* Divisor Latch Access Bit */
+};
+
+enum { /* Mcr */
+ Dtr = 0x01, /* Data Terminal Ready */
+ Rts = 0x02, /* Ready To Send */
+ Out1 = 0x04, /* no longer in use */
+ Ie = 0x08, /* IRQ Enable */
+ Dm = 0x10, /* Diagnostic Mode loopback */
+};
+
+enum { /* Lsr */
+ Dr = 0x01, /* Data Ready */
+ Oe = 0x02, /* Overrun Error */
+ Pe = 0x04, /* Parity Error */
+ Fe = 0x08, /* Framing Error */
+ Bi = 0x10, /* Break Interrupt */
+ Thre = 0x20, /* Thr Empty */
+ Temt = 0x40, /* Tramsmitter Empty */
+ FIFOerr = 0x80, /* error in receiver FIFO */
+};
+
+enum { /* Msr */
+ Dcts = 0x01, /* Delta Cts */
+ Ddsr = 0x02, /* Delta Dsr */
+ Teri = 0x04, /* Trailing Edge of Ri */
+ Ddcd = 0x08, /* Delta Dcd */
+ Cts = 0x10, /* Clear To Send */
+ Dsr = 0x20, /* Data Set Ready */
+ Ri = 0x40, /* Ring Indicator */
+ Dcd = 0x80, /* Data Set Ready */
+};
+
+typedef struct Ctlr {
+ int io;
+ int irq;
+ int tbdf;
+ int iena;
+
+ uchar sticky[8];
+
+ Lock;
+ int hasfifo;
+ int checkfifo;
+ int fena;
+} Ctlr;
+
+extern PhysUart i8250physuart;
+
+static Ctlr i8250ctlr[2] = {
+{ .io = Uart0,
+ .irq = Uart0IRQ,
+ .tbdf = BUSUNKNOWN, },
+
+{ .io = Uart1,
+ .irq = Uart1IRQ,
+ .tbdf = BUSUNKNOWN, },
+};
+
+static Uart i8250uart[2] = {
+{ .regs = &i8250ctlr[0],
+ .name = "COM1",
+ .freq = UartFREQ,
+ .phys = &i8250physuart,
+ .special= 0,
+ .next = &i8250uart[1], },
+
+{ .regs = &i8250ctlr[1],
+ .name = "COM2",
+ .freq = UartFREQ,
+ .phys = &i8250physuart,
+ .special= 0,
+ .next = nil, },
+};
+
+#define csr8r(c, r) inb((c)->io+(r))
+#define csr8w(c, r, v) outb((c)->io+(r), (c)->sticky[(r)]|(v))
+
+static long
+i8250status(Uart* uart, void* buf, long n, long offset)
+{
+ char *p;
+ Ctlr *ctlr;
+ uchar ier, lcr, mcr, msr;
+
+ ctlr = uart->regs;
+ p = malloc(READSTR);
+ mcr = ctlr->sticky[Mcr];
+ msr = csr8r(ctlr, Msr);
+ ier = ctlr->sticky[Ier];
+ lcr = ctlr->sticky[Lcr];
+ snprint(p, READSTR,
+ "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
+ "dev(%d) type(%d) framing(%d) overruns(%d) "
+ "berr(%d) serr(%d)%s%s%s%s\n",
+
+ uart->baud,
+ uart->hup_dcd,
+ (msr & Dsr) != 0,
+ uart->hup_dsr,
+ (lcr & WlsMASK) + 5,
+ (ier & Ems) != 0,
+ (lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n',
+ (mcr & Rts) != 0,
+ (lcr & Stb) ? 2: 1,
+ ctlr->fena,
+
+ uart->dev,
+ uart->type,
+ uart->ferr,
+ uart->oerr,
+ uart->berr,
+ uart->serr,
+ (msr & Cts) ? " cts": "",
+ (msr & Dsr) ? " dsr": "",
+ (msr & Dcd) ? " dcd": "",
+ (msr & Ri) ? " ring": ""
+ );
+ n = readstr(offset, buf, n, p);
+ free(p);
+
+ return n;
+}
+
+static void
+i8250fifo(Uart* uart, int level)
+{
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ if(ctlr->hasfifo == 0)
+ return;
+
+ /*
+ * Changing the FIFOena bit in Fcr flushes data
+ * from both receive and transmit FIFOs; there's
+ * no easy way to guarantee not losing data on
+ * the receive side, but it's possible to wait until
+ * the transmitter is really empty.
+ */
+ ilock(ctlr);
+ while(!(csr8r(ctlr, Lsr) & Temt))
+ ;
+
+ /*
+ * Set the trigger level, default is the max.
+ * value.
+ * Some UARTs require FIFOena to be set before
+ * other bits can take effect, so set it twice.
+ */
+ ctlr->fena = level;
+ switch(level){
+ case 0:
+ break;
+ case 1:
+ level = FIFO1|FIFOena;
+ break;
+ case 4:
+ level = FIFO4|FIFOena;
+ break;
+ case 8:
+ level = FIFO8|FIFOena;
+ break;
+ default:
+ level = FIFO14|FIFOena;
+ break;
+ }
+ csr8w(ctlr, Fcr, level);
+ csr8w(ctlr, Fcr, level);
+ iunlock(ctlr);
+}
+
+static void
+i8250dtr(Uart* uart, int on)
+{
+ Ctlr *ctlr;
+
+ /*
+ * Toggle DTR.
+ */
+ ctlr = uart->regs;
+ if(on)
+ ctlr->sticky[Mcr] |= Dtr;
+ else
+ ctlr->sticky[Mcr] &= ~Dtr;
+ csr8w(ctlr, Mcr, 0);
+}
+
+static void
+i8250rts(Uart* uart, int on)
+{
+ Ctlr *ctlr;
+
+ /*
+ * Toggle RTS.
+ */
+ ctlr = uart->regs;
+ if(on)
+ ctlr->sticky[Mcr] |= Rts;
+ else
+ ctlr->sticky[Mcr] &= ~Rts;
+ csr8w(ctlr, Mcr, 0);
+}
+
+static void
+i8250modemctl(Uart* uart, int on)
+{
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ ilock(&uart->tlock);
+ if(on){
+ ctlr->sticky[Ier] |= Ems;
+ csr8w(ctlr, Ier, ctlr->sticky[Ier]);
+ uart->modem = 1;
+ uart->cts = csr8r(ctlr, Msr) & Cts;
+ }
+ else{
+ ctlr->sticky[Ier] &= ~Ems;
+ csr8w(ctlr, Ier, ctlr->sticky[Ier]);
+ uart->modem = 0;
+ uart->cts = 1;
+ }
+ iunlock(&uart->tlock);
+
+ /* modem needs fifo */
+ (*uart->phys->fifo)(uart, on);
+}
+
+static int
+i8250parity(Uart* uart, int parity)
+{
+ int lcr;
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ lcr = ctlr->sticky[Lcr] & ~(Eps|Pen);
+
+ switch(parity){
+ case 'e':
+ lcr |= Eps|Pen;
+ break;
+ case 'o':
+ lcr |= Pen;
+ break;
+ case 'n':
+ break;
+ default:
+ return -1;
+ }
+ ctlr->sticky[Lcr] = lcr;
+ csr8w(ctlr, Lcr, 0);
+
+ uart->parity = parity;
+
+ return 0;
+}
+
+static int
+i8250stop(Uart* uart, int stop)
+{
+ int lcr;
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ lcr = ctlr->sticky[Lcr] & ~Stb;
+
+ switch(stop){
+ case 1:
+ break;
+ case 2:
+ lcr |= Stb;
+ break;
+ default:
+ return -1;
+ }
+ ctlr->sticky[Lcr] = lcr;
+ csr8w(ctlr, Lcr, 0);
+
+ uart->stop = stop;
+
+ return 0;
+}
+
+static int
+i8250bits(Uart* uart, int bits)
+{
+ int lcr;
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ lcr = ctlr->sticky[Lcr] & ~WlsMASK;
+
+ switch(bits){
+ case 5:
+ lcr |= Wls5;
+ break;
+ case 6:
+ lcr |= Wls6;
+ break;
+ case 7:
+ lcr |= Wls7;
+ break;
+ case 8:
+ lcr |= Wls8;
+ break;
+ default:
+ return -1;
+ }
+ ctlr->sticky[Lcr] = lcr;
+ csr8w(ctlr, Lcr, 0);
+
+ uart->bits = bits;
+
+ return 0;
+}
+
+static int
+i8250baud(Uart* uart, int baud)
+{
+ ulong bgc;
+ Ctlr *ctlr;
+
+ /*
+ * Set the Baud rate by calculating and setting the Baud rate
+ * Generator Constant. This will work with fairly non-standard
+ * Baud rates.
+ */
+ if(uart->freq == 0 || baud <= 0)
+ return -1;
+ bgc = (uart->freq+8*baud-1)/(16*baud);
+
+ ctlr = uart->regs;
+ csr8w(ctlr, Lcr, Dlab);
+ outb(ctlr->io+Dlm, bgc>>8);
+ outb(ctlr->io+Dll, bgc);
+ csr8w(ctlr, Lcr, 0);
+
+ uart->baud = baud;
+
+ return 0;
+}
+
+static void
+i8250break(Uart* uart, int ms)
+{
+ Ctlr *ctlr;
+
+ /*
+ * Send a break.
+ */
+ if(ms <= 0)
+ ms = 200;
+
+ ctlr = uart->regs;
+ csr8w(ctlr, Lcr, Brk);
+ tsleep(&up->sleep, return0, 0, ms);
+ csr8w(ctlr, Lcr, 0);
+}
+
+static void
+i8250kick(Uart* uart)
+{
+ int i;
+ Ctlr *ctlr;
+
+ if(uart->cts == 0 || uart->blocked)
+ return;
+
+ /*
+ * 128 here is an arbitrary limit to make sure
+ * we don't stay in this loop too long. If the
+ * chip's output queue is longer than 128, too
+ * bad -- presotto
+ */
+ ctlr = uart->regs;
+ for(i = 0; i < 128; i++){
+ if(!(csr8r(ctlr, Lsr) & Thre))
+ break;
+ if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
+ break;
+ outb(ctlr->io+Thr, *(uart->op++));
+ }
+}
+
+static void
+i8250interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Uart *uart;
+ int iir, lsr, old, r;
+
+ uart = arg;
+
+ ctlr = uart->regs;
+ for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){
+ switch(iir & IirMASK){
+ case Ims: /* Ms interrupt */
+ r = csr8r(ctlr, Msr);
+ if(r & Dcts){
+ ilock(&uart->tlock);
+ old = uart->cts;
+ uart->cts = r & Cts;
+ if(old == 0 && uart->cts)
+ uart->ctsbackoff = 2;
+ iunlock(&uart->tlock);
+ }
+ if(r & Ddsr){
+ old = r & Dsr;
+ if(uart->hup_dsr && uart->dsr && !old)
+ uart->dohup = 1;
+ uart->dsr = old;
+ }
+ if(r & Ddcd){
+ old = r & Dcd;
+ if(uart->hup_dcd && uart->dcd && !old)
+ uart->dohup = 1;
+ uart->dcd = old;
+ }
+ break;
+ case Ithre: /* Thr Empty */
+ uartkick(uart);
+ break;
+ case Irda: /* Received Data Available */
+ case Irls: /* Receiver Line Status */
+ case Ictoi: /* Character Time-out Indication */
+ /*
+ * Consume any received data.
+ * If the received byte came in with a break,
+ * parity or framing error, throw it away;
+ * overrun is an indication that something has
+ * already been tossed.
+ */
+ while((lsr = csr8r(ctlr, Lsr)) & Dr){
+ if(lsr & (FIFOerr|Oe))
+ uart->oerr++;
+ if(lsr & Pe)
+ uart->perr++;
+ if(lsr & Fe)
+ uart->ferr++;
+ r = csr8r(ctlr, Rbr);
+ if(!(lsr & (Bi|Fe|Pe)))
+ uartrecv(uart, r);
+ }
+ break;
+
+ default:
+ iprint("weird uart interrupt 0x%2.2uX\n", iir);
+ break;
+ }
+ }
+}
+
+static void
+i8250disable(Uart* uart)
+{
+ Ctlr *ctlr;
+
+ /*
+ * Turn off DTR and RTS, disable interrupts and fifos.
+ */
+ (*uart->phys->dtr)(uart, 0);
+ (*uart->phys->rts)(uart, 0);
+ (*uart->phys->fifo)(uart, 0);
+
+ ctlr = uart->regs;
+ ctlr->sticky[Ier] = 0;
+ csr8w(ctlr, Ier, ctlr->sticky[Ier]);
+
+ if(ctlr->iena != 0){
+ if(intrdisable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name) == 0)
+ ctlr->iena = 0;
+ }
+}
+
+static void
+i8250enable(Uart* uart, int ie)
+{
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+
+ /*
+ * Check if there is a FIFO.
+ * Changing the FIFOena bit in Fcr flushes data
+ * from both receive and transmit FIFOs; there's
+ * no easy way to guarantee not losing data on
+ * the receive side, but it's possible to wait until
+ * the transmitter is really empty.
+ * Also, reading the Iir outwith i8250interrupt()
+ * can be dangerous, but this should only happen
+ * once before interrupts are enabled.
+ */
+ ilock(ctlr);
+ if(!ctlr->checkfifo){
+ /*
+ * Wait until the transmitter is really empty.
+ */
+ while(!(csr8r(ctlr, Lsr) & Temt))
+ ;
+ csr8w(ctlr, Fcr, FIFOena);
+ if(csr8r(ctlr, Iir) & Ifena)
+ ctlr->hasfifo = 1;
+ csr8w(ctlr, Fcr, 0);
+ ctlr->checkfifo = 1;
+ }
+ iunlock(ctlr);
+
+ /*
+ * Enable interrupts and turn on DTR and RTS.
+ * Be careful if this is called to set up a polled serial line
+ * early on not to try to enable interrupts as interrupt-
+ * -enabling mechanisms might not be set up yet.
+ */
+ if(ie){
+ if(ctlr->iena == 0){
+ intrenable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name);
+ ctlr->iena = 1;
+ }
+ ctlr->sticky[Ier] = Ethre|Erda;
+ ctlr->sticky[Mcr] |= Ie;
+ }
+ else{
+ ctlr->sticky[Ier] = 0;
+ ctlr->sticky[Mcr] = 0;
+ }
+ csr8w(ctlr, Ier, ctlr->sticky[Ier]);
+ csr8w(ctlr, Mcr, ctlr->sticky[Mcr]);
+
+ (*uart->phys->dtr)(uart, 1);
+ (*uart->phys->rts)(uart, 1);
+
+ /*
+ * During startup, the i8259 interrupt controller is reset.
+ * This may result in a lost interrupt from the i8250 uart.
+ * The i8250 thinks the interrupt is still outstanding and does not
+ * generate any further interrupts. The workaround is to call the
+ * interrupt handler to clear any pending interrupt events.
+ * Note: this must be done after setting Ier.
+ */
+ if(ie)
+ i8250interrupt(nil, uart);
+}
+
+void*
+i8250alloc(int io, int irq, int tbdf)
+{
+ Ctlr *ctlr;
+
+ if((ctlr = malloc(sizeof(Ctlr))) != nil){
+ ctlr->io = io;
+ ctlr->irq = irq;
+ ctlr->tbdf = tbdf;
+ }
+
+ return ctlr;
+}
+
+static Uart*
+i8250pnp(void)
+{
+ return i8250uart;
+}
+
+static int
+i8250getc(Uart *uart)
+{
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ while(!(csr8r(ctlr, Lsr)&Dr))
+ delay(1);
+ return csr8r(ctlr, Rbr);
+}
+
+static void
+i8250putc(Uart *uart, int c)
+{
+ int i;
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
+ delay(1);
+ outb(ctlr->io+Thr, c);
+ for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++)
+ delay(1);
+}
+
+PhysUart i8250physuart = {
+ .name = "i8250",
+ .pnp = i8250pnp,
+ .enable = i8250enable,
+ .disable = i8250disable,
+ .kick = i8250kick,
+ .dobreak = i8250break,
+ .baud = i8250baud,
+ .bits = i8250bits,
+ .stop = i8250stop,
+ .parity = i8250parity,
+ .modemctl = i8250modemctl,
+ .rts = i8250rts,
+ .dtr = i8250dtr,
+ .status = i8250status,
+ .fifo = i8250fifo,
+ .getc = i8250getc,
+ .putc = i8250putc,
+};
+
+void
+i8250console(void)
+{
+ Uart *uart;
+ int n;
+ char *cmd, *p;
+
+ if((p = getconf("console")) == nil)
+ return;
+ n = strtoul(p, &cmd, 0);
+ if(p == cmd)
+ return;
+ switch(n){
+ default:
+ return;
+ case 0:
+ uart = &i8250uart[0];
+ break;
+ case 1:
+ uart = &i8250uart[1];
+ break;
+ }
+
+ (*uart->phys->enable)(uart, 0);
+ uartctl(uart, "b9600 l8 pn s1");
+ if(*cmd != '\0')
+ uartctl(uart, cmd);
+
+ consuart = uart;
+ uart->console = 1;
+}
+
+void
+i8250mouse(char* which, int (*putc)(Queue*, int), int setb1200)
+{
+ char *p;
+ int port;
+
+ port = strtol(which, &p, 0);
+ if(p == which || port < 0 || port > 1)
+ error(Ebadarg);
+ uartmouse(&i8250uart[port], putc, setb1200);
+}
+
+void
+i8250setmouseputc(char* which, int (*putc)(Queue*, int))
+{
+ char *p;
+ int port;
+
+ port = strtol(which, &p, 0);
+ if(p == which || port < 0 || port > 1)
+ error(Ebadarg);
+ uartsetmouseputc(&i8250uart[port], putc);
+
+}
diff --git a/sys/src/9/pc/uartisa.c b/sys/src/9/pc/uartisa.c
new file mode 100755
index 000000000..7252813bf
--- /dev/null
+++ b/sys/src/9/pc/uartisa.c
@@ -0,0 +1,97 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+extern PhysUart i8250physuart;
+extern PhysUart isaphysuart;
+extern void* i8250alloc(int, int, int);
+
+static Uart*
+uartisa(int ctlrno, ISAConf* isa)
+{
+ int io;
+ void *ctlr;
+ Uart *uart;
+ char buf[64];
+
+ io = isa->port;
+ snprint(buf, sizeof(buf), "%s%d", isaphysuart.name, ctlrno);
+ if(ioalloc(io, 8, 0, buf) < 0){
+ print("uartisa: I/O 0x%uX in use\n", io);
+ return nil;
+ }
+
+ uart = malloc(sizeof(Uart));
+ ctlr = i8250alloc(io, isa->irq, BUSUNKNOWN);
+ if(ctlr == nil){
+ iofree(io);
+ free(uart);
+ return nil;
+ }
+
+ uart->regs = ctlr;
+ snprint(buf, sizeof(buf), "COM%d", ctlrno+1);
+ kstrdup(&uart->name, buf);
+ uart->freq = isa->freq;
+ uart->phys = &i8250physuart;
+
+ return uart;
+}
+
+static Uart*
+uartisapnp(void)
+{
+ int ctlrno;
+ ISAConf isa;
+ Uart *head, *tail, *uart;
+
+ /*
+ * Look for up to 4 discrete UARTs on the ISA bus.
+ * All suitable devices are configured to simply point
+ * to the generic i8250 driver.
+ */
+ head = tail = nil;
+ for(ctlrno = 2; ctlrno < 6; ctlrno++){
+ memset(&isa, 0, sizeof(isa));
+ if(!isaconfig("uart", ctlrno, &isa))
+ continue;
+ if(strcmp(isa.type, "isa") != 0)
+ continue;
+ if(isa.port == 0 || isa.irq == 0)
+ continue;
+ if(isa.freq == 0)
+ isa.freq = 1843200;
+ uart = uartisa(ctlrno, &isa);
+ if(uart == nil)
+ continue;
+ if(head != nil)
+ tail->next = uart;
+ else
+ head = uart;
+ tail = uart;
+ }
+
+ return head;
+}
+
+PhysUart isaphysuart = {
+ .name = "UartISA",
+ .pnp = uartisapnp,
+ .enable = nil,
+ .disable = nil,
+ .kick = nil,
+ .dobreak = nil,
+ .baud = nil,
+ .bits = nil,
+ .stop = nil,
+ .parity = nil,
+ .modemctl = nil,
+ .rts = nil,
+ .dtr = nil,
+ .status = nil,
+ .fifo = nil,
+};
diff --git a/sys/src/9/pc/uartpci.c b/sys/src/9/pc/uartpci.c
new file mode 100755
index 000000000..d86acf50f
--- /dev/null
+++ b/sys/src/9/pc/uartpci.c
@@ -0,0 +1,219 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+extern PhysUart i8250physuart;
+extern PhysUart pciphysuart;
+extern void* i8250alloc(int, int, int);
+
+static Uart *perlehead, *perletail;
+
+static Uart*
+uartpci(int ctlrno, Pcidev* p, int barno, int n, int freq, char* name,
+ int iosize)
+{
+ int i, io;
+ void *ctlr;
+ char buf[64];
+ Uart *head, *uart;
+
+ io = p->mem[barno].bar & ~0x01;
+ snprint(buf, sizeof(buf), "%s%d", pciphysuart.name, ctlrno);
+ if(ioalloc(io, p->mem[barno].size, 0, buf) < 0){
+ print("uartpci: I/O 0x%uX in use\n", io);
+ return nil;
+ }
+
+ head = uart = malloc(sizeof(Uart)*n);
+ for(i = 0; i < n; i++){
+ ctlr = i8250alloc(io, p->intl, p->tbdf);
+ io += iosize;
+ if(ctlr == nil)
+ continue;
+
+ uart->regs = ctlr;
+ snprint(buf, sizeof(buf), "%s.%8.8uX", name, p->tbdf);
+ kstrdup(&uart->name, buf);
+ uart->freq = freq;
+ uart->phys = &i8250physuart;
+ if(uart != head)
+ (uart-1)->next = uart;
+ uart++;
+ }
+
+ if (head) {
+ if(perlehead != nil)
+ perletail->next = head;
+ else
+ perlehead = head;
+ for(perletail = head; perletail->next != nil;
+ perletail = perletail->next)
+ ;
+ }
+ return head;
+}
+
+static Uart *
+ultraport16si(int ctlrno, Pcidev *p, ulong freq)
+{
+ int io, i;
+ char *name;
+ Uart *uart;
+
+ name = "Ultraport16si"; /* 16L788 UARTs */
+ io = p->mem[4].bar & ~1;
+ if (ioalloc(io, p->mem[4].size, 0, name) < 0) {
+ print("uartpci: can't get IO space to set %s to rs-232\n", name);
+ return nil;
+ }
+ for (i = 0; i < 16; i++) {
+ outb(io, i << 4);
+ outb(io, (i << 4) + 1); /* set to RS232 mode (Don't ask!) */
+ }
+
+ uart = uartpci(ctlrno, p, 2, 8, freq, name, 16);
+ if(uart)
+ uart = uartpci(ctlrno, p, 3, 8, freq, name, 16);
+ return uart;
+}
+
+static Uart*
+uartpcipnp(void)
+{
+ Pcidev *p;
+ char *name;
+ int ctlrno, subid;
+ ulong freq;
+ Uart *uart;
+
+ /*
+ * Loop through all PCI devices looking for simple serial
+ * controllers (ccrb == Pcibccomm (7)) and configure the ones which
+ * are familiar. All suitable devices are configured to
+ * simply point to the generic i8250 driver.
+ */
+ perlehead = perletail = nil;
+ ctlrno = 0;
+ for(p = pcimatch(nil, 0, 0); p != nil; p = pcimatch(p, 0, 0)){
+ if(p->ccrb != Pcibccomm || p->ccru > 2)
+ continue;
+
+ switch(p->did<<16 | p->vid){
+ default:
+ continue;
+ case (0x9835<<16)|0x9710: /* StarTech PCI2S550 */
+ uart = uartpci(ctlrno, p, 0, 1, 1843200, "PCI2S550-0", 8);
+ if(uart == nil)
+ continue;
+ uart->next = uartpci(ctlrno, p, 1, 1, 1843200,
+ "PCI2S550-1", 8);
+ if(uart->next == nil)
+ continue;
+ break;
+ case (0x950A<<16)|0x1415: /* Oxford Semi OX16PCI954 */
+ case (0x9501<<16)|0x1415:
+ case (0x9521<<16)|0x1415:
+ /*
+ * These are common devices used by 3rd-party
+ * manufacturers.
+ * Must check the subsystem VID and DID for correct
+ * match.
+ */
+ subid = pcicfgr16(p, PciSVID);
+ subid |= pcicfgr16(p, PciSID)<<16;
+ switch(subid){
+ default:
+ print("oxsemi uart %.8#ux of vid %#ux did %#ux unknown\n",
+ subid, p->vid, p->did);
+ continue;
+ case (0<<16)|0x1415:
+ uart = uartpci(ctlrno, p, 0, 4, 1843200,
+ "starport-pex4s", 8);
+ break;
+ case (1<<16)|0x1415:
+ uart = uartpci(ctlrno, p, 0, 2, 14745600,
+ "starport-pex2s", 8);
+ break;
+ case (0x2000<<16)|0x131F:/* SIIG CyberSerial PCIe */
+ uart = uartpci(ctlrno, p, 0, 1, 18432000,
+ "CyberSerial-1S", 8);
+ break;
+ }
+ break;
+ case (0x9505<<16)|0x1415: /* Oxford Semi OXuPCI952 */
+ name = "SATAGear-IOI-102"; /* PciSVID=1415, PciSID=0 */
+ if (uartpci(ctlrno, p, 0, 1, 14745600, name, 8) != nil)
+ ctlrno++;
+ if (uartpci(ctlrno, p, 1, 1, 14745600, name, 8) != nil)
+ ctlrno++;
+ uart = nil; /* don't ctlrno++ below */
+ break;
+ case (0x9050<<16)|0x10B5: /* Perle PCI-Fast4 series */
+ case (0x9030<<16)|0x10B5: /* Perle Ultraport series */
+ /*
+ * These devices consists of a PLX bridge (the above
+ * PCI VID+DID) behind which are some 16C654 UARTs.
+ * Must check the subsystem VID and DID for correct
+ * match.
+ */
+ subid = pcicfgr16(p, PciSVID);
+ subid |= pcicfgr16(p, PciSID)<<16;
+ freq = 7372800;
+ switch(subid){
+ default:
+ continue;
+ case (0x0011<<16)|0x12E0: /* Perle PCI-Fast16 */
+ name = "PCI-Fast16";
+ uart = uartpci(ctlrno, p, 2, 16, freq, name, 8);
+ break;
+ case (0x0021<<16)|0x12E0: /* Perle PCI-Fast8 */
+ name = "PCI-Fast8";
+ uart = uartpci(ctlrno, p, 2, 8, freq, name, 8);
+ break;
+ case (0x0031<<16)|0x12E0: /* Perle PCI-Fast4 */
+ name = "PCI-Fast4";
+ uart = uartpci(ctlrno, p, 2, 4, freq, name, 8);
+ break;
+ case (0x0021<<16)|0x155F: /* Perle Ultraport8 */
+ name = "Ultraport8"; /* 16C754 UARTs */
+ uart = uartpci(ctlrno, p, 2, 8, freq, name, 8);
+ break;
+ case (0x0041<<16)|0x155F: /* Perle Ultraport16 */
+ name = "Ultraport16";
+ uart = uartpci(ctlrno, p, 2, 16, 2 * freq,
+ name, 8);
+ break;
+ case (0x0241<<16)|0x155F: /* Perle Ultraport16 */
+ uart = ultraport16si(ctlrno, p, 4 * freq);
+ break;
+ }
+ break;
+ }
+ if(uart)
+ ctlrno++;
+ }
+
+ return perlehead;
+}
+
+PhysUart pciphysuart = {
+ .name = "UartPCI",
+ .pnp = uartpcipnp,
+ .enable = nil,
+ .disable = nil,
+ .kick = nil,
+ .dobreak = nil,
+ .baud = nil,
+ .bits = nil,
+ .stop = nil,
+ .parity = nil,
+ .modemctl = nil,
+ .rts = nil,
+ .dtr = nil,
+ .status = nil,
+ .fifo = nil,
+};
diff --git a/sys/src/9/pc/uncached.h b/sys/src/9/pc/uncached.h
new file mode 100755
index 000000000..c8aff3ac8
--- /dev/null
+++ b/sys/src/9/pc/uncached.h
@@ -0,0 +1,4 @@
+/*
+ * On the PC, processor accesses, memory caches and DMA are all
+ * coherent, so we don't need to use uncached memory.
+ */
diff --git a/sys/src/9/pc/usbehci.h b/sys/src/9/pc/usbehci.h
new file mode 100755
index 000000000..f3bf0f760
--- /dev/null
+++ b/sys/src/9/pc/usbehci.h
@@ -0,0 +1,221 @@
+/* override default macros from ../port/usb.h */
+#undef dprint
+#undef ddprint
+#undef deprint
+#undef ddeprint
+#define dprint if(ehcidebug)print
+#define ddprint if(ehcidebug>1)print
+#define deprint if(ehcidebug || ep->debug)print
+#define ddeprint if(ehcidebug>1 || ep->debug>1)print
+
+typedef struct Ctlr Ctlr;
+typedef struct Ecapio Ecapio;
+typedef struct Edbgio Edbgio;
+typedef struct Eopio Eopio;
+typedef struct Isoio Isoio;
+typedef struct Poll Poll;
+typedef struct Qh Qh;
+typedef struct Qtree Qtree;
+
+#pragma incomplete Ctlr;
+#pragma incomplete Ecapio;
+#pragma incomplete Edbgio;
+#pragma incomplete Eopio;
+#pragma incomplete Isoio;
+#pragma incomplete Poll;
+#pragma incomplete Qh;
+#pragma incomplete Qtree;
+
+/*
+ * EHCI interface registers and bits
+ */
+enum
+{
+ Cnports = 0xF, /* nport bits in Ecapio parms. */
+ Cdbgportshift = 20, /* debug port in Ecapio parms. */
+ Cdbgportmask = 0xF,
+ C64 = 1, /* 64-bits, in Ecapio capparms. */
+ Ceecpshift = 8, /* extended capabilities ptr. in */
+ Ceecpmask = 8, /* the Ecapio capparms reg. */
+ Clegacy = 1, /* legacy support cap. id */
+ CLbiossem = 2, /* legacy cap. bios sem. */
+ CLossem = 3, /* legacy cap. os sem */
+ CLcontrol = 4, /* legacy support control & status */
+
+ /* typed links */
+ Lterm = 1,
+ Litd = 0<<1,
+ Lqh = 1<<1,
+ Lsitd = 2<<1,
+ Lfstn = 3<<1, /* we don't use these */
+
+ /* Cmd reg. */
+ Cstop = 0x00000, /* stop running */
+ Crun = 0x00001, /* start operation */
+ Chcreset = 0x00002, /* host controller reset */
+ Cflsmask = 0x0000C, /* frame list size bits */
+ Cfls1024 = 0x00000, /* frame list size 1024 */
+ Cfls512 = 0x00004, /* frame list size 512 frames */
+ Cfls256 = 0x00008, /* frame list size 256 frames */
+ Cpse = 0x00010, /* periodic sched. enable */
+ Case = 0x00020, /* async sched. enable */
+ Ciasync = 0x00040, /* interrupt on async advance doorbell */
+ Citc1 = 0x10000, /* interrupt threshold ctl. 1 µframe */
+ Citc4 = 0x40000, /* same. 2 µframes */
+ /* ... */
+ Citc8 = 0x80000, /* same. 8 µframes (can go up to 64) */
+
+ /* Sts reg. */
+ Sasyncss = 0x08000, /* aync schedule status */
+ Speriodss = 0x04000, /* periodic schedule status */
+ Srecl = 0x02000, /* reclamnation (empty async sched.) */
+ Shalted = 0x01000, /* h.c. is halted */
+ Sasync = 0x00020, /* interrupt on async advance */
+ Sherr = 0x00010, /* host system error */
+ Sfrroll = 0x00008, /* frame list roll over */
+ Sportchg = 0x00004, /* port change detect */
+ Serrintr = 0x00002, /* error interrupt */
+ Sintr = 0x00001, /* interrupt */
+ Sintrs = 0x0003F, /* interrupts status */
+
+ /* Intr reg. */
+ Iusb = 0x01, /* intr. on usb */
+ Ierr = 0x02, /* intr. on usb error */
+ Iportchg = 0x04, /* intr. on port change */
+ Ifrroll = 0x08, /* intr. on frlist roll over */
+ Ihcerr = 0x10, /* intr. on host error */
+ Iasync = 0x20, /* intr. on async advance enable */
+ Iall = 0x3F, /* all interrupts */
+
+ /* Config reg. */
+ Callmine = 1, /* route all ports to us */
+
+ /* Portsc reg. */
+ Pspresent = 0x00000001, /* device present */
+ Psstatuschg = 0x00000002, /* Pspresent changed */
+ Psenable = 0x00000004, /* device enabled */
+ Pschange = 0x00000008, /* Psenable changed */
+ Psresume = 0x00000040, /* resume detected */
+ Pssuspend = 0x00000080, /* port suspended */
+ Psreset = 0x00000100, /* port reset */
+ Pspower = 0x00001000, /* port power on */
+ Psowner = 0x00002000, /* port owned by companion */
+ Pslinemask = 0x00000C00, /* line status bits */
+ Pslow = 0x00000400, /* low speed device */
+
+ /* Debug port csw reg. */
+ Cowner = 0x40000000, /* port owned by ehci */
+ Cenable = 0x10000000, /* debug port enabled */
+ Cdone = 0x00010000, /* request is done */
+ Cbusy = 0x00000400, /* port in use by a driver */
+ Cerrmask= 0x00000380, /* error code bits */
+ Chwerr = 0x00000100, /* hardware error */
+ Cterr = 0x00000080, /* transaction error */
+ Cfailed = 0x00000040, /* transaction did fail */
+ Cgo = 0x00000020, /* execute the transaction */
+ Cwrite = 0x00000010, /* request is a write */
+ Clen = 0x0000000F, /* data len */
+
+ /* Debug port pid reg. */
+ Prpidshift = 16, /* received pid */
+ Prpidmask = 0xFF,
+ Pspidshift = 8, /* sent pid */
+ Pspidmask = 0xFF,
+ Ptokshift = 0, /* token pid */
+ Ptokmask = 0xFF,
+
+ Ptoggle = 0x00008800, /* to update toggles */
+ Ptogglemask = 0x0000FF00,
+
+ /* Debug port addr reg. */
+ Adevshift = 8, /* device address */
+ Adevmask = 0x7F,
+ Aepshift = 0, /* endpoint number */
+ Aepmask = 0xF,
+};
+
+/*
+ * Capability registers (hw)
+ */
+struct Ecapio
+{
+ ulong cap; /* 00 controller capability register */
+ ulong parms; /* 04 structural parameters register */
+ ulong capparms; /* 08 capability parameters */
+ ulong portroute; /* 0c not on the CS5536 */
+};
+
+/*
+ * Debug port registers (hw)
+ */
+struct Edbgio
+{
+ ulong csw; /* control and status */
+ ulong pid; /* USB pid */
+ uchar data[8]; /* data buffer */
+ ulong addr; /* device and endpoint addresses */
+};
+
+struct Poll
+{
+ Lock;
+ Rendez;
+ int must;
+ int does;
+};
+
+struct Ctlr
+{
+ Rendez; /* for waiting to async advance doorbell */
+ Lock; /* for ilock. qh lists and basic ctlr I/O */
+ QLock portlck; /* for port resets/enable... (and doorbell) */
+ int active; /* in use or not */
+ Pcidev* pcidev;
+ Ecapio* capio; /* Capability i/o regs */
+ Eopio* opio; /* Operational i/o regs */
+
+ int nframes; /* 1024, 512, or 256 frames in the list */
+ ulong* frames; /* periodic frame list (hw) */
+ Qh* qhs; /* async Qh circular list for bulk/ctl */
+ Qtree* tree; /* tree of Qhs for the periodic list */
+ int ntree; /* number of dummy qhs in tree */
+ Qh* intrqhs; /* list of (not dummy) qhs in tree */
+ Isoio* iso; /* list of active Iso I/O */
+ ulong load;
+ ulong isoload;
+ int nintr; /* number of interrupts attended */
+ int ntdintr; /* number of intrs. with something to do */
+ int nqhintr; /* number of async td intrs. */
+ int nisointr; /* number of periodic td intrs. */
+ int nreqs;
+ Poll poll;
+};
+
+/*
+ * PC-specific stuff
+ */
+
+/*
+ * Operational registers (hw)
+ */
+struct Eopio
+{
+ ulong cmd; /* 00 command */
+ ulong sts; /* 04 status */
+ ulong intr; /* 08 interrupt enable */
+ ulong frno; /* 0c frame index */
+ ulong seg; /* 10 bits 63:32 of EHCI datastructs (unused) */
+ ulong frbase; /* 14 frame list base addr, 4096-byte boundary */
+ ulong link; /* 18 link for async list */
+ uchar d2c[0x40-0x1c]; /* 1c dummy */
+ ulong config; /* 40 1: all ports default-routed to this HC */
+ ulong portsc[1]; /* 44 Port status and control, one per port */
+};
+
+extern int ehcidebug;
+extern Ecapio *ehcidebugcapio;
+extern int ehcidebugport;
+
+void ehcilinkage(Hci *hp);
+void ehcimeminit(Ctlr *ctlr);
+void ehcirun(Ctlr *ctlr, int on);
diff --git a/sys/src/9/pc/usbehcipc.c b/sys/src/9/pc/usbehcipc.c
new file mode 100755
index 000000000..1fa9b0752
--- /dev/null
+++ b/sys/src/9/pc/usbehcipc.c
@@ -0,0 +1,273 @@
+/*
+ * PC-specific code for
+ * USB Enhanced Host Controller Interface (EHCI) driver
+ * High speed USB 2.0.
+ */
+
+#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/usb.h"
+#include "usbehci.h"
+
+static Ctlr* ctlrs[Nhcis];
+
+/* Isn't this cap list search in a helper function? */
+static void
+getehci(Ctlr* ctlr)
+{
+ int i, ptr, cap, sem;
+
+ ptr = (ctlr->capio->capparms >> Ceecpshift) & Ceecpmask;
+ for(; ptr != 0; ptr = pcicfgr8(ctlr->pcidev, ptr+1)){
+ if(ptr < 0x40 || (ptr & ~0xFC))
+ break;
+ cap = pcicfgr8(ctlr->pcidev, ptr);
+ if(cap != Clegacy)
+ continue;
+ sem = pcicfgr8(ctlr->pcidev, ptr+CLbiossem);
+ if(sem == 0)
+ continue;
+ pcicfgw8(ctlr->pcidev, ptr+CLossem, 1);
+ for(i = 0; i < 100; i++){
+ if(pcicfgr8(ctlr->pcidev, ptr+CLbiossem) == 0)
+ break;
+ delay(10);
+ }
+ if(i == 100)
+ dprint("ehci %#p: bios timed out\n", ctlr->capio);
+ pcicfgw32(ctlr->pcidev, ptr+CLcontrol, 0); /* no SMIs */
+ ctlr->opio->config = 0;
+ coherence();
+ return;
+ }
+}
+
+static void
+ehcireset(Ctlr *ctlr)
+{
+ Eopio *opio;
+ int i;
+
+ ilock(ctlr);
+ dprint("ehci %#p reset\n", ctlr->capio);
+ opio = ctlr->opio;
+
+ /*
+ * Turn off legacy mode. Some controllers won't
+ * interrupt us as expected otherwise.
+ */
+ ehcirun(ctlr, 0);
+ pcicfgw16(ctlr->pcidev, 0xc0, 0x2000);
+
+ /*
+ * reclaim from bios
+ */
+ getehci(ctlr);
+
+ /* clear high 32 bits of address signals if it's 64 bits capable.
+ * This is probably not needed but it does not hurt and others do it.
+ */
+ if((ctlr->capio->capparms & C64) != 0){
+ dprint("ehci: 64 bits\n");
+ opio->seg = 0;
+ coherence();
+ }
+
+ if(ehcidebugcapio != ctlr->capio){
+ opio->cmd |= Chcreset; /* controller reset */
+ coherence();
+ for(i = 0; i < 100; i++){
+ if((opio->cmd & Chcreset) == 0)
+ break;
+ delay(1);
+ }
+ if(i == 100)
+ print("ehci %#p controller reset timed out\n", ctlr->capio);
+ }
+
+ /* requesting more interrupts per µframe may miss interrupts */
+ opio->cmd |= Citc8; /* 1 intr. per ms */
+ coherence();
+ switch(opio->cmd & Cflsmask){
+ case Cfls1024:
+ ctlr->nframes = 1024;
+ break;
+ case Cfls512:
+ ctlr->nframes = 512;
+ break;
+ case Cfls256:
+ ctlr->nframes = 256;
+ break;
+ default:
+ panic("ehci: unknown fls %ld", opio->cmd & Cflsmask);
+ }
+ dprint("ehci: %d frames\n", ctlr->nframes);
+ iunlock(ctlr);
+}
+
+static void
+setdebug(Hci*, int d)
+{
+ ehcidebug = d;
+}
+
+static void
+shutdown(Hci *hp)
+{
+ int i;
+ Ctlr *ctlr;
+ Eopio *opio;
+
+ ctlr = hp->aux;
+ ilock(ctlr);
+ opio = ctlr->opio;
+ opio->cmd |= Chcreset; /* controller reset */
+ coherence();
+ for(i = 0; i < 100; i++){
+ if((opio->cmd & Chcreset) == 0)
+ break;
+ delay(1);
+ }
+ if(i >= 100)
+ print("ehci %#p controller reset timed out\n", ctlr->capio);
+ delay(100);
+ ehcirun(ctlr, 0);
+ opio->frbase = 0;
+ iunlock(ctlr);
+}
+
+static void
+scanpci(void)
+{
+ static int already = 0;
+ int i;
+ ulong io;
+ Ctlr *ctlr;
+ Pcidev *p;
+ Ecapio *capio;
+
+ if(already)
+ return;
+ already = 1;
+ p = nil;
+ while ((p = pcimatch(p, 0, 0)) != nil) {
+ /*
+ * Find EHCI controllers (Programming Interface = 0x20).
+ */
+ if(p->ccrb != Pcibcserial || p->ccru != Pciscusb)
+ continue;
+ switch(p->ccrp){
+ case 0x20:
+ io = p->mem[0].bar & ~0x0f;
+ break;
+ default:
+ continue;
+ }
+ if(io == 0){
+ print("usbehci: %x %x: failed to map registers\n",
+ p->vid, p->did);
+ continue;
+ }
+ if(p->intl == 0xff || p->intl == 0) {
+ print("usbehci: no irq assigned for port %#lux\n", io);
+ continue;
+ }
+ dprint("usbehci: %#x %#x: port %#lux size %#x irq %d\n",
+ p->vid, p->did, io, p->mem[0].size, p->intl);
+
+ ctlr = smalloc(sizeof(Ctlr));
+ ctlr->pcidev = p;
+ capio = ctlr->capio = vmap(io, p->mem[0].size);
+ ctlr->opio = (Eopio*)((uintptr)capio + (capio->cap & 0xff));
+ pcisetbme(p);
+ pcisetpms(p, 0);
+ for(i = 0; i < Nhcis; i++)
+ if(ctlrs[i] == nil){
+ ctlrs[i] = ctlr;
+ break;
+ }
+ if(i >= Nhcis)
+ print("ehci: bug: more than %d controllers\n", Nhcis);
+
+ /*
+ * currently, if we enable a second ehci controller,
+ * we'll wedge solid after iunlock in init for the second one.
+ */
+ if (i > 0) {
+// iprint("usbehci: ignoring controllers after the first, "
+// "at %#p\n", io);
+// ctlrs[i] = nil;
+ iprint("usbehci: multiple controllers present\n");
+ }
+ }
+}
+
+static int
+reset(Hci *hp)
+{
+ int i;
+ Ctlr *ctlr;
+ Ecapio *capio;
+ Pcidev *p;
+ static Lock resetlck;
+
+ if(getconf("*nousbehci"))
+ return -1;
+ ilock(&resetlck);
+ scanpci();
+
+ /*
+ * Any adapter matches if no hp->port is supplied,
+ * otherwise the ports must match.
+ */
+ ctlr = nil;
+ for(i = 0; i < Nhcis && ctlrs[i] != nil; i++){
+ ctlr = ctlrs[i];
+ if(ctlr->active == 0)
+ if(hp->port == 0 || hp->port == (uintptr)ctlr->capio){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ iunlock(&resetlck);
+ if(i >= Nhcis || ctlrs[i] == nil)
+ return -1;
+
+ p = ctlr->pcidev;
+ hp->aux = ctlr;
+ hp->port = (uintptr)ctlr->capio;
+ hp->irq = p->intl;
+ hp->tbdf = p->tbdf;
+
+ capio = ctlr->capio;
+ hp->nports = capio->parms & Cnports;
+
+ ddprint("echi: %s, ncc %lud npcc %lud\n",
+ capio->parms & 0x10000 ? "leds" : "no leds",
+ (capio->parms >> 12) & 0xf, (capio->parms >> 8) & 0xf);
+ ddprint("ehci: routing %s, %sport power ctl, %d ports\n",
+ capio->parms & 0x40 ? "explicit" : "automatic",
+ capio->parms & 0x10 ? "" : "no ", hp->nports);
+
+ ehcireset(ctlr);
+ ehcimeminit(ctlr);
+
+ /*
+ * Linkage to the generic HCI driver.
+ */
+ ehcilinkage(hp);
+ hp->shutdown = shutdown;
+ hp->debug = setdebug;
+ return 0;
+}
+
+void
+usbehcilink(void)
+{
+ addhcitype("ehci", reset);
+}
diff --git a/sys/src/9/pc/usbohci.c b/sys/src/9/pc/usbohci.c
new file mode 100755
index 000000000..c0a790ff9
--- /dev/null
+++ b/sys/src/9/pc/usbohci.c
@@ -0,0 +1,2567 @@
+/*
+ * USB Open Host Controller Interface (Ohci) driver
+ *
+ * BUGS:
+ * - Missing isochronous input streams.
+ * - Too many delays and ilocks.
+ * - bandwidth admission control must be done per-frame.
+ * - Buffering could be handled like in uhci, to avoid
+ * needed block allocation and avoid allocs for small Tds.
+ * - must warn of power overruns.
+ */
+
+#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/usb.h"
+
+typedef struct Ctlio Ctlio;
+typedef struct Ctlr Ctlr;
+typedef struct Ed Ed;
+typedef struct Edpool Edpool;
+typedef struct Epx Epx;
+typedef struct Hcca Hcca;
+typedef struct Isoio Isoio;
+typedef struct Ohci Ohci;
+typedef struct Qio Qio;
+typedef struct Qtree Qtree;
+typedef struct Td Td;
+typedef struct Tdpool Tdpool;
+
+enum
+{
+ Incr = 64, /* for Td and Ed pools */
+
+ Align = 0x20, /* OHCI only requires 0x10 */
+ /* use always a power of 2 */
+
+ Abortdelay = 1, /* delay after cancelling Tds (ms) */
+ Tdatomic = 8, /* max nb. of Tds per bulk I/O op. */
+ Enabledelay = 100, /* waiting for a port to enable */
+
+
+ /* Queue states (software) */
+ Qidle = 0,
+ Qinstall,
+ Qrun,
+ Qdone,
+ Qclose,
+ Qfree,
+
+ /* Ed control bits */
+ Edmpsmask = 0x7ff, /* max packet size */
+ Edmpsshift = 16,
+ Edlow = 1 << 13, /* low speed */
+ Edskip = 1 << 14, /* skip this ed */
+ Ediso = 1 << 15, /* iso Tds used */
+ Edtddir = 0, /* get dir from td */
+ Edin = 2 << 11, /* direction in */
+ Edout = 1 << 11, /* direction out */
+ Eddirmask = 3 << 11, /* direction bits */
+ Edhalt = 1, /* halted (in head ptr) */
+ Edtoggle = 2, /* toggle (in head ptr) 1 == data1 */
+
+ /* Td control bits */
+ Tdround = 1<<18, /* (rounding) short packets ok */
+ Tdtoksetup = 0<<19, /* setup packet */
+ Tdtokin = 2<<19, /* in packet */
+ Tdtokout = 1<<19, /* out packet */
+ Tdtokmask = 3<<19, /* in/out/setup bits */
+ Tdnoioc = 7<<21, /* intr. cnt. value for no interrupt */
+ Tdusetog = 1<<25, /* use toggle from Td (1) or Ed (0) */
+ Tddata1 = 1<<24, /* data toggle (1 == data1) */
+ Tddata0 = 0<<24,
+ Tdfcmask = 7, /* frame count (iso) */
+ Tdfcshift = 24,
+ Tdsfmask = 0xFFFF, /* starting frame (iso) */
+ Tderrmask = 3, /* error counter */
+ Tderrshift = 26,
+ Tdccmask = 0xf, /* condition code (status) */
+ Tdccshift = 28,
+ Tdiccmask = 0xf, /* condition code (iso, offsets) */
+ Tdiccshift = 12,
+
+ Ntdframes = 0x10000, /* # of different iso frame numbers */
+
+ /* Td errors (condition code) */
+ Tdok = 0,
+ Tdcrc = 1,
+ Tdbitstuff = 2,
+ Tdbadtog = 3,
+ Tdstalled = 4,
+ Tdtmout = 5,
+ Tdpidchk = 6,
+ Tdbadpid = 7,
+ Tddataovr = 8,
+ Tddataund = 9,
+ Tdbufovr = 0xC,
+ Tdbufund = 0xD,
+ Tdnotacc = 0xE,
+
+ /* control register */
+ Cple = 0x04, /* periodic list enable */
+ Cie = 0x08, /* iso. list enable */
+ Ccle = 0x10, /* ctl list enable */
+ Cble = 0x20, /* bulk list enable */
+ Cfsmask = 3 << 6, /* functional state... */
+ Cfsreset = 0 << 6,
+ Cfsresume = 1 << 6,
+ Cfsoper = 2 << 6,
+ Cfssuspend = 3 << 6,
+
+ /* command status */
+ Sblf = 1 << 2, /* bulk list (load) flag */
+ Sclf = 1 << 1, /* control list (load) flag */
+ Shcr = 1 << 0, /* host controller reset */
+
+ /* intr enable */
+ Mie = 1 << 31,
+ Oc = 1 << 30,
+ Rhsc = 1 << 6,
+ Fno = 1 << 5,
+ Ue = 1 << 4,
+ Rd = 1 << 3,
+ Sf = 1 << 2,
+ Wdh = 1 << 1,
+ So = 1 << 0,
+
+ Fmaxpktmask = 0x7fff,
+ Fmaxpktshift = 16,
+ HcRhDescA_POTPGT_MASK = 0xff << 24,
+ HcRhDescA_POTPGT_SHIFT = 24,
+
+ /* Rh status */
+ Lps = 1 << 0,
+ Cgp = 1 << 0,
+ Oci = 1 << 1,
+ Psm = 1 << 8,
+ Nps = 1 << 9,
+ Drwe = 1 << 15,
+ Srwe = 1 << 15,
+ Lpsc = 1 << 16,
+ Ccic = 1 << 17,
+ Crwe = 1 << 31,
+
+ /* port status */
+ Ccs = 0x00001, /* current connect status */
+ Pes = 0x00002, /* port enable status */
+ Pss = 0x00004, /* port suspend status */
+ Poci = 0x00008, /* over current indicator */
+ Prs = 0x00010, /* port reset status */
+ Pps = 0x00100, /* port power status */
+ Lsda = 0x00200, /* low speed device attached */
+ Csc = 0x10000, /* connect status change */
+ Pesc = 0x20000, /* enable status change */
+ Pssc = 0x40000, /* suspend status change */
+ Ocic = 0x80000, /* over current ind. change */
+ Prsc = 0x100000, /* reset status change */
+
+ /* port status write bits */
+ Cpe = 0x001, /* clear port enable */
+ Spe = 0x002, /* set port enable */
+ Spr = 0x010, /* set port reset */
+ Spp = 0x100, /* set port power */
+ Cpp = 0x200, /* clear port power */
+
+};
+
+/*
+ * Endpoint descriptor. (first 4 words used by hardware)
+ */
+struct Ed {
+ ulong ctrl;
+ ulong tail; /* transfer descriptor */
+ ulong head;
+ ulong nexted;
+
+ Ed* next; /* sw; in free list or next in list */
+ Td* tds; /* in use by current xfer; all for iso */
+ Ep* ep; /* debug/align */
+ Ed* inext; /* debug/align (dump interrupt eds). */
+};
+
+/*
+ * Endpoint I/O state (software), per direction.
+ */
+struct Qio
+{
+ QLock; /* for the entire I/O process */
+ Rendez; /* wait for completion */
+ Ed* ed; /* to place Tds on it */
+ int sched; /* queue number (intr/iso) */
+ int toggle; /* Tddata0/Tddata1 */
+ ulong usbid; /* device/endpoint address */
+ int tok; /* Tdsetup, Tdtokin, Tdtokout */
+ long iotime; /* last I/O time; to hold interrupt polls */
+ int debug; /* for the endpoint */
+ char* err; /* error status */
+ int state; /* Qidle -> Qinstall -> Qrun -> Qdone | Qclose */
+ long bw; /* load (intr/iso) */
+};
+
+struct Ctlio
+{
+ Qio; /* single Ed for all transfers */
+ uchar* data; /* read from last ctl req. */
+ int ndata; /* number of bytes read */
+};
+
+struct Isoio
+{
+ Qio;
+ int nframes; /* number of frames for a full second */
+ Td* atds; /* Tds avail for further I/O */
+ int navail; /* number of avail Tds */
+ ulong frno; /* next frame number avail for I/O */
+ ulong left; /* remainder after rounding Hz to samples/ms */
+ int nerrs; /* consecutive errors on iso I/O */
+};
+
+/*
+ * Transfer descriptor. Size must be multiple of 32
+ * First block is used by hardware (aligned to 32).
+ */
+struct Td
+{
+ ulong ctrl;
+ ulong cbp; /* current buffer pointer */
+ ulong nexttd;
+ ulong be;
+ ushort offsets[8]; /* used by Iso Tds only */
+
+ Td* next; /* in free or Ed tds list */
+ Td* anext; /* in avail td list (iso) */
+ Ep* ep; /* using this Td for I/O */
+ Qio* io; /* using this Td for I/O */
+ Block* bp; /* data for this Td */
+ ulong nbytes; /* bytes in this Td */
+ ulong cbp0; /* initial value for cbp */
+ ulong last; /* true for last Td in Qio */
+};
+
+/*
+ * Host controller communication area (hardware)
+ */
+struct Hcca
+{
+ ulong intrtable[32];
+ ushort framenumber;
+ ushort pad1;
+ ulong donehead;
+ uchar reserved[116];
+};
+
+/*
+ * I/O registers
+ */
+struct Ohci
+{
+ /* control and status group */
+ ulong revision; /*00*/
+ ulong control; /*04*/
+ ulong cmdsts; /*08*/
+ ulong intrsts; /*0c*/
+ ulong intrenable; /*10*/
+ ulong intrdisable; /*14*/
+
+ /* memory pointer group */
+ ulong hcca; /*18*/
+ ulong periodcurred; /*1c*/
+ ulong ctlheaded; /*20*/
+ ulong ctlcurred; /*24*/
+ ulong bulkheaded; /*28*/
+ ulong bulkcurred; /*2c*/
+ ulong donehead; /*30*/
+
+ /* frame counter group */
+ ulong fminterval; /*34*/
+ ulong fmremaining; /*38*/
+ ulong fmnumber; /*3c*/
+ ulong periodicstart; /*40*/
+ ulong lsthreshold; /*44*/
+
+ /* root hub group */
+ ulong rhdesca; /*48*/
+ ulong rhdescb; /*4c*/
+ ulong rhsts; /*50*/
+ ulong rhportsts[15]; /*54*/
+ ulong pad25[20]; /*90*/
+
+ /* unknown */
+ ulong hostueaddr; /*e0*/
+ ulong hostuests; /*e4*/
+ ulong hosttimeoutctrl; /*e8*/
+ ulong pad59; /*ec*/
+ ulong pad60; /*f0*/
+ ulong hostrevision; /*f4*/
+ ulong pad62[2];
+ /*100*/
+};
+
+/*
+ * Endpoint tree (software)
+ */
+struct Qtree
+{
+ int nel;
+ int depth;
+ ulong* bw;
+ Ed** root;
+};
+
+struct Tdpool
+{
+ Lock;
+ Td* free;
+ int nalloc;
+ int ninuse;
+ int nfree;
+};
+
+struct Edpool
+{
+ Lock;
+ Ed* free;
+ int nalloc;
+ int ninuse;
+ int nfree;
+};
+
+struct Ctlr
+{
+ Lock; /* for ilock; lists and basic ctlr I/O */
+ QLock resetl; /* lock controller during USB reset */
+ int active;
+ Ctlr* next;
+ int nports;
+
+ Ohci* ohci; /* base I/O address */
+ Hcca* hcca; /* intr/done Td lists (used by hardware) */
+ int overrun; /* sched. overrun */
+ Ed* intrhd; /* list of intr. eds in tree */
+ Qtree* tree; /* tree for t Ep i/o */
+ int ntree; /* number of dummy Eds in tree */
+ Pcidev* pcidev;
+};
+
+#define dqprint if(debug || io && io->debug)print
+#define ddqprint if(debug>1 || (io && io->debug>1))print
+#define diprint if(debug || iso && iso->debug)print
+#define ddiprint if(debug>1 || (iso && iso->debug>1))print
+#define TRUNC(x, sz) ((x) & ((sz)-1))
+
+static int ohciinterrupts[Nttypes];
+static char* iosname[] = { "idle", "install", "run", "done", "close", "FREE" };
+
+static int debug;
+static Edpool edpool;
+static Tdpool tdpool;
+static Ctlr* ctlrs[Nhcis];
+
+static char EnotWritten[] = "usb write unfinished";
+static char EnotRead[] = "usb read unfinished";
+static char Eunderrun[] = "usb endpoint underrun";
+
+static QLock usbhstate; /* protects name space state */
+
+static int schedendpt(Ctlr *ub, Ep *ep);
+static void unschedendpt(Ctlr *ub, Ep *ep);
+static long qtd(Ctlr*, Ep*, int, Block*, uchar*, uchar*, int, ulong);
+
+static char* errmsgs[] =
+{
+[Tdcrc] "crc error",
+[Tdbitstuff] "bit stuffing error",
+[Tdbadtog] "bad toggle",
+[Tdstalled] Estalled,
+[Tdtmout] "timeout error",
+[Tdpidchk] "pid check error",
+[Tdbadpid] "bad pid",
+[Tddataovr] "data overrun",
+[Tddataund] "data underrun",
+[Tdbufovr] "buffer overrun",
+[Tdbufund] "buffer underrun",
+[Tdnotacc] "not accessed"
+};
+
+static void*
+pa2ptr(ulong pa)
+{
+ if(pa == 0)
+ return nil;
+ else
+ return KADDR(pa);
+}
+
+static ulong
+ptr2pa(void *p)
+{
+ if(p == nil)
+ return 0;
+ else
+ return PADDR(p);
+}
+
+static void
+waitSOF(Ctlr *ub)
+{
+ int frame = ub->hcca->framenumber & 0x3f;
+
+ do {
+ delay(2);
+ } while(frame == (ub->hcca->framenumber & 0x3f));
+}
+
+static char*
+errmsg(int err)
+{
+
+ if(err < nelem(errmsgs))
+ return errmsgs[err];
+ return nil;
+}
+
+static Ed*
+ctlhd(Ctlr *ctlr)
+{
+ return pa2ptr(ctlr->ohci->ctlheaded);
+}
+
+static Ed*
+bulkhd(Ctlr *ctlr)
+{
+ return pa2ptr(ctlr->ohci->bulkheaded);
+}
+
+static void
+edlinked(Ed *ed, Ed *next)
+{
+ if(ed == nil)
+ print("edlinked: nil ed: pc %#p\n", getcallerpc(&ed));
+ ed->nexted = ptr2pa(next);
+ ed->next = next;
+}
+
+static void
+setctlhd(Ctlr *ctlr, Ed *ed)
+{
+ ctlr->ohci->ctlheaded = ptr2pa(ed);
+ if(ed != nil)
+ ctlr->ohci->cmdsts |= Sclf; /* reload it on next pass */
+}
+
+static void
+setbulkhd(Ctlr *ctlr, Ed *ed)
+{
+ ctlr->ohci->bulkheaded = ptr2pa(ed);
+ if(ed != nil)
+ ctlr->ohci->cmdsts |= Sblf; /* reload it on next pass */
+}
+
+static void
+unlinkctl(Ctlr *ctlr, Ed *ed)
+{
+ Ed *this, *prev, *next;
+
+ ctlr->ohci->control &= ~Ccle;
+ waitSOF(ctlr);
+ this = ctlhd(ctlr);
+ ctlr->ohci->ctlcurred = 0;
+ prev = nil;
+ while(this != nil && this != ed){
+ prev = this;
+ this = this->next;
+ }
+ if(this == nil){
+ print("unlinkctl: not found\n");
+ return;
+ }
+ next = this->next;
+ if(prev == nil)
+ setctlhd(ctlr, next);
+ else
+ edlinked(prev, next);
+ ctlr->ohci->control |= Ccle;
+ edlinked(ed, nil); /* wipe out next field */
+}
+
+static void
+unlinkbulk(Ctlr *ctlr, Ed *ed)
+{
+ Ed *this, *prev, *next;
+
+ ctlr->ohci->control &= ~Cble;
+ waitSOF(ctlr);
+ this = bulkhd(ctlr);
+ ctlr->ohci->bulkcurred = 0;
+ prev = nil;
+ while(this != nil && this != ed){
+ prev = this;
+ this = this->next;
+ }
+ if(this == nil){
+ print("unlinkbulk: not found\n");
+ return;
+ }
+ next = this->next;
+ if(prev == nil)
+ setbulkhd(ctlr, next);
+ else
+ edlinked(prev, next);
+ ctlr->ohci->control |= Cble;
+ edlinked(ed, nil); /* wipe out next field */
+}
+
+static void
+edsetaddr(Ed *ed, ulong addr)
+{
+ ulong ctrl;
+
+ ctrl = ed->ctrl & ~((Epmax<<7)|Devmax);
+ ctrl |= (addr & ((Epmax<<7)|Devmax));
+ ed->ctrl = ctrl;
+}
+
+static void
+edsettog(Ed *ed, int c)
+{
+ if(c != 0)
+ ed->head |= Edtoggle;
+ else
+ ed->head &= ~Edtoggle;
+}
+
+static int
+edtoggle(Ed *ed)
+{
+ return ed->head & Edtoggle;
+}
+
+static int
+edhalted(Ed *ed)
+{
+ return ed->head & Edhalt;
+}
+
+static int
+edmaxpkt(Ed *ed)
+{
+ return (ed->ctrl >> Edmpsshift) & Edmpsmask;
+}
+
+static void
+edsetmaxpkt(Ed *ed, int m)
+{
+ ulong c;
+
+ c = ed->ctrl & ~(Edmpsmask << Edmpsshift);
+ ed->ctrl = c | ((m&Edmpsmask) << Edmpsshift);
+}
+
+static int
+tderrs(Td *td)
+{
+ return (td->ctrl >> Tdccshift) & Tdccmask;
+}
+
+static int
+tdtok(Td *td)
+{
+ return (td->ctrl & Tdtokmask);
+}
+
+static Td*
+tdalloc(void)
+{
+ Td *td;
+ Td *pool;
+ int i;
+
+ lock(&tdpool);
+ if(tdpool.free == nil){
+ ddprint("ohci: tdalloc %d Tds\n", Incr);
+ pool = xspanalloc(Incr*sizeof(Td), Align, 0);
+ if(pool == nil)
+ panic("tdalloc");
+ for(i=Incr; --i>=0;){
+ pool[i].next = tdpool.free;
+ tdpool.free = &pool[i];
+ }
+ tdpool.nalloc += Incr;
+ tdpool.nfree += Incr;
+ }
+ tdpool.ninuse++;
+ tdpool.nfree--;
+ td = tdpool.free;
+ tdpool.free = td->next;
+ memset(td, 0, sizeof(Td));
+ unlock(&tdpool);
+
+ assert(((uintptr)td & 0xF) == 0);
+ return td;
+}
+
+static void
+tdfree(Td *td)
+{
+ if(td == 0)
+ return;
+ freeb(td->bp);
+ td->bp = nil;
+ lock(&tdpool);
+ if(td->nexttd == 0x77777777)
+ panic("ohci: tdfree: double free");
+ memset(td, 7, sizeof(Td)); /* poison */
+ td->next = tdpool.free;
+ tdpool.free = td;
+ tdpool.ninuse--;
+ tdpool.nfree++;
+ unlock(&tdpool);
+}
+
+static Ed*
+edalloc(void)
+{
+ Ed *ed, *pool;
+ int i;
+
+ lock(&edpool);
+ if(edpool.free == nil){
+ ddprint("ohci: edalloc %d Eds\n", Incr);
+ pool = xspanalloc(Incr*sizeof(Ed), Align, 0);
+ if(pool == nil)
+ panic("edalloc");
+ for(i=Incr; --i>=0;){
+ pool[i].next = edpool.free;
+ edpool.free = &pool[i];
+ }
+ edpool.nalloc += Incr;
+ edpool.nfree += Incr;
+ }
+ edpool.ninuse++;
+ edpool.nfree--;
+ ed = edpool.free;
+ edpool.free = ed->next;
+ memset(ed, 0, sizeof(Ed));
+ unlock(&edpool);
+
+ return ed;
+}
+
+static void
+edfree(Ed *ed)
+{
+ Td *td, *next;
+ int i;
+
+ if(ed == 0)
+ return;
+ i = 0;
+ for(td = ed->tds; td != nil; td = next){
+ next = td->next;
+ tdfree(td);
+ if(i++ > 2000){
+ print("ohci: bug: ed with more than 2000 tds\n");
+ break;
+ }
+ }
+ lock(&edpool);
+ if(ed->nexted == 0x99999999)
+ panic("ohci: edfree: double free");
+ memset(ed, 9, sizeof(Ed)); /* poison */
+ ed->next = edpool.free;
+ edpool.free = ed;
+ edpool.ninuse--;
+ edpool.nfree++;
+ unlock(&edpool);
+ ddprint("edfree: ed %#p\n", ed);
+}
+
+/*
+ * return smallest power of 2 >= n
+ */
+static int
+flog2(int n)
+{
+ int i;
+
+ for(i = 0; (1 << i) < n; i++)
+ ;
+ return i;
+}
+
+/*
+ * return smallest power of 2 <= n
+ */
+static int
+flog2lower(int n)
+{
+ int i;
+
+ for(i = 0; (1 << (i + 1)) <= n; i++)
+ ;
+ return i;
+}
+
+static int
+pickschedq(Qtree *qt, int pollival, ulong bw, ulong limit)
+{
+ int i, j, d, upperb, q;
+ ulong best, worst, total;
+
+ d = flog2lower(pollival);
+ if(d > qt->depth)
+ d = qt->depth;
+ q = -1;
+ worst = 0;
+ best = ~0;
+ upperb = (1 << (d+1)) - 1;
+ for(i = (1 << d) - 1; i < upperb; i++){
+ total = qt->bw[0];
+ for(j = i; j > 0; j = (j - 1) / 2)
+ total += qt->bw[j];
+ if(total < best){
+ best = total;
+ q = i;
+ }
+ if(total > worst)
+ worst = total;
+ }
+ if(worst + bw >= limit)
+ return -1;
+ return q;
+}
+
+static int
+schedq(Ctlr *ctlr, Qio *io, int pollival)
+{
+ int q;
+ Ed *ted;
+
+ q = pickschedq(ctlr->tree, pollival, io->bw, ~0);
+ ddqprint("ohci: sched %#p q %d, ival %d, bw %ld\n", io, q, pollival, io->bw);
+ if(q < 0){
+ print("ohci: no room for ed\n");
+ return -1;
+ }
+ ctlr->tree->bw[q] += io->bw;
+ ted = ctlr->tree->root[q];
+ io->sched = q;
+ edlinked(io->ed, ted->next);
+ edlinked(ted, io->ed);
+ io->ed->inext = ctlr->intrhd;
+ ctlr->intrhd = io->ed;
+ return 0;
+}
+
+static void
+unschedq(Ctlr *ctlr, Qio *qio)
+{
+ int q;
+ Ed *prev, *this, *next;
+ Ed **l;
+
+ q = qio->sched;
+ if(q < 0)
+ return;
+ ctlr->tree->bw[q] -= qio->bw;
+
+ prev = ctlr->tree->root[q];
+ this = prev->next;
+ while(this != nil && this != qio->ed){
+ prev = this;
+ this = this->next;
+ }
+ if(this == nil)
+ print("ohci: unschedq %d: not found\n", q);
+ else{
+ next = this->next;
+ edlinked(prev, next);
+ }
+ waitSOF(ctlr);
+ for(l = &ctlr->intrhd; *l != nil; l = &(*l)->inext)
+ if(*l == qio->ed){
+ *l = (*l)->inext;
+ return;
+ }
+ print("ohci: unschedq: ed %#p not found\n", qio->ed);
+}
+
+static char*
+seprinttdtok(char *s, char *e, int tok)
+{
+ switch(tok){
+ case Tdtoksetup:
+ s = seprint(s, e, " setup");
+ break;
+ case Tdtokin:
+ s = seprint(s, e, " in");
+ break;
+ case Tdtokout:
+ s = seprint(s, e, " out");
+ break;
+ }
+ return s;
+}
+
+
+static char*
+seprinttd(char *s, char *e, Td *td, int iso)
+{
+ int i;
+ Block *bp;
+
+ if(td == nil)
+ return seprint(s, e, "<nil td>\n");
+ s = seprint(s, e, "%#p ep %#p ctrl %#p", td, td->ep, td->ctrl);
+ s = seprint(s, e, " cc=%#ulx", (td->ctrl >> Tdccshift) & Tdccmask);
+ if(iso == 0){
+ if((td->ctrl & Tdround) != 0)
+ s = seprint(s, e, " rnd");
+ s = seprinttdtok(s, e, td->ctrl & Tdtokmask);
+ if((td->ctrl & Tdusetog) != 0)
+ s = seprint(s, e, " d%d", (td->ctrl & Tddata1) ? 1 : 0);
+ else
+ s = seprint(s, e, " d-");
+ s = seprint(s, e, " ec=%uld", (td->ctrl >> Tderrshift) & Tderrmask);
+ }else{
+ s = seprint(s, e, " fc=%uld", (td->ctrl >> Tdfcshift) & Tdfcmask);
+ s = seprint(s, e, " sf=%uld", td->ctrl & Tdsfmask);
+ }
+ s = seprint(s, e, " cbp0 %#p cbp %#p next %#p be %#p %s",
+ td->cbp0, td->cbp, td->nexttd, td->be, td->last ? "last" : "");
+ s = seprint(s, e, "\n\t\t%ld bytes", td->nbytes);
+ if((bp = td->bp) != nil){
+ s = seprint(s, e, " rp %#p wp %#p ", bp->rp, bp->wp);
+ if(BLEN(bp) > 0)
+ s = seprintdata(s, e, bp->rp, bp->wp - bp->rp);
+ }
+ if(iso == 0)
+ return seprint(s, e, "\n");
+ s = seprint(s, e, "\n\t\t");
+ /* we use only offsets[0] */
+ i = 0;
+ s = seprint(s, e, "[%d] %#ux cc=%#ux sz=%ud\n", i, td->offsets[i],
+ (td->offsets[i] >> Tdiccshift) & Tdiccmask,
+ td->offsets[i] & 0x7FF);
+ return s;
+}
+
+static void
+dumptd(Td *td, char *p, int iso)
+{
+ static char buf[512]; /* Too much */
+ char *s;
+
+ s = seprint(buf, buf+sizeof(buf), "%s: ", p);
+ s = seprinttd(s, buf+sizeof(buf), td, iso);
+ if(s > buf && s[-1] != '\n')
+ s[-1] = '\n';
+ print("\t%s", buf);
+}
+
+static void
+dumptds(Td *td, char *p, int iso)
+{
+ int i;
+
+ for(i = 0; td != nil; td = td->next){
+ dumptd(td, p, iso);
+ if(td->last)
+ break;
+ if(tdtok(td) == Tdtokin && ++i > 2){
+ print("\t\t...\n");
+ break;
+ }
+ }
+}
+
+static void
+dumped(Ed *ed)
+{
+ char *buf, *s, *e;
+
+ if(ed == nil){
+ print("<null ed>\n");
+ return;
+ }
+ buf = malloc(512);
+ /* no waserror; may want to use from interrupt context */
+ if(buf == nil)
+ return;
+ e = buf+512;
+ s = seprint(buf, e, "\ted %#p: ctrl %#p", ed, ed->ctrl);
+ if((ed->ctrl & Edskip) != 0)
+ s = seprint(s, e, " skip");
+ if((ed->ctrl & Ediso) != 0)
+ s = seprint(s, e, " iso");
+ if((ed->ctrl & Edlow) != 0)
+ s = seprint(s, e, " low");
+ s = seprint(s, e, " d%d", (ed->head & Edtoggle) ? 1 : 0);
+ if((ed->ctrl & Eddirmask) == Edin)
+ s = seprint(s, e, " in");
+ if((ed->ctrl & Eddirmask) == Edout)
+ s = seprint(s, e, " out");
+ if(edhalted(ed))
+ s = seprint(s, e, " hlt");
+ s = seprint(s, e, " ep%uld.%uld", (ed->ctrl>>7)&Epmax, ed->ctrl&0x7f);
+ s = seprint(s, e, " maxpkt %uld", (ed->ctrl>>Edmpsshift)&Edmpsmask);
+ seprint(s, e, " tail %#p head %#p next %#p\n",ed->tail,ed->head,ed->nexted);
+ print("%s", buf);
+ free(buf);
+ if(ed->tds != nil && (ed->ctrl & Ediso) == 0)
+ dumptds(ed->tds, "td", 0);
+}
+
+static char*
+seprintio(char *s, char *e, Qio *io, char *pref)
+{
+ s = seprint(s, e, "%s qio %#p ed %#p", pref, io, io->ed);
+ s = seprint(s, e, " tog %d iot %ld err %s id %#ulx",
+ io->toggle, io->iotime, io->err, io->usbid);
+ s = seprinttdtok(s, e, io->tok);
+ s = seprint(s, e, " %s\n", iosname[io->state]);
+ return s;
+}
+
+static char*
+seprintep(char* s, char* e, Ep *ep)
+{
+ Isoio *iso;
+ Qio *io;
+ Ctlio *cio;
+
+ if(ep == nil)
+ return seprint(s, e, "<nil ep>\n");
+ if(ep->aux == nil)
+ return seprint(s, e, "no mdep\n");
+ switch(ep->ttype){
+ case Tctl:
+ cio = ep->aux;
+ s = seprintio(s, e, cio, "c");
+ s = seprint(s, e, "\trepl %d ndata %d\n", ep->rhrepl, cio->ndata);
+ break;
+ case Tbulk:
+ case Tintr:
+ io = ep->aux;
+ if(ep->mode != OWRITE)
+ s = seprintio(s, e, &io[OREAD], "r");
+ if(ep->mode != OREAD)
+ s = seprintio(s, e, &io[OWRITE], "w");
+ break;
+ case Tiso:
+ iso = ep->aux;
+ s = seprintio(s, e, iso, "w");
+ s = seprint(s, e, "\tntds %d avail %d frno %uld left %uld next avail %#p\n",
+ iso->nframes, iso->navail, iso->frno, iso->left, iso->atds);
+ break;
+ }
+ return s;
+}
+
+static char*
+seprintctl(char *s, char *se, ulong ctl)
+{
+ s = seprint(s, se, "en=");
+ if((ctl&Cple) != 0)
+ s = seprint(s, se, "p");
+ if((ctl&Cie) != 0)
+ s = seprint(s, se, "i");
+ if((ctl&Ccle) != 0)
+ s = seprint(s, se, "c");
+ if((ctl&Cble) != 0)
+ s = seprint(s, se, "b");
+ switch(ctl & Cfsmask){
+ case Cfsreset:
+ return seprint(s, se, " reset");
+ case Cfsresume:
+ return seprint(s, se, " resume");
+ case Cfsoper:
+ return seprint(s, se, " run");
+ case Cfssuspend:
+ return seprint(s, se, " suspend");
+ default:
+ return seprint(s, se, " ???");
+ }
+}
+
+static void
+dump(Hci *hp)
+{
+ Ctlr *ctlr;
+ Ed *ed;
+ char cs[20];
+
+ ctlr = hp->aux;
+ ilock(ctlr);
+ seprintctl(cs, cs+sizeof(cs), ctlr->ohci->control);
+ print("ohci ctlr %#p: frno %#ux ctl %#lux %s sts %#lux intr %#lux\n",
+ ctlr, ctlr->hcca->framenumber, ctlr->ohci->control, cs,
+ ctlr->ohci->cmdsts, ctlr->ohci->intrsts);
+ print("ctlhd %#ulx cur %#ulx bulkhd %#ulx cur %#ulx done %#ulx\n",
+ ctlr->ohci->ctlheaded, ctlr->ohci->ctlcurred,
+ ctlr->ohci->bulkheaded, ctlr->ohci->bulkcurred,
+ ctlr->ohci->donehead);
+ if(ctlhd(ctlr) != nil)
+ print("[ctl]\n");
+ for(ed = ctlhd(ctlr); ed != nil; ed = ed->next)
+ dumped(ed);
+ if(bulkhd(ctlr) != nil)
+ print("[bulk]\n");
+ for(ed = bulkhd(ctlr); ed != nil; ed = ed->next)
+ dumped(ed);
+ if(ctlr->intrhd != nil)
+ print("[intr]\n");
+ for(ed = ctlr->intrhd; ed != nil; ed = ed->inext)
+ dumped(ed);
+ if(ctlr->tree->root[0]->next != nil)
+ print("[iso]");
+ for(ed = ctlr->tree->root[0]->next; ed != nil; ed = ed->next)
+ dumped(ed);
+ print("%d eds in tree\n", ctlr->ntree);
+ iunlock(ctlr);
+ lock(&tdpool);
+ print("%d tds allocated = %d in use + %d free\n",
+ tdpool.nalloc, tdpool.ninuse, tdpool.nfree);
+ unlock(&tdpool);
+ lock(&edpool);
+ print("%d eds allocated = %d in use + %d free\n",
+ edpool.nalloc, edpool.ninuse, edpool.nfree);
+ unlock(&edpool);
+}
+
+/*
+ * Compute size for the next iso Td and setup its
+ * descriptor for I/O according to the buffer size.
+ */
+static void
+isodtdinit(Ep *ep, Isoio *iso, Td *td)
+{
+ Block *bp;
+ long size;
+ int i;
+
+ bp = td->bp;
+ assert(bp != nil && BLEN(bp) == 0);
+ size = (ep->hz+iso->left) * ep->pollival / 1000;
+ iso->left = (ep->hz+iso->left) * ep->pollival % 1000;
+ size *= ep->samplesz;
+ if(size > ep->maxpkt){
+ print("ohci: ep%d.%d: size > maxpkt\n",
+ ep->dev->nb, ep->nb);
+ print("size = %uld max = %ld\n", size, ep->maxpkt);
+ size = ep->maxpkt;
+ }
+ td->nbytes = size;
+ memset(bp->wp, 0, size); /* in case we don't fill it on time */
+ td->cbp0 = td->cbp = ptr2pa(bp->rp) & ~0xFFF;
+ td->ctrl = TRUNC(iso->frno, Ntdframes);
+ td->offsets[0] = (ptr2pa(bp->rp) & 0xFFF);
+ td->offsets[0] |= (Tdnotacc << Tdiccshift);
+ /* in case the controller checks out the offests... */
+ for(i = 1; i < nelem(td->offsets); i++)
+ td->offsets[i] = td->offsets[0];
+ td->be = ptr2pa(bp->rp + size - 1);
+ td->ctrl |= (0 << Tdfcshift); /* frame count is 1 */
+
+ iso->frno = TRUNC(iso->frno + ep->pollival, Ntdframes);
+}
+
+/*
+ * start I/O on the dummy td and setup a new dummy to fill up.
+ */
+static void
+isoadvance(Ep *ep, Isoio *iso, Td *td)
+{
+ Td *dtd;
+
+ dtd = iso->atds;
+ iso->atds = dtd->anext;
+ iso->navail--;
+ dtd->anext = nil;
+ dtd->bp->wp = dtd->bp->rp;
+ dtd->nexttd = 0;
+ td->nexttd = ptr2pa(dtd);
+ isodtdinit(ep, iso, dtd);
+ iso->ed->tail = ptr2pa(dtd);
+}
+
+static int
+isocanwrite(void *a)
+{
+ Isoio *iso;
+
+ iso = a;
+ return iso->state == Qclose || iso->err != nil ||
+ iso->navail > iso->nframes / 2;
+}
+
+/*
+ * Service a completed/failed Td from the done queue.
+ * It may be of any transfer type.
+ * The queue is not in completion order.
+ * (It's actually in reverse completion order).
+ *
+ * When an error, a short packet, or a last Td is found
+ * we awake the process waiting for the transfer.
+ * Although later we will process other Tds completed
+ * before, epio won't be able to touch the current Td
+ * until interrupt returns and releases the lock on the
+ * controller.
+ */
+static void
+qhinterrupt(Ctlr *, Ep *ep, Qio *io, Td *td, int)
+{
+ Block *bp;
+ int mode, err;
+ Ed *ed;
+
+ ed = io->ed;
+ if(io->state != Qrun)
+ return;
+ if(tdtok(td) == Tdtokin)
+ mode = OREAD;
+ else
+ mode = OWRITE;
+ bp = td->bp;
+ err = tderrs(td);
+
+ switch(err){
+ case Tddataovr: /* Overrun is not an error */
+ case Tdok:
+ /* can't make this assertion in virtualbox */
+// if(td->cbp != 0)
+// panic("ohci: full packet but cbp != 0");
+ break;
+ case Tddataund:
+ /* short input packets are ok */
+ if(mode == OREAD){
+ if(td->cbp == 0)
+ panic("ohci: short packet but cbp == 0");
+ /*
+ * td->cbp and td->cbp0 are the real addresses
+ * corresponding to virtual addresses bp->wp and
+ * bp->rp respectively.
+ */
+ bp->wp = bp->rp + (td->cbp - td->cbp0);
+ if(bp->wp < bp->rp)
+ panic("ohci: wp < rp");
+ /*
+ * It's ok. clear error and flag as last in xfer.
+ * epio must ignore following Tds.
+ */
+ td->last = 1;
+ td->ctrl &= ~(Tdccmask << Tdccshift);
+ break;
+ }
+ /* else fall; it's an error */
+ case Tdcrc:
+ case Tdbitstuff:
+ case Tdbadtog:
+ case Tdstalled:
+ case Tdtmout:
+ case Tdpidchk:
+ case Tdbadpid:
+ bp->wp = bp->rp; /* no bytes in xfer. */
+ io->err = errmsg(err);
+ if(debug || ep->debug){
+ print("tdinterrupt: failed err %d (%s)\n", err, io->err);
+ dumptd(td, "failed", ed->ctrl & Ediso);
+ }
+ td->last = 1;
+ break;
+ default:
+ panic("ohci: td cc %ud unknown", err);
+ }
+
+ if(td->last != 0){
+ /*
+ * clear td list and halt flag.
+ */
+ ed->head = (ed->head & Edtoggle) | ed->tail;
+ ed->tds = pa2ptr(ed->tail);
+ io->state = Qdone;
+ wakeup(io);
+ }
+}
+
+/*
+ * BUG: Iso input streams are not implemented.
+ */
+static void
+isointerrupt(Ctlr *ctlr, Ep *ep, Qio *io, Td *td, int)
+{
+ Isoio *iso;
+ Block *bp;
+ Ed *ed;
+ int err, isoerr;
+
+ iso = ep->aux;
+ ed = io->ed;
+ if(io->state == Qclose)
+ return;
+ bp = td->bp;
+ /*
+ * When we get more than half the frames consecutive errors
+ * we signal an actual error. Errors in the entire Td are
+ * more serious and are always singaled.
+ * Errors like overrun are not really errors. In fact, for
+ * output, errors cannot be really detected. The driver will
+ * hopefully notice I/O errors on input endpoints and detach the device.
+ */
+ err = tderrs(td);
+ isoerr = (td->offsets[0] >> Tdiccshift) & Tdiccmask;
+ if(isoerr == Tdok || isoerr == Tdnotacc)
+ iso->nerrs = 0;
+ else if(iso->nerrs++ > iso->nframes/2)
+ err = Tdstalled;
+ if(err != Tdok && err != Tddataovr){
+ bp->wp = bp->rp;
+ io->err = errmsg(err);
+ if(debug || ep->debug){
+ print("ohci: isointerrupt: ep%d.%d: err %d (%s) frnum 0x%lux\n",
+ ep->dev->nb, ep->nb,
+ err, errmsg(err), ctlr->ohci->fmnumber);
+ dumptd(td, "failed", ed->ctrl & Ediso);
+ }
+ }
+ td->bp->wp = td->bp->rp;
+ td->nbytes = 0;
+ td->anext = iso->atds;
+ iso->atds = td;
+ iso->navail++;
+ /*
+ * If almost all Tds are avail the user is not doing I/O at the
+ * required rate. We put another Td in place to keep the polling rate.
+ */
+ if(iso->err == nil && iso->navail > iso->nframes - 10)
+ isoadvance(ep, iso, pa2ptr(iso->ed->tail));
+ /*
+ * If there's enough buffering futher I/O can be done.
+ */
+ if(isocanwrite(iso))
+ wakeup(iso);
+}
+
+static void
+interrupt(Ureg *, void *arg)
+{
+ Td *td, *ntd, *td0;
+ Hci *hp;
+ Ctlr *ctlr;
+ ulong status, curred;
+ int i, frno;
+
+ hp = arg;
+ ctlr = hp->aux;
+ ilock(ctlr);
+ status = ctlr->ohci->intrsts;
+ status &= ctlr->ohci->intrenable;
+ status &= Oc|Rhsc|Fno|Ue|Rd|Sf|Wdh|So;
+ frno = TRUNC(ctlr->ohci->fmnumber, Ntdframes);
+ if((status & Wdh) != 0){
+ /* lsb of donehead has bit to flag other intrs. */
+ td = pa2ptr(ctlr->hcca->donehead & ~0xF);
+ }else
+ td = nil;
+ td0 = td;
+
+ for(i = 0; td != nil && i < 1024; i++){
+ if(0)ddprint("ohci tdinterrupt: td %#p\n", td);
+ ntd = pa2ptr(td->nexttd & ~0xF);
+ td->nexttd = 0;
+ if(td->ep == nil || td->io == nil)
+ panic("ohci: interrupt: ep %#p io %#p", td->ep, td->io);
+ ohciinterrupts[td->ep->ttype]++;
+ if(td->ep->ttype == Tiso)
+ isointerrupt(ctlr, td->ep, td->io, td, frno);
+ else
+ qhinterrupt(ctlr, td->ep, td->io, td, frno);
+ td = ntd;
+ }
+ if(i == 1024)
+ print("ohci: bug: more than 1024 done Tds?\n");
+
+ if(pa2ptr(ctlr->hcca->donehead & ~0xF) != td0)
+ print("ohci: bug: donehead changed before ack\n");
+ ctlr->hcca->donehead = 0;
+
+ ctlr->ohci->intrsts = status;
+ status &= ~Wdh;
+ status &= ~Sf;
+ if(status & So){
+ print("ohci: sched overrun: too much load\n");
+ ctlr->overrun++;
+ status &= ~So;
+ }
+ if((status & Ue) != 0){
+ curred = ctlr->ohci->periodcurred;
+ print("ohci: unrecoverable error frame 0x%.8lux ed 0x%.8lux, "
+ "ints %d %d %d %d\n",
+ ctlr->ohci->fmnumber, curred,
+ ohciinterrupts[Tctl], ohciinterrupts[Tintr],
+ ohciinterrupts[Tbulk], ohciinterrupts[Tiso]);
+ if(curred != 0)
+ dumped(pa2ptr(curred));
+ status &= ~Ue;
+ }
+ if(status != 0)
+ print("ohci interrupt: unhandled sts 0x%.8lux\n", status);
+ iunlock(ctlr);
+}
+
+/*
+ * The old dummy Td is used to implement the new Td.
+ * A new dummy is linked at the end of the old one and
+ * returned, to link further Tds if needed.
+ */
+static Td*
+epgettd(Ep *ep, Qio *io, Td **dtdp, int flags, void *a, int count)
+{
+ Td *td, *dtd;
+ Block *bp;
+
+ if(ep->maxpkt > 0x2000)
+ panic("ohci: max packet > two pages");
+ if(ep->maxpkt < count)
+ error("maxpkt too short");
+ bp = allocb(ep->maxpkt); /* panics if no mem */
+ assert(bp != nil);
+ dtd = *dtdp;
+ td = dtd;
+ td->bp = bp;
+ if(count > 0){
+ td->cbp0 = td->cbp = ptr2pa(bp->wp);
+ td->be = ptr2pa(bp->wp + count - 1);
+ if(a != nil){
+ /* validaddr((uintptr)a, count, 0); DEBUG */
+ assert(bp != nil);
+ assert(bp->wp != nil);
+ memmove(bp->wp, a, count);
+ }
+ bp->wp += count;
+ }
+ td->nbytes = count;
+ td->ctrl = io->tok|Tdusetog|io->toggle|flags;
+ if(io->toggle == Tddata0)
+ io->toggle = Tddata1;
+ else
+ io->toggle = Tddata0;
+ assert(td->ep == ep);
+ td->io = io;
+ dtd = tdalloc(); /* new dummy */
+ dtd->ep = ep;
+ td->nexttd = ptr2pa(dtd);
+ td->next = dtd;
+ *dtdp = dtd;
+ return td;
+}
+
+/*
+ * Try to get them idle
+ */
+static void
+aborttds(Qio *io)
+{
+ Ed *ed;
+ Td *td;
+
+ ed = io->ed;
+ if(ed == nil)
+ return;
+ ed->ctrl |= Edskip;
+ for(td = ed->tds; td != nil; td = td->next)
+ if(td->bp != nil)
+ td->bp->wp = td->bp->rp;
+ ed->head = (ed->head&0xF) | ed->tail;
+ if((ed->ctrl & Ediso) == 0)
+ ed->tds = pa2ptr(ed->tail);
+}
+
+static int
+epiodone(void *a)
+{
+ Qio *io;
+
+ io = a;
+ return io->state != Qrun;
+}
+
+static void
+epiowait(Ctlr *ctlr, Qio *io, int tmout, ulong)
+{
+ Ed *ed;
+ int timedout;
+
+ ed = io->ed;
+ if(0)ddqprint("ohci io %#p sleep on ed %#p state %s\n",
+ io, ed, iosname[io->state]);
+ timedout = 0;
+ if(waserror()){
+ dqprint("ohci io %#p ed %#p timed out\n", io, ed);
+ timedout++;
+ }else{
+ if(tmout == 0)
+ sleep(io, epiodone, io);
+ else
+ tsleep(io, epiodone, io, tmout);
+ poperror();
+ }
+ ilock(ctlr);
+ if(io->state == Qrun)
+ timedout = 1;
+ else if(io->state != Qdone && io->state != Qclose)
+ panic("epio: ed not done and not closed");
+ if(timedout){
+ aborttds(io);
+ io->err = "request timed out";
+ iunlock(ctlr);
+ if(!waserror()){
+ tsleep(&up->sleep, return0, 0, Abortdelay);
+ poperror();
+ }
+ ilock(ctlr);
+ }
+ if(io->state != Qclose)
+ io->state = Qidle;
+ iunlock(ctlr);
+}
+
+/*
+ * Non iso I/O.
+ * To make it work for control transfers, the caller may
+ * lock the Qio for the entire control transfer.
+ */
+static long
+epio(Ep *ep, Qio *io, void *a, long count, int mustlock)
+{
+ Ed *ed;
+ Ctlr *ctlr;
+ char buf[80];
+ char *err;
+ uchar *c;
+ Td *td, *ltd, *ntd, *td0;
+ int last, ntds, tmout;
+ long tot, n;
+ ulong load;
+
+ ed = io->ed;
+ ctlr = ep->hp->aux;
+ io->debug = ep->debug;
+ tmout = ep->tmout;
+ ddeprint("ohci: %s ep%d.%d io %#p count %ld\n",
+ io->tok == Tdtokin ? "in" : "out",
+ ep->dev->nb, ep->nb, io, count);
+ if((debug > 1 || ep->debug > 1) && io->tok != Tdtokin){
+ seprintdata(buf, buf+sizeof(buf), a, count);
+ print("\t%s\n", buf);
+ }
+ if(mustlock){
+ qlock(io);
+ if(waserror()){
+ qunlock(io);
+ nexterror();
+ }
+ }
+ io->err = nil;
+ ilock(ctlr);
+ if(io->state == Qclose){ /* Tds released by cancelio */
+ iunlock(ctlr);
+ error(io->err ? io->err : Eio);
+ }
+ if(io->state != Qidle)
+ panic("epio: qio not idle");
+ io->state = Qinstall;
+
+ c = a;
+ ltd = td0 = ed->tds;
+ load = tot = 0;
+ do{
+ n = ep->maxpkt;
+ if(count-tot < n)
+ n = count-tot;
+ if(c != nil && io->tok != Tdtokin)
+ td = epgettd(ep, io, &ltd, 0, c+tot, n);
+ else
+ td = epgettd(ep, io, &ltd, 0, nil, n);
+ tot += n;
+ load += ep->load;
+ }while(tot < count);
+ if(td0 == nil || ltd == nil || td0 == ltd)
+ panic("epio: no td");
+ td->last = 1;
+ if(debug > 2 || ep->debug > 2)
+ dumptds(td0, "put td", ep->ttype == Tiso);
+ iunlock(ctlr);
+
+ ilock(ctlr);
+ if(io->state != Qclose){
+ io->iotime = TK2MS(MACHP(0)->ticks);
+ io->state = Qrun;
+ ed->tail = ptr2pa(ltd);
+ if(ep->ttype == Tctl)
+ ctlr->ohci->cmdsts |= Sclf;
+ else if(ep->ttype == Tbulk)
+ ctlr->ohci->cmdsts |= Sblf;
+ }
+ iunlock(ctlr);
+
+ epiowait(ctlr, io, tmout, load);
+ ilock(ctlr);
+ if(debug > 1 || ep->debug > 1)
+ dumptds(td0, "got td", 0);
+ iunlock(ctlr);
+
+ tot = 0;
+ c = a;
+ ntds = last = 0;
+ for(td = td0; td != ltd; td = ntd){
+ ntds++;
+ /*
+ * If the Td is flagged as last we must
+ * ignore any following Td. The block may
+ * seem to have bytes but interrupt has not seen
+ * those Tds through the done queue, and they are void.
+ */
+ if(last == 0 && tderrs(td) == Tdok){
+ n = BLEN(td->bp);
+ tot += n;
+ if(c != nil && tdtok(td) == Tdtokin && n > 0){
+ memmove(c, td->bp->rp, n);
+ c += n;
+ }
+ }
+ last |= td->last;
+ ntd = td->next;
+ tdfree(td);
+ }
+ if(edtoggle(ed) == 0)
+ io->toggle = Tddata0;
+ else
+ io->toggle = Tddata1;
+
+ err = io->err;
+ if(mustlock){
+ qunlock(io);
+ poperror();
+ }
+ ddeprint("ohci: io %#p: %d tds: return %ld err '%s'\n\n",
+ io, ntds, tot, err);
+ if(err != nil)
+ error(err);
+ if(tot < 0)
+ error(Eio);
+ return tot;
+}
+
+/*
+ * halt condition was cleared on the endpoint. update our toggles.
+ */
+static void
+clrhalt(Ep *ep)
+{
+ Qio *io;
+
+ ep->clrhalt = 0;
+ switch(ep->ttype){
+ case Tbulk:
+ case Tintr:
+ io = ep->aux;
+ if(ep->mode != OREAD){
+ qlock(&io[OWRITE]);
+ io[OWRITE].toggle = Tddata0;
+ deprint("ep clrhalt for io %#p\n", io+OWRITE);
+ qunlock(&io[OWRITE]);
+ }
+ if(ep->mode != OWRITE){
+ qlock(&io[OREAD]);
+ io[OREAD].toggle = Tddata0;
+ deprint("ep clrhalt for io %#p\n", io+OREAD);
+ qunlock(&io[OREAD]);
+ }
+ break;
+ }
+}
+
+static long
+epread(Ep *ep, void *a, long count)
+{
+ Ctlio *cio;
+ Qio *io;
+ char buf[80];
+ ulong delta;
+
+ if(ep->aux == nil)
+ panic("epread: not open");
+
+ switch(ep->ttype){
+ case Tctl:
+ cio = ep->aux;
+ qlock(cio);
+ if(waserror()){
+ qunlock(cio);
+ nexterror();
+ }
+ ddeprint("epread ctl ndata %d\n", cio->ndata);
+ if(cio->ndata < 0)
+ error("request expected");
+ else if(cio->ndata == 0){
+ cio->ndata = -1;
+ count = 0;
+ }else{
+ if(count > cio->ndata)
+ count = cio->ndata;
+ if(count > 0)
+ memmove(a, cio->data, count);
+ /* BUG for big transfers */
+ free(cio->data);
+ cio->data = nil;
+ cio->ndata = 0; /* signal EOF next time */
+ }
+ qunlock(cio);
+ poperror();
+ if(debug>1 || ep->debug){
+ seprintdata(buf, buf+sizeof(buf), a, count);
+ print("epread: %s\n", buf);
+ }
+ return count;
+ case Tbulk:
+ io = ep->aux;
+ if(ep->clrhalt)
+ clrhalt(ep);
+ return epio(ep, &io[OREAD], a, count, 1);
+ case Tintr:
+ io = ep->aux;
+ delta = TK2MS(MACHP(0)->ticks) - io[OREAD].iotime + 1;
+ if(delta < ep->pollival / 2)
+ tsleep(&up->sleep, return0, 0, ep->pollival/2 - delta);
+ if(ep->clrhalt)
+ clrhalt(ep);
+ return epio(ep, &io[OREAD], a, count, 1);
+ case Tiso:
+ panic("ohci: iso read not implemented");
+ break;
+ default:
+ panic("epread: bad ep ttype %d", ep->ttype);
+ }
+ return -1;
+}
+
+/*
+ * Control transfers are one setup write (data0)
+ * plus zero or more reads/writes (data1, data0, ...)
+ * plus a final write/read with data1 to ack.
+ * For both host to device and device to host we perform
+ * the entire transfer when the user writes the request,
+ * and keep any data read from the device for a later read.
+ * We call epio three times instead of placing all Tds at
+ * the same time because doing so leads to crc/tmout errors
+ * for some devices.
+ * Upon errors on the data phase we must still run the status
+ * phase or the device may cease responding in the future.
+ */
+static long
+epctlio(Ep *ep, Ctlio *cio, void *a, long count)
+{
+ uchar *c;
+ long len;
+
+ ddeprint("epctlio: cio %#p ep%d.%d count %ld\n",
+ cio, ep->dev->nb, ep->nb, count);
+ if(count < Rsetuplen)
+ error("short usb command");
+ qlock(cio);
+ free(cio->data);
+ cio->data = nil;
+ cio->ndata = 0;
+ if(waserror()){
+ qunlock(cio);
+ free(cio->data);
+ cio->data = nil;
+ cio->ndata = 0;
+ nexterror();
+ }
+
+ /* set the address if unset and out of configuration state */
+ if(ep->dev->state != Dconfig && ep->dev->state != Dreset)
+ if(cio->usbid == 0){
+ cio->usbid = (ep->nb<<7)|(ep->dev->nb & Devmax);
+ edsetaddr(cio->ed, cio->usbid);
+ }
+ /* adjust maxpkt if the user has learned a different one */
+ if(edmaxpkt(cio->ed) != ep->maxpkt)
+ edsetmaxpkt(cio->ed, ep->maxpkt);
+ c = a;
+ cio->tok = Tdtoksetup;
+ cio->toggle = Tddata0;
+ if(epio(ep, cio, a, Rsetuplen, 0) < Rsetuplen)
+ error(Eio);
+
+ a = c + Rsetuplen;
+ count -= Rsetuplen;
+
+ cio->toggle = Tddata1;
+ if(c[Rtype] & Rd2h){
+ cio->tok = Tdtokin;
+ len = GET2(c+Rcount);
+ if(len <= 0)
+ error("bad length in d2h request");
+ if(len > Maxctllen)
+ error("d2h data too large to fit in ohci");
+ a = cio->data = smalloc(len+1);
+ }else{
+ cio->tok = Tdtokout;
+ len = count;
+ }
+ if(len > 0)
+ if(waserror())
+ len = -1;
+ else{
+ len = epio(ep, cio, a, len, 0);
+ poperror();
+ }
+ if(c[Rtype] & Rd2h){
+ count = Rsetuplen;
+ cio->ndata = len;
+ cio->tok = Tdtokout;
+ }else{
+ if(len < 0)
+ count = -1;
+ else
+ count = Rsetuplen + len;
+ cio->tok = Tdtokin;
+ }
+ cio->toggle = Tddata1;
+ epio(ep, cio, nil, 0, 0);
+ qunlock(cio);
+ poperror();
+ ddeprint("epctlio cio %#p return %ld\n", cio, count);
+ return count;
+}
+
+/*
+ * Put new samples in the dummy Td.
+ * BUG: This does only a transfer per Td. We could do up to 8.
+ */
+static long
+putsamples(Ctlr *ctlr, Ep *ep, Isoio *iso, uchar *b, long count)
+{
+ Td *td;
+ ulong n;
+
+ td = pa2ptr(iso->ed->tail);
+ n = count;
+ if(n > td->nbytes - BLEN(td->bp))
+ n = td->nbytes - BLEN(td->bp);
+ assert(td->bp->wp + n <= td->bp->lim);
+ memmove(td->bp->wp, b, n);
+ td->bp->wp += n;
+ if(BLEN(td->bp) == td->nbytes){ /* full Td: activate it */
+ ilock(ctlr);
+ isoadvance(ep, iso, td);
+ iunlock(ctlr);
+ }
+ return n;
+}
+
+static long
+episowrite(Ep *ep, void *a, long count)
+{
+ long tot, nw;
+ char *err;
+ uchar *b;
+ Ctlr *ctlr;
+ Isoio *iso;
+
+ ctlr = ep->hp->aux;
+ iso = ep->aux;
+ iso->debug = ep->debug;
+
+ qlock(iso);
+ if(waserror()){
+ qunlock(iso);
+ nexterror();
+ }
+ diprint("ohci: episowrite: %#p ep%d.%d\n", iso, ep->dev->nb, ep->nb);
+ ilock(ctlr);
+ if(iso->state == Qclose){
+ iunlock(ctlr);
+ error(iso->err ? iso->err : Eio);
+ }
+ iso->state = Qrun;
+ b = a;
+ for(tot = 0; tot < count; tot += nw){
+ while(isocanwrite(iso) == 0){
+ iunlock(ctlr);
+ diprint("ohci: episowrite: %#p sleep\n", iso);
+ if(waserror()){
+ if(iso->err == nil)
+ iso->err = "I/O timed out";
+ ilock(ctlr);
+ break;
+ }
+ tsleep(iso, isocanwrite, iso, ep->tmout);
+ poperror();
+ ilock(ctlr);
+ }
+ err = iso->err;
+ iso->err = nil;
+ if(iso->state == Qclose || err != nil){
+ iunlock(ctlr);
+ error(err ? err : Eio);
+ }
+ if(iso->state != Qrun)
+ panic("episowrite: iso not running");
+ iunlock(ctlr); /* We could page fault here */
+ nw = putsamples(ctlr, ep, iso, b+tot, count-tot);
+ ilock(ctlr);
+ }
+ if(iso->state != Qclose)
+ iso->state = Qdone;
+ iunlock(ctlr);
+ err = iso->err; /* in case it failed early */
+ iso->err = nil;
+ qunlock(iso);
+ poperror();
+ if(err != nil)
+ error(err);
+ diprint("ohci: episowrite: %#p %ld bytes\n", iso, tot);
+ return tot;
+}
+
+static long
+epwrite(Ep *ep, void *a, long count)
+{
+ Qio *io;
+ Ctlio *cio;
+ ulong delta;
+ uchar *b;
+ long tot, nw;
+
+ if(ep->aux == nil)
+ panic("ohci: epwrite: not open");
+ switch(ep->ttype){
+ case Tctl:
+ cio = ep->aux;
+ return epctlio(ep, cio, a, count);
+ case Tbulk:
+ io = ep->aux;
+ if(ep->clrhalt)
+ clrhalt(ep);
+ /*
+ * Put at most Tdatomic Tds (512 bytes) at a time.
+ * Otherwise some devices produce babble errors.
+ */
+ b = a;
+ assert(a != nil);
+ for(tot = 0; tot < count ; tot += nw){
+ nw = count - tot;
+ if(nw > Tdatomic * ep->maxpkt)
+ nw = Tdatomic * ep->maxpkt;
+ nw = epio(ep, &io[OWRITE], b+tot, nw, 1);
+ }
+ return tot;
+ case Tintr:
+ io = ep->aux;
+ delta = TK2MS(MACHP(0)->ticks) - io[OWRITE].iotime + 1;
+ if(delta < ep->pollival)
+ tsleep(&up->sleep, return0, 0, ep->pollival - delta);
+ if(ep->clrhalt)
+ clrhalt(ep);
+ return epio(ep, &io[OWRITE], a, count, 1);
+ case Tiso:
+ return episowrite(ep, a, count);
+ default:
+ panic("ohci: epwrite: bad ep ttype %d", ep->ttype);
+ }
+ return -1;
+}
+
+static Ed*
+newed(Ctlr *ctlr, Ep *ep, Qio *io, char *)
+{
+ Ed *ed;
+ Td *td;
+
+ ed = io->ed = edalloc(); /* no errors raised here, really */
+ td = tdalloc();
+ td->ep = ep;
+ td->io = io;
+ ed->tail = ptr2pa(td);
+ ed->head = ptr2pa(td);
+ ed->tds = td;
+ ed->ep = ep;
+ ed->ctrl = (ep->maxpkt & Edmpsmask) << Edmpsshift;
+ if(ep->ttype == Tiso)
+ ed->ctrl |= Ediso;
+ if(waserror()){
+ edfree(ed);
+ io->ed = nil;
+ nexterror();
+ }
+ /* For setup endpoints we start with the config address */
+ if(ep->ttype != Tctl)
+ edsetaddr(io->ed, io->usbid);
+ if(ep->dev->speed == Lowspeed)
+ ed->ctrl |= Edlow;
+ switch(io->tok){
+ case Tdtokin:
+ ed->ctrl |= Edin;
+ break;
+ case Tdtokout:
+ ed->ctrl |= Edout;
+ break;
+ default:
+ ed->ctrl |= Edtddir; /* Td will say */
+ break;
+ }
+
+ switch(ep->ttype){
+ case Tctl:
+ ilock(ctlr);
+ edlinked(ed, ctlhd(ctlr));
+ setctlhd(ctlr, ed);
+ iunlock(ctlr);
+ break;
+ case Tbulk:
+ ilock(ctlr);
+ edlinked(ed, bulkhd(ctlr));
+ setbulkhd(ctlr, ed);
+ iunlock(ctlr);
+ break;
+ case Tintr:
+ case Tiso:
+ ilock(ctlr);
+ schedq(ctlr, io, ep->pollival);
+ iunlock(ctlr);
+ break;
+ default:
+ panic("ohci: newed: bad ttype");
+ }
+ poperror();
+ return ed;
+}
+
+static void
+isoopen(Ctlr *ctlr, Ep *ep)
+{
+ Td *td, *edtds;
+ Isoio *iso;
+ int i;
+
+ iso = ep->aux;
+ iso->usbid = (ep->nb<<7)|(ep->dev->nb & Devmax);
+ iso->bw = ep->hz * ep->samplesz; /* bytes/sec */
+ if(ep->mode != OWRITE){
+ print("ohci: bug: iso input streams not implemented\n");
+ error("ohci iso input streams not implemented");
+ }else
+ iso->tok = Tdtokout;
+
+ iso->left = 0;
+ iso->nerrs = 0;
+ iso->frno = TRUNC(ctlr->ohci->fmnumber + 10, Ntdframes);
+ iso->nframes = 1000 / ep->pollival;
+ if(iso->nframes < 10){
+ print("ohci: isoopen: less than 10 frames; using 10.\n");
+ iso->nframes = 10;
+ }
+ iso->navail = iso->nframes;
+ iso->atds = edtds = nil;
+ for(i = 0; i < iso->nframes-1; i++){ /* -1 for dummy */
+ td = tdalloc();
+ td->ep = ep;
+ td->io = iso;
+ td->bp = allocb(ep->maxpkt);
+ td->anext = iso->atds; /* link as avail */
+ iso->atds = td;
+ td->next = edtds;
+ edtds = td;
+ }
+ newed(ctlr, ep, iso, "iso"); /* allocates a dummy td */
+ iso->ed->tds->bp = allocb(ep->maxpkt); /* but not its block */
+ iso->ed->tds->next = edtds;
+ isodtdinit(ep, iso, iso->ed->tds);
+}
+
+/*
+ * Allocate the endpoint and set it up for I/O
+ * in the controller. This must follow what's said
+ * in Ep regarding configuration, including perhaps
+ * the saved toggles (saved on a previous close of
+ * the endpoint data file by epclose).
+ */
+static void
+epopen(Ep *ep)
+{
+ Ctlr *ctlr;
+ Qio *io;
+ Ctlio *cio;
+ ulong usbid;
+
+ ctlr = ep->hp->aux;
+ deprint("ohci: epopen ep%d.%d\n", ep->dev->nb, ep->nb);
+ if(ep->aux != nil)
+ panic("ohci: epopen called with open ep");
+ if(waserror()){
+ free(ep->aux);
+ ep->aux = nil;
+ nexterror();
+ }
+ switch(ep->ttype){
+ case Tnone:
+ error("endpoint not configured");
+ case Tiso:
+ ep->aux = smalloc(sizeof(Isoio));
+ isoopen(ctlr, ep);
+ break;
+ case Tctl:
+ cio = ep->aux = smalloc(sizeof(Ctlio));
+ cio->debug = ep->debug;
+ cio->ndata = -1;
+ cio->data = nil;
+ cio->tok = -1; /* invalid; Tds will say */
+ if(ep->dev->isroot != 0 && ep->nb == 0) /* root hub */
+ break;
+ newed(ctlr, ep, cio, "epc");
+ break;
+ case Tbulk:
+ ep->pollival = 1; /* assume this; doesn't really matter */
+ /* and fall... */
+ case Tintr:
+ io = ep->aux = smalloc(sizeof(Qio)*2);
+ io[OREAD].debug = io[OWRITE].debug = ep->debug;
+ usbid = (ep->nb<<7)|(ep->dev->nb & Devmax);
+ if(ep->mode != OREAD){
+ if(ep->toggle[OWRITE] != 0)
+ io[OWRITE].toggle = Tddata1;
+ else
+ io[OWRITE].toggle = Tddata0;
+ io[OWRITE].tok = Tdtokout;
+ io[OWRITE].usbid = usbid;
+ io[OWRITE].bw = ep->maxpkt*1000/ep->pollival; /* bytes/s */
+ newed(ctlr, ep, io+OWRITE, "epw");
+ }
+ if(ep->mode != OWRITE){
+ if(ep->toggle[OREAD] != 0)
+ io[OREAD].toggle = Tddata1;
+ else
+ io[OREAD].toggle = Tddata0;
+ io[OREAD].tok = Tdtokin;
+ io[OREAD].usbid = usbid;
+ io[OREAD].bw = ep->maxpkt*1000/ep->pollival; /* bytes/s */
+ newed(ctlr, ep, io+OREAD, "epr");
+ }
+ break;
+ }
+ deprint("ohci: epopen done:\n");
+ if(debug || ep->debug)
+ dump(ep->hp);
+ poperror();
+}
+
+static void
+cancelio(Ep *ep, Qio *io)
+{
+ Ed *ed;
+ Ctlr *ctlr;
+
+ ctlr = ep->hp->aux;
+
+ ilock(ctlr);
+ if(io == nil || io->state == Qclose){
+ assert(io == nil || io->ed == nil);
+ iunlock(ctlr);
+ return;
+ }
+ ed = io->ed;
+ io->state = Qclose;
+ io->err = Eio;
+ aborttds(io);
+ iunlock(ctlr);
+ if(!waserror()){
+ tsleep(&up->sleep, return0, 0, Abortdelay);
+ poperror();
+ }
+
+ wakeup(io);
+ qlock(io);
+ /* wait for epio if running */
+ qunlock(io);
+
+ ilock(ctlr);
+ switch(ep->ttype){
+ case Tctl:
+ unlinkctl(ctlr, ed);
+ break;
+ case Tbulk:
+ unlinkbulk(ctlr, ed);
+ break;
+ case Tintr:
+ case Tiso:
+ unschedq(ctlr, io);
+ break;
+ default:
+ panic("ohci cancelio: bad ttype");
+ }
+ iunlock(ctlr);
+ edfree(io->ed);
+ io->ed = nil;
+}
+
+static void
+epclose(Ep *ep)
+{
+ Ctlio *cio;
+ Isoio *iso;
+ Qio *io;
+
+ deprint("ohci: epclose ep%d.%d\n", ep->dev->nb, ep->nb);
+ if(ep->aux == nil)
+ panic("ohci: epclose called with closed ep");
+ switch(ep->ttype){
+ case Tctl:
+ cio = ep->aux;
+ cancelio(ep, cio);
+ free(cio->data);
+ cio->data = nil;
+ break;
+ case Tbulk:
+ case Tintr:
+ io = ep->aux;
+ if(ep->mode != OWRITE){
+ cancelio(ep, &io[OREAD]);
+ if(io[OREAD].toggle == Tddata1)
+ ep->toggle[OREAD] = 1;
+ }
+ if(ep->mode != OREAD){
+ cancelio(ep, &io[OWRITE]);
+ if(io[OWRITE].toggle == Tddata1)
+ ep->toggle[OWRITE] = 1;
+ }
+ break;
+ case Tiso:
+ iso = ep->aux;
+ cancelio(ep, iso);
+ break;
+ default:
+ panic("epclose: bad ttype %d", ep->ttype);
+ }
+
+ deprint("ohci: epclose ep%d.%d: done\n", ep->dev->nb, ep->nb);
+ free(ep->aux);
+ ep->aux = nil;
+}
+
+static int
+portreset(Hci *hp, int port, int on)
+{
+ Ctlr *ctlr;
+ Ohci *ohci;
+
+ if(on == 0)
+ return 0;
+
+ ctlr = hp->aux;
+ qlock(&ctlr->resetl);
+ if(waserror()){
+ qunlock(&ctlr->resetl);
+ nexterror();
+ }
+ ilock(ctlr);
+ ohci = ctlr->ohci;
+ ohci->rhportsts[port - 1] = Spp;
+ if((ohci->rhportsts[port - 1] & Ccs) == 0){
+ iunlock(ctlr);
+ error("port not connected");
+ }
+ ohci->rhportsts[port - 1] = Spr;
+ while((ohci->rhportsts[port - 1] & Prsc) == 0){
+ iunlock(ctlr);
+ dprint("ohci: portreset, wait for reset complete\n");
+ ilock(ctlr);
+ }
+ ohci->rhportsts[port - 1] = Prsc;
+ iunlock(ctlr);
+ poperror();
+ qunlock(&ctlr->resetl);
+ return 0;
+}
+
+static int
+portenable(Hci *hp, int port, int on)
+{
+ Ctlr *ctlr;
+
+ ctlr = hp->aux;
+ dprint("ohci: %#p port %d enable=%d\n", ctlr->ohci, port, on);
+ qlock(&ctlr->resetl);
+ if(waserror()){
+ qunlock(&ctlr->resetl);
+ nexterror();
+ }
+ ilock(ctlr);
+ if(on)
+ ctlr->ohci->rhportsts[port - 1] = Spe | Spp;
+ else
+ ctlr->ohci->rhportsts[port - 1] = Cpe;
+ iunlock(ctlr);
+ tsleep(&up->sleep, return0, 0, Enabledelay);
+ poperror();
+ qunlock(&ctlr->resetl);
+ return 0;
+}
+
+static int
+portstatus(Hci *hp, int port)
+{
+ int v;
+ Ctlr *ub;
+ ulong ohcistatus;
+
+ /*
+ * We must return status bits as a
+ * get port status hub request would do.
+ */
+ ub = hp->aux;
+ ohcistatus = ub->ohci->rhportsts[port - 1];
+ v = 0;
+ if(ohcistatus & Ccs)
+ v |= HPpresent;
+ if(ohcistatus & Pes)
+ v |= HPenable;
+ if(ohcistatus & Pss)
+ v |= HPsuspend;
+ if(ohcistatus & Prs)
+ v |= HPreset;
+ else {
+ /* port is not in reset; these potential writes are ok */
+ if(ohcistatus & Csc){
+ v |= HPstatuschg;
+ ub->ohci->rhportsts[port - 1] = Csc;
+ }
+ if(ohcistatus & Pesc){
+ v |= HPchange;
+ ub->ohci->rhportsts[port - 1] = Pesc;
+ }
+ }
+ if(ohcistatus & Lsda)
+ v |= HPslow;
+ if(v & (HPstatuschg|HPchange))
+ ddprint("ohci port %d sts %#ulx hub sts %#x\n", port, ohcistatus, v);
+ return v;
+}
+
+static void
+dumpohci(Ctlr *ctlr)
+{
+ int i;
+ ulong *ohci;
+
+ ohci = &ctlr->ohci->revision;
+ print("ohci registers: \n");
+ for(i = 0; i < sizeof(Ohci)/sizeof(ulong); i++)
+ if(i < 3 || ohci[i] != 0)
+ print("\t[%#2.2x]\t%#8.8ulx\n", i * 4, ohci[i]);
+ print("\n");
+}
+
+static void
+init(Hci *hp)
+{
+ Ctlr *ctlr;
+ Ohci *ohci;
+ int i;
+ ulong ival, ctrl, fmi;
+
+ ctlr = hp->aux;
+ dprint("ohci %#p init\n", ctlr->ohci);
+ ohci = ctlr->ohci;
+
+ fmi = ctlr->ohci->fminterval;
+ ctlr->ohci->cmdsts = Shcr; /* reset the block */
+ while(ctlr->ohci->cmdsts & Shcr)
+ delay(1); /* wait till reset complete, Ohci says 10us max. */
+ ctlr->ohci->fminterval = fmi;
+
+ /*
+ * now that soft reset is done we are in suspend state.
+ * Setup registers which take in suspend state
+ * (will only be here for 2ms).
+ */
+
+ ctlr->ohci->hcca = ptr2pa(ctlr->hcca);
+ setctlhd(ctlr, nil);
+ ctlr->ohci->ctlcurred = 0;
+ setbulkhd(ctlr, nil);
+ ctlr->ohci->bulkcurred = 0;
+
+ ohci->intrenable = Mie | Wdh | Ue;
+ ohci->control |= Ccle | Cble | Cple | Cie | Cfsoper;
+
+ /* set frame after operational */
+ ohci->rhdesca = Nps; /* no power switching */
+ if(ohci->rhdesca & Nps){
+ dprint("ohci: ports are not power switched\n");
+ }else{
+ dprint("ohci: ports are power switched\n");
+ ohci->rhdesca &= ~Psm;
+ ohci->rhsts &= ~Lpsc;
+ }
+ for(i = 0; i < ctlr->nports; i++) /* paranoia */
+ ohci->rhportsts[i] = 0; /* this has no effect */
+ delay(50);
+
+ for(i = 0; i < ctlr->nports; i++){
+ ohci->rhportsts[i] = Spp;
+ if((ohci->rhportsts[i] & Ccs) != 0)
+ ohci->rhportsts[i] |= Spr;
+ }
+ delay(100);
+
+ ctrl = ohci->control;
+ if((ctrl & Cfsmask) != Cfsoper){
+ ctrl = (ctrl & ~Cfsmask) | Cfsoper;
+ ohci->control = ctrl;
+ ohci->rhsts = Lpsc;
+ }
+ ival = ohci->fminterval & ~(Fmaxpktmask << Fmaxpktshift);
+ ohci->fminterval = ival | (5120 << Fmaxpktshift);
+
+ if(debug > 1)
+ dumpohci(ctlr);
+}
+
+static void
+scanpci(void)
+{
+ ulong mem;
+ Ctlr *ctlr;
+ Pcidev *p;
+ int i;
+ static int already = 0;
+
+ if(already)
+ return;
+ already = 1;
+ p = nil;
+ while(p = pcimatch(p, 0, 0)) {
+ /*
+ * Find Ohci controllers (Programming Interface = 0x10).
+ */
+ if(p->ccrb != Pcibcserial || p->ccru != Pciscusb ||
+ p->ccrp != 0x10)
+ continue;
+ mem = p->mem[0].bar & ~0x0F;
+ dprint("ohci: %x/%x port 0x%lux size 0x%x irq %d\n",
+ p->vid, p->did, mem, p->mem[0].size, p->intl);
+ if(mem == 0){
+ print("ohci: failed to map registers\n");
+ continue;
+ }
+ if(p->intl == 0xFF || p->intl == 0) {
+ print("ohci: no irq assigned for port %#lux\n", mem);
+ continue;
+ }
+
+ ctlr = smalloc(sizeof(Ctlr));
+ ctlr->pcidev = p;
+ ctlr->ohci = vmap(mem, p->mem[0].size);
+ dprint("scanpci: ctlr %#p, ohci %#p\n", ctlr, ctlr->ohci);
+ pcisetbme(p);
+ pcisetpms(p, 0);
+ for(i = 0; i < Nhcis; i++)
+ if(ctlrs[i] == nil){
+ ctlrs[i] = ctlr;
+ break;
+ }
+ if(i == Nhcis)
+ print("ohci: bug: no more controllers\n");
+ }
+}
+
+static void
+usbdebug(Hci*, int d)
+{
+ debug = d;
+}
+
+/*
+ * build the periodic scheduling tree:
+ * framesize must be a multiple of the tree size
+ */
+static void
+mkqhtree(Ctlr *ctlr)
+{
+ int i, n, d, o, leaf0, depth;
+ Ed **tree;
+ Qtree *qt;
+
+ depth = flog2(32);
+ n = (1 << (depth+1)) - 1;
+ qt = mallocz(sizeof(*qt), 1);
+ if(qt == nil)
+ panic("usb: can't allocate scheduling tree");
+ qt->nel = n;
+ qt->depth = depth;
+ qt->bw = mallocz(n * sizeof(qt->bw), 1);
+ qt->root = tree = mallocz(n * sizeof(Ed *), 1);
+ if(qt->bw == nil || qt->root == nil)
+ panic("usb: can't allocate scheduling tree");
+ for(i = 0; i < n; i++){
+ if((tree[i] = edalloc()) == nil)
+ panic("mkqhtree");
+ tree[i]->ctrl = (8 << Edmpsshift); /* not needed */
+ tree[i]->ctrl |= Edskip;
+
+ if(i > 0)
+ edlinked(tree[i], tree[(i-1)/2]);
+ else
+ edlinked(tree[i], nil);
+ }
+ ctlr->ntree = i;
+ dprint("ohci: tree: %d endpoints allocated\n", i);
+
+ /* distribute leaves evenly round the frame list */
+ leaf0 = n / 2;
+ for(i = 0; i < 32; i++){
+ o = 0;
+ for(d = 0; d < depth; d++){
+ o <<= 1;
+ if(i & (1 << d))
+ o |= 1;
+ }
+ if(leaf0 + o >= n){
+ print("leaf0=%d o=%d i=%d n=%d\n", leaf0, o, i, n);
+ break;
+ }
+ ctlr->hcca->intrtable[i] = ptr2pa(tree[leaf0 + o]);
+ }
+ ctlr->tree = qt;
+}
+
+static void
+ohcimeminit(Ctlr *ctlr)
+{
+ Hcca *hcca;
+
+ edfree(edalloc()); /* allocate pools now */
+ tdfree(tdalloc());
+
+ hcca = xspanalloc(sizeof(Hcca), 256, 0);
+ if(hcca == nil)
+ panic("usbhreset: no memory for Hcca");
+ memset(hcca, 0, sizeof(*hcca));
+ ctlr->hcca = hcca;
+
+ mkqhtree(ctlr);
+}
+
+static void
+ohcireset(Ctlr *ctlr)
+{
+ ilock(ctlr);
+ dprint("ohci %#p reset\n", ctlr->ohci);
+
+ /*
+ * usually enter here in reset, wait till its through,
+ * then do our own so we are on known timing conditions.
+ * Is this needed?
+ */
+ delay(100);
+ ctlr->ohci->control = 0;
+ delay(100);
+
+ /* legacy support register: turn off lunacy mode */
+ pcicfgw16(ctlr->pcidev, 0xc0, 0x2000);
+
+ iunlock(ctlr);
+}
+
+static void
+shutdown(Hci *hp)
+{
+ Ctlr *ctlr;
+
+ ctlr = hp->aux;
+
+ ilock(ctlr);
+ ctlr->ohci->intrenable = 0;
+ ctlr->ohci->control = 0;
+ delay(100);
+ iunlock(ctlr);
+}
+
+static int
+reset(Hci *hp)
+{
+ int i;
+ Ctlr *ctlr;
+ Pcidev *p;
+ static Lock resetlck;
+
+ if(getconf("*nousbohci"))
+ return -1;
+ ilock(&resetlck);
+ scanpci();
+
+ /*
+ * Any adapter matches if no hp->port is supplied,
+ * otherwise the ports must match.
+ */
+ ctlr = nil;
+ for(i = 0; i < Nhcis && ctlrs[i] != nil; i++){
+ ctlr = ctlrs[i];
+ if(ctlr->active == 0)
+ if(hp->port == 0 || hp->port == (uintptr)ctlr->ohci){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ iunlock(&resetlck);
+ if(ctlrs[i] == nil || i == Nhcis)
+ return -1;
+ if(ctlr->ohci->control == ~0)
+ return -1;
+
+
+ p = ctlr->pcidev;
+ hp->aux = ctlr;
+ hp->port = (uintptr)ctlr->ohci;
+ hp->irq = p->intl;
+ hp->tbdf = p->tbdf;
+ ctlr->nports = hp->nports = ctlr->ohci->rhdesca & 0xff;
+
+ ohcireset(ctlr);
+ ohcimeminit(ctlr);
+
+ /*
+ * Linkage to the generic HCI driver.
+ */
+ hp->init = init;
+ hp->dump = dump;
+ hp->interrupt = interrupt;
+ hp->epopen = epopen;
+ hp->epclose = epclose;
+ hp->epread = epread;
+ hp->epwrite = epwrite;
+ hp->seprintep = seprintep;
+ hp->portenable = portenable;
+ hp->portreset = portreset;
+ hp->portstatus = portstatus;
+ hp->shutdown = shutdown;
+ hp->debug = usbdebug;
+ hp->type = "ohci";
+ return 0;
+}
+
+void
+usbohcilink(void)
+{
+ addhcitype("ohci", reset);
+}
diff --git a/sys/src/9/pc/usbuhci.c b/sys/src/9/pc/usbuhci.c
new file mode 100755
index 000000000..2bb98bc14
--- /dev/null
+++ b/sys/src/9/pc/usbuhci.c
@@ -0,0 +1,2315 @@
+/*
+ * USB Universal Host Controller Interface (sic) driver.
+ *
+ * BUGS:
+ * - Too many delays and ilocks.
+ * - bandwidth admission control must be done per-frame.
+ * - interrupt endpoints should go on a tree like [oe]hci.
+ * - must warn of power overruns.
+ */
+
+#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/usb.h"
+
+typedef struct Ctlio Ctlio;
+typedef struct Ctlr Ctlr;
+typedef struct Isoio Isoio;
+typedef struct Qh Qh;
+typedef struct Qhpool Qhpool;
+typedef struct Qio Qio;
+typedef struct Td Td;
+typedef struct Tdpool Tdpool;
+
+enum
+{
+ Resetdelay = 100, /* delay after a controller reset (ms) */
+ Enabledelay = 100, /* waiting for a port to enable */
+ Abortdelay = 5, /* delay after cancelling Tds (ms) */
+ Incr = 64, /* for Td and Qh pools */
+
+ Tdatomic = 8, /* max nb. of Tds per bulk I/O op. */
+
+ /* Queue states (software) */
+ Qidle = 0,
+ Qinstall,
+ Qrun,
+ Qdone,
+ Qclose,
+ Qfree,
+
+ /*
+ * HW constants
+ */
+
+ Nframes = 1024, /* 2ⁿ for xspanalloc; max 1024 */
+ Align = 16, /* for data structures */
+
+ /* Size of small buffer kept within Tds. (software) */
+ /* Keep as a multiple of Align to maintain alignment of Tds in pool */
+ Tdndata = 1*Align,
+
+ /* i/o space
+ * Some ports are short, some are long, some are byte.
+ * We use ins[bsl] and not vmap.
+ */
+ Cmd = 0,
+ Crun = 0x01,
+ Chcreset = 0x02, /* host controller reset */
+ Cgreset = 0x04, /* global reset */
+ Cegsm = 0x08, /* enter global suspend */
+ Cfgr = 0x10, /* forge global resume */
+ Cdbg = 0x20, /* single step, debug */
+ Cmaxp = 0x80, /* max packet */
+
+ Status = 2,
+ Susbintr = 0x01, /* interrupt */
+ Seintr = 0x02, /* error interrupt */
+ Sresume = 0x04, /* resume detect */
+ Shserr = 0x08, /* host system error */
+ Shcerr = 0x10, /* host controller error */
+ Shalted = 0x20, /* controller halted */
+ Sall = 0x3F,
+
+ Usbintr = 4,
+ Itmout = 0x01, /* timeout or crc */
+ Iresume = 0x02, /* resume interrupt enable */
+ Ioc = 0x04, /* interrupt on complete */
+ Ishort = 0x08, /* short packet interrupt */
+ Iall = 0x0F,
+ Frnum = 6,
+ Flbaseadd = 8,
+ SOFmod = 0xC, /* start of frame modifier register */
+
+ Portsc0 = 0x10,
+ PSpresent = 0x0001, /* device present */
+ PSstatuschg = 0x0002, /* PSpresent changed */
+ PSenable = 0x0004, /* device enabled */
+ PSchange = 0x0008, /* PSenable changed */
+ PSresume = 0x0040, /* resume detected */
+ PSreserved1 = 0x0080, /* always read as 1; reserved */
+ PSslow = 0x0100, /* device has low speed */
+ PSreset = 0x0200, /* port reset */
+ PSsuspend = 0x1000, /* port suspended */
+
+ /* Transfer descriptor link */
+ Tdterm = 0x1, /* nil (terminate) */
+ Tdlinkqh = 0x2, /* link refers to a QH */
+ Tdvf = 0x4, /* run linked Tds first (depth-first)*/
+
+ /* Transfer status bits */
+ Tdbitstuff = 0x00020000, /* bit stuffing error */
+ Tdcrcto = 0x00040000, /* crc or timeout error */
+ Tdnak = 0x00080000, /* nak packet received */
+ Tdbabble = 0x00100000, /* babble detected */
+ Tddberr = 0x00200000, /* data buf. error */
+ Tdstalled = 0x00400000, /* serious error to ep. */
+ Tdactive = 0x00800000, /* enabled/in use by hw */
+ /* Transfer control bits */
+ Tdioc = 0x01000000, /* interrupt on complete */
+ Tdiso = 0x02000000, /* isochronous select */
+ Tdlow = 0x04000000, /* low speed device */
+ Tderr1 = 0x08000000, /* bit 0 of error counter */
+ Tderr2 = 0x10000000, /* bit 1 of error counter */
+ Tdspd = 0x20000000, /* short packet detect */
+
+ Tdlen = 0x000003FF, /* actual length field */
+
+ Tdfatalerr = Tdnak|Tdbabble|Tdstalled, /* hw retries others */
+ Tderrors = Tdfatalerr|Tdbitstuff|Tdcrcto|Tddberr,
+
+ /* Transfer descriptor token bits */
+ Tddata0 = 0,
+ Tddata1 = 0x80000, /* data toggle (1==DATA1) */
+ Tdtokin = 0x69,
+ Tdtokout = 0xE1,
+ Tdtoksetup = 0x2D,
+
+ Tdmaxpkt = 0x800, /* max packet size */
+
+ /* Queue head bits */
+ QHterm = 1<<0, /* nil (terminate) */
+ QHlinkqh = 1<<1, /* link refers to a QH */
+ QHvf = 1<<2, /* vertical first (depth first) */
+};
+
+struct Ctlr
+{
+ Lock; /* for ilock. qh lists and basic ctlr I/O */
+ QLock portlck; /* for port resets/enable... */
+ Pcidev* pcidev;
+ int active;
+ int port; /* I/O address */
+ Qh* qhs; /* list of Qhs for this controller */
+ Qh* qh[Tmax]; /* Dummy Qhs to insert Qhs after */
+ Isoio* iso; /* list of active iso I/O */
+ ulong* frames; /* frame list (used by hw) */
+ ulong load; /* max load for a single frame */
+ ulong isoload; /* max iso load for a single frame */
+ int nintr; /* number of interrupts attended */
+ int ntdintr; /* number of intrs. with something to do */
+ int nqhintr; /* number of intrs. for Qhs */
+ int nisointr; /* number of intrs. for iso transfers */
+};
+
+struct Qio
+{
+ QLock; /* for the entire I/O process */
+ Rendez; /* wait for completion */
+ Qh* qh; /* Td list (field const after init) */
+ int usbid; /* usb address for endpoint/device */
+ int toggle; /* Tddata0/Tddata1 */
+ int tok; /* Tdtoksetup, Tdtokin, Tdtokout */
+ ulong iotime; /* time of last I/O */
+ int debug; /* debug flag from the endpoint */
+ char* err; /* error string */
+};
+
+struct Ctlio
+{
+ Qio; /* a single Qio for each RPC */
+ uchar* data; /* read from last ctl req. */
+ int ndata; /* number of bytes read */
+};
+
+struct Isoio
+{
+ QLock;
+ Rendez; /* wait for space/completion/errors */
+ int usbid; /* address used for device/endpoint */
+ int tok; /* Tdtokin or Tdtokout */
+ int state; /* Qrun -> Qdone -> Qrun... -> Qclose */
+ int nframes; /* Nframes/ep->pollival */
+ uchar* data; /* iso data buffers if not embedded */
+ int td0frno; /* frame number for first Td */
+ Td* tdu; /* next td for user I/O in tdps */
+ Td* tdi; /* next td processed by interrupt */
+ char* err; /* error string */
+ int nerrs; /* nb of consecutive I/O errors */
+ long nleft; /* number of bytes left from last write */
+ int debug; /* debug flag from the endpoint */
+ Isoio* next; /* in list of active Isoios */
+ Td* tdps[Nframes]; /* pointer to Td used for i-th frame or nil */
+};
+
+struct Tdpool
+{
+ Lock;
+ Td* free;
+ int nalloc;
+ int ninuse;
+ int nfree;
+};
+
+struct Qhpool
+{
+ Lock;
+ Qh* free;
+ int nalloc;
+ int ninuse;
+ int nfree;
+};
+
+/*
+ * HW data structures
+ */
+
+/*
+ * Queue header (known by hw).
+ * 16-byte aligned. first two words used by hw.
+ * They are taken from the pool upon endpoint opening and
+ * queued after the dummy queue header for the endpoint type
+ * in the controller. Actual I/O happens as Tds are linked into it.
+ * The driver does I/O in lock-step.
+ * The user builds a list of Tds and links it into the Qh,
+ * then the Qh goes from Qidle to Qrun and nobody touches it until
+ * it becomes Qdone at interrupt time.
+ * At that point the user collects the Tds and it goes Qidle.
+ * A premature cancel may set the state to Qclose and abort I/O.
+ * The Ctlr lock protects change of state for Qhs in use.
+ */
+struct Qh
+{
+ ulong link; /* link to next horiz. item (eg. Qh) */
+ ulong elink; /* link to element (eg. Td; updated by hw) */
+
+ ulong state; /* Qidle -> Qinstall -> Qrun -> Qdone | Qclose */
+ Qio* io; /* for this queue */
+
+ Qh* next; /* in active or free list */
+ Td* tds; /* Td list in this Qh (initially, elink) */
+ char* tag; /* debug and align, mostly */
+ ulong align;
+};
+
+/*
+ * Transfer descriptor.
+ * 16-byte aligned. first two words used by hw. Next 4 by sw.
+ * We keep an embedded buffer for small I/O transfers.
+ * They are taken from the pool when buffers are needed for I/O
+ * and linked at the Qh/Isoio for the endpoint and direction requiring it.
+ * The block keeps actual data. They are protected from races by
+ * the queue or the pool keeping it. The owner of the link to the Td
+ * is free to use it and can be the only one using it.
+ */
+struct Td
+{
+ ulong link; /* Link to next Td or Qh */
+ ulong csw; /* control and status word (updated by hw) */
+ ulong token; /* endpt, device, pid */
+ ulong buffer; /* buffer pointer */
+
+ Td* next; /* in qh or Isoio or free list */
+ ulong ndata; /* bytes available/used at data */
+ uchar* data; /* pointer to actual data */
+ void* buff; /* allocated data, for large transfers */
+
+ uchar sbuff[Tdndata]; /* embedded buffer, for small transfers */
+};
+
+#define INB(x) inb(ctlr->port+(x))
+#define INS(x) ins(ctlr->port+(x))
+#define INL(x) inl(ctlr->port+(x))
+#define OUTB(x, v) outb(ctlr->port+(x), (v))
+#define OUTS(x, v) outs(ctlr->port+(x), (v))
+#define OUTL(x, v) outl(ctlr->port+(x), (v))
+#define TRUNC(x, sz) ((x) & ((sz)-1))
+#define PTR(q) ((void*)KADDR((ulong)(q) & ~ (0xF|PCIWINDOW)))
+#define QPTR(q) ((Qh*)PTR(q))
+#define TPTR(q) ((Td*)PTR(q))
+#define PORT(p) (Portsc0 + 2*(p))
+#define diprint if(debug || iso->debug)print
+#define ddiprint if(debug>1 || iso->debug>1)print
+#define dqprint if(debug || (qh->io && qh->io->debug))print
+#define ddqprint if(debug>1 || (qh->io && qh->io->debug>1))print
+
+static Ctlr* ctlrs[Nhcis];
+
+static Tdpool tdpool;
+static Qhpool qhpool;
+static int debug;
+
+static char* qhsname[] = { "idle", "install", "run", "done", "close", "FREE" };
+
+static void
+uhcicmd(Ctlr *ctlr, int c)
+{
+ OUTS(Cmd, c);
+}
+
+static void
+uhcirun(Ctlr *ctlr, int on)
+{
+ int i;
+
+ ddprint("uhci %#ux setting run to %d\n", ctlr->port, on);
+
+ if(on)
+ uhcicmd(ctlr, INS(Cmd)|Crun);
+ else
+ uhcicmd(ctlr, INS(Cmd) & ~Crun);
+ for(i = 0; i < 100; i++)
+ if(on == 0 && (INS(Status) & Shalted) != 0)
+ break;
+ else if(on != 0 && (INS(Status) & Shalted) == 0)
+ break;
+ else
+ delay(1);
+ if(i == 100)
+ dprint("uhci %#x run cmd timed out\n", ctlr->port);
+ ddprint("uhci %#ux cmd %#ux sts %#ux\n",
+ ctlr->port, INS(Cmd), INS(Status));
+}
+
+static int
+tdlen(Td *td)
+{
+ return (td->csw+1) & Tdlen;
+}
+
+static int
+maxtdlen(Td *td)
+{
+ return ((td->token>>21)+1) & (Tdmaxpkt-1);
+}
+
+static int
+tdtok(Td *td)
+{
+ return td->token & 0xFF;
+}
+
+static char*
+seprinttd(char *s, char *se, Td *td)
+{
+ s = seprint(s, se, "%#p link %#ulx", td, td->link);
+ if((td->link & Tdvf) != 0)
+ s = seprint(s, se, "V");
+ if((td->link & Tdterm) != 0)
+ s = seprint(s, se, "T");
+ if((td->link & Tdlinkqh) != 0)
+ s = seprint(s, se, "Q");
+ s = seprint(s, se, " csw %#ulx ", td->csw);
+ if(td->csw & Tdactive)
+ s = seprint(s, se, "a");
+ if(td->csw & Tdiso)
+ s = seprint(s, se, "I");
+ if(td->csw & Tdioc)
+ s = seprint(s, se, "i");
+ if(td->csw & Tdlow)
+ s = seprint(s, se, "l");
+ if((td->csw & (Tderr1|Tderr2)) == 0)
+ s = seprint(s, se, "z");
+ if(td->csw & Tderrors)
+ s = seprint(s, se, " err %#ulx", td->csw & Tderrors);
+ if(td->csw & Tdstalled)
+ s = seprint(s, se, "s");
+ if(td->csw & Tddberr)
+ s = seprint(s, se, "d");
+ if(td->csw & Tdbabble)
+ s = seprint(s, se, "b");
+ if(td->csw & Tdnak)
+ s = seprint(s, se, "n");
+ if(td->csw & Tdcrcto)
+ s = seprint(s, se, "c");
+ if(td->csw & Tdbitstuff)
+ s = seprint(s, se, "B");
+ s = seprint(s, se, " stslen %d", tdlen(td));
+
+ s = seprint(s, se, " token %#ulx", td->token);
+ if(td->token == 0) /* the BWS loopback Td, ignore rest */
+ return s;
+ s = seprint(s, se, " maxlen %d", maxtdlen(td));
+ if(td->token & Tddata1)
+ s = seprint(s, se, " d1");
+ else
+ s = seprint(s, se, " d0");
+ s = seprint(s, se, " id %#ulx:", (td->token>>15) & Epmax);
+ s = seprint(s, se, "%#ulx", (td->token>>8) & Devmax);
+ switch(tdtok(td)){
+ case Tdtokin:
+ s = seprint(s, se, " in");
+ break;
+ case Tdtokout:
+ s = seprint(s, se, " out");
+ break;
+ case Tdtoksetup:
+ s = seprint(s, se, " setup");
+ break;
+ default:
+ s = seprint(s, se, " BADPID");
+ }
+ s = seprint(s, se, "\n\t buffer %#ulx data %#p", td->buffer, td->data);
+ s = seprint(s, se, " ndata %uld sbuff %#p buff %#p",
+ td->ndata, td->sbuff, td->buff);
+ if(td->ndata > 0)
+ s = seprintdata(s, se, td->data, td->ndata);
+ return s;
+}
+
+static void
+isodump(Isoio *iso, int all)
+{
+ char buf[256];
+ Td *td;
+ int i;
+
+ print("iso %#p %s state %d nframes %d"
+ " td0 %#p tdu %#p tdi %#p data %#p\n",
+ iso, iso->tok == Tdtokin ? "in" : "out",
+ iso->state, iso->nframes, iso->tdps[iso->td0frno],
+ iso->tdu, iso->tdi, iso->data);
+ if(iso->err != nil)
+ print("\terr='%s'\n", iso->err);
+ if(all == 0){
+ seprinttd(buf, buf+sizeof(buf), iso->tdu);
+ print("\ttdu %s\n", buf);
+ seprinttd(buf, buf+sizeof(buf), iso->tdi);
+ print("\ttdi %s\n", buf);
+ }else{
+ td = iso->tdps[iso->td0frno];
+ for(i = 0; i < iso->nframes; i++){
+ seprinttd(buf, buf+sizeof(buf), td);
+ if(td == iso->tdi)
+ print("i->");
+ if(td == iso->tdu)
+ print("u->");
+ print("\t%s\n", buf);
+ td = td->next;
+ }
+ }
+}
+
+static int
+sameptr(void *p, ulong l)
+{
+ if(l & QHterm)
+ return p == nil;
+ return PTR(l) == p;
+}
+
+static void
+dumptd(Td *td, char *pref)
+{
+ char buf[256];
+ char *s;
+ char *se;
+ int i;
+
+ i = 0;
+ se = buf+sizeof(buf);
+ for(; td != nil; td = td->next){
+ s = seprinttd(buf, se, td);
+ if(!sameptr(td->next, td->link))
+ seprint(s, se, " next %#p != link %#ulx %#p",
+ td->next, td->link, TPTR(td->link));
+ print("%std %s\n", pref, buf);
+ if(i++ > 20){
+ print("...more tds...\n");
+ break;
+ }
+ }
+}
+
+static void
+qhdump(Qh *qh, char *pref)
+{
+ char buf[256];
+ char *s;
+ char *se;
+ ulong td;
+ int i;
+
+ s = buf;
+ se = buf+sizeof(buf);
+ s = seprint(s, se, "%sqh %s %#p state %s link %#ulx", pref,
+ qh->tag, qh, qhsname[qh->state], qh->link);
+ if(!sameptr(qh->tds, qh->elink))
+ s = seprint(s, se, " [tds %#p != elink %#ulx %#p]",
+ qh->tds, qh->elink, TPTR(qh->elink));
+ if(!sameptr(qh->next, qh->link))
+ s = seprint(s, se, " [next %#p != link %#ulx %#p]",
+ qh->next, qh->link, QPTR(qh->link));
+ if((qh->link & Tdterm) != 0)
+ s = seprint(s, se, "T");
+ if((qh->link & Tdlinkqh) != 0)
+ s = seprint(s, se, "Q");
+ s = seprint(s, se, " elink %#ulx", qh->elink);
+ if((qh->elink & Tdterm) != 0)
+ s = seprint(s, se, "T");
+ if((qh->elink & Tdlinkqh) != 0)
+ s = seprint(s, se, "Q");
+ s = seprint(s, se, " io %#p", qh->io);
+ if(qh->io != nil && qh->io->err != nil)
+ seprint(s, se, " err='%s'", qh->io->err);
+ print("%s\n", buf);
+ dumptd(qh->tds, "\t");
+ if((qh->elink & QHterm) == 0){
+ print("\thw tds:");
+ i = 0;
+ for(td = qh->elink; (td & Tdterm) == 0; td = TPTR(td)->link){
+ print(" %#ulx", td);
+ if(td == TPTR(td)->link) /* BWS Td */
+ break;
+ if(i++ > 40){
+ print("...");
+ break;
+ }
+ }
+ print("\n");
+ }
+}
+
+static void
+xdump(Ctlr *ctlr, int doilock)
+{
+ Isoio *iso;
+ Qh *qh;
+ int i;
+
+ if(doilock){
+ if(ctlr == ctlrs[0]){
+ lock(&tdpool);
+ print("tds: alloc %d = inuse %d + free %d\n",
+ tdpool.nalloc, tdpool.ninuse, tdpool.nfree);
+ unlock(&tdpool);
+ lock(&qhpool);
+ print("qhs: alloc %d = inuse %d + free %d\n",
+ qhpool.nalloc, qhpool.ninuse, qhpool.nfree);
+ unlock(&qhpool);
+ }
+ ilock(ctlr);
+ }
+ print("uhci port %#x frames %#p nintr %d ntdintr %d",
+ ctlr->port, ctlr->frames, ctlr->nintr, ctlr->ntdintr);
+ print(" nqhintr %d nisointr %d\n", ctlr->nqhintr, ctlr->nisointr);
+ print("cmd %#ux sts %#ux fl %#ulx ps1 %#ux ps2 %#ux frames[0] %#ulx\n",
+ INS(Cmd), INS(Status),
+ INL(Flbaseadd), INS(PORT(0)), INS(PORT(1)),
+ ctlr->frames[0]);
+ for(iso = ctlr->iso; iso != nil; iso = iso->next)
+ isodump(iso, 1);
+ i = 0;
+ for(qh = ctlr->qhs; qh != nil; qh = qh->next){
+ qhdump(qh, "");
+ if(i++ > 20){
+ print("qhloop\n");
+ break;
+ }
+ }
+ print("\n");
+ if(doilock)
+ iunlock(ctlr);
+}
+
+static void
+dump(Hci *hp)
+{
+ xdump(hp->aux, 1);
+}
+
+static Td*
+tdalloc(void)
+{
+ int i;
+ Td *td;
+ Td *pool;
+
+ lock(&tdpool);
+ if(tdpool.free == nil){
+ ddprint("uhci: tdalloc %d Tds\n", Incr);
+ pool = xspanalloc(Incr*sizeof(Td), Align, 0);
+ if(pool == nil)
+ panic("tdalloc");
+ for(i=Incr; --i>=0;){
+ pool[i].next = tdpool.free;
+ tdpool.free = &pool[i];
+ }
+ tdpool.nalloc += Incr;
+ tdpool.nfree += Incr;
+ }
+ td = tdpool.free;
+ tdpool.free = td->next;
+ tdpool.ninuse++;
+ tdpool.nfree--;
+ unlock(&tdpool);
+
+ memset(td, 0, sizeof(Td));
+ td->link = Tdterm;
+ assert(((ulong)td & 0xF) == 0);
+ return td;
+}
+
+static void
+tdfree(Td *td)
+{
+ if(td == nil)
+ return;
+ free(td->buff);
+ td->buff = nil;
+ lock(&tdpool);
+ td->next = tdpool.free;
+ tdpool.free = td;
+ tdpool.ninuse--;
+ tdpool.nfree++;
+ unlock(&tdpool);
+}
+
+static void
+qhlinkqh(Qh* qh, Qh* next)
+{
+ if(next == nil)
+ qh->link = QHterm;
+ else{
+ next->link = qh->link;
+ next->next = qh->next;
+ qh->link = PCIWADDR(next)|QHlinkqh;
+ }
+ qh->next = next;
+}
+
+static void
+qhlinktd(Qh *qh, Td *td)
+{
+ qh->tds = td;
+ if(td == nil)
+ qh->elink = QHvf|QHterm;
+ else
+ qh->elink = PCIWADDR(td);
+}
+
+static void
+tdlinktd(Td *td, Td *next)
+{
+ td->next = next;
+ if(next == nil)
+ td->link = Tdterm;
+ else
+ td->link = PCIWADDR(next)|Tdvf;
+}
+
+static Qh*
+qhalloc(Ctlr *ctlr, Qh *prev, Qio *io, char *tag)
+{
+ int i;
+ Qh *qh;
+ Qh *pool;
+
+ lock(&qhpool);
+ if(qhpool.free == nil){
+ ddprint("uhci: qhalloc %d Qhs\n", Incr);
+ pool = xspanalloc(Incr*sizeof(Qh), Align, 0);
+ if(pool == nil)
+ panic("qhalloc");
+ for(i=Incr; --i>=0;){
+ pool[i].next = qhpool.free;
+ qhpool.free = &pool[i];
+ }
+ qhpool.nalloc += Incr;
+ qhpool.nfree += Incr;
+ }
+ qh = qhpool.free;
+ qhpool.free = qh->next;
+ qh->next = nil;
+ qh->link = QHterm;
+ qhpool.ninuse++;
+ qhpool.nfree--;
+ unlock(&qhpool);
+
+ qh->tds = nil;
+ qh->elink = QHterm;
+ qh->state = Qidle;
+ qh->io = io;
+ qh->tag = nil;
+ kstrdup(&qh->tag, tag);
+
+ if(prev != nil){
+ coherence();
+ ilock(ctlr);
+ qhlinkqh(prev, qh);
+ iunlock(ctlr);
+ }
+
+ assert(((ulong)qh & 0xF) == 0);
+ return qh;
+}
+
+static void
+qhfree(Ctlr *ctlr, Qh *qh)
+{
+ Td *td;
+ Td *ltd;
+ Qh *q;
+
+ if(qh == nil)
+ return;
+
+ ilock(ctlr);
+ for(q = ctlr->qhs; q != nil; q = q->next)
+ if(q->next == qh)
+ break;
+ if(q == nil)
+ panic("qhfree: nil q");
+ q->next = qh->next;
+ q->link = qh->link;
+ iunlock(ctlr);
+
+ for(td = qh->tds; td != nil; td = ltd){
+ ltd = td->next;
+ tdfree(td);
+ }
+ lock(&qhpool);
+ qh->state = Qfree; /* paranoia */
+ qh->next = qhpool.free;
+ qh->tag = nil;
+ qh->io = nil;
+ qhpool.free = qh;
+ qhpool.ninuse--;
+ qhpool.nfree++;
+ unlock(&qhpool);
+ ddprint("qhfree: qh %#p\n", qh);
+}
+
+static char*
+errmsg(int err)
+{
+ if(err == 0)
+ return "ok";
+ if(err & Tdcrcto)
+ return "crc/timeout error";
+ if(err & Tdbabble)
+ return "babble detected";
+ if(err & Tddberr)
+ return "db error";
+ if(err & Tdbitstuff)
+ return "bit stuffing error";
+ if(err & Tdstalled)
+ return Estalled;
+ return Eio;
+}
+
+static int
+isocanread(void *a)
+{
+ Isoio *iso;
+
+ iso = a;
+ return iso->state == Qclose ||
+ (iso->state == Qrun &&
+ iso->tok == Tdtokin && iso->tdi != iso->tdu);
+}
+
+static int
+isocanwrite(void *a)
+{
+ Isoio *iso;
+
+ iso = a;
+ return iso->state == Qclose ||
+ (iso->state == Qrun &&
+ iso->tok == Tdtokout && iso->tdu->next != iso->tdi);
+}
+
+static void
+tdisoinit(Isoio *iso, Td *td, long count)
+{
+ td->ndata = count;
+ td->token = ((count-1)<<21)| ((iso->usbid & 0x7FF)<<8) | iso->tok;
+ td->csw = Tderr1|Tdiso|Tdactive|Tdioc;
+}
+
+/*
+ * Process Iso i/o on interrupt. For writes update just error status.
+ * For reads update tds to reflect data and also error status.
+ * When tdi aproaches tdu, advance tdu; data may be lost.
+ * (If nframes is << Nframes tdu might be far away but this avoids
+ * races regarding frno.)
+ * If we suffer errors for more than half the frames we stall.
+ */
+static void
+isointerrupt(Ctlr *ctlr, Isoio* iso)
+{
+ Td *tdi;
+ int err;
+ int i;
+ int nframes;
+
+ tdi = iso->tdi;
+ if((tdi->csw & Tdactive) != 0) /* nothing new done */
+ return;
+ ctlr->nisointr++;
+ ddiprint("isointr: iso %#p: tdi %#p tdu %#p\n", iso, tdi, iso->tdu);
+ if(iso->state != Qrun && iso->state != Qdone)
+ panic("isointr: iso state");
+ if(debug > 1 || iso->debug > 1)
+ isodump(iso, 0);
+
+ nframes = iso->nframes / 2; /* limit how many we look */
+ if(nframes > 64)
+ nframes = 64;
+
+ for(i = 0; i < nframes && (tdi->csw & Tdactive) == 0; i++){
+ tdi->csw &= ~Tdioc;
+ err = tdi->csw & Tderrors;
+ if(err == 0)
+ iso->nerrs = 0;
+ else if(iso->nerrs++ > iso->nframes/2)
+ tdi->csw |= Tdstalled;
+ if((tdi->csw & Tdstalled) != 0){
+ if(iso->err == nil){
+ iso->err = errmsg(err);
+ diprint("isointerrupt: tdi %#p error %#ux %s\n",
+ tdi, err, iso->err);
+ diprint("ctlr load %uld\n", ctlr->load);
+ }
+ tdi->ndata = 0;
+ }else
+ tdi->ndata = tdlen(tdi);
+
+ if(tdi->next == iso->tdu || tdi->next->next == iso->tdu){
+ memset(iso->tdu->data, 0, maxtdlen(iso->tdu));
+ tdisoinit(iso, iso->tdu, maxtdlen(iso->tdu));
+ iso->tdu = iso->tdu->next;
+ iso->nleft = 0;
+ }
+ tdi = tdi->next;
+ }
+ ddiprint("isointr: %d frames processed\n", nframes);
+ if(i == nframes)
+ tdi->csw |= Tdioc;
+ iso->tdi = tdi;
+ if(isocanwrite(iso) || isocanread(iso)){
+ diprint("wakeup iso %#p tdi %#p tdu %#p\n", iso,
+ iso->tdi, iso->tdu);
+ wakeup(iso);
+ }
+
+}
+
+/*
+ * Process a Qh upon interrupt. There's one per ongoing user I/O.
+ * User process releases resources later, that is not done here.
+ * We may find in this order one or more Tds:
+ * - none/many non active and completed Tds
+ * - none/one (usually(!) not active) and failed Td
+ * - none/many active Tds.
+ * Upon errors the entire transfer is aborted and error reported.
+ * Otherwise, the transfer is complete only when all Tds are done or
+ * when a read with less than maxpkt is found.
+ * Use the software list and not qh->elink to avoid races.
+ * We could use qh->elink to see if there's something new or not.
+ */
+static void
+qhinterrupt(Ctlr *ctlr, Qh *qh)
+{
+ Td *td;
+ int err;
+
+ ctlr->nqhintr++;
+ if(qh->state != Qrun)
+ panic("qhinterrupt: qh state");
+ if(qh->tds == nil)
+ panic("qhinterrupt: no tds");
+ if((qh->tds->csw & Tdactive) == 0)
+ ddqprint("qhinterrupt port %#ux qh %#p p0 %#x p1 %#x\n",
+ ctlr->port, qh, INS(PORT(0)), INS(PORT(1)));
+ for(td = qh->tds; td != nil; td = td->next){
+ if(td->csw & Tdactive)
+ return;
+ td->csw &= ~Tdioc;
+ if((td->csw & Tdstalled) != 0){
+ err = td->csw & Tderrors;
+ /* just stalled is end of xfer but not an error */
+ if(err != Tdstalled && qh->io->err == nil){
+ qh->io->err = errmsg(td->csw & Tderrors);
+ dqprint("qhinterrupt: td %#p error %#ux %s\n",
+ td, err, qh->io->err);
+ dqprint("ctlr load %uld\n", ctlr->load);
+ }
+ break;
+ }
+ if((td->csw & Tdnak) != 0){ /* retransmit; not serious */
+ td->csw &= ~Tdnak;
+ if(td->next == nil)
+ td->csw |= Tdioc;
+ }
+ td->ndata = tdlen(td);
+ if(td->ndata < maxtdlen(td)){ /* EOT */
+ td = td->next;
+ break;
+ }
+ }
+
+ /*
+ * Done. Make void the Tds not used (errors or EOT) and wakeup epio.
+ */
+ qh->elink = QHterm;
+ for(; td != nil; td = td->next)
+ td->ndata = 0;
+ qh->state = Qdone;
+ wakeup(qh->io);
+}
+
+static void
+interrupt(Ureg*, void *a)
+{
+ Hci *hp;
+ Ctlr *ctlr;
+ int frptr;
+ int frno;
+ Qh *qh;
+ Isoio *iso;
+ int sts;
+ int cmd;
+
+ hp = a;
+ ctlr = hp->aux;
+ ilock(ctlr);
+ ctlr->nintr++;
+ sts = INS(Status);
+ if((sts & Sall) == 0){ /* not for us; sharing irq */
+ iunlock(ctlr);
+ return;
+ }
+ OUTS(Status, sts & Sall);
+ cmd = INS(Cmd);
+ if(cmd & Crun == 0){
+ print("uhci %#ux: not running: uhci bug?\n", ctlr->port);
+ /* BUG: should abort everything in this case */
+ }
+ if(debug > 1){
+ frptr = INL(Flbaseadd);
+ frno = INL(Frnum);
+ frno = TRUNC(frno, Nframes);
+ print("cmd %#ux sts %#ux frptr %#ux frno %d\n",
+ cmd, sts, frptr, frno);
+ }
+ ctlr->ntdintr++;
+ /*
+ * Will we know in USB 3.0 who the interrupt was for?.
+ * Do they still teach indexing in CS?
+ * This is Intel's doing.
+ */
+ for(iso = ctlr->iso; iso != nil; iso = iso->next)
+ if(iso->state == Qrun || iso->state == Qdone)
+ isointerrupt(ctlr, iso);
+ for(qh = ctlr->qhs; qh != nil; qh = qh->next)
+ if(qh->state == Qrun)
+ qhinterrupt(ctlr, qh);
+ else if(qh->state == Qclose)
+ qhlinktd(qh, nil);
+ iunlock(ctlr);
+}
+
+/*
+ * iso->tdu is the next place to put data. When it gets full
+ * it is activated and tdu advanced.
+ */
+static long
+putsamples(Isoio *iso, uchar *b, long count)
+{
+ long tot;
+ long n;
+
+ for(tot = 0; isocanwrite(iso) && tot < count; tot += n){
+ n = count-tot;
+ if(n > maxtdlen(iso->tdu) - iso->nleft)
+ n = maxtdlen(iso->tdu) - iso->nleft;
+ memmove(iso->tdu->data+iso->nleft, b+tot, n);
+ iso->nleft += n;
+ if(iso->nleft == maxtdlen(iso->tdu)){
+ tdisoinit(iso, iso->tdu, iso->nleft);
+ iso->nleft = 0;
+ iso->tdu = iso->tdu->next;
+ }
+ }
+ return tot;
+}
+
+/*
+ * Queue data for writing and return error status from
+ * last writes done, to maintain buffered data.
+ */
+static long
+episowrite(Ep *ep, Isoio *iso, void *a, long count)
+{
+ Ctlr *ctlr;
+ uchar *b;
+ int tot;
+ int nw;
+ char *err;
+
+ iso->debug = ep->debug;
+ diprint("uhci: episowrite: %#p ep%d.%d\n", iso, ep->dev->nb, ep->nb);
+
+ ctlr = ep->hp->aux;
+ qlock(iso);
+ if(waserror()){
+ qunlock(iso);
+ nexterror();
+ }
+ ilock(ctlr);
+ if(iso->state == Qclose){
+ iunlock(ctlr);
+ error(iso->err ? iso->err : Eio);
+ }
+ iso->state = Qrun;
+ b = a;
+ for(tot = 0; tot < count; tot += nw){
+ while(isocanwrite(iso) == 0){
+ iunlock(ctlr);
+ diprint("uhci: episowrite: %#p sleep\n", iso);
+ if(waserror()){
+ if(iso->err == nil)
+ iso->err = "I/O timed out";
+ ilock(ctlr);
+ break;
+ }
+ tsleep(iso, isocanwrite, iso, ep->tmout);
+ poperror();
+ ilock(ctlr);
+ }
+ err = iso->err;
+ iso->err = nil;
+ if(iso->state == Qclose || err != nil){
+ iunlock(ctlr);
+ error(err ? err : Eio);
+ }
+ if(iso->state != Qrun)
+ panic("episowrite: iso not running");
+ iunlock(ctlr); /* We could page fault here */
+ nw = putsamples(iso, b+tot, count-tot);
+ ilock(ctlr);
+ }
+ if(iso->state != Qclose)
+ iso->state = Qdone;
+ iunlock(ctlr);
+ err = iso->err; /* in case it failed early */
+ iso->err = nil;
+ qunlock(iso);
+ poperror();
+ if(err != nil)
+ error(err);
+ diprint("uhci: episowrite: %#p %d bytes\n", iso, tot);
+ return tot;
+}
+
+/*
+ * Available data is kept at tdu and following tds, up to tdi (excluded).
+ */
+static long
+episoread(Ep *ep, Isoio *iso, void *a, int count)
+{
+ Ctlr *ctlr;
+ uchar *b;
+ int nr;
+ int tot;
+ Td *tdu;
+
+ iso->debug = ep->debug;
+ diprint("uhci: episoread: %#p ep%d.%d\n", iso, ep->dev->nb, ep->nb);
+
+ b = a;
+ ctlr = ep->hp->aux;
+ qlock(iso);
+ if(waserror()){
+ qunlock(iso);
+ nexterror();
+ }
+ iso->err = nil;
+ iso->nerrs = 0;
+ ilock(ctlr);
+ if(iso->state == Qclose){
+ iunlock(ctlr);
+ error(iso->err ? iso->err : Eio);
+ }
+ iso->state = Qrun;
+ while(isocanread(iso) == 0){
+ iunlock(ctlr);
+ diprint("uhci: episoread: %#p sleep\n", iso);
+ if(waserror()){
+ if(iso->err == nil)
+ iso->err = "I/O timed out";
+ ilock(ctlr);
+ break;
+ }
+ tsleep(iso, isocanread, iso, ep->tmout);
+ poperror();
+ ilock(ctlr);
+ }
+ if(iso->state == Qclose){
+ iunlock(ctlr);
+ error(iso->err ? iso->err : Eio);
+ }
+ iso->state = Qdone;
+ assert(iso->tdu != iso->tdi);
+
+ for(tot = 0; iso->tdi != iso->tdu && tot < count; tot += nr){
+ tdu = iso->tdu;
+ if(tdu->csw & Tdactive){
+ diprint("uhci: episoread: %#p tdu active\n", iso);
+ break;
+ }
+ nr = tdu->ndata;
+ if(tot + nr > count)
+ nr = count - tot;
+ if(nr == 0)
+ print("uhci: ep%d.%d: too many polls\n",
+ ep->dev->nb, ep->nb);
+ else{
+ iunlock(ctlr); /* We could page fault here */
+ memmove(b+tot, tdu->data, nr);
+ ilock(ctlr);
+ if(nr < tdu->ndata)
+ memmove(tdu->data, tdu->data+nr, tdu->ndata - nr);
+ tdu->ndata -= nr;
+ }
+ if(tdu->ndata == 0){
+ tdisoinit(iso, tdu, ep->maxpkt);
+ iso->tdu = tdu->next;
+ }
+ }
+ iunlock(ctlr);
+ qunlock(iso);
+ poperror();
+ diprint("uhci: episoread: %#p %d bytes err '%s'\n", iso, tot, iso->err);
+ if(iso->err != nil)
+ error(iso->err);
+ return tot;
+}
+
+static int
+nexttoggle(int tog)
+{
+ if(tog == Tddata0)
+ return Tddata1;
+ else
+ return Tddata0;
+}
+
+static Td*
+epgettd(Ep *ep, Qio *io, int flags, void *a, int count)
+{
+ Td *td;
+ int tok;
+
+ if(ep->maxpkt < count)
+ error("maxpkt too short");
+ td = tdalloc();
+ if(count <= Tdndata)
+ td->data = td->sbuff;
+ else
+ td->data = td->buff = smalloc(ep->maxpkt);
+ td->buffer = PCIWADDR(td->data);
+ td->ndata = count;
+ if(a != nil && count > 0)
+ memmove(td->data, a, count);
+ td->csw = Tderr2|Tderr1|flags;
+ if(ep->dev->speed == Lowspeed)
+ td->csw |= Tdlow;
+ tok = io->tok | io->toggle;
+ io->toggle = nexttoggle(io->toggle);
+ td->token = ((count-1)<<21) | ((io->usbid&0x7FF)<<8) | tok;
+
+ return td;
+}
+
+/*
+ * Try to get them idle
+ */
+static void
+aborttds(Qh *qh)
+{
+ Td *td;
+
+ qh->state = Qdone;
+ qh->elink = QHterm;
+ for(td = qh->tds; td != nil; td = td->next){
+ if(td->csw & Tdactive)
+ td->ndata = 0;
+ td->csw &= ~(Tdactive|Tdioc);
+ }
+}
+
+static int
+epiodone(void *a)
+{
+ Qh *qh;
+
+ qh = a;
+ return qh->state != Qrun;
+}
+
+static void
+epiowait(Ctlr *ctlr, Qio *io, int tmout, ulong load)
+{
+ Qh *qh;
+ int timedout;
+
+ qh = io->qh;
+ ddqprint("uhci io %#p sleep on qh %#p state %uld\n", io, qh, qh->state);
+ timedout = 0;
+ if(waserror()){
+ dqprint("uhci io %#p qh %#p timed out\n", io, qh);
+ timedout++;
+ }else{
+ if(tmout == 0)
+ sleep(io, epiodone, qh);
+ else
+ tsleep(io, epiodone, qh, tmout);
+ poperror();
+ }
+ ilock(ctlr);
+ if(qh->state == Qrun)
+ timedout = 1;
+ else if(qh->state != Qdone && qh->state != Qclose)
+ panic("epio: queue not done and not closed");
+ if(timedout){
+ aborttds(io->qh);
+ io->err = "request timed out";
+ iunlock(ctlr);
+ if(!waserror()){
+ tsleep(&up->sleep, return0, 0, Abortdelay);
+ poperror();
+ }
+ ilock(ctlr);
+ }
+ if(qh->state != Qclose)
+ qh->state = Qidle;
+ qhlinktd(qh, nil);
+ ctlr->load -= load;
+ iunlock(ctlr);
+}
+
+/*
+ * Non iso I/O.
+ * To make it work for control transfers, the caller may
+ * lock the Qio for the entire control transfer.
+ */
+static long
+epio(Ep *ep, Qio *io, void *a, long count, int mustlock)
+{
+ Td *td, *ltd, *td0, *ntd;
+ Ctlr *ctlr;
+ Qh* qh;
+ long n, tot;
+ char buf[128];
+ uchar *c;
+ int saved, ntds, tmout;
+ ulong load;
+ char *err;
+
+ qh = io->qh;
+ ctlr = ep->hp->aux;
+ io->debug = ep->debug;
+ tmout = ep->tmout;
+ ddeprint("epio: %s ep%d.%d io %#p count %ld load %uld\n",
+ io->tok == Tdtokin ? "in" : "out",
+ ep->dev->nb, ep->nb, io, count, ctlr->load);
+ if((debug > 1 || ep->debug > 1) && io->tok != Tdtokin){
+ seprintdata(buf, buf+sizeof(buf), a, count);
+ print("uchi epio: user data: %s\n", buf);
+ }
+ if(mustlock){
+ qlock(io);
+ if(waserror()){
+ qunlock(io);
+ nexterror();
+ }
+ }
+ io->err = nil;
+ ilock(ctlr);
+ if(qh->state == Qclose){ /* Tds released by cancelio */
+ iunlock(ctlr);
+ error(io->err ? io->err : Eio);
+ }
+ if(qh->state != Qidle)
+ panic("epio: qh not idle");
+ qh->state = Qinstall;
+ iunlock(ctlr);
+
+ c = a;
+ td0 = ltd = nil;
+ load = tot = 0;
+ do{
+ n = ep->maxpkt;
+ if(count-tot < n)
+ n = count-tot;
+ if(c != nil && io->tok != Tdtokin)
+ td = epgettd(ep, io, Tdactive, c+tot, n);
+ else
+ td = epgettd(ep, io, Tdactive|Tdspd, nil, n);
+ if(td0 == nil)
+ td0 = td;
+ else
+ tdlinktd(ltd, td);
+ ltd = td;
+ tot += n;
+ load += ep->load;
+ }while(tot < count);
+ if(td0 == nil || ltd == nil)
+ panic("epio: no td");
+
+ ltd->csw |= Tdioc; /* the last one interrupts */
+ ddeprint("uhci: load %uld ctlr load %uld\n", load, ctlr->load);
+ ilock(ctlr);
+ if(qh->state != Qclose){
+ io->iotime = TK2MS(MACHP(0)->ticks);
+ qh->state = Qrun;
+ coherence();
+ qhlinktd(qh, td0);
+ ctlr->load += load;
+ }
+ iunlock(ctlr);
+
+ epiowait(ctlr, io, tmout, load);
+
+ if(debug > 1 || ep->debug > 1)
+ dumptd(td0, "epio: got tds: ");
+
+ tot = 0;
+ c = a;
+ saved = 0;
+ ntds = 0;
+ for(td = td0; td != nil; td = ntd){
+ ntds++;
+ /*
+ * Use td tok, not io tok, because of setup packets.
+ * Also, if the Td was stalled or active (previous Td
+ * was a short packet), we must save the toggle as it is.
+ */
+ if(td->csw & (Tdstalled|Tdactive)){
+ if(saved++ == 0)
+ io->toggle = td->token & Tddata1;
+ }else{
+ tot += td->ndata;
+ if(c != nil && tdtok(td) == Tdtokin && td->ndata > 0){
+ memmove(c, td->data, td->ndata);
+ c += td->ndata;
+ }
+ }
+ ntd = td->next;
+ tdfree(td);
+ }
+ err = io->err;
+ if(mustlock){
+ qunlock(io);
+ poperror();
+ }
+ ddeprint("epio: io %#p: %d tds: return %ld err '%s'\n",
+ io, ntds, tot, err);
+ if(err != nil)
+ error(err);
+ if(tot < 0)
+ error(Eio);
+ return tot;
+}
+
+/*
+ * halt condition was cleared on the endpoint. update our toggles.
+ */
+static void
+clrhalt(Ep *ep)
+{
+ Qio *io;
+
+ ep->clrhalt = 0;
+ switch(ep->ttype){
+ case Tbulk:
+ case Tintr:
+ io = ep->aux;
+ if(ep->mode != OREAD){
+ qlock(&io[OWRITE]);
+ io[OWRITE].toggle = Tddata0;
+ deprint("ep clrhalt for io %#p\n", io+OWRITE);
+ qunlock(&io[OWRITE]);
+ }
+ if(ep->mode != OWRITE){
+ qlock(&io[OREAD]);
+ io[OREAD].toggle = Tddata0;
+ deprint("ep clrhalt for io %#p\n", io+OREAD);
+ qunlock(&io[OREAD]);
+ }
+ break;
+ }
+}
+
+static long
+epread(Ep *ep, void *a, long count)
+{
+ Ctlio *cio;
+ Qio *io;
+ Isoio *iso;
+ char buf[160];
+ ulong delta;
+
+ ddeprint("uhci: epread\n");
+ if(ep->aux == nil)
+ panic("epread: not open");
+
+ switch(ep->ttype){
+ case Tctl:
+ cio = ep->aux;
+ qlock(cio);
+ if(waserror()){
+ qunlock(cio);
+ nexterror();
+ }
+ ddeprint("epread ctl ndata %d\n", cio->ndata);
+ if(cio->ndata < 0)
+ error("request expected");
+ else if(cio->ndata == 0){
+ cio->ndata = -1;
+ count = 0;
+ }else{
+ if(count > cio->ndata)
+ count = cio->ndata;
+ if(count > 0)
+ memmove(a, cio->data, count);
+ /* BUG for big transfers */
+ free(cio->data);
+ cio->data = nil;
+ cio->ndata = 0; /* signal EOF next time */
+ }
+ qunlock(cio);
+ poperror();
+ if(debug>1 || ep->debug){
+ seprintdata(buf, buf+sizeof(buf), a, count);
+ print("epread: %s\n", buf);
+ }
+ return count;
+ case Tbulk:
+ io = ep->aux;
+ if(ep->clrhalt)
+ clrhalt(ep);
+ return epio(ep, &io[OREAD], a, count, 1);
+ case Tintr:
+ io = ep->aux;
+ delta = TK2MS(MACHP(0)->ticks) - io[OREAD].iotime + 1;
+ if(delta < ep->pollival / 2)
+ tsleep(&up->sleep, return0, 0, ep->pollival/2 - delta);
+ if(ep->clrhalt)
+ clrhalt(ep);
+ return epio(ep, &io[OREAD], a, count, 1);
+ case Tiso:
+ iso = ep->aux;
+ return episoread(ep, iso, a, count);
+ default:
+ panic("epread: bad ep ttype %d", ep->ttype);
+ }
+ return -1;
+}
+
+/*
+ * Control transfers are one setup write (data0)
+ * plus zero or more reads/writes (data1, data0, ...)
+ * plus a final write/read with data1 to ack.
+ * For both host to device and device to host we perform
+ * the entire transfer when the user writes the request,
+ * and keep any data read from the device for a later read.
+ * We call epio three times instead of placing all Tds at
+ * the same time because doing so leads to crc/tmout errors
+ * for some devices.
+ * Upon errors on the data phase we must still run the status
+ * phase or the device may cease responding in the future.
+ */
+static long
+epctlio(Ep *ep, Ctlio *cio, void *a, long count)
+{
+ uchar *c;
+ long len;
+
+ ddeprint("epctlio: cio %#p ep%d.%d count %ld\n",
+ cio, ep->dev->nb, ep->nb, count);
+ if(count < Rsetuplen)
+ error("short usb comand");
+ qlock(cio);
+ free(cio->data);
+ cio->data = nil;
+ cio->ndata = 0;
+ if(waserror()){
+ qunlock(cio);
+ free(cio->data);
+ cio->data = nil;
+ cio->ndata = 0;
+ nexterror();
+ }
+
+ /* set the address if unset and out of configuration state */
+ if(ep->dev->state != Dconfig && ep->dev->state != Dreset)
+ if(cio->usbid == 0)
+ cio->usbid = ((ep->nb&Epmax)<<7)|(ep->dev->nb&Devmax);
+ c = a;
+ cio->tok = Tdtoksetup;
+ cio->toggle = Tddata0;
+ if(epio(ep, cio, a, Rsetuplen, 0) < Rsetuplen)
+ error(Eio);
+ a = c + Rsetuplen;
+ count -= Rsetuplen;
+
+ cio->toggle = Tddata1;
+ if(c[Rtype] & Rd2h){
+ cio->tok = Tdtokin;
+ len = GET2(c+Rcount);
+ if(len <= 0)
+ error("bad length in d2h request");
+ if(len > Maxctllen)
+ error("d2h data too large to fit in uhci");
+ a = cio->data = smalloc(len+1);
+ }else{
+ cio->tok = Tdtokout;
+ len = count;
+ }
+ if(len > 0)
+ if(waserror())
+ len = -1;
+ else{
+ len = epio(ep, cio, a, len, 0);
+ poperror();
+ }
+ if(c[Rtype] & Rd2h){
+ count = Rsetuplen;
+ cio->ndata = len;
+ cio->tok = Tdtokout;
+ }else{
+ if(len < 0)
+ count = -1;
+ else
+ count = Rsetuplen + len;
+ cio->tok = Tdtokin;
+ }
+ cio->toggle = Tddata1;
+ epio(ep, cio, nil, 0, 0);
+ qunlock(cio);
+ poperror();
+ ddeprint("epctlio cio %#p return %ld\n", cio, count);
+ return count;
+}
+
+static long
+epwrite(Ep *ep, void *a, long count)
+{
+ Ctlio *cio;
+ Isoio *iso;
+ Qio *io;
+ ulong delta;
+ char *b;
+ int tot;
+ int nw;
+
+ ddeprint("uhci: epwrite ep%d.%d\n", ep->dev->nb, ep->nb);
+ if(ep->aux == nil)
+ panic("uhci: epwrite: not open");
+ switch(ep->ttype){
+ case Tctl:
+ cio = ep->aux;
+ return epctlio(ep, cio, a, count);
+ case Tbulk:
+ io = ep->aux;
+ if(ep->clrhalt)
+ clrhalt(ep);
+ /*
+ * Put at most Tdatomic Tds (512 bytes) at a time.
+ * Otherwise some devices produce babble errors.
+ */
+ b = a;
+ for(tot = 0; tot < count ; tot += nw){
+ nw = count - tot;
+ if(nw > Tdatomic * ep->maxpkt)
+ nw = Tdatomic * ep->maxpkt;
+ nw = epio(ep, &io[OWRITE], b+tot, nw, 1);
+ }
+ return tot;
+ case Tintr:
+ io = ep->aux;
+ delta = TK2MS(MACHP(0)->ticks) - io[OWRITE].iotime + 1;
+ if(delta < ep->pollival)
+ tsleep(&up->sleep, return0, 0, ep->pollival - delta);
+ if(ep->clrhalt)
+ clrhalt(ep);
+ return epio(ep, &io[OWRITE], a, count, 1);
+ case Tiso:
+ iso = ep->aux;
+ return episowrite(ep, iso, a, count);
+ default:
+ panic("uhci: epwrite: bad ep ttype %d", ep->ttype);
+ }
+ return -1;
+}
+
+static void
+isoopen(Ep *ep)
+{
+ Ctlr *ctlr;
+ Isoio *iso;
+ int frno;
+ int i;
+ Td* td;
+ Td* ltd;
+ int size;
+ int left;
+
+ if(ep->mode == ORDWR)
+ error("iso i/o is half-duplex");
+ ctlr = ep->hp->aux;
+ iso = ep->aux;
+ iso->debug = ep->debug;
+ iso->next = nil; /* paranoia */
+ if(ep->mode == OREAD)
+ iso->tok = Tdtokin;
+ else
+ iso->tok = Tdtokout;
+ iso->usbid = ((ep->nb & Epmax)<<7)|(ep->dev->nb & Devmax);
+ iso->state = Qidle;
+ iso->nframes = Nframes/ep->pollival;
+ if(iso->nframes < 3)
+ error("uhci isoopen bug"); /* we need at least 3 tds */
+
+ ilock(ctlr);
+ if(ctlr->load + ep->load > 800)
+ print("usb: uhci: bandwidth may be exceeded\n");
+ ctlr->load += ep->load;
+ ctlr->isoload += ep->load;
+ dprint("uhci: load %uld isoload %uld\n", ctlr->load, ctlr->isoload);
+ iunlock(ctlr);
+
+ /*
+ * From here on this cannot raise errors
+ * unless we catch them and release here all memory allocated.
+ */
+ if(ep->maxpkt > Tdndata)
+ iso->data = smalloc(iso->nframes*ep->maxpkt);
+ ilock(ctlr);
+ frno = INS(Frnum) + 10; /* start 10ms ahead */
+ frno = TRUNC(frno, Nframes);
+ iunlock(ctlr);
+ iso->td0frno = frno;
+ ltd = nil;
+ left = 0;
+ for(i = 0; i < iso->nframes; i++){
+ td = iso->tdps[frno] = tdalloc();
+ if(ep->mode == OREAD)
+ size = ep->maxpkt;
+ else{
+ size = (ep->hz+left) * ep->pollival / 1000;
+ size *= ep->samplesz;
+ left = (ep->hz+left) * ep->pollival % 1000;
+ if(size > ep->maxpkt){
+ print("uhci: ep%d.%d: size > maxpkt\n",
+ ep->dev->nb, ep->nb);
+ print("size = %d max = %ld\n", size, ep->maxpkt);
+ size = ep->maxpkt;
+ }
+ }
+ if(size > Tdndata)
+ td->data = iso->data + i * ep->maxpkt;
+ else
+ td->data = td->sbuff;
+ td->buffer = PCIWADDR(td->data);
+ tdisoinit(iso, td, size);
+ if(ltd != nil)
+ ltd->next = td;
+ ltd = td;
+ frno = TRUNC(frno+ep->pollival, Nframes);
+ }
+ ltd->next = iso->tdps[iso->td0frno];
+ iso->tdi = iso->tdps[iso->td0frno];
+ iso->tdu = iso->tdi; /* read: right now; write: 1s ahead */
+ ilock(ctlr);
+ frno = iso->td0frno;
+ for(i = 0; i < iso->nframes; i++){
+ iso->tdps[frno]->link = ctlr->frames[frno];
+ frno = TRUNC(frno+ep->pollival, Nframes);
+ }
+ coherence();
+ frno = iso->td0frno;
+ for(i = 0; i < iso->nframes; i++){
+ ctlr->frames[frno] = PCIWADDR(iso->tdps[frno]);
+ frno = TRUNC(frno+ep->pollival, Nframes);
+ }
+ iso->next = ctlr->iso;
+ ctlr->iso = iso;
+ iso->state = Qdone;
+ iunlock(ctlr);
+ if(debug > 1 || iso->debug >1)
+ isodump(iso, 0);
+}
+
+/*
+ * Allocate the endpoint and set it up for I/O
+ * in the controller. This must follow what's said
+ * in Ep regarding configuration, including perhaps
+ * the saved toggles (saved on a previous close of
+ * the endpoint data file by epclose).
+ */
+static void
+epopen(Ep *ep)
+{
+ Ctlr *ctlr;
+ Qh *cqh;
+ Qio *io;
+ Ctlio *cio;
+ int usbid;
+
+ ctlr = ep->hp->aux;
+ deprint("uhci: epopen ep%d.%d\n", ep->dev->nb, ep->nb);
+ if(ep->aux != nil)
+ panic("uhci: epopen called with open ep");
+ if(waserror()){
+ free(ep->aux);
+ ep->aux = nil;
+ nexterror();
+ }
+ if(ep->maxpkt > Tdmaxpkt){
+ print("uhci: maxkpkt too large: using %d\n", Tdmaxpkt);
+ ep->maxpkt = Tdmaxpkt;
+ }
+ cqh = ctlr->qh[ep->ttype];
+ switch(ep->ttype){
+ case Tnone:
+ error("endpoint not configured");
+ case Tiso:
+ ep->aux = smalloc(sizeof(Isoio));
+ isoopen(ep);
+ break;
+ case Tctl:
+ cio = ep->aux = smalloc(sizeof(Ctlio));
+ cio->debug = ep->debug;
+ cio->ndata = -1;
+ cio->data = nil;
+ if(ep->dev->isroot != 0 && ep->nb == 0) /* root hub */
+ break;
+ cio->qh = qhalloc(ctlr, cqh, cio, "epc");
+ break;
+ case Tbulk:
+ case Tintr:
+ io = ep->aux = smalloc(sizeof(Qio)*2);
+ io[OREAD].debug = io[OWRITE].debug = ep->debug;
+ usbid = ((ep->nb&Epmax)<<7)|(ep->dev->nb &Devmax);
+ if(ep->mode != OREAD){
+ if(ep->toggle[OWRITE] != 0)
+ io[OWRITE].toggle = Tddata1;
+ else
+ io[OWRITE].toggle = Tddata0;
+ io[OWRITE].tok = Tdtokout;
+ io[OWRITE].qh = qhalloc(ctlr, cqh, io+OWRITE, "epw");
+ io[OWRITE].usbid = usbid;
+ }
+ if(ep->mode != OWRITE){
+ if(ep->toggle[OREAD] != 0)
+ io[OREAD].toggle = Tddata1;
+ else
+ io[OREAD].toggle = Tddata0;
+ io[OREAD].tok = Tdtokin;
+ io[OREAD].qh = qhalloc(ctlr, cqh, io+OREAD, "epr");
+ io[OREAD].usbid = usbid;
+ }
+ break;
+ }
+ if(debug>1 || ep->debug)
+ dump(ep->hp);
+ deprint("uhci: epopen done\n");
+ poperror();
+}
+
+static void
+cancelio(Ctlr *ctlr, Qio *io)
+{
+ Qh *qh;
+
+ ilock(ctlr);
+ qh = io->qh;
+ if(io == nil || io->qh == nil || io->qh->state == Qclose){
+ iunlock(ctlr);
+ return;
+ }
+ dqprint("uhci: cancelio for qh %#p state %s\n",
+ qh, qhsname[qh->state]);
+ aborttds(qh);
+ qh->state = Qclose;
+ iunlock(ctlr);
+ if(!waserror()){
+ tsleep(&up->sleep, return0, 0, Abortdelay);
+ poperror();
+ }
+
+ wakeup(io);
+ qlock(io);
+ /* wait for epio if running */
+ qunlock(io);
+
+ qhfree(ctlr, qh);
+ io->qh = nil;
+}
+
+static void
+cancelisoio(Ctlr *ctlr, Isoio *iso, int pollival, ulong load)
+{
+ Isoio **il;
+ ulong *lp;
+ int i;
+ int frno;
+ Td *td;
+
+ ilock(ctlr);
+ if(iso->state == Qclose){
+ iunlock(ctlr);
+ return;
+ }
+ if(iso->state != Qrun && iso->state != Qdone)
+ panic("bad iso state");
+ iso->state = Qclose;
+ if(ctlr->isoload < load)
+ panic("uhci: low isoload");
+ ctlr->isoload -= load;
+ ctlr->load -= load;
+ for(il = &ctlr->iso; *il != nil; il = &(*il)->next)
+ if(*il == iso)
+ break;
+ if(*il == nil)
+ panic("isocancel: not found");
+ *il = iso->next;
+ frno = iso->td0frno;
+ for(i = 0; i < iso->nframes; i++){
+ td = iso->tdps[frno];
+ td->csw &= ~(Tdioc|Tdactive);
+ for(lp=&ctlr->frames[frno]; !(*lp & Tdterm);
+ lp = &TPTR(*lp)->link)
+ if(TPTR(*lp) == td)
+ break;
+ if(*lp & Tdterm)
+ panic("cancelisoio: td not found");
+ *lp = td->link;
+ frno = TRUNC(frno+pollival, Nframes);
+ }
+ iunlock(ctlr);
+
+ /*
+ * wakeup anyone waiting for I/O and
+ * wait to be sure no I/O is in progress in the controller.
+ * and then wait to be sure episo-io is no longer running.
+ */
+ wakeup(iso);
+ diprint("cancelisoio iso %#p waiting for I/O to cease\n", iso);
+ tsleep(&up->sleep, return0, 0, 5);
+ qlock(iso);
+ qunlock(iso);
+ diprint("cancelisoio iso %#p releasing iso\n", iso);
+
+ frno = iso->td0frno;
+ for(i = 0; i < iso->nframes; i++){
+ tdfree(iso->tdps[frno]);
+ iso->tdps[frno] = nil;
+ frno = TRUNC(frno+pollival, Nframes);
+ }
+ free(iso->data);
+ iso->data = nil;
+}
+
+static void
+epclose(Ep *ep)
+{
+ Ctlr *ctlr;
+ Ctlio *cio;
+ Isoio *iso;
+ Qio *io;
+
+ ctlr = ep->hp->aux;
+ deprint("uhci: epclose ep%d.%d\n", ep->dev->nb, ep->nb);
+
+ if(ep->aux == nil)
+ panic("uhci: epclose called with closed ep");
+ switch(ep->ttype){
+ case Tctl:
+ cio = ep->aux;
+ cancelio(ctlr, cio);
+ free(cio->data);
+ cio->data = nil;
+ break;
+ case Tbulk:
+ case Tintr:
+ io = ep->aux;
+ ep->toggle[OREAD] = ep->toggle[OWRITE] = 0;
+ if(ep->mode != OWRITE){
+ cancelio(ctlr, &io[OREAD]);
+ if(io[OREAD].toggle == Tddata1)
+ ep->toggle[OREAD] = 1;
+ }
+ if(ep->mode != OREAD){
+ cancelio(ctlr, &io[OWRITE]);
+ if(io[OWRITE].toggle == Tddata1)
+ ep->toggle[OWRITE] = 1;
+ }
+ break;
+ case Tiso:
+ iso = ep->aux;
+ cancelisoio(ctlr, iso, ep->pollival, ep->load);
+ break;
+ default:
+ panic("epclose: bad ttype %d", ep->ttype);
+ }
+
+ free(ep->aux);
+ ep->aux = nil;
+
+}
+
+static char*
+seprintep(char *s, char *e, Ep *ep)
+{
+ Ctlio *cio;
+ Qio *io;
+ Isoio *iso;
+ Ctlr *ctlr;
+
+ ctlr = ep->hp->aux;
+ ilock(ctlr);
+ if(ep->aux == nil){
+ *s = 0;
+ iunlock(ctlr);
+ return s;
+ }
+ switch(ep->ttype){
+ case Tctl:
+ cio = ep->aux;
+ s = seprint(s,e,"cio %#p qh %#p"
+ " id %#x tog %#x tok %#x err %s\n",
+ cio, cio->qh, cio->usbid, cio->toggle,
+ cio->tok, cio->err);
+ break;
+ case Tbulk:
+ case Tintr:
+ io = ep->aux;
+ if(ep->mode != OWRITE)
+ s = seprint(s,e,"r: qh %#p id %#x tog %#x tok %#x err %s\n",
+ io[OREAD].qh, io[OREAD].usbid, io[OREAD].toggle,
+ io[OREAD].tok, io[OREAD].err);
+ if(ep->mode != OREAD)
+ s = seprint(s,e,"w: qh %#p id %#x tog %#x tok %#x err %s\n",
+ io[OWRITE].qh, io[OWRITE].usbid, io[OWRITE].toggle,
+ io[OWRITE].tok, io[OWRITE].err);
+ break;
+ case Tiso:
+ iso = ep->aux;
+ s = seprint(s,e,"iso %#p id %#x tok %#x tdu %#p tdi %#p err %s\n",
+ iso, iso->usbid, iso->tok, iso->tdu, iso->tdi, iso->err);
+ break;
+ }
+ iunlock(ctlr);
+ return s;
+}
+
+static int
+portenable(Hci *hp, int port, int on)
+{
+ int s;
+ int ioport;
+ Ctlr *ctlr;
+
+ ctlr = hp->aux;
+ dprint("uhci: %#x port %d enable=%d\n", ctlr->port, port, on);
+ ioport = PORT(port-1);
+ qlock(&ctlr->portlck);
+ if(waserror()){
+ qunlock(&ctlr->portlck);
+ nexterror();
+ }
+ ilock(ctlr);
+ s = INS(ioport);
+ if(on)
+ OUTS(ioport, s | PSenable);
+ else
+ OUTS(ioport, s & ~PSenable);
+ microdelay(64);
+ iunlock(ctlr);
+ tsleep(&up->sleep, return0, 0, Enabledelay);
+ dprint("uhci %#ux port %d enable=%d: sts %#x\n",
+ ctlr->port, port, on, INS(ioport));
+ qunlock(&ctlr->portlck);
+ poperror();
+ return 0;
+}
+
+static int
+portreset(Hci *hp, int port, int on)
+{
+ int i, p;
+ Ctlr *ctlr;
+
+ if(on == 0)
+ return 0;
+ ctlr = hp->aux;
+ dprint("uhci: %#ux port %d reset\n", ctlr->port, port);
+ p = PORT(port-1);
+ ilock(ctlr);
+ OUTS(p, PSreset);
+ delay(50);
+ OUTS(p, INS(p) & ~PSreset);
+ OUTS(p, INS(p) | PSenable);
+ microdelay(64);
+ for(i=0; i<1000 && (INS(p) & PSenable) == 0; i++)
+ ;
+ OUTS(p, (INS(p) & ~PSreset)|PSenable);
+ iunlock(ctlr);
+ dprint("uhci %#ux after port %d reset: sts %#x\n",
+ ctlr->port, port, INS(p));
+ return 0;
+}
+
+static int
+portstatus(Hci *hp, int port)
+{
+ int s;
+ int r;
+ int ioport;
+ Ctlr *ctlr;
+
+ ctlr = hp->aux;
+ ioport = PORT(port-1);
+ qlock(&ctlr->portlck);
+ if(waserror()){
+ iunlock(ctlr);
+ qunlock(&ctlr->portlck);
+ nexterror();
+ }
+ ilock(ctlr);
+ s = INS(ioport);
+ if(s & (PSstatuschg | PSchange)){
+ OUTS(ioport, s);
+ ddprint("uhci %#ux port %d status %#x\n", ctlr->port, port, s);
+ }
+ iunlock(ctlr);
+ qunlock(&ctlr->portlck);
+ poperror();
+
+ /*
+ * We must return status bits as a
+ * get port status hub request would do.
+ */
+ r = 0;
+ if(s & PSpresent)
+ r |= HPpresent;
+ if(s & PSenable)
+ r |= HPenable;
+ if(s & PSsuspend)
+ r |= HPsuspend;
+ if(s & PSreset)
+ r |= HPreset;
+ if(s & PSslow)
+ r |= HPslow;
+ if(s & PSstatuschg)
+ r |= HPstatuschg;
+ if(s & PSchange)
+ r |= HPchange;
+ return r;
+}
+
+static void
+scanpci(void)
+{
+ static int already = 0;
+ int io;
+ int i;
+ Ctlr *ctlr;
+ Pcidev *p;
+
+ if(already)
+ return;
+ already = 1;
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ /*
+ * Find UHCI controllers (Programming Interface = 0).
+ */
+ if(p->ccrb != Pcibcserial || p->ccru != Pciscusb)
+ continue;
+ switch(p->ccrp){
+ case 0:
+ io = p->mem[4].bar & ~0x0F;
+ break;
+ default:
+ continue;
+ }
+ if(io == 0){
+ print("usbuhci: %#x %#x: failed to map registers\n",
+ p->vid, p->did);
+ continue;
+ }
+ if(ioalloc(io, p->mem[4].size, 0, "usbuhci") < 0){
+ print("usbuhci: port %#ux in use\n", io);
+ continue;
+ }
+ if(p->intl == 0xFF || p->intl == 0){
+ print("usbuhci: no irq assigned for port %#ux\n", io);
+ continue;
+ }
+
+ dprint("uhci: %#x %#x: port %#ux size %#x irq %d\n",
+ p->vid, p->did, io, p->mem[4].size, p->intl);
+
+ ctlr = smalloc(sizeof(Ctlr));
+ ctlr->pcidev = p;
+ ctlr->port = io;
+ for(i = 0; i < Nhcis; i++)
+ if(ctlrs[i] == nil){
+ ctlrs[i] = ctlr;
+ break;
+ }
+ if(i == Nhcis)
+ print("uhci: bug: no more controllers\n");
+ }
+}
+
+static void
+uhcimeminit(Ctlr *ctlr)
+{
+ Td* td;
+ Qh *qh;
+ int frsize;
+ int i;
+
+ ctlr->qhs = ctlr->qh[Tctl] = qhalloc(ctlr, nil, nil, "CTL");
+ ctlr->qh[Tintr] = qhalloc(ctlr, ctlr->qh[Tctl], nil, "INT");
+ ctlr->qh[Tbulk] = qhalloc(ctlr, ctlr->qh[Tintr], nil, "BLK");
+
+ /* idle Td from dummy Qh at the end. looped back to itself */
+ /* This is a workaround for PIIX4 errata 29773804.pdf */
+ qh = qhalloc(ctlr, ctlr->qh[Tbulk], nil, "BWS");
+ td = tdalloc();
+ td->link = PCIWADDR(td);
+ qhlinktd(qh, td);
+
+ /* loop (hw only) from the last qh back to control xfers.
+ * this may be done only for some of them. Disable until ehci comes.
+ */
+ if(0)
+ qh->link = PCIWADDR(ctlr->qhs);
+
+ frsize = Nframes*sizeof(ulong);
+ ctlr->frames = xspanalloc(frsize, frsize, 0);
+ if(ctlr->frames == nil)
+ panic("uhci reset: no memory");
+
+ ctlr->iso = nil;
+ for(i = 0; i < Nframes; i++)
+ ctlr->frames[i] = PCIWADDR(ctlr->qhs)|QHlinkqh;
+ OUTL(Flbaseadd, PCIWADDR(ctlr->frames));
+ OUTS(Frnum, 0);
+ dprint("uhci %#ux flb %#ulx frno %#ux\n", ctlr->port,
+ INL(Flbaseadd), INS(Frnum));
+}
+
+static void
+init(Hci *hp)
+{
+ Ctlr *ctlr;
+ int sts;
+ int i;
+
+ ctlr = hp->aux;
+ dprint("uhci %#ux init\n", ctlr->port);
+ coherence();
+ ilock(ctlr);
+ OUTS(Usbintr, Itmout|Iresume|Ioc|Ishort);
+ uhcirun(ctlr, 1);
+ dprint("uhci: init: cmd %#ux sts %#ux sof %#ux",
+ INS(Cmd), INS(Status), INS(SOFmod));
+ dprint(" flb %#ulx frno %#ux psc0 %#ux psc1 %#ux",
+ INL(Flbaseadd), INS(Frnum), INS(PORT(0)), INS(PORT(1)));
+ /* guess other ports */
+ for(i = 2; i < 6; i++){
+ sts = INS(PORT(i));
+ if(sts != 0xFFFF && (sts & PSreserved1) == 1){
+ dprint(" psc%d %#ux", i, sts);
+ hp->nports++;
+ }else
+ break;
+ }
+ for(i = 0; i < hp->nports; i++)
+ OUTS(PORT(i), 0);
+ iunlock(ctlr);
+}
+
+static void
+uhcireset(Ctlr *ctlr)
+{
+ int i;
+ int sof;
+
+ ilock(ctlr);
+ dprint("uhci %#ux reset\n", ctlr->port);
+
+ /*
+ * Turn off legacy mode. Some controllers won't
+ * interrupt us as expected otherwise.
+ */
+ uhcirun(ctlr, 0);
+ pcicfgw16(ctlr->pcidev, 0xc0, 0x2000);
+
+ OUTS(Usbintr, 0);
+ sof = INB(SOFmod);
+ uhcicmd(ctlr, Cgreset); /* global reset */
+ delay(Resetdelay);
+ uhcicmd(ctlr, 0); /* all halt */
+ uhcicmd(ctlr, Chcreset); /* controller reset */
+ for(i = 0; i < 100; i++){
+ if((INS(Cmd) & Chcreset) == 0)
+ break;
+ delay(1);
+ }
+ if(i == 100)
+ print("uhci %#x controller reset timed out\n", ctlr->port);
+ OUTB(SOFmod, sof);
+ iunlock(ctlr);
+}
+
+static void
+setdebug(Hci*, int d)
+{
+ debug = d;
+}
+
+static void
+shutdown(Hci *hp)
+{
+ Ctlr *ctlr;
+
+ ctlr = hp->aux;
+
+ ilock(ctlr);
+ uhcirun(ctlr, 0);
+ delay(100);
+ iunlock(ctlr);
+}
+
+static int
+reset(Hci *hp)
+{
+ static Lock resetlck;
+ int i;
+ Ctlr *ctlr;
+ Pcidev *p;
+
+ if(getconf("*nousbuhci"))
+ return -1;
+
+ ilock(&resetlck);
+ scanpci();
+
+ /*
+ * Any adapter matches if no hp->port is supplied,
+ * otherwise the ports must match.
+ */
+ ctlr = nil;
+ for(i = 0; i < Nhcis && ctlrs[i] != nil; i++){
+ ctlr = ctlrs[i];
+ if(ctlr->active == 0)
+ if(hp->port == 0 || hp->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ iunlock(&resetlck);
+ if(ctlrs[i] == nil || i == Nhcis)
+ return -1;
+
+ p = ctlr->pcidev;
+ hp->aux = ctlr;
+ hp->port = ctlr->port;
+ hp->irq = p->intl;
+ hp->tbdf = p->tbdf;
+ hp->nports = 2; /* default */
+
+ uhcireset(ctlr);
+ uhcimeminit(ctlr);
+
+ /*
+ * Linkage to the generic HCI driver.
+ */
+ hp->init = init;
+ hp->dump = dump;
+ hp->interrupt = interrupt;
+ hp->epopen = epopen;
+ hp->epclose = epclose;
+ hp->epread = epread;
+ hp->epwrite = epwrite;
+ hp->seprintep = seprintep;
+ hp->portenable = portenable;
+ hp->portreset = portreset;
+ hp->portstatus = portstatus;
+ hp->shutdown = shutdown;
+ hp->debug = setdebug;
+ hp->type = "uhci";
+ return 0;
+}
+
+void
+usbuhcilink(void)
+{
+ addhcitype("uhci", reset);
+}
diff --git a/sys/src/9/pc/vga.c b/sys/src/9/pc/vga.c
new file mode 100755
index 000000000..587d8c185
--- /dev/null
+++ b/sys/src/9/pc/vga.c
@@ -0,0 +1,263 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+static Memimage* back;
+static Memimage *conscol;
+
+static Point curpos;
+static Rectangle window;
+static int *xp;
+static int xbuf[256];
+Lock vgascreenlock;
+int drawdebug;
+
+void
+vgaimageinit(ulong chan)
+{
+ if(back == nil){
+ back = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */
+ if(back == nil)
+ panic("back alloc"); /* RSC BUG */
+ back->flags |= Frepl;
+ back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
+ memfillcolor(back, DBlack);
+ }
+
+ if(conscol == nil){
+ conscol = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */
+ if(conscol == nil)
+ panic("conscol alloc"); /* RSC BUG */
+ conscol->flags |= Frepl;
+ conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
+ memfillcolor(conscol, DWhite);
+ }
+}
+
+static void
+vgascroll(VGAscr* scr)
+{
+ int h, o;
+ Point p;
+ Rectangle r;
+
+ h = scr->memdefont->height;
+ o = 8*h;
+ r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
+ p = Pt(window.min.x, window.min.y+o);
+ memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p, S);
+ r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
+ memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S);
+
+ curpos.y -= o;
+}
+
+static void
+vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)
+{
+ Point p;
+ int h, w, pos;
+ Rectangle r;
+
+// drawdebug = 1;
+ if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
+ xp = xbuf;
+
+ h = scr->memdefont->height;
+ switch(buf[0]){
+
+ case '\n':
+ if(curpos.y+h >= window.max.y){
+ vgascroll(scr);
+ *flushr = window;
+ }
+ curpos.y += h;
+ vgascreenputc(scr, "\r", flushr);
+ break;
+
+ case '\r':
+ xp = xbuf;
+ curpos.x = window.min.x;
+ break;
+
+ case '\t':
+ p = memsubfontwidth(scr->memdefont, " ");
+ w = p.x;
+ if(curpos.x >= window.max.x-4*w)
+ vgascreenputc(scr, "\n", flushr);
+
+ pos = (curpos.x-window.min.x)/w;
+ pos = 4-(pos%4);
+ *xp++ = curpos.x;
+ r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
+ memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
+ curpos.x += pos*w;
+ break;
+
+ case '\b':
+ if(xp <= xbuf)
+ break;
+ xp--;
+ r = Rect(*xp, curpos.y, curpos.x, curpos.y+h);
+ memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP, S);
+ combinerect(flushr, r);
+ curpos.x = *xp;
+ break;
+
+ case '\0':
+ break;
+
+ default:
+ p = memsubfontwidth(scr->memdefont, buf);
+ w = p.x;
+
+ if(curpos.x >= window.max.x-w)
+ vgascreenputc(scr, "\n", flushr);
+
+ *xp++ = curpos.x;
+ r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h);
+ memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
+ memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf);
+ combinerect(flushr, r);
+ curpos.x += w;
+ }
+// drawdebug = 0;
+}
+
+static void
+vgascreenputs(char* s, int n)
+{
+ int i, gotdraw;
+ Rune r;
+ char buf[4];
+ VGAscr *scr;
+ Rectangle flushr;
+
+ scr = &vgascreen[0];
+
+ if(!islo()){
+ /*
+ * Don't deadlock trying to
+ * print in an interrupt.
+ */
+ if(!canlock(&vgascreenlock))
+ return;
+ }
+ 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){
+ i = chartorune(&r, s);
+ if(i == 0){
+ s++;
+ --n;
+ continue;
+ }
+ memmove(buf, s, i);
+ buf[i] = 0;
+ n -= i;
+ s += i;
+ vgascreenputc(scr, buf, &flushr);
+ }
+ flushmemscreen(flushr);
+
+ if(gotdraw)
+ qunlock(&drawlock);
+ unlock(&vgascreenlock);
+}
+
+void
+vgascreenwin(VGAscr* scr)
+{
+ int h, w;
+
+ h = scr->memdefont->height;
+ w = scr->memdefont->info[' '].width;
+
+ window = insetrect(scr->gscreen->r, 48);
+ window.max.x = window.min.x+((window.max.x-window.min.x)/w)*w;
+ window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
+ curpos = window.min;
+
+ screenputs = vgascreenputs;
+}
+
+/*
+ * Supposedly this is the way to turn DPMS
+ * monitors off using just the VGA registers.
+ * Unfortunately, it seems to mess up the video mode
+ * on the cards I've tried.
+ */
+void
+vgablank(VGAscr*, int blank)
+{
+ uchar seq1, crtc17;
+
+ if(blank) {
+ seq1 = 0x00;
+ crtc17 = 0x80;
+ } else {
+ seq1 = 0x20;
+ crtc17 = 0x00;
+ }
+
+ outs(Seqx, 0x0100); /* synchronous reset */
+ seq1 |= vgaxi(Seqx, 1) & ~0x20;
+ vgaxo(Seqx, 1, seq1);
+ crtc17 |= vgaxi(Crtx, 0x17) & ~0x80;
+ delay(10);
+ vgaxo(Crtx, 0x17, crtc17);
+ outs(Crtx, 0x0300); /* end synchronous reset */
+}
+
+void
+addvgaseg(char *name, ulong pa, ulong size)
+{
+ Physseg seg;
+
+ memset(&seg, 0, sizeof seg);
+ seg.attr = SG_PHYSICAL;
+ seg.name = name;
+ seg.pa = pa;
+ seg.size = size;
+ addphysseg(&seg);
+}
+
+void
+cornerstring(char *s)
+{
+ int h, w;
+ VGAscr *scr;
+ Rectangle r;
+ Point p;
+
+ scr = &vgascreen[0];
+ if(scr->vaddr == nil || screenputs != vgascreenputs)
+ return;
+ p = memsubfontwidth(scr->memdefont, s);
+ w = p.x;
+ h = scr->memdefont->height;
+
+ r = Rect(0, 0, w, h);
+ memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
+ memimagestring(scr->gscreen, r.min, conscol, ZP, scr->memdefont, s);
+// flushmemscreen(r);
+}
diff --git a/sys/src/9/pc/vga3dfx.c b/sys/src/9/pc/vga3dfx.c
new file mode 100755
index 000000000..d7a052070
--- /dev/null
+++ b/sys/src/9/pc/vga3dfx.c
@@ -0,0 +1,202 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+typedef struct Cursor3dfx Cursor3dfx;
+struct Cursor3dfx {
+ int vidProcCfg;
+ int hwCurPatAddr;
+ int hwCurLoc;
+ int hwCurC0;
+ int hwCurC1;
+};
+
+enum {
+ dramInit0 = 0x18,
+ dramInit1 = 0x1C,
+
+ hwCur = 0x5C,
+};
+
+static void
+tdfxenable(VGAscr* scr)
+{
+ Pcidev *p;
+ int i, *mmio;
+
+ if(scr->mmio)
+ return;
+ if(p = pcimatch(nil, 0x121A, 0)){
+ switch(p->did){
+ case 0x0003: /* Banshee */
+ case 0x0005: /* Avenger (a.k.a. Voodoo3) */
+ break;
+ default:
+ return;
+ }
+ }
+ else
+ return;
+
+ scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
+ if(scr->mmio == nil)
+ return;
+ 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.
+ * If SDRAM then there's 16MB memory else it's SGRAM
+ * and can count it based on the power-on straps -
+ * chip size can be 8Mb or 16Mb, and there can be 4 or
+ * 8 of them.
+ * Use the last 1KB of the framebuffer.
+ */
+ mmio = (void*)((uchar*)scr->mmio+dramInit0);
+ if(*(mmio+1) & 0x40000000)
+ i = 16*1024*1024;
+ else{
+ if(*mmio & 0x08000000)
+ i = 16*1024*1024/8;
+ else
+ i = 8*1024*1024/8;
+ if(*mmio & 0x04000000)
+ i *= 8;
+ else
+ i *= 4;
+ }
+ scr->storage = i - 1024;
+}
+
+static void
+tdfxcurdisable(VGAscr* scr)
+{
+ Cursor3dfx *cursor3dfx;
+
+ if(scr->mmio == 0)
+ return;
+ cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
+ cursor3dfx->vidProcCfg &= ~0x08000000;
+}
+
+static void
+tdfxcurload(VGAscr* scr, Cursor* curs)
+{
+ int y;
+ uchar *p;
+ Cursor3dfx *cursor3dfx;
+
+ if(scr->mmio == 0)
+ return;
+ cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
+
+ /*
+ * Disable the cursor then load the new image in
+ * the top-left of the 64x64 array.
+ * The cursor data is stored in memory as 128-bit
+ * words consisting of plane 0 in the least significant 64-bits
+ * and plane 1 in the most significant.
+ * The X11 cursor truth table is:
+ * p0 p1 colour
+ * 0 0 transparent
+ * 0 1 transparent
+ * 1 0 hwCurC0
+ * 1 1 hwCurC1
+ * Unused portions of the image have been initialised to be
+ * transparent.
+ */
+ cursor3dfx->vidProcCfg &= ~0x08000000;
+ 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];
+ p += 6;
+ *p++ = curs->set[2*y];
+ *p++ = curs->set[2*y+1];
+ p += 6;
+ }
+
+ /*
+ * Save the cursor hotpoint and enable the cursor.
+ * The 0,0 cursor point is bottom-right.
+ */
+ scr->offset.x = 63+curs->offset.x;
+ scr->offset.y = 63+curs->offset.y;
+ cursor3dfx->vidProcCfg |= 0x08000000;
+}
+
+static int
+tdfxcurmove(VGAscr* scr, Point p)
+{
+ Cursor3dfx *cursor3dfx;
+
+ if(scr->mmio == 0)
+ return 1;
+ cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
+
+ cursor3dfx->hwCurLoc = ((p.y+scr->offset.y)<<16)|(p.x+scr->offset.x);
+
+ return 0;
+}
+
+static void
+tdfxcurenable(VGAscr* scr)
+{
+ Cursor3dfx *cursor3dfx;
+
+ tdfxenable(scr);
+ if(scr->mmio == 0)
+ return;
+ cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
+
+ /*
+ * Cursor colours.
+ */
+ cursor3dfx->hwCurC0 = 0xFFFFFFFF;
+ cursor3dfx->hwCurC1 = 0x00000000;
+
+ /*
+ * Initialise the 64x64 cursor to be transparent (X11 mode).
+ */
+ cursor3dfx->hwCurPatAddr = scr->storage;
+ memset((uchar*)scr->vaddr + scr->storage, 0, 64*16);
+
+ /*
+ * Load, locate and enable the 64x64 cursor in X11 mode.
+ */
+ tdfxcurload(scr, &arrow);
+ tdfxcurmove(scr, ZP);
+ cursor3dfx->vidProcCfg |= 0x08000002;
+}
+
+VGAdev vga3dfxdev = {
+ "3dfx",
+
+ tdfxenable,
+ nil,
+ nil,
+ nil,
+};
+
+VGAcur vga3dfxcur = {
+ "3dfxhwgc",
+
+ tdfxcurenable,
+ tdfxcurdisable,
+ tdfxcurload,
+ tdfxcurmove,
+};
diff --git a/sys/src/9/pc/vgaark2000pv.c b/sys/src/9/pc/vgaark2000pv.c
new file mode 100755
index 000000000..542a7b3a2
--- /dev/null
+++ b/sys/src/9/pc/vgaark2000pv.c
@@ -0,0 +1,191 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+static int
+ark2000pvpageset(VGAscr*, int page)
+{
+ uchar seq15;
+
+ seq15 = vgaxi(Seqx, 0x15);
+ vgaxo(Seqx, 0x15, page);
+ vgaxo(Seqx, 0x16, page);
+
+ return seq15;
+}
+
+static void
+ark2000pvpage(VGAscr* scr, int page)
+{
+ lock(&scr->devlock);
+ ark2000pvpageset(scr, page);
+ unlock(&scr->devlock);
+}
+
+static void
+ark2000pvdisable(VGAscr*)
+{
+ uchar seq20;
+
+ seq20 = vgaxi(Seqx, 0x20) & ~0x08;
+ vgaxo(Seqx, 0x20, seq20);
+}
+
+static void
+ark2000pvenable(VGAscr* scr)
+{
+ uchar seq20;
+ ulong storage;
+
+ /*
+ * Disable the cursor then configure for X-Windows style,
+ * 32x32 and 4/8-bit colour depth.
+ * Set cursor colours for 4/8-bit.
+ */
+ seq20 = vgaxi(Seqx, 0x20) & ~0x1F;
+ vgaxo(Seqx, 0x20, seq20);
+ seq20 |= 0x18;
+
+ vgaxo(Seqx, 0x26, 0x00);
+ vgaxo(Seqx, 0x27, 0x00);
+ vgaxo(Seqx, 0x28, 0x00);
+ vgaxo(Seqx, 0x29, 0xFF);
+ vgaxo(Seqx, 0x2A, 0xFF);
+ vgaxo(Seqx, 0x2B, 0xFF);
+
+ /*
+ * Cursor storage is a 256 byte or 1Kb block located in the last
+ * 16Kb of video memory. Crt25 is the index of which block.
+ */
+ storage = (vgaxi(Seqx, 0x10)>>6) & 0x03;
+ storage = (1024*1024)<<storage;
+ storage -= 256;
+ scr->storage = storage;
+ vgaxo(Seqx, 0x25, 0x3F);
+
+ /*
+ * Enable the cursor.
+ */
+ vgaxo(Seqx, 0x20, seq20);
+}
+
+static void
+ark2000pvload(VGAscr* scr, Cursor* curs)
+{
+ uchar *p, seq10;
+ int opage, x, y;
+
+ /*
+ * Is linear addressing turned on? This will determine
+ * how we access the cursor storage.
+ */
+ seq10 = vgaxi(Seqx, 0x10);
+ opage = 0;
+ p = scr->vaddr;
+ if(!(seq10 & 0x10)){
+ lock(&scr->devlock);
+ opage = ark2000pvpageset(scr, scr->storage>>16);
+ p += (scr->storage & 0xFFFF);
+ }
+ else
+ p += scr->storage;
+
+ /*
+ * The cursor is set in X11 mode which gives the following
+ * truth table:
+ * and xor colour
+ * 0 0 underlying pixel colour
+ * 0 1 underlying pixel colour
+ * 1 0 background colour
+ * 1 1 foreground colour
+ * Put the cursor into the top-left of the 32x32 array.
+ * The manual doesn't say what the data layout in memory is -
+ * this worked out by trial and error.
+ */
+ for(y = 0; y < 32; y++){
+ for(x = 0; x < 32/8; x++){
+ if(x < 16/8 && y < 16){
+ *p++ = curs->clr[2*y + x]|curs->set[2*y + x];
+ *p++ = curs->set[2*y + x];
+ }
+ else {
+ *p++ = 0x00;
+ *p++ = 0x00;
+ }
+ }
+ }
+
+ if(!(seq10 & 0x10)){
+ ark2000pvpageset(scr, opage);
+ unlock(&scr->devlock);
+ }
+
+ /*
+ * Save the cursor hotpoint.
+ */
+ scr->offset = curs->offset;
+}
+
+static int
+ark2000pvmove(VGAscr* scr, Point p)
+{
+ int x, xo, y, yo;
+
+ /*
+ * Mustn't position the cursor offscreen even partially,
+ * or it might disappear. Therefore, if x or y is -ve, adjust the
+ * cursor origins instead.
+ */
+ if((x = p.x+scr->offset.x) < 0){
+ xo = -x;
+ x = 0;
+ }
+ else
+ xo = 0;
+ if((y = p.y+scr->offset.y) < 0){
+ yo = -y;
+ y = 0;
+ }
+ else
+ yo = 0;
+
+ /*
+ * Load the new values.
+ */
+ vgaxo(Seqx, 0x2C, xo);
+ vgaxo(Seqx, 0x2D, yo);
+ vgaxo(Seqx, 0x21, (x>>8) & 0x0F);
+ vgaxo(Seqx, 0x22, x & 0xFF);
+ vgaxo(Seqx, 0x23, (y>>8) & 0x0F);
+ vgaxo(Seqx, 0x24, y & 0xFF);
+
+ return 0;
+}
+
+VGAdev vgaark2000pvdev = {
+ "ark2000pv",
+
+ 0,
+ 0,
+ ark2000pvpage,
+ 0,
+};
+
+VGAcur vgaark2000pvcur = {
+ "ark2000pvhwgc",
+
+ ark2000pvenable,
+ ark2000pvdisable,
+ ark2000pvload,
+ ark2000pvmove,
+};
diff --git a/sys/src/9/pc/vgabt485.c b/sys/src/9/pc/vgabt485.c
new file mode 100755
index 000000000..50dbfa392
--- /dev/null
+++ b/sys/src/9/pc/vgabt485.c
@@ -0,0 +1,246 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+/*
+ * Hardware graphics cursor support for
+ * Brooktree Bt485 Monolithic True-Color RAMDAC.
+ * Assumes hooked up to an S3 86C928.
+ *
+ * BUGS:
+ * 64x64x2 cursor always used;
+ * no support for interlaced mode.
+ */
+enum {
+ AddrW = 0x00, /* Address register; palette/cursor RAM write */
+ Palette = 0x01, /* 6/8-bit color palette data */
+ Pmask = 0x02, /* Pixel mask register */
+ AddrR = 0x03, /* Address register; palette/cursor RAM read */
+ ColorW = 0x04, /* Address register; cursor/overscan color write */
+ Color = 0x05, /* Cursor/overscan color data */
+ Cmd0 = 0x06, /* Command register 0 */
+ ColorR = 0x07, /* Address register; cursor/overscan color read */
+ Cmd1 = 0x08, /* Command register 1 */
+ Cmd2 = 0x09, /* Command register 2 */
+ Status = 0x0A, /* Status */
+ Cmd3 = 0x1A, /* Command register 3 */
+ Cram = 0x0B, /* Cursor RAM array data */
+ Cxlr = 0x0C, /* Cursor x-low register */
+ Cxhr = 0x0D, /* Cursor x-high register */
+ Cylr = 0x0E, /* Cursor y-low register */
+ Cyhr = 0x0F, /* Cursor y-high register */
+
+ Nreg = 0x10,
+};
+
+/*
+ * Lower 2-bits of indirect DAC register
+ * addressing.
+ */
+static ushort dacxreg[4] = {
+ PaddrW, Pdata, Pixmask, PaddrR
+};
+
+static uchar
+bt485io(uchar reg)
+{
+ uchar crt55, cr0;
+
+ crt55 = vgaxi(Crtx, 0x55) & 0xFC;
+ if((reg & 0x0F) == Status){
+ /*
+ * 1,2: Set indirect addressing for Status or
+ * Cmd3 - set bit7 of Cr0.
+ */
+ vgaxo(Crtx, 0x55, crt55|((Cmd0>>2) & 0x03));
+ cr0 = vgai(dacxreg[Cmd0 & 0x03])|0x80;
+ vgao(dacxreg[Cmd0 & 0x03], cr0);
+
+ /*
+ * 3,4: Set the index into the Write register,
+ * index == 0x00 for Status, 0x01 for Cmd3.
+ */
+ vgaxo(Crtx, 0x55, crt55|((AddrW>>2) & 0x03));
+ vgao(dacxreg[AddrW & 0x03], (reg == Status) ? 0x00: 0x01);
+
+ /*
+ * 5,6: Get the contents of the appropriate
+ * register at 0x0A.
+ */
+ }
+
+ return crt55;
+}
+
+static uchar
+bt485i(uchar reg)
+{
+ uchar crt55, r;
+
+ crt55 = bt485io(reg);
+ vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
+ r = vgai(dacxreg[reg & 0x03]);
+ vgaxo(Crtx, 0x55, crt55);
+
+ return r;
+}
+
+static void
+bt485o(uchar reg, uchar data)
+{
+ uchar crt55;
+
+ crt55 = bt485io(reg);
+ vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
+ vgao(dacxreg[reg & 0x03], data);
+ vgaxo(Crtx, 0x55, crt55);
+}
+
+static void
+bt485disable(VGAscr*)
+{
+ uchar r;
+
+ /*
+ * Disable
+ * cursor mode 3;
+ * cursor control enable for Bt485 DAC;
+ * the hardware cursor external operation mode.
+ */
+ r = bt485i(Cmd2) & ~0x03;
+ bt485o(Cmd2, r);
+
+ r = vgaxi(Crtx, 0x45) & ~0x20;
+ vgaxo(Crtx, 0x45, r);
+
+ r = vgaxi(Crtx, 0x55) & ~0x20;
+ vgaxo(Crtx, 0x55, r);
+}
+
+static void
+bt485enable(VGAscr*)
+{
+ uchar r;
+
+ /*
+ * Turn cursor off.
+ */
+ r = bt485i(Cmd2) & 0xFC;
+ bt485o(Cmd2, r);
+
+ /*
+ * Overscan colour,
+ * cursor colour 1 (white),
+ * cursor colour 2, 3 (black).
+ */
+ bt485o(ColorW, 0x00);
+ bt485o(Color, Pwhite); bt485o(Color, Pwhite); bt485o(Color, Pwhite);
+
+ bt485o(Color, Pwhite); bt485o(Color, Pwhite); bt485o(Color, Pwhite);
+
+ bt485o(Color, Pblack); bt485o(Color, Pblack); bt485o(Color, Pblack);
+ bt485o(Color, Pblack); bt485o(Color, Pblack); bt485o(Color, Pblack);
+
+ /*
+ * Finally, enable
+ * the hardware cursor external operation mode;
+ * cursor control enable for Bt485 DAC.
+ * The #9GXE cards seem to need the 86C928 Bt485 support
+ * enabled in order to work at all in enhanced mode.
+ */
+
+ r = vgaxi(Crtx, 0x55)|0x20;
+ vgaxo(Crtx, 0x55, r);
+
+ r = vgaxi(Crtx, 0x45)|0x20;
+ vgaxo(Crtx, 0x45, r);
+}
+
+static void
+bt485load(VGAscr* scr, Cursor* curs)
+{
+ uchar r;
+ int x, y;
+
+ /*
+ * Turn cursor off;
+ * put cursor into 64x64x2 mode and clear MSBs of address;
+ * clear LSBs of address;
+ */
+ r = bt485i(Cmd2) & 0xFC;
+ bt485o(Cmd2, r);
+
+ r = (bt485i(Cmd3) & 0xFC)|0x04;
+ bt485o(Cmd3, r);
+
+ bt485o(AddrW, 0x00);
+
+ /*
+ * Now load the cursor RAM array, both planes.
+ * The cursor is 16x16, the array 64x64; put
+ * the cursor in the top left. The 0,0 cursor
+ * point is bottom-right, so positioning will
+ * have to take that into account.
+ */
+ for(y = 0; y < 64; y++){
+ for(x = 0; x < 64/8; x++){
+ if(x < 16/8 && y < 16)
+ bt485o(Cram, curs->clr[x+y*2]);
+ else
+ bt485o(Cram, 0x00);
+ }
+ }
+ for(y = 0; y < 64; y++){
+ for(x = 0; x < 64/8; x++){
+ if(x < 16/8 && y < 16)
+ bt485o(Cram, curs->set[x+y*2]);
+ else
+ bt485o(Cram, 0x00);
+ }
+ }
+
+ /*
+ * Initialise the cursor hot-point
+ * and enable the cursor.
+ */
+ scr->offset.x = 64+curs->offset.x;
+ scr->offset.y = 64+curs->offset.y;
+
+ r = (bt485i(Cmd2) & 0xFC)|0x01;
+ bt485o(Cmd2, r);
+}
+
+static int
+bt485move(VGAscr* scr, Point p)
+{
+ int x, y;
+
+ x = p.x+scr->offset.x;
+ y = p.y+scr->offset.y;
+
+ bt485o(Cxlr, x & 0xFF);
+ bt485o(Cxhr, (x>>8) & 0x0F);
+ bt485o(Cylr, y & 0xFF);
+ bt485o(Cyhr, (y>>8) & 0x0F);
+
+ return 0;
+}
+
+VGAcur vgabt485cur = {
+ "bt485hwgc",
+
+ bt485enable,
+ bt485disable,
+ bt485load,
+ bt485move,
+};
diff --git a/sys/src/9/pc/vgaclgd542x.c b/sys/src/9/pc/vgaclgd542x.c
new file mode 100755
index 000000000..2a980c3da
--- /dev/null
+++ b/sys/src/9/pc/vgaclgd542x.c
@@ -0,0 +1,277 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+static int
+clgd542xpageset(VGAscr*, int page)
+{
+ uchar gr09;
+ int opage;
+
+ if(vgaxi(Seqx, 0x07) & 0xF0)
+ page = 0;
+ gr09 = vgaxi(Grx, 0x09);
+ if(vgaxi(Grx, 0x0B) & 0x20){
+ vgaxo(Grx, 0x09, page<<2);
+ opage = gr09>>2;
+ }
+ else{
+ vgaxo(Grx, 0x09, page<<4);
+ opage = gr09>>4;
+ }
+
+ return opage;
+}
+
+static void
+clgd542xpage(VGAscr* scr, int page)
+{
+ lock(&scr->devlock);
+ clgd542xpageset(scr, page);
+ unlock(&scr->devlock);
+}
+
+static void
+clgd542xlinear(VGAscr* scr, int, int)
+{
+ vgalinearpciid(scr, 0x1013, 0);
+}
+
+static void
+clgd542xdisable(VGAscr*)
+{
+ uchar sr12;
+
+ sr12 = vgaxi(Seqx, 0x12);
+ vgaxo(Seqx, 0x12, sr12 & ~0x01);
+}
+
+static void
+clgd542xenable(VGAscr* scr)
+{
+ uchar sr12;
+ int mem, x;
+
+ /*
+ * Disable the cursor.
+ */
+ sr12 = vgaxi(Seqx, 0x12);
+ vgaxo(Seqx, 0x12, sr12 & ~0x01);
+
+ /*
+ * Cursor colours.
+ * Can't call setcolor here as cursor is already locked.
+ */
+ vgaxo(Seqx, 0x12, sr12|0x02);
+ vgao(PaddrW, 0x00);
+ vgao(Pdata, Pwhite);
+ vgao(Pdata, Pwhite);
+ vgao(Pdata, Pwhite);
+ vgao(PaddrW, 0x0F);
+ vgao(Pdata, Pblack);
+ vgao(Pdata, Pblack);
+ vgao(Pdata, Pblack);
+ vgaxo(Seqx, 0x12, sr12);
+
+ mem = 0;
+ switch(vgaxi(Crtx, 0x27) & ~0x03){
+
+ case 0x88: /* CL-GD5420 */
+ case 0x8C: /* CL-GD5422 */
+ case 0x94: /* CL-GD5424 */
+ case 0x80: /* CL-GD5425 */
+ case 0x90: /* CL-GD5426 */
+ case 0x98: /* CL-GD5427 */
+ case 0x9C: /* CL-GD5429 */
+ /*
+ * The BIOS leaves the memory size in Seq0A, bits 4 and 3.
+ * See Technical Reference Manual Appendix E1, Section 1.3.2.
+ *
+ * The storage area for the 64x64 cursors is the last 16Kb of
+ * display memory.
+ */
+ mem = (vgaxi(Seqx, 0x0A)>>3) & 0x03;
+ break;
+
+ case 0xA0: /* CL-GD5430 */
+ case 0xA8: /* CL-GD5434 */
+ case 0xAC: /* CL-GD5436 */
+ case 0xB8: /* CL-GD5446 */
+ case 0x30: /* CL-GD7543 */
+ /*
+ * Attempt to intuit the memory size from the DRAM control
+ * register. Minimum is 512KB.
+ * If DRAM bank switching is on then there's double.
+ */
+ x = vgaxi(Seqx, 0x0F);
+ mem = (x>>3) & 0x03;
+ if(x & 0x80)
+ mem++;
+ break;
+
+ case 0xBC: /* CL-GD5480 */
+ mem = 2; /* 1024 = 256<<2 */
+ x = vgaxi(Seqx, 0x0F);
+ if((x & 0x18) == 0x18){
+ mem <<= 1; /* 2048 = 256<<3 */
+ if(x & 0x80)
+ mem <<= 2; /* 2048 = 256<<4 */
+ }
+ if(vgaxi(Seqx, 0x17) & 0x80)
+ mem <<= 1;
+ break;
+
+ default: /* uh, ah dunno */
+ break;
+ }
+ scr->storage = ((256<<mem)-16)*1024;
+
+ /*
+ * Set the current cursor to index 0
+ * and turn the 64x64 cursor on.
+ */
+ vgaxo(Seqx, 0x13, 0);
+ vgaxo(Seqx, 0x12, sr12|0x05);
+}
+
+static void
+clgd542xinitcursor(VGAscr* scr, int xo, int yo, int index)
+{
+ uchar *p, seq07;
+ uint p0, p1;
+ int opage, x, y;
+
+ /*
+ * Is linear addressing turned on? This will determine
+ * how we access the cursor storage.
+ */
+ seq07 = vgaxi(Seqx, 0x07);
+ opage = 0;
+ p = scr->vaddr;
+ if(!(seq07 & 0xF0)){
+ lock(&scr->devlock);
+ opage = clgd542xpageset(scr, scr->storage>>16);
+ p += (scr->storage & 0xFFFF);
+ }
+ else
+ p += scr->storage;
+ p += index*1024;
+
+ for(y = yo; y < 16; y++){
+ p0 = scr->set[2*y];
+ p1 = scr->set[2*y+1];
+ if(xo){
+ p0 = (p0<<xo)|(p1>>(8-xo));
+ p1 <<= xo;
+ }
+ *p++ = p0;
+ *p++ = p1;
+
+ for(x = 16; x < 64; x += 8)
+ *p++ = 0x00;
+
+ p0 = scr->clr[2*y]|scr->set[2*y];
+ p1 = scr->clr[2*y+1]|scr->set[2*y+1];
+ if(xo){
+ p0 = (p0<<xo)|(p1>>(8-xo));
+ p1 <<= xo;
+ }
+ *p++ = p0;
+ *p++ = p1;
+
+ for(x = 16; x < 64; x += 8)
+ *p++ = 0x00;
+ }
+ while(y < 64+yo){
+ for(x = 0; x < 64; x += 8){
+ *p++ = 0x00;
+ *p++ = 0x00;
+ }
+ y++;
+ }
+
+ if(!(seq07 & 0xF0)){
+ clgd542xpageset(scr, opage);
+ unlock(&scr->devlock);
+ }
+}
+
+static void
+clgd542xload(VGAscr* scr, Cursor* curs)
+{
+ uchar sr12;
+
+ /*
+ * Disable the cursor.
+ */
+ sr12 = vgaxi(Seqx, 0x12);
+ vgaxo(Seqx, 0x12, sr12 & ~0x01);
+
+ memmove(&scr->Cursor, curs, sizeof(Cursor));
+ clgd542xinitcursor(scr, 0, 0, 0);
+
+ /*
+ * Enable the cursor.
+ */
+ vgaxo(Seqx, 0x13, 0);
+ vgaxo(Seqx, 0x12, sr12|0x05);
+}
+
+static int
+clgd542xmove(VGAscr* scr, Point p)
+{
+ int index, x, xo, y, yo;
+
+ index = 0;
+ if((x = p.x+scr->offset.x) < 0){
+ xo = -x;
+ x = 0;
+ }
+ else
+ xo = 0;
+ if((y = p.y+scr->offset.y) < 0){
+ yo = -y;
+ y = 0;
+ }
+ else
+ yo = 0;
+
+ if(xo || yo){
+ clgd542xinitcursor(scr, xo, yo, 1);
+ index = 1;
+ }
+ vgaxo(Seqx, 0x13, index<<2);
+
+ vgaxo(Seqx, 0x10|((x & 0x07)<<5), (x>>3) & 0xFF);
+ vgaxo(Seqx, 0x11|((y & 0x07)<<5), (y>>3) & 0xFF);
+
+ return 0;
+}
+
+VGAdev vgaclgd542xdev = {
+ "clgd542x",
+
+ 0,
+ 0,
+ clgd542xpage,
+ clgd542xlinear,
+};
+
+VGAcur vgaclgd542xcur = {
+ "clgd542xhwgc",
+
+ clgd542xenable,
+ clgd542xdisable,
+ clgd542xload,
+ clgd542xmove,
+};
diff --git a/sys/src/9/pc/vgaclgd546x.c b/sys/src/9/pc/vgaclgd546x.c
new file mode 100755
index 000000000..7e66a0960
--- /dev/null
+++ b/sys/src/9/pc/vgaclgd546x.c
@@ -0,0 +1,219 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+typedef struct Cursor546x Cursor546x;
+struct Cursor546x {
+ ushort x;
+ ushort y;
+ ushort preset;
+ ushort enable;
+ ushort addr;
+};
+
+enum {
+ PaletteState = 0xB0,
+ CursorMMIO = 0xE0,
+};
+
+static void
+clgd546xlinear(VGAscr* scr, int, int)
+{
+ vgalinearpci(scr);
+}
+
+static void
+clgd546xenable(VGAscr* scr)
+{
+ Pcidev *p;
+
+ if(scr->mmio)
+ return;
+ if((p = pcimatch(nil, 0x1013, 0)) == nil)
+ return;
+ switch(p->did){
+ case 0xD0:
+ case 0xD4:
+ case 0xD6:
+ break;
+ default:
+ return;
+ }
+
+ 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
+clgd546xcurdisable(VGAscr* scr)
+{
+ Cursor546x *cursor546x;
+
+ if(scr->mmio == 0)
+ return;
+ cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
+ cursor546x->enable = 0;
+}
+
+static void
+clgd546xcurload(VGAscr* scr, Cursor* curs)
+{
+ int c, i, m, y;
+ uchar *p;
+ Cursor546x *cursor546x;
+
+ if(scr->mmio == 0)
+ return;
+ cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
+
+ /*
+ * Disable the cursor then change only the bits
+ * that need it.
+ */
+ cursor546x->enable = 0;
+ p = (uchar*)scr->vaddr + scr->storage;
+ for(y = 0; y < 16; y++){
+ c = curs->set[2*y];
+ m = 0;
+ for(i = 0; i < 8; i++){
+ if(c & (1<<(7-i)))
+ m |= 1<<i;
+ }
+ *p++ = m;
+ c = curs->set[2*y + 1];
+ m = 0;
+ for(i = 0; i < 8; i++){
+ if(c & (1<<(7-i)))
+ m |= 1<<i;
+ }
+ *p++ = m;
+ p += 6;
+ c = curs->set[2*y]|curs->clr[2*y];
+ m = 0;
+ for(i = 0; i < 8; i++){
+ if(c & (1<<(7-i)))
+ m |= 1<<i;
+ }
+ *p++ = m;
+ c = curs->set[2*y + 1]|curs->clr[2*y + 1];
+ m = 0;
+ for(i = 0; i < 8; i++){
+ if(c & (1<<(7-i)))
+ m |= 1<<i;
+ }
+ *p++ = m;
+ p += 6;
+ }
+
+ /*
+ * Save the cursor hotpoint and enable the cursor.
+ */
+ scr->offset = curs->offset;
+ cursor546x->enable = 1;
+}
+
+static int
+clgd546xcurmove(VGAscr* scr, Point p)
+{
+ int x, xo, y, yo;
+ Cursor546x *cursor546x;
+
+ if(scr->mmio == 0)
+ return 1;
+ cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
+
+ if((x = p.x+scr->offset.x) < 0){
+ xo = -x;
+ x = 0;
+ }
+ else
+ xo = 0;
+ if((y = p.y+scr->offset.y) < 0){
+ yo = -y;
+ y = 0;
+ }
+ else
+ yo = 0;
+
+ cursor546x->preset = (xo<<8)|yo;
+ cursor546x->x = x;
+ cursor546x->y = y;
+
+ return 0;
+}
+
+static void
+clgd546xcurenable(VGAscr* scr)
+{
+ uchar *p;
+ Cursor546x *cursor546x;
+
+ clgd546xenable(scr);
+ if(scr->mmio == 0)
+ return;
+ cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
+
+ /*
+ * Cursor colours.
+ * Can't call setcolor here as cursor is already locked.
+ */
+ p = (uchar*)scr->mmio+PaletteState;
+ *p |= 0x08;
+ vgao(PaddrW, 0x00);
+ vgao(Pdata, Pwhite);
+ vgao(Pdata, Pwhite);
+ vgao(Pdata, Pwhite);
+ vgao(PaddrW, 0x0F);
+ vgao(Pdata, Pblack);
+ vgao(Pdata, Pblack);
+ vgao(Pdata, Pblack);
+ *p &= ~0x08;
+
+ /*
+ * Find a place for the cursor data in display memory.
+ * 2 cursor images might be needed, 1KB each so use the last
+ * 2KB of the framebuffer and initialise them to be
+ * transparent.
+ */
+ scr->storage = ((vgaxi(Seqx, 0x14) & 0x07)+1)*1024*1022;
+ cursor546x->addr = (scr->storage>>10)<<2;
+ memset((uchar*)scr->vaddr + scr->storage, 0, 2*64*16);
+
+ /*
+ * Load, locate and enable the 64x64 cursor.
+ */
+ clgd546xcurload(scr, &arrow);
+ clgd546xcurmove(scr, ZP);
+ cursor546x->enable = 1;
+}
+
+VGAdev vgaclgd546xdev = {
+ "clgd546x",
+
+ clgd546xenable,
+ nil,
+ nil,
+ clgd546xlinear,
+};
+
+VGAcur vgaclgd546xcur = {
+ "clgd546xhwgc",
+
+ clgd546xcurenable,
+ clgd546xcurdisable,
+ clgd546xcurload,
+ clgd546xcurmove,
+};
diff --git a/sys/src/9/pc/vgact65545.c b/sys/src/9/pc/vgact65545.c
new file mode 100755
index 000000000..03818ea29
--- /dev/null
+++ b/sys/src/9/pc/vgact65545.c
@@ -0,0 +1,150 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+static void
+ct65545page(VGAscr*, int page)
+{
+ outb(0x3D6, 0x10);
+ outb(0x3D7, page<<6);
+}
+
+static void
+ct65545disable(VGAscr*)
+{
+ outl(0xA3D0, 0);
+}
+
+static void
+ct65545enable(VGAscr* scr)
+{
+ ulong storage;
+
+ /*
+ * Find a place for the cursor data in display memory.
+ * Must be on a 1024-byte boundary.
+ */
+ storage = ROUND(scr->gscreen->width*BY2WD*scr->gscreen->r.max.y, 1024);
+ outl(0xB3D0, storage);
+ scr->storage = storage;
+
+ /*
+ * Set the colours.
+ * Enable the cursor.
+ */
+ outl(0xA7D0, 0xFFFF0000);
+ outl(0xA3D0, 2);
+}
+
+static void
+ct65545initcursor(VGAscr* scr, int xo, int yo, int index)
+{
+ uchar *mem;
+ uint and, clr, set, xor;
+ int i, x, y;
+
+ mem = scr->vaddr;
+ mem += scr->storage + index*1024;
+
+ for(y = yo; y < 16; y++){
+ clr = (scr->clr[2*y]<<8)|scr->clr[2*y+1];
+ set = (scr->set[2*y]<<8)|scr->set[2*y+1];
+ if(xo){
+ clr <<= xo;
+ set <<= xo;
+ }
+
+ and = 0;
+ xor = 0;
+ for(i = 0; i < 16; i++){
+ if(set & (1<<i)){
+ /* nothing to do */
+ }
+ else if(clr & (1<<i))
+ xor |= 1<<i;
+ else
+ and |= 1<<i;
+ }
+ *mem++ = and>>8;
+ *mem++ = xor>>8;
+ *mem++ = and;
+ *mem++ = xor;
+
+ for(x = 16; x < 64; x += 8){
+ *mem++ = 0xFF;
+ *mem++ = 0x00;
+ }
+ }
+ while(y < 64+yo){
+ for(x = 0; x < 64; x += 8){
+ *mem++ = 0xFF;
+ *mem++ = 0x00;
+ }
+ y++;
+ }
+}
+
+static void
+ct65545load(VGAscr* scr, Cursor* curs)
+{
+ memmove(&scr->Cursor, curs, sizeof(Cursor));
+ ct65545initcursor(scr, 0, 0, 0);
+}
+
+static int
+ct65545move(VGAscr* scr, Point p)
+{
+ int index, x, xo, y, yo;
+
+ index = 0;
+ if((x = p.x+scr->offset.x) < 0){
+ xo = -x;
+ x = 0;
+ }
+ else
+ xo = 0;
+ if((y = p.y+scr->offset.y) < 0){
+ yo = -y;
+ y = 0;
+ }
+ else
+ yo = 0;
+
+ if(xo || yo){
+ ct65545initcursor(scr, xo, yo, 1);
+ index = 1;
+ }
+ outl(0xB3D0, scr->storage + index*1024);
+
+ outl(0xAFD0, (y<<16)|x);
+
+ return 0;
+}
+
+VGAdev vgact65545dev = {
+ "ct65540", /* BUG: really 65545 */
+
+ 0,
+ 0,
+ ct65545page,
+ 0,
+};
+
+VGAcur vgact65545cur = {
+ "ct65545hwgc",
+
+ ct65545enable,
+ ct65545disable,
+ ct65545load,
+ ct65545move,
+};
diff --git a/sys/src/9/pc/vgacyber938x.c b/sys/src/9/pc/vgacyber938x.c
new file mode 100755
index 000000000..a27cdc933
--- /dev/null
+++ b/sys/src/9/pc/vgacyber938x.c
@@ -0,0 +1,203 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+enum {
+ CursorON = 0xC8,
+ CursorOFF = 0x00,
+};
+
+static int
+cyber938xpageset(VGAscr*, int page)
+{
+ int opage;
+
+ opage = inb(0x3D8);
+
+ outb(0x3D8, page);
+ outb(0x3D9, page);
+
+ return opage;
+}
+
+static void
+cyber938xpage(VGAscr* scr, int page)
+{
+ lock(&scr->devlock);
+ cyber938xpageset(scr, page);
+ unlock(&scr->devlock);
+}
+
+static void
+cyber938xlinear(VGAscr* scr, int, int)
+{
+ Pcidev *p;
+
+ if(scr->vaddr)
+ return;
+
+ vgalinearpciid(scr, 0x1023, 0);
+ p = scr->pci;
+
+ /*
+ * 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(scr->apsize)
+ addvgaseg("cyber938xscreen", scr->paddr, scr->apsize);
+ if(scr->mmio)
+ addvgaseg("cyber938xmmio", p->mem[1].bar&~0x0F, 0x20000);
+}
+
+static void
+cyber938xcurdisable(VGAscr*)
+{
+ vgaxo(Crtx, 0x50, CursorOFF);
+}
+
+static void
+cyber938xcurload(VGAscr* scr, Cursor* curs)
+{
+ uchar *p;
+ int islinear, opage, y;
+
+ cyber938xcurdisable(scr);
+
+ opage = 0;
+ p = scr->vaddr;
+ islinear = vgaxi(Crtx, 0x21) & 0x20;
+ if(!islinear){
+ lock(&scr->devlock);
+ opage = cyber938xpageset(scr, scr->storage>>16);
+ p += (scr->storage & 0xFFFF);
+ }
+ else
+ p += scr->storage;
+
+ for(y = 0; y < 16; y++){
+ *p++ = curs->set[2*y]|curs->clr[2*y];
+ *p++ = curs->set[2*y + 1]|curs->clr[2*y + 1];
+ *p++ = 0x00;
+ *p++ = 0x00;
+ *p++ = curs->set[2*y];
+ *p++ = curs->set[2*y + 1];
+ *p++ = 0x00;
+ *p++ = 0x00;
+ }
+ memset(p, 0, (32-y)*8);
+
+ if(!islinear){
+ cyber938xpageset(scr, opage);
+ unlock(&scr->devlock);
+ }
+
+ /*
+ * Save the cursor hotpoint and enable the cursor.
+ */
+ scr->offset = curs->offset;
+ vgaxo(Crtx, 0x50, CursorON);
+}
+
+static int
+cyber938xcurmove(VGAscr* scr, Point p)
+{
+ int x, xo, y, yo;
+
+ /*
+ * Mustn't position the cursor offscreen even partially,
+ * or it might disappear. Therefore, if x or y is -ve, adjust the
+ * cursor origins instead.
+ */
+ if((x = p.x+scr->offset.x) < 0){
+ xo = -x;
+ x = 0;
+ }
+ else
+ xo = 0;
+ if((y = p.y+scr->offset.y) < 0){
+ yo = -y;
+ y = 0;
+ }
+ else
+ yo = 0;
+
+ /*
+ * Load the new values.
+ */
+ vgaxo(Crtx, 0x46, xo);
+ vgaxo(Crtx, 0x47, yo);
+ vgaxo(Crtx, 0x40, x & 0xFF);
+ vgaxo(Crtx, 0x41, (x>>8) & 0xFF);
+ vgaxo(Crtx, 0x42, y & 0xFF);
+ vgaxo(Crtx, 0x43, (y>>8) & 0xFF);
+
+ return 0;
+}
+
+static void
+cyber938xcurenable(VGAscr* scr)
+{
+ int i;
+ ulong storage;
+
+ cyber938xcurdisable(scr);
+
+ /*
+ * Cursor colours.
+ */
+ for(i = 0x48; i < 0x4C; i++)
+ vgaxo(Crtx, i, 0x00);
+ for(i = 0x4C; i < 0x50; i++)
+ vgaxo(Crtx, i, 0xFF);
+
+ /*
+ * Find a place for the cursor data in display memory.
+ */
+ storage = ((scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024);
+ vgaxo(Crtx, 0x44, storage & 0xFF);
+ vgaxo(Crtx, 0x45, (storage>>8) & 0xFF);
+ storage *= 1024;
+ scr->storage = storage;
+
+ /*
+ * Load, locate and enable the 32x32 cursor.
+ * (64x64 is bit 0, X11 format is bit 6 and cursor
+ * enable is bit 7). Bit 3 needs to be set on 9382
+ * chips otherwise even the white bits are black.
+ */
+ cyber938xcurload(scr, &arrow);
+ cyber938xcurmove(scr, ZP);
+ vgaxo(Crtx, 0x50, CursorON);
+}
+
+VGAdev vgacyber938xdev = {
+ "cyber938x",
+
+ nil, /* enable */
+ nil, /* disable */
+ cyber938xpage, /* page */
+ cyber938xlinear, /* linear */
+ nil, /* drawinit */
+};
+
+VGAcur vgacyber938xcur = {
+ "cyber938xhwgc",
+
+ cyber938xcurenable, /* enable */
+ cyber938xcurdisable, /* disable */
+ cyber938xcurload, /* load */
+ cyber938xcurmove, /* move */
+};
diff --git a/sys/src/9/pc/vgaet4000.c b/sys/src/9/pc/vgaet4000.c
new file mode 100755
index 000000000..b7ec5dede
--- /dev/null
+++ b/sys/src/9/pc/vgaet4000.c
@@ -0,0 +1,271 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+static void
+setet4000page(int page)
+{
+ uchar p;
+
+ p = page & 0x0F;
+ p |= p<<4;
+ outb(0x3CD, p);
+
+ p = (page & 0x30);
+ p |= p>>4;
+ outb(0x3CB, p);
+}
+
+static void
+et4000page(VGAscr *scr, int page)
+{
+ lock(&scr->devlock);
+ setet4000page(page);
+ unlock(&scr->devlock);
+}
+
+static void
+et4000disable(VGAscr*)
+{
+ uchar imaF7;
+
+ outb(0x217A, 0xF7);
+ imaF7 = inb(0x217B) & ~0x80;
+ outb(0x217B, imaF7);
+}
+
+static void
+et4000enable(VGAscr *scr)
+{
+ uchar imaF7;
+
+ et4000disable(scr);
+
+ /*
+ * Configure CRTCB for Sprite, 64x64,
+ * CRTC pixel overlay.
+ */
+ outb(0x217A, 0xEF);
+ outb(0x217B, 0x02);
+
+ /*
+ * Cursor goes in the top left corner
+ * of the Sprite area, so the horizontal and
+ * vertical presets are 0.
+ */
+ outb(0x217A, 0xE2);
+ outb(0x217B, 0x00);
+ outb(0x217A, 0xE3);
+ outb(0x217B, 0x00);
+
+ outb(0x217A, 0xE6);
+ outb(0x217B, 0x00);
+ outb(0x217A, 0xE7);
+ outb(0x217B, 0x00);
+
+ /*
+ * Find a place for the cursor data in display memory.
+ * Must be on a "doubleword" boundary, but put it on a
+ * 1024-byte boundary so that there's no danger of it
+ * crossing a page.
+ */
+ scr->storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024;
+ scr->storage *= 1024/4;
+ outb(0x217A, 0xE8);
+ outb(0x217B, scr->storage & 0xFF);
+ outb(0x217A, 0xE9);
+ outb(0x217B, (scr->storage>>8) & 0xFF);
+ outb(0x217A, 0xEA);
+ outb(0x217B, (scr->storage>>16) & 0x0F);
+ scr->storage *= 4;
+
+ /*
+ * Row offset in "quadwords". Must be 2 for Sprite.
+ * Bag the pixel-panning.
+ * Colour depth, must be 2 for Sprite.
+ */
+ outb(0x217A, 0xEB);
+ outb(0x217B, 0x02);
+ outb(0x217A, 0xEC);
+ outb(0x217B, 0x00);
+
+ outb(0x217A, 0xED);
+ outb(0x217B, 0x00);
+
+ outb(0x217A, 0xEE);
+// if(vgascreen.ldepth == 3)
+ outb(0x217B, 0x01);
+// else
+// outb(0x217B, 0x00);
+
+ /*
+ * Enable the CRTCB/Sprite.
+ */
+ outb(0x217A, 0xF7);
+ imaF7 = inb(0x217B);
+ outb(0x217B, 0x80|imaF7);
+}
+
+static void
+et4000load(VGAscr *scr, Cursor *c)
+{
+ uchar p0, p1, *mem;
+ int i, x, y;
+ ushort p;
+ uchar clr[2*16], set[2*16];
+
+ /*
+ * Lock the display memory so we can update the
+ * cursor bitmap if necessary.
+ */
+ lock(&scr->devlock);
+
+ /*
+ * Disable the cursor.
+ * Set the display page (do we need to restore
+ * the current contents when done?) and the
+ * pointer to the two planes. What if this crosses
+ * into a new page?
+ */
+ et4000disable(scr);
+
+ setet4000page(scr->storage>>16);
+ mem = (uchar*)scr->vaddr + (scr->storage & 0xFFFF);
+
+ /*
+ * Initialise the 64x64 cursor RAM array. There are 2 planes,
+ * p0 and p1. Data is written 4 pixels per byte, with p1 the
+ * MS bit of each pixel.
+ * The cursor mode gives the following truth table:
+ * p1 p0 colour
+ * 0 0 Sprite Colour 0 (defined as 0x00)
+ * 0 1 Sprite Colour 1 (defined as 0xFF)
+ * 1 0 Transparent (allow CRTC pixel pass through)
+ * 1 1 Invert (allow CRTC pixel invert through)
+ * Put the cursor into the top-left of the 64x64 array.
+ *
+ * This is almost certainly wrong, since it has not
+ * been updated for the 3rd edition color values.
+ */
+ memmove(clr, c->clr, sizeof(clr));
+// pixreverse(clr, sizeof(clr), 0);
+ memmove(set, c->set, sizeof(set));
+// pixreverse(set, sizeof(set), 0);
+ for(y = 0; y < 64; y++){
+ for(x = 0; x < 64/8; x++){
+ if(x < 16/8 && y < 16){
+ p0 = clr[x+y*2];
+ p1 = set[x+y*2];
+
+ p = 0x0000;
+ for(i = 0; i < 8; i++){
+ if(p1 & (1<<(7-i))){
+ /* nothing to do */
+ }
+ else if(p0 & (1<<(7-i)))
+ p |= 0x01<<(2*i);
+ else
+ p |= 0x02<<(2*i);
+ }
+ *mem++ = p & 0xFF;
+ *mem++ = (p>>8) & 0xFF;
+ }
+ else {
+ *mem++ = 0xAA;
+ *mem++ = 0xAA;
+ }
+ }
+ }
+
+ /*
+ * enable the cursor.
+ */
+ outb(0x217A, 0xF7);
+ p = inb(0x217B)|0x80;
+ outb(0x217B, p);
+
+ unlock(&scr->devlock);
+}
+
+static int
+et4000move(VGAscr *scr, Point p)
+{
+ int x, xo, y, yo;
+
+ if(canlock(&scr->devlock) == 0)
+ return 1;
+
+ /*
+ * Mustn't position the cursor offscreen even partially,
+ * or it disappears. Therefore, if x or y is -ve, adjust the
+ * cursor presets instead.
+ */
+ if((x = p.x+scr->offset.x) < 0){
+ xo = -x;
+ x = 0;
+ }
+ else
+ xo = 0;
+ if((y = p.y+scr->offset.y) < 0){
+ yo = -y;
+ y = 0;
+ }
+ else
+ yo = 0;
+
+ /*
+ * The cursor image is jerky if we don't do this.
+ * The cursor information is probably fetched from
+ * display memory during the horizontal blank active
+ * time and it doesn't like it if the coordinates
+ * are changed underneath.
+ */
+ while((vgai(Status1) & 0x08) == 0)
+ ;
+
+ outb(0x217A, 0xE2);
+ outb(0x217B, xo);
+
+ outb(0x217A, 0xE6);
+ outb(0x217B, yo);
+
+ outb(0x217A, 0xE1);
+ outb(0x217B, (x>>8) & 0xFF);
+ outb(0x217A, 0xE0);
+ outb(0x217B, x & 0xFF);
+ outb(0x217A, 0xE5);
+ outb(0x217B, (y>>8) & 0xFF);
+ outb(0x217A, 0xE4);
+ outb(0x217B, y & 0xFF);
+
+ unlock(&scr->devlock);
+ return 0;
+}
+
+VGAcur vgaet4000cur = {
+ "et4000hwgc",
+
+ et4000enable,
+ et4000disable,
+ et4000load,
+ et4000move,
+};
+
+VGAdev vgaet4000dev = {
+ "et4000",
+
+ 0,
+ 0,
+ et4000page,
+ 0
+};
diff --git a/sys/src/9/pc/vgahiqvideo.c b/sys/src/9/pc/vgahiqvideo.c
new file mode 100755
index 000000000..6314e7832
--- /dev/null
+++ b/sys/src/9/pc/vgahiqvideo.c
@@ -0,0 +1,228 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+enum {
+ Xrx = 0x3D6, /* Configuration Extensions Index */
+};
+
+static uchar
+hiqvideoxi(long port, uchar index)
+{
+ uchar data;
+
+ outb(port, index);
+ data = inb(port+1);
+
+ return data;
+}
+
+static void
+hiqvideoxo(long port, uchar index, uchar data)
+{
+ outb(port, index);
+ outb(port+1, data);
+}
+
+static void
+hiqvideolinear(VGAscr*, int, int)
+{
+}
+
+static void
+hiqvideoenable(VGAscr* scr)
+{
+ Pcidev *p;
+ int vmsize;
+
+ /*
+ * Only once, can't be disabled for now.
+ */
+ if(scr->mmio)
+ return;
+ if(p = pcimatch(nil, 0x102C, 0)){
+ switch(p->did){
+ case 0x00C0: /* 69000 HiQVideo */
+ vmsize = 2*1024*1024;
+ break;
+ case 0x00E0: /* 65550 HiQV32 */
+ case 0x00E4: /* 65554 HiQV32 */
+ case 0x00E5: /* 65555 HiQV32 */
+ switch((hiqvideoxi(Xrx, 0x43)>>1) & 0x03){
+ default:
+ case 0:
+ vmsize = 1*1024*1024;
+ break;
+ case 1:
+ vmsize = 2*1024*1024;
+ break;
+ }
+ break;
+ default:
+ return;
+ }
+ }
+ else
+ return;
+
+ 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->mmio holds the virtual address of the cursor
+ * storage area in the framebuffer region.
+ */
+ scr->storage = vmsize-4096;
+ scr->mmio = (ulong*)((uchar*)scr->vaddr+scr->storage);
+}
+
+static void
+hiqvideocurdisable(VGAscr*)
+{
+ hiqvideoxo(Xrx, 0xA0, 0x10);
+}
+
+static void
+hiqvideocurload(VGAscr* scr, Cursor* curs)
+{
+ uchar *p;
+ int x, y;
+
+ /*
+ * Disable the cursor.
+ */
+ hiqvideocurdisable(scr);
+
+ if(scr->mmio == 0)
+ return;
+ p = (uchar*)scr->mmio;
+
+ 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]);
+ *p++ = 0xFF;
+ *p++ = 0xFF;
+ *p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]);
+ *p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]);
+ *p++ = 0xFF;
+ *p++ = 0xFF;
+ *p++ = curs->set[2*y];
+ *p++ = curs->set[2*y+1];
+ *p++ = 0x00;
+ *p++ = 0x00;
+ *p++ = curs->set[2*y+2];
+ *p++ = curs->set[2*y+3];
+ *p++ = 0x00;
+ *p++ = 0x00;
+ }
+ while(y < 32){
+ for(x = 0; x < 64; x += 8)
+ *p++ = 0xFF;
+ for(x = 0; x < 64; x += 8)
+ *p++ = 0x00;
+ y += 2;
+ }
+
+ /*
+ * Save the cursor hotpoint and enable the cursor.
+ */
+ scr->offset = curs->offset;
+ hiqvideoxo(Xrx, 0xA0, 0x11);
+}
+
+static int
+hiqvideocurmove(VGAscr* scr, Point p)
+{
+ int x, y;
+
+ if(scr->mmio == 0)
+ return 1;
+
+ if((x = p.x+scr->offset.x) < 0)
+ x = 0x8000|(-x & 0x07FF);
+ if((y = p.y+scr->offset.y) < 0)
+ y = 0x8000|(-y & 0x07FF);
+
+ hiqvideoxo(Xrx, 0xA4, x & 0xFF);
+ hiqvideoxo(Xrx, 0xA5, (x>>8) & 0xFF);
+ hiqvideoxo(Xrx, 0xA6, y & 0xFF);
+ hiqvideoxo(Xrx, 0xA7, (y>>8) & 0xFF);
+
+ return 0;
+}
+
+static void
+hiqvideocurenable(VGAscr* scr)
+{
+ uchar xr80;
+
+ hiqvideoenable(scr);
+ if(scr->mmio == 0)
+ return;
+
+ /*
+ * Disable the cursor.
+ */
+ hiqvideocurdisable(scr);
+
+ /*
+ * Cursor colours.
+ * Can't call setcolor here as cursor is already locked.
+ * When done make sure the cursor enable in Xr80 is set.
+ */
+ xr80 = hiqvideoxi(Xrx, 0x80);
+ hiqvideoxo(Xrx, 0x80, xr80|0x01);
+ vgao(PaddrW, 0x04);
+ vgao(Pdata, Pwhite);
+ vgao(Pdata, Pwhite);
+ vgao(Pdata, Pwhite);
+ vgao(Pdata, Pblack);
+ vgao(Pdata, Pblack);
+ vgao(Pdata, Pblack);
+ hiqvideoxo(Xrx, 0x80, xr80|0x10);
+
+ hiqvideoxo(Xrx, 0xA2, (scr->storage>>12)<<4);
+ hiqvideoxo(Xrx, 0xA3, (scr->storage>>16) & 0x3F);
+
+ /*
+ * Load, locate and enable the 32x32 cursor.
+ * Cursor enable in Xr80 better be set already.
+ */
+ hiqvideocurload(scr, &arrow);
+ hiqvideocurmove(scr, ZP);
+ hiqvideoxo(Xrx, 0xA0, 0x11);
+}
+
+VGAdev vgahiqvideodev = {
+ "hiqvideo",
+
+ hiqvideoenable, /* enable */
+ nil, /* disable */
+ nil, /* page */
+ hiqvideolinear, /* linear */
+};
+
+VGAcur vgahiqvideocur = {
+ "hiqvideohwgc",
+
+ hiqvideocurenable, /* enable */
+ hiqvideocurdisable, /* disable */
+ hiqvideocurload, /* load */
+ hiqvideocurmove, /* move */
+};
diff --git a/sys/src/9/pc/vgai81x.c b/sys/src/9/pc/vgai81x.c
new file mode 100755
index 000000000..1e801c421
--- /dev/null
+++ b/sys/src/9/pc/vgai81x.c
@@ -0,0 +1,259 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+typedef struct
+{
+ ushort ctl;
+ ushort pad;
+ ulong base;
+ ulong pos;
+} CursorI81x;
+
+enum {
+ Fbsize = 8*MB,
+
+ hwCur = 0x70080,
+ SRX = 0x3c4,
+ DPMSsync = 0x5002,
+};
+
+static void
+i81xblank(VGAscr *scr, int blank)
+{
+ char *srx, *srxd, *dpms;
+ char sr01, mode;
+
+ srx = (char *)scr->mmio+SRX;
+ srxd = srx+1;
+ dpms = (char *)scr->mmio+DPMSsync;
+
+ *srx = 0x01;
+ sr01 = *srxd & ~0x20;
+ mode = *dpms & 0xf0;
+
+ if(blank) {
+ sr01 |= 0x20;
+ mode |= 0x0a;
+ }
+ *srxd = sr01;
+ *dpms = mode;
+}
+
+static Pcidev *
+i81xpcimatch(void)
+{
+ Pcidev *p;
+
+ p = nil;
+ while((p = pcimatch(p, 0x8086, 0)) != nil){
+ switch(p->did){
+ default:
+ continue;
+ case 0x7121:
+ case 0x7123:
+ case 0x7125:
+ case 0x1102:
+ case 0x1112:
+ case 0x1132:
+ case 0x3577: /* IBM R31 uses intel 830M chipset */
+ return p;
+ }
+ }
+ return nil;
+}
+
+static void
+i81xenable(VGAscr* scr)
+{
+ Pcidev *p;
+ int size;
+ Mach *mach0;
+ ulong *pgtbl, *rp, cursor, *pte, fbuf, fbend;
+
+ if(scr->mmio)
+ return;
+ p = i81xpcimatch();
+ if(p == nil)
+ return;
+ 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 = xspanalloc(64*1024, BY2PG, 0);
+ scr->mmio[0x2020/4] = PADDR(pgtbl) | 1;
+
+ size = p->mem[0].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;
+ }
+
+ /*
+ * allocate space for the cursor data in system memory.
+ * must be uncached.
+ */
+ cursor = (ulong)xspanalloc(BY2PG, BY2PG, 0);
+ mach0 = MACHP(0);
+ pte = mmuwalk(mach0->pdb, cursor, 2, 0);
+ if(pte == nil)
+ panic("i81x cursor mmuwalk");
+ *pte |= PTEUNCACHED;
+ scr->storage = cursor;
+
+ scr->blank = i81xblank;
+ hwblank = 1;
+}
+
+static void
+i81xcurdisable(VGAscr* scr)
+{
+ CursorI81x *hwcurs;
+
+ if(scr->mmio == 0)
+ return;
+ hwcurs = (void*)((uchar*)scr->mmio+hwCur);
+ hwcurs->ctl = (1<<4);
+}
+
+static void
+i81xcurload(VGAscr* scr, Cursor* curs)
+{
+ int y;
+ uchar *p;
+ CursorI81x *hwcurs;
+
+ if(scr->mmio == 0)
+ return;
+ hwcurs = (void*)((uchar*)scr->mmio+hwCur);
+
+ /*
+ * Disable the cursor then load the new image in
+ * the top-left of the 32x32 array.
+ * Unused portions of the image have been initialised to be
+ * transparent.
+ */
+ hwcurs->ctl = (1<<4);
+ 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]);
+ p += 2;
+ *p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]);
+ *p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]);
+ p += 2;
+ *p++ = curs->set[2*y];
+ *p++ = curs->set[2*y+1];
+ p += 2;
+ *p++ = curs->set[2*y+2];
+ *p++ = curs->set[2*y+3];
+ p += 2;
+ }
+
+ /*
+ * Save the cursor hotpoint and enable the cursor.
+ * The 0,0 cursor point is top-left.
+ */
+ scr->offset.x = curs->offset.x;
+ scr->offset.y = curs->offset.y;
+ hwcurs->ctl = (1<<4)|1;
+}
+
+static int
+i81xcurmove(VGAscr* scr, Point p)
+{
+ int x, y;
+ ulong pos;
+ CursorI81x *hwcurs;
+
+ if(scr->mmio == 0)
+ return 1;
+ hwcurs = (void*)((uchar*)scr->mmio+hwCur);
+
+ x = p.x+scr->offset.x;
+ y = p.y+scr->offset.y;
+ pos = 0;
+ if(x < 0) {
+ pos |= (1<<15);
+ x = -x;
+ }
+ if(y < 0) {
+ pos |= (1<<31);
+ y = -y;
+ }
+ pos |= ((y&0x7ff)<<16)|(x&0x7ff);
+ hwcurs->pos = pos;
+
+ return 0;
+}
+
+static void
+i81xcurenable(VGAscr* scr)
+{
+ int i;
+ uchar *p;
+ CursorI81x *hwcurs;
+
+ i81xenable(scr);
+ if(scr->mmio == 0)
+ return;
+ hwcurs = (void*)((uchar*)scr->mmio+hwCur);
+
+ /*
+ * Initialise the 32x32 cursor to be transparent in 2bpp mode.
+ */
+ 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);
+ p += 16;
+ }
+ /*
+ * Load, locate and enable the 32x32 cursor in 2bpp mode.
+ */
+ i81xcurload(scr, &arrow);
+ i81xcurmove(scr, ZP);
+}
+
+VGAdev vgai81xdev = {
+ "i81x",
+
+ i81xenable,
+ nil,
+ nil,
+ nil,
+};
+
+VGAcur vgai81xcur = {
+ "i81xhwgc",
+
+ i81xcurenable,
+ i81xcurdisable,
+ i81xcurload,
+ i81xcurmove,
+};
diff --git a/sys/src/9/pc/vgamach64xx.c b/sys/src/9/pc/vgamach64xx.c
new file mode 100755
index 000000000..801b46219
--- /dev/null
+++ b/sys/src/9/pc/vgamach64xx.c
@@ -0,0 +1,1210 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+char Eunsupportedformat[] = "unsupported video format";
+char Enotconfigured[] = "device not configured";
+
+#define SCALE_ZERO_EXTEND 0x0
+#define SCALE_DYNAMIC 0x1
+#define SCALE_RED_TEMP_6500K 0x0
+#define SCALE_RED_TEMP_9800K 0x2
+#define SCALE_HORZ_BLEND 0x0
+#define SCALE_HORZ_REP 0x4
+#define SCALE_VERT_BLEND 0x0
+#define SCALE_VERT_REP 0x8
+#define SCALE_BANDWIDTH_NORMAL 0x0
+#define SCALE_BANDWIDTH_EXCEEDED 0x4000000
+#define SCALE_BANDWIDTH_RESET 0x4000000
+#define SCALE_CLK_ACTIVITY 0x0
+#define SCALE_CLK_CONTINUOUS 0x20000000
+#define OVERLAY_DISABLE 0x0
+#define OVERLAY_ENABLE 0x40000000
+#define SCALE_DISABLE 0x0
+#define SCALE_ENABLE 0x80000000
+
+#define SCALER_FRAME_READ_MODE_FULL 0x0
+#define SCALER_BUF_MODE_SINGLE 0x0
+#define SCALER_BUF_MODE_DOUBLE 0x40000
+#define SCALER_BUF_NEXT_0 0x0
+#define SCALER_BUF_NEXT_1 0x80000
+#define SCALER_BUF_STATUS_0 0x0
+#define SCALER_BUF_STATUS_1 0x100000
+
+#define OVERLAY_MIX_G_CMP 0x0
+#define OVERLAY_MIX_ALWAYS_G 0x100
+#define OVERLAY_MIX_ALWAYS_V 0x200
+#define OVERLAY_MIX_NOT_G 0x300
+#define OVERLAY_MIX_NOT_V 0x400
+#define OVERLAY_MIX_G_XOR_V 0x500
+#define OVERLAY_MIX_NOT_G_XOR_V 0x600
+#define OVERLAY_MIX_V_CMP 0x700
+#define OVERLAY_MIX_NOT_G_OR_NOT_V 0x800
+#define OVERLAY_MIX_G_OR_NOT_V 0x900
+#define OVERLAY_MIX_NOT_G_OR_V 0xA00
+#define OVERLAY_MIX_G_OR_V 0xB00
+#define OVERLAY_MIX_G_AND_V 0xC00
+#define OVERLAY_MIX_NOT_G_AND_V 0xD00
+#define OVERLAY_MIX_G_AND_NOT_V 0xE00
+#define OVERLAY_MIX_NOT_G_AND_NOT_V 0xF00
+#define OVERLAY_EXCLUSIVE_NORMAL 0x0
+#define OVERLAY_EXCLUSIVE_V_ONLY 0x80000000
+
+#define VIDEO_IN_8BPP 0x2
+#define VIDEO_IN_16BPP 0x4
+#define VIDEO_IN_32BPP 0x6
+#define VIDEO_IN_VYUY422 0xB /*16 bpp */
+#define VIDEO_IN_YVYU422 0xC /* 16 bpp */
+#define SCALE_IN_15BPP 0x30000 /* aRGB 1555 */
+#define SCALE_IN_16BPP 0x40000 /* RGB 565 */
+#define SCALE_IN_32BPP 0x60000 /* aRGB 8888 */
+#define SCALE_IN_YUV9 0x90000 /* planar */
+#define SCALE_IN_YUV12 0xA0000 /* planar */
+#define SCALE_IN_VYUY422 0xB0000 /* 16 bpp */
+#define SCALE_IN_YVYU422 0xC0000 /* 16 bpp */
+#define HOST_YUV_APERTURE_UPPER 0x0
+#define HOST_YUV_APERTURE_LOWER 0x20000000
+#define HOST_MEM_MODE_Y 0x40000000
+#define HOST_MEM_MODE_U 0x80000000
+#define HOST_MEM_MODE_V 0xC0000000
+#define HOST_MEM_MODE_NORMAL HOST_YUV_APERTURE_UPPER
+
+static Chan *ovl_chan; /* Channel of controlling process */
+static int ovl_width; /* Width of input overlay buffer */
+static int ovl_height; /* Height of input overlay buffer */
+static int ovl_format; /* Overlay format */
+static ulong ovl_fib; /* Frame in bytes */
+
+enum {
+ VTGTB1S1 = 0x01, /* Asic description for VTB1S1 and GTB1S1. */
+ VT4GTIIC = 0x3A, /* asic descr for VT4 and RAGE IIC */
+ GTB1U1 = 0x19, /* Asic description for GTB1U1. */
+ GTB1S2 = 0x41, /* Asic description for GTB1S2. */
+ GTB2U1 = 0x1A,
+ GTB2U2 = 0x5A,
+ GTB2U3 = 0x9A,
+ GTIIIC1U1 = 0x1B, /* 3D RAGE PRO asic descrp. */
+ GTIIIC1U2 = 0x5B, /* 3D RAGE PRO asic descrp. */
+ GTIIIC2U1 = 0x1C, /* 3D RAGE PRO asic descrp. */
+ GTIIIC2U2 = 0x5C, /* 3D RAGE PRO asic descrp. */
+ GTIIIC2U3 = 0x7C, /* 3D RAGE PRO asic descrp. */
+ GTBC = 0x3A, /* 3D RAGE IIC asic descrp. */
+ LTPRO = 0x9C, /* 3D RAGE LT PRO */
+};
+
+/*
+ * ATI Mach64(CT|ET|G*|V*|L*).
+ */
+typedef struct Mach64types Mach64types;
+struct Mach64types {
+ ushort m64_id; /* Chip ID */
+ int m64_vtgt; /* Is this a VT or GT chipset? */
+ ulong m64_ovlclock; /* Max. overlay clock frequency */
+ int m64_pro; /* Is this a PRO? */
+};
+
+static ulong mach64refclock;
+static Mach64types *mach64type;
+static int mach64revb; /* Revision B or greater? */
+static ulong mach64overlay; /* Overlay buffer */
+
+static Mach64types mach64s[] = {
+ ('C'<<8)|'T', 0, 1350000, /*?*/ 0, /* 4354: CT */
+ ('E'<<8)|'T', 0, 1350000, /*?*/ 0, /* 4554: ET */
+ ('G'<<8)|'B', 1, 1250000, 1, /* 4742: 264GT PRO */
+ ('G'<<8)|'D', 1, 1250000, 1, /* 4744: 264GT PRO */
+ ('G'<<8)|'I', 1, 1250000, 1, /* 4749: 264GT PRO */
+ ('G'<<8)|'M', 0, 1350000, 0, /* 474D: Rage XL */
+ ('G'<<8)|'P', 1, 1250000, 1, /* 4750: 264GT PRO */
+ ('G'<<8)|'Q', 1, 1250000, 1, /* 4751: 264GT PRO */
+ ('G'<<8)|'R', 1, 1250000, 1, /* 4752: */
+ ('G'<<8)|'T', 1, 800000, 0, /* 4754: 264GT[B] */
+ ('G'<<8)|'U', 1, 1000000, 0, /* 4755: 264GT DVD */
+ ('G'<<8)|'V', 1, 1000000, 0, /* 4756: Rage2C */
+ ('G'<<8)|'Z', 1, 1000000, 0, /* 475A: Rage2C */
+ ('V'<<8)|'T', 1, 800000, 0, /* 5654: 264VT/GT/VTB */
+ ('V'<<8)|'U', 1, 800000, 0, /* 5655: 264VT3 */
+ ('V'<<8)|'V', 1, 1000000, 0, /* 5656: 264VT4 */
+ ('L'<<8)|'B', 0, 1350000, 1, /* 4C42: Rage LTPro AGP */
+ ('L'<<8)|'I', 0, 1350000, 0, /* 4C49: Rage LTPro AGP */
+ ('L'<<8)|'M', 0, 1350000, 0, /* 4C4D: Rage Mobility */
+ ('L'<<8)|'P', 0, 1350000, 1, /* 4C50: 264LT PRO */
+};
+
+
+static int hwfill(VGAscr*, Rectangle, ulong);
+static int hwscroll(VGAscr*, Rectangle, Rectangle);
+static void initengine(VGAscr*);
+
+static Pcidev*
+mach64xxpci(void)
+{
+ Pcidev *p;
+ int i;
+
+ if((p = pcimatch(nil, 0x1002, 0)) == nil)
+ return nil;
+
+ for (i = 0; i != nelem(mach64s); i++)
+ if (mach64s[i].m64_id == p->did) {
+ mach64type = &mach64s[i];
+ return p;
+ }
+ return nil;
+}
+
+static void
+mach64xxenable(VGAscr* scr)
+{
+ Pcidev *p;
+
+ 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
+ * in the PCI base registers. There is a way to find
+ * it via the vendor-specific PCI config space but
+ * this will do for now.
+ */
+ scr->io = p->mem[1].bar & ~0x03;
+
+ if(scr->io == 0)
+ scr->io = 0x2EC;
+ }
+}
+
+static void
+mach64xxlinear(VGAscr* scr, int size, int)
+{
+ 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 {
+ CrtcOffPitch = 0x05,
+ CrtcGenCtl = 0x07,
+ CurClr0 = 0x0B, /* I/O Select */
+ CurClr1 = 0x0C,
+ CurOffset = 0x0D,
+ CurHVposn = 0x0E,
+ CurHVoff = 0x0F,
+ BusCntl = 0x13,
+ GenTestCntl = 0x19,
+
+ CrtcHsyncDis = 0x04,
+ CrtcVsyncDis = 0x08,
+
+ ContextMask = 0x100, /* not accessible via I/O */
+ FifoStat,
+ GuiStat,
+ DpFrgdClr,
+ DpBkgdClr,
+ DpWriteMask,
+ DpMix,
+ DpPixWidth,
+ DpSrc,
+ ClrCmpCntl,
+ GuiTrajCntl,
+ ScLeftRight,
+ ScTopBottom,
+ DstOffPitch,
+ DstYX,
+ DstHeightWidth,
+ DstCntl,
+ DstHeight,
+ DstBresErr,
+ DstBresInc,
+ DstBresDec,
+ SrcCntl,
+ SrcHeight1Width1,
+ SrcHeight2Width2,
+ SrcYX,
+ SrcWidth1,
+ SrcYXstart,
+ HostCntl,
+ PatReg0,
+ PatReg1,
+ PatCntl,
+ ScBottom,
+ ScLeft,
+ ScRight,
+ ScTop,
+ ClrCmpClr,
+ ClrCmpMask,
+ DpChainMask,
+ SrcOffPitch,
+ LcdIndex,
+ LcdData,
+ ClockCntl,
+ OverlayScaleCntl,
+ ConfigChipId,
+ Buf0Pitch,
+ ScalerBuf0Pitch,
+ CaptureConfig,
+ OverlayKeyCntl,
+ ScalerColourCntl,
+ ScalerHCoef0,
+ ScalerHCoef1,
+ ScalerHCoef2,
+ ScalerHCoef3,
+ ScalerHCoef4,
+ VideoFormat,
+ Buf0Offset,
+ ScalerBuf0Offset,
+ CrtcGenCntl,
+ OverlayScaleInc,
+ OverlayYX,
+ OverlayYXEnd,
+ ScalerHeightWidth,
+ HTotalDisp,
+ VTotalDisp,
+};
+
+enum {
+ LCD_ConfigPanel = 0,
+ LCD_GenCtrl,
+ LCD_DstnCntl,
+ LCD_HfbPitchAddr,
+ LCD_HorzStretch,
+ LCD_VertStretch,
+ LCD_ExtVertStretch,
+ LCD_LtGio,
+ LCD_PowerMngmnt,
+ LCD_ZvgPio,
+ Nlcd,
+};
+
+#define Bank1 (-0x100) /* 1KB */
+
+static int mmoffset[] = {
+ [HTotalDisp] 0x00,
+ [VTotalDisp] 0x02,
+ [CrtcOffPitch] 0x05,
+ [CrtcGenCntl] 0x07,
+ [CurClr0] 0x18,
+ [CurClr1] 0x19,
+ [CurOffset] 0x1A,
+ [CurHVposn] 0x1B,
+ [CurHVoff] 0x1C,
+ [ClockCntl] 0x24,
+ [BusCntl] 0x28,
+ [LcdIndex] 0x29,
+ [LcdData] 0x2A,
+ [GenTestCntl] 0x34,
+ [ConfigChipId] 0x38,
+ [DstOffPitch] 0x40,
+ [DstYX] 0x43,
+ [DstHeight] 0x45,
+ [DstHeightWidth] 0x46,
+ [DstBresErr] 0x49,
+ [DstBresInc] 0x4A,
+ [DstBresDec] 0x4B,
+ [DstCntl] 0x4C,
+ [SrcOffPitch] 0x60,
+ [SrcYX] 0x63,
+ [SrcWidth1] 0x64,
+ [SrcYXstart] 0x69,
+ [SrcHeight1Width1] 0x66,
+ [SrcHeight2Width2] 0x6C,
+ [SrcCntl] 0x6D,
+ [HostCntl] 0x90,
+ [PatReg0] 0xA0,
+ [PatReg1] 0xA1,
+ [PatCntl] 0xA2,
+ [ScLeft] 0xA8,
+ [ScRight] 0xA9,
+ [ScLeftRight] 0xAA,
+ [ScTop] 0xAB,
+ [ScBottom] 0xAC,
+ [ScTopBottom] 0xAD,
+ [DpBkgdClr] 0xB0,
+ [DpFrgdClr] 0xB1,
+ [DpWriteMask] 0xB2,
+ [DpChainMask] 0xB3,
+ [DpPixWidth] 0xB4,
+ [DpMix] 0xB5,
+ [DpSrc] 0xB6,
+ [ClrCmpClr] 0xC0,
+ [ClrCmpMask] 0xC1,
+ [ClrCmpCntl] 0xC2,
+ [FifoStat] 0xC4,
+ [ContextMask] 0xC8,
+ [GuiTrajCntl] 0xCC,
+ [GuiStat] 0xCE,
+
+ /* Bank1 */
+ [OverlayYX] Bank1 + 0x00,
+ [OverlayYXEnd] Bank1 + 0x01,
+ [OverlayKeyCntl] Bank1 + 0x06,
+ [OverlayScaleInc] Bank1 + 0x08,
+ [OverlayScaleCntl] Bank1 + 0x09,
+ [ScalerHeightWidth] Bank1 + 0x0A,
+ [ScalerBuf0Offset] Bank1 + 0x0D,
+ [ScalerBuf0Pitch] Bank1 + 0x0F,
+ [VideoFormat] Bank1 + 0x12,
+ [CaptureConfig] Bank1 + 0x14,
+ [Buf0Offset] Bank1 + 0x20,
+ [Buf0Pitch] Bank1 + 0x23,
+ [ScalerColourCntl] Bank1 + 0x54,
+ [ScalerHCoef0] Bank1 + 0x55,
+ [ScalerHCoef1] Bank1 + 0x56,
+ [ScalerHCoef2] Bank1 + 0x57,
+ [ScalerHCoef3] Bank1 + 0x58,
+ [ScalerHCoef4] Bank1 + 0x59,
+};
+
+static ulong
+ior32(VGAscr* scr, int r)
+{
+ if(scr->io == 0x2EC || scr->io == 0x1C8)
+ return inl((r<<10)+scr->io);
+ if(r >= 0x100 && scr->mmio != nil)
+ return scr->mmio[mmoffset[r]];
+ return inl((mmoffset[r]<<2)+scr->io);
+}
+
+static void
+iow32(VGAscr* scr, int r, ulong l)
+{
+ if(scr->io == 0x2EC || scr->io == 0x1C8)
+ outl(((r)<<10)+scr->io, l);
+ else if(r >= 0x100 && scr->mmio != nil)
+ scr->mmio[mmoffset[r]] = l;
+ else
+ outl((mmoffset[r]<<2)+scr->io, l);
+}
+
+static ulong
+lcdr32(VGAscr *scr, ulong r)
+{
+ ulong or;
+
+ or = ior32(scr, LcdIndex);
+ iow32(scr, LcdIndex, (or&~0x0F) | (r&0x0F));
+ return ior32(scr, LcdData);
+}
+
+static void
+lcdw32(VGAscr *scr, ulong r, ulong v)
+{
+ ulong or;
+
+ or = ior32(scr, LcdIndex);
+ iow32(scr, LcdIndex, (or&~0x0F) | (r&0x0F));
+ iow32(scr, LcdData, v);
+}
+
+static void
+mach64xxcurdisable(VGAscr* scr)
+{
+ ulong r;
+
+ r = ior32(scr, GenTestCntl);
+ iow32(scr, GenTestCntl, r & ~0x80);
+}
+
+static void
+mach64xxcurload(VGAscr* scr, Cursor* curs)
+{
+ uchar *p;
+ int i, y;
+ ulong c, s, m, r;
+
+ /*
+ * Disable the cursor.
+ */
+ r = ior32(scr, GenTestCntl);
+ iow32(scr, GenTestCntl, r & ~0x80);
+
+ p = scr->vaddr;
+ p += scr->storage;
+
+ /*
+ * Initialise the 64x64 cursor RAM array.
+ * The cursor mode gives the following truth table:
+ * p1 p0 colour
+ * 0 0 Cursor Colour 0
+ * 0 1 Cursor Colour 1
+ * 1 0 Transparent
+ * 1 1 Complement
+ * Put the cursor into the top-right of the 64x64 array.
+ */
+ for(y = 0; y < 16; y++){
+ for(i = 0; i < (64-16)/8; i++){
+ *p++ = 0xAA;
+ *p++ = 0xAA;
+ }
+
+ c = (curs->clr[2*y]<<8)|curs->clr[y*2 + 1];
+ s = (curs->set[2*y]<<8)|curs->set[y*2 + 1];
+
+ m = 0x00000000;
+ for(i = 0; i < 16; i++){
+ if(s & (1<<(15-i)))
+ m |= 0x01<<(2*i);
+ else if(c & (1<<(15-i))){
+ /* nothing to do */
+ }
+ else
+ m |= 0x02<<(2*i);
+ }
+ *p++ = m;
+ *p++ = m>>8;
+ *p++ = m>>16;
+ *p++ = m>>24;
+ }
+ memset(p, 0xAA, (64-16)*16);
+
+ /*
+ * Set the cursor hotpoint and enable the cursor.
+ */
+ scr->offset = curs->offset;
+ iow32(scr, GenTestCntl, 0x80|r);
+}
+
+static int
+ptalmostinrect(Point p, Rectangle r)
+{
+ return p.x>=r.min.x && p.x<=r.max.x &&
+ p.y>=r.min.y && p.y<=r.max.y;
+}
+
+/*
+ * If necessary, translate the rectangle physr
+ * some multiple of [dx dy] so that it includes p.
+ * Return 1 if the rectangle changed.
+ */
+static int
+screenpan(Point p, Rectangle *physr, int dx, int dy)
+{
+ int d;
+
+ if(ptalmostinrect(p, *physr))
+ return 0;
+
+ if(p.y < physr->min.y){
+ d = physr->min.y - (p.y&~(dy-1));
+ physr->min.y -= d;
+ physr->max.y -= d;
+ }
+ if(p.y > physr->max.y){
+ d = ((p.y+dy-1)&~(dy-1)) - physr->max.y;
+ physr->min.y += d;
+ physr->max.y += d;
+ }
+
+ if(p.x < physr->min.x){
+ d = physr->min.x - (p.x&~(dx-1));
+ physr->min.x -= d;
+ physr->max.x -= d;
+ }
+ if(p.x > physr->max.x){
+ d = ((p.x+dx-1)&~(dx-1)) - physr->max.x;
+ physr->min.x += d;
+ physr->max.x += d;
+ }
+ return 1;
+}
+
+static int
+mach64xxcurmove(VGAscr* scr, Point p)
+{
+ int x, xo, y, yo;
+ int dx;
+ ulong off, pitch;
+
+ /*
+ * If the point we want to display is outside the current
+ * screen rectangle, pan the screen to display it.
+ *
+ * We have to move in 64-bit chunks.
+ */
+ if(scr->gscreen->depth == 24)
+ dx = (64*3)/24;
+ else
+ dx = 64 / scr->gscreen->depth;
+
+ if(panning && screenpan(p, &physgscreenr, dx, 1)){
+ off = (physgscreenr.min.y*Dx(scr->gscreen->r)+physgscreenr.min.x)/dx;
+ pitch = Dx(scr->gscreen->r)/8;
+ iow32(scr, CrtcOffPitch, (pitch<<22)|off);
+ }
+
+ p.x -= physgscreenr.min.x;
+ p.y -= physgscreenr.min.y;
+
+ /*
+ * Mustn't position the cursor offscreen even partially,
+ * or it disappears. Therefore, if x or y is -ve, adjust the
+ * cursor presets instead. If y is negative also have to
+ * adjust the starting offset.
+ */
+ if((x = p.x+scr->offset.x) < 0){
+ xo = x;
+ x = 0;
+ }
+ else
+ xo = 0;
+ if((y = p.y+scr->offset.y) < 0){
+ yo = y;
+ y = 0;
+ }
+ else
+ yo = 0;
+
+ iow32(scr, CurHVoff, ((64-16-yo)<<16)|(64-16-xo));
+ iow32(scr, CurOffset, scr->storage/8 + (-yo*2));
+ iow32(scr, CurHVposn, (y<<16)|x);
+
+ return 0;
+}
+
+static void
+mach64xxcurenable(VGAscr* scr)
+{
+ ulong r, storage;
+
+ mach64xxenable(scr);
+ if(scr->io == 0)
+ return;
+
+ r = ior32(scr, GenTestCntl);
+ iow32(scr, GenTestCntl, r & ~0x80);
+
+ iow32(scr, CurClr0, (Pwhite<<24)|(Pwhite<<16)|(Pwhite<<8)|Pwhite);
+ iow32(scr, CurClr1, (Pblack<<24)|(Pblack<<16)|(Pblack<<8)|Pblack);
+
+ /*
+ * Find a place for the cursor data in display memory.
+ * Must be 64-bit aligned.
+ */
+ storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+7)/8;
+ iow32(scr, CurOffset, storage);
+ scr->storage = storage*8;
+
+ /*
+ * Cursor goes in the top right corner of the 64x64 array
+ * so the horizontal and vertical presets are 64-16.
+ */
+ iow32(scr, CurHVposn, (0<<16)|0);
+ iow32(scr, CurHVoff, ((64-16)<<16)|(64-16));
+
+ /*
+ * Load, locate and enable the 64x64 cursor.
+ */
+ mach64xxcurload(scr, &arrow);
+ mach64xxcurmove(scr, ZP);
+ iow32(scr, GenTestCntl, 0x80|r);
+}
+
+static void
+waitforfifo(VGAscr *scr, int entries)
+{
+ int x;
+
+ x = 0;
+ while((ior32(scr, FifoStat)&0xFF) > (0x8000>>entries) && x++ < 1000000)
+ ;
+ if(x >= 1000000)
+ iprint("fifo %d stat %#.8lux %#.8lux scrio %#.8lux mmio %#p scr %#p pc %#p\n", entries, ior32(scr, FifoStat), scr->mmio[mmoffset[FifoStat]], scr->io, scr->mmio, scr, getcallerpc(&scr));
+}
+
+static void
+waitforidle(VGAscr *scr)
+{
+ int x;
+
+ waitforfifo(scr, 16);
+ x = 0;
+ while((ior32(scr, GuiStat)&1) && x++ < 1000000)
+ ;
+ if(x >= 1000000)
+ iprint("idle stat %#.8lux %#.8lux scrio %#.8lux mmio %#p scr %#p pc %#p\n", ior32(scr, GuiStat), scr->mmio[mmoffset[GuiStat]], scr->io, scr->mmio, scr, getcallerpc(&scr));
+}
+
+static void
+resetengine(VGAscr *scr)
+{
+ ulong x;
+ x = ior32(scr, GenTestCntl);
+ iow32(scr, GenTestCntl, x&~0x100);
+ iow32(scr, GenTestCntl, x|0x100);
+ iow32(scr, BusCntl, ior32(scr, BusCntl)|0x00A00000);
+}
+
+static void
+init_overlayclock(VGAscr *scr)
+{
+ uchar *cc, save, pll_ref_div, pll_vclk_cntl, vclk_post_div,
+ vclk_fb_div, ecp_div;
+ int i;
+ ulong dotclock;
+
+ /* Taken from GLX */
+ /* Get monitor dotclock, check for Overlay Scaler clock limit */
+ cc = (uchar *)&scr->mmio[mmoffset[ClockCntl]];
+ save = cc[1]; i = cc[0] & 3;
+ cc[1] = 2<<2; pll_ref_div = cc[2];
+ cc[1] = 5<<2; pll_vclk_cntl = cc[2];
+ cc[1] = 6<<2; vclk_post_div = (cc[2]>>(i+i)) & 3;
+ cc[1] = (7+i)<<2; vclk_fb_div = cc[2];
+
+ dotclock = 2 * mach64refclock * vclk_fb_div /
+ (pll_ref_div * (1 << vclk_post_div));
+ /* ecp_div: 0=dotclock, 1=dotclock/2, 2=dotclock/4 */
+ ecp_div = dotclock / mach64type->m64_ovlclock;
+ if (ecp_div>2) ecp_div = 2;
+
+ /* Force a scaler clock factor of 1 if refclock *
+ * is unknown (VCLK_SRC not PLLVCLK) */
+ if ((pll_vclk_cntl & 0x03) != 0x03)
+ ecp_div = 0;
+ if ((pll_vclk_cntl & 0x30) != ecp_div<<4) {
+ cc[1] = (5<<2)|2;
+ cc[2] = (pll_vclk_cntl&0xCF) | (ecp_div<<4);
+ }
+
+ /* Restore PLL Register Index */
+ cc[1] = save;
+}
+
+static void
+initengine(VGAscr *scr)
+{
+ ulong pitch;
+ uchar *bios;
+ ushort table;
+
+ pitch = Dx(scr->gscreen->r)/8;
+ if(scr->gscreen->depth == 24)
+ pitch *= 3;
+
+ resetengine(scr);
+ waitforfifo(scr, 14);
+ iow32(scr, ContextMask, ~0);
+ iow32(scr, DstOffPitch, pitch<<22);
+ iow32(scr, DstYX, 0);
+ iow32(scr, DstHeight, 0);
+ iow32(scr, DstBresErr, 0);
+ iow32(scr, DstBresInc, 0);
+ iow32(scr, DstBresDec, 0);
+ iow32(scr, DstCntl, 0x23);
+ iow32(scr, SrcOffPitch, pitch<<22);
+ iow32(scr, SrcYX, 0);
+ iow32(scr, SrcHeight1Width1, 1);
+ iow32(scr, SrcYXstart, 0);
+ iow32(scr, SrcHeight2Width2, 1);
+ iow32(scr, SrcCntl, 0x01);
+
+ waitforfifo(scr, 13);
+ iow32(scr, HostCntl, 0);
+ iow32(scr, PatReg0, 0);
+ iow32(scr, PatReg1, 0);
+ iow32(scr, PatCntl, 0);
+ iow32(scr, ScLeft, 0);
+ iow32(scr, ScTop, 0);
+ iow32(scr, ScBottom, 0xFFFF);
+ iow32(scr, ScRight, 0xFFFF);
+ iow32(scr, DpBkgdClr, 0);
+ iow32(scr, DpFrgdClr, ~0);
+ iow32(scr, DpWriteMask, ~0);
+ iow32(scr, DpMix, 0x70003);
+ iow32(scr, DpSrc, 0x00010100);
+
+ waitforfifo(scr, 3);
+ iow32(scr, ClrCmpClr, 0);
+ iow32(scr, ClrCmpMask, ~0);
+ iow32(scr, ClrCmpCntl, 0);
+
+ waitforfifo(scr, 2);
+ switch(scr->gscreen->depth){
+ case 8:
+ case 24: /* [sic] */
+ iow32(scr, DpPixWidth, 0x00020202);
+ iow32(scr, DpChainMask, 0x8080);
+ break;
+ case 16:
+ iow32(scr, DpPixWidth, 0x00040404);
+ iow32(scr, DpChainMask, 0x8410);
+ break;
+ case 32:
+ iow32(scr, DpPixWidth, 0x00060606);
+ iow32(scr, DpChainMask, 0x8080);
+ break;
+ }
+
+ /* Get the base freq from the BIOS */
+ bios = kaddr(0xC000);
+ table = *(ushort *)(bios + 0x48);
+ table = *(ushort *)(bios + table + 0x10);
+ switch (*(ushort *)(bios + table + 0x08)) {
+ case 2700:
+ mach64refclock = 270000;
+ break;
+ case 2863:
+ case 2864:
+ mach64refclock = 286363;
+ break;
+ case 2950:
+ mach64refclock = 294989;
+ break;
+ case 1432:
+ default:
+ mach64refclock = 143181;
+ break ;
+ }
+
+ /* Figure out which revision this chip is */
+ switch ((scr->mmio[mmoffset[ConfigChipId]] >> 24) & 0xFF) {
+ case VTGTB1S1:
+ case GTB1U1:
+ case GTB1S2:
+ case GTB2U1:
+ case GTB2U2:
+ case GTB2U3:
+ case GTBC:
+ case GTIIIC1U1:
+ case GTIIIC1U2:
+ case GTIIIC2U1:
+ case GTIIIC2U2:
+ case GTIIIC2U3:
+ case LTPRO:
+ mach64revb = 1;
+ break;
+ default:
+ mach64revb = 0;
+ break;
+ }
+
+ waitforidle(scr);
+}
+
+static int
+mach64hwfill(VGAscr *scr, Rectangle r, ulong sval)
+{
+ ulong pitch;
+ ulong ctl;
+
+if(drawdebug)
+ iprint("hwfill %R val %lux...\n", r, sval);
+
+ /* shouldn't happen */
+ if(scr->io == 0x2EC || scr->io == 0x1C8 || scr->io == 0)
+ return 0;
+
+ pitch = Dx(scr->gscreen->r)/8;
+ ctl = 1|2; /* left-to-right, top-to-bottom */
+ if(scr->gscreen->depth == 24){
+ r.min.x *= 3;
+ r.max.x *= 3;
+ pitch *= 3;
+ ctl |= (1<<7)|(((r.min.x/4)%6)<<8);
+ }
+
+ waitforfifo(scr, 11);
+ iow32(scr, DpFrgdClr, sval);
+ iow32(scr, DpWriteMask, 0xFFFFFFFF);
+ iow32(scr, DpMix, 0x00070003);
+ iow32(scr, DpSrc, 0x00000111);
+ iow32(scr, ClrCmpCntl, 0x00000000);
+ iow32(scr, ScLeftRight, 0x1FFF0000);
+ iow32(scr, ScTopBottom, 0x1FFF0000);
+ iow32(scr, DstOffPitch, pitch<<22);
+ iow32(scr, DstCntl, ctl);
+ iow32(scr, DstYX, (r.min.x<<16)|r.min.y);
+ iow32(scr, DstHeightWidth, (Dx(r)<<16)|Dy(r));
+
+ waitforidle(scr);
+ return 1;
+}
+
+static int
+mach64hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
+{
+ ulong pitch;
+ Point dp, sp;
+ ulong ctl;
+ int dx, dy;
+
+ dx = Dx(r);
+ dy = Dy(r);
+ pitch = Dx(scr->gscreen->r)/8;
+ if(scr->gscreen->depth == 24){
+ dx *= 3;
+ pitch *= 3;
+ r.min.x *= 3;
+ sr.min.x *= 3;
+ }
+
+ ctl = 0;
+ if(r.min.x <= sr.min.x){
+ ctl |= 1;
+ dp.x = r.min.x;
+ sp.x = sr.min.x;
+ }else{
+ dp.x = r.min.x+dx-1;
+ sp.x = sr.min.x+dx-1;
+ }
+
+ if(r.min.y <= sr.min.y){
+ ctl |= 2;
+ dp.y = r.min.y;
+ sp.y = sr.min.y;
+ }else{
+ dp.y = r.min.y+dy-1;
+ sp.y = sr.min.y+dy-1;
+ }
+
+ if(scr->gscreen->depth == 24)
+ ctl |= (1<<7)|(((dp.x/4)%6)<<8);
+
+ waitforfifo(scr, 6);
+ iow32(scr, ScLeftRight, 0x1FFF0000);
+ iow32(scr, ScTopBottom, 0x1FFF0000);
+ iow32(scr, DpWriteMask, 0xFFFFFFFF);
+ iow32(scr, DpMix, 0x00070003);
+ iow32(scr, DpSrc, 0x00000300);
+ iow32(scr, ClrCmpCntl, 0x00000000);
+
+ waitforfifo(scr, 8);
+ iow32(scr, SrcOffPitch, pitch<<22);
+ iow32(scr, SrcCntl, 0x00000000);
+ iow32(scr, SrcYX, (sp.x<<16)|sp.y);
+ iow32(scr, SrcWidth1, dx);
+ iow32(scr, DstOffPitch, pitch<<22);
+ iow32(scr, DstCntl, ctl);
+
+ iow32(scr, DstYX, (dp.x<<16)|dp.y);
+ iow32(scr, DstHeightWidth, (dx<<16)|dy);
+
+ waitforidle(scr);
+
+ return 1;
+}
+
+/*
+ * This should work, but doesn't.
+ * It messes up the screen timings for some reason.
+ */
+static void
+mach64blank(VGAscr *scr, int blank)
+{
+ ulong ctl;
+
+ ctl = ior32(scr, CrtcGenCtl) & ~(CrtcHsyncDis|CrtcVsyncDis);
+ if(blank)
+ ctl |= CrtcHsyncDis|CrtcVsyncDis;
+ iow32(scr, CrtcGenCtl, ctl);
+}
+
+/*
+ * We squirrel away whether the LCD and/or CRT were
+ * on when we were called to blank the screen, and
+ * restore the old state. If we are called to blank the
+ * screen when it is already blank, we don't update the state.
+ * Such a call sequence should not happen, though.
+ *
+ * We could try forcing the chip into power management
+ * mode instead, but I'm not sure how that would interact
+ * with screen updates going on while the screen is blanked.
+ */
+static void
+mach64lcdblank(VGAscr *scr, int blank)
+{
+ static int crtlcd;
+ ulong x;
+
+ if(blank) {
+ x = lcdr32(scr, LCD_GenCtrl);
+ if(x & 3) {
+ crtlcd = x & 3;
+ lcdw32(scr, LCD_GenCtrl, x&~3);
+ }
+ } else {
+ if(crtlcd == 0)
+ crtlcd = 2; /* lcd only */
+ x = lcdr32(scr, LCD_GenCtrl);
+ lcdw32(scr, LCD_GenCtrl, x | crtlcd);
+ }
+}
+
+static void
+mach64xxdrawinit(VGAscr *scr)
+{
+ if(scr->io > 0x2FF){
+ initengine(scr);
+ scr->fill = mach64hwfill;
+ scr->scroll = mach64hwscroll;
+ }
+/* scr->blank = mach64blank; */
+ switch(scr->id){
+ default:
+ break;
+ case ('L'<<8)|'B': /* 4C42: Rage 3D LTPro */
+ case ('L'<<8)|'I': /* 4C49: Rage 3D LTPro */
+ case ('L'<<8)|'M': /* 4C4D: Rage Mobility */
+ case ('L'<<8)|'P': /* 4C50: Rage 3D LTPro */
+ scr->blank = mach64lcdblank;
+ hwblank = 1;
+ break;
+ }
+}
+
+static void
+ovl_configure(VGAscr *scr, Chan *c, char **field)
+{
+ int w, h;
+ char *format;
+
+ w = (int)strtol(field[1], nil, 0);
+ h = (int)strtol(field[2], nil, 0);
+ format = field[3];
+
+ if (c != ovl_chan)
+ error(Einuse);
+ if (strcmp(format, "YUYV"))
+ error(Eunsupportedformat);
+
+ ovl_width = w;
+ ovl_height = h;
+ ovl_fib = w * h * sizeof(ushort);
+
+ waitforidle(scr);
+ scr->mmio[mmoffset[BusCntl]] |= 0x08000000; /* Enable regblock 1 */
+ scr->mmio[mmoffset[OverlayScaleCntl]] =
+ SCALE_ZERO_EXTEND|SCALE_RED_TEMP_6500K|
+ SCALE_HORZ_BLEND|SCALE_VERT_BLEND;
+ scr->mmio[mmoffset[!mach64revb? Buf0Pitch: ScalerBuf0Pitch]] = w;
+ scr->mmio[mmoffset[CaptureConfig]] =
+ SCALER_FRAME_READ_MODE_FULL|
+ SCALER_BUF_MODE_SINGLE|
+ SCALER_BUF_NEXT_0;
+ scr->mmio[mmoffset[OverlayKeyCntl]] = !mach64revb?
+ OVERLAY_MIX_ALWAYS_V|(OVERLAY_EXCLUSIVE_NORMAL << 28):
+ 0x011;
+
+ if (mach64type->m64_pro) {
+ waitforfifo(scr, 6);
+
+ /* set the scaler co-efficient registers */
+ scr->mmio[mmoffset[ScalerColourCntl]] =
+ (0x00) | (0x10 << 8) | (0x10 << 16);
+ scr->mmio[mmoffset[ScalerHCoef0]] =
+ (0x00) | (0x20 << 8);
+ scr->mmio[mmoffset[ScalerHCoef1]] =
+ (0x0D) | (0x20 << 8) | (0x06 << 16) | (0x0D << 24);
+ scr->mmio[mmoffset[ScalerHCoef2]] =
+ (0x0D) | (0x1C << 8) | (0x0A << 16) | (0x0D << 24);
+ scr->mmio[mmoffset[ScalerHCoef3]] =
+ (0x0C) | (0x1A << 8) | (0x0E << 16) | (0x0C << 24);
+ scr->mmio[mmoffset[ScalerHCoef4]] =
+ (0x0C) | (0x14 << 8) | (0x14 << 16) | (0x0C << 24);
+ }
+
+ waitforfifo(scr, 3);
+ scr->mmio[mmoffset[VideoFormat]] = SCALE_IN_YVYU422 |
+ (!mach64revb? 0xC: 0);
+
+ if (mach64overlay == 0)
+ mach64overlay = scr->storage + 64 * 64 * sizeof(uchar);
+ scr->mmio[mmoffset[!mach64revb? Buf0Offset: ScalerBuf0Offset]] =
+ mach64overlay;
+}
+
+static void
+ovl_enable(VGAscr *scr, Chan *c, char **field)
+{
+ int x, y, w, h;
+ long h_inc, v_inc;
+
+ x = (int)strtol(field[1], nil, 0);
+ y = (int)strtol(field[2], nil, 0);
+ w = (int)strtol(field[3], nil, 0);
+ h = (int)strtol(field[4], nil, 0);
+
+ if (x < 0 || x + w > physgscreenr.max.x ||
+ y < 0 || y + h > physgscreenr.max.y)
+ error(Ebadarg);
+
+ if (c != ovl_chan)
+ error(Einuse);
+ if (scr->mmio[mmoffset[CrtcGenCntl]] & 1) { /* double scan enable */
+ y *= 2;
+ h *= 2;
+ }
+
+ waitforfifo(scr, 2);
+ scr->mmio[mmoffset[OverlayYX]] =
+ ((x & 0xFFFF) << 16) | (y & 0xFFFF);
+ scr->mmio[mmoffset[OverlayYXEnd]] =
+ (((x + w) & 0xFFFF) << 16) | ((y + h) & 0xFFFF);
+
+ h_inc = (ovl_width << 12) / (w >> 1); /* ??? */
+ v_inc = (ovl_height << 12) / h;
+ waitforfifo(scr, 2);
+ scr->mmio[mmoffset[OverlayScaleInc]] =
+ ((h_inc & 0xFFFF) << 16) | (v_inc & 0xFFFF);
+ scr->mmio[mmoffset[ScalerHeightWidth]] =
+ ((ovl_width & 0xFFFF) << 16) | (ovl_height & 0xFFFF);
+ waitforidle(scr);
+ scr->mmio[mmoffset[OverlayScaleCntl]] |=
+ (SCALE_ENABLE|OVERLAY_ENABLE);
+}
+
+static void
+ovl_status(VGAscr *scr, Chan *, char **field)
+{
+ pprint("%s: %s %.4uX, VT/GT %s, PRO %s, ovlclock %lud, rev B %s, refclock %ld\n",
+ scr->dev->name, field[0], mach64type->m64_id,
+ mach64type->m64_vtgt? "yes": "no",
+ mach64type->m64_pro? "yes": "no",
+ mach64type->m64_ovlclock,
+ mach64revb? "yes": "no",
+ mach64refclock);
+ pprint("%s: storage @%.8luX, aperture @%8.ulX, ovl buf @%.8ulX\n",
+ scr->dev->name, scr->storage, scr->paddr,
+ mach64overlay);
+}
+
+static void
+ovl_openctl(VGAscr *, Chan *c, char **)
+{
+ if (ovl_chan)
+ error(Einuse);
+ ovl_chan = c;
+}
+
+static void
+ovl_closectl(VGAscr *scr, Chan *c, char **)
+{
+ if (c != ovl_chan) return;
+
+ waitforidle(scr);
+ scr->mmio[mmoffset[OverlayScaleCntl]] &=
+ ~(SCALE_ENABLE|OVERLAY_ENABLE);
+ ovl_chan = nil;
+ ovl_width = ovl_height = ovl_fib = 0;
+}
+
+enum
+{
+ CMclosectl,
+ CMconfigure,
+ CMenable,
+ CMopenctl,
+ CMstatus,
+};
+
+static void (*ovl_cmds[])(VGAscr *, Chan *, char **) =
+{
+ [CMclosectl] ovl_closectl,
+ [CMconfigure] ovl_configure,
+ [CMenable] ovl_enable,
+ [CMopenctl] ovl_openctl,
+ [CMstatus] ovl_status,
+};
+
+static Cmdtab mach64xxcmd[] =
+{
+ CMclosectl, "closectl", 1,
+ CMconfigure, "configure", 4,
+ CMenable, "enable", 5,
+ CMopenctl, "openctl", 1,
+ CMstatus, "status", 1,
+};
+
+static void
+mach64xxovlctl(VGAscr *scr, Chan *c, void *a, int n)
+{
+ Cmdbuf *cb;
+ Cmdtab *ct;
+
+ if(!mach64type->m64_vtgt)
+ error(Enodev);
+
+ if(!scr->overlayinit){
+ scr->overlayinit = 1;
+ init_overlayclock(scr);
+ }
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+
+ ct = lookupcmd(cb, mach64xxcmd, nelem(mach64xxcmd));
+
+ ovl_cmds[ct->index](scr, c, cb->f);
+
+ poperror();
+ free(cb);
+}
+
+static int
+mach64xxovlwrite(VGAscr *scr, void *a, int len, vlong offs)
+{
+ uchar *src;
+ int _len;
+
+ if (ovl_chan == nil) return len; /* Acts as a /dev/null */
+
+ /* Calculate the destination address */
+ _len = len;
+ src = (uchar *)a;
+ while (len > 0) {
+ ulong _offs;
+ int nb;
+
+ _offs = (ulong)(offs % ovl_fib);
+ nb = (_offs + len > ovl_fib)? ovl_fib - _offs: len;
+ memmove((uchar *)scr->vaddr + mach64overlay + _offs,
+ src, nb);
+ offs += nb;
+ src += nb;
+ len -= nb;
+ }
+ return _len;
+}
+
+VGAdev vgamach64xxdev = {
+ "mach64xx",
+
+ mach64xxenable, /* enable */
+ 0, /* disable */
+ 0, /* page */
+ mach64xxlinear, /* linear */
+ mach64xxdrawinit, /* drawinit */
+ 0,
+ mach64xxovlctl, /* overlay control */
+ mach64xxovlwrite, /* write the overlay */
+};
+
+VGAcur vgamach64xxcur = {
+ "mach64xxhwgc",
+
+ mach64xxcurenable, /* enable */
+ mach64xxcurdisable, /* disable */
+ mach64xxcurload, /* load */
+ mach64xxcurmove, /* move */
+
+ 1 /* doespanning */
+};
+
diff --git a/sys/src/9/pc/vgamga2164w.c b/sys/src/9/pc/vgamga2164w.c
new file mode 100755
index 000000000..8144d245f
--- /dev/null
+++ b/sys/src/9/pc/vgamga2164w.c
@@ -0,0 +1,240 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+/*
+ * Matrox Millennium and Matrox Millennium II.
+ * Matrox MGA-2064W, MGA-2164W 3D graphics accelerators.
+ * Texas Instruments Tvp3026 RAMDAC.
+ */
+
+enum {
+ /* pci chip manufacturer */
+ MATROX = 0x102B,
+
+ /* pci chip device ids */
+ MGA2064 = 0x0519,
+ MGA2164 = 0x051B,
+ MGA2164AGP = 0x051F
+};
+
+static Pcidev*
+mgapcimatch(void)
+{
+ Pcidev *p;
+
+ p = pcimatch(nil, MATROX, MGA2164AGP);
+ if(p == nil) {
+ p = pcimatch(nil, MATROX, MGA2164);
+ if(p == nil)
+ p = pcimatch(nil, MATROX, MGA2064);
+ }
+ return p;
+}
+
+static void
+mga2164wenable(VGAscr* scr)
+{
+ Pcidev *p;
+
+ if(scr->mmio)
+ return;
+
+ p = mgapcimatch();
+ if(p == nil)
+ return;
+
+ if(p->did == MGA2064){
+ scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
+ if(scr->mmio == nil)
+ return;
+ addvgaseg("mga2164wmmio", p->mem[0].bar&~0x0F, p->mem[0].size);
+ 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;
+ addvgaseg("mga2164wmmio", p->mem[1].bar&~0x0F, p->mem[1].size);
+ vgalinearaddr(scr, p->mem[0].bar&~0x0F, 16*MB);
+ }
+ if(scr->paddr)
+ addvgaseg("mga2164wscreen", scr->paddr, scr->apsize);
+}
+
+enum {
+ Index = 0x00, /* Index */
+ Data = 0x0A, /* Data */
+
+ CaddrW = 0x04, /* Colour Write Address */
+ Cdata = 0x05, /* Colour Data */
+
+ Cctl = 0x09, /* Direct Cursor Control */
+ Cram = 0x0B, /* Cursor Ram Data */
+ Cxlsb = 0x0C, /* Cursor X LSB */
+ Cxmsb = 0x0D, /* Cursor X MSB */
+ Cylsb = 0x0E, /* Cursor Y LSB */
+ Cymsb = 0x0F, /* Cursor Y MSB */
+
+ Icctl = 0x06, /* Indirect Cursor Control */
+};
+
+static void
+tvp3026disable(VGAscr* scr)
+{
+ uchar *tvp3026;
+
+ if(scr->mmio == 0)
+ return;
+ tvp3026 = (uchar*)scr->mmio+0x3C00;
+
+ /*
+ * Make sure cursor is off
+ * and direct control enabled.
+ */
+ *(tvp3026+Index) = Icctl;
+ *(tvp3026+Data) = 0x90;
+ *(tvp3026+Cctl) = 0x00;
+}
+
+static void
+tvp3026load(VGAscr* scr, Cursor* curs)
+{
+ int x, y;
+ uchar *tvp3026;
+
+ if(scr->mmio == 0)
+ return;
+ tvp3026 = (uchar*)scr->mmio+0x3C00;
+
+ /*
+ * Make sure cursor is off by initialising the cursor
+ * control to defaults.
+ * Write to the indirect control register to make sure
+ * direct register is enabled and upper 2 bits of cursor
+ * RAM address are 0.
+ * Put 0 in index register for lower 8 bits of cursor RAM address.
+ */
+ tvp3026disable(scr);
+ *(tvp3026+Index) = 0;
+
+ /*
+ * Initialise the 64x64 cursor RAM array. There are 2 planes,
+ * p0 and p1. Data is written 8 pixels per byte, with p0 in the
+ * first 512 bytes of the array and p1 in the second.
+ * The cursor is set in 3-colour mode which gives the following
+ * truth table:
+ * p1 p0 colour
+ * 0 0 transparent
+ * 0 1 cursor colour 0
+ * 1 0 cursor colour 1
+ * 1 1 cursor colour 2
+ * Put the cursor into the top-left of the 64x64 array.
+ * The 0,0 cursor point is bottom-right, so positioning will
+ * have to take that into account.
+ */
+ for(y = 0; y < 64; y++){
+ for(x = 0; x < 64/8; x++){
+ if(x < 16/8 && y < 16)
+ *(tvp3026+Cram) = curs->clr[x+y*2];
+ else
+ *(tvp3026+Cram) = 0x00;
+ }
+ }
+ for(y = 0; y < 64; y++){
+ for(x = 0; x < 64/8; x++){
+ if(x < 16/8 && y < 16)
+ *(tvp3026+Cram) = curs->set[x+y*2];
+ else
+ *(tvp3026+Cram) = 0x00;
+ }
+ }
+
+ /*
+ * Initialise the cursor hotpoint
+ * and enable the cursor in 3-colour mode.
+ */
+ scr->offset.x = 64+curs->offset.x;
+ scr->offset.y = 64+curs->offset.y;
+ *(tvp3026+Cctl) = 0x01;
+}
+
+static int
+tvp3026move(VGAscr* scr, Point p)
+{
+ int x, y;
+ uchar *tvp3026;
+
+ if(scr->mmio == 0)
+ return 1;
+ tvp3026 = (uchar*)scr->mmio+0x3C00;
+
+ x = p.x+scr->offset.x;
+ y = p.y+scr->offset.y;
+
+ *(tvp3026+Cxlsb) = x & 0xFF;
+ *(tvp3026+Cxmsb) = (x>>8) & 0x0F;
+ *(tvp3026+Cylsb) = y & 0xFF;
+ *(tvp3026+Cymsb) = (y>>8) & 0x0F;
+
+ return 0;
+}
+
+static void
+tvp3026enable(VGAscr* scr)
+{
+ int i;
+ uchar *tvp3026;
+
+ if(scr->mmio == 0)
+ return;
+ tvp3026 = (uchar*)scr->mmio+0x3C00;
+
+ tvp3026disable(scr);
+
+ /*
+ * Overscan colour,
+ * cursor colour 1 (white),
+ * cursor colour 2, 3 (black).
+ */
+ *(tvp3026+CaddrW) = 0x00;
+ for(i = 0; i < 6; i++)
+ *(tvp3026+Cdata) = Pwhite;
+ for(i = 0; i < 6; i++)
+ *(tvp3026+Cdata) = Pblack;
+
+ /*
+ * Load, locate and enable the
+ * 64x64 cursor in 3-colour mode.
+ */
+ tvp3026load(scr, &arrow);
+ tvp3026move(scr, ZP);
+ *(tvp3026+Cctl) = 0x01;
+}
+
+VGAdev vgamga2164wdev = {
+ "mga2164w",
+
+ mga2164wenable, /* enable */
+ 0, /* disable */
+ 0, /* page */
+ 0, /* linear */
+};
+
+VGAcur vgamga2164wcur = {
+ "mga2164whwgc",
+
+ tvp3026enable,
+ tvp3026disable,
+ tvp3026load,
+ tvp3026move,
+};
diff --git a/sys/src/9/pc/vgamga4xx.c b/sys/src/9/pc/vgamga4xx.c
new file mode 100755
index 000000000..d0a902808
--- /dev/null
+++ b/sys/src/9/pc/vgamga4xx.c
@@ -0,0 +1,525 @@
+
+/*
+ * Matrox G200, G400 and G450.
+ * Written by Philippe Anel <xigh@free.fr>
+ *
+ * 2006-08-07 : Minor fix to allow the G200 cards to work fine. YDSTORG is now initialized.
+ * : Also support for 16 and 24 bit modes is added.
+ * : by Leonardo Valencia <leoval@anixcorp.com>
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+enum {
+ MATROX = 0x102B,
+ MGA550 = 0x2527,
+ MGA4xx = 0x0525,
+ MGA200 = 0x0521,
+
+ FCOL = 0x1c24,
+ FXRIGHT = 0x1cac,
+ FXLEFT = 0x1ca8,
+ YDST = 0x1c90,
+ YLEN = 0x1c5c,
+ DWGCTL = 0x1c00,
+ DWG_TRAP = 0x04,
+ DWG_BITBLT = 0x08,
+ DWG_ILOAD = 0x09,
+ DWG_LINEAR = 0x0080,
+ DWG_SOLID = 0x0800,
+ DWG_ARZERO = 0x1000,
+ DWG_SGNZERO = 0x2000,
+ DWG_SHIFTZERO = 0x4000,
+ DWG_REPLACE = 0x000C0000,
+ DWG_BFCOL = 0x04000000,
+ SRCORG = 0x2cb4,
+ PITCH = 0x1c8c,
+ DSTORG = 0x2cb8,
+ YDSTORG = 0x1c94,
+ PLNWRT = 0x1c1c,
+ ZORG = 0x1c0c,
+ MACCESS = 0x1c04,
+ STATUS = 0x1e14,
+ FXBNDRY = 0x1C84,
+ CXBNDRY = 0x1C80,
+ YTOP = 0x1C98,
+ YBOT = 0x1C9C,
+ YDSTLEN = 0x1C88,
+ AR0 = 0x1C60,
+ AR1 = 0x1C64,
+ AR2 = 0x1C68,
+ AR3 = 0x1C6C,
+ AR4 = 0x1C70,
+ AR5 = 0x1C74,
+ SGN = 0x1C58,
+ SGN_LEFT = 1,
+ SGN_UP = 4,
+
+ GO = 0x0100,
+ FIFOSTATUS = 0x1E10,
+ CACHEFLUSH = 0x1FFF,
+
+ CRTCEXTIDX = 0x1FDE, /* CRTC Extension Index */
+ CRTCEXTDATA = 0x1FDF, /* CRTC Extension Data */
+
+ FILL_OPERAND = 0x800c7804,
+};
+
+static Pcidev *
+mgapcimatch(void)
+{
+ Pcidev *p;
+
+ p = pcimatch(nil, MATROX, MGA4xx);
+ if(p == nil)
+ p = pcimatch(nil, MATROX, MGA550);
+ if(p == nil)
+ p = pcimatch(nil, MATROX, MGA200);
+ return p;
+}
+
+
+static void
+mgawrite8(VGAscr *scr, int index, uchar val)
+{
+ ((uchar*)scr->mmio)[index] = val;
+}
+
+static uchar
+mgaread8(VGAscr *scr, int index)
+{
+ return ((uchar*)scr->mmio)[index];
+}
+
+static uchar
+crtcextset(VGAscr *scr, int index, uchar set, uchar clr)
+{
+ uchar tmp;
+
+ mgawrite8(scr, CRTCEXTIDX, index);
+ tmp = mgaread8(scr, CRTCEXTDATA);
+ mgawrite8(scr, CRTCEXTIDX, index);
+ mgawrite8(scr, CRTCEXTDATA, (tmp & ~clr) | set);
+
+ return tmp;
+}
+
+static void
+mga4xxenable(VGAscr* scr)
+{
+ Pcidev *pci;
+ int size;
+ int i, n, k;
+ uchar *p;
+ uchar x[16];
+ uchar crtcext3;
+
+ if(scr->mmio)
+ return;
+
+ pci = mgapcimatch();
+ if(pci == nil)
+ return;
+
+ scr->mmio = vmap(pci->mem[1].bar&~0x0F, 16*1024);
+ if(scr->mmio == nil)
+ return;
+
+ addvgaseg("mga4xxmmio", pci->mem[1].bar&~0x0F, pci->mem[1].size);
+
+ /* need to map frame buffer here too, so vga can find memory size */
+ if(pci->did == MGA4xx || pci->did == MGA550)
+ size = 32*MB;
+ else
+ size = 8*MB;
+ vgalinearaddr(scr, pci->mem[0].bar&~0x0F, size);
+
+ 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 = scr->vaddr;
+ n = (size / MB) / 2;
+ for(i = 0; i < n; i++){
+ k = (2*i+1)*MB;
+ p[k] = 0;
+ p[k] = i+1;
+ *((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*MB; /* sketchy */
+ addvgaseg("mga4xxscreen", scr->paddr, scr->apsize);
+ crtcextset(scr, 3, crtcext3, 0xff);
+ }
+}
+
+enum{
+ Index = 0x00, /* Index */
+ Data = 0x0A, /* Data */
+
+ Cxlsb = 0x0C, /* Cursor X LSB */
+ Cxmsb = 0x0D, /* Cursor X MSB */
+ Cylsb = 0x0E, /* Cursor Y LSB */
+ Cymsb = 0x0F, /* Cursor Y MSB */
+
+ Icuradrl = 0x04, /* Cursor Base Address Low */
+ Icuradrh = 0x05, /* Cursor Base Address High */
+ Icctl = 0x06, /* Indirect Cursor Control */
+};
+
+static void
+dac4xxdisable(VGAscr *scr)
+{
+ uchar *dac4xx;
+
+ if(scr->mmio == 0)
+ return;
+
+ dac4xx = (uchar*)scr->mmio+0x3C00;
+
+ *(dac4xx+Index) = Icctl;
+ *(dac4xx+Data) = 0x00;
+}
+
+static void
+dac4xxload(VGAscr *scr, Cursor *curs)
+{
+ int y;
+ uchar *p;
+ uchar *dac4xx;
+
+ if(scr->mmio == 0)
+ return;
+
+ dac4xx = (uchar*)scr->mmio+0x3C00;
+
+ dac4xxdisable(scr);
+
+ p = (uchar*)scr->storage;
+ for(y = 0; y < 64; y++){
+ *p++ = 0; *p++ = 0; *p++ = 0;
+ *p++ = 0; *p++ = 0; *p++ = 0;
+ if(y < 16){
+ *p++ = curs->set[1+y*2];
+ *p++ = curs->set[y*2];
+ } else{
+ *p++ = 0; *p++ = 0;
+ }
+
+ *p++ = 0; *p++ = 0; *p++ = 0;
+ *p++ = 0; *p++ = 0; *p++ = 0;
+ if(y < 16){
+ *p++ = curs->set[1+y*2]|curs->clr[1+2*y];
+ *p++ = curs->set[y*2]|curs->clr[2*y];
+ } else{
+ *p++ = 0; *p++ = 0;
+ }
+ }
+ scr->offset.x = 64 + curs->offset.x;
+ scr->offset.y = 64 + curs->offset.y;
+
+ *(dac4xx+Index) = Icctl;
+ *(dac4xx+Data) = 0x03;
+}
+
+static int
+dac4xxmove(VGAscr *scr, Point p)
+{
+ int x, y;
+ uchar *dac4xx;
+
+ if(scr->mmio == 0)
+ return 1;
+
+ dac4xx = (uchar*)scr->mmio + 0x3C00;
+
+ x = p.x + scr->offset.x;
+ y = p.y + scr->offset.y;
+
+ *(dac4xx+Cxlsb) = x & 0xFF;
+ *(dac4xx+Cxmsb) = (x>>8) & 0x0F;
+
+ *(dac4xx+Cylsb) = y & 0xFF;
+ *(dac4xx+Cymsb) = (y>>8) & 0x0F;
+
+ return 0;
+}
+
+static void
+dac4xxenable(VGAscr *scr)
+{
+ uchar *dac4xx;
+ ulong storage;
+
+ if(scr->mmio == 0)
+ return;
+ dac4xx = (uchar*)scr->mmio+0x3C00;
+
+ dac4xxdisable(scr);
+
+ storage = (scr->apsize-4096)&~0x3ff;
+
+ *(dac4xx+Index) = Icuradrl;
+ *(dac4xx+Data) = 0xff & (storage >> 10);
+ *(dac4xx+Index) = Icuradrh;
+ *(dac4xx+Data) = 0xff & (storage >> 18);
+
+ scr->storage = (ulong)scr->vaddr + storage;
+
+ /* Show X11-Like Cursor */
+ *(dac4xx+Index) = Icctl;
+ *(dac4xx+Data) = 0x03;
+
+ /* Cursor Color 0 : White */
+ *(dac4xx+Index) = 0x08;
+ *(dac4xx+Data) = 0xff;
+ *(dac4xx+Index) = 0x09;
+ *(dac4xx+Data) = 0xff;
+ *(dac4xx+Index) = 0x0a;
+ *(dac4xx+Data) = 0xff;
+
+ /* Cursor Color 1 : Black */
+ *(dac4xx+Index) = 0x0c;
+ *(dac4xx+Data) = 0x00;
+ *(dac4xx+Index) = 0x0d;
+ *(dac4xx+Data) = 0x00;
+ *(dac4xx+Index) = 0x0e;
+ *(dac4xx+Data) = 0x00;
+
+ /* Cursor Color 2 : Red */
+ *(dac4xx+Index) = 0x10;
+ *(dac4xx+Data) = 0xff;
+ *(dac4xx+Index) = 0x11;
+ *(dac4xx+Data) = 0x00;
+ *(dac4xx+Index) = 0x12;
+ *(dac4xx+Data) = 0x00;
+
+ /*
+ * Load, locate and enable the
+ * 64x64 cursor in X11 mode.
+ */
+ dac4xxload(scr, &arrow);
+ dac4xxmove(scr, ZP);
+}
+
+static void
+mga4xxblank(VGAscr *scr, int blank)
+{
+ char *cp;
+ uchar *mga;
+ uchar seq1, crtcext1;
+
+ /* blank = 0 -> turn screen on */
+ /* blank = 1 -> turn screen off */
+
+ if(scr->mmio == 0)
+ return;
+ mga = (uchar*)scr->mmio;
+
+ if(blank == 0){
+ seq1 = 0x00;
+ crtcext1 = 0x00;
+ } else {
+ seq1 = 0x20;
+ crtcext1 = 0x10; /* Default value ... : standby */
+ cp = getconf("*dpms");
+ if(cp){
+ if(cistrcmp(cp, "standby") == 0)
+ crtcext1 = 0x10;
+ else if(cistrcmp(cp, "suspend") == 0)
+ crtcext1 = 0x20;
+ else if(cistrcmp(cp, "off") == 0)
+ crtcext1 = 0x30;
+ }
+ }
+
+ *(mga + 0x1fc4) = 1;
+ seq1 |= *(mga + 0x1fc5) & ~0x20;
+ *(mga + 0x1fc5) = seq1;
+
+ *(mga + 0x1fde) = 1;
+ crtcext1 |= *(mga + 0x1fdf) & ~0x30;
+ *(mga + 0x1fdf) = crtcext1;
+}
+
+static void
+mgawrite32(uchar *mga, ulong reg, ulong val)
+{
+ *((ulong*)(&mga[reg])) = val;
+}
+
+static ulong
+mgaread32(uchar *mga, ulong reg)
+{
+ return *((ulong*)(&mga[reg]));
+}
+
+static void
+mga_fifo(uchar *mga, uchar n)
+{
+ ulong t;
+
+#define Timeout 100
+ for (t = 0; t < Timeout; t++)
+ if ((mgaread32(mga, FIFOSTATUS) & 0xff) >= n)
+ break;
+ if (t >= Timeout)
+ print("mga4xx: fifo timeout");
+}
+
+static int
+mga4xxfill(VGAscr *scr, Rectangle r, ulong color)
+{
+ uchar *mga;
+
+ if(scr->mmio == 0)
+ return 0;
+ mga = (uchar*)scr->mmio;
+
+ mga_fifo(mga, 7);
+ mgawrite32(mga, DWGCTL, 0);
+ mgawrite32(mga, FCOL, color);
+ mgawrite32(mga, FXLEFT, r.min.x);
+ mgawrite32(mga, FXRIGHT, r.max.x);
+ mgawrite32(mga, YDST, r.min.y);
+ mgawrite32(mga, YLEN, Dy(r));
+ mgawrite32(mga, DWGCTL + GO, FILL_OPERAND);
+
+ while(mgaread32(mga, STATUS) & 0x00010000)
+ ;
+
+ return 1;
+}
+
+static int
+mga4xxscroll(VGAscr *scr, Rectangle dr, Rectangle sr)
+{
+ uchar * mga;
+ int pitch;
+ int width, height;
+ ulong start, end, sgn;
+ Point sp, dp;
+
+ if(scr->mmio == 0)
+ return 0;
+ mga = (uchar*)scr->mmio;
+
+ assert(Dx(sr) == Dx(dr) && Dy(sr) == Dy(dr));
+
+ sp = sr.min;
+ dp = dr.min;
+ if(eqpt(sp, dp))
+ return 1;
+
+ pitch = Dx(scr->gscreen->r);
+ width = Dx(sr);
+ height = Dy(sr);
+ sgn = 0;
+
+ if(dp.y > sp.y && dp.y < sp.y + height){
+ sp.y += height - 1;
+ dp.y += height - 1;
+ sgn |= SGN_UP;
+ }
+
+ width--;
+ start = end = sp.x + (sp.y * pitch);
+
+ if(dp.x > sp.x && dp.x < sp.x + width){
+ start += width;
+ sgn |= SGN_LEFT;
+ }
+ else
+ end += width;
+
+ mga_fifo(mga, 8);
+ mgawrite32(mga, DWGCTL, 0);
+ mgawrite32(mga, SGN, sgn);
+ mgawrite32(mga, AR5, sgn & SGN_UP ? -pitch : pitch);
+ mgawrite32(mga, AR0, end);
+ mgawrite32(mga, AR3, start);
+ mgawrite32(mga, FXBNDRY, ((dp.x + width) << 16) | dp.x);
+ mgawrite32(mga, YDSTLEN, (dp.y << 16) | height);
+ mgawrite32(mga, DWGCTL + GO, DWG_BITBLT | DWG_SHIFTZERO | DWG_BFCOL | DWG_REPLACE);
+
+ while(mgaread32(mga, STATUS) & 0x00010000)
+ ;
+
+ return 1;
+}
+
+static void
+mga4xxdrawinit(VGAscr *scr)
+{
+ uchar *mga;
+
+ if(scr->mmio == 0)
+ return;
+
+ mga = (uchar*)scr->mmio;
+
+ mgawrite32(mga, SRCORG, 0);
+ mgawrite32(mga, DSTORG, 0);
+ mgawrite32(mga, YDSTORG, 0);
+ mgawrite32(mga, ZORG, 0);
+ mgawrite32(mga, PLNWRT, ~0);
+ mgawrite32(mga, FCOL, 0xffff0000);
+ mgawrite32(mga, CXBNDRY, 0xFFFF0000);
+ mgawrite32(mga, YTOP, 0);
+ mgawrite32(mga, YBOT, 0x01FFFFFF);
+ mgawrite32(mga, PITCH, Dx(scr->gscreen->r) & ((1 << 13) - 1));
+ switch(scr->gscreen->depth){
+ case 8:
+ mgawrite32(mga, MACCESS, 0);
+ break;
+ case 16:
+ mgawrite32(mga, MACCESS, 1);
+ break;
+ case 24:
+ mgawrite32(mga, MACCESS, 3);
+ break;
+ case 32:
+ mgawrite32(mga, MACCESS, 2);
+ break;
+ default:
+ return; /* depth not supported ! */
+ }
+ scr->fill = mga4xxfill;
+ scr->scroll = mga4xxscroll;
+ scr->blank = mga4xxblank;
+}
+
+VGAdev vgamga4xxdev = {
+ "mga4xx",
+ mga4xxenable, /* enable */
+ 0, /* disable */
+ 0, /* page */
+ 0, /* linear */
+ mga4xxdrawinit,
+};
+
+VGAcur vgamga4xxcur = {
+ "mga4xxhwgc",
+ dac4xxenable,
+ dac4xxdisable,
+ dac4xxload,
+ dac4xxmove,
+};
diff --git a/sys/src/9/pc/vganeomagic.c b/sys/src/9/pc/vganeomagic.c
new file mode 100755
index 000000000..ad9c4a29c
--- /dev/null
+++ b/sys/src/9/pc/vganeomagic.c
@@ -0,0 +1,516 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+typedef struct CursorNM CursorNM;
+struct CursorNM {
+ int enable;
+ int x;
+ int y;
+ int colour1;
+ int colour2;
+ int addr;
+};
+
+static void
+neomagicenable(VGAscr* scr)
+{
+ Pcidev *p;
+ int curoff, vmsize;
+ ulong ioaddr;
+ ulong iosize;
+
+ /*
+ * 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.
+ *
+ * scr->io holds the offset into mmio of the CursorNM struct.
+ */
+ if(scr->mmio)
+ return;
+ if(p = pcimatch(nil, 0x10C8, 0)){
+ switch(p->did){
+ case 0x0003: /* MagicGraph 128ZV */
+ curoff = 0x100;
+ vmsize = 1152*1024;
+ ioaddr = (p->mem[0].bar & ~0x0F) + 0x200000;
+ iosize = 0x200000;
+ break;
+ case 0x0083: /* MagicGraph 128ZV+ */
+ curoff = 0x100;
+ vmsize = 1152*1024;
+ ioaddr = p->mem[1].bar & ~0x0F;
+ iosize = p->mem[1].size;
+ break;
+ case 0x0004: /* MagicGraph 128XD */
+ curoff = 0x100;
+ vmsize = 2048*1024;
+ ioaddr = p->mem[1].bar & ~0x0F;
+ iosize = p->mem[1].size;
+ break;
+ case 0x0005: /* MagicMedia 256AV */
+ curoff = 0x1000;
+ vmsize = 2560*1024;
+ ioaddr = p->mem[1].bar & ~0x0F;
+ iosize = p->mem[1].size;
+ break;
+ case 0x0006: /* MagicMedia 256ZX */
+ curoff = 0x1000;
+ vmsize = 4096*1024;
+ ioaddr = p->mem[1].bar & ~0x0F;
+ iosize = p->mem[1].size;
+ break;
+ case 0x0016: /* MagicMedia 256XL+ */
+ curoff = 0x1000;
+ /* Vaio VESA BIOS says 6080, but then hwgc doesn't work */
+ vmsize = 4096*1024;
+ ioaddr = p->mem[1].bar & ~0x0F;
+ iosize = p->mem[1].size;
+ break;
+ default:
+ return;
+ }
+ }
+ else
+ return;
+ scr->pci = p;
+
+ scr->mmio = vmap(ioaddr, iosize);
+ if(scr->mmio == nil)
+ return;
+ addvgaseg("neomagicmmio", ioaddr, iosize);
+
+ /*
+ * Find a place for the cursor data in display memory.
+ * 2 cursor images might be needed, 1KB each so use the
+ * last 2KB of the framebuffer.
+ */
+ scr->storage = vmsize-2*1024;
+ scr->io = curoff;
+ vgalinearpci(scr);
+ if(scr->paddr)
+ addvgaseg("neomagicscreen", scr->paddr, scr->apsize);
+}
+
+static void
+neomagiccurdisable(VGAscr* scr)
+{
+ CursorNM *cursornm;
+
+ if(scr->mmio == 0)
+ return;
+ cursornm = (void*)((char*)scr->mmio + scr->io);
+ cursornm->enable = 0;
+}
+
+static void
+neomagicinitcursor(VGAscr* scr, int xo, int yo, int index)
+{
+ uchar *p;
+ uint p0, p1;
+ int x, y;
+
+ p = (uchar*)scr->vaddr;
+ p += scr->storage + index*1024;
+
+ for(y = yo; y < 16; y++){
+ p0 = scr->set[2*y];
+ p1 = scr->set[2*y+1];
+ if(xo){
+ p0 = (p0<<xo)|(p1>>(8-xo));
+ p1 <<= xo;
+ }
+ *p++ = p0;
+ *p++ = p1;
+
+ for(x = 16; x < 64; x += 8)
+ *p++ = 0x00;
+
+ p0 = scr->clr[2*y]|scr->set[2*y];
+ p1 = scr->clr[2*y+1]|scr->set[2*y+1];
+ if(xo){
+ p0 = (p0<<xo)|(p1>>(8-xo));
+ p1 <<= xo;
+ }
+ *p++ = p0;
+ *p++ = p1;
+
+ for(x = 16; x < 64; x += 8)
+ *p++ = 0x00;
+ }
+ while(y < 64+yo){
+ for(x = 0; x < 64; x += 8){
+ *p++ = 0x00;
+ *p++ = 0x00;
+ }
+ y++;
+ }
+}
+
+static void
+neomagiccurload(VGAscr* scr, Cursor* curs)
+{
+ CursorNM *cursornm;
+
+ if(scr->mmio == 0)
+ return;
+ cursornm = (void*)((char*)scr->mmio + scr->io);
+
+ cursornm->enable = 0;
+ memmove(&scr->Cursor, curs, sizeof(Cursor));
+ neomagicinitcursor(scr, 0, 0, 0);
+ cursornm->enable = 1;
+}
+
+static int
+neomagiccurmove(VGAscr* scr, Point p)
+{
+ CursorNM *cursornm;
+ int addr, index, x, xo, y, yo;
+
+ if(scr->mmio == 0)
+ return 1;
+ cursornm = (void*)((char*)scr->mmio + scr->io);
+
+ index = 0;
+ if((x = p.x+scr->offset.x) < 0){
+ xo = -x;
+ x = 0;
+ }
+ else
+ xo = 0;
+ if((y = p.y+scr->offset.y) < 0){
+ yo = -y;
+ y = 0;
+ }
+ else
+ yo = 0;
+
+ if(xo || yo){
+ index = 1;
+ neomagicinitcursor(scr, xo, yo, index);
+ }
+ addr = ((scr->storage+(1024*index))>>10) & 0xFFF;
+ addr = ((addr & 0x00F)<<8)|((addr>>4) & 0xFF);
+ if(cursornm->addr != addr)
+ cursornm->addr = addr;
+
+ cursornm->x = x;
+ cursornm->y = y;
+
+ return 0;
+}
+
+static void
+neomagiccurenable(VGAscr* scr)
+{
+ CursorNM *cursornm;
+
+ neomagicenable(scr);
+ if(scr->mmio == 0)
+ return;
+ cursornm = (void*)((char*)scr->mmio + scr->io);
+ cursornm->enable = 0;
+
+ /*
+ * Cursor colours.
+ */
+ cursornm->colour1 = (Pblack<<16)|(Pblack<<8)|Pblack;
+ cursornm->colour2 = (Pwhite<<16)|(Pwhite<<8)|Pwhite;
+
+ /*
+ * Load, locate and enable the 64x64 cursor.
+ */
+ neomagiccurload(scr, &arrow);
+ neomagiccurmove(scr, ZP);
+ cursornm->enable = 1;
+}
+
+static int neomagicbltflags;
+
+/* registers */
+enum {
+ BltStat = 0,
+ BltCntl = 1,
+ XPColor = 2,
+ FGColor = 3,
+ BGColor = 4,
+ Pitch = 5,
+ ClipLT = 6,
+ ClipRB = 7,
+ SrcBitOff = 8,
+ SrcStartOff = 9,
+
+ DstStartOff = 11,
+ XYExt = 12,
+
+ PageCntl = 20,
+ PageBase,
+ PostBase,
+ PostPtr,
+ DataPtr,
+};
+
+/* flags */
+enum {
+ NEO_BS0_BLT_BUSY = 0x00000001,
+ NEO_BS0_FIFO_AVAIL = 0x00000002,
+ NEO_BS0_FIFO_PEND = 0x00000004,
+
+ NEO_BC0_DST_Y_DEC = 0x00000001,
+ NEO_BC0_X_DEC = 0x00000002,
+ NEO_BC0_SRC_TRANS = 0x00000004,
+ NEO_BC0_SRC_IS_FG = 0x00000008,
+ NEO_BC0_SRC_Y_DEC = 0x00000010,
+ NEO_BC0_FILL_PAT = 0x00000020,
+ NEO_BC0_SRC_MONO = 0x00000040,
+ NEO_BC0_SYS_TO_VID = 0x00000080,
+
+ NEO_BC1_DEPTH8 = 0x00000100,
+ NEO_BC1_DEPTH16 = 0x00000200,
+ NEO_BC1_DEPTH24 = 0x00000300,
+ NEO_BC1_X_320 = 0x00000400,
+ NEO_BC1_X_640 = 0x00000800,
+ NEO_BC1_X_800 = 0x00000c00,
+ NEO_BC1_X_1024 = 0x00001000,
+ NEO_BC1_X_1152 = 0x00001400,
+ NEO_BC1_X_1280 = 0x00001800,
+ NEO_BC1_X_1600 = 0x00001c00,
+ NEO_BC1_DST_TRANS = 0x00002000,
+ NEO_BC1_MSTR_BLT = 0x00004000,
+ NEO_BC1_FILTER_Z = 0x00008000,
+
+ NEO_BC2_WR_TR_DST = 0x00800000,
+
+ NEO_BC3_SRC_XY_ADDR = 0x01000000,
+ NEO_BC3_DST_XY_ADDR = 0x02000000,
+ NEO_BC3_CLIP_ON = 0x04000000,
+ NEO_BC3_FIFO_EN = 0x08000000,
+ NEO_BC3_BLT_ON_ADDR = 0x10000000,
+ NEO_BC3_SKIP_MAPPING = 0x80000000,
+
+ NEO_MODE1_DEPTH8 = 0x0100,
+ NEO_MODE1_DEPTH16 = 0x0200,
+ NEO_MODE1_DEPTH24 = 0x0300,
+ NEO_MODE1_X_320 = 0x0400,
+ NEO_MODE1_X_640 = 0x0800,
+ NEO_MODE1_X_800 = 0x0c00,
+ NEO_MODE1_X_1024 = 0x1000,
+ NEO_MODE1_X_1152 = 0x1400,
+ NEO_MODE1_X_1280 = 0x1800,
+ NEO_MODE1_X_1600 = 0x1c00,
+ NEO_MODE1_BLT_ON_ADDR = 0x2000,
+};
+
+/* Raster Operations */
+enum {
+ GXclear = 0x000000, /* 0x0000 */
+ GXand = 0x080000, /* 0x1000 */
+ GXandReverse = 0x040000, /* 0x0100 */
+ GXcopy = 0x0c0000, /* 0x1100 */
+ GXandInvert = 0x020000, /* 0x0010 */
+ GXnoop = 0x0a0000, /* 0x1010 */
+ GXxor = 0x060000, /* 0x0110 */
+ GXor = 0x0e0000, /* 0x1110 */
+ GXnor = 0x010000, /* 0x0001 */
+ GXequiv = 0x090000, /* 0x1001 */
+ GXinvert = 0x050000, /* 0x0101 */
+ GXorReverse = 0x0d0000, /* 0x1101 */
+ GXcopyInvert = 0x030000, /* 0x0011 */
+ GXorInverted = 0x0b0000, /* 0x1011 */
+ GXnand = 0x070000, /* 0x0111 */
+ GXset = 0x0f0000, /* 0x1111 */
+};
+
+static void
+waitforidle(VGAscr *scr)
+{
+ ulong *mmio;
+ long x;
+
+ mmio = scr->mmio;
+ x = 0;
+ while((mmio[BltStat] & NEO_BS0_BLT_BUSY) && x++ < 1000000)
+ ;
+ //if(x >= 1000000)
+ // iprint("idle stat %lud scrmmio %#.8lux scr %#p pc %#p\n", mmio[BltStat], scr->mmio, scr, getcallerpc(&scr));
+}
+
+static void
+waitforfifo(VGAscr *scr, int entries)
+{
+ ulong *mmio;
+ long x;
+
+ mmio = scr->mmio;
+ x = 0;
+ while(((mmio[BltStat]>>8) < entries) && x++ < 1000000)
+ ;
+ //if(x >= 1000000)
+ // iprint("fifo stat %d scrmmio %#.8lux scr %#p pc %#p\n", mmio[BltStat]>>8, scr->mmio, scr, getcallerpc(&scr));
+ /* DirectFB says the above doesn't work. if so... */
+ /* waitforidle(scr); */
+}
+
+static int
+neomagichwfill(VGAscr *scr, Rectangle r, ulong sval)
+{
+ ulong *mmio;
+
+ mmio = scr->mmio;
+
+ waitforfifo(scr, 1);
+ mmio[FGColor] = sval;
+ waitforfifo(scr, 3);
+ mmio[BltCntl] = neomagicbltflags
+ | NEO_BC3_FIFO_EN
+ | NEO_BC0_SRC_IS_FG
+ | NEO_BC3_SKIP_MAPPING
+ | GXcopy;
+ 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);
+ waitforidle(scr);
+ return 1;
+}
+
+static int
+neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
+{
+ ulong *mmio;
+ int pitch, pixel;
+
+ mmio = scr->mmio;
+
+ pitch = scr->gscreen->width*BY2WD;
+ pixel = scr->gscreen->depth/BI2BY;
+
+ waitforfifo(scr, 4);
+ if (r.min.y < sr.min.y || (r.min.y == sr.min.y && r.min.x < sr.min.x)) {
+ /* start from upper-left */
+ mmio[BltCntl] = neomagicbltflags
+ | NEO_BC3_FIFO_EN
+ | NEO_BC3_SKIP_MAPPING
+ | GXcopy;
+ mmio[SrcStartOff] = scr->paddr
+ + sr.min.y*pitch + sr.min.x*pixel;
+ mmio[DstStartOff] = scr->paddr
+ + r.min.y*pitch + r.min.x*pixel;
+ } else {
+ /* start from lower-right */
+ mmio[BltCntl] = neomagicbltflags
+ | NEO_BC0_X_DEC
+ | NEO_BC0_DST_Y_DEC
+ | NEO_BC0_SRC_Y_DEC
+ | NEO_BC3_FIFO_EN
+ | NEO_BC3_SKIP_MAPPING
+ | GXcopy;
+ mmio[SrcStartOff] = scr->paddr
+ + (sr.max.y-1)*pitch + (sr.max.x-1)*pixel;
+ mmio[DstStartOff] = scr->paddr
+ + (r.max.y-1)*pitch + (r.max.x-1)*pixel;
+ }
+ mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
+ waitforidle(scr);
+ return 1;
+}
+
+static void
+neomagicdrawinit(VGAscr *scr)
+{
+ ulong *mmio;
+ uint bltmode, pitch;
+
+ mmio = scr->mmio;
+
+ pitch = scr->gscreen->width*BY2WD;
+
+ neomagicbltflags = bltmode = 0;
+
+ switch(scr->gscreen->depth) {
+ case 8:
+ bltmode |= NEO_MODE1_DEPTH8;
+ neomagicbltflags |= NEO_BC1_DEPTH8;
+ break;
+ case 16:
+ bltmode |= NEO_MODE1_DEPTH16;
+ neomagicbltflags |= NEO_BC1_DEPTH16;
+ break;
+ case 24: /* I can't get it to work, and XFree86 doesn't either. */
+ default: /* give up */
+ return;
+ }
+
+ switch(Dx(scr->gscreen->r)) {
+ case 320:
+ bltmode |= NEO_MODE1_X_320;
+ neomagicbltflags |= NEO_BC1_X_320;
+ break;
+ case 640:
+ bltmode |= NEO_MODE1_X_640;
+ neomagicbltflags |= NEO_BC1_X_640;
+ break;
+ case 800:
+ bltmode |= NEO_MODE1_X_800;
+ neomagicbltflags |= NEO_BC1_X_800;
+ break;
+ case 1024:
+ bltmode |= NEO_MODE1_X_1024;
+ neomagicbltflags |= NEO_BC1_X_1024;
+ break;
+ case 1152:
+ bltmode |= NEO_MODE1_X_1152;
+ neomagicbltflags |= NEO_BC1_X_1152;
+ break;
+ case 1280:
+ bltmode |= NEO_MODE1_X_1280;
+ neomagicbltflags |= NEO_BC1_X_1280;
+ break;
+ case 1600:
+ bltmode |= NEO_MODE1_X_1600;
+ neomagicbltflags |= NEO_BC1_X_1600;
+ break;
+ default:
+ /* don't worry about it */
+ break;
+ }
+
+ waitforidle(scr);
+ mmio[BltStat] = bltmode << 16;
+ mmio[Pitch] = (pitch << 16) | (pitch & 0xffff);
+
+ scr->fill = neomagichwfill;
+ scr->scroll = neomagichwscroll;
+}
+
+VGAdev vganeomagicdev = {
+ "neomagic",
+
+ neomagicenable,
+ nil,
+ nil,
+ nil,
+ neomagicdrawinit,
+};
+
+VGAcur vganeomagiccur = {
+ "neomagichwgc",
+
+ neomagiccurenable,
+ neomagiccurdisable,
+ neomagiccurload,
+ neomagiccurmove,
+};
+
diff --git a/sys/src/9/pc/vganvidia.c b/sys/src/9/pc/vganvidia.c
new file mode 100755
index 000000000..5ef910451
--- /dev/null
+++ b/sys/src/9/pc/vganvidia.c
@@ -0,0 +1,540 @@
+
+/* Portions of this file derived from work with the following copyright */
+
+ /***************************************************************************\
+|* *|
+|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NOTICE TO USER: The source code is copyrighted under U.S. and *|
+|* international laws. Users and possessors of this source code are *|
+|* hereby granted a nonexclusive, royalty-free copyright license to *|
+|* use this code in individual and commercial software. *|
+|* *|
+|* Any use of this source code must include, in the user documenta- *|
+|* tion and internal comments to the code, notices to the end user *|
+|* as follows: *|
+|* *|
+|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
+|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
+|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
+|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
+|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
+|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
+|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
+|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
+|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
+|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
+|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
+|* *|
+|* U.S. Government End Users. This source code is a "commercial *|
+|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
+|* consisting of "commercial computer software" and "commercial *|
+|* computer software documentation," as such terms are used in *|
+|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
+|* ment only as a commercial end item. Consistent with 48 C.F.R. *|
+|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
+|* all U.S. Government End Users acquire the source code with only *|
+|* those rights set forth herein. *|
+|* *|
+ \***************************************************************************/
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+#include "nv_dma.h"
+
+enum {
+ Pramin = 0x00710000,
+ Pramdac = 0x00680000,
+ Fifo = 0x00800000,
+ Pgraph = 0x00400000,
+ Pfb = 0x00100000
+};
+
+enum {
+ hwCurPos = Pramdac + 0x0300,
+};
+
+#define SKIPS 8
+
+struct {
+ ulong *dmabase;
+ int dmacurrent;
+ int dmaput;
+ int dmafree;
+ int dmamax;
+} nv;
+
+static Pcidev*
+nvidiapci(void)
+{
+ Pcidev *p;
+
+ p = nil;
+ while((p = pcimatch(p, 0x10DE, 0)) != nil){
+ if(p->did >= 0x20 && p->ccrb == 3) /* video card */
+ return p;
+ }
+ return nil;
+}
+
+static void
+nvidialinear(VGAscr*, int, int)
+{
+}
+
+static void
+nvidiaenable(VGAscr* scr)
+{
+ Pcidev *p;
+ ulong *q;
+ int tmp;
+
+ if(scr->mmio)
+ return;
+ p = nvidiapci();
+ if(p == nil)
+ return;
+ scr->id = p->did;
+ scr->pci = p;
+
+ scr->mmio = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
+ if(scr->mmio == nil)
+ return;
+ 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 = (void*)((uchar*)scr->mmio + Pfb);
+ tmp = *q;
+ if (tmp & 0x0100) {
+ scr->storage = ((tmp >> 12) & 0x0F) * 1024 + 1024 * 2;
+ } else {
+ tmp &= 0x03;
+ if (tmp)
+ scr->storage = (1024*1024*2) << tmp;
+ else
+ scr->storage = 1024*1024*32;
+ }
+ break;
+ case 0x01A0:
+ p = pcimatchtbdf(MKBUS(BusPCI, 0, 0, 1));
+ tmp = pcicfgr32(p, 0x7C);
+ scr->storage = (((tmp >> 6) & 31) + 1) * 1024 * 1024;
+ break;
+ case 0x01F0:
+ p = pcimatchtbdf(MKBUS(BusPCI, 0, 0, 1));
+ tmp = pcicfgr32(p, 0x84);
+ scr->storage = (((tmp >> 4) & 127) + 1) * 1024 * 1024;
+ break;
+ default:
+ q = (void*)((uchar*)scr->mmio + Pfb + 0x020C);
+ tmp = (*q >> 20) & 0xFFF;
+ if (tmp == 0)
+ tmp = 16;
+ scr->storage = tmp*1024*1024;
+ break;
+ }
+}
+
+static void
+nvidiacurdisable(VGAscr* scr)
+{
+ if(scr->mmio == 0)
+ return;
+
+ vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
+}
+
+
+static void
+nvidiacurload(VGAscr* scr, Cursor* curs)
+{
+ ulong* p;
+ int i,j;
+ ushort c,s;
+ ulong tmp;
+
+ if(scr->mmio == 0)
+ return;
+
+ vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
+
+ switch (scr->id & 0x0ff0) {
+ case 0x0020:
+ case 0x00A0:
+ p = (void*)((uchar*)scr->mmio + Pramin + 0x1E00 * 4);
+ break;
+ default:
+ /*
+ * Reset the cursor location, since the kernel may
+ * have allocated less storage than aux/vga
+ * expected.
+ */
+ tmp = scr->apsize - 96*1024;
+ p = (void*)((uchar*)scr->vaddr + tmp);
+ vgaxo(Crtx, 0x30, 0x80|(tmp>>17));
+ vgaxo(Crtx, 0x31, (tmp>>11)<<2);
+ vgaxo(Crtx, 0x2F, tmp>>24);
+ break;
+ }
+
+ for(i=0; i<16; i++) {
+ c = (curs->clr[2 * i] << 8) | curs->clr[2 * i+1];
+ s = (curs->set[2 * i] << 8) | curs->set[2 * i+1];
+ tmp = 0;
+ for (j=0; j<16; j++){
+ if(s&0x8000)
+ tmp |= 0x80000000;
+ else if(c&0x8000)
+ tmp |= 0xFFFF0000;
+ if (j&0x1){
+ *p++ = tmp;
+ tmp = 0;
+ } else {
+ tmp>>=16;
+ }
+ c<<=1;
+ s<<=1;
+ }
+ for (j=0; j<8; j++)
+ *p++ = 0;
+ }
+ for (i=0; i<256; i++)
+ *p++ = 0;
+
+ scr->offset = curs->offset;
+ vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
+
+ return;
+}
+
+static int
+nvidiacurmove(VGAscr* scr, Point p)
+{
+ ulong* cursorpos;
+
+ if(scr->mmio == 0)
+ return 1;
+
+ cursorpos = (void*)((uchar*)scr->mmio + hwCurPos);
+ *cursorpos = ((p.y+scr->offset.y)<<16)|((p.x+scr->offset.x) & 0xFFFF);
+
+ return 0;
+}
+
+static void
+nvidiacurenable(VGAscr* scr)
+{
+ nvidiaenable(scr);
+ if(scr->mmio == 0)
+ return;
+
+ vgaxo(Crtx, 0x1F, 0x57);
+
+ nvidiacurload(scr, &arrow);
+ nvidiacurmove(scr, ZP);
+
+ vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
+}
+
+void
+writeput(VGAscr *scr, int data)
+{
+ uchar *p, scratch;
+ ulong *fifo;
+
+ outb(0x3D0,0);
+ p = scr->vaddr;
+ scratch = *p;
+ fifo = (void*)((uchar*)scr->mmio + Fifo);
+ fifo[0x10] = (data << 2);
+ USED(scratch);
+}
+
+ulong
+readget(VGAscr *scr)
+{
+ ulong *fifo;
+
+ fifo = (void*)((uchar*)scr->mmio + Fifo);
+ return (fifo[0x0011] >> 2);
+}
+
+void
+nvdmakickoff(VGAscr *scr)
+{
+ if(nv.dmacurrent != nv.dmaput) {
+ nv.dmaput = nv.dmacurrent;
+ writeput(scr, nv.dmaput);
+ }
+}
+
+static void
+nvdmanext(ulong data)
+{
+ nv.dmabase[nv.dmacurrent++] = data;
+}
+
+void
+nvdmawait(VGAscr *scr, int size)
+{
+ int dmaget;
+
+ size++;
+
+ while(nv.dmafree < size) {
+ dmaget = readget(scr);
+
+ if(nv.dmaput >= dmaget) {
+ nv.dmafree = nv.dmamax - nv.dmacurrent;
+ if(nv.dmafree < size) {
+ nvdmanext(0x20000000);
+ if(dmaget <= SKIPS) {
+ if (nv.dmaput <= SKIPS) /* corner case - will be idle */
+ writeput(scr, SKIPS + 1);
+ do { dmaget = readget(scr); }
+ while(dmaget <= SKIPS);
+ }
+ writeput(scr, SKIPS);
+ nv.dmacurrent = nv.dmaput = SKIPS;
+ nv.dmafree = dmaget - (SKIPS + 1);
+ }
+ } else
+ nv.dmafree = dmaget - nv.dmacurrent - 1;
+ }
+}
+
+
+static void
+nvdmastart(VGAscr *scr, ulong tag, int size)
+{
+ if (nv.dmafree <= size)
+ nvdmawait(scr, size);
+ nvdmanext((size << 18) | tag);
+ nv.dmafree -= (size + 1);
+}
+
+static void
+waitforidle(VGAscr *scr)
+{
+ ulong* pgraph;
+ int x;
+
+ pgraph = (void*)((uchar*)scr->mmio + Pgraph);
+
+ x = 0;
+ while((readget(scr) != nv.dmaput) && x++ < 1000000)
+ ;
+ if(x >= 1000000)
+ iprint("idle stat %lud put %d scr %#p pc %#p\n", readget(scr), nv.dmaput, scr, getcallerpc(&scr));
+
+ x = 0;
+ while(pgraph[0x00000700/4] & 0x01 && x++ < 1000000)
+ ;
+
+ if(x >= 1000000)
+ iprint("idle stat %lud scrio %#p scr %#p pc %#p\n", *pgraph, scr->mmio, scr, getcallerpc(&scr));
+}
+
+static void
+nvresetgraphics(VGAscr *scr)
+{
+ ulong surfaceFormat, patternFormat, rectFormat, lineFormat;
+ int pitch, i;
+
+ pitch = scr->gscreen->width*BY2WD;
+
+ /*
+ * DMA is at the end of the virtual window,
+ * but we might have cut it short when mapping it.
+ */
+ if(nv.dmabase == nil){
+ if(scr->storage <= scr->apsize)
+ nv.dmabase = (ulong*)((uchar*)scr->vaddr + scr->storage - 128*1024);
+ else{
+ nv.dmabase = (void*)vmap(scr->paddr + scr->storage - 128*1024, 128*1024);
+ if(nv.dmabase == 0){
+ hwaccel = 0;
+ hwblank = 0;
+ print("vmap nvidia dma failed\n");
+ return;
+ }
+ }
+ }
+
+ for(i=0; i<SKIPS; i++)
+ nv.dmabase[i] = 0x00000000;
+
+ nv.dmabase[0x0 + SKIPS] = 0x00040000;
+ nv.dmabase[0x1 + SKIPS] = 0x80000010;
+ nv.dmabase[0x2 + SKIPS] = 0x00042000;
+ nv.dmabase[0x3 + SKIPS] = 0x80000011;
+ nv.dmabase[0x4 + SKIPS] = 0x00044000;
+ nv.dmabase[0x5 + SKIPS] = 0x80000012;
+ nv.dmabase[0x6 + SKIPS] = 0x00046000;
+ nv.dmabase[0x7 + SKIPS] = 0x80000013;
+ nv.dmabase[0x8 + SKIPS] = 0x00048000;
+ nv.dmabase[0x9 + SKIPS] = 0x80000014;
+ nv.dmabase[0xA + SKIPS] = 0x0004A000;
+ nv.dmabase[0xB + SKIPS] = 0x80000015;
+ nv.dmabase[0xC + SKIPS] = 0x0004C000;
+ nv.dmabase[0xD + SKIPS] = 0x80000016;
+ nv.dmabase[0xE + SKIPS] = 0x0004E000;
+ nv.dmabase[0xF + SKIPS] = 0x80000017;
+
+ nv.dmaput = 0;
+ nv.dmacurrent = 16 + SKIPS;
+ nv.dmamax = 8191;
+ nv.dmafree = nv.dmamax - nv.dmacurrent;
+
+ switch(scr->gscreen->depth) {
+ case 32:
+ case 24:
+ surfaceFormat = SURFACE_FORMAT_DEPTH24;
+ patternFormat = PATTERN_FORMAT_DEPTH24;
+ rectFormat = RECT_FORMAT_DEPTH24;
+ lineFormat = LINE_FORMAT_DEPTH24;
+ break;
+ case 16:
+ case 15:
+ surfaceFormat = SURFACE_FORMAT_DEPTH16;
+ patternFormat = PATTERN_FORMAT_DEPTH16;
+ rectFormat = RECT_FORMAT_DEPTH16;
+ lineFormat = LINE_FORMAT_DEPTH16;
+ break;
+ default:
+ surfaceFormat = SURFACE_FORMAT_DEPTH8;
+ patternFormat = PATTERN_FORMAT_DEPTH8;
+ rectFormat = RECT_FORMAT_DEPTH8;
+ lineFormat = LINE_FORMAT_DEPTH8;
+ break;
+ }
+
+ nvdmastart(scr, SURFACE_FORMAT, 4);
+ nvdmanext(surfaceFormat);
+ nvdmanext(pitch | (pitch << 16));
+ nvdmanext(0);
+ nvdmanext(0);
+
+ nvdmastart(scr, PATTERN_FORMAT, 1);
+ nvdmanext(patternFormat);
+
+ nvdmastart(scr, RECT_FORMAT, 1);
+ nvdmanext(rectFormat);
+
+ nvdmastart(scr, LINE_FORMAT, 1);
+ nvdmanext(lineFormat);
+
+ nvdmastart(scr, PATTERN_COLOR_0, 4);
+ nvdmanext(~0);
+ nvdmanext(~0);
+ nvdmanext(~0);
+ nvdmanext(~0);
+
+ nvdmastart(scr, ROP_SET, 1);
+ nvdmanext(0xCC);
+
+ nvdmakickoff(scr);
+ waitforidle(scr);
+}
+
+
+static int
+nvidiahwfill(VGAscr *scr, Rectangle r, ulong sval)
+{
+ nvdmastart(scr, RECT_SOLID_COLOR, 1);
+ nvdmanext(sval);
+
+ nvdmastart(scr, RECT_SOLID_RECTS(0), 2);
+ nvdmanext((r.min.x << 16) | r.min.y);
+ nvdmanext((Dx(r) << 16) | Dy(r));
+
+ //if ( (Dy(r) * Dx(r)) >= 512)
+ nvdmakickoff(scr);
+
+ waitforidle(scr);
+
+ return 1;
+}
+
+static int
+nvidiahwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
+{
+ nvdmastart(scr, BLIT_POINT_SRC, 3);
+ nvdmanext((sr.min.y << 16) | sr.min.x);
+ nvdmanext((r.min.y << 16) | r.min.x);
+ nvdmanext((Dy(r) << 16) | Dx(r));
+
+ //if ( (Dy(r) * Dx(r)) >= 512)
+ nvdmakickoff(scr);
+
+ waitforidle(scr);
+
+ return 1;
+}
+
+void
+nvidiablank(VGAscr*, int blank)
+{
+ uchar seq1, crtc1A;
+
+ seq1 = vgaxi(Seqx, 1) & ~0x20;
+ crtc1A = vgaxi(Crtx, 0x1A) & ~0xC0;
+
+ if(blank){
+ seq1 |= 0x20;
+// crtc1A |= 0xC0;
+ crtc1A |= 0x80;
+ }
+
+ vgaxo(Seqx, 1, seq1);
+ vgaxo(Crtx, 0x1A, crtc1A);
+}
+
+static void
+nvidiadrawinit(VGAscr *scr)
+{
+ nvresetgraphics(scr);
+ scr->blank = nvidiablank;
+ hwblank = 1;
+ scr->fill = nvidiahwfill;
+ scr->scroll = nvidiahwscroll;
+}
+
+VGAdev vganvidiadev = {
+ "nvidia",
+
+ nvidiaenable,
+ nil,
+ nil,
+ nvidialinear,
+ nvidiadrawinit,
+};
+
+VGAcur vganvidiacur = {
+ "nvidiahwgc",
+
+ nvidiacurenable,
+ nvidiacurdisable,
+ nvidiacurload,
+ nvidiacurmove,
+};
diff --git a/sys/src/9/pc/vgaradeon.c b/sys/src/9/pc/vgaradeon.c
new file mode 100755
index 000000000..6fb89c8da
--- /dev/null
+++ b/sys/src/9/pc/vgaradeon.c
@@ -0,0 +1,520 @@
+/*
+ * ATI Radeon [789]XXX vga driver
+ * see /sys/src/cmd/aux/vga/radeon.c
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+#include "/sys/src/cmd/aux/vga/radeon.h" /* ugh */
+
+/* #define HW_ACCEL */
+
+enum {
+ Kilo = 1024,
+ Meg = Kilo * Kilo,
+};
+
+static Pcidev*
+radeonpci(void)
+{
+ static Pcidev *p = nil;
+ struct pciids *ids;
+
+ while ((p = pcimatch(p, ATI_PCIVID, 0)) != nil)
+ for (ids = radeon_pciids; ids->did; ids++)
+ if (ids->did == p->did)
+ return p;
+ return nil;
+}
+
+/* mmio access */
+
+static void
+OUTREG8(ulong mmio, ulong offset, uchar val)
+{
+ ((uchar*)KADDR((mmio + offset)))[0] = val;
+}
+
+static void
+OUTREG(ulong mmio, ulong offset, ulong val)
+{
+ ((ulong*)KADDR((mmio + offset)))[0] = val;
+}
+
+static ulong
+INREG(ulong mmio, ulong offset)
+{
+ return ((ulong*)KADDR((mmio + offset)))[0];
+}
+
+static void
+OUTREGP(ulong mmio, ulong offset, ulong val, ulong mask)
+{
+ OUTREG(mmio, offset, (INREG(mmio, offset) & mask) | val);
+}
+
+static void
+OUTPLL(ulong mmio, ulong offset, ulong val)
+{
+ OUTREG8(mmio, CLOCK_CNTL_INDEX, (offset & 0x3f) | PLL_WR_EN);
+ OUTREG(mmio, CLOCK_CNTL_DATA, val);
+}
+
+static ulong
+INPLL(ulong mmio, ulong offset)
+{
+ OUTREG8(mmio, CLOCK_CNTL_INDEX, offset & 0x3f);
+ return INREG(mmio, CLOCK_CNTL_DATA);
+}
+
+static void
+OUTPLLP(ulong mmio, ulong offset, ulong val, ulong mask)
+{
+ OUTPLL(mmio, offset, (INPLL(mmio, offset) & mask) | val);
+}
+
+static void
+radeonlinear(VGAscr *, int, int)
+{
+}
+
+static void
+radeonenable(VGAscr *scr)
+{
+ Pcidev *p;
+
+ if (scr->mmio)
+ return;
+ p = radeonpci();
+ if (p == nil)
+ return;
+ scr->id = p->did;
+ scr->pci = p;
+
+ scr->mmio = vmap(p->mem[2].bar & ~0x0f, p->mem[2].size);
+ if(scr->mmio == 0)
+ return;
+ addvgaseg("radeonmmio", p->mem[2].bar & ~0x0f, p->mem[2].size);
+
+ vgalinearpci(scr);
+ if(scr->apsize)
+ addvgaseg("radeonscreen", scr->paddr, scr->apsize);
+}
+
+static void
+radeoncurload(VGAscr *scr, Cursor *curs)
+{
+ int x, y;
+ ulong *p;
+
+ if(scr->mmio == nil)
+ return;
+
+ p = (ulong*)KADDR(scr->storage);
+
+ for(y = 0; y < 64; y++){
+ int cv, sv;
+
+ if (y < 16) {
+ cv = curs->clr[2*y] << 8 | curs->clr[2*y+1];
+ sv = curs->set[2*y] << 8 | curs->set[2*y+1];
+ } else
+ cv = sv = 0;
+
+ for(x = 0; x < 64; x++){
+ ulong col = 0;
+ int c, s;
+
+ if (x < 16) {
+ c = (cv >> (15 - x)) & 1;
+ s = (sv >> (15 - x)) & 1;
+ } else
+ c = s = 0;
+
+ switch(c | s<<1) {
+ case 0:
+ col = 0;
+ break;
+ case 1:
+ col = ~0ul; /* white */
+ break;
+ case 2:
+ case 3:
+ col = 0xff000000; /* black */
+ break;
+ }
+
+ *p++ = col;
+ }
+ }
+
+ scr->offset.x = curs->offset.x;
+ scr->offset.y = curs->offset.y;
+}
+
+static int
+radeoncurmove(VGAscr *scr, Point p)
+{
+ int x, y, ox, oy;
+ static ulong storage = 0;
+
+ if(scr->mmio == nil)
+ return 1;
+
+ if (storage == 0)
+ storage = scr->apsize - 1*Meg;
+
+ x = p.x + scr->offset.x;
+ y = p.y + scr->offset.y;
+ ox = oy = 0;
+
+ if (x < 0) {
+ ox = -x - 1;
+ x = 0;
+ }
+ if (y < 0) {
+ oy = -y - 1;
+ y = 0;
+ }
+
+ OUTREG((ulong)scr->mmio, CUR_OFFSET, storage + oy * 256);
+ OUTREG((ulong)scr->mmio, CUR_HORZ_VERT_OFF,
+ (ox & 0x7fff) << 16 | (oy & 0x7fff));
+ OUTREG((ulong)scr->mmio, CUR_HORZ_VERT_POSN,
+ (x & 0x7fff) << 16 | (y & 0x7fff));
+ return 0;
+}
+
+static void
+radeoncurdisable(VGAscr *scr)
+{
+ if(scr->mmio == nil)
+ return;
+ OUTREGP((ulong)scr->mmio, CRTC_GEN_CNTL, 0, ~CRTC_CUR_EN);
+}
+
+static void
+radeoncurenable(VGAscr *scr)
+{
+ ulong storage;
+
+ if(scr->mmio == 0)
+ return;
+
+ radeoncurdisable(scr);
+ storage = scr->apsize - 1*Meg;
+ scr->storage = (ulong)KADDR(scr->paddr + storage);
+ radeoncurload(scr, &arrow);
+ radeoncurmove(scr, ZP);
+
+ OUTREGP((ulong)scr->mmio, CRTC_GEN_CNTL, CRTC_CUR_EN | 2<<20,
+ ~(CRTC_CUR_EN | 3<<20));
+}
+
+/* hw blank */
+
+static void
+radeonblank(VGAscr* scr, int blank)
+{
+ ulong mask;
+ char *cp;
+
+ if (scr->mmio == 0)
+ return;
+
+// iprint("radeon: hwblank(%d)\n", blank);
+
+ mask = CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | CRTC_VSYNC_DIS;
+ if (blank == 0) {
+ OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL, 0, ~mask);
+ return;
+ }
+
+ cp = getconf("*dpms");
+ if (cp) {
+ if (strcmp(cp, "standby") == 0)
+ OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL,
+ CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS, ~mask);
+ else if (strcmp(cp, "suspend") == 0)
+ OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL,
+ CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS, ~mask);
+ else if (strcmp(cp, "off") == 0)
+ OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
+ return;
+ }
+
+ OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
+}
+
+/* hw acceleration */
+
+static void
+radeonwaitfifo(VGAscr *scr, int entries)
+{
+ int i;
+
+ for (i = 0; i < 2000000; i++)
+ if (INREG((ulong)scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK >=
+ entries)
+ return;
+ iprint("radeon: fifo timeout\n");
+}
+
+static void
+radeonwaitidle(VGAscr *scr)
+{
+ radeonwaitfifo(scr, 64);
+
+ for (; ; ) {
+ int i;
+
+ for (i = 0; i < 2000000; i++)
+ if (!(INREG((ulong)scr->mmio, RBBM_STATUS) & RBBM_ACTIVE))
+ return;
+
+ iprint("radeon: idle timed out: %uld entries, stat=0x%.8ulx\n",
+ INREG((ulong)scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK,
+ INREG((ulong)scr->mmio, RBBM_STATUS));
+ }
+}
+
+static ulong dp_gui_master_cntl = 0;
+
+static int
+radeonfill(VGAscr *scr, Rectangle r, ulong color)
+{
+ if (scr->mmio == nil)
+ return 0;
+
+ radeonwaitfifo(scr, 6);
+ OUTREG((ulong)scr->mmio, DP_GUI_MASTER_CNTL,
+ dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR |
+ GMC_SRC_DATATYPE_COLOR | ROP3_P);
+ OUTREG((ulong)scr->mmio, DP_BRUSH_FRGD_CLR, color);
+ OUTREG((ulong)scr->mmio, DP_WRITE_MASK, ~0ul);
+ OUTREG((ulong)scr->mmio, DP_CNTL,
+ DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
+ OUTREG((ulong)scr->mmio, DST_Y_X, r.min.y << 16 | r.min.x);
+ OUTREG((ulong)scr->mmio, DST_WIDTH_HEIGHT, Dx(r) << 16 | Dy(r));
+
+ radeonwaitidle(scr);
+ return 1;
+}
+
+static int
+radeonscroll(VGAscr*scr, Rectangle dst, Rectangle src)
+{
+ int xs, ys, xd, yd, w, h;
+ ulong dp_cntl = 0x20;
+
+ if (scr->mmio == nil)
+ return 0;
+
+ // iprint("radeon: hwscroll(dst:%R, src:%R)\n", dst, src);
+
+ xd = dst.min.x;
+ yd = dst.min.y;
+ xs = src.min.x;
+ ys = src.min.y;
+ w = Dx(dst);
+ h = Dy(dst);
+
+ if (ys < yd) {
+ ys += h - 1;
+ yd += h - 1;
+ } else
+ dp_cntl |= DST_Y_TOP_TO_BOTTOM;
+
+ if (xs < xd) {
+ xs += w - 1;
+ xd += w - 1;
+ } else
+ dp_cntl |= DST_X_LEFT_TO_RIGHT;
+
+ radeonwaitfifo(scr, 6);
+ OUTREG((ulong)scr->mmio, DP_GUI_MASTER_CNTL, dp_gui_master_cntl |
+ GMC_BRUSH_NONE | GMC_SRC_DATATYPE_COLOR | DP_SRC_SOURCE_MEMORY |
+ ROP3_S);
+ OUTREG((ulong)scr->mmio, DP_WRITE_MASK, ~0ul);
+ OUTREG((ulong)scr->mmio, DP_CNTL, dp_cntl);
+ OUTREG((ulong)scr->mmio, SRC_Y_X, ys << 16 | xs);
+ OUTREG((ulong)scr->mmio, DST_Y_X, yd << 16 | xd);
+ OUTREG((ulong)scr->mmio, DST_WIDTH_HEIGHT, w << 16 | h);
+
+ radeonwaitidle(scr);
+
+ // iprint("radeon: hwscroll(xs=%d ys=%d xd=%d yd=%d w=%d h=%d)\n",
+ // xs, ys, xd, yd, w, h);
+ return 1;
+}
+
+static void
+radeondrawinit(VGAscr*scr)
+{
+ ulong bpp, dtype, i, pitch, clock_cntl_index, mclk_cntl, rbbm_soft_reset;
+
+ if (scr->mmio == 0)
+ return;
+
+ switch (scr->gscreen->depth) {
+ case 6:
+ case 8:
+ dtype = 2;
+ bpp = 1;
+ break;
+ case 15:
+ dtype = 3;
+ bpp = 2;
+ break;
+ case 16:
+ dtype = 4;
+ bpp = 2;
+ break;
+ case 32:
+ dtype = 6;
+ bpp = 4;
+ break;
+ default:
+ return;
+ }
+
+ /* disable 3D */
+ OUTREG((ulong)scr->mmio, RB3D_CNTL, 0);
+
+ /* flush engine */
+ OUTREGP((ulong)scr->mmio, RB2D_DSTCACHE_CTLSTAT,
+ RB2D_DC_FLUSH_ALL, ~RB2D_DC_FLUSH_ALL);
+ for (i = 0; i < 2000000; i++)
+ if (!(INREG((ulong)scr->mmio, RB2D_DSTCACHE_CTLSTAT) &
+ RB2D_DC_BUSY))
+ break;
+
+ /* reset 2D engine */
+ clock_cntl_index = INREG((ulong)scr->mmio, CLOCK_CNTL_INDEX);
+
+ mclk_cntl = INPLL((ulong)scr->mmio, MCLK_CNTL);
+ OUTPLL((ulong)scr->mmio, MCLK_CNTL, mclk_cntl | FORCEON_MCLKA |
+ FORCEON_MCLKB | FORCEON_YCLKA | FORCEON_YCLKB | FORCEON_MC |
+ FORCEON_AIC);
+ rbbm_soft_reset = INREG((ulong)scr->mmio, RBBM_SOFT_RESET);
+
+ OUTREG((ulong)scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset |
+ SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE |
+ SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB);
+ INREG((ulong)scr->mmio, RBBM_SOFT_RESET);
+ OUTREG((ulong)scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset &
+ ~(SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE |
+ SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB));
+ INREG((ulong)scr->mmio, RBBM_SOFT_RESET);
+
+ OUTPLL((ulong)scr->mmio, MCLK_CNTL, mclk_cntl);
+ OUTREG((ulong)scr->mmio, CLOCK_CNTL_INDEX, clock_cntl_index);
+
+ /* init 2D engine */
+ radeonwaitfifo(scr, 1);
+ OUTREG((ulong)scr->mmio, RB2D_DSTCACHE_MODE, 0);
+
+ pitch = Dx(scr->gscreen->r) * bpp;
+ radeonwaitfifo(scr, 4);
+ OUTREG((ulong)scr->mmio, DEFAULT_PITCH, pitch);
+ OUTREG((ulong)scr->mmio, DST_PITCH, pitch);
+ OUTREG((ulong)scr->mmio, SRC_PITCH, pitch);
+ OUTREG((ulong)scr->mmio, DST_PITCH_OFFSET_C, 0);
+
+ radeonwaitfifo(scr, 3);
+ OUTREG((ulong)scr->mmio, DEFAULT_OFFSET, 0);
+ OUTREG((ulong)scr->mmio, DST_OFFSET, 0);
+ OUTREG((ulong)scr->mmio, SRC_OFFSET, 0);
+
+ radeonwaitfifo(scr, 1);
+ OUTREGP((ulong)scr->mmio, DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
+
+ radeonwaitfifo(scr, 1);
+ OUTREG((ulong)scr->mmio, DEFAULT_SC_BOTTOM_RIGHT,
+ DEFAULT_SC_RIGHT_MAX | DEFAULT_SC_BOTTOM_MAX);
+
+ dp_gui_master_cntl = dtype << GMC_DST_DATATYPE_SHIFT |
+ GMC_SRC_PITCH_OFFSET_CNTL | GMC_DST_PITCH_OFFSET_CNTL |
+ GMC_CLR_CMP_CNTL_DIS;
+ radeonwaitfifo(scr, 1);
+ OUTREG((ulong)scr->mmio, DP_GUI_MASTER_CNTL,
+ dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR | GMC_SRC_DATATYPE_COLOR);
+
+ radeonwaitfifo(scr, 7);
+ OUTREG((ulong)scr->mmio, DST_LINE_START, 0);
+ OUTREG((ulong)scr->mmio, DST_LINE_END, 0);
+ OUTREG((ulong)scr->mmio, DP_BRUSH_FRGD_CLR, ~0ul);
+ OUTREG((ulong)scr->mmio, DP_BRUSH_BKGD_CLR, 0);
+ OUTREG((ulong)scr->mmio, DP_SRC_FRGD_CLR, ~0ul);
+ OUTREG((ulong)scr->mmio, DP_SRC_BKGD_CLR, 0);
+ OUTREG((ulong)scr->mmio, DP_WRITE_MASK, ~0ul);
+
+ radeonwaitidle(scr);
+
+ scr->fill = radeonfill;
+ scr->scroll = radeonscroll;
+ hwaccel = 1;
+
+ scr->blank = radeonblank;
+ hwblank = 1;
+}
+
+/* hw overlay */
+
+static void
+radeonovlctl(VGAscr *scr, Chan *c, void *data, int len)
+{
+ USED(scr, c, data, len);
+}
+
+static int
+radeonovlwrite(VGAscr *scr, void *data, int len, vlong opt)
+{
+ USED(scr, data, len, opt);
+ return -1;
+}
+
+static void
+radeonflush(VGAscr *scr, Rectangle r)
+{
+ USED(scr, r);
+}
+
+/* Export */
+
+VGAdev vgaradeondev = {
+ "radeon",
+
+ radeonenable,
+ 0, /* disable */
+ 0, /* page */
+ radeonlinear,
+
+ radeondrawinit,
+#ifdef HW_ACCEL
+ radeonfill,
+
+ radeonovlctl,
+ radeonovlwrite,
+ radeonflush,
+#endif
+};
+VGAcur vgaradeoncur = {
+ "radeonhwgc",
+ radeoncurenable,
+ radeoncurdisable,
+ radeoncurload,
+ radeoncurmove,
+ 0 /* doespanning */
+};
diff --git a/sys/src/9/pc/vgargb524.c b/sys/src/9/pc/vgargb524.c
new file mode 100755
index 000000000..384901fc4
--- /dev/null
+++ b/sys/src/9/pc/vgargb524.c
@@ -0,0 +1,237 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+/*
+ * IBM RGB524.
+ * 170/220MHz High Performance Palette DAC.
+ *
+ * Assumes hooked up to an S3 Vision96[48].
+ */
+enum {
+ IndexLo = 0x00,
+ IndexHi = 0x01,
+ Data = 0x02,
+ IndexCtl = 0x03,
+};
+
+enum { /* index registers */
+ CursorCtl = 0x30,
+ CursorXLo = 0x31,
+ CursorXHi = 0x32,
+ CursorYLo = 0x33,
+ CursorYHi = 0x34,
+ CursorHotX = 0x35,
+ CursorHotY = 0x36,
+
+ CursorR1 = 0x40,
+ CursorG1 = 0x41,
+ CursorB1 = 0x42,
+ CursorR2 = 0x43,
+ CursorG2 = 0x44,
+ CursorB2 = 0x45,
+ CursorR3 = 0x46,
+ CursorG3 = 0x47,
+ CursorB3 = 0x48,
+
+ CursorArray = 0x100,
+};
+
+/*
+ * Lower 2-bits of indirect DAC register
+ * addressing.
+ */
+static ushort dacxreg[4] = {
+ PaddrW, Pdata, Pixmask, PaddrR
+};
+
+static uchar
+rgb524setrs2(void)
+{
+ uchar rs2;
+
+ rs2 = vgaxi(Crtx, 0x55);
+ vgaxo(Crtx, 0x55, (rs2 & 0xFC)|0x01);
+
+ return rs2;
+}
+
+static void
+rgb524xo(int index, uchar data)
+{
+ vgao(dacxreg[IndexLo], index & 0xFF);
+ vgao(dacxreg[IndexHi], (index>>8) & 0xFF);
+ vgao(dacxreg[Data], data);
+}
+
+static void
+rgb524disable(VGAscr*)
+{
+ uchar rs2;
+
+ rs2 = rgb524setrs2();
+ rgb524xo(CursorCtl, 0x00);
+ vgaxo(Crtx, 0x55, rs2);
+}
+
+static void
+rgb524enable(VGAscr*)
+{
+ uchar rs2;
+
+ rs2 = rgb524setrs2();
+
+ /*
+ * Make sure cursor is off by initialising the cursor
+ * control to defaults.
+ */
+ rgb524xo(CursorCtl, 0x00);
+
+ /*
+ * Cursor colour 1 (white),
+ * cursor colour 2 (black).
+ */
+ rgb524xo(CursorR1, Pwhite); rgb524xo(CursorG1, Pwhite); rgb524xo(CursorB1, Pwhite);
+ rgb524xo(CursorR2, Pblack); rgb524xo(CursorG2, Pblack); rgb524xo(CursorB2, Pblack);
+
+ /*
+ * Enable the cursor, 32x32, mode 2.
+ */
+ rgb524xo(CursorCtl, 0x23);
+
+ vgaxo(Crtx, 0x55, rs2);
+}
+
+static void
+rgb524load(VGAscr*, Cursor* curs)
+{
+ uchar p, p0, p1, rs2;
+ int x, y;
+
+ rs2 = rgb524setrs2();
+
+ /*
+ * Make sure cursor is off by initialising the cursor
+ * control to defaults.
+ */
+ rgb524xo(CursorCtl, 0x00);
+
+ /*
+ * Set auto-increment mode for index-register addressing
+ * and initialise the cursor array index.
+ */
+ vgao(dacxreg[IndexCtl], 0x01);
+ vgao(dacxreg[IndexLo], CursorArray & 0xFF);
+ vgao(dacxreg[IndexHi], (CursorArray>>8) & 0xFF);
+
+ /*
+ * Initialise the 32x32 cursor RAM array. There are 2 planes,
+ * p0 and p1. Data is written 4 pixels per byte, with p1 the
+ * MS bit of each pixel.
+ * The cursor is set in X-Windows mode which gives the following
+ * truth table:
+ * p1 p0 colour
+ * 0 0 underlying pixel colour
+ * 0 1 underlying pixel colour
+ * 1 0 cursor colour 1
+ * 1 1 cursor colour 2
+ * Put the cursor into the top-left of the 32x32 array.
+ */
+ for(y = 0; y < 32; y++){
+ for(x = 0; x < 32/8; x++){
+ if(x < 16/8 && y < 16){
+ p0 = curs->clr[x+y*2];
+ p1 = curs->set[x+y*2];
+
+ p = 0x00;
+ if(p1 & 0x80)
+ p |= 0xC0;
+ else if(p0 & 0x80)
+ p |= 0x80;
+ if(p1 & 0x40)
+ p |= 0x30;
+ else if(p0 & 0x40)
+ p |= 0x20;
+ if(p1 & 0x20)
+ p |= 0x0C;
+ else if(p0 & 0x20)
+ p |= 0x08;
+ if(p1 & 0x10)
+ p |= 0x03;
+ else if(p0 & 0x10)
+ p |= 0x02;
+ vgao(dacxreg[Data], p);
+
+ p = 0x00;
+ if(p1 & 0x08)
+ p |= 0xC0;
+ else if(p0 & 0x08)
+ p |= 0x80;
+ if(p1 & 0x04)
+ p |= 0x30;
+ else if(p0 & 0x04)
+ p |= 0x20;
+ if(p1 & 0x02)
+ p |= 0x0C;
+ else if(p0 & 0x02)
+ p |= 0x08;
+ if(p1 & 0x01)
+ p |= 0x03;
+ else if(p0 & 0x01)
+ p |= 0x02;
+ vgao(dacxreg[Data], p);
+ }
+ else{
+ vgao(dacxreg[Data], 0x00);
+ vgao(dacxreg[Data], 0x00);
+ }
+ }
+ }
+
+ /*
+ * Initialise the cursor hotpoint,
+ * enable the cursor and restore state.
+ */
+ rgb524xo(CursorHotX, -curs->offset.x);
+ rgb524xo(CursorHotY, -curs->offset.y);
+
+ rgb524xo(CursorCtl, 0x23);
+
+ vgaxo(Crtx, 0x55, rs2);
+}
+
+static int
+rgb524move(VGAscr*, Point p)
+{
+ uchar rs2;
+
+ rs2 = rgb524setrs2();
+
+ rgb524xo(CursorXLo, p.x & 0xFF);
+ rgb524xo(CursorXHi, (p.x>>8) & 0x0F);
+ rgb524xo(CursorYLo, p.y & 0xFF);
+ rgb524xo(CursorYHi, (p.y>>8) & 0x0F);
+
+ vgaxo(Crtx, 0x55, rs2);
+
+ return 0;
+}
+
+VGAcur vgargb524cur = {
+ "rgb524hwgc",
+
+ rgb524enable,
+ rgb524disable,
+ rgb524load,
+ rgb524move,
+};
diff --git a/sys/src/9/pc/vgas3.c b/sys/src/9/pc/vgas3.c
new file mode 100755
index 000000000..14dc53840
--- /dev/null
+++ b/sys/src/9/pc/vgas3.c
@@ -0,0 +1,568 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+enum {
+ PCIS3 = 0x5333, /* PCI VID */
+
+ SAVAGE3D = 0x8A20, /* PCI DID */
+ SAVAGE3DMV = 0x8A21,
+ SAVAGE4 = 0x8A22,
+ PROSAVAGEP = 0x8A25,
+ PROSAVAGEK = 0x8A26,
+ PROSAVAGE8 = 0x8D04,
+ SAVAGEMXMV = 0x8C10,
+ SAVAGEMX = 0x8C11,
+ SAVAGEIXMV = 0x8C12,
+ SAVAGEIX = 0x8C13,
+ SUPERSAVAGEIXC16 = 0x8C2E,
+ SAVAGE2000 = 0x9102,
+
+ VIRGE = 0x5631,
+ VIRGEGX2 = 0x8A10,
+ VIRGEDXGX = 0x8A01,
+ VIRGEVX = 0x883D,
+ VIRGEMX = 0x8C01,
+ VIRGEMXP = 0x8C03,
+
+ VIRTUALPC2004 = 0x8810,
+ AURORA64VPLUS = 0x8812,
+};
+
+static int
+s3pageset(VGAscr* scr, int page)
+{
+ uchar crt35, crt51;
+ int opage;
+
+ crt35 = vgaxi(Crtx, 0x35);
+ if(scr->gscreen->depth >= 8){
+ /*
+ * The S3 registers need to be unlocked for this.
+ * Let's hope they are already:
+ * vgaxo(Crtx, 0x38, 0x48);
+ * vgaxo(Crtx, 0x39, 0xA0);
+ *
+ * The page is 6 bits, the lower 4 bits in Crt35<3:0>,
+ * the upper 2 in Crt51<3:2>.
+ */
+ vgaxo(Crtx, 0x35, page & 0x0F);
+ crt51 = vgaxi(Crtx, 0x51);
+ vgaxo(Crtx, 0x51, (crt51 & ~0x0C)|((page & 0x30)>>2));
+ opage = ((crt51 & 0x0C)<<2)|(crt35 & 0x0F);
+ }
+ else{
+ vgaxo(Crtx, 0x35, (page<<2) & 0x0C);
+ opage = (crt35>>2) & 0x03;
+ }
+
+ return opage;
+}
+
+static void
+s3page(VGAscr* scr, int page)
+{
+ int id;
+
+ id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
+ switch(id){
+
+ case VIRGEGX2:
+ break;
+
+ default:
+ lock(&scr->devlock);
+ s3pageset(scr, page);
+ unlock(&scr->devlock);
+ break;
+ }
+}
+
+static void
+s3linear(VGAscr* scr, int, int)
+{
+ int id, j;
+ ulong mmiobase, mmiosize;
+ Pcidev *p;
+
+ vgalinearpciid(scr, PCIS3, 0);
+ p = scr->pci;
+ if(scr->paddr == 0 || p == nil)
+ return;
+
+ addvgaseg("s3screen", scr->paddr, scr->apsize);
+
+ id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
+ switch(id){ /* find mmio */
+ case SAVAGE4:
+ case PROSAVAGEP:
+ case PROSAVAGEK:
+ case PROSAVAGE8:
+ case SUPERSAVAGEIXC16:
+ /*
+ * We could assume that the MMIO registers
+ * will be in the screen segment and just use
+ * that, but PCI software is allowed to move them
+ * if it feels like it, so we look for an aperture of
+ * the right size; only the first 512k actually means
+ * anything. The S3 engineers overestimated how
+ * much space they would need in the first design.
+ */
+ for(j=0; j<nelem(p->mem); j++){
+ if((p->mem[j].bar&~0x0F) != scr->paddr)
+ if(p->mem[j].size==512*1024 || p->mem[j].size==16*1024*1024){
+ mmiobase = p->mem[j].bar & ~0x0F;
+ mmiosize = 512*1024;
+ scr->mmio = vmap(mmiobase, mmiosize);
+ if(scr->mmio == nil)
+ return;
+ addvgaseg("savagemmio", mmiobase, mmiosize);
+ break;
+ }
+ }
+ }
+}
+
+static void
+s3vsyncactive(void)
+{
+ /*
+ * Hardware cursor information is fetched from display memory
+ * during the horizontal blank active time. The 80x chips may hang
+ * if the cursor is turned on or off during this period.
+ */
+ while((vgai(Status1) & 0x08) == 0)
+ ;
+}
+
+static void
+s3disable(VGAscr*)
+{
+ uchar crt45;
+
+ /*
+ * Turn cursor off.
+ */
+ crt45 = vgaxi(Crtx, 0x45) & 0xFE;
+ s3vsyncactive();
+ vgaxo(Crtx, 0x45, crt45);
+}
+
+static void
+s3load(VGAscr* scr, Cursor* curs)
+{
+ uchar *p;
+ int id, dolock, opage, x, y;
+
+ /*
+ * Disable the cursor and
+ * set the pointer to the two planes.
+ */
+ s3disable(scr);
+
+ opage = 0;
+ p = scr->vaddr;
+ id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
+ switch(id){
+
+ case VIRTUALPC2004:
+ case VIRGE:
+ case VIRGEDXGX:
+ case VIRGEGX2:
+ case VIRGEVX:
+ case SAVAGEMXMV:
+ case SAVAGEIXMV:
+ case SAVAGE4:
+ case PROSAVAGEP:
+ case PROSAVAGEK:
+ case PROSAVAGE8:
+ case SUPERSAVAGEIXC16:
+ dolock = 0;
+ p += scr->storage;
+ break;
+
+ default:
+ dolock = 1;
+ lock(&scr->devlock);
+ opage = s3pageset(scr, scr->storage>>16);
+ p += (scr->storage & 0xFFFF);
+ break;
+ }
+
+ /*
+ * The cursor is set in Microsoft Windows format (the ViRGE/GX2 doesn't
+ * support the X11 format) which gives the following truth table:
+ * and xor colour
+ * 0 0 background colour
+ * 0 1 foreground colour
+ * 1 0 current screen pixel
+ * 1 1 NOT current screen pixel
+ * Put the cursor into the top-left of the 64x64 array.
+ *
+ * The cursor pattern in memory is interleaved words of
+ * AND and XOR patterns.
+ */
+ for(y = 0; y < 64; y++){
+ for(x = 0; x < 64/8; x += 2){
+ if(x < 16/8 && y < 16){
+ *p++ = ~(curs->clr[2*y + x]|curs->set[2*y + x]);
+ *p++ = ~(curs->clr[2*y + x+1]|curs->set[2*y + x+1]);
+ *p++ = curs->set[2*y + x];
+ *p++ = curs->set[2*y + x+1];
+ }
+ else {
+ *p++ = 0xFF;
+ *p++ = 0xFF;
+ *p++ = 0x00;
+ *p++ = 0x00;
+ }
+ }
+ }
+
+ if(dolock){
+ s3pageset(scr, opage);
+ unlock(&scr->devlock);
+ }
+
+ /*
+ * Save the cursor hotpoint and enable the cursor.
+ */
+ scr->offset = curs->offset;
+ s3vsyncactive();
+ vgaxo(Crtx, 0x45, 0x01);
+}
+
+static int
+s3move(VGAscr* scr, Point p)
+{
+ int x, xo, y, yo;
+
+ /*
+ * Mustn't position the cursor offscreen even partially,
+ * or it disappears. Therefore, if x or y is -ve, adjust the
+ * cursor offset instead.
+ * There seems to be a bug in that if the offset is 1, the
+ * cursor doesn't disappear off the left edge properly, so
+ * round it up to be even.
+ */
+ if((x = p.x+scr->offset.x) < 0){
+ xo = -x;
+ xo = ((xo+1)/2)*2;
+ x = 0;
+ }
+ else
+ xo = 0;
+ if((y = p.y+scr->offset.y) < 0){
+ yo = -y;
+ y = 0;
+ }
+ else
+ yo = 0;
+
+ vgaxo(Crtx, 0x46, (x>>8) & 0x07);
+ vgaxo(Crtx, 0x47, x & 0xFF);
+ vgaxo(Crtx, 0x49, y & 0xFF);
+ vgaxo(Crtx, 0x4E, xo);
+ vgaxo(Crtx, 0x4F, yo);
+ vgaxo(Crtx, 0x48, (y>>8) & 0x07);
+
+ return 0;
+}
+
+static void
+s3enable(VGAscr* scr)
+{
+ int i;
+ ulong storage;
+
+ s3disable(scr);
+
+ /*
+ * Cursor colours. Set both the CR0[EF] and the colour
+ * stack in case we are using a 16-bit RAMDAC.
+ */
+ vgaxo(Crtx, 0x0E, Pwhite);
+ vgaxo(Crtx, 0x0F, Pblack);
+ vgaxi(Crtx, 0x45);
+
+ for(i = 0; i < 3; i++)
+ vgaxo(Crtx, 0x4A, Pblack);
+ vgaxi(Crtx, 0x45);
+ for(i = 0; i < 3; i++)
+ vgaxo(Crtx, 0x4B, Pwhite);
+
+ /*
+ * Find a place for the cursor data in display memory.
+ * Must be on a 1024-byte boundary.
+ */
+ storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024;
+ vgaxo(Crtx, 0x4C, storage>>8);
+ vgaxo(Crtx, 0x4D, storage & 0xFF);
+ storage *= 1024;
+ scr->storage = storage;
+
+ /*
+ * Load, locate and enable the cursor
+ * in Microsoft Windows format.
+ */
+ s3load(scr, &arrow);
+ s3move(scr, ZP);
+ vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55) & ~0x10);
+ s3vsyncactive();
+ vgaxo(Crtx, 0x45, 0x01);
+}
+
+/*
+ * The manual gives byte offsets, but we want ulong offsets, hence /4.
+ */
+enum {
+ SrcBase = 0xA4D4/4,
+ DstBase = 0xA4D8/4,
+ Stride = 0xA4E4/4,
+ FgrdData = 0xA4F4/4,
+ WidthHeight = 0xA504/4,
+ SrcXY = 0xA508/4,
+ DestXY = 0xA50C/4,
+ Command = 0xA500/4,
+ SubStat = 0x8504/4,
+ FifoStat = 0x850C/4,
+};
+
+/*
+ * Wait for writes to VGA memory via linear aperture to flush.
+ */
+enum {Maxloop = 1<<24};
+struct {
+ ulong linear;
+ ulong fifo;
+ ulong idle;
+ ulong lineartimeout;
+ ulong fifotimeout;
+ ulong idletimeout;
+} waitcount;
+
+static void
+waitforlinearfifo(VGAscr *scr)
+{
+ ulong *mmio;
+ long x;
+ static ulong nwaitforlinearfifo;
+ ulong mask, val;
+
+ switch(scr->id){
+ default:
+ panic("unknown scr->id in s3 waitforlinearfifo");
+ case 0x8A01: /* ViRGE/[DG]X. XFree86 says no waiting necessary */
+ return;
+ case 0x5631: /* ViRGE */
+ case 0x883D: /* ViRGE/VX */
+ mask = 0x0F<<6;
+ val = 0x08<<6;
+ break;
+ case 0x8A10: /* ViRGE/GX2 */
+ mask = 0x1F<<6;
+ val = 0x10<<6;
+ break;
+ }
+ mmio = scr->mmio;
+ x = 0;
+ while((mmio[FifoStat]&mask) != val && x++ < Maxloop)
+ waitcount.linear++;
+ if(x >= Maxloop)
+ waitcount.lineartimeout++;
+}
+
+static void
+waitforfifo(VGAscr *scr, int entries)
+{
+ ulong *mmio;
+ long x;
+ static ulong nwaitforfifo;
+
+ mmio = scr->mmio;
+ x = 0;
+ while((mmio[SubStat]&0x1F00) < ((entries+2)<<8) && x++ < Maxloop)
+ waitcount.fifo++;
+ if(x >= Maxloop)
+ waitcount.fifotimeout++;
+}
+
+static void
+waitforidle(VGAscr *scr)
+{
+ ulong *mmio;
+ long x;
+
+ mmio = scr->mmio;
+ x = 0;
+ while((mmio[SubStat]&0x3F00) != 0x3000 && x++ < Maxloop)
+ waitcount.idle++;
+ if(x >= Maxloop)
+ waitcount.idletimeout++;
+}
+
+static int
+hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
+{
+ enum { Bitbltop = 0xCC }; /* copy source */
+ ulong *mmio;
+ ulong cmd, stride;
+ Point dp, sp;
+ int did, d;
+
+ d = scr->gscreen->depth;
+ did = (d-8)/8;
+ cmd = 0x00000020|(Bitbltop<<17)|(did<<2);
+ stride = Dx(scr->gscreen->r)*d/8;
+
+ if(r.min.x <= sr.min.x){
+ cmd |= 1<<25;
+ dp.x = r.min.x;
+ sp.x = sr.min.x;
+ }else{
+ dp.x = r.max.x-1;
+ sp.x = sr.max.x-1;
+ }
+
+ if(r.min.y <= sr.min.y){
+ cmd |= 1<<26;
+ dp.y = r.min.y;
+ sp.y = sr.min.y;
+ }else{
+ dp.y = r.max.y-1;
+ sp.y = sr.max.y-1;
+ }
+
+ mmio = scr->mmio;
+ waitforlinearfifo(scr);
+ waitforfifo(scr, 7);
+ mmio[SrcBase] = scr->paddr;
+ mmio[DstBase] = scr->paddr;
+ mmio[Stride] = (stride<<16)|stride;
+ mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
+ mmio[SrcXY] = (sp.x<<16)|sp.y;
+ mmio[DestXY] = (dp.x<<16)|dp.y;
+ mmio[Command] = cmd;
+ waitforidle(scr);
+ return 1;
+}
+
+static int
+hwfill(VGAscr *scr, Rectangle r, ulong sval)
+{
+ enum { Bitbltop = 0xCC }; /* copy source */
+ ulong *mmio;
+ ulong cmd, stride;
+ int did, d;
+
+ d = scr->gscreen->depth;
+ did = (d-8)/8;
+ cmd = 0x16000120|(Bitbltop<<17)|(did<<2);
+ stride = Dx(scr->gscreen->r)*d/8;
+ mmio = scr->mmio;
+ waitforlinearfifo(scr);
+ waitforfifo(scr, 8);
+ mmio[SrcBase] = scr->paddr;
+ mmio[DstBase] = scr->paddr;
+ mmio[DstBase] = scr->paddr;
+ mmio[Stride] = (stride<<16)|stride;
+ mmio[FgrdData] = sval;
+ mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
+ mmio[DestXY] = (r.min.x<<16)|r.min.y;
+ mmio[Command] = cmd;
+ waitforidle(scr);
+ return 1;
+}
+
+enum {
+ CursorSyncCtl = 0x0D, /* in Seqx */
+ VsyncHi = 0x80,
+ VsyncLo = 0x40,
+ HsyncHi = 0x20,
+ HsyncLo = 0x10,
+};
+
+static void
+s3blank(VGAscr*, int blank)
+{
+ uchar x;
+
+ x = vgaxi(Seqx, CursorSyncCtl);
+ x &= ~0xF0;
+ if(blank)
+ x |= VsyncLo | HsyncLo;
+ vgaxo(Seqx, CursorSyncCtl, x);
+}
+
+static void
+s3drawinit(VGAscr *scr)
+{
+ extern void savageinit(VGAscr*); /* vgasavage.c */
+ ulong id;
+
+ id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
+ scr->id = id;
+
+ /*
+ * It's highly likely that other ViRGEs will work without
+ * change to the driver, with the exception of the size of
+ * the linear aperture memory write FIFO. Since we don't
+ * know that size, I'm not turning them on. See waitforlinearfifo
+ * above.
+ */
+ scr->blank = s3blank;
+ /* hwblank = 1; not known to work well */
+
+ switch(id){
+ case VIRGE:
+ case VIRGEVX:
+ case VIRGEGX2:
+ scr->mmio = (ulong*)((char*)scr->vaddr+0x1000000);
+ scr->fill = hwfill;
+ scr->scroll = hwscroll;
+ break;
+ case SAVAGEMXMV:
+ case SAVAGEIXMV:
+ scr->mmio = (ulong*)((char*)scr->vaddr+0x1000000);
+ savageinit(scr);
+ break;
+ case SUPERSAVAGEIXC16:
+ case SAVAGE4:
+ case PROSAVAGEP:
+ case PROSAVAGE8:
+ case PROSAVAGEK:
+ /* scr->mmio is set by s3linear */
+ savageinit(scr);
+ break;
+ }
+}
+
+VGAdev vgas3dev = {
+ "s3",
+
+ 0,
+ 0,
+ s3page,
+ s3linear,
+ s3drawinit,
+};
+
+VGAcur vgas3cur = {
+ "s3hwgc",
+
+ s3enable,
+ s3disable,
+ s3load,
+ s3move,
+};
+
diff --git a/sys/src/9/pc/vgasavage.c b/sys/src/9/pc/vgasavage.c
new file mode 100755
index 000000000..263b688b0
--- /dev/null
+++ b/sys/src/9/pc/vgasavage.c
@@ -0,0 +1,571 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+enum {
+ PCIS3 = 0x5333, /* PCI VID */
+
+ SAVAGE3D = 0x8A20, /* PCI DID */
+ SAVAGE3DMV = 0x8A21,
+ SAVAGE4 = 0x8A22,
+ PROSAVAGEP = 0x8A25,
+ PROSAVAGEK = 0x8A26,
+ PROSAVAGE8 = 0x8D04,
+ SAVAGEMXMV = 0x8C10,
+ SAVAGEMX = 0x8C11,
+ SAVAGEIXMV = 0x8C12,
+ SAVAGEIX = 0x8C13,
+ SUPERSAVAGEIXC16 = 0x8C2E,
+ SAVAGE2000 = 0x9102,
+
+ VIRGE = 0x5631,
+ VIRGEGX2 = 0x8A10,
+ VIRGEDXGX = 0x8A01,
+ VIRGEVX = 0x883D,
+ VIRGEMX = 0x8C01,
+ VIRGEMXP = 0x8C03,
+
+ AURORA64VPLUS = 0x8812,
+};
+
+/*
+ * Savage4 et al. acceleration.
+ *
+ * This is based only on the Savage4 documentation.
+ * It is expected to work on other Savage cards as well,
+ * but has not been tried.
+ *
+ * There are five ways to access the 2D graphics engine registers:
+ * - Old MMIO non-packed format
+ * - Old MMIO packed format
+ * - New MMIO non-packed format
+ * - New MMIO packed format
+ * - Burst Command Interface (BCI)
+ *
+ * Of these, the manual hints that the first three are deprecated,
+ * and it does not document any of those three well enough to use.
+ *
+ * I have tried for many hours with no success to understand the BCI
+ * interface well enough to use it. It is not well documented, and the
+ * XFree86 driver seems to completely contradict what little documentation
+ * there is.
+ *
+ * This leaves the packed new MMIO.
+ * The manual contradicts itself here, claming that the registers
+ * start at 0x2008100 as well as at 0x0008100 from the base of the
+ * mmio segment. Since the segment is only 512k, we assume that
+ * the latter is the correct offset.
+ *
+ * According to the manual, only 16-bit reads of the 2D registers
+ * are supported: 32-bit reads will return garbage in the upper word.
+ * 32-bit writes must be enabled explicitly.
+ *
+ * 32-bit reads of the status registers seem just fine.
+ */
+
+/* 2D graphics engine registers for Savage4; others appear to be mostly the same */
+enum {
+ SubsystemStatus = 0x8504, /* Subsystem Status: read only */
+ /* read only: whether we get interrupts on various events */
+ VsyncInt = 1<<0, /* vertical sync */
+ GeBusyInt = 1<<1, /* 2D graphics engine busy */
+ BfifoFullInt = 1<<2, /* BIU FIFO full */
+ BfifoEmptyInt = 1<<3, /* BIU FIFO empty */
+ CfifoFullInt = 1<<4, /* command FIFO full */
+ CfifoEmptyInt = 1<<5, /* command FIFO empty */
+ BciInt = 1<<6, /* BCI */
+ LpbInt = 1<<7, /* LPB */
+ CbHiInt = 1<<16, /* COB upper threshold */
+ CbLoInt = 1<<17, /* COB lower threshold */
+
+ SubsystemCtl = 0x8504, /* Subsystem Control: write only */
+ /* clear interrupts for various events */
+ VsyncClr = 1<<0,
+ GeBusyClr = 1<<1,
+ BfifoFullClr = 1<<2,
+ BfifoEmptyClr = 1<<3,
+ CfifoFullClr = 1<<4,
+ CfifoEmptyClr = 1<<5,
+ BciClr = 1<<6,
+ LpbClr = 1<<7,
+ CbHiClr = 1<<16,
+ CbLoClr = 1<<17,
+
+ /* enable interrupts for various events */
+ VsyncEna = 1<<8,
+ Busy2DEna = 1<<9,
+ BfifoFullEna = 1<<10,
+ BfifoEmptyEna = 1<<11,
+ CfifoFullEna = 1<<12,
+ CfifoEmptyEna = 1<<13,
+ SubsysBciEna = 1<<14,
+ CbHiEna = 1<<24,
+ CbLoEna = 1<<25,
+
+ /* 2D graphics engine software reset */
+ GeSoftReset = 1<<15,
+
+ FifoStatus = 0x8508, /* FIFO status: read only */
+ CwbEmpty = 1<<0, /* command write buffer empty */
+ CrbEmpty = 1<<1, /* command read buffer empty */
+ CobEmpty = 1<<2, /* command overflow buffer empty */
+ CfifoEmpty = 1<<3, /* command FIFO empty */
+ CwbFull = 1<<8, /* command write buffer full */
+ CrbFull = 1<<9, /* command read buffer full */
+ CobFull = 1<<10, /* command overflow buffer full */
+ CfifoFull = 1<<11, /* command FIFO full */
+
+ AdvFunCtl = 0x850C, /* Advanced Function Control: read/write */
+ GeEna = 1<<0, /* enable 2D/3D engine */
+ /*
+ * according to the manual, BigPixel should be
+ * set when bpp >= 8 (bpp != 4), and then CR50_5-4 are
+ * used to figure out bpp example. however, it does bad things
+ * to the screen in 8bpp mode.
+ */
+ BigPixel = 1<<2, /* 8 or more bpp enhanced mode */
+ LaEna = 1<<3, /* linear addressing ena: or'ed with CR58_4 */
+ Mclk_2 = 0<<8, /* 2D engine clock divide: MCLK/2 */
+ Mclk_4 = 1<<8, /* " MCLK/4 */
+ Mclk = 2<<8, /* " MCLK */
+ /* Mclk = 3<<8, /* " MCLK */
+ Ic33mhz = 1<<16, /* Internal clock 33 MHz (instead of 66) */
+
+ WakeupReg = 0x8510, /* Wakeup: read/write */
+ WakeupBit = 1<<0, /* wake up: or'ed with 3C3_0 */
+
+ SourceY = 0x8100, /* UL corner of bitblt source */
+ SourceX = 0x8102, /* " */
+ RectY = 0x8100, /* UL corner of rectangle fill */
+ RectX = 0x8102, /* " */
+ DestY = 0x8108, /* UL corner of bitblt dest */
+ DestX = 0x810A, /* " */
+ Height = 0x8148, /* bitblt, image xfer rectangle height */
+ Width = 0x814A, /* bitblt, image xfer rectangle width */
+
+ StartY = 0x8100, /* Line draw: first point*/
+ StartX = 0x8102, /* " */
+ /*
+ * For line draws, the following must be programmed:
+ * axial step constant = 2*min(|dx|,|dy|)
+ * diagonal step constant = 2*[min(|dx|,|dy|) - max(|dx|,|dy|)]
+ * error term = 2*min(|dx|,|dy|) - max(|dx|,|dy| - 1
+ * [sic] when start X < end X
+ * error term = 2*min(|dx|,|dy|) - max(|dx|,|dy|
+ * [sic] when start X >= end X
+ */
+ AxialStep = 0x8108,
+ DiagonalStep = 0x810A,
+ LineError = 0x8110,
+ MinorLength = 0x8148, /* pixel count along minor axis */
+ MajorLength = 0x814A, /* pixel count along major axis */
+
+ DrawCmd = 0x8118, /* Drawing Command: write only */
+ CmdMagic = 0<<1,
+ AcrossPlane = 1<<1, /* across the plane mode */
+ LastPixelOff = 1<<2, /* last pixel of line or vector draw not drawn */
+ Radial = 1<<3, /* enable radial direction (else axial) */
+ DoDraw = 1<<4, /* draw pixels (else only move current pos) */
+
+ DrawRight = 1<<5, /* axial drawing direction: left to right */
+ /* DrawLeft = 0<<5, */
+ MajorY = 1<<6,
+ /* MajorX = 0<<6, */
+ DrawDown = 1<<7,
+ /* DrawUp = 0<<7, */
+ Degree0 = 0<<5, /* drawing direction when Radial */
+ Degree45 = 1<<5,
+ /* ... */
+ Degree315 = 7<<5,
+
+ UseCPUData = 1<<8,
+
+ /* image write bus transfer width */
+ Bus8 = 0<<9,
+ Bus16 = 1<<9,
+ /*
+ * in Bus32 mode, doubleword bits beyond the image rect width are
+ * discarded. each line starts on a new doubleword.
+ * Bus32AP is intended for across-the-plane mode and
+ * rounds to byte boundaries instead.
+ */
+ Bus32 = 2<<9,
+ Bus32AP = 3<<9,
+
+ CmdNop = 0<<13, /* nop */
+ CmdLine = 1<<13, /* draw line */
+ CmdFill = 2<<13, /* fill rectangle */
+ CmdBitblt = 6<<13, /* bitblt */
+ CmdPatblt = 7<<13, /* 8x8 pattern blt */
+
+ SrcGBD = 0<<16,
+ SrcPBD = 1<<16,
+ SrcSBD = 2<<16,
+
+ DstGBD = 0<<18,
+ DstPBD = 1<<18,
+ DstSBD = 2<<18,
+
+ /* color sources, controls */
+ BgColor = 0x8120, /* Background Color: read/write */
+ FgColor = 0x8124, /* Foreground Color: read/write */
+ BitplaneWmask = 0x8128, /* Bitplane Write Mask: read/write */
+ BitplaneRmask = 0x812C, /* Bitplane Read Mask: read/write */
+ CmpColor = 0x8130, /* Color Compare: read/write */
+ BgMix = 0x8134,
+ FgMix = 0x8136,
+ MixNew = 7,
+ SrcBg = 0<<5,
+ SrcFg = 1<<5,
+ SrcCPU = 2<<5,
+ SrcDisp = 3<<5,
+
+ /* clipping rectangle */
+ TopScissors = 0x8138, /* Top Scissors: write only */
+ LeftScissors = 0x813A, /* Left Scissors: write only */
+ BottomScissors = 0x813C, /* Bottom Scissors: write only */
+ RightScissors = 0x813E, /* Right Scissors: write only */
+
+ /*
+ * Registers with Magic were indirectly accessed in older modes.
+ * It is not clear whether the Magic is necessary.
+ * In the older modes, writes to these registers were pipelined,
+ * so that you had to issue an engine command and wait for engine
+ * idle before reading a write back. It is not clear if this is
+ * still the case either.
+ */
+ PixCtl = 0x8140, /* Pixel Control: write only */
+ PixMagic = 0xA<<12,
+ PixMixFg = 0<<6, /* foreground mix register always */
+ PixMixCPU = 2<<6, /* CPU data determines mix register */
+ PixMixDisp = 3<<6, /* display data determines mix register */
+
+ MfMisc2Ctl = 0x8142, /* Multifunction Control Misc. 2: write only */
+ MfMisc2Magic = 0xD<<12,
+ DstShift = 0, /* 3 bits: destination base address in MB */
+ SrcShift = 4, /* 3 bits: source base address in MB */
+ WaitFifoEmpty = 2<<8, /* wait for write FIFO empty between draws */
+
+ MfMiscCtl = 0x8144, /* Multifunction Control Misc: write only */
+ MfMiscMagic = 0xE<<12,
+ UseHighBits = 1<<4, /* select upper 16 bits for 32-bit reg access */
+ ClipInvert = 1<<5, /* only touch pixels outside clip rectangle */
+ SkipSame = 0<<6, /* ignore pixels with color CmpColor */
+ SkipDifferent = 1<<7, /* ignore pixels not color CmpColor */
+ CmpEna = 1<<8, /* enable color compare */
+ W32Ena = 1<<9, /* enable 32-bit register write */
+ ClipDis = 1<<11, /* disable clipping */
+
+ /*
+ * The bitmap descriptor 1 registers contain the starting
+ * address of the bitmap (in bytes).
+ * The bitmap descriptor 2 registesr contain stride (in pixels)
+ * in the lower 16 bits, depth (in bits) in the next 8 bits,
+ * and whether block write is disabled.
+ */
+ GBD1 = 0x8168, /* Global Bitmap Descriptor 1: read/write */
+ GBD2 = 0x816C, /* Global Bitmap Descriptor 2: read/write */
+ /* GBD2-only bits */
+ BDS64 = 1<<0, /* bitmap descriptor size 64 bits */
+ GBDBciEna = 1<<3, /* BCI enable */
+ /* generic BD2 bits */
+ BlockWriteDis = 1<<28,
+ StrideShift = 0,
+ DepthShift = 16,
+
+ PBD1 = 0x8170, /* Primary Bitmap Descriptor: read/write */
+ PBD2 = 0x8174,
+ SBD1 = 0x8178, /* Secondary Bitmap Descriptor: read/write */
+ SBD2 = 0x817C,
+};
+
+/* mastered data transfer registers */
+
+/* configuration/status registers */
+enum {
+ XStatus0 = 0x48C00, /* Status Word 0: read only */
+ /* rev. A silicon differs from rev. B; use AltStatus0 */
+ CBEMaskA = 0x1FFFF, /* filled command buffer entries */
+ CBEShiftA = 0,
+ BciIdleA = 1<<17, /* BCI idle */
+ Ge3IdleA = 1<<18, /* 3D engine idle */
+ Ge2IdleA = 1<<19, /* 2D engine idle */
+ McpIdleA = 1<<20, /* motion compensation processor idle */
+ MeIdleA = 1<<22, /* master engine idle */
+ PfPendA = 1<<23, /* page flip pending */
+
+ CBEMaskB = 0x1FFFFF,
+ CBEShiftB = 0,
+ BciIdleB = 1<<25,
+ Ge3IdleB = 1<<26,
+ Ge2IdleB = 1<<27,
+ McpIdleB = 1<<28,
+ MeIdleB = 1<<30,
+ PfPendB = 1<<31,
+
+ AltStatus0 = 0x48C60, /* Alternate Status Word 0: read only */
+ CBEMask = 0x1FFFF,
+ CBEShift = 0,
+ /* the Savage4 manual says bits 17..23 for these, like Status0 */
+ /* empirically, they are bits 21..26 */
+ BciIdle = 1<<21,
+ Ge3Idle = 1<<22,
+ Ge2Idle = 1<<23,
+ McpIdle = 1<<24,
+ MeIdle = 1<<25,
+ PfPend = 1<<26,
+
+ XStatus1 = 0x48C04, /* Status Word 1: read only */
+ /* contains event tag 1, event tag 0, both 16 bits */
+
+ XStatus2 = 0x48C08, /* Status Word 2: read only */
+ ScanMask = 0x3FF, /* current scan line */
+ ScanShift = 0,
+ VRTMask = 0x7F100, /* vert retrace count */
+ VRTShift = 11,
+
+ CbThresh = 0x48C10, /* Command Buffer Thresholds: read/write */
+ CobOff = 0x48C14, /* Command Overflow Buffer: read/write */
+
+ CobPtr = 0x48C18, /* Command Overflow Buffer Pointers: read/write */
+ CobEna = 1<<2, /* command overflow buffer enable */
+ CobBciEna = 1<<3, /* BCI function enable */
+ CbeMask = 0xFFFF8000, /* no. of entries in command buffer */
+ CbeShift = 15,
+
+ AltStatus1 = 0x48C64, /* Alternate Status Word 1: read onnly */
+ /* contains current texture surface tag, vertex buffer tag */
+
+};
+
+struct {
+ ulong idletimeout;
+ ulong tostatw[16];
+} savagestats;
+
+enum {
+ Maxloop = 1<<20
+};
+
+static void
+savagewaitidle(VGAscr *scr)
+{
+ long x;
+ ulong *statw, mask, goal;
+
+ switch(scr->id){
+ case SAVAGE4:
+ case PROSAVAGEP:
+ case PROSAVAGEK:
+ case PROSAVAGE8:
+ /* wait for engine idle and FIFO empty */
+ statw = (ulong*)((uchar*)scr->mmio+AltStatus0);
+ mask = CBEMask | Ge2Idle;
+ goal = Ge2Idle;
+ break;
+ /* case SAVAGEMXMV: ? */
+ /* case SAVAGEMX: ? */
+ /* case SAVAGEIX: ? */
+ case SUPERSAVAGEIXC16:
+ case SAVAGEIXMV:
+ case SAVAGEMXMV:
+ /* wait for engine idle and FIFO empty */
+ statw = (ulong*)((uchar*)scr->mmio+XStatus0);
+ mask = CBEMaskA | Ge2IdleA;
+ goal = Ge2IdleA;
+ break;
+ default:
+ /*
+ * best we can do: can't print or we'll call ourselves.
+ * savageinit is supposed to not let this happen.
+ */
+ return;
+ }
+
+ for(x=0; x<Maxloop; x++)
+ if((*statw & mask) == goal)
+ return;
+
+ savagestats.tostatw[savagestats.idletimeout++&15] = *statw;
+ savagestats.tostatw[savagestats.idletimeout++&15] = (ulong)statw;
+}
+
+static int
+savagefill(VGAscr *scr, Rectangle r, ulong sval)
+{
+ uchar *mmio;
+
+ mmio = (uchar*)scr->mmio;
+
+ *(ulong*)(mmio+FgColor) = sval;
+ *(ulong*)(mmio+BgColor) = sval;
+ *(ulong*)(mmio+BgMix) = SrcFg|MixNew;
+ *(ulong*)(mmio+FgMix) = SrcFg|MixNew;
+ *(ushort*)(mmio+RectY) = r.min.y;
+ *(ushort*)(mmio+RectX) = r.min.x;
+ *(ushort*)(mmio+Width) = Dx(r)-1;
+ *(ushort*)(mmio+Height) = Dy(r)-1;
+ *(ulong*)(mmio+DrawCmd) = CmdMagic | DoDraw | CmdFill | DrawRight | DrawDown;
+ savagewaitidle(scr);
+ return 1;
+}
+
+static int
+savagescroll(VGAscr *scr, Rectangle r, Rectangle sr)
+{
+ uchar *mmio;
+ ulong cmd;
+ Point dp, sp;
+
+ cmd = CmdMagic | DoDraw | CmdBitblt | SrcPBD | DstGBD;
+
+ if(r.min.x <= sr.min.x){
+ cmd |= DrawRight;
+ dp.x = r.min.x;
+ sp.x = sr.min.x;
+ }else{
+ dp.x = r.max.x-1;
+ sp.x = sr.max.x-1;
+ }
+
+ if(r.min.y <= sr.min.y){
+ cmd |= DrawDown;
+ dp.y = r.min.y;
+ sp.y = sr.min.y;
+ }else{
+ dp.y = r.max.y-1;
+ sp.y = sr.max.y-1;
+ }
+
+ mmio = (uchar*)scr->mmio;
+
+ *(ushort*)(mmio+SourceX) = sp.x;
+ *(ushort*)(mmio+SourceY) = sp.y;
+ *(ushort*)(mmio+DestX) = dp.x;
+ *(ushort*)(mmio+DestY) = dp.y;
+ *(ushort*)(mmio+Width) = Dx(r)-1;
+ *(ushort*)(mmio+Height) = Dy(r)-1;
+ *(ulong*)(mmio+BgMix) = SrcDisp|MixNew;
+ *(ulong*)(mmio+FgMix) = SrcDisp|MixNew;
+ *(ulong*)(mmio+DrawCmd) = cmd;
+ savagewaitidle(scr);
+ return 1;
+}
+
+static void
+savageblank(VGAscr*, int blank)
+{
+ uchar seqD;
+
+ /*
+ * Will handle DPMS to monitor
+ */
+ vgaxo(Seqx, 8, vgaxi(Seqx,8)|0x06);
+ seqD = vgaxi(Seqx, 0xD);
+ seqD &= 0x03;
+ if(blank)
+ seqD |= 0x50;
+ vgaxo(Seqx, 0xD, seqD);
+
+ /*
+ * Will handle LCD
+ */
+ if(blank)
+ vgaxo(Seqx, 0x31, vgaxi(Seqx, 0x31) & ~0x10);
+ else
+ vgaxo(Seqx, 0x31, vgaxi(Seqx, 0x31) | 0x10);
+}
+
+
+void
+savageinit(VGAscr *scr)
+{
+ uchar *mmio;
+ ulong bd;
+
+ /* if you add chip IDs here be sure to update savagewaitidle */
+ switch(scr->id){
+ case SAVAGE4:
+ case PROSAVAGEP:
+ case PROSAVAGEK:
+ case PROSAVAGE8:
+ case SAVAGEIXMV:
+ case SUPERSAVAGEIXC16:
+ case SAVAGEMXMV:
+ break;
+ default:
+ print("unknown savage %.4lux\n", scr->id);
+ return;
+ }
+
+ mmio = (uchar*)scr->mmio;
+ if(mmio == nil) {
+ print("savageinit: no mmio\n");
+ return;
+ }
+
+ /* 2D graphics engine software reset */
+ *(ushort*)(mmio+SubsystemCtl) = GeSoftReset;
+ delay(2);
+ *(ushort*)(mmio+SubsystemCtl) = 0;
+ savagewaitidle(scr);
+
+ /* disable BCI as much as possible */
+ *(ushort*)(mmio+CobPtr) &= ~CobBciEna;
+ *(ushort*)(mmio+GBD2) &= ~GBDBciEna;
+ savagewaitidle(scr);
+
+ /* enable 32-bit writes, disable clipping */
+ *(ushort*)(mmio+MfMiscCtl) = MfMiscMagic|W32Ena|ClipDis;
+ savagewaitidle(scr);
+
+ /* enable all read, write planes */
+ *(ulong*)(mmio+BitplaneRmask) = ~0;
+ *(ulong*)(mmio+BitplaneWmask) = ~0;
+ savagewaitidle(scr);
+
+ /* turn on linear access, 2D engine */
+ *(ulong*)(mmio+AdvFunCtl) |= GeEna|LaEna;
+ savagewaitidle(scr);
+
+ /* set bitmap descriptors */
+ bd = (scr->gscreen->depth<<DepthShift) |
+ (Dx(scr->gscreen->r)<<StrideShift) | BlockWriteDis
+ | BDS64;
+
+ *(ulong*)(mmio+GBD1) = 0;
+ *(ulong*)(mmio+GBD2) = bd;
+
+ *(ulong*)(mmio+PBD1) = 0;
+ *(ulong*)(mmio+PBD2) = bd;
+
+ *(ulong*)(mmio+SBD1) = 0;
+ *(ulong*)(mmio+SBD2) = bd;
+
+ /*
+ * For some reason, the GBD needs to get programmed twice,
+ * once before the PBD, SBD, and once after.
+ * This empirically makes it get set right.
+ * I would like to better understand the ugliness
+ * going on here.
+ */
+ *(ulong*)(mmio+GBD1) = 0;
+ *(ulong*)(mmio+GBD2) = bd;
+ *(ushort*)(mmio+GBD2+2) = bd>>16;
+ savagewaitidle(scr);
+
+ scr->fill = savagefill;
+ scr->scroll = savagescroll;
+ scr->blank = savageblank;
+ hwblank = 0;
+}
diff --git a/sys/src/9/pc/vgat2r4.c b/sys/src/9/pc/vgat2r4.c
new file mode 100755
index 000000000..e106fa3f2
--- /dev/null
+++ b/sys/src/9/pc/vgat2r4.c
@@ -0,0 +1,531 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+/*
+ * #9 Ticket to Ride IV.
+ */
+enum {
+ IndexLo = 0x10/4,
+ IndexHi = 0x14/4,
+ Data = 0x18/4,
+ IndexCtl = 0x1C/4,
+
+ Zoom = 0x54/4,
+};
+
+enum { /* index registers */
+ CursorSyncCtl = 0x03,
+ HsyncHi = 0x01,
+ HsyncLo = 0x02,
+ VsyncHi = 0x04,
+ VsyncLo = 0x08,
+
+ CursorCtl = 0x30,
+ CursorXLo = 0x31,
+ CursorXHi = 0x32,
+ CursorYLo = 0x33,
+ CursorYHi = 0x34,
+ CursorHotX = 0x35,
+ CursorHotY = 0x36,
+
+ CursorR1 = 0x40,
+ CursorG1 = 0x41,
+ CursorB1 = 0x42,
+ CursorR2 = 0x43,
+ CursorG2 = 0x44,
+ CursorB2 = 0x45,
+ CursorR3 = 0x46,
+ CursorG3 = 0x47,
+ CursorB3 = 0x48,
+
+ CursorArray = 0x100,
+
+ CursorMode32x32 = 0x23,
+ CursorMode64x64 = 0x27,
+ CursorMode = CursorMode32x32,
+};
+
+static void
+t2r4enable(VGAscr* scr)
+{
+ Pcidev *p;
+ void *mmio;
+
+ if(scr->mmio)
+ return;
+ if(p = pcimatch(nil, 0x105D, 0)){
+ switch(p->did){
+ case 0x5348:
+ break;
+ default:
+ return;
+ }
+ }
+ else
+ return;
+ scr->pci = p;
+
+ mmio = vmap(p->mem[4].bar & ~0x0F, p->mem[4].size);
+ if(mmio == nil)
+ return;
+ addvgaseg("t2r4mmio", p->mem[4].bar & ~0x0F, p->mem[4].size);
+
+ scr->mmio = mmio;
+ vgalinearpci(scr);
+ if(scr->paddr)
+ addvgaseg("t2r4screen", scr->paddr, scr->apsize);
+}
+
+static uchar
+t2r4xi(VGAscr* scr, int index)
+{
+ ulong *mmio;
+
+ mmio = scr->mmio;
+ mmio[IndexLo] = index & 0xFF;
+ mmio[IndexHi] = (index>>8) & 0xFF;
+
+ return mmio[Data];
+}
+
+static void
+t2r4xo(VGAscr* scr, int index, uchar data)
+{
+ ulong *mmio;
+
+ mmio = scr->mmio;
+ mmio[IndexLo] = index & 0xFF;
+ mmio[IndexHi] = (index>>8) & 0xFF;
+
+ mmio[Data] = data;
+}
+
+static void
+t2r4curdisable(VGAscr* scr)
+{
+ if(scr->mmio == 0)
+ return;
+ t2r4xo(scr, CursorCtl, 0x00);
+}
+
+static void
+t2r4curload(VGAscr* scr, Cursor* curs)
+{
+ uchar *data;
+ int size, x, y, zoom;
+ ulong clr, *mmio, pixels, set;
+
+ mmio = scr->mmio;
+ if(mmio == 0)
+ return;
+
+ /*
+ * Make sure cursor is off by initialising the cursor
+ * control to defaults.
+ */
+ t2r4xo(scr, CursorCtl, 0x00);
+
+ /*
+ * Set auto-increment mode for index-register addressing
+ * and initialise the cursor array index.
+ */
+ mmio[IndexCtl] = 0x01;
+ mmio[IndexLo] = CursorArray & 0xFF;
+ mmio[IndexHi] = (CursorArray>>8) & 0xFF;
+
+ /*
+ * Initialise the cursor RAM array. There are 2 planes,
+ * p0 and p1. Data is written 4 pixels per byte, with p1 the
+ * MS bit of each pixel.
+ * The cursor is set in X-Windows mode which gives the following
+ * truth table:
+ * p1 p0 colour
+ * 0 0 underlying pixel colour
+ * 0 1 underlying pixel colour
+ * 1 0 cursor colour 1
+ * 1 1 cursor colour 2
+ * Put the cursor into the top-left of the array.
+ *
+ * Although this looks a lot like the IBM RGB524 cursor, the
+ * scanlines appear to be twice as long as they should be and
+ * some of the other features are missing.
+ */
+ if(mmio[Zoom] & 0x0F)
+ zoom = 32;
+ else
+ zoom = 16;
+ data = (uchar*)&mmio[Data];
+ for(y = 0; y < zoom; y++){
+ clr = (curs->clr[2*y]<<8)|curs->clr[y*2 + 1];
+ set = (curs->set[2*y]<<8)|curs->set[y*2 + 1];
+ pixels = 0;
+ for(x = 0; x < 16; x++){
+ if(set & (1<<x))
+ pixels |= 0x03<<(x*2);
+ else if(clr & (1<<x))
+ pixels |= 0x02<<(x*2);
+ }
+
+ *data = pixels>>24;
+ *data = pixels>>16;
+ *data = pixels>>8;
+ *data = pixels;
+
+ *data = 0x00;
+ *data = 0x00;
+ *data = 0x00;
+ *data = 0x00;
+
+ if(CursorMode == CursorMode32x32 && zoom == 16)
+ continue;
+ *data = pixels>>24;
+ *data = pixels>>16;
+ *data = pixels>>8;
+ *data = pixels;
+
+ *data = 0x00;
+ *data = 0x00;
+ *data = 0x00;
+ *data = 0x00;
+ }
+ if(CursorMode == CursorMode32x32)
+ size = 32;
+ else
+ size = 64;
+ while(y < size){
+ for(x = 0; x < size/8; x++){
+ *data = 0x00;
+ *data = 0x00;
+ }
+ y++;
+ }
+ mmio[IndexCtl] = 0x00;
+
+ /*
+ * Initialise the hotpoint and enable the cursor.
+ */
+ t2r4xo(scr, CursorHotX, -curs->offset.x);
+ zoom = (scr->mmio[Zoom] & 0x0F)+1;
+ t2r4xo(scr, CursorHotY, -curs->offset.y*zoom);
+
+ t2r4xo(scr, CursorCtl, CursorMode);
+}
+
+static int
+t2r4curmove(VGAscr* scr, Point p)
+{
+ int y, zoom;
+
+ if(scr->mmio == 0)
+ return 1;
+
+ t2r4xo(scr, CursorXLo, p.x & 0xFF);
+ t2r4xo(scr, CursorXHi, (p.x>>8) & 0x0F);
+
+ zoom = (scr->mmio[Zoom] & 0x0F)+1;
+ y = p.y*zoom;
+ t2r4xo(scr, CursorYLo, y & 0xFF);
+ t2r4xo(scr, CursorYHi, (y>>8) & 0x0F);
+
+ return 0;
+}
+
+static void
+t2r4curenable(VGAscr* scr)
+{
+ t2r4enable(scr);
+ if(scr->mmio == 0)
+ return;
+
+ /*
+ * Make sure cursor is off by initialising the cursor
+ * control to defaults.
+ */
+ t2r4xo(scr, CursorCtl, 0x00);
+
+ /*
+ * Cursor colour 1 (white),
+ * cursor colour 2 (black).
+ */
+ t2r4xo(scr, CursorR1, Pwhite);
+ t2r4xo(scr, CursorG1, Pwhite);
+ t2r4xo(scr, CursorB1, Pwhite);
+
+ t2r4xo(scr, CursorR2, Pblack);
+ t2r4xo(scr, CursorG2, Pblack);
+ t2r4xo(scr, CursorB2, Pblack);
+
+ /*
+ * Load, locate and enable the cursor, 64x64, mode 2.
+ */
+ t2r4curload(scr, &arrow);
+ t2r4curmove(scr, ZP);
+ t2r4xo(scr, CursorCtl, CursorMode);
+}
+
+enum {
+ Flow = 0x08/4,
+ Busy = 0x0C/4,
+ BufCtl = 0x20/4,
+ DeSorg = 0x28/4,
+ DeDorg = 0x2C/4,
+ DeSptch = 0x40/4,
+ DeDptch = 0x44/4,
+ CmdOpc = 0x50/4,
+ CmdRop = 0x54/4,
+ CmdStyle = 0x58/4,
+ CmdPatrn = 0x5C/4,
+ CmdClp = 0x60/4,
+ CmdPf = 0x64/4,
+ Fore = 0x68/4,
+ Back = 0x6C/4,
+ Mask = 0x70/4,
+ DeKey = 0x74/4,
+ Lpat = 0x78/4,
+ Pctrl = 0x7C/4,
+ Clptl = 0x80/4,
+ Clpbr = 0x84/4,
+ XY0 = 0x88/4,
+ XY1 = 0x8C/4,
+ XY2 = 0x90/4,
+ XY3 = 0x94/4,
+ XY4 = 0x98/4,
+ Alpha = 0x128/4,
+ ACtl = 0x16C/4,
+
+ RBaseD = 0x4000/4,
+};
+
+/* wait until pipeline ready for new command */
+static void
+waitforfifo(VGAscr *scr)
+{
+ int x;
+ ulong *d;
+ x = 0;
+
+ d = scr->mmio + RBaseD;
+ while((d[Busy]&1) && x++ < 1000000)
+ ;
+ if(x >= 1000000) /* shouldn't happen */
+ iprint("busy %8lux\n", d[Busy]);
+}
+
+/* wait until command has finished executing */
+static void
+waitforcmd(VGAscr *scr)
+{
+ int x;
+ ulong *d;
+ x = 0;
+
+ d = scr->mmio + RBaseD;
+ while((d[Flow]&0x1B) && x++ < 1000000)
+ ;
+ if(x >= 1000000) /* shouldn't happen */
+ iprint("flow %8lux\n", d[Flow]);
+}
+
+/* wait until memory controller not busy (i.e. wait for writes to flush) */
+static void
+waitformem(VGAscr *scr)
+{
+ int x;
+ ulong *d;
+ x = 0;
+
+ d = scr->mmio + RBaseD;
+ while((d[Flow]&2)&& x++ < 1000000)
+ ;
+ if(x >= 1000000) /* shouldn't happen */
+ iprint("mem %8lux\n", d[Busy]);
+}
+
+static int
+t2r4hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
+{
+ int ctl;
+ Point dp, sp;
+ ulong *d;
+ int depth;
+
+ if(r.min.y == sr.min.y){ /* a purely horizontal scroll */
+ depth = scr->gscreen->depth;
+ switch(depth){
+ case 32:
+ /*
+ * Using the SGI flat panels with the Ticket-to-Ride IV, horizontal
+ * 32-bit scrolls don't work perfectly on rectangles of width <= 24.
+ * we bail on a bigger bound for padding.
+ */
+ if(Dx(r) < 32)
+ return 0;
+ break;
+ case 16:
+ /*
+ * Using the SGI flat panels with the Ticket-to-Ride IV, horizontal
+ * 16-bit scrolls don't work perfectly on rectangles of width <= 96.
+ * we bail on a bigger bound for padding.
+ */
+ if(Dx(r) < 104)
+ return 0;
+ break;
+ }
+ }
+ waitformem(scr);
+ waitforfifo(scr);
+ d = scr->mmio + RBaseD;
+ ctl = 0;
+ if(r.min.x <= sr.min.x){
+ dp.x = r.min.x;
+ sp.x = sr.min.x;
+ }else{
+ ctl |= 2;
+ dp.x = r.max.x-1;
+ sp.x = sr.max.x-1;
+ }
+
+ if(r.min.y < sr.min.y){
+ dp.y = r.min.y;
+ sp.y = sr.min.y;
+ }else{
+ ctl |= 1;
+ dp.y = r.max.y-1;
+ sp.y = sr.max.y-1;
+ }
+
+ d[CmdOpc] = 0x1; /* bitblt */
+ d[CmdRop] = 0xC; /* copy source */
+ d[CmdStyle] = 0;
+ d[CmdPatrn] = 0;
+ d[Fore] = 0;
+ d[Back] = 0;
+
+ /* writing XY1 executes cmd */
+ d[XY3] = ctl;
+ d[XY0] = (sp.x<<16)|sp.y;
+ d[XY2] = (Dx(r)<<16)|Dy(r);
+ d[XY4] = 0;
+ d[XY1] = (dp.x<<16)|dp.y;
+ waitforcmd(scr);
+
+ return 1;
+}
+
+static int
+t2r4hwfill(VGAscr *scr, Rectangle r, ulong sval)
+{
+ ulong *d;
+
+ d = scr->mmio + RBaseD;
+
+ waitformem(scr);
+ waitforfifo(scr);
+ d[CmdOpc] = 0x1; /* bitblt */
+ d[CmdRop] = 0xC; /* copy source */
+ d[CmdStyle] = 1; /* use source from Fore register */
+ d[CmdPatrn] = 0; /* no stipple */
+ d[Fore] = sval;
+ d[Back] = sval;
+
+ /* writing XY1 executes cmd */
+ d[XY3] = 0;
+ d[XY0] = (r.min.x<<16)|r.min.y;
+ d[XY2] = (Dx(r)<<16)|Dy(r);
+ d[XY4] = 0;
+ d[XY1] = (r.min.x<<16)|r.min.y;
+ waitforcmd(scr);
+
+ return 1;
+}
+
+static void
+t2r4blank(VGAscr *scr, int blank)
+{
+ uchar x;
+
+ x = t2r4xi(scr, CursorSyncCtl);
+ x &= ~0x0F;
+ if(blank)
+ x |= HsyncLo | VsyncLo;
+ t2r4xo(scr, CursorSyncCtl, x);
+}
+
+static void
+t2r4drawinit(VGAscr *scr)
+{
+ ulong pitch;
+ int depth;
+ int fmt;
+ ulong *d;
+
+ pitch = Dx(scr->gscreen->r);
+ depth = scr->gscreen->depth;
+
+ switch(scr->gscreen->chan){
+ case RGB16:
+ fmt = 3;
+ break;
+ case XRGB32:
+ fmt = 2;
+ break;
+ case RGB15:
+ fmt = 1;
+ break;
+ default:
+ scr->fill = nil;
+ scr->scroll = nil;
+ return;
+ }
+
+ d = scr->mmio + RBaseD;
+
+ d[BufCtl] = fmt<<24;
+ d[DeSorg] = 0;
+ d[DeDorg] = 0;
+ d[DeSptch] = (pitch*depth)/8;
+ d[DeDptch] = (pitch*depth)/8;
+ d[CmdClp] = 0; /* 2 = inside rectangle */
+ d[Mask] = ~0;
+ d[DeKey] = 0;
+ d[Clptl] = 0;
+ d[Clpbr] = 0xFFF0FFF0;
+ d[Alpha] = 0;
+ d[ACtl] = 0;
+
+ scr->fill = t2r4hwfill;
+ scr->scroll = t2r4hwscroll;
+ scr->blank = t2r4blank;
+ hwblank = 1;
+}
+
+VGAdev vgat2r4dev = {
+ "t2r4",
+
+ t2r4enable,
+ nil,
+ nil,
+ nil,
+ t2r4drawinit,
+};
+
+VGAcur vgat2r4cur = {
+ "t2r4hwgc",
+
+ t2r4curenable,
+ t2r4curdisable,
+ t2r4curload,
+ t2r4curmove,
+};
+
diff --git a/sys/src/9/pc/vgatvp3020.c b/sys/src/9/pc/vgatvp3020.c
new file mode 100755
index 000000000..b1286251e
--- /dev/null
+++ b/sys/src/9/pc/vgatvp3020.c
@@ -0,0 +1,217 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+/*
+ * TVP3020 Viewpoint Video Interface Pallette.
+ * Assumes hooked up to an S3 86C928.
+ */
+enum {
+ Index = 0x06, /* Index register */
+ Data = 0x07, /* Data register */
+};
+
+/*
+ * Lower 2-bits of indirect DAC register
+ * addressing.
+ */
+static ushort dacxreg[4] = {
+ PaddrW, Pdata, Pixmask, PaddrR
+};
+
+static uchar
+tvp3020io(uchar reg, uchar data)
+{
+ uchar crt55;
+
+ crt55 = vgaxi(Crtx, 0x55) & 0xFC;
+ vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
+ vgao(dacxreg[reg & 0x03], data);
+
+ return crt55;
+}
+
+static void
+tvp3020xo(uchar index, uchar data)
+{
+ uchar crt55;
+
+ crt55 = tvp3020io(Index, index);
+ vgao(dacxreg[Data & 0x03], data);
+ vgaxo(Crtx, 0x55, crt55);
+}
+
+static void
+tvp3020disable(VGAscr*)
+{
+ uchar r;
+
+ /*
+ * Disable
+ * cursor;
+ * cursor control enable for Bt485 DAC (!);
+ * the hardware cursor external operation mode.
+ */
+ tvp3020xo(0x06, 0x10); /* Cursor Control Register */
+
+ r = vgaxi(Crtx, 0x45) & ~0x20;
+ vgaxo(Crtx, 0x45, r);
+
+ r = vgaxi(Crtx, 0x55) & ~0x20;
+ vgaxo(Crtx, 0x55, r);
+}
+
+static void
+tvp3020enable(VGAscr*)
+{
+ uchar r;
+
+ /*
+ * Make sure cursor is off by initialising the cursor
+ * control to defaults + X-Windows cursor mode.
+ */
+ tvp3020xo(0x06, 0x10); /* Cursor Control Register */
+
+ /*
+ * Overscan colour,
+ * cursor colour 1 (white),
+ * cursor colour 2 (black).
+ */
+ tvp3020xo(0x20, Pwhite); tvp3020xo(0x21, Pwhite); tvp3020xo(0x22, Pwhite);
+ tvp3020xo(0x23, Pwhite); tvp3020xo(0x24, Pwhite); tvp3020xo(0x25, Pwhite);
+ tvp3020xo(0x26, Pblack); tvp3020xo(0x27, Pblack); tvp3020xo(0x28, Pblack);
+
+ /*
+ * Finally, enable
+ * the hardware cursor external operation mode;
+ * cursor control enable for Bt485 DAC (!).
+ */
+ r = vgaxi(Crtx, 0x55)|0x20;
+ vgaxo(Crtx, 0x55, r);
+
+ r = vgaxi(Crtx, 0x45)|0x20;
+ vgaxo(Crtx, 0x45, r);
+}
+
+static void
+tvp3020load(VGAscr*, Cursor* curs)
+{
+ uchar p, p0, p1;
+ int x, y;
+
+ /*
+ * Make sure cursor is off by initialising the cursor
+ * control to defaults + X-Windows cursor mode.
+ */
+ tvp3020xo(0x06, 0x10); /* Cursor Control Register */
+
+ /*
+ * Initialise the cursor RAM LS and MS address
+ * (LS must be first).
+ */
+ tvp3020xo(0x08, 0x00); /* Cursor RAM LS Address */
+ tvp3020xo(0x09, 0x00); /* Cursor RAM MS Address */
+
+ /*
+ * Initialise the 64x64 cursor RAM array. There are 2 planes,
+ * p0 and p1. Data is written 4 pixels per byte, with p1 the
+ * MS bit of each pixel.
+ * The cursor is set in X-Windows mode which gives the following
+ * truth table:
+ * p1 p0 colour
+ * 0 0 underlying pixel colour
+ * 0 1 underlying pixel colour
+ * 1 0 cursor colour 1
+ * 1 1 cursor colour 2
+ * Put the cursor into the top-left of the 64x64 array.
+ */
+ for(y = 0; y < 64; y++){
+ for(x = 0; x < 64/8; x++){
+ if(x < 16/8 && y < 16){
+ p0 = curs->clr[x+y*2];
+ p1 = curs->set[x+y*2];
+
+ p = 0x00;
+ if(p1 & 0x10)
+ p |= 0x03;
+ else if(p0 & 0x10)
+ p |= 0x02;
+ if(p1 & 0x20)
+ p |= 0x0C;
+ else if(p0 & 0x20)
+ p |= 0x08;
+ if(p1 & 0x40)
+ p |= 0x30;
+ else if(p0 & 0x40)
+ p |= 0x20;
+ if(p1 & 0x80)
+ p |= 0xC0;
+ else if(p0 & 0x80)
+ p |= 0x80;
+ tvp3020xo(0x0A, p); /* Cursor RAM Data */
+
+ p = 0x00;
+ if(p1 & 0x01)
+ p |= 0x03;
+ else if(p0 & 0x01)
+ p |= 0x02;
+ if(p1 & 0x02)
+ p |= 0x0C;
+ else if(p0 & 0x02)
+ p |= 0x08;
+ if(p1 & 0x04)
+ p |= 0x30;
+ else if(p0 & 0x04)
+ p |= 0x20;
+ if(p1 & 0x08)
+ p |= 0xC0;
+ else if(p0 & 0x08)
+ p |= 0x80;
+ tvp3020xo(0x0A, p); /* Cursor RAM Data */
+ }
+ else{
+ tvp3020xo(0x0A, 0x00); /* Cursor RAM Data */
+ tvp3020xo(0x0A, 0x00);
+ }
+ }
+ }
+
+ /*
+ * Initialise the cursor hotpoint
+ * and enable the cursor.
+ */
+ tvp3020xo(0x04, -curs->offset.x); /* Sprite Origin X */
+ tvp3020xo(0x05, -curs->offset.y); /* Sprite Origin Y */
+
+ tvp3020xo(0x06, 0x40|0x10); /* Cursor Control Register */
+}
+
+static int
+tvp3020move(VGAscr*, Point p)
+{
+ tvp3020xo(0x00, p.x & 0xFF); /* Cursor Position X LSB */
+ tvp3020xo(0x01, (p.x>>8) & 0x0F); /* Cursor Position X MSB */
+ tvp3020xo(0x02, p.y & 0xFF); /* Cursor Position Y LSB */
+ tvp3020xo(0x03, (p.y>>8) & 0x0F); /* Cursor Position Y MSB */
+
+ return 0;
+}
+
+VGAcur vgatvp3020cur = {
+ "tvp3020hwgc",
+
+ tvp3020enable,
+ tvp3020disable,
+ tvp3020load,
+ tvp3020move,
+};
diff --git a/sys/src/9/pc/vgatvp3026.c b/sys/src/9/pc/vgatvp3026.c
new file mode 100755
index 000000000..db3196bc1
--- /dev/null
+++ b/sys/src/9/pc/vgatvp3026.c
@@ -0,0 +1,190 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+/*
+ * TVP3026 Viewpoint Video Interface Pallette.
+ * Assumes hooked up to an S3 Vision968.
+ */
+enum {
+ Index = 0x00, /* Index */
+ Data = 0x0A, /* Data */
+
+ CaddrW = 0x04, /* Colour Write Address */
+ Cdata = 0x05, /* Colour Data */
+
+ Cctl = 0x09, /* Direct Cursor Control */
+ Cram = 0x0B, /* Cursor Ram Data */
+ Cxlsb = 0x0C, /* Cursor X LSB */
+ Cxmsb = 0x0D, /* Cursor X MSB */
+ Cylsb = 0x0E, /* Cursor Y LSB */
+ Cymsb = 0x0F, /* Cursor Y MSB */
+
+ Icctl = 0x06, /* Indirect Cursor Control */
+};
+
+/*
+ * Lower 2-bits of indirect DAC register
+ * addressing.
+ */
+static ushort dacxreg[4] = {
+ PaddrW, Pdata, Pixmask, PaddrR
+};
+
+static uchar
+tvp3026io(uchar reg, uchar data)
+{
+ uchar crt55;
+
+ crt55 = vgaxi(Crtx, 0x55) & 0xFC;
+ vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
+ vgao(dacxreg[reg & 0x03], data);
+
+ return crt55;
+}
+
+static void
+tvp3026o(uchar reg, uchar data)
+{
+ uchar crt55;
+
+ crt55 = tvp3026io(reg, data);
+ vgaxo(Crtx, 0x55, crt55);
+}
+
+void
+tvp3026xo(uchar index, uchar data)
+{
+ uchar crt55;
+
+ crt55 = tvp3026io(Index, index);
+ vgaxo(Crtx, 0x55, crt55|((Data>>2) & 0x03));
+ vgao(dacxreg[Data & 0x03], data);
+ vgaxo(Crtx, 0x55, crt55);
+}
+
+static void
+tvp3026disable(VGAscr*)
+{
+ tvp3026xo(Icctl, 0x90);
+ tvp3026o(Cctl, 0x00);
+}
+
+static void
+tvp3026enable(VGAscr*)
+{
+ /*
+ * Make sure cursor is off and direct control enabled.
+ */
+ tvp3026xo(Icctl, 0x90);
+ tvp3026o(Cctl, 0x00);
+
+ /*
+ * Overscan colour,
+ * cursor colour 1 (white),
+ * cursor colour 2, 3 (black).
+ */
+ tvp3026o(CaddrW, 0x00);
+ tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite);
+ tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite);
+ tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack);
+ tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack);
+
+ /*
+ * Enable the cursor in 3-colour mode.
+ */
+ tvp3026o(Cctl, 0x01);
+}
+
+static void
+tvp3026load(VGAscr* scr, Cursor* curs)
+{
+ int x, y;
+
+ /*
+ * Make sure cursor is off by initialising the cursor
+ * control to defaults.
+ * Write to the indirect control register to make sure
+ * direct register is enabled and upper 2 bits of cursor
+ * RAM address are 0.
+ * The LSBs of the cursor RAM address are in PaddrW.
+ */
+ tvp3026xo(Icctl, 0x90);
+ tvp3026o(Cctl, 0x00);
+ vgao(PaddrW, 0x00);
+
+ /*
+ * Initialise the 64x64 cursor RAM array. There are 2 planes,
+ * p0 and p1. Data is written 8 pixels per byte, with p0 in the
+ * first 512 bytes of the array and p1 in the second.
+ * The cursor is set in 3-colour mode which gives the following
+ * truth table:
+ * p1 p0 colour
+ * 0 0 transparent
+ * 0 1 cursor colour 0
+ * 1 0 cursor colour 1
+ * 1 1 cursor colour 2
+ * Put the cursor into the top-left of the 64x64 array.
+ * The 0,0 cursor point is bottom-right, so positioning will
+ * have to take that into account.
+ */
+ for(y = 0; y < 64; y++){
+ for(x = 0; x < 64/8; x++){
+ if(x < 16/8 && y < 16)
+ tvp3026o(Cram, curs->clr[x+y*2]);
+ else
+ tvp3026o(Cram, 0x00);
+ }
+ }
+ for(y = 0; y < 64; y++){
+ for(x = 0; x < 64/8; x++){
+ if(x < 16/8 && y < 16)
+ tvp3026o(Cram, curs->set[x+y*2]);
+ else
+ tvp3026o(Cram, 0x00);
+ }
+ }
+
+ /*
+ * Initialise the cursor hotpoint
+ * and enable the cursor in 3-colour mode.
+ */
+ scr->offset.x = 64+curs->offset.x;
+ scr->offset.y = 64+curs->offset.y;
+ tvp3026o(Cctl, 0x01);
+}
+
+static int
+tvp3026move(VGAscr* scr, Point p)
+{
+ int x, y;
+
+ x = p.x+scr->offset.x;
+ y = p.y+scr->offset.y;
+
+ tvp3026o(Cxlsb, x & 0xFF);
+ tvp3026o(Cxmsb, (x>>8) & 0x0F);
+ tvp3026o(Cylsb, y & 0xFF);
+ tvp3026o(Cymsb, (y>>8) & 0x0F);
+
+ return 0;
+}
+
+VGAcur vgatvp3026cur = {
+ "tvp3026hwgc",
+
+ tvp3026enable,
+ tvp3026disable,
+ tvp3026load,
+ tvp3026move,
+};
diff --git a/sys/src/9/pc/vgavesa.c b/sys/src/9/pc/vgavesa.c
new file mode 100755
index 000000000..3fe1bfb17
--- /dev/null
+++ b/sys/src/9/pc/vgavesa.c
@@ -0,0 +1,227 @@
+/*
+ * vga driver using just vesa bios to set up.
+ *
+ * note that setting hwaccel to zero will cause cursor ghosts to be
+ * left behind. hwaccel set non-zero repairs this.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "ureg.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+enum {
+ Usesoftscreen = 1,
+};
+
+static void *hardscreen;
+static uchar modebuf[0x1000];
+
+#define WORD(p) ((p)[0] | ((p)[1]<<8))
+#define LONG(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
+#define PWORD(p, v) (p)[0] = (v); (p)[1] = (v)>>8
+#define PLONG(p, v) (p)[0] = (v); (p)[1] = (v)>>8; (p)[2] = (v)>>16; (p)[3] = (v)>>24
+
+static uchar*
+vbesetup(Ureg *u, int ax)
+{
+ ulong pa;
+
+ pa = PADDR(RMBUF);
+ memset(modebuf, 0, sizeof modebuf);
+ memset(u, 0, sizeof *u);
+ u->ax = ax;
+ u->es = (pa>>4)&0xF000;
+ u->di = pa&0xFFFF;
+ return modebuf;
+}
+
+static void
+vbecall(Ureg *u)
+{
+ Chan *creg, *cmem;
+ ulong pa;
+
+ cmem = namec("/dev/realmodemem", Aopen, ORDWR, 0);
+ if(waserror()){
+ cclose(cmem);
+ nexterror();
+ }
+ creg = namec("/dev/realmode", Aopen, ORDWR, 0);
+ if(waserror()){
+ cclose(creg);
+ nexterror();
+ }
+ pa = PADDR(RMBUF);
+ /* TODO: check read and write return values */
+ devtab[cmem->type]->write(cmem, modebuf, sizeof modebuf, pa);
+ u->trap = 0x10;
+ devtab[creg->type]->write(creg, u, sizeof *u, 0);
+
+ devtab[creg->type]->read(creg, u, sizeof *u, 0);
+ if((u->ax&0xFFFF) != 0x004F)
+ error("vesa bios error");
+ devtab[cmem->type]->read(cmem, modebuf, sizeof modebuf, pa);
+
+ poperror();
+ cclose(creg);
+ poperror();
+ cclose(cmem);
+}
+
+static void
+vbecheck(void)
+{
+ Ureg u;
+ uchar *p;
+
+ p = vbesetup(&u, 0x4F00);
+ strcpy((char*)p, "VBE2");
+ vbecall(&u);
+ if(memcmp((char*)p, "VESA", 4) != 0)
+ error("bad vesa signature");
+ if(p[5] < 2)
+ error("bad vesa version");
+}
+
+static int
+vbegetmode(void)
+{
+ Ureg u;
+
+ vbesetup(&u, 0x4F03);
+ vbecall(&u);
+ return u.bx;
+}
+
+static uchar*
+vbemodeinfo(int mode)
+{
+ uchar *p;
+ Ureg u;
+
+ p = vbesetup(&u, 0x4F01);
+ u.cx = mode;
+ vbecall(&u);
+ return p;
+}
+
+static void
+vesalinear(VGAscr *scr, int, int)
+{
+ int i, mode, size, havesize;
+ uchar *p;
+ ulong paddr;
+ Pcidev *pci;
+
+ if(hardscreen) {
+ scr->vaddr = 0;
+ scr->paddr = scr->apsize = 0;
+ return;
+ }
+
+ vbecheck();
+ mode = vbegetmode();
+ /*
+ * bochs loses the top bits - cannot use this
+ if((mode&(1<<14)) == 0)
+ error("not in linear graphics mode");
+ */
+ mode &= 0x3FFF;
+ p = vbemodeinfo(mode);
+ if(!(WORD(p+0) & (1<<4)))
+ error("not in VESA graphics mode");
+ if(!(WORD(p+0) & (1<<7)))
+ error("not in linear graphics mode");
+
+ paddr = LONG(p+40);
+ size = WORD(p+20)*WORD(p+16);
+ size = PGROUND(size);
+
+ /*
+ * figure out max size of memory so that we have
+ * enough if the screen is resized.
+ */
+ pci = nil;
+ havesize = 0;
+ while(!havesize && (pci = pcimatch(pci, 0, 0)) != nil){
+ if(pci->ccrb != Pcibcdisp)
+ continue;
+ for(i=0; i<nelem(pci->mem); i++)
+ if(paddr == (pci->mem[i].bar&~0x0F)){
+ if(pci->mem[i].size > size)
+ size = pci->mem[i].size;
+ havesize = 1;
+ break;
+ }
+ }
+
+ /* no pci - heuristic guess */
+ if (!havesize)
+ if(size < 4*1024*1024)
+ size = 4*1024*1024;
+ else
+ size = ROUND(size, 1024*1024);
+ if(size > 16*1024*1024) /* arbitrary */
+ size = 16*1024*1024;
+
+ vgalinearaddr(scr, paddr, size);
+ if(scr->apsize)
+ addvgaseg("vesascreen", scr->paddr, scr->apsize);
+
+ if(Usesoftscreen){
+ hardscreen = scr->vaddr;
+ scr->vaddr = 0;
+ scr->paddr = scr->apsize = 0;
+ }
+}
+
+static void
+vesaflush(VGAscr *scr, Rectangle r)
+{
+ int t, w, wid, off;
+ ulong *hp, *sp, *esp;
+
+ if(hardscreen == nil)
+ return;
+ if(rectclip(&r, scr->gscreen->r) == 0)
+ return;
+ sp = (ulong*)(scr->gscreendata->bdata + scr->gscreen->zero);
+ t = (r.max.x * scr->gscreen->depth + 2*BI2WD-1) / BI2WD;
+ w = (r.min.x * scr->gscreen->depth) / BI2WD;
+ w = (t - w) * BY2WD;
+ wid = scr->gscreen->width;
+ off = r.min.y * wid + (r.min.x * scr->gscreen->depth) / BI2WD;
+
+ hp = hardscreen;
+ hp += off;
+ sp += off;
+ esp = sp + Dy(r) * wid;
+ while(sp < esp){
+ memmove(hp, sp, w);
+ hp += wid;
+ sp += wid;
+ }
+}
+
+VGAdev vgavesadev = {
+ "vesa",
+ 0,
+ 0,
+ 0,
+ vesalinear,
+ 0,
+ 0,
+ 0,
+ 0,
+ vesaflush,
+};
diff --git a/sys/src/9/pc/vgavmware.c b/sys/src/9/pc/vgavmware.c
new file mode 100755
index 000000000..60c8cfa73
--- /dev/null
+++ b/sys/src/9/pc/vgavmware.c
@@ -0,0 +1,370 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+enum {
+ PCIVMWARE = 0x15AD, /* PCI VID */
+
+ VMWARE1 = 0x0710, /* PCI DID */
+ VMWARE2 = 0x0405,
+};
+
+enum {
+ Rid = 0,
+ Renable,
+ Rwidth,
+ Rheight,
+ Rmaxwidth,
+
+ Rmaxheight,
+ Rdepth,
+ Rbpp,
+ Rpseudocolor,
+ Rrmask,
+
+ Rgmask,
+ Rbmask,
+ Rbpl,
+ Rfbstart,
+ Rfboffset,
+
+ Rfbmaxsize,
+ Rfbsize,
+ Rcap,
+ Rmemstart,
+ Rmemsize,
+
+ Rconfigdone,
+ Rsync,
+ Rbusy,
+ Rguestid,
+ Rcursorid,
+
+ Rcursorx,
+ Rcursory,
+ Rcursoron,
+ Nreg,
+
+ Crectfill = 1<<0,
+ Crectcopy = 1<<1,
+ Crectpatfill = 1<<2,
+ Coffscreen = 1<<3,
+ Crasterop = 1<<4,
+ Ccursor = 1<<5,
+ Ccursorbypass = 1<<6,
+ Ccursorbypass2 = 1<<7,
+ C8bitemulation = 1<<8,
+ Calphacursor = 1<<9,
+
+ FifoMin = 0,
+ FifoMax = 1,
+ FifoNextCmd = 2,
+ FifoStop = 3,
+ FifoUser = 4,
+
+ Xupdate = 1,
+ Xrectfill = 2,
+ Xrectcopy = 3,
+ Xdefinebitmap = 4,
+ Xdefinebitmapscanline = 5,
+ Xdefinepixmap = 6,
+ Xdefinepixmapscanline = 7,
+ Xrectbitmapfill = 8,
+ Xrectpixmapfill = 9,
+ Xrectbitmapcopy = 10,
+ Xrectpixmapcopy = 11,
+ Xfreeobject = 12,
+ Xrectropfill = 13,
+ Xrectropcopy = 14,
+ Xrectropbitmapfill = 15,
+ Xrectroppixmapfill = 16,
+ Xrectropbitmapcopy = 17,
+ Xrectroppixmapcopy = 18,
+ Xdefinecursor = 19,
+ Xdisplaycursor = 20,
+ Xmovecursor = 21,
+ Xdefinealphacursor = 22,
+ Xcmdmax = 23,
+
+ CursorOnHide = 0,
+ CursorOnShow = 1,
+ CursorOnRemoveFromFb = 2,
+ CursorOnRestoreToFb = 3,
+
+ Rpalette = 1024,
+};
+
+typedef struct Vmware Vmware;
+struct Vmware {
+ ulong fb;
+
+ ulong ra;
+ ulong rd;
+
+ ulong r[Nreg];
+ ulong *mmio;
+ ulong mmiosize;
+
+ char chan[32];
+ int depth;
+};
+
+Vmware xvm;
+Vmware *vm=&xvm;
+
+static ulong
+vmrd(Vmware *vm, int i)
+{
+ outl(vm->ra, i);
+ return inl(vm->rd);
+}
+
+static void
+vmwr(Vmware *vm, int i, ulong v)
+{
+ outl(vm->ra, i);
+ outl(vm->rd, v);
+}
+
+static void
+vmwait(Vmware *vm)
+{
+ vmwr(vm, Rsync, 1);
+ while(vmrd(vm, Rbusy))
+ ;
+}
+
+static void
+vmwarelinear(VGAscr* scr, int, int)
+{
+ char err[64];
+ Pcidev *p;
+
+ err[0] = 0;
+ p = nil;
+ while((p = pcimatch(p, PCIVMWARE, 0)) != nil){
+ if(p->ccrb != Pcibcdisp)
+ continue;
+ switch(p->did){
+ default:
+ snprint(err, sizeof err, "unknown vmware pci did %.4ux",
+ p->did);
+ continue;
+
+ case VMWARE1:
+ vm->ra = 0x4560;
+ vm->rd = 0x4560 + 4;
+ break;
+
+ case VMWARE2:
+ vm->ra = p->mem[0].bar & ~3;
+ vm->rd = vm->ra + 1;
+ break;
+ }
+ break; /* found a card, p is set */
+ }
+ if(p == nil)
+ error(err[0]? err: "no vmware vga card found");
+
+ vgalinearaddr(scr, vmrd(vm, Rfbstart), vmrd(vm, Rfbsize));
+ if(scr->apsize)
+ addvgaseg("vmwarescreen", scr->paddr, scr->apsize);
+}
+
+static void
+vmfifowr(Vmware *vm, ulong v)
+{
+ ulong *mm;
+
+ mm = vm->mmio;
+ if(mm == nil){
+ iprint("!");
+ return;
+ }
+
+ if(mm[FifoNextCmd]+sizeof(ulong) == mm[FifoStop]
+ || (mm[FifoNextCmd]+sizeof(ulong) == mm[FifoMax]
+ && mm[FifoStop] == mm[FifoMin]))
+ vmwait(vm);
+
+ mm[mm[FifoNextCmd]/sizeof(ulong)] = v;
+
+ /* must do this way so mm[FifoNextCmd] is never mm[FifoMax] */
+ v = mm[FifoNextCmd] + sizeof(ulong);
+ if(v == mm[FifoMax])
+ v = mm[FifoMin];
+ mm[FifoNextCmd] = v;
+}
+
+static void
+vmwareflush(VGAscr*, Rectangle r)
+{
+ if(vm->mmio == nil)
+ return;
+
+ vmfifowr(vm, Xupdate);
+ vmfifowr(vm, r.min.x);
+ vmfifowr(vm, r.min.y);
+ vmfifowr(vm, r.max.x-r.min.x);
+ vmfifowr(vm, r.max.y-r.min.y);
+ vmwait(vm);
+}
+
+static void
+vmwareload(VGAscr*, Cursor *c)
+{
+ int i;
+ ulong clr, set;
+ ulong and[16];
+ ulong xor[16];
+
+ if(vm->mmio == nil)
+ return;
+ vmfifowr(vm, Xdefinecursor);
+ vmfifowr(vm, 1); /* cursor id */
+ vmfifowr(vm, -c->offset.x);
+ vmfifowr(vm, -c->offset.y);
+
+ vmfifowr(vm, 16); /* width */
+ vmfifowr(vm, 16); /* height */
+ vmfifowr(vm, 1); /* depth for and mask */
+ vmfifowr(vm, 1); /* depth for xor mask */
+
+ for(i=0; i<16; i++){
+ clr = (c->clr[i*2+1]<<8) | c->clr[i*2];
+ set = (c->set[i*2+1]<<8) | c->set[i*2];
+ and[i] = ~(clr|set); /* clr and set pixels => black */
+ xor[i] = clr&~set; /* clr pixels => white */
+ }
+ for(i=0; i<16; i++)
+ vmfifowr(vm, and[i]);
+ for(i=0; i<16; i++)
+ vmfifowr(vm, xor[i]);
+
+ vmwait(vm);
+}
+
+static int
+vmwaremove(VGAscr*, Point p)
+{
+ vmwr(vm, Rcursorid, 1);
+ vmwr(vm, Rcursorx, p.x);
+ vmwr(vm, Rcursory, p.y);
+ vmwr(vm, Rcursoron, CursorOnShow);
+ return 0;
+}
+
+static void
+vmwaredisable(VGAscr*)
+{
+ vmwr(vm, Rcursorid, 1);
+ vmwr(vm, Rcursoron, CursorOnHide);
+}
+
+static void
+vmwareenable(VGAscr*)
+{
+ vmwr(vm, Rcursorid, 1);
+ vmwr(vm, Rcursoron, CursorOnShow);
+}
+
+static void
+vmwareblank(int)
+{
+}
+
+static int
+vmwarescroll(VGAscr*, Rectangle r, Rectangle sr)
+{
+ if(vm->mmio == nil)
+ return 0;
+ vmfifowr(vm, Xrectcopy);
+ vmfifowr(vm, sr.min.x);
+ vmfifowr(vm, sr.min.y);
+ vmfifowr(vm, r.min.x);
+ vmfifowr(vm, r.min.y);
+ vmfifowr(vm, Dx(r));
+ vmfifowr(vm, Dy(r));
+ vmwait(vm);
+ return 1;
+}
+
+static int
+vmwarefill(VGAscr*, Rectangle r, ulong sval)
+{
+ if(vm->mmio == nil)
+ return 0;
+ vmfifowr(vm, Xrectfill);
+ vmfifowr(vm, sval);
+ vmfifowr(vm, r.min.x);
+ vmfifowr(vm, r.min.y);
+ vmfifowr(vm, r.max.x-r.min.x);
+ vmfifowr(vm, r.max.y-r.min.y);
+ vmwait(vm);
+ return 1;
+}
+
+static void
+vmwaredrawinit(VGAscr *scr)
+{
+ ulong offset;
+ ulong mmiobase, mmiosize;
+
+ if(scr->mmio==nil){
+ mmiobase = vmrd(vm, Rmemstart);
+ if(mmiobase == 0)
+ return;
+ mmiosize = vmrd(vm, Rmemsize);
+ scr->mmio = vmap(mmiobase, mmiosize);
+ if(scr->mmio == nil)
+ return;
+ vm->mmio = scr->mmio;
+ vm->mmiosize = mmiosize;
+ addvgaseg("vmwaremmio", mmiobase, mmiosize);
+ }
+
+ scr->mmio[FifoMin] = 4*sizeof(ulong);
+ scr->mmio[FifoMax] = vm->mmiosize;
+ scr->mmio[FifoNextCmd] = 4*sizeof(ulong);
+ scr->mmio[FifoStop] = 4*sizeof(ulong);
+ vmwr(vm, Rconfigdone, 1);
+
+ scr->scroll = vmwarescroll;
+ scr->fill = vmwarefill;
+
+ offset = vmrd(vm, Rfboffset);
+ scr->gscreendata->bdata += offset;
+}
+
+VGAdev vgavmwaredev = {
+ "vmware",
+
+ 0,
+ 0,
+ 0,
+ vmwarelinear,
+ vmwaredrawinit,
+ 0,
+ 0,
+ 0,
+ vmwareflush,
+};
+
+VGAcur vgavmwarecur = {
+ "vmwarehwgc",
+
+ vmwareenable,
+ vmwaredisable,
+ vmwareload,
+ vmwaremove,
+};
diff --git a/sys/src/9/pc/vgax.c b/sys/src/9/pc/vgax.c
new file mode 100755
index 000000000..757ca171a
--- /dev/null
+++ b/sys/src/9/pc/vgax.c
@@ -0,0 +1,103 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+static Lock vgaxlock; /* access to index registers */
+
+int
+vgaxi(long port, uchar index)
+{
+ uchar data;
+
+ ilock(&vgaxlock);
+ switch(port){
+
+ case Seqx:
+ case Crtx:
+ case Grx:
+ outb(port, index);
+ data = inb(port+1);
+ break;
+
+ case Attrx:
+ /*
+ * Allow processor access to the colour
+ * palette registers. Writes to Attrx must
+ * be preceded by a read from Status1 to
+ * initialise the register to point to the
+ * index register and not the data register.
+ * Processor access is allowed by turning
+ * off bit 0x20.
+ */
+ inb(Status1);
+ if(index < 0x10){
+ outb(Attrx, index);
+ data = inb(Attrx+1);
+ inb(Status1);
+ outb(Attrx, 0x20|index);
+ }
+ else{
+ outb(Attrx, 0x20|index);
+ data = inb(Attrx+1);
+ }
+ break;
+
+ default:
+ iunlock(&vgaxlock);
+ return -1;
+ }
+ iunlock(&vgaxlock);
+
+ return data & 0xFF;
+}
+
+int
+vgaxo(long port, uchar index, uchar data)
+{
+ ilock(&vgaxlock);
+ switch(port){
+
+ case Seqx:
+ case Crtx:
+ case Grx:
+ /*
+ * We could use an outport here, but some chips
+ * (e.g. 86C928) have trouble with that for some
+ * registers.
+ */
+ outb(port, index);
+ outb(port+1, data);
+ break;
+
+ case Attrx:
+ inb(Status1);
+ if(index < 0x10){
+ outb(Attrx, index);
+ outb(Attrx, data);
+ inb(Status1);
+ outb(Attrx, 0x20|index);
+ }
+ else{
+ outb(Attrx, 0x20|index);
+ outb(Attrx, data);
+ }
+ break;
+
+ default:
+ iunlock(&vgaxlock);
+ return -1;
+ }
+ iunlock(&vgaxlock);
+
+ return 0;
+}
diff --git a/sys/src/9/pc/wavelan.c b/sys/src/9/pc/wavelan.c
new file mode 100755
index 000000000..bf42c3c52
--- /dev/null
+++ b/sys/src/9/pc/wavelan.c
@@ -0,0 +1,1263 @@
+/*
+ Lucent Wavelan IEEE 802.11 pcmcia.
+ There is almost no documentation for the card.
+ the driver is done using both the FreeBSD, Linux and
+ original Plan 9 drivers as `documentation'.
+
+ Has been used with the card plugged in during all up time.
+ no cards removals/insertions yet.
+
+ For known BUGS see the comments below. Besides,
+ the driver keeps interrupts disabled for just too
+ long. When it gets robust, locks should be revisited.
+
+ BUGS: check endian, alignment and mem/io issues;
+ receive watchdog interrupts.
+ TODO: automatic power management;
+ multicast filtering;
+ improve locking.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+#include "etherif.h"
+#include "wavelan.h"
+
+enum
+{
+ MSperTick= 50, /* ms between ticks of kproc */
+};
+
+/*
+ * When we're using a PCI device and memory-mapped I/O,
+ * the registers are spaced out as though each takes 32 bits,
+ * even though they are only 16-bit registers. Thus,
+ * ctlr->mmb[reg] is the right way to access register reg,
+ * even though a priori you'd expect to use ctlr->mmb[reg/2].
+ */
+void
+csr_outs(Ctlr *ctlr, int reg, ushort arg)
+{
+ if(ctlr->mmb)
+ ctlr->mmb[reg] = arg;
+ else
+ outs(ctlr->iob+reg, arg);
+}
+
+ushort
+csr_ins(Ctlr *ctlr, int reg)
+{
+ if(ctlr->mmb)
+ return ctlr->mmb[reg];
+ else
+ return ins(ctlr->iob+reg);
+}
+
+static void
+csr_ack(Ctlr *ctlr, int ev)
+{
+ csr_outs(ctlr, WR_EvAck, ev);
+}
+
+static void
+csr_inss(Ctlr *ctlr, int reg, void *dat, int ndat)
+{
+ ushort *rp, *wp;
+
+ if(ctlr->mmb){
+ rp = &ctlr->mmb[reg];
+ wp = dat;
+ while(ndat-- > 0)
+ *wp++ = *rp;
+ }else
+ inss(ctlr->iob+reg, dat, ndat);
+}
+
+static void
+csr_outss(Ctlr *ctlr, int reg, void *dat, int ndat)
+{
+ ushort *rp, *wp;
+
+ if(ctlr->mmb){
+ rp = dat;
+ wp = &ctlr->mmb[reg];
+ while(ndat-- > 0)
+ *wp = *rp++;
+ }else
+ outss(ctlr->iob+reg, dat, ndat);
+}
+
+// w_... routines do not ilock the Ctlr and should
+// be called locked.
+
+void
+w_intdis(Ctlr* ctlr)
+{
+ csr_outs(ctlr, WR_IntEna, 0);
+ csr_ack(ctlr, 0xffff);
+}
+
+static void
+w_intena(Ctlr* ctlr)
+{
+ csr_outs(ctlr, WR_IntEna, WEvs);
+}
+
+int
+w_cmd(Ctlr *ctlr, ushort cmd, ushort arg)
+{
+ int i, rc;
+
+ for(i=0; i<WTmOut; i++)
+ if((csr_ins(ctlr, WR_Cmd)&WCmdBusy) == 0)
+ break;
+ if(i==WTmOut){
+ print("#l%d: issuing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_Cmd));
+ return -1;
+ }
+
+ csr_outs(ctlr, WR_Parm0, arg);
+ csr_outs(ctlr, WR_Cmd, cmd);
+
+ for(i=0; i<WTmOut; i++)
+ if(csr_ins(ctlr, WR_EvSts)&WCmdEv)
+ break;
+ if(i==WTmOut){
+ /*
+ * WCmdIni can take a really long time.
+ */
+ enum { IniTmOut = 2000 };
+ for(i=0; i<IniTmOut; i++){
+ if(csr_ins(ctlr, WR_EvSts)&WCmdEv)
+ break;
+ microdelay(100);
+ }
+ if(i < IniTmOut)
+ if(0) print("#l%d: long cmd %.4ux %d\n", ctlr->ctlrno, cmd, i);
+ if(i == IniTmOut){
+ print("#l%d: execing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_EvSts));
+ return -1;
+ }
+ }
+ rc = csr_ins(ctlr, WR_Sts);
+ csr_ack(ctlr, WCmdEv);
+
+ if((rc&WCmdMsk) != (cmd&WCmdMsk)){
+ print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc);
+ return -1;
+ }
+ if(rc&WResSts){
+ /*
+ * Don't print; this happens on every WCmdAccWr for some reason.
+ */
+ if(0) print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+w_seek(Ctlr* ctlr, ushort id, ushort offset, int chan)
+{
+ int i, rc;
+ static ushort sel[] = { WR_Sel0, WR_Sel1 };
+ static ushort off[] = { WR_Off0, WR_Off1 };
+
+ if(chan != 0 && chan != 1)
+ panic("wavelan: bad chan\n");
+ csr_outs(ctlr, sel[chan], id);
+ csr_outs(ctlr, off[chan], offset);
+ for (i=0; i<WTmOut; i++){
+ rc = csr_ins(ctlr, off[chan]);
+ if((rc & (WBusyOff|WErrOff)) == 0)
+ return 0;
+ }
+ return -1;
+}
+
+int
+w_inltv(Ctlr* ctlr, Wltv* ltv)
+{
+ int len;
+ ushort code;
+
+ if(w_cmd(ctlr, WCmdAccRd, ltv->type)){
+ DEBUG("wavelan: access read failed\n");
+ return -1;
+ }
+ if(w_seek(ctlr,ltv->type,0,1)){
+ DEBUG("wavelan: seek failed\n");
+ return -1;
+ }
+ len = csr_ins(ctlr, WR_Data1);
+ if(len > ltv->len)
+ return -1;
+ ltv->len = len;
+ if((code=csr_ins(ctlr, WR_Data1)) != ltv->type){
+ USED(code);
+ DEBUG("wavelan: type %x != code %x\n",ltv->type,code);
+ return -1;
+ }
+ if(ltv->len > 0)
+ csr_inss(ctlr, WR_Data1, &ltv->val, ltv->len-1);
+
+ return 0;
+}
+
+static void
+w_outltv(Ctlr* ctlr, Wltv* ltv)
+{
+ if(w_seek(ctlr,ltv->type, 0, 1))
+ return;
+ csr_outss(ctlr, WR_Data1, ltv, ltv->len+1);
+ w_cmd(ctlr, WCmdAccWr, ltv->type);
+}
+
+void
+ltv_outs(Ctlr* ctlr, int type, ushort val)
+{
+ Wltv ltv;
+
+ ltv.len = 2;
+ ltv.type = type;
+ ltv.val = val;
+ w_outltv(ctlr, &ltv);
+}
+
+int
+ltv_ins(Ctlr* ctlr, int type)
+{
+ Wltv ltv;
+
+ ltv.len = 2;
+ ltv.type = type;
+ ltv.val = 0;
+ if(w_inltv(ctlr, &ltv))
+ return -1;
+ return ltv.val;
+}
+
+static void
+ltv_outstr(Ctlr* ctlr, int type, char* val)
+{
+ Wltv ltv;
+ int len;
+
+ len = strlen(val);
+ if(len > sizeof(ltv.s))
+ len = sizeof(ltv.s);
+ memset(&ltv, 0, sizeof(ltv));
+ ltv.len = (sizeof(ltv.type)+sizeof(ltv.slen)+sizeof(ltv.s))/2;
+ ltv.type = type;
+
+// This should be ltv.slen = len; according to Axel Belinfante
+ ltv.slen = len;
+
+ strncpy(ltv.s, val, len);
+ w_outltv(ctlr, &ltv);
+}
+
+static char Unkname[] = "who knows";
+static char Nilname[] = "card does not tell";
+
+static char*
+ltv_inname(Ctlr* ctlr, int type)
+{
+ static Wltv ltv;
+ int len;
+
+ memset(&ltv,0,sizeof(ltv));
+ ltv.len = WNameLen/2+2;
+ ltv.type = type;
+ if(w_inltv(ctlr, &ltv))
+ return Unkname;
+ len = ltv.slen;
+ if(len == 0 || ltv.s[0] == 0)
+ return Nilname;
+ if(len >= sizeof ltv.s)
+ len = sizeof ltv.s - 1;
+ ltv.s[len] = '\0';
+ return ltv.s;
+}
+
+static int
+w_read(Ctlr* ctlr, int type, int off, void* buf, ulong len)
+{
+ if(w_seek(ctlr, type, off, 1)){
+ DEBUG("wavelan: w_read: seek failed");
+ return 0;
+ }
+ csr_inss(ctlr, WR_Data1, buf, len/2);
+
+ return len;
+}
+
+static int
+w_write(Ctlr* ctlr, int type, int off, void* buf, ulong len)
+{
+ if(w_seek(ctlr, type, off, 0)){
+ DEBUG("wavelan: w_write: seek failed\n");
+ return 0;
+ }
+
+ csr_outss(ctlr, WR_Data0, buf, len/2);
+ csr_outs(ctlr, WR_Data0, 0xdead);
+ csr_outs(ctlr, WR_Data0, 0xbeef);
+ if(w_seek(ctlr, type, off + len, 0)){
+ DEBUG("wavelan: write seek failed\n");
+ return 0;
+ }
+ if(csr_ins(ctlr, WR_Data0) == 0xdead && csr_ins(ctlr, WR_Data0) == 0xbeef)
+ return len;
+
+ DEBUG("wavelan: Hermes bug byte.\n");
+ return 0;
+}
+
+static int
+w_alloc(Ctlr* ctlr, int len)
+{
+ int rc;
+ int i,j;
+
+ if(w_cmd(ctlr, WCmdMalloc, len)==0)
+ for (i = 0; i<WTmOut; i++)
+ if(csr_ins(ctlr, WR_EvSts) & WAllocEv){
+ csr_ack(ctlr, WAllocEv);
+ rc=csr_ins(ctlr, WR_Alloc);
+ if(w_seek(ctlr, rc, 0, 0))
+ return -1;
+ len = len/2;
+ for (j=0; j<len; j++)
+ csr_outs(ctlr, WR_Data0, 0);
+ return rc;
+ }
+ return -1;
+}
+
+static int
+w_enable(Ether* ether)
+{
+ Wltv ltv;
+ Ctlr* ctlr = (Ctlr*) ether->ctlr;
+
+ if(!ctlr)
+ return -1;
+
+ w_intdis(ctlr);
+ w_cmd(ctlr, WCmdDis, 0);
+ w_intdis(ctlr);
+ if(w_cmd(ctlr, WCmdIni, 0))
+ return -1;
+ w_intdis(ctlr);
+
+ ltv_outs(ctlr, WTyp_Tick, 8);
+ ltv_outs(ctlr, WTyp_MaxLen, ctlr->maxlen);
+ ltv_outs(ctlr, WTyp_Ptype, ctlr->ptype);
+ ltv_outs(ctlr, WTyp_CreateIBSS, ctlr->createibss);
+ ltv_outs(ctlr, WTyp_RtsThres, ctlr->rtsthres);
+ ltv_outs(ctlr, WTyp_TxRate, ctlr->txrate);
+ ltv_outs(ctlr, WTyp_ApDens, ctlr->apdensity);
+ ltv_outs(ctlr, WTyp_PMWait, ctlr->pmwait);
+ ltv_outs(ctlr, WTyp_PM, ctlr->pmena);
+ if(*ctlr->netname)
+ ltv_outstr(ctlr, WTyp_NetName, ctlr->netname);
+ if(*ctlr->wantname)
+ ltv_outstr(ctlr, WTyp_WantName, ctlr->wantname);
+ ltv_outs(ctlr, WTyp_Chan, ctlr->chan);
+ if(*ctlr->nodename)
+ ltv_outstr(ctlr, WTyp_NodeName, ctlr->nodename);
+ ltv.len = 4;
+ ltv.type = WTyp_Mac;
+ memmove(ltv.addr, ether->ea, Eaddrlen);
+ w_outltv(ctlr, &ltv);
+
+ ltv_outs(ctlr, WTyp_Prom, (ether->prom?1:0));
+
+ if(ctlr->hascrypt && ctlr->crypt){
+ ltv_outs(ctlr, WTyp_Crypt, ctlr->crypt);
+ ltv_outs(ctlr, WTyp_TxKey, ctlr->txkey);
+ w_outltv(ctlr, &ctlr->keys);
+ ltv_outs(ctlr, WTyp_XClear, ctlr->xclear);
+ }
+
+ // BUG: set multicast addresses
+
+ if(w_cmd(ctlr, WCmdEna, 0)){
+ DEBUG("wavelan: Enable failed");
+ return -1;
+ }
+ ctlr->txdid = w_alloc(ctlr, 1518 + sizeof(WFrame) + 8);
+ ctlr->txmid = w_alloc(ctlr, 1518 + sizeof(WFrame) + 8);
+ if(ctlr->txdid == -1 || ctlr->txmid == -1)
+ DEBUG("wavelan: alloc failed");
+ ctlr->txbusy = 0;
+ w_intena(ctlr);
+ return 0;
+}
+
+static void
+w_rxdone(Ether* ether)
+{
+ Ctlr* ctlr = (Ctlr*) ether->ctlr;
+ int len, sp;
+ WFrame f;
+ Block* bp=0;
+ Etherpkt* ep;
+
+ sp = csr_ins(ctlr, WR_RXId);
+ len = w_read(ctlr, sp, 0, &f, sizeof(f));
+ if(len == 0){
+ DEBUG("wavelan: read frame error\n");
+ goto rxerror;
+ }
+ if(f.sts&WF_Err){
+ goto rxerror;
+ }
+ switch(f.sts){
+ case WF_1042:
+ case WF_Tunnel:
+ case WF_WMP:
+ len = f.dlen + WSnapHdrLen;
+ bp = iallocb(ETHERHDRSIZE + len + 2);
+ if(!bp)
+ goto rxerror;
+ ep = (Etherpkt*) bp->wp;
+ memmove(ep->d, f.addr1, Eaddrlen);
+ memmove(ep->s, f.addr2, Eaddrlen);
+ memmove(ep->type,&f.type,2);
+ bp->wp += ETHERHDRSIZE;
+ if(w_read(ctlr, sp, WF_802_11_Off, bp->wp, len+2) == 0){
+ DEBUG("wavelan: read 802.11 error\n");
+ goto rxerror;
+ }
+ bp->wp = bp->rp+(ETHERHDRSIZE+f.dlen);
+ break;
+ default:
+ len = ETHERHDRSIZE + f.dlen + 2;
+ bp = iallocb(len);
+ if(!bp)
+ goto rxerror;
+ if(w_read(ctlr, sp, WF_802_3_Off, bp->wp, len) == 0){
+ DEBUG("wavelan: read 800.3 error\n");
+ goto rxerror;
+ }
+ bp->wp += len;
+ }
+
+ ctlr->nrx++;
+ etheriq(ether,bp,1);
+ ctlr->signal = ((ctlr->signal*15)+((f.qinfo>>8) & 0xFF))/16;
+ ctlr->noise = ((ctlr->noise*15)+(f.qinfo & 0xFF))/16;
+ return;
+
+rxerror:
+ freeb(bp);
+ ctlr->nrxerr++;
+}
+
+static void
+w_txstart(Ether* ether)
+{
+ Etherpkt *pkt;
+ Ctlr *ctlr;
+ Block *bp;
+ int len, off;
+
+ if((ctlr = ether->ctlr) == nil || (ctlr->state & (Attached|Power)) != (Attached|Power) || ctlr->txbusy)
+ return;
+
+ if((bp = qget(ether->oq)) == nil)
+ return;
+ pkt = (Etherpkt*)bp->rp;
+
+ //
+ // If the packet header type field is > 1500 it is an IP or
+ // ARP datagram, otherwise it is an 802.3 packet. See RFC1042.
+ //
+ memset(&ctlr->txf, 0, sizeof(ctlr->txf));
+ if(((pkt->type[0]<<8)|pkt->type[1]) > 1500){
+ ctlr->txf.framectl = WF_Data;
+ memmove(ctlr->txf.addr1, pkt->d, Eaddrlen);
+ memmove(ctlr->txf.addr2, pkt->s, Eaddrlen);
+ memmove(ctlr->txf.dstaddr, pkt->d, Eaddrlen);
+ memmove(ctlr->txf.srcaddr, pkt->s, Eaddrlen);
+ memmove(&ctlr->txf.type, pkt->type, 2);
+ bp->rp += ETHERHDRSIZE;
+ len = BLEN(bp);
+ off = WF_802_11_Off;
+ ctlr->txf.dlen = len+ETHERHDRSIZE-WSnapHdrLen;
+ hnputs((uchar*)&ctlr->txf.dat[0], WSnap0);
+ hnputs((uchar*)&ctlr->txf.dat[1], WSnap1);
+ hnputs((uchar*)&ctlr->txf.len, len+ETHERHDRSIZE-WSnapHdrLen);
+ }
+ else{
+ len = BLEN(bp);
+ off = WF_802_3_Off;
+ ctlr->txf.dlen = len;
+ }
+ w_write(ctlr, ctlr->txdid, 0, &ctlr->txf, sizeof(ctlr->txf));
+ w_write(ctlr, ctlr->txdid, off, bp->rp, len+2);
+
+ if(w_cmd(ctlr, WCmdReclaim|WCmdTx, ctlr->txdid)){
+ DEBUG("wavelan: transmit failed\n");
+ ctlr->ntxerr++;
+ }
+ else{
+ ctlr->txbusy = 1;
+ ctlr->txtmout = 2;
+ }
+ freeb(bp);
+}
+
+static void
+w_txdone(Ctlr* ctlr, int sts)
+{
+ ctlr->txbusy = 0;
+ ctlr->txtmout = 0;
+ if(sts & WTxErrEv)
+ ctlr->ntxerr++;
+ else
+ ctlr->ntx++;
+}
+
+/* save the stats info in the ctlr struct */
+static void
+w_stats(Ctlr* ctlr, int len)
+{
+ int i, rc;
+ ulong* p = (ulong*)&ctlr->WStats;
+ ulong* pend = (ulong*)&ctlr->end;
+
+ for (i = 0; i < len && p < pend; i++){
+ rc = csr_ins(ctlr, WR_Data1);
+ if(rc > 0xf000)
+ rc = ~rc & 0xffff;
+ p[i] += rc;
+ }
+}
+
+/* send the base station scan info to any readers */
+static void
+w_scaninfo(Ether* ether, Ctlr *ctlr, int len)
+{
+ int i, j;
+ Netfile **ep, *f, **fp;
+ Block *bp;
+ WScan *wsp;
+ ushort *scanbuf;
+
+ scanbuf = malloc(len*2);
+ if(scanbuf == nil)
+ return;
+
+ for (i = 0; i < len ; i++)
+ scanbuf[i] = csr_ins(ctlr, WR_Data1);
+
+ /* calculate number of samples */
+ len /= 25;
+ if(len == 0)
+ goto out;
+
+ i = ether->scan;
+ ep = &ether->f[Ntypes];
+ for(fp = ether->f; fp < ep && i > 0; fp++){
+ f = *fp;
+ if(f == nil || f->scan == 0)
+ continue;
+
+ bp = iallocb(100*len);
+ if(bp == nil)
+ break;
+ for(j = 0; j < len; j++){
+ wsp = (WScan*)(&scanbuf[j*25]);
+ if(wsp->ssid_len > 32)
+ wsp->ssid_len = 32;
+ bp->wp = (uchar*)seprint((char*)bp->wp, (char*)bp->lim,
+ "ssid=%.*s;bssid=%E;signal=%d;noise=%d;chan=%d%s\n",
+ wsp->ssid_len, wsp->ssid, wsp->bssid, wsp->signal,
+ wsp->noise, wsp->chan, (wsp->capinfo&(1<<4))?";wep":"");
+ }
+ qpass(f->in, bp);
+ i--;
+ }
+out:
+ free(scanbuf);
+}
+
+static int
+w_info(Ether *ether, Ctlr* ctlr)
+{
+ int sp;
+ Wltv ltv;
+
+ sp = csr_ins(ctlr, WR_InfoId);
+ ltv.len = ltv.type = 0;
+ w_read(ctlr, sp, 0, &ltv, 4);
+ ltv.len--;
+ switch(ltv.type){
+ case WTyp_Stats:
+ w_stats(ctlr, ltv.len);
+ return 0;
+ case WTyp_Scan:
+ w_scaninfo(ether, ctlr, ltv.len);
+ return 0;
+ }
+ return -1;
+}
+
+/* set scanning interval */
+static void
+w_scanbs(void *a, uint secs)
+{
+ Ether *ether = a;
+ Ctlr* ctlr = (Ctlr*) ether->ctlr;
+
+ ctlr->scanticks = secs*(1000/MSperTick);
+}
+
+static void
+w_intr(Ether *ether)
+{
+ int rc, txid;
+ Ctlr* ctlr = (Ctlr*) ether->ctlr;
+
+ if((ctlr->state & Power) == 0)
+ return;
+
+ if((ctlr->state & Attached) == 0){
+ csr_ack(ctlr, 0xffff);
+ csr_outs(ctlr, WR_IntEna, 0);
+ return;
+ }
+
+ rc = csr_ins(ctlr, WR_EvSts);
+ csr_ack(ctlr, ~WEvs); // Not interested in them
+ if(rc & WRXEv){
+ w_rxdone(ether);
+ csr_ack(ctlr, WRXEv);
+ }
+ if(rc & WTXEv){
+ w_txdone(ctlr, rc);
+ csr_ack(ctlr, WTXEv);
+ }
+ if(rc & WAllocEv){
+ ctlr->nalloc++;
+ txid = csr_ins(ctlr, WR_Alloc);
+ csr_ack(ctlr, WAllocEv);
+ if(txid == ctlr->txdid){
+ if((rc & WTXEv) == 0)
+ w_txdone(ctlr, rc);
+ }
+ }
+ if(rc & WInfoEv){
+ ctlr->ninfo++;
+ w_info(ether, ctlr);
+ csr_ack(ctlr, WInfoEv);
+ }
+ if(rc & WTxErrEv){
+ w_txdone(ctlr, rc);
+ csr_ack(ctlr, WTxErrEv);
+ }
+ if(rc & WIDropEv){
+ ctlr->nidrop++;
+ csr_ack(ctlr, WIDropEv);
+ }
+ w_txstart(ether);
+}
+
+// Watcher to ensure that the card still works properly and
+// to request WStats updates once a minute.
+// BUG: it runs much more often, see the comment below.
+
+static void
+w_timer(void* arg)
+{
+ Ether* ether = (Ether*) arg;
+ Ctlr* ctlr = (Ctlr*)ether->ctlr;
+
+ ctlr->timerproc = up;
+ for(;;){
+ tsleep(&up->sleep, return0, 0, MSperTick);
+ ctlr = (Ctlr*)ether->ctlr;
+ if(ctlr == 0)
+ break;
+ if((ctlr->state & (Attached|Power)) != (Attached|Power))
+ continue;
+ ctlr->ticks++;
+
+ ilock(ctlr);
+
+ // Seems that the card gets frames BUT does
+ // not send the interrupt; this is a problem because
+ // I suspect it runs out of receive buffers and
+ // stops receiving until a transmit watchdog
+ // reenables the card.
+ // The problem is serious because it leads to
+ // poor rtts.
+ // This can be seen clearly by commenting out
+ // the next if and doing a ping: it will stop
+ // receiving (although the icmp replies are being
+ // issued from the remote) after a few seconds.
+ // Of course this `bug' could be because I'm reading
+ // the card frames in the wrong way; due to the
+ // lack of documentation I cannot know.
+
+ if(csr_ins(ctlr, WR_EvSts)&WEvs){
+ ctlr->tickintr++;
+ w_intr(ether);
+ }
+
+ if((ctlr->ticks % 10) == 0) {
+ if(ctlr->txtmout && --ctlr->txtmout == 0){
+ ctlr->nwatchdogs++;
+ w_txdone(ctlr, WTxErrEv);
+ if(w_enable(ether)){
+ DEBUG("wavelan: wdog enable failed\n");
+ }
+ w_txstart(ether);
+ }
+ if((ctlr->ticks % 120) == 0)
+ if(ctlr->txbusy == 0)
+ w_cmd(ctlr, WCmdEnquire, WTyp_Stats);
+ if(ctlr->scanticks > 0)
+ if((ctlr->ticks % ctlr->scanticks) == 0)
+ if(ctlr->txbusy == 0)
+ w_cmd(ctlr, WCmdEnquire, WTyp_Scan);
+ }
+ iunlock(ctlr);
+ }
+ pexit("terminated", 0);
+}
+
+void
+w_multicast(void *ether, uchar*, int add)
+{
+ /* BUG: use controller's multicast filter */
+ if (add)
+ w_promiscuous(ether, 1);
+}
+
+void
+w_attach(Ether* ether)
+{
+ Ctlr* ctlr;
+ char name[64];
+ int rc;
+
+ if(ether->ctlr == 0)
+ return;
+
+ snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno);
+ ctlr = (Ctlr*) ether->ctlr;
+ if((ctlr->state & Attached) == 0){
+ ilock(ctlr);
+ rc = w_enable(ether);
+ iunlock(ctlr);
+ if(rc == 0){
+ ctlr->state |= Attached;
+ kproc(name, w_timer, ether);
+ } else
+ print("#l%d: enable failed\n",ether->ctlrno);
+ }
+}
+
+void
+w_detach(Ether* ether)
+{
+ Ctlr* ctlr;
+ char name[64];
+
+ if(ether->ctlr == nil)
+ return;
+
+ snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno);
+ ctlr = (Ctlr*) ether->ctlr;
+ if(ctlr->state & Attached){
+ ilock(ctlr);
+ w_intdis(ctlr);
+ if(ctlr->timerproc){
+ if(!postnote(ctlr->timerproc, 1, "kill", NExit))
+ print("timerproc note not posted\n");
+ print("w_detach, killing 0x%p\n", ctlr->timerproc);
+ }
+ ctlr->state &= ~Attached;
+ iunlock(ctlr);
+ }
+ ether->ctlr = nil;
+}
+
+void
+w_power(Ether* ether, int on)
+{
+ Ctlr *ctlr;
+
+ ctlr = (Ctlr*) ether->ctlr;
+ ilock(ctlr);
+iprint("w_power %d\n", on);
+ if(on){
+ if((ctlr->state & Power) == 0){
+ if (wavelanreset(ether, ctlr) < 0){
+ iprint("w_power: reset failed\n");
+ iunlock(ctlr);
+ w_detach(ether);
+ free(ctlr);
+ return;
+ }
+ if(ctlr->state & Attached)
+ w_enable(ether);
+ ctlr->state |= Power;
+ }
+ }else{
+ if(ctlr->state & Power){
+ if(ctlr->state & Attached)
+ w_intdis(ctlr);
+ ctlr->state &= ~Power;
+ }
+ }
+ iunlock(ctlr);
+}
+
+#define PRINTSTAT(fmt,val) l += snprint(p+l, READSTR-l, (fmt), (val))
+#define PRINTSTR(fmt) l += snprint(p+l, READSTR-l, (fmt))
+
+long
+w_ifstat(Ether* ether, void* a, long n, ulong offset)
+{
+ Ctlr *ctlr = (Ctlr*) ether->ctlr;
+ char *k, *p;
+ int i, l, txid;
+
+ ether->oerrs = ctlr->ntxerr;
+ ether->crcs = ctlr->nrxfcserr;
+ ether->frames = 0;
+ ether->buffs = ctlr->nrxdropnobuf;
+ ether->overflows = 0;
+
+ //
+ // Offset must be zero or there's a possibility the
+ // new data won't match the previous read.
+ //
+ if(n == 0 || offset != 0)
+ return 0;
+
+ p = malloc(READSTR);
+ l = 0;
+
+ PRINTSTAT("Signal: %d\n", ctlr->signal-149);
+ PRINTSTAT("Noise: %d\n", ctlr->noise-149);
+ PRINTSTAT("SNR: %ud\n", ctlr->signal-ctlr->noise);
+ PRINTSTAT("Interrupts: %lud\n", ctlr->nints);
+ PRINTSTAT("Double Interrupts: %lud\n", ctlr->ndoubleint);
+ PRINTSTAT("TxPackets: %lud\n", ctlr->ntx);
+ PRINTSTAT("RxPackets: %lud\n", ctlr->nrx);
+ PRINTSTAT("TxErrors: %lud\n", ctlr->ntxerr);
+ PRINTSTAT("RxErrors: %lud\n", ctlr->nrxerr);
+ PRINTSTAT("TxRequests: %lud\n", ctlr->ntxrq);
+ PRINTSTAT("AllocEvs: %lud\n", ctlr->nalloc);
+ PRINTSTAT("InfoEvs: %lud\n", ctlr->ninfo);
+ PRINTSTAT("InfoDrop: %lud\n", ctlr->nidrop);
+ PRINTSTAT("WatchDogs: %lud\n", ctlr->nwatchdogs);
+ PRINTSTAT("Ticks: %ud\n", ctlr->ticks);
+ PRINTSTAT("TickIntr: %ud\n", ctlr->tickintr);
+ k = ((ctlr->state & Attached) ? "attached" : "not attached");
+ PRINTSTAT("Card %s", k);
+ k = ((ctlr->state & Power) ? "on" : "off");
+ PRINTSTAT(", power %s", k);
+ k = ((ctlr->txbusy)? ", txbusy" : "");
+ PRINTSTAT("%s\n", k);
+
+ if(ctlr->hascrypt){
+ PRINTSTR("Keys: ");
+ for (i = 0; i < WNKeys; i++){
+ if(ctlr->keys.keys[i].len == 0)
+ PRINTSTR("none ");
+ else if(SEEKEYS == 0)
+ PRINTSTR("set ");
+ else
+ PRINTSTAT("%s ", ctlr->keys.keys[i].dat);
+ }
+ PRINTSTR("\n");
+ }
+
+ // real card stats
+ ilock(ctlr);
+ PRINTSTR("\nCard stats: \n");
+ PRINTSTAT("Status: %ux\n", csr_ins(ctlr, WR_Sts));
+ PRINTSTAT("Event status: %ux\n", csr_ins(ctlr, WR_EvSts));
+ i = ltv_ins(ctlr, WTyp_Ptype);
+ PRINTSTAT("Port type: %d\n", i);
+ PRINTSTAT("Transmit rate: %d\n", ltv_ins(ctlr, WTyp_TxRate));
+ PRINTSTAT("Current Transmit rate: %d\n",
+ ltv_ins(ctlr, WTyp_CurTxRate));
+ PRINTSTAT("Channel: %d\n", ltv_ins(ctlr, WTyp_Chan));
+ PRINTSTAT("AP density: %d\n", ltv_ins(ctlr, WTyp_ApDens));
+ PRINTSTAT("Promiscuous mode: %d\n", ltv_ins(ctlr, WTyp_Prom));
+ if(i == WPTypeAdHoc)
+ PRINTSTAT("SSID name: %s\n", ltv_inname(ctlr, WTyp_NetName));
+ else {
+ Wltv ltv;
+ PRINTSTAT("Current name: %s\n", ltv_inname(ctlr, WTyp_CurName));
+ ltv.type = WTyp_BaseID;
+ ltv.len = 4;
+ if(w_inltv(ctlr, &ltv))
+ print("#l%d: unable to read base station mac addr\n", ether->ctlrno);
+ l += snprint(p+l, READSTR-l, "Base station: %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
+ ltv.addr[0], ltv.addr[1], ltv.addr[2], ltv.addr[3], ltv.addr[4], ltv.addr[5]);
+ }
+ PRINTSTAT("Net name: %s\n", ltv_inname(ctlr, WTyp_WantName));
+ PRINTSTAT("Node name: %s\n", ltv_inname(ctlr, WTyp_NodeName));
+ if(ltv_ins(ctlr, WTyp_HasCrypt) == 0)
+ PRINTSTR("WEP: not supported\n");
+ else {
+ if(ltv_ins(ctlr, WTyp_Crypt) == 0)
+ PRINTSTR("WEP: disabled\n");
+ else{
+ PRINTSTR("WEP: enabled\n");
+ k = ((ctlr->xclear)? "excluded": "included");
+ PRINTSTAT("Clear packets: %s\n", k);
+ txid = ltv_ins(ctlr, WTyp_TxKey);
+ PRINTSTAT("Transmit key id: %d\n", txid);
+ }
+ }
+ iunlock(ctlr);
+
+ PRINTSTAT("ntxuframes: %lud\n", ctlr->ntxuframes);
+ PRINTSTAT("ntxmframes: %lud\n", ctlr->ntxmframes);
+ PRINTSTAT("ntxfrags: %lud\n", ctlr->ntxfrags);
+ PRINTSTAT("ntxubytes: %lud\n", ctlr->ntxubytes);
+ PRINTSTAT("ntxmbytes: %lud\n", ctlr->ntxmbytes);
+ PRINTSTAT("ntxdeferred: %lud\n", ctlr->ntxdeferred);
+ PRINTSTAT("ntxsretries: %lud\n", ctlr->ntxsretries);
+ PRINTSTAT("ntxmultiretries: %lud\n", ctlr->ntxmultiretries);
+ PRINTSTAT("ntxretrylimit: %lud\n", ctlr->ntxretrylimit);
+ PRINTSTAT("ntxdiscards: %lud\n", ctlr->ntxdiscards);
+ PRINTSTAT("nrxuframes: %lud\n", ctlr->nrxuframes);
+ PRINTSTAT("nrxmframes: %lud\n", ctlr->nrxmframes);
+ PRINTSTAT("nrxfrags: %lud\n", ctlr->nrxfrags);
+ PRINTSTAT("nrxubytes: %lud\n", ctlr->nrxubytes);
+ PRINTSTAT("nrxmbytes: %lud\n", ctlr->nrxmbytes);
+ PRINTSTAT("nrxfcserr: %lud\n", ctlr->nrxfcserr);
+ PRINTSTAT("nrxdropnobuf: %lud\n", ctlr->nrxdropnobuf);
+ PRINTSTAT("nrxdropnosa: %lud\n", ctlr->nrxdropnosa);
+ PRINTSTAT("nrxcantdecrypt: %lud\n", ctlr->nrxcantdecrypt);
+ PRINTSTAT("nrxmsgfrag: %lud\n", ctlr->nrxmsgfrag);
+ PRINTSTAT("nrxmsgbadfrag: %lud\n", ctlr->nrxmsgbadfrag);
+ USED(l);
+ n = readstr(offset, a, n, p);
+ free(p);
+ return n;
+}
+#undef PRINTSTR
+#undef PRINTSTAT
+
+static int
+parsekey(WKey* key, char* a)
+{
+ int i, k, len, n;
+ char buf[WMaxKeyLen];
+
+ len = strlen(a);
+ if(len == WMinKeyLen || len == WMaxKeyLen){
+ memset(key->dat, 0, sizeof(key->dat));
+ memmove(key->dat, a, len);
+ key->len = len;
+
+ return 0;
+ }
+ else if(len == WMinKeyLen*2 || len == WMaxKeyLen*2){
+ k = 0;
+ for(i = 0; i < len; i++){
+ if(*a >= '0' && *a <= '9')
+ n = *a++ - '0';
+ else if(*a >= 'a' && *a <= 'f')
+ n = *a++ - 'a' + 10;
+ else if(*a >= 'A' && *a <= 'F')
+ n = *a++ - 'A' + 10;
+ else
+ return -1;
+
+ if(i & 1){
+ buf[k] |= n;
+ k++;
+ }
+ else
+ buf[k] = n<<4;
+ }
+
+ memset(key->dat, 0, sizeof(key->dat));
+ memmove(key->dat, buf, k);
+ key->len = k;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+w_option(Ctlr* ctlr, char* buf, long n)
+{
+ char *p;
+ int i, r;
+ Cmdbuf *cb;
+
+ r = 0;
+
+ cb = parsecmd(buf, n);
+ if(cb->nf < 2)
+ r = -1;
+ else if(cistrcmp(cb->f[0], "essid") == 0){
+ if(cistrcmp(cb->f[1],"default") == 0)
+ p = "";
+ else
+ p = cb->f[1];
+ if(ctlr->ptype == WPTypeAdHoc){
+ memset(ctlr->netname, 0, sizeof(ctlr->netname));
+ strncpy(ctlr->netname, p, WNameLen);
+ }
+ else{
+ memset(ctlr->wantname, 0, sizeof(ctlr->wantname));
+ strncpy(ctlr->wantname, p, WNameLen);
+ }
+ }
+ else if(cistrcmp(cb->f[0], "station") == 0){
+ memset(ctlr->nodename, 0, sizeof(ctlr->nodename));
+ strncpy(ctlr->nodename, cb->f[1], WNameLen);
+ }
+ else if(cistrcmp(cb->f[0], "channel") == 0){
+ if((i = atoi(cb->f[1])) >= 1 && i <= 16)
+ ctlr->chan = i;
+ else
+ r = -1;
+ }
+ else if(cistrcmp(cb->f[0], "mode") == 0){
+ if(cistrcmp(cb->f[1], "managed") == 0)
+ ctlr->ptype = WPTypeManaged;
+ else if(cistrcmp(cb->f[1], "wds") == 0)
+ ctlr->ptype = WPTypeWDS;
+ else if(cistrcmp(cb->f[1], "adhoc") == 0)
+ ctlr->ptype = WPTypeAdHoc;
+ else if((i = atoi(cb->f[1])) >= 0 && i <= 3)
+ ctlr->ptype = i;
+ else
+ r = -1;
+ }
+ else if(cistrcmp(cb->f[0], "ibss") == 0){
+ if(cistrcmp(cb->f[1], "on") == 0)
+ ctlr->createibss = 1;
+ else
+ ctlr->createibss = 0;
+ }
+ else if(cistrcmp(cb->f[0], "crypt") == 0){
+ if(cistrcmp(cb->f[1], "off") == 0)
+ ctlr->crypt = 0;
+ else if(cistrcmp(cb->f[1], "on") == 0 && ctlr->hascrypt)
+ ctlr->crypt = 1;
+ else
+ r = -1;
+ }
+ else if(cistrcmp(cb->f[0], "clear") == 0){
+ if(cistrcmp(cb->f[1], "on") == 0)
+ ctlr->xclear = 0;
+ else if(cistrcmp(cb->f[1], "off") == 0 && ctlr->hascrypt)
+ ctlr->xclear = 1;
+ else
+ r = -1;
+ }
+ else if(cistrncmp(cb->f[0], "key", 3) == 0){
+ if((i = atoi(cb->f[0]+3)) >= 1 && i <= WNKeys){
+ ctlr->txkey = i-1;
+ if(parsekey(&ctlr->keys.keys[ctlr->txkey], cb->f[1]))
+ r = -1;
+ }
+ else
+ r = -1;
+ }
+ else if(cistrcmp(cb->f[0], "txkey") == 0){
+ if((i = atoi(cb->f[1])) >= 1 && i <= WNKeys)
+ ctlr->txkey = i-1;
+ else
+ r = -1;
+ }
+ else if(cistrcmp(cb->f[0], "pm") == 0){
+ if(cistrcmp(cb->f[1], "off") == 0)
+ ctlr->pmena = 0;
+ else if(cistrcmp(cb->f[1], "on") == 0){
+ ctlr->pmena = 1;
+ if(cb->nf == 3){
+ i = atoi(cb->f[2]);
+ // check range here? what are the units?
+ ctlr->pmwait = i;
+ }
+ }
+ else
+ r = -1;
+ }
+ else
+ r = -2;
+ free(cb);
+
+ return r;
+}
+
+long
+w_ctl(Ether* ether, void* buf, long n)
+{
+ Ctlr *ctlr;
+
+ if((ctlr = ether->ctlr) == nil)
+ error(Enonexist);
+ if((ctlr->state & Attached) == 0)
+ error(Eshutdown);
+
+ ilock(ctlr);
+ if(w_option(ctlr, buf, n)){
+ iunlock(ctlr);
+ error(Ebadctl);
+ }
+ if(ctlr->txbusy)
+ w_txdone(ctlr, WTxErrEv);
+ w_enable(ether);
+ w_txstart(ether);
+ iunlock(ctlr);
+
+ return n;
+}
+
+void
+w_transmit(Ether* ether)
+{
+ Ctlr* ctlr = ether->ctlr;
+
+ if(ctlr == 0)
+ return;
+
+ ilock(ctlr);
+ ctlr->ntxrq++;
+ w_txstart(ether);
+ iunlock(ctlr);
+}
+
+void
+w_promiscuous(void* arg, int on)
+{
+ Ether* ether = (Ether*)arg;
+ Ctlr* ctlr = ether->ctlr;
+
+ if(ctlr == nil)
+ error("card not found");
+ if((ctlr->state & Attached) == 0)
+ error("card not attached");
+ ilock(ctlr);
+ ltv_outs(ctlr, WTyp_Prom, (on?1:0));
+ iunlock(ctlr);
+}
+
+void
+w_interrupt(Ureg* ,void* arg)
+{
+ Ether* ether = (Ether*) arg;
+ Ctlr* ctlr = (Ctlr*) ether->ctlr;
+
+ if(ctlr == 0)
+ return;
+ ilock(ctlr);
+ ctlr->nints++;
+ w_intr(ether);
+ iunlock(ctlr);
+}
+
+int
+wavelanreset(Ether* ether, Ctlr *ctlr)
+{
+ Wltv ltv;
+
+ iprint("wavelanreset, iob 0x%ux\n", ctlr->iob);
+ w_intdis(ctlr);
+ if(w_cmd(ctlr,WCmdIni,0)){
+ iprint("#l%d: init failed\n", ether->ctlrno);
+ return -1;
+ }
+ w_intdis(ctlr);
+ ltv_outs(ctlr, WTyp_Tick, 8);
+
+ ctlr->chan = 0;
+ ctlr->ptype = WDfltPType;
+ ctlr->txkey = 0;
+ ctlr->createibss = 0;
+ ctlr->keys.len = sizeof(WKey)*WNKeys/2 + 1;
+ ctlr->keys.type = WTyp_Keys;
+ if(ctlr->hascrypt = ltv_ins(ctlr, WTyp_HasCrypt))
+ ctlr->crypt = 1;
+ *ctlr->netname = *ctlr->wantname = 0;
+ strcpy(ctlr->nodename, "Plan 9 STA");
+
+ ctlr->netname[WNameLen-1] = 0;
+ ctlr->wantname[WNameLen-1] = 0;
+ ctlr->nodename[WNameLen-1] =0;
+
+ ltv.type = WTyp_Mac;
+ ltv.len = 4;
+ if(w_inltv(ctlr, &ltv)){
+ iprint("#l%d: unable to read mac addr\n",
+ ether->ctlrno);
+ return -1;
+ }
+ memmove(ether->ea, ltv.addr, Eaddrlen);
+
+ if(ctlr->chan == 0)
+ ctlr->chan = ltv_ins(ctlr, WTyp_Chan);
+ ctlr->apdensity = WDfltApDens;
+ ctlr->rtsthres = WDfltRtsThres;
+ ctlr->txrate = WDfltTxRate;
+ ctlr->maxlen = WMaxLen;
+ ctlr->pmena = 0;
+ ctlr->pmwait = 100;
+ ctlr->signal = 1;
+ ctlr->noise = 1;
+ ctlr->state |= Power;
+
+ // free old Ctlr struct if resetting after suspend
+ if(ether->ctlr && ether->ctlr != ctlr)
+ free(ether->ctlr);
+
+ // link to ether
+ ether->ctlr = ctlr;
+ ether->mbps = 10;
+ ether->attach = w_attach;
+ ether->detach = w_detach;
+ ether->interrupt = w_interrupt;
+ ether->transmit = w_transmit;
+ ether->ifstat = w_ifstat;
+ ether->ctl = w_ctl;
+ ether->power = w_power;
+ ether->promiscuous = w_promiscuous;
+ ether->multicast = w_multicast;
+ ether->scanbs = w_scanbs;
+ ether->arg = ether;
+
+ DEBUG("#l%d: irq %d port %lx type %s",
+ ether->ctlrno, ether->irq, ether->port, ether->type);
+ DEBUG(" %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux\n",
+ ether->ea[0], ether->ea[1], ether->ea[2],
+ ether->ea[3], ether->ea[4], ether->ea[5]);
+
+ return 0;
+}
+
+char* wavenames[] = {
+ "WaveLAN/IEEE",
+ "TrueMobile 1150",
+ "Instant Wireless ; Network PC CARD",
+ "Instant Wireless Network PC Card",
+ "Avaya Wireless PC Card",
+ "AirLancer MC-11",
+ "INTERSIL;HFA384x/IEEE;Version 01.02;",
+ nil,
+};
diff --git a/sys/src/9/pc/wavelan.h b/sys/src/9/pc/wavelan.h
new file mode 100755
index 000000000..7f76149e0
--- /dev/null
+++ b/sys/src/9/pc/wavelan.h
@@ -0,0 +1,327 @@
+#define DEBUG if(1){}else print
+
+#define SEEKEYS 0
+
+// Lucent's Length-Type-Value records to talk to the wavelan.
+// most operational parameters are read/set using this.
+enum
+{
+ WTyp_Stats = 0xf100,
+ WTyp_Scan = 0xf101,
+ WTyp_Link = 0xf200,
+ WTyp_Ptype = 0xfc00,
+ WTyp_Mac = 0xfc01,
+ WTyp_WantName = 0xfc02,
+ WTyp_Chan = 0xfc03,
+ WTyp_NetName = 0xfc04,
+ WTyp_ApDens = 0xfc06,
+ WTyp_MaxLen = 0xfc07,
+ WTyp_PM = 0xfc09,
+ WTyp_PMWait = 0xfc0c,
+ WTyp_NodeName = 0xfc0e,
+ WTyp_Crypt = 0xfc20,
+ WTyp_XClear = 0xfc22,
+ WTyp_CreateIBSS = 0xfc81,
+ WTyp_RtsThres = 0xfc83,
+ WTyp_TxRate = 0xfc84,
+ WTx1Mbps = 0x0,
+ WTx2Mbps = 0x1,
+ WTxAuto = 0x3,
+ WTyp_Prom = 0xfc85,
+ WTyp_Keys = 0xfcb0,
+ WTyp_TxKey = 0xfcb1,
+ WTyp_StationID = 0xfd20,
+ WTyp_CurName = 0xfd41,
+ WTyp_BaseID = 0xfd42, // ID of the currently connected-to base station
+ WTyp_CurTxRate = 0xfd44, // Current TX rate
+ WTyp_HasCrypt = 0xfd4f,
+ WTyp_Tick = 0xfce0,
+};
+
+// Controller
+enum
+{
+ WDfltIRQ = 3, // default irq
+ WDfltIOB = 0x180, // default IO base
+
+ WIOLen = 0x40, // Hermes IO length
+
+ WTmOut = 65536, // Cmd time out
+
+ WPTypeManaged = 1,
+ WPTypeWDS = 2,
+ WPTypeAdHoc = 3,
+ WDfltPType = WPTypeManaged,
+
+ WDfltApDens = 1,
+ WDfltRtsThres = 2347, // == disabled
+ WDfltTxRate = WTxAuto, // 2Mbps
+
+ WMaxLen = 2304,
+ WNameLen = 32,
+
+ WNKeys = 4,
+ WKeyLen = 14,
+ WMinKeyLen = 5,
+ WMaxKeyLen = 13,
+
+ // Wavelan hermes registers
+ WR_Cmd = 0x00,
+ WCmdIni = 0x0000,
+ WCmdEna = 0x0001,
+ WCmdDis = 0x0002,
+ WCmdTx = 0x000b,
+ WCmdMalloc = 0x000a,
+ WCmdEnquire = 0x0011,
+ WCmdMsk = 0x003f,
+ WCmdAccRd = 0x0021,
+ WCmdReclaim = 0x0100,
+ WCmdAccWr = 0x0121,
+ WCmdBusy = 0x8000,
+ WR_Parm0 = 0x02,
+ WR_Parm1 = 0x04,
+ WR_Parm2 = 0x06,
+ WR_Sts = 0x08,
+ WR_InfoId = 0x10,
+ WR_Sel0 = 0x18,
+ WR_Sel1 = 0x1a,
+ WR_Off0 = 0x1c,
+ WR_Off1 = 0x1e,
+ WBusyOff = 0x8000,
+ WErrOff = 0x4000,
+ WResSts = 0x7f00,
+ WR_RXId = 0x20,
+ WR_Alloc = 0x22,
+ WR_EvSts = 0x30,
+ WR_IntEna = 0x32,
+ WCmdEv = 0x0010,
+ WRXEv = 0x0001,
+ WTXEv = 0x0002,
+ WTxErrEv = 0x0004,
+ WAllocEv = 0x0008,
+ WInfoEv = 0x0080,
+ WIDropEv = 0x2000,
+ WTickEv = 0x8000,
+ WEvs = WRXEv|WTXEv|WAllocEv|WInfoEv|WIDropEv,
+
+ WR_EvAck = 0x34,
+ WR_Data0 = 0x36,
+ WR_Data1 = 0x38,
+
+ WR_PciCor = 0x26,
+ WR_PciHcr = 0x2E,
+
+ // Frame stuff
+
+ WF_Err = 0x0003,
+ WF_1042 = 0x2000,
+ WF_Tunnel = 0x4000,
+ WF_WMP = 0x6000,
+
+ WF_Data = 0x0008,
+
+ WSnapK1 = 0xaa,
+ WSnapK2 = 0x00,
+ WSnapCtlr = 0x03,
+ WSnap0 = (WSnapK1|(WSnapK1<<8)),
+ WSnap1 = (WSnapK2|(WSnapCtlr<<8)),
+ WSnapHdrLen = 6,
+
+ WF_802_11_Off = 0x44,
+ WF_802_3_Off = 0x2e,
+
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Wltv Wltv;
+typedef struct WFrame WFrame;
+typedef struct Stats Stats;
+typedef struct WStats WStats;
+typedef struct WScan WScan;
+typedef struct WKey WKey;
+
+struct WStats
+{
+ ulong ntxuframes; // unicast frames
+ ulong ntxmframes; // multicast frames
+ ulong ntxfrags; // fragments
+ ulong ntxubytes; // unicast bytes
+ ulong ntxmbytes; // multicast bytes
+ ulong ntxdeferred; // deferred transmits
+ ulong ntxsretries; // single retries
+ ulong ntxmultiretries; // multiple retries
+ ulong ntxretrylimit;
+ ulong ntxdiscards;
+ ulong nrxuframes; // unicast frames
+ ulong nrxmframes; // multicast frames
+ ulong nrxfrags; // fragments
+ ulong nrxubytes; // unicast bytes
+ ulong nrxmbytes; // multicast bytes
+ ulong nrxfcserr;
+ ulong nrxdropnobuf;
+ ulong nrxdropnosa;
+ ulong nrxcantdecrypt;
+ ulong nrxmsgfrag;
+ ulong nrxmsgbadfrag;
+ ulong end;
+};
+
+struct WScan
+{
+ ushort chan; /* dss channel */
+ ushort noise; /* average noise in the air */
+ ushort signal; /* signal strength */
+ uchar bssid[Eaddrlen]; /* MAC address of the ap */
+ ushort interval; /* beacon transmit interval */
+ ushort capinfo; /* capability bits (0-ess, 1-ibss, 4-privacy [wep]) */
+ ushort ssid_len; /* ssid length */
+ char ssid[WNameLen]; /* ssid (ap name) */
+};
+
+struct WFrame
+{
+ ushort sts;
+ ushort rsvd0;
+ ushort rsvd1;
+ ushort qinfo;
+ ushort rsvd2;
+ ushort rsvd3;
+ ushort txctl;
+ ushort framectl;
+ ushort id;
+ uchar addr1[Eaddrlen];
+ uchar addr2[Eaddrlen];
+ uchar addr3[Eaddrlen];
+ ushort seqctl;
+ uchar addr4[Eaddrlen];
+ ushort dlen;
+ uchar dstaddr[Eaddrlen];
+ uchar srcaddr[Eaddrlen];
+ ushort len;
+ ushort dat[3];
+ ushort type;
+};
+
+struct WKey
+{
+ ushort len;
+ char dat[WKeyLen];
+};
+
+struct Wltv
+{
+ ushort len;
+ ushort type;
+ union
+ {
+ struct {
+ ushort val;
+ ushort pad;
+ };
+ struct {
+ uchar addr[8];
+ };
+ struct {
+ ushort slen;
+ char s[WNameLen];
+ };
+ struct {
+ char name[WNameLen];
+ };
+ struct {
+ WKey keys[WNKeys];
+ };
+ };
+};
+
+// What the driver thinks. Not what the card thinks.
+struct Stats
+{
+ ulong nints;
+ ulong ndoubleint;
+ ulong nrx;
+ ulong ntx;
+ ulong ntxrq;
+ ulong nrxerr;
+ ulong ntxerr;
+ ulong nalloc; // allocation (reclaim) events
+ ulong ninfo;
+ ulong nidrop;
+ ulong nwatchdogs; // transmit time outs, actually
+ int ticks;
+ int tickintr;
+ int signal;
+ int noise;
+};
+
+enum {
+ Attached = 0x01,
+ Power = 0x02,
+};
+
+struct Ctlr
+{
+ Lock;
+
+ int state; // Attached | Power
+ int slot;
+ int iob;
+ int createibss;
+ int ptype;
+ int apdensity;
+ int rtsthres;
+ int txbusy;
+ int txrate;
+ int txdid;
+ int txmid;
+ int txtmout;
+ int maxlen;
+ int chan;
+ int pmena;
+ int pmwait;
+
+ Proc *timerproc;
+ int scanticks;
+
+ char netname[WNameLen];
+ char wantname[WNameLen];
+ char nodename[WNameLen];
+ WFrame txf;
+ uchar txbuf[1536];
+
+ int hascrypt; // card has encryption
+ int crypt; // encryption off/on
+ int txkey; // transmit key
+ Wltv keys; // default keys
+ int xclear; // exclude clear packets off/on
+
+ int ctlrno;
+
+ ushort *mmb;
+ /* for PCI-based devices */
+ Ctlr *next;
+ int active;
+ Pcidev *pcidev;
+
+ Stats;
+ WStats;
+};
+
+extern char* wavenames[];
+
+void csr_outs(Ctlr*, int, ushort);
+ushort csr_ins(Ctlr*, int);
+void w_intdis(Ctlr*);
+int w_cmd(Ctlr *, ushort, ushort);
+void ltv_outs(Ctlr*, int, ushort);
+int ltv_ins(Ctlr*, int);
+int w_option(Ctlr*, char*, long);
+int w_inltv(Ctlr*, Wltv*);
+void w_attach(Ether*);
+void w_interrupt(Ureg*,void*);
+void w_transmit(Ether*);
+long w_ifstat(Ether*, void*, long, ulong);
+long w_ctl(Ether*, void*, long);
+void w_promiscuous(void*, int);
+void w_multicast(void*, uchar*, int);
+int wavelanreset(Ether*, Ctlr*);
diff --git a/sys/src/9/port/alarm.c b/sys/src/9/port/alarm.c
new file mode 100755
index 000000000..ea4d4e653
--- /dev/null
+++ b/sys/src/9/port/alarm.c
@@ -0,0 +1,101 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+static Alarms alarms;
+static Rendez alarmr;
+
+void
+alarmkproc(void*)
+{
+ Proc *rp;
+ ulong now;
+
+ for(;;){
+ now = MACHP(0)->ticks;
+ qlock(&alarms);
+ while((rp = alarms.head) && rp->alarm <= now){
+ if(rp->alarm != 0L){
+ if(canqlock(&rp->debug)){
+ if(!waserror()){
+ postnote(rp, 0, "alarm", NUser);
+ poperror();
+ }
+ qunlock(&rp->debug);
+ rp->alarm = 0L;
+ }else
+ break;
+ }
+ alarms.head = rp->palarm;
+ }
+ qunlock(&alarms);
+
+ sleep(&alarmr, return0, 0);
+ }
+}
+
+/*
+ * called every clock tick
+ */
+void
+checkalarms(void)
+{
+ Proc *p;
+ ulong now;
+
+ p = alarms.head;
+ now = MACHP(0)->ticks;
+
+ if(p && p->alarm <= now)
+ wakeup(&alarmr);
+}
+
+ulong
+procalarm(ulong time)
+{
+ Proc **l, *f;
+ ulong when, old;
+
+ if(up->alarm)
+ old = tk2ms(up->alarm - MACHP(0)->ticks);
+ else
+ old = 0;
+ if(time == 0) {
+ up->alarm = 0;
+ return old;
+ }
+ when = ms2tk(time)+MACHP(0)->ticks;
+
+ qlock(&alarms);
+ l = &alarms.head;
+ for(f = *l; f; f = f->palarm) {
+ if(up == f){
+ *l = f->palarm;
+ break;
+ }
+ l = &f->palarm;
+ }
+
+ up->palarm = 0;
+ if(alarms.head) {
+ l = &alarms.head;
+ for(f = *l; f; f = f->palarm) {
+ if(f->alarm > when) {
+ up->palarm = f;
+ *l = up;
+ goto done;
+ }
+ l = &f->palarm;
+ }
+ *l = up;
+ }
+ else
+ alarms.head = up;
+done:
+ up->alarm = when;
+ qunlock(&alarms);
+
+ return old;
+}
diff --git a/sys/src/9/port/alloc.c b/sys/src/9/port/alloc.c
new file mode 100755
index 000000000..ed9797967
--- /dev/null
+++ b/sys/src/9/port/alloc.c
@@ -0,0 +1,315 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include <pool.h>
+
+static void poolprint(Pool*, char*, ...);
+static void ppanic(Pool*, char*, ...);
+static void plock(Pool*);
+static void punlock(Pool*);
+
+typedef struct Private Private;
+struct Private {
+ Lock lk;
+ char msg[256]; /* a rock for messages to be printed at unlock */
+};
+
+static Private pmainpriv;
+static Pool pmainmem = {
+ .name= "Main",
+ .maxsize= 4*1024*1024,
+ .minarena= 128*1024,
+ .quantum= 32,
+ .alloc= xalloc,
+ .merge= xmerge,
+ .flags= POOL_TOLERANCE,
+
+ .lock= plock,
+ .unlock= punlock,
+ .print= poolprint,
+ .panic= ppanic,
+
+ .private= &pmainpriv,
+};
+
+static Private pimagpriv;
+static Pool pimagmem = {
+ .name= "Image",
+ .maxsize= 16*1024*1024,
+ .minarena= 2*1024*1024,
+ .quantum= 32,
+ .alloc= xalloc,
+ .merge= xmerge,
+ .flags= 0,
+
+ .lock= plock,
+ .unlock= punlock,
+ .print= poolprint,
+ .panic= ppanic,
+
+ .private= &pimagpriv,
+};
+
+Pool* mainmem = &pmainmem;
+Pool* imagmem = &pimagmem;
+
+/*
+ * because we can't print while we're holding the locks,
+ * we have the save the message and print it once we let go.
+ */
+static void
+poolprint(Pool *p, char *fmt, ...)
+{
+ va_list v;
+ Private *pv;
+
+ pv = p->private;
+ va_start(v, fmt);
+ vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
+ va_end(v);
+}
+
+static void
+ppanic(Pool *p, char *fmt, ...)
+{
+ va_list v;
+ Private *pv;
+ char msg[sizeof pv->msg];
+
+ pv = p->private;
+ va_start(v, fmt);
+ vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
+ va_end(v);
+ memmove(msg, pv->msg, sizeof msg);
+ iunlock(&pv->lk);
+ panic("%s", msg);
+}
+
+static void
+plock(Pool *p)
+{
+ Private *pv;
+
+ pv = p->private;
+ ilock(&pv->lk);
+ pv->lk.pc = getcallerpc(&p);
+ pv->msg[0] = 0;
+}
+
+static void
+punlock(Pool *p)
+{
+ Private *pv;
+ char msg[sizeof pv->msg];
+
+ pv = p->private;
+ if(pv->msg[0] == 0){
+ iunlock(&pv->lk);
+ return;
+ }
+
+ memmove(msg, pv->msg, sizeof msg);
+ iunlock(&pv->lk);
+ iprint("%.*s", sizeof pv->msg, msg);
+}
+
+void
+poolsummary(Pool *p)
+{
+ print("%s max %lud cur %lud free %lud alloc %lud\n", p->name,
+ p->maxsize, p->cursize, p->curfree, p->curalloc);
+}
+
+void
+mallocsummary(void)
+{
+ poolsummary(mainmem);
+ poolsummary(imagmem);
+}
+
+/* everything from here down should be the same in libc, libdebugmalloc, and the kernel */
+/* - except the code for malloc(), which alternately doesn't clear or does. */
+/* - except the code for smalloc(), which lives only in the kernel. */
+
+/*
+ * Npadlong is the number of 32-bit longs to leave at the beginning of
+ * each allocated buffer for our own bookkeeping. We return to the callers
+ * a pointer that points immediately after our bookkeeping area. Incoming pointers
+ * must be decremented by that much, and outgoing pointers incremented.
+ * The malloc tag is stored at MallocOffset from the beginning of the block,
+ * and the realloc tag at ReallocOffset. The offsets are from the true beginning
+ * of the block, not the beginning the caller sees.
+ *
+ * The extra if(Npadlong != 0) in various places is a hint for the compiler to
+ * compile out function calls that would otherwise be no-ops.
+ */
+
+/* non tracing
+ *
+enum {
+ Npadlong = 0,
+ MallocOffset = 0,
+ ReallocOffset = 0,
+};
+ *
+ */
+
+/* tracing */
+enum {
+ Npadlong = 2,
+ MallocOffset = 0,
+ ReallocOffset = 1
+};
+
+
+void*
+smalloc(ulong size)
+{
+ void *v;
+
+ for(;;) {
+ v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
+ if(v != nil)
+ break;
+ tsleep(&up->sleep, return0, 0, 100);
+ }
+ if(Npadlong){
+ v = (ulong*)v+Npadlong;
+ setmalloctag(v, getcallerpc(&size));
+ }
+ memset(v, 0, size);
+ return v;
+}
+
+void*
+malloc(ulong size)
+{
+ void *v;
+
+ v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
+ if(v == nil)
+ return nil;
+ if(Npadlong){
+ v = (ulong*)v+Npadlong;
+ setmalloctag(v, getcallerpc(&size));
+ setrealloctag(v, 0);
+ }
+ memset(v, 0, size);
+ return v;
+}
+
+void*
+mallocz(ulong size, int clr)
+{
+ void *v;
+
+ v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
+ if(Npadlong && v != nil){
+ v = (ulong*)v+Npadlong;
+ setmalloctag(v, getcallerpc(&size));
+ setrealloctag(v, 0);
+ }
+ if(clr && v != nil)
+ memset(v, 0, size);
+ return v;
+}
+
+void*
+mallocalign(ulong size, ulong align, long offset, ulong span)
+{
+ void *v;
+
+ v = poolallocalign(mainmem, size+Npadlong*sizeof(ulong), align, offset-Npadlong*sizeof(ulong), span);
+ if(Npadlong && v != nil){
+ v = (ulong*)v+Npadlong;
+ setmalloctag(v, getcallerpc(&size));
+ setrealloctag(v, 0);
+ }
+ if(v)
+ memset(v, 0, size);
+ return v;
+}
+
+void
+free(void *v)
+{
+ if(v != nil)
+ poolfree(mainmem, (ulong*)v-Npadlong);
+}
+
+void*
+realloc(void *v, ulong size)
+{
+ void *nv;
+
+ if(v != nil)
+ v = (ulong*)v-Npadlong;
+ if(Npadlong !=0 && size != 0)
+ size += Npadlong*sizeof(ulong);
+
+ if(nv = poolrealloc(mainmem, v, size)){
+ nv = (ulong*)nv+Npadlong;
+ setrealloctag(nv, getcallerpc(&v));
+ if(v == nil)
+ setmalloctag(nv, getcallerpc(&v));
+ }
+ return nv;
+}
+
+ulong
+msize(void *v)
+{
+ return poolmsize(mainmem, (ulong*)v-Npadlong)-Npadlong*sizeof(ulong);
+}
+
+void*
+calloc(ulong n, ulong szelem)
+{
+ void *v;
+ if(v = mallocz(n*szelem, 1))
+ setmalloctag(v, getcallerpc(&n));
+ return v;
+}
+
+void
+setmalloctag(void *v, ulong pc)
+{
+ ulong *u;
+ USED(v, pc);
+ if(Npadlong <= MallocOffset || v == nil)
+ return;
+ u = v;
+ u[-Npadlong+MallocOffset] = pc;
+}
+
+void
+setrealloctag(void *v, ulong pc)
+{
+ ulong *u;
+ USED(v, pc);
+ if(Npadlong <= ReallocOffset || v == nil)
+ return;
+ u = v;
+ u[-Npadlong+ReallocOffset] = pc;
+}
+
+ulong
+getmalloctag(void *v)
+{
+ USED(v);
+ if(Npadlong <= MallocOffset)
+ return ~0;
+ return ((ulong*)v)[-Npadlong+MallocOffset];
+}
+
+ulong
+getrealloctag(void *v)
+{
+ USED(v);
+ if(Npadlong <= ReallocOffset)
+ return ((ulong*)v)[-Npadlong+ReallocOffset];
+ return ~0;
+}
diff --git a/sys/src/9/port/allocb.c b/sys/src/9/port/allocb.c
new file mode 100755
index 000000000..c6989452b
--- /dev/null
+++ b/sys/src/9/port/allocb.c
@@ -0,0 +1,185 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+
+enum
+{
+ Hdrspc = 64, /* leave room for high-level headers */
+ Bdead = 0x51494F42, /* "QIOB" */
+};
+
+struct
+{
+ Lock;
+ ulong bytes;
+} ialloc;
+
+static Block*
+_allocb(int size)
+{
+ Block *b;
+ ulong addr;
+
+ if((b = mallocz(sizeof(Block)+size+Hdrspc, 0)) == nil)
+ return nil;
+
+ b->next = nil;
+ b->list = nil;
+ b->free = 0;
+ b->flag = 0;
+ b->ref = 0;
+ _xinc(&b->ref);
+
+ /* align start of data portion by rounding up */
+ addr = (ulong)b;
+ addr = ROUND(addr + sizeof(Block), BLOCKALIGN);
+ b->base = (uchar*)addr;
+
+ /* align end of data portion by rounding down */
+ b->lim = ((uchar*)b) + msize(b);
+ addr = (ulong)(b->lim);
+ addr = addr & ~(BLOCKALIGN-1);
+ b->lim = (uchar*)addr;
+
+ /* leave sluff at beginning for added headers */
+ b->rp = b->lim - ROUND(size, BLOCKALIGN);
+ if(b->rp < b->base)
+ panic("_allocb");
+ b->wp = b->rp;
+
+ return b;
+}
+
+Block*
+allocb(int size)
+{
+ Block *b;
+
+ /*
+ * Check in a process and wait until successful.
+ * Can still error out of here, though.
+ */
+ if(up == nil)
+ panic("allocb without up: %#p", getcallerpc(&size));
+ if((b = _allocb(size)) == nil){
+ xsummary();
+ mallocsummary();
+ panic("allocb: no memory for %d bytes", size);
+ }
+ setmalloctag(b, getcallerpc(&size));
+
+ return b;
+}
+
+Block*
+iallocb(int size)
+{
+ Block *b;
+ static int m1, m2, mp;
+
+ if(ialloc.bytes > conf.ialloc){
+ if((m1++%10000)==0){
+ if(mp++ > 1000){
+ active.exiting = 1;
+ exit(0);
+ }
+ iprint("iallocb: limited %lud/%lud\n",
+ ialloc.bytes, conf.ialloc);
+ }
+ return nil;
+ }
+
+ if((b = _allocb(size)) == nil){
+ if((m2++%10000)==0){
+ if(mp++ > 1000){
+ active.exiting = 1;
+ exit(0);
+ }
+ iprint("iallocb: no memory %lud/%lud\n",
+ ialloc.bytes, conf.ialloc);
+ }
+ return nil;
+ }
+ setmalloctag(b, getcallerpc(&size));
+ b->flag = BINTR;
+
+ ilock(&ialloc);
+ ialloc.bytes += b->lim - b->base;
+ iunlock(&ialloc);
+
+ return b;
+}
+
+void
+freeb(Block *b)
+{
+ void *dead = (void*)Bdead;
+ long ref;
+
+ if(b == nil || (ref = _xdec(&b->ref)) > 0)
+ return;
+
+ if(ref < 0){
+ dumpstack();
+ panic("freeb: ref %ld; caller pc %#p", ref, getcallerpc(&b));
+ }
+
+ /*
+ * drivers which perform non cache coherent DMA manage their own buffer
+ * pool of uncached buffers and provide their own free routine.
+ */
+ if(b->free) {
+ b->free(b);
+ return;
+ }
+ if(b->flag & BINTR) {
+ ilock(&ialloc);
+ ialloc.bytes -= b->lim - b->base;
+ iunlock(&ialloc);
+ }
+
+ /* poison the block in case someone is still holding onto it */
+ b->next = dead;
+ b->rp = dead;
+ b->wp = dead;
+ b->lim = dead;
+ b->base = dead;
+
+ free(b);
+}
+
+void
+checkb(Block *b, char *msg)
+{
+ void *dead = (void*)Bdead;
+
+ if(b == dead)
+ panic("checkb b %s %#p", msg, b);
+ if(b->base == dead || b->lim == dead || b->next == dead
+ || b->rp == dead || b->wp == dead){
+ print("checkb: base %#p lim %#p next %#p\n",
+ b->base, b->lim, b->next);
+ print("checkb: rp %#p wp %#p\n", b->rp, b->wp);
+ panic("checkb dead: %s", msg);
+ }
+
+ if(b->base > b->lim)
+ panic("checkb 0 %s %#p %#p", msg, b->base, b->lim);
+ if(b->rp < b->base)
+ panic("checkb 1 %s %#p %#p", msg, b->base, b->rp);
+ if(b->wp < b->base)
+ panic("checkb 2 %s %#p %#p", msg, b->base, b->wp);
+ if(b->rp > b->lim)
+ panic("checkb 3 %s %#p %#p", msg, b->rp, b->lim);
+ if(b->wp > b->lim)
+ panic("checkb 4 %s %#p %#p", msg, b->wp, b->lim);
+}
+
+void
+iallocsummary(void)
+{
+ print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc);
+}
diff --git a/sys/src/9/port/aoe.h b/sys/src/9/port/aoe.h
new file mode 100755
index 000000000..6a8895ccc
--- /dev/null
+++ b/sys/src/9/port/aoe.h
@@ -0,0 +1,78 @@
+/*
+ * ATA-over-Ethernet (AoE) protocol
+ */
+enum {
+ ACata,
+ ACconfig,
+};
+
+enum {
+ AQCread,
+ AQCtest,
+ AQCprefix,
+ AQCset,
+ AQCfset,
+};
+
+enum {
+ AEcmd = 1,
+ AEarg,
+ AEdev,
+ AEcfg,
+ AEver,
+};
+
+enum {
+ Aoetype = 0x88a2,
+ Aoesectsz = 512, /* standard sector size */
+ Aoever = 1,
+
+ AFerr = 1<<2,
+ AFrsp = 1<<3,
+
+ AAFwrite= 1,
+ AAFext = 1<<6,
+};
+
+typedef struct {
+ uchar dst[Eaddrlen];
+ uchar src[Eaddrlen];
+ uchar type[2];
+ uchar verflag;
+ uchar error;
+ uchar major[2];
+ uchar minor;
+ uchar cmd;
+ uchar tag[4];
+ uchar payload[];
+} Aoehdr;
+
+#define AOEHDRSZ offsetof(Aoehdr, payload[0])
+
+typedef struct {
+ Aoehdr;
+ uchar aflag;
+ uchar errfeat;
+ uchar scnt;
+ uchar cmdstat;
+ uchar lba[6];
+ uchar res[2];
+ uchar payload[];
+} Aoeata;
+
+#define AOEATASZ offsetof(Aoeata, payload[0])
+
+typedef struct {
+ Aoehdr;
+ uchar bufcnt[2];
+ uchar fwver[2];
+ uchar scnt;
+ uchar verccmd;
+ uchar cslen[2];
+ uchar payload[];
+} Aoeqc;
+
+#define AOEQCSZ offsetof(Aoeqc, payload[0])
+
+extern char Echange[];
+extern char Enotup[];
diff --git a/sys/src/9/port/auth.c b/sys/src/9/port/auth.c
new file mode 100755
index 000000000..9565acd4e
--- /dev/null
+++ b/sys/src/9/port/auth.c
@@ -0,0 +1,157 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include <authsrv.h>
+
+char *eve;
+char hostdomain[DOMLEN];
+
+/*
+ * return true if current user is eve
+ */
+int
+iseve(void)
+{
+ return strcmp(eve, up->user) == 0;
+}
+
+long
+sysfversion(ulong *arg)
+{
+ char *vers;
+ uint arglen, m, msize;
+ Chan *c;
+
+ msize = arg[1];
+ vers = (char*)arg[2];
+ arglen = arg[3];
+ validaddr(arg[2], arglen, 1);
+ /* check there's a NUL in the version string */
+ if(arglen==0 || memchr(vers, 0, arglen)==0)
+ error(Ebadarg);
+ c = fdtochan(arg[0], ORDWR, 0, 1);
+ if(waserror()){
+ cclose(c);
+ nexterror();
+ }
+
+ m = mntversion(c, vers, msize, arglen);
+
+ cclose(c);
+ poperror();
+ return m;
+}
+
+long
+sys_fsession(ulong *arg)
+{
+ /* deprecated; backwards compatibility only */
+
+ if(arg[2] == 0)
+ error(Ebadarg);
+ validaddr(arg[1], arg[2], 1);
+ ((uchar*)arg[1])[0] = '\0';
+ return 0;
+}
+
+long
+sysfauth(ulong *arg)
+{
+ Chan *c, *ac;
+ char *aname;
+ int fd;
+
+ validaddr(arg[1], 1, 0);
+ aname = validnamedup((char*)arg[1], 1);
+ if(waserror()){
+ free(aname);
+ nexterror();
+ }
+ c = fdtochan(arg[0], ORDWR, 0, 1);
+ if(waserror()){
+ cclose(c);
+ nexterror();
+ }
+
+ ac = mntauth(c, aname);
+ /* at this point ac is responsible for keeping c alive */
+ poperror(); /* c */
+ cclose(c);
+ poperror(); /* aname */
+ free(aname);
+
+ if(waserror()){
+ cclose(ac);
+ nexterror();
+ }
+
+ fd = newfd(ac);
+ if(fd < 0)
+ error(Enofd);
+ poperror(); /* ac */
+
+ /* always mark it close on exec */
+ ac->flag |= CCEXEC;
+
+ return fd;
+}
+
+/*
+ * called by devcons() for user device
+ *
+ * anyone can become none
+ */
+long
+userwrite(char *a, int n)
+{
+ if(n!=4 || strncmp(a, "none", 4)!=0)
+ error(Eperm);
+ kstrdup(&up->user, "none");
+ up->basepri = PriNormal;
+ return n;
+}
+
+/*
+ * called by devcons() for host owner/domain
+ *
+ * writing hostowner also sets user
+ */
+long
+hostownerwrite(char *a, int n)
+{
+ char buf[128];
+
+ if(!iseve())
+ error(Eperm);
+ if(n <= 0 || n >= sizeof buf)
+ error(Ebadarg);
+ memmove(buf, a, n);
+ buf[n] = 0;
+
+ renameuser(eve, buf);
+ kstrdup(&eve, buf);
+ kstrdup(&up->user, buf);
+ up->basepri = PriNormal;
+ return n;
+}
+
+long
+hostdomainwrite(char *a, int n)
+{
+ char buf[DOMLEN];
+
+ if(!iseve())
+ error(Eperm);
+ if(n >= DOMLEN)
+ error(Ebadarg);
+ memset(buf, 0, DOMLEN);
+ strncpy(buf, a, n);
+ if(buf[0] == 0)
+ error(Ebadarg);
+ memmove(hostdomain, buf, DOMLEN);
+ return n;
+}
diff --git a/sys/src/9/port/cache.c b/sys/src/9/port/cache.c
new file mode 100755
index 000000000..2322822d9
--- /dev/null
+++ b/sys/src/9/port/cache.c
@@ -0,0 +1,630 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+enum
+{
+ NHASH = 128,
+ MAXCACHE = 1024*1024,
+ NFILE = 4096,
+ NEXTENT = 200, /* extent allocation size */
+};
+
+typedef struct Extent Extent;
+struct Extent
+{
+ int bid;
+ ulong start;
+ int len;
+ Page *cache;
+ Extent *next;
+};
+
+typedef struct Mntcache Mntcache;
+struct Mntcache
+{
+ Qid qid;
+ int dev;
+ int type;
+ QLock;
+ Extent *list;
+ Mntcache *hash;
+ Mntcache *prev;
+ Mntcache *next;
+};
+
+typedef struct Cache Cache;
+struct Cache
+{
+ Lock;
+ int pgno;
+ Mntcache *head;
+ Mntcache *tail;
+ Mntcache *hash[NHASH];
+};
+
+typedef struct Ecache Ecache;
+struct Ecache
+{
+ Lock;
+ int total;
+ int free;
+ Extent* head;
+};
+
+static Image fscache;
+static Cache cache;
+static Ecache ecache;
+static int maxcache = MAXCACHE;
+
+static void
+extentfree(Extent* e)
+{
+ lock(&ecache);
+ e->next = ecache.head;
+ ecache.head = e;
+ ecache.free++;
+ unlock(&ecache);
+}
+
+static Extent*
+extentalloc(void)
+{
+ Extent *e;
+ int i;
+
+ lock(&ecache);
+ if(ecache.head == nil){
+ e = xalloc(NEXTENT*sizeof(Extent));
+ if(e == nil){
+ unlock(&ecache);
+ return nil;
+ }
+ for(i = 0; i < NEXTENT; i++){
+ e->next = ecache.head;
+ ecache.head = e;
+ e++;
+ }
+ ecache.free += NEXTENT;
+ ecache.total += NEXTENT;
+ }
+
+ e = ecache.head;
+ ecache.head = e->next;
+ memset(e, 0, sizeof(Extent));
+ ecache.free--;
+ unlock(&ecache);
+
+ return e;
+}
+
+void
+cinit(void)
+{
+ int i;
+ Mntcache *m;
+
+ cache.head = xalloc(sizeof(Mntcache)*NFILE);
+ m = cache.head;
+ if (m == nil)
+ panic("cinit: no memory");
+
+ /* a better algorithm would be nice */
+// if(conf.npage*BY2PG > 200*MB)
+// maxcache = 10*MAXCACHE;
+// if(conf.npage*BY2PG > 400*MB)
+// maxcache = 50*MAXCACHE;
+
+ for(i = 0; i < NFILE-1; i++) {
+ m->next = m+1;
+ m->prev = m-1;
+ m++;
+ }
+
+ cache.tail = m;
+ cache.tail->next = 0;
+ cache.head->prev = 0;
+
+ fscache.notext = 1;
+}
+
+void
+cprint(Chan *c, Mntcache *m, char *s)
+{
+ ulong o;
+ int nb, ct;
+ Extent *e;
+
+ nb = 0;
+ ct = 1;
+ o = 0;
+ if(m->list)
+ o = m->list->start;
+ for(e = m->list; e; e = e->next) {
+ nb += e->len;
+ if(o != e->start)
+ ct = 0;
+ o = e->start+e->len;
+ }
+ pprint("%s: %#llux.%#lux %d %d %s (%d %c)\n",
+ s, m->qid.path, m->qid.vers, m->type, m->dev, c->path->s, nb, ct ? 'C' : 'N');
+
+ for(e = m->list; e; e = e->next) {
+ pprint("\t%4d %5lud %4d %#p\n",
+ e->bid, e->start, e->len, e->cache);
+ }
+}
+
+Page*
+cpage(Extent *e)
+{
+ /* Easy consistency check */
+ if(e->cache->daddr != e->bid)
+ return 0;
+
+ return lookpage(&fscache, e->bid);
+}
+
+void
+cnodata(Mntcache *m)
+{
+ Extent *e, *n;
+
+ /*
+ * Invalidate all extent data
+ * Image lru will waste the pages
+ */
+ for(e = m->list; e; e = n) {
+ n = e->next;
+ extentfree(e);
+ }
+ m->list = 0;
+}
+
+void
+ctail(Mntcache *m)
+{
+ /* Unlink and send to the tail */
+ if(m->prev)
+ m->prev->next = m->next;
+ else
+ cache.head = m->next;
+ if(m->next)
+ m->next->prev = m->prev;
+ else
+ cache.tail = m->prev;
+
+ if(cache.tail) {
+ m->prev = cache.tail;
+ cache.tail->next = m;
+ m->next = 0;
+ cache.tail = m;
+ }
+ else {
+ cache.head = m;
+ cache.tail = m;
+ m->prev = 0;
+ m->next = 0;
+ }
+}
+
+void
+copen(Chan *c)
+{
+ int h;
+ Extent *e, *next;
+ Mntcache *m, *f, **l;
+
+ /* directories aren't cacheable and append-only files confuse us */
+ if(c->qid.type&(QTDIR|QTAPPEND))
+ return;
+
+ h = c->qid.path%NHASH;
+ lock(&cache);
+ for(m = cache.hash[h]; m; m = m->hash) {
+ if(m->qid.path == c->qid.path)
+ if(m->qid.type == c->qid.type)
+ if(m->dev == c->dev && m->type == c->type) {
+ c->mcp = m;
+ ctail(m);
+ unlock(&cache);
+
+ /* File was updated, invalidate cache */
+ if(m->qid.vers != c->qid.vers) {
+ m->qid.vers = c->qid.vers;
+ qlock(m);
+ cnodata(m);
+ qunlock(m);
+ }
+ return;
+ }
+ }
+
+ /* LRU the cache headers */
+ m = cache.head;
+ l = &cache.hash[m->qid.path%NHASH];
+ for(f = *l; f; f = f->hash) {
+ if(f == m) {
+ *l = m->hash;
+ break;
+ }
+ l = &f->hash;
+ }
+
+ m->qid = c->qid;
+ m->dev = c->dev;
+ m->type = c->type;
+
+ l = &cache.hash[h];
+ m->hash = *l;
+ *l = m;
+ ctail(m);
+
+ qlock(m);
+ c->mcp = m;
+ e = m->list;
+ m->list = 0;
+ unlock(&cache);
+
+ while(e) {
+ next = e->next;
+ extentfree(e);
+ e = next;
+ }
+ qunlock(m);
+}
+
+static int
+cdev(Mntcache *m, Chan *c)
+{
+ if(m->qid.path != c->qid.path)
+ return 0;
+ if(m->qid.type != c->qid.type)
+ return 0;
+ if(m->dev != c->dev)
+ return 0;
+ if(m->type != c->type)
+ return 0;
+ if(m->qid.vers != c->qid.vers)
+ return 0;
+ return 1;
+}
+
+int
+cread(Chan *c, uchar *buf, int len, vlong off)
+{
+ KMap *k;
+ Page *p;
+ Mntcache *m;
+ Extent *e, **t;
+ int o, l, total;
+ ulong offset;
+
+ if(off+len > maxcache)
+ return 0;
+
+ m = c->mcp;
+ if(m == 0)
+ return 0;
+
+ qlock(m);
+ if(cdev(m, c) == 0) {
+ qunlock(m);
+ return 0;
+ }
+
+ offset = off;
+ t = &m->list;
+ for(e = *t; e; e = e->next) {
+ if(offset >= e->start && offset < e->start+e->len)
+ break;
+ t = &e->next;
+ }
+
+ if(e == 0) {
+ qunlock(m);
+ return 0;
+ }
+
+ total = 0;
+ while(len) {
+ p = cpage(e);
+ if(p == 0) {
+ *t = e->next;
+ extentfree(e);
+ qunlock(m);
+ return total;
+ }
+
+ o = offset - e->start;
+ l = len;
+ if(l > e->len-o)
+ l = e->len-o;
+
+ k = kmap(p);
+ if(waserror()) {
+ kunmap(k);
+ putpage(p);
+ qunlock(m);
+ nexterror();
+ }
+
+ memmove(buf, (uchar*)VA(k) + o, l);
+
+ poperror();
+ kunmap(k);
+
+ putpage(p);
+
+ buf += l;
+ len -= l;
+ offset += l;
+ total += l;
+ t = &e->next;
+ e = e->next;
+ if(e == 0 || e->start != offset)
+ break;
+ }
+
+ qunlock(m);
+ return total;
+}
+
+Extent*
+cchain(uchar *buf, ulong offset, int len, Extent **tail)
+{
+ int l;
+ Page *p;
+ KMap *k;
+ Extent *e, *start, **t;
+
+ start = 0;
+ *tail = 0;
+ t = &start;
+ while(len) {
+ e = extentalloc();
+ if(e == 0)
+ break;
+
+ p = auxpage();
+ if(p == 0) {
+ extentfree(e);
+ break;
+ }
+ l = len;
+ if(l > BY2PG)
+ l = BY2PG;
+
+ e->cache = p;
+ e->start = offset;
+ e->len = l;
+
+ lock(&cache);
+ e->bid = cache.pgno;
+ cache.pgno += BY2PG;
+ /* wrap the counter; low bits are unused by pghash but checked by lookpage */
+ if((cache.pgno & ~(BY2PG-1)) == 0){
+ if(cache.pgno == BY2PG-1){
+ print("cache wrapped\n");
+ cache.pgno = 0;
+ }else
+ cache.pgno++;
+ }
+ unlock(&cache);
+
+ p->daddr = e->bid;
+ k = kmap(p);
+ if(waserror()) { /* buf may be virtual */
+ kunmap(k);
+ nexterror();
+ }
+ memmove((void*)VA(k), buf, l);
+ poperror();
+ kunmap(k);
+
+ cachepage(p, &fscache);
+ putpage(p);
+
+ buf += l;
+ offset += l;
+ len -= l;
+
+ *t = e;
+ *tail = e;
+ t = &e->next;
+ }
+
+ return start;
+}
+
+int
+cpgmove(Extent *e, uchar *buf, int boff, int len)
+{
+ Page *p;
+ KMap *k;
+
+ p = cpage(e);
+ if(p == 0)
+ return 0;
+
+ k = kmap(p);
+ if(waserror()) { /* Since buf may be virtual */
+ kunmap(k);
+ nexterror();
+ }
+
+ memmove((uchar*)VA(k)+boff, buf, len);
+
+ poperror();
+ kunmap(k);
+ putpage(p);
+
+ return 1;
+}
+
+void
+cupdate(Chan *c, uchar *buf, int len, vlong off)
+{
+ Mntcache *m;
+ Extent *tail;
+ Extent *e, *f, *p;
+ int o, ee, eblock;
+ ulong offset;
+
+ if(off > maxcache || len == 0)
+ return;
+
+ m = c->mcp;
+ if(m == 0)
+ return;
+ qlock(m);
+ if(cdev(m, c) == 0) {
+ qunlock(m);
+ return;
+ }
+
+ /*
+ * Find the insertion point
+ */
+ offset = off;
+ p = 0;
+ for(f = m->list; f; f = f->next) {
+ if(f->start > offset)
+ break;
+ p = f;
+ }
+
+ /* trim if there is a successor */
+ eblock = offset+len;
+ if(f != 0 && eblock > f->start) {
+ len -= (eblock - f->start);
+ if(len <= 0) {
+ qunlock(m);
+ return;
+ }
+ }
+
+ if(p == 0) { /* at the head */
+ e = cchain(buf, offset, len, &tail);
+ if(e != 0) {
+ m->list = e;
+ tail->next = f;
+ }
+ qunlock(m);
+ return;
+ }
+
+ /* trim to the predecessor */
+ ee = p->start+p->len;
+ if(offset < ee) {
+ o = ee - offset;
+ len -= o;
+ if(len <= 0) {
+ qunlock(m);
+ return;
+ }
+ buf += o;
+ offset += o;
+ }
+
+ /* try and pack data into the predecessor */
+ if(offset == ee && p->len < BY2PG) {
+ o = len;
+ if(o > BY2PG - p->len)
+ o = BY2PG - p->len;
+ if(cpgmove(p, buf, p->len, o)) {
+ p->len += o;
+ buf += o;
+ len -= o;
+ offset += o;
+ if(len <= 0) {
+if(f && p->start + p->len > f->start) print("CACHE: p->start=%uld p->len=%d f->start=%uld\n", p->start, p->len, f->start);
+ qunlock(m);
+ return;
+ }
+ }
+ }
+
+ e = cchain(buf, offset, len, &tail);
+ if(e != 0) {
+ p->next = e;
+ tail->next = f;
+ }
+ qunlock(m);
+}
+
+void
+cwrite(Chan* c, uchar *buf, int len, vlong off)
+{
+ int o, eo;
+ Mntcache *m;
+ ulong eblock, ee;
+ Extent *p, *f, *e, *tail;
+ ulong offset;
+
+ if(off > maxcache || len == 0)
+ return;
+
+ m = c->mcp;
+ if(m == 0)
+ return;
+
+ qlock(m);
+ if(cdev(m, c) == 0) {
+ qunlock(m);
+ return;
+ }
+
+ offset = off;
+ m->qid.vers++;
+ c->qid.vers++;
+
+ p = 0;
+ for(f = m->list; f; f = f->next) {
+ if(f->start >= offset)
+ break;
+ p = f;
+ }
+
+ if(p != 0) {
+ ee = p->start+p->len;
+ eo = offset - p->start;
+ /* pack in predecessor if there is space */
+ if(offset <= ee && eo < BY2PG) {
+ o = len;
+ if(o > BY2PG - eo)
+ o = BY2PG - eo;
+ if(cpgmove(p, buf, eo, o)) {
+ if(eo+o > p->len)
+ p->len = eo+o;
+ buf += o;
+ len -= o;
+ offset += o;
+ }
+ }
+ }
+
+ /* free the overlap -- it's a rare case */
+ eblock = offset+len;
+ while(f && f->start < eblock) {
+ e = f->next;
+ extentfree(f);
+ f = e;
+ }
+
+ /* link the block (if any) into the middle */
+ e = cchain(buf, offset, len, &tail);
+ if(e != 0) {
+ tail->next = f;
+ f = e;
+ }
+
+ if(p == 0)
+ m->list = f;
+ else
+ p->next = f;
+ qunlock(m);
+}
diff --git a/sys/src/9/port/chan.c b/sys/src/9/port/chan.c
new file mode 100755
index 000000000..12af9baa3
--- /dev/null
+++ b/sys/src/9/port/chan.c
@@ -0,0 +1,1775 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+int chandebug=0; /* toggled by sysr1 */
+#define DBG if(chandebug)iprint
+
+enum
+{
+ PATHSLOP = 20,
+ PATHMSLOP = 20,
+};
+
+struct
+{
+ Lock;
+ int fid;
+ Chan *free;
+ Chan *list;
+}chanalloc;
+
+typedef struct Elemlist Elemlist;
+
+struct Elemlist
+{
+ char *aname; /* original name */
+ char *name; /* copy of name, so '/' can be overwritten */
+ int nelems;
+ char **elems;
+ int *off;
+ int mustbedir;
+ int nerror;
+ int prefix;
+};
+
+#define SEP(c) ((c) == 0 || (c) == '/')
+
+static void
+dumpmount(void) /* DEBUGGING */
+{
+ Pgrp *pg;
+ Mount *t;
+ Mhead **h, **he, *f;
+
+ if(up == nil){
+ print("no process for dumpmount\n");
+ return;
+ }
+ pg = up->pgrp;
+ if(pg == nil){
+ print("no pgrp for dumpmount\n");
+ return;
+ }
+ rlock(&pg->ns);
+ if(waserror()){
+ runlock(&pg->ns);
+ nexterror();
+ }
+
+ he = &pg->mnthash[MNTHASH];
+ for(h = pg->mnthash; h < he; h++){
+ for(f = *h; f; f = f->hash){
+ print("head: %#p: %s %#llux.%lud %C %lud -> \n", f,
+ f->from->path->s, f->from->qid.path,
+ f->from->qid.vers, devtab[f->from->type]->dc,
+ f->from->dev);
+ for(t = f->mount; t; t = t->next)
+ print("\t%#p: %s (umh %#p) (path %#.8llux dev %C %lud)\n", t, t->to->path->s, t->to->umh, t->to->qid.path, devtab[t->to->type]->dc, t->to->dev);
+ }
+ }
+ poperror();
+ runlock(&pg->ns);
+}
+
+char*
+chanpath(Chan *c)
+{
+ if(c == nil)
+ return "<nil chan>";
+ if(c->path == nil)
+ return "<nil path>";
+ if(c->path->s == nil)
+ return "<nil path.s>";
+ return c->path->s;
+}
+
+int
+isdotdot(char *p)
+{
+ return p[0]=='.' && p[1]=='.' && p[2]=='\0';
+}
+
+long
+incref(Ref *r)
+{
+ long x;
+
+ lock(r);
+ x = ++r->ref;
+ unlock(r);
+ return x;
+}
+
+long
+decref(Ref *r)
+{
+ long x;
+
+ lock(r);
+ x = --r->ref;
+ unlock(r);
+ if(x < 0)
+ panic("decref pc=%#p", getcallerpc(&r));
+
+ return x;
+}
+
+/*
+ * Rather than strncpy, which zeros the rest of the buffer, kstrcpy
+ * truncates if necessary, always zero terminates, does not zero fill,
+ * and puts ... at the end of the string if it's too long. Usually used to
+ * save a string in up->genbuf;
+ */
+void
+kstrcpy(char *s, char *t, int ns)
+{
+ int nt;
+
+ nt = strlen(t);
+ if(nt+1 <= ns){
+ memmove(s, t, nt+1);
+ return;
+ }
+ /* too long */
+ if(ns < 4){
+ /* but very short! */
+ strncpy(s, t, ns);
+ return;
+ }
+ /* truncate with ... at character boundary (very rare case) */
+ memmove(s, t, ns-4);
+ ns -= 4;
+ s[ns] = '\0';
+ /* look for first byte of UTF-8 sequence by skipping continuation bytes */
+ while(ns>0 && (s[--ns]&0xC0)==0x80)
+ ;
+ strcpy(s+ns, "...");
+}
+
+int
+emptystr(char *s)
+{
+ if(s == nil)
+ return 1;
+ if(s[0] == '\0')
+ return 1;
+ return 0;
+}
+
+/*
+ * Atomically replace *p with copy of s
+ */
+void
+kstrdup(char **p, char *s)
+{
+ int n;
+ char *t, *prev;
+
+ n = strlen(s)+1;
+ /* if it's a user, we can wait for memory; if not, something's very wrong */
+ if(up){
+ t = smalloc(n);
+ setmalloctag(t, getcallerpc(&p));
+ }else{
+ t = malloc(n);
+ if(t == nil)
+ panic("kstrdup: no memory");
+ }
+ memmove(t, s, n);
+ prev = *p;
+ *p = t;
+ free(prev);
+}
+
+void
+chandevreset(void)
+{
+ int i;
+
+ todinit(); /* avoid later reentry causing infinite recursion */
+ for(i=0; devtab[i] != nil; i++)
+ devtab[i]->reset();
+}
+
+void
+chandevinit(void)
+{
+ int i;
+
+ for(i=0; devtab[i] != nil; i++)
+ devtab[i]->init();
+}
+
+void
+chandevshutdown(void)
+{
+ int i;
+
+ /* shutdown in reverse order */
+ for(i=0; devtab[i] != nil; i++)
+ ;
+ for(i--; i >= 0; i--)
+ devtab[i]->shutdown();
+}
+
+Chan*
+newchan(void)
+{
+ Chan *c;
+
+ lock(&chanalloc);
+ c = chanalloc.free;
+ if(c != 0)
+ chanalloc.free = c->next;
+ unlock(&chanalloc);
+
+ if(c == nil){
+ c = smalloc(sizeof(Chan));
+ lock(&chanalloc);
+ c->fid = ++chanalloc.fid;
+ c->link = chanalloc.list;
+ chanalloc.list = c;
+ unlock(&chanalloc);
+ }
+
+ /* if you get an error before associating with a dev,
+ close calls rootclose, a nop */
+ c->type = 0;
+ c->flag = 0;
+ c->ref = 1;
+ c->dev = 0;
+ c->offset = 0;
+ c->devoffset = 0;
+ c->iounit = 0;
+ c->umh = 0;
+ c->uri = 0;
+ c->dri = 0;
+ c->aux = 0;
+ c->mchan = 0;
+ c->mcp = 0;
+ c->mux = 0;
+ memset(&c->mqid, 0, sizeof(c->mqid));
+ c->path = 0;
+ c->ismtpt = 0;
+
+ return c;
+}
+
+Ref npath;
+
+Path*
+newpath(char *s)
+{
+ int i;
+ Path *p;
+
+ p = smalloc(sizeof(Path));
+ i = strlen(s);
+ p->len = i;
+ p->alen = i+PATHSLOP;
+ p->s = smalloc(p->alen);
+ memmove(p->s, s, i+1);
+ p->ref = 1;
+ incref(&npath);
+
+ /*
+ * Cannot use newpath for arbitrary names because the mtpt
+ * array will not be populated correctly. The names #/ and / are
+ * allowed, but other names with / in them draw warnings.
+ */
+ if(strchr(s, '/') && strcmp(s, "#/") != 0 && strcmp(s, "/") != 0)
+ print("newpath: %s from %#p\n", s, getcallerpc(&s));
+
+ p->mlen = 1;
+ p->malen = PATHMSLOP;
+ p->mtpt = smalloc(p->malen*sizeof p->mtpt[0]);
+ return p;
+}
+
+static Path*
+copypath(Path *p)
+{
+ int i;
+ Path *pp;
+
+ pp = smalloc(sizeof(Path));
+ pp->ref = 1;
+ incref(&npath);
+ DBG("copypath %s %p => %p\n", p->s, p, pp);
+
+ pp->len = p->len;
+ pp->alen = p->alen;
+ pp->s = smalloc(p->alen);
+ memmove(pp->s, p->s, p->len+1);
+
+ pp->mlen = p->mlen;
+ pp->malen = p->malen;
+ pp->mtpt = smalloc(p->malen*sizeof pp->mtpt[0]);
+ for(i=0; i<pp->mlen; i++){
+ pp->mtpt[i] = p->mtpt[i];
+ if(pp->mtpt[i])
+ incref(pp->mtpt[i]);
+ }
+
+ return pp;
+}
+
+void
+pathclose(Path *p)
+{
+ int i;
+
+ if(p == nil)
+ return;
+//XXX
+ DBG("pathclose %p %s ref=%ld =>", p, p->s, p->ref);
+ for(i=0; i<p->mlen; i++)
+ DBG(" %p", p->mtpt[i]);
+ DBG("\n");
+
+ if(decref(p))
+ return;
+ decref(&npath);
+ free(p->s);
+ for(i=0; i<p->mlen; i++)
+ if(p->mtpt[i])
+ cclose(p->mtpt[i]);
+ free(p->mtpt);
+ free(p);
+}
+
+/*
+ * In place, rewrite name to compress multiple /, eliminate ., and process ..
+ * (Really only called to remove a trailing .. that has been added.
+ * Otherwise would need to update n->mtpt as well.)
+ */
+static void
+fixdotdotname(Path *p)
+{
+ char *r;
+
+ if(p->s[0] == '#'){
+ r = strchr(p->s, '/');
+ if(r == nil)
+ return;
+ cleanname(r);
+
+ /*
+ * The correct name is #i rather than #i/,
+ * but the correct name of #/ is #/.
+ */
+ if(strcmp(r, "/")==0 && p->s[1] != '/')
+ *r = '\0';
+ }else
+ cleanname(p->s);
+ p->len = strlen(p->s);
+}
+
+static Path*
+uniquepath(Path *p)
+{
+ Path *new;
+
+ if(p->ref > 1){
+ /* copy on write */
+ new = copypath(p);
+ pathclose(p);
+ p = new;
+ }
+ return p;
+}
+
+static Path*
+addelem(Path *p, char *s, Chan *from)
+{
+ char *t;
+ int a, i;
+ Chan *c, **tt;
+
+ if(s[0]=='.' && s[1]=='\0')
+ return p;
+
+ p = uniquepath(p);
+
+ i = strlen(s);
+ if(p->len+1+i+1 > p->alen){
+ a = p->len+1+i+1 + PATHSLOP;
+ t = smalloc(a);
+ memmove(t, p->s, p->len+1);
+ free(p->s);
+ p->s = t;
+ p->alen = a;
+ }
+ /* don't insert extra slash if one is present */
+ if(p->len>0 && p->s[p->len-1]!='/' && s[0]!='/')
+ p->s[p->len++] = '/';
+ memmove(p->s+p->len, s, i+1);
+ p->len += i;
+ if(isdotdot(s)){
+ fixdotdotname(p);
+ DBG("addelem %s .. => rm %p\n", p->s, p->mtpt[p->mlen-1]);
+ if(p->mlen>1 && (c = p->mtpt[--p->mlen])){
+ p->mtpt[p->mlen] = nil;
+ cclose(c);
+ }
+ }else{
+ if(p->mlen >= p->malen){
+ p->malen = p->mlen+1+PATHMSLOP;
+ tt = smalloc(p->malen*sizeof tt[0]);
+ memmove(tt, p->mtpt, p->mlen*sizeof tt[0]);
+ free(p->mtpt);
+ p->mtpt = tt;
+ }
+ DBG("addelem %s %s => add %p\n", p->s, s, from);
+ p->mtpt[p->mlen++] = from;
+ if(from)
+ incref(from);
+ }
+ return p;
+}
+
+void
+chanfree(Chan *c)
+{
+ c->flag = CFREE;
+
+ if(c->dirrock != nil){
+ free(c->dirrock);
+ c->dirrock = 0;
+ c->nrock = 0;
+ c->mrock = 0;
+ }
+ if(c->umh != nil){
+ putmhead(c->umh);
+ c->umh = nil;
+ }
+ if(c->umc != nil){
+ cclose(c->umc);
+ c->umc = nil;
+ }
+ if(c->mux != nil){
+ muxclose(c->mux);
+ c->mux = nil;
+ }
+ if(c->mchan != nil){
+ cclose(c->mchan);
+ c->mchan = nil;
+ }
+
+ pathclose(c->path);
+ c->path = nil;
+
+ lock(&chanalloc);
+ c->next = chanalloc.free;
+ chanalloc.free = c;
+ unlock(&chanalloc);
+}
+
+void
+cclose(Chan *c)
+{
+ if(c->flag&CFREE)
+ panic("cclose %#p", getcallerpc(&c));
+
+ DBG("cclose %p name=%s ref=%ld\n", c, c->path->s, c->ref);
+ if(decref(c))
+ return;
+
+ if(!waserror()){
+ devtab[c->type]->close(c);
+ poperror();
+ }
+ chanfree(c);
+}
+
+/*
+ * Queue a chan to be closed by one of the clunk procs.
+ */
+struct {
+ Chan *head;
+ Chan *tail;
+ int nqueued;
+ int nclosed;
+ Lock l;
+ QLock q;
+ Rendez r;
+} clunkq;
+void closeproc(void*);
+
+void
+ccloseq(Chan *c)
+{
+ if(c->flag&CFREE)
+ panic("cclose %#p", getcallerpc(&c));
+
+ DBG("ccloseq %p name=%s ref=%ld\n", c, c->path->s, c->ref);
+
+ if(decref(c))
+ return;
+
+ lock(&clunkq.l);
+ clunkq.nqueued++;
+ c->next = nil;
+ if(clunkq.head)
+ clunkq.tail->next = c;
+ else
+ clunkq.head = c;
+ clunkq.tail = c;
+ unlock(&clunkq.l);
+
+ if(!wakeup(&clunkq.r))
+ kproc("closeproc", closeproc, nil);
+}
+
+static int
+clunkwork(void*)
+{
+ return clunkq.head != nil;
+}
+
+void
+closeproc(void*)
+{
+ Chan *c;
+
+ for(;;){
+ qlock(&clunkq.q);
+ if(clunkq.head == nil){
+ if(!waserror()){
+ tsleep(&clunkq.r, clunkwork, nil, 5000);
+ poperror();
+ }
+ if(clunkq.head == nil){
+ qunlock(&clunkq.q);
+ pexit("no work", 1);
+ }
+ }
+ lock(&clunkq.l);
+ c = clunkq.head;
+ clunkq.head = c->next;
+ clunkq.nclosed++;
+ unlock(&clunkq.l);
+ qunlock(&clunkq.q);
+ if(!waserror()){
+ devtab[c->type]->close(c);
+ poperror();
+ }
+ chanfree(c);
+ }
+}
+
+/*
+ * Make sure we have the only copy of c. (Copy on write.)
+ */
+Chan*
+cunique(Chan *c)
+{
+ Chan *nc;
+
+ if(c->ref != 1){
+ nc = cclone(c);
+ cclose(c);
+ c = nc;
+ }
+
+ return c;
+}
+
+int
+eqqid(Qid a, Qid b)
+{
+ return a.path==b.path && a.vers==b.vers;
+}
+
+int
+eqchan(Chan *a, Chan *b, int skipvers)
+{
+ if(a->qid.path != b->qid.path)
+ return 0;
+ if(!skipvers && a->qid.vers!=b->qid.vers)
+ return 0;
+ if(a->type != b->type)
+ return 0;
+ if(a->dev != b->dev)
+ return 0;
+ return 1;
+}
+
+int
+eqchantdqid(Chan *a, int type, int dev, Qid qid, int skipvers)
+{
+ if(a->qid.path != qid.path)
+ return 0;
+ if(!skipvers && a->qid.vers!=qid.vers)
+ return 0;
+ if(a->type != type)
+ return 0;
+ if(a->dev != dev)
+ return 0;
+ return 1;
+}
+
+Mhead*
+newmhead(Chan *from)
+{
+ Mhead *mh;
+
+ mh = smalloc(sizeof(Mhead));
+ mh->ref = 1;
+ mh->from = from;
+ incref(from);
+ return mh;
+}
+
+int
+cmount(Chan **newp, Chan *old, int flag, char *spec)
+{
+ int order, flg;
+ Chan *new;
+ Mhead *m, **l, *mh;
+ Mount *nm, *f, *um, **h;
+ Pgrp *pg;
+
+ if(QTDIR & (old->qid.type^(*newp)->qid.type))
+ error(Emount);
+
+ if(old->umh)
+ print("cmount: unexpected umh, caller %#p\n", getcallerpc(&newp));
+
+ order = flag&MORDER;
+
+ if((old->qid.type&QTDIR)==0 && order != MREPL)
+ error(Emount);
+
+ new = *newp;
+ mh = new->umh;
+
+ /*
+ * Not allowed to bind when the old directory is itself a union.
+ * (Maybe it should be allowed, but I don't see what the semantics
+ * would be.)
+ *
+ * We need to check mh->mount->next to tell unions apart from
+ * simple mount points, so that things like
+ * mount -c fd /root
+ * bind -c /root /
+ * work.
+ *
+ * The check of mount->mflag allows things like
+ * mount fd /root
+ * bind -c /root /
+ *
+ * This is far more complicated than it should be, but I don't
+ * see an easier way at the moment.
+ */
+ if((flag&MCREATE) && mh && mh->mount
+ && (mh->mount->next || !(mh->mount->mflag&MCREATE)))
+ error(Emount);
+
+ pg = up->pgrp;
+ wlock(&pg->ns);
+
+ l = &MOUNTH(pg, old->qid);
+ for(m = *l; m; m = m->hash){
+ if(eqchan(m->from, old, 1))
+ break;
+ l = &m->hash;
+ }
+
+ if(m == nil){
+ /*
+ * nothing mounted here yet. create a mount
+ * head and add to the hash table.
+ */
+ m = newmhead(old);
+ *l = m;
+
+ /*
+ * if this is a union mount, add the old
+ * node to the mount chain.
+ */
+ if(order != MREPL)
+ m->mount = newmount(m, old, 0, 0);
+ }
+ wlock(&m->lock);
+ if(waserror()){
+ wunlock(&m->lock);
+ nexterror();
+ }
+ wunlock(&pg->ns);
+
+ nm = newmount(m, new, flag, spec);
+ if(mh != nil && mh->mount != nil){
+ /*
+ * copy a union when binding it onto a directory
+ */
+ flg = order;
+ if(order == MREPL)
+ flg = MAFTER;
+ h = &nm->next;
+ um = mh->mount;
+ for(um = um->next; um; um = um->next){
+ f = newmount(m, um->to, flg, um->spec);
+ *h = f;
+ h = &f->next;
+ }
+ }
+
+ if(m->mount && order == MREPL){
+ mountfree(m->mount);
+ m->mount = 0;
+ }
+
+ if(flag & MCREATE)
+ nm->mflag |= MCREATE;
+
+ if(m->mount && order == MAFTER){
+ for(f = m->mount; f->next; f = f->next)
+ ;
+ f->next = nm;
+ }else{
+ for(f = nm; f->next; f = f->next)
+ ;
+ f->next = m->mount;
+ m->mount = nm;
+ }
+
+ wunlock(&m->lock);
+ poperror();
+ return nm->mountid;
+}
+
+void
+cunmount(Chan *mnt, Chan *mounted)
+{
+ Pgrp *pg;
+ Mhead *m, **l;
+ Mount *f, **p;
+
+ if(mnt->umh) /* should not happen */
+ print("cunmount newp extra umh %p has %p\n", mnt, mnt->umh);
+
+ /*
+ * It _can_ happen that mounted->umh is non-nil,
+ * because mounted is the result of namec(Aopen)
+ * (see sysfile.c:/^sysunmount).
+ * If we open a union directory, it will have a umh.
+ * Although surprising, this is okay, since the
+ * cclose will take care of freeing the umh.
+ */
+
+ pg = up->pgrp;
+ wlock(&pg->ns);
+
+ l = &MOUNTH(pg, mnt->qid);
+ for(m = *l; m; m = m->hash){
+ if(eqchan(m->from, mnt, 1))
+ break;
+ l = &m->hash;
+ }
+
+ if(m == 0){
+ wunlock(&pg->ns);
+ error(Eunmount);
+ }
+
+ wlock(&m->lock);
+ if(mounted == 0){
+ *l = m->hash;
+ wunlock(&pg->ns);
+ mountfree(m->mount);
+ m->mount = nil;
+ cclose(m->from);
+ wunlock(&m->lock);
+ putmhead(m);
+ return;
+ }
+
+ p = &m->mount;
+ for(f = *p; f; f = f->next){
+ /* BUG: Needs to be 2 pass */
+ if(eqchan(f->to, mounted, 1) ||
+ (f->to->mchan && eqchan(f->to->mchan, mounted, 1))){
+ *p = f->next;
+ f->next = 0;
+ mountfree(f);
+ if(m->mount == nil){
+ *l = m->hash;
+ cclose(m->from);
+ wunlock(&m->lock);
+ wunlock(&pg->ns);
+ putmhead(m);
+ return;
+ }
+ wunlock(&m->lock);
+ wunlock(&pg->ns);
+ return;
+ }
+ p = &f->next;
+ }
+ wunlock(&m->lock);
+ wunlock(&pg->ns);
+ error(Eunion);
+}
+
+Chan*
+cclone(Chan *c)
+{
+ Chan *nc;
+ Walkqid *wq;
+
+ wq = devtab[c->type]->walk(c, nil, nil, 0);
+ if(wq == nil)
+ error("clone failed");
+ nc = wq->clone;
+ free(wq);
+ nc->path = c->path;
+ if(c->path)
+ incref(c->path);
+ return nc;
+}
+
+/* also used by sysfile.c:/^mountfix */
+int
+findmount(Chan **cp, Mhead **mp, int type, int dev, Qid qid)
+{
+ Pgrp *pg;
+ Mhead *m;
+
+ pg = up->pgrp;
+ rlock(&pg->ns);
+ for(m = MOUNTH(pg, qid); m; m = m->hash){
+ rlock(&m->lock);
+ if(m->from == nil){
+ print("m %p m->from 0\n", m);
+ runlock(&m->lock);
+ continue;
+ }
+ if(eqchantdqid(m->from, type, dev, qid, 1)){
+ runlock(&pg->ns);
+ if(mp != nil){
+ incref(m);
+ if(*mp != nil)
+ putmhead(*mp);
+ *mp = m;
+ }
+ if(*cp != nil)
+ cclose(*cp);
+ incref(m->mount->to);
+ *cp = m->mount->to;
+ runlock(&m->lock);
+ return 1;
+ }
+ runlock(&m->lock);
+ }
+
+ runlock(&pg->ns);
+ return 0;
+}
+
+/*
+ * Calls findmount but also updates path.
+ */
+static int
+domount(Chan **cp, Mhead **mp, Path **path)
+{
+ Chan **lc;
+ Path *p;
+
+ if(findmount(cp, mp, (*cp)->type, (*cp)->dev, (*cp)->qid) == 0)
+ return 0;
+
+ if(path){
+ p = *path;
+ p = uniquepath(p);
+ if(p->mlen <= 0)
+ print("domount: path %s has mlen==%d\n", p->s, p->mlen);
+ else{
+ lc = &p->mtpt[p->mlen-1];
+DBG("domount %p %s => add %p (was %p)\n", p, p->s, (*mp)->from, p->mtpt[p->mlen-1]);
+ incref((*mp)->from);
+ if(*lc)
+ cclose(*lc);
+ *lc = (*mp)->from;
+ }
+ *path = p;
+ }
+ return 1;
+}
+
+/*
+ * If c is the right-hand-side of a mount point, returns the left hand side.
+ * Changes name to reflect the fact that we've uncrossed the mountpoint,
+ * so name had better be ours to change!
+ */
+static Chan*
+undomount(Chan *c, Path *path)
+{
+ Chan *nc;
+
+ if(path->ref != 1 || path->mlen == 0)
+ print("undomount: path %s ref %ld mlen %d caller %#p\n",
+ path->s, path->ref, path->mlen, getcallerpc(&c));
+
+ if(path->mlen>0 && (nc=path->mtpt[path->mlen-1]) != nil){
+DBG("undomount %p %s => remove %p\n", path, path->s, nc);
+ cclose(c);
+ path->mtpt[path->mlen-1] = nil;
+ c = nc;
+ }
+ return c;
+}
+
+/*
+ * Call dev walk but catch errors.
+ */
+static Walkqid*
+ewalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ Walkqid *wq;
+
+ if(waserror())
+ return nil;
+ wq = devtab[c->type]->walk(c, nc, name, nname);
+ poperror();
+ return wq;
+}
+
+/*
+ * Either walks all the way or not at all. No partial results in *cp.
+ * *nerror is the number of names to display in an error message.
+ */
+static char Edoesnotexist[] = "does not exist";
+int
+walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
+{
+ int dev, didmount, dotdot, i, n, nhave, ntry, type;
+ Chan *c, *nc, *mtpt;
+ Path *path;
+ Mhead *mh, *nmh;
+ Mount *f;
+ Walkqid *wq;
+
+ c = *cp;
+ incref(c);
+ path = c->path;
+ incref(path);
+ mh = nil;
+
+ /*
+ * While we haven't gotten all the way down the path:
+ * 1. step through a mount point, if any
+ * 2. send a walk request for initial dotdot or initial prefix without dotdot
+ * 3. move to the first mountpoint along the way.
+ * 4. repeat.
+ *
+ * Each time through the loop:
+ *
+ * If didmount==0, c is on the undomount side of the mount point.
+ * If didmount==1, c is on the domount side of the mount point.
+ * Either way, c's full path is path.
+ */
+ didmount = 0;
+ for(nhave=0; nhave<nnames; nhave+=n){
+ if((c->qid.type&QTDIR)==0){
+ if(nerror)
+ *nerror = nhave;
+ pathclose(path);
+ cclose(c);
+ strcpy(up->errstr, Enotdir);
+ if(mh != nil)
+ putmhead(mh);
+ return -1;
+ }
+ ntry = nnames - nhave;
+ if(ntry > MAXWELEM)
+ ntry = MAXWELEM;
+ dotdot = 0;
+ for(i=0; i<ntry; i++){
+ if(isdotdot(names[nhave+i])){
+ if(i==0){
+ dotdot = 1;
+ ntry = 1;
+ }else
+ ntry = i;
+ break;
+ }
+ }
+
+ if(!dotdot && !nomount && !didmount)
+ domount(&c, &mh, &path);
+
+ type = c->type;
+ dev = c->dev;
+
+ if((wq = ewalk(c, nil, names+nhave, ntry)) == nil){
+ /* try a union mount, if any */
+ if(mh && !nomount){
+ /*
+ * mh->mount->to == c, so start at mh->mount->next
+ */
+ rlock(&mh->lock);
+ f = mh->mount;
+ for(f = (f? f->next: f); f; f = f->next)
+ if((wq = ewalk(f->to, nil, names+nhave, ntry)) != nil)
+ break;
+ runlock(&mh->lock);
+ if(f != nil){
+ type = f->to->type;
+ dev = f->to->dev;
+ }
+ }
+ if(wq == nil){
+ cclose(c);
+ pathclose(path);
+ if(nerror)
+ *nerror = nhave+1;
+ if(mh != nil)
+ putmhead(mh);
+ return -1;
+ }
+ }
+
+ didmount = 0;
+ if(dotdot){
+ assert(wq->nqid == 1);
+ assert(wq->clone != nil);
+
+ path = addelem(path, "..", nil);
+ nc = undomount(wq->clone, path);
+ nmh = nil;
+ n = 1;
+ }else{
+ nc = nil;
+ nmh = nil;
+ if(!nomount){
+ for(i=0; i<wq->nqid && i<ntry-1; i++){
+ if(findmount(&nc, &nmh, type, dev, wq->qid[i])){
+ didmount = 1;
+ break;
+ }
+ }
+ }
+ if(nc == nil){ /* no mount points along path */
+ if(wq->clone == nil){
+ cclose(c);
+ pathclose(path);
+ if(wq->nqid==0 || (wq->qid[wq->nqid-1].type&QTDIR)){
+ if(nerror)
+ *nerror = nhave+wq->nqid+1;
+ strcpy(up->errstr, Edoesnotexist);
+ }else{
+ if(nerror)
+ *nerror = nhave+wq->nqid;
+ strcpy(up->errstr, Enotdir);
+ }
+ free(wq);
+ if(mh != nil)
+ putmhead(mh);
+ return -1;
+ }
+ n = wq->nqid;
+ nc = wq->clone;
+ }else{ /* stopped early, at a mount point */
+ didmount = 1;
+ if(wq->clone != nil){
+ cclose(wq->clone);
+ wq->clone = nil;
+ }
+ n = i+1;
+ }
+ for(i=0; i<n; i++){
+ mtpt = nil;
+ if(i==n-1 && nmh)
+ mtpt = nmh->from;
+ path = addelem(path, names[nhave+i], mtpt);
+ }
+ }
+ cclose(c);
+ c = nc;
+ putmhead(mh);
+ mh = nmh;
+ free(wq);
+ }
+
+ putmhead(mh);
+
+ c = cunique(c);
+
+ if(c->umh != nil){ //BUG
+ print("walk umh\n");
+ putmhead(c->umh);
+ c->umh = nil;
+ }
+
+ pathclose(c->path);
+ c->path = path;
+
+ cclose(*cp);
+ *cp = c;
+ if(nerror)
+ *nerror = nhave;
+ return 0;
+}
+
+/*
+ * c is a mounted non-creatable directory. find a creatable one.
+ */
+Chan*
+createdir(Chan *c, Mhead *m)
+{
+ Chan *nc;
+ Mount *f;
+
+ rlock(&m->lock);
+ if(waserror()){
+ runlock(&m->lock);
+ nexterror();
+ }
+ for(f = m->mount; f; f = f->next){
+ if(f->mflag&MCREATE){
+ nc = cclone(f->to);
+ runlock(&m->lock);
+ poperror();
+ cclose(c);
+ return nc;
+ }
+ }
+ error(Enocreate);
+ return 0;
+}
+
+void
+saveregisters(void)
+{
+}
+
+static void
+growparse(Elemlist *e)
+{
+ char **new;
+ int *inew;
+ enum { Delta = 8 };
+
+ if(e->nelems % Delta == 0){
+ new = smalloc((e->nelems+Delta) * sizeof(char*));
+ memmove(new, e->elems, e->nelems*sizeof(char*));
+ free(e->elems);
+ e->elems = new;
+ inew = smalloc((e->nelems+Delta+1) * sizeof(int));
+ memmove(inew, e->off, (e->nelems+1)*sizeof(int));
+ free(e->off);
+ e->off = inew;
+ }
+}
+
+/*
+ * The name is known to be valid.
+ * Copy the name so slashes can be overwritten.
+ * An empty string will set nelem=0.
+ * A path ending in / or /. or /.//./ etc. will have
+ * e.mustbedir = 1, so that we correctly
+ * reject, e.g., "/adm/users/." when /adm/users is a file
+ * rather than a directory.
+ */
+static void
+parsename(char *aname, Elemlist *e)
+{
+ char *name, *slash;
+
+ kstrdup(&e->name, aname);
+ name = e->name;
+ e->nelems = 0;
+ e->elems = nil;
+ e->off = smalloc(sizeof(int));
+ e->off[0] = skipslash(name) - name;
+ for(;;){
+ name = skipslash(name);
+ if(*name == '\0'){
+ e->off[e->nelems] = name+strlen(name) - e->name;
+ e->mustbedir = 1;
+ break;
+ }
+ growparse(e);
+ e->elems[e->nelems++] = name;
+ slash = utfrune(name, '/');
+ if(slash == nil){
+ e->off[e->nelems] = name+strlen(name) - e->name;
+ e->mustbedir = 0;
+ break;
+ }
+ e->off[e->nelems] = slash - e->name;
+ *slash++ = '\0';
+ name = slash;
+ }
+
+ if(0 && chandebug){
+ int i;
+
+ print("parsename %s:", e->name);
+ for(i=0; i<=e->nelems; i++)
+ print(" %d", e->off[i]);
+ print("\n");
+ }
+}
+
+void*
+memrchr(void *va, int c, long n)
+{
+ uchar *a, *e;
+
+ a = va;
+ for(e=a+n-1; e>a; e--)
+ if(*e == c)
+ return e;
+ return nil;
+}
+
+void
+namelenerror(char *aname, int len, char *err)
+{
+ char *ename, *name, *next;
+ int i, errlen;
+
+ /*
+ * If the name is short enough, just use the whole thing.
+ */
+ errlen = strlen(err);
+ if(len < ERRMAX/3 || len+errlen < 2*ERRMAX/3)
+ snprint(up->genbuf, sizeof up->genbuf, "%.*s",
+ utfnlen(aname, len), aname);
+ else{
+ /*
+ * Print a suffix of the name, but try to get a little info.
+ */
+ ename = aname+len;
+ next = ename;
+ do{
+ name = next;
+ next = memrchr(aname, '/', name-aname);
+ if(next == nil)
+ next = aname;
+ len = ename-next;
+ }while(len < ERRMAX/3 || len + errlen < 2*ERRMAX/3);
+
+ /*
+ * If the name is ridiculously long, chop it.
+ */
+ if(name == ename){
+ name = ename-ERRMAX/4;
+ if(name <= aname)
+ panic("bad math in namelenerror");
+ /* walk out of current UTF sequence */
+ for(i=0; (*name&0xC0)==0x80 && i<UTFmax; i++)
+ name++;
+ }
+ snprint(up->genbuf, sizeof up->genbuf, "...%.*s",
+ utfnlen(name, ename-name), name);
+ }
+ snprint(up->errstr, ERRMAX, "%#q %s", up->genbuf, err);
+ nexterror();
+}
+
+void
+nameerror(char *name, char *err)
+{
+ namelenerror(name, strlen(name), err);
+}
+
+/*
+ * Turn a name into a channel.
+ * &name[0] is known to be a valid address. It may be a kernel address.
+ *
+ * Opening with amode Aopen, Acreate, Aremove, or Aaccess guarantees
+ * that the result will be the only reference to that particular fid.
+ * This is necessary since we might pass the result to
+ * devtab[]->remove().
+ *
+ * Opening Atodir or Amount does not guarantee this.
+ *
+ * Under certain circumstances, opening Aaccess will cause
+ * an unnecessary clone in order to get a cunique Chan so it
+ * can attach the correct name. Sysstat and sys_stat need the
+ * correct name so they can rewrite the stat info.
+ */
+Chan*
+namec(char *aname, int amode, int omode, ulong perm)
+{
+ int len, n, t, nomount;
+ Chan *c, *cnew;
+ Path *path;
+ Elemlist e;
+ Rune r;
+ Mhead *m;
+ char *createerr, tmperrbuf[ERRMAX];
+ char *name;
+
+ if(aname[0] == '\0')
+ error("empty file name");
+ aname = validnamedup(aname, 1);
+ if(waserror()){
+ free(aname);
+ nexterror();
+ }
+ DBG("namec %s %d %d\n", aname, amode, omode);
+ name = aname;
+
+ /*
+ * Find the starting off point (the current slash, the root of
+ * a device tree, or the current dot) as well as the name to
+ * evaluate starting there.
+ */
+ nomount = 0;
+ switch(name[0]){
+ case '/':
+ c = up->slash;
+ incref(c);
+ break;
+
+ case '#':
+ nomount = 1;
+ up->genbuf[0] = '\0';
+ n = 0;
+ while(*name != '\0' && (*name != '/' || n < 2)){
+ if(n >= sizeof(up->genbuf)-1)
+ error(Efilename);
+ up->genbuf[n++] = *name++;
+ }
+ up->genbuf[n] = '\0';
+ /*
+ * noattach is sandboxing.
+ *
+ * the OK exceptions are:
+ * | it only gives access to pipes you create
+ * d this process's file descriptors
+ * e this process's environment
+ * the iffy exceptions are:
+ * c time and pid, but also cons and consctl
+ * p control of your own processes (and unfortunately
+ * any others left unprotected)
+ */
+ n = chartorune(&r, up->genbuf+1)+1;
+ /* actually / is caught by parsing earlier */
+ if(utfrune("M", r))
+ error(Enoattach);
+ if(up->pgrp->noattach && utfrune("|decp", r)==nil)
+ error(Enoattach);
+ t = devno(r, 1);
+ if(t == -1)
+ error(Ebadsharp);
+ c = devtab[t]->attach(up->genbuf+n);
+ break;
+
+ default:
+ c = up->dot;
+ incref(c);
+ break;
+ }
+
+ e.aname = aname;
+ e.prefix = name - aname;
+ e.name = nil;
+ e.elems = nil;
+ e.off = nil;
+ e.nelems = 0;
+ e.nerror = 0;
+ if(waserror()){
+ cclose(c);
+ free(e.name);
+ free(e.elems);
+ /*
+ * Prepare nice error, showing first e.nerror elements of name.
+ */
+ if(e.nerror == 0)
+ nexterror();
+ strcpy(tmperrbuf, up->errstr);
+ if(e.off[e.nerror]==0)
+ print("nerror=%d but off=%d\n",
+ e.nerror, e.off[e.nerror]);
+ if(0 && chandebug)
+ print("showing %d+%d/%d (of %d) of %s (%d %d)\n", e.prefix, e.off[e.nerror], e.nerror, e.nelems, aname, e.off[0], e.off[1]);
+ len = e.prefix+e.off[e.nerror];
+ free(e.off);
+ namelenerror(aname, len, tmperrbuf);
+ }
+
+ /*
+ * Build a list of elements in the name.
+ */
+ parsename(name, &e);
+
+ /*
+ * On create, ....
+ */
+ if(amode == Acreate){
+ /* perm must have DMDIR if last element is / or /. */
+ if(e.mustbedir && !(perm&DMDIR)){
+ e.nerror = e.nelems;
+ error("create without DMDIR");
+ }
+
+ /* don't try to walk the last path element just yet. */
+ if(e.nelems == 0)
+ error(Eexist);
+ e.nelems--;
+ }
+
+ if(walk(&c, e.elems, e.nelems, nomount, &e.nerror) < 0){
+ if(e.nerror < 0 || e.nerror > e.nelems){
+ print("namec %s walk error nerror=%d\n", aname, e.nerror);
+ e.nerror = 0;
+ }
+ nexterror();
+ }
+
+ if(e.mustbedir && !(c->qid.type&QTDIR))
+ error("not a directory");
+
+ if(amode == Aopen && (omode&3) == OEXEC && (c->qid.type&QTDIR))
+ error("cannot exec directory");
+
+ switch(amode){
+ case Abind:
+ /* no need to maintain path - cannot dotdot an Abind */
+ m = nil;
+ if(!nomount)
+ domount(&c, &m, nil);
+ if(c->umh != nil)
+ putmhead(c->umh);
+ c->umh = m;
+ break;
+
+ case Aaccess:
+ case Aremove:
+ case Aopen:
+ Open:
+ /* save&update the name; domount might change c */
+ path = c->path;
+ incref(path);
+ m = nil;
+ if(!nomount)
+ domount(&c, &m, &path);
+
+ /* our own copy to open or remove */
+ c = cunique(c);
+
+ /* now it's our copy anyway, we can put the name back */
+ pathclose(c->path);
+ c->path = path;
+
+ /* record whether c is on a mount point */
+ c->ismtpt = m!=nil;
+
+ switch(amode){
+ case Aaccess:
+ case Aremove:
+ putmhead(m);
+ break;
+
+ case Aopen:
+ case Acreate:
+if(c->umh != nil){
+ print("cunique umh Open\n");
+ putmhead(c->umh);
+ c->umh = nil;
+}
+ /* only save the mount head if it's a multiple element union */
+ if(m && m->mount && m->mount->next)
+ c->umh = m;
+ else
+ putmhead(m);
+
+ /* save registers else error() in open has wrong value of c saved */
+ saveregisters();
+
+ if(omode == OEXEC)
+ c->flag &= ~CCACHE;
+
+ c = devtab[c->type]->open(c, omode&~OCEXEC);
+
+ if(omode & OCEXEC)
+ c->flag |= CCEXEC;
+ if(omode & ORCLOSE)
+ c->flag |= CRCLOSE;
+ break;
+ }
+ break;
+
+ case Atodir:
+ /*
+ * Directories (e.g. for cd) are left before the mount point,
+ * so one may mount on / or . and see the effect.
+ */
+ if(!(c->qid.type & QTDIR))
+ error(Enotdir);
+ break;
+
+ case Amount:
+ /*
+ * When mounting on an already mounted upon directory,
+ * one wants subsequent mounts to be attached to the
+ * original directory, not the replacement. Don't domount.
+ */
+ break;
+
+ case Acreate:
+ /*
+ * We've already walked all but the last element.
+ * If the last exists, try to open it OTRUNC.
+ * If omode&OEXCL is set, just give up.
+ */
+ e.nelems++;
+ e.nerror++;
+ if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) == 0){
+ if(omode&OEXCL)
+ error(Eexist);
+ omode |= OTRUNC;
+ goto Open;
+ }
+
+ /*
+ * The semantics of the create(2) system call are that if the
+ * file exists and can be written, it is to be opened with truncation.
+ * On the other hand, the create(5) message fails if the file exists.
+ * If we get two create(2) calls happening simultaneously,
+ * they might both get here and send create(5) messages, but only
+ * one of the messages will succeed. To provide the expected create(2)
+ * semantics, the call with the failed message needs to try the above
+ * walk again, opening for truncation. This correctly solves the
+ * create/create race, in the sense that any observable outcome can
+ * be explained as one happening before the other.
+ * The create/create race is quite common. For example, it happens
+ * when two rc subshells simultaneously update the same
+ * environment variable.
+ *
+ * The implementation still admits a create/create/remove race:
+ * (A) walk to file, fails
+ * (B) walk to file, fails
+ * (A) create file, succeeds, returns
+ * (B) create file, fails
+ * (A) remove file, succeeds, returns
+ * (B) walk to file, return failure.
+ *
+ * This is hardly as common as the create/create race, and is really
+ * not too much worse than what might happen if (B) got a hold of a
+ * file descriptor and then the file was removed -- either way (B) can't do
+ * anything with the result of the create call. So we don't care about this race.
+ *
+ * Applications that care about more fine-grained decision of the races
+ * can use the OEXCL flag to get at the underlying create(5) semantics;
+ * by default we provide the common case.
+ *
+ * We need to stay behind the mount point in case we
+ * need to do the first walk again (should the create fail).
+ *
+ * We also need to cross the mount point and find the directory
+ * in the union in which we should be creating.
+ *
+ * The channel staying behind is c, the one moving forward is cnew.
+ */
+ m = nil;
+ cnew = nil; /* is this assignment necessary? */
+ if(!waserror()){ /* try create */
+ if(!nomount && findmount(&cnew, &m, c->type, c->dev, c->qid))
+ cnew = createdir(cnew, m);
+ else{
+ cnew = c;
+ incref(cnew);
+ }
+
+ /*
+ * We need our own copy of the Chan because we're
+ * about to send a create, which will move it. Once we have
+ * our own copy, we can fix the name, which might be wrong
+ * if findmount gave us a new Chan.
+ */
+ cnew = cunique(cnew);
+ pathclose(cnew->path);
+ cnew->path = c->path;
+ incref(cnew->path);
+
+ devtab[cnew->type]->create(cnew, e.elems[e.nelems-1], omode&~(OEXCL|OCEXEC), perm);
+ poperror();
+ if(omode & OCEXEC)
+ cnew->flag |= CCEXEC;
+ if(omode & ORCLOSE)
+ cnew->flag |= CRCLOSE;
+ if(m)
+ putmhead(m);
+ cclose(c);
+ c = cnew;
+ c->path = addelem(c->path, e.elems[e.nelems-1], nil);
+ break;
+ }
+
+ /* create failed */
+ cclose(cnew);
+ if(m)
+ putmhead(m);
+ if(omode & OEXCL)
+ nexterror();
+ /* save error */
+ createerr = up->errstr;
+ up->errstr = tmperrbuf;
+ /* note: we depend that walk does not error */
+ if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) < 0){
+ up->errstr = createerr;
+ error(createerr); /* report true error */
+ }
+ up->errstr = createerr;
+ omode |= OTRUNC;
+ goto Open;
+
+ default:
+ panic("unknown namec access %d\n", amode);
+ }
+
+ /* place final element in genbuf for e.g. exec */
+ if(e.nelems > 0)
+ kstrcpy(up->genbuf, e.elems[e.nelems-1], sizeof up->genbuf);
+ else
+ kstrcpy(up->genbuf, ".", sizeof up->genbuf);
+ free(e.name);
+ free(e.elems);
+ free(e.off);
+ poperror(); /* e c */
+ free(aname);
+ poperror(); /* aname */
+
+ return c;
+}
+
+/*
+ * name is valid. skip leading / and ./ as much as possible
+ */
+char*
+skipslash(char *name)
+{
+ while(name[0]=='/' || (name[0]=='.' && (name[1]==0 || name[1]=='/')))
+ name++;
+ return name;
+}
+
+char isfrog[256]={
+ /*NUL*/ 1, 1, 1, 1, 1, 1, 1, 1,
+ /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1,
+ /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1,
+ /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1,
+ ['/'] 1,
+ [0x7f] 1,
+};
+
+/*
+ * Check that the name
+ * a) is in valid memory.
+ * b) is shorter than 2^16 bytes, so it can fit in a 9P string field.
+ * c) contains no frogs.
+ * The first byte is known to be addressible by the requester, so the
+ * routine works for kernel and user memory both.
+ * The parameter slashok flags whether a slash character is an error
+ * or a valid character.
+ *
+ * The parameter dup flags whether the string should be copied
+ * out of user space before being scanned the second time.
+ * (Otherwise a malicious thread could remove the NUL, causing us
+ * to access unchecked addresses.)
+ */
+static char*
+validname0(char *aname, int slashok, int dup, ulong pc)
+{
+ char *ename, *name, *s;
+ int c, n;
+ Rune r;
+
+ name = aname;
+ if((ulong)name < KZERO){
+ if(!dup)
+ print("warning: validname called from %#p with user pointer", pc);
+ ename = vmemchr(name, 0, (1<<16));
+ }else
+ ename = memchr(name, 0, (1<<16));
+
+ if(ename==nil || ename-name>=(1<<16))
+ error("name too long");
+
+ s = nil;
+ if(dup){
+ n = ename-name;
+ s = smalloc(n+1);
+ memmove(s, name, n);
+ s[n] = 0;
+ aname = s;
+ name = s;
+ setmalloctag(s, pc);
+ }
+
+ while(*name){
+ /* all characters above '~' are ok */
+ c = *(uchar*)name;
+ if(c >= Runeself)
+ name += chartorune(&r, name);
+ else{
+ if(isfrog[c])
+ if(!slashok || c!='/'){
+ snprint(up->genbuf, sizeof(up->genbuf), "%s: %q", Ebadchar, aname);
+ free(s);
+ error(up->genbuf);
+ }
+ name++;
+ }
+ }
+ return s;
+}
+
+void
+validname(char *aname, int slashok)
+{
+ validname0(aname, slashok, 0, getcallerpc(&aname));
+}
+
+char*
+validnamedup(char *aname, int slashok)
+{
+ return validname0(aname, slashok, 1, getcallerpc(&aname));
+}
+
+void
+isdir(Chan *c)
+{
+ if(c->qid.type & QTDIR)
+ return;
+ error(Enotdir);
+}
+
+/*
+ * This is necessary because there are many
+ * pointers to the top of a given mount list:
+ *
+ * - the mhead in the namespace hash table
+ * - the mhead in chans returned from findmount:
+ * used in namec and then by unionread.
+ * - the mhead in chans returned from createdir:
+ * used in the open/create race protect, which is gone.
+ *
+ * The RWlock in the Mhead protects the mount list it contains.
+ * The mount list is deleted when we cunmount.
+ * The RWlock ensures that nothing is using the mount list at that time.
+ *
+ * It is okay to replace c->mh with whatever you want as
+ * long as you are sure you have a unique reference to it.
+ *
+ * This comment might belong somewhere else.
+ */
+void
+putmhead(Mhead *m)
+{
+ if(m && decref(m) == 0){
+ m->mount = (Mount*)0xCafeBeef;
+ free(m);
+ }
+}
+
diff --git a/sys/src/9/port/cis.c b/sys/src/9/port/cis.c
new file mode 100755
index 000000000..368eb6d68
--- /dev/null
+++ b/sys/src/9/port/cis.c
@@ -0,0 +1,539 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+
+enum{
+ Linktarget = 0x13,
+};
+
+/*
+ * read and crack the card information structure enough to set
+ * important parameters like power
+ */
+/* cis memory walking */
+typedef struct Cisdat {
+ uchar *cisbase;
+ int cispos;
+ int cisskip;
+ int cislen;
+} Cisdat;
+
+static void tcfig(PCMslot*, Cisdat*, int);
+static void tentry(PCMslot*, Cisdat*, int);
+static void tvers1(PCMslot*, Cisdat*, int);
+static void tlonglnkmfc(PCMslot*, Cisdat*, int);
+
+static int
+readc(Cisdat *cis, uchar *x)
+{
+ if(cis->cispos >= cis->cislen)
+ return 0;
+ *x = cis->cisbase[cis->cisskip*cis->cispos];
+ cis->cispos++;
+ return 1;
+}
+
+static int
+xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
+{
+ PCMmap *m;
+ Cisdat cis;
+ int i, l;
+ uchar *p;
+ uchar type, link, n, c;
+ int this, subtype;
+
+ m = pcmmap(slotno, 0, 0, attr);
+ if(m == 0)
+ return -1;
+
+ cis.cisbase = KADDR(m->isa);
+ cis.cispos = 0;
+ cis.cisskip = attr ? 2 : 1;
+ cis.cislen = m->len;
+
+ /* loop through all the tuples */
+ for(i = 0; i < 1000; i++){
+ this = cis.cispos;
+ if(readc(&cis, &type) != 1)
+ break;
+ if(type == 0xFF)
+ break;
+ if(readc(&cis, &link) != 1)
+ break;
+ if(link == 0xFF)
+ break;
+
+ n = link;
+ if(link > 1 && subtuple != -1){
+ if(readc(&cis, &c) != 1)
+ break;
+ subtype = c;
+ n--;
+ }else
+ subtype = -1;
+
+ if(type == tuple && subtype == subtuple){
+ p = v;
+ for(l=0; l<nv && l<n; l++)
+ if(readc(&cis, p++) != 1)
+ break;
+ pcmunmap(slotno, m);
+ return nv;
+ }
+ cis.cispos = this + (2+link);
+ }
+ pcmunmap(slotno, m);
+ return -1;
+}
+
+int
+pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv)
+{
+ int n;
+
+ /* try attribute space, then memory */
+ if((n = xcistuple(slotno, tuple, subtuple, v, nv, 1)) >= 0)
+ return n;
+ return xcistuple(slotno, tuple, subtuple, v, nv, 0);
+}
+
+void
+pcmcisread(PCMslot *pp)
+{
+ int this;
+ Cisdat cis;
+ PCMmap *m;
+ uchar type, link;
+
+ memset(pp->ctab, 0, sizeof(pp->ctab));
+ pp->ncfg = 0;
+ memset(pp->cfg, 0, sizeof(pp->cfg));
+ pp->configed = 0;
+ pp->nctab = 0;
+ pp->verstr[0] = 0;
+
+ /*
+ * Read all tuples in attribute space.
+ */
+ m = pcmmap(pp->slotno, 0, 0, 1);
+ if(m == 0)
+ return;
+
+ cis.cisbase = KADDR(m->isa);
+ cis.cispos = 0;
+ cis.cisskip = 2;
+ cis.cislen = m->len;
+
+ /* loop through all the tuples */
+ for(;;){
+ this = cis.cispos;
+ if(readc(&cis, &type) != 1)
+ break;
+ if(type == 0xFF)
+ break;
+ if(readc(&cis, &link) != 1)
+ break;
+
+ switch(type){
+ default:
+ break;
+ case 6:
+ tlonglnkmfc(pp, &cis, type);
+ break;
+ case 0x15:
+ tvers1(pp, &cis, type);
+ break;
+ case 0x1A:
+ tcfig(pp, &cis, type);
+ break;
+ case 0x1B:
+ tentry(pp, &cis, type);
+ break;
+ }
+
+ if(link == 0xFF)
+ break;
+ cis.cispos = this + (2+link);
+ }
+ pcmunmap(pp->slotno, m);
+}
+
+static ulong
+getlong(Cisdat *cis, int size)
+{
+ uchar c;
+ int i;
+ ulong x;
+
+ x = 0;
+ for(i = 0; i < size; i++){
+ if(readc(cis, &c) != 1)
+ break;
+ x |= c<<(i*8);
+ }
+ return x;
+}
+
+static void
+tcfig(PCMslot *pp, Cisdat *cis, int )
+{
+ uchar size, rasize, rmsize;
+ uchar last;
+
+ if(readc(cis, &size) != 1)
+ return;
+ rasize = (size&0x3) + 1;
+ rmsize = ((size>>2)&0xf) + 1;
+ if(readc(cis, &last) != 1)
+ return;
+
+ if(pp->ncfg >= 8){
+ print("tcfig: too many configuration registers\n");
+ return;
+ }
+
+ pp->cfg[pp->ncfg].caddr = getlong(cis, rasize);
+ pp->cfg[pp->ncfg].cpresent = getlong(cis, rmsize);
+ pp->ncfg++;
+}
+
+static ulong vexp[8] =
+{
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
+};
+static ulong vmant[16] =
+{
+ 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
+};
+
+static ulong
+microvolt(Cisdat *cis)
+{
+ uchar c;
+ ulong microvolts;
+ ulong exp;
+
+ if(readc(cis, &c) != 1)
+ return 0;
+ exp = vexp[c&0x7];
+ microvolts = vmant[(c>>3)&0xf]*exp;
+ while(c & 0x80){
+ if(readc(cis, &c) != 1)
+ return 0;
+ switch(c){
+ case 0x7d:
+ break; /* high impedence when sleeping */
+ case 0x7e:
+ case 0x7f:
+ microvolts = 0; /* no connection */
+ break;
+ default:
+ exp /= 10;
+ microvolts += exp*(c&0x7f);
+ }
+ }
+ return microvolts;
+}
+
+static ulong
+nanoamps(Cisdat *cis)
+{
+ uchar c;
+ ulong nanoamps;
+
+ if(readc(cis, &c) != 1)
+ return 0;
+ nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
+ while(c & 0x80){
+ if(readc(cis, &c) != 1)
+ return 0;
+ if(c == 0x7d || c == 0x7e || c == 0x7f)
+ nanoamps = 0;
+ }
+ return nanoamps;
+}
+
+/*
+ * only nominal voltage (feature 1) is important for config,
+ * other features must read card to stay in sync.
+ */
+static ulong
+power(Cisdat *cis)
+{
+ uchar feature;
+ ulong mv;
+
+ mv = 0;
+ if(readc(cis, &feature) != 1)
+ return 0;
+ if(feature & 1)
+ mv = microvolt(cis);
+ if(feature & 2)
+ microvolt(cis);
+ if(feature & 4)
+ microvolt(cis);
+ if(feature & 8)
+ nanoamps(cis);
+ if(feature & 0x10)
+ nanoamps(cis);
+ if(feature & 0x20)
+ nanoamps(cis);
+ if(feature & 0x40)
+ nanoamps(cis);
+ return mv/1000000;
+}
+
+static ulong mantissa[16] =
+{ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };
+
+static ulong exponent[8] =
+{ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };
+
+static ulong
+ttiming(Cisdat *cis, int scale)
+{
+ uchar unscaled;
+ ulong nanosecs;
+
+ if(readc(cis, &unscaled) != 1)
+ return 0;
+ nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
+ nanosecs = nanosecs * vexp[scale];
+ return nanosecs;
+}
+
+static void
+timing(Cisdat *cis, PCMconftab *ct)
+{
+ uchar c, i;
+
+ if(readc(cis, &c) != 1)
+ return;
+ i = c&0x3;
+ if(i != 3)
+ ct->maxwait = ttiming(cis, i); /* max wait */
+ i = (c>>2)&0x7;
+ if(i != 7)
+ ct->readywait = ttiming(cis, i); /* max ready/busy wait */
+ i = (c>>5)&0x7;
+ if(i != 7)
+ ct->otherwait = ttiming(cis, i); /* reserved wait */
+}
+
+static void
+iospaces(Cisdat *cis, PCMconftab *ct)
+{
+ uchar c;
+ int i, nio;
+
+ ct->nio = 0;
+ if(readc(cis, &c) != 1)
+ return;
+
+ ct->bit16 = ((c>>5)&3) >= 2;
+ if(!(c & 0x80)){
+ ct->io[0].start = 0;
+ ct->io[0].len = 1<<(c&0x1f);
+ ct->nio = 1;
+ return;
+ }
+
+ if(readc(cis, &c) != 1)
+ return;
+
+ /*
+ * For each of the range descriptions read the
+ * start address and the length (value is length-1).
+ */
+ nio = (c&0xf)+1;
+ for(i = 0; i < nio; i++){
+ ct->io[i].start = getlong(cis, (c>>4)&0x3);
+ ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
+ }
+ ct->nio = nio;
+}
+
+static void
+irq(Cisdat *cis, PCMconftab *ct)
+{
+ uchar c;
+
+ if(readc(cis, &c) != 1)
+ return;
+ ct->irqtype = c & 0xe0;
+ if(c & 0x10)
+ ct->irqs = getlong(cis, 2);
+ else
+ ct->irqs = 1<<(c&0xf);
+ ct->irqs &= 0xDEB8; /* levels available to card */
+}
+
+static void
+memspace(Cisdat *cis, int asize, int lsize, int host)
+{
+ ulong haddress, address, len;
+
+ len = getlong(cis, lsize)*256;
+ address = getlong(cis, asize)*256;
+ USED(len, address);
+ if(host){
+ haddress = getlong(cis, asize)*256;
+ USED(haddress);
+ }
+}
+
+static void
+tentry(PCMslot *pp, Cisdat *cis, int )
+{
+ uchar c, i, feature;
+ PCMconftab *ct;
+
+ if(pp->nctab >= nelem(pp->ctab))
+ return;
+ if(readc(cis, &c) != 1)
+ return;
+ ct = &pp->ctab[pp->nctab++];
+
+ /* copy from last default config */
+ if(pp->def)
+ *ct = *pp->def;
+
+ ct->index = c & 0x3f;
+
+ /* is this the new default? */
+ if(c & 0x40)
+ pp->def = ct;
+
+ /* memory wait specified? */
+ if(c & 0x80){
+ if(readc(cis, &i) != 1)
+ return;
+ if(i&0x80)
+ ct->memwait = 1;
+ }
+
+ if(readc(cis, &feature) != 1)
+ return;
+ switch(feature&0x3){
+ case 1:
+ ct->vpp1 = ct->vpp2 = power(cis);
+ break;
+ case 2:
+ power(cis);
+ ct->vpp1 = ct->vpp2 = power(cis);
+ break;
+ case 3:
+ power(cis);
+ ct->vpp1 = power(cis);
+ ct->vpp2 = power(cis);
+ break;
+ default:
+ break;
+ }
+ if(feature&0x4)
+ timing(cis, ct);
+ if(feature&0x8)
+ iospaces(cis, ct);
+ if(feature&0x10)
+ irq(cis, ct);
+ switch((feature>>5)&0x3){
+ case 1:
+ memspace(cis, 0, 2, 0);
+ break;
+ case 2:
+ memspace(cis, 2, 2, 0);
+ break;
+ case 3:
+ if(readc(cis, &c) != 1)
+ return;
+ for(i = 0; i <= (c&0x7); i++)
+ memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
+ break;
+ }
+ pp->configed++;
+}
+
+static void
+tvers1(PCMslot *pp, Cisdat *cis, int )
+{
+ uchar c, major, minor, last;
+ int i;
+
+ if(readc(cis, &major) != 1)
+ return;
+ if(readc(cis, &minor) != 1)
+ return;
+ last = 0;
+ for(i = 0; i < sizeof(pp->verstr)-1; i++){
+ if(readc(cis, &c) != 1)
+ return;
+ if(c == 0)
+ c = ';';
+ if(c == '\n')
+ c = ';';
+ if(c == 0xff)
+ break;
+ if(c == ';' && last == ';')
+ continue;
+ pp->verstr[i] = c;
+ last = c;
+ }
+ pp->verstr[i] = 0;
+}
+
+static void
+tlonglnkmfc(PCMslot *pp, Cisdat *cis, int)
+{
+ int i, npos, opos;
+ uchar nfn, space, expect, type, this, link;
+
+ readc(cis, &nfn);
+ for(i = 0; i < nfn; i++){
+ readc(cis, &space);
+ npos = getlong(cis, 4);
+ opos = cis->cispos;
+ cis->cispos = npos;
+ expect = Linktarget;
+
+ while(1){
+ this = cis->cispos;
+ if(readc(cis, &type) != 1)
+ break;
+ if(type == 0xFF)
+ break;
+ if(readc(cis, &link) != 1)
+ break;
+
+ if(expect && expect != type){
+ print("tlonglnkmfc: expected %X found %X\n",
+ expect, type);
+ break;
+ }
+ expect = 0;
+
+ switch(type){
+ default:
+ break;
+ case 0x15:
+ tvers1(pp, cis, type);
+ break;
+ case 0x1A:
+ tcfig(pp, cis, type);
+ break;
+ case 0x1B:
+ tentry(pp, cis, type);
+ break;
+ }
+
+ if(link == 0xFF)
+ break;
+ cis->cispos = this + (2+link);
+ }
+ cis->cispos = opos;
+ }
+}
diff --git a/sys/src/9/port/debugalloc.c b/sys/src/9/port/debugalloc.c
new file mode 100755
index 000000000..e6a97e048
--- /dev/null
+++ b/sys/src/9/port/debugalloc.c
@@ -0,0 +1,681 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "pool.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+
+#define left u.s.bhl
+#define right u.s.bhr
+#define fwd u.s.bhf
+#define prev u.s.bhv
+#define parent u.s.bhp
+
+typedef struct Bhdr Bhdr;
+
+struct Bhdr {
+ ulong magic;
+ ulong size;
+};
+enum {
+ NOT_MAGIC = 0xdeadfa11,
+};
+
+struct Pool
+{
+ char* name;
+ ulong maxsize;
+ int quanta;
+ int chunk;
+ ulong cursize;
+ ulong arenasize;
+ ulong hw;
+ Lock l;
+ Bhdr* root;
+ Bhdr* chain;
+ int nalloc;
+ int nfree;
+ int nbrk;
+ int lastfree;
+ void (*move)(void*, void*);
+};
+
+struct
+{
+ int n;
+ Pool pool[MAXPOOL];
+ Lock l;
+} table = {
+ 2,
+ {
+ { "Main", 4*1024*1024, 31, 128*1024 },
+ { "Image", 16*1024*1024, 31, 2*1024*1024 },
+ }
+};
+
+Pool* mainmem = &table.pool[0];
+Pool* imagmem = &table.pool[1];
+
+int poolcompact(Pool*);
+
+Bhdr*
+poolchain(Pool *p)
+{
+ return p->chain;
+}
+
+void
+pooldel(Pool *p, Bhdr *t)
+{
+ Bhdr *s, *f, *rp, *q;
+
+ if(t->parent == nil && p->root != t) {
+ t->prev->fwd = t->fwd;
+ t->fwd->prev = t->prev;
+ return;
+ }
+
+ if(t->fwd != t) {
+ f = t->fwd;
+ s = t->parent;
+ f->parent = s;
+ if(s == nil)
+ p->root = f;
+ else {
+ if(s->left == t)
+ s->left = f;
+ else
+ s->right = f;
+ }
+
+ rp = t->left;
+ f->left = rp;
+ if(rp != nil)
+ rp->parent = f;
+ rp = t->right;
+ f->right = rp;
+ if(rp != nil)
+ rp->parent = f;
+
+ t->prev->fwd = t->fwd;
+ t->fwd->prev = t->prev;
+ return;
+ }
+
+ if(t->left == nil)
+ rp = t->right;
+ else {
+ if(t->right == nil)
+ rp = t->left;
+ else {
+ f = t;
+ rp = t->right;
+ s = rp->left;
+ while(s != nil) {
+ f = rp;
+ rp = s;
+ s = rp->left;
+ }
+ if(f != t) {
+ s = rp->right;
+ f->left = s;
+ if(s != nil)
+ s->parent = f;
+ s = t->right;
+ rp->right = s;
+ if(s != nil)
+ s->parent = rp;
+ }
+ s = t->left;
+ rp->left = s;
+ s->parent = rp;
+ }
+ }
+ q = t->parent;
+ if(q == nil)
+ p->root = rp;
+ else {
+ if(t == q->left)
+ q->left = rp;
+ else
+ q->right = rp;
+ }
+ if(rp != nil)
+ rp->parent = q;
+}
+
+void
+pooladd(Pool *p, Bhdr *q)
+{
+ int size;
+ Bhdr *tp, *t;
+
+ q->magic = MAGIC_F;
+
+ q->left = nil;
+ q->right = nil;
+ q->parent = nil;
+ q->fwd = q;
+ q->prev = q;
+
+ t = p->root;
+ if(t == nil) {
+ p->root = q;
+ return;
+ }
+
+ size = q->size;
+
+ tp = nil;
+ while(t != nil) {
+ if(size == t->size) {
+ q->fwd = t->fwd;
+ q->fwd->prev = q;
+ q->prev = t;
+ t->fwd = q;
+ return;
+ }
+ tp = t;
+ if(size < t->size)
+ t = t->left;
+ else
+ t = t->right;
+ }
+
+ q->parent = tp;
+ if(size < tp->size)
+ tp->left = q;
+ else
+ tp->right = q;
+}
+
+void*
+poolalloc(Pool *p, int size)
+{
+ Bhdr *q, *t;
+ int alloc, ldr, ns, frag;
+
+ if(size < 0 || size >= 1024*1024*1024) /* for sanity and to avoid overflow */
+ return nil;
+ size = (size + BHDRSIZE + p->quanta) & ~(p->quanta);
+
+ ilock(&p->l);
+ p->nalloc++;
+
+ t = p->root;
+ q = nil;
+ while(t) {
+ if(t->size == size) {
+ pooldel(p, t);
+ t->magic = MAGIC_A;
+ p->cursize += t->size;
+ if(p->cursize > p->hw)
+ p->hw = p->cursize;
+ iunlock(&p->l);
+ return B2D(t);
+ }
+ if(size < t->size) {
+ q = t;
+ t = t->left;
+ }
+ else
+ t = t->right;
+ }
+ if(q != nil) {
+ pooldel(p, q);
+ q->magic = MAGIC_A;
+ frag = q->size - size;
+ if(frag < (size>>2)) {
+ p->cursize += q->size;
+ if(p->cursize > p->hw)
+ p->hw = p->cursize;
+ iunlock(&p->l);
+ return B2D(q);
+ }
+ /* Split */
+ ns = q->size - size;
+ q->size = size;
+ B2T(q)->hdr = q;
+ t = B2NB(q);
+ t->size = ns;
+ B2T(t)->hdr = t;
+ pooladd(p, t);
+ p->cursize += q->size;
+ if(p->cursize > p->hw)
+ p->hw = p->cursize;
+ iunlock(&p->l);
+ return B2D(q);
+ }
+
+ ns = p->chunk;
+ if(size > ns)
+ ns = size;
+ ldr = p->quanta+1;
+
+ alloc = ns+ldr+sizeof(t->magic);
+ p->arenasize += alloc;
+ if(p->arenasize > p->maxsize) {
+ p->arenasize -= alloc;
+
+ if(poolcompact(p)) {
+ iunlock(&p->l);
+ return poolalloc(p, size);
+ }
+
+ iunlock(&p->l);
+ print("%s arena too large: size %d cursize %lud arenasize %lud maxsize %lud\n",
+ p->name, size, p->cursize, p->arenasize, p->maxsize);
+ return nil;
+ }
+
+ p->nbrk++;
+ t = xalloc(alloc);
+ if(t == nil) {
+ iunlock(&p->l);
+ return nil;
+ }
+
+ t->magic = MAGIC_E; /* Make a leader */
+ t->size = ldr;
+ t->csize = ns+ldr;
+ t->clink = p->chain;
+ p->chain = t;
+ B2T(t)->hdr = t;
+ t = B2NB(t);
+
+ t->magic = MAGIC_A; /* Make the block we are going to return */
+ t->size = size;
+ B2T(t)->hdr = t;
+ q = t;
+
+ ns -= size; /* Free the rest */
+ if(ns > 0) {
+ q = B2NB(t);
+ q->size = ns;
+ B2T(q)->hdr = q;
+ pooladd(p, q);
+ }
+ B2NB(q)->magic = MAGIC_E; /* Mark the end of the chunk */
+
+ p->cursize += t->size;
+ if(p->cursize > p->hw)
+ p->hw = p->cursize;
+ iunlock(&p->l);
+ return B2D(t);
+}
+
+void
+poolfree(Pool *p, void *v)
+{
+ Bhdr *b, *c;
+
+ D2B(b, v);
+
+ ilock(&p->l);
+ p->nfree++;
+ p->cursize -= b->size;
+
+ c = B2NB(b);
+ if(c->magic == MAGIC_F) { /* Join forward */
+ pooldel(p, c);
+ c->magic = 0;
+ b->size += c->size;
+ B2T(b)->hdr = b;
+ }
+
+ c = B2PT(b)->hdr;
+ if(c->magic == MAGIC_F) { /* Join backward */
+ pooldel(p, c);
+ b->magic = 0;
+ c->size += b->size;
+ b = c;
+ B2T(b)->hdr = b;
+ }
+
+ pooladd(p, b);
+ iunlock(&p->l);
+}
+
+int
+poolread(char *va, int count, ulong offset)
+{
+ Pool *p;
+ int n, i, signed_off;
+
+ n = 0;
+ signed_off = offset;
+ for(i = 0; i < table.n; i++) {
+ p = &table.pool[i];
+ n += snprint(va+n, count-n, "%11lud %11lud %11lud %11d %11d %11d %s\n",
+ p->cursize,
+ p->maxsize,
+ p->hw,
+ p->nalloc,
+ p->nfree,
+ p->nbrk,
+ p->name);
+
+ if(signed_off > 0) {
+ signed_off -= n;
+ if(signed_off < 0) {
+ memmove(va, va+n+signed_off, -signed_off);
+ n = -signed_off;
+ }
+ else
+ n = 0;
+ }
+
+ }
+ return n;
+}
+
+Lock pcxlock;
+struct {
+ ulong n;
+ ulong pc;
+} pcx[1024];
+
+static void
+remember(ulong pc, void *v)
+{
+ Bhdr *b;
+ int i;
+
+ if(v == nil)
+ return;
+
+ D2B(b, v);
+ if((b->size>>5) != 2)
+ return;
+
+ ilock(&pcxlock);
+ B2T(b)->pad = 0;
+ for(i = 0; i < 1024; i++)
+ if(pcx[i].pc == pc || pcx[i].pc == 0){
+ pcx[i].pc = pc;
+ pcx[i].n++;
+ B2T(b)->pad = i;
+ break;
+ }
+ iunlock(&pcxlock);
+}
+
+static void
+forget(void *v)
+{
+ Bhdr *b;
+
+ if(v == nil)
+ return;
+
+ D2B(b, v);
+ if((b->size>>5) != 2)
+ return;
+
+ ilock(&pcxlock);
+ pcx[B2T(b)->pad].n--;
+ iunlock(&pcxlock);
+}
+
+void*
+malloc(ulong size)
+{
+ void *v;
+
+ v = poolalloc(mainmem, size);
+remember(getcallerpc(&size), v);
+ if(v != nil)
+ memset(v, 0, size);
+ return v;
+}
+
+void*
+smalloc(ulong size)
+{
+ void *v;
+
+ for(;;) {
+ v = poolalloc(mainmem, size);
+remember(getcallerpc(&size), v);
+ if(v != nil)
+ break;
+ tsleep(&up->sleep, return0, 0, 100);
+ }
+ memset(v, 0, size);
+ return v;
+}
+
+void*
+mallocz(ulong size, int clr)
+{
+ void *v;
+
+ v = poolalloc(mainmem, size);
+remember(getcallerpc(&size), v);
+ if(clr && v != nil)
+ memset(v, 0, size);
+ return v;
+}
+
+void
+free(void *v)
+{
+ Bhdr *b;
+
+ if(v != nil) {
+forget(v);
+ D2B(b, v);
+ poolfree(mainmem, v);
+ }
+}
+
+void*
+realloc(void *v, ulong size)
+{
+ Bhdr *b;
+ void *nv;
+ int osize;
+
+ if(v == nil)
+ return malloc(size);
+
+ D2B(b, v);
+
+ osize = b->size - BHDRSIZE;
+ if(osize >= size)
+ return v;
+
+ nv = poolalloc(mainmem, size);
+remember(getcallerpc(&v), nv);
+ if(nv != nil) {
+ memmove(nv, v, osize);
+ free(v);
+ }
+ return nv;
+}
+
+int
+msize(void *v)
+{
+ Bhdr *b;
+
+ D2B(b, v);
+ return b->size - BHDRSIZE;
+}
+
+void*
+calloc(ulong n, ulong szelem)
+{
+ return malloc(n*szelem);
+}
+
+/*
+void
+pooldump(Bhdr *b, int d, int c)
+{
+ Bhdr *t;
+
+ if(b == nil)
+ return;
+
+ print("%.8lux %.8lux %.8lux %c %4d %d (f %.8lux p %.8lux)\n",
+ b, b->left, b->right, c, d, b->size, b->fwd, b->prev);
+ d++;
+ for(t = b->fwd; t != b; t = t->fwd)
+ print("\t%.8lux %.8lux %.8lux\n", t, t->prev, t->fwd);
+ pooldump(b->left, d, 'l');
+ pooldump(b->right, d, 'r');
+}
+
+
+void
+poolshow(void)
+{
+ int i;
+
+ for(i = 0; i < table.n; i++) {
+ print("Arena: %s root=%.8lux\n", table.pool[i].name, table.pool[i].root);
+ pooldump(table.pool[i].root, 0, 'R');
+ }
+}
+*/
+
+void
+poolsummary(void)
+{
+ int i;
+
+ for(i = 0; i < table.n; i++)
+ print("Arena: %s cursize=%lud; maxsize=%lud\n",
+ table.pool[i].name,
+ table.pool[i].cursize,
+ table.pool[i].maxsize);
+}
+
+/*
+void
+pooldump(Pool *p)
+{
+ Bhdr *b, *base, *limit, *ptr;
+
+ b = p->chain;
+ if(b == nil)
+ return;
+ base = b;
+ ptr = b;
+ limit = B2LIMIT(b);
+
+ while(base != nil) {
+ print("\tbase #%.8lux ptr #%.8lux", base, ptr);
+ if(ptr->magic == MAGIC_A)
+ print("\tA%.5d\n", ptr->size);
+ else if(ptr->magic == MAGIC_E)
+ print("\tE\tL#%.8lux\tS#%.8lux\n", ptr->clink, ptr->csize);
+ else
+ print("\tF%.5d\tL#%.8lux\tR#%.8lux\tF#%.8lux\tP#%.8lux\tT#%.8lux\n",
+ ptr->size, ptr->left, ptr->right, ptr->fwd, ptr->prev, ptr->parent);
+ ptr = B2NB(ptr);
+ if(ptr >= limit) {
+ print("link to #%.8lux\n", base->clink);
+ base = base->clink;
+ if(base == nil)
+ break;
+ ptr = base;
+ limit = B2LIMIT(base);
+ }
+ }
+ return;
+}
+*/
+
+void
+poolsetcompact(Pool *p, void (*move)(void*, void*))
+{
+ p->move = move;
+}
+
+void
+poolsetparam(char *name, ulong maxsize, int quanta, int chunk)
+{
+ Pool *p;
+ int i;
+
+ for(i=0; i<table.n; i++){
+ p = &table.pool[i];
+ if(strcmp(name, p->name) == 0){
+ if(maxsize)
+ p->maxsize = maxsize;
+ if(quanta)
+ p->quanta = quanta;
+ if(chunk)
+ p->chunk = chunk;
+ return;
+ }
+ }
+}
+
+int
+poolcompact(Pool *pool)
+{
+ Bhdr *base, *limit, *ptr, *end, *next;
+ int compacted, recov, nb;
+
+ if(pool->move == nil || pool->lastfree == pool->nfree)
+ return 0;
+
+ pool->lastfree = pool->nfree;
+
+ base = pool->chain;
+ ptr = B2NB(base); /* First Block in arena has clink */
+ limit = B2LIMIT(base);
+ compacted = 0;
+
+ pool->root = nil;
+ end = ptr;
+ recov = 0;
+ while(base != nil) {
+ next = B2NB(ptr);
+ if(ptr->magic == MAGIC_A) {
+ if(ptr != end) {
+ memmove(end, ptr, ptr->size);
+ pool->move(B2D(ptr), B2D(end));
+ recov = (uchar*)ptr - (uchar*)end;
+ compacted = 1;
+ }
+ end = B2NB(end);
+ }
+ if(next >= limit) {
+ nb = (uchar*)limit - (uchar*)end;
+ //print("recovered %d bytes\n", recov);
+ //print("%d bytes at end\n", nb);
+ USED(recov);
+ if(nb > 0){
+ if(nb < pool->quanta+1)
+ panic("poolcompact: leftover too small\n");
+ end->size = nb;
+ pooladd(pool, end);
+ }
+ base = base->clink;
+ if(base == nil)
+ break;
+ ptr = B2NB(base);
+ end = ptr; /* could do better by copying between chains */
+ limit = B2LIMIT(base);
+ recov = 0;
+ } else
+ ptr = next;
+ }
+
+ return compacted;
+}
+
+int
+recur(Bhdr *t)
+{
+ if(t == 0)
+ return 1;
+ if((uintptr)t < KZERO || (uintptr)t - KZERO > 0x10000000)
+ return 0;
+ return recur(t->right) && recur(t->left);
+}
diff --git a/sys/src/9/port/dev.c b/sys/src/9/port/dev.c
new file mode 100755
index 000000000..bbe1fcc12
--- /dev/null
+++ b/sys/src/9/port/dev.c
@@ -0,0 +1,449 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+extern ulong kerndate;
+
+void
+mkqid(Qid *q, vlong path, ulong vers, int type)
+{
+ q->type = type;
+ q->vers = vers;
+ q->path = path;
+}
+
+int
+devno(int c, int user)
+{
+ int i;
+
+ for(i = 0; devtab[i] != nil; i++) {
+ if(devtab[i]->dc == c)
+ return i;
+ }
+ if(user == 0)
+ panic("devno %C %#ux", c, c);
+
+ return -1;
+}
+
+void
+devdir(Chan *c, Qid qid, char *n, vlong length, char *user, long perm, Dir *db)
+{
+ db->name = n;
+ if(c->flag&CMSG)
+ qid.type |= QTMOUNT;
+ db->qid = qid;
+ db->type = devtab[c->type]->dc;
+ db->dev = c->dev;
+ db->mode = perm;
+ db->mode |= qid.type << 24;
+ db->atime = seconds();
+ db->mtime = kerndate;
+ db->length = length;
+ db->uid = user;
+ db->gid = eve;
+ db->muid = user;
+}
+
+/*
+ * (here, Devgen is the prototype; devgen is the function in dev.c.)
+ *
+ * a Devgen is expected to return the directory entry for ".."
+ * if you pass it s==DEVDOTDOT (-1). otherwise...
+ *
+ * there are two contradictory rules.
+ *
+ * (i) if c is a directory, a Devgen is expected to list its children
+ * as you iterate s.
+ *
+ * (ii) whether or not c is a directory, a Devgen is expected to list
+ * its siblings as you iterate s.
+ *
+ * devgen always returns the list of children in the root
+ * directory. thus it follows (i) when c is the root and (ii) otherwise.
+ * many other Devgens follow (i) when c is a directory and (ii) otherwise.
+ *
+ * devwalk assumes (i). it knows that devgen breaks (i)
+ * for children that are themselves directories, and explicitly catches them.
+ *
+ * devstat assumes (ii). if the Devgen in question follows (i)
+ * for this particular c, devstat will not find the necessary info.
+ * with our particular Devgen functions, this happens only for
+ * directories, so devstat makes something up, assuming
+ * c->name, c->qid, eve, DMDIR|0555.
+ *
+ * devdirread assumes (i). the callers have to make sure
+ * that the Devgen satisfies (i) for the chan being read.
+ */
+/*
+ * the zeroth element of the table MUST be the directory itself for ..
+*/
+int
+devgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
+{
+ if(tab == 0)
+ return -1;
+ if(i == DEVDOTDOT){
+ /* nothing */
+ }else if(name){
+ for(i=1; i<ntab; i++)
+ if(strcmp(tab[i].name, name) == 0)
+ break;
+ if(i==ntab)
+ return -1;
+ tab += i;
+ }else{
+ /* skip over the first element, that for . itself */
+ i++;
+ if(i >= ntab)
+ return -1;
+ tab += i;
+ }
+ devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
+ return 1;
+}
+
+void
+devreset(void)
+{
+}
+
+void
+devinit(void)
+{
+}
+
+void
+devshutdown(void)
+{
+}
+
+Chan*
+devattach(int tc, char *spec)
+{
+ int n;
+ Chan *c;
+ char *buf;
+
+ c = newchan();
+ mkqid(&c->qid, 0, 0, QTDIR);
+ c->type = devno(tc, 0);
+ if(spec == nil)
+ spec = "";
+ n = 1+UTFmax+strlen(spec)+1;
+ buf = smalloc(n);
+ snprint(buf, n, "#%C%s", tc, spec);
+ c->path = newpath(buf);
+ free(buf);
+ return c;
+}
+
+
+Chan*
+devclone(Chan *c)
+{
+ Chan *nc;
+
+ if(c->flag & COPEN)
+ panic("clone of open file type %C\n", devtab[c->type]->dc);
+
+ nc = newchan();
+
+ nc->type = c->type;
+ nc->dev = c->dev;
+ nc->mode = c->mode;
+ nc->qid = c->qid;
+ nc->offset = c->offset;
+ nc->umh = nil;
+ nc->aux = c->aux;
+ nc->mqid = c->mqid;
+ nc->mcp = c->mcp;
+ return nc;
+}
+
+Walkqid*
+devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen)
+{
+ int i, j, alloc;
+ Walkqid *wq;
+ char *n;
+ Dir dir;
+
+ if(nname > 0)
+ isdir(c);
+
+ alloc = 0;
+ wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
+ if(waserror()){
+ if(alloc && wq->clone!=nil)
+ cclose(wq->clone);
+ free(wq);
+ return nil;
+ }
+ if(nc == nil){
+ nc = devclone(c);
+ nc->type = 0; /* device doesn't know about this channel yet */
+ alloc = 1;
+ }
+ wq->clone = nc;
+
+ for(j=0; j<nname; j++){
+ if(!(nc->qid.type&QTDIR)){
+ if(j==0)
+ error(Enotdir);
+ goto Done;
+ }
+ n = name[j];
+ if(strcmp(n, ".") == 0){
+ Accept:
+ wq->qid[wq->nqid++] = nc->qid;
+ continue;
+ }
+ if(strcmp(n, "..") == 0){
+ if((*gen)(nc, nil, tab, ntab, DEVDOTDOT, &dir) != 1){
+ print("devgen walk .. in dev%s %llux broken\n",
+ devtab[nc->type]->name, nc->qid.path);
+ error("broken devgen");
+ }
+ nc->qid = dir.qid;
+ goto Accept;
+ }
+ /*
+ * Ugly problem: If we're using devgen, make sure we're
+ * walking the directory itself, represented by the first
+ * entry in the table, and not trying to step into a sub-
+ * directory of the table, e.g. /net/net. Devgen itself
+ * should take care of the problem, but it doesn't have
+ * the necessary information (that we're doing a walk).
+ */
+ if(gen==devgen && nc->qid.path!=tab[0].qid.path)
+ goto Notfound;
+ for(i=0;; i++) {
+ switch((*gen)(nc, n, tab, ntab, i, &dir)){
+ case -1:
+ Notfound:
+ if(j == 0)
+ error(Enonexist);
+ kstrcpy(up->errstr, Enonexist, ERRMAX);
+ goto Done;
+ case 0:
+ continue;
+ case 1:
+ if(strcmp(n, dir.name) == 0){
+ nc->qid = dir.qid;
+ goto Accept;
+ }
+ continue;
+ }
+ }
+ }
+ /*
+ * We processed at least one name, so will return some data.
+ * If we didn't process all nname entries succesfully, we drop
+ * the cloned channel and return just the Qids of the walks.
+ */
+Done:
+ poperror();
+ if(wq->nqid < nname){
+ if(alloc)
+ cclose(wq->clone);
+ wq->clone = nil;
+ }else if(wq->clone){
+ /* attach cloned channel to same device */
+ wq->clone->type = c->type;
+ }
+ return wq;
+}
+
+int
+devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen)
+{
+ int i;
+ Dir dir;
+ char *p, *elem;
+
+ for(i=0;; i++){
+ switch((*gen)(c, nil, tab, ntab, i, &dir)){
+ case -1:
+ if(c->qid.type & QTDIR){
+ if(c->path == nil)
+ elem = "???";
+ else if(strcmp(c->path->s, "/") == 0)
+ elem = "/";
+ else
+ for(elem=p=c->path->s; *p; p++)
+ if(*p == '/')
+ elem = p+1;
+ devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir);
+ n = convD2M(&dir, db, n);
+ if(n == 0)
+ error(Ebadarg);
+ return n;
+ }
+
+ error(Enonexist);
+ case 0:
+ break;
+ case 1:
+ if(c->qid.path == dir.qid.path) {
+ if(c->flag&CMSG)
+ dir.mode |= DMMOUNT;
+ n = convD2M(&dir, db, n);
+ if(n == 0)
+ error(Ebadarg);
+ return n;
+ }
+ break;
+ }
+ }
+}
+
+long
+devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen)
+{
+ long m, dsz;
+ Dir dir;
+
+ for(m=0; m<n; c->dri++) {
+ switch((*gen)(c, nil, tab, ntab, c->dri, &dir)){
+ case -1:
+ return m;
+
+ case 0:
+ break;
+
+ case 1:
+ dsz = convD2M(&dir, (uchar*)d, n-m);
+ if(dsz <= BIT16SZ){ /* <= not < because this isn't stat; read is stuck */
+ if(m == 0)
+ error(Eshort);
+ return m;
+ }
+ m += dsz;
+ d += dsz;
+ break;
+ }
+ }
+
+ return m;
+}
+
+/*
+ * error(Eperm) if open permission not granted for up->user.
+ */
+void
+devpermcheck(char *fileuid, ulong perm, int omode)
+{
+ ulong t;
+ static int access[] = { 0400, 0200, 0600, 0100 };
+
+ if(strcmp(up->user, fileuid) == 0)
+ perm <<= 0;
+ else
+ if(strcmp(up->user, eve) == 0)
+ perm <<= 3;
+ else
+ perm <<= 6;
+
+ t = access[omode&3];
+ if((t&perm) != t)
+ error(Eperm);
+}
+
+Chan*
+devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen)
+{
+ int i;
+ Dir dir;
+
+ for(i=0;; i++) {
+ switch((*gen)(c, nil, tab, ntab, i, &dir)){
+ case -1:
+ goto Return;
+ case 0:
+ break;
+ case 1:
+ if(c->qid.path == dir.qid.path) {
+ devpermcheck(dir.uid, dir.mode, omode);
+ goto Return;
+ }
+ break;
+ }
+ }
+Return:
+ c->offset = 0;
+ if((c->qid.type&QTDIR) && omode!=OREAD)
+ error(Eperm);
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ return c;
+}
+
+void
+devcreate(Chan*, char*, int, ulong)
+{
+ error(Eperm);
+}
+
+Block*
+devbread(Chan *c, long n, ulong offset)
+{
+ Block *bp;
+
+ bp = allocb(n);
+ if(bp == 0)
+ error(Enomem);
+ if(waserror()) {
+ freeb(bp);
+ nexterror();
+ }
+ bp->wp += devtab[c->type]->read(c, bp->wp, n, offset);
+ poperror();
+ return bp;
+}
+
+long
+devbwrite(Chan *c, Block *bp, ulong offset)
+{
+ long n;
+
+ if(waserror()) {
+ freeb(bp);
+ nexterror();
+ }
+ n = devtab[c->type]->write(c, bp->rp, BLEN(bp), offset);
+ poperror();
+ freeb(bp);
+
+ return n;
+}
+
+void
+devremove(Chan*)
+{
+ error(Eperm);
+}
+
+int
+devwstat(Chan*, uchar*, int)
+{
+ error(Eperm);
+ return 0;
+}
+
+void
+devpower(int)
+{
+ error(Eperm);
+}
+
+int
+devconfig(int, char *, DevConf *)
+{
+ error(Eperm);
+ return 0;
+}
diff --git a/sys/src/9/port/devaoe.c b/sys/src/9/port/devaoe.c
new file mode 100755
index 000000000..66f67f86a
--- /dev/null
+++ b/sys/src/9/port/devaoe.c
@@ -0,0 +1,2581 @@
+/*
+ * © 2005-2010 coraid
+ * aoe storage initiator
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+#include "etherif.h"
+#include "../ip/ip.h"
+#include "../port/aoe.h"
+
+#pragma varargck argpos eventlog 1
+
+#define dprint(...) if(debug) eventlog(__VA_ARGS__); else USED(debug);
+#define uprint(...) snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__);
+
+enum {
+ Maxunits = 0xff,
+ Maxframes = 128,
+ Ndevlink = 6,
+ Nea = 6,
+ Nnetlink = 6,
+};
+
+#define TYPE(q) ((ulong)(q).path & 0xf)
+#define UNIT(q) (((ulong)(q).path>>4) & 0xff)
+#define L(q) (((ulong)(q).path>>12) & 0xf)
+#define QID(u, t) ((u)<<4 | (t))
+#define Q3(l, u, t) ((l)<<8 | QID(u, t))
+#define UP(d) ((d)->flag & Dup)
+/*
+ * would like this to depend on the chan (srb).
+ * not possible in the current structure.
+ */
+#define Nofail(d, s) ((d)->flag & Dnofail)
+
+#define MS2TK(t) ((t)/MS2HZ)
+
+enum {
+ Qzero,
+ Qtopdir = 1,
+ Qtopbase,
+ Qtopctl = Qtopbase,
+ Qtoplog,
+ Qtopend,
+
+ Qunitdir,
+ Qunitbase,
+ Qctl = Qunitbase,
+ Qdata,
+ Qconfig,
+ Qident,
+
+ Qdevlinkdir,
+ Qdevlinkbase,
+ Qdevlink = Qdevlinkbase,
+ Qdevlinkend,
+
+ Qtopfiles = Qtopend-Qtopbase,
+ Qdevlinkfiles = Qdevlinkend-Qdevlinkbase,
+
+ Eventlen = 256,
+ Nevents = 64, /* must be power of 2 */
+
+ Fread = 0,
+ Fwrite,
+ Tfree = -1,
+ Tmgmt,
+
+ /*
+ * round trip bounds, timeouts, in ticks.
+ * timeouts should be long enough that rebooting
+ * the coraid (which usually takes under two minutes)
+ * doesn't trigger a timeout.
+ */
+ Rtmax = MS2TK(320),
+ Rtmin = MS2TK(20),
+ Maxreqticks = 4*60*HZ, /* was 45*HZ */
+
+ Dbcnt = 1024,
+
+ Crd = 0x20,
+ Crdext = 0x24,
+ Cwr = 0x30,
+ Cwrext = 0x34,
+ Cid = 0xec,
+};
+
+enum {
+ Read,
+ Write,
+};
+
+/*
+ * unified set of flags
+ * a Netlink + Aoedev most both be jumbo capable
+ * to send jumbograms to that interface.
+ */
+enum {
+ /* sync with ahci.h */
+ Dllba = 1<<0,
+ Dsmart = 1<<1,
+ Dpower = 1<<2,
+ Dnop = 1<<3,
+ Datapi = 1<<4,
+ Datapi16= 1<<5,
+
+ /* aoe specific */
+ Dup = 1<<6,
+ Djumbo = 1<<7,
+ Dnofail = 1<<8,
+};
+
+static char *flagname[] = {
+ "llba",
+ "smart",
+ "power",
+ "nop",
+ "atapi",
+ "atapi16",
+
+ "up",
+ "jumbo",
+ "nofail",
+};
+
+typedef struct {
+ ushort flag;
+ uint lostjumbo;
+ int datamtu;
+
+ Chan *cc;
+ Chan *dc;
+ Chan *mtu; /* open early to prevent bind issues. */
+ char path[Maxpath];
+ uchar ea[Eaddrlen];
+} Netlink;
+
+typedef struct {
+ Netlink *nl;
+ int nea;
+ ulong eaidx;
+ uchar eatab[Nea][Eaddrlen];
+ ulong npkt;
+ ulong resent;
+ ushort flag;
+
+ ulong rttavg;
+ ulong mintimer;
+} Devlink;
+
+typedef struct Srb Srb;
+struct Srb {
+ Rendez;
+ Srb *next;
+ ulong ticksent;
+ ulong len;
+ vlong sector;
+ short write;
+ short nout;
+ char *error;
+ void *dp;
+ void *data;
+};
+
+typedef struct {
+ int tag;
+ ulong bcnt;
+ ulong dlen;
+ vlong lba;
+ ulong ticksent;
+ int nhdr;
+ uchar hdr[ETHERMINTU];
+ void *dp;
+ Devlink *dl;
+ Netlink *nl;
+ int eaidx;
+ Srb *srb;
+} Frame;
+
+typedef struct Aoedev Aoedev;
+struct Aoedev {
+ QLock;
+ Aoedev *next;
+
+ ulong vers;
+
+ int ndl;
+ ulong dlidx;
+ Devlink *dl;
+ Devlink dltab[Ndevlink];
+
+ ushort fwver;
+ ushort flag;
+ int nopen;
+ int major;
+ int minor;
+ int unit;
+ int lasttag;
+ int nframes;
+ Frame *frames;
+ vlong bsize;
+ vlong realbsize;
+
+ uint maxbcnt;
+ ushort nout;
+ ushort maxout;
+ ulong lastwadj;
+ Srb *head;
+ Srb *tail;
+ Srb *inprocess;
+
+ /* magic numbers 'R' us */
+ char serial[20+1];
+ char firmware[8+1];
+ char model[40+1];
+ int nconfig;
+ uchar config[1024];
+ uchar ident[512];
+};
+
+#pragma varargck type "æ" Aoedev*
+
+static struct {
+ Lock;
+ QLock;
+ Rendez;
+ char buf[Eventlen*Nevents];
+ char *rp;
+ char *wp;
+} events;
+
+static struct {
+ RWlock;
+ int nd;
+ Aoedev *d;
+} devs;
+
+static struct {
+ Lock;
+ int reader[Nnetlink]; /* reader is running. */
+ Rendez rendez[Nnetlink]; /* confirm exit. */
+ Netlink nl[Nnetlink];
+} netlinks;
+
+extern Dev aoedevtab;
+static Ref units;
+static Ref drivevers;
+static int debug;
+static int autodiscover = 1;
+static int rediscover;
+
+char Enotup[] = "aoe device is down";
+char Echange[] = "media or partition has changed";
+
+static Srb*
+srballoc(ulong sz)
+{
+ Srb *srb;
+
+ srb = malloc(sizeof *srb+sz);
+ srb->dp = srb->data = srb+1;
+ srb->ticksent = MACHP(0)->ticks;
+ return srb;
+}
+
+static Srb*
+srbkalloc(void *db, ulong)
+{
+ Srb *srb;
+
+ srb = malloc(sizeof *srb);
+ srb->dp = srb->data = db;
+ srb->ticksent = MACHP(0)->ticks;
+ return srb;
+}
+
+#define srbfree(srb) free(srb)
+
+static void
+srberror(Srb *srb, char *s)
+{
+ srb->error = s;
+ srb->nout--;
+ if (srb->nout == 0)
+ wakeup(srb);
+}
+
+static void
+frameerror(Aoedev *d, Frame *f, char *s)
+{
+ Srb *srb;
+
+ srb = f->srb;
+ if(f->tag == Tfree || !srb)
+ return;
+ f->srb = nil;
+ f->tag = Tfree; /* don't get fooled by way-slow responses */
+ srberror(srb, s);
+ d->nout--;
+}
+
+static char*
+unitname(Aoedev *d)
+{
+ uprint("%d.%d", d->major, d->minor);
+ return up->genbuf;
+}
+
+static int
+eventlogready(void*)
+{
+ return *events.rp;
+}
+
+static long
+eventlogread(void *a, long n)
+{
+ int len;
+ char *p, *buf;
+
+ buf = smalloc(Eventlen);
+ qlock(&events);
+ lock(&events);
+ p = events.rp;
+ len = *p;
+ if(len == 0){
+ n = 0;
+ unlock(&events);
+ } else {
+ if(n > len)
+ n = len;
+ /* can't move directly into pageable space with events lock held */
+ memmove(buf, p+1, n);
+ *p = 0;
+ events.rp = p += Eventlen;
+ if(p >= events.buf + sizeof events.buf)
+ events.rp = events.buf;
+ unlock(&events);
+
+ /* the concern here is page faults in memmove below */
+ if(waserror()){
+ free(buf);
+ qunlock(&events);
+ nexterror();
+ }
+ memmove(a, buf, n);
+ poperror();
+ }
+ free(buf);
+ qunlock(&events);
+ return n;
+}
+
+static int
+eventlog(char *fmt, ...)
+{
+ int dragrp, n;
+ char *p;
+ va_list arg;
+
+ lock(&events);
+ p = events.wp;
+ dragrp = *p++;
+ va_start(arg, fmt);
+ n = vsnprint(p, Eventlen-1, fmt, arg);
+ *--p = n;
+ p = events.wp += Eventlen;
+ if(p >= events.buf + sizeof events.buf)
+ p = events.wp = events.buf;
+ if(dragrp)
+ events.rp = p;
+ unlock(&events);
+ wakeup(&events);
+ return n;
+}
+
+static int
+eventcount(void)
+{
+ int n;
+
+ lock(&events);
+ if(*events.rp == 0)
+ n = 0;
+ else
+ n = (events.wp - events.rp) & (Nevents - 1);
+ unlock(&events);
+ return n/Eventlen;
+}
+
+static int
+tsince(int tag)
+{
+ int n;
+
+ n = MACHP(0)->ticks & 0xffff;
+ n -= tag & 0xffff;
+ if(n < 0)
+ n += 1<<16;
+ return n;
+}
+
+static int
+newtag(Aoedev *d)
+{
+ int t;
+
+ do {
+ t = ++d->lasttag << 16;
+ t |= MACHP(0)->ticks & 0xffff;
+ } while (t == Tfree || t == Tmgmt);
+ return t;
+}
+
+static void
+downdev(Aoedev *d, char *err)
+{
+ Frame *f, *e;
+
+ d->flag &= ~Dup;
+ f = d->frames;
+ e = f + d->nframes;
+ for(; f < e; f->tag = Tfree, f->srb = nil, f++)
+ frameerror(d, f, Enotup);
+ d->inprocess = nil;
+ eventlog("%æ: removed; %s\n", d, err);
+}
+
+static Block*
+allocfb(Frame *f)
+{
+ int len;
+ Block *b;
+
+ len = f->nhdr + f->dlen;
+ if(len < ETHERMINTU)
+ len = ETHERMINTU;
+ b = allocb(len);
+ memmove(b->wp, f->hdr, f->nhdr);
+ if(f->dlen)
+ memmove(b->wp + f->nhdr, f->dp, f->dlen);
+ b->wp += len;
+ return b;
+}
+
+static void
+putlba(Aoeata *a, vlong lba)
+{
+ uchar *c;
+
+ c = a->lba;
+ c[0] = lba;
+ c[1] = lba >> 8;
+ c[2] = lba >> 16;
+ c[3] = lba >> 24;
+ c[4] = lba >> 32;
+ c[5] = lba >> 40;
+}
+
+static Devlink*
+pickdevlink(Aoedev *d)
+{
+ ulong i, n;
+ Devlink *l;
+
+ for(i = 0; i < d->ndl; i++){
+ n = d->dlidx++ % d->ndl;
+ l = d->dl + n;
+ if(l && l->flag & Dup)
+ return l;
+ }
+ return 0;
+}
+
+static int
+pickea(Devlink *l)
+{
+ if(l == 0)
+ return -1;
+ if(l->nea == 0)
+ return -1;
+ return l->eaidx++ % l->nea;
+}
+
+static int
+hset(Aoedev *d, Frame *f, Aoehdr *h, int cmd)
+{
+ int i;
+ Devlink *l;
+
+ if(f->srb && MACHP(0)->ticks - f->srb->ticksent > Maxreqticks){
+ eventlog("%æ: srb timeout\n", d);
+ if(cmd == ACata && f->srb && Nofail(d, s))
+ f->srb->ticksent = MACHP(0)->ticks;
+ else
+ frameerror(d, f, Etimedout);
+ return -1;
+ }
+ l = pickdevlink(d);
+ i = pickea(l);
+ if(i == -1){
+ if(cmd != ACata || f->srb == nil || !Nofail(d, s))
+ downdev(d, "resend fails; no netlink/ea");
+ return -1;
+ }
+ memmove(h->dst, l->eatab[i], Eaddrlen);
+ memmove(h->src, l->nl->ea, sizeof h->src);
+ hnputs(h->type, Aoetype);
+ h->verflag = Aoever << 4;
+ h->error = 0;
+ hnputs(h->major, d->major);
+ h->minor = d->minor;
+ h->cmd = cmd;
+
+ hnputl(h->tag, f->tag = newtag(d));
+ f->dl = l;
+ f->nl = l->nl;
+ f->eaidx = i;
+ f->ticksent = MACHP(0)->ticks;
+
+ return f->tag;
+}
+
+static int
+resend(Aoedev *d, Frame *f)
+{
+ ulong n;
+ Aoeata *a;
+
+ a = (Aoeata*)f->hdr;
+ if(hset(d, f, a, a->cmd) == -1)
+ return -1;
+ n = f->bcnt;
+ if(n > d->maxbcnt){
+ n = d->maxbcnt; /* mtu mismatch (jumbo fail?) */
+ if(f->dlen > n)
+ f->dlen = n;
+ }
+ a->scnt = n / Aoesectsz;
+ f->dl->resent++;
+ f->dl->npkt++;
+ if(waserror())
+ return -1;
+ devtab[f->nl->dc->type]->bwrite(f->nl->dc, allocfb(f), 0);
+ poperror();
+ return 0;
+}
+
+static void
+discover(int major, int minor)
+{
+ Aoehdr *h;
+ Block *b;
+ Netlink *nl, *e;
+
+ nl = netlinks.nl;
+ e = nl + nelem(netlinks.nl);
+ for(; nl < e; nl++){
+ if(nl->cc == nil)
+ continue;
+ b = allocb(ETHERMINTU);
+ if(waserror()){
+ freeb(b);
+ nexterror();
+ }
+ b->wp = b->rp + ETHERMINTU;
+ memset(b->rp, 0, ETHERMINTU);
+ h = (Aoehdr*)b->rp;
+ memset(h->dst, 0xff, sizeof h->dst);
+ memmove(h->src, nl->ea, sizeof h->src);
+ hnputs(h->type, Aoetype);
+ h->verflag = Aoever << 4;
+ hnputs(h->major, major);
+ h->minor = minor;
+ h->cmd = ACconfig;
+ poperror();
+ /* send b down the queue */
+ devtab[nl->dc->type]->bwrite(nl->dc, b, 0);
+ }
+}
+
+/*
+ * Check all frames on device and resend any frames that have been
+ * outstanding for 200% of the device round trip time average.
+ */
+static void
+aoesweepproc(void*)
+{
+ ulong i, tx, timeout, nbc;
+ vlong starttick;
+ enum { Nms = 100, Nbcms = 30*1000, }; /* magic */
+ uchar *ea;
+ Aoeata *a;
+ Aoedev *d;
+ Devlink *l;
+ Frame *f, *e;
+
+ nbc = Nbcms/Nms;
+loop:
+ if(nbc-- == 0){
+ if(rediscover && !waserror()){
+ discover(0xffff, 0xff);
+ poperror();
+ }
+ nbc = Nbcms/Nms;
+ }
+ starttick = MACHP(0)->ticks;
+ rlock(&devs);
+ for(d = devs.d; d; d = d->next){
+ if(!canqlock(d))
+ continue;
+ if(!UP(d)){
+ qunlock(d);
+ continue;
+ }
+ tx = 0;
+ f = d->frames;
+ e = f + d->nframes;
+ for (; f < e; f++){
+ if(f->tag == Tfree)
+ continue;
+ l = f->dl;
+ timeout = l->rttavg << 1;
+ i = tsince(f->tag);
+ if(i < timeout)
+ continue;
+ if(d->nout == d->maxout){
+ if(d->maxout > 1)
+ d->maxout--;
+ d->lastwadj = MACHP(0)->ticks;
+ }
+ a = (Aoeata*)f->hdr;
+ if(a->scnt > Dbcnt / Aoesectsz &&
+ ++f->nl->lostjumbo > (d->nframes << 1)){
+ ea = f->dl->eatab[f->eaidx];
+ eventlog("%æ: jumbo failure on %s:%E; lba%lld\n",
+ d, f->nl->path, ea, f->lba);
+ d->maxbcnt = Dbcnt;
+ d->flag &= ~Djumbo;
+ }
+ resend(d, f);
+ if(tx++ == 0){
+ if((l->rttavg <<= 1) > Rtmax)
+ l->rttavg = Rtmax;
+ eventlog("%æ: rtt %ldms\n", d, TK2MS(l->rttavg));
+ }
+ }
+ if(d->nout == d->maxout && d->maxout < d->nframes &&
+ TK2MS(MACHP(0)->ticks - d->lastwadj) > 10*1000){ /* more magic */
+ d->maxout++;
+ d->lastwadj = MACHP(0)->ticks;
+ }
+ qunlock(d);
+ }
+ runlock(&devs);
+ i = Nms - TK2MS(MACHP(0)->ticks - starttick);
+ if(i > 0)
+ tsleep(&up->sleep, return0, 0, i);
+ goto loop;
+}
+
+static int
+fmtæ(Fmt *f)
+{
+ char buf[16];
+ Aoedev *d;
+
+ d = va_arg(f->args, Aoedev*);
+ snprint(buf, sizeof buf, "aoe%d.%d", d->major, d->minor);
+ return fmtstrcpy(f, buf);
+}
+
+static void netbind(char *path);
+
+static void
+aoecfg(void)
+{
+ int n, i;
+ char *p, *f[32], buf[24];
+
+ if((p = getconf("aoeif")) == nil || (n = tokenize(p, f, nelem(f))) < 1)
+ return;
+ /* goo! */
+ for(i = 0; i < n; i++){
+ p = f[i];
+ if(strncmp(p, "ether", 5) == 0)
+ snprint(buf, sizeof buf, "#l%c/ether%c", p[5], p[5]);
+ else if(strncmp(p, "#l", 2) == 0)
+ snprint(buf, sizeof buf, "#l%c/ether%c", p[2], p[2]);
+ else
+ continue;
+ if(!waserror()){
+ netbind(buf);
+ poperror();
+ }
+ }
+}
+
+static void
+aoeinit(void)
+{
+ static int init;
+ static QLock l;
+
+ if(!canqlock(&l))
+ return;
+ if(init == 0){
+ fmtinstall(L'æ', fmtæ);
+ events.rp = events.wp = events.buf;
+ kproc("aoesweep", aoesweepproc, nil);
+ aoecfg();
+ init = 1;
+ }
+ qunlock(&l);
+}
+
+static Chan*
+aoeattach(char *spec)
+{
+ Chan *c;
+
+ if(*spec)
+ error(Enonexist);
+ aoeinit();
+ c = devattach(L'æ', spec);
+ mkqid(&c->qid, Qzero, 0, QTDIR);
+ return c;
+}
+
+static Aoedev*
+unit2dev(ulong unit)
+{
+ int i;
+ Aoedev *d;
+
+ rlock(&devs);
+ i = 0;
+ for(d = devs.d; d; d = d->next)
+ if(i++ == unit){
+ runlock(&devs);
+ return d;
+ }
+ runlock(&devs);
+ uprint("unit lookup failure: %lux pc %#p", unit, getcallerpc(&unit));
+ error(up->genbuf);
+ return nil;
+}
+
+static int
+unitgen(Chan *c, ulong type, Dir *dp)
+{
+ int perm, t;
+ ulong vers;
+ vlong size;
+ char *p;
+ Aoedev *d;
+ Qid q;
+
+ d = unit2dev(UNIT(c->qid));
+ perm = 0644;
+ size = 0;
+ vers = d->vers;
+ t = QTFILE;
+
+ switch(type){
+ default:
+ return -1;
+ case Qctl:
+ p = "ctl";
+ break;
+ case Qdata:
+ p = "data";
+ perm = 0640;
+ if(UP(d))
+ size = d->bsize;
+ break;
+ case Qconfig:
+ p = "config";
+ if(UP(d))
+ size = d->nconfig;
+ break;
+ case Qident:
+ p = "ident";
+ if(UP(d))
+ size = sizeof d->ident;
+ break;
+ case Qdevlinkdir:
+ p = "devlink";
+ t = QTDIR;
+ perm = 0555;
+ break;
+ }
+ mkqid(&q, QID(UNIT(c->qid), type), vers, t);
+ devdir(c, q, p, size, eve, perm, dp);
+ return 1;
+}
+
+static int
+topgen(Chan *c, ulong type, Dir *d)
+{
+ int perm;
+ vlong size;
+ char *p;
+ Qid q;
+
+ perm = 0444;
+ size = 0;
+ switch(type){
+ default:
+ return -1;
+ case Qtopctl:
+ p = "ctl";
+ perm = 0644;
+ break;
+ case Qtoplog:
+ p = "log";
+ size = eventcount();
+ break;
+ }
+ mkqid(&q, type, 0, QTFILE);
+ devdir(c, q, p, size, eve, perm, d);
+ return 1;
+}
+
+static int
+aoegen(Chan *c, char *, Dirtab *, int, int s, Dir *dp)
+{
+ int i;
+ Aoedev *d;
+ Qid q;
+
+ if(c->qid.path == 0){
+ switch(s){
+ case DEVDOTDOT:
+ q.path = 0;
+ q.type = QTDIR;
+ devdir(c, q, "#æ", 0, eve, 0555, dp);
+ break;
+ case 0:
+ q.path = Qtopdir;
+ q.type = QTDIR;
+ devdir(c, q, "aoe", 0, eve, 0555, dp);
+ break;
+ default:
+ return -1;
+ }
+ return 1;
+ }
+
+ switch(TYPE(c->qid)){
+ default:
+ return -1;
+ case Qtopdir:
+ if(s == DEVDOTDOT){
+ mkqid(&q, Qzero, 0, QTDIR);
+ devdir(c, q, "aoe", 0, eve, 0555, dp);
+ return 1;
+ }
+ if(s < Qtopfiles)
+ return topgen(c, Qtopbase + s, dp);
+ s -= Qtopfiles;
+ if(s >= units.ref)
+ return -1;
+ mkqid(&q, QID(s, Qunitdir), 0, QTDIR);
+ d = unit2dev(s);
+ assert(d != nil);
+ devdir(c, q, unitname(d), 0, eve, 0555, dp);
+ return 1;
+ case Qtopctl:
+ case Qtoplog:
+ return topgen(c, TYPE(c->qid), dp);
+ case Qunitdir:
+ if(s == DEVDOTDOT){
+ mkqid(&q, QID(0, Qtopdir), 0, QTDIR);
+ uprint("%uld", UNIT(c->qid));
+ devdir(c, q, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+ }
+ return unitgen(c, Qunitbase+s, dp);
+ case Qctl:
+ case Qdata:
+ case Qconfig:
+ case Qident:
+ return unitgen(c, TYPE(c->qid), dp);
+ case Qdevlinkdir:
+ i = UNIT(c->qid);
+ if(s == DEVDOTDOT){
+ mkqid(&q, QID(i, Qunitdir), 0, QTDIR);
+ devdir(c, q, "devlink", 0, eve, 0555, dp);
+ return 1;
+ }
+ if(i >= units.ref)
+ return -1;
+ d = unit2dev(i);
+ if(s >= d->ndl)
+ return -1;
+ uprint("%d", s);
+ mkqid(&q, Q3(s, i, Qdevlink), 0, QTFILE);
+ devdir(c, q, up->genbuf, 0, eve, 0755, dp);
+ return 1;
+ case Qdevlink:
+ uprint("%d", s);
+ mkqid(&q, Q3(s, UNIT(c->qid), Qdevlink), 0, QTFILE);
+ devdir(c, q, up->genbuf, 0, eve, 0755, dp);
+ return 1;
+ }
+}
+
+static Walkqid*
+aoewalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, nil, 0, aoegen);
+}
+
+static int
+aoestat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, nil, 0, aoegen);
+}
+
+static Chan*
+aoeopen(Chan *c, int omode)
+{
+ Aoedev *d;
+
+ if(TYPE(c->qid) != Qdata)
+ return devopen(c, omode, 0, 0, aoegen);
+
+ d = unit2dev(UNIT(c->qid));
+ qlock(d);
+ if(waserror()){
+ qunlock(d);
+ nexterror();
+ }
+ if(!UP(d))
+ error(Enotup);
+ c = devopen(c, omode, 0, 0, aoegen);
+ d->nopen++;
+ poperror();
+ qunlock(d);
+ return c;
+}
+
+static void
+aoeclose(Chan *c)
+{
+ Aoedev *d;
+
+ if(TYPE(c->qid) != Qdata || (c->flag&COPEN) == 0)
+ return;
+
+ d = unit2dev(UNIT(c->qid));
+ qlock(d);
+ if(--d->nopen == 0 && !waserror()){
+ discover(d->major, d->minor);
+ poperror();
+ }
+ qunlock(d);
+}
+
+static void
+atarw(Aoedev *d, Frame *f)
+{
+ ulong bcnt;
+ char extbit, writebit;
+ Aoeata *ah;
+ Srb *srb;
+
+ extbit = 0x4;
+ writebit = 0x10;
+
+ srb = d->inprocess;
+ bcnt = d->maxbcnt;
+ if(bcnt > srb->len)
+ bcnt = srb->len;
+ f->nhdr = AOEATASZ;
+ memset(f->hdr, 0, f->nhdr);
+ ah = (Aoeata*)f->hdr;
+ if(hset(d, f, ah, ACata) == -1) {
+ d->inprocess = nil;
+ return;
+ }
+ f->dp = srb->dp;
+ f->bcnt = bcnt;
+ f->lba = srb->sector;
+ f->srb = srb;
+
+ ah->scnt = bcnt / Aoesectsz;
+ putlba(ah, f->lba);
+ if(d->flag & Dllba)
+ ah->aflag |= AAFext;
+ else {
+ extbit = 0;
+ ah->lba[3] &= 0x0f;
+ ah->lba[3] |= 0xe0; /* LBA bit+obsolete 0xa0 */
+ }
+ if(srb->write){
+ ah->aflag |= AAFwrite;
+ f->dlen = bcnt;
+ }else{
+ writebit = 0;
+ f->dlen = 0;
+ }
+ ah->cmdstat = 0x20 | writebit | extbit;
+
+ /* mark tracking fields and load out */
+ srb->nout++;
+ srb->dp = (uchar*)srb->dp + bcnt;
+ srb->len -= bcnt;
+ srb->sector += bcnt / Aoesectsz;
+ if(srb->len == 0)
+ d->inprocess = nil;
+ d->nout++;
+ f->dl->npkt++;
+ if(waserror()){
+ f->tag = Tfree;
+ d->inprocess = nil;
+ nexterror();
+ }
+ devtab[f->nl->dc->type]->bwrite(f->nl->dc, allocfb(f), 0);
+ poperror();
+}
+
+static char*
+aoeerror(Aoehdr *h)
+{
+ int n;
+ static char *errs[] = {
+ "aoe protocol error: unknown",
+ "aoe protocol error: bad command code",
+ "aoe protocol error: bad argument param",
+ "aoe protocol error: device unavailable",
+ "aoe protocol error: config string present",
+ "aoe protocol error: unsupported version",
+ "aoe protocol error: target is reserved",
+ };
+
+ if((h->verflag & AFerr) == 0)
+ return 0;
+ n = h->error;
+ if(n > nelem(errs))
+ n = 0;
+ return errs[n];
+}
+
+static void
+rtupdate(Devlink *l, int rtt)
+{
+ int n;
+
+ n = rtt;
+ if(rtt < 0){
+ n = -rtt;
+ if(n < Rtmin)
+ n = Rtmin;
+ else if(n > Rtmax)
+ n = Rtmax;
+ l->mintimer += (n - l->mintimer) >> 1;
+ } else if(n < l->mintimer)
+ n = l->mintimer;
+ else if(n > Rtmax)
+ n = Rtmax;
+
+ /* g == .25; cf. Congestion Avoidance and Control, Jacobson&Karels; 1988 */
+ n -= l->rttavg;
+ l->rttavg += n >> 2;
+}
+
+static int
+srbready(void *v)
+{
+ Srb *s;
+
+ s = v;
+ return s->error || (!s->nout && !s->len);
+}
+
+static Frame*
+getframe(Aoedev *d, int tag)
+{
+ Frame *f, *e;
+
+ f = d->frames;
+ e = f + d->nframes;
+ for(; f < e; f++)
+ if(f->tag == tag)
+ return f;
+ return nil;
+}
+
+static Frame*
+freeframe(Aoedev *d)
+{
+ if(d->nout < d->maxout)
+ return getframe(d, Tfree);
+ return nil;
+}
+
+static void
+work(Aoedev *d)
+{
+ Frame *f;
+
+ while ((f = freeframe(d)) != nil) {
+ if(d->inprocess == nil){
+ if(d->head == nil)
+ return;
+ d->inprocess = d->head;
+ d->head = d->head->next;
+ if(d->head == nil)
+ d->tail = nil;
+ }
+ atarw(d, f);
+ }
+}
+
+static void
+strategy(Aoedev *d, Srb *srb)
+{
+ qlock(d);
+ if(waserror()){
+ qunlock(d);
+ nexterror();
+ }
+ srb->next = nil;
+ if(d->tail)
+ d->tail->next = srb;
+ d->tail = srb;
+ if(d->head == nil)
+ d->head = srb;
+ work(d);
+ poperror();
+ qunlock(d);
+
+ while(waserror())
+ ;
+ sleep(srb, srbready, srb);
+ poperror();
+}
+
+#define iskaddr(a) ((uintptr)(a) > KZERO)
+
+static long
+rw(Aoedev *d, int write, uchar *db, long len, uvlong off)
+{
+ long n, nlen, copy;
+ enum { Srbsz = 1<<19, }; /* magic allocation */
+ Srb *srb;
+
+ if((off|len) & (Aoesectsz-1))
+ error("offset and length must be sector multiple.\n");
+ if(off > d->bsize || len == 0)
+ return 0;
+ if(off + len > d->bsize)
+ len = d->bsize - off;
+ copy = 0;
+ if(iskaddr(db)){
+ srb = srbkalloc(db, len);
+ copy = 1;
+ }else
+ srb = srballoc(Srbsz <= len? Srbsz: len);
+ if(waserror()){
+ srbfree(srb);
+ nexterror();
+ }
+ nlen = len;
+ srb->write = write;
+ do {
+ if(!UP(d))
+ error(Eio);
+ srb->sector = off / Aoesectsz;
+ srb->dp = srb->data;
+ n = nlen;
+ if(n > Srbsz)
+ n = Srbsz;
+ srb->len = n;
+ if(write && !copy)
+ memmove(srb->data, db, n);
+ strategy(d, srb);
+ if(srb->error)
+ error(srb->error);
+ if(!write && !copy)
+ memmove(db, srb->data, n);
+ nlen -= n;
+ db += n;
+ off += n;
+ } while (nlen > 0);
+ poperror();
+ srbfree(srb);
+ return len;
+}
+
+static long
+readmem(ulong off, void *dst, long n, void *src, long size)
+{
+ if(off >= size)
+ return 0;
+ if(off + n > size)
+ n = size - off;
+ memmove(dst, (uchar*)src + off, n);
+ return n;
+}
+
+static char *
+pflag(char *s, char *e, uchar f)
+{
+ uchar i, m;
+
+ for(i = 0; i < 8; i++){
+ m = 1 << i;
+ if(f & m)
+ s = seprint(s, e, "%s ", flagname[i]? flagname[i]: "oops");
+ }
+ return seprint(s, e, "\n");
+}
+
+static int
+pstat(Aoedev *d, char *db, int len, int off)
+{
+ int i;
+ char *state, *s, *p, *e;
+
+ s = p = malloc(READSTR);
+ e = p + READSTR;
+
+ state = "down";
+ if(UP(d))
+ state = "up";
+
+ p = seprint(p, e,
+ "state: %s\n" "nopen: %d\n" "nout: %d\n"
+ "nmaxout: %d\n" "nframes: %d\n" "maxbcnt: %d\n"
+ "fw: %.4ux\n"
+ "model: %s\n" "serial: %s\n" "firmware: %s\n",
+ state, d->nopen, d->nout,
+ d->maxout, d->nframes, d->maxbcnt,
+ d->fwver,
+ d->model, d->serial, d->firmware);
+ p = seprint(p, e, "flag: ");
+ p = pflag(p, e, d->flag);
+
+ if(p - s < len)
+ len = p - s;
+ i = readstr(off, db, len, s);
+ free(s);
+ return i;
+}
+
+static long
+unitread(Chan *c, void *db, long len, vlong off)
+{
+ Aoedev *d;
+
+ d = unit2dev(UNIT(c->qid));
+ if(d->vers != c->qid.vers)
+ error(Echange);
+ switch(TYPE(c->qid)){
+ default:
+ error(Ebadarg);
+ case Qctl:
+ return pstat(d, db, len, off);
+ case Qdata:
+ return rw(d, Read, db, len, off);
+ case Qconfig:
+ if (!UP(d))
+ error(Enotup);
+ return readmem(off, db, len, d->config, d->nconfig);
+ case Qident:
+ if (!UP(d))
+ error(Enotup);
+ return readmem(off, db, len, d->ident, sizeof d->ident);
+ }
+}
+
+static int
+devlinkread(Chan *c, void *db, int len, int off)
+{
+ int i;
+ char *s, *p, *e;
+ Aoedev *d;
+ Devlink *l;
+
+ d = unit2dev(UNIT(c->qid));
+ i = L(c->qid);
+ if(i >= d->ndl)
+ return 0;
+ l = d->dl + i;
+
+ s = p = malloc(READSTR);
+ e = s + READSTR;
+
+ p = seprint(p, e, "addr: ");
+ for(i = 0; i < l->nea; i++)
+ p = seprint(p, e, "%E ", l->eatab[i]);
+ p = seprint(p, e, "\n");
+ p = seprint(p, e, "npkt: %uld\n", l->npkt);
+ p = seprint(p, e, "resent: %uld\n", l->resent);
+ p = seprint(p, e, "flag: "); p = pflag(p, e, l->flag);
+ p = seprint(p, e, "rttavg: %uld\n", TK2MS(l->rttavg));
+ p = seprint(p, e, "mintimer: %uld\n", TK2MS(l->mintimer));
+
+ p = seprint(p, e, "nl path: %s\n", l->nl->path);
+ p = seprint(p, e, "nl ea: %E\n", l->nl->ea);
+ p = seprint(p, e, "nl flag: "); p = pflag(p, e, l->flag);
+ p = seprint(p, e, "nl lostjumbo: %d\n", l->nl->lostjumbo);
+ p = seprint(p, e, "nl datamtu: %d\n", l->nl->datamtu);
+
+ if(p - s < len)
+ len = p - s;
+ i = readstr(off, db, len, s);
+ free(s);
+ return i;
+}
+
+static long
+topctlread(Chan *, void *db, int len, int off)
+{
+ int i;
+ char *s, *p, *e;
+ Netlink *n;
+
+ s = p = malloc(READSTR);
+ e = s + READSTR;
+
+ p = seprint(p, e, "debug: %d\n", debug);
+ p = seprint(p, e, "autodiscover: %d\n", autodiscover);
+ p = seprint(p, e, "rediscover: %d\n", rediscover);
+
+ for(i = 0; i < Nnetlink; i++){
+ n = netlinks.nl+i;
+ if(n->cc == 0)
+ continue;
+ p = seprint(p, e, "if%d path: %s\n", i, n->path);
+ p = seprint(p, e, "if%d ea: %E\n", i, n->ea);
+ p = seprint(p, e, "if%d flag: ", i); p = pflag(p, e, n->flag);
+ p = seprint(p, e, "if%d lostjumbo: %d\n", i, n->lostjumbo);
+ p = seprint(p, e, "if%d datamtu: %d\n", i, n->datamtu);
+ }
+
+ if(p - s < len)
+ len = p - s;
+ i = readstr(off, db, len, s);
+ free(s);
+ return i;
+}
+
+static long
+aoeread(Chan *c, void *db, long n, vlong off)
+{
+ switch(TYPE(c->qid)){
+ default:
+ error(Eperm);
+ case Qzero:
+ case Qtopdir:
+ case Qunitdir:
+ case Qdevlinkdir:
+ return devdirread(c, db, n, 0, 0, aoegen);
+ case Qtopctl:
+ return topctlread(c, db, n, off);
+ case Qtoplog:
+ return eventlogread(db, n);
+ case Qctl:
+ case Qdata:
+ case Qconfig:
+ case Qident:
+ return unitread(c, db, n, off);
+ case Qdevlink:
+ return devlinkread(c, db, n, off);
+ }
+}
+
+static long
+configwrite(Aoedev *d, void *db, long len)
+{
+ char *s;
+ Aoeqc *ch;
+ Frame *f;
+ Srb *srb;
+
+ if(!UP(d))
+ error(Enotup);
+ if(len > ETHERMAXTU - AOEQCSZ)
+ error(Etoobig);
+ srb = srballoc(len);
+ s = malloc(len);
+ memmove(s, db, len);
+ if(waserror()){
+ srbfree(srb);
+ free(s);
+ nexterror();
+ }
+ for (;;) {
+ qlock(d);
+ if(waserror()){
+ qunlock(d);
+ nexterror();
+ }
+ f = freeframe(d);
+ if(f != nil)
+ break;
+ poperror();
+ qunlock(d);
+ if(waserror())
+ nexterror();
+ tsleep(&up->sleep, return0, 0, 100);
+ poperror();
+ }
+ f->nhdr = AOEQCSZ;
+ memset(f->hdr, 0, f->nhdr);
+ ch = (Aoeqc*)f->hdr;
+ if(hset(d, f, ch, ACconfig) == -1)
+ return 0;
+ f->srb = srb;
+ f->dp = s;
+ ch->verccmd = AQCfset;
+ hnputs(ch->cslen, len);
+ d->nout++;
+ srb->nout++;
+ f->dl->npkt++;
+ f->dlen = len;
+ /*
+ * these refer to qlock & waserror in the above for loop.
+ * there's still the first waserror outstanding.
+ */
+ poperror();
+ qunlock(d);
+
+ devtab[f->nl->dc->type]->bwrite(f->nl->dc, allocfb(f), 0);
+ sleep(srb, srbready, srb);
+ if(srb->error)
+ error(srb->error);
+
+ qlock(d);
+ if(waserror()){
+ qunlock(d);
+ nexterror();
+ }
+ memmove(d->config, s, len);
+ d->nconfig = len;
+ poperror();
+ qunlock(d);
+
+ poperror(); /* pop first waserror */
+
+ srbfree(srb);
+ memmove(db, s, len);
+ free(s);
+ return len;
+}
+
+static int getmtu(Chan*);
+
+static int
+devmaxdata(Aoedev *d)
+{
+ int i, m, mtu;
+ Devlink *l;
+ Netlink *n;
+
+ mtu = 100000;
+ for(i = 0; i < d->ndl; i++){
+ l = d->dl + i;
+ n = l->nl;
+ if((l->flag & Dup) == 0 || (n->flag & Dup) == 0)
+ continue;
+ m = getmtu(n->mtu);
+ if(m < mtu)
+ mtu = m;
+ }
+ if(mtu == 100000)
+ mtu = 0;
+ mtu -= AOEATASZ;
+ return mtu;
+}
+
+static int
+toggle(char *s, int init)
+{
+ if(s == nil)
+ return init ^ 1;
+ return strcmp(s, "on") == 0;
+}
+
+static void ataident(Aoedev*);
+
+static long
+unitctlwrite(Aoedev *d, void *db, long n)
+{
+ uint maxbcnt, m;
+ uvlong bsize;
+ enum {
+ Failio,
+ Ident,
+ Jumbo,
+ Maxbno,
+ Mtu,
+ Nofailf,
+ Setsize,
+ };
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ static Cmdtab cmds[] = {
+ {Failio, "failio", 1 },
+ {Ident, "identify", 1 },
+ {Jumbo, "jumbo", 0 },
+ {Maxbno, "maxbno", 0 },
+ {Mtu, "mtu", 0 },
+ {Nofailf, "nofail", 0 },
+ {Setsize, "setsize", 0 },
+ };
+
+ cb = parsecmd(db, n);
+ qlock(d);
+ if(waserror()){
+ qunlock(d);
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, cmds, nelem(cmds));
+ switch(ct->index){
+ case Failio:
+ downdev(d, "i/o failure");
+ break;
+ case Ident:
+ ataident(d);
+ break;
+ case Jumbo:
+ m = 0;
+ if(d->flag & Djumbo)
+ m = 1;
+ toggle(cb->f[1], m);
+ if(m)
+ d->flag |= Djumbo;
+ else
+ d->flag &= ~Djumbo;
+ break;
+ case Maxbno:
+ case Mtu:
+ maxbcnt = devmaxdata(d);
+ if(cb->nf > 2)
+ error(Ecmdargs);
+ if(cb->nf == 2){
+ m = strtoul(cb->f[1], 0, 0);
+ if(ct->index == Maxbno)
+ m *= Aoesectsz;
+ else{
+ m -= AOEATASZ;
+ m &= ~(Aoesectsz-1);
+ }
+ if(m == 0 || m > maxbcnt)
+ cmderror(cb, "mtu out of legal range");
+ maxbcnt = m;
+ }
+ d->maxbcnt = maxbcnt;
+ break;
+ case Nofailf:
+ if (toggle(cb->f[1], (d->flag & Dnofail) != 0))
+ d->flag |= Dnofail;
+ else
+ d->flag &= ~Dnofail;
+ break;
+ case Setsize:
+ bsize = d->realbsize;
+ if(cb->nf > 2)
+ error(Ecmdargs);
+ if(cb->nf == 2){
+ bsize = strtoull(cb->f[1], 0, 0);
+ if(bsize % Aoesectsz)
+ cmderror(cb, "disk size must be sector aligned");
+ }
+ d->bsize = bsize;
+ break;
+ default:
+ cmderror(cb, "unknown aoe control message");
+ }
+ poperror();
+ qunlock(d);
+ free(cb);
+ return n;
+}
+
+static long
+unitwrite(Chan *c, void *db, long n, vlong off)
+{
+ long rv;
+ char *buf;
+ Aoedev *d;
+
+ d = unit2dev(UNIT(c->qid));
+ switch(TYPE(c->qid)){
+ default:
+ error(Ebadarg);
+ case Qctl:
+ return unitctlwrite(d, db, n);
+ case Qident:
+ error(Eperm);
+ case Qdata:
+ return rw(d, Write, db, n, off);
+ case Qconfig:
+ if(off + n > sizeof d->config)
+ error(Etoobig);
+ buf = malloc(sizeof d->config);
+ if(waserror()){
+ free(buf);
+ nexterror();
+ }
+ memmove(buf, d->config, d->nconfig);
+ memmove(buf + off, db, n);
+ rv = configwrite(d, buf, n + off);
+ poperror();
+ free(buf);
+ return rv;
+ }
+}
+
+static Netlink*
+addnet(char *path, Chan *cc, Chan *dc, Chan *mtu, uchar *ea)
+{
+ Netlink *nl, *e;
+
+ lock(&netlinks);
+ if(waserror()){
+ unlock(&netlinks);
+ nexterror();
+ }
+ nl = netlinks.nl;
+ e = nl + nelem(netlinks.nl);
+ for(; nl < e && nl->cc; nl++)
+ continue;
+ if (nl >= e)
+ error("out of netlink structures");
+ nl->cc = cc;
+ nl->dc = dc;
+ nl->mtu = mtu;
+ strncpy(nl->path, path, sizeof nl->path);
+ memmove(nl->ea, ea, sizeof nl->ea);
+ poperror();
+ nl->flag |= Dup;
+ unlock(&netlinks);
+ return nl;
+}
+
+static int
+newunit(void)
+{
+ int x;
+
+ lock(&units);
+ if(units.ref == Maxunits)
+ x = -1;
+ else
+ x = units.ref++;
+ unlock(&units);
+ return x;
+}
+
+static int
+dropunit(void)
+{
+ int x;
+
+ lock(&units);
+ x = --units.ref;
+ unlock(&units);
+ return x;
+}
+
+/*
+ * always allocate max frames. maxout may change.
+ */
+static Aoedev*
+newdev(long major, long minor, int n)
+{
+ Aoedev *d;
+ Frame *f, *e;
+
+ d = mallocz(sizeof *d, 1);
+ f = mallocz(sizeof *f * Maxframes, 1);
+ if (!d || !f) {
+ free(d);
+ free(f);
+ error("aoe device allocation failure");
+ }
+ d->nframes = n;
+ d->frames = f;
+ for (e = f + n; f < e; f++)
+ f->tag = Tfree;
+ d->maxout = n;
+ d->major = major;
+ d->minor = minor;
+ d->maxbcnt = Dbcnt;
+ d->flag = Djumbo;
+ d->unit = newunit(); /* bzzt. inaccurate if units removed */
+ if(d->unit == -1){
+ free(d);
+ free(d->frames);
+ error("too many units");
+ }
+ d->dl = d->dltab;
+ return d;
+}
+
+static Aoedev*
+mm2dev(int major, int minor)
+{
+ Aoedev *d;
+
+ rlock(&devs);
+ for(d = devs.d; d; d = d->next)
+ if(d->major == major && d->minor == minor){
+ runlock(&devs);
+ return d;
+ }
+ runlock(&devs);
+ eventlog("mm2dev: %d.%d not found\n", major, minor);
+ return nil;
+}
+
+/* Find the device in our list. If not known, add it */
+static Aoedev*
+getdev(long major, long minor, int n)
+{
+ Aoedev *d;
+
+ if(major == 0xffff || minor == 0xff)
+ return 0;
+ wlock(&devs);
+ if(waserror()){
+ wunlock(&devs);
+ nexterror();
+ }
+ for(d = devs.d; d; d = d->next)
+ if(d->major == major && d->minor == minor)
+ break;
+ if (d == nil) {
+ d = newdev(major, minor, n);
+ d->next = devs.d;
+ devs.d = d;
+ }
+ poperror();
+ wunlock(&devs);
+ return d;
+}
+
+static ushort
+gbit16(void *a)
+{
+ uchar *i;
+
+ i = a;
+ return i[1] << 8 | i[0];
+}
+
+static ulong
+gbit32(void *a)
+{
+ ulong j;
+ uchar *i;
+
+ i = a;
+ j = i[3] << 24;
+ j |= i[2] << 16;
+ j |= i[1] << 8;
+ j |= i[0];
+ return j;
+}
+
+static uvlong
+gbit64(void *a)
+{
+ uchar *i;
+
+ i = a;
+ return (uvlong)gbit32(i+4) << 32 | gbit32(a);
+}
+
+static void
+ataident(Aoedev *d)
+{
+ Aoeata *a;
+ Block *b;
+ Frame *f;
+
+ f = freeframe(d);
+ if(f == nil)
+ return;
+ f->nhdr = AOEATASZ;
+ memset(f->hdr, 0, f->nhdr);
+ a = (Aoeata*)f->hdr;
+ if(hset(d, f, a, ACata) == -1)
+ return;
+ a->cmdstat = Cid; /* ata 6, page 110 */
+ a->scnt = 1;
+ a->lba[3] = 0xa0;
+ d->nout++;
+ f->dl->npkt++;
+ f->bcnt = 512;
+ f->dlen = 0;
+ b = allocfb(f);
+ devtab[f->nl->dc->type]->bwrite(f->nl->dc, b, 0);
+}
+
+static int
+getmtu(Chan *m)
+{
+ int n, mtu;
+ char buf[36];
+
+ mtu = 1514;
+ if(m == nil || waserror())
+ return mtu;
+ n = devtab[m->type]->read(m, buf, sizeof buf - 1, 0);
+ if(n > 12){
+ buf[n] = 0;
+ mtu = strtoul(buf + 12, 0, 0);
+ }
+ poperror();
+ return mtu;
+}
+
+static int
+newdlea(Devlink *l, uchar *ea)
+{
+ int i;
+ uchar *t;
+
+ for(i = 0; i < Nea; i++){
+ t = l->eatab[i];
+ if(i == l->nea){
+ memmove(t, ea, Eaddrlen);
+ return l->nea++;
+ }
+ if(memcmp(t, ea, Eaddrlen) == 0)
+ return i;
+ }
+ return -1;
+}
+
+static Devlink*
+newdevlink(Aoedev *d, Netlink *n, Aoeqc *c)
+{
+ int i;
+ Devlink *l;
+
+ for(i = 0; i < Ndevlink; i++){
+ l = d->dl + i;
+ if(i == d->ndl){
+ d->ndl++;
+ newdlea(l, c->src);
+ l->nl = n;
+ l->flag |= Dup;
+ l->mintimer = Rtmin;
+ l->rttavg = Rtmax;
+ return l;
+ }
+ if(l->nl == n) {
+ newdlea(l, c->src);
+ l->flag |= Dup;
+ return l;
+ }
+ }
+ eventlog("%æ: out of links: %s:%E to %E\n", d, n->path, n->ea, c->src);
+ return 0;
+}
+
+static void
+errrsp(Block *b, char *s)
+{
+ int n;
+ Aoedev *d;
+ Aoehdr *h;
+ Frame *f;
+
+ h = (Aoehdr*)b->rp;
+ n = nhgetl(h->tag);
+ if(n == Tmgmt || n == Tfree)
+ return;
+ d = mm2dev(nhgets(h->major), h->minor);
+ if(d == 0)
+ return;
+ if(f = getframe(d, n))
+ frameerror(d, f, s);
+}
+
+static void
+qcfgrsp(Block *b, Netlink *nl)
+{
+ int major, cmd, cslen, blen;
+ unsigned n;
+ Aoedev *d;
+ Aoeqc *ch;
+ Devlink *l;
+ Frame *f;
+
+ ch = (Aoeqc*)b->rp;
+ major = nhgets(ch->major);
+ n = nhgetl(ch->tag);
+ if(n != Tmgmt){
+ d = mm2dev(major, ch->minor);
+ if(d == nil)
+ return;
+ qlock(d);
+ f = getframe(d, n);
+ if(f == nil){
+ qunlock(d);
+ eventlog("%æ: unknown response tag %ux\n", d, n);
+ return;
+ }
+ cslen = nhgets(ch->cslen);
+ blen = BLEN(b) - AOEQCSZ;
+ if(cslen < blen && BLEN(b) > 60)
+ eventlog("%æ: cfgrsp: tag %.8ux oversized %d %d\n",
+ d, n, cslen, blen);
+ if(cslen > blen){
+ eventlog("%æ: cfgrsp: tag %.8ux runt %d %d\n",
+ d, n, cslen, blen);
+ cslen = blen;
+ }
+ memmove(f->dp, ch + 1, cslen);
+ f->srb->nout--;
+ wakeup(f->srb);
+ d->nout--;
+ f->srb = nil;
+ f->tag = Tfree;
+ qunlock(d);
+ return;
+ }
+
+ cmd = ch->verccmd & 0xf;
+ if(cmd != 0){
+ eventlog("aoe%d.%d: cfgrsp: bad command %d\n", major, ch->minor, cmd);
+ return;
+ }
+ n = nhgets(ch->bufcnt);
+ if(n > Maxframes)
+ n = Maxframes;
+
+ if(waserror()){
+ eventlog("getdev: %d.%d ignored: %s\n", major, ch->minor, up->errstr);
+ return;
+ }
+ d = getdev(major, ch->minor, n);
+ poperror();
+ if(d == 0)
+ return;
+
+ qlock(d);
+ *up->errstr = 0;
+ if(waserror()){
+ qunlock(d);
+ eventlog("%æ: %s\n", d, up->errstr);
+ nexterror();
+ }
+
+ l = newdevlink(d, nl, ch); /* add this interface. */
+
+ d->fwver = nhgets(ch->fwver);
+ n = nhgets(ch->cslen);
+ if(n > sizeof d->config)
+ n = sizeof d->config;
+ d->nconfig = n;
+ memmove(d->config, ch + 1, n);
+ if(l != 0 && d->flag & Djumbo){
+ n = getmtu(nl->mtu) - AOEATASZ;
+ n /= Aoesectsz;
+ if(n > ch->scnt)
+ n = ch->scnt;
+ n = n? n * Aoesectsz: Dbcnt;
+ if(n != d->maxbcnt){
+ eventlog("%æ: setting %d byte data frames on %s:%E\n",
+ d, n, nl->path, nl->ea);
+ d->maxbcnt = n;
+ }
+ }
+ if(d->nopen == 0)
+ ataident(d);
+ poperror();
+ qunlock(d);
+}
+
+void
+aoeidmove(char *p, ushort *u, unsigned n)
+{
+ int i;
+ char *op, *e, *s;
+
+ op = p;
+ /*
+ * the ushort `*u' is sometimes not aligned on a short boundary,
+ * so dereferencing u[i] causes an alignment exception on
+ * some machines.
+ */
+ s = (char *)u;
+ for(i = 0; i < n; i += 2){
+ *p++ = s[i + 1];
+ *p++ = s[i];
+ }
+ *p = 0;
+ while(p > op && *--p == ' ')
+ *p = 0;
+ e = p;
+ p = op;
+ while(*p == ' ')
+ p++;
+ memmove(op, p, n - (e - p));
+}
+
+static vlong
+aoeidentify(Aoedev *d, ushort *id)
+{
+ int i;
+ vlong s;
+
+ d->flag &= ~(Dllba|Dpower|Dsmart|Dnop|Dup);
+
+ i = gbit16(id+83) | gbit16(id+86);
+ if(i & (1<<10)){
+ d->flag |= Dllba;
+ s = gbit64(id+100);
+ }else
+ s = gbit32(id+60);
+
+ i = gbit16(id+83);
+ if((i>>14) == 1) {
+ if(i & (1<<3))
+ d->flag |= Dpower;
+ i = gbit16(id+82);
+ if(i & 1)
+ d->flag |= Dsmart;
+ if(i & (1<<14))
+ d->flag |= Dnop;
+ }
+// eventlog("%æ up\n", d);
+ d->flag |= Dup;
+ memmove(d->ident, id, sizeof d->ident);
+ return s;
+}
+
+static void
+newvers(Aoedev *d)
+{
+ lock(&drivevers);
+ d->vers = drivevers.ref++;
+ unlock(&drivevers);
+}
+
+static int
+identify(Aoedev *d, ushort *id)
+{
+ vlong osectors, s;
+ uchar oserial[21];
+
+ s = aoeidentify(d, id);
+ if(s == -1)
+ return -1;
+ osectors = d->realbsize;
+ memmove(oserial, d->serial, sizeof d->serial);
+
+ aoeidmove(d->serial, id+10, 20);
+ aoeidmove(d->firmware, id+23, 8);
+ aoeidmove(d->model, id+27, 40);
+
+ s *= Aoesectsz;
+ if((osectors == 0 || osectors != s) &&
+ memcmp(oserial, d->serial, sizeof oserial) != 0){
+ d->bsize = s;
+ d->realbsize = s;
+// d->mediachange = 1;
+ newvers(d);
+ }
+ return 0;
+}
+
+static void
+atarsp(Block *b)
+{
+ unsigned n;
+ short major;
+ Aoeata *ahin, *ahout;
+ Aoedev *d;
+ Frame *f;
+ Srb *srb;
+
+ ahin = (Aoeata*)b->rp;
+ major = nhgets(ahin->major);
+ d = mm2dev(major, ahin->minor);
+ if(d == nil)
+ return;
+ qlock(d);
+ if(waserror()){
+ qunlock(d);
+ nexterror();
+ }
+ n = nhgetl(ahin->tag);
+ f = getframe(d, n);
+ if(f == nil){
+ dprint("%æ: unexpected response; tag %ux\n", d, n);
+ goto bail;
+ }
+ rtupdate(f->dl, tsince(f->tag));
+ ahout = (Aoeata*)f->hdr;
+ srb = f->srb;
+
+ if(ahin->cmdstat & 0xa9){
+ eventlog("%æ: ata error cmd %.2ux stat %.2ux\n",
+ d, ahout->cmdstat, ahin->cmdstat);
+ if(srb)
+ srb->error = Eio;
+ } else {
+ n = ahout->scnt * Aoesectsz;
+ switch(ahout->cmdstat){
+ case Crd:
+ case Crdext:
+ if(BLEN(b) - AOEATASZ < n){
+ eventlog("%æ: runt read blen %ld expect %d\n",
+ d, BLEN(b), n);
+ goto bail;
+ }
+ memmove(f->dp, (uchar *)ahin + AOEATASZ, n);
+ case Cwr:
+ case Cwrext:
+ if(n > Dbcnt)
+ f->nl->lostjumbo = 0;
+ if(f->bcnt -= n){
+ f->lba += n / Aoesectsz;
+ f->dp = (uchar*)f->dp + n;
+ resend(d, f);
+ goto bail;
+ }
+ break;
+ case Cid:
+ if(BLEN(b) - AOEATASZ < 512){
+ eventlog("%æ: runt identify blen %ld expect %d\n",
+ d, BLEN(b), n);
+ goto bail;
+ }
+ identify(d, (ushort*)((uchar *)ahin + AOEATASZ));
+ break;
+ default:
+ eventlog("%æ: unknown ata command %.2ux \n",
+ d, ahout->cmdstat);
+ }
+ }
+
+ if(srb && --srb->nout == 0 && srb->len == 0)
+ wakeup(srb);
+ f->srb = nil;
+ f->tag = Tfree;
+ d->nout--;
+
+ work(d);
+bail:
+ poperror();
+ qunlock(d);
+}
+
+static void
+netrdaoeproc(void *v)
+{
+ int idx;
+ char name[Maxpath+1], *s;
+ Aoehdr *h;
+ Block *b;
+ Netlink *nl;
+
+ nl = (Netlink*)v;
+ idx = nl - netlinks.nl;
+ netlinks.reader[idx] = 1;
+ kstrcpy(name, nl->path, Maxpath);
+
+ if(waserror()){
+ eventlog("netrdaoe exiting: %s\n", up->errstr);
+ netlinks.reader[idx] = 0;
+ wakeup(netlinks.rendez + idx);
+ pexit(up->errstr, 1);
+ }
+ if(autodiscover)
+ discover(0xffff, 0xff);
+ for (;;) {
+ if(!(nl->flag & Dup)) {
+ uprint("%s: netlink is down", name);
+ error(up->genbuf);
+ }
+ if (nl->dc == nil)
+ panic("netrdaoe: nl->dc == nil");
+ b = devtab[nl->dc->type]->bread(nl->dc, 1<<16, 0);
+ if(b == nil) {
+ uprint("%s: nil read from network", name);
+ error(up->genbuf);
+ }
+ h = (Aoehdr*)b->rp;
+ if(h->verflag & AFrsp)
+ if(s = aoeerror(h)){
+ eventlog("%s: %s\n", nl->path, up->errstr);
+ errrsp(b, s);
+ }else
+ switch(h->cmd){
+ case ACata:
+ atarsp(b);
+ break;
+ case ACconfig:
+ qcfgrsp(b, nl);
+ break;
+ default:
+ if((h->cmd & 0xf0) == 0){
+ eventlog("%s: unknown cmd %d\n",
+ nl->path, h->cmd);
+ errrsp(b, "unknown command");
+ }
+ break;
+ }
+ freeb(b);
+ }
+}
+
+static void
+getaddr(char *path, uchar *ea)
+{
+ int n;
+ char buf[2*Eaddrlen+1];
+ Chan *c;
+
+ uprint("%s/addr", path);
+ c = namec(up->genbuf, Aopen, OREAD, 0);
+ if(waserror()) {
+ cclose(c);
+ nexterror();
+ }
+ if (c == nil)
+ panic("æ: getaddr: c == nil");
+ n = devtab[c->type]->read(c, buf, sizeof buf-1, 0);
+ poperror();
+ cclose(c);
+ buf[n] = 0;
+ if(parseether(ea, buf) < 0)
+ error("parseether failure");
+}
+
+static void
+netbind(char *path)
+{
+ char addr[Maxpath];
+ uchar ea[2*Eaddrlen+1];
+ Chan *dc, *cc, *mtu;
+ Netlink *nl;
+
+ snprint(addr, sizeof addr, "%s!%#x", path, Aoetype);
+ dc = chandial(addr, nil, nil, &cc);
+ snprint(addr, sizeof addr, "%s/mtu", path);
+ if(waserror())
+ mtu = nil;
+ else {
+ mtu = namec(addr, Aopen, OREAD, 0);
+ poperror();
+ }
+
+ if(waserror()){
+ cclose(dc);
+ cclose(cc);
+ if(mtu)
+ cclose(mtu);
+ nexterror();
+ }
+ if(dc == nil || cc == nil)
+ error(Enonexist);
+ getaddr(path, ea);
+ nl = addnet(path, cc, dc, mtu, ea);
+ snprint(addr, sizeof addr, "netrdaoe@%s", path);
+ kproc(addr, netrdaoeproc, nl);
+ poperror();
+}
+
+static int
+unbound(void *v)
+{
+ return *(int*)v != 0;
+}
+
+static void
+netunbind(char *path)
+{
+ int i, idx;
+ Aoedev *d, *p, *next;
+ Chan *dc, *cc;
+ Devlink *l;
+ Frame *f;
+ Netlink *n, *e;
+
+ n = netlinks.nl;
+ e = n + nelem(netlinks.nl);
+
+ lock(&netlinks);
+ for(; n < e; n++)
+ if(n->dc && strcmp(n->path, path) == 0)
+ break;
+ unlock(&netlinks);
+ if (n >= e)
+ error("device not bound");
+
+ /*
+ * hunt down devices using this interface; disable
+ * this also terminates the reader.
+ */
+ idx = n - netlinks.nl;
+ wlock(&devs);
+ for(d = devs.d; d; d = d->next){
+ qlock(d);
+ for(i = 0; i < d->ndl; i++){
+ l = d->dl + i;
+ if(l->nl == n)
+ l->flag &= ~Dup;
+ }
+ qunlock(d);
+ }
+ n->flag &= ~Dup;
+ wunlock(&devs);
+
+ /* confirm reader is down. */
+ while(waserror())
+ ;
+ sleep(netlinks.rendez + idx, unbound, netlinks.reader + idx);
+ poperror();
+
+ /* reschedule packets. */
+ wlock(&devs);
+ for(d = devs.d; d; d = d->next){
+ qlock(d);
+ for(i = 0; i < d->nframes; i++){
+ f = d->frames + i;
+ if(f->tag != Tfree && f->nl == n)
+ resend(d, f);
+ }
+ qunlock(d);
+ }
+ wunlock(&devs);
+
+ /* squeeze devlink pool. (we assert nobody is using them now) */
+ wlock(&devs);
+ for(d = devs.d; d; d = d->next){
+ qlock(d);
+ for(i = 0; i < d->ndl; i++){
+ l = d->dl + i;
+ if(l->nl == n)
+ memmove(l, l + 1, sizeof *l * (--d->ndl - i));
+ }
+ qunlock(d);
+ }
+ wunlock(&devs);
+
+ /* close device link. */
+ lock(&netlinks);
+ dc = n->dc;
+ cc = n->cc;
+ if(n->mtu)
+ cclose(n->mtu);
+ memset(n, 0, sizeof *n);
+ unlock(&netlinks);
+
+ cclose(dc);
+ cclose(cc);
+
+ /* squeeze orphan devices */
+ wlock(&devs);
+ for(p = d = devs.d; d; d = next){
+ next = d->next;
+ if(d->ndl > 0) {
+ p = d;
+ continue;
+ }
+ qlock(d);
+ downdev(d, "orphan");
+ qunlock(d);
+ if(p != devs.d)
+ p->next = next;
+ else{
+ devs.d = next;
+ p = devs.d;
+ }
+ free(d->frames);
+ free(d);
+ dropunit();
+ }
+ wunlock(&devs);
+}
+
+static void
+removeaoedev(Aoedev *d)
+{
+ int i;
+ Aoedev *p;
+
+ wlock(&devs);
+ p = 0;
+ if(d != devs.d)
+ for(p = devs.d; p; p = p->next)
+ if(p->next == d)
+ break;
+ qlock(d);
+ d->flag &= ~Dup;
+ newvers(d);
+ d->ndl = 0;
+ qunlock(d);
+ for(i = 0; i < d->nframes; i++)
+ frameerror(d, d->frames+i, Enotup);
+
+ if(p)
+ p->next = d->next;
+ else
+ devs.d = d->next;
+ free(d->frames);
+ free(d);
+ dropunit();
+ wunlock(&devs);
+}
+
+static void
+removedev(char *name)
+{
+ Aoedev *d, *p;
+
+ wlock(&devs);
+ for(p = d = devs.d; d; p = d, d = d->next)
+ if(strcmp(name, unitname(d)) == 0) {
+ wunlock(&devs);
+ removeaoedev(p);
+ return;
+ }
+ wunlock(&devs);
+ error("device not bound");
+}
+
+static void
+discoverstr(char *f)
+{
+ ushort shelf, slot;
+ ulong sh;
+ char *s;
+
+ if(f == 0){
+ discover(0xffff, 0xff);
+ return;
+ }
+
+ shelf = sh = strtol(f, &s, 0);
+ if(s == f || sh > 0xffff)
+ error("bad shelf");
+ f = s;
+ if(*f++ == '.'){
+ slot = strtol(f, &s, 0);
+ if(s == f || slot > 0xff)
+ error("bad shelf");
+ }else
+ slot = 0xff;
+ discover(shelf, slot);
+}
+
+
+static void
+aoeremove(Chan *c)
+{
+ switch(TYPE(c->qid)){
+ default:
+ error(Eperm);
+ case Qunitdir:
+ removeaoedev(unit2dev(UNIT(c->qid)));
+ break;
+ }
+}
+
+static long
+topctlwrite(void *db, long n)
+{
+ enum {
+ Autodiscover,
+ Bind,
+ Debug,
+ Discover,
+ Rediscover,
+ Remove,
+ Unbind,
+ };
+ char *f;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ static Cmdtab cmds[] = {
+ { Autodiscover, "autodiscover", 0 },
+ { Bind, "bind", 2 },
+ { Debug, "debug", 0 },
+ { Discover, "discover", 0 },
+ { Rediscover, "rediscover", 0 },
+ { Remove, "remove", 2 },
+ { Unbind, "unbind", 2 },
+ };
+
+ cb = parsecmd(db, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, cmds, nelem(cmds));
+ f = cb->f[1];
+ switch(ct->index){
+ case Autodiscover:
+ autodiscover = toggle(f, autodiscover);
+ break;
+ case Bind:
+ netbind(f);
+ break;
+ case Debug:
+ debug = toggle(f, debug);
+ break;
+ case Discover:
+ discoverstr(f);
+ break;
+ case Rediscover:
+ rediscover = toggle(f, rediscover);
+ break;
+ case Remove:
+ removedev(f);
+ break;
+ case Unbind:
+ netunbind(f);
+ break;
+ default:
+ cmderror(cb, "unknown aoe control message");
+ }
+ poperror();
+ free(cb);
+ return n;
+}
+
+static long
+aoewrite(Chan *c, void *db, long n, vlong off)
+{
+ switch(TYPE(c->qid)){
+ default:
+ case Qzero:
+ case Qtopdir:
+ case Qunitdir:
+ case Qtoplog:
+ error(Eperm);
+ case Qtopctl:
+ return topctlwrite(db, n);
+ case Qctl:
+ case Qdata:
+ case Qconfig:
+ case Qident:
+ return unitwrite(c, db, n, off);
+ }
+}
+
+Dev aoedevtab = {
+ L'æ',
+ "aoe",
+
+ devreset,
+ devinit,
+ devshutdown,
+ aoeattach,
+ aoewalk,
+ aoestat,
+ aoeopen,
+ devcreate,
+ aoeclose,
+ aoeread,
+ devbread,
+ aoewrite,
+ devbwrite,
+ aoeremove,
+ devwstat,
+ devpower,
+ devconfig,
+};
diff --git a/sys/src/9/port/devaudio.c b/sys/src/9/port/devaudio.c
new file mode 100755
index 000000000..690fc39ba
--- /dev/null
+++ b/sys/src/9/port/devaudio.c
@@ -0,0 +1,1261 @@
+/*
+ * SB 16 driver
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+#include "audio.h"
+
+typedef struct AQueue AQueue;
+typedef struct Buf Buf;
+
+enum
+{
+ Qdir = 0,
+ Qaudio,
+ Qvolume,
+ Qstatus,
+
+ Fmono = 1,
+ Fin = 2,
+ Fout = 4,
+
+ Aclosed = 0,
+ Aread,
+ Awrite,
+
+ Vaudio = 0,
+ Vsynth,
+ Vcd,
+ Vline,
+ Vmic,
+ Vspeaker,
+ Vtreb,
+ Vbass,
+ Vspeed,
+ Nvol,
+
+ Speed = 44100,
+ Ncmd = 50, /* max volume command words */
+};
+
+Dirtab
+audiodir[] =
+{
+ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
+ "audio", {Qaudio}, 0, 0666,
+ "volume", {Qvolume}, 0, 0666,
+ "audiostat",{Qstatus}, 0, 0444,
+};
+
+struct Buf
+{
+ uchar* virt;
+ ulong phys;
+ Buf* next;
+};
+struct AQueue
+{
+ Lock;
+ Buf* first;
+ Buf* last;
+};
+static struct
+{
+ QLock;
+ Rendez vous;
+ int buffered; /* number of bytes en route */
+ int bufinit; /* boolean if buffers allocated */
+ int curcount; /* how much data in current buffer */
+ int active; /* boolean dma running */
+ int intr; /* boolean an interrupt has happened */
+ int amode; /* Aclosed/Aread/Awrite for /audio */
+ int rivol[Nvol]; /* right/left input/output volumes */
+ int livol[Nvol];
+ int rovol[Nvol];
+ int lovol[Nvol];
+ int major; /* SB16 major version number (sb 4) */
+ int minor; /* SB16 minor version number */
+ ulong totcount; /* how many bytes processed since open */
+ vlong tottime; /* time at which totcount bytes were processed */
+
+ Buf buf[Nbuf]; /* buffers and queues */
+ AQueue empty;
+ AQueue full;
+ Buf* current;
+ Buf* filling;
+} audio;
+
+static struct
+{
+ char* name;
+ int flag;
+ int ilval; /* initial values */
+ int irval;
+} volumes[] =
+{
+[Vaudio] "audio", Fout, 50, 50,
+[Vsynth] "synth", Fin|Fout, 0, 0,
+[Vcd] "cd", Fin|Fout, 0, 0,
+[Vline] "line", Fin|Fout, 0, 0,
+[Vmic] "mic", Fin|Fout|Fmono, 0, 0,
+[Vspeaker] "speaker", Fout|Fmono, 0, 0,
+
+[Vtreb] "treb", Fout, 50, 50,
+[Vbass] "bass", Fout, 50, 50,
+
+[Vspeed] "speed", Fin|Fout|Fmono, Speed, Speed,
+ 0
+};
+
+static struct
+{
+ Lock;
+ int reset; /* io ports to the sound blaster */
+ int read;
+ int write;
+ int wstatus;
+ int rstatus;
+ int mixaddr;
+ int mixdata;
+ int clri8;
+ int clri16;
+ int clri401;
+ int dma;
+
+ void (*startdma)(void);
+ void (*intr)(void);
+} blaster;
+
+static void swab(uchar*);
+
+static char Emajor[] = "soundblaster not responding/wrong version";
+static char Emode[] = "illegal open mode";
+static char Evolume[] = "illegal volume specifier";
+
+static int
+sbcmd(int val)
+{
+ int i, s;
+
+ for(i=1<<16; i!=0; i--) {
+ s = inb(blaster.wstatus);
+ if((s & 0x80) == 0) {
+ outb(blaster.write, val);
+ return 0;
+ }
+ }
+/* print("#A: sbcmd (%#.2x) timeout\n", val); /**/
+ return 1;
+}
+
+static int
+sbread(void)
+{
+ int i, s;
+
+ for(i=1<<16; i!=0; i--) {
+ s = inb(blaster.rstatus);
+ if((s & 0x80) != 0) {
+ return inb(blaster.read);
+ }
+ }
+/* print("#A: sbread did not respond\n"); /**/
+ return -1;
+}
+
+static int
+ess1688w(int reg, int val)
+{
+ if(sbcmd(reg) || sbcmd(val))
+ return 1;
+
+ return 0;
+}
+
+static int
+ess1688r(int reg)
+{
+ if(sbcmd(0xC0) || sbcmd(reg))
+ return -1;
+
+ return sbread();
+}
+
+static int
+mxcmd(int addr, int val)
+{
+
+ outb(blaster.mixaddr, addr);
+ outb(blaster.mixdata, val);
+ return 1;
+}
+
+static int
+mxread(int addr)
+{
+ int s;
+
+ outb(blaster.mixaddr, addr);
+ s = inb(blaster.mixdata);
+ return s;
+}
+
+static void
+mxcmds(int s, int v)
+{
+
+ if(v > 100)
+ v = 100;
+ if(v < 0)
+ v = 0;
+ mxcmd(s, (v*255)/100);
+}
+
+static void
+mxcmdt(int s, int v)
+{
+
+ if(v > 100)
+ v = 100;
+ if(v <= 0)
+ mxcmd(s, 0);
+ else
+ mxcmd(s, 255-100+v);
+}
+
+static void
+mxcmdu(int s, int v)
+{
+
+ if(v > 100)
+ v = 100;
+ if(v <= 0)
+ v = 0;
+ mxcmd(s, 128-50+v);
+}
+
+static void
+mxvolume(void)
+{
+ int *left, *right;
+ int source;
+
+ if(audio.amode == Aread){
+ left = audio.livol;
+ right = audio.rivol;
+ }else{
+ left = audio.lovol;
+ right = audio.rovol;
+ }
+
+ ilock(&blaster);
+
+ mxcmd(0x30, 255); /* left master */
+ mxcmd(0x31, 255); /* right master */
+ mxcmd(0x3f, 0); /* left igain */
+ mxcmd(0x40, 0); /* right igain */
+ mxcmd(0x41, 0); /* left ogain */
+ mxcmd(0x42, 0); /* right ogain */
+
+ mxcmds(0x32, left[Vaudio]);
+ mxcmds(0x33, right[Vaudio]);
+
+ mxcmds(0x34, left[Vsynth]);
+ mxcmds(0x35, right[Vsynth]);
+
+ mxcmds(0x36, left[Vcd]);
+ mxcmds(0x37, right[Vcd]);
+
+ mxcmds(0x38, left[Vline]);
+ mxcmds(0x39, right[Vline]);
+
+ mxcmds(0x3a, left[Vmic]);
+ mxcmds(0x3b, left[Vspeaker]);
+
+ mxcmdu(0x44, left[Vtreb]);
+ mxcmdu(0x45, right[Vtreb]);
+
+ mxcmdu(0x46, left[Vbass]);
+ mxcmdu(0x47, right[Vbass]);
+
+ source = 0;
+ if(left[Vsynth])
+ source |= 1<<6;
+ if(right[Vsynth])
+ source |= 1<<5;
+ if(left[Vaudio])
+ source |= 1<<4;
+ if(right[Vaudio])
+ source |= 1<<3;
+ if(left[Vcd])
+ source |= 1<<2;
+ if(right[Vcd])
+ source |= 1<<1;
+ if(left[Vmic])
+ source |= 1<<0;
+ if(audio.amode == Aread)
+ mxcmd(0x3c, 0); /* output switch */
+ else
+ mxcmd(0x3c, source);
+ mxcmd(0x3d, source); /* input left switch */
+ mxcmd(0x3e, source); /* input right switch */
+ iunlock(&blaster);
+}
+
+static Buf*
+getbuf(AQueue *q)
+{
+ Buf *b;
+
+ ilock(q);
+ b = q->first;
+ if(b)
+ q->first = b->next;
+ iunlock(q);
+
+ return b;
+}
+
+static void
+putbuf(AQueue *q, Buf *b)
+{
+
+ ilock(q);
+ b->next = 0;
+ if(q->first)
+ q->last->next = b;
+ else
+ q->first = b;
+ q->last = b;
+ iunlock(q);
+}
+
+/*
+ * move the dma to the next buffer
+ */
+static void
+contindma(void)
+{
+ Buf *b;
+
+ if(!audio.active)
+ goto shutdown;
+
+ b = audio.current;
+ if(b){
+ audio.totcount += Bufsize;
+ audio.tottime = todget(nil);
+ }
+ if(audio.amode == Aread) {
+ if(b){
+ putbuf(&audio.full, b);
+ audio.buffered += Bufsize;
+ }
+ b = getbuf(&audio.empty);
+ } else {
+ if(b){
+ putbuf(&audio.empty, b);
+ audio.buffered -= Bufsize;
+ }
+ b = getbuf(&audio.full);
+ }
+ audio.current = b;
+ if(b == 0)
+ goto shutdown;
+
+ if(dmasetup(blaster.dma, b->virt, Bufsize, audio.amode == Aread) >= 0)
+ return;
+ print("#A: dmasetup fail\n");
+ putbuf(&audio.empty, b);
+
+shutdown:
+ dmaend(blaster.dma);
+ sbcmd(0xd9); /* exit at end of count */
+ sbcmd(0xd5); /* pause */
+ audio.curcount = 0;
+ audio.active = 0;
+}
+
+/*
+ * cause sb to get an interrupt per buffer.
+ * start first dma
+ */
+static void
+sb16startdma(void)
+{
+ ulong count;
+ int speed;
+
+ ilock(&blaster);
+ dmaend(blaster.dma);
+ if(audio.amode == Aread) {
+ sbcmd(0x42); /* input sampling rate */
+ speed = audio.livol[Vspeed];
+ } else {
+ sbcmd(0x41); /* output sampling rate */
+ speed = audio.lovol[Vspeed];
+ }
+ sbcmd(speed>>8);
+ sbcmd(speed);
+
+ count = (Bufsize >> 1) - 1;
+ if(audio.amode == Aread)
+ sbcmd(0xbe); /* A/D, autoinit */
+ else
+ sbcmd(0xb6); /* D/A, autoinit */
+ sbcmd(0x30); /* stereo, 16 bit */
+ sbcmd(count);
+ sbcmd(count>>8);
+
+ audio.active = 1;
+ contindma();
+ iunlock(&blaster);
+}
+
+static int
+ess1688reset(void)
+{
+ int i;
+
+ outb(blaster.reset, 3);
+ delay(1); /* >3 υs */
+ outb(blaster.reset, 0);
+ delay(1);
+
+ i = sbread();
+ if(i != 0xAA) {
+ print("#A: no response %#.2x\n", i);
+ return 1;
+ }
+
+ if(sbcmd(0xC6)){ /* extended mode */
+ print("#A: barf 3\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
+ess1688startdma(void)
+{
+ ulong count;
+ int speed, x;
+
+ ilock(&blaster);
+ dmaend(blaster.dma);
+
+ if(audio.amode == Awrite)
+ ess1688reset();
+ if(audio.amode == Aread)
+ sbcmd(0xD3); /* speaker off */
+
+ /*
+ * Set the speed.
+ */
+ if(audio.amode == Aread)
+ speed = audio.livol[Vspeed];
+ else
+ speed = audio.lovol[Vspeed];
+ if(speed < 4000)
+ speed = 4000;
+ else if(speed > 48000)
+ speed = 48000;
+
+ if(speed > 22000)
+ x = 0x80|(256-(795500+speed/2)/speed);
+ else
+ x = 128-(397700+speed/2)/speed;
+ ess1688w(0xA1, x & 0xFF);
+
+ speed = (speed * 9) / 20;
+ x = 256 - 7160000 / (speed * 82);
+ ess1688w(0xA2, x & 0xFF);
+
+ if(audio.amode == Aread)
+ ess1688w(0xB8, 0x0E); /* A/D, autoinit */
+ else
+ ess1688w(0xB8, 0x04); /* D/A, autoinit */
+ x = ess1688r(0xA8) & ~0x03;
+ ess1688w(0xA8, x|0x01); /* 2 channels */
+ ess1688w(0xB9, 2); /* demand mode, 4 bytes per request */
+
+ if(audio.amode == Awrite)
+ ess1688w(0xB6, 0);
+ ess1688w(0xB7, 0x71);
+ ess1688w(0xB7, 0xBC);
+
+ x = ess1688r(0xB1) & 0x0F;
+ ess1688w(0xB1, x|0x50);
+ x = ess1688r(0xB2) & 0x0F;
+ ess1688w(0xB2, x|0x50);
+ if(audio.amode == Awrite)
+ sbcmd(0xD1); /* speaker on */
+
+ count = -Bufsize;
+ ess1688w(0xA4, count & 0xFF);
+ ess1688w(0xA5, (count>>8) & 0xFF);
+ x = ess1688r(0xB8);
+ ess1688w(0xB8, x|0x05);
+
+ audio.active = 1;
+ contindma();
+ iunlock(&blaster);
+}
+
+/*
+ * if audio is stopped,
+ * start it up again.
+ */
+static void
+pokeaudio(void)
+{
+ if(!audio.active)
+ blaster.startdma();
+}
+
+static void
+sb16intr(void)
+{
+ int stat, dummy;
+
+ stat = mxread(0x82) & 7; /* get irq status */
+ if(stat) {
+ dummy = 0;
+ if(stat & 2) {
+ ilock(&blaster);
+ dummy = inb(blaster.clri16);
+ contindma();
+ iunlock(&blaster);
+ audio.intr = 1;
+ wakeup(&audio.vous);
+ }
+ if(stat & 1) {
+ dummy = inb(blaster.clri8);
+ }
+ if(stat & 4) {
+ dummy = inb(blaster.clri401);
+ }
+ USED(dummy);
+ }
+}
+
+static void
+ess1688intr(void)
+{
+ int dummy;
+
+ if(audio.active){
+ ilock(&blaster);
+ contindma();
+ dummy = inb(blaster.clri8);
+ iunlock(&blaster);
+ audio.intr = 1;
+ wakeup(&audio.vous);
+ USED(dummy);
+ }
+ else
+ print("#A: unexpected ess1688 interrupt\n");
+}
+
+void
+audiosbintr(void)
+{
+ /*
+ * Carrera interrupt interface.
+ */
+ blaster.intr();
+}
+
+static void
+pcaudiosbintr(Ureg*, void*)
+{
+ /*
+ * x86 interrupt interface.
+ */
+ blaster.intr();
+}
+
+void
+audiodmaintr(void)
+{
+/* print("#A: dma interrupt\n"); /**/
+}
+
+static int
+anybuf(void*)
+{
+ return audio.intr;
+}
+
+/*
+ * wait for some output to get
+ * empty buffers back.
+ */
+static void
+waitaudio(void)
+{
+
+ audio.intr = 0;
+ pokeaudio();
+ tsleep(&audio.vous, anybuf, 0, 10000);
+ if(audio.intr == 0) {
+/* print("#A: audio timeout\n"); /**/
+ audio.active = 0;
+ pokeaudio();
+ }
+}
+
+static void
+sbbufinit(void)
+{
+ int i;
+ uchar *p;
+
+ p = (uchar*)(((ulong)xalloc((Nbuf+1) * Bufsize) + Bufsize-1) &
+ ~(Bufsize-1));
+ if (p == nil)
+ panic("sbbufinit: no memory");
+ for(i=0; i<Nbuf; i++) {
+ dcflush(p, Bufsize);
+ audio.buf[i].virt = UNCACHED(uchar, p);
+ audio.buf[i].phys = (ulong)PADDR(p);
+ p += Bufsize;
+ }
+}
+
+static void
+setempty(void)
+{
+ int i;
+
+ ilock(&blaster);
+ audio.empty.first = 0;
+ audio.empty.last = 0;
+ audio.full.first = 0;
+ audio.full.last = 0;
+ audio.current = 0;
+ audio.filling = 0;
+ audio.buffered = 0;
+ for(i=0; i<Nbuf; i++)
+ putbuf(&audio.empty, &audio.buf[i]);
+ audio.totcount = 0;
+ audio.tottime = 0LL;
+ iunlock(&blaster);
+}
+
+static void
+resetlevel(void)
+{
+ int i;
+
+ for(i=0; volumes[i].name; i++) {
+ audio.lovol[i] = volumes[i].ilval;
+ audio.rovol[i] = volumes[i].irval;
+ audio.livol[i] = volumes[i].ilval;
+ audio.rivol[i] = volumes[i].irval;
+ }
+}
+
+static int
+ess1688(ISAConf* sbconf)
+{
+ int i, major, minor;
+
+ /*
+ * Try for ESS1688.
+ */
+ sbcmd(0xE7); /* get version */
+ major = sbread();
+ minor = sbread();
+ if(major != 0x68 || minor != 0x8B){
+ print("#A: model %#.2x %#.2x; not ESS1688 compatible\n", major, minor);
+ return 1;
+ }
+
+ ess1688reset();
+
+ switch(sbconf->irq){
+ case 2:
+ case 9:
+ i = 0x50|(0<<2);
+ break;
+ case 5:
+ i = 0x50|(1<<2);
+ break;
+ case 7:
+ i = 0x50|(2<<2);
+ break;
+ case 10:
+ i = 0x50|(3<<2);
+ break;
+ default:
+ print("#A: bad ESS1688 irq %d\n", sbconf->irq);
+ return 1;
+ }
+ ess1688w(0xB1, i);
+
+ switch(sbconf->dma){
+ case 0:
+ i = 0x50|(1<<2);
+ break;
+ case 1:
+ i = 0xF0|(2<<2);
+ break;
+ case 3:
+ i = 0x50|(3<<2);
+ break;
+ default:
+ print("#A: bad ESS1688 dma %lud\n", sbconf->dma);
+ return 1;
+ }
+ ess1688w(0xB2, i);
+
+ ess1688reset();
+
+ blaster.startdma = ess1688startdma;
+ blaster.intr = ess1688intr;
+
+ return 0;
+}
+
+static void
+audioinit(void)
+{
+ ISAConf sbconf;
+ int i, x;
+ static int irq[] = {2,5,7,10};
+
+ sbconf.port = 0x220;
+ sbconf.dma = Dma;
+ sbconf.irq = IrqAUDIO;
+ if(isaconfig("audio", 0, &sbconf) == 0)
+ return;
+ if(sbconf.type == nil ||
+ (cistrcmp(sbconf.type, "sb16") != 0 &&
+ cistrcmp(sbconf.type, "ess1688") != 0))
+ return;
+ switch(sbconf.port){
+ case 0x220:
+ case 0x240:
+ case 0x260:
+ case 0x280:
+ break;
+ default:
+ print("#A: bad port %#lux\n", sbconf.port);
+ return;
+ }
+
+ if(ioalloc(sbconf.port, 0x10, 0, "audio") < 0){
+ print("#A: cannot ioalloc range %lux+0x10\n", sbconf.port);
+ return;
+ }
+ if(ioalloc(sbconf.port+0x100, 1, 0, "audio.mpu401") < 0){
+ iofree(sbconf.port);
+ print("#A: cannot ioalloc range %lux+0x01\n", sbconf.port+0x100);
+ return;
+ }
+
+ switch(sbconf.irq){
+ case 2:
+ case 5:
+ case 7:
+ case 9:
+ case 10:
+ break;
+ default:
+ print("#A: bad irq %d\n", sbconf.irq);
+ iofree(sbconf.port);
+ iofree(sbconf.port+0x100);
+ return;
+ }
+
+ blaster.reset = sbconf.port + 0x6;
+ blaster.read = sbconf.port + 0xa;
+ blaster.write = sbconf.port + 0xc;
+ blaster.wstatus = sbconf.port + 0xc;
+ blaster.rstatus = sbconf.port + 0xe;
+ blaster.mixaddr = sbconf.port + 0x4;
+ blaster.mixdata = sbconf.port + 0x5;
+ blaster.clri8 = sbconf.port + 0xe;
+ blaster.clri16 = sbconf.port + 0xf;
+ blaster.clri401 = sbconf.port + 0x100;
+ blaster.dma = sbconf.dma;
+
+ blaster.startdma = sb16startdma;
+ blaster.intr = sb16intr;
+
+ audio.amode = Aclosed;
+ resetlevel();
+
+ outb(blaster.reset, 1);
+ delay(1); /* >3 υs */
+ outb(blaster.reset, 0);
+ delay(1);
+
+ i = sbread();
+ if(i != 0xaa) {
+ print("#A: no response #%.2x\n", i);
+ iofree(sbconf.port);
+ iofree(sbconf.port+0x100);
+ return;
+ }
+
+ sbcmd(0xe1); /* get version */
+ audio.major = sbread();
+ audio.minor = sbread();
+
+ if(audio.major != 4) {
+ if(audio.major != 3 || audio.minor != 1 || ess1688(&sbconf)){
+ print("#A: model %#.2x %#.2x; not SB 16 compatible\n",
+ audio.major, audio.minor);
+ iofree(sbconf.port);
+ iofree(sbconf.port+0x100);
+ return;
+ }
+ audio.major = 4;
+ }
+
+ /*
+ * initialize the mixer
+ */
+ mxcmd(0x00, 0); /* Reset mixer */
+ mxvolume();
+
+ /*
+ * Attempt to set IRQ/DMA channels.
+ * On old ISA boards, these registers are writable.
+ * On Plug-n-Play boards, these are read-only.
+ *
+ * To accomodate both, we write to the registers,
+ * but then use the contents in case the write is
+ * disallowed.
+ */
+ mxcmd(0x80, /* irq */
+ (sbconf.irq==2)? 1:
+ (sbconf.irq==5)? 2:
+ (sbconf.irq==7)? 4:
+ (sbconf.irq==9)? 1:
+ (sbconf.irq==10)? 8:
+ 0);
+
+ mxcmd(0x81, 1<<blaster.dma); /* dma */
+
+ x = mxread(0x81);
+ for(i=5; i<=7; i++)
+ if(x & (1<<i)){
+ blaster.dma = i;
+ break;
+ }
+
+ x = mxread(0x80);
+ for(i=0; i<=3; i++)
+ if(x & (1<<i)){
+ sbconf.irq = irq[i];
+ break;
+ }
+
+ seteisadma(blaster.dma, audiodmaintr);
+ setvec(Int0vec+sbconf.irq, pcaudiosbintr, 0);
+}
+
+static Chan*
+audioattach(char *param)
+{
+ return devattach('A', param);
+}
+
+static Walkqid*
+audiowalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, audiodir, nelem(audiodir), devgen);
+}
+
+static int
+audiostat(Chan *c, uchar *db, int n)
+{
+ audiodir[Qaudio].length = audio.buffered;
+ return devstat(c, db, n, audiodir, nelem(audiodir), devgen);
+}
+
+static Chan*
+audioopen(Chan *c, int omode)
+{
+ int amode;
+
+ if(audio.major != 4)
+ error(Emajor);
+
+ switch((ulong)c->qid.path) {
+ default:
+ error(Eperm);
+ break;
+
+ case Qstatus:
+ if((omode&7) != OREAD)
+ error(Eperm);
+ case Qvolume:
+ case Qdir:
+ break;
+
+ case Qaudio:
+ amode = Awrite;
+ if((omode&7) == OREAD)
+ amode = Aread;
+ qlock(&audio);
+ if(audio.amode != Aclosed){
+ qunlock(&audio);
+ error(Einuse);
+ }
+ if(audio.bufinit == 0) {
+ audio.bufinit = 1;
+ sbbufinit();
+ }
+ audio.amode = amode;
+ setempty();
+ audio.curcount = 0;
+ qunlock(&audio);
+ mxvolume();
+ break;
+ }
+ c = devopen(c, omode, audiodir, nelem(audiodir), devgen);
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+
+ return c;
+}
+
+static void
+audioclose(Chan *c)
+{
+ Buf *b;
+
+ switch((ulong)c->qid.path) {
+ default:
+ error(Eperm);
+ break;
+
+ case Qdir:
+ case Qvolume:
+ case Qstatus:
+ break;
+
+ case Qaudio:
+ if(c->flag & COPEN) {
+ qlock(&audio);
+ if(audio.amode == Awrite) {
+ /* flush out last partial buffer */
+ b = audio.filling;
+ if(b) {
+ audio.filling = 0;
+ memset(b->virt+audio.curcount, 0, Bufsize-audio.curcount);
+ audio.buffered += Bufsize-audio.curcount;
+ swab(b->virt);
+ putbuf(&audio.full, b);
+ }
+ if(!audio.active && audio.full.first)
+ pokeaudio();
+ }
+ audio.amode = Aclosed;
+ if(waserror()){
+ qunlock(&audio);
+ nexterror();
+ }
+ while(audio.active)
+ waitaudio();
+ setempty();
+ poperror();
+ qunlock(&audio);
+ }
+ break;
+ }
+}
+
+static long
+audioread(Chan *c, void *v, long n, vlong off)
+{
+ int liv, riv, lov, rov;
+ long m, n0;
+ char buf[300];
+ Buf *b;
+ int j;
+ ulong offset = off;
+ char *a;
+
+ n0 = n;
+ a = v;
+ switch((ulong)c->qid.path) {
+ default:
+ error(Eperm);
+ break;
+
+ case Qdir:
+ return devdirread(c, a, n, audiodir, nelem(audiodir), devgen);
+
+ case Qaudio:
+ if(audio.amode != Aread)
+ error(Emode);
+ qlock(&audio);
+ if(waserror()){
+ qunlock(&audio);
+ nexterror();
+ }
+ while(n > 0) {
+ b = audio.filling;
+ if(b == 0) {
+ b = getbuf(&audio.full);
+ if(b == 0) {
+ waitaudio();
+ continue;
+ }
+ audio.filling = b;
+ swab(b->virt);
+ audio.curcount = 0;
+ }
+ m = Bufsize-audio.curcount;
+ if(m > n)
+ m = n;
+ memmove(a, b->virt+audio.curcount, m);
+
+ audio.curcount += m;
+ n -= m;
+ a += m;
+ audio.buffered -= m;
+ if(audio.curcount >= Bufsize) {
+ audio.filling = 0;
+ putbuf(&audio.empty, b);
+ }
+ }
+ poperror();
+ qunlock(&audio);
+ break;
+
+ case Qstatus:
+ buf[0] = 0;
+ snprint(buf, sizeof(buf), "bufsize %6d buffered %6d offset %10lud time %19lld\n",
+ Bufsize, audio.buffered, audio.totcount, audio.tottime);
+ return readstr(offset, a, n, buf);
+
+ case Qvolume:
+ j = 0;
+ buf[0] = 0;
+ for(m=0; volumes[m].name; m++){
+ liv = audio.livol[m];
+ riv = audio.rivol[m];
+ lov = audio.lovol[m];
+ rov = audio.rovol[m];
+ j += snprint(buf+j, sizeof(buf)-j, "%s", volumes[m].name);
+ if((volumes[m].flag & Fmono) || liv==riv && lov==rov){
+ if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov)
+ j += snprint(buf+j, sizeof(buf)-j, " %d", liv);
+ else{
+ if(volumes[m].flag & Fin)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " in %d", liv);
+ if(volumes[m].flag & Fout)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " out %d", lov);
+ }
+ }else{
+ if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) &&
+ liv==lov && riv==rov)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " left %d right %d",
+ liv, riv);
+ else{
+ if(volumes[m].flag & Fin)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " in left %d right %d",
+ liv, riv);
+ if(volumes[m].flag & Fout)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " out left %d right %d",
+ lov, rov);
+ }
+ }
+ j += snprint(buf+j, sizeof(buf)-j, "\n");
+ }
+ return readstr(offset, a, n, buf);
+ }
+ return n0-n;
+}
+
+static long
+audiowrite(Chan *c, void *vp, long n, vlong)
+{
+ long m, n0;
+ int i, v, left, right, in, out;
+ Cmdbuf *cb;
+ Buf *b;
+ char *a;
+
+ a = vp;
+ n0 = n;
+ switch((ulong)c->qid.path) {
+ default:
+ error(Eperm);
+ break;
+
+ case Qvolume:
+ v = Vaudio;
+ left = 1;
+ right = 1;
+ in = 1;
+ out = 1;
+ cb = parsecmd(vp, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+
+ for(i = 0; i < cb->nf; i++){
+ /*
+ * a number is volume
+ */
+ if(cb->f[i][0] >= '0' && cb->f[i][0] <= '9') {
+ m = strtoul(cb->f[i], 0, 10);
+ if(left && out)
+ audio.lovol[v] = m;
+ if(left && in)
+ audio.livol[v] = m;
+ if(right && out)
+ audio.rovol[v] = m;
+ if(right && in)
+ audio.rivol[v] = m;
+ mxvolume();
+ goto cont0;
+ }
+
+ for(m=0; volumes[m].name; m++) {
+ if(strcmp(cb->f[i], volumes[m].name) == 0) {
+ v = m;
+ in = 1;
+ out = 1;
+ left = 1;
+ right = 1;
+ goto cont0;
+ }
+ }
+
+ if(strcmp(cb->f[i], "reset") == 0) {
+ resetlevel();
+ mxvolume();
+ goto cont0;
+ }
+ if(strcmp(cb->f[i], "in") == 0) {
+ in = 1;
+ out = 0;
+ goto cont0;
+ }
+ if(strcmp(cb->f[i], "out") == 0) {
+ in = 0;
+ out = 1;
+ goto cont0;
+ }
+ if(strcmp(cb->f[i], "left") == 0) {
+ left = 1;
+ right = 0;
+ goto cont0;
+ }
+ if(strcmp(cb->f[i], "right") == 0) {
+ left = 0;
+ right = 1;
+ goto cont0;
+ }
+ error(Evolume);
+ break;
+ cont0:;
+ }
+ free(cb);
+ poperror();
+ break;
+
+ case Qaudio:
+ if(audio.amode != Awrite)
+ error(Emode);
+ qlock(&audio);
+ if(waserror()){
+ qunlock(&audio);
+ nexterror();
+ }
+ while(n > 0) {
+ b = audio.filling;
+ if(b == 0) {
+ b = getbuf(&audio.empty);
+ if(b == 0) {
+ waitaudio();
+ continue;
+ }
+ audio.filling = b;
+ audio.curcount = 0;
+ }
+
+ m = Bufsize-audio.curcount;
+ if(m > n)
+ m = n;
+ memmove(b->virt+audio.curcount, a, m);
+
+ audio.curcount += m;
+ n -= m;
+ a += m;
+ audio.buffered += m;
+ if(audio.curcount >= Bufsize) {
+ audio.filling = 0;
+ swab(b->virt);
+ putbuf(&audio.full, b);
+ pokeaudio();
+ }
+ }
+ poperror();
+ qunlock(&audio);
+ break;
+ }
+ return n0 - n;
+}
+
+static void
+swab(uchar *a)
+{
+ ulong *p, *ep, b;
+
+ if(!SBswab){
+ USED(a);
+ return;
+ }
+ p = (ulong*)a;
+ ep = p + (Bufsize>>2);
+ while(p < ep) {
+ b = *p;
+ b = (b>>24) | (b<<24) |
+ ((b&0xff0000) >> 8) |
+ ((b&0x00ff00) << 8);
+ *p++ = b;
+ }
+}
+
+Dev audiodevtab = {
+ 'A',
+ "audio",
+
+ devreset,
+ audioinit,
+ devshutdown,
+ audioattach,
+ audiowalk,
+ audiostat,
+ audioopen,
+ devcreate,
+ audioclose,
+ audioread,
+ devbread,
+ audiowrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/port/devbridge.c b/sys/src/9/port/devbridge.c
new file mode 100755
index 000000000..be416a249
--- /dev/null
+++ b/sys/src/9/port/devbridge.c
@@ -0,0 +1,1195 @@
+/*
+ * IPv4 Ethernet bridge
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../ip/ip.h"
+#include "../port/netif.h"
+#include "../port/error.h"
+
+typedef struct Bridge Bridge;
+typedef struct Port Port;
+typedef struct Centry Centry;
+typedef struct Iphdr Iphdr;
+typedef struct Tcphdr Tcphdr;
+
+enum
+{
+ Qtopdir= 1, /* top level directory */
+
+ Qbridgedir, /* bridge* directory */
+ Qbctl,
+ Qstats,
+ Qcache,
+ Qlog,
+
+ Qportdir, /* directory for a protocol */
+ Qpctl,
+ Qlocal,
+ Qstatus,
+
+ MaxQ,
+
+ Maxbridge= 4,
+ Maxport= 128, // power of 2
+ CacheHash= 257, // prime
+ CacheLook= 5, // how many cache entries to examine
+ CacheSize= (CacheHash+CacheLook-1),
+ CacheTimeout= 5*60, // timeout for cache entry in seconds
+
+ TcpMssMax = 1300, // max desirable Tcp MSS value
+ TunnelMtu = 1400,
+};
+
+static Dirtab bridgedirtab[]={
+ "ctl", {Qbctl}, 0, 0666,
+ "stats", {Qstats}, 0, 0444,
+ "cache", {Qcache}, 0, 0444,
+ "log", {Qlog}, 0, 0666,
+};
+
+static Dirtab portdirtab[]={
+ "ctl", {Qpctl}, 0, 0666,
+ "local", {Qlocal}, 0, 0444,
+ "status", {Qstatus}, 0, 0444,
+};
+
+enum {
+ Logcache= (1<<0),
+ Logmcast= (1<<1),
+};
+
+// types of interfaces
+enum
+{
+ Tether,
+ Ttun,
+};
+
+static Logflag logflags[] =
+{
+ { "cache", Logcache, },
+ { "multicast", Logmcast, },
+ { nil, 0, },
+};
+
+static Dirtab *dirtab[MaxQ];
+
+#define TYPE(x) (((ulong)(x).path) & 0xff)
+#define PORT(x) ((((ulong)(x).path) >> 8)&(Maxport-1))
+#define QID(x, y) (((x)<<8) | (y))
+
+struct Centry
+{
+ uchar d[Eaddrlen];
+ int port;
+ long expire; // entry expires this many seconds after bootime
+ long src;
+ long dst;
+};
+
+struct Bridge
+{
+ QLock;
+ int nport;
+ Port *port[Maxport];
+ Centry cache[CacheSize];
+ ulong hit;
+ ulong miss;
+ ulong copy;
+ long delay0; // constant microsecond delay per packet
+ long delayn; // microsecond delay per byte
+ int tcpmss; // modify tcpmss value
+
+ Log;
+};
+
+struct Port
+{
+ int id;
+ Bridge *bridge;
+ int ref;
+ int closed;
+
+ Chan *data[2]; // channel to data
+
+ Proc *readp; // read proc
+
+ // the following uniquely identifies the port
+ int type;
+ char name[KNAMELEN];
+
+ // owner hash - avoids bind/unbind races
+ ulong ownhash;
+
+ // various stats
+ int in; // number of packets read
+ int inmulti; // multicast or broadcast
+ int inunknown; // unknown address
+ int out; // number of packets read
+ int outmulti; // multicast or broadcast
+ int outunknown; // unknown address
+ int outfrag; // fragmented the packet
+ int nentry; // number of cache entries for this port
+};
+
+enum {
+ IP_TCPPROTO = 6,
+ EOLOPT = 0,
+ NOOPOPT = 1,
+ MSSOPT = 2,
+ MSS_LENGTH = 4, /* Mean segment size */
+ SYN = 0x02, /* Pkt. is synchronise */
+ IPHDR = 20, /* sizeof(Iphdr) */
+};
+
+struct Iphdr
+{
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* ip->identification */
+ uchar frag[2]; /* Fragment information */
+ uchar ttl; /* Time to live */
+ uchar proto; /* Protocol */
+ uchar cksum[2]; /* Header checksum */
+ uchar src[4]; /* IP source */
+ uchar dst[4]; /* IP destination */
+};
+
+struct Tcphdr
+{
+ uchar sport[2];
+ uchar dport[2];
+ uchar seq[4];
+ uchar ack[4];
+ uchar flag[2];
+ uchar win[2];
+ uchar cksum[2];
+ uchar urg[2];
+};
+
+static Bridge bridgetab[Maxbridge];
+
+static int m2p[] = {
+ [OREAD] 4,
+ [OWRITE] 2,
+ [ORDWR] 6
+};
+
+static int bridgegen(Chan *c, char*, Dirtab*, int, int s, Dir *dp);
+static void portbind(Bridge *b, int argc, char *argv[]);
+static void portunbind(Bridge *b, int argc, char *argv[]);
+static void etherread(void *a);
+static char *cachedump(Bridge *b);
+static void portfree(Port *port);
+static void cacheflushport(Bridge *b, int port);
+static void etherwrite(Port *port, Block *bp);
+
+static void
+bridgeinit(void)
+{
+ int i;
+ Dirtab *dt;
+
+ // setup dirtab with non directory entries
+ for(i=0; i<nelem(bridgedirtab); i++) {
+ dt = bridgedirtab + i;
+ dirtab[TYPE(dt->qid)] = dt;
+ }
+ for(i=0; i<nelem(portdirtab); i++) {
+ dt = portdirtab + i;
+ dirtab[TYPE(dt->qid)] = dt;
+ }
+}
+
+static Chan*
+bridgeattach(char* spec)
+{
+ Chan *c;
+ int dev;
+
+ dev = atoi(spec);
+ if(dev<0 || dev >= Maxbridge)
+ error("bad specification");
+
+ c = devattach('B', spec);
+ mkqid(&c->qid, QID(0, Qtopdir), 0, QTDIR);
+ c->dev = dev;
+ return c;
+}
+
+static Walkqid*
+bridgewalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, (Dirtab*)0, 0, bridgegen);
+}
+
+static int
+bridgestat(Chan* c, uchar* db, int n)
+{
+ return devstat(c, db, n, (Dirtab *)0, 0L, bridgegen);
+}
+
+static Chan*
+bridgeopen(Chan* c, int omode)
+{
+ int perm;
+ Bridge *b;
+
+ omode &= 3;
+ perm = m2p[omode];
+ USED(perm);
+
+ b = bridgetab + c->dev;
+ USED(b);
+
+ switch(TYPE(c->qid)) {
+ default:
+ break;
+ case Qlog:
+ logopen(b);
+ break;
+ case Qcache:
+ c->aux = cachedump(b);
+ break;
+ }
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+static void
+bridgeclose(Chan* c)
+{
+ Bridge *b = bridgetab + c->dev;
+
+ switch(TYPE(c->qid)) {
+ case Qcache:
+ if(c->flag & COPEN)
+ free(c->aux);
+ break;
+ case Qlog:
+ if(c->flag & COPEN)
+ logclose(b);
+ break;
+ }
+}
+
+static long
+bridgeread(Chan *c, void *a, long n, vlong off)
+{
+ char buf[256];
+ Bridge *b = bridgetab + c->dev;
+ Port *port;
+ int i, ingood, outgood;
+
+ USED(off);
+ switch(TYPE(c->qid)) {
+ default:
+ error(Eperm);
+ case Qtopdir:
+ case Qbridgedir:
+ case Qportdir:
+ return devdirread(c, a, n, 0, 0, bridgegen);
+ case Qlog:
+ return logread(b, a, off, n);
+ case Qstatus:
+ qlock(b);
+ port = b->port[PORT(c->qid)];
+ if(port == 0)
+ strcpy(buf, "unbound\n");
+ else {
+ i = 0;
+ switch(port->type) {
+ default:
+ panic("bridgeread: unknown port type: %d",
+ port->type);
+ case Tether:
+ i += snprint(buf+i, sizeof(buf)-i, "ether %s: ", port->name);
+ break;
+ case Ttun:
+ i += snprint(buf+i, sizeof(buf)-i, "tunnel %s: ", port->name);
+ break;
+ }
+ ingood = port->in - port->inmulti - port->inunknown;
+ outgood = port->out - port->outmulti - port->outunknown;
+ i += snprint(buf+i, sizeof(buf)-i,
+ "in=%d(%d:%d:%d) out=%d(%d:%d:%d:%d)\n",
+ port->in, ingood, port->inmulti, port->inunknown,
+ port->out, outgood, port->outmulti,
+ port->outunknown, port->outfrag);
+ USED(i);
+ }
+ n = readstr(off, a, n, buf);
+ qunlock(b);
+ return n;
+ case Qbctl:
+ snprint(buf, sizeof(buf), "%s tcpmss\ndelay %ld %ld\n",
+ b->tcpmss ? "set" : "clear", b->delay0, b->delayn);
+ n = readstr(off, a, n, buf);
+ return n;
+ case Qcache:
+ n = readstr(off, a, n, c->aux);
+ return n;
+ case Qstats:
+ snprint(buf, sizeof(buf), "hit=%uld miss=%uld copy=%uld\n",
+ b->hit, b->miss, b->copy);
+ n = readstr(off, a, n, buf);
+ return n;
+ }
+}
+
+static void
+bridgeoption(Bridge *b, char *option, int value)
+{
+ if(strcmp(option, "tcpmss") == 0)
+ b->tcpmss = value;
+ else
+ error("unknown bridge option");
+}
+
+
+static long
+bridgewrite(Chan *c, void *a, long n, vlong off)
+{
+ Bridge *b = bridgetab + c->dev;
+ Cmdbuf *cb;
+ char *arg0, *p;
+
+ USED(off);
+ switch(TYPE(c->qid)) {
+ default:
+ error(Eperm);
+ case Qbctl:
+ cb = parsecmd(a, n);
+ qlock(b);
+ if(waserror()) {
+ qunlock(b);
+ free(cb);
+ nexterror();
+ }
+ if(cb->nf == 0)
+ error("short write");
+ arg0 = cb->f[0];
+ if(strcmp(arg0, "bind") == 0) {
+ portbind(b, cb->nf-1, cb->f+1);
+ } else if(strcmp(arg0, "unbind") == 0) {
+ portunbind(b, cb->nf-1, cb->f+1);
+ } else if(strcmp(arg0, "cacheflush") == 0) {
+ log(b, Logcache, "cache flush\n");
+ memset(b->cache, 0, CacheSize*sizeof(Centry));
+ } else if(strcmp(arg0, "set") == 0) {
+ if(cb->nf != 2)
+ error("usage: set option");
+ bridgeoption(b, cb->f[1], 1);
+ } else if(strcmp(arg0, "clear") == 0) {
+ if(cb->nf != 2)
+ error("usage: clear option");
+ bridgeoption(b, cb->f[1], 0);
+ } else if(strcmp(arg0, "delay") == 0) {
+ if(cb->nf != 3)
+ error("usage: delay delay0 delayn");
+ b->delay0 = strtol(cb->f[1], nil, 10);
+ b->delayn = strtol(cb->f[2], nil, 10);
+ } else
+ error("unknown control request");
+ poperror();
+ qunlock(b);
+ free(cb);
+ return n;
+ case Qlog:
+ cb = parsecmd(a, n);
+ p = logctl(b, cb->nf, cb->f, logflags);
+ free(cb);
+ if(p != nil)
+ error(p);
+ return n;
+ }
+}
+
+static int
+bridgegen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
+{
+ Bridge *b = bridgetab + c->dev;
+ int type = TYPE(c->qid);
+ Dirtab *dt;
+ Qid qid;
+
+ if(s == DEVDOTDOT){
+ switch(TYPE(c->qid)){
+ case Qtopdir:
+ case Qbridgedir:
+ snprint(up->genbuf, sizeof(up->genbuf), "#B%ld", c->dev);
+ mkqid(&qid, Qtopdir, 0, QTDIR);
+ devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ break;
+ case Qportdir:
+ snprint(up->genbuf, sizeof(up->genbuf), "bridge%ld", c->dev);
+ mkqid(&qid, Qbridgedir, 0, QTDIR);
+ devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ break;
+ default:
+ panic("bridgewalk %llux", c->qid.path);
+ }
+ return 1;
+ }
+
+ switch(type) {
+ default:
+ /* non-directory entries end up here */
+ if(c->qid.type & QTDIR)
+ panic("bridgegen: unexpected directory");
+ if(s != 0)
+ return -1;
+ dt = dirtab[TYPE(c->qid)];
+ if(dt == nil)
+ panic("bridgegen: unknown type: %lud", TYPE(c->qid));
+ devdir(c, c->qid, dt->name, dt->length, eve, dt->perm, dp);
+ return 1;
+ case Qtopdir:
+ if(s != 0)
+ return -1;
+ snprint(up->genbuf, sizeof(up->genbuf), "bridge%ld", c->dev);
+ mkqid(&qid, QID(0, Qbridgedir), 0, QTDIR);
+ devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+ case Qbridgedir:
+ if(s<nelem(bridgedirtab)) {
+ dt = bridgedirtab+s;
+ devdir(c, dt->qid, dt->name, dt->length, eve, dt->perm, dp);
+ return 1;
+ }
+ s -= nelem(bridgedirtab);
+ if(s >= b->nport)
+ return -1;
+ mkqid(&qid, QID(s, Qportdir), 0, QTDIR);
+ snprint(up->genbuf, sizeof(up->genbuf), "%d", s);
+ devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+ case Qportdir:
+ if(s>=nelem(portdirtab))
+ return -1;
+ dt = portdirtab+s;
+ mkqid(&qid, QID(PORT(c->qid),TYPE(dt->qid)), 0, QTFILE);
+ devdir(c, qid, dt->name, dt->length, eve, dt->perm, dp);
+ return 1;
+ }
+}
+
+// parse mac address; also in netif.c
+static int
+parseaddr(uchar *to, char *from, int alen)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ for(i = 0; i < alen; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+// assumes b is locked
+static void
+portbind(Bridge *b, int argc, char *argv[])
+{
+ Port *port;
+ Chan *ctl;
+ int type = 0, i, n;
+ ulong ownhash;
+ char *dev, *dev2 = nil, *p;
+ char buf[100], name[KNAMELEN], path[8*KNAMELEN];
+ static char usage[] = "usage: bind ether|tunnel name ownhash dev [dev2]";
+
+ memset(name, 0, KNAMELEN);
+ if(argc < 4)
+ error(usage);
+ if(strcmp(argv[0], "ether") == 0) {
+ if(argc != 4)
+ error(usage);
+ type = Tether;
+ strncpy(name, argv[1], KNAMELEN);
+ name[KNAMELEN-1] = 0;
+// parseaddr(addr, argv[1], Eaddrlen);
+ } else if(strcmp(argv[0], "tunnel") == 0) {
+ if(argc != 5)
+ error(usage);
+ type = Ttun;
+ strncpy(name, argv[1], KNAMELEN);
+ name[KNAMELEN-1] = 0;
+// parseip(addr, argv[1]);
+ dev2 = argv[4];
+ } else
+ error(usage);
+ ownhash = atoi(argv[2]);
+ dev = argv[3];
+ for(i=0; i<b->nport; i++) {
+ port = b->port[i];
+ if(port != nil && port->type == type &&
+ memcmp(port->name, name, KNAMELEN) == 0)
+ error("port in use");
+ }
+ for(i=0; i<Maxport; i++)
+ if(b->port[i] == nil)
+ break;
+ if(i == Maxport)
+ error("no more ports");
+ port = smalloc(sizeof(Port));
+ port->ref = 1;
+ port->id = i;
+ port->ownhash = ownhash;
+
+ if(waserror()) {
+ portfree(port);
+ nexterror();
+ }
+ port->type = type;
+ memmove(port->name, name, KNAMELEN);
+ switch(port->type) {
+ default:
+ panic("portbind: unknown port type: %d", type);
+ case Tether:
+ snprint(path, sizeof(path), "%s/clone", dev);
+ ctl = namec(path, Aopen, ORDWR, 0);
+ if(waserror()) {
+ cclose(ctl);
+ nexterror();
+ }
+ // check addr?
+
+ // get directory name
+ n = devtab[ctl->type]->read(ctl, buf, sizeof(buf), 0);
+ buf[n] = 0;
+ for(p = buf; *p == ' '; p++)
+ ;
+ snprint(path, sizeof(path), "%s/%lud/data", dev, strtoul(p, 0, 0));
+
+ // setup connection to be promiscuous
+ snprint(buf, sizeof(buf), "connect -1");
+ devtab[ctl->type]->write(ctl, buf, strlen(buf), 0);
+ snprint(buf, sizeof(buf), "promiscuous");
+ devtab[ctl->type]->write(ctl, buf, strlen(buf), 0);
+ snprint(buf, sizeof(buf), "bridge");
+ devtab[ctl->type]->write(ctl, buf, strlen(buf), 0);
+
+ // open data port
+ port->data[0] = namec(path, Aopen, ORDWR, 0);
+ // dup it
+ incref(port->data[0]);
+ port->data[1] = port->data[0];
+
+ poperror();
+ cclose(ctl);
+
+ break;
+ case Ttun:
+ port->data[0] = namec(dev, Aopen, OREAD, 0);
+ port->data[1] = namec(dev2, Aopen, OWRITE, 0);
+ break;
+ }
+
+ poperror();
+
+ /* committed to binding port */
+ b->port[port->id] = port;
+ port->bridge = b;
+ if(b->nport <= port->id)
+ b->nport = port->id+1;
+
+ // assumes kproc always succeeds
+ kproc("etherread", etherread, port); // poperror must be next
+ port->ref++;
+}
+
+// assumes b is locked
+static void
+portunbind(Bridge *b, int argc, char *argv[])
+{
+ int type = 0, i;
+ char name[KNAMELEN];
+ ulong ownhash;
+ Port *port = nil;
+ static char usage[] = "usage: unbind ether|tunnel addr [ownhash]";
+
+ memset(name, 0, KNAMELEN);
+ if(argc < 2 || argc > 3)
+ error(usage);
+ if(strcmp(argv[0], "ether") == 0) {
+ type = Tether;
+ strncpy(name, argv[1], KNAMELEN);
+ name[KNAMELEN-1] = 0;
+// parseaddr(addr, argv[1], Eaddrlen);
+ } else if(strcmp(argv[0], "tunnel") == 0) {
+ type = Ttun;
+ strncpy(name, argv[1], KNAMELEN);
+ name[KNAMELEN-1] = 0;
+// parseip(addr, argv[1]);
+ } else
+ error(usage);
+ if(argc == 3)
+ ownhash = atoi(argv[2]);
+ else
+ ownhash = 0;
+ for(i=0; i<b->nport; i++) {
+ port = b->port[i];
+ if(port != nil && port->type == type &&
+ memcmp(port->name, name, KNAMELEN) == 0)
+ break;
+ }
+ if(i == b->nport)
+ error("port not found");
+ if(ownhash != 0 && port->ownhash != 0 && ownhash != port->ownhash)
+ error("bad owner hash");
+
+ port->closed = 1;
+ b->port[i] = nil; // port is now unbound
+ cacheflushport(b, i);
+
+ // try and stop reader
+ if(port->readp)
+ postnote(port->readp, 1, "unbind", 0);
+ portfree(port);
+}
+
+// assumes b is locked
+static Centry *
+cachelookup(Bridge *b, uchar d[Eaddrlen])
+{
+ int i;
+ uint h;
+ Centry *p;
+ long sec;
+
+ // dont cache multicast or broadcast
+ if(d[0] & 1)
+ return 0;
+
+ h = 0;
+ for(i=0; i<Eaddrlen; i++) {
+ h *= 7;
+ h += d[i];
+ }
+ h %= CacheHash;
+ p = b->cache + h;
+ sec = TK2SEC(m->ticks);
+ for(i=0; i<CacheLook; i++,p++) {
+ if(memcmp(d, p->d, Eaddrlen) == 0) {
+ p->dst++;
+ if(sec >= p->expire) {
+ log(b, Logcache, "expired cache entry: %E %d\n",
+ d, p->port);
+ return nil;
+ }
+ p->expire = sec + CacheTimeout;
+ return p;
+ }
+ }
+ log(b, Logcache, "cache miss: %E\n", d);
+ return nil;
+}
+
+// assumes b is locked
+static void
+cacheupdate(Bridge *b, uchar d[Eaddrlen], int port)
+{
+ int i;
+ uint h;
+ Centry *p, *pp;
+ long sec;
+
+ // dont cache multicast or broadcast
+ if(d[0] & 1) {
+ log(b, Logcache, "bad source address: %E\n", d);
+ return;
+ }
+
+ h = 0;
+ for(i=0; i<Eaddrlen; i++) {
+ h *= 7;
+ h += d[i];
+ }
+ h %= CacheHash;
+ p = b->cache + h;
+ pp = p;
+ sec = p->expire;
+
+ // look for oldest entry
+ for(i=0; i<CacheLook; i++,p++) {
+ if(memcmp(p->d, d, Eaddrlen) == 0) {
+ p->expire = TK2SEC(m->ticks) + CacheTimeout;
+ if(p->port != port) {
+ log(b, Logcache, "NIC changed port %d->%d: %E\n",
+ p->port, port, d);
+ p->port = port;
+ }
+ p->src++;
+ return;
+ }
+ if(p->expire < sec) {
+ sec = p->expire;
+ pp = p;
+ }
+ }
+ if(pp->expire != 0)
+ log(b, Logcache, "bumping from cache: %E %d\n", pp->d, pp->port);
+ pp->expire = TK2SEC(m->ticks) + CacheTimeout;
+ memmove(pp->d, d, Eaddrlen);
+ pp->port = port;
+ pp->src = 1;
+ pp->dst = 0;
+ log(b, Logcache, "adding to cache: %E %d\n", pp->d, pp->port);
+}
+
+// assumes b is locked
+static void
+cacheflushport(Bridge *b, int port)
+{
+ Centry *ce;
+ int i;
+
+ ce = b->cache;
+ for(i=0; i<CacheSize; i++,ce++) {
+ if(ce->port != port)
+ continue;
+ memset(ce, 0, sizeof(Centry));
+ }
+}
+
+static char *
+cachedump(Bridge *b)
+{
+ int i, n;
+ long sec, off;
+ char *buf, *p, *ep;
+ Centry *ce;
+ char c;
+
+ qlock(b);
+ if(waserror()) {
+ qunlock(b);
+ nexterror();
+ }
+ sec = TK2SEC(m->ticks);
+ n = 0;
+ for(i=0; i<CacheSize; i++)
+ if(b->cache[i].expire != 0)
+ n++;
+
+ n *= 51; // change if print format is changed
+ n += 10; // some slop at the end
+ buf = malloc(n);
+ p = buf;
+ ep = buf + n;
+ ce = b->cache;
+ off = seconds() - sec;
+ for(i=0; i<CacheSize; i++,ce++) {
+ if(ce->expire == 0)
+ continue;
+ c = (sec < ce->expire)?'v':'e';
+ p += snprint(p, ep-p, "%E %2d %10ld %10ld %10ld %c\n", ce->d,
+ ce->port, ce->src, ce->dst, ce->expire+off, c);
+ }
+ *p = 0;
+ poperror();
+ qunlock(b);
+
+ return buf;
+}
+
+
+
+// assumes b is locked
+static void
+ethermultiwrite(Bridge *b, Block *bp, Port *port)
+{
+ Port *oport;
+ Block *bp2;
+ Etherpkt *ep;
+ int i, mcast;
+
+ if(waserror()) {
+ if(bp)
+ freeb(bp);
+ nexterror();
+ }
+
+ ep = (Etherpkt*)bp->rp;
+ mcast = ep->d[0] & 1; /* multicast bit of ethernet address */
+
+ oport = nil;
+ for(i=0; i<b->nport; i++) {
+ if(i == port->id || b->port[i] == nil)
+ continue;
+ /*
+ * we need to forward multicast packets for ipv6,
+ * so always do it.
+ */
+ if(mcast)
+ b->port[i]->outmulti++;
+ else
+ b->port[i]->outunknown++;
+
+ // delay one so that the last write does not copy
+ if(oport != nil) {
+ b->copy++;
+ bp2 = copyblock(bp, blocklen(bp));
+ if(!waserror()) {
+ etherwrite(oport, bp2);
+ poperror();
+ }
+ }
+ oport = b->port[i];
+ }
+
+ // last write free block
+ if(oport) {
+ bp2 = bp; bp = nil; USED(bp);
+ if(!waserror()) {
+ etherwrite(oport, bp2);
+ poperror();
+ }
+ } else
+ freeb(bp);
+
+ poperror();
+}
+
+static void
+tcpmsshack(Etherpkt *epkt, int n)
+{
+ int hl, optlen;
+ Iphdr *iphdr;
+ Tcphdr *tcphdr;
+ ulong mss, cksum;
+ uchar *optr;
+
+ /* ignore non-ipv4 packets */
+ if(nhgets(epkt->type) != ETIP4)
+ return;
+ iphdr = (Iphdr*)(epkt->data);
+ n -= ETHERHDRSIZE;
+ if(n < IPHDR)
+ return;
+
+ /* ignore bad packets */
+ if(iphdr->vihl != (IP_VER4|IP_HLEN4)) {
+ hl = (iphdr->vihl&0xF)<<2;
+ if((iphdr->vihl&0xF0) != IP_VER4 || hl < (IP_HLEN4<<2))
+ return;
+ } else
+ hl = IP_HLEN4<<2;
+
+ /* ignore non-tcp packets */
+ if(iphdr->proto != IP_TCPPROTO)
+ return;
+ n -= hl;
+ if(n < sizeof(Tcphdr))
+ return;
+ tcphdr = (Tcphdr*)((uchar*)(iphdr) + hl);
+ // MSS can only appear in SYN packet
+ if(!(tcphdr->flag[1] & SYN))
+ return;
+ hl = (tcphdr->flag[0] & 0xf0)>>2;
+ if(n < hl)
+ return;
+
+ // check for MSS option
+ optr = (uchar*)tcphdr + sizeof(Tcphdr);
+ n = hl - sizeof(Tcphdr);
+ for(;;) {
+ if(n <= 0 || *optr == EOLOPT)
+ return;
+ if(*optr == NOOPOPT) {
+ n--;
+ optr++;
+ continue;
+ }
+ optlen = optr[1];
+ if(optlen < 2 || optlen > n)
+ return;
+ if(*optr == MSSOPT && optlen == MSS_LENGTH)
+ break;
+ n -= optlen;
+ optr += optlen;
+ }
+
+ mss = nhgets(optr+2);
+ if(mss <= TcpMssMax)
+ return;
+ // fit checksum
+ cksum = nhgets(tcphdr->cksum);
+ if(optr-(uchar*)tcphdr & 1) {
+print("tcpmsshack: odd alignment!\n");
+ // odd alignments are a pain
+ cksum += nhgets(optr+1);
+ cksum -= (optr[1]<<8)|(TcpMssMax>>8);
+ cksum += (cksum>>16);
+ cksum &= 0xffff;
+ cksum += nhgets(optr+3);
+ cksum -= ((TcpMssMax&0xff)<<8)|optr[4];
+ cksum += (cksum>>16);
+ } else {
+ cksum += mss;
+ cksum -= TcpMssMax;
+ cksum += (cksum>>16);
+ }
+ hnputs(tcphdr->cksum, cksum);
+ hnputs(optr+2, TcpMssMax);
+}
+
+/*
+ * process to read from the ethernet
+ */
+static void
+etherread(void *a)
+{
+ Port *port = a;
+ Bridge *b = port->bridge;
+ Block *bp, *bp2;
+ Etherpkt *ep;
+ Centry *ce;
+ long md;
+
+ qlock(b);
+ port->readp = up; /* hide identity under a rock for unbind */
+
+ while(!port->closed){
+ // release lock to read - error means it is time to quit
+ qunlock(b);
+ if(waserror()) {
+ print("etherread read error: %s\n", up->errstr);
+ qlock(b);
+ break;
+ }
+ if(0)
+ print("devbridge: etherread: reading\n");
+ bp = devtab[port->data[0]->type]->bread(port->data[0],
+ ETHERMAXTU, 0);
+ if(0)
+ print("devbridge: etherread: blocklen = %d\n",
+ blocklen(bp));
+ poperror();
+ qlock(b);
+ if(bp == nil || port->closed)
+ break;
+ if(waserror()) {
+// print("etherread bridge error\n");
+ if(bp)
+ freeb(bp);
+ continue;
+ }
+ if(blocklen(bp) < ETHERMINTU)
+ error("short packet");
+ port->in++;
+
+ ep = (Etherpkt*)bp->rp;
+ cacheupdate(b, ep->s, port->id);
+ if(b->tcpmss)
+ tcpmsshack(ep, BLEN(bp));
+
+ /*
+ * delay packets to simulate a slow link
+ */
+ if(b->delay0 || b->delayn){
+ md = b->delay0 + b->delayn * BLEN(bp);
+ if(md > 0)
+ microdelay(md);
+ }
+
+ if(ep->d[0] & 1) {
+ log(b, Logmcast, "multicast: port=%d src=%E dst=%E type=%#.4ux\n",
+ port->id, ep->s, ep->d, ep->type[0]<<8|ep->type[1]);
+ port->inmulti++;
+ bp2 = bp; bp = nil;
+ ethermultiwrite(b, bp2, port);
+ } else {
+ ce = cachelookup(b, ep->d);
+ if(ce == nil) {
+ b->miss++;
+ port->inunknown++;
+ bp2 = bp; bp = nil;
+ ethermultiwrite(b, bp2, port);
+ }else if(ce->port != port->id){
+ b->hit++;
+ bp2 = bp; bp = nil;
+ etherwrite(b->port[ce->port], bp2);
+ }
+ }
+
+ poperror();
+ if(bp)
+ freeb(bp);
+ }
+// print("etherread: trying to exit\n");
+ port->readp = nil;
+ portfree(port);
+ qunlock(b);
+ pexit("hangup", 1);
+}
+
+static int
+fragment(Etherpkt *epkt, int n)
+{
+ Iphdr *iphdr;
+
+ if(n <= TunnelMtu)
+ return 0;
+
+ /* ignore non-ipv4 packets */
+ if(nhgets(epkt->type) != ETIP4)
+ return 0;
+ iphdr = (Iphdr*)(epkt->data);
+ n -= ETHERHDRSIZE;
+ /*
+ * ignore: IP runt packets, bad packets (I don't handle IP
+ * options for the moment), packets with don't-fragment set,
+ * and short blocks.
+ */
+ if(n < IPHDR || iphdr->vihl != (IP_VER4|IP_HLEN4) ||
+ iphdr->frag[0] & (IP_DF>>8) || nhgets(iphdr->length) > n)
+ return 0;
+
+ return 1;
+}
+
+
+static void
+etherwrite(Port *port, Block *bp)
+{
+ Iphdr *eh, *feh;
+ Etherpkt *epkt;
+ int n, lid, len, seglen, chunk, dlen, blklen, offset, mf;
+ Block *xp, *nb;
+ ushort fragoff, frag;
+
+ port->out++;
+ epkt = (Etherpkt*)bp->rp;
+ n = blocklen(bp);
+ if(port->type != Ttun || !fragment(epkt, n)) {
+ devtab[port->data[1]->type]->bwrite(port->data[1], bp, 0);
+ return;
+ }
+ port->outfrag++;
+ if(waserror()){
+ freeblist(bp);
+ nexterror();
+ }
+
+ seglen = (TunnelMtu - ETHERHDRSIZE - IPHDR) & ~7;
+ eh = (Iphdr*)(epkt->data);
+ len = nhgets(eh->length);
+ frag = nhgets(eh->frag);
+ mf = frag & IP_MF;
+ frag <<= 3;
+ dlen = len - IPHDR;
+ xp = bp;
+ lid = nhgets(eh->id);
+ offset = ETHERHDRSIZE+IPHDR;
+ while(xp != nil && offset && offset >= BLEN(xp)) {
+ offset -= BLEN(xp);
+ xp = xp->next;
+ }
+ xp->rp += offset;
+
+ if(0)
+ print("seglen=%d, dlen=%d, mf=%x, frag=%d\n",
+ seglen, dlen, mf, frag);
+ for(fragoff = 0; fragoff < dlen; fragoff += seglen) {
+ nb = allocb(ETHERHDRSIZE+IPHDR+seglen);
+
+ feh = (Iphdr*)(nb->wp+ETHERHDRSIZE);
+
+ memmove(nb->wp, epkt, ETHERHDRSIZE+IPHDR);
+ nb->wp += ETHERHDRSIZE+IPHDR;
+
+ if((fragoff + seglen) >= dlen) {
+ seglen = dlen - fragoff;
+ hnputs(feh->frag, (frag+fragoff)>>3 | mf);
+ }
+ else
+ hnputs(feh->frag, (frag+fragoff>>3) | IP_MF);
+
+ hnputs(feh->length, seglen + IPHDR);
+ hnputs(feh->id, lid);
+
+ /* Copy up the data area */
+ chunk = seglen;
+ while(chunk) {
+ blklen = chunk;
+ if(BLEN(xp) < chunk)
+ blklen = BLEN(xp);
+ memmove(nb->wp, xp->rp, blklen);
+ nb->wp += blklen;
+ xp->rp += blklen;
+ chunk -= blklen;
+ if(xp->rp == xp->wp)
+ xp = xp->next;
+ }
+
+ feh->cksum[0] = 0;
+ feh->cksum[1] = 0;
+ hnputs(feh->cksum, ipcsum(&feh->vihl));
+
+ /* don't generate small packets */
+ if(BLEN(nb) < ETHERMINTU)
+ nb->wp = nb->rp + ETHERMINTU;
+ devtab[port->data[1]->type]->bwrite(port->data[1], nb, 0);
+ }
+ poperror();
+ freeblist(bp);
+}
+
+// hold b lock
+static void
+portfree(Port *port)
+{
+ port->ref--;
+ if(port->ref < 0)
+ panic("portfree: bad ref");
+ if(port->ref > 0)
+ return;
+
+ if(port->data[0])
+ cclose(port->data[0]);
+ if(port->data[1])
+ cclose(port->data[1]);
+ memset(port, 0, sizeof(Port));
+ free(port);
+}
+
+Dev bridgedevtab = {
+ 'B',
+ "bridge",
+
+ devreset,
+ bridgeinit,
+ devshutdown,
+ bridgeattach,
+ bridgewalk,
+ bridgestat,
+ bridgeopen,
+ devcreate,
+ bridgeclose,
+ bridgeread,
+ devbread,
+ bridgewrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/port/devcap.c b/sys/src/9/port/devcap.c
new file mode 100755
index 000000000..90cde2453
--- /dev/null
+++ b/sys/src/9/port/devcap.c
@@ -0,0 +1,286 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include <libsec.h>
+
+enum
+{
+ Hashlen= SHA1dlen,
+ Maxhash= 256,
+};
+
+/*
+ * if a process knows cap->cap, it can change user
+ * to capabilty->user.
+ */
+typedef struct Caphash Caphash;
+struct Caphash
+{
+ Caphash *next;
+ char hash[Hashlen];
+ ulong ticks;
+};
+
+struct
+{
+ QLock;
+ Caphash *first;
+ int nhash;
+} capalloc;
+
+enum
+{
+ Qdir,
+ Qhash,
+ Quse,
+};
+
+/* caphash must be last */
+Dirtab capdir[] =
+{
+ ".", {Qdir,0,QTDIR}, 0, DMDIR|0500,
+ "capuse", {Quse}, 0, 0222,
+ "caphash", {Qhash}, 0, 0200,
+};
+int ncapdir = nelem(capdir);
+
+static Chan*
+capattach(char *spec)
+{
+ return devattach(L'¤', spec);
+}
+
+static Walkqid*
+capwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, capdir, ncapdir, devgen);
+}
+
+static void
+capremove(Chan *c)
+{
+ if(iseve() && c->qid.path == Qhash)
+ ncapdir = nelem(capdir)-1;
+ else
+ error(Eperm);
+}
+
+
+static int
+capstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, capdir, ncapdir, devgen);
+}
+
+/*
+ * if the stream doesn't exist, create it
+ */
+static Chan*
+capopen(Chan *c, int omode)
+{
+ if(c->qid.type & QTDIR){
+ if(omode != OREAD)
+ error(Ebadarg);
+ c->mode = omode;
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+ }
+
+ switch((ulong)c->qid.path){
+ case Qhash:
+ if(!iseve())
+ error(Eperm);
+ break;
+ }
+
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+/*
+static char*
+hashstr(uchar *hash)
+{
+ static char buf[2*Hashlen+1];
+ int i;
+
+ for(i = 0; i < Hashlen; i++)
+ sprint(buf+2*i, "%2.2ux", hash[i]);
+ buf[2*Hashlen] = 0;
+ return buf;
+}
+ */
+
+static Caphash*
+remcap(uchar *hash)
+{
+ Caphash *t, **l;
+
+ qlock(&capalloc);
+
+ /* find the matching capability */
+ for(l = &capalloc.first; *l != nil;){
+ t = *l;
+ if(memcmp(hash, t->hash, Hashlen) == 0)
+ break;
+ l = &t->next;
+ }
+ t = *l;
+ if(t != nil){
+ capalloc.nhash--;
+ *l = t->next;
+ }
+ qunlock(&capalloc);
+
+ return t;
+}
+
+/* add a capability, throwing out any old ones */
+static void
+addcap(uchar *hash)
+{
+ Caphash *p, *t, **l;
+
+ p = smalloc(sizeof *p);
+ memmove(p->hash, hash, Hashlen);
+ p->next = nil;
+ p->ticks = m->ticks;
+
+ qlock(&capalloc);
+
+ /* trim extras */
+ while(capalloc.nhash >= Maxhash){
+ t = capalloc.first;
+ if(t == nil)
+ panic("addcap");
+ capalloc.first = t->next;
+ free(t);
+ capalloc.nhash--;
+ }
+
+ /* add new one */
+ for(l = &capalloc.first; *l != nil; l = &(*l)->next)
+ ;
+ *l = p;
+ capalloc.nhash++;
+
+ qunlock(&capalloc);
+}
+
+static void
+capclose(Chan*)
+{
+}
+
+static long
+capread(Chan *c, void *va, long n, vlong)
+{
+ switch((ulong)c->qid.path){
+ case Qdir:
+ return devdirread(c, va, n, capdir, ncapdir, devgen);
+
+ default:
+ error(Eperm);
+ break;
+ }
+ return n;
+}
+
+static long
+capwrite(Chan *c, void *va, long n, vlong)
+{
+ Caphash *p;
+ char *cp;
+ uchar hash[Hashlen];
+ char *key, *from, *to;
+ char err[256];
+
+ switch((ulong)c->qid.path){
+ case Qhash:
+ if(!iseve())
+ error(Eperm);
+ if(n < Hashlen)
+ error(Eshort);
+ memmove(hash, va, Hashlen);
+ addcap(hash);
+ break;
+
+ case Quse:
+ /* copy key to avoid a fault in hmac_xx */
+ cp = nil;
+ if(waserror()){
+ free(cp);
+ nexterror();
+ }
+ cp = smalloc(n+1);
+ memmove(cp, va, n);
+ cp[n] = 0;
+
+ from = cp;
+ key = strrchr(cp, '@');
+ if(key == nil)
+ error(Eshort);
+ *key++ = 0;
+
+ hmac_sha1((uchar*)from, strlen(from), (uchar*)key, strlen(key), hash, nil);
+
+ p = remcap(hash);
+ if(p == nil){
+ snprint(err, sizeof err, "invalid capability %s@%s", from, key);
+ error(err);
+ }
+
+ /* if a from user is supplied, make sure it matches */
+ to = strchr(from, '@');
+ if(to == nil){
+ to = from;
+ } else {
+ *to++ = 0;
+ if(strcmp(from, up->user) != 0)
+ error("capability must match user");
+ }
+
+ /* set user id */
+ kstrdup(&up->user, to);
+ up->basepri = PriNormal;
+
+ free(p);
+ free(cp);
+ poperror();
+ break;
+
+ default:
+ error(Eperm);
+ break;
+ }
+
+ return n;
+}
+
+Dev capdevtab = {
+ L'¤',
+ "cap",
+
+ devreset,
+ devinit,
+ devshutdown,
+ capattach,
+ capwalk,
+ capstat,
+ capopen,
+ devcreate,
+ capclose,
+ capread,
+ devbread,
+ capwrite,
+ devbwrite,
+ capremove,
+ devwstat
+};
diff --git a/sys/src/9/port/devcons.c b/sys/src/9/port/devcons.c
new file mode 100755
index 000000000..6666f01b5
--- /dev/null
+++ b/sys/src/9/port/devcons.c
@@ -0,0 +1,1354 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "pool.h"
+
+#include <authsrv.h>
+
+void (*consdebug)(void) = nil;
+void (*screenputs)(char*, int) = nil;
+
+Queue* kbdq; /* unprocessed console input */
+Queue* lineq; /* processed console input */
+Queue* serialoq; /* serial console output */
+Queue* kprintoq; /* console output, for /dev/kprint */
+ulong kprintinuse; /* test and set whether /dev/kprint is open */
+int iprintscreenputs = 1;
+
+int panicking;
+
+static struct
+{
+ QLock;
+
+ int raw; /* true if we shouldn't process input */
+ Ref ctl; /* number of opens to the control file */
+ int x; /* index into line */
+ char line[1024]; /* current input line */
+
+ int count;
+ int ctlpoff;
+
+ /* a place to save up characters at interrupt time before dumping them in the queue */
+ Lock lockputc;
+ char istage[1024];
+ char *iw;
+ char *ir;
+ char *ie;
+} kbd = {
+ .iw = kbd.istage,
+ .ir = kbd.istage,
+ .ie = kbd.istage + sizeof(kbd.istage),
+};
+
+char *sysname;
+vlong fasthz;
+
+static void seedrand(void);
+static int readtime(ulong, char*, int);
+static int readbintime(char*, int);
+static int writetime(char*, int);
+static int writebintime(char*, int);
+
+enum
+{
+ CMhalt,
+ CMreboot,
+ CMpanic,
+};
+
+Cmdtab rebootmsg[] =
+{
+ CMhalt, "halt", 1,
+ CMreboot, "reboot", 0,
+ CMpanic, "panic", 0,
+};
+
+void
+printinit(void)
+{
+ lineq = qopen(2*1024, 0, nil, nil);
+ if(lineq == nil)
+ panic("printinit");
+ qnoblock(lineq, 1);
+}
+
+int
+consactive(void)
+{
+ if(serialoq)
+ return qlen(serialoq) > 0;
+ return 0;
+}
+
+void
+prflush(void)
+{
+ ulong now;
+
+ now = m->ticks;
+ while(consactive())
+ if(m->ticks - now >= HZ)
+ break;
+}
+
+/*
+ * Log console output so it can be retrieved via /dev/kmesg.
+ * This is good for catching boot-time messages after the fact.
+ */
+struct {
+ Lock lk;
+// char buf[16384]; /* normal */
+ char buf[256*1024]; /* for acpi debugging */
+ uint n;
+} kmesg;
+
+static void
+kmesgputs(char *str, int n)
+{
+ uint nn, d;
+
+ ilock(&kmesg.lk);
+ /* take the tail of huge writes */
+ if(n > sizeof kmesg.buf){
+ d = n - sizeof kmesg.buf;
+ str += d;
+ n -= d;
+ }
+
+ /* slide the buffer down to make room */
+ nn = kmesg.n;
+ if(nn + n >= sizeof kmesg.buf){
+ d = nn + n - sizeof kmesg.buf;
+ if(d)
+ memmove(kmesg.buf, kmesg.buf+d, sizeof kmesg.buf-d);
+ nn -= d;
+ }
+
+ /* copy the data in */
+ memmove(kmesg.buf+nn, str, n);
+ nn += n;
+ kmesg.n = nn;
+ iunlock(&kmesg.lk);
+}
+
+/*
+ * Print a string on the console. Convert \n to \r\n for serial
+ * line consoles. Locking of the queues is left up to the screen
+ * or uart code. Multi-line messages to serial consoles may get
+ * interspersed with other messages.
+ */
+static void
+putstrn0(char *str, int n, int usewrite)
+{
+ int m;
+ char *t;
+
+ if(!islo())
+ usewrite = 0;
+
+ /*
+ * how many different output devices do we need?
+ */
+ kmesgputs(str, n);
+
+ /*
+ * if someone is reading /dev/kprint,
+ * put the message there.
+ * if not and there's an attached bit mapped display,
+ * put the message there.
+ *
+ * if there's a serial line being used as a console,
+ * put the message there.
+ */
+ if(kprintoq != nil && !qisclosed(kprintoq)){
+ if(usewrite)
+ qwrite(kprintoq, str, n);
+ else
+ qiwrite(kprintoq, str, n);
+ }else if(screenputs != nil)
+ screenputs(str, n);
+
+ if(serialoq == nil){
+ uartputs(str, n);
+ return;
+ }
+
+ while(n > 0) {
+ t = memchr(str, '\n', n);
+ if(t && !kbd.raw) {
+ m = t-str;
+ if(usewrite){
+ qwrite(serialoq, str, m);
+ qwrite(serialoq, "\r\n", 2);
+ } else {
+ qiwrite(serialoq, str, m);
+ qiwrite(serialoq, "\r\n", 2);
+ }
+ n -= m+1;
+ str = t+1;
+ } else {
+ if(usewrite)
+ qwrite(serialoq, str, n);
+ else
+ qiwrite(serialoq, str, n);
+ break;
+ }
+ }
+}
+
+void
+putstrn(char *str, int n)
+{
+ putstrn0(str, n, 0);
+}
+
+int noprint;
+
+int
+print(char *fmt, ...)
+{
+ int n;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ if(noprint)
+ return -1;
+
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+ putstrn(buf, n);
+
+ return n;
+}
+
+/*
+ * Want to interlock iprints to avoid interlaced output on
+ * multiprocessor, but don't want to deadlock if one processor
+ * dies during print and another has something important to say.
+ * Make a good faith effort.
+ */
+static Lock iprintlock;
+static int
+iprintcanlock(Lock *l)
+{
+ int i;
+
+ for(i=0; i<1000; i++){
+ if(canlock(l))
+ return 1;
+ if(l->m == MACHP(m->machno))
+ return 0;
+ microdelay(100);
+ }
+ return 0;
+}
+
+int
+iprint(char *fmt, ...)
+{
+ int n, s, locked;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ s = splhi();
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+ locked = iprintcanlock(&iprintlock);
+ if(screenputs != nil && iprintscreenputs)
+ screenputs(buf, n);
+ uartputs(buf, n);
+ if(locked)
+ unlock(&iprintlock);
+ splx(s);
+
+ return n;
+}
+
+void
+panic(char *fmt, ...)
+{
+ int n, s;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ kprintoq = nil; /* don't try to write to /dev/kprint */
+
+ if(panicking)
+ for(;;);
+ panicking = 1;
+
+ s = splhi();
+ strcpy(buf, "panic: ");
+ va_start(arg, fmt);
+ n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+ iprint("%s\n", buf);
+ if(consdebug)
+ (*consdebug)();
+ splx(s);
+ prflush();
+ buf[n] = '\n';
+ putstrn(buf, n+1);
+ dumpstack();
+
+ exit(1);
+}
+
+/* libmp at least contains a few calls to sysfatal; simulate with panic */
+void
+sysfatal(char *fmt, ...)
+{
+ char err[256];
+ va_list arg;
+
+ va_start(arg, fmt);
+ vseprint(err, err + sizeof err, fmt, arg);
+ va_end(arg);
+ panic("sysfatal: %s", err);
+}
+
+void
+_assert(char *fmt)
+{
+ panic("assert failed at %#p: %s", getcallerpc(&fmt), fmt);
+}
+
+int
+pprint(char *fmt, ...)
+{
+ int n;
+ Chan *c;
+ va_list arg;
+ char buf[2*PRINTSIZE];
+
+ if(up == nil || up->fgrp == nil)
+ return 0;
+
+ c = up->fgrp->fd[2];
+ if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR))
+ return 0;
+ n = snprint(buf, sizeof buf, "%s %lud: ", up->text, up->pid);
+ va_start(arg, fmt);
+ n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+
+ if(waserror())
+ return 0;
+ devtab[c->type]->write(c, buf, n, c->offset);
+ poperror();
+
+ lock(c);
+ c->offset += n;
+ unlock(c);
+
+ return n;
+}
+
+static void
+echoscreen(char *buf, int n)
+{
+ char *e, *p;
+ char ebuf[128];
+ int x;
+
+ p = ebuf;
+ e = ebuf + sizeof(ebuf) - 4;
+ while(n-- > 0){
+ if(p >= e){
+ screenputs(ebuf, p - ebuf);
+ p = ebuf;
+ }
+ x = *buf++;
+ if(x == 0x15){
+ *p++ = '^';
+ *p++ = 'U';
+ *p++ = '\n';
+ } else
+ *p++ = x;
+ }
+ if(p != ebuf)
+ screenputs(ebuf, p - ebuf);
+}
+
+static void
+echoserialoq(char *buf, int n)
+{
+ char *e, *p;
+ char ebuf[128];
+ int x;
+
+ p = ebuf;
+ e = ebuf + sizeof(ebuf) - 4;
+ while(n-- > 0){
+ if(p >= e){
+ qiwrite(serialoq, ebuf, p - ebuf);
+ p = ebuf;
+ }
+ x = *buf++;
+ if(x == '\n'){
+ *p++ = '\r';
+ *p++ = '\n';
+ } else if(x == 0x15){
+ *p++ = '^';
+ *p++ = 'U';
+ *p++ = '\n';
+ } else
+ *p++ = x;
+ }
+ if(p != ebuf)
+ qiwrite(serialoq, ebuf, p - ebuf);
+}
+
+static void
+echo(char *buf, int n)
+{
+ static int ctrlt, pid;
+ int x;
+ char *e, *p;
+
+ if(n == 0)
+ return;
+
+ e = buf+n;
+ for(p = buf; p < e; p++){
+ switch(*p){
+ case 0x10: /* ^P */
+ if(cpuserver && !kbd.ctlpoff){
+ active.exiting = 1;
+ return;
+ }
+ break;
+ case 0x14: /* ^T */
+ ctrlt++;
+ if(ctrlt > 2)
+ ctrlt = 2;
+ continue;
+ }
+
+ if(ctrlt != 2)
+ continue;
+
+ /* ^T escapes */
+ ctrlt = 0;
+ switch(*p){
+ case 'S':
+ x = splhi();
+ dumpstack();
+ procdump();
+ splx(x);
+ return;
+ case 's':
+ dumpstack();
+ return;
+ case 'x':
+ xsummary();
+ ixsummary();
+ mallocsummary();
+ // memorysummary();
+ pagersummary();
+ return;
+ case 'd':
+ if(consdebug == nil)
+ consdebug = rdb;
+ else
+ consdebug = nil;
+ print("consdebug now %#p\n", consdebug);
+ return;
+ case 'D':
+ if(consdebug == nil)
+ consdebug = rdb;
+ consdebug();
+ return;
+ case 'p':
+ x = spllo();
+ procdump();
+ splx(x);
+ return;
+ case 'q':
+ scheddump();
+ return;
+ case 'k':
+ killbig("^t ^t k");
+ return;
+ case 'r':
+ exit(0);
+ return;
+ }
+ }
+
+ qproduce(kbdq, buf, n);
+ if(kbd.raw)
+ return;
+ kmesgputs(buf, n);
+ if(screenputs != nil)
+ echoscreen(buf, n);
+ if(serialoq)
+ echoserialoq(buf, n);
+}
+
+/*
+ * Called by a uart interrupt for console input.
+ *
+ * turn '\r' into '\n' before putting it into the queue.
+ */
+int
+kbdcr2nl(Queue*, int ch)
+{
+ char *next;
+
+ ilock(&kbd.lockputc); /* just a mutex */
+ if(ch == '\r' && !kbd.raw)
+ ch = '\n';
+ next = kbd.iw+1;
+ if(next >= kbd.ie)
+ next = kbd.istage;
+ if(next != kbd.ir){
+ *kbd.iw = ch;
+ kbd.iw = next;
+ }
+ iunlock(&kbd.lockputc);
+ return 0;
+}
+
+/*
+ * Put character, possibly a rune, into read queue at interrupt time.
+ * Called at interrupt time to process a character.
+ */
+int
+kbdputc(Queue*, int ch)
+{
+ int i, n;
+ char buf[3];
+ Rune r;
+ char *next;
+
+ if(kbd.ir == nil)
+ return 0; /* in case we're not inited yet */
+
+ ilock(&kbd.lockputc); /* just a mutex */
+ r = ch;
+ n = runetochar(buf, &r);
+ for(i = 0; i < n; i++){
+ next = kbd.iw+1;
+ if(next >= kbd.ie)
+ next = kbd.istage;
+ if(next == kbd.ir)
+ break;
+ *kbd.iw = buf[i];
+ kbd.iw = next;
+ }
+ iunlock(&kbd.lockputc);
+ return 0;
+}
+
+/*
+ * we save up input characters till clock time to reduce
+ * per character interrupt overhead.
+ */
+static void
+kbdputcclock(void)
+{
+ char *iw;
+
+ /* this amortizes cost of qproduce */
+ if(kbd.iw != kbd.ir){
+ iw = kbd.iw;
+ if(iw < kbd.ir){
+ echo(kbd.ir, kbd.ie-kbd.ir);
+ kbd.ir = kbd.istage;
+ }
+ if(kbd.ir != iw){
+ echo(kbd.ir, iw-kbd.ir);
+ kbd.ir = iw;
+ }
+ }
+}
+
+enum{
+ Qdir,
+ Qbintime,
+ Qcons,
+ Qconsctl,
+ Qcputime,
+ Qdrivers,
+ Qkmesg,
+ Qkprint,
+ Qhostdomain,
+ Qhostowner,
+ Qnull,
+ Qosversion,
+ Qpgrpid,
+ Qpid,
+ Qppid,
+ Qrandom,
+ Qreboot,
+ Qswap,
+ Qsysname,
+ Qsysstat,
+ Qtime,
+ Quser,
+ Qzero,
+ Qconfig,
+};
+
+enum
+{
+ VLNUMSIZE= 22,
+};
+
+static Dirtab consdir[]={
+ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
+ "bintime", {Qbintime}, 24, 0664,
+ "cons", {Qcons}, 0, 0660,
+ "consctl", {Qconsctl}, 0, 0220,
+ "cputime", {Qcputime}, 6*NUMSIZE, 0444,
+ "drivers", {Qdrivers}, 0, 0444,
+ "hostdomain", {Qhostdomain}, DOMLEN, 0664,
+ "hostowner", {Qhostowner}, 0, 0664,
+ "kmesg", {Qkmesg}, 0, 0440,
+ "kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL|0440,
+ "null", {Qnull}, 0, 0666,
+ "osversion", {Qosversion}, 0, 0444,
+ "pgrpid", {Qpgrpid}, NUMSIZE, 0444,
+ "pid", {Qpid}, NUMSIZE, 0444,
+ "ppid", {Qppid}, NUMSIZE, 0444,
+ "random", {Qrandom}, 0, 0444,
+ "reboot", {Qreboot}, 0, 0664,
+ "swap", {Qswap}, 0, 0664,
+ "sysname", {Qsysname}, 0, 0664,
+ "sysstat", {Qsysstat}, 0, 0666,
+ "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664,
+ "user", {Quser}, 0, 0666,
+ "zero", {Qzero}, 0, 0444,
+ "config", {Qconfig}, 0, 0444,
+};
+
+int
+readnum(ulong off, char *buf, ulong n, ulong val, int size)
+{
+ char tmp[64];
+
+ snprint(tmp, sizeof(tmp), "%*lud", size-1, val);
+ tmp[size-1] = ' ';
+ if(off >= size)
+ return 0;
+ if(off+n > size)
+ n = size-off;
+ memmove(buf, tmp+off, n);
+ return n;
+}
+
+int
+readstr(ulong off, char *buf, ulong n, char *str)
+{
+ int size;
+
+ size = strlen(str);
+ if(off >= size)
+ return 0;
+ if(off+n > size)
+ n = size-off;
+ memmove(buf, str+off, n);
+ return n;
+}
+
+static void
+consinit(void)
+{
+ todinit();
+ randominit();
+ /*
+ * at 115200 baud, the 1024 char buffer takes 56 ms to process,
+ * processing it every 22 ms should be fine
+ */
+ addclock0link(kbdputcclock, 22);
+}
+
+static Chan*
+consattach(char *spec)
+{
+ return devattach('c', spec);
+}
+
+static Walkqid*
+conswalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);
+}
+
+static int
+consstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, consdir, nelem(consdir), devgen);
+}
+
+static Chan*
+consopen(Chan *c, int omode)
+{
+ c->aux = nil;
+ c = devopen(c, omode, consdir, nelem(consdir), devgen);
+ switch((ulong)c->qid.path){
+ case Qconsctl:
+ incref(&kbd.ctl);
+ break;
+
+ case Qkprint:
+ if(tas(&kprintinuse) != 0){
+ c->flag &= ~COPEN;
+ error(Einuse);
+ }
+ if(kprintoq == nil){
+ kprintoq = qopen(8*1024, Qcoalesce, 0, 0);
+ if(kprintoq == nil){
+ c->flag &= ~COPEN;
+ error(Enomem);
+ }
+ qnoblock(kprintoq, 1);
+ }else
+ qreopen(kprintoq);
+ c->iounit = qiomaxatomic;
+ break;
+ }
+ return c;
+}
+
+static void
+consclose(Chan *c)
+{
+ switch((ulong)c->qid.path){
+ /* last close of control file turns off raw */
+ case Qconsctl:
+ if(c->flag&COPEN){
+ if(decref(&kbd.ctl) == 0)
+ kbd.raw = 0;
+ }
+ break;
+
+ /* close of kprint allows other opens */
+ case Qkprint:
+ if(c->flag & COPEN){
+ kprintinuse = 0;
+ qhangup(kprintoq, nil);
+ }
+ break;
+ }
+}
+
+static long
+consread(Chan *c, void *buf, long n, vlong off)
+{
+ ulong l;
+ Mach *mp;
+ char *b, *bp, ch;
+ char tmp[256]; /* must be >= 18*NUMSIZE (Qswap) */
+ int i, k, id, send;
+ vlong offset = off;
+ extern char configfile[];
+
+ if(n <= 0)
+ return n;
+
+ switch((ulong)c->qid.path){
+ case Qdir:
+ return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
+
+ case Qcons:
+ qlock(&kbd);
+ if(waserror()) {
+ qunlock(&kbd);
+ nexterror();
+ }
+ while(!qcanread(lineq)){
+ if(qread(kbdq, &ch, 1) == 0)
+ continue;
+ send = 0;
+ if(ch == 0){
+ /* flush output on rawoff -> rawon */
+ if(kbd.x > 0)
+ send = !qcanread(kbdq);
+ }else if(kbd.raw){
+ kbd.line[kbd.x++] = ch;
+ send = !qcanread(kbdq);
+ }else{
+ switch(ch){
+ case '\b':
+ if(kbd.x > 0)
+ kbd.x--;
+ break;
+ case 0x15: /* ^U */
+ kbd.x = 0;
+ break;
+ case '\n':
+ case 0x04: /* ^D */
+ send = 1;
+ default:
+ if(ch != 0x04)
+ kbd.line[kbd.x++] = ch;
+ break;
+ }
+ }
+ if(send || kbd.x == sizeof kbd.line){
+ qwrite(lineq, kbd.line, kbd.x);
+ kbd.x = 0;
+ }
+ }
+ n = qread(lineq, buf, n);
+ qunlock(&kbd);
+ poperror();
+ return n;
+
+ case Qcputime:
+ k = offset;
+ if(k >= 6*NUMSIZE)
+ return 0;
+ if(k+n > 6*NUMSIZE)
+ n = 6*NUMSIZE - k;
+ /* easiest to format in a separate buffer and copy out */
+ for(i=0; i<6 && NUMSIZE*i<k+n; i++){
+ l = up->time[i];
+ if(i == TReal)
+ l = MACHP(0)->ticks - l;
+ l = TK2MS(l);
+ readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
+ }
+ memmove(buf, tmp+k, n);
+ return n;
+
+ case Qkmesg:
+ /*
+ * This is unlocked to avoid tying up a process
+ * that's writing to the buffer. kmesg.n never
+ * gets smaller, so worst case the reader will
+ * see a slurred buffer.
+ */
+ if(off >= kmesg.n)
+ n = 0;
+ else{
+ if(off+n > kmesg.n)
+ n = kmesg.n - off;
+ memmove(buf, kmesg.buf+off, n);
+ }
+ return n;
+
+ case Qkprint:
+ return qread(kprintoq, buf, n);
+
+ case Qpgrpid:
+ return readnum((ulong)offset, buf, n, up->pgrp->pgrpid, NUMSIZE);
+
+ case Qpid:
+ return readnum((ulong)offset, buf, n, up->pid, NUMSIZE);
+
+ case Qppid:
+ return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE);
+
+ case Qtime:
+ return readtime((ulong)offset, buf, n);
+
+ case Qbintime:
+ return readbintime(buf, n);
+
+ case Qhostowner:
+ return readstr((ulong)offset, buf, n, eve);
+
+ case Qhostdomain:
+ return readstr((ulong)offset, buf, n, hostdomain);
+
+ case Quser:
+ return readstr((ulong)offset, buf, n, up->user);
+
+ case Qnull:
+ return 0;
+
+ case Qconfig:
+ return readstr((ulong)offset, buf, n, configfile);
+
+ case Qsysstat:
+ b = smalloc(conf.nmach*(NUMSIZE*11+1) + 1); /* +1 for NUL */
+ bp = b;
+ for(id = 0; id < 32; id++) {
+ if(active.machs & (1<<id)) {
+ mp = MACHP(id);
+ readnum(0, bp, NUMSIZE, id, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE, mp->load, NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE,
+ (mp->perf.avg_inidle*100)/mp->perf.period,
+ NUMSIZE);
+ bp += NUMSIZE;
+ readnum(0, bp, NUMSIZE,
+ (mp->perf.avg_inintr*100)/mp->perf.period,
+ NUMSIZE);
+ bp += NUMSIZE;
+ *bp++ = '\n';
+ }
+ }
+ if(waserror()){
+ free(b);
+ nexterror();
+ }
+ n = readstr((ulong)offset, buf, n, b);
+ free(b);
+ poperror();
+ return n;
+
+ case Qswap:
+ snprint(tmp, sizeof tmp,
+ "%lud memory\n"
+ "%d pagesize\n"
+ "%lud kernel\n"
+ "%lud/%lud user\n"
+ "%lud/%lud swap\n"
+ "%lud/%lud kernel malloc\n"
+ "%lud/%lud kernel draw\n",
+ conf.npage*BY2PG,
+ BY2PG,
+ conf.npage-conf.upages,
+ palloc.user-palloc.freecount, palloc.user,
+ conf.nswap-swapalloc.free, conf.nswap,
+ mainmem->cursize, mainmem->maxsize,
+ imagmem->cursize, imagmem->maxsize);
+
+ return readstr((ulong)offset, buf, n, tmp);
+
+ case Qsysname:
+ if(sysname == nil)
+ return 0;
+ return readstr((ulong)offset, buf, n, sysname);
+
+ case Qrandom:
+ return randomread(buf, n);
+
+ case Qdrivers:
+ b = malloc(READSTR);
+ if(b == nil)
+ error(Enomem);
+ k = 0;
+ for(i = 0; devtab[i] != nil; i++)
+ k += snprint(b+k, READSTR-k, "#%C %s\n",
+ devtab[i]->dc, devtab[i]->name);
+ if(waserror()){
+ free(b);
+ nexterror();
+ }
+ n = readstr((ulong)offset, buf, n, b);
+ free(b);
+ poperror();
+ return n;
+
+ case Qzero:
+ memset(buf, 0, n);
+ return n;
+
+ case Qosversion:
+ snprint(tmp, sizeof tmp, "2000");
+ n = readstr((ulong)offset, buf, n, tmp);
+ return n;
+
+ default:
+ print("consread %#llux\n", c->qid.path);
+ error(Egreg);
+ }
+ return -1; /* never reached */
+}
+
+static long
+conswrite(Chan *c, void *va, long n, vlong off)
+{
+ char buf[256], ch;
+ long l, bp;
+ char *a;
+ Mach *mp;
+ int id, fd;
+ Chan *swc;
+ ulong offset;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+
+ a = va;
+ offset = off;
+
+ switch((ulong)c->qid.path){
+ case Qcons:
+ /*
+ * Can't page fault in putstrn, so copy the data locally.
+ */
+ l = n;
+ while(l > 0){
+ bp = l;
+ if(bp > sizeof buf)
+ bp = sizeof buf;
+ memmove(buf, a, bp);
+ putstrn0(buf, bp, 1);
+ a += bp;
+ l -= bp;
+ }
+ break;
+
+ case Qconsctl:
+ if(n >= sizeof(buf))
+ n = sizeof(buf)-1;
+ strncpy(buf, a, n);
+ buf[n] = 0;
+ for(a = buf; a;){
+ if(strncmp(a, "rawon", 5) == 0){
+ kbd.raw = 1;
+ /* clumsy hack - wake up reader */
+ ch = 0;
+ qwrite(kbdq, &ch, 1);
+ } else if(strncmp(a, "rawoff", 6) == 0){
+ kbd.raw = 0;
+ } else if(strncmp(a, "ctlpon", 6) == 0){
+ kbd.ctlpoff = 0;
+ } else if(strncmp(a, "ctlpoff", 7) == 0){
+ kbd.ctlpoff = 1;
+ }
+ if(a = strchr(a, ' '))
+ a++;
+ }
+ break;
+
+ case Qtime:
+ if(!iseve())
+ error(Eperm);
+ return writetime(a, n);
+
+ case Qbintime:
+ if(!iseve())
+ error(Eperm);
+ return writebintime(a, n);
+
+ case Qhostowner:
+ return hostownerwrite(a, n);
+
+ case Qhostdomain:
+ return hostdomainwrite(a, n);
+
+ case Quser:
+ return userwrite(a, n);
+
+ case Qnull:
+ break;
+
+ case Qconfig:
+ error(Eperm);
+ break;
+
+ case Qreboot:
+ if(!iseve())
+ error(Eperm);
+ cb = parsecmd(a, n);
+
+ if(waserror()) {
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
+ switch(ct->index) {
+ case CMhalt:
+ reboot(nil, 0, 0);
+ break;
+ case CMreboot:
+ rebootcmd(cb->nf-1, cb->f+1);
+ break;
+ case CMpanic:
+ *(ulong*)0=0;
+ panic("/dev/reboot");
+ }
+ poperror();
+ free(cb);
+ break;
+
+ case Qsysstat:
+ for(id = 0; id < 32; id++) {
+ if(active.machs & (1<<id)) {
+ mp = MACHP(id);
+ mp->cs = 0;
+ mp->intr = 0;
+ mp->syscall = 0;
+ mp->pfault = 0;
+ mp->tlbfault = 0;
+ mp->tlbpurge = 0;
+ }
+ }
+ break;
+
+ case Qswap:
+ if(n >= sizeof buf)
+ error(Egreg);
+ memmove(buf, va, n); /* so we can NUL-terminate */
+ buf[n] = 0;
+ /* start a pager if not already started */
+ if(strncmp(buf, "start", 5) == 0){
+ kickpager();
+ break;
+ }
+ if(!iseve())
+ error(Eperm);
+ if(buf[0]<'0' || '9'<buf[0])
+ error(Ebadarg);
+ fd = strtoul(buf, 0, 0);
+ swc = fdtochan(fd, -1, 1, 1);
+ setswapchan(swc);
+ break;
+
+ case Qsysname:
+ if(offset != 0)
+ error(Ebadarg);
+ if(n <= 0 || n >= sizeof buf)
+ error(Ebadarg);
+ strncpy(buf, a, n);
+ buf[n] = 0;
+ if(buf[n-1] == '\n')
+ buf[n-1] = 0;
+ kstrdup(&sysname, buf);
+ break;
+
+ default:
+ print("conswrite: %#llux\n", c->qid.path);
+ error(Egreg);
+ }
+ return n;
+}
+
+Dev consdevtab = {
+ 'c',
+ "cons",
+
+ devreset,
+ consinit,
+ devshutdown,
+ consattach,
+ conswalk,
+ consstat,
+ consopen,
+ devcreate,
+ consclose,
+ consread,
+ devbread,
+ conswrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+static ulong randn;
+
+static void
+seedrand(void)
+{
+ if(!waserror()){
+ randomread((void*)&randn, sizeof(randn));
+ poperror();
+ }
+}
+
+int
+nrand(int n)
+{
+ if(randn == 0)
+ seedrand();
+ randn = randn*1103515245 + 12345 + MACHP(0)->ticks;
+ return (randn>>16) % n;
+}
+
+int
+rand(void)
+{
+ nrand(1);
+ return randn;
+}
+
+static uvlong uvorder = 0x0001020304050607ULL;
+
+static uchar*
+le2vlong(vlong *to, uchar *f)
+{
+ uchar *t, *o;
+ int i;
+
+ t = (uchar*)to;
+ o = (uchar*)&uvorder;
+ for(i = 0; i < sizeof(vlong); i++)
+ t[o[i]] = f[i];
+ return f+sizeof(vlong);
+}
+
+static uchar*
+vlong2le(uchar *t, vlong from)
+{
+ uchar *f, *o;
+ int i;
+
+ f = (uchar*)&from;
+ o = (uchar*)&uvorder;
+ for(i = 0; i < sizeof(vlong); i++)
+ t[i] = f[o[i]];
+ return t+sizeof(vlong);
+}
+
+static long order = 0x00010203;
+
+static uchar*
+le2long(long *to, uchar *f)
+{
+ uchar *t, *o;
+ int i;
+
+ t = (uchar*)to;
+ o = (uchar*)&order;
+ for(i = 0; i < sizeof(long); i++)
+ t[o[i]] = f[i];
+ return f+sizeof(long);
+}
+
+static uchar*
+long2le(uchar *t, long from)
+{
+ uchar *f, *o;
+ int i;
+
+ f = (uchar*)&from;
+ o = (uchar*)&order;
+ for(i = 0; i < sizeof(long); i++)
+ t[i] = f[o[i]];
+ return t+sizeof(long);
+}
+
+char *Ebadtimectl = "bad time control";
+
+/*
+ * like the old #c/time but with added info. Return
+ *
+ * secs nanosecs fastticks fasthz
+ */
+static int
+readtime(ulong off, char *buf, int n)
+{
+ vlong nsec, ticks;
+ long sec;
+ char str[7*NUMSIZE];
+
+ nsec = todget(&ticks);
+ if(fasthz == 0LL)
+ fastticks((uvlong*)&fasthz);
+ sec = nsec/1000000000ULL;
+ snprint(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
+ NUMSIZE-1, sec,
+ VLNUMSIZE-1, nsec,
+ VLNUMSIZE-1, ticks,
+ VLNUMSIZE-1, fasthz);
+ return readstr(off, buf, n, str);
+}
+
+/*
+ * set the time in seconds
+ */
+static int
+writetime(char *buf, int n)
+{
+ char b[13];
+ long i;
+ vlong now;
+
+ if(n >= sizeof(b))
+ error(Ebadtimectl);
+ strncpy(b, buf, n);
+ b[n] = 0;
+ i = strtol(b, 0, 0);
+ if(i <= 0)
+ error(Ebadtimectl);
+ now = i*1000000000LL;
+ todset(now, 0, 0);
+ return n;
+}
+
+/*
+ * read binary time info. all numbers are little endian.
+ * ticks and nsec are syncronized.
+ */
+static int
+readbintime(char *buf, int n)
+{
+ int i;
+ vlong nsec, ticks;
+ uchar *b = (uchar*)buf;
+
+ i = 0;
+ if(fasthz == 0LL)
+ fastticks((uvlong*)&fasthz);
+ nsec = todget(&ticks);
+ if(n >= 3*sizeof(uvlong)){
+ vlong2le(b+2*sizeof(uvlong), fasthz);
+ i += sizeof(uvlong);
+ }
+ if(n >= 2*sizeof(uvlong)){
+ vlong2le(b+sizeof(uvlong), ticks);
+ i += sizeof(uvlong);
+ }
+ if(n >= 8){
+ vlong2le(b, nsec);
+ i += sizeof(vlong);
+ }
+ return i;
+}
+
+/*
+ * set any of the following
+ * - time in nsec
+ * - nsec trim applied over some seconds
+ * - clock frequency
+ */
+static int
+writebintime(char *buf, int n)
+{
+ uchar *p;
+ vlong delta;
+ long period;
+
+ n--;
+ p = (uchar*)buf + 1;
+ switch(*buf){
+ case 'n':
+ if(n < sizeof(vlong))
+ error(Ebadtimectl);
+ le2vlong(&delta, p);
+ todset(delta, 0, 0);
+ break;
+ case 'd':
+ if(n < sizeof(vlong)+sizeof(long))
+ error(Ebadtimectl);
+ p = le2vlong(&delta, p);
+ le2long(&period, p);
+ todset(-1, delta, period);
+ break;
+ case 'f':
+ if(n < sizeof(uvlong))
+ error(Ebadtimectl);
+ le2vlong(&fasthz, p);
+ if(fasthz <= 0)
+ error(Ebadtimectl);
+ todsetfreq(fasthz);
+ break;
+ }
+ return n;
+}
diff --git a/sys/src/9/port/devdraw.c b/sys/src/9/port/devdraw.c
new file mode 100755
index 000000000..d11ab05a2
--- /dev/null
+++ b/sys/src/9/port/devdraw.c
@@ -0,0 +1,2203 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <memlayer.h>
+#include <cursor.h>
+#include "screen.h"
+
+enum
+{
+ Qtopdir = 0,
+ Qnew,
+ Qwinname,
+ Q3rd,
+ Q2nd,
+ Qcolormap,
+ Qctl,
+ Qdata,
+ Qrefresh,
+};
+
+/*
+ * Qid path is:
+ * 4 bits of file type (qids above)
+ * 24 bits of mux slot number +1; 0 means not attached to client
+ */
+#define QSHIFT 4 /* location in qid of client # */
+
+#define QID(q) ((((ulong)(q).path)&0x0000000F)>>0)
+#define CLIENTPATH(q) ((((ulong)q)&0x7FFFFFF0)>>QSHIFT)
+#define CLIENT(q) CLIENTPATH((q).path)
+
+#define NHASH (1<<5)
+#define HASHMASK (NHASH-1)
+#define IOUNIT (64*1024)
+
+typedef struct Client Client;
+typedef struct Draw Draw;
+typedef struct DImage DImage;
+typedef struct DScreen DScreen;
+typedef struct CScreen CScreen;
+typedef struct FChar FChar;
+typedef struct Refresh Refresh;
+typedef struct Refx Refx;
+typedef struct DName DName;
+
+ulong blanktime = 30; /* in minutes; a half hour */
+
+struct Draw
+{
+ int clientid;
+ int nclient;
+ Client** client;
+ int nname;
+ DName* name;
+ int vers;
+ int softscreen;
+ int blanked; /* screen turned off */
+ ulong blanktime; /* time of last operation */
+ ulong savemap[3*256];
+};
+
+struct Client
+{
+ Ref r;
+ DImage* dimage[NHASH];
+ CScreen* cscreen;
+ Refresh* refresh;
+ Rendez refrend;
+ uchar* readdata;
+ int nreaddata;
+ int busy;
+ int clientid;
+ int slot;
+ int refreshme;
+ int infoid;
+ int op;
+};
+
+struct Refresh
+{
+ DImage* dimage;
+ Rectangle r;
+ Refresh* next;
+};
+
+struct Refx
+{
+ Client* client;
+ DImage* dimage;
+};
+
+struct DName
+{
+ char *name;
+ Client *client;
+ DImage* dimage;
+ int vers;
+};
+
+struct FChar
+{
+ int minx; /* left edge of bits */
+ int maxx; /* right edge of bits */
+ uchar miny; /* first non-zero scan-line */
+ uchar maxy; /* last non-zero scan-line + 1 */
+ schar left; /* offset of baseline */
+ uchar width; /* width of baseline */
+};
+
+/*
+ * Reference counts in DImages:
+ * one per open by original client
+ * one per screen image or fill
+ * one per image derived from this one by name
+ */
+struct DImage
+{
+ int id;
+ int ref;
+ char *name;
+ int vers;
+ Memimage* image;
+ int ascent;
+ int nfchar;
+ FChar* fchar;
+ DScreen* dscreen; /* 0 if not a window */
+ DImage* fromname; /* image this one is derived from, by name */
+ DImage* next;
+};
+
+struct CScreen
+{
+ DScreen* dscreen;
+ CScreen* next;
+};
+
+struct DScreen
+{
+ int id;
+ int public;
+ int ref;
+ DImage *dimage;
+ DImage *dfill;
+ Memscreen* screen;
+ Client* owner;
+ DScreen* next;
+};
+
+static Draw sdraw;
+ QLock drawlock;
+
+static Memimage *screenimage;
+static DImage* screendimage;
+static char screenname[40];
+static int screennameid;
+
+static Rectangle flushrect;
+static int waste;
+static DScreen* dscreen;
+extern void flushmemscreen(Rectangle);
+ void drawmesg(Client*, void*, int);
+ void drawuninstall(Client*, int);
+ void drawfreedimage(DImage*);
+ Client* drawclientofpath(ulong);
+ DImage* allocdimage(Memimage*);
+
+static char Enodrawimage[] = "unknown id for draw image";
+static char Enodrawscreen[] = "unknown id for draw screen";
+static char Eshortdraw[] = "short draw message";
+static char Eshortread[] = "draw read too short";
+static char Eimageexists[] = "image id in use";
+static char Escreenexists[] = "screen id in use";
+static char Edrawmem[] = "image memory allocation failed";
+static char Ereadoutside[] = "readimage outside image";
+static char Ewriteoutside[] = "writeimage outside image";
+static char Enotfont[] = "image not a font";
+static char Eindex[] = "character index out of range";
+static char Enoclient[] = "no such draw client";
+static char Edepth[] = "image has bad depth";
+static char Enameused[] = "image name in use";
+static char Enoname[] = "no image with that name";
+static char Eoldname[] = "named image no longer valid";
+static char Enamed[] = "image already has name";
+static char Ewrongname[] = "wrong name for image";
+
+static void
+dlock(void)
+{
+ qlock(&drawlock);
+}
+
+static int
+candlock(void)
+{
+ return canqlock(&drawlock);
+}
+
+static void
+dunlock(void)
+{
+ qunlock(&drawlock);
+}
+
+static int
+drawgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
+{
+ int t;
+ Qid q;
+ ulong path;
+ Client *cl;
+
+ q.vers = 0;
+
+ if(s == DEVDOTDOT){
+ switch(QID(c->qid)){
+ case Qtopdir:
+ case Q2nd:
+ mkqid(&q, Qtopdir, 0, QTDIR);
+ devdir(c, q, "#i", 0, eve, 0500, dp);
+ break;
+ case Q3rd:
+ cl = drawclientofpath(c->qid.path);
+ if(cl == nil)
+ strcpy(up->genbuf, "??");
+ else
+ sprint(up->genbuf, "%d", cl->clientid);
+ mkqid(&q, Q2nd, 0, QTDIR);
+ devdir(c, q, up->genbuf, 0, eve, 0500, dp);
+ break;
+ default:
+ panic("drawwalk %llux", c->qid.path);
+ }
+ return 1;
+ }
+
+ /*
+ * Top level directory contains the name of the device.
+ */
+ t = QID(c->qid);
+ if(t == Qtopdir){
+ switch(s){
+ case 0:
+ mkqid(&q, Q2nd, 0, QTDIR);
+ devdir(c, q, "draw", 0, eve, 0555, dp);
+ break;
+ case 1:
+ mkqid(&q, Qwinname, 0, 0);
+ devdir(c, q, "winname", 0, eve, 0444, dp);
+ break;
+ default:
+ return -1;
+ }
+ return 1;
+ }
+
+ /*
+ * Second level contains "new" plus all the clients.
+ */
+ if(t == Q2nd || t == Qnew){
+ if(s == 0){
+ mkqid(&q, Qnew, 0, QTFILE);
+ devdir(c, q, "new", 0, eve, 0666, dp);
+ }
+ else if(s <= sdraw.nclient){
+ cl = sdraw.client[s-1];
+ if(cl == 0)
+ return 0;
+ sprint(up->genbuf, "%d", cl->clientid);
+ mkqid(&q, (s<<QSHIFT)|Q3rd, 0, QTDIR);
+ devdir(c, q, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+ }
+ else
+ return -1;
+ return 1;
+ }
+
+ /*
+ * Third level.
+ */
+ path = c->qid.path&~((1<<QSHIFT)-1); /* slot component */
+ q.vers = c->qid.vers;
+ q.type = QTFILE;
+ switch(s){
+ case 0:
+ q.path = path|Qcolormap;
+ devdir(c, q, "colormap", 0, eve, 0600, dp);
+ break;
+ case 1:
+ q.path = path|Qctl;
+ devdir(c, q, "ctl", 0, eve, 0600, dp);
+ break;
+ case 2:
+ q.path = path|Qdata;
+ devdir(c, q, "data", 0, eve, 0600, dp);
+ break;
+ case 3:
+ q.path = path|Qrefresh;
+ devdir(c, q, "refresh", 0, eve, 0400, dp);
+ break;
+ default:
+ return -1;
+ }
+ return 1;
+}
+
+static
+int
+drawrefactive(void *a)
+{
+ Client *c;
+
+ c = a;
+ return c->refreshme || c->refresh!=0;
+}
+
+static
+void
+drawrefreshscreen(DImage *l, Client *client)
+{
+ while(l != nil && l->dscreen == nil)
+ l = l->fromname;
+ if(l != nil && l->dscreen->owner != client)
+ l->dscreen->owner->refreshme = 1;
+}
+
+static
+void
+drawrefresh(Memimage*, Rectangle r, void *v)
+{
+ Refx *x;
+ DImage *d;
+ Client *c;
+ Refresh *ref;
+
+ if(v == 0)
+ return;
+ x = v;
+ c = x->client;
+ d = x->dimage;
+ for(ref=c->refresh; ref; ref=ref->next)
+ if(ref->dimage == d){
+ combinerect(&ref->r, r);
+ return;
+ }
+ ref = malloc(sizeof(Refresh));
+ if(ref){
+ ref->dimage = d;
+ ref->r = r;
+ ref->next = c->refresh;
+ c->refresh = ref;
+ }
+}
+
+static void
+addflush(Rectangle r)
+{
+ int abb, ar, anbb;
+ Rectangle nbb;
+
+ if(sdraw.softscreen==0 || !rectclip(&r, screenimage->r))
+ return;
+
+ if(flushrect.min.x >= flushrect.max.x){
+ flushrect = r;
+ waste = 0;
+ return;
+ }
+ nbb = flushrect;
+ combinerect(&nbb, r);
+ ar = Dx(r)*Dy(r);
+ abb = Dx(flushrect)*Dy(flushrect);
+ anbb = Dx(nbb)*Dy(nbb);
+ /*
+ * Area of new waste is area of new bb minus area of old bb,
+ * less the area of the new segment, which we assume is not waste.
+ * This could be negative, but that's OK.
+ */
+ waste += anbb-abb - ar;
+ if(waste < 0)
+ waste = 0;
+ /*
+ * absorb if:
+ * total area is small
+ * waste is less than half total area
+ * rectangles touch
+ */
+ if(anbb<=1024 || waste*2<anbb || rectXrect(flushrect, r)){
+ flushrect = nbb;
+ return;
+ }
+ /* emit current state */
+ if(flushrect.min.x < flushrect.max.x)
+ flushmemscreen(flushrect);
+ flushrect = r;
+ waste = 0;
+}
+
+static
+void
+dstflush(int dstid, Memimage *dst, Rectangle r)
+{
+ Memlayer *l;
+
+ if(dstid == 0){
+ combinerect(&flushrect, r);
+ return;
+ }
+ /* how can this happen? -rsc, dec 12 2002 */
+ if(dst == 0){
+ print("nil dstflush\n");
+ return;
+ }
+ l = dst->layer;
+ if(l == nil)
+ return;
+ do{
+ if(l->screen->image->data != screenimage->data)
+ return;
+ r = rectaddpt(r, l->delta);
+ l = l->screen->image->layer;
+ }while(l);
+ addflush(r);
+}
+
+void
+drawflush(void)
+{
+ if(flushrect.min.x < flushrect.max.x)
+ flushmemscreen(flushrect);
+ flushrect = Rect(10000, 10000, -10000, -10000);
+}
+
+static
+int
+drawcmp(char *a, char *b, int n)
+{
+ if(strlen(a) != n)
+ return 1;
+ return memcmp(a, b, n);
+}
+
+DName*
+drawlookupname(int n, char *str)
+{
+ DName *name, *ename;
+
+ name = sdraw.name;
+ ename = &name[sdraw.nname];
+ for(; name<ename; name++)
+ if(drawcmp(name->name, str, n) == 0)
+ return name;
+ return 0;
+}
+
+int
+drawgoodname(DImage *d)
+{
+ DName *n;
+
+ /* if window, validate the screen's own images */
+ if(d->dscreen)
+ if(drawgoodname(d->dscreen->dimage) == 0
+ || drawgoodname(d->dscreen->dfill) == 0)
+ return 0;
+ if(d->name == nil)
+ return 1;
+ n = drawlookupname(strlen(d->name), d->name);
+ if(n==nil || n->vers!=d->vers)
+ return 0;
+ return 1;
+}
+
+DImage*
+drawlookup(Client *client, int id, int checkname)
+{
+ DImage *d;
+
+ d = client->dimage[id&HASHMASK];
+ while(d){
+ if(d->id == id){
+ if(checkname && !drawgoodname(d))
+ error(Eoldname);
+ return d;
+ }
+ d = d->next;
+ }
+ return 0;
+}
+
+DScreen*
+drawlookupdscreen(int id)
+{
+ DScreen *s;
+
+ s = dscreen;
+ while(s){
+ if(s->id == id)
+ return s;
+ s = s->next;
+ }
+ return 0;
+}
+
+DScreen*
+drawlookupscreen(Client *client, int id, CScreen **cs)
+{
+ CScreen *s;
+
+ s = client->cscreen;
+ while(s){
+ if(s->dscreen->id == id){
+ *cs = s;
+ return s->dscreen;
+ }
+ s = s->next;
+ }
+ error(Enodrawscreen);
+ return 0;
+}
+
+DImage*
+allocdimage(Memimage *i)
+{
+ DImage *d;
+
+ d = malloc(sizeof(DImage));
+ if(d == 0)
+ return 0;
+ d->ref = 1;
+ d->name = 0;
+ d->vers = 0;
+ d->image = i;
+ d->nfchar = 0;
+ d->fchar = 0;
+ d->fromname = 0;
+ return d;
+}
+
+Memimage*
+drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
+{
+ DImage *d;
+
+ d = allocdimage(i);
+ if(d == 0)
+ return 0;
+ d->id = id;
+ d->dscreen = dscreen;
+ d->next = client->dimage[id&HASHMASK];
+ client->dimage[id&HASHMASK] = d;
+ return i;
+}
+
+Memscreen*
+drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *dfill, int public)
+{
+ Memscreen *s;
+ CScreen *c;
+
+ c = malloc(sizeof(CScreen));
+ if(dimage && dimage->image && dimage->image->chan == 0)
+ panic("bad image %p in drawinstallscreen", dimage->image);
+
+ if(c == 0)
+ return 0;
+ if(d == 0){
+ d = malloc(sizeof(DScreen));
+ if(d == 0){
+ free(c);
+ return 0;
+ }
+ s = malloc(sizeof(Memscreen));
+ if(s == 0){
+ free(c);
+ free(d);
+ return 0;
+ }
+ s->frontmost = 0;
+ s->rearmost = 0;
+ d->dimage = dimage;
+ if(dimage){
+ s->image = dimage->image;
+ dimage->ref++;
+ }
+ d->dfill = dfill;
+ if(dfill){
+ s->fill = dfill->image;
+ dfill->ref++;
+ }
+ d->ref = 0;
+ d->id = id;
+ d->screen = s;
+ d->public = public;
+ d->next = dscreen;
+ d->owner = client;
+ dscreen = d;
+ }
+ c->dscreen = d;
+ d->ref++;
+ c->next = client->cscreen;
+ client->cscreen = c;
+ return d->screen;
+}
+
+void
+drawdelname(DName *name)
+{
+ int i;
+
+ i = name-sdraw.name;
+ memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName));
+ sdraw.nname--;
+}
+
+void
+drawfreedscreen(DScreen *this)
+{
+ DScreen *ds, *next;
+
+ this->ref--;
+ if(this->ref < 0)
+ print("negative ref in drawfreedscreen\n");
+ if(this->ref > 0)
+ return;
+ ds = dscreen;
+ if(ds == this){
+ dscreen = this->next;
+ goto Found;
+ }
+ while(next = ds->next){ /* assign = */
+ if(next == this){
+ ds->next = this->next;
+ goto Found;
+ }
+ ds = next;
+ }
+ error(Enodrawimage);
+
+ Found:
+ if(this->dimage)
+ drawfreedimage(this->dimage);
+ if(this->dfill)
+ drawfreedimage(this->dfill);
+ free(this->screen);
+ free(this);
+}
+
+void
+drawfreedimage(DImage *dimage)
+{
+ int i;
+ Memimage *l;
+ DScreen *ds;
+
+ dimage->ref--;
+ if(dimage->ref < 0)
+ print("negative ref in drawfreedimage\n");
+ if(dimage->ref > 0)
+ return;
+
+ /* any names? */
+ for(i=0; i<sdraw.nname; )
+ if(sdraw.name[i].dimage == dimage)
+ drawdelname(sdraw.name+i);
+ else
+ i++;
+ if(dimage->fromname){ /* acquired by name; owned by someone else*/
+ drawfreedimage(dimage->fromname);
+ goto Return;
+ }
+// if(dimage->image == screenimage) /* don't free the display */
+// goto Return;
+ ds = dimage->dscreen;
+ if(ds){
+ l = dimage->image;
+ if(l->data == screenimage->data)
+ addflush(l->layer->screenr);
+ if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */
+ free(l->layer->refreshptr);
+ l->layer->refreshptr = nil;
+ if(drawgoodname(dimage))
+ memldelete(l);
+ else
+ memlfree(l);
+ drawfreedscreen(ds);
+ }else
+ freememimage(dimage->image);
+ Return:
+ free(dimage->fchar);
+ free(dimage);
+}
+
+void
+drawuninstallscreen(Client *client, CScreen *this)
+{
+ CScreen *cs, *next;
+
+ cs = client->cscreen;
+ if(cs == this){
+ client->cscreen = this->next;
+ drawfreedscreen(this->dscreen);
+ free(this);
+ return;
+ }
+ while(next = cs->next){ /* assign = */
+ if(next == this){
+ cs->next = this->next;
+ drawfreedscreen(this->dscreen);
+ free(this);
+ return;
+ }
+ cs = next;
+ }
+}
+
+void
+drawuninstall(Client *client, int id)
+{
+ DImage *d, *next;
+
+ d = client->dimage[id&HASHMASK];
+ if(d == 0)
+ error(Enodrawimage);
+ if(d->id == id){
+ client->dimage[id&HASHMASK] = d->next;
+ drawfreedimage(d);
+ return;
+ }
+ while(next = d->next){ /* assign = */
+ if(next->id == id){
+ d->next = next->next;
+ drawfreedimage(next);
+ return;
+ }
+ d = next;
+ }
+ error(Enodrawimage);
+}
+
+void
+drawaddname(Client *client, DImage *di, int n, char *str)
+{
+ DName *name, *ename, *new, *t;
+
+ name = sdraw.name;
+ ename = &name[sdraw.nname];
+ for(; name<ename; name++)
+ if(drawcmp(name->name, str, n) == 0)
+ error(Enameused);
+ t = smalloc((sdraw.nname+1)*sizeof(DName));
+ memmove(t, sdraw.name, sdraw.nname*sizeof(DName));
+ free(sdraw.name);
+ sdraw.name = t;
+ new = &sdraw.name[sdraw.nname++];
+ new->name = smalloc(n+1);
+ memmove(new->name, str, n);
+ new->name[n] = 0;
+ new->dimage = di;
+ new->client = client;
+ new->vers = ++sdraw.vers;
+}
+
+Client*
+drawnewclient(void)
+{
+ Client *cl, **cp;
+ int i;
+
+ for(i=0; i<sdraw.nclient; i++){
+ cl = sdraw.client[i];
+ if(cl == 0)
+ break;
+ }
+ if(i == sdraw.nclient){
+ cp = malloc((sdraw.nclient+1)*sizeof(Client*));
+ if(cp == 0)
+ return 0;
+ memmove(cp, sdraw.client, sdraw.nclient*sizeof(Client*));
+ free(sdraw.client);
+ sdraw.client = cp;
+ sdraw.nclient++;
+ cp[i] = 0;
+ }
+ cl = malloc(sizeof(Client));
+ if(cl == 0)
+ return 0;
+ memset(cl, 0, sizeof(Client));
+ cl->slot = i;
+ cl->clientid = ++sdraw.clientid;
+ cl->op = SoverD;
+ sdraw.client[i] = cl;
+ return cl;
+}
+
+static int
+drawclientop(Client *cl)
+{
+ int op;
+
+ op = cl->op;
+ cl->op = SoverD;
+ return op;
+}
+
+int
+drawhasclients(void)
+{
+ /*
+ * if draw has ever been used, we can't resize the frame buffer,
+ * even if all clients have exited (nclients is cumulative); it's too
+ * hard to make work.
+ */
+ return sdraw.nclient != 0;
+}
+
+Client*
+drawclientofpath(ulong path)
+{
+ Client *cl;
+ int slot;
+
+ slot = CLIENTPATH(path);
+ if(slot == 0)
+ return nil;
+ cl = sdraw.client[slot-1];
+ if(cl==0 || cl->clientid==0)
+ return nil;
+ return cl;
+}
+
+
+Client*
+drawclient(Chan *c)
+{
+ Client *client;
+
+ client = drawclientofpath(c->qid.path);
+ if(client == nil)
+ error(Enoclient);
+ return client;
+}
+
+Memimage*
+drawimage(Client *client, uchar *a)
+{
+ DImage *d;
+
+ d = drawlookup(client, BGLONG(a), 1);
+ if(d == nil)
+ error(Enodrawimage);
+ return d->image;
+}
+
+void
+drawrectangle(Rectangle *r, uchar *a)
+{
+ r->min.x = BGLONG(a+0*4);
+ r->min.y = BGLONG(a+1*4);
+ r->max.x = BGLONG(a+2*4);
+ r->max.y = BGLONG(a+3*4);
+}
+
+void
+drawpoint(Point *p, uchar *a)
+{
+ p->x = BGLONG(a+0*4);
+ p->y = BGLONG(a+1*4);
+}
+
+Point
+drawchar(Memimage *dst, Memimage *rdst, Point p, Memimage *src, Point *sp, DImage *font, int index, int op)
+{
+ FChar *fc;
+ Rectangle r;
+ Point sp1;
+ static Memimage *tmp;
+
+ fc = &font->fchar[index];
+ r.min.x = p.x+fc->left;
+ r.min.y = p.y-(font->ascent-fc->miny);
+ r.max.x = r.min.x+(fc->maxx-fc->minx);
+ r.max.y = r.min.y+(fc->maxy-fc->miny);
+ sp1.x = sp->x+fc->left;
+ sp1.y = sp->y+fc->miny;
+
+ /*
+ * If we're drawing greyscale fonts onto a VGA screen,
+ * it's very costly to read the screen memory to do the
+ * alpha blending inside memdraw. If this is really a stringbg,
+ * then rdst is the bg image (in main memory) which we can
+ * refer to for the underlying dst pixels instead of reading dst
+ * directly.
+ */
+ if(ishwimage(dst) && !ishwimage(rdst) && font->image->depth > 1){
+ if(tmp == nil || tmp->chan != dst->chan || Dx(tmp->r) < Dx(r) || Dy(tmp->r) < Dy(r)){
+ if(tmp)
+ freememimage(tmp);
+ tmp = allocmemimage(Rect(0,0,Dx(r),Dy(r)), dst->chan);
+ if(tmp == nil)
+ goto fallback;
+ }
+ memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), rdst, r.min, memopaque, ZP, S);
+ memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), src, sp1, font->image, Pt(fc->minx, fc->miny), op);
+ memdraw(dst, r, tmp, ZP, memopaque, ZP, S);
+ }else{
+ fallback:
+ memdraw(dst, r, src, sp1, font->image, Pt(fc->minx, fc->miny), op);
+ }
+
+ p.x += fc->width;
+ sp->x += fc->width;
+ return p;
+}
+
+static DImage*
+makescreenimage(void)
+{
+ int width, depth;
+ ulong chan;
+ DImage *di;
+ Memdata *md;
+ Memimage *i;
+ Rectangle r;
+
+ md = malloc(sizeof *md);
+ if(md == nil)
+ return nil;
+ md->allocd = 1;
+ md->base = nil;
+ md->bdata = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen);
+ if(md->bdata == nil){
+ free(md);
+ return nil;
+ }
+ md->ref = 1;
+ i = allocmemimaged(r, chan, md);
+ if(i == nil){
+ free(md);
+ return nil;
+ }
+ i->width = width;
+ i->clipr = r;
+
+ di = allocdimage(i);
+ if(di == nil){
+ freememimage(i); /* frees md */
+ return nil;
+ }
+ if(!waserror()){
+ snprint(screenname, sizeof screenname, "noborder.screen.%d", ++screennameid);
+ drawaddname(nil, di, strlen(screenname), screenname);
+ poperror();
+ }
+ return di;
+}
+
+static int
+initscreenimage(void)
+{
+ if(screenimage != nil)
+ return 1;
+
+ screendimage = makescreenimage();
+ if(screendimage == nil)
+ return 0;
+ screenimage = screendimage->image;
+// iprint("initscreenimage %p %p\n", screendimage, screenimage);
+ mouseresize();
+ return 1;
+}
+
+void
+deletescreenimage(void)
+{
+ dlock();
+ if(screenimage){
+ /* will be freed via screendimage; disable */
+ screenimage->clipr = ZR;
+ screenimage = nil;
+ }
+ if(screendimage){
+ drawfreedimage(screendimage);
+ screendimage = nil;
+ }
+ dunlock();
+}
+
+void
+resetscreenimage(void)
+{
+ dlock();
+ initscreenimage();
+ dunlock();
+}
+
+static Chan*
+drawattach(char *spec)
+{
+ dlock();
+ if(!initscreenimage()){
+ dunlock();
+ error("no frame buffer");
+ }
+ dunlock();
+ return devattach('i', spec);
+}
+
+static Walkqid*
+drawwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ if(screenimage == nil)
+ error("no frame buffer");
+ return devwalk(c, nc, name, nname, 0, 0, drawgen);
+}
+
+static int
+drawstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, 0, 0, drawgen);
+}
+
+static Chan*
+drawopen(Chan *c, int omode)
+{
+ Client *cl;
+ DName *dn;
+ DImage *di;
+
+ if(c->qid.type & QTDIR){
+ c = devopen(c, omode, 0, 0, drawgen);
+ c->iounit = IOUNIT;
+ }
+
+ dlock();
+ if(waserror()){
+ dunlock();
+ nexterror();
+ }
+
+ if(QID(c->qid) == Qnew){
+ cl = drawnewclient();
+ if(cl == 0)
+ error(Enodev);
+ c->qid.path = Qctl|((cl->slot+1)<<QSHIFT);
+ }
+
+ switch(QID(c->qid)){
+ case Qwinname:
+ break;
+
+ case Qnew:
+ break;
+
+ case Qctl:
+ cl = drawclient(c);
+ if(cl->busy)
+ error(Einuse);
+ cl->busy = 1;
+ flushrect = Rect(10000, 10000, -10000, -10000);
+ dn = drawlookupname(strlen(screenname), screenname);
+ if(dn == 0)
+ error("draw: cannot happen 2");
+ if(drawinstall(cl, 0, dn->dimage->image, 0) == 0)
+ error(Edrawmem);
+ di = drawlookup(cl, 0, 0);
+ if(di == 0)
+ error("draw: cannot happen 1");
+ di->vers = dn->vers;
+ di->name = smalloc(strlen(screenname)+1);
+ strcpy(di->name, screenname);
+ di->fromname = dn->dimage;
+ di->fromname->ref++;
+ incref(&cl->r);
+ break;
+
+ case Qcolormap:
+ case Qdata:
+ case Qrefresh:
+ cl = drawclient(c);
+ incref(&cl->r);
+ break;
+ }
+ dunlock();
+ poperror();
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ c->iounit = IOUNIT;
+ return c;
+}
+
+static void
+drawclose(Chan *c)
+{
+ int i;
+ DImage *d, **dp;
+ Client *cl;
+ Refresh *r;
+
+ if(QID(c->qid) < Qcolormap) /* Qtopdir, Qnew, Q3rd, Q2nd have no client */
+ return;
+ dlock();
+ if(waserror()){
+ dunlock();
+ nexterror();
+ }
+
+ cl = drawclient(c);
+ if(QID(c->qid) == Qctl)
+ cl->busy = 0;
+ if((c->flag&COPEN) && (decref(&cl->r)==0)){
+ while(r = cl->refresh){ /* assign = */
+ cl->refresh = r->next;
+ free(r);
+ }
+ /* free names */
+ for(i=0; i<sdraw.nname; )
+ if(sdraw.name[i].client == cl)
+ drawdelname(sdraw.name+i);
+ else
+ i++;
+ while(cl->cscreen)
+ drawuninstallscreen(cl, cl->cscreen);
+ /* all screens are freed, so now we can free images */
+ dp = cl->dimage;
+ for(i=0; i<NHASH; i++){
+ while((d = *dp) != nil){
+ *dp = d->next;
+ drawfreedimage(d);
+ }
+ dp++;
+ }
+ sdraw.client[cl->slot] = 0;
+ drawflush(); /* to erase visible, now dead windows */
+ free(cl);
+ }
+ dunlock();
+ poperror();
+}
+
+long
+drawread(Chan *c, void *a, long n, vlong off)
+{
+ int index, m;
+ ulong red, green, blue;
+ Client *cl;
+ uchar *p;
+ Refresh *r;
+ DImage *di;
+ Memimage *i;
+ ulong offset = off;
+ char buf[16];
+
+ if(c->qid.type & QTDIR)
+ return devdirread(c, a, n, 0, 0, drawgen);
+ if(QID(c->qid) == Qwinname)
+ return readstr(off, a, n, screenname);
+
+ cl = drawclient(c);
+ dlock();
+ if(waserror()){
+ dunlock();
+ nexterror();
+ }
+ switch(QID(c->qid)){
+ case Qctl:
+ if(n < 12*12)
+ error(Eshortread);
+ if(cl->infoid < 0)
+ error(Enodrawimage);
+ if(cl->infoid == 0){
+ i = screenimage;
+ if(i == nil)
+ error(Enodrawimage);
+ }else{
+ di = drawlookup(cl, cl->infoid, 1);
+ if(di == nil)
+ error(Enodrawimage);
+ i = di->image;
+ }
+ n = sprint(a, "%11d %11d %11s %11d %11d %11d %11d %11d %11d %11d %11d %11d ",
+ cl->clientid, cl->infoid, chantostr(buf, i->chan), (i->flags&Frepl)==Frepl,
+ i->r.min.x, i->r.min.y, i->r.max.x, i->r.max.y,
+ i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y);
+ cl->infoid = -1;
+ break;
+
+ case Qcolormap:
+ drawactive(1); /* to restore map from backup */
+ p = malloc(4*12*256+1);
+ if(p == 0)
+ error(Enomem);
+ m = 0;
+ for(index = 0; index < 256; index++){
+ getcolor(index, &red, &green, &blue);
+ m += sprint((char*)p+m, "%11d %11lud %11lud %11lud\n", index, red>>24, green>>24, blue>>24);
+ }
+ n = readstr(offset, a, n, (char*)p);
+ free(p);
+ break;
+
+ case Qdata:
+ if(cl->readdata == nil)
+ error("no draw data");
+ if(n < cl->nreaddata)
+ error(Eshortread);
+ n = cl->nreaddata;
+ memmove(a, cl->readdata, cl->nreaddata);
+ free(cl->readdata);
+ cl->readdata = nil;
+ break;
+
+ case Qrefresh:
+ if(n < 5*4)
+ error(Ebadarg);
+ for(;;){
+ if(cl->refreshme || cl->refresh)
+ break;
+ dunlock();
+ if(waserror()){
+ dlock(); /* restore lock for waserror() above */
+ nexterror();
+ }
+ sleep(&cl->refrend, drawrefactive, cl);
+ poperror();
+ dlock();
+ }
+ p = a;
+ while(cl->refresh && n>=5*4){
+ r = cl->refresh;
+ BPLONG(p+0*4, r->dimage->id);
+ BPLONG(p+1*4, r->r.min.x);
+ BPLONG(p+2*4, r->r.min.y);
+ BPLONG(p+3*4, r->r.max.x);
+ BPLONG(p+4*4, r->r.max.y);
+ cl->refresh = r->next;
+ free(r);
+ p += 5*4;
+ n -= 5*4;
+ }
+ cl->refreshme = 0;
+ n = p-(uchar*)a;
+ break;
+ }
+ dunlock();
+ poperror();
+ return n;
+}
+
+void
+drawwakeall(void)
+{
+ Client *cl;
+ int i;
+
+ for(i=0; i<sdraw.nclient; i++){
+ cl = sdraw.client[i];
+ if(cl && (cl->refreshme || cl->refresh))
+ wakeup(&cl->refrend);
+ }
+}
+
+static long
+drawwrite(Chan *c, void *a, long n, vlong)
+{
+ char buf[128], *fields[4], *q;
+ Client *cl;
+ int i, m, red, green, blue, x;
+
+ if(c->qid.type & QTDIR)
+ error(Eisdir);
+ cl = drawclient(c);
+ dlock();
+ if(waserror()){
+ drawwakeall();
+ dunlock();
+ nexterror();
+ }
+ switch(QID(c->qid)){
+ case Qctl:
+ if(n != 4)
+ error("unknown draw control request");
+ cl->infoid = BGLONG((uchar*)a);
+ break;
+
+ case Qcolormap:
+ drawactive(1); /* to restore map from backup */
+ m = n;
+ n = 0;
+ while(m > 0){
+ x = m;
+ if(x > sizeof(buf)-1)
+ x = sizeof(buf)-1;
+ q = memccpy(buf, a, '\n', x);
+ if(q == 0)
+ break;
+ i = q-buf;
+ n += i;
+ a = (char*)a + i;
+ m -= i;
+ *q = 0;
+ if(tokenize(buf, fields, nelem(fields)) != 4)
+ error(Ebadarg);
+ i = strtoul(fields[0], 0, 0);
+ red = strtoul(fields[1], 0, 0);
+ green = strtoul(fields[2], 0, 0);
+ blue = strtoul(fields[3], &q, 0);
+ if(fields[3] == q)
+ error(Ebadarg);
+ if(red>255 || green>255 || blue>255 || i<0 || i>255)
+ error(Ebadarg);
+ red |= red<<8;
+ red |= red<<16;
+ green |= green<<8;
+ green |= green<<16;
+ blue |= blue<<8;
+ blue |= blue<<16;
+ setcolor(i, red, green, blue);
+ }
+ break;
+
+ case Qdata:
+ drawmesg(cl, a, n);
+ drawwakeall();
+ break;
+
+ default:
+ error(Ebadusefd);
+ }
+ dunlock();
+ poperror();
+ return n;
+}
+
+uchar*
+drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
+{
+ int b, x;
+
+ if(p >= maxp)
+ error(Eshortdraw);
+ b = *p++;
+ x = b & 0x7F;
+ if(b & 0x80){
+ if(p+1 >= maxp)
+ error(Eshortdraw);
+ x |= *p++ << 7;
+ x |= *p++ << 15;
+ if(x & (1<<22))
+ x |= ~0<<23;
+ }else{
+ if(b & 0x40)
+ x |= ~0<<7;
+ x += oldx;
+ }
+ *newx = x;
+ return p;
+}
+
+static void
+printmesg(char *fmt, uchar *a, int plsprnt)
+{
+ char buf[256];
+ char *p, *q;
+ int s;
+
+ if(1|| plsprnt==0){
+ SET(s,q,p);
+ USED(fmt, a, buf, p, q, s);
+ return;
+ }
+ q = buf;
+ *q++ = *a++;
+ for(p=fmt; *p; p++){
+ switch(*p){
+ case 'l':
+ q += sprint(q, " %ld", (long)BGLONG(a));
+ a += 4;
+ break;
+ case 'L':
+ q += sprint(q, " %.8lux", (ulong)BGLONG(a));
+ a += 4;
+ break;
+ case 'R':
+ q += sprint(q, " [%d %d %d %d]", BGLONG(a), BGLONG(a+4), BGLONG(a+8), BGLONG(a+12));
+ a += 16;
+ break;
+ case 'P':
+ q += sprint(q, " [%d %d]", BGLONG(a), BGLONG(a+4));
+ a += 8;
+ break;
+ case 'b':
+ q += sprint(q, " %d", *a++);
+ break;
+ case 's':
+ q += sprint(q, " %d", BGSHORT(a));
+ a += 2;
+ break;
+ case 'S':
+ q += sprint(q, " %.4ux", BGSHORT(a));
+ a += 2;
+ break;
+ }
+ }
+ *q++ = '\n';
+ *q = 0;
+ iprint("%.*s", (int)(q-buf), buf);
+}
+
+void
+drawmesg(Client *client, void *av, int n)
+{
+ int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush;
+ uchar *u, *a, refresh;
+ char *fmt;
+ ulong value, chan;
+ Rectangle r, clipr;
+ Point p, q, *pp, sp;
+ Memimage *i, *bg, *dst, *src, *mask;
+ Memimage *l, **lp;
+ Memscreen *scrn;
+ DImage *font, *ll, *di, *ddst, *dsrc;
+ DName *dn;
+ DScreen *dscrn;
+ FChar *fc;
+ Refx *refx;
+ CScreen *cs;
+ Refreshfn reffn;
+
+ a = av;
+ m = 0;
+ fmt = nil;
+ if(waserror()){
+ if(fmt) printmesg(fmt, a, 1);
+ /* iprint("error: %s\n", up->errstr); */
+ nexterror();
+ }
+ while((n-=m) > 0){
+ USED(fmt);
+ a += m;
+ switch(*a){
+ default:
+ error("bad draw command");
+ /* new allocate: 'b' id[4] screenid[4] refresh[1] chan[4] repl[1] R[4*4] clipR[4*4] rrggbbaa[4] */
+ case 'b':
+ printmesg(fmt="LLbLbRRL", a, 0);
+ m = 1+4+4+1+4+1+4*4+4*4+4;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ scrnid = BGSHORT(a+5);
+ refresh = a[9];
+ chan = BGLONG(a+10);
+ repl = a[14];
+ drawrectangle(&r, a+15);
+ drawrectangle(&clipr, a+31);
+ value = BGLONG(a+47);
+ if(drawlookup(client, dstid, 0))
+ error(Eimageexists);
+ if(scrnid){
+ dscrn = drawlookupscreen(client, scrnid, &cs);
+ scrn = dscrn->screen;
+ if(repl || chan!=scrn->image->chan)
+ error("image parameters incompatible with screen");
+ reffn = nil;
+ switch(refresh){
+ case Refbackup:
+ break;
+ case Refnone:
+ reffn = memlnorefresh;
+ break;
+ case Refmesg:
+ reffn = drawrefresh;
+ break;
+ default:
+ error("unknown refresh method");
+ }
+ l = memlalloc(scrn, r, reffn, 0, value);
+ if(l == 0)
+ error(Edrawmem);
+ addflush(l->layer->screenr);
+ l->clipr = clipr;
+ rectclip(&l->clipr, r);
+ if(drawinstall(client, dstid, l, dscrn) == 0){
+ memldelete(l);
+ error(Edrawmem);
+ }
+ dscrn->ref++;
+ if(reffn){
+ refx = nil;
+ if(reffn == drawrefresh){
+ refx = malloc(sizeof(Refx));
+ if(refx == 0){
+ drawuninstall(client, dstid);
+ error(Edrawmem);
+ }
+ refx->client = client;
+ refx->dimage = drawlookup(client, dstid, 1);
+ }
+ memlsetrefresh(l, reffn, refx);
+ }
+ continue;
+ }
+ i = allocmemimage(r, chan);
+ if(i == 0)
+ error(Edrawmem);
+ if(repl)
+ i->flags |= Frepl;
+ i->clipr = clipr;
+ if(!repl)
+ rectclip(&i->clipr, r);
+ if(drawinstall(client, dstid, i, 0) == 0){
+ freememimage(i);
+ error(Edrawmem);
+ }
+ memfillcolor(i, value);
+ continue;
+
+ /* allocate screen: 'A' id[4] imageid[4] fillid[4] public[1] */
+ case 'A':
+ printmesg(fmt="LLLb", a, 1);
+ m = 1+4+4+4+1;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ if(dstid == 0)
+ error(Ebadarg);
+ if(drawlookupdscreen(dstid))
+ error(Escreenexists);
+ ddst = drawlookup(client, BGLONG(a+5), 1);
+ dsrc = drawlookup(client, BGLONG(a+9), 1);
+ if(ddst==0 || dsrc==0)
+ error(Enodrawimage);
+ if(drawinstallscreen(client, 0, dstid, ddst, dsrc, a[13]) == 0)
+ error(Edrawmem);
+ continue;
+
+ /* set repl and clip: 'c' dstid[4] repl[1] clipR[4*4] */
+ case 'c':
+ printmesg(fmt="LbR", a, 0);
+ m = 1+4+1+4*4;
+ if(n < m)
+ error(Eshortdraw);
+ ddst = drawlookup(client, BGLONG(a+1), 1);
+ if(ddst == nil)
+ error(Enodrawimage);
+ if(ddst->name)
+ error("cannot change repl/clipr of shared image");
+ dst = ddst->image;
+ if(a[5])
+ dst->flags |= Frepl;
+ drawrectangle(&dst->clipr, a+6);
+ continue;
+
+ /* draw: 'd' dstid[4] srcid[4] maskid[4] R[4*4] P[2*4] P[2*4] */
+ case 'd':
+ printmesg(fmt="LLLRPP", a, 0);
+ m = 1+4+4+4+4*4+2*4+2*4;
+ if(n < m)
+ error(Eshortdraw);
+ dst = drawimage(client, a+1);
+ dstid = BGLONG(a+1);
+ src = drawimage(client, a+5);
+ mask = drawimage(client, a+9);
+ drawrectangle(&r, a+13);
+ drawpoint(&p, a+29);
+ drawpoint(&q, a+37);
+ op = drawclientop(client);
+ memdraw(dst, r, src, p, mask, q, op);
+ dstflush(dstid, dst, r);
+ continue;
+
+ /* toggle debugging: 'D' val[1] */
+ case 'D':
+ printmesg(fmt="b", a, 0);
+ m = 1+1;
+ if(n < m)
+ error(Eshortdraw);
+ drawdebug = a[1];
+ continue;
+
+ /* ellipse: 'e' dstid[4] srcid[4] center[2*4] a[4] b[4] thick[4] sp[2*4] alpha[4] phi[4]*/
+ case 'e':
+ case 'E':
+ printmesg(fmt="LLPlllPll", a, 0);
+ m = 1+4+4+2*4+4+4+4+2*4+2*4;
+ if(n < m)
+ error(Eshortdraw);
+ dst = drawimage(client, a+1);
+ dstid = BGLONG(a+1);
+ src = drawimage(client, a+5);
+ drawpoint(&p, a+9);
+ e0 = BGLONG(a+17);
+ e1 = BGLONG(a+21);
+ if(e0<0 || e1<0)
+ error("invalid ellipse semidiameter");
+ j = BGLONG(a+25);
+ if(j < 0)
+ error("negative ellipse thickness");
+ drawpoint(&sp, a+29);
+ c = j;
+ if(*a == 'E')
+ c = -1;
+ ox = BGLONG(a+37);
+ oy = BGLONG(a+41);
+ op = drawclientop(client);
+ /* high bit indicates arc angles are present */
+ if(ox & (1<<31)){
+ if((ox & (1<<30)) == 0)
+ ox &= ~(1<<31);
+ memarc(dst, p, e0, e1, c, src, sp, ox, oy, op);
+ }else
+ memellipse(dst, p, e0, e1, c, src, sp, op);
+ dstflush(dstid, dst, Rect(p.x-e0-j, p.y-e1-j, p.x+e0+j+1, p.y+e1+j+1));
+ continue;
+
+ /* free: 'f' id[4] */
+ case 'f':
+ printmesg(fmt="L", a, 1);
+ m = 1+4;
+ if(n < m)
+ error(Eshortdraw);
+ ll = drawlookup(client, BGLONG(a+1), 0);
+ if(ll && ll->dscreen && ll->dscreen->owner != client)
+ ll->dscreen->owner->refreshme = 1;
+ drawuninstall(client, BGLONG(a+1));
+ continue;
+
+ /* free screen: 'F' id[4] */
+ case 'F':
+ printmesg(fmt="L", a, 1);
+ m = 1+4;
+ if(n < m)
+ error(Eshortdraw);
+ drawlookupscreen(client, BGLONG(a+1), &cs);
+ drawuninstallscreen(client, cs);
+ continue;
+
+ /* initialize font: 'i' fontid[4] nchars[4] ascent[1] */
+ case 'i':
+ printmesg(fmt="Llb", a, 1);
+ m = 1+4+4+1;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ if(dstid == 0)
+ error("cannot use display as font");
+ font = drawlookup(client, dstid, 1);
+ if(font == 0)
+ error(Enodrawimage);
+ if(font->image->layer)
+ error("cannot use window as font");
+ ni = BGLONG(a+5);
+ if(ni<=0 || ni>4096)
+ error("bad font size (4096 chars max)");
+ free(font->fchar); /* should we complain if non-zero? */
+ font->fchar = malloc(ni*sizeof(FChar));
+ if(font->fchar == 0)
+ error("no memory for font");
+ memset(font->fchar, 0, ni*sizeof(FChar));
+ font->nfchar = ni;
+ font->ascent = a[9];
+ continue;
+
+ /* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */
+ case 'l':
+ printmesg(fmt="LLSRPbb", a, 0);
+ m = 1+4+4+2+4*4+2*4+1+1;
+ if(n < m)
+ error(Eshortdraw);
+ font = drawlookup(client, BGLONG(a+1), 1);
+ if(font == 0)
+ error(Enodrawimage);
+ if(font->nfchar == 0)
+ error(Enotfont);
+ src = drawimage(client, a+5);
+ ci = BGSHORT(a+9);
+ if(ci >= font->nfchar)
+ error(Eindex);
+ drawrectangle(&r, a+11);
+ drawpoint(&p, a+27);
+ memdraw(font->image, r, src, p, memopaque, p, S);
+ fc = &font->fchar[ci];
+ fc->minx = r.min.x;
+ fc->maxx = r.max.x;
+ fc->miny = r.min.y;
+ fc->maxy = r.max.y;
+ fc->left = a[35];
+ fc->width = a[36];
+ continue;
+
+ /* draw line: 'L' dstid[4] p0[2*4] p1[2*4] end0[4] end1[4] radius[4] srcid[4] sp[2*4] */
+ case 'L':
+ printmesg(fmt="LPPlllLP", a, 0);
+ m = 1+4+2*4+2*4+4+4+4+4+2*4;
+ if(n < m)
+ error(Eshortdraw);
+ dst = drawimage(client, a+1);
+ dstid = BGLONG(a+1);
+ drawpoint(&p, a+5);
+ drawpoint(&q, a+13);
+ e0 = BGLONG(a+21);
+ e1 = BGLONG(a+25);
+ j = BGLONG(a+29);
+ if(j < 0)
+ error("negative line width");
+ src = drawimage(client, a+33);
+ drawpoint(&sp, a+37);
+ op = drawclientop(client);
+ memline(dst, p, q, e0, e1, j, src, sp, op);
+ /* avoid memlinebbox if possible */
+ if(dstid==0 || dst->layer!=nil){
+ /* BUG: this is terribly inefficient: update maximal containing rect*/
+ r = memlinebbox(p, q, e0, e1, j);
+ dstflush(dstid, dst, insetrect(r, -(1+1+j)));
+ }
+ continue;
+
+ /* create image mask: 'm' newid[4] id[4] */
+/*
+ *
+ case 'm':
+ printmesg("LL", a, 0);
+ m = 4+4;
+ if(n < m)
+ error(Eshortdraw);
+ break;
+ *
+ */
+
+ /* attach to a named image: 'n' dstid[4] j[1] name[j] */
+ case 'n':
+ printmesg(fmt="Lz", a, 0);
+ m = 1+4+1;
+ if(n < m)
+ error(Eshortdraw);
+ j = a[5];
+ if(j == 0) /* give me a non-empty name please */
+ error(Eshortdraw);
+ m += j;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ if(drawlookup(client, dstid, 0))
+ error(Eimageexists);
+ dn = drawlookupname(j, (char*)a+6);
+ if(dn == nil)
+ error(Enoname);
+ if(drawinstall(client, dstid, dn->dimage->image, 0) == 0)
+ error(Edrawmem);
+ di = drawlookup(client, dstid, 0);
+ if(di == 0)
+ error("draw: cannot happen");
+ di->vers = dn->vers;
+ di->name = smalloc(j+1);
+ di->fromname = dn->dimage;
+ di->fromname->ref++;
+ memmove(di->name, a+6, j);
+ di->name[j] = 0;
+ client->infoid = dstid;
+ continue;
+
+ /* name an image: 'N' dstid[4] in[1] j[1] name[j] */
+ case 'N':
+ printmesg(fmt="Lbz", a, 0);
+ m = 1+4+1+1;
+ if(n < m)
+ error(Eshortdraw);
+ c = a[5];
+ j = a[6];
+ if(j == 0) /* give me a non-empty name please */
+ error(Eshortdraw);
+ m += j;
+ if(n < m)
+ error(Eshortdraw);
+ di = drawlookup(client, BGLONG(a+1), 0);
+ if(di == 0)
+ error(Enodrawimage);
+ if(di->name)
+ error(Enamed);
+ if(c)
+ drawaddname(client, di, j, (char*)a+7);
+ else{
+ dn = drawlookupname(j, (char*)a+7);
+ if(dn == nil)
+ error(Enoname);
+ if(dn->dimage != di)
+ error(Ewrongname);
+ drawdelname(dn);
+ }
+ continue;
+
+ /* position window: 'o' id[4] r.min [2*4] screenr.min [2*4] */
+ case 'o':
+ printmesg(fmt="LPP", a, 0);
+ m = 1+4+2*4+2*4;
+ if(n < m)
+ error(Eshortdraw);
+ dst = drawimage(client, a+1);
+ if(dst->layer){
+ drawpoint(&p, a+5);
+ drawpoint(&q, a+13);
+ r = dst->layer->screenr;
+ ni = memlorigin(dst, p, q);
+ if(ni < 0)
+ error("image origin failed");
+ if(ni > 0){
+ addflush(r);
+ addflush(dst->layer->screenr);
+ ll = drawlookup(client, BGLONG(a+1), 1);
+ drawrefreshscreen(ll, client);
+ }
+ }
+ continue;
+
+ /* set compositing operator for next draw operation: 'O' op */
+ case 'O':
+ printmesg(fmt="b", a, 0);
+ m = 1+1;
+ if(n < m)
+ error(Eshortdraw);
+ client->op = a[1];
+ continue;
+
+ /* filled polygon: 'P' dstid[4] n[2] wind[4] ignore[2*4] srcid[4] sp[2*4] p0[2*4] dp[2*2*n] */
+ /* polygon: 'p' dstid[4] n[2] end0[4] end1[4] radius[4] srcid[4] sp[2*4] p0[2*4] dp[2*2*n] */
+ case 'p':
+ case 'P':
+ printmesg(fmt="LslllLPP", a, 0);
+ m = 1+4+2+4+4+4+4+2*4;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ dst = drawimage(client, a+1);
+ ni = BGSHORT(a+5);
+ if(ni < 0)
+ error("negative count in polygon");
+ e0 = BGLONG(a+7);
+ e1 = BGLONG(a+11);
+ j = 0;
+ if(*a == 'p'){
+ j = BGLONG(a+15);
+ if(j < 0)
+ error("negative polygon line width");
+ }
+ src = drawimage(client, a+19);
+ drawpoint(&sp, a+23);
+ drawpoint(&p, a+31);
+ ni++;
+ pp = malloc(ni*sizeof(Point));
+ if(pp == nil)
+ error(Enomem);
+ doflush = 0;
+ if(dstid==0 || (dst->layer && dst->layer->screen->image->data == screenimage->data))
+ doflush = 1; /* simplify test in loop */
+ ox = oy = 0;
+ esize = 0;
+ u = a+m;
+ for(y=0; y<ni; y++){
+ q = p;
+ oesize = esize;
+ u = drawcoord(u, a+n, ox, &p.x);
+ u = drawcoord(u, a+n, oy, &p.y);
+ ox = p.x;
+ oy = p.y;
+ if(doflush){
+ esize = j;
+ if(*a == 'p'){
+ if(y == 0){
+ c = memlineendsize(e0);
+ if(c > esize)
+ esize = c;
+ }
+ if(y == ni-1){
+ c = memlineendsize(e1);
+ if(c > esize)
+ esize = c;
+ }
+ }
+ if(*a=='P' && e0!=1 && e0 !=~0)
+ r = dst->clipr;
+ else if(y > 0){
+ r = Rect(q.x-oesize, q.y-oesize, q.x+oesize+1, q.y+oesize+1);
+ combinerect(&r, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
+ }
+ if(rectclip(&r, dst->clipr)) /* should perhaps be an arg to dstflush */
+ dstflush(dstid, dst, r);
+ }
+ pp[y] = p;
+ }
+ if(y == 1)
+ dstflush(dstid, dst, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
+ op = drawclientop(client);
+ if(*a == 'p')
+ mempoly(dst, pp, ni, e0, e1, j, src, sp, op);
+ else
+ memfillpoly(dst, pp, ni, e0, src, sp, op);
+ free(pp);
+ m = u-a;
+ continue;
+
+ /* read: 'r' id[4] R[4*4] */
+ case 'r':
+ printmesg(fmt="LR", a, 0);
+ m = 1+4+4*4;
+ if(n < m)
+ error(Eshortdraw);
+ i = drawimage(client, a+1);
+ drawrectangle(&r, a+5);
+ if(!rectinrect(r, i->r))
+ error(Ereadoutside);
+ c = bytesperline(r, i->depth);
+ c *= Dy(r);
+ free(client->readdata);
+ client->readdata = mallocz(c, 0);
+ if(client->readdata == nil)
+ error("readimage malloc failed");
+ client->nreaddata = memunload(i, r, client->readdata, c);
+ if(client->nreaddata < 0){
+ free(client->readdata);
+ client->readdata = nil;
+ error("bad readimage call");
+ }
+ continue;
+
+ /* string: 's' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] ni*(index[2]) */
+ /* stringbg: 'x' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] bgid[4] bgpt[2*4] ni*(index[2]) */
+ case 's':
+ case 'x':
+ printmesg(fmt="LLLPRPs", a, 0);
+ m = 1+4+4+4+2*4+4*4+2*4+2;
+ if(*a == 'x')
+ m += 4+2*4;
+ if(n < m)
+ error(Eshortdraw);
+
+ dst = drawimage(client, a+1);
+ dstid = BGLONG(a+1);
+ src = drawimage(client, a+5);
+ font = drawlookup(client, BGLONG(a+9), 1);
+ if(font == 0)
+ error(Enodrawimage);
+ if(font->nfchar == 0)
+ error(Enotfont);
+ drawpoint(&p, a+13);
+ drawrectangle(&r, a+21);
+ drawpoint(&sp, a+37);
+ ni = BGSHORT(a+45);
+ u = a+m;
+ m += ni*2;
+ if(n < m)
+ error(Eshortdraw);
+ clipr = dst->clipr;
+ dst->clipr = r;
+ op = drawclientop(client);
+ bg = dst;
+ if(*a == 'x'){
+ /* paint background */
+ bg = drawimage(client, a+47);
+ drawpoint(&q, a+51);
+ r.min.x = p.x;
+ r.min.y = p.y-font->ascent;
+ r.max.x = p.x;
+ r.max.y = r.min.y+Dy(font->image->r);
+ j = ni;
+ while(--j >= 0){
+ ci = BGSHORT(u);
+ if(ci<0 || ci>=font->nfchar){
+ dst->clipr = clipr;
+ error(Eindex);
+ }
+ r.max.x += font->fchar[ci].width;
+ u += 2;
+ }
+ memdraw(dst, r, bg, q, memopaque, ZP, op);
+ u -= 2*ni;
+ }
+ q = p;
+ while(--ni >= 0){
+ ci = BGSHORT(u);
+ if(ci<0 || ci>=font->nfchar){
+ dst->clipr = clipr;
+ error(Eindex);
+ }
+ q = drawchar(dst, bg, q, src, &sp, font, ci, op);
+ u += 2;
+ }
+ dst->clipr = clipr;
+ p.y -= font->ascent;
+ dstflush(dstid, dst, Rect(p.x, p.y, q.x, p.y+Dy(font->image->r)));
+ continue;
+
+ /* use public screen: 'S' id[4] chan[4] */
+ case 'S':
+ printmesg(fmt="Ll", a, 0);
+ m = 1+4+4;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ if(dstid == 0)
+ error(Ebadarg);
+ dscrn = drawlookupdscreen(dstid);
+ if(dscrn==0 || (dscrn->public==0 && dscrn->owner!=client))
+ error(Enodrawscreen);
+ if(dscrn->screen->image->chan != BGLONG(a+5))
+ error("inconsistent chan");
+ if(drawinstallscreen(client, dscrn, 0, 0, 0, 0) == 0)
+ error(Edrawmem);
+ continue;
+
+ /* top or bottom windows: 't' top[1] nw[2] n*id[4] */
+ case 't':
+ printmesg(fmt="bsL", a, 0);
+ m = 1+1+2;
+ if(n < m)
+ error(Eshortdraw);
+ nw = BGSHORT(a+2);
+ if(nw < 0)
+ error(Ebadarg);
+ if(nw == 0)
+ continue;
+ m += nw*4;
+ if(n < m)
+ error(Eshortdraw);
+ lp = malloc(nw*sizeof(Memimage*));
+ if(lp == 0)
+ error(Enomem);
+ if(waserror()){
+ free(lp);
+ nexterror();
+ }
+ for(j=0; j<nw; j++)
+ lp[j] = drawimage(client, a+1+1+2+j*4);
+ if(lp[0]->layer == 0)
+ error("images are not windows");
+ for(j=1; j<nw; j++)
+ if(lp[j]->layer->screen != lp[0]->layer->screen)
+ error("images not on same screen");
+ if(a[1])
+ memltofrontn(lp, nw);
+ else
+ memltorearn(lp, nw);
+ if(lp[0]->layer->screen->image->data == screenimage->data)
+ for(j=0; j<nw; j++)
+ addflush(lp[j]->layer->screenr);
+ ll = drawlookup(client, BGLONG(a+1+1+2), 1);
+ drawrefreshscreen(ll, client);
+ poperror();
+ free(lp);
+ continue;
+
+ /* visible: 'v' */
+ case 'v':
+ printmesg(fmt="", a, 0);
+ m = 1;
+ drawflush();
+ continue;
+
+ /* write: 'y' id[4] R[4*4] data[x*1] */
+ /* write from compressed data: 'Y' id[4] R[4*4] data[x*1] */
+ case 'y':
+ case 'Y':
+ printmesg(fmt="LR", a, 0);
+ // iprint("load %c\n", *a);
+ m = 1+4+4*4;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ dst = drawimage(client, a+1);
+ drawrectangle(&r, a+5);
+ if(!rectinrect(r, dst->r))
+ error(Ewriteoutside);
+ y = memload(dst, r, a+m, n-m, *a=='Y');
+ if(y < 0)
+ error("bad writeimage call");
+ dstflush(dstid, dst, r);
+ m += y;
+ continue;
+ }
+ }
+ poperror();
+}
+
+Dev drawdevtab = {
+ 'i',
+ "draw",
+
+ devreset,
+ devinit,
+ devshutdown,
+ drawattach,
+ drawwalk,
+ drawstat,
+ drawopen,
+ devcreate,
+ drawclose,
+ drawread,
+ devbread,
+ drawwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+/*
+ * On 8 bit displays, load the default color map
+ */
+void
+drawcmap(void)
+{
+ int r, g, b, cr, cg, cb, v;
+ int num, den;
+ int i, j;
+
+ drawactive(1); /* to restore map from backup */
+ for(r=0,i=0; r!=4; r++)
+ for(v=0; v!=4; v++,i+=16){
+ for(g=0,j=v-r; g!=4; g++)
+ for(b=0;b!=4;b++,j++){
+ den = r;
+ if(g > den)
+ den = g;
+ if(b > den)
+ den = b;
+ if(den == 0) /* divide check -- pick grey shades */
+ cr = cg = cb = v*17;
+ else{
+ num = 17*(4*den+v);
+ cr = r*num/den;
+ cg = g*num/den;
+ cb = b*num/den;
+ }
+ setcolor(i+(j&15),
+ cr*0x01010101, cg*0x01010101, cb*0x01010101);
+ }
+ }
+}
+
+void
+drawblankscreen(int blank)
+{
+ int i, nc;
+ ulong *p;
+
+ if(blank == sdraw.blanked)
+ return;
+ if(!candlock())
+ return;
+ if(screenimage == nil){
+ dunlock();
+ return;
+ }
+ p = sdraw.savemap;
+ nc = screenimage->depth > 8 ? 256 : 1<<screenimage->depth;
+
+ /*
+ * blankscreen uses the hardware to blank the screen
+ * when possible. to help in cases when it is not possible,
+ * we set the color map to be all black.
+ */
+ if(blank == 0){ /* turn screen on */
+ for(i=0; i<nc; i++, p+=3)
+ setcolor(i, p[0], p[1], p[2]);
+ blankscreen(0);
+ }else{ /* turn screen off */
+ blankscreen(1);
+ for(i=0; i<nc; i++, p+=3){
+ getcolor(i, &p[0], &p[1], &p[2]);
+ setcolor(i, 0, 0, 0);
+ }
+ }
+ sdraw.blanked = blank;
+ dunlock();
+}
+
+/*
+ * record activity on screen, changing blanking as appropriate
+ */
+void
+drawactive(int active)
+{
+ if(active){
+ drawblankscreen(0);
+ sdraw.blanktime = MACHP(0)->ticks;
+ }else{
+ if(blanktime && sdraw.blanktime && TK2SEC(MACHP(0)->ticks - sdraw.blanktime)/60 >= blanktime)
+ drawblankscreen(1);
+ }
+}
+
+int
+drawidletime(void)
+{
+ return TK2SEC(MACHP(0)->ticks - sdraw.blanktime)/60;
+}
diff --git a/sys/src/9/port/devdup.c b/sys/src/9/port/devdup.c
new file mode 100755
index 000000000..c3a30caef
--- /dev/null
+++ b/sys/src/9/port/devdup.c
@@ -0,0 +1,146 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+/* Qid is (2*fd + (file is ctl))+1 */
+
+static int
+dupgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
+{
+ Fgrp *fgrp = up->fgrp;
+ Chan *f;
+ static int perm[] = { 0400, 0200, 0600, 0 };
+ int p;
+ Qid q;
+
+ if(s == DEVDOTDOT){
+ devdir(c, c->qid, ".", 0, eve, DMDIR|0555, dp);
+ return 1;
+ }
+ if(s == 0)
+ return 0;
+ s--;
+ if(s/2 > fgrp->maxfd)
+ return -1;
+ if((f=fgrp->fd[s/2]) == nil)
+ return 0;
+ if(s & 1){
+ p = 0400;
+ sprint(up->genbuf, "%dctl", s/2);
+ }else{
+ p = perm[f->mode&3];
+ sprint(up->genbuf, "%d", s/2);
+ }
+ mkqid(&q, s+1, 0, QTFILE);
+ devdir(c, q, up->genbuf, 0, eve, p, dp);
+ return 1;
+}
+
+static Chan*
+dupattach(char *spec)
+{
+ return devattach('d', spec);
+}
+
+static Walkqid*
+dupwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, (Dirtab *)0, 0, dupgen);
+}
+
+static int
+dupstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, (Dirtab *)0, 0L, dupgen);
+}
+
+static Chan*
+dupopen(Chan *c, int omode)
+{
+ Chan *f;
+ int fd, twicefd;
+
+ if(c->qid.type & QTDIR){
+ if(omode != 0)
+ error(Eisdir);
+ c->mode = 0;
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+ }
+ if(c->qid.type & QTAUTH)
+ error(Eperm);
+ twicefd = c->qid.path - 1;
+ fd = twicefd/2;
+ if((twicefd & 1)){
+ /* ctl file */
+ f = c;
+ f->mode = openmode(omode);
+ f->flag |= COPEN;
+ f->offset = 0;
+ }else{
+ /* fd file */
+ f = fdtochan(fd, openmode(omode), 0, 1);
+ cclose(c);
+ }
+ if(omode & OCEXEC)
+ f->flag |= CCEXEC;
+ return f;
+}
+
+static void
+dupclose(Chan*)
+{
+}
+
+static long
+dupread(Chan *c, void *va, long n, vlong offset)
+{
+ char *a = va;
+ char buf[256];
+ int fd, twicefd;
+
+ if(c->qid.type == QTDIR)
+ return devdirread(c, a, n, (Dirtab *)0, 0L, dupgen);
+ twicefd = c->qid.path - 1;
+ fd = twicefd/2;
+ if(twicefd & 1){
+ c = fdtochan(fd, -1, 0, 1);
+ procfdprint(c, fd, 0, buf, sizeof buf);
+ cclose(c);
+ return readstr((ulong)offset, va, n, buf);
+ }
+ panic("dupread");
+ return 0;
+}
+
+static long
+dupwrite(Chan*, void*, long, vlong)
+{
+ error(Eperm);
+ return 0; /* not reached */
+}
+
+Dev dupdevtab = {
+ 'd',
+ "dup",
+
+ devreset,
+ devinit,
+ devshutdown,
+ dupattach,
+ dupwalk,
+ dupstat,
+ dupopen,
+ devcreate,
+ dupclose,
+ dupread,
+ devbread,
+ dupwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/port/devenv.c b/sys/src/9/port/devenv.c
new file mode 100755
index 000000000..3031cc50e
--- /dev/null
+++ b/sys/src/9/port/devenv.c
@@ -0,0 +1,438 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+enum
+{
+ Maxenvsize = 16300,
+};
+
+static Egrp *envgrp(Chan *c);
+static int envwriteable(Chan *c);
+
+static Egrp confegrp; /* global environment group containing the kernel configuration */
+
+static Evalue*
+envlookup(Egrp *eg, char *name, ulong qidpath)
+{
+ Evalue *e;
+ int i;
+
+ for(i=0; i<eg->nent; i++){
+ e = eg->ent[i];
+ if(e->qid.path == qidpath || (name && e->name[0]==name[0] && strcmp(e->name, name) == 0))
+ return e;
+ }
+ return nil;
+}
+
+static int
+envgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
+{
+ Egrp *eg;
+ Evalue *e;
+
+ if(s == DEVDOTDOT){
+ devdir(c, c->qid, "#e", 0, eve, DMDIR|0775, dp);
+ return 1;
+ }
+
+ eg = envgrp(c);
+ rlock(eg);
+ e = 0;
+ if(name)
+ e = envlookup(eg, name, -1);
+ else if(s < eg->nent)
+ e = eg->ent[s];
+
+ if(e == 0) {
+ runlock(eg);
+ return -1;
+ }
+
+ /* make sure name string continues to exist after we release lock */
+ kstrcpy(up->genbuf, e->name, sizeof up->genbuf);
+ devdir(c, e->qid, up->genbuf, e->len, eve, 0666, dp);
+ runlock(eg);
+ return 1;
+}
+
+static Chan*
+envattach(char *spec)
+{
+ Chan *c;
+ Egrp *egrp = nil;
+
+ if(spec && *spec) {
+ if(strcmp(spec, "c") == 0)
+ egrp = &confegrp;
+ if(egrp == nil)
+ error(Ebadarg);
+ }
+
+ c = devattach('e', spec);
+ c->aux = egrp;
+ return c;
+}
+
+static Walkqid*
+envwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, 0, 0, envgen);
+}
+
+static int
+envstat(Chan *c, uchar *db, int n)
+{
+ if(c->qid.type & QTDIR)
+ c->qid.vers = envgrp(c)->vers;
+ return devstat(c, db, n, 0, 0, envgen);
+}
+
+static Chan*
+envopen(Chan *c, int omode)
+{
+ Egrp *eg;
+ Evalue *e;
+ int trunc;
+
+ eg = envgrp(c);
+ if(c->qid.type & QTDIR) {
+ if(omode != OREAD)
+ error(Eperm);
+ }
+ else {
+ trunc = omode & OTRUNC;
+ if(omode != OREAD && !envwriteable(c))
+ error(Eperm);
+ if(trunc)
+ wlock(eg);
+ else
+ rlock(eg);
+ e = envlookup(eg, nil, c->qid.path);
+ if(e == 0) {
+ if(trunc)
+ wunlock(eg);
+ else
+ runlock(eg);
+ error(Enonexist);
+ }
+ if(trunc && e->value) {
+ e->qid.vers++;
+ free(e->value);
+ e->value = 0;
+ e->len = 0;
+ }
+ if(trunc)
+ wunlock(eg);
+ else
+ runlock(eg);
+ }
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+static void
+envcreate(Chan *c, char *name, int omode, ulong)
+{
+ Egrp *eg;
+ Evalue *e;
+ Evalue **ent;
+
+ if(c->qid.type != QTDIR)
+ error(Eperm);
+
+ omode = openmode(omode);
+ eg = envgrp(c);
+
+ wlock(eg);
+ if(waserror()) {
+ wunlock(eg);
+ nexterror();
+ }
+
+ if(envlookup(eg, name, -1))
+ error(Eexist);
+
+ e = smalloc(sizeof(Evalue));
+ e->name = smalloc(strlen(name)+1);
+ strcpy(e->name, name);
+
+ if(eg->nent == eg->ment){
+ eg->ment += 32;
+ ent = smalloc(sizeof(eg->ent[0])*eg->ment);
+ if(eg->nent)
+ memmove(ent, eg->ent, sizeof(eg->ent[0])*eg->nent);
+ free(eg->ent);
+ eg->ent = ent;
+ }
+ e->qid.path = ++eg->path;
+ e->qid.vers = 0;
+ eg->vers++;
+ eg->ent[eg->nent++] = e;
+ c->qid = e->qid;
+
+ wunlock(eg);
+ poperror();
+
+ c->offset = 0;
+ c->mode = omode;
+ c->flag |= COPEN;
+}
+
+static void
+envremove(Chan *c)
+{
+ int i;
+ Egrp *eg;
+ Evalue *e;
+
+ if(c->qid.type & QTDIR)
+ error(Eperm);
+
+ eg = envgrp(c);
+ wlock(eg);
+ e = 0;
+ for(i=0; i<eg->nent; i++){
+ if(eg->ent[i]->qid.path == c->qid.path){
+ e = eg->ent[i];
+ eg->nent--;
+ eg->ent[i] = eg->ent[eg->nent];
+ eg->vers++;
+ break;
+ }
+ }
+ wunlock(eg);
+ if(e == 0)
+ error(Enonexist);
+ free(e->name);
+ if(e->value)
+ free(e->value);
+ free(e);
+}
+
+static void
+envclose(Chan *c)
+{
+ /*
+ * cclose can't fail, so errors from remove will be ignored.
+ * since permissions aren't checked,
+ * envremove can't not remove it if its there.
+ */
+ if(c->flag & CRCLOSE)
+ envremove(c);
+}
+
+static long
+envread(Chan *c, void *a, long n, vlong off)
+{
+ Egrp *eg;
+ Evalue *e;
+ ulong offset = off;
+
+ if(c->qid.type & QTDIR)
+ return devdirread(c, a, n, 0, 0, envgen);
+
+ eg = envgrp(c);
+ rlock(eg);
+ e = envlookup(eg, nil, c->qid.path);
+ if(e == 0) {
+ runlock(eg);
+ error(Enonexist);
+ }
+
+ if(offset > e->len) /* protects against overflow converting vlong to ulong */
+ n = 0;
+ else if(offset + n > e->len)
+ n = e->len - offset;
+ if(n <= 0)
+ n = 0;
+ else
+ memmove(a, e->value+offset, n);
+ runlock(eg);
+ return n;
+}
+
+static long
+envwrite(Chan *c, void *a, long n, vlong off)
+{
+ char *s;
+ ulong len;
+ Egrp *eg;
+ Evalue *e;
+ ulong offset = off;
+
+ if(n <= 0)
+ return 0;
+ if(offset > Maxenvsize || n > (Maxenvsize - offset))
+ error(Etoobig);
+
+ eg = envgrp(c);
+ wlock(eg);
+ e = envlookup(eg, nil, c->qid.path);
+ if(e == 0) {
+ wunlock(eg);
+ error(Enonexist);
+ }
+
+ len = offset+n;
+ if(len > e->len) {
+ s = smalloc(len);
+ if(e->value){
+ memmove(s, e->value, e->len);
+ free(e->value);
+ }
+ e->value = s;
+ e->len = len;
+ }
+ memmove(e->value+offset, a, n);
+ e->qid.vers++;
+ eg->vers++;
+ wunlock(eg);
+ return n;
+}
+
+Dev envdevtab = {
+ 'e',
+ "env",
+
+ devreset,
+ devinit,
+ devshutdown,
+ envattach,
+ envwalk,
+ envstat,
+ envopen,
+ envcreate,
+ envclose,
+ envread,
+ devbread,
+ envwrite,
+ devbwrite,
+ envremove,
+ devwstat,
+};
+
+void
+envcpy(Egrp *to, Egrp *from)
+{
+ int i;
+ Evalue *ne, *e;
+
+ rlock(from);
+ to->ment = (from->nent+31)&~31;
+ to->ent = smalloc(to->ment*sizeof(to->ent[0]));
+ for(i=0; i<from->nent; i++){
+ e = from->ent[i];
+ ne = smalloc(sizeof(Evalue));
+ ne->name = smalloc(strlen(e->name)+1);
+ strcpy(ne->name, e->name);
+ if(e->value){
+ ne->value = smalloc(e->len);
+ memmove(ne->value, e->value, e->len);
+ ne->len = e->len;
+ }
+ ne->qid.path = ++to->path;
+ to->ent[i] = ne;
+ }
+ to->nent = from->nent;
+ runlock(from);
+}
+
+void
+closeegrp(Egrp *eg)
+{
+ int i;
+ Evalue *e;
+
+ if(decref(eg) == 0){
+ for(i=0; i<eg->nent; i++){
+ e = eg->ent[i];
+ free(e->name);
+ if(e->value)
+ free(e->value);
+ free(e);
+ }
+ free(eg->ent);
+ free(eg);
+ }
+}
+
+static Egrp*
+envgrp(Chan *c)
+{
+ if(c->aux == nil)
+ return up->egrp;
+ return c->aux;
+}
+
+static int
+envwriteable(Chan *c)
+{
+ return iseve() || c->aux == nil;
+}
+
+/*
+ * to let the kernel set environment variables
+ */
+void
+ksetenv(char *ename, char *eval, int conf)
+{
+ Chan *c;
+ char buf[2*KNAMELEN];
+
+ snprint(buf, sizeof(buf), "#e%s/%s", conf?"c":"", ename);
+ c = namec(buf, Acreate, OWRITE, 0600);
+ devtab[c->type]->write(c, eval, strlen(eval), 0);
+ cclose(c);
+}
+
+/*
+ * Return a copy of configuration environment as a sequence of strings.
+ * The strings alternate between name and value. A zero length name string
+ * indicates the end of the list
+ */
+char *
+getconfenv(void)
+{
+ Egrp *eg = &confegrp;
+ Evalue *e;
+ char *p, *q;
+ int i, n;
+
+ rlock(eg);
+ if(waserror()) {
+ runlock(eg);
+ nexterror();
+ }
+
+ /* determine size */
+ n = 0;
+ for(i=0; i<eg->nent; i++){
+ e = eg->ent[i];
+ n += strlen(e->name) + e->len + 2;
+ }
+ p = malloc(n + 1);
+ if(p == nil)
+ error(Enomem);
+ q = p;
+ for(i=0; i<eg->nent; i++){
+ e = eg->ent[i];
+ strcpy(q, e->name);
+ q += strlen(q) + 1;
+ memmove(q, e->value, e->len);
+ q[e->len] = 0;
+ /* move up to the first null */
+ q += strlen(q) + 1;
+ }
+ *q = 0;
+
+ poperror();
+ runlock(eg);
+ return p;
+}
diff --git a/sys/src/9/port/devflash.c b/sys/src/9/port/devflash.c
new file mode 100755
index 000000000..87331ac53
--- /dev/null
+++ b/sys/src/9/port/devflash.c
@@ -0,0 +1,654 @@
+/*
+ * flash memory
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "../port/flashif.h"
+
+typedef struct Flashtype Flashtype;
+struct Flashtype {
+ char* name;
+ int (*reset)(Flash*);
+ Flashtype* next;
+};
+
+enum {
+ Nbanks = 2,
+};
+
+static struct
+{
+ Flash* card[Nbanks]; /* actual card type, reset for access */
+ Flashtype* types; /* possible card types */
+}flash;
+
+enum{
+ Qtopdir,
+ Qflashdir,
+ Qdata,
+ Qctl,
+};
+
+#define TYPE(q) ((ulong)(q) & 0xFF)
+#define PART(q) ((ulong)(q)>>8)
+#define QID(p,t) (((p)<<8) | (t))
+
+static Flashregion* flashregion(Flash*, ulong);
+static char* flashnewpart(Flash*, char*, ulong, ulong);
+static ulong flashaddr(Flash*, Flashpart*, char*);
+static void protect(Flash*, ulong);
+static void eraseflash(Flash*, Flashregion*, ulong);
+static long readflash(Flash*, void*, long, int);
+static long writeflash(Flash*, long, void*,int);
+
+static char Eprotect[] = "flash region protected";
+
+static int
+flash2gen(Chan *c, ulong p, Dir *dp)
+{
+ Flashpart *fp;
+ Flash *f;
+ Qid q;
+ int mode;
+
+ f = flash.card[c->dev];
+ fp = &f->part[PART(p)];
+ if(fp->name == nil)
+ return 0;
+ mkqid(&q, p, 0, QTFILE);
+ switch(TYPE(p)){
+ case Qdata:
+ mode = 0660;
+ if(f->write == nil)
+ mode = 0440;
+ devdir(c, q, fp->name, fp->end-fp->start, eve, mode, dp);
+ return 1;
+ case Qctl:
+ snprint(up->genbuf, sizeof(up->genbuf), "%sctl", fp->name);
+ devdir(c, q, up->genbuf, 0, eve, 0660, dp);
+ return 1;
+ default:
+ return -1;
+ }
+}
+
+static int
+flashgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
+{
+ Qid q;
+ char *n;
+
+ if(s == DEVDOTDOT){
+ mkqid(&q, QID(0, Qtopdir), 0, QTDIR);
+ n = "#F";
+ if(c->dev != 0){
+ sprint(up->genbuf, "#F%ld", c->dev);
+ n = up->genbuf;
+ }
+ devdir(c, q, n, 0, eve, 0555, dp);
+ return 1;
+ }
+ switch(TYPE(c->qid.path)){
+ case Qtopdir:
+ if(s != 0)
+ break;
+ mkqid(&q, QID(0, Qflashdir), 0, QTDIR);
+ n = "flash";
+ if(c->dev != 0){
+ sprint(up->genbuf, "flash%ld", c->dev);
+ n = up->genbuf;
+ }
+ devdir(c, q, n, 0, eve, 0555, dp);
+ return 1;
+ case Qflashdir:
+ if(s >= 2*nelem(flash.card[c->dev]->part))
+ return -1;
+ return flash2gen(c, QID(s>>1, s&1?Qctl:Qdata), dp);
+ case Qctl:
+ case Qdata:
+ return flash2gen(c, (ulong)c->qid.path, dp);
+ }
+ return -1;
+}
+
+static void
+flashreset(void)
+{
+ Flash *f;
+ Flashtype *t;
+ char *e;
+ int bank;
+
+ for(bank = 0; bank < Nbanks; bank++){
+ f = malloc(sizeof(*f));
+ if(f == nil){
+ print("#F%d: can't allocate Flash data\n", bank);
+ return;
+ }
+ f->cmask = ~(ulong)0;
+ if(archflashreset(bank, f) < 0 || f->type == nil ||
+ f->addr == nil){
+ free(f);
+ return;
+ }
+ for(t = flash.types; t != nil; t = t->next)
+ if(strcmp(f->type, t->name) == 0)
+ break;
+ if(t == nil){
+ iprint("#F%d: no flash driver for type %s (addr %p)\n",
+ bank, f->type, f->addr);
+ free(f);
+ return;
+ }
+ f->reset = t->reset;
+ f->protect = 1;
+ if(f->reset(f) == 0){
+ flash.card[bank] = f;
+ iprint("#F%d: %s addr %#p len %lud width %d interleave %d\n",
+// bank, f->type, PADDR(f->addr), f->size,
+ bank, f->type, f->addr, f->size,
+ f->width, f->interleave);
+ e = flashnewpart(f, "flash", 0, f->size);
+ if(e != nil)
+ panic("#F%d: couldn't init table: %s", bank, e);
+ }else
+ iprint("#F%d: %#p: reset failed (%s)\n",
+ bank, f->addr, f->type);
+ }
+}
+
+static Chan*
+flashattach(char *spec)
+{
+ Flash *f;
+ int bank;
+ Chan *c;
+
+ bank = strtol(spec, nil, 0);
+ if(bank < 0 || bank >= Nbanks ||
+ (f = flash.card[bank]) == nil ||
+ f->attach != nil && f->attach(f) < 0)
+ error(Enodev);
+ c = devattach('F', spec);
+ c->dev = bank;
+ return c;
+}
+
+static Walkqid*
+flashwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, nil, 0, flashgen);
+}
+
+static int
+flashstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, nil, 0, flashgen);
+}
+
+static Chan*
+flashopen(Chan *c, int omode)
+{
+ omode = openmode(omode);
+ switch(TYPE(c->qid.path)){
+ case Qdata:
+ case Qctl:
+ if(flash.card[c->dev] == nil)
+ error(Enodev);
+ break;
+ }
+ return devopen(c, omode, nil, 0, flashgen);
+}
+
+static void
+flashclose(Chan*)
+{
+}
+
+static long
+flashread(Chan *c, void *buf, long n, vlong offset)
+{
+ Flash *f;
+ Flashpart *fp;
+ Flashregion *r;
+ int i;
+ ulong start, end;
+ char *s, *o;
+
+ if(c->qid.type & QTDIR)
+ return devdirread(c, buf, n, nil, 0, flashgen);
+
+ f = flash.card[c->dev];
+ fp = &f->part[PART(c->qid.path)];
+ if(fp->name == nil)
+ error(Egreg);
+ switch(TYPE(c->qid.path)){
+ case Qdata:
+ offset += fp->start;
+ if(offset >= fp->end)
+ return 0;
+ if(offset+n > fp->end)
+ n = fp->end - offset;
+ n = readflash(f, buf, offset, n);
+ if(n < 0)
+ error(Eio);
+ return n;
+ case Qctl:
+ s = malloc(READSTR);
+ if(waserror()){
+ free(s);
+ nexterror();
+ }
+ o = seprint(s, s+READSTR, "%#2.2ux %#4.4ux %d %q\n",
+ f->id, f->devid, f->width, f->sort!=nil? f->sort: "nor");
+ for(i=0; i<f->nr; i++){
+ r = &f->regions[i];
+ if(r->start < fp->end && fp->start < r->end){
+ start = r->start;
+ if(fp->start > start)
+ start = fp->start;
+ end = r->end;
+ if(fp->end < end)
+ end = fp->end;
+ o = seprint(o, s+READSTR, "%#8.8lux %#8.8lux %#8.8lux",
+ start, end, r->erasesize);
+ if(r->pagesize)
+ o = seprint(o, s+READSTR, " %#8.8lux",
+ r->pagesize);
+ o = seprint(o, s+READSTR, "\n");
+ }
+ }
+ n = readstr(offset, buf, n, s);
+ poperror();
+ free(s);
+ return n;
+ }
+ error(Egreg);
+ return 0; /* not reached */
+}
+
+enum {
+ CMerase,
+ CMadd,
+ CMremove,
+ CMsync,
+ CMprotectboot,
+};
+
+static Cmdtab flashcmds[] = {
+ {CMerase, "erase", 2},
+ {CMadd, "add", 0},
+ {CMremove, "remove", 2},
+ {CMsync, "sync", 0},
+ {CMprotectboot, "protectboot", 0},
+};
+
+static long
+flashwrite(Chan *c, void *buf, long n, vlong offset)
+{
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ ulong addr, start, end;
+ char *e;
+ Flashpart *fp;
+ Flashregion *r;
+ Flash *f;
+
+ f = flash.card[c->dev];
+ fp = &f->part[PART(c->qid.path)];
+ if(fp->name == nil)
+ error(Egreg);
+ switch(TYPE(c->qid.path)){
+ case Qdata:
+ if(f->write == nil)
+ error(Eperm);
+ offset += fp->start;
+ if(offset >= fp->end)
+ return 0;
+ if(offset+n > fp->end)
+ n = fp->end - offset;
+ n = writeflash(f, offset, buf, n);
+ if(n < 0)
+ error(Eio);
+ return n;
+ case Qctl:
+ cb = parsecmd(buf, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, flashcmds, nelem(flashcmds));
+ switch(ct->index){
+ case CMerase:
+ if(strcmp(cb->f[1], "all") != 0){
+ addr = flashaddr(f, fp, cb->f[1]);
+ r = flashregion(f, addr);
+ if(r == nil)
+ error("nonexistent flash region");
+ if(addr%r->erasesize != 0)
+ error("invalid erase block address");
+ eraseflash(f, r, addr);
+ }else if(fp->start == 0 && fp->end == f->size &&
+ f->eraseall != nil){
+ eraseflash(f, nil, 0);
+ }else{
+ for(addr = fp->start; addr < fp->end;
+ addr += r->erasesize){
+ r = flashregion(f, addr);
+ if(r == nil)
+ error("nonexistent flash region");
+ if(addr%r->erasesize != 0)
+ error("invalid erase block address");
+ eraseflash(f, r, addr);
+ }
+ }
+ break;
+ case CMadd:
+ if(cb->nf < 3)
+ error(Ebadarg);
+ start = flashaddr(f, fp, cb->f[2]);
+ if(cb->nf > 3 && strcmp(cb->f[3], "end") != 0)
+ end = flashaddr(f, fp, cb->f[3]);
+ else
+ end = fp->end;
+ if(start > end || start >= fp->end || end > fp->end)
+ error(Ebadarg);
+ e = flashnewpart(f, cb->f[1], start, end);
+ if(e != nil)
+ error(e);
+ break;
+ case CMremove:
+ /* TO DO */
+ break;
+ case CMprotectboot:
+ if(cb->nf > 1 && strcmp(cb->f[1], "off") == 0)
+ f->protect = 0;
+ else
+ f->protect = 1;
+ break;
+ case CMsync:
+ /* TO DO? */
+ break;
+ default:
+ error(Ebadarg);
+ }
+ poperror();
+ free(cb);
+ return n;
+ }
+ error(Egreg);
+ return 0; /* not reached */
+}
+
+static char*
+flashnewpart(Flash *f, char *name, ulong start, ulong end)
+{
+ Flashpart *fp, *empty;
+ int i;
+
+ empty = nil;
+ for(i = 0; i < nelem(f->part); i++){
+ fp = &f->part[i];
+ if(fp->name == nil){
+ if(empty == nil)
+ empty = fp;
+ }else if(strcmp(fp->name, name) == 0)
+ return Eexist;
+ }
+ if((fp = empty) == nil)
+ return "partition table full";
+// fp->name = nil;
+ kstrdup(&fp->name, name);
+ if(fp->name == nil)
+ return Enomem;
+ fp->start = start;
+ fp->end = end;
+ return nil;
+}
+
+static ulong
+flashaddr(Flash *f, Flashpart *fp, char *s)
+{
+ Flashregion *r;
+ ulong addr;
+
+ addr = strtoul(s, &s, 0);
+ if(*s)
+ error(Ebadarg);
+ if(fp->name == nil)
+ error("partition removed");
+ addr += fp->start;
+ r = flashregion(f, addr);
+ if(r != nil && addr%r->erasesize != 0)
+ error("invalid erase unit address");
+ if(addr < fp->start || addr > fp->end || addr > f->size)
+ error(Ebadarg);
+ return addr;
+}
+
+static Flashregion*
+flashregion(Flash *f, ulong a)
+{
+ int i;
+ Flashregion *r;
+
+ for(i=0; i<f->nr; i++){
+ r = &f->regions[i];
+ if(r->start <= a && a < r->end)
+ return r;
+ }
+ return nil;
+}
+
+Dev flashdevtab = {
+ 'F',
+ "flash",
+
+ flashreset,
+ devinit,
+ devshutdown,
+ flashattach,
+ flashwalk,
+ flashstat,
+ flashopen,
+ devcreate,
+ flashclose,
+ flashread,
+ devbread,
+ flashwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+/*
+ * called by flash card types named in link section (eg, flashamd.c)
+ */
+void
+addflashcard(char *name, int (*reset)(Flash*))
+{
+ Flashtype *f, **l;
+
+ f = (Flashtype*)malloc(sizeof(*f));
+ f->name = name;
+ f->reset = reset;
+ f->next = nil;
+ for(l = &flash.types; *l != nil; l = &(*l)->next)
+ ;
+ *l = f;
+}
+
+static long
+readflash(Flash *f, void *buf, long offset, int n)
+{
+ int r, width, wmask;
+ uchar tmp[16];
+ uchar *p;
+ ulong o;
+
+ if(offset < 0 || offset+n > f->size)
+ error(Ebadarg);
+ qlock(f);
+ if(waserror()){
+ qunlock(f);
+ nexterror();
+ }
+ if(f->read != nil){
+ width = f->width;
+ wmask = width-1;
+ p = buf;
+ if(offset & wmask) {
+ o = offset & ~wmask;
+ if(f->read(f, o, (ulong*)tmp, width) < 0)
+ error(Eio);
+ memmove(tmp, (uchar*)f->addr + o, width);
+ for(; n > 0 && offset & wmask; n--)
+ *p++ = tmp[offset++ & wmask];
+ }
+ r = n & wmask;
+ n &= ~wmask;
+ if(n){
+ if(f->read(f, offset, (ulong*)p, n) < 0)
+ error(Eio);
+ offset += n;
+ p += n;
+ }
+ if(r){
+ if(f->read(f, offset, (ulong*)tmp, width))
+ error(Eio);
+ memmove(p, tmp, r);
+ }
+ }else
+ /* assumes hardware supports byte access */
+ memmove(buf, (uchar*)f->addr+offset, n);
+ poperror();
+ qunlock(f);
+ return n;
+}
+
+static long
+writeflash(Flash *f, long offset, void *buf, int n)
+{
+ uchar tmp[16];
+ uchar *p;
+ ulong o;
+ int r, width, wmask;
+ Flashregion *rg;
+
+ if(f->write == nil || offset < 0 || offset+n > f->size)
+ error(Ebadarg);
+ rg = flashregion(f, offset);
+ if(f->protect && rg != nil && rg->start == 0 && offset < rg->erasesize)
+ error(Eprotect);
+ width = f->width;
+ wmask = width-1;
+ qlock(f);
+ archflashwp(f, 0);
+ if(waserror()){
+ archflashwp(f, 1);
+ qunlock(f);
+ nexterror();
+ }
+ p = buf;
+ if(offset&wmask){
+ o = offset & ~wmask;
+ if(f->read != nil){
+ if(f->read(f, o, tmp, width) < 0)
+ error(Eio);
+ }else
+ memmove(tmp, (uchar*)f->addr+o, width);
+ for(; n > 0 && offset&wmask; n--)
+ tmp[offset++&wmask] = *p++;
+ if(f->write(f, o, tmp, width) < 0)
+ error(Eio);
+ }
+ r = n&wmask;
+ n &= ~wmask;
+ if(n){
+ if(f->write(f, offset, p, n) < 0)
+ error(Eio);
+ offset += n;
+ p += n;
+ }
+ if(r){
+ if(f->read != nil){
+ if(f->read(f, offset, tmp, width) < 0)
+ error(Eio);
+ }else
+ memmove(tmp, (uchar*)f->addr+offset, width);
+ memmove(tmp, p, r);
+ if(f->write(f, offset, tmp, width) < 0)
+ error(Eio);
+ }
+ poperror();
+ archflashwp(f, 1);
+ qunlock(f);
+ return n;
+}
+
+static void
+eraseflash(Flash *f, Flashregion *r, ulong addr)
+{
+ int rv;
+
+ if(f->protect && r != nil && r->start == 0 && addr < r->erasesize)
+ error(Eprotect);
+ qlock(f);
+ archflashwp(f, 0);
+ if(waserror()){
+ archflashwp(f, 1);
+ qunlock(f);
+ nexterror();
+ }
+ if(r == nil){
+ if(f->eraseall != nil)
+ rv = f->eraseall(f);
+ else
+ rv = -1;
+ }else
+ rv = f->erasezone(f, r, addr);
+ if(rv < 0)
+ error(Eio);
+ poperror();
+ archflashwp(f, 1);
+ qunlock(f);
+}
+
+/*
+ * flash access taking width and interleave into account
+ */
+int
+flashget(Flash *f, ulong a)
+{
+ switch(f->width){
+ default:
+ return ((uchar*)f->addr)[a<<f->bshift];
+ case 2:
+ return ((ushort*)f->addr)[a];
+ case 4:
+ return ((ulong*)f->addr)[a];
+ }
+}
+
+void
+flashput(Flash *f, ulong a, int v)
+{
+ switch(f->width){
+ default:
+ ((uchar*)f->addr)[a<<f->bshift] = v;
+ break;
+ case 2:
+ ((ushort*)f->addr)[a] = v;
+ break;
+ case 4:
+ ((ulong*)f->addr)[a] = v;
+ break;
+ }
+ coherence();
+}
diff --git a/sys/src/9/port/devfs.c b/sys/src/9/port/devfs.c
new file mode 100755
index 000000000..8e5fa5606
--- /dev/null
+++ b/sys/src/9/port/devfs.c
@@ -0,0 +1,1266 @@
+/*
+ * File system devices.
+ * Follows device config in Ken's file server.
+ * Builds mirrors, concatenations, interleavings, and partitions
+ * of devices out of other (inner) devices.
+ * It is ok if inner devices are provided by this driver.
+ *
+ * Built files are grouped on different directories
+ * (called trees, and used to represent disks).
+ * The "#k/fs" tree is always available and never goes away.
+ * Configuration changes happen only while no I/O is in progress.
+ *
+ * Default sector size is one byte unless changed by the "disk" ctl.
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+enum
+{
+ Fnone,
+ Fmirror, /* mirror of others */
+ Fcat, /* catenation of others */
+ Finter, /* interleaving of others */
+ Fpart, /* part of other */
+ Fclear, /* start over */
+ Fdel, /* delete a configure device */
+ Fdisk, /* set default tree and sector sz*/
+
+ Sectorsz = 1,
+ Blksize = 8*1024, /* for Finter only */
+
+ Incr = 5, /* Increments for the dev array */
+
+ /*
+ * All qids are decorated with the tree number.
+ * #k/fs is tree number 0, is automatically added and
+ * its first qid is for the ctl file. It never goes away.
+ */
+ Qtop = 0, /* #k */
+ Qdir, /* directory (#k/fs) */
+ Qctl, /* ctl, only for #k/fs/ctl */
+ Qfirst, /* first qid assigned for device */
+
+ Iswrite = 0,
+ Isread,
+
+ Optional = 0,
+ Mustexist,
+
+ /* tunable parameters */
+ Maxconf = 4*1024, /* max length for config */
+ Ndevs = 32, /* max. inner devs per command */
+ Ntrees = 128, /* max. number of trees */
+ Maxretries = 3, /* max. retries of i/o errors */
+ Retrypause = 5000, /* ms. to pause between retries */
+};
+
+typedef struct Inner Inner;
+typedef struct Fsdev Fsdev;
+typedef struct Tree Tree;
+
+struct Inner
+{
+ char *iname; /* inner device name */
+ vlong isize; /* size of inner device */
+ Chan *idev; /* inner device */
+};
+
+struct Fsdev
+{
+ Ref; /* one per Chan doing I/O */
+ int gone; /* true if removed */
+ int vers; /* qid version for this device */
+ int type; /* Fnone, Fmirror, ... */
+ char *name; /* name for this fsdev */
+ Tree* tree; /* where the device is kept */
+ vlong size; /* min(inner[X].isize) */
+ vlong start; /* start address (for Fpart) */
+ uint ndevs; /* number of inner devices */
+ Inner *inner[Ndevs]; /* inner devices */
+};
+
+struct Tree
+{
+ char *name; /* name for #k/<name> */
+ Fsdev **devs; /* devices in dir. */
+ uint ndevs; /* number of devices */
+ uint nadevs; /* number of allocated devices in devs */
+};
+
+#define dprint if(debug)print
+
+extern Dev fsdevtab; /* forward */
+
+static RWlock lck; /* r: use devices; w: change config */
+static Tree fstree; /* The main "fs" tree. Never goes away */
+static Tree *trees[Ntrees]; /* internal representation of config */
+static int ntrees; /* max number of trees */
+static int qidvers;
+static char *disk; /* default tree name used */
+static char *source; /* default inner device used */
+static int sectorsz = Sectorsz; /* default sector size */
+static char confstr[Maxconf]; /* textual configuration */
+
+static int debug;
+
+static char cfgstr[] = "fsdev:\n";
+
+static Qid tqid = {Qtop, 0, QTDIR};
+static Qid cqid = {Qctl, 0, 0};
+
+static char* tnames[] = {
+ [Fmirror] "mirror",
+ [Fcat] "cat",
+ [Finter] "inter",
+ [Fpart] "part",
+};
+
+static Cmdtab configs[] = {
+ Fmirror,"mirror", 0,
+ Fcat, "cat", 0,
+ Finter, "inter", 0,
+ Fpart, "part", 0,
+ Fclear, "clear", 1,
+ Fdel, "del", 2,
+ Fdisk, "disk", 0,
+};
+
+static char Egone[] = "device is gone"; /* file has been removed */
+
+static char*
+seprintdev(char *s, char *e, Fsdev *mp)
+{
+ int i;
+
+ if(mp == nil)
+ return seprint(s, e, "<null Fsdev>");
+ if(mp->type < 0 || mp->type >= nelem(tnames) || tnames[mp->type] == nil)
+ return seprint(s, e, "bad device type %d\n", mp->type);
+
+ s = strecpy(s, e, tnames[mp->type]);
+ if(mp->tree != &fstree)
+ s = seprint(s, e, " %s/%s", mp->tree->name, mp->name);
+ else
+ s = seprint(s, e, " %s", mp->name);
+ for(i = 0; i < mp->ndevs; i++)
+ s = seprint(s, e, " %s", mp->inner[i]->iname);
+ switch(mp->type){
+ case Fmirror:
+ case Fcat:
+ case Finter:
+ s = strecpy(s, e, "\n");
+ break;
+ case Fpart:
+ s = seprint(s, e, " %ulld %ulld\n", mp->start, mp->size);
+ break;
+ default:
+ panic("#k: seprintdev bug");
+ }
+ return s;
+}
+
+static vlong
+mkpath(int tree, int devno)
+{
+ return (tree&0xFFFF)<<16 | devno&0xFFFF;
+}
+
+static int
+path2treeno(int q)
+{
+ return q>>16 & 0xFFFF;
+}
+
+static int
+path2devno(int q)
+{
+ return q & 0xFFFF;
+}
+
+static Tree*
+gettree(int i, int mustexist)
+{
+ dprint("gettree %d\n", i);
+ if(i < 0)
+ panic("#k: bug: bad tree index %d in gettree", i);
+ if(i >= ntrees || trees[i] == nil)
+ if(mustexist)
+ error(Enonexist);
+ else
+ return nil;
+ return trees[i];
+}
+
+static Fsdev*
+getdev(Tree *t, int i, int mustexist)
+{
+ dprint("getdev %d\n", i);
+ if(i < 0)
+ panic("#k: bug: bad dev index %d in getdev", i);
+ if(i >= t->nadevs || t->devs[i] == nil)
+ if(mustexist)
+ error(Enonexist);
+ else
+ return nil;
+ return t->devs[i];
+}
+
+static Fsdev*
+path2dev(int q)
+{
+ Tree *t;
+
+ dprint("path2dev %ux\n", q);
+ t = gettree(path2treeno(q), Mustexist);
+ return getdev(t, path2devno(q) - Qfirst, Mustexist);
+}
+
+static Tree*
+treealloc(char *name)
+{
+ int i;
+ Tree *t;
+
+ dprint("treealloc %s\n", name);
+ for(i = 0; i < nelem(trees); i++)
+ if(trees[i] == nil)
+ break;
+ if(i == nelem(trees))
+ return nil;
+ t = trees[i] = mallocz(sizeof(Tree), 1);
+ if(t == nil)
+ return nil;
+ if(i == ntrees)
+ ntrees++;
+ kstrdup(&t->name, name);
+ return t;
+}
+
+static Tree*
+lookuptree(char *name)
+{
+ int i;
+
+ dprint("lookuptree %s\n", name);
+ for(i = 0; i < ntrees; i++)
+ if(trees[i] != nil && strcmp(trees[i]->name, name) == 0)
+ return trees[i];
+ return nil;
+}
+
+static Fsdev*
+devalloc(Tree *t, char *name)
+{
+ int i, ndevs;
+ Fsdev *mp, **devs;
+
+ dprint("devalloc %s %s\n", t->name, name);
+ mp = mallocz(sizeof(Fsdev), 1);
+ if(mp == nil)
+ return nil;
+ for(i = 0; i < t->nadevs; i++)
+ if(t->devs[i] == nil)
+ break;
+ if(i >= t->nadevs){
+ if(t->nadevs % Incr == 0){
+ ndevs = t->nadevs + Incr;
+ devs = realloc(t->devs, ndevs * sizeof(Fsdev*));
+ if(devs == nil){
+ free(mp);
+ return nil;
+ }
+ t->devs = devs;
+ }
+ t->devs[t->nadevs] = nil;
+ t->nadevs++;
+ }
+ kstrdup(&mp->name, name);
+ mp->vers = ++qidvers;
+ mp->tree = t;
+ t->devs[i] = mp;
+ t->ndevs++;
+ return mp;
+}
+
+static void
+deltree(Tree *t)
+{
+ int i;
+
+ dprint("deltree %s\n", t->name);
+ for(i = 0; i < ntrees; i++)
+ if(trees[i] == t){
+ if(i > 0){ /* "fs" never goes away */
+ free(t->name);
+ free(t->devs);
+ free(t);
+ trees[i] = nil;
+ }
+ return;
+ }
+ panic("#k: deltree: bug: tree not found");
+}
+
+/*
+ * A device is gone and we know that all its users are gone.
+ * A tree is gone when all its devices are gone ("fs" is never gone).
+ * Must close devices outside locks, so we could nest our own devices.
+ */
+static void
+mdeldev(Fsdev *mp)
+{
+ int i;
+ Inner *in;
+ Tree *t;
+
+ dprint("deldev %s gone %d ref %uld\n", mp->name, mp->gone, mp->ref);
+
+ mp->gone = 1;
+ mp->vers = ++qidvers;
+
+ wlock(&lck);
+ t = mp->tree;
+ for(i = 0; i < t->nadevs; i++)
+ if(t->devs[i] == mp){
+ t->devs[i] = nil;
+ t->ndevs--;
+ if(t->ndevs == 0)
+ deltree(t);
+ break;
+ }
+ wunlock(&lck);
+
+ free(mp->name);
+ for(i = 0; i < mp->ndevs; i++){
+ in = mp->inner[i];
+ if(in->idev != nil)
+ cclose(in->idev);
+ free(in->iname);
+ free(in);
+ }
+ if(debug)
+ memset(mp, 9, sizeof *mp); /* poison */
+ free(mp);
+}
+
+/*
+ * Delete one or all devices in one or all trees.
+ */
+static void
+mdelctl(char *tname, char *dname)
+{
+ int i, alldevs, alltrees, some;
+ Fsdev *mp;
+ Tree *t;
+
+ dprint("delctl %s\n", dname);
+ alldevs = strcmp(dname, "*") == 0;
+ alltrees = strcmp(tname, "*") == 0;
+ some = 0;
+Again:
+ wlock(&lck);
+ for(i = 0; i < ntrees; i++){
+ t = trees[i];
+ if(t == nil)
+ continue;
+ if(alltrees == 0 && strcmp(t->name, tname) != 0)
+ continue;
+ for(i = 0; i < t->nadevs; i++){
+ mp = t->devs[i];
+ if(t->devs[i] == nil)
+ continue;
+ if(alldevs == 0 && strcmp(mp->name, dname) != 0)
+ continue;
+ /*
+ * Careful: must close outside locks and that
+ * may change the file tree we are looking at.
+ */
+ some++;
+ mp->gone = 1;
+ if(mp->ref == 0){
+ incref(mp); /* keep it there */
+ wunlock(&lck);
+ mdeldev(mp);
+ goto Again; /* tree can change */
+ }
+ }
+ }
+ wunlock(&lck);
+ if(some == 0 && alltrees == 0)
+ error(Enonexist);
+}
+
+static void
+setdsize(Fsdev* mp, vlong *ilen)
+{
+ int i;
+ vlong inlen;
+ Inner *in;
+
+ dprint("setdsize %s\n", mp->name);
+ for (i = 0; i < mp->ndevs; i++){
+ in = mp->inner[i];
+ in->isize = ilen[i];
+ inlen = in->isize;
+ switch(mp->type){
+ case Finter:
+ /* truncate to multiple of Blksize */
+ inlen &= ~(Blksize-1);
+ in->isize = inlen;
+ /* fall through */
+ case Fmirror:
+ /* use size of smallest inner device */
+ if (mp->size == 0 || mp->size > inlen)
+ mp->size = inlen;
+ break;
+ case Fcat:
+ mp->size += inlen;
+ break;
+ case Fpart:
+ if(mp->start > inlen)
+ error("partition starts after device end");
+ if(inlen < mp->start + mp->size){
+ print("#k: %s: partition truncated from "
+ "%lld to %lld bytes\n", mp->name,
+ mp->size, inlen - mp->start);
+ mp->size = inlen - mp->start;
+ }
+ break;
+ }
+ }
+ if(mp->type == Finter)
+ mp->size *= mp->ndevs;
+}
+
+static void
+validdevname(Tree *t, char *dname)
+{
+ int i;
+
+ for(i = 0; i < t->nadevs; i++)
+ if(t->devs[i] != nil && strcmp(t->devs[i]->name, dname) == 0)
+ error(Eexist);
+}
+
+static void
+parseconfig(char *a, long n, Cmdbuf **cbp, Cmdtab **ctp)
+{
+ Cmdbuf *cb;
+ Cmdtab *ct;
+
+ *cbp = cb = parsecmd(a, n);
+ *ctp = ct = lookupcmd(cb, configs, nelem(configs));
+
+ cb->f++; /* skip command */
+ cb->nf--;
+ switch(ct->index){
+ case Fmirror:
+ case Fcat:
+ case Finter:
+ if(cb->nf < 2)
+ error("too few arguments for ctl");
+ if(cb->nf - 1 > Ndevs)
+ error("too many devices in ctl");
+ break;
+ case Fdisk:
+ if(cb->nf < 1 || cb->nf > 3)
+ error("ctl usage: disk name [sz dev]");
+ break;
+ case Fpart:
+ if(cb->nf != 4 && (cb->nf != 3 || source == nil))
+ error("ctl usage: part new [file] off len");
+ break;
+ }
+}
+
+static void
+parsename(char *name, char *disk, char **tree, char **dev)
+{
+ char *slash;
+
+ slash = strchr(name, '/');
+ if(slash == nil){
+ if(disk != nil)
+ *tree = disk;
+ else
+ *tree = "fs";
+ *dev = name;
+ }else{
+ *tree = name;
+ *slash++ = 0;
+ *dev = slash;
+ }
+ validname(*tree, 0);
+ validname(*dev, 0);
+}
+
+static vlong
+getlen(Chan *c)
+{
+ uchar buf[128]; /* old DIRLEN plus a little should be plenty */
+ Dir d;
+ long l;
+
+ l = devtab[c->type]->stat(c, buf, sizeof buf);
+ convM2D(buf, l, &d, nil);
+ return d.length;
+}
+
+/*
+ * Process a single line of configuration,
+ * often of the form "cmd newname idev0 idev1".
+ * locking is tricky, because we need a write lock to
+ * add/remove devices yet adding/removing them may lead
+ * to calls to this driver that require a read lock (when
+ * inner devices are also provided by us).
+ */
+static void
+mconfig(char* a, long n)
+{
+ int i;
+ vlong size, start;
+ vlong *ilen;
+ char *tname, *dname, *fakef[4];
+ Chan **idev;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ Fsdev *mp;
+ Inner *inprv;
+ Tree *t;
+
+ /* ignore comments & empty lines */
+ if (*a == '\0' || *a == '#' || *a == '\n')
+ return;
+
+ dprint("mconfig\n");
+ size = 0;
+ start = 0;
+ mp = nil;
+ cb = nil;
+ idev = nil;
+ ilen = nil;
+
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+
+ parseconfig(a, n, &cb, &ct);
+ switch (ct->index) {
+ case Fdisk:
+ kstrdup(&disk, cb->f[0]);
+ if(cb->nf >= 2)
+ sectorsz = strtoul(cb->f[1], 0, 0);
+ else
+ sectorsz = Sectorsz;
+ if(cb->nf == 3)
+ kstrdup(&source, cb->f[2]);
+ else{
+ free(source);
+ source = nil;
+ }
+ poperror();
+ free(cb);
+ return;
+ case Fclear:
+ poperror();
+ free(cb);
+ mdelctl("*", "*"); /* del everything */
+ return;
+ case Fpart:
+ if(cb->nf == 3){
+ /*
+ * got a request in the format of sd(3),
+ * pretend we got one in our format.
+ * later we change end to be len.
+ */
+ fakef[0] = cb->f[0];
+ fakef[1] = source;
+ fakef[2] = cb->f[1];
+ fakef[3] = cb->f[2];
+ cb->f = fakef;
+ cb->nf = 4;
+ }
+ start = strtoll(cb->f[2], nil, 10);
+ size = strtoll(cb->f[3], nil, 10);
+ if(cb->f == fakef)
+ size -= start; /* it was end */
+ cb->nf -= 2;
+ break;
+ }
+ parsename(cb->f[0], disk, &tname, &dname);
+ for(i = 1; i < cb->nf; i++)
+ validname(cb->f[i], 1);
+
+ if(ct->index == Fdel){
+ mdelctl(tname, dname);
+ poperror();
+ free(cb);
+ return;
+ }
+
+ /*
+ * Open all inner devices while we have only a read lock.
+ */
+ poperror();
+ rlock(&lck);
+ if(waserror()){
+ runlock(&lck);
+Fail:
+ for(i = 1; i < cb->nf; i++)
+ if(idev != nil && idev[i-1] != nil)
+ cclose(idev[i]);
+ if(mp != nil)
+ mdeldev(mp);
+ free(idev);
+ free(ilen);
+ free(cb);
+ nexterror();
+ }
+ idev = smalloc(sizeof(Chan*) * Ndevs);
+ ilen = smalloc(sizeof(vlong) * Ndevs);
+ for(i = 1; i < cb->nf; i++){
+ idev[i-1] = namec(cb->f[i], Aopen, ORDWR, 0);
+ ilen[i-1] = getlen(idev[i-1]);
+ }
+ poperror();
+ runlock(&lck);
+
+ /*
+ * Get a write lock and add the device if we can.
+ */
+ wlock(&lck);
+ if(waserror()){
+ wunlock(&lck);
+ goto Fail;
+ }
+
+ t = lookuptree(tname);
+ if(t != nil)
+ validdevname(t, dname);
+ else
+ t = treealloc(tname);
+ if(t == nil)
+ error("no more trees");
+ mp = devalloc(t, dname);
+ if(mp == nil){
+ if(t->ndevs == 0) /* it was created for us */
+ deltree(t); /* but we will not mdeldev() */
+ error(Enomem);
+ }
+
+ mp->type = ct->index;
+ if(mp->type == Fpart){
+ mp->start = start * sectorsz;
+ mp->size = size * sectorsz;
+ }
+ for(i = 1; i < cb->nf; i++){
+ inprv = mp->inner[i-1] = mallocz(sizeof(Inner), 1);
+ if(inprv == nil)
+ error(Enomem);
+ mp->ndevs++;
+ kstrdup(&inprv->iname, cb->f[i]);
+ inprv->idev = idev[i-1];
+ idev[i-1] = nil;
+ }
+ setdsize(mp, ilen);
+
+ poperror();
+ wunlock(&lck);
+ free(idev);
+ free(ilen);
+ free(cb);
+}
+
+static void
+rdconf(void)
+{
+ int mustrd;
+ char *c, *e, *p, *s;
+ Chan *cc;
+ static int configed;
+
+ /* only read config file once */
+ if (configed)
+ return;
+ configed = 1;
+
+ dprint("rdconf\n");
+ /* add the std "fs" tree */
+ trees[0] = &fstree;
+ ntrees++;
+ fstree.name = "fs";
+
+ /* identify the config file */
+ s = getconf("fsconfig");
+ if (s == nil){
+ mustrd = 0;
+ s = "/dev/sdC0/fscfg";
+ } else
+ mustrd = 1;
+
+ /* read it */
+ cc = nil;
+ c = nil;
+ if (waserror()){
+ if (cc != nil)
+ cclose(cc);
+ if (c)
+ free(c);
+ if (!mustrd)
+ return;
+ nexterror();
+ }
+ cc = namec(s, Aopen, OREAD, 0);
+ devtab[cc->type]->read(cc, confstr, sizeof confstr, 0);
+ cclose(cc);
+ cc = nil;
+
+ /* validate, copy and erase config; mconfig will repopulate confstr */
+ if (strncmp(confstr, cfgstr, sizeof cfgstr - 1) != 0)
+ error("bad #k config, first line must be: 'fsdev:\\n'");
+ kstrdup(&c, confstr + sizeof cfgstr - 1);
+ memset(confstr, 0, sizeof confstr);
+
+ /* process config copy one line at a time */
+ for (p = c; p != nil && *p != '\0'; p = e){
+ e = strchr(p, '\n');
+ if (e == nil)
+ e = p + strlen(p);
+ else
+ e++;
+ mconfig(p, e - p);
+ }
+ USED(cc); /* until now, can be used in waserror clause */
+ poperror();
+}
+
+static int
+mgen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
+{
+ int treeno;
+ Fsdev *mp;
+ Qid qid;
+ Tree *t;
+
+ dprint("mgen %#ullx %d\n", c->qid.path, i);
+ qid.type = QTDIR;
+ qid.vers = 0;
+ if(c->qid.path == Qtop){
+ if(i == DEVDOTDOT){
+ devdir(c, tqid, "#k", 0, eve, DMDIR|0775, dp);
+ return 1;
+ }
+ t = gettree(i, Optional);
+ if(t == nil){
+ dprint("no\n");
+ return -1;
+ }
+ qid.path = mkpath(i, Qdir);
+ devdir(c, qid, t->name, 0, eve, DMDIR|0775, dp);
+ return 1;
+ }
+
+ treeno = path2treeno(c->qid.path);
+ t = gettree(treeno, Optional);
+ if(t == nil){
+ dprint("no\n");
+ return -1;
+ }
+ if((c->qid.type & QTDIR) != 0){
+ if(i == DEVDOTDOT){
+ devdir(c, tqid, "#k", 0, eve, DMDIR|0775, dp);
+ return 1;
+ }
+ if(treeno == 0){
+ /* take care of #k/fs/ctl */
+ if(i == 0){
+ devdir(c, cqid, "ctl", 0, eve, 0664, dp);
+ return 1;
+ }
+ i--;
+ }
+ mp = getdev(t, i, Optional);
+ if(mp == nil){
+ dprint("no\n");
+ return -1;
+ }
+ qid.type = QTFILE;
+ qid.vers = mp->vers;
+ qid.path = mkpath(treeno, Qfirst+i);
+ devdir(c, qid, mp->name, mp->size, eve, 0664, dp);
+ return 1;
+ }
+
+ if(i == DEVDOTDOT){
+ qid.path = mkpath(treeno, Qdir);
+ devdir(c, qid, t->name, 0, eve, DMDIR|0775, dp);
+ return 1;
+ }
+ dprint("no\n");
+ return -1;
+}
+
+static Chan*
+mattach(char *spec)
+{
+ dprint("mattach\n");
+ return devattach(fsdevtab.dc, spec);
+}
+
+static Walkqid*
+mwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ Walkqid *wq;
+
+ rdconf();
+
+ dprint("mwalk %llux\n", c->qid.path);
+ rlock(&lck);
+ if(waserror()){
+ runlock(&lck);
+ nexterror();
+ }
+ wq = devwalk(c, nc, name, nname, 0, 0, mgen);
+ poperror();
+ runlock(&lck);
+ return wq;
+}
+
+static int
+mstat(Chan *c, uchar *db, int n)
+{
+ int p;
+ Dir d;
+ Fsdev *mp;
+ Qid q;
+ Tree *t;
+
+ dprint("mstat %llux\n", c->qid.path);
+ rlock(&lck);
+ if(waserror()){
+ runlock(&lck);
+ nexterror();
+ }
+ p = c->qid.path;
+ memset(&d, 0, sizeof d);
+ switch(p){
+ case Qtop:
+ devdir(c, tqid, "#k", 0, eve, DMDIR|0775, &d);
+ break;
+ case Qctl:
+ devdir(c, cqid, "ctl", 0, eve, 0664, &d);
+ break;
+ default:
+ t = gettree(path2treeno(p), Mustexist);
+ if(c->qid.type & QTDIR)
+ devdir(c, c->qid, t->name, 0, eve, DMDIR|0775, &d);
+ else{
+ mp = getdev(t, path2devno(p) - Qfirst, Mustexist);
+ q = c->qid;
+ q.vers = mp->vers;
+ devdir(c, q, mp->name, mp->size, eve, 0664, &d);
+ }
+ }
+ n = convD2M(&d, db, n);
+ if (n == 0)
+ error(Ebadarg);
+ poperror();
+ runlock(&lck);
+ return n;
+}
+
+static Chan*
+mopen(Chan *c, int omode)
+{
+ int q;
+ Fsdev *mp;
+
+ dprint("mopen %llux\n", c->qid.path);
+ if((c->qid.type & QTDIR) && omode != OREAD)
+ error(Eperm);
+ if(c->qid.path != Qctl && (c->qid.type&QTDIR) == 0){
+ rlock(&lck);
+ if(waserror()){
+ runlock(&lck);
+ nexterror();
+ }
+ q = c->qid.path;
+ mp = path2dev(q);
+ if(mp->gone)
+ error(Egone);
+ incref(mp);
+ poperror();
+ runlock(&lck);
+ }
+ /*
+ * Our mgen does not return the info for the qid
+ * but only for its children. Don't use devopen here.
+ */
+ c->offset = 0;
+ c->mode = openmode(omode & ~OTRUNC);
+ c->flag |= COPEN;
+ return c;
+}
+
+static void
+mclose(Chan *c)
+{
+ int mustdel, q;
+ Fsdev *mp;
+
+ dprint("mclose %llux\n", c->qid.path);
+ if(c->qid.type & QTDIR || !(c->flag & COPEN))
+ return;
+ rlock(&lck);
+ if(waserror()){
+ runlock(&lck);
+ nexterror();
+ }
+ mustdel = 0;
+ mp = nil;
+ q = c->qid.path;
+ if(q == Qctl){
+ free(disk);
+ disk = nil; /* restore defaults */
+ free(source);
+ source = nil;
+ sectorsz = Sectorsz;
+ }else{
+ mp = path2dev(q);
+ if(mp->gone != 0 && mp->ref == 1)
+ mustdel = 1;
+ else
+ decref(mp);
+ }
+ poperror();
+ runlock(&lck);
+ if(mustdel)
+ mdeldev(mp);
+}
+
+static long
+io(Fsdev *mp, Inner *in, int isread, void *a, long l, vlong off)
+{
+ long wl;
+ Chan *mc;
+
+ mc = in->idev;
+ if(mc == nil)
+ error(Egone);
+ if (waserror()) {
+ print("#k: %s: byte %,lld count %ld (of #k/%s): %s error: %s\n",
+ in->iname, off, l, mp->name, (isread? "read": "write"),
+ (up && up->errstr? up->errstr: ""));
+ nexterror();
+ }
+ if (isread)
+ wl = devtab[mc->type]->read(mc, a, l, off);
+ else
+ wl = devtab[mc->type]->write(mc, a, l, off);
+ poperror();
+ return wl;
+}
+
+/* NB: a transfer could span multiple inner devices */
+static long
+catio(Fsdev *mp, int isread, void *a, long n, vlong off)
+{
+ int i;
+ long l, res;
+ Inner *in;
+
+ if(debug)
+ print("catio %d %p %ld %lld\n", isread, a, n, off);
+ res = n;
+ for (i = 0; n > 0 && i < mp->ndevs; i++){
+ in = mp->inner[i];
+ if (off >= in->isize){
+ off -= in->isize;
+ continue; /* not there yet */
+ }
+ if (off + n > in->isize)
+ l = in->isize - off;
+ else
+ l = n;
+ if(debug)
+ print("\tdev %d %p %ld %lld\n", i, a, l, off);
+
+ if (io(mp, in, isread, a, l, off) != l)
+ error(Eio);
+
+ a = (char*)a + l;
+ off = 0;
+ n -= l;
+ }
+ if(debug)
+ print("\tres %ld\n", res - n);
+ return res - n;
+}
+
+static long
+interio(Fsdev *mp, int isread, void *a, long n, vlong off)
+{
+ int i;
+ long boff, res, l, wl, wsz;
+ vlong woff, blk, mblk;
+
+ blk = off / Blksize;
+ boff = off % Blksize;
+ wsz = Blksize - boff;
+ res = n;
+ while(n > 0){
+ mblk = blk / mp->ndevs;
+ i = blk % mp->ndevs;
+ woff = mblk*Blksize + boff;
+ if (n > wsz)
+ l = wsz;
+ else
+ l = n;
+
+ wl = io(mp, mp->inner[i], isread, a, l, woff);
+ if (wl != l)
+ error(Eio);
+
+ blk++;
+ boff = 0;
+ wsz = Blksize;
+ a = (char*)a + l;
+ n -= l;
+ }
+ return res;
+}
+
+static char*
+seprintconf(char *s, char *e)
+{
+ int i, j;
+ Tree *t;
+
+ *s = 0;
+ for(i = 0; i < ntrees; i++){
+ t = trees[i];
+ if(t != nil)
+ for(j = 0; j < t->nadevs; j++)
+ if(t->devs[j] != nil)
+ s = seprintdev(s, e, t->devs[j]);
+ }
+ return s;
+}
+
+static long
+mread(Chan *c, void *a, long n, vlong off)
+{
+ int i, retry;
+ long l, res;
+ Fsdev *mp;
+ Tree *t;
+
+ dprint("mread %llux\n", c->qid.path);
+ rlock(&lck);
+ if(waserror()){
+ runlock(&lck);
+ nexterror();
+ }
+ res = -1;
+ if(c->qid.type & QTDIR){
+ res = devdirread(c, a, n, 0, 0, mgen);
+ goto Done;
+ }
+ if(c->qid.path == Qctl){
+ seprintconf(confstr, confstr + sizeof(confstr));
+ res = readstr((long)off, a, n, confstr);
+ goto Done;
+ }
+
+ t = gettree(path2treeno(c->qid.path), Mustexist);
+ mp = getdev(t, path2devno(c->qid.path) - Qfirst, Mustexist);
+
+ if(off >= mp->size){
+ res = 0;
+ goto Done;
+ }
+ if(off + n > mp->size)
+ n = mp->size - off;
+ if(n == 0){
+ res = 0;
+ goto Done;
+ }
+
+ switch(mp->type){
+ case Fcat:
+ res = catio(mp, Isread, a, n, off);
+ break;
+ case Finter:
+ res = interio(mp, Isread, a, n, off);
+ break;
+ case Fpart:
+ res = io(mp, mp->inner[0], Isread, a, n, mp->start + off);
+ break;
+ case Fmirror:
+ retry = 0;
+ do {
+ if (retry > 0) {
+ print("#k/%s: retry %d read for byte %,lld "
+ "count %ld: %s\n", mp->name, retry, off,
+ n, (up && up->errstr? up->errstr: ""));
+ /*
+ * pause before retrying in case it's due to
+ * a transient bus or controller problem.
+ */
+ tsleep(&up->sleep, return0, 0, Retrypause);
+ }
+ for (i = 0; i < mp->ndevs; i++){
+ if (waserror())
+ continue;
+ l = io(mp, mp->inner[i], Isread, a, n, off);
+ poperror();
+ if (l >= 0){
+ res = l;
+ break; /* read a good copy */
+ }
+ }
+ } while (i == mp->ndevs && ++retry <= Maxretries);
+ if (retry > Maxretries) {
+ /* no mirror had a good copy of the block */
+ print("#k/%s: byte %,lld count %ld: CAN'T READ "
+ "from mirror: %s\n", mp->name, off, n,
+ (up && up->errstr? up->errstr: ""));
+ error(Eio);
+ } else if (retry > 0)
+ print("#k/%s: byte %,lld count %ld: retry read OK "
+ "from mirror: %s\n", mp->name, off, n,
+ (up && up->errstr? up->errstr: ""));
+ break;
+ }
+Done:
+ poperror();
+ runlock(&lck);
+ return res;
+}
+
+static long
+mwrite(Chan *c, void *a, long n, vlong off)
+{
+ int i, allbad, anybad, retry;
+ long l, res;
+ Fsdev *mp;
+ Tree *t;
+
+ dprint("mwrite %llux\n", c->qid.path);
+ if (c->qid.type & QTDIR)
+ error(Eisdir);
+ if (c->qid.path == Qctl){
+ mconfig(a, n);
+ return n;
+ }
+
+ rlock(&lck);
+ if(waserror()){
+ runlock(&lck);
+ nexterror();
+ }
+
+ t = gettree(path2treeno(c->qid.path), Mustexist);
+ mp = getdev(t, path2devno(c->qid.path) - Qfirst, Mustexist);
+
+ if(off >= mp->size){
+ res = 0;
+ goto Done;
+ }
+ if(off + n > mp->size)
+ n = mp->size - off;
+ if(n == 0){
+ res = 0;
+ goto Done;
+ }
+ res = n;
+ switch(mp->type){
+ case Fcat:
+ res = catio(mp, Iswrite, a, n, off);
+ break;
+ case Finter:
+ res = interio(mp, Iswrite, a, n, off);
+ break;
+ case Fpart:
+ res = io(mp, mp->inner[0], Iswrite, a, n, mp->start + off);
+ if (res != n)
+ error(Eio);
+ break;
+ case Fmirror:
+ retry = 0;
+ do {
+ if (retry > 0) {
+ print("#k/%s: retry %d write for byte %,lld "
+ "count %ld: %s\n", mp->name, retry, off,
+ n, (up && up->errstr? up->errstr: ""));
+ /*
+ * pause before retrying in case it's due to
+ * a transient bus or controller problem.
+ */
+ tsleep(&up->sleep, return0, 0, Retrypause);
+ }
+ allbad = 1;
+ anybad = 0;
+ for (i = mp->ndevs - 1; i >= 0; i--){
+ if (waserror()) {
+ anybad = 1;
+ continue;
+ }
+ l = io(mp, mp->inner[i], Iswrite, a, n, off);
+ poperror();
+ if (l == n)
+ allbad = 0; /* wrote a good copy */
+ else
+ anybad = 1;
+ }
+ } while (anybad && ++retry <= Maxretries);
+ if (allbad) {
+ /* no mirror took a good copy of the block */
+ print("#k/%s: byte %,lld count %ld: CAN'T WRITE "
+ "to mirror: %s\n", mp->name, off, n,
+ (up && up->errstr? up->errstr: ""));
+ error(Eio);
+ } else if (retry > 0)
+ print("#k/%s: byte %,lld count %ld: retry wrote OK "
+ "to mirror: %s\n", mp->name, off, n,
+ (up && up->errstr? up->errstr: ""));
+
+ break;
+ }
+Done:
+ poperror();
+ runlock(&lck);
+ return res;
+}
+
+Dev fsdevtab = {
+ 'k',
+ "fs",
+
+ devreset,
+ devinit,
+ devshutdown,
+ mattach,
+ mwalk,
+ mstat,
+ mopen,
+ devcreate,
+ mclose,
+ mread,
+ devbread,
+ mwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+ devpower,
+ devconfig,
+};
diff --git a/sys/src/9/port/devkbin.c b/sys/src/9/port/devkbin.c
new file mode 100755
index 000000000..1f5fae8e0
--- /dev/null
+++ b/sys/src/9/port/devkbin.c
@@ -0,0 +1,120 @@
+/*
+ * keyboard scan code input from outside the kernel.
+ * to avoid duplication of keyboard map processing for usb.
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+extern void kbdputsc(int, int);
+
+enum {
+ Qdir,
+ Qkbd,
+};
+
+Dirtab kbintab[] = {
+ ".", {Qdir, 0, QTDIR}, 0, 0555,
+ "kbin", {Qkbd, 0}, 0, 0200,
+};
+
+Lock kbinlck;
+int kbinbusy;
+
+static Chan *
+kbinattach(char *spec)
+{
+ return devattach(L'Ι', spec);
+}
+
+static Walkqid*
+kbinwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, kbintab, nelem(kbintab), devgen);
+}
+
+static int
+kbinstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, kbintab, nelem(kbintab), devgen);
+}
+
+static Chan*
+kbinopen(Chan *c, int omode)
+{
+ if(!iseve())
+ error(Eperm);
+ if(c->qid.path == Qkbd){
+ lock(&kbinlck);
+ if(kbinbusy){
+ unlock(&kbinlck);
+ error(Einuse);
+ }
+ kbinbusy++;
+ unlock(&kbinlck);
+ }
+ return devopen(c, omode, kbintab, nelem(kbintab), devgen);
+}
+
+static void
+kbinclose(Chan *c)
+{
+ if(c->aux){
+ free(c->aux);
+ c->aux = nil;
+ }
+ if(c->qid.path == Qkbd)
+ kbinbusy = 0;
+}
+
+static long
+kbinread(Chan *c, void *a, long n, vlong )
+{
+ if(c->qid.type == QTDIR)
+ return devdirread(c, a, n, kbintab, nelem(kbintab), devgen);
+ return 0;
+}
+
+static long
+kbinwrite(Chan *c, void *a, long n, vlong)
+{
+ int i;
+ uchar *p = a;
+
+ if(c->qid.type == QTDIR)
+ error(Eisdir);
+ switch((int)c->qid.path){
+ case Qkbd:
+ for(i = 0; i < n; i++)
+ kbdputsc(*p++, 1); /* external source */
+ break;
+ default:
+ error(Egreg);
+ }
+ return n;
+}
+
+Dev kbindevtab = {
+ L'Ι',
+ "kbin",
+
+ devreset,
+ devinit,
+ devshutdown,
+ kbinattach,
+ kbinwalk,
+ kbinstat,
+ kbinopen,
+ devcreate,
+ kbinclose,
+ kbinread,
+ devbread,
+ kbinwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/port/devkbmap.c b/sys/src/9/port/devkbmap.c
new file mode 100755
index 000000000..fec4d8efb
--- /dev/null
+++ b/sys/src/9/port/devkbmap.c
@@ -0,0 +1,179 @@
+/*
+ * keyboard map
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+enum{
+ Qdir,
+ Qdata,
+};
+Dirtab kbmaptab[]={
+ ".", {Qdir, 0, QTDIR}, 0, 0555,
+ "kbmap", {Qdata, 0}, 0, 0600,
+};
+#define NKBFILE sizeof(kbmaptab)/sizeof(kbmaptab[0])
+
+#define KBLINELEN (3*NUMSIZE+1) /* t code val\n */
+
+static Chan *
+kbmapattach(char *spec)
+{
+ return devattach(L'κ', spec);
+}
+
+static Walkqid*
+kbmapwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, kbmaptab, NKBFILE, devgen);
+}
+
+static int
+kbmapstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, kbmaptab, NKBFILE, devgen);
+}
+
+static Chan*
+kbmapopen(Chan *c, int omode)
+{
+ if(!iseve())
+ error(Eperm);
+ return devopen(c, omode, kbmaptab, NKBFILE, devgen);
+}
+
+static void
+kbmapclose(Chan *c)
+{
+ if(c->aux){
+ free(c->aux);
+ c->aux = nil;
+ }
+}
+
+static long
+kbmapread(Chan *c, void *a, long n, vlong offset)
+{
+ char *bp;
+ char tmp[KBLINELEN+1];
+ int t, sc;
+ Rune r;
+
+ if(c->qid.type == QTDIR)
+ return devdirread(c, a, n, kbmaptab, NKBFILE, devgen);
+
+ switch((int)(c->qid.path)){
+ case Qdata:
+ if(kbdgetmap(offset/KBLINELEN, &t, &sc, &r)) {
+ bp = tmp;
+ bp += readnum(0, bp, NUMSIZE, t, NUMSIZE);
+ bp += readnum(0, bp, NUMSIZE, sc, NUMSIZE);
+ bp += readnum(0, bp, NUMSIZE, r, NUMSIZE);
+ *bp++ = '\n';
+ *bp = 0;
+ n = readstr(offset%KBLINELEN, a, n, tmp);
+ } else
+ n = 0;
+ break;
+ default:
+ n=0;
+ break;
+ }
+ return n;
+}
+
+static long
+kbmapwrite(Chan *c, void *a, long n, vlong)
+{
+ char line[100], *lp, *b;
+ int key, m, l;
+ Rune r;
+
+ if(c->qid.type == QTDIR)
+ error(Eperm);
+
+ switch((int)(c->qid.path)){
+ case Qdata:
+ b = a;
+ l = n;
+ lp = line;
+ if(c->aux){
+ strcpy(line, c->aux);
+ lp = line+strlen(line);
+ free(c->aux);
+ c->aux = nil;
+ }
+ while(--l >= 0) {
+ *lp++ = *b++;
+ if(lp[-1] == '\n' || lp == &line[sizeof(line)-1]) {
+ *lp = 0;
+ if(*line == 0)
+ error(Ebadarg);
+ if(*line == '\n' || *line == '#'){
+ lp = line;
+ continue;
+ }
+ lp = line;
+ while(*lp == ' ' || *lp == '\t')
+ lp++;
+ m = strtoul(line, &lp, 0);
+ key = strtoul(lp, &lp, 0);
+ while(*lp == ' ' || *lp == '\t')
+ lp++;
+ r = 0;
+ if(*lp == '\'' && lp[1])
+ chartorune(&r, lp+1);
+ else if(*lp == '^' && lp[1]){
+ chartorune(&r, lp+1);
+ if(0x40 <= r && r < 0x60)
+ r -= 0x40;
+ else
+ error(Ebadarg);
+ }else if(*lp == 'M' && ('1' <= lp[1] && lp[1] <= '5'))
+ r = 0xF900+lp[1]-'0';
+ else if(*lp>='0' && *lp<='9') /* includes 0x... */
+ r = strtoul(lp, &lp, 0);
+ else
+ error(Ebadarg);
+ kbdputmap(m, key, r);
+ lp = line;
+ }
+ }
+ if(lp != line){
+ l = lp-line;
+ c->aux = lp = smalloc(l+1);
+ memmove(lp, line, l);
+ lp[l] = 0;
+ }
+ break;
+ default:
+ error(Ebadusefd);
+ }
+ return n;
+}
+
+Dev kbmapdevtab = {
+ L'κ',
+ "kbmap",
+
+ devreset,
+ devinit,
+ devshutdown,
+ kbmapattach,
+ kbmapwalk,
+ kbmapstat,
+ kbmapopen,
+ devcreate,
+ kbmapclose,
+ kbmapread,
+ devbread,
+ kbmapwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/port/devkprof.c b/sys/src/9/port/devkprof.c
new file mode 100755
index 000000000..85ca17a58
--- /dev/null
+++ b/sys/src/9/port/devkprof.c
@@ -0,0 +1,192 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+
+#define LRES 3 /* log of PC resolution */
+#define SZ 4 /* sizeof of count cell; well known as 4 */
+
+struct
+{
+ int minpc;
+ int maxpc;
+ int nbuf;
+ int time;
+ ulong *buf;
+}kprof;
+
+enum{
+ Kprofdirqid,
+ Kprofdataqid,
+ Kprofctlqid,
+};
+Dirtab kproftab[]={
+ ".", {Kprofdirqid, 0, QTDIR}, 0, DMDIR|0550,
+ "kpdata", {Kprofdataqid}, 0, 0600,
+ "kpctl", {Kprofctlqid}, 0, 0600,
+};
+
+static void
+_kproftimer(ulong pc)
+{
+ extern void spldone(void);
+
+ if(kprof.time == 0)
+ return;
+ /*
+ * if the pc is coming out of spllo or splx,
+ * use the pc saved when we went splhi.
+ */
+ if(pc>=(ulong)spllo && pc<=(ulong)spldone)
+ pc = m->splpc;
+
+ kprof.buf[0] += TK2MS(1);
+ if(kprof.minpc<=pc && pc<kprof.maxpc){
+ pc -= kprof.minpc;
+ pc >>= LRES;
+ kprof.buf[pc] += TK2MS(1);
+ }else
+ kprof.buf[1] += TK2MS(1);
+}
+
+static void
+kprofinit(void)
+{
+ if(SZ != sizeof kprof.buf[0])
+ panic("kprof size");
+ kproftimer = _kproftimer;
+}
+
+static Chan*
+kprofattach(char *spec)
+{
+ ulong n;
+
+ /* allocate when first used */
+ kprof.minpc = KTZERO;
+ kprof.maxpc = (ulong)etext;
+ kprof.nbuf = (kprof.maxpc-kprof.minpc) >> LRES;
+ n = kprof.nbuf*SZ;
+ if(kprof.buf == 0) {
+ kprof.buf = xalloc(n);
+ if(kprof.buf == 0)
+ error(Enomem);
+ }
+ kproftab[1].length = n;
+ return devattach('K', spec);
+}
+
+static Walkqid*
+kprofwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, kproftab, nelem(kproftab), devgen);
+}
+
+static int
+kprofstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, kproftab, nelem(kproftab), devgen);
+}
+
+static Chan*
+kprofopen(Chan *c, int omode)
+{
+ if(c->qid.type == QTDIR){
+ if(omode != OREAD)
+ error(Eperm);
+ }
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+static void
+kprofclose(Chan*)
+{
+}
+
+static long
+kprofread(Chan *c, void *va, long n, vlong off)
+{
+ ulong end;
+ ulong w, *bp;
+ uchar *a, *ea;
+ ulong offset = off;
+
+ switch((int)c->qid.path){
+ case Kprofdirqid:
+ return devdirread(c, va, n, kproftab, nelem(kproftab), devgen);
+
+ case Kprofdataqid:
+ end = kprof.nbuf*SZ;
+ if(offset & (SZ-1))
+ error(Ebadarg);
+ if(offset >= end){
+ n = 0;
+ break;
+ }
+ if(offset+n > end)
+ n = end-offset;
+ n &= ~(SZ-1);
+ a = va;
+ ea = a + n;
+ bp = kprof.buf + offset/SZ;
+ while(a < ea){
+ w = *bp++;
+ *a++ = w>>24;
+ *a++ = w>>16;
+ *a++ = w>>8;
+ *a++ = w>>0;
+ }
+ break;
+
+ default:
+ n = 0;
+ break;
+ }
+ return n;
+}
+
+static long
+kprofwrite(Chan *c, void *a, long n, vlong)
+{
+ switch((int)(c->qid.path)){
+ case Kprofctlqid:
+ if(strncmp(a, "startclr", 8) == 0){
+ memset((char *)kprof.buf, 0, kprof.nbuf*SZ);
+ kprof.time = 1;
+ }else if(strncmp(a, "start", 5) == 0)
+ kprof.time = 1;
+ else if(strncmp(a, "stop", 4) == 0)
+ kprof.time = 0;
+ break;
+ default:
+ error(Ebadusefd);
+ }
+ return n;
+}
+
+Dev kprofdevtab = {
+ 'K',
+ "kprof",
+
+ devreset,
+ kprofinit,
+ devshutdown,
+ kprofattach,
+ kprofwalk,
+ kprofstat,
+ kprofopen,
+ devcreate,
+ kprofclose,
+ kprofread,
+ devbread,
+ kprofwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/port/devloopback.c b/sys/src/9/port/devloopback.c
new file mode 100755
index 000000000..d3a64932b
--- /dev/null
+++ b/sys/src/9/port/devloopback.c
@@ -0,0 +1,743 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+typedef struct Link Link;
+typedef struct Loop Loop;
+
+struct Link
+{
+ Lock;
+
+ int ref;
+
+ long packets; /* total number of packets sent */
+ long bytes; /* total number of bytes sent */
+ int indrop; /* enable dropping on iq overflow */
+ long soverflows; /* packets dropped because iq overflowed */
+ long droprate; /* drop 1/droprate packets in tq */
+ long drops; /* packets deliberately dropped */
+
+ vlong delay0ns; /* nanosec of delay in the link */
+ long delaynns; /* nanosec of delay per byte */
+
+ Block *tq; /* transmission queue */
+ Block *tqtail;
+ vlong tout; /* time the last packet in tq is really out */
+ vlong tin; /* time the head packet in tq enters the remote side */
+
+ long limit; /* queue buffering limit */
+ Queue *oq; /* output queue from other side & packets in the link */
+ Queue *iq;
+
+ Timer ci; /* time to move packets from next packet from oq */
+};
+
+struct Loop
+{
+ QLock;
+ int ref;
+ int minmtu; /* smallest block transmittable */
+ Loop *next;
+ ulong path;
+ Link link[2];
+};
+
+static struct
+{
+ Lock;
+ ulong path;
+} loopbackalloc;
+
+enum
+{
+ Qtopdir= 1, /* top level directory */
+
+ Qloopdir, /* loopback* directory */
+
+ Qportdir, /* directory each end of the loop */
+ Qctl,
+ Qstatus,
+ Qstats,
+ Qdata,
+
+ MaxQ,
+
+ Nloopbacks = 5,
+
+ Statelen = 23*1024, /* status buffer size */
+
+ Tmsize = 8,
+ Delayn = 10000, /* default delays in ns */
+ Delay0 = 2500000,
+
+ Loopqlim = 32*1024, /* default size of queues */
+};
+
+static Dirtab loopportdir[] =
+{
+ "ctl", {Qctl}, 0, 0222,
+ "status", {Qstatus}, 0, 0444,
+ "stats", {Qstats}, 0, 0444,
+ "data", {Qdata}, 0, 0666,
+};
+static Dirtab loopdirs[MaxQ];
+
+static Loop loopbacks[Nloopbacks];
+
+#define TYPE(x) (((ulong)(x))&0xff)
+#define ID(x) (((ulong)(x))>>8)
+#define QID(x,y) ((((ulong)(x))<<8)|((ulong)(y)))
+
+static void looper(Loop *lb);
+static long loopoput(Loop *lb, Link *link, Block *bp);
+static void ptime(uchar *p, vlong t);
+static vlong gtime(uchar *p);
+static void closelink(Link *link, int dofree);
+static void pushlink(Link *link, vlong now);
+static void freelb(Loop *lb);
+static void linkintr(Ureg*, Timer *ci);
+
+static void
+loopbackinit(void)
+{
+ int i;
+
+ for(i = 0; i < Nloopbacks; i++)
+ loopbacks[i].path = i;
+
+ /* invert directory tables for non-directory entries */
+ for(i=0; i<nelem(loopportdir); i++)
+ loopdirs[loopportdir[i].qid.path] = loopportdir[i];
+}
+
+static Chan*
+loopbackattach(char *spec)
+{
+ Loop *volatile lb;
+ Queue *q;
+ Chan *c;
+ int chan;
+ int dev;
+
+ dev = 0;
+ if(spec != nil){
+ dev = atoi(spec);
+ if(dev >= Nloopbacks)
+ error(Ebadspec);
+ }
+
+ c = devattach('X', spec);
+ lb = &loopbacks[dev];
+
+ qlock(lb);
+ if(waserror()){
+ lb->ref--;
+ qunlock(lb);
+ nexterror();
+ }
+
+ lb->ref++;
+ if(lb->ref == 1){
+ for(chan = 0; chan < 2; chan++){
+ lb->link[chan].ci.mode = Trelative;
+ lb->link[chan].ci.a = &lb->link[chan];
+ lb->link[chan].ci.f = linkintr;
+ lb->link[chan].limit = Loopqlim;
+ q = qopen(lb->link[chan].limit, 0, 0, 0);
+ lb->link[chan].iq = q;
+ if(q == nil){
+ freelb(lb);
+ exhausted("memory");
+ }
+ q = qopen(lb->link[chan].limit, 0, 0, 0);
+ lb->link[chan].oq = q;
+ if(q == nil){
+ freelb(lb);
+ exhausted("memory");
+ }
+ lb->link[chan].indrop = 1;
+
+ lb->link[chan].delaynns = Delayn;
+ lb->link[chan].delay0ns = Delay0;
+ }
+ }
+ poperror();
+ qunlock(lb);
+
+ mkqid(&c->qid, QID(0, Qtopdir), 0, QTDIR);
+ c->aux = lb;
+ c->dev = dev;
+ return c;
+}
+
+static int
+loopbackgen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
+{
+ Dirtab *tab;
+ int len, type;
+ Qid qid;
+
+ type = TYPE(c->qid.path);
+ if(i == DEVDOTDOT){
+ switch(type){
+ case Qtopdir:
+ case Qloopdir:
+ snprint(up->genbuf, sizeof(up->genbuf), "#X%ld", c->dev);
+ mkqid(&qid, QID(0, Qtopdir), 0, QTDIR);
+ devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ break;
+ case Qportdir:
+ snprint(up->genbuf, sizeof(up->genbuf), "loopback%ld", c->dev);
+ mkqid(&qid, QID(0, Qloopdir), 0, QTDIR);
+ devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ break;
+ default:
+ panic("loopbackgen %llux", c->qid.path);
+ }
+ return 1;
+ }
+
+ switch(type){
+ case Qtopdir:
+ if(i != 0)
+ return -1;
+ snprint(up->genbuf, sizeof(up->genbuf), "loopback%ld", c->dev);
+ mkqid(&qid, QID(0, Qloopdir), 0, QTDIR);
+ devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+ case Qloopdir:
+ if(i >= 2)
+ return -1;
+ snprint(up->genbuf, sizeof(up->genbuf), "%d", i);
+ mkqid(&qid, QID(i, QID(0, Qportdir)), 0, QTDIR);
+ devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+ case Qportdir:
+ if(i >= nelem(loopportdir))
+ return -1;
+ tab = &loopportdir[i];
+ mkqid(&qid, QID(ID(c->qid.path), tab->qid.path), 0, QTFILE);
+ devdir(c, qid, tab->name, tab->length, eve, tab->perm, dp);
+ return 1;
+ default:
+ /* non directory entries end up here; must be in lowest level */
+ if(c->qid.type & QTDIR)
+ panic("loopbackgen: unexpected directory");
+ if(i != 0)
+ return -1;
+ tab = &loopdirs[type];
+ if(tab == nil)
+ panic("loopbackgen: unknown type: %d", type);
+ len = tab->length;
+ devdir(c, c->qid, tab->name, len, eve, tab->perm, dp);
+ return 1;
+ }
+}
+
+
+static Walkqid*
+loopbackwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ Walkqid *wq;
+ Loop *lb;
+
+ wq = devwalk(c, nc, name, nname, nil, 0, loopbackgen);
+ if(wq != nil && wq->clone != nil && wq->clone != c){
+ lb = c->aux;
+ qlock(lb);
+ lb->ref++;
+ if((c->flag & COPEN) && TYPE(c->qid.path) == Qdata)
+ lb->link[ID(c->qid.path)].ref++;
+ qunlock(lb);
+ }
+ return wq;
+}
+
+static int
+loopbackstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, nil, 0, loopbackgen);
+}
+
+/*
+ * if the stream doesn't exist, create it
+ */
+static Chan*
+loopbackopen(Chan *c, int omode)
+{
+ Loop *lb;
+
+ if(c->qid.type & QTDIR){
+ if(omode != OREAD)
+ error(Ebadarg);
+ c->mode = omode;
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+ }
+
+ lb = c->aux;
+ qlock(lb);
+ if(TYPE(c->qid.path) == Qdata){
+ if(lb->link[ID(c->qid.path)].ref){
+ qunlock(lb);
+ error(Einuse);
+ }
+ lb->link[ID(c->qid.path)].ref++;
+ }
+ qunlock(lb);
+
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ c->iounit = qiomaxatomic;
+ return c;
+}
+
+static void
+loopbackclose(Chan *c)
+{
+ Loop *lb;
+ int ref, chan;
+
+ lb = c->aux;
+
+ qlock(lb);
+
+ /*
+ * closing either side hangs up the stream
+ */
+ if((c->flag & COPEN) && TYPE(c->qid.path) == Qdata){
+ chan = ID(c->qid.path);
+ if(--lb->link[chan].ref == 0){
+ qhangup(lb->link[chan ^ 1].oq, nil);
+ looper(lb);
+ }
+ }
+
+
+ /*
+ * if both sides are closed, they are reusable
+ */
+ if(lb->link[0].ref == 0 && lb->link[1].ref == 0){
+ for(chan = 0; chan < 2; chan++){
+ closelink(&lb->link[chan], 0);
+ qreopen(lb->link[chan].iq);
+ qreopen(lb->link[chan].oq);
+ qsetlimit(lb->link[chan].oq, lb->link[chan].limit);
+ qsetlimit(lb->link[chan].iq, lb->link[chan].limit);
+ }
+ }
+ ref = --lb->ref;
+ if(ref == 0)
+ freelb(lb);
+ qunlock(lb);
+}
+
+static void
+freelb(Loop *lb)
+{
+ int chan;
+
+ for(chan = 0; chan < 2; chan++)
+ closelink(&lb->link[chan], 1);
+}
+
+/*
+ * called with the Loop qlocked,
+ * so only pushlink can mess with the queues
+ */
+static void
+closelink(Link *link, int dofree)
+{
+ Queue *iq, *oq;
+ Block *bp;
+
+ ilock(link);
+ iq = link->iq;
+ oq = link->oq;
+ bp = link->tq;
+ link->tq = nil;
+ link->tqtail = nil;
+ link->tout = 0;
+ link->tin = 0;
+ timerdel(&link->ci);
+ iunlock(link);
+ if(iq != nil){
+ qclose(iq);
+ if(dofree){
+ ilock(link);
+ free(iq);
+ link->iq = nil;
+ iunlock(link);
+ }
+ }
+ if(oq != nil){
+ qclose(oq);
+ if(dofree){
+ ilock(link);
+ free(oq);
+ link->oq = nil;
+ iunlock(link);
+ }
+ }
+ freeblist(bp);
+}
+
+static long
+loopbackread(Chan *c, void *va, long n, vlong offset)
+{
+ Loop *lb;
+ Link *link;
+ char *buf;
+ long rv;
+
+ lb = c->aux;
+ switch(TYPE(c->qid.path)){
+ default:
+ error(Eperm);
+ return -1; /* not reached */
+ case Qtopdir:
+ case Qloopdir:
+ case Qportdir:
+ return devdirread(c, va, n, nil, 0, loopbackgen);
+ case Qdata:
+ return qread(lb->link[ID(c->qid.path)].iq, va, n);
+ case Qstatus:
+ link = &lb->link[ID(c->qid.path)];
+ buf = smalloc(Statelen);
+ rv = snprint(buf, Statelen, "delay %lld %ld\n", link->delay0ns, link->delaynns);
+ rv += snprint(buf+rv, Statelen-rv, "limit %ld\n", link->limit);
+ rv += snprint(buf+rv, Statelen-rv, "indrop %d\n", link->indrop);
+ snprint(buf+rv, Statelen-rv, "droprate %ld\n", link->droprate);
+ rv = readstr(offset, va, n, buf);
+ free(buf);
+ break;
+ case Qstats:
+ link = &lb->link[ID(c->qid.path)];
+ buf = smalloc(Statelen);
+ rv = snprint(buf, Statelen, "packets: %ld\n", link->packets);
+ rv += snprint(buf+rv, Statelen-rv, "bytes: %ld\n", link->bytes);
+ rv += snprint(buf+rv, Statelen-rv, "dropped: %ld\n", link->drops);
+ snprint(buf+rv, Statelen-rv, "soft overflows: %ld\n", link->soverflows);
+ rv = readstr(offset, va, n, buf);
+ free(buf);
+ break;
+ }
+ return rv;
+}
+
+static Block*
+loopbackbread(Chan *c, long n, ulong offset)
+{
+ Loop *lb;
+
+ lb = c->aux;
+ if(TYPE(c->qid.path) == Qdata)
+ return qbread(lb->link[ID(c->qid.path)].iq, n);
+
+ return devbread(c, n, offset);
+}
+
+static long
+loopbackbwrite(Chan *c, Block *bp, ulong off)
+{
+ Loop *lb;
+
+ lb = c->aux;
+ if(TYPE(c->qid.path) == Qdata)
+ return loopoput(lb, &lb->link[ID(c->qid.path) ^ 1], bp);
+ return devbwrite(c, bp, off);
+}
+
+static long
+loopbackwrite(Chan *c, void *va, long n, vlong off)
+{
+ Loop *lb;
+ Link *link;
+ Cmdbuf *volatile cb;
+ Block *volatile bp;
+ vlong d0, d0ns;
+ long dn, dnns;
+
+ switch(TYPE(c->qid.path)){
+ case Qdata:
+ bp = allocb(n);
+ if(waserror()){
+ freeb(bp);
+ nexterror();
+ }
+ memmove(bp->wp, va, n);
+ poperror();
+ bp->wp += n;
+ return loopbackbwrite(c, bp, off);
+ case Qctl:
+ lb = c->aux;
+ link = &lb->link[ID(c->qid.path)];
+ cb = parsecmd(va, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ if(cb->nf < 1)
+ error("short control request");
+ if(strcmp(cb->f[0], "delay") == 0){
+ if(cb->nf != 3)
+ error("usage: delay latency bytedelay");
+ d0ns = strtoll(cb->f[1], nil, 10);
+ dnns = strtol(cb->f[2], nil, 10);
+
+ /*
+ * it takes about 20000 cycles on a pentium ii
+ * to run pushlink; perhaps this should be accounted.
+ */
+
+ ilock(link);
+ link->delay0ns = d0ns;
+ link->delaynns = dnns;
+ iunlock(link);
+ }else if(strcmp(cb->f[0], "indrop") == 0){
+ if(cb->nf != 2)
+ error("usage: indrop [01]");
+ ilock(link);
+ link->indrop = strtol(cb->f[1], nil, 0) != 0;
+ iunlock(link);
+ }else if(strcmp(cb->f[0], "droprate") == 0){
+ if(cb->nf != 2)
+ error("usage: droprate ofn");
+ ilock(link);
+ link->droprate = strtol(cb->f[1], nil, 0);
+ iunlock(link);
+ }else if(strcmp(cb->f[0], "limit") == 0){
+ if(cb->nf != 2)
+ error("usage: limit maxqsize");
+ ilock(link);
+ link->limit = strtol(cb->f[1], nil, 0);
+ qsetlimit(link->oq, link->limit);
+ qsetlimit(link->iq, link->limit);
+ iunlock(link);
+ }else if(strcmp(cb->f[0], "reset") == 0){
+ if(cb->nf != 1)
+ error("usage: reset");
+ ilock(link);
+ link->packets = 0;
+ link->bytes = 0;
+ link->indrop = 0;
+ link->soverflows = 0;
+ link->drops = 0;
+ iunlock(link);
+ }else
+ error("unknown control request");
+ poperror();
+ free(cb);
+ break;
+ default:
+ error(Eperm);
+ }
+
+ return n;
+}
+
+static long
+loopoput(Loop *lb, Link *link, Block *volatile bp)
+{
+ long n;
+
+ n = BLEN(bp);
+
+ /* make it a single block with space for the loopback timing header */
+ if(waserror()){
+ freeb(bp);
+ nexterror();
+ }
+ bp = padblock(bp, Tmsize);
+ if(bp->next)
+ bp = concatblock(bp);
+ if(BLEN(bp) < lb->minmtu)
+ bp = adjustblock(bp, lb->minmtu);
+ poperror();
+ ptime(bp->rp, todget(nil));
+
+ link->packets++;
+ link->bytes += n;
+
+ qbwrite(link->oq, bp);
+
+ looper(lb);
+ return n;
+}
+
+static void
+looper(Loop *lb)
+{
+ vlong t;
+ int chan;
+
+ t = todget(nil);
+ for(chan = 0; chan < 2; chan++)
+ pushlink(&lb->link[chan], t);
+}
+
+static void
+linkintr(Ureg*, Timer *ci)
+{
+ Link *link;
+
+ link = ci->a;
+ pushlink(link, ci->ns);
+}
+
+/*
+ * move blocks between queues if they are ready.
+ * schedule an interrupt for the next interesting time.
+ *
+ * must be called with the link ilocked.
+ */
+static void
+pushlink(Link *link, vlong now)
+{
+ Block *bp;
+ vlong tout, tin;
+
+ /*
+ * put another block in the link queue
+ */
+ ilock(link);
+ if(link->iq == nil || link->oq == nil){
+ iunlock(link);
+ return;
+
+ }
+ timerdel(&link->ci);
+
+ /*
+ * put more blocks into the xmit queue
+ * use the time the last packet was supposed to go out
+ * as the start time for the next packet, rather than
+ * the current time. this more closely models a network
+ * device which can queue multiple output packets.
+ */
+ tout = link->tout;
+ if(!tout)
+ tout = now;
+ while(tout <= now){
+ bp = qget(link->oq);
+ if(bp == nil){
+ tout = 0;
+ break;
+ }
+
+ /*
+ * can't send the packet before it gets queued
+ */
+ tin = gtime(bp->rp);
+ if(tin > tout)
+ tout = tin;
+ tout = tout + (BLEN(bp) - Tmsize) * link->delayn;
+
+ /*
+ * drop packets
+ */
+ if(link->droprate && nrand(link->droprate) == 0)
+ link->drops++;
+ else{
+ ptime(bp->rp, tout + link->delay0ns);
+ if(link->tq == nil)
+ link->tq = bp;
+ else
+ link->tqtail->next = bp;
+ link->tqtail = bp;
+ }
+ }
+
+ /*
+ * record the next time a packet can be sent,
+ * but don't schedule an interrupt if none is waiting
+ */
+ link->tout = tout;
+ if(!qcanread(link->oq))
+ tout = 0;
+
+ /*
+ * put more blocks into the receive queue
+ */
+ tin = 0;
+ while(bp = link->tq){
+ tin = gtime(bp->rp);
+ if(tin > now)
+ break;
+ bp->rp += Tmsize;
+ link->tq = bp->next;
+ bp->next = nil;
+ if(!link->indrop)
+ qpassnolim(link->iq, bp);
+ else if(qpass(link->iq, bp) < 0)
+ link->soverflows++;
+ tin = 0;
+ }
+ if(bp == nil && qisclosed(link->oq) && !qcanread(link->oq) && !qisclosed(link->iq))
+ qhangup(link->iq, nil);
+ link->tin = tin;
+ if(!tin || tin > tout && tout)
+ tin = tout;
+
+ link->ci.ns = tin - now;
+ if(tin){
+ if(tin < now)
+ panic("loopback unfinished business");
+ timeradd(&link->ci);
+ }
+ iunlock(link);
+}
+
+static void
+ptime(uchar *p, vlong t)
+{
+ ulong tt;
+
+ tt = t >> 32;
+ p[0] = tt >> 24;
+ p[1] = tt >> 16;
+ p[2] = tt >> 8;
+ p[3] = tt;
+ tt = t;
+ p[4] = tt >> 24;
+ p[5] = tt >> 16;
+ p[6] = tt >> 8;
+ p[7] = tt;
+}
+
+static vlong
+gtime(uchar *p)
+{
+ ulong t1, t2;
+
+ t1 = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ t2 = (p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7];
+ return ((vlong)t1 << 32) | t2;
+}
+
+Dev loopbackdevtab = {
+ 'X',
+ "loopback",
+
+ devreset,
+ loopbackinit,
+ devshutdown,
+ loopbackattach,
+ loopbackwalk,
+ loopbackstat,
+ loopbackopen,
+ devcreate,
+ loopbackclose,
+ loopbackread,
+ loopbackbread,
+ loopbackwrite,
+ loopbackbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/port/devmnt.c b/sys/src/9/port/devmnt.c
new file mode 100755
index 000000000..129d06e2a
--- /dev/null
+++ b/sys/src/9/port/devmnt.c
@@ -0,0 +1,1197 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+/*
+ * References are managed as follows:
+ * The channel to the server - a network connection or pipe - has one
+ * reference for every Chan open on the server. The server channel has
+ * c->mux set to the Mnt used for muxing control to that server. Mnts
+ * have no reference count; they go away when c goes away.
+ * Each channel derived from the mount point has mchan set to c,
+ * and increfs/decrefs mchan to manage references on the server
+ * connection.
+ */
+
+#define MAXRPC (IOHDRSZ+8192)
+
+struct Mntrpc
+{
+ Chan* c; /* Channel for whom we are working */
+ Mntrpc* list; /* Free/pending list */
+ Fcall request; /* Outgoing file system protocol message */
+ Fcall reply; /* Incoming reply */
+ Mnt* m; /* Mount device during rpc */
+ Rendez r; /* Place to hang out */
+ uchar* rpc; /* I/O Data buffer */
+ uint rpclen; /* len of buffer */
+ Block *b; /* reply blocks */
+ char done; /* Rpc completed */
+ uvlong stime; /* start time for mnt statistics */
+ ulong reqlen; /* request length for mnt statistics */
+ ulong replen; /* reply length for mnt statistics */
+ Mntrpc* flushed; /* message this one flushes */
+};
+
+enum
+{
+ TAGSHIFT = 5, /* ulong has to be 32 bits */
+ TAGMASK = (1<<TAGSHIFT)-1,
+ NMASK = (64*1024)>>TAGSHIFT,
+};
+
+struct Mntalloc
+{
+ Lock;
+ Mnt* list; /* Mount devices in use */
+ Mnt* mntfree; /* Free list */
+ Mntrpc* rpcfree;
+ int nrpcfree;
+ int nrpcused;
+ ulong id;
+ ulong tagmask[NMASK];
+}mntalloc;
+
+Mnt* mntchk(Chan*);
+void mntdirfix(uchar*, Chan*);
+Mntrpc* mntflushalloc(Mntrpc*, ulong);
+void mntflushfree(Mnt*, Mntrpc*);
+void mntfree(Mntrpc*);
+void mntgate(Mnt*);
+void mntpntfree(Mnt*);
+void mntqrm(Mnt*, Mntrpc*);
+Mntrpc* mntralloc(Chan*, ulong);
+long mntrdwr(int, Chan*, void*, long, vlong);
+int mntrpcread(Mnt*, Mntrpc*);
+void mountio(Mnt*, Mntrpc*);
+void mountmux(Mnt*, Mntrpc*);
+void mountrpc(Mnt*, Mntrpc*);
+int rpcattn(void*);
+Chan* mntchan(void);
+
+char Esbadstat[] = "invalid directory entry received from server";
+char Enoversion[] = "version not established for mount channel";
+
+
+void (*mntstats)(int, Chan*, uvlong, ulong);
+
+static void
+mntreset(void)
+{
+ mntalloc.id = 1;
+ mntalloc.tagmask[0] = 1; /* don't allow 0 as a tag */
+ mntalloc.tagmask[NMASK-1] = 0x80000000UL; /* don't allow NOTAG */
+ fmtinstall('F', fcallfmt);
+ fmtinstall('D', dirfmt);
+/* We can't install %M since eipfmt does and is used in the kernel [sape] */
+
+ cinit();
+}
+
+/*
+ * Version is not multiplexed: message sent only once per connection.
+ */
+long
+mntversion(Chan *c, char *version, int msize, int returnlen)
+{
+ Fcall f;
+ uchar *msg;
+ Mnt *m;
+ char *v;
+ long k, l;
+ uvlong oo;
+ char buf[128];
+
+ qlock(&c->umqlock); /* make sure no one else does this until we've established ourselves */
+ if(waserror()){
+ qunlock(&c->umqlock);
+ nexterror();
+ }
+
+ /* defaults */
+ if(msize == 0)
+ msize = MAXRPC;
+ if(msize > c->iounit && c->iounit != 0)
+ msize = c->iounit;
+ v = version;
+ if(v == nil || v[0] == '\0')
+ v = VERSION9P;
+
+ /* validity */
+ if(msize < 0)
+ error("bad iounit in version call");
+ if(strncmp(v, VERSION9P, strlen(VERSION9P)) != 0)
+ error("bad 9P version specification");
+
+ m = c->mux;
+
+ if(m != nil){
+ qunlock(&c->umqlock);
+ poperror();
+
+ strecpy(buf, buf+sizeof buf, m->version);
+ k = strlen(buf);
+ if(strncmp(buf, v, k) != 0){
+ snprint(buf, sizeof buf, "incompatible 9P versions %s %s", m->version, v);
+ error(buf);
+ }
+ if(returnlen > 0){
+ if(returnlen < k)
+ error(Eshort);
+ memmove(version, buf, k);
+ }
+ return k;
+ }
+
+ f.type = Tversion;
+ f.tag = NOTAG;
+ f.msize = msize;
+ f.version = v;
+ msg = malloc(8192+IOHDRSZ);
+ if(msg == nil)
+ exhausted("version memory");
+ if(waserror()){
+ free(msg);
+ nexterror();
+ }
+ k = convS2M(&f, msg, 8192+IOHDRSZ);
+ if(k == 0)
+ error("bad fversion conversion on send");
+
+ lock(c);
+ oo = c->offset;
+ c->offset += k;
+ unlock(c);
+
+ l = devtab[c->type]->write(c, msg, k, oo);
+
+ if(l < k){
+ lock(c);
+ c->offset -= k - l;
+ unlock(c);
+ error("short write in fversion");
+ }
+
+ /* message sent; receive and decode reply */
+ k = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset);
+ if(k <= 0)
+ error("EOF receiving fversion reply");
+
+ lock(c);
+ c->offset += k;
+ unlock(c);
+
+ l = convM2S(msg, k, &f);
+ if(l != k)
+ error("bad fversion conversion on reply");
+ if(f.type != Rversion){
+ if(f.type == Rerror)
+ error(f.ename);
+ error("unexpected reply type in fversion");
+ }
+ if(f.msize > msize)
+ error("server tries to increase msize in fversion");
+ if(f.msize<256 || f.msize>1024*1024)
+ error("nonsense value of msize in fversion");
+ k = strlen(f.version);
+ if(strncmp(f.version, v, k) != 0)
+ error("bad 9P version returned from server");
+
+ /* now build Mnt associated with this connection */
+ lock(&mntalloc);
+ m = mntalloc.mntfree;
+ if(m != 0)
+ mntalloc.mntfree = m->list;
+ else {
+ m = malloc(sizeof(Mnt));
+ if(m == 0) {
+ unlock(&mntalloc);
+ exhausted("mount devices");
+ }
+ }
+ m->list = mntalloc.list;
+ mntalloc.list = m;
+ m->version = nil;
+ kstrdup(&m->version, f.version);
+ m->id = mntalloc.id++;
+ m->q = qopen(10*MAXRPC, 0, nil, nil);
+ m->msize = f.msize;
+ unlock(&mntalloc);
+
+ if(returnlen > 0){
+ if(returnlen < k)
+ error(Eshort);
+ memmove(version, f.version, k);
+ }
+
+ poperror(); /* msg */
+ free(msg);
+
+ lock(m);
+ m->queue = 0;
+ m->rip = 0;
+
+ c->flag |= CMSG;
+ c->mux = m;
+ m->c = c;
+ unlock(m);
+
+ poperror(); /* c */
+ qunlock(&c->umqlock);
+
+ return k;
+}
+
+Chan*
+mntauth(Chan *c, char *spec)
+{
+ Mnt *m;
+ Mntrpc *r;
+
+ m = c->mux;
+
+ if(m == nil){
+ mntversion(c, VERSION9P, MAXRPC, 0);
+ m = c->mux;
+ if(m == nil)
+ error(Enoversion);
+ }
+
+ c = mntchan();
+ if(waserror()) {
+ /* Close must not be called since it will
+ * call mnt recursively
+ */
+ chanfree(c);
+ nexterror();
+ }
+
+ r = mntralloc(0, m->msize);
+
+ if(waserror()) {
+ mntfree(r);
+ nexterror();
+ }
+
+ r->request.type = Tauth;
+ r->request.afid = c->fid;
+ r->request.uname = up->user;
+ r->request.aname = spec;
+ mountrpc(m, r);
+
+ c->qid = r->reply.aqid;
+ c->mchan = m->c;
+ incref(m->c);
+ c->mqid = c->qid;
+ c->mode = ORDWR;
+
+ poperror(); /* r */
+ mntfree(r);
+
+ poperror(); /* c */
+
+ return c;
+
+}
+
+static Chan*
+mntattach(char *muxattach)
+{
+ Mnt *m;
+ Chan *c;
+ Mntrpc *r;
+ struct bogus{
+ Chan *chan;
+ Chan *authchan;
+ char *spec;
+ int flags;
+ }bogus;
+
+ bogus = *((struct bogus *)muxattach);
+ c = bogus.chan;
+
+ m = c->mux;
+
+ if(m == nil){
+ mntversion(c, nil, 0, 0);
+ m = c->mux;
+ if(m == nil)
+ error(Enoversion);
+ }
+
+ c = mntchan();
+ if(waserror()) {
+ /* Close must not be called since it will
+ * call mnt recursively
+ */
+ chanfree(c);
+ nexterror();
+ }
+
+ r = mntralloc(0, m->msize);
+
+ if(waserror()) {
+ mntfree(r);
+ nexterror();
+ }
+
+ r->request.type = Tattach;
+ r->request.fid = c->fid;
+ if(bogus.authchan == nil)
+ r->request.afid = NOFID;
+ else
+ r->request.afid = bogus.authchan->fid;
+ r->request.uname = up->user;
+ r->request.aname = bogus.spec;
+ mountrpc(m, r);
+
+ c->qid = r->reply.qid;
+ c->mchan = m->c;
+ incref(m->c);
+ c->mqid = c->qid;
+
+ poperror(); /* r */
+ mntfree(r);
+
+ poperror(); /* c */
+
+ if(bogus.flags&MCACHE)
+ c->flag |= CCACHE;
+ return c;
+}
+
+Chan*
+mntchan(void)
+{
+ Chan *c;
+
+ c = devattach('M', 0);
+ lock(&mntalloc);
+ c->dev = mntalloc.id++;
+ unlock(&mntalloc);
+
+ if(c->mchan)
+ panic("mntchan non-zero %p", c->mchan);
+ return c;
+}
+
+static Walkqid*
+mntwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ int i, alloc;
+ Mnt *m;
+ Mntrpc *r;
+ Walkqid *wq;
+
+ if(nc != nil)
+ print("mntwalk: nc != nil\n");
+ if(nname > MAXWELEM)
+ error("devmnt: too many name elements");
+ alloc = 0;
+ wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
+ if(waserror()){
+ if(alloc && wq->clone!=nil)
+ cclose(wq->clone);
+ free(wq);
+ return nil;
+ }
+
+ alloc = 0;
+ m = mntchk(c);
+ r = mntralloc(c, m->msize);
+ if(nc == nil){
+ nc = devclone(c);
+ /*
+ * Until the other side accepts this fid, we can't mntclose it.
+ * Therefore set type to 0 for now; rootclose is known to be safe.
+ */
+ nc->type = 0;
+ alloc = 1;
+ }
+ wq->clone = nc;
+
+ if(waserror()) {
+ mntfree(r);
+ nexterror();
+ }
+ r->request.type = Twalk;
+ r->request.fid = c->fid;
+ r->request.newfid = nc->fid;
+ r->request.nwname = nname;
+ memmove(r->request.wname, name, nname*sizeof(char*));
+
+ mountrpc(m, r);
+
+ if(r->reply.nwqid > nname)
+ error("too many QIDs returned by walk");
+ if(r->reply.nwqid < nname){
+ if(alloc)
+ cclose(nc);
+ wq->clone = nil;
+ if(r->reply.nwqid == 0){
+ free(wq);
+ wq = nil;
+ goto Return;
+ }
+ }
+
+ /* move new fid onto mnt device and update its qid */
+ if(wq->clone != nil){
+ if(wq->clone != c){
+ wq->clone->type = c->type;
+ wq->clone->mchan = c->mchan;
+ incref(c->mchan);
+ }
+ if(r->reply.nwqid > 0)
+ wq->clone->qid = r->reply.wqid[r->reply.nwqid-1];
+ }
+ wq->nqid = r->reply.nwqid;
+ for(i=0; i<wq->nqid; i++)
+ wq->qid[i] = r->reply.wqid[i];
+
+ Return:
+ poperror();
+ mntfree(r);
+ poperror();
+ return wq;
+}
+
+static int
+mntstat(Chan *c, uchar *dp, int n)
+{
+ Mnt *m;
+ Mntrpc *r;
+
+ if(n < BIT16SZ)
+ error(Eshortstat);
+ m = mntchk(c);
+ r = mntralloc(c, m->msize);
+ if(waserror()) {
+ mntfree(r);
+ nexterror();
+ }
+ r->request.type = Tstat;
+ r->request.fid = c->fid;
+ mountrpc(m, r);
+
+ if(r->reply.nstat > n){
+ n = BIT16SZ;
+ PBIT16((uchar*)dp, r->reply.nstat-2);
+ }else{
+ n = r->reply.nstat;
+ memmove(dp, r->reply.stat, n);
+ validstat(dp, n);
+ mntdirfix(dp, c);
+ }
+ poperror();
+ mntfree(r);
+ return n;
+}
+
+static Chan*
+mntopencreate(int type, Chan *c, char *name, int omode, ulong perm)
+{
+ Mnt *m;
+ Mntrpc *r;
+
+ m = mntchk(c);
+ r = mntralloc(c, m->msize);
+ if(waserror()) {
+ mntfree(r);
+ nexterror();
+ }
+ r->request.type = type;
+ r->request.fid = c->fid;
+ r->request.mode = omode;
+ if(type == Tcreate){
+ r->request.perm = perm;
+ r->request.name = name;
+ }
+ mountrpc(m, r);
+
+ c->qid = r->reply.qid;
+ c->offset = 0;
+ c->mode = openmode(omode);
+ c->iounit = r->reply.iounit;
+ if(c->iounit == 0 || c->iounit > m->msize-IOHDRSZ)
+ c->iounit = m->msize-IOHDRSZ;
+ c->flag |= COPEN;
+ poperror();
+ mntfree(r);
+
+ if(c->flag & CCACHE)
+ copen(c);
+
+ return c;
+}
+
+static Chan*
+mntopen(Chan *c, int omode)
+{
+ return mntopencreate(Topen, c, nil, omode, 0);
+}
+
+static void
+mntcreate(Chan *c, char *name, int omode, ulong perm)
+{
+ mntopencreate(Tcreate, c, name, omode, perm);
+}
+
+static void
+mntclunk(Chan *c, int t)
+{
+ Mnt *m;
+ Mntrpc *r;
+
+ m = mntchk(c);
+ r = mntralloc(c, m->msize);
+ if(waserror()){
+ mntfree(r);
+ nexterror();
+ }
+
+ r->request.type = t;
+ r->request.fid = c->fid;
+ mountrpc(m, r);
+ mntfree(r);
+ poperror();
+}
+
+void
+muxclose(Mnt *m)
+{
+ Mntrpc *q, *r;
+
+ for(q = m->queue; q; q = r) {
+ r = q->list;
+ mntfree(q);
+ }
+ m->id = 0;
+ free(m->version);
+ m->version = nil;
+ mntpntfree(m);
+}
+
+void
+mntpntfree(Mnt *m)
+{
+ Mnt *f, **l;
+ Queue *q;
+
+ lock(&mntalloc);
+ l = &mntalloc.list;
+ for(f = *l; f; f = f->list) {
+ if(f == m) {
+ *l = m->list;
+ break;
+ }
+ l = &f->list;
+ }
+ m->list = mntalloc.mntfree;
+ mntalloc.mntfree = m;
+ q = m->q;
+ unlock(&mntalloc);
+
+ qfree(q);
+}
+
+static void
+mntclose(Chan *c)
+{
+ mntclunk(c, Tclunk);
+}
+
+static void
+mntremove(Chan *c)
+{
+ mntclunk(c, Tremove);
+}
+
+static int
+mntwstat(Chan *c, uchar *dp, int n)
+{
+ Mnt *m;
+ Mntrpc *r;
+
+ m = mntchk(c);
+ r = mntralloc(c, m->msize);
+ if(waserror()) {
+ mntfree(r);
+ nexterror();
+ }
+ r->request.type = Twstat;
+ r->request.fid = c->fid;
+ r->request.nstat = n;
+ r->request.stat = dp;
+ mountrpc(m, r);
+ poperror();
+ mntfree(r);
+ return n;
+}
+
+static long
+mntread(Chan *c, void *buf, long n, vlong off)
+{
+ uchar *p, *e;
+ int nc, cache, isdir, dirlen;
+
+ isdir = 0;
+ cache = c->flag & CCACHE;
+ if(c->qid.type & QTDIR) {
+ cache = 0;
+ isdir = 1;
+ }
+
+ p = buf;
+ if(cache) {
+ nc = cread(c, buf, n, off);
+ if(nc > 0) {
+ n -= nc;
+ if(n == 0)
+ return nc;
+ p += nc;
+ off += nc;
+ }
+ n = mntrdwr(Tread, c, p, n, off);
+ cupdate(c, p, n, off);
+ return n + nc;
+ }
+
+ n = mntrdwr(Tread, c, buf, n, off);
+ if(isdir) {
+ for(e = &p[n]; p+BIT16SZ < e; p += dirlen){
+ dirlen = BIT16SZ+GBIT16(p);
+ if(p+dirlen > e)
+ break;
+ validstat(p, dirlen);
+ mntdirfix(p, c);
+ }
+ if(p != e)
+ error(Esbadstat);
+ }
+ return n;
+}
+
+static long
+mntwrite(Chan *c, void *buf, long n, vlong off)
+{
+ return mntrdwr(Twrite, c, buf, n, off);
+}
+
+long
+mntrdwr(int type, Chan *c, void *buf, long n, vlong off)
+{
+ Mnt *m;
+ Mntrpc *r;
+ char *uba;
+ int cache;
+ ulong cnt, nr, nreq;
+
+ m = mntchk(c);
+ uba = buf;
+ cnt = 0;
+ cache = c->flag & CCACHE;
+ if(c->qid.type & QTDIR)
+ cache = 0;
+ for(;;) {
+ r = mntralloc(c, m->msize);
+ if(waserror()) {
+ mntfree(r);
+ nexterror();
+ }
+ r->request.type = type;
+ r->request.fid = c->fid;
+ r->request.offset = off;
+ r->request.data = uba;
+ nr = n;
+ if(nr > m->msize-IOHDRSZ)
+ nr = m->msize-IOHDRSZ;
+ r->request.count = nr;
+ mountrpc(m, r);
+ nreq = r->request.count;
+ nr = r->reply.count;
+ if(nr > nreq)
+ nr = nreq;
+
+ if(type == Tread)
+ r->b = bl2mem((uchar*)uba, r->b, nr);
+ else if(cache)
+ cwrite(c, (uchar*)uba, nr, off);
+
+ poperror();
+ mntfree(r);
+ off += nr;
+ uba += nr;
+ cnt += nr;
+ n -= nr;
+ if(nr != nreq || n == 0 || up->nnote)
+ break;
+ }
+ return cnt;
+}
+
+void
+mountrpc(Mnt *m, Mntrpc *r)
+{
+ char *sn, *cn;
+ int t;
+
+ r->reply.tag = 0;
+ r->reply.type = Tmax; /* can't ever be a valid message type */
+
+ mountio(m, r);
+
+ t = r->reply.type;
+ switch(t) {
+ case Rerror:
+ error(r->reply.ename);
+ case Rflush:
+ error(Eintr);
+ default:
+ if(t == r->request.type+1)
+ break;
+ sn = "?";
+ if(m->c->path != nil)
+ sn = m->c->path->s;
+ cn = "?";
+ if(r->c != nil && r->c->path != nil)
+ cn = r->c->path->s;
+ print("mnt: proc %s %lud: mismatch from %s %s rep %#p tag %d fid %d T%d R%d rp %d\n",
+ up->text, up->pid, sn, cn,
+ r, r->request.tag, r->request.fid, r->request.type,
+ r->reply.type, r->reply.tag);
+ error(Emountrpc);
+ }
+}
+
+void
+mountio(Mnt *m, Mntrpc *r)
+{
+ int n;
+
+ while(waserror()) {
+ if(m->rip == up)
+ mntgate(m);
+ if(strcmp(up->errstr, Eintr) != 0){
+ mntflushfree(m, r);
+ nexterror();
+ }
+ r = mntflushalloc(r, m->msize);
+ }
+
+ lock(m);
+ r->m = m;
+ r->list = m->queue;
+ m->queue = r;
+ unlock(m);
+
+ /* Transmit a file system rpc */
+ if(m->msize == 0)
+ panic("msize");
+ n = convS2M(&r->request, r->rpc, m->msize);
+ if(n < 0)
+ panic("bad message type in mountio");
+ if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n)
+ error(Emountrpc);
+ r->stime = fastticks(nil);
+ r->reqlen = n;
+
+ /* Gate readers onto the mount point one at a time */
+ for(;;) {
+ lock(m);
+ if(m->rip == 0)
+ break;
+ unlock(m);
+ sleep(&r->r, rpcattn, r);
+ if(r->done){
+ poperror();
+ mntflushfree(m, r);
+ return;
+ }
+ }
+ m->rip = up;
+ unlock(m);
+ while(r->done == 0) {
+ if(mntrpcread(m, r) < 0)
+ error(Emountrpc);
+ mountmux(m, r);
+ }
+ mntgate(m);
+ poperror();
+ mntflushfree(m, r);
+}
+
+static int
+doread(Mnt *m, int len)
+{
+ Block *b;
+
+ while(qlen(m->q) < len){
+ b = devtab[m->c->type]->bread(m->c, m->msize, 0);
+ if(b == nil)
+ return -1;
+ if(blocklen(b) == 0){
+ freeblist(b);
+ return -1;
+ }
+ qaddlist(m->q, b);
+ }
+ return 0;
+}
+
+int
+mntrpcread(Mnt *m, Mntrpc *r)
+{
+ int i, t, len, hlen;
+ Block *b, **l, *nb;
+
+ r->reply.type = 0;
+ r->reply.tag = 0;
+
+ /* read at least length, type, and tag and pullup to a single block */
+ if(doread(m, BIT32SZ+BIT8SZ+BIT16SZ) < 0)
+ return -1;
+ nb = pullupqueue(m->q, BIT32SZ+BIT8SZ+BIT16SZ);
+
+ /* read in the rest of the message, avoid ridiculous (for now) message sizes */
+ len = GBIT32(nb->rp);
+ if(len > m->msize){
+ qdiscard(m->q, qlen(m->q));
+ return -1;
+ }
+ if(doread(m, len) < 0)
+ return -1;
+
+ /* pullup the header (i.e. everything except data) */
+ t = nb->rp[BIT32SZ];
+ switch(t){
+ case Rread:
+ hlen = BIT32SZ+BIT8SZ+BIT16SZ+BIT32SZ;
+ break;
+ default:
+ hlen = len;
+ break;
+ }
+ nb = pullupqueue(m->q, hlen);
+
+ if(convM2S(nb->rp, len, &r->reply) <= 0){
+ /* bad message, dump it */
+ print("mntrpcread: convM2S failed\n");
+ qdiscard(m->q, len);
+ return -1;
+ }
+
+ /* hang the data off of the fcall struct */
+ l = &r->b;
+ *l = nil;
+ do {
+ b = qremove(m->q);
+ if(hlen > 0){
+ b->rp += hlen;
+ len -= hlen;
+ hlen = 0;
+ }
+ i = BLEN(b);
+ if(i <= len){
+ len -= i;
+ *l = b;
+ l = &(b->next);
+ } else {
+ /* split block and put unused bit back */
+ nb = allocb(i-len);
+ memmove(nb->wp, b->rp+len, i-len);
+ b->wp = b->rp+len;
+ nb->wp += i-len;
+ qputback(m->q, nb);
+ *l = b;
+ return 0;
+ }
+ }while(len > 0);
+
+ return 0;
+}
+
+void
+mntgate(Mnt *m)
+{
+ Mntrpc *q;
+
+ lock(m);
+ m->rip = 0;
+ for(q = m->queue; q; q = q->list) {
+ if(q->done == 0)
+ if(wakeup(&q->r))
+ break;
+ }
+ unlock(m);
+}
+
+void
+mountmux(Mnt *m, Mntrpc *r)
+{
+ Mntrpc **l, *q;
+
+ lock(m);
+ l = &m->queue;
+ for(q = *l; q; q = q->list) {
+ /* look for a reply to a message */
+ if(q->request.tag == r->reply.tag) {
+ *l = q->list;
+ if(q != r) {
+ /*
+ * Completed someone else.
+ * Trade pointers to receive buffer.
+ */
+ q->reply = r->reply;
+ q->b = r->b;
+ r->b = nil;
+ }
+ q->done = 1;
+ unlock(m);
+ if(mntstats != nil)
+ (*mntstats)(q->request.type,
+ m->c, q->stime,
+ q->reqlen + r->replen);
+ if(q != r)
+ wakeup(&q->r);
+ return;
+ }
+ l = &q->list;
+ }
+ unlock(m);
+ print("unexpected reply tag %ud; type %d\n", r->reply.tag, r->reply.type);
+}
+
+/*
+ * Create a new flush request and chain the previous
+ * requests from it
+ */
+Mntrpc*
+mntflushalloc(Mntrpc *r, ulong iounit)
+{
+ Mntrpc *fr;
+
+ fr = mntralloc(0, iounit);
+
+ fr->request.type = Tflush;
+ if(r->request.type == Tflush)
+ fr->request.oldtag = r->request.oldtag;
+ else
+ fr->request.oldtag = r->request.tag;
+ fr->flushed = r;
+
+ return fr;
+}
+
+/*
+ * Free a chain of flushes. Remove each unanswered
+ * flush and the original message from the unanswered
+ * request queue. Mark the original message as done
+ * and if it hasn't been answered set the reply to to
+ * Rflush.
+ */
+void
+mntflushfree(Mnt *m, Mntrpc *r)
+{
+ Mntrpc *fr;
+
+ while(r){
+ fr = r->flushed;
+ if(!r->done){
+ r->reply.type = Rflush;
+ mntqrm(m, r);
+ }
+ if(fr)
+ mntfree(r);
+ r = fr;
+ }
+}
+
+int
+alloctag(void)
+{
+ int i, j;
+ ulong v;
+
+ for(i = 0; i < NMASK; i++){
+ v = mntalloc.tagmask[i];
+ if(v == ~0UL)
+ continue;
+ for(j = 0; j < 1<<TAGSHIFT; j++)
+ if((v & (1<<j)) == 0){
+ mntalloc.tagmask[i] |= 1<<j;
+ return (i<<TAGSHIFT) + j;
+ }
+ }
+ panic("no friggin tags left");
+ return NOTAG;
+}
+
+void
+freetag(int t)
+{
+ mntalloc.tagmask[t>>TAGSHIFT] &= ~(1<<(t&TAGMASK));
+}
+
+Mntrpc*
+mntralloc(Chan *c, ulong msize)
+{
+ Mntrpc *new;
+
+ lock(&mntalloc);
+ new = mntalloc.rpcfree;
+ if(new == nil){
+ new = malloc(sizeof(Mntrpc));
+ if(new == nil) {
+ unlock(&mntalloc);
+ exhausted("mount rpc header");
+ }
+ /*
+ * The header is split from the data buffer as
+ * mountmux may swap the buffer with another header.
+ */
+ new->rpc = mallocz(msize, 0);
+ if(new->rpc == nil){
+ free(new);
+ unlock(&mntalloc);
+ exhausted("mount rpc buffer");
+ }
+ new->rpclen = msize;
+ new->request.tag = alloctag();
+ }
+ else {
+ mntalloc.rpcfree = new->list;
+ mntalloc.nrpcfree--;
+ if(new->rpclen < msize){
+ free(new->rpc);
+ new->rpc = mallocz(msize, 0);
+ if(new->rpc == nil){
+ free(new);
+ mntalloc.nrpcused--;
+ unlock(&mntalloc);
+ exhausted("mount rpc buffer");
+ }
+ new->rpclen = msize;
+ }
+ }
+ mntalloc.nrpcused++;
+ unlock(&mntalloc);
+ new->c = c;
+ new->done = 0;
+ new->flushed = nil;
+ new->b = nil;
+ return new;
+}
+
+void
+mntfree(Mntrpc *r)
+{
+ if(r->b != nil)
+ freeblist(r->b);
+ lock(&mntalloc);
+ if(mntalloc.nrpcfree >= 10){
+ free(r->rpc);
+ freetag(r->request.tag);
+ free(r);
+ }
+ else{
+ r->list = mntalloc.rpcfree;
+ mntalloc.rpcfree = r;
+ mntalloc.nrpcfree++;
+ }
+ mntalloc.nrpcused--;
+ unlock(&mntalloc);
+}
+
+void
+mntqrm(Mnt *m, Mntrpc *r)
+{
+ Mntrpc **l, *f;
+
+ lock(m);
+ r->done = 1;
+
+ l = &m->queue;
+ for(f = *l; f; f = f->list) {
+ if(f == r) {
+ *l = r->list;
+ break;
+ }
+ l = &f->list;
+ }
+ unlock(m);
+}
+
+Mnt*
+mntchk(Chan *c)
+{
+ Mnt *m;
+
+ /* This routine is mostly vestiges of prior lives; now it's just sanity checking */
+
+ if(c->mchan == nil)
+ panic("mntchk 1: nil mchan c %s\n", chanpath(c));
+
+ m = c->mchan->mux;
+
+ if(m == nil)
+ print("mntchk 2: nil mux c %s c->mchan %s \n", chanpath(c), chanpath(c->mchan));
+
+ /*
+ * Was it closed and reused (was error(Eshutdown); now, it cannot happen)
+ */
+ if(m->id == 0 || m->id >= c->dev)
+ panic("mntchk 3: can't happen");
+
+ return m;
+}
+
+/*
+ * Rewrite channel type and dev for in-flight data to
+ * reflect local values. These entries are known to be
+ * the first two in the Dir encoding after the count.
+ */
+void
+mntdirfix(uchar *dirbuf, Chan *c)
+{
+ uint r;
+
+ r = devtab[c->type]->dc;
+ dirbuf += BIT16SZ; /* skip count */
+ PBIT16(dirbuf, r);
+ dirbuf += BIT16SZ;
+ PBIT32(dirbuf, c->dev);
+}
+
+int
+rpcattn(void *v)
+{
+ Mntrpc *r;
+
+ r = v;
+ return r->done || r->m->rip == 0;
+}
+
+Dev mntdevtab = {
+ 'M',
+ "mnt",
+
+ mntreset,
+ devinit,
+ devshutdown,
+ mntattach,
+ mntwalk,
+ mntstat,
+ mntopen,
+ mntcreate,
+ mntclose,
+ mntread,
+ devbread,
+ mntwrite,
+ devbwrite,
+ mntremove,
+ mntwstat,
+};
diff --git a/sys/src/9/port/devmouse.c b/sys/src/9/port/devmouse.c
new file mode 100755
index 000000000..5b620720c
--- /dev/null
+++ b/sys/src/9/port/devmouse.c
@@ -0,0 +1,790 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+enum {
+ ScrollUp = 0x08,
+ ScrollDown = 0x10,
+ ScrollLeft = 0x20,
+ ScrollRight = 0x40,
+};
+
+typedef struct Mouseinfo Mouseinfo;
+typedef struct Mousestate Mousestate;
+
+struct Mousestate
+{
+ Point xy; /* mouse.xy */
+ int buttons; /* mouse.buttons */
+ ulong counter; /* increments every update */
+ ulong msec; /* time of last event */
+};
+
+struct Mouseinfo
+{
+ Lock;
+ Mousestate;
+ int dx;
+ int dy;
+ int track; /* dx & dy updated */
+ int redraw; /* update cursor on screen */
+ ulong lastcounter; /* value when /dev/mouse read */
+ ulong lastresize;
+ ulong resize;
+ Rendez r;
+ Ref;
+ QLock;
+ int open;
+ int inopen;
+ int acceleration;
+ int maxacc;
+ Mousestate queue[16]; /* circular buffer of click events */
+ int ri; /* read index into queue */
+ int wi; /* write index into queue */
+ uchar qfull; /* queue is full */
+};
+
+enum
+{
+ CMbuttonmap,
+ CMscrollswap,
+ CMswap,
+ CMwildcard,
+};
+
+static Cmdtab mousectlmsg[] =
+{
+ CMbuttonmap, "buttonmap", 0,
+ CMscrollswap, "scrollswap", 0,
+ CMswap, "swap", 1,
+ CMwildcard, "*", 0,
+};
+
+Mouseinfo mouse;
+Cursorinfo cursor;
+int mouseshifted;
+int kbdbuttons;
+void (*kbdmouse)(int);
+Cursor curs;
+
+void Cursortocursor(Cursor*);
+int mousechanged(void*);
+
+static void mouseclock(void);
+static void xkbdmouse(int);
+
+enum{
+ Qdir,
+ Qcursor,
+ Qmouse,
+ Qmousein,
+ Qmousectl,
+};
+
+static Dirtab mousedir[]={
+ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
+ "cursor", {Qcursor}, 0, 0666,
+ "mouse", {Qmouse}, 0, 0666,
+ "mousein", {Qmousein}, 0, 0220,
+ "mousectl", {Qmousectl}, 0, 0220,
+};
+
+static uchar buttonmap[8] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+};
+static int mouseswap;
+static int scrollswap;
+static ulong mousetime;
+
+extern Memimage* gscreen;
+extern ulong kerndate;
+
+static void
+mousereset(void)
+{
+ if(!conf.monitor)
+ return;
+
+ curs = arrow;
+ Cursortocursor(&arrow);
+ /* redraw cursor about 30 times per second */
+ addclock0link(mouseclock, 33);
+}
+
+static void
+mousefromkbd(int buttons)
+{
+ kbdbuttons = buttons;
+ mousetrack(0, 0, 0, TK2MS(MACHP(0)->ticks));
+}
+
+static int
+mousedevgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
+{
+ int rc;
+
+ rc = devgen(c, name, tab, ntab, i, dp);
+ if(rc != -1)
+ dp->atime = mousetime;
+ return rc;
+}
+
+static void
+mouseinit(void)
+{
+ if(!conf.monitor)
+ return;
+
+ curs = arrow;
+ Cursortocursor(&arrow);
+ cursoron(1);
+ kbdmouse = mousefromkbd;
+ mousetime = seconds();
+}
+
+static Chan*
+mouseattach(char *spec)
+{
+ if(!conf.monitor)
+ error(Egreg);
+ return devattach('m', spec);
+}
+
+static Walkqid*
+mousewalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ Walkqid *wq;
+
+ /*
+ * We use devgen() and not mousedevgen() here
+ * see "Ugly problem" in dev.c/devwalk()
+ */
+ wq = devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
+ if(wq != nil && wq->clone != c && wq->clone != nil && (wq->clone->qid.type&QTDIR)==0)
+ incref(&mouse);
+ return wq;
+}
+
+static int
+mousestat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, mousedir, nelem(mousedir), mousedevgen);
+}
+
+static Chan*
+mouseopen(Chan *c, int omode)
+{
+ switch((ulong)c->qid.path){
+ case Qdir:
+ if(omode != OREAD)
+ error(Eperm);
+ break;
+ case Qmouse:
+ lock(&mouse);
+ if(mouse.open){
+ unlock(&mouse);
+ error(Einuse);
+ }
+ mouse.open = 1;
+ mouse.ref++;
+ mouse.lastresize = mouse.resize;
+ unlock(&mouse);
+ break;
+ case Qmousein:
+ if(!iseve())
+ error(Eperm);
+ lock(&mouse);
+ if(mouse.inopen){
+ unlock(&mouse);
+ error(Einuse);
+ }
+ mouse.inopen = 1;
+ unlock(&mouse);
+ break;
+ default:
+ incref(&mouse);
+ }
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+static void
+mousecreate(Chan*, char*, int, ulong)
+{
+ if(!conf.monitor)
+ error(Egreg);
+ error(Eperm);
+}
+
+static void
+mouseclose(Chan *c)
+{
+ if((c->qid.type&QTDIR)==0 && (c->flag&COPEN)){
+ lock(&mouse);
+ if(c->qid.path == Qmouse)
+ mouse.open = 0;
+ else if(c->qid.path == Qmousein){
+ mouse.inopen = 0;
+ unlock(&mouse);
+ return;
+ }
+ if(--mouse.ref == 0){
+ cursoroff(1);
+ curs = arrow;
+ Cursortocursor(&arrow);
+ cursoron(1);
+ }
+ unlock(&mouse);
+ }
+}
+
+
+static long
+mouseread(Chan *c, void *va, long n, vlong off)
+{
+ char buf[1+4*12+1];
+ uchar *p;
+ static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };
+ ulong offset = off;
+ Mousestate m;
+ int b;
+
+ p = va;
+ switch((ulong)c->qid.path){
+ case Qdir:
+ return devdirread(c, va, n, mousedir, nelem(mousedir), mousedevgen);
+
+ case Qcursor:
+ if(offset != 0)
+ return 0;
+ if(n < 2*4+2*2*16)
+ error(Eshort);
+ n = 2*4+2*2*16;
+ lock(&cursor);
+ BPLONG(p+0, curs.offset.x);
+ BPLONG(p+4, curs.offset.y);
+ memmove(p+8, curs.clr, 2*16);
+ memmove(p+40, curs.set, 2*16);
+ unlock(&cursor);
+ return n;
+
+ case Qmouse:
+ while(mousechanged(0) == 0)
+ sleep(&mouse.r, mousechanged, 0);
+
+ mouse.qfull = 0;
+ mousetime = seconds();
+
+ /*
+ * No lock of the indices is necessary here, because ri is only
+ * updated by us, and there is only one mouse reader
+ * at a time. I suppose that more than one process
+ * could try to read the fd at one time, but such behavior
+ * is degenerate and already violates the calling
+ * conventions for sleep above.
+ */
+ if(mouse.ri != mouse.wi) {
+ m = mouse.queue[mouse.ri];
+ if(++mouse.ri == nelem(mouse.queue))
+ mouse.ri = 0;
+ } else {
+ while(!canlock(&cursor))
+ tsleep(&up->sleep, return0, 0, TK2MS(1));
+
+ m = mouse.Mousestate;
+ unlock(&cursor);
+ }
+
+ b = buttonmap[m.buttons&7];
+ /* put buttons 4 and 5 back in */
+ b |= m.buttons & (3<<3);
+ if (scrollswap)
+ if (b == 8)
+ b = 16;
+ else if (b == 16)
+ b = 8;
+ sprint(buf, "m%11d %11d %11d %11lud ",
+ m.xy.x, m.xy.y,
+ b,
+ m.msec);
+ 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;
+ }
+ return 0;
+}
+
+static void
+setbuttonmap(char* map)
+{
+ int i, x, one, two, three;
+
+ one = two = three = 0;
+ for(i = 0; i < 3; i++){
+ if(map[i] == 0)
+ error(Ebadarg);
+ if(map[i] == '1'){
+ if(one)
+ error(Ebadarg);
+ one = 1<<i;
+ }
+ else if(map[i] == '2'){
+ if(two)
+ error(Ebadarg);
+ two = 1<<i;
+ }
+ else if(map[i] == '3'){
+ if(three)
+ error(Ebadarg);
+ three = 1<<i;
+ }
+ else
+ error(Ebadarg);
+ }
+ if(map[i])
+ error(Ebadarg);
+
+ memset(buttonmap, 0, 8);
+ for(i = 0; i < 8; i++){
+ x = 0;
+ if(i & 1)
+ x |= one;
+ if(i & 2)
+ x |= two;
+ if(i & 4)
+ x |= three;
+ buttonmap[x] = i;
+ }
+}
+
+static long
+mousewrite(Chan *c, void *va, long n, vlong)
+{
+ char *p;
+ Point pt;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ char buf[64];
+ int b, msec;
+
+ p = va;
+ switch((ulong)c->qid.path){
+ case Qdir:
+ error(Eisdir);
+
+ case Qcursor:
+ cursoroff(1);
+ if(n < 2*4+2*2*16){
+ curs = arrow;
+ Cursortocursor(&arrow);
+ }else{
+ n = 2*4+2*2*16;
+ curs.offset.x = BGLONG(p+0);
+ curs.offset.y = BGLONG(p+4);
+ memmove(curs.clr, p+8, 2*16);
+ memmove(curs.set, p+40, 2*16);
+ Cursortocursor(&curs);
+ }
+ qlock(&mouse);
+ mouse.redraw = 1;
+ mouseclock();
+ qunlock(&mouse);
+ cursoron(1);
+ return n;
+
+ case Qmousectl:
+ cb = parsecmd(va, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+
+ ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg));
+
+ switch(ct->index){
+ case CMswap:
+ if(mouseswap)
+ setbuttonmap("123");
+ else
+ setbuttonmap("321");
+ mouseswap ^= 1;
+ break;
+
+ case CMscrollswap:
+ scrollswap ^= 1;
+ break;
+
+ case CMbuttonmap:
+ if(cb->nf == 1)
+ setbuttonmap("123");
+ else
+ setbuttonmap(cb->f[1]);
+ break;
+
+ case CMwildcard:
+ mousectl(cb);
+ break;
+ }
+
+ free(cb);
+ poperror();
+ return n;
+
+ case Qmousein:
+ if(n > sizeof buf-1)
+ n = sizeof buf -1;
+ memmove(buf, va, n);
+ buf[n] = 0;
+ p = 0;
+ pt.x = strtol(buf+1, &p, 0);
+ if(p == 0)
+ error(Eshort);
+ pt.y = strtol(p, &p, 0);
+ if(p == 0)
+ error(Eshort);
+ b = strtol(p, &p, 0);
+ msec = strtol(p, &p, 0);
+ if(msec == 0)
+ msec = TK2MS(MACHP(0)->ticks);
+ mousetrack(pt.x, pt.y, b, msec);
+ return n;
+
+ case Qmouse:
+ if(n > sizeof buf-1)
+ n = sizeof buf -1;
+ memmove(buf, va, n);
+ buf[n] = 0;
+ p = 0;
+ pt.x = strtoul(buf+1, &p, 0);
+ if(p == 0)
+ error(Eshort);
+ pt.y = strtoul(p, 0, 0);
+ qlock(&mouse);
+ if(ptinrect(pt, gscreen->r)){
+ mouse.xy = pt;
+ mouse.redraw = 1;
+ mouse.track = 1;
+ mouseclock();
+ }
+ qunlock(&mouse);
+ return n;
+ }
+
+ error(Egreg);
+ return -1;
+}
+
+Dev mousedevtab = {
+ 'm',
+ "mouse",
+
+ mousereset,
+ mouseinit,
+ devshutdown,
+ mouseattach,
+ mousewalk,
+ mousestat,
+ mouseopen,
+ mousecreate,
+ mouseclose,
+ mouseread,
+ devbread,
+ mousewrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+void
+Cursortocursor(Cursor *c)
+{
+ lock(&cursor);
+ memmove(&cursor.Cursor, c, sizeof(Cursor));
+ setcursor(c);
+ unlock(&cursor);
+}
+
+
+/*
+ * called by the clock routine to redraw the cursor
+ */
+static void
+mouseclock(void)
+{
+ if(mouse.track){
+ mousetrack(mouse.dx, mouse.dy, mouse.buttons, TK2MS(MACHP(0)->ticks));
+ mouse.track = 0;
+ mouse.dx = 0;
+ mouse.dy = 0;
+ }
+ if(mouse.redraw && canlock(&cursor)){
+ mouse.redraw = 0;
+ cursoroff(0);
+ mouse.redraw = cursoron(0);
+ unlock(&cursor);
+ }
+ drawactive(0);
+}
+
+static int
+scale(int x)
+{
+ int sign = 1;
+
+ if(x < 0){
+ sign = -1;
+ x = -x;
+ }
+ switch(x){
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ break;
+ case 4:
+ x = 6 + (mouse.acceleration>>2);
+ break;
+ case 5:
+ x = 9 + (mouse.acceleration>>1);
+ break;
+ default:
+ x *= mouse.maxacc;
+ break;
+ }
+ return sign*x;
+}
+
+/*
+ * called at interrupt level to update the structure and
+ * awaken any waiting procs.
+ */
+void
+mousetrack(int dx, int dy, int b, int msec)
+{
+ int x, y, lastb;
+
+ if(gscreen==nil)
+ return;
+
+ if(mouse.acceleration){
+ dx = scale(dx);
+ dy = scale(dy);
+ }
+ x = mouse.xy.x + dx;
+ if(x < gscreen->clipr.min.x)
+ x = gscreen->clipr.min.x;
+ if(x >= gscreen->clipr.max.x)
+ x = gscreen->clipr.max.x;
+ y = mouse.xy.y + dy;
+ if(y < gscreen->clipr.min.y)
+ y = gscreen->clipr.min.y;
+ if(y >= gscreen->clipr.max.y)
+ y = gscreen->clipr.max.y;
+
+ lastb = mouse.buttons;
+ mouse.xy = Pt(x, y);
+ mouse.buttons = b|kbdbuttons;
+ mouse.redraw = 1;
+ mouse.counter++;
+ mouse.msec = msec;
+
+ /*
+ * if the queue fills, we discard the entire queue and don't
+ * queue any more events until a reader polls the mouse.
+ */
+ if(!mouse.qfull && lastb != b) { /* add to ring */
+ mouse.queue[mouse.wi] = mouse.Mousestate;
+ if(++mouse.wi == nelem(mouse.queue))
+ mouse.wi = 0;
+ if(mouse.wi == mouse.ri)
+ mouse.qfull = 1;
+ }
+ wakeup(&mouse.r);
+ drawactive(1);
+}
+
+/*
+ * microsoft 3 button, 7 bit bytes
+ *
+ * byte 0 - 1 L R Y7 Y6 X7 X6
+ * byte 1 - 0 X5 X4 X3 X2 X1 X0
+ * byte 2 - 0 Y5 Y4 Y3 Y2 Y1 Y0
+ * byte 3 - 0 M x x x x x (optional)
+ *
+ * shift & right button is the same as middle button (for 2 button mice)
+ */
+int
+m3mouseputc(Queue*, int c)
+{
+ static uchar msg[3];
+ static int nb;
+ static int middle;
+ static uchar b[] = { 0, 4, 1, 5, 0, 2, 1, 3 };
+ short x;
+ int dx, dy, newbuttons;
+ static ulong lasttick;
+ ulong m;
+
+ /* Resynchronize in stream with timing. */
+ m = MACHP(0)->ticks;
+ if(TK2SEC(m - lasttick) > 2)
+ nb = 0;
+ lasttick = m;
+
+ if(nb==0){
+ /*
+ * an extra byte comes for middle button motion.
+ * only two possible values for the extra byte.
+ */
+ if(c == 0x00 || c == 0x20){
+ /* an extra byte gets sent for the middle button */
+ middle = (c&0x20) ? 2 : 0;
+ newbuttons = (mouse.buttons & ~2) | middle;
+ mousetrack(0, 0, newbuttons, TK2MS(MACHP(0)->ticks));
+ return 0;
+ }
+ }
+ msg[nb] = c;
+ if(++nb == 3){
+ nb = 0;
+ newbuttons = middle | b[(msg[0]>>4)&3 | (mouseshifted ? 4 : 0)];
+ x = (msg[0]&0x3)<<14;
+ dx = (x>>8) | msg[1];
+ x = (msg[0]&0xc)<<12;
+ dy = (x>>8) | msg[2];
+ mousetrack(dx, dy, newbuttons, TK2MS(MACHP(0)->ticks));
+ }
+ return 0;
+}
+
+/*
+ * microsoft intellimouse 3 buttons + scroll
+ * byte 0 - 1 L R Y7 Y6 X7 X6
+ * byte 1 - 0 X5 X4 X3 X2 X1 X0
+ * byte 2 - 0 Y5 Y4 Y3 Y2 Y1 Y0
+ * byte 3 - 0 0 M % % % %
+ *
+ * %: 0xf => U , 0x1 => D
+ *
+ * L: left
+ * R: right
+ * U: up
+ * D: down
+ */
+int
+m5mouseputc(Queue*, int c)
+{
+ static uchar msg[3];
+ static int nb;
+ static ulong lasttick;
+ ulong m;
+
+ /* Resynchronize in stream with timing. */
+ m = MACHP(0)->ticks;
+ if(TK2SEC(m - lasttick) > 2)
+ nb = 0;
+ lasttick = m;
+
+ msg[nb++] = c & 0x7f;
+ if (nb == 4) {
+ schar dx,dy,newbuttons;
+ dx = msg[1] | (msg[0] & 0x3) << 6;
+ dy = msg[2] | (msg[0] & 0xc) << 4;
+ newbuttons =
+ (msg[0] & 0x10) >> (mouseshifted ? 3 : 2)
+ | (msg[0] & 0x20) >> 5
+ | ( msg[3] == 0x10 ? 0x02 :
+ msg[3] == 0x0f ? ScrollUp :
+ msg[3] == 0x01 ? ScrollDown : 0 );
+ mousetrack(dx, dy, newbuttons, TK2MS(MACHP(0)->ticks));
+ nb = 0;
+ }
+ return 0;
+}
+
+/*
+ * Logitech 5 byte packed binary mouse format, 8 bit bytes
+ *
+ * shift & right button is the same as middle button (for 2 button mice)
+ */
+int
+mouseputc(Queue*, int c)
+{
+ static short msg[5];
+ static int nb;
+ static uchar b[] = {0, 4, 2, 6, 1, 5, 3, 7, 0, 2, 2, 6, 1, 3, 3, 7};
+ int dx, dy, newbuttons;
+ static ulong lasttick;
+ ulong m;
+
+ /* Resynchronize in stream with timing. */
+ m = MACHP(0)->ticks;
+ if(TK2SEC(m - lasttick) > 2)
+ nb = 0;
+ lasttick = m;
+
+ if((c&0xF0) == 0x80)
+ nb=0;
+ msg[nb] = c;
+ if(c & 0x80)
+ msg[nb] |= ~0xFF; /* sign extend */
+ if(++nb == 5){
+ newbuttons = b[((msg[0]&7)^7) | (mouseshifted ? 8 : 0)];
+ dx = msg[1]+msg[3];
+ dy = -(msg[2]+msg[4]);
+ mousetrack(dx, dy, newbuttons, TK2MS(MACHP(0)->ticks));
+ nb = 0;
+ }
+ return 0;
+}
+
+int
+mousechanged(void*)
+{
+ return mouse.lastcounter != mouse.counter ||
+ mouse.lastresize != mouse.resize;
+}
+
+Point
+mousexy(void)
+{
+ return mouse.xy;
+}
+
+void
+mouseaccelerate(int x)
+{
+ mouse.acceleration = x;
+ if(mouse.acceleration < 3)
+ mouse.maxacc = 2;
+ else
+ mouse.maxacc = mouse.acceleration;
+}
+
+/*
+ * notify reader that screen has been resized
+ */
+void
+mouseresize(void)
+{
+ mouse.resize++;
+ wakeup(&mouse.r);
+}
+
diff --git a/sys/src/9/port/devpipe.c b/sys/src/9/port/devpipe.c
new file mode 100755
index 000000000..bea354b78
--- /dev/null
+++ b/sys/src/9/port/devpipe.c
@@ -0,0 +1,391 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "netif.h"
+
+typedef struct Pipe Pipe;
+struct Pipe
+{
+ QLock;
+ Pipe *next;
+ int ref;
+ ulong path;
+ Queue *q[2];
+ int qref[2];
+};
+
+struct
+{
+ Lock;
+ ulong path;
+} pipealloc;
+
+enum
+{
+ Qdir,
+ Qdata0,
+ Qdata1,
+};
+
+Dirtab pipedir[] =
+{
+ ".", {Qdir,0,QTDIR}, 0, DMDIR|0500,
+ "data", {Qdata0}, 0, 0600,
+ "data1", {Qdata1}, 0, 0600,
+};
+#define NPIPEDIR 3
+
+static void
+pipeinit(void)
+{
+ if(conf.pipeqsize == 0){
+ if(conf.nmach > 1)
+ conf.pipeqsize = 256*1024;
+ else
+ conf.pipeqsize = 32*1024;
+ }
+}
+
+/*
+ * create a pipe, no streams are created until an open
+ */
+static Chan*
+pipeattach(char *spec)
+{
+ Pipe *p;
+ Chan *c;
+
+ c = devattach('|', spec);
+ p = malloc(sizeof(Pipe));
+ if(p == 0)
+ exhausted("memory");
+ p->ref = 1;
+
+ p->q[0] = qopen(conf.pipeqsize, 0, 0, 0);
+ if(p->q[0] == 0){
+ free(p);
+ exhausted("memory");
+ }
+ p->q[1] = qopen(conf.pipeqsize, 0, 0, 0);
+ if(p->q[1] == 0){
+ free(p->q[0]);
+ free(p);
+ exhausted("memory");
+ }
+
+ lock(&pipealloc);
+ p->path = ++pipealloc.path;
+ unlock(&pipealloc);
+
+ mkqid(&c->qid, NETQID(2*p->path, Qdir), 0, QTDIR);
+ c->aux = p;
+ c->dev = 0;
+ return c;
+}
+
+static int
+pipegen(Chan *c, char*, Dirtab *tab, int ntab, int i, Dir *dp)
+{
+ Qid q;
+ int len;
+ Pipe *p;
+
+ if(i == DEVDOTDOT){
+ devdir(c, c->qid, "#|", 0, eve, DMDIR|0555, dp);
+ return 1;
+ }
+ i++; /* skip . */
+ if(tab==0 || i>=ntab)
+ return -1;
+
+ tab += i;
+ p = c->aux;
+ switch((ulong)tab->qid.path){
+ case Qdata0:
+ len = qlen(p->q[0]);
+ break;
+ case Qdata1:
+ len = qlen(p->q[1]);
+ break;
+ default:
+ len = tab->length;
+ break;
+ }
+ mkqid(&q, NETQID(NETID(c->qid.path), tab->qid.path), 0, QTFILE);
+ devdir(c, q, tab->name, len, eve, tab->perm, dp);
+ return 1;
+}
+
+
+static Walkqid*
+pipewalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ Walkqid *wq;
+ Pipe *p;
+
+ wq = devwalk(c, nc, name, nname, pipedir, NPIPEDIR, pipegen);
+ if(wq != nil && wq->clone != nil && wq->clone != c){
+ p = c->aux;
+ qlock(p);
+ p->ref++;
+ if(c->flag & COPEN){
+ print("channel open in pipewalk\n");
+ switch(NETTYPE(c->qid.path)){
+ case Qdata0:
+ p->qref[0]++;
+ break;
+ case Qdata1:
+ p->qref[1]++;
+ break;
+ }
+ }
+ qunlock(p);
+ }
+ return wq;
+}
+
+static int
+pipestat(Chan *c, uchar *db, int n)
+{
+ Pipe *p;
+ Dir dir;
+
+ p = c->aux;
+
+ switch(NETTYPE(c->qid.path)){
+ case Qdir:
+ devdir(c, c->qid, ".", 0, eve, DMDIR|0555, &dir);
+ break;
+ case Qdata0:
+ devdir(c, c->qid, "data", qlen(p->q[0]), eve, 0600, &dir);
+ break;
+ case Qdata1:
+ devdir(c, c->qid, "data1", qlen(p->q[1]), eve, 0600, &dir);
+ break;
+ default:
+ panic("pipestat");
+ }
+ n = convD2M(&dir, db, n);
+ if(n < BIT16SZ)
+ error(Eshortstat);
+ return n;
+}
+
+/*
+ * if the stream doesn't exist, create it
+ */
+static Chan*
+pipeopen(Chan *c, int omode)
+{
+ Pipe *p;
+
+ if(c->qid.type & QTDIR){
+ if(omode != OREAD)
+ error(Ebadarg);
+ c->mode = omode;
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+ }
+
+ p = c->aux;
+ qlock(p);
+ switch(NETTYPE(c->qid.path)){
+ case Qdata0:
+ p->qref[0]++;
+ break;
+ case Qdata1:
+ p->qref[1]++;
+ break;
+ }
+ qunlock(p);
+
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ c->iounit = qiomaxatomic;
+ return c;
+}
+
+static void
+pipeclose(Chan *c)
+{
+ Pipe *p;
+
+ p = c->aux;
+ qlock(p);
+
+ if(c->flag & COPEN){
+ /*
+ * closing either side hangs up the stream
+ */
+ switch(NETTYPE(c->qid.path)){
+ case Qdata0:
+ p->qref[0]--;
+ if(p->qref[0] == 0){
+ qhangup(p->q[1], 0);
+ qclose(p->q[0]);
+ }
+ break;
+ case Qdata1:
+ p->qref[1]--;
+ if(p->qref[1] == 0){
+ qhangup(p->q[0], 0);
+ qclose(p->q[1]);
+ }
+ break;
+ }
+ }
+
+
+ /*
+ * if both sides are closed, they are reusable
+ */
+ if(p->qref[0] == 0 && p->qref[1] == 0){
+ qreopen(p->q[0]);
+ qreopen(p->q[1]);
+ }
+
+ /*
+ * free the structure on last close
+ */
+ p->ref--;
+ if(p->ref == 0){
+ qunlock(p);
+ free(p->q[0]);
+ free(p->q[1]);
+ free(p);
+ } else
+ qunlock(p);
+}
+
+static long
+piperead(Chan *c, void *va, long n, vlong)
+{
+ Pipe *p;
+
+ p = c->aux;
+
+ switch(NETTYPE(c->qid.path)){
+ case Qdir:
+ return devdirread(c, va, n, pipedir, NPIPEDIR, pipegen);
+ case Qdata0:
+ return qread(p->q[0], va, n);
+ case Qdata1:
+ return qread(p->q[1], va, n);
+ default:
+ panic("piperead");
+ }
+ return -1; /* not reached */
+}
+
+static Block*
+pipebread(Chan *c, long n, ulong offset)
+{
+ Pipe *p;
+
+ p = c->aux;
+
+ switch(NETTYPE(c->qid.path)){
+ case Qdata0:
+ return qbread(p->q[0], n);
+ case Qdata1:
+ return qbread(p->q[1], n);
+ }
+
+ return devbread(c, n, offset);
+}
+
+/*
+ * a write to a closed pipe causes a note to be sent to
+ * the process.
+ */
+static long
+pipewrite(Chan *c, void *va, long n, vlong)
+{
+ Pipe *p;
+
+ if(!islo())
+ print("pipewrite hi %#p\n", getcallerpc(&c));
+ if(waserror()) {
+ /* avoid notes when pipe is a mounted queue */
+ if((c->flag & CMSG) == 0)
+ postnote(up, 1, "sys: write on closed pipe", NUser);
+ nexterror();
+ }
+
+ p = c->aux;
+
+ switch(NETTYPE(c->qid.path)){
+ case Qdata0:
+ n = qwrite(p->q[1], va, n);
+ break;
+
+ case Qdata1:
+ n = qwrite(p->q[0], va, n);
+ break;
+
+ default:
+ panic("pipewrite");
+ }
+
+ poperror();
+ return n;
+}
+
+static long
+pipebwrite(Chan *c, Block *bp, ulong)
+{
+ long n;
+ Pipe *p;
+
+ if(waserror()) {
+ /* avoid notes when pipe is a mounted queue */
+ if((c->flag & CMSG) == 0)
+ postnote(up, 1, "sys: write on closed pipe", NUser);
+ nexterror();
+ }
+
+ p = c->aux;
+ switch(NETTYPE(c->qid.path)){
+ case Qdata0:
+ n = qbwrite(p->q[1], bp);
+ break;
+
+ case Qdata1:
+ n = qbwrite(p->q[0], bp);
+ break;
+
+ default:
+ n = 0;
+ panic("pipebwrite");
+ }
+
+ poperror();
+ return n;
+}
+
+Dev pipedevtab = {
+ '|',
+ "pipe",
+
+ devreset,
+ pipeinit,
+ devshutdown,
+ pipeattach,
+ pipewalk,
+ pipestat,
+ pipeopen,
+ devcreate,
+ pipeclose,
+ piperead,
+ pipebread,
+ pipewrite,
+ pipebwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/port/devpnp.c b/sys/src/9/port/devpnp.c
new file mode 100755
index 000000000..805a21303
--- /dev/null
+++ b/sys/src/9/port/devpnp.c
@@ -0,0 +1,691 @@
+/*
+ * ISA PNP 1.0 support + access to PCI configuration space
+ *
+ * TODO
+ * - implement PNP card configuration (setting io bases etc)
+ * - write user program to drive PNP configuration...
+ * - extend PCI raw access to configuration space (writes, byte/short access?)
+ * - implement PCI access to memory/io space/BIOS ROM
+ * - use c->aux instead of performing lookup on each read/write?
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+typedef struct Pnp Pnp;
+typedef struct Card Card;
+
+struct Pnp
+{
+ QLock;
+ int rddata;
+ int debug;
+ Card *cards;
+};
+
+struct Card
+{
+ int csn;
+ ulong id1;
+ ulong id2;
+ char *cfgstr;
+ int ncfg;
+ Card* next;
+};
+
+static Pnp pnp;
+
+#define DPRINT if(pnp.debug) print
+#define XPRINT if(1) print
+
+enum {
+ Address = 0x279,
+ WriteData = 0xa79,
+
+ Qtopdir = 0,
+
+ Qpnpdir,
+ Qpnpctl,
+ Qcsnctl,
+ Qcsnraw,
+
+ Qpcidir,
+ Qpcictl,
+ Qpciraw,
+};
+
+#define TYPE(q) ((ulong)(q).path & 0x0F)
+#define CSN(q) (((ulong)(q).path>>4) & 0xFF)
+#define QID(c, t) (((c)<<4)|(t))
+
+static Dirtab topdir[] = {
+ ".", { Qtopdir, 0, QTDIR }, 0, 0555,
+ "pnp", { Qpnpdir, 0, QTDIR }, 0, 0555,
+ "pci", { Qpcidir, 0, QTDIR }, 0, 0555,
+};
+
+static Dirtab pnpdir[] = {
+ ".", { Qpnpdir, 0, QTDIR }, 0, 0555,
+ "ctl", { Qpnpctl, 0, 0 }, 0, 0666,
+};
+
+extern Dev pnpdevtab;
+static int wrconfig(Card*, char*);
+
+static char key[32] =
+{
+ 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,
+ 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,
+ 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,
+ 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x39,
+};
+
+static void
+cmd(int reg, int val)
+{
+ outb(Address, reg);
+ outb(WriteData, val);
+}
+
+/* Send initiation key, putting each card in Sleep state */
+static void
+initiation(void)
+{
+ int i;
+
+ /* ensure each card's LFSR is reset */
+ outb(Address, 0x00);
+ outb(Address, 0x00);
+
+ /* send initiation key */
+ for (i = 0; i < 32; i++)
+ outb(Address, key[i]);
+}
+
+/* isolation protocol... */
+static int
+readbit(int rddata)
+{
+ int r1, r2;
+
+ r1 = inb(rddata);
+ r2 = inb(rddata);
+ microdelay(250);
+ return (r1 == 0x55) && (r2 == 0xaa);
+}
+
+static int
+isolate(int rddata, ulong *id1, ulong *id2)
+{
+ int i, csum, bit;
+ uchar *p, id[9];
+
+ outb(Address, 0x01); /* point to serial isolation register */
+ delay(1);
+ csum = 0x6a;
+ for(i = 0; i < 64; i++){
+ bit = readbit(rddata);
+ csum = (csum>>1) | (((csum&1) ^ ((csum>>1)&1) ^ bit)<<7);
+ p = &id[i>>3];
+ *p = (*p>>1) | (bit<<7);
+ }
+ for(; i < 72; i++){
+ p = &id[i>>3];
+ *p = (*p>>1) | (readbit(rddata)<<7);
+ }
+ *id1 = (id[3]<<24)|(id[2]<<16)|(id[1]<<8)|id[0];
+ *id2 = (id[7]<<24)|(id[6]<<16)|(id[5]<<8)|id[4];
+ if(*id1 == 0)
+ return 0;
+ if(id[8] != csum)
+ DPRINT("pnp: bad checksum id1 %lux id2 %lux csum %x != %x\n", *id1, *id2, csum, id[8]); /**/
+ return id[8] == csum;
+}
+
+static int
+getresbyte(int rddata)
+{
+ int tries = 0;
+
+ outb(Address, 0x05);
+ while ((inb(rddata) & 1) == 0)
+ if (tries++ > 1000000)
+ error("pnp: timeout waiting for resource data\n");
+ outb(Address, 0x04);
+ return inb(rddata);
+}
+
+static char *
+serial(ulong id1, ulong id2)
+{
+ int i1, i2, i3;
+ ulong x;
+ static char buf[20];
+
+ i1 = (id1>>2)&31;
+ i2 = ((id1<<3)&24)+((id1>>13)&7);
+ i3 = (id1>>8)&31;
+ x = (id1>>8)&0xff00|(id1>>24)&0x00ff;
+ if (i1 > 0 && i1 < 27 && i2 > 0 && i2 < 27 && i3 > 0 && i3 < 27 && (id1 & (1<<7)) == 0)
+ snprint(buf, sizeof(buf), "%c%c%c%.4lux.%lux", 'A'+i1-1, 'A'+i2-1, 'A'+i3-1, x, id2);
+ else
+ snprint(buf, sizeof(buf), "%.4lux%.4lux.%lux", (id1<<8)&0xff00|(id1>>8)&0x00ff, x, id2);
+ return buf;
+}
+
+static Card *
+findcsn(int csn, int create, int dolock)
+{
+ Card *c, *nc, **l;
+
+ if(dolock)
+ qlock(&pnp);
+ l = &pnp.cards;
+ for(c = *l; c != nil; c = *l) {
+ if(c->csn == csn)
+ goto done;
+ if(c->csn > csn)
+ break;
+ l = &c->next;
+ }
+ if(create) {
+ *l = nc = malloc(sizeof(Card));
+ nc->next = c;
+ nc->csn = csn;
+ c = nc;
+ }
+done:
+ if(dolock)
+ qunlock(&pnp);
+ return c;
+}
+
+static int
+newcsn(void)
+{
+ int csn;
+ Card *c;
+
+ csn = 1;
+ for(c = pnp.cards; c != nil; c = c->next) {
+ if(c->csn > csn)
+ break;
+ csn = c->csn+1;
+ }
+ return csn;
+}
+
+static int
+pnpncfg(int rddata)
+{
+ int i, n, x, ncfg, n1, n2;
+
+ ncfg = 0;
+ for (;;) {
+ x = getresbyte(rddata);
+ if((x & 0x80) == 0) {
+ n = (x&7)+1;
+ for(i = 1; i < n; i++)
+ getresbyte(rddata);
+ }
+ else {
+ n1 = getresbyte(rddata);
+ n2 = getresbyte(rddata);
+ n = (n2<<8)|n1 + 3;
+ for (i = 3; i < n; i++)
+ getresbyte(rddata);
+ }
+ ncfg += n;
+ if((x>>3) == 0x0f)
+ break;
+ }
+ return ncfg;
+}
+
+/* look for cards, and assign them CSNs */
+static int
+pnpscan(int rddata, int dawn)
+{
+ Card *c;
+ int csn;
+ ulong id1, id2;
+
+ initiation(); /* upsilon sigma */
+ cmd(0x02, 0x04+0x01); /* reset CSN on all cards and reset logical devices */
+ delay(1); /* delay after resetting cards */
+
+ cmd(0x03, 0); /* Wake all cards with a CSN of 0 */
+ cmd(0x00, rddata>>2); /* Set the READ_DATA port on all cards */
+ while(isolate(rddata, &id1, &id2)) {
+ for(c = pnp.cards; c != nil; c = c->next)
+ if(c->id1 == id1 && c->id2 == id2)
+ break;
+ if(c == nil) {
+ csn = newcsn();
+ c = findcsn(csn, 1, 0);
+ c->id1 = id1;
+ c->id2 = id2;
+ }
+ else if(c->cfgstr != nil) {
+ if(!wrconfig(c, c->cfgstr))
+ print("pnp%d: bad cfg: %s\n", c->csn, c->cfgstr);
+ c->cfgstr = nil;
+ }
+ cmd(0x06, c->csn); /* set the card's csn */
+ if(dawn)
+ print("pnp%d: %s\n", c->csn, serial(id1, id2));
+ c->ncfg = pnpncfg(rddata);
+ cmd(0x03, 0); /* Wake all cards with a CSN of 0, putting this card to sleep */
+ }
+ cmd(0x02, 0x02); /* return cards to Wait for Key state */
+ if(pnp.cards != 0) {
+ pnp.rddata = rddata;
+ return 1;
+ }
+ return 0;
+}
+
+static void
+pnpreset(void)
+{
+ Card *c;
+ ulong id1, id2;
+ int csn, i1, i2, i3, x;
+ char *s, *p, buf[20];
+ ISAConf isa;
+
+ memset(&isa, 0, sizeof(ISAConf));
+ pnp.rddata = -1;
+ if (isaconfig("pnp", 0, &isa) == 0)
+ return;
+ if(isa.port < 0x203 || isa.port > 0x3ff)
+ return;
+ for(csn = 1; csn < 256; csn++) {
+ snprint(buf, sizeof buf, "pnp%d", csn);
+ s = getconf(buf);
+ if(s == 0)
+ continue;
+ if(strlen(s) < 8 || s[7] != '.' || s[0] < 'A' || s[0] > 'Z' || s[1] < 'A' || s[1] > 'Z' || s[2] < 'A' || s[2] > 'Z') {
+bad:
+ print("pnp%d: bad conf string %s\n", csn, s);
+ continue;
+ }
+ i1 = s[0]-'A'+1;
+ i2 = s[1]-'A'+1;
+ i3 = s[2]-'A'+1;
+ x = strtoul(&s[3], 0, 16);
+ id1 = (i1<<2)|((i2>>3)&3)|((i2&7)<<13)|(i3<<8)|((x&0xff)<<24)|((x&0xff00)<<8);
+ id2 = strtoul(&s[8], &p, 16);
+ if(*p == ' ')
+ p++;
+ else if(*p == '\0')
+ p = nil;
+ else
+ goto bad;
+ c = findcsn(csn, 1, 0);
+ c->id1 = id1;
+ c->id2 = id2;
+ c->cfgstr = p;
+ }
+ pnpscan(isa.port, 1);
+}
+
+static int
+csngen(Chan *c, int t, int csn, Card *cp, Dir *dp)
+{
+ Qid q;
+
+ switch(t) {
+ case Qcsnctl:
+ q = (Qid){QID(csn, Qcsnctl), 0, 0};
+ snprint(up->genbuf, sizeof up->genbuf, "csn%dctl", csn);
+ devdir(c, q, up->genbuf, 0, eve, 0664, dp);
+ return 1;
+ case Qcsnraw:
+ q = (Qid){QID(csn, Qcsnraw), 0, 0};
+ snprint(up->genbuf, sizeof up->genbuf, "csn%draw", csn);
+ devdir(c, q, up->genbuf, cp->ncfg, eve, 0444, dp);
+ return 1;
+ }
+ return -1;
+}
+
+static int
+pcigen(Chan *c, int t, int tbdf, Dir *dp)
+{
+ Qid q;
+
+ q = (Qid){BUSBDF(tbdf)|t, 0, 0};
+ switch(t) {
+ case Qpcictl:
+ snprint(up->genbuf, sizeof up->genbuf, "%d.%d.%dctl",
+ BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
+ devdir(c, q, up->genbuf, 0, eve, 0444, dp);
+ return 1;
+ case Qpciraw:
+ snprint(up->genbuf, sizeof up->genbuf, "%d.%d.%draw",
+ BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
+ devdir(c, q, up->genbuf, 128, eve, 0660, dp);
+ return 1;
+ }
+ return -1;
+}
+
+static int
+pnpgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
+{
+ Qid q;
+ Card *cp;
+ Pcidev *p;
+ int csn, tbdf;
+
+ switch(TYPE(c->qid)){
+ case Qtopdir:
+ if(s == DEVDOTDOT){
+ q = (Qid){QID(0, Qtopdir), 0, QTDIR};
+ snprint(up->genbuf, sizeof up->genbuf, "#%C", pnpdevtab.dc);
+ devdir(c, q, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+ }
+ return devgen(c, nil, topdir, nelem(topdir), s, dp);
+ case Qpnpdir:
+ if(s == DEVDOTDOT){
+ q = (Qid){QID(0, Qtopdir), 0, QTDIR};
+ snprint(up->genbuf, sizeof up->genbuf, "#%C", pnpdevtab.dc);
+ devdir(c, q, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+ }
+ if(s < nelem(pnpdir)-1)
+ return devgen(c, nil, pnpdir, nelem(pnpdir), s, dp);
+ s -= nelem(pnpdir)-1;
+ qlock(&pnp);
+ cp = pnp.cards;
+ while(s >= 2 && cp != nil) {
+ s -= 2;
+ cp = cp->next;
+ }
+ qunlock(&pnp);
+ if(cp == nil)
+ return -1;
+ return csngen(c, s+Qcsnctl, cp->csn, cp, dp);
+ case Qpnpctl:
+ return devgen(c, nil, pnpdir, nelem(pnpdir), s, dp);
+ case Qcsnctl:
+ case Qcsnraw:
+ csn = CSN(c->qid);
+ cp = findcsn(csn, 0, 1);
+ if(cp == nil)
+ return -1;
+ return csngen(c, TYPE(c->qid), csn, cp, dp);
+ case Qpcidir:
+ if(s == DEVDOTDOT){
+ q = (Qid){QID(0, Qtopdir), 0, QTDIR};
+ snprint(up->genbuf, sizeof up->genbuf, "#%C", pnpdevtab.dc);
+ devdir(c, q, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+ }
+ p = pcimatch(nil, 0, 0);
+ while(s >= 2 && p != nil) {
+ p = pcimatch(p, 0, 0);
+ s -= 2;
+ }
+ if(p == nil)
+ return -1;
+ return pcigen(c, s+Qpcictl, p->tbdf, dp);
+ case Qpcictl:
+ case Qpciraw:
+ tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path);
+ p = pcimatchtbdf(tbdf);
+ if(p == nil)
+ return -1;
+ return pcigen(c, TYPE(c->qid), tbdf, dp);
+ default:
+ break;
+ }
+ return -1;
+}
+
+static Chan*
+pnpattach(char *spec)
+{
+ return devattach(pnpdevtab.dc, spec);
+}
+
+Walkqid*
+pnpwalk(Chan* c, Chan *nc, char** name, int nname)
+{
+ return devwalk(c, nc, name, nname, (Dirtab *)0, 0, pnpgen);
+}
+
+static int
+pnpstat(Chan* c, uchar* dp, int n)
+{
+ return devstat(c, dp, n, (Dirtab *)0, 0L, pnpgen);
+}
+
+static Chan*
+pnpopen(Chan *c, int omode)
+{
+ c = devopen(c, omode, (Dirtab*)0, 0, pnpgen);
+ switch(TYPE(c->qid)){
+ default:
+ break;
+ }
+ return c;
+}
+
+static void
+pnpclose(Chan*)
+{
+}
+
+static long
+pnpread(Chan *c, void *va, long n, vlong offset)
+{
+ ulong x;
+ Card *cp;
+ Pcidev *p;
+ char buf[256], *ebuf, *w;
+ char *a = va;
+ int csn, i, tbdf, r;
+
+ switch(TYPE(c->qid)){
+ case Qtopdir:
+ case Qpnpdir:
+ case Qpcidir:
+ return devdirread(c, a, n, (Dirtab *)0, 0L, pnpgen);
+ case Qpnpctl:
+ if(pnp.rddata > 0)
+ snprint(up->genbuf, sizeof up->genbuf, "enabled %#x\n",
+ pnp.rddata);
+ else
+ snprint(up->genbuf, sizeof up->genbuf, "disabled\n");
+ return readstr(offset, a, n, up->genbuf);
+ case Qcsnraw:
+ csn = CSN(c->qid);
+ cp = findcsn(csn, 0, 1);
+ if(cp == nil)
+ error(Egreg);
+ if(offset+n > cp->ncfg)
+ n = cp->ncfg - offset;
+ qlock(&pnp);
+ initiation();
+ cmd(0x03, csn); /* Wake up the card */
+ for(i = 0; i < offset+9; i++) /* 9 == skip serial + csum */
+ getresbyte(pnp.rddata);
+ for(i = 0; i < n; i++)
+ a[i] = getresbyte(pnp.rddata);
+ cmd(0x03, 0); /* Wake all cards with a CSN of 0, putting this card to sleep */
+ cmd(0x02, 0x02); /* return cards to Wait for Key state */
+ qunlock(&pnp);
+ break;
+ case Qcsnctl:
+ csn = CSN(c->qid);
+ cp = findcsn(csn, 0, 1);
+ if(cp == nil)
+ error(Egreg);
+ snprint(up->genbuf, sizeof up->genbuf, "%s\n",
+ serial(cp->id1, cp->id2));
+ return readstr(offset, a, n, up->genbuf);
+ case Qpcictl:
+ tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path);
+ p = pcimatchtbdf(tbdf);
+ if(p == nil)
+ error(Egreg);
+ ebuf = buf+sizeof buf-1; /* -1 for newline */
+ w = seprint(buf, ebuf, "%.2x.%.2x.%.2x %.4x/%.4x %3d",
+ p->ccrb, p->ccru, p->ccrp, p->vid, p->did, p->intl);
+ for(i=0; i<nelem(p->mem); i++){
+ if(p->mem[i].size == 0)
+ continue;
+ w = seprint(w, ebuf, " %d:%.8lux %d", i, p->mem[i].bar, p->mem[i].size);
+ }
+ *w++ = '\n';
+ *w = '\0';
+ return readstr(offset, a, n, buf);
+ case Qpciraw:
+ tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path);
+ p = pcimatchtbdf(tbdf);
+ if(p == nil)
+ error(Egreg);
+ if(offset > 256)
+ return 0;
+ if(n+offset > 256)
+ n = 256-offset;
+ r = offset;
+ if(!(r & 3) && n == 4){
+ x = pcicfgr32(p, r);
+ PBIT32(a, x);
+ return 4;
+ }
+ if(!(r & 1) && n == 2){
+ x = pcicfgr16(p, r);
+ PBIT16(a, x);
+ return 2;
+ }
+ for(i = 0; i < n; i++){
+ x = pcicfgr8(p, r);
+ PBIT8(a, x);
+ a++;
+ r++;
+ }
+ return i;
+ default:
+ error(Egreg);
+ }
+ return n;
+}
+
+static long
+pnpwrite(Chan *c, void *va, long n, vlong offset)
+{
+ Card *cp;
+ Pcidev *p;
+ ulong port, x;
+ char buf[256];
+ uchar *a;
+ int csn, i, r, tbdf;
+
+ if(n >= sizeof(buf))
+ n = sizeof(buf)-1;
+ a = va;
+ strncpy(buf, va, n);
+ buf[n] = 0;
+
+ switch(TYPE(c->qid)){
+ case Qpnpctl:
+ if(strncmp(buf, "port ", 5) == 0) {
+ port = strtoul(buf+5, 0, 0);
+ if(port < 0x203 || port > 0x3ff)
+ error("bad value for rddata port");
+ qlock(&pnp);
+ if(waserror()) {
+ qunlock(&pnp);
+ nexterror();
+ }
+ if(pnp.rddata > 0)
+ error("pnp port already set");
+ if(!pnpscan(port, 0))
+ error("no cards found");
+ qunlock(&pnp);
+ poperror();
+ }
+ else if(strncmp(buf, "debug ", 6) == 0)
+ pnp.debug = strtoul(buf+6, 0, 0);
+ else
+ error(Ebadctl);
+ break;
+ case Qcsnctl:
+ csn = CSN(c->qid);
+ cp = findcsn(csn, 0, 1);
+ if(cp == nil)
+ error(Egreg);
+ if(!wrconfig(cp, buf))
+ error(Ebadctl);
+ break;
+ case Qpciraw:
+ tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path);
+ p = pcimatchtbdf(tbdf);
+ if(p == nil)
+ error(Egreg);
+ if(offset > 256)
+ return 0;
+ if(n+offset > 256)
+ n = 256-offset;
+ r = offset;
+ if(!(r & 3) && n == 4){
+ x = GBIT32(a);
+ pcicfgw32(p, r, x);
+ return 4;
+ }
+ if(!(r & 1) && n == 2){
+ x = GBIT16(a);
+ pcicfgw16(p, r, x);
+ return 2;
+ }
+ for(i = 0; i < n; i++){
+ x = GBIT8(a);
+ pcicfgw8(p, r, x);
+ a++;
+ r++;
+ }
+ return i;
+ default:
+ error(Egreg);
+ }
+ return n;
+}
+
+static int
+wrconfig(Card *c, char *cmd)
+{
+ /* This should implement setting of I/O bases, etc */
+ USED(c, cmd);
+ return 1;
+}
+
+
+Dev pnpdevtab = {
+ '$',
+ "pnp",
+
+ pnpreset,
+ devinit,
+ devshutdown,
+ pnpattach,
+ pnpwalk,
+ pnpstat,
+ pnpopen,
+ devcreate,
+ pnpclose,
+ pnpread,
+ devbread,
+ pnpwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/port/devproc.c b/sys/src/9/port/devproc.c
new file mode 100755
index 000000000..d1ee87d5f
--- /dev/null
+++ b/sys/src/9/port/devproc.c
@@ -0,0 +1,1592 @@
+#include "u.h"
+#include <trace.h>
+#include "tos.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "ureg.h"
+#include "edf.h"
+
+enum
+{
+ Qdir,
+ Qtrace,
+ Qargs,
+ Qctl,
+ Qfd,
+ Qfpregs,
+ Qkregs,
+ Qmem,
+ Qnote,
+ Qnoteid,
+ Qnotepg,
+ Qns,
+ Qproc,
+ Qregs,
+ Qsegment,
+ Qstatus,
+ Qtext,
+ Qwait,
+ Qprofile,
+ Qsyscall,
+};
+
+enum
+{
+ CMclose,
+ CMclosefiles,
+ CMfixedpri,
+ CMhang,
+ CMkill,
+ CMnohang,
+ CMnoswap,
+ CMpri,
+ CMprivate,
+ CMprofile,
+ CMstart,
+ CMstartstop,
+ CMstartsyscall,
+ CMstop,
+ CMwaitstop,
+ CMwired,
+ CMtrace,
+ /* real time */
+ CMperiod,
+ CMdeadline,
+ CMcost,
+ CMsporadic,
+ CMdeadlinenotes,
+ CMadmit,
+ CMextra,
+ CMexpel,
+ CMevent,
+};
+
+enum{
+ Nevents = 0x4000,
+ Emask = Nevents - 1,
+};
+
+#define STATSIZE (2*KNAMELEN+12+9*12)
+/*
+ * Status, fd, and ns are left fully readable (0444) because of their use in debugging,
+ * particularly on shared servers.
+ * Arguably, ns and fd shouldn't be readable; if you'd prefer, change them to 0000
+ */
+Dirtab procdir[] =
+{
+ "args", {Qargs}, 0, 0660,
+ "ctl", {Qctl}, 0, 0000,
+ "fd", {Qfd}, 0, 0444,
+ "fpregs", {Qfpregs}, sizeof(FPsave), 0000,
+ "kregs", {Qkregs}, sizeof(Ureg), 0400,
+ "mem", {Qmem}, 0, 0000,
+ "note", {Qnote}, 0, 0000,
+ "noteid", {Qnoteid}, 0, 0664,
+ "notepg", {Qnotepg}, 0, 0000,
+ "ns", {Qns}, 0, 0444,
+ "proc", {Qproc}, 0, 0400,
+ "regs", {Qregs}, sizeof(Ureg), 0000,
+ "segment", {Qsegment}, 0, 0444,
+ "status", {Qstatus}, STATSIZE, 0444,
+ "text", {Qtext}, 0, 0000,
+ "wait", {Qwait}, 0, 0400,
+ "profile", {Qprofile}, 0, 0400,
+ "syscall", {Qsyscall}, 0, 0400,
+};
+
+static
+Cmdtab proccmd[] = {
+ CMclose, "close", 2,
+ CMclosefiles, "closefiles", 1,
+ CMfixedpri, "fixedpri", 2,
+ CMhang, "hang", 1,
+ CMnohang, "nohang", 1,
+ CMnoswap, "noswap", 1,
+ CMkill, "kill", 1,
+ CMpri, "pri", 2,
+ CMprivate, "private", 1,
+ CMprofile, "profile", 1,
+ CMstart, "start", 1,
+ CMstartstop, "startstop", 1,
+ CMstartsyscall, "startsyscall", 1,
+ CMstop, "stop", 1,
+ CMwaitstop, "waitstop", 1,
+ CMwired, "wired", 2,
+ CMtrace, "trace", 0,
+ CMperiod, "period", 2,
+ CMdeadline, "deadline", 2,
+ CMcost, "cost", 2,
+ CMsporadic, "sporadic", 1,
+ CMdeadlinenotes, "deadlinenotes", 1,
+ CMadmit, "admit", 1,
+ CMextra, "extra", 1,
+ CMexpel, "expel", 1,
+ CMevent, "event", 1,
+};
+
+/* Segment type from portdat.h */
+static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", };
+
+/*
+ * Qids are, in path:
+ * 4 bits of file type (qids above)
+ * 23 bits of process slot number + 1
+ * in vers,
+ * 32 bits of pid, for consistency checking
+ * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid.
+ */
+#define QSHIFT 5 /* location in qid of proc slot # */
+
+#define QID(q) ((((ulong)(q).path)&0x0000001F)>>0)
+#define SLOT(q) (((((ulong)(q).path)&0x07FFFFFE0)>>QSHIFT)-1)
+#define PID(q) ((q).vers)
+#define NOTEID(q) ((q).vers)
+
+void procctlreq(Proc*, char*, int);
+int procctlmemio(Proc*, ulong, int, void*, int);
+Chan* proctext(Chan*, Proc*);
+Segment* txt2data(Proc*, Segment*);
+int procstopped(void*);
+void mntscan(Mntwalk*, Proc*);
+
+static Traceevent *tevents;
+static Lock tlock;
+static int topens;
+static int tproduced, tconsumed;
+void (*proctrace)(Proc*, int, vlong);
+
+extern int unfair;
+
+static void
+profclock(Ureg *ur, Timer *)
+{
+ Tos *tos;
+
+ if(up == 0 || up->state != Running)
+ return;
+
+ /* user profiling clock */
+ if(userureg(ur)){
+ tos = (Tos*)(USTKTOP-sizeof(Tos));
+ tos->clock += TK2MS(1);
+ segclock(ur->pc);
+ }
+}
+
+static int
+procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp)
+{
+ Qid qid;
+ Proc *p;
+ char *ename;
+ Segment *q;
+ ulong pid, path, perm, len;
+
+ if(s == DEVDOTDOT){
+ mkqid(&qid, Qdir, 0, QTDIR);
+ devdir(c, qid, "#p", 0, eve, 0555, dp);
+ return 1;
+ }
+
+ if(c->qid.path == Qdir){
+ if(s == 0){
+ strcpy(up->genbuf, "trace");
+ mkqid(&qid, Qtrace, -1, QTFILE);
+ devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
+ return 1;
+ }
+
+ if(name != nil){
+ /* ignore s and use name to find pid */
+ pid = strtol(name, &ename, 10);
+ if(pid==0 || ename[0]!='\0')
+ return -1;
+ s = procindex(pid);
+ if(s < 0)
+ return -1;
+ }
+ else if(--s >= conf.nproc)
+ return -1;
+
+ p = proctab(s);
+ pid = p->pid;
+ if(pid == 0)
+ return 0;
+ sprint(up->genbuf, "%lud", pid);
+ /*
+ * String comparison is done in devwalk so name must match its formatted pid
+ */
+ if(name != nil && strcmp(name, up->genbuf) != 0)
+ return -1;
+ mkqid(&qid, (s+1)<<QSHIFT, pid, QTDIR);
+ devdir(c, qid, up->genbuf, 0, p->user, DMDIR|0555, dp);
+ return 1;
+ }
+ if(c->qid.path == Qtrace){
+ strcpy(up->genbuf, "trace");
+ mkqid(&qid, Qtrace, -1, QTFILE);
+ devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
+ return 1;
+ }
+ if(s >= nelem(procdir))
+ return -1;
+ if(tab)
+ panic("procgen");
+
+ tab = &procdir[s];
+ path = c->qid.path&~(((1<<QSHIFT)-1)); /* slot component */
+
+ /* p->procmode determines default mode for files in /proc */
+ p = proctab(SLOT(c->qid));
+ perm = tab->perm;
+ if(perm == 0)
+ perm = p->procmode;
+ else /* just copy read bits */
+ perm |= p->procmode & 0444;
+
+ len = tab->length;
+ switch(QID(c->qid)) {
+ case Qwait:
+ len = p->nwait; /* incorrect size, but >0 means there's something to read */
+ break;
+ case Qprofile:
+ q = p->seg[TSEG];
+ if(q && q->profile) {
+ len = (q->top-q->base)>>LRESPROF;
+ len *= sizeof(*q->profile);
+ }
+ break;
+ }
+
+ mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE);
+ devdir(c, qid, tab->name, len, p->user, perm, dp);
+ return 1;
+}
+
+static void
+_proctrace(Proc* p, Tevent etype, vlong ts)
+{
+ Traceevent *te;
+
+ if (p->trace == 0 || topens == 0 ||
+ tproduced - tconsumed >= Nevents)
+ return;
+
+ te = &tevents[tproduced&Emask];
+ te->pid = p->pid;
+ te->etype = etype;
+ if (ts == 0)
+ te->time = todget(nil);
+ else
+ te->time = ts;
+ tproduced++;
+}
+
+static void
+procinit(void)
+{
+ if(conf.nproc >= (1<<(16-QSHIFT))-1)
+ print("warning: too many procs for devproc\n");
+ addclock0link((void (*)(void))profclock, 113); /* Relative prime to HZ */
+}
+
+static Chan*
+procattach(char *spec)
+{
+ return devattach('p', spec);
+}
+
+static Walkqid*
+procwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, 0, 0, procgen);
+}
+
+static int
+procstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, 0, 0, procgen);
+}
+
+/*
+ * none can't read or write state on other
+ * processes. This is to contain access of
+ * servers running as none should they be
+ * subverted by, for example, a stack attack.
+ */
+static void
+nonone(Proc *p)
+{
+ if(p == up)
+ return;
+ if(strcmp(up->user, "none") != 0)
+ return;
+ if(iseve())
+ return;
+ error(Eperm);
+}
+
+static Chan*
+procopen(Chan *c, int omode)
+{
+ Proc *p;
+ Pgrp *pg;
+ Chan *tc;
+ int pid;
+
+ if(c->qid.type & QTDIR)
+ return devopen(c, omode, 0, 0, procgen);
+
+ if(QID(c->qid) == Qtrace){
+ if (omode != OREAD)
+ error(Eperm);
+ lock(&tlock);
+ if (waserror()){
+ unlock(&tlock);
+ nexterror();
+ }
+ if (topens > 0)
+ error("already open");
+ topens++;
+ if (tevents == nil){
+ tevents = (Traceevent*)malloc(sizeof(Traceevent) * Nevents);
+ if(tevents == nil)
+ error(Enomem);
+ tproduced = tconsumed = 0;
+ }
+ proctrace = _proctrace;
+ unlock(&tlock);
+ poperror();
+
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+ }
+
+ p = proctab(SLOT(c->qid));
+ qlock(&p->debug);
+ if(waserror()){
+ qunlock(&p->debug);
+ nexterror();
+ }
+ pid = PID(c->qid);
+ if(p->pid != pid)
+ error(Eprocdied);
+
+ omode = openmode(omode);
+
+ switch(QID(c->qid)){
+ case Qtext:
+ if(omode != OREAD)
+ error(Eperm);
+ tc = proctext(c, p);
+ tc->offset = 0;
+ qunlock(&p->debug);
+ poperror();
+ return tc;
+
+ case Qproc:
+ case Qkregs:
+ case Qsegment:
+ case Qprofile:
+ case Qfd:
+ if(omode != OREAD)
+ error(Eperm);
+ break;
+
+ case Qnote:
+ if(p->privatemem)
+ error(Eperm);
+ break;
+
+ case Qmem:
+ case Qctl:
+ if(p->privatemem)
+ error(Eperm);
+ nonone(p);
+ break;
+
+ case Qargs:
+ case Qnoteid:
+ case Qstatus:
+ case Qwait:
+ case Qregs:
+ case Qfpregs:
+ case Qsyscall:
+ nonone(p);
+ break;
+
+ case Qns:
+ if(omode != OREAD)
+ error(Eperm);
+ c->aux = malloc(sizeof(Mntwalk));
+ break;
+
+ case Qnotepg:
+ nonone(p);
+ pg = p->pgrp;
+ if(pg == nil)
+ error(Eprocdied);
+ if(omode!=OWRITE || pg->pgrpid == 1)
+ error(Eperm);
+ c->pgrpid.path = pg->pgrpid+1;
+ c->pgrpid.vers = p->noteid;
+ break;
+
+ default:
+ pprint("procopen %#lux\n", QID(c->qid));
+ error(Egreg);
+ }
+
+ /* Affix pid to qid */
+ if(p->state != Dead)
+ c->qid.vers = p->pid;
+
+ /* make sure the process slot didn't get reallocated while we were playing */
+ coherence();
+ if(p->pid != pid)
+ error(Eprocdied);
+
+ tc = devopen(c, omode, 0, 0, procgen);
+ qunlock(&p->debug);
+ poperror();
+
+ return tc;
+}
+
+static int
+procwstat(Chan *c, uchar *db, int n)
+{
+ Proc *p;
+ Dir *d;
+
+ if(c->qid.type&QTDIR)
+ error(Eperm);
+
+ if(QID(c->qid) == Qtrace)
+ return devwstat(c, db, n);
+
+ p = proctab(SLOT(c->qid));
+ nonone(p);
+ d = nil;
+ if(waserror()){
+ free(d);
+ qunlock(&p->debug);
+ nexterror();
+ }
+ qlock(&p->debug);
+
+ if(p->pid != PID(c->qid))
+ error(Eprocdied);
+
+ if(strcmp(up->user, p->user) != 0 && strcmp(up->user, eve) != 0)
+ error(Eperm);
+
+ d = smalloc(sizeof(Dir)+n);
+ n = convM2D(db, n, &d[0], (char*)&d[1]);
+ if(n == 0)
+ error(Eshortstat);
+ if(!emptystr(d->uid) && strcmp(d->uid, p->user) != 0){
+ if(strcmp(up->user, eve) != 0)
+ error(Eperm);
+ else
+ kstrdup(&p->user, d->uid);
+ }
+ /* p->procmode determines default mode for files in /proc */
+ if(d->mode != ~0UL)
+ p->procmode = d->mode&0777;
+
+ poperror();
+ free(d);
+ qunlock(&p->debug);
+ return n;
+}
+
+
+static long
+procoffset(long offset, char *va, int *np)
+{
+ if(offset > 0) {
+ offset -= *np;
+ if(offset < 0) {
+ memmove(va, va+*np+offset, -offset);
+ *np = -offset;
+ }
+ else
+ *np = 0;
+ }
+ return offset;
+}
+
+static int
+procqidwidth(Chan *c)
+{
+ char buf[32];
+
+ return sprint(buf, "%lud", c->qid.vers);
+}
+
+int
+procfdprint(Chan *c, int fd, int w, char *s, int ns)
+{
+ int n;
+
+ if(w == 0)
+ w = procqidwidth(c);
+ n = snprint(s, ns, "%3d %.2s %C %4ld (%.16llux %*lud %.2ux) %5ld %8lld %s\n",
+ fd,
+ &"r w rw"[(c->mode&3)<<1],
+ devtab[c->type]->dc, c->dev,
+ c->qid.path, w, c->qid.vers, c->qid.type,
+ c->iounit, c->offset, c->path->s);
+ return n;
+}
+
+static int
+procfds(Proc *p, char *va, int count, long offset)
+{
+ Fgrp *f;
+ Chan *c;
+ char buf[256];
+ int n, i, w, ww;
+ char *a;
+
+ /* print to buf to avoid holding fgrp lock while writing to user space */
+ if(count > sizeof buf)
+ count = sizeof buf;
+ a = buf;
+
+ qlock(&p->debug);
+ f = p->fgrp;
+ if(f == nil){
+ qunlock(&p->debug);
+ return 0;
+ }
+ lock(f);
+ if(waserror()){
+ unlock(f);
+ qunlock(&p->debug);
+ nexterror();
+ }
+
+ n = readstr(0, a, count, p->dot->path->s);
+ n += snprint(a+n, count-n, "\n");
+ offset = procoffset(offset, a, &n);
+ /* compute width of qid.path */
+ w = 0;
+ for(i = 0; i <= f->maxfd; i++) {
+ c = f->fd[i];
+ if(c == nil)
+ continue;
+ ww = procqidwidth(c);
+ if(ww > w)
+ w = ww;
+ }
+ for(i = 0; i <= f->maxfd; i++) {
+ c = f->fd[i];
+ if(c == nil)
+ continue;
+ n += procfdprint(c, i, w, a+n, count-n);
+ offset = procoffset(offset, a, &n);
+ }
+ unlock(f);
+ qunlock(&p->debug);
+ poperror();
+
+ /* copy result to user space, now that locks are released */
+ memmove(va, buf, n);
+
+ return n;
+}
+
+static void
+procclose(Chan * c)
+{
+ if(QID(c->qid) == Qtrace){
+ lock(&tlock);
+ if(topens > 0)
+ topens--;
+ if(topens == 0)
+ proctrace = nil;
+ unlock(&tlock);
+ }
+ if(QID(c->qid) == Qns && c->aux != 0)
+ free(c->aux);
+}
+
+static void
+int2flag(int flag, char *s)
+{
+ if(flag == 0){
+ *s = '\0';
+ return;
+ }
+ *s++ = '-';
+ if(flag & MAFTER)
+ *s++ = 'a';
+ if(flag & MBEFORE)
+ *s++ = 'b';
+ if(flag & MCREATE)
+ *s++ = 'c';
+ if(flag & MCACHE)
+ *s++ = 'C';
+ *s = '\0';
+}
+
+static int
+procargs(Proc *p, char *buf, int nbuf)
+{
+ int j, k, m;
+ char *a;
+ int n;
+
+ a = p->args;
+ if(p->setargs){
+ snprint(buf, nbuf, "%s [%s]", p->text, p->args);
+ return strlen(buf);
+ }
+ n = p->nargs;
+ for(j = 0; j < nbuf - 1; j += m){
+ if(n <= 0)
+ break;
+ if(j != 0)
+ buf[j++] = ' ';
+ m = snprint(buf+j, nbuf-j, "%q", a);
+ k = strlen(a) + 1;
+ a += k;
+ n -= k;
+ }
+ return j;
+}
+
+static int
+eventsavailable(void *)
+{
+ return tproduced > tconsumed;
+}
+
+static long
+procread(Chan *c, void *va, long n, vlong off)
+{
+ /* NSEG*32 was too small for worst cases */
+ char *a, flag[10], *sps, *srv, statbuf[NSEG*64];
+ int i, j, m, navail, ne, pid, rsize;
+ long l;
+ uchar *rptr;
+ ulong offset;
+ Confmem *cm;
+ Mntwalk *mw;
+ Proc *p;
+ Segment *sg, *s;
+ Ureg kur;
+ Waitq *wq;
+
+ a = va;
+ offset = off;
+
+ if(c->qid.type & QTDIR)
+ return devdirread(c, a, n, 0, 0, procgen);
+
+ if(QID(c->qid) == Qtrace){
+ if(!eventsavailable(nil))
+ return 0;
+
+ rptr = (uchar*)va;
+ navail = tproduced - tconsumed;
+ if(navail > n / sizeof(Traceevent))
+ navail = n / sizeof(Traceevent);
+ while(navail > 0) {
+ ne = ((tconsumed & Emask) + navail > Nevents)?
+ Nevents - (tconsumed & Emask): navail;
+ memmove(rptr, &tevents[tconsumed & Emask],
+ ne * sizeof(Traceevent));
+
+ tconsumed += ne;
+ rptr += ne * sizeof(Traceevent);
+ navail -= ne;
+ }
+ return rptr - (uchar*)va;
+ }
+
+ p = proctab(SLOT(c->qid));
+ if(p->pid != PID(c->qid))
+ error(Eprocdied);
+
+ switch(QID(c->qid)){
+ case Qargs:
+ qlock(&p->debug);
+ j = procargs(p, up->genbuf, sizeof up->genbuf);
+ qunlock(&p->debug);
+ if(offset >= j)
+ return 0;
+ if(offset+n > j)
+ n = j-offset;
+ memmove(a, &up->genbuf[offset], n);
+ return n;
+ case Qsyscall:
+ if(!p->syscalltrace)
+ return 0;
+ n = readstr(offset, a, n, p->syscalltrace);
+ return n;
+
+ case Qmem:
+ if(offset < KZERO)
+ return procctlmemio(p, offset, n, va, 1);
+
+ if(!iseve())
+ error(Eperm);
+
+ /* validate kernel addresses */
+ if(offset < (ulong)end) {
+ if(offset+n > (ulong)end)
+ n = (ulong)end - offset;
+ memmove(a, (char*)offset, n);
+ return n;
+ }
+ for(i=0; i<nelem(conf.mem); i++){
+ cm = &conf.mem[i];
+ /* klimit-1 because klimit might be zero! */
+ if(cm->kbase <= offset && offset <= cm->klimit-1){
+ if(offset+n >= cm->klimit-1)
+ n = cm->klimit - offset;
+ memmove(a, (char*)offset, n);
+ return n;
+ }
+ }
+ error(Ebadarg);
+
+ case Qprofile:
+ s = p->seg[TSEG];
+ if(s == 0 || s->profile == 0)
+ error("profile is off");
+ i = (s->top-s->base)>>LRESPROF;
+ i *= sizeof(*s->profile);
+ if(offset >= i)
+ return 0;
+ if(offset+n > i)
+ n = i - offset;
+ memmove(a, ((char*)s->profile)+offset, n);
+ return n;
+
+ case Qnote:
+ qlock(&p->debug);
+ if(waserror()){
+ qunlock(&p->debug);
+ nexterror();
+ }
+ if(p->pid != PID(c->qid))
+ error(Eprocdied);
+ if(n < 1) /* must accept at least the '\0' */
+ error(Etoosmall);
+ if(p->nnote == 0)
+ n = 0;
+ else {
+ m = strlen(p->note[0].msg) + 1;
+ if(m > n)
+ m = n;
+ memmove(va, p->note[0].msg, m);
+ ((char*)va)[m-1] = '\0';
+ p->nnote--;
+ memmove(p->note, p->note+1, p->nnote*sizeof(Note));
+ n = m;
+ }
+ if(p->nnote == 0)
+ p->notepending = 0;
+ poperror();
+ qunlock(&p->debug);
+ return n;
+
+ case Qproc:
+ if(offset >= sizeof(Proc))
+ return 0;
+ if(offset+n > sizeof(Proc))
+ n = sizeof(Proc) - offset;
+ memmove(a, ((char*)p)+offset, n);
+ return n;
+
+ case Qregs:
+ rptr = (uchar*)p->dbgreg;
+ rsize = sizeof(Ureg);
+ goto regread;
+
+ case Qkregs:
+ memset(&kur, 0, sizeof(Ureg));
+ setkernur(&kur, p);
+ rptr = (uchar*)&kur;
+ rsize = sizeof(Ureg);
+ goto regread;
+
+ case Qfpregs:
+ rptr = (uchar*)&p->fpsave;
+ rsize = sizeof(FPsave);
+ regread:
+ if(rptr == 0)
+ error(Enoreg);
+ if(offset >= rsize)
+ return 0;
+ if(offset+n > rsize)
+ n = rsize - offset;
+ memmove(a, rptr+offset, n);
+ return n;
+
+ case Qstatus:
+ if(offset >= STATSIZE)
+ return 0;
+ if(offset+n > STATSIZE)
+ n = STATSIZE - offset;
+
+ sps = p->psstate;
+ if(sps == 0)
+ sps = statename[p->state];
+ memset(statbuf, ' ', sizeof statbuf);
+ memmove(statbuf+0*KNAMELEN, p->text, strlen(p->text));
+ memmove(statbuf+1*KNAMELEN, p->user, strlen(p->user));
+ memmove(statbuf+2*KNAMELEN, sps, strlen(sps));
+ j = 2*KNAMELEN + 12;
+
+ for(i = 0; i < 6; i++) {
+ l = p->time[i];
+ if(i == TReal)
+ l = MACHP(0)->ticks - l;
+ l = TK2MS(l);
+ readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
+ }
+ /* ignore stack, which is mostly non-existent */
+ l = 0;
+ for(i=1; i<NSEG; i++){
+ s = p->seg[i];
+ if(s)
+ l += s->top - s->base;
+ }
+ readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, l>>10, NUMSIZE);
+ readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE);
+ readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE);
+ memmove(a, statbuf+offset, n);
+ return n;
+
+ case Qsegment:
+ j = 0;
+ for(i = 0; i < NSEG; i++) {
+ sg = p->seg[i];
+ if(sg == 0)
+ continue;
+ j += sprint(statbuf+j, "%-6s %c%c %.8lux %.8lux %4ld\n",
+ sname[sg->type&SG_TYPE],
+ sg->type&SG_RONLY ? 'R' : ' ',
+ sg->profile ? 'P' : ' ',
+ sg->base, sg->top, sg->ref);
+ }
+ if(offset >= j)
+ return 0;
+ if(offset+n > j)
+ n = j-offset;
+ if(n == 0 && offset == 0)
+ exhausted("segments");
+ memmove(a, &statbuf[offset], n);
+ return n;
+
+ case Qwait:
+ if(!canqlock(&p->qwaitr))
+ error(Einuse);
+
+ if(waserror()) {
+ qunlock(&p->qwaitr);
+ nexterror();
+ }
+
+ lock(&p->exl);
+ if(up == p && p->nchild == 0 && p->waitq == 0) {
+ unlock(&p->exl);
+ error(Enochild);
+ }
+ pid = p->pid;
+ while(p->waitq == 0) {
+ unlock(&p->exl);
+ sleep(&p->waitr, haswaitq, p);
+ if(p->pid != pid)
+ error(Eprocdied);
+ lock(&p->exl);
+ }
+ wq = p->waitq;
+ p->waitq = wq->next;
+ p->nwait--;
+ unlock(&p->exl);
+
+ qunlock(&p->qwaitr);
+ poperror();
+ n = snprint(a, n, "%d %lud %lud %lud %q",
+ wq->w.pid,
+ wq->w.time[TUser], wq->w.time[TSys], wq->w.time[TReal],
+ wq->w.msg);
+ free(wq);
+ return n;
+
+ case Qns:
+ qlock(&p->debug);
+ if(waserror()){
+ qunlock(&p->debug);
+ nexterror();
+ }
+ if(p->pgrp == nil || p->pid != PID(c->qid))
+ error(Eprocdied);
+ mw = c->aux;
+ if(mw->cddone){
+ qunlock(&p->debug);
+ poperror();
+ return 0;
+ }
+ mntscan(mw, p);
+ if(mw->mh == 0){
+ mw->cddone = 1;
+ i = snprint(a, n, "cd %s\n", p->dot->path->s);
+ qunlock(&p->debug);
+ poperror();
+ return i;
+ }
+ int2flag(mw->cm->mflag, flag);
+ if(strcmp(mw->cm->to->path->s, "#M") == 0){
+ srv = srvname(mw->cm->to->mchan);
+ i = snprint(a, n, "mount %s %s %s %s\n", flag,
+ srv==nil? mw->cm->to->mchan->path->s : srv,
+ mw->mh->from->path->s, mw->cm->spec? mw->cm->spec : "");
+ free(srv);
+ }else
+ i = snprint(a, n, "bind %s %s %s\n", flag,
+ mw->cm->to->path->s, mw->mh->from->path->s);
+ qunlock(&p->debug);
+ poperror();
+ return i;
+
+ case Qnoteid:
+ return readnum(offset, va, n, p->noteid, NUMSIZE);
+ case Qfd:
+ return procfds(p, va, n, offset);
+ }
+ error(Egreg);
+ return 0; /* not reached */
+}
+
+void
+mntscan(Mntwalk *mw, Proc *p)
+{
+ Pgrp *pg;
+ Mount *t;
+ Mhead *f;
+ int nxt, i;
+ ulong last, bestmid;
+
+ pg = p->pgrp;
+ rlock(&pg->ns);
+
+ nxt = 0;
+ bestmid = ~0;
+
+ last = 0;
+ if(mw->mh)
+ last = mw->cm->mountid;
+
+ for(i = 0; i < MNTHASH; i++) {
+ for(f = pg->mnthash[i]; f; f = f->hash) {
+ for(t = f->mount; t; t = t->next) {
+ if(mw->mh == 0 ||
+ (t->mountid > last && t->mountid < bestmid)) {
+ mw->cm = t;
+ mw->mh = f;
+ bestmid = mw->cm->mountid;
+ nxt = 1;
+ }
+ }
+ }
+ }
+ if(nxt == 0)
+ mw->mh = 0;
+
+ runlock(&pg->ns);
+}
+
+static long
+procwrite(Chan *c, void *va, long n, vlong off)
+{
+ int id, m;
+ Proc *p, *t, *et;
+ char *a, *arg, buf[ERRMAX];
+ ulong offset = off;
+
+ a = va;
+ if(c->qid.type & QTDIR)
+ error(Eisdir);
+
+ p = proctab(SLOT(c->qid));
+
+ /* Use the remembered noteid in the channel rather
+ * than the process pgrpid
+ */
+ if(QID(c->qid) == Qnotepg) {
+ pgrpnote(NOTEID(c->pgrpid), va, n, NUser);
+ return n;
+ }
+
+ qlock(&p->debug);
+ if(waserror()){
+ qunlock(&p->debug);
+ nexterror();
+ }
+ if(p->pid != PID(c->qid))
+ error(Eprocdied);
+
+ switch(QID(c->qid)){
+ case Qargs:
+ if(n == 0)
+ error(Eshort);
+ if(n >= ERRMAX)
+ error(Etoobig);
+ arg = malloc(n+1);
+ if(arg == nil)
+ error(Enomem);
+ memmove(arg, va, n);
+ m = n;
+ if(arg[m-1] != 0)
+ arg[m++] = 0;
+ free(p->args);
+ p->nargs = m;
+ p->args = arg;
+ p->setargs = 1;
+ break;
+
+ case Qmem:
+ if(p->state != Stopped)
+ error(Ebadctl);
+
+ n = procctlmemio(p, offset, n, va, 0);
+ break;
+
+ case Qregs:
+ if(offset >= sizeof(Ureg))
+ n = 0;
+ else if(offset+n > sizeof(Ureg))
+ n = sizeof(Ureg) - offset;
+ if(p->dbgreg == 0)
+ error(Enoreg);
+ setregisters(p->dbgreg, (char*)(p->dbgreg)+offset, va, n);
+ break;
+
+ case Qfpregs:
+ if(offset >= sizeof(FPsave))
+ n = 0;
+ else if(offset+n > sizeof(FPsave))
+ n = sizeof(FPsave) - offset;
+ memmove((uchar*)&p->fpsave+offset, va, n);
+ break;
+
+ case Qctl:
+ procctlreq(p, va, n);
+ break;
+
+ case Qnote:
+ if(p->kp)
+ error(Eperm);
+ if(n >= ERRMAX-1)
+ error(Etoobig);
+ memmove(buf, va, n);
+ buf[n] = 0;
+ if(!postnote(p, 0, buf, NUser))
+ error("note not posted");
+ break;
+ case Qnoteid:
+ id = atoi(a);
+ if(id == p->pid) {
+ p->noteid = id;
+ break;
+ }
+ t = proctab(0);
+ for(et = t+conf.nproc; t < et; t++) {
+ if(t->state == Dead)
+ continue;
+ if(id == t->noteid) {
+ if(strcmp(p->user, t->user) != 0)
+ error(Eperm);
+ p->noteid = id;
+ break;
+ }
+ }
+ if(p->noteid != id)
+ error(Ebadarg);
+ break;
+ default:
+ pprint("unknown qid in procwrite\n");
+ error(Egreg);
+ }
+ poperror();
+ qunlock(&p->debug);
+ return n;
+}
+
+Dev procdevtab = {
+ 'p',
+ "proc",
+
+ devreset,
+ procinit,
+ devshutdown,
+ procattach,
+ procwalk,
+ procstat,
+ procopen,
+ devcreate,
+ procclose,
+ procread,
+ devbread,
+ procwrite,
+ devbwrite,
+ devremove,
+ procwstat,
+};
+
+Chan*
+proctext(Chan *c, Proc *p)
+{
+ Chan *tc;
+ Image *i;
+ Segment *s;
+
+ s = p->seg[TSEG];
+ if(s == 0)
+ error(Enonexist);
+ if(p->state==Dead)
+ error(Eprocdied);
+
+ lock(s);
+ i = s->image;
+ if(i == 0) {
+ unlock(s);
+ error(Eprocdied);
+ }
+ unlock(s);
+
+ lock(i);
+ if(waserror()) {
+ unlock(i);
+ nexterror();
+ }
+
+ tc = i->c;
+ if(tc == 0)
+ error(Eprocdied);
+
+ if(incref(tc) == 1 || (tc->flag&COPEN) == 0 || tc->mode!=OREAD) {
+ cclose(tc);
+ error(Eprocdied);
+ }
+
+ if(p->pid != PID(c->qid))
+ error(Eprocdied);
+
+ unlock(i);
+ poperror();
+
+ return tc;
+}
+
+void
+procstopwait(Proc *p, int ctl)
+{
+ int pid;
+
+ if(p->pdbg)
+ error(Einuse);
+ if(procstopped(p) || p->state == Broken)
+ return;
+
+ if(ctl != 0)
+ p->procctl = ctl;
+ p->pdbg = up;
+ pid = p->pid;
+ qunlock(&p->debug);
+ up->psstate = "Stopwait";
+ if(waserror()) {
+ p->pdbg = 0;
+ qlock(&p->debug);
+ nexterror();
+ }
+ sleep(&up->sleep, procstopped, p);
+ poperror();
+ qlock(&p->debug);
+ if(p->pid != pid)
+ error(Eprocdied);
+}
+
+static void
+procctlcloseone(Proc *p, Fgrp *f, int fd)
+{
+ Chan *c;
+
+ c = f->fd[fd];
+ if(c == nil)
+ return;
+ f->fd[fd] = nil;
+ unlock(f);
+ qunlock(&p->debug);
+ cclose(c);
+ qlock(&p->debug);
+ lock(f);
+}
+
+void
+procctlclosefiles(Proc *p, int all, int fd)
+{
+ int i;
+ Fgrp *f;
+
+ f = p->fgrp;
+ if(f == nil)
+ error(Eprocdied);
+
+ lock(f);
+ f->ref++;
+ if(all)
+ for(i = 0; i < f->maxfd; i++)
+ procctlcloseone(p, f, i);
+ else
+ procctlcloseone(p, f, fd);
+ unlock(f);
+ closefgrp(f);
+}
+
+static char *
+parsetime(vlong *rt, char *s)
+{
+ uvlong ticks;
+ ulong l;
+ char *e, *p;
+ static int p10[] = {100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
+
+ if (s == nil)
+ return("missing value");
+ ticks=strtoul(s, &e, 10);
+ if (*e == '.'){
+ p = e+1;
+ l = strtoul(p, &e, 10);
+ if(e-p > nelem(p10))
+ return "too many digits after decimal point";
+ if(e-p == 0)
+ return "ill-formed number";
+ l *= p10[e-p-1];
+ }else
+ l = 0;
+ if (*e == '\0' || strcmp(e, "s") == 0){
+ ticks = 1000000000 * ticks + l;
+ }else if (strcmp(e, "ms") == 0){
+ ticks = 1000000 * ticks + l/1000;
+ }else if (strcmp(e, "µs") == 0 || strcmp(e, "us") == 0){
+ ticks = 1000 * ticks + l/1000000;
+ }else if (strcmp(e, "ns") != 0)
+ return "unrecognized unit";
+ *rt = ticks;
+ return nil;
+}
+
+void
+procctlreq(Proc *p, char *va, int n)
+{
+ Segment *s;
+ int npc, pri;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+ vlong time;
+ char *e;
+ void (*pt)(Proc*, int, vlong);
+
+ if(p->kp) /* no ctl requests to kprocs */
+ error(Eperm);
+
+ cb = parsecmd(va, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+
+ ct = lookupcmd(cb, proccmd, nelem(proccmd));
+
+ switch(ct->index){
+ case CMclose:
+ procctlclosefiles(p, 0, atoi(cb->f[1]));
+ break;
+ case CMclosefiles:
+ procctlclosefiles(p, 1, 0);
+ break;
+ case CMhang:
+ p->hang = 1;
+ break;
+ case CMkill:
+ switch(p->state) {
+ case Broken:
+ unbreak(p);
+ break;
+ case Stopped:
+ p->procctl = Proc_exitme;
+ postnote(p, 0, "sys: killed", NExit);
+ ready(p);
+ break;
+ default:
+ p->procctl = Proc_exitme;
+ postnote(p, 0, "sys: killed", NExit);
+ }
+ break;
+ case CMnohang:
+ p->hang = 0;
+ break;
+ case CMnoswap:
+ p->noswap = 1;
+ break;
+ case CMpri:
+ pri = atoi(cb->f[1]);
+ if(pri > PriNormal && !iseve())
+ error(Eperm);
+ procpriority(p, pri, 0);
+ break;
+ case CMfixedpri:
+ pri = atoi(cb->f[1]);
+ if(pri > PriNormal && !iseve())
+ error(Eperm);
+ procpriority(p, pri, 1);
+ break;
+ case CMprivate:
+ p->privatemem = 1;
+ break;
+ case CMprofile:
+ s = p->seg[TSEG];
+ if(s == 0 || (s->type&SG_TYPE) != SG_TEXT)
+ error(Ebadctl);
+ if(s->profile != 0)
+ free(s->profile);
+ npc = (s->top-s->base)>>LRESPROF;
+ s->profile = malloc(npc*sizeof(*s->profile));
+ if(s->profile == 0)
+ error(Enomem);
+ break;
+ case CMstart:
+ if(p->state != Stopped)
+ error(Ebadctl);
+ ready(p);
+ break;
+ case CMstartstop:
+ if(p->state != Stopped)
+ error(Ebadctl);
+ p->procctl = Proc_traceme;
+ ready(p);
+ procstopwait(p, Proc_traceme);
+ break;
+ case CMstartsyscall:
+ if(p->state != Stopped)
+ error(Ebadctl);
+ p->procctl = Proc_tracesyscall;
+ ready(p);
+ procstopwait(p, Proc_tracesyscall);
+ break;
+ case CMstop:
+ procstopwait(p, Proc_stopme);
+ break;
+ case CMwaitstop:
+ procstopwait(p, 0);
+ break;
+ case CMwired:
+ procwired(p, atoi(cb->f[1]));
+ break;
+ case CMtrace:
+ switch(cb->nf){
+ case 1:
+ p->trace ^= 1;
+ break;
+ case 2:
+ p->trace = (atoi(cb->f[1]) != 0);
+ break;
+ default:
+ error("args");
+ }
+ break;
+ /* real time */
+ case CMperiod:
+ if(p->edf == nil)
+ edfinit(p);
+ if(e=parsetime(&time, cb->f[1])) /* time in ns */
+ error(e);
+ edfstop(p);
+ p->edf->T = time/1000; /* Edf times are in µs */
+ break;
+ case CMdeadline:
+ if(p->edf == nil)
+ edfinit(p);
+ if(e=parsetime(&time, cb->f[1]))
+ error(e);
+ edfstop(p);
+ p->edf->D = time/1000;
+ break;
+ case CMcost:
+ if(p->edf == nil)
+ edfinit(p);
+ if(e=parsetime(&time, cb->f[1]))
+ error(e);
+ edfstop(p);
+ p->edf->C = time/1000;
+ break;
+ case CMsporadic:
+ if(p->edf == nil)
+ edfinit(p);
+ p->edf->flags |= Sporadic;
+ break;
+ case CMdeadlinenotes:
+ if(p->edf == nil)
+ edfinit(p);
+ p->edf->flags |= Sendnotes;
+ break;
+ case CMadmit:
+ if(p->edf == 0)
+ error("edf params");
+ if(e = edfadmit(p))
+ error(e);
+ break;
+ case CMextra:
+ if(p->edf == nil)
+ edfinit(p);
+ p->edf->flags |= Extratime;
+ break;
+ case CMexpel:
+ if(p->edf)
+ edfstop(p);
+ break;
+ case CMevent:
+ pt = proctrace;
+ if(up->trace && pt)
+ pt(up, SUser, 0);
+ break;
+ }
+
+ poperror();
+ free(cb);
+}
+
+int
+procstopped(void *a)
+{
+ Proc *p = a;
+ return p->state == Stopped;
+}
+
+int
+procctlmemio(Proc *p, ulong offset, int n, void *va, int read)
+{
+ KMap *k;
+ Pte *pte;
+ Page *pg;
+ Segment *s;
+ ulong soff, l;
+ char *a = va, *b;
+
+ for(;;) {
+ s = seg(p, offset, 1);
+ if(s == 0)
+ error(Ebadarg);
+
+ if(offset+n >= s->top)
+ n = s->top-offset;
+
+ if(!read && (s->type&SG_TYPE) == SG_TEXT)
+ s = txt2data(p, s);
+
+ s->steal++;
+ soff = offset-s->base;
+ if(waserror()) {
+ s->steal--;
+ nexterror();
+ }
+ if(fixfault(s, offset, read, 0) == 0)
+ break;
+ poperror();
+ s->steal--;
+ }
+ poperror();
+ pte = s->map[soff/PTEMAPMEM];
+ if(pte == 0)
+ panic("procctlmemio");
+ pg = pte->pages[(soff&(PTEMAPMEM-1))/BY2PG];
+ if(pagedout(pg))
+ panic("procctlmemio1");
+
+ l = BY2PG - (offset&(BY2PG-1));
+ if(n > l)
+ n = l;
+
+ k = kmap(pg);
+ if(waserror()) {
+ s->steal--;
+ kunmap(k);
+ nexterror();
+ }
+ b = (char*)VA(k);
+ b += offset&(BY2PG-1);
+ if(read == 1)
+ memmove(a, b, n); /* This can fault */
+ else
+ memmove(b, a, n);
+ kunmap(k);
+ poperror();
+
+ /* Ensure the process sees text page changes */
+ if(s->flushme)
+ memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
+
+ s->steal--;
+
+ if(read == 0)
+ p->newtlb = 1;
+
+ return n;
+}
+
+Segment*
+txt2data(Proc *p, Segment *s)
+{
+ int i;
+ Segment *ps;
+
+ ps = newseg(SG_DATA, s->base, s->size);
+ ps->image = s->image;
+ incref(ps->image);
+ ps->fstart = s->fstart;
+ ps->flen = s->flen;
+ ps->flushme = 1;
+
+ qlock(&p->seglock);
+ for(i = 0; i < NSEG; i++)
+ if(p->seg[i] == s)
+ break;
+ if(i == NSEG)
+ panic("segment gone");
+
+ qunlock(&s->lk);
+ putseg(s);
+ qlock(&ps->lk);
+ p->seg[i] = ps;
+ qunlock(&p->seglock);
+
+ return ps;
+}
+
+Segment*
+data2txt(Segment *s)
+{
+ Segment *ps;
+
+ ps = newseg(SG_TEXT, s->base, s->size);
+ ps->image = s->image;
+ incref(ps->image);
+ ps->fstart = s->fstart;
+ ps->flen = s->flen;
+ ps->flushme = 1;
+
+ return ps;
+}
diff --git a/sys/src/9/port/devroot.c b/sys/src/9/port/devroot.c
new file mode 100755
index 000000000..f3aebc387
--- /dev/null
+++ b/sys/src/9/port/devroot.c
@@ -0,0 +1,261 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+enum
+{
+ Qdir = 0,
+ Qboot = 0x1000,
+
+ Nrootfiles = 32,
+ Nbootfiles = 32,
+};
+
+typedef struct Dirlist Dirlist;
+struct Dirlist
+{
+ uint base;
+ Dirtab *dir;
+ uchar **data;
+ int ndir;
+ int mdir;
+};
+
+static Dirtab rootdir[Nrootfiles] = {
+ "#/", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
+ "boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555,
+};
+static uchar *rootdata[Nrootfiles];
+static Dirlist rootlist =
+{
+ 0,
+ rootdir,
+ rootdata,
+ 2,
+ Nrootfiles
+};
+
+static Dirtab bootdir[Nbootfiles] = {
+ "boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555,
+};
+static uchar *bootdata[Nbootfiles];
+static Dirlist bootlist =
+{
+ Qboot,
+ bootdir,
+ bootdata,
+ 1,
+ Nbootfiles
+};
+
+/*
+ * add a file to the list
+ */
+static void
+addlist(Dirlist *l, char *name, uchar *contents, ulong len, int perm)
+{
+ Dirtab *d;
+
+ if(l->ndir >= l->mdir)
+ panic("too many root files");
+ l->data[l->ndir] = contents;
+ d = &l->dir[l->ndir];
+ strcpy(d->name, name);
+ d->length = len;
+ d->perm = perm;
+ d->qid.type = 0;
+ d->qid.vers = 0;
+ d->qid.path = ++l->ndir + l->base;
+ if(perm & DMDIR)
+ d->qid.type |= QTDIR;
+}
+
+/*
+ * add a root file
+ */
+void
+addbootfile(char *name, uchar *contents, ulong len)
+{
+ addlist(&bootlist, name, contents, len, 0555);
+}
+
+/*
+ * add a root directory
+ */
+static void
+addrootdir(char *name)
+{
+ addlist(&rootlist, name, nil, 0, DMDIR|0555);
+}
+
+static void
+rootreset(void)
+{
+ addrootdir("bin");
+ addrootdir("dev");
+ addrootdir("env");
+ addrootdir("fd");
+ addrootdir("mnt");
+ addrootdir("net");
+ addrootdir("net.alt");
+ addrootdir("proc");
+ addrootdir("root");
+ addrootdir("srv");
+}
+
+static Chan*
+rootattach(char *spec)
+{
+ return devattach('/', spec);
+}
+
+static int
+rootgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
+{
+ int t;
+ Dirtab *d;
+ Dirlist *l;
+
+ switch((int)c->qid.path){
+ case Qdir:
+ if(s == DEVDOTDOT){
+ devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
+ return 1;
+ }
+ return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp);
+ case Qboot:
+ if(s == DEVDOTDOT){
+ devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
+ return 1;
+ }
+ return devgen(c, name, bootlist.dir, bootlist.ndir, s, dp);
+ default:
+ if(s == DEVDOTDOT){
+ if((int)c->qid.path < Qboot)
+ devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
+ else
+ devdir(c, (Qid){Qboot, 0, QTDIR}, "#/", 0, eve, 0555, dp);
+ return 1;
+ }
+ if(s != 0)
+ return -1;
+ if((int)c->qid.path < Qboot){
+ t = c->qid.path-1;
+ l = &rootlist;
+ }else{
+ t = c->qid.path - Qboot - 1;
+ l = &bootlist;
+ }
+ if(t >= l->ndir)
+ return -1;
+if(t < 0){
+print("rootgen %llud %d %d\n", c->qid.path, s, t);
+panic("whoops");
+}
+ d = &l->dir[t];
+ devdir(c, d->qid, d->name, d->length, eve, d->perm, dp);
+ return 1;
+ }
+}
+
+static Walkqid*
+rootwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, nil, 0, rootgen);
+}
+
+static int
+rootstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, nil, 0, rootgen);
+}
+
+static Chan*
+rootopen(Chan *c, int omode)
+{
+ return devopen(c, omode, nil, 0, devgen);
+}
+
+/*
+ * sysremove() knows this is a nop
+ */
+static void
+rootclose(Chan*)
+{
+}
+
+static long
+rootread(Chan *c, void *buf, long n, vlong off)
+{
+ ulong t;
+ Dirtab *d;
+ Dirlist *l;
+ uchar *data;
+ ulong offset = off;
+
+ t = c->qid.path;
+ switch(t){
+ case Qdir:
+ case Qboot:
+ return devdirread(c, buf, n, nil, 0, rootgen);
+ }
+
+ if(t<Qboot)
+ l = &rootlist;
+ else{
+ t -= Qboot;
+ l = &bootlist;
+ }
+
+ t--;
+ if(t >= l->ndir)
+ error(Egreg);
+
+ d = &l->dir[t];
+ data = l->data[t];
+ if(offset >= d->length)
+ return 0;
+ if(offset+n > d->length)
+ n = d->length - offset;
+#ifdef asdf
+print("[%d] kaddr %.8ulx base %.8ulx offset %ld (%.8ulx), n %d %.8ulx %.8ulx %.8ulx\n",
+ t, buf, data, offset, offset, n,
+ ((ulong*)(data+offset))[0],
+ ((ulong*)(data+offset))[1],
+ ((ulong*)(data+offset))[2]);
+#endif asdf
+ memmove(buf, data+offset, n);
+ return n;
+}
+
+static long
+rootwrite(Chan*, void*, long, vlong)
+{
+ error(Egreg);
+ return 0;
+}
+
+Dev rootdevtab = {
+ '/',
+ "root",
+
+ rootreset,
+ devinit,
+ devshutdown,
+ rootattach,
+ rootwalk,
+ rootstat,
+ rootopen,
+ devcreate,
+ rootclose,
+ rootread,
+ devbread,
+ rootwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
diff --git a/sys/src/9/port/devsd.c b/sys/src/9/port/devsd.c
new file mode 100755
index 000000000..2753f2bbd
--- /dev/null
+++ b/sys/src/9/port/devsd.c
@@ -0,0 +1,1644 @@
+/*
+ * Storage Device.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+#include "../port/sd.h"
+
+extern Dev sddevtab;
+extern SDifc* sdifc[];
+
+static char Echange[] = "media or partition has changed";
+
+static char devletters[] = "0123456789"
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+static SDev *devs[sizeof devletters-1];
+static QLock devslock;
+
+enum {
+ Rawcmd,
+ Rawdata,
+ Rawstatus,
+};
+
+enum {
+ Qtopdir = 1, /* top level directory */
+ Qtopbase,
+ Qtopctl = Qtopbase,
+
+ Qunitdir, /* directory per unit */
+ Qunitbase,
+ Qctl = Qunitbase,
+ Qraw,
+ Qpart,
+
+ TypeLOG = 4,
+ NType = (1<<TypeLOG),
+ TypeMASK = (NType-1),
+ TypeSHIFT = 0,
+
+ PartLOG = 8,
+ NPart = (1<<PartLOG),
+ PartMASK = (NPart-1),
+ PartSHIFT = TypeLOG,
+
+ UnitLOG = 8,
+ NUnit = (1<<UnitLOG),
+ UnitMASK = (NUnit-1),
+ UnitSHIFT = (PartLOG+TypeLOG),
+
+ DevLOG = 8,
+ NDev = (1 << DevLOG),
+ DevMASK = (NDev-1),
+ DevSHIFT = (UnitLOG+PartLOG+TypeLOG),
+
+ Ncmd = 20,
+};
+
+#define TYPE(q) ((((ulong)(q).path)>>TypeSHIFT) & TypeMASK)
+#define PART(q) ((((ulong)(q).path)>>PartSHIFT) & PartMASK)
+#define UNIT(q) ((((ulong)(q).path)>>UnitSHIFT) & UnitMASK)
+#define DEV(q) ((((ulong)(q).path)>>DevSHIFT) & DevMASK)
+#define QID(d,u, p, t) (((d)<<DevSHIFT)|((u)<<UnitSHIFT)|\
+ ((p)<<PartSHIFT)|((t)<<TypeSHIFT))
+
+
+static void
+sdaddpart(SDunit* unit, char* name, uvlong start, uvlong end)
+{
+ SDpart *pp;
+ int i, partno;
+
+ /*
+ * Check name not already used
+ * and look for a free slot.
+ */
+ if(unit->part != nil){
+ partno = -1;
+ for(i = 0; i < unit->npart; i++){
+ pp = &unit->part[i];
+ if(!pp->valid){
+ if(partno == -1)
+ partno = i;
+ break;
+ }
+ if(strcmp(name, pp->name) == 0){
+ if(pp->start == start && pp->end == end)
+ return;
+ error(Ebadctl);
+ }
+ }
+ }
+ else{
+ if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil)
+ error(Enomem);
+ unit->npart = SDnpart;
+ partno = 0;
+ }
+
+ /*
+ * If no free slot found then increase the
+ * array size (can't get here with unit->part == nil).
+ */
+ if(partno == -1){
+ if(unit->npart >= NPart)
+ error(Enomem);
+ if((pp = malloc(sizeof(SDpart)*(unit->npart+SDnpart))) == nil)
+ error(Enomem);
+ memmove(pp, unit->part, sizeof(SDpart)*unit->npart);
+ free(unit->part);
+ unit->part = pp;
+ partno = unit->npart;
+ unit->npart += SDnpart;
+ }
+
+ /*
+ * Check size and extent are valid.
+ */
+ if(start > end || end > unit->sectors)
+ error(Eio);
+ pp = &unit->part[partno];
+ pp->start = start;
+ pp->end = end;
+ kstrdup(&pp->name, name);
+ kstrdup(&pp->user, eve);
+ pp->perm = 0640;
+ pp->valid = 1;
+}
+
+static void
+sddelpart(SDunit* unit, char* name)
+{
+ int i;
+ SDpart *pp;
+
+ /*
+ * Look for the partition to delete.
+ * Can't delete if someone still has it open.
+ */
+ pp = unit->part;
+ for(i = 0; i < unit->npart; i++){
+ if(strcmp(name, pp->name) == 0)
+ break;
+ pp++;
+ }
+ if(i >= unit->npart)
+ error(Ebadctl);
+ if(strcmp(up->user, pp->user) && !iseve())
+ error(Eperm);
+ pp->valid = 0;
+ pp->vers++;
+}
+
+static void
+sdincvers(SDunit *unit)
+{
+ int i;
+
+ unit->vers++;
+ if(unit->part){
+ for(i = 0; i < unit->npart; i++){
+ unit->part[i].valid = 0;
+ unit->part[i].vers++;
+ }
+ }
+}
+
+static int
+sdinitpart(SDunit* unit)
+{
+ int nf;
+ uvlong start, end;
+ char *f[4], *p, *q, buf[10];
+
+ if(unit->sectors > 0){
+ unit->sectors = unit->secsize = 0;
+ sdincvers(unit);
+ }
+
+ if(unit->inquiry[0] & 0xC0)
+ return 0;
+ switch(unit->inquiry[0] & 0x1F){
+ case 0x00: /* DA */
+ case 0x04: /* WORM */
+ case 0x05: /* CD-ROM */
+ case 0x07: /* MO */
+ break;
+ default:
+ return 0;
+ }
+
+ if(unit->dev->ifc->online)
+ unit->dev->ifc->online(unit);
+ if(unit->sectors){
+ sdincvers(unit);
+ sdaddpart(unit, "data", 0, unit->sectors);
+
+ /*
+ * Use partitions passed from boot program,
+ * e.g.
+ * sdC0part=dos 63 123123/plan9 123123 456456
+ * This happens before /boot sets hostname so the
+ * partitions will have the null-string for user.
+ * The gen functions patch it up.
+ */
+ snprint(buf, sizeof buf, "%spart", unit->name);
+ for(p = getconf(buf); p != nil; p = q){
+ if(q = strchr(p, '/'))
+ *q++ = '\0';
+ nf = tokenize(p, f, nelem(f));
+ if(nf < 3)
+ continue;
+
+ start = strtoull(f[1], 0, 0);
+ end = strtoull(f[2], 0, 0);
+ if(!waserror()){
+ sdaddpart(unit, f[0], start, end);
+ poperror();
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int
+sdindex(int idno)
+{
+ char *p;
+
+ p = strchr(devletters, idno);
+ if(p == nil)
+ return -1;
+ return p-devletters;
+}
+
+static SDev*
+sdgetdev(int idno)
+{
+ SDev *sdev;
+ int i;
+
+ if((i = sdindex(idno)) < 0)
+ return nil;
+
+ qlock(&devslock);
+ if(sdev = devs[i])
+ incref(&sdev->r);
+ qunlock(&devslock);
+ return sdev;
+}
+
+static SDunit*
+sdgetunit(SDev* sdev, int subno)
+{
+ SDunit *unit;
+ char buf[32];
+
+ /*
+ * Associate a unit with a given device and sub-unit
+ * number on that device.
+ * The device will be probed if it has not already been
+ * successfully accessed.
+ */
+ qlock(&sdev->unitlock);
+ if(subno > sdev->nunit){
+ qunlock(&sdev->unitlock);
+ return nil;
+ }
+
+ unit = sdev->unit[subno];
+ if(unit == nil){
+ /*
+ * Probe the unit only once. This decision
+ * may be a little severe and reviewed later.
+ */
+ if(sdev->unitflg[subno]){
+ qunlock(&sdev->unitlock);
+ return nil;
+ }
+ if((unit = malloc(sizeof(SDunit))) == nil){
+ qunlock(&sdev->unitlock);
+ return nil;
+ }
+ sdev->unitflg[subno] = 1;
+
+ snprint(buf, sizeof(buf), "%s%d", sdev->name, subno);
+ kstrdup(&unit->name, buf);
+ kstrdup(&unit->user, eve);
+ unit->perm = 0555;
+ unit->subno = subno;
+ unit->dev = sdev;
+
+ if(sdev->enabled == 0 && sdev->ifc->enable)
+ sdev->ifc->enable(sdev);
+ sdev->enabled = 1;
+
+ /*
+ * No need to lock anything here as this is only
+ * called before the unit is made available in the
+ * sdunit[] array.
+ */
+ if(unit->dev->ifc->verify(unit) == 0){
+ qunlock(&sdev->unitlock);
+ free(unit);
+ return nil;
+ }
+ sdev->unit[subno] = unit;
+ }
+ qunlock(&sdev->unitlock);
+ return unit;
+}
+
+static void
+sdreset(void)
+{
+ int i;
+ SDev *sdev;
+
+ /*
+ * Probe all known controller types and register any devices found.
+ */
+ for(i = 0; sdifc[i] != nil; i++){
+ if(sdifc[i]->pnp == nil || (sdev = sdifc[i]->pnp()) == nil)
+ continue;
+ sdadddevs(sdev);
+ }
+}
+
+void
+sdadddevs(SDev *sdev)
+{
+ int i, j, id;
+ SDev *next;
+
+ for(; sdev; sdev=next){
+ next = sdev->next;
+
+ sdev->unit = (SDunit**)malloc(sdev->nunit * sizeof(SDunit*));
+ sdev->unitflg = (int*)malloc(sdev->nunit * sizeof(int));
+ if(sdev->unit == nil || sdev->unitflg == nil){
+ print("sdadddevs: out of memory\n");
+ giveup:
+ free(sdev->unit);
+ free(sdev->unitflg);
+ if(sdev->ifc->clear)
+ sdev->ifc->clear(sdev);
+ free(sdev);
+ continue;
+ }
+ id = sdindex(sdev->idno);
+ if(id == -1){
+ print("sdadddevs: bad id number %d (%C)\n", id, id);
+ goto giveup;
+ }
+ qlock(&devslock);
+ for(i=0; i<nelem(devs); i++){
+ if(devs[j = (id+i)%nelem(devs)] == nil){
+ sdev->idno = devletters[j];
+ devs[j] = sdev;
+ snprint(sdev->name, sizeof sdev->name, "sd%c", devletters[j]);
+ break;
+ }
+ }
+ qunlock(&devslock);
+ if(i == nelem(devs)){
+ print("sdadddevs: out of device letters\n");
+ goto giveup;
+ }
+ }
+}
+
+// void
+// sdrmdevs(SDev *sdev)
+// {
+// char buf[2];
+//
+// snprint(buf, sizeof buf, "%c", sdev->idno);
+// unconfigure(buf);
+// }
+
+static int
+sd2gen(Chan* c, int i, Dir* dp)
+{
+ Qid q;
+ uvlong l;
+ SDpart *pp;
+ SDperm *perm;
+ SDunit *unit;
+ SDev *sdev;
+ int rv;
+
+ sdev = sdgetdev(DEV(c->qid));
+ assert(sdev);
+ unit = sdev->unit[UNIT(c->qid)];
+
+ rv = -1;
+ switch(i){
+ case Qctl:
+ mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qctl),
+ unit->vers, QTFILE);
+ perm = &unit->ctlperm;
+ if(emptystr(perm->user)){
+ kstrdup(&perm->user, eve);
+ perm->perm = 0640;
+ }
+ devdir(c, q, "ctl", 0, perm->user, perm->perm, dp);
+ rv = 1;
+ break;
+
+ case Qraw:
+ mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qraw),
+ unit->vers, QTFILE);
+ perm = &unit->rawperm;
+ if(emptystr(perm->user)){
+ kstrdup(&perm->user, eve);
+ perm->perm = DMEXCL|0600;
+ }
+ devdir(c, q, "raw", 0, perm->user, perm->perm, dp);
+ rv = 1;
+ break;
+
+ case Qpart:
+ pp = &unit->part[PART(c->qid)];
+ l = (pp->end - pp->start) * unit->secsize;
+ mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qpart),
+ unit->vers+pp->vers, QTFILE);
+ if(emptystr(pp->user))
+ kstrdup(&pp->user, eve);
+ devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
+ rv = 1;
+ break;
+ }
+
+ decref(&sdev->r);
+ return rv;
+}
+
+static int
+sd1gen(Chan* c, int i, Dir* dp)
+{
+ Qid q;
+
+ switch(i){
+ case Qtopctl:
+ mkqid(&q, QID(0, 0, 0, Qtopctl), 0, QTFILE);
+ devdir(c, q, "sdctl", 0, eve, 0640, dp);
+ return 1;
+ }
+ return -1;
+}
+
+static int
+sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp)
+{
+ Qid q;
+ uvlong l;
+ int i, r;
+ SDpart *pp;
+ SDunit *unit;
+ SDev *sdev;
+
+ switch(TYPE(c->qid)){
+ case Qtopdir:
+ if(s == DEVDOTDOT){
+ mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);
+ sprint(up->genbuf, "#%C", sddevtab.dc);
+ devdir(c, q, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+ }
+
+ if(s+Qtopbase < Qunitdir)
+ return sd1gen(c, s+Qtopbase, dp);
+ s -= (Qunitdir-Qtopbase);
+
+ qlock(&devslock);
+ for(i=0; i<nelem(devs); i++){
+ if(devs[i]){
+ if(s < devs[i]->nunit)
+ break;
+ s -= devs[i]->nunit;
+ }
+ }
+
+ if(i == nelem(devs)){
+ /* Run off the end of the list */
+ qunlock(&devslock);
+ return -1;
+ }
+
+ if((sdev = devs[i]) == nil){
+ qunlock(&devslock);
+ return 0;
+ }
+
+ incref(&sdev->r);
+ qunlock(&devslock);
+
+ if((unit = sdev->unit[s]) == nil)
+ if((unit = sdgetunit(sdev, s)) == nil){
+ decref(&sdev->r);
+ return 0;
+ }
+
+ mkqid(&q, QID(sdev->idno, s, 0, Qunitdir), 0, QTDIR);
+ if(emptystr(unit->user))
+ kstrdup(&unit->user, eve);
+ devdir(c, q, unit->name, 0, unit->user, unit->perm, dp);
+ decref(&sdev->r);
+ return 1;
+
+ case Qunitdir:
+ if(s == DEVDOTDOT){
+ mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);
+ sprint(up->genbuf, "#%C", sddevtab.dc);
+ devdir(c, q, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+ }
+
+ if((sdev = sdgetdev(DEV(c->qid))) == nil){
+ devdir(c, c->qid, "unavailable", 0, eve, 0, dp);
+ return 1;
+ }
+
+ unit = sdev->unit[UNIT(c->qid)];
+ qlock(&unit->ctl);
+
+ /*
+ * Check for media change.
+ * If one has already been detected, sectors will be zero.
+ * If there is one waiting to be detected, online
+ * will return > 1.
+ * Online is a bit of a large hammer but does the job.
+ */
+ if(unit->sectors == 0
+ || (unit->dev->ifc->online && unit->dev->ifc->online(unit) > 1))
+ sdinitpart(unit);
+
+ i = s+Qunitbase;
+ if(i < Qpart){
+ r = sd2gen(c, i, dp);
+ qunlock(&unit->ctl);
+ decref(&sdev->r);
+ return r;
+ }
+ i -= Qpart;
+ if(unit->part == nil || i >= unit->npart){
+ qunlock(&unit->ctl);
+ decref(&sdev->r);
+ break;
+ }
+ pp = &unit->part[i];
+ if(!pp->valid){
+ qunlock(&unit->ctl);
+ decref(&sdev->r);
+ return 0;
+ }
+ l = (pp->end - pp->start) * unit->secsize;
+ mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qpart),
+ unit->vers+pp->vers, QTFILE);
+ if(emptystr(pp->user))
+ kstrdup(&pp->user, eve);
+ devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
+ qunlock(&unit->ctl);
+ decref(&sdev->r);
+ return 1;
+ case Qraw:
+ case Qctl:
+ case Qpart:
+ if((sdev = sdgetdev(DEV(c->qid))) == nil){
+ devdir(c, q, "unavailable", 0, eve, 0, dp);
+ return 1;
+ }
+ unit = sdev->unit[UNIT(c->qid)];
+ qlock(&unit->ctl);
+ r = sd2gen(c, TYPE(c->qid), dp);
+ qunlock(&unit->ctl);
+ decref(&sdev->r);
+ return r;
+ case Qtopctl:
+ return sd1gen(c, TYPE(c->qid), dp);
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+static Chan*
+sdattach(char* spec)
+{
+ Chan *c;
+ char *p;
+ SDev *sdev;
+ int idno, subno;
+
+ if(*spec == '\0'){
+ c = devattach(sddevtab.dc, spec);
+ mkqid(&c->qid, QID(0, 0, 0, Qtopdir), 0, QTDIR);
+ return c;
+ }
+
+ if(spec[0] != 's' || spec[1] != 'd')
+ error(Ebadspec);
+ idno = spec[2];
+ subno = strtol(&spec[3], &p, 0);
+ if(p == &spec[3])
+ error(Ebadspec);
+
+ if((sdev=sdgetdev(idno)) == nil)
+ error(Enonexist);
+ if(sdgetunit(sdev, subno) == nil){
+ decref(&sdev->r);
+ error(Enonexist);
+ }
+
+ c = devattach(sddevtab.dc, spec);
+ mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR);
+ c->dev = (sdev->idno << UnitLOG) + subno;
+ decref(&sdev->r);
+ return c;
+}
+
+static Walkqid*
+sdwalk(Chan* c, Chan* nc, char** name, int nname)
+{
+ return devwalk(c, nc, name, nname, nil, 0, sdgen);
+}
+
+static int
+sdstat(Chan* c, uchar* db, int n)
+{
+ return devstat(c, db, n, nil, 0, sdgen);
+}
+
+static Chan*
+sdopen(Chan* c, int omode)
+{
+ SDpart *pp;
+ SDunit *unit;
+ SDev *sdev;
+ uchar tp;
+
+ c = devopen(c, omode, 0, 0, sdgen);
+ if((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart)
+ return c;
+
+ sdev = sdgetdev(DEV(c->qid));
+ if(sdev == nil)
+ error(Enonexist);
+
+ unit = sdev->unit[UNIT(c->qid)];
+
+ switch(TYPE(c->qid)){
+ case Qctl:
+ c->qid.vers = unit->vers;
+ break;
+ case Qraw:
+ c->qid.vers = unit->vers;
+ if(tas(&unit->rawinuse) != 0){
+ c->flag &= ~COPEN;
+ decref(&sdev->r);
+ error(Einuse);
+ }
+ unit->state = Rawcmd;
+ break;
+ case Qpart:
+ qlock(&unit->ctl);
+ if(waserror()){
+ qunlock(&unit->ctl);
+ c->flag &= ~COPEN;
+ decref(&sdev->r);
+ nexterror();
+ }
+ pp = &unit->part[PART(c->qid)];
+ c->qid.vers = unit->vers+pp->vers;
+ qunlock(&unit->ctl);
+ poperror();
+ break;
+ }
+ decref(&sdev->r);
+ return c;
+}
+
+static void
+sdclose(Chan* c)
+{
+ SDunit *unit;
+ SDev *sdev;
+
+ if(c->qid.type & QTDIR)
+ return;
+ if(!(c->flag & COPEN))
+ return;
+
+ switch(TYPE(c->qid)){
+ default:
+ break;
+ case Qraw:
+ sdev = sdgetdev(DEV(c->qid));
+ if(sdev){
+ unit = sdev->unit[UNIT(c->qid)];
+ unit->rawinuse = 0;
+ decref(&sdev->r);
+ }
+ break;
+ }
+}
+
+static long
+sdbio(Chan* c, int write, char* a, long len, uvlong off)
+{
+ int nchange;
+ long l;
+ uchar *b;
+ SDpart *pp;
+ SDunit *unit;
+ SDev *sdev;
+ ulong max, nb, offset;
+ uvlong bno;
+
+ sdev = sdgetdev(DEV(c->qid));
+ if(sdev == nil){
+ decref(&sdev->r);
+ error(Enonexist);
+ }
+ unit = sdev->unit[UNIT(c->qid)];
+ if(unit == nil)
+ error(Enonexist);
+
+ nchange = 0;
+ qlock(&unit->ctl);
+ while(waserror()){
+ /* notification of media change; go around again */
+ if(strcmp(up->errstr, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){
+ sdinitpart(unit);
+ continue;
+ }
+
+ /* other errors; give up */
+ qunlock(&unit->ctl);
+ decref(&sdev->r);
+ nexterror();
+ }
+ pp = &unit->part[PART(c->qid)];
+ if(unit->vers+pp->vers != c->qid.vers)
+ error(Echange);
+
+ /*
+ * Check the request is within bounds.
+ * Removeable drives are locked throughout the I/O
+ * in case the media changes unexpectedly.
+ * Non-removeable drives are not locked during the I/O
+ * to allow the hardware to optimise if it can; this is
+ * a little fast and loose.
+ * It's assumed that non-removeable media parameters
+ * (sectors, secsize) can't change once the drive has
+ * been brought online.
+ */
+ bno = (off/unit->secsize) + pp->start;
+ nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;
+ max = SDmaxio/unit->secsize;
+ if(nb > max)
+ nb = max;
+ if(bno+nb > pp->end)
+ nb = pp->end - bno;
+ if(bno >= pp->end || nb == 0){
+ if(write)
+ error(Eio);
+ qunlock(&unit->ctl);
+ decref(&sdev->r);
+ poperror();
+ return 0;
+ }
+ if(!(unit->inquiry[1] & 0x80)){
+ qunlock(&unit->ctl);
+ poperror();
+ }
+
+ b = sdmalloc(nb*unit->secsize);
+ if(b == nil)
+ error(Enomem);
+ if(waserror()){
+ sdfree(b);
+ if(!(unit->inquiry[1] & 0x80))
+ decref(&sdev->r); /* gadverdamme! */
+ nexterror();
+ }
+
+ offset = off%unit->secsize;
+ if(offset+len > nb*unit->secsize)
+ len = nb*unit->secsize - offset;
+ if(write){
+ if(offset || (len%unit->secsize)){
+ l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
+ if(l < 0)
+ error(Eio);
+ if(l < (nb*unit->secsize)){
+ nb = l/unit->secsize;
+ l = nb*unit->secsize - offset;
+ if(len > l)
+ len = l;
+ }
+ }
+ memmove(b+offset, a, len);
+ l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno);
+ if(l < 0)
+ error(Eio);
+ if(l < offset)
+ len = 0;
+ else if(len > l - offset)
+ len = l - offset;
+ }
+ else{
+ l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
+ if(l < 0)
+ error(Eio);
+ if(l < offset)
+ len = 0;
+ else if(len > l - offset)
+ len = l - offset;
+ memmove(a, b+offset, len);
+ }
+ sdfree(b);
+ poperror();
+
+ if(unit->inquiry[1] & 0x80){
+ qunlock(&unit->ctl);
+ poperror();
+ }
+
+ decref(&sdev->r);
+ return len;
+}
+
+static long
+sdrio(SDreq* r, void* a, long n)
+{
+ void *data;
+
+ if(n >= SDmaxio || n < 0)
+ error(Etoobig);
+
+ data = nil;
+ if(n){
+ if((data = sdmalloc(n)) == nil)
+ error(Enomem);
+ if(r->write)
+ memmove(data, a, n);
+ }
+ r->data = data;
+ r->dlen = n;
+
+ if(waserror()){
+ sdfree(data);
+ r->data = nil;
+ nexterror();
+ }
+
+ if(r->unit->dev->ifc->rio(r) != SDok)
+ error(Eio);
+
+ if(!r->write && r->rlen > 0)
+ memmove(a, data, r->rlen);
+ sdfree(data);
+ r->data = nil;
+ poperror();
+
+ return r->rlen;
+}
+
+/*
+ * SCSI simulation for non-SCSI devices
+ */
+int
+sdsetsense(SDreq *r, int status, int key, int asc, int ascq)
+{
+ int len;
+ SDunit *unit;
+
+ unit = r->unit;
+ unit->sense[2] = key;
+ unit->sense[12] = asc;
+ unit->sense[13] = ascq;
+
+ r->status = status;
+ if(status == SDcheck && !(r->flags & SDnosense)){
+ /* request sense case from sdfakescsi */
+ len = sizeof unit->sense;
+ if(len > sizeof r->sense-1)
+ len = sizeof r->sense-1;
+ memmove(r->sense, unit->sense, len);
+ unit->sense[2] = 0;
+ unit->sense[12] = 0;
+ unit->sense[13] = 0;
+ r->flags |= SDvalidsense;
+ return SDok;
+ }
+ return status;
+}
+
+int
+sdmodesense(SDreq *r, uchar *cmd, void *info, int ilen)
+{
+ int len;
+ uchar *data;
+
+ /*
+ * Fake a vendor-specific request with page code 0,
+ * return the drive info.
+ */
+ if((cmd[2] & 0x3F) != 0 && (cmd[2] & 0x3F) != 0x3F)
+ return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
+ len = (cmd[7]<<8)|cmd[8];
+ if(len == 0)
+ return SDok;
+ if(len < 8+ilen)
+ return sdsetsense(r, SDcheck, 0x05, 0x1A, 0);
+ if(r->data == nil || r->dlen < len)
+ return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
+ data = r->data;
+ memset(data, 0, 8);
+ data[0] = ilen>>8;
+ data[1] = ilen;
+ if(ilen)
+ memmove(data+8, info, ilen);
+ r->rlen = 8+ilen;
+ return sdsetsense(r, SDok, 0, 0, 0);
+}
+
+int
+sdfakescsi(SDreq *r, void *info, int ilen)
+{
+ uchar *cmd, *p;
+ uvlong len;
+ SDunit *unit;
+
+ cmd = r->cmd;
+ r->rlen = 0;
+ unit = r->unit;
+
+ /*
+ * Rewrite read(6)/write(6) into read(10)/write(10).
+ */
+ switch(cmd[0]){
+ case 0x08: /* read */
+ case 0x0A: /* write */
+ cmd[9] = 0;
+ cmd[8] = cmd[4];
+ cmd[7] = 0;
+ cmd[6] = 0;
+ cmd[5] = cmd[3];
+ cmd[4] = cmd[2];
+ cmd[3] = cmd[1] & 0x0F;
+ cmd[2] = 0;
+ cmd[1] &= 0xE0;
+ cmd[0] |= 0x20;
+ break;
+ }
+
+ /*
+ * Map SCSI commands into ATA commands for discs.
+ * Fail any command with a LUN except INQUIRY which
+ * will return 'logical unit not supported'.
+ */
+ if((cmd[1]>>5) && cmd[0] != 0x12)
+ return sdsetsense(r, SDcheck, 0x05, 0x25, 0);
+
+ switch(cmd[0]){
+ default:
+ return sdsetsense(r, SDcheck, 0x05, 0x20, 0);
+
+ case 0x00: /* test unit ready */
+ return sdsetsense(r, SDok, 0, 0, 0);
+
+ case 0x03: /* request sense */
+ if(cmd[4] < sizeof unit->sense)
+ len = cmd[4];
+ else
+ len = sizeof unit->sense;
+ if(r->data && r->dlen >= len){
+ memmove(r->data, unit->sense, len);
+ r->rlen = len;
+ }
+ return sdsetsense(r, SDok, 0, 0, 0);
+
+ case 0x12: /* inquiry */
+ if(cmd[4] < sizeof unit->inquiry)
+ len = cmd[4];
+ else
+ len = sizeof unit->inquiry;
+ if(r->data && r->dlen >= len){
+ memmove(r->data, unit->inquiry, len);
+ r->rlen = len;
+ }
+ return sdsetsense(r, SDok, 0, 0, 0);
+
+ case 0x1B: /* start/stop unit */
+ /*
+ * nop for now, can use power management later.
+ */
+ return sdsetsense(r, SDok, 0, 0, 0);
+
+ case 0x25: /* read capacity */
+ if((cmd[1] & 0x01) || cmd[2] || cmd[3])
+ return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
+ if(r->data == nil || r->dlen < 8)
+ return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
+
+ /*
+ * Read capacity returns the LBA of the last sector.
+ */
+ len = unit->sectors - 1;
+ p = r->data;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p++ = len;
+ len = 512;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p++ = len;
+ r->rlen = p - (uchar*)r->data;
+ return sdsetsense(r, SDok, 0, 0, 0);
+
+ case 0x9E: /* long read capacity */
+ if((cmd[1] & 0x01) || cmd[2] || cmd[3])
+ return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
+ if(r->data == nil || r->dlen < 8)
+ return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
+ /*
+ * Read capcity returns the LBA of the last sector.
+ */
+ len = unit->sectors - 1;
+ p = r->data;
+ *p++ = len>>56;
+ *p++ = len>>48;
+ *p++ = len>>40;
+ *p++ = len>>32;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p++ = len;
+ len = 512;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p++ = len;
+ r->rlen = p - (uchar*)r->data;
+ return sdsetsense(r, SDok, 0, 0, 0);
+
+ case 0x5A: /* mode sense */
+ return sdmodesense(r, cmd, info, ilen);
+
+ case 0x28: /* read */
+ case 0x2A: /* write */
+ case 0x88: /* read16 */
+ case 0x8a: /* write16 */
+ return SDnostatus;
+ }
+}
+
+static long
+sdread(Chan *c, void *a, long n, vlong off)
+{
+ char *p, *e, *buf;
+ SDpart *pp;
+ SDunit *unit;
+ SDev *sdev;
+ ulong offset;
+ int i, l, m, status;
+
+ offset = off;
+ switch(TYPE(c->qid)){
+ default:
+ error(Eperm);
+ case Qtopctl:
+ m = 64*1024; /* room for register dumps */
+ p = buf = malloc(m);
+ assert(p);
+ e = p + m;
+ qlock(&devslock);
+ for(i = 0; i < nelem(devs); i++){
+ sdev = devs[i];
+ if(sdev && sdev->ifc->rtopctl)
+ p = sdev->ifc->rtopctl(sdev, p, e);
+ }
+ qunlock(&devslock);
+ n = readstr(off, a, n, buf);
+ free(buf);
+ return n;
+
+ case Qtopdir:
+ case Qunitdir:
+ return devdirread(c, a, n, 0, 0, sdgen);
+
+ case Qctl:
+ sdev = sdgetdev(DEV(c->qid));
+ if(sdev == nil)
+ error(Enonexist);
+
+ unit = sdev->unit[UNIT(c->qid)];
+ m = 16*1024; /* room for register dumps */
+ p = malloc(m);
+ l = snprint(p, m, "inquiry %.48s\n",
+ (char*)unit->inquiry+8);
+ qlock(&unit->ctl);
+ /*
+ * If there's a device specific routine it must
+ * provide all information pertaining to night geometry
+ * and the garscadden trains.
+ */
+ if(unit->dev->ifc->rctl)
+ l += unit->dev->ifc->rctl(unit, p+l, m-l);
+ if(unit->sectors == 0)
+ sdinitpart(unit);
+ if(unit->sectors){
+ if(unit->dev->ifc->rctl == nil)
+ l += snprint(p+l, m-l,
+ "geometry %llud %lud\n",
+ unit->sectors, unit->secsize);
+ pp = unit->part;
+ for(i = 0; i < unit->npart; i++){
+ if(pp->valid)
+ l += snprint(p+l, m-l,
+ "part %s %llud %llud\n",
+ pp->name, pp->start, pp->end);
+ pp++;
+ }
+ }
+ qunlock(&unit->ctl);
+ decref(&sdev->r);
+ l = readstr(offset, a, n, p);
+ free(p);
+ return l;
+
+ case Qraw:
+ sdev = sdgetdev(DEV(c->qid));
+ if(sdev == nil)
+ error(Enonexist);
+
+ unit = sdev->unit[UNIT(c->qid)];
+ qlock(&unit->raw);
+ if(waserror()){
+ qunlock(&unit->raw);
+ decref(&sdev->r);
+ nexterror();
+ }
+ if(unit->state == Rawdata){
+ unit->state = Rawstatus;
+ i = sdrio(unit->req, a, n);
+ }
+ else if(unit->state == Rawstatus){
+ status = unit->req->status;
+ unit->state = Rawcmd;
+ free(unit->req);
+ unit->req = nil;
+ i = readnum(0, a, n, status, NUMSIZE);
+ } else
+ i = 0;
+ qunlock(&unit->raw);
+ decref(&sdev->r);
+ poperror();
+ return i;
+
+ case Qpart:
+ return sdbio(c, 0, a, n, off);
+ }
+}
+
+static void legacytopctl(Cmdbuf*);
+
+static long
+sdwrite(Chan* c, void* a, long n, vlong off)
+{
+ char *f0;
+ int i;
+ uvlong end, start;
+ Cmdbuf *cb;
+ SDifc *ifc;
+ SDreq *req;
+ SDunit *unit;
+ SDev *sdev;
+
+ switch(TYPE(c->qid)){
+ default:
+ error(Eperm);
+ case Qtopctl:
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ if(cb->nf == 0)
+ error("empty control message");
+ f0 = cb->f[0];
+ cb->f++;
+ cb->nf--;
+ if(strcmp(f0, "config") == 0){
+ /* wormhole into ugly legacy interface */
+ legacytopctl(cb);
+ poperror();
+ free(cb);
+ break;
+ }
+ /*
+ * "ata arg..." invokes sdifc[i]->wtopctl(nil, cb),
+ * where sdifc[i]->name=="ata" and cb contains the args.
+ */
+ ifc = nil;
+ sdev = nil;
+ for(i=0; sdifc[i]; i++){
+ if(strcmp(sdifc[i]->name, f0) == 0){
+ ifc = sdifc[i];
+ sdev = nil;
+ goto subtopctl;
+ }
+ }
+ /*
+ * "sd1 arg..." invokes sdifc[i]->wtopctl(sdev, cb),
+ * where sdifc[i] and sdev match controller letter "1",
+ * and cb contains the args.
+ */
+ if(f0[0]=='s' && f0[1]=='d' && f0[2] && f0[3] == 0){
+ if((sdev = sdgetdev(f0[2])) != nil){
+ ifc = sdev->ifc;
+ goto subtopctl;
+ }
+ }
+ error("unknown interface");
+
+ subtopctl:
+ if(waserror()){
+ if(sdev)
+ decref(&sdev->r);
+ nexterror();
+ }
+ if(ifc->wtopctl)
+ ifc->wtopctl(sdev, cb);
+ else
+ error(Ebadctl);
+ poperror();
+ poperror();
+ if (sdev)
+ decref(&sdev->r);
+ free(cb);
+ break;
+
+ case Qctl:
+ cb = parsecmd(a, n);
+ sdev = sdgetdev(DEV(c->qid));
+ if(sdev == nil)
+ error(Enonexist);
+ unit = sdev->unit[UNIT(c->qid)];
+
+ qlock(&unit->ctl);
+ if(waserror()){
+ qunlock(&unit->ctl);
+ decref(&sdev->r);
+ free(cb);
+ nexterror();
+ }
+ if(unit->vers != c->qid.vers)
+ error(Echange);
+
+ if(cb->nf < 1)
+ error(Ebadctl);
+ if(strcmp(cb->f[0], "part") == 0){
+ if(cb->nf != 4)
+ error(Ebadctl);
+ if(unit->sectors == 0 && !sdinitpart(unit))
+ error(Eio);
+ start = strtoull(cb->f[2], 0, 0);
+ end = strtoull(cb->f[3], 0, 0);
+ sdaddpart(unit, cb->f[1], start, end);
+ }
+ else if(strcmp(cb->f[0], "delpart") == 0){
+ if(cb->nf != 2 || unit->part == nil)
+ error(Ebadctl);
+ sddelpart(unit, cb->f[1]);
+ }
+ else if(unit->dev->ifc->wctl)
+ unit->dev->ifc->wctl(unit, cb);
+ else
+ error(Ebadctl);
+ qunlock(&unit->ctl);
+ decref(&sdev->r);
+ poperror();
+ free(cb);
+ break;
+
+ case Qraw:
+ sdev = sdgetdev(DEV(c->qid));
+ if(sdev == nil)
+ error(Enonexist);
+ unit = sdev->unit[UNIT(c->qid)];
+ qlock(&unit->raw);
+ if(waserror()){
+ qunlock(&unit->raw);
+ decref(&sdev->r);
+ nexterror();
+ }
+ switch(unit->state){
+ case Rawcmd:
+ if(n < 6 || n > sizeof(req->cmd))
+ error(Ebadarg);
+ if((req = malloc(sizeof(SDreq))) == nil)
+ error(Enomem);
+ req->unit = unit;
+ memmove(req->cmd, a, n);
+ req->clen = n;
+ req->flags = SDnosense;
+ req->status = ~0;
+
+ unit->req = req;
+ unit->state = Rawdata;
+ break;
+
+ case Rawstatus:
+ unit->state = Rawcmd;
+ free(unit->req);
+ unit->req = nil;
+ error(Ebadusefd);
+
+ case Rawdata:
+ unit->state = Rawstatus;
+ unit->req->write = 1;
+ n = sdrio(unit->req, a, n);
+ }
+ qunlock(&unit->raw);
+ decref(&sdev->r);
+ poperror();
+ break;
+ case Qpart:
+ return sdbio(c, 1, a, n, off);
+ }
+
+ return n;
+}
+
+static int
+sdwstat(Chan* c, uchar* dp, int n)
+{
+ Dir *d;
+ SDpart *pp;
+ SDperm *perm;
+ SDunit *unit;
+ SDev *sdev;
+
+ if(c->qid.type & QTDIR)
+ error(Eperm);
+
+ sdev = sdgetdev(DEV(c->qid));
+ if(sdev == nil)
+ error(Enonexist);
+ unit = sdev->unit[UNIT(c->qid)];
+ qlock(&unit->ctl);
+ d = nil;
+ if(waserror()){
+ free(d);
+ qunlock(&unit->ctl);
+ decref(&sdev->r);
+ nexterror();
+ }
+
+ switch(TYPE(c->qid)){
+ default:
+ error(Eperm);
+ case Qctl:
+ perm = &unit->ctlperm;
+ break;
+ case Qraw:
+ perm = &unit->rawperm;
+ break;
+ case Qpart:
+ pp = &unit->part[PART(c->qid)];
+ if(unit->vers+pp->vers != c->qid.vers)
+ error(Enonexist);
+ perm = &pp->SDperm;
+ break;
+ }
+
+ if(strcmp(up->user, perm->user) && !iseve())
+ error(Eperm);
+
+ d = smalloc(sizeof(Dir)+n);
+ n = convM2D(dp, n, &d[0], (char*)&d[1]);
+ if(n == 0)
+ error(Eshortstat);
+ if(!emptystr(d[0].uid))
+ kstrdup(&perm->user, d[0].uid);
+ if(d[0].mode != ~0UL)
+ perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777);
+
+ free(d);
+ qunlock(&unit->ctl);
+ decref(&sdev->r);
+ poperror();
+ return n;
+}
+
+static int
+configure(char* spec, DevConf* cf)
+{
+ SDev *s, *sdev;
+ char *p;
+ int i;
+
+ if(sdindex(*spec) < 0)
+ error("bad sd spec");
+
+ if((p = strchr(cf->type, '/')) != nil)
+ *p++ = '\0';
+
+ for(i = 0; sdifc[i] != nil; i++)
+ if(strcmp(sdifc[i]->name, cf->type) == 0)
+ break;
+ if(sdifc[i] == nil)
+ error("sd type not found");
+ if(p)
+ *(p-1) = '/';
+
+ if(sdifc[i]->probe == nil)
+ error("sd type cannot probe");
+
+ sdev = sdifc[i]->probe(cf);
+ for(s=sdev; s; s=s->next)
+ s->idno = *spec;
+ sdadddevs(sdev);
+ return 0;
+}
+
+static int
+unconfigure(char* spec)
+{
+ int i;
+ SDev *sdev;
+ SDunit *unit;
+
+ if((i = sdindex(*spec)) < 0)
+ error(Enonexist);
+
+ qlock(&devslock);
+ if((sdev = devs[i]) == nil){
+ qunlock(&devslock);
+ error(Enonexist);
+ }
+ if(sdev->r.ref){
+ qunlock(&devslock);
+ error(Einuse);
+ }
+ devs[i] = nil;
+ qunlock(&devslock);
+
+ /* make sure no interrupts arrive anymore before removing resources */
+ if(sdev->enabled && sdev->ifc->disable)
+ sdev->ifc->disable(sdev);
+
+ for(i = 0; i != sdev->nunit; i++){
+ if(unit = sdev->unit[i]){
+ free(unit->name);
+ free(unit->user);
+ free(unit);
+ }
+ }
+
+ if(sdev->ifc->clear)
+ sdev->ifc->clear(sdev);
+ free(sdev);
+ return 0;
+}
+
+static int
+sdconfig(int on, char* spec, DevConf* cf)
+{
+ if(on)
+ return configure(spec, cf);
+ return unconfigure(spec);
+}
+
+Dev sddevtab = {
+ 'S',
+ "sd",
+
+ sdreset,
+ devinit,
+ devshutdown,
+ sdattach,
+ sdwalk,
+ sdstat,
+ sdopen,
+ devcreate,
+ sdclose,
+ sdread,
+ devbread,
+ sdwrite,
+ devbwrite,
+ devremove,
+ sdwstat,
+ devpower,
+ sdconfig,
+};
+
+/*
+ * This is wrong for so many reasons. This code must go.
+ */
+typedef struct Confdata Confdata;
+struct Confdata {
+ int on;
+ char* spec;
+ DevConf cf;
+};
+
+static void
+parseswitch(Confdata* cd, char* option)
+{
+ if(!strcmp("on", option))
+ cd->on = 1;
+ else if(!strcmp("off", option))
+ cd->on = 0;
+ else
+ error(Ebadarg);
+}
+
+static void
+parsespec(Confdata* cd, char* option)
+{
+ if(strlen(option) > 1)
+ error(Ebadarg);
+ cd->spec = option;
+}
+
+static Devport*
+getnewport(DevConf* dc)
+{
+ Devport *p;
+
+ p = (Devport *)malloc((dc->nports + 1) * sizeof(Devport));
+ if(dc->nports > 0){
+ memmove(p, dc->ports, dc->nports * sizeof(Devport));
+ free(dc->ports);
+ }
+ dc->ports = p;
+ p = &dc->ports[dc->nports++];
+ p->size = -1;
+ p->port = (ulong)-1;
+ return p;
+}
+
+static void
+parseport(Confdata* cd, char* option)
+{
+ char *e;
+ Devport *p;
+
+ if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].port != (ulong)-1)
+ p = getnewport(&cd->cf);
+ else
+ p = &cd->cf.ports[cd->cf.nports-1];
+ p->port = strtol(option, &e, 0);
+ if(e == nil || *e != '\0')
+ error(Ebadarg);
+}
+
+static void
+parsesize(Confdata* cd, char* option)
+{
+ char *e;
+ Devport *p;
+
+ if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].size != -1)
+ p = getnewport(&cd->cf);
+ else
+ p = &cd->cf.ports[cd->cf.nports-1];
+ p->size = (int)strtol(option, &e, 0);
+ if(e == nil || *e != '\0')
+ error(Ebadarg);
+}
+
+static void
+parseirq(Confdata* cd, char* option)
+{
+ char *e;
+
+ cd->cf.intnum = strtoul(option, &e, 0);
+ if(e == nil || *e != '\0')
+ error(Ebadarg);
+}
+
+static void
+parsetype(Confdata* cd, char* option)
+{
+ cd->cf.type = option;
+}
+
+static struct {
+ char *name;
+ void (*parse)(Confdata*, char*);
+} options[] = {
+ "switch", parseswitch,
+ "spec", parsespec,
+ "port", parseport,
+ "size", parsesize,
+ "irq", parseirq,
+ "type", parsetype,
+};
+
+static void
+legacytopctl(Cmdbuf *cb)
+{
+ char *opt;
+ int i, j;
+ Confdata cd;
+
+ memset(&cd, 0, sizeof cd);
+ cd.on = -1;
+ for(i=0; i<cb->nf; i+=2){
+ if(i+2 > cb->nf)
+ error(Ebadarg);
+ opt = cb->f[i];
+ for(j=0; j<nelem(options); j++)
+ if(strcmp(opt, options[j].name) == 0){
+ options[j].parse(&cd, cb->f[i+1]);
+ break;
+ }
+ if(j == nelem(options))
+ error(Ebadarg);
+ }
+ /* this has been rewritten to accomodate sdaoe */
+ if(cd.on < 0 || cd.spec == 0)
+ error(Ebadarg);
+ if(cd.on && cd.cf.type == nil)
+ error(Ebadarg);
+ sdconfig(cd.on, cd.spec, &cd.cf);
+}
diff --git a/sys/src/9/port/devsdp.c b/sys/src/9/port/devsdp.c
new file mode 100755
index 000000000..5ed0472a1
--- /dev/null
+++ b/sys/src/9/port/devsdp.c
@@ -0,0 +1,2317 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/netif.h"
+#include "../port/error.h"
+
+#include <libsec.h>
+#include "../port/thwack.h"
+
+/*
+ * sdp - secure datagram protocol
+ */
+
+typedef struct Sdp Sdp;
+typedef struct Conv Conv;
+typedef struct OneWay OneWay;
+typedef struct Stats Stats;
+typedef struct AckPkt AckPkt;
+typedef struct Algorithm Algorithm;
+typedef struct CipherRc4 CipherRc4;
+
+enum
+{
+ Qtopdir= 1, /* top level directory */
+
+ Qsdpdir, /* sdp directory */
+ Qclone,
+ Qlog,
+
+ Qconvdir, /* directory per conversation */
+ Qctl,
+ Qdata, /* unreliable packet channel */
+ Qcontrol, /* reliable control channel */
+ Qstatus,
+ Qstats,
+ Qrstats,
+
+ MaxQ,
+
+ Maxconv= 256, // power of 2
+ Nfs= 4, // number of file systems
+ MaxRetries= 12,
+ KeepAlive = 300, // keep alive in seconds - should probably be about 60 but is higher to avoid linksys bug
+ SecretLength= 32, // a secret per direction
+ SeqMax = (1<<24),
+ SeqWindow = 32,
+ NCompStats = 8,
+};
+
+#define TYPE(x) (((ulong)(x).path) & 0xff)
+#define CONV(x) ((((ulong)(x).path) >> 8)&(Maxconv-1))
+#define QID(x, y) (((x)<<8) | (y))
+
+struct Stats
+{
+ ulong outPackets;
+ ulong outDataPackets;
+ ulong outDataBytes;
+ ulong outCompDataBytes;
+ ulong outCompBytes;
+ ulong outCompStats[NCompStats];
+ ulong inPackets;
+ ulong inDataPackets;
+ ulong inDataBytes;
+ ulong inCompDataBytes;
+ ulong inMissing;
+ ulong inDup;
+ ulong inReorder;
+ ulong inBadComp;
+ ulong inBadAuth;
+ ulong inBadSeq;
+ ulong inBadOther;
+};
+
+struct OneWay
+{
+ Rendez statsready;
+
+ ulong seqwrap; // number of wraps of the sequence number
+ ulong seq;
+ ulong window;
+
+ uchar secret[SecretLength];
+
+ QLock controllk;
+ Rendez controlready;
+ Block *controlpkt; // control channel
+ ulong controlseq;
+
+ void *cipherstate; // state cipher
+ int cipherivlen; // initial vector length
+ int cipherblklen; // block length
+ int (*cipher)(OneWay*, uchar *buf, int len);
+
+ void *authstate; // auth state
+ int authlen; // auth data length in bytes
+ int (*auth)(OneWay*, uchar *buf, int len);
+
+ void *compstate;
+ int (*comp)(Conv*, int subtype, ulong seq, Block **);
+};
+
+// conv states
+enum {
+ CFree,
+ CInit,
+ CDial,
+ CAccept,
+ COpen,
+ CLocalClose,
+ CRemoteClose,
+ CClosed,
+};
+
+struct Conv {
+ QLock;
+ Sdp *sdp;
+ int id;
+
+ int ref; // holds conv up
+
+ int state;
+
+ int dataopen; // ref count of opens on Qdata
+ int controlopen; // ref count of opens on Qcontrol
+ int reader; // reader proc has been started
+
+ Stats lstats;
+ Stats rstats;
+
+ ulong lastrecv; // time last packet was received
+ ulong timeout;
+ int retries;
+
+ // the following pair uniquely define conversation on this port
+ ulong dialid;
+ ulong acceptid;
+
+ QLock readlk; // protects readproc
+ Proc *readproc;
+
+ Chan *chan; // packet channel
+ char *channame;
+
+ char owner[KNAMELEN]; /* protections */
+ int perm;
+
+ Algorithm *auth;
+ Algorithm *cipher;
+ Algorithm *comp;
+
+ int drop;
+
+ OneWay in;
+ OneWay out;
+};
+
+struct Sdp {
+ QLock;
+ Log;
+ int nconv;
+ Conv *conv[Maxconv];
+ int ackproc;
+};
+
+enum {
+ TConnect,
+ TControl,
+ TData,
+ TCompData,
+};
+
+enum {
+ ControlMesg,
+ ControlAck,
+};
+
+enum {
+ ThwackU,
+ ThwackC,
+};
+
+enum {
+ ConOpenRequest,
+ ConOpenAck,
+ ConOpenAckAck,
+ ConClose,
+ ConCloseAck,
+ ConReset,
+};
+
+struct AckPkt
+{
+ uchar cseq[4];
+ uchar outPackets[4];
+ uchar outDataPackets[4];
+ uchar outDataBytes[4];
+ uchar outCompDataBytes[4];
+ uchar outCompStats[4*NCompStats];
+ uchar inPackets[4];
+ uchar inDataPackets[4];
+ uchar inDataBytes[4];
+ uchar inCompDataBytes[4];
+ uchar inMissing[4];
+ uchar inDup[4];
+ uchar inReorder[4];
+ uchar inBadComp[4];
+ uchar inBadAuth[4];
+ uchar inBadSeq[4];
+ uchar inBadOther[4];
+};
+
+struct Algorithm
+{
+ char *name;
+ int keylen; // in bytes
+ void (*init)(Conv*);
+};
+
+enum {
+ RC4forward = 10*1024*1024, // maximum skip forward
+ RC4back = 100*1024, // maximum look back
+};
+
+struct CipherRc4
+{
+ ulong cseq; // current byte sequence number
+ RC4state current;
+
+ int ovalid; // old is valid
+ ulong lgseq; // last good sequence
+ ulong oseq; // old byte sequence number
+ RC4state old;
+};
+
+static Dirtab sdpdirtab[]={
+ "log", {Qlog}, 0, 0666,
+ "clone", {Qclone}, 0, 0666,
+};
+
+static Dirtab convdirtab[]={
+ "ctl", {Qctl}, 0, 0666,
+ "data", {Qdata}, 0, 0666,
+ "control", {Qcontrol}, 0, 0666,
+ "status", {Qstatus}, 0, 0444,
+ "stats", {Qstats}, 0, 0444,
+ "rstats", {Qrstats}, 0, 0444,
+};
+
+static int m2p[] = {
+ [OREAD] 4,
+ [OWRITE] 2,
+ [ORDWR] 6
+};
+
+enum {
+ Logcompress= (1<<0),
+ Logauth= (1<<1),
+ Loghmac= (1<<2),
+};
+
+static Logflag logflags[] =
+{
+ { "compress", Logcompress, },
+ { "auth", Logauth, },
+ { "hmac", Loghmac, },
+ { nil, 0, },
+};
+
+static Dirtab *dirtab[MaxQ];
+static Sdp sdptab[Nfs];
+static char *convstatename[] = {
+ [CFree] "Free",
+ [CInit] "Init",
+ [CDial] "Dial",
+ [CAccept] "Accept",
+ [COpen] "Open",
+ [CLocalClose] "LocalClose",
+ [CRemoteClose] "RemoteClose",
+ [CClosed] "Closed",
+};
+
+static int sdpgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp);
+static Conv *sdpclone(Sdp *sdp);
+static void sdpackproc(void *a);
+static void onewaycleanup(OneWay *ow);
+static int readready(void *a);
+static int controlread();
+static void convsetstate(Conv *c, int state);
+static Block *readcontrol(Conv *c, int n);
+static void writecontrol(Conv *c, void *p, int n, int wait);
+static Block *readdata(Conv *c, int n);
+static long writedata(Conv *c, Block *b);
+static void convderef(Conv *c);
+static Block *conviput(Conv *c, Block *b, int control);
+static void conviconnect(Conv *c, int op, Block *b);
+static void convicontrol(Conv *c, int op, Block *b);
+static Block *convicomp(Conv *c, int op, ulong, Block *b);
+static void convoput(Conv *c, int type, int subtype, Block *b);
+static void convoconnect(Conv *c, int op, ulong dialid, ulong acceptid);
+static void convopenchan(Conv *c, char *path);
+static void convstats(Conv *c, int local, char *buf, int n);
+static void convreader(void *a);
+
+static void setalg(Conv *c, char *name, Algorithm *tab, Algorithm **);
+static void setsecret(OneWay *cc, char *secret);
+
+static void nullcipherinit(Conv*c);
+static void descipherinit(Conv*c);
+static void rc4cipherinit(Conv*c);
+static void nullauthinit(Conv*c);
+static void shaauthinit(Conv*c);
+static void md5authinit(Conv*c);
+static void nullcompinit(Conv*c);
+static void thwackcompinit(Conv*c);
+
+static Algorithm cipheralg[] =
+{
+ "null", 0, nullcipherinit,
+ "des_56_cbc", 7, descipherinit,
+ "rc4_128", 16, rc4cipherinit,
+ "rc4_256", 32, rc4cipherinit,
+ nil, 0, nil,
+};
+
+static Algorithm authalg[] =
+{
+ "null", 0, nullauthinit,
+ "hmac_sha1_96", 16, shaauthinit,
+ "hmac_md5_96", 16, md5authinit,
+ nil, 0, nil,
+};
+
+static Algorithm compalg[] =
+{
+ "null", 0, nullcompinit,
+ "thwack", 0, thwackcompinit,
+ nil, 0, nil,
+};
+
+
+static void
+sdpinit(void)
+{
+ int i;
+ Dirtab *dt;
+
+ // setup dirtab with non directory entries
+ for(i=0; i<nelem(sdpdirtab); i++) {
+ dt = sdpdirtab + i;
+ dirtab[TYPE(dt->qid)] = dt;
+ }
+
+ for(i=0; i<nelem(convdirtab); i++) {
+ dt = convdirtab + i;
+ dirtab[TYPE(dt->qid)] = dt;
+ }
+
+}
+
+static Chan*
+sdpattach(char* spec)
+{
+ Chan *c;
+ int dev;
+ char buf[100];
+ Sdp *sdp;
+ int start;
+
+ dev = atoi(spec);
+ if(dev<0 || dev >= Nfs)
+ error("bad specification");
+
+ c = devattach('E', spec);
+ c->qid = (Qid){QID(0, Qtopdir), 0, QTDIR};
+ c->dev = dev;
+
+ sdp = sdptab + dev;
+ qlock(sdp);
+ start = sdp->ackproc == 0;
+ sdp->ackproc = 1;
+ qunlock(sdp);
+
+ if(start) {
+ snprint(buf, sizeof(buf), "sdpackproc%d", dev);
+ kproc(buf, sdpackproc, sdp);
+ }
+
+ return c;
+}
+
+static Walkqid*
+sdpwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, 0, 0, sdpgen);
+}
+
+static int
+sdpstat(Chan* c, uchar* db, int n)
+{
+ return devstat(c, db, n, nil, 0, sdpgen);
+}
+
+static Chan*
+sdpopen(Chan* ch, int omode)
+{
+ int perm;
+ Sdp *sdp;
+ Conv *c;
+
+ omode &= 3;
+ perm = m2p[omode];
+ USED(perm);
+
+ sdp = sdptab + ch->dev;
+
+ switch(TYPE(ch->qid)) {
+ default:
+ break;
+ case Qtopdir:
+ case Qsdpdir:
+ case Qconvdir:
+ if(omode != OREAD)
+ error(Eperm);
+ break;
+ case Qlog:
+ logopen(sdp);
+ break;
+ case Qclone:
+ c = sdpclone(sdp);
+ if(c == nil)
+ error(Enodev);
+ ch->qid.path = QID(c->id, Qctl);
+ break;
+ case Qdata:
+ case Qctl:
+ case Qstatus:
+ case Qcontrol:
+ case Qstats:
+ case Qrstats:
+ c = sdp->conv[CONV(ch->qid)];
+ qlock(c);
+ if(waserror()) {
+ qunlock(c);
+ nexterror();
+ }
+ if((perm & (c->perm>>6)) != perm)
+ if(strcmp(up->user, c->owner) != 0 || (perm & c->perm) != perm)
+ error(Eperm);
+
+ c->ref++;
+ if(TYPE(ch->qid) == Qdata) {
+ c->dataopen++;
+ // kill reader if Qdata is opened for the first time
+ if(c->dataopen == 1)
+ if(c->readproc != nil)
+ postnote(c->readproc, 1, "interrupt", 0);
+ } else if(TYPE(ch->qid) == Qcontrol) {
+ c->controlopen++;
+ }
+ qunlock(c);
+ poperror();
+ break;
+ }
+ ch->mode = openmode(omode);
+ ch->flag |= COPEN;
+ ch->offset = 0;
+ return ch;
+}
+
+static void
+sdpclose(Chan* ch)
+{
+ Sdp *sdp = sdptab + ch->dev;
+ Conv *c;
+
+ if(!(ch->flag & COPEN))
+ return;
+ switch(TYPE(ch->qid)) {
+ case Qlog:
+ logclose(sdp);
+ break;
+ case Qctl:
+ case Qstatus:
+ case Qstats:
+ case Qrstats:
+ c = sdp->conv[CONV(ch->qid)];
+ qlock(c);
+ convderef(c);
+ qunlock(c);
+ break;
+
+ case Qdata:
+ c = sdp->conv[CONV(ch->qid)];
+ qlock(c);
+ c->dataopen--;
+ convderef(c);
+ if(c->dataopen == 0)
+ if(c->reader == 0)
+ if(c->chan != nil)
+ if(!waserror()) {
+ kproc("convreader", convreader, c);
+ c->reader = 1;
+ c->ref++;
+ poperror();
+ }
+ qunlock(c);
+ break;
+
+ case Qcontrol:
+ c = sdp->conv[CONV(ch->qid)];
+ qlock(c);
+ c->controlopen--;
+ convderef(c);
+ if(c->controlopen == 0 && c->ref != 0) {
+ switch(c->state) {
+ default:
+ convsetstate(c, CClosed);
+ break;
+ case CAccept:
+ case COpen:
+ convsetstate(c, CLocalClose);
+ break;
+ }
+ }
+ qunlock(c);
+ break;
+ }
+}
+
+static long
+sdpread(Chan *ch, void *a, long n, vlong off)
+{
+ char buf[256];
+ char *s;
+ Sdp *sdp = sdptab + ch->dev;
+ Conv *c;
+ Block *b;
+ int rv;
+
+ USED(off);
+ switch(TYPE(ch->qid)) {
+ default:
+ error(Eperm);
+ case Qtopdir:
+ case Qsdpdir:
+ case Qconvdir:
+ return devdirread(ch, a, n, 0, 0, sdpgen);
+ case Qlog:
+ return logread(sdp, a, off, n);
+ case Qstatus:
+ c = sdp->conv[CONV(ch->qid)];
+ qlock(c);
+ n = readstr(off, a, n, convstatename[c->state]);
+ qunlock(c);
+ return n;
+ case Qctl:
+ sprint(buf, "%lud", CONV(ch->qid));
+ return readstr(off, a, n, buf);
+ case Qcontrol:
+ b = readcontrol(sdp->conv[CONV(ch->qid)], n);
+ if(b == nil)
+ return 0;
+ if(BLEN(b) < n)
+ n = BLEN(b);
+ memmove(a, b->rp, n);
+ freeb(b);
+ return n;
+ case Qdata:
+ b = readdata(sdp->conv[CONV(ch->qid)], n);
+ if(b == nil)
+ return 0;
+ if(BLEN(b) < n)
+ n = BLEN(b);
+ memmove(a, b->rp, n);
+ freeb(b);
+ return n;
+ case Qstats:
+ case Qrstats:
+ c = sdp->conv[CONV(ch->qid)];
+ s = smalloc(1000);
+ convstats(c, TYPE(ch->qid) == Qstats, s, 1000);
+ rv = readstr(off, a, n, s);
+ free(s);
+ return rv;
+ }
+}
+
+static Block*
+sdpbread(Chan* ch, long n, ulong offset)
+{
+ Sdp *sdp = sdptab + ch->dev;
+
+ if(TYPE(ch->qid) != Qdata)
+ return devbread(ch, n, offset);
+ return readdata(sdp->conv[CONV(ch->qid)], n);
+}
+
+
+static long
+sdpwrite(Chan *ch, void *a, long n, vlong off)
+{
+ Sdp *sdp = sdptab + ch->dev;
+ Cmdbuf *cb;
+ char *arg0;
+ char *p;
+ Conv *c;
+ Block *b;
+
+ USED(off);
+ switch(TYPE(ch->qid)) {
+ default:
+ error(Eperm);
+ case Qctl:
+ c = sdp->conv[CONV(ch->qid)];
+ cb = parsecmd(a, n);
+ qlock(c);
+ if(waserror()) {
+ qunlock(c);
+ free(cb);
+ nexterror();
+ }
+ if(cb->nf == 0)
+ error("short write");
+ arg0 = cb->f[0];
+ if(strcmp(arg0, "accept") == 0) {
+ if(cb->nf != 2)
+ error("usage: accept file");
+ convopenchan(c, cb->f[1]);
+ } else if(strcmp(arg0, "dial") == 0) {
+ if(cb->nf != 2)
+ error("usage: dial file");
+ convopenchan(c, cb->f[1]);
+ convsetstate(c, CDial);
+ } else if(strcmp(arg0, "drop") == 0) {
+ if(cb->nf != 2)
+ error("usage: drop permil");
+ c->drop = atoi(cb->f[1]);
+ } else if(strcmp(arg0, "cipher") == 0) {
+ if(cb->nf != 2)
+ error("usage: cipher alg");
+ setalg(c, cb->f[1], cipheralg, &c->cipher);
+ } else if(strcmp(arg0, "auth") == 0) {
+ if(cb->nf != 2)
+ error("usage: auth alg");
+ setalg(c, cb->f[1], authalg, &c->auth);
+ } else if(strcmp(arg0, "comp") == 0) {
+ if(cb->nf != 2)
+ error("usage: comp alg");
+ setalg(c, cb->f[1], compalg, &c->comp);
+ } else if(strcmp(arg0, "insecret") == 0) {
+ if(cb->nf != 2)
+ error("usage: insecret secret");
+ setsecret(&c->in, cb->f[1]);
+ if(c->cipher)
+ c->cipher->init(c);
+ if(c->auth)
+ c->auth->init(c);
+ } else if(strcmp(arg0, "outsecret") == 0) {
+ if(cb->nf != 2)
+ error("usage: outsecret secret");
+ setsecret(&c->out, cb->f[1]);
+ if(c->cipher)
+ c->cipher->init(c);
+ if(c->auth)
+ c->auth->init(c);
+ } else
+ error("unknown control request");
+ poperror();
+ qunlock(c);
+ free(cb);
+ return n;
+ case Qlog:
+ cb = parsecmd(a, n);
+ p = logctl(sdp, cb->nf, cb->f, logflags);
+ free(cb);
+ if(p != nil)
+ error(p);
+ return n;
+ case Qcontrol:
+ writecontrol(sdp->conv[CONV(ch->qid)], a, n, 0);
+ return n;
+ case Qdata:
+ b = allocb(n);
+ memmove(b->wp, a, n);
+ b->wp += n;
+ return writedata(sdp->conv[CONV(ch->qid)], b);
+ }
+}
+
+long
+sdpbwrite(Chan *ch, Block *bp, ulong offset)
+{
+ Sdp *sdp = sdptab + ch->dev;
+
+ if(TYPE(ch->qid) != Qdata)
+ return devbwrite(ch, bp, offset);
+ return writedata(sdp->conv[CONV(ch->qid)], bp);
+}
+
+static int
+sdpgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
+{
+ Sdp *sdp = sdptab + c->dev;
+ int type = TYPE(c->qid);
+ Dirtab *dt;
+ Qid qid;
+
+ if(s == DEVDOTDOT){
+ switch(TYPE(c->qid)){
+ case Qtopdir:
+ case Qsdpdir:
+ snprint(up->genbuf, sizeof(up->genbuf), "#E%ld", c->dev);
+ mkqid(&qid, Qtopdir, 0, QTDIR);
+ devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ break;
+ case Qconvdir:
+ snprint(up->genbuf, sizeof(up->genbuf), "%d", s);
+ mkqid(&qid, Qsdpdir, 0, QTDIR);
+ devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ break;
+ default:
+ panic("sdpwalk %llux", c->qid.path);
+ }
+ return 1;
+ }
+
+ switch(type) {
+ default:
+ // non directory entries end up here
+ if(c->qid.type & QTDIR)
+ panic("sdpgen: unexpected directory");
+ if(s != 0)
+ return -1;
+ dt = dirtab[TYPE(c->qid)];
+ if(dt == nil)
+ panic("sdpgen: unknown type: %lud", TYPE(c->qid));
+ devdir(c, c->qid, dt->name, dt->length, eve, dt->perm, dp);
+ return 1;
+ case Qtopdir:
+ if(s != 0)
+ return -1;
+ mkqid(&qid, QID(0, Qsdpdir), 0, QTDIR);
+ devdir(c, qid, "sdp", 0, eve, 0555, dp);
+ return 1;
+ case Qsdpdir:
+ if(s<nelem(sdpdirtab)) {
+ dt = sdpdirtab+s;
+ devdir(c, dt->qid, dt->name, dt->length, eve, dt->perm, dp);
+ return 1;
+ }
+ s -= nelem(sdpdirtab);
+ if(s >= sdp->nconv)
+ return -1;
+ mkqid(&qid, QID(s, Qconvdir), 0, QTDIR);
+ snprint(up->genbuf, sizeof(up->genbuf), "%d", s);
+ devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ return 1;
+ case Qconvdir:
+ if(s>=nelem(convdirtab))
+ return -1;
+ dt = convdirtab+s;
+ mkqid(&qid, QID(CONV(c->qid),TYPE(dt->qid)), 0, QTFILE);
+ devdir(c, qid, dt->name, dt->length, eve, dt->perm, dp);
+ return 1;
+ }
+}
+
+static Conv*
+sdpclone(Sdp *sdp)
+{
+ Conv *c, **pp, **ep;
+
+ c = nil;
+ ep = sdp->conv + nelem(sdp->conv);
+ qlock(sdp);
+ if(waserror()) {
+ qunlock(sdp);
+ nexterror();
+ }
+ for(pp = sdp->conv; pp < ep; pp++) {
+ c = *pp;
+ if(c == nil){
+ c = malloc(sizeof(Conv));
+ if(c == nil)
+ error(Enomem);
+ memset(c, 0, sizeof(Conv));
+ qlock(c);
+ c->sdp = sdp;
+ c->id = pp - sdp->conv;
+ *pp = c;
+ sdp->nconv++;
+ break;
+ }
+ if(c->ref == 0 && canqlock(c)){
+ if(c->ref == 0)
+ break;
+ qunlock(c);
+ }
+ }
+ poperror();
+ qunlock(sdp);
+
+ if(pp >= ep)
+ return nil;
+
+ assert(c->state == CFree);
+ // set ref to 2 - 1 ref for open - 1 ref for channel state
+ c->ref = 2;
+ c->state = CInit;
+ c->in.window = ~0;
+ strncpy(c->owner, up->user, sizeof(c->owner));
+ c->perm = 0660;
+ qunlock(c);
+
+ return c;
+}
+
+// assume c is locked
+static void
+convretryinit(Conv *c)
+{
+ c->retries = 0;
+ // +2 to avoid rounding effects.
+ c->timeout = TK2SEC(m->ticks) + 2;
+}
+
+// assume c is locked
+static int
+convretry(Conv *c, int reset)
+{
+ c->retries++;
+ if(c->retries > MaxRetries) {
+ if(reset)
+ convoconnect(c, ConReset, c->dialid, c->acceptid);
+ convsetstate(c, CClosed);
+ return 0;
+ }
+ c->timeout = TK2SEC(m->ticks) + (c->retries+1);
+ return 1;
+}
+
+// assumes c is locked
+static void
+convtimer(Conv *c, ulong sec)
+{
+ Block *b;
+
+ if(c->timeout > sec)
+ return;
+
+ switch(c->state) {
+ case CInit:
+ break;
+ case CDial:
+ if(convretry(c, 1))
+ convoconnect(c, ConOpenRequest, c->dialid, 0);
+ break;
+ case CAccept:
+ if(convretry(c, 1))
+ convoconnect(c, ConOpenAck, c->dialid, c->acceptid);
+ break;
+ case COpen:
+ b = c->out.controlpkt;
+ if(b != nil) {
+ if(convretry(c, 1))
+ convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b)));
+ break;
+ }
+
+ c->timeout = c->lastrecv + KeepAlive;
+ if(c->timeout > sec)
+ break;
+ // keepalive - randomly spaced between KeepAlive and 2*KeepAlive
+ if(c->timeout + KeepAlive > sec && nrand(c->lastrecv + 2*KeepAlive - sec) > 0)
+ break;
+ // can not use writecontrol
+ b = allocb(4);
+ c->out.controlseq++;
+ hnputl(b->wp, c->out.controlseq);
+ b->wp += 4;
+ c->out.controlpkt = b;
+ convretryinit(c);
+ if(!waserror()) {
+ convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b)));
+ poperror();
+ }
+ break;
+ case CLocalClose:
+ if(convretry(c, 0))
+ convoconnect(c, ConClose, c->dialid, c->acceptid);
+ break;
+ case CRemoteClose:
+ case CClosed:
+ break;
+ }
+}
+
+
+static void
+sdpackproc(void *a)
+{
+ Sdp *sdp = a;
+ ulong sec;
+ int i;
+ Conv *c;
+
+ for(;;) {
+ tsleep(&up->sleep, return0, 0, 1000);
+ sec = TK2SEC(m->ticks);
+ qlock(sdp);
+ for(i=0; i<sdp->nconv; i++) {
+ c = sdp->conv[i];
+ if(c->ref == 0)
+ continue;
+ qunlock(sdp);
+ qlock(c);
+ if(c->ref > 0 && !waserror()) {
+ convtimer(c, sec);
+ poperror();
+ }
+ qunlock(c);
+ qlock(sdp);
+ }
+ qunlock(sdp);
+ }
+}
+
+Dev sdpdevtab = {
+ 'E',
+ "sdp",
+
+ devreset,
+ sdpinit,
+ devshutdown,
+ sdpattach,
+ sdpwalk,
+ sdpstat,
+ sdpopen,
+ devcreate,
+ sdpclose,
+ sdpread,
+ devbread,
+ sdpwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+// assume hold lock on c
+static void
+convsetstate(Conv *c, int state)
+{
+
+if(0)print("convsetstate %d: %s -> %s\n", c->id, convstatename[c->state], convstatename[state]);
+
+ switch(state) {
+ default:
+ panic("setstate: bad state: %d", state);
+ case CDial:
+ assert(c->state == CInit);
+ c->dialid = (rand()<<16) + rand();
+ convretryinit(c);
+ convoconnect(c, ConOpenRequest, c->dialid, 0);
+ break;
+ case CAccept:
+ assert(c->state == CInit);
+ c->acceptid = (rand()<<16) + rand();
+ convretryinit(c);
+ convoconnect(c, ConOpenAck, c->dialid, c->acceptid);
+ break;
+ case COpen:
+ assert(c->state == CDial || c->state == CAccept);
+ c->lastrecv = TK2SEC(m->ticks);
+ if(c->state == CDial) {
+ convretryinit(c);
+ convoconnect(c, ConOpenAckAck, c->dialid, c->acceptid);
+ hnputl(c->in.secret, c->acceptid);
+ hnputl(c->in.secret+4, c->dialid);
+ hnputl(c->out.secret, c->dialid);
+ hnputl(c->out.secret+4, c->acceptid);
+ } else {
+ hnputl(c->in.secret, c->dialid);
+ hnputl(c->in.secret+4, c->acceptid);
+ hnputl(c->out.secret, c->acceptid);
+ hnputl(c->out.secret+4, c->dialid);
+ }
+ setalg(c, "hmac_md5_96", authalg, &c->auth);
+ break;
+ case CLocalClose:
+ assert(c->state == CAccept || c->state == COpen);
+ convretryinit(c);
+ convoconnect(c, ConClose, c->dialid, c->acceptid);
+ break;
+ case CRemoteClose:
+ wakeup(&c->in.controlready);
+ wakeup(&c->out.controlready);
+ break;
+ case CClosed:
+ wakeup(&c->in.controlready);
+ wakeup(&c->out.controlready);
+ if(c->readproc)
+ postnote(c->readproc, 1, "interrupt", 0);
+ if(c->state != CClosed)
+ convderef(c);
+ break;
+ }
+ c->state = state;
+}
+
+
+//assumes c is locked
+static void
+convderef(Conv *c)
+{
+ c->ref--;
+ if(c->ref > 0) {
+ return;
+ }
+ assert(c->ref == 0);
+ assert(c->dataopen == 0);
+ assert(c->controlopen == 0);
+if(0)print("convderef: %d: ref == 0!\n", c->id);
+ c->state = CFree;
+ if(c->chan) {
+ cclose(c->chan);
+ c->chan = nil;
+ }
+ if(c->channame) {
+ free(c->channame);
+ c->channame = nil;
+ }
+ c->cipher = nil;
+ c->auth = nil;
+ c->comp = nil;
+ strcpy(c->owner, "network");
+ c->perm = 0660;
+ c->dialid = 0;
+ c->acceptid = 0;
+ c->timeout = 0;
+ c->retries = 0;
+ c->drop = 0;
+ onewaycleanup(&c->in);
+ onewaycleanup(&c->out);
+ memset(&c->lstats, 0, sizeof(Stats));
+ memset(&c->rstats, 0, sizeof(Stats));
+}
+
+static void
+onewaycleanup(OneWay *ow)
+{
+ if(ow->controlpkt)
+ freeb(ow->controlpkt);
+ if(ow->authstate)
+ free(ow->authstate);
+ if(ow->cipherstate)
+ free(ow->cipherstate);
+ if(ow->compstate)
+ free(ow->compstate);
+ memset(ow, 0, sizeof(OneWay));
+}
+
+
+// assumes conv is locked
+static void
+convopenchan(Conv *c, char *path)
+{
+ if(c->state != CInit || c->chan != nil)
+ error("already connected");
+ c->chan = namec(path, Aopen, ORDWR, 0);
+ c->channame = smalloc(strlen(path)+1);
+ strcpy(c->channame, path);
+ if(waserror()) {
+ cclose(c->chan);
+ c->chan = nil;
+ free(c->channame);
+ c->channame = nil;
+ nexterror();
+ }
+ kproc("convreader", convreader, c);
+
+ assert(c->reader == 0 && c->ref > 0);
+ // after kproc in case it fails
+ c->reader = 1;
+ c->ref++;
+
+ poperror();
+}
+
+static void
+convstats(Conv *c, int local, char *buf, int n)
+{
+ Stats *stats;
+ char *p, *ep;
+ int i;
+
+ if(local) {
+ stats = &c->lstats;
+ } else {
+ if(!waserror()) {
+ writecontrol(c, 0, 0, 1);
+ poperror();
+ }
+ stats = &c->rstats;
+ }
+
+ qlock(c);
+ p = buf;
+ ep = buf + n;
+ p += snprint(p, ep-p, "outPackets: %lud\n", stats->outPackets);
+ p += snprint(p, ep-p, "outDataPackets: %lud\n", stats->outDataPackets);
+ p += snprint(p, ep-p, "outDataBytes: %lud\n", stats->outDataBytes);
+ p += snprint(p, ep-p, "outCompDataBytes: %lud\n", stats->outCompDataBytes);
+ for(i=0; i<NCompStats; i++) {
+ if(stats->outCompStats[i] == 0)
+ continue;
+ p += snprint(p, ep-p, "outCompStats[%d]: %lud\n", i, stats->outCompStats[i]);
+ }
+ p += snprint(p, ep-p, "inPackets: %lud\n", stats->inPackets);
+ p += snprint(p, ep-p, "inDataPackets: %lud\n", stats->inDataPackets);
+ p += snprint(p, ep-p, "inDataBytes: %lud\n", stats->inDataBytes);
+ p += snprint(p, ep-p, "inCompDataBytes: %lud\n", stats->inCompDataBytes);
+ p += snprint(p, ep-p, "inMissing: %lud\n", stats->inMissing);
+ p += snprint(p, ep-p, "inDup: %lud\n", stats->inDup);
+ p += snprint(p, ep-p, "inReorder: %lud\n", stats->inReorder);
+ p += snprint(p, ep-p, "inBadComp: %lud\n", stats->inBadComp);
+ p += snprint(p, ep-p, "inBadAuth: %lud\n", stats->inBadAuth);
+ p += snprint(p, ep-p, "inBadSeq: %lud\n", stats->inBadSeq);
+ p += snprint(p, ep-p, "inBadOther: %lud\n", stats->inBadOther);
+ USED(p);
+ qunlock(c);
+}
+
+// c is locked
+static void
+convack(Conv *c)
+{
+ Block *b;
+ AckPkt *ack;
+ Stats *s;
+ int i;
+
+ b = allocb(sizeof(AckPkt));
+ ack = (AckPkt*)b->wp;
+ b->wp += sizeof(AckPkt);
+ s = &c->lstats;
+ hnputl(ack->cseq, c->in.controlseq);
+ hnputl(ack->outPackets, s->outPackets);
+ hnputl(ack->outDataPackets, s->outDataPackets);
+ hnputl(ack->outDataBytes, s->outDataBytes);
+ hnputl(ack->outCompDataBytes, s->outCompDataBytes);
+ for(i=0; i<NCompStats; i++)
+ hnputl(ack->outCompStats+i*4, s->outCompStats[i]);
+ hnputl(ack->inPackets, s->inPackets);
+ hnputl(ack->inDataPackets, s->inDataPackets);
+ hnputl(ack->inDataBytes, s->inDataBytes);
+ hnputl(ack->inCompDataBytes, s->inCompDataBytes);
+ hnputl(ack->inMissing, s->inMissing);
+ hnputl(ack->inDup, s->inDup);
+ hnputl(ack->inReorder, s->inReorder);
+ hnputl(ack->inBadComp, s->inBadComp);
+ hnputl(ack->inBadAuth, s->inBadAuth);
+ hnputl(ack->inBadSeq, s->inBadSeq);
+ hnputl(ack->inBadOther, s->inBadOther);
+ convoput(c, TControl, ControlAck, b);
+}
+
+
+// assume we hold lock for c
+static Block *
+conviput(Conv *c, Block *b, int control)
+{
+ int type, subtype;
+ ulong seq, seqwrap;
+ long seqdiff;
+ int pad;
+
+ c->lstats.inPackets++;
+
+ if(BLEN(b) < 4) {
+ c->lstats.inBadOther++;
+ freeb(b);
+ return nil;
+ }
+
+ type = b->rp[0] >> 4;
+ subtype = b->rp[0] & 0xf;
+ b->rp += 1;
+ if(type == TConnect) {
+ conviconnect(c, subtype, b);
+ return nil;
+ }
+
+ switch(c->state) {
+ case CInit:
+ case CDial:
+ c->lstats.inBadOther++;
+ convoconnect(c, ConReset, c->dialid, c->acceptid);
+ convsetstate(c, CClosed);
+ break;
+ case CAccept:
+ case CRemoteClose:
+ case CLocalClose:
+ c->lstats.inBadOther++;
+ freeb(b);
+ return nil;
+ }
+
+ seq = (b->rp[0]<<16) + (b->rp[1]<<8) + b->rp[2];
+ b->rp += 3;
+
+ seqwrap = c->in.seqwrap;
+ seqdiff = seq - c->in.seq;
+ if(seqdiff < -(SeqMax*3/4)) {
+ seqwrap++;
+ seqdiff += SeqMax;
+ } else if(seqdiff > SeqMax*3/4) {
+ seqwrap--;
+ seqdiff -= SeqMax;
+ }
+
+ if(seqdiff <= 0) {
+ if(seqdiff <= -SeqWindow) {
+if(0)print("old sequence number: %ld (%ld %ld)\n", seq, c->in.seqwrap, seqdiff);
+ c->lstats.inBadSeq++;
+ freeb(b);
+ return nil;
+ }
+
+ if(c->in.window & (1<<-seqdiff)) {
+if(0)print("dup sequence number: %ld (%ld %ld)\n", seq, c->in.seqwrap, seqdiff);
+ c->lstats.inDup++;
+ freeb(b);
+ return nil;
+ }
+
+ c->lstats.inReorder++;
+ }
+
+ // ok the sequence number looks ok
+if(0) print("coniput seq=%ulx\n", seq);
+ if(c->in.auth != 0) {
+ if(!(*c->in.auth)(&c->in, b->rp-4, BLEN(b)+4)) {
+if(0)print("bad auth %ld\n", BLEN(b)+4);
+ c->lstats.inBadAuth++;
+ freeb(b);
+ return nil;
+ }
+ b->wp -= c->in.authlen;
+ }
+
+ if(c->in.cipher != 0) {
+ if(!(*c->in.cipher)(&c->in, b->rp, BLEN(b))) {
+if(0)print("bad cipher\n");
+ c->lstats.inBadOther++;
+ freeb(b);
+ return nil;
+ }
+ b->rp += c->in.cipherivlen;
+ if(c->in.cipherblklen > 1) {
+ pad = b->wp[-1];
+ if(pad > BLEN(b)) {
+if(0)print("pad too big\n");
+ c->lstats.inBadOther++;
+ freeb(b);
+ return nil;
+ }
+ b->wp -= pad;
+ }
+ }
+
+ // ok the packet is good
+ if(seqdiff > 0) {
+ while(seqdiff > 0 && c->in.window != 0) {
+ if((c->in.window & (1<<(SeqWindow-1))) == 0) {
+ c->lstats.inMissing++;
+ }
+ c->in.window <<= 1;
+ seqdiff--;
+ }
+ if(seqdiff > 0) {
+ c->lstats.inMissing += seqdiff;
+ seqdiff = 0;
+ }
+ c->in.seq = seq;
+ c->in.seqwrap = seqwrap;
+ }
+ c->in.window |= 1<<-seqdiff;
+ c->lastrecv = TK2SEC(m->ticks);
+
+ switch(type) {
+ case TControl:
+ convicontrol(c, subtype, b);
+ return nil;
+ case TData:
+ c->lstats.inDataPackets++;
+ c->lstats.inDataBytes += BLEN(b);
+ if(control)
+ break;
+ return b;
+ case TCompData:
+ c->lstats.inDataPackets++;
+ c->lstats.inCompDataBytes += BLEN(b);
+ b = convicomp(c, subtype, seq, b);
+ if(b == nil) {
+ c->lstats.inBadComp++;
+ return nil;
+ }
+ c->lstats.inDataBytes += BLEN(b);
+ if(control)
+ break;
+ return b;
+ }
+if(0)print("dropping packet id=%d: type=%d n=%ld control=%d\n", c->id, type, BLEN(b), control);
+ c->lstats.inBadOther++;
+ freeb(b);
+ return nil;
+}
+
+// assume hold conv lock
+static void
+conviconnect(Conv *c, int subtype, Block *b)
+{
+ ulong dialid;
+ ulong acceptid;
+
+ if(BLEN(b) != 8) {
+ freeb(b);
+ return;
+ }
+ dialid = nhgetl(b->rp);
+ acceptid = nhgetl(b->rp + 4);
+ freeb(b);
+
+if(0)print("sdp: conviconnect: %s: %d %uld %uld\n", convstatename[c->state], subtype, dialid, acceptid);
+
+ if(subtype == ConReset) {
+ convsetstate(c, CClosed);
+ return;
+ }
+
+ switch(c->state) {
+ default:
+ panic("unknown state: %d", c->state);
+ case CInit:
+ break;
+ case CDial:
+ if(dialid != c->dialid)
+ goto Reset;
+ break;
+ case CAccept:
+ case COpen:
+ case CLocalClose:
+ case CRemoteClose:
+ if(dialid != c->dialid
+ || subtype != ConOpenRequest && acceptid != c->acceptid)
+ goto Reset;
+ break;
+ case CClosed:
+ goto Reset;
+ }
+
+ switch(subtype) {
+ case ConOpenRequest:
+ switch(c->state) {
+ case CInit:
+ c->dialid = dialid;
+ convsetstate(c, CAccept);
+ return;
+ case CAccept:
+ case COpen:
+ // duplicate ConOpenRequest that we ignore
+ return;
+ }
+ break;
+ case ConOpenAck:
+ switch(c->state) {
+ case CDial:
+ c->acceptid = acceptid;
+ convsetstate(c, COpen);
+ return;
+ case COpen:
+ // duplicate that we have to ack
+ convoconnect(c, ConOpenAckAck, acceptid, dialid);
+ return;
+ }
+ break;
+ case ConOpenAckAck:
+ switch(c->state) {
+ case CAccept:
+ convsetstate(c, COpen);
+ return;
+ case COpen:
+ case CLocalClose:
+ case CRemoteClose:
+ // duplicate that we ignore
+ return;
+ }
+ break;
+ case ConClose:
+ switch(c->state) {
+ case COpen:
+ convoconnect(c, ConCloseAck, dialid, acceptid);
+ convsetstate(c, CRemoteClose);
+ return;
+ case CRemoteClose:
+ // duplicate ConClose
+ convoconnect(c, ConCloseAck, dialid, acceptid);
+ return;
+ }
+ break;
+ case ConCloseAck:
+ switch(c->state) {
+ case CLocalClose:
+ convsetstate(c, CClosed);
+ return;
+ }
+ break;
+ }
+Reset:
+ // invalid connection message - reset to sender
+if(1)print("sdp: invalid conviconnect - sending reset\n");
+ convoconnect(c, ConReset, dialid, acceptid);
+ convsetstate(c, CClosed);
+}
+
+static void
+convicontrol(Conv *c, int subtype, Block *b)
+{
+ ulong cseq;
+ AckPkt *ack;
+ int i;
+
+ if(BLEN(b) < 4)
+ return;
+ cseq = nhgetl(b->rp);
+
+ switch(subtype){
+ case ControlMesg:
+ if(cseq == c->in.controlseq) {
+if(0)print("duplicate control packet: %ulx\n", cseq);
+ // duplicate control packet
+ freeb(b);
+ if(c->in.controlpkt == nil)
+ convack(c);
+ return;
+ }
+
+ if(cseq != c->in.controlseq+1)
+ return;
+ c->in.controlseq = cseq;
+ b->rp += 4;
+ if(BLEN(b) == 0) {
+ // just a ping
+ freeb(b);
+ convack(c);
+ } else {
+ c->in.controlpkt = b;
+if(0) print("recv %ld size=%ld\n", cseq, BLEN(b));
+ wakeup(&c->in.controlready);
+ }
+ return;
+ case ControlAck:
+ if(cseq != c->out.controlseq)
+ return;
+ if(BLEN(b) < sizeof(AckPkt))
+ return;
+ ack = (AckPkt*)(b->rp);
+ c->rstats.outPackets = nhgetl(ack->outPackets);
+ c->rstats.outDataPackets = nhgetl(ack->outDataPackets);
+ c->rstats.outDataBytes = nhgetl(ack->outDataBytes);
+ c->rstats.outCompDataBytes = nhgetl(ack->outCompDataBytes);
+ for(i=0; i<NCompStats; i++)
+ c->rstats.outCompStats[i] = nhgetl(ack->outCompStats + 4*i);
+ c->rstats.inPackets = nhgetl(ack->inPackets);
+ c->rstats.inDataPackets = nhgetl(ack->inDataPackets);
+ c->rstats.inDataBytes = nhgetl(ack->inDataBytes);
+ c->rstats.inCompDataBytes = nhgetl(ack->inCompDataBytes);
+ c->rstats.inMissing = nhgetl(ack->inMissing);
+ c->rstats.inDup = nhgetl(ack->inDup);
+ c->rstats.inReorder = nhgetl(ack->inReorder);
+ c->rstats.inBadComp = nhgetl(ack->inBadComp);
+ c->rstats.inBadAuth = nhgetl(ack->inBadAuth);
+ c->rstats.inBadSeq = nhgetl(ack->inBadSeq);
+ c->rstats.inBadOther = nhgetl(ack->inBadOther);
+ freeb(b);
+ freeb(c->out.controlpkt);
+ c->out.controlpkt = nil;
+ c->timeout = c->lastrecv + KeepAlive;
+ wakeup(&c->out.controlready);
+ return;
+ }
+}
+
+static Block*
+convicomp(Conv *c, int subtype, ulong seq, Block *b)
+{
+ if(c->in.comp == nil) {
+ freeb(b);
+ return nil;
+ }
+ if(!(*c->in.comp)(c, subtype, seq, &b))
+ return nil;
+ return b;
+}
+
+// c is locked
+static void
+convwriteblock(Conv *c, Block *b)
+{
+ // simulated errors
+ if(c->drop && nrand(c->drop) == 0)
+ return;
+
+ if(waserror()) {
+ convsetstate(c, CClosed);
+ nexterror();
+ }
+ devtab[c->chan->type]->bwrite(c->chan, b, 0);
+ poperror();
+}
+
+
+// assume hold conv lock
+static void
+convoput(Conv *c, int type, int subtype, Block *b)
+{
+ int pad;
+
+ c->lstats.outPackets++;
+ /* Make room for sdp trailer */
+ if(c->out.cipherblklen > 1)
+ pad = c->out.cipherblklen - (BLEN(b) + c->out.cipherivlen) % c->out.cipherblklen;
+ else
+ pad = 0;
+
+ b = padblock(b, -(pad+c->out.authlen));
+
+ if(pad) {
+ memset(b->wp, 0, pad-1);
+ b->wp[pad-1] = pad;
+ b->wp += pad;
+ }
+
+ /* Make space to fit sdp header */
+ b = padblock(b, 4 + c->out.cipherivlen);
+ b->rp[0] = (type << 4) | subtype;
+ c->out.seq++;
+ if(c->out.seq == (1<<24)) {
+ c->out.seq = 0;
+ c->out.seqwrap++;
+ }
+ b->rp[1] = c->out.seq>>16;
+ b->rp[2] = c->out.seq>>8;
+ b->rp[3] = c->out.seq;
+
+ if(c->out.cipher)
+ (*c->out.cipher)(&c->out, b->rp+4, BLEN(b)-4);
+
+ // auth
+ if(c->out.auth) {
+ b->wp += c->out.authlen;
+ (*c->out.auth)(&c->out, b->rp, BLEN(b));
+ }
+
+ convwriteblock(c, b);
+}
+
+// assume hold conv lock
+static void
+convoconnect(Conv *c, int op, ulong dialid, ulong acceptid)
+{
+ Block *b;
+
+ c->lstats.outPackets++;
+ assert(c->chan != nil);
+ b = allocb(9);
+ b->wp[0] = (TConnect << 4) | op;
+ hnputl(b->wp+1, dialid);
+ hnputl(b->wp+5, acceptid);
+ b->wp += 9;
+
+ if(!waserror()) {
+ convwriteblock(c, b);
+ poperror();
+ }
+}
+
+static Block *
+convreadblock(Conv *c, int n)
+{
+ Block *b;
+ Chan *ch;
+
+ qlock(&c->readlk);
+ if(waserror()) {
+ c->readproc = nil;
+ qunlock(&c->readlk);
+ nexterror();
+ }
+ qlock(c);
+ if(c->state == CClosed) {
+ qunlock(c);
+ error("closed");
+ }
+ c->readproc = up;
+ ch = c->chan;
+ assert(c->ref > 0);
+ qunlock(c);
+
+ b = devtab[ch->type]->bread(ch, n, 0);
+ c->readproc = nil;
+ poperror();
+ qunlock(&c->readlk);
+
+ return b;
+}
+
+static int
+readready(void *a)
+{
+ Conv *c = a;
+
+ return c->in.controlpkt != nil || (c->state == CClosed) || (c->state == CRemoteClose);
+}
+
+static Block *
+readcontrol(Conv *c, int n)
+{
+ Block *b;
+
+ USED(n);
+
+ qlock(&c->in.controllk);
+ if(waserror()) {
+ qunlock(&c->in.controllk);
+ nexterror();
+ }
+ qlock(c); // this lock is not held during the sleep below
+
+ for(;;) {
+ if(c->chan == nil || c->state == CClosed) {
+ qunlock(c);
+if(0)print("readcontrol: return error - state = %s\n", convstatename[c->state]);
+ error("conversation closed");
+ }
+
+ if(c->in.controlpkt != nil)
+ break;
+
+ if(c->state == CRemoteClose) {
+ qunlock(c);
+if(0)print("readcontrol: return nil - state = %s\n", convstatename[c->state]);
+ poperror();
+ return nil;
+ }
+ qunlock(c);
+ sleep(&c->in.controlready, readready, c);
+ qlock(c);
+ }
+
+ convack(c);
+
+ b = c->in.controlpkt;
+ c->in.controlpkt = nil;
+ qunlock(c);
+ poperror();
+ qunlock(&c->in.controllk);
+ return b;
+}
+
+
+static int
+writeready(void *a)
+{
+ Conv *c = a;
+
+ return c->out.controlpkt == nil || (c->state == CClosed) || (c->state == CRemoteClose);
+}
+
+// c is locked
+static void
+writewait(Conv *c)
+{
+ for(;;) {
+ if(c->state == CFree || c->state == CInit ||
+ c->state == CClosed || c->state == CRemoteClose)
+ error("conversation closed");
+
+ if(c->state == COpen && c->out.controlpkt == nil)
+ break;
+
+ qunlock(c);
+ if(waserror()) {
+ qlock(c);
+ nexterror();
+ }
+ sleep(&c->out.controlready, writeready, c);
+ poperror();
+ qlock(c);
+ }
+}
+
+static void
+writecontrol(Conv *c, void *p, int n, int wait)
+{
+ Block *b;
+
+ qlock(&c->out.controllk);
+ qlock(c);
+ if(waserror()) {
+ qunlock(c);
+ qunlock(&c->out.controllk);
+ nexterror();
+ }
+ writewait(c);
+ b = allocb(4+n);
+ c->out.controlseq++;
+ hnputl(b->wp, c->out.controlseq);
+ memmove(b->wp+4, p, n);
+ b->wp += 4+n;
+ c->out.controlpkt = b;
+ convretryinit(c);
+ convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b)));
+ if(wait)
+ writewait(c);
+ poperror();
+ qunlock(c);
+ qunlock(&c->out.controllk);
+}
+
+static Block *
+readdata(Conv *c, int n)
+{
+ Block *b;
+ int nn;
+
+ for(;;) {
+
+ // some slack for tunneling overhead
+ nn = n + 100;
+
+ // make sure size is big enough for control messages
+ if(nn < 1000)
+ nn = 1000;
+ b = convreadblock(c, nn);
+ if(b == nil)
+ return nil;
+ qlock(c);
+ if(waserror()) {
+ qunlock(c);
+ return nil;
+ }
+ b = conviput(c, b, 0);
+ poperror();
+ qunlock(c);
+ if(b != nil) {
+ if(BLEN(b) > n)
+ b->wp = b->rp + n;
+ return b;
+ }
+ }
+}
+
+static long
+writedata(Conv *c, Block *b)
+{
+ int n;
+ ulong seq;
+ int subtype;
+
+ qlock(c);
+ if(waserror()) {
+ qunlock(c);
+ nexterror();
+ }
+
+ if(c->state != COpen) {
+ freeb(b);
+ error("conversation not open");
+ }
+
+ n = BLEN(b);
+ c->lstats.outDataPackets++;
+ c->lstats.outDataBytes += n;
+
+ if(c->out.comp != nil) {
+ // must generate same value as convoput
+ seq = (c->out.seq + 1) & (SeqMax-1);
+
+ subtype = (*c->out.comp)(c, 0, seq, &b);
+ c->lstats.outCompDataBytes += BLEN(b);
+ convoput(c, TCompData, subtype, b);
+ } else
+ convoput(c, TData, 0, b);
+
+ poperror();
+ qunlock(c);
+ return n;
+}
+
+static void
+convreader(void *a)
+{
+ Conv *c = a;
+ Block *b;
+
+ qlock(c);
+ assert(c->reader == 1);
+ while(c->dataopen == 0 && c->state != CClosed) {
+ qunlock(c);
+ b = nil;
+ if(!waserror()) {
+ b = convreadblock(c, 2000);
+ poperror();
+ }
+ qlock(c);
+ if(b == nil) {
+ if(strcmp(up->errstr, Eintr) != 0) {
+ convsetstate(c, CClosed);
+ break;
+ }
+ } else if(!waserror()) {
+ conviput(c, b, 1);
+ poperror();
+ }
+ }
+ c->reader = 0;
+ convderef(c);
+ qunlock(c);
+ pexit("hangup", 1);
+}
+
+
+/* ciphers, authenticators, and compressors */
+
+static void
+setalg(Conv *c, char *name, Algorithm *alg, Algorithm **p)
+{
+ for(; alg->name; alg++)
+ if(strcmp(name, alg->name) == 0)
+ break;
+ if(alg->name == nil)
+ error("unknown algorithm");
+
+ *p = alg;
+ alg->init(c);
+}
+
+static void
+setsecret(OneWay *ow, char *secret)
+{
+ char *p;
+ int i, c;
+
+ i = 0;
+ memset(ow->secret, 0, sizeof(ow->secret));
+ for(p=secret; *p; p++) {
+ if(i >= sizeof(ow->secret)*2)
+ break;
+ c = *p;
+ if(c >= '0' && c <= '9')
+ c -= '0';
+ else if(c >= 'a' && c <= 'f')
+ c -= 'a'-10;
+ else if(c >= 'A' && c <= 'F')
+ c -= 'A'-10;
+ else
+ error("bad character in secret");
+ if((i&1) == 0)
+ c <<= 4;
+ ow->secret[i>>1] |= c;
+ i++;
+ }
+}
+
+static void
+setkey(uchar *key, int n, OneWay *ow, char *prefix)
+{
+ uchar ibuf[SHA1dlen], obuf[MD5dlen], salt[10];
+ int i, round = 0;
+
+ while(n > 0){
+ for(i=0; i<round+1; i++)
+ salt[i] = 'A'+round;
+ sha1((uchar*)prefix, strlen(prefix), ibuf, sha1(salt, round+1, nil, nil));
+ md5(ibuf, SHA1dlen, obuf, md5(ow->secret, sizeof(ow->secret), nil, nil));
+ i = (n<MD5dlen) ? n : MD5dlen;
+ memmove(key, obuf, i);
+ key += i;
+ n -= i;
+ if(++round > sizeof salt)
+ panic("setkey: you ask too much");
+ }
+}
+
+static void
+cipherfree(Conv *c)
+{
+ if(c->in.cipherstate) {
+ free(c->in.cipherstate);
+ c->in.cipherstate = nil;
+ }
+ if(c->out.cipherstate) {
+ free(c->out.cipherstate);
+ c->out.cipherstate = nil;
+ }
+ c->in.cipher = nil;
+ c->in.cipherblklen = 0;
+ c->out.cipherblklen = 0;
+ c->in.cipherivlen = 0;
+ c->out.cipherivlen = 0;
+}
+
+static void
+authfree(Conv *c)
+{
+ if(c->in.authstate) {
+ free(c->in.authstate);
+ c->in.authstate = nil;
+ }
+ if(c->out.authstate) {
+ free(c->out.authstate);
+ c->out.authstate = nil;
+ }
+ c->in.auth = nil;
+ c->in.authlen = 0;
+ c->out.authlen = 0;
+}
+
+static void
+compfree(Conv *c)
+{
+ if(c->in.compstate) {
+ free(c->in.compstate);
+ c->in.compstate = nil;
+ }
+ if(c->out.compstate) {
+ free(c->out.compstate);
+ c->out.compstate = nil;
+ }
+ c->in.comp = nil;
+}
+
+static void
+nullcipherinit(Conv *c)
+{
+ cipherfree(c);
+}
+
+static int
+desencrypt(OneWay *ow, uchar *p, int n)
+{
+ uchar *pp, *ip, *eip, *ep;
+ DESstate *ds = ow->cipherstate;
+
+ if(n < 8 || (n & 0x7 != 0))
+ return 0;
+ ep = p + n;
+ memmove(p, ds->ivec, 8);
+ for(p += 8; p < ep; p += 8){
+ pp = p;
+ ip = ds->ivec;
+ for(eip = ip+8; ip < eip; )
+ *pp++ ^= *ip++;
+ block_cipher(ds->expanded, p, 0);
+ memmove(ds->ivec, p, 8);
+ }
+ return 1;
+}
+
+static int
+desdecrypt(OneWay *ow, uchar *p, int n)
+{
+ uchar tmp[8];
+ uchar *tp, *ip, *eip, *ep;
+ DESstate *ds = ow->cipherstate;
+
+ if(n < 8 || (n & 0x7 != 0))
+ return 0;
+ ep = p + n;
+ memmove(ds->ivec, p, 8);
+ p += 8;
+ while(p < ep){
+ memmove(tmp, p, 8);
+ block_cipher(ds->expanded, p, 1);
+ tp = tmp;
+ ip = ds->ivec;
+ for(eip = ip+8; ip < eip; ){
+ *p++ ^= *ip;
+ *ip++ = *tp++;
+ }
+ }
+ return 1;
+}
+
+static void
+descipherinit(Conv *c)
+{
+ uchar key[8];
+ uchar ivec[8];
+ int i;
+ int n = c->cipher->keylen;
+
+ cipherfree(c);
+
+ if(n > sizeof(key))
+ n = sizeof(key);
+
+ /* in */
+ memset(key, 0, sizeof(key));
+ setkey(key, n, &c->in, "cipher");
+ memset(ivec, 0, sizeof(ivec));
+ c->in.cipherblklen = 8;
+ c->in.cipherivlen = 8;
+ c->in.cipher = desdecrypt;
+ c->in.cipherstate = smalloc(sizeof(DESstate));
+ setupDESstate(c->in.cipherstate, key, ivec);
+
+ /* out */
+ memset(key, 0, sizeof(key));
+ setkey(key, n, &c->out, "cipher");
+ for(i=0; i<8; i++)
+ ivec[i] = nrand(256);
+ c->out.cipherblklen = 8;
+ c->out.cipherivlen = 8;
+ c->out.cipher = desencrypt;
+ c->out.cipherstate = smalloc(sizeof(DESstate));
+ setupDESstate(c->out.cipherstate, key, ivec);
+}
+
+static int
+rc4encrypt(OneWay *ow, uchar *p, int n)
+{
+ CipherRc4 *cr = ow->cipherstate;
+
+ if(n < 4)
+ return 0;
+
+ hnputl(p, cr->cseq);
+ p += 4;
+ n -= 4;
+ rc4(&cr->current, p, n);
+ cr->cseq += n;
+ return 1;
+}
+
+static int
+rc4decrypt(OneWay *ow, uchar *p, int n)
+{
+ CipherRc4 *cr = ow->cipherstate;
+ RC4state tmpstate;
+ ulong seq;
+ long d, dd;
+
+ if(n < 4)
+ return 0;
+
+ seq = nhgetl(p);
+ p += 4;
+ n -= 4;
+ d = seq-cr->cseq;
+ if(d == 0) {
+ rc4(&cr->current, p, n);
+ cr->cseq += n;
+ if(cr->ovalid) {
+ dd = cr->cseq - cr->lgseq;
+ if(dd > RC4back)
+ cr->ovalid = 0;
+ }
+ } else if(d > 0) {
+//print("missing packet: %uld %ld\n", seq, d);
+ // this link is hosed
+ if(d > RC4forward)
+ return 0;
+ cr->lgseq = seq;
+ if(!cr->ovalid) {
+ cr->ovalid = 1;
+ cr->oseq = cr->cseq;
+ memmove(&cr->old, &cr->current, sizeof(RC4state));
+ }
+ rc4skip(&cr->current, d);
+ rc4(&cr->current, p, n);
+ cr->cseq = seq+n;
+ } else {
+//print("reordered packet: %uld %ld\n", seq, d);
+ dd = seq - cr->oseq;
+ if(!cr->ovalid || -d > RC4back || dd < 0)
+ return 0;
+ memmove(&tmpstate, &cr->old, sizeof(RC4state));
+ rc4skip(&tmpstate, dd);
+ rc4(&tmpstate, p, n);
+ return 1;
+ }
+
+ // move old state up
+ if(cr->ovalid) {
+ dd = cr->cseq - RC4back - cr->oseq;
+ if(dd > 0) {
+ rc4skip(&cr->old, dd);
+ cr->oseq += dd;
+ }
+ }
+
+ return 1;
+}
+
+static void
+rc4cipherinit(Conv *c)
+{
+ uchar key[32];
+ CipherRc4 *cr;
+ int n;
+
+ cipherfree(c);
+
+ n = c->cipher->keylen;
+ if(n > sizeof(key))
+ n = sizeof(key);
+
+ /* in */
+ memset(key, 0, sizeof(key));
+ setkey(key, n, &c->in, "cipher");
+ c->in.cipherblklen = 1;
+ c->in.cipherivlen = 4;
+ c->in.cipher = rc4decrypt;
+ cr = smalloc(sizeof(CipherRc4));
+ memset(cr, 0, sizeof(*cr));
+ setupRC4state(&cr->current, key, n);
+ c->in.cipherstate = cr;
+
+ /* out */
+ memset(key, 0, sizeof(key));
+ setkey(key, n, &c->out, "cipher");
+ c->out.cipherblklen = 1;
+ c->out.cipherivlen = 4;
+ c->out.cipher = rc4encrypt;
+ cr = smalloc(sizeof(CipherRc4));
+ memset(cr, 0, sizeof(*cr));
+ setupRC4state(&cr->current, key, n);
+ c->out.cipherstate = cr;
+}
+
+static void
+nullauthinit(Conv *c)
+{
+ authfree(c);
+}
+
+static void
+shaauthinit(Conv *c)
+{
+ authfree(c);
+}
+
+static void
+seanq_hmac_md5(uchar hash[MD5dlen], ulong wrap, uchar *t, long tlen, uchar *key, long klen)
+{
+ uchar ipad[65], opad[65], wbuf[4];
+ int i;
+ DigestState *digest;
+ uchar innerhash[MD5dlen];
+
+ for(i=0; i<64; i++){
+ ipad[i] = 0x36;
+ opad[i] = 0x5c;
+ }
+ ipad[64] = opad[64] = 0;
+ for(i=0; i<klen; i++){
+ ipad[i] ^= key[i];
+ opad[i] ^= key[i];
+ }
+ hnputl(wbuf, wrap);
+ digest = md5(ipad, 64, nil, nil);
+ digest = md5(wbuf, sizeof(wbuf), nil, digest);
+ md5(t, tlen, innerhash, digest);
+ digest = md5(opad, 64, nil, nil);
+ md5(innerhash, MD5dlen, hash, digest);
+}
+
+static int
+md5auth(OneWay *ow, uchar *t, int tlen)
+{
+ uchar hash[MD5dlen];
+ int r;
+
+ if(tlen < ow->authlen)
+ return 0;
+ tlen -= ow->authlen;
+
+ memset(hash, 0, MD5dlen);
+ seanq_hmac_md5(hash, ow->seqwrap, t, tlen, (uchar*)ow->authstate, 16);
+ r = memcmp(t+tlen, hash, ow->authlen) == 0;
+ memmove(t+tlen, hash, ow->authlen);
+ return r;
+}
+
+static void
+md5authinit(Conv *c)
+{
+ int keylen;
+
+ authfree(c);
+
+ keylen = c->auth->keylen;
+ if(keylen > 16)
+ keylen = 16;
+
+ /* in */
+ c->in.authstate = smalloc(16);
+ memset(c->in.authstate, 0, 16);
+ setkey(c->in.authstate, keylen, &c->in, "auth");
+ c->in.authlen = 12;
+ c->in.auth = md5auth;
+
+ /* out */
+ c->out.authstate = smalloc(16);
+ memset(c->out.authstate, 0, 16);
+ setkey(c->out.authstate, keylen, &c->out, "auth");
+ c->out.authlen = 12;
+ c->out.auth = md5auth;
+}
+
+static void
+nullcompinit(Conv *c)
+{
+ compfree(c);
+}
+
+static int
+thwackcomp(Conv *c, int, ulong seq, Block **bp)
+{
+ Block *b, *bb;
+ int nn;
+ ulong ackseq;
+ uchar mask;
+
+ // add ack info
+ b = padblock(*bp, 4);
+
+ ackseq = unthwackstate(c->in.compstate, &mask);
+ b->rp[0] = mask;
+ b->rp[1] = ackseq>>16;
+ b->rp[2] = ackseq>>8;
+ b->rp[3] = ackseq;
+
+ bb = allocb(BLEN(b));
+ nn = thwack(c->out.compstate, bb->wp, b->rp, BLEN(b), seq, c->lstats.outCompStats);
+ if(nn < 0) {
+ freeb(bb);
+ *bp = b;
+ return ThwackU;
+ } else {
+ bb->wp += nn;
+ freeb(b);
+ *bp = bb;
+ return ThwackC;
+ }
+}
+
+static int
+thwackuncomp(Conv *c, int subtype, ulong seq, Block **bp)
+{
+ Block *b, *bb;
+ ulong mask;
+ ulong mseq;
+ int n;
+
+ switch(subtype) {
+ default:
+ return 0;
+ case ThwackU:
+ b = *bp;
+ mask = b->rp[0];
+ mseq = (b->rp[1]<<16) | (b->rp[2]<<8) | b->rp[3];
+ b->rp += 4;
+ thwackack(c->out.compstate, mseq, mask);
+ return 1;
+ case ThwackC:
+ bb = *bp;
+ b = allocb(ThwMaxBlock);
+ n = unthwack(c->in.compstate, b->wp, ThwMaxBlock, bb->rp, BLEN(bb), seq);
+ freeb(bb);
+ *bp = nil;
+ if(n < 0) {
+if(0)print("unthwack failed: %d\n", n);
+ freeb(b);
+ return 0;
+ }
+ b->wp += n;
+ mask = b->rp[0];
+ mseq = (b->rp[1]<<16) | (b->rp[2]<<8) | b->rp[3];
+ thwackack(c->out.compstate, mseq, mask);
+ b->rp += 4;
+ *bp = b;
+ return 1;
+ }
+}
+
+static void
+thwackcompinit(Conv *c)
+{
+ compfree(c);
+
+ c->in.compstate = malloc(sizeof(Unthwack));
+ if(c->in.compstate == nil)
+ error(Enomem);
+ unthwackinit(c->in.compstate);
+ c->out.compstate = malloc(sizeof(Thwack));
+ if(c->out.compstate == nil)
+ error(Enomem);
+ thwackinit(c->out.compstate);
+ c->in.comp = thwackuncomp;
+ c->out.comp = thwackcomp;
+}
diff --git a/sys/src/9/port/devsegment.c b/sys/src/9/port/devsegment.c
new file mode 100755
index 000000000..8e5091b79
--- /dev/null
+++ b/sys/src/9/port/devsegment.c
@@ -0,0 +1,578 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+enum
+{
+ Qtopdir,
+ Qsegdir,
+ Qctl,
+ Qdata,
+
+ /* commands to kproc */
+ Cnone=0,
+ Cread,
+ Cwrite,
+ Cstart,
+ Cdie,
+};
+
+#define TYPE(x) (int)( (c)->qid.path & 0x7 )
+#define SEG(x) ( ((c)->qid.path >> 3) & 0x3f )
+#define PATH(s, t) ( ((s)<<3) | (t) )
+
+typedef struct Globalseg Globalseg;
+struct Globalseg
+{
+ Ref;
+ Segment *s;
+
+ char *name;
+ char *uid;
+ vlong length;
+ long perm;
+
+ /* kproc to do reading and writing */
+ QLock l; /* sync kproc access */
+ Rendez cmdwait; /* where kproc waits */
+ Rendez replywait; /* where requestor waits */
+ Proc *kproc;
+ char *data;
+ long off;
+ int dlen;
+ int cmd;
+ char err[64];
+};
+
+static Globalseg *globalseg[100];
+static Lock globalseglock;
+
+
+ Segment* (*_globalsegattach)(Proc*, char*);
+static Segment* globalsegattach(Proc *p, char *name);
+static int cmddone(void*);
+static void segmentkproc(void*);
+static void docmd(Globalseg *g, int cmd);
+
+/*
+ * returns with globalseg incref'd
+ */
+static Globalseg*
+getgseg(Chan *c)
+{
+ int x;
+ Globalseg *g;
+
+ x = SEG(c);
+ lock(&globalseglock);
+ if(x >= nelem(globalseg))
+ panic("getgseg");
+ g = globalseg[x];
+ if(g != nil)
+ incref(g);
+ unlock(&globalseglock);
+ if(g == nil)
+ error("global segment disappeared");
+ return g;
+}
+
+static void
+putgseg(Globalseg *g)
+{
+ if(decref(g) > 0)
+ return;
+ if(g->s != nil)
+ putseg(g->s);
+ if(g->kproc)
+ docmd(g, Cdie);
+ free(g->name);
+ free(g->uid);
+ free(g);
+}
+
+static int
+segmentgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
+{
+ Qid q;
+ Globalseg *g;
+ ulong size;
+
+ switch(TYPE(c)) {
+ case Qtopdir:
+ if(s == DEVDOTDOT){
+ q.vers = 0;
+ q.path = PATH(0, Qtopdir);
+ q.type = QTDIR;
+ devdir(c, q, "#g", 0, eve, DMDIR|0777, dp);
+ break;
+ }
+
+ if(s >= nelem(globalseg))
+ return -1;
+
+ lock(&globalseglock);
+ g = globalseg[s];
+ if(g == nil){
+ unlock(&globalseglock);
+ return 0;
+ }
+ q.vers = 0;
+ q.path = PATH(s, Qsegdir);
+ q.type = QTDIR;
+ devdir(c, q, g->name, 0, g->uid, DMDIR|0777, dp);
+ unlock(&globalseglock);
+
+ break;
+ case Qsegdir:
+ if(s == DEVDOTDOT){
+ q.vers = 0;
+ q.path = PATH(0, Qtopdir);
+ q.type = QTDIR;
+ devdir(c, q, "#g", 0, eve, DMDIR|0777, dp);
+ break;
+ }
+ /* fall through */
+ case Qctl:
+ case Qdata:
+ switch(s){
+ case 0:
+ g = getgseg(c);
+ q.vers = 0;
+ q.path = PATH(SEG(c), Qctl);
+ q.type = QTFILE;
+ devdir(c, q, "ctl", 0, g->uid, g->perm, dp);
+ putgseg(g);
+ break;
+ case 1:
+ g = getgseg(c);
+ q.vers = 0;
+ q.path = PATH(SEG(c), Qdata);
+ q.type = QTFILE;
+ if(g->s != nil)
+ size = g->s->top - g->s->base;
+ else
+ size = 0;
+ devdir(c, q, "data", size, g->uid, g->perm, dp);
+ putgseg(g);
+ break;
+ default:
+ return -1;
+ }
+ break;
+ }
+ return 1;
+}
+
+static void
+segmentinit(void)
+{
+ _globalsegattach = globalsegattach;
+}
+
+static Chan*
+segmentattach(char *spec)
+{
+ return devattach('g', spec);
+}
+
+static Walkqid*
+segmentwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, 0, 0, segmentgen);
+}
+
+static int
+segmentstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, 0, 0, segmentgen);
+}
+
+static int
+cmddone(void *arg)
+{
+ Globalseg *g = arg;
+
+ return g->cmd == Cnone;
+}
+
+static Chan*
+segmentopen(Chan *c, int omode)
+{
+ Globalseg *g;
+
+ switch(TYPE(c)){
+ case Qtopdir:
+ case Qsegdir:
+ if(omode != 0)
+ error(Eisdir);
+ break;
+ case Qctl:
+ g = getgseg(c);
+ if(waserror()){
+ putgseg(g);
+ nexterror();
+ }
+ devpermcheck(g->uid, g->perm, omode);
+ c->aux = g;
+ poperror();
+ c->flag |= COPEN;
+ break;
+ case Qdata:
+ g = getgseg(c);
+ if(waserror()){
+ putgseg(g);
+ nexterror();
+ }
+ devpermcheck(g->uid, g->perm, omode);
+ if(g->s == nil)
+ error("segment not yet allocated");
+ if(g->kproc == nil){
+ qlock(&g->l);
+ if(waserror()){
+ qunlock(&g->l);
+ nexterror();
+ }
+ if(g->kproc == nil){
+ g->cmd = Cnone;
+ kproc(g->name, segmentkproc, g);
+ docmd(g, Cstart);
+ }
+ qunlock(&g->l);
+ poperror();
+ }
+ c->aux = g;
+ poperror();
+ c->flag |= COPEN;
+ break;
+ default:
+ panic("segmentopen");
+ }
+ c->mode = openmode(omode);
+ c->offset = 0;
+ return c;
+}
+
+static void
+segmentclose(Chan *c)
+{
+ if(TYPE(c) == Qtopdir)
+ return;
+ if(c->flag & COPEN)
+ putgseg(c->aux);
+}
+
+static void
+segmentcreate(Chan *c, char *name, int omode, ulong perm)
+{
+ int x, xfree;
+ Globalseg *g;
+
+ if(TYPE(c) != Qtopdir)
+ error(Eperm);
+
+ if(isphysseg(name))
+ error(Eexist);
+
+ if((perm & DMDIR) == 0)
+ error(Ebadarg);
+
+ if(waserror()){
+ unlock(&globalseglock);
+ nexterror();
+ }
+ lock(&globalseglock);
+ xfree = -1;
+ for(x = 0; x < nelem(globalseg); x++){
+ g = globalseg[x];
+ if(g == nil){
+ if(xfree < 0)
+ xfree = x;
+ } else {
+ if(strcmp(g->name, name) == 0)
+ error(Eexist);
+ }
+ }
+ if(xfree < 0)
+ error("too many global segments");
+ g = smalloc(sizeof(Globalseg));
+ g->ref = 1;
+ kstrdup(&g->name, name);
+ kstrdup(&g->uid, up->user);
+ g->perm = 0660;
+ globalseg[xfree] = g;
+ unlock(&globalseglock);
+ poperror();
+
+ c->qid.path = PATH(x, Qsegdir);
+ c->qid.type = QTDIR;
+ c->qid.vers = 0;
+ c->mode = openmode(omode);
+ c->mode = OWRITE;
+}
+
+static long
+segmentread(Chan *c, void *a, long n, vlong voff)
+{
+ Globalseg *g;
+ char buf[32];
+
+ if(c->qid.type == QTDIR)
+ return devdirread(c, a, n, (Dirtab *)0, 0L, segmentgen);
+
+ switch(TYPE(c)){
+ case Qctl:
+ g = c->aux;
+ if(g->s == nil)
+ error("segment not yet allocated");
+ sprint(buf, "va %#lux %#lux\n", g->s->base, g->s->top-g->s->base);
+ return readstr(voff, a, n, buf);
+ case Qdata:
+ g = c->aux;
+ if(voff > g->s->top - g->s->base)
+ error(Ebadarg);
+ if(voff + n > g->s->top - g->s->base)
+ n = g->s->top - g->s->base - voff;
+ qlock(&g->l);
+ g->off = voff + g->s->base;
+ g->data = smalloc(n);
+ if(waserror()){
+ free(g->data);
+ qunlock(&g->l);
+ nexterror();
+ }
+ g->dlen = n;
+ docmd(g, Cread);
+ memmove(a, g->data, g->dlen);
+ free(g->data);
+ qunlock(&g->l);
+ poperror();
+ return g->dlen;
+ default:
+ panic("segmentread");
+ }
+ return 0; /* not reached */
+}
+
+static long
+segmentwrite(Chan *c, void *a, long n, vlong voff)
+{
+ Cmdbuf *cb;
+ Globalseg *g;
+ ulong va, len, top;
+
+ if(c->qid.type == QTDIR)
+ error(Eperm);
+
+ switch(TYPE(c)){
+ case Qctl:
+ g = c->aux;
+ cb = parsecmd(a, n);
+ if(strcmp(cb->f[0], "va") == 0){
+ if(g->s != nil)
+ error("already has a virtual address");
+ if(cb->nf < 3)
+ error(Ebadarg);
+ va = strtoul(cb->f[1], 0, 0);
+ len = strtoul(cb->f[2], 0, 0);
+ top = PGROUND(va + len);
+ va = va&~(BY2PG-1);
+ len = (top - va) / BY2PG;
+ if(len == 0)
+ error(Ebadarg);
+ g->s = newseg(SG_SHARED, va, len);
+ } else
+ error(Ebadctl);
+ break;
+ case Qdata:
+ g = c->aux;
+ if(voff + n > g->s->top - g->s->base)
+ error(Ebadarg);
+ qlock(&g->l);
+ g->off = voff + g->s->base;
+ g->data = smalloc(n);
+ if(waserror()){
+ free(g->data);
+ qunlock(&g->l);
+ nexterror();
+ }
+ g->dlen = n;
+ memmove(g->data, a, g->dlen);
+ docmd(g, Cwrite);
+ free(g->data);
+ qunlock(&g->l);
+ poperror();
+ return g->dlen;
+ default:
+ panic("segmentwrite");
+ }
+ return 0; /* not reached */
+}
+
+static int
+segmentwstat(Chan *c, uchar *dp, int n)
+{
+ Globalseg *g;
+ Dir *d;
+
+ if(c->qid.type == QTDIR)
+ error(Eperm);
+
+ g = getgseg(c);
+ if(waserror()){
+ putgseg(g);
+ nexterror();
+ }
+
+ if(strcmp(g->uid, up->user) && !iseve())
+ error(Eperm);
+ d = smalloc(sizeof(Dir)+n);
+ n = convM2D(dp, n, &d[0], (char*)&d[1]);
+ g->perm = d->mode & 0777;
+
+ putgseg(g);
+ poperror();
+
+ free(d);
+ return n;
+}
+
+static void
+segmentremove(Chan *c)
+{
+ Globalseg *g;
+ int x;
+
+ if(TYPE(c) != Qsegdir)
+ error(Eperm);
+ lock(&globalseglock);
+ x = SEG(c);
+ g = globalseg[x];
+ globalseg[x] = nil;
+ unlock(&globalseglock);
+ if(g != nil)
+ putgseg(g);
+}
+
+/*
+ * called by segattach()
+ */
+static Segment*
+globalsegattach(Proc *p, char *name)
+{
+ int x;
+ Globalseg *g;
+ Segment *s;
+
+ g = nil;
+ if(waserror()){
+ unlock(&globalseglock);
+ nexterror();
+ }
+ lock(&globalseglock);
+ for(x = 0; x < nelem(globalseg); x++){
+ g = globalseg[x];
+ if(g != nil && strcmp(g->name, name) == 0)
+ break;
+ }
+ if(x == nelem(globalseg)){
+ unlock(&globalseglock);
+ poperror();
+ return nil;
+ }
+ devpermcheck(g->uid, g->perm, ORDWR);
+ s = g->s;
+ if(s == nil)
+ error("global segment not assigned a virtual address");
+ if(isoverlap(p, s->base, s->top - s->base) != nil)
+ error("overlaps existing segment");
+ incref(s);
+ unlock(&globalseglock);
+ poperror();
+ return s;
+}
+
+static void
+docmd(Globalseg *g, int cmd)
+{
+ g->err[0] = 0;
+ g->cmd = cmd;
+ wakeup(&g->cmdwait);
+ sleep(&g->replywait, cmddone, g);
+ if(g->err[0])
+ error(g->err);
+}
+
+static int
+cmdready(void *arg)
+{
+ Globalseg *g = arg;
+
+ return g->cmd != Cnone;
+}
+
+static void
+segmentkproc(void *arg)
+{
+ Globalseg *g = arg;
+ int done;
+ int sno;
+
+ for(sno = 0; sno < NSEG; sno++)
+ if(up->seg[sno] == nil && sno != ESEG)
+ break;
+ if(sno == NSEG)
+ panic("segmentkproc");
+ g->kproc = up;
+
+ incref(g->s);
+ up->seg[sno] = g->s;
+
+ for(done = 0; !done;){
+ sleep(&g->cmdwait, cmdready, g);
+ if(waserror()){
+ strncpy(g->err, up->errstr, sizeof(g->err));
+ } else {
+ switch(g->cmd){
+ case Cstart:
+ break;
+ case Cdie:
+ done = 1;
+ break;
+ case Cread:
+ memmove(g->data, (char*)g->off, g->dlen);
+ break;
+ case Cwrite:
+ memmove((char*)g->off, g->data, g->dlen);
+ break;
+ }
+ poperror();
+ }
+ g->cmd = Cnone;
+ wakeup(&g->replywait);
+ }
+}
+
+Dev segmentdevtab = {
+ 'g',
+ "segment",
+
+ devreset,
+ segmentinit,
+ devshutdown,
+ segmentattach,
+ segmentwalk,
+ segmentstat,
+ segmentopen,
+ segmentcreate,
+ segmentclose,
+ segmentread,
+ devbread,
+ segmentwrite,
+ devbwrite,
+ segmentremove,
+ segmentwstat,
+};
+
diff --git a/sys/src/9/port/devsrv.c b/sys/src/9/port/devsrv.c
new file mode 100755
index 000000000..161e77eed
--- /dev/null
+++ b/sys/src/9/port/devsrv.c
@@ -0,0 +1,357 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+
+typedef struct Srv Srv;
+struct Srv
+{
+ char *name;
+ char *owner;
+ ulong perm;
+ Chan *chan;
+ Srv *link;
+ ulong path;
+};
+
+static QLock srvlk;
+static Srv *srv;
+static int qidpath;
+
+static int
+srvgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
+{
+ Srv *sp;
+ Qid q;
+
+ if(s == DEVDOTDOT){
+ devdir(c, c->qid, "#s", 0, eve, 0555, dp);
+ return 1;
+ }
+
+ qlock(&srvlk);
+ for(sp = srv; sp && s; sp = sp->link)
+ s--;
+
+ if(sp == 0) {
+ qunlock(&srvlk);
+ return -1;
+ }
+
+ mkqid(&q, sp->path, 0, QTFILE);
+ /* make sure name string continues to exist after we release lock */
+ kstrcpy(up->genbuf, sp->name, sizeof up->genbuf);
+ devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp);
+ qunlock(&srvlk);
+ return 1;
+}
+
+static void
+srvinit(void)
+{
+ qidpath = 1;
+}
+
+static Chan*
+srvattach(char *spec)
+{
+ return devattach('s', spec);
+}
+
+static Walkqid*
+srvwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, 0, 0, srvgen);
+}
+
+static Srv*
+srvlookup(char *name, ulong qidpath)
+{
+ Srv *sp;
+ for(sp = srv; sp; sp = sp->link)
+ if(sp->path == qidpath || (name && strcmp(sp->name, name) == 0))
+ return sp;
+ return nil;
+}
+
+static int
+srvstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, 0, 0, srvgen);
+}
+
+char*
+srvname(Chan *c)
+{
+ Srv *sp;
+ char *s;
+
+ for(sp = srv; sp; sp = sp->link)
+ if(sp->chan == c){
+ s = smalloc(3+strlen(sp->name)+1);
+ sprint(s, "#s/%s", sp->name);
+ return s;
+ }
+ return nil;
+}
+
+static Chan*
+srvopen(Chan *c, int omode)
+{
+ Srv *sp;
+
+ if(c->qid.type == QTDIR){
+ if(omode & ORCLOSE)
+ error(Eperm);
+ if(omode != OREAD)
+ error(Eisdir);
+ c->mode = omode;
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+ }
+ qlock(&srvlk);
+ if(waserror()){
+ qunlock(&srvlk);
+ nexterror();
+ }
+
+ sp = srvlookup(nil, c->qid.path);
+ if(sp == 0 || sp->chan == 0)
+ error(Eshutdown);
+
+ if(omode&OTRUNC)
+ error("srv file already exists");
+ if(openmode(omode)!=sp->chan->mode && sp->chan->mode!=ORDWR)
+ error(Eperm);
+ devpermcheck(sp->owner, sp->perm, omode);
+
+ cclose(c);
+ incref(sp->chan);
+ qunlock(&srvlk);
+ poperror();
+ return sp->chan;
+}
+
+static void
+srvcreate(Chan *c, char *name, int omode, ulong perm)
+{
+ char *sname;
+ Srv *sp;
+
+ if(openmode(omode) != OWRITE)
+ error(Eperm);
+
+ if(omode & OCEXEC) /* can't happen */
+ panic("someone broke namec");
+
+ sp = smalloc(sizeof *sp);
+ sname = smalloc(strlen(name)+1);
+
+ qlock(&srvlk);
+ if(waserror()){
+ free(sp);
+ free(sname);
+ qunlock(&srvlk);
+ nexterror();
+ }
+ if(sp == nil || sname == nil)
+ error(Enomem);
+ if(srvlookup(name, -1))
+ error(Eexist);
+
+ sp->path = qidpath++;
+ sp->link = srv;
+ strcpy(sname, name);
+ sp->name = sname;
+ c->qid.type = QTFILE;
+ c->qid.path = sp->path;
+ srv = sp;
+ qunlock(&srvlk);
+ poperror();
+
+ kstrdup(&sp->owner, up->user);
+ sp->perm = perm&0777;
+
+ c->flag |= COPEN;
+ c->mode = OWRITE;
+}
+
+static void
+srvremove(Chan *c)
+{
+ Srv *sp, **l;
+
+ if(c->qid.type == QTDIR)
+ error(Eperm);
+
+ qlock(&srvlk);
+ if(waserror()){
+ qunlock(&srvlk);
+ nexterror();
+ }
+ l = &srv;
+ for(sp = *l; sp; sp = sp->link) {
+ if(sp->path == c->qid.path)
+ break;
+
+ l = &sp->link;
+ }
+ if(sp == 0)
+ error(Enonexist);
+
+ /*
+ * Only eve can remove system services.
+ * No one can remove #s/boot.
+ */
+ if(strcmp(sp->owner, eve) == 0 && !iseve())
+ error(Eperm);
+ if(strcmp(sp->name, "boot") == 0)
+ error(Eperm);
+
+ /*
+ * No removing personal services.
+ */
+ if((sp->perm&7) != 7 && strcmp(sp->owner, up->user) && !iseve())
+ error(Eperm);
+
+ *l = sp->link;
+ qunlock(&srvlk);
+ poperror();
+
+ if(sp->chan)
+ cclose(sp->chan);
+ free(sp->owner);
+ free(sp->name);
+ free(sp);
+}
+
+static int
+srvwstat(Chan *c, uchar *dp, int n)
+{
+ char *strs;
+ Dir d;
+ Srv *sp;
+
+ if(c->qid.type & QTDIR)
+ error(Eperm);
+
+ strs = nil;
+ qlock(&srvlk);
+ if(waserror()){
+ qunlock(&srvlk);
+ free(strs);
+ nexterror();
+ }
+
+ sp = srvlookup(nil, c->qid.path);
+ if(sp == 0)
+ error(Enonexist);
+
+ if(strcmp(sp->owner, up->user) != 0 && !iseve())
+ error(Eperm);
+
+ strs = smalloc(n);
+ n = convM2D(dp, n, &d, strs);
+ if(n == 0)
+ error(Eshortstat);
+ if(d.mode != ~0UL)
+ sp->perm = d.mode & 0777;
+ if(d.uid && *d.uid)
+ kstrdup(&sp->owner, d.uid);
+ if(d.name && *d.name && strcmp(sp->name, d.name) != 0) {
+ if(strchr(d.name, '/') != nil)
+ error(Ebadchar);
+ kstrdup(&sp->name, d.name);
+ }
+ qunlock(&srvlk);
+ free(strs);
+ poperror();
+ return n;
+}
+
+static void
+srvclose(Chan *c)
+{
+ /*
+ * in theory we need to override any changes in removability
+ * since open, but since all that's checked is the owner,
+ * which is immutable, all is well.
+ */
+ if(c->flag & CRCLOSE){
+ if(waserror())
+ return;
+ srvremove(c);
+ poperror();
+ }
+}
+
+static long
+srvread(Chan *c, void *va, long n, vlong)
+{
+ isdir(c);
+ return devdirread(c, va, n, 0, 0, srvgen);
+}
+
+static long
+srvwrite(Chan *c, void *va, long n, vlong)
+{
+ Srv *sp;
+ Chan *c1;
+ int fd;
+ char buf[32];
+
+ if(n >= sizeof buf)
+ error(Egreg);
+ memmove(buf, va, n); /* so we can NUL-terminate */
+ buf[n] = 0;
+ fd = strtoul(buf, 0, 0);
+
+ c1 = fdtochan(fd, -1, 0, 1); /* error check and inc ref */
+
+ qlock(&srvlk);
+ if(waserror()) {
+ qunlock(&srvlk);
+ cclose(c1);
+ nexterror();
+ }
+ if(c1->flag & (CCEXEC|CRCLOSE))
+ error("posted fd has remove-on-close or close-on-exec");
+ if(c1->qid.type & QTAUTH)
+ error("cannot post auth file in srv");
+ sp = srvlookup(nil, c->qid.path);
+ if(sp == 0)
+ error(Enonexist);
+
+ if(sp->chan)
+ error(Ebadusefd);
+
+ sp->chan = c1;
+ qunlock(&srvlk);
+ poperror();
+ return n;
+}
+
+Dev srvdevtab = {
+ 's',
+ "srv",
+
+ devreset,
+ srvinit,
+ devshutdown,
+ srvattach,
+ srvwalk,
+ srvstat,
+ srvopen,
+ srvcreate,
+ srvclose,
+ srvread,
+ devbread,
+ srvwrite,
+ devbwrite,
+ srvremove,
+ srvwstat,
+};
diff --git a/sys/src/9/port/devssl.c b/sys/src/9/port/devssl.c
new file mode 100755
index 000000000..25c2dd835
--- /dev/null
+++ b/sys/src/9/port/devssl.c
@@ -0,0 +1,1505 @@
+/*
+ * devssl - secure sockets layer
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include <libsec.h>
+
+#define NOSPOOKS 1
+
+typedef struct OneWay OneWay;
+struct OneWay
+{
+ QLock q;
+ QLock ctlq;
+
+ void *state; /* encryption state */
+ int slen; /* hash data length */
+ uchar *secret; /* secret */
+ ulong mid; /* message id */
+};
+
+enum
+{
+ /* connection states */
+ Sincomplete= 0,
+ Sclear= 1,
+ Sencrypting= 2,
+ Sdigesting= 4,
+ Sdigenc= Sencrypting|Sdigesting,
+
+ /* encryption algorithms */
+ Noencryption= 0,
+ DESCBC= 1,
+ DESECB= 2,
+ RC4= 3
+};
+
+typedef struct Dstate Dstate;
+struct Dstate
+{
+ Chan *c; /* io channel */
+ uchar state; /* state of connection */
+ int ref; /* serialized by dslock for atomic destroy */
+
+ uchar encryptalg; /* encryption algorithm */
+ ushort blocklen; /* blocking length */
+
+ ushort diglen; /* length of digest */
+ DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*); /* hash func */
+
+ /* for SSL format */
+ int max; /* maximum unpadded data per msg */
+ int maxpad; /* maximum padded data per msg */
+
+ /* input side */
+ OneWay in;
+ Block *processed;
+ Block *unprocessed;
+
+ /* output side */
+ OneWay out;
+
+ /* protections */
+ char *user;
+ int perm;
+};
+
+enum
+{
+ Maxdmsg= 1<<16,
+ Maxdstate= 512, /* max. open ssl conn's; must be a power of 2 */
+};
+
+static Lock dslock;
+static int dshiwat;
+static char *dsname[Maxdstate];
+static Dstate *dstate[Maxdstate];
+static char *encalgs;
+static char *hashalgs;
+
+enum{
+ Qtopdir = 1, /* top level directory */
+ Qprotodir,
+ Qclonus,
+ Qconvdir, /* directory for a conversation */
+ Qdata,
+ Qctl,
+ Qsecretin,
+ Qsecretout,
+ Qencalgs,
+ Qhashalgs,
+};
+
+#define TYPE(x) ((x).path & 0xf)
+#define CONV(x) (((x).path >> 5)&(Maxdstate-1))
+#define QID(c, y) (((c)<<5) | (y))
+
+static void ensure(Dstate*, Block**, int);
+static void consume(Block**, uchar*, int);
+static void setsecret(OneWay*, uchar*, int);
+static Block* encryptb(Dstate*, Block*, int);
+static Block* decryptb(Dstate*, Block*);
+static Block* digestb(Dstate*, Block*, int);
+static void checkdigestb(Dstate*, Block*);
+static Chan* buftochan(char*);
+static void sslhangup(Dstate*);
+static Dstate* dsclone(Chan *c);
+static void dsnew(Chan *c, Dstate **);
+static long sslput(Dstate *s, Block * volatile b);
+
+char *sslnames[] = {
+[Qclonus] "clone",
+[Qdata] "data",
+[Qctl] "ctl",
+[Qsecretin] "secretin",
+[Qsecretout] "secretout",
+[Qencalgs] "encalgs",
+[Qhashalgs] "hashalgs",
+};
+
+static int
+sslgen(Chan *c, char*, Dirtab *d, int nd, int s, Dir *dp)
+{
+ Qid q;
+ Dstate *ds;
+ char name[16], *p, *nm;
+ int ft;
+
+ USED(nd);
+ USED(d);
+
+ q.type = QTFILE;
+ q.vers = 0;
+
+ ft = TYPE(c->qid);
+ switch(ft) {
+ case Qtopdir:
+ if(s == DEVDOTDOT){
+ q.path = QID(0, Qtopdir);
+ q.type = QTDIR;
+ devdir(c, q, "#D", 0, eve, 0555, dp);
+ return 1;
+ }
+ if(s > 0)
+ return -1;
+ q.path = QID(0, Qprotodir);
+ q.type = QTDIR;
+ devdir(c, q, "ssl", 0, eve, 0555, dp);
+ return 1;
+ case Qprotodir:
+ if(s == DEVDOTDOT){
+ q.path = QID(0, Qtopdir);
+ q.type = QTDIR;
+ devdir(c, q, ".", 0, eve, 0555, dp);
+ return 1;
+ }
+ if(s < dshiwat) {
+ q.path = QID(s, Qconvdir);
+ q.type = QTDIR;
+ ds = dstate[s];
+ if(ds != 0)
+ nm = ds->user;
+ else
+ nm = eve;
+ if(dsname[s] == nil){
+ sprint(name, "%d", s);
+ kstrdup(&dsname[s], name);
+ }
+ devdir(c, q, dsname[s], 0, nm, 0555, dp);
+ return 1;
+ }
+ if(s > dshiwat)
+ return -1;
+ q.path = QID(0, Qclonus);
+ devdir(c, q, "clone", 0, eve, 0555, dp);
+ return 1;
+ case Qconvdir:
+ if(s == DEVDOTDOT){
+ q.path = QID(0, Qprotodir);
+ q.type = QTDIR;
+ devdir(c, q, "ssl", 0, eve, 0555, dp);
+ return 1;
+ }
+ ds = dstate[CONV(c->qid)];
+ if(ds != 0)
+ nm = ds->user;
+ else
+ nm = eve;
+ switch(s) {
+ default:
+ return -1;
+ case 0:
+ q.path = QID(CONV(c->qid), Qctl);
+ p = "ctl";
+ break;
+ case 1:
+ q.path = QID(CONV(c->qid), Qdata);
+ p = "data";
+ break;
+ case 2:
+ q.path = QID(CONV(c->qid), Qsecretin);
+ p = "secretin";
+ break;
+ case 3:
+ q.path = QID(CONV(c->qid), Qsecretout);
+ p = "secretout";
+ break;
+ case 4:
+ q.path = QID(CONV(c->qid), Qencalgs);
+ p = "encalgs";
+ break;
+ case 5:
+ q.path = QID(CONV(c->qid), Qhashalgs);
+ p = "hashalgs";
+ break;
+ }
+ devdir(c, q, p, 0, nm, 0660, dp);
+ return 1;
+ case Qclonus:
+ devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, eve, 0555, dp);
+ return 1;
+ default:
+ ds = dstate[CONV(c->qid)];
+ if(ds != 0)
+ nm = ds->user;
+ else
+ nm = eve;
+ devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, nm, 0660, dp);
+ return 1;
+ }
+}
+
+static Chan*
+sslattach(char *spec)
+{
+ Chan *c;
+
+ c = devattach('D', spec);
+ c->qid.path = QID(0, Qtopdir);
+ c->qid.vers = 0;
+ c->qid.type = QTDIR;
+ return c;
+}
+
+static Walkqid*
+sslwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, nil, 0, sslgen);
+}
+
+static int
+sslstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, nil, 0, sslgen);
+}
+
+static Chan*
+sslopen(Chan *c, int omode)
+{
+ Dstate *s, **pp;
+ int perm;
+ int ft;
+
+ perm = 0;
+ omode &= 3;
+ switch(omode) {
+ case OREAD:
+ perm = 4;
+ break;
+ case OWRITE:
+ perm = 2;
+ break;
+ case ORDWR:
+ perm = 6;
+ break;
+ }
+
+ ft = TYPE(c->qid);
+ switch(ft) {
+ default:
+ panic("sslopen");
+ case Qtopdir:
+ case Qprotodir:
+ case Qconvdir:
+ if(omode != OREAD)
+ error(Eperm);
+ break;
+ case Qclonus:
+ s = dsclone(c);
+ if(s == 0)
+ error(Enodev);
+ break;
+ case Qctl:
+ case Qdata:
+ case Qsecretin:
+ case Qsecretout:
+ if(waserror()) {
+ unlock(&dslock);
+ nexterror();
+ }
+ lock(&dslock);
+ pp = &dstate[CONV(c->qid)];
+ s = *pp;
+ if(s == 0)
+ dsnew(c, pp);
+ else {
+ if((perm & (s->perm>>6)) != perm
+ && (strcmp(up->user, s->user) != 0
+ || (perm & s->perm) != perm))
+ error(Eperm);
+
+ s->ref++;
+ }
+ unlock(&dslock);
+ poperror();
+ break;
+ case Qencalgs:
+ case Qhashalgs:
+ if(omode != OREAD)
+ error(Eperm);
+ break;
+ }
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+static int
+sslwstat(Chan *c, uchar *db, int n)
+{
+ Dir *dir;
+ Dstate *s;
+ int m;
+
+ s = dstate[CONV(c->qid)];
+ if(s == 0)
+ error(Ebadusefd);
+ if(strcmp(s->user, up->user) != 0)
+ error(Eperm);
+
+ dir = smalloc(sizeof(Dir)+n);
+ m = convM2D(db, n, &dir[0], (char*)&dir[1]);
+ if(m == 0){
+ free(dir);
+ error(Eshortstat);
+ }
+
+ if(!emptystr(dir->uid))
+ kstrdup(&s->user, dir->uid);
+ if(dir->mode != ~0UL)
+ s->perm = dir->mode;
+
+ free(dir);
+ return m;
+}
+
+static void
+sslclose(Chan *c)
+{
+ Dstate *s;
+ int ft;
+
+ ft = TYPE(c->qid);
+ switch(ft) {
+ case Qctl:
+ case Qdata:
+ case Qsecretin:
+ case Qsecretout:
+ if((c->flag & COPEN) == 0)
+ break;
+
+ s = dstate[CONV(c->qid)];
+ if(s == 0)
+ break;
+
+ lock(&dslock);
+ if(--s->ref > 0) {
+ unlock(&dslock);
+ break;
+ }
+ dstate[CONV(c->qid)] = 0;
+ unlock(&dslock);
+
+ if(s->user != nil)
+ free(s->user);
+ sslhangup(s);
+ if(s->c)
+ cclose(s->c);
+ if(s->in.secret)
+ free(s->in.secret);
+ if(s->out.secret)
+ free(s->out.secret);
+ if(s->in.state)
+ free(s->in.state);
+ if(s->out.state)
+ free(s->out.state);
+ free(s);
+
+ }
+}
+
+/*
+ * make sure we have at least 'n' bytes in list 'l'
+ */
+static void
+ensure(Dstate *s, Block **l, int n)
+{
+ int sofar, i;
+ Block *b, *bl;
+
+ sofar = 0;
+ for(b = *l; b; b = b->next){
+ sofar += BLEN(b);
+ if(sofar >= n)
+ return;
+ l = &b->next;
+ }
+
+ while(sofar < n){
+ bl = devtab[s->c->type]->bread(s->c, Maxdmsg, 0);
+ if(bl == 0)
+ nexterror();
+ *l = bl;
+ i = 0;
+ for(b = bl; b; b = b->next){
+ i += BLEN(b);
+ l = &b->next;
+ }
+ if(i == 0)
+ error(Ehungup);
+ sofar += i;
+ }
+}
+
+/*
+ * copy 'n' bytes from 'l' into 'p' and free
+ * the bytes in 'l'
+ */
+static void
+consume(Block **l, uchar *p, int n)
+{
+ Block *b;
+ int i;
+
+ for(; *l && n > 0; n -= i){
+ b = *l;
+ i = BLEN(b);
+ if(i > n)
+ i = n;
+ memmove(p, b->rp, i);
+ b->rp += i;
+ p += i;
+ if(BLEN(b) < 0)
+ panic("consume");
+ if(BLEN(b))
+ break;
+ *l = b->next;
+ freeb(b);
+ }
+}
+
+/*
+ * give back n bytes
+static void
+regurgitate(Dstate *s, uchar *p, int n)
+{
+ Block *b;
+
+ if(n <= 0)
+ return;
+ b = s->unprocessed;
+ if(s->unprocessed == nil || b->rp - b->base < n) {
+ b = allocb(n);
+ memmove(b->wp, p, n);
+ b->wp += n;
+ b->next = s->unprocessed;
+ s->unprocessed = b;
+ } else {
+ b->rp -= n;
+ memmove(b->rp, p, n);
+ }
+}
+ */
+
+/*
+ * remove at most n bytes from the queue, if discard is set
+ * dump the remainder
+ */
+static Block*
+qtake(Block **l, int n, int discard)
+{
+ Block *nb, *b, *first;
+ int i;
+
+ first = *l;
+ for(b = first; b; b = b->next){
+ i = BLEN(b);
+ if(i == n){
+ if(discard){
+ freeblist(b->next);
+ *l = 0;
+ } else
+ *l = b->next;
+ b->next = 0;
+ return first;
+ } else if(i > n){
+ i -= n;
+ if(discard){
+ freeblist(b->next);
+ b->wp -= i;
+ *l = 0;
+ } else {
+ nb = allocb(i);
+ memmove(nb->wp, b->rp+n, i);
+ nb->wp += i;
+ b->wp -= i;
+ nb->next = b->next;
+ *l = nb;
+ }
+ b->next = 0;
+ if(BLEN(b) < 0)
+ panic("qtake");
+ return first;
+ } else
+ n -= i;
+ if(BLEN(b) < 0)
+ panic("qtake");
+ }
+ *l = 0;
+ return first;
+}
+
+/*
+ * We can't let Eintr's lose data since the program
+ * doing the read may be able to handle it. The only
+ * places Eintr is possible is during the read's in consume.
+ * Therefore, we make sure we can always put back the bytes
+ * consumed before the last ensure.
+ */
+static Block*
+sslbread(Chan *c, long n, ulong)
+{
+ Dstate * volatile s;
+ Block *b;
+ uchar consumed[3], *p;
+ int toconsume;
+ int len, pad;
+
+ s = dstate[CONV(c->qid)];
+ if(s == 0)
+ panic("sslbread");
+ if(s->state == Sincomplete)
+ error(Ebadusefd);
+
+ qlock(&s->in.q);
+ if(waserror()){
+ qunlock(&s->in.q);
+ nexterror();
+ }
+
+ if(s->processed == 0){
+ /*
+ * Read in the whole message. Until we've got it all,
+ * it stays on s->unprocessed, so that if we get Eintr,
+ * we'll pick up where we left off.
+ */
+ ensure(s, &s->unprocessed, 3);
+ s->unprocessed = pullupblock(s->unprocessed, 2);
+ p = s->unprocessed->rp;
+ if(p[0] & 0x80){
+ len = ((p[0] & 0x7f)<<8) | p[1];
+ ensure(s, &s->unprocessed, len);
+ pad = 0;
+ toconsume = 2;
+ } else {
+ s->unprocessed = pullupblock(s->unprocessed, 3);
+ len = ((p[0] & 0x3f)<<8) | p[1];
+ pad = p[2];
+ if(pad > len){
+ print("pad %d buf len %d\n", pad, len);
+ error("bad pad in ssl message");
+ }
+ toconsume = 3;
+ }
+ ensure(s, &s->unprocessed, toconsume+len);
+
+ /* skip header */
+ consume(&s->unprocessed, consumed, toconsume);
+
+ /* grab the next message and decode/decrypt it */
+ b = qtake(&s->unprocessed, len, 0);
+
+ if(blocklen(b) != len)
+ print("devssl: sslbread got wrong count %d != %d", blocklen(b), len);
+
+ if(waserror()){
+ qunlock(&s->in.ctlq);
+ if(b != nil)
+ freeb(b);
+ nexterror();
+ }
+ qlock(&s->in.ctlq);
+ switch(s->state){
+ case Sencrypting:
+ if(b == nil)
+ error("ssl message too short (encrypting)");
+ b = decryptb(s, b);
+ break;
+ case Sdigesting:
+ b = pullupblock(b, s->diglen);
+ if(b == nil)
+ error("ssl message too short (digesting)");
+ checkdigestb(s, b);
+ pullblock(&b, s->diglen);
+ len -= s->diglen;
+ break;
+ case Sdigenc:
+ b = decryptb(s, b);
+ b = pullupblock(b, s->diglen);
+ if(b == nil)
+ error("ssl message too short (dig+enc)");
+ checkdigestb(s, b);
+ pullblock(&b, s->diglen);
+ len -= s->diglen;
+ break;
+ }
+
+ /* remove pad */
+ if(pad)
+ s->processed = qtake(&b, len - pad, 1);
+ else
+ s->processed = b;
+ b = nil;
+ s->in.mid++;
+ qunlock(&s->in.ctlq);
+ poperror();
+ }
+
+ /* return at most what was asked for */
+ b = qtake(&s->processed, n, 0);
+
+ qunlock(&s->in.q);
+ poperror();
+
+ return b;
+}
+
+static long
+sslread(Chan *c, void *a, long n, vlong off)
+{
+ Block * volatile b;
+ Block *nb;
+ uchar *va;
+ int i;
+ char buf[128];
+ ulong offset = off;
+ int ft;
+
+ if(c->qid.type & QTDIR)
+ return devdirread(c, a, n, 0, 0, sslgen);
+
+ ft = TYPE(c->qid);
+ switch(ft) {
+ default:
+ error(Ebadusefd);
+ case Qctl:
+ ft = CONV(c->qid);
+ sprint(buf, "%d", ft);
+ return readstr(offset, a, n, buf);
+ case Qdata:
+ b = sslbread(c, n, offset);
+ break;
+ case Qencalgs:
+ return readstr(offset, a, n, encalgs);
+ break;
+ case Qhashalgs:
+ return readstr(offset, a, n, hashalgs);
+ break;
+ }
+
+ if(waserror()){
+ freeblist(b);
+ nexterror();
+ }
+
+ n = 0;
+ va = a;
+ for(nb = b; nb; nb = nb->next){
+ i = BLEN(nb);
+ memmove(va+n, nb->rp, i);
+ n += i;
+ }
+
+ freeblist(b);
+ poperror();
+
+ return n;
+}
+
+/*
+ * this algorithm doesn't have to be great since we're just
+ * trying to obscure the block fill
+ */
+static void
+randfill(uchar *buf, int len)
+{
+ while(len-- > 0)
+ *buf++ = nrand(256);
+}
+
+static long
+sslbwrite(Chan *c, Block *b, ulong)
+{
+ Dstate * volatile s;
+ long rv;
+
+ s = dstate[CONV(c->qid)];
+ if(s == nil)
+ panic("sslbwrite");
+
+ if(s->state == Sincomplete){
+ freeb(b);
+ error(Ebadusefd);
+ }
+
+ /* lock so split writes won't interleave */
+ if(waserror()){
+ qunlock(&s->out.q);
+ nexterror();
+ }
+ qlock(&s->out.q);
+
+ rv = sslput(s, b);
+
+ poperror();
+ qunlock(&s->out.q);
+
+ return rv;
+}
+
+/*
+ * use SSL record format, add in count, digest and/or encrypt.
+ * the write is interruptable. if it is interrupted, we'll
+ * get out of sync with the far side. not much we can do about
+ * it since we don't know if any bytes have been written.
+ */
+static long
+sslput(Dstate *s, Block * volatile b)
+{
+ Block *nb;
+ int h, n, m, pad, rv;
+ uchar *p;
+ int offset;
+
+ if(waserror()){
+ if(b != nil)
+ free(b);
+ nexterror();
+ }
+
+ rv = 0;
+ while(b != nil){
+ m = n = BLEN(b);
+ h = s->diglen + 2;
+
+ /* trim to maximum block size */
+ pad = 0;
+ if(m > s->max){
+ m = s->max;
+ } else if(s->blocklen != 1){
+ pad = (m + s->diglen)%s->blocklen;
+ if(pad){
+ if(m > s->maxpad){
+ pad = 0;
+ m = s->maxpad;
+ } else {
+ pad = s->blocklen - pad;
+ h++;
+ }
+ }
+ }
+
+ rv += m;
+ if(m != n){
+ nb = allocb(m + h + pad);
+ memmove(nb->wp + h, b->rp, m);
+ nb->wp += m + h;
+ b->rp += m;
+ } else {
+ /* add header space */
+ nb = padblock(b, h);
+ b = 0;
+ }
+ m += s->diglen;
+
+ /* SSL style count */
+ if(pad){
+ nb = padblock(nb, -pad);
+ randfill(nb->wp, pad);
+ nb->wp += pad;
+ m += pad;
+
+ p = nb->rp;
+ p[0] = (m>>8);
+ p[1] = m;
+ p[2] = pad;
+ offset = 3;
+ } else {
+ p = nb->rp;
+ p[0] = (m>>8) | 0x80;
+ p[1] = m;
+ offset = 2;
+ }
+
+ switch(s->state){
+ case Sencrypting:
+ nb = encryptb(s, nb, offset);
+ break;
+ case Sdigesting:
+ nb = digestb(s, nb, offset);
+ break;
+ case Sdigenc:
+ nb = digestb(s, nb, offset);
+ nb = encryptb(s, nb, offset);
+ break;
+ }
+
+ s->out.mid++;
+
+ m = BLEN(nb);
+ devtab[s->c->type]->bwrite(s->c, nb, s->c->offset);
+ s->c->offset += m;
+ }
+
+ poperror();
+ return rv;
+}
+
+static void
+setsecret(OneWay *w, uchar *secret, int n)
+{
+ if(w->secret)
+ free(w->secret);
+
+ w->secret = smalloc(n);
+ memmove(w->secret, secret, n);
+ w->slen = n;
+}
+
+static void
+initDESkey(OneWay *w)
+{
+ if(w->state){
+ free(w->state);
+ w->state = 0;
+ }
+
+ w->state = smalloc(sizeof(DESstate));
+ if(w->slen >= 16)
+ setupDESstate(w->state, w->secret, w->secret+8);
+ else if(w->slen >= 8)
+ setupDESstate(w->state, w->secret, 0);
+ else
+ error("secret too short");
+}
+
+/*
+ * 40 bit DES is the same as 56 bit DES. However,
+ * 16 bits of the key are masked to zero.
+ */
+static void
+initDESkey_40(OneWay *w)
+{
+ uchar key[8];
+
+ if(w->state){
+ free(w->state);
+ w->state = 0;
+ }
+
+ if(w->slen >= 8){
+ memmove(key, w->secret, 8);
+ key[0] &= 0x0f;
+ key[2] &= 0x0f;
+ key[4] &= 0x0f;
+ key[6] &= 0x0f;
+ }
+
+ w->state = malloc(sizeof(DESstate));
+ if(w->slen >= 16)
+ setupDESstate(w->state, key, w->secret+8);
+ else if(w->slen >= 8)
+ setupDESstate(w->state, key, 0);
+ else
+ error("secret too short");
+}
+
+static void
+initRC4key(OneWay *w)
+{
+ if(w->state){
+ free(w->state);
+ w->state = 0;
+ }
+
+ w->state = smalloc(sizeof(RC4state));
+ setupRC4state(w->state, w->secret, w->slen);
+}
+
+/*
+ * 40 bit RC4 is the same as n-bit RC4. However,
+ * we ignore all but the first 40 bits of the key.
+ */
+static void
+initRC4key_40(OneWay *w)
+{
+ if(w->state){
+ free(w->state);
+ w->state = 0;
+ }
+
+ if(w->slen > 5)
+ w->slen = 5;
+
+ w->state = malloc(sizeof(RC4state));
+ setupRC4state(w->state, w->secret, w->slen);
+}
+
+/*
+ * 128 bit RC4 is the same as n-bit RC4. However,
+ * we ignore all but the first 128 bits of the key.
+ */
+static void
+initRC4key_128(OneWay *w)
+{
+ if(w->state){
+ free(w->state);
+ w->state = 0;
+ }
+
+ if(w->slen > 16)
+ w->slen = 16;
+
+ w->state = malloc(sizeof(RC4state));
+ setupRC4state(w->state, w->secret, w->slen);
+}
+
+
+typedef struct Hashalg Hashalg;
+struct Hashalg
+{
+ char *name;
+ int diglen;
+ DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*);
+};
+
+Hashalg hashtab[] =
+{
+ { "md4", MD4dlen, md4, },
+ { "md5", MD5dlen, md5, },
+ { "sha1", SHA1dlen, sha1, },
+ { "sha", SHA1dlen, sha1, },
+ { 0 }
+};
+
+static int
+parsehashalg(char *p, Dstate *s)
+{
+ Hashalg *ha;
+
+ for(ha = hashtab; ha->name; ha++){
+ if(strcmp(p, ha->name) == 0){
+ s->hf = ha->hf;
+ s->diglen = ha->diglen;
+ s->state &= ~Sclear;
+ s->state |= Sdigesting;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+typedef struct Encalg Encalg;
+struct Encalg
+{
+ char *name;
+ int blocklen;
+ int alg;
+ void (*keyinit)(OneWay*);
+};
+
+#ifdef NOSPOOKS
+Encalg encrypttab[] =
+{
+ { "descbc", 8, DESCBC, initDESkey, }, /* DEPRECATED -- use des_56_cbc */
+ { "desecb", 8, DESECB, initDESkey, }, /* DEPRECATED -- use des_56_ecb */
+ { "des_56_cbc", 8, DESCBC, initDESkey, },
+ { "des_56_ecb", 8, DESECB, initDESkey, },
+ { "des_40_cbc", 8, DESCBC, initDESkey_40, },
+ { "des_40_ecb", 8, DESECB, initDESkey_40, },
+ { "rc4", 1, RC4, initRC4key_40, }, /* DEPRECATED -- use rc4_X */
+ { "rc4_256", 1, RC4, initRC4key, },
+ { "rc4_128", 1, RC4, initRC4key_128, },
+ { "rc4_40", 1, RC4, initRC4key_40, },
+ { 0 }
+};
+#else
+Encalg encrypttab[] =
+{
+ { "des_40_cbc", 8, DESCBC, initDESkey_40, },
+ { "des_40_ecb", 8, DESECB, initDESkey_40, },
+ { "rc4", 1, RC4, initRC4key_40, }, /* DEPRECATED -- use rc4_X */
+ { "rc4_40", 1, RC4, initRC4key_40, },
+ { 0 }
+};
+#endif NOSPOOKS
+
+static int
+parseencryptalg(char *p, Dstate *s)
+{
+ Encalg *ea;
+
+ for(ea = encrypttab; ea->name; ea++){
+ if(strcmp(p, ea->name) == 0){
+ s->encryptalg = ea->alg;
+ s->blocklen = ea->blocklen;
+ (*ea->keyinit)(&s->in);
+ (*ea->keyinit)(&s->out);
+ s->state &= ~Sclear;
+ s->state |= Sencrypting;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static long
+sslwrite(Chan *c, void *a, long n, vlong)
+{
+ Dstate * volatile s;
+ Block * volatile b;
+ int m, t;
+ char *p, *np, *e, buf[128];
+ uchar *x;
+
+ s = dstate[CONV(c->qid)];
+ if(s == 0)
+ panic("sslwrite");
+
+ t = TYPE(c->qid);
+ if(t == Qdata){
+ if(s->state == Sincomplete)
+ error(Ebadusefd);
+
+ /* lock should a write gets split over multiple records */
+ if(waserror()){
+ qunlock(&s->out.q);
+ nexterror();
+ }
+ qlock(&s->out.q);
+
+ p = a;
+ e = p + n;
+ do {
+ m = e - p;
+ if(m > s->max)
+ m = s->max;
+
+ b = allocb(m);
+ if(waserror()){
+ freeb(b);
+ nexterror();
+ }
+ memmove(b->wp, p, m);
+ poperror();
+ b->wp += m;
+
+ sslput(s, b);
+
+ p += m;
+ } while(p < e);
+
+ poperror();
+ qunlock(&s->out.q);
+ return n;
+ }
+
+ /* mutex with operations using what we're about to change */
+ if(waserror()){
+ qunlock(&s->in.ctlq);
+ qunlock(&s->out.q);
+ nexterror();
+ }
+ qlock(&s->in.ctlq);
+ qlock(&s->out.q);
+
+ switch(t){
+ default:
+ panic("sslwrite");
+ case Qsecretin:
+ setsecret(&s->in, a, n);
+ goto out;
+ case Qsecretout:
+ setsecret(&s->out, a, n);
+ goto out;
+ case Qctl:
+ break;
+ }
+
+ if(n >= sizeof(buf))
+ error("arg too long");
+ strncpy(buf, a, n);
+ buf[n] = 0;
+ p = strchr(buf, '\n');
+ if(p)
+ *p = 0;
+ p = strchr(buf, ' ');
+ if(p)
+ *p++ = 0;
+
+ if(strcmp(buf, "fd") == 0){
+ s->c = buftochan(p);
+
+ /* default is clear (msg delimiters only) */
+ s->state = Sclear;
+ s->blocklen = 1;
+ s->diglen = 0;
+ s->maxpad = s->max = (1<<15) - s->diglen - 1;
+ s->in.mid = 0;
+ s->out.mid = 0;
+ } else if(strcmp(buf, "alg") == 0 && p != 0){
+ s->blocklen = 1;
+ s->diglen = 0;
+
+ if(s->c == 0)
+ error("must set fd before algorithm");
+
+ s->state = Sclear;
+ s->maxpad = s->max = (1<<15) - s->diglen - 1;
+ if(strcmp(p, "clear") == 0){
+ goto out;
+ }
+
+ if(s->in.secret && s->out.secret == 0)
+ setsecret(&s->out, s->in.secret, s->in.slen);
+ if(s->out.secret && s->in.secret == 0)
+ setsecret(&s->in, s->out.secret, s->out.slen);
+ if(s->in.secret == 0 || s->out.secret == 0)
+ error("algorithm but no secret");
+
+ s->hf = 0;
+ s->encryptalg = Noencryption;
+ s->blocklen = 1;
+
+ for(;;){
+ np = strchr(p, ' ');
+ if(np)
+ *np++ = 0;
+
+ if(parsehashalg(p, s) < 0)
+ if(parseencryptalg(p, s) < 0)
+ error("bad algorithm");
+
+ if(np == 0)
+ break;
+ p = np;
+ }
+
+ if(s->hf == 0 && s->encryptalg == Noencryption)
+ error("bad algorithm");
+
+ if(s->blocklen != 1){
+ s->max = (1<<15) - s->diglen - 1;
+ s->max -= s->max % s->blocklen;
+ s->maxpad = (1<<14) - s->diglen - 1;
+ s->maxpad -= s->maxpad % s->blocklen;
+ } else
+ s->maxpad = s->max = (1<<15) - s->diglen - 1;
+ } else if(strcmp(buf, "secretin") == 0 && p != 0) {
+ m = (strlen(p)*3)/2;
+ x = smalloc(m);
+ t = dec64(x, m, p, strlen(p));
+ setsecret(&s->in, x, t);
+ free(x);
+ } else if(strcmp(buf, "secretout") == 0 && p != 0) {
+ m = (strlen(p)*3)/2 + 1;
+ x = smalloc(m);
+ t = dec64(x, m, p, strlen(p));
+ setsecret(&s->out, x, t);
+ free(x);
+ } else
+ error(Ebadarg);
+
+out:
+ qunlock(&s->in.ctlq);
+ qunlock(&s->out.q);
+ poperror();
+ return n;
+}
+
+static void
+sslinit(void)
+{
+ struct Encalg *e;
+ struct Hashalg *h;
+ int n;
+ char *cp;
+
+ n = 1;
+ for(e = encrypttab; e->name != nil; e++)
+ n += strlen(e->name) + 1;
+ cp = encalgs = smalloc(n);
+ for(e = encrypttab;;){
+ strcpy(cp, e->name);
+ cp += strlen(e->name);
+ e++;
+ if(e->name == nil)
+ break;
+ *cp++ = ' ';
+ }
+ *cp = 0;
+
+ n = 1;
+ for(h = hashtab; h->name != nil; h++)
+ n += strlen(h->name) + 1;
+ cp = hashalgs = smalloc(n);
+ for(h = hashtab;;){
+ strcpy(cp, h->name);
+ cp += strlen(h->name);
+ h++;
+ if(h->name == nil)
+ break;
+ *cp++ = ' ';
+ }
+ *cp = 0;
+}
+
+Dev ssldevtab = {
+ 'D',
+ "ssl",
+
+ devreset,
+ sslinit,
+ devshutdown,
+ sslattach,
+ sslwalk,
+ sslstat,
+ sslopen,
+ devcreate,
+ sslclose,
+ sslread,
+ sslbread,
+ sslwrite,
+ sslbwrite,
+ devremove,
+ sslwstat,
+};
+
+static Block*
+encryptb(Dstate *s, Block *b, int offset)
+{
+ uchar *p, *ep, *p2, *ip, *eip;
+ DESstate *ds;
+
+ switch(s->encryptalg){
+ case DESECB:
+ ds = s->out.state;
+ ep = b->rp + BLEN(b);
+ for(p = b->rp + offset; p < ep; p += 8)
+ block_cipher(ds->expanded, p, 0);
+ break;
+ case DESCBC:
+ ds = s->out.state;
+ ep = b->rp + BLEN(b);
+ for(p = b->rp + offset; p < ep; p += 8){
+ p2 = p;
+ ip = ds->ivec;
+ for(eip = ip+8; ip < eip; )
+ *p2++ ^= *ip++;
+ block_cipher(ds->expanded, p, 0);
+ memmove(ds->ivec, p, 8);
+ }
+ break;
+ case RC4:
+ rc4(s->out.state, b->rp + offset, BLEN(b) - offset);
+ break;
+ }
+ return b;
+}
+
+static Block*
+decryptb(Dstate *s, Block *bin)
+{
+ Block *b, **l;
+ uchar *p, *ep, *tp, *ip, *eip;
+ DESstate *ds;
+ uchar tmp[8];
+ int i;
+
+ l = &bin;
+ for(b = bin; b; b = b->next){
+ /* make sure we have a multiple of s->blocklen */
+ if(s->blocklen > 1){
+ i = BLEN(b);
+ if(i % s->blocklen){
+ *l = b = pullupblock(b, i + s->blocklen - (i%s->blocklen));
+ if(b == 0)
+ error("ssl encrypted message too short");
+ }
+ }
+ l = &b->next;
+
+ /* decrypt */
+ switch(s->encryptalg){
+ case DESECB:
+ ds = s->in.state;
+ ep = b->rp + BLEN(b);
+ for(p = b->rp; p < ep; p += 8)
+ block_cipher(ds->expanded, p, 1);
+ break;
+ case DESCBC:
+ ds = s->in.state;
+ ep = b->rp + BLEN(b);
+ for(p = b->rp; p < ep;){
+ memmove(tmp, p, 8);
+ block_cipher(ds->expanded, p, 1);
+ tp = tmp;
+ ip = ds->ivec;
+ for(eip = ip+8; ip < eip; ){
+ *p++ ^= *ip;
+ *ip++ = *tp++;
+ }
+ }
+ break;
+ case RC4:
+ rc4(s->in.state, b->rp, BLEN(b));
+ break;
+ }
+ }
+ return bin;
+}
+
+static Block*
+digestb(Dstate *s, Block *b, int offset)
+{
+ uchar *p;
+ DigestState ss;
+ uchar msgid[4];
+ ulong n, h;
+ OneWay *w;
+
+ w = &s->out;
+
+ memset(&ss, 0, sizeof(ss));
+ h = s->diglen + offset;
+ n = BLEN(b) - h;
+
+ /* hash secret + message */
+ (*s->hf)(w->secret, w->slen, 0, &ss);
+ (*s->hf)(b->rp + h, n, 0, &ss);
+
+ /* hash message id */
+ p = msgid;
+ n = w->mid;
+ *p++ = n>>24;
+ *p++ = n>>16;
+ *p++ = n>>8;
+ *p = n;
+ (*s->hf)(msgid, 4, b->rp + offset, &ss);
+
+ return b;
+}
+
+static void
+checkdigestb(Dstate *s, Block *bin)
+{
+ uchar *p;
+ DigestState ss;
+ uchar msgid[4];
+ int n, h;
+ OneWay *w;
+ uchar digest[128];
+ Block *b;
+
+ w = &s->in;
+
+ memset(&ss, 0, sizeof(ss));
+
+ /* hash secret */
+ (*s->hf)(w->secret, w->slen, 0, &ss);
+
+ /* hash message */
+ h = s->diglen;
+ for(b = bin; b; b = b->next){
+ n = BLEN(b) - h;
+ if(n < 0)
+ panic("checkdigestb");
+ (*s->hf)(b->rp + h, n, 0, &ss);
+ h = 0;
+ }
+
+ /* hash message id */
+ p = msgid;
+ n = w->mid;
+ *p++ = n>>24;
+ *p++ = n>>16;
+ *p++ = n>>8;
+ *p = n;
+ (*s->hf)(msgid, 4, digest, &ss);
+
+ if(memcmp(digest, bin->rp, s->diglen) != 0)
+ error("bad digest");
+}
+
+/* get channel associated with an fd */
+static Chan*
+buftochan(char *p)
+{
+ Chan *c;
+ int fd;
+
+ if(p == 0)
+ error(Ebadarg);
+ fd = strtoul(p, 0, 0);
+ if(fd < 0)
+ error(Ebadarg);
+ c = fdtochan(fd, -1, 0, 1); /* error check and inc ref */
+ if(devtab[c->type] == &ssldevtab){
+ cclose(c);
+ error("cannot ssl encrypt devssl files");
+ }
+ return c;
+}
+
+/* hand up a digest connection */
+static void
+sslhangup(Dstate *s)
+{
+ Block *b;
+
+ qlock(&s->in.q);
+ for(b = s->processed; b; b = s->processed){
+ s->processed = b->next;
+ freeb(b);
+ }
+ if(s->unprocessed){
+ freeb(s->unprocessed);
+ s->unprocessed = 0;
+ }
+ s->state = Sincomplete;
+ qunlock(&s->in.q);
+}
+
+static Dstate*
+dsclone(Chan *ch)
+{
+ int i;
+ Dstate *ret;
+
+ if(waserror()) {
+ unlock(&dslock);
+ nexterror();
+ }
+ lock(&dslock);
+ ret = nil;
+ for(i=0; i<Maxdstate; i++){
+ if(dstate[i] == nil){
+ dsnew(ch, &dstate[i]);
+ ret = dstate[i];
+ break;
+ }
+ }
+ unlock(&dslock);
+ poperror();
+ return ret;
+}
+
+static void
+dsnew(Chan *ch, Dstate **pp)
+{
+ Dstate *s;
+ int t;
+
+ *pp = s = malloc(sizeof(*s));
+ if(!s)
+ error(Enomem);
+ if(pp - dstate >= dshiwat)
+ dshiwat++;
+ memset(s, 0, sizeof(*s));
+ s->state = Sincomplete;
+ s->ref = 1;
+ kstrdup(&s->user, up->user);
+ s->perm = 0660;
+ t = TYPE(ch->qid);
+ if(t == Qclonus)
+ t = Qctl;
+ ch->qid.path = QID(pp - dstate, t);
+ ch->qid.vers = 0;
+}
diff --git a/sys/src/9/port/devtls.c b/sys/src/9/port/devtls.c
new file mode 100755
index 000000000..7a5e1da53
--- /dev/null
+++ b/sys/src/9/port/devtls.c
@@ -0,0 +1,2180 @@
+/*
+ * devtls - record layer for transport layer security 1.0 and secure sockets layer 3.0
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include <libsec.h>
+
+typedef struct OneWay OneWay;
+typedef struct Secret Secret;
+typedef struct TlsRec TlsRec;
+typedef struct TlsErrs TlsErrs;
+
+enum {
+ Statlen= 1024, /* max. length of status or stats message */
+ /* buffer limits */
+ MaxRecLen = 1<<14, /* max payload length of a record layer message */
+ MaxCipherRecLen = MaxRecLen + 2048,
+ RecHdrLen = 5,
+ MaxMacLen = SHA1dlen,
+
+ /* protocol versions we can accept */
+ TLSVersion = 0x0301,
+ SSL3Version = 0x0300,
+ ProtocolVersion = 0x0301, /* maximum version we speak */
+ MinProtoVersion = 0x0300, /* limits on version we accept */
+ MaxProtoVersion = 0x03ff,
+
+ /* connection states */
+ SHandshake = 1 << 0, /* doing handshake */
+ SOpen = 1 << 1, /* application data can be sent */
+ SRClose = 1 << 2, /* remote side has closed down */
+ SLClose = 1 << 3, /* sent a close notify alert */
+ SAlert = 1 << 5, /* sending or sent a fatal alert */
+ SError = 1 << 6, /* some sort of error has occured */
+ SClosed = 1 << 7, /* it is all over */
+
+ /* record types */
+ RChangeCipherSpec = 20,
+ RAlert,
+ RHandshake,
+ RApplication,
+
+ SSL2ClientHello = 1,
+ HSSL2ClientHello = 9, /* local convention; see tlshand.c */
+
+ /* alerts */
+ ECloseNotify = 0,
+ EUnexpectedMessage = 10,
+ EBadRecordMac = 20,
+ EDecryptionFailed = 21,
+ ERecordOverflow = 22,
+ EDecompressionFailure = 30,
+ EHandshakeFailure = 40,
+ ENoCertificate = 41,
+ EBadCertificate = 42,
+ EUnsupportedCertificate = 43,
+ ECertificateRevoked = 44,
+ ECertificateExpired = 45,
+ ECertificateUnknown = 46,
+ EIllegalParameter = 47,
+ EUnknownCa = 48,
+ EAccessDenied = 49,
+ EDecodeError = 50,
+ EDecryptError = 51,
+ EExportRestriction = 60,
+ EProtocolVersion = 70,
+ EInsufficientSecurity = 71,
+ EInternalError = 80,
+ EUserCanceled = 90,
+ ENoRenegotiation = 100,
+
+ EMAX = 256
+};
+
+struct Secret
+{
+ char *encalg; /* name of encryption alg */
+ char *hashalg; /* name of hash alg */
+ int (*enc)(Secret*, uchar*, int);
+ int (*dec)(Secret*, uchar*, int);
+ int (*unpad)(uchar*, int, int);
+ DigestState *(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+ int block; /* encryption block len, 0 if none */
+ int maclen;
+ void *enckey;
+ uchar mackey[MaxMacLen];
+};
+
+struct OneWay
+{
+ QLock io; /* locks io access */
+ QLock seclock; /* locks secret paramaters */
+ ulong seq;
+ Secret *sec; /* cipher in use */
+ Secret *new; /* cipher waiting for enable */
+};
+
+struct TlsRec
+{
+ Chan *c; /* io channel */
+ int ref; /* serialized by tdlock for atomic destroy */
+ int version; /* version of the protocol we are speaking */
+ char verset; /* version has been set */
+ char opened; /* opened command every issued? */
+ char err[ERRMAX]; /* error message to return to handshake requests */
+ vlong handin; /* bytes communicated by the record layer */
+ vlong handout;
+ vlong datain;
+ vlong dataout;
+
+ Lock statelk;
+ int state;
+ int debug;
+
+ /* record layer mac functions for different protocol versions */
+ void (*packMac)(Secret*, uchar*, uchar*, uchar*, uchar*, int, uchar*);
+
+ /* input side -- protected by in.io */
+ OneWay in;
+ Block *processed; /* next bunch of application data */
+ Block *unprocessed; /* data read from c but not parsed into records */
+
+ /* handshake queue */
+ Lock hqlock; /* protects hqref, alloc & free of handq, hprocessed */
+ int hqref;
+ Queue *handq; /* queue of handshake messages */
+ Block *hprocessed; /* remainder of last block read from handq */
+ QLock hqread; /* protects reads for hprocessed, handq */
+
+ /* output side */
+ OneWay out;
+
+ /* protections */
+ char *user;
+ int perm;
+};
+
+struct TlsErrs{
+ int err;
+ int sslerr;
+ int tlserr;
+ int fatal;
+ char *msg;
+};
+
+static TlsErrs tlserrs[] = {
+ {ECloseNotify, ECloseNotify, ECloseNotify, 0, "close notify"},
+ {EUnexpectedMessage, EUnexpectedMessage, EUnexpectedMessage, 1, "unexpected message"},
+ {EBadRecordMac, EBadRecordMac, EBadRecordMac, 1, "bad record mac"},
+ {EDecryptionFailed, EIllegalParameter, EDecryptionFailed, 1, "decryption failed"},
+ {ERecordOverflow, EIllegalParameter, ERecordOverflow, 1, "record too long"},
+ {EDecompressionFailure, EDecompressionFailure, EDecompressionFailure, 1, "decompression failed"},
+ {EHandshakeFailure, EHandshakeFailure, EHandshakeFailure, 1, "could not negotiate acceptable security parameters"},
+ {ENoCertificate, ENoCertificate, ECertificateUnknown, 1, "no appropriate certificate available"},
+ {EBadCertificate, EBadCertificate, EBadCertificate, 1, "corrupted or invalid certificate"},
+ {EUnsupportedCertificate, EUnsupportedCertificate, EUnsupportedCertificate, 1, "unsupported certificate type"},
+ {ECertificateRevoked, ECertificateRevoked, ECertificateRevoked, 1, "revoked certificate"},
+ {ECertificateExpired, ECertificateExpired, ECertificateExpired, 1, "expired certificate"},
+ {ECertificateUnknown, ECertificateUnknown, ECertificateUnknown, 1, "unacceptable certificate"},
+ {EIllegalParameter, EIllegalParameter, EIllegalParameter, 1, "illegal parameter"},
+ {EUnknownCa, EHandshakeFailure, EUnknownCa, 1, "unknown certificate authority"},
+ {EAccessDenied, EHandshakeFailure, EAccessDenied, 1, "access denied"},
+ {EDecodeError, EIllegalParameter, EDecodeError, 1, "error decoding message"},
+ {EDecryptError, EIllegalParameter, EDecryptError, 1, "error decrypting message"},
+ {EExportRestriction, EHandshakeFailure, EExportRestriction, 1, "export restriction violated"},
+ {EProtocolVersion, EIllegalParameter, EProtocolVersion, 1, "protocol version not supported"},
+ {EInsufficientSecurity, EHandshakeFailure, EInsufficientSecurity, 1, "stronger security routines required"},
+ {EInternalError, EHandshakeFailure, EInternalError, 1, "internal error"},
+ {EUserCanceled, ECloseNotify, EUserCanceled, 0, "handshake canceled by user"},
+ {ENoRenegotiation, EUnexpectedMessage, ENoRenegotiation, 0, "no renegotiation"},
+};
+
+enum
+{
+ /* max. open tls connections */
+ MaxTlsDevs = 1024
+};
+
+static Lock tdlock;
+static int tdhiwat;
+static int maxtlsdevs = 128;
+static TlsRec **tlsdevs;
+static char **trnames;
+static char *encalgs;
+static char *hashalgs;
+
+enum{
+ Qtopdir = 1, /* top level directory */
+ Qprotodir,
+ Qclonus,
+ Qencalgs,
+ Qhashalgs,
+ Qconvdir, /* directory for a conversation */
+ Qdata,
+ Qctl,
+ Qhand,
+ Qstatus,
+ Qstats,
+};
+
+#define TYPE(x) ((x).path & 0xf)
+#define CONV(x) (((x).path >> 5)&(MaxTlsDevs-1))
+#define QID(c, y) (((c)<<5) | (y))
+
+static void checkstate(TlsRec *, int, int);
+static void ensure(TlsRec*, Block**, int);
+static void consume(Block**, uchar*, int);
+static Chan* buftochan(char*);
+static void tlshangup(TlsRec*);
+static void tlsError(TlsRec*, char *);
+static void alertHand(TlsRec*, char *);
+static TlsRec *newtls(Chan *c);
+static TlsRec *mktlsrec(void);
+static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
+static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
+static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
+static void sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
+static void tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
+static void put64(uchar *p, vlong x);
+static void put32(uchar *p, u32int);
+static void put24(uchar *p, int);
+static void put16(uchar *p, int);
+static u32int get32(uchar *p);
+static int get16(uchar *p);
+static void tlsSetState(TlsRec *tr, int new, int old);
+static void rcvAlert(TlsRec *tr, int err);
+static void sendAlert(TlsRec *tr, int err);
+static void rcvError(TlsRec *tr, int err, char *msg, ...);
+static int rc4enc(Secret *sec, uchar *buf, int n);
+static int des3enc(Secret *sec, uchar *buf, int n);
+static int des3dec(Secret *sec, uchar *buf, int n);
+static int noenc(Secret *sec, uchar *buf, int n);
+static int sslunpad(uchar *buf, int n, int block);
+static int tlsunpad(uchar *buf, int n, int block);
+static void freeSec(Secret *sec);
+static char *tlsstate(int s);
+static void pdump(int, void*, char*);
+
+#pragma varargck argpos rcvError 3
+
+static char *tlsnames[] = {
+[Qclonus] "clone",
+[Qencalgs] "encalgs",
+[Qhashalgs] "hashalgs",
+[Qdata] "data",
+[Qctl] "ctl",
+[Qhand] "hand",
+[Qstatus] "status",
+[Qstats] "stats",
+};
+
+static int convdir[] = { Qctl, Qdata, Qhand, Qstatus, Qstats };
+
+static int
+tlsgen(Chan *c, char*, Dirtab *, int, int s, Dir *dp)
+{
+ Qid q;
+ TlsRec *tr;
+ char *name, *nm;
+ int perm, t;
+
+ q.vers = 0;
+ q.type = QTFILE;
+
+ t = TYPE(c->qid);
+ switch(t) {
+ case Qtopdir:
+ if(s == DEVDOTDOT){
+ q.path = QID(0, Qtopdir);
+ q.type = QTDIR;
+ devdir(c, q, "#a", 0, eve, 0555, dp);
+ return 1;
+ }
+ if(s > 0)
+ return -1;
+ q.path = QID(0, Qprotodir);
+ q.type = QTDIR;
+ devdir(c, q, "tls", 0, eve, 0555, dp);
+ return 1;
+ case Qprotodir:
+ if(s == DEVDOTDOT){
+ q.path = QID(0, Qtopdir);
+ q.type = QTDIR;
+ devdir(c, q, ".", 0, eve, 0555, dp);
+ return 1;
+ }
+ if(s < 3){
+ switch(s) {
+ default:
+ return -1;
+ case 0:
+ q.path = QID(0, Qclonus);
+ break;
+ case 1:
+ q.path = QID(0, Qencalgs);
+ break;
+ case 2:
+ q.path = QID(0, Qhashalgs);
+ break;
+ }
+ perm = 0444;
+ if(TYPE(q) == Qclonus)
+ perm = 0555;
+ devdir(c, q, tlsnames[TYPE(q)], 0, eve, perm, dp);
+ return 1;
+ }
+ s -= 3;
+ if(s >= tdhiwat)
+ return -1;
+ q.path = QID(s, Qconvdir);
+ q.type = QTDIR;
+ lock(&tdlock);
+ tr = tlsdevs[s];
+ if(tr != nil)
+ nm = tr->user;
+ else
+ nm = eve;
+ if((name = trnames[s]) == nil){
+ name = trnames[s] = smalloc(16);
+ sprint(name, "%d", s);
+ }
+ devdir(c, q, name, 0, nm, 0555, dp);
+ unlock(&tdlock);
+ return 1;
+ case Qconvdir:
+ if(s == DEVDOTDOT){
+ q.path = QID(0, Qprotodir);
+ q.type = QTDIR;
+ devdir(c, q, "tls", 0, eve, 0555, dp);
+ return 1;
+ }
+ if(s < 0 || s >= nelem(convdir))
+ return -1;
+ lock(&tdlock);
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr != nil){
+ nm = tr->user;
+ perm = tr->perm;
+ }else{
+ perm = 0;
+ nm = eve;
+ }
+ t = convdir[s];
+ if(t == Qstatus || t == Qstats)
+ perm &= 0444;
+ q.path = QID(CONV(c->qid), t);
+ devdir(c, q, tlsnames[t], 0, nm, perm, dp);
+ unlock(&tdlock);
+ return 1;
+ case Qclonus:
+ case Qencalgs:
+ case Qhashalgs:
+ perm = 0444;
+ if(t == Qclonus)
+ perm = 0555;
+ devdir(c, c->qid, tlsnames[t], 0, eve, perm, dp);
+ return 1;
+ default:
+ lock(&tdlock);
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr != nil){
+ nm = tr->user;
+ perm = tr->perm;
+ }else{
+ perm = 0;
+ nm = eve;
+ }
+ if(t == Qstatus || t == Qstats)
+ perm &= 0444;
+ devdir(c, c->qid, tlsnames[t], 0, nm, perm, dp);
+ unlock(&tdlock);
+ return 1;
+ }
+}
+
+static Chan*
+tlsattach(char *spec)
+{
+ Chan *c;
+
+ c = devattach('a', spec);
+ c->qid.path = QID(0, Qtopdir);
+ c->qid.type = QTDIR;
+ c->qid.vers = 0;
+ return c;
+}
+
+static Walkqid*
+tlswalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, nil, 0, tlsgen);
+}
+
+static int
+tlsstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, nil, 0, tlsgen);
+}
+
+static Chan*
+tlsopen(Chan *c, int omode)
+{
+ TlsRec *tr, **pp;
+ int t, perm;
+
+ perm = 0;
+ omode &= 3;
+ switch(omode) {
+ case OREAD:
+ perm = 4;
+ break;
+ case OWRITE:
+ perm = 2;
+ break;
+ case ORDWR:
+ perm = 6;
+ break;
+ }
+
+ t = TYPE(c->qid);
+ switch(t) {
+ default:
+ panic("tlsopen");
+ case Qtopdir:
+ case Qprotodir:
+ case Qconvdir:
+ if(omode != OREAD)
+ error(Eperm);
+ break;
+ case Qclonus:
+ tr = newtls(c);
+ if(tr == nil)
+ error(Enodev);
+ break;
+ case Qctl:
+ case Qdata:
+ case Qhand:
+ case Qstatus:
+ case Qstats:
+ if((t == Qstatus || t == Qstats) && omode != OREAD)
+ error(Eperm);
+ if(waserror()) {
+ unlock(&tdlock);
+ nexterror();
+ }
+ lock(&tdlock);
+ pp = &tlsdevs[CONV(c->qid)];
+ tr = *pp;
+ if(tr == nil)
+ error("must open connection using clone");
+ if((perm & (tr->perm>>6)) != perm
+ && (strcmp(up->user, tr->user) != 0
+ || (perm & tr->perm) != perm))
+ error(Eperm);
+ if(t == Qhand){
+ if(waserror()){
+ unlock(&tr->hqlock);
+ nexterror();
+ }
+ lock(&tr->hqlock);
+ if(tr->handq != nil)
+ error(Einuse);
+ tr->handq = qopen(2 * MaxCipherRecLen, 0, nil, nil);
+ if(tr->handq == nil)
+ error("cannot allocate handshake queue");
+ tr->hqref = 1;
+ unlock(&tr->hqlock);
+ poperror();
+ }
+ tr->ref++;
+ unlock(&tdlock);
+ poperror();
+ break;
+ case Qencalgs:
+ case Qhashalgs:
+ if(omode != OREAD)
+ error(Eperm);
+ break;
+ }
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ c->iounit = qiomaxatomic;
+ return c;
+}
+
+static int
+tlswstat(Chan *c, uchar *dp, int n)
+{
+ Dir *d;
+ TlsRec *tr;
+ int rv;
+
+ d = nil;
+ if(waserror()){
+ free(d);
+ unlock(&tdlock);
+ nexterror();
+ }
+
+ lock(&tdlock);
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr == nil)
+ error(Ebadusefd);
+ if(strcmp(tr->user, up->user) != 0)
+ error(Eperm);
+
+ d = smalloc(n + sizeof *d);
+ rv = convM2D(dp, n, &d[0], (char*) &d[1]);
+ if(rv == 0)
+ error(Eshortstat);
+ if(!emptystr(d->uid))
+ kstrdup(&tr->user, d->uid);
+ if(d->mode != ~0UL)
+ tr->perm = d->mode;
+
+ free(d);
+ poperror();
+ unlock(&tdlock);
+
+ return rv;
+}
+
+static void
+dechandq(TlsRec *tr)
+{
+ lock(&tr->hqlock);
+ if(--tr->hqref == 0){
+ if(tr->handq != nil){
+ qfree(tr->handq);
+ tr->handq = nil;
+ }
+ if(tr->hprocessed != nil){
+ freeb(tr->hprocessed);
+ tr->hprocessed = nil;
+ }
+ }
+ unlock(&tr->hqlock);
+}
+
+static void
+tlsclose(Chan *c)
+{
+ TlsRec *tr;
+ int t;
+
+ t = TYPE(c->qid);
+ switch(t) {
+ case Qctl:
+ case Qdata:
+ case Qhand:
+ case Qstatus:
+ case Qstats:
+ if((c->flag & COPEN) == 0)
+ break;
+
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr == nil)
+ break;
+
+ if(t == Qhand)
+ dechandq(tr);
+
+ lock(&tdlock);
+ if(--tr->ref > 0) {
+ unlock(&tdlock);
+ return;
+ }
+ tlsdevs[CONV(c->qid)] = nil;
+ unlock(&tdlock);
+
+ if(tr->c != nil && !waserror()){
+ checkstate(tr, 0, SOpen|SHandshake|SRClose);
+ sendAlert(tr, ECloseNotify);
+ poperror();
+ }
+ tlshangup(tr);
+ if(tr->c != nil)
+ cclose(tr->c);
+ freeSec(tr->in.sec);
+ freeSec(tr->in.new);
+ freeSec(tr->out.sec);
+ freeSec(tr->out.new);
+ free(tr->user);
+ free(tr);
+ break;
+ }
+}
+
+/*
+ * make sure we have at least 'n' bytes in list 'l'
+ */
+static void
+ensure(TlsRec *s, Block **l, int n)
+{
+ int sofar, i;
+ Block *b, *bl;
+
+ sofar = 0;
+ for(b = *l; b; b = b->next){
+ sofar += BLEN(b);
+ if(sofar >= n)
+ return;
+ l = &b->next;
+ }
+
+ while(sofar < n){
+ bl = devtab[s->c->type]->bread(s->c, MaxCipherRecLen + RecHdrLen, 0);
+ if(bl == 0)
+ error(Ehungup);
+ *l = bl;
+ i = 0;
+ for(b = bl; b; b = b->next){
+ i += BLEN(b);
+ l = &b->next;
+ }
+ if(i == 0)
+ error(Ehungup);
+ sofar += i;
+ }
+if(s->debug) pprint("ensure read %d\n", sofar);
+}
+
+/*
+ * copy 'n' bytes from 'l' into 'p' and free
+ * the bytes in 'l'
+ */
+static void
+consume(Block **l, uchar *p, int n)
+{
+ Block *b;
+ int i;
+
+ for(; *l && n > 0; n -= i){
+ b = *l;
+ i = BLEN(b);
+ if(i > n)
+ i = n;
+ memmove(p, b->rp, i);
+ b->rp += i;
+ p += i;
+ if(BLEN(b) < 0)
+ panic("consume");
+ if(BLEN(b))
+ break;
+ *l = b->next;
+ freeb(b);
+ }
+}
+
+/*
+ * give back n bytes
+ */
+static void
+regurgitate(TlsRec *s, uchar *p, int n)
+{
+ Block *b;
+
+ if(n <= 0)
+ return;
+ b = s->unprocessed;
+ if(s->unprocessed == nil || b->rp - b->base < n) {
+ b = allocb(n);
+ memmove(b->wp, p, n);
+ b->wp += n;
+ b->next = s->unprocessed;
+ s->unprocessed = b;
+ } else {
+ b->rp -= n;
+ memmove(b->rp, p, n);
+ }
+}
+
+/*
+ * remove at most n bytes from the queue
+ */
+static Block*
+qgrab(Block **l, int n)
+{
+ Block *bb, *b;
+ int i;
+
+ b = *l;
+ if(BLEN(b) == n){
+ *l = b->next;
+ b->next = nil;
+ return b;
+ }
+
+ i = 0;
+ for(bb = b; bb != nil && i < n; bb = bb->next)
+ i += BLEN(bb);
+ if(i > n)
+ i = n;
+
+ bb = allocb(i);
+ consume(l, bb->wp, i);
+ bb->wp += i;
+ return bb;
+}
+
+static void
+tlsclosed(TlsRec *tr, int new)
+{
+ lock(&tr->statelk);
+ if(tr->state == SOpen || tr->state == SHandshake)
+ tr->state = new;
+ else if((new | tr->state) == (SRClose|SLClose))
+ tr->state = SClosed;
+ unlock(&tr->statelk);
+ alertHand(tr, "close notify");
+}
+
+/*
+ * read and process one tls record layer message
+ * must be called with tr->in.io held
+ * We can't let Eintrs lose data, since doing so will get
+ * us out of sync with the sender and break the reliablity
+ * of the channel. Eintr only happens during the reads in
+ * consume. Therefore we put back any bytes consumed before
+ * the last call to ensure.
+ */
+static void
+tlsrecread(TlsRec *tr)
+{
+ OneWay *volatile in;
+ Block *volatile b;
+ uchar *p, seq[8], header[RecHdrLen], hmac[MD5dlen];
+ int volatile nconsumed;
+ int len, type, ver, unpad_len;
+
+ nconsumed = 0;
+ if(waserror()){
+ if(strcmp(up->errstr, Eintr) == 0 && !waserror()){
+ regurgitate(tr, header, nconsumed);
+ poperror();
+ }else
+ tlsError(tr, "channel error");
+ nexterror();
+ }
+ ensure(tr, &tr->unprocessed, RecHdrLen);
+ consume(&tr->unprocessed, header, RecHdrLen);
+if(tr->debug)pprint("consumed %d header\n", RecHdrLen);
+ nconsumed = RecHdrLen;
+
+ if((tr->handin == 0) && (header[0] & 0x80)){
+ /* Cope with an SSL3 ClientHello expressed in SSL2 record format.
+ This is sent by some clients that we must interoperate
+ with, such as Java's JSSE and Microsoft's Internet Explorer. */
+ len = (get16(header) & ~0x8000) - 3;
+ type = header[2];
+ ver = get16(header + 3);
+ if(type != SSL2ClientHello || len < 22)
+ rcvError(tr, EProtocolVersion, "invalid initial SSL2-like message");
+ }else{ /* normal SSL3 record format */
+ type = header[0];
+ ver = get16(header+1);
+ len = get16(header+3);
+ }
+ if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion))
+ rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'",
+ tr->version, tr->verset?"/set":"", len, type, ver, (char*)header);
+ if(len > MaxCipherRecLen || len < 0)
+ rcvError(tr, ERecordOverflow, "record message too long %d", len);
+ ensure(tr, &tr->unprocessed, len);
+ nconsumed = 0;
+ poperror();
+
+ /*
+ * If an Eintr happens after this, we'll get out of sync.
+ * Make sure nothing we call can sleep.
+ * Errors are ok, as they kill the connection.
+ * Luckily, allocb won't sleep, it'll just error out.
+ */
+ b = nil;
+ if(waserror()){
+ if(b != nil)
+ freeb(b);
+ tlsError(tr, "channel error");
+ nexterror();
+ }
+ b = qgrab(&tr->unprocessed, len);
+if(tr->debug) pprint("consumed unprocessed %d\n", len);
+
+ in = &tr->in;
+ if(waserror()){
+ qunlock(&in->seclock);
+ nexterror();
+ }
+ qlock(&in->seclock);
+ p = b->rp;
+ if(in->sec != nil) {
+ /* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here
+ should look alike, including timing of the response. */
+ unpad_len = (*in->sec->dec)(in->sec, p, len);
+ if(unpad_len >= in->sec->maclen)
+ len = unpad_len - in->sec->maclen;
+if(tr->debug) pprint("decrypted %d\n", unpad_len);
+if(tr->debug) pdump(unpad_len, p, "decrypted:");
+
+ /* update length */
+ put16(header+3, len);
+ put64(seq, in->seq);
+ in->seq++;
+ (*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac);
+ if(unpad_len < in->sec->maclen)
+ rcvError(tr, EBadRecordMac, "short record mac");
+ if(memcmp(hmac, p+len, in->sec->maclen) != 0)
+ rcvError(tr, EBadRecordMac, "record mac mismatch");
+ b->wp = b->rp + len;
+ }
+ qunlock(&in->seclock);
+ poperror();
+ if(len < 0)
+ rcvError(tr, EDecodeError, "runt record message");
+
+ switch(type) {
+ default:
+ rcvError(tr, EIllegalParameter, "invalid record message %#x", type);
+ break;
+ case RChangeCipherSpec:
+ if(len != 1 || p[0] != 1)
+ rcvError(tr, EDecodeError, "invalid change cipher spec");
+ qlock(&in->seclock);
+ if(in->new == nil){
+ qunlock(&in->seclock);
+ rcvError(tr, EUnexpectedMessage, "unexpected change cipher spec");
+ }
+ freeSec(in->sec);
+ in->sec = in->new;
+ in->new = nil;
+ in->seq = 0;
+ qunlock(&in->seclock);
+ break;
+ case RAlert:
+ if(len != 2)
+ rcvError(tr, EDecodeError, "invalid alert");
+ if(p[0] == 2)
+ rcvAlert(tr, p[1]);
+ if(p[0] != 1)
+ rcvError(tr, EIllegalParameter, "invalid alert fatal code");
+
+ /*
+ * propate non-fatal alerts to handshaker
+ */
+ if(p[1] == ECloseNotify) {
+ tlsclosed(tr, SRClose);
+ if(tr->opened)
+ error("tls hungup");
+ error("close notify");
+ }
+ if(p[1] == ENoRenegotiation)
+ alertHand(tr, "no renegotiation");
+ else if(p[1] == EUserCanceled)
+ alertHand(tr, "handshake canceled by user");
+ else
+ rcvError(tr, EIllegalParameter, "invalid alert code");
+ break;
+ case RHandshake:
+ /*
+ * don't worry about dropping the block
+ * qbwrite always queues even if flow controlled and interrupted.
+ *
+ * if there isn't any handshaker, ignore the request,
+ * but notify the other side we are doing so.
+ */
+ lock(&tr->hqlock);
+ if(tr->handq != nil){
+ tr->hqref++;
+ unlock(&tr->hqlock);
+ if(waserror()){
+ dechandq(tr);
+ nexterror();
+ }
+ b = padblock(b, 1);
+ *b->rp = RHandshake;
+ qbwrite(tr->handq, b);
+ b = nil;
+ poperror();
+ dechandq(tr);
+ }else{
+ unlock(&tr->hqlock);
+ if(tr->verset && tr->version != SSL3Version && !waserror()){
+ sendAlert(tr, ENoRenegotiation);
+ poperror();
+ }
+ }
+ break;
+ case SSL2ClientHello:
+ lock(&tr->hqlock);
+ if(tr->handq != nil){
+ tr->hqref++;
+ unlock(&tr->hqlock);
+ if(waserror()){
+ dechandq(tr);
+ nexterror();
+ }
+ /* Pass the SSL2 format data, so that the handshake code can compute
+ the correct checksums. HSSL2ClientHello = HandshakeType 9 is
+ unused in RFC2246. */
+ b = padblock(b, 8);
+ b->rp[0] = RHandshake;
+ b->rp[1] = HSSL2ClientHello;
+ put24(&b->rp[2], len+3);
+ b->rp[5] = SSL2ClientHello;
+ put16(&b->rp[6], ver);
+ qbwrite(tr->handq, b);
+ b = nil;
+ poperror();
+ dechandq(tr);
+ }else{
+ unlock(&tr->hqlock);
+ if(tr->verset && tr->version != SSL3Version && !waserror()){
+ sendAlert(tr, ENoRenegotiation);
+ poperror();
+ }
+ }
+ break;
+ case RApplication:
+ if(!tr->opened)
+ rcvError(tr, EUnexpectedMessage, "application message received before handshake completed");
+ if(BLEN(b) > 0){
+ tr->processed = b;
+ b = nil;
+ }
+ break;
+ }
+ if(b != nil)
+ freeb(b);
+ poperror();
+}
+
+/*
+ * got a fatal alert message
+ */
+static void
+rcvAlert(TlsRec *tr, int err)
+{
+ char *s;
+ int i;
+
+ s = "unknown error";
+ for(i=0; i < nelem(tlserrs); i++){
+ if(tlserrs[i].err == err){
+ s = tlserrs[i].msg;
+ break;
+ }
+ }
+if(tr->debug) pprint("rcvAlert: %s\n", s);
+
+ tlsError(tr, s);
+ if(!tr->opened)
+ error(s);
+ error("tls error");
+}
+
+/*
+ * found an error while decoding the input stream
+ */
+static void
+rcvError(TlsRec *tr, int err, char *fmt, ...)
+{
+ char msg[ERRMAX];
+ va_list arg;
+
+ va_start(arg, fmt);
+ vseprint(msg, msg+sizeof(msg), fmt, arg);
+ va_end(arg);
+if(tr->debug) pprint("rcvError: %s\n", msg);
+
+ sendAlert(tr, err);
+
+ if(!tr->opened)
+ error(msg);
+ error("tls error");
+}
+
+/*
+ * make sure the next hand operation returns with a 'msg' error
+ */
+static void
+alertHand(TlsRec *tr, char *msg)
+{
+ Block *b;
+ int n;
+
+ lock(&tr->hqlock);
+ if(tr->handq == nil){
+ unlock(&tr->hqlock);
+ return;
+ }
+ tr->hqref++;
+ unlock(&tr->hqlock);
+
+ n = strlen(msg);
+ if(waserror()){
+ dechandq(tr);
+ nexterror();
+ }
+ b = allocb(n + 2);
+ *b->wp++ = RAlert;
+ memmove(b->wp, msg, n + 1);
+ b->wp += n + 1;
+
+ qbwrite(tr->handq, b);
+
+ poperror();
+ dechandq(tr);
+}
+
+static void
+checkstate(TlsRec *tr, int ishand, int ok)
+{
+ int state;
+
+ lock(&tr->statelk);
+ state = tr->state;
+ unlock(&tr->statelk);
+ if(state & ok)
+ return;
+ switch(state){
+ case SHandshake:
+ case SOpen:
+ break;
+ case SError:
+ case SAlert:
+ if(ishand)
+ error(tr->err);
+ error("tls error");
+ case SRClose:
+ case SLClose:
+ case SClosed:
+ error("tls hungup");
+ }
+ error("tls improperly configured");
+}
+
+static Block*
+tlsbread(Chan *c, long n, ulong offset)
+{
+ int ty;
+ Block *b;
+ TlsRec *volatile tr;
+
+ ty = TYPE(c->qid);
+ switch(ty) {
+ default:
+ return devbread(c, n, offset);
+ case Qhand:
+ case Qdata:
+ break;
+ }
+
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr == nil)
+ panic("tlsbread");
+
+ if(waserror()){
+ qunlock(&tr->in.io);
+ nexterror();
+ }
+ qlock(&tr->in.io);
+ if(ty == Qdata){
+ checkstate(tr, 0, SOpen);
+ while(tr->processed == nil)
+ tlsrecread(tr);
+
+ /* return at most what was asked for */
+ b = qgrab(&tr->processed, n);
+if(tr->debug) pprint("consumed processed %ld\n", BLEN(b));
+if(tr->debug) pdump(BLEN(b), b->rp, "consumed:");
+ qunlock(&tr->in.io);
+ poperror();
+ tr->datain += BLEN(b);
+ }else{
+ checkstate(tr, 1, SOpen|SHandshake|SLClose);
+
+ /*
+ * it's ok to look at state without the lock
+ * since it only protects reading records,
+ * and we have that tr->in.io held.
+ */
+ while(!tr->opened && tr->hprocessed == nil && !qcanread(tr->handq))
+ tlsrecread(tr);
+
+ qunlock(&tr->in.io);
+ poperror();
+
+ if(waserror()){
+ qunlock(&tr->hqread);
+ nexterror();
+ }
+ qlock(&tr->hqread);
+ if(tr->hprocessed == nil){
+ b = qbread(tr->handq, MaxRecLen + 1);
+ if(*b->rp++ == RAlert){
+ kstrcpy(up->errstr, (char*)b->rp, ERRMAX);
+ freeb(b);
+ nexterror();
+ }
+ tr->hprocessed = b;
+ }
+ b = qgrab(&tr->hprocessed, n);
+ poperror();
+ qunlock(&tr->hqread);
+ tr->handin += BLEN(b);
+ }
+
+ return b;
+}
+
+static long
+tlsread(Chan *c, void *a, long n, vlong off)
+{
+ Block *volatile b;
+ Block *nb;
+ uchar *va;
+ int i, ty;
+ char *buf, *s, *e;
+ ulong offset = off;
+ TlsRec * tr;
+
+ if(c->qid.type & QTDIR)
+ return devdirread(c, a, n, 0, 0, tlsgen);
+
+ tr = tlsdevs[CONV(c->qid)];
+ ty = TYPE(c->qid);
+ switch(ty) {
+ default:
+ error(Ebadusefd);
+ case Qstatus:
+ buf = smalloc(Statlen);
+ qlock(&tr->in.seclock);
+ qlock(&tr->out.seclock);
+ s = buf;
+ e = buf + Statlen;
+ s = seprint(s, e, "State: %s\n", tlsstate(tr->state));
+ s = seprint(s, e, "Version: %#x\n", tr->version);
+ if(tr->in.sec != nil)
+ s = seprint(s, e, "EncIn: %s\nHashIn: %s\n", tr->in.sec->encalg, tr->in.sec->hashalg);
+ if(tr->in.new != nil)
+ s = seprint(s, e, "NewEncIn: %s\nNewHashIn: %s\n", tr->in.new->encalg, tr->in.new->hashalg);
+ if(tr->out.sec != nil)
+ s = seprint(s, e, "EncOut: %s\nHashOut: %s\n", tr->out.sec->encalg, tr->out.sec->hashalg);
+ if(tr->out.new != nil)
+ seprint(s, e, "NewEncOut: %s\nNewHashOut: %s\n", tr->out.new->encalg, tr->out.new->hashalg);
+ qunlock(&tr->in.seclock);
+ qunlock(&tr->out.seclock);
+ n = readstr(offset, a, n, buf);
+ free(buf);
+ return n;
+ case Qstats:
+ buf = smalloc(Statlen);
+ s = buf;
+ e = buf + Statlen;
+ s = seprint(s, e, "DataIn: %lld\n", tr->datain);
+ s = seprint(s, e, "DataOut: %lld\n", tr->dataout);
+ s = seprint(s, e, "HandIn: %lld\n", tr->handin);
+ seprint(s, e, "HandOut: %lld\n", tr->handout);
+ n = readstr(offset, a, n, buf);
+ free(buf);
+ return n;
+ case Qctl:
+ buf = smalloc(Statlen);
+ snprint(buf, Statlen, "%llud", CONV(c->qid));
+ n = readstr(offset, a, n, buf);
+ free(buf);
+ return n;
+ case Qdata:
+ case Qhand:
+ b = tlsbread(c, n, offset);
+ break;
+ case Qencalgs:
+ return readstr(offset, a, n, encalgs);
+ case Qhashalgs:
+ return readstr(offset, a, n, hashalgs);
+ }
+
+ if(waserror()){
+ freeblist(b);
+ nexterror();
+ }
+
+ n = 0;
+ va = a;
+ for(nb = b; nb; nb = nb->next){
+ i = BLEN(nb);
+ memmove(va+n, nb->rp, i);
+ n += i;
+ }
+
+ freeblist(b);
+ poperror();
+
+ return n;
+}
+
+/*
+ * write a block in tls records
+ */
+static void
+tlsrecwrite(TlsRec *tr, int type, Block *b)
+{
+ Block *volatile bb;
+ Block *nb;
+ uchar *p, seq[8];
+ OneWay *volatile out;
+ int n, maclen, pad, ok;
+
+ out = &tr->out;
+ bb = b;
+ if(waserror()){
+ qunlock(&out->io);
+ if(bb != nil)
+ freeb(bb);
+ nexterror();
+ }
+ qlock(&out->io);
+if(tr->debug)pprint("send %ld\n", BLEN(b));
+if(tr->debug)pdump(BLEN(b), b->rp, "sent:");
+
+
+ ok = SHandshake|SOpen|SRClose;
+ if(type == RAlert)
+ ok |= SAlert;
+ while(bb != nil){
+ checkstate(tr, type != RApplication, ok);
+
+ /*
+ * get at most one maximal record's input,
+ * with padding on the front for header and
+ * back for mac and maximal block padding.
+ */
+ if(waserror()){
+ qunlock(&out->seclock);
+ nexterror();
+ }
+ qlock(&out->seclock);
+ maclen = 0;
+ pad = 0;
+ if(out->sec != nil){
+ maclen = out->sec->maclen;
+ pad = maclen + out->sec->block;
+ }
+ n = BLEN(bb);
+ if(n > MaxRecLen){
+ n = MaxRecLen;
+ nb = allocb(n + pad + RecHdrLen);
+ memmove(nb->wp + RecHdrLen, bb->rp, n);
+ bb->rp += n;
+ }else{
+ /*
+ * carefully reuse bb so it will get freed if we're out of memory
+ */
+ bb = padblock(bb, RecHdrLen);
+ if(pad)
+ nb = padblock(bb, -pad);
+ else
+ nb = bb;
+ bb = nil;
+ }
+
+ p = nb->rp;
+ p[0] = type;
+ put16(p+1, tr->version);
+ put16(p+3, n);
+
+ if(out->sec != nil){
+ put64(seq, out->seq);
+ out->seq++;
+ (*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen, n, p + RecHdrLen + n);
+ n += maclen;
+
+ /* encrypt */
+ n = (*out->sec->enc)(out->sec, p + RecHdrLen, n);
+ nb->wp = p + RecHdrLen + n;
+
+ /* update length */
+ put16(p+3, n);
+ }
+ if(type == RChangeCipherSpec){
+ if(out->new == nil)
+ error("change cipher without a new cipher");
+ freeSec(out->sec);
+ out->sec = out->new;
+ out->new = nil;
+ out->seq = 0;
+ }
+ qunlock(&out->seclock);
+ poperror();
+
+ /*
+ * if bwrite error's, we assume the block is queued.
+ * if not, we're out of sync with the receiver and will not recover.
+ */
+ if(waserror()){
+ if(strcmp(up->errstr, "interrupted") != 0)
+ tlsError(tr, "channel error");
+ nexterror();
+ }
+ devtab[tr->c->type]->bwrite(tr->c, nb, 0);
+ poperror();
+ }
+ qunlock(&out->io);
+ poperror();
+}
+
+static long
+tlsbwrite(Chan *c, Block *b, ulong offset)
+{
+ int ty;
+ ulong n;
+ TlsRec *tr;
+
+ n = BLEN(b);
+
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr == nil)
+ panic("tlsbread");
+
+ ty = TYPE(c->qid);
+ switch(ty) {
+ default:
+ return devbwrite(c, b, offset);
+ case Qhand:
+ tlsrecwrite(tr, RHandshake, b);
+ tr->handout += n;
+ break;
+ case Qdata:
+ checkstate(tr, 0, SOpen);
+ tlsrecwrite(tr, RApplication, b);
+ tr->dataout += n;
+ break;
+ }
+
+ return n;
+}
+
+typedef struct Hashalg Hashalg;
+struct Hashalg
+{
+ char *name;
+ int maclen;
+ void (*initkey)(Hashalg *, int, Secret *, uchar*);
+};
+
+static void
+initmd5key(Hashalg *ha, int version, Secret *s, uchar *p)
+{
+ s->maclen = ha->maclen;
+ if(version == SSL3Version)
+ s->mac = sslmac_md5;
+ else
+ s->mac = hmac_md5;
+ memmove(s->mackey, p, ha->maclen);
+}
+
+static void
+initclearmac(Hashalg *, int, Secret *s, uchar *)
+{
+ s->maclen = 0;
+ s->mac = nomac;
+}
+
+static void
+initsha1key(Hashalg *ha, int version, Secret *s, uchar *p)
+{
+ s->maclen = ha->maclen;
+ if(version == SSL3Version)
+ s->mac = sslmac_sha1;
+ else
+ s->mac = hmac_sha1;
+ memmove(s->mackey, p, ha->maclen);
+}
+
+static Hashalg hashtab[] =
+{
+ { "clear", 0, initclearmac, },
+ { "md5", MD5dlen, initmd5key, },
+ { "sha1", SHA1dlen, initsha1key, },
+ { 0 }
+};
+
+static Hashalg*
+parsehashalg(char *p)
+{
+ Hashalg *ha;
+
+ for(ha = hashtab; ha->name; ha++)
+ if(strcmp(p, ha->name) == 0)
+ return ha;
+ error("unsupported hash algorithm");
+ return nil;
+}
+
+typedef struct Encalg Encalg;
+struct Encalg
+{
+ char *name;
+ int keylen;
+ int ivlen;
+ void (*initkey)(Encalg *ea, Secret *, uchar*, uchar*);
+};
+
+static void
+initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *)
+{
+ s->enckey = smalloc(sizeof(RC4state));
+ s->enc = rc4enc;
+ s->dec = rc4enc;
+ s->block = 0;
+ setupRC4state(s->enckey, p, ea->keylen);
+}
+
+static void
+initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv)
+{
+ s->enckey = smalloc(sizeof(DES3state));
+ s->enc = des3enc;
+ s->dec = des3dec;
+ s->block = 8;
+ setupDES3state(s->enckey, (uchar(*)[8])p, iv);
+}
+
+static void
+initclearenc(Encalg *, Secret *s, uchar *, uchar *)
+{
+ s->enc = noenc;
+ s->dec = noenc;
+ s->block = 0;
+}
+
+static Encalg encrypttab[] =
+{
+ { "clear", 0, 0, initclearenc },
+ { "rc4_128", 128/8, 0, initRC4key },
+ { "3des_ede_cbc", 3 * 8, 8, initDES3key },
+ { 0 }
+};
+
+static Encalg*
+parseencalg(char *p)
+{
+ Encalg *ea;
+
+ for(ea = encrypttab; ea->name; ea++)
+ if(strcmp(p, ea->name) == 0)
+ return ea;
+ error("unsupported encryption algorithm");
+ return nil;
+}
+
+static long
+tlswrite(Chan *c, void *a, long n, vlong off)
+{
+ Encalg *ea;
+ Hashalg *ha;
+ TlsRec *volatile tr;
+ Secret *volatile tos, *volatile toc;
+ Block *volatile b;
+ Cmdbuf *volatile cb;
+ int m, ty;
+ char *p, *e;
+ uchar *volatile x;
+ ulong offset = off;
+
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr == nil)
+ panic("tlswrite");
+
+ ty = TYPE(c->qid);
+ switch(ty){
+ case Qdata:
+ case Qhand:
+ p = a;
+ e = p + n;
+ do{
+ m = e - p;
+ if(m > MaxRecLen)
+ m = MaxRecLen;
+
+ b = allocb(m);
+ if(waserror()){
+ freeb(b);
+ nexterror();
+ }
+ memmove(b->wp, p, m);
+ poperror();
+ b->wp += m;
+
+ tlsbwrite(c, b, offset);
+
+ p += m;
+ }while(p < e);
+ return n;
+ case Qctl:
+ break;
+ default:
+ error(Ebadusefd);
+ return -1;
+ }
+
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ if(cb->nf < 1)
+ error("short control request");
+
+ /* mutex with operations using what we're about to change */
+ if(waserror()){
+ qunlock(&tr->in.seclock);
+ qunlock(&tr->out.seclock);
+ nexterror();
+ }
+ qlock(&tr->in.seclock);
+ qlock(&tr->out.seclock);
+
+ if(strcmp(cb->f[0], "fd") == 0){
+ if(cb->nf != 3)
+ error("usage: fd open-fd version");
+ if(tr->c != nil)
+ error(Einuse);
+ m = strtol(cb->f[2], nil, 0);
+ if(m < MinProtoVersion || m > MaxProtoVersion)
+ error("unsupported version");
+ tr->c = buftochan(cb->f[1]);
+ tr->version = m;
+ tlsSetState(tr, SHandshake, SClosed);
+ }else if(strcmp(cb->f[0], "version") == 0){
+ if(cb->nf != 2)
+ error("usage: version vers");
+ if(tr->c == nil)
+ error("must set fd before version");
+ if(tr->verset)
+ error("version already set");
+ m = strtol(cb->f[1], nil, 0);
+ if(m == SSL3Version)
+ tr->packMac = sslPackMac;
+ else if(m == TLSVersion)
+ tr->packMac = tlsPackMac;
+ else
+ error("unsupported version");
+ tr->verset = 1;
+ tr->version = m;
+ }else if(strcmp(cb->f[0], "secret") == 0){
+ if(cb->nf != 5)
+ error("usage: secret hashalg encalg isclient secretdata");
+ if(tr->c == nil || !tr->verset)
+ error("must set fd and version before secrets");
+
+ if(tr->in.new != nil){
+ freeSec(tr->in.new);
+ tr->in.new = nil;
+ }
+ if(tr->out.new != nil){
+ freeSec(tr->out.new);
+ tr->out.new = nil;
+ }
+
+ ha = parsehashalg(cb->f[1]);
+ ea = parseencalg(cb->f[2]);
+
+ p = cb->f[4];
+ m = (strlen(p)*3)/2;
+ x = smalloc(m);
+ tos = nil;
+ toc = nil;
+ if(waserror()){
+ freeSec(tos);
+ freeSec(toc);
+ free(x);
+ nexterror();
+ }
+ m = dec64(x, m, p, strlen(p));
+ if(m < 2 * ha->maclen + 2 * ea->keylen + 2 * ea->ivlen)
+ error("not enough secret data provided");
+
+ tos = smalloc(sizeof(Secret));
+ toc = smalloc(sizeof(Secret));
+ if(!ha->initkey || !ea->initkey)
+ error("misimplemented secret algorithm");
+ (*ha->initkey)(ha, tr->version, tos, &x[0]);
+ (*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]);
+ (*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]);
+ (*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]);
+
+ if(!tos->mac || !tos->enc || !tos->dec
+ || !toc->mac || !toc->enc || !toc->dec)
+ error("missing algorithm implementations");
+ if(strtol(cb->f[3], nil, 0) == 0){
+ tr->in.new = tos;
+ tr->out.new = toc;
+ }else{
+ tr->in.new = toc;
+ tr->out.new = tos;
+ }
+ if(tr->version == SSL3Version){
+ toc->unpad = sslunpad;
+ tos->unpad = sslunpad;
+ }else{
+ toc->unpad = tlsunpad;
+ tos->unpad = tlsunpad;
+ }
+ toc->encalg = ea->name;
+ toc->hashalg = ha->name;
+ tos->encalg = ea->name;
+ tos->hashalg = ha->name;
+
+ free(x);
+ poperror();
+ }else if(strcmp(cb->f[0], "changecipher") == 0){
+ if(cb->nf != 1)
+ error("usage: changecipher");
+ if(tr->out.new == nil)
+ error("cannot change cipher spec without setting secret");
+
+ qunlock(&tr->in.seclock);
+ qunlock(&tr->out.seclock);
+ poperror();
+ free(cb);
+ poperror();
+
+ /*
+ * the real work is done as the message is written
+ * so the stream is encrypted in sync.
+ */
+ b = allocb(1);
+ *b->wp++ = 1;
+ tlsrecwrite(tr, RChangeCipherSpec, b);
+ return n;
+ }else if(strcmp(cb->f[0], "opened") == 0){
+ if(cb->nf != 1)
+ error("usage: opened");
+ if(tr->in.sec == nil || tr->out.sec == nil)
+ error("cipher must be configured before enabling data messages");
+ lock(&tr->statelk);
+ if(tr->state != SHandshake && tr->state != SOpen){
+ unlock(&tr->statelk);
+ error("cannot enable data messages");
+ }
+ tr->state = SOpen;
+ unlock(&tr->statelk);
+ tr->opened = 1;
+ }else if(strcmp(cb->f[0], "alert") == 0){
+ if(cb->nf != 2)
+ error("usage: alert n");
+ if(tr->c == nil)
+ error("must set fd before sending alerts");
+ m = strtol(cb->f[1], nil, 0);
+
+ qunlock(&tr->in.seclock);
+ qunlock(&tr->out.seclock);
+ poperror();
+ free(cb);
+ poperror();
+
+ sendAlert(tr, m);
+
+ if(m == ECloseNotify)
+ tlsclosed(tr, SLClose);
+
+ return n;
+ } else if(strcmp(cb->f[0], "debug") == 0){
+ if(cb->nf == 2){
+ if(strcmp(cb->f[1], "on") == 0)
+ tr->debug = 1;
+ else
+ tr->debug = 0;
+ } else
+ tr->debug = 1;
+ } else
+ error(Ebadarg);
+
+ qunlock(&tr->in.seclock);
+ qunlock(&tr->out.seclock);
+ poperror();
+ free(cb);
+ poperror();
+
+ return n;
+}
+
+static void
+tlsinit(void)
+{
+ struct Encalg *e;
+ struct Hashalg *h;
+ int n;
+ char *cp;
+ static int already;
+
+ if(!already){
+ fmtinstall('H', encodefmt);
+ already = 1;
+ }
+
+ tlsdevs = smalloc(sizeof(TlsRec*) * maxtlsdevs);
+ trnames = smalloc((sizeof *trnames) * maxtlsdevs);
+
+ n = 1;
+ for(e = encrypttab; e->name != nil; e++)
+ n += strlen(e->name) + 1;
+ cp = encalgs = smalloc(n);
+ for(e = encrypttab;;){
+ strcpy(cp, e->name);
+ cp += strlen(e->name);
+ e++;
+ if(e->name == nil)
+ break;
+ *cp++ = ' ';
+ }
+ *cp = 0;
+
+ n = 1;
+ for(h = hashtab; h->name != nil; h++)
+ n += strlen(h->name) + 1;
+ cp = hashalgs = smalloc(n);
+ for(h = hashtab;;){
+ strcpy(cp, h->name);
+ cp += strlen(h->name);
+ h++;
+ if(h->name == nil)
+ break;
+ *cp++ = ' ';
+ }
+ *cp = 0;
+}
+
+Dev tlsdevtab = {
+ 'a',
+ "tls",
+
+ devreset,
+ tlsinit,
+ devshutdown,
+ tlsattach,
+ tlswalk,
+ tlsstat,
+ tlsopen,
+ devcreate,
+ tlsclose,
+ tlsread,
+ tlsbread,
+ tlswrite,
+ tlsbwrite,
+ devremove,
+ tlswstat,
+};
+
+/* get channel associated with an fd */
+static Chan*
+buftochan(char *p)
+{
+ Chan *c;
+ int fd;
+
+ if(p == 0)
+ error(Ebadarg);
+ fd = strtoul(p, 0, 0);
+ if(fd < 0)
+ error(Ebadarg);
+ c = fdtochan(fd, -1, 0, 1); /* error check and inc ref */
+ return c;
+}
+
+static void
+sendAlert(TlsRec *tr, int err)
+{
+ Block *b;
+ int i, fatal;
+ char *msg;
+
+if(tr->debug)pprint("sendAlert %d\n", err);
+ fatal = 1;
+ msg = "tls unknown alert";
+ for(i=0; i < nelem(tlserrs); i++) {
+ if(tlserrs[i].err == err) {
+ msg = tlserrs[i].msg;
+ if(tr->version == SSL3Version)
+ err = tlserrs[i].sslerr;
+ else
+ err = tlserrs[i].tlserr;
+ fatal = tlserrs[i].fatal;
+ break;
+ }
+ }
+
+ if(!waserror()){
+ b = allocb(2);
+ *b->wp++ = fatal + 1;
+ *b->wp++ = err;
+ if(fatal)
+ tlsSetState(tr, SAlert, SOpen|SHandshake|SRClose);
+ tlsrecwrite(tr, RAlert, b);
+ poperror();
+ }
+ if(fatal)
+ tlsError(tr, msg);
+}
+
+static void
+tlsError(TlsRec *tr, char *msg)
+{
+ int s;
+
+if(tr->debug)pprint("tleError %s\n", msg);
+ lock(&tr->statelk);
+ s = tr->state;
+ tr->state = SError;
+ if(s != SError){
+ strncpy(tr->err, msg, ERRMAX - 1);
+ tr->err[ERRMAX - 1] = '\0';
+ }
+ unlock(&tr->statelk);
+ if(s != SError)
+ alertHand(tr, msg);
+}
+
+static void
+tlsSetState(TlsRec *tr, int new, int old)
+{
+ lock(&tr->statelk);
+ if(tr->state & old)
+ tr->state = new;
+ unlock(&tr->statelk);
+}
+
+/* hand up a digest connection */
+static void
+tlshangup(TlsRec *tr)
+{
+ Block *b;
+
+ qlock(&tr->in.io);
+ for(b = tr->processed; b; b = tr->processed){
+ tr->processed = b->next;
+ freeb(b);
+ }
+ if(tr->unprocessed != nil){
+ freeb(tr->unprocessed);
+ tr->unprocessed = nil;
+ }
+ qunlock(&tr->in.io);
+
+ tlsSetState(tr, SClosed, ~0);
+}
+
+static TlsRec*
+newtls(Chan *ch)
+{
+ TlsRec **pp, **ep, **np;
+ char **nmp;
+ int t, newmax;
+
+ if(waserror()) {
+ unlock(&tdlock);
+ nexterror();
+ }
+ lock(&tdlock);
+ ep = &tlsdevs[maxtlsdevs];
+ for(pp = tlsdevs; pp < ep; pp++)
+ if(*pp == nil)
+ break;
+ if(pp >= ep) {
+ if(maxtlsdevs >= MaxTlsDevs) {
+ unlock(&tdlock);
+ poperror();
+ return nil;
+ }
+ newmax = 2 * maxtlsdevs;
+ if(newmax > MaxTlsDevs)
+ newmax = MaxTlsDevs;
+ np = smalloc(sizeof(TlsRec*) * newmax);
+ memmove(np, tlsdevs, sizeof(TlsRec*) * maxtlsdevs);
+ tlsdevs = np;
+ pp = &tlsdevs[maxtlsdevs];
+ memset(pp, 0, sizeof(TlsRec*)*(newmax - maxtlsdevs));
+
+ nmp = smalloc(sizeof *nmp * newmax);
+ memmove(nmp, trnames, sizeof *nmp * maxtlsdevs);
+ trnames = nmp;
+
+ maxtlsdevs = newmax;
+ }
+ *pp = mktlsrec();
+ if(pp - tlsdevs >= tdhiwat)
+ tdhiwat++;
+ t = TYPE(ch->qid);
+ if(t == Qclonus)
+ t = Qctl;
+ ch->qid.path = QID(pp - tlsdevs, t);
+ ch->qid.vers = 0;
+ unlock(&tdlock);
+ poperror();
+ return *pp;
+}
+
+static TlsRec *
+mktlsrec(void)
+{
+ TlsRec *tr;
+
+ tr = mallocz(sizeof(*tr), 1);
+ if(tr == nil)
+ error(Enomem);
+ tr->state = SClosed;
+ tr->ref = 1;
+ kstrdup(&tr->user, up->user);
+ tr->perm = 0660;
+ return tr;
+}
+
+static char*
+tlsstate(int s)
+{
+ switch(s){
+ case SHandshake:
+ return "Handshaking";
+ case SOpen:
+ return "Established";
+ case SRClose:
+ return "RemoteClosed";
+ case SLClose:
+ return "LocalClosed";
+ case SAlert:
+ return "Alerting";
+ case SError:
+ return "Errored";
+ case SClosed:
+ return "Closed";
+ }
+ return "Unknown";
+}
+
+static void
+freeSec(Secret *s)
+{
+ if(s != nil){
+ free(s->enckey);
+ free(s);
+ }
+}
+
+static int
+noenc(Secret *, uchar *, int n)
+{
+ return n;
+}
+
+static int
+rc4enc(Secret *sec, uchar *buf, int n)
+{
+ rc4(sec->enckey, buf, n);
+ return n;
+}
+
+static int
+tlsunpad(uchar *buf, int n, int block)
+{
+ int pad, nn;
+
+ pad = buf[n - 1];
+ nn = n - 1 - pad;
+ if(nn <= 0 || n % block)
+ return -1;
+ while(--n > nn)
+ if(pad != buf[n - 1])
+ return -1;
+ return nn;
+}
+
+static int
+sslunpad(uchar *buf, int n, int block)
+{
+ int pad, nn;
+
+ pad = buf[n - 1];
+ nn = n - 1 - pad;
+ if(nn <= 0 || n % block)
+ return -1;
+ return nn;
+}
+
+static int
+blockpad(uchar *buf, int n, int block)
+{
+ int pad, nn;
+
+ nn = n + block;
+ nn -= nn % block;
+ pad = nn - (n + 1);
+ while(n < nn)
+ buf[n++] = pad;
+ return nn;
+}
+
+static int
+des3enc(Secret *sec, uchar *buf, int n)
+{
+ n = blockpad(buf, n, 8);
+ des3CBCencrypt(buf, n, sec->enckey);
+ return n;
+}
+
+static int
+des3dec(Secret *sec, uchar *buf, int n)
+{
+ des3CBCdecrypt(buf, n, sec->enckey);
+ return (*sec->unpad)(buf, n, 8);
+}
+static DigestState*
+nomac(uchar *, ulong, uchar *, ulong, uchar *, DigestState *)
+{
+ return nil;
+}
+
+/*
+ * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac.
+ */
+static DigestState*
+sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s,
+ DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen)
+{
+ int i;
+ uchar pad[48], innerdigest[20];
+
+ if(xlen > sizeof(innerdigest)
+ || padlen > sizeof(pad))
+ return nil;
+
+ if(klen>64)
+ return nil;
+
+ /* first time through */
+ if(s == nil){
+ for(i=0; i<padlen; i++)
+ pad[i] = 0x36;
+ s = (*x)(key, klen, nil, nil);
+ s = (*x)(pad, padlen, nil, s);
+ if(s == nil)
+ return nil;
+ }
+
+ s = (*x)(p, len, nil, s);
+ if(digest == nil)
+ return s;
+
+ /* last time through */
+ for(i=0; i<padlen; i++)
+ pad[i] = 0x5c;
+ (*x)(nil, 0, innerdigest, s);
+ s = (*x)(key, klen, nil, nil);
+ s = (*x)(pad, padlen, nil, s);
+ (*x)(innerdigest, xlen, digest, s);
+ return nil;
+}
+
+static DigestState*
+sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
+{
+ return sslmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen, 40);
+}
+
+static DigestState*
+sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
+{
+ return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);
+}
+
+static void
+sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
+{
+ DigestState *s;
+ uchar buf[11];
+
+ memmove(buf, seq, 8);
+ buf[8] = header[0];
+ buf[9] = header[3];
+ buf[10] = header[4];
+
+ s = (*sec->mac)(buf, 11, mackey, sec->maclen, 0, 0);
+ (*sec->mac)(body, len, mackey, sec->maclen, mac, s);
+}
+
+static void
+tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
+{
+ DigestState *s;
+ uchar buf[13];
+
+ memmove(buf, seq, 8);
+ memmove(&buf[8], header, 5);
+
+ s = (*sec->mac)(buf, 13, mackey, sec->maclen, 0, 0);
+ (*sec->mac)(body, len, mackey, sec->maclen, mac, s);
+}
+
+static void
+put32(uchar *p, u32int x)
+{
+ p[0] = x>>24;
+ p[1] = x>>16;
+ p[2] = x>>8;
+ p[3] = x;
+}
+
+static void
+put64(uchar *p, vlong x)
+{
+ put32(p, (u32int)(x >> 32));
+ put32(p+4, (u32int)x);
+}
+
+static void
+put24(uchar *p, int x)
+{
+ p[0] = x>>16;
+ p[1] = x>>8;
+ p[2] = x;
+}
+
+static void
+put16(uchar *p, int x)
+{
+ p[0] = x>>8;
+ p[1] = x;
+}
+
+static u32int
+get32(uchar *p)
+{
+ return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
+}
+
+static int
+get16(uchar *p)
+{
+ return (p[0]<<8)|p[1];
+}
+
+static char *charmap = "0123456789abcdef";
+
+static void
+pdump(int len, void *a, char *tag)
+{
+ uchar *p;
+ int i;
+ char buf[65+32];
+ char *q;
+
+ p = a;
+ strcpy(buf, tag);
+ while(len > 0){
+ q = buf + strlen(tag);
+ for(i = 0; len > 0 && i < 32; i++){
+ if(*p >= ' ' && *p < 0x7f){
+ *q++ = ' ';
+ *q++ = *p;
+ } else {
+ *q++ = charmap[*p>>4];
+ *q++ = charmap[*p & 0xf];
+ }
+ len--;
+ p++;
+ }
+ *q = 0;
+
+ if(len > 0)
+ pprint("%s...\n", buf);
+ else
+ pprint("%s\n", buf);
+ }
+}
diff --git a/sys/src/9/port/devuart.c b/sys/src/9/port/devuart.c
new file mode 100755
index 000000000..a93f70e4c
--- /dev/null
+++ b/sys/src/9/port/devuart.c
@@ -0,0 +1,784 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#include "../port/netif.h"
+
+enum
+{
+ /* soft flow control chars */
+ CTLS= 023,
+ CTLQ= 021,
+};
+
+extern Dev uartdevtab;
+extern PhysUart* physuart[];
+
+static Uart* uartlist;
+static Uart** uart;
+static int uartnuart;
+static Dirtab *uartdir;
+static int uartndir;
+static Timer *uarttimer;
+
+struct Uartalloc {
+ Lock;
+ Uart *elist; /* list of enabled interfaces */
+} uartalloc;
+
+static void uartclock(void);
+static void uartflow(void*);
+
+/*
+ * enable/disable uart and add/remove to list of enabled uarts
+ */
+static Uart*
+uartenable(Uart *p)
+{
+ Uart **l;
+
+ if(p->enabled)
+ return p;
+ if(p->iq == nil){
+ if((p->iq = qopen(8*1024, 0, uartflow, p)) == nil)
+ return nil;
+ }
+ else
+ qreopen(p->iq);
+ if(p->oq == nil){
+ if((p->oq = qopen(8*1024, 0, uartkick, p)) == nil){
+ qfree(p->iq);
+ p->iq = nil;
+ return nil;
+ }
+ }
+ else
+ qreopen(p->oq);
+
+ p->ir = p->istage;
+ p->iw = p->istage;
+ p->ie = &p->istage[Stagesize];
+ p->op = p->ostage;
+ p->oe = p->ostage;
+
+ p->hup_dsr = p->hup_dcd = 0;
+ p->dsr = p->dcd = 0;
+
+ /* assume we can send */
+ p->cts = 1;
+ p->ctsbackoff = 0;
+
+ if(p->bits == 0)
+ uartctl(p, "l8");
+ if(p->stop == 0)
+ uartctl(p, "s1");
+ if(p->parity == 0)
+ uartctl(p, "pn");
+ if(p->baud == 0)
+ uartctl(p, "b9600");
+ (*p->phys->enable)(p, 1);
+
+ /*
+ * use ilock because uartclock can otherwise interrupt here
+ * and would hang on an attempt to lock uartalloc.
+ */
+ ilock(&uartalloc);
+ for(l = &uartalloc.elist; *l; l = &(*l)->elist){
+ if(*l == p)
+ break;
+ }
+ if(*l == 0){
+ p->elist = uartalloc.elist;
+ uartalloc.elist = p;
+ }
+ p->enabled = 1;
+ iunlock(&uartalloc);
+
+ return p;
+}
+
+static void
+uartdisable(Uart *p)
+{
+ Uart **l;
+
+ if(!p->enabled)
+ return;
+ (*p->phys->disable)(p);
+
+ ilock(&uartalloc);
+ for(l = &uartalloc.elist; *l; l = &(*l)->elist){
+ if(*l == p){
+ *l = p->elist;
+ break;
+ }
+ }
+ p->enabled = 0;
+ iunlock(&uartalloc);
+}
+
+void
+uartmouse(Uart* p, int (*putc)(Queue*, int), int setb1200)
+{
+ qlock(p);
+ if(p->opens++ == 0 && uartenable(p) == nil){
+ qunlock(p);
+ error(Enodev);
+ }
+ if(setb1200)
+ uartctl(p, "b1200");
+ p->putc = putc;
+ p->special = 1;
+ qunlock(p);
+}
+
+void
+uartsetmouseputc(Uart* p, int (*putc)(Queue*, int))
+{
+ qlock(p);
+ if(p->opens == 0 || p->special == 0){
+ qunlock(p);
+ error(Enodev);
+ }
+ p->putc = putc;
+ qunlock(p);
+}
+
+static void
+setlength(int i)
+{
+ Uart *p;
+
+ if(i > 0){
+ p = uart[i];
+ if(p && p->opens && p->iq)
+ uartdir[1+3*i].length = qlen(p->iq);
+ } else for(i = 0; i < uartnuart; i++){
+ p = uart[i];
+ if(p && p->opens && p->iq)
+ uartdir[1+3*i].length = qlen(p->iq);
+ }
+}
+
+/*
+ * set up the '#t' directory
+ */
+static void
+uartreset(void)
+{
+ int i;
+ Dirtab *dp;
+ Uart *p, *tail;
+
+ tail = nil;
+ for(i = 0; physuart[i] != nil; i++){
+ if(physuart[i]->pnp == nil)
+ continue;
+ if((p = physuart[i]->pnp()) == nil)
+ continue;
+ if(uartlist != nil)
+ tail->next = p;
+ else
+ uartlist = p;
+ for(tail = p; tail->next != nil; tail = tail->next)
+ uartnuart++;
+ uartnuart++;
+ }
+
+ if(uartnuart)
+ uart = xalloc(uartnuart*sizeof(Uart*));
+
+ uartndir = 1 + 3*uartnuart;
+ uartdir = xalloc(uartndir * sizeof(Dirtab));
+ if (uart == nil || uartdir == nil)
+ panic("uartreset: no memory");
+ dp = uartdir;
+ strcpy(dp->name, ".");
+ mkqid(&dp->qid, 0, 0, QTDIR);
+ dp->length = 0;
+ dp->perm = DMDIR|0555;
+ dp++;
+ p = uartlist;
+ for(i = 0; i < uartnuart; i++){
+ /* 3 directory entries per port */
+ snprint(dp->name, sizeof dp->name, "eia%d", i);
+ dp->qid.path = NETQID(i, Ndataqid);
+ dp->perm = 0660;
+ dp++;
+ snprint(dp->name, sizeof dp->name, "eia%dctl", i);
+ dp->qid.path = NETQID(i, Nctlqid);
+ dp->perm = 0660;
+ dp++;
+ snprint(dp->name, sizeof dp->name, "eia%dstatus", i);
+ dp->qid.path = NETQID(i, Nstatqid);
+ dp->perm = 0444;
+ dp++;
+
+ uart[i] = p;
+ p->dev = i;
+ if(p->console || p->special){
+ if(uartenable(p) != nil){
+ if(p->console){
+ kbdq = p->iq;
+ serialoq = p->oq;
+ p->putc = kbdcr2nl;
+ }
+ p->opens++;
+ }
+ }
+ p = p->next;
+ }
+
+ if(uartnuart){
+ /*
+ * at 115200 baud, the 1024 char buffer takes 56 ms to process,
+ * processing it every 22 ms should be fine.
+ */
+ uarttimer = addclock0link(uartclock, 22);
+ }
+}
+
+
+static Chan*
+uartattach(char *spec)
+{
+ return devattach('t', spec);
+}
+
+static Walkqid*
+uartwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, uartdir, uartndir, devgen);
+}
+
+static int
+uartstat(Chan *c, uchar *dp, int n)
+{
+ if(NETTYPE(c->qid.path) == Ndataqid)
+ setlength(NETID(c->qid.path));
+ return devstat(c, dp, n, uartdir, uartndir, devgen);
+}
+
+static Chan*
+uartopen(Chan *c, int omode)
+{
+ Uart *p;
+
+ c = devopen(c, omode, uartdir, uartndir, devgen);
+
+ switch(NETTYPE(c->qid.path)){
+ case Nctlqid:
+ case Ndataqid:
+ p = uart[NETID(c->qid.path)];
+ qlock(p);
+ if(p->opens++ == 0 && uartenable(p) == nil){
+ qunlock(p);
+ c->flag &= ~COPEN;
+ error(Enodev);
+ }
+ qunlock(p);
+ break;
+ }
+
+ c->iounit = qiomaxatomic;
+ return c;
+}
+
+static int
+uartdrained(void* arg)
+{
+ Uart *p;
+
+ p = arg;
+ return qlen(p->oq) == 0 && p->op == p->oe;
+}
+
+static void
+uartdrainoutput(Uart *p)
+{
+ if(!p->enabled)
+ return;
+
+ p->drain = 1;
+ if(waserror()){
+ p->drain = 0;
+ nexterror();
+ }
+ sleep(&p->r, uartdrained, p);
+ poperror();
+}
+
+static void
+uartclose(Chan *c)
+{
+ Uart *p;
+
+ if(c->qid.type & QTDIR)
+ return;
+ if((c->flag & COPEN) == 0)
+ return;
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ case Nctlqid:
+ p = uart[NETID(c->qid.path)];
+ qlock(p);
+ if(--(p->opens) == 0){
+ qclose(p->iq);
+ ilock(&p->rlock);
+ p->ir = p->iw = p->istage;
+ iunlock(&p->rlock);
+
+ /*
+ */
+ qhangup(p->oq, nil);
+ if(!waserror()){
+ uartdrainoutput(p);
+ poperror();
+ }
+ qclose(p->oq);
+ uartdisable(p);
+ p->dcd = p->dsr = p->dohup = 0;
+ }
+ qunlock(p);
+ break;
+ }
+}
+
+static long
+uartread(Chan *c, void *buf, long n, vlong off)
+{
+ Uart *p;
+ ulong offset = off;
+
+ if(c->qid.type & QTDIR){
+ setlength(-1);
+ return devdirread(c, buf, n, uartdir, uartndir, devgen);
+ }
+
+ p = uart[NETID(c->qid.path)];
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ return qread(p->iq, buf, n);
+ case Nctlqid:
+ return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE);
+ case Nstatqid:
+ return (*p->phys->status)(p, buf, n, offset);
+ }
+
+ return 0;
+}
+
+int
+uartctl(Uart *p, char *cmd)
+{
+ char *f[16];
+ int i, n, nf;
+
+ nf = tokenize(cmd, f, nelem(f));
+ for(i = 0; i < nf; i++){
+ if(strncmp(f[i], "break", 5) == 0){
+ (*p->phys->dobreak)(p, 0);
+ continue;
+ }
+
+ n = atoi(f[i]+1);
+ switch(*f[i]){
+ case 'B':
+ case 'b':
+ uartdrainoutput(p);
+ if((*p->phys->baud)(p, n) < 0)
+ return -1;
+ break;
+ case 'C':
+ case 'c':
+ p->hup_dcd = n;
+ break;
+ case 'D':
+ case 'd':
+ uartdrainoutput(p);
+ (*p->phys->dtr)(p, n);
+ break;
+ case 'E':
+ case 'e':
+ p->hup_dsr = n;
+ break;
+ case 'f':
+ case 'F':
+ if(p->oq != nil)
+ qflush(p->oq);
+ break;
+ case 'H':
+ case 'h':
+ if(p->iq != nil)
+ qhangup(p->iq, 0);
+ if(p->oq != nil)
+ qhangup(p->oq, 0);
+ break;
+ case 'i':
+ case 'I':
+ uartdrainoutput(p);
+ (*p->phys->fifo)(p, n);
+ break;
+ case 'K':
+ case 'k':
+ uartdrainoutput(p);
+ (*p->phys->dobreak)(p, n);
+ break;
+ case 'L':
+ case 'l':
+ uartdrainoutput(p);
+ if((*p->phys->bits)(p, n) < 0)
+ return -1;
+ break;
+ case 'm':
+ case 'M':
+ uartdrainoutput(p);
+ (*p->phys->modemctl)(p, n);
+ break;
+ case 'n':
+ case 'N':
+ if(p->oq != nil)
+ qnoblock(p->oq, n);
+ break;
+ case 'P':
+ case 'p':
+ uartdrainoutput(p);
+ if((*p->phys->parity)(p, *(f[i]+1)) < 0)
+ return -1;
+ break;
+ case 'Q':
+ case 'q':
+ if(p->iq != nil)
+ qsetlimit(p->iq, n);
+ if(p->oq != nil)
+ qsetlimit(p->oq, n);
+ break;
+ case 'R':
+ case 'r':
+ uartdrainoutput(p);
+ (*p->phys->rts)(p, n);
+ break;
+ case 'S':
+ case 's':
+ uartdrainoutput(p);
+ if((*p->phys->stop)(p, n) < 0)
+ return -1;
+ break;
+ case 'W':
+ case 'w':
+ if(uarttimer == nil || n < 1)
+ return -1;
+ uarttimer->tns = (vlong)n * 100000LL;
+ break;
+ case 'X':
+ case 'x':
+ if(p->enabled){
+ ilock(&p->tlock);
+ p->xonoff = n;
+ iunlock(&p->tlock);
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+static long
+uartwrite(Chan *c, void *buf, long n, vlong)
+{
+ Uart *p;
+ char *cmd;
+
+ if(c->qid.type & QTDIR)
+ error(Eperm);
+
+ p = uart[NETID(c->qid.path)];
+
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ qlock(p);
+ if(waserror()){
+ qunlock(p);
+ nexterror();
+ }
+
+ n = qwrite(p->oq, buf, n);
+
+ qunlock(p);
+ poperror();
+ break;
+ case Nctlqid:
+ cmd = malloc(n+1);
+ memmove(cmd, buf, n);
+ cmd[n] = 0;
+ qlock(p);
+ if(waserror()){
+ qunlock(p);
+ free(cmd);
+ nexterror();
+ }
+
+ /* let output drain */
+ if(uartctl(p, cmd) < 0)
+ error(Ebadarg);
+
+ qunlock(p);
+ poperror();
+ free(cmd);
+ break;
+ }
+
+ return n;
+}
+
+static int
+uartwstat(Chan *c, uchar *dp, int n)
+{
+ Dir d;
+ Dirtab *dt;
+
+ if(!iseve())
+ error(Eperm);
+ if(QTDIR & c->qid.type)
+ error(Eperm);
+ if(NETTYPE(c->qid.path) == Nstatqid)
+ error(Eperm);
+
+ dt = &uartdir[1 + 3 * NETID(c->qid.path)];
+ n = convM2D(dp, n, &d, nil);
+ if(n == 0)
+ error(Eshortstat);
+ if(d.mode != ~0UL)
+ dt[0].perm = dt[1].perm = d.mode;
+ return n;
+}
+
+void
+uartpower(int on)
+{
+ Uart *p;
+
+ for(p = uartlist; p != nil; p = p->next) {
+ if(p->phys->power)
+ (*p->phys->power)(p, on);
+ }
+}
+
+Dev uartdevtab = {
+ 't',
+ "uart",
+
+ uartreset,
+ devinit,
+ devshutdown,
+ uartattach,
+ uartwalk,
+ uartstat,
+ uartopen,
+ devcreate,
+ uartclose,
+ uartread,
+ devbread,
+ uartwrite,
+ devbwrite,
+ devremove,
+ uartwstat,
+ uartpower,
+};
+
+/*
+ * restart input if it's off
+ */
+static void
+uartflow(void *v)
+{
+ Uart *p;
+
+ p = v;
+ if(p->modem)
+ (*p->phys->rts)(p, 1);
+}
+
+/*
+ * put some bytes into the local queue to avoid calling
+ * qconsume for every character
+ */
+int
+uartstageoutput(Uart *p)
+{
+ int n;
+
+ n = qconsume(p->oq, p->ostage, Stagesize);
+ if(n <= 0)
+ return 0;
+ p->op = p->ostage;
+ p->oe = p->ostage + n;
+ return n;
+}
+
+/*
+ * restart output
+ */
+void
+uartkick(void *v)
+{
+ Uart *p = v;
+
+ if(p->blocked)
+ return;
+
+ ilock(&p->tlock);
+ (*p->phys->kick)(p);
+ iunlock(&p->tlock);
+
+ if(p->drain && uartdrained(p)){
+ p->drain = 0;
+ wakeup(&p->r);
+ }
+}
+
+/*
+ * Move data from the interrupt staging area to
+ * the input Queue.
+ */
+static void
+uartstageinput(Uart *p)
+{
+ int n;
+ uchar *ir, *iw;
+
+ while(p->ir != p->iw){
+ ir = p->ir;
+ if(p->ir > p->iw){
+ iw = p->ie;
+ p->ir = p->istage;
+ }
+ else{
+ iw = p->iw;
+ p->ir = p->iw;
+ }
+ if((n = qproduce(p->iq, ir, iw - ir)) < 0){
+ p->serr++;
+ (*p->phys->rts)(p, 0);
+ }
+ else if(n == 0)
+ p->berr++;
+ }
+}
+
+/*
+ * receive a character at interrupt time
+ */
+void
+uartrecv(Uart *p, char ch)
+{
+ uchar *next;
+
+ /* software flow control */
+ if(p->xonoff){
+ if(ch == CTLS){
+ p->blocked = 1;
+ }else if(ch == CTLQ){
+ p->blocked = 0;
+ p->ctsbackoff = 2; /* clock gets output going again */
+ }
+ }
+
+ /* receive the character */
+ if(p->putc)
+ p->putc(p->iq, ch);
+ else if (p->iw) { /* maybe the line isn't enabled yet */
+ ilock(&p->rlock);
+ next = p->iw + 1;
+ if(next == p->ie)
+ next = p->istage;
+ if(next == p->ir)
+ uartstageinput(p);
+ if(next != p->ir){
+ *p->iw = ch;
+ p->iw = next;
+ }
+ iunlock(&p->rlock);
+ }
+}
+
+/*
+ * we save up input characters till clock time to reduce
+ * per character interrupt overhead.
+ */
+static void
+uartclock(void)
+{
+ Uart *p;
+
+ ilock(&uartalloc);
+ for(p = uartalloc.elist; p; p = p->elist){
+
+ /* this hopefully amortizes cost of qproduce to many chars */
+ if(p->iw != p->ir){
+ ilock(&p->rlock);
+ uartstageinput(p);
+ iunlock(&p->rlock);
+ }
+
+ /* hang up if requested */
+ if(p->dohup){
+ qhangup(p->iq, 0);
+ qhangup(p->oq, 0);
+ p->dohup = 0;
+ }
+
+ /* this adds hysteresis to hardware/software flow control */
+ if(p->ctsbackoff){
+ ilock(&p->tlock);
+ if(p->ctsbackoff){
+ if(--(p->ctsbackoff) == 0)
+ (*p->phys->kick)(p);
+ }
+ iunlock(&p->tlock);
+ }
+ }
+ iunlock(&uartalloc);
+}
+
+/*
+ * polling console input, output
+ */
+
+Uart* consuart;
+
+int
+uartgetc(void)
+{
+ if(consuart == nil || consuart->phys->getc == nil)
+ return -1;
+ return consuart->phys->getc(consuart);
+}
+
+void
+uartputc(int c)
+{
+ if(consuart == nil || consuart->phys->putc == nil)
+ return;
+ consuart->phys->putc(consuart, c);
+}
+
+void
+uartputs(char *s, int n)
+{
+ char *e;
+
+ if(consuart == nil || consuart->phys->putc == nil)
+ return;
+
+ e = s+n;
+ for(; s<e; s++){
+ if(*s == '\n')
+ consuart->phys->putc(consuart, '\r');
+ consuart->phys->putc(consuart, *s);
+ }
+}
diff --git a/sys/src/9/port/devwd.c b/sys/src/9/port/devwd.c
new file mode 100755
index 000000000..30529e2f4
--- /dev/null
+++ b/sys/src/9/port/devwd.c
@@ -0,0 +1,156 @@
+/*
+ * watchdog framework
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+enum {
+ Qdir,
+ Qwdctl,
+};
+
+static Watchdog *wd;
+static Dirtab wddir[] = {
+ ".", { Qdir, 0, QTDIR }, 0, 0550,
+ "wdctl", { Qwdctl, 0 }, 0, 0660,
+};
+
+
+void
+addwatchdog(Watchdog *watchdog)
+{
+ if(wd){
+ print("addwatchdog: watchdog already installed\n");
+ return;
+ }
+ wd = watchdog;
+ if(wd)
+ wd->disable();
+}
+
+static Chan*
+wdattach(char *spec)
+{
+ return devattach('w', spec);
+}
+
+static Walkqid*
+wdwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, wddir, nelem(wddir), devgen);
+}
+
+static int
+wdstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, wddir, nelem(wddir), devgen);
+}
+
+static Chan*
+wdopen(Chan* c, int omode)
+{
+ return devopen(c, omode, wddir, nelem(wddir), devgen);
+}
+
+static void
+wdclose(Chan*)
+{
+}
+
+static long
+wdread(Chan* c, void* a, long n, vlong off)
+{
+ ulong offset = off;
+ char *p;
+
+ switch((ulong)c->qid.path){
+ case Qdir:
+ return devdirread(c, a, n, wddir, nelem(wddir), devgen);
+
+ case Qwdctl:
+ if(wd == nil || wd->stat == nil)
+ return 0;
+
+ p = malloc(READSTR);
+ if(waserror()){
+ free(p);
+ nexterror();
+ }
+
+ wd->stat(p, p + READSTR);
+ n = readstr(offset, a, n, p);
+ free(p);
+ poperror();
+ return n;
+
+ default:
+ error(Egreg);
+ break;
+ }
+ return 0;
+}
+
+static long
+wdwrite(Chan* c, void* a, long n, vlong off)
+{
+ ulong offset = off;
+ char *p;
+
+ switch((ulong)c->qid.path){
+ case Qdir:
+ error(Eperm);
+
+ case Qwdctl:
+ if(wd == nil)
+ return n;
+
+ if(offset || n >= READSTR)
+ error(Ebadarg);
+
+ if((p = strchr(a, '\n')) != nil)
+ *p = 0;
+
+ if(strncmp(a, "enable", n) == 0)
+ wd->enable();
+ else if(strncmp(a, "disable", n) == 0)
+ wd->disable();
+ else if(strncmp(a, "restart", n) == 0)
+ wd->restart();
+ else
+ error(Ebadarg);
+ return n;
+
+ default:
+ error(Egreg);
+ break;
+ }
+
+ return 0;
+}
+
+Dev wddevtab = {
+ 'w',
+ "watchdog",
+
+ devreset,
+ devinit,
+ devshutdown,
+ wdattach,
+ wdwalk,
+ wdstat,
+ wdopen,
+ devcreate,
+ wdclose,
+ wdread,
+ devbread,
+ wdwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+ devpower,
+};
diff --git a/sys/src/9/port/ecc.c b/sys/src/9/port/ecc.c
new file mode 100755
index 000000000..3f0e5ec3e
--- /dev/null
+++ b/sys/src/9/port/ecc.c
@@ -0,0 +1,119 @@
+/* error correcting code for nand flash */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "nandecc.h"
+
+#define CORRECTABLEMASK 0x545555
+
+static uchar ecctab[] = {
+ 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
+ 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
+ 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
+ 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
+ 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
+ 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
+ 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
+ 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
+ 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
+ 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
+ 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
+ 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
+ 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
+ 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
+ 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
+ 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
+ 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
+ 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
+ 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
+ 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
+ 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
+ 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
+ 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
+ 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
+ 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
+ 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
+ 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
+ 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
+ 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
+ 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
+ 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
+ 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
+};
+
+ulong
+nandecc(uchar *buf)
+{
+ int cp, zeros, ones, im, lp, om, i;
+
+ cp = 0xff;
+ zeros = 0xff;
+ ones = 0xff;
+ for (i = 0; i < 256; i++) {
+ int tabent = ecctab[buf[i]];
+
+ cp ^= tabent;
+ if (tabent & 1) {
+ zeros ^= ~i;
+ ones ^= i;
+ }
+ }
+ lp = 0;
+ for (im = 0x80, om = 0x8000; im; im >>= 1, om >>= 1) {
+ if (ones & im)
+ lp |= om;
+ om >>= 1;
+ if (zeros & im)
+ lp |= om;
+ }
+ return (((cp & 0xff) | 3) << 16) | lp;
+}
+
+NandEccError
+nandecccorrect(uchar *buf, ulong calcecc, ulong *storedecc, int reportbad)
+{
+ ulong xorecc, mask;
+ int k;
+
+ if (calcecc == *storedecc)
+ return NandEccErrorGood;
+ if (reportbad)
+ print("nandecccorrect: calculated ecc %.8lux stored ecc %.8lux\n",
+ calcecc, *storedecc);
+ xorecc = calcecc ^ *storedecc;
+ if (((xorecc ^ (xorecc >> 1)) & CORRECTABLEMASK) == CORRECTABLEMASK) {
+ ulong imask;
+ ushort out, omask;
+ int line, col;
+
+ for (imask = 0x800000, omask = 0x800, out = 0; imask;
+ imask >>= 2, omask >>= 1)
+ if (xorecc & imask)
+ out |= omask;
+ line = out & 0xff;
+ col = out >> 9;
+ if (reportbad)
+ print("nandecccorrect: single bit error line %d col %d\n",
+ line, col);
+ buf[line] ^= (1 << col);
+ *storedecc = calcecc;
+ return NandEccErrorOneBit;
+ }
+ for (mask = 0x800000, k = 0; mask; mask >>= 1)
+ if (mask & xorecc)
+ k++;
+ if (k == 1) {
+ if (reportbad)
+ print("nandecccorrect: single bit error in ecc\n");
+ /* assume the stored ecc was wrong */
+ *storedecc = calcecc;
+ return NandEccErrorOneBitInEcc;
+ }
+ if (reportbad)
+ print("nandecccorrect: 2 bit error\n");
+ return NandEccErrorBad;
+}
diff --git a/sys/src/9/port/edf.c b/sys/src/9/port/edf.c
new file mode 100755
index 000000000..a9fc4b854
--- /dev/null
+++ b/sys/src/9/port/edf.c
@@ -0,0 +1,679 @@
+/* EDF scheduling */
+#include <u.h>
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "../port/edf.h"
+#include <trace.h>
+
+/* debugging */
+enum {
+ Dontprint = 1,
+};
+
+#define DPRINT if(Dontprint){}else print
+
+static long now; /* Low order 32 bits of time in µs */
+extern ulong delayedscheds;
+extern Schedq runq[Nrq];
+extern int nrdy;
+extern ulong runvec;
+
+/* Statistics stuff */
+ulong nilcount;
+ulong scheds;
+ulong edfnrun;
+int misseddeadlines;
+
+/* Edfschedlock protects modification of admission params */
+int edfinited;
+QLock edfschedlock;
+static Lock thelock;
+
+enum{
+ Dl, /* Invariant for schedulability test: Dl < Rl */
+ Rl,
+};
+
+static char *testschedulability(Proc*);
+static Proc *qschedulability;
+
+enum {
+ Onemicrosecond = 1,
+ Onemillisecond = 1000,
+ Onesecond = 1000000,
+ OneRound = Onemillisecond/2,
+};
+
+static int
+timeconv(Fmt *f)
+{
+ char buf[128], *sign;
+ vlong t;
+
+ buf[0] = 0;
+ switch(f->r) {
+ case 'U':
+ t = va_arg(f->args, uvlong);
+ break;
+ case 't': /* vlong in nanoseconds */
+ t = va_arg(f->args, long);
+ break;
+ default:
+ return fmtstrcpy(f, "(timeconv)");
+ }
+ if (t < 0) {
+ sign = "-";
+ t = -t;
+ }
+ else
+ sign = "";
+ if (t > Onesecond){
+ t += OneRound;
+ sprint(buf, "%s%d.%.3ds", sign, (int)(t / Onesecond),
+ (int)(t % Onesecond)/Onemillisecond);
+ }else if (t > Onemillisecond)
+ sprint(buf, "%s%d.%.3dms", sign, (int)(t / Onemillisecond),
+ (int)(t % Onemillisecond));
+ else
+ sprint(buf, "%s%dµs", sign, (int)t);
+ return fmtstrcpy(f, buf);
+}
+
+long edfcycles;
+
+Edf*
+edflock(Proc *p)
+{
+ Edf *e;
+
+ if (p->edf == nil)
+ return nil;
+ ilock(&thelock);
+ if((e = p->edf) && (e->flags & Admitted)){
+ thelock.pc = getcallerpc(&p);
+#ifdef EDFCYCLES
+ edfcycles -= lcycles();
+#endif
+ now = µs();
+ return e;
+ }
+ iunlock(&thelock);
+ return nil;
+}
+
+void
+edfunlock(void)
+{
+
+#ifdef EDFCYCLES
+ edfcycles += lcycles();
+#endif
+ edfnrun++;
+ iunlock(&thelock);
+}
+
+void
+edfinit(Proc*p)
+{
+ if(!edfinited){
+ fmtinstall('t', timeconv);
+ edfinited++;
+ }
+ now = µs();
+ DPRINT("%lud edfinit %lud[%s]\n", now, p->pid, statename[p->state]);
+ p->edf = malloc(sizeof(Edf));
+ if(p->edf == nil)
+ error(Enomem);
+ return;
+}
+
+static void
+deadlineintr(Ureg*, Timer *t)
+{
+ /* Proc reached deadline */
+ extern int panicking;
+ Proc *p;
+ void (*pt)(Proc*, int, vlong);
+
+ if(panicking || active.exiting)
+ return;
+
+ p = t->ta;
+ now = µs();
+ DPRINT("%lud deadlineintr %lud[%s]\n", now, p->pid, statename[p->state]);
+ /* If we're interrupting something other than the proc pointed to by t->a,
+ * we've already achieved recheduling, so we need not do anything
+ * Otherwise, we must cause a reschedule, but if we call sched()
+ * here directly, the timer interrupt routine will not finish its business
+ * Instead, we cause the resched to happen when the interrupted proc
+ * returns to user space
+ */
+ if(p == up){
+ if(up->trace && (pt = proctrace))
+ pt(up, SInts, 0);
+ up->delaysched++;
+ delayedscheds++;
+ }
+}
+
+static void
+release(Proc *p)
+{
+ /* Called with edflock held */
+ Edf *e;
+ void (*pt)(Proc*, int, vlong);
+ long n;
+ vlong nowns;
+
+ e = p->edf;
+ e->flags &= ~Yield;
+ if(e->d - now < 0){
+ e->periods++;
+ e->r = now;
+ if((e->flags & Sporadic) == 0){
+ /*
+ * Non sporadic processes stay true to their period;
+ * calculate next release time.
+ * Second test limits duration of while loop.
+ */
+ if((n = now - e->t) > 0){
+ if(n < e->T)
+ e->t += e->T;
+ else
+ e->t = now + e->T - (n % e->T);
+ }
+ }else{
+ /* Sporadic processes may not be released earlier than
+ * one period after this release
+ */
+ e->t = e->r + e->T;
+ }
+ e->d = e->r + e->D;
+ e->S = e->C;
+ DPRINT("%lud release %lud[%s], r=%lud, d=%lud, t=%lud, S=%lud\n",
+ now, p->pid, statename[p->state], e->r, e->d, e->t, e->S);
+ if(pt = proctrace){
+ nowns = todget(nil);
+ pt(p, SRelease, nowns);
+ pt(p, SDeadline, nowns + 1000LL*e->D);
+ }
+ }else{
+ DPRINT("%lud release %lud[%s], too late t=%lud, called from %#p\n",
+ now, p->pid, statename[p->state], e->t, getcallerpc(&p));
+ }
+}
+
+static void
+releaseintr(Ureg*, Timer *t)
+{
+ Proc *p;
+ extern int panicking;
+ Schedq *rq;
+
+ if(panicking || active.exiting)
+ return;
+
+ p = t->ta;
+ if((edflock(p)) == nil)
+ return;
+ DPRINT("%lud releaseintr %lud[%s]\n", now, p->pid, statename[p->state]);
+ switch(p->state){
+ default:
+ edfunlock();
+ return;
+ case Ready:
+ /* remove proc from current runq */
+ rq = &runq[p->priority];
+ if(dequeueproc(rq, p) != p){
+ DPRINT("releaseintr: can't find proc or lock race\n");
+ release(p); /* It'll start best effort */
+ edfunlock();
+ return;
+ }
+ p->state = Waitrelease;
+ /* fall through */
+ case Waitrelease:
+ release(p);
+ edfunlock();
+ if(p->state == Wakeme){
+ iprint("releaseintr: wakeme\n");
+ }
+ ready(p);
+ if(up){
+ up->delaysched++;
+ delayedscheds++;
+ }
+ return;
+ case Running:
+ release(p);
+ edfrun(p, 1);
+ break;
+ case Wakeme:
+ release(p);
+ edfunlock();
+ if(p->trend)
+ wakeup(p->trend);
+ p->trend = nil;
+ if(up){
+ up->delaysched++;
+ delayedscheds++;
+ }
+ return;
+ }
+ edfunlock();
+}
+
+void
+edfrecord(Proc *p)
+{
+ long used;
+ Edf *e;
+ void (*pt)(Proc*, int, vlong);
+
+ if((e = edflock(p)) == nil)
+ return;
+ used = now - e->s;
+ if(e->d - now <= 0)
+ e->edfused += used;
+ else
+ e->extraused += used;
+ if(e->S > 0){
+ if(e->S <= used){
+ if(pt = proctrace)
+ pt(p, SSlice, 0);
+ DPRINT("%lud edfrecord slice used up\n", now);
+ e->d = now;
+ e->S = 0;
+ }else
+ e->S -= used;
+ }
+ e->s = now;
+ edfunlock();
+}
+
+void
+edfrun(Proc *p, int edfpri)
+{
+ Edf *e;
+ void (*pt)(Proc*, int, vlong);
+ long tns;
+
+ e = p->edf;
+ /* Called with edflock held */
+ if(edfpri){
+ tns = e->d - now;
+ if(tns <= 0 || e->S == 0){
+ /* Deadline reached or resources exhausted,
+ * deschedule forthwith
+ */
+ p->delaysched++;
+ delayedscheds++;
+ e->s = now;
+ return;
+ }
+ if(e->S < tns)
+ tns = e->S;
+ if(tns < 20)
+ tns = 20;
+ e->tns = 1000LL * tns; /* µs to ns */
+ if(e->tt == nil || e->tf != deadlineintr){
+ DPRINT("%lud edfrun, deadline=%lud\n", now, tns);
+ }else{
+ DPRINT("v");
+ }
+ if(p->trace && (pt = proctrace))
+ pt(p, SInte, todget(nil) + e->tns);
+ e->tmode = Trelative;
+ e->tf = deadlineintr;
+ e->ta = p;
+ timeradd(e);
+ }else{
+ DPRINT("<");
+ }
+ e->s = now;
+}
+
+char *
+edfadmit(Proc *p)
+{
+ char *err;
+ Edf *e;
+ int i;
+ Proc *r;
+ void (*pt)(Proc*, int, vlong);
+ long tns;
+
+ e = p->edf;
+ if (e->flags & Admitted)
+ return "task state"; /* should never happen */
+
+ /* simple sanity checks */
+ if (e->T == 0)
+ return "T not set";
+ if (e->C == 0)
+ return "C not set";
+ if (e->D > e->T)
+ return "D > T";
+ if (e->D == 0) /* if D is not set, set it to T */
+ e->D = e->T;
+ if (e->C > e->D)
+ return "C > D";
+
+ qlock(&edfschedlock);
+ if (err = testschedulability(p)){
+ qunlock(&edfschedlock);
+ return err;
+ }
+ e->flags |= Admitted;
+
+ edflock(p);
+
+ if(p->trace && (pt = proctrace))
+ pt(p, SAdmit, 0);
+
+ /* Look for another proc with the same period to synchronize to */
+ SET(r);
+ for(i=0; i<conf.nproc; i++) {
+ r = proctab(i);
+ if(r->state == Dead || r == p)
+ continue;
+ if (r->edf == nil || (r->edf->flags & Admitted) == 0)
+ continue;
+ if (r->edf->T == e->T)
+ break;
+ }
+ if (i == conf.nproc){
+ /* Can't synchronize to another proc, release now */
+ e->t = now;
+ e->d = 0;
+ release(p);
+ if (p == up){
+ DPRINT("%lud edfadmit self %lud[%s], release now: r=%lud d=%lud t=%lud\n",
+ now, p->pid, statename[p->state], e->r, e->d, e->t);
+ /* We're already running */
+ edfrun(p, 1);
+ }else{
+ /* We're releasing another proc */
+ DPRINT("%lud edfadmit other %lud[%s], release now: r=%lud d=%lud t=%lud\n",
+ now, p->pid, statename[p->state], e->r, e->d, e->t);
+ p->ta = p;
+ edfunlock();
+ qunlock(&edfschedlock);
+ releaseintr(nil, p);
+ return nil;
+ }
+ }else{
+ /* Release in synch to something else */
+ e->t = r->edf->t;
+ if (p == up){
+ DPRINT("%lud edfadmit self %lud[%s], release at %lud\n",
+ now, p->pid, statename[p->state], e->t);
+ edfunlock();
+ qunlock(&edfschedlock);
+ return nil;
+ }else{
+ DPRINT("%lud edfadmit other %lud[%s], release at %lud\n",
+ now, p->pid, statename[p->state], e->t);
+ if(e->tt == nil){
+ e->tf = releaseintr;
+ e->ta = p;
+ tns = e->t - now;
+ if(tns < 20)
+ tns = 20;
+ e->tns = 1000LL * tns;
+ e->tmode = Trelative;
+ timeradd(e);
+ }
+ }
+ }
+ edfunlock();
+ qunlock(&edfschedlock);
+ return nil;
+}
+
+void
+edfstop(Proc *p)
+{
+ Edf *e;
+ void (*pt)(Proc*, int, vlong);
+
+ if(e = edflock(p)){
+ DPRINT("%lud edfstop %lud[%s]\n", now, p->pid, statename[p->state]);
+ if(p->trace && (pt = proctrace))
+ pt(p, SExpel, 0);
+ e->flags &= ~Admitted;
+ if(e->tt)
+ timerdel(e);
+ edfunlock();
+ }
+}
+
+static int
+yfn(void *)
+{
+ now = µs();
+ return up->trend == nil || now - up->edf->r >= 0;
+}
+
+void
+edfyield(void)
+{
+ /* sleep until next release */
+ Edf *e;
+ void (*pt)(Proc*, int, vlong);
+ long n;
+
+ if((e = edflock(up)) == nil)
+ return;
+ if(up->trace && (pt = proctrace))
+ pt(up, SYield, 0);
+ if((n = now - e->t) > 0){
+ if(n < e->T)
+ e->t += e->T;
+ else
+ e->t = now + e->T - (n % e->T);
+ }
+ e->r = e->t;
+ e->flags |= Yield;
+ e->d = now;
+ if (up->tt == nil){
+ n = e->t - now;
+ if(n < 20)
+ n = 20;
+ up->tns = 1000LL * n;
+ up->tf = releaseintr;
+ up->tmode = Trelative;
+ up->ta = up;
+ up->trend = &up->sleep;
+ timeradd(up);
+ }else if(up->tf != releaseintr)
+ print("edfyield: surprise! %#p\n", up->tf);
+ edfunlock();
+ sleep(&up->sleep, yfn, nil);
+}
+
+int
+edfready(Proc *p)
+{
+ Edf *e;
+ Schedq *rq;
+ Proc *l, *pp;
+ void (*pt)(Proc*, int, vlong);
+ long n;
+
+ if((e = edflock(p)) == nil)
+ return 0;
+
+ if(p->state == Wakeme && p->r){
+ iprint("edfready: wakeme\n");
+ }
+ if(e->d - now <= 0){
+ /* past deadline, arrange for next release */
+ if((e->flags & Sporadic) == 0){
+ /*
+ * Non sporadic processes stay true to their period;
+ * calculate next release time.
+ */
+ if((n = now - e->t) > 0){
+ if(n < e->T)
+ e->t += e->T;
+ else
+ e->t = now + e->T - (n % e->T);
+ }
+ }
+ if(now - e->t < 0){
+ /* Next release is in the future, schedule it */
+ if(e->tt == nil || e->tf != releaseintr){
+ n = e->t - now;
+ if(n < 20)
+ n = 20;
+ e->tns = 1000LL * n;
+ e->tmode = Trelative;
+ e->tf = releaseintr;
+ e->ta = p;
+ timeradd(e);
+ DPRINT("%lud edfready %lud[%s], release=%lud\n",
+ now, p->pid, statename[p->state], e->t);
+ }
+ if(p->state == Running && (e->flags & (Yield|Yieldonblock)) == 0 && (e->flags & Extratime)){
+ /* If we were running, we've overrun our CPU allocation
+ * or missed the deadline, continue running best-effort at low priority
+ * Otherwise we were blocked. If we don't yield on block, we continue
+ * best effort
+ */
+ DPRINT(">");
+ p->basepri = PriExtra;
+ p->fixedpri = 1;
+ edfunlock();
+ return 0; /* Stick on runq[PriExtra] */
+ }
+ DPRINT("%lud edfready %lud[%s] wait release at %lud\n",
+ now, p->pid, statename[p->state], e->t);
+ p->state = Waitrelease;
+ edfunlock();
+ return 1; /* Make runnable later */
+ }
+ DPRINT("%lud edfready %lud %s release now\n", now, p->pid, statename[p->state]);
+ /* release now */
+ release(p);
+ }
+ edfunlock();
+ DPRINT("^");
+ rq = &runq[PriEdf];
+ /* insert in queue in earliest deadline order */
+ lock(runq);
+ l = nil;
+ for(pp = rq->head; pp; pp = pp->rnext){
+ if(pp->edf->d > e->d)
+ break;
+ l = pp;
+ }
+ p->rnext = pp;
+ if (l == nil)
+ rq->head = p;
+ else
+ l->rnext = p;
+ if(pp == nil)
+ rq->tail = p;
+ rq->n++;
+ nrdy++;
+ runvec |= 1 << PriEdf;
+ p->priority = PriEdf;
+ p->readytime = m->ticks;
+ p->state = Ready;
+ unlock(runq);
+ if(p->trace && (pt = proctrace))
+ pt(p, SReady, 0);
+ return 1;
+}
+
+
+static void
+testenq(Proc *p)
+{
+ Proc *xp, **xpp;
+ Edf *e;
+
+ e = p->edf;
+ e->testnext = nil;
+ if (qschedulability == nil) {
+ qschedulability = p;
+ return;
+ }
+ SET(xp);
+ for (xpp = &qschedulability; *xpp; xpp = &xp->edf->testnext) {
+ xp = *xpp;
+ if (e->testtime - xp->edf->testtime < 0
+ || (e->testtime == xp->edf->testtime && e->testtype < xp->edf->testtype)){
+ e->testnext = xp;
+ *xpp = p;
+ return;
+ }
+ }
+ assert(xp->edf->testnext == nil);
+ xp->edf->testnext = p;
+}
+
+static char *
+testschedulability(Proc *theproc)
+{
+ Proc *p;
+ long H, G, Cb, ticks;
+ int steps, i;
+
+ /* initialize */
+ DPRINT("schedulability test %lud\n", theproc->pid);
+ qschedulability = nil;
+ for(i=0; i<conf.nproc; i++) {
+ p = proctab(i);
+ if(p->state == Dead)
+ continue;
+ if ((p->edf == nil || (p->edf->flags & Admitted) == 0) && p != theproc)
+ continue;
+ p->edf->testtype = Rl;
+ p->edf->testtime = 0;
+ DPRINT("\tInit: edfenqueue %lud\n", p->pid);
+ testenq(p);
+ }
+ H=0;
+ G=0;
+ for(steps = 0; steps < Maxsteps; steps++){
+ p = qschedulability;
+ qschedulability = p->edf->testnext;
+ ticks = p->edf->testtime;
+ switch (p->edf->testtype){
+ case Dl:
+ H += p->edf->C;
+ Cb = 0;
+ DPRINT("\tStep %3d, Ticks %lud, pid %lud, deadline, H += %lud → %lud, Cb = %lud\n",
+ steps, ticks, p->pid, p->edf->C, H, Cb);
+ if (H+Cb>ticks){
+ DPRINT("not schedulable\n");
+ return "not schedulable";
+ }
+ p->edf->testtime += p->edf->T - p->edf->D;
+ p->edf->testtype = Rl;
+ testenq(p);
+ break;
+ case Rl:
+ DPRINT("\tStep %3d, Ticks %lud, pid %lud, release, G %lud, C%lud\n",
+ steps, ticks, p->pid, p->edf->C, G);
+ if(ticks && G <= ticks){
+ DPRINT("schedulable\n");
+ return nil;
+ }
+ G += p->edf->C;
+ p->edf->testtime += p->edf->D;
+ p->edf->testtype = Dl;
+ testenq(p);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ DPRINT("probably not schedulable\n");
+ return "probably not schedulable";
+}
diff --git a/sys/src/9/port/edf.h b/sys/src/9/port/edf.h
new file mode 100755
index 000000000..b31aef28c
--- /dev/null
+++ b/sys/src/9/port/edf.h
@@ -0,0 +1,54 @@
+enum {
+ Maxsteps = 200 * 100 * 2, /* 100 periods of 200 procs */
+
+ /* Edf.flags field */
+ Admitted = 0x01,
+ Sporadic = 0x02,
+ Yieldonblock = 0x04,
+ Sendnotes = 0x08,
+ Deadline = 0x10,
+ Yield = 0x20,
+ Extratime = 0x40,
+
+ Infinity = ~0ULL,
+};
+
+typedef struct Edf Edf;
+
+struct Edf {
+ /* All times in µs */
+ /* time intervals */
+ long D; /* Deadline */
+ long Delta; /* Inherited deadline */
+ long T; /* period */
+ long C; /* Cost */
+ long S; /* Slice: time remaining in this period */
+ /* times (only low-order bits of absolute time) */
+ long r; /* (this) release time */
+ long d; /* (this) deadline */
+ long t; /* Start of next period, t += T at release */
+ long s; /* Time at which this proc was last scheduled */
+ /* for schedulability testing */
+ long testDelta;
+ int testtype; /* Release or Deadline */
+ long testtime;
+ Proc *testnext;
+ /* other */
+ ushort flags;
+ Timer;
+ /* Stats */
+ long edfused;
+ long extraused;
+ long aged;
+ ulong periods;
+ ulong missed;
+};
+
+extern Lock edftestlock; /* for atomic admitting/expelling */
+
+#pragma varargck type "t" long
+#pragma varargck type "U" uvlong
+
+/* Interface: */
+Edf* edflock(Proc*);
+void edfunlock(void);
diff --git a/sys/src/9/port/error.h b/sys/src/9/port/error.h
new file mode 100755
index 000000000..e9ff15023
--- /dev/null
+++ b/sys/src/9/port/error.h
@@ -0,0 +1,53 @@
+extern char Enoerror[]; /* no error */
+extern char Emount[]; /* inconsistent mount */
+extern char Eunmount[]; /* not mounted */
+extern char Eismtpt[]; /* is a mount point */
+extern char Eunion[]; /* not in union */
+extern char Emountrpc[]; /* mount rpc error */
+extern char Eshutdown[]; /* device shut down */
+extern char Enocreate[]; /* mounted directory forbids creation */
+extern char Enonexist[]; /* file does not exist */
+extern char Eexist[]; /* file already exists */
+extern char Ebadsharp[]; /* unknown device in # filename */
+extern char Enotdir[]; /* not a directory */
+extern char Eisdir[]; /* file is a directory */
+extern char Ebadchar[]; /* bad character in file name */
+extern char Efilename[]; /* file name syntax */
+extern char Eperm[]; /* permission denied */
+extern char Ebadusefd[]; /* inappropriate use of fd */
+extern char Ebadarg[]; /* bad arg in system call */
+extern char Einuse[]; /* device or object already in use */
+extern char Eio[]; /* i/o error */
+extern char Etoobig[]; /* read or write too large */
+extern char Etoosmall[]; /* read or write too small */
+extern char Enoport[]; /* network port not available */
+extern char Ehungup[]; /* i/o on hungup channel */
+extern char Ebadctl[]; /* bad process or channel control request */
+extern char Enodev[]; /* no free devices */
+extern char Eprocdied[]; /* process exited */
+extern char Enochild[]; /* no living children */
+extern char Eioload[]; /* i/o error in demand load */
+extern char Enovmem[]; /* virtual memory allocation failed */
+extern char Ebadfd[]; /* fd out of range or not open */
+extern char Enofd[]; /* no free file descriptors */
+extern char Eisstream[]; /* seek on a stream */
+extern char Ebadexec[]; /* exec header invalid */
+extern char Etimedout[]; /* connection timed out */
+extern char Econrefused[]; /* connection refused */
+extern char Econinuse[]; /* connection in use */
+extern char Eintr[]; /* interrupted */
+extern char Enomem[]; /* kernel allocate failed */
+extern char Enoswap[]; /* swap space full */
+extern char Esoverlap[]; /* segments overlap */
+extern char Emouseset[]; /* mouse type already set */
+extern char Eshort[]; /* i/o count too small */
+extern char Egreg[]; /* jmk added reentrancy for threads */
+extern char Ebadspec[]; /* bad attach specifier */
+extern char Enoreg[]; /* process has no saved registers */
+extern char Enoattach[]; /* mount/attach disallowed */
+extern char Eshortstat[]; /* stat buffer too small */
+extern char Ebadstat[]; /* malformed stat buffer */
+extern char Enegoff[]; /* negative i/o offset */
+extern char Ecmdargs[]; /* wrong #args in control message */
+extern char Ebadip[]; /* bad ip address syntax */
+extern char Edirseek[]; /* seek in directory */
diff --git a/sys/src/9/port/fault.c b/sys/src/9/port/fault.c
new file mode 100755
index 000000000..b6ae6e456
--- /dev/null
+++ b/sys/src/9/port/fault.c
@@ -0,0 +1,407 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+int
+fault(ulong addr, int read)
+{
+ Segment *s;
+ char *sps;
+
+ if(up == nil)
+ panic("fault: nil up");
+ if(up->nlocks.ref)
+ print("fault: nlocks %ld\n", up->nlocks.ref);
+
+ sps = up->psstate;
+ up->psstate = "Fault";
+ spllo();
+
+ m->pfault++;
+ for(;;) {
+ s = seg(up, addr, 1); /* leaves s->lk qlocked if seg != nil */
+ if(s == 0) {
+ up->psstate = sps;
+ return -1;
+ }
+
+ if(!read && (s->type&SG_RONLY)) {
+ qunlock(&s->lk);
+ up->psstate = sps;
+ return -1;
+ }
+
+ if(fixfault(s, addr, read, 1) == 0)
+ break;
+ }
+
+ up->psstate = sps;
+ return 0;
+}
+
+static void
+faulterror(char *s, Chan *c, int freemem)
+{
+ char buf[ERRMAX];
+
+ if(c && c->path){
+ snprint(buf, sizeof buf, "%s accessing %s: %s", s, c->path->s, up->errstr);
+ s = buf;
+ }
+ if(up->nerrlab) {
+ postnote(up, 1, s, NDebug);
+ error(s);
+ }
+ pexit(s, freemem);
+}
+
+void (*checkaddr)(ulong, Segment *, Page *);
+ulong addr2check;
+
+int
+fixfault(Segment *s, ulong addr, int read, int doputmmu)
+{
+ int type;
+ int ref;
+ Pte **p, *etp;
+ ulong mmuphys=0, soff;
+ Page **pg, *lkp, *new;
+ Page *(*fn)(Segment*, ulong);
+
+ addr &= ~(BY2PG-1);
+ soff = addr-s->base;
+ p = &s->map[soff/PTEMAPMEM];
+ if(*p == 0)
+ *p = ptealloc();
+
+ etp = *p;
+ pg = &etp->pages[(soff&(PTEMAPMEM-1))/BY2PG];
+ type = s->type&SG_TYPE;
+
+ if(pg < etp->first)
+ etp->first = pg;
+ if(pg > etp->last)
+ etp->last = pg;
+
+ switch(type) {
+ default:
+ panic("fault");
+ break;
+
+ case SG_TEXT: /* Demand load */
+ if(pagedout(*pg))
+ pio(s, addr, soff, pg);
+
+ mmuphys = PPN((*pg)->pa) | PTERONLY|PTEVALID;
+ (*pg)->modref = PG_REF;
+ break;
+
+ case SG_BSS:
+ case SG_SHARED: /* Zero fill on demand */
+ case SG_STACK:
+ if(*pg == 0) {
+ new = newpage(1, &s, addr);
+ if(s == 0)
+ return -1;
+
+ *pg = new;
+ }
+ goto common;
+
+ case SG_DATA:
+ common: /* Demand load/pagein/copy on write */
+ if(pagedout(*pg))
+ pio(s, addr, soff, pg);
+
+ /*
+ * It's only possible to copy on write if
+ * we're the only user of the segment.
+ */
+ if(read && conf.copymode == 0 && s->ref == 1) {
+ mmuphys = PPN((*pg)->pa)|PTERONLY|PTEVALID;
+ (*pg)->modref |= PG_REF;
+ break;
+ }
+
+ lkp = *pg;
+ lock(lkp);
+
+ if(lkp->image == &swapimage)
+ ref = lkp->ref + swapcount(lkp->daddr);
+ else
+ ref = lkp->ref;
+ if(ref > 1) {
+ unlock(lkp);
+
+ new = newpage(0, &s, addr);
+ if(s == 0)
+ return -1;
+ *pg = new;
+ copypage(lkp, *pg);
+ putpage(lkp);
+ }
+ else {
+ /* save a copy of the original for the image cache */
+ if(lkp->image)
+ duppage(lkp);
+
+ unlock(lkp);
+ }
+ mmuphys = PPN((*pg)->pa) | PTEWRITE | PTEVALID;
+ (*pg)->modref = PG_MOD|PG_REF;
+ break;
+
+ case SG_PHYSICAL:
+ if(*pg == 0) {
+ fn = s->pseg->pgalloc;
+ if(fn)
+ *pg = (*fn)(s, addr);
+ else {
+ new = smalloc(sizeof(Page));
+ new->va = addr;
+ new->pa = s->pseg->pa+(addr-s->base);
+ new->ref = 1;
+ *pg = new;
+ }
+ }
+
+ if (checkaddr && addr == addr2check)
+ (*checkaddr)(addr, s, *pg);
+ mmuphys = PPN((*pg)->pa) |PTEWRITE|PTEUNCACHED|PTEVALID;
+ (*pg)->modref = PG_MOD|PG_REF;
+ break;
+ }
+ qunlock(&s->lk);
+
+ if(doputmmu)
+ putmmu(addr, mmuphys, *pg);
+
+ return 0;
+}
+
+void
+pio(Segment *s, ulong addr, ulong soff, Page **p)
+{
+ Page *new;
+ KMap *k;
+ Chan *c;
+ int n, ask;
+ char *kaddr;
+ ulong daddr;
+ Page *loadrec;
+
+retry:
+ loadrec = *p;
+ if(loadrec == 0) { /* from a text/data image */
+ daddr = s->fstart+soff;
+ new = lookpage(s->image, daddr);
+ if(new != nil) {
+ *p = new;
+ return;
+ }
+
+ c = s->image->c;
+ ask = s->flen-soff;
+ if(ask > BY2PG)
+ ask = BY2PG;
+ }
+ else { /* from a swap image */
+ daddr = swapaddr(loadrec);
+ new = lookpage(&swapimage, daddr);
+ if(new != nil) {
+ putswap(loadrec);
+ *p = new;
+ return;
+ }
+
+ c = swapimage.c;
+ ask = BY2PG;
+ }
+ qunlock(&s->lk);
+
+ new = newpage(0, 0, addr);
+ k = kmap(new);
+ kaddr = (char*)VA(k);
+
+ while(waserror()) {
+ if(strcmp(up->errstr, Eintr) == 0)
+ continue;
+ kunmap(k);
+ putpage(new);
+ faulterror(Eioload, c, 0);
+ }
+
+ n = devtab[c->type]->read(c, kaddr, ask, daddr);
+ if(n != ask)
+ faulterror(Eioload, c, 0);
+ if(ask < BY2PG)
+ memset(kaddr+ask, 0, BY2PG-ask);
+
+ poperror();
+ kunmap(k);
+ qlock(&s->lk);
+ if(loadrec == 0) { /* This is demand load */
+ /*
+ * race, another proc may have gotten here first while
+ * s->lk was unlocked
+ */
+ if(*p == 0) {
+ new->daddr = daddr;
+ cachepage(new, s->image);
+ *p = new;
+ }
+ else
+ putpage(new);
+ }
+ else { /* This is paged out */
+ /*
+ * race, another proc may have gotten here first
+ * (and the pager may have run on that page) while
+ * s->lk was unlocked
+ */
+ if(*p != loadrec){
+ if(!pagedout(*p)){
+ /* another process did it for me */
+ putpage(new);
+ goto done;
+ } else {
+ /* another process and the pager got in */
+ putpage(new);
+ goto retry;
+ }
+ }
+
+ new->daddr = daddr;
+ cachepage(new, &swapimage);
+ *p = new;
+ putswap(loadrec);
+ }
+
+done:
+ if(s->flushme)
+ memset((*p)->cachectl, PG_TXTFLUSH, sizeof((*p)->cachectl));
+}
+
+/*
+ * Called only in a system call
+ */
+int
+okaddr(ulong addr, ulong len, int write)
+{
+ Segment *s;
+
+ if((long)len >= 0) {
+ for(;;) {
+ s = seg(up, addr, 0);
+ if(s == 0 || (write && (s->type&SG_RONLY)))
+ break;
+
+ if(addr+len > s->top) {
+ len -= s->top - addr;
+ addr = s->top;
+ continue;
+ }
+ return 1;
+ }
+ }
+ pprint("suicide: invalid address %#lux/%lud in sys call pc=%#lux\n", addr, len, userpc());
+ return 0;
+}
+
+void
+validaddr(ulong addr, ulong len, int write)
+{
+ if(!okaddr(addr, len, write)){
+ postnote(up, 1, "sys: bad address in syscall", NDebug);
+ error(Ebadarg);
+ }
+}
+
+/*
+ * &s[0] is known to be a valid address.
+ */
+void*
+vmemchr(void *s, int c, int n)
+{
+ int m;
+ ulong a;
+ void *t;
+
+ a = (ulong)s;
+ while(PGROUND(a) != PGROUND(a+n-1)){
+ /* spans pages; handle this page */
+ m = BY2PG - (a & (BY2PG-1));
+ t = memchr((void*)a, c, m);
+ if(t)
+ return t;
+ a += m;
+ n -= m;
+ if(a < KZERO)
+ validaddr(a, 1, 0);
+ }
+
+ /* fits in one page */
+ return memchr((void*)a, c, n);
+}
+
+Segment*
+seg(Proc *p, ulong addr, int dolock)
+{
+ Segment **s, **et, *n;
+
+ et = &p->seg[NSEG];
+ for(s = p->seg; s < et; s++) {
+ n = *s;
+ if(n == 0)
+ continue;
+ if(addr >= n->base && addr < n->top) {
+ if(dolock == 0)
+ return n;
+
+ qlock(&n->lk);
+ if(addr >= n->base && addr < n->top)
+ return n;
+ qunlock(&n->lk);
+ }
+ }
+
+ return 0;
+}
+
+extern void checkmmu(ulong, ulong);
+void
+checkpages(void)
+{
+ int checked;
+ ulong addr, off;
+ Pte *p;
+ Page *pg;
+ Segment **sp, **ep, *s;
+
+ if(up == nil)
+ return;
+
+ checked = 0;
+ for(sp=up->seg, ep=&up->seg[NSEG]; sp<ep; sp++){
+ s = *sp;
+ if(s == nil)
+ continue;
+ qlock(&s->lk);
+ for(addr=s->base; addr<s->top; addr+=BY2PG){
+ off = addr - s->base;
+ p = s->map[off/PTEMAPMEM];
+ if(p == 0)
+ continue;
+ pg = p->pages[(off&(PTEMAPMEM-1))/BY2PG];
+ if(pg == 0 || pagedout(pg))
+ continue;
+ checkmmu(addr, pg->pa);
+ checked++;
+ }
+ qunlock(&s->lk);
+ }
+ print("%ld %s: checked %d page table entries\n", up->pid, up->text, checked);
+}
diff --git a/sys/src/9/port/flashif.h b/sys/src/9/port/flashif.h
new file mode 100755
index 000000000..213a8c201
--- /dev/null
+++ b/sys/src/9/port/flashif.h
@@ -0,0 +1,152 @@
+typedef struct Flash Flash;
+typedef struct Flashchip Flashchip;
+typedef struct Flashpart Flashpart;
+typedef struct Flashregion Flashregion;
+
+/*
+ * logical partitions
+ */
+enum {
+ Maxflashpart = 8
+};
+
+struct Flashpart {
+ char* name;
+ ulong start;
+ ulong end;
+};
+
+enum {
+ Maxflashregion = 4
+};
+
+/*
+ * physical erase block regions
+ */
+struct Flashregion {
+ int n; /* number of blocks in region */
+ ulong start; /* physical base address (allowing for banks) */
+ ulong end;
+ ulong erasesize;
+ ulong eraseshift; /* log2(erasesize) */
+ ulong pagesize; /* if non-0, size of pages within erase block */
+ ulong pageshift; /* log2(pagesize) */
+ ulong spares; /* spare bytes per page, for ecc, etc. */
+};
+
+/*
+ * one of a set of chips in a given region
+ */
+struct Flashchip {
+ int nr;
+ Flashregion regions[Maxflashregion];
+
+ uchar id; /* flash manufacturer ID */
+ ushort devid; /* flash device ID */
+ int width; /* bytes per flash line */
+ int maxwb; /* max write buffer size */
+ ulong devsize; /* physical device size */
+ int alg; /* programming algorithm (if CFI) */
+ int protect; /* software protection */
+};
+
+/*
+ * structure defining a contiguous region of flash memory
+ */
+struct Flash {
+ QLock; /* interlock on flash operations */
+ Flash* next;
+
+ /* following are filled in before calling Flash.reset */
+ char* type;
+ void* addr;
+ ulong size;
+ int xip; /* executing in place: don't query */
+ int (*reset)(Flash*);
+
+ /* following are filled in by the reset routine */
+ int (*eraseall)(Flash*);
+ int (*erasezone)(Flash*, Flashregion*, ulong);
+ /* (optional) reads of correct width and alignment */
+ int (*read)(Flash*, ulong, void*, long);
+ /* writes of correct width and alignment */
+ int (*write)(Flash*, ulong, void*, long);
+ int (*suspend)(Flash*);
+ int (*resume)(Flash*);
+ int (*attach)(Flash*);
+
+ /* following might be filled in by either archflashreset or reset routine */
+ int nr;
+ Flashregion regions[Maxflashregion];
+
+ uchar id; /* flash manufacturer ID */
+ ushort devid; /* flash device ID */
+ int width; /* bytes per flash line */
+ int interleave; /* addresses are interleaved across set of chips */
+ int bshift; /* byte addresses are shifted */
+ ulong cmask; /* command mask for interleaving */
+ int maxwb; /* max write buffer size */
+ ulong devsize; /* physical device size */
+ int alg; /* programming algorithm (if CFI) */
+ void* data; /* flash type routines' private storage, or nil */
+ Flashpart part[Maxflashpart]; /* logical partitions */
+ int protect; /* software protection */
+ char* sort; /* "nand", "nor", "serial", nil (unspecified) */
+};
+
+/*
+ * called by link routine of driver for specific flash type: arguments are
+ * conventional name for card type/model, and card driver's reset routine.
+ */
+void addflashcard(char*, int (*)(Flash*));
+
+/*
+ * called by devflash.c:/^flashreset; if flash exists,
+ * sets type, address, and size in bytes of flash
+ * and returns 0; returns -1 if flash doesn't exist
+ */
+int archflashreset(int, Flash*);
+
+/*
+ * enable/disable write protect
+ */
+void archflashwp(Flash*, int);
+
+/*
+ * flash access taking width and interleave into account
+ */
+int flashget(Flash*, ulong);
+void flashput(Flash*, ulong, int);
+
+/*
+ * Architecture specific routines for managing nand devices
+ */
+
+/*
+ * do any device spcific initialisation
+ */
+void archnand_init(Flash*);
+
+/*
+ * if claim is 1, claim device exclusively, and enable it (power it up)
+ * if claim is 0, release, and disable it (power it down)
+ * claiming may be as simple as a qlock per device
+ */
+void archnand_claim(Flash*, int claim);
+
+/*
+ * set command latch enable (CLE) and address latch enable (ALE)
+ * appropriately
+ */
+void archnand_setCLEandALE(Flash*, int cle, int ale);
+
+/*
+ * write a sequence of bytes to the device
+ */
+void archnand_write(Flash*, void *buf, int len);
+
+/*
+ * read a sequence of bytes from the device
+ * if buf is 0, throw away the data
+ */
+void archnand_read(Flash*, void *buf, int len);
diff --git a/sys/src/9/port/initcode.c b/sys/src/9/port/initcode.c
new file mode 100755
index 000000000..7fb15cc13
--- /dev/null
+++ b/sys/src/9/port/initcode.c
@@ -0,0 +1,39 @@
+/*
+ * IMPORTANT! DO NOT ADD LIBRARY CALLS TO THIS FILE.
+ * The entire text image must fit on one page
+ * (and there's no data segment, so any read/write data must be on the stack).
+ */
+
+#include <u.h>
+#include <libc.h>
+
+char cons[] = "#c/cons";
+char boot[] = "/boot/boot";
+char dev[] = "/dev";
+char c[] = "#c";
+char e[] = "#e";
+char ec[] = "#ec";
+char s[] = "#s";
+char srv[] = "/srv";
+char env[] = "/env";
+
+void
+startboot(char *argv0, char **argv)
+{
+ char buf[200]; /* keep this fairly large to capture error details */
+
+ /* in case boot is a shell script */
+ open(cons, OREAD);
+ open(cons, OWRITE);
+ open(cons, OWRITE);
+ bind(c, dev, MAFTER);
+ bind(ec, env, MAFTER);
+ bind(e, env, MCREATE|MAFTER);
+ bind(s, srv, MREPL|MCREATE);
+
+ exec(boot, argv);
+
+ rerrstr(buf, sizeof buf);
+ buf[sizeof buf - 1] = '\0';
+ _exits(buf);
+}
diff --git a/sys/src/9/port/latin1.c b/sys/src/9/port/latin1.c
new file mode 100755
index 000000000..8dcb0d7e4
--- /dev/null
+++ b/sys/src/9/port/latin1.c
@@ -0,0 +1,76 @@
+#include <u.h>
+
+/*
+ * The code makes two assumptions: strlen(ld) is 1 or 2; latintab[i].ld can be a
+ * prefix of latintab[j].ld only when j<i.
+ */
+struct cvlist
+{
+ char *ld; /* must be seen before using this conversion */
+ char *si; /* options for last input characters */
+ Rune *so; /* the corresponding Rune for each si entry */
+} latintab[] = {
+#include "../port/latin1.h"
+ 0, 0, 0
+};
+
+/*
+ * Given 5 characters k[0]..k[4], find the rune or return -1 for failure.
+ */
+long
+unicode(Rune *k)
+{
+ long i, c;
+
+ k++; /* skip 'X' */
+ c = 0;
+ for(i=0; i<4; i++,k++){
+ c <<= 4;
+ if('0'<=*k && *k<='9')
+ c += *k-'0';
+ else if('a'<=*k && *k<='f')
+ c += 10 + *k-'a';
+ else if('A'<=*k && *k<='F')
+ c += 10 + *k-'A';
+ else
+ return -1;
+ }
+ return c;
+}
+
+/*
+ * Given n characters k[0]..k[n-1], find the corresponding rune or return -1 for
+ * failure, or something < -1 if n is too small. In the latter case, the result
+ * is minus the required n.
+ */
+long
+latin1(Rune *k, int n)
+{
+ struct cvlist *l;
+ int c;
+ char* p;
+
+ if(k[0] == 'X')
+ if(n>=5)
+ return unicode(k);
+ else
+ return -5;
+ for(l=latintab; l->ld!=0; l++)
+ if(k[0] == l->ld[0]){
+ if(n == 1)
+ return -2;
+ if(l->ld[1] == 0)
+ c = k[1];
+ else if(l->ld[1] != k[1])
+ continue;
+ else if(n == 2)
+ return -3;
+ else
+ c = k[2];
+ for(p=l->si; *p!=0; p++)
+ if(*p == c)
+ return l->so[p - l->si];
+ return -1;
+ }
+ return -1;
+}
diff --git a/sys/src/9/port/latin1.h b/sys/src/9/port/latin1.h
new file mode 100755
index 000000000..88c080c03
--- /dev/null
+++ b/sys/src/9/port/latin1.h
@@ -0,0 +1,100 @@
+ " ", " i", L"␣ı",
+ "!~", "-=~", L"≄≇≉",
+ "!", "!<=>?bmp", L"¡≮≠≯‽⊄∉⊅",
+ "\"*", "IUiu", L"ΪΫϊϋ",
+ "\"", "\"AEIOUYaeiouy", L"¨ÄËÏÖÜŸäëïöüÿ",
+ "$*", "fhk", L"ϕϑϰ",
+ "$", "BEFHILMRVaefglopv", L"ℬℰℱℋℐℒℳℛƲɑℯƒℊℓℴ℘ʋ",
+ "\'\"", "Uu", L"Ǘǘ",
+ "\'", "\'ACEILNORSUYZacegilnorsuyz", L"´ÁĆÉÍĹŃÓŔŚÚÝŹáćéģíĺńóŕśúýź",
+ "*", "*ABCDEFGHIKLMNOPQRSTUWXYZabcdefghiklmnopqrstuwxyz", L"∗ΑΒΞΔΕΦΓΘΙΚΛΜΝΟΠΨΡΣΤΥΩΧΗΖαβξδεφγθικλμνοπψρστυωχηζ",
+ "+", "-O", L"±⊕",
+ ",", ",ACEGIKLNORSTUacegiklnorstu", L"¸ĄÇĘĢĮĶĻŅǪŖŞŢŲąçęģįķļņǫŗşţų",
+ "-*", "l", L"ƛ",
+ "-", "+-2:>DGHILOTZbdghiltuz~", L"∓­ƻ÷→ÐǤĦƗŁ⊖ŦƵƀðǥℏɨłŧʉƶ≂",
+ ".", ".CEGILOZceglz", L"·ĊĖĠİĿ⊙Żċėġŀż",
+ "/", "Oo", L"Øø",
+ "1", ".234568", L"․½⅓¼⅕⅙⅛",
+ "2", "-.35", L"ƻ‥⅔⅖",
+ "3", ".458", L"…¾⅗⅜",
+ "4", "5", L"⅘",
+ "5", "68", L"⅚⅝",
+ "7", "8", L"⅞",
+ ":", "()-=", L"☹☺÷≔",
+ "<!", "=~", L"≨⋦",
+ "<", "-<=>~", L"←«≤≶≲",
+ "=", ":<=>OV", L"≕⋜≡⋝⊜⇒",
+ ">!", "=~", L"≩⋧",
+ ">", "<=>~", L"≷≥»≳",
+ "?", "!?", L"‽¿",
+ "@\'", "\'", L"ъ",
+ "@@", "\'EKSTYZekstyz", L"ьЕКСТЫЗекстыз",
+ "@C", "Hh", L"ЧЧ",
+ "@E", "Hh", L"ЭЭ",
+ "@K", "Hh", L"ХХ",
+ "@S", "CHch", L"ЩШЩШ",
+ "@T", "Ss", L"ЦЦ",
+ "@Y", "AEOUaeou", L"ЯЕЁЮЯЕЁЮ",
+ "@Z", "Hh", L"ЖЖ",
+ "@c", "h", L"ч",
+ "@e", "h", L"э",
+ "@k", "h", L"х",
+ "@s", "ch", L"щш",
+ "@t", "s", L"ц",
+ "@y", "aeou", L"яеёю",
+ "@z", "h", L"ж",
+ "@", "ABDFGIJLMNOPRUVXabdfgijlmnopruvx", L"АБДФГИЙЛМНОПРУВХабдфгийлмнопрувх",
+ "A", "E", L"Æ",
+ "C", "ACU", L"⋂ℂ⋃",
+ "Dv", "Zz", L"DŽDž",
+ "D", "-e", L"Ð∆",
+ "G", "-", L"Ǥ",
+ "H", "-H", L"Ħℍ",
+ "I", "-J", L"ƗIJ",
+ "L", "&-Jj|", L"⋀ŁLJLj⋁",
+ "M", "#48bs", L"♮♩♪♭♯",
+ "N", "JNj", L"NJℕNj",
+ "O", "*+-./=EIcoprx", L"⊛⊕⊖⊙⊘⊜ŒƢ©⊚℗®⊗",
+ "P", "P", L"ℙ",
+ "Q", "Q", L"ℚ",
+ "R", "R", L"ℝ",
+ "S", "123S", L"¹²³§",
+ "T", "-u", L"Ŧ⊨",
+ "V", "=", L"⇐",
+ "Y", "R", L"Ʀ",
+ "Z", "-ACSZ", L"Ƶℤ",
+ "^", "ACEGHIJOSUWYaceghijosuwy", L"ÂĈÊĜĤÎĴÔŜÛŴŶâĉêĝĥîĵôŝûŵŷ",
+ "_\"", "AUau", L"ǞǕǟǖ",
+ "_,", "Oo", L"Ǭǭ",
+ "_.", "Aa", L"Ǡǡ",
+ "_", "AEIOU_aeiou", L"ĀĒĪŌŪ¯āēīōū",
+ "`\"", "Uu", L"Ǜǜ",
+ "`", "AEIOUaeiou", L"ÀÈÌÒÙàèìòù",
+ "a", "ben", L"↔æ∠",
+ "b", "()+-0123456789=bknpqru", L"₍₎₊₋₀₁₂₃₄₅₆₇₈₉₌♝♚♞♟♛♜•",
+ "c", "$Oagu", L"¢©∩≅∪",
+ "dv", "z", L"dž",
+ "d", "-adegz", L"ð↓‡°†ʣ",
+ "e", "$lmns", L"€⋯—–∅",
+ "f", "a", L"∀",
+ "g", "$-r", L"¤ǥ∇",
+ "h", "-v", L"ℏƕ",
+ "i", "-bfjps", L"ɨ⊆∞ij⊇∫",
+ "l", "\"$&\'-jz|", L"“£∧‘łlj⋄∨",
+ "m", "iou", L"µ∈×",
+ "n", "jo", L"nj¬",
+ "o", "AOUaeiu", L"Å⊚Ůåœƣů",
+ "p", "Odgrt", L"℗∂¶∏∝",
+ "r", "\"\'O", L"”’®",
+ "s", "()+-0123456789=abnoprstu", L"⁽⁾⁺⁻⁰ⁱ⁲⁳⁴⁵⁶⁷⁸⁹⁼ª⊂ⁿº⊃√ß∍∑",
+ "t", "-efmsu", L"ŧ∃∴™ς⊢",
+ "u", "-AEGIOUaegiou", L"ʉĂĔĞĬŎŬ↑ĕğĭŏŭ",
+ "v\"", "Uu", L"Ǚǚ",
+ "v", "ACDEGIKLNORSTUZacdegijklnorstuz", L"ǍČĎĚǦǏǨĽŇǑŘŠŤǓŽǎčďěǧǐǰǩľňǒřšťǔž",
+ "w", "bknpqr", L"♗♔♘♙♕♖",
+ "x", "O", L"⊗",
+ "y", "$", L"¥",
+ "z", "-", L"ƶ",
+ "|", "Pp|", L"Þþ¦",
+ "~!", "=", L"≆",
+ "~", "-=AINOUainou~", L"≃≅ÃĨÑÕŨãĩñõũ≈",
diff --git a/sys/src/9/port/lib.h b/sys/src/9/port/lib.h
new file mode 100755
index 000000000..b72b3ed97
--- /dev/null
+++ b/sys/src/9/port/lib.h
@@ -0,0 +1,223 @@
+/*
+ * functions (possibly) linked in, complete, from libc.
+ */
+#define nelem(x) (sizeof(x)/sizeof((x)[0]))
+#define offsetof(s, m) (ulong)(&(((s*)0)->m))
+#define assert(x) if(x){}else _assert("x")
+
+/*
+ * mem routines
+ */
+extern void* memccpy(void*, void*, int, ulong);
+extern void* memset(void*, int, ulong);
+extern int memcmp(void*, void*, ulong);
+extern void* memmove(void*, void*, ulong);
+extern void* memchr(void*, int, ulong);
+
+/*
+ * string routines
+ */
+extern char* strcat(char*, char*);
+extern char* strchr(char*, int);
+extern char* strrchr(char*, int);
+extern int strcmp(char*, char*);
+extern char* strcpy(char*, char*);
+extern char* strecpy(char*, char*, char*);
+extern char* strncat(char*, char*, long);
+extern char* strncpy(char*, char*, long);
+extern int strncmp(char*, char*, long);
+extern long strlen(char*);
+extern char* strstr(char*, char*);
+extern int atoi(char*);
+extern int fullrune(char*, int);
+extern int cistrcmp(char*, char*);
+extern int cistrncmp(char*, char*, int);
+
+enum
+{
+ UTFmax = 3, /* maximum bytes per rune */
+ Runesync = 0x80, /* cannot represent part of a UTF sequence */
+ Runeself = 0x80, /* rune and UTF sequences are the same (<) */
+ Runeerror = 0x80, /* decoding error in UTF */
+};
+
+/*
+ * rune routines
+ */
+extern int runetochar(char*, Rune*);
+extern int chartorune(Rune*, char*);
+extern char* utfrune(char*, long);
+extern int utflen(char*);
+extern int utfnlen(char*, long);
+extern int runelen(long);
+
+extern int abs(int);
+
+/*
+ * print routines
+ */
+typedef struct Fmt Fmt;
+typedef int (*Fmts)(Fmt*);
+struct Fmt{
+ uchar runes; /* output buffer is runes or chars? */
+ void *start; /* of buffer */
+ void *to; /* current place in the buffer */
+ void *stop; /* end of the buffer; overwritten if flush fails */
+ int (*flush)(Fmt *); /* called when to == stop */
+ void *farg; /* to make flush a closure */
+ int nfmt; /* num chars formatted so far */
+ va_list args; /* args passed to dofmt */
+ int r; /* % format Rune */
+ int width;
+ int prec;
+ ulong flags;
+};
+extern int print(char*, ...);
+extern char* seprint(char*, char*, char*, ...);
+extern char* vseprint(char*, char*, char*, va_list);
+extern int snprint(char*, int, char*, ...);
+extern int vsnprint(char*, int, char*, va_list);
+extern int sprint(char*, char*, ...);
+
+#pragma varargck argpos fmtprint 2
+#pragma varargck argpos print 1
+#pragma varargck argpos seprint 3
+#pragma varargck argpos snprint 3
+#pragma varargck argpos sprint 2
+
+#pragma varargck type "lld" vlong
+#pragma varargck type "llx" vlong
+#pragma varargck type "lld" uvlong
+#pragma varargck type "llx" uvlong
+#pragma varargck type "ld" long
+#pragma varargck type "lx" long
+#pragma varargck type "ld" ulong
+#pragma varargck type "lx" ulong
+#pragma varargck type "d" int
+#pragma varargck type "x" int
+#pragma varargck type "c" int
+#pragma varargck type "C" int
+#pragma varargck type "d" uint
+#pragma varargck type "x" uint
+#pragma varargck type "c" uint
+#pragma varargck type "C" uint
+#pragma varargck type "s" char*
+#pragma varargck type "q" char*
+#pragma varargck type "S" Rune*
+#pragma varargck type "%" void
+#pragma varargck type "p" uintptr
+#pragma varargck type "p" void*
+#pragma varargck flag ','
+
+extern int fmtstrinit(Fmt*);
+extern int fmtinstall(int, int (*)(Fmt*));
+extern void quotefmtinstall(void);
+extern int fmtprint(Fmt*, char*, ...);
+extern int fmtstrcpy(Fmt*, char*);
+extern char* fmtstrflush(Fmt*);
+
+/*
+ * one-of-a-kind
+ */
+extern char* cleanname(char*);
+extern ulong getcallerpc(void*);
+
+extern long strtol(char*, char**, int);
+extern ulong strtoul(char*, char**, int);
+extern vlong strtoll(char*, char**, int);
+extern uvlong strtoull(char*, char**, int);
+extern char etext[];
+extern char edata[];
+extern char end[];
+extern int getfields(char*, char**, int, int, char*);
+extern int tokenize(char*, char**, int);
+extern int dec64(uchar*, int, char*, int);
+extern int encodefmt(Fmt*);
+extern void qsort(void*, long, long, int (*)(void*, void*));
+
+/*
+ * Syscall data structures
+ */
+#define MORDER 0x0003 /* mask for bits defining order of mounting */
+#define MREPL 0x0000 /* mount replaces object */
+#define MBEFORE 0x0001 /* mount goes before others in union directory */
+#define MAFTER 0x0002 /* mount goes after others in union directory */
+#define MCREATE 0x0004 /* permit creation in mounted directory */
+#define MCACHE 0x0010 /* cache some data */
+#define MMASK 0x0017 /* all bits on */
+
+#define OREAD 0 /* open for read */
+#define OWRITE 1 /* write */
+#define ORDWR 2 /* read and write */
+#define OEXEC 3 /* execute, == read but check execute permission */
+#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
+#define OCEXEC 32 /* or'ed in, close on exec */
+#define ORCLOSE 64 /* or'ed in, remove on close */
+#define OEXCL 0x1000 /* or'ed in, exclusive create */
+
+#define NCONT 0 /* continue after note */
+#define NDFLT 1 /* terminate after note */
+#define NSAVE 2 /* clear note but hold state */
+#define NRSTR 3 /* restore saved state */
+
+typedef struct Qid Qid;
+typedef struct Dir Dir;
+typedef struct OWaitmsg OWaitmsg;
+typedef struct Waitmsg Waitmsg;
+
+#define ERRMAX 128 /* max length of error string */
+#define KNAMELEN 28 /* max length of name held in kernel */
+
+/* bits in Qid.type */
+#define QTDIR 0x80 /* type bit for directories */
+#define QTAPPEND 0x40 /* type bit for append only files */
+#define QTEXCL 0x20 /* type bit for exclusive use files */
+#define QTMOUNT 0x10 /* type bit for mounted channel */
+#define QTAUTH 0x08 /* type bit for authentication file */
+#define QTFILE 0x00 /* plain file */
+
+/* bits in Dir.mode */
+#define DMDIR 0x80000000 /* mode bit for directories */
+#define DMAPPEND 0x40000000 /* mode bit for append only files */
+#define DMEXCL 0x20000000 /* mode bit for exclusive use files */
+#define DMMOUNT 0x10000000 /* mode bit for mounted channel */
+#define DMREAD 0x4 /* mode bit for read permission */
+#define DMWRITE 0x2 /* mode bit for write permission */
+#define DMEXEC 0x1 /* mode bit for execute permission */
+
+struct Qid
+{
+ uvlong path;
+ ulong vers;
+ uchar type;
+};
+
+struct Dir {
+ /* system-modified data */
+ ushort type; /* server type */
+ uint dev; /* server subtype */
+ /* file data */
+ Qid qid; /* unique id from server */
+ ulong mode; /* permissions */
+ ulong atime; /* last read time */
+ ulong mtime; /* last write time */
+ vlong length; /* file length: see <u.h> */
+ char *name; /* last element of path */
+ char *uid; /* owner name */
+ char *gid; /* group name */
+ char *muid; /* last modifier name */
+};
+
+struct OWaitmsg
+{
+ char pid[12]; /* of loved one */
+ char time[3*12]; /* of loved one and descendants */
+ char msg[64]; /* compatibility BUG */
+};
+
+struct Waitmsg
+{
+ int pid; /* of loved one */
+ ulong time[3]; /* of loved one and descendants */
+ char msg[ERRMAX]; /* actually variable-size in user mode */
+};
diff --git a/sys/src/9/port/log.c b/sys/src/9/port/log.c
new file mode 100755
index 000000000..34edda696
--- /dev/null
+++ b/sys/src/9/port/log.c
@@ -0,0 +1,186 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+static char Ebadlogctl[] = "unknown log ctl message";
+
+void
+logopen(Log *alog)
+{
+ lock(alog);
+ if(waserror()){
+ unlock(alog);
+ nexterror();
+ }
+ if(alog->opens == 0){
+ if(alog->nlog == 0)
+ alog->nlog = 4*1024;
+ if(alog->minread == 0)
+ alog->minread = 1;
+ if(alog->buf == nil)
+ alog->buf = malloc(alog->nlog);
+ alog->rptr = alog->buf;
+ alog->end = alog->buf + alog->nlog;
+ alog->len = 0;
+ }
+ alog->opens++;
+ unlock(alog);
+ poperror();
+}
+
+void
+logclose(Log *alog)
+{
+ lock(alog);
+ alog->opens--;
+ if(alog->opens == 0){
+ free(alog->buf);
+ alog->buf = nil;
+ }
+ unlock(alog);
+}
+
+static int
+logready(void *a)
+{
+ Log *alog = a;
+
+ return alog->len >= alog->minread;
+}
+
+long
+logread(Log *alog, void *a, ulong, long n)
+{
+ int i, d;
+ char *p, *rptr;
+
+ qlock(&alog->readq);
+ if(waserror()){
+ qunlock(&alog->readq);
+ nexterror();
+ }
+
+ for(;;){
+ lock(alog);
+ if(alog->len >= alog->minread || alog->len >= n){
+ if(n > alog->len)
+ n = alog->len;
+ d = 0;
+ rptr = alog->rptr;
+ alog->rptr += n;
+ if(alog->rptr >= alog->end){
+ d = alog->rptr - alog->end;
+ alog->rptr = alog->buf + d;
+ }
+ alog->len -= n;
+ unlock(alog);
+
+ i = n-d;
+ p = a;
+ memmove(p, rptr, i);
+ memmove(p+i, alog->buf, d);
+ break;
+ }
+ else
+ unlock(alog);
+
+ sleep(&alog->readr, logready, alog);
+ }
+
+ qunlock(&alog->readq);
+ poperror();
+
+ return n;
+}
+
+char*
+logctl(Log *alog, int argc, char *argv[], Logflag *flags)
+{
+ int i, set;
+ Logflag *fp;
+
+ if(argc < 2)
+ return Ebadlogctl;
+
+ if(strcmp("set", argv[0]) == 0)
+ set = 1;
+ else if(strcmp("clear", argv[0]) == 0)
+ set = 0;
+ else
+ return Ebadlogctl;
+
+ for(i = 1; i < argc; i++){
+ for(fp = flags; fp->name; fp++)
+ if(strcmp(fp->name, argv[i]) == 0)
+ break;
+ if(fp->name == nil)
+ continue;
+ if(set)
+ alog->logmask |= fp->mask;
+ else
+ alog->logmask &= ~fp->mask;
+ }
+
+ return nil;
+}
+
+void
+logn(Log *alog, int mask, void *buf, int n)
+{
+ char *fp, *t;
+ int dowake, i;
+
+ if(!(alog->logmask & mask))
+ return;
+
+ if(alog->opens == 0)
+ return;
+
+ if(n > alog->nlog)
+ return;
+
+ lock(alog);
+ i = alog->len + n - alog->nlog;
+ if(i > 0){
+ alog->len -= i;
+ alog->rptr += i;
+ if(alog->rptr >= alog->end)
+ alog->rptr = alog->buf + (alog->rptr - alog->end);
+ }
+ t = alog->rptr + alog->len;
+ fp = buf;
+ alog->len += n;
+ while(n-- > 0){
+ if(t >= alog->end)
+ t = alog->buf + (t - alog->end);
+ *t++ = *fp++;
+ }
+ dowake = alog->len >= alog->minread;
+ unlock(alog);
+
+ if(dowake)
+ wakeup(&alog->readr);
+}
+
+void
+log(Log *alog, int mask, char *fmt, ...)
+{
+ int n;
+ va_list arg;
+ char buf[128];
+
+ if(!(alog->logmask & mask))
+ return;
+
+ if(alog->opens == 0)
+ return;
+
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+
+ logn(alog, mask, buf, n);
+}
diff --git a/sys/src/9/port/master b/sys/src/9/port/master
new file mode 100755
index 000000000..0e627aaf8
--- /dev/null
+++ b/sys/src/9/port/master
@@ -0,0 +1,63 @@
+# do not edit; automatically generated
+
+$ pnp
+/ root
+A audio
+A uda1341
+B bridge
+C ce
+D ssl
+E sdp
+F flash
+G gs1
+I ip
+K kprof
+L lpt
+M mnt
+P arch
+S sd
+T lm78
+U usb
+V lml
+V tv
+X loopback
+Y pccard
+a tls
+b irq
+c cons
+d dup
+e env
+f floppy
+g segment
+i draw
+k fs
+l ether
+m mouse
+m penmouse
+p proc
+q qmux
+r rtc
+r µc
+s srv
+t uart
+v vga
+w wd
+y i82365
+y pcmcia
+| pipe
+¤ cap
+æ aoe
+Ι kbin
+κ kbmap
+μ moipv6
+霞 kasumi
+
+α local use
+β local use
+γ local use
+δ local use
+ε local use
+ζ local use
+η local use
+θ local use
+ι local use
diff --git a/sys/src/9/port/master.local b/sys/src/9/port/master.local
new file mode 100755
index 000000000..6e74697c5
--- /dev/null
+++ b/sys/src/9/port/master.local
@@ -0,0 +1,9 @@
+α local use
+β local use
+γ local use
+δ local use
+ε local use
+ζ local use
+η local use
+θ local use
+ι local use
diff --git a/sys/src/9/port/mkbootrules b/sys/src/9/port/mkbootrules
new file mode 100755
index 000000000..309108ed0
--- /dev/null
+++ b/sys/src/9/port/mkbootrules
@@ -0,0 +1,59 @@
+#!/bin/rc
+
+rfork e
+if(~ $#CONF 0)
+ CONF=$1
+awk -v 'objtype='$objtype -v 'CONF='$CONF '
+BEGIN { nfs = 0 }
+/^$/{
+ next;
+}
+/^#/{
+ next;
+}
+collect && /^[^ \t]/{
+ collect = 0;
+}
+collect && section ~ "bootdir" {
+ if(NF >= 2)
+ x = $2;
+ else{
+ x = $1;
+ sub(/.*\//, "", x);
+ }
+ fsname[nfs] = x;
+ x = $1;
+ gsub(/[^a-zA-Z0-9_]/, "_", x);
+ fs[nfs] = x;
+ file[nfs] = $1;
+ nfs++;
+}
+$0 ~ /^[^ \t]/{
+ if($0 ~ "bootdir"){
+ section = $0;
+ collect = 1;
+ }
+ next;
+}
+
+END{
+ printf "%s.root.s:D:", CONF;
+ for(i=0; i<nfs; i++)
+ printf " %s", file[i];
+ printf "\n";
+ printf "\t../port/mkrootall \\\n";
+ for(i=0; i<nfs; i++)
+ printf "\t\t%s %s %s\\\n", fsname[i], fs[i], file[i];
+ printf "\t>$target\n";
+
+ printf "%s.rootc.c:D:", CONF;
+ for(i=0; i<nfs; i++)
+ printf " %s", file[i];
+ printf "\n";
+ printf "\t../port/mkrootc \\\n";
+ for(i=0; i<nfs; i++)
+ printf "\t\t%s %s %s\\\n", fsname[i], fs[i], file[i];
+ printf "\t>$target\n";
+}
+
+' $*
diff --git a/sys/src/9/port/mkdevc b/sys/src/9/port/mkdevc
new file mode 100755
index 000000000..17b6a852a
--- /dev/null
+++ b/sys/src/9/port/mkdevc
@@ -0,0 +1,191 @@
+#!/bin/rc
+
+awk -v 'objtype='$objtype -v 'pwd='`{pwd} '
+BEGIN{
+ if(ARGC < 2)
+ exit
+}
+
+/^[ \t]*$/{
+ next;
+}
+/^#/{
+ next;
+}
+collect && /^[^ \t]/{
+ collect = 0;
+}
+collect && section == "dev"{
+ dev[ndev++] = $1;
+ if($1 == "ad")
+ devad = 1;
+ else if($1 == "sd")
+ devsd = 1;
+ else if($1 == "uart")
+ devuart = 1;
+ else if($1 == "vga")
+ devvga = 1;
+ for(i = 2; i <= NF; i++){
+ if($i == "dma" && objtype ~ "(386|alpha|amd64)")
+ i8237dma++;
+ }
+}
+collect && section == "ip"{
+ ip[nip++] = $1;
+}
+collect && section == "link"{
+ link[nlink++] = $1;
+}
+collect && section == "misc"{
+ sub(/^[ \t]*/, "");
+ misc[nmisc++] = $1;
+ if($1 ~ "^arch.*")
+ arch[narch++] = $1;
+ else if($1 ~ "^ad.*")
+ adifc[nadifc++] = $1;
+ else if($1 ~ "^sd.*")
+ sdifc[nsdifc++] = $1;
+ else if($1 ~ "^uart.*")
+ physuart[nphysuart++] = substr($1, 5, length($1)-4) "physuart";
+ else if($1 ~ "^vga.*"){
+ if(NF == 1)
+ vgadev[nvgadev++] = $1;
+ else for(i = 2; i <= NF; i++){
+ if($i ~ "[+]cur")
+ vgadev[nvgadev++] = $1;
+ if($i ~ "[+=]cur")
+ vgacur[nvgacur++] = $1;
+ }
+ }
+}
+
+collect && section == "port"{
+ sub(/^[ \t]*/, "");
+ port[nport++] = $0;
+}
+$0 ~ /^[^ \t]/{
+ if($1 ~ "(bootdir|dev|ip|link|misc|port)"){
+ section = $1;
+ collect = 1;
+ }
+ next;
+}
+
+END{
+ if(ARGC < 2)
+ exit "usage"
+
+ printf "#include \"u.h\"\n";
+ printf "#include \"../port/lib.h\"\n";
+ printf "#include \"mem.h\"\n";
+ printf "#include \"dat.h\"\n";
+ printf "#include \"fns.h\"\n";
+ printf "#include \"io.h\"\n";
+ printf "#include \"../port/error.h\"\n\n";
+
+ for(i = 0; i < ndev; i++)
+ printf "extern Dev %sdevtab;\n", dev[i];
+ printf "Dev* devtab[]={\n";
+ for(i = 0; i < ndev; i++)
+ printf "\t&%sdevtab,\n", dev[i];
+ printf "\tnil,\n};\n\n";
+
+ if(objtype ~ "(386|alpha|amd64)"){
+ alloc = "nil";
+ if(i8237dma){
+ printf "extern void _i8237alloc(void);\n";
+ alloc = "_i8237alloc";
+ }
+ printf "void (*i8237alloc)(void) = %s;\n", alloc;
+ printf "int i8237dma = %d;\n\n", i8237dma;
+ }
+
+ for(i = 0; i < nlink; i++)
+ printf "extern void %slink(void);\n", link[i];
+
+ printf "void links(void){\n";
+ print "\tbootlinks();\n";
+ for(i = 0; i < nlink; i++)
+ printf "\t%slink();\n", link[i];
+ printf "}\n\n";
+
+ if(narch || objtype == "386"){
+ for(i = 0; i < narch; i++)
+ printf "extern PCArch %s;\n", arch[i];
+ printf "PCArch* knownarch[] = {\n";
+ for(i = 0; i < narch; i++)
+ printf "\t&%s,\n", arch[i];
+ printf "\tnil,\n};\n\n";
+ }
+
+ if(devad){
+ printf "#include \"../port/ad.h\"\n";
+ for(i = 0; i < nadifc; i++)
+ printf "extern ADifc %sifc;\n", adifc[i];
+ printf "ADifc* adifc[] = {\n";
+ for(i = 0; i < nadifc; i++)
+ printf "\t&%sifc,\n", adifc[i];
+ printf "\tnil,\n};\n\n";
+ }
+ if(devsd){
+ printf "#include \"../port/sd.h\"\n";
+ for(i = 0; i < nsdifc; i++)
+ printf "extern SDifc %sifc;\n", sdifc[i];
+ printf "SDifc* sdifc[] = {\n";
+ for(i = 0; i < nsdifc; i++)
+ printf "\t&%sifc,\n", sdifc[i];
+ printf "\tnil,\n};\n\n";
+ }
+
+ if(devuart){
+ for(i = 0; i < nphysuart; i++)
+ printf "extern PhysUart %s;\n", physuart[i];
+ printf "PhysUart* physuart[] = {\n";
+ for(i = 0; i < nphysuart; i++)
+ printf "\t&%s,\n", physuart[i];
+ printf "\tnil,\n};\n\n";
+ }
+
+ if(devvga){
+ printf "#define Image IMAGE\n";
+ printf "#include <draw.h>\n";
+ printf "#include <memdraw.h>\n";
+ printf "#include <cursor.h>\n";
+ printf "#include \"screen.h\"\n";
+
+ for(i = 0; i < nvgadev; i++)
+ printf "extern VGAdev %sdev;\n", vgadev[i];
+ printf "VGAdev* vgadev[] = {\n";
+ for(i = 0; i < nvgadev; i++)
+ printf "\t&%sdev,\n", vgadev[i];
+ printf "\tnil,\n};\n\n";
+
+ for(i = 0; i < nvgacur; i++)
+ printf "extern VGAcur %scur;\n", vgacur[i];
+ printf "VGAcur* vgacur[] = {\n";
+ for(i = 0; i < nvgacur; i++)
+ printf "\t&%scur,\n", vgacur[i];
+ printf "\tnil,\n};\n\n";
+ }
+
+ if(nip){
+ printf "#include \"../ip/ip.h\"\n";
+ for(i = 0; i < nip; i++)
+ printf "extern void %sinit(Fs*);\n", ip[i];
+ printf "void (*ipprotoinit[])(Fs*) = {\n";
+ for(i = 0; i < nip; i++)
+ printf "\t%sinit,\n", ip[i];
+ printf "\tnil,\n};\n\n";
+ }
+
+ if(nport){
+ for(i = 0; i < nport; i++)
+ printf "%s\n", port[i];
+ printf "\n";
+ }
+
+ printf "char* conffile = \"%s/%s\";\n", pwd, ARGV[1];
+ printf "ulong kerndate = KERNDATE;\n";
+
+ exit
+}' $*
diff --git a/sys/src/9/port/mkdevlist b/sys/src/9/port/mkdevlist
new file mode 100755
index 000000000..6d745b318
--- /dev/null
+++ b/sys/src/9/port/mkdevlist
@@ -0,0 +1,46 @@
+#!/bin/rc
+
+awk -v 'objtype='$objtype '
+BEGIN{
+ if(ARGC < 2)
+ exit;
+ collect = isdev = 0;
+}
+
+/^[ \t]*$/{
+ next;
+}
+/^#/{
+ next;
+}
+collect && /^[^ \t]/{
+ collect = isdev = 0;
+}
+collect && $0 ~ /[^ \t]+/{
+ if(isdev)
+ obj["dev" $1 "'.$O'"]++;
+ else
+ obj[$1 "'.$O'"]++;
+ for(i = 2; i <= NF; i++){
+ if($i !~ "[+=-].*")
+ obj[$i "'.$O'"]++;
+ }
+}
+$0 ~ /^[^ \t]/{
+ if($1 ~ "dev"){
+ isdev = 1;
+ collect = 1;
+ }
+ else if($1 ~ "misc" || $1 ~ "link" || $1 ~ "ip")
+ collect = 1;
+ next;
+}
+
+END{
+ x = ""
+ for(i in obj)
+ x = x i "\n";
+ if(objtype ~ "386" && obj["pci" "'.$O'"])
+ x = x "bios32'.$O' \n";
+ printf x;
+}' $*
diff --git a/sys/src/9/port/mkerrstr b/sys/src/9/port/mkerrstr
new file mode 100755
index 000000000..a0d87ec7e
--- /dev/null
+++ b/sys/src/9/port/mkerrstr
@@ -0,0 +1,3 @@
+#!/bin/rc
+
+sed 's/extern //;s,;.*/\* (.*) \*/, = "\1";,' < ../port/error.h
diff --git a/sys/src/9/port/mkextract b/sys/src/9/port/mkextract
new file mode 100755
index 000000000..514d36ebc
--- /dev/null
+++ b/sys/src/9/port/mkextract
@@ -0,0 +1,37 @@
+#!/bin/rc
+
+switch($#*){
+case [012]
+ echo usage: mkextract [-u] field n file... >[1=2]
+ exit 1
+}
+
+switch($1){
+case -u
+ flag=$1; shift
+case *
+ flag=''
+}
+
+field=$1
+n=$2
+shift 2
+
+fn select {
+ awk '
+
+ BEGIN { doprint=0 }
+ /^$/ { next }
+ /^#/ { next }
+ doprint && /^[^ ]/ { doprint=0 }
+ doprint { print $'^$n^' }
+ $1 ~ "^'^$field^'$" { doprint=1; next }
+ ' $*
+}
+
+switch($flag){
+case -u
+ select $* | sort -u
+case *
+ select $*
+}
diff --git a/sys/src/9/port/mkfile b/sys/src/9/port/mkfile
new file mode 100755
index 000000000..4817e894f
--- /dev/null
+++ b/sys/src/9/port/mkfile
@@ -0,0 +1,15 @@
+# If the existence of this mkfile screws something up, rename it. -rsc
+
+master:DV:
+ {
+ echo '# do not edit; automatically generated'
+ echo
+ echo '
+ X , s/Dev (.*)devtab.*{.*\n L?''(.*)''/DEV \1 \2\n/
+ X ,x g/^DEV/ p
+ ' | sam -d ../*/dev*.c >[2]/dev/null |
+ awk '/^DEV/ { printf("%s\t%s\n", $3, $2); }' |
+ sort -u
+ echo
+ cat master.local
+ } >master
diff --git a/sys/src/9/port/mkfilelist b/sys/src/9/port/mkfilelist
new file mode 100755
index 000000000..733ca07a6
--- /dev/null
+++ b/sys/src/9/port/mkfilelist
@@ -0,0 +1,15 @@
+#!/bin/rc
+
+rfork e
+switch($#*){
+case 1
+ RE=`{echo *.c | sed 's/ /|/g; s/.*/^(&)$/'}
+ if(~ $RE '^(*.c)$')
+ LIST=`{builtin cd $1; ls *.c }
+ if not
+ LIST=`{builtin cd $1; ls *.c | grep -v ''$RE''}
+ echo $LIST | sed 's/\.c//g; s/ +/|/g'
+case *
+ exit 'usage'
+}
+exit ''
diff --git a/sys/src/9/port/mkroot b/sys/src/9/port/mkroot
new file mode 100755
index 000000000..874541758
--- /dev/null
+++ b/sys/src/9/port/mkroot
@@ -0,0 +1,15 @@
+#!/bin/rc
+
+rfork e
+echo mkroot $*
+if(! ~ $#* 2){
+ echo usage: mkroot path name >[2=1]
+ exit 1
+}
+n=`{basename $1}
+cp $1 $2.out
+t=`{file $2.out}
+if(~ $"t *executable*)
+ strip $2.out
+aux/data2s $2 < $2.out > $2.root.s
+echo mkroot $* done
diff --git a/sys/src/9/port/mkrootall b/sys/src/9/port/mkrootall
new file mode 100755
index 000000000..77fbfd9b7
--- /dev/null
+++ b/sys/src/9/port/mkrootall
@@ -0,0 +1,31 @@
+#!/bin/rc
+
+rfork e
+n=`{echo $#*^'%3' | hoc}
+if(! ~ $n 0){
+ echo 'usage: mkrootall [name cname file]...' >[1=2]
+ exit usage
+}
+
+tmp=mkroot.$pid.out
+fn sigexit {
+ rm -f $tmp
+}
+
+allcname=()
+while(! ~ $#* 0){
+ name=$1
+ cname=$2
+ file=$3
+ shift
+ shift
+ shift
+ allcname=($allcname $cname)
+ cp $file $tmp
+ t=`{file $tmp}
+ # do not strip venti - it uses its own symbols
+ if(~ $"t *executable* && ! ~ $name venti)
+ strip $tmp
+ aux/data2s $cname < $tmp
+}
+exit 0
diff --git a/sys/src/9/port/mkrootc b/sys/src/9/port/mkrootc
new file mode 100755
index 000000000..4c6907f68
--- /dev/null
+++ b/sys/src/9/port/mkrootc
@@ -0,0 +1,54 @@
+#!/bin/rc
+
+rfork e
+n=`{echo $#*^'%3' | hoc}
+if(! ~ $n 0){
+ echo 'usage: mkrootc [name cname file]...' >[1=2]
+ exit usage
+}
+
+tmp=mkroot.$pid.out
+fn sigexit {
+ rm -f $tmp
+}
+
+allcname=()
+allname=()
+while(! ~ $#* 0){
+ name=$1
+ cname=$2
+ file=$3
+ shift
+ shift
+ shift
+ allname=($allname $name)
+ allcname=($allcname $cname)
+}
+
+echo '
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+'
+
+for(i in $allcname){
+ echo 'extern uchar '$i'code[];'
+ echo 'extern ulong '$i'len;'
+}
+
+echo '
+void bootlinks(void){
+'
+x=($allname)
+for(i in $allcname){
+ name=$x(1)
+ *=($x); shift; x=($*)
+ echo ' addbootfile("'$name'", '$i'code, '$i'len);'
+}
+echo '
+}
+'
diff --git a/sys/src/9/port/mksystab b/sys/src/9/port/mksystab
new file mode 100755
index 000000000..71975c118
--- /dev/null
+++ b/sys/src/9/port/mksystab
@@ -0,0 +1,50 @@
+#!/bin/rc
+
+file=/sys/src/libc/9syscall/sys.h
+
+cat <<'!'
+#include "/sys/src/libc/9syscall/sys.h"
+
+typedef long Syscall(ulong*);
+
+!
+
+sed 's/#define[ ]*([A-Z0-9_][A-Z0-9_]*).*/SYS\1/; s/SYSSYSR1/SYSR1/' $file |
+ tr A-Z a-z |
+ sed 's/.*/Syscall &;/'
+
+cat <<'!'
+Syscall sysdeath;
+
+Syscall *systab[]={
+!
+sam -d $file >[2] /dev/null <<'!'
+,s/#define.([A-Z0-9_]+).*/ [\1] SYS\1,/g
+,x/SYS[A-Z0-9_]+,/ | tr A-Z a-z
+,x/syssysr1/c/sysr1
+,x/sys_x[0-9]*/c/sysdeath
+,x v/\[......+\]/ s/\]/]
+,p
+!
+
+cat <<'!'
+};
+
+char *sysctab[]={
+!
+
+sam -d $file >[2] /dev/null <<'!'
+,s/#define.([A-Z0-9_]+).*/ [\1] "\1",/g
+,x/"[A-Z0-9_]+",/ y/"[A-Z]/ | tr A-Z a-z
+,x/_"/c/"
+,x/Sysr1/c/Running
+,x/Rendezvous/c/Rendez
+,x v/\[......+\]/ s/\]/]
+,p
+!
+
+cat <<'!'
+};
+
+int nsyscall = (sizeof systab/sizeof systab[0]);
+!
diff --git a/sys/src/9/port/mul64fract.c b/sys/src/9/port/mul64fract.c
new file mode 100755
index 000000000..ca6270739
--- /dev/null
+++ b/sys/src/9/port/mul64fract.c
@@ -0,0 +1,39 @@
+#include <u.h>
+
+/* mul64fract(uvlong*r, uvlong a, uvlong b)
+ *
+ * Multiply two 64 numbers and return the middle 64 bits of the 128 bit result.
+ *
+ * The assumption is that one of the numbers is a
+ * fixed point number with the integer portion in the
+ * high word and the fraction in the low word.
+ *
+ * There should be an assembler version of this routine
+ * for each architecture. This one is intended to
+ * make ports easier.
+ *
+ * ignored r0 = lo(a0*b0)
+ * lsw of result r1 = hi(a0*b0) +lo(a0*b1) +lo(a1*b0)
+ * msw of result r2 = hi(a0*b1) +hi(a1*b0) +lo(a1*b1)
+ * ignored r3 = hi(a1*b1)
+ */
+
+void
+mul64fract(uvlong *r, uvlong a, uvlong b)
+{
+ uvlong bh, bl;
+ uvlong ah, al;
+ uvlong res;
+
+ bl = b & 0xffffffffULL;
+ bh = b >> 32;
+ al = a & 0xffffffffULL;
+ ah = a >> 32;
+
+ res = (al*bl)>>32;
+ res += (al*bh);
+ res += (ah*bl);
+ res += (ah*bh)<<32;
+
+ *r = res;
+}
diff --git a/sys/src/9/port/nandecc.h b/sys/src/9/port/nandecc.h
new file mode 100755
index 000000000..d4f37f39c
--- /dev/null
+++ b/sys/src/9/port/nandecc.h
@@ -0,0 +1,11 @@
+typedef enum NandEccError {
+ NandEccErrorBad,
+ NandEccErrorGood,
+ NandEccErrorOneBit,
+ NandEccErrorOneBitInEcc,
+} NandEccError;
+
+ulong nandecc(uchar buf[256]);
+NandEccError nandecccorrect(uchar buf[256], ulong calcecc, ulong *storedecc,
+ int reportbad);
+
diff --git a/sys/src/9/port/netif.c b/sys/src/9/port/netif.c
new file mode 100755
index 000000000..3260a65b2
--- /dev/null
+++ b/sys/src/9/port/netif.c
@@ -0,0 +1,725 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+static int netown(Netfile*, char*, int);
+static int openfile(Netif*, int);
+static char* matchtoken(char*, char*);
+static char* netmulti(Netif*, Netfile*, uchar*, int);
+static int parseaddr(uchar*, char*, int);
+
+/*
+ * set up a new network interface
+ */
+void
+netifinit(Netif *nif, char *name, int nfile, ulong limit)
+{
+ strncpy(nif->name, name, KNAMELEN-1);
+ nif->name[KNAMELEN-1] = 0;
+ nif->nfile = nfile;
+ nif->f = xalloc(nfile*sizeof(Netfile*));
+ if (nif->f == nil)
+ panic("netifinit: no memory");
+ memset(nif->f, 0, nfile*sizeof(Netfile*));
+ nif->limit = limit;
+}
+
+/*
+ * generate a 3 level directory
+ */
+static int
+netifgen(Chan *c, char*, Dirtab *vp, int, int i, Dir *dp)
+{
+ Qid q;
+ Netif *nif = (Netif*)vp;
+ Netfile *f;
+ int t;
+ int perm;
+ char *o;
+
+ q.type = QTFILE;
+ q.vers = 0;
+
+ /* top level directory contains the name of the network */
+ if(c->qid.path == 0){
+ switch(i){
+ case DEVDOTDOT:
+ q.path = 0;
+ q.type = QTDIR;
+ devdir(c, q, ".", 0, eve, 0555, dp);
+ break;
+ case 0:
+ q.path = N2ndqid;
+ q.type = QTDIR;
+ strcpy(up->genbuf, nif->name);
+ devdir(c, q, up->genbuf, 0, eve, 0555, dp);
+ break;
+ default:
+ return -1;
+ }
+ return 1;
+ }
+
+ /* second level contains clone plus all the conversations */
+ t = NETTYPE(c->qid.path);
+ if(t == N2ndqid || t == Ncloneqid || t == Naddrqid){
+ switch(i) {
+ case DEVDOTDOT:
+ q.type = QTDIR;
+ q.path = 0;
+ devdir(c, q, ".", 0, eve, DMDIR|0555, dp);
+ break;
+ case 0:
+ q.path = Ncloneqid;
+ devdir(c, q, "clone", 0, eve, 0666, dp);
+ break;
+ case 1:
+ q.path = Naddrqid;
+ devdir(c, q, "addr", 0, eve, 0666, dp);
+ break;
+ case 2:
+ q.path = Nstatqid;
+ devdir(c, q, "stats", 0, eve, 0444, dp);
+ break;
+ case 3:
+ q.path = Nifstatqid;
+ devdir(c, q, "ifstats", 0, eve, 0444, dp);
+ break;
+ default:
+ i -= 4;
+ if(i >= nif->nfile)
+ return -1;
+ if(nif->f[i] == 0)
+ return 0;
+ q.type = QTDIR;
+ q.path = NETQID(i, N3rdqid);
+ snprint(up->genbuf, sizeof up->genbuf, "%d", i);
+ devdir(c, q, up->genbuf, 0, eve, DMDIR|0555, dp);
+ break;
+ }
+ return 1;
+ }
+
+ /* third level */
+ f = nif->f[NETID(c->qid.path)];
+ if(f == 0)
+ return 0;
+ if(*f->owner){
+ o = f->owner;
+ perm = f->mode;
+ } else {
+ o = eve;
+ perm = 0666;
+ }
+ switch(i){
+ case DEVDOTDOT:
+ q.type = QTDIR;
+ q.path = N2ndqid;
+ strcpy(up->genbuf, nif->name);
+ devdir(c, q, up->genbuf, 0, eve, DMDIR|0555, dp);
+ break;
+ case 0:
+ q.path = NETQID(NETID(c->qid.path), Ndataqid);
+ devdir(c, q, "data", 0, o, perm, dp);
+ break;
+ case 1:
+ q.path = NETQID(NETID(c->qid.path), Nctlqid);
+ devdir(c, q, "ctl", 0, o, perm, dp);
+ break;
+ case 2:
+ q.path = NETQID(NETID(c->qid.path), Nstatqid);
+ devdir(c, q, "stats", 0, eve, 0444, dp);
+ break;
+ case 3:
+ q.path = NETQID(NETID(c->qid.path), Ntypeqid);
+ devdir(c, q, "type", 0, eve, 0444, dp);
+ break;
+ case 4:
+ q.path = NETQID(NETID(c->qid.path), Nifstatqid);
+ devdir(c, q, "ifstats", 0, eve, 0444, dp);
+ break;
+ default:
+ return -1;
+ }
+ return 1;
+}
+
+Walkqid*
+netifwalk(Netif *nif, Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, (Dirtab *)nif, 0, netifgen);
+}
+
+Chan*
+netifopen(Netif *nif, Chan *c, int omode)
+{
+ int id;
+ Netfile *f;
+
+ id = 0;
+ if(c->qid.type & QTDIR){
+ if(omode != OREAD)
+ error(Eperm);
+ } else {
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ case Nctlqid:
+ id = NETID(c->qid.path);
+ openfile(nif, id);
+ break;
+ case Ncloneqid:
+ id = openfile(nif, -1);
+ c->qid.path = NETQID(id, Nctlqid);
+ break;
+ default:
+ if(omode != OREAD)
+ error(Ebadarg);
+ }
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ case Nctlqid:
+ f = nif->f[id];
+ if(netown(f, up->user, omode&7) < 0)
+ error(Eperm);
+ break;
+ }
+ }
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ c->iounit = qiomaxatomic;
+ return c;
+}
+
+long
+netifread(Netif *nif, Chan *c, void *a, long n, ulong offset)
+{
+ int i, j;
+ Netfile *f;
+ char *p;
+
+ if(c->qid.type&QTDIR)
+ return devdirread(c, a, n, (Dirtab*)nif, 0, netifgen);
+
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ f = nif->f[NETID(c->qid.path)];
+ return qread(f->in, a, n);
+ case Nctlqid:
+ return readnum(offset, a, n, NETID(c->qid.path), NUMSIZE);
+ case Nstatqid:
+ p = malloc(READSTR);
+ j = snprint(p, READSTR, "in: %llud\n", nif->inpackets);
+ j += snprint(p+j, READSTR-j, "link: %d\n", nif->link);
+ j += snprint(p+j, READSTR-j, "out: %llud\n", nif->outpackets);
+ j += snprint(p+j, READSTR-j, "crc errs: %d\n", nif->crcs);
+ j += snprint(p+j, READSTR-j, "overflows: %d\n", nif->overflows);
+ j += snprint(p+j, READSTR-j, "soft overflows: %d\n", nif->soverflows);
+ j += snprint(p+j, READSTR-j, "framing errs: %d\n", nif->frames);
+ j += snprint(p+j, READSTR-j, "buffer errs: %d\n", nif->buffs);
+ j += snprint(p+j, READSTR-j, "output errs: %d\n", nif->oerrs);
+ j += snprint(p+j, READSTR-j, "prom: %d\n", nif->prom);
+ j += snprint(p+j, READSTR-j, "mbps: %d\n", nif->mbps);
+ j += snprint(p+j, READSTR-j, "addr: ");
+ for(i = 0; i < nif->alen; i++)
+ j += snprint(p+j, READSTR-j, "%2.2ux", nif->addr[i]);
+ snprint(p+j, READSTR-j, "\n");
+ n = readstr(offset, a, n, p);
+ free(p);
+ return n;
+ case Naddrqid:
+ p = malloc(READSTR);
+ j = 0;
+ for(i = 0; i < nif->alen; i++)
+ j += snprint(p+j, READSTR-j, "%2.2ux", nif->addr[i]);
+ n = readstr(offset, a, n, p);
+ free(p);
+ return n;
+ case Ntypeqid:
+ f = nif->f[NETID(c->qid.path)];
+ return readnum(offset, a, n, f->type, NUMSIZE);
+ case Nifstatqid:
+ return 0;
+ }
+ error(Ebadarg);
+ return -1; /* not reached */
+}
+
+Block*
+netifbread(Netif *nif, Chan *c, long n, ulong offset)
+{
+ if((c->qid.type & QTDIR) || NETTYPE(c->qid.path) != Ndataqid)
+ return devbread(c, n, offset);
+
+ return qbread(nif->f[NETID(c->qid.path)]->in, n);
+}
+
+/*
+ * make sure this type isn't already in use on this device
+ */
+static int
+typeinuse(Netif *nif, int type)
+{
+ Netfile *f, **fp, **efp;
+
+ if(type <= 0)
+ return 0;
+
+ efp = &nif->f[nif->nfile];
+ for(fp = nif->f; fp < efp; fp++){
+ f = *fp;
+ if(f == 0)
+ continue;
+ if(f->type == type)
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * the devxxx.c that calls us handles writing data, it knows best
+ */
+long
+netifwrite(Netif *nif, Chan *c, void *a, long n)
+{
+ Netfile *f;
+ int type;
+ char *p, buf[64];
+ uchar binaddr[Nmaxaddr];
+
+ if(NETTYPE(c->qid.path) != Nctlqid)
+ error(Eperm);
+
+ if(n >= sizeof(buf))
+ n = sizeof(buf)-1;
+ memmove(buf, a, n);
+ buf[n] = 0;
+
+ if(waserror()){
+ qunlock(nif);
+ nexterror();
+ }
+
+ qlock(nif);
+ f = nif->f[NETID(c->qid.path)];
+ if((p = matchtoken(buf, "connect")) != 0){
+ type = atoi(p);
+ if(typeinuse(nif, type))
+ error(Einuse);
+ f->type = type;
+ if(f->type < 0)
+ nif->all++;
+ } else if(matchtoken(buf, "promiscuous")){
+ if(f->prom == 0){
+ if(nif->prom == 0 && nif->promiscuous != nil)
+ nif->promiscuous(nif->arg, 1);
+ f->prom = 1;
+ nif->prom++;
+ }
+ } else if((p = matchtoken(buf, "scanbs")) != 0){
+ /* scan for base stations */
+ if(f->scan == 0){
+ type = atoi(p);
+ if(type < 5)
+ type = 5;
+ if(nif->scanbs != nil)
+ nif->scanbs(nif->arg, type);
+ f->scan = type;
+ nif->scan++;
+ }
+ } else if(matchtoken(buf, "bridge")){
+ f->bridge = 1;
+ } else if(matchtoken(buf, "headersonly")){
+ f->headersonly = 1;
+ } else if((p = matchtoken(buf, "addmulti")) != 0){
+ if(parseaddr(binaddr, p, nif->alen) < 0)
+ error("bad address");
+ p = netmulti(nif, f, binaddr, 1);
+ if(p)
+ error(p);
+ } else if((p = matchtoken(buf, "remmulti")) != 0){
+ if(parseaddr(binaddr, p, nif->alen) < 0)
+ error("bad address");
+ p = netmulti(nif, f, binaddr, 0);
+ if(p)
+ error(p);
+ } else
+ n = -1;
+ qunlock(nif);
+ poperror();
+ return n;
+}
+
+int
+netifwstat(Netif *nif, Chan *c, uchar *db, int n)
+{
+ Dir *dir;
+ Netfile *f;
+ int m;
+
+ f = nif->f[NETID(c->qid.path)];
+ if(f == 0)
+ error(Enonexist);
+
+ if(netown(f, up->user, OWRITE) < 0)
+ error(Eperm);
+
+ dir = smalloc(sizeof(Dir)+n);
+ m = convM2D(db, n, &dir[0], (char*)&dir[1]);
+ if(m == 0){
+ free(dir);
+ error(Eshortstat);
+ }
+ if(!emptystr(dir[0].uid))
+ strncpy(f->owner, dir[0].uid, KNAMELEN);
+ if(dir[0].mode != ~0UL)
+ f->mode = dir[0].mode;
+ free(dir);
+ return m;
+}
+
+int
+netifstat(Netif *nif, Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, (Dirtab *)nif, 0, netifgen);
+}
+
+void
+netifclose(Netif *nif, Chan *c)
+{
+ Netfile *f;
+ int t;
+ Netaddr *ap;
+
+ if((c->flag & COPEN) == 0)
+ return;
+
+ t = NETTYPE(c->qid.path);
+ if(t != Ndataqid && t != Nctlqid)
+ return;
+
+ f = nif->f[NETID(c->qid.path)];
+ qlock(f);
+ if(--(f->inuse) == 0){
+ if(f->prom){
+ qlock(nif);
+ if(--(nif->prom) == 0 && nif->promiscuous != nil)
+ nif->promiscuous(nif->arg, 0);
+ qunlock(nif);
+ f->prom = 0;
+ }
+ if(f->scan){
+ qlock(nif);
+ if(--(nif->scan) == 0 && nif->scanbs != nil)
+ nif->scanbs(nif->arg, 0);
+ qunlock(nif);
+ f->prom = 0;
+ f->scan = 0;
+ }
+ if(f->nmaddr){
+ qlock(nif);
+ t = 0;
+ for(ap = nif->maddr; ap; ap = ap->next){
+ if(f->maddr[t/8] & (1<<(t%8)))
+ netmulti(nif, f, ap->addr, 0);
+ }
+ qunlock(nif);
+ f->nmaddr = 0;
+ }
+ if(f->type < 0){
+ qlock(nif);
+ --(nif->all);
+ qunlock(nif);
+ }
+ f->owner[0] = 0;
+ f->type = 0;
+ f->bridge = 0;
+ f->headersonly = 0;
+ qclose(f->in);
+ }
+ qunlock(f);
+}
+
+Lock netlock;
+
+static int
+netown(Netfile *p, char *o, int omode)
+{
+ static int access[] = { 0400, 0200, 0600, 0100 };
+ int mode;
+ int t;
+
+ lock(&netlock);
+ if(*p->owner){
+ if(strncmp(o, p->owner, KNAMELEN) == 0) /* User */
+ mode = p->mode;
+ else if(strncmp(o, eve, KNAMELEN) == 0) /* Bootes is group */
+ mode = p->mode<<3;
+ else
+ mode = p->mode<<6; /* Other */
+
+ t = access[omode&3];
+ if((t & mode) == t){
+ unlock(&netlock);
+ return 0;
+ } else {
+ unlock(&netlock);
+ return -1;
+ }
+ }
+ strncpy(p->owner, o, KNAMELEN);
+ p->mode = 0660;
+ unlock(&netlock);
+ return 0;
+}
+
+/*
+ * Increment the reference count of a network device.
+ * If id < 0, return an unused ether device.
+ */
+static int
+openfile(Netif *nif, int id)
+{
+ Netfile *f, **fp, **efp;
+
+ if(id >= 0){
+ f = nif->f[id];
+ if(f == 0)
+ error(Enodev);
+ qlock(f);
+ qreopen(f->in);
+ f->inuse++;
+ qunlock(f);
+ return id;
+ }
+
+ qlock(nif);
+ if(waserror()){
+ qunlock(nif);
+ nexterror();
+ }
+ efp = &nif->f[nif->nfile];
+ for(fp = nif->f; fp < efp; fp++){
+ f = *fp;
+ if(f == 0){
+ f = malloc(sizeof(Netfile));
+ if(f == 0)
+ exhausted("memory");
+ f->in = qopen(nif->limit, Qmsg, 0, 0);
+ if(f->in == nil){
+ free(f);
+ exhausted("memory");
+ }
+ *fp = f;
+ qlock(f);
+ } else {
+ qlock(f);
+ if(f->inuse){
+ qunlock(f);
+ continue;
+ }
+ }
+ f->inuse = 1;
+ qreopen(f->in);
+ netown(f, up->user, 0);
+ qunlock(f);
+ qunlock(nif);
+ poperror();
+ return fp - nif->f;
+ }
+ error(Enodev);
+ return -1; /* not reached */
+}
+
+/*
+ * look for a token starting a string,
+ * return a pointer to first non-space char after it
+ */
+static char*
+matchtoken(char *p, char *token)
+{
+ int n;
+
+ n = strlen(token);
+ if(strncmp(p, token, n))
+ return 0;
+ p += n;
+ if(*p == 0)
+ return p;
+ if(*p != ' ' && *p != '\t' && *p != '\n')
+ return 0;
+ while(*p == ' ' || *p == '\t' || *p == '\n')
+ p++;
+ return p;
+}
+
+void
+hnputv(void *p, uvlong v)
+{
+ uchar *a;
+
+ a = p;
+ hnputl(a, v>>32);
+ hnputl(a+4, v);
+}
+
+void
+hnputl(void *p, uint v)
+{
+ uchar *a;
+
+ a = p;
+ a[0] = v>>24;
+ a[1] = v>>16;
+ a[2] = v>>8;
+ a[3] = v;
+}
+
+void
+hnputs(void *p, ushort v)
+{
+ uchar *a;
+
+ a = p;
+ a[0] = v>>8;
+ a[1] = v;
+}
+
+uvlong
+nhgetv(void *p)
+{
+ uchar *a;
+
+ a = p;
+ return ((vlong)nhgetl(a) << 32) | nhgetl(a+4);
+}
+
+uint
+nhgetl(void *p)
+{
+ uchar *a;
+
+ a = p;
+ return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0);
+}
+
+ushort
+nhgets(void *p)
+{
+ uchar *a;
+
+ a = p;
+ return (a[0]<<8)|(a[1]<<0);
+}
+
+static ulong
+hash(uchar *a, int len)
+{
+ ulong sum = 0;
+
+ while(len-- > 0)
+ sum = (sum << 1) + *a++;
+ return sum%Nmhash;
+}
+
+int
+activemulti(Netif *nif, uchar *addr, int alen)
+{
+ Netaddr *hp;
+
+ for(hp = nif->mhash[hash(addr, alen)]; hp; hp = hp->hnext)
+ if(memcmp(addr, hp->addr, alen) == 0){
+ if(hp->ref)
+ return 1;
+ else
+ break;
+ }
+ return 0;
+}
+
+static int
+parseaddr(uchar *to, char *from, int alen)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ for(i = 0; i < alen; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+/*
+ * keep track of multicast addresses
+ */
+static char*
+netmulti(Netif *nif, Netfile *f, uchar *addr, int add)
+{
+ Netaddr **l, *ap;
+ int i;
+ ulong h;
+
+ if(nif->multicast == nil)
+ return "interface does not support multicast";
+
+ l = &nif->maddr;
+ i = 0;
+ for(ap = *l; ap; ap = *l){
+ if(memcmp(addr, ap->addr, nif->alen) == 0)
+ break;
+ i++;
+ l = &ap->next;
+ }
+
+ if(add){
+ if(ap == 0){
+ *l = ap = smalloc(sizeof(*ap));
+ memmove(ap->addr, addr, nif->alen);
+ ap->next = 0;
+ ap->ref = 1;
+ h = hash(addr, nif->alen);
+ ap->hnext = nif->mhash[h];
+ nif->mhash[h] = ap;
+ } else {
+ ap->ref++;
+ }
+ if(ap->ref == 1){
+ nif->nmaddr++;
+ nif->multicast(nif->arg, addr, 1);
+ }
+ if(i < 8*sizeof(f->maddr)){
+ if((f->maddr[i/8] & (1<<(i%8))) == 0)
+ f->nmaddr++;
+ f->maddr[i/8] |= 1<<(i%8);
+ }
+ } else {
+ if(ap == 0 || ap->ref == 0)
+ return 0;
+ ap->ref--;
+ if(ap->ref == 0){
+ nif->nmaddr--;
+ nif->multicast(nif->arg, addr, 0);
+ }
+ if(i < 8*sizeof(f->maddr)){
+ if((f->maddr[i/8] & (1<<(i%8))) != 0)
+ f->nmaddr--;
+ f->maddr[i/8] &= ~(1<<(i%8));
+ }
+ }
+ return 0;
+}
diff --git a/sys/src/9/port/netif.h b/sys/src/9/port/netif.h
new file mode 100755
index 000000000..af1d5f455
--- /dev/null
+++ b/sys/src/9/port/netif.h
@@ -0,0 +1,139 @@
+typedef struct Etherpkt Etherpkt;
+typedef struct Netaddr Netaddr;
+typedef struct Netfile Netfile;
+typedef struct Netif Netif;
+
+enum
+{
+ Nmaxaddr= 64,
+ Nmhash= 31,
+
+ Ncloneqid= 1,
+ Naddrqid,
+ N2ndqid,
+ N3rdqid,
+ Ndataqid,
+ Nctlqid,
+ Nstatqid,
+ Ntypeqid,
+ Nifstatqid,
+};
+
+/*
+ * Macros to manage Qid's used for multiplexed devices
+ */
+#define NETTYPE(x) (((ulong)x)&0x1f)
+#define NETID(x) ((((ulong)x))>>5)
+#define NETQID(i,t) ((((ulong)i)<<5)|(t))
+
+/*
+ * one per multiplexed connection
+ */
+struct Netfile
+{
+ QLock;
+
+ int inuse;
+ ulong mode;
+ char owner[KNAMELEN];
+
+ int type; /* multiplexor type */
+ int prom; /* promiscuous mode */
+ int scan; /* base station scanning interval */
+ int bridge; /* bridge mode */
+ int headersonly; /* headers only - no data */
+ uchar maddr[8]; /* bitmask of multicast addresses requested */
+ int nmaddr; /* number of multicast addresses */
+
+ Queue *in; /* input buffer */
+};
+
+/*
+ * a network address
+ */
+struct Netaddr
+{
+ Netaddr *next; /* allocation chain */
+ Netaddr *hnext;
+ uchar addr[Nmaxaddr];
+ int ref;
+};
+
+/*
+ * a network interface
+ */
+struct Netif
+{
+ QLock;
+
+ /* multiplexing */
+ char name[KNAMELEN]; /* for top level directory */
+ int nfile; /* max number of Netfiles */
+ Netfile **f;
+
+ /* about net */
+ int limit; /* flow control */
+ int alen; /* address length */
+ int mbps; /* megabits per sec */
+ int link; /* link status */
+ uchar addr[Nmaxaddr];
+ uchar bcast[Nmaxaddr];
+ Netaddr *maddr; /* known multicast addresses */
+ int nmaddr; /* number of known multicast addresses */
+ Netaddr *mhash[Nmhash]; /* hash table of multicast addresses */
+ int prom; /* number of promiscuous opens */
+ int scan; /* number of base station scanners */
+ int all; /* number of -1 multiplexors */
+
+ /* statistics */
+ int misses;
+ uvlong inpackets;
+ uvlong outpackets;
+ int crcs; /* input crc errors */
+ int oerrs; /* output errors */
+ int frames; /* framing errors */
+ int overflows; /* packet overflows */
+ int buffs; /* buffering errors */
+ int soverflows; /* software overflow */
+
+ /* routines for touching the hardware */
+ void *arg;
+ void (*promiscuous)(void*, int);
+ void (*multicast)(void*, uchar*, int);
+ void (*scanbs)(void*, uint); /* scan for base stations */
+};
+
+void netifinit(Netif*, char*, int, ulong);
+Walkqid* netifwalk(Netif*, Chan*, Chan*, char **, int);
+Chan* netifopen(Netif*, Chan*, int);
+void netifclose(Netif*, Chan*);
+long netifread(Netif*, Chan*, void*, long, ulong);
+Block* netifbread(Netif*, Chan*, long, ulong);
+long netifwrite(Netif*, Chan*, void*, long);
+int netifwstat(Netif*, Chan*, uchar*, int);
+int netifstat(Netif*, Chan*, uchar*, int);
+int activemulti(Netif*, uchar*, int);
+
+/*
+ * Ethernet specific
+ */
+enum
+{
+ Eaddrlen= 6,
+ ETHERMINTU = 60, /* minimum transmit size */
+ ETHERMAXTU = 1514, /* maximum transmit size */
+ ETHERHDRSIZE = 14, /* size of an ethernet header */
+
+ /* ethernet packet types */
+ ETARP = 0x0806,
+ ETIP4 = 0x0800,
+ ETIP6 = 0x86DD,
+};
+
+struct Etherpkt
+{
+ uchar d[Eaddrlen];
+ uchar s[Eaddrlen];
+ uchar type[2];
+ uchar data[1500];
+};
diff --git a/sys/src/9/port/page.c b/sys/src/9/port/page.c
new file mode 100755
index 000000000..b99e3588b
--- /dev/null
+++ b/sys/src/9/port/page.c
@@ -0,0 +1,652 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#define pghash(daddr) palloc.hash[(daddr>>PGSHIFT)&(PGHSIZE-1)]
+
+struct Palloc palloc;
+
+void
+pageinit(void)
+{
+ int color, i, j;
+ Page *p;
+ Pallocmem *pm;
+ ulong m, np, k, vkb, pkb;
+
+ np = 0;
+ for(i=0; i<nelem(palloc.mem); i++){
+ pm = &palloc.mem[i];
+ np += pm->npage;
+ }
+ palloc.pages = xalloc(np*sizeof(Page));
+ if(palloc.pages == 0)
+ panic("pageinit");
+
+ color = 0;
+ palloc.head = palloc.pages;
+ p = palloc.head;
+ for(i=0; i<nelem(palloc.mem); i++){
+ pm = &palloc.mem[i];
+ for(j=0; j<pm->npage; j++){
+ p->prev = p-1;
+ p->next = p+1;
+ p->pa = pm->base+j*BY2PG;
+ p->color = color;
+ palloc.freecount++;
+ color = (color+1)%NCOLOR;
+ p++;
+ }
+ }
+ palloc.tail = p - 1;
+ palloc.head->prev = 0;
+ palloc.tail->next = 0;
+
+ palloc.user = p - palloc.pages;
+ pkb = palloc.user*BY2PG/1024;
+ vkb = pkb + (conf.nswap*BY2PG)/1024;
+
+ /* Paging numbers */
+ swapalloc.highwater = (palloc.user*5)/100;
+ swapalloc.headroom = swapalloc.highwater + (swapalloc.highwater/4);
+
+ m = 0;
+ for(i=0; i<nelem(conf.mem); i++)
+ if(conf.mem[i].npage)
+ m += conf.mem[i].npage*BY2PG;
+ k = PGROUND(end - (char*)KTZERO);
+ print("%ldM memory: ", (m+k+1024*1024-1)/(1024*1024));
+ print("%ldM kernel data, ", (m+k-pkb*1024+1024*1024-1)/(1024*1024));
+ print("%ldM user, ", pkb/1024);
+ print("%ldM swap\n", vkb/1024);
+}
+
+static void
+pageunchain(Page *p)
+{
+ if(canlock(&palloc))
+ panic("pageunchain (palloc %p)", &palloc);
+ if(p->prev)
+ p->prev->next = p->next;
+ else
+ palloc.head = p->next;
+ if(p->next)
+ p->next->prev = p->prev;
+ else
+ palloc.tail = p->prev;
+ p->prev = p->next = nil;
+ palloc.freecount--;
+}
+
+void
+pagechaintail(Page *p)
+{
+ if(canlock(&palloc))
+ panic("pagechaintail");
+ if(palloc.tail) {
+ p->prev = palloc.tail;
+ palloc.tail->next = p;
+ }
+ else {
+ palloc.head = p;
+ p->prev = 0;
+ }
+ palloc.tail = p;
+ p->next = 0;
+ palloc.freecount++;
+}
+
+void
+pagechainhead(Page *p)
+{
+ if(canlock(&palloc))
+ panic("pagechainhead");
+ if(palloc.head) {
+ p->next = palloc.head;
+ palloc.head->prev = p;
+ }
+ else {
+ palloc.tail = p;
+ p->next = 0;
+ }
+ palloc.head = p;
+ p->prev = 0;
+ palloc.freecount++;
+}
+
+Page*
+newpage(int clear, Segment **s, ulong va)
+{
+ Page *p;
+ KMap *k;
+ uchar ct;
+ int i, hw, dontalloc, color;
+
+ lock(&palloc);
+ color = getpgcolor(va);
+ hw = swapalloc.highwater;
+ for(;;) {
+ if(palloc.freecount > hw)
+ break;
+ if(up->kp && palloc.freecount > 0)
+ break;
+
+ unlock(&palloc);
+ dontalloc = 0;
+ if(s && *s) {
+ qunlock(&((*s)->lk));
+ *s = 0;
+ dontalloc = 1;
+ }
+ qlock(&palloc.pwait); /* Hold memory requesters here */
+
+ while(waserror()) /* Ignore interrupts */
+ ;
+
+ kickpager();
+ tsleep(&palloc.r, ispages, 0, 1000);
+
+ poperror();
+
+ qunlock(&palloc.pwait);
+
+ /*
+ * If called from fault and we lost the segment from
+ * underneath don't waste time allocating and freeing
+ * a page. Fault will call newpage again when it has
+ * reacquired the segment locks
+ */
+ if(dontalloc)
+ return 0;
+
+ lock(&palloc);
+ }
+
+ /* First try for our colour */
+ for(p = palloc.head; p; p = p->next)
+ if(p->color == color)
+ break;
+
+ ct = PG_NOFLUSH;
+ if(p == 0) {
+ p = palloc.head;
+ p->color = color;
+ ct = PG_NEWCOL;
+ }
+
+ pageunchain(p);
+
+ lock(p);
+ if(p->ref != 0)
+ panic("newpage: p->ref %d != 0", p->ref);
+
+ uncachepage(p);
+ p->ref++;
+ p->va = va;
+ p->modref = 0;
+ for(i = 0; i < MAXMACH; i++)
+ p->cachectl[i] = ct;
+ unlock(p);
+ unlock(&palloc);
+
+ if(clear) {
+ k = kmap(p);
+ memset((void*)VA(k), 0, BY2PG);
+ kunmap(k);
+ }
+
+ return p;
+}
+
+int
+ispages(void*)
+{
+ return palloc.freecount >= swapalloc.highwater;
+}
+
+void
+putpage(Page *p)
+{
+ if(onswap(p)) {
+ putswap(p);
+ return;
+ }
+
+ lock(&palloc);
+ lock(p);
+
+ if(p->ref == 0)
+ panic("putpage");
+
+ if(--p->ref > 0) {
+ unlock(p);
+ unlock(&palloc);
+ return;
+ }
+
+ if(p->image && p->image != &swapimage)
+ pagechaintail(p);
+ else
+ pagechainhead(p);
+
+ if(palloc.r.p != 0)
+ wakeup(&palloc.r);
+
+ unlock(p);
+ unlock(&palloc);
+}
+
+Page*
+auxpage(void)
+{
+ Page *p;
+
+ lock(&palloc);
+ p = palloc.head;
+ if(palloc.freecount < swapalloc.highwater) {
+ unlock(&palloc);
+ return 0;
+ }
+ pageunchain(p);
+
+ lock(p);
+ if(p->ref != 0)
+ panic("auxpage");
+ p->ref++;
+ uncachepage(p);
+ unlock(p);
+ unlock(&palloc);
+
+ return p;
+}
+
+static int dupretries = 15000;
+
+int
+duppage(Page *p) /* Always call with p locked */
+{
+ Page *np;
+ int color;
+ int retries;
+
+ retries = 0;
+retry:
+
+ if(retries++ > dupretries){
+ print("duppage %d, up %p\n", retries, up);
+ dupretries += 100;
+ if(dupretries > 100000)
+ panic("duppage\n");
+ uncachepage(p);
+ return 1;
+ }
+
+
+ /* don't dup pages with no image */
+ if(p->ref == 0 || p->image == nil || p->image->notext)
+ return 0;
+
+ /*
+ * normal lock ordering is to call
+ * lock(&palloc) before lock(p).
+ * To avoid deadlock, we have to drop
+ * our locks and try again.
+ */
+ if(!canlock(&palloc)){
+ unlock(p);
+ if(up)
+ sched();
+ lock(p);
+ goto retry;
+ }
+
+ /* No freelist cache when memory is very low */
+ if(palloc.freecount < swapalloc.highwater) {
+ unlock(&palloc);
+ uncachepage(p);
+ return 1;
+ }
+
+ color = getpgcolor(p->va);
+ for(np = palloc.head; np; np = np->next)
+ if(np->color == color)
+ break;
+
+ /* No page of the correct color */
+ if(np == 0) {
+ unlock(&palloc);
+ uncachepage(p);
+ return 1;
+ }
+
+ pageunchain(np);
+ pagechaintail(np);
+/*
+* XXX - here's a bug? - np is on the freelist but it's not really free.
+* when we unlock palloc someone else can come in, decide to
+* use np, and then try to lock it. they succeed after we've
+* run copypage and cachepage and unlock(np). then what?
+* they call pageunchain before locking(np), so it's removed
+* from the freelist, but still in the cache because of
+* cachepage below. if someone else looks in the cache
+* before they remove it, the page will have a nonzero ref
+* once they finally lock(np).
+*/
+ lock(np);
+ unlock(&palloc);
+
+ /* Cache the new version */
+ uncachepage(np);
+ np->va = p->va;
+ np->daddr = p->daddr;
+ copypage(p, np);
+ cachepage(np, p->image);
+ unlock(np);
+ uncachepage(p);
+
+ return 0;
+}
+
+void
+copypage(Page *f, Page *t)
+{
+ KMap *ks, *kd;
+
+ ks = kmap(f);
+ kd = kmap(t);
+ memmove((void*)VA(kd), (void*)VA(ks), BY2PG);
+ kunmap(ks);
+ kunmap(kd);
+}
+
+void
+uncachepage(Page *p) /* Always called with a locked page */
+{
+ Page **l, *f;
+
+ if(p->image == 0)
+ return;
+
+ lock(&palloc.hashlock);
+ l = &pghash(p->daddr);
+ for(f = *l; f; f = f->hash) {
+ if(f == p) {
+ *l = p->hash;
+ break;
+ }
+ l = &f->hash;
+ }
+ unlock(&palloc.hashlock);
+ putimage(p->image);
+ p->image = 0;
+ p->daddr = 0;
+}
+
+void
+cachepage(Page *p, Image *i)
+{
+ Page **l;
+
+ /* If this ever happens it should be fixed by calling
+ * uncachepage instead of panic. I think there is a race
+ * with pio in which this can happen. Calling uncachepage is
+ * correct - I just wanted to see if we got here.
+ */
+ if(p->image)
+ panic("cachepage");
+
+ incref(i);
+ lock(&palloc.hashlock);
+ p->image = i;
+ l = &pghash(p->daddr);
+ p->hash = *l;
+ *l = p;
+ unlock(&palloc.hashlock);
+}
+
+void
+cachedel(Image *i, ulong daddr)
+{
+ Page *f, **l;
+
+ lock(&palloc.hashlock);
+ l = &pghash(daddr);
+ for(f = *l; f; f = f->hash) {
+ if(f->image == i && f->daddr == daddr) {
+ lock(f);
+ if(f->image == i && f->daddr == daddr){
+ *l = f->hash;
+ putimage(f->image);
+ f->image = 0;
+ f->daddr = 0;
+ }
+ unlock(f);
+ break;
+ }
+ l = &f->hash;
+ }
+ unlock(&palloc.hashlock);
+}
+
+Page *
+lookpage(Image *i, ulong daddr)
+{
+ Page *f;
+
+ lock(&palloc.hashlock);
+ for(f = pghash(daddr); f; f = f->hash) {
+ if(f->image == i && f->daddr == daddr) {
+ unlock(&palloc.hashlock);
+
+ lock(&palloc);
+ lock(f);
+ if(f->image != i || f->daddr != daddr) {
+ unlock(f);
+ unlock(&palloc);
+ return 0;
+ }
+ if(++f->ref == 1)
+ pageunchain(f);
+ unlock(&palloc);
+ unlock(f);
+
+ return f;
+ }
+ }
+ unlock(&palloc.hashlock);
+
+ return 0;
+}
+
+Pte*
+ptecpy(Pte *old)
+{
+ Pte *new;
+ Page **src, **dst;
+
+ new = ptealloc();
+ dst = &new->pages[old->first-old->pages];
+ new->first = dst;
+ for(src = old->first; src <= old->last; src++, dst++)
+ if(*src) {
+ if(onswap(*src))
+ dupswap(*src);
+ else {
+ lock(*src);
+ (*src)->ref++;
+ unlock(*src);
+ }
+ new->last = dst;
+ *dst = *src;
+ }
+
+ return new;
+}
+
+Pte*
+ptealloc(void)
+{
+ Pte *new;
+
+ new = smalloc(sizeof(Pte));
+ new->first = &new->pages[PTEPERTAB];
+ new->last = new->pages;
+ return new;
+}
+
+void
+freepte(Segment *s, Pte *p)
+{
+ int ref;
+ void (*fn)(Page*);
+ Page *pt, **pg, **ptop;
+
+ switch(s->type&SG_TYPE) {
+ case SG_PHYSICAL:
+ fn = s->pseg->pgfree;
+ ptop = &p->pages[PTEPERTAB];
+ if(fn) {
+ for(pg = p->pages; pg < ptop; pg++) {
+ if(*pg == 0)
+ continue;
+ (*fn)(*pg);
+ *pg = 0;
+ }
+ break;
+ }
+ for(pg = p->pages; pg < ptop; pg++) {
+ pt = *pg;
+ if(pt == 0)
+ continue;
+ lock(pt);
+ ref = --pt->ref;
+ unlock(pt);
+ if(ref == 0)
+ free(pt);
+ }
+ break;
+ default:
+ for(pg = p->first; pg <= p->last; pg++)
+ if(*pg) {
+ putpage(*pg);
+ *pg = 0;
+ }
+ }
+ free(p);
+}
+
+ulong
+pagenumber(Page *p)
+{
+ return p-palloc.pages;
+}
+
+void
+checkpagerefs(void)
+{
+ int s;
+ ulong i, np, nwrong;
+ ulong *ref;
+
+ np = palloc.user;
+ ref = malloc(np*sizeof ref[0]);
+ if(ref == nil){
+ print("checkpagerefs: out of memory\n");
+ return;
+ }
+
+ /*
+ * This may not be exact if there are other processes
+ * holding refs to pages on their stacks. The hope is
+ * that if you run it on a quiescent system it will still
+ * be useful.
+ */
+ s = splhi();
+ lock(&palloc);
+ countpagerefs(ref, 0);
+ portcountpagerefs(ref, 0);
+ nwrong = 0;
+ for(i=0; i<np; i++){
+ if(palloc.pages[i].ref != ref[i]){
+ iprint("page %#.8lux ref %d actual %lud\n",
+ palloc.pages[i].pa, palloc.pages[i].ref, ref[i]);
+ ref[i] = 1;
+ nwrong++;
+ }else
+ ref[i] = 0;
+ }
+ countpagerefs(ref, 1);
+ portcountpagerefs(ref, 1);
+ iprint("%lud mistakes found\n", nwrong);
+ unlock(&palloc);
+ splx(s);
+}
+
+void
+portcountpagerefs(ulong *ref, int print)
+{
+ ulong i, j, k, ns, n;
+ Page **pg, *entry;
+ Proc *p;
+ Pte *pte;
+ Segment *s;
+
+ /*
+ * Pages in segments. s->mark avoids double-counting.
+ */
+ n = 0;
+ ns = 0;
+ for(i=0; i<conf.nproc; i++){
+ p = proctab(i);
+ for(j=0; j<NSEG; j++){
+ s = p->seg[j];
+ if(s)
+ s->mark = 0;
+ }
+ }
+ for(i=0; i<conf.nproc; i++){
+ p = proctab(i);
+ for(j=0; j<NSEG; j++){
+ s = p->seg[j];
+ if(s == nil || s->mark++)
+ continue;
+ ns++;
+ for(k=0; k<s->mapsize; k++){
+ pte = s->map[k];
+ if(pte == nil)
+ continue;
+ for(pg = pte->first; pg <= pte->last; pg++){
+ entry = *pg;
+ if(pagedout(entry))
+ continue;
+ if(print){
+ if(ref[pagenumber(entry)])
+ iprint("page %#.8lux in segment %#p\n", entry->pa, s);
+ continue;
+ }
+ if(ref[pagenumber(entry)]++ == 0)
+ n++;
+ }
+ }
+ }
+ }
+ if(!print){
+ iprint("%lud pages in %lud segments\n", n, ns);
+ for(i=0; i<conf.nproc; i++){
+ p = proctab(i);
+ for(j=0; j<NSEG; j++){
+ s = p->seg[j];
+ if(s == nil)
+ continue;
+ if(s->ref != s->mark){
+ iprint("segment %#p (used by proc %lud pid %lud) has bad ref count %lud actual %lud\n",
+ s, i, p->pid, s->ref, s->mark);
+ }
+ }
+ }
+ }
+}
+
diff --git a/sys/src/9/port/parse.c b/sys/src/9/port/parse.c
new file mode 100755
index 000000000..9d59b5672
--- /dev/null
+++ b/sys/src/9/port/parse.c
@@ -0,0 +1,114 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+/*
+ * Generous estimate of number of fields, including terminal nil pointer
+ */
+static int
+ncmdfield(char *p, int n)
+{
+ int white, nwhite;
+ char *ep;
+ int nf;
+
+ if(p == nil)
+ return 1;
+
+ nf = 0;
+ ep = p+n;
+ white = 1; /* first text will start field */
+ while(p < ep){
+ nwhite = (strchr(" \t\r\n", *p++ & 0xFF) != 0); /* UTF is irrelevant */
+ if(white && !nwhite) /* beginning of field */
+ nf++;
+ white = nwhite;
+ }
+ return nf+1; /* +1 for nil */
+}
+
+/*
+ * parse a command written to a device
+ */
+Cmdbuf*
+parsecmd(char *p, int n)
+{
+ Cmdbuf *volatile cb;
+ int nf;
+ char *sp;
+
+ nf = ncmdfield(p, n);
+
+ /* allocate Cmdbuf plus string pointers plus copy of string including \0 */
+ sp = smalloc(sizeof(*cb) + nf * sizeof(char*) + n + 1);
+ cb = (Cmdbuf*)sp;
+ cb->f = (char**)(&cb[1]);
+ cb->buf = (char*)(&cb->f[nf]);
+
+ if(up!=nil && waserror()){
+ free(cb);
+ nexterror();
+ }
+ memmove(cb->buf, p, n);
+ if(up != nil)
+ poperror();
+
+ /* dump new line and null terminate */
+ if(n > 0 && cb->buf[n-1] == '\n')
+ n--;
+ cb->buf[n] = '\0';
+
+ cb->nf = tokenize(cb->buf, cb->f, nf-1);
+ cb->f[cb->nf] = nil;
+
+ return cb;
+}
+
+/*
+ * Reconstruct original message, for error diagnostic
+ */
+void
+cmderror(Cmdbuf *cb, char *s)
+{
+ int i;
+ char *p, *e;
+
+ p = up->genbuf;
+ e = p+ERRMAX-10;
+ p = seprint(p, e, "%s \"", s);
+ for(i=0; i<cb->nf; i++){
+ if(i > 0)
+ p = seprint(p, e, " ");
+ p = seprint(p, e, "%q", cb->f[i]);
+ }
+ strcpy(p, "\"");
+ error(up->genbuf);
+}
+
+/*
+ * Look up entry in table
+ */
+Cmdtab*
+lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab)
+{
+ int i;
+ Cmdtab *ct;
+
+ if(cb->nf == 0)
+ error("empty control message");
+
+ for(ct = ctab, i=0; i<nctab; i++, ct++){
+ if(strcmp(ct->cmd, "*") !=0) /* wildcard always matches */
+ if(strcmp(ct->cmd, cb->f[0]) != 0)
+ continue;
+ if(ct->narg != 0 && ct->narg != cb->nf)
+ cmderror(cb, Ecmdargs);
+ return ct;
+ }
+
+ cmderror(cb, "unknown control message");
+ return nil;
+}
diff --git a/sys/src/9/port/pgrp.c b/sys/src/9/port/pgrp.c
new file mode 100755
index 000000000..22fc78b56
--- /dev/null
+++ b/sys/src/9/port/pgrp.c
@@ -0,0 +1,320 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+enum {
+ Whinesecs = 10, /* frequency of out-of-resources printing */
+};
+
+static Ref pgrpid;
+static Ref mountid;
+
+void
+pgrpnote(ulong noteid, char *a, long n, int flag)
+{
+ Proc *p, *ep;
+ char buf[ERRMAX];
+
+ if(n >= ERRMAX-1)
+ error(Etoobig);
+
+ memmove(buf, a, n);
+ buf[n] = 0;
+ p = proctab(0);
+ ep = p+conf.nproc;
+ for(; p < ep; p++) {
+ if(p->state == Dead)
+ continue;
+ if(up != p && p->noteid == noteid && p->kp == 0) {
+ qlock(&p->debug);
+ if(p->pid == 0 || p->noteid != noteid){
+ qunlock(&p->debug);
+ continue;
+ }
+ if(!waserror()) {
+ postnote(p, 0, buf, flag);
+ poperror();
+ }
+ qunlock(&p->debug);
+ }
+ }
+}
+
+Pgrp*
+newpgrp(void)
+{
+ Pgrp *p;
+
+ p = smalloc(sizeof(Pgrp));
+ p->ref = 1;
+ p->pgrpid = incref(&pgrpid);
+ return p;
+}
+
+Rgrp*
+newrgrp(void)
+{
+ Rgrp *r;
+
+ r = smalloc(sizeof(Rgrp));
+ r->ref = 1;
+ return r;
+}
+
+void
+closergrp(Rgrp *r)
+{
+ if(decref(r) == 0)
+ free(r);
+}
+
+void
+closepgrp(Pgrp *p)
+{
+ Mhead **h, **e, *f, *next;
+
+ if(decref(p) != 0)
+ return;
+
+ qlock(&p->debug);
+ wlock(&p->ns);
+ p->pgrpid = -1;
+
+ e = &p->mnthash[MNTHASH];
+ for(h = p->mnthash; h < e; h++) {
+ for(f = *h; f; f = next) {
+ wlock(&f->lock);
+ cclose(f->from);
+ mountfree(f->mount);
+ f->mount = nil;
+ next = f->hash;
+ wunlock(&f->lock);
+ putmhead(f);
+ }
+ }
+ wunlock(&p->ns);
+ qunlock(&p->debug);
+ free(p);
+}
+
+void
+pgrpinsert(Mount **order, Mount *m)
+{
+ Mount *f;
+
+ m->order = 0;
+ if(*order == 0) {
+ *order = m;
+ return;
+ }
+ for(f = *order; f; f = f->order) {
+ if(m->mountid < f->mountid) {
+ m->order = f;
+ *order = m;
+ return;
+ }
+ order = &f->order;
+ }
+ *order = m;
+}
+
+/*
+ * pgrpcpy MUST preserve the mountid allocation order of the parent group
+ */
+void
+pgrpcpy(Pgrp *to, Pgrp *from)
+{
+ int i;
+ Mount *n, *m, **link, *order;
+ Mhead *f, **tom, **l, *mh;
+
+ wlock(&from->ns);
+ order = 0;
+ tom = to->mnthash;
+ for(i = 0; i < MNTHASH; i++) {
+ l = tom++;
+ for(f = from->mnthash[i]; f; f = f->hash) {
+ rlock(&f->lock);
+ mh = newmhead(f->from);
+ *l = mh;
+ l = &mh->hash;
+ link = &mh->mount;
+ for(m = f->mount; m; m = m->next) {
+ n = newmount(mh, m->to, m->mflag, m->spec);
+ m->copy = n;
+ pgrpinsert(&order, m);
+ *link = n;
+ link = &n->next;
+ }
+ runlock(&f->lock);
+ }
+ }
+ /*
+ * Allocate mount ids in the same sequence as the parent group
+ */
+ lock(&mountid);
+ for(m = order; m; m = m->order)
+ m->copy->mountid = mountid.ref++;
+ unlock(&mountid);
+ wunlock(&from->ns);
+}
+
+Fgrp*
+dupfgrp(Fgrp *f)
+{
+ Fgrp *new;
+ Chan *c;
+ int i;
+
+ new = smalloc(sizeof(Fgrp));
+ if(f == nil){
+ new->fd = smalloc(DELTAFD*sizeof(Chan*));
+ new->nfd = DELTAFD;
+ new->ref = 1;
+ return new;
+ }
+
+ lock(f);
+ /* Make new fd list shorter if possible, preserving quantization */
+ new->nfd = f->maxfd+1;
+ i = new->nfd%DELTAFD;
+ if(i != 0)
+ new->nfd += DELTAFD - i;
+ new->fd = malloc(new->nfd*sizeof(Chan*));
+ if(new->fd == nil){
+ unlock(f);
+ free(new);
+ error("no memory for fgrp");
+ }
+ new->ref = 1;
+
+ new->maxfd = f->maxfd;
+ for(i = 0; i <= f->maxfd; i++) {
+ if(c = f->fd[i]){
+ incref(c);
+ new->fd[i] = c;
+ }
+ }
+ unlock(f);
+
+ return new;
+}
+
+void
+closefgrp(Fgrp *f)
+{
+ int i;
+ Chan *c;
+
+ if(f == 0)
+ return;
+
+ if(decref(f) != 0)
+ return;
+
+ /*
+ * If we get into trouble, forceclosefgrp
+ * will bail us out.
+ */
+ up->closingfgrp = f;
+ for(i = 0; i <= f->maxfd; i++)
+ if(c = f->fd[i]){
+ f->fd[i] = nil;
+ cclose(c);
+ }
+ up->closingfgrp = nil;
+
+ free(f->fd);
+ free(f);
+}
+
+/*
+ * Called from sleep because up is in the middle
+ * of closefgrp and just got a kill ctl message.
+ * This usually means that up has wedged because
+ * of some kind of deadly embrace with mntclose
+ * trying to talk to itself. To break free, hand the
+ * unclosed channels to the close queue. Once they
+ * are finished, the blocked cclose that we've
+ * interrupted will finish by itself.
+ */
+void
+forceclosefgrp(void)
+{
+ int i;
+ Chan *c;
+ Fgrp *f;
+
+ if(up->procctl != Proc_exitme || up->closingfgrp == nil){
+ print("bad forceclosefgrp call");
+ return;
+ }
+
+ f = up->closingfgrp;
+ for(i = 0; i <= f->maxfd; i++)
+ if(c = f->fd[i]){
+ f->fd[i] = nil;
+ ccloseq(c);
+ }
+}
+
+
+Mount*
+newmount(Mhead *mh, Chan *to, int flag, char *spec)
+{
+ Mount *m;
+
+ m = smalloc(sizeof(Mount));
+ m->to = to;
+ m->head = mh;
+ incref(to);
+ m->mountid = incref(&mountid);
+ m->mflag = flag;
+ if(spec != 0)
+ kstrdup(&m->spec, spec);
+
+ return m;
+}
+
+void
+mountfree(Mount *m)
+{
+ Mount *f;
+
+ while(m) {
+ f = m->next;
+ cclose(m->to);
+ m->mountid = 0;
+ free(m->spec);
+ free(m);
+ m = f;
+ }
+}
+
+void
+resrcwait(char *reason)
+{
+ ulong now;
+ char *p;
+ static ulong lastwhine;
+
+ if(up == 0)
+ panic("resrcwait");
+
+ p = up->psstate;
+ if(reason) {
+ up->psstate = reason;
+ now = seconds();
+ /* don't tie up the console with complaints */
+ if(now - lastwhine > Whinesecs) {
+ lastwhine = now;
+ print("%s\n", reason);
+ }
+ }
+
+ tsleep(&up->sleep, return0, 0, 300);
+ up->psstate = p;
+}
diff --git a/sys/src/9/port/portclock.c b/sys/src/9/port/portclock.c
new file mode 100755
index 000000000..624283d3c
--- /dev/null
+++ b/sys/src/9/port/portclock.c
@@ -0,0 +1,272 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+struct Timers
+{
+ Lock;
+ Timer *head;
+};
+
+static Timers timers[MAXMACH];
+
+ulong intrcount[MAXMACH];
+ulong fcallcount[MAXMACH];
+
+static vlong
+tadd(Timers *tt, Timer *nt)
+{
+ Timer *t, **last;
+
+ /* Called with tt locked */
+ assert(nt->tt == nil);
+ switch(nt->tmode){
+ default:
+ panic("timer");
+ break;
+ case Trelative:
+ if(nt->tns <= 0)
+ nt->tns = 1;
+ nt->twhen = fastticks(nil) + ns2fastticks(nt->tns);
+ break;
+ case Tperiodic:
+ assert(nt->tns >= 100000); /* At least 100 µs period */
+ if(nt->twhen == 0){
+ /* look for another timer at same frequency for combining */
+ for(t = tt->head; t; t = t->tnext){
+ if(t->tmode == Tperiodic && t->tns == nt->tns)
+ break;
+ }
+ if (t)
+ nt->twhen = t->twhen;
+ else
+ nt->twhen = fastticks(nil);
+ }
+ nt->twhen += ns2fastticks(nt->tns);
+ break;
+ }
+
+ for(last = &tt->head; t = *last; last = &t->tnext){
+ if(t->twhen > nt->twhen)
+ break;
+ }
+ nt->tnext = *last;
+ *last = nt;
+ nt->tt = tt;
+ if(last == &tt->head)
+ return nt->twhen;
+ return 0;
+}
+
+static uvlong
+tdel(Timer *dt)
+{
+
+ Timer *t, **last;
+ Timers *tt;
+
+ tt = dt->tt;
+ if (tt == nil)
+ return 0;
+ for(last = &tt->head; t = *last; last = &t->tnext){
+ if(t == dt){
+ assert(dt->tt);
+ dt->tt = nil;
+ *last = t->tnext;
+ break;
+ }
+ }
+ if(last == &tt->head && tt->head)
+ return tt->head->twhen;
+ return 0;
+}
+
+/* add or modify a timer */
+void
+timeradd(Timer *nt)
+{
+ Timers *tt;
+ vlong when;
+
+ /* Must lock Timer struct before Timers struct */
+ ilock(nt);
+ if(tt = nt->tt){
+ ilock(tt);
+ tdel(nt);
+ iunlock(tt);
+ }
+ tt = &timers[m->machno];
+ ilock(tt);
+ when = tadd(tt, nt);
+ if(when)
+ timerset(when);
+ iunlock(tt);
+ iunlock(nt);
+}
+
+
+void
+timerdel(Timer *dt)
+{
+ Timers *tt;
+ uvlong when;
+
+ ilock(dt);
+ if(tt = dt->tt){
+ ilock(tt);
+ when = tdel(dt);
+ if(when && tt == &timers[m->machno])
+ timerset(tt->head->twhen);
+ iunlock(tt);
+ }
+ iunlock(dt);
+}
+
+void
+hzclock(Ureg *ur)
+{
+ m->ticks++;
+ if(m->proc)
+ m->proc->pc = ur->pc;
+
+ if(m->flushmmu){
+ if(up)
+ flushmmu();
+ m->flushmmu = 0;
+ }
+
+ accounttime();
+ kmapinval();
+
+ if(kproftimer != nil)
+ kproftimer(ur->pc);
+
+ if((active.machs&(1<<m->machno)) == 0)
+ return;
+
+ if(active.exiting) {
+ print("someone's exiting\n");
+ exit(0);
+ }
+
+ checkalarms();
+
+ if(up && up->state == Running)
+ hzsched(); /* in proc.c */
+}
+
+void
+timerintr(Ureg *u, Tval)
+{
+ Timer *t;
+ Timers *tt;
+ uvlong when, now;
+ int callhzclock;
+ static int sofar;
+
+ intrcount[m->machno]++;
+ callhzclock = 0;
+ tt = &timers[m->machno];
+ now = fastticks(nil);
+ ilock(tt);
+ while(t = tt->head){
+ /*
+ * No need to ilock t here: any manipulation of t
+ * requires tdel(t) and this must be done with a
+ * lock to tt held. We have tt, so the tdel will
+ * wait until we're done
+ */
+ when = t->twhen;
+ if(when > now){
+ timerset(when);
+ iunlock(tt);
+ if(callhzclock)
+ hzclock(u);
+ return;
+ }
+ tt->head = t->tnext;
+ assert(t->tt == tt);
+ t->tt = nil;
+ fcallcount[m->machno]++;
+ iunlock(tt);
+ if(t->tf)
+ (*t->tf)(u, t);
+ else
+ callhzclock++;
+ ilock(tt);
+ if(t->tmode == Tperiodic)
+ tadd(tt, t);
+ }
+ iunlock(tt);
+}
+
+void
+timersinit(void)
+{
+ Timer *t;
+
+ /*
+ * T->tf == nil means the HZ clock for this processor.
+ */
+ todinit();
+ t = malloc(sizeof(*t));
+ t->tmode = Tperiodic;
+ t->tt = nil;
+ t->tns = 1000000000/HZ;
+ t->tf = nil;
+ timeradd(t);
+}
+
+Timer*
+addclock0link(void (*f)(void), int ms)
+{
+ Timer *nt;
+ uvlong when;
+
+ /* Synchronize to hztimer if ms is 0 */
+ nt = malloc(sizeof(Timer));
+ if(ms == 0)
+ ms = 1000/HZ;
+ nt->tns = (vlong)ms*1000000LL;
+ nt->tmode = Tperiodic;
+ nt->tt = nil;
+ nt->tf = (void (*)(Ureg*, Timer*))f;
+
+ ilock(&timers[0]);
+ when = tadd(&timers[0], nt);
+ if(when)
+ timerset(when);
+ iunlock(&timers[0]);
+ return nt;
+}
+
+/*
+ * This tk2ms avoids overflows that the macro version is prone to.
+ * It is a LOT slower so shouldn't be used if you're just converting
+ * a delta.
+ */
+ulong
+tk2ms(ulong ticks)
+{
+ uvlong t, hz;
+
+ t = ticks;
+ hz = HZ;
+ t *= 1000L;
+ t = t/hz;
+ ticks = t;
+ return ticks;
+}
+
+ulong
+ms2tk(ulong ms)
+{
+ /* avoid overflows at the cost of precision */
+ if(ms >= 1000000000/HZ)
+ return (ms/1000)*HZ;
+ return (ms*HZ+500)/1000;
+}
diff --git a/sys/src/9/port/portdat.h b/sys/src/9/port/portdat.h
new file mode 100755
index 000000000..6d8a59c0b
--- /dev/null
+++ b/sys/src/9/port/portdat.h
@@ -0,0 +1,961 @@
+typedef struct Alarms Alarms;
+typedef struct Block Block;
+typedef struct Chan Chan;
+typedef struct Cmdbuf Cmdbuf;
+typedef struct Cmdtab Cmdtab;
+typedef struct Confmem Confmem;
+typedef struct Dev Dev;
+typedef struct Dirtab Dirtab;
+typedef struct Edf Edf;
+typedef struct Egrp Egrp;
+typedef struct Evalue Evalue;
+typedef struct Fgrp Fgrp;
+typedef struct DevConf DevConf;
+typedef struct Image Image;
+typedef struct Log Log;
+typedef struct Logflag Logflag;
+typedef struct Mntcache Mntcache;
+typedef struct Mount Mount;
+typedef struct Mntrpc Mntrpc;
+typedef struct Mntwalk Mntwalk;
+typedef struct Mnt Mnt;
+typedef struct Mhead Mhead;
+typedef struct Note Note;
+typedef struct Page Page;
+typedef struct Path Path;
+typedef struct Palloc Palloc;
+typedef struct Pallocmem Pallocmem;
+typedef struct Perf Perf;
+typedef struct PhysUart PhysUart;
+typedef struct Pgrp Pgrp;
+typedef struct Physseg Physseg;
+typedef struct Proc Proc;
+typedef struct Pte Pte;
+typedef struct QLock QLock;
+typedef struct Queue Queue;
+typedef struct Ref Ref;
+typedef struct Rendez Rendez;
+typedef struct Rgrp Rgrp;
+typedef struct RWlock RWlock;
+typedef struct Sargs Sargs;
+typedef struct Schedq Schedq;
+typedef struct Segment Segment;
+typedef struct Sema Sema;
+typedef struct Timer Timer;
+typedef struct Timers Timers;
+typedef struct Uart Uart;
+typedef struct Waitq Waitq;
+typedef struct Walkqid Walkqid;
+typedef struct Watchdog Watchdog;
+typedef int Devgen(Chan*, char*, Dirtab*, int, int, Dir*);
+
+#pragma incomplete DevConf
+#pragma incomplete Edf
+#pragma incomplete Mntcache
+#pragma incomplete Mntrpc
+#pragma incomplete Queue
+#pragma incomplete Timers
+
+#include <fcall.h>
+
+struct Ref
+{
+ Lock;
+ long ref;
+};
+
+struct Rendez
+{
+ Lock;
+ Proc *p;
+};
+
+struct QLock
+{
+ Lock use; /* to access Qlock structure */
+ Proc *head; /* next process waiting for object */
+ Proc *tail; /* last process waiting for object */
+ int locked; /* flag */
+};
+
+struct RWlock
+{
+ Lock use;
+ Proc *head; /* list of waiting processes */
+ Proc *tail;
+ ulong wpc; /* pc of writer */
+ Proc *wproc; /* writing proc */
+ int readers; /* number of readers */
+ int writer; /* number of writers */
+};
+
+struct Alarms
+{
+ QLock;
+ Proc *head;
+};
+
+struct Sargs
+{
+ ulong args[MAXSYSARG];
+};
+
+/*
+ * Access types in namec & channel flags
+ */
+enum
+{
+ Aaccess, /* as in stat, wstat */
+ Abind, /* for left-hand-side of bind */
+ Atodir, /* as in chdir */
+ Aopen, /* for i/o */
+ Amount, /* to be mounted or mounted upon */
+ Acreate, /* is to be created */
+ Aremove, /* will be removed by caller */
+
+ COPEN = 0x0001, /* for i/o */
+ CMSG = 0x0002, /* the message channel for a mount */
+/*rsc CCREATE = 0x0004, /* permits creation if c->mnt */
+ CCEXEC = 0x0008, /* close on exec */
+ CFREE = 0x0010, /* not in use */
+ CRCLOSE = 0x0020, /* remove on close */
+ CCACHE = 0x0080, /* client cache */
+};
+
+/* flag values */
+enum
+{
+ BINTR = (1<<0),
+ BFREE = (1<<1),
+ Bipck = (1<<2), /* ip checksum */
+ Budpck = (1<<3), /* udp checksum */
+ Btcpck = (1<<4), /* tcp checksum */
+ Bpktck = (1<<5), /* packet checksum */
+};
+
+struct Block
+{
+ long ref;
+ Block* next;
+ Block* list;
+ uchar* rp; /* first unconsumed byte */
+ uchar* wp; /* first empty byte */
+ uchar* lim; /* 1 past the end of the buffer */
+ uchar* base; /* start of the buffer */
+ void (*free)(Block*);
+ ushort flag;
+ ushort checksum; /* IP checksum of complete packet (minus media header) */
+};
+
+#define BLEN(s) ((s)->wp - (s)->rp)
+#define BALLOC(s) ((s)->lim - (s)->base)
+
+struct Chan
+{
+ Ref; /* the Lock in this Ref is also Chan's lock */
+ Chan* next; /* allocation */
+ Chan* link;
+ vlong offset; /* in fd */
+ vlong devoffset; /* in underlying device; see read */
+ ushort type;
+ ulong dev;
+ ushort mode; /* read/write */
+ ushort flag;
+ Qid qid;
+ int fid; /* for devmnt */
+ ulong iounit; /* chunk size for i/o; 0==default */
+ Mhead* umh; /* mount point that derived Chan; used in unionread */
+ Chan* umc; /* channel in union; held for union read */
+ QLock umqlock; /* serialize unionreads */
+ int uri; /* union read index */
+ int dri; /* devdirread index */
+ uchar* dirrock; /* directory entry rock for translations */
+ int nrock;
+ int mrock;
+ QLock rockqlock;
+ int ismtpt;
+ Mntcache*mcp; /* Mount cache pointer */
+ Mnt* mux; /* Mnt for clients using me for messages */
+ union {
+ void* aux;
+ Qid pgrpid; /* for #p/notepg */
+ ulong mid; /* for ns in devproc */
+ };
+ Chan* mchan; /* channel to mounted server */
+ Qid mqid; /* qid of root of mount point */
+ Path* path;
+};
+
+struct Path
+{
+ Ref;
+ char *s;
+ Chan **mtpt; /* mtpt history */
+ int len; /* strlen(s) */
+ int alen; /* allocated length of s */
+ int mlen; /* number of path elements */
+ int malen; /* allocated length of mtpt */
+};
+
+struct Dev
+{
+ int dc;
+ char* name;
+
+ void (*reset)(void);
+ void (*init)(void);
+ void (*shutdown)(void);
+ Chan* (*attach)(char*);
+ Walkqid*(*walk)(Chan*, Chan*, char**, int);
+ int (*stat)(Chan*, uchar*, int);
+ Chan* (*open)(Chan*, int);
+ void (*create)(Chan*, char*, int, ulong);
+ void (*close)(Chan*);
+ long (*read)(Chan*, void*, long, vlong);
+ Block* (*bread)(Chan*, long, ulong);
+ long (*write)(Chan*, void*, long, vlong);
+ long (*bwrite)(Chan*, Block*, ulong);
+ void (*remove)(Chan*);
+ int (*wstat)(Chan*, uchar*, int);
+ void (*power)(int); /* power mgt: power(1) => on, power (0) => off */
+ int (*config)(int, char*, DevConf*); /* returns nil on error */
+};
+
+struct Dirtab
+{
+ char name[KNAMELEN];
+ Qid qid;
+ vlong length;
+ long perm;
+};
+
+struct Walkqid
+{
+ Chan *clone;
+ int nqid;
+ Qid qid[1];
+};
+
+enum
+{
+ NSMAX = 1000,
+ NSLOG = 7,
+ NSCACHE = (1<<NSLOG),
+};
+
+struct Mntwalk /* state for /proc/#/ns */
+{
+ int cddone;
+ Mhead* mh;
+ Mount* cm;
+};
+
+struct Mount
+{
+ ulong mountid;
+ Mount* next;
+ Mhead* head;
+ Mount* copy;
+ Mount* order;
+ Chan* to; /* channel replacing channel */
+ int mflag;
+ char *spec;
+};
+
+struct Mhead
+{
+ Ref;
+ RWlock lock;
+ Chan* from; /* channel mounted upon */
+ Mount* mount; /* what's mounted upon it */
+ Mhead* hash; /* Hash chain */
+};
+
+struct Mnt
+{
+ Lock;
+ /* references are counted using c->ref; channels on this mount point incref(c->mchan) == Mnt.c */
+ Chan *c; /* Channel to file service */
+ Proc *rip; /* Reader in progress */
+ Mntrpc *queue; /* Queue of pending requests on this channel */
+ ulong id; /* Multiplexer id for channel check */
+ Mnt *list; /* Free list */
+ int flags; /* cache */
+ int msize; /* data + IOHDRSZ */
+ char *version; /* 9P version */
+ Queue *q; /* input queue */
+};
+
+enum
+{
+ NUser, /* note provided externally */
+ NExit, /* deliver note quietly */
+ NDebug, /* print debug message */
+};
+
+struct Note
+{
+ char msg[ERRMAX];
+ int flag; /* whether system posted it */
+};
+
+enum
+{
+ PG_NOFLUSH = 0,
+ PG_TXTFLUSH = 1, /* flush dcache and invalidate icache */
+ PG_DATFLUSH = 2, /* flush both i & d caches (UNUSED) */
+ PG_NEWCOL = 3, /* page has been recolored */
+
+ PG_MOD = 0x01, /* software modified bit */
+ PG_REF = 0x02, /* software referenced bit */
+};
+
+struct Page
+{
+ Lock;
+ ulong pa; /* Physical address in memory */
+ ulong va; /* Virtual address for user */
+ ulong daddr; /* Disc address on swap */
+ ulong gen; /* Generation counter for swap */
+ ushort ref; /* Reference count */
+ char modref; /* Simulated modify/reference bits */
+ char color; /* Cache coloring */
+ char cachectl[MAXMACH]; /* Cache flushing control for putmmu */
+ Image *image; /* Associated text or swap image */
+ Page *next; /* Lru free list */
+ Page *prev;
+ Page *hash; /* Image hash chains */
+};
+
+struct Swapalloc
+{
+ Lock; /* Free map lock */
+ int free; /* currently free swap pages */
+ uchar* swmap; /* Base of swap map in memory */
+ uchar* alloc; /* Round robin allocator */
+ uchar* last; /* Speed swap allocation */
+ uchar* top; /* Top of swap map */
+ Rendez r; /* Pager kproc idle sleep */
+ ulong highwater; /* Pager start threshold */
+ ulong headroom; /* Space pager frees under highwater */
+}swapalloc;
+
+struct Image
+{
+ Ref;
+ Chan *c; /* channel to text file */
+ Qid qid; /* Qid for page cache coherence */
+ Qid mqid;
+ Chan *mchan;
+ ushort type; /* Device type of owning channel */
+ Segment *s; /* TEXT segment for image if running */
+ Image *hash; /* Qid hash chains */
+ Image *next; /* Free list */
+ int notext; /* no file associated */
+};
+
+struct Pte
+{
+ Page *pages[PTEPERTAB]; /* Page map for this chunk of pte */
+ Page **first; /* First used entry */
+ Page **last; /* Last used entry */
+};
+
+/* Segment types */
+enum
+{
+ SG_TYPE = 07, /* Mask type of segment */
+ SG_TEXT = 00,
+ SG_DATA = 01,
+ SG_BSS = 02,
+ SG_STACK = 03,
+ SG_SHARED = 04,
+ SG_PHYSICAL = 05,
+
+ SG_RONLY = 0040, /* Segment is read only */
+ SG_CEXEC = 0100, /* Detach at exec */
+};
+
+#define PG_ONSWAP 1
+#define onswap(s) (((ulong)s)&PG_ONSWAP)
+#define pagedout(s) (((ulong)s)==0 || onswap(s))
+#define swapaddr(s) (((ulong)s)&~PG_ONSWAP)
+
+#define SEGMAXSIZE (SEGMAPSIZE*PTEMAPMEM)
+
+struct Physseg
+{
+ ulong attr; /* Segment attributes */
+ char *name; /* Attach name */
+ ulong pa; /* Physical address */
+ ulong size; /* Maximum segment size in pages */
+ Page *(*pgalloc)(Segment*, ulong); /* Allocation if we need it */
+ void (*pgfree)(Page*);
+};
+
+struct Sema
+{
+ Rendez;
+ long *addr;
+ int waiting;
+ Sema *next;
+ Sema *prev;
+};
+
+struct Segment
+{
+ Ref;
+ QLock lk;
+ ushort steal; /* Page stealer lock */
+ ushort type; /* segment type */
+ ulong base; /* virtual base */
+ ulong top; /* virtual top */
+ ulong size; /* size in pages */
+ ulong fstart; /* start address in file for demand load */
+ ulong flen; /* length of segment in file */
+ int flushme; /* maintain icache for this segment */
+ Image *image; /* text in file attached to this segment */
+ Physseg *pseg;
+ ulong* profile; /* Tick profile area */
+ Pte **map;
+ int mapsize;
+ Pte *ssegmap[SSEGMAPSIZE];
+ Lock semalock;
+ Sema sema;
+ ulong mark; /* portcountrefs */
+};
+
+enum
+{
+ RENDLOG = 5,
+ RENDHASH = 1<<RENDLOG, /* Hash to lookup rendezvous tags */
+ MNTLOG = 5,
+ MNTHASH = 1<<MNTLOG, /* Hash to walk mount table */
+ NFD = 100, /* per process file descriptors */
+ PGHLOG = 9,
+ PGHSIZE = 1<<PGHLOG, /* Page hash for image lookup */
+};
+#define REND(p,s) ((p)->rendhash[(s)&((1<<RENDLOG)-1)])
+#define MOUNTH(p,qid) ((p)->mnthash[(qid).path&((1<<MNTLOG)-1)])
+
+struct Pgrp
+{
+ Ref; /* also used as a lock when mounting */
+ int noattach;
+ ulong pgrpid;
+ QLock debug; /* single access via devproc.c */
+ RWlock ns; /* Namespace n read/one write lock */
+ Mhead *mnthash[MNTHASH];
+};
+
+struct Rgrp
+{
+ Ref; /* the Ref's lock is also the Rgrp's lock */
+ Proc *rendhash[RENDHASH]; /* Rendezvous tag hash */
+};
+
+struct Egrp
+{
+ Ref;
+ RWlock;
+ Evalue **ent;
+ int nent;
+ int ment;
+ ulong path; /* qid.path of next Evalue to be allocated */
+ ulong vers; /* of Egrp */
+};
+
+struct Evalue
+{
+ char *name;
+ char *value;
+ int len;
+ Evalue *link;
+ Qid qid;
+};
+
+struct Fgrp
+{
+ Ref;
+ Chan **fd;
+ int nfd; /* number allocated */
+ int maxfd; /* highest fd in use */
+ int exceed; /* debugging */
+};
+
+enum
+{
+ DELTAFD = 20 /* incremental increase in Fgrp.fd's */
+};
+
+struct Pallocmem
+{
+ ulong base;
+ ulong npage;
+};
+
+struct Palloc
+{
+ Lock;
+ Pallocmem mem[4];
+ Page *head; /* most recently used */
+ Page *tail; /* least recently used */
+ ulong freecount; /* how many pages on free list now */
+ Page *pages; /* array of all pages */
+ ulong user; /* how many user pages */
+ Page *hash[PGHSIZE];
+ Lock hashlock;
+ Rendez r; /* Sleep for free mem */
+ QLock pwait; /* Queue of procs waiting for memory */
+};
+
+struct Waitq
+{
+ Waitmsg w;
+ Waitq *next;
+};
+
+/*
+ * fasttick timer interrupts
+ */
+enum {
+ /* Mode */
+ Trelative, /* timer programmed in ns from now */
+ Tperiodic, /* periodic timer, period in ns */
+};
+
+struct Timer
+{
+ /* Public interface */
+ int tmode; /* See above */
+ vlong tns; /* meaning defined by mode */
+ void (*tf)(Ureg*, Timer*);
+ void *ta;
+ /* Internal */
+ Lock;
+ Timers *tt; /* Timers queue this timer runs on */
+ Tval tticks; /* tns converted to ticks */
+ Tval twhen; /* ns represented in fastticks */
+ Timer *tnext;
+};
+
+enum
+{
+ RFNAMEG = (1<<0),
+ RFENVG = (1<<1),
+ RFFDG = (1<<2),
+ RFNOTEG = (1<<3),
+ RFPROC = (1<<4),
+ RFMEM = (1<<5),
+ RFNOWAIT = (1<<6),
+ RFCNAMEG = (1<<10),
+ RFCENVG = (1<<11),
+ RFCFDG = (1<<12),
+ RFREND = (1<<13),
+ RFNOMNT = (1<<14),
+};
+
+/*
+ * process memory segments - NSEG always last !
+ */
+enum
+{
+ SSEG, TSEG, DSEG, BSEG, ESEG, LSEG, SEG1, SEG2, SEG3, SEG4, NSEG
+};
+
+enum
+{
+ Dead = 0, /* Process states */
+ Moribund,
+ Ready,
+ Scheding,
+ Running,
+ Queueing,
+ QueueingR,
+ QueueingW,
+ Wakeme,
+ Broken,
+ Stopped,
+ Rendezvous,
+ Waitrelease,
+
+ Proc_stopme = 1, /* devproc requests */
+ Proc_exitme,
+ Proc_traceme,
+ Proc_exitbig,
+ Proc_tracesyscall,
+
+ TUser = 0, /* Proc.time */
+ TSys,
+ TReal,
+ TCUser,
+ TCSys,
+ TCReal,
+
+ NERR = 64,
+ NNOTE = 5,
+
+ Npriq = 20, /* number of scheduler priority levels */
+ Nrq = Npriq+2, /* number of priority levels including real time */
+ PriRelease = Npriq, /* released edf processes */
+ PriEdf = Npriq+1, /* active edf processes */
+ PriNormal = 10, /* base priority for normal processes */
+ PriExtra = Npriq-1, /* edf processes at high best-effort pri */
+ PriKproc = 13, /* base priority for kernel processes */
+ PriRoot = 13, /* base priority for root processes */
+};
+
+struct Schedq
+{
+ Lock;
+ Proc* head;
+ Proc* tail;
+ int n;
+};
+
+struct Proc
+{
+ Label sched; /* known to l.s */
+ char *kstack; /* known to l.s */
+ Mach *mach; /* machine running this proc */
+ char *text;
+ char *user;
+ char *args;
+ int nargs; /* number of bytes of args */
+ Proc *rnext; /* next process in run queue */
+ Proc *qnext; /* next process on queue for a QLock */
+ QLock *qlock; /* addr of qlock being queued for DEBUG */
+ int state;
+ char *psstate; /* What /proc/#/status reports */
+ Segment *seg[NSEG];
+ QLock seglock; /* locked whenever seg[] changes */
+ ulong pid;
+ ulong noteid; /* Equivalent of note group */
+ Proc *pidhash; /* next proc in pid hash */
+
+ Lock exl; /* Lock count and waitq */
+ Waitq *waitq; /* Exited processes wait children */
+ int nchild; /* Number of living children */
+ int nwait; /* Number of uncollected wait records */
+ QLock qwaitr;
+ Rendez waitr; /* Place to hang out in wait */
+ Proc *parent;
+
+ Pgrp *pgrp; /* Process group for namespace */
+ Egrp *egrp; /* Environment group */
+ Fgrp *fgrp; /* File descriptor group */
+ Rgrp *rgrp; /* Rendez group */
+
+ Fgrp *closingfgrp; /* used during teardown */
+
+ ulong parentpid;
+ ulong time[6]; /* User, Sys, Real; child U, S, R */
+
+ uvlong kentry; /* Kernel entry time stamp (for profiling) */
+ /*
+ * pcycles: cycles spent in this process (updated on procsave/restore)
+ * when this is the current proc and we're in the kernel
+ * (procrestores outnumber procsaves by one)
+ * the number of cycles spent in the proc is pcycles + cycles()
+ * when this is not the current process or we're in user mode
+ * (procrestores and procsaves balance), it is pcycles.
+ */
+ vlong pcycles;
+
+ int insyscall;
+ int fpstate;
+
+ QLock debug; /* to access debugging elements of User */
+ Proc *pdbg; /* the debugging process */
+ ulong procmode; /* proc device default file mode */
+ ulong privatemem; /* proc does not let anyone read mem */
+ int hang; /* hang at next exec for debug */
+ int procctl; /* Control for /proc debugging */
+ ulong pc; /* DEBUG only */
+
+ Lock rlock; /* sync sleep/wakeup with postnote */
+ Rendez *r; /* rendezvous point slept on */
+ Rendez sleep; /* place for syssleep/debug */
+ int notepending; /* note issued but not acted on */
+ int kp; /* true if a kernel process */
+ Proc *palarm; /* Next alarm time */
+ ulong alarm; /* Time of call */
+ int newtlb; /* Pager has changed my pte's, I must flush */
+ int noswap; /* process is not swappable */
+
+ uintptr rendtag; /* Tag for rendezvous */
+ uintptr rendval; /* Value for rendezvous */
+ Proc *rendhash; /* Hash list for tag values */
+
+ Timer; /* For tsleep and real-time */
+ Rendez *trend;
+ int (*tfn)(void*);
+ void (*kpfun)(void*);
+ void *kparg;
+
+ FPsave fpsave; /* address of this is known by db */
+ int scallnr; /* sys call number - known by db */
+ Sargs s; /* address of this is known by db */
+ int nerrlab;
+ Label errlab[NERR];
+ char *syserrstr; /* last error from a system call, errbuf0 or 1 */
+ char *errstr; /* reason we're unwinding the error stack, errbuf1 or 0 */
+ char errbuf0[ERRMAX];
+ char errbuf1[ERRMAX];
+ char genbuf[128]; /* buffer used e.g. for last name element from namec */
+ Chan *slash;
+ Chan *dot;
+
+ Note note[NNOTE];
+ short nnote;
+ short notified; /* sysnoted is due */
+ Note lastnote;
+ int (*notify)(void*, char*);
+
+ Lock *lockwait;
+ Lock *lastlock; /* debugging */
+ Lock *lastilock; /* debugging */
+
+ Mach *wired;
+ Mach *mp; /* machine this process last ran on */
+ Ref nlocks; /* number of locks held by proc */
+ ulong delaysched;
+ ulong priority; /* priority level */
+ ulong basepri; /* base priority level */
+ uchar fixedpri; /* priority level deson't change */
+ ulong cpu; /* cpu average */
+ ulong lastupdate;
+ uchar yield; /* non-zero if the process just did a sleep(0) */
+ ulong readytime; /* time process came ready */
+ ulong movetime; /* last time process switched processors */
+ int preempted; /* true if this process hasn't finished the interrupt
+ * that last preempted it
+ */
+ Edf *edf; /* if non-null, real-time proc, edf contains scheduling params */
+ int trace; /* process being traced? */
+
+ ulong qpc; /* pc calling last blocking qlock */
+
+ int setargs;
+
+ void *ureg; /* User registers for notes */
+ void *dbgreg; /* User registers for devproc */
+ Notsave;
+
+ /*
+ * machine specific MMU
+ */
+ PMMU;
+ char *syscalltrace; /* syscall trace */
+};
+
+enum
+{
+ PRINTSIZE = 256,
+ MAXCRYPT = 127,
+ NUMSIZE = 12, /* size of formatted number */
+ MB = (1024*1024),
+ /* READSTR was 1000, which is way too small for usb's ctl file */
+ READSTR = 4000, /* temporary buffer size for device reads */
+};
+
+extern Conf conf;
+extern char* conffile;
+extern int cpuserver;
+extern Dev* devtab[];
+extern char* eve;
+extern char hostdomain[];
+extern uchar initcode[];
+extern int kbdbuttons;
+extern Queue* kbdq;
+extern Queue* kprintoq;
+extern Ref noteidalloc;
+extern int nsyscall;
+extern Palloc palloc;
+extern Queue* serialoq;
+extern char* statename[];
+extern Image swapimage;
+extern char* sysname;
+extern uint qiomaxatomic;
+extern char* sysctab[];
+
+enum
+{
+ LRESPROF = 3,
+};
+
+/*
+ * action log
+ */
+struct Log {
+ Lock;
+ int opens;
+ char* buf;
+ char *end;
+ char *rptr;
+ int len;
+ int nlog;
+ int minread;
+
+ int logmask; /* mask of things to debug */
+
+ QLock readq;
+ Rendez readr;
+};
+
+struct Logflag {
+ char* name;
+ int mask;
+};
+
+enum
+{
+ NCMDFIELD = 128
+};
+
+struct Cmdbuf
+{
+ char *buf;
+ char **f;
+ int nf;
+};
+
+struct Cmdtab
+{
+ int index; /* used by client to switch on result */
+ char *cmd; /* command name */
+ int narg; /* expected #args; 0 ==> variadic */
+};
+
+/*
+ * routines to access UART hardware
+ */
+struct PhysUart
+{
+ char* name;
+ Uart* (*pnp)(void);
+ void (*enable)(Uart*, int);
+ void (*disable)(Uart*);
+ void (*kick)(Uart*);
+ void (*dobreak)(Uart*, int);
+ int (*baud)(Uart*, int);
+ int (*bits)(Uart*, int);
+ int (*stop)(Uart*, int);
+ int (*parity)(Uart*, int);
+ void (*modemctl)(Uart*, int);
+ void (*rts)(Uart*, int);
+ void (*dtr)(Uart*, int);
+ long (*status)(Uart*, void*, long, long);
+ void (*fifo)(Uart*, int);
+ void (*power)(Uart*, int);
+ int (*getc)(Uart*); /* polling versions, for iprint, rdb */
+ void (*putc)(Uart*, int);
+};
+
+enum {
+ Stagesize= 2048
+};
+
+/*
+ * software UART
+ */
+struct Uart
+{
+ void* regs; /* hardware stuff */
+ void* saveregs; /* place to put registers on power down */
+ char* name; /* internal name */
+ ulong freq; /* clock frequency */
+ int bits; /* bits per character */
+ int stop; /* stop bits */
+ int parity; /* even, odd or no parity */
+ int baud; /* baud rate */
+ PhysUart*phys;
+ int console; /* used as a serial console */
+ int special; /* internal kernel device */
+ Uart* next; /* list of allocated uarts */
+
+ QLock;
+ int type; /* ?? */
+ int dev;
+ int opens;
+
+ int enabled;
+ Uart *elist; /* next enabled interface */
+
+ int perr; /* parity errors */
+ int ferr; /* framing errors */
+ int oerr; /* rcvr overruns */
+ int berr; /* no input buffers */
+ int serr; /* input queue overflow */
+
+ /* buffers */
+ int (*putc)(Queue*, int);
+ Queue *iq;
+ Queue *oq;
+
+ Lock rlock;
+ uchar istage[Stagesize];
+ uchar *iw;
+ uchar *ir;
+ uchar *ie;
+
+ Lock tlock; /* transmit */
+ uchar ostage[Stagesize];
+ uchar *op;
+ uchar *oe;
+ int drain;
+
+ int modem; /* hardware flow control on */
+ int xonoff; /* software flow control on */
+ int blocked;
+ int cts, dsr, dcd; /* keep track of modem status */
+ int ctsbackoff;
+ int hup_dsr, hup_dcd; /* send hangup upstream? */
+ int dohup;
+
+ Rendez r;
+};
+
+extern Uart* consuart;
+
+/*
+ * performance timers, all units in perfticks
+ */
+struct Perf
+{
+ ulong intrts; /* time of last interrupt */
+ ulong inintr; /* time since last clock tick in interrupt handlers */
+ ulong avg_inintr; /* avg time per clock tick in interrupt handlers */
+ ulong inidle; /* time since last clock tick in idle loop */
+ ulong avg_inidle; /* avg time per clock tick in idle loop */
+ ulong last; /* value of perfticks() at last clock tick */
+ ulong period; /* perfticks() per clock tick */
+};
+
+struct Watchdog
+{
+ void (*enable)(void); /* watchdog enable */
+ void (*disable)(void); /* watchdog disable */
+ void (*restart)(void); /* watchdog restart */
+ void (*stat)(char*, char*); /* watchdog statistics */
+};
+
+
+/* queue state bits, Qmsg, Qcoalesce, and Qkick can be set in qopen */
+enum
+{
+ /* Queue.state */
+ Qstarve = (1<<0), /* consumer starved */
+ Qmsg = (1<<1), /* message stream */
+ Qclosed = (1<<2), /* queue has been closed/hungup */
+ Qflow = (1<<3), /* producer flow controlled */
+ Qcoalesce = (1<<4), /* coallesce packets on read */
+ Qkick = (1<<5), /* always call the kick routine after qwrite */
+};
+
+#define DEVDOTDOT -1
+
+#pragma varargck type "I" uchar*
+#pragma varargck type "V" uchar*
+#pragma varargck type "E" uchar*
+#pragma varargck type "M" uchar*
diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h
new file mode 100755
index 000000000..14c3506e5
--- /dev/null
+++ b/sys/src/9/port/portfns.h
@@ -0,0 +1,395 @@
+void _assert(char*);
+void accounttime(void);
+Timer* addclock0link(void (*)(void), int);
+int addphysseg(Physseg*);
+void addbootfile(char*, uchar*, ulong);
+void addwatchdog(Watchdog*);
+Block* adjustblock(Block*, int);
+void alarmkproc(void*);
+Block* allocb(int);
+int anyhigher(void);
+int anyready(void);
+Image* attachimage(int, Chan*, ulong, ulong);
+Page* auxpage(void);
+Block* bl2mem(uchar*, Block*, int);
+int blocklen(Block*);
+void bootlinks(void);
+void cachedel(Image*, ulong);
+void cachepage(Page*, Image*);
+void callwithureg(void(*)(Ureg*));
+char* chanpath(Chan*);
+int canlock(Lock*);
+int canpage(Proc*);
+int canqlock(QLock*);
+int canrlock(RWlock*);
+void chandevinit(void);
+void chandevreset(void);
+void chandevshutdown(void);
+void chanfree(Chan*);
+void checkalarms(void);
+void checkb(Block*, char*);
+void cinit(void);
+Chan* cclone(Chan*);
+void cclose(Chan*);
+void ccloseq(Chan*);
+void closeegrp(Egrp*);
+void closefgrp(Fgrp*);
+void closepgrp(Pgrp*);
+void closergrp(Rgrp*);
+long clrfpintr(void);
+void cmderror(Cmdbuf*, char*);
+int cmount(Chan**, Chan*, int, char*);
+void confinit(void);
+int consactive(void);
+void (*consdebug)(void);
+void copen(Chan*);
+Block* concatblock(Block*);
+Block* copyblock(Block*, int);
+void copypage(Page*, Page*);
+void countpagerefs(ulong*, int);
+int cread(Chan*, uchar*, int, vlong);
+void cunmount(Chan*, Chan*);
+void cupdate(Chan*, uchar*, int, vlong);
+void cwrite(Chan*, uchar*, int, vlong);
+ulong dbgpc(Proc*);
+long decref(Ref*);
+int decrypt(void*, void*, int);
+void delay(int);
+Proc* dequeueproc(Schedq*, Proc*);
+Chan* devattach(int, char*);
+Block* devbread(Chan*, long, ulong);
+long devbwrite(Chan*, Block*, ulong);
+Chan* devclone(Chan*);
+int devconfig(int, char *, DevConf *);
+void devcreate(Chan*, char*, int, ulong);
+void devdir(Chan*, Qid, char*, vlong, char*, long, Dir*);
+long devdirread(Chan*, char*, long, Dirtab*, int, Devgen*);
+Devgen devgen;
+void devinit(void);
+int devno(int, int);
+Chan* devopen(Chan*, int, Dirtab*, int, Devgen*);
+void devpermcheck(char*, ulong, int);
+void devpower(int);
+void devremove(Chan*);
+void devreset(void);
+void devshutdown(void);
+int devstat(Chan*, uchar*, int, Dirtab*, int, Devgen*);
+Walkqid* devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*);
+int devwstat(Chan*, uchar*, int);
+void drawactive(int);
+void drawcmap(void);
+void dumpaproc(Proc*);
+void dumpregs(Ureg*);
+void dumpstack(void);
+Fgrp* dupfgrp(Fgrp*);
+int duppage(Page*);
+void dupswap(Page*);
+void edfinit(Proc*);
+char* edfadmit(Proc*);
+int edfready(Proc*);
+void edfrecord(Proc*);
+void edfrun(Proc*, int);
+void edfstop(Proc*);
+void edfyield(void);
+int emptystr(char*);
+int encrypt(void*, void*, int);
+void envcpy(Egrp*, Egrp*);
+int eqchan(Chan*, Chan*, int);
+int eqchantdqid(Chan*, int, int, Qid, int);
+int eqqid(Qid, Qid);
+void error(char*);
+long execregs(ulong, ulong, ulong);
+void exhausted(char*);
+void exit(int);
+uvlong fastticks(uvlong*);
+uvlong fastticks2ns(uvlong);
+uvlong fastticks2us(uvlong);
+int fault(ulong, int);
+void fdclose(int, int);
+Chan* fdtochan(int, int, int, int);
+int findmount(Chan**, Mhead**, int, int, Qid);
+int fixfault(Segment*, ulong, int, int);
+void flushmmu(void);
+void forceclosefgrp(void);
+void forkchild(Proc*, Ureg*);
+void forkret(void);
+void free(void*);
+void freeb(Block*);
+void freeblist(Block*);
+int freebroken(void);
+void freepte(Segment*, Pte*);
+void getcolor(ulong, ulong*, ulong*, ulong*);
+ulong getmalloctag(void*);
+ulong getrealloctag(void*);
+void gotolabel(Label*);
+char* getconfenv(void);
+int haswaitq(void*);
+long hostdomainwrite(char*, int);
+long hostownerwrite(char*, int);
+void hzsched(void);
+Block* iallocb(int);
+void iallocsummary(void);
+long ibrk(ulong, int);
+void ilock(Lock*);
+void iunlock(Lock*);
+long incref(Ref*);
+void initseg(void);
+int iprint(char*, ...);
+void isdir(Chan*);
+int iseve(void);
+int islo(void);
+Segment* isoverlap(Proc*, ulong, int);
+int ispages(void*);
+int isphysseg(char*);
+void ixsummary(void);
+int kbdcr2nl(Queue*, int);
+int kbdgetmap(uint, int*, int*, Rune*);
+int kbdputc(Queue*, int);
+void kbdputmap(ushort, ushort, Rune);
+void kickpager(void);
+void killbig(char*);
+void kproc(char*, void(*)(void*), void*);
+void kprocchild(Proc*, void (*)(void*), void*);
+void (*kproftimer)(ulong);
+void ksetenv(char*, char*, int);
+void kstrcpy(char*, char*, int);
+void kstrdup(char**, char*);
+long latin1(Rune*, int);
+int lock(Lock*);
+void logopen(Log*);
+void logclose(Log*);
+char* logctl(Log*, int, char**, Logflag*);
+void logn(Log*, int, void*, int);
+long logread(Log*, void*, ulong, long);
+void log(Log*, int, char*, ...);
+Cmdtab* lookupcmd(Cmdbuf*, Cmdtab*, int);
+Page* lookpage(Image*, ulong);
+#define MS2NS(n) (((vlong)(n))*1000000LL)
+void machinit(void);
+void* mallocz(ulong, int);
+void* malloc(ulong);
+void* mallocalign(ulong, ulong, long, ulong);
+void mallocsummary(void);
+Block* mem2bl(uchar*, int);
+void mfreeseg(Segment*, ulong, int);
+void microdelay(int);
+uvlong mk64fract(uvlong, uvlong);
+void mkqid(Qid*, vlong, ulong, int);
+void mmurelease(Proc*);
+void mmuswitch(Proc*);
+Chan* mntauth(Chan*, char*);
+long mntversion(Chan*, char*, int, int);
+void mouseresize(void);
+void mountfree(Mount*);
+ulong ms2tk(ulong);
+ulong msize(void*);
+ulong ms2tk(ulong);
+uvlong ms2fastticks(ulong);
+void mul64fract(uvlong*, uvlong, uvlong);
+void muxclose(Mnt*);
+Chan* namec(char*, int, int, ulong);
+void nameerror(char*, char*);
+Chan* newchan(void);
+int newfd(Chan*);
+Mhead* newmhead(Chan*);
+Mount* newmount(Mhead*, Chan*, int, char*);
+Page* newpage(int, Segment **, ulong);
+Path* newpath(char*);
+Pgrp* newpgrp(void);
+Rgrp* newrgrp(void);
+Proc* newproc(void);
+void nexterror(void);
+int notify(Ureg*);
+int nrand(int);
+uvlong ns2fastticks(uvlong);
+int okaddr(ulong, ulong, int);
+int openmode(ulong);
+Block* packblock(Block*);
+Block* padblock(Block*, int);
+void pagechainhead(Page*);
+void pageinit(void);
+ulong pagenumber(Page*);
+void pagersummary(void);
+void panic(char*, ...);
+Cmdbuf* parsecmd(char *a, int n);
+void pathclose(Path*);
+ulong perfticks(void);
+void pexit(char*, int);
+void pgrpcpy(Pgrp*, Pgrp*);
+void pgrpnote(ulong, char*, long, int);
+void pio(Segment *, ulong, ulong, Page **);
+#define poperror() up->nerrlab--
+void portcountpagerefs(ulong*, int);
+int postnote(Proc*, int, char*, int);
+int pprint(char*, ...);
+int preempted(void);
+void prflush(void);
+void printinit(void);
+ulong procalarm(ulong);
+void procctl(Proc*);
+void procdump(void);
+int procfdprint(Chan*, int, int, char*, int);
+int procindex(ulong);
+void procinit0(void);
+void procflushseg(Segment*);
+void procpriority(Proc*, int, int);
+Proc* proctab(int);
+extern void (*proctrace)(Proc*, int, vlong);
+void procwired(Proc*, int);
+Pte* ptealloc(void);
+Pte* ptecpy(Pte*);
+int pullblock(Block**, int);
+Block* pullupblock(Block*, int);
+Block* pullupqueue(Queue*, int);
+void putimage(Image*);
+void putmhead(Mhead*);
+void putmmu(ulong, ulong, Page*);
+void putpage(Page*);
+void putseg(Segment*);
+void putstrn(char*, int);
+void putswap(Page*);
+ulong pwait(Waitmsg*);
+void qaddlist(Queue*, Block*);
+Block* qbread(Queue*, int);
+long qbwrite(Queue*, Block*);
+Queue* qbypass(void (*)(void*, Block*), void*);
+int qcanread(Queue*);
+void qclose(Queue*);
+int qconsume(Queue*, void*, int);
+Block* qcopy(Queue*, int, ulong);
+int qdiscard(Queue*, int);
+void qflush(Queue*);
+void qfree(Queue*);
+int qfull(Queue*);
+Block* qget(Queue*);
+void qhangup(Queue*, char*);
+int qisclosed(Queue*);
+int qiwrite(Queue*, void*, int);
+int qlen(Queue*);
+void qlock(QLock*);
+Queue* qopen(int, int, void (*)(void*), void*);
+int qpass(Queue*, Block*);
+int qpassnolim(Queue*, Block*);
+int qproduce(Queue*, void*, int);
+void qputback(Queue*, Block*);
+long qread(Queue*, void*, int);
+Block* qremove(Queue*);
+void qreopen(Queue*);
+void qsetlimit(Queue*, int);
+void qunlock(QLock*);
+int qwindow(Queue*);
+int qwrite(Queue*, void*, int);
+void qnoblock(Queue*, int);
+int rand(void);
+void randominit(void);
+ulong randomread(void*, ulong);
+void rdb(void);
+int readnum(ulong, char*, ulong, ulong, int);
+int readstr(ulong, char*, ulong, char*);
+void ready(Proc*);
+void* realloc(void *v, ulong size);
+void rebootcmd(int, char**);
+void reboot(void*, void*, ulong);
+void relocateseg(Segment*, ulong);
+void renameuser(char*, char*);
+void resched(char*);
+void resrcwait(char*);
+int return0(void*);
+void rlock(RWlock*);
+long rtctime(void);
+void runlock(RWlock*);
+Proc* runproc(void);
+void savefpregs(FPsave*);
+void sched(void);
+void scheddump(void);
+void schedinit(void);
+void (*screenputs)(char*, int);
+long seconds(void);
+ulong segattach(Proc*, ulong, char *, ulong, ulong);
+void segclock(ulong);
+void segpage(Segment*, Page*);
+int setcolor(ulong, ulong, ulong, ulong);
+void setkernur(Ureg*, Proc*);
+int setlabel(Label*);
+void setmalloctag(void*, ulong);
+void setrealloctag(void*, ulong);
+void setregisters(Ureg*, char*, char*, int);
+void setswapchan(Chan*);
+char* skipslash(char*);
+void sleep(Rendez*, int(*)(void*), void*);
+void* smalloc(ulong);
+int splhi(void);
+int spllo(void);
+void splx(int);
+void splxpc(int);
+char* srvname(Chan*);
+int swapcount(ulong);
+int swapfull(void);
+void swapinit(void);
+void timeradd(Timer*);
+void timerdel(Timer*);
+void timersinit(void);
+void timerintr(Ureg*, Tval);
+void timerset(Tval);
+ulong tk2ms(ulong);
+#define TK2MS(x) ((x)*(1000/HZ))
+uvlong tod2fastticks(vlong);
+vlong todget(vlong*);
+void todsetfreq(vlong);
+void todinit(void);
+void todset(vlong, vlong, int);
+Block* trimblock(Block*, int, int);
+void tsleep(Rendez*, int (*)(void*), void*, ulong);
+int uartctl(Uart*, char*);
+int uartgetc(void);
+void uartkick(void*);
+void uartmouse(Uart*, int (*)(Queue*, int), int);
+void uartsetmouseputc(Uart*, int (*)(Queue*, int));
+void uartputc(int);
+void uartputs(char*, int);
+void uartrecv(Uart*, char);
+int uartstageoutput(Uart*);
+void unbreak(Proc*);
+void uncachepage(Page*);
+long unionread(Chan*, void*, long);
+void unlock(Lock*);
+uvlong us2fastticks(uvlong);
+void userinit(void);
+ulong userpc(void);
+long userwrite(char*, int);
+void validaddr(ulong, ulong, int);
+void validname(char*, int);
+char* validnamedup(char*, int);
+void validstat(uchar*, int);
+void* vmemchr(void*, int, int);
+Proc* wakeup(Rendez*);
+int walk(Chan**, char**, int, int, int*);
+void wlock(RWlock*);
+void wunlock(RWlock*);
+void* xalloc(ulong);
+void* xallocz(ulong, int);
+void xfree(void*);
+void xhole(ulong, ulong);
+void xinit(void);
+int xmerge(void*, void*);
+void* xspanalloc(ulong, int, ulong);
+void xsummary(void);
+void yield(void);
+Segment* data2txt(Segment*);
+Segment* dupseg(Segment**, int, int);
+Segment* newseg(int, ulong, ulong);
+Segment* seg(Proc*, ulong, int);
+void hnputv(void*, uvlong);
+void hnputl(void*, uint);
+void hnputs(void*, ushort);
+uvlong nhgetv(void*);
+uint nhgetl(void*);
+ushort nhgets(void*);
+ulong µs(void);
+void _xinc(long*);
+long _xdec(long*);
+long lcycles(void);
+
+#pragma varargck argpos iprint 1
+#pragma varargck argpos panic 1
+#pragma varargck argpos pprint 1
diff --git a/sys/src/9/port/portmkfile b/sys/src/9/port/portmkfile
new file mode 100755
index 000000000..545376745
--- /dev/null
+++ b/sys/src/9/port/portmkfile
@@ -0,0 +1,97 @@
+PORTFILES=`{../port/mkfilelist ../port}
+^($PORTFILES)\.$O:R: '../port/\1.c'
+ $CC $CFLAGS -I. ../port/$stem1.c
+
+IPFILES=`{../port/mkfilelist ../ip}
+^($IPFILES)\.$O:R: '../ip/\1.c' ../ip/ip.h ../ip/ipv6.h
+ $CC $CFLAGS -I. ../ip/$stem1.c
+
+%.$O: %.s
+ $AS $AFLAGS $stem.s
+
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+
+%.acid: %.c
+ $CC $CFLAGS -a $stem.c >$stem.acid
+
+%.acid: ../ip/%.c
+ $CC $CFLAGS -a -I. ../ip/$stem.c >$stem.acid
+
+%.acid: ../port/%.c
+ $CC $CFLAGS -a -I. ../port/$stem.c >$stem.acid
+
+installall:V:
+ for(i in $CONFLIST)
+ mk 'CONF='$i install
+
+all:V:
+ for(i in $CONFLIST)
+ mk 'CONF='$i
+
+clean:V:
+ rm -f *.[$OS] *.root.s *.rootc.c cfs.h fs.h init.h conf.h *.out *.m errstr.h
+ for(i in $CONFLIST $CRAPLIST)
+ mk $i.clean
+
+%.clean:V:
+ rm -f $stem.c [9bz]$stem [9bz]$stem.gz s[9bz]$stem boot$stem.* *.acid
+
+nuke:V: clean
+ rm -f ../boot/libboot.a$O *.elf *.rr
+
+%.$O: /$objtype/include/u.h ../port/lib.h mem.h dat.h fns.h io.h ../port/error.h ../port/portdat.h ../port/portfns.h
+
+../port/systab.h: /sys/src/libc/9syscall/sys.h ../port/mksystab
+ rc ../port/mksystab > ../port/systab.h
+
+$CONF.$O: $CONF.c
+ $CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
+
+$CONF.c: ../port/mkdevc $CONF
+ rc ../port/mkdevc $CONF > $CONF.c
+ {echo 'uchar configfile[]={'
+ xd -1x $CONF |
+ sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+ echo 0,
+ echo '};'} >> $CONF.c
+
+errstr.h: ../port/mkerrstr ../port/error.h
+ rc ../port/mkerrstr > errstr.h
+
+../port/latin1.h: /lib/keyboard
+ aux/mklatinkbd /lib/keyboard > ../port/latin1.h
+
+%.db: main.$O
+ $CC -s$stem main.c | dbfmt > $stem.db
+
+alloc.$O: /sys/include/pool.h
+devmnt.$O: /sys/include/fcall.h
+proc.$O: errstr.h
+devroot.$O: errstr.h
+devaoe.$O: /$objtype/include/ureg.h
+devfs.$O: /$objtype/include/ureg.h
+devsd.$O: /$objtype/include/ureg.h
+sdscsi.$O: /$objtype/include/ureg.h
+trap.$O: /$objtype/include/ureg.h
+devproc.$O: /$objtype/include/ureg.h
+main.$O: init.h
+trap.$O: ../port/systab.h
+devpipe.$O: ../port/netif.h
+netif.$O: ../port/netif.h
+devuart.$O: ../port/netif.h
+devmouse.$O: screen.h /sys/include/memdraw.h
+devdraw.$O: screen.h /sys/include/memdraw.h
+screen.$O: screen.h /sys/include/memdraw.h
+latin1.$O: ../port/latin1.h
+thwack.$O: ../port/thwack.h
+unthwack.$O: ../port/thwack.h
+devsdp.$O: ../port/thwack.h
+devproc.$O sysproc.$O: /sys/include/tos.h
+devproc.$O edf.$O proc.$O: /sys/include/trace.h
+
+boot$CONF.out: $CONF print.$O $BOOTDIR/boot.c $BOOTLIB
+ $BOOTDIR/mkboot $CONF > boot$CONF.c
+ $CC $CFLAGS boot$CONF.c
+ $CC $CFLAGS ../boot/printstub.c
+ $LD -o boot$CONF.out boot$CONF.$O $BOOTLIB printstub.$O
diff --git a/sys/src/9/port/print.c b/sys/src/9/port/print.c
new file mode 100755
index 000000000..9fe1091e8
--- /dev/null
+++ b/sys/src/9/port/print.c
@@ -0,0 +1,25 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+static Lock fmtl;
+
+void
+_fmtlock(void)
+{
+ lock(&fmtl);
+}
+
+void
+_fmtunlock(void)
+{
+ unlock(&fmtl);
+}
+
+int
+_efgfmt(Fmt*)
+{
+ return -1;
+}
diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c
new file mode 100755
index 000000000..dc15b47b0
--- /dev/null
+++ b/sys/src/9/port/proc.c
@@ -0,0 +1,1616 @@
+#include <u.h>
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "edf.h"
+#include <trace.h>
+
+int schedgain = 30; /* units in seconds */
+int nrdy;
+Ref noteidalloc;
+
+void updatecpu(Proc*);
+int reprioritize(Proc*);
+
+ulong delayedscheds; /* statistics */
+long skipscheds;
+long preempts;
+ulong load;
+
+static Ref pidalloc;
+
+static struct Procalloc
+{
+ Lock;
+ Proc* ht[128];
+ Proc* arena;
+ Proc* free;
+} procalloc;
+
+enum
+{
+ Q=10,
+ DQ=4,
+ Scaling=2,
+};
+
+Schedq runq[Nrq];
+ulong runvec;
+
+char *statename[] =
+{ /* BUG: generate automatically */
+ "Dead",
+ "Moribund",
+ "Ready",
+ "Scheding",
+ "Running",
+ "Queueing",
+ "QueueingR",
+ "QueueingW",
+ "Wakeme",
+ "Broken",
+ "Stopped",
+ "Rendez",
+ "Waitrelease",
+};
+
+static void pidhash(Proc*);
+static void pidunhash(Proc*);
+static void rebalance(void);
+
+/*
+ * Always splhi()'ed.
+ */
+void
+schedinit(void) /* never returns */
+{
+ Edf *e;
+
+ setlabel(&m->sched);
+ if(up) {
+ if((e = up->edf) && (e->flags & Admitted))
+ edfrecord(up);
+ m->proc = 0;
+ switch(up->state) {
+ case Running:
+ ready(up);
+ break;
+ case Moribund:
+ up->state = Dead;
+ edfstop(up);
+ if (up->edf)
+ free(up->edf);
+ up->edf = nil;
+
+ /*
+ * Holding locks from pexit:
+ * procalloc
+ * palloc
+ */
+ mmurelease(up);
+
+ up->qnext = procalloc.free;
+ procalloc.free = up;
+
+ unlock(&palloc);
+ unlock(&procalloc);
+ break;
+ }
+ up->mach = nil;
+ updatecpu(up);
+ up = nil;
+ }
+ sched();
+}
+
+/*
+ * If changing this routine, look also at sleep(). It
+ * contains a copy of the guts of sched().
+ */
+void
+sched(void)
+{
+ Proc *p;
+
+ if(m->ilockdepth)
+ panic("cpu%d: ilockdepth %d, last lock %#p at %#p, sched called from %#p",
+ m->machno,
+ m->ilockdepth,
+ up? up->lastilock: nil,
+ (up && up->lastilock)? up->lastilock->pc: 0,
+ getcallerpc(&p+2));
+ if(up){
+ /*
+ * Delay the sched until the process gives up the locks
+ * it is holding. This avoids dumb lock loops.
+ * Don't delay if the process is Moribund.
+ * It called sched to die.
+ * But do sched eventually. This avoids a missing unlock
+ * from hanging the entire kernel.
+ * But don't reschedule procs holding palloc or procalloc.
+ * Those are far too important to be holding while asleep.
+ *
+ * This test is not exact. There can still be a few instructions
+ * in the middle of taslock when a process holds a lock
+ * but Lock.p has not yet been initialized.
+ */
+ if(up->nlocks.ref)
+ if(up->state != Moribund)
+ if(up->delaysched < 20
+ || palloc.Lock.p == up
+ || procalloc.Lock.p == up){
+ up->delaysched++;
+ delayedscheds++;
+ return;
+ }
+ up->delaysched = 0;
+
+ splhi();
+
+ /* statistics */
+ m->cs++;
+
+ procsave(up);
+ if(setlabel(&up->sched)){
+ procrestore(up);
+ spllo();
+ return;
+ }
+ gotolabel(&m->sched);
+ }
+ p = runproc();
+ if(!p->edf){
+ updatecpu(p);
+ p->priority = reprioritize(p);
+ }
+ if(p != m->readied)
+ m->schedticks = m->ticks + HZ/10;
+ m->readied = 0;
+ up = p;
+ up->state = Running;
+ up->mach = MACHP(m->machno);
+ m->proc = up;
+ mmuswitch(up);
+ gotolabel(&up->sched);
+}
+
+int
+anyready(void)
+{
+ return runvec;
+}
+
+int
+anyhigher(void)
+{
+ return runvec & ~((1<<(up->priority+1))-1);
+}
+
+/*
+ * here once per clock tick to see if we should resched
+ */
+void
+hzsched(void)
+{
+ /* once a second, rebalance will reprioritize ready procs */
+ if(m->machno == 0)
+ rebalance();
+
+ /* unless preempted, get to run for at least 100ms */
+ if(anyhigher()
+ || (!up->fixedpri && m->ticks > m->schedticks && anyready())){
+ m->readied = nil; /* avoid cooperative scheduling */
+ up->delaysched++;
+ }
+}
+
+/*
+ * here at the end of non-clock interrupts to see if we should preempt the
+ * current process. Returns 1 if preempted, 0 otherwise.
+ */
+int
+preempted(void)
+{
+ if(up && up->state == Running)
+ if(up->preempted == 0)
+ if(anyhigher())
+ if(!active.exiting){
+ m->readied = nil; /* avoid cooperative scheduling */
+ up->preempted = 1;
+ sched();
+ splhi();
+ up->preempted = 0;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Update the cpu time average for this particular process,
+ * which is about to change from up -> not up or vice versa.
+ * p->lastupdate is the last time an updatecpu happened.
+ *
+ * The cpu time average is a decaying average that lasts
+ * about D clock ticks. D is chosen to be approximately
+ * the cpu time of a cpu-intensive "quick job". A job has to run
+ * for approximately D clock ticks before we home in on its
+ * actual cpu usage. Thus if you manage to get in and get out
+ * quickly, you won't be penalized during your burst. Once you
+ * start using your share of the cpu for more than about D
+ * clock ticks though, your p->cpu hits 1000 (1.0) and you end up
+ * below all the other quick jobs. Interactive tasks, because
+ * they basically always use less than their fair share of cpu,
+ * will be rewarded.
+ *
+ * If the process has not been running, then we want to
+ * apply the filter
+ *
+ * cpu = cpu * (D-1)/D
+ *
+ * n times, yielding
+ *
+ * cpu = cpu * ((D-1)/D)^n
+ *
+ * but D is big enough that this is approximately
+ *
+ * cpu = cpu * (D-n)/D
+ *
+ * so we use that instead.
+ *
+ * If the process has been running, we apply the filter to
+ * 1 - cpu, yielding a similar equation. Note that cpu is
+ * stored in fixed point (* 1000).
+ *
+ * Updatecpu must be called before changing up, in order
+ * to maintain accurate cpu usage statistics. It can be called
+ * at any time to bring the stats for a given proc up-to-date.
+ */
+void
+updatecpu(Proc *p)
+{
+ int n, t, ocpu;
+ int D = schedgain*HZ*Scaling;
+
+ if(p->edf)
+ return;
+
+ t = MACHP(0)->ticks*Scaling + Scaling/2;
+ n = t - p->lastupdate;
+ p->lastupdate = t;
+
+ if(n == 0)
+ return;
+ if(n > D)
+ n = D;
+
+ ocpu = p->cpu;
+ if(p != up)
+ p->cpu = (ocpu*(D-n))/D;
+ else{
+ t = 1000 - ocpu;
+ t = (t*(D-n))/D;
+ p->cpu = 1000 - t;
+ }
+
+//iprint("pid %d %s for %d cpu %d -> %d\n", p->pid,p==up?"active":"inactive",n, ocpu,p->cpu);
+}
+
+/*
+ * On average, p has used p->cpu of a cpu recently.
+ * Its fair share is conf.nmach/m->load of a cpu. If it has been getting
+ * too much, penalize it. If it has been getting not enough, reward it.
+ * I don't think you can get much more than your fair share that
+ * often, so most of the queues are for using less. Having a priority
+ * of 3 means you're just right. Having a higher priority (up to p->basepri)
+ * means you're not using as much as you could.
+ */
+int
+reprioritize(Proc *p)
+{
+ int fairshare, n, load, ratio;
+
+ load = MACHP(0)->load;
+ if(load == 0)
+ return p->basepri;
+
+ /*
+ * fairshare = 1.000 * conf.nproc * 1.000/load,
+ * except the decimal point is moved three places
+ * on both load and fairshare.
+ */
+ fairshare = (conf.nmach*1000*1000)/load;
+ n = p->cpu;
+ if(n == 0)
+ n = 1;
+ ratio = (fairshare+n/2) / n;
+ if(ratio > p->basepri)
+ ratio = p->basepri;
+ if(ratio < 0)
+ panic("reprioritize");
+//iprint("pid %d cpu %d load %d fair %d pri %d\n", p->pid, p->cpu, load, fairshare, ratio);
+ return ratio;
+}
+
+/*
+ * add a process to a scheduling queue
+ */
+void
+queueproc(Schedq *rq, Proc *p)
+{
+ int pri;
+
+ pri = rq - runq;
+ lock(runq);
+ p->priority = pri;
+ p->rnext = 0;
+ if(rq->tail)
+ rq->tail->rnext = p;
+ else
+ rq->head = p;
+ rq->tail = p;
+ rq->n++;
+ nrdy++;
+ runvec |= 1<<pri;
+ unlock(runq);
+}
+
+/*
+ * try to remove a process from a scheduling queue (called splhi)
+ */
+Proc*
+dequeueproc(Schedq *rq, Proc *tp)
+{
+ Proc *l, *p;
+
+ if(!canlock(runq))
+ return nil;
+
+ /*
+ * the queue may have changed before we locked runq,
+ * refind the target process.
+ */
+ l = 0;
+ for(p = rq->head; p; p = p->rnext){
+ if(p == tp)
+ break;
+ l = p;
+ }
+
+ /*
+ * p->mach==0 only when process state is saved
+ */
+ if(p == 0 || p->mach){
+ unlock(runq);
+ return nil;
+ }
+ if(p->rnext == 0)
+ rq->tail = l;
+ if(l)
+ l->rnext = p->rnext;
+ else
+ rq->head = p->rnext;
+ if(rq->head == nil)
+ runvec &= ~(1<<(rq-runq));
+ rq->n--;
+ nrdy--;
+ if(p->state != Ready)
+ print("dequeueproc %s %lud %s\n", p->text, p->pid, statename[p->state]);
+
+ unlock(runq);
+ return p;
+}
+
+/*
+ * ready(p) picks a new priority for a process and sticks it in the
+ * runq for that priority.
+ */
+void
+ready(Proc *p)
+{
+ int s, pri;
+ Schedq *rq;
+ void (*pt)(Proc*, int, vlong);
+
+ s = splhi();
+ if(edfready(p)){
+ splx(s);
+ return;
+ }
+
+ if(up != p)
+ m->readied = p; /* group scheduling */
+
+ updatecpu(p);
+ pri = reprioritize(p);
+ p->priority = pri;
+ rq = &runq[pri];
+ p->state = Ready;
+ queueproc(rq, p);
+ pt = proctrace;
+ if(pt)
+ pt(p, SReady, 0);
+ splx(s);
+}
+
+/*
+ * yield the processor and drop our priority
+ */
+void
+yield(void)
+{
+ if(anyready()){
+ /* pretend we just used 1/2 tick */
+ up->lastupdate -= Scaling/2;
+ sched();
+ }
+}
+
+/*
+ * recalculate priorities once a second. We need to do this
+ * since priorities will otherwise only be recalculated when
+ * the running process blocks.
+ */
+ulong balancetime;
+
+static void
+rebalance(void)
+{
+ int pri, npri, t, x;
+ Schedq *rq;
+ Proc *p;
+
+ t = m->ticks;
+ if(t - balancetime < HZ)
+ return;
+ balancetime = t;
+
+ for(pri=0, rq=runq; pri<Npriq; pri++, rq++){
+another:
+ p = rq->head;
+ if(p == nil)
+ continue;
+ if(p->mp != MACHP(m->machno))
+ continue;
+ if(pri == p->basepri)
+ continue;
+ updatecpu(p);
+ npri = reprioritize(p);
+ if(npri != pri){
+ x = splhi();
+ p = dequeueproc(rq, p);
+ if(p)
+ queueproc(&runq[npri], p);
+ splx(x);
+ goto another;
+ }
+ }
+}
+
+
+/*
+ * pick a process to run
+ */
+Proc*
+runproc(void)
+{
+ Schedq *rq;
+ Proc *p;
+ ulong start, now;
+ int i;
+ void (*pt)(Proc*, int, vlong);
+
+ start = perfticks();
+
+ /* cooperative scheduling until the clock ticks */
+ if((p=m->readied) && p->mach==0 && p->state==Ready
+ && runq[Nrq-1].head == nil && runq[Nrq-2].head == nil){
+ skipscheds++;
+ rq = &runq[p->priority];
+ goto found;
+ }
+
+ preempts++;
+
+loop:
+ /*
+ * find a process that last ran on this processor (affinity),
+ * or one that hasn't moved in a while (load balancing). Every
+ * time around the loop affinity goes down.
+ */
+ spllo();
+ for(i = 0;; i++){
+ /*
+ * find the highest priority target process that this
+ * processor can run given affinity constraints.
+ *
+ */
+ for(rq = &runq[Nrq-1]; rq >= runq; rq--){
+ for(p = rq->head; p; p = p->rnext){
+ if(p->mp == nil || p->mp == MACHP(m->machno)
+ || (!p->wired && i > 0))
+ goto found;
+ }
+ }
+
+ /* waste time or halt the CPU */
+ idlehands();
+
+ /* remember how much time we're here */
+ now = perfticks();
+ m->perf.inidle += now-start;
+ start = now;
+ }
+
+found:
+ splhi();
+ p = dequeueproc(rq, p);
+ if(p == nil)
+ goto loop;
+
+ p->state = Scheding;
+ p->mp = MACHP(m->machno);
+
+ if(edflock(p)){
+ edfrun(p, rq == &runq[PriEdf]); /* start deadline timer and do admin */
+ edfunlock();
+ }
+ pt = proctrace;
+ if(pt)
+ pt(p, SRun, 0);
+ return p;
+}
+
+int
+canpage(Proc *p)
+{
+ int ok = 0;
+
+ splhi();
+ lock(runq);
+ /* Only reliable way to see if we are Running */
+ if(p->mach == 0) {
+ p->newtlb = 1;
+ ok = 1;
+ }
+ unlock(runq);
+ spllo();
+
+ return ok;
+}
+
+Proc*
+newproc(void)
+{
+ char msg[64];
+ Proc *p;
+
+ lock(&procalloc);
+ for(;;) {
+ if(p = procalloc.free)
+ break;
+
+ snprint(msg, sizeof msg, "no procs; %s forking",
+ up? up->text: "kernel");
+ unlock(&procalloc);
+ resrcwait(msg);
+ lock(&procalloc);
+ }
+ procalloc.free = p->qnext;
+ unlock(&procalloc);
+
+ p->state = Scheding;
+ p->psstate = "New";
+ p->mach = 0;
+ p->qnext = 0;
+ p->nchild = 0;
+ p->nwait = 0;
+ p->waitq = 0;
+ p->parent = 0;
+ p->pgrp = 0;
+ p->egrp = 0;
+ p->fgrp = 0;
+ p->rgrp = 0;
+ p->pdbg = 0;
+ p->fpstate = FPinit;
+ p->kp = 0;
+ if(up && up->procctl == Proc_tracesyscall)
+ p->procctl = Proc_tracesyscall;
+ else
+ p->procctl = 0;
+ p->syscalltrace = 0;
+ p->notepending = 0;
+ p->ureg = 0;
+ p->privatemem = 0;
+ p->noswap = 0;
+ p->errstr = p->errbuf0;
+ p->syserrstr = p->errbuf1;
+ p->errbuf0[0] = '\0';
+ p->errbuf1[0] = '\0';
+ p->nlocks.ref = 0;
+ p->delaysched = 0;
+ p->trace = 0;
+ kstrdup(&p->user, "*nouser");
+ kstrdup(&p->text, "*notext");
+ kstrdup(&p->args, "");
+ p->nargs = 0;
+ p->setargs = 0;
+ memset(p->seg, 0, sizeof p->seg);
+ p->pid = incref(&pidalloc);
+ pidhash(p);
+ p->noteid = incref(&noteidalloc);
+ if(p->pid==0 || p->noteid==0)
+ panic("pidalloc");
+ if(p->kstack == 0)
+ p->kstack = smalloc(KSTACK);
+
+ /* sched params */
+ p->mp = 0;
+ p->wired = 0;
+ procpriority(p, PriNormal, 0);
+ p->cpu = 0;
+ p->lastupdate = MACHP(0)->ticks*Scaling;
+ p->edf = nil;
+
+ return p;
+}
+
+/*
+ * wire this proc to a machine
+ */
+void
+procwired(Proc *p, int bm)
+{
+ Proc *pp;
+ int i;
+ char nwired[MAXMACH];
+ Mach *wm;
+
+ if(bm < 0){
+ /* pick a machine to wire to */
+ memset(nwired, 0, sizeof(nwired));
+ p->wired = 0;
+ pp = proctab(0);
+ for(i=0; i<conf.nproc; i++, pp++){
+ wm = pp->wired;
+ if(wm && pp->pid)
+ nwired[wm->machno]++;
+ }
+ bm = 0;
+ for(i=0; i<conf.nmach; i++)
+ if(nwired[i] < nwired[bm])
+ bm = i;
+ } else {
+ /* use the virtual machine requested */
+ bm = bm % conf.nmach;
+ }
+
+ p->wired = MACHP(bm);
+ p->mp = p->wired;
+}
+
+void
+procpriority(Proc *p, int pri, int fixed)
+{
+ if(pri >= Npriq)
+ pri = Npriq - 1;
+ else if(pri < 0)
+ pri = 0;
+ p->basepri = pri;
+ p->priority = pri;
+ if(fixed){
+ p->fixedpri = 1;
+ } else {
+ p->fixedpri = 0;
+ }
+}
+
+void
+procinit0(void) /* bad planning - clashes with devproc.c */
+{
+ Proc *p;
+ int i;
+
+ procalloc.free = xalloc(conf.nproc*sizeof(Proc));
+ if(procalloc.free == nil){
+ xsummary();
+ panic("cannot allocate %lud procs (%ludMB)\n", conf.nproc, conf.nproc*sizeof(Proc)/(1024*1024));
+ }
+ procalloc.arena = procalloc.free;
+
+ p = procalloc.free;
+ for(i=0; i<conf.nproc-1; i++,p++)
+ p->qnext = p+1;
+ p->qnext = 0;
+}
+
+/*
+ * sleep if a condition is not true. Another process will
+ * awaken us after it sets the condition. When we awaken
+ * the condition may no longer be true.
+ *
+ * we lock both the process and the rendezvous to keep r->p
+ * and p->r synchronized.
+ */
+void
+sleep(Rendez *r, int (*f)(void*), void *arg)
+{
+ int s;
+ void (*pt)(Proc*, int, vlong);
+
+ s = splhi();
+
+ if(up->nlocks.ref)
+ print("process %lud sleeps with %lud locks held, last lock %#p locked at pc %#lux, sleep called from %#p\n",
+ up->pid, up->nlocks.ref, up->lastlock, up->lastlock->pc, getcallerpc(&r));
+ lock(r);
+ lock(&up->rlock);
+ if(r->p){
+ print("double sleep called from %#p, %lud %lud\n", getcallerpc(&r), r->p->pid, up->pid);
+ dumpstack();
+ }
+
+ /*
+ * Wakeup only knows there may be something to do by testing
+ * r->p in order to get something to lock on.
+ * Flush that information out to memory in case the sleep is
+ * committed.
+ */
+ r->p = up;
+
+ if((*f)(arg) || up->notepending){
+ /*
+ * if condition happened or a note is pending
+ * never mind
+ */
+ r->p = nil;
+ unlock(&up->rlock);
+ unlock(r);
+ } else {
+ /*
+ * now we are committed to
+ * change state and call scheduler
+ */
+ pt = proctrace;
+ if(pt)
+ pt(up, SSleep, 0);
+ up->state = Wakeme;
+ up->r = r;
+
+ /* statistics */
+ m->cs++;
+
+ procsave(up);
+ if(setlabel(&up->sched)) {
+ /*
+ * here when the process is awakened
+ */
+ procrestore(up);
+ spllo();
+ } else {
+ /*
+ * here to go to sleep (i.e. stop Running)
+ */
+ unlock(&up->rlock);
+ unlock(r);
+ gotolabel(&m->sched);
+ }
+ }
+
+ if(up->notepending) {
+ up->notepending = 0;
+ splx(s);
+ if(up->procctl == Proc_exitme && up->closingfgrp)
+ forceclosefgrp();
+ error(Eintr);
+ }
+
+ splx(s);
+}
+
+static int
+tfn(void *arg)
+{
+ return up->trend == nil || up->tfn(arg);
+}
+
+void
+twakeup(Ureg*, Timer *t)
+{
+ Proc *p;
+ Rendez *trend;
+
+ p = t->ta;
+ trend = p->trend;
+ p->trend = 0;
+ if(trend)
+ wakeup(trend);
+}
+
+void
+tsleep(Rendez *r, int (*fn)(void*), void *arg, ulong ms)
+{
+ if (up->tt){
+ print("tsleep: timer active: mode %d, tf %#p\n", up->tmode, up->tf);
+ timerdel(up);
+ }
+ up->tns = MS2NS(ms);
+ up->tf = twakeup;
+ up->tmode = Trelative;
+ up->ta = up;
+ up->trend = r;
+ up->tfn = fn;
+ timeradd(up);
+
+ if(waserror()){
+ timerdel(up);
+ nexterror();
+ }
+ sleep(r, tfn, arg);
+ if (up->tt)
+ timerdel(up);
+ up->twhen = 0;
+ poperror();
+}
+
+/*
+ * Expects that only one process can call wakeup for any given Rendez.
+ * We hold both locks to ensure that r->p and p->r remain consistent.
+ * Richard Miller has a better solution that doesn't require both to
+ * be held simultaneously, but I'm a paranoid - presotto.
+ */
+Proc*
+wakeup(Rendez *r)
+{
+ Proc *p;
+ int s;
+
+ s = splhi();
+
+ lock(r);
+ p = r->p;
+
+ if(p != nil){
+ lock(&p->rlock);
+ if(p->state != Wakeme || p->r != r){
+ iprint("%p %p %d\n", p->r, r, p->state);
+ panic("wakeup: state");
+ }
+ r->p = nil;
+ p->r = nil;
+ ready(p);
+ unlock(&p->rlock);
+ }
+ unlock(r);
+
+ splx(s);
+
+ return p;
+}
+
+/*
+ * if waking a sleeping process, this routine must hold both
+ * p->rlock and r->lock. However, it can't know them in
+ * the same order as wakeup causing a possible lock ordering
+ * deadlock. We break the deadlock by giving up the p->rlock
+ * lock if we can't get the r->lock and retrying.
+ */
+int
+postnote(Proc *p, int dolock, char *n, int flag)
+{
+ int s, ret;
+ Rendez *r;
+ Proc *d, **l;
+
+ if(dolock)
+ qlock(&p->debug);
+
+ if(flag != NUser && (p->notify == 0 || p->notified))
+ p->nnote = 0;
+
+ ret = 0;
+ if(p->nnote < NNOTE) {
+ strcpy(p->note[p->nnote].msg, n);
+ p->note[p->nnote++].flag = flag;
+ ret = 1;
+ }
+ p->notepending = 1;
+ if(dolock)
+ qunlock(&p->debug);
+
+ /* this loop is to avoid lock ordering problems. */
+ for(;;){
+ s = splhi();
+ lock(&p->rlock);
+ r = p->r;
+
+ /* waiting for a wakeup? */
+ if(r == nil)
+ break; /* no */
+
+ /* try for the second lock */
+ if(canlock(r)){
+ if(p->state != Wakeme || r->p != p)
+ panic("postnote: state %d %d %d", r->p != p, p->r != r, p->state);
+ p->r = nil;
+ r->p = nil;
+ ready(p);
+ unlock(r);
+ break;
+ }
+
+ /* give other process time to get out of critical section and try again */
+ unlock(&p->rlock);
+ splx(s);
+ sched();
+ }
+ unlock(&p->rlock);
+ splx(s);
+
+ if(p->state != Rendezvous)
+ return ret;
+
+ /* Try and pull out of a rendezvous */
+ lock(p->rgrp);
+ if(p->state == Rendezvous) {
+ p->rendval = ~0;
+ l = &REND(p->rgrp, p->rendtag);
+ for(d = *l; d; d = d->rendhash) {
+ if(d == p) {
+ *l = p->rendhash;
+ break;
+ }
+ l = &d->rendhash;
+ }
+ ready(p);
+ }
+ unlock(p->rgrp);
+ return ret;
+}
+
+/*
+ * weird thing: keep at most NBROKEN around
+ */
+#define NBROKEN 4
+struct
+{
+ QLock;
+ int n;
+ Proc *p[NBROKEN];
+}broken;
+
+void
+addbroken(Proc *p)
+{
+ qlock(&broken);
+ if(broken.n == NBROKEN) {
+ ready(broken.p[0]);
+ memmove(&broken.p[0], &broken.p[1], sizeof(Proc*)*(NBROKEN-1));
+ --broken.n;
+ }
+ broken.p[broken.n++] = p;
+ qunlock(&broken);
+
+ edfstop(up);
+ p->state = Broken;
+ p->psstate = 0;
+ sched();
+}
+
+void
+unbreak(Proc *p)
+{
+ int b;
+
+ qlock(&broken);
+ for(b=0; b < broken.n; b++)
+ if(broken.p[b] == p) {
+ broken.n--;
+ memmove(&broken.p[b], &broken.p[b+1],
+ sizeof(Proc*)*(NBROKEN-(b+1)));
+ ready(p);
+ break;
+ }
+ qunlock(&broken);
+}
+
+int
+freebroken(void)
+{
+ int i, n;
+
+ qlock(&broken);
+ n = broken.n;
+ for(i=0; i<n; i++) {
+ ready(broken.p[i]);
+ broken.p[i] = 0;
+ }
+ broken.n = 0;
+ qunlock(&broken);
+ return n;
+}
+
+void
+pexit(char *exitstr, int freemem)
+{
+ Proc *p;
+ Segment **s, **es;
+ long utime, stime;
+ Waitq *wq, *f, *next;
+ Fgrp *fgrp;
+ Egrp *egrp;
+ Rgrp *rgrp;
+ Pgrp *pgrp;
+ Chan *dot;
+ void (*pt)(Proc*, int, vlong);
+
+ if(up->syscalltrace)
+ free(up->syscalltrace);
+ up->alarm = 0;
+ if (up->tt)
+ timerdel(up);
+ pt = proctrace;
+ if(pt)
+ pt(up, SDead, 0);
+
+ /* nil out all the resources under lock (free later) */
+ qlock(&up->debug);
+ fgrp = up->fgrp;
+ up->fgrp = nil;
+ egrp = up->egrp;
+ up->egrp = nil;
+ rgrp = up->rgrp;
+ up->rgrp = nil;
+ pgrp = up->pgrp;
+ up->pgrp = nil;
+ dot = up->dot;
+ up->dot = nil;
+ qunlock(&up->debug);
+
+ if(fgrp)
+ closefgrp(fgrp);
+ if(egrp)
+ closeegrp(egrp);
+ if(rgrp)
+ closergrp(rgrp);
+ if(dot)
+ cclose(dot);
+ if(pgrp)
+ closepgrp(pgrp);
+
+ /*
+ * if not a kernel process and have a parent,
+ * do some housekeeping.
+ */
+ if(up->kp == 0) {
+ p = up->parent;
+ if(p == 0) {
+ if(exitstr == 0)
+ exitstr = "unknown";
+ panic("boot process died: %s", exitstr);
+ }
+
+ while(waserror())
+ ;
+
+ wq = smalloc(sizeof(Waitq));
+ poperror();
+
+ wq->w.pid = up->pid;
+ utime = up->time[TUser] + up->time[TCUser];
+ stime = up->time[TSys] + up->time[TCSys];
+ wq->w.time[TUser] = tk2ms(utime);
+ wq->w.time[TSys] = tk2ms(stime);
+ wq->w.time[TReal] = tk2ms(MACHP(0)->ticks - up->time[TReal]);
+ if(exitstr && exitstr[0])
+ snprint(wq->w.msg, sizeof(wq->w.msg), "%s %lud: %s", up->text, up->pid, exitstr);
+ else
+ wq->w.msg[0] = '\0';
+
+ lock(&p->exl);
+ /*
+ * Check that parent is still alive.
+ */
+ if(p->pid == up->parentpid && p->state != Broken) {
+ p->nchild--;
+ p->time[TCUser] += utime;
+ p->time[TCSys] += stime;
+ /*
+ * If there would be more than 128 wait records
+ * processes for my parent, then don't leave a wait
+ * record behind. This helps prevent badly written
+ * daemon processes from accumulating lots of wait
+ * records.
+ */
+ if(p->nwait < 128) {
+ wq->next = p->waitq;
+ p->waitq = wq;
+ p->nwait++;
+ wq = nil;
+ wakeup(&p->waitr);
+ }
+ }
+ unlock(&p->exl);
+ if(wq)
+ free(wq);
+ }
+
+ if(!freemem)
+ addbroken(up);
+
+ qlock(&up->seglock);
+ es = &up->seg[NSEG];
+ for(s = up->seg; s < es; s++) {
+ if(*s) {
+ putseg(*s);
+ *s = 0;
+ }
+ }
+ qunlock(&up->seglock);
+
+ lock(&up->exl); /* Prevent my children from leaving waits */
+ pidunhash(up);
+ up->pid = 0;
+ wakeup(&up->waitr);
+ unlock(&up->exl);
+
+ for(f = up->waitq; f; f = next) {
+ next = f->next;
+ free(f);
+ }
+
+ /* release debuggers */
+ qlock(&up->debug);
+ if(up->pdbg) {
+ wakeup(&up->pdbg->sleep);
+ up->pdbg = 0;
+ }
+ qunlock(&up->debug);
+
+ /* Sched must not loop for these locks */
+ lock(&procalloc);
+ lock(&palloc);
+
+ edfstop(up);
+ up->state = Moribund;
+ sched();
+ panic("pexit");
+}
+
+int
+haswaitq(void *x)
+{
+ Proc *p;
+
+ p = (Proc *)x;
+ return p->waitq != 0;
+}
+
+ulong
+pwait(Waitmsg *w)
+{
+ ulong cpid;
+ Waitq *wq;
+
+ if(!canqlock(&up->qwaitr))
+ error(Einuse);
+
+ if(waserror()) {
+ qunlock(&up->qwaitr);
+ nexterror();
+ }
+
+ lock(&up->exl);
+ if(up->nchild == 0 && up->waitq == 0) {
+ unlock(&up->exl);
+ error(Enochild);
+ }
+ unlock(&up->exl);
+
+ sleep(&up->waitr, haswaitq, up);
+
+ lock(&up->exl);
+ wq = up->waitq;
+ up->waitq = wq->next;
+ up->nwait--;
+ unlock(&up->exl);
+
+ qunlock(&up->qwaitr);
+ poperror();
+
+ if(w)
+ memmove(w, &wq->w, sizeof(Waitmsg));
+ cpid = wq->w.pid;
+ free(wq);
+ return cpid;
+}
+
+Proc*
+proctab(int i)
+{
+ return &procalloc.arena[i];
+}
+
+void
+dumpaproc(Proc *p)
+{
+ ulong bss;
+ char *s;
+
+ if(p == 0)
+ return;
+
+ bss = 0;
+ if(p->seg[BSEG])
+ bss = p->seg[BSEG]->top;
+
+ s = p->psstate;
+ if(s == 0)
+ s = statename[p->state];
+ print("%3lud:%10s pc %8lux dbgpc %8lux %8s (%s) ut %ld st %ld bss %lux qpc %lux nl %lud nd %lud lpc %lux pri %lud\n",
+ p->pid, p->text, p->pc, dbgpc(p), s, statename[p->state],
+ p->time[0], p->time[1], bss, p->qpc, p->nlocks.ref, p->delaysched, p->lastlock ? p->lastlock->pc : 0, p->priority);
+}
+
+void
+procdump(void)
+{
+ int i;
+ Proc *p;
+
+ if(up)
+ print("up %lud\n", up->pid);
+ else
+ print("no current process\n");
+ for(i=0; i<conf.nproc; i++) {
+ p = &procalloc.arena[i];
+ if(p->state == Dead)
+ continue;
+
+ dumpaproc(p);
+ }
+}
+
+/*
+ * wait till all processes have flushed their mmu
+ * state about segement s
+ */
+void
+procflushseg(Segment *s)
+{
+ int i, ns, nm, nwait;
+ Proc *p;
+
+ /*
+ * tell all processes with this
+ * segment to flush their mmu's
+ */
+ nwait = 0;
+ for(i=0; i<conf.nproc; i++) {
+ p = &procalloc.arena[i];
+ if(p->state == Dead)
+ continue;
+ for(ns = 0; ns < NSEG; ns++)
+ if(p->seg[ns] == s){
+ p->newtlb = 1;
+ for(nm = 0; nm < conf.nmach; nm++){
+ if(MACHP(nm)->proc == p){
+ MACHP(nm)->flushmmu = 1;
+ nwait++;
+ }
+ }
+ break;
+ }
+ }
+
+ if(nwait == 0)
+ return;
+
+ /*
+ * wait for all processors to take a clock interrupt
+ * and flush their mmu's
+ */
+ for(nm = 0; nm < conf.nmach; nm++)
+ if(MACHP(nm) != m)
+ while(MACHP(nm)->flushmmu)
+ sched();
+}
+
+void
+scheddump(void)
+{
+ Proc *p;
+ Schedq *rq;
+
+ for(rq = &runq[Nrq-1]; rq >= runq; rq--){
+ if(rq->head == 0)
+ continue;
+ print("rq%ld:", rq-runq);
+ for(p = rq->head; p; p = p->rnext)
+ print(" %lud(%lud)", p->pid, m->ticks - p->readytime);
+ print("\n");
+ delay(150);
+ }
+ print("nrdy %d\n", nrdy);
+}
+
+void
+kproc(char *name, void (*func)(void *), void *arg)
+{
+ Proc *p;
+ static Pgrp *kpgrp;
+
+ p = newproc();
+ p->psstate = 0;
+ p->procmode = 0640;
+ p->kp = 1;
+ p->noswap = 1;
+
+ p->fpsave = up->fpsave;
+ p->scallnr = up->scallnr;
+ p->s = up->s;
+ p->nerrlab = 0;
+ p->slash = up->slash;
+ p->dot = up->dot;
+ if(p->dot)
+ incref(p->dot);
+
+ memmove(p->note, up->note, sizeof(p->note));
+ p->nnote = up->nnote;
+ p->notified = 0;
+ p->lastnote = up->lastnote;
+ p->notify = up->notify;
+ p->ureg = 0;
+ p->dbgreg = 0;
+
+ procpriority(p, PriKproc, 0);
+
+ kprocchild(p, func, arg);
+
+ kstrdup(&p->user, eve);
+ kstrdup(&p->text, name);
+ if(kpgrp == 0)
+ kpgrp = newpgrp();
+ p->pgrp = kpgrp;
+ incref(kpgrp);
+
+ memset(p->time, 0, sizeof(p->time));
+ p->time[TReal] = MACHP(0)->ticks;
+ ready(p);
+ /*
+ * since the bss/data segments are now shareable,
+ * any mmu info about this process is now stale
+ * and has to be discarded.
+ */
+ p->newtlb = 1;
+ flushmmu();
+}
+
+/*
+ * called splhi() by notify(). See comment in notify for the
+ * reasoning.
+ */
+void
+procctl(Proc *p)
+{
+ char *state;
+ ulong s;
+
+ switch(p->procctl) {
+ case Proc_exitbig:
+ spllo();
+ pexit("Killed: Insufficient physical memory", 1);
+
+ case Proc_exitme:
+ spllo(); /* pexit has locks in it */
+ pexit("Killed", 1);
+
+ case Proc_traceme:
+ if(p->nnote == 0)
+ return;
+ /* No break */
+
+ case Proc_stopme:
+ p->procctl = 0;
+ state = p->psstate;
+ p->psstate = "Stopped";
+ /* free a waiting debugger */
+ s = spllo();
+ qlock(&p->debug);
+ if(p->pdbg) {
+ wakeup(&p->pdbg->sleep);
+ p->pdbg = 0;
+ }
+ qunlock(&p->debug);
+ splhi();
+ p->state = Stopped;
+ sched();
+ p->psstate = state;
+ splx(s);
+ return;
+ }
+}
+
+#include "errstr.h"
+
+void
+error(char *err)
+{
+ spllo();
+
+ assert(up->nerrlab < NERR);
+ kstrcpy(up->errstr, err, ERRMAX);
+ setlabel(&up->errlab[NERR-1]);
+ nexterror();
+}
+
+void
+nexterror(void)
+{
+ gotolabel(&up->errlab[--up->nerrlab]);
+}
+
+void
+exhausted(char *resource)
+{
+ char buf[ERRMAX];
+
+ snprint(buf, sizeof buf, "no free %s", resource);
+ iprint("%s\n", buf);
+ error(buf);
+}
+
+void
+killbig(char *why)
+{
+ int i;
+ Segment *s;
+ ulong l, max;
+ Proc *p, *ep, *kp;
+
+ max = 0;
+ kp = 0;
+ ep = procalloc.arena+conf.nproc;
+ for(p = procalloc.arena; p < ep; p++) {
+ if(p->state == Dead || p->kp)
+ continue;
+ l = 0;
+ for(i=1; i<NSEG; i++) {
+ s = p->seg[i];
+ if(s != 0)
+ l += s->top - s->base;
+ }
+ if(l > max && ((p->procmode&0222) || strcmp(eve, p->user)!=0)) {
+ kp = p;
+ max = l;
+ }
+ }
+
+ print("%lud: %s killed: %s\n", kp->pid, kp->text, why);
+ for(p = procalloc.arena; p < ep; p++) {
+ if(p->state == Dead || p->kp)
+ continue;
+ if(p != kp && p->seg[BSEG] && p->seg[BSEG] == kp->seg[BSEG])
+ p->procctl = Proc_exitbig;
+ }
+ kp->procctl = Proc_exitbig;
+ for(i = 0; i < NSEG; i++) {
+ s = kp->seg[i];
+ if(s != 0 && canqlock(&s->lk)) {
+ mfreeseg(s, s->base, (s->top - s->base)/BY2PG);
+ qunlock(&s->lk);
+ }
+ }
+}
+
+/*
+ * change ownership to 'new' of all processes owned by 'old'. Used when
+ * eve changes.
+ */
+void
+renameuser(char *old, char *new)
+{
+ Proc *p, *ep;
+
+ ep = procalloc.arena+conf.nproc;
+ for(p = procalloc.arena; p < ep; p++)
+ if(p->user!=nil && strcmp(old, p->user)==0)
+ kstrdup(&p->user, new);
+}
+
+/*
+ * time accounting called by clock() splhi'd
+ */
+void
+accounttime(void)
+{
+ Proc *p;
+ ulong n, per;
+ static ulong nrun;
+
+ p = m->proc;
+ if(p) {
+ nrun++;
+ p->time[p->insyscall]++;
+ }
+
+ /* calculate decaying duty cycles */
+ n = perfticks();
+ per = n - m->perf.last;
+ m->perf.last = n;
+ per = (m->perf.period*(HZ-1) + per)/HZ;
+ if(per != 0)
+ m->perf.period = per;
+
+ m->perf.avg_inidle = (m->perf.avg_inidle*(HZ-1)+m->perf.inidle)/HZ;
+ m->perf.inidle = 0;
+
+ m->perf.avg_inintr = (m->perf.avg_inintr*(HZ-1)+m->perf.inintr)/HZ;
+ m->perf.inintr = 0;
+
+ /* only one processor gets to compute system load averages */
+ if(m->machno != 0)
+ return;
+
+ /*
+ * calculate decaying load average.
+ * if we decay by (n-1)/n then it takes
+ * n clock ticks to go from load L to .36 L once
+ * things quiet down. it takes about 5 n clock
+ * ticks to go to zero. so using HZ means this is
+ * approximately the load over the last second,
+ * with a tail lasting about 5 seconds.
+ */
+ n = nrun;
+ nrun = 0;
+ n = (nrdy+n)*1000;
+ m->load = (m->load*(HZ-1)+n)/HZ;
+}
+
+static void
+pidhash(Proc *p)
+{
+ int h;
+
+ h = p->pid % nelem(procalloc.ht);
+ lock(&procalloc);
+ p->pidhash = procalloc.ht[h];
+ procalloc.ht[h] = p;
+ unlock(&procalloc);
+}
+
+static void
+pidunhash(Proc *p)
+{
+ int h;
+ Proc **l;
+
+ h = p->pid % nelem(procalloc.ht);
+ lock(&procalloc);
+ for(l = &procalloc.ht[h]; *l != nil; l = &(*l)->pidhash)
+ if(*l == p){
+ *l = p->pidhash;
+ break;
+ }
+ unlock(&procalloc);
+}
+
+int
+procindex(ulong pid)
+{
+ Proc *p;
+ int h;
+ int s;
+
+ s = -1;
+ h = pid % nelem(procalloc.ht);
+ lock(&procalloc);
+ for(p = procalloc.ht[h]; p != nil; p = p->pidhash)
+ if(p->pid == pid){
+ s = p - procalloc.arena;
+ break;
+ }
+ unlock(&procalloc);
+ return s;
+}
diff --git a/sys/src/9/port/qio.c b/sys/src/9/port/qio.c
new file mode 100755
index 000000000..76b04be2b
--- /dev/null
+++ b/sys/src/9/port/qio.c
@@ -0,0 +1,1540 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+static ulong padblockcnt;
+static ulong concatblockcnt;
+static ulong pullupblockcnt;
+static ulong copyblockcnt;
+static ulong consumecnt;
+static ulong producecnt;
+static ulong qcopycnt;
+
+static int debugging;
+
+#define QDEBUG if(0)
+
+/*
+ * IO queues
+ */
+typedef struct Queue Queue;
+
+struct Queue
+{
+ Lock;
+
+ Block* bfirst; /* buffer */
+ Block* blast;
+
+ int len; /* bytes allocated to queue */
+ int dlen; /* data bytes in queue */
+ int limit; /* max bytes in queue */
+ int inilim; /* initial limit */
+ int state;
+ int noblock; /* true if writes return immediately when q full */
+ int eof; /* number of eofs read by user */
+
+ void (*kick)(void*); /* restart output */
+ void (*bypass)(void*, Block*); /* bypass queue altogether */
+ void* arg; /* argument to kick */
+
+ QLock rlock; /* mutex for reading processes */
+ Rendez rr; /* process waiting to read */
+ QLock wlock; /* mutex for writing processes */
+ Rendez wr; /* process waiting to write */
+
+ char err[ERRMAX];
+};
+
+enum
+{
+ Maxatomic = 64*1024,
+};
+
+uint qiomaxatomic = Maxatomic;
+
+void
+ixsummary(void)
+{
+ debugging ^= 1;
+ iallocsummary();
+ print("pad %lud, concat %lud, pullup %lud, copy %lud\n",
+ padblockcnt, concatblockcnt, pullupblockcnt, copyblockcnt);
+ print("consume %lud, produce %lud, qcopy %lud\n",
+ consumecnt, producecnt, qcopycnt);
+}
+
+/*
+ * free a list of blocks
+ */
+void
+freeblist(Block *b)
+{
+ Block *next;
+
+ for(; b != 0; b = next){
+ next = b->next;
+ if(b->ref == 1)
+ b->next = nil;
+ freeb(b);
+ }
+}
+
+/*
+ * pad a block to the front (or the back if size is negative)
+ */
+Block*
+padblock(Block *bp, int size)
+{
+ int n;
+ Block *nbp;
+
+ QDEBUG checkb(bp, "padblock 1");
+ if(size >= 0){
+ if(bp->rp - bp->base >= size){
+ bp->rp -= size;
+ return bp;
+ }
+
+ if(bp->next)
+ panic("padblock %#p", getcallerpc(&bp));
+ n = BLEN(bp);
+ padblockcnt++;
+ nbp = allocb(size+n);
+ nbp->rp += size;
+ nbp->wp = nbp->rp;
+ memmove(nbp->wp, bp->rp, n);
+ nbp->wp += n;
+ freeb(bp);
+ nbp->rp -= size;
+ } else {
+ size = -size;
+
+ if(bp->next)
+ panic("padblock %#p", getcallerpc(&bp));
+
+ if(bp->lim - bp->wp >= size)
+ return bp;
+
+ n = BLEN(bp);
+ padblockcnt++;
+ nbp = allocb(size+n);
+ memmove(nbp->wp, bp->rp, n);
+ nbp->wp += n;
+ freeb(bp);
+ }
+ QDEBUG checkb(nbp, "padblock 1");
+ return nbp;
+}
+
+/*
+ * return count of bytes in a string of blocks
+ */
+int
+blocklen(Block *bp)
+{
+ int len;
+
+ len = 0;
+ while(bp) {
+ len += BLEN(bp);
+ bp = bp->next;
+ }
+ return len;
+}
+
+/*
+ * return count of space in blocks
+ */
+int
+blockalloclen(Block *bp)
+{
+ int len;
+
+ len = 0;
+ while(bp) {
+ len += BALLOC(bp);
+ bp = bp->next;
+ }
+ return len;
+}
+
+/*
+ * copy the string of blocks into
+ * a single block and free the string
+ */
+Block*
+concatblock(Block *bp)
+{
+ int len;
+ Block *nb, *f;
+
+ if(bp->next == 0)
+ return bp;
+
+ nb = allocb(blocklen(bp));
+ for(f = bp; f; f = f->next) {
+ len = BLEN(f);
+ memmove(nb->wp, f->rp, len);
+ nb->wp += len;
+ }
+ concatblockcnt += BLEN(nb);
+ freeblist(bp);
+ QDEBUG checkb(nb, "concatblock 1");
+ return nb;
+}
+
+/*
+ * make sure the first block has at least n bytes
+ */
+Block*
+pullupblock(Block *bp, int n)
+{
+ int i;
+ Block *nbp;
+
+ /*
+ * this should almost always be true, it's
+ * just to avoid every caller checking.
+ */
+ if(BLEN(bp) >= n)
+ return bp;
+
+ /*
+ * if not enough room in the first block,
+ * add another to the front of the list.
+ */
+ if(bp->lim - bp->rp < n){
+ nbp = allocb(n);
+ nbp->next = bp;
+ bp = nbp;
+ }
+
+ /*
+ * copy bytes from the trailing blocks into the first
+ */
+ n -= BLEN(bp);
+ while(nbp = bp->next){
+ i = BLEN(nbp);
+ if(i > n) {
+ memmove(bp->wp, nbp->rp, n);
+ pullupblockcnt++;
+ bp->wp += n;
+ nbp->rp += n;
+ QDEBUG checkb(bp, "pullupblock 1");
+ return bp;
+ } else {
+ /* shouldn't happen but why crash if it does */
+ if(i < 0){
+ print("pullup negative length packet, called from %#p\n",
+ getcallerpc(&bp));
+ i = 0;
+ }
+ memmove(bp->wp, nbp->rp, i);
+ pullupblockcnt++;
+ bp->wp += i;
+ bp->next = nbp->next;
+ nbp->next = 0;
+ freeb(nbp);
+ n -= i;
+ if(n == 0){
+ QDEBUG checkb(bp, "pullupblock 2");
+ return bp;
+ }
+ }
+ }
+ freeb(bp);
+ return 0;
+}
+
+/*
+ * make sure the first block has at least n bytes
+ */
+Block*
+pullupqueue(Queue *q, int n)
+{
+ Block *b;
+
+ if(BLEN(q->bfirst) >= n)
+ return q->bfirst;
+ q->bfirst = pullupblock(q->bfirst, n);
+ for(b = q->bfirst; b != nil && b->next != nil; b = b->next)
+ ;
+ q->blast = b;
+ return q->bfirst;
+}
+
+/*
+ * trim to len bytes starting at offset
+ */
+Block *
+trimblock(Block *bp, int offset, int len)
+{
+ ulong l;
+ Block *nb, *startb;
+
+ QDEBUG checkb(bp, "trimblock 1");
+ if(blocklen(bp) < offset+len) {
+ freeblist(bp);
+ return nil;
+ }
+
+ while((l = BLEN(bp)) < offset) {
+ offset -= l;
+ nb = bp->next;
+ bp->next = nil;
+ freeb(bp);
+ bp = nb;
+ }
+
+ startb = bp;
+ bp->rp += offset;
+
+ while((l = BLEN(bp)) < len) {
+ len -= l;
+ bp = bp->next;
+ }
+
+ bp->wp -= (BLEN(bp) - len);
+
+ if(bp->next) {
+ freeblist(bp->next);
+ bp->next = nil;
+ }
+
+ return startb;
+}
+
+/*
+ * copy 'count' bytes into a new block
+ */
+Block*
+copyblock(Block *bp, int count)
+{
+ int l;
+ Block *nbp;
+
+ QDEBUG checkb(bp, "copyblock 0");
+ nbp = allocb(count);
+ for(; count > 0 && bp != 0; bp = bp->next){
+ l = BLEN(bp);
+ if(l > count)
+ l = count;
+ memmove(nbp->wp, bp->rp, l);
+ nbp->wp += l;
+ count -= l;
+ }
+ if(count > 0){
+ memset(nbp->wp, 0, count);
+ nbp->wp += count;
+ }
+ copyblockcnt++;
+ QDEBUG checkb(nbp, "copyblock 1");
+
+ return nbp;
+}
+
+Block*
+adjustblock(Block* bp, int len)
+{
+ int n;
+ Block *nbp;
+
+ if(len < 0){
+ freeb(bp);
+ return nil;
+ }
+
+ if(bp->rp+len > bp->lim){
+ nbp = copyblock(bp, len);
+ freeblist(bp);
+ QDEBUG checkb(nbp, "adjustblock 1");
+
+ return nbp;
+ }
+
+ n = BLEN(bp);
+ if(len > n)
+ memset(bp->wp, 0, len-n);
+ bp->wp = bp->rp+len;
+ QDEBUG checkb(bp, "adjustblock 2");
+
+ return bp;
+}
+
+
+/*
+ * throw away up to count bytes from a
+ * list of blocks. Return count of bytes
+ * thrown away.
+ */
+int
+pullblock(Block **bph, int count)
+{
+ Block *bp;
+ int n, bytes;
+
+ bytes = 0;
+ if(bph == nil)
+ return 0;
+
+ while(*bph != nil && count != 0) {
+ bp = *bph;
+ n = BLEN(bp);
+ if(count < n)
+ n = count;
+ bytes += n;
+ count -= n;
+ bp->rp += n;
+ QDEBUG checkb(bp, "pullblock ");
+ if(BLEN(bp) == 0) {
+ *bph = bp->next;
+ bp->next = nil;
+ freeb(bp);
+ }
+ }
+ return bytes;
+}
+
+/*
+ * get next block from a queue, return null if nothing there
+ */
+Block*
+qget(Queue *q)
+{
+ int dowakeup;
+ Block *b;
+
+ /* sync with qwrite */
+ ilock(q);
+
+ b = q->bfirst;
+ if(b == nil){
+ q->state |= Qstarve;
+ iunlock(q);
+ return nil;
+ }
+ q->bfirst = b->next;
+ b->next = 0;
+ q->len -= BALLOC(b);
+ q->dlen -= BLEN(b);
+ QDEBUG checkb(b, "qget");
+
+ /* if writer flow controlled, restart */
+ if((q->state & Qflow) && q->len < q->limit/2){
+ q->state &= ~Qflow;
+ dowakeup = 1;
+ } else
+ dowakeup = 0;
+
+ iunlock(q);
+
+ if(dowakeup)
+ wakeup(&q->wr);
+
+ return b;
+}
+
+/*
+ * throw away the next 'len' bytes in the queue
+ */
+int
+qdiscard(Queue *q, int len)
+{
+ Block *b;
+ int dowakeup, n, sofar;
+
+ ilock(q);
+ for(sofar = 0; sofar < len; sofar += n){
+ b = q->bfirst;
+ if(b == nil)
+ break;
+ QDEBUG checkb(b, "qdiscard");
+ n = BLEN(b);
+ if(n <= len - sofar){
+ q->bfirst = b->next;
+ b->next = 0;
+ q->len -= BALLOC(b);
+ q->dlen -= BLEN(b);
+ freeb(b);
+ } else {
+ n = len - sofar;
+ b->rp += n;
+ q->dlen -= n;
+ }
+ }
+
+ /*
+ * if writer flow controlled, restart
+ *
+ * This used to be
+ * q->len < q->limit/2
+ * but it slows down tcp too much for certain write sizes.
+ * I really don't understand it completely. It may be
+ * due to the queue draining so fast that the transmission
+ * stalls waiting for the app to produce more data. - presotto
+ */
+ if((q->state & Qflow) && q->len < q->limit){
+ q->state &= ~Qflow;
+ dowakeup = 1;
+ } else
+ dowakeup = 0;
+
+ iunlock(q);
+
+ if(dowakeup)
+ wakeup(&q->wr);
+
+ return sofar;
+}
+
+/*
+ * Interrupt level copy out of a queue, return # bytes copied.
+ */
+int
+qconsume(Queue *q, void *vp, int len)
+{
+ Block *b;
+ int n, dowakeup;
+ uchar *p = vp;
+ Block *tofree = nil;
+
+ /* sync with qwrite */
+ ilock(q);
+
+ for(;;) {
+ b = q->bfirst;
+ if(b == 0){
+ q->state |= Qstarve;
+ iunlock(q);
+ return -1;
+ }
+ QDEBUG checkb(b, "qconsume 1");
+
+ n = BLEN(b);
+ if(n > 0)
+ break;
+ q->bfirst = b->next;
+ q->len -= BALLOC(b);
+
+ /* remember to free this */
+ b->next = tofree;
+ tofree = b;
+ };
+
+ if(n < len)
+ len = n;
+ memmove(p, b->rp, len);
+ consumecnt += n;
+ b->rp += len;
+ q->dlen -= len;
+
+ /* discard the block if we're done with it */
+ if((q->state & Qmsg) || len == n){
+ q->bfirst = b->next;
+ b->next = 0;
+ q->len -= BALLOC(b);
+ q->dlen -= BLEN(b);
+
+ /* remember to free this */
+ b->next = tofree;
+ tofree = b;
+ }
+
+ /* if writer flow controlled, restart */
+ if((q->state & Qflow) && q->len < q->limit/2){
+ q->state &= ~Qflow;
+ dowakeup = 1;
+ } else
+ dowakeup = 0;
+
+ iunlock(q);
+
+ if(dowakeup)
+ wakeup(&q->wr);
+
+ if(tofree != nil)
+ freeblist(tofree);
+
+ return len;
+}
+
+int
+qpass(Queue *q, Block *b)
+{
+ int dlen, len, dowakeup;
+
+ /* sync with qread */
+ dowakeup = 0;
+ ilock(q);
+ if(q->len >= q->limit){
+ freeblist(b);
+ iunlock(q);
+ return -1;
+ }
+ if(q->state & Qclosed){
+ len = BALLOC(b);
+ freeblist(b);
+ iunlock(q);
+ return len;
+ }
+
+ /* add buffer to queue */
+ if(q->bfirst)
+ q->blast->next = b;
+ else
+ q->bfirst = b;
+ len = BALLOC(b);
+ dlen = BLEN(b);
+ QDEBUG checkb(b, "qpass");
+ while(b->next){
+ b = b->next;
+ QDEBUG checkb(b, "qpass");
+ len += BALLOC(b);
+ dlen += BLEN(b);
+ }
+ q->blast = b;
+ q->len += len;
+ q->dlen += dlen;
+
+ if(q->len >= q->limit/2)
+ q->state |= Qflow;
+
+ if(q->state & Qstarve){
+ q->state &= ~Qstarve;
+ dowakeup = 1;
+ }
+ iunlock(q);
+
+ if(dowakeup)
+ wakeup(&q->rr);
+
+ return len;
+}
+
+int
+qpassnolim(Queue *q, Block *b)
+{
+ int dlen, len, dowakeup;
+
+ /* sync with qread */
+ dowakeup = 0;
+ ilock(q);
+
+ if(q->state & Qclosed){
+ freeblist(b);
+ iunlock(q);
+ return BALLOC(b);
+ }
+
+ /* add buffer to queue */
+ if(q->bfirst)
+ q->blast->next = b;
+ else
+ q->bfirst = b;
+ len = BALLOC(b);
+ dlen = BLEN(b);
+ QDEBUG checkb(b, "qpass");
+ while(b->next){
+ b = b->next;
+ QDEBUG checkb(b, "qpass");
+ len += BALLOC(b);
+ dlen += BLEN(b);
+ }
+ q->blast = b;
+ q->len += len;
+ q->dlen += dlen;
+
+ if(q->len >= q->limit/2)
+ q->state |= Qflow;
+
+ if(q->state & Qstarve){
+ q->state &= ~Qstarve;
+ dowakeup = 1;
+ }
+ iunlock(q);
+
+ if(dowakeup)
+ wakeup(&q->rr);
+
+ return len;
+}
+
+/*
+ * if the allocated space is way out of line with the used
+ * space, reallocate to a smaller block
+ */
+Block*
+packblock(Block *bp)
+{
+ Block **l, *nbp;
+ int n;
+
+ for(l = &bp; *l; l = &(*l)->next){
+ nbp = *l;
+ n = BLEN(nbp);
+ if((n<<2) < BALLOC(nbp)){
+ *l = allocb(n);
+ memmove((*l)->wp, nbp->rp, n);
+ (*l)->wp += n;
+ (*l)->next = nbp->next;
+ freeb(nbp);
+ }
+ }
+
+ return bp;
+}
+
+int
+qproduce(Queue *q, void *vp, int len)
+{
+ Block *b;
+ int dowakeup;
+ uchar *p = vp;
+
+ /* sync with qread */
+ dowakeup = 0;
+ ilock(q);
+
+ /* no waiting receivers, room in buffer? */
+ if(q->len >= q->limit){
+ q->state |= Qflow;
+ iunlock(q);
+ return -1;
+ }
+
+ /* save in buffer */
+ b = iallocb(len);
+ if(b == 0){
+ iunlock(q);
+ return 0;
+ }
+ memmove(b->wp, p, len);
+ producecnt += len;
+ b->wp += len;
+ if(q->bfirst)
+ q->blast->next = b;
+ else
+ q->bfirst = b;
+ q->blast = b;
+ /* b->next = 0; done by iallocb() */
+ q->len += BALLOC(b);
+ q->dlen += BLEN(b);
+ QDEBUG checkb(b, "qproduce");
+
+ if(q->state & Qstarve){
+ q->state &= ~Qstarve;
+ dowakeup = 1;
+ }
+
+ if(q->len >= q->limit)
+ q->state |= Qflow;
+ iunlock(q);
+
+ if(dowakeup)
+ wakeup(&q->rr);
+
+ return len;
+}
+
+/*
+ * copy from offset in the queue
+ */
+Block*
+qcopy(Queue *q, int len, ulong offset)
+{
+ int sofar;
+ int n;
+ Block *b, *nb;
+ uchar *p;
+
+ nb = allocb(len);
+
+ ilock(q);
+
+ /* go to offset */
+ b = q->bfirst;
+ for(sofar = 0; ; sofar += n){
+ if(b == nil){
+ iunlock(q);
+ return nb;
+ }
+ n = BLEN(b);
+ if(sofar + n > offset){
+ p = b->rp + offset - sofar;
+ n -= offset - sofar;
+ break;
+ }
+ QDEBUG checkb(b, "qcopy");
+ b = b->next;
+ }
+
+ /* copy bytes from there */
+ for(sofar = 0; sofar < len;){
+ if(n > len - sofar)
+ n = len - sofar;
+ memmove(nb->wp, p, n);
+ qcopycnt += n;
+ sofar += n;
+ nb->wp += n;
+ b = b->next;
+ if(b == nil)
+ break;
+ n = BLEN(b);
+ p = b->rp;
+ }
+ iunlock(q);
+
+ return nb;
+}
+
+/*
+ * called by non-interrupt code
+ */
+Queue*
+qopen(int limit, int msg, void (*kick)(void*), void *arg)
+{
+ Queue *q;
+
+ q = malloc(sizeof(Queue));
+ if(q == 0)
+ return 0;
+
+ q->limit = q->inilim = limit;
+ q->kick = kick;
+ q->arg = arg;
+ q->state = msg;
+
+ q->state |= Qstarve;
+ q->eof = 0;
+ q->noblock = 0;
+
+ return q;
+}
+
+/* open a queue to be bypassed */
+Queue*
+qbypass(void (*bypass)(void*, Block*), void *arg)
+{
+ Queue *q;
+
+ q = malloc(sizeof(Queue));
+ if(q == 0)
+ return 0;
+
+ q->limit = 0;
+ q->arg = arg;
+ q->bypass = bypass;
+ q->state = 0;
+
+ return q;
+}
+
+static int
+notempty(void *a)
+{
+ Queue *q = a;
+
+ return (q->state & Qclosed) || q->bfirst != 0;
+}
+
+/*
+ * wait for the queue to be non-empty or closed.
+ * called with q ilocked.
+ */
+static int
+qwait(Queue *q)
+{
+ /* wait for data */
+ for(;;){
+ if(q->bfirst != nil)
+ break;
+
+ if(q->state & Qclosed){
+ if(++q->eof > 3)
+ return -1;
+ if(*q->err && strcmp(q->err, Ehungup) != 0)
+ return -1;
+ return 0;
+ }
+
+ q->state |= Qstarve; /* flag requesting producer to wake me */
+ iunlock(q);
+ sleep(&q->rr, notempty, q);
+ ilock(q);
+ }
+ return 1;
+}
+
+/*
+ * add a block list to a queue
+ */
+void
+qaddlist(Queue *q, Block *b)
+{
+ /* queue the block */
+ if(q->bfirst)
+ q->blast->next = b;
+ else
+ q->bfirst = b;
+ q->len += blockalloclen(b);
+ q->dlen += blocklen(b);
+ while(b->next)
+ b = b->next;
+ q->blast = b;
+}
+
+/*
+ * called with q ilocked
+ */
+Block*
+qremove(Queue *q)
+{
+ Block *b;
+
+ b = q->bfirst;
+ if(b == nil)
+ return nil;
+ q->bfirst = b->next;
+ b->next = nil;
+ q->dlen -= BLEN(b);
+ q->len -= BALLOC(b);
+ QDEBUG checkb(b, "qremove");
+ return b;
+}
+
+/*
+ * copy the contents of a string of blocks into
+ * memory. emptied blocks are freed. return
+ * pointer to first unconsumed block.
+ */
+Block*
+bl2mem(uchar *p, Block *b, int n)
+{
+ int i;
+ Block *next;
+
+ for(; b != nil; b = next){
+ i = BLEN(b);
+ if(i > n){
+ memmove(p, b->rp, n);
+ b->rp += n;
+ return b;
+ }
+ memmove(p, b->rp, i);
+ n -= i;
+ p += i;
+ b->rp += i;
+ next = b->next;
+ freeb(b);
+ }
+ return nil;
+}
+
+/*
+ * copy the contents of memory into a string of blocks.
+ * return nil on error.
+ */
+Block*
+mem2bl(uchar *p, int len)
+{
+ int n;
+ Block *b, *first, **l;
+
+ first = nil;
+ l = &first;
+ if(waserror()){
+ freeblist(first);
+ nexterror();
+ }
+ do {
+ n = len;
+ if(n > Maxatomic)
+ n = Maxatomic;
+
+ *l = b = allocb(n);
+ setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]);
+ memmove(b->wp, p, n);
+ b->wp += n;
+ p += n;
+ len -= n;
+ l = &b->next;
+ } while(len > 0);
+ poperror();
+
+ return first;
+}
+
+/*
+ * put a block back to the front of the queue
+ * called with q ilocked
+ */
+void
+qputback(Queue *q, Block *b)
+{
+ b->next = q->bfirst;
+ if(q->bfirst == nil)
+ q->blast = b;
+ q->bfirst = b;
+ q->len += BALLOC(b);
+ q->dlen += BLEN(b);
+}
+
+/*
+ * flow control, get producer going again
+ * called with q ilocked
+ */
+static void
+qwakeup_iunlock(Queue *q)
+{
+ int dowakeup = 0;
+
+ /* if writer flow controlled, restart */
+ if((q->state & Qflow) && q->len < q->limit/2){
+ q->state &= ~Qflow;
+ dowakeup = 1;
+ }
+
+ iunlock(q);
+
+ /* wakeup flow controlled writers */
+ if(dowakeup){
+ if(q->kick)
+ q->kick(q->arg);
+ wakeup(&q->wr);
+ }
+}
+
+/*
+ * get next block from a queue (up to a limit)
+ */
+Block*
+qbread(Queue *q, int len)
+{
+ Block *b, *nb;
+ int n;
+
+ qlock(&q->rlock);
+ if(waserror()){
+ qunlock(&q->rlock);
+ nexterror();
+ }
+
+ ilock(q);
+ switch(qwait(q)){
+ case 0:
+ /* queue closed */
+ iunlock(q);
+ qunlock(&q->rlock);
+ poperror();
+ return nil;
+ case -1:
+ /* multiple reads on a closed queue */
+ iunlock(q);
+ error(q->err);
+ }
+
+ /* if we get here, there's at least one block in the queue */
+ b = qremove(q);
+ n = BLEN(b);
+
+ /* split block if it's too big and this is not a message queue */
+ nb = b;
+ if(n > len){
+ if((q->state&Qmsg) == 0){
+ n -= len;
+ b = allocb(n);
+ memmove(b->wp, nb->rp+len, n);
+ b->wp += n;
+ qputback(q, b);
+ }
+ nb->wp = nb->rp + len;
+ }
+
+ /* restart producer */
+ qwakeup_iunlock(q);
+
+ poperror();
+ qunlock(&q->rlock);
+ return nb;
+}
+
+/*
+ * read a queue. if no data is queued, post a Block
+ * and wait on its Rendez.
+ */
+long
+qread(Queue *q, void *vp, int len)
+{
+ Block *b, *first, **l;
+ int m, n;
+
+ qlock(&q->rlock);
+ if(waserror()){
+ qunlock(&q->rlock);
+ nexterror();
+ }
+
+ ilock(q);
+again:
+ switch(qwait(q)){
+ case 0:
+ /* queue closed */
+ iunlock(q);
+ qunlock(&q->rlock);
+ poperror();
+ return 0;
+ case -1:
+ /* multiple reads on a closed queue */
+ iunlock(q);
+ error(q->err);
+ }
+
+ /* if we get here, there's at least one block in the queue */
+ if(q->state & Qcoalesce){
+ /* when coalescing, 0 length blocks just go away */
+ b = q->bfirst;
+ if(BLEN(b) <= 0){
+ freeb(qremove(q));
+ goto again;
+ }
+
+ /* grab the first block plus as many
+ * following blocks as will completely
+ * fit in the read.
+ */
+ n = 0;
+ l = &first;
+ m = BLEN(b);
+ for(;;) {
+ *l = qremove(q);
+ l = &b->next;
+ n += m;
+
+ b = q->bfirst;
+ if(b == nil)
+ break;
+ m = BLEN(b);
+ if(n+m > len)
+ break;
+ }
+ } else {
+ first = qremove(q);
+ n = BLEN(first);
+ }
+
+ /* copy to user space outside of the ilock */
+ iunlock(q);
+ b = bl2mem(vp, first, len);
+ ilock(q);
+
+ /* take care of any left over partial block */
+ if(b != nil){
+ n -= BLEN(b);
+ if(q->state & Qmsg)
+ freeb(b);
+ else
+ qputback(q, b);
+ }
+
+ /* restart producer */
+ qwakeup_iunlock(q);
+
+ poperror();
+ qunlock(&q->rlock);
+ return n;
+}
+
+static int
+qnotfull(void *a)
+{
+ Queue *q = a;
+
+ return q->len < q->limit || (q->state & Qclosed);
+}
+
+ulong noblockcnt;
+
+/*
+ * add a block to a queue obeying flow control
+ */
+long
+qbwrite(Queue *q, Block *b)
+{
+ int n, dowakeup;
+ Proc *p;
+
+ n = BLEN(b);
+
+ if(q->bypass){
+ (*q->bypass)(q->arg, b);
+ return n;
+ }
+
+ dowakeup = 0;
+ qlock(&q->wlock);
+ if(waserror()){
+ if(b != nil)
+ freeb(b);
+ qunlock(&q->wlock);
+ nexterror();
+ }
+
+ ilock(q);
+
+ /* give up if the queue is closed */
+ if(q->state & Qclosed){
+ iunlock(q);
+ error(q->err);
+ }
+
+ /* if nonblocking, don't queue over the limit */
+ if(q->len >= q->limit){
+ if(q->noblock){
+ iunlock(q);
+ freeb(b);
+ noblockcnt += n;
+ qunlock(&q->wlock);
+ poperror();
+ return n;
+ }
+ }
+
+ /* queue the block */
+ if(q->bfirst)
+ q->blast->next = b;
+ else
+ q->bfirst = b;
+ q->blast = b;
+ b->next = 0;
+ q->len += BALLOC(b);
+ q->dlen += n;
+ QDEBUG checkb(b, "qbwrite");
+ b = nil;
+
+ /* make sure other end gets awakened */
+ if(q->state & Qstarve){
+ q->state &= ~Qstarve;
+ dowakeup = 1;
+ }
+ iunlock(q);
+
+ /* get output going again */
+ if(q->kick && (dowakeup || (q->state&Qkick)))
+ q->kick(q->arg);
+
+ /* wakeup anyone consuming at the other end */
+ if(dowakeup){
+ p = wakeup(&q->rr);
+
+ /* if we just wokeup a higher priority process, let it run */
+ if(p != nil && p->priority > up->priority)
+ sched();
+ }
+
+ /*
+ * flow control, wait for queue to get below the limit
+ * before allowing the process to continue and queue
+ * more. We do this here so that postnote can only
+ * interrupt us after the data has been queued. This
+ * means that things like 9p flushes and ssl messages
+ * will not be disrupted by software interrupts.
+ *
+ * Note - this is moderately dangerous since a process
+ * that keeps getting interrupted and rewriting will
+ * queue infinite crud.
+ */
+ for(;;){
+ if(q->noblock || qnotfull(q))
+ break;
+
+ ilock(q);
+ q->state |= Qflow;
+ iunlock(q);
+ sleep(&q->wr, qnotfull, q);
+ }
+ USED(b);
+
+ qunlock(&q->wlock);
+ poperror();
+ return n;
+}
+
+/*
+ * write to a queue. only Maxatomic bytes at a time is atomic.
+ */
+int
+qwrite(Queue *q, void *vp, int len)
+{
+ int n, sofar;
+ Block *b;
+ uchar *p = vp;
+
+ QDEBUG if(!islo())
+ print("qwrite hi %#p\n", getcallerpc(&q));
+
+ sofar = 0;
+ do {
+ n = len-sofar;
+ if(n > Maxatomic)
+ n = Maxatomic;
+
+ b = allocb(n);
+ setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]);
+ if(waserror()){
+ freeb(b);
+ nexterror();
+ }
+ memmove(b->wp, p+sofar, n);
+ poperror();
+ b->wp += n;
+
+ qbwrite(q, b);
+
+ sofar += n;
+ } while(sofar < len && (q->state & Qmsg) == 0);
+
+ return len;
+}
+
+/*
+ * used by print() to write to a queue. Since we may be splhi or not in
+ * a process, don't qlock.
+ *
+ * this routine merges adjacent blocks if block n+1 will fit into
+ * the free space of block n.
+ */
+int
+qiwrite(Queue *q, void *vp, int len)
+{
+ int n, sofar, dowakeup;
+ Block *b;
+ uchar *p = vp;
+
+ dowakeup = 0;
+
+ sofar = 0;
+ do {
+ n = len-sofar;
+ if(n > Maxatomic)
+ n = Maxatomic;
+
+ b = iallocb(n);
+ if(b == nil)
+ break;
+ memmove(b->wp, p+sofar, n);
+ b->wp += n;
+
+ ilock(q);
+
+ /* we use an artificially high limit for kernel prints since anything
+ * over the limit gets dropped
+ */
+ if(q->dlen >= 16*1024){
+ iunlock(q);
+ freeb(b);
+ break;
+ }
+
+ QDEBUG checkb(b, "qiwrite");
+ if(q->bfirst)
+ q->blast->next = b;
+ else
+ q->bfirst = b;
+ q->blast = b;
+ q->len += BALLOC(b);
+ q->dlen += n;
+
+ if(q->state & Qstarve){
+ q->state &= ~Qstarve;
+ dowakeup = 1;
+ }
+
+ iunlock(q);
+
+ if(dowakeup){
+ if(q->kick)
+ q->kick(q->arg);
+ wakeup(&q->rr);
+ }
+
+ sofar += n;
+ } while(sofar < len && (q->state & Qmsg) == 0);
+
+ return sofar;
+}
+
+/*
+ * be extremely careful when calling this,
+ * as there is no reference accounting
+ */
+void
+qfree(Queue *q)
+{
+ qclose(q);
+ free(q);
+}
+
+/*
+ * Mark a queue as closed. No further IO is permitted.
+ * All blocks are released.
+ */
+void
+qclose(Queue *q)
+{
+ Block *bfirst;
+
+ if(q == nil)
+ return;
+
+ /* mark it */
+ ilock(q);
+ q->state |= Qclosed;
+ q->state &= ~(Qflow|Qstarve);
+ strcpy(q->err, Ehungup);
+ bfirst = q->bfirst;
+ q->bfirst = 0;
+ q->len = 0;
+ q->dlen = 0;
+ q->noblock = 0;
+ iunlock(q);
+
+ /* free queued blocks */
+ freeblist(bfirst);
+
+ /* wake up readers/writers */
+ wakeup(&q->rr);
+ wakeup(&q->wr);
+}
+
+/*
+ * Mark a queue as closed. Wakeup any readers. Don't remove queued
+ * blocks.
+ */
+void
+qhangup(Queue *q, char *msg)
+{
+ /* mark it */
+ ilock(q);
+ q->state |= Qclosed;
+ if(msg == 0 || *msg == 0)
+ strcpy(q->err, Ehungup);
+ else
+ strncpy(q->err, msg, ERRMAX-1);
+ iunlock(q);
+
+ /* wake up readers/writers */
+ wakeup(&q->rr);
+ wakeup(&q->wr);
+}
+
+/*
+ * return non-zero if the q is hungup
+ */
+int
+qisclosed(Queue *q)
+{
+ return q->state & Qclosed;
+}
+
+/*
+ * mark a queue as no longer hung up
+ */
+void
+qreopen(Queue *q)
+{
+ ilock(q);
+ q->state &= ~Qclosed;
+ q->state |= Qstarve;
+ q->eof = 0;
+ q->limit = q->inilim;
+ iunlock(q);
+}
+
+/*
+ * return bytes queued
+ */
+int
+qlen(Queue *q)
+{
+ return q->dlen;
+}
+
+/*
+ * return space remaining before flow control
+ */
+int
+qwindow(Queue *q)
+{
+ int l;
+
+ l = q->limit - q->len;
+ if(l < 0)
+ l = 0;
+ return l;
+}
+
+/*
+ * return true if we can read without blocking
+ */
+int
+qcanread(Queue *q)
+{
+ return q->bfirst!=0;
+}
+
+/*
+ * change queue limit
+ */
+void
+qsetlimit(Queue *q, int limit)
+{
+ q->limit = limit;
+}
+
+/*
+ * set blocking/nonblocking
+ */
+void
+qnoblock(Queue *q, int onoff)
+{
+ q->noblock = onoff;
+}
+
+/*
+ * flush the output queue
+ */
+void
+qflush(Queue *q)
+{
+ Block *bfirst;
+
+ /* mark it */
+ ilock(q);
+ bfirst = q->bfirst;
+ q->bfirst = 0;
+ q->len = 0;
+ q->dlen = 0;
+ iunlock(q);
+
+ /* free queued blocks */
+ freeblist(bfirst);
+
+ /* wake up readers/writers */
+ wakeup(&q->wr);
+}
+
+int
+qfull(Queue *q)
+{
+ return q->state & Qflow;
+}
+
+int
+qstate(Queue *q)
+{
+ return q->state;
+}
diff --git a/sys/src/9/port/qlock.c b/sys/src/9/port/qlock.c
new file mode 100755
index 000000000..3d666516d
--- /dev/null
+++ b/sys/src/9/port/qlock.c
@@ -0,0 +1,223 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+struct {
+ ulong rlock;
+ ulong rlockq;
+ ulong wlock;
+ ulong wlockq;
+ ulong qlock;
+ ulong qlockq;
+} rwstats;
+
+void
+qlock(QLock *q)
+{
+ Proc *p;
+
+ if(m->ilockdepth != 0)
+ print("qlock: %#p: ilockdepth %d\n", getcallerpc(&q), m->ilockdepth);
+ if(up != nil && up->nlocks.ref)
+ print("qlock: %#p: nlocks %lud\n", getcallerpc(&q), up->nlocks.ref);
+
+ if(q->use.key == 0x55555555)
+ panic("qlock: q %#p, key 5*\n", q);
+ lock(&q->use);
+ rwstats.qlock++;
+ if(!q->locked) {
+ q->locked = 1;
+ unlock(&q->use);
+ return;
+ }
+ if(up == 0)
+ panic("qlock");
+ rwstats.qlockq++;
+ p = q->tail;
+ if(p == 0)
+ q->head = up;
+ else
+ p->qnext = up;
+ q->tail = up;
+ up->qnext = 0;
+ up->state = Queueing;
+ up->qpc = getcallerpc(&q);
+ unlock(&q->use);
+ sched();
+}
+
+int
+canqlock(QLock *q)
+{
+ if(!canlock(&q->use))
+ return 0;
+ if(q->locked){
+ unlock(&q->use);
+ return 0;
+ }
+ q->locked = 1;
+ unlock(&q->use);
+ return 1;
+}
+
+void
+qunlock(QLock *q)
+{
+ Proc *p;
+
+ lock(&q->use);
+ if (q->locked == 0)
+ print("qunlock called with qlock not held, from %#p\n",
+ getcallerpc(&q));
+ p = q->head;
+ if(p){
+ q->head = p->qnext;
+ if(q->head == 0)
+ q->tail = 0;
+ unlock(&q->use);
+ ready(p);
+ return;
+ }
+ q->locked = 0;
+ unlock(&q->use);
+}
+
+void
+rlock(RWlock *q)
+{
+ Proc *p;
+
+ lock(&q->use);
+ rwstats.rlock++;
+ if(q->writer == 0 && q->head == nil){
+ /* no writer, go for it */
+ q->readers++;
+ unlock(&q->use);
+ return;
+ }
+
+ rwstats.rlockq++;
+ p = q->tail;
+ if(up == nil)
+ panic("rlock");
+ if(p == 0)
+ q->head = up;
+ else
+ p->qnext = up;
+ q->tail = up;
+ up->qnext = 0;
+ up->state = QueueingR;
+ unlock(&q->use);
+ sched();
+}
+
+void
+runlock(RWlock *q)
+{
+ Proc *p;
+
+ lock(&q->use);
+ p = q->head;
+ if(--(q->readers) > 0 || p == nil){
+ unlock(&q->use);
+ return;
+ }
+
+ /* start waiting writer */
+ if(p->state != QueueingW)
+ panic("runlock");
+ q->head = p->qnext;
+ if(q->head == 0)
+ q->tail = 0;
+ q->writer = 1;
+ unlock(&q->use);
+ ready(p);
+}
+
+void
+wlock(RWlock *q)
+{
+ Proc *p;
+
+ lock(&q->use);
+ rwstats.wlock++;
+ if(q->readers == 0 && q->writer == 0){
+ /* noone waiting, go for it */
+ q->wpc = getcallerpc(&q);
+ q->wproc = up;
+ q->writer = 1;
+ unlock(&q->use);
+ return;
+ }
+
+ /* wait */
+ rwstats.wlockq++;
+ p = q->tail;
+ if(up == nil)
+ panic("wlock");
+ if(p == nil)
+ q->head = up;
+ else
+ p->qnext = up;
+ q->tail = up;
+ up->qnext = 0;
+ up->state = QueueingW;
+ unlock(&q->use);
+ sched();
+}
+
+void
+wunlock(RWlock *q)
+{
+ Proc *p;
+
+ lock(&q->use);
+ p = q->head;
+ if(p == nil){
+ q->writer = 0;
+ unlock(&q->use);
+ return;
+ }
+ if(p->state == QueueingW){
+ /* start waiting writer */
+ q->head = p->qnext;
+ if(q->head == nil)
+ q->tail = nil;
+ unlock(&q->use);
+ ready(p);
+ return;
+ }
+
+ if(p->state != QueueingR)
+ panic("wunlock");
+
+ /* waken waiting readers */
+ while(q->head != nil && q->head->state == QueueingR){
+ p = q->head;
+ q->head = p->qnext;
+ q->readers++;
+ ready(p);
+ }
+ if(q->head == nil)
+ q->tail = nil;
+ q->writer = 0;
+ unlock(&q->use);
+}
+
+/* same as rlock but punts if there are any writers waiting */
+int
+canrlock(RWlock *q)
+{
+ lock(&q->use);
+ rwstats.rlock++;
+ if(q->writer == 0 && q->head == nil){
+ /* no writer, go for it */
+ q->readers++;
+ unlock(&q->use);
+ return 1;
+ }
+ unlock(&q->use);
+ return 0;
+}
diff --git a/sys/src/9/port/rdb.c b/sys/src/9/port/rdb.c
new file mode 100755
index 000000000..12977da26
--- /dev/null
+++ b/sys/src/9/port/rdb.c
@@ -0,0 +1,109 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+#define DBG if(0)scrprint
+#pragma varargck argpos scrprint 1
+static Ureg ureg;
+
+static void
+scrprint(char *fmt, ...)
+{
+ char buf[128];
+ va_list va;
+ int n;
+
+ va_start(va, fmt);
+ n = vseprint(buf, buf+sizeof buf, fmt, va)-buf;
+ va_end(va);
+ putstrn(buf, n);
+}
+
+static char*
+getline(void)
+{
+ static char buf[128];
+ int i, c;
+
+ for(;;){
+ for(i=0; i<nelem(buf) && (c=uartgetc()) != '\n'; i++){
+ DBG("%c...", c);
+ buf[i] = c;
+ }
+
+ if(i < nelem(buf)){
+ buf[i] = 0;
+ return buf;
+ }
+ }
+}
+
+static void*
+addr(char *s, Ureg *ureg, char **p)
+{
+ ulong a;
+
+ a = strtoul(s, p, 16);
+ if(a < sizeof(Ureg))
+ return ((uchar*)ureg)+a;
+ return (void*)a;
+}
+
+static void
+talkrdb(Ureg *ureg)
+{
+ uchar *a;
+ char *p, *req;
+
+ serialoq = nil; /* turn off serial console */
+ kprintoq = nil; /* turn off /dev/kprint if active */
+// scrprint("Plan 9 debugger\n");
+ iprint("Edebugger reset\n");
+ for(;;){
+ req = getline();
+ switch(*req){
+ case 'r':
+ a = addr(req+1, ureg, nil);
+ DBG("read %p\n", a);
+ iprint("R%.8lux %.2ux %.2ux %.2ux %.2ux\n",
+ strtoul(req+1, 0, 16), a[0], a[1], a[2], a[3]);
+ break;
+
+ case 'w':
+ a = addr(req+1, ureg, &p);
+ *(ulong*)a = strtoul(p, nil, 16);
+ iprint("W\n");
+ break;
+/*
+ * case Tmput:
+ n = min[4];
+ if(n > 4){
+ mesg(Rerr, Ecount);
+ break;
+ }
+ a = addr(min+0);
+ scrprint("mput %.8lux\n", a);
+ memmove(a, min+5, n);
+ mesg(Rmput, mout);
+ break;
+ *
+ */
+ default:
+ DBG("unknown %c\n", *req);
+ iprint("Eunknown message\n");
+ break;
+ }
+ }
+}
+
+void
+rdb(void)
+{
+ splhi();
+ iprint("rdb...");
+ callwithureg(talkrdb);
+}
diff --git a/sys/src/9/port/rebootcmd.c b/sys/src/9/port/rebootcmd.c
new file mode 100755
index 000000000..591864903
--- /dev/null
+++ b/sys/src/9/port/rebootcmd.c
@@ -0,0 +1,100 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "a.out.h"
+
+static ulong
+l2be(long l)
+{
+ uchar *cp;
+
+ cp = (uchar*)&l;
+ return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
+}
+
+
+static void
+readn(Chan *c, void *vp, long n)
+{
+ char *p = vp;
+ long nn;
+
+ while(n > 0) {
+ nn = devtab[c->type]->read(c, p, n, c->offset);
+ if(nn == 0)
+ error(Eshort);
+ c->offset += nn;
+ p += nn;
+ n -= nn;
+ }
+}
+
+static void
+setbootcmd(int argc, char *argv[])
+{
+ char *buf, *p, *ep;
+ int i;
+
+ buf = malloc(1024);
+ if(buf == nil)
+ error(Enomem);
+ p = buf;
+ ep = buf + 1024;
+ for(i=0; i<argc; i++)
+ p = seprint(p, ep, "%q ", argv[i]);
+ *p = 0;
+ ksetenv("bootcmd", buf, 1);
+ free(buf);
+}
+
+void
+rebootcmd(int argc, char *argv[])
+{
+ Chan *c;
+ Exec exec;
+ ulong magic, text, rtext, entry, data, size;
+ uchar *p;
+
+ if(argc == 0)
+ exit(0);
+
+ c = namec(argv[0], Aopen, OEXEC, 0);
+ if(waserror()){
+ cclose(c);
+ nexterror();
+ }
+
+ readn(c, &exec, sizeof(Exec));
+ magic = l2be(exec.magic);
+ entry = l2be(exec.entry);
+ text = l2be(exec.text);
+ data = l2be(exec.data);
+ if(magic != AOUT_MAGIC)
+ error(Ebadexec);
+
+ /* round text out to page boundary */
+ rtext = PGROUND(entry+text)-entry;
+ size = rtext + data;
+ p = malloc(size);
+ if(p == nil)
+ error(Enomem);
+
+ if(waserror()){
+ free(p);
+ nexterror();
+ }
+
+ memset(p, 0, size);
+ readn(c, p, text);
+ readn(c, p + rtext, data);
+
+ ksetenv("bootfile", argv[0], 1);
+ setbootcmd(argc-1, argv+1);
+
+ reboot((void*)entry, p, size);
+
+ panic("return from reboot!");
+}
diff --git a/sys/src/9/port/sd.h b/sys/src/9/port/sd.h
new file mode 100755
index 000000000..13e16a5b5
--- /dev/null
+++ b/sys/src/9/port/sd.h
@@ -0,0 +1,137 @@
+/*
+ * Storage Device.
+ */
+typedef struct SDev SDev;
+typedef struct SDifc SDifc;
+typedef struct SDpart SDpart;
+typedef struct SDperm SDperm;
+typedef struct SDreq SDreq;
+typedef struct SDunit SDunit;
+
+struct SDperm {
+ char* name;
+ char* user;
+ ulong perm;
+};
+
+struct SDpart {
+ uvlong start;
+ uvlong end;
+ SDperm;
+ int valid;
+ ulong vers;
+};
+
+struct SDunit {
+ SDev* dev;
+ int subno;
+ uchar inquiry[255]; /* format follows SCSI spec */
+ uchar sense[18]; /* format follows SCSI spec */
+ SDperm;
+
+ QLock ctl;
+ uvlong sectors;
+ ulong secsize;
+ SDpart* part; /* nil or array of size npart */
+ int npart;
+ ulong vers;
+ SDperm ctlperm;
+
+ QLock raw; /* raw read or write in progress */
+ ulong rawinuse; /* really just a test-and-set */
+ int state;
+ SDreq* req;
+ SDperm rawperm;
+};
+
+/*
+ * Each controller is represented by a SDev.
+ */
+struct SDev {
+ Ref r; /* Number of callers using device */
+ SDifc* ifc; /* pnp/legacy */
+ void* ctlr;
+ int idno;
+ char name[8];
+ SDev* next;
+
+ QLock; /* enable/disable */
+ int enabled;
+ int nunit; /* Number of units */
+ QLock unitlock; /* `Loading' of units */
+ int* unitflg; /* Unit flags */
+ SDunit**unit;
+};
+
+struct SDifc {
+ char* name;
+
+ SDev* (*pnp)(void);
+ SDev* (*legacy)(int, int);
+ int (*enable)(SDev*);
+ int (*disable)(SDev*);
+
+ int (*verify)(SDunit*);
+ int (*online)(SDunit*);
+ int (*rio)(SDreq*);
+ int (*rctl)(SDunit*, char*, int);
+ int (*wctl)(SDunit*, Cmdbuf*);
+
+ long (*bio)(SDunit*, int, int, void*, long, uvlong);
+ SDev* (*probe)(DevConf*);
+ void (*clear)(SDev*);
+ char* (*rtopctl)(SDev*, char*, char*);
+ int (*wtopctl)(SDev*, Cmdbuf*);
+};
+
+struct SDreq {
+ SDunit* unit;
+ int lun;
+ int write;
+ uchar cmd[16];
+ int clen;
+ void* data;
+ int dlen;
+
+ int flags;
+
+ int status;
+ long rlen;
+ uchar sense[256];
+};
+
+enum {
+ SDnosense = 0x00000001,
+ SDvalidsense = 0x00010000,
+};
+
+enum {
+ SDretry = -5, /* internal to controllers */
+ SDmalloc = -4,
+ SDeio = -3,
+ SDtimeout = -2,
+ SDnostatus = -1,
+
+ SDok = 0,
+
+ SDcheck = 0x02, /* check condition */
+ SDbusy = 0x08, /* busy */
+
+ SDmaxio = 2048*1024,
+ SDnpart = 16,
+};
+
+#define sdmalloc(n) malloc(n)
+#define sdfree(p) free(p)
+
+/* devsd.c */
+extern void sdadddevs(SDev*);
+extern int sdsetsense(SDreq*, int, int, int, int);
+extern int sdmodesense(SDreq*, uchar*, void*, int);
+extern int sdfakescsi(SDreq*, void*, int);
+
+/* sdscsi.c */
+extern int scsiverify(SDunit*);
+extern int scsionline(SDunit*);
+extern long scsibio(SDunit*, int, int, void*, long, uvlong);
+extern SDev* scsiid(SDev*, SDifc*);
diff --git a/sys/src/9/port/sdaoe.c b/sys/src/9/port/sdaoe.c
new file mode 100755
index 000000000..633b7020f
--- /dev/null
+++ b/sys/src/9/port/sdaoe.c
@@ -0,0 +1,625 @@
+/*
+ * aoe sd driver, copyright © 2007 coraid
+ */
+
+#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"
+#include "../port/netif.h"
+#include "../port/aoe.h"
+
+extern char Echange[];
+extern char Enotup[];
+
+#define uprint(...) snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__);
+
+enum {
+ Nctlr = 32,
+ Maxpath = 128,
+
+ Probeintvl = 100, /* ms. between probes */
+ Probemax = 20, /* max probes */
+};
+
+enum {
+ /* sync with ahci.h */
+ Dllba = 1<<0,
+ Dsmart = 1<<1,
+ Dpower = 1<<2,
+ Dnop = 1<<3,
+ Datapi = 1<<4,
+ Datapi16= 1<<5,
+};
+
+static char *flagname[] = {
+ "llba",
+ "smart",
+ "power",
+ "nop",
+ "atapi",
+ "atapi16",
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr{
+ QLock;
+
+ Ctlr *next;
+ SDunit *unit;
+
+ char path[Maxpath];
+ Chan *c;
+
+ ulong vers;
+ uchar mediachange;
+ uchar flag;
+ uchar smart;
+ uchar smartrs;
+ uchar feat;
+
+ uvlong sectors;
+ char serial[20+1];
+ char firmware[8+1];
+ char model[40+1];
+ char ident[0x100];
+};
+
+void aoeidmove(char *p, ushort *a, unsigned n);
+
+static Lock ctlrlock;
+static Ctlr *head;
+static Ctlr *tail;
+
+SDifc sdaoeifc;
+
+static ushort
+gbit16(void *a)
+{
+ uchar *i;
+
+ i = a;
+ return i[1] << 8 | i[0];
+}
+
+static ulong
+gbit32(void *a)
+{
+ ulong j;
+ uchar *i;
+
+ i = a;
+ j = i[3] << 24;
+ j |= i[2] << 16;
+ j |= i[1] << 8;
+ j |= i[0];
+ return j;
+}
+
+static uvlong
+gbit64(void *a)
+{
+ uchar *i;
+
+ i = a;
+ return (uvlong)gbit32(i+4)<<32 | gbit32(i);
+}
+
+static int
+identify(Ctlr *c, ushort *id)
+{
+ int i;
+ uchar oserial[21];
+ uvlong osectors, s;
+
+ osectors = c->sectors;
+ memmove(oserial, c->serial, sizeof c->serial);
+
+ c->feat &= ~(Dllba|Dpower|Dsmart|Dnop);
+ i = gbit16(id+83) | gbit16(id+86);
+ if(i & (1<<10)){
+ c->feat |= Dllba;
+ s = gbit64(id+100);
+ }else
+ s = gbit32(id+60);
+
+ i = gbit16(id+83);
+ if((i>>14) == 1) {
+ if(i & (1<<3))
+ c->feat |= Dpower;
+ i = gbit16(id+82);
+ if(i & 1)
+ c->feat |= Dsmart;
+ if(i & (1<<14))
+ c->feat |= Dnop;
+ }
+
+ aoeidmove(c->serial, id+10, 20);
+ aoeidmove(c->firmware, id+23, 8);
+ aoeidmove(c->model, id+27, 40);
+
+ if((osectors == 0 || osectors != s) &&
+ memcmp(oserial, c->serial, sizeof oserial) != 0){
+ c->sectors = s;
+ c->mediachange = 1;
+ c->vers++;
+ }
+ return 0;
+}
+
+/* must call with d qlocked */
+static int
+aoeidentify(Ctlr *d, SDunit *u)
+{
+ Chan *c;
+
+ c = nil;
+ if(waserror()){
+ if(c)
+ cclose(c);
+ iprint("aoeidentify: %s\n", up->errstr);
+ nexterror();
+ }
+
+ uprint("%s/ident", d->path);
+ c = namec(up->genbuf, Aopen, OREAD, 0);
+ devtab[c->type]->read(c, d->ident, sizeof d->ident, 0);
+
+ poperror();
+ cclose(c);
+
+ d->feat = 0;
+ d->smart = 0;
+ identify(d, (ushort*)d->ident);
+
+ memset(u->inquiry, 0, sizeof u->inquiry);
+ u->inquiry[2] = 2;
+ u->inquiry[3] = 2;
+ u->inquiry[4] = sizeof u->inquiry - 4;
+ memmove(u->inquiry+8, d->model, 40);
+
+ return 0;
+}
+
+static Ctlr*
+ctlrlookup(char *path)
+{
+ Ctlr *c;
+
+ lock(&ctlrlock);
+ for(c = head; c; c = c->next)
+ if(strcmp(c->path, path) == 0)
+ break;
+ unlock(&ctlrlock);
+ return c;
+}
+
+static Ctlr*
+newctlr(char *path)
+{
+ Ctlr *c;
+
+ /* race? */
+ if(ctlrlookup(path))
+ error(Eexist);
+
+ if((c = malloc(sizeof *c)) == nil)
+ return 0;
+ kstrcpy(c->path, path, sizeof c->path);
+ lock(&ctlrlock);
+ if(head != nil)
+ tail->next = c;
+ else
+ head = c;
+ tail = c;
+ unlock(&ctlrlock);
+ return c;
+}
+
+static void
+delctlr(Ctlr *c)
+{
+ Ctlr *x, *prev;
+
+ lock(&ctlrlock);
+
+ for(prev = 0, x = head; x; prev = x, x = c->next)
+ if(strcmp(c->path, x->path) == 0)
+ break;
+ if(x == 0){
+ unlock(&ctlrlock);
+ error(Enonexist);
+ }
+
+ if(prev)
+ prev->next = x->next;
+ else
+ head = x->next;
+ if(x->next == nil)
+ tail = prev;
+ unlock(&ctlrlock);
+
+ if(x->c)
+ cclose(x->c);
+ free(x);
+}
+
+/* don't call aoeprobe from within a loop; it loops internally retrying open. */
+static SDev*
+aoeprobe(char *path, SDev *s)
+{
+ int n, i;
+ char *p;
+ Chan *c;
+ Ctlr *ctlr;
+
+ if((p = strrchr(path, '/')) == 0)
+ error(Ebadarg);
+ *p = 0;
+ uprint("%s/ctl", path);
+ *p = '/';
+
+ c = namec(up->genbuf, Aopen, OWRITE, 0);
+ if(waserror()) {
+ cclose(c);
+ nexterror();
+ }
+ n = uprint("discover %s", p+1);
+ devtab[c->type]->write(c, up->genbuf, n, 0);
+ poperror();
+ cclose(c);
+
+ for(i = 0; i < Probemax; i++){
+ tsleep(&up->sleep, return0, 0, Probeintvl);
+ uprint("%s/ident", path);
+ if(!waserror()) {
+ c = namec(up->genbuf, Aopen, OREAD, 0);
+ poperror();
+ cclose(c);
+ break;
+ }
+ }
+ if(i >= Probemax)
+ error(Etimedout);
+ uprint("%s/ident", path);
+ ctlr = newctlr(path);
+ if(ctlr == nil || s == nil && (s = malloc(sizeof *s)) == nil)
+ return nil;
+ s->ctlr = ctlr;
+ s->ifc = &sdaoeifc;
+ s->nunit = 1;
+ return s;
+}
+
+static char *probef[32];
+static int nprobe;
+
+static int
+pnpprobeid(char *s)
+{
+ if(strlen(s) < 2)
+ return 0;
+ return s[1] == '!'? s[0]: 'e';
+}
+
+static SDev*
+aoepnp(void)
+{
+ int i, id;
+ char *p;
+ SDev *h, *t, *s;
+
+ if((p = getconf("aoedev")) == 0)
+ return 0;
+ nprobe = tokenize(p, probef, nelem(probef));
+ h = t = 0;
+ for(i = 0; i < nprobe; i++){
+ id = pnpprobeid(probef[i]);
+ if(id == 0)
+ continue;
+ s = malloc(sizeof *s);
+ if(s == nil)
+ break;
+ s->ctlr = 0;
+ s->idno = id;
+ s->ifc = &sdaoeifc;
+ s->nunit = 1;
+
+ if(h)
+ t->next = s;
+ else
+ h = s;
+ t = s;
+ }
+ return h;
+}
+
+static Ctlr*
+pnpprobe(SDev *sd)
+{
+ ulong start;
+ char *p;
+ static int i;
+
+ if(i > nprobe)
+ return 0;
+ p = probef[i++];
+ if(strlen(p) < 2)
+ return 0;
+ if(p[1] == '!')
+ p += 2;
+
+ start = TK2MS(MACHP(0)->ticks);
+ if(waserror()){
+ print("#æ: pnpprobe failed in %lud ms: %s: %s\n",
+ TK2MS(MACHP(0)->ticks) - start, probef[i-1],
+ up->errstr);
+ return nil;
+ }
+ sd = aoeprobe(p, sd); /* does a round of probing */
+ poperror();
+ print("#æ: pnpprobe established %s in %lud ms\n",
+ probef[i-1], TK2MS(MACHP(0)->ticks) - start);
+ return sd->ctlr;
+}
+
+
+static int
+aoeverify(SDunit *u)
+{
+ SDev *s;
+ Ctlr *c;
+
+ s = u->dev;
+ c = s->ctlr;
+ if(c == nil && (s->ctlr = c = pnpprobe(s)) == nil)
+ return 0;
+ c->mediachange = 1;
+ return 1;
+}
+
+static int
+aoeconnect(SDunit *u, Ctlr *c)
+{
+ qlock(c);
+ if(waserror()){
+ qunlock(c);
+ return -1;
+ }
+
+ aoeidentify(u->dev->ctlr, u);
+ if(c->c)
+ cclose(c->c);
+ c->c = 0;
+ uprint("%s/data", c->path);
+ c->c = namec(up->genbuf, Aopen, ORDWR, 0);
+ qunlock(c);
+ poperror();
+
+ return 0;
+}
+
+static int
+aoeonline(SDunit *u)
+{
+ Ctlr *c;
+ int r;
+
+ c = u->dev->ctlr;
+ r = 0;
+
+ if((c->feat&Datapi) && c->mediachange){
+ if(aoeconnect(u, c) == 0 && (r = scsionline(u)) > 0)
+ c->mediachange = 0;
+ return r;
+ }
+
+ if(c->mediachange){
+ if(aoeconnect(u, c) == -1)
+ return 0;
+ r = 2;
+ c->mediachange = 0;
+ u->sectors = c->sectors;
+ u->secsize = Aoesectsz;
+ } else
+ r = 1;
+
+ return r;
+}
+
+static int
+aoerio(SDreq *r)
+{
+ int i, count;
+ uvlong lba;
+ char *name;
+ uchar *cmd;
+ long (*rio)(Chan*, void*, long, vlong);
+ Ctlr *c;
+ SDunit *unit;
+
+ unit = r->unit;
+ c = unit->dev->ctlr;
+// if(c->feat & Datapi)
+// return aoeriopkt(r, d);
+
+ cmd = r->cmd;
+ name = unit->name;
+
+ if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91){
+// qlock(c);
+// i = flushcache();
+// qunlock(c);
+// if(i == 0)
+// return sdsetsense(r, SDok, 0, 0, 0);
+ return sdsetsense(r, SDcheck, 3, 0xc, 2);
+ }
+
+ if((i = sdfakescsi(r, c->ident, sizeof c->ident)) != SDnostatus){
+ r->status = i;
+ return i;
+ }
+
+ switch(*cmd){
+ case 0x88:
+ case 0x28:
+ rio = devtab[c->c->type]->read;
+ break;
+ case 0x8a:
+ case 0x2a:
+ rio = devtab[c->c->type]->write;
+ break;
+ default:
+ print("%s: bad cmd %#.2ux\n", name, cmd[0]);
+ r->status = SDcheck;
+ return SDcheck;
+ }
+
+ if(r->data == nil)
+ return SDok;
+
+ if(r->clen == 16){
+ if(cmd[2] || cmd[3])
+ return sdsetsense(r, SDcheck, 3, 0xc, 2);
+ lba = (uvlong)cmd[4]<<40 | (uvlong)cmd[5]<<32;
+ lba |= cmd[6]<<24 | cmd[7]<<16 | cmd[8]<<8 | cmd[9];
+ count = cmd[10]<<24 | cmd[11]<<16 | cmd[12]<<8 | cmd[13];
+ }else{
+ lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5];
+ count = cmd[7]<<8 | cmd[8];
+ }
+
+ count *= Aoesectsz;
+
+ if(r->dlen < count)
+ count = r->dlen & ~0x1ff;
+
+ if(waserror()){
+ if(strcmp(up->errstr, Echange) == 0 ||
+ strcmp(up->errstr, Enotup) == 0)
+ unit->sectors = 0;
+ nexterror();
+ }
+ r->rlen = rio(c->c, r->data, count, Aoesectsz * lba);
+ poperror();
+ r->status = SDok;
+ return SDok;
+}
+
+static char *smarttab[] = {
+ "unset",
+ "error",
+ "threshold exceeded",
+ "normal"
+};
+
+static char *
+pflag(char *s, char *e, uchar f)
+{
+ uchar i, m;
+
+ for(i = 0; i < 8; i++){
+ m = 1 << i;
+ if(f & m)
+ s = seprint(s, e, "%s ", flagname[i]);
+ }
+ return seprint(s, e, "\n");
+}
+
+static int
+aoerctl(SDunit *u, char *p, int l)
+{
+ Ctlr *c;
+ char *e, *op;
+
+ if((c = u->dev->ctlr) == nil)
+ return 0;
+ e = p+l;
+ op = p;
+
+ p = seprint(p, e, "model\t%s\n", c->model);
+ p = seprint(p, e, "serial\t%s\n", c->serial);
+ p = seprint(p, e, "firm %s\n", c->firmware);
+ if(c->smartrs == 0xff)
+ p = seprint(p, e, "smart\tenable error\n");
+ else if(c->smartrs == 0)
+ p = seprint(p, e, "smart\tdisabled\n");
+ else
+ p = seprint(p, e, "smart\t%s\n", smarttab[c->smart]);
+ p = seprint(p, e, "flag ");
+ p = pflag(p, e, c->feat);
+ p = seprint(p, e, "geometry %llud %d\n", c->sectors, Aoesectsz);
+ return p-op;
+}
+
+static int
+aoewctl(SDunit *, Cmdbuf *cmd)
+{
+ cmderror(cmd, Ebadarg);
+ return 0;
+}
+
+static SDev*
+aoeprobew(DevConf *c)
+{
+ char *p;
+
+ p = strchr(c->type, '/');
+ if(p == nil || strlen(p) > Maxpath - 11)
+ error(Ebadarg);
+ if(p[1] == '#')
+ p++; /* hack */
+ if(ctlrlookup(p))
+ error(Einuse);
+ return aoeprobe(p, 0);
+}
+
+static void
+aoeclear(SDev *s)
+{
+ delctlr((Ctlr *)s->ctlr);
+}
+
+static char*
+aoertopctl(SDev *s, char *p, char *e)
+{
+ Ctlr *c;
+
+ c = s->ctlr;
+ return seprint(p, e, "%s aoe %s\n", s->name, c->path);
+}
+
+static int
+aoewtopctl(SDev *, Cmdbuf *cmd)
+{
+ switch(cmd->nf){
+ default:
+ cmderror(cmd, Ebadarg);
+ }
+ return 0;
+}
+
+SDifc sdaoeifc = {
+ "aoe",
+
+ aoepnp,
+ nil, /* legacy */
+ nil, /* enable */
+ nil, /* disable */
+
+ aoeverify,
+ aoeonline,
+ aoerio,
+ aoerctl,
+ aoewctl,
+
+ scsibio,
+ aoeprobew, /* probe */
+ aoeclear, /* clear */
+ aoertopctl,
+ aoewtopctl,
+};
diff --git a/sys/src/9/port/sdscsi.c b/sys/src/9/port/sdscsi.c
new file mode 100755
index 000000000..fe182caac
--- /dev/null
+++ b/sys/src/9/port/sdscsi.c
@@ -0,0 +1,424 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+#include "../port/sd.h"
+
+static int
+scsitest(SDreq* r)
+{
+ r->write = 0;
+ memset(r->cmd, 0, sizeof(r->cmd));
+ r->cmd[1] = r->lun<<5;
+ r->clen = 6;
+ r->data = nil;
+ r->dlen = 0;
+ r->flags = 0;
+
+ r->status = ~0;
+
+ return r->unit->dev->ifc->rio(r);
+}
+
+int
+scsiverify(SDunit* unit)
+{
+ SDreq *r;
+ int i, status;
+ uchar *inquiry;
+
+ if((r = malloc(sizeof(SDreq))) == nil)
+ return 0;
+ if((inquiry = sdmalloc(sizeof(unit->inquiry))) == nil){
+ free(r);
+ return 0;
+ }
+ r->unit = unit;
+ r->lun = 0; /* ??? */
+
+ memset(unit->inquiry, 0, sizeof(unit->inquiry));
+ r->write = 0;
+ r->cmd[0] = 0x12;
+ r->cmd[1] = r->lun<<5;
+ r->cmd[4] = sizeof(unit->inquiry)-1;
+ r->clen = 6;
+ r->data = inquiry;
+ r->dlen = sizeof(unit->inquiry)-1;
+ r->flags = 0;
+
+ r->status = ~0;
+ if(unit->dev->ifc->rio(r) != SDok){
+ free(r);
+ return 0;
+ }
+ memmove(unit->inquiry, inquiry, r->dlen);
+ free(inquiry);
+
+ SET(status);
+ for(i = 0; i < 3; i++){
+ while((status = scsitest(r)) == SDbusy)
+ ;
+ if(status == SDok || status != SDcheck)
+ break;
+ if(!(r->flags & SDvalidsense))
+ break;
+ if((r->sense[2] & 0x0F) != 0x02)
+ continue;
+
+ /*
+ * Unit is 'not ready'.
+ * If it is in the process of becoming ready or needs
+ * an initialising command, set status so it will be spun-up
+ * below.
+ * If there's no medium, that's OK too, but don't
+ * try to spin it up.
+ */
+ if(r->sense[12] == 0x04){
+ if(r->sense[13] == 0x02 || r->sense[13] == 0x01){
+ status = SDok;
+ break;
+ }
+ }
+ if(r->sense[12] == 0x3A)
+ break;
+ }
+
+ if(status == SDok){
+ /*
+ * Try to ensure a direct-access device is spinning.
+ * Don't wait for completion, ignore the result.
+ */
+ if((unit->inquiry[0] & 0x1F) == 0){
+ memset(r->cmd, 0, sizeof(r->cmd));
+ r->write = 0;
+ r->cmd[0] = 0x1B;
+ r->cmd[1] = (r->lun<<5)|0x01;
+ r->cmd[4] = 1;
+ r->clen = 6;
+ r->data = nil;
+ r->dlen = 0;
+ r->flags = 0;
+
+ r->status = ~0;
+ unit->dev->ifc->rio(r);
+ }
+ }
+ free(r);
+
+ if(status == SDok || status == SDcheck)
+ return 1;
+ return 0;
+}
+
+static int
+scsirio(SDreq* r)
+{
+ /*
+ * Perform an I/O request, returning
+ * -1 failure
+ * 0 ok
+ * 1 no medium present
+ * 2 retry
+ * The contents of r may be altered so the
+ * caller should re-initialise if necesary.
+ */
+ r->status = ~0;
+ switch(r->unit->dev->ifc->rio(r)){
+ default:
+ break;
+ case SDcheck:
+ if(!(r->flags & SDvalidsense))
+ break;
+ switch(r->sense[2] & 0x0F){
+ case 0x00: /* no sense */
+ case 0x01: /* recovered error */
+ return 2;
+ case 0x06: /* check condition */
+ /*
+ * 0x28 - not ready to ready transition,
+ * medium may have changed.
+ * 0x29 - power on or some type of reset.
+ */
+ if(r->sense[12] == 0x28 && r->sense[13] == 0)
+ return 2;
+ if(r->sense[12] == 0x29)
+ return 2;
+ break;
+ case 0x02: /* not ready */
+ /*
+ * If no medium present, bail out.
+ * If unit is becoming ready, rather than not
+ * not ready, wait a little then poke it again. */
+ if(r->sense[12] == 0x3A)
+ break;
+ if(r->sense[12] != 0x04 || r->sense[13] != 0x01)
+ break;
+
+ while(waserror())
+ ;
+ tsleep(&up->sleep, return0, 0, 500);
+ poperror();
+ scsitest(r);
+ return 2;
+ default:
+ break;
+ }
+ break;
+ case SDok:
+ return 0;
+ }
+ return -1;
+}
+
+int
+scsionline(SDunit* unit)
+{
+ SDreq *r;
+ uchar *p;
+ int ok, retries;
+
+ if((r = malloc(sizeof(SDreq))) == nil)
+ return 0;
+ if((p = sdmalloc(8)) == nil){
+ free(r);
+ return 0;
+ }
+
+ ok = 0;
+
+ r->unit = unit;
+ r->lun = 0; /* ??? */
+ for(retries = 0; retries < 10; retries++){
+ /*
+ * Read-capacity is mandatory for DA, WORM, CD-ROM and
+ * MO. It may return 'not ready' if type DA is not
+ * spun up, type MO or type CD-ROM are not loaded or just
+ * plain slow getting their act together after a reset.
+ */
+ r->write = 0;
+ memset(r->cmd, 0, sizeof(r->cmd));
+ r->cmd[0] = 0x25;
+ r->cmd[1] = r->lun<<5;
+ r->clen = 10;
+ r->data = p;
+ r->dlen = 8;
+ r->flags = 0;
+
+ r->status = ~0;
+ switch(scsirio(r)){
+ default:
+ break;
+ case 0:
+ unit->sectors = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
+ unit->secsize = (p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7];
+
+ /*
+ * Some ATAPI CD readers lie about the block size.
+ * Since we don't read audio via this interface
+ * it's okay to always fudge this.
+ */
+ if(unit->secsize == 2352)
+ unit->secsize = 2048;
+ /*
+ * Devices with removable media may return 0 sectors
+ * when they have empty media (e.g. sata dvd writers);
+ * if so, keep the count zero.
+ *
+ * Read-capacity returns the LBA of the last sector,
+ * therefore the number of sectors must be incremented.
+ */
+ if(unit->sectors != 0)
+ unit->sectors++;
+ ok = 1;
+ break;
+ case 1:
+ ok = 1;
+ break;
+ case 2:
+ continue;
+ }
+ break;
+ }
+ free(p);
+ free(r);
+
+ if(ok)
+ return ok+retries;
+ else
+ return 0;
+}
+
+int
+scsiexec(SDunit* unit, int write, uchar* cmd, int clen, void* data, int* dlen)
+{
+ SDreq *r;
+ int status;
+
+ if((r = malloc(sizeof(SDreq))) == nil)
+ return SDmalloc;
+ r->unit = unit;
+ r->lun = cmd[1]>>5; /* ??? */
+ r->write = write;
+ memmove(r->cmd, cmd, clen);
+ r->clen = clen;
+ r->data = data;
+ if(dlen)
+ r->dlen = *dlen;
+ r->flags = 0;
+
+ r->status = ~0;
+
+ /*
+ * Call the device-specific I/O routine.
+ * There should be no calls to 'error()' below this
+ * which percolate back up.
+ */
+ switch(status = unit->dev->ifc->rio(r)){
+ case SDok:
+ if(dlen)
+ *dlen = r->rlen;
+ /*FALLTHROUGH*/
+ case SDcheck:
+ /*FALLTHROUGH*/
+ default:
+ /*
+ * It's more complicated than this. There are conditions
+ * which are 'ok' but for which the returned status code
+ * is not 'SDok'.
+ * Also, not all conditions require a reqsense, might
+ * need to do a reqsense here and make it available to the
+ * caller somehow.
+ *
+ * Mañana.
+ */
+ break;
+ }
+ sdfree(r);
+
+ return status;
+}
+
+static void
+scsifmt10(SDreq *r, int write, int lun, ulong nb, uvlong bno)
+{
+ uchar *c;
+
+ c = r->cmd;
+ if(write == 0)
+ c[0] = 0x28;
+ else
+ c[0] = 0x2A;
+ c[1] = lun<<5;
+ c[2] = bno>>24;
+ c[3] = bno>>16;
+ c[4] = bno>>8;
+ c[5] = bno;
+ c[6] = 0;
+ c[7] = nb>>8;
+ c[8] = nb;
+ c[9] = 0;
+
+ r->clen = 10;
+}
+
+static void
+scsifmt16(SDreq *r, int write, int lun, ulong nb, uvlong bno)
+{
+ uchar *c;
+
+ c = r->cmd;
+ if(write == 0)
+ c[0] = 0x88;
+ else
+ c[0] = 0x8A;
+ c[1] = lun<<5; /* so wrong */
+ c[2] = bno>>56;
+ c[3] = bno>>48;
+ c[4] = bno>>40;
+ c[5] = bno>>32;
+ c[6] = bno>>24;
+ c[7] = bno>>16;
+ c[8] = bno>>8;
+ c[9] = bno;
+ c[10] = nb>>24;
+ c[11] = nb>>16;
+ c[12] = nb>>8;
+ c[13] = nb;
+ c[14] = 0;
+ c[15] = 0;
+
+ r->clen = 16;
+}
+
+long
+scsibio(SDunit* unit, int lun, int write, void* data, long nb, uvlong bno)
+{
+ SDreq *r;
+ long rlen;
+
+ if((r = malloc(sizeof(SDreq))) == nil)
+ error(Enomem);
+ r->unit = unit;
+ r->lun = lun;
+again:
+ r->write = write;
+ if(bno >= (1ULL<<32))
+ scsifmt16(r, write, lun, nb, bno);
+ else
+ scsifmt10(r, write, lun, nb, bno);
+ r->data = data;
+ r->dlen = nb*unit->secsize;
+ r->flags = 0;
+
+ r->status = ~0;
+ switch(scsirio(r)){
+ default:
+ rlen = -1;
+ break;
+ case 0:
+ rlen = r->rlen;
+ break;
+ case 2:
+ rlen = -1;
+ if(!(r->flags & SDvalidsense))
+ break;
+ switch(r->sense[2] & 0x0F){
+ default:
+ break;
+ case 0x01: /* recovered error */
+ print("%s: recovered error at sector %llud\n",
+ unit->name, bno);
+ rlen = r->rlen;
+ break;
+ case 0x06: /* check condition */
+ /*
+ * Check for a removeable media change.
+ * If so, mark it by zapping the geometry info
+ * to force an online request.
+ */
+ if(r->sense[12] != 0x28 || r->sense[13] != 0)
+ break;
+ if(unit->inquiry[1] & 0x80)
+ unit->sectors = 0;
+ break;
+ case 0x02: /* not ready */
+ /*
+ * If unit is becoming ready,
+ * rather than not not ready, try again.
+ */
+ if(r->sense[12] == 0x04 && r->sense[13] == 0x01)
+ goto again;
+ break;
+ }
+ break;
+ }
+ free(r);
+
+ return rlen;
+}
+
diff --git a/sys/src/9/port/segment.c b/sys/src/9/port/segment.c
new file mode 100755
index 000000000..94267ae85
--- /dev/null
+++ b/sys/src/9/port/segment.c
@@ -0,0 +1,799 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+static void imagereclaim(void);
+static void imagechanreclaim(void);
+
+#include "io.h"
+
+/*
+ * Attachable segment types
+ */
+static Physseg physseg[10] = {
+ { SG_SHARED, "shared", 0, SEGMAXSIZE, 0, 0 },
+ { SG_BSS, "memory", 0, SEGMAXSIZE, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+};
+
+static Lock physseglock;
+
+#define NFREECHAN 64
+#define IHASHSIZE 64
+#define ihash(s) imagealloc.hash[s%IHASHSIZE]
+static struct Imagealloc
+{
+ Lock;
+ Image *free;
+ Image *hash[IHASHSIZE];
+ QLock ireclaim; /* mutex on reclaiming free images */
+
+ Chan **freechan; /* free image channels */
+ int nfreechan; /* number of free channels */
+ int szfreechan; /* size of freechan array */
+ QLock fcreclaim; /* mutex on reclaiming free channels */
+}imagealloc;
+
+Segment* (*_globalsegattach)(Proc*, char*);
+
+void
+initseg(void)
+{
+ Image *i, *ie;
+
+ imagealloc.free = xalloc(conf.nimage*sizeof(Image));
+ if (imagealloc.free == nil)
+ panic("initseg: no memory");
+ ie = &imagealloc.free[conf.nimage-1];
+ for(i = imagealloc.free; i < ie; i++)
+ i->next = i+1;
+ i->next = 0;
+ imagealloc.freechan = malloc(NFREECHAN * sizeof(Chan*));
+ imagealloc.szfreechan = NFREECHAN;
+}
+
+Segment *
+newseg(int type, ulong base, ulong size)
+{
+ Segment *s;
+ int mapsize;
+
+ if(size > (SEGMAPSIZE*PTEPERTAB))
+ error(Enovmem);
+
+ s = smalloc(sizeof(Segment));
+ s->ref = 1;
+ s->type = type;
+ s->base = base;
+ s->top = base+(size*BY2PG);
+ s->size = size;
+ s->sema.prev = &s->sema;
+ s->sema.next = &s->sema;
+
+ mapsize = ROUND(size, PTEPERTAB)/PTEPERTAB;
+ if(mapsize > nelem(s->ssegmap)){
+ mapsize *= 2;
+ if(mapsize > (SEGMAPSIZE*PTEPERTAB))
+ mapsize = (SEGMAPSIZE*PTEPERTAB);
+ s->map = smalloc(mapsize*sizeof(Pte*));
+ s->mapsize = mapsize;
+ }
+ else{
+ s->map = s->ssegmap;
+ s->mapsize = nelem(s->ssegmap);
+ }
+
+ return s;
+}
+
+void
+putseg(Segment *s)
+{
+ Pte **pp, **emap;
+ Image *i;
+
+ if(s == 0)
+ return;
+
+ i = s->image;
+ if(i != 0) {
+ lock(i);
+ lock(s);
+ if(i->s == s && s->ref == 1)
+ i->s = 0;
+ unlock(i);
+ }
+ else
+ lock(s);
+
+ s->ref--;
+ if(s->ref != 0) {
+ unlock(s);
+ return;
+ }
+ unlock(s);
+
+ qlock(&s->lk);
+ if(i)
+ putimage(i);
+
+ emap = &s->map[s->mapsize];
+ for(pp = s->map; pp < emap; pp++)
+ if(*pp)
+ freepte(s, *pp);
+
+ qunlock(&s->lk);
+ if(s->map != s->ssegmap)
+ free(s->map);
+ if(s->profile != 0)
+ free(s->profile);
+ free(s);
+}
+
+void
+relocateseg(Segment *s, ulong offset)
+{
+ Page **pg, *x;
+ Pte *pte, **p, **endpte;
+
+ endpte = &s->map[s->mapsize];
+ for(p = s->map; p < endpte; p++) {
+ if(*p == 0)
+ continue;
+ pte = *p;
+ for(pg = pte->first; pg <= pte->last; pg++) {
+ if(x = *pg)
+ x->va += offset;
+ }
+ }
+}
+
+Segment*
+dupseg(Segment **seg, int segno, int share)
+{
+ int i, size;
+ Pte *pte;
+ Segment *n, *s;
+
+ SET(n);
+ s = seg[segno];
+
+ qlock(&s->lk);
+ if(waserror()){
+ qunlock(&s->lk);
+ nexterror();
+ }
+ switch(s->type&SG_TYPE) {
+ case SG_TEXT: /* New segment shares pte set */
+ case SG_SHARED:
+ case SG_PHYSICAL:
+ goto sameseg;
+
+ case SG_STACK:
+ n = newseg(s->type, s->base, s->size);
+ break;
+
+ case SG_BSS: /* Just copy on write */
+ if(share)
+ goto sameseg;
+ n = newseg(s->type, s->base, s->size);
+ break;
+
+ case SG_DATA: /* Copy on write plus demand load info */
+ if(segno == TSEG){
+ poperror();
+ qunlock(&s->lk);
+ return data2txt(s);
+ }
+
+ if(share)
+ goto sameseg;
+ n = newseg(s->type, s->base, s->size);
+
+ incref(s->image);
+ n->image = s->image;
+ n->fstart = s->fstart;
+ n->flen = s->flen;
+ break;
+ }
+ size = s->mapsize;
+ for(i = 0; i < size; i++)
+ if(pte = s->map[i])
+ n->map[i] = ptecpy(pte);
+
+ n->flushme = s->flushme;
+ if(s->ref > 1)
+ procflushseg(s);
+ poperror();
+ qunlock(&s->lk);
+ return n;
+
+sameseg:
+ incref(s);
+ poperror();
+ qunlock(&s->lk);
+ return s;
+}
+
+void
+segpage(Segment *s, Page *p)
+{
+ Pte **pte;
+ ulong off;
+ Page **pg;
+
+ if(p->va < s->base || p->va >= s->top)
+ panic("segpage");
+
+ off = p->va - s->base;
+ pte = &s->map[off/PTEMAPMEM];
+ if(*pte == 0)
+ *pte = ptealloc();
+
+ pg = &(*pte)->pages[(off&(PTEMAPMEM-1))/BY2PG];
+ *pg = p;
+ if(pg < (*pte)->first)
+ (*pte)->first = pg;
+ if(pg > (*pte)->last)
+ (*pte)->last = pg;
+}
+
+Image*
+attachimage(int type, Chan *c, ulong base, ulong len)
+{
+ Image *i, **l;
+
+ /* reclaim any free channels from reclaimed segments */
+ if(imagealloc.nfreechan)
+ imagechanreclaim();
+
+ lock(&imagealloc);
+
+ /*
+ * Search the image cache for remains of the text from a previous
+ * or currently running incarnation
+ */
+ for(i = ihash(c->qid.path); i; i = i->hash) {
+ if(c->qid.path == i->qid.path) {
+ lock(i);
+ if(eqqid(c->qid, i->qid) &&
+ eqqid(c->mqid, i->mqid) &&
+ c->mchan == i->mchan &&
+ c->type == i->type) {
+ goto found;
+ }
+ unlock(i);
+ }
+ }
+
+ /*
+ * imagereclaim dumps pages from the free list which are cached by image
+ * structures. This should free some image structures.
+ */
+ while(!(i = imagealloc.free)) {
+ unlock(&imagealloc);
+ imagereclaim();
+ sched();
+ lock(&imagealloc);
+ }
+
+ imagealloc.free = i->next;
+
+ lock(i);
+ incref(c);
+ i->c = c;
+ i->type = c->type;
+ i->qid = c->qid;
+ i->mqid = c->mqid;
+ i->mchan = c->mchan;
+ l = &ihash(c->qid.path);
+ i->hash = *l;
+ *l = i;
+found:
+ unlock(&imagealloc);
+
+ if(i->s == 0) {
+ /* Disaster after commit in exec */
+ if(waserror()) {
+ unlock(i);
+ pexit(Enovmem, 1);
+ }
+ i->s = newseg(type, base, len);
+ i->s->image = i;
+ i->ref++;
+ poperror();
+ }
+ else
+ incref(i->s);
+
+ return i;
+}
+
+static struct {
+ int calls; /* times imagereclaim was called */
+ int loops; /* times the main loop was run */
+ uvlong ticks; /* total time in the main loop */
+ uvlong maxt; /* longest time in main loop */
+} irstats;
+
+static void
+imagereclaim(void)
+{
+ int n;
+ Page *p;
+ uvlong ticks;
+
+ irstats.calls++;
+ /* Somebody is already cleaning the page cache */
+ if(!canqlock(&imagealloc.ireclaim))
+ return;
+
+ lock(&palloc);
+ ticks = fastticks(nil);
+ n = 0;
+ /*
+ * All the pages with images backing them are at the
+ * end of the list (see putpage) so start there and work
+ * backward.
+ */
+ for(p = palloc.tail; p && p->image && n<1000; p = p->prev) {
+ if(p->ref == 0 && canlock(p)) {
+ if(p->ref == 0) {
+ n++;
+ uncachepage(p);
+ }
+ unlock(p);
+ }
+ }
+ ticks = fastticks(nil) - ticks;
+ unlock(&palloc);
+ irstats.loops++;
+ irstats.ticks += ticks;
+ if(ticks > irstats.maxt)
+ irstats.maxt = ticks;
+ //print("T%llud+", ticks);
+ qunlock(&imagealloc.ireclaim);
+}
+
+/*
+ * since close can block, this has to be called outside of
+ * spin locks.
+ */
+static void
+imagechanreclaim(void)
+{
+ Chan *c;
+
+ /* Somebody is already cleaning the image chans */
+ if(!canqlock(&imagealloc.fcreclaim))
+ return;
+
+ /*
+ * We don't have to recheck that nfreechan > 0 after we
+ * acquire the lock, because we're the only ones who decrement
+ * it (the other lock contender increments it), and there's only
+ * one of us thanks to the qlock above.
+ */
+ while(imagealloc.nfreechan > 0){
+ lock(&imagealloc);
+ imagealloc.nfreechan--;
+ c = imagealloc.freechan[imagealloc.nfreechan];
+ unlock(&imagealloc);
+ cclose(c);
+ }
+
+ qunlock(&imagealloc.fcreclaim);
+}
+
+void
+putimage(Image *i)
+{
+ Chan *c, **cp;
+ Image *f, **l;
+
+ if(i->notext)
+ return;
+
+ lock(i);
+ if(--i->ref == 0) {
+ l = &ihash(i->qid.path);
+ mkqid(&i->qid, ~0, ~0, QTFILE);
+ unlock(i);
+ c = i->c;
+
+ lock(&imagealloc);
+ for(f = *l; f; f = f->hash) {
+ if(f == i) {
+ *l = i->hash;
+ break;
+ }
+ l = &f->hash;
+ }
+
+ i->next = imagealloc.free;
+ imagealloc.free = i;
+
+ /* defer freeing channel till we're out of spin lock's */
+ if(imagealloc.nfreechan == imagealloc.szfreechan){
+ imagealloc.szfreechan += NFREECHAN;
+ cp = malloc(imagealloc.szfreechan*sizeof(Chan*));
+ if(cp == nil)
+ panic("putimage");
+ memmove(cp, imagealloc.freechan, imagealloc.nfreechan*sizeof(Chan*));
+ free(imagealloc.freechan);
+ imagealloc.freechan = cp;
+ }
+ imagealloc.freechan[imagealloc.nfreechan++] = c;
+ unlock(&imagealloc);
+
+ return;
+ }
+ unlock(i);
+}
+
+long
+ibrk(ulong addr, int seg)
+{
+ Segment *s, *ns;
+ ulong newtop, newsize;
+ int i, mapsize;
+ Pte **map;
+
+ s = up->seg[seg];
+ if(s == 0)
+ error(Ebadarg);
+
+ if(addr == 0)
+ return s->base;
+
+ qlock(&s->lk);
+
+ /* We may start with the bss overlapping the data */
+ if(addr < s->base) {
+ if(seg != BSEG || up->seg[DSEG] == 0 || addr < up->seg[DSEG]->base) {
+ qunlock(&s->lk);
+ error(Enovmem);
+ }
+ addr = s->base;
+ }
+
+ newtop = PGROUND(addr);
+ newsize = (newtop-s->base)/BY2PG;
+ if(newtop < s->top) {
+ /*
+ * do not shrink a segment shared with other procs, as the
+ * to-be-freed address space may have been passed to the kernel
+ * already by another proc and is past the validaddr stage.
+ */
+ if(s->ref > 1){
+ qunlock(&s->lk);
+ error(Einuse);
+ }
+ mfreeseg(s, newtop, (s->top-newtop)/BY2PG);
+ s->top = newtop;
+ s->size = newsize;
+ qunlock(&s->lk);
+ flushmmu();
+ return 0;
+ }
+
+ for(i = 0; i < NSEG; i++) {
+ ns = up->seg[i];
+ if(ns == 0 || ns == s)
+ continue;
+ if(newtop >= ns->base && newtop < ns->top) {
+ qunlock(&s->lk);
+ error(Esoverlap);
+ }
+ }
+
+ if(newsize > (SEGMAPSIZE*PTEPERTAB)) {
+ qunlock(&s->lk);
+ error(Enovmem);
+ }
+ mapsize = ROUND(newsize, PTEPERTAB)/PTEPERTAB;
+ if(mapsize > s->mapsize){
+ map = smalloc(mapsize*sizeof(Pte*));
+ memmove(map, s->map, s->mapsize*sizeof(Pte*));
+ if(s->map != s->ssegmap)
+ free(s->map);
+ s->map = map;
+ s->mapsize = mapsize;
+ }
+
+ s->top = newtop;
+ s->size = newsize;
+ qunlock(&s->lk);
+ return 0;
+}
+
+/*
+ * called with s->lk locked
+ */
+void
+mfreeseg(Segment *s, ulong start, int pages)
+{
+ int i, j, size;
+ ulong soff;
+ Page *pg;
+ Page *list;
+
+ soff = start-s->base;
+ j = (soff&(PTEMAPMEM-1))/BY2PG;
+
+ size = s->mapsize;
+ list = nil;
+ for(i = soff/PTEMAPMEM; i < size; i++) {
+ if(pages <= 0)
+ break;
+ if(s->map[i] == 0) {
+ pages -= PTEPERTAB-j;
+ j = 0;
+ continue;
+ }
+ while(j < PTEPERTAB) {
+ pg = s->map[i]->pages[j];
+ /*
+ * We want to zero s->map[i]->page[j] and putpage(pg),
+ * but we have to make sure other processors flush the
+ * entry from their TLBs before the page is freed.
+ * We construct a list of the pages to be freed, zero
+ * the entries, then (below) call procflushseg, and call
+ * putpage on the whole list.
+ *
+ * Swapped-out pages don't appear in TLBs, so it's okay
+ * to putswap those pages before procflushseg.
+ */
+ if(pg){
+ if(onswap(pg))
+ putswap(pg);
+ else{
+ pg->next = list;
+ list = pg;
+ }
+ s->map[i]->pages[j] = 0;
+ }
+ if(--pages == 0)
+ goto out;
+ j++;
+ }
+ j = 0;
+ }
+out:
+ /* flush this seg in all other processes */
+ if(s->ref > 1)
+ procflushseg(s);
+
+ /* free the pages */
+ for(pg = list; pg != nil; pg = list){
+ list = list->next;
+ putpage(pg);
+ }
+}
+
+Segment*
+isoverlap(Proc *p, ulong va, int len)
+{
+ int i;
+ Segment *ns;
+ ulong newtop;
+
+ newtop = va+len;
+ for(i = 0; i < NSEG; i++) {
+ ns = p->seg[i];
+ if(ns == 0)
+ continue;
+ if((newtop > ns->base && newtop <= ns->top) ||
+ (va >= ns->base && va < ns->top))
+ return ns;
+ }
+ return nil;
+}
+
+int
+addphysseg(Physseg* new)
+{
+ Physseg *ps;
+
+ /*
+ * Check not already entered and there is room
+ * for a new entry and the terminating null entry.
+ */
+ lock(&physseglock);
+ for(ps = physseg; ps->name; ps++){
+ if(strcmp(ps->name, new->name) == 0){
+ unlock(&physseglock);
+ return -1;
+ }
+ }
+ if(ps-physseg >= nelem(physseg)-2){
+ unlock(&physseglock);
+ return -1;
+ }
+
+ *ps = *new;
+ unlock(&physseglock);
+
+ return 0;
+}
+
+int
+isphysseg(char *name)
+{
+ Physseg *ps;
+ int rv = 0;
+
+ lock(&physseglock);
+ for(ps = physseg; ps->name; ps++){
+ if(strcmp(ps->name, name) == 0){
+ rv = 1;
+ break;
+ }
+ }
+ unlock(&physseglock);
+ return rv;
+}
+
+ulong
+segattach(Proc *p, ulong attr, char *name, ulong va, ulong len)
+{
+ int sno;
+ Segment *s, *os;
+ Physseg *ps;
+
+ if(va != 0 && va >= USTKTOP)
+ error(Ebadarg);
+
+ validaddr((ulong)name, 1, 0);
+ vmemchr(name, 0, ~0);
+
+ for(sno = 0; sno < NSEG; sno++)
+ if(p->seg[sno] == nil && sno != ESEG)
+ break;
+
+ if(sno == NSEG)
+ error(Enovmem);
+
+ /*
+ * first look for a global segment with the
+ * same name
+ */
+ if(_globalsegattach != nil){
+ s = (*_globalsegattach)(p, name);
+ if(s != nil){
+ p->seg[sno] = s;
+ return s->base;
+ }
+ }
+
+ len = PGROUND(len);
+ if(len == 0)
+ error(Ebadarg);
+
+ /*
+ * Find a hole in the address space.
+ * Starting at the lowest possible stack address - len,
+ * check for an overlapping segment, and repeat at the
+ * base of that segment - len until either a hole is found
+ * or the address space is exhausted. Ensure that we don't
+ * map the zero page.
+ */
+ if(va == 0) {
+ for (os = p->seg[SSEG]; os != nil; os = isoverlap(p, va, len)) {
+ va = os->base;
+ if(len >= va)
+ error(Enovmem);
+ va -= len;
+ }
+ va &= ~(BY2PG-1);
+ } else {
+ va &= ~(BY2PG-1);
+ if(va == 0 || va >= USTKTOP)
+ error(Ebadarg);
+ }
+
+ if(isoverlap(p, va, len) != nil)
+ error(Esoverlap);
+
+ for(ps = physseg; ps->name; ps++)
+ if(strcmp(name, ps->name) == 0)
+ goto found;
+
+ error(Ebadarg);
+found:
+ if(len > ps->size)
+ error(Enovmem);
+
+ attr &= ~SG_TYPE; /* Turn off what is not allowed */
+ attr |= ps->attr; /* Copy in defaults */
+
+ s = newseg(attr, va, len/BY2PG);
+ s->pseg = ps;
+ p->seg[sno] = s;
+
+ return va;
+}
+
+void
+pteflush(Pte *pte, int s, int e)
+{
+ int i;
+ Page *p;
+
+ for(i = s; i < e; i++) {
+ p = pte->pages[i];
+ if(pagedout(p) == 0)
+ memset(p->cachectl, PG_TXTFLUSH, sizeof(p->cachectl));
+ }
+}
+
+long
+syssegflush(ulong *arg)
+{
+ Segment *s;
+ ulong addr, l;
+ Pte *pte;
+ int chunk, ps, pe, len;
+
+ addr = arg[0];
+ len = arg[1];
+
+ while(len > 0) {
+ s = seg(up, addr, 1);
+ if(s == 0)
+ error(Ebadarg);
+
+ s->flushme = 1;
+ more:
+ l = len;
+ if(addr+l > s->top)
+ l = s->top - addr;
+
+ ps = addr-s->base;
+ pte = s->map[ps/PTEMAPMEM];
+ ps &= PTEMAPMEM-1;
+ pe = PTEMAPMEM;
+ if(pe-ps > l){
+ pe = ps + l;
+ pe = (pe+BY2PG-1)&~(BY2PG-1);
+ }
+ if(pe == ps) {
+ qunlock(&s->lk);
+ error(Ebadarg);
+ }
+
+ if(pte)
+ pteflush(pte, ps/BY2PG, pe/BY2PG);
+
+ chunk = pe-ps;
+ len -= chunk;
+ addr += chunk;
+
+ if(len > 0 && addr < s->top)
+ goto more;
+
+ qunlock(&s->lk);
+ }
+ flushmmu();
+ return 0;
+}
+
+void
+segclock(ulong pc)
+{
+ Segment *s;
+
+ s = up->seg[TSEG];
+ if(s == 0 || s->profile == 0)
+ return;
+
+ s->profile[0] += TK2MS(1);
+ if(pc >= s->base && pc < s->top) {
+ pc -= s->base;
+ s->profile[pc>>LRESPROF] += TK2MS(1);
+ }
+}
+
diff --git a/sys/src/9/port/semaphore.p b/sys/src/9/port/semaphore.p
new file mode 100755
index 000000000..8284ffd7f
--- /dev/null
+++ b/sys/src/9/port/semaphore.p
@@ -0,0 +1,183 @@
+/*
+spin -a semaphore.p
+pcc -DSAFETY -DREACH -DMEMLIM'='500 -o pan pan.c
+pan -i
+rm pan.* pan
+
+*/
+
+#define N 3
+
+bit listlock;
+byte value;
+bit onlist[N];
+bit waiting[N];
+bit sleeping[N];
+bit acquired[N];
+
+inline lock(x)
+{
+ atomic { x == 0; x = 1 }
+}
+
+inline unlock(x)
+{
+ assert x==1;
+ x = 0
+}
+
+inline sleep(cond)
+{
+ assert !sleeping[_pid];
+ assert !interrupted;
+ if
+ :: cond
+ :: atomic { else -> sleeping[_pid] = 1 } ->
+ !sleeping[_pid]
+ fi;
+ if
+ :: skip
+ :: interrupted = 1
+ fi
+}
+
+inline wakeup(id)
+{
+ if
+ :: sleeping[id] == 1 -> sleeping[id] = 0
+ :: else
+ fi
+}
+
+inline semqueue()
+{
+ lock(listlock);
+ assert !onlist[_pid];
+ onlist[_pid] = 1;
+ unlock(listlock)
+}
+
+inline semdequeue()
+{
+ lock(listlock);
+ assert onlist[_pid];
+ onlist[_pid] = 0;
+ waiting[_pid] = 0;
+ unlock(listlock)
+}
+
+inline semwakeup(n)
+{
+ byte i, j;
+
+ lock(listlock);
+ i = 0;
+ j = n;
+ do
+ :: (i < N && j > 0) ->
+ if
+ :: onlist[i] && waiting[i] ->
+ atomic { printf("kicked %d\n", i);
+ waiting[i] = 0 };
+ wakeup(i);
+ j--
+ :: else
+ fi;
+ i++
+ :: else -> break
+ od;
+ /* reset i and j to reduce state space */
+ i = 0;
+ j = 0;
+ unlock(listlock)
+}
+
+inline semrelease(n)
+{
+ atomic { value = value+n; printf("release %d\n", n); };
+ semwakeup(n)
+}
+
+inline canacquire()
+{
+ atomic { value > 0 -> value--; };
+ acquired[_pid] = 1
+}
+
+#define semawoke() !waiting[_pid]
+
+inline semacquire(block)
+{
+ if
+ :: atomic { canacquire() -> printf("easy acquire\n"); } ->
+ goto out
+ :: else
+ fi;
+ if
+ :: !block -> goto out
+ :: else
+ fi;
+
+ semqueue();
+ do
+ :: skip ->
+ waiting[_pid] = 1;
+ if
+ :: atomic { canacquire() -> printf("hard acquire\n"); } ->
+ break
+ :: else
+ fi;
+ sleep(semawoke())
+ if
+ :: interrupted ->
+ printf("%d interrupted\n", _pid);
+ break
+ :: !interrupted
+ fi
+ od;
+ semdequeue();
+ if
+ :: !waiting[_pid] ->
+ semwakeup(1)
+ :: else
+ fi;
+out:
+ assert (!block || interrupted || acquired[_pid]);
+ assert !(interrupted && acquired[_pid]);
+ assert !waiting[_pid];
+ printf("%d done\n", _pid);
+}
+
+active[N] proctype acquire()
+{
+ bit interrupted;
+
+ semacquire(1);
+ printf("%d finished\n", _pid);
+ skip
+}
+
+active proctype release()
+{
+ byte k;
+
+ k = 0;
+ do
+ :: k < N ->
+ semrelease(1);
+ k++;
+ :: else -> break
+ od;
+ skip
+}
+
+/*
+ * If this guy, the highest-numbered proc, sticks
+ * around, then everyone else sticks around.
+ * This makes sure that we get a state line for
+ * everyone in a proc dump.
+ */
+active proctype dummy()
+{
+end: 0;
+}
diff --git a/sys/src/9/port/swap.c b/sys/src/9/port/swap.c
new file mode 100755
index 000000000..64bb88352
--- /dev/null
+++ b/sys/src/9/port/swap.c
@@ -0,0 +1,447 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+static int canflush(Proc*, Segment*);
+static void executeio(void);
+static int needpages(void*);
+static void pageout(Proc*, Segment*);
+static void pagepte(int, Page**);
+static void pager(void*);
+
+Image swapimage;
+
+static int swopen;
+static Page **iolist;
+static int ioptr;
+
+static ulong genage, genclock, gencount;
+static uvlong gensum;
+
+static void
+gentick(void)
+{
+ genclock++;
+ if(gencount)
+ genage = gensum / gencount;
+ else
+ genage = 0;
+ gensum = gencount = 0;
+}
+
+void
+swapinit(void)
+{
+ swapalloc.swmap = xalloc(conf.nswap);
+ swapalloc.top = &swapalloc.swmap[conf.nswap];
+ swapalloc.alloc = swapalloc.swmap;
+ swapalloc.last = swapalloc.swmap;
+ swapalloc.free = conf.nswap;
+ iolist = xalloc(conf.nswppo*sizeof(Page*));
+ if(swapalloc.swmap == 0 || iolist == 0)
+ panic("swapinit: not enough memory");
+
+ swapimage.notext = 1;
+}
+
+ulong
+newswap(void)
+{
+ uchar *look;
+
+ lock(&swapalloc);
+
+ if(swapalloc.free == 0){
+ unlock(&swapalloc);
+ return ~0;
+ }
+
+ look = memchr(swapalloc.last, 0, swapalloc.top-swapalloc.last);
+ if(look == 0)
+ panic("inconsistent swap");
+
+ *look = 1;
+ swapalloc.last = look;
+ swapalloc.free--;
+ unlock(&swapalloc);
+ return (look-swapalloc.swmap) * BY2PG;
+}
+
+void
+putswap(Page *p)
+{
+ uchar *idx;
+
+ lock(&swapalloc);
+ idx = &swapalloc.swmap[((ulong)p)/BY2PG];
+ if(--(*idx) == 0) {
+ swapalloc.free++;
+ if(idx < swapalloc.last)
+ swapalloc.last = idx;
+ }
+ if(*idx >= 254)
+ panic("putswap %#p == %ud", p, *idx);
+ unlock(&swapalloc);
+}
+
+void
+dupswap(Page *p)
+{
+ lock(&swapalloc);
+ if(++swapalloc.swmap[((ulong)p)/BY2PG] == 0)
+ panic("dupswap");
+ unlock(&swapalloc);
+}
+
+int
+swapcount(ulong daddr)
+{
+ return swapalloc.swmap[daddr/BY2PG];
+}
+
+void
+kickpager(void)
+{
+ static int started;
+
+ if(started)
+ wakeup(&swapalloc.r);
+ else {
+ kproc("pager", pager, 0);
+ started = 1;
+ }
+}
+
+static void
+pager(void *junk)
+{
+ int i;
+ Segment *s;
+ Proc *p, *ep;
+
+ if(waserror())
+ panic("pager: os error");
+
+ p = proctab(0);
+ ep = &p[conf.nproc];
+
+loop:
+ up->psstate = "Idle";
+ wakeup(&palloc.r);
+ sleep(&swapalloc.r, needpages, 0);
+
+ while(needpages(junk)) {
+ if(swapimage.c) {
+ p++;
+ if(p >= ep){
+ p = proctab(0);
+ gentick();
+ }
+
+ if(p->state == Dead || p->noswap)
+ continue;
+
+ if(!canqlock(&p->seglock))
+ continue; /* process changing its segments */
+
+ for(i = 0; i < NSEG; i++) {
+ if(!needpages(junk)){
+ qunlock(&p->seglock);
+ goto loop;
+ }
+
+ if(s = p->seg[i]) {
+ switch(s->type&SG_TYPE) {
+ default:
+ break;
+ case SG_TEXT:
+ pageout(p, s);
+ break;
+ case SG_DATA:
+ case SG_BSS:
+ case SG_STACK:
+ case SG_SHARED:
+ up->psstate = "Pageout";
+ pageout(p, s);
+ if(ioptr != 0) {
+ up->psstate = "I/O";
+ executeio();
+ }
+ break;
+ }
+ }
+ }
+ qunlock(&p->seglock);
+ } else {
+ print("out of memory\n");
+ killbig("out of memory");
+ freebroken(); /* can use the memory */
+
+ /* Emulate the old system if no swap channel */
+ if(!swapimage.c)
+ tsleep(&up->sleep, return0, 0, 5000);
+ }
+ }
+ goto loop;
+}
+
+static void
+pageout(Proc *p, Segment *s)
+{
+ int type, i, size;
+ ulong age;
+ Pte *l;
+ Page **pg, *entry;
+
+ if(!canqlock(&s->lk)) /* We cannot afford to wait, we will surely deadlock */
+ return;
+
+ if(s->steal) { /* Protected by /dev/proc */
+ qunlock(&s->lk);
+ return;
+ }
+
+ if(!canflush(p, s)) { /* Able to invalidate all tlbs with references */
+ qunlock(&s->lk);
+ putseg(s);
+ return;
+ }
+
+ if(waserror()) {
+ qunlock(&s->lk);
+ putseg(s);
+ return;
+ }
+
+ /* Pass through the pte tables looking for memory pages to swap out */
+ type = s->type&SG_TYPE;
+ size = s->mapsize;
+ for(i = 0; i < size; i++) {
+ l = s->map[i];
+ if(l == 0)
+ continue;
+ for(pg = l->first; pg < l->last; pg++) {
+ entry = *pg;
+ if(pagedout(entry))
+ continue;
+
+ if(entry->modref & PG_REF) {
+ entry->modref &= ~PG_REF;
+ entry->gen = genclock;
+ }
+
+ if(genclock < entry->gen)
+ age = ~(entry->gen - genclock);
+ else
+ age = genclock - entry->gen;
+ gensum += age;
+ gencount++;
+ if(age <= genage)
+ continue;
+
+ pagepte(type, pg);
+
+ if(ioptr >= conf.nswppo)
+ goto out;
+ }
+ }
+out:
+ poperror();
+ qunlock(&s->lk);
+ putseg(s);
+}
+
+static int
+canflush(Proc *p, Segment *s)
+{
+ int i;
+ Proc *ep;
+
+ lock(s);
+ if(s->ref == 1) { /* Easy if we are the only user */
+ s->ref++;
+ unlock(s);
+ return canpage(p);
+ }
+ s->ref++;
+ unlock(s);
+
+ /* Now we must do hardwork to ensure all processes which have tlb
+ * entries for this segment will be flushed if we succeed in paging it out
+ */
+ p = proctab(0);
+ ep = &p[conf.nproc];
+ while(p < ep) {
+ if(p->state != Dead) {
+ for(i = 0; i < NSEG; i++)
+ if(p->seg[i] == s)
+ if(!canpage(p))
+ return 0;
+ }
+ p++;
+ }
+ return 1;
+}
+
+static void
+pagepte(int type, Page **pg)
+{
+ ulong daddr;
+ Page *outp;
+
+ outp = *pg;
+ switch(type) {
+ case SG_TEXT: /* Revert to demand load */
+ putpage(outp);
+ *pg = 0;
+ break;
+
+ case SG_DATA:
+ case SG_BSS:
+ case SG_STACK:
+ case SG_SHARED:
+ /*
+ * get a new swap address and clear any pages
+ * referring to it from the cache
+ */
+ daddr = newswap();
+ if(daddr == ~0)
+ break;
+ cachedel(&swapimage, daddr);
+
+ lock(outp);
+
+ /* forget anything that it used to cache */
+ uncachepage(outp);
+
+ /*
+ * incr the reference count to make sure it sticks around while
+ * being written
+ */
+ outp->ref++;
+
+ /*
+ * enter it into the cache so that a fault happening
+ * during the write will grab the page from the cache
+ * rather than one partially written to the disk
+ */
+ outp->daddr = daddr;
+ cachepage(outp, &swapimage);
+ *pg = (Page*)(daddr|PG_ONSWAP);
+ unlock(outp);
+
+ /* Add page to IO transaction list */
+ iolist[ioptr++] = outp;
+ break;
+ }
+}
+
+void
+pagersummary(void)
+{
+ print("%lud/%lud memory %lud/%lud swap %d iolist\n",
+ palloc.user-palloc.freecount,
+ palloc.user, conf.nswap-swapalloc.free, conf.nswap,
+ ioptr);
+}
+
+static int
+pageiocomp(void *a, void *b)
+{
+ Page *p1, *p2;
+
+ p1 = *(Page **)a;
+ p2 = *(Page **)b;
+ if(p1->daddr > p2->daddr)
+ return 1;
+ else
+ return -1;
+}
+
+static void
+executeio(void)
+{
+ Page *out;
+ int i, n;
+ Chan *c;
+ char *kaddr;
+ KMap *k;
+
+ c = swapimage.c;
+ qsort(iolist, ioptr, sizeof iolist[0], pageiocomp);
+ for(i = 0; i < ioptr; i++) {
+ if(ioptr > conf.nswppo)
+ panic("executeio: ioptr %d > %d", ioptr, conf.nswppo);
+ out = iolist[i];
+ k = kmap(out);
+ kaddr = (char*)VA(k);
+
+ if(waserror())
+ panic("executeio: page out I/O error");
+
+ n = devtab[c->type]->write(c, kaddr, BY2PG, out->daddr);
+ if(n != BY2PG)
+ nexterror();
+
+ kunmap(k);
+ poperror();
+
+ /* Free up the page after I/O */
+ lock(out);
+ out->ref--;
+ unlock(out);
+ putpage(out);
+ }
+ ioptr = 0;
+}
+
+static int
+needpages(void*)
+{
+ return palloc.freecount < swapalloc.headroom;
+}
+
+void
+setswapchan(Chan *c)
+{
+ uchar dirbuf[sizeof(Dir)+100];
+ Dir d;
+ int n;
+
+ if(swapimage.c) {
+ if(swapalloc.free != conf.nswap){
+ cclose(c);
+ error(Einuse);
+ }
+ cclose(swapimage.c);
+ }
+
+ /*
+ * if this isn't a file, set the swap space
+ * to be at most the size of the partition
+ */
+ if(devtab[c->type]->dc != L'M'){
+ n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf);
+ if(n <= 0){
+ cclose(c);
+ error("stat failed in setswapchan");
+ }
+ convM2D(dirbuf, n, &d, nil);
+ if(d.length < conf.nswap*BY2PG){
+ conf.nswap = d.length/BY2PG;
+ swapalloc.top = &swapalloc.swmap[conf.nswap];
+ swapalloc.free = conf.nswap;
+ }
+ }
+
+ swapimage.c = c;
+}
+
+int
+swapfull(void)
+{
+ return swapalloc.free < conf.nswap/10;
+}
diff --git a/sys/src/9/port/syscallfmt.c b/sys/src/9/port/syscallfmt.c
new file mode 100755
index 000000000..c04cc5cf8
--- /dev/null
+++ b/sys/src/9/port/syscallfmt.c
@@ -0,0 +1,405 @@
+/*
+ * Print functions for system call tracing.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#include "/sys/src/libc/9syscall/sys.h"
+
+// WE ARE OVERRUNNING SOMEHOW
+static void
+fmtrwdata(Fmt* f, char* a, int n, char* suffix)
+{
+ int i;
+ char *t;
+
+ if(a == nil){
+ fmtprint(f, "0x0%s", suffix);
+ return;
+ }
+ validaddr((ulong)a, n, 0);
+ t = smalloc(n+1);
+ for(i = 0; i < n; i++)
+ if(a[i] > 0x20 && a[i] < 0x7f) /* printable ascii? */
+ t[i] = a[i];
+ else
+ t[i] = '.';
+
+ fmtprint(f, " %#p/\"%s\"%s", a, t, suffix);
+ free(t);
+}
+
+static void
+fmtuserstring(Fmt* f, char* a, char* suffix)
+{
+ int n;
+ char *t;
+
+ if(a == nil){
+ fmtprint(f, "0/\"\"%s", suffix);
+ return;
+ }
+ validaddr((ulong)a, 1, 0);
+ n = ((char*)vmemchr(a, 0, 0x7fffffff) - a) + 1;
+ t = smalloc(n+1);
+ memmove(t, a, n);
+ t[n] = 0;
+ fmtprint(f, "%#p/\"%s\"%s", a, t, suffix);
+ free(t);
+}
+
+void
+syscallfmt(int syscallno, ulong pc, va_list list)
+{
+ long l;
+ Fmt fmt;
+ void *v;
+ vlong vl;
+ uintptr p;
+ int i[2], len;
+ char *a, **argv;
+
+ fmtstrinit(&fmt);
+ fmtprint(&fmt, "%uld %s ", up->pid, up->text);
+
+ if(syscallno > nsyscall)
+ fmtprint(&fmt, " %d ", syscallno);
+ else
+ fmtprint(&fmt, "%s ", sysctab[syscallno]?
+ sysctab[syscallno]: "huh?");
+
+ fmtprint(&fmt, "%ulx ", pc);
+ if(up->syscalltrace != nil)
+ free(up->syscalltrace);
+
+ switch(syscallno){
+ case SYSR1:
+ p = va_arg(list, uintptr);
+ fmtprint(&fmt, "%#p", p);
+ break;
+ case _ERRSTR: /* deprecated */
+ case CHDIR:
+ case EXITS:
+ case REMOVE:
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, "");
+ break;
+ case BIND:
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, " ");
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, " ");
+ i[0] = va_arg(list, int);
+ fmtprint(&fmt, "%#ux", i[0]);
+ break;
+ case CLOSE:
+ case NOTED:
+ i[0] = va_arg(list, int);
+ fmtprint(&fmt, "%d", i[0]);
+ break;
+ case DUP:
+ i[0] = va_arg(list, int);
+ i[1] = va_arg(list, int);
+ fmtprint(&fmt, "%d %d", i[0], i[1]);
+ break;
+ case ALARM:
+ l = va_arg(list, unsigned long);
+ fmtprint(&fmt, "%#lud ", l);
+ break;
+ case EXEC:
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, "");
+ argv = va_arg(list, char**);
+ evenaddr(PTR2UINT(argv));
+ for(;;){
+ validaddr((ulong)argv, sizeof(char**), 0);
+ a = *(char **)argv;
+ if(a == nil)
+ break;
+ fmtprint(&fmt, " ");
+ fmtuserstring(&fmt, a, "");
+ argv++;
+ }
+ break;
+ case _FSESSION: /* deprecated */
+ case _FSTAT: /* deprecated */
+ case _FWSTAT: /* obsolete */
+ i[0] = va_arg(list, int);
+ a = va_arg(list, char*);
+ fmtprint(&fmt, "%d %#p", i[0], a);
+ break;
+ case FAUTH:
+ i[0] = va_arg(list, int);
+ a = va_arg(list, char*);
+ fmtprint(&fmt, "%d", i[0]);
+ fmtuserstring(&fmt, a, "");
+ break;
+ case SEGBRK:
+ case RENDEZVOUS:
+ v = va_arg(list, void*);
+ fmtprint(&fmt, "%#p ", v);
+ v = va_arg(list, void*);
+ fmtprint(&fmt, "%#p", v);
+ break;
+ case _MOUNT: /* deprecated */
+ i[0] = va_arg(list, int);
+ fmtprint(&fmt, "%d ", i[0]);
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, " ");
+ i[0] = va_arg(list, int);
+ fmtprint(&fmt, "%#ux ", i[0]);
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, "");
+ break;
+ case OPEN:
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, " ");
+ i[0] = va_arg(list, int);
+ fmtprint(&fmt, "%#ux", i[0]);
+ break;
+ case OSEEK: /* deprecated */
+ i[0] = va_arg(list, int);
+ l = va_arg(list, long);
+ i[1] = va_arg(list, int);
+ fmtprint(&fmt, "%d %ld %d", i[0], l, i[1]);
+ break;
+ case SLEEP:
+ l = va_arg(list, long);
+ fmtprint(&fmt, "%ld", l);
+ break;
+ case _STAT: /* obsolete */
+ case _WSTAT: /* obsolete */
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, " ");
+ a = va_arg(list, char*);
+ fmtprint(&fmt, "%#p", a);
+ break;
+ case RFORK:
+ i[0] = va_arg(list, int);
+ fmtprint(&fmt, "%#ux", i[0]);
+ break;
+ case PIPE:
+ case BRK_:
+ v = va_arg(list, int*);
+ fmtprint(&fmt, "%#p", v);
+ break;
+ case CREATE:
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, " ");
+ i[0] = va_arg(list, int);
+ i[1] = va_arg(list, int);
+ fmtprint(&fmt, "%#ux %#ux", i[0], i[1]);
+ break;
+ case FD2PATH:
+ case FSTAT:
+ case FWSTAT:
+ i[0] = va_arg(list, int);
+ a = va_arg(list, char*);
+ l = va_arg(list, unsigned long);
+ fmtprint(&fmt, "%d %#p %lud", i[0], a, l);
+ break;
+ case NOTIFY:
+ case SEGDETACH:
+ case _WAIT: /* deprecated */
+ v = va_arg(list, void*);
+ fmtprint(&fmt, "%#p", v);
+ break;
+ case SEGATTACH:
+ i[0] = va_arg(list, int);
+ fmtprint(&fmt, "%d ", i[0]);
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, " ");
+ /*FALLTHROUGH*/
+ case SEGFREE:
+ case SEGFLUSH:
+ v = va_arg(list, void*);
+ l = va_arg(list, unsigned long);
+ fmtprint(&fmt, "%#p %lud", v, l);
+ break;
+ case UNMOUNT:
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, " ");
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, "");
+ break;
+ case SEMACQUIRE:
+ case SEMRELEASE:
+ v = va_arg(list, int*);
+ i[0] = va_arg(list, int);
+ fmtprint(&fmt, "%#p %d", v, i[0]);
+ break;
+ case SEEK:
+ v = va_arg(list, vlong*);
+ i[0] = va_arg(list, int);
+ vl = va_arg(list, vlong);
+ i[1] = va_arg(list, int);
+ fmtprint(&fmt, "%#p %d %#llux %d", v, i[0], vl, i[1]);
+ break;
+ case FVERSION:
+ i[0] = va_arg(list, int);
+ i[1] = va_arg(list, int);
+ fmtprint(&fmt, "%d %d ", i[0], i[1]);
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, " ");
+ l = va_arg(list, unsigned long);
+ fmtprint(&fmt, "%lud", l);
+ break;
+ case WSTAT:
+ case STAT:
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, " ");
+ /*FALLTHROUGH*/
+ case ERRSTR:
+ case AWAIT:
+ a = va_arg(list, char*);
+ l = va_arg(list, unsigned long);
+ fmtprint(&fmt, "%#p %lud", a, l);
+ break;
+ case MOUNT:
+ i[0] = va_arg(list, int);
+ i[1] = va_arg(list, int);
+ fmtprint(&fmt, "%d %d ", i[0], i[1]);
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, " ");
+ i[0] = va_arg(list, int);
+ fmtprint(&fmt, "%#ux ", i[0]);
+ a = va_arg(list, char*);
+ fmtuserstring(&fmt, a, "");
+ break;
+ case _READ: /* deprecated */
+ case PREAD:
+ i[0] = va_arg(list, int);
+ v = va_arg(list, void*);
+ l = va_arg(list, long);
+ fmtprint(&fmt, "%d %#p %ld", i[0], v, l);
+ if(syscallno == PREAD){
+ vl = va_arg(list, vlong);
+ fmtprint(&fmt, " %lld", vl);
+ }
+ break;
+ case _WRITE: /* deprecated */
+ case PWRITE:
+ i[0] = va_arg(list, int);
+ v = va_arg(list, void*);
+ l = va_arg(list, long);
+ fmtprint(&fmt, "%d ", i[0]);
+ len = MIN(l, 64);
+ fmtrwdata(&fmt, v, len, " ");
+ fmtprint(&fmt, "%ld", l);
+ if(syscallno == PWRITE){
+ vl = va_arg(list, vlong);
+ fmtprint(&fmt, " %lld", vl);
+ }
+ break;
+ }
+
+ up->syscalltrace = fmtstrflush(&fmt);
+}
+
+void
+sysretfmt(int syscallno, va_list list, long ret, uvlong start, uvlong stop)
+{
+ long l;
+ void* v;
+ Fmt fmt;
+ vlong vl;
+ int i, len;
+ char *a, *errstr;
+
+ fmtstrinit(&fmt);
+
+ if(up->syscalltrace)
+ free(up->syscalltrace);
+
+ errstr = "\"\"";
+ switch(syscallno){
+ default:
+ if(ret == -1)
+ errstr = up->errstr;
+ fmtprint(&fmt, " = %ld", ret);
+ break;
+ case ALARM:
+ case _WRITE:
+ case PWRITE:
+ if(ret == -1)
+ errstr = up->errstr;
+ fmtprint(&fmt, " = %ld", ret);
+ break;
+ case EXEC:
+ case SEGBRK:
+ case SEGATTACH:
+ case RENDEZVOUS:
+ if((void *)ret == (void*)-1)
+ errstr = up->errstr;
+ fmtprint(&fmt, " = %#p", (void *)ret);
+ break;
+ case AWAIT:
+ a = va_arg(list, char*);
+ l = va_arg(list, unsigned long);
+ if(ret > 0){
+ fmtuserstring(&fmt, a, " ");
+ fmtprint(&fmt, "%lud = %ld", l, ret);
+ }
+ else{
+ fmtprint(&fmt, "%#p/\"\" %lud = %ld", a, l, ret);
+ errstr = up->errstr;
+ }
+ break;
+ case _ERRSTR:
+ case ERRSTR:
+ a = va_arg(list, char*);
+ if(syscallno == _ERRSTR)
+ l = 64;
+ else
+ l = va_arg(list, unsigned long);
+ if(ret > 0){
+ fmtuserstring(&fmt, a, " ");
+ fmtprint(&fmt, "%lud = %ld", l, ret);
+ }
+ else{
+ fmtprint(&fmt, "\"\" %lud = %ld", l, ret);
+ errstr = up->errstr;
+ }
+ break;
+ case FD2PATH:
+ i = va_arg(list, int);
+ USED(i);
+ a = va_arg(list, char*);
+ l = va_arg(list, unsigned long);
+ if(ret > 0){
+ fmtuserstring(&fmt, a, " ");
+ fmtprint(&fmt, "%lud = %ld", l, ret);
+ }
+ else{
+ fmtprint(&fmt, "\"\" %lud = %ld", l, ret);
+ errstr = up->errstr;
+ }
+ break;
+ case _READ:
+ case PREAD:
+ i = va_arg(list, int);
+ USED(i);
+ v = va_arg(list, void*);
+ l = va_arg(list, long);
+ if(ret > 0){
+ len = MIN(ret, 64);
+ fmtrwdata(&fmt, v, len, "");
+ }
+ else{
+ fmtprint(&fmt, "/\"\"");
+ errstr = up->errstr;
+ }
+ fmtprint(&fmt, " %ld", l);
+ if(syscallno == PREAD){
+ vl = va_arg(list, vlong);
+ fmtprint(&fmt, " %lld", vl);
+ }
+ fmtprint(&fmt, " = %ld", ret);
+ break;
+ }
+ fmtprint(&fmt, " %s %#llud %#llud\n", errstr, start, stop);
+ up->syscalltrace = fmtstrflush(&fmt);
+}
diff --git a/sys/src/9/port/sysfile.c b/sys/src/9/port/sysfile.c
new file mode 100755
index 000000000..87b0cba3b
--- /dev/null
+++ b/sys/src/9/port/sysfile.c
@@ -0,0 +1,1335 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+/*
+ * The sys*() routines needn't poperror() as they return directly to syscall().
+ */
+
+static void
+unlockfgrp(Fgrp *f)
+{
+ int ex;
+
+ ex = f->exceed;
+ f->exceed = 0;
+ unlock(f);
+ if(ex)
+ pprint("warning: process exceeds %d file descriptors\n", ex);
+}
+
+int
+growfd(Fgrp *f, int fd) /* fd is always >= 0 */
+{
+ Chan **newfd, **oldfd;
+
+ if(fd < f->nfd)
+ return 0;
+ if(fd >= f->nfd+DELTAFD)
+ return -1; /* out of range */
+ /*
+ * Unbounded allocation is unwise; besides, there are only 16 bits
+ * of fid in 9P
+ */
+ if(f->nfd >= 5000){
+ Exhausted:
+ print("no free file descriptors\n");
+ return -1;
+ }
+ newfd = malloc((f->nfd+DELTAFD)*sizeof(Chan*));
+ if(newfd == 0)
+ goto Exhausted;
+ oldfd = f->fd;
+ memmove(newfd, oldfd, f->nfd*sizeof(Chan*));
+ f->fd = newfd;
+ free(oldfd);
+ f->nfd += DELTAFD;
+ if(fd > f->maxfd){
+ if(fd/100 > f->maxfd/100)
+ f->exceed = (fd/100)*100;
+ f->maxfd = fd;
+ }
+ return 1;
+}
+
+/*
+ * this assumes that the fgrp is locked
+ */
+int
+findfreefd(Fgrp *f, int start)
+{
+ int fd;
+
+ for(fd=start; fd<f->nfd; fd++)
+ if(f->fd[fd] == 0)
+ break;
+ if(fd >= f->nfd && growfd(f, fd) < 0)
+ return -1;
+ return fd;
+}
+
+int
+newfd(Chan *c)
+{
+ int fd;
+ Fgrp *f;
+
+ f = up->fgrp;
+ lock(f);
+ fd = findfreefd(f, 0);
+ if(fd < 0){
+ unlockfgrp(f);
+ return -1;
+ }
+ if(fd > f->maxfd)
+ f->maxfd = fd;
+ f->fd[fd] = c;
+ unlockfgrp(f);
+ return fd;
+}
+
+int
+newfd2(int fd[2], Chan *c[2])
+{
+ Fgrp *f;
+
+ f = up->fgrp;
+ lock(f);
+ fd[0] = findfreefd(f, 0);
+ if(fd[0] < 0){
+ unlockfgrp(f);
+ return -1;
+ }
+ fd[1] = findfreefd(f, fd[0]+1);
+ if(fd[1] < 0){
+ unlockfgrp(f);
+ return -1;
+ }
+ if(fd[1] > f->maxfd)
+ f->maxfd = fd[1];
+ f->fd[fd[0]] = c[0];
+ f->fd[fd[1]] = c[1];
+ unlockfgrp(f);
+
+ return 0;
+}
+
+Chan*
+fdtochan(int fd, int mode, int chkmnt, int iref)
+{
+ Chan *c;
+ Fgrp *f;
+
+ c = 0;
+ f = up->fgrp;
+
+ lock(f);
+ if(fd<0 || f->nfd<=fd || (c = f->fd[fd])==0) {
+ unlock(f);
+ error(Ebadfd);
+ }
+ if(iref)
+ incref(c);
+ unlock(f);
+
+ if(chkmnt && (c->flag&CMSG)) {
+ if(iref)
+ cclose(c);
+ error(Ebadusefd);
+ }
+
+ if(mode<0 || c->mode==ORDWR)
+ return c;
+
+ if((mode&OTRUNC) && c->mode==OREAD) {
+ if(iref)
+ cclose(c);
+ error(Ebadusefd);
+ }
+
+ if((mode&~OTRUNC) != c->mode) {
+ if(iref)
+ cclose(c);
+ error(Ebadusefd);
+ }
+
+ return c;
+}
+
+int
+openmode(ulong o)
+{
+ o &= ~(OTRUNC|OCEXEC|ORCLOSE);
+ if(o > OEXEC)
+ error(Ebadarg);
+ if(o == OEXEC)
+ return OREAD;
+ return o;
+}
+
+long
+sysfd2path(ulong *arg)
+{
+ Chan *c;
+
+ validaddr(arg[1], arg[2], 1);
+
+ c = fdtochan(arg[0], -1, 0, 1);
+ snprint((char*)arg[1], arg[2], "%s", chanpath(c));
+ cclose(c);
+ return 0;
+}
+
+long
+syspipe(ulong *arg)
+{
+ int fd[2];
+ Chan *c[2];
+ Dev *d;
+ static char *datastr[] = {"data", "data1"};
+
+ validaddr(arg[0], 2*BY2WD, 1);
+ evenaddr(arg[0]);
+ d = devtab[devno('|', 0)];
+ c[0] = namec("#|", Atodir, 0, 0);
+ c[1] = 0;
+ fd[0] = -1;
+ fd[1] = -1;
+
+ if(waserror()){
+ cclose(c[0]);
+ if(c[1])
+ cclose(c[1]);
+ nexterror();
+ }
+ c[1] = cclone(c[0]);
+ if(walk(&c[0], datastr+0, 1, 1, nil) < 0)
+ error(Egreg);
+ if(walk(&c[1], datastr+1, 1, 1, nil) < 0)
+ error(Egreg);
+ c[0] = d->open(c[0], ORDWR);
+ c[1] = d->open(c[1], ORDWR);
+ if(newfd2(fd, c) < 0)
+ error(Enofd);
+ poperror();
+
+ ((long*)arg[0])[0] = fd[0];
+ ((long*)arg[0])[1] = fd[1];
+ return 0;
+}
+
+long
+sysdup(ulong *arg)
+{
+ int fd;
+ Chan *c, *oc;
+ Fgrp *f = up->fgrp;
+
+ /*
+ * Close after dup'ing, so date > #d/1 works
+ */
+ c = fdtochan(arg[0], -1, 0, 1);
+ fd = arg[1];
+ if(fd != -1){
+ lock(f);
+ if(fd<0 || growfd(f, fd)<0) {
+ unlockfgrp(f);
+ cclose(c);
+ error(Ebadfd);
+ }
+ if(fd > f->maxfd)
+ f->maxfd = fd;
+
+ oc = f->fd[fd];
+ f->fd[fd] = c;
+ unlockfgrp(f);
+ if(oc)
+ cclose(oc);
+ }else{
+ if(waserror()) {
+ cclose(c);
+ nexterror();
+ }
+ fd = newfd(c);
+ if(fd < 0)
+ error(Enofd);
+ poperror();
+ }
+
+ return fd;
+}
+
+long
+sysopen(ulong *arg)
+{
+ int fd;
+ Chan *c;
+
+ openmode(arg[1]); /* error check only */
+ validaddr(arg[0], 1, 0);
+ c = namec((char*)arg[0], Aopen, arg[1], 0);
+ if(waserror()){
+ cclose(c);
+ nexterror();
+ }
+ fd = newfd(c);
+ if(fd < 0)
+ error(Enofd);
+ poperror();
+ return fd;
+}
+
+void
+fdclose(int fd, int flag)
+{
+ int i;
+ Chan *c;
+ Fgrp *f = up->fgrp;
+
+ lock(f);
+ c = f->fd[fd];
+ if(c == 0){
+ /* can happen for users with shared fd tables */
+ unlock(f);
+ return;
+ }
+ if(flag){
+ if(c==0 || !(c->flag&flag)){
+ unlock(f);
+ return;
+ }
+ }
+ f->fd[fd] = 0;
+ if(fd == f->maxfd)
+ for(i=fd; --i>=0 && f->fd[i]==0; )
+ f->maxfd = i;
+
+ unlock(f);
+ cclose(c);
+}
+
+long
+sysclose(ulong *arg)
+{
+ fdtochan(arg[0], -1, 0, 0);
+ fdclose(arg[0], 0);
+
+ return 0;
+}
+
+long
+unionread(Chan *c, void *va, long n)
+{
+ int i;
+ long nr;
+ Mhead *m;
+ Mount *mount;
+
+ qlock(&c->umqlock);
+ m = c->umh;
+ rlock(&m->lock);
+ mount = m->mount;
+ /* bring mount in sync with c->uri and c->umc */
+ for(i = 0; mount != nil && i < c->uri; i++)
+ mount = mount->next;
+
+ nr = 0;
+ while(mount != nil){
+ /* Error causes component of union to be skipped */
+ if(mount->to && !waserror()){
+ if(c->umc == nil){
+ c->umc = cclone(mount->to);
+ c->umc = devtab[c->umc->type]->open(c->umc, OREAD);
+ }
+
+ nr = devtab[c->umc->type]->read(c->umc, va, n, c->umc->offset);
+ c->umc->offset += nr;
+ poperror();
+ }
+ if(nr > 0)
+ break;
+
+ /* Advance to next element */
+ c->uri++;
+ if(c->umc){
+ cclose(c->umc);
+ c->umc = nil;
+ }
+ mount = mount->next;
+ }
+ runlock(&m->lock);
+ qunlock(&c->umqlock);
+ return nr;
+}
+
+static void
+unionrewind(Chan *c)
+{
+ qlock(&c->umqlock);
+ c->uri = 0;
+ if(c->umc){
+ cclose(c->umc);
+ c->umc = nil;
+ }
+ qunlock(&c->umqlock);
+}
+
+static int
+dirfixed(uchar *p, uchar *e, Dir *d)
+{
+ int len;
+
+ len = GBIT16(p)+BIT16SZ;
+ if(p + len > e)
+ return -1;
+
+ p += BIT16SZ; /* ignore size */
+ d->type = devno(GBIT16(p), 1);
+ p += BIT16SZ;
+ d->dev = GBIT32(p);
+ p += BIT32SZ;
+ d->qid.type = GBIT8(p);
+ p += BIT8SZ;
+ d->qid.vers = GBIT32(p);
+ p += BIT32SZ;
+ d->qid.path = GBIT64(p);
+ p += BIT64SZ;
+ d->mode = GBIT32(p);
+ p += BIT32SZ;
+ d->atime = GBIT32(p);
+ p += BIT32SZ;
+ d->mtime = GBIT32(p);
+ p += BIT32SZ;
+ d->length = GBIT64(p);
+
+ return len;
+}
+
+static char*
+dirname(uchar *p, int *n)
+{
+ p += BIT16SZ+BIT16SZ+BIT32SZ+BIT8SZ+BIT32SZ+BIT64SZ
+ + BIT32SZ+BIT32SZ+BIT32SZ+BIT64SZ;
+ *n = GBIT16(p);
+ return (char*)p+BIT16SZ;
+}
+
+static long
+dirsetname(char *name, int len, uchar *p, long n, long maxn)
+{
+ char *oname;
+ int olen;
+ long nn;
+
+ if(n == BIT16SZ)
+ return BIT16SZ;
+
+ oname = dirname(p, &olen);
+
+ nn = n+len-olen;
+ PBIT16(p, nn-BIT16SZ);
+ if(nn > maxn)
+ return BIT16SZ;
+
+ if(len != olen)
+ memmove(oname+len, oname+olen, p+n-(uchar*)(oname+olen));
+ PBIT16((uchar*)(oname-2), len);
+ memmove(oname, name, len);
+ return nn;
+}
+
+/*
+ * Mountfix might have caused the fixed results of the directory read
+ * to overflow the buffer. Catch the overflow in c->dirrock.
+ */
+static void
+mountrock(Chan *c, uchar *p, uchar **pe)
+{
+ uchar *e, *r;
+ int len, n;
+
+ e = *pe;
+
+ /* find last directory entry */
+ for(;;){
+ len = BIT16SZ+GBIT16(p);
+ if(p+len >= e)
+ break;
+ p += len;
+ }
+
+ /* save it away */
+ qlock(&c->rockqlock);
+ if(c->nrock+len > c->mrock){
+ n = ROUND(c->nrock+len, 1024);
+ r = smalloc(n);
+ memmove(r, c->dirrock, c->nrock);
+ free(c->dirrock);
+ c->dirrock = r;
+ c->mrock = n;
+ }
+ memmove(c->dirrock+c->nrock, p, len);
+ c->nrock += len;
+ qunlock(&c->rockqlock);
+
+ /* drop it */
+ *pe = p;
+}
+
+/*
+ * Satisfy a directory read with the results saved in c->dirrock.
+ */
+static int
+mountrockread(Chan *c, uchar *op, long n, long *nn)
+{
+ long dirlen;
+ uchar *rp, *erp, *ep, *p;
+
+ /* common case */
+ if(c->nrock == 0)
+ return 0;
+
+ /* copy out what we can */
+ qlock(&c->rockqlock);
+ rp = c->dirrock;
+ erp = rp+c->nrock;
+ p = op;
+ ep = p+n;
+ while(rp+BIT16SZ <= erp){
+ dirlen = BIT16SZ+GBIT16(rp);
+ if(p+dirlen > ep)
+ break;
+ memmove(p, rp, dirlen);
+ p += dirlen;
+ rp += dirlen;
+ }
+
+ if(p == op){
+ qunlock(&c->rockqlock);
+ return 0;
+ }
+
+ /* shift the rest */
+ if(rp != erp)
+ memmove(c->dirrock, rp, erp-rp);
+ c->nrock = erp - rp;
+
+ *nn = p - op;
+ qunlock(&c->rockqlock);
+ return 1;
+}
+
+static void
+mountrewind(Chan *c)
+{
+ c->nrock = 0;
+}
+
+/*
+ * Rewrite the results of a directory read to reflect current
+ * name space bindings and mounts. Specifically, replace
+ * directory entries for bind and mount points with the results
+ * of statting what is mounted there. Except leave the old names.
+ */
+static long
+mountfix(Chan *c, uchar *op, long n, long maxn)
+{
+ char *name;
+ int nbuf, nname;
+ Chan *nc;
+ Mhead *mh;
+ Mount *m;
+ uchar *p;
+ int dirlen, rest;
+ long l;
+ uchar *buf, *e;
+ Dir d;
+
+ p = op;
+ buf = nil;
+ nbuf = 0;
+ for(e=&p[n]; p+BIT16SZ<e; p+=dirlen){
+ dirlen = dirfixed(p, e, &d);
+ if(dirlen < 0)
+ break;
+ nc = nil;
+ mh = nil;
+ if(findmount(&nc, &mh, d.type, d.dev, d.qid)){
+ /*
+ * If it's a union directory and the original is
+ * in the union, don't rewrite anything.
+ */
+ for(m=mh->mount; m; m=m->next)
+ if(eqchantdqid(m->to, d.type, d.dev, d.qid, 1))
+ goto Norewrite;
+
+ name = dirname(p, &nname);
+ /*
+ * Do the stat but fix the name. If it fails, leave old entry.
+ * BUG: If it fails because there isn't room for the entry,
+ * what can we do? Nothing, really. Might as well skip it.
+ */
+ if(buf == nil){
+ buf = smalloc(4096);
+ nbuf = 4096;
+ }
+ if(waserror())
+ goto Norewrite;
+ l = devtab[nc->type]->stat(nc, buf, nbuf);
+ l = dirsetname(name, nname, buf, l, nbuf);
+ if(l == BIT16SZ)
+ error("dirsetname");
+ poperror();
+
+ /*
+ * Shift data in buffer to accomodate new entry,
+ * possibly overflowing into rock.
+ */
+ rest = e - (p+dirlen);
+ if(l > dirlen){
+ while(p+l+rest > op+maxn){
+ mountrock(c, p, &e);
+ if(e == p){
+ dirlen = 0;
+ goto Norewrite;
+ }
+ rest = e - (p+dirlen);
+ }
+ }
+ if(l != dirlen){
+ memmove(p+l, p+dirlen, rest);
+ dirlen = l;
+ e = p+dirlen+rest;
+ }
+
+ /*
+ * Rewrite directory entry.
+ */
+ memmove(p, buf, l);
+
+ Norewrite:
+ cclose(nc);
+ putmhead(mh);
+ }
+ }
+ if(buf)
+ free(buf);
+
+ if(p != e)
+ error("oops in rockfix");
+
+ return e-op;
+}
+
+static long
+read(ulong *arg, vlong *offp)
+{
+ long n, nn, nnn;
+ uchar *p;
+ Chan *c;
+ vlong off;
+
+ n = arg[2];
+ validaddr(arg[1], n, 1);
+ p = (void*)arg[1];
+ c = fdtochan(arg[0], OREAD, 1, 1);
+
+ if(waserror()){
+ cclose(c);
+ nexterror();
+ }
+
+ /*
+ * The offset is passed through on directories, normally.
+ * Sysseek complains, but pread is used by servers like exportfs,
+ * that shouldn't need to worry about this issue.
+ *
+ * Notice that c->devoffset is the offset that c's dev is seeing.
+ * The number of bytes read on this fd (c->offset) may be different
+ * due to rewritings in rockfix.
+ */
+ if(offp == nil) /* use and maintain channel's offset */
+ off = c->offset;
+ else
+ off = *offp;
+ if(off < 0)
+ error(Enegoff);
+
+ if(off == 0){ /* rewind to the beginning of the directory */
+ if(offp == nil){
+ c->offset = 0;
+ c->devoffset = 0;
+ }
+ mountrewind(c);
+ unionrewind(c);
+ }
+
+ if(c->qid.type & QTDIR){
+ if(mountrockread(c, p, n, &nn)){
+ /* do nothing: mountrockread filled buffer */
+ }else if(c->umh)
+ nn = unionread(c, p, n);
+ else{
+ if(off != c->offset)
+ error(Edirseek);
+ nn = devtab[c->type]->read(c, p, n, c->devoffset);
+ }
+ nnn = mountfix(c, p, nn, n);
+ }else
+ nnn = nn = devtab[c->type]->read(c, p, n, off);
+
+ lock(c);
+ c->devoffset += nn;
+ c->offset += nnn;
+ unlock(c);
+
+ poperror();
+ cclose(c);
+
+ return nnn;
+}
+
+long
+sys_read(ulong *arg)
+{
+ return read(arg, nil);
+}
+
+long
+syspread(ulong *arg)
+{
+ vlong v;
+ va_list list;
+
+ /* use varargs to guarantee alignment of vlong */
+ va_start(list, arg[2]);
+ v = va_arg(list, vlong);
+ va_end(list);
+
+ if(v == ~0ULL)
+ return read(arg, nil);
+
+ return read(arg, &v);
+}
+
+static long
+write(ulong *arg, vlong *offp)
+{
+ Chan *c;
+ long m, n;
+ vlong off;
+
+ validaddr(arg[1], arg[2], 0);
+ n = 0;
+ c = fdtochan(arg[0], OWRITE, 1, 1);
+ if(waserror()) {
+ if(offp == nil){
+ lock(c);
+ c->offset -= n;
+ unlock(c);
+ }
+ cclose(c);
+ nexterror();
+ }
+
+ if(c->qid.type & QTDIR)
+ error(Eisdir);
+
+ n = arg[2];
+
+ if(offp == nil){ /* use and maintain channel's offset */
+ lock(c);
+ off = c->offset;
+ c->offset += n;
+ unlock(c);
+ }else
+ off = *offp;
+
+ if(off < 0)
+ error(Enegoff);
+
+ m = devtab[c->type]->write(c, (void*)arg[1], n, off);
+
+ if(offp == nil && m < n){
+ lock(c);
+ c->offset -= n - m;
+ unlock(c);
+ }
+
+ poperror();
+ cclose(c);
+
+ return m;
+}
+
+long
+sys_write(ulong *arg)
+{
+ return write(arg, nil);
+}
+
+long
+syspwrite(ulong *arg)
+{
+ vlong v;
+ va_list list;
+
+ /* use varargs to guarantee alignment of vlong */
+ va_start(list, arg[2]);
+ v = va_arg(list, vlong);
+ va_end(list);
+
+ if(v == ~0ULL)
+ return write(arg, nil);
+
+ return write(arg, &v);
+}
+
+static void
+sseek(ulong *arg)
+{
+ Chan *c;
+ uchar buf[sizeof(Dir)+100];
+ Dir dir;
+ int n;
+ vlong off;
+ union {
+ vlong v;
+ ulong u[2];
+ } o;
+
+ c = fdtochan(arg[1], -1, 1, 1);
+ if(waserror()){
+ cclose(c);
+ nexterror();
+ }
+ if(devtab[c->type]->dc == '|')
+ error(Eisstream);
+
+ off = 0;
+ o.u[0] = arg[2];
+ o.u[1] = arg[3];
+ switch(arg[4]){
+ case 0:
+ off = o.v;
+ if((c->qid.type & QTDIR) && off != 0)
+ error(Eisdir);
+ if(off < 0)
+ error(Enegoff);
+ c->offset = off;
+ break;
+
+ case 1:
+ if(c->qid.type & QTDIR)
+ error(Eisdir);
+ lock(c); /* lock for read/write update */
+ off = o.v + c->offset;
+ if(off < 0){
+ unlock(c);
+ error(Enegoff);
+ }
+ c->offset = off;
+ unlock(c);
+ break;
+
+ case 2:
+ if(c->qid.type & QTDIR)
+ error(Eisdir);
+ n = devtab[c->type]->stat(c, buf, sizeof buf);
+ if(convM2D(buf, n, &dir, nil) == 0)
+ error("internal error: stat error in seek");
+ off = dir.length + o.v;
+ if(off < 0)
+ error(Enegoff);
+ c->offset = off;
+ break;
+
+ default:
+ error(Ebadarg);
+ }
+ *(vlong*)arg[0] = off;
+ c->uri = 0;
+ c->dri = 0;
+ cclose(c);
+ poperror();
+}
+
+long
+sysseek(ulong *arg)
+{
+ validaddr(arg[0], BY2V, 1);
+ sseek(arg);
+ return 0;
+}
+
+long
+sysoseek(ulong *arg)
+{
+ union {
+ vlong v;
+ ulong u[2];
+ } o;
+ ulong a[5];
+
+ o.v = (long)arg[1];
+ a[0] = (ulong)&o.v;
+ a[1] = arg[0];
+ a[2] = o.u[0];
+ a[3] = o.u[1];
+ a[4] = arg[2];
+ sseek(a);
+ return o.v;
+}
+
+void
+validstat(uchar *s, int n)
+{
+ int m;
+ char buf[64];
+
+ if(statcheck(s, n) < 0)
+ error(Ebadstat);
+ /* verify that name entry is acceptable */
+ s += STATFIXLEN - 4*BIT16SZ; /* location of first string */
+ /*
+ * s now points at count for first string.
+ * if it's too long, let the server decide; this is
+ * only for his protection anyway. otherwise
+ * we'd have to allocate and waserror.
+ */
+ m = GBIT16(s);
+ s += BIT16SZ;
+ if(m+1 > sizeof buf)
+ return;
+ memmove(buf, s, m);
+ buf[m] = '\0';
+ /* name could be '/' */
+ if(strcmp(buf, "/") != 0)
+ validname(buf, 0);
+}
+
+static char*
+pathlast(Path *p)
+{
+ char *s;
+
+ if(p == nil)
+ return nil;
+ if(p->len == 0)
+ return nil;
+ s = strrchr(p->s, '/');
+ if(s)
+ return s+1;
+ return p->s;
+}
+
+long
+sysfstat(ulong *arg)
+{
+ Chan *c;
+ uint l;
+
+ l = arg[2];
+ validaddr(arg[1], l, 1);
+ c = fdtochan(arg[0], -1, 0, 1);
+ if(waserror()) {
+ cclose(c);
+ nexterror();
+ }
+ l = devtab[c->type]->stat(c, (uchar*)arg[1], l);
+ poperror();
+ cclose(c);
+ return l;
+}
+
+long
+sysstat(ulong *arg)
+{
+ char *name;
+ Chan *c;
+ uint l;
+
+ l = arg[2];
+ validaddr(arg[1], l, 1);
+ validaddr(arg[0], 1, 0);
+ c = namec((char*)arg[0], Aaccess, 0, 0);
+ if(waserror()){
+ cclose(c);
+ nexterror();
+ }
+ l = devtab[c->type]->stat(c, (uchar*)arg[1], l);
+ name = pathlast(c->path);
+ if(name)
+ l = dirsetname(name, strlen(name), (uchar*)arg[1], l, arg[2]);
+
+ poperror();
+ cclose(c);
+ return l;
+}
+
+long
+syschdir(ulong *arg)
+{
+ Chan *c;
+
+ validaddr(arg[0], 1, 0);
+
+ c = namec((char*)arg[0], Atodir, 0, 0);
+ cclose(up->dot);
+ up->dot = c;
+ return 0;
+}
+
+long
+bindmount(int ismount, int fd, int afd, char* arg0, char* arg1, ulong flag, char* spec)
+{
+ int ret;
+ Chan *c0, *c1, *ac, *bc;
+ struct{
+ Chan *chan;
+ Chan *authchan;
+ char *spec;
+ int flags;
+ }bogus;
+
+ if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER))
+ error(Ebadarg);
+
+ if(ismount){
+ validaddr((ulong)spec, 1, 0);
+ spec = validnamedup(spec, 1);
+ if(waserror()){
+ free(spec);
+ nexterror();
+ }
+
+ if(up->pgrp->noattach)
+ error(Enoattach);
+
+ ac = nil;
+ bc = fdtochan(fd, ORDWR, 0, 1);
+ if(waserror()) {
+ if(ac)
+ cclose(ac);
+ cclose(bc);
+ nexterror();
+ }
+
+ if(afd >= 0)
+ ac = fdtochan(afd, ORDWR, 0, 1);
+
+ bogus.flags = flag & MCACHE;
+ bogus.chan = bc;
+ bogus.authchan = ac;
+ bogus.spec = spec;
+ ret = devno('M', 0);
+ c0 = devtab[ret]->attach((char*)&bogus);
+ poperror(); /* ac bc */
+ if(ac)
+ cclose(ac);
+ cclose(bc);
+ }else{
+ spec = 0;
+ validaddr((ulong)arg0, 1, 0);
+ c0 = namec(arg0, Abind, 0, 0);
+ }
+
+ if(waserror()){
+ cclose(c0);
+ nexterror();
+ }
+
+ validaddr((ulong)arg1, 1, 0);
+ c1 = namec(arg1, Amount, 0, 0);
+ if(waserror()){
+ cclose(c1);
+ nexterror();
+ }
+
+ ret = cmount(&c0, c1, flag, spec);
+
+ poperror();
+ cclose(c1);
+ poperror();
+ cclose(c0);
+ if(ismount){
+ fdclose(fd, 0);
+ poperror();
+ free(spec);
+ }
+ return ret;
+}
+
+long
+sysbind(ulong *arg)
+{
+ return bindmount(0, -1, -1, (char*)arg[0], (char*)arg[1], arg[2], nil);
+}
+
+long
+sysmount(ulong *arg)
+{
+ return bindmount(1, arg[0], arg[1], nil, (char*)arg[2], arg[3], (char*)arg[4]);
+}
+
+long
+sys_mount(ulong *arg)
+{
+ return bindmount(1, arg[0], -1, nil, (char*)arg[1], arg[2], (char*)arg[3]);
+}
+
+long
+sysunmount(ulong *arg)
+{
+ Chan *cmount, *cmounted;
+
+ cmounted = 0;
+
+ validaddr(arg[1], 1, 0);
+ cmount = namec((char *)arg[1], Amount, 0, 0);
+ if(waserror()) {
+ cclose(cmount);
+ if(cmounted)
+ cclose(cmounted);
+ nexterror();
+ }
+
+ if(arg[0]) {
+ /*
+ * This has to be namec(..., Aopen, ...) because
+ * if arg[0] is something like /srv/cs or /fd/0,
+ * opening it is the only way to get at the real
+ * Chan underneath.
+ */
+ validaddr(arg[0], 1, 0);
+ cmounted = namec((char*)arg[0], Aopen, OREAD, 0);
+ }
+ cunmount(cmount, cmounted);
+ poperror();
+ cclose(cmount);
+ if(cmounted)
+ cclose(cmounted);
+ return 0;
+}
+
+long
+syscreate(ulong *arg)
+{
+ int fd;
+ Chan *c;
+
+ openmode(arg[1]&~OEXCL); /* error check only; OEXCL okay here */
+ validaddr(arg[0], 1, 0);
+ c = namec((char*)arg[0], Acreate, arg[1], arg[2]);
+ if(waserror()) {
+ cclose(c);
+ nexterror();
+ }
+ fd = newfd(c);
+ if(fd < 0)
+ error(Enofd);
+ poperror();
+ return fd;
+}
+
+long
+sysremove(ulong *arg)
+{
+ Chan *c;
+
+ validaddr(arg[0], 1, 0);
+ c = namec((char*)arg[0], Aremove, 0, 0);
+ /*
+ * Removing mount points is disallowed to avoid surprises
+ * (which should be removed: the mount point or the mounted Chan?).
+ */
+ if(c->ismtpt){
+ cclose(c);
+ error(Eismtpt);
+ }
+ if(waserror()){
+ c->type = 0; /* see below */
+ cclose(c);
+ nexterror();
+ }
+ devtab[c->type]->remove(c);
+ /*
+ * Remove clunks the fid, but we need to recover the Chan
+ * so fake it up. rootclose() is known to be a nop.
+ */
+ c->type = 0;
+ poperror();
+ cclose(c);
+ return 0;
+}
+
+static long
+wstat(Chan *c, uchar *d, int nd)
+{
+ long l;
+ int namelen;
+
+ if(waserror()){
+ cclose(c);
+ nexterror();
+ }
+ if(c->ismtpt){
+ /*
+ * Renaming mount points is disallowed to avoid surprises
+ * (which should be renamed? the mount point or the mounted Chan?).
+ */
+ dirname(d, &namelen);
+ if(namelen)
+ nameerror(chanpath(c), Eismtpt);
+ }
+ l = devtab[c->type]->wstat(c, d, nd);
+ poperror();
+ cclose(c);
+ return l;
+}
+
+long
+syswstat(ulong *arg)
+{
+ Chan *c;
+ uint l;
+
+ l = arg[2];
+ validaddr(arg[1], l, 0);
+ validstat((uchar*)arg[1], l);
+ validaddr(arg[0], 1, 0);
+ c = namec((char*)arg[0], Aaccess, 0, 0);
+ return wstat(c, (uchar*)arg[1], l);
+}
+
+long
+sysfwstat(ulong *arg)
+{
+ Chan *c;
+ uint l;
+
+ l = arg[2];
+ validaddr(arg[1], l, 0);
+ validstat((uchar*)arg[1], l);
+ c = fdtochan(arg[0], -1, 1, 1);
+ return wstat(c, (uchar*)arg[1], l);
+}
+
+static void
+packoldstat(uchar *buf, Dir *d)
+{
+ uchar *p;
+ ulong q;
+
+ /* lay down old stat buffer - grotty code but it's temporary */
+ p = buf;
+ strncpy((char*)p, d->name, 28);
+ p += 28;
+ strncpy((char*)p, d->uid, 28);
+ p += 28;
+ strncpy((char*)p, d->gid, 28);
+ p += 28;
+ q = d->qid.path & ~DMDIR; /* make sure doesn't accidentally look like directory */
+ if(d->qid.type & QTDIR) /* this is the real test of a new directory */
+ q |= DMDIR;
+ PBIT32(p, q);
+ p += BIT32SZ;
+ PBIT32(p, d->qid.vers);
+ p += BIT32SZ;
+ PBIT32(p, d->mode);
+ p += BIT32SZ;
+ PBIT32(p, d->atime);
+ p += BIT32SZ;
+ PBIT32(p, d->mtime);
+ p += BIT32SZ;
+ PBIT64(p, d->length);
+ p += BIT64SZ;
+ PBIT16(p, d->type);
+ p += BIT16SZ;
+ PBIT16(p, d->dev);
+}
+
+long
+sys_stat(ulong *arg)
+{
+ Chan *c;
+ uint l;
+ uchar buf[128]; /* old DIRLEN plus a little should be plenty */
+ char strs[128], *name;
+ Dir d;
+ char old[] = "old stat system call - recompile";
+
+ validaddr(arg[1], 116, 1);
+ validaddr(arg[0], 1, 0);
+ c = namec((char*)arg[0], Aaccess, 0, 0);
+ if(waserror()){
+ cclose(c);
+ nexterror();
+ }
+ l = devtab[c->type]->stat(c, buf, sizeof buf);
+ /* buf contains a new stat buf; convert to old. yuck. */
+ if(l <= BIT16SZ) /* buffer too small; time to face reality */
+ error(old);
+ name = pathlast(c->path);
+ if(name)
+ l = dirsetname(name, strlen(name), buf, l, sizeof buf);
+ l = convM2D(buf, l, &d, strs);
+ if(l == 0)
+ error(old);
+ packoldstat((uchar*)arg[1], &d);
+
+ poperror();
+ cclose(c);
+ return 0;
+}
+
+long
+sys_fstat(ulong *arg)
+{
+ Chan *c;
+ char *name;
+ uint l;
+ uchar buf[128]; /* old DIRLEN plus a little should be plenty */
+ char strs[128];
+ Dir d;
+ char old[] = "old fstat system call - recompile";
+
+ validaddr(arg[1], 116, 1);
+ c = fdtochan(arg[0], -1, 0, 1);
+ if(waserror()){
+ cclose(c);
+ nexterror();
+ }
+ l = devtab[c->type]->stat(c, buf, sizeof buf);
+ /* buf contains a new stat buf; convert to old. yuck. */
+ if(l <= BIT16SZ) /* buffer too small; time to face reality */
+ error(old);
+ name = pathlast(c->path);
+ if(name)
+ l = dirsetname(name, strlen(name), buf, l, sizeof buf);
+ l = convM2D(buf, l, &d, strs);
+ if(l == 0)
+ error(old);
+ packoldstat((uchar*)arg[1], &d);
+
+ poperror();
+ cclose(c);
+ return 0;
+}
+
+long
+sys_wstat(ulong *)
+{
+ error("old wstat system call - recompile");
+ return -1;
+}
+
+long
+sys_fwstat(ulong *)
+{
+ error("old fwstat system call - recompile");
+ return -1;
+}
diff --git a/sys/src/9/port/sysproc.c b/sys/src/9/port/sysproc.c
new file mode 100755
index 000000000..0048dc0b9
--- /dev/null
+++ b/sys/src/9/port/sysproc.c
@@ -0,0 +1,1068 @@
+#include "u.h"
+#include "tos.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "edf.h"
+
+#include <a.out.h>
+
+int shargs(char*, int, char**);
+
+extern void checkpages(void);
+extern void checkpagerefs(void);
+
+long
+sysr1(ulong*)
+{
+ checkpagerefs();
+ return 0;
+}
+
+long
+sysrfork(ulong *arg)
+{
+ Proc *p;
+ int n, i;
+ Fgrp *ofg;
+ Pgrp *opg;
+ Rgrp *org;
+ Egrp *oeg;
+ ulong pid, flag;
+ Mach *wm;
+
+ flag = arg[0];
+ /* Check flags before we commit */
+ if((flag & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG))
+ error(Ebadarg);
+ if((flag & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG))
+ error(Ebadarg);
+ if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG))
+ error(Ebadarg);
+
+ if((flag&RFPROC) == 0) {
+ if(flag & (RFMEM|RFNOWAIT))
+ error(Ebadarg);
+ if(flag & (RFFDG|RFCFDG)) {
+ ofg = up->fgrp;
+ if(flag & RFFDG)
+ up->fgrp = dupfgrp(ofg);
+ else
+ up->fgrp = dupfgrp(nil);
+ closefgrp(ofg);
+ }
+ if(flag & (RFNAMEG|RFCNAMEG)) {
+ opg = up->pgrp;
+ up->pgrp = newpgrp();
+ if(flag & RFNAMEG)
+ pgrpcpy(up->pgrp, opg);
+ /* inherit noattach */
+ up->pgrp->noattach = opg->noattach;
+ closepgrp(opg);
+ }
+ if(flag & RFNOMNT)
+ up->pgrp->noattach = 1;
+ if(flag & RFREND) {
+ org = up->rgrp;
+ up->rgrp = newrgrp();
+ closergrp(org);
+ }
+ if(flag & (RFENVG|RFCENVG)) {
+ oeg = up->egrp;
+ up->egrp = smalloc(sizeof(Egrp));
+ up->egrp->ref = 1;
+ if(flag & RFENVG)
+ envcpy(up->egrp, oeg);
+ closeegrp(oeg);
+ }
+ if(flag & RFNOTEG)
+ up->noteid = incref(&noteidalloc);
+ return 0;
+ }
+
+ p = newproc();
+
+ p->fpsave = up->fpsave;
+ p->scallnr = up->scallnr;
+ p->s = up->s;
+ p->nerrlab = 0;
+ p->slash = up->slash;
+ p->dot = up->dot;
+ incref(p->dot);
+
+ memmove(p->note, up->note, sizeof(p->note));
+ p->privatemem = up->privatemem;
+ p->noswap = up->noswap;
+ p->nnote = up->nnote;
+ p->notified = 0;
+ p->lastnote = up->lastnote;
+ p->notify = up->notify;
+ p->ureg = up->ureg;
+ p->dbgreg = 0;
+
+ /* Make a new set of memory segments */
+ n = flag & RFMEM;
+ qlock(&p->seglock);
+ if(waserror()){
+ qunlock(&p->seglock);
+ nexterror();
+ }
+ for(i = 0; i < NSEG; i++)
+ if(up->seg[i])
+ p->seg[i] = dupseg(up->seg, i, n);
+ qunlock(&p->seglock);
+ poperror();
+
+ /* File descriptors */
+ if(flag & (RFFDG|RFCFDG)) {
+ if(flag & RFFDG)
+ p->fgrp = dupfgrp(up->fgrp);
+ else
+ p->fgrp = dupfgrp(nil);
+ }
+ else {
+ p->fgrp = up->fgrp;
+ incref(p->fgrp);
+ }
+
+ /* Process groups */
+ if(flag & (RFNAMEG|RFCNAMEG)) {
+ p->pgrp = newpgrp();
+ if(flag & RFNAMEG)
+ pgrpcpy(p->pgrp, up->pgrp);
+ /* inherit noattach */
+ p->pgrp->noattach = up->pgrp->noattach;
+ }
+ else {
+ p->pgrp = up->pgrp;
+ incref(p->pgrp);
+ }
+ if(flag & RFNOMNT)
+ up->pgrp->noattach = 1;
+
+ if(flag & RFREND)
+ p->rgrp = newrgrp();
+ else {
+ incref(up->rgrp);
+ p->rgrp = up->rgrp;
+ }
+
+ /* Environment group */
+ if(flag & (RFENVG|RFCENVG)) {
+ p->egrp = smalloc(sizeof(Egrp));
+ p->egrp->ref = 1;
+ if(flag & RFENVG)
+ envcpy(p->egrp, up->egrp);
+ }
+ else {
+ p->egrp = up->egrp;
+ incref(p->egrp);
+ }
+ p->hang = up->hang;
+ p->procmode = up->procmode;
+
+ /* Craft a return frame which will cause the child to pop out of
+ * the scheduler in user mode with the return register zero
+ */
+ forkchild(p, up->dbgreg);
+
+ p->parent = up;
+ p->parentpid = up->pid;
+ if(flag&RFNOWAIT)
+ p->parentpid = 0;
+ else {
+ lock(&up->exl);
+ up->nchild++;
+ unlock(&up->exl);
+ }
+ if((flag&RFNOTEG) == 0)
+ p->noteid = up->noteid;
+
+ p->fpstate = up->fpstate;
+ pid = p->pid;
+ memset(p->time, 0, sizeof(p->time));
+ p->time[TReal] = MACHP(0)->ticks;
+
+ kstrdup(&p->text, up->text);
+ kstrdup(&p->user, up->user);
+ /*
+ * since the bss/data segments are now shareable,
+ * any mmu info about this process is now stale
+ * (i.e. has bad properties) and has to be discarded.
+ */
+ flushmmu();
+ p->basepri = up->basepri;
+ p->priority = up->basepri;
+ p->fixedpri = up->fixedpri;
+ p->mp = up->mp;
+ wm = up->wired;
+ if(wm)
+ procwired(p, wm->machno);
+ ready(p);
+ sched();
+ return pid;
+}
+
+static ulong
+l2be(long l)
+{
+ uchar *cp;
+
+ cp = (uchar*)&l;
+ return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
+}
+
+long
+sysexec(ulong *arg)
+{
+ Segment *s, *ts;
+ ulong t, d, b;
+ int i;
+ Chan *tc;
+ char **argv, **argp;
+ char *a, *charp, *args, *file, *file0;
+ char *progarg[sizeof(Exec)/2+1], *elem, progelem[64];
+ ulong ssize, spage, nargs, nbytes, n, bssend;
+ int indir;
+ Exec exec;
+ char line[sizeof(Exec)];
+ Fgrp *f;
+ Image *img;
+ ulong magic, text, entry, data, bss;
+ Tos *tos;
+
+ indir = 0;
+ elem = nil;
+ validaddr(arg[0], 1, 0);
+ file0 = validnamedup((char*)arg[0], 1);
+ if(waserror()){
+ free(file0);
+ free(elem);
+ nexterror();
+ }
+ file = file0;
+ for(;;){
+ tc = namec(file, Aopen, OEXEC, 0);
+ if(waserror()){
+ cclose(tc);
+ nexterror();
+ }
+ if(!indir)
+ kstrdup(&elem, up->genbuf);
+
+ n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);
+ if(n < 2)
+ error(Ebadexec);
+ magic = l2be(exec.magic);
+ text = l2be(exec.text);
+ entry = l2be(exec.entry);
+ if(n==sizeof(Exec) && (magic == AOUT_MAGIC)){
+ if(text >= USTKTOP-UTZERO
+ || entry < UTZERO+sizeof(Exec)
+ || entry >= UTZERO+sizeof(Exec)+text)
+ error(Ebadexec);
+ break; /* for binary */
+ }
+
+ /*
+ * Process #! /bin/sh args ...
+ */
+ memmove(line, &exec, sizeof(Exec));
+ if(indir || line[0]!='#' || line[1]!='!')
+ error(Ebadexec);
+ n = shargs(line, n, progarg);
+ if(n == 0)
+ error(Ebadexec);
+ indir = 1;
+ /*
+ * First arg becomes complete file name
+ */
+ progarg[n++] = file;
+ progarg[n] = 0;
+ validaddr(arg[1], BY2WD, 1);
+ arg[1] += BY2WD;
+ file = progarg[0];
+ if(strlen(elem) >= sizeof progelem)
+ error(Ebadexec);
+ strcpy(progelem, elem);
+ progarg[0] = progelem;
+ poperror();
+ cclose(tc);
+ }
+
+ data = l2be(exec.data);
+ bss = l2be(exec.bss);
+ t = (UTZERO+sizeof(Exec)+text+(BY2PG-1)) & ~(BY2PG-1);
+ d = (t + data + (BY2PG-1)) & ~(BY2PG-1);
+ bssend = t + data + bss;
+ b = (bssend + (BY2PG-1)) & ~(BY2PG-1);
+ if(t >= KZERO || d >= KZERO || b >= KZERO)
+ error(Ebadexec);
+
+ /*
+ * Args: pass 1: count
+ */
+ nbytes = sizeof(Tos); /* hole for profiling clock at top of stack (and more) */
+ nargs = 0;
+ if(indir){
+ argp = progarg;
+ while(*argp){
+ a = *argp++;
+ nbytes += strlen(a) + 1;
+ nargs++;
+ }
+ }
+ evenaddr(arg[1]);
+ argp = (char**)arg[1];
+ validaddr((ulong)argp, BY2WD, 0);
+ while(*argp){
+ a = *argp++;
+ if(((ulong)argp&(BY2PG-1)) < BY2WD)
+ validaddr((ulong)argp, BY2WD, 0);
+ validaddr((ulong)a, 1, 0);
+ nbytes += ((char*)vmemchr(a, 0, 0x7FFFFFFF) - a) + 1;
+ nargs++;
+ }
+ ssize = BY2WD*(nargs+1) + ((nbytes+(BY2WD-1)) & ~(BY2WD-1));
+
+ /*
+ * 8-byte align SP for those (e.g. sparc) that need it.
+ * execregs() will subtract another 4 bytes for argc.
+ */
+ if((ssize+4) & 7)
+ ssize += 4;
+ spage = (ssize+(BY2PG-1)) >> PGSHIFT;
+
+ /*
+ * Build the stack segment, putting it in kernel virtual for the moment
+ */
+ if(spage > TSTKSIZ)
+ error(Enovmem);
+
+ qlock(&up->seglock);
+ if(waserror()){
+ qunlock(&up->seglock);
+ nexterror();
+ }
+ up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG);
+
+ /*
+ * Args: pass 2: assemble; the pages will be faulted in
+ */
+ tos = (Tos*)(TSTKTOP - sizeof(Tos));
+ tos->cyclefreq = m->cyclefreq;
+ cycles((uvlong*)&tos->pcycles);
+ tos->pcycles = -tos->pcycles;
+ tos->kcycles = tos->pcycles;
+ tos->clock = 0;
+ argv = (char**)(TSTKTOP - ssize);
+ charp = (char*)(TSTKTOP - nbytes);
+ args = charp;
+ if(indir)
+ argp = progarg;
+ else
+ argp = (char**)arg[1];
+
+ for(i=0; i<nargs; i++){
+ if(indir && *argp==0) {
+ indir = 0;
+ argp = (char**)arg[1];
+ }
+ *argv++ = charp + (USTKTOP-TSTKTOP);
+ n = strlen(*argp) + 1;
+ memmove(charp, *argp++, n);
+ charp += n;
+ }
+ free(file0);
+
+ free(up->text);
+ up->text = elem;
+ elem = nil; /* so waserror() won't free elem */
+ USED(elem);
+
+ /* copy args; easiest from new process's stack */
+ n = charp - args;
+ if(n > 128) /* don't waste too much space on huge arg lists */
+ n = 128;
+ a = up->args;
+ up->args = nil;
+ free(a);
+ up->args = smalloc(n);
+ memmove(up->args, args, n);
+ if(n>0 && up->args[n-1]!='\0'){
+ /* make sure last arg is NUL-terminated */
+ /* put NUL at UTF-8 character boundary */
+ for(i=n-1; i>0; --i)
+ if(fullrune(up->args+i, n-i))
+ break;
+ up->args[i] = 0;
+ n = i+1;
+ }
+ up->nargs = n;
+
+ /*
+ * Committed.
+ * Free old memory.
+ * Special segments are maintained across exec
+ */
+ for(i = SSEG; i <= BSEG; i++) {
+ putseg(up->seg[i]);
+ /* prevent a second free if we have an error */
+ up->seg[i] = 0;
+ }
+ for(i = BSEG+1; i < NSEG; i++) {
+ s = up->seg[i];
+ if(s != 0 && (s->type&SG_CEXEC)) {
+ putseg(s);
+ up->seg[i] = 0;
+ }
+ }
+
+ /*
+ * Close on exec
+ */
+ f = up->fgrp;
+ for(i=0; i<=f->maxfd; i++)
+ fdclose(i, CCEXEC);
+
+ /* Text. Shared. Attaches to cache image if possible */
+ /* attachimage returns a locked cache image */
+ img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (t-UTZERO)>>PGSHIFT);
+ ts = img->s;
+ up->seg[TSEG] = ts;
+ ts->flushme = 1;
+ ts->fstart = 0;
+ ts->flen = sizeof(Exec)+text;
+ unlock(img);
+
+ /* Data. Shared. */
+ s = newseg(SG_DATA, t, (d-t)>>PGSHIFT);
+ up->seg[DSEG] = s;
+
+ /* Attached by hand */
+ incref(img);
+ s->image = img;
+ s->fstart = ts->fstart+ts->flen;
+ s->flen = data;
+
+ /* BSS. Zero fill on demand */
+ up->seg[BSEG] = newseg(SG_BSS, d, (b-d)>>PGSHIFT);
+
+ /*
+ * Move the stack
+ */
+ s = up->seg[ESEG];
+ up->seg[ESEG] = 0;
+ up->seg[SSEG] = s;
+ qunlock(&up->seglock);
+ poperror(); /* seglock */
+ poperror(); /* elem */
+ s->base = USTKTOP-USTKSIZE;
+ s->top = USTKTOP;
+ relocateseg(s, USTKTOP-TSTKTOP);
+
+ /*
+ * '/' processes are higher priority (hack to make /ip more responsive).
+ */
+ if(devtab[tc->type]->dc == L'/')
+ up->basepri = PriRoot;
+ up->priority = up->basepri;
+ poperror();
+ cclose(tc);
+
+ /*
+ * At this point, the mmu contains info about the old address
+ * space and needs to be flushed
+ */
+ flushmmu();
+ qlock(&up->debug);
+ up->nnote = 0;
+ up->notify = 0;
+ up->notified = 0;
+ up->privatemem = 0;
+ procsetup(up);
+ qunlock(&up->debug);
+ if(up->hang)
+ up->procctl = Proc_stopme;
+
+ return execregs(entry, ssize, nargs);
+}
+
+int
+shargs(char *s, int n, char **ap)
+{
+ int i;
+
+ s += 2;
+ n -= 2; /* skip #! */
+ for(i=0; s[i]!='\n'; i++)
+ if(i == n-1)
+ return 0;
+ s[i] = 0;
+ *ap = 0;
+ i = 0;
+ for(;;) {
+ while(*s==' ' || *s=='\t')
+ s++;
+ if(*s == 0)
+ break;
+ i++;
+ *ap++ = s;
+ *ap = 0;
+ while(*s && *s!=' ' && *s!='\t')
+ s++;
+ if(*s == 0)
+ break;
+ else
+ *s++ = 0;
+ }
+ return i;
+}
+
+int
+return0(void*)
+{
+ return 0;
+}
+
+long
+syssleep(ulong *arg)
+{
+
+ int n;
+
+ n = arg[0];
+ if(n <= 0) {
+ if (up->edf && (up->edf->flags & Admitted))
+ edfyield();
+ else
+ yield();
+ return 0;
+ }
+ if(n < TK2MS(1))
+ n = TK2MS(1);
+ tsleep(&up->sleep, return0, 0, n);
+ return 0;
+}
+
+long
+sysalarm(ulong *arg)
+{
+ return procalarm(arg[0]);
+}
+
+long
+sysexits(ulong *arg)
+{
+ char *status;
+ char *inval = "invalid exit string";
+ char buf[ERRMAX];
+
+ status = (char*)arg[0];
+ if(status){
+ if(waserror())
+ status = inval;
+ else{
+ validaddr((ulong)status, 1, 0);
+ if(vmemchr(status, 0, ERRMAX) == 0){
+ memmove(buf, status, ERRMAX);
+ buf[ERRMAX-1] = 0;
+ status = buf;
+ }
+ poperror();
+ }
+
+ }
+ pexit(status, 1);
+ return 0; /* not reached */
+}
+
+long
+sys_wait(ulong *arg)
+{
+ int pid;
+ Waitmsg w;
+ OWaitmsg *ow;
+
+ if(arg[0] == 0)
+ return pwait(nil);
+
+ validaddr(arg[0], sizeof(OWaitmsg), 1);
+ evenaddr(arg[0]);
+ pid = pwait(&w);
+ if(pid >= 0){
+ ow = (OWaitmsg*)arg[0];
+ readnum(0, ow->pid, NUMSIZE, w.pid, NUMSIZE);
+ readnum(0, ow->time+TUser*NUMSIZE, NUMSIZE, w.time[TUser], NUMSIZE);
+ readnum(0, ow->time+TSys*NUMSIZE, NUMSIZE, w.time[TSys], NUMSIZE);
+ readnum(0, ow->time+TReal*NUMSIZE, NUMSIZE, w.time[TReal], NUMSIZE);
+ strncpy(ow->msg, w.msg, sizeof(ow->msg));
+ ow->msg[sizeof(ow->msg)-1] = '\0';
+ }
+ return pid;
+}
+
+long
+sysawait(ulong *arg)
+{
+ int i;
+ int pid;
+ Waitmsg w;
+ ulong n;
+
+ n = arg[1];
+ validaddr(arg[0], n, 1);
+ pid = pwait(&w);
+ if(pid < 0)
+ return -1;
+ i = snprint((char*)arg[0], n, "%d %lud %lud %lud %q",
+ w.pid,
+ w.time[TUser], w.time[TSys], w.time[TReal],
+ w.msg);
+
+ return i;
+}
+
+void
+werrstr(char *fmt, ...)
+{
+ va_list va;
+
+ if(up == nil)
+ return;
+
+ va_start(va, fmt);
+ vseprint(up->syserrstr, up->syserrstr+ERRMAX, fmt, va);
+ va_end(va);
+}
+
+static long
+generrstr(char *buf, uint nbuf)
+{
+ char tmp[ERRMAX];
+
+ if(nbuf == 0)
+ error(Ebadarg);
+ validaddr((ulong)buf, nbuf, 1);
+ if(nbuf > sizeof tmp)
+ nbuf = sizeof tmp;
+ memmove(tmp, buf, nbuf);
+
+ /* make sure it's NUL-terminated */
+ tmp[nbuf-1] = '\0';
+ memmove(buf, up->syserrstr, nbuf);
+ buf[nbuf-1] = '\0';
+ memmove(up->syserrstr, tmp, nbuf);
+ return 0;
+}
+
+long
+syserrstr(ulong *arg)
+{
+ return generrstr((char*)arg[0], arg[1]);
+}
+
+/* compatibility for old binaries */
+long
+sys_errstr(ulong *arg)
+{
+ return generrstr((char*)arg[0], 64);
+}
+
+long
+sysnotify(ulong *arg)
+{
+ if(arg[0] != 0)
+ validaddr(arg[0], sizeof(ulong), 0);
+ up->notify = (int(*)(void*, char*))(arg[0]);
+ return 0;
+}
+
+long
+sysnoted(ulong *arg)
+{
+ if(arg[0]!=NRSTR && !up->notified)
+ error(Egreg);
+ return 0;
+}
+
+long
+syssegbrk(ulong *arg)
+{
+ int i;
+ ulong addr;
+ Segment *s;
+
+ addr = arg[0];
+ for(i = 0; i < NSEG; i++) {
+ s = up->seg[i];
+ if(s == 0 || addr < s->base || addr >= s->top)
+ continue;
+ switch(s->type&SG_TYPE) {
+ case SG_TEXT:
+ case SG_DATA:
+ case SG_STACK:
+ error(Ebadarg);
+ default:
+ return ibrk(arg[1], i);
+ }
+ }
+
+ error(Ebadarg);
+ return 0; /* not reached */
+}
+
+long
+syssegattach(ulong *arg)
+{
+ return segattach(up, arg[0], (char*)arg[1], arg[2], arg[3]);
+}
+
+long
+syssegdetach(ulong *arg)
+{
+ int i;
+ ulong addr;
+ Segment *s;
+
+ qlock(&up->seglock);
+ if(waserror()){
+ qunlock(&up->seglock);
+ nexterror();
+ }
+
+ s = 0;
+ addr = arg[0];
+ for(i = 0; i < NSEG; i++)
+ if(s = up->seg[i]) {
+ qlock(&s->lk);
+ if((addr >= s->base && addr < s->top) ||
+ (s->top == s->base && addr == s->base))
+ goto found;
+ qunlock(&s->lk);
+ }
+
+ error(Ebadarg);
+
+found:
+ /*
+ * Check we are not detaching the initial stack segment.
+ */
+ if(s == up->seg[SSEG]){
+ qunlock(&s->lk);
+ error(Ebadarg);
+ }
+ up->seg[i] = 0;
+ qunlock(&s->lk);
+ putseg(s);
+ qunlock(&up->seglock);
+ poperror();
+
+ /* Ensure we flush any entries from the lost segment */
+ flushmmu();
+ return 0;
+}
+
+long
+syssegfree(ulong *arg)
+{
+ Segment *s;
+ ulong from, to;
+
+ from = arg[0];
+ s = seg(up, from, 1);
+ if(s == nil)
+ error(Ebadarg);
+ to = (from + arg[1]) & ~(BY2PG-1);
+ from = PGROUND(from);
+
+ if(to > s->top) {
+ qunlock(&s->lk);
+ error(Ebadarg);
+ }
+
+ mfreeseg(s, from, (to - from) / BY2PG);
+ qunlock(&s->lk);
+ flushmmu();
+
+ return 0;
+}
+
+/* For binary compatibility */
+long
+sysbrk_(ulong *arg)
+{
+ return ibrk(arg[0], BSEG);
+}
+
+long
+sysrendezvous(ulong *arg)
+{
+ uintptr tag, val;
+ Proc *p, **l;
+
+ tag = arg[0];
+ l = &REND(up->rgrp, tag);
+ up->rendval = ~(uintptr)0;
+
+ lock(up->rgrp);
+ for(p = *l; p; p = p->rendhash) {
+ if(p->rendtag == tag) {
+ *l = p->rendhash;
+ val = p->rendval;
+ p->rendval = arg[1];
+
+ while(p->mach != 0)
+ ;
+ ready(p);
+ unlock(up->rgrp);
+ return val;
+ }
+ l = &p->rendhash;
+ }
+
+ /* Going to sleep here */
+ up->rendtag = tag;
+ up->rendval = arg[1];
+ up->rendhash = *l;
+ *l = up;
+ up->state = Rendezvous;
+ unlock(up->rgrp);
+
+ sched();
+
+ return up->rendval;
+}
+
+/*
+ * The implementation of semaphores is complicated by needing
+ * to avoid rescheduling in syssemrelease, so that it is safe
+ * to call from real-time processes. This means syssemrelease
+ * cannot acquire any qlocks, only spin locks.
+ *
+ * Semacquire and semrelease must both manipulate the semaphore
+ * wait list. Lock-free linked lists only exist in theory, not
+ * in practice, so the wait list is protected by a spin lock.
+ *
+ * The semaphore value *addr is stored in user memory, so it
+ * cannot be read or written while holding spin locks.
+ *
+ * Thus, we can access the list only when holding the lock, and
+ * we can access the semaphore only when not holding the lock.
+ * This makes things interesting. Note that sleep's condition function
+ * is called while holding two locks - r and up->rlock - so it cannot
+ * access the semaphore value either.
+ *
+ * An acquirer announces its intention to try for the semaphore
+ * by putting a Sema structure onto the wait list and then
+ * setting Sema.waiting. After one last check of semaphore,
+ * the acquirer sleeps until Sema.waiting==0. A releaser of n
+ * must wake up n acquirers who have Sema.waiting set. It does
+ * this by clearing Sema.waiting and then calling wakeup.
+ *
+ * There are three interesting races here.
+
+ * The first is that in this particular sleep/wakeup usage, a single
+ * wakeup can rouse a process from two consecutive sleeps!
+ * The ordering is:
+ *
+ * (a) set Sema.waiting = 1
+ * (a) call sleep
+ * (b) set Sema.waiting = 0
+ * (a) check Sema.waiting inside sleep, return w/o sleeping
+ * (a) try for semaphore, fail
+ * (a) set Sema.waiting = 1
+ * (a) call sleep
+ * (b) call wakeup(a)
+ * (a) wake up again
+ *
+ * This is okay - semacquire will just go around the loop
+ * again. It does mean that at the top of the for(;;) loop in
+ * semacquire, phore.waiting might already be set to 1.
+ *
+ * The second is that a releaser might wake an acquirer who is
+ * interrupted before he can acquire the lock. Since
+ * release(n) issues only n wakeup calls -- only n can be used
+ * anyway -- if the interrupted process is not going to use his
+ * wakeup call he must pass it on to another acquirer.
+ *
+ * The third race is similar to the second but more subtle. An
+ * acquirer sets waiting=1 and then does a final canacquire()
+ * before going to sleep. The opposite order would result in
+ * missing wakeups that happen between canacquire and
+ * waiting=1. (In fact, the whole point of Sema.waiting is to
+ * avoid missing wakeups between canacquire() and sleep().) But
+ * there can be spurious wakeups between a successful
+ * canacquire() and the following semdequeue(). This wakeup is
+ * not useful to the acquirer, since he has already acquired
+ * the semaphore. Like in the previous case, though, the
+ * acquirer must pass the wakeup call along.
+ *
+ * This is all rather subtle. The code below has been verified
+ * with the spin model /sys/src/9/port/semaphore.p. The
+ * original code anticipated the second race but not the first
+ * or third, which were caught only with spin. The first race
+ * is mentioned in /sys/doc/sleep.ps, but I'd forgotten about it.
+ * It was lucky that my abstract model of sleep/wakeup still managed
+ * to preserve that behavior.
+ *
+ * I remain slightly concerned about memory coherence
+ * outside of locks. The spin model does not take
+ * queued processor writes into account so we have to
+ * think hard. The only variables accessed outside locks
+ * are the semaphore value itself and the boolean flag
+ * Sema.waiting. The value is only accessed with cmpswap,
+ * whose job description includes doing the right thing as
+ * far as memory coherence across processors. That leaves
+ * Sema.waiting. To handle it, we call coherence() before each
+ * read and after each write. - rsc
+ */
+
+/* Add semaphore p with addr a to list in seg. */
+static void
+semqueue(Segment *s, long *a, Sema *p)
+{
+ memset(p, 0, sizeof *p);
+ p->addr = a;
+ lock(&s->sema); /* uses s->sema.Rendez.Lock, but no one else is */
+ p->next = &s->sema;
+ p->prev = s->sema.prev;
+ p->next->prev = p;
+ p->prev->next = p;
+ unlock(&s->sema);
+}
+
+/* Remove semaphore p from list in seg. */
+static void
+semdequeue(Segment *s, Sema *p)
+{
+ lock(&s->sema);
+ p->next->prev = p->prev;
+ p->prev->next = p->next;
+ unlock(&s->sema);
+}
+
+/* Wake up n waiters with addr a on list in seg. */
+static void
+semwakeup(Segment *s, long *a, long n)
+{
+ Sema *p;
+
+ lock(&s->sema);
+ for(p=s->sema.next; p!=&s->sema && n>0; p=p->next){
+ if(p->addr == a && p->waiting){
+ p->waiting = 0;
+ coherence();
+ wakeup(p);
+ n--;
+ }
+ }
+ unlock(&s->sema);
+}
+
+/* Add delta to semaphore and wake up waiters as appropriate. */
+static long
+semrelease(Segment *s, long *addr, long delta)
+{
+ long value;
+
+ do
+ value = *addr;
+ while(!cmpswap(addr, value, value+delta));
+ semwakeup(s, addr, delta);
+ return value+delta;
+}
+
+/* Try to acquire semaphore using compare-and-swap */
+static int
+canacquire(long *addr)
+{
+ long value;
+
+ while((value=*addr) > 0)
+ if(cmpswap(addr, value, value-1))
+ return 1;
+ return 0;
+}
+
+/* Should we wake up? */
+static int
+semawoke(void *p)
+{
+ coherence();
+ return !((Sema*)p)->waiting;
+}
+
+/* Acquire semaphore (subtract 1). */
+static int
+semacquire(Segment *s, long *addr, int block)
+{
+ int acquired;
+ Sema phore;
+
+ if(canacquire(addr))
+ return 1;
+ if(!block)
+ return 0;
+
+ acquired = 0;
+ semqueue(s, addr, &phore);
+ for(;;){
+ phore.waiting = 1;
+ coherence();
+ if(canacquire(addr)){
+ acquired = 1;
+ break;
+ }
+ if(waserror())
+ break;
+ sleep(&phore, semawoke, &phore);
+ poperror();
+ }
+ semdequeue(s, &phore);
+ coherence(); /* not strictly necessary due to lock in semdequeue */
+ if(!phore.waiting)
+ semwakeup(s, addr, 1);
+ if(!acquired)
+ nexterror();
+ return 1;
+}
+
+long
+syssemacquire(ulong *arg)
+{
+ int block;
+ long *addr;
+ Segment *s;
+
+ validaddr(arg[0], sizeof(long), 1);
+ evenaddr(arg[0]);
+ addr = (long*)arg[0];
+ block = arg[1];
+
+ if((s = seg(up, (ulong)addr, 0)) == nil)
+ error(Ebadarg);
+ if(*addr < 0)
+ error(Ebadarg);
+ return semacquire(s, addr, block);
+}
+
+long
+syssemrelease(ulong *arg)
+{
+ long *addr, delta;
+ Segment *s;
+
+ validaddr(arg[0], sizeof(long), 1);
+ evenaddr(arg[0]);
+ addr = (long*)arg[0];
+ delta = arg[1];
+
+ if((s = seg(up, (ulong)addr, 0)) == nil)
+ error(Ebadarg);
+ if(delta < 0 || *addr < 0)
+ error(Ebadarg);
+ return semrelease(s, addr, arg[1]);
+}
diff --git a/sys/src/9/port/systab.h b/sys/src/9/port/systab.h
new file mode 100755
index 000000000..3cf5beef7
--- /dev/null
+++ b/sys/src/9/port/systab.h
@@ -0,0 +1,163 @@
+#include "/sys/src/libc/9syscall/sys.h"
+
+typedef long Syscall(ulong*);
+
+Syscall sysr1;
+Syscall sys_errstr;
+Syscall sysbind;
+Syscall syschdir;
+Syscall sysclose;
+Syscall sysdup;
+Syscall sysalarm;
+Syscall sysexec;
+Syscall sysexits;
+Syscall sys_fsession;
+Syscall sysfauth;
+Syscall sys_fstat;
+Syscall syssegbrk;
+Syscall sys_mount;
+Syscall sysopen;
+Syscall sys_read;
+Syscall sysoseek;
+Syscall syssleep;
+Syscall sys_stat;
+Syscall sysrfork;
+Syscall sys_write;
+Syscall syspipe;
+Syscall syscreate;
+Syscall sysfd2path;
+Syscall sysbrk_;
+Syscall sysremove;
+Syscall sys_wstat;
+Syscall sys_fwstat;
+Syscall sysnotify;
+Syscall sysnoted;
+Syscall syssegattach;
+Syscall syssegdetach;
+Syscall syssegfree;
+Syscall syssegflush;
+Syscall sysrendezvous;
+Syscall sysunmount;
+Syscall sys_wait;
+Syscall syssemacquire;
+Syscall syssemrelease;
+Syscall sysseek;
+Syscall sysfversion;
+Syscall syserrstr;
+Syscall sysstat;
+Syscall sysfstat;
+Syscall syswstat;
+Syscall sysfwstat;
+Syscall sysmount;
+Syscall sysawait;
+Syscall syspread;
+Syscall syspwrite;
+Syscall sysdeath;
+
+Syscall *systab[]={
+ [SYSR1] sysr1,
+ [_ERRSTR] sys_errstr,
+ [BIND] sysbind,
+ [CHDIR] syschdir,
+ [CLOSE] sysclose,
+ [DUP] sysdup,
+ [ALARM] sysalarm,
+ [EXEC] sysexec,
+ [EXITS] sysexits,
+ [_FSESSION] sys_fsession,
+ [FAUTH] sysfauth,
+ [_FSTAT] sys_fstat,
+ [SEGBRK] syssegbrk,
+ [_MOUNT] sys_mount,
+ [OPEN] sysopen,
+ [_READ] sys_read,
+ [OSEEK] sysoseek,
+ [SLEEP] syssleep,
+ [_STAT] sys_stat,
+ [RFORK] sysrfork,
+ [_WRITE] sys_write,
+ [PIPE] syspipe,
+ [CREATE] syscreate,
+ [FD2PATH] sysfd2path,
+ [BRK_] sysbrk_,
+ [REMOVE] sysremove,
+ [_WSTAT] sys_wstat,
+ [_FWSTAT] sys_fwstat,
+ [NOTIFY] sysnotify,
+ [NOTED] sysnoted,
+ [SEGATTACH] syssegattach,
+ [SEGDETACH] syssegdetach,
+ [SEGFREE] syssegfree,
+ [SEGFLUSH] syssegflush,
+ [RENDEZVOUS] sysrendezvous,
+ [UNMOUNT] sysunmount,
+ [_WAIT] sys_wait,
+ [SEMACQUIRE] syssemacquire,
+ [SEMRELEASE] syssemrelease,
+ [SEEK] sysseek,
+ [FVERSION] sysfversion,
+ [ERRSTR] syserrstr,
+ [STAT] sysstat,
+ [FSTAT] sysfstat,
+ [WSTAT] syswstat,
+ [FWSTAT] sysfwstat,
+ [MOUNT] sysmount,
+ [AWAIT] sysawait,
+ [PREAD] syspread,
+ [PWRITE] syspwrite,
+};
+
+char *sysctab[]={
+ [SYSR1] "Running",
+ [_ERRSTR] "_errstr",
+ [BIND] "Bind",
+ [CHDIR] "Chdir",
+ [CLOSE] "Close",
+ [DUP] "Dup",
+ [ALARM] "Alarm",
+ [EXEC] "Exec",
+ [EXITS] "Exits",
+ [_FSESSION] "_fsession",
+ [FAUTH] "Fauth",
+ [_FSTAT] "_fstat",
+ [SEGBRK] "Segbrk",
+ [_MOUNT] "_mount",
+ [OPEN] "Open",
+ [_READ] "_read",
+ [OSEEK] "Oseek",
+ [SLEEP] "Sleep",
+ [_STAT] "_stat",
+ [RFORK] "Rfork",
+ [_WRITE] "_write",
+ [PIPE] "Pipe",
+ [CREATE] "Create",
+ [FD2PATH] "Fd2path",
+ [BRK_] "Brk",
+ [REMOVE] "Remove",
+ [_WSTAT] "_wstat",
+ [_FWSTAT] "_fwstat",
+ [NOTIFY] "Notify",
+ [NOTED] "Noted",
+ [SEGATTACH] "Segattach",
+ [SEGDETACH] "Segdetach",
+ [SEGFREE] "Segfree",
+ [SEGFLUSH] "Segflush",
+ [RENDEZVOUS] "Rendez",
+ [UNMOUNT] "Unmount",
+ [_WAIT] "_wait",
+ [SEMACQUIRE] "Semacquire",
+ [SEMRELEASE] "Semrelease",
+ [SEEK] "Seek",
+ [FVERSION] "Fversion",
+ [ERRSTR] "Errstr",
+ [STAT] "Stat",
+ [FSTAT] "Fstat",
+ [WSTAT] "Wstat",
+ [FWSTAT] "Fwstat",
+ [MOUNT] "Mount",
+ [AWAIT] "Await",
+ [PREAD] "Pread",
+ [PWRITE] "Pwrite",
+};
+
+int nsyscall = (sizeof systab/sizeof systab[0]);
diff --git a/sys/src/9/port/taslock.c b/sys/src/9/port/taslock.c
new file mode 100755
index 000000000..b93aaf832
--- /dev/null
+++ b/sys/src/9/port/taslock.c
@@ -0,0 +1,255 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "edf.h"
+
+long maxlockcycles;
+long maxilockcycles;
+long cumlockcycles;
+long cumilockcycles;
+ulong maxlockpc;
+ulong maxilockpc;
+
+struct
+{
+ ulong locks;
+ ulong glare;
+ ulong inglare;
+} lockstats;
+
+static void
+inccnt(Ref *r)
+{
+ _xinc(&r->ref);
+}
+
+static int
+deccnt(Ref *r)
+{
+ int x;
+
+ x = _xdec(&r->ref);
+ if(x < 0)
+ panic("deccnt pc=%#p", getcallerpc(&r));
+ return x;
+}
+
+static void
+dumplockmem(char *tag, Lock *l)
+{
+ uchar *cp;
+ int i;
+
+ iprint("%s: ", tag);
+ cp = (uchar*)l;
+ for(i = 0; i < 64; i++)
+ iprint("%2.2ux ", cp[i]);
+ iprint("\n");
+}
+
+void
+lockloop(Lock *l, ulong pc)
+{
+ Proc *p;
+
+ p = l->p;
+ print("lock %#p loop key %#lux pc %#lux held by pc %#lux proc %lud\n",
+ l, l->key, pc, l->pc, p ? p->pid : 0);
+ dumpaproc(up);
+ if(p != nil)
+ dumpaproc(p);
+}
+
+int
+lock(Lock *l)
+{
+ int i;
+ ulong pc;
+
+ pc = getcallerpc(&l);
+
+ lockstats.locks++;
+ if(up)
+ inccnt(&up->nlocks); /* prevent being scheded */
+ if(tas(&l->key) == 0){
+ if(up)
+ up->lastlock = l;
+ l->pc = pc;
+ l->p = up;
+ l->isilock = 0;
+#ifdef LOCKCYCLES
+ l->lockcycles = -lcycles();
+#endif
+ return 0;
+ }
+ if(up)
+ deccnt(&up->nlocks);
+
+ lockstats.glare++;
+ for(;;){
+ lockstats.inglare++;
+ i = 0;
+ while(l->key){
+ if(conf.nmach < 2 && up && up->edf && (up->edf->flags & Admitted)){
+ /*
+ * Priority inversion, yield on a uniprocessor; on a
+ * multiprocessor, the other processor will unlock
+ */
+ print("inversion %#p pc %#lux proc %lud held by pc %#lux proc %lud\n",
+ l, pc, up ? up->pid : 0, l->pc, l->p ? l->p->pid : 0);
+ up->edf->d = todget(nil); /* yield to process with lock */
+ }
+ if(i++ > 100000000){
+ i = 0;
+ lockloop(l, pc);
+ }
+ }
+ if(up)
+ inccnt(&up->nlocks);
+ if(tas(&l->key) == 0){
+ if(up)
+ up->lastlock = l;
+ l->pc = pc;
+ l->p = up;
+ l->isilock = 0;
+#ifdef LOCKCYCLES
+ l->lockcycles = -lcycles();
+#endif
+ return 1;
+ }
+ if(up)
+ deccnt(&up->nlocks);
+ }
+}
+
+void
+ilock(Lock *l)
+{
+ ulong x;
+ ulong pc;
+
+ pc = getcallerpc(&l);
+ lockstats.locks++;
+
+ x = splhi();
+ if(tas(&l->key) != 0){
+ lockstats.glare++;
+ /*
+ * Cannot also check l->pc, l->m, or l->isilock here
+ * because they might just not be set yet, or
+ * (for pc and m) the lock might have just been unlocked.
+ */
+ for(;;){
+ lockstats.inglare++;
+ splx(x);
+ while(l->key)
+ ;
+ x = splhi();
+ if(tas(&l->key) == 0)
+ goto acquire;
+ }
+ }
+acquire:
+ m->ilockdepth++;
+ if(up)
+ up->lastilock = l;
+ l->sr = x;
+ l->pc = pc;
+ l->p = up;
+ l->isilock = 1;
+ l->m = MACHP(m->machno);
+#ifdef LOCKCYCLES
+ l->lockcycles = -lcycles();
+#endif
+}
+
+int
+canlock(Lock *l)
+{
+ if(up)
+ inccnt(&up->nlocks);
+ if(tas(&l->key)){
+ if(up)
+ deccnt(&up->nlocks);
+ return 0;
+ }
+
+ if(up)
+ up->lastlock = l;
+ l->pc = getcallerpc(&l);
+ l->p = up;
+ l->m = MACHP(m->machno);
+ l->isilock = 0;
+#ifdef LOCKCYCLES
+ l->lockcycles = -lcycles();
+#endif
+ return 1;
+}
+
+void
+unlock(Lock *l)
+{
+#ifdef LOCKCYCLES
+ l->lockcycles += lcycles();
+ cumlockcycles += l->lockcycles;
+ if(l->lockcycles > maxlockcycles){
+ maxlockcycles = l->lockcycles;
+ maxlockpc = l->pc;
+ }
+#endif
+ if(l->key == 0)
+ print("unlock: not locked: pc %#p\n", getcallerpc(&l));
+ if(l->isilock)
+ print("unlock of ilock: pc %lux, held by %lux\n", getcallerpc(&l), l->pc);
+ if(l->p != up)
+ print("unlock: up changed: pc %#p, acquired at pc %lux, lock p %#p, unlock up %#p\n", getcallerpc(&l), l->pc, l->p, up);
+ l->m = nil;
+ l->key = 0;
+ coherence();
+
+ if(up && deccnt(&up->nlocks) == 0 && up->delaysched && islo()){
+ /*
+ * Call sched if the need arose while locks were held
+ * But, don't do it from interrupt routines, hence the islo() test
+ */
+ sched();
+ }
+}
+
+ulong ilockpcs[0x100] = { [0xff] = 1 };
+static int n;
+
+void
+iunlock(Lock *l)
+{
+ ulong sr;
+
+#ifdef LOCKCYCLES
+ l->lockcycles += lcycles();
+ cumilockcycles += l->lockcycles;
+ if(l->lockcycles > maxilockcycles){
+ maxilockcycles = l->lockcycles;
+ maxilockpc = l->pc;
+ }
+ if(l->lockcycles > 2400)
+ ilockpcs[n++ & 0xff] = l->pc;
+#endif
+ if(l->key == 0)
+ print("iunlock: not locked: pc %#p\n", getcallerpc(&l));
+ if(!l->isilock)
+ print("iunlock of lock: pc %#p, held by %#lux\n", getcallerpc(&l), l->pc);
+ if(islo())
+ print("iunlock while lo: pc %#p, held by %#lux\n", getcallerpc(&l), l->pc);
+
+ sr = l->sr;
+ l->m = nil;
+ l->key = 0;
+ coherence();
+ m->ilockdepth--;
+ if(up)
+ up->lastilock = nil;
+ splx(sr);
+}
diff --git a/sys/src/9/port/thwack.c b/sys/src/9/port/thwack.c
new file mode 100755
index 000000000..2b48de671
--- /dev/null
+++ b/sys/src/9/port/thwack.c
@@ -0,0 +1,381 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#include "thwack.h"
+
+typedef struct Huff Huff;
+
+enum
+{
+ MaxFastLen = 9,
+ BigLenCode = 0x1f4, /* minimum code for large lenth encoding */
+ BigLenBits = 9,
+ BigLenBase = 4 /* starting items to encode for big lens */
+};
+
+enum
+{
+ StatBytes,
+ StatOutBytes,
+ StatLits,
+ StatMatches,
+ StatOffBits,
+ StatLenBits,
+
+ StatDelay,
+ StatHist,
+
+ MaxStat
+};
+
+struct Huff
+{
+ short bits; /* length of the code */
+ ulong encode; /* the code */
+};
+
+static Huff lentab[MaxFastLen] =
+{
+ {2, 0x2}, /* 10 */
+ {3, 0x6}, /* 110 */
+ {5, 0x1c}, /* 11100 */
+ {5, 0x1d}, /* 11101 */
+ {6, 0x3c}, /* 111100 */
+ {7, 0x7a}, /* 1111010 */
+ {7, 0x7b}, /* 1111011 */
+ {8, 0xf8}, /* 11111000 */
+ {8, 0xf9}, /* 11111001 */
+};
+
+void
+thwackinit(Thwack *tw)
+{
+ int i;
+
+ memset(tw, 0, sizeof *tw);
+ for(i = 0; i < EWinBlocks; i++){
+ tw->blocks[i].data = tw->data[i];
+ tw->blocks[i].edata = tw->blocks[i].data;
+ tw->blocks[i].hash = tw->hash[i];
+ tw->blocks[i].acked = 0;
+ }
+}
+
+/*
+ * acknowledgement for block seq & nearby preds
+ */
+void
+thwackack(Thwack *tw, ulong seq, ulong mask)
+{
+ int slot, b;
+
+ slot = tw->slot;
+ for(;;){
+ slot--;
+ if(slot < 0)
+ slot += EWinBlocks;
+ if(slot == tw->slot)
+ break;
+ if(tw->blocks[slot].seq != seq)
+ continue;
+
+ tw->blocks[slot].acked = 1;
+
+ if(mask == 0)
+ break;
+ do{
+ b = mask & 1;
+ seq--;
+ mask >>= 1;
+ }while(!b);
+ }
+}
+
+/*
+ * find a string in the dictionary
+ */
+static int
+thwmatch(ThwBlock *b, ThwBlock *eblocks, uchar **ss, uchar *esrc, ulong h)
+{
+ int then, toff, w, ok;
+ uchar *s, *t;
+
+ s = *ss;
+ if(esrc < s + MinMatch)
+ return 0;
+
+ toff = 0;
+ for(; b < eblocks; b++){
+ then = b->hash[(h ^ b->seq) & HashMask];
+ toff += b->maxoff;
+ w = (ushort)(then - b->begin);
+
+ if(w >= b->maxoff)
+ continue;
+
+
+ /*
+ * don't need to check for the end because
+ * 1) s too close check above
+ * 2) entries too close not added to hash tables
+ */
+ t = w + b->data;
+ if(s[0] != t[0] || s[1] != t[1] || s[2] != t[2])
+ continue;
+ ok = b->edata - t;
+ if(esrc - s > ok)
+ esrc = s + ok;
+
+ t += 3;
+ for(s += 3; s < esrc; s++){
+ if(*s != *t)
+ break;
+ t++;
+ }
+ *ss = s;
+ return toff - w;
+ }
+ return 0;
+}
+
+/*
+ * knuth vol. 3 multiplicative hashing
+ * each byte x chosen according to rules
+ * 1/4 < x < 3/10, 1/3 x < < 3/7, 4/7 < x < 2/3, 7/10 < x < 3/4
+ * with reasonable spread between the bytes & their complements
+ *
+ * the 3 byte value appears to be as almost good as the 4 byte value,
+ * and might be faster on some machines
+ */
+/*
+#define hashit(c) (((ulong)(c) * 0x6b43a9) >> (24 - HashLog))
+*/
+#define hashit(c) ((((ulong)(c) & 0xffffff) * 0x6b43a9b5) >> (32 - HashLog))
+
+/*
+ * lz77 compression with single lookup in a hash table for each block
+ */
+int
+thwack(Thwack *tw, uchar *dst, uchar *src, int n, ulong seq, ulong stats[ThwStats])
+{
+ ThwBlock *eblocks, *b, blocks[CompBlocks];
+ uchar *s, *ss, *sss, *esrc, *half, *twdst, *twdmax;
+ ulong cont, cseq, bseq, cmask, code, twbits;
+ int now, toff, lithist, h, len, slot, bits, use, twnbits, lits, matches, offbits, lenbits, nhist;
+
+ if(n > ThwMaxBlock || n < MinMatch)
+ return -1;
+
+ twdst = dst;
+ twdmax = dst + n;
+
+ /*
+ * add source to the coding window
+ * there is always enough space
+ */
+ slot = tw->slot;
+ b = &tw->blocks[slot];
+ b->seq = seq;
+ b->acked = 0;
+ now = b->begin + b->maxoff;
+ s = b->data;
+ memmove(s, src, n);
+ b->edata = s + n;
+ b->begin = now;
+ b->maxoff = n;
+
+ /*
+ * set up the history blocks
+ */
+ cseq = seq;
+ cmask = 0;
+ *blocks = *b;
+ b = blocks;
+ b->maxoff = 0;
+ b++;
+ nhist = 0;
+ while(b < blocks + CompBlocks){
+ slot--;
+ if(slot < 0)
+ slot += EWinBlocks;
+ if(slot == tw->slot)
+ break;
+ if(!tw->blocks[slot].acked)
+ continue;
+ bseq = tw->blocks[slot].seq;
+ if(cseq == seq){
+ if(seq - bseq >= MaxSeqStart)
+ break;
+ cseq = bseq;
+ }else if(cseq - bseq > MaxSeqMask)
+ break;
+ else
+ cmask |= 1 << (cseq - bseq - 1);
+ *b = tw->blocks[slot];
+ nhist += b->maxoff;
+ b++;
+ }
+ eblocks = b;
+ *twdst++ = seq - cseq;
+ *twdst++ = cmask;
+
+ cont = (s[0] << 16) | (s[1] << 8) | s[2];
+
+ esrc = s + n;
+ half = s + (n >> 1);
+ twnbits = 0;
+ twbits = 0;
+ lits = 0;
+ matches = 0;
+ offbits = 0;
+ lenbits = 0;
+ lithist = ~0;
+ while(s < esrc){
+ h = hashit(cont);
+
+ sss = s;
+ toff = thwmatch(blocks, eblocks, &sss, esrc, h);
+ ss = sss;
+
+ len = ss - s;
+ for(; twnbits >= 8; twnbits -= 8){
+ if(twdst >= twdmax)
+ return -1;
+ *twdst++ = twbits >> (twnbits - 8);
+ }
+ if(len < MinMatch){
+ toff = *s;
+ lithist = (lithist << 1) | (toff < 32) | (toff > 127);
+ if(lithist & 0x1e){
+ twbits = (twbits << 9) | toff;
+ twnbits += 9;
+ }else if(lithist & 1){
+ toff = (toff + 64) & 0xff;
+ if(toff < 96){
+ twbits = (twbits << 10) | toff;
+ twnbits += 10;
+ }else{
+ twbits = (twbits << 11) | toff;
+ twnbits += 11;
+ }
+ }else{
+ twbits = (twbits << 8) | toff;
+ twnbits += 8;
+ }
+ lits++;
+ blocks->maxoff++;
+
+ /*
+ * speed hack
+ * check for compression progress, bail if none achieved
+ */
+ if(s > half){
+ if(4 * blocks->maxoff < 5 * lits)
+ return -1;
+ half = esrc;
+ }
+
+ if(s + MinMatch <= esrc){
+ blocks->hash[(h ^ blocks->seq) & HashMask] = now;
+ if(s + MinMatch < esrc)
+ cont = (cont << 8) | s[MinMatch];
+ }
+ now++;
+ s++;
+ continue;
+ }
+
+ blocks->maxoff += len;
+ matches++;
+
+ /*
+ * length of match
+ */
+ len -= MinMatch;
+ if(len < MaxFastLen){
+ bits = lentab[len].bits;
+ twbits = (twbits << bits) | lentab[len].encode;
+ twnbits += bits;
+ lenbits += bits;
+ }else{
+ code = BigLenCode;
+ bits = BigLenBits;
+ use = BigLenBase;
+ len -= MaxFastLen;
+ while(len >= use){
+ len -= use;
+ code = (code + use) << 1;
+ use <<= (bits & 1) ^ 1;
+ bits++;
+ }
+ twbits = (twbits << bits) | (code + len);
+ twnbits += bits;
+ lenbits += bits;
+
+ for(; twnbits >= 8; twnbits -= 8){
+ if(twdst >= twdmax)
+ return -1;
+ *twdst++ = twbits >> (twnbits - 8);
+ }
+ }
+
+ /*
+ * offset in history
+ */
+ toff--;
+ for(bits = OffBase; toff >= (1 << bits); bits++)
+ ;
+ if(bits < MaxOff+OffBase-1){
+ twbits = (twbits << 3) | (bits - OffBase);
+ if(bits != OffBase)
+ bits--;
+ twnbits += bits + 3;
+ offbits += bits + 3;
+ }else{
+ twbits = (twbits << 4) | 0xe | (bits - (MaxOff+OffBase-1));
+ bits--;
+ twnbits += bits + 4;
+ offbits += bits + 4;
+ }
+ twbits = (twbits << bits) | toff & ((1 << bits) - 1);
+
+ for(; s != ss; s++){
+ if(s + MinMatch <= esrc){
+ h = hashit(cont);
+ blocks->hash[(h ^ blocks->seq) & HashMask] = now;
+ if(s + MinMatch < esrc)
+ cont = (cont << 8) | s[MinMatch];
+ }
+ now++;
+ }
+ }
+
+
+ if(twnbits & 7){
+ twbits <<= 8 - (twnbits & 7);
+ twnbits += 8 - (twnbits & 7);
+ }
+ for(; twnbits >= 8; twnbits -= 8){
+ if(twdst >= twdmax)
+ return -1;
+ *twdst++ = twbits >> (twnbits - 8);
+ }
+
+ tw->slot++;
+ if(tw->slot >= EWinBlocks)
+ tw->slot = 0;
+
+ stats[StatBytes] += blocks->maxoff;
+ stats[StatLits] += lits;
+ stats[StatMatches] += matches;
+ stats[StatOffBits] += offbits;
+ stats[StatLenBits] += lenbits;
+ stats[StatDelay] = stats[StatDelay]*7/8 + dst[0];
+ stats[StatHist] = stats[StatHist]*7/8 + nhist;
+ stats[StatOutBytes] += twdst - dst;
+
+ return twdst - dst;
+}
diff --git a/sys/src/9/port/thwack.h b/sys/src/9/port/thwack.h
new file mode 100755
index 000000000..d50c47c23
--- /dev/null
+++ b/sys/src/9/port/thwack.h
@@ -0,0 +1,68 @@
+typedef struct Thwack Thwack;
+typedef struct Unthwack Unthwack;
+typedef struct ThwBlock ThwBlock;
+typedef struct UnthwBlock UnthwBlock;
+
+enum
+{
+ ThwStats = 8,
+ ThwMaxBlock = 1600, /* max size of compressible block */
+
+ HashLog = 12,
+ HashSize = 1<<HashLog,
+ HashMask = HashSize - 1,
+
+ MinMatch = 3, /* shortest match possible */
+
+ MaxOff = 8,
+ OffBase = 6,
+
+ MinDecode = 8, /* minimum bits to decode a match or lit; >= 8 */
+
+ EWinBlocks = 22, /* blocks held in encoder window */
+ DWinBlocks = 32, /* blocks held in decoder window */
+ CompBlocks = 10, /* max blocks used to encode data */
+
+ MaxSeqMask = 8, /* number of bits in coding block mask */
+ MaxSeqStart = 256 /* max offset of initial coding block */
+};
+
+struct ThwBlock
+{
+ ulong seq; /* sequence number for this data */
+ uchar acked; /* ok to use this block; the decoder has it */
+ ushort begin; /* time of first byte in hash */
+ uchar *edata; /* last byte of valid data */
+ ushort maxoff; /* time of last valid hash entry */
+ ushort *hash;
+ uchar *data;
+};
+
+struct Thwack
+{
+ int slot; /* next block to use */
+ ThwBlock blocks[EWinBlocks];
+ ushort hash[EWinBlocks][HashSize];
+ uchar data[EWinBlocks][ThwMaxBlock];
+};
+
+struct UnthwBlock
+{
+ ulong seq; /* sequence number for this data */
+ ushort maxoff; /* valid data in each block */
+ uchar *data;
+};
+
+struct Unthwack
+{
+ int slot; /* next block to use */
+ UnthwBlock blocks[DWinBlocks];
+ uchar data[DWinBlocks][ThwMaxBlock];
+};
+
+void thwackinit(Thwack*);
+void unthwackinit(Unthwack*);
+int thwack(Thwack*, uchar *dst, uchar *src, int nsrc, ulong seq, ulong stats[ThwStats]);
+void thwackack(Thwack*, ulong seq, ulong mask);
+int unthwack(Unthwack*, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq);
+ulong unthwackstate(Unthwack *ut, uchar *mask);
diff --git a/sys/src/9/port/tod.c b/sys/src/9/port/tod.c
new file mode 100755
index 000000000..424e0f290
--- /dev/null
+++ b/sys/src/9/port/tod.c
@@ -0,0 +1,315 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+/*
+ * Compute nanosecond epoch time from the fastest ticking clock
+ * on the system. Converting the time to nanoseconds requires
+ * the following formula
+ *
+ * t = (((1000000000<<31)/f)*ticks)>>31
+ *
+ * where
+ *
+ * 'f' is the clock frequency
+ * 'ticks' are clock ticks
+ *
+ * to avoid too much calculation in todget(), we calculate
+ *
+ * mult = (1000000000<<32)/f
+ *
+ * each time f is set. f is normally set by a user level
+ * program writing to /dev/fastclock. mul64fract will then
+ * take that fractional multiplier and a 64 bit integer and
+ * return the resulting integer product.
+ *
+ * We assume that the cpu's of a multiprocessor are synchronized.
+ * This assumption needs to be questioned with each new architecture.
+ */
+
+/* frequency of the tod clock */
+#define TODFREQ 1000000000ULL
+#define MicroFREQ 1000000ULL
+
+struct {
+ int init; /* true if initialized */
+ ulong cnt;
+ Lock;
+ uvlong multiplier; /* ns = off + (multiplier*ticks)>>31 */
+ uvlong divider; /* ticks = (divider*(ns-off))>>31 */
+ uvlong umultiplier; /* µs = (µmultiplier*ticks)>>31 */
+ uvlong udivider; /* ticks = (µdivider*µs)>>31 */
+ vlong hz; /* frequency of fast clock */
+ vlong last; /* last reading of fast clock */
+ vlong off; /* offset from epoch to last */
+ vlong lasttime; /* last return value from todget */
+ vlong delta; /* add 'delta' each slow clock tick from sstart to send */
+ ulong sstart; /* ... */
+ ulong send; /* ... */
+} tod;
+
+static void todfix(void);
+
+void
+todinit(void)
+{
+ if(tod.init)
+ return;
+ ilock(&tod);
+ tod.init = 1; /* prevent reentry via fastticks */
+ tod.last = fastticks((uvlong *)&tod.hz);
+ iunlock(&tod);
+ todsetfreq(tod.hz);
+ addclock0link(todfix, 100);
+}
+
+/*
+ * calculate multiplier
+ */
+void
+todsetfreq(vlong f)
+{
+ if (f <= 0)
+ panic("todsetfreq: freq %lld <= 0", f);
+ ilock(&tod);
+ tod.hz = f;
+
+ /* calculate multiplier for time conversion */
+ tod.multiplier = mk64fract(TODFREQ, f);
+ tod.divider = mk64fract(f, TODFREQ) + 1;
+ tod.umultiplier = mk64fract(MicroFREQ, f);
+ tod.udivider = mk64fract(f, MicroFREQ) + 1;
+ iunlock(&tod);
+}
+
+/*
+ * Set the time of day struct
+ */
+void
+todset(vlong t, vlong delta, int n)
+{
+ if(!tod.init)
+ todinit();
+
+ ilock(&tod);
+ if(t >= 0){
+ tod.off = t;
+ tod.last = fastticks(nil);
+ tod.lasttime = 0;
+ tod.delta = 0;
+ tod.sstart = tod.send;
+ } else {
+ if(n <= 0)
+ n = 1;
+ n *= HZ;
+ if(delta < 0 && n > -delta)
+ n = -delta;
+ if(delta > 0 && n > delta)
+ n = delta;
+ if (n == 0) {
+ iprint("todset: n == 0, delta == %lld\n", delta);
+ delta = 0;
+ } else
+ delta /= n;
+ tod.sstart = MACHP(0)->ticks;
+ tod.send = tod.sstart + n;
+ tod.delta = delta;
+ }
+ iunlock(&tod);
+}
+
+/*
+ * get time of day
+ */
+vlong
+todget(vlong *ticksp)
+{
+ uvlong x;
+ vlong ticks, diff;
+ ulong t;
+
+ if(!tod.init)
+ todinit();
+
+ /*
+ * we don't want time to pass twixt the measuring of fastticks
+ * and grabbing tod.last. Also none of the vlongs are atomic so
+ * we have to look at them inside the lock.
+ */
+ ilock(&tod);
+ tod.cnt++;
+ ticks = fastticks(nil);
+
+ /* add in correction */
+ if(tod.sstart != tod.send){
+ t = MACHP(0)->ticks;
+ if(t >= tod.send)
+ t = tod.send;
+ tod.off = tod.off + tod.delta*(t - tod.sstart);
+ tod.sstart = t;
+ }
+
+ /* convert to epoch */
+ diff = ticks - tod.last;
+ if(diff < 0)
+ diff = 0;
+ mul64fract(&x, diff, tod.multiplier);
+ x += tod.off;
+
+ /* time can't go backwards */
+ if(x < tod.lasttime)
+ x = tod.lasttime;
+ else
+ tod.lasttime = x;
+
+ iunlock(&tod);
+
+ if(ticksp != nil)
+ *ticksp = ticks;
+
+ return x;
+}
+
+/*
+ * convert time of day to ticks
+ */
+uvlong
+tod2fastticks(vlong ns)
+{
+ uvlong x;
+
+ ilock(&tod);
+ mul64fract(&x, ns-tod.off, tod.divider);
+ x += tod.last;
+ iunlock(&tod);
+ return x;
+}
+
+/*
+ * called regularly to avoid calculation overflows
+ */
+static void
+todfix(void)
+{
+ vlong ticks, diff;
+ uvlong x;
+
+ ticks = fastticks(nil);
+
+ diff = ticks - tod.last;
+ if(diff > tod.hz){
+ ilock(&tod);
+
+ /* convert to epoch */
+ mul64fract(&x, diff, tod.multiplier);
+if(x > 30000000000ULL) iprint("todfix %llud\n", x);
+ x += tod.off;
+
+ /* protect against overflows */
+ tod.last = ticks;
+ tod.off = x;
+
+ iunlock(&tod);
+ }
+}
+
+long
+seconds(void)
+{
+ return (vlong)todget(nil) / TODFREQ;
+}
+
+uvlong
+fastticks2us(uvlong ticks)
+{
+ uvlong res;
+
+ if(!tod.init)
+ todinit();
+ mul64fract(&res, ticks, tod.umultiplier);
+ return res;
+}
+
+uvlong
+us2fastticks(uvlong us)
+{
+ uvlong res;
+
+ if(!tod.init)
+ todinit();
+ mul64fract(&res, us, tod.udivider);
+ return res;
+}
+
+/*
+ * convert milliseconds to fast ticks
+ */
+uvlong
+ms2fastticks(ulong ms)
+{
+ if(!tod.init)
+ todinit();
+ return (tod.hz*ms)/1000ULL;
+}
+
+/*
+ * convert nanoseconds to fast ticks
+ */
+uvlong
+ns2fastticks(uvlong ns)
+{
+ uvlong res;
+
+ if(!tod.init)
+ todinit();
+ mul64fract(&res, ns, tod.divider);
+ return res;
+}
+
+/*
+ * convert fast ticks to ns
+ */
+uvlong
+fastticks2ns(uvlong ticks)
+{
+ uvlong res;
+
+ if(!tod.init)
+ todinit();
+ mul64fract(&res, ticks, tod.multiplier);
+ return res;
+}
+
+/*
+ * Make a 64 bit fixed point number that has a decimal point
+ * to the left of the low order 32 bits. This is used with
+ * mul64fract for converting twixt nanoseconds and fastticks.
+ *
+ * multiplier = (to<<32)/from
+ */
+uvlong
+mk64fract(uvlong to, uvlong from)
+{
+/*
+ int shift;
+
+ if(to == 0ULL)
+ return 0ULL;
+
+ shift = 0;
+ while(shift < 32 && to < (1ULL<<(32+24))){
+ to <<= 8;
+ shift += 8;
+ }
+ while(shift < 32 && to < (1ULL<<(32+31))){
+ to <<= 1;
+ shift += 1;
+ }
+
+ return (to/from)<<(32-shift);
+ */
+ return (to<<32) / from;
+}
diff --git a/sys/src/9/port/unthwack.c b/sys/src/9/port/unthwack.c
new file mode 100755
index 000000000..b60857596
--- /dev/null
+++ b/sys/src/9/port/unthwack.c
@@ -0,0 +1,298 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#include "thwack.h"
+
+enum
+{
+ DMaxFastLen = 7,
+ DBigLenCode = 0x3c, /* minimum code for large lenth encoding */
+ DBigLenBits = 6,
+ DBigLenBase = 1 /* starting items to encode for big lens */
+};
+
+static uchar lenval[1 << (DBigLenBits - 1)] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4,
+ 5,
+ 6,
+ 255,
+ 255
+};
+
+static uchar lenbits[] =
+{
+ 0, 0, 0,
+ 2, 3, 5, 5,
+};
+
+static uchar offbits[16] =
+{
+ 5, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 12, 13
+};
+
+static ushort offbase[16] =
+{
+ 0, 0x20,
+ 0x40, 0x60,
+ 0x80, 0xc0,
+ 0x100, 0x180,
+ 0x200, 0x300,
+ 0x400, 0x600,
+ 0x800, 0xc00,
+ 0x1000,
+ 0x2000
+};
+
+void
+unthwackinit(Unthwack *ut)
+{
+ int i;
+
+ memset(ut, 0, sizeof *ut);
+ for(i = 0; i < DWinBlocks; i++)
+ ut->blocks[i].data = ut->data[i];
+}
+
+ulong
+unthwackstate(Unthwack *ut, uchar *mask)
+{
+ ulong bseq, seq;
+ int slot, m;
+
+ seq = ~0UL;
+ m = 0;
+ slot = ut->slot;
+ for(;;){
+ slot--;
+ if(slot < 0)
+ slot += DWinBlocks;
+ if(slot == ut->slot)
+ break;
+ if(ut->blocks[slot].maxoff == 0)
+ continue;
+ bseq = ut->blocks[slot].seq;
+ if(seq == ~0UL)
+ seq = bseq;
+ else if(seq - bseq > MaxSeqMask)
+ break;
+ else
+ m |= 1 << (seq - bseq - 1);
+ }
+ *mask = m;
+ return seq;
+}
+
+/*
+ * insert this block in it's correct sequence number order.
+ * replace the oldest block, which is always pointed to by ut->slot.
+ * the encoder doesn't use a history at wraparound,
+ * so don't worry about that case.
+ */
+static int
+unthwackinsert(Unthwack *ut, int len, ulong seq)
+{
+ uchar *d;
+ int slot, tslot;
+
+ tslot = ut->slot;
+ for(;;){
+ slot = tslot - 1;
+ if(slot < 0)
+ slot += DWinBlocks;
+ if(ut->blocks[slot].seq <= seq || ut->blocks[slot].maxoff == 0)
+ break;
+ d = ut->blocks[tslot].data;
+ ut->blocks[tslot] = ut->blocks[slot];
+ ut->blocks[slot].data = d;
+ tslot = slot;
+ }
+ ut->blocks[tslot].seq = seq;
+ ut->blocks[tslot].maxoff = len;
+
+ ut->slot++;
+ if(ut->slot >= DWinBlocks)
+ ut->slot = 0;
+
+ ut->blocks[ut->slot].seq = ~0UL;
+ ut->blocks[ut->slot].maxoff = 0;
+
+ return tslot;
+}
+
+int
+unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
+{
+ UnthwBlock blocks[CompBlocks], *b, *eblocks;
+ uchar *s, *d, *dmax, *smax, lit;
+ ulong cmask, cseq, bseq, utbits;
+ int i, off, len, bits, slot, use, code, utnbits, overbits, lithist;
+
+ if(nsrc < 4 || nsrc > ThwMaxBlock)
+ return -1;
+
+ slot = ut->slot;
+ b = blocks;
+ *b = ut->blocks[slot];
+ d = b->data;
+ dmax = d + ndst;
+
+ /*
+ * set up the history blocks
+ */
+ cseq = seq - src[0];
+ cmask = src[1];
+ b++;
+ while(cseq != seq && b < blocks + CompBlocks){
+ slot--;
+ if(slot < 0)
+ slot += DWinBlocks;
+ if(slot == ut->slot)
+ break;
+ bseq = ut->blocks[slot].seq;
+ if(bseq == cseq){
+ *b = ut->blocks[slot];
+ b++;
+ if(cmask == 0){
+ cseq = seq;
+ break;
+ }
+ do{
+ bits = cmask & 1;
+ cseq--;
+ cmask >>= 1;
+ }while(!bits);
+ }
+ }
+ eblocks = b;
+ if(cseq != seq){
+ print("unthwack: blocks dropped: seq=%ld cseq=%ld %d cmask=%#lx %#x\n",
+ seq, cseq, src[0], cmask, src[1]);
+ return -2;
+ }
+
+ smax = src + nsrc;
+ src += 2;
+ utnbits = 0;
+ utbits = 0;
+ overbits = 0;
+ lithist = ~0;
+ while(src < smax || utnbits - overbits >= MinDecode){
+ while(utnbits <= 24){
+ utbits <<= 8;
+ if(src < smax)
+ utbits |= *src++;
+ else
+ overbits += 8;
+ utnbits += 8;
+ }
+
+ /*
+ * literal
+ */
+ len = lenval[(utbits >> (utnbits - 5)) & 0x1f];
+ if(len == 0){
+ if(lithist & 0xf){
+ utnbits -= 9;
+ lit = (utbits >> utnbits) & 0xff;
+ lit &= 255;
+ }else{
+ utnbits -= 8;
+ lit = (utbits >> utnbits) & 0x7f;
+ if(lit < 32){
+ if(lit < 24){
+ utnbits -= 2;
+ lit = (lit << 2) | ((utbits >> utnbits) & 3);
+ }else{
+ utnbits -= 3;
+ lit = (lit << 3) | ((utbits >> utnbits) & 7);
+ }
+ lit = (lit - 64) & 0xff;
+ }
+ }
+ if(d >= dmax)
+ return -1;
+ *d++ = lit;
+ lithist = (lithist << 1) | (lit < 32) | (lit > 127);
+ blocks->maxoff++;
+ continue;
+ }
+
+ /*
+ * length
+ */
+ if(len < 255)
+ utnbits -= lenbits[len];
+ else{
+ utnbits -= DBigLenBits;
+ code = ((utbits >> utnbits) & ((1 << DBigLenBits) - 1)) - DBigLenCode;
+ len = DMaxFastLen;
+ use = DBigLenBase;
+ bits = (DBigLenBits & 1) ^ 1;
+ while(code >= use){
+ len += use;
+ code -= use;
+ code <<= 1;
+ utnbits--;
+ if(utnbits < 0)
+ return -1;
+ code |= (utbits >> utnbits) & 1;
+ use <<= bits;
+ bits ^= 1;
+ }
+ len += code;
+
+ while(utnbits <= 24){
+ utbits <<= 8;
+ if(src < smax)
+ utbits |= *src++;
+ else
+ overbits += 8;
+ utnbits += 8;
+ }
+ }
+
+ /*
+ * offset
+ */
+ utnbits -= 4;
+ bits = (utbits >> utnbits) & 0xf;
+ off = offbase[bits];
+ bits = offbits[bits];
+
+ utnbits -= bits;
+ off |= (utbits >> utnbits) & ((1 << bits) - 1);
+ off++;
+
+ b = blocks;
+ while(off > b->maxoff){
+ off -= b->maxoff;
+ b++;
+ if(b >= eblocks)
+ return -1;
+ }
+ if(d + len > dmax
+ || b != blocks && len > off)
+ return -1;
+ s = b->data + b->maxoff - off;
+ blocks->maxoff += len;
+
+ for(i = 0; i < len; i++)
+ d[i] = s[i];
+ d += len;
+ }
+ if(utnbits < overbits)
+ return -1;
+
+ len = d - blocks->data;
+ memmove(dst, blocks->data, len);
+
+ unthwackinsert(ut, len, seq);
+
+ return len;
+}
diff --git a/sys/src/9/port/usb.h b/sys/src/9/port/usb.h
new file mode 100755
index 000000000..11b00212f
--- /dev/null
+++ b/sys/src/9/port/usb.h
@@ -0,0 +1,196 @@
+/*
+ * common USB definitions.
+ */
+#define dprint if(debug)print
+#define ddprint if(debug>1)print
+#define deprint if(debug || ep->debug)print
+#define ddeprint if(debug>1 || ep->debug>1)print
+
+#define GET2(p) ((((p)[1]&0xFF)<<8)|((p)[0]&0xFF))
+#define PUT2(p,v) {((p)[0] = (v)); ((p)[1] = (v)>>8);}
+
+typedef struct Udev Udev; /* USB device */
+typedef struct Ep Ep; /* Endpoint */
+typedef struct Hci Hci; /* Host Controller Interface */
+typedef struct Hciimpl Hciimpl; /* Link to the controller impl. */
+
+enum
+{
+ /* fundamental constants */
+ Ndeveps = 16, /* max nb. of endpoints per device */
+
+ /* tunable parameters */
+ Nhcis = 16, /* max nb. of HCIs */
+ Neps = 64, /* max nb. of endpoints */
+ Maxctllen = 32*1024, /* max allowed sized for ctl. xfers; see Maxdevconf */
+ Xfertmout = 2000, /* default request time out (ms) */
+
+ /* transfer types. keep this order */
+ Tnone = 0, /* no tranfer type configured */
+ Tctl, /* wr req + rd/wr data + wr/rd sts */
+ Tiso, /* stream rd or wr (real time) */
+ Tbulk, /* stream rd or wr */
+ Tintr, /* msg rd or wr */
+ Nttypes, /* number of transfer types */
+
+ Epmax = 0xF, /* max ep. addr */
+ Devmax = 0x7F, /* max dev. addr */
+
+ /* Speeds */
+ Fullspeed = 0,
+ Lowspeed,
+ Highspeed,
+ Nospeed,
+
+ /* request type */
+ Rh2d = 0<<7,
+ Rd2h = 1<<7,
+ Rstd = 0<<5,
+ Rclass = 1<<5,
+ Rdev = 0,
+ Rep = 2,
+ Rother = 3,
+
+ /* req offsets */
+ Rtype = 0,
+ Rreq = 1,
+ Rvalue = 2,
+ Rindex = 4,
+ Rcount = 6,
+ Rsetuplen = 8,
+
+ /* standard requests */
+ Rgetstatus = 0,
+ Rclearfeature = 1,
+ Rsetfeature = 3,
+ Rsetaddr = 5,
+ Rgetdesc = 6,
+
+ /* device states */
+ Dconfig = 0, /* configuration in progress */
+ Denabled, /* address assigned */
+ Ddetach, /* device is detached */
+ Dreset, /* its port is being reset */
+
+ /* (root) Hub reply to port status (reported to usbd) */
+ HPpresent = 0x1,
+ HPenable = 0x2,
+ HPsuspend = 0x4,
+ HPovercurrent = 0x8,
+ HPreset = 0x10,
+ HPpower = 0x100,
+ HPslow = 0x200,
+ HPhigh = 0x400,
+ HPstatuschg = 0x10000,
+ HPchange = 0x20000,
+};
+
+/*
+ * Services provided by the driver.
+ * epopen allocates hardware structures to prepare the endpoint
+ * for I/O. This happens when the user opens the data file.
+ * epclose releases them. This happens when the data file is closed.
+ * epwrite tries to write the given bytes, waiting until all of them
+ * have been written (or failed) before returning; but not for Iso.
+ * epread does the same for reading.
+ * It can be assumed that endpoints are DMEXCL but concurrent
+ * read/writes may be issued and the controller must take care.
+ * For control endpoints, device-to-host requests must be followed by
+ * a read of the expected length if needed.
+ * The port requests are called when usbd issues commands for root
+ * hubs. Port status must return bits as a hub request would do.
+ * Toggle handling and other details are left for the controller driver
+ * to avoid mixing too much the controller and the comon device.
+ * While an endpoint is closed, its toggles are saved in the Ep struct.
+ */
+struct Hciimpl
+{
+ void *aux; /* for controller info */
+ void (*init)(Hci*); /* init. controller */
+ void (*dump)(Hci*); /* debug */
+ void (*interrupt)(Ureg*, void*); /* service interrupt */
+ void (*epopen)(Ep*); /* prepare ep. for I/O */
+ void (*epclose)(Ep*); /* terminate I/O on ep. */
+ long (*epread)(Ep*,void*,long); /* transmit data for ep */
+ long (*epwrite)(Ep*,void*,long); /* receive data for ep */
+ char* (*seprintep)(char*,char*,Ep*); /* debug */
+ int (*portenable)(Hci*, int, int); /* enable/disable port */
+ int (*portreset)(Hci*, int, int); /* set/clear port reset */
+ int (*portstatus)(Hci*, int); /* get port status */
+ void (*shutdown)(Hci*); /* shutdown for reboot */
+ void (*debug)(Hci*, int); /* set/clear debug flag */
+};
+
+struct Hci
+{
+ ISAConf; /* hardware info */
+ int tbdf; /* type+busno+devno+funcno */
+ int ctlrno; /* controller number */
+ int nports; /* number of ports in hub */
+ int highspeed;
+ Hciimpl; /* HCI driver */
+};
+
+/*
+ * USB endpoint.
+ * All endpoints are kept in a global array. The first
+ * block of fields is constant after endpoint creation.
+ * The rest is configuration information given to all controllers.
+ * The first endpoint for a device (known as ep0) represents the
+ * device and is used to configure it and create other endpoints.
+ * Its QLock also protects per-device data in dev.
+ * See Hciimpl for clues regarding how this is used by controllers.
+ */
+struct Ep
+{
+ Ref; /* one per fid (and per dev ep for ep0s) */
+
+ /* const once inited. */
+ int idx; /* index in global eps array */
+ int nb; /* endpoint number in device */
+ Hci* hp; /* HCI it belongs to */
+ Udev* dev; /* device for the endpoint */
+ Ep* ep0; /* control endpoint for its device */
+
+ QLock; /* protect fields below */
+ char* name; /* for ep file names at #u/ */
+ int inuse; /* endpoint is open */
+ int mode; /* OREAD, OWRITE, or ORDWR */
+ int clrhalt; /* true if halt was cleared on ep. */
+ int debug; /* per endpoint debug flag */
+ char* info; /* for humans to read */
+ long maxpkt; /* maximum packet size */
+ int ttype; /* tranfer type */
+ ulong load; /* in µs, for a fransfer of maxpkt bytes */
+ void* aux; /* for controller specific info */
+ int rhrepl; /* fake root hub replies */
+ int toggle[2]; /* saved toggles (while ep is not in use) */
+ long pollival; /* poll interval ([µ]frames; intr/iso) */
+ long hz; /* poll frequency (iso) */
+ long samplesz; /* sample size (iso) */
+ int ntds; /* nb. of Tds per µframe */
+ int tmout; /* 0 or timeout for transfers (ms) */
+};
+
+/*
+ * Per-device configuration and cached list of endpoints.
+ * eps[0]->QLock protects it.
+ */
+struct Udev
+{
+ int nb; /* USB device number */
+ int state; /* state for the device */
+ int ishub; /* hubs can allocate devices */
+ int isroot; /* is a root hub */
+ int speed; /* Full/Low/High/No -speed */
+ int hub; /* dev number for the parent hub */
+ int port; /* port number in the parent hub */
+ Ep* eps[Ndeveps]; /* end points for this device (cached) */
+};
+
+void addhcitype(char *type, int (*reset)(Hci*));
+
+extern char *usbmodename[];
+extern char Estalled[];
+
+extern char *seprintdata(char*,char*,uchar*,int);
diff --git a/sys/src/9/port/usbehci.c b/sys/src/9/port/usbehci.c
new file mode 100755
index 000000000..e6ff879e3
--- /dev/null
+++ b/sys/src/9/port/usbehci.c
@@ -0,0 +1,3204 @@
+/*
+ * USB Enhanced Host Controller Interface (EHCI) driver
+ * High speed USB 2.0.
+ *
+ * Note that all of our unlock routines call coherence.
+ *
+ * BUGS:
+ * - Too many delays and ilocks.
+ * - bandwidth admission control must be done per-frame.
+ * - requires polling (some controllers miss interrupts).
+ * - must warn of power overruns.
+ */
+
+#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/usb.h"
+#include "usbehci.h"
+#include "uncached.h"
+
+#define diprint if(ehcidebug || iso->debug)print
+#define ddiprint if(ehcidebug>1 || iso->debug>1)print
+#define dqprint if(ehcidebug || (qh->io && qh->io->debug))print
+#define ddqprint if(ehcidebug>1 || (qh->io && qh->io->debug>1))print
+
+#define TRUNC(x, sz) ((x) & ((sz)-1))
+#define LPTR(q) ((ulong*)KADDR((q) & ~0x1F))
+
+typedef struct Ctlio Ctlio;
+typedef union Ed Ed;
+typedef struct Edpool Edpool;
+typedef struct Itd Itd;
+typedef struct Qio Qio;
+typedef struct Qtd Qtd;
+typedef struct Sitd Sitd;
+typedef struct Td Td;
+
+/*
+ * EHCI interface registers and bits
+ */
+enum
+{
+ /* Queue states (software) */
+ Qidle = 0,
+ Qinstall,
+ Qrun,
+ Qdone,
+ Qclose,
+ Qfree,
+
+ Enabledelay = 100, /* waiting for a port to enable */
+ Abortdelay = 5, /* delay after cancelling Tds (ms) */
+
+ Incr = 64, /* for pools of Tds, Qhs, etc. */
+ Align = 128, /* in bytes for all those descriptors */
+
+ /* Keep them as a power of 2, lower than ctlr->nframes */
+ /* Also, keep Nisoframes >= Nintrleafs */
+ Nintrleafs = 32, /* nb. of leaf frames in intr. tree */
+ Nisoframes = 64, /* nb. of iso frames (in window) */
+
+ /*
+ * HW constants
+ */
+
+ /* Itd bits (csw[]) */
+ Itdactive = 0x80000000, /* execution enabled */
+ Itddberr = 0x40000000, /* data buffer error */
+ Itdbabble = 0x20000000, /* babble error */
+ Itdtrerr = 0x10000000, /* transaction error */
+ Itdlenshift = 16, /* transaction length */
+ Itdlenmask = 0xFFF,
+ Itdioc = 0x00008000, /* interrupt on complete */
+ Itdpgshift = 12, /* page select field */
+ Itdoffshift = 0, /* transaction offset */
+ /* Itd bits, buffer[] */
+ Itdepshift = 8, /* endpoint address (buffer[0]) */
+ Itddevshift = 0, /* device address (buffer[0]) */
+ Itdin = 0x800, /* is input (buffer[1]) */
+ Itdout = 0,
+ Itdmaxpktshift = 0, /* max packet (buffer[1]) */
+ Itdntdsshift = 0, /* nb. of tds per µframe (buffer[2]) */
+
+ Itderrors = Itddberr|Itdbabble|Itdtrerr,
+
+ /* Sitd bits (epc) */
+ Stdin = 0x80000000, /* input direction */
+ Stdportshift = 24, /* hub port number */
+ Stdhubshift = 16, /* hub address */
+ Stdepshift = 8, /* endpoint address */
+ Stddevshift = 0, /* device address */
+ /* Sitd bits (mfs) */
+ Stdssmshift = 0, /* split start mask */
+ Stdscmshift = 8, /* split complete mask */
+ /* Sitd bits (csw) */
+ Stdioc = 0x80000000, /* interrupt on complete */
+ Stdpg = 0x40000000, /* page select */
+ Stdlenshift = 16, /* total bytes to transfer */
+ Stdlenmask = 0x3FF,
+ Stdactive = 0x00000080, /* active */
+ Stderr = 0x00000040, /* tr. translator error */
+ Stddberr = 0x00000020, /* data buffer error */
+ Stdbabble = 0x00000010, /* babble error */
+ Stdtrerr = 0x00000008, /* transaction error */
+ Stdmmf = 0x00000004, /* missed µframe */
+ Stddcs = 0x00000002, /* do complete split */
+
+ Stderrors = Stderr|Stddberr|Stdbabble|Stdtrerr|Stdmmf,
+
+ /* Sitd bits buffer[1] */
+ Stdtpall = 0x00000000, /* all payload here (188 bytes) */
+ Stdtpbegin = 0x00000008, /* first payload for fs trans. */
+ Stdtcntmask = 0x00000007, /* T-count */
+
+ /* Td bits (csw) */
+ Tddata1 = 0x80000000, /* data toggle 1 */
+ Tddata0 = 0x00000000, /* data toggle 0 */
+ Tdlenshift = 16, /* total bytes to transfer */
+ Tdlenmask = 0x7FFF,
+ Tdmaxpkt = 0x5000, /* max buffer for a Td */
+ Tdioc = 0x00008000, /* interrupt on complete */
+ Tdpgshift = 12, /* current page */
+ Tdpgmask = 7,
+ Tderr1 = 0x00000400, /* bit 0 of error counter */
+ Tderr2 = 0x00000800, /* bit 1 of error counter */
+ Tdtokout = 0x00000000, /* direction out */
+ Tdtokin = 0x00000100, /* direction in */
+ Tdtoksetup = 0x00000200, /* setup packet */
+ Tdtok = 0x00000300, /* token bits */
+ Tdactive = 0x00000080, /* active */
+ Tdhalt = 0x00000040, /* halted */
+ Tddberr = 0x00000020, /* data buffer error */
+ Tdbabble = 0x00000010, /* babble error */
+ Tdtrerr = 0x00000008, /* transaction error */
+ Tdmmf = 0x00000004, /* missed µframe */
+ Tddcs = 0x00000002, /* do complete split */
+ Tdping = 0x00000001, /* do ping */
+
+ Tderrors = Tdhalt|Tddberr|Tdbabble|Tdtrerr|Tdmmf,
+
+ /* Qh bits (eps0) */
+ Qhrlcmask = 0xF, /* nak reload count */
+ Qhrlcshift = 28, /* nak reload count */
+ Qhnhctl = 0x08000000, /* not-high speed ctl */
+ Qhmplmask = 0x7FF, /* max packet */
+ Qhmplshift = 16,
+ Qhhrl = 0x00008000, /* head of reclamation list */
+ Qhdtc = 0x00004000, /* data toggle ctl. */
+ Qhint = 0x00000080, /* inactivate on next transition */
+ Qhspeedmask = 0x00003000, /* speed bits */
+ Qhfull = 0x00000000, /* full speed */
+ Qhlow = 0x00001000, /* low speed */
+ Qhhigh = 0x00002000, /* high speed */
+
+ /* Qh bits (eps1) */
+ Qhmultshift = 30, /* multiple tds per µframe */
+ Qhmultmask = 3,
+ Qhportshift = 23, /* hub port number */
+ Qhhubshift = 16, /* hub address */
+ Qhscmshift = 8, /* split completion mask bits */
+ Qhismshift = 0, /* interrupt sched. mask bits */
+};
+
+/*
+ * Endpoint tree (software)
+ */
+struct Qtree
+{
+ int nel;
+ int depth;
+ ulong* bw;
+ Qh** root;
+};
+
+/*
+ * One per endpoint per direction, to control I/O.
+ */
+struct Qio
+{
+ QLock; /* for the entire I/O process */
+ Rendez; /* wait for completion */
+ Qh* qh; /* Td list (field const after init) */
+ int usbid; /* usb address for endpoint/device */
+ int toggle; /* Tddata0/Tddata1 */
+ int tok; /* Tdtoksetup, Tdtokin, Tdtokout */
+ ulong iotime; /* last I/O time; to hold interrupt polls */
+ int debug; /* debug flag from the endpoint */
+ char* err; /* error string */
+ char* tag; /* debug (no room in Qh for this) */
+ ulong bw;
+};
+
+struct Ctlio
+{
+ Qio; /* a single Qio for each RPC */
+ uchar* data; /* read from last ctl req. */
+ int ndata; /* number of bytes read */
+};
+
+struct Isoio
+{
+ QLock;
+ Rendez; /* wait for space/completion/errors */
+ int usbid; /* address used for device/endpoint */
+ int tok; /* Tdtokin or Tdtokout */
+ int state; /* Qrun -> Qdone -> Qrun... -> Qclose */
+ int nframes; /* number of frames ([S]Itds) used */
+ uchar* data; /* iso data buffers if not embedded */
+ char* err; /* error string */
+ int nerrs; /* nb of consecutive I/O errors */
+ ulong maxsize; /* ntds * ep->maxpkt */
+ long nleft; /* number of bytes left from last write */
+ int debug; /* debug flag from the endpoint */
+ int hs; /* is high speed? */
+ Isoio* next; /* in list of active Isoios */
+ ulong td0frno; /* first frame used in ctlr */
+ union{
+ Itd* tdi; /* next td processed by interrupt */
+ Sitd* stdi;
+ };
+ union{
+ Itd* tdu; /* next td for user I/O in tdps */
+ Sitd* stdu;
+ };
+ union{
+ Itd** itdps; /* itdps[i]: ptr to Itd for i-th frame or nil */
+ Sitd** sitdps; /* sitdps[i]: ptr to Sitd for i-th frame or nil */
+ ulong** tdps; /* same thing, as seen by hw */
+ };
+};
+
+struct Edpool
+{
+ Lock;
+ Ed* free;
+ int nalloc;
+ int ninuse;
+ int nfree;
+};
+
+/*
+ * We use the 64-bit version for Itd, Sitd, Td, and Qh.
+ * If the ehci is 64-bit capable it assumes we are using those
+ * structures even when the system is 32 bits.
+ */
+
+/*
+ * Iso transfer descriptor. hw: 92 bytes, 108 bytes total
+ * aligned to 32.
+ */
+struct Itd
+{
+ ulong link; /* to next hw struct */
+ ulong csw[8]; /* sts/length/pg/off. updated by hw */
+ ulong buffer[7]; /* buffer pointers, addrs, maxsz */
+ ulong xbuffer[7]; /* high 32 bits of buffer for 64-bits */
+
+ ulong _pad0; /* pad to next cache line */
+ /* cache-line boundary here */
+
+ /* software */
+ Itd* next;
+ ulong ndata; /* number of bytes in data */
+ ulong mdata; /* max number of bytes in data */
+ uchar* data;
+};
+
+/*
+ * Split transaction iso transfer descriptor.
+ * hw: 36 bytes, 52 bytes total. aligned to 32.
+ */
+struct Sitd
+{
+ ulong link; /* to next hw struct */
+ ulong epc; /* static endpoint state. addrs */
+ ulong mfs; /* static endpoint state. µ-frame sched. */
+ ulong csw; /* transfer state. updated by hw */
+ ulong buffer[2]; /* buf. ptr/offset. offset updated by hw */
+ /* buf ptr/TP/Tcnt. TP/Tcnt updated by hw */
+ ulong blink; /* back pointer */
+ /* cache-line boundary after xbuffer[0] */
+ ulong xbuffer[2]; /* high 32 bits of buffer for 64-bits */
+
+ /* software */
+ Sitd* next;
+ ulong ndata; /* number of bytes in data */
+ ulong mdata; /* max number of bytes in data */
+ uchar* data;
+};
+
+/*
+ * Queue element transfer descriptor.
+ * hw: first 52 bytes, total 68+sbuff bytes. aligned to 32 bytes.
+ */
+struct Td
+{
+ ulong nlink; /* to next Td */
+ ulong alink; /* alternate link to next Td */
+ ulong csw; /* cmd/sts. updated by hw */
+ ulong buffer[5]; /* buf ptrs. offset updated by hw */
+ /* cache-line boundary here */
+ ulong xbuffer[5]; /* high 32 bits of buffer for 64-bits */
+
+ /* software */
+ Td* next; /* in qh or Isoio or free list */
+ ulong ndata; /* bytes available/used at data */
+ uchar* data; /* pointer to actual data */
+ uchar* buff; /* allocated data buffer or nil */
+ uchar sbuff[1]; /* first byte of embedded buffer */
+};
+
+/*
+ * Queue head. Aligned to 32 bytes.
+ * hw: first 68 bytes, 92 total.
+ */
+struct Qh
+{
+ ulong link; /* to next Qh in round robin */
+ ulong eps0; /* static endpoint state. addrs */
+ ulong eps1; /* static endpoint state. µ-frame sched. */
+
+ /* updated by hw */
+ ulong tclink; /* current Td (No Term bit here!) */
+ ulong nlink; /* to next Td */
+ ulong alink; /* alternate link to next Td */
+ ulong csw; /* cmd/sts. updated by hw */
+ /* cache-line boundary after buffer[0] */
+ ulong buffer[5]; /* buf ptrs. offset updated by hw */
+ ulong xbuffer[5]; /* high 32 bits of buffer for 64-bits */
+
+ /* software */
+ Qh* next; /* in controller list/tree of Qhs */
+ int state; /* Qidle -> Qinstall -> Qrun -> Qdone | Qclose */
+ Qio* io; /* for this queue */
+ Td* tds; /* for this queue */
+ int sched; /* slot for for intr. Qhs */
+ Qh* inext; /* next in list of intr. qhs */
+};
+
+/*
+ * We can avoid frame span traversal nodes if we don't span frames.
+ * Just schedule transfers that can fit on the current frame and
+ * wait a little bit otherwise.
+ */
+
+/*
+ * Software. Ehci descriptors provided by pool.
+ * There are soo few because we avoid using Fstn.
+ */
+union Ed
+{
+ Ed* next; /* in free list */
+ Qh qh;
+ Td td;
+ Itd itd;
+ Sitd sitd;
+ uchar align[Align];
+};
+
+int ehcidebug;
+
+static Edpool edpool;
+static char Ebug[] = "not yet implemented";
+static char* qhsname[] = { "idle", "install", "run", "done", "close", "FREE" };
+
+Ecapio* ehcidebugcapio;
+int ehcidebugport;
+
+void
+ehcirun(Ctlr *ctlr, int on)
+{
+ int i;
+ Eopio *opio;
+
+ ddprint("ehci %#p %s\n", ctlr->capio, on ? "starting" : "halting");
+ opio = ctlr->opio;
+ if(on)
+ opio->cmd |= Crun;
+ else
+ opio->cmd = Cstop;
+ coherence();
+ for(i = 0; i < 100; i++)
+ if(on == 0 && (opio->sts & Shalted) != 0)
+ break;
+ else if(on != 0 && (opio->sts & Shalted) == 0)
+ break;
+ else
+ delay(1);
+ if(i == 100)
+ print("ehci %#p %s cmd timed out\n",
+ ctlr->capio, on ? "run" : "halt");
+ ddprint("ehci %#p cmd %#lux sts %#lux\n",
+ ctlr->capio, opio->cmd, opio->sts);
+}
+
+static void*
+edalloc(void)
+{
+ Ed *ed, *pool;
+ int i;
+
+ lock(&edpool);
+ if(edpool.free == nil){
+ pool = xspanalloc(Incr*sizeof(Ed), Align, 0);
+ if(pool == nil)
+ panic("edalloc");
+ for(i=Incr; --i>=0;){
+ pool[i].next = edpool.free;
+ edpool.free = &pool[i];
+ }
+ edpool.nalloc += Incr;
+ edpool.nfree += Incr;
+ dprint("ehci: edalloc: %d eds\n", edpool.nalloc);
+ }
+ ed = edpool.free;
+ edpool.free = ed->next;
+ edpool.ninuse++;
+ edpool.nfree--;
+ unlock(&edpool);
+
+ memset(ed, 0, sizeof(Ed)); /* safety */
+ assert(((ulong)ed & 0xF) == 0);
+ return ed;
+}
+
+static void
+edfree(void *a)
+{
+ Ed *ed;
+
+ ed = a;
+ lock(&edpool);
+ ed->next = edpool.free;
+ edpool.free = ed;
+ edpool.ninuse--;
+ edpool.nfree++;
+ unlock(&edpool);
+}
+
+/*
+ * Allocate and do some initialization.
+ * Free after releasing buffers used.
+ */
+
+static Itd*
+itdalloc(void)
+{
+ Itd *td;
+
+ td = edalloc();
+ td->link = Lterm;
+ return td;
+}
+
+static void
+itdfree(Itd *td)
+{
+ edfree(td);
+}
+
+static Sitd*
+sitdalloc(void)
+{
+ Sitd *td;
+
+ td = edalloc();
+ td->link = td->blink = Lterm;
+ return td;
+}
+
+static void
+sitdfree(Sitd *td)
+{
+ edfree(td);
+}
+
+static Td*
+tdalloc(void)
+{
+ Td *td;
+
+ td = edalloc();
+ td->nlink = td->alink = Lterm;
+ return td;
+}
+
+static void
+tdfree(Td *td)
+{
+ if(td == nil)
+ return;
+ free(td->buff);
+ edfree(td);
+}
+
+static void
+tdlinktd(Td *td, Td *next)
+{
+ td->next = next;
+ td->alink = Lterm;
+ if(next == nil)
+ td->nlink = Lterm;
+ else
+ td->nlink = PADDR(next);
+ coherence();
+}
+
+static Qh*
+qhlinkqh(Qh *qh, Qh *next)
+{
+ qh->next = next;
+ qh->link = PADDR(next)|Lqh;
+ coherence();
+ return qh;
+}
+
+static void
+qhsetaddr(Qh *qh, ulong addr)
+{
+ ulong eps0;
+
+ eps0 = qh->eps0 & ~((Epmax<<8)|Devmax);
+ qh->eps0 = eps0 | addr & Devmax | ((addr >> 7) & Epmax) << 8;
+ coherence();
+}
+
+/*
+ * return smallest power of 2 <= n
+ */
+static int
+flog2lower(int n)
+{
+ int i;
+
+ for(i = 0; (1 << (i + 1)) <= n; i++)
+ ;
+ return i;
+}
+
+static int
+pickschedq(Qtree *qt, int pollival, ulong bw, ulong limit)
+{
+ int i, j, d, upperb, q;
+ ulong best, worst, total;
+
+ d = flog2lower(pollival);
+ if(d > qt->depth)
+ d = qt->depth;
+ q = -1;
+ worst = 0;
+ best = ~0;
+ upperb = (1 << (d+1)) - 1;
+ for(i = (1 << d) - 1; i < upperb; i++){
+ total = qt->bw[0];
+ for(j = i; j > 0; j = (j - 1) / 2)
+ total += qt->bw[j];
+ if(total < best){
+ best = total;
+ q = i;
+ }
+ if(total > worst)
+ worst = total;
+ }
+ if(worst + bw >= limit)
+ return -1;
+ return q;
+}
+
+static int
+schedq(Ctlr *ctlr, Qh *qh, int pollival)
+{
+ int q;
+ Qh *tqh;
+ ulong bw;
+
+ bw = qh->io->bw;
+ q = pickschedq(ctlr->tree, pollival, 0, ~0);
+ ddqprint("ehci: sched %#p q %d, ival %d, bw %uld\n",
+ qh->io, q, pollival, bw);
+ if(q < 0){
+ print("ehci: no room for ed\n");
+ return -1;
+ }
+ ctlr->tree->bw[q] += bw;
+ tqh = ctlr->tree->root[q];
+ qh->sched = q;
+ qhlinkqh(qh, tqh->next);
+ qhlinkqh(tqh, qh);
+ coherence();
+ qh->inext = ctlr->intrqhs;
+ ctlr->intrqhs = qh;
+ coherence();
+ return 0;
+}
+
+static void
+unschedq(Ctlr *ctlr, Qh *qh)
+{
+ int q;
+ Qh *prev, *this, *next;
+ Qh **l;
+ ulong bw;
+
+ bw = qh->io->bw;
+ q = qh->sched;
+ if(q < 0)
+ return;
+ ctlr->tree->bw[q] -= bw;
+
+ prev = ctlr->tree->root[q];
+ this = prev->next;
+ while(this != nil && this != qh){
+ prev = this;
+ this = this->next;
+ }
+ if(this == nil)
+ print("ehci: unschedq %d: not found\n", q);
+ else{
+ next = this->next;
+ qhlinkqh(prev, next);
+ }
+ for(l = &ctlr->intrqhs; *l != nil; l = &(*l)->inext)
+ if(*l == qh){
+ *l = (*l)->inext;
+ return;
+ }
+ print("ehci: unschedq: qh %#p not found\n", qh);
+}
+
+static ulong
+qhmaxpkt(Qh *qh)
+{
+ return (qh->eps0 >> Qhmplshift) & Qhmplmask;
+}
+
+static void
+qhsetmaxpkt(Qh *qh, int maxpkt)
+{
+ ulong eps0;
+
+ eps0 = qh->eps0 & ~(Qhmplmask << Qhmplshift);
+ qh->eps0 = eps0 | (maxpkt & Qhmplmask) << Qhmplshift;
+ coherence();
+}
+
+/*
+ * Initialize the round-robin circular list of ctl/bulk Qhs
+ * if ep is nil. Otherwise, allocate and link a new Qh in the ctlr.
+ */
+static Qh*
+qhalloc(Ctlr *ctlr, Ep *ep, Qio *io, char* tag)
+{
+ Qh *qh;
+ int ttype;
+
+ qh = edalloc();
+ qh->nlink = Lterm;
+ qh->alink = Lterm;
+ qh->csw = Tdhalt;
+ qh->state = Qidle;
+ qh->sched = -1;
+ qh->io = io;
+ if(ep != nil){
+ qh->eps0 = 0;
+ qhsetmaxpkt(qh, ep->maxpkt);
+ if(ep->dev->speed == Lowspeed)
+ qh->eps0 |= Qhlow;
+ if(ep->dev->speed == Highspeed)
+ qh->eps0 |= Qhhigh;
+ else if(ep->ttype == Tctl)
+ qh->eps0 |= Qhnhctl;
+ qh->eps0 |= Qhdtc | 8 << Qhrlcshift; /* 8 naks max */
+ coherence();
+ qhsetaddr(qh, io->usbid);
+ qh->eps1 = (ep->ntds & Qhmultmask) << Qhmultshift;
+ qh->eps1 |= ep->dev->port << Qhportshift;
+ qh->eps1 |= ep->dev->hub << Qhhubshift;
+ qh->eps1 |= 034 << Qhscmshift;
+ if(ep->ttype == Tintr)
+ qh->eps1 |= 1 << Qhismshift; /* intr. start µf. */
+ coherence();
+ if(io != nil)
+ io->tag = tag;
+ }
+ ilock(ctlr);
+ ttype = Tctl;
+ if(ep != nil)
+ ttype = ep->ttype;
+ switch(ttype){
+ case Tctl:
+ case Tbulk:
+ if(ctlr->qhs == nil){
+ ctlr->qhs = qhlinkqh(qh, qh);
+ qh->eps0 |= Qhhigh | Qhhrl;
+ coherence();
+ ctlr->opio->link = PADDR(qh)|Lqh;
+ coherence();
+ }else{
+ qhlinkqh(qh, ctlr->qhs->next);
+ qhlinkqh(ctlr->qhs, qh);
+ }
+ break;
+ case Tintr:
+ schedq(ctlr, qh, ep->pollival);
+ break;
+ default:
+ print("ehci: qhalloc called for ttype != ctl/bulk\n");
+ }
+ iunlock(ctlr);
+ return qh;
+}
+
+static int
+qhadvanced(void *a)
+{
+ Ctlr *ctlr;
+
+ ctlr = a;
+ return (ctlr->opio->cmd & Ciasync) == 0;
+}
+
+/*
+ * called when a qh is removed, to be sure the hw is not
+ * keeping pointers into it.
+ */
+static void
+qhcoherency(Ctlr *ctlr)
+{
+ int i;
+
+ qlock(&ctlr->portlck);
+ ctlr->opio->cmd |= Ciasync; /* ask for intr. on async advance */
+ coherence();
+ for(i = 0; i < 3 && qhadvanced(ctlr) == 0; i++)
+ if(!waserror()){
+ tsleep(ctlr, qhadvanced, ctlr, Abortdelay);
+ poperror();
+ }
+ dprint("ehci: qhcoherency: doorbell %d\n", qhadvanced(ctlr));
+ if(i == 3)
+ print("ehci: async advance doorbell did not ring\n");
+ ctlr->opio->cmd &= ~Ciasync; /* try to clean */
+ qunlock(&ctlr->portlck);
+}
+
+static void
+qhfree(Ctlr *ctlr, Qh *qh)
+{
+ Td *td, *ltd;
+ Qh *q;
+
+ if(qh == nil)
+ return;
+ ilock(ctlr);
+ if(qh->sched < 0){
+ for(q = ctlr->qhs; q != nil; q = q->next)
+ if(q->next == qh)
+ break;
+ if(q == nil)
+ panic("qhfree: nil q");
+ q->next = qh->next;
+ q->link = qh->link;
+ coherence();
+ }else
+ unschedq(ctlr, qh);
+ iunlock(ctlr);
+
+ qhcoherency(ctlr);
+
+ for(td = qh->tds; td != nil; td = ltd){
+ ltd = td->next;
+ tdfree(td);
+ }
+
+ edfree(qh);
+}
+
+static void
+qhlinktd(Qh *qh, Td *td)
+{
+ ulong csw;
+ int i;
+
+ csw = qh->csw;
+ qh->tds = td;
+ if(td == nil)
+ qh->csw = (csw & ~Tdactive) | Tdhalt;
+ else{
+ csw &= Tddata1 | Tdping; /* save */
+ qh->csw = Tdhalt;
+ coherence();
+ qh->tclink = 0;
+ qh->alink = Lterm;
+ qh->nlink = PADDR(td);
+ for(i = 0; i < nelem(qh->buffer); i++)
+ qh->buffer[i] = 0;
+ coherence();
+ qh->csw = csw & ~(Tdhalt|Tdactive); /* activate next */
+ }
+ coherence();
+}
+
+static char*
+seprintlink(char *s, char *se, char *name, ulong l, int typed)
+{
+ s = seprint(s, se, "%s %ulx", name, l);
+ if((l & Lterm) != 0)
+ return seprint(s, se, "T");
+ if(typed == 0)
+ return s;
+ switch(l & (3<<1)){
+ case Litd:
+ return seprint(s, se, "I");
+ case Lqh:
+ return seprint(s, se, "Q");
+ case Lsitd:
+ return seprint(s, se, "S");
+ default:
+ return seprint(s, se, "F");
+ }
+}
+
+static char*
+seprintitd(char *s, char *se, Itd *td)
+{
+ int i;
+ ulong b0, b1;
+ char flags[6];
+ char *rw;
+
+ if(td == nil)
+ return seprint(s, se, "<nil itd>\n");
+ b0 = td->buffer[0];
+ b1 = td->buffer[1];
+
+ s = seprint(s, se, "itd %#p", td);
+ rw = (b1 & Itdin) ? "in" : "out";
+ s = seprint(s, se, " %s ep %uld dev %uld max %uld mult %uld",
+ rw, (b0>>8)&Epmax, (b0&Devmax),
+ td->buffer[1] & 0x7ff, b1 & 3);
+ s = seprintlink(s, se, " link", td->link, 1);
+ s = seprint(s, se, "\n");
+ for(i = 0; i < nelem(td->csw); i++){
+ memset(flags, '-', 5);
+ if((td->csw[i] & Itdactive) != 0)
+ flags[0] = 'a';
+ if((td->csw[i] & Itdioc) != 0)
+ flags[1] = 'i';
+ if((td->csw[i] & Itddberr) != 0)
+ flags[2] = 'd';
+ if((td->csw[i] & Itdbabble) != 0)
+ flags[3] = 'b';
+ if((td->csw[i] & Itdtrerr) != 0)
+ flags[4] = 't';
+ flags[5] = 0;
+ s = seprint(s, se, "\ttd%d %s", i, flags);
+ s = seprint(s, se, " len %uld", (td->csw[i] >> 16) & 0x7ff);
+ s = seprint(s, se, " pg %uld", (td->csw[i] >> 12) & 0x7);
+ s = seprint(s, se, " off %uld\n", td->csw[i] & 0xfff);
+ }
+ s = seprint(s, se, "\tbuffs:");
+ for(i = 0; i < nelem(td->buffer); i++)
+ s = seprint(s, se, " %#lux", td->buffer[i] >> 12);
+ return seprint(s, se, "\n");
+}
+
+static char*
+seprintsitd(char *s, char *se, Sitd *td)
+{
+ char rw, pg, ss;
+ char flags[8];
+ static char pc[4] = { 'a', 'b', 'm', 'e' };
+
+ if(td == nil)
+ return seprint(s, se, "<nil sitd>\n");
+ s = seprint(s, se, "sitd %#p", td);
+ rw = (td->epc & Stdin) ? 'r' : 'w';
+ s = seprint(s, se, " %c ep %uld dev %uld",
+ rw, (td->epc>>8)&0xf, td->epc&0x7f);
+ s = seprint(s, se, " max %uld", (td->csw >> 16) & 0x3ff);
+ s = seprint(s, se, " hub %uld", (td->epc >> 16) & 0x7f);
+ s = seprint(s, se, " port %uld\n", (td->epc >> 24) & 0x7f);
+ memset(flags, '-', 7);
+ if((td->csw & Stdactive) != 0)
+ flags[0] = 'a';
+ if((td->csw & Stdioc) != 0)
+ flags[1] = 'i';
+ if((td->csw & Stderr) != 0)
+ flags[2] = 'e';
+ if((td->csw & Stddberr) != 0)
+ flags[3] = 'd';
+ if((td->csw & Stdbabble) != 0)
+ flags[4] = 'b';
+ if((td->csw & Stdtrerr) != 0)
+ flags[5] = 't';
+ if((td->csw & Stdmmf) != 0)
+ flags[6] = 'n';
+ flags[7] = 0;
+ ss = (td->csw & Stddcs) ? 'c' : 's';
+ pg = (td->csw & Stdpg) ? '1' : '0';
+ s = seprint(s, se, "\t%s %cs pg%c", flags, ss, pg);
+ s = seprint(s, se, " b0 %#lux b1 %#lux off %uld\n",
+ td->buffer[0] >> 12, td->buffer[1] >> 12, td->buffer[0] & 0xfff);
+ s = seprint(s, se, "\ttpos %c tcnt %uld",
+ pc[(td->buffer[0]>>3)&3], td->buffer[1] & 7);
+ s = seprint(s, se, " ssm %#lux csm %#lux cspm %#lux",
+ td->mfs & 0xff, (td->mfs>>8) & 0xff, (td->csw>>8) & 0xff);
+ s = seprintlink(s, se, " link", td->link, 1);
+ s = seprintlink(s, se, " blink", td->blink, 0);
+ return seprint(s, se, "\n");
+}
+
+static long
+maxtdlen(Td *td)
+{
+ return (td->csw >> Tdlenshift) & Tdlenmask;
+}
+
+static long
+tdlen(Td *td)
+{
+ if(td->data == nil)
+ return 0;
+ return td->ndata - maxtdlen(td);
+}
+
+static char*
+seprinttd(char *s, char *se, Td *td, char *tag)
+{
+ int i;
+ char t, ss;
+ char flags[9];
+ static char *tok[4] = { "out", "in", "setup", "BUG" };
+
+ if(td == nil)
+ return seprint(s, se, "%s <nil td>\n", tag);
+ s = seprint(s, se, "%s %#p", tag, td);
+ s = seprintlink(s, se, " nlink", td->nlink, 0);
+ s = seprintlink(s, se, " alink", td->alink, 0);
+ s = seprint(s, se, " %s", tok[(td->csw & Tdtok) >> 8]);
+ if((td->csw & Tdping) != 0)
+ s = seprint(s, se, " png");
+ memset(flags, '-', 8);
+ if((td->csw & Tdactive) != 0)
+ flags[0] = 'a';
+ if((td->csw & Tdioc) != 0)
+ flags[1] = 'i';
+ if((td->csw & Tdhalt) != 0)
+ flags[2] = 'h';
+ if((td->csw & Tddberr) != 0)
+ flags[3] = 'd';
+ if((td->csw & Tdbabble) != 0)
+ flags[4] = 'b';
+ if((td->csw & Tdtrerr) != 0)
+ flags[5] = 't';
+ if((td->csw & Tdmmf) != 0)
+ flags[6] = 'n';
+ if((td->csw & (Tderr2|Tderr1)) == 0)
+ flags[7] = 'z';
+ flags[8] = 0;
+ t = (td->csw & Tddata1) ? '1' : '0';
+ ss = (td->csw & Tddcs) ? 'c' : 's';
+ s = seprint(s, se, "\n\td%c %s %cs", t, flags, ss);
+ s = seprint(s, se, " max %uld", maxtdlen(td));
+ s = seprint(s, se, " pg %uld off %#lux\n",
+ (td->csw >> Tdpgshift) & Tdpgmask, td->buffer[0] & 0xFFF);
+ s = seprint(s, se, "\tbuffs:");
+ for(i = 0; i < nelem(td->buffer); i++)
+ s = seprint(s, se, " %#lux", td->buffer[i]>>12);
+ if(td->data != nil)
+ s = seprintdata(s, se, td->data, td->ndata);
+ return seprint(s, se, "\n");
+}
+
+static void
+dumptd(Td *td, char *pref)
+{
+ char buf[256];
+ char *se;
+ int i;
+
+ i = 0;
+ se = buf+sizeof(buf);
+ for(; td != nil; td = td->next){
+ seprinttd(buf, se, td, pref);
+ print("%s", buf);
+ if(i++ > 20){
+ print("...more tds...\n");
+ break;
+ }
+ }
+}
+
+static void
+qhdump(Qh *qh)
+{
+ char buf[256];
+ char *s, *se, *tag;
+ Td td;
+ static char *speed[] = {"full", "low", "high", "BUG"};
+
+ if(qh == nil){
+ print("<nil qh>\n");
+ return;
+ }
+ if(qh->io == nil)
+ tag = "qh";
+ else
+ tag = qh->io->tag;
+ se = buf+sizeof(buf);
+ s = seprint(buf, se, "%s %#p", tag, qh);
+ s = seprint(s, se, " ep %uld dev %uld",
+ (qh->eps0>>8)&0xf, qh->eps0&0x7f);
+ s = seprint(s, se, " hub %uld", (qh->eps1 >> 16) & 0x7f);
+ s = seprint(s, se, " port %uld", (qh->eps1 >> 23) & 0x7f);
+ s = seprintlink(s, se, " link", qh->link, 1);
+ seprint(s, se, " clink %#lux", qh->tclink);
+ print("%s\n", buf);
+ s = seprint(buf, se, "\tnrld %uld", (qh->eps0 >> Qhrlcshift) & Qhrlcmask);
+ s = seprint(s, se, " nak %uld", (qh->alink >> 1) & 0xf);
+ s = seprint(s, se, " max %uld ", qhmaxpkt(qh));
+ if((qh->eps0 & Qhnhctl) != 0)
+ s = seprint(s, se, "c");
+ if((qh->eps0 & Qhhrl) != 0)
+ s = seprint(s, se, "h");
+ if((qh->eps0 & Qhdtc) != 0)
+ s = seprint(s, se, "d");
+ if((qh->eps0 & Qhint) != 0)
+ s = seprint(s, se, "i");
+ s = seprint(s, se, " %s", speed[(qh->eps0 >> 12) & 3]);
+ s = seprint(s, se, " mult %uld", (qh->eps1 >> Qhmultshift) & Qhmultmask);
+ seprint(s, se, " scm %#lux ism %#lux\n",
+ (qh->eps1 >> 8 & 0xff), qh->eps1 & 0xff);
+ print("%s\n", buf);
+ memset(&td, 0, sizeof(td));
+ memmove(&td, &qh->nlink, 32); /* overlay area */
+ seprinttd(buf, se, &td, "\tovl");
+ print("%s", buf);
+}
+
+static void
+isodump(Isoio* iso, int all)
+{
+ Itd *td, *tdi, *tdu;
+ Sitd *std, *stdi, *stdu;
+ char buf[256];
+ int i;
+
+ if(iso == nil){
+ print("<nil iso>\n");
+ return;
+ }
+ print("iso %#p %s %s speed state %d nframes %d maxsz %uld",
+ iso, iso->tok == Tdtokin ? "in" : "out",
+ iso->hs ? "high" : "full",
+ iso->state, iso->nframes, iso->maxsize);
+ print(" td0 %uld tdi %#p tdu %#p data %#p\n",
+ iso->td0frno, iso->tdi, iso->tdu, iso->data);
+ if(iso->err != nil)
+ print("\terr %s\n", iso->err);
+ if(iso->err != nil)
+ print("\terr='%s'\n", iso->err);
+ if(all == 0)
+ if(iso->hs != 0){
+ tdi = iso->tdi;
+ seprintitd(buf, buf+sizeof(buf), tdi);
+ print("\ttdi %s\n", buf);
+ tdu = iso->tdu;
+ seprintitd(buf, buf+sizeof(buf), tdu);
+ print("\ttdu %s\n", buf);
+ }else{
+ stdi = iso->stdi;
+ seprintsitd(buf, buf+sizeof(buf), stdi);
+ print("\tstdi %s\n", buf);
+ stdu = iso->stdu;
+ seprintsitd(buf, buf+sizeof(buf), stdu);
+ print("\tstdu %s\n", buf);
+ }
+ else
+ for(i = 0; i < Nisoframes; i++)
+ if(iso->tdps[i] != nil)
+ if(iso->hs != 0){
+ td = iso->itdps[i];
+ seprintitd(buf, buf+sizeof(buf), td);
+ if(td == iso->tdi)
+ print("i->");
+ if(td == iso->tdu)
+ print("i->");
+ print("[%d]\t%s", i, buf);
+ }else{
+ std = iso->sitdps[i];
+ seprintsitd(buf, buf+sizeof(buf), std);
+ if(std == iso->stdi)
+ print("i->");
+ if(std == iso->stdu)
+ print("u->");
+ print("[%d]\t%s", i, buf);
+ }
+}
+
+static void
+dump(Hci *hp)
+{
+ int i;
+ char *s, *se;
+ char buf[128];
+ Ctlr *ctlr;
+ Eopio *opio;
+ Isoio *iso;
+ Qh *qh;
+
+ ctlr = hp->aux;
+ opio = ctlr->opio;
+ ilock(ctlr);
+ print("ehci port %#p frames %#p (%d fr.) nintr %d ntdintr %d",
+ ctlr->capio, ctlr->frames, ctlr->nframes,
+ ctlr->nintr, ctlr->ntdintr);
+ print(" nqhintr %d nisointr %d\n", ctlr->nqhintr, ctlr->nisointr);
+ print("\tcmd %#lux sts %#lux intr %#lux frno %uld",
+ opio->cmd, opio->sts, opio->intr, opio->frno);
+ print(" base %#lux link %#lux fr0 %#lux\n",
+ opio->frbase, opio->link, ctlr->frames[0]);
+ se = buf+sizeof(buf);
+ s = seprint(buf, se, "\t");
+ for(i = 0; i < hp->nports; i++){
+ s = seprint(s, se, "p%d %#lux ", i, opio->portsc[i]);
+ if(hp->nports > 4 && i == hp->nports/2 - 1)
+ s = seprint(s, se, "\n\t");
+ }
+ print("%s\n", buf);
+ qh = ctlr->qhs;
+ i = 0;
+ do{
+ qhdump(qh);
+ qh = qh->next;
+ }while(qh != ctlr->qhs && i++ < 100);
+ if(i > 100)
+ print("...too many Qhs...\n");
+ if(ctlr->intrqhs != nil)
+ print("intr qhs:\n");
+ for(qh = ctlr->intrqhs; qh != nil; qh = qh->inext)
+ qhdump(qh);
+ if(ctlr->iso != nil)
+ print("iso:\n");
+ for(iso = ctlr->iso; iso != nil; iso = iso->next)
+ isodump(ctlr->iso, 0);
+ print("%d eds in tree\n", ctlr->ntree);
+ iunlock(ctlr);
+ lock(&edpool);
+ print("%d eds allocated = %d in use + %d free\n",
+ edpool.nalloc, edpool.ninuse, edpool.nfree);
+ unlock(&edpool);
+}
+
+static char*
+errmsg(int err)
+{
+ if(err == 0)
+ return "ok";
+ if(err & Tddberr)
+ return "data buffer error";
+ if(err & Tdbabble)
+ return "babble detected";
+ if(err & Tdtrerr)
+ return "transaction error";
+ if(err & Tdmmf)
+ return "missed µframe";
+ if(err & Tdhalt)
+ return Estalled; /* [uo]hci report this error */
+ return Eio;
+}
+
+static char*
+ierrmsg(int err)
+{
+ if(err == 0)
+ return "ok";
+ if(err & Itddberr)
+ return "data buffer error";
+ if(err & Itdbabble)
+ return "babble detected";
+ if(err & Itdtrerr)
+ return "transaction error";
+ return Eio;
+}
+
+static char*
+serrmsg(int err)
+{
+ if(err & Stderr)
+ return "translation translator error";
+ /* other errors have same numbers than Td errors */
+ return errmsg(err);
+}
+
+static int
+isocanread(void *a)
+{
+ Isoio *iso;
+
+ iso = a;
+ if(iso->state == Qclose)
+ return 1;
+ if(iso->state == Qrun && iso->tok == Tdtokin){
+ if(iso->hs != 0 && iso->tdi != iso->tdu)
+ return 1;
+ if(iso->hs == 0 && iso->stdi != iso->stdu)
+ return 1;
+ }
+ return 0;
+}
+
+static int
+isocanwrite(void *a)
+{
+ Isoio *iso;
+
+ iso = a;
+ if(iso->state == Qclose)
+ return 1;
+ if(iso->state == Qrun && iso->tok == Tdtokout){
+ if(iso->hs != 0 && iso->tdu->next != iso->tdi)
+ return 1;
+ if(iso->hs == 0 && iso->stdu->next != iso->stdi)
+ return 1;
+ }
+ return 0;
+}
+
+static void
+itdinit(Isoio *iso, Itd *td)
+{
+ int p, t;
+ ulong pa, tsize, size;
+
+ /*
+ * BUG: This does not put an integral number of samples
+ * on each µframe unless samples per packet % 8 == 0
+ * Also, all samples are packed early on each frame.
+ */
+ p = 0;
+ size = td->ndata = td->mdata;
+ pa = PADDR(td->data);
+ for(t = 0; size > 0 && t < 8; t++){
+ tsize = size;
+ if(tsize > iso->maxsize)
+ tsize = iso->maxsize;
+ size -= tsize;
+ assert(p < nelem(td->buffer));
+ td->csw[t] = tsize << Itdlenshift | p << Itdpgshift |
+ (pa & 0xFFF) << Itdoffshift | Itdactive | Itdioc;
+ coherence();
+ if(((pa+tsize) & ~0xFFF) != (pa & ~0xFFF))
+ p++;
+ pa += tsize;
+ }
+}
+
+static void
+sitdinit(Isoio *iso, Sitd *td)
+{
+ td->ndata = td->mdata & Stdlenmask;
+ td->buffer[0] = PADDR(td->data);
+ td->buffer[1] = (td->buffer[0] & ~0xFFF) + 0x1000;
+ if(iso->tok == Tdtokin || td->ndata <= 188)
+ td->buffer[1] |= Stdtpall;
+ else
+ td->buffer[1] |= Stdtpbegin;
+ if(iso->tok == Tdtokin)
+ td->buffer[1] |= 1;
+ else
+ td->buffer[1] |= ((td->ndata + 187) / 188) & Stdtcntmask;
+ coherence();
+ td->csw = td->ndata << Stdlenshift | Stdactive | Stdioc;
+ coherence();
+}
+
+static int
+itdactive(Itd *td)
+{
+ int i;
+
+ for(i = 0; i < nelem(td->csw); i++)
+ if((td->csw[i] & Itdactive) != 0)
+ return 1;
+ return 0;
+}
+
+static int
+isohsinterrupt(Ctlr *ctlr, Isoio *iso)
+{
+ int err, i, nframes, t;
+ Itd *tdi;
+
+ tdi = iso->tdi;
+ assert(tdi != nil);
+ if(itdactive(tdi)) /* not all tds are done */
+ return 0;
+ ctlr->nisointr++;
+ ddiprint("isohsintr: iso %#p: tdi %#p tdu %#p\n", iso, tdi, iso->tdu);
+ if(iso->state != Qrun && iso->state != Qdone)
+ panic("isofsintr: iso state");
+ if(ehcidebug > 1 || iso->debug > 1)
+ isodump(iso, 0);
+
+ nframes = iso->nframes / 2; /* limit how many we look */
+ if(nframes > Nisoframes)
+ nframes = Nisoframes;
+
+ if(iso->tok == Tdtokin)
+ tdi->ndata = 0;
+ /* else, it has the number of bytes transferred */
+
+ for(i = 0; i < nframes && itdactive(tdi) == 0; i++){
+ if(iso->tok == Tdtokin)
+ tdi->ndata += (tdi->csw[i] >> Itdlenshift) & Itdlenmask;
+ err = 0;
+ coherence();
+ for(t = 0; t < nelem(tdi->csw); t++){
+ tdi->csw[t] &= ~Itdioc;
+ coherence();
+ err |= tdi->csw[t] & Itderrors;
+ }
+ if(err == 0)
+ iso->nerrs = 0;
+ else if(iso->nerrs++ > iso->nframes/2){
+ if(iso->err == nil){
+ iso->err = ierrmsg(err);
+ diprint("isohsintr: tdi %#p error %#ux %s\n",
+ tdi, err, iso->err);
+ diprint("ctlr load %uld\n", ctlr->load);
+ }
+ tdi->ndata = 0;
+ }else
+ tdi->ndata = 0;
+ if(tdi->next == iso->tdu || tdi->next->next == iso->tdu){
+ memset(iso->tdu->data, 0, iso->tdu->mdata);
+ itdinit(iso, iso->tdu);
+ iso->tdu = iso->tdu->next;
+ iso->nleft = 0;
+ }
+ tdi = tdi->next;
+ coherence();
+ }
+ ddiprint("isohsintr: %d frames processed\n", nframes);
+ if(i == nframes){
+ tdi->csw[0] |= Itdioc;
+ coherence();
+ }
+ iso->tdi = tdi;
+ coherence();
+ if(isocanwrite(iso) || isocanread(iso)){
+ diprint("wakeup iso %#p tdi %#p tdu %#p\n", iso,
+ iso->tdi, iso->tdu);
+ wakeup(iso);
+ }
+ return 1;
+}
+
+static int
+isofsinterrupt(Ctlr *ctlr, Isoio *iso)
+{
+ int err, i, nframes;
+ Sitd *stdi;
+
+ stdi = iso->stdi;
+ assert(stdi != nil);
+ if((stdi->csw & Stdactive) != 0) /* nothing new done */
+ return 0;
+ ctlr->nisointr++;
+ ddiprint("isofsintr: iso %#p: tdi %#p tdu %#p\n", iso, stdi, iso->stdu);
+ if(iso->state != Qrun && iso->state != Qdone)
+ panic("isofsintr: iso state");
+ if(ehcidebug > 1 || iso->debug > 1)
+ isodump(iso, 0);
+
+ nframes = iso->nframes / 2; /* limit how many we look */
+ if(nframes > Nisoframes)
+ nframes = Nisoframes;
+
+ for(i = 0; i < nframes && (stdi->csw & Stdactive) == 0; i++){
+ stdi->csw &= ~Stdioc;
+ /* write back csw and see if it produces errors */
+ coherence();
+ err = stdi->csw & Stderrors;
+ if(err == 0){
+ iso->nerrs = 0;
+ if(iso->tok == Tdtokin)
+ stdi->ndata = (stdi->csw>>Stdlenshift)&Stdlenmask;
+ /* else len is assumed correct */
+ }else if(iso->nerrs++ > iso->nframes/2){
+ if(iso->err == nil){
+ iso->err = serrmsg(err);
+ diprint("isofsintr: tdi %#p error %#ux %s\n",
+ stdi, err, iso->err);
+ diprint("ctlr load %uld\n", ctlr->load);
+ }
+ stdi->ndata = 0;
+ }else
+ stdi->ndata = 0;
+
+ if(stdi->next == iso->stdu || stdi->next->next == iso->stdu){
+ memset(iso->stdu->data, 0, iso->stdu->mdata);
+ coherence();
+ sitdinit(iso, iso->stdu);
+ iso->stdu = iso->stdu->next;
+ iso->nleft = 0;
+ }
+ coherence();
+ stdi = stdi->next;
+ }
+ ddiprint("isofsintr: %d frames processed\n", nframes);
+ if(i == nframes){
+ stdi->csw |= Stdioc;
+ coherence();
+ }
+ iso->stdi = stdi;
+ coherence();
+ if(isocanwrite(iso) || isocanread(iso)){
+ diprint("wakeup iso %#p tdi %#p tdu %#p\n", iso,
+ iso->stdi, iso->stdu);
+ wakeup(iso);
+ }
+ return 1;
+}
+
+static int
+qhinterrupt(Ctlr *ctlr, Qh *qh)
+{
+ Td *td;
+ int err;
+
+ if(qh->state != Qrun)
+ panic("qhinterrupt: qh state");
+ td = qh->tds;
+ if(td == nil)
+ panic("qhinterrupt: no tds");
+ if((td->csw & Tdactive) == 0)
+ ddqprint("qhinterrupt port %#p qh %#p\n", ctlr->capio, qh);
+ for(; td != nil; td = td->next){
+ if(td->csw & Tdactive)
+ return 0;
+ err = td->csw & Tderrors;
+ if(err != 0){
+ if(qh->io->err == nil){
+ qh->io->err = errmsg(err);
+ dqprint("qhintr: td %#p csw %#lux error %#ux %s\n",
+ td, td->csw, err, qh->io->err);
+ }
+ break;
+ }
+ td->ndata = tdlen(td);
+ coherence();
+ if(td->ndata < maxtdlen(td)){ /* EOT */
+ td = td->next;
+ break;
+ }
+ }
+ /*
+ * Done. Make void the Tds not used (errors or EOT) and wakeup epio.
+ */
+ for(; td != nil; td = td->next)
+ td->ndata = 0;
+ coherence();
+ qh->state = Qdone;
+ coherence();
+ wakeup(qh->io);
+ return 1;
+}
+
+static int
+ehciintr(Hci *hp)
+{
+ Ctlr *ctlr;
+ Eopio *opio;
+ Isoio *iso;
+ ulong sts;
+ Qh *qh;
+ int i, some;
+
+ ctlr = hp->aux;
+ opio = ctlr->opio;
+
+ /*
+ * Will we know in USB 3.0 who the interrupt was for?.
+ * Do they still teach indexing in CS?
+ * This is Intel's doing.
+ */
+ ilock(ctlr);
+ ctlr->nintr++;
+ sts = opio->sts & Sintrs;
+ if(sts == 0){ /* not ours; shared intr. */
+ iunlock(ctlr);
+ return 0;
+ }
+ opio->sts = sts;
+ coherence();
+ if((sts & Sherr) != 0)
+ print("ehci: port %#p fatal host system error\n", ctlr->capio);
+ if((sts & Shalted) != 0)
+ print("ehci: port %#p: halted\n", ctlr->capio);
+ if((sts & Sasync) != 0){
+ dprint("ehci: doorbell\n");
+ wakeup(ctlr);
+ }
+ /*
+ * We enter always this if, even if it seems the
+ * interrupt does not report anything done/failed.
+ * Some controllers don't post interrupts right.
+ */
+ some = 0;
+ if((sts & (Serrintr|Sintr)) != 0){
+ ctlr->ntdintr++;
+ if(ehcidebug > 1){
+ print("ehci port %#p frames %#p nintr %d ntdintr %d",
+ ctlr->capio, ctlr->frames,
+ ctlr->nintr, ctlr->ntdintr);
+ print(" nqhintr %d nisointr %d\n",
+ ctlr->nqhintr, ctlr->nisointr);
+ print("\tcmd %#lux sts %#lux intr %#lux frno %uld",
+ opio->cmd, opio->sts, opio->intr, opio->frno);
+ }
+
+ /* process the Iso transfers */
+ for(iso = ctlr->iso; iso != nil; iso = iso->next)
+ if(iso->state == Qrun || iso->state == Qdone)
+ if(iso->hs != 0)
+ some += isohsinterrupt(ctlr, iso);
+ else
+ some += isofsinterrupt(ctlr, iso);
+
+ /* process the qhs in the periodic tree */
+ for(qh = ctlr->intrqhs; qh != nil; qh = qh->inext)
+ if(qh->state == Qrun)
+ some += qhinterrupt(ctlr, qh);
+
+ /* process the async Qh circular list */
+ qh = ctlr->qhs;
+ i = 0;
+ do{
+ if (qh == nil)
+ panic("ehciintr: nil qh");
+ if(qh->state == Qrun)
+ some += qhinterrupt(ctlr, qh);
+ qh = qh->next;
+ }while(qh != ctlr->qhs && i++ < 100);
+ if(i > 100)
+ print("echi: interrupt: qh loop?\n");
+ }
+// if (some == 0)
+// panic("ehciintr: no work");
+ iunlock(ctlr);
+ return some;
+}
+
+static void
+interrupt(Ureg*, void* a)
+{
+ ehciintr(a);
+}
+
+static int
+portenable(Hci *hp, int port, int on)
+{
+ Ctlr *ctlr;
+ Eopio *opio;
+ int s;
+
+ ctlr = hp->aux;
+ opio = ctlr->opio;
+ s = opio->portsc[port-1];
+ qlock(&ctlr->portlck);
+ if(waserror()){
+ qunlock(&ctlr->portlck);
+ nexterror();
+ }
+ dprint("ehci %#p port %d enable=%d; sts %#x\n",
+ ctlr->capio, port, on, s);
+ ilock(ctlr);
+ if(s & (Psstatuschg | Pschange))
+ opio->portsc[port-1] = s;
+ if(on)
+ opio->portsc[port-1] |= Psenable;
+ else
+ opio->portsc[port-1] &= ~Psenable;
+ coherence();
+ microdelay(64);
+ iunlock(ctlr);
+ tsleep(&up->sleep, return0, 0, Enabledelay);
+ dprint("ehci %#p port %d enable=%d: sts %#lux\n",
+ ctlr->capio, port, on, opio->portsc[port-1]);
+ qunlock(&ctlr->portlck);
+ poperror();
+ return 0;
+}
+
+/*
+ * If we detect during status that the port is low-speed or
+ * during reset that it's full-speed, the device is not for
+ * ourselves. The companion controller will take care.
+ * Low-speed devices will not be seen by usbd. Full-speed
+ * ones are seen because it's only after reset that we know what
+ * they are (usbd may notice a device not enabled in this case).
+ */
+static void
+portlend(Ctlr *ctlr, int port, char *ss)
+{
+ Eopio *opio;
+ ulong s;
+
+ opio = ctlr->opio;
+
+ dprint("ehci %#p port %d: %s speed device: no longer owned\n",
+ ctlr->capio, port, ss);
+ s = opio->portsc[port-1] & ~(Pschange|Psstatuschg);
+ opio->portsc[port-1] = s | Psowner;
+ coherence();
+}
+
+static int
+portreset(Hci *hp, int port, int on)
+{
+ ulong s;
+ Eopio *opio;
+ Ctlr *ctlr;
+ int i;
+
+ if(on == 0)
+ return 0;
+
+ ctlr = hp->aux;
+ opio = ctlr->opio;
+ qlock(&ctlr->portlck);
+ if(waserror()){
+ iunlock(ctlr);
+ qunlock(&ctlr->portlck);
+ nexterror();
+ }
+ s = opio->portsc[port-1];
+ dprint("ehci %#p port %d reset; sts %#lux\n", ctlr->capio, port, s);
+ ilock(ctlr);
+ s &= ~(Psenable|Psreset);
+ opio->portsc[port-1] = s | Psreset; /* initiate reset */
+ coherence();
+
+ for(i = 0; i < 50; i++){ /* was 10 */
+ delay(10);
+ if((opio->portsc[port-1] & Psreset) == 0)
+ break;
+ }
+ if (opio->portsc[port-1] & Psreset)
+ iprint("ehci %#p: port %d didn't reset after %d ms; sts %#lux\n",
+ ctlr->capio, port, i * 10, opio->portsc[port-1]);
+ opio->portsc[port-1] &= ~Psreset; /* force appearance of reset done */
+ coherence();
+
+ delay(10);
+ if((opio->portsc[port-1] & Psenable) == 0)
+ portlend(ctlr, port, "full");
+
+ iunlock(ctlr);
+ dprint("ehci %#p after port %d reset; sts %#lux\n",
+ ctlr->capio, port, opio->portsc[port-1]);
+ qunlock(&ctlr->portlck);
+ poperror();
+ return 0;
+}
+
+static int
+portstatus(Hci *hp, int port)
+{
+ int s, r;
+ Eopio *opio;
+ Ctlr *ctlr;
+
+ ctlr = hp->aux;
+ opio = ctlr->opio;
+ qlock(&ctlr->portlck);
+ if(waserror()){
+ iunlock(ctlr);
+ qunlock(&ctlr->portlck);
+ nexterror();
+ }
+ ilock(ctlr);
+ s = opio->portsc[port-1];
+ if(s & (Psstatuschg | Pschange)){
+ opio->portsc[port-1] = s;
+ coherence();
+ ddprint("ehci %#p port %d status %#x\n", ctlr->capio, port, s);
+ }
+ /*
+ * If the port is a low speed port we yield ownership now
+ * to the [uo]hci companion controller and pretend it's not here.
+ */
+ if((s & Pspresent) != 0 && (s & Pslinemask) == Pslow){
+ portlend(ctlr, port, "low");
+ s &= ~Pspresent; /* not for us this time */
+ }
+ iunlock(ctlr);
+ qunlock(&ctlr->portlck);
+ poperror();
+
+ /*
+ * We must return status bits as a
+ * get port status hub request would do.
+ */
+ r = 0;
+ if(s & Pspresent)
+ r |= HPpresent|HPhigh;
+ if(s & Psenable)
+ r |= HPenable;
+ if(s & Pssuspend)
+ r |= HPsuspend;
+ if(s & Psreset)
+ r |= HPreset;
+ if(s & Psstatuschg)
+ r |= HPstatuschg;
+ if(s & Pschange)
+ r |= HPchange;
+ return r;
+}
+
+static char*
+seprintio(char *s, char *e, Qio *io, char *pref)
+{
+ s = seprint(s,e,"%s io %#p qh %#p id %#x", pref, io, io->qh, io->usbid);
+ s = seprint(s,e," iot %ld", io->iotime);
+ s = seprint(s,e," tog %#x tok %#x err %s", io->toggle, io->tok, io->err);
+ return s;
+}
+
+static char*
+seprintep(char *s, char *e, Ep *ep)
+{
+ Qio *io;
+ Ctlio *cio;
+ Ctlr *ctlr;
+
+ ctlr = ep->hp->aux;
+ ilock(ctlr);
+ if(ep->aux == nil){
+ *s = 0;
+ iunlock(ctlr);
+ return s;
+ }
+ switch(ep->ttype){
+ case Tctl:
+ cio = ep->aux;
+ s = seprintio(s, e, cio, "c");
+ s = seprint(s, e, "\trepl %d ndata %d\n", ep->rhrepl, cio->ndata);
+ break;
+ case Tbulk:
+ case Tintr:
+ io = ep->aux;
+ if(ep->mode != OWRITE)
+ s = seprintio(s, e, &io[OREAD], "r");
+ if(ep->mode != OREAD)
+ s = seprintio(s, e, &io[OWRITE], "w");
+ break;
+ case Tiso:
+ *s = 0;
+ break;
+ }
+ iunlock(ctlr);
+ return s;
+}
+
+/*
+ * halt condition was cleared on the endpoint. update our toggles.
+ */
+static void
+clrhalt(Ep *ep)
+{
+ Qio *io;
+
+ ep->clrhalt = 0;
+ coherence();
+ switch(ep->ttype){
+ case Tintr:
+ case Tbulk:
+ io = ep->aux;
+ if(ep->mode != OREAD){
+ qlock(&io[OWRITE]);
+ io[OWRITE].toggle = Tddata0;
+ deprint("ep clrhalt for io %#p\n", io+OWRITE);
+ qunlock(&io[OWRITE]);
+ }
+ if(ep->mode != OWRITE){
+ qlock(&io[OREAD]);
+ io[OREAD].toggle = Tddata0;
+ deprint("ep clrhalt for io %#p\n", io+OREAD);
+ qunlock(&io[OREAD]);
+ }
+ break;
+ }
+}
+
+static void
+xdump(char* pref, void *qh)
+{
+ int i;
+ ulong *u;
+
+ u = qh;
+ print("%s %#p:", pref, u);
+ for(i = 0; i < 16; i++)
+ if((i%4) == 0)
+ print("\n %#8.8ulx", u[i]);
+ else
+ print(" %#8.8ulx", u[i]);
+ print("\n");
+}
+
+static long
+episohscpy(Ctlr *ctlr, Ep *ep, Isoio* iso, uchar *b, long count)
+{
+ int nr;
+ long tot;
+ Itd *tdu;
+
+ for(tot = 0; iso->tdi != iso->tdu && tot < count; tot += nr){
+ tdu = iso->tdu;
+ if(itdactive(tdu))
+ break;
+ nr = tdu->ndata;
+ if(tot + nr > count)
+ nr = count - tot;
+ if(nr == 0)
+ print("ehci: ep%d.%d: too many polls\n",
+ ep->dev->nb, ep->nb);
+ else{
+ iunlock(ctlr); /* We could page fault here */
+ memmove(b+tot, tdu->data, nr);
+ ilock(ctlr);
+ if(nr < tdu->ndata)
+ memmove(tdu->data, tdu->data+nr, tdu->ndata - nr);
+ tdu->ndata -= nr;
+ coherence();
+ }
+ if(tdu->ndata == 0){
+ itdinit(iso, tdu);
+ iso->tdu = tdu->next;
+ }
+ }
+ return tot;
+}
+
+static long
+episofscpy(Ctlr *ctlr, Ep *ep, Isoio* iso, uchar *b, long count)
+{
+ int nr;
+ long tot;
+ Sitd *stdu;
+
+ for(tot = 0; iso->stdi != iso->stdu && tot < count; tot += nr){
+ stdu = iso->stdu;
+ if(stdu->csw & Stdactive){
+ diprint("ehci: episoread: %#p tdu active\n", iso);
+ break;
+ }
+ nr = stdu->ndata;
+ if(tot + nr > count)
+ nr = count - tot;
+ if(nr == 0)
+ print("ehci: ep%d.%d: too many polls\n",
+ ep->dev->nb, ep->nb);
+ else{
+ iunlock(ctlr); /* We could page fault here */
+ memmove(b+tot, stdu->data, nr);
+ ilock(ctlr);
+ if(nr < stdu->ndata)
+ memmove(stdu->data, stdu->data+nr,
+ stdu->ndata - nr);
+ stdu->ndata -= nr;
+ coherence();
+ }
+ if(stdu->ndata == 0){
+ sitdinit(iso, stdu);
+ iso->stdu = stdu->next;
+ }
+ }
+ return tot;
+}
+
+static long
+episoread(Ep *ep, Isoio *iso, void *a, long count)
+{
+ Ctlr *ctlr;
+ uchar *b;
+ long tot;
+
+ iso->debug = ep->debug;
+ diprint("ehci: episoread: %#p ep%d.%d\n", iso, ep->dev->nb, ep->nb);
+
+ b = a;
+ ctlr = ep->hp->aux;
+ qlock(iso);
+ if(waserror()){
+ qunlock(iso);
+ nexterror();
+ }
+ iso->err = nil;
+ iso->nerrs = 0;
+ ilock(ctlr);
+ if(iso->state == Qclose){
+ iunlock(ctlr);
+ error(iso->err ? iso->err : Eio);
+ }
+ iso->state = Qrun;
+ coherence();
+ while(isocanread(iso) == 0){
+ iunlock(ctlr);
+ diprint("ehci: episoread: %#p sleep\n", iso);
+ if(waserror()){
+ if(iso->err == nil)
+ iso->err = "I/O timed out";
+ ilock(ctlr);
+ break;
+ }
+ tsleep(iso, isocanread, iso, ep->tmout);
+ poperror();
+ ilock(ctlr);
+ }
+ if(iso->state == Qclose){
+ iunlock(ctlr);
+ error(iso->err ? iso->err : Eio);
+ }
+ iso->state = Qdone;
+ coherence();
+ assert(iso->tdu != iso->tdi);
+
+ if(iso->hs != 0)
+ tot = episohscpy(ctlr, ep, iso, b, count);
+ else
+ tot = episofscpy(ctlr, ep, iso, b, count);
+ iunlock(ctlr);
+ qunlock(iso);
+ poperror();
+ diprint("uhci: episoread: %#p %uld bytes err '%s'\n", iso, tot, iso->err);
+ if(iso->err != nil)
+ error(iso->err);
+ return tot;
+}
+
+/*
+ * iso->tdu is the next place to put data. When it gets full
+ * it is activated and tdu advanced.
+ */
+static long
+putsamples(Isoio *iso, uchar *b, long count)
+{
+ long tot, n;
+
+ for(tot = 0; isocanwrite(iso) && tot < count; tot += n){
+ n = count-tot;
+ if(iso->hs != 0){
+ if(n > iso->tdu->mdata - iso->nleft)
+ n = iso->tdu->mdata - iso->nleft;
+ memmove(iso->tdu->data + iso->nleft, b + tot, n);
+ coherence();
+ iso->nleft += n;
+ if(iso->nleft == iso->tdu->mdata){
+ itdinit(iso, iso->tdu);
+ iso->nleft = 0;
+ iso->tdu = iso->tdu->next;
+ }
+ }else{
+ if(n > iso->stdu->mdata - iso->nleft)
+ n = iso->stdu->mdata - iso->nleft;
+ memmove(iso->stdu->data + iso->nleft, b + tot, n);
+ coherence();
+ iso->nleft += n;
+ if(iso->nleft == iso->stdu->mdata){
+ sitdinit(iso, iso->stdu);
+ iso->nleft = 0;
+ iso->stdu = iso->stdu->next;
+ }
+ }
+ }
+ return tot;
+}
+
+/*
+ * Queue data for writing and return error status from
+ * last writes done, to maintain buffered data.
+ */
+static long
+episowrite(Ep *ep, Isoio *iso, void *a, long count)
+{
+ Ctlr *ctlr;
+ uchar *b;
+ int tot, nw;
+ char *err;
+
+ iso->debug = ep->debug;
+ diprint("ehci: episowrite: %#p ep%d.%d\n", iso, ep->dev->nb, ep->nb);
+
+ ctlr = ep->hp->aux;
+ qlock(iso);
+ if(waserror()){
+ qunlock(iso);
+ nexterror();
+ }
+ ilock(ctlr);
+ if(iso->state == Qclose){
+ iunlock(ctlr);
+ error(iso->err ? iso->err : Eio);
+ }
+ iso->state = Qrun;
+ coherence();
+ b = a;
+ for(tot = 0; tot < count; tot += nw){
+ while(isocanwrite(iso) == 0){
+ iunlock(ctlr);
+ diprint("ehci: episowrite: %#p sleep\n", iso);
+ if(waserror()){
+ if(iso->err == nil)
+ iso->err = "I/O timed out";
+ ilock(ctlr);
+ break;
+ }
+ tsleep(iso, isocanwrite, iso, ep->tmout);
+ poperror();
+ ilock(ctlr);
+ }
+ err = iso->err;
+ iso->err = nil;
+ if(iso->state == Qclose || err != nil){
+ iunlock(ctlr);
+ error(err ? err : Eio);
+ }
+ if(iso->state != Qrun)
+ panic("episowrite: iso not running");
+ iunlock(ctlr); /* We could page fault here */
+ nw = putsamples(iso, b+tot, count-tot);
+ ilock(ctlr);
+ }
+ if(iso->state != Qclose)
+ iso->state = Qdone;
+ iunlock(ctlr);
+ err = iso->err; /* in case it failed early */
+ iso->err = nil;
+ qunlock(iso);
+ poperror();
+ if(err != nil)
+ error(err);
+ diprint("ehci: episowrite: %#p %d bytes\n", iso, tot);
+ return tot;
+}
+
+static int
+nexttoggle(int toggle, int count, int maxpkt)
+{
+ int np;
+
+ np = count / maxpkt;
+ if(np == 0)
+ np = 1;
+ if((np % 2) == 0)
+ return toggle;
+ if(toggle == Tddata1)
+ return Tddata0;
+ else
+ return Tddata1;
+}
+
+static Td*
+epgettd(Qio *io, int flags, void *a, int count, int maxpkt)
+{
+ Td *td;
+ ulong pa;
+ int i;
+
+ if(count > Tdmaxpkt)
+ panic("ehci: epgettd: too many bytes");
+ td = tdalloc();
+ td->csw = flags | io->toggle | io->tok | count << Tdlenshift |
+ Tderr2 | Tderr1;
+ coherence();
+
+ /*
+ * use the space wasted by alignment as an
+ * embedded buffer if count bytes fit in there.
+ */
+ assert(Align > sizeof(Td));
+ if(count <= Align - sizeof(Td)){
+ td->data = td->sbuff;
+ td->buff = nil;
+ }else
+ td->data = td->buff = smalloc(Tdmaxpkt);
+
+ pa = PADDR(td->data);
+ for(i = 0; i < nelem(td->buffer); i++){
+ td->buffer[i] = pa;
+ if(i > 0)
+ td->buffer[i] &= ~0xFFF;
+ pa += 0x1000;
+ }
+ td->ndata = count;
+ if(a != nil && count > 0)
+ memmove(td->data, a, count);
+ coherence();
+ io->toggle = nexttoggle(io->toggle, count, maxpkt);
+ coherence();
+ return td;
+}
+
+/*
+ * Try to get them idle
+ */
+static void
+aborttds(Qh *qh)
+{
+ Td *td;
+
+ qh->state = Qdone;
+ coherence();
+ if(qh->sched >= 0 && (qh->eps0 & Qhspeedmask) != Qhhigh)
+ qh->eps0 |= Qhint; /* inactivate on next pass */
+ coherence();
+ for(td = qh->tds; td != nil; td = td->next){
+ if(td->csw & Tdactive)
+ td->ndata = 0;
+ td->csw |= Tdhalt;
+ coherence();
+ }
+}
+
+/*
+ * Some controllers do not post the usb/error interrupt after
+ * the work has been done. It seems that we must poll for them.
+ */
+static int
+workpending(void *a)
+{
+ Ctlr *ctlr;
+
+ ctlr = a;
+ return ctlr->nreqs > 0;
+}
+
+static void
+ehcipoll(void* a)
+{
+ Hci *hp;
+ Ctlr *ctlr;
+ Poll *poll;
+ int i;
+
+ hp = a;
+ ctlr = hp->aux;
+ poll = &ctlr->poll;
+ for(;;){
+ if(ctlr->nreqs == 0){
+ if(0)ddprint("ehcipoll %#p sleep\n", ctlr->capio);
+ sleep(poll, workpending, ctlr);
+ if(0)ddprint("ehcipoll %#p awaken\n", ctlr->capio);
+ }
+ for(i = 0; i < 16 && ctlr->nreqs > 0; i++)
+ if(ehciintr(hp) == 0)
+ break;
+ do{
+ tsleep(&up->sleep, return0, 0, 1);
+ ehciintr(hp);
+ }while(ctlr->nreqs > 0);
+ }
+}
+
+static void
+pollcheck(Hci *hp)
+{
+ Ctlr *ctlr;
+ Poll *poll;
+
+ ctlr = hp->aux;
+ poll = &ctlr->poll;
+
+ if(poll->must != 0 && poll->does == 0){
+ lock(poll);
+ if(poll->must != 0 && poll->does == 0){
+ poll->does++;
+ print("ehci %#p: polling\n", ctlr->capio);
+ kproc("ehcipoll", ehcipoll, hp);
+ }
+ unlock(poll);
+ }
+}
+
+static int
+epiodone(void *a)
+{
+ Qh *qh;
+
+ qh = a;
+ return qh->state != Qrun;
+}
+
+static void
+epiowait(Hci *hp, Qio *io, int tmout, ulong load)
+{
+ Qh *qh;
+ int timedout;
+ Ctlr *ctlr;
+
+ ctlr = hp->aux;
+ qh = io->qh;
+ ddqprint("ehci io %#p sleep on qh %#p state %s\n",
+ io, qh, qhsname[qh->state]);
+ timedout = 0;
+ if(waserror()){
+ dqprint("ehci io %#p qh %#p timed out\n", io, qh);
+ timedout++;
+ }else{
+ if(tmout == 0)
+ sleep(io, epiodone, qh);
+ else
+ tsleep(io, epiodone, qh, tmout);
+ poperror();
+ }
+
+ ilock(ctlr);
+ /* Are we missing interrupts? */
+ if(qh->state == Qrun){
+ iunlock(ctlr);
+ ehciintr(hp);
+ ilock(ctlr);
+ if(qh->state == Qdone){
+ dqprint("ehci %#p: polling required\n", ctlr->capio);
+ ctlr->poll.must = 1;
+ pollcheck(hp);
+ }
+ }
+
+ if(qh->state == Qrun){
+ dqprint("ehci io %#p qh %#p timed out (no intr?)\n", io, qh);
+ timedout = 1;
+ }else if(qh->state != Qdone && qh->state != Qclose)
+ panic("ehci: epio: queue state %d", qh->state);
+ if(timedout){
+ aborttds(io->qh);
+ io->err = "request timed out";
+ iunlock(ctlr);
+ if(!waserror()){
+ tsleep(&up->sleep, return0, 0, Abortdelay);
+ poperror();
+ }
+ ilock(ctlr);
+ }
+ if(qh->state != Qclose)
+ qh->state = Qidle;
+ coherence();
+ qhlinktd(qh, nil);
+ ctlr->load -= load;
+ ctlr->nreqs--;
+ iunlock(ctlr);
+}
+
+/*
+ * Non iso I/O.
+ * To make it work for control transfers, the caller may
+ * lock the Qio for the entire control transfer.
+ */
+static long
+epio(Ep *ep, Qio *io, void *a, long count, int mustlock)
+{
+ int saved, ntds, tmout;
+ long n, tot;
+ ulong load;
+ char *err;
+ char buf[128];
+ uchar *c;
+ Ctlr *ctlr;
+ Qh* qh;
+ Td *td, *ltd, *td0, *ntd;
+
+ qh = io->qh;
+ ctlr = ep->hp->aux;
+ io->debug = ep->debug;
+ tmout = ep->tmout;
+ ddeprint("epio: %s ep%d.%d io %#p count %ld load %uld\n",
+ io->tok == Tdtokin ? "in" : "out",
+ ep->dev->nb, ep->nb, io, count, ctlr->load);
+ if((ehcidebug > 1 || ep->debug > 1) && io->tok != Tdtokin){
+ seprintdata(buf, buf+sizeof(buf), a, count);
+ print("echi epio: user data: %s\n", buf);
+ }
+ if(mustlock){
+ qlock(io);
+ if(waserror()){
+ qunlock(io);
+ nexterror();
+ }
+ }
+ io->err = nil;
+ ilock(ctlr);
+ if(qh->state == Qclose){ /* Tds released by cancelio */
+ iunlock(ctlr);
+ error(io->err ? io->err : Eio);
+ }
+ if(qh->state != Qidle)
+ panic("epio: qh not idle");
+ qh->state = Qinstall;
+ iunlock(ctlr);
+
+ c = a;
+ td0 = ltd = nil;
+ load = tot = 0;
+ do{
+ n = (Tdmaxpkt / ep->maxpkt) * ep->maxpkt;
+ if(count-tot < n)
+ n = count-tot;
+ if(c != nil && io->tok != Tdtokin)
+ td = epgettd(io, Tdactive, c+tot, n, ep->maxpkt);
+ else
+ td = epgettd(io, Tdactive, nil, n, ep->maxpkt);
+ if(td0 == nil)
+ td0 = td;
+ else
+ tdlinktd(ltd, td);
+ ltd = td;
+ tot += n;
+ load += ep->load;
+ }while(tot < count);
+ if(td0 == nil || ltd == nil)
+ panic("epio: no td");
+
+ ltd->csw |= Tdioc; /* the last one interrupts */
+ coherence();
+
+ ddeprint("ehci: load %uld ctlr load %uld\n", load, ctlr->load);
+ if(ehcidebug > 1 || ep->debug > 1)
+ dumptd(td0, "epio: put: ");
+
+ ilock(ctlr);
+ if(qh->state != Qclose){
+ io->iotime = TK2MS(MACHP(0)->ticks);
+ qh->state = Qrun;
+ coherence();
+ qhlinktd(qh, td0);
+ ctlr->nreqs++;
+ ctlr->load += load;
+ }
+ iunlock(ctlr);
+
+ if(ctlr->poll.does)
+ wakeup(&ctlr->poll);
+
+ epiowait(ep->hp, io, tmout, load);
+ if(ehcidebug > 1 || ep->debug > 1){
+ dumptd(td0, "epio: got: ");
+ qhdump(qh);
+ }
+
+ tot = 0;
+ c = a;
+ saved = 0;
+ ntds = 0;
+ for(td = td0; td != nil; td = ntd){
+ ntds++;
+ /*
+ * Use td tok, not io tok, because of setup packets.
+ * Also, if the Td was stalled or active (previous Td
+ * was a short packet), we must save the toggle as it is.
+ */
+ if(td->csw & (Tdhalt|Tdactive)){
+ if(saved++ == 0) {
+ io->toggle = td->csw & Tddata1;
+ coherence();
+ }
+ }else{
+ tot += td->ndata;
+ if(c != nil && (td->csw & Tdtok) == Tdtokin && td->ndata > 0){
+ memmove(c, td->data, td->ndata);
+ c += td->ndata;
+ }
+ }
+ ntd = td->next;
+ tdfree(td);
+ }
+ err = io->err;
+ if(mustlock){
+ qunlock(io);
+ poperror();
+ }
+ ddeprint("epio: io %#p: %d tds: return %ld err '%s'\n",
+ io, ntds, tot, err);
+ if(err == Estalled)
+ return 0; /* that's our convention */
+ if(err != nil)
+ error(err);
+ if(tot < 0)
+ error(Eio);
+ return tot;
+}
+
+static long
+epread(Ep *ep, void *a, long count)
+{
+ Ctlio *cio;
+ Qio *io;
+ Isoio *iso;
+ char buf[160];
+ ulong delta;
+
+ ddeprint("ehci: epread\n");
+ if(ep->aux == nil)
+ panic("epread: not open");
+
+ pollcheck(ep->hp);
+
+ switch(ep->ttype){
+ case Tctl:
+ cio = ep->aux;
+ qlock(cio);
+ if(waserror()){
+ qunlock(cio);
+ nexterror();
+ }
+ ddeprint("epread ctl ndata %d\n", cio->ndata);
+ if(cio->ndata < 0)
+ error("request expected");
+ else if(cio->ndata == 0){
+ cio->ndata = -1;
+ count = 0;
+ }else{
+ if(count > cio->ndata)
+ count = cio->ndata;
+ if(count > 0)
+ memmove(a, cio->data, count);
+ /* BUG for big transfers */
+ free(cio->data);
+ cio->data = nil;
+ cio->ndata = 0; /* signal EOF next time */
+ }
+ qunlock(cio);
+ poperror();
+ if(ehcidebug>1 || ep->debug){
+ seprintdata(buf, buf+sizeof(buf), a, count);
+ print("epread: %s\n", buf);
+ }
+ return count;
+ case Tbulk:
+ io = ep->aux;
+ if(ep->clrhalt)
+ clrhalt(ep);
+ return epio(ep, &io[OREAD], a, count, 1);
+ case Tintr:
+ io = ep->aux;
+ delta = TK2MS(MACHP(0)->ticks) - io[OREAD].iotime + 1;
+ if(delta < ep->pollival / 2)
+ tsleep(&up->sleep, return0, 0, ep->pollival/2 - delta);
+ if(ep->clrhalt)
+ clrhalt(ep);
+ return epio(ep, &io[OREAD], a, count, 1);
+ case Tiso:
+ iso = ep->aux;
+ return episoread(ep, iso, a, count);
+ }
+ return -1;
+}
+
+/*
+ * Control transfers are one setup write (data0)
+ * plus zero or more reads/writes (data1, data0, ...)
+ * plus a final write/read with data1 to ack.
+ * For both host to device and device to host we perform
+ * the entire transfer when the user writes the request,
+ * and keep any data read from the device for a later read.
+ * We call epio three times instead of placing all Tds at
+ * the same time because doing so leads to crc/tmout errors
+ * for some devices.
+ * Upon errors on the data phase we must still run the status
+ * phase or the device may cease responding in the future.
+ */
+static long
+epctlio(Ep *ep, Ctlio *cio, void *a, long count)
+{
+ uchar *c;
+ long len;
+
+ ddeprint("epctlio: cio %#p ep%d.%d count %ld\n",
+ cio, ep->dev->nb, ep->nb, count);
+ if(count < Rsetuplen)
+ error("short usb comand");
+ qlock(cio);
+ free(cio->data);
+ cio->data = nil;
+ cio->ndata = 0;
+ if(waserror()){
+ free(cio->data);
+ cio->data = nil;
+ cio->ndata = 0;
+ qunlock(cio);
+ nexterror();
+ }
+
+ /* set the address if unset and out of configuration state */
+ if(ep->dev->state != Dconfig && ep->dev->state != Dreset)
+ if(cio->usbid == 0){
+ cio->usbid = (ep->nb&Epmax) << 7 | ep->dev->nb&Devmax;
+ coherence();
+ qhsetaddr(cio->qh, cio->usbid);
+ }
+ /* adjust maxpkt if the user has learned a different one */
+ if(qhmaxpkt(cio->qh) != ep->maxpkt)
+ qhsetmaxpkt(cio->qh, ep->maxpkt);
+ c = a;
+ cio->tok = Tdtoksetup;
+ cio->toggle = Tddata0;
+ coherence();
+ if(epio(ep, cio, a, Rsetuplen, 0) < Rsetuplen)
+ error(Eio);
+ a = c + Rsetuplen;
+ count -= Rsetuplen;
+
+ cio->toggle = Tddata1;
+ if(c[Rtype] & Rd2h){
+ cio->tok = Tdtokin;
+ len = GET2(c+Rcount);
+ if(len <= 0)
+ error("bad length in d2h request");
+ if(len > Maxctllen)
+ error("d2h data too large to fit in ehci");
+ a = cio->data = smalloc(len+1);
+ }else{
+ cio->tok = Tdtokout;
+ len = count;
+ }
+ coherence();
+ if(len > 0)
+ if(waserror())
+ len = -1;
+ else{
+ len = epio(ep, cio, a, len, 0);
+ poperror();
+ }
+ if(c[Rtype] & Rd2h){
+ count = Rsetuplen;
+ cio->ndata = len;
+ cio->tok = Tdtokout;
+ }else{
+ if(len < 0)
+ count = -1;
+ else
+ count = Rsetuplen + len;
+ cio->tok = Tdtokin;
+ }
+ cio->toggle = Tddata1;
+ coherence();
+ epio(ep, cio, nil, 0, 0);
+ qunlock(cio);
+ poperror();
+ ddeprint("epctlio cio %#p return %ld\n", cio, count);
+ return count;
+}
+
+static long
+epwrite(Ep *ep, void *a, long count)
+{
+ Qio *io;
+ Ctlio *cio;
+ Isoio *iso;
+ ulong delta;
+
+ pollcheck(ep->hp);
+
+ ddeprint("ehci: epwrite ep%d.%d\n", ep->dev->nb, ep->nb);
+ if(ep->aux == nil)
+ panic("ehci: epwrite: not open");
+ switch(ep->ttype){
+ case Tctl:
+ cio = ep->aux;
+ return epctlio(ep, cio, a, count);
+ case Tbulk:
+ io = ep->aux;
+ if(ep->clrhalt)
+ clrhalt(ep);
+ return epio(ep, &io[OWRITE], a, count, 1);
+ case Tintr:
+ io = ep->aux;
+ delta = TK2MS(MACHP(0)->ticks) - io[OWRITE].iotime + 1;
+ if(delta < ep->pollival)
+ tsleep(&up->sleep, return0, 0, ep->pollival - delta);
+ if(ep->clrhalt)
+ clrhalt(ep);
+ return epio(ep, &io[OWRITE], a, count, 1);
+ case Tiso:
+ iso = ep->aux;
+ return episowrite(ep, iso, a, count);
+ }
+ return -1;
+}
+
+static void
+isofsinit(Ep *ep, Isoio *iso)
+{
+ long left;
+ Sitd *td, *ltd;
+ int i;
+ ulong frno;
+
+ left = 0;
+ ltd = nil;
+ frno = iso->td0frno;
+ for(i = 0; i < iso->nframes; i++){
+ td = sitdalloc();
+ td->data = iso->data + i * ep->maxpkt;
+ td->epc = ep->dev->port << Stdportshift;
+ td->epc |= ep->dev->hub << Stdhubshift;
+ td->epc |= ep->nb << Stdepshift;
+ td->epc |= ep->dev->nb << Stddevshift;
+ td->mfs = 034 << Stdscmshift | 1 << Stdssmshift;
+ if(ep->mode == OREAD){
+ td->epc |= Stdin;
+ td->mdata = ep->maxpkt;
+ }else{
+ td->mdata = (ep->hz+left) * ep->pollival / 1000;
+ td->mdata *= ep->samplesz;
+ left = (ep->hz+left) * ep->pollival % 1000;
+ if(td->mdata > ep->maxpkt){
+ print("ehci: ep%d.%d: size > maxpkt\n",
+ ep->dev->nb, ep->nb);
+ print("size = %ld max = %ld\n",
+ td->mdata,ep->maxpkt);
+ td->mdata = ep->maxpkt;
+ }
+ }
+ coherence();
+
+ iso->sitdps[frno] = td;
+ coherence();
+ sitdinit(iso, td);
+ if(ltd != nil)
+ ltd->next = td;
+ ltd = td;
+ frno = TRUNC(frno+ep->pollival, Nisoframes);
+ }
+ ltd->next = iso->sitdps[iso->td0frno];
+ coherence();
+}
+
+static void
+isohsinit(Ep *ep, Isoio *iso)
+{
+ int ival, p;
+ long left;
+ ulong frno, i, pa;
+ Itd *ltd, *td;
+
+ iso->hs = 1;
+ ival = 1;
+ if(ep->pollival > 8)
+ ival = ep->pollival/8;
+ left = 0;
+ ltd = nil;
+ frno = iso->td0frno;
+ for(i = 0; i < iso->nframes; i++){
+ td = itdalloc();
+ td->data = iso->data + i * 8 * iso->maxsize;
+ pa = PADDR(td->data) & ~0xFFF;
+ for(p = 0; p < 8; p++)
+ td->buffer[i] = pa + p * 0x1000;
+ td->buffer[0] = PADDR(iso->data) & ~0xFFF |
+ ep->nb << Itdepshift | ep->dev->nb << Itddevshift;
+ if(ep->mode == OREAD)
+ td->buffer[1] |= Itdin;
+ else
+ td->buffer[1] |= Itdout;
+ td->buffer[1] |= ep->maxpkt << Itdmaxpktshift;
+ td->buffer[2] |= ep->ntds << Itdntdsshift;
+
+ if(ep->mode == OREAD)
+ td->mdata = 8 * iso->maxsize;
+ else{
+ td->mdata = (ep->hz + left) * ep->pollival / 1000;
+ td->mdata *= ep->samplesz;
+ left = (ep->hz + left) * ep->pollival % 1000;
+ }
+ coherence();
+ iso->itdps[frno] = td;
+ coherence();
+ itdinit(iso, td);
+ if(ltd != nil)
+ ltd->next = td;
+ ltd = td;
+ frno = TRUNC(frno + ival, Nisoframes);
+ }
+}
+
+static void
+isoopen(Ctlr *ctlr, Ep *ep)
+{
+ int ival; /* pollival in ms */
+ int tpf; /* tds per frame */
+ int i, n, w, woff;
+ ulong frno;
+ Isoio *iso;
+
+ iso = ep->aux;
+ switch(ep->mode){
+ case OREAD:
+ iso->tok = Tdtokin;
+ break;
+ case OWRITE:
+ iso->tok = Tdtokout;
+ break;
+ default:
+ error("iso i/o is half-duplex");
+ }
+ iso->usbid = ep->nb << 7 | ep->dev->nb & Devmax;
+ iso->state = Qidle;
+ coherence();
+ iso->debug = ep->debug;
+ ival = ep->pollival;
+ tpf = 1;
+ if(ep->dev->speed == Highspeed){
+ tpf = 8;
+ if(ival <= 8)
+ ival = 1;
+ else
+ ival /= 8;
+ }
+ assert(ival != 0);
+ iso->nframes = Nisoframes / ival;
+ if(iso->nframes < 3)
+ error("uhci isoopen bug"); /* we need at least 3 tds */
+ iso->maxsize = ep->ntds * ep->maxpkt;
+ if(ctlr->load + ep->load > 800)
+ print("usb: ehci: bandwidth may be exceeded\n");
+ ilock(ctlr);
+ ctlr->load += ep->load;
+ ctlr->isoload += ep->load;
+ ctlr->nreqs++;
+ dprint("ehci: load %uld isoload %uld\n", ctlr->load, ctlr->isoload);
+ diprint("iso nframes %d pollival %uld ival %d maxpkt %uld ntds %d\n",
+ iso->nframes, ep->pollival, ival, ep->maxpkt, ep->ntds);
+ iunlock(ctlr);
+ if(ctlr->poll.does)
+ wakeup(&ctlr->poll);
+
+ /*
+ * From here on this cannot raise errors
+ * unless we catch them and release here all memory allocated.
+ */
+ assert(ep->maxpkt > 0 && ep->ntds > 0 && ep->ntds < 4);
+ assert(ep->maxpkt <= 1024);
+ iso->tdps = smalloc(sizeof(uintptr) * Nisoframes);
+ iso->data = smalloc(iso->nframes * tpf * ep->ntds * ep->maxpkt);
+ iso->td0frno = TRUNC(ctlr->opio->frno + 10, Nisoframes);
+ /* read: now; write: 1s ahead */
+
+ if(ep->dev->speed == Highspeed)
+ isohsinit(ep, iso);
+ else
+ isofsinit(ep, iso);
+ iso->tdu = iso->tdi = iso->itdps[iso->td0frno];
+ iso->stdu = iso->stdi = iso->sitdps[iso->td0frno];
+ coherence();
+
+ ilock(ctlr);
+ frno = iso->td0frno;
+ for(i = 0; i < iso->nframes; i++){
+ *iso->tdps[frno] = ctlr->frames[frno];
+ frno = TRUNC(frno+ival, Nisoframes);
+ }
+
+ /*
+ * Iso uses a virtual frame window of Nisoframes, and we must
+ * fill the actual ctlr frame array by placing ctlr->nframes/Nisoframes
+ * copies of the window in the frame array.
+ */
+ assert(ctlr->nframes >= Nisoframes && Nisoframes >= iso->nframes);
+ assert(Nisoframes >= Nintrleafs);
+ n = ctlr->nframes / Nisoframes;
+ for(w = 0; w < n; w++){
+ frno = iso->td0frno;
+ woff = w * Nisoframes;
+ for(i = 0; i < iso->nframes ; i++){
+ assert(woff+frno < ctlr->nframes);
+ assert(iso->tdps[frno] != nil);
+ if(ep->dev->speed == Highspeed)
+ ctlr->frames[woff+frno] = PADDR(iso->tdps[frno])
+ |Litd;
+ else
+ ctlr->frames[woff+frno] = PADDR(iso->tdps[frno])
+ |Lsitd;
+ coherence();
+ frno = TRUNC(frno+ep->pollival, Nisoframes);
+ }
+ }
+ coherence();
+ iso->next = ctlr->iso;
+ ctlr->iso = iso;
+ coherence();
+ iso->state = Qdone;
+ iunlock(ctlr);
+ if(ehcidebug > 1 || iso->debug >1)
+ isodump(iso, 0);
+}
+
+/*
+ * Allocate the endpoint and set it up for I/O
+ * in the controller. This must follow what's said
+ * in Ep regarding configuration, including perhaps
+ * the saved toggles (saved on a previous close of
+ * the endpoint data file by epclose).
+ */
+static void
+epopen(Ep *ep)
+{
+ Ctlr *ctlr;
+ Ctlio *cio;
+ Qio *io;
+ int usbid;
+
+ ctlr = ep->hp->aux;
+ deprint("ehci: epopen ep%d.%d\n", ep->dev->nb, ep->nb);
+ if(ep->aux != nil)
+ panic("ehci: epopen called with open ep");
+ if(waserror()){
+ free(ep->aux);
+ ep->aux = nil;
+ nexterror();
+ }
+ switch(ep->ttype){
+ case Tnone:
+ error("endpoint not configured");
+ case Tiso:
+ ep->aux = smalloc(sizeof(Isoio));
+ isoopen(ctlr, ep);
+ break;
+ case Tctl:
+ cio = ep->aux = smalloc(sizeof(Ctlio));
+ cio->debug = ep->debug;
+ cio->ndata = -1;
+ cio->data = nil;
+ if(ep->dev->isroot != 0 && ep->nb == 0) /* root hub */
+ break;
+ cio->qh = qhalloc(ctlr, ep, cio, "epc");
+ break;
+ case Tbulk:
+ ep->pollival = 1; /* assume this; doesn't really matter */
+ /* and fall... */
+ case Tintr:
+ io = ep->aux = smalloc(sizeof(Qio)*2);
+ io[OREAD].debug = io[OWRITE].debug = ep->debug;
+ usbid = (ep->nb&Epmax) << 7 | ep->dev->nb &Devmax;
+ assert(ep->pollival != 0);
+ if(ep->mode != OREAD){
+ if(ep->toggle[OWRITE] != 0)
+ io[OWRITE].toggle = Tddata1;
+ else
+ io[OWRITE].toggle = Tddata0;
+ io[OWRITE].tok = Tdtokout;
+ io[OWRITE].usbid = usbid;
+ io[OWRITE].bw = ep->maxpkt*1000/ep->pollival; /* bytes/s */
+ io[OWRITE].qh = qhalloc(ctlr, ep, io+OWRITE, "epw");
+ }
+ if(ep->mode != OWRITE){
+ if(ep->toggle[OREAD] != 0)
+ io[OREAD].toggle = Tddata1;
+ else
+ io[OREAD].toggle = Tddata0;
+ io[OREAD].tok = Tdtokin;
+ io[OREAD].usbid = usbid;
+ io[OREAD].bw = ep->maxpkt*1000/ep->pollival; /* bytes/s */
+ io[OREAD].qh = qhalloc(ctlr, ep, io+OREAD, "epr");
+ }
+ break;
+ }
+ coherence();
+ if(ehcidebug>1 || ep->debug)
+ dump(ep->hp);
+ deprint("ehci: epopen done\n");
+ poperror();
+}
+
+static void
+cancelio(Ctlr *ctlr, Qio *io)
+{
+ Qh *qh;
+
+ ilock(ctlr);
+ qh = io->qh;
+ if(io == nil || io->qh == nil || io->qh->state == Qclose){
+ iunlock(ctlr);
+ return;
+ }
+ dqprint("ehci: cancelio for qh %#p state %s\n",
+ qh, qhsname[qh->state]);
+ aborttds(qh);
+ qh->state = Qclose;
+ iunlock(ctlr);
+ if(!waserror()){
+ tsleep(&up->sleep, return0, 0, Abortdelay);
+ poperror();
+ }
+ wakeup(io);
+ qlock(io);
+ /* wait for epio if running */
+ qunlock(io);
+
+ qhfree(ctlr, qh);
+ io->qh = nil;
+}
+
+static void
+cancelisoio(Ctlr *ctlr, Isoio *iso, int pollival, ulong load)
+{
+ int frno, i, n, t, w, woff;
+ ulong *lp, *tp;
+ Isoio **il;
+ Itd *td;
+ Sitd *std;
+
+ ilock(ctlr);
+ if(iso->state == Qclose){
+ iunlock(ctlr);
+ return;
+ }
+ ctlr->nreqs--;
+ if(iso->state != Qrun && iso->state != Qdone)
+ panic("bad iso state");
+ iso->state = Qclose;
+ coherence();
+ if(ctlr->isoload < load)
+ panic("ehci: low isoload");
+ ctlr->isoload -= load;
+ ctlr->load -= load;
+ for(il = &ctlr->iso; *il != nil; il = &(*il)->next)
+ if(*il == iso)
+ break;
+ if(*il == nil)
+ panic("cancleiso: not found");
+ *il = iso->next;
+
+ frno = iso->td0frno;
+ for(i = 0; i < iso->nframes; i++){
+ tp = iso->tdps[frno];
+ if(iso->hs != 0){
+ td = iso->itdps[frno];
+ for(t = 0; t < nelem(td->csw); t++)
+ td->csw[t] &= ~(Itdioc|Itdactive);
+ }else{
+ std = iso->sitdps[frno];
+ std->csw &= ~(Stdioc|Stdactive);
+ }
+ coherence();
+ for(lp = &ctlr->frames[frno]; !(*lp & Lterm);
+ lp = &LPTR(*lp)[0])
+ if(LPTR(*lp) == tp)
+ break;
+ if(*lp & Lterm)
+ panic("cancelisoio: td not found");
+ *lp = tp[0];
+ /*
+ * Iso uses a virtual frame window of Nisoframes, and we must
+ * restore pointers in copies of the window kept at ctlr->frames.
+ */
+ if(lp == &ctlr->frames[frno]){
+ n = ctlr->nframes / Nisoframes;
+ for(w = 1; w < n; w++){
+ woff = w * Nisoframes;
+ ctlr->frames[woff+frno] = *lp;
+ }
+ }
+ coherence();
+ frno = TRUNC(frno+pollival, Nisoframes);
+ }
+ iunlock(ctlr);
+
+ /*
+ * wakeup anyone waiting for I/O and
+ * wait to be sure no I/O is in progress in the controller.
+ * and then wait to be sure episo* is no longer running.
+ */
+ wakeup(iso);
+ diprint("cancelisoio iso %#p waiting for I/O to cease\n", iso);
+ tsleep(&up->sleep, return0, 0, 5);
+ qlock(iso);
+ qunlock(iso);
+ diprint("cancelisoio iso %#p releasing iso\n", iso);
+
+ frno = iso->td0frno;
+ for(i = 0; i < iso->nframes; i++){
+ if(iso->hs != 0)
+ itdfree(iso->itdps[frno]);
+ else
+ sitdfree(iso->sitdps[frno]);
+ iso->tdps[frno] = nil;
+ frno = TRUNC(frno+pollival, Nisoframes);
+ }
+ free(iso->tdps);
+ iso->tdps = nil;
+ free(iso->data);
+ iso->data = nil;
+ coherence();
+}
+
+static void
+epclose(Ep *ep)
+{
+ Qio *io;
+ Ctlio *cio;
+ Isoio *iso;
+ Ctlr *ctlr;
+
+ ctlr = ep->hp->aux;
+ deprint("ehci: epclose ep%d.%d\n", ep->dev->nb, ep->nb);
+
+ if(ep->aux == nil)
+ panic("ehci: epclose called with closed ep");
+ switch(ep->ttype){
+ case Tctl:
+ cio = ep->aux;
+ cancelio(ctlr, cio);
+ free(cio->data);
+ cio->data = nil;
+ break;
+ case Tintr:
+ case Tbulk:
+ io = ep->aux;
+ ep->toggle[OREAD] = ep->toggle[OWRITE] = 0;
+ if(ep->mode != OWRITE){
+ cancelio(ctlr, &io[OREAD]);
+ if(io[OREAD].toggle == Tddata1)
+ ep->toggle[OREAD] = 1;
+ }
+ if(ep->mode != OREAD){
+ cancelio(ctlr, &io[OWRITE]);
+ if(io[OWRITE].toggle == Tddata1)
+ ep->toggle[OWRITE] = 1;
+ }
+ coherence();
+ break;
+ case Tiso:
+ iso = ep->aux;
+ cancelisoio(ctlr, iso, ep->pollival, ep->load);
+ break;
+ default:
+ panic("epclose: bad ttype");
+ }
+ free(ep->aux);
+ ep->aux = nil;
+}
+
+/*
+ * return smallest power of 2 >= n
+ */
+static int
+flog2(int n)
+{
+ int i;
+
+ for(i = 0; (1 << i) < n; i++)
+ ;
+ return i;
+}
+
+/*
+ * build the periodic scheduling tree:
+ * framesize must be a multiple of the tree size
+ */
+static void
+mkqhtree(Ctlr *ctlr)
+{
+ int i, n, d, o, leaf0, depth;
+ ulong leafs[Nintrleafs];
+ Qh *qh;
+ Qh **tree;
+ Qtree *qt;
+
+ depth = flog2(Nintrleafs);
+ n = (1 << (depth+1)) - 1;
+ qt = mallocz(sizeof(*qt), 1);
+ if(qt == nil)
+ panic("ehci: mkqhtree: no memory");
+ qt->nel = n;
+ qt->depth = depth;
+ qt->bw = mallocz(n * sizeof(qt->bw), 1);
+ qt->root = tree = mallocz(n * sizeof(Qh *), 1);
+ if(qt->bw == nil || tree == nil)
+ panic("ehci: mkqhtree: no memory");
+ for(i = 0; i < n; i++){
+ tree[i] = qh = edalloc();
+ if(qh == nil)
+ panic("ehci: mkqhtree: no memory");
+ qh->nlink = qh->alink = qh->link = Lterm;
+ qh->csw = Tdhalt;
+ qh->state = Qidle;
+ coherence();
+ if(i > 0)
+ qhlinkqh(tree[i], tree[(i-1)/2]);
+ }
+ ctlr->ntree = i;
+ dprint("ehci: tree: %d endpoints allocated\n", i);
+
+ /* distribute leaves evenly round the frame list */
+ leaf0 = n / 2;
+ for(i = 0; i < Nintrleafs; i++){
+ o = 0;
+ for(d = 0; d < depth; d++){
+ o <<= 1;
+ if(i & (1 << d))
+ o |= 1;
+ }
+ if(leaf0 + o >= n){
+ print("leaf0=%d o=%d i=%d n=%d\n", leaf0, o, i, n);
+ break;
+ }
+ leafs[i] = PADDR(tree[leaf0 + o]) | Lqh;
+ }
+ assert((ctlr->nframes % Nintrleafs) == 0);
+ for(i = 0; i < ctlr->nframes; i += Nintrleafs){
+ memmove(ctlr->frames + i, leafs, sizeof leafs);
+ coherence();
+ }
+ ctlr->tree = qt;
+ coherence();
+}
+
+void
+ehcimeminit(Ctlr *ctlr)
+{
+ int i, frsize;
+ Eopio *opio;
+
+ opio = ctlr->opio;
+ frsize = ctlr->nframes * sizeof(ulong);
+ assert((frsize & 0xFFF) == 0); /* must be 4k aligned */
+ ctlr->frames = xspanalloc(frsize, frsize, 0);
+ if(ctlr->frames == nil)
+ panic("ehci reset: no memory");
+
+ for (i = 0; i < ctlr->nframes; i++)
+ ctlr->frames[i] = Lterm;
+ opio->frbase = PADDR(ctlr->frames);
+ opio->frno = 0;
+ coherence();
+
+ qhalloc(ctlr, nil, nil, nil); /* init async list */
+ mkqhtree(ctlr); /* init sync list */
+ edfree(edalloc()); /* try to get some ones pre-allocated */
+
+ dprint("ehci %#p flb %#lux frno %#lux\n",
+ ctlr->capio, opio->frbase, opio->frno);
+}
+
+static void
+init(Hci *hp)
+{
+ Ctlr *ctlr;
+ Eopio *opio;
+ int i;
+
+ hp->highspeed = 1;
+ ctlr = hp->aux;
+ opio = ctlr->opio;
+ dprint("ehci %#p init\n", ctlr->capio);
+
+ ilock(ctlr);
+ /*
+ * Unless we activate frroll interrupt
+ * some machines won't post other interrupts.
+ */
+ opio->intr = Iusb|Ierr|Iportchg|Ihcerr|Iasync;
+ coherence();
+ opio->cmd |= Cpse;
+ coherence();
+ opio->cmd |= Case;
+ coherence();
+ ehcirun(ctlr, 1);
+ opio->config = Callmine; /* reclaim all ports */
+ coherence();
+
+ for (i = 0; i < hp->nports; i++)
+ opio->portsc[i] = Pspower;
+ iunlock(ctlr);
+ if(ehcidebug > 1)
+ dump(hp);
+}
+
+void
+ehcilinkage(Hci *hp)
+{
+ hp->init = init;
+ hp->dump = dump;
+ hp->interrupt = interrupt;
+ hp->epopen = epopen;
+ hp->epclose = epclose;
+ hp->epread = epread;
+ hp->epwrite = epwrite;
+ hp->seprintep = seprintep;
+ hp->portenable = portenable;
+ hp->portreset = portreset;
+ hp->portstatus = portstatus;
+// hp->shutdown = shutdown;
+// hp->debug = setdebug;
+ hp->type = "ehci";
+}
diff --git a/sys/src/9/port/xalloc.c b/sys/src/9/port/xalloc.c
new file mode 100755
index 000000000..873cbe021
--- /dev/null
+++ b/sys/src/9/port/xalloc.c
@@ -0,0 +1,273 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+enum
+{
+ Nhole = 128,
+ Magichole = 0x484F4C45, /* HOLE */
+};
+
+typedef struct Hole Hole;
+typedef struct Xalloc Xalloc;
+typedef struct Xhdr Xhdr;
+
+struct Hole
+{
+ ulong addr;
+ ulong size;
+ ulong top;
+ Hole* link;
+};
+
+struct Xhdr
+{
+ ulong size;
+ ulong magix;
+ char data[];
+};
+
+struct Xalloc
+{
+ Lock;
+ Hole hole[Nhole];
+ Hole* flist;
+ Hole* table;
+};
+
+static Xalloc xlists;
+
+void
+xinit(void)
+{
+ int i, n, upages, kpages;
+ ulong maxpages;
+ Confmem *m;
+ Pallocmem *pm;
+ Hole *h, *eh;
+
+ eh = &xlists.hole[Nhole-1];
+ for(h = xlists.hole; h < eh; h++)
+ h->link = h+1;
+
+ xlists.flist = xlists.hole;
+
+ upages = conf.upages;
+ kpages = conf.npage - upages;
+ pm = palloc.mem;
+ for(i=0; i<nelem(conf.mem); i++){
+ m = &conf.mem[i];
+ n = m->npage;
+ if(n > kpages)
+ n = kpages;
+ /* don't try to use non-KADDR-able memory for kernel */
+ maxpages = cankaddr(m->base)/BY2PG;
+ if(n > maxpages)
+ n = maxpages;
+ /* first give to kernel */
+ if(n > 0){
+ m->kbase = (ulong)KADDR(m->base);
+ m->klimit = (ulong)KADDR(m->base+n*BY2PG);
+ xhole(m->base, n*BY2PG);
+ kpages -= n;
+ }
+ /* if anything left over, give to user */
+ if(n < m->npage){
+ if(pm >= palloc.mem+nelem(palloc.mem)){
+ print("xinit: losing %lud pages\n", m->npage-n);
+ continue;
+ }
+ pm->base = m->base+n*BY2PG;
+ pm->npage = m->npage - n;
+ pm++;
+ }
+ }
+ xsummary();
+}
+
+void*
+xspanalloc(ulong size, int align, ulong span)
+{
+ ulong a, v, t;
+ a = (ulong)xalloc(size+align+span);
+ if(a == 0)
+ panic("xspanalloc: %lud %d %lux", size, align, span);
+
+ if(span > 2) {
+ v = (a + span) & ~(span-1);
+ t = v - a;
+ if(t > 0)
+ xhole(PADDR(a), t);
+ t = a + span - v;
+ if(t > 0)
+ xhole(PADDR(v+size+align), t);
+ }
+ else
+ v = a;
+
+ if(align > 1)
+ v = (v + align) & ~(align-1);
+
+ return (void*)v;
+}
+
+void*
+xallocz(ulong size, int zero)
+{
+ Xhdr *p;
+ Hole *h, **l;
+
+ /* add room for magix & size overhead, round up to nearest vlong */
+ size += BY2V + offsetof(Xhdr, data[0]);
+ size &= ~(BY2V-1);
+
+ ilock(&xlists);
+ l = &xlists.table;
+ for(h = *l; h; h = h->link) {
+ if(h->size >= size) {
+ p = (Xhdr*)KADDR(h->addr);
+ h->addr += size;
+ h->size -= size;
+ if(h->size == 0) {
+ *l = h->link;
+ h->link = xlists.flist;
+ xlists.flist = h;
+ }
+ iunlock(&xlists);
+ if(zero)
+ memset(p, 0, size);
+ p->magix = Magichole;
+ p->size = size;
+ return p->data;
+ }
+ l = &h->link;
+ }
+ iunlock(&xlists);
+ return nil;
+}
+
+void*
+xalloc(ulong size)
+{
+ return xallocz(size, 1);
+}
+
+void
+xfree(void *p)
+{
+ Xhdr *x;
+
+ x = (Xhdr*)((ulong)p - offsetof(Xhdr, data[0]));
+ if(x->magix != Magichole) {
+ xsummary();
+ panic("xfree(%#p) %#ux != %#lux", p, Magichole, x->magix);
+ }
+ xhole(PADDR((uintptr)x), x->size);
+}
+
+int
+xmerge(void *vp, void *vq)
+{
+ Xhdr *p, *q;
+
+ p = (Xhdr*)(((ulong)vp - offsetof(Xhdr, data[0])));
+ q = (Xhdr*)(((ulong)vq - offsetof(Xhdr, data[0])));
+ if(p->magix != Magichole || q->magix != Magichole) {
+ int i;
+ ulong *wd;
+ void *badp;
+
+ xsummary();
+ badp = (p->magix != Magichole? p: q);
+ wd = (ulong *)badp - 12;
+ for (i = 24; i-- > 0; ) {
+ print("%#p: %lux", wd, *wd);
+ if (wd == badp)
+ print(" <-");
+ print("\n");
+ wd++;
+ }
+ panic("xmerge(%#p, %#p) bad magic %#lux, %#lux",
+ vp, vq, p->magix, q->magix);
+ }
+ if((uchar*)p+p->size == (uchar*)q) {
+ p->size += q->size;
+ return 1;
+ }
+ return 0;
+}
+
+void
+xhole(ulong addr, ulong size)
+{
+ ulong top;
+ Hole *h, *c, **l;
+
+ if(size == 0)
+ return;
+
+ top = addr + size;
+ ilock(&xlists);
+ l = &xlists.table;
+ for(h = *l; h; h = h->link) {
+ if(h->top == addr) {
+ h->size += size;
+ h->top = h->addr+h->size;
+ c = h->link;
+ if(c && h->top == c->addr) {
+ h->top += c->size;
+ h->size += c->size;
+ h->link = c->link;
+ c->link = xlists.flist;
+ xlists.flist = c;
+ }
+ iunlock(&xlists);
+ return;
+ }
+ if(h->addr > addr)
+ break;
+ l = &h->link;
+ }
+ if(h && top == h->addr) {
+ h->addr -= size;
+ h->size += size;
+ iunlock(&xlists);
+ return;
+ }
+
+ if(xlists.flist == nil) {
+ iunlock(&xlists);
+ print("xfree: no free holes, leaked %lud bytes\n", size);
+ return;
+ }
+
+ h = xlists.flist;
+ xlists.flist = h->link;
+ h->addr = addr;
+ h->top = top;
+ h->size = size;
+ h->link = *l;
+ *l = h;
+ iunlock(&xlists);
+}
+
+void
+xsummary(void)
+{
+ int i;
+ Hole *h;
+
+ i = 0;
+ for(h = xlists.flist; h; h = h->link)
+ i++;
+
+ print("%d holes free\n", i);
+ i = 0;
+ for(h = xlists.table; h; h = h->link) {
+ print("%.8lux %.8lux %lud\n", h->addr, h->top, h->size);
+ i += h->size;
+ }
+ print("%d bytes free\n", i);
+}
diff --git a/sys/src/9/ppc/blast b/sys/src/9/ppc/blast
new file mode 100755
index 000000000..5581d7a40
--- /dev/null
+++ b/sys/src/9/ppc/blast
@@ -0,0 +1,59 @@
+dev
+ root
+ cons
+ env
+ flash
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ ssl
+ cap
+ kprof
+ uart
+ irq
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netif netlog nullmedium pktmedium ptclbsum inferno
+
+link
+ etherfcc ethermii
+ ethermedium
+ netdevmedium
+ loopbackmedium
+
+misc
+ uartsmc
+ m8260
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+
+port
+ int cpuserver = 1;
+
+boot cpu
+ tcp
+
+bootdir
+ /power/bin/rc
+ /rc/lib/rcmain
+ /power/bin/bind
+ /power/bin/sed
+ /power/bin/srv
+ /power/bin/cat
+ /power/bin/cp
+ /power/bin/rm
+ /power/bin/echo
+ /power/bin/mount
+ /power/bin/sleep
+ /power/bin/ip/ipconfig
+ /power/bin/auth/factotum
+ /power/bin/ls
+ /power/bin/auth/wrkey
+ /sys/lib/sysconfig/blast/boot
diff --git a/sys/src/9/ppc/blast.h b/sys/src/9/ppc/blast.h
new file mode 100755
index 000000000..4b4904842
--- /dev/null
+++ b/sys/src/9/ppc/blast.h
@@ -0,0 +1,99 @@
+/*
+ * Here, we define everything that is specific for the blast board from Crawford Hill
+ */
+
+
+/* Clock speed of the blast board */
+#define CLKIN 72000000
+
+/*
+ * Blast memory layout:
+ * CS0: FE000000 -> FFFFFFFF (Flash)
+ * CS1: FC000000 -> FCFFFFFF (DSP hpi)
+ * CS2: 00000000 -> 03FFFFFF (60x sdram)
+ * CS3: 04000000 -> 04FFFFFF (FPGA)
+ * CS4: 05000000 -> 06FFFFFF (local bus sdram)
+ * CS5: 07000000 -> 070FFFFF (eeprom - not populated)
+ * CS6: E0000000 -> E0FFFFFF (FPGA)
+ *
+ * Main Board memory lay out:
+ * CS0: FE000000 -> FEFFFFFF (16 M FLASH)
+ * CS1: FC000000 -> FCFFFFFF (16 M DSP1)
+ * CS2: 00000000 -> 03FFFFFF (64 M SDRAM)
+ * CS3: 04000000 -> 04FFFFFF (16M DSP2)
+ * CS4: 05000000 -> 06FFFFFF (32 M Local SDRAM)
+ * CS5: 07000000 -> 070FFFFF (eeprom - not populated)
+ * CS6: E0000000 -> E0FFFFFF (16 M FPGA)
+ *
+ * CS2, CS3, CS4, (and CS5) are covered by DBAT 0, CS0 and CS1 by DBAT 3, CS6 by DBAT 2
+ */
+#define FLASHMEM 0xfe000000
+#define FLASHSIZE 0x01000000
+#define DSP1BASE 0xfc000000
+#define DSP1SIZE 0x01000000
+#define MEM1BASE 0x00000000
+#define MEM1SIZE 0x04000000
+#define DSP2BASE 0x04000000
+#define DSP2SIZE 0x01000000
+#define MEM2BASE 0x05000000
+/* #define MEM2SIZE 0x02000000 */
+#define MEM2SIZE 0
+#define FPGABASE 0xe0000000
+#define FPGASIZE 0x01000000
+
+#define PLAN9INI 0x00460000
+
+#define TLBENTRIES 32
+/*
+ * PTE bits for fault.c. These belong to the second PTE word. Validity is
+ * implied for putmmu(), and we always set PTE0_V. PTEVALID is used
+ * here to set cache policy bits on a global basis.
+ */
+#define PTEVALID PTE1_M
+#define PTEWRITE (PTE1_RW|PTE1_C)
+#define PTERONLY PTE1_RO
+#define PTEUNCACHED PTE1_I
+
+/* SMC Uart configuration */
+#define SMC1PORT 3 /* Port D */
+#define SMTXD1 BIT(9)
+#define SMRXD1 BIT(8)
+
+/* Ethernet FCC configuration */
+#define A1txer 0x00000004
+#define A1rxdv 0x00000010
+#define A1txen 0x00000008
+#define A1rxer 0x00000020
+#define A1col 0x00000001
+#define A1crs 0x00000002
+#define A1txdat 0x00003c00
+#define A1rxdat 0x0003c000
+#define B2txer 0x00000001
+#define B2rxdv 0x00000002
+#define B2txen 0x00000004
+#define B2rxer 0x00000008
+#define B2col 0x00000010
+#define B2crs 0x00000020
+#define B2txdat 0x000003c0
+#define B2rxdat 0x00003c00
+#define B3rxdv 0x00004000
+#define B3rxer 0x00008000
+#define B3txer 0x00010000
+#define B3txen 0x00020000
+#define B3col 0x00040000
+#define B3crs 0x00080000
+#define B3txdat 0x0f000000
+#define B3rxdat 0x00f00000
+
+#define A1psor0 (A1rxdat | A1txdat)
+#define A1psor1 (A1col | A1crs | A1txer | A1txen | A1rxdv | A1rxer)
+#define A1dir0 (A1rxdat | A1crs | A1col | A1rxer | A1rxdv)
+#define A1dir1 (A1txdat | A1txen | A1txer)
+#define B2psor0 (B2rxdat | B2txdat | B2crs | B2col | B2rxer | B2rxdv | B2txer)
+#define B2psor1 (B2txen)
+#define B2dir0 (B2rxdat | B2crs | B2col | B2rxer | B2rxdv)
+#define B2dir1 (B2txdat | B2txen | B2txer)
+#define B3psor0 (B3rxdat | B3txdat | B3crs | B3col | B3rxer | B3rxdv | B3txer | B3txen)
+#define B3psor1 0
+#define B3dir0 (B3rxdat | B3crs | B3col | B3rxer | B3rxdv)
+#define B3dir1 (B3txdat | B3txen | B3txer)
diff --git a/sys/src/9/ppc/clock.c b/sys/src/9/ppc/clock.c
new file mode 100755
index 000000000..30d350a2d
--- /dev/null
+++ b/sys/src/9/ppc/clock.c
@@ -0,0 +1,88 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "io.h"
+#include "fns.h"
+#include "ureg.h"
+
+static ulong clkreload;
+
+void
+delayloopinit(void)
+{
+ ulong v;
+ uvlong x;
+
+ /* initial value for loopconst set in machinit */
+ m->loopconst = 1000;
+ v = getdec();
+ delay(1000);
+ v -= getdec();
+
+ x = m->loopconst;
+ x *= m->dechz;
+ x /= v;
+ m->loopconst = x;
+}
+
+void
+clockinit(void)
+{
+ m->dechz = m->bushz/4; /* true for all 604e */
+ m->tbhz = m->dechz; /* conjecture; manual doesn't say */
+
+ delayloopinit();
+
+ clkreload = m->dechz/HZ-1;
+ putdec(clkreload);
+}
+
+void
+clockintr(Ureg *)
+{
+ long v;
+
+ v = -getdec();
+ if(v > (clkreload >> 1)){
+ if(v > clkreload)
+ m->ticks += v/clkreload;
+ v = 0;
+ }
+ putdec(clkreload-v);
+}
+
+void
+delay(int l)
+{
+ ulong i, j;
+
+ j = 0;
+ if(m)
+ j = m->loopconst;
+ if(j == 0)
+ j = 1096;
+ while(l-- > 0)
+ for(i=0; i < j; i++)
+ ;
+}
+
+void
+microdelay(int l)
+{
+ ulong i;
+
+ l *= m->loopconst;
+ l += 500;
+ l /= 1000;
+ if(l <= 0)
+ l = 1;
+ for(i = 0; i < l; i++)
+ ;
+}
+
+ulong
+perfticks(void)
+{
+ return (ulong)fastticks(nil);
+}
diff --git a/sys/src/9/ppc/dat.h b/sys/src/9/ppc/dat.h
new file mode 100755
index 000000000..f92367764
--- /dev/null
+++ b/sys/src/9/ppc/dat.h
@@ -0,0 +1,231 @@
+typedef struct Conf Conf;
+typedef struct FPsave FPsave;
+typedef struct ISAConf ISAConf;
+typedef struct Imap Imap;
+typedef struct Label Label;
+typedef struct Lock Lock;
+typedef struct Mach Mach;
+typedef struct Notsave Notsave;
+typedef struct PCArch PCArch;
+typedef struct PMMU PMMU;
+typedef struct Page Page;
+typedef struct Pcidev Pcidev;
+typedef struct Proc Proc;
+typedef struct Sys Sys;
+typedef struct Ureg Ureg;
+typedef struct Vctl Vctl;
+
+#pragma incomplete Ureg
+#pragma incomplete Imap
+
+#define MAXSYSARG 5 /* for mount(fd, mpt, flag, arg, srv) */
+
+/*
+ * parameters for sysproc.c
+ */
+#define AOUT_MAGIC Q_MAGIC
+
+/*
+ * machine dependent definitions used by ../port/dat.h
+ */
+
+struct Lock
+{
+ ulong key; /* semaphore (non-zero = locked) */
+ ulong sr;
+ ulong pc;
+ Proc *p;
+ ulong pid;
+ ushort isilock;
+};
+
+struct Label
+{
+ ulong sp;
+ ulong pc;
+};
+
+/*
+ * Proc.fpstate
+ */
+enum
+{
+ /* Floating point states */
+ FPinit = 0,
+ FPactive = 1,
+ FPinactive = 2,
+ /* Bit that's or-ed in during note handling (FP is illegal in note handlers) */
+ FPillegal = 0x100,
+};
+
+/*
+ * This structure must agree with fpsave and fprestore asm routines
+ */
+struct FPsave
+{
+ double fpreg[32];
+ union {
+ double fpscrd;
+ struct {
+ ulong pad;
+ ulong fpscr;
+ };
+ };
+};
+
+struct Conf
+{
+ ulong nmach; /* processors */
+ ulong nproc; /* processes */
+ ulong npage0; /* total physical pages of memory */
+ ulong npage1; /* total physical pages of memory */
+ 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 */
+ int nswppo; /* max # of pageouts per segment pass */
+ ulong copymode; /* 0 is copy on write, 1 is copy on reference */
+ int monitor; /* has display? */
+ ulong ialloc; /* bytes available for interrupt time allocation */
+ ulong pipeqsize; /* size in bytes of pipe queues */
+};
+
+/*
+ * mmu goo in the Proc structure
+ */
+#define NCOLOR 1
+struct PMMU
+{
+ int mmupid;
+ Ureg *mmureg; /* pointer to ureg structure */
+};
+
+/*
+ * things saved in the Proc structure during a notify
+ */
+struct Notsave
+{
+ ulong UNUSED;
+};
+
+#include "../port/portdat.h"
+
+/*
+ * machine dependent definitions not used by ../port/dat.h
+ */
+/*
+ * Fake kmap
+ */
+typedef void KMap;
+#define VA(k) ((ulong)(k))
+#define kmap(p) (KMap*)((p)->pa|KZERO)
+#define kunmap(k)
+
+struct Mach
+{
+ /* OFFSETS OF THE FOLLOWING KNOWN BY l.s */
+/*0x00*/ int machno; /* physical id of processor */
+/*0x04*/ ulong splpc; /* pc that called splhi() */
+/*0x08*/ Proc *proc; /* current process on this processor */
+ /* Debugging/statistics for software TLB in l.s (therefore, also known by l.s) */
+/*0x0c*/ ulong tlbfault; /* type of last miss */
+/*0x10*/ ulong imiss; /* number of instruction misses */
+/*0x14*/ ulong dmiss; /* number of data misses */
+
+ /* ordering from here on irrelevant */
+
+ Imap* imap;
+
+ ulong ticks; /* of the clock since boot time */
+ Label sched; /* scheduler wakeup */
+ Lock alarmlock; /* access to alarm list */
+ void *alarm; /* alarms bound to this clock */
+ int inclockintr;
+ int cputype;
+ ulong loopconst;
+ Perf perf; /* performance counters */
+
+ Proc* readied; /* for runproc */
+ ulong schedticks; /* next forced context switch */
+
+ ulong clkin; /* basic clock frequency */
+ ulong vco_out;
+ vlong cpuhz;
+ uvlong cyclefreq; /* Frequency of user readable cycle counter */
+ ulong bushz;
+ ulong dechz;
+ ulong tbhz;
+ ulong cpmhz; /* communications processor module frequency */
+ ulong brghz; /* baud rate generator frequency */
+
+ ulong pcclast;
+ uvlong fastclock;
+
+ int tlbpurge; /* # of tlb purges */
+ int pfault; /* # of page faults */
+ int cs;
+ int syscall;
+ int load;
+ int intr;
+ int flushmmu; /* make current proc flush it's mmu state */
+ int ilockdepth;
+
+ ulong ptabbase; /* start of page table in kernel virtual space */
+ int slotgen; /* next pte (byte offset) when pteg is full */
+ int mmupid; /* next mmu pid to use */
+ int sweepcolor;
+ int trigcolor;
+ Rendez sweepr;
+
+ ulong spuriousintr;
+ int lastintr;
+
+ /* MUST BE LAST */
+ int stack[1];
+};
+
+struct
+{
+ Lock;
+ short machs;
+ short exiting;
+ short ispanic;
+}active;
+
+/*
+ * a parsed plan9.ini line
+ */
+#define NISAOPT 8
+
+struct ISAConf {
+ char *type;
+ ulong port;
+ int irq;
+ ulong dma;
+ ulong mem;
+ ulong size;
+ ulong freq;
+
+ int nopt;
+ char *opt[NISAOPT];
+};
+
+struct Vctl {
+ Vctl* next; /* handlers on this vector */
+
+ char name[KNAMELEN]; /* of driver */
+ int isintr; /* interrupt or fault/trap */
+ int irq;
+
+ void (*f)(Ureg*, void*); /* handler to call */
+ void* a; /* argument to call it with */
+};
+
+extern Mach mach0;
+
+extern register Mach *m;
+extern register Proc *up;
+
+extern FPsave initfp;
diff --git a/sys/src/9/ppc/devether.c b/sys/src/9/ppc/devether.c
new file mode 100755
index 000000000..6d58e70dd
--- /dev/null
+++ b/sys/src/9/ppc/devether.c
@@ -0,0 +1,470 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+static Ether *etherxx[MaxEther];
+extern uchar etheraddr[];
+
+Chan*
+etherattach(char* spec)
+{
+ ulong ctlrno;
+ char *p;
+ Chan *chan;
+
+ ctlrno = 0;
+ if(spec && *spec){
+ ctlrno = strtoul(spec, &p, 0);
+ if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
+ error(Ebadarg);
+ }
+ if(etherxx[ctlrno] == 0)
+ error(Enodev);
+
+ chan = devattach('l', spec);
+ chan->dev = ctlrno;
+ if(etherxx[ctlrno]->attach)
+ etherxx[ctlrno]->attach(etherxx[ctlrno]);
+ return chan;
+}
+
+static Walkqid*
+etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
+{
+ return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
+}
+
+static int
+etherstat(Chan* chan, uchar* dp, int n)
+{
+ return netifstat(etherxx[chan->dev], chan, dp, n);
+}
+
+static Chan*
+etheropen(Chan* chan, int omode)
+{
+ return netifopen(etherxx[chan->dev], chan, omode);
+}
+
+static void
+ethercreate(Chan*, char*, int, ulong)
+{
+}
+
+static void
+etherclose(Chan* chan)
+{
+ netifclose(etherxx[chan->dev], chan);
+}
+
+static long
+etherread(Chan* chan, void* buf, long n, vlong off)
+{
+ Ether *ether;
+ ulong offset = off;
+
+ ether = etherxx[chan->dev];
+ if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
+ /*
+ * With some controllers it is necessary to reach
+ * into the chip to extract statistics.
+ */
+ if(NETTYPE(chan->qid.path) == Nifstatqid)
+ return ether->ifstat(ether, buf, n, offset);
+ else if(NETTYPE(chan->qid.path) == Nstatqid)
+ ether->ifstat(ether, buf, 0, offset);
+ }
+
+ return netifread(ether, chan, buf, n, offset);
+}
+
+static Block*
+etherbread(Chan* chan, long n, ulong offset)
+{
+ return netifbread(etherxx[chan->dev], chan, n, offset);
+}
+
+static int
+etherwstat(Chan* chan, uchar* dp, int n)
+{
+ return netifwstat(etherxx[chan->dev], chan, dp, n);
+}
+
+static void
+etherrtrace(Netfile* f, Etherpkt* pkt, int len)
+{
+ int i, n;
+ Block *bp;
+
+ if(qwindow(f->in) <= 0)
+ return;
+ if(len > 58)
+ n = 58;
+ else
+ n = len;
+ bp = iallocb(64);
+ if(bp == nil)
+ return;
+ memmove(bp->wp, pkt->d, n);
+ i = TK2MS(MACHP(0)->ticks);
+ bp->wp[58] = len>>8;
+ bp->wp[59] = len;
+ bp->wp[60] = i>>24;
+ bp->wp[61] = i>>16;
+ bp->wp[62] = i>>8;
+ bp->wp[63] = i;
+ bp->wp += 64;
+ qpass(f->in, bp);
+}
+
+Block*
+etheriq(Ether* ether, Block* bp, int fromwire)
+{
+ Etherpkt *pkt;
+ ushort type;
+ int len, multi, tome, fromme;
+ Netfile **ep, *f, **fp, *fx;
+ Block *xbp;
+
+ ether->inpackets++;
+
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ type = (pkt->type[0]<<8)|pkt->type[1];
+ fx = 0;
+ ep = &ether->f[Ntypes];
+
+ multi = pkt->d[0] & 1;
+ /* check for valid multicast addresses */
+ if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){
+ if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
+ if(fromwire){
+ freeb(bp);
+ bp = 0;
+ }
+ return bp;
+ }
+ }
+
+ /* is it for me? */
+ tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
+ fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
+
+ /*
+ * Multiplex the packet to all the connections which want it.
+ * If the packet is not to be used subsequently (fromwire != 0),
+ * attempt to simply pass it into one of the connections, thereby
+ * saving a copy of the data (usual case hopefully).
+ */
+ for(fp = ether->f; fp < ep; fp++){
+ if(f = *fp)
+ if(f->type == type || f->type < 0)
+ if(tome || multi || f->prom){
+ /* Don't want to hear bridged packets */
+ if(f->bridge && !fromwire && !fromme)
+ continue;
+ if(!f->headersonly){
+ if(fromwire && fx == 0)
+ fx = f;
+ else if(xbp = iallocb(len)){
+ memmove(xbp->wp, pkt, len);
+ xbp->wp += len;
+ qpass(f->in, xbp);
+ }
+ else
+ ether->soverflows++;
+ }
+ else
+ etherrtrace(f, pkt, len);
+ }
+ }
+
+ if(fx){
+ if(qpass(fx->in, bp) < 0)
+ ether->soverflows++;
+ return 0;
+ }
+ if(fromwire){
+ freeb(bp);
+ return 0;
+ }
+
+ return bp;
+}
+
+static int
+etheroq(Ether* ether, Block* bp)
+{
+ int len, loopback, s;
+ Etherpkt *pkt;
+
+ ether->outpackets++;
+ /*
+ * Check if the packet has to be placed back onto the input queue,
+ * i.e. if it's a loopback or broadcast packet or the interface is
+ * in promiscuous mode.
+ * If it's a loopback packet indicate to etheriq that the data isn't
+ * needed and return, etheriq will pass-on or free the block.
+ * To enable bridging to work, only packets that were originated
+ * by this interface are fed back.
+ */
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
+ if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
+ s = splhi();
+ etheriq(ether, bp, 0);
+ splx(s);
+ }
+
+ if(!loopback){
+ qbwrite(ether->oq, bp);
+ ether->transmit(ether);
+ } else
+ freeb(bp);
+
+ return len;
+}
+
+static long
+etherwrite(Chan* chan, void* buf, long n, vlong)
+{
+ Ether *ether;
+ Block *bp;
+ int nn;
+
+ ether = etherxx[chan->dev];
+ if(NETTYPE(chan->qid.path) != Ndataqid) {
+ nn = netifwrite(ether, chan, buf, n);
+ if(nn >= 0)
+ return nn;
+ if(n == sizeof("nonblocking")-1 && strncmp((char*)buf, "nonblocking", n) == 0){
+ qnoblock(ether->oq, 1);
+ return n;
+ }
+ if(ether->ctl!=nil)
+ return ether->ctl(ether,buf,n);
+
+ error(Ebadctl);
+ }
+
+ if(n > ether->maxmtu)
+ error(Etoobig);
+ if(n < ether->minmtu)
+ error(Etoosmall);
+
+ bp = allocb(n);
+ if(waserror()){
+ freeb(bp);
+ nexterror();
+ }
+ memmove(bp->rp, buf, n);
+ memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
+ poperror();
+ bp->wp += n;
+
+ return etheroq(ether, bp);
+}
+
+static long
+etherbwrite(Chan* chan, Block* bp, ulong)
+{
+ Ether *ether;
+ long n;
+
+ n = BLEN(bp);
+ if(NETTYPE(chan->qid.path) != Ndataqid){
+ if(waserror()) {
+ freeb(bp);
+ nexterror();
+ }
+ n = etherwrite(chan, bp->rp, n, 0);
+ poperror();
+ freeb(bp);
+ return n;
+ }
+ ether = etherxx[chan->dev];
+
+ if(n > ether->maxmtu){
+ freeb(bp);
+ error(Etoobig);
+ }
+ if(n < ether->minmtu){
+ freeb(bp);
+ error(Etoosmall);
+ }
+
+ return etheroq(ether, bp);
+}
+
+static struct {
+ char* type;
+ int (*reset)(Ether*);
+} cards[MaxEther+1];
+
+void
+addethercard(char* t, int (*r)(Ether*))
+{
+ static int ncard;
+
+ if(ncard == MaxEther)
+ panic("too many ether cards");
+ cards[ncard].type = t;
+ cards[ncard].reset = r;
+ ncard++;
+}
+
+int
+parseether(uchar *to, char *from)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ for(i = 0; i < 6; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+static void
+etherreset(void)
+{
+ Ether *ether;
+ int i, n, ctlrno;
+ char name[32], buf[128];
+
+ for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+ if(ether == 0)
+ ether = malloc(sizeof(Ether));
+ memset(ether, 0, sizeof(Ether));
+ ether->ctlrno = ctlrno;
+ ether->tbdf = BUSUNKNOWN;
+ ether->mbps = 10;
+ ether->minmtu = ETHERMINTU;
+ ether->maxmtu = ETHERMAXTU;
+ if(isaconfig("ether", ctlrno, ether) == 0)
+ continue;
+ for(n = 0; cards[n].type; n++){
+ if(cistrcmp(cards[n].type, ether->type))
+ continue;
+ memmove(ether->ea, etheraddr, 6);
+ for(i = 0; i < ether->nopt; i++){
+ if(strncmp(ether->opt[i], "ea=", 3))
+ continue;
+ if(parseether(ether->ea, &ether->opt[i][3]) == -1)
+ memset(ether->ea, 0, Eaddrlen);
+ }
+ if(cards[n].reset(ether))
+ break;
+
+ /*
+ * IRQ2 doesn't really exist, it's used to gang the interrupt
+ * controllers together. A device set to IRQ2 will appear on
+ * the second interrupt controller as IRQ9.
+ */
+ if(ether->irq == 2 && BUSTYPE(ether->tbdf) != BusPCI)
+ ether->irq = 9;
+ snprint(name, sizeof(name), "ether%d", ctlrno);
+
+ /*
+ * If ether->irq is <0, it is a hack to indicate no interrupt
+ * used by ethersink.
+ */
+ if(ether->irq >= 0)
+ intrenable(ether->irq, ether->interrupt, ether, name);
+ i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
+ ctlrno, ether->type, ether->mbps, ether->port, ether->irq);
+ if(ether->mem)
+ i += sprint(buf+i, " addr 0x%luX", PADDR(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",
+ ether->ea[0], ether->ea[1], ether->ea[2],
+ ether->ea[3], ether->ea[4], ether->ea[5]);
+ sprint(buf+i, "\n");
+ print(buf);
+
+ if(ether->mbps >= 100){
+ netifinit(ether, name, Ntypes, 256*1024);
+ if(ether->oq == 0)
+ ether->oq = qopen(256*1024, Qmsg, 0, 0);
+ }
+ else{
+ netifinit(ether, name, Ntypes, 65*1024);
+ if(ether->oq == 0)
+ ether->oq = qopen(65*1024, Qmsg, 0, 0);
+ }
+ if(ether->oq == 0)
+ panic("etherreset %s", name);
+ ether->alen = Eaddrlen;
+ memmove(ether->addr, ether->ea, Eaddrlen);
+ memset(ether->bcast, 0xFF, Eaddrlen);
+
+ etherxx[ctlrno] = ether;
+ ether = 0;
+ break;
+ }
+ }
+ if(ether)
+ free(ether);
+}
+
+#define POLY 0xedb88320
+
+/* really slow 32 bit crc for ethers */
+ulong
+ethercrc(uchar *p, int len)
+{
+ int i, j;
+ ulong crc, b;
+
+ crc = 0xffffffff;
+ for(i = 0; i < len; i++){
+ b = *p++;
+ for(j = 0; j < 8; j++){
+ crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
+ b >>= 1;
+ }
+ }
+ return crc;
+}
+
+Dev etherdevtab = {
+ 'l',
+ "ether",
+
+ etherreset,
+ devinit,
+ devshutdown,
+ etherattach,
+ etherwalk,
+ etherstat,
+ etheropen,
+ ethercreate,
+ etherclose,
+ etherread,
+ etherbread,
+ etherwrite,
+ etherbwrite,
+ devremove,
+ etherwstat,
+};
diff --git a/sys/src/9/ppc/devflash.c b/sys/src/9/ppc/devflash.c
new file mode 100755
index 000000000..b6fe365c0
--- /dev/null
+++ b/sys/src/9/ppc/devflash.c
@@ -0,0 +1,963 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+enum {
+ Nflash = 2,
+ Maxwchunk= 1024, /* maximum chunk written by one call to falg->write */
+};
+
+
+/*
+ * Flashes are either 8 or 16 bits wide. On some installations (e.g., the
+ * bitsy, they are interleaved: address 0 is in the first chip, address 2
+ * on the second, address 4 on the first, etc.
+ * We define Funit as the unit that matches the width of a single flash chip,
+ * so Funit is either `uchar' or `ushort' (I haven't seen 32-bit wide flashes),
+ * and we define Fword as the unit that matches a set of interleaved Funits.
+ * We access interleaved flashes simultaneously, by doing single reads and
+ * writes to both. The macro `mirror' takes a command and replicates it for
+ * this purpose.
+ * The Blast board has a non-interleaved 16-bit wide flash. When doing
+ * writes to it, we must swap bytes.
+ */
+
+typedef struct FlashAlg FlashAlg;
+typedef struct Flash Flash;
+typedef struct FlashRegion FlashRegion;
+
+#ifdef WIDTH8
+ typedef uchar Funit; /* Width of the flash (uchar or ushort) */
+# define toendian(x) (x) /* Little or big endianness */
+# define fromendian(x) (x)
+# define reg(x) ((x)<<1)
+# ifdef INTERLEAVED
+# define mirror(x) ((x)<<8|(x)) /* Double query for interleaved flashes */
+ typedef ushort Fword; /* Width after interleaving */
+# define Wshift 1
+# else
+# define mirror(x) (x)
+ typedef uchar Fword;
+# define Wshift 0
+# endif
+#else
+ typedef ushort Funit;
+# define toendian(x) ((x)<<8)
+# define fromendian(x) ((x)>>8)
+# define reg(x) (x)
+# ifdef INTERLEAVED
+# define mirror(x) (toendian(x)<<16|toendian(x))
+ typedef ulong Fword;
+# define Wshift 2
+# else
+# define mirror(x) toendian(x)
+ typedef ushort Fword;
+# define Wshift 1
+# endif
+#endif
+
+/* this defines a contiguous set of erase blocks of one size */
+struct FlashRegion
+{
+ ulong addr; /* start of region */
+ ulong end; /* end of region + 1 */
+ ulong n; /* number of blocks */
+ ulong size; /* size of each block */
+};
+
+struct Flash
+{
+ ISAConf; /* contains size */
+ RWlock;
+ Fword *p;
+ ushort algid; /* access algorithm */
+ FlashAlg *alg;
+ ushort manid; /* manufacturer id */
+ ushort devid; /* device id */
+ int wbsize; /* size of write buffer */
+ ulong nr; /* number of regions */
+ uchar bootprotect;
+ ulong offset; /* beginning offset of this flash */
+ FlashRegion r[32];
+};
+
+/* this defines a particular access algorithm */
+struct FlashAlg
+{
+ int id;
+ char *name;
+ void (*identify)(Flash*); /* identify device */
+ void (*erase)(Flash*, ulong); /* erase a region */
+ void (*write)(Flash*, void*, long, ulong); /* write a region */
+};
+
+static void ise_id(Flash*);
+static void ise_erase(Flash*, ulong);
+static void ise_write(Flash*, void*, long, ulong);
+
+static void afs_id(Flash*);
+static void afs_erase(Flash*, ulong);
+static void afs_write(Flash*, void*, long, ulong);
+
+static ulong blockstart(Flash*, ulong);
+static ulong blockend(Flash*, ulong);
+
+FlashAlg falg[] =
+{
+ { 1, "Intel/Sharp Extended", ise_id, ise_erase, ise_write },
+ { 2, "AMD/Fujitsu Standard", afs_id, afs_erase, afs_write },
+};
+
+Flash flashes[Nflash];
+
+/*
+ * common flash interface
+ */
+static uchar
+cfigetc(Flash *flash, int off)
+{
+ uchar rv;
+
+ flash->p[reg(0x55)] = mirror(0x98);
+ rv = fromendian(flash->p[reg(off)]);
+ flash->p[reg(0x55)] = mirror(0xFF);
+ return rv;
+}
+
+static ushort
+cfigets(Flash *flash, int off)
+{
+ return (cfigetc(flash, off+1)<<8)|cfigetc(flash, off);
+}
+
+static ulong
+cfigetl(Flash *flash, int off)
+{
+ return (cfigetc(flash, off+3)<<24)|(cfigetc(flash, off+2)<<16)|
+ (cfigetc(flash, off+1)<<8)|cfigetc(flash, off);
+}
+
+static void
+cfiquery(Flash *flash)
+{
+ uchar q, r, y;
+ ulong x, addr;
+
+ q = cfigetc(flash, 0x10);
+ r = cfigetc(flash, 0x11);
+ y = cfigetc(flash, 0x12);
+ if(q != 'Q' || r != 'R' || y != 'Y'){
+ print("cfi query failed: %ux %ux %ux\n", q, r, y);
+ return;
+ }
+ flash->algid = cfigetc(flash, 0x13);
+ flash->size = (sizeof(Fword)/sizeof(Funit)) * (1<<(cfigetc(flash, 0x27)));
+ flash->wbsize = (sizeof(Fword)/sizeof(Funit)) * (1<<(cfigetc(flash, 0x2a)));
+ flash->nr = cfigetc(flash, 0x2c);
+ if(flash->nr > nelem(flash->r)){
+ print("cfi reports > %d regions\n", nelem(flash->r));
+ flash->nr = nelem(flash->r);
+ }
+ addr = 0;
+ for(q = 0; q < flash->nr; q++){
+ x = cfigetl(flash, q+0x2d);
+ flash->r[q].size = (sizeof(Fword)/sizeof(Funit)) * 256 * (x>>16);
+ flash->r[q].n = (x&0xffff)+1;
+ flash->r[q].addr = addr;
+ addr += flash->r[q].size*flash->r[q].n;
+ flash->r[q].end = addr;
+ }
+}
+
+/*
+ * flash device interface
+ */
+
+enum
+{
+ Qtopdir,
+ Q2nddir,
+ Qfctl,
+ Qfdata,
+
+ Maxpart= 8,
+};
+
+
+typedef struct FPart FPart;
+struct FPart
+{
+ Flash *flash;
+ char *name;
+ char *ctlname;
+ ulong start;
+ ulong end;
+};
+static FPart part[Maxpart];
+
+#define FQID(p,q) ((p)<<8|(q))
+#define FTYPE(q) ((q) & 0xff)
+#define FPART(q) (&part[(q) >>8])
+
+static int
+gen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
+{
+ Qid q;
+ FPart *fp;
+
+ q.vers = 0;
+
+ /* top level directory contains the name of the network */
+ if(c->qid.path == Qtopdir){
+ switch(i){
+ case DEVDOTDOT:
+ q.path = Qtopdir;
+ q.type = QTDIR;
+ devdir(c, q, "#F", 0, eve, DMDIR|0555, dp);
+ break;
+ case 0:
+ q.path = Q2nddir;
+ q.type = QTDIR;
+ devdir(c, q, "flash", 0, eve, DMDIR|0555, dp);
+ break;
+ default:
+ return -1;
+ }
+ return 1;
+ }
+
+ /* second level contains all partitions and their control files */
+ switch(i) {
+ case DEVDOTDOT:
+ q.path = Qtopdir;
+ q.type = QTDIR;
+ devdir(c, q, "#F", 0, eve, DMDIR|0555, dp);
+ break;
+ default:
+ if(i >= 2*Maxpart)
+ return -1;
+ fp = &part[i>>1];
+ if(fp->name == nil)
+ return 0;
+ if(i & 1){
+ q.path = FQID(i>>1, Qfdata);
+ q.type = QTFILE;
+ devdir(c, q, fp->name, fp->end-fp->start, eve, 0660, dp);
+ } else {
+ q.path = FQID(i>>1, Qfctl);
+ q.type = QTFILE;
+ devdir(c, q, fp->ctlname, 0, eve, 0660, dp);
+ }
+ break;
+ }
+ return 1;
+}
+
+static Flash *
+findflash(ulong addr)
+{
+ Flash *flash;
+
+ for (flash = flashes; flash < flashes + Nflash; flash++)
+ if(addr >= flash->offset && addr < flash->offset + flash->size)
+ return flash;
+ return nil;
+}
+
+static FPart*
+findpart(char *name)
+{
+ int i;
+
+ for(i = 0; i < Maxpart; i++)
+ if(part[i].name != nil && strcmp(name, part[i].name) == 0)
+ break;
+ if(i >= Maxpart)
+ return nil;
+ return &part[i];
+}
+
+static void
+addpart(FPart *fp, char *name, ulong start, ulong end)
+{
+ int i;
+ char ctlname[64];
+ Flash *flash;
+ if (start > end)
+ error(Ebadarg);
+ if(fp == nil){
+ flash = findflash(start);
+ if (flash == nil || end > flash->offset + flash->size)
+ error(Ebadarg);
+ start -= flash->offset;
+ end -= flash->offset;
+ } else {
+ start += fp->start;
+ end += fp->start;
+ if(start >= fp->end || end > fp->end){
+ error(Ebadarg);
+ }
+ flash = fp->flash;
+ }
+ if(blockstart(flash, start) != start)
+ error("must start on erase boundary");
+ if(blockstart(flash, end) != end && end != flash->size)
+ error("must end on erase boundary");
+
+ fp = findpart(name);
+ if(fp != nil)
+ error(Eexist);
+ for(i = 0; i < Maxpart; i++)
+ if(part[i].name == nil)
+ break;
+ if(i == Maxpart)
+ error("no more partitions");
+ fp = &part[i];
+ kstrdup(&fp->name, name);
+ snprint(ctlname, sizeof ctlname, "%sctl", name);
+ kstrdup(&fp->ctlname, ctlname);
+ fp->flash = flash;
+ fp->start = start;
+ fp->end = end;
+}
+
+static void
+rempart(FPart *fp)
+{
+ char *p, *cp;
+
+ p = fp->name;
+ fp->name = nil;
+ cp = fp->ctlname;
+ fp->ctlname = nil;
+ free(p);
+ free(cp);
+}
+
+void
+flashinit(void)
+{
+ int i, ctlrno;
+ char *fname;
+ ulong offset;
+ Flash *flash;
+
+ offset = 0;
+ for (ctlrno = 0; ctlrno < Nflash; ctlrno++){
+ flash = flashes + ctlrno;
+ if(isaconfig("flash", ctlrno, flash) == 0)
+ continue;
+ flash->p = (Fword*)flash->mem;
+ cfiquery(flash);
+ for(i = 0; i < nelem(falg); i++)
+ if(flash->algid == falg[i].id){
+ flash->alg = &falg[i];
+ (*flash->alg->identify)(flash);
+ break;
+ }
+ flash->bootprotect = 1;
+ flash->offset = offset;
+ fname = malloc(8);
+ sprint(fname, "flash%d", ctlrno);
+ addpart(nil, fname, offset, offset + flash->size);
+ offset += flash->size;
+ }
+}
+
+static Chan*
+flashattach(char* spec)
+{
+ return devattach('F', spec);
+}
+
+static Walkqid*
+flashwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, nil, 0, gen);
+}
+
+static int
+flashstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, nil, 0, gen);
+}
+
+static Chan*
+flashopen(Chan* c, int omode)
+{
+ omode = openmode(omode);
+ if(strcmp(up->user, eve)!=0)
+ error(Eperm);
+ return devopen(c, omode, nil, 0, gen);
+}
+
+static void
+flashclose(Chan*)
+{
+}
+
+static long
+flashctlread(FPart *fp, void* a, long n, vlong off)
+{
+ char *buf, *p, *e;
+ int i;
+ ulong addr, end;
+ Flash *flash;
+
+ flash = fp->flash;
+ buf = smalloc(1024);
+ e = buf + 1024;
+ p = seprint(buf, e, "0x%-9lux 0x%-9lux 0x%-9lux 0x%-9x 0x%-9ux 0x%-9ux\n",
+ flash->offset, fp->start, fp->end-fp->start, flash->wbsize, flash->manid, flash->devid);
+ addr = fp->start;
+ for(i = 0; i < flash->nr && addr < fp->end; i++)
+ if(flash->r[i].addr <= addr && flash->r[i].end > addr){
+ if(fp->end <= flash->r[i].end)
+ end = fp->end;
+ else
+ end = flash->r[i].end;
+ p = seprint(p, e, "0x%-9lux 0x%-9lux 0x%-9lux\n", addr,
+ (end-addr)/flash->r[i].size, flash->r[i].size);
+ addr = end;
+ }
+ n = readstr(off, a, n, buf);
+ free(buf);
+ return n;
+}
+
+static long
+flashdataread(FPart *fp, void* a, long n, vlong off)
+{
+ Flash *flash;
+
+ flash = fp->flash;
+ rlock(flash);
+ if(waserror()){
+ runlock(flash);
+ nexterror();
+ }
+ if(fp->name == nil)
+ error("partition vanished");
+ if(!iseve())
+ error(Eperm);
+ off += fp->start;
+ if(off >= fp->end)
+ n = 0;
+ if(off+n >= fp->end)
+ n = fp->end - off;
+ if(n > 0)
+ memmove(a, ((uchar*)flash->mem)+off, n);
+ runlock(flash);
+ poperror();
+
+ return n;
+}
+
+static long
+flashread(Chan* c, void* a, long n, vlong off)
+{
+ int t;
+
+ if(c->qid.type == QTDIR)
+ return devdirread(c, a, n, nil, 0, gen);
+ t = FTYPE(c->qid.path);
+ switch(t){
+ default:
+ error(Eperm);
+ case Qfctl:
+ n = flashctlread(FPART(c->qid.path), a, n, off);
+ break;
+ case Qfdata:
+ n = flashdataread(FPART(c->qid.path), a, n, off);
+ break;
+ }
+ return n;
+}
+
+static void
+bootprotect(ulong addr)
+{
+ FlashRegion *r;
+ Flash *flash;
+
+ flash = findflash(addr);
+ if (flash == nil)
+ error(Ebadarg);
+ if(flash->bootprotect == 0)
+ return;
+ if(flash->nr == 0)
+ error("writing over boot loader disallowed");
+ r = flash->r;
+ if(addr >= r->addr && addr < r->addr + r->size)
+ error("writing over boot loader disallowed");
+}
+
+static ulong
+blockstart(Flash *flash, ulong addr)
+{
+ FlashRegion *r, *e;
+ ulong x;
+
+ r = flash->r;
+ for(e = &flash->r[flash->nr]; r < e; r++){
+ if(addr >= r->addr && addr < r->end){
+ x = addr - r->addr;
+ x /= r->size;
+ return r->addr + x*r->size;
+ }
+ }
+
+ return (ulong)-1;
+}
+
+static ulong
+blockend(Flash *flash, ulong addr)
+{
+ FlashRegion *r, *e;
+ ulong x;
+
+ r = flash->r;
+ for(e = &flash->r[flash->nr]; r < e; r++)
+ if(addr >= r->addr && addr < r->end){
+ x = addr - r->addr;
+ x /= r->size;
+ return r->addr + (x+1)*r->size;
+ }
+
+ return (ulong)-1;
+}
+
+static long
+flashctlwrite(FPart *fp, char *p, long n)
+{
+ Cmdbuf *cmd;
+ ulong off;
+ Flash *flash;
+
+ if(fp == nil)
+ panic("flashctlwrite");
+
+ flash = fp->flash;
+ cmd = parsecmd(p, n);
+ wlock(flash);
+ if(waserror()){
+ wunlock(flash);
+ nexterror();
+ }
+ if(strcmp(cmd->f[0], "erase") == 0){
+ switch(cmd->nf){
+ case 2:
+ /* erase a single block in the partition */
+ off = atoi(cmd->f[1]);
+ off += fp->start;
+ if(off >= fp->end)
+ error("region not in partition");
+ if(off != blockstart(flash, off))
+ error("erase must be a block boundary");
+ bootprotect(off);
+ (*flash->alg->erase)(flash, off);
+ break;
+ case 1:
+ /* erase the whole partition */
+ bootprotect(fp->start);
+ for(off = fp->start; off < fp->end; off = blockend(flash, off))
+ (*flash->alg->erase)(flash, off);
+ break;
+ default:
+ error(Ebadarg);
+ }
+ } else if(strcmp(cmd->f[0], "add") == 0){
+ if(cmd->nf != 4)
+ error(Ebadarg);
+ addpart(fp, cmd->f[1], strtoul(cmd->f[2], nil, 0), strtoul(cmd->f[3], nil, 0));
+ } else if(strcmp(cmd->f[0], "remove") == 0){
+ rempart(fp);
+ } else if(strcmp(cmd->f[0], "protectboot") == 0){
+ if(cmd->nf == 0 || strcmp(cmd->f[1], "off") != 0)
+ flash->bootprotect = 1;
+ else
+ flash->bootprotect = 0;
+ } else
+ error(Ebadarg);
+ poperror();
+ wunlock(flash);
+ free(cmd);
+
+ return n;
+}
+
+static long
+flashdatawrite(FPart *fp, uchar *p, long n, long off)
+{
+ uchar *end;
+ int m;
+ int on;
+ long ooff;
+ uchar *buf;
+ Flash *flash;
+
+ if(fp == nil)
+ panic("flashdatawrite");
+
+ flash = fp->flash;
+ buf = nil;
+ wlock(flash);
+ if(waserror()){
+ wunlock(flash);
+ if(buf != nil)
+ free(buf);
+ nexterror();
+ }
+
+ if(fp->name == nil)
+ error("partition vanished");
+ if(!iseve())
+ error(Eperm);
+
+ /* can't cross partition boundaries */
+ off += fp->start;
+ if(off >= fp->end || off+n > fp->end || n <= 0)
+ error(Ebadarg);
+
+ /* make sure we're not writing the boot sector */
+ bootprotect(off);
+
+ on = n;
+
+ /*
+ * get the data into kernel memory to avoid faults during writing.
+ * if write is not on a quad boundary or not a multiple of 4 bytes,
+ * extend with data already in flash.
+ */
+ buf = smalloc(n+8);
+ m = off & 3;
+ if(m){
+ *(ulong*)buf = flash->p[off>>Wshift];
+ n += m;
+ off -= m;
+ }
+ if(n & 3){
+ n -= n & 3;
+ *(ulong*)(&buf[n]) = flash->p[(off+n)>>Wshift];
+ n += 4;
+ }
+ memmove(&buf[m], p, on);
+
+ /* (*flash->alg->write) can't cross blocks */
+ ooff = off;
+ p = buf;
+ for(end = p + n; p < end; p += m){
+ m = blockend(flash, off) - off;
+ if(m > end - p)
+ m = end - p;
+ if(m > Maxwchunk)
+ m = Maxwchunk;
+ (*flash->alg->write)(flash, p, m, off);
+ off += m;
+ }
+
+ /* make sure write succeeded */
+ if(memcmp(buf, &flash->p[ooff>>Wshift], n) != 0)
+ error("written bytes don't match");
+
+ wunlock(flash);
+ free(buf);
+ poperror();
+
+ return on;
+}
+
+static long
+flashwrite(Chan* c, void* a, long n, vlong off)
+{
+ int t;
+
+ if(c->qid.type == QTDIR)
+ error(Eperm);
+
+ if(!iseve())
+ error(Eperm);
+
+ t = FTYPE(c->qid.path);
+ switch(t){
+ default:
+ panic("flashwrite");
+ case Qfctl:
+ n = flashctlwrite(FPART(c->qid.path), a, n);
+ break;
+ case Qfdata:
+ n = flashdatawrite(FPART(c->qid.path), a, n, off);
+ break;
+ }
+ return n;
+}
+
+Dev flashdevtab = {
+ 'F',
+ "flash",
+
+ devreset,
+ flashinit,
+ devshutdown,
+ flashattach,
+ flashwalk,
+ flashstat,
+ flashopen,
+ devcreate,
+ flashclose,
+ flashread,
+ devbread,
+ flashwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+enum
+{
+ /* status register */
+ ISEs_lockerr= 1<<1,
+ ISEs_powererr= 1<<3,
+ ISEs_progerr= 1<<4,
+ ISEs_eraseerr= 1<<5,
+ ISEs_ready= 1<<7,
+ ISEs_err= (ISEs_lockerr|ISEs_powererr|ISEs_progerr|ISEs_eraseerr),
+
+ /* extended status register */
+ ISExs_bufavail= 1<<7,
+};
+
+/* intel/sharp extended command set */
+static void
+ise_reset(Flash* flash)
+{
+ flash->p[reg(0xaa)] = mirror(0xff); /* reset */
+}
+
+static void
+ise_id(Flash* flash)
+{
+ ise_reset(flash);
+ flash->p[reg(0xaaa)] = mirror(0x90); /* uncover vendor info */
+ flash->manid = fromendian(flash->p[reg(0x0)]);
+ flash->devid = fromendian(flash->p[reg(0x1)]);
+ ise_reset(flash);
+}
+
+static void
+ise_clearerror(Flash* flash)
+{
+ flash->p[reg(0x200)] = mirror(0x50);
+
+}
+
+static void
+ise_error(int bank, ulong status)
+{
+ char err[64];
+
+ if(status & (ISEs_lockerr)){
+ sprint(err, "flash%d: block locked %lux", bank, status);
+ error(err);
+ }
+ if(status & (ISEs_powererr)){
+ sprint(err, "flash%d: low prog voltage %lux", bank, status);
+ error(err);
+ }
+ if(status & (ISEs_progerr|ISEs_eraseerr)){
+ sprint(err, "flash%d: i/o error %lux", bank, status);
+ error(err);
+ }
+}
+static void
+ise_erase(Flash *flash, ulong addr)
+{
+ ulong start;
+ ulong x;
+
+ addr >>= Wshift;
+
+ flashprogpower(1);
+ flash->p[addr] = mirror(0x20);
+ flash->p[addr] = mirror(0xd0);
+ start = m->ticks;
+ do {
+ x = fromendian(flash->p[addr]);
+ if((x & mirror(ISEs_ready)) == mirror(ISEs_ready))
+ break;
+ } while(TK2MS(m->ticks-start) < 1500);
+ flashprogpower(0);
+
+ ise_clearerror(flash);
+ ise_error(0, x);
+ ise_error(1, x>>16);
+
+ ise_reset(flash);
+}
+/*
+ * the flash spec claimes writing goes faster if we use
+ * the write buffer. We fill the write buffer and then
+ * issue the write request. After the write request,
+ * subsequent reads will yield the status register.
+ *
+ * returns the status, even on timeouts.
+ *
+ * NOTE: I tried starting back to back buffered writes
+ * without reading the status in between, as the
+ * flowchart in the intel data sheet suggests.
+ * However, it always responded with an illegal
+ * command sequence, so I must be missing something.
+ * If someone learns better, please email me, though
+ * I doubt it will be much faster. - presotto@bell-labs.com
+ */
+static long
+ise_wbwrite(Flash *flash, Fword *p, int n, ulong off, ulong baddr, ulong *status)
+{
+ Fword x;
+ ulong start;
+ int i;
+ int s;
+
+ /* put flash into write buffer mode */
+ start = m->ticks;
+ for(;;) {
+ s = splhi();
+ /* request write buffer mode */
+ flash->p[baddr] = mirror(0xe8);
+
+ /* look at extended status reg for status */
+ if((flash->p[baddr] & mirror(1<<7)) == mirror(1<<7))
+ break;
+ splx(s);
+
+ /* didn't work, keep trying for 2 secs */
+ if(TK2MS(m->ticks-start) > 2000){
+ /* set up to read status */
+ flash->p[baddr] = mirror(0x70);
+ *status = fromendian(flash->p[baddr]);
+ pprint("write buffered cmd timed out\n");
+ return -1;
+ }
+ }
+
+ /* fill write buffer */
+ flash->p[baddr] = mirror(n-1);
+ for(i = 0; i < n; i++)
+ flash->p[off+i] = *p++;
+
+ /* program from buffer */
+ flash->p[baddr] = mirror(0xd0);
+ splx(s);
+
+ /* wait till the programming is done */
+ start = m->ticks;
+ for(;;) {
+ x = flash->p[baddr]; /* read status register */
+ *status = fromendian(x);
+ if((x & mirror(ISEs_ready)) == mirror(ISEs_ready))
+ break;
+ if(TK2MS(m->ticks-start) > 2000){
+ pprint("read status timed out\n");
+ return -1;
+ }
+ }
+ if(x & mirror(ISEs_err))
+ return -1;
+
+ return n;
+}
+
+static void
+ise_write(Flash *flash, void *a, long n, ulong off)
+{
+ Fword *p, *end;
+ int i, wbsize;
+ ulong x, baddr;
+
+ /* everything in terms of Fwords */
+ wbsize = flash->wbsize >> Wshift;
+ baddr = blockstart(flash, off) >> Wshift;
+ off >>= Wshift;
+ n >>= Wshift;
+ p = a;
+
+ /* first see if write will succeed */
+ for(i = 0; i < n; i++)
+ if((p[i] & flash->p[off+i]) != p[i])
+ error("flash needs erase");
+
+ if(waserror()){
+ ise_reset(flash);
+ flashprogpower(0);
+ nexterror();
+ }
+ flashprogpower(1);
+
+ /*
+ * use the first write to reach
+ * a write buffer boundary. the intel maunal
+ * says writes starting at wb boundaries
+ * maximize speed.
+ */
+ i = wbsize - (off & (wbsize-1));
+ for(end = p + n; p < end;){
+ if(i > end - p)
+ i = end - p;
+
+ if(ise_wbwrite(flash, p, i, off, baddr, &x) < 0)
+ break;
+
+ off += i;
+ p += i;
+ i = wbsize;
+ }
+
+ ise_clearerror(flash);
+ ise_error(0, x);
+ ise_error(1, x>>16);
+
+ ise_reset(flash);
+ flashprogpower(0);
+ poperror();
+}
+
+/* amd/fujitsu standard command set
+ * I don't have an amd chipset to work with
+ * so I'm loathe to write this yet. If someone
+ * else does, please send it to me and I'll
+ * incorporate it -- presotto@bell-labs.com
+ */
+static void
+afs_reset(Flash *flash)
+{
+ flash->p[reg(0xaa)] = mirror(0xf0); /* reset */
+}
+static void
+afs_id(Flash *flash)
+{
+ afs_reset(flash);
+ flash->p[reg(0xaa)] = mirror(0xf0); /* reset */
+ flash->p[reg(0xaaa)] = mirror(0xaa); /* query vendor block */
+ flash->p[reg(0x554)] = mirror(0x55);
+ flash->p[reg(0xaaa)] = mirror(0x90);
+ flash->manid = fromendian(flash->p[reg(0x00)]);
+ afs_reset(flash);
+ flash->p[reg(0xaaa)] = mirror(0xaa); /* query vendor block */
+ flash->p[reg(0x554)] = mirror(0x55);
+ flash->p[reg(0xaaa)] = mirror(0x90);
+ flash->devid = fromendian(flash->p[reg(0x02)]);
+ afs_reset(flash);
+}
+static void
+afs_erase(Flash*, ulong)
+{
+ error("amd/fujistsu erase not implemented");
+}
+static void
+afs_write(Flash*, void*, long, ulong)
+{
+ error("amd/fujistsu write not implemented");
+}
diff --git a/sys/src/9/ppc/devirq.c b/sys/src/9/ppc/devirq.c
new file mode 100755
index 000000000..dab8ceac2
--- /dev/null
+++ b/sys/src/9/ppc/devirq.c
@@ -0,0 +1,355 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "m8260.h"
+#include "../port/error.h"
+
+enum{
+ IRQ0 = 18,
+ Level = 0,
+ Edge = 1,
+};
+
+enum{
+ Qdir,
+ Qirq1,
+ Qirq2,
+ Qirq3,
+ Qirq4,
+ Qirq5,
+ Qirq6,
+ Qirq7,
+ Qmstimer,
+ Qfpgareset,
+ NIRQ,
+};
+
+static Dirtab irqdir[]={
+ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
+ "irq1", {Qirq1}, 0, 0666,
+ "irq2", {Qirq2}, 0, 0666,
+ "irq3", {Qirq1}, 0, 0666,
+ "irq4", {Qirq1}, 0, 0666,
+ "irq5", {Qirq1}, 0, 0666,
+ "irq6", {Qirq1}, 0, 0666,
+ "irq7", {Qirq1}, 0, 0666,
+ "mstimer", {Qmstimer}, 0, 0666,
+ "fpgareset", {Qfpgareset}, 0, 0222,
+};
+
+enum
+{
+ CMinterrupt,
+ CMmode,
+ CMreset,
+ CMwait,
+ CMdebug,
+};
+
+Cmdtab irqmsg[] =
+{
+ CMinterrupt, "interrupt", 2,
+ CMmode, "mode", 2,
+ CMreset, "reset", 1,
+ CMwait, "wait", 1,
+ CMdebug, "debug", 1,
+};
+
+typedef struct Irqconfig Irqconfig;
+struct Irqconfig {
+ int intenable; /* Interrupts are enabled */
+ int mode; /* level == 0; edge == 1 */
+ ulong interrupts; /* Count interrupts */
+ ulong sleepints; /* interrupt count when waiting */
+ Rendez r; /* Rendez-vous point for interrupt waiting */
+ Irqconfig *next;
+ Timer;
+};
+
+Irqconfig *irqconfig[NIRQ]; /* irqconfig[0] is not used */
+Lock irqlock;
+
+static void interrupt(Ureg*, void*);
+void dumpvno(void);
+
+static void
+ticmstimer(Ureg*, Timer *t)
+{
+ Irqconfig *ic;
+
+ ic = t->ta;
+ ic->interrupts++;
+ wakeup(&ic->r);
+}
+
+void
+irqenable(Irqconfig *ic, int irq)
+{
+ /* call with ilock(&irqlock) held */
+
+ if (ic->intenable)
+ return;
+ if (irq == Qmstimer){
+ if (ic->tnext == nil)
+ ic->tns = MS2NS(ic->mode);
+ ic->tmode = Tperiodic;
+ timeradd(&ic->Timer);
+ }else{
+ if (irqconfig[irq]){
+ ic->next = irqconfig[irq];
+ irqconfig[irq] = ic;
+ }else{
+ ic->next = nil;
+ irqconfig[irq] = ic;
+ intrenable(IRQ0 + irq, interrupt, &irqconfig[irq], irqdir[irq].name);
+ }
+ }
+ ic->intenable = 1;
+}
+
+void
+irqdisable(Irqconfig *ic, int irq)
+{
+ Irqconfig **pic;
+
+ /* call with ilock(&irqlock) held */
+
+ if (ic->intenable == 0)
+ return;
+ if (irq == Qmstimer){
+ timerdel(&ic->Timer);
+ }else{
+ for(pic = &irqconfig[irq]; *pic != ic; pic = &(*pic)->next)
+ assert(*pic);
+ *pic = (*pic)->next;
+ if (irqconfig[irq] == nil)
+ intrdisable(IRQ0 + irq, interrupt, &irqconfig[irq], irqdir[irq].name);
+ }
+ ic->intenable = 0;
+}
+
+static Chan*
+irqattach(char *spec)
+{
+ return devattach('b', spec);
+}
+
+static Walkqid*
+irqwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name,nname, irqdir, nelem(irqdir), devgen);
+}
+
+static int
+irqstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, irqdir, nelem(irqdir), devgen);
+}
+
+static Chan*
+irqopen(Chan *c, int omode)
+{
+ Irqconfig *ic;
+ int irq;
+
+ irq = (ulong)c->qid.path;
+ if(irq != Qdir){
+ ic = mallocz(sizeof(Irqconfig), 1);
+ ic->tf = ticmstimer;
+ ic->ta = ic;
+ if (irq == Qmstimer)
+ ic->mode = 1000;
+ c->aux = ic;
+ }
+ return devopen(c, omode, irqdir, nelem(irqdir), devgen);
+}
+
+static void
+irqclose(Chan *c)
+{
+ int irq;
+ Irqconfig *ic;
+
+ irq = (ulong)c->qid.path;
+ if(irq == Qdir)
+ return;
+ ic = c->aux;
+ if (irq > Qmstimer)
+ return;
+ ilock(&irqlock);
+ irqdisable(ic, irq);
+ iunlock(&irqlock);
+ free(ic);
+}
+
+static int
+irqtfn(void *arg)
+{
+ Irqconfig *ic;
+
+ ic = arg;
+ return ic->sleepints != ic->interrupts;
+}
+
+static long
+irqread(Chan *c, void *buf, long n, vlong)
+{
+ int irq;
+ Irqconfig *ic;
+ char tmp[24];
+
+ if(n <= 0)
+ return n;
+ irq = (ulong)c->qid.path;
+ if(irq == Qdir)
+ return devdirread(c, buf, n, irqdir, nelem(irqdir), devgen);
+ if(irq > Qmstimer){
+ print("irqread 0x%llux\n", c->qid.path);
+ error(Egreg);
+ }
+ ic = c->aux;
+ if (ic->intenable == 0)
+ error("disabled");
+ ic->sleepints = ic->interrupts;
+ sleep(&ic->r, irqtfn, ic);
+ if (irq == Qmstimer)
+ snprint(tmp, sizeof tmp, "%11lud %d", ic->interrupts, ic->mode);
+ else
+ snprint(tmp, sizeof tmp, "%11lud %s", ic->interrupts, ic->mode ?"edge":"level");
+ n = readstr(0, buf, n, tmp);
+ return n;
+}
+
+static long
+irqwrite(Chan *c, void *a, long n, vlong)
+{
+ int irq;
+ Irqconfig *ic;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+
+ if(n <= 0)
+ return n;
+
+ irq = (ulong)c->qid.path;
+ if(irq <= 0 || irq >= nelem(irqdir)){
+ print("irqwrite 0x%llux\n", c->qid.path);
+ error(Egreg);
+ }
+ if (irq == Qfpgareset){
+ if (strncmp(a, "reset", 5) == 0)
+ fpgareset();
+ else
+ error(Egreg);
+ return n;
+ }
+ ic = c->aux;
+
+ cb = parsecmd(a, n);
+
+ if(waserror()) {
+ free(cb);
+ nexterror();
+ }
+ ct = lookupcmd(cb, irqmsg, nelem(irqmsg));
+ switch(ct->index) {
+ case CMinterrupt:
+ /* Turn interrupts on or off */
+ if (strcmp(cb->f[1], "on") == 0){
+ ilock(&irqlock);
+ irqenable(ic, irq);
+ iomem->siprr = 0x65009770;
+ iunlock(&irqlock);
+ }else if (strcmp(cb->f[1], "off") == 0){
+ ilock(&irqlock);
+ irqdisable(ic, irq);
+ iunlock(&irqlock);
+ }else
+ error(Ebadarg);
+ break;
+ case CMmode:
+ /* Set mode */
+ if (irq == Qmstimer){
+ ic->mode = strtol(cb->f[1], nil, 0);
+ if (ic->mode <= 0){
+ ic->tns = MS2NS(1000);
+ ic->mode = 1000;
+ error(Ebadarg);
+ }
+ ic->tns = MS2NS(ic->mode);
+ }else if (strcmp(cb->f[1], "level") == 0){
+ ic->mode = Level;
+ iomem->siexr &= ~(0x8000 >> irq);
+ }else if (strcmp(cb->f[1], "edge") == 0){
+ ic->mode = Edge;
+ iomem->siexr |= 0x8000 >> irq;
+ }else
+ error(Ebadarg);
+ break;
+ case CMreset:
+ ic->interrupts = 0;
+ break;
+ case CMwait:
+ if (ic->intenable == 0)
+ error("interrupts are off");
+ ic->sleepints = ic->interrupts;
+ sleep(&ic->r, irqtfn, ic);
+ break;
+ case CMdebug:
+ print("simr h/l 0x%lux/0x%lux, sipnr h/l 0x%lux/0x%lux, siexr 0x%lux, siprr 0x%lux\n",
+ iomem->simr_h, iomem->simr_l,
+ iomem->sipnr_h, iomem->sipnr_l,
+ iomem->siexr, iomem->siprr);
+ dumpvno();
+ }
+ poperror();
+ free(cb);
+
+ /* Irqi */
+ return n;
+}
+
+static void
+interrupt(Ureg*, void *arg)
+{
+ Irqconfig **pic, *ic;
+ int irq;
+
+ pic = arg;
+ irq = pic - irqconfig;
+ if (irq <= 0 || irq > nelem(irqdir)){
+ print("Unexpected interrupt: %d\n", irq);
+ return;
+ }
+ ilock(&irqlock);
+ if (irq <= Qirq7)
+ iomem->sipnr_h |= 0x8000 >> irq; /* Clear the interrupt */
+ for(ic = *pic; ic; ic = ic->next){
+ ic->interrupts++;
+ wakeup(&ic->r);
+ }
+ iunlock(&irqlock);
+}
+
+Dev irqdevtab = {
+ 'b',
+ "irq",
+
+ devreset,
+ devinit,
+ devshutdown,
+ irqattach,
+ irqwalk,
+ irqstat,
+ irqopen,
+ devcreate,
+ irqclose,
+ irqread,
+ devbread,
+ irqwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
diff --git a/sys/src/9/ppc/devtls.c b/sys/src/9/ppc/devtls.c
new file mode 100755
index 000000000..d333b10b9
--- /dev/null
+++ b/sys/src/9/ppc/devtls.c
@@ -0,0 +1,2113 @@
+/*
+ * devtls - record layer for transport layer security 1.0 and secure sockets layer 3.0
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include <libsec.h>
+
+typedef struct OneWay OneWay;
+typedef struct Secret Secret;
+typedef struct TlsRec TlsRec;
+typedef struct TlsErrs TlsErrs;
+
+enum {
+ Statlen= 1024, /* max. length of status or stats message */
+ /* buffer limits */
+ MaxRecLen = 1<<14, /* max payload length of a record layer message */
+ MaxCipherRecLen = MaxRecLen + 2048,
+ RecHdrLen = 5,
+ MaxMacLen = SHA1dlen,
+
+ /* protocol versions we can accept */
+ TLSVersion = 0x0301,
+ SSL3Version = 0x0300,
+ ProtocolVersion = 0x0301, /* maximum version we speak */
+ MinProtoVersion = 0x0300, /* limits on version we accept */
+ MaxProtoVersion = 0x03ff,
+
+ /* connection states */
+ SHandshake = 1 << 0, /* doing handshake */
+ SOpen = 1 << 1, /* application data can be sent */
+ SRClose = 1 << 2, /* remote side has closed down */
+ SLClose = 1 << 3, /* sent a close notify alert */
+ SAlert = 1 << 5, /* sending or sent a fatal alert */
+ SError = 1 << 6, /* some sort of error has occured */
+ SClosed = 1 << 7, /* it is all over */
+
+ /* record types */
+ RChangeCipherSpec = 20,
+ RAlert,
+ RHandshake,
+ RApplication,
+
+ SSL2ClientHello = 1,
+ HSSL2ClientHello = 9, /* local convention; see tlshand.c */
+
+ /* alerts */
+ ECloseNotify = 0,
+ EUnexpectedMessage = 10,
+ EBadRecordMac = 20,
+ EDecryptionFailed = 21,
+ ERecordOverflow = 22,
+ EDecompressionFailure = 30,
+ EHandshakeFailure = 40,
+ ENoCertificate = 41,
+ EBadCertificate = 42,
+ EUnsupportedCertificate = 43,
+ ECertificateRevoked = 44,
+ ECertificateExpired = 45,
+ ECertificateUnknown = 46,
+ EIllegalParameter = 47,
+ EUnknownCa = 48,
+ EAccessDenied = 49,
+ EDecodeError = 50,
+ EDecryptError = 51,
+ EExportRestriction = 60,
+ EProtocolVersion = 70,
+ EInsufficientSecurity = 71,
+ EInternalError = 80,
+ EUserCanceled = 90,
+ ENoRenegotiation = 100,
+
+ EMAX = 256
+};
+
+struct Secret
+{
+ char *encalg; /* name of encryption alg */
+ char *hashalg; /* name of hash alg */
+ int (*enc)(Secret*, uchar*, int);
+ int (*dec)(Secret*, uchar*, int);
+ int (*unpad)(uchar*, int, int);
+ DigestState *(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+ int block; /* encryption block len, 0 if none */
+ int maclen;
+ void *enckey;
+ uchar mackey[MaxMacLen];
+};
+
+struct OneWay
+{
+ QLock io; /* locks io access */
+ QLock seclock; /* locks secret paramaters */
+ ulong seq;
+ Secret *sec; /* cipher in use */
+ Secret *new; /* cipher waiting for enable */
+};
+
+struct TlsRec
+{
+ Chan *c; /* io channel */
+ int ref; /* serialized by tdlock for atomic destroy */
+ int version; /* version of the protocol we are speaking */
+ char verset; /* version has been set */
+ char opened; /* opened command every issued? */
+ char err[ERRMAX]; /* error message to return to handshake requests */
+ vlong handin; /* bytes communicated by the record layer */
+ vlong handout;
+ vlong datain;
+ vlong dataout;
+
+ Lock statelk;
+ int state;
+
+ /* record layer mac functions for different protocol versions */
+ void (*packMac)(Secret*, uchar*, uchar*, uchar*, uchar*, int, uchar*);
+
+ /* input side -- protected by in.io */
+ OneWay in;
+ Block *processed; /* next bunch of application data */
+ Block *unprocessed; /* data read from c but not parsed into records */
+
+ /* handshake queue */
+ Lock hqlock; /* protects hqref, alloc & free of handq, hprocessed */
+ int hqref;
+ Queue *handq; /* queue of handshake messages */
+ Block *hprocessed; /* remainder of last block read from handq */
+ QLock hqread; /* protects reads for hprocessed, handq */
+
+ /* output side */
+ OneWay out;
+
+ /* protections */
+ char *user;
+ int perm;
+};
+
+struct TlsErrs{
+ int err;
+ int sslerr;
+ int tlserr;
+ int fatal;
+ char *msg;
+};
+
+static TlsErrs tlserrs[] = {
+ {ECloseNotify, ECloseNotify, ECloseNotify, 0, "close notify"},
+ {EUnexpectedMessage, EUnexpectedMessage, EUnexpectedMessage, 1, "unexpected message"},
+ {EBadRecordMac, EBadRecordMac, EBadRecordMac, 1, "bad record mac"},
+ {EDecryptionFailed, EIllegalParameter, EDecryptionFailed, 1, "decryption failed"},
+ {ERecordOverflow, EIllegalParameter, ERecordOverflow, 1, "record too long"},
+ {EDecompressionFailure, EDecompressionFailure, EDecompressionFailure, 1, "decompression failed"},
+ {EHandshakeFailure, EHandshakeFailure, EHandshakeFailure, 1, "could not negotiate acceptable security paramters"},
+ {ENoCertificate, ENoCertificate, ECertificateUnknown, 1, "no appropriate certificate available"},
+ {EBadCertificate, EBadCertificate, EBadCertificate, 1, "corrupted or invalid certificate"},
+ {EUnsupportedCertificate, EUnsupportedCertificate, EUnsupportedCertificate, 1, "unsupported certificate type"},
+ {ECertificateRevoked, ECertificateRevoked, ECertificateRevoked, 1, "revoked certificate"},
+ {ECertificateExpired, ECertificateExpired, ECertificateExpired, 1, "expired certificate"},
+ {ECertificateUnknown, ECertificateUnknown, ECertificateUnknown, 1, "unacceptable certificate"},
+ {EIllegalParameter, EIllegalParameter, EIllegalParameter, 1, "illegal parameter"},
+ {EUnknownCa, EHandshakeFailure, EUnknownCa, 1, "unknown certificate authority"},
+ {EAccessDenied, EHandshakeFailure, EAccessDenied, 1, "access denied"},
+ {EDecodeError, EIllegalParameter, EDecodeError, 1, "error decoding message"},
+ {EDecryptError, EIllegalParameter, EDecryptError, 1, "error decrypting message"},
+ {EExportRestriction, EHandshakeFailure, EExportRestriction, 1, "export restriction violated"},
+ {EProtocolVersion, EIllegalParameter, EProtocolVersion, 1, "protocol version not supported"},
+ {EInsufficientSecurity, EHandshakeFailure, EInsufficientSecurity, 1, "stronger security routines required"},
+ {EInternalError, EHandshakeFailure, EInternalError, 1, "internal error"},
+ {EUserCanceled, ECloseNotify, EUserCanceled, 0, "handshake canceled by user"},
+ {ENoRenegotiation, EUnexpectedMessage, ENoRenegotiation, 0, "no renegotiation"},
+};
+
+enum
+{
+ /* max. open tls connections */
+ MaxTlsDevs = 1024
+};
+
+static Lock tdlock;
+static int tdhiwat;
+static int maxtlsdevs = 128;
+static TlsRec **tlsdevs;
+static char **trnames;
+static char *encalgs;
+static char *hashalgs;
+
+enum{
+ Qtopdir = 1, /* top level directory */
+ Qprotodir,
+ Qclonus,
+ Qencalgs,
+ Qhashalgs,
+ Qconvdir, /* directory for a conversation */
+ Qdata,
+ Qctl,
+ Qhand,
+ Qstatus,
+ Qstats,
+};
+
+#define TYPE(x) ((x).path & 0xf)
+#define CONV(x) (((x).path >> 5)&(MaxTlsDevs-1))
+#define QID(c, y) (((c)<<5) | (y))
+
+static void checkstate(TlsRec *, int, int);
+static void ensure(TlsRec*, Block**, int);
+static void consume(Block**, uchar*, int);
+static Chan* buftochan(char*);
+static void tlshangup(TlsRec*);
+static void tlsError(TlsRec*, char *);
+static void alertHand(TlsRec*, char *);
+static TlsRec *newtls(Chan *c);
+static TlsRec *mktlsrec(void);
+static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
+static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
+static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
+static void sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
+static void tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
+static void put64(uchar *p, vlong x);
+static void put32(uchar *p, u32int);
+static void put24(uchar *p, int);
+static void put16(uchar *p, int);
+static u32int get32(uchar *p);
+static int get16(uchar *p);
+static void tlsSetState(TlsRec *tr, int new, int old);
+static void rcvAlert(TlsRec *tr, int err);
+static void sendAlert(TlsRec *tr, int err);
+static void rcvError(TlsRec *tr, int err, char *msg, ...);
+static int rc4enc(Secret *sec, uchar *buf, int n);
+static int des3enc(Secret *sec, uchar *buf, int n);
+static int des3dec(Secret *sec, uchar *buf, int n);
+static int noenc(Secret *sec, uchar *buf, int n);
+static int sslunpad(uchar *buf, int n, int block);
+static int tlsunpad(uchar *buf, int n, int block);
+static void freeSec(Secret *sec);
+static char *tlsstate(int s);
+
+#pragma varargck argpos rcvError 3
+
+static char *tlsnames[] = {
+[Qclonus] "clone",
+[Qencalgs] "encalgs",
+[Qhashalgs] "hashalgs",
+[Qdata] "data",
+[Qctl] "ctl",
+[Qhand] "hand",
+[Qstatus] "status",
+[Qstats] "stats",
+};
+
+static int convdir[] = { Qctl, Qdata, Qhand, Qstatus, Qstats };
+
+static int
+tlsgen(Chan *c, char*, Dirtab *, int, int s, Dir *dp)
+{
+ Qid q;
+ TlsRec *tr;
+ char *name, *nm;
+ int perm, t;
+
+ q.vers = 0;
+ q.type = QTFILE;
+
+ t = TYPE(c->qid);
+ switch(t) {
+ case Qtopdir:
+ if(s == DEVDOTDOT){
+ q.path = QID(0, Qtopdir);
+ q.type = QTDIR;
+ devdir(c, q, "#a", 0, eve, 0555, dp);
+ return 1;
+ }
+ if(s > 0)
+ return -1;
+ q.path = QID(0, Qprotodir);
+ q.type = QTDIR;
+ devdir(c, q, "tls", 0, eve, 0555, dp);
+ return 1;
+ case Qprotodir:
+ if(s == DEVDOTDOT){
+ q.path = QID(0, Qtopdir);
+ q.type = QTDIR;
+ devdir(c, q, ".", 0, eve, 0555, dp);
+ return 1;
+ }
+ if(s < 3){
+ switch(s) {
+ default:
+ return -1;
+ case 0:
+ q.path = QID(0, Qclonus);
+ break;
+ case 1:
+ q.path = QID(0, Qencalgs);
+ break;
+ case 2:
+ q.path = QID(0, Qhashalgs);
+ break;
+ }
+ perm = 0444;
+ if(TYPE(q) == Qclonus)
+ perm = 0555;
+ devdir(c, q, tlsnames[TYPE(q)], 0, eve, perm, dp);
+ return 1;
+ }
+ s -= 3;
+ if(s >= tdhiwat)
+ return -1;
+ q.path = QID(s, Qconvdir);
+ q.type = QTDIR;
+ lock(&tdlock);
+ tr = tlsdevs[s];
+ if(tr != nil)
+ nm = tr->user;
+ else
+ nm = eve;
+ if((name = trnames[s]) == nil) {
+ name = trnames[s] = smalloc(16);
+ sprint(name, "%d", s);
+ }
+ devdir(c, q, name, 0, nm, 0555, dp);
+ unlock(&tdlock);
+ return 1;
+ case Qconvdir:
+ if(s == DEVDOTDOT){
+ q.path = QID(0, Qprotodir);
+ q.type = QTDIR;
+ devdir(c, q, "tls", 0, eve, 0555, dp);
+ return 1;
+ }
+ if(s < 0 || s >= nelem(convdir))
+ return -1;
+ lock(&tdlock);
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr != nil){
+ nm = tr->user;
+ perm = tr->perm;
+ }else{
+ perm = 0;
+ nm = eve;
+ }
+ t = convdir[s];
+ if(t == Qstatus || t == Qstats)
+ perm &= 0444;
+ q.path = QID(CONV(c->qid), t);
+ devdir(c, q, tlsnames[t], 0, nm, perm, dp);
+ unlock(&tdlock);
+ return 1;
+ case Qclonus:
+ case Qencalgs:
+ case Qhashalgs:
+ perm = 0444;
+ if(t == Qclonus)
+ perm = 0555;
+ devdir(c, c->qid, tlsnames[t], 0, eve, perm, dp);
+ return 1;
+ default:
+ lock(&tdlock);
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr != nil){
+ nm = tr->user;
+ perm = tr->perm;
+ }else{
+ perm = 0;
+ nm = eve;
+ }
+ if(t == Qstatus || t == Qstats)
+ perm &= 0444;
+ devdir(c, c->qid, tlsnames[t], 0, nm, perm, dp);
+ unlock(&tdlock);
+ return 1;
+ }
+ return -1;
+}
+
+static Chan*
+tlsattach(char *spec)
+{
+ Chan *c;
+
+ c = devattach('a', spec);
+ c->qid.path = QID(0, Qtopdir);
+ c->qid.type = QTDIR;
+ c->qid.vers = 0;
+ return c;
+}
+
+static Walkqid*
+tlswalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, nil, 0, tlsgen);
+}
+
+static int
+tlsstat(Chan *c, uchar *db, int n)
+{
+ return devstat(c, db, n, nil, 0, tlsgen);
+}
+
+static Chan*
+tlsopen(Chan *c, int omode)
+{
+ TlsRec *tr, **pp;
+ int t, perm;
+
+ perm = 0;
+ omode &= 3;
+ switch(omode) {
+ case OREAD:
+ perm = 4;
+ break;
+ case OWRITE:
+ perm = 2;
+ break;
+ case ORDWR:
+ perm = 6;
+ break;
+ }
+
+ t = TYPE(c->qid);
+ switch(t) {
+ default:
+ panic("tlsopen");
+ case Qtopdir:
+ case Qprotodir:
+ case Qconvdir:
+ if(omode != OREAD)
+ error(Eperm);
+ break;
+ case Qclonus:
+ tr = newtls(c);
+ if(tr == nil)
+ error(Enodev);
+ break;
+ case Qctl:
+ case Qdata:
+ case Qhand:
+ case Qstatus:
+ case Qstats:
+ if((t == Qstatus || t == Qstats) && omode != OREAD)
+ error(Eperm);
+ if(waserror()) {
+ unlock(&tdlock);
+ nexterror();
+ }
+ lock(&tdlock);
+ pp = &tlsdevs[CONV(c->qid)];
+ tr = *pp;
+ if(tr == nil)
+ error("must open connection using clone");
+ if((perm & (tr->perm>>6)) != perm
+ && (strcmp(up->user, tr->user) != 0
+ || (perm & tr->perm) != perm))
+ error(Eperm);
+ if(t == Qhand){
+ if(waserror()){
+ unlock(&tr->hqlock);
+ nexterror();
+ }
+ lock(&tr->hqlock);
+ if(tr->handq != nil)
+ error(Einuse);
+ tr->handq = qopen(2 * MaxCipherRecLen, 0, nil, nil);
+ if(tr->handq == nil)
+ error("can't allocate handshake queue");
+ tr->hqref = 1;
+ unlock(&tr->hqlock);
+ poperror();
+ }
+ tr->ref++;
+ unlock(&tdlock);
+ poperror();
+ break;
+ case Qencalgs:
+ case Qhashalgs:
+ if(omode != OREAD)
+ error(Eperm);
+ break;
+ }
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ c->iounit = qiomaxatomic;
+ return c;
+}
+
+static int
+tlswstat(Chan *c, uchar *dp, int n)
+{
+ Dir *d;
+ TlsRec *tr;
+ int rv;
+
+ d = nil;
+ if(waserror()){
+ free(d);
+ unlock(&tdlock);
+ nexterror();
+ }
+
+ lock(&tdlock);
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr == nil)
+ error(Ebadusefd);
+ if(strcmp(tr->user, up->user) != 0)
+ error(Eperm);
+
+ d = smalloc(n + sizeof *d);
+ rv = convM2D(dp, n, &d[0], (char*) &d[1]);
+ if(rv == 0)
+ error(Eshortstat);
+ if(!emptystr(d->uid))
+ kstrdup(&tr->user, d->uid);
+ if(d->mode != ~0UL)
+ tr->perm = d->mode;
+
+ free(d);
+ poperror();
+ unlock(&tdlock);
+
+ return rv;
+}
+
+static void
+dechandq(TlsRec *tr)
+{
+ lock(&tr->hqlock);
+ if(--tr->hqref == 0){
+ if(tr->handq != nil){
+ qfree(tr->handq);
+ tr->handq = nil;
+ }
+ if(tr->hprocessed != nil){
+ freeb(tr->hprocessed);
+ tr->hprocessed = nil;
+ }
+ }
+ unlock(&tr->hqlock);
+}
+
+static void
+tlsclose(Chan *c)
+{
+ TlsRec *tr;
+ int t;
+
+ t = TYPE(c->qid);
+ switch(t) {
+ case Qctl:
+ case Qdata:
+ case Qhand:
+ case Qstatus:
+ case Qstats:
+ if((c->flag & COPEN) == 0)
+ break;
+
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr == nil)
+ break;
+
+ if(t == Qhand)
+ dechandq(tr);
+
+ lock(&tdlock);
+ if(--tr->ref > 0) {
+ unlock(&tdlock);
+ return;
+ }
+ tlsdevs[CONV(c->qid)] = nil;
+ unlock(&tdlock);
+
+ if(tr->c != nil && !waserror()){
+ checkstate(tr, 0, SOpen|SHandshake|SRClose);
+ sendAlert(tr, ECloseNotify);
+ poperror();
+ }
+ tlshangup(tr);
+ if(tr->c != nil)
+ cclose(tr->c);
+ freeSec(tr->in.sec);
+ freeSec(tr->in.new);
+ freeSec(tr->out.sec);
+ freeSec(tr->out.new);
+ free(tr->user);
+ free(tr);
+ break;
+ }
+}
+
+/*
+ * make sure we have at least 'n' bytes in list 'l'
+ */
+static void
+ensure(TlsRec *s, Block **l, int n)
+{
+ int sofar, i;
+ Block *b, *bl;
+
+ sofar = 0;
+ for(b = *l; b; b = b->next){
+ sofar += BLEN(b);
+ if(sofar >= n)
+ return;
+ l = &b->next;
+ }
+
+ while(sofar < n){
+ bl = devtab[s->c->type]->bread(s->c, MaxCipherRecLen + RecHdrLen, 0);
+ if(bl == 0)
+ error(Ehungup);
+ *l = bl;
+ i = 0;
+ for(b = bl; b; b = b->next){
+ i += BLEN(b);
+ l = &b->next;
+ }
+ if(i == 0)
+ error(Ehungup);
+ sofar += i;
+ }
+}
+
+/*
+ * copy 'n' bytes from 'l' into 'p' and free
+ * the bytes in 'l'
+ */
+static void
+consume(Block **l, uchar *p, int n)
+{
+ Block *b;
+ int i;
+
+ for(; *l && n > 0; n -= i){
+ b = *l;
+ i = BLEN(b);
+ if(i > n)
+ i = n;
+ memmove(p, b->rp, i);
+ b->rp += i;
+ p += i;
+ if(BLEN(b) < 0)
+ panic("consume");
+ if(BLEN(b))
+ break;
+ *l = b->next;
+ freeb(b);
+ }
+}
+
+/*
+ * give back n bytes
+ */
+static void
+regurgitate(TlsRec *s, uchar *p, int n)
+{
+ Block *b;
+
+ if(n <= 0)
+ return;
+ b = s->unprocessed;
+ if(s->unprocessed == nil || b->rp - b->base < n) {
+ b = allocb(n);
+ memmove(b->wp, p, n);
+ b->wp += n;
+ b->next = s->unprocessed;
+ s->unprocessed = b;
+ } else {
+ b->rp -= n;
+ memmove(b->rp, p, n);
+ }
+}
+
+/*
+ * remove at most n bytes from the queue
+ */
+static Block*
+qgrab(Block **l, int n)
+{
+ Block *bb, *b;
+ int i;
+
+ b = *l;
+ if(BLEN(b) == n){
+ *l = b->next;
+ b->next = nil;
+ return b;
+ }
+
+ i = 0;
+ for(bb = b; bb != nil && i < n; bb = bb->next)
+ i += BLEN(bb);
+ if(i > n)
+ i = n;
+
+ bb = allocb(i);
+ consume(l, bb->wp, i);
+ bb->wp += i;
+ return bb;
+}
+
+static void
+tlsclosed(TlsRec *tr, int new)
+{
+ lock(&tr->statelk);
+ if(tr->state == SOpen || tr->state == SHandshake)
+ tr->state = new;
+ else if((new | tr->state) == (SRClose|SLClose))
+ tr->state = SClosed;
+ unlock(&tr->statelk);
+ alertHand(tr, "close notify");
+}
+
+/*
+ * read and process one tls record layer message
+ * must be called with tr->in.io held
+ * We can't let Eintrs lose data, since doing so will get
+ * us out of sync with the sender and break the reliablity
+ * of the channel. Eintr only happens during the reads in
+ * consume. Therefore we put back any bytes consumed before
+ * the last call to ensure.
+ */
+static void
+tlsrecread(TlsRec *tr)
+{
+ OneWay *volatile in;
+ Block *volatile b;
+ uchar *p, seq[8], header[RecHdrLen], hmac[MD5dlen];
+ int volatile nconsumed;
+ int len, type, ver, unpad_len;
+
+ nconsumed = 0;
+ if(waserror()){
+ if(strcmp(up->errstr, Eintr) == 0 && !waserror()){
+ regurgitate(tr, header, nconsumed);
+ poperror();
+ }else
+ tlsError(tr, "channel error");
+ nexterror();
+ }
+ ensure(tr, &tr->unprocessed, RecHdrLen);
+ consume(&tr->unprocessed, header, RecHdrLen);
+ nconsumed = RecHdrLen;
+
+ if((tr->handin == 0) && (header[0] & 0x80)){
+ /* Cope with an SSL3 ClientHello expressed in SSL2 record format.
+ This is sent by some clients that we must interoperate
+ with, such as Java's JSSE and Microsoft's Internet Explorer. */
+ len = (get16(header) & ~0x8000) - 3;
+ type = header[2];
+ ver = get16(header + 3);
+ if(type != SSL2ClientHello || len < 22)
+ rcvError(tr, EProtocolVersion, "invalid initial SSL2-like message");
+ }else{ /* normal SSL3 record format */
+ type = header[0];
+ ver = get16(header+1);
+ len = get16(header+3);
+ }
+ if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion))
+ rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'",
+ tr->version, tr->verset?"/set":"", len, type, ver, (char*)header);
+ if(len > MaxCipherRecLen || len < 0)
+ rcvError(tr, ERecordOverflow, "record message too long %d", len);
+ ensure(tr, &tr->unprocessed, len);
+ nconsumed = 0;
+ poperror();
+
+ /*
+ * If an Eintr happens after this, we'll get out of sync.
+ * Make sure nothing we call can sleep.
+ * Errors are ok, as they kill the connection.
+ * Luckily, allocb won't sleep, it'll just error out.
+ */
+ b = nil;
+ if(waserror()){
+ if(b != nil)
+ freeb(b);
+ tlsError(tr, "channel error");
+ nexterror();
+ }
+ b = qgrab(&tr->unprocessed, len);
+
+ in = &tr->in;
+ if(waserror()){
+ qunlock(&in->seclock);
+ nexterror();
+ }
+ qlock(&in->seclock);
+ p = b->rp;
+ if(in->sec != nil) {
+ /* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here
+ should look alike, including timing of the response. */
+ unpad_len = (*in->sec->dec)(in->sec, p, len);
+ if(unpad_len > in->sec->maclen)
+ len = unpad_len - in->sec->maclen;
+
+ /* update length */
+ put16(header+3, len);
+ put64(seq, in->seq);
+ in->seq++;
+ (*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac);
+ if(unpad_len <= in->sec->maclen || memcmp(hmac, p+len, in->sec->maclen) != 0)
+ rcvError(tr, EBadRecordMac, "record mac mismatch");
+ b->wp = b->rp + len;
+ }
+ qunlock(&in->seclock);
+ poperror();
+ if(len <= 0)
+ rcvError(tr, EDecodeError, "runt record message");
+
+ switch(type) {
+ default:
+ rcvError(tr, EIllegalParameter, "invalid record message 0x%x", type);
+ break;
+ case RChangeCipherSpec:
+ if(len != 1 || p[0] != 1)
+ rcvError(tr, EDecodeError, "invalid change cipher spec");
+ qlock(&in->seclock);
+ if(in->new == nil){
+ qunlock(&in->seclock);
+ rcvError(tr, EUnexpectedMessage, "unexpected change cipher spec");
+ }
+ freeSec(in->sec);
+ in->sec = in->new;
+ in->new = nil;
+ in->seq = 0;
+ qunlock(&in->seclock);
+ break;
+ case RAlert:
+ if(len != 2)
+ rcvError(tr, EDecodeError, "invalid alert");
+ if(p[0] == 2)
+ rcvAlert(tr, p[1]);
+ if(p[0] != 1)
+ rcvError(tr, EIllegalParameter, "invalid alert fatal code");
+
+ /*
+ * propate non-fatal alerts to handshaker
+ */
+ if(p[1] == ECloseNotify) {
+ tlsclosed(tr, SRClose);
+ if(tr->opened)
+ error("tls hungup");
+ error("close notify");
+ }
+ if(p[1] == ENoRenegotiation)
+ alertHand(tr, "no renegotiation");
+ else if(p[1] == EUserCanceled)
+ alertHand(tr, "handshake canceled by user");
+ else
+ rcvError(tr, EIllegalParameter, "invalid alert code");
+ break;
+ case RHandshake:
+ /*
+ * don't worry about dropping the block
+ * qbwrite always queues even if flow controlled and interrupted.
+ *
+ * if there isn't any handshaker, ignore the request,
+ * but notify the other side we are doing so.
+ */
+ lock(&tr->hqlock);
+ if(tr->handq != nil){
+ tr->hqref++;
+ unlock(&tr->hqlock);
+ if(waserror()){
+ dechandq(tr);
+ nexterror();
+ }
+ b = padblock(b, 1);
+ *b->rp = RHandshake;
+ qbwrite(tr->handq, b);
+ b = nil;
+ poperror();
+ dechandq(tr);
+ }else{
+ unlock(&tr->hqlock);
+ if(tr->verset && tr->version != SSL3Version && !waserror()){
+ sendAlert(tr, ENoRenegotiation);
+ poperror();
+ }
+ }
+ break;
+ case SSL2ClientHello:
+ lock(&tr->hqlock);
+ if(tr->handq != nil){
+ tr->hqref++;
+ unlock(&tr->hqlock);
+ if(waserror()){
+ dechandq(tr);
+ nexterror();
+ }
+ /* Pass the SSL2 format data, so that the handshake code can compute
+ the correct checksums. HSSL2ClientHello = HandshakeType 9 is
+ unused in RFC2246. */
+ b = padblock(b, 8);
+ b->rp[0] = RHandshake;
+ b->rp[1] = HSSL2ClientHello;
+ put24(&b->rp[2], len+3);
+ b->rp[5] = SSL2ClientHello;
+ put16(&b->rp[6], ver);
+ qbwrite(tr->handq, b);
+ b = nil;
+ poperror();
+ dechandq(tr);
+ }else{
+ unlock(&tr->hqlock);
+ if(tr->verset && tr->version != SSL3Version && !waserror()){
+ sendAlert(tr, ENoRenegotiation);
+ poperror();
+ }
+ }
+ break;
+ case RApplication:
+ if(!tr->opened)
+ rcvError(tr, EUnexpectedMessage, "application message received before handshake completed");
+ tr->processed = b;
+ b = nil;
+ break;
+ }
+ if(b != nil)
+ freeb(b);
+ poperror();
+}
+
+/*
+ * got a fatal alert message
+ */
+static void
+rcvAlert(TlsRec *tr, int err)
+{
+ char *s;
+ int i;
+
+ s = "unknown error";
+ for(i=0; i < nelem(tlserrs); i++){
+ if(tlserrs[i].err == err){
+ s = tlserrs[i].msg;
+ break;
+ }
+ }
+
+ tlsError(tr, s);
+ if(!tr->opened)
+ error(s);
+ error("tls error");
+}
+
+/*
+ * found an error while decoding the input stream
+ */
+static void
+rcvError(TlsRec *tr, int err, char *fmt, ...)
+{
+ char msg[ERRMAX];
+ va_list arg;
+
+ va_start(arg, fmt);
+ vseprint(msg, msg+sizeof(msg), fmt, arg);
+ va_end(arg);
+
+ sendAlert(tr, err);
+
+ if(!tr->opened)
+ error(msg);
+ error("tls error");
+}
+
+/*
+ * make sure the next hand operation returns with a 'msg' error
+ */
+static void
+alertHand(TlsRec *tr, char *msg)
+{
+ Block *b;
+ int n;
+
+ lock(&tr->hqlock);
+ if(tr->handq == nil){
+ unlock(&tr->hqlock);
+ return;
+ }
+ tr->hqref++;
+ unlock(&tr->hqlock);
+
+ n = strlen(msg);
+ if(waserror()){
+ dechandq(tr);
+ nexterror();
+ }
+ b = allocb(n + 2);
+ *b->wp++ = RAlert;
+ memmove(b->wp, msg, n + 1);
+ b->wp += n + 1;
+
+ qbwrite(tr->handq, b);
+
+ poperror();
+ dechandq(tr);
+}
+
+static void
+checkstate(TlsRec *tr, int ishand, int ok)
+{
+ int state;
+
+ lock(&tr->statelk);
+ state = tr->state;
+ unlock(&tr->statelk);
+ if(state & ok)
+ return;
+ switch(state){
+ case SHandshake:
+ case SOpen:
+ break;
+ case SError:
+ case SAlert:
+ if(ishand)
+ error(tr->err);
+ error("tls error");
+ case SRClose:
+ case SLClose:
+ case SClosed:
+ error("tls hungup");
+ }
+ error("tls improperly configured");
+}
+
+static Block*
+tlsbread(Chan *c, long n, ulong offset)
+{
+ int ty;
+ Block *b;
+ TlsRec *volatile tr;
+
+ ty = TYPE(c->qid);
+ switch(ty) {
+ default:
+ return devbread(c, n, offset);
+ case Qhand:
+ case Qdata:
+ break;
+ }
+
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr == nil)
+ panic("tlsbread");
+
+ if(waserror()){
+ qunlock(&tr->in.io);
+ nexterror();
+ }
+ qlock(&tr->in.io);
+ if(ty == Qdata){
+ checkstate(tr, 0, SOpen);
+ while(tr->processed == nil)
+ tlsrecread(tr);
+
+ /* return at most what was asked for */
+ b = qgrab(&tr->processed, n);
+ qunlock(&tr->in.io);
+ poperror();
+ tr->datain += BLEN(b);
+ }else{
+ checkstate(tr, 1, SOpen|SHandshake|SLClose);
+
+ /*
+ * it's ok to look at state without the lock
+ * since it only protects reading records,
+ * and we have that tr->in.io held.
+ */
+ while(!tr->opened && tr->hprocessed == nil && !qcanread(tr->handq))
+ tlsrecread(tr);
+
+ qunlock(&tr->in.io);
+ poperror();
+
+ if(waserror()){
+ qunlock(&tr->hqread);
+ nexterror();
+ }
+ qlock(&tr->hqread);
+ if(tr->hprocessed == nil){
+ b = qbread(tr->handq, MaxRecLen + 1);
+ if(*b->rp++ == RAlert){
+ strecpy(up->errstr, up->errstr+ERRMAX, (char*)b->rp);
+ freeb(b);
+ nexterror();
+ }
+ tr->hprocessed = b;
+ }
+ b = qgrab(&tr->hprocessed, n);
+ poperror();
+ qunlock(&tr->hqread);
+ tr->handin += BLEN(b);
+ }
+
+ return b;
+}
+
+static long
+tlsread(Chan *c, void *a, long n, vlong off)
+{
+ Block *volatile b;
+ Block *nb;
+ uchar *va;
+ int i, ty;
+ char *buf, *s, *e;
+ ulong offset = off;
+ TlsRec * tr;
+
+ if(c->qid.type & QTDIR)
+ return devdirread(c, a, n, 0, 0, tlsgen);
+
+ tr = tlsdevs[CONV(c->qid)];
+ ty = TYPE(c->qid);
+ switch(ty) {
+ default:
+ error(Ebadusefd);
+ case Qstatus:
+ buf = smalloc(Statlen);
+ qlock(&tr->in.seclock);
+ qlock(&tr->out.seclock);
+ s = buf;
+ e = buf + Statlen;
+ s = seprint(s, e, "State: %s\n", tlsstate(tr->state));
+ s = seprint(s, e, "Version: 0x%x\n", tr->version);
+ if(tr->in.sec != nil)
+ s = seprint(s, e, "EncIn: %s\nHashIn: %s\n", tr->in.sec->encalg, tr->in.sec->hashalg);
+ if(tr->in.new != nil)
+ s = seprint(s, e, "NewEncIn: %s\nNewHashIn: %s\n", tr->in.new->encalg, tr->in.new->hashalg);
+ if(tr->out.sec != nil)
+ s = seprint(s, e, "EncOut: %s\nHashOut: %s\n", tr->out.sec->encalg, tr->out.sec->hashalg);
+ if(tr->out.new != nil)
+ seprint(s, e, "NewEncOut: %s\nNewHashOut: %s\n", tr->out.new->encalg, tr->out.new->hashalg);
+ qunlock(&tr->in.seclock);
+ qunlock(&tr->out.seclock);
+ n = readstr(offset, a, n, buf);
+ free(buf);
+ return n;
+ case Qstats:
+ buf = smalloc(Statlen);
+ s = buf;
+ e = buf + Statlen;
+ s = seprint(s, e, "DataIn: %lld\n", tr->datain);
+ s = seprint(s, e, "DataOut: %lld\n", tr->dataout);
+ s = seprint(s, e, "HandIn: %lld\n", tr->handin);
+ seprint(s, e, "HandOut: %lld\n", tr->handout);
+ n = readstr(offset, a, n, buf);
+ free(buf);
+ return n;
+ case Qctl:
+ buf = smalloc(Statlen);
+ snprint(buf, Statlen, "%llud", CONV(c->qid));
+ n = readstr(offset, a, n, buf);
+ free(buf);
+ return n;
+ case Qdata:
+ case Qhand:
+ b = tlsbread(c, n, offset);
+ break;
+ case Qencalgs:
+ return readstr(offset, a, n, encalgs);
+ case Qhashalgs:
+ return readstr(offset, a, n, hashalgs);
+ }
+
+ if(waserror()){
+ freeblist(b);
+ nexterror();
+ }
+
+ n = 0;
+ va = a;
+ for(nb = b; nb; nb = nb->next){
+ i = BLEN(nb);
+ memmove(va+n, nb->rp, i);
+ n += i;
+ }
+
+ freeblist(b);
+ poperror();
+
+ return n;
+}
+
+/*
+ * write a block in tls records
+ */
+static void
+tlsrecwrite(TlsRec *tr, int type, Block *b)
+{
+ Block *volatile bb;
+ Block *nb;
+ uchar *p, seq[8];
+ OneWay *volatile out;
+ int n, maclen, pad, ok;
+
+ out = &tr->out;
+ bb = b;
+ if(waserror()){
+ qunlock(&out->io);
+ if(bb != nil)
+ freeb(bb);
+ nexterror();
+ }
+ qlock(&out->io);
+
+ ok = SHandshake|SOpen|SRClose;
+ if(type == RAlert)
+ ok |= SAlert;
+ while(bb != nil){
+ checkstate(tr, type != RApplication, ok);
+
+ /*
+ * get at most one maximal record's input,
+ * with padding on the front for header and
+ * back for mac and maximal block padding.
+ */
+ if(waserror()){
+ qunlock(&out->seclock);
+ nexterror();
+ }
+ qlock(&out->seclock);
+ maclen = 0;
+ pad = 0;
+ if(out->sec != nil){
+ maclen = out->sec->maclen;
+ pad = maclen + out->sec->block;
+ }
+ n = BLEN(bb);
+ if(n > MaxRecLen){
+ n = MaxRecLen;
+ nb = allocb(n + pad + RecHdrLen);
+ memmove(nb->wp + RecHdrLen, bb->rp, n);
+ bb->rp += n;
+ }else{
+ /*
+ * carefully reuse bb so it will get freed if we're out of memory
+ */
+ bb = padblock(bb, RecHdrLen);
+ if(pad)
+ nb = padblock(bb, -pad);
+ else
+ nb = bb;
+ bb = nil;
+ }
+
+ p = nb->rp;
+ p[0] = type;
+ put16(p+1, tr->version);
+ put16(p+3, n);
+
+ if(out->sec != nil){
+ put64(seq, out->seq);
+ out->seq++;
+ (*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen, n, p + RecHdrLen + n);
+ n += maclen;
+
+ /* encrypt */
+ n = (*out->sec->enc)(out->sec, p + RecHdrLen, n);
+ nb->wp = p + RecHdrLen + n;
+
+ /* update length */
+ put16(p+3, n);
+ }
+ if(type == RChangeCipherSpec){
+ if(out->new == nil)
+ error("change cipher without a new cipher");
+ freeSec(out->sec);
+ out->sec = out->new;
+ out->new = nil;
+ out->seq = 0;
+ }
+ qunlock(&out->seclock);
+ poperror();
+
+ /*
+ * if bwrite error's, we assume the block is queued.
+ * if not, we're out of sync with the receiver and will not recover.
+ */
+ if(waserror()){
+ if(strcmp(up->errstr, "interrupted") != 0)
+ tlsError(tr, "channel error");
+ nexterror();
+ }
+ devtab[tr->c->type]->bwrite(tr->c, nb, 0);
+ poperror();
+ }
+ qunlock(&out->io);
+ poperror();
+}
+
+static long
+tlsbwrite(Chan *c, Block *b, ulong offset)
+{
+ int ty;
+ ulong n;
+ TlsRec *tr;
+
+ n = BLEN(b);
+
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr == nil)
+ panic("tlsbread");
+
+ ty = TYPE(c->qid);
+ switch(ty) {
+ default:
+ return devbwrite(c, b, offset);
+ case Qhand:
+ tlsrecwrite(tr, RHandshake, b);
+ tr->handout += n;
+ break;
+ case Qdata:
+ checkstate(tr, 0, SOpen);
+ tlsrecwrite(tr, RApplication, b);
+ tr->dataout += n;
+ break;
+ }
+
+ return n;
+}
+
+typedef struct Hashalg Hashalg;
+struct Hashalg
+{
+ char *name;
+ int maclen;
+ void (*initkey)(Hashalg *, int, Secret *, uchar*);
+};
+
+static void
+initmd5key(Hashalg *ha, int version, Secret *s, uchar *p)
+{
+ s->maclen = ha->maclen;
+ if(version == SSL3Version)
+ s->mac = sslmac_md5;
+ else
+ s->mac = hmac_md5;
+ memmove(s->mackey, p, ha->maclen);
+}
+
+static void
+initclearmac(Hashalg *, int, Secret *s, uchar *)
+{
+ s->maclen = 0;
+ s->mac = nomac;
+}
+
+static void
+initsha1key(Hashalg *ha, int version, Secret *s, uchar *p)
+{
+ s->maclen = ha->maclen;
+ if(version == SSL3Version)
+ s->mac = sslmac_sha1;
+ else
+ s->mac = hmac_sha1;
+ memmove(s->mackey, p, ha->maclen);
+}
+
+static Hashalg hashtab[] =
+{
+ { "clear", 0, initclearmac, },
+ { "md5", MD5dlen, initmd5key, },
+ { "sha1", SHA1dlen, initsha1key, },
+ { 0 }
+};
+
+static Hashalg*
+parsehashalg(char *p)
+{
+ Hashalg *ha;
+
+ for(ha = hashtab; ha->name; ha++)
+ if(strcmp(p, ha->name) == 0)
+ return ha;
+ error("unsupported hash algorithm");
+ return nil;
+}
+
+typedef struct Encalg Encalg;
+struct Encalg
+{
+ char *name;
+ int keylen;
+ int ivlen;
+ void (*initkey)(Encalg *ea, Secret *, uchar*, uchar*);
+};
+
+static void
+initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *)
+{
+ s->enckey = smalloc(sizeof(RC4state));
+ s->enc = rc4enc;
+ s->dec = rc4enc;
+ s->block = 0;
+ setupRC4state(s->enckey, p, ea->keylen);
+}
+
+static void
+initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv)
+{
+ s->enckey = smalloc(sizeof(DES3state));
+ s->enc = des3enc;
+ s->dec = des3dec;
+ s->block = 8;
+ setupDES3state(s->enckey, (uchar(*)[8])p, iv);
+}
+
+static void
+initclearenc(Encalg *, Secret *s, uchar *, uchar *)
+{
+ s->enc = noenc;
+ s->dec = noenc;
+ s->block = 0;
+}
+
+static Encalg encrypttab[] =
+{
+ { "clear", 0, 0, initclearenc },
+ { "rc4_128", 128/8, 0, initRC4key },
+ { "3des_ede_cbc", 3 * 8, 8, initDES3key },
+ { 0 }
+};
+
+static Encalg*
+parseencalg(char *p)
+{
+ Encalg *ea;
+
+ for(ea = encrypttab; ea->name; ea++)
+ if(strcmp(p, ea->name) == 0)
+ return ea;
+ error("unsupported encryption algorithm");
+ return nil;
+}
+
+static long
+tlswrite(Chan *c, void *a, long n, vlong off)
+{
+ Encalg *ea;
+ Hashalg *ha;
+ TlsRec *volatile tr;
+ Secret *volatile tos, *volatile toc;
+ Block *volatile b;
+ Cmdbuf *volatile cb;
+ int m, ty;
+ char *p, *e;
+ uchar *volatile x;
+ ulong offset = off;
+
+ tr = tlsdevs[CONV(c->qid)];
+ if(tr == nil)
+ panic("tlswrite");
+
+ ty = TYPE(c->qid);
+ switch(ty){
+ case Qdata:
+ case Qhand:
+ p = a;
+ e = p + n;
+ do{
+ m = e - p;
+ if(m > MaxRecLen)
+ m = MaxRecLen;
+
+ b = allocb(m);
+ if(waserror()){
+ freeb(b);
+ nexterror();
+ }
+ memmove(b->wp, p, m);
+ poperror();
+ b->wp += m;
+
+ tlsbwrite(c, b, offset);
+
+ p += m;
+ }while(p < e);
+ return n;
+ case Qctl:
+ break;
+ default:
+ error(Ebadusefd);
+ return -1;
+ }
+
+ cb = parsecmd(a, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+ if(cb->nf < 1)
+ error("short control request");
+
+ /* mutex with operations using what we're about to change */
+ if(waserror()){
+ qunlock(&tr->in.seclock);
+ qunlock(&tr->out.seclock);
+ nexterror();
+ }
+ qlock(&tr->in.seclock);
+ qlock(&tr->out.seclock);
+
+ if(strcmp(cb->f[0], "fd") == 0){
+ if(cb->nf != 3)
+ error("usage: fd open-fd version");
+ if(tr->c != nil)
+ error(Einuse);
+ m = strtol(cb->f[2], nil, 0);
+ if(m < MinProtoVersion || m > MaxProtoVersion)
+ error("unsupported version");
+ tr->c = buftochan(cb->f[1]);
+ tr->version = m;
+ tlsSetState(tr, SHandshake, SClosed);
+ }else if(strcmp(cb->f[0], "version") == 0){
+ if(cb->nf != 2)
+ error("usage: version vers");
+ if(tr->c == nil)
+ error("must set fd before version");
+ if(tr->verset)
+ error("version already set");
+ m = strtol(cb->f[1], nil, 0);
+ if(m == SSL3Version)
+ tr->packMac = sslPackMac;
+ else if(m == TLSVersion)
+ tr->packMac = tlsPackMac;
+ else
+ error("unsupported version");
+ tr->verset = 1;
+ tr->version = m;
+ }else if(strcmp(cb->f[0], "secret") == 0){
+ if(cb->nf != 5)
+ error("usage: secret hashalg encalg isclient secretdata");
+ if(tr->c == nil || !tr->verset)
+ error("must set fd and version before secrets");
+
+ if(tr->in.new != nil){
+ freeSec(tr->in.new);
+ tr->in.new = nil;
+ }
+ if(tr->out.new != nil){
+ freeSec(tr->out.new);
+ tr->out.new = nil;
+ }
+
+ ha = parsehashalg(cb->f[1]);
+ ea = parseencalg(cb->f[2]);
+
+ p = cb->f[4];
+ m = (strlen(p)*3)/2;
+ x = smalloc(m);
+ tos = nil;
+ toc = nil;
+ if(waserror()){
+ freeSec(tos);
+ freeSec(toc);
+ free(x);
+ nexterror();
+ }
+ m = dec64(x, m, p, strlen(p));
+ if(m < 2 * ha->maclen + 2 * ea->keylen + 2 * ea->ivlen)
+ error("not enough secret data provided");
+
+ tos = smalloc(sizeof(Secret));
+ toc = smalloc(sizeof(Secret));
+ if(!ha->initkey || !ea->initkey)
+ error("misimplemented secret algorithm");
+ (*ha->initkey)(ha, tr->version, tos, &x[0]);
+ (*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]);
+ (*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]);
+ (*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]);
+
+ if(!tos->mac || !tos->enc || !tos->dec
+ || !toc->mac || !toc->enc || !toc->dec)
+ error("missing algorithm implementations");
+ if(strtol(cb->f[3], nil, 0) == 0){
+ tr->in.new = tos;
+ tr->out.new = toc;
+ }else{
+ tr->in.new = toc;
+ tr->out.new = tos;
+ }
+ if(tr->version == SSL3Version){
+ toc->unpad = sslunpad;
+ tos->unpad = sslunpad;
+ }else{
+ toc->unpad = tlsunpad;
+ tos->unpad = tlsunpad;
+ }
+ toc->encalg = ea->name;
+ toc->hashalg = ha->name;
+ tos->encalg = ea->name;
+ tos->hashalg = ha->name;
+
+ free(x);
+ poperror();
+ }else if(strcmp(cb->f[0], "changecipher") == 0){
+ if(cb->nf != 1)
+ error("usage: changecipher");
+ if(tr->out.new == nil)
+ error("can't change cipher spec without setting secret");
+
+ qunlock(&tr->in.seclock);
+ qunlock(&tr->out.seclock);
+ poperror();
+ free(cb);
+ poperror();
+
+ /*
+ * the real work is done as the message is written
+ * so the stream is encrypted in sync.
+ */
+ b = allocb(1);
+ *b->wp++ = 1;
+ tlsrecwrite(tr, RChangeCipherSpec, b);
+ return n;
+ }else if(strcmp(cb->f[0], "opened") == 0){
+ if(cb->nf != 1)
+ error("usage: opened");
+ if(tr->in.sec == nil || tr->out.sec == nil)
+ error("cipher must be configured before enabling data messages");
+ lock(&tr->statelk);
+ if(tr->state != SHandshake && tr->state != SOpen){
+ unlock(&tr->statelk);
+ error("can't enable data messages");
+ }
+ tr->state = SOpen;
+ unlock(&tr->statelk);
+ tr->opened = 1;
+ }else if(strcmp(cb->f[0], "alert") == 0){
+ if(cb->nf != 2)
+ error("usage: alert n");
+ if(tr->c == nil)
+ error("must set fd before sending alerts");
+ m = strtol(cb->f[1], nil, 0);
+
+ qunlock(&tr->in.seclock);
+ qunlock(&tr->out.seclock);
+ poperror();
+ free(cb);
+ poperror();
+
+ sendAlert(tr, m);
+
+ if(m == ECloseNotify)
+ tlsclosed(tr, SLClose);
+
+ return n;
+ } else
+ error(Ebadarg);
+
+ qunlock(&tr->in.seclock);
+ qunlock(&tr->out.seclock);
+ poperror();
+ free(cb);
+ poperror();
+
+ return n;
+}
+
+static void
+tlsinit(void)
+{
+ struct Encalg *e;
+ struct Hashalg *h;
+ int n;
+ char *cp;
+
+ tlsdevs = smalloc(sizeof(TlsRec*) * maxtlsdevs);
+ trnames = smalloc((sizeof *trnames) * maxtlsdevs);
+
+ n = 1;
+ for(e = encrypttab; e->name != nil; e++)
+ n += strlen(e->name) + 1;
+ cp = encalgs = smalloc(n);
+ for(e = encrypttab;;){
+ strcpy(cp, e->name);
+ cp += strlen(e->name);
+ e++;
+ if(e->name == nil)
+ break;
+ *cp++ = ' ';
+ }
+ *cp = 0;
+
+ n = 1;
+ for(h = hashtab; h->name != nil; h++)
+ n += strlen(h->name) + 1;
+ cp = hashalgs = smalloc(n);
+ for(h = hashtab;;){
+ strcpy(cp, h->name);
+ cp += strlen(h->name);
+ h++;
+ if(h->name == nil)
+ break;
+ *cp++ = ' ';
+ }
+ *cp = 0;
+}
+
+Dev tlsdevtab = {
+ 'a',
+ "tls",
+
+ devreset,
+ tlsinit,
+ devshutdown,
+ tlsattach,
+ tlswalk,
+ tlsstat,
+ tlsopen,
+ devcreate,
+ tlsclose,
+ tlsread,
+ tlsbread,
+ tlswrite,
+ tlsbwrite,
+ devremove,
+ tlswstat,
+};
+
+/* get channel associated with an fd */
+static Chan*
+buftochan(char *p)
+{
+ Chan *c;
+ int fd;
+
+ if(p == 0)
+ error(Ebadarg);
+ fd = strtoul(p, 0, 0);
+ if(fd < 0)
+ error(Ebadarg);
+ c = fdtochan(fd, -1, 0, 1); /* error check and inc ref */
+ return c;
+}
+
+static void
+sendAlert(TlsRec *tr, int err)
+{
+ Block *b;
+ int i, fatal;
+ char *msg;
+
+ fatal = 1;
+ msg = "tls unknown alert";
+ for(i=0; i < nelem(tlserrs); i++) {
+ if(tlserrs[i].err == err) {
+ msg = tlserrs[i].msg;
+ if(tr->version == SSL3Version)
+ err = tlserrs[i].sslerr;
+ else
+ err = tlserrs[i].tlserr;
+ fatal = tlserrs[i].fatal;
+ break;
+ }
+ }
+
+ if(!waserror()){
+ b = allocb(2);
+ *b->wp++ = fatal + 1;
+ *b->wp++ = err;
+ if(fatal)
+ tlsSetState(tr, SAlert, SOpen|SHandshake|SRClose);
+ tlsrecwrite(tr, RAlert, b);
+ poperror();
+ }
+ if(fatal)
+ tlsError(tr, msg);
+}
+
+static void
+tlsError(TlsRec *tr, char *msg)
+{
+ int s;
+
+ lock(&tr->statelk);
+ s = tr->state;
+ tr->state = SError;
+ if(s != SError){
+ strncpy(tr->err, msg, ERRMAX - 1);
+ tr->err[ERRMAX - 1] = '\0';
+ }
+ unlock(&tr->statelk);
+ if(s != SError)
+ alertHand(tr, msg);
+}
+
+static void
+tlsSetState(TlsRec *tr, int new, int old)
+{
+ lock(&tr->statelk);
+ if(tr->state & old)
+ tr->state = new;
+ unlock(&tr->statelk);
+}
+
+/* hand up a digest connection */
+static void
+tlshangup(TlsRec *tr)
+{
+ Block *b;
+
+ qlock(&tr->in.io);
+ for(b = tr->processed; b; b = tr->processed){
+ tr->processed = b->next;
+ freeb(b);
+ }
+ if(tr->unprocessed != nil){
+ freeb(tr->unprocessed);
+ tr->unprocessed = nil;
+ }
+ qunlock(&tr->in.io);
+
+ tlsSetState(tr, SClosed, ~0);
+}
+
+static TlsRec*
+newtls(Chan *ch)
+{
+ TlsRec **pp, **ep, **np;
+ char **nmp;
+ int t, newmax;
+
+ if(waserror()) {
+ unlock(&tdlock);
+ nexterror();
+ }
+ lock(&tdlock);
+ ep = &tlsdevs[maxtlsdevs];
+ for(pp = tlsdevs; pp < ep; pp++)
+ if(*pp == nil)
+ break;
+ if(pp >= ep) {
+ if(maxtlsdevs >= MaxTlsDevs) {
+ unlock(&tdlock);
+ poperror();
+ return nil;
+ }
+ newmax = 2 * maxtlsdevs;
+ if(newmax > MaxTlsDevs)
+ newmax = MaxTlsDevs;
+ np = smalloc(sizeof(TlsRec*) * newmax);
+ memmove(np, tlsdevs, sizeof(TlsRec*) * maxtlsdevs);
+ tlsdevs = np;
+ pp = &tlsdevs[maxtlsdevs];
+ memset(pp, 0, sizeof(TlsRec*)*(newmax - maxtlsdevs));
+
+ nmp = smalloc(sizeof *nmp * newmax);
+ memmove(nmp, trnames, sizeof *nmp * maxtlsdevs);
+ trnames = nmp;
+
+ maxtlsdevs = newmax;
+ }
+ *pp = mktlsrec();
+ if(pp - tlsdevs >= tdhiwat)
+ tdhiwat++;
+ t = TYPE(ch->qid);
+ if(t == Qclonus)
+ t = Qctl;
+ ch->qid.path = QID(pp - tlsdevs, t);
+ ch->qid.vers = 0;
+ unlock(&tdlock);
+ poperror();
+ return *pp;
+}
+
+static TlsRec *
+mktlsrec(void)
+{
+ TlsRec *tr;
+
+ tr = mallocz(sizeof(*tr), 1);
+ if(tr == nil)
+ error(Enomem);
+ tr->state = SClosed;
+ tr->ref = 1;
+ kstrdup(&tr->user, up->user);
+ tr->perm = 0660;
+ return tr;
+}
+
+static char*
+tlsstate(int s)
+{
+ switch(s){
+ case SHandshake:
+ return "Handshaking";
+ case SOpen:
+ return "Established";
+ case SRClose:
+ return "RemoteClosed";
+ case SLClose:
+ return "LocalClosed";
+ case SAlert:
+ return "Alerting";
+ case SError:
+ return "Errored";
+ case SClosed:
+ return "Closed";
+ }
+ return "Unknown";
+}
+
+static void
+freeSec(Secret *s)
+{
+ if(s != nil){
+ free(s->enckey);
+ free(s);
+ }
+}
+
+static int
+noenc(Secret *, uchar *, int n)
+{
+ return n;
+}
+
+static int
+rc4enc(Secret *sec, uchar *buf, int n)
+{
+ rc4(sec->enckey, buf, n);
+ return n;
+}
+
+static int
+tlsunpad(uchar *buf, int n, int block)
+{
+ int pad, nn;
+
+ pad = buf[n - 1];
+ nn = n - 1 - pad;
+ if(nn <= 0 || n % block)
+ return -1;
+ while(--n > nn)
+ if(pad != buf[n - 1])
+ return -1;
+ return nn;
+}
+
+static int
+sslunpad(uchar *buf, int n, int block)
+{
+ int pad, nn;
+
+ pad = buf[n - 1];
+ nn = n - 1 - pad;
+ if(nn <= 0 || n % block)
+ return -1;
+ return nn;
+}
+
+static int
+blockpad(uchar *buf, int n, int block)
+{
+ int pad, nn;
+
+ nn = n + block;
+ nn -= nn % block;
+ pad = nn - (n + 1);
+ while(n < nn)
+ buf[n++] = pad;
+ return nn;
+}
+
+static int
+des3enc(Secret *sec, uchar *buf, int n)
+{
+ n = blockpad(buf, n, 8);
+ des3CBCencrypt(buf, n, sec->enckey);
+ return n;
+}
+
+static int
+des3dec(Secret *sec, uchar *buf, int n)
+{
+ des3CBCdecrypt(buf, n, sec->enckey);
+ return (*sec->unpad)(buf, n, 8);
+}
+static DigestState*
+nomac(uchar *, ulong, uchar *, ulong, uchar *, DigestState *)
+{
+ return nil;
+}
+
+/*
+ * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac.
+ */
+static DigestState*
+sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s,
+ DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen)
+{
+ int i;
+ uchar pad[48], innerdigest[20];
+
+ if(xlen > sizeof(innerdigest)
+ || padlen > sizeof(pad))
+ return nil;
+
+ if(klen>64)
+ return nil;
+
+ /* first time through */
+ if(s == nil){
+ for(i=0; i<padlen; i++)
+ pad[i] = 0x36;
+ s = (*x)(key, klen, nil, nil);
+ s = (*x)(pad, padlen, nil, s);
+ if(s == nil)
+ return nil;
+ }
+
+ s = (*x)(p, len, nil, s);
+ if(digest == nil)
+ return s;
+
+ /* last time through */
+ for(i=0; i<padlen; i++)
+ pad[i] = 0x5c;
+ (*x)(nil, 0, innerdigest, s);
+ s = (*x)(key, klen, nil, nil);
+ s = (*x)(pad, padlen, nil, s);
+ (*x)(innerdigest, xlen, digest, s);
+ return nil;
+}
+
+static DigestState*
+sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
+{
+ return sslmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen, 40);
+}
+
+static DigestState*
+sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
+{
+ return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);
+}
+
+static void
+sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
+{
+ DigestState *s;
+ uchar buf[11];
+
+ memmove(buf, seq, 8);
+ buf[8] = header[0];
+ buf[9] = header[3];
+ buf[10] = header[4];
+
+ s = (*sec->mac)(buf, 11, mackey, sec->maclen, 0, 0);
+ (*sec->mac)(body, len, mackey, sec->maclen, mac, s);
+}
+
+static void
+tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
+{
+ DigestState *s;
+ uchar buf[13];
+
+ memmove(buf, seq, 8);
+ memmove(&buf[8], header, 5);
+
+ s = (*sec->mac)(buf, 13, mackey, sec->maclen, 0, 0);
+ (*sec->mac)(body, len, mackey, sec->maclen, mac, s);
+}
+
+static void
+put32(uchar *p, u32int x)
+{
+ p[0] = x>>24;
+ p[1] = x>>16;
+ p[2] = x>>8;
+ p[3] = x;
+}
+
+static void
+put64(uchar *p, vlong x)
+{
+ put32(p, (u32int)(x >> 32));
+ put32(p+4, (u32int)x);
+}
+
+static void
+put24(uchar *p, int x)
+{
+ p[0] = x>>16;
+ p[1] = x>>8;
+ p[2] = x;
+}
+
+static void
+put16(uchar *p, int x)
+{
+ p[0] = x>>8;
+ p[1] = x;
+}
+
+static u32int
+get32(uchar *p)
+{
+ return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
+}
+
+static int
+get16(uchar *p)
+{
+ return (p[0]<<8)|p[1];
+}
diff --git a/sys/src/9/ppc/etherfcc.c b/sys/src/9/ppc/etherfcc.c
new file mode 100755
index 000000000..0b2e1f21e
--- /dev/null
+++ b/sys/src/9/ppc/etherfcc.c
@@ -0,0 +1,891 @@
+/*
+ * FCCn ethernet
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "imm.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+#include "../ppc/ethermii.h"
+
+#define DBG 1
+
+enum {
+ Nrdre = 128, /* receive descriptor ring entries */
+ Ntdre = 128, /* transmit descriptor ring entries */
+
+ Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
+ Bufsize = Rbsize+CACHELINESZ, /* extra room for alignment */
+};
+
+enum {
+
+ /* ether-specific Rx BD bits */
+ RxMiss= SBIT(7),
+ RxeLG= SBIT(10),
+ RxeNO= SBIT(11),
+ RxeSH= SBIT(12),
+ RxeCR= SBIT(13),
+ RxeOV= SBIT(14),
+ RxeCL= SBIT(15),
+ RxError= (RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL), /* various error flags */
+
+ /* ether-specific Tx BD bits */
+ TxPad= SBIT(1), /* pad short frames */
+ TxTC= SBIT(5), /* transmit CRC */
+ TxeDEF= SBIT(6),
+ TxeHB= SBIT(7),
+ TxeLC= SBIT(8),
+ TxeRL= SBIT(9),
+ TxeUN= SBIT(14),
+ TxeCSL= SBIT(15),
+
+ /* psmr */
+ CRCE= BIT(24), /* Ethernet CRC */
+ FCE= BIT(10), /* flow control */
+ PRO= BIT(9), /* promiscuous mode */
+ FDE= BIT(5), /* full duplex ethernet */
+ LPB= BIT(3), /* local protect bit */
+
+ /* gfmr */
+ ENET= 0xc, /* ethernet mode */
+ ENT= BIT(27),
+ ENR= BIT(26),
+ TCI= BIT(2),
+
+ /* FCC function code register */
+ GBL= 0x20,
+ BO= 0x18,
+ EB= 0x10, /* Motorola byte order */
+ TC2= 0x04,
+ DTB= 0x02,
+ BDB= 0x01,
+
+ /* FCC Event/Mask bits */
+ GRA= SBIT(8),
+ RXC= SBIT(9),
+ TXC= SBIT(10),
+ TXE= SBIT(11),
+ RXF= SBIT(12),
+ BSY= SBIT(13),
+ TXB= SBIT(14),
+ RXB= SBIT(15),
+};
+
+enum { /* Mcr */
+ MDIread = 0x60020000, /* read opcode */
+ MDIwrite = 0x50020000, /* write opcode */
+};
+
+typedef struct Etherparam Etherparam;
+struct Etherparam {
+/*0x00*/ FCCparam;
+/*0x3c*/ ulong stat_buf;
+/*0x40*/ ulong cam_ptr;
+/*0x44*/ ulong cmask;
+/*0x48*/ ulong cpres;
+/*0x4c*/ ulong crcec;
+/*0x50*/ ulong alec;
+/*0x54*/ ulong disfc;
+/*0x58*/ ushort retlim;
+/*0x5a*/ ushort retcnt;
+/*0x5c*/ ushort p_per;
+/*0x5e*/ ushort boff_cnt;
+/*0x60*/ ulong gaddr[2];
+/*0x68*/ ushort tfcstat;
+/*0x6a*/ ushort tfclen;
+/*0x6c*/ ulong tfcptr;
+/*0x70*/ ushort mflr;
+/*0x72*/ ushort paddr[3];
+/*0x78*/ ushort ibd_cnt;
+/*0x7a*/ ushort ibd_start;
+/*0x7c*/ ushort ibd_end;
+/*0x7e*/ ushort tx_len;
+/*0x80*/ uchar ibd_base[32];
+/*0xa0*/ ulong iaddr[2];
+/*0xa8*/ ushort minflr;
+/*0xaa*/ ushort taddr[3];
+/*0xb0*/ ushort padptr;
+/*0xb2*/ ushort Rsvdb2;
+/*0xb4*/ ushort cf_range;
+/*0xb6*/ ushort max_b;
+/*0xb8*/ ushort maxd1;
+/*0xba*/ ushort maxd2;
+/*0xbc*/ ushort maxd;
+/*0xbe*/ ushort dma_cnt;
+/*0xc0*/ ulong octc;
+/*0xc4*/ ulong colc;
+/*0xc8*/ ulong broc;
+/*0xcc*/ ulong mulc;
+/*0xd0*/ ulong uspc;
+/*0xd4*/ ulong frgc;
+/*0xd8*/ ulong ospc;
+/*0xdc*/ ulong jbrc;
+/*0xe0*/ ulong p64c;
+/*0xe4*/ ulong p65c;
+/*0xe8*/ ulong p128c;
+/*0xec*/ ulong p256c;
+/*0xf0*/ ulong p512c;
+/*0xf4*/ ulong p1024c;
+/*0xf8*/ ulong cam_buf;
+/*0xfc*/ ulong Rsvdfc;
+/*0x100*/
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ Lock;
+ int fccid;
+ int port;
+ ulong pmdio;
+ ulong pmdck;
+ int init;
+ int active;
+ int duplex; /* 1 == full */
+ FCC* fcc;
+
+ Ring;
+ Block* rcvbufs[Nrdre];
+ Mii* mii;
+ Timer;
+
+ ulong interrupts; /* statistics */
+ ulong deferred;
+ ulong heartbeat;
+ ulong latecoll;
+ ulong retrylim;
+ ulong underrun;
+ ulong overrun;
+ ulong carrierlost;
+ ulong retrycount;
+};
+
+static int fccirq[] = {0x20, 0x21, 0x22};
+static int fccid[] = {FCC1ID, FCC2ID, FCC3ID};
+
+#ifdef DBG
+ulong fccrhisto[16];
+ulong fccthisto[16];
+ulong fccrthisto[16];
+ulong fcctrhisto[16];
+ulong ehisto[0x80];
+#endif
+
+static int fccmiimir(Mii*, int, int);
+static int fccmiimiw(Mii*, int, int, int);
+static void fccltimer(Ureg*, Timer*);
+
+static void
+attach(Ether *ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(ctlr);
+ ctlr->active = 1;
+ ctlr->fcc->gfmr |= ENR|ENT;
+ iunlock(ctlr);
+ ctlr->tmode = Tperiodic;
+ ctlr->tf = fccltimer;
+ ctlr->ta = ether;
+ ctlr->tns = 5000000000LL; /* 5 seconds */
+ timeradd(ctlr);
+}
+
+static void
+closed(Ether *ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(ctlr);
+ ctlr->active = 0;
+ ctlr->fcc->gfmr &= ~(ENR|ENT);
+ iunlock(ctlr);
+ print("Ether closed\n");
+}
+
+static void
+promiscuous(void* arg, int on)
+{
+ Ether *ether;
+ Ctlr *ctlr;
+
+ ether = (Ether*)arg;
+ ctlr = ether->ctlr;
+
+ ilock(ctlr);
+ if(on || ether->nmaddr)
+ ctlr->fcc->fpsmr |= PRO;
+ else
+ ctlr->fcc->fpsmr &= ~PRO;
+ iunlock(ctlr);
+}
+
+static void
+multicast(void* arg, uchar *addr, int on)
+{
+ Ether *ether;
+ Ctlr *ctlr;
+
+ USED(addr, on); /* if on, could SetGroupAddress; if !on, it's hard */
+
+ ether = (Ether*)arg;
+ ctlr = ether->ctlr;
+
+ ilock(ctlr);
+ if(ether->prom || ether->nmaddr)
+ ctlr->fcc->fpsmr |= PRO;
+ else
+ ctlr->fcc->fpsmr &= ~PRO;
+ iunlock(ctlr);
+}
+
+static void
+txstart(Ether *ether)
+{
+ int len;
+ Ctlr *ctlr;
+ Block *b;
+ BD *dre;
+
+ ctlr = ether->ctlr;
+ if(ctlr->init)
+ return;
+ while(ctlr->ntq < Ntdre-1){
+ b = qget(ether->oq);
+ if(b == 0)
+ break;
+
+ dre = &ctlr->tdr[ctlr->tdrh];
+ dczap(dre, sizeof(BD));
+ if(dre->status & BDReady)
+ panic("ether: txstart");
+
+ /*
+ * Give ownership of the descriptor to the chip, increment the
+ * software ring descriptor pointer and tell the chip to poll.
+ */
+ len = BLEN(b);
+ if(ctlr->txb[ctlr->tdrh] != nil)
+ panic("fcc/ether: txstart");
+ ctlr->txb[ctlr->tdrh] = b;
+ if((ulong)b->rp&1)
+ panic("fcc/ether: txstart align"); /* TO DO: ensure alignment */
+ dre->addr = PADDR(b->rp);
+ dre->length = len;
+ dcflush(b->rp, len);
+ dcflush(dre, sizeof(BD));
+ dre->status = (dre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
+ dcflush(dre, sizeof(BD));
+/* ctlr->fcc->ftodr = 1<<15; /* transmit now; Don't do this according to errata */
+ ctlr->ntq++;
+ ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
+ }
+}
+
+static void
+transmit(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(ctlr);
+ txstart(ether);
+ iunlock(ctlr);
+}
+
+static void
+interrupt(Ureg*, void *arg)
+{
+ int len, status, rcvd, xmtd, restart;
+ ushort events;
+ Ctlr *ctlr;
+ BD *dre;
+ Block *b, *nb;
+ Ether *ether = arg;
+
+ ctlr = ether->ctlr;
+ if(!ctlr->active)
+ return; /* not ours */
+
+ /*
+ * Acknowledge all interrupts and whine about those that shouldn't
+ * happen.
+ */
+ events = ctlr->fcc->fcce;
+ ctlr->fcc->fcce = events; /* clear events */
+
+#ifdef DBG
+ ehisto[events & 0x7f]++;
+#endif
+
+ ctlr->interrupts++;
+
+ if(events & BSY)
+ ctlr->overrun++;
+ if(events & TXE)
+ ether->oerrs++;
+
+#ifdef DBG
+ rcvd = xmtd = 0;
+#endif
+ /*
+ * Receiver interrupt: run round the descriptor ring logging
+ * errors and passing valid receive data up to the higher levels
+ * until we encounter a descriptor still owned by the chip.
+ */
+ if(events & RXF){
+ dre = &ctlr->rdr[ctlr->rdrx];
+ dczap(dre, sizeof(BD));
+ while(((status = dre->status) & BDEmpty) == 0){
+ rcvd++;
+ if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
+ if(status & (RxeLG|RxeSH))
+ ether->buffs++;
+ if(status & RxeNO)
+ ether->frames++;
+ if(status & RxeCR)
+ ether->crcs++;
+ if(status & RxeOV)
+ ether->overflows++;
+ print("eth rx: %ux\n", status);
+ }else{
+ /*
+ * We have a packet. Read it in.
+ */
+ len = dre->length-4;
+ b = ctlr->rcvbufs[ctlr->rdrx];
+ assert(dre->addr == PADDR(b->rp));
+ dczap(b->rp, len);
+ if(nb = iallocb(Bufsize)){
+ b->wp += len;
+ etheriq(ether, b, 1);
+ b = nb;
+ b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1));
+ b->wp = b->rp;
+ ctlr->rcvbufs[ctlr->rdrx] = b;
+ ctlr->rdr[ctlr->rdrx].addr = PADDR(b->wp);
+ }else
+ ether->soverflows++;
+ }
+
+ /*
+ * Finished with this descriptor, reinitialise it,
+ * give it back to the chip, then on to the next...
+ */
+ dre->length = 0;
+ dre->status = (status & BDWrap) | BDEmpty | BDInt;
+ dcflush(dre, sizeof(BD));
+
+ ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
+ dre = &ctlr->rdr[ctlr->rdrx];
+ dczap(dre, sizeof(BD));
+ }
+ }
+
+ /*
+ * Transmitter interrupt: handle anything queued for a free descriptor.
+ */
+ if(events & (TXB|TXE)){
+ ilock(ctlr);
+ restart = 0;
+ while(ctlr->ntq){
+ dre = &ctlr->tdr[ctlr->tdri];
+ dczap(dre, sizeof(BD));
+ status = dre->status;
+ if(status & BDReady)
+ break;
+ if(status & TxeDEF)
+ ctlr->deferred++;
+ if(status & TxeHB)
+ ctlr->heartbeat++;
+ if(status & TxeLC)
+ ctlr->latecoll++;
+ if(status & TxeRL)
+ ctlr->retrylim++;
+ if(status & TxeUN)
+ ctlr->underrun++;
+ if(status & TxeCSL)
+ ctlr->carrierlost++;
+ if(status & (TxeLC|TxeRL|TxeUN))
+ restart = 1;
+ ctlr->retrycount += (status>>2)&0xF;
+ b = ctlr->txb[ctlr->tdri];
+ if(b == nil)
+ panic("fcce/interrupt: bufp");
+ ctlr->txb[ctlr->tdri] = nil;
+ freeb(b);
+ ctlr->ntq--;
+ ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
+ xmtd++;
+ }
+
+ if(restart){
+ ctlr->fcc->gfmr &= ~ENT;
+ delay(10);
+ ctlr->fcc->gfmr |= ENT;
+ cpmop(RestartTx, ctlr->fccid, 0xc);
+ }
+ txstart(ether);
+ iunlock(ctlr);
+ }
+#ifdef DBG
+ if(rcvd >= nelem(fccrhisto))
+ rcvd = nelem(fccrhisto) - 1;
+ if(xmtd >= nelem(fccthisto))
+ xmtd = nelem(fccthisto) - 1;
+ if(rcvd)
+ fcctrhisto[xmtd]++;
+ else
+ fccthisto[xmtd]++;
+ if(xmtd)
+ fccrthisto[rcvd]++;
+ else
+ fccrhisto[rcvd]++;
+#endif
+}
+
+static long
+ifstat(Ether* ether, void* a, long n, ulong offset)
+{
+ char *p;
+ int len, i, r;
+ Ctlr *ctlr;
+ MiiPhy *phy;
+
+ if(n == 0)
+ return 0;
+
+ ctlr = ether->ctlr;
+
+ p = malloc(READSTR);
+ len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts);
+ len += snprint(p+len, READSTR-len, "carrierlost: %lud\n", ctlr->carrierlost);
+ len += snprint(p+len, READSTR-len, "heartbeat: %lud\n", ctlr->heartbeat);
+ len += snprint(p+len, READSTR-len, "retrylimit: %lud\n", ctlr->retrylim);
+ len += snprint(p+len, READSTR-len, "retrycount: %lud\n", ctlr->retrycount);
+ len += snprint(p+len, READSTR-len, "latecollisions: %lud\n", ctlr->latecoll);
+ len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n", ctlr->overrun);
+ len += snprint(p+len, READSTR-len, "txunderruns: %lud\n", ctlr->underrun);
+ len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n", ctlr->deferred);
+ miistatus(ctlr->mii);
+ phy = ctlr->mii->curphy;
+ len += snprint(p+len, READSTR-len, "phy: link=%d, tfc=%d, rfc=%d, speed=%d, fd=%d\n",
+ phy->link, phy->tfc, phy->rfc, phy->speed, phy->fd);
+
+#ifdef DBG
+ if(ctlr->mii != nil && ctlr->mii->curphy != nil){
+ len += snprint(p+len, READSTR, "phy: ");
+ for(i = 0; i < NMiiPhyr; i++){
+ if(i && ((i & 0x07) == 0))
+ len += snprint(p+len, READSTR-len, "\n ");
+ r = miimir(ctlr->mii, i);
+ len += snprint(p+len, READSTR-len, " %4.4uX", r);
+ }
+ snprint(p+len, READSTR-len, "\n");
+ }
+#endif
+ snprint(p+len, READSTR-len, "\n");
+
+ n = readstr(offset, a, n, p);
+ free(p);
+
+ return n;
+}
+
+/*
+ * This follows the MPC8260 user guide: section28.9's initialisation sequence.
+ */
+static int
+fccsetup(Ctlr *ctlr, FCC *fcc, uchar *ea)
+{
+ int i;
+ Etherparam *p;
+ MiiPhy *phy;
+
+ /* Turn Ethernet off */
+ fcc->gfmr &= ~(ENR | ENT);
+
+ ioplock();
+ switch(ctlr->port) {
+ default:
+ iopunlock();
+ return -1;
+ case 0:
+ /* Step 1 (Section 28.9), write the parallel ports */
+ ctlr->pmdio = 0x01000000;
+ ctlr->pmdck = 0x08000000;
+ imm->port[0].pdir &= ~A1dir0;
+ imm->port[0].pdir |= A1dir1;
+ imm->port[0].psor &= ~A1psor0;
+ imm->port[0].psor |= A1psor1;
+ imm->port[0].ppar |= (A1dir0 | A1dir1);
+ /* Step 2, Port C clocks */
+ imm->port[2].psor &= ~0x00000c00;
+ imm->port[2].pdir &= ~0x00000c00;
+ imm->port[2].ppar |= 0x00000c00;
+ imm->port[3].pdat |= (ctlr->pmdio | ctlr->pmdck);
+ imm->port[3].podr |= ctlr->pmdio;
+ imm->port[3].pdir |= (ctlr->pmdio | ctlr->pmdck);
+ imm->port[3].ppar &= ~(ctlr->pmdio | ctlr->pmdck);
+ eieio();
+ /* Step 3, Serial Interface clock routing */
+ imm->cmxfcr &= ~0xff000000; /* Clock mask */
+ imm->cmxfcr |= 0x37000000; /* Clock route */
+ break;
+
+ case 1:
+ /* Step 1 (Section 28.9), write the parallel ports */
+ ctlr->pmdio = 0x00400000;
+ ctlr->pmdck = 0x00200000;
+ imm->port[1].pdir &= ~B2dir0;
+ imm->port[1].pdir |= B2dir1;
+ imm->port[1].psor &= ~B2psor0;
+ imm->port[1].psor |= B2psor1;
+ imm->port[1].ppar |= (B2dir0 | B2dir1);
+ /* Step 2, Port C clocks */
+ imm->port[2].psor &= ~0x00003000;
+ imm->port[2].pdir &= ~0x00003000;
+ imm->port[2].ppar |= 0x00003000;
+
+ imm->port[2].pdat |= (ctlr->pmdio | ctlr->pmdck);
+ imm->port[2].podr |= ctlr->pmdio;
+ imm->port[2].pdir |= (ctlr->pmdio | ctlr->pmdck);
+ imm->port[2].ppar &= ~(ctlr->pmdio | ctlr->pmdck);
+ eieio();
+ /* Step 3, Serial Interface clock routing */
+ imm->cmxfcr &= ~0x00ff0000;
+ imm->cmxfcr |= 0x00250000;
+ break;
+
+ case 2:
+ /* Step 1 (Section 28.9), write the parallel ports */
+ imm->port[1].pdir &= ~B3dir0;
+ imm->port[1].pdir |= B3dir1;
+ imm->port[1].psor &= ~B3psor0;
+ imm->port[1].psor |= B3psor1;
+ imm->port[1].ppar |= (B3dir0 | B3dir1);
+ /* Step 2, Port C clocks */
+ imm->port[2].psor &= ~0x0000c000;
+ imm->port[2].pdir &= ~0x0000c000;
+ imm->port[2].ppar |= 0x0000c000;
+ imm->port[3].pdat |= (ctlr->pmdio | ctlr->pmdck);
+ imm->port[3].podr |= ctlr->pmdio;
+ imm->port[3].pdir |= (ctlr->pmdio | ctlr->pmdck);
+ imm->port[3].ppar &= ~(ctlr->pmdio | ctlr->pmdck);
+ eieio();
+ /* Step 3, Serial Interface clock routing */
+ imm->cmxfcr &= ~0x0000ff00;
+ imm->cmxfcr |= 0x00003700;
+ break;
+ }
+ iopunlock();
+
+ p = (Etherparam*)(m->immr->prmfcc + ctlr->port);
+ memset(p, 0, sizeof(Etherparam));
+
+ /* Step 4 */
+ fcc->gfmr |= ENET;
+
+ /* Step 5 */
+ fcc->fpsmr = CRCE | FDE | LPB; /* full duplex operation */
+ ctlr->duplex = ~0;
+
+ /* Step 6 */
+ fcc->fdsr = 0xd555;
+
+ /* Step 7, initialize parameter ram */
+ p->rbase = PADDR(ctlr->rdr);
+ p->tbase = PADDR(ctlr->tdr);
+ p->rstate = (GBL | EB) << 24;
+ p->tstate = (GBL | EB) << 24;
+
+ p->cmask = 0xdebb20e3;
+ p->cpres = 0xffffffff;
+
+ p->retlim = 15; /* retry limit */
+
+ p->mrblr = (Rbsize+0x1f)&~0x1f; /* multiple of 32 */
+ p->mflr = Rbsize;
+ p->minflr = ETHERMINTU;
+ p->maxd1 = (Rbsize+7) & ~7;
+ p->maxd2 = (Rbsize+7) & ~7;
+
+ for(i=0; i<Eaddrlen; i+=2)
+ p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i];
+
+ /* Step 7, initialize parameter ram, configuration-dependent values */
+ p->riptr = m->immr->fccextra[ctlr->port].ri - (uchar*)IMMR;
+ p->tiptr = m->immr->fccextra[ctlr->port].ti - (uchar*)IMMR;
+ p->padptr = m->immr->fccextra[ctlr->port].pad - (uchar*)IMMR;
+ memset(m->immr->fccextra[ctlr->port].pad, 0x88, 0x20);
+
+ /* Step 8, clear out events */
+ fcc->fcce = ~0;
+
+ /* Step 9, Interrupt enable */
+ fcc->fccm = TXE | RXF | TXB;
+
+ /* Step 10, Configure interrupt priority (not done here) */
+ /* Step 11, Clear out current events */
+ /* Step 12, Enable interrupts to the CP interrupt controller */
+
+ /* Step 13, Issue the Init Tx and Rx command, specifying 0xc for ethernet*/
+ cpmop(InitRxTx, fccid[ctlr->port], 0xc);
+
+ /* Step 14, Link management */
+ if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+ return -1;
+ ctlr->mii->mir = fccmiimir;
+ ctlr->mii->miw = fccmiimiw;
+ ctlr->mii->ctlr = ctlr;
+
+ if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
+ free(ctlr->mii);
+ ctlr->mii = nil;
+ return -1;
+ }
+ miiane(ctlr->mii, ~0, ~0, ~0);
+#ifdef DBG
+ print("oui=%X, phyno=%d, ", phy->oui, phy->phyno);
+ print("anar=%ux, ", phy->anar);
+ print("fc=%ux, ", phy->fc);
+ print("mscr=%ux, ", phy->mscr);
+
+ print("link=%ux, ", phy->link);
+ print("speed=%ux, ", phy->speed);
+ print("fd=%ux, ", phy->fd);
+ print("rfc=%ux, ", phy->rfc);
+ print("tfc=%ux\n", phy->tfc);
+#endif
+ /* Step 15, Enable ethernet: done at attach time */
+ return 0;
+}
+
+static int
+reset(Ether* ether)
+{
+ uchar ea[Eaddrlen];
+ Ctlr *ctlr;
+ FCC *fcc;
+ Block *b;
+ int i;
+
+ if(m->cpuhz < 24000000){
+ print("%s ether: system speed must be >= 24MHz for ether use\n", ether->type);
+ return -1;
+ }
+
+ if(ether->port > 3){
+ print("%s ether: no FCC port %ld\n", ether->type, ether->port);
+ return -1;
+ }
+ ether->irq = fccirq[ether->port];
+ ether->tbdf = BusPPC;
+ fcc = imm->fcc + ether->port;
+
+ ctlr = malloc(sizeof(*ctlr));
+ ether->ctlr = ctlr;
+ memset(ctlr, 0, sizeof(*ctlr));
+ ctlr->fcc = fcc;
+ ctlr->port = ether->port;
+ ctlr->fccid = fccid[ether->port];
+
+ /* Ioringinit will allocate the buffer descriptors in normal memory
+ * and NOT in Dual-Ported Ram, as prescribed by the MPC8260
+ * PowerQUICC II manual (Section 28.6). When they are allocated
+ * in DPram and the Dcache is enabled, the processor will hang
+ */
+ if(ioringinit(ctlr, Nrdre, Ntdre, 0) < 0)
+ panic("etherfcc init");
+ for(i = 0; i < Nrdre; i++){
+ b = iallocb(Bufsize);
+ b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1));
+ b->wp = b->rp;
+ ctlr->rcvbufs[i] = b;
+ ctlr->rdr[i].addr = PADDR(b->wp);
+ }
+
+ fccsetup(ctlr, fcc, ether->ea);
+
+ ether->mbps = 100; /* TO DO: could be 10mbps */
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->ifstat = ifstat;
+
+ ether->arg = ether;
+ ether->promiscuous = promiscuous;
+ ether->multicast = multicast;
+
+ /*
+ * Until we know where to find it, insist that the plan9.ini
+ * entry holds the Ethernet address.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+ print("no ether address");
+ return -1;
+ }
+
+ return 0;
+}
+
+void
+etherfcclink(void)
+{
+ addethercard("fcc", reset);
+}
+
+static void
+nanodelay(void)
+{
+ static int count;
+ int i;
+
+ for(i = 0; i < 500; i++)
+ count++;
+ return;
+}
+
+static
+void miiwriteloop(Ctlr *ctlr, Port *port, int cnt, ulong cmd)
+{
+ int i;
+
+ for(i = 0; i < cnt; i++){
+ port->pdat &= ~ctlr->pmdck;
+ if(cmd & BIT(i))
+ port->pdat |= ctlr->pmdio;
+ else
+ port->pdat &= ~ctlr->pmdio;
+ nanodelay();
+ port->pdat |= ctlr->pmdck;
+ nanodelay();
+ }
+}
+
+static int
+fccmiimiw(Mii *mii, int pa, int ra, int data)
+{
+ int x;
+ Port *port;
+ ulong cmd;
+ Ctlr *ctlr;
+
+ /*
+ * MII Management Interface Write.
+ */
+
+ ctlr = mii->ctlr;
+ port = imm->port + 3;
+ cmd = MDIwrite | (pa<<(5+2+16))| (ra<<(2+16)) | (data & 0xffff);
+
+ x = splhi();
+
+ port->pdir |= (ctlr->pmdio|ctlr->pmdck);
+ nanodelay();
+
+ miiwriteloop(ctlr, port, 32, ~0);
+ miiwriteloop(ctlr, port, 32, cmd);
+
+ port->pdir |= (ctlr->pmdio|ctlr->pmdck);
+ nanodelay();
+
+ miiwriteloop(ctlr, port, 32, ~0);
+
+ splx(x);
+ return 1;
+}
+
+static int
+fccmiimir(Mii *mii, int pa, int ra)
+{
+ int data, i, x;
+ Port *port;
+ ulong cmd;
+ Ctlr *ctlr;
+
+ ctlr = mii->ctlr;
+ port = imm->port + 3;
+
+ cmd = MDIread | pa<<(5+2+16) | ra<<(2+16);
+
+ x = splhi();
+ port->pdir |= (ctlr->pmdio|ctlr->pmdck);
+ nanodelay();
+
+ miiwriteloop(ctlr, port, 32, ~0);
+
+ /* Clock out the first 14 MS bits of the command */
+ miiwriteloop(ctlr, port, 14, cmd);
+
+ /* Turn-around */
+ port->pdat &= ~ctlr->pmdck;
+ port->pdir &= ~ctlr->pmdio;
+ nanodelay();
+
+ /* For read, clock in 18 bits, use 16 */
+ data = 0;
+ for(i=0; i<18; i++){
+ data <<= 1;
+ if(port->pdat & ctlr->pmdio)
+ data |= 1;
+ port->pdat |= ctlr->pmdck;
+ nanodelay();
+ port->pdat &= ~ctlr->pmdck;
+ nanodelay();
+ }
+ port->pdir |= (ctlr->pmdio|ctlr->pmdck);
+ nanodelay();
+ miiwriteloop(ctlr, port, 32, ~0);
+ splx(x);
+ return data & 0xffff;
+}
+
+static void
+fccltimer(Ureg*, Timer *t)
+{
+ Ether *ether;
+ Ctlr *ctlr;
+ MiiPhy *phy;
+ ulong gfmr;
+
+ ether = t->ta;
+ ctlr = ether->ctlr;
+ if(ctlr->mii == nil || ctlr->mii->curphy == nil)
+ return;
+ phy = ctlr->mii->curphy;
+ if(miistatus(ctlr->mii) < 0){
+ print("miistatus failed\n");
+ return;
+ }
+ if(phy->link == 0){
+ print("link lost\n");
+ return;
+ }
+ ether->mbps = phy->speed;
+
+ if(phy->fd != ctlr->duplex)
+ print("set duplex\n");
+ ilock(ctlr);
+ gfmr = ctlr->fcc->gfmr;
+ if(phy->fd != ctlr->duplex){
+ ctlr->fcc->gfmr &= ~(ENR|ENT);
+ if(phy->fd)
+ ctlr->fcc->fpsmr |= FDE | LPB; /* full duplex operation */
+ else
+ ctlr->fcc->fpsmr &= ~(FDE | LPB); /* half duplex operation */
+ ctlr->duplex = phy->fd;
+ }
+ ctlr->fcc->gfmr = gfmr;
+ iunlock(ctlr);
+}
diff --git a/sys/src/9/ppc/etherif.h b/sys/src/9/ppc/etherif.h
new file mode 100755
index 000000000..34fa2cc02
--- /dev/null
+++ b/sys/src/9/ppc/etherif.h
@@ -0,0 +1,35 @@
+enum {
+ MaxEther = 24,
+ Ntypes = 8,
+};
+
+typedef struct Ether Ether;
+struct Ether {
+ ISAConf; /* hardware info */
+
+ int ctlrno;
+ int tbdf; /* type+busno+devno+funcno */
+ int minmtu;
+ int maxmtu;
+ uchar ea[Eaddrlen];
+
+ void (*attach)(Ether*); /* filled in by reset routine */
+ void (*transmit)(Ether*);
+ void (*interrupt)(Ureg*, void*);
+ long (*ifstat)(Ether*, void*, long, ulong);
+ long (*ctl)(Ether*, void*, long); /* custom ctl messages */
+ void *ctlr;
+
+ Queue* oq;
+
+ Netif;
+};
+
+extern Block* etheriq(Ether*, Block*, int);
+extern void addethercard(char*, int(*)(Ether*));
+extern ulong ethercrc(uchar*, int);
+
+#define NEXT(x, l) (((x)+1)%(l))
+#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
diff --git a/sys/src/9/ppc/ethersaturn.c b/sys/src/9/ppc/ethersaturn.c
new file mode 100755
index 000000000..893835f87
--- /dev/null
+++ b/sys/src/9/ppc/ethersaturn.c
@@ -0,0 +1,229 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+#include "msaturn.h"
+
+#include "etherif.h"
+
+enum{
+ Etcr = Saturn + 0x0c00,
+ Etsr = Saturn + 0x0c02,
+ Ercr = Saturn + 0x0c04,
+ Ersr = Saturn + 0x0c06,
+ Eisr = Saturn + 0x0d04,
+ Eimr = Saturn + 0x0d06,
+ Emacaddr0 = Saturn + 0x0e02,
+ Miicr = Saturn + 0x0f02,
+ Miiwdr = Saturn + 0x0f04,
+ Miirdr = Saturn + 0x0f06,
+
+ Ethermem = 0xf2c00000,
+ Etherfsize = 0x2000,
+ Nrx = 14,
+ Ntx = 2, // Nrx + Ntx must be 16
+
+ Ersr_rxfpmask = 0xf,
+ Ersr_rxevent = RBIT(0, ushort),
+ Etcr_txfpmask = 0xf,
+ Ercr_rxenab = RBIT(0, ushort),
+ Ercr_auienab = RBIT(2, ushort),
+ Etcr_txstart = RBIT(1, ushort),
+ Etcr_retries = 0xf<<8,
+ Ei_txecall = RBIT(0, ushort),
+ Ei_txretry = RBIT(2, ushort),
+ Ei_txdefer = RBIT(3, ushort),
+ Ei_txcrs = RBIT(4, ushort),
+ Ei_txdone = RBIT(5, ushort),
+ Ei_rxcrcerr = RBIT(8, ushort),
+ Ei_rxdrib = RBIT(9, ushort),
+ Ei_rxdone = RBIT(10, ushort),
+ Ei_rxshort = RBIT(11, ushort),
+ Ei_rxlong = RBIT(12, ushort),
+
+ Miicr_regshift = 6,
+ Miicr_read = RBIT(10, ushort),
+ Miicr_preambledis = RBIT(12, ushort),
+ Miicr_accack = RBIT(14, ushort),
+ Miicr_accbsy = RBIT(15, ushort),
+};
+
+typedef struct {
+ Lock;
+ int txbusy;
+ int txempty;
+ int txfull;
+ int ntx; /* number of entries in transmit ring */
+ int rxlast;
+
+ int active;
+ ulong interrupts; /* statistics */
+ ulong overflows;
+} Ctlr;
+
+static ushort*etcr=(ushort*)Etcr;
+static ushort*etsr=(ushort*)Etsr;
+static ushort*ercr=(ushort*)Ercr;
+static ushort*ersr=(ushort*)Ersr;
+static ushort*eimr=(ushort*)Eimr;
+static ushort*eisr=(ushort*)Eisr;
+static ushort*miicr=(ushort*)Miicr;
+static ushort*miirdr=(ushort*)Miirdr;
+
+static void
+txfill(Ether*ether, Ctlr*ctlr)
+{
+ int len;
+ Block *b;
+ ushort*dst;
+
+ while(ctlr->ntx<Ntx){
+ if((b=qget(ether->oq)) == nil)
+ break;
+
+ len = BLEN(b);
+ dst = (ushort*)(Ethermem+(ctlr->txempty+Nrx)*Etherfsize);
+ *dst = len;
+ memmove(&dst[1], b->rp, len);
+ ctlr->ntx++;
+ ctlr->txempty++;
+ if(ctlr->txempty==Ntx)
+ ctlr->txempty = 0;
+ freeb(b);
+ }
+}
+
+static void
+txrestart(Ctlr*ctlr)
+{
+ if(ctlr->ntx==0 || ctlr->txbusy)
+ return;
+ ctlr->txbusy = 1;
+ *etcr = Etcr_txstart|Etcr_retries|(ctlr->txfull+Nrx);
+}
+
+static void interrupt(Ureg*, void*);
+
+static void
+transmit(Ether*ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(ctlr);
+ txfill(ether, ctlr);
+ txrestart(ctlr);
+ iunlock(ctlr);
+
+}
+
+static void
+interrupt(Ureg*, void*arg)
+{
+ Ctlr*ctlr;
+ Ether*ether = arg;
+ Etherpkt*pkt;
+ ushort ie;
+ int rx, len;
+ Block *b;
+
+ ctlr = ether->ctlr;
+ if(!ctlr->active)
+ return; /* not ours */
+ ctlr->interrupts++;
+
+ ilock(ctlr);
+ ie = *eisr;
+ *eisr = ie;
+ intack();
+
+ if(ie==0)
+ iprint("interrupt: no interrupt source?\n");
+
+ if(ie&Ei_txdone){
+ if((*etcr&Etcr_txstart)==0){
+ if(ctlr->txbusy){
+ ctlr->txbusy = 0;
+ ctlr->ntx--;
+ ctlr->txfull++;
+ if(ctlr->txfull==Ntx)
+ ctlr->txfull = 0;
+ }
+ txrestart(ctlr);
+ txfill(ether, ctlr);
+ txrestart(ctlr);
+ }
+ else
+ iprint("interrupt: bogus tx interrupt\n");
+ ie &= ~Ei_txdone;
+ }
+
+ if(ie&Ei_rxdone){
+ rx=*ersr&Ersr_rxfpmask;
+ while(ctlr->rxlast!=rx){
+
+ ctlr->rxlast++;
+ if(ctlr->rxlast >= Nrx)
+ ctlr->rxlast = 0;
+
+ pkt = (Etherpkt*)(Ethermem+ctlr->rxlast*Etherfsize);
+ len = *(ushort*)pkt;
+ if((b = iallocb(len+sizeof(ushort))) != nil){
+ memmove(b->wp, pkt, len+sizeof(ushort));
+ b->rp += sizeof(ushort);
+ b->wp = b->rp + len;
+ etheriq(ether, b, 1);
+ }else
+ ether->soverflows++;
+ rx=*ersr&Ersr_rxfpmask;
+ }
+ ie &= ~Ei_rxdone;
+ }
+
+ if(ie&Ei_txretry){
+ iprint("ethersaturn: txretry!\n");
+ ie &= ~Ei_txretry;
+ ctlr->txbusy = 0;
+ txrestart(ctlr);
+ }
+
+ ie &= ~Ei_txcrs;
+ if(ie)
+ iprint("interrupt: unhandled interrupts %.4uX\n", ie);
+ iunlock(ctlr);
+}
+
+static int
+reset(Ether* ether)
+{
+ Ctlr*ctlr;
+
+ *ercr = 0;
+ ctlr = malloc(sizeof(*ctlr));
+ memset(ctlr, 0, sizeof(*ctlr));
+ ctlr->active = 1;
+
+ ether->ctlr = ctlr;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->irq = Vecether;
+ ether->arg = ether;
+ memmove(ether->ea, (ushort*)Emacaddr0, Eaddrlen);
+
+ *ercr = Ercr_rxenab|Ercr_auienab|(Nrx-1);
+ *eimr = Ei_rxdone|Ei_txretry|Ei_txdone;
+
+ iprint("reset: ercr %.4uX\n", *ercr);
+ return 0;
+}
+
+void
+ethersaturnlink(void)
+{
+ addethercard("saturn", reset);
+}
+
diff --git a/sys/src/9/ppc/fns.h b/sys/src/9/ppc/fns.h
new file mode 100755
index 000000000..56b6aceab
--- /dev/null
+++ b/sys/src/9/ppc/fns.h
@@ -0,0 +1,124 @@
+#include "../port/portfns.h"
+
+int cistrcmp(char*, char*);
+int cistrncmp(char*, char*, int);
+void clockinit(void);
+void clockintr(Ureg*);
+void cpuidprint(void);
+void cycles(uvlong*);
+void dbgputc(int c);
+void dcacheenb(void);
+void dcflush(void*, ulong);
+void dczap(void*, ulong);
+void delay(int);
+void delayloopinit(void);
+void dmiss(void);
+void dumpregs(Ureg*);
+void eieio(void);
+void evenaddr(ulong);
+void faultpower(Ureg*, ulong addr, int read);
+void flashprogpower(int);
+void fpgareset(void);
+void fprestore(FPsave*);
+void fpsave(FPsave*);
+void fptrap(Ureg*);
+char* getconf(char*);
+ulong getdar(void);
+ulong getdcmp(void);
+ulong getdec(void);
+ulong getdmiss(void);
+ulong getdsisr(void);
+ulong gethash1(void);
+ulong gethash2(void);
+ulong gethid0(void);
+ulong gethid1(void);
+ulong geticmp(void);
+ulong geticmp(void);
+ulong getimiss(void);
+ulong getmsr(void);
+ulong getpvr(void);
+ulong getrpa(void);
+ulong getsdr1(void);
+ulong getsr(int);
+ulong getsrr1(void);
+void gotopc(ulong);
+void hwintrinit(void);
+void icacheenb(void);
+void icflush(void*, ulong);
+void idle(void);
+#define idlehands() /* nothing to do in the runproc */
+void imiss(void);
+int inb(int);
+void intr(Ureg*);
+void intrenable(int, void (*)(Ureg*, void*), void*, char*);
+void intrdisable(int, void (*)(Ureg*, void*), void*, char*);
+int ioalloc(int, int, int, char*);
+void iofree(int);
+int iprint(char*, ...);
+int isaconfig(char*, int, ISAConf*);
+void kfpinit(void);
+#define kmapinval()
+void links(void);
+void vectordisable(Vctl *);
+int vectorenable(Vctl *);
+void intack(void);
+void intend(int);
+int intvec(void);
+void l2disable(void);
+void mmuinit(void);
+void mmusweep(void*);
+int newmmupid(void);
+void outb(int, int);
+int pcicfgr16(Pcidev*, int);
+int pcicfgr32(Pcidev*, int);
+int pcicfgr8(Pcidev*, int);
+void pcicfgw16(Pcidev*, int, int);
+void pcicfgw32(Pcidev*, int, int);
+void pcicfgw8(Pcidev*, int, int);
+void procsave(Proc*);
+void procsetup(Proc*);
+void putdcmp(ulong);
+void putdec(ulong);
+void puthash1(ulong);
+void puthash2(ulong);
+void puthid0(ulong);
+void puthid2(ulong);
+void puticmp(ulong);
+void puticmp(ulong);
+void putmsr(ulong);
+void putrpa(ulong);
+void putsdr1(ulong);
+void putsdr1(ulong);
+void putsr(int, ulong);
+void putsrr1(ulong);
+void sethvec(int, void (*)(void));
+void setmvec(int, void (*)(void), void (*)(void));
+void sharedseginit(void);
+void console(void);
+void sync(void);
+int tas(void*);
+void timeradd(Timer *);
+void timerdel(Timer *);
+void timerinit(void);
+void tlbflush(ulong);
+void tlbflushall(void);
+void tlbld(ulong);
+void tlbli(ulong);
+void tlbvec(void);
+void touser(void*);
+void trapinit(void);
+void trapvec(void);
+#define userureg(ur) (((ur)->status & MSR_PR) != 0)
+#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
+#define KADDR(a) ((void*)((ulong)(a)|KZERO))
+#define PADDR(a) ((((ulong)(a)&0xf0000000)==0xf0000000)?(ulong)(a):((ulong)(a)&~KZERO))
+#define coherence() eieio()
+Pcidev* pcimatch(Pcidev*, int, int);
+Pcidev* pcimatchtbdf(int);
+void procrestore(Proc*);
+
+#ifdef ucuconf
+extern ulong getpll(void);
+extern ulong getl2cr(void);
+extern void putl2cr(ulong);
+#endif
diff --git a/sys/src/9/ppc/init9.s b/sys/src/9/ppc/init9.s
new file mode 100755
index 000000000..3445f26f8
--- /dev/null
+++ b/sys/src/9/ppc/init9.s
@@ -0,0 +1,29 @@
+/* this is the same as a c program:
+ * main(char *argv0){
+ * startboot(argv0, &argv0);
+ * }
+ *
+ * it is in asm because we need to set the SB before
+ * doing it and the only way to do this in c drags in
+ * too many other routines.
+ */
+
+TEXT _main(SB),$8
+
+ MOVW $setSB(SB), R2
+
+ /* make a frame */
+ SUB $16,R1
+
+ /* argv0 is already passed to us in R3 so it is already the first arg */
+
+ /* copy argv0 into the stack and push its address as the second arg */
+ MOVW R3,0x14(R1)
+ ADD $0x14,R1,R6
+ MOVW R6,0x8(R1)
+
+ BL startboot(SB)
+
+ /* should never get here */
+loop:
+ BR loop
diff --git a/sys/src/9/ppc/initcode b/sys/src/9/ppc/initcode
new file mode 100755
index 000000000..1d846abe5
--- /dev/null
+++ b/sys/src/9/ppc/initcode
@@ -0,0 +1,25 @@
+#include "/sys/src/libc/9syscall/sys.h"
+
+/*
+ * we pass in the argument of the exec parameters as 0(FP)
+ */
+
+TEXT main(SB),$8
+
+ MOVW $setSB(SB), R2
+ MOVW $boot(SB), R3
+ ADD $12, R1, R4 /* get a pointer to 0(FP) */
+ MOVW R3, 4(R1)
+ MOVW R4, 8(R1)
+ MOVW $EXEC, R3
+ SYSCALL
+
+ /* should never get here */
+loop:
+ BR loop
+
+DATA boot+0(SB)/5,$"/boot"
+DATA boot+5(SB)/5,$"/boot"
+DATA bootv+0(SB)/4,$boot+6(SB)
+GLOBL boot+0(SB),$11
+GLOBL bootv+0(SB),$8
diff --git a/sys/src/9/ppc/io.h b/sys/src/9/ppc/io.h
new file mode 100755
index 000000000..c14051b2e
--- /dev/null
+++ b/sys/src/9/ppc/io.h
@@ -0,0 +1,30 @@
+
+enum {
+ BusCBUS = 0, /* Corollary CBUS */
+ BusCBUSII, /* Corollary CBUS II */
+ BusEISA, /* Extended ISA */
+ BusFUTURE, /* IEEE Futurebus */
+ BusINTERN, /* Internal bus */
+ BusISA, /* Industry Standard Architecture */
+ BusMBI, /* Multibus I */
+ BusMBII, /* Multibus II */
+ BusMCA, /* Micro Channel Architecture */
+ BusMPI, /* MPI */
+ BusMPSA, /* MPSA */
+ BusNUBUS, /* Apple Macintosh NuBus */
+ BusPCI, /* Peripheral Component Interconnect */
+ BusPCMCIA, /* PC Memory Card International Association */
+ BusTC, /* DEC TurboChannel */
+ BusVL, /* VESA Local bus */
+ BusVME, /* VMEbus */
+ BusXPRESS, /* Express System Bus */
+ BusPPC /* Power PC internal bus */
+};
+
+#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
+#define BUSFNO(tbdf) (((tbdf)>>8)&0x07)
+#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F)
+#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF)
+#define BUSTYPE(tbdf) ((tbdf)>>24)
+#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00)
+#define BUSUNKNOWN (-1)
diff --git a/sys/src/9/ppc/l.s b/sys/src/9/ppc/l.s
new file mode 100755
index 000000000..878aa457d
--- /dev/null
+++ b/sys/src/9/ppc/l.s
@@ -0,0 +1,1037 @@
+#include "mem.h"
+
+/* use of SPRG registers in save/restore */
+#define SAVER0 SPRG0
+#define SAVER1 SPRG1
+#define SAVELR SPRG2
+#define SAVEXX SPRG3
+
+#ifdef ucuconf
+/* These only exist on the PPC 755: */
+#define SAVER4 SPRG4
+#define SAVER5 SPRG5
+#define SAVER6 SPRG6
+#define SAVER7 SPRG7
+#endif /* ucuconf */
+
+/* special instruction definitions */
+#define BDNZ BC 16, 0,
+#define BDNE BC 0, 2,
+#define MTCRF(r, crm) WORD $((31<<26)|((r)<<21)|(crm<<12)|(144<<1))
+
+/* #define TLBIA WORD $((31<<26)|(370<<1)) Not implemented on the 603e */
+#define TLBSYNC WORD $((31<<26)|(566<<1))
+#define TLBLI(n) WORD $((31<<26)|((n)<<11)|(1010<<1))
+#define TLBLD(n) WORD $((31<<26)|((n)<<11)|(978<<1))
+
+/* on some models mtmsr doesn't synchronise enough (eg, 603e) */
+#define MSRSYNC SYNC
+
+#define UREGSPACE (UREGSIZE+8)
+
+TEXT start(SB), $-4
+
+ /*
+ * setup MSR
+ * turn off interrupts
+ * use 0x000 as exception prefix
+ * enable machine check
+ */
+ MOVW MSR, R3
+ MOVW $(MSR_ME|MSR_EE|MSR_IP), R4
+ ANDN R4, R3
+ SYNC
+ MOVW R3, MSR
+ MSRSYNC
+
+ /* except during trap handling, R0 is zero from now on */
+ MOVW $0, R0
+
+ /* setup SB for pre mmu */
+ MOVW $setSB(SB), R2
+ MOVW $KZERO, R3
+ ANDN R3, R2
+
+ /* before this we're not running above KZERO */
+ BL mmuinit0(SB)
+ /* after this we are */
+
+#ifdef ucuconf
+ MOVW $0x2000000, R4 /* size */
+ MOVW $0, R3 /* base address */
+ RLWNM $0, R3, $~(CACHELINESZ-1), R5
+ CMP R4, $0
+ BLE _dcf1
+ SUB R5, R3
+ ADD R3, R4
+ ADD $(CACHELINESZ-1), R4
+ SRAW $CACHELINELOG, R4
+ MOVW R4, CTR
+_dcf0: DCBF (R5)
+ ADD $CACHELINESZ, R5
+ BDNZ _dcf0
+_dcf1:
+ SYNC
+
+ /* BAT0, 3 unused, copy of BAT2 */
+ MOVW SPR(IBATL(2)), R3
+ MOVW R3, SPR(IBATL(0))
+ MOVW SPR(IBATU(2)), R3
+ MOVW R3, SPR(IBATU(0))
+ MOVW SPR(DBATL(2)), R3
+ MOVW R3, SPR(DBATL(0))
+ MOVW SPR(DBATU(2)), R3
+ MOVW R3, SPR(DBATU(0))
+
+ MOVW SPR(IBATL(2)), R3
+ MOVW R3, SPR(IBATL(3))
+ MOVW SPR(IBATU(2)), R3
+ MOVW R3, SPR(IBATU(3))
+ MOVW SPR(DBATL(2)), R3
+ MOVW R3, SPR(DBATL(3))
+ MOVW SPR(DBATU(2)), R3
+ MOVW R3, SPR(DBATU(3))
+#endif /* ucuconf */
+
+ /* running with MMU on!! */
+
+ /* set R2 to correct value */
+ MOVW $setSB(SB), R2
+
+ /* set up Mach */
+ MOVW $MACHADDR, R(MACH)
+ ADD $(MACHSIZE-8), R(MACH), R1 /* set stack */
+
+ MOVW R0, R(USER) /* up-> set to zero */
+ MOVW R0, 0(R(MACH)) /* machno set to zero */
+
+ BL main(SB)
+
+ RETURN /* not reached */
+
+/*
+ * on return from this function we will be running in virtual mode.
+ * We set up the Block Address Translation (BAT) registers thus:
+ * 1) first 3 BATs are 256M blocks, starting from KZERO->0
+ * 2) remaining BAT maps last 256M directly
+ */
+TEXT mmuinit0(SB), $0
+ /* reset all the tlbs */
+ MOVW $64, R3
+ MOVW R3, CTR
+ MOVW $0, R4
+
+tlbloop:
+ TLBIE R4
+ SYNC
+ ADD $BIT(19), R4
+ BDNZ tlbloop
+ TLBSYNC
+
+#ifndef ucuconf
+ /* BATs 0 and 1 cover memory from 0x00000000 to 0x20000000 */
+
+ /* KZERO -> 0, IBAT and DBAT, 256 MB */
+ MOVW $(KZERO|(0x7ff<<2)|2), R3
+ MOVW $(PTEVALID|PTEWRITE), R4 /* PTEVALID => Cache coherency on */
+ MOVW R3, SPR(IBATU(0))
+ MOVW R4, SPR(IBATL(0))
+ MOVW R3, SPR(DBATU(0))
+ MOVW R4, SPR(DBATL(0))
+
+ /* KZERO+256M -> 256M, IBAT and DBAT, 256 MB */
+ ADD $(1<<28), R3
+ ADD $(1<<28), R4
+ MOVW R3, SPR(IBATU(1))
+ MOVW R4, SPR(IBATL(1))
+ MOVW R3, SPR(DBATU(1))
+ MOVW R4, SPR(DBATL(1))
+
+ /* FPGABASE -> FPGABASE, DBAT, 16 MB */
+ MOVW $(FPGABASE|(0x7f<<2)|2), R3
+ MOVW $(FPGABASE|PTEWRITE|PTEUNCACHED), R4 /* FPGA memory, don't cache */
+ MOVW R3, SPR(DBATU(2))
+ MOVW R4, SPR(DBATL(2))
+
+ /* IBAT 2 unused */
+ MOVW R0, SPR(IBATU(2))
+ MOVW R0, SPR(IBATL(2))
+
+ /* direct map last block, uncached, (not guarded, doesn't work for BAT), DBAT only */
+ MOVW $(INTMEM|(0x7ff<<2)|2), R3
+ MOVW $(INTMEM|PTEWRITE|PTEUNCACHED), R4 /* Don't set PTEVALID here */
+ MOVW R3, SPR(DBATU(3))
+ MOVW R4, SPR(DBATL(3))
+
+ /* IBAT 3 unused */
+ MOVW R0, SPR(IBATU(3))
+ MOVW R0, SPR(IBATL(3))
+#else /* ucuconf */
+ /* BAT 2 covers memory from 0x00000000 to 0x10000000 */
+
+ /* KZERO -> 0, IBAT2 and DBAT2, 256 MB */
+ MOVW $(KZERO|(0x7ff<<2)|2), R3
+ MOVW $(PTEVALID|PTEWRITE), R4 /* PTEVALID => Cache coherency on */
+ MOVW R3, SPR(DBATU(2))
+ MOVW R4, SPR(DBATL(2))
+ MOVW R3, SPR(IBATU(2))
+ MOVW R4, SPR(IBATL(2))
+#endif /* ucuconf */
+
+ /* enable MMU */
+ MOVW LR, R3
+ OR $KZERO, R3
+ MOVW R3, SPR(SRR0) /* Stored PC for RFI instruction */
+ MOVW MSR, R4
+ OR $(MSR_IR|MSR_DR|MSR_RI|MSR_FP), R4
+ MOVW R4, SPR(SRR1)
+ RFI /* resume in kernel mode in caller */
+
+ RETURN
+
+TEXT kfpinit(SB), $0
+ MOVFL $0, FPSCR(7)
+ MOVFL $0xD, FPSCR(6) /* VE, OE, ZE */
+ MOVFL $0, FPSCR(5)
+ MOVFL $0, FPSCR(3)
+ MOVFL $0, FPSCR(2)
+ MOVFL $0, FPSCR(1)
+ MOVFL $0, FPSCR(0)
+
+ FMOVD $4503601774854144.0, F27
+ FMOVD $0.5, F29
+ FSUB F29, F29, F28
+ FADD F29, F29, F30
+ FADD F30, F30, F31
+ FMOVD F28, F0
+ FMOVD F28, F1
+ FMOVD F28, F2
+ FMOVD F28, F3
+ FMOVD F28, F4
+ FMOVD F28, F5
+ FMOVD F28, F6
+ FMOVD F28, F7
+ FMOVD F28, F8
+ FMOVD F28, F9
+ FMOVD F28, F10
+ FMOVD F28, F11
+ FMOVD F28, F12
+ FMOVD F28, F13
+ FMOVD F28, F14
+ FMOVD F28, F15
+ FMOVD F28, F16
+ FMOVD F28, F17
+ FMOVD F28, F18
+ FMOVD F28, F19
+ FMOVD F28, F20
+ FMOVD F28, F21
+ FMOVD F28, F22
+ FMOVD F28, F23
+ FMOVD F28, F24
+ FMOVD F28, F25
+ FMOVD F28, F26
+ RETURN
+
+TEXT splhi(SB), $0
+ MOVW LR, R31
+ MOVW R31, 4(R(MACH)) /* save PC in m->splpc */
+ MOVW MSR, R3
+ RLWNM $0, R3, $~MSR_EE, R4
+ SYNC
+ MOVW R4, MSR
+ MSRSYNC
+ RETURN
+
+TEXT splx(SB), $0
+ /* fall though */
+
+TEXT splxpc(SB), $0
+ MOVW LR, R31
+ MOVW R31, 4(R(MACH)) /* save PC in m->splpc */
+ MOVW MSR, R4
+ RLWMI $0, R3, $MSR_EE, R4
+ SYNC
+ MOVW R4, MSR
+ MSRSYNC
+ RETURN
+
+TEXT spllo(SB), $0
+ MOVW MSR, R3
+ OR $MSR_EE, R3, R4
+ SYNC
+ MOVW R4, MSR
+ MSRSYNC
+ RETURN
+
+TEXT spldone(SB), $0
+ RETURN
+
+TEXT islo(SB), $0
+ MOVW MSR, R3
+ RLWNM $0, R3, $MSR_EE, R3
+ RETURN
+
+TEXT setlabel(SB), $-4
+ MOVW LR, R31
+ MOVW R1, 0(R3)
+ MOVW R31, 4(R3)
+ MOVW $0, R3
+ RETURN
+
+TEXT gotolabel(SB), $-4
+ MOVW 4(R3), R31
+ MOVW R31, LR
+ MOVW 0(R3), R1
+ MOVW $1, R3
+ RETURN
+
+TEXT touser(SB), $-4
+ MOVW $(UTZERO+32), R5 /* header appears in text */
+ MOVW $(MSR_EE|MSR_PR|MSR_IR|MSR_DR|MSR_RI), R4
+ MOVW R4, SPR(SRR1)
+ MOVW R3, R1
+ MOVW R5, SPR(SRR0)
+ RFI
+
+TEXT dczap(SB), $-4 /* dczap(virtaddr, count) */
+ MOVW n+4(FP), R4
+ RLWNM $0, R3, $~(CACHELINESZ-1), R5
+ CMP R4, $0
+ BLE dcz1
+ SUB R5, R3
+ ADD R3, R4
+ ADD $(CACHELINESZ-1), R4
+ SRAW $CACHELINELOG, R4
+ MOVW R4, CTR
+dcz0:
+ DCBI (R5)
+ ADD $CACHELINESZ, R5
+ BDNZ dcz0
+dcz1:
+ SYNC
+ RETURN
+
+TEXT dcflush(SB), $-4 /* dcflush(virtaddr, count) */
+ MOVW n+4(FP), R4
+ RLWNM $0, R3, $~(CACHELINESZ-1), R5
+ CMP R4, $0
+ BLE dcf1
+ SUB R5, R3
+ ADD R3, R4
+ ADD $(CACHELINESZ-1), R4
+ SRAW $CACHELINELOG, R4
+ MOVW R4, CTR
+dcf0: DCBST (R5)
+ ADD $CACHELINESZ, R5
+ BDNZ dcf0
+dcf1:
+ SYNC
+ RETURN
+
+TEXT icflush(SB), $-4 /* icflush(virtaddr, count) */
+ MOVW n+4(FP), R4
+ RLWNM $0, R3, $~(CACHELINESZ-1), R5
+ CMP R4, $0
+ BLE icf1
+ SUB R5, R3
+ ADD R3, R4
+ ADD $(CACHELINESZ-1), R4
+ SRAW $CACHELINELOG, R4
+ MOVW R4, CTR
+icf0: ICBI (R5) /* invalidate the instruction cache */
+ ADD $CACHELINESZ, R5
+ BDNZ icf0
+ ISYNC
+icf1:
+ RETURN
+
+TEXT tas(SB), $0
+ MOVW R3, R4
+ MOVW $0xdead, R5
+tas1:
+ DCBF (R4) /* fix for 603x bug */
+ SYNC
+ LWAR (R4), R3
+ CMP R3, $0
+ BNE tas0
+ STWCCC R5, (R4)
+ BNE tas1
+ EIEIO
+tas0:
+ SYNC
+ RETURN
+
+TEXT _xinc(SB), $0 /* void _xinc(long *); */
+ MOVW R3, R4
+xincloop:
+ DCBF (R4) /* fix for 603x bug */
+ LWAR (R4), R3
+ ADD $1, R3
+ STWCCC R3, (R4)
+ BNE xincloop
+ RETURN
+
+TEXT _xdec(SB), $0 /* long _xdec(long *); */
+ MOVW R3, R4
+xdecloop:
+ DCBF (R4) /* fix for 603x bug */
+ LWAR (R4), R3
+ ADD $-1, R3
+ STWCCC R3, (R4)
+ BNE xdecloop
+ RETURN
+
+TEXT tlbflushall(SB), $0
+ MOVW $TLBENTRIES, R3
+ MOVW R3, CTR
+ MOVW $0, R4
+ ISYNC
+tlbflushall0:
+ TLBIE R4
+ SYNC
+ ADD $BIT(19), R4
+ BDNZ tlbflushall0
+ TLBSYNC
+ RETURN
+
+TEXT tlbflush(SB), $0
+ ISYNC
+ TLBIE R3
+ SYNC
+ TLBSYNC
+ RETURN
+
+TEXT gotopc(SB), $0
+ MOVW R3, CTR
+ MOVW LR, R31 /* for trace back */
+ BR (CTR)
+
+/* On an imiss, we get here. If we can resolve it, we do.
+ * Otherwise take the real trap. The code at the vector is
+ * MOVW R0, SPR(SAVER0) No point to this, of course
+ * MOVW LR, R0
+ * MOVW R0, SPR(SAVELR)
+ * BL imiss(SB) or dmiss, as the case may be
+ * BL tlbvec(SB)
+ */
+TEXT imiss(SB), $-4
+ /* Statistics */
+ MOVW $MACHPADDR, R1
+ MOVW 0xc(R1), R3 /* count m->tlbfault */
+ ADD $1, R3
+ MOVW R3, 0xc(R1)
+ MOVW 0x10(R1), R3 /* count m->imiss */
+ ADD $1, R3
+ MOVW R3, 0x10(R1)
+
+ /* Real work */
+ MOVW SPR(HASH1), R1 /* (phys) pointer into the hash table */
+ ADD $BY2PTEG, R1, R2 /* end pointer */
+ MOVW SPR(iCMP), R3 /* pattern to look for */
+imiss1:
+ MOVW (R1), R0
+ CMP R3, R0
+ BEQ imiss2 /* found the entry */
+ ADD $8, R1
+ CMP R1, R2 /* test end of loop */
+ BNE imiss1 /* Loop */
+ /* Failed to find an entry; take the full trap */
+ MOVW SPR(SRR1), R1
+ MTCRF(1, 0x80) /* restore CR0 bits (they're auto saved in SRR1) */
+ RETURN
+imiss2:
+ /* Found the entry */
+ MOVW 4(R1), R2 /* Phys addr */
+ MOVW R2, SPR(RPA)
+ MOVW SPR(IMISS), R3
+ TLBLI(3)
+
+ /* Restore Registers */
+ MOVW SPR(SRR1), R1 /* Restore the CR0 field of the CR register from SRR1 */
+ MTCRF(1, 0x80)
+ MOVW SPR(SAVELR), R0
+ MOVW R0, LR
+ RFI
+
+/* On a data load or store miss, we get here. If we can resolve it, we do.
+ * Otherwise take the real trap
+ */
+TEXT dmiss(SB), $-4
+ /* Statistics */
+ MOVW $MACHPADDR, R1
+ MOVW 0xc(R1), R3 /* count m->tlbfault */
+ ADD $1, R3
+ MOVW R3, 0xc(R1)
+ MOVW 0x14(R1), R3 /* count m->dmiss */
+ ADD $1, R3
+ MOVW R3, 0x14(R1)
+ /* Real work */
+ MOVW SPR(HASH1), R1 /* (phys) pointer into the hash table */
+ ADD $BY2PTEG, R1, R2 /* end pointer */
+ MOVW SPR(DCMP), R3 /* pattern to look for */
+dmiss1:
+ MOVW (R1), R0
+ CMP R3, R0
+ BEQ dmiss2 /* found the entry */
+ ADD $8, R1
+ CMP R1, R2 /* test end of loop */
+ BNE dmiss1 /* Loop */
+ /* Failed to find an entry; take the full trap */
+ MOVW SPR(SRR1), R1
+ MTCRF(1, 0x80) /* restore CR0 bits (they're auto saved in SRR1) */
+ RETURN
+dmiss2:
+ /* Found the entry */
+ MOVW 4(R1), R2 /* Phys addr */
+ MOVW R2, SPR(RPA)
+ MOVW SPR(DMISS), R3
+ TLBLD(3)
+ /* Restore Registers */
+ MOVW SPR(SRR1), R1 /* Restore the CR0 field of the CR register from SRR1 */
+ MTCRF(1, 0x80)
+ MOVW SPR(SAVELR), R0
+ MOVW R0, LR
+ RFI
+
+/*
+ * When a trap sets the TGPR bit (TLB miss traps do this),
+ * registers get remapped: R0-R31 are temporarily inaccessible,
+ * and Temporary Registers TR0-TR3 are mapped onto R0-R3.
+ * While this bit is set, R4-R31 cannot be used.
+ * The code at the vector has executed this code before
+ * coming to tlbvec:
+ * MOVW R0, SPR(SAVER0) No point to this, of course
+ * MOVW LR, R0
+ * MOVW R0, SPR(SAVELR)
+ * BL tlbvec(SB)
+ * SAVER0 can be reused. We're not interested in the value of TR0
+ */
+TEXT tlbvec(SB), $-4
+ MOVW MSR, R1
+ RLWNM $0, R1, $~MSR_TGPR, R1 /* Clear the dreaded TGPR bit in the MSR */
+ SYNC
+ MOVW R1, MSR
+ MSRSYNC
+ /* Now the GPRs are what they're supposed to be, save R0 again */
+ MOVW R0, SPR(SAVER0)
+ /* Fall through to trapvec */
+
+/*
+ * traps force memory mapping off.
+ * the following code has been executed at the exception
+ * vector location
+ * MOVW R0, SPR(SAVER0)
+ * MOVW LR, R0
+ * MOVW R0, SPR(SAVELR)
+ * bl trapvec(SB)
+ *
+ */
+TEXT trapvec(SB), $-4
+ MOVW LR, R0
+ MOVW R1, SPR(SAVER1)
+ MOVW R0, SPR(SAVEXX) /* vector */
+
+ /* did we come from user space */
+ MOVW SPR(SRR1), R0
+ MOVW CR, R1
+ MOVW R0, CR
+ BC 4, 17, ktrap
+
+ /* switch to kernel stack */
+ MOVW R1, CR
+ MOVW $MACHPADDR, R1 /* PADDR(m->) */
+ MOVW 8(R1), R1 /* m->proc */
+ RLWNM $0, R1, $~KZERO, R1 /* PADDR(m->proc) */
+ MOVW 8(R1), R1 /* m->proc->kstack */
+ RLWNM $0, R1, $~KZERO, R1 /* PADDR(m->proc->kstack) */
+ ADD $(KSTACK-UREGSIZE), R1 /* make room on stack */
+
+ BL saveureg(SB)
+ BL trap(SB)
+ BR restoreureg
+
+ktrap:
+ MOVW R1, CR
+ MOVW SPR(SAVER1), R1
+ RLWNM $0, R1, $~KZERO, R1 /* set stack pointer */
+ SUB $UREGSPACE, R1
+
+ BL saveureg(SB) /* addressed relative to PC */
+ BL trap(SB)
+ BR restoreureg
+
+/*
+ * enter with stack set and mapped.
+ * on return, SB (R2) has been set, and R3 has the Ureg*,
+ * the MMU has been re-enabled, kernel text and PC are in KSEG,
+ * R(MACH) has been set, and R0 contains 0.
+ *
+ */
+TEXT saveureg(SB), $-4
+/*
+ * save state
+ */
+ MOVMW R2, 48(R1) /* save r2 .. r31 in 48(R1) .. 164(R1) */
+ MOVW $MACHPADDR, R(MACH) /* PADDR(m->) */
+ MOVW 8(R(MACH)), R(USER) /* up-> */
+ MOVW $MACHADDR, R(MACH) /* m-> */
+ MOVW SPR(SAVER1), R4
+ MOVW R4, 44(R1)
+ MOVW SPR(SAVER0), R5
+ MOVW R5, 40(R1)
+ MOVW CTR, R6
+ MOVW R6, 36(R1)
+ MOVW XER, R4
+ MOVW R4, 32(R1)
+ MOVW CR, R5
+ MOVW R5, 28(R1)
+ MOVW SPR(SAVELR), R6 /* LR */
+ MOVW R6, 24(R1)
+ /* pad at 20(R1) */
+ MOVW SPR(SRR0), R0
+ MOVW R0, 16(R1) /* old PC */
+ MOVW SPR(SRR1), R0
+ MOVW R0, 12(R1) /* old status */
+ MOVW SPR(SAVEXX), R0
+ MOVW R0, 8(R1) /* cause/vector */
+ MOVW SPR(DCMP), R0
+ MOVW R0, (160+8)(R1)
+ MOVW SPR(iCMP), R0
+ MOVW R0, (164+8)(R1)
+ MOVW SPR(DMISS), R0
+ MOVW R0, (168+8)(R1)
+ MOVW SPR(IMISS), R0
+ MOVW R0, (172+8)(R1)
+ MOVW SPR(HASH1), R0
+ MOVW R0, (176+8)(R1)
+ MOVW SPR(HASH2), R0
+ MOVW R0, (180+8)(R1)
+ MOVW SPR(DAR), R0
+ MOVW R0, (184+8)(R1)
+ MOVW SPR(DSISR), R0
+ MOVW R0, (188+8)(R1)
+ ADD $8, R1, R3 /* Ureg* */
+ OR $KZERO, R3 /* fix ureg */
+ STWCCC R3, (R1) /* break any pending reservations */
+ MOVW $0, R0 /* compiler/linker expect R0 to be zero */
+ MOVW $setSB(SB), R2 /* SB register */
+
+ MOVW MSR, R5
+ OR $(MSR_IR|MSR_DR|MSR_FP|MSR_RI), R5 /* enable MMU */
+ MOVW R5, SPR(SRR1)
+ MOVW LR, R31
+ OR $KZERO, R31 /* return PC in KSEG0 */
+ MOVW R31, SPR(SRR0)
+ OR $KZERO, R1 /* fix stack pointer */
+ RFI /* returns to trap handler */
+
+/*
+ * restore state from Ureg and return from trap/interrupt
+ */
+TEXT forkret(SB), $0
+ BR restoreureg
+
+restoreureg:
+ MOVMW 48(R1), R2 /* restore r2 through r31 */
+ /* defer R1 */
+ MOVW 40(R1), R0
+ MOVW R0, SPR(SAVER0) /* resave saved R0 */
+ MOVW 36(R1), R0
+ MOVW R0, CTR
+ MOVW 32(R1), R0
+ MOVW R0, XER
+ MOVW 28(R1), R0
+ MOVW R0, CR /* Condition register*/
+ MOVW 24(R1), R0
+ MOVW R0, LR
+ /* pad, skip */
+ MOVW 16(R1), R0
+ MOVW R0, SPR(SRR0) /* old PC */
+ MOVW 12(R1), R0
+ MOVW R0, SPR(SRR1) /* old MSR */
+ /* cause, skip */
+ MOVW 44(R1), R1 /* old SP */
+ MOVW SPR(SAVER0), R0
+ RFI
+
+TEXT getpvr(SB), $0
+ MOVW SPR(PVR), R3
+ RETURN
+
+TEXT getdec(SB), $0
+ MOVW SPR(DEC), R3
+ RETURN
+
+TEXT putdec(SB), $0
+ MOVW R3, SPR(DEC)
+ RETURN
+
+TEXT getdar(SB), $0
+ MOVW SPR(DAR), R3
+ RETURN
+
+TEXT getdsisr(SB), $0
+ MOVW SPR(DSISR), R3
+ RETURN
+
+TEXT getmsr(SB), $0
+ MOVW MSR, R3
+ RETURN
+
+TEXT putmsr(SB), $0
+ MOVW R3, MSR
+ MSRSYNC
+ RETURN
+
+TEXT putsdr1(SB), $0
+ SYNC
+ MOVW R3, SPR(SDR1)
+ ISYNC
+ RETURN
+
+TEXT putsr(SB), $0
+ MOVW 4(FP), R4
+ SYNC
+ MOVW R4, SEG(R3)
+ MSRSYNC
+ RETURN
+
+TEXT getsr(SB), $0
+ MOVW SEG(R3), R3
+ RETURN
+
+TEXT gethid0(SB), $0
+ MOVW SPR(HID0), R3
+ RETURN
+
+TEXT puthid0(SB), $0
+ SYNC
+ ISYNC
+ MOVW R3, SPR(HID0)
+ SYNC
+ RETURN
+
+TEXT gethid1(SB), $0
+ MOVW SPR(HID1), R3
+ RETURN
+
+TEXT gethid2(SB), $0
+ MOVW SPR(HID2), R3
+ RETURN
+
+TEXT puthid2(SB), $0
+ MOVW R3, SPR(HID2)
+ RETURN
+
+TEXT eieio(SB), $0
+ EIEIO
+ RETURN
+
+TEXT sync(SB), $0
+ SYNC
+ RETURN
+
+/* Power PC 603e specials */
+TEXT getimiss(SB), $0
+ MOVW SPR(IMISS), R3
+ RETURN
+
+TEXT geticmp(SB), $0
+ MOVW SPR(iCMP), R3
+ RETURN
+
+TEXT puticmp(SB), $0
+ MOVW R3, SPR(iCMP)
+ RETURN
+
+TEXT getdmiss(SB), $0
+ MOVW SPR(DMISS), R3
+ RETURN
+
+TEXT getdcmp(SB), $0
+ MOVW SPR(DCMP), R3
+ RETURN
+
+TEXT putdcmp(SB), $0
+ MOVW R3, SPR(DCMP)
+ RETURN
+
+TEXT getsdr1(SB), $0
+ MOVW SPR(SDR1), R3
+ RETURN
+
+TEXT gethash1(SB), $0
+ MOVW SPR(HASH1), R3
+ RETURN
+
+TEXT puthash1(SB), $0
+ MOVW R3, SPR(HASH1)
+ RETURN
+
+TEXT gethash2(SB), $0
+ MOVW SPR(HASH2), R3
+ RETURN
+
+TEXT puthash2(SB), $0
+ MOVW R3, SPR(HASH2)
+ RETURN
+
+TEXT getrpa(SB), $0
+ MOVW SPR(RPA), R3
+ RETURN
+
+TEXT putrpa(SB), $0
+ MOVW R3, SPR(RPA)
+ RETURN
+
+TEXT tlbli(SB), $0
+ TLBLI(3)
+ ISYNC
+ RETURN
+
+TEXT tlbld(SB), $0
+ SYNC
+ TLBLD(3)
+ ISYNC
+ RETURN
+
+TEXT getsrr1(SB), $0
+ MOVW SPR(SRR1), R3
+ RETURN
+
+TEXT putsrr1(SB), $0
+ MOVW R3, SPR(SRR1)
+ RETURN
+
+TEXT fpsave(SB), $0
+ FMOVD F0, (0*8)(R3)
+ FMOVD F1, (1*8)(R3)
+ FMOVD F2, (2*8)(R3)
+ FMOVD F3, (3*8)(R3)
+ FMOVD F4, (4*8)(R3)
+ FMOVD F5, (5*8)(R3)
+ FMOVD F6, (6*8)(R3)
+ FMOVD F7, (7*8)(R3)
+ FMOVD F8, (8*8)(R3)
+ FMOVD F9, (9*8)(R3)
+ FMOVD F10, (10*8)(R3)
+ FMOVD F11, (11*8)(R3)
+ FMOVD F12, (12*8)(R3)
+ FMOVD F13, (13*8)(R3)
+ FMOVD F14, (14*8)(R3)
+ FMOVD F15, (15*8)(R3)
+ FMOVD F16, (16*8)(R3)
+ FMOVD F17, (17*8)(R3)
+ FMOVD F18, (18*8)(R3)
+ FMOVD F19, (19*8)(R3)
+ FMOVD F20, (20*8)(R3)
+ FMOVD F21, (21*8)(R3)
+ FMOVD F22, (22*8)(R3)
+ FMOVD F23, (23*8)(R3)
+ FMOVD F24, (24*8)(R3)
+ FMOVD F25, (25*8)(R3)
+ FMOVD F26, (26*8)(R3)
+ FMOVD F27, (27*8)(R3)
+ FMOVD F28, (28*8)(R3)
+ FMOVD F29, (29*8)(R3)
+ FMOVD F30, (30*8)(R3)
+ FMOVD F31, (31*8)(R3)
+ MOVFL FPSCR, F0
+ FMOVD F0, (32*8)(R3)
+ RETURN
+
+TEXT fprestore(SB), $0
+ FMOVD (32*8)(R3), F0
+ MOVFL F0, FPSCR
+ FMOVD (0*8)(R3), F0
+ FMOVD (1*8)(R3), F1
+ FMOVD (2*8)(R3), F2
+ FMOVD (3*8)(R3), F3
+ FMOVD (4*8)(R3), F4
+ FMOVD (5*8)(R3), F5
+ FMOVD (6*8)(R3), F6
+ FMOVD (7*8)(R3), F7
+ FMOVD (8*8)(R3), F8
+ FMOVD (9*8)(R3), F9
+ FMOVD (10*8)(R3), F10
+ FMOVD (11*8)(R3), F11
+ FMOVD (12*8)(R3), F12
+ FMOVD (13*8)(R3), F13
+ FMOVD (14*8)(R3), F14
+ FMOVD (15*8)(R3), F15
+ FMOVD (16*8)(R3), F16
+ FMOVD (17*8)(R3), F17
+ FMOVD (18*8)(R3), F18
+ FMOVD (19*8)(R3), F19
+ FMOVD (20*8)(R3), F20
+ FMOVD (21*8)(R3), F21
+ FMOVD (22*8)(R3), F22
+ FMOVD (23*8)(R3), F23
+ FMOVD (24*8)(R3), F24
+ FMOVD (25*8)(R3), F25
+ FMOVD (26*8)(R3), F26
+ FMOVD (27*8)(R3), F27
+ FMOVD (28*8)(R3), F28
+ FMOVD (29*8)(R3), F29
+ FMOVD (30*8)(R3), F30
+ FMOVD (31*8)(R3), F31
+ RETURN
+
+TEXT dcacheenb(SB), $0
+ SYNC
+ MOVW SPR(HID0), R4 /* Get HID0 and clear unwanted bits */
+ RLWNM $0, R4, $~(HID_DLOCK), R4
+ MOVW $(HID_DCFI|HID_DCE), R5
+ OR R4, R5
+ MOVW $HID_DCE, R3
+ OR R4, R3
+ SYNC
+// MOVW R5, SPR(HID0) /* Cache enable and flash invalidate */
+ MOVW R3, SPR(HID0) /* Cache enable */
+ SYNC
+ RETURN
+
+TEXT icacheenb(SB), $0
+ SYNC
+ MOVW SPR(HID0), R4 /* Get HID0 and clear unwanted bits */
+ RLWNM $0, R4, $~(HID_ILOCK), R4
+ MOVW $(HID_ICFI|HID_ICE), R5
+ OR R4, R5
+ MOVW $HID_ICE, R3
+ OR R4, R3
+ SYNC
+ MOVW R5, SPR(HID0) /* Cache enable and flash invalidate */
+ MOVW R3, SPR(HID0) /* Cache enable */
+ SYNC
+ RETURN
+
+#ifdef ucuconf
+TEXT getpll(SB), $0
+ MOVW SPR(1009), R3
+ ISYNC
+ RETURN
+
+TEXT getl2pm(SB), $0
+ MOVW SPR(1016), R3
+ RETURN
+
+TEXT getl2cr(SB), $0
+ MOVW SPR(1017), R3
+ RETURN
+
+TEXT putl2cr(SB), $0
+ MOVW R3, SPR(1017)
+ RETURN
+
+TEXT dcachedis(SB), $0
+ SYNC
+/* MOVW SPR(HID0), R4
+ RLWNM $0, R4, $~(HID_DCE), R4
+ MOVW R4, SPR(HID0) /* L1 Cache disable */
+
+ MOVW SPR(1017), R4
+ RLWNM $0, R4, $~(0x80000000), R4
+ MOVW R4, SPR(1017) /* L2 Cache disable */
+
+ SYNC
+ RETURN
+
+TEXT l2disable(SB), $0
+ SYNC
+ MOVW SPR(1017), R4
+ RLWNM $0, R4, $~(0x80000000), R4
+ MOVW R4, SPR(1017) /* L2 Cache disable */
+ SYNC
+ RETURN
+
+TEXT getbats(SB), $0
+ MOVW SPR(DBATU(0)), R4
+ MOVW R4, 0(R3)
+ MOVW SPR(DBATL(0)), R4
+ MOVW R4, 4(R3)
+ MOVW SPR(IBATU(0)), R4
+ MOVW R4, 8(R3)
+ MOVW SPR(IBATL(0)), R4
+ MOVW R4, 12(R3)
+ MOVW SPR(DBATU(1)), R4
+ MOVW R4, 16(R3)
+ MOVW SPR(DBATL(1)), R4
+ MOVW R4, 20(R3)
+ MOVW SPR(IBATU(1)), R4
+ MOVW R4, 24(R3)
+ MOVW SPR(IBATL(1)), R4
+ MOVW R4, 28(R3)
+ MOVW SPR(DBATU(2)), R4
+ MOVW R4, 32(R3)
+ MOVW SPR(DBATL(2)), R4
+ MOVW R4, 36(R3)
+ MOVW SPR(IBATU(2)), R4
+ MOVW R4, 40(R3)
+ MOVW SPR(IBATL(2)), R4
+ MOVW R4, 44(R3)
+ MOVW SPR(DBATU(3)), R4
+ MOVW R4, 48(R3)
+ MOVW SPR(DBATL(3)), R4
+ MOVW R4, 52(R3)
+ MOVW SPR(IBATU(3)), R4
+ MOVW R4, 56(R3)
+ MOVW SPR(IBATL(3)), R4
+ MOVW R4, 60(R3)
+ RETURN
+
+TEXT setdbat0(SB), $0
+ MOVW 0(R3), R4
+ MOVW R4, SPR(DBATU(0))
+ MOVW 4(R3), R4
+ MOVW R4, SPR(DBATL(0))
+ RETURN
+#endif /* ucuconf */
+
+TEXT mmudisable(SB), $0
+ /* disable MMU */
+ MOVW LR, R4
+ MOVW $KZERO, R5
+ ANDN R5, R4
+ MOVW R4, SPR(SRR0) /* Stored PC for RFI instruction */
+
+ MOVW MSR, R4
+ MOVW $(MSR_IR|MSR_DR|MSR_RI|MSR_FP), R5
+ ANDN R5, R4
+ MOVW R4, SPR(SRR1)
+
+ MOVW SPR(HID0), R4 /* Get HID0 and clear unwanted bits */
+ MOVW $(HID_ICE|HID_DCE), R5
+ ANDN R5, R4
+ MOVW R4, SPR(HID0) /* Cache disable */
+ RFI /* resume caller with MMU off */
+ RETURN
+
+TEXT kreboot(SB), $0
+ BL mmudisable(SB)
+ MOVW R3, LR
+ RETURN
+
+TEXT mul64fract(SB), $0
+ MOVW a0+8(FP), R9
+ MOVW a1+4(FP), R10
+ MOVW b0+16(FP), R4
+ MOVW b1+12(FP), R5
+
+ MULLW R10, R5, R13 /* c2 = lo(a1*b1) */
+
+ MULLW R10, R4, R12 /* c1 = lo(a1*b0) */
+ MULHWU R10, R4, R7 /* hi(a1*b0) */
+ ADD R7, R13 /* c2 += hi(a1*b0) */
+
+ MULLW R9, R5, R6 /* lo(a0*b1) */
+ MULHWU R9, R5, R7 /* hi(a0*b1) */
+ ADDC R6, R12 /* c1 += lo(a0*b1) */
+ ADDE R7, R13 /* c2 += hi(a0*b1) + carry */
+
+ MULHWU R9, R4, R7 /* hi(a0*b0) */
+ ADDC R7, R12 /* c1 += hi(a0*b0) */
+ ADDE R0, R13 /* c2 += carry */
+
+ MOVW R12, 4(R3)
+ MOVW R13, 0(R3)
+ RETURN
diff --git a/sys/src/9/ppc/lblast.h b/sys/src/9/ppc/lblast.h
new file mode 100755
index 000000000..2b3bf4833
--- /dev/null
+++ b/sys/src/9/ppc/lblast.h
@@ -0,0 +1,66 @@
+/*
+ * on return from this function we will be running in virtual mode.
+ * We set up the Block Address Translation (BAT) registers thus:
+ * 1) first 3 BATs are 256M blocks, starting from KZERO->0
+ * 2) remaining BAT maps last 256M directly
+ */
+TEXT mmuinit0(SB), $0
+ /* reset all the tlbs */
+ MOVW $64, R3
+ MOVW R3, CTR
+ MOVW $0, R4
+tlbloop:
+ TLBIE R4
+ SYNC
+ ADD $BIT(19), R4
+ BDNZ tlbloop
+ TLBSYNC
+
+ /* BATs 0 and 1 cover memory from 0x00000000 to 0x20000000 */
+
+ /* KZERO -> 0, IBAT and DBAT, 256 MB */
+ MOVW $(KZERO|(0x7ff<<2)|2), R3
+ MOVW $(PTEVALID|PTEWRITE), R4 /* PTEVALID => Cache coherency on */
+ MOVW R3, SPR(IBATU(0))
+ MOVW R4, SPR(IBATL(0))
+ MOVW R3, SPR(DBATU(0))
+ MOVW R4, SPR(DBATL(0))
+
+ /* KZERO+256M -> 256M, IBAT and DBAT, 256 MB */
+ ADD $(1<<28), R3
+ ADD $(1<<28), R4
+ MOVW R3, SPR(IBATU(1))
+ MOVW R4, SPR(IBATL(1))
+ MOVW R3, SPR(DBATU(1))
+ MOVW R4, SPR(DBATL(1))
+
+ /* FPGABASE -> FPGABASE, DBAT, 16 MB */
+ MOVW $(FPGABASE|(0x7f<<2)|2), R3
+ MOVW $(FPGABASE|PTEWRITE|PTEUNCACHED), R4 /* FPGA memory, don't cache */
+ MOVW R3, SPR(DBATU(2))
+ MOVW R4, SPR(DBATL(2))
+
+ /* IBAT 2 unused */
+ MOVW R0, SPR(IBATU(2))
+ MOVW R0, SPR(IBATL(2))
+
+ /* direct map last block, uncached, (not guarded, doesn't work for BAT), DBAT only */
+ MOVW $(INTMEM|(0x7ff<<2)|2), R3
+ MOVW $(INTMEM|PTEWRITE|PTEUNCACHED), R4 /* Don't set PTEVALID here */
+ MOVW R3, SPR(DBATU(3))
+ MOVW R4, SPR(DBATL(3))
+
+ /* IBAT 3 unused */
+ MOVW R0, SPR(IBATU(3))
+ MOVW R0, SPR(IBATL(3))
+
+ /* enable MMU */
+ MOVW LR, R3
+ OR $KZERO, R3
+ MOVW R3, SPR(SRR0) /* Stored PC for RFI instruction */
+ MOVW MSR, R4
+ OR $(MSR_IR|MSR_DR|MSR_RI|MSR_FP), R4
+ MOVW R4, SPR(SRR1)
+ RFI /* resume in kernel mode in caller */
+
+ RETURN
diff --git a/sys/src/9/ppc/lucu.h b/sys/src/9/ppc/lucu.h
new file mode 100755
index 000000000..e8b040e7e
--- /dev/null
+++ b/sys/src/9/ppc/lucu.h
@@ -0,0 +1,39 @@
+/*
+ * on return from this function we will be running in virtual mode.
+ * We set up the Block Address Translation (BAT) registers thus:
+ * 1) first 3 BATs are 256M blocks, starting from KZERO->0
+ * 2) remaining BAT maps last 256M directly
+ */
+TEXT mmuinit0(SB), $0
+ /* reset all the tlbs */
+ MOVW $64, R3
+ MOVW R3, CTR
+ MOVW $0, R4
+
+tlbloop:
+ TLBIE R4
+ SYNC
+ ADD $BIT(19), R4
+ BDNZ tlbloop
+ TLBSYNC
+
+ /* BATs 0 and 1 cover memory from 0x00000000 to 0x20000000 */
+
+ /* KZERO -> 0, IBAT2 and DBAT2, 256 MB */
+ MOVW $(KZERO|(0x7ff<<2)|2), R3
+ MOVW $(PTEVALID|PTEWRITE), R4 /* PTEVALID => Cache coherency on */
+ MOVW R3, SPR(DBATU(2))
+ MOVW R4, SPR(DBATL(2))
+ MOVW R3, SPR(IBATU(2))
+ MOVW R4, SPR(IBATL(2))
+
+ /* enable MMU */
+ MOVW LR, R3
+ OR $KZERO, R3
+ MOVW R3, SPR(SRR0) /* Stored PC for RFI instruction */
+ MOVW MSR, R4
+ OR $(MSR_IR|MSR_DR|MSR_RI|MSR_FP), R4
+ MOVW R4, SPR(SRR1)
+ RFI /* resume in kernel mode in caller */
+
+ RETURN
diff --git a/sys/src/9/ppc/m8260.c b/sys/src/9/ppc/m8260.c
new file mode 100755
index 000000000..4f84ec135
--- /dev/null
+++ b/sys/src/9/ppc/m8260.c
@@ -0,0 +1,661 @@
+/*
+ * 8260 specific stuff:
+ * Interrupt handling
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "io.h"
+#include "fns.h"
+#include "m8260.h"
+
+enum {
+ Pin4 = BIT(4),
+};
+
+static union {
+ struct {
+ ulong hi;
+ ulong lo;
+ };
+ uvlong val;
+} ticks;
+
+struct {
+ ulong hi;
+ ulong lo;
+} vec2mask[64] = {
+[0] = {0, 0 }, /* Error, No interrupt */
+[1] = {0, BIT(16) }, /* I2C */
+[2] = {0, BIT(17) }, /* SPI */
+[3] = {0, BIT(18) }, /* Risc Timers */
+[4] = {0, BIT(19) }, /* SMC1 */
+[5] = {0, BIT(20) }, /* SMC2 */
+[6] = {0, BIT(21) }, /* IDMA1 */
+[7] = {0, BIT(22) }, /* IDMA2 */
+[8] = {0, BIT(23) }, /* IDMA3 */
+[9] = {0, BIT(24) }, /* IDMA4 */
+[10] = {0, BIT(25) }, /* SDMA */
+[11] = {0, 0 }, /* Reserved */
+[12] = {0, BIT(27) }, /* Timer1 */
+[13] = {0, BIT(28) }, /* Timer2 */
+[14] = {0, BIT(29) }, /* Timer3 */
+[15] = {0, BIT(30) }, /* Timer4 */
+
+[16] = {BIT(29), 0 }, /* TMCNT */
+[17] = {BIT(30), 0 }, /* PIT */
+[18] = {0, 0 }, /* Reserved */
+[19] = {BIT(17), 0 }, /* IRQ1 */
+[20] = {BIT(18), 0 }, /* IRQ2 */
+[21] = {BIT(19), 0 }, /* IRQ3 */
+[22] = {BIT(20), 0 }, /* IRQ4 */
+[23] = {BIT(21), 0 }, /* IRQ5 */
+[24] = {BIT(22), 0 }, /* IRQ6 */
+[25] = {BIT(23), 0 }, /* IRQ7 */
+[26] = {0, 0 }, /* Reserved */
+[27] = {0, 0 }, /* Reserved */
+[28] = {0, 0 }, /* Reserved */
+[29] = {0, 0 }, /* Reserved */
+[30] = {0, 0 }, /* Reserved */
+[31] = {0, 0 }, /* Reserved */
+
+[32] = {0, BIT(0) }, /* FCC1 */
+[33] = {0, BIT(1) }, /* FCC2 */
+[34] = {0, BIT(2) }, /* FCC3 */
+[35] = {0, 0 }, /* Reserved */
+[36] = {0, BIT(4) }, /* MCC1 */
+[37] = {0, BIT(5) }, /* MCC2 */
+[38] = {0, 0 }, /* Reserved */
+[39] = {0, 0 }, /* Reserved */
+[40] = {0, BIT(8) }, /* SCC1 */
+[41] = {0, BIT(9) }, /* SCC2 */
+[42] = {0, BIT(10) }, /* SCC3 */
+[43] = {0, BIT(11) }, /* SCC4 */
+[44] = {0, 0 }, /* Reserved */
+[45] = {0, 0 }, /* Reserved */
+[46] = {0, 0 }, /* Reserved */
+[47] = {0, 0 }, /* Reserved */
+
+[48] = {BIT(15), 0 }, /* PC15 */
+[49] = {BIT(14), 0 }, /* PC14 */
+[50] = {BIT(13), 0 }, /* PC13 */
+[51] = {BIT(12), 0 }, /* PC12 */
+[52] = {BIT(11), 0 }, /* PC11 */
+[53] = {BIT(10), 0 }, /* PC10 */
+[54] = {BIT(9), 0 }, /* PC9 */
+[55] = {BIT(8), 0 }, /* PC8 */
+[56] = {BIT(7), 0 }, /* PC7 */
+[57] = {BIT(6), 0 }, /* PC6 */
+[58] = {BIT(5), 0 }, /* PC5 */
+[59] = {BIT(4), 0 }, /* PC4 */
+[60] = {BIT(3), 0 }, /* PC3 */
+[61] = {BIT(2), 0 }, /* PC2 */
+[62] = {BIT(1), 0 }, /* PC1 */
+[63] = {BIT(0), 0 }, /* PC0 */
+};
+
+/* Blast memory layout:
+ * CS0: FE000000 -> FFFFFFFF (Flash)
+ * CS1: FC000000 -> FCFFFFFF (DSP hpi)
+ * CS2: 00000000 -> 03FFFFFF (60x sdram)
+ * CS3: 04000000 -> 04FFFFFF (FPGA)
+ * CS4: 05000000 -> 06FFFFFF (local bus sdram)
+ * CS5: 07000000 -> 0700FFFF (eeprom - not populated)
+ * CS6: E0000000 -> E0FFFFFF (FPGA - 64bits)
+ *
+ * Main Board memory layout:
+ * CS0: FE000000 -> FEFFFFFF (16 M FLASH)
+ * CS1: FC000000 -> FCFFFFFF (16 M DSP1)
+ * CS2: 00000000 -> 03FFFFFF (64 M SDRAM)
+ * CS3: 04000000 -> 04FFFFFF (16M DSP2)
+ * CS4: 05000000 -> 06FFFFFF (32 M Local SDRAM)
+ * CS5: 07000000 -> 0700FFFF (eeprom - not populated)
+ * CS6: unused
+ * CS7: E0000000 -> E0FFFFFF (16 M FPGA)
+ */
+
+IMM* iomem = (IMM*)IOMEM;
+
+static Lock cpmlock;
+
+void
+machinit(void)
+{
+ ulong scmr;
+ int pllmf;
+ extern char* plan9inistr;
+
+ memset(m, 0, sizeof(*m));
+ m->cputype = getpvr()>>16; /* pvr = 0x00810101 for the 8260 */
+ m->imap = (Imap*)INTMEM;
+
+ m->loopconst = 1096;
+
+ /* Make sure Ethernet is disabled (boot code may have buffers allocated anywhere in memory) */
+ iomem->fcc[0].gfmr &= ~(BIT(27)|BIT(26));
+ iomem->fcc[1].gfmr &= ~(BIT(27)|BIT(26));
+ iomem->fcc[2].gfmr &= ~(BIT(27)|BIT(26));
+
+ /* Flashed CS configuration is wrong for DSP2. It's set to 64 bits, should be 16 */
+ iomem->bank[3].br = 0x04001001; /* Set 16-bit port */
+
+ /*
+ * FPGA is capable of doing 64-bit transfers. To use these, set br to 0xe0000001.
+ * Currently we use 32-bit transfers, because the 8260 does not easily do 64-bit operations.
+ */
+ iomem->bank[6].br = 0xe0001801;
+ iomem->bank[6].or = 0xff000830; /* Was 0xff000816 */
+
+/*
+ * All systems with rev. A.1 (0K26N) silicon had serious problems when doing
+ * DMA transfers with data cache enabled (usually this shows when using
+ * one of the FCC's with some traffic on the ethernet). Allocating FCC buffer
+ * descriptors in main memory instead of DP ram solves this problem.
+ */
+
+ /* Guess at clocks based upon the PLL configuration from the
+ * power-on reset.
+ */
+ scmr = iomem->scmr;
+
+ /* The EST8260 is typically run using either 33 or 66 MHz
+ * external clock. The configuration byte in the Flash will
+ * tell us which is configured. The blast appears to be slightly
+ * overclocked at 72 MHz (if set to 66 MHz, the uart runs too fast)
+ */
+
+ m->clkin = CLKIN;
+
+ pllmf = scmr & 0xfff;
+
+ /* This is arithmetic from the 8260 manual, section 9.4.1. */
+
+ /* Collect the bits from the scmr.
+ */
+ m->vco_out = m->clkin * (pllmf + 1);
+ if (scmr & BIT(19)) /* plldf (division factor is 1 or 2) */
+ m->vco_out >>= 1;
+
+ m->cpmhz = m->vco_out >> 1; /* cpm hz is half of vco_out */
+ m->brghz = m->vco_out >> (2 * ((iomem->sccr & 0x3) + 1));
+ m->bushz = m->vco_out / (((scmr & 0x00f00000) >> 20) + 1);
+
+ /* Serial init sets BRG clock....I don't know how to compute
+ * core clock from core configuration, but I think I know the
+ * mapping....
+ */
+ switch(scmr >> (31-7)){
+ case 0x0a:
+ m->cpuhz = m->clkin * 2;
+ break;
+ case 0x0b:
+ m->cpuhz = (m->clkin >> 1) * 5;
+ break;
+ default:
+ case 0x0d:
+ m->cpuhz = m->clkin * 3;
+ break;
+ case 0x14:
+ m->cpuhz = (m->clkin >> 1) * 7;
+ break;
+ case 0x1c:
+ m->cpuhz = m->clkin * 4;
+ break;
+ }
+
+ m->cyclefreq = m->bushz / 4;
+
+/* Expect:
+ intfreq 133 m->cpuhz
+ busfreq 33 m->bushz
+ cpmfreq 99 m->cpmhz
+ brgfreq 49.5 m->brghz
+ vco 198
+*/
+
+ active.machs = 1;
+ active.exiting = 0;
+
+ putmsr(getmsr() | MSR_ME);
+
+ /*
+ * turn on data cache before instruction cache;
+ * for some reason which I don't understand,
+ * you can't turn on both caches at once
+ */
+ icacheenb();
+ dcacheenb();
+
+ kfpinit();
+
+ /* Plan9.ini location in flash is FLASHMEM+PLAN9INI
+ * if PLAN9INI == ~0, it's not stored in flash or there is no flash
+ * if *cp == 0xff, flash memory is not initialized
+ */
+ if (PLAN9INI == ~0 || *(plan9inistr = (char*)(FLASHMEM+PLAN9INI)) == 0xff){
+ /* No plan9.ini in flash */
+ plan9inistr =
+ "console=0\n"
+ "ether0=type=fcc port=0 ea=00601d051dd8\n"
+ "flash0=mem=0xfe000000\n"
+ "fs=135.104.9.42\n"
+ "auth=135.104.9.7\n"
+ "authdom=cs.bell-labs.com\n"
+ "sys=blast\n"
+ "ntp=135.104.9.52\n";
+ }
+}
+
+void
+fpgareset(void)
+{
+ print("fpga reset\n");
+
+ ioplock();
+
+ iomem->port[1].pdat &= ~Pin4; /* force reset signal to 0 */
+ delay(100);
+ iomem->port[1].pdat |= Pin4; /* force reset signal back to one */
+
+ iopunlock();
+}
+
+void
+hwintrinit(void)
+{
+ iomem->sicr = 2 << 8;
+ /* Write ones into most bits of the interrupt pending registers to clear interrupts */
+ iomem->sipnr_h = ~7;
+ iomem->sipnr_h = ~1;
+ /* Clear the interrupt masks, thereby disabling all interrupts */
+ iomem->simr_h = 0;
+ iomem->simr_l = 0;
+
+ iomem->sypcr &= ~2; /* cause a machine check interrupt on memory timeout */
+
+ /* Initialize fpga reset pin */
+ iomem->port[1].pdir |= Pin4; /* 1 is an output */
+ iomem->port[1].ppar &= ~Pin4;
+ iomem->port[1].pdat |= Pin4; /* force reset signal back to one */
+}
+
+int
+vectorenable(Vctl *v)
+{
+ ulong hi, lo;
+
+ if (v->irq & ~0x3f){
+ print("m8260enable: interrupt vector %d out of range\n", v->irq);
+ return -1;
+ }
+ hi = vec2mask[v->irq].hi;
+ lo = vec2mask[v->irq].lo;
+ if (hi == 0 && lo == 0){
+ print("m8260enable: nonexistent vector %d\n", v->irq);
+ return -1;
+ }
+ ioplock();
+ /* Clear the interrupt before enabling */
+ iomem->sipnr_h |= hi;
+ iomem->sipnr_l |= lo;
+ /* Enable */
+ iomem->simr_h |= hi;
+ iomem->simr_l |= lo;
+ iopunlock();
+ return v->irq;
+}
+
+void
+vectordisable(Vctl *v)
+{
+ ulong hi, lo;
+
+ if (v->irq & ~0x3f){
+ print("m8260disable: interrupt vector %d out of range\n", v->irq);
+ return;
+ }
+ hi = vec2mask[v->irq].hi;
+ lo = vec2mask[v->irq].lo;
+ if (hi == 0 && lo == 0){
+ print("m8260disable: nonexistent vector %d\n", v->irq);
+ return;
+ }
+ ioplock();
+ iomem->simr_h &= ~hi;
+ iomem->simr_l &= ~lo;
+ iopunlock();
+}
+
+int
+intvec(void)
+{
+ return iomem->sivec >> 26;
+}
+
+void
+intend(int vno)
+{
+ /* Clear interrupt */
+ ioplock();
+ iomem->sipnr_h |= vec2mask[vno].hi;
+ iomem->sipnr_l |= vec2mask[vno].lo;
+ iopunlock();
+}
+
+int
+m8260eoi(int)
+{
+ return 0;
+}
+
+int
+m8260isr(int)
+{
+ return 0;
+}
+
+void
+flashprogpower(int)
+{
+}
+
+enum {
+ TgcrCas = 0x80,
+ TgcrGm = 0x08,
+ TgcrStp = 0x2, /* There are two of these, timer-2 bits are bits << 4 */
+ TgcrRst = 0x1,
+
+ TmrIclkCasc = 0x00<<1,
+ TmrIclkIntclock = 0x01<<1,
+ TmrIclkIntclock16 = 0x02<<1,
+ TmrIclkTin = 0x03<<1,
+ TmrCERising = 0x1 << 6,
+ TmrCEFalling = 0x2 << 6,
+ TmrCEAny = 0x3 << 6,
+ TmrFrr = SBIT(12),
+ TmrOri = SBIT(11),
+
+ TerRef = SBIT(14),
+ TerCap = SBIT(15),
+};
+
+uvlong
+fastticks(uvlong *hz)
+{
+ ulong count;
+ static Lock fasttickslock;
+
+ if (hz)
+ *hz = m->clkin>>1;
+ ilock(&fasttickslock);
+ count = iomem->tcnl1;
+ if (count < ticks.lo)
+ ticks.hi += 1;
+ ticks.lo = count;
+ iunlock(&fasttickslock);
+ return ticks.val;
+}
+
+void
+timerset(uvlong next)
+{
+ long offset;
+ uvlong now;
+ static int cnt;
+
+ now = fastticks(nil);
+ offset = next - now;
+ if (offset < 2500)
+ next = now + 2500; /* 10000 instructions */
+ else if (offset > m->clkin / HZ){
+ print("too far in the future: offset %llux, now %llux\n", next, now);
+ next = now + m->clkin / HZ;
+ }
+ iomem->trrl1 = next;
+}
+
+void
+m8260timerintr(Ureg *u, void*)
+{
+ iomem->ter2 |= TerRef | TerCap; /* Clear interrupt */
+ timerintr(u, 0);
+}
+
+void
+timerinit(void)
+{
+
+ iomem->tgcr1 = TgcrCas | TgcrGm; /* cascade timers 1 & 2, normal gate mode */
+ iomem->tcnl1 = 0;
+ iomem->trrl1 = m->clkin / HZ; /* first capture in 1/HZ seconds */
+ iomem->tmr1 = TmrIclkCasc;
+ iomem->tmr2 = TmrIclkIntclock | TmrOri;
+ intrenable(13, m8260timerintr, nil, "timer"); /* Timer 2 interrupt is on 13 */
+ iomem->tgcr1 |= TgcrRst << 4;
+}
+
+static void
+addseg(char *name, ulong start, ulong length)
+{
+ Physseg segbuf;
+
+ memset(&segbuf, 0, sizeof(segbuf));
+ segbuf.attr = SG_PHYSICAL;
+ kstrdup(&segbuf.name, name);
+ segbuf.pa = start;
+ segbuf.size = length;
+ if (addphysseg(&segbuf) == -1) {
+ print("addphysseg: %s\n", name);
+ return;
+ }
+}
+
+void
+sharedseginit(void)
+{
+ int i, j;
+ ulong base, size;
+ char name[16], *a, *b, *s;
+ static char *segnames[] = {
+ "fpga",
+ "dsp",
+ };
+
+ for (j = 0; j < nelem(segnames); j++){
+ for (i = 0; i < 8; i++){
+ snprint(name, sizeof name, "%s%d", segnames[j], i);
+ if ((a = getconf(name)) == nil)
+ continue;
+ if ((b = strstr(a, "mem=")) == nil){
+ print("blastseginit: %s: no base\n", name);
+ continue;
+ }
+ b += 4;
+ base = strtoul(b, nil, 0);
+ if (base == 0){
+ print("blastseginit: %s: bad base: %s\n", name, b);
+ continue;
+ }
+ if ((s = strstr(a, "size=")) == nil){
+ print("blastseginit: %s: no size\n", name);
+ continue;
+ }
+ s += 5;
+ size = strtoul(s, nil, 0);
+ if (size == 0){
+ print("blastseginit: %s: bad size: %s\n", name, s);
+ continue;
+ }
+ addseg(name, base, size);
+ }
+ }
+}
+
+void
+cpmop(int op, int dev, int mcn)
+{
+ ioplock();
+ eieio();
+ while(iomem->cpcr & 0x10000)
+ eieio();
+ iomem->cpcr = dev<<(31-10) | mcn<<(31-25) | op | 0x10000;
+ eieio();
+ while(iomem->cpcr & 0x10000)
+ eieio();
+ iopunlock();
+}
+
+/*
+ * connect SCCx clocks in NSMI mode (x=1 for USB)
+ */
+void
+sccnmsi(int x, int rcs, int tcs)
+{
+ ulong v;
+ int sh;
+
+ sh = (x-1)*8; /* each SCCx field in sicr is 8 bits */
+ v = (((rcs&7)<<3) | (tcs&7)) << sh;
+ iomem->sicr = (iomem->sicr & ~(0xFF<<sh)) | v;
+}
+
+/*
+ * lock the shared IO memory and return a reference to it
+ */
+void
+ioplock(void)
+{
+ ilock(&cpmlock);
+}
+
+/*
+ * release the lock on the shared IO memory
+ */
+void
+iopunlock(void)
+{
+ eieio();
+ iunlock(&cpmlock);
+}
+
+BD*
+bdalloc(int n)
+{
+ static BD *palloc = ((Imap*)INTMEM)->bd;
+ BD *p;
+
+ p = palloc;
+ if (palloc > ((Imap*)INTMEM)->bd + nelem(((Imap*)INTMEM)->bd)){
+ print("bdalloc: out of BDs\n");
+ return nil;
+ }
+ palloc += n;
+ return p;
+}
+
+/*
+ * Initialise receive and transmit buffer rings. Only used for FCC
+ * Ethernet now.
+ *
+ * Ioringinit will allocate the buffer descriptors in normal memory
+ * and NOT in Dual-Ported Ram, as prescribed by the MPC8260
+ * PowerQUICC II manual (Section 28.6). When they are allocated
+ * in DPram and the Dcache is enabled, the processor will hang.
+ * This has been observed for the FCCs, it may or may not be true
+ * for SCCs or DMA.
+ * The SMC Uart buffer descriptors are not allocated here; (1) they
+ * can ONLY be in DPram and (2) they are not configured as a ring.
+ */
+int
+ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
+{
+ int i, x;
+ static uchar *dpmallocaddr;
+ static uchar *dpmallocend;
+
+ if (dpmallocaddr == nil){
+ dpmallocaddr = m->imap->dpram1;
+ dpmallocend = dpmallocaddr + sizeof(m->imap->dpram1);
+ }
+ /* the ring entries must be aligned on sizeof(BD) boundaries */
+ r->nrdre = nrdre;
+ if(r->rdr == nil)
+ r->rdr = xspanalloc(nrdre*sizeof(BD), 0, 8);
+ if(r->rdr == nil)
+ return -1;
+ if(r->rrb == nil && bufsize){
+ r->rrb = xspanalloc(nrdre*bufsize, 0, CACHELINESZ);
+ if(r->rrb == nil)
+ return -1;
+ }
+ x = bufsize ? PADDR(r->rrb) : 0;
+ for(i = 0; i < nrdre; i++){
+ r->rdr[i].length = 0;
+ r->rdr[i].addr = x;
+ r->rdr[i].status = BDEmpty|BDInt;
+ x += bufsize;
+ }
+ r->rdr[i-1].status |= BDWrap;
+ r->rdrx = 0;
+
+ r->ntdre = ntdre;
+ if(r->tdr == nil)
+ r->tdr = xspanalloc(ntdre*sizeof(BD), 0, 8);
+ if(r->txb == nil)
+ r->txb = xspanalloc(ntdre*sizeof(Block*), 0, CACHELINESZ);
+ if(r->tdr == nil || r->txb == nil)
+ return -1;
+ for(i = 0; i < ntdre; i++){
+ r->txb[i] = nil;
+ r->tdr[i].addr = 0;
+ r->tdr[i].length = 0;
+ r->tdr[i].status = 0;
+ }
+ r->tdr[i-1].status |= BDWrap;
+ r->tdrh = 0;
+ r->tdri = 0;
+ r->ntq = 0;
+ return 0;
+}
+
+void
+trapinit(void)
+{
+ int i;
+
+ /*
+ * set all exceptions to trap
+ */
+ for(i = 0x0; i < 0x2000; i += 0x100)
+ sethvec(i, trapvec);
+
+ setmvec(0x1000, imiss, tlbvec);
+ setmvec(0x1100, dmiss, tlbvec);
+ setmvec(0x1200, dmiss, tlbvec);
+
+/* Useful for avoiding assembler miss handling:
+ sethvec(0x1000, tlbvec);
+ sethvec(0x1100, tlbvec);
+ sethvec(0x1200, tlbvec);
+/* */
+ dcflush(KADDR(0), 0x2000);
+ icflush(KADDR(0), 0x2000);
+
+ putmsr(getmsr() & ~MSR_IP);
+}
+
+void
+reboot(void*, void*, ulong)
+{
+ ulong *p;
+ int x;
+
+ p = (ulong*)0x90000000;
+ x = splhi();
+ iomem->sypcr |= 0xc0;
+ print("iomem->sypcr = 0x%lux\n", iomem->sypcr);
+ *p = 0;
+ print("still alive\n");
+ splx(x);
+}
diff --git a/sys/src/9/ppc/m8260.h b/sys/src/9/ppc/m8260.h
new file mode 100755
index 000000000..9aa0ffb82
--- /dev/null
+++ b/sys/src/9/ppc/m8260.h
@@ -0,0 +1,658 @@
+
+typedef struct BD BD;
+struct BD {
+ ushort status;
+ ushort length;
+ ulong addr;
+};
+
+enum{
+ BDEmpty= SBIT(0),
+ BDReady= SBIT(0),
+ BDWrap= SBIT(2),
+ BDInt= SBIT(3),
+ BDLast= SBIT(4),
+ BDFirst= SBIT(5),
+};
+
+typedef struct Ring Ring;
+
+struct Ring {
+ BD* rdr; /* receive descriptor ring */
+ void* rrb; /* receive ring buffers */
+ int rdrx; /* index into rdr */
+ int nrdre; /* length of rdr */
+
+ BD* tdr; /* transmit descriptor ring */
+ void** txb; /* corresponding transmit ring buffers */
+ int tdrh; /* host index into tdr */
+ int tdri; /* interface index into tdr */
+ int ntdre; /* length of tdr */
+ int ntq; /* pending transmit requests */
+};
+
+int ioringinit(Ring*, int, int, int);
+
+/*
+ * MCC parameters
+ */
+typedef struct MCCparam MCCparam;
+struct MCCparam {
+/*0x00*/ ulong mccbase;
+/*0x04*/ ushort mccstate;
+/*0x06*/ ushort mrblr;
+/*0x08*/ ushort grfthr;
+/*0x0a*/ ushort grfcnt;
+/*0x0c*/ ulong rinttmp;
+/*0x10*/ ulong data0;
+/*0x14*/ ulong data1;
+/*0x18*/ ulong tintbase;
+/*0x1c*/ ulong tintptr;
+/*0x20*/ ulong tinttmp;
+/*0x24*/ ushort sctpbase;
+/*0x26*/ ushort Rsvd26;
+/*0x28*/ ulong cmask32;
+/*0x2c*/ ushort xtrabase;
+/*0x2e*/ ushort cmask16;
+/*0x30*/ ulong rinttmp[4];
+/*0x40*/ struct {
+ ulong base;
+ ulong ptr;
+ } rint[4];
+/*0x60*/ ulong tstmp;
+/*0x64*/
+};
+/*
+ * IO controller parameters
+ */
+typedef struct IOCparam IOCparam;
+struct IOCparam {
+/*0x00*/ ushort rbase;
+/*0x02*/ ushort tbase;
+/*0x04*/ uchar rfcr;
+/*0x05*/ uchar tfcr;
+/*0x06*/ ushort mrblr;
+/*0x08*/ ulong rstate;
+/*0x0c*/ ulong rxidp;
+/*0x10*/ ushort rbptr;
+/*0x12*/ ushort rxibc;
+/*0x14*/ ulong rxtemp;
+/*0x18*/ ulong tstate;
+/*0x1c*/ ulong txidp;
+/*0x20*/ ushort tbptr;
+/*0x22*/ ushort txibc;
+/*0x24*/ ulong txtemp;
+/*0x28*/
+};
+
+typedef struct SCCparam SCCparam;
+struct SCCparam {
+ IOCparam;
+ ulong rcrc;
+ ulong tcrc;
+};
+
+typedef struct FCCparam FCCparam;
+struct FCCparam {
+/*0x00*/ ushort riptr;
+/*0x02*/ ushort tiptr;
+/*0x04*/ ushort Rsvd04;
+/*0x06*/ ushort mrblr;
+/*0x08*/ ulong rstate;
+/*0x0c*/ ulong rbase;
+/*0x10*/ ushort rbdstat;
+/*0x12*/ ushort rbdlen;
+/*0x14*/ char* rdptr;
+/*0x18*/ ulong tstate;
+/*0x1c*/ ulong tbase;
+/*0x20*/ ushort tbdstat;
+/*0x22*/ ushort tbdlen;
+/*0x24*/ ulong tdptr;
+/*0x28*/ ulong rbptr;
+/*0x2c*/ ulong tbptr;
+/*0x30*/ ulong rcrc;
+/*0x34*/ ulong Rsvd34;
+/*0x38*/ ulong tcrc;
+/*0x3c*/
+};
+
+typedef struct SCC SCC;
+struct SCC {
+ ulong gsmrl;
+ ulong gsmrh;
+ ushort psmr;
+ uchar rsvscc0[2];
+ ushort todr;
+ ushort dsr;
+ ushort scce;
+ uchar rsvscc1[2];
+ ushort sccm;
+ uchar rsvscc2;
+ uchar sccs;
+ ushort irmode;
+ ushort irsip;
+ uchar rsvscc3[4]; /* BUG */
+};
+
+typedef struct FCC FCC;
+struct FCC {
+/*0x00*/ ulong gfmr; /* general mode register 28.2/28-3 */
+/*0x04*/ ulong fpsmr; /* protocol-specific mode reg. 29.13.2(ATM) 30.18.1(Ether) */
+/*0x08*/ ushort ftodr; /* transmit on demand register 28.5/28-7 */
+/*0x0A*/ ushort Rsvd0A;
+/*0x0C*/ ushort fdsr; /* data synchronization register 28.4/28-7 */
+/*0x0E*/ ushort Rsvd0E;
+/*0x10*/ ushort fcce; /* event register 29.13.3 (ATM), 30.18.2 (Ethernet) */
+/*0x12*/ ushort Rsvd12;
+/*0x14*/ ushort fccm; /* mask register */
+/*0x16*/ ushort Rsvd16;
+/*0x18*/ uchar fccs; /* status register 8 bits 31.10 (HDLC) */
+/*0x19*/ uchar Rsvd19[3];
+/*0x1C*/ uchar ftirrphy[4]; /* transmit internal rate registers for PHY0DH3 29.13.4/29-88 (ATM) */
+/*0x20*/
+};
+
+typedef struct SMC SMC;
+struct SMC {
+/*0x0*/ ushort pad1;
+/*0x2*/ ushort smcmr;
+/*0x4*/ ushort pad2;
+/*0x6*/ uchar smce;
+/*0x7*/ uchar pad3[3];
+/*0xa*/ uchar smcm;
+/*0xb*/ uchar pad4[5];
+/*0x10*/
+};
+
+typedef struct SPI SPI;
+struct SPI {
+ ushort spmode;
+ uchar res1[4];
+ uchar spie;
+ uchar res2[3];
+ uchar spim;
+ uchar res3[2];
+ uchar spcom;
+ uchar res4[2];
+};
+
+typedef struct Bankmap Bankmap;
+struct Bankmap {
+/*0*/ ulong br; /* Base register bank 32 bits 10.3.1/10-14 */
+/*4*/ ulong or; /* Option register bank 32 bits 10.3.2/10-16 */
+/*8*/
+};
+
+typedef struct Port Port;
+struct Port {
+/*0x00*/ ulong pdir; /* Port A data direction register 32 bits 35.2.3/35-3 */
+/*0x04*/ ulong ppar; /* Port Apin assignment register 32 bits 35.2.4/35-4 */
+/*0x08*/ ulong psor; /* Port A special options register 32 bits 35.2.5/35-4 */
+/*0x0C*/ ulong podr; /* Port Aopen drain register 32 bits 35.2.1/35-2 */
+/*0x10*/ ulong pdat; /* Port A data register 32 bits 35.2.2/35-2 */
+/*0x14*/ uchar Rsvd14[12];
+/*0x20*/
+};
+
+typedef struct IDMA IDMA;
+struct IDMA {
+/*0x0*/ uchar idsr; /* IDMA event register 8 bits 18.8.4/18-22 */
+/*0x1*/ uchar Rsvd1[3];
+/*0x4*/ uchar idmr; /* IDMA mask register 8 bits 18.8.4/18-22 */
+/*0x5*/ uchar Rsvd5[3];
+/*0x8*/
+};
+
+typedef struct PrmSCC PrmSCC;
+struct PrmSCC {
+ uchar sccbytes[0x100];
+};
+
+typedef struct PrmFCC PrmFCC;
+struct PrmFCC {
+ uchar fccbytes[0x100];
+};
+
+typedef struct Bases Bases;
+struct Bases {
+/*0x00*/ uchar mcc[0x80];
+/*0x80*/ uchar Rsvd80[0x60];
+/*0xe0*/ uchar risctimers[0x10];
+/*0xf0*/ ushort revnum;
+/*0xf2*/ uchar Rsvdf2[6];
+/*0xf8*/ ulong rand;
+/*0xfc*/ ushort smcbase;
+#define i2cbase smcbase
+/*0xfe*/ ushort idmabase;
+/*0x100*/
+};
+
+typedef struct Uartsmc Uartsmc;
+struct Uartsmc {
+/*0x00*/ IOCparam;
+/*0x28*/ ushort maxidl;
+/*0x2a*/ ushort idlc;
+/*0x2c*/ ushort brkln;
+/*0x2e*/ ushort brkec;
+/*0x30*/ ushort brkcr;
+/*0x32*/ ushort r_mask;
+/*0x34*/ ulong sdminternal;
+/*0x38*/ uchar Rsvd38[8];
+/*0x40*/
+};
+
+typedef struct SI SI;
+struct SI {
+/*0x11B20*/ ushort siamr; /* SI TDMA1 mode register 16 bits 14.5.2/14-17 */
+/*0x11B22*/ ushort sibmr; /* SI TDMB1 mode register 16 bits */
+/*0x11B24*/ ushort sicmr; /* SI TDMC1 mode register 16 bits */
+/*0x11B26*/ ushort sidmr; /* SI TDMD1 mode register 16 bits */
+/*0x11B28*/ uchar sigmr; /* SI global mode register 8 bits 14.5.1/14-17 */
+/*0x11B29*/ uchar Rsvd11B29;
+/*0x11B2A*/ ushort sicmdr; /* SI command register 8 bits 14.5.4/14-24 */
+/*0x11B2C*/ ushort sistr; /* SI status register 8 bits 14.5.5/14-25 */
+/*0x11B2E*/ ushort sirsr; /* SI RAM shadow address register 16 bits 14.5.3/14-23 */
+};
+
+typedef struct IMM IMM;
+struct IMM {
+/* General SIU */
+/*0x10000*/ ulong siumcr; /* SIU module configuration register 32 bits 4.3.2.6/4-31 */
+/*0x10004*/ ulong sypcr; /* System protection control register 32 bits 4.3.2.8/4-35 */
+/*0x10008*/ uchar Rsvd10008[0xe-0x8];
+/*0x1000E*/ ushort swsr; /* Softwareservice register 16 bits 4.3.2.9/4-36 */
+/*0x10010*/ uchar Rsvd10010[0x14];
+/*0x10024*/ ulong bcr; /* Bus configuration register 32 bits 4.3.2.1/4-25 */
+/*0x10028*/ ulong PPC_ACR; /* 60x bus arbiter configuration register 8 bits 4.3.2.2/4-28 */
+/*0x1002C*/ ulong PPCALRH; /* 60x bus arbitration-level register high (first 8 clients) 32 bits 4.3.2.3/4-28 */
+/*0x10030*/ ulong PPC_ALRL; /* 60x bus arbitration-level register low (next 8 clients) 32 bits 4.3.2.3/4-28 */
+/*0x10034*/ ulong LCL_ACR; /* Local arbiter configuration register 8 bits 4.3.2.4/4-29 */
+/*0x10038*/ ulong LCL_ALRH; /* Local arbitration-level register (first 8 clients) 32 bits 4.3.2.5/4-30 */
+
+/*0x1003C*/ ulong LCL_ALRL; /* Local arbitration-level register (next 8 clients) 32 bits 4.3.2.3/4-28 */
+/*0x10040*/ ulong TESCR1; /* 60x bus transfer error status control register1 32 bits 4.3.2.10/4-36 */
+/*0x10044*/ ulong TESCR2; /* 60x bus transfer error status control register2 32 bits 4.3.2.11/4-37 */
+/*0x10048*/ ulong L_TESCR1; /* Local bus transfer error status control register1 32 bits 4.3.2.12/4-38 */
+/*0x1004C*/ ulong L_TESCR2; /* Local bus transfer error status control register2 32 bits 4.3.2.13/4-39 */
+/*0x10050*/ ulong pdtea; /* 60x bus DMAtransfer error address 32 bits 18.2.3/18-4 */
+/*0x10054*/ uchar pdtem; /* 60x bus DMAtransfer error MSNUM 8 bits 18.2.4/18-4 */
+/*0x10055*/ uchar Rsvd10055[3];
+/*0x10058*/ void* ldtea; /* Local bus DMA transfer error address 32 bits 18.2.3/18-4 */
+/*0x1005C*/ uchar ldtem; /* Local bus DMA transfer error MSNUM 8 bits 18.2.4/18-4 */
+/*0x1005D*/ uchar Rsvd1005D[163];
+
+/* Memory Controller */
+/*0x10100*/ Bankmap bank[12];
+
+/*0x10160*/ uchar Rsvd10160[8];
+/*0x10168*/ void* MAR; /* Memory address register 32 bits 10.3.7/10-29 */
+/*0x1016C*/ ulong Rsvd1016C;
+/*0x10170*/ ulong MAMR; /* Machine A mode register 32 bits 10.3.5/10-26 */
+/*0x10174*/ ulong MBMR; /* Machine B mode register 32 bits */
+/*0x10178*/ ulong MCMR; /* Machine C mode register 32 bits */
+/*0x1017C*/ uchar Rsvd1017C[6];
+/*0x10184*/ ulong mptpr; /* Memory periodic timer prescaler 16 bits 10.3.12/10-32 */
+/*0x10188*/ ulong mdr; /* Memorydata register 32 bits 10.3.6/10-28 */
+/*0x1018C*/ ulong Rsvd1018C;
+/*0x10190*/ ulong psdmr; /* 60x bus SDRAM mode register 32 bits 10.3.3/10-21 */
+/*0x10194*/ ulong lsdmr; /* Local bus SDRAM mode register 32 bits 10.3.4/10-24 */
+/*0x10198*/ ulong PURT; /* 60x bus-assigned UPM refresh timer 8 bits 10.3.8/10-30 */
+/*0x1019C*/ ulong PSRT; /* 60x bus-assigned SDRAM refresh timer 8 bits 10.3.10/10-31 */
+
+/*0x101A0*/ ulong LURT; /* Local bus-assigned UPM refresh timer8 bits 10.3.9/10-30 */
+/*0x101A4*/ ulong LSRT; /* Local bus-assigned SDRAM refresh timer 8 bits 10.3.11/10-32 */
+
+/*0x101A8*/ ulong immr; /* Internal memory map register 32 bits 4.3.2.7/4-34 */
+/*0x101AC*/ uchar Rsvd101AC[84];
+/* System Integration Timers */
+/*0x10200*/ uchar Rsvd10200[32];
+/*0x10220*/ ulong TMCNTSC; /* Time counter statusand control register 16 bits 4.3.2.14/4-40 */
+
+/*0x10224*/ ulong TMCNT; /* Time counter register 32 bits 4.3.2.15/4-41 */
+/*0x10228*/ ulong Rsvd10228;
+/*0x1022C*/ ulong TMCNTAL; /* Time counter alarm register 32 bits 4.3.2.16/4-41 */
+/*0x10230*/ uchar Rsvd10230[0x10];
+/*0x10240*/ ulong PISCR; /* Periodic interrupt statusand control register 16 bits 4.3.3.1/4-42 */
+
+/*0x10244*/ ulong PITC; /* Periodic interrupt count register 32 bits 4.3.3.2/4-43 */
+/*0x10248*/ ulong PITR; /* Periodic interrupt timer register 32 bits 4.3.3.3/4-44 */
+/*0x1024C*/ uchar Rsvd1024C[94];
+/*0x102AA*/ uchar Rsvd102AA[2390];
+
+/* Interrupt Controller */
+/*0x10C00*/ ushort sicr; /* SIU interrupt configuration register 16 bits 4.3.1.1/4-17 */
+/*0x10C02*/ ushort Rsvd10C02;
+/*0x10C04*/ ulong sivec; /* SIU interrupt vector register 32 bits 4.3.1.6/4-23 */
+/*0x10C08*/ ulong sipnr_h; /* SIU interrupt pending register(high) 32 bits 4.3.1.4/4-21 */
+/*0x10C0C*/ ulong sipnr_l; /* SIU interrupt pending register(low) 32 bits 4.3.1.4/4-21 */
+/*0x10C10*/ ulong siprr; /* SIU interrupt priority register 32 bits 4.3.1.2/4-18 */
+/*0x10C14*/ ulong scprr_h; /* CPM interrupt priority register(high) 32 bits 4.3.1.3/4-19 */
+/*0x10C18*/ ulong scprr_l; /* CPM interrupt priority register(low) 32 bits 4.3.1.3/4-19 */
+/*0x10C1C*/ ulong simr_h; /* SIU interrupt mask register(high) 32 bits 4.3.1.5/4-22 */
+/*0x10C20*/ ulong simr_l; /* SIU interrupt mask register(low) 32 bits 4.3.1.5/4-22 */
+/*0x10C24*/ ulong siexr; /* SIUexternal interrupt control register 32 bits 4.3.1.7/4-24 */
+/*0x10C28*/ uchar Rsvd10C28[88];
+
+/* Clocksand Reset */
+/*0x10C80*/ ulong sccr; /* Systemclock control register 32 bits 9.8/9-8 */
+/*0x10C84*/ uchar Rsvd10C84[4];
+/*0x10C88*/ ulong scmr; /* Systemclock mode register 32 bits 9.9/9-9 */
+/*0x10C8C*/ uchar Rsvd10C8C[4];
+/*0x10C90*/ ulong rsr; /* Reset status register 32 bits 5.2/5-4 */
+/*0x10C94*/ ulong rmr; /* Reset mode register 32 bits 5.3/5-5 */
+/*0x10C98*/ uchar Rsvd10C98[104];
+
+/* Part I.Overview Input/Output Port */
+/*0x10D00*/ Port port[4];
+
+/* CPMTimers */
+/*0x10D80*/ uchar tgcr1; /* Timer1 and timer2 global configuration register 8 bits 17.2.2/17-4 */
+
+/*0x10D81*/ uchar Rsvd10D81[3];
+/*0x10D84*/ uchar tgcr2; /* Timer3 and timer4 global configuration register 8 bits 17.2.2/17-4 */
+/*0x10D85*/ uchar Rsvd10D85[3];
+
+/*0x10D88*/ uchar Rsvd10D88[8];
+/*0x10D90*/ ushort tmr1; /* Timer1 mode register 16 bits 17.2.3/17-6 */
+/*0x10D92*/ ushort tmr2; /* Timer2 mode register 16 bits 17.2.3/17-6 */
+ union{
+ struct {
+/*0x10D94*/ ushort trr1; /* Timer1 reference register 16 bits 17.2.4/17-7 */
+/*0x10D96*/ ushort trr2; /* Timer2 reference register 16 bits 17.2.4/17-7 */
+ };
+/*0x10D94*/ ulong trrl1; /* Combined Timer 1/2 trr register */
+ };
+ union{
+ struct {
+/*0x10D98*/ ushort tcr1; /* Timer1 capture register 16 bits 17.2.5/17-8 */
+/*0x10D9A*/ ushort tcr2; /* Timer2 capture register 16 bits 17.2.5/17-8 */
+ };
+/*0x10D98*/ ulong tcrl1; /* Combined timer1/2 capture register */
+ };
+ union{
+ struct {
+/*0x10D9C*/ ushort tcn1; /* Timer1 counter 16 bits 17.2.6/17-8 */
+/*0x10D9E*/ ushort tcn2; /* Timer2 counter 16 bits 17.2.6/17-8 */
+ };
+/*0x10D9C*/ ulong tcnl1; /* Combined timer1/2 counter */
+ };
+/*0x10DA0*/ ushort tmr3; /* Timer3 mode register 16 bits 17.2.3/17-6 */
+/*0x10DA2*/ ushort tmr4; /* Timer4 mode register 16 bits 17.2.3/17-6 */
+ union{
+ struct {
+/*0x10DA4*/ ushort trr3; /* Timer3 reference register 16 bits 17.2.4/17-7 */
+/*0x10DA6*/ ushort trr4; /* Timer4 reference register 16 bits 17.2.4/17-7 */
+ };
+/*0x10DA4*/ ulong trrl3;
+ };
+ union{
+ struct {
+/*0x10DA8*/ ushort tcr3; /* Timer3 capture register 16 bits 17.2.5/17-8 */
+/*0x10DAA*/ ushort tcr4; /* Timer4 capture register 16 bits 17.2.5/17-8 */
+ };
+/*0x10DA8*/ ulong tcrl3;
+ };
+ union{
+ struct {
+/*0x10DAC*/ ushort tcn3; /* Timer3 counter 16 bits 17.2.6/17-8 */
+/*0x10DAE*/ ushort tcn4; /* Timer4 counter 16 bits 17.2.6/17-8 */
+ };
+/*0x10DAC*/ ulong tcnl3;
+ };
+/*0x10DB0*/ ushort ter1; /* Timer1 event register 16 bits 17.2.7/17-8 */
+/*0x10DB2*/ ushort ter2; /* Timer2 event register 16 bits 17.2.7/17-8 */
+/*0x10DB4*/ ushort ter3; /* Timer3 event register 16 bits 17.2.7/17-8 */
+/*0x10DB6*/ ushort ter4; /* Timer4 event register 16 bits 17.2.7/17-8 */
+/*0x10DB8*/ uchar Rsvd10DB8[608];
+
+/* SDMADHGeneral */
+/*0x11018*/ uchar sdsr; /* SDMA status register 8 bits 18.2.1/18-3 */
+/*0x11019*/ uchar Rsvd11019[3];
+/*0x1101C*/ uchar sdmr; /* SDMA mask register 8 bits 18.2.2/18-4 */
+/*0x1101D*/ uchar Rsvd1101D[3];
+
+/* IDMA */
+/*0x11020*/ IDMA idma[4];
+
+/*0x11040*/ uchar Rsvd11040[704];
+
+/*0x11300*/ FCC fcc[3];
+
+/*0x11360*/ uchar Rsvd11360[0x290];
+
+/* BRGs5DH8 */
+/*0x115F0*/ ulong BRGC5; /* BRG5 configuration register 32 bits 16.1/16-2 */
+/*0x115F4*/ ulong BRGC6; /* BRG6configuration register 32 bits */
+/*0x115F8*/ ulong BRGC7; /* BRG7configuration register 32 bits */
+/*0x115FC*/ ulong BRGC8; /* BRG8configuration register 32 bits */
+/*0x11600*/ uchar Rsvd11600[0x260];
+/*0x11860*/ uchar I2MOD; /* I2C mode register 8 bits 34.4.1/34-6 */
+/*0x11861*/ uchar Rsvd11861[3];
+/*0x11864*/ uchar I2ADD; /* I2C address register 8 bits 34.4.2/34-7 */
+/*0x11865*/ uchar Rsvd11865[3];
+/*0x11868*/ uchar I2BRG; /* I2C BRG register 8 bits 34.4.3/34-7 */
+/*0x11869*/ uchar Rsvd11869[3];
+/*0x1186C*/ uchar I2COM; /* I2C command register 8 bits 34.4.5/34-8 */
+/*0x1186D*/ uchar Rsvd1186D[3];
+/*0x11870*/ uchar I2CER; /* I2C event register 8 bits 34.4.4/34-8 */
+/*0x11871*/ uchar Rsvd11871[3];
+/*0x11874*/ uchar I2CMR; /* I2C mask register 8 bits 34.4.4/34-8 */
+/*0x11875*/ uchar Rsvd11875[331];
+
+/* Communications Processor */
+/*0x119C0*/ ulong cpcr; /* Communications processor command register 32 bits 13.4.1/13-11 */
+
+/*0x119C4*/ ulong rccr; /* CP configuration register 32 bits 13.3.6/13-7 */
+/*0x119C8*/ uchar Rsvd119C8[14];
+/*0x119D6*/ ushort rter; /* CP timers event register 16 bits 13.6.4/13-21 */
+/*0x119D8*/ ushort Rsvd119D8;
+/*0x119DA*/ ushort rtmr; /* CP timers mask register 16 bits */
+/*0x119DC*/ ushort rtscr; /* CPtime-stamp timer control register 16 bits 13.3.7/13-9 */
+/*0x119DE*/ ushort Rsvd119DE;
+/*0x119E0*/ ulong rtsr; /* CPtime-stamp register 32 bits 13.3.8/13-10 */
+/*0x119E4*/ uchar Rsvd119E4[12];
+
+/*0x119F0*/ ulong brgc[4]; /* BRG configuration registers 32 bits 16.1/16-2 */
+
+/*0x11A00*/ SCC scc[4];
+
+/*0x11A80*/ SMC smc[2];
+
+ SPI spi;
+
+/*0x11AB0*/ uchar Rsvd11AB0[80];
+
+/* CPMMux */
+/*0x11B00*/ uchar cmxsi1cr; /* CPM mux SI1clock route register 8 bits 15.4.2/15-10 */
+/*0x11B01*/ uchar Rsvd11B01;
+/*0x11B02*/ uchar cmxsi2cr; /* CPM mux SI2clock route register 8 bits 15.4.3/15-11 */
+/*0x11B03*/ uchar Rsvd11B03;
+/*0x11B04*/ ulong cmxfcr; /* CPM mux FCC clock route register 32 bits 15.4.4/15-12 */
+/*0x11B08*/ ulong cmxscr; /* CPM mux SCC clock route register 32 bits 15.4.5/15-14 */
+/*0x11B0C*/ uchar cmxsmr; /* CPM mux SMC clock route register 8 bits 15.4.6/15-17 */
+/*0x11B0D*/ uchar Rsvd11B0D;
+/*0x11B0E*/ ushort cmxuar; /* CPM mux UTOPIA address register 16 bits 15.4.1/15-7 */
+/*0x11B10*/ uchar Rsvd11B10[16];
+
+ SI si1; /* SI 1 Registers */
+
+/* MCC1Registers */
+/*0x11B30*/ ushort MCCE1; /* MCC1 event register 16 bits 27.10.1/27-18 */
+/*0x11B32*/ ushort Rsvd11B32;
+/*0x11B34*/ ushort MCCM1; /* MCC1 mask register 16 bits */
+/*0x11B36*/ ushort Rsvd11B36;
+/*0x11B38*/ uchar MCCF1; /* MCC1 configuration register 8 bits 27.8/27-15 */
+/*0x11B39*/ uchar Rsvd11B39[7];
+
+ SI si2; /* SI 2 Registers */
+
+/* MCC2Registers */
+/*0x11B50*/ ushort MCCE2; /* MCC2 event register 16 bits 27.10.1/27-18 */
+/*0x11B52*/ ushort Rsvd11B52;
+/*0x11B54*/ ushort MCCM2; /* MCC2 mask register 16 bits */
+/*0x11B56*/ ushort Rsvd11B56;
+/*0x11B58*/ uchar MCCF2; /* MCC2 configuration register 8 bits 27.8/27-15 */
+/*0x11B59*/ uchar Rsvd11B59[1191];
+
+/* SI1RAM */
+/*0x12000*/ uchar SI1TxRAM[0x200];/* SI1 transmit routing RAM 512 14.4.3/14-10 */
+/*0x12200*/ uchar Rsvd12200[0x200];
+/*0x12400*/ uchar SI1RxRAM[0x200];/* SI1 receive routing RAM 512 14.4.3/14-10 */
+/*0x12600*/ uchar Rsvd12600[0x200];
+
+/* SI2RAM */
+/*0x12800*/ uchar SI2TxRAM[0x200];/* SI2 transmit routing RAM 512 14.4.3/14-10 */
+/*0x12A00*/ uchar Rsvd12A00[0x200];
+/*0x12C00*/ uchar SI2RxRAM[0x200];/* SI2 receive routing RAM 512 14.4.3/14-10 */
+/*0x12E00*/ uchar Rsvd12E00[0x200];
+/*0x13000*/ uchar Rsvd13000[0x800];
+/*0x13800*/ uchar Rsvd13800[0x800];
+};
+
+typedef struct FCCextra FCCextra;
+struct FCCextra {
+/*0x00*/ uchar ri[0x20];
+/*0x20*/ uchar ti[0x20];
+/*0x40*/ uchar pad[0x20];
+};
+
+typedef struct Imap Imap;
+struct Imap {
+/* CPMDual-Port RAM */
+/*0x00000*/ uchar dpram1[0x3800]; /* Dual-port RAM 16Kbytes 13.5/13-15 */
+/*0x03800*/ FCCextra fccextra[4];
+/*0x03980*/ Uartsmc uartsmc[2];
+/*0x03a00*/ uchar dsp1p[0x40];
+/*0x03a40*/ uchar dsp2p[0x40];
+/*0x03a80*/ BD bd[(0x04000-0x03a80)/sizeof(BD)]; /* Buffer descriptors */
+/*0x04000*/ uchar Rsvd4000[0x04000];
+
+/* Dual port RAM bank 2 -- Parameter Ram, Section 13.5 */
+/*0x08000*/ PrmSCC prmscc[4];
+/*0x08400*/ PrmFCC prmfcc[3];
+/*0x08700*/ Bases param[4];
+/*0x08b00*/ uchar dpram2[0x500];
+
+/*0x09000*/ uchar Rsvd9000[0x2000];
+
+/* Dual port RAM bank 3 -- Section 13.5 */
+/*0x0B000*/ uchar dpram3[0x1000]; /* Dual-port RAM 4Kbytes 13.5/13-15 */
+/*0x0C000*/ uchar Rsvdc000[0x4000];
+
+/*0x10000*/ IMM;
+};
+
+enum {
+/* CPM Command register. */
+ cpm_rst = 0x80000000,
+ cpm_page = 0x7c000000,
+ cpm_sblock = 0x03e00000,
+ cpm_flg = 0x00010000,
+ cpm_mcn = 0x00003fc0,
+ cpm_opcode = 0x0000000f,
+
+/* Device sub-block and page codes. */
+ cpm_fcc1_sblock = 0x10,
+ cpm_fcc2_sblock = 0x11,
+ cpm_fcc3_sblock = 0x12,
+ cpm_scc1_sblock = 0x04,
+ cpm_scc2_sblock = 0x05,
+ cpm_scc3_sblock = 0x06,
+ cpm_scc4_sblock = 0x07,
+ cpm_smc1_sblock = 0x08,
+ cpm_smc2_sblock = 0x09,
+ cpm_rand_sblock = 0x0e,
+ cpm_spi_sblock = 0x0a,
+ cpm_i2c_sblock = 0x0b,
+ cpm_timer_sblock = 0x0f,
+ cpm_mcc1_sblock = 0x1c,
+ cpm_mcc2_sblock = 0x1d,
+ cpm_idma1_sblock = 0x14,
+ cpm_idma2_sblock = 0x15,
+ cpm_idma3_sblock = 0x16,
+ cpm_idma4_sblock = 0x17,
+
+ cpm_scc1_page = 0x00,
+ cpm_scc2_page = 0x01,
+ cpm_scc3_page = 0x02,
+ cpm_scc4_page = 0x03,
+ cpm_smc1_page = 0x07,
+ cpm_smc2_page = 0x08,
+ cpm_spi_page = 0x09,
+ cpm_i2c_page = 0x0a,
+ cpm_timer_page = 0x0a,
+ cpm_rand_page = 0x0a,
+ cpm_fcc1_page = 0x04,
+ cpm_fcc2_page = 0x05,
+ cpm_fcc3_page = 0x06,
+ cpm_idma1_page = 0x07,
+ cpm_idma2_page = 0x08,
+ cpm_idma3_page = 0x09,
+ cpm_idma4_page = 0x0a,
+ cpm_mcc1_page = 0x07,
+ cpm_mcc2_page = 0x08,
+
+};
+
+/*
+ * CPM
+ */
+enum {
+ /* commands */
+ InitRxTx = 0,
+ InitRx = 1,
+ InitTx = 2,
+ EnterHunt= 3,
+ StopTx= 4,
+ GracefulStopTx = 5,
+ InitIDMA = 5,
+ RestartTx = 6,
+ CloseRxBD = 7,
+ SetGroupAddr = 8,
+ SetTimer = 8,
+ GCITimeout = 9,
+ GCIAbort = 10,
+ StopIDMA = 11,
+ StartDSP = 12,
+ ArmIDMA = 13,
+ InitDSP = 13,
+ USBCmd = 15,
+
+ /* channel IDs */
+ SCC1ID= cpm_scc1_page << 5 | cpm_scc1_sblock,
+ SCC2ID= cpm_scc2_page << 5 | cpm_scc2_sblock,
+ SCC3ID= cpm_scc3_page << 5 | cpm_scc3_sblock,
+ SMC1ID= cpm_smc1_page << 5 | cpm_smc1_sblock,
+ SMC2ID= cpm_smc2_page << 5 | cpm_smc2_sblock,
+ FCC1ID= cpm_fcc1_page << 5 | cpm_fcc1_sblock,
+ FCC2ID= cpm_fcc2_page << 5 | cpm_fcc2_sblock,
+ FCC3ID= cpm_fcc3_page << 5 | cpm_fcc3_sblock,
+// USBID= 0, These are wrong
+// I2CID= 1,
+// IDMA1ID= 1,
+// SPIID= 5,
+// IDMA2ID= 5,
+// TIMERID= 5,
+// DSP1ID=9,
+// SCC4ID= 10,
+// DSP2ID= 13,
+
+ /* sicr */
+ BRG1 = 0,
+ BRG2 = 1,
+ BRG3 = 2,
+ BRG4 = 4,
+ CLK1 = 4,
+ CLK2 = 5,
+ CLK3 = 6,
+ CLK4 = 7,
+
+};
+
+extern IMM* iomem;
+
+BD* bdalloc(int);
+void cpmop(int, int, int);
+void ioplock(void);
+void iopunlock(void);
+void kreboot(ulong);
diff --git a/sys/src/9/ppc/main.c b/sys/src/9/ppc/main.c
new file mode 100755
index 000000000..380d6fd6f
--- /dev/null
+++ b/sys/src/9/ppc/main.c
@@ -0,0 +1,511 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "init.h"
+#include "pool.h"
+#include "tos.h"
+
+#define MAXCONF 64
+
+typedef struct Plan9ini Plan9ini;
+struct Plan9ini
+{
+ char *name;
+ char *val;
+};
+
+char *plan9inistr;
+Plan9ini plan9ini[MAXCONF];
+int nconf;
+
+Conf conf;
+FPsave initfp;
+Lock testlock;
+
+static void plan9iniinit(void);
+
+char *
+cpuid(void)
+{
+ char *id;
+
+ id = "unknown PowerPC";
+ switch(m->cputype) {
+ case 8:
+ id = "PowerPC 750";
+ break;
+ case 9:
+ id = "PowerPC 604e";
+ break;
+ case 0x81:
+ id = "PowerPC 8260";
+ break;
+ case 0x8081:
+ id = "PowerPC 826xA";
+ break;
+ default:
+ break;
+ }
+ return id;
+}
+
+void
+cpuidprint(void)
+{
+ print("cpu0: %s, rev 0x%lux, cpu hz %lld, bus hz %ld\n",
+ cpuid(), getpvr()&0xffff, m->cpuhz, m->bushz);
+}
+
+void
+main(void)
+{
+ memset(edata, 0, (ulong)end-(ulong)edata);
+ conf.nmach = 1;
+ machinit();
+ confinit();
+ xinit();
+ trapinit();
+ mmuinit();
+ plan9iniinit();
+ hwintrinit();
+ clockinit();
+ timerinit();
+ console();
+ quotefmtinstall();
+ printinit();
+ cpuidprint();
+ print("\nPlan 9 from Bell Labs\n");
+ procinit0();
+ initseg();
+ timersinit();
+ links();
+ chandevreset();
+ pageinit();
+ swapinit();
+ sharedseginit();
+ fpsave(&initfp);
+ initfp.fpscr = 0;
+ userinit();
+ schedinit();
+}
+
+char*
+getconf(char *name)
+{
+ int i;
+
+ for(i = 0; i < nconf; i++)
+ if(cistrcmp(name, plan9ini[i].name) == 0)
+ return plan9ini[i].val;
+ return nil;
+}
+
+static void
+plan9iniinit(void)
+{
+ long i;
+ int c;
+ char *cp, line[MAXCONF], *p, *q;
+
+ /*
+ * parse configuration args from dos file plan9.ini
+ */
+
+ cp = plan9inistr;
+ for(i = 0; i < MAXCONF; i++){
+ /*
+ * Strip out '\r', change '\t' -> ' ', test for 0xff which is end of file
+ */
+ p = line;
+ for(q = cp; c = (uchar)*q; q++){
+ if(c == '\r')
+ continue;
+ if(c == '\t')
+ c = ' ';
+ if(c == 0xff || c == '\n')
+ break;
+ *p++ = c;
+ }
+ *p = 0;
+ if (*line == 0)
+ break;
+ if(*line != '#' && (cp = strchr(line, '='))){
+ *cp++ = '\0';
+ kstrdup(&plan9ini[nconf].name, line);
+ kstrdup(&plan9ini[nconf].val, cp);
+ nconf++;
+ }
+ if (c == 0xff)
+ break;
+
+ cp = q + 1;
+ }
+}
+
+void
+init0(void)
+{
+// char **p, *q, name[KNAMELEN];
+ int i;
+ char buf[2*KNAMELEN];
+
+ up->nerrlab = 0;
+ spllo();
+
+ /*
+ * These are o.k. because rootinit is null.
+ * Then early kproc's will have a root and dot.
+ */
+ up->slash = namec("#/", Atodir, 0, 0);
+ pathclose(up->slash->path);
+ up->slash->path = newpath("/");
+ up->dot = cclone(up->slash);
+
+ chandevinit();
+
+ if(!waserror()){
+ snprint(buf, sizeof(buf), "power %s mtx", conffile);
+ ksetenv("terminal", buf, 0);
+ ksetenv("cputype", "power", 0);
+ if(cpuserver)
+ ksetenv("service", "cpu", 0);
+ else
+ ksetenv("service", "terminal", 0);
+
+ for(i = 0; i < nconf; i++){
+ if(plan9ini[i].name[0] != '*')
+ ksetenv(plan9ini[i].name, plan9ini[i].val, 0);
+ ksetenv(plan9ini[i].name, plan9ini[i].val, 1);
+ }
+ poperror();
+ }
+ kproc("alarm", alarmkproc, 0);
+ kproc("mmusweep", mmusweep, 0);
+ touser((void*)(USTKTOP-sizeof(Tos)));
+}
+
+void
+userinit(void)
+{
+ Proc *p;
+ Segment *s;
+ KMap *k;
+ Page *pg;
+
+ p = newproc();
+ p->pgrp = newpgrp();
+ p->egrp = smalloc(sizeof(Egrp));
+ p->egrp->ref = 1;
+ p->fgrp = dupfgrp(nil);
+ p->rgrp = newrgrp();
+ p->procmode = 0640;
+
+ kstrdup(&eve, "");
+ kstrdup(&p->text, "*init*");
+ kstrdup(&p->user, eve);
+
+ p->fpstate = FPinit;
+
+ /*
+ * Stack
+ *
+ * N.B. The -12 for the stack pointer is important.
+ * 4 bytes for gotolabel's return PC
+ */
+ p->sched.pc = (ulong)init0;
+ p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
+
+ /*
+ * User Stack
+ */
+ s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
+ p->seg[SSEG] = s;
+ pg = newpage(1, 0, USTKTOP-BY2PG);
+ segpage(s, pg);
+
+ /*
+ * Text
+ */
+ s = newseg(SG_TEXT, UTZERO, 1);
+ s->flushme++;
+ p->seg[TSEG] = s;
+ pg = newpage(1, 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);
+
+ ready(p);
+}
+
+void
+exit(int ispanic)
+{
+ int ms, once;
+
+ lock(&active);
+ if(ispanic)
+ active.ispanic = ispanic;
+ else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
+ active.ispanic = 0;
+ once = active.machs & (1<<m->machno);
+ active.machs &= ~(1<<m->machno);
+ active.exiting = 1;
+ unlock(&active);
+
+ if(once)
+ print("cpu%d: exiting\n", m->machno);
+ spllo();
+ for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
+ delay(TK2MS(2));
+ if(active.machs == 0 && consactive() == 0)
+ break;
+ }
+
+ if(active.ispanic && m->machno == 0){
+ if(cpuserver)
+ delay(10000);
+ else if(conf.monitor)
+ for(;;);
+ }
+ else
+ delay(1000);
+
+}
+
+/*
+ * set up floating point for a new process
+ */
+void
+procsetup(Proc *p)
+{
+ p->fpstate = FPinit;
+}
+
+void
+procrestore(Proc *p)
+{
+ uvlong t;
+
+ if(p->kp)
+ return;
+ cycles(&t);
+ p->pcycles -= t;
+}
+
+/*
+ * Save the mach dependent part of the process state.
+ */
+void
+procsave(Proc *p)
+{
+ uvlong t;
+
+ cycles(&t);
+ p->pcycles += t;
+ if(p->fpstate == FPactive){
+ if(p->state != Moribund)
+ fpsave(&up->fpsave);
+ p->fpstate = FPinactive;
+ }
+}
+
+void
+confinit(void)
+{
+ char *p;
+ int userpcnt;
+ ulong pa, kpages;
+ /* passed in from ROM monitor: */
+
+ if(p = getconf("*kernelpercent"))
+ userpcnt = 100 - strtol(p, 0, 0);
+ else
+ userpcnt = 0;
+
+ pa = PGROUND(PADDR(end));
+
+ /* Blast Board specific */
+ conf.mem[0].npage = (MEM1SIZE - pa)/BY2PG;
+ conf.mem[0].base = pa;
+
+ conf.mem[1].npage = MEM2SIZE/BY2PG;
+ conf.mem[1].base = MEM2BASE;
+
+ conf.npage = conf.mem[0].npage + conf.mem[1].npage;
+
+ conf.nmach = 1;
+ conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
+ if(cpuserver)
+ conf.nproc *= 3;
+ if(conf.nproc > 2000)
+ conf.nproc = 2000;
+ conf.nimage = 200;
+ conf.nswap = conf.nproc*80;
+ conf.nswppo = 4096;
+ conf.copymode = 0; /* copy on write */
+
+ if(cpuserver) {
+ if(userpcnt < 10)
+ userpcnt = 70;
+ kpages = conf.npage - (conf.npage*userpcnt)/100;
+
+ /*
+ * Hack for the big boys. Only good while physmem < 4GB.
+ * Give the kernel a max. of 16MB + enough to allocate the
+ * page pool.
+ * This is an overestimate as conf.upages < conf.npages.
+ * The patch of nimage is a band-aid, scanning the whole
+ * page list in imagereclaim just takes too long.
+ */
+ if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){
+ kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;
+ conf.nimage = 2000;
+ kpages += (conf.nproc*KSTACK)/BY2PG;
+ }
+ } else {
+ if(userpcnt < 10) {
+ if(conf.npage*BY2PG < 16*MB)
+ userpcnt = 40;
+ else
+ userpcnt = 60;
+ }
+ kpages = conf.npage - (conf.npage*userpcnt)/100;
+
+ /*
+ * Make sure terminals with low memory get at least
+ * 4MB on the first Image chunk allocation.
+ */
+ if(conf.npage*BY2PG < 16*MB)
+ imagmem->minarena = 4*1024*1024;
+ }
+ conf.upages = conf.npage - kpages;
+ conf.ialloc = (kpages/2)*BY2PG;
+
+ /*
+ * Guess how much is taken by the large permanent
+ * datastructures. Mntcache and Mntrpc are not accounted for
+ * (probably ~300KB).
+ */
+ kpages *= BY2PG;
+ kpages -= conf.upages*sizeof(Page)
+ + conf.nproc*sizeof(Proc)
+ + conf.nimage*sizeof(Image)
+ + conf.nswap
+ + conf.nswppo*sizeof(Page);
+ mainmem->maxsize = kpages;
+ if(!cpuserver){
+ /*
+ * give terminals lots of image memory, too; the dynamic
+ * allocation will balance the load properly, hopefully.
+ * be careful with 32-bit overflow.
+ */
+ imagmem->maxsize = kpages;
+ }
+
+// conf.monitor = 1; /* BUG */
+}
+
+static int
+getcfields(char* lp, char** fields, int n, char* sep)
+{
+ int i;
+
+ for(i = 0; lp && *lp && i < n; i++){
+ while(*lp && strchr(sep, *lp) != 0)
+ *lp++ = 0;
+ if(*lp == 0)
+ break;
+ fields[i] = lp;
+ while(*lp && strchr(sep, *lp) == 0){
+ if(*lp == '\\' && *(lp+1) == '\n')
+ *lp++ = ' ';
+ lp++;
+ }
+ }
+
+ return i;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ int i;
+ char cc[KNAMELEN], *p;
+
+ sprint(cc, "%s%d", class, ctlrno);
+
+ p = getconf(cc);
+ if(p == 0)
+ return 0;
+ isa->nopt = tokenize(p, isa->opt, NISAOPT);
+ for(i = 0; i < isa->nopt; i++){
+ p = isa->opt[i];
+ if(cistrncmp(p, "type=", 5) == 0)
+ isa->type = p + 5;
+ else if(cistrncmp(p, "port=", 5) == 0)
+ isa->port = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "irq=", 4) == 0)
+ isa->irq = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "dma=", 4) == 0)
+ isa->dma = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "mem=", 4) == 0)
+ isa->mem = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "size=", 5) == 0)
+ isa->size = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "freq=", 5) == 0)
+ isa->freq = strtoul(p+5, &p, 0);
+ }
+ return 1;
+}
+
+int
+cistrcmp(char *a, char *b)
+{
+ int ac, bc;
+
+ for(;;){
+ ac = *a++;
+ bc = *b++;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+ return 0;
+}
+
+int
+cistrncmp(char *a, char *b, int n)
+{
+ unsigned ac, bc;
+
+ while(n > 0){
+ ac = *a++;
+ bc = *b++;
+ n--;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+
+ return 0;
+}
diff --git a/sys/src/9/ppc/mcc.c b/sys/src/9/ppc/mcc.c
new file mode 100755
index 000000000..8d89f2d69
--- /dev/null
+++ b/sys/src/9/ppc/mcc.c
@@ -0,0 +1,351 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+/*
+ *
+ * mcc.c
+ *
+ * This is the driver for the Multi-Channel Communications Controller
+ * of the MPC8260. This version is constructed for the EST SBC8260 to
+ * handle data from an interface to an offboard T1 framer. The driver
+ * supports MCC2 + TDM A:2 (channel 128) which is connected to the
+ * external interface.
+ *
+ * Neville Chandler
+ * Lucent Technologies - Bell Labs
+ * March 2001
+ *
+ */
+
+#define PKT_LEN 40
+#define MPC82XX_INIT_DELAY 0x10000
+
+#define HPIC 0xFC000000
+#define HPIA 0xFC000010
+#define HPID_A 0xFC000020
+#define HPID 0xFC000030
+
+
+#include "mcc2.h"
+
+static ssize_t mcc2_read( struct file *, char *, size_t, loff_t * );
+static ssize_t mcc2_write( struct file *, const char *, size_t, loff_t *);
+static loff_t mcc2_lseek( struct file *, loff_t, int );
+static int mcc2_release( struct inode *, struct file * );
+static ssize_t mcc2_ioctl( struct inode *, struct file *, unsigned int, unsigned long );
+//static ssize_t mcc2_ioctl( struct inode *, struct file *, unsigned int, char * );
+
+void MPC82xxCpmInit( void );
+void PortInit( void );
+void PortSelectPin( unsigned short );
+
+void InitMemAlloc( void );
+void HeapCreate( U32, U32, U32, U32, char *);
+void HeapCreate( U32, U32, U32, U32, char *);
+void *HeapSearchMem( U32, U32);
+void *HeapAllocMem( U32, U32);
+void HeapFreeMem( U32, void *);
+
+void InitLinkedList( void );
+boolean DwCreateList( ListDB * );
+void *DwMalloc( U32 );
+void DwFree( U32, void * );
+
+void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
+
+#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
+
+extern int ppc_spurious_interrupts;
+extern int ppc_second_irq;
+extern struct irqaction *ppc_irq_action[NR_IRQS];
+extern unsigned int ppc_local_bh_count[NR_CPUS];
+extern unsigned int ppc_local_irq_count[NR_CPUS];
+extern unsigned int ppc_cached_irq_mask[NR_MASK_WORDS];
+extern unsigned int ppc_lost_interrupts[NR_MASK_WORDS];
+extern atomic_t ppc_n_lost_interrupts;
+
+//static void disp_led( unsigned char );
+
+void Mcc2Init( void );
+void MccDisable( unsigned char );
+void MccEnable( unsigned char, unsigned char, unsigned char );
+void MccRiscCmd( unsigned char, dwv_RISC_OPCODE, unsigned char );
+boolean MccTest( void );
+int MccTxBuffer( unsigned char, unsigned char, char *, unsigned short, unsigned short );
+extern U32 PpcDisable( void );
+extern void PpcMsrRestore( U32 );
+
+static int mcc2_major = MCC_MAJOR;
+
+static BOOLEAN insertBD_T( BD_PFIFO *, BD_P );
+static BOOLEAN removBD_T( BD_PFIFO *, BD_P * );
+BOOLEAN empty(volatile register FIFO *);
+int insert( FIFO *, char * );
+int remove( FIFO *, char ** );
+void AppInit( void );
+
+#define physaddr(ADDR) (0x60020000 | ((ADDR) << 23) | (2 << 18))
+
+mcc_iorw_t mcc_iorw;
+
+#if 0
+typedef struct mcc_io {
+ unsigned int cmd;
+ unsigned int address;
+ unsigned int *buf;
+ int ind;
+ int nbytes;
+ siramctl_t SiRam;
+ cpmux_t CpMux;
+ mcc_t Mcc_T;
+ iop8260_t Io_Ports;
+} mcc_iorw_t;
+#endif
+
+static void
+ioctl_parm( unsigned int loop_mode )
+{
+
+ /* Setup the SIMODE Register */
+ Si2Regs->SiAmr = SIxMR_SAD_BANK0_FIRST_HALF | /* SADx */
+ loop_mode | /* SDMx */
+ SIxMR_NO_BIT_RX_SYNC_DELAY | /* RFSDx */
+ SIxMR_DSC_CH_DATA_CLK_EQU | /* DSCx */
+ SIxMR_CRT_SPEPARATE_PINS | /* CRTx */
+ SIxMR_SLx_NORMAL_OPERATION | /* SLx */
+ SIxMR_CE_TX_RISING_RX_FALLING | /* CEx */
+ SIxMR_FE_FALLING_EDGE | /* FEx */
+ SIxMR_GM_GCI_SCIT_MODE | /* GMx */
+ SIxMR_NO_BIT_TX_SYNC_DELAY; /* TFSDx */
+}
+
+#if 0
+static void
+disp_led( unsigned char byte )
+{
+ //int i;
+
+ *leds = byte;
+ //for(i=0; i<1000; i++);
+
+}
+#endif
+
+
+
+static ssize_t
+mcc2_ioctl( struct inode *inode, struct file *file,
+ unsigned int ioctl_cmd, // IOCTL number
+ unsigned long param )
+// char *param ) // IOCTL parameter
+{
+ static unsigned char mode;
+ char cp, *cptr;
+ void *vptr;
+ unsigned long *lptr;
+ int i, j;
+ unsigned int ld;
+ unsigned long lng;
+ volatile immap_t *Mmap;
+
+ cptr = (char *)param;
+ mode = (unsigned char)*cptr;
+ Mmap = ((volatile immap_t *)IMAP_ADDR);
+ switch(ioctl_cmd)
+ {
+ case IOCTL_SET_MODE:
+ //mode = (unsigned char)*param;
+ mode = ((mcc_iorw_t *)param)->cmd;
+ switch( mode )
+ {
+ case NORMAL_OPERATION:
+ /* Setup the SIMODE Register */
+ D( printk("mcc2_ioctl: ioctl set NORMAL_OPERATION mode\n"); )
+ ioctl_parm( (unsigned int)SIxMR_SDM_NORMAL_OPERATION ); /* SDMx */
+ break;
+
+ case AUTOMATIC_ECHO:
+ /* Setup the SIMODE Register */
+ D( printk("mcc2_ioctl: ioctl set AUTOMATIC_ECHO mode\n"); )
+ ioctl_parm( (unsigned int)SIxMR_SDM_AUTOMATIC_ECHO ); /* SDMx */
+ break;
+
+ case INTERNAL_LOOPBACK:
+ /* Setup the SIMODE Register */
+ D( printk("mcc2_ioctl: ioctl set INTERNAL_LOOPBACK mode\n"); )
+ ioctl_parm( (unsigned int)SIxMR_SDM_INTERNAL_LOOPBACK ); /* SDMx */
+ break;
+
+ case LOOPBACK_CONTROL:
+ /* Setup the SIMODE Register */
+ D( printk("mcc2_ioctl: ioctl set LOOPBACK_CONTROL mode\n"); )
+ ioctl_parm( (unsigned int)SIxMR_SDM_LOOPBACK_CONTROL ); /* SDMx */
+ break;
+
+
+ default:
+ printk("mcc2_ioctl: Error, unrecognized ioctl parameter, device operation unchanged.\n");
+ break;
+
+ }
+ break;
+
+ case IOCTL_RWX_MODE:
+ mode = ((mcc_iorw_t *)param)->cmd;
+ switch(mode)
+ {
+ case HPI_RD:
+ lng = (long)(((mcc_iorw_t *)param)->address);
+ lptr = ((unsigned long *)lng);
+ vptr = (void *)lptr;
+ if (copy_to_user( (((mcc_iorw_t *)param)->buf), (void *)vptr, (((mcc_iorw_t *)param)->nbytes))) {
+ printk("mcc2_ioctl: Failed during read from hpi.\n");
+ return -EFAULT;
+ }
+ break;
+
+
+ case HPI_WR:
+ lng = (long)(((mcc_iorw_t *)param)->address);
+ lptr = ((unsigned long *)lng);
+ vptr = (void *)lptr;
+ if (copy_from_user( (void *)vptr, (((mcc_iorw_t *)param)->buf), (((mcc_iorw_t *)param)->nbytes))) {
+ printk("mcc2_ioctl: Failed during write to hpi\n");
+ return -EFAULT;
+ }
+ break;
+
+
+
+ case FPGA_RD:
+ lng = (long)(((mcc_iorw_t *)param)->address);
+ lptr = ((unsigned long *)lng);
+ vptr = (void *)lptr;
+ if (copy_to_user( (((mcc_iorw_t *)param)->buf), (void *)vptr, (((mcc_iorw_t *)param)->nbytes))) {
+ printk("mcc2_ioctl: Failed during read from FPGA.\n");
+ return -EFAULT;
+ }
+ break;
+
+
+ case FPGA_WR:
+ lng = (long)(((mcc_iorw_t *)param)->address);
+ lptr = ((unsigned long *)lng);
+ vptr = (void *)lptr;
+ if (copy_from_user( (void *)vptr, (((mcc_iorw_t *)param)->buf), (((mcc_iorw_t *)param)->nbytes))) {
+ printk("mcc2_ioctl: Failed during write to FPGA\n");
+ return -EFAULT;
+ }
+ break;
+
+
+
+
+
+ case MEM_MODR:
+ cptr = (char *)Mmap;
+ cptr += ((mcc_iorw_t *)param)->address;
+ if (copy_to_user( (((mcc_iorw_t *)param)->buf), (void *)cptr, (((mcc_iorw_t *)param)->nbytes))) {
+ printk("mcc2_ioctl: Failed during read of read-modify memory\n");
+ return -EFAULT;
+ }
+ break;
+
+ case MEM_MODW:
+ cptr = (char *)Mmap;
+ cptr += ((mcc_iorw_t *)param)->address;
+ if (copy_from_user( (void *)cptr, (((mcc_iorw_t *)param)->buf), (((mcc_iorw_t *)param)->nbytes))) {
+ printk("mcc2_ioctl: Failed during modify of read-modify memory\n");
+ return -EFAULT;
+ }
+ break;
+
+ case IO_PORTS:
+ break;
+ case SI_RAM_CTL1:
+ break;
+ case SI_RAM_CTL2:
+ if (copy_to_user( (void *)param, (siramctl_t *)&(Mmap->im_siramctl2), sizeof(siramctl_t))) {
+ printk("mcc2_ioctl: Failed to copy SI_RAM_CTL2 struct\n");
+ return -EFAULT;
+ }
+ break;
+
+
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ //if (copy_to_user((void *)param, &mode, sizeof(mode)))
+ printk("We are at the end ...\n");
+ return -EFAULT;
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////
+
+static ssize_t
+mcc2_open( struct inode *inode, struct file *file )
+{
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////
+
+static int
+mcc2_release( struct inode *inode, struct file *file )
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+
+
+
+
+
+#ifndef MODULE
+
+////////////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////////////
+
+long
+mcc2_init( long mem_start, long mem_end )
+{
+
+ if ((mcc2_major = register_chrdev(MCC_MAJOR, MCC_NAME, &mcc2_fops)))
+ printk("mcc2_init: Unable to get major for mcc2 device %d\n", MCC_MAJOR);
+ else {
+ //MPC82xxSiuInit();
+ MPC82xxCpmInit();
+ }
+ return mem_start;
+}
+
+#else
+
diff --git a/sys/src/9/ppc/mem.h b/sys/src/9/ppc/mem.h
new file mode 100755
index 000000000..dcaa0ad68
--- /dev/null
+++ b/sys/src/9/ppc/mem.h
@@ -0,0 +1,229 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+
+#ifdef ucuconf
+#include "ucu.h"
+#else
+#include "blast.h"
+#endif
+
+/*
+ * Sizes
+ */
+
+#define BI2BY 8 /* bits per byte */
+#define BI2WD 32 /* bits per word */
+#define BY2WD 4 /* bytes per word */
+#define BY2V 8 /* bytes per vlong */
+#define BY2PG 4096 /* bytes per page */
+#define WD2PG (BY2PG/BY2WD) /* words per page */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
+#define PGROUND(s) ROUND(s, BY2PG)
+#define CACHELINELOG 5
+#define CACHELINESZ (1<<CACHELINELOG)
+#define BLOCKALIGN CACHELINESZ
+
+#define MHz 1000000
+
+#define BY2PTE 8 /* bytes per pte entry */
+#define BY2PTEG 64 /* bytes per pte group */
+
+#define MAXMACH 1 /* max # cpus system can run */
+#define MACHSIZE BY2PG
+#define KSTACK 4096 /* Size of kernel stack */
+
+/*
+ * Time
+ */
+#define HZ 1000 /* clock frequency */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+
+/*
+ * Standard PPC Special Purpose Registers (OEA and VEA)
+ */
+#define DSISR 18
+#define DAR 19 /* Data Address Register */
+#define DEC 22 /* Decrementer */
+#define SDR1 25
+#define SRR0 26 /* Saved Registers (exception) */
+#define SRR1 27
+#define TBRL 268
+#define TBRU 269 /* Time base Upper/Lower (Reading) */
+#define SPRG0 272 /* Supervisor Private Registers */
+#define SPRG1 273
+#define SPRG2 274
+#define SPRG3 275
+#define SPRG4 276
+#define SPRG5 277
+#define SPRG6 278
+#define SPRG7 279
+#define ASR 280 /* Address Space Register */
+#define EAR 282 /* External Access Register (optional) */
+#define TBWU 284 /* Time base Upper/Lower (Writing) */
+#define TBWL 285
+#define PVR 287 /* Processor Version */
+#define IABR 1010 /* Instruction Address Breakpoint Register (optional) */
+#define DABR 1013 /* Data Address Breakpoint Register (optional) */
+#define FPECR 1022 /* Floating-Point Exception Cause Register (optional) */
+#define PIR 1023 /* Processor Identification Register (optional) */
+
+#define IBATU(i) (528+2*(i)) /* Instruction BAT register (upper) */
+#define IBATL(i) (529+2*(i)) /* Instruction BAT register (lower) */
+#define DBATU(i) (536+2*(i)) /* Data BAT register (upper) */
+#define DBATL(i) (537+2*(i)) /* Data BAT register (lower) */
+
+/*
+ * PPC604e-specific Special Purpose Registers (OEA)
+ */
+#define MMCR0 952 /* Monitor Control Register 0 */
+#define PMC1 953 /* Performance Monitor Counter 1 */
+#define PMC2 954 /* Performance Monitor Counter 2 */
+#define SIA 955 /* Sampled Instruction Address */
+#define MMCR1 956 /* Monitor Control Register 0 */
+#define PMC3 957 /* Performance Monitor Counter 3 */
+#define PMC4 958 /* Performance Monitor Counter 4 */
+#define SDA 959 /* Sampled Data Address */
+/*
+ * PPC603e-specific Special Purpose Registers
+ */
+#define DMISS 976 /* Data Miss Address Register */
+#define DCMP 977 /* Data Miss Address Register */
+#define HASH1 978
+#define HASH2 979
+#define IMISS 980 /* Instruction Miss Address Register */
+#define iCMP 981 /* Instruction Miss Address Register */
+#define RPA 982
+#define HID0 1008 /* Hardware Implementation Dependent Register 0 */
+#define HID1 1009 /* Hardware Implementation Dependent Register 1 */
+/*
+ * PowerQUICC II (MPC 8260) Special Purpose Registers
+ */
+#define HID2 1011 /* Hardware Implementation Dependent Register 2 */
+
+#define BIT(i) (1<<(31-(i))) /* Silly backwards register bit numbering scheme */
+#define SBIT(n) ((ushort)1<<(15-(n)))
+#define RBIT(b,n) (1<<(8*sizeof(n)-1-(b)))
+
+/*
+ * Bit encodings for Machine State Register (MSR)
+ */
+#define MSR_POW BIT(13) /* Enable Power Management */
+#define MSR_TGPR BIT(14) /* Temporary GPR Registers in use (603e) */
+#define MSR_ILE BIT(15) /* Interrupt Little-Endian enable */
+#define MSR_EE BIT(16) /* External Interrupt enable */
+#define MSR_PR BIT(17) /* Supervisor/User privilege */
+#define MSR_FP BIT(18) /* Floating Point enable */
+#define MSR_ME BIT(19) /* Machine Check enable */
+#define MSR_FE0 BIT(20) /* Floating Exception mode 0 */
+#define MSR_SE BIT(21) /* Single Step (optional) */
+#define MSR_BE BIT(22) /* Branch Trace (optional) */
+#define MSR_FE1 BIT(23) /* Floating Exception mode 1 */
+#define MSR_IP BIT(25) /* Exception prefix 0x000/0xFFF */
+#define MSR_IR BIT(26) /* Instruction MMU enable */
+#define MSR_DR BIT(27) /* Data MMU enable */
+#define MSR_PM BIT(29) /* Performance Monitor marked mode (604e specific) */
+#define MSR_RI BIT(30) /* Recoverable Exception */
+#define MSR_LE BIT(31) /* Little-Endian enable */
+/* SRR1 bits for TLB operations */
+#define MSR_SR0 0xf0000000 /* Saved bits from CR register */
+#define MSR_KEY BIT(12) /* Copy of Ks or Kp bit */
+#define MSR_IMISS BIT(13) /* It was an I miss */
+#define MSR_WAY BIT(14) /* TLB set to be replaced */
+#define MSR_STORE BIT(15) /* Miss caused by a store */
+
+/*
+ * Exception codes (trap vectors)
+ */
+#define CRESET 0x01
+#define CMCHECK 0x02
+#define CDSI 0x03
+#define CISI 0x04
+#define CEI 0x05
+#define CALIGN 0x06
+#define CPROG 0x07
+#define CFPU 0x08
+#define CDEC 0x09
+#define CSYSCALL 0x0C
+#define CTRACE 0x0D /* optional */
+#define CFPA 0x0E /* not implemented in 603e */
+
+/* PPC603e-specific: */
+#define CIMISS 0x10 /* Instruction TLB miss */
+#define CLMISS 0x11 /* Data load TLB miss */
+#define CSMISS 0x12 /* Data store TLB miss */
+#define CIBREAK 0x13
+#define CSMI 0x14
+
+/*
+ * Magic registers
+ */
+
+#define MACH 30 /* R30 is m-> */
+#define USER 29 /* R29 is up-> */
+
+
+/*
+ * virtual MMU
+ */
+#define PTEMAPMEM (1024*1024)
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 1984
+#define SSEGMAPSIZE 16
+#define PPN(x) ((x)&~(BY2PG-1))
+
+/*
+ * First pte word
+ */
+#define PTE0(v, vsid, h, va) (((v)<<31)|((vsid)<<7)|((h)<<6)|(((va)>>22)&0x3f))
+
+/*
+ * Second pte word; WIMG & PP(RW/RO) common to page table and BATs
+ */
+#define PTE1_R BIT(23)
+#define PTE1_C BIT(24)
+
+#define PTE1_W BIT(25)
+#define PTE1_I BIT(26)
+#define PTE1_M BIT(27)
+#define PTE1_G BIT(28)
+
+#define PTE1_RW BIT(30)
+#define PTE1_RO BIT(31)
+
+/* HID0 register bits */
+#define HID_ICE BIT(16)
+#define HID_DCE BIT(17)
+#define HID_ILOCK BIT(18)
+#define HID_DLOCK BIT(19)
+#define HID_ICFI BIT(20)
+#define HID_DCFI BIT(21)
+#define HID_IFEM BIT(24)
+
+/*
+ * Address spaces
+ */
+
+#define KZERO 0x80000000 /* base of kernel address space */
+#define KTZERO 0x80100000 /* first address in kernel text */
+#define UZERO 0 /* base of user address space */
+#define UTZERO (UZERO+BY2PG) /* first address in user text */
+#define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */
+#define TSTKTOP KZERO /* top of temporary stack */
+#define TSTKSIZ 100
+#define USTKSIZE (4*1024*1024) /* size of user stack */
+#define UREGSIZE ((8+40)*4)
+#define MACHADDR (KTZERO-MAXMACH*MACHSIZE)
+#define MACHPADDR (MACHADDR&~KZERO)
+#define MACHP(n) ((Mach *)(MACHADDR+(n)*MACHSIZE))
+
+#define isphys(x) (((ulong)x&KZERO)!=0)
+
+/*
+ * MPC8xx addresses
+ */
+#define INTMEM 0xf0000000
+#define IOMEM (INTMEM+0x10000)
+
+#define getpgcolor(a) 0
diff --git a/sys/src/9/ppc/mkfile b/sys/src/9/ppc/mkfile
new file mode 100755
index 000000000..37b2486c9
--- /dev/null
+++ b/sys/src/9/ppc/mkfile
@@ -0,0 +1,108 @@
+CONF=ucu
+CONFLIST=blast ucu
+
+loadaddr = 0x80100000
+
+objtype=power
+</$objtype/mkfile
+p=9
+
+DEVS=`{rc ../port/mkdevlist $CONF}
+
+PORT=\
+ alarm.$O\
+ alloc.$O\
+ allocb.$O\
+ auth.$O\
+ cache.$O\
+ chan.$O\
+ dev.$O\
+ edf.$O\
+ fault.$O\
+ latin1.$O\
+ log.$O\
+ rebootcmd.$O\
+ page.$O\
+ parse.$O\
+ pgrp.$O\
+ portclock.$O\
+ print.$O\
+ proc.$O\
+ qio.$O\
+ qlock.$O\
+ rdb.$O\
+ segment.$O\
+ swap.$O\
+ sysfile.$O\
+ sysproc.$O\
+ taslock.$O\
+ tod.$O\
+ xalloc.$O\
+
+OBJ=\
+ l.$O\
+ clock.$O\
+ main.$O\
+ mmu.$O\
+ random.$O\
+ trap.$O\
+ $CONF.root.$O\
+ $CONF.rootc.$O\
+ $DEVS\
+ $PORT\
+
+HFILES=\
+ dat.h\
+ errstr.h\
+ etherif.h\
+ fns.h\
+ init.h\
+ io.h\
+ mem.h\
+
+LIB=\
+ /$objtype/lib/libmemlayer.a\
+ /$objtype/lib/libmemdraw.a\
+ /$objtype/lib/libdraw.a\
+ /$objtype/lib/libc.a\
+ /$objtype/lib/libsec.a\
+
+ETHER=`{echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
+VGA=`{echo devvga.c screen.c vga*.c | sed 's/\.c/.'$O'/g'}
+SDEV=`{echo devsd.c sd*.c | sed 's/\.c/.'$O'/g'}
+
+CFLAGS=$CFLAGS -D$CONF'conf='$CONF
+AFLAGS=$AFLAGS -D$CONF'conf='$CONF
+
+it:V: $p$CONF
+
+9blast: $CONF.c $OBJ $LIB
+ $CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
+ $LD -o $target -T$loadaddr -R4096 -l $OBJ $CONF.$O $LIB
+ size $p$CONF
+
+9ucu: $CONF.c $OBJ $LIB
+ $CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
+ $LD -R0x1000 -H5 -o $target -T$loadaddr -l $OBJ $CONF.$O $LIB
+
+install:V: $p$CONF
+ cp $p$CONF /$objtype/$p$CONF
+
+<../boot/bootmkfile
+<../port/portmkfile
+<|../port/mkbootrules $CONF
+
+clock.$O devether.$O main.$O trap.$O: /$objtype/include/ureg.h
+
+%.$O: $HFILES
+
+$ETHER: etherif.h ../port/netif.h
+
+init.h: ../port/initcode.c init9.s
+ $CC ../port/initcode.c
+ $AS init9.s
+ $LD -l -s -R4 -o init.out init9.$O initcode.$O /power/lib/libc.a
+ {echo 'uchar initcode[]={'
+ strip < init.out | xd -1x |
+ sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+ echo '};'} > init.h
diff --git a/sys/src/9/ppc/mmu.c b/sys/src/9/ppc/mmu.c
new file mode 100755
index 000000000..73155e448
--- /dev/null
+++ b/sys/src/9/ppc/mmu.c
@@ -0,0 +1,282 @@
+#include <u.h>
+#include <ureg.h>
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+/*
+ * We have one page table per processor.
+ *
+ * Different processes are distinguished via the VSID field in
+ * the segment registers. As flushing the entire page table is an
+ * expensive operation, we implement an aging algorithm for
+ * mmu pids, with a background kproc to purge stale pids en mass.
+ *
+ * This needs modifications to run on a multiprocessor.
+ */
+
+static ulong ptabsize; /* number of bytes in page table */
+static ulong ptabmask; /* hash mask */
+
+/*
+ * VSID is 24 bits. 3 are required to distinguish segments in user
+ * space (kernel space only uses the BATs). pid 0 is reserved.
+ * The top 2 bits of the pid are used as a `color' for the background
+ * pid reclamation algorithm.
+ */
+
+enum {
+ PIDBASE = 1,
+ PIDBITS = 21,
+ COLBITS = 2,
+ PIDMAX = ((1<<PIDBITS)-1),
+ COLMASK = ((1<<COLBITS)-1),
+};
+
+#define VSID(pid, i) (((pid)<<3)|i)
+#define PIDCOLOR(pid) ((pid)>>(PIDBITS-COLBITS))
+#define PTECOL(color) PTE0(1, VSID(((color)<<(PIDBITS-COLBITS)), 0), 0, 0)
+
+void
+mmuinit(void)
+{
+ int lhash, mem, i;
+ ulong memsize;
+
+ memsize = conf.npage * BY2PG;
+ if(ptabsize == 0) {
+ /* heuristically size the hash table */
+ lhash = 10;
+ mem = (1<<23);
+ while(mem < memsize) {
+ lhash++;
+ mem <<= 1;
+ }
+ ptabsize = (1<<(lhash+6));
+ ptabmask = (1<<lhash)-1;
+ }
+ m->ptabbase = (ulong)xspanalloc(ptabsize, 0, ptabsize);
+ /* set page table base address */
+ putsdr1(PADDR(m->ptabbase) | (ptabmask>>10));
+ m->mmupid = PIDBASE;
+ m->sweepcolor = 0;
+ m->trigcolor = COLMASK;
+
+ for(i = 0; i < 16; i++)
+ putsr(i<<28, 0);
+}
+
+static int
+work(void*)
+{
+ return PIDCOLOR(m->mmupid) == m->trigcolor;
+}
+
+void
+mmusweep(void*)
+{
+ Proc *p;
+ int i, x, sweepcolor;
+ ulong *ptab, *ptabend, ptecol;
+
+ for(;;) {
+ if(PIDCOLOR(m->mmupid) != m->trigcolor)
+ sleep(&m->sweepr, work, nil);
+
+ sweepcolor = m->sweepcolor;
+ x = splhi();
+ p = proctab(0);
+ for(i = 0; i < conf.nproc; i++, p++)
+ if(PIDCOLOR(p->mmupid) == sweepcolor)
+ p->mmupid = 0;
+ splx(x);
+
+ ptab = (ulong*)m->ptabbase;
+ ptabend = (ulong*)(m->ptabbase+ptabsize);
+ ptecol = PTECOL(sweepcolor);
+ while(ptab < ptabend) {
+ if((*ptab & PTECOL(3)) == ptecol){
+ *ptab = 0;
+ }
+ ptab += 2;
+ }
+
+ m->sweepcolor = (sweepcolor+1) & COLMASK;
+ m->trigcolor = (m->trigcolor+1) & COLMASK;
+ }
+}
+
+int
+newmmupid(void)
+{
+ int pid, newcolor, i, x;
+ Proc *p;
+
+ pid = m->mmupid++;
+ if(m->mmupid > PIDMAX){
+ /* Used up all mmupids, start again from first. Flush the tlb
+ * to delete any entries with old pids remaining, then reassign
+ * all pids.
+ */
+ m->mmupid = PIDBASE;
+ x = splhi();
+ tlbflushall();
+ p = proctab(0);
+ for(i = 0; i < conf.nproc; i++, p++)
+ p->mmupid = 0;
+ splx(x);
+ wakeup(&m->sweepr);
+ }
+ newcolor = PIDCOLOR(m->mmupid);
+ if(newcolor != PIDCOLOR(pid)) {
+ if(newcolor == m->sweepcolor) {
+ /* desperation time. can't block here. punt to fault/putmmu */
+ print("newmmupid: %uld: no free mmu pids\n", up->pid);
+ if(m->mmupid == PIDBASE)
+ m->mmupid = PIDMAX;
+ else
+ m->mmupid--;
+ pid = 0;
+ }
+ else if(newcolor == m->trigcolor)
+ wakeup(&m->sweepr);
+ }
+ up->mmupid = pid;
+ return pid;
+}
+
+void
+flushmmu(void)
+{
+ int x;
+
+ x = splhi();
+ up->newtlb = 1;
+ mmuswitch(up);
+ splx(x);
+}
+
+/*
+ * called with splhi
+ */
+void
+mmuswitch(Proc *p)
+{
+ int i, mp;
+ ulong r;
+
+ if(p->kp) {
+ for(i = 0; i < 8; i++)
+ putsr(i<<28, 0);
+ return;
+ }
+
+ if(p->newtlb) {
+ p->mmupid = 0;
+ p->newtlb = 0;
+ }
+ mp = p->mmupid;
+ if(mp == 0)
+ mp = newmmupid();
+
+ for(i = 0; i < 8; i++){
+ r = VSID(mp, i)|BIT(1)|BIT(2);
+ putsr(i<<28, r);
+ }
+}
+
+void
+mmurelease(Proc* p)
+{
+ p->mmupid = 0;
+}
+
+void
+putmmu(ulong va, ulong pa, Page *pg)
+{
+ int mp;
+ char *ctl;
+ ulong *p, *ep, *q, pteg;
+ ulong vsid, hash;
+ ulong ptehi, x;
+ static ulong pva;
+
+ /*
+ * If mmupid is 0, mmuswitch/newmmupid was unable to assign us
+ * a pid, hence we faulted. Keep calling sched() until the mmusweep
+ * proc catches up, and we are able to get a pid.
+ */
+ while((mp = up->mmupid) == 0)
+ sched();
+
+ vsid = VSID(mp, va>>28);
+ hash = (vsid ^ ((va>>12)&0xffff)) & ptabmask;
+ ptehi = PTE0(1, vsid, 0, va);
+ pteg = m->ptabbase + BY2PTEG*hash;
+
+ p = (ulong*)pteg;
+ ep = (ulong*)(pteg+BY2PTEG);
+ q = nil;
+
+ while(p < ep) {
+ x = p[0];
+ if(x == ptehi) {
+ q = p;
+ break;
+ }
+ if(q == nil && (x & BIT(0)) == 0)
+ q = p;
+ p += 2;
+ }
+ if(q == nil) {
+ q = (ulong*)(pteg+m->slotgen);
+ m->slotgen = (m->slotgen + BY2PTE) & (BY2PTEG-1);
+ }
+
+ if (q[0] != ptehi || q[1] != pa){
+ tlbflush(va);
+ m->tlbpurge++;
+ }
+ q[0] = ptehi;
+ q[1] = pa;
+
+ ctl = &pg->cachectl[m->machno];
+ switch(*ctl) {
+ case PG_NEWCOL:
+ default:
+ panic("putmmu: %d\n", *ctl);
+ break;
+ case PG_TXTFLUSH:
+ dcflush((void*)pg->va, BY2PG);
+ icflush((void*)pg->va, BY2PG);
+ *ctl = PG_NOFLUSH;
+ break;
+ case PG_NOFLUSH:
+ break;
+ }
+
+}
+
+void
+checkmmu(ulong, ulong)
+{
+}
+
+void
+countpagerefs(ulong*, int)
+{
+}
+
+/*
+ * Return the number of bytes that can be accessed via KADDR(pa).
+ * If pa is not a valid argument to KADDR, return 0.
+ */
+ulong
+cankaddr(ulong pa)
+{
+ if(pa >= -KZERO)
+ return 0;
+ return -KZERO - pa;
+}
+
diff --git a/sys/src/9/ppc/msaturn.c b/sys/src/9/ppc/msaturn.c
new file mode 100755
index 000000000..94aa1fb17
--- /dev/null
+++ b/sys/src/9/ppc/msaturn.c
@@ -0,0 +1,190 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "msaturn.h"
+
+enum {
+ Isr = Saturn + 0x0400,
+ Ipol = Saturn + 0x0404,
+ Issr = Saturn + 0x0500,
+ Ier = Saturn + 0x0504,
+ Ipri = Saturn + 0x0600,
+ Ithresh = Saturn + 0x0706,
+#define Iar Ithresh
+};
+
+enum{
+ Syscfg = Saturn + 0x0100,
+};
+
+static uchar intprio[] = {
+ Vecuart0, // uart 0
+ Vecunused, // uart 1
+ Vecunused, // sint
+ Vectimer0, // timer 0
+ Vecunused, // timer 1
+ Vecether, // ethernet
+ Vecunused, // tea
+ Vecunused, // irq0
+ Vecunused, // irq1
+ Vecunused, // irq2
+ Vecunused, // irq3
+ Vecunused, // irq4
+ Vecunused, // irq5
+ Vecunused, // irq6
+ Vecunused, // irq7
+ Vecunused, // irq8
+};
+
+void
+intend(int)
+{
+}
+
+void
+hwintrinit(void)
+{
+ int i;
+
+ *(ulong*)Ier=0;
+
+ for(i=0; i<nelem(intprio)/2; i++)
+ ((uchar*)Ipri)[i] = (intprio[2*i]<<4)|intprio[2*i+1];
+}
+
+int
+vectorenable(Vctl*v)
+{
+ int i;
+
+ for(i=0; i<nelem(intprio); i++)
+ if(v->irq==intprio[i]){
+ *(ulong*)Ier |= 1<<(31-i);
+ return v->irq;
+ }
+ print("intrenable: cannot enable intr %d\n", v->irq);
+ return -1;
+}
+
+void
+vectordisable(Vctl*v)
+{
+ int i;
+
+ for(i=0; i<nelem(intprio); i++)
+ if(v->irq==intprio[i]){
+ *(ulong*)Ier &= ~(1<<(31-i));
+ return;
+ }
+}
+
+int
+intvec(void)
+{
+ ushort iar;
+ int i;
+
+ iar = *(ushort*)Iar; // push(prio) onto stack
+ for(i=0; i<nelem(intprio); i++)
+ if(iar==intprio[i])
+ return iar;
+
+ iprint("saturnint: no vector %d\n", iar);
+ intack();
+ return -1;
+}
+
+void
+intack(void)
+{
+ *(ushort*)Ithresh = 0; // pop(prio) stack
+}
+
+void
+machinit(void)
+{
+ int rrate;
+ ulong hid;
+ extern char* plan9inistr;
+ ulong l2cr;
+
+ memset(m, 0, sizeof(*m));
+ m->cputype = getpvr()>>16;
+ m->imap = (Imap*)INTMEM;
+
+ m->loopconst = 1096;
+
+ rrate = (*(ushort*)Syscfg >> 6) & 3;
+ switch(rrate){
+ case 0:
+ m->bushz = 66666666;
+ break;
+ case 1:
+ m->bushz = 83333333;
+ break;
+ case 2:
+ m->bushz = 100000000;
+ break;
+ case 3:
+ m->bushz = 133333333;
+ break;
+ }
+
+ if(getpll() == 0x80000000)
+ m->cpuhz = 300000000;
+ else
+ m->cpuhz = 200000000; /* 750FX? */
+ m->cyclefreq = m->bushz / 4;
+
+ active.machs = 1;
+ active.exiting = 0;
+
+ putmsr(getmsr() | MSR_ME);
+
+ dcflush((void*)KZERO, 0x2000000);
+ l2cr = getl2cr();
+ putl2cr(l2cr|BIT(10));
+
+ kfpinit();
+
+ hid=gethid0();
+ hid |= BIT(28)|BIT(26)|BIT(24);
+ puthid0(hid);
+
+ plan9inistr =
+ "console=0\n"
+ "ether0=type=saturn\n"
+ "fs=135.104.9.42\n"
+ "auth=135.104.9.7\n"
+ "authdom=cs.bell-labs.com\n"
+ "sys=ucu\n"
+ "ntp=135.104.9.52\n";
+}
+
+void
+sharedseginit(void)
+{
+}
+
+void
+trapinit(void)
+{
+ int i;
+
+ for(i = 0x0; i < 0x2000; i += 0x100)
+ sethvec(i, trapvec);
+
+ dcflush(KADDR(0), 0x2000);
+ icflush(KADDR(0), 0x2000);
+
+ putmsr(getmsr() & ~MSR_IP);
+}
+
+void
+reboot(void*, void*, ulong)
+{
+}
diff --git a/sys/src/9/ppc/msaturn.h b/sys/src/9/ppc/msaturn.h
new file mode 100755
index 000000000..0beab872b
--- /dev/null
+++ b/sys/src/9/ppc/msaturn.h
@@ -0,0 +1,7 @@
+enum {
+ Vecuart0 = 1,
+ Vecuart1 = Vecuart0 + 1,
+ Vectimer0 = 0,
+ Vecether = 3,
+ Vecunused = 15,
+};
diff --git a/sys/src/9/ppc/mtx.c b/sys/src/9/ppc/mtx.c
new file mode 100755
index 000000000..aaf8ebd7b
--- /dev/null
+++ b/sys/src/9/ppc/mtx.c
@@ -0,0 +1,11 @@
+/*
+ * mtx specific stuff:
+ * Interrupt handling
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "io.h"
+#include "mtx.h"
+#include "fns.h"
diff --git a/sys/src/9/ppc/random.c b/sys/src/9/ppc/random.c
new file mode 100755
index 000000000..3c204b8d1
--- /dev/null
+++ b/sys/src/9/ppc/random.c
@@ -0,0 +1,138 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+
+struct Rb
+{
+ QLock;
+ Rendez producer;
+ Rendez consumer;
+ ulong randomcount;
+ uchar buf[1024];
+ uchar *ep;
+ uchar *rp;
+ uchar *wp;
+ uchar next;
+ uchar wakeme;
+ ushort bits;
+ ulong randn;
+} rb;
+
+static int
+rbnotfull(void*)
+{
+ int i;
+
+ i = rb.rp - rb.wp;
+ return i != 1 && i != (1 - sizeof(rb.buf));
+}
+
+static int
+rbnotempty(void*)
+{
+ return rb.wp != rb.rp;
+}
+
+static void
+genrandom(void*)
+{
+ up->basepri = PriNormal;
+ up->priority = up->basepri;
+
+ for(;;){
+ for(;;)
+ if(++rb.randomcount > 100000)
+ break;
+ if(anyhigher())
+ sched();
+ if(!rbnotfull(0))
+ sleep(&rb.producer, rbnotfull, 0);
+ }
+}
+
+/*
+ * produce random bits in a circular buffer
+ */
+static void
+randomclock(void)
+{
+ if(rb.randomcount == 0 || !rbnotfull(0))
+ return;
+
+ rb.bits = (rb.bits<<2) ^ rb.randomcount;
+ rb.randomcount = 0;
+
+ rb.next++;
+ if(rb.next != 8/2)
+ return;
+ rb.next = 0;
+
+ *rb.wp ^= rb.bits;
+ if(rb.wp+1 == rb.ep)
+ rb.wp = rb.buf;
+ else
+ rb.wp = rb.wp+1;
+
+ if(rb.wakeme)
+ wakeup(&rb.consumer);
+}
+
+void
+randominit(void)
+{
+ addclock0link(randomclock, 1000/HZ);
+ rb.ep = rb.buf + sizeof(rb.buf);
+ rb.rp = rb.wp = rb.buf;
+ kproc("genrandom", genrandom, 0);
+}
+
+/*
+ * consume random bytes from a circular buffer
+ */
+ulong
+randomread(void *xp, ulong n)
+{
+ uchar *e, *p;
+ ulong x;
+
+ p = xp;
+
+ if(waserror()){
+ qunlock(&rb);
+ nexterror();
+ }
+
+ qlock(&rb);
+ for(e = p + n; p < e; ){
+ if(rb.wp == rb.rp){
+ rb.wakeme = 1;
+ wakeup(&rb.producer);
+ sleep(&rb.consumer, rbnotempty, 0);
+ rb.wakeme = 0;
+ continue;
+ }
+
+ /*
+ * beating clocks will be precictable if
+ * they are synchronized. Use a cheap pseudo
+ * random number generator to obscure any cycles.
+ */
+ x = rb.randn*1103515245 ^ *rb.rp;
+ *p++ = rb.randn = x;
+
+ if(rb.rp+1 == rb.ep)
+ rb.rp = rb.buf;
+ else
+ rb.rp = rb.rp+1;
+ }
+ qunlock(&rb);
+ poperror();
+
+ wakeup(&rb.producer);
+
+ return n;
+}
diff --git a/sys/src/9/ppc/saturntimer.c b/sys/src/9/ppc/saturntimer.c
new file mode 100755
index 000000000..2b9ef66cc
--- /dev/null
+++ b/sys/src/9/ppc/saturntimer.c
@@ -0,0 +1,95 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "msaturn.h"
+
+enum {
+ Timer_ctrl = Saturn + 0x0106,
+ Timer0_load = Saturn + 0x0200,
+ Timer0_cnt = Saturn + 0x0204,
+ Timer1_load = Saturn + 0x0300,
+ Timer1_cnt = Saturn + 0x0304,
+
+ T0_event = RBIT(13, ushort),
+ T0_ie = RBIT(14, ushort),
+ T0_cen = RBIT(15, ushort),
+ T1_event = RBIT(5, ushort),
+ T1_ie = RBIT(6, ushort),
+ T1_cen = RBIT(7, ushort),
+};
+
+static ulong ticks;
+static Lock tlock;
+static ushort timer_ctl;
+
+void
+saturntimerintr(Ureg *u, void*)
+{
+ ushort ctl = *(ushort*)Timer_ctrl, v = 0;
+
+ if(ctl&T1_event){
+ v = T1_event;
+ ticks++;
+ }
+
+ *(ushort*)Timer_ctrl = timer_ctl|T0_event|v;
+ intack();
+ timerintr(u, 0);
+}
+
+void
+timerinit(void)
+{
+ *(ushort*)Timer_ctrl = 0;
+ *(ulong*)Timer0_load = m->bushz / HZ;
+ *(ulong*)Timer0_cnt = m->bushz / HZ;
+ *(ulong*)Timer1_load = m->bushz;
+ *(ulong*)Timer1_cnt = m->bushz;
+
+ intrenable(Vectimer0, saturntimerintr, nil, "timer");
+
+ timer_ctl = T0_cen|T0_ie|T1_cen;
+ *(ushort*)Timer_ctrl = timer_ctl;
+}
+
+uvlong
+fastticks(uvlong *hz)
+{
+ assert(*(ushort*)Timer_ctrl&T1_cen);
+ if(*(ushort*)Timer_ctrl&T1_event){
+ *(ushort*)Timer_ctrl = timer_ctl|T1_event;
+ ticks++;
+ }
+
+ if (hz)
+ *hz = m->bushz;
+
+ return (uvlong)ticks*m->bushz+(uvlong)(m->bushz-*(ulong*)Timer1_cnt);
+}
+
+void
+timerset(uvlong next)
+{
+ ulong offset;
+ uvlong now;
+
+ ilock(&tlock);
+ *(ushort*)Timer_ctrl = T1_cen;
+
+ now = fastticks(nil);
+ offset = next - now;
+ if((long)offset < 10000)
+ offset = 10000;
+ else if(offset > m->bushz)
+ offset = m->bushz;
+
+ *(ulong*)Timer0_cnt = offset;
+ *(ushort*)Timer_ctrl = timer_ctl;
+ assert(*(ushort*)Timer_ctrl & T1_cen);
+ iunlock(&tlock);
+}
+
diff --git a/sys/src/9/ppc/trap.c b/sys/src/9/ppc/trap.c
new file mode 100755
index 000000000..ceacce8a8
--- /dev/null
+++ b/sys/src/9/ppc/trap.c
@@ -0,0 +1,857 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "ureg.h"
+#include "../port/error.h"
+#include "tos.h"
+#include <trace.h>
+
+static Lock vctllock;
+Vctl *vctl[256];
+
+void
+intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
+{
+ int vno;
+ Vctl *v;
+
+ if(f == nil){
+ print("intrenable: nil handler for %d for %s\n",
+ irq, name);
+ return;
+ }
+
+ v = xalloc(sizeof(Vctl));
+ v->isintr = 1;
+ v->irq = irq;
+ v->f = f;
+ v->a = a;
+ strncpy(v->name, name, KNAMELEN-1);
+ v->name[KNAMELEN-1] = 0;
+
+ ilock(&vctllock);
+ vno = vectorenable(v);
+ if(vno == -1){
+ iunlock(&vctllock);
+ print("intrenable: couldn't enable irq %d for %s\n",
+ irq, v->name);
+ xfree(v);
+ return;
+ }
+ v->next = vctl[vno];
+ vctl[vno] = v;
+ iunlock(&vctllock);
+}
+
+void
+intrdisable(int irq, void (*f)(Ureg *, void *), void *a, char *name)
+{
+ Vctl **pv, *v;
+
+ ilock(&vctllock);
+ pv = &vctl[irq];
+ while (*pv &&
+ ((*pv)->irq != irq || (*pv)->f != f || (*pv)->a != a ||
+ strcmp((*pv)->name, name)))
+ pv = &((*pv)->next);
+
+ if(*pv == nil){
+ print("intrdisable: irq %d not found\n", irq);
+ iunlock(&vctllock);
+ return;
+ }
+
+ v = *pv;
+ *pv = (*pv)->next; /* Link out the entry */
+
+ if(vctl[irq] == nil)
+ vectordisable(v);
+ iunlock(&vctllock);
+ xfree(v);
+}
+
+void syscall(Ureg*);
+void noted(Ureg*, ulong);
+static void _dumpstack(Ureg*);
+
+char *excname[] =
+{
+ "reserved 0",
+ "system reset",
+ "machine check",
+ "data access",
+ "instruction access",
+ "external interrupt",
+ "alignment",
+ "program exception",
+ "floating-point unavailable",
+ "decrementer",
+ "reserved A",
+ "reserved B",
+ "system call",
+ "trace trap",
+ "floating point assist",
+ "reserved F",
+ "reserved 10",
+ "data load translation miss",
+ "data store translation miss",
+ "instruction address breakpoint",
+ "system management interrupt",
+};
+
+char *fpcause[] =
+{
+ "inexact operation",
+ "division by zero",
+ "underflow",
+ "overflow",
+ "invalid operation",
+};
+char *fpexcname(Ureg*, ulong, char*);
+#define FPEXPMASK 0xfff80300 /* Floating exception bits in fpscr */
+
+
+char *regname[]={
+ "CAUSE", "SRR1",
+ "PC", "GOK",
+ "LR", "CR",
+ "XER", "CTR",
+ "R0", "R1",
+ "R2", "R3",
+ "R4", "R5",
+ "R6", "R7",
+ "R8", "R9",
+ "R10", "R11",
+ "R12", "R13",
+ "R14", "R15",
+ "R16", "R17",
+ "R18", "R19",
+ "R20", "R21",
+ "R22", "R23",
+ "R24", "R25",
+ "R26", "R27",
+ "R28", "R29",
+ "R30", "R31",
+ "DCMP", "ICMP",
+ "DMISS", "IMISS",
+ "HASH1", "HASH2",
+ "DAR", "DSISR",
+};
+
+void
+kexit(Ureg*)
+{
+ uvlong t;
+ Tos *tos;
+
+ /* precise time accounting, kernel exit */
+ tos = (Tos*)(USTKTOP-sizeof(Tos));
+ cycles(&t);
+ tos->kcycles += t - up->kentry;
+ tos->pcycles = up->pcycles;
+ tos->pid = up->pid;
+}
+
+void
+trap(Ureg *ureg)
+{
+ int ecode, user;
+ char buf[ERRMAX], *s;
+ extern FPsave initfp;
+
+ ecode = (ureg->cause >> 8) & 0xff;
+ user = (ureg->srr1 & MSR_PR) != 0;
+ if(user){
+ cycles(&up->kentry);
+ up->dbgreg = ureg;
+ }
+ if(ureg->status & MSR_RI == 0)
+ print("double fault?: ecode = %d\n", ecode);
+
+ switch(ecode) {
+ case CEI:
+ m->intr++;
+ intr(ureg);
+ break;
+ case CDEC:
+ clockintr(ureg);
+ break;
+ case CDSI:
+ m->pfault++;
+ if (up == nil){
+ dumpregs(ureg);
+ panic("kernel fault");
+ }
+ up->mmureg = ureg;
+ faultpower(ureg, ureg->dar, (ureg->dsisr & BIT(6)) == 0);
+ break;
+ case CISI:
+ m->pfault++;
+ if (up == nil){
+ dumpregs(ureg);
+ panic("kernel fault");
+ }
+ up->mmureg = ureg;
+ faultpower(ureg, ureg->pc, 1);
+ break;
+ case CIMISS: /* instruction miss */
+ if (up == nil){
+ dumpregs(ureg);
+ panic("kernel fault");
+ }
+ up->mmureg = ureg;
+ faultpower(ureg, ureg->imiss, 1);
+ break;
+ case CLMISS: /* data load miss */
+ if (up == nil){
+ dumpregs(ureg);
+ panic("kernel fault");
+ }
+ up->mmureg = ureg;
+ faultpower(ureg, ureg->dmiss, 1);
+ break;
+ case CSMISS: /* data store miss */
+ if (up == nil){
+ dumpregs(ureg);
+ panic("kernel fault");
+ }
+ up->mmureg = ureg;
+ faultpower(ureg, ureg->dmiss, 0);
+ break;
+
+ case CSYSCALL:
+ if(!user)
+ panic("syscall in kernel: srr1 0x%4.4luX\n", ureg->srr1);
+ syscall(ureg);
+ if (up->delaysched){
+ sched();
+ splhi();
+ }
+ kexit(ureg);
+ return; /* syscall() calls notify itself, don't do it again */
+
+ case CFPU:
+ if(!user || up == nil) {
+ dumpregs(ureg);
+ panic("floating point in kernel");
+ }
+ switch(up->fpstate){
+ case FPinit:
+ fprestore(&initfp);
+ up->fpstate = FPactive;
+ break;
+ case FPinactive:
+ fprestore(&up->fpsave);
+ up->fpstate = FPactive;
+ break;
+ case FPactive:
+ print("up->fpstate %d\n", up->fpstate);
+ delay(100);
+ dumpregs(ureg);
+ delay(200);
+ panic("fpstate");
+ break;
+ default:
+ if(user){
+ spllo();
+ sprint(buf, "sys: floating point in note handler:");
+ postnote(up, 1, buf, NDebug);
+ break;
+ }
+ panic("kernel fpstate illegal");
+ }
+ ureg->srr1 |= MSR_FP;
+ break;
+ case CPROG:
+ if(ureg->status & (1<<19))
+ s = "floating point exception";
+ else if(ureg->status & (1<<18))
+ s = "illegal instruction";
+ else if(ureg->status & (1<<17))
+ s = "privileged instruction";
+ else
+ s = "undefined program exception";
+ if(user){
+ spllo();
+ sprint(buf, "sys: trap: %s", s);
+ postnote(up, 1, buf, NDebug);
+ break;
+ }
+ dumpregs(ureg);
+ panic(s);
+ break;
+ default:
+ if(ecode < nelem(excname) && user){
+ spllo();
+ sprint(buf, "sys: trap: %s", excname[ecode]);
+ postnote(up, 1, buf, NDebug);
+ break;
+ }
+ dumpregs(ureg);
+ if(ecode < nelem(excname))
+ panic("%s", excname[ecode]);
+ panic("unknown trap/intr: %d\n", ecode);
+ }
+
+ /* restoreureg must execute at high IPL */
+ splhi();
+
+ /* delaysched set because we held a lock or because our quantum ended */
+ if(up && up->delaysched && ecode == CDEC){
+ sched();
+ splhi();
+ }
+
+ if(user) {
+ if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
+ postnote(up, 1, buf, NDebug);
+ }
+ notify(ureg);
+ if(up->fpstate != FPactive)
+ ureg->srr1 &= ~MSR_FP;
+ kexit(ureg);
+ }
+}
+
+void
+faultpower(Ureg *ureg, ulong addr, int read)
+{
+ int user, insyscall, n;
+ char buf[ERRMAX];
+
+ user = (ureg->srr1 & MSR_PR) != 0;
+ insyscall = up->insyscall;
+ up->insyscall = 1;
+ n = fault(addr, read);
+ if(n < 0){
+ if(!user){
+ dumpregs(ureg);
+ panic("fault: 0x%lux", addr);
+ }
+ sprint(buf, "sys: trap: fault %s addr=0x%lux", read? "read" : "write", addr);
+ postnote(up, 1, buf, NDebug);
+ }
+ up->insyscall = insyscall;
+}
+
+void
+sethvec(int v, void (*r)(void))
+{
+ ulong *vp, pa, o;
+
+ vp = KADDR(v);
+ vp[0] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */
+ vp[1] = 0x7c0802a6; /* MOVW LR, R0 */
+ vp[2] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */
+ pa = PADDR(r);
+ o = pa >> 25;
+ if(o != 0 && o != 0x7F){
+ /* a branch too far */
+ vp[3] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */
+ vp[4] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
+ vp[5] = 0x7c0803a6; /* MOVW R0, LR */
+ vp[6] = 0x4e800021; /* BL (LR) */
+ }else
+ vp[3] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */
+}
+
+void
+setmvec(int v, void (*r)(void), void (*t)(void))
+{
+ ulong *vp, pa, o, n;
+
+ vp = KADDR(v);
+ n = 0;
+ vp[n++] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */
+ vp[n++] = 0x7c0802a6; /* MOVW LR, R0 */
+ vp[n++] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */
+ pa = PADDR(r);
+ o = pa >> 25;
+ if(o != 0 && o != 0x7F){
+ /* a branch too far */
+ vp[n++] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */
+ vp[n++] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
+ vp[n++] = 0x7c0803a6; /* MOVW R0, LR */
+ vp[n++] = 0x4e800021; /* BL (LR) */
+ }else
+ vp[n++] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */
+ pa = PADDR(t);
+ o = pa >> 25;
+ if(o != 0 && o != 0x7F){
+ /* a branch too far */
+ vp[n++] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */
+ vp[n++] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
+ vp[n++] = 0x7c0803a6; /* MOVW R0, LR */
+ vp[n] = 0x4e800021; /* BL (LR) */
+ }else
+ vp[n] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */
+}
+
+char*
+fpexcname(Ureg *ur, ulong fpscr, char *buf)
+{
+ int i;
+ char *s;
+ ulong fppc;
+
+ fppc = ur->pc;
+ s = 0;
+ fpscr >>= 3; /* trap enable bits */
+ fpscr &= (fpscr>>22); /* anded with exceptions */
+ for(i=0; i<5; i++)
+ if(fpscr & (1<<i))
+ s = fpcause[i];
+ if(s == 0)
+ return "no floating point exception";
+ sprint(buf, "%s fppc=0x%lux", s, fppc);
+ return buf;
+}
+
+/*
+ * Fill in enough of Ureg to get a stack trace, and call a function.
+ * Used by debugging interface rdb.
+ */
+
+static void
+getpcsp(ulong *pc, ulong *sp)
+{
+ *pc = getcallerpc(&pc);
+ *sp = (ulong)&pc-4;
+}
+
+void
+callwithureg(void (*fn)(Ureg*))
+{
+ Ureg ureg;
+
+ getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
+ ureg.lr = getcallerpc(&fn);
+ fn(&ureg);
+}
+
+static void
+_dumpstack(Ureg *ureg)
+{
+ ulong l, sl, el, v;
+ int i;
+
+ l = (ulong)&l;
+ if(up == 0){
+ el = (ulong)m+BY2PG;
+ sl = el-KSTACK;
+ }
+ else{
+ sl = (ulong)up->kstack;
+ el = sl + KSTACK;
+ }
+ if(l > el || l < sl){
+ el = (ulong)m+BY2PG;
+ sl = el-KSTACK;
+ }
+ if(l > el || l < sl)
+ return;
+ print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->lr);
+ i = 0;
+ for(; l < el; l += 4){
+ v = *(ulong*)l;
+ if(KTZERO < v && v < (ulong)etext){
+ print("%.8lux=%.8lux ", l, v);
+ if(i++ == 4){
+ print("\n");
+ i = 0;
+ }
+ }
+ }
+}
+
+void
+dumpstack(void)
+{
+ callwithureg(_dumpstack);
+}
+
+void
+dumpregs(Ureg *ur)
+{
+ int i;
+ ulong *l;
+
+ if(up) {
+ print("registers for %s %ld\n", up->text, up->pid);
+ if(ur->srr1 & MSR_PR == 0)
+ if(ur->usp < (ulong)up->kstack || ur->usp > (ulong)up->kstack+KSTACK)
+ print("invalid stack ptr\n");
+ }
+ else
+ print("registers for kernel\n");
+
+ for(i=0; i<16; i+=2)
+ print("sr[%x]\t0x%.8lux\tsr[%x]\t0x%.8lux\n", i, getsr(i<<28), i+1, getsr((i+1)<<28));
+ l = &ur->cause;
+ for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
+ print("%s\t0x%.8lux\t%s\t0x%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
+ delay(500);
+}
+
+static void
+linkproc(void)
+{
+ spllo();
+ (*up->kpfun)(up->kparg);
+ pexit("", 0);
+}
+
+void
+kprocchild(Proc *p, void (*func)(void*), void *arg)
+{
+ p->sched.pc = (ulong)linkproc;
+ p->sched.sp = (ulong)p->kstack+KSTACK;
+
+ p->kpfun = func;
+ p->kparg = arg;
+}
+
+/*
+ * called in sysfile.c
+ */
+void
+evenaddr(ulong addr)
+{
+ if(addr & 3){
+ postnote(up, 1, "sys: odd address", NDebug);
+ error(Ebadarg);
+ }
+}
+
+long
+execregs(ulong entry, ulong ssize, ulong nargs)
+{
+ ulong *sp;
+ Ureg *ureg;
+
+ sp = (ulong*)(USTKTOP - ssize);
+ *--sp = nargs;
+
+ ureg = up->dbgreg;
+ ureg->usp = (ulong)sp;
+ ureg->pc = entry;
+ ureg->srr1 &= ~MSR_FP; /* disable floating point */
+ up->fpstate = FPinit;
+ return USTKTOP-sizeof(Tos); /* address of kernel/user shared data */
+}
+
+void
+forkchild(Proc *p, Ureg *ur)
+{
+ Ureg *cur;
+
+ p->sched.sp = (ulong)p->kstack+KSTACK-UREGSIZE;
+ p->sched.pc = (ulong)forkret;
+
+ cur = (Ureg*)(p->sched.sp+2*BY2WD);
+ memmove(cur, ur, sizeof(Ureg));
+ cur->r3 = 0;
+
+ /* Things from bottom of syscall we never got to execute */
+ p->psstate = 0;
+ p->insyscall = 0;
+}
+
+ulong
+userpc(void)
+{
+ Ureg *ureg;
+
+ ureg = (Ureg*)up->dbgreg;
+ return ureg->pc;
+}
+
+
+/* This routine must save the values of registers the user is not
+ * permitted to write from devproc and then restore the saved values
+ * before returning
+ */
+void
+setregisters(Ureg *xp, char *pureg, char *uva, int n)
+{
+ ulong status;
+
+ status = xp->status;
+ memmove(pureg, uva, n);
+ xp->status = status;
+}
+
+/* Give enough context in the ureg to produce a kernel stack for
+ * a sleeping process
+ */
+void
+setkernur(Ureg* ureg, Proc* p)
+{
+ ureg->pc = p->sched.pc;
+ ureg->sp = p->sched.sp+4;
+}
+
+ulong
+dbgpc(Proc *p)
+{
+ Ureg *ureg;
+
+ ureg = p->dbgreg;
+ if(ureg == 0)
+ return 0;
+
+ return ureg->pc;
+}
+
+/*
+ * system calls
+ */
+#include "../port/systab.h"
+
+/* TODO: make this trap a separate asm entry point, like on other RISC architectures */
+void
+syscall(Ureg* ureg)
+{
+ int i;
+ char *e;
+ long ret;
+ ulong sp, scallnr;
+
+ m->syscall++;
+ up->insyscall = 1;
+ up->pc = ureg->pc;
+ up->dbgreg = ureg;
+
+ if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
+ print("fpstate check, entry syscall\n");
+ delay(200);
+ dumpregs(ureg);
+ print("fpstate check, entry syscall\n");
+ }
+
+ scallnr = ureg->r3;
+ up->scallnr = ureg->r3;
+ if(scallnr == RFORK && up->fpstate == FPactive){
+ fpsave(&up->fpsave);
+ up->fpstate = FPinactive;
+ }
+ spllo();
+
+ sp = ureg->usp;
+ up->nerrlab = 0;
+ ret = -1;
+ if(!waserror()){
+ if(scallnr >= nsyscall || systab[scallnr] == nil){
+ pprint("bad sys call number %d pc %lux\n", scallnr, ureg->pc);
+ postnote(up, 1, "sys: bad sys call", NDebug);
+ error(Ebadarg);
+ }
+
+ if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
+ validaddr(sp, sizeof(Sargs)+BY2WD, 0);
+
+ up->s = *((Sargs*)(sp+BY2WD));
+ up->psstate = sysctab[scallnr];
+
+ ret = systab[scallnr](up->s.args);
+ poperror();
+ }else{
+ /* failure: save the error buffer for errstr */
+ e = up->syserrstr;
+ up->syserrstr = up->errstr;
+ up->errstr = e;
+ }
+ if(up->nerrlab){
+ print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
+ print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr);
+ for(i = 0; i < NERR; i++)
+ print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
+ panic("error stack");
+ }
+
+ up->insyscall = 0;
+ up->psstate = 0;
+
+ /*
+ * Put return value in frame. On the x86 the syscall is
+ * just another trap and the return value from syscall is
+ * ignored. On other machines the return value is put into
+ * the results register by caller of syscall.
+ */
+ ureg->r3 = ret;
+
+ if(scallnr == NOTED)
+ noted(ureg, *(ulong*)(sp+BY2WD));
+
+ /* restoreureg must execute at high IPL */
+ splhi();
+ if(scallnr!=RFORK)
+ notify(ureg);
+
+ if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
+ print("fpstate check, exit syscall nr %lud, pid %lud\n", scallnr, up->pid);
+ dumpregs(ureg);
+ }
+ if(up->fpstate != FPactive)
+ ureg->srr1 &= ~MSR_FP;
+}
+
+/*
+ * Call user, if necessary, with note.
+ * Pass user the Ureg struct and the note on his stack.
+ */
+int
+notify(Ureg* ur)
+{
+ int l;
+ ulong s, sp;
+ Note *n;
+
+ if(up->procctl)
+ procctl(up);
+ if(up->nnote == 0)
+ return 0;
+
+ s = spllo();
+ qlock(&up->debug);
+ up->notepending = 0;
+ n = &up->note[0];
+ if(strncmp(n->msg, "sys:", 4) == 0){
+ l = strlen(n->msg);
+ if(l > ERRMAX-15) /* " pc=0x12345678\0" */
+ l = ERRMAX-15;
+ sprint(n->msg+l, " pc=0x%.8lux", ur->pc);
+ }
+
+ if(n->flag!=NUser && (up->notified || up->notify==0)){
+ if(n->flag == NDebug)
+ pprint("suicide: %s\n", n->msg);
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag!=NDebug);
+ }
+
+ if(up->notified) {
+ qunlock(&up->debug);
+ splhi();
+ return 0;
+ }
+
+ if(!up->notify) {
+ qunlock(&up->debug);
+ pexit(n->msg, n->flag!=NDebug);
+ }
+
+ if(up->fpstate == FPactive){
+ fpsave(&up->fpsave);
+ up->fpstate = FPinactive;
+ }
+ up->fpstate |= FPillegal;
+
+ sp = ur->usp & ~(BY2V-1);
+ sp -= sizeof(Ureg);
+
+ if(!okaddr((ulong)up->notify, BY2WD, 0) ||
+ !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)) {
+ pprint("suicide: bad address or sp in notify\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+
+ memmove((Ureg*)sp, ur, sizeof(Ureg));
+ *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
+ up->ureg = (void*)sp;
+ sp -= BY2WD+ERRMAX;
+ memmove((char*)sp, up->note[0].msg, ERRMAX);
+ sp -= 3*BY2WD;
+ *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */
+ ur->r1 = (long)up->ureg; /* arg 1 is ureg* */
+ ((ulong*)sp)[1] = (ulong)up->ureg; /* arg 1 0(FP) is ureg* */
+ ((ulong*)sp)[0] = 0; /* arg 0 is pc */
+ ur->usp = sp;
+ ur->pc = (ulong)up->notify;
+ up->notified = 1;
+ up->nnote--;
+ memmove(&up->lastnote, &up->note[0], sizeof(Note));
+ memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
+
+ qunlock(&up->debug);
+ splx(s);
+ return 1;
+}
+
+
+/*
+ * Return user to state before notify()
+ */
+void
+noted(Ureg* ureg, ulong arg0)
+{
+ Ureg *nureg;
+ ulong oureg, sp;
+
+ qlock(&up->debug);
+ if(arg0!=NRSTR && !up->notified) {
+ qunlock(&up->debug);
+ pprint("call to noted() when not notified\n");
+ pexit("Suicide", 0);
+ }
+ up->notified = 0;
+
+ nureg = up->ureg; /* pointer to user returned Ureg struct */
+
+ /* sanity clause */
+ oureg = (ulong)nureg;
+ if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
+ pprint("bad ureg in noted or call to noted when not notified\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+
+ memmove(ureg, nureg, sizeof(Ureg));
+
+ switch(arg0){
+ case NCONT:
+ case NRSTR:
+ if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->usp, BY2WD, 0)){
+ pprint("suicide: trap in noted\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+ up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
+ qunlock(&up->debug);
+ break;
+
+ case NSAVE:
+ if(!okaddr(nureg->pc, BY2WD, 0)
+ || !okaddr(nureg->usp, BY2WD, 0)){
+ pprint("suicide: trap in noted\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+ qunlock(&up->debug);
+ sp = oureg-4*BY2WD-ERRMAX;
+ splhi();
+ ureg->sp = sp;
+ ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
+ ((ulong*)sp)[0] = 0; /* arg 0 is pc */
+ break;
+
+ default:
+ pprint("unknown noted arg 0x%lux\n", arg0);
+ up->lastnote.flag = NDebug;
+ /* fall through */
+
+ case NDFLT:
+ if(up->lastnote.flag == NDebug)
+ pprint("suicide: %s\n", up->lastnote.msg);
+ qunlock(&up->debug);
+ pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
+ }
+ up->fpstate &= ~FPillegal;
+ if (up->fpstate == FPactive)
+ ureg->srr1 |= MSR_FP;
+ else
+ ureg->srr1 &= ~MSR_FP;
+}
diff --git a/sys/src/9/ppc/uartsaturn.c b/sys/src/9/ppc/uartsaturn.c
new file mode 100755
index 000000000..51f91f94c
--- /dev/null
+++ b/sys/src/9/ppc/uartsaturn.c
@@ -0,0 +1,472 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "msaturn.h"
+
+enum{
+ UartAoffs = Saturn + 0x0a00,
+ UartBoffs = Saturn + 0x0b00,
+ Nuart = 2,
+
+ Baudfreq = 14745600 / 16,
+ Lcr_div = RBIT(1, uchar),
+ Lcr_peven = RBIT(3, uchar),
+ Lcr_pen = RBIT(4, uchar),
+ Lcr_stop = RBIT(5, uchar),
+ Lcr_wrdlenmask = RBIT(6, uchar) | RBIT(7, uchar),
+ Lcr_wrdlenshift = 0,
+ Lsr_tbre = RBIT(2, uchar),
+ Fcr_txreset = RBIT(5, uchar),
+ Fcr_rxreset = RBIT(6, uchar),
+ Iir_txempty = RBIT(5, uchar),
+ Iir_rxfull = RBIT(6, uchar),
+ Iir_rxerr = RBIT(7, uchar),
+ Ier_rxerr = RBIT(5, uchar),
+ Ier_txempty = RBIT(6, uchar),
+ Ier_rxfull = RBIT(7, uchar),
+ Lsr_rxavail = RBIT(7, uchar),
+ Txsize = 16,
+ Rxsize = 16,
+};
+
+typedef struct Saturnuart Saturnuart;
+struct Saturnuart {
+ uchar rxb;
+#define txb rxb
+#define dll rxb
+ uchar ier; // Interrupt enable, divisor latch
+#define dlm ier
+ uchar iir; // Interrupt identification, fifo control
+#define fcr iir
+ uchar lcr; // Line control register
+ uchar f1;
+ uchar lsr; // Line status register
+ ushort f2;
+};
+
+typedef struct UartData UartData;
+struct UartData {
+ int suno; /* saturn uart number: 0 or 1 */
+ Saturnuart *su;
+ char *rxbuf;
+ char *txbuf;
+ int initialized;
+ int enabled;
+} uartdata[Nuart];
+
+extern PhysUart saturnphysuart;
+
+Uart suart[Nuart] = {
+ {
+ .name = "SaturnUart1",
+ .baud = 19200,
+ .bits = 8,
+ .stop = 1,
+ .parity = 'n',
+ .phys = &saturnphysuart,
+ .special = 0,
+ },
+ {
+ .name = "SaturnUart2",
+ .baud = 115200,
+ .bits = 8,
+ .stop = 1,
+ .parity = 'n',
+ .phys = &saturnphysuart,
+ .special = 0,
+ },
+};
+
+static void suinterrupt(Ureg*, void*);
+
+static Uart*
+supnp(void)
+{
+ int i;
+
+ for (i = 0; i < nelem(suart)-1; i++)
+ suart[i].next = &suart[i + 1];
+ suart[nelem(suart)-1].next=nil;
+ return suart;
+}
+
+static void
+suinit(Uart*uart)
+{
+ UartData *ud;
+ Saturnuart *su;
+
+ ud = uart->regs;
+ su = ud->su;
+ su->fcr=Fcr_txreset|Fcr_rxreset;
+ ud->initialized=1;
+}
+
+static void
+suenable(Uart*uart, int ie)
+{
+ Saturnuart *su;
+ UartData *ud;
+ int nr;
+
+ nr = uart - suart;
+ if (nr < 0 || nr > Nuart)
+ panic("No uart %d", nr);
+ ud = uartdata + nr;
+ ud->suno = nr;
+ su=ud->su = (Saturnuart*)((nr == 0)? UartAoffs: UartBoffs);
+ uart->regs = ud;
+
+ if(ud->initialized==0)
+ suinit(uart);
+
+ if(!ud->enabled && ie){
+ intrenable(Vecuart0+nr , suinterrupt, uart, uart->name);
+ su->ier=Ier_txempty|Ier_rxfull;
+ ud->enabled=1;
+ }
+}
+
+
+static long
+sustatus(Uart* uart, void* buf, long n, long offset)
+{
+ Saturnuart *su;
+ char p[128];
+
+ su = ((UartData*)uart->regs)->su;
+ snprint(p, sizeof p, "b%d c%d e%d l%d m0 p%c s%d i1\n"
+ "dev(%d) type(%d) framing(%d) overruns(%d)\n",
+
+ uart->baud,
+ uart->hup_dcd,
+ uart->hup_dsr,
+ Txsize,
+ (su->lcr & Lcr_pen)? ((su->lcr & Lcr_peven) ? 'e': 'o'): 'n',
+ (su->lcr & Lcr_stop)? 2: 1,
+
+ uart->dev,
+ uart->type,
+ uart->ferr,
+ uart->oerr);
+ n = readstr(offset, buf, n, p);
+ free(p);
+
+ return n;
+}
+
+static void
+sufifo(Uart*, int)
+{}
+
+static void
+sudtr(Uart*, int)
+{}
+
+static void
+surts(Uart*, int)
+{}
+
+static void
+sumodemctl(Uart*, int)
+{}
+
+static int
+suparity(Uart*uart, int parity)
+{
+ int lcr;
+ Saturnuart *su;
+
+ su = ((UartData*)uart->regs)->su;
+
+ lcr = su->lcr & ~(Lcr_pen|Lcr_peven);
+
+ switch(parity){
+ case 'e':
+ lcr |= (Lcr_pen|Lcr_peven);
+ break;
+ case 'o':
+ lcr |= Lcr_pen;
+ break;
+ case 'n':
+ default:
+ break;
+ }
+
+ su->lcr = lcr;
+ uart->parity = parity;
+
+ return 0;
+}
+
+static int
+sustop(Uart* uart, int stop)
+{
+ int lcr;
+ Saturnuart *su;
+
+ su = ((UartData*)uart->regs)->su;
+ lcr = su->lcr & ~Lcr_stop;
+
+ switch(stop){
+ case 1:
+ break;
+ case 2:
+ lcr |= Lcr_stop;
+ break;
+ default:
+ return -1;
+ }
+
+ /* Set new value and reenable if device was previously enabled */
+ su->lcr = lcr;
+ uart->stop = stop;
+
+ return 0;
+}
+
+static int
+subits(Uart*uart, int n)
+{
+ Saturnuart *su;
+ uchar lcr;
+
+ su = ((UartData*)uart->regs)->su;
+ if(n<5||n>8)
+ return -1;
+
+ lcr = su->lcr & ~Lcr_wrdlenmask;
+ lcr |= (n-5) << Lcr_wrdlenshift;
+ su->lcr = lcr;
+ return 0;
+}
+
+static int
+subaud(Uart* uart, int baud)
+{
+ ushort v;
+ Saturnuart *su;
+
+ if (uart->enabled){
+ su = ((UartData*)uart->regs)->su;
+
+ if(baud <= 0)
+ return -1;
+
+ v = Baudfreq / baud;
+ su->lcr |= Lcr_div;
+ su->dll = v;
+ su->dlm = v >> 8;
+ su->lcr &= ~Lcr_div;
+ }
+ uart->baud = baud;
+
+ return 0;
+}
+
+static void
+subreak(Uart*, int)
+{}
+
+static void
+sukick(Uart *uart)
+{
+ Saturnuart *su;
+ int i;
+
+ if(uart->blocked)
+ return;
+
+ su = ((UartData*)uart->regs)->su;
+ if((su->iir & Iir_txempty) == 0)
+ return;
+
+ for(i = 0; i < Txsize; i++){
+ if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
+ break;
+ su->txb = *(uart->op++);
+ su->ier |= Ier_txempty;
+ break;
+ }
+}
+
+static void
+suputc(Uart *uart, int c)
+{
+ Saturnuart *su;
+
+ su = ((UartData*)uart->regs)->su;
+ while((su->lsr&Lsr_tbre) == 0)
+ ;
+
+ su->txb=c;
+ while((su->lsr&Lsr_tbre) == 0)
+ ;
+}
+
+static int
+getchars(Uart *uart, uchar *cbuf)
+{
+ int nc;
+ UartData *ud;
+ Saturnuart *su;
+
+ ud = uart->regs;
+ su = ud->su;
+
+ while((su->lsr&Lsr_rxavail) == 0)
+ ;
+
+ *cbuf++ = su->rxb;
+ nc = 1;
+ while(su->lsr&Lsr_rxavail){
+ *cbuf++ = su->rxb;
+ nc++;
+ }
+ return nc;
+}
+
+static int
+sugetc(Uart *uart)
+{
+ static uchar buf[128], *p;
+ static int cnt;
+ char c;
+
+ if (cnt <= 0) {
+ cnt = getchars(uart, buf);
+ p = buf;
+ }
+ c = *p++;
+ cnt--;
+ return c;
+}
+
+static void
+suinterrupt(Ureg*, void*u)
+{
+ Saturnuart *su;
+ Uart *uart;
+ uchar iir;
+
+ uart = u;
+ if (uart == nil)
+ panic("uart is nil");
+ su = ((UartData*)uart->regs)->su;
+ iir = su->iir;
+ if(iir&Iir_rxfull)
+ while(su->lsr&Lsr_rxavail)
+ uartrecv(uart, su->rxb);
+ if(iir & Iir_txempty){
+ su->ier&=~Ier_txempty;
+ uartkick(uart);
+ }
+ if (iir & Iir_rxerr)
+ uart->oerr++;
+ intack();
+}
+
+static void
+sudisable(Uart* uart)
+{
+ Saturnuart *su;
+
+ su = ((UartData*)uart->regs)->su;
+ su->ier&=~(Ier_txempty|Ier_rxfull);
+}
+
+PhysUart saturnphysuart = {
+ .name = "su",
+ .pnp = supnp,
+ .enable = suenable,
+ .disable = sudisable,
+ .kick = sukick,
+ .dobreak = subreak,
+ .baud = subaud,
+ .bits = subits,
+ .stop = sustop,
+ .parity = suparity,
+ .modemctl = sumodemctl,
+ .rts = surts,
+ .dtr = sudtr,
+ .status = sustatus,
+ .fifo = sufifo,
+ .getc = sugetc,
+ .putc = suputc,
+};
+
+void
+console(void)
+{
+ Uart *uart;
+ int n;
+ char *cmd, *p;
+
+ if((p = getconf("console")) == nil)
+ return;
+ n = strtoul(p, &cmd, 0);
+ if(p == cmd)
+ return;
+ if(n < 0 || n >= nelem(suart))
+ return;
+
+ uart = suart + n;
+
+/* uartctl(uart, "b115200 l8 pn s1"); */
+ if(*cmd != '\0')
+ uartctl(uart, cmd);
+ (*uart->phys->enable)(uart, 0);
+
+ consuart = uart;
+ uart->console = 1;
+}
+
+Saturnuart*uart = (Saturnuart*)UartAoffs;
+
+void
+dbgputc(int c)
+{
+ while((uart->lsr&Lsr_tbre) == 0)
+ ;
+
+ uart->txb=c;
+ while((uart->lsr&Lsr_tbre) == 0)
+ ;
+}
+
+void
+dbgputs(char*s)
+{
+ while(*s)
+ dbgputc(*s++);
+}
+
+void
+dbgputx(ulong x)
+{
+ int i;
+ char c;
+
+ for(i=0; i < sizeof(ulong) * 2; i++){
+ c = ((x >> (28 - i * 4))) & 0xf;
+ if(c >= 0 && c <= 9)
+ c += '0';
+ else
+ c += 'a' - 10;
+
+ while((uart->lsr&Lsr_tbre) == 0)
+ ;
+
+ uart->txb=c;
+ }
+ while((uart->lsr&Lsr_tbre) == 0)
+ ;
+
+ uart->txb='\n';
+ while((uart->lsr&Lsr_tbre) == 0)
+ ;
+}
diff --git a/sys/src/9/ppc/uartsmc.c b/sys/src/9/ppc/uartsmc.c
new file mode 100755
index 000000000..fe48f53fe
--- /dev/null
+++ b/sys/src/9/ppc/uartsmc.c
@@ -0,0 +1,585 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "imm.h"
+#include "../port/error.h"
+#include "../ppc/uartsmc.h"
+
+/*
+ * PowerPC 8260 SMC UART
+ */
+
+enum {
+ /* SMC Mode Registers */
+ Clen = 0x7800, /* Character length */
+ Sl = 0x0400, /* Stop length, 0: one stop bit, 1: two */
+ Pen = 0x0200, /* Parity enable */
+ Pm = 0x0100, /* Parity mode, 0 is odd */
+ Sm = 0x0030, /* SMC mode, two bits */
+ SMUart = 0x0020, /* SMC mode, 0b10 is uart */
+ Dm = 0x000c, /* Diagnostic mode, 00 is normal */
+ Ten = 0x0002, /* Transmit enable, 1 is enabled */
+ Ren = 0x0001, /* Receive enable, 1 is enabled */
+
+ /* SMC Event/Mask Registers */
+ ce_Brke = 0x0040, /* Break end */
+ ce_Br = 0x0020, /* Break character received */
+ ce_Bsy = 0x0004, /* Busy condition */
+ ce_Txb = 0x0002, /* Tx buffer */
+ ce_Rxb = 0x0001, /* Rx buffer */
+
+ /* Receive/Transmit Buffer Descriptor Control bits */
+ BDContin= 1<<9,
+ BDIdle= 1<<8,
+ BDPreamble= 1<<8,
+ BDBreak= 1<<5,
+ BDFrame= 1<<4,
+ BDParity= 1<<3,
+ BDOverrun= 1<<1,
+
+ /* Tx and Rx buffer sizes (32 bytes) */
+ Rxsize= CACHELINESZ,
+ Txsize= CACHELINESZ,
+};
+
+extern PhysUart smcphysuart;
+
+Uart smcuart[Nuart] = {
+ {
+ .name = "SMC1",
+ .baud = 115200,
+ .bits = 8,
+ .stop = 1,
+ .parity = 'n',
+ .phys = &smcphysuart,
+ .special = 0,
+ },
+/* Only configure SMC1 for now
+ {
+ .name = "SMC2",
+ .baud = 115200,
+ .bits = 8,
+ .stop = 1,
+ .parity = 'n',
+ .phys = &smcphysuart,
+ .special = 0,
+ },
+*/
+};
+
+int uartinited = 0;
+
+static void smcinterrupt(Ureg*, void*);
+static void smcputc(Uart *uart, int c);
+
+int
+baudgen(int baud)
+{
+ int d;
+
+ d = ((m->brghz+(baud>>1))/baud)>>4;
+ if(d >= (1<<12))
+ return ((d+15)>>3)|1;
+ return d<<1;
+}
+
+static Uart*
+smcpnp(void)
+{
+ int i;
+
+ for (i = 0; i < nelem(smcuart) - 1; i++)
+ smcuart[i].next = smcuart + i + 1;
+ return smcuart;
+}
+
+void
+smcinit(Uart *uart)
+{
+ Uartsmc *p;
+ SMC *smc;
+ UartData *ud;
+ ulong lcr;
+ int bits;
+
+ ud = uart->regs;
+
+ if (ud->initialized)
+ return;
+
+ smcsetup(uart); /* Steps 1 through 4, PPC-dependent */
+ p = ud->usmc;
+ smc = ud->smc;
+
+ /* step 5: set up buffer descriptors */
+ /* setup my uart structure */
+ if (ud->rxb == nil)
+ ud->rxb = bdalloc(1);
+ if (ud->txb == nil)
+ ud->txb = bdalloc(1);
+
+ p->rbase = ((ulong)ud->rxb) - (ulong)IMMR;
+ p->tbase = ((ulong)ud->txb) - (ulong)IMMR;
+
+ /* step 8: receive buffer size */
+ p->mrblr = Rxsize;
+
+ /* step 9: */
+ p->maxidl = 15;
+
+ /* step 10: */
+ p->brkln = 0;
+ p->brkec = 0;
+
+ /* step 11: */
+ p->brkcr = 0;
+
+ /* step 12: setup receive buffer */
+ ud->rxb->status = BDEmpty|BDWrap|BDInt;
+ ud->rxb->length = 0;
+ ud->rxbuf = xspanalloc(Rxsize, 0, CACHELINESZ);
+ ud->rxb->addr = PADDR(ud->rxbuf);
+
+ /* step 13: step transmit buffer */
+ ud->txb->status = BDWrap|BDInt;
+ ud->txb->length = 0;
+ ud->txbuf = xspanalloc(Txsize, 0, CACHELINESZ);
+ ud->txb->addr = PADDR(ud->txbuf);
+
+ /* step 14: clear events */
+ smc->smce = ce_Brke | ce_Br | ce_Bsy | ce_Txb | ce_Rxb;
+
+ /*
+ * step 15: enable interrupts (done later)
+ * smc->smcm = ce_Brke | ce_Br | ce_Bsy | ce_Txb | ce_Rxb;
+ */
+
+ /* step 17: set parity, no of bits, UART mode, ... */
+ lcr = SMUart;
+ bits = uart->bits + 1;
+
+ switch(uart->parity){
+ case 'e':
+ lcr |= (Pen|Pm);
+ bits +=1;
+ break;
+ case 'o':
+ lcr |= Pen;
+ bits +=1;
+ break;
+ case 'n':
+ default:
+ break;
+ }
+
+ if(uart->stop == 2){
+ lcr |= Sl;
+ bits += 1;
+ }
+
+ /* Set new value and reenable if device was previously enabled */
+ smc->smcmr = lcr | bits <<11 | 0x3;
+
+ ud->initialized = 1;
+}
+
+static void
+smcenable(Uart *uart, int intenb)
+{
+ UartData *ud;
+ SMC *smc;
+ int nr;
+
+ nr = uart - smcuart;
+ if (nr < 0 || nr > Nuart)
+ panic("No SMC %d", nr);
+ ud = uartdata + nr;
+ ud->smcno = nr;
+ uart->regs = ud;
+ if (ud->initialized == 0)
+ smcinit(uart);
+ if (ud->enabled || intenb == 0)
+ return;
+ smc = ud->smc;
+ /* clear events */
+ smc->smce = ce_Brke | ce_Br | ce_Bsy | ce_Txb | ce_Rxb;
+ /* enable interrupts */
+ smc->smcm = ce_Brke | ce_Br | ce_Bsy | ce_Txb | ce_Rxb;
+ intrenable(VecSMC1 + ud->smcno, smcinterrupt, uart, uart->name);
+ ud->enabled = 1;
+}
+
+static long
+smcstatus(Uart* uart, void* buf, long n, long offset)
+{
+ SMC *sp;
+ char p[128];
+
+ sp = ((UartData*)uart->regs)->smc;
+ snprint(p, sizeof p, "b%d c%d e%d l%d m0 p%c s%d i1\n"
+ "dev(%d) type(%d) framing(%d) overruns(%d)\n",
+
+ uart->baud,
+ uart->hup_dcd,
+ uart->hup_dsr,
+ ((sp->smcmr & Clen) >>11) - ((sp->smcmr&Pen) ? 1 : 0) - ((sp->smcmr&Sl) ? 2 : 1),
+ (sp->smcmr & Pen) ? ((sp->smcmr & Pm) ? 'e': 'o'): 'n',
+ (sp->smcmr & Sl) ? 2: 1,
+
+ uart->dev,
+ uart->type,
+ uart->ferr,
+ uart->oerr
+ );
+ n = readstr(offset, buf, n, p);
+ free(p);
+
+ return n;
+}
+
+static void
+smcfifo(Uart*, int)
+{
+ /*
+ * Toggle FIFOs:
+ * if none, do nothing;
+ * reset the Rx and Tx FIFOs;
+ * empty the Rx buffer and clear any interrupt conditions;
+ * if enabling, try to turn them on.
+ */
+ return;
+}
+
+static void
+smcdtr(Uart*, int)
+{
+}
+
+static void
+smcrts(Uart*, int)
+{
+}
+
+static void
+smcmodemctl(Uart*, int)
+{
+}
+
+static int
+smcparity(Uart* uart, int parity)
+{
+ int lcr;
+ SMC *sp;
+
+ sp = ((UartData*)uart->regs)->smc;
+
+ lcr = sp->smcmr & ~(Pen|Pm);
+
+ /* Disable transmitter/receiver. */
+ sp->smcmr &= ~(Ren | Ten);
+
+ switch(parity){
+ case 'e':
+ lcr |= (Pen|Pm);
+ break;
+ case 'o':
+ lcr |= Pen;
+ break;
+ case 'n':
+ default:
+ break;
+ }
+ /* Set new value and reenable if device was previously enabled */
+ sp->smcmr = lcr;
+
+ uart->parity = parity;
+
+ return 0;
+}
+
+static int
+smcstop(Uart* uart, int stop)
+{
+ int lcr, bits;
+ SMC *sp;
+
+ sp = ((UartData*)uart->regs)->smc;
+ lcr = sp->smcmr & ~(Sl | Clen);
+
+ /* Disable transmitter/receiver. */
+ sp->smcmr &= ~(Ren | Ten);
+
+ switch(stop){
+ case 1:
+ break;
+ case 2:
+ lcr |= Sl;
+ break;
+ default:
+ return -1;
+ }
+
+ bits = uart->bits + ((lcr & Pen) ? 1 : 0) + ((lcr & Sl) ? 2 : 1);
+ lcr |= bits<<11;
+
+ /* Set new value and reenable if device was previously enabled */
+ sp->smcmr = lcr;
+
+ uart->stop = stop;
+
+ return 0;
+}
+
+static int
+smcbits(Uart* uart, int bits)
+{
+ int lcr, b;
+ SMC *sp;
+
+ if (bits < 5 || bits > 14)
+ return -1;
+
+ sp = ((UartData*)uart->regs)->smc;
+ lcr = sp->smcmr & ~Clen;
+
+ b = bits + ((sp->smcmr & Pen) ? 1 : 0) + ((sp->smcmr & Sl) ? 2 : 1);
+
+ if (b > 15)
+ return -1;
+
+ /* Disable transmitter/receiver */
+ sp->smcmr &= ~(Ren | Ten);
+
+ /* Set new value and reenable if device was previously enabled */
+ sp->smcmr = lcr | b<<11;
+
+ uart->bits = bits;
+
+ return 0;
+}
+
+static int
+smcbaud(Uart* uart, int baud)
+{
+ int i;
+ SMC *sp;
+
+ if (uart->enabled){
+ sp = ((UartData*)uart->regs)->smc;
+
+ if(uart->freq == 0 || baud <= 0)
+ return -1;
+
+ i = sp - imm->smc;
+ imm->brgc[i] = (((m->brghz >> 4) / baud) << 1) | 0x00010000;
+ }
+ uart->baud = baud;
+
+ return 0;
+}
+
+static void
+smcbreak(Uart*, int)
+{
+}
+
+static void
+smckick(Uart *uart)
+{
+ BD *txb;
+ UartData *ud;
+ int i;
+
+ if(uart->blocked)
+ return;
+
+ ud = uart->regs;
+ txb = ud->txb;
+
+ if (txb->status & BDReady)
+ return; /* Still busy */
+
+ for(i = 0; i < Txsize; i++){
+ if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
+ break;
+ ud->txbuf[i] = *(uart->op++);
+ }
+ if (i == 0)
+ return;
+ dcflush(ud->txbuf, Txsize);
+ txb->length = i;
+ sync();
+ txb->status |= BDReady|BDInt;
+}
+
+static void
+smcinterrupt(Ureg*, void* u)
+{
+ int i, nc;
+ char *buf;
+ BD *rxb;
+ UartData *ud;
+ Uart *uart;
+ uchar events;
+
+ uart = u;
+ if (uart == nil)
+ panic("uart is nil");
+ ud = uart->regs;
+ if (ud == nil)
+ panic("ud is nil");
+
+ events = ud->smc->smce;
+ ud->smc->smce = events; /* Clear events */
+
+ if (events & 0x10)
+ iprint("smc%d: break\n", ud->smcno);
+ if (events & 0x4)
+ uart->oerr++;
+ if (events & 0x1){
+ /* Receive characters
+ */
+ rxb = ud->rxb;
+ buf = ud->rxbuf;
+ dczap(buf, Rxsize); /* invalidate data cache before copying */
+ if ((rxb->status & BDEmpty) == 0){
+ nc = rxb->length;
+ for (i=0; i<nc; i++)
+ uartrecv(uart, *buf++);
+ sync();
+ rxb->status |= BDEmpty;
+ }else{
+ iprint("uartsmc: unexpected receive event\n");
+ }
+ }
+ if (events & 0x2){
+ if ((ud->txb->status & BDReady) == 0)
+ uartkick(uart);
+ }
+}
+
+static void
+smcdisable(Uart* uart)
+{
+ SMC *sp;
+
+ sp = ((UartData*)uart->regs)->smc;
+ sp->smcmr &= ~(Ren | Ten);
+}
+
+static int
+getchars(Uart *uart, uchar *cbuf)
+{
+ int i, nc;
+ char *buf;
+ BD *rxb;
+ UartData *ud;
+
+ ud = uart->regs;
+ rxb = ud->rxb;
+
+ /* Wait for character to show up.
+ */
+ buf = ud->rxbuf;
+ while (rxb->status & BDEmpty)
+ ;
+ nc = rxb->length;
+ for (i=0; i<nc; i++)
+ *cbuf++ = *buf++;
+ sync();
+ rxb->status |= BDEmpty;
+
+ return(nc);
+}
+
+static int
+smcgetc(Uart *uart)
+{
+ static uchar buf[128], *p;
+ static int cnt;
+ char c;
+
+ if (cnt <= 0) {
+ cnt = getchars(uart, buf);
+ p = buf;
+ }
+ c = *p++;
+ cnt--;
+
+ return(c);
+}
+
+static void
+smcputc(Uart *uart, int c)
+{
+ BD *txb;
+ UartData *ud;
+ SMC *smc;
+
+ ud = uart->regs;
+ txb = ud->txb;
+ smc = ud->smc;
+ smc->smcm = 0;
+
+ /* Wait for last character to go.
+ */
+ while (txb->status & BDReady)
+ ;
+
+ ud->txbuf[0] = c;
+ dcflush(ud->txbuf, 1);
+ txb->length = 1;
+ sync();
+ txb->status |= BDReady;
+
+ while (txb->status & BDReady)
+ ;
+}
+
+PhysUart smcphysuart = {
+ .name = "smc",
+ .pnp = smcpnp,
+ .enable = smcenable,
+ .disable = smcdisable,
+ .kick = smckick,
+ .dobreak = smcbreak,
+ .baud = smcbaud,
+ .bits = smcbits,
+ .stop = smcstop,
+ .parity = smcparity,
+ .modemctl = smcmodemctl,
+ .rts = smcrts,
+ .dtr = smcdtr,
+ .status = smcstatus,
+ .fifo = smcfifo,
+ .getc = smcgetc,
+ .putc = smcputc,
+};
+
+void
+console(void)
+{
+ Uart *uart;
+ int n;
+ char *cmd, *p;
+
+ if((p = getconf("console")) == nil)
+ return;
+ n = strtoul(p, &cmd, 0);
+ if(p == cmd)
+ return;
+ if(n < 0 || n >= nelem(smcuart))
+ return;
+ uart = smcuart + n;
+
+/* uartctl(uart, "b115200 l8 pn s1"); */
+ if(*cmd != '\0')
+ uartctl(uart, cmd);
+ (*uart->phys->enable)(uart, 0);
+
+ consuart = uart;
+ uart->console = 1;
+}
diff --git a/sys/src/9/ppc/ucu b/sys/src/9/ppc/ucu
new file mode 100755
index 000000000..56631f851
--- /dev/null
+++ b/sys/src/9/ppc/ucu
@@ -0,0 +1,59 @@
+dev
+ root
+ cons
+ env
+ pipe
+ proc
+ mnt
+ srv
+ dup
+ ssl
+ cap
+ kprof
+ uart
+
+ ether netif
+ ip arp chandial ip ipv6 ipaux iproute netif netlog nullmedium pktmedium ptclbsum inferno
+ ce
+
+link
+ ethersaturn
+ ethermedium
+ netdevmedium
+
+misc
+ uartsaturn
+ saturntimer
+ msaturn
+
+ip
+ tcp
+ udp
+ ipifc
+ icmp
+ icmp6
+
+port
+ int cpuserver = 1;
+
+boot cpu
+ tcp
+
+bootdir
+ /power/bin/rc
+ /rc/lib/rcmain
+ /power/bin/bind
+ /power/bin/sed
+ /power/bin/srv
+ /power/bin/cat
+ /power/bin/cp
+ /power/bin/rm
+ /power/bin/echo
+ /power/bin/mount
+ /power/bin/sleep
+ /power/bin/auth/factotum
+ /power/bin/ip/ipconfig
+ /power/bin/ls
+ /power/bin/ps
+ /power/bin/auth/wrkey
+ /sys/lib/sysconfig/blast/boot
diff --git a/sys/src/9/ppc/ucu.h b/sys/src/9/ppc/ucu.h
new file mode 100755
index 000000000..91653bc42
--- /dev/null
+++ b/sys/src/9/ppc/ucu.h
@@ -0,0 +1,21 @@
+
+#define FLASHMEM (~0)
+#define MEM1BASE 0
+#define MEM1SIZE 0x02000000
+#define MEM2BASE 0
+#define MEM2SIZE 0
+#define PLAN9INI (~0)
+
+#define Saturn 0xf0000000
+
+#define TLBENTRIES 128
+
+/*
+ * PTE bits for fault.c. These belong to the second PTE word. Validity is
+ * implied for putmmu(), and we always set PTE0_V. PTEVALID is used
+ * here to set cache policy bits on a global basis.
+ */
+#define PTEVALID (PTE1_M|PTE1_W) /* write through */
+#define PTEWRITE (PTE1_RW|PTE1_C)
+#define PTERONLY PTE1_RO
+#define PTEUNCACHED PTE1_I